InnoSetup 调用给定服务的依赖服务

问题描述 投票:0回答:1

我目前正在研究 InnoSetup 安装程序,它检查给定服务的依赖服务。根据 MSDN 文档,我需要函数

EnumDependentServices()
.

但是,当我将参数传递给该函数时,InnoSetup 给我状态代码 5,代表“拒绝访问”,尽管我以管理员身份执行我的安装程序。

我正在使用

SC_MANAGER_ALL_ACCESS (0xF003F)
权限启动服务处理程序,但它仍然拒绝我的函数调用。

SCManager 和打开的服务(我用“DnsCache”测试过)都返回非零值,并与我的其他函数一起工作。

这是我的

[Code]
文件中的
.iss
片段:

#ifdef UNICODE
  #define AW "W"
#else
  #define AW "A"
#endif



type
    SERVICE_STATUS = record
    dwServiceType: DWORD;
    dwCurrentState: DWORD;
    dwControlsAccepted: DWORD;
    dwWin32ExitCode: DWORD;
    dwServiceSpecificExitCode: DWORD;
    dwCheckPoint: DWORD;
    dwWaitHint: DWORD;
  end;
    HANDLE = THandle;
    PDWord = DWORD;

const
    SERVICE_QUERY_CONFIG        = $1;
    SC_MANAGER_CONNECT          = $0001;
    SERVICE_QUERY_STATUS        = $0004;
    SERVICE_CHANGE_CONFIG       = $2;
    SERVICE_CURRENT_STATUS      = $0003;
    SERVICE_START               = $10;
    SERVICE_STOP                = $20;
    SERVICE_ALL_ACCESS          = $f01ff;
    SC_MANAGER_ALL_ACCESS       = $F003F;
    SERVICE_WIN32_OWN_PROCESS   = $10;
    SERVICE_WIN32_SHARE_PROCESS = $20;
    SERVICE_WIN32               = $30;
    SERVICE_INTERACTIVE_PROCESS = $100;
    SERVICE_BOOT_START          = $0;
    SERVICE_SYSTEM_START        = $1;
    SERVICE_AUTO_START          = $2;
    SERVICE_DEMAND_START        = $3;
    SERVICE_DISABLED            = $4;
    SERVICE_DELETE              = $10000;
    SERVICE_CONTROL_STOP        = $1;
    SERVICE_CONTROL_PAUSE       = $2;
    SERVICE_CONTROL_CONTINUE    = $3;
    SERVICE_CONTROL_INTERROGATE = $4;
    SERVICE_STOPPED             = $1;
    SERVICE_START_PENDING       = $2;
    SERVICE_STOP_PENDING        = $3;
    SERVICE_RUNNING             = $4;
    SERVICE_CONTINUE_PENDING    = $5;
    SERVICE_PAUSE_PENDING       = $6;
    SERVICE_PAUSED              = $7;

// #######################################################################################
// nt based service utilities
// #######################################################################################
function OpenSCManager(lpMachineName, lpDatabaseName: string; dwDesiredAccess :cardinal): HANDLE;
external 'OpenSCManager{#AW}@advapi32.dll stdcall';

function OpenService(hSCManager :HANDLE;lpServiceName: string; dwDesiredAccess :cardinal): HANDLE;
external 'OpenService{#AW}@advapi32.dll stdcall';

function CloseServiceHandle(hSCObject :HANDLE): boolean;
external '[email protected] stdcall';

function CreateService(hSCManager :HANDLE;lpServiceName, lpDisplayName: string;dwDesiredAccess,dwServiceType,dwStartType,dwErrorControl: cardinal;lpBinaryPathName,lpLoadOrderGroup: String; lpdwTagId : cardinal;lpDependencies,lpServiceStartName,lpPassword :string): cardinal;
external 'CreateService{#AW}@advapi32.dll stdcall';

function DeleteService(hService :HANDLE): boolean;
external '[email protected] stdcall';

function StartNTService(hService :HANDLE;dwNumServiceArgs : cardinal;lpServiceArgVectors : cardinal) : boolean;
external 'StartService{#AW}@advapi32.dll stdcall';

function ControlService(hService :HANDLE; dwControl :cardinal;var ServiceStatus :SERVICE_STATUS) : boolean;
external '[email protected] stdcall';

function QueryServiceStatus(hService :HANDLE;var ServiceStatus :SERVICE_STATUS) : boolean;
external '[email protected] stdcall';

function QueryServiceStatusEx(hService :HANDLE;ServiceStatus :SERVICE_STATUS) : boolean;
external '[email protected] stdcall';

function GetLastError() : cardinal;
external '[email protected] stdcall';

function EnumDependentServices(
  hService :HANDLE; 
  ServiceStatus : LongInt; 
  lpServices: DWORD; 
  cbBufSize: DWORD; 
  var pcbBytesNeeded: DWORD; 
  var lpServicesReturned : DWORD) : boolean;
