关于LSP是什么我就不多说了,假定大家都知道,不知道的可以去Google问问。
LSP其实还是很有用的,不过最近看到许多人在学习过程中老遇到一些问题,下面就把我的一些经验说出来,纯属个人理解,有错勿怪。
1,安装LSP后系统逐渐卡死? 额,我当时学习的时候曾经遇到过这个问题,没仔细研究是什么原因,最近解决的方法是禁止Explorer.exe进程加载。
2,安装LSP后上不了网?
写完DLL后忘记导出一些函数了吧?其中WSPStartup是必须要导出的,通常情况下这个函数的写法也是固定的。由于blogbus的日志限制字数,我发了几次都被截断了,所以就把这个代码省略了,大家去网上找吧。
3,LSP怎么安装?
很多人都是通过王艳平《Windows网络与通信程序设计》一书学习的,不过那本书的安装代码有问题,在XP上没法用。下面我发出自己的安装/卸载代码。
#include <ws2spi.h>
#include <sporder.h>
#include <windows.h>
#include <stdio.h>
#pragma comment(lib,"ws2_32.lib")
#pragma comment(lib,"rpcrt4.lib")
#pragma comment(lib,"sporder.lib")
//
// 要安装的LSP的硬编码,在移除的时候还要使用它
//
GUID
ProviderGuid
=
{
0x9d6c9dd7
,
0xa201
,
0x42f5
,{
0xa8
,
0xbc
,
0x03
,
0xf0
,
0x1f
,
0x41
,
0x72
,
0xc6
}};
//
// 枚举协议链
//
LPWSAPROTOCOL_INFOW
GetProvider(
LPINT
lpnTotalProtocols)
{
DWORD
dwSize
=
0;
int
nError;
LPWSAPROTOCOL_INFOW
pProtoInfo
=
NULL;
// 取得需要的缓冲区大小
if(
::
WSCEnumProtocols(
NULL
,
pProtoInfo
,
&
dwSize
,
&
nError)
==
SOCKET_ERROR)
{
if(
nError
!=
WSAENOBUFS)
return
NULL;
}
// 分配缓冲区
pProtoInfo
= (
LPWSAPROTOCOL_INFOW)
::
GlobalAlloc(
GPTR
,
dwSize);
*
lpnTotalProtocols
=
::
WSCEnumProtocols(
NULL
,
pProtoInfo
,
&
dwSize
,
&
nError);
return
pProtoInfo;
}
//
// 释放缓冲区
//
void
FreeProvider(
LPWSAPROTOCOL_INFOW
pProtoInfo)
{
::
GlobalFree(
pProtoInfo);
}
//
// 安装LSP
//
BOOL
InstallProvider(
char
*
pszPathName)
{
WCHAR
wszLSPName
[]
=
L"CuitWlgcxLSP";
LPWSAPROTOCOL_INFOW
pProtoInfo;
WSAPROTOCOL_INFOW
OriginalProtocolInfo
[
3
];
DWORD
dwOrigCatalogId
[
3
];
DWORD
dwLayeredCatalogId;
// 我们的分层协议目录ID
int
nProtocols;
int
nArrayCount
=
0;
int
nError;
WCHAR
wszPathName
[
256
];
memset(
wszPathName
,
0
,
sizeof(
wszPathName));
if(
!::
MultiByteToWideChar(
CP_ACP
,
0
,
pszPathName
,
-
1
,
wszPathName
,
256))
{
printf(
"MultiByteToWideChar Failed!(%d)
/n
"
,
::
GetLastError());
return
FALSE;
}
// --输出LSP DLL路径
printf(
"LSP PathName: %s
/n
"
,
pszPathName);
// 找到我们的下层协议,将信息放入数组中
pProtoInfo
=
GetProvider(
&
nProtocols);
BOOL
bFindUdp
=
FALSE;
BOOL
bFindTcp
=
FALSE;
BOOL
bFindRaw
=
FALSE;
for(
int
i
=
0;
i
<
nProtocols;
i
++)
{
if(
pProtoInfo
[
i
].
iAddressFamily
==
AF_INET)
{
if(
!
bFindTcp
&&
pProtoInfo
[
i
].
iProtocol
==
IPPROTO_TCP)
{
memcpy(
&
OriginalProtocolInfo
[
nArrayCount
],
&
pProtoInfo
[
i
],
sizeof(
WSAPROTOCOL_INFOW));
// 去掉XP1_IFS_HANDLES标志
OriginalProtocolInfo
[
nArrayCount
].
dwServiceFlags1
=
OriginalProtocolInfo
[
nArrayCount
].
dwServiceFlags1
& (
~
XP1_IFS_HANDLES);
// 保存原来的入口ID
dwOrigCatalogId
[
nArrayCount
++
]
=
pProtoInfo
[
i
].
dwCatalogEntryId;
bFindTcp
=
TRUE;
}
if(
!
bFindUdp
&&
pProtoInfo
[
i
].
iProtocol
==
IPPROTO_UDP)
{
memcpy(
&
OriginalProtocolInfo
[
nArrayCount
],
&
pProtoInfo
[
i
],
sizeof(
WSAPROTOCOL_INFOW));
OriginalProtocolInfo
[
nArrayCount
].
dwServiceFlags1
=
OriginalProtocolInfo
[
nArrayCount
].
dwServiceFlags1
& (
~
XP1_IFS_HANDLES);
dwOrigCatalogId
[
nArrayCount
++
]
=
pProtoInfo
[
i
].
dwCatalogEntryId;
bFindUdp
=
TRUE;
}
if(
!
bFindRaw
&&
pProtoInfo
[
i
].
iProtocol
==
IPPROTO_IP)
{
memcpy(
&
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;
memcpy(
&
LayeredProtocolInfo
,
&
OriginalProtocolInfo
[
0
],
sizeof(
WSAPROTOCOL_INFOW));
// 修改协议名称,类型,设置PFL_HIDDEN标志
wcscpy(
LayeredProtocolInfo
.
szProtocol
,
wszLSPName);
LayeredProtocolInfo
.
ProtocolChain
.
ChainLen
=
LAYERED_PROTOCOL;
LayeredProtocolInfo
.
dwProviderFlags
|=
PFL_HIDDEN;
// 正式安装
if(
::
WSCInstallProvider(
&
ProviderGuid
,
wszPathName
,
&
LayeredProtocolInfo
,
1
,
&
nError)
==
SOCKET_ERROR)
{
return
FALSE;
}
// 重新枚举协议,获取分层协议的目录ID号
FreeProvider(
pProtoInfo);
pProtoInfo
=
GetProvider(
&
nProtocols);
for(
i
=
0;
i
<
nProtocols;
i
++)
{
if(
memcmp(
&
pProtoInfo
[
i
].
ProviderId
,
&
ProviderGuid
,
sizeof(
ProviderGuid))
==
0)
{
dwLayeredCatalogId
=
pProtoInfo
[
i
].
dwCatalogEntryId;
break;
}
}
// 安装协议链
// 修改协议名称,类型
WCHAR
wszChainName
[
WSAPROTOCOL_LEN
+
1
];
for(
i
=
0;
i
<
nArrayCount;
i
++)
{
swprintf(
wszChainName
,
L"%ws over %ws"
,
wszLSPName
,
OriginalProtocolInfo
[
i
].
szProtocol);
wcscpy(
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(
::
UuidCreate(
&
ProviderChainGuid)
==
RPC_S_OK)
{
if(
::
WSCInstallProvider(
&
ProviderChainGuid
,
wszPathName
,
OriginalProtocolInfo
,
nArrayCount
,
&
nError)
==
SOCKET_ERROR)
{
return
FALSE;
}
}
else
return
FALSE;
// 重新排序Winsock目录,将我们的协议链提前
// 重新枚举安装的协议
FreeProvider(
pProtoInfo);
pProtoInfo
=
GetProvider(
&
nProtocols);
DWORD
dwIds
[
20
];
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((
nError
=
::
WSCWriteProviderOrder(
dwIds
,
nIndex))
!=
ERROR_SUCCESS)
{
return
FALSE;
}
FreeProvider(
pProtoInfo);
return
TRUE;
}
//
// 卸载LSP
//
BOOL
RemoveProvider()
{
LPWSAPROTOCOL_INFOW
pProtoInfo;
int
nProtocols;
DWORD
dwLayeredCatalogId;
// 根据Guid取得分层协议的目录ID号
pProtoInfo
=
GetProvider(
&
nProtocols);
int
nError;
for(
int
i
=
0;
i
<
nProtocols;
i
++)
{
if(
memcmp(
&
ProviderGuid
,
&
pProtoInfo
[
i
].
ProviderId
,
sizeof(
ProviderGuid))
==
0)
{
dwLayeredCatalogId
=
pProtoInfo
[
i
].
dwCatalogEntryId;
break;
}
}
if(
i
<
nProtocols)
{
// 移除协议链
for(
i
=
0;
i
<
nProtocols;
i
++)
{
if((
pProtoInfo
[
i
].
ProtocolChain
.
ChainLen
>
1)
&& (
pProtoInfo
[
i
].
ProtocolChain
.
ChainEntries
[
0
]
==
dwLayeredCatalogId))
{
::
WSCDeinstallProvider(
&
pProtoInfo
[
i
].
ProviderId
,
&
nError);
}
}
// 移除分层协议
::
WSCDeinstallProvider(
&
ProviderGuid
,
&
nError);
}
return
TRUE;
}
void
main(
int
argc
,
char
*
argv
[])
{
char
szFileName
[
256
];
char
szPathName
[
256
];
char
* p;
if(
argc
==
3)
{
strcpy(
szFileName
,
argv
[
2
]);
if(
strcmp(
argv
[
1
],
"-install")
==
0)
{
if(
::
GetFullPathName(
szFileName
,
256
,
szPathName
,
&p)
!=
0)
{
if(
InstallProvider(
szPathName))
{
printf(
"
/n
Install Successully!
/n
");
return;
}
}
if(
::
GetFileAttributes(
szPathName)
==
-
1)
{
printf(
"Error:Can't Find File!
/n
");
return;
}
printf(
"
/n
Install Failed -> %d
/n
"
,
::
GetLastError());
return;
}
else
if(
strcmp(
argv
[
1
],
"-remove")
==
0)
{
if(
RemoveProvider())
printf(
"
/n
Remove Successully!
/n
");
else
printf(
"
/n
Remove Failed -> %d
/n
"
,
::
GetLastError());
return;
}
}
}