title: How do you check if a user has access rights for a file with the windows api
body: <p>I am trying to write a simple function for windows that answers the following question.  </p>
  
  <p>Does user (U) have rights (R) on file (F)? <br>
  Where,<br>
     R is some combination of (GENERIC_READ, GENERIC_WRITE, GENERIC_EXECUTE) <br>
     U does not have to be logged in or impersonated <br></p>
  
  <p>The code that I wrote is shown below.  The application calls the first UserHasPermission that is shown.</p>
  
  <p>The access rights returned by GetEffectiveRightsFromAcl are the same for all user/file combinations that I tested ($001200A9).  I double checked and $001200A9 is not just a pointer to the location where the access rights are actually stored.</p>
  
  <p>My question is twofold: <br>
    1. Is there a better way of doing this?<br>
    2. Can anyone tell me where I am going wrong?</p>
  
  <pre>
  function UserHasPermission(APermission: Longword; out HasPermission: Boolean; AFileName: WideString; AUserName: String; ADomainName: String): Boolean;
      var
        SID: PSID;
        ACL: PACL;
      begin
        SID := nil;
        ACL := nil;
        try
          Result := GetUserSID(SID, AUserNAme, ADomainName);
          Result := Result and GetFileDACL(AFileName, ACL);
          Result := Result and UserHasPermission(APermission, HasPermission, ACL, SID);
        finally
          Dispose(SID);
        end;
      end;
  
      function UserHasPermission(APermission: Longword; out HasPermission: Boolean; AACL: PACL; AUserSID: PSID): Boolean;
      var
        T: TRUSTEE;
        Rights: ACCESS_MASK;
      begin
        BuildTrusteeWithSid(@T, AUserSID);
        Result := GetEffectiveRightsFromAcl(AACL, @T, @Rights) = ERROR_SUCCESS;
        HasPermission := (Rights and APermission) = APermission;
      end;
  
      function GetUserSID(out ASID: PSID; AUserName: WideString; const ADomainName: WideString): Boolean;
      var
        NSID, NDomain: Longword;
        Use: SID_NAME_USE;
        DomainName: WideString;
      begin
        Result := False;
        if Length(AUserName) > 0 then
          begin
            if Length(ADomainName) > 0 then
              AUserName := ADomainName + '\' + AUserName;
  
            // determine memory requirements
            NSID := 0;
            NDomain := 0;
            LookupAccountNameW(nil, PWideChar(AUserName), nil, NSID, nil, NDomain, Use);
  
            // allocate memory
            GetMem(ASID, NSID);
            SetLength(DomainName, NDomain);
  
            Result := LookupAccountNameW(nil, PWideChar(AUserName), ASID, NSID, PWideChar(DomainName), NDomain, Use);
          end;
      end;
  
      function GetFileDACL(AFileName: WideString; out AACL: PACL): Boolean;
      var
        SD: PSecurityDescriptor;
        NSD, NNeeded: Longword;
        Present, Defualted: Longbool;
      begin
        GetFileSecurityW(PWideChar(AFileName), DACL_SECURITY_INFORMATION, nil, 0, NNeeded);
        GetMem(SD, NNeeded);
        try
          NSD := NNeeded;
          Result := GetFileSecurityW(PWideChar(AFileName), DACL_SECURITY_INFORMATION, SD, NSD, NNeeded);
          Result := Result and GetSecurityDescriptorDacl(SD, Present, AACL, Defualted);
          Result := Result and Present;
        finally
          Dispose(SD);
        end;
      end;
  </pre>