Search code examples
windowsdelphiwinapidelphi-7

How to set a Windows folder's permissions using SID's in Delphi


Just now I'm looking at fixing a localization bug with a small application that get's fired during the install of a software package. The small application essentially brute forces permissions on our own folder within Application Data to set EVERYONE to full access.

The problem arises with EVERYONE not being localized. I know I need to use SID's, which for EVERYONE, is S-1-1-0. I can't find a WinAPI function for setting permissions using an SID.

The function just now uses BuildExplicitAccessWithName and SetNamedSecurityInfo as shown below

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;

Which functions should I be looking at using instead?


Solution

  • After some searching through the WinAPI documentation I went for the solution below. Essentially I use the SID to lookup the "readable" name and then use that. It won't be the most elegant solution but it works for me.

    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;