在项目中使用LSP模块时碰到以下几个问题,在此总结下:
1、在64位系统中,针对32位程序和64位程序需要分别实现对应的LSP模块,即64位程序不会加载32位的lsp
2、lsp模块最后放到系统盘的system32(64位 syswow64)下,否则可能导致某些程序加载不到对应的模块
3、多个lsp同时安装时,按照google搜索的用例(中文主要是这篇http://blog.csdn.net/xxaqzy/article/details/4399271,和这篇文章 http://blog.csdn.net/karen_mo/article/details/26674249),会导致后面安装的lsp卸载其他lsp模块问题,主要原因在于 lsp实现的 WSPStartup 函数,在 LoadLibrary 加载下层LSP后,不能进行释放,否则会导致下层LSP失效
示例代码如下:
LSP实现(实现代码自行google,这里仅给出关键的WSPStartup函数)
-
- //WSPStartup
- int WSPAPI WSPStartup(
- WORD wversionrequested,
- LPWSPDATA lpwspdata,
- LPWSAPROTOCOL_INFOW lppProtoInfo,
- WSPUPCALLTABLE upcalltable,
- LPWSPPROC_TABLE lpproctable)
- {
- int nRet = -1;
- int i;
- int nErrcode = 0;
- int filterpathlen, wfilterpathlen;
- int count;
- string strErr;
- DWORD layerid=0;
- DWORD nextlayerid=0;
- TCHAR *filterpath = NULL;
- WCHAR *wfilterpath = NULL;
- HINSTANCE hfilter = NULL;
- LPWSPSTARTUP wspstartupfunc = NULL;
- LPWSAPROTOCOL_INFOW pProtoInfo = NULL;
-
- do {
- if (1 >= lppProtoInfo->ProtocolChain.ChainLen) {
- //error
- break;
- }
- if (NULL == (pProtoInfo = _get_lsp(count))) {
- //error
- break;
- }
- for (i = 0; i < count; ++i) {
- if (0 == memcmp(&pProtoInfo[i].ProviderId,&filterguid,sizeof(GUID))) {
- layerid = pProtoInfo[i].dwCatalogEntryId;
- break;
- }
- }
- if (i == count) {
- //error
- break;
- }
- for (i = 0; i < lppProtoInfo->ProtocolChain.ChainLen; ++i) {
- if (lppProtoInfo->ProtocolChain.ChainEntries[i] == layerid) {
- nextlayerid = lppProtoInfo->ProtocolChain.ChainEntries[i + 1];
- break;
- }
- }
- if (i == lppProtoInfo->ProtocolChain.ChainLen) {
- //error
- break;
- }
- filterpathlen = MAX_PATH*2;
- wfilterpathlen = MAX_PATH;
- if (NULL == (filterpath =(TCHAR*)GlobalAlloc(GPTR, filterpathlen))) {
- //error
- break;
- }
- if (NULL == (wfilterpath =(WCHAR*)GlobalAlloc(GPTR, wfilterpathlen))) {
- //error
- break;
- }
- for (i = 0; i < count; ++i) {
- if (nextlayerid == pProtoInfo[i].dwCatalogEntryId) {
- break;
- }
- }
- if (i == count) {
- //error
- break;
- }
- if (SOCKET_ERROR == WSCGetProviderPath(&pProtoInfo[i].ProviderId, wfilterpath, &wfilterpathlen ,&nErrcode)) {
- //error
- break;
- }
- if (0 == WideCharToMultiByte(CP_OEMCP, NULL, wfilterpath, wfilterpathlen,
- (char *)filterpath, filterpathlen, NULL, NULL))
- {
- //error
- break;
- }
- TCHAR szPath[MAX_PATH];
- memset(szPath, 0, sizeof(szPath)*sizeof(TCHAR));
- if (0 == ExpandEnvironmentStrings(filterpath, szPath, MAX_PATH)) {
- //error
- break;
- }
- if (NULL == (hfilter = LoadLibrary(szPath))) {
- nErrcode = GetLastError();
- //error
- break;
- }
- if (NULL == (wspstartupfunc = (LPWSPSTARTUP)GetProcAddress(hfilter, "WSPStartup"))) {
- //error
- break;
- }
- if (ERROR_SUCCESS != (nErrcode = wspstartupfunc(wversionrequested, lpwspdata, lppProtoInfo, upcalltable, lpproctable))) {
- //error
- break;
- }
-
- g_next_proc_table = *lpproctable;
-
- lpproctable->lpWSPConnect = WSPConnect;
- lpproctable->lpWSPSend = WSPSend; //TCP
- lpproctable->lpWSPSendTo = WSPSendTo; //UDP
-
- nRet = 0;
- } while (0);
-
- if (0 != nRet) {
- //error
- }
-
- _free_lsp(&pProtoInfo);
- if (NULL != filterpath) {
- GlobalFree(filterpath);
- filterpath = NULL;
- }
- if (NULL != wfilterpath) {
- GlobalFree(wfilterpath);
- wfilterpath = NULL;
- }
- /* 此处不能释放,否则会导致安装多个LSP时卸载下层的LSP
- if (NULL != hfilter) {
- FreeLibrary(hfilter);
- hfilter = NULL;
- }*/
-
- return nRet;
- }
LSP安装代码
-
- int _install(
- IN const TCHAR *pszPathName)
- {
- int nRet = -1;
- string strErr;
- WCHAR wszLSPName[] = L"mmclient.lsp";
- LPWSAPROTOCOL_INFOW pProtoInfo = NULL;
- int i, nProtocols;
- WSAPROTOCOL_INFOW OriginalProtocolInfo[3];
- DWORD dwOrigCatalogId[3];
- int nArrayCount = 0;
- DWORD dwLayeredCatalogId; // 要安装的分层协议的目录ID号
- int nErrcode = 0;
- WCHAR *pwszPathName = NULL;
- DWORD dwPathNameLen = strlen(pszPathName);
- DWORD dwWPathNameLen = dwPathNameLen*3;
- PDWORD dwIds = NULL;
-
- do {
- if (NULL == (pwszPathName = (WCHAR *)GlobalAlloc(GPTR, dwWPathNameLen))) {
- //error
- break;
- }
- if (0 == MultiByteToWideChar(CP_ACP, 0, (char *)pszPathName, dwPathNameLen, pwszPathName, dwWPathNameLen)) {
- //error
- break;
- }
-
- // 枚举所有服务程序提供者
- if (NULL == (pProtoInfo = _get_provider(&nProtocols))) {
- //error
- break;
- }
- BOOL bFindUdp = FALSE;
- BOOL bFindTcp = FALSE;
- BOOL bFindRaw = FALSE;
- for (i = 0; i < nProtocols; ++i) {
- if (AF_INET == pProtoInfo[i].iAddressFamily) {
- if (FALSE == bFindUdp && IPPROTO_UDP == pProtoInfo[i].iProtocol) {
- memmove(&OriginalProtocolInfo[nArrayCount], &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));
- OriginalProtocolInfo[nArrayCount].dwServiceFlags1 = OriginalProtocolInfo[nArrayCount].dwServiceFlags1 & (~XP1_IFS_HANDLES);
- dwOrigCatalogId[nArrayCount++] = pProtoInfo[i].dwCatalogEntryId;
- bFindUdp = TRUE;
- }
- if (FALSE == bFindTcp && IPPROTO_TCP == pProtoInfo[i].iProtocol) {
- memmove(&OriginalProtocolInfo[nArrayCount], &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));
- OriginalProtocolInfo[nArrayCount].dwServiceFlags1 = OriginalProtocolInfo[nArrayCount].dwServiceFlags1 & (~XP1_IFS_HANDLES);
- dwOrigCatalogId[nArrayCount++] = pProtoInfo[i].dwCatalogEntryId;
- bFindTcp = TRUE;
- }
- if (FALSE == bFindRaw && IPPROTO_IP == pProtoInfo[i].iProtocol && pProtoInfo[i].ProtocolChain.ChainLen != LAYERED_PROTOCOL) {
- memmove(&OriginalProtocolInfo[nArrayCount], &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));
- OriginalProtocolInfo[nArrayCount].dwServiceFlags1 = OriginalProtocolInfo[nArrayCount].dwServiceFlags1 & (~XP1_IFS_HANDLES);
- dwOrigCatalogId[nArrayCount++] = pProtoInfo[i].dwCatalogEntryId;
- bFindRaw = TRUE;
- }
- }
- }
-
- // 安装我们的分层协议,获取一个dwLayeredCatalogId
- // 随便找一个下层协议的结构复制过来即可
- WSAPROTOCOL_INFOW LayeredProtocolInfo;
- memmove(&LayeredProtocolInfo, &OriginalProtocolInfo[0], sizeof(WSAPROTOCOL_INFOW));
- // 修改协议名称,类型,设置PFL_HIDDEN标志
- wcscpy_s(LayeredProtocolInfo.szProtocol, wszLSPName);
- LayeredProtocolInfo.ProtocolChain.ChainLen = LAYERED_PROTOCOL; // 0;
- LayeredProtocolInfo.dwProviderFlags |= PFL_HIDDEN;
- // 安装
- if (SOCKET_ERROR == ::WSCInstallProvider(&ProviderGuid, pwszPathName, &LayeredProtocolInfo, 1, &nErrcode)) {
- //error
- break;
- }
-
- _free_provider(&pProtoInfo);
-
- // 重新枚举协议,获取分层协议的目录ID号
- if (NULL == (pProtoInfo = _get_provider(&nProtocols))) {
- //error
- break;
- }
-
- for (i = 0; i < nProtocols; ++i) {
- if (memcmp(&pProtoInfo[i].ProviderId, &ProviderGuid, sizeof(ProviderGuid)) == 0) {
- dwLayeredCatalogId = pProtoInfo[i].dwCatalogEntryId;
- break;
- }
- }
- if (i == nProtocols) {
- //error
- break;
- }
- // 安装协议链
- // 修改协议名称,类型
- WCHAR wszChainName[WSAPROTOCOL_LEN + 1];
-
- for (i = 0; i < nArrayCount; ++i) {
- swprintf_s(wszChainName, L"%ws over %ws", wszLSPName, OriginalProtocolInfo[i].szProtocol);
- wcscpy_s(OriginalProtocolInfo[i].szProtocol, wszChainName);
- if (OriginalProtocolInfo[i].ProtocolChain.ChainLen == 1) {
- OriginalProtocolInfo[i].ProtocolChain.ChainEntries[1] = dwOrigCatalogId[i];
- } else {
- for (int j = OriginalProtocolInfo[i].ProtocolChain.ChainLen; j > 0; --j) {
- OriginalProtocolInfo[i].ProtocolChain.ChainEntries[j] = OriginalProtocolInfo[i].ProtocolChain.ChainEntries[j-1];
- }
- }
- OriginalProtocolInfo[i].ProtocolChain.ChainLen ++;
- OriginalProtocolInfo[i].ProtocolChain.ChainEntries[0] = dwLayeredCatalogId;
- }
-
- // 获取一个Guid,安装之
- GUID ProviderChainGuid;
- if (RPC_S_OK != ::UuidCreate(&ProviderChainGuid)) {
- //error
- break;
- }
- if (::WSCInstallProvider(&ProviderChainGuid, pwszPathName, OriginalProtocolInfo, nArrayCount, &nErrcode) == SOCKET_ERROR) {
- //error
- break;
- }
-
- _free_provider(&pProtoInfo);
-
- // 重新排序Winsock目录,将我们的协议链提前
- // 重新枚举安装的协议
- if (NULL == (pProtoInfo = _get_provider(&nProtocols))) {
- //error
- break;
- }
-
- if (NULL == (dwIds = (PDWORD)malloc(sizeof(DWORD) * nProtocols))) {
- //error
- break;
- }
-
- int nIndex = 0;
- // 添加我们的协议链
- for (i = 0; i < nProtocols; ++i) {
- if ((pProtoInfo[i].ProtocolChain.ChainLen > 1) &&
- (pProtoInfo[i].ProtocolChain.ChainEntries[0] == dwLayeredCatalogId))
- {
- dwIds[nIndex++] = pProtoInfo[i].dwCatalogEntryId;
- }
- }
- // 添加其它协议
- for (i = 0; i < nProtocols; ++i) {
- if ((pProtoInfo[i].ProtocolChain.ChainLen <= 1) ||
- (pProtoInfo[i].ProtocolChain.ChainEntries[0] != dwLayeredCatalogId))
- {
- dwIds[nIndex++] = pProtoInfo[i].dwCatalogEntryId;
- }
- }
- // 重新排序Winsock目录
- if ((nErrcode = ::WSCWriteProviderOrder(dwIds, nIndex)) != ERROR_SUCCESS) {
- //error
- break;
- }
-
- nRet = 0;
- } while(0);
-
- _free_provider(&pProtoInfo);
- if (NULL != pwszPathName) {
- GlobalFree(pwszPathName);
- pwszPathName = NULL;
- }
- if (NULL != dwIds) {
- free(dwIds);
- dwIds = NULL;
- }
-
- return nRet;
- }
另,附上比较有价值的 通用LSP实现和安装示例
http://www.komodia.com/lsp/lsp-sample