您的位置:首页 > 其它

使用 NetShareEnum 遍历本地共享目录需要注意的问题

2013-01-14 09:33 861 查看

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上验证。希望各位能够给出点意见和建议。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: