Win32 C++调用NetShareEnum无结果,如何排查与修复?
我用Win32 C++编写枚举Windows共享资源的函数时遇到问题:net share命令可正常显示包括默认共享在内的所有共享,但我的代码返回ERROR_SUCCESS却没有任何结果,尝试_SHARE_INFO_1、_SHARE_INFO_2、_SHARE_INFO_501等结构体均无效。
通过IDA Free分析net.exe,发现其调用NetShareEnum()时通过NetWkstaGetInfo()获取服务器名称,Ghidra显示相关导入项存在,未发现GetComputerNameEx等其他相关导入。我疑惑是否需先执行登录操作,或是杀毒软件阻止了相关调用?
以下是我的代码,调试时totalEntries和entriesRead均为0:
std::list<String> FileSystem::listShares() { std::list<String> shares; _SHARE_INFO_502* buffer, p; LPWKSTA_INFO_100 pBuf = NULL; NET_API_STATUS nStatus; // Retrieve workstation information at level 100 nStatus = NetWkstaGetInfo(NULL, 100, (LPBYTE*)&pBuf); if (nStatus != NERR_Success) { Util::printError(L"NetWkstaGetInfo"); } LPWSTR serverName = pBuf->wki100_computername; DWORD entriesRead; DWORD totalEntries; DWORD resumeHandle; DWORD result = NetShareEnum(serverName, 502, (LPBYTE*)&buffer, MAX_PREFERRED_LENGTH, &entriesRead, &totalEntries, &resumeHandle); std::wstringstream ss; if (result == 0) { for (DWORD i = 0; i < entriesRead; i++) { p = buffer[i]; ss << L"Share Name: " << p.shi502_netname << L"\n\tShare Type: " << p.shi502_type << L"\n\tRemark: " << p.shi502_remark << std::endl; shares.push_back(ss.str()); ss.str(L""); } } else { Util::printError(L"NetShareEnum"); } return shares; }
问题分析与修复
1. 核心问题:resumeHandle未初始化
NetShareEnum的resume_handle参数必须初始化为0,否则函数会因未定义行为无法正确枚举共享。你的代码仅声明了该变量但未赋值,这是导致返回成功却无条目读取的关键原因。
2. 次要问题:未处理NetWkstaGetInfo失败的情况
如果NetWkstaGetInfo调用失败,pBuf会是NULL,后续访问pBuf->wki100_computername会直接触发崩溃,必须在错误发生后终止后续逻辑。
3. 内存泄漏风险
调用NetShareEnum和NetWkstaGetInfo后,未使用NetApiBufferFree释放系统分配的内存,会造成内存泄漏。
修复后的代码
#include <list> #include <sstream> #include <windows.h> #include <lmshare.h> #pragma comment(lib, "netapi32.lib") std::list<std::wstring> FileSystem::listShares() { std::list<std::wstring> shares; _SHARE_INFO_502* buffer = nullptr; LPWKSTA_INFO_100 pBuf = nullptr; NET_API_STATUS nStatus; // 获取工作站信息 nStatus = NetWkstaGetInfo(nullptr, 100, reinterpret_cast<LPBYTE*>(&pBuf)); if (nStatus != NERR_Success) { Util::printError(L"NetWkstaGetInfo"); return shares; } DWORD entriesRead = 0; DWORD totalEntries = 0; DWORD resumeHandle = 0; // 必须初始化为0 nStatus = NetShareEnum(pBuf->wki100_computername, 502, reinterpret_cast<LPBYTE*>(&buffer), MAX_PREFERRED_LENGTH, &entriesRead, &totalEntries, &resumeHandle); std::wstringstream ss; if (nStatus == NERR_Success || nStatus == ERROR_MORE_DATA) { // 处理分段枚举的情况 do { if (buffer != nullptr && entriesRead > 0) { for (DWORD i = 0; i < entriesRead; ++i) { _SHARE_INFO_502& share = buffer[i]; ss << L"Share Name: " << share.shi502_netname << L"\n\tShare Type: " << share.shi502_type << L"\n\tRemark: " << (share.shi502_remark ? share.shi502_remark : L"") << std::endl; shares.push_back(ss.str()); ss.str(L""); } NetApiBufferFree(buffer); buffer = nullptr; } // 还有更多数据则继续枚举 if (nStatus == ERROR_MORE_DATA) { nStatus = NetShareEnum(pBuf->wki100_computername, 502, reinterpret_cast<LPBYTE*>(&buffer), MAX_PREFERRED_LENGTH, &entriesRead, &totalEntries, &resumeHandle); } else { break; } } while (nStatus == ERROR_MORE_DATA); } else { Util::printError(L"NetShareEnum"); } // 释放所有分配的内存 if (pBuf != nullptr) NetApiBufferFree(pBuf); if (buffer != nullptr) NetApiBufferFree(buffer); return shares; }
额外说明
- 无需额外登录:本地枚举共享时,普通用户权限即可枚举大部分共享,默认共享(如
C$)需要管理员权限,若看不到默认共享可尝试以管理员身份运行程序。 - 杀毒软件干扰概率低:
net share能正常运行说明系统API可用,问题基本出在代码本身而非外部拦截。
内容的提问来源于stack exchange,提问作者seanlum
相关产品推荐
相关产品推荐

