目前,我正在參與的項目需要在本機上創建一個文件夾,並將其設置爲只讀共享,其他用戶可以通過局域網讀取該文件夾內的文件。環境是XP+VC6.0。
創建文件夾使用的命令是CreateDirectory("F:\\TEMP", NULL);
使用WIN32 API設置文件夾爲共享的命令是NetShareAdd();
具體方法見:http://www.haogongju.net/art/827019
但是這裏有一個問題,SHARE_INFO_2中的shi2_permissions對於Windows XP無效,你可以設爲任意值,但對文件夾的共享讀寫權限不起作用。
因此使用SHARE_INFO_2是無法設置文件夾爲只讀共享的。文章中提供了另一種設置的方法,但本人覺得太繁雜。
於是借鑑文章最後提到的方法使用SHARE_INFO_502來設置。由於作者只是給出了一個方向,並未提出具體的解決方案,所以需要自己想辦法。
遇到的困難集中在PSECURITY_DESCRIPTOR shi502_security_descriptor參數的設置上,這個參數設置很繁瑣。
經過搜索後,發現使用這種方法的人很少,網上的內容具有參考價值的少之又少。
最後本人難得從國外的網站上發現一個範例,能夠很好的解決該問題,主要功能就是設置PSECURITY_DESCRIPTOR shi502_security_descriptor參數。
貼出來大家共享一下,同時爲後來者提供一個參考,避免走彎路。
// create the SID representing everyone
SID_IDENTIFIER_AUTHORITY world_auth = SECURITY_WORLD_SID_AUTHORITY;
if (!AllocateAndInitializeSid(&world_auth,
1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &sid))
{
res = GetLastError();
goto error;
}
// create an ACL with read access for everyone,
// note GENERIC_READ|GENERIC_EXECUTE seem to correspond to
// read only access on a share but I haven't seen this documented
EXPLICIT_ACCESS access;
access.grfAccessPermissions = GENERIC_READ|GENERIC_EXECUTE;
access.grfAccessMode = SET_ACCESS;
access.grfInheritance = NO_INHERITANCE;
access.Trustee.pMultipleTrustee = 0;
access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
access.Trustee.TrusteeType = TRUSTEE_IS_GROUP;
access.Trustee.ptstrName = (LPSTR)sid;
res = SetEntriesInAclA(1, &access, 0, &dacl);
if (res != ERROR_SUCCESS)
{
goto error;
}
// create empty security descriptor
SECURITY_DESCRIPTOR sd;
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
{
res = GetLastError();
goto error;
}
// add the ACL to the security descriptor
if (!SetSecurityDescriptorDacl(&sd, TRUE, dacl, FALSE))
{
res = GetLastError();
goto error;
}
// create the share
SHARE_INFO_502 info;
info.shi502_netname = (LPTSTR)wshare;
info.shi502_type = STYPE_DISKTREE;
info.shi502_remark = (LPTSTR)L"";
info.shi502_permissions = ACCESS_ALL;
info.shi502_max_uses = -1;
info.shi502_current_uses = 0;
info.shi502_path = (LPTSTR)wpath;
info.shi502_passwd = (LPTSTR)L"";
info.shi502_reserved = 0;
info.shi502_security_descriptor = &sd;
res = NetShareAdd((LPTSTR)wserver, 502, (LPBYTE)&info, 0);