0

Using external function CheckTokenMembership in the below example from SO, I get access errors after the function IsUserAdmin returns to IsUserAdminStr.

When b is local var to n then there will be an access violation immediately after IsUserAdmin. If b is global var then it works.

Removing CheckTokenMembership stops error. FreeSid(AdministratorsGroup) has no effect. Changing to Result := true; has no effect

Please, please point out what I am so obviously missing.

//from https://stackoverflow.com/questions/6261865/looking-for-delphi-7-code-to-detect-if-a-program-is-started-with-administrator-r

//var b:boolean;   // <------ Works if b is here
function IsUserAdminStr(SingleChar:boolean=false):string;
begin
  if IsUserAdmin
      then result:='Admin'
      else result:='User';   //<----------- throws access error here
end;
function CheckTokenMembership(TokenHandle: THandle; SIdToCheck: PSID; var IsMember: Boolean): BOOL; StdCall; External AdvApi32;
function IsUserAdmin: Boolean;
var
  b: boolean;     // <-----------Fails if b is here
  b: BOOL;        // <------- this works 
  AdministratorsGroup: PSID;

const
  SECURITY_NT_AUTHORITY: SID_IDENTIFIER_AUTHORITY =
    (Value: (0,0,0,0,0,5)); // ntifs
  SECURITY_BUILTIN_DOMAIN_RID: DWORD = $00000020;
  DOMAIN_ALIAS_RID_ADMINS: DWORD = $00000220;
begin
  b := AllocateAndInitializeSid(
      SECURITY_NT_AUTHORITY,
      2, //2 sub-authorities
      SECURITY_BUILTIN_DOMAIN_RID,  //sub-authority 0
      DOMAIN_ALIAS_RID_ADMINS,      //sub-authority 1
      0, 0, 0, 0, 0, 0,             //sub-authorities 2-7 not passed
      AdministratorsGroup);
  if (b) then
  begin
    if not CheckTokenMembership(0, AdministratorsGroup, b) then
      b := False;
    FreeSid(AdministratorsGroup);
  end;
  Result := b;
end;
Henry Crun
  • 235
  • 1
  • 11
  • It's an output `BOOL` parameter. Define it as such (`out IsMember: BOOL`). I'm not saying it's the source of problem you report as I don't have Delphi by hand (except some mysterious force explanation :) Do some more debugging is my advice. – Victoria Oct 08 '17 at 20:36
  • Nope. But var b: BOOL; instead of boolean make it work. Why? – Henry Crun Oct 08 '17 at 20:38
  • Nope? Look into Windows SDK how `CheckTokenMembership` is declared ([this should work](https://pastebin.com/MvJ9vwJw)). – Victoria Oct 09 '17 at 05:24

1 Answers1

2

if b is BOOL not boolean, it works ``var b: BOOL;`

Still don't understand why, or why it apparently worked for original SO posters. (Using D10.1)

Henry Crun
  • 235
  • 1
  • 11
  • 1
    The Win32 API has no concept of Delphi's `Boolean` type, only its own `BOOL` type. They are different types with different sizes (`Boolean` = 1 byte, `BOOL` = 4 bytes). A `BOOL` is equivalent to Delphi's `LongBool`. When the variable is a `Boolean`, the API function is trying to write 4 bytes where only 1 byte is allocated. – Remy Lebeau Oct 09 '17 at 00:14