当前位置:   article > 正文

windows LSP 实现及多个lsp兼容安装的几个坑

64位lsp安装失败

在项目中使用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函数)

  1. //WSPStartup
  2. int WSPAPI WSPStartup(
  3. WORD wversionrequested,
  4. LPWSPDATA lpwspdata,
  5. LPWSAPROTOCOL_INFOW lppProtoInfo,
  6. WSPUPCALLTABLE upcalltable,
  7. LPWSPPROC_TABLE lpproctable)
  8. {
  9. int nRet = -1;
  10. int i;
  11. int nErrcode = 0;
  12. int filterpathlen, wfilterpathlen;
  13. int count;
  14. string strErr;
  15. DWORD layerid=0;
  16. DWORD nextlayerid=0;
  17. TCHAR *filterpath = NULL;
  18. WCHAR *wfilterpath = NULL;
  19. HINSTANCE hfilter = NULL;
  20. LPWSPSTARTUP wspstartupfunc = NULL;
  21. LPWSAPROTOCOL_INFOW pProtoInfo = NULL;
  22. do {
  23. if (1 >= lppProtoInfo->ProtocolChain.ChainLen) {
  24. //error
  25. break;
  26. }
  27. if (NULL == (pProtoInfo = _get_lsp(count))) {
  28. //error
  29. break;
  30. }
  31. for (i = 0; i < count; ++i) {
  32. if (0 == memcmp(&pProtoInfo[i].ProviderId,&filterguid,sizeof(GUID))) {
  33. layerid = pProtoInfo[i].dwCatalogEntryId;
  34. break;
  35. }
  36. }
  37. if (i == count) {
  38. //error
  39. break;
  40. }
  41. for (i = 0; i < lppProtoInfo->ProtocolChain.ChainLen; ++i) {
  42. if (lppProtoInfo->ProtocolChain.ChainEntries[i] == layerid) {
  43. nextlayerid = lppProtoInfo->ProtocolChain.ChainEntries[i + 1];
  44. break;
  45. }
  46. }
  47. if (i == lppProtoInfo->ProtocolChain.ChainLen) {
  48. //error
  49. break;
  50. }
  51. filterpathlen = MAX_PATH*2;
  52. wfilterpathlen = MAX_PATH;
  53. if (NULL == (filterpath =(TCHAR*)GlobalAlloc(GPTR, filterpathlen))) {
  54. //error
  55. break;
  56. }
  57. if (NULL == (wfilterpath =(WCHAR*)GlobalAlloc(GPTR, wfilterpathlen))) {
  58. //error
  59. break;
  60. }
  61. for (i = 0; i < count; ++i) {
  62. if (nextlayerid == pProtoInfo[i].dwCatalogEntryId) {
  63. break;
  64. }
  65. }
  66. if (i == count) {
  67. //error
  68. break;
  69. }
  70. if (SOCKET_ERROR == WSCGetProviderPath(&pProtoInfo[i].ProviderId, wfilterpath, &wfilterpathlen ,&nErrcode)) {
  71. //error
  72. break;
  73. }
  74. if (0 == WideCharToMultiByte(CP_OEMCP, NULL, wfilterpath, wfilterpathlen,
  75. (char *)filterpath, filterpathlen, NULL, NULL))
  76. {
  77. //error
  78. break;
  79. }
  80. TCHAR szPath[MAX_PATH];
  81. memset(szPath, 0, sizeof(szPath)*sizeof(TCHAR));
  82. if (0 == ExpandEnvironmentStrings(filterpath, szPath, MAX_PATH)) {
  83. //error
  84. break;
  85. }
  86. if (NULL == (hfilter = LoadLibrary(szPath))) {
  87. nErrcode = GetLastError();
  88. //error
  89. break;
  90. }
  91. if (NULL == (wspstartupfunc = (LPWSPSTARTUP)GetProcAddress(hfilter, "WSPStartup"))) {
  92. //error
  93. break;
  94. }
  95. if (ERROR_SUCCESS != (nErrcode = wspstartupfunc(wversionrequested, lpwspdata, lppProtoInfo, upcalltable, lpproctable))) {
  96. //error
  97. break;
  98. }
  99. g_next_proc_table = *lpproctable;
  100. lpproctable->lpWSPConnect = WSPConnect;
  101. lpproctable->lpWSPSend = WSPSend; //TCP
  102. lpproctable->lpWSPSendTo = WSPSendTo; //UDP
  103. nRet = 0;
  104. } while (0);
  105. if (0 != nRet) {
  106. //error
  107. }
  108. _free_lsp(&pProtoInfo);
  109. if (NULL != filterpath) {
  110. GlobalFree(filterpath);
  111. filterpath = NULL;
  112. }
  113. if (NULL != wfilterpath) {
  114. GlobalFree(wfilterpath);
  115. wfilterpath = NULL;
  116. }
  117. /* 此处不能释放,否则会导致安装多个LSP时卸载下层的LSP
  118. if (NULL != hfilter) {
  119. FreeLibrary(hfilter);
  120. hfilter = NULL;
  121. }*/
  122. return nRet;
  123. }

