function GetAccountType(aCheckTokenForGroupDeny: boolean): string;
type
_TCTN = function(TokenHandle: THANDLE; SidToCheck: Pointer;
var IsMember: BOOL): BOOL; stdcall;
_TGroup = record
auth_id: DWORD;
name: string;
end;
const
DOMAIN_ALIAS_RID_ADMINS = $00000220;
DOMAIN_ALIAS_RID_USERS = $00000221;
DOMAIN_ALIAS_RID_GUESTS = $00000222;
DOMAIN_ALIAS_RID_POWER_USERS = $00000223;
SECURITY_BUILTIN_DOMAIN_RID = $00000020;
SE_GROUP_USE_FOR_DENY_ONLY = $00000010;
cGroups: array[0..3] of _TGroup = (
(auth_id: DOMAIN_ALIAS_RID_USERS; name: 'User'),
(auth_id: DOMAIN_ALIAS_RID_GUESTS; name: 'Guest'),
(auth_id: DOMAIN_ALIAS_RID_POWER_USERS; name: 'Power'),
(auth_id: DOMAIN_ALIAS_RID_ADMINS; name: 'Admin'));
var
fCurrGroup: string;
fpTG: PTokenGroups;
fIsValidTokenGroups: Boolean;
fIsMember: LongBool;
fcbTokenGroups: DWORD;
fHToken: DWORD;
i, j: Integer;
fCheckTokenMembershipFunc: _TCTN;
fpSID: PSID;
const
SystemSidAuthority: SID_IDENTIFIER_AUTHORITY = (Value: (0, 0, 0, 0, 0, 5));
// SECURITY_NT_AUTHORITY {0,0,0,0,0,5}
begin
fCurrGroup := '';
fHToken := 0;
fCheckTokenMembershipFunc := nil;
// Открываем хэндл токена доступа к текущему треду
if (OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, fHToken)
or OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, fHToken)) then begin
fpTG := nil;
fIsValidTokenGroups := False;
if aCheckTokenForGroupDeny then
// ...без Load/Freelibrary
fCheckTokenMembershipFunc :=
GetProcAddress(GetModuleHandle('ADVAPI32'), 'CheckTokenMembership');
// "Олдскул"...
if (not aCheckTokenForGroupDeny
or not Assigned(fCheckTokenMembershipFunc)) then
// Запрашиваем размер информации. Ожидаем от GetTokenInformation результата FALSE,
// так передаем ему NULL - буфер. По завершению в cbTokenGroups будет размер
// групповой информации.
if (not GetTokenInformation(fHToken, TokenGroups, nil, 0, fcbTokenGroups)
and (GetLastError() = ERROR_INSUFFICIENT_BUFFER)) then
begin
// Выделяем память и снова запрашиваем инфу.
// ! Если админ добавит эту учетку к дополнительной группе между
// вызовами GetTokenInformation - возможен глюк
fpTG := PTokenGroups(GlobalAlloc(GPTR, fcbTokenGroups));
if (Assigned(fpTG) and
GetTokenInformation(fHToken, TokenGroups, fpTG,
fcbTokenGroups, fcbTokenGroups)) then
fIsValidTokenGroups := True
end;
if (fIsValidTokenGroups
or (aCheckTokenForGroupDeny
and Assigned(fCheckTokenMembershipFunc))) then begin
for i := 0 to High(cGroups) do begin
// Создаем SID для локальной группы, потом проверяем, существует ли он в нашем токене
if (AllocateAndInitializeSid(
SystemSidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
cGroups[i].auth_id, 0, 0, 0, 0, 0, 0, fpSID)) then begin
fIsMember := False;
if aCheckTokenForGroupDeny
and Assigned(fCheckTokenMembershipFunc) then
fCheckTokenMembershipFunc(0, fpSID, fIsMember)
else if fIsValidTokenGroups then
for j := 0 to fpTG.GroupCount - 1 do
// Временно отключаем проверку диапазонов, из-за Groups: array[0..0]
{$IFOPT R+}
{$R-}
{$DEFINE RANGE}
{$ENDIF}
if (EqualSid(fpTG.Groups[j].Sid, fpSID)) then
{$IFDEF RANGE}
{$R+}
{$UNDEF RANGE}
{$ENDIF}
fIsMember := True;
if (fIsMember) then
fCurrGroup := cGroups[i].name;
FreeSid(fpSID);
end
end
end;
if Assigned(fpTG) then
GlobalFree(HGLOBAL(fpTG));
CloseHandle(fHToken);
result := fCurrGroup;
exit;
end;
result := '';
end;
|