Subversion Repositories userdetect2

Rev

Rev 82 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
68 daniel-mar 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
 
82 daniel-mar 8
            (*** Modified and extended by ViaThinkSoft ***)
68 daniel-mar 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;
82 daniel-mar 27
function GetComputerSID: string;
68 daniel-mar 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
 
81 daniel-mar 95
function ObtainTextSid(hToken: THandle; pszSid: PChar; var dwBufferLen: DWORD): BOOL;
68 daniel-mar 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;
81 daniel-mar 137
  szSid: array[0..MAX_PATH] of Char;
68 daniel-mar 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
 
82 daniel-mar 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
98 daniel-mar 179
  dllHandle: HMODULE;
82 daniel-mar 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
 
68 daniel-mar 263
end.