Rumah > Artikel > pangkalan data > 编写安全的SQL Server扩展存储过程
SQL Server 的 扩展 存储 过程 ,其实就是一个普通的 Windows DLL,只不过按照某种规则实现了某些函数而已。 近日在写一个 扩展 存储 过程 时,发现再写这类动态库时,还是有一些需要特别注意的地方。之所以会特别注意,是因为DLL运行于SQL Server的地址空间
SQL Server 的扩展存储过程,其实就是一个普通的 Windows DLL,只不过按照某种规则实现了某些函数而已。
#include "stdafx.h" #include using namespace std; extern "C" { RETCODE __declspec(dllexport) xp_part_init(SRV_PROC *srvproc); RETCODE __declspec(dllexport) xp_part_process(SRV_PROC *srvproc); RETCODE __declspec(dllexport) xp_part_finalize(SRV_PROC *srvproc); } #define XP_NOERROR 0 #define XP_ERROR 1 HINSTANCE hInst = NULL; int nRef = 0; void printError (SRV_PROC *pSrvProc, CHAR* szErrorMsg); ULONG __GetXpVersion(){ return ODS_VERSION;} SRVRETCODE xp_part_init(SRV_PROC* pSrvProc){ typedef bool (*Func)(); if(nRef == 0){ hInst = ::LoadLibrary("part.dll"); if(hInst == NULL){ printError(pSrvProc,"不能加载part.dll"); return XP_ERROR; } Func theFunc = (Func)::GetProcAddress(hInst,"Init"); if(!theFunc()){ ::FreeLibrary(hInst); printError(pSrvProc,"不能获得分类号与专辑的对应表"); return XP_ERROR; } } ++ nRef; return (XP_NOERROR); } SRVRETCODE xp_part_process(SRV_PROC* pSrvProc){ typedef bool (*Func)(char*); if(nRef == 0){ printError(pSrvProc,"函数尚未初始化,请首先调用xp_part_init"); return XP_ERROR; } Func theFunc = (Func)::GetProcAddress(hInst,"Get"); BYTE bType; ULONG cbMaxLen,cbActualLen; BOOL fNull; char szInput[256] = {0}; if (srv_paraminfo(pSrvProc, 1, &bType, (ULONG*)&cbMaxLen, (ULONG*)&cbActualLen, (BYTE*)szInput, &fNull) == FAIL){ printError(pSrvProc,"srv_paraminfo 返回 FAIL"); return XP_ERROR; } szInput[cbActualLen] = 0; string strInput = szInput; string strOutput = ";"; int cur,old = 0; while(string::npos != (cur = strInput.find(’;’,old)) ){ strncpy(szInput,strInput.c_str() + old,cur - old); szInput[cur - old] = 0; old = cur + 1; theFunc(szInput); if(string::npos ==strOutput.find((string)";" + szInput)) strOutput += szInput; } strcpy(szInput,strOutput.c_str()); if (FAIL == srv_paramsetoutput(pSrvProc, 1, (BYTE*)(szInput + 1), strlen(szInput) - 1,FALSE)){ printError (pSrvProc, "srv_paramsetoutput 调用失败"); return XP_ERROR; } srv_senddone(pSrvProc, (SRV_DONE_COUNT | SRV_DONE_MORE), 0, 0); return XP_NOERROR; } SRVRETCODE xp_part_finalize(SRV_PROC* pSrvProc){ typedef void (*Func)(); if(nRef == 0) return XP_NOERROR; Func theFunc = (Func)::GetProcAddress(hInst,"Fin"); if((--nRef) == 0){ theFunc(); ::FreeLibrary(hInst); hInst = NULL; } return (XP_NOERROR); } |