最近在使用金山词霸2005,由于金山词霸2005在启动的时候会发一个UDP包到局域网,然后检测是否有相同序列号的金山词霸,如果发现则要求退出。甚为无奈。windows 2000自带有防火墙的功能,但是只有Permit all 和 Permit only两种模式,居然没有Deny only,奇怪。
所以我就查了一下MSDN,发现有Routing and Remote Access Service一类的API可以用。
于是程序的流程就是这样
1.设置临时防火墙,以阻挡发到端口11113的UDP包
2.启动金山词霸
3.删除设置
代码:
#include <stdlib.h>
#include <Iphlpapi.h>
#include <Fltdefs.h>
#pragma comment(lib, "Iphlpapi.lib")
const int XDICT_PORT = 11113;
unsigned long CharToIp(const char *sIp)
{
int octets[4];
int i;
const char * auxCad = sIp;
unsigned long lIp = 0;
//we extract each octet of the ip address
//atoi will get characters until it found a non numeric character(in our case '.')
for(i = 0; i < 4; i++)
{
octets[i] = atoi(auxCad);
if(octets[i] < 0 || octets[i] > 255)
return 0;
lIp |= (octets[i] << (i*8));
//update auxCad to point to the next octet
auxCad = strchr(auxCad, '.');
if(auxCad == NULL && i!=3)
return -1;
auxCad++;
}
return lIp;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
//first get adapter info
PIP_ADAPTER_INFO pAdapterInfo = NULL,tmp;
unsigned long len = 0;
GetAdaptersInfo(pAdapterInfo,&len);
pAdapterInfo = (PIP_ADAPTER_INFO) malloc (len);
DWORD result = GetAdaptersInfo(pAdapterInfo, &len);
if(result!=ERROR_SUCCESS)
{
MessageBox(NULL,"Fail to call GetAdaptersInfo","ERROR",MB_OK);
return -1;
}
//create filters interface
INTERFACE_HANDLE hInterface = NULL;
result = PfCreateInterface(0,PF_ACTION_FORWARD,PF_ACTION_FORWARD,FALSE,TRUE,&hInterface);
if(result!=NO_ERROR)
{
MessageBox(NULL,"Fail to call PfCreateInterface","ERROR",MB_OK);
return -1;
}
//add the filter to adapter
unsigned long dmp = 0;
PF_FILTER_DESCRIPTOR ipFlt;
ipFlt.dwFilterFlags = 0;
ipFlt.dwRule = 0;
ipFlt.pfatType = PF_IPV4;
ipFlt.dwProtocol = FILTER_PROTO_UDP;
ipFlt.fLateBound = 0;
ipFlt.wSrcPort = 0;
ipFlt.wSrcPortHighRange = 0;
ipFlt.wDstPort = XDICT_PORT;
ipFlt.wDstPortHighRange = XDICT_PORT;
ipFlt.SrcAddr = (PBYTE)&dmp ;
ipFlt.SrcMask = (PBYTE)&dmp;
ipFlt.DstAddr = (PBYTE)&dmp;
ipFlt.DstMask = (PBYTE)&dmp;
//bind
IP_ADDR_STRING *localIp;
for(tmp=pAdapterInfo;tmp != NULL;tmp=tmp->Next)
{
// each ip of a adapter
for(localIp=&tmp->IpAddressList;localIp!=NULL;localIp=localIp->Next)
{
unsigned long ul = CharToIp(localIp->IpAddress.String);
PBYTE lIp = (PBYTE)&ul;
PfBindInterfaceToIPAddress(hInterface, PF_IPV4, lIp);
}
}
result = PfAddFiltersToInterface(hInterface,1,&ipFlt,1,&ipFlt,NULL);
if(result!=NO_ERROR)
{
MessageBox(NULL,"Fail to call PfAddFiltersToInterface","ERROR",MB_OK);
return -1;
}
//start XDict
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
::CreateProcess(NULL,"XDICT.exe",
NULL, // Process handle not inheritable.
NULL, // Thread handle not inheritable.
FALSE, // Set handle inheritance to FALSE.
0, // No creation flags.
NULL, // Use parent's environment block.
NULL, // Use parent's starting directory.
&si, // Pointer to STARTUPINFO structure.
&pi ); // Pointer to PROCESS_INFORMATION structure.
// Wait until child process exits.
WaitForSingleObject( pi.hProcess, INFINITE );
// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
//remove filter
for(tmp=pAdapterInfo;tmp != NULL;tmp=tmp->Next)
{
result = PfRemoveFiltersFromInterface(hInterface,1,&ipFlt,1,&ipFlt);
if(result!=NO_ERROR)
{
MessageBox(NULL,"Fail to call PfRemoveFiltersFromInterface","ERROR",MB_OK);
return -1;
}
}
PfUnBindInterface(hInterface);
PfDeleteInterface(hInterface);
//free
free(pAdapterInfo);
return 0;
}
使用的API有
GetAdapaterInfo --- 取得网卡的信息,如ip
PfCreateInterface ----Create一个Filter Interface
PfBindInterfaceToIPAddress ----绑定Filter Interface到IP
PfAddFiltersToInterface ----增加Filter到Interface
PfRemoveFiltersFromInterface ---Remove Filter
PfUnBindInterface---取消绑定到ip
PfDeleteInterface---删除Filter Interface
附上可执行文件: http://www.cppblog.com/Files/sandy/XDictWrapper.zip
使用的时候解压放在金山词霸同一个目录就可以了,然后通过这个程序来启动金山词霸。