windows-nt/Source/XPSP1/NT/printscan/wia/setup/clsinst/service.cpp
2020-09-26 16:20:57 +08:00

765 lines
19 KiB
C++

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
service.cpp
Abstract:
This file provides access to the service control
manager for starting, stopping, adding, and removing
services.
Environment:
WIN32 User Mode
Author:
Vlad Sadovsky (vlads) 17-Apr-1998
--*/
//
// Precompiled header
//
#include "precomp.h"
#pragma hdrstop
//
// Include
//
#include "sti_ci.h"
#include "device.h"
#include <regstr.h>
#include <sti.h>
#include <stiregi.h>
#include <stilib.h>
#include <stidebug.h>
#include <stiapi.h>
#include <stisvc.h>
#include <eventlog.h>
//
// Extern
//
extern HINSTANCE g_hDllInstance;
//
// Prototype
//
DWORD
SetServiceSecurity(
LPTSTR AccountName
);
DLLEXPORT
VOID
CALLBACK
InstallWiaService(
HWND hwnd,
HINSTANCE hinst,
LPTSTR lpszCmdLine,
int nCmdShow
);
//
// Function
//
DWORD
WINAPI
StiServiceInstall(
BOOL UseLocalSystem,
BOOL DemandStart,
LPTSTR lpszUserName,
LPTSTR lpszUserPassword
)
/*++
Routine Description:
Service installation function.
Calls SCM to install STI service, which is running in user security context
Arguments:
Return Value:
None.
--*/
{
DWORD dwError = NOERROR;
SC_HANDLE hSCM = NULL;
SC_HANDLE hService = NULL;
SERVICE_DESCRIPTION ServiceDescroption;
TCHAR szServiceDesc[MAX_PATH];
TCHAR szServiceName[MAX_PATH];
__try {
hSCM = ::OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if (!hSCM) {
dwError = GetLastError();
__leave;
}
//
// If service already exists change startup type, else CreateService.
// NOTE: The service should already be installed - if it isn't, we're
// patching it here because it MUST be installed in order to use WIA.
//
hService = OpenService(
hSCM,
STI_SERVICE_NAME,
SERVICE_ALL_ACCESS
);
if (hService) {
//
// Change the service config parameters. Note: we're only changing StartType
//
if (!ChangeServiceConfig(hService, // handle to WIA service
SERVICE_NO_CHANGE, // Don't change ServiceType
DemandStart ? SERVICE_DEMAND_START : SERVICE_AUTO_START, // Change StartType
SERVICE_NO_CHANGE, // Don't change ErrorControl
NULL, // Don't change BinaryPathName
NULL, // Don't change LoadOrderGroup
NULL, // Don't change TagId
NULL, // Don't change Dependencies
NULL, // Don't change ServiceStartName
NULL, // Don't change Password
NULL)) { // Don't change DisplayName
dwError = GetLastError();
DebugTrace(TRACE_ERROR,(("StiServiceInstall: ChangeServiceConfig() failed. Err=0x%x.\r\n"), dwError));
__leave;
} // if (!ChangeServiceConfig(...))
} else {
//
// If use local system - set security
//
if (!UseLocalSystem) {
#ifdef LATER
dwError = SetServiceSecurity( lpszUserName );
if (dwError) {
dwError = ERROR_SERVICE_LOGON_FAILED ;
__leave;
}
#endif
}
//
// Load service name.
//
if(0 == LoadString(g_hDllInstance, WiaServiceName, szServiceName, MAX_PATH)){
dwError = GetLastError();
__leave;
} // if(0 != LoadString(g_hDllInstance, WiaServiceName, szServiceName, MAX_PATH))
hService = CreateService(
hSCM,
STI_SERVICE_NAME,
szServiceName,
SERVICE_ALL_ACCESS,
STI_SVC_SERVICE_TYPE,
DemandStart ? SERVICE_DEMAND_START : SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL,
STI_IMAGE_NAME_SVCHOST,
NULL,
NULL,
STI_SVC_DEPENDENCIES, //STI_SERVICE_DEPENDENCY,
UseLocalSystem ? NULL : lpszUserName,
UseLocalSystem ? NULL : lpszUserPassword
);
if (!hService) {
dwError = GetLastError();
DebugTrace(TRACE_ERROR,(("StiServiceInstall: CreateService() failed. Err=0x%x.\r\n"), dwError));
__leave;
}
//
// Load service description.
//
if(0 != LoadString(g_hDllInstance, WiaServiceDescription, szServiceDesc, MAX_PATH)){
//
// Change service description.
//
ServiceDescroption.lpDescription = (LPTSTR)szServiceDesc;
ChangeServiceConfig2(hService,
SERVICE_CONFIG_DESCRIPTION,
(LPVOID)&ServiceDescroption);
} // if(0 != LoadString(g_hDllInstance, WiaServiceDescription, szServiceDesc, MAX_PATH))
}
//
// Add registry settings for event logging
//
RegisterStiEventSources();
//
// Start service if AUTO_START.
//
if(FALSE == DemandStart){
if(!StartService(hService,0,(LPCTSTR *)NULL)){
dwError = GetLastError();
} // if(!StartService(hService,0,(LPCTSTR *)NULL))
} // if(FALSE == DemandStart)
}
__finally {
//
// Close service handle.
//
if (NULL != hService) {
CloseServiceHandle(hService);
} // if(NULL != hService)
if(NULL != hSCM){
CloseServiceHandle( hSCM );
} // if(NULL != hSCM)
}
return dwError;
} //StiServiceInstall
DWORD
WINAPI
StiServiceRemove(
VOID
)
/*++
Routine Description:
Service removal function. This function calls SCM to remove the STI service.
Arguments:
None.
Return Value:
Return code. Return zero for success
--*/
{
DWORD dwError = NOERROR;
SC_HANDLE hSCM = NULL;
SC_HANDLE hService = NULL;
SERVICE_STATUS ServiceStatus;
UINT uiRetry = 10;
HKEY hkRun;
__try {
hSCM = ::OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if (!hSCM) {
dwError = GetLastError();
DebugTrace(TRACE_ERROR,(("StiServiceRemove: OpenSCManager() failed. Err=0x%x.\r\n"), dwError));
__leave;
}
hService = OpenService(
hSCM,
STI_SERVICE_NAME,
SERVICE_ALL_ACCESS
);
if (!hService) {
dwError = GetLastError();
DebugTrace(TRACE_ERROR,(("StiServiceRemove: OpenService() failed. Err=0x%x.\r\n"), dwError));
__leave;
}
//
// Stop service first
//
if (ControlService( hService, SERVICE_CONTROL_STOP, &ServiceStatus )) {
//
// Wait a little
//
Sleep( STI_STOP_FOR_REMOVE_TIMEOUT );
ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
while( QueryServiceStatus( hService, &ServiceStatus ) &&
(SERVICE_STOP_PENDING == ServiceStatus.dwCurrentState)) {
Sleep( STI_STOP_FOR_REMOVE_TIMEOUT );
if (!uiRetry--) {
break;
}
}
if (ServiceStatus.dwCurrentState != SERVICE_STOPPED) {
dwError = GetLastError();
DebugTrace(TRACE_ERROR,(("StiServiceRemove: Unable to stop service. Err=0x%x.\r\n"), dwError));
if(ServiceStatus.dwCurrentState != ERROR_SERVICE_NOT_ACTIVE) {
__leave;
} // if(ServiceStatus.dwCurrentState != ERROR_SERVICE_NOT_ACTIVE)
} // if (ServiceStatus.dwCurrentState != SERVICE_STOPPED)
} else { // if (ControlService( hService, SERVICE_CONTROL_STOP, &ServiceStatus ))
dwError = GetLastError();
DebugTrace(TRACE_ERROR,(("StiServiceRemove: ControlService() failed. Err=0x%x.\r\n"), dwError));
//
// If service hasn't been started yet, just ignore.
//
if(ERROR_SERVICE_NOT_ACTIVE != dwError){
__leave;
}
}
if (!DeleteService( hService )) {
dwError = GetLastError();
DebugTrace(TRACE_ERROR,(("StiServiceRemove: DeleteService() failed. Err=0x%x.\r\n"), dwError));
__leave;
} else {
dwError = NOERROR;
}
}
__finally {
if(NULL != hService){
CloseServiceHandle( hService );
}
if(NULL != hSCM){
CloseServiceHandle( hSCM );
}
} // __finally
//
// Leftovers from Win9x - remove STI monitor from Run section
//
if (RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_RUN, &hkRun) == NO_ERROR) {
RegDeleteValue (hkRun, REGSTR_VAL_MONITOR);
RegCloseKey(hkRun);
}
return dwError;
} // StiServiceRemove
BOOL
SetServiceDependency(
LPTSTR ServiceName,
LPTSTR DependentServiceName
)
{
BOOL rVal = FALSE;
SC_HANDLE hSvcMgr = NULL;
SC_HANDLE hService = NULL;
hSvcMgr = OpenSCManager(
NULL,
NULL,
SC_MANAGER_ALL_ACCESS
);
if (!hSvcMgr) {
goto exit;
}
hService = OpenService(
hSvcMgr,
ServiceName,
SERVICE_ALL_ACCESS
);
if (!hService) {
goto exit;
}
if (!ChangeServiceConfig(
hService, // handle to service
SERVICE_NO_CHANGE, // type of service
SERVICE_NO_CHANGE, // when to start service
SERVICE_NO_CHANGE, // severity if service fails to start
NULL, // pointer to service binary file name
NULL, // pointer to load ordering group name
NULL, // pointer to variable to get tag identifier
DependentServiceName, // pointer to array of dependency names
NULL, // pointer to account name of service
NULL, // pointer to password for service account
NULL // pointer to display name
)) {
goto exit;
}
rVal = TRUE;
exit:
if(NULL != hService){
CloseServiceHandle( hService );
}
if(NULL != hSvcMgr){
CloseServiceHandle( hSvcMgr );
}
return rVal;
}
BOOL
SetServiceStart(
LPTSTR ServiceName,
DWORD StartType
)
{
BOOL rVal = FALSE;
SC_HANDLE hSvcMgr = NULL;
SC_HANDLE hService = NULL;
hSvcMgr = OpenSCManager(
NULL,
NULL,
SC_MANAGER_ALL_ACCESS
);
if (!hSvcMgr) {
goto exit;
}
hService = OpenService(
hSvcMgr,
ServiceName,
SERVICE_ALL_ACCESS
);
if (!hService) {
goto exit;
}
if (!ChangeServiceConfig(
hService, // handle to service
SERVICE_NO_CHANGE, // type of service
StartType, // when to start service
SERVICE_NO_CHANGE, // severity if service fails to start
NULL, // pointer to service binary file name
NULL, // pointer to load ordering group name
NULL, // pointer to variable to get tag identifier
NULL, // pointer to array of dependency names
NULL, // pointer to account name of service
NULL, // pointer to password for service account
NULL // pointer to display name
))
{
goto exit;
}
rVal = TRUE;
exit:
if(NULL != hService){
CloseServiceHandle( hService );
}
if(NULL != hSvcMgr){
CloseServiceHandle( hSvcMgr );
}
return rVal;
}
BOOL
StartWiaService(
VOID
)
{
BOOL rVal = FALSE;
SC_HANDLE hSvcMgr = NULL;
SC_HANDLE hService = NULL;
SERVICE_STATUS ServiceStatus;
UINT uiRetry = 40; // start time is much larger than stop time.
// Setting 40 sec just to be safe.
DebugTrace(TRACE_PROC_ENTER,(("StartWiaService: Enter... \r\n")));
//
// Open Service Control Manager.
//
hSvcMgr = OpenSCManager(
NULL,
NULL,
SC_MANAGER_ALL_ACCESS
);
if (!hSvcMgr) {
DebugTrace(TRACE_ERROR,(("StartWiaService: ERROR!! OpenSCManager failed. Err=0x%x\n"), GetLastError()));
goto exit;
}
//
// Open WIA service.
//
hService = OpenService(
hSvcMgr,
STI_SERVICE_NAME,
SERVICE_ALL_ACCESS
);
if (!hService) {
DebugTrace(TRACE_ERROR,(("StartWiaService: ERROR!! OpenService failed, re-creating Service Entry (Err=0x%x)\n"), GetLastError()));
//
// Attempt to re-install service
//
InstallWiaService(NULL,
NULL,
NULL,
0);
Sleep(3000);
//
// Try to open it again
//
hService = OpenService(
hSvcMgr,
STI_SERVICE_NAME,
SERVICE_ALL_ACCESS
);
if (!hService) {
DebugTrace(TRACE_ERROR,(("StartWiaService: ERROR!! OpenService failed for the second time. Err=0x%x\n"), GetLastError()));
goto exit;
}
}
rVal = StartService(hService,
0,
(LPCTSTR *)NULL);
if(!rVal){
DebugTrace(TRACE_STATUS,(("StartWiaService: ERROR!! StartService failed. Err=0x%x\n"), GetLastError()));
goto exit;
}
//
// Wait for WIA service to really start.
//
Sleep( STI_STOP_FOR_REMOVE_TIMEOUT );
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
while( QueryServiceStatus( hService, &ServiceStatus ) &&
(SERVICE_START_PENDING == ServiceStatus.dwCurrentState)) {
Sleep( STI_STOP_FOR_REMOVE_TIMEOUT );
if (!uiRetry--) {
break;
}
}
if (ServiceStatus.dwCurrentState != SERVICE_RUNNING) {
DebugTrace(TRACE_ERROR,(("StartWiaService: ERROR!! Hit timeout to start service. Err=0x%x\n"), GetLastError()));
}
exit:
if(NULL != hService){
CloseServiceHandle( hService );
}
if(NULL != hSvcMgr){
CloseServiceHandle( hSvcMgr );
}
DebugTrace(TRACE_PROC_LEAVE,(("StartWiaService: Leaving... Ret=0x%x\n"), rVal));
return rVal;
}
BOOL
StopWiaService(
VOID
)
{
BOOL rVal = FALSE;
SC_HANDLE hSvcMgr = NULL;
SC_HANDLE hService = NULL;
SERVICE_STATUS ServiceStatus;
UINT uiRetry = 10;
DebugTrace(TRACE_PROC_ENTER,(("StopWiaService: Enter... \r\n")));
//
// Open Service Control Manager.
//
hSvcMgr = OpenSCManager(
NULL,
NULL,
SC_MANAGER_ALL_ACCESS
);
if (!hSvcMgr) {
DebugTrace(TRACE_ERROR,(("StopWiaService: ERROR!! OpenSCManager failed. Err=0x%x\n"), GetLastError()));
goto exit;
}
//
// Open WIA service.
//
hService = OpenService(
hSvcMgr,
STI_SERVICE_NAME,
SERVICE_ALL_ACCESS
);
if (!hService) {
DebugTrace(TRACE_ERROR,(("StopWiaService: ERROR!! OpenService failed. Err=0x%x\n"), GetLastError()));
goto exit;
}
//
// Stop WIA service.
//
rVal = ControlService(hService,
SERVICE_CONTROL_STOP,
&ServiceStatus);
if(!rVal){
DebugTrace(TRACE_ERROR,(("StopWiaService: ERROR!! ControlService failed. Err=0x%x\n"), GetLastError()));
} else {
//
// Wait for WIA service really stops.
//
Sleep( STI_STOP_FOR_REMOVE_TIMEOUT );
ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
while( QueryServiceStatus( hService, &ServiceStatus ) &&
(SERVICE_STOP_PENDING == ServiceStatus.dwCurrentState)) {
Sleep( STI_STOP_FOR_REMOVE_TIMEOUT );
if (!uiRetry--) {
break;
}
}
if (ServiceStatus.dwCurrentState != SERVICE_STOPPED) {
DebugTrace(TRACE_ERROR,(("StopWiaService: ERROR!! Hit timeout to stop service. Err=0x%x\n"), GetLastError()));
}
}
exit:
if(NULL != hService){
CloseServiceHandle( hService );
}
if(NULL != hSvcMgr){
CloseServiceHandle( hSvcMgr );
}
DebugTrace(TRACE_PROC_LEAVE,(("StopWiaService: Leaving... Ret=0x%x\n"), rVal));
return rVal;
}
/*
BOOL
SetServiceAccount(
LPTSTR ServiceName,
PSECURITY_INFO SecurityInfo
)
{
BOOL rVal = FALSE;
SC_HANDLE hSvcMgr;
SC_HANDLE hService;
hSvcMgr = OpenSCManager(
NULL,
NULL,
SC_MANAGER_ALL_ACCESS
);
if (!hSvcMgr) {
goto exit;
}
hService = OpenService(
hSvcMgr,
ServiceName,
SERVICE_ALL_ACCESS
);
if (!hService) {
goto exit;
}
if (!ChangeServiceConfig(
hService, // handle to service
SERVICE_NO_CHANGE, // type of service
SERVICE_NO_CHANGE, // when to start service
SERVICE_NO_CHANGE, // severity if service fails to start
NULL, // pointer to service binary file name
NULL, // pointer to load ordering group name
NULL, // pointer to variable to get tag identifier
NULL, // pointer to array of dependency names
SecurityInfo->AccountName, // pointer to account name of service
SecurityInfo->Password, // pointer to password for service account
NULL // pointer to display name
)) {
goto exit;
}
rVal = TRUE;
exit:
CloseServiceHandle( hService );
CloseServiceHandle( hSvcMgr );
return rVal;
}
*/