1 简介
Windows提供了NetShareEnum函数用于实现遍历服务器的共享目录,但在实现该功能时发现一个有关UNICODE和ANSI字符串的问题。
2. 函数原型简介
该函数原型如下:
NET_API_STATUS NetShareEnum( LPWSTR servername, DWORD level, LPBYTE* bufptr, DWORD prefmaxlen, LPDWORD entriesread, LPDWORD totalentries, LPDWORD resume_handle );通过第二个参数 level 用来选择使用哪种级别的信息提取,可取值分别为0,1,2,50,502,。不同的level决定了bufptr所指向的结构体不同。以502 Level为例,bufptr需要指向SHARE_INFO_502的结构体。其定义如下所示:
typedef struct _SHARE_INFO_502 { LPWSTR shi502_netname; DWORD shi502_type; LPWSTR shi502_remark; DWORD shi502_permissions; DWORD shi502_max_uses; DWORD shi502_current_uses; LPWSTR shi502_path; LPWSTR shi502_passwd; DWORD shi502_reserved; PSECURITY_DESCRIPTOR shi502_security_descriptor; } SHARE_INFO_502, *PSHARE_INFO_502, *LPSHARE_INFO_502;
3. 实现方式
//定义一个简单的结构体,用于存放一个共享目录的目录名和所在的路径。
struct SHARE_FOLDER { SHARE_FOLDER(): wsNetName(L""), wsPath(L""){} std::wstring wsNetName; std::wstring wsPath; };
//遍历本地共享文件目录,结果存放至resShareFolders容器中
bool EnumLocalShareFolders(std::vector<SHARE_FOLDER>& resShareFolders) { resShareFolders.clear(); PSHARE_INFO_502 pBuf=NULL; NET_API_STATUS res; DWORD er=0, tr=0, resume=0; do { res = NetShareEnum(NULL, 502, (LPBYTE*) &pBuf, MAX_PREFERRED_LENGTH,&er, &tr, &resume); if( NULL == pBuf) { return false; } if( ERROR_SUCCESS == res || ERROR_MORE_DATA == res ) { PSHARE_INFO_502 pPos = pBuf; for(DWORD i=1; i<=er; ++i) { SHARE_FOLDER folder; folder.wsNetName = (wchar_t*)(pPos->shi502_netname); //[1] folder.wsPath = (wchar_t*)(pPos->shi502_path); //[2] resShareFolders.push_back(folder); ++pPos; } NetApiBufferFree(pBuf); } } while(ERROR_MORE_DATA==res); return true; }
4. 存在问题
由MSDN提供的函数原型可以看出,用于存储返回信息的结构体 SHARE_INFO_502的字符串类型的成员变量都是宽字符类型 LPWSTR, 例如shi502_netname和shi502_path。事实上,通过系统的调用所提取出的字符串信息也是UNICODE字符串。但是在编译器的头文件中,该类型的字符串被定义成了LPSTR,也就是ANSI字符串,这就导致了两者的不一致。因此需要进行强制的类型转换,如上例代码中[1] [2]标记的的部分。如果不进行转换而直接将路径值和共享文件名赋值给std::wstring编译器报错。如果直接将
shi502_netname和shi502_path赋值给std::string类型,则只会赋值第一个字母。
例如,假设提取出的信息 shi502_netname 值为"ADMIN$",实际上,该值是以UNICODE编码, std::string name = shi502_netname 的赋值结果是,name=="A"。因为由于对字母高位补0,因此将后面的字符串截断。
5. 疑问
不知道是我个人理解问题,还是微软在这方面的实现有问题,笔者使用的平台是 Win7+vs2005 。 还没有在其它平台和IDE上验证。希望各位能够给出点意见和建议。