最近在使用金山詞霸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.shnenglu.com/Files/sandy/XDictWrapper.zip
使用的時候解壓放在金山詞霸同一個目錄就可以了,然后通過這個程序來啟動金山詞霸。