您的位置:首页 > 其它

用Win32 API设置windows XP中FAT32文件夹共享的读写权限

2012-06-15 11:17 197 查看
首先是将文件夹设为共享的代码:





//Set a folder for net share


NET_API_STATUS AddNetShare(LPSTR sharedFolderPath, LPSTR shareName)


{


DWORD level = 2;


SHARE_INFO_2 si;


DWORD parmErr = 0;




si.shi2_netname = shareName; //share name


si.shi2_type = STYPE_DISKTREE;


si.shi2_remark = (LPSTR)L"This
is a shared folder."; //remark for the shared folder


si.shi2_path = sharedFolderPath; //path of the shared folder


si.shi2_permissions = ACCESS_ALL; //this parameter doesn't work
acctually


si.shi2_passwd = NULL; //no password need


si.shi2_max_uses = -1; //unlimited connected


si.shi2_current_uses = 0;




NET_API_STATUS res = NetShareAdd(NULL, level, (LPBYTE)&si, &parmErr);




return res;


}






注意,在上篇中谈到过,SHARE_INFO_2中的shi2_permissions对于Windows XP无效,你可以设为任意值,但对文件夹的共享读写权限不起作用。

如果只调用上面的函数将文件夹设为共享,则默认情况下,网络用户拥有全部读写权限,但很多时候我们不希望网络用户修改共享文件的内容,这样就必须编程将共享权限设置为只读,下面就是设置共享权限的代码:





enum NetShareAccessPermission


{


NetShareReadOnly = 0x001200a9, //readonly permission


NetShareFullControl = 0x001f01ff //full control permission


};




//Set access permission for net shared folder


DWORD SetNetsharePermission(LPTSTR shareName, NetShareAccessPermission permission)


{


DWORD res = 0;


PACL pOldDacl = NULL, pNewDacl = NULL;


PSECURITY_DESCRIPTOR pSD = NULL;


EXPLICIT_ACCESS ea;




res = GetNamedSecurityInfo(shareName,


SE_LMSHARE,


DACL_SECURITY_INFORMATION ,


NULL,


NULL,


&pOldDacl,


NULL,


&pSD);


if (res != ERROR_SUCCESS)


{


goto Cleanup;


}




ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));




ea.grfAccessPermissions = permission; //Set access permission (defined in enum NetShareAccessPermission)


ea.grfAccessMode = SET_ACCESS ;


ea.grfInheritance= CONTAINER_INHERIT_ACE;


ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;


ea.Trustee.ptstrName = L"Everyone";




res = SetEntriesInAcl(1, &ea, pOldDacl, &pNewDacl);


if (res != ERROR_SUCCESS)


{


goto Cleanup;


}




res = SetNamedSecurityInfo(shareName,


SE_LMSHARE,


DACL_SECURITY_INFORMATION ,


NULL,


NULL,


pNewDacl,


NULL);




Cleanup: //Release resource


if (pSD != NULL)


{


LocalFree((HLOCAL) pSD);


}




if (pNewDacl != NULL)


{


LocalFree((HLOCAL) pNewDacl);


}




return res;


}



这段代码最关键的语句是:


ea.grfAccessPermissions = permission;

其中的permission参数是一个自定义的NetShareAccessPermission枚举,如果permission==NetShareReadOnly(即0x001200a9),这样就可以将共享文件夹设为只读了。

但问题的关键是为什么要自己定义一个这样的枚举?0x001200a9和0x001f01ff这两个密码一般的十六进制数是哪里来的?难道MSDN中没有定义一个这样的枚举或宏吗?

实际上,MSDN中的确存在几个预定义的可以为ea.grfAccessPermissions 赋值的宏,上面那两个十六进制数是一个与设置文件系统安全性有关的DWORD开关变量,名为ACCESS_MASK,具体定义可以参考MSDN。win32 API函数的头文件中已经定义了几个可以为这个参数赋值的宏,如GENERIC_READ,KEY_READ等,不过这两个宏在MSDN中也是语焉不详(还是我这个菜鸟实在菜到家了,人家明明说的清清楚楚,就你一个睁眼瞎……),但你可以在VS中输入这两个宏,然后选中后右键转入定义这两个东东的头文件,在头文件有少量的解释。在这个头文件中我们还可以看到更多的预定义的宏。

不幸的是,我没有找到我要的宏,KEY_READ是用来设置注册表只读权限的,GENERIC_READ,呃,我也不知道是用来设置什么的,只知道这两个宏对我的共享权限设置除了引发一些怪异的行为外,没什么帮助。

这样只能靠自己手动的设置那个恐怖的32位的开关变量了。对于一个32位的二进制数,一共有4G种组合,假设我试一种组合要花30s,将吃饭睡觉上XX的时间都搭上,一天24小时,算一下,呃,我要花3800年才试的完……

不过,我可以考虑将这项光荣的任务交给我未来的儿子,然后来个递归,利用“子又有子,子又有孙,子子孙孙无穷匮也,而const不可增”……

不过好在我思维还算缜密,我考虑到无法保证我会有儿子,这样我的递归很可能由于条件不满足产生异常而终止……

我一向不打无把握的仗,想到了一种投机取巧的办法:我可以先通过Windows的UI设置共享文件夹的权限,然后编程获取相关的变量和结构体的值,将这些值保存下来,先不管这些值看得懂看不懂(事实上,不太可能看得懂,又是一些32位的开关量,又是一些3800年),给我们的代码赋值就行了。

我没找到直接获取ACCESS_MASK的API,于是想办法通过VS的调试功能来获取,下面是我用来获取ACCESS_MASK的代码:





//Get the value of access mask


void GetAceTest()


{


DWORD res = 0;


PACL pOldDacl = NULL, pNewDacl = NULL;


PSECURITY_DESCRIPTOR pSD = NULL;


EXPLICIT_ACCESS ea;




ACCESS_ALLOWED_ACE* pAce;




LPTSTR shareName=(LPTSTR)L"TestShareFolder";




res = GetNamedSecurityInfo(shareName,


SE_LMSHARE,


DACL_SECURITY_INFORMATION ,


NULL,


NULL,


&pOldDacl,


NULL,


&pSD);




GetAce(pOldDacl,0,(LPVOID*)&pAce);




ACCESS_MASK Mask=pAce->Mask;




return;


}



ACCESS_MASK是和ACE直接关联的,至于ACE么,呃,说来话长,还是看MSDN吧。

  但要注意的是GetAce()的第二个参数要设为0,因为ACEs是从0开始索引的,如果不小心设为1了,你在VS调试器中看到的东西足够让你郁闷了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: