好不容易考完了,打算把很久以前就想写的一个小东西写出来,其实就是一个局域网内的聊天工具,原因很单纯:我的哥们有时想相互问个问题,又不想用Messenger(其实是不想被从游戏中弹出来),所以这个任务就落到了我的头上,同时练练手,好久没有编程了,因为考试。
其中用到了一个Enum局域网中的机器的程序,本来用WNetOpenEnum和WNetEnumResource就可以实现的,于是我写了这么一个东西:
bool CLANViewer::EnumHosts(NETRESOURCE* pNetRes)
{
HANDLE hEnum = NULL;
DWORD dwRet= WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_ANY, 0, pNetRes, &hEnum);
if (dwRet != NO_ERROR) return false;
NETRESOURCE* pResBuf = new NETRESOURCE[8];
DWORD cCount, dwBuf = 8*sizeof NETRESOURCE;
cCount = (DWORD)-1;
do {
dwRet = WNetEnumResource(hEnum, &cCount, (LPVOID)pResBuf, &dwBuf);
for (DWORD i = 0; i < cCount; ++i) {
AddHostToVector(&pResBuf[i]);
}
if(pResBuf[i].dwUsage & RESOURCEUSAGE_CONTAINER)
EnumHosts(&pResBuf[i]);
if (dwRet == ERROR_NO_MORE_ITEMS) { //Enum finished.
dwRet = NO_ERROR;
break;
}else if (dwRet != NO_ERROR)
break;
}while (dwRet == NO_ERROR);
delete pResBuf;
return (dwRet == NO_ERROR);
}
这个东东在Win2K下跑得很好,但是在WinXP下跑不出来,我后来跟踪了一下,发现在Win2K下程序进行Enum是直接就得到了所有的计算机明,但是在WinXP下则会先得到一个东东是“Resource Container”,也就是说dwUsage为RESOURCEUSAGE_CONTAINER,注意看我用黄色底子标出的部分:在进行第一次递归后,While循环回去,再次调用WNetEnumResource,但是这时cCount已经有了一个正值(上次调用返回的),因此调用失败,当然跑不出来。
改正很简单:把那句话移到循环内就可以了。程序如下:
bool CLANViewer::EnumHosts(NETRESOURCE* pNetRes)
{
HANDLE hEnum = NULL;
DWORD dwRet= WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_ANY, 0, pNetRes, &hEnum);
if (dwRet != NO_ERROR) return false;
NETRESOURCE* pResBuf = new NETRESOURCE[8];
DWORD cCount, dwBuf = 8*sizeof NETRESOURCE;
do {
cCount = (DWORD)-1;
dwRet = WNetEnumResource(hEnum, &cCount, (LPVOID)pResBuf, &dwBuf);
for (DWORD i = 0; i < cCount; ++i) {
AddHostToVector(&pResBuf[i]);
}
if(pResBuf[i].dwUsage & RESOURCEUSAGE_CONTAINER)
EnumHosts(&pResBuf[i]);
if (dwRet == ERROR_NO_MORE_ITEMS) { //Enum finished.
dwRet = NO_ERROR;
break;
}else if (dwRet != NO_ERROR)
break;
}while (dwRet == NO_ERROR);
delete pResBuf;
return (dwRet == NO_ERROR);
}
在XP和2K下都跑出来的。