SPI黑客技术研究[3]

而对于分层服务提供者而言,安装要复杂一点。他需要建立两个WSAPROTOCOL_INFOW结构,一个代表分层提供者(ChainLen==0),另一个代表协议链(ChainLen>1),利用该协议链把分层服务提供者和基础服务提供者连接起来。

分层服务提供者安装的具体的步骤,概括起来大致分为五步:

第一,初始化两个协议信息结构,初始化可以借助于WSCEnumProtocols函数取回的信息来完成;

第二,用WSCInstallProvider调用来安装你的分层服务提供者;

第三,在第二步成功的基础上,列举所有的目录条目,获得新安装的分层提供者的目录编号。并利用这个目录信息来设置一个协议链的目录信息,通过这个协议链,将你的分层提供者和基础服务提供者(或者是它下一层的分层协议提供者)连接起来。

第四,调用WSCInstallProvider安装这个协议链。

第五,分层服务提供者安装成功后,Windows会在服务提供者目录的最后加入这个新的条目。但是我们为了让我们的分层服务提供者成为系统默认的TCP服务提供者的话,就必须对目录进行重新排列,让新安装的协议链目录条目放在最上面。这些排序过程通过调用WSCWriteProviderOrder完成,该函数将所有的服务提供者重新排序。需要包含 <sporder.h>头文件和sporder.lib库。

 

以下是单纯针对TCP协议(其他协议处理方法雷同)的分层服务提供者示例:

 

int CLSPinstallDlg::EnumProtocols(LPWSAPROTOCOL_INFOW* lppInfo,DWORD& dwProtocolInfoSize,int& nTotalProtocols)

{

LPWSAPROTOCOL_INFOW lpProtocolInfo=*lppInfo;

if(lpProtocolInfo!=NULL) delete[] lpProtocolInfo; lpProtocolInfo=NULL;

int nErrorCode=0;

int nRet=WSCEnumProtocols(NULL,lpProtocolInfo,&dwProtocolInfoSize,&nErrorCode);

if(nRet==SOCKET_ERROR&&nErrorCode!=WSAENOBUFS) return nErrorCode;

lpProtocolInfo = (LPWSAPROTOCOL_INFOW)new BYTE[dwProtocolInfoSize];

ASSERT(lpProtocolInfo!=NULL);

nTotalProtocols = WSCEnumProtocols(NULL,lpProtocolInfo,&dwProtocolInfoSize,&nErrorCode);

if(nTotalProtocols== SOCKET_ERROR) return -1;

*lppInfo=lpProtocolInfo;

 

return 0;

}

 

void CLSPinstallDlg::InstallLSP()

