Subversion Repositories userdetect2

Rev

Rev 81 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. (******************************************************************************)
  2. (* SPGetSid - Retrieve the current user's SID in text format                  *)
  3. (*                                                                            *)
  4. (* Copyright (c) 2004 Shorter Path Software                                   *)
  5. (* http://www.shorterpath.com                                                 *)
  6. (******************************************************************************)
  7.  
  8.             (*** Modified and extended by ViaThinkSoft ***)
  9.  
  10. {
  11.   SID is a data structure of variable length that identifies user, group,
  12.   and computer accounts.
  13.   Every account on a network is issued a unique SID when the account is first created.
  14.   Internal processes in Windows refer to an account's SID
  15.   rather than the account's user or group name.
  16. }
  17.  
  18.  
  19. unit SPGetSid;
  20.  
  21. interface
  22.  
  23. uses
  24.   Windows, SysUtils;
  25.  
  26. function GetCurrentUserSid: string;
  27. function GetComputerSID: string;
  28.  
  29. implementation
  30.  
  31. const
  32.   HEAP_ZERO_MEMORY = $00000008;
  33.   SID_REVISION     = 1; // Current revision level
  34.  
  35. type
  36.   PTokenUser = ^TTokenUser;
  37.   TTokenUser = packed record
  38.     User: TSidAndAttributes;
  39.   end;
  40.  
  41. function ConvertSid(Sid: PSID; pszSidText: PChar; var dwBufferLen: DWORD): BOOL;
  42. var
  43.   psia: PSIDIdentifierAuthority;
  44.   dwSubAuthorities: DWORD;
  45.   dwSidRev: DWORD;
  46.   dwCounter: DWORD;
  47.   dwSidSize: DWORD;
  48. begin
  49.   Result := False;
  50.  
  51.   dwSidRev := SID_REVISION;
  52.  
  53.   if not IsValidSid(Sid) then Exit;
  54.  
  55.   psia := GetSidIdentifierAuthority(Sid);
  56.  
  57.   dwSubAuthorities := GetSidSubAuthorityCount(Sid)^;
  58.  
  59.   dwSidSize := (15 + 12 + (12 * dwSubAuthorities) + 1) * SizeOf(Char);
  60.  
  61.   if (dwBufferLen < dwSidSize) then
  62.   begin
  63.     dwBufferLen := dwSidSize;
  64.     SetLastError(ERROR_INSUFFICIENT_BUFFER);
  65.     Exit;
  66.   end;
  67.  
  68.   StrFmt(pszSidText, 'S-%u-', [dwSidRev]);
  69.  
  70.   if (psia.Value[0] <> 0) or (psia.Value[1] <> 0) then
  71.     StrFmt(pszSidText + StrLen(pszSidText),
  72.       '0x%.2x%.2x%.2x%.2x%.2x%.2x',
  73.       [psia.Value[0], psia.Value[1], psia.Value[2],
  74.       psia.Value[3], psia.Value[4], psia.Value[5]])
  75.   else
  76.     StrFmt(pszSidText + StrLen(pszSidText),
  77.       '%u',
  78.       [DWORD(psia.Value[5]) +
  79.       DWORD(psia.Value[4] shl 8) +
  80.       DWORD(psia.Value[3] shl 16) +
  81.       DWORD(psia.Value[2] shl 24)]);
  82.  
  83.   dwSidSize := StrLen(pszSidText);
  84.  
  85.   for dwCounter := 0 to dwSubAuthorities - 1 do
  86.   begin
  87.     StrFmt(pszSidText + dwSidSize, '-%u',
  88.       [GetSidSubAuthority(Sid, dwCounter)^]);
  89.     dwSidSize := StrLen(pszSidText);
  90.   end;
  91.  
  92.   Result := True;
  93. end;
  94.  
  95. function ObtainTextSid(hToken: THandle; pszSid: PChar; var dwBufferLen: DWORD): BOOL;
  96. var
  97.   dwReturnLength: DWORD;
  98.   dwTokenUserLength: DWORD;
  99.   tic: TTokenInformationClass;
  100.   ptu: Pointer;
  101. begin
  102.   Result := False;
  103.   dwReturnLength := 0;
  104.   dwTokenUserLength := 0;
  105.   tic := TokenUser;
  106.   ptu := nil;
  107.  
  108.   if not GetTokenInformation(hToken, tic, ptu, dwTokenUserLength,
  109.     dwReturnLength) then
  110.   begin
  111.     if GetLastError = ERROR_INSUFFICIENT_BUFFER then
  112.     begin
  113.       ptu := HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, dwReturnLength);
  114.       if ptu = nil then Exit;
  115.       dwTokenUserLength := dwReturnLength;
  116.       dwReturnLength    := 0;
  117.  
  118.       if not GetTokenInformation(hToken, tic, ptu, dwTokenUserLength,
  119.         dwReturnLength) then Exit;
  120.     end
  121.     else
  122.       Exit;
  123.   end;
  124.  
  125.   if not ConvertSid((PTokenUser(ptu).User).Sid, pszSid, dwBufferLen) then Exit;
  126.  
  127.   if not HeapFree(GetProcessHeap, 0, ptu) then Exit;
  128.  
  129.   Result := True;
  130. end;
  131.  
  132. function GetCurrentUserSid: string;
  133. var
  134.   hAccessToken: THandle;
  135.   bSuccess: BOOL;
  136.   dwBufferLen: DWORD;
  137.   szSid: array[0..MAX_PATH] of Char;
  138. begin
  139.   Result := '';
  140.  
  141.   bSuccess := OpenThreadToken(GetCurrentThread, TOKEN_QUERY, True,
  142.     hAccessToken);
  143.   if not bSuccess then
  144.   begin
  145.     if GetLastError = ERROR_NO_TOKEN then
  146.       bSuccess := OpenProcessToken(GetCurrentProcess, TOKEN_QUERY,
  147.         hAccessToken);
  148.   end;
  149.   if bSuccess then
  150.   begin
  151.     ZeroMemory(@szSid, SizeOf(szSid));
  152.     dwBufferLen := SizeOf(szSid);
  153.  
  154.     if ObtainTextSid(hAccessToken, szSid, dwBufferLen) then
  155.       Result := szSid;
  156.     CloseHandle(hAccessToken);
  157.   end;
  158. end;
  159.  
  160. // --- Section added by ViaThinkSoft ---
  161.  
  162. function SIDToString(ASID: PSID): string;
  163.  
  164.   function _FallBack: string;
  165.   var
  166.     StringSid : PChar;
  167.     len: DWORD;
  168.   begin
  169.     len := MAX_PATH;
  170.     StringSid := AllocMem(MAX_PATH);
  171.     ConvertSid(ASID, StringSid, len);
  172.     Result := string(StringSid);
  173.     FreeMem(StringSid);
  174.   end;
  175.  
  176. type
  177.   TFuncConvertSidToStringSid = function(Sid: PSID; out StringSid: PChar): BOOL; stdcall;
  178. var
  179.   dllHandle: Cardinal;
  180.   fConvertSidToStringSid: TFuncConvertSidToStringSid;
  181.   StringSid : PChar;
  182. begin
  183.   dllHandle := LoadLibrary(advapi32);
  184.   if dllHandle = 0 then
  185.   begin
  186.     result := _FallBack;
  187.     Exit;
  188.   end;
  189.   try
  190.     @fConvertSidToStringSid := GetProcAddress(dllHandle, {$IFDEF UNICODE}'ConvertSidToStringSidW'{$ELSE}'ConvertSidToStringSidA'{$ENDIF});
  191.     if not Assigned(fConvertSidToStringSid) then
  192.     begin
  193.       result := _FallBack;
  194.       Exit;
  195.     end;
  196.  
  197.     fConvertSidToStringSid(ASID, StringSid);
  198.     Result := string(StringSid);
  199.     LocalFree(HLocal(StringSid)); // added by ViaThinkSoft
  200.   finally
  201.     FreeLibrary(dllHandle);
  202.   end;
  203. end;
  204.  
  205. function GetComputerName: string;
  206. // Source: http://www.delphi-treff.de/tipps-tricks/netzwerkinternet/netzwerkeigenschaften/computernamen-des-eigenen-rechners-ermitteln/
  207. var
  208.   Len: DWORD;
  209. begin
  210.   Len := MAX_COMPUTERNAME_LENGTH+1;
  211.   SetLength(Result,Len);
  212.   if Windows.GetComputerName(PChar(Result), Len) then
  213.     SetLength(Result,Len)
  214.   else
  215.     RaiseLastOSError;
  216. end;
  217.  
  218. function GetComputerSID: string;
  219. // Source: http://stackoverflow.com/a/7643383
  220. var
  221.   Sid: PSID;
  222.   cbSid: DWORD;
  223.   cbReferencedDomainName : DWORD;
  224.   ReferencedDomainName: string;
  225.   peUse: SID_NAME_USE;
  226.   Success: BOOL;
  227.   lpSystemName : string;
  228.   lpAccountName: string;
  229. begin
  230.   result := '';
  231.   Sid:=nil;
  232.   try
  233.     lpSystemName:='';
  234.     lpAccountName:=GetComputerName;
  235.  
  236.     cbSid := 0;
  237.     cbReferencedDomainName := 0;
  238.     // First call to LookupAccountName to get the buffer sizes.
  239.     Success := LookupAccountName(PChar(lpSystemName), PChar(lpAccountName), nil, cbSid, nil, cbReferencedDomainName, peUse);
  240.     if (not Success) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) then
  241.     begin
  242.       SetLength(ReferencedDomainName, cbReferencedDomainName);
  243.       Sid := AllocMem(cbSid);
  244.       // Second call to LookupAccountName to get the SID.
  245.       Success := LookupAccountName(PChar(lpSystemName), PChar(lpAccountName), Sid, cbSid, PChar(ReferencedDomainName), cbReferencedDomainName, peUse);
  246.       if not Success then
  247.       begin
  248.         FreeMem(Sid);
  249.         Sid := nil;
  250.         RaiseLastOSError;
  251.       end
  252.       else
  253.         Result := SIDToString(Sid);
  254.     end
  255.     else
  256.       RaiseLastOSError;
  257.   finally
  258.     if Assigned(Sid) then
  259.       FreeMem(Sid);
  260.   end;
  261. end;
  262.  
  263. end.
  264.