Closed rshuck closed 4 years ago
I have tried your test case in Delphi 10.3.3 with both FastMM4 and FastMM5 and cannot reproduce the issue.
Looking at the code it is not obvious to me how the memory manager could be a factor here, it being mostly Windows API calls.
Many thanks for looking into this. As you couldn't find a problem I had another dig. I was reading the paths from a json file with SuperObject and when I changed the code to use Rio built-in Json the problem disappeared. I have read that SuperObject does not work 64bit so although I am not using 64 atm was intending to switch at some point anyway.
I have attached a simple bit of code which will show the problem. If call SetEveryoneFullPermissions({file or folder path}) when calling setentriesinacl you receive the error no entries were set
` unit SecurityUtils;
interface
uses SysUtils, Windows, OleDB, AclApi, AccCtrl, IOUtils;
type TPermissionsGroup = (sgEveryone);
procedure SetEveryoneFullPermissions(const Paths: Array of String);
implementation
function ConvertStringSidToSid(StringSid: PWideChar; var Sid: PSID): Boolean; stdcall; external 'advapi32.dll' name 'ConvertStringSidToSidW';
function GetSid(Group: TPermissionsGroup): PSID; const SecuritySIDs: Array[TPermissionsGroup] of String = ('S-1-1-0'); begin Result:=nil; ConvertStringSIDToSID(PChar(SecuritySIDs[Group]),Result); end;
function BuildAccess(Sid: PSID): EXPLICIT_ACCESS; var cchDomain: DWORD; cchName: DWORD; Name: array of Char; Domain: array of Char; peUse: DWORD; begin cchName := 0; cchDomain := 0; if not LookupAccountSid(nil, Sid, nil, cchName, nil, cchDomain, peUse) and (GetLastError=ERROR_INSUFFICIENT_BUFFER) then begin SetLength(Name, cchName); SetLength(Domain, cchDomain); end;
if not LookupAccountSid(nil, Sid, @Name[0], cchName, @Domain[0], cchDomain, peUse) then RaiseLastOSError;
ZeroMemory(@Result,SizeOf(Result)); BuildExplicitAccessWithName(@Result, PChar(Name), GENERIC_ALL,GRANT_ACCESS, SUB_CONTAINERS_AND_OBJECTS_INHERIT); end;
function GetAcl(const Access: EXPLICIT_ACCESS): PACL; var R: DWORD; begin R := SetEntriesInAcl(1, @Access, nil, Result); if R<>ERROR_SUCCESS then raise Exception.Create('Failed To SetEntriesInAcl '+SysErrorMessage(R)); end;
procedure SetPermissions(Path: String; ACL: PACL); begin SetNamedSecurityInfo(PChar(Path), SE_FILE_OBJECT,DACL_SECURITY_INFORMATION, nil, nil, ACL, nil); end;
procedure SetEveryoneFullPermissions(const Paths: Array of String); var Path: String; Sid: PSID; Access: EXPLICIT_ACCESS; Acl: PACL; begin Sid:=GetSid(sgEveryone); try Access:=BuildAccess(Sid); Acl:=GetAcl(Access); try for Path in Paths do if not Path.IsEmpty then SetPermissions(Path,Acl); finally LocalFree(HLOCAL(Acl)); end; finally LocalFree(HLOCAL(Sid)); end; end;
end. `