windows LSP 实现及多个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函数)


//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

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值