客户在安装期间从我们的应用程序报告错误,这表明当域管理员执行安装时,下面“IsWindowsAdministrator”中的代码返回 FALSE。以本地管理员身份登录,一切正常。安装程序 (Innosetup) 调用一个 exe 文件,该文件执行一些服务控制管理器操作(见下文),但在调用下面的 IsWindowsAdministrator 以检查用户状态之后。
我想要检查管理员状态的原因是在调用服务管理器任务以使用驱动程序之前提供一个正常的错误(请参阅下面的驱动程序安装代码)。这些是我在 Innosetup 中无法轻松完成的任务,我选择将它们包装到安装程序调用的小 exe 中。
CHECK ADMIN CODE 中的代码对此任务有效吗?还是我应该简单地放弃它并将对服务控制管理器的调用包装在 try-except 中并带有更好的错误消息?
谢谢
===================== 驱动程序安装代码 ========================
procedure ArtIODriver_Install( AShowSummary : boolean );
var
hServiceControlManager : THandle;
hService : SC_HANDLE;
ServiceStatus : TServiceStatus;
ServiceArgVectors : PAnsiString;
begin
If not IsWindowsAdministrator then
Raise EArtIODriver.Create(
'Error IODR4 - You must be a windows administrator to perform this action' );
If not FileExists( ArtIODriver_FilePath ) then
Raise EArtIODriver.CreateFmt(
'Error IODR7 - Unable to locate the driver file "%s"',
[ArtIODriver_FilePath] );
hService := 0;
hServiceControlManager := 0;
try
hServiceControlManager := OpenSCManager(
nil,
nil,
SC_MANAGER_ALL_ACCESS);
If hServiceControlManager = 0 then
Raise EArtIODriver.CreateFmt(
'Error IOD1 - Unable to open service control manager - %s',
[GetWinLastErrorStr] );
// can we see the service?
hService := OpenService(
hServiceControlManager,
JustDriverName,
SERVICE_ALL_ACCESS);
etc
etc
========= 检查管理员代码 =================
function IsWindowsAdministrator: Boolean;
// Returns TRUE if the user has administrator priveleges
// Returns a boolean indicating whether or not user has admin
// privileges. Call only when running under NT. Win9.x will return false!
var
hAccessToken : tHandle;
ptgGroups : pTokenGroups;
dwInfoBufferSize : DWORD;
psidAdministrators : PSID;
int : integer; // counter
blnResult : boolean; // return flag
const
SECURITY_NT_AUTHORITY: SID_IDENTIFIER_AUTHORITY =
(Value: (0,0,0,0,0,5)); // ntifs
SECURITY_BUILTIN_DOMAIN_RID: DWORD = $00000020;
DOMAIN_ALIAS_RID_ADMINS: DWORD = $00000220;
DOMAIN_ALIAS_RID_USERS : DWORD = $00000221;
DOMAIN_ALIAS_RID_GUESTS: DWORD = $00000222;
DOMAIN_ALIAS_RID_POWER_: DWORD = $00000223;
begin
Result := False;
blnResult := OpenThreadToken( GetCurrentThread, TOKEN_QUERY,
True, hAccessToken );
if ( not blnResult ) then
begin
if GetLastError = ERROR_NO_TOKEN then
blnResult := OpenProcessToken( GetCurrentProcess,
TOKEN_QUERY, hAccessToken );
end;
ptgGroups := nil;
if ( blnResult ) then
try
GetMem(ptgGroups, 1024);
blnResult := GetTokenInformation( hAccessToken, TokenGroups,
ptgGroups, 1024,
dwInfoBufferSize );
CloseHandle( hAccessToken );
if ( blnResult ) then
begin
AllocateAndInitializeSid( SECURITY_NT_AUTHORITY, 2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
psidAdministrators );
{$IFOPT R+}
{$DEFINE RMINUS}
{$R-}
{$ENDIF}
for int := 0 to ptgGroups.GroupCount - 1 do
if EqualSid( psidAdministrators,
ptgGroups.Groups[ int ].Sid ) then
begin
Result := True;
Break;
end;
{$IFDEF IMINUS}
{$R-}
{$UNDEF IMINUS}
{$ENDIF}
FreeSid( psidAdministrators );
end;
finally
If ptgGroups <> nil then
FreeMem( ptgGroups );
end;
end;