/*++ 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 #include #include #include #include #include #include #include // // 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_DISABLED : 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_DISABLED : 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; BOOL bRetult = FALSE; SC_HANDLE hSvcMgr = NULL; SC_HANDLE hService = NULL; LPQUERY_SERVICE_CONFIG pServiceConfig = NULL; DWORD dwSize; hSvcMgr = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); if (!hSvcMgr) { goto exit; } hService = OpenService( hSvcMgr, ServiceName, SERVICE_ALL_ACCESS ); if (!hService) { goto exit; } // // Query service config to get current state. // dwSize = 0; bRetult = QueryServiceConfig(hService, NULL, dwSize, &dwSize); if(0 == dwSize){ goto exit; } // // Allocate required memory. // pServiceConfig = (LPQUERY_SERVICE_CONFIG)new BYTE[dwSize]; if(NULL == pServiceConfig){ goto exit; } // if(NULL == pServiceConfig) if(!QueryServiceConfig(hService, pServiceConfig, dwSize, &dwSize)){ goto exit; } // if(!QueryServiceConig(hService, pServiceConfig, dwSize, &dwSize)) if(SERVICE_DISABLED == pServiceConfig->dwStartType){ // // Service is disabled, we can't change the state here. // goto exit; } else if(StartType == pServiceConfig->dwStartType){ // // We're already in the specified state. // rVal = TRUE; 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 != pServiceConfig){ delete[] pServiceConfig; pServiceConfig = NULL; } // if(NULL != pServiceConfig) 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; } */