external 'EnumDependentServices{#AW}@advapi32.dll stdcall';

function HasServiceDependencies(const ServiceName: string) : boolean;
var  
  hSCM: HANDLE;
  hService: HANDLE;
  pcbBytesNeeded : DWORD;
  lpServicesReturned : DWORD;
begin
    hSCM := OpenSCManager('', '', SC_MANAGER_ALL_ACCESS);
    Log(Format('%d', [hSCM]));
    if hSCM <> 0 then begin
        hService := OpenService(hSCM, ServiceName, SERVICE_QUERY_STATUS);
        Log(Format('%d', [hService]));
        if hService <> 0 then begin

            EnumDependentServices( hService, SERVICE_CURRENT_STATUS, 0, 0, pcbBytesNeeded, lpServicesReturned);
            
            MsgBox(SysErrorMessage(DLLGetLastError()), mbError, mb_Ok);

            CloseServiceHandle(hService)
            end;
        CloseServiceHandle(hSCM)
    end;
    Result := false;
end;

function InitializeSetup(): Boolean;
begin
  Log('InitializeSetup called');
  Result := HasServiceDependencies('Dnscache');
  if Result = False then
    MsgBox('InitializeSetup:' #13#13 'Ok, bye bye.', mbInformation, MB_OK);
end;

我尝试将状态和查询代码修改为其他代码,但这也没有帮助。

.net delphi dll inno-setup pascal
1个回答
0
投票

根据

EnumDependentServices()
文档:

[in] hService

服务句柄。该句柄由

OpenService
CreateService
函数返回,它必须具有
SERVICE_ENUMERATE_DEPENDENTS
访问权限
。有关更多信息,请参阅服务安全和访问权限

...

以下错误代码可能由服务控制管理器设置。其他错误代码可能由服务控制管理器调用的注册表函数设置。

返回代码 说明
ERROR_ACCESS_DENIED 句柄没有SERVICE_ENUMERATE_DEPENDENTS访问权限。

当你打开你的

hService
手柄时,你没有指定
SERVICE_ENUMERATE_DEPENDENTS
的权利,只有
SERVICE_QUERY_STATUS
的权利(仅由
QueryServiceStatus/Ex()
NotifyServiceStatusChange()
使用,而不是由
EnumDependentServices()
使用)。

此外,

SC_MANAGER_ALL_ACCESS
要求的权利太多了。不要要求比您实际需要更多的权利。在这种情况下,你只需要
SC_MANAGER_CONNECT
.

此外,

SERVICE_CURRENT_STATUS
不是 Win32 API 定义的有效符号。您将其声明为
$0003
,与
SERVICE_STATE_ALL
的值相同,这是
EnumDependentServices()
定义的实际符号。

试试这个:

const
  ...
  SERVICE_STATE_ALL = $0003;
  SERVICE_ENUMERATE_DEPENDENTS = $0008;
  ERROR_MORE_DATA = 234;
  ...

procedure LogError(const FuncName: string);
var
  ErrCode : DWORD;
  ErrMsg : string; 
begin
  ErrCode := GetLastError();
  ErrMsg := Format('%s failed: (%d) %s', [FuncName, ErrCode, SysErrorMessage(ErrCode)]);
  Log(ErrMsg);
  MsgBox(ErrMsg, mbError, mb_Ok);
end;

function HasServiceDependencies(const ServiceName: string) : boolean;
var  
  hSCM: HANDLE;
  hService: HANDLE;
  dwBytesNeeded : DWORD;
  dwServicesReturned : DWORD;
begin
  Result := False;
  hSCM := OpenSCManager('', '', SC_MANAGER_CONNECT);
  if hSCM = 0 then begin
    LogError('OpenSCManager');
  end
  else begin
    hService := OpenService(hSCM, ServiceName, SERVICE_ENUMERATE_DEPENDENTS);
    if hService = 0 then begin
      LogError('OpenService');
    end
    else begin
      // specifying a nil buffer, so will return True if there are no dependencies,
      // otherwise will return False and set LastError=ERROR_MORE_DATA if
      // dependency data is available...
      if EnumDependentServices(hService, SERVICE_STATE_ALL, 0, 0, dwBytesNeeded, dwServicesReturned) then begin
        Log(Format('%s has no dependencies', [ServiceName]));
      end
      else if GetLastError() <> ERROR_MORE_DATA then begin
        LogError('EnumDependentServices');
      end
      else begin
        Log(Format('%s has dependencies', [ServiceName]));
      end;
      CloseServiceHandle(hService);
    end;
    CloseServiceHandle(hSCM);
  end;
end;
© www.soinside.com 2019 - 2024. All rights reserved.