科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道编写安全SQL Server扩展存储过程(1)

编写安全SQL Server扩展存储过程(1)

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

SQL Server 的扩展存储过程,其实就是一个普通的 Windows DLL,只不过按照某种规则实现了某些函数而已。 {!) zo:

作者:赛迪网技术社区 来源:赛迪网技术社区 2007年9月2日

关键字: 存储过程 数据库 SQL Server SQL Server 各版本

  • 评论
  • 分享微博
  • 分享邮件
SQL Server 的扩展存储过程,其实就是一个普通的 Windows DLL,只不过按照某种规则实现了某些函数而已。 {!) zo:  
   4.9T?(glL~  
近日在写一个扩展存储过程时,发现再写这类动态库时,还是有一些需要特别注意的地方。之所以会特别注意,是因为DLL运行于SQL Server的地址空间,而SQL Server到底是怎么进行线程调度的,却不是我们能了解的,即便了解也无法控制。 {Y 15TgL  
   at;W_CpU  
我们写动态库一般是自己用,即便给别人用,也很少像SQL Server这样,一个动态库很有可能加载多次,并且都是加载到一个进程的地址空间中。我们知道,当一个动态库加载到进程的地址空间时,DLL所有全局与局部变量初始化且仅初始化一次,以后再次调用 LoadLibrary函数时,仅仅增加其引用计数而已,那么很显然,假如有一全局 int ,初始化为0,调用一个函数另其自加,此时其值为1,然后再调用LoadLibray,并利用返回的句柄调用输出函数输出该值,虽然调用者觉得自己加载后立即输出,然后该值确实1而不是0。windows是进程独立的,而在线程方面,假如不注意,上面的情况很可能会程序员带来麻烦。 (/bLSW  
   nYFSWF,  
介绍一下我的扩展存储过程,该动态库导出了三个函数: Init,work,Final,Init读文件,存储信息于内存,work简单的只是向该内存检索信息,Final回收内存。如上所说,假如不考虑同一进程空间多次加载问题,两次调用Init将造成无谓的浪费,因为我第一次已经读进了内存,要是通过堆分配内存,还会造成内存泄露。 Dsx^4,Ej  
   -iLrd Q  
我使用的引用计数解决的该问题,代码很短,直接贴上来: #H>yx~Xz+  
@5%8~{wJ  
#include "stdafx.h" `'+G`Xv  
#include <string> \+ s Cq  
using namespace std; uh>3jLB3  
extern "C" { 'L_&[[s  
RETCODE __declspec(dllexport) xp_part_init(SRV_PROC *srvproc); ]7 z'H  
RETCODE __declspec(dllexport) xp_part_process(SRV_PROC *srvproc); <yvd %W  
RETCODE __declspec(dllexport) xp_part_finalize(SRV_PROC *srvproc); RP~>o{op  
} cL%dfj  
#define XP_NOERROR 0 Hge^7I  
#define XP_ERROR 1 Bg=[a#  
HINSTANCE hInst = NULL; gM>/9  
int nRef = 0; XE%N}k2  
void printError (SRV_PROC *pSrvProc, CHAR* szErrorMsg); %fhp%e+1]]  
ULONG __GetXpVersion(){ return ODS_VERSION;} {'|b;tV 4A  
SRVRETCODE xp_part_init(SRV_PROC* pSrvProc){ EEDN:B3V  
typedef bool (*Func)(); %mQgBrD  
if(nRef == 0){ u\.7!  
hInst = ::LoadLibrary("part.dll"); dv-JE :  
if(hInst == NULL){ Q\yZlz#H  
printError(pSrvProc,"不能加载part.dll"); =eLTm&!,$  
return XP_ERROR; XQ!JS  
} -qjpV7<LE  
Func theFunc = (Func)::GetProcAddress(hInst,"Init"); =*: A>'/  
if(!theFunc()){ 0@'B"0a(  
::FreeLibrary(hInst); ?/ \|sV:JH  
printError(pSrvProc,"不能获得分类号与专辑的对应表"); +DUp0\5s  
return XP_ERROR; VnzEF0)  
} s )O6U<  
} SFH:T7 !g  
++ nRef; 7:1ADUfu?  
return (XP_NOERROR);  ATnWb"V@  
} C ML^]wz+  
SRVRETCODE xp_part_process(SRV_PROC* pSrvProc){ n); ?b  
typedef bool (*Func)(char*); .Dsz6<;  
if(nRef == 0){ Au0`vhs}  
printError(pSrvProc,"函数尚未初始化,请首先调用xp_part_init"); T TwvGniS  
return XP_ERROR; y?'bKMG<>  
} bdC`!\k.  
Func theFunc = (Func)::GetProcAddress(hInst,"Get"); + ;] k`r  
BYTE bType; X`LaH:n+  
ULONG cbMaxLen,cbActualLen; Wq,wf ^OL  
BOOL fNull; Sl8$^=>  
char szInput[256] = {0}; Lg<c~DdT  
if (srv_paraminfo(pSrvProc, 1, &bType, (ULONG*)&cbMaxLen, (ULONG*)&cbActualLen, (BYTE*)szInput, &fNull) == FAIL){ A:B(5gk  
printError(pSrvProc,"srv_paraminfo 返回 FAIL"); o MSDV>  
return XP_ERROR; 7S}% Huj  
} d;-L+%qu  
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章