Ian Boyd
Ian Boyd

Reputation: 257095

How to get the SID of the current machine?

I know how to get the SID for the current user. Conceptually the answer is:

So in pseudocode:

String GetCurrentUserSid()
{
   // Get the calling thread's access token.
   TOKEN hToken;
   if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, true, out hToken)
   { 
       if (GetLastError() != ERROR_NO_TOKEN)
          RaiseLastWin32Error();

       // No thread token exists, try again against the process token
       if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, out hToken)
          RaiseLastWin32Error();
   }
   try
   {
      // Obtain the size of the user information in the token.
      DWORD cbReturned;
      GetTokenInformation(hToken, TokenUser, nil, 0, out cbReturned);

      //Allocate memory and try again for real
      TOKEN_USER* tiUser = GetMemory(cbReturned);
      if (!GetTokenInformation(hToken, TokenUser, tiUser, cbReturned, out cbReturned))
      RaiseLastWin32Error();
   }
   finally
   {
      CloseHandle(hToken);
   }

   //Convert the structure to a string
   return SidToString(tiUser.User.Sid);
}

But how to do it for the current machine?

String GetCurrentMachineSid()
{
   // TODO: Ask Stackoverflow
}

Bonus Reading

Upvotes: 0

Views: 1496

Answers (2)

Ian Boyd
Ian Boyd

Reputation: 257095

Simpler Method

  1. Use GetComputerName to get the name of the local machine (e.g. hydrogen
  2. Call LookupAccountName to resolve the name of the computer account into its SID

Sample Code

function GetCurrentMachineSid: string;
var
    computerName: string;
    cbSid: Cardinal;
    domainName: string;
    cbDomainName: Cardinal;
    sidType: SID_NAME_USE;
    res: Boolean;
    sid: PSID;
    le: DWORD;
begin
    computerName := GetComputerNameString;

    // Get the size of the buffer required to hold the SID
    cbSid := 0;
    cbDomainName := 0;
    res := LookupAccountName(nil, PChar(computerName), nil, {var}cbSid, nil, {var}cbDomainName, {var}sidType); //sidType should be SidTypeComputer when it returns
    le := GetLastError;
    if le <> ERROR_INSUFFICIENT_BUFFER then
        RaiseLastOSError;

    sid := GetMemory(cbSid);
    try
        // Query for the actual SID
        SetLength(domainName, cbDomainName);
        res := LookupAccountName(nil, PChar(computerName), sid, {var}cbSid, PChar(domainName), {var}cbDomainName, {var}sidType);
        if not res then
            RaiseLastOSError;

        // Convert the binary SID to string form
        Result := SidToString(sid);
    finally
        FreeMemory(sid);
    end;
end;

Upvotes: 1

RbMm
RbMm

Reputation: 33804

You can see the machine SID on your computer by running Sysinternals PsGetSid with no parameters

so i simply look under debugger how PsGetSid do this.

it get SID from POLICY_ACCOUNT_DOMAIN_INFO - DomainSid : Pointer to the SID of the account domain

code can be next

LSA_HANDLE PolicyHandle;

LSA_OBJECT_ATTRIBUTES ObjectAttributes = { sizeof(ObjectAttributes) };

NTSTATUS status = LsaOpenPolicy(0, &ObjectAttributes, POLICY_VIEW_LOCAL_INFORMATION, &PolicyHandle);

if (0 <= status)
{
    POLICY_ACCOUNT_DOMAIN_INFO* ppadi;

    status = LsaQueryInformationPolicy(PolicyHandle, PolicyAccountDomainInformation, (void**)&ppadi);

    if (0 <= status)
    {
        PWSTR szSid;
        BOOL b = ConvertSidToStringSidW(ppadi->DomainSid, &szSid);
        LsaFreeMemory(ppadi);

        if (b)
        {
            DbgPrint("%S\n", szSid);
            LocalFree(szSid);
        }
    }

    LsaClose(PolicyHandle);
}

Upvotes: 1

Related Questions