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

 

首先是将文件夹设为共享的代码:

复制代码

//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调试器中看到的东西足够让你郁闷了。

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值