{

LPWSAPROTOCOL_INFOW lpProtocolInfo=NULL;

DWORD dwProtocolInfoSize=0;

int nTotalProtocols=0;

_try

{

// 第一步,初始化两个协议信息结构,初始化可以借助于WSCEnumProtocols函数取回的信息来完成;

int nRet=EnumProtocols(&lpProtocolInfo,dwProtocolInfoSize,nTotalProtocols);

if(nRet!=0)

{

TRACE1("WSCEnumProtocols() returns error: %d/n",nRet);

return;

}

DWORD dwLayeredCatalogId,dwTcpCatalogId;

WSAPROTOCOL_INFOW stuLayeredInfo,stuTcpChainInfo;

for(int i=0;i<nTotalProtocols;i++)

{

if(lpProtocolInfo[i].iAddressFamily == AF_INET && lpProtocolInfo[i].iProtocol == IPPROTO_TCP)

{

dwTcpCatalogId = lpProtocolInfo[i].dwCatalogEntryId;

memmove(&stuTcpChainInfo, &lpProtocolInfo[i], sizeof(WSAPROTOCOL_INFOW));

memmove(&stuLayeredInfo, &lpProtocolInfo[i], sizeof(WSAPROTOCOL_INFOW));

stuTcpChainInfo.dwServiceFlags1 = lpProtocolInfo[i].dwServiceFlags1 & ~XP1_IFS_HANDLES; 

break;

}

}

 

// 第二步,用WSCInstallProvider调用来安装你的分层服务提供者;

wcscpy(stuLayeredInfo.szProtocol, L"Mini Layered Provider";

stuLayeredInfo.ProtocolChain.ChainLen = LAYERED_PROTOCOL;

WCHAR wszDllPath[MAX_PATH*2+2]={ '/0' };

swprintf(wszDllPath,L"%%SystemRoot%%//System32//%s",m_strFileName);

int nErrorCode=0;

nRet=WSCInstallProvider(&guidMiniProvider,wszDllPath,&stuLayeredInfo,1,&nErrorCode);

if(nRet==SOCKET_ERROR)

{

printf("WSCInstallProvider failed %d/n", nErrorCode);

return;

}

 

// 第三步,在第二步成功的基础上,列举所有的目录条目,获得新安装的分层提供者的目录编号。

// 并利用这个目录信息来设置一个协议链的目录信息,通过这个协议链,将分层提供者和基础服务提供者

// (或者是它下一层的分层协议提供者)连接起来。

nRet=EnumProtocols(&lpProtocolInfo,dwProtocolInfoSize,nTotalProtocols);

if(nRet!=0)

{

TRACE1("WSCEnumProtocols() returns error: %d/n",nRet);

return;

}

for (i=0;i<nTotalProtocols;i++)

{

if(memcmp(&lpProtocolInfo[i].ProviderId, &guidMiniProvider,sizeof (GUID))==0)

{

dwLayeredCatalogId = lpProtocolInfo[i].dwCatalogEntryId;

break;

}

}

WCHAR wszChainName[MAX_PATH*2+2]={ '/0' };

swprintf(wszChainName, L"Mini Layered TCP [%s]", stuTcpChainInfo.szProtocol);

wcscpy(stuTcpChainInfo.szProtocol,wszChainName);

if (stuTcpChainInfo.ProtocolChain.ChainLen==BASE_PROTOCOL)

{

stuTcpChainInfo.ProtocolChain.ChainEntries[1] = dwTcpCatalogId;

}

else

{

for (i=stuTcpChainInfo.ProtocolChain.ChainLen;i>0;i--)

{

stuTcpChainInfo.ProtocolChain.ChainEntries[i+1] = stuTcpChainInfo.ProtocolChain.ChainEntries[i];

}

}

stuTcpChainInfo.ProtocolChain.ChainLen++;

stuTcpChainInfo.ProtocolChain.ChainEntries[0] = dwLayeredCatalogId;

 

// 第四步,调用WSCInstallProvider安装这个协议链

nRet=WSCInstallProvider(&guidMiniProviderChain,wszDllPath,&stuTcpChainInfo,1,&nErrorCode);

if(nRet==SOCKET_ERROR)

{

printf("WSCInstallProvider for protocol chain failed %d/n", nErrorCode);

return;

}

 

// 第五步,安装成功后将所有的服务提供者重新排序。

LPDWORD lpCatalogEntries=(LPDWORD)new BYTE[nTotalProtocols*sizeof(DWORD)];

ASSERT(lpCatalogEntries!=NULL);

memset(lpCatalogEntries,0,nTotalProtocols*sizeof(DWORD));

DWORD dwIndex=0;

for (i=0;i<nTotalProtocols;i++)

{

if(memcmp(&lpProtocolInfo[i].ProviderId, &guidMiniProvider, sizeof (GUID))==0 || /

memcmp (&lpProtocolInfo[i].ProviderId, &guidMiniProviderChain, sizeof (GUID))==0)

lpCatalogEntries[dwIndex++] = lpProtocolInfo[i].dwCatalogEntryId;

}

for (i=0;i<nTotalProtocols;i++)

{

if(memcmp (&lpProtocolInfo[i].ProviderId, &guidMiniProvider, sizeof (GUID))!=0 && /

memcmp (&lpProtocolInfo[i].ProviderId, &guidMiniProviderChain, sizeof (GUID))!=0)

lpCatalogEntries[dwIndex++]=lpProtocolInfo[i].dwCatalogEntryId;

}

nRet=WSCWriteProviderOrder(lpCatalogEntries,nTotalProtocols);

delete[] lpCatalogEntries; lpCatalogEntries=NULL; 

if(nRet!=ERROR_SUCCESS)

{

printf("WSCWriteProviderOrder failed %d/n", nErrorCode);

return;

}

}

__finally

{

if(lpProtocolInfo) delete[] lpProtocolInfo; lpProtocolInfo=NULL;

}

}

 

好了,到目前,我们安装了基础服务提供者和分层服务提供者,到了该卸载他们的时候了,对于基础服务提供者,简单地恢复原来的目录信息就可以了,对于分层服务提供者,调用WSCDeinstallProvider卸载函数可以简单的卸载,但是对于分层服务提供者,一定要维护好协议链,把所有和你的分层服务提供者的协议链相关的信息都清除掉,恢复安装之前的协议链状态,免得发生协议链断开的现象发生,如果断开了,就会影响网络的功能。Windows SPI在这方面存在缺陷,如果很多人装了很多个分层服务提供者,那怎么办呢?会很麻烦的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值