LSP安装代码

  1. int _install(
  2. IN const TCHAR *pszPathName)
  3. {
  4. int nRet = -1;
  5. string strErr;
  6. WCHAR wszLSPName[] = L"mmclient.lsp";
  7. LPWSAPROTOCOL_INFOW pProtoInfo = NULL;
  8. int i, nProtocols;
  9. WSAPROTOCOL_INFOW OriginalProtocolInfo[3];
  10. DWORD dwOrigCatalogId[3];
  11. int nArrayCount = 0;
  12. DWORD dwLayeredCatalogId; // 要安装的分层协议的目录ID号
  13. int nErrcode = 0;
  14. WCHAR *pwszPathName = NULL;
  15. DWORD dwPathNameLen = strlen(pszPathName);
  16. DWORD dwWPathNameLen = dwPathNameLen*3;
  17. PDWORD dwIds = NULL;
  18. do {
  19. if (NULL == (pwszPathName = (WCHAR *)GlobalAlloc(GPTR, dwWPathNameLen))) {
  20. //error
  21. break;
  22. }
  23. if (0 == MultiByteToWideChar(CP_ACP, 0, (char *)pszPathName, dwPathNameLen, pwszPathName, dwWPathNameLen)) {
  24. //error
  25. break;
  26. }
  27. // 枚举所有服务程序提供者
  28. if (NULL == (pProtoInfo = _get_provider(&nProtocols))) {
  29. //error
  30. break;
  31. }
  32. BOOL bFindUdp = FALSE;
  33. BOOL bFindTcp = FALSE;
  34. BOOL bFindRaw = FALSE;
  35. for (i = 0; i < nProtocols; ++i) {
  36. if (AF_INET == pProtoInfo[i].iAddressFamily) {
  37. if (FALSE == bFindUdp && IPPROTO_UDP == pProtoInfo[i].iProtocol) {
  38. memmove(&OriginalProtocolInfo[nArrayCount], &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));
  39. OriginalProtocolInfo[nArrayCount].dwServiceFlags1 = OriginalProtocolInfo[nArrayCount].dwServiceFlags1 & (~XP1_IFS_HANDLES);
  40. dwOrigCatalogId[nArrayCount++] = pProtoInfo[i].dwCatalogEntryId;
  41. bFindUdp = TRUE;
  42. }
  43. if (FALSE == bFindTcp && IPPROTO_TCP == pProtoInfo[i].iProtocol) {
  44. memmove(&OriginalProtocolInfo[nArrayCount], &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));
  45. OriginalProtocolInfo[nArrayCount].dwServiceFlags1 = OriginalProtocolInfo[nArrayCount].dwServiceFlags1 & (~XP1_IFS_HANDLES);
  46. dwOrigCatalogId[nArrayCount++] = pProtoInfo[i].dwCatalogEntryId;
  47. bFindTcp = TRUE;
  48. }
  49. if (FALSE == bFindRaw && IPPROTO_IP == pProtoInfo[i].iProtocol && pProtoInfo[i].ProtocolChain.ChainLen != LAYERED_PROTOCOL) {
  50. memmove(&OriginalProtocolInfo[nArrayCount], &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW));
  51. OriginalProtocolInfo[nArrayCount].dwServiceFlags1 = OriginalProtocolInfo[nArrayCount].dwServiceFlags1 & (~XP1_IFS_HANDLES);
  52. dwOrigCatalogId[nArrayCount++] = pProtoInfo[i].dwCatalogEntryId;
  53. bFindRaw = TRUE;
  54. }
  55. }
  56. }
  57. // 安装我们的分层协议,获取一个dwLayeredCatalogId
  58. // 随便找一个下层协议的结构复制过来即可
  59. WSAPROTOCOL_INFOW LayeredProtocolInfo;
  60. memmove(&LayeredProtocolInfo, &OriginalProtocolInfo[0], sizeof(WSAPROTOCOL_INFOW));
  61. // 修改协议名称,类型,设置PFL_HIDDEN标志
  62. wcscpy_s(LayeredProtocolInfo.szProtocol, wszLSPName);
  63. LayeredProtocolInfo.ProtocolChain.ChainLen = LAYERED_PROTOCOL; // 0;
  64. LayeredProtocolInfo.dwProviderFlags |= PFL_HIDDEN;
  65. // 安装
  66. if (SOCKET_ERROR == ::WSCInstallProvider(&ProviderGuid, pwszPathName, &LayeredProtocolInfo, 1, &nErrcode)) {
  67. //error
  68. break;
  69. }
  70. _free_provider(&pProtoInfo);
  71. // 重新枚举协议,获取分层协议的目录ID号
  72. if (NULL == (pProtoInfo = _get_provider(&nProtocols))) {
  73. //error
  74. break;
  75. }
  76. for (i = 0; i < nProtocols; ++i) {
  77. if (memcmp(&pProtoInfo[i].ProviderId, &ProviderGuid, sizeof(ProviderGuid)) == 0) {
  78. dwLayeredCatalogId = pProtoInfo[i].dwCatalogEntryId;
  79. break;
  80. }
  81. }
  82. if (i == nProtocols) {
  83. //error
  84. break;
  85. }
  86. // 安装协议链
  87. // 修改协议名称,类型
  88. WCHAR wszChainName[WSAPROTOCOL_LEN + 1];
  89. for (i = 0; i < nArrayCount; ++i) {
  90. swprintf_s(wszChainName, L"%ws over %ws", wszLSPName, OriginalProtocolInfo[i].szProtocol);
  91. wcscpy_s(OriginalProtocolInfo[i].szProtocol, wszChainName);
  92. if (OriginalProtocolInfo[i].ProtocolChain.ChainLen == 1) {
  93. OriginalProtocolInfo[i].ProtocolChain.ChainEntries[1] = dwOrigCatalogId[i];
  94. } else {
  95. for (int j = OriginalProtocolInfo[i].ProtocolChain.ChainLen; j > 0; --j) {
  96. OriginalProtocolInfo[i].ProtocolChain.ChainEntries[j] = OriginalProtocolInfo[i].ProtocolChain.ChainEntries[j-1];
  97. }
  98. }
  99. OriginalProtocolInfo[i].ProtocolChain.ChainLen ++;
  100. OriginalProtocolInfo[i].ProtocolChain.ChainEntries[0] = dwLayeredCatalogId;
  101. }
  102. // 获取一个Guid,安装之
  103. GUID ProviderChainGuid;
  104. if (RPC_S_OK != ::UuidCreate(&ProviderChainGuid)) {
  105. //error
  106. break;
  107. }
  108. if (::WSCInstallProvider(&ProviderChainGuid, pwszPathName, OriginalProtocolInfo, nArrayCount, &nErrcode) == SOCKET_ERROR) {
  109. //error
  110. break;
  111. }
  112. _free_provider(&pProtoInfo);
  113. // 重新排序Winsock目录,将我们的协议链提前
  114. // 重新枚举安装的协议
  115. if (NULL == (pProtoInfo = _get_provider(&nProtocols))) {
  116. //error
  117. break;
  118. }
  119. if (NULL == (dwIds = (PDWORD)malloc(sizeof(DWORD) * nProtocols))) {
  120. //error
  121. break;
  122. }
  123. int nIndex = 0;
  124. // 添加我们的协议链
  125. for (i = 0; i < nProtocols; ++i) {
  126. if ((pProtoInfo[i].ProtocolChain.ChainLen > 1) &&
  127. (pProtoInfo[i].ProtocolChain.ChainEntries[0] == dwLayeredCatalogId))
  128. {
  129. dwIds[nIndex++] = pProtoInfo[i].dwCatalogEntryId;
  130. }
  131. }
  132. // 添加其它协议
  133. for (i = 0; i < nProtocols; ++i) {
  134. if ((pProtoInfo[i].ProtocolChain.ChainLen <= 1) ||
  135. (pProtoInfo[i].ProtocolChain.ChainEntries[0] != dwLayeredCatalogId))
  136. {
  137. dwIds[nIndex++] = pProtoInfo[i].dwCatalogEntryId;
  138. }
  139. }
  140. // 重新排序Winsock目录
  141. if ((nErrcode = ::WSCWriteProviderOrder(dwIds, nIndex)) != ERROR_SUCCESS) {
  142. //error
  143. break;
  144. }
  145. nRet = 0;
  146. } while(0);
  147. _free_provider(&pProtoInfo);
  148. if (NULL != pwszPathName) {
  149. GlobalFree(pwszPathName);
  150. pwszPathName = NULL;
  151. }
  152. if (NULL != dwIds) {
  153. free(dwIds);
  154. dwIds = NULL;
  155. }
  156. return nRet;
  157. }

 

另,附上比较有价值的 通用LSP实现和安装示例

http://www.komodia.com/lsp/lsp-sample

转载于:https://my.oschina.net/lastmagician/blog/741952

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/620491
推荐阅读
相关标签
  

闽ICP备14008679号