Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I programmatically check modify permissions?

How do I programmatically check create file permission for folder? Modify file permission? Delete file permission?
GetNamedSecurityInfo returns that I can write into C:\Program Files but UAC says Access Denied (5)
How can I effective determine access permissions?

My code:

function GetAccessRights(const FileName: String; ObjectType: SE_OBJECT_TYPE; 
  var Access: Cardinal): Cardinal;
var
  SecDesc: PSECURITY_DESCRIPTOR;
  pDacl: PACL;
  Trusteee: TRUSTEE_;
begin
  result := GetNamedSecurityInfo(PChar(FileName), ObjectType, 
    DACL_SECURITY_INFORMATION, nil, nil, @pDacl, nil, SecDesc);
  if ERROR_SUCCESS = result then
  begin
    // the pDacl may be NULL if the object has unrestricted access
    if pDacl <> nil then
    begin
      with Trusteee do
      begin
        pMultipleTrustee := nil;
        MultipleTrusteeOperation := NO_MULTIPLE_TRUSTEE;
        TrusteeForm := TRUSTEE_IS_NAME;
        TrusteeType := TRUSTEE_IS_UNKNOWN;
        ptstrName := 'CURRENT_USER';
      end;
      result := GetEffectiveRightsFromAcl(pDacl^, Trusteee, Access);
    end
    else
    begin
      Access := $FFFFFFFF;
      result := ERROR_SUCCESS;
    end;
    if SecDesc <> nil then
      LocalFree(Cardinal(SecDesc));
  end;
end;
like image 331
barbaris Avatar asked Feb 18 '13 14:02

barbaris


1 Answers

I have been using NT Utilities for this. Worked very well for me with Win2K/XP/Vista/7

Example from my setup project:

uses unitNTSecurity;

function CheckAccessToFile(DesiredAccess: DWORD; const FileOrDirName: string; ObjectName: string): Boolean;
var
  fo: TNTFileObject;
  acl: TAccessControlList;
  ace: TAccessControlElement;
  name: string;
  i: integer;
begin
  Result := False;
  if FileExists(FileOrDirName) or DirectoryExists(FileOrDirName) then
  begin
    fo := TNTFileObject.Create(FileOrDirName);
    acl := TAccessControlList.Create;
    try
      fo.GetDiscretionaryAccessList(acl);
      for i := 0 to acl.ElementCount - 1 do
      begin
        ace := acl.Element[i];
        name := ace.Name; // format is: BUILTIN\Users
        if (CompareText(ObjectName, name) = 0) and
          (ace.Type_ = aeAccessAllowed) and
          (DesiredAccess = ace.Mask) then
        begin
          Result := True;
          Break;
        end;
      end;
    finally
      fo.Free;
      acl.Free;
    end;
  end;
end;

Check for modifypermission:

Result := CheckAccessToFile($001301BF, 'C:\foo', 'BUILTIN\Users');

A note about my answer: The above code answers the OP question:

How do I programmatically check modify permissions

But, if all you need to do, is check that your application is being able to write to a directory, I would not go for this kind of ACL solution, and actually attempt to write a temp file to it, so that I'm 100% sure I can write to it.

I use this code as part of my setup process where I need to grant modify permissions for some directories, so this code is used to check if that directory does not already have these permissions - That might be a very different scenario than yours.

There are a few discussions about this issue:

  • Get FileSystem Restrictions
  • How can I use Delphi to test if a Directory is writeable?

So you need to select your solution according to your actual scenario.

like image 140
kobik Avatar answered Oct 15 '22 22:10

kobik