HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
のEnableLUA
(DWORD値)が0かどうかで判断できます(0はUAC無効、1はUAC有効)。一方でUACが有効のときにそのプロセスが管理者権限に昇格しているかどうかはOpenProcessToken (ja)でカレントプロセスのハンドルからアクセストークンを取得し、GetTokenInformation (ja)でTokenInformationClassにTokenElevationを指定して取得したTOKEN_ELEVATION構造体のTokenIsElevatedが0かどうかで判断できます(0は昇格していない、非0は昇格している)。まずプロセスが管理者権限に昇格しているかどうかを判定する処理です。Windows.pasのTTokenInformationClassのTokenElevationやTOKEN_ELEVATION構造体の定義はDelphi 2009で追加されたものなので、それ以前のバージョンでは独自に定義する必要があります。
{$IF (NOT DEFINED(CONDITIONALEXPRESSIONS)) OR (RTLVersion < 20.0)}
type
TTokenInformationClass = (TokenUser = 1,
TokenGroups,
TokenPrivileges,
TokenOwner,
TokenPrimaryGroup,
TokenDefaultDacl,
TokenSource,
TokenType,
TokenImpersonationLevel,
TokenStatistics,
TokenRestrictedSids,
TokenSessionId,
TokenGroupsAndPrivileges,
TokenSessionReference,
TokenSandBoxInert,
TokenAuditPolicy,
TokenOrigin,
TokenElevationType,
TokenLinkedToken,
TokenElevation,
TokenHasRestrictions,
TokenAccessInformation,
TokenVirtualizationAllowed,
TokenVirtualizationEnabled,
TokenIntegrityLevel,
TokenUIAccess,
TokenMandatoryPolicy,
TokenLogonSid,
MaxTokenInfoClass);
{$EXTERNALSYM TTokenInformationClass}
PTokenElevation = ^TTokenElevation;
_TOKEN_ELEVATION = record
TokenIsElevated: DWORD;
end;
{$EXTERNALSYM _TOKEN_ELEVATION}
TTokenElevation = _TOKEN_ELEVATION;
TOKEN_ELEVATION = _TOKEN_ELEVATION;
{$EXTERNALSYM TOKEN_ELEVATION}
function GetTokenInformation(TokenHandle: THandle;
TokenInformationClass: TTokenInformationClass;
TokenInformation: Pointer;
TokenInformationLength: DWORD;
var ReturnLength: DWORD): BOOL; stdcall;
external advapi32 name 'GetTokenInformation';
{$EXTERNALSYM GetTokenInformation}
{$IFEND}
function IsProcessTokenElevated(ProcessHandle: THandle): Boolean;
var
TokenHandle: THandle;
TE: TOKEN_ELEVATION;
dwLength: DWORD;
begin
Result := False;
if OpenProcessToken(ProcessHandle,TOKEN_QUERY,TokenHandle) = False then
begin
Exit;
end;
try
if GetTokenInformation(TokenHandle,TokenElevation,
@TE,SizeOf(TE),dwLength) = False then
begin
Exit;
end;
finally
CloseHandle(TokenHandle);
end;
Result := (TE.TokenIsElevated <> 0);
end;
これを使用して、レジストリの値をチェックし、UACが有効ならIsProcessTokenElevatedで管理者権限に昇格しているかどうかを確認します。type
TUACStatus = (usNoUAC, // UAC is not implemented
usUACDisabled, // UAC is disabled
usUACEnabled, // UAC is enabled
usUACRunAsAdmin); // UAC is enabled and process token is elevated
function GetUACStatus: TUACStatus;
var
ReadValue: Integer;
begin
Result := usNoUAC;
if CheckWin32Version(6,0) = False then
begin
// Windows 2000 or XP: UAC is not implemented
Exit;
end;
with TRegistry.Create do
begin
try
RootKey := HKEY_LOCAL_MACHINE;
if OpenKeyReadOnly('\Software\Microsoft\Windows\CurrentVersion\Policies\System') = False then
begin
raise ERegistryException.Create('Error: Cannot open registry key.');
end;
try
ReadValue := ReadInteger('EnableLUA');
if ReadValue = 0 then
begin
Result := usUACDisabled;
end
else
begin
Result := usUACEnabled;
end;
finally
CloseKey;
end;
finally
Free;
end;
end;
if Result = usUACEnabled then
begin
if IsProcessTokenElevated(GetCurrentProcess) = True then
begin
Result := usUACRunAsAdmin;
end;
end;
end;
GetUACStatusの戻値がusUACEnabledの場合、REGEDITのように実行時に管理者権限を要求するプロセスを起動するときにUACの確認ダイアログが開くことになります(usNoUAC/usUACDisabledならUACは動作せず、usUACRunAsAdminなら既に昇格済なので確認されない)。UACが有効かどうかとプロセスが昇格しているかは別々に取得するようにしたほうがいいのかもしれませんが、UAC有効でなければプロセスの昇格も起きないので、ここでは1つにまとめました。
元ねたはDisplay UAC Status - Sysinternals Forums - Page 1とEternalWindowsのセキュリティ / セキュリティコンテキスト / UAC。
0 件のコメント:
コメントを投稿