[英]How to set a Windows folder's permissions using SID's in Delphi
刚才,我正在研究使用安装在软件包安装过程中的小型应用程序修复本地化错误。 小型应用程序本质上是蛮横地强制对应用程序数据内我们自己的文件夹设置权限,以将所有人设置为完全访问权限。
问题是每个人都没有被本地化。 我知道我需要使用SID,对于每个人来说,它都是S-1-1-0
。 我找不到用于使用SID设置权限的WinAPI函数。
该函数现在使用BuildExplicitAccessWithName
和SetNamedSecurityInfo
,如下所示
function setfullaccess(foldername:string):boolean; //B2415 MDE
var
pDACL: PACL;
pEA: PEXPLICIT_ACCESS_A;
R: DWORD;
begin
result := true;
pEA := AllocMem(SizeOf(EXPLICIT_ACCESS));
BuildExplicitAccessWithName(pEA, 'EVERYONE', GENERIC_ALL{GENERIC_READ},GRANT_ACCESS, SUB_CONTAINERS_AND_OBJECTS_INHERIT{NO_INHERITANCE});
R := SetEntriesInAcl(1, pEA, nil, pDACL);
if R = ERROR_SUCCESS then
begin
if SetNamedSecurityInfo(pchar(foldername), SE_FILE_OBJECT,DACL_SECURITY_INFORMATION, nil, nil, pDACL, nil) <> ERROR_SUCCESS then result := false;
LocalFree(Cardinal(pDACL));
end
else result := false;//ShowMessage('SetEntriesInAcl failed: ' + SysErrorMessage(R));
end;
我应该改用哪些功能?
在搜索WinAPI文档后,我找到了下面的解决方案。 本质上,我使用SID查找“可读”名称,然后使用该名称。 这不是最优雅的解决方案,但对我有用。
procedure TTestform.Button4Click(Sender: TObject);
var
Sid: PSID;
peUse: DWORD;
cchDomain: DWORD;
cchName: DWORD;
Name: array of Char;
Domain: array of Char;
pDACL: PACL;
pEA: PEXPLICIT_ACCESS_A;
R: DWORD;
foldername: String; //Temp to hardcode
begin
foldername := 'C:\TEMP'; //Temp to hardcode
Sid := nil;
Win32Check(ConvertStringSidToSidA(PChar('S-1-1-0'), Sid));
cchName := 0;
cchDomain := 0;
//Get Length
if (not LookupAccountSid(nil, Sid, nil, cchName, nil, cchDomain, peUse)) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) then
begin
SetLength(Name, cchName);
SetLength(Domain, cchDomain);
if LookupAccountSid(nil, Sid, @Name[0], cchName, @Domain[0], cchDomain, peUse) then
begin
pEA := AllocMem(SizeOf(EXPLICIT_ACCESS));
BuildExplicitAccessWithName(pEA, PChar(Name), GENERIC_ALL{GENERIC_READ},GRANT_ACCESS, SUB_CONTAINERS_AND_OBJECTS_INHERIT{NO_INHERITANCE});
R := SetEntriesInAcl(1, pEA, nil, pDACL);
if R = ERROR_SUCCESS then
begin
if SetNamedSecurityInfo(pchar(foldername), SE_FILE_OBJECT,DACL_SECURITY_INFORMATION, nil, nil, pDACL, nil) <> ERROR_SUCCESS then ShowMessage('SetNamedSecurityInfo failed: ' + SysErrorMessage(GetLastError));
LocalFree(Cardinal(pDACL));
end
else ShowMessage('SetEntriesInAcl failed: ' + SysErrorMessage(R));
end;
end;
end;
避免同时使用lookup
和build
替代方法
var SID: JwaWinNT.PSid; // JWA clashes with Delphi XE2 Windows.Windows.PSID type
pDACL: PACL;
EA: EXPLICIT_ACCESS;
SID_DATA: array[1..SECURITY_MAX_SID_SIZE] of byte;
SID_DATA_SIZE: DWORD;
SID_DATA_SIZE := Length(SID_DATA);
Pointer(SID) := @SID_DATA; // @SID_DATA[Low(SID_DATA)] for non-static arrays
pDACL := nil;
// if ConvertStringSidToSid(Auth_Users_SID, SID) then
if CreateWellKnownSid(WinAuthenticatedUserSid, nil, SID, SID_DATA_SIZE) then
try
EA.grfInheritance := SUB_CONTAINERS_AND_OBJECTS_INHERIT; // NO_INHERITANCE; // 0
EA.grfAccessMode := GRANT_ACCESS;
EA.grfAccessPermissions := GENERIC_ALL;
EA.Trustee.MultipleTrusteeOperation := NO_MULTIPLE_TRUSTEE;
EA.Trustee.pMultipleTrustee := nil;
EA.Trustee.TrusteeType := TRUSTEE_IS_WELL_KNOWN_GROUP;
EA.Trustee.TrusteeForm := TRUSTEE_IS_SID;
EA.Trustee.ptstrName := pointer(SID);
if ERROR_SUCCESS = SetEntriesInAcl(1, @EA, nil, pDACL) then begin
// optional creation of PATH and 0-bytes dummy file skipped
SetNamedSecurityInfo(pchar(foldername), SE_FILE_OBJECT, .... {see the author's answer above }
end;
finally
LocalFree(pDACL); // SID is not allocated on heap - no need to free it
end;
您也可以在http://forum.vingrad.ru/forum/topic-374131/0.html#st_15_view_0上第 2页的单元上检查此代码段
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.