#include "stdafx.h" #include #include #include #include "w3svc.h" #include #include #include "kill.h" #include "svc.h" TCHAR gServicesWhichMustBeRestarted[20][PROCESS_SIZE]; int gServicesWhichMustBeRestarted_nextuse = 0; int gServicesWhichMustBeRestarted_total = 0; extern int g_GlobalDebugLevelFlag; int ServicesRestartList_EntryExists(LPCTSTR szServiceName) { int iFoundMatch = FALSE; // loop thru the whole list for(int i=0; i < gServicesWhichMustBeRestarted_total;i++) { if (_tcsicmp(gServicesWhichMustBeRestarted[i], szServiceName) == 0) { iFoundMatch = TRUE; break; } } return iFoundMatch; } int ServicesRestartList_Add(LPCTSTR szServiceName) { // check if this value already exists in the globalarary if (ServicesRestartList_EntryExists(szServiceName)) {return FALSE;} // move info into global array if (gServicesWhichMustBeRestarted_nextuse <= 20) { _tcscpy(gServicesWhichMustBeRestarted[gServicesWhichMustBeRestarted_nextuse],szServiceName); // increment counter to array // increment next use space ++gServicesWhichMustBeRestarted_total; ++gServicesWhichMustBeRestarted_nextuse; } return TRUE; } int ServicesRestartList_RestartServices(void) { int iReturn = FALSE; INT err = 0; // loop thru the whole list and restart the services in reverse // order from how they were entered? if (gServicesWhichMustBeRestarted_total >= 1) { iisDebugOut((LOG_TYPE_TRACE, _T("RestartServices()Start.\n"))); for(int i=0; i < gServicesWhichMustBeRestarted_total;i++) { if (CheckifServiceExist(gServicesWhichMustBeRestarted[i]) == 0 ) { err = InetStartService(gServicesWhichMustBeRestarted[i]); } else { iisDebugOut((LOG_TYPE_TRACE, _T("RestartServices():%s:Not restarting since it no longer exist.\n"),gServicesWhichMustBeRestarted[i])); } } iisDebugOut_End(_T("RestartServices")); } return iReturn; } DWORD InetStopExtraWait(LPCTSTR lpServiceName) { DWORD dwSvcMaxSleep = 180000; int iFileExist = FALSE; // Wait. How long should we really wait for this service to actually stop? // the iisadmin Service can take a long time if the metabase.bin file is huge. // So... if it's the iisadmin service we're trying to stop, then // check to see how big the metabase.bin file is, then for each 1meg give it 3 minutes (180000) if (_tcsicmp(lpServiceName,_T("IISADMIN")) == 0) { // look for the metabase.bin file TCHAR szTempDir[_MAX_PATH]; _tcscpy(szTempDir, g_pTheApp->m_csPathInetsrv); AddPath(szTempDir, _T("Metabase.bin")); if (IsFileExist(szTempDir)) { iFileExist = TRUE; } else { _tcscpy(szTempDir, g_pTheApp->m_csPathInetsrv); AddPath(szTempDir, _T("Metabase.xml")); if (IsFileExist(szTempDir)) { iFileExist = TRUE; } } if (TRUE == iFileExist) { // Check to see how big it is. DWORD dwFileSize = ReturnFileSize(szTempDir); if (dwFileSize != 0xFFFFFFFF) { int iTime = 1; // We were able to get the file size. // for each meg for size, give it 3 minutes to save. if (dwFileSize > 1000000) { iTime = (dwFileSize/1000000); dwSvcMaxSleep = iTime * 180000; iisDebugOut((LOG_TYPE_TRACE, _T("InetStopExtraWait():Metabase.bin is kind of big (>1meg), Lets wait longer for IISADMIN service to stop.maxmilsec=0x%x.\n"),dwSvcMaxSleep)); } } } } return dwSvcMaxSleep; } // function: IsServiceDisabled // // Check to see if the service being sent in is disabled BOOL IsServiceDisabled(LPTSTR szServiceName) { SC_HANDLE hService; SC_HANDLE hSCManager; BOOL bRet = FALSE; BUFFER buffConfig; DWORD dwSizeRequired; hSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT | GENERIC_READ ); if ( hSCManager == NULL ) { return FALSE; } hService = OpenService( hSCManager, szServiceName, SERVICE_QUERY_CONFIG ); if ( hService == NULL ) { CloseServiceHandle( hSCManager ); return FALSE; } if ( !QueryServiceConfig( hService, NULL, 0, &dwSizeRequired ) && ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) && buffConfig.Resize( dwSizeRequired ) && QueryServiceConfig( hService, (LPQUERY_SERVICE_CONFIG) buffConfig.QueryPtr(), buffConfig.QuerySize(), &dwSizeRequired ) ) { // Check the service Startup Type bRet = ((LPQUERY_SERVICE_CONFIG) buffConfig.QueryPtr())->dwStartType == SERVICE_DISABLED; } CloseServiceHandle( hSCManager ); CloseServiceHandle( hService ); return bRet; } // function: SetServiceStart // // Change the service state void SetServiceStart(LPTSTR szServiceName, DWORD dwServiceStart) { SC_HANDLE hService; SC_HANDLE hSCManager; hSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT | GENERIC_READ ); if ( hSCManager == NULL ) { return; } hService = OpenService( hSCManager, szServiceName, SERVICE_CHANGE_CONFIG ); if ( hService == NULL ) { CloseServiceHandle( hSCManager ); return; } ChangeServiceConfig( hService, SERVICE_NO_CHANGE, // ServiceType dwServiceStart, // Startup SERVICE_NO_CHANGE, // Error Control NULL, // Binary Path NULL, // Load order group NULL, // TagId NULL, // Dependencies NULL, // Service Start Name NULL, // Password NULL ); // StartName CloseServiceHandle( hSCManager ); CloseServiceHandle( hService ); } INT InetDisableService( LPCTSTR lpServiceName ) { INT err = 0; const DWORD dwSvcSleepInterval = 500 ; DWORD dwSvcMaxSleep = 180000 ; DWORD dwSleepTotal; SC_HANDLE hScManager = NULL; SC_HANDLE hService = NULL; // Calculcate if this is a "special" service which we // need to give more time to in order to stop. dwSvcMaxSleep = InetStopExtraWait(lpServiceName); do { if ((hScManager = OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL ) { err = GetLastError(); break; } // if the service is running, stop it SERVICE_STATUS svcStatus; if ( QueryServiceStatus( hService, &svcStatus )) { if (( svcStatus.dwCurrentState == SERVICE_RUNNING )) { if ( !ControlService( hService, SERVICE_CONTROL_STOP, &svcStatus )) { err = GetLastError(); break; } for ( dwSleepTotal = 0 ; dwSleepTotal < dwSvcMaxSleep && (QueryServiceStatus( hService, & svcStatus )) && svcStatus.dwCurrentState == SERVICE_STOP_PENDING ; dwSleepTotal += dwSvcSleepInterval ) { ::Sleep( dwSvcSleepInterval ) ; } } } if ( !ChangeServiceConfig( hService, SERVICE_NO_CHANGE, SERVICE_DISABLED, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) ) { err = GetLastError(); } } while ( FALSE ); if (hService){CloseServiceHandle(hService);} if (hScManager){CloseServiceHandle(hScManager);} iisDebugOut((LOG_TYPE_TRACE, _T("InetDisableService():ServiceName=%s. Return=0x%x\n"), lpServiceName, err)); return(err); } INT InetStartService( LPCTSTR lpServiceName ) { iisDebugOut_Start1(_T("InetStartService"),(LPTSTR) lpServiceName); INT err = 0; INT err2 = 0; const DWORD dwSvcSleepInterval = 500 ; DWORD dwSvcMaxSleep = 180000 ; SC_HANDLE hScManager = NULL; SC_HANDLE hService = NULL; // Calculcate if this is a "special" service which we // need to give more time to in order to stop. dwSvcMaxSleep = InetStopExtraWait(lpServiceName); do { // set up the service first if ((hScManager = OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL ) { err = GetLastError(); break; } SERVICE_STATUS svcStatus; if ( !QueryServiceStatus( hService, &svcStatus )) { err = ::GetLastError(); break; } if ( svcStatus.dwCurrentState == SERVICE_RUNNING ) { // We will only get this ERROR_SERVICE_MARKED_FOR_DELETE // message if the service is already running. if ( !::StartService( hService, 0, NULL )) { err2 = ::GetLastError(); if (err2 == ERROR_SERVICE_MARKED_FOR_DELETE) {err = err2;} } break; // service already started and running } if ( !::StartService( hService, 0, NULL )) { err = ::GetLastError(); break; } // Wait for the service to attain "running" status; but // wait no more than 3 minute. DWORD dwSleepTotal; for ( dwSleepTotal = 0 ; dwSleepTotal < dwSvcMaxSleep && (QueryServiceStatus( hService, &svcStatus )) && svcStatus.dwCurrentState == SERVICE_START_PENDING ; dwSleepTotal += dwSvcSleepInterval ) { ::Sleep( dwSvcSleepInterval ) ; } if ( svcStatus.dwCurrentState != SERVICE_RUNNING ) { err = dwSleepTotal > dwSvcMaxSleep ? ERROR_SERVICE_REQUEST_TIMEOUT : svcStatus.dwWin32ExitCode; break; } } while ( FALSE ); if (hService){CloseServiceHandle(hService);} if (hScManager){CloseServiceHandle(hScManager);} if (err){iisDebugOut((LOG_TYPE_WARN, _T("InetStartService():ServiceName=%s unable to start WARNING. Err=0x%x.\n"), lpServiceName, err));} else{iisDebugOut((LOG_TYPE_TRACE, _T("InetStartService():ServiceName=%s success.\n"), lpServiceName));} return(err); } DWORD InetQueryServiceStatus( LPCTSTR lpServiceName ) { iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("InetQueryServiceStatus():ServiceName=%s\n"), (LPTSTR) lpServiceName)); DWORD dwStatus = 0; INT err = 0; SC_HANDLE hScManager = NULL; SC_HANDLE hService = NULL; SERVICE_STATUS svcStatus; do { if ((hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL || !::QueryServiceStatus( hService, &svcStatus ) ) { err = GetLastError(); break; } dwStatus = svcStatus.dwCurrentState; } while (0); if (hService){CloseServiceHandle(hService);} if (hScManager){CloseServiceHandle(hScManager);} iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("InetQueryServiceStatus():ServiceName=%s. Return=0x%x.\n"), lpServiceName, err)); return( dwStatus ); } INT InetStopService( LPCTSTR lpServiceName ) { INT err = 0; const DWORD dwSvcSleepInterval = 500 ; DWORD dwSvcMaxSleep = 180000 ; DWORD dwSleepTotal; SC_HANDLE hScManager = NULL; SC_HANDLE hService = NULL; // Calculcate if this is a "special" service which we // need to give more time to in order to stop. dwSvcMaxSleep = InetStopExtraWait(lpServiceName); do { if ((hScManager = OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL ) { err = GetLastError(); break; } SERVICE_STATUS svcStatus; if ( !QueryServiceStatus( hService, &svcStatus )) { err = ::GetLastError(); break; } if ( svcStatus.dwCurrentState == SERVICE_STOPPED ) break; // service already stopped if (( svcStatus.dwCurrentState == SERVICE_RUNNING )) { if ( !ControlService( hService, SERVICE_CONTROL_STOP, &svcStatus )) { err = GetLastError(); break; } for ( dwSleepTotal = 0 ; dwSleepTotal < dwSvcMaxSleep && (QueryServiceStatus( hService, & svcStatus )) && svcStatus.dwCurrentState == SERVICE_STOP_PENDING ; dwSleepTotal += dwSvcSleepInterval ) { ::Sleep( dwSvcSleepInterval ) ; } } if ( svcStatus.dwCurrentState != SERVICE_STOPPED ) { err = dwSleepTotal > dwSvcMaxSleep ? ERROR_SERVICE_REQUEST_TIMEOUT : svcStatus.dwWin32ExitCode; break; } } while ( FALSE ); if (hService){CloseServiceHandle(hService);} if (hScManager){CloseServiceHandle(hScManager);} iisDebugOut((LOG_TYPE_TRACE, _T("InetStopService():ServiceName=%s. Return=0x%x.\n"), lpServiceName, err)); return(err); } INT InetDeleteService( LPCTSTR lpServiceName ) { INT err = 0; SC_HANDLE hScManager = NULL; SC_HANDLE hService = NULL; /* The DeleteService function marks a service for deletion from the service control manager database. The database entry is not removed until all open handles to the service have been closed by calls to the CloseServiceHandle function, and the service is not running. A running service is stopped by a call to the ControlService function with the SERVICE_CONTROL_STOP control code. If the service cannot be stopped, the database entry is removed when the system is restarted. The service control manager deletes the service by deleting the service key and its subkeys from the registry. */ // To delete service immediately, we need to stop service first StopServiceAndDependencies(lpServiceName, FALSE); do { if ((hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL || !::DeleteService( hService ) ) { err = GetLastError(); break; } } while (0); if (hService){CloseServiceHandle(hService);} if (hScManager){CloseServiceHandle(hScManager);} iisDebugOut((LOG_TYPE_TRACE, _T("InetDeleteService():ServiceName=%s. Return=0x%x.\n"), lpServiceName, err)); return(err); } INT InetCreateDriver(LPCTSTR lpServiceName, LPCTSTR lpDisplayName, LPCTSTR lpBinaryPathName, DWORD dwStartType) { iisDebugOut_Start1(_T("InetCreateDriver"),(LPTSTR) lpServiceName); INT err = 0; SC_HANDLE hScManager = NULL; SC_HANDLE hService = NULL; do { if ( (hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL ) { err = GetLastError(); break; } // // if Driver already exits then just change the parameters // if ( CheckifServiceExist( lpServiceName ) == 0 ) { hService = OpenService( hScManager, lpServiceName, GENERIC_ALL ); if ( hService ) { if ( ChangeServiceConfig( hService, // handle to service SERVICE_KERNEL_DRIVER, // type of service dwStartType, // when to start service SERVICE_ERROR_NORMAL, // severity if service fails to start lpBinaryPathName, // 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 lpDisplayName // pointer to display name ) ){ break; } } } else { hService = ::CreateService( hScManager, lpServiceName, lpDisplayName, GENERIC_ALL, SERVICE_KERNEL_DRIVER, dwStartType, SERVICE_ERROR_NORMAL, lpBinaryPathName, NULL, NULL, NULL, NULL, NULL ); if ( hService ) { break; } } err = GetLastError(); } while ( FALSE ); if (hService){CloseServiceHandle(hService);} if (hScManager){CloseServiceHandle(hScManager);} iisDebugOut((LOG_TYPE_TRACE, _T("InetCreateDriver():Name=%s. Return=0x%x.\n"), lpServiceName, err)); return(err); } INT InetCreateService( LPCTSTR lpServiceName, LPCTSTR lpDisplayName, LPCTSTR lpBinaryPathName, DWORD dwStartType, LPCTSTR lpDependencies) { iisDebugOut_Start1(_T("InetCreateService"),(LPTSTR) lpServiceName); INT err = 0; SC_HANDLE hScManager = NULL; SC_HANDLE hService = NULL; do { if ( (hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL ) { err = GetLastError(); break; } hService = ::CreateService( hScManager, lpServiceName, lpDisplayName, GENERIC_ALL, SERVICE_WIN32_SHARE_PROCESS, dwStartType, SERVICE_ERROR_NORMAL, lpBinaryPathName, NULL, NULL, lpDependencies, _T("LocalSystem"), NULL ); if ( !hService ) { err = GetLastError(); break; } } while ( FALSE ); if (hService){CloseServiceHandle(hService);} if (hScManager){CloseServiceHandle(hScManager);} iisDebugOut((LOG_TYPE_TRACE, _T("InetCreateService():ServiceName=%s. Return=0x%x.\n"), lpServiceName, err)); return(err); } INT InetConfigService( LPCTSTR lpServiceName, LPCTSTR lpDisplayName, LPCTSTR lpBinaryPathName, LPCTSTR lpDependencies) { iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("InetConfigService():ServiceName=%s\n"), (LPTSTR) lpServiceName)); INT err = 0; SC_HANDLE hScManager = NULL; SC_HANDLE hService = NULL; do { if ((hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL ) { err = GetLastError(); iisDebugOut((LOG_TYPE_ERROR, _T("InetConfigService():OpenSCManager or OpenService: Service=%s BinPathName=%s Dependencies=%s Err=0x%x FAILED\n"), lpServiceName, lpBinaryPathName, lpDependencies, err)); break; } if ( !::ChangeServiceConfig(hService, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, lpBinaryPathName, NULL, NULL, lpDependencies, _T("LocalSystem"), NULL, lpDisplayName) ) { err = GetLastError(); iisDebugOut((LOG_TYPE_ERROR, _T("InetConfigService():ChangeServiceConfig: Service=%s BinPathName=%s Dependencies=%s Err=0x%x FAILED\n"), lpServiceName, lpBinaryPathName, lpDependencies, err)); break; } } while ( FALSE ); if (hService) {CloseServiceHandle(hService);} if (hScManager) {CloseServiceHandle(hScManager);} iisDebugOut((LOG_TYPE_TRACE, _T("InetConfigService():ServiceName=%s. Return=0x%x.\n"), lpServiceName, err)); return(err); } INT InetConfigService2( LPCTSTR lpServiceName, LPCTSTR lpDescription) { iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("InetConfigService2():ServiceName=%s\n"), (LPTSTR) lpServiceName)); INT err = 0; SC_HANDLE hScManager = NULL; SC_HANDLE hService = NULL; SERVICE_DESCRIPTION ServiceDescription; do { if ((hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL ) { err = GetLastError(); iisDebugOut((LOG_TYPE_ERROR, _T("InetConfigService2():OpenSCManager or OpenService: Service=%s Err=0x%x FAILED\n"), lpServiceName, err)); break; } if (lpDescription) { if (_tcscmp(lpDescription, _T("")) != 0) { ServiceDescription.lpDescription = (LPTSTR) lpDescription; if (!ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, (LPVOID)&ServiceDescription)) { err = GetLastError(); iisDebugOut((LOG_TYPE_ERROR, _T("InetConfigService2():ChangeServiceConfig2: Service=%s Err=0x%x FAILED\n"), lpServiceName, err)); break; } } } } while ( FALSE ); if (hService) {CloseServiceHandle(hService);} if (hScManager) {CloseServiceHandle(hScManager);} iisDebugOut((LOG_TYPE_TRACE, _T("InetConfigService2():ServiceName=%s. Return=0x%x.\n"), lpServiceName, err)); return(err); } # define SetServiceTypeValues( pSvcTypeValue, dwNS, dwType, dwSize, lpValName, lpVal) \ ( pSvcTypeValue)->dwNameSpace = ( dwNS); \ ( pSvcTypeValue)->dwValueType = ( dwType); \ ( pSvcTypeValue)->dwValueSize = ( dwSize); \ ( pSvcTypeValue)->lpValueName = ( lpValName); \ ( pSvcTypeValue)->lpValue = (PVOID ) ( lpVal); \ # define SetServiceTypeValuesDword( pSvcTypeValue, dwNS, lpValName, lpVal) \ SetServiceTypeValues( (pSvcTypeValue), (dwNS), REG_DWORD, sizeof( DWORD), \ ( lpValName), ( lpVal)) BOOL InetRegisterService( LPCTSTR pszMachine, LPCTSTR pszServiceName, GUID *pGuid, DWORD SapId, DWORD TcpPort, BOOL fAdd ) { iisDebugOut_Start1(_T("InetRegisterService"),(LPTSTR) pszServiceName); int err; WSADATA WsaData; SERVICE_INFO serviceInfo; LPSERVICE_TYPE_INFO_ABS lpServiceTypeInfo ; LPSERVICE_TYPE_VALUE_ABS lpServiceTypeValues ; BYTE serviceTypeInfoBuffer[sizeof(SERVICE_TYPE_INFO) + 1024]; // Buffer large enough for 3 values ( SERVICE_TYPE_VALUE_ABS) DWORD Value1 = 1 ; DWORD SapValue = SapId; DWORD TcpPortValue = TcpPort; DWORD statusFlags; // // Initialize Windows Sockets DLL // err = WSAStartup( 0x0101, & WsaData); if ( err == SOCKET_ERROR) { return ( FALSE); } // // Setup the service information to be passed to SetService() for adding // or deleting this service. Most of the SERVICE_INFO fields are not // required for add or delete operation. The main things of interests are // GUIDs and ServiceSpecificInfo structure. // memset( (PVOID ) & serviceInfo, 0, sizeof( serviceInfo)); //null all fields serviceInfo.lpServiceType = pGuid; serviceInfo.lpMachineName = (LPTSTR)pszMachine; // // The "Blob" will contain the service specific information. // In this case, fill it with a SERVICE_TYPE_INFO_ABS structure // and associated information. // serviceInfo.ServiceSpecificInfo.pBlobData = serviceTypeInfoBuffer; serviceInfo.ServiceSpecificInfo.cbSize = sizeof( serviceTypeInfoBuffer); lpServiceTypeInfo = (LPSERVICE_TYPE_INFO_ABS ) serviceTypeInfoBuffer; // // There are totally 3 values associated with this service if we're doing // both SPX and TCP, there's only one value if TCP. // if ( SapId ) { lpServiceTypeInfo->dwValueCount = 3; } else { lpServiceTypeInfo->dwValueCount = 1; } lpServiceTypeInfo->lpTypeName = (LPTSTR)pszServiceName; lpServiceTypeValues = lpServiceTypeInfo->Values; if ( SapId ) { // // 1st value: tells the SAP that this is a connection oriented service. // SetServiceTypeValuesDword( ( lpServiceTypeValues + 0), NS_SAP, // Name Space SERVICE_TYPE_VALUE_CONN, // ValueName &Value1 // actual value ); // // 2nd Value: tells SAP about object type to be used for broadcasting // the service name. // SetServiceTypeValuesDword( ( lpServiceTypeValues + 1), NS_SAP, SERVICE_TYPE_VALUE_SAPID, &SapValue); // // 3rd value: tells TCPIP name-space provider about TCP/IP port to be used. // SetServiceTypeValuesDword( ( lpServiceTypeValues + 2), NS_DNS, SERVICE_TYPE_VALUE_TCPPORT, &TcpPortValue); } else { SetServiceTypeValuesDword( ( lpServiceTypeValues + 0), NS_DNS, SERVICE_TYPE_VALUE_TCPPORT, &TcpPortValue); } // // Finally, call SetService to actually perform the operation. // err = SetService( NS_DEFAULT, // all default name spaces ( fAdd ) ? SERVICE_ADD_TYPE : SERVICE_DELETE_TYPE, // either ADD or DELETE 0, // dwFlags not used &serviceInfo, // the service info structure NULL, // lpServiceAsyncInfo &statusFlags // additional status information ); // for some unknown reason, the SERVICE_DELETE_TYPE never remove the related registry // I have to manually clean it here. if (!fAdd) { CRegKey regSvcTypes(HKEY_LOCAL_MACHINE, _T("System\\CurrentControlSet\\Control\\ServiceProvider\\ServiceTypes")); if ((HKEY)regSvcTypes) {regSvcTypes.DeleteTree(pszServiceName);} } iisDebugOut((LOG_TYPE_TRACE, _T("InetRegisterService():ServiceName=%s.End.Return=%d.\n"), pszServiceName, err)); return ( err != NO_ERROR); } // InetRegisterService() INT CheckifServiceExistAndDependencies( LPCTSTR lpServiceName ) { INT err = 0; INT iReturn = 0; SC_HANDLE hScManager = NULL; SC_HANDLE hService = NULL; LPQUERY_SERVICE_CONFIG ServiceConfig=NULL; BYTE ConfigBuffer[4096]; LPENUM_SERVICE_STATUS ServiceConfigEnum = (LPENUM_SERVICE_STATUS) &ConfigBuffer; if (( hScManager = OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL ) { // Failed, or more likely the service doesn't exist iReturn = GetLastError(); goto CheckifServiceExistAndDependencies_Exit; } // There was no error and the service exists. // Then let's make sure the actual file exists!!! // The above calls will only return true if the service has been registered, but // the call doesn't actually check if the file exists! // Retrieve the service's config for the BinaryPathName // if it fails then hey, we don't have a correctly installed service // so return error! if(RetrieveServiceConfig(hService, &ServiceConfig) != NO_ERROR) { iReturn = GetLastError(); goto CheckifServiceExistAndDependencies_Exit; } if (!ServiceConfig) { iReturn = GetLastError(); goto CheckifServiceExistAndDependencies_Exit; } if ( (ServiceConfig->dwServiceType & SERVICE_WIN32_OWN_PROCESS) || (ServiceConfig->dwServiceType & SERVICE_WIN32_SHARE_PROCESS)) { if (ServiceConfig->lpBinaryPathName) { if (IsFileExist(ServiceConfig->lpBinaryPathName)) { // the service exists and the file exists too! iReturn = 0; } else { iReturn = ERROR_FILE_NOT_FOUND; goto CheckifServiceExistAndDependencies_Exit; } } } else { iReturn = 0; } // Get our list of services which we depend upon. // let's make sure they are registered and exist. // ServiceConfig->lpDependencies should look something like this // service\0service\0\0 double null terminated { TCHAR * pdest = NULL; long RightMostNull = 0; pdest = ServiceConfig->lpDependencies; do { if (*pdest != _T('\0')) { RightMostNull = RightMostNull + _tcslen(pdest) + 1; // Check if the service exists if (0 != CheckifServiceExistAndDependencies(pdest)){iReturn = err;} pdest = _tcschr(pdest, _T('\0')); pdest++; } else { break; } } while (TRUE); } CheckifServiceExistAndDependencies_Exit: if (ServiceConfig) {free(ServiceConfig);} if (hService) {CloseServiceHandle(hService);} if (hScManager) {CloseServiceHandle(hScManager);} return (iReturn); } INT CheckifServiceExist( LPCTSTR lpServiceName ) { INT err = 0; SC_HANDLE hScManager = NULL; SC_HANDLE hService = NULL; if (( hScManager = OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL ) {err = GetLastError();} if (hService) CloseServiceHandle(hService); if (hScManager) CloseServiceHandle(hScManager); return (err); } /*---------------------------------------------------------------------------------------- Routine Description: This routine allocates a buffer for the specified service's configuration parameters, and retrieves those parameters into the buffer. The caller is responsible for freeing the buffer. Remarks: The pointer whose address is contained in ServiceConfig is guaranteed to be NULL upon return if any error occurred. -----------------------------------------------------------------------------------------*/ DWORD RetrieveServiceConfig(IN SC_HANDLE ServiceHandle,OUT LPQUERY_SERVICE_CONFIG *ServiceConfig) { DWORD ServiceConfigSize = 0, Err; if (NULL == ServiceConfig) { return ERROR_INVALID_PARAMETER; } *ServiceConfig = NULL; while(TRUE) { if(QueryServiceConfig(ServiceHandle, *ServiceConfig, ServiceConfigSize, &ServiceConfigSize)) { //assert(*ServiceConfig); return NO_ERROR; } else { Err = GetLastError(); if(*ServiceConfig) { free(*ServiceConfig); *ServiceConfig=NULL; } if(Err == ERROR_INSUFFICIENT_BUFFER) { // Allocate a larger buffer, and try again. *ServiceConfig = (LPQUERY_SERVICE_CONFIG) malloc(ServiceConfigSize); if( !( *ServiceConfig ) ) { return ERROR_NOT_ENOUGH_MEMORY; } } else { *ServiceConfig = NULL; return Err; } } } // while (TRUE) } INT CreateDependencyForService( LPCTSTR lpServiceName, LPCTSTR lpDependency ) { iisDebugOut_Start1(_T("CreateDependencyForService"),(LPTSTR) lpServiceName); INT err = 0; SC_HANDLE hScManager = NULL; SC_HANDLE hService = NULL; LPQUERY_SERVICE_CONFIG ServiceConfig=NULL; TCHAR szTempDependencies[1024]; TCHAR * pszTempDependencies = NULL; pszTempDependencies = szTempDependencies; do { // set up the service first if ((hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL ) { err = GetLastError(); break; } // Get the existing Service information if(RetrieveServiceConfig(hService, &ServiceConfig) != NO_ERROR) { err = GetLastError(); break; } if(!ServiceConfig) { err = GetLastError(); break; } // Check if our service is already in there. // ServiceConfig->lpDependencies should look something like this // service\0service\0\0 double null terminated TCHAR * pdest = NULL; int bFoundFlag = FALSE; long RightMostNull = 0; pdest = ServiceConfig->lpDependencies; do { if (*pdest != _T('\0')) { RightMostNull = RightMostNull + _tcslen(pdest) + 1; if (_tcsicmp(pdest, lpDependency) == 0) { bFoundFlag = TRUE; break; } // copy the entry onto our string which we'll use later. _tcscpy(pszTempDependencies,pdest); // position pointer to the end pszTempDependencies=pszTempDependencies + RightMostNull; pdest = _tcschr(pdest, _T('\0')); pdest++; } else { break; } } while (TRUE); // if the service is already on the dependency list then exit if (bFoundFlag == TRUE) { break; } // The Service is not there So Let's add it to the end of the list then change the data // The pointer should be at the beginning or at the next entry point _tcscpy(pszTempDependencies, lpDependency); // position pointer to the end pszTempDependencies=pszTempDependencies + (_tcslen(pszTempDependencies) + 1); // add another null to the end *pszTempDependencies = _T('\0'); if(!::ChangeServiceConfig(hService,SERVICE_NO_CHANGE,SERVICE_NO_CHANGE,SERVICE_NO_CHANGE,NULL,NULL,NULL,szTempDependencies,NULL,NULL,NULL)) { err = GetLastError(); break; } } while ( FALSE ); if (ServiceConfig) {free(ServiceConfig);} if (hService) {CloseServiceHandle(hService);} if (hScManager) {CloseServiceHandle(hScManager);} iisDebugOut((LOG_TYPE_TRACE, _T("CreateDependencyForService():ServiceName=%s. Return=0x%x.\n"), lpServiceName, err)); return err; } INT RemoveDependencyForService( LPCTSTR lpServiceName, LPCTSTR lpDependency ) { iisDebugOut_Start1(_T("RemoveDependencyForService"),(LPTSTR) lpServiceName); INT err = 0; SC_HANDLE hScManager = NULL; SC_HANDLE hService = NULL; LPQUERY_SERVICE_CONFIG ServiceConfig=NULL; TCHAR szTempDependencies[1024]; TCHAR * pszTempDependencies = NULL; pszTempDependencies = szTempDependencies; do { // set up the service first if ((hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL ) { err = GetLastError(); break; } // Get the existing Service information if(RetrieveServiceConfig(hService, &ServiceConfig) != NO_ERROR) { err = GetLastError(); break; } if(!ServiceConfig) { err = GetLastError(); break; } // Check if our service is already in there. // ServiceConfig->lpDependencies should look something like this // service\0service\0\0 double null terminated TCHAR * pdest = NULL; int bFoundFlag = FALSE; long RightMostNull = 0; _tcsset(szTempDependencies, _T('\0')); pdest = ServiceConfig->lpDependencies; do { if (*pdest != _T('\0')) { RightMostNull = RightMostNull + _tcslen(pdest) + 1; if (_tcsicmp(pdest, lpDependency) == 0) { bFoundFlag = TRUE; } else { // copy the entry onto our string which we'll use later. _tcscpy(pszTempDependencies,pdest); // position pointer to the end pszTempDependencies=pszTempDependencies + RightMostNull; *pszTempDependencies = _T('\0'); /* if (_tcslen(szTempDependencies) == 0) memcpy(szTempDependencies, pdest, _tcslen(pdest) + 1); else memcpy(szTempDependencies + _tcslen(szTempDependencies) + 1, pdest, _tcslen(pdest) + 1); */ } pdest = _tcschr(pdest, _T('\0')); pdest++; } else { break; } } while (TRUE); // if the service was in the list. // Then let's remove it. if (bFoundFlag == FALSE) { break; } if(!::ChangeServiceConfig(hService,SERVICE_NO_CHANGE,SERVICE_NO_CHANGE,SERVICE_NO_CHANGE,NULL,NULL,NULL,szTempDependencies,NULL,NULL,NULL)) { err = GetLastError(); break; } } while ( FALSE ); if (ServiceConfig) {free(ServiceConfig);} if (hService) {CloseServiceHandle(hService);} if (hScManager) {CloseServiceHandle(hScManager);} iisDebugOut((LOG_TYPE_TRACE, _T("RemoveDependencyForService():ServiceName=%s. Return=0x%x.\n"), lpServiceName, err)); return err; } INT DisplayDependencyForService( LPCTSTR lpServiceName) { INT err = 0; SC_HANDLE hScManager = NULL; SC_HANDLE hService = NULL; LPQUERY_SERVICE_CONFIG ServiceConfig=NULL; do { // set up the service first if ((hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL ) { err = GetLastError(); break; } // Get the existing Service information if(RetrieveServiceConfig(hService, &ServiceConfig) != NO_ERROR) { err = GetLastError(); break; } if(!ServiceConfig) { err = GetLastError(); break; } // Check if our service is already in there. // ServiceConfig->lpDependencies should look something like this // service\0service\0\0 double null terminated TCHAR * pdest = NULL; int bFoundFlag = FALSE; long RightMostNull = 0; pdest = ServiceConfig->lpDependencies; do { if (*pdest != _T('\0')) { pdest = _tcschr(pdest, _T('\0')); pdest++; } else { break; } } while (TRUE); } while ( FALSE ); if (ServiceConfig) {free(ServiceConfig);} if (hService) {CloseServiceHandle(hService);} if (hScManager) {CloseServiceHandle(hScManager);} return err; } // //Routine Description: // Stop the named service and all those services which depend upon it. // And if the service is hung and can't be stopped, then kill the darn thing. // //Arguments: // ServiceName (Name of service to stop) // //Return Status: // TRUE - Indicates service successfully stopped // FALSE - Timeout occurred. // int StopServiceAndDependencies(LPCTSTR ServiceName, int AddToRestartList) { iisDebugOut_Start1(_T("StopServiceAndDependencies"),(LPTSTR) ServiceName); int Err = 0; int iBeforeServiceStatus = 0; SC_HANDLE ScManagerHandle = NULL; SC_HANDLE ServiceHandle = NULL; SERVICE_STATUS ServiceStatus; DWORD Timeout; int iReturn = FALSE; DWORD TimeoutMaxSecs = 60; DWORD dwSvcMaxSleep = 0; // // Open a handle to the Service. // ScManagerHandle = OpenSCManager(NULL,NULL,SC_MANAGER_CONNECT ); if (ScManagerHandle == NULL) { Err = GetLastError(); iisDebugOut((LOG_TYPE_ERROR, _T("StopServiceAndDependencies():OpenSCManager: Err on Service %s Err=0x%x FAILED\n"), ServiceName, Err)); goto Cleanup; } ServiceHandle = OpenService(ScManagerHandle,ServiceName,SERVICE_QUERY_STATUS | SERVICE_INTERROGATE | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_STOP | SERVICE_QUERY_CONFIG ); if ( ServiceHandle == NULL ) { Err = GetLastError(); if (Err == ERROR_SERVICE_DOES_NOT_EXIST) { iReturn = TRUE; iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("StopServiceAndDependencies():%s Service does not exist.\n"), ServiceName)); } else { iisDebugOut((LOG_TYPE_ERROR, _T("StopServiceAndDependencies():OpenService: Err on Service %s Err=0x%x FAILED\n"), ServiceName, Err)); } goto Cleanup; } // Get the before service status. if (QueryServiceStatus(ServiceHandle, &ServiceStatus)) { iBeforeServiceStatus = ServiceStatus.dwCurrentState; } // // Ask the service to stop. // if ( !ControlService( ServiceHandle, SERVICE_CONTROL_STOP, &ServiceStatus) ) { Err = GetLastError(); // If there are dependent services running, // determine their names and stop them. if ( Err == ERROR_DEPENDENT_SERVICES_RUNNING ) { BYTE ConfigBuffer[4096]; LPENUM_SERVICE_STATUS ServiceConfig = (LPENUM_SERVICE_STATUS) &ConfigBuffer; DWORD BytesNeeded; DWORD ServiceCount; DWORD ServiceIndex; // // Get the names of the dependent services. // if ( !EnumDependentServices( ServiceHandle,SERVICE_ACTIVE,ServiceConfig,sizeof(ConfigBuffer),&BytesNeeded,&ServiceCount ) ) { Err = GetLastError(); iisDebugOut((LOG_TYPE_ERROR, _T("StopServiceAndDependencies():EnumDependentServices: Err on Service %s Err=0x%x FAILED\n"), ServiceName, Err)); goto Cleanup; } // // Stop those services. // for ( ServiceIndex=0; ServiceIndexdwServiceType & SERVICE_WIN32_OWN_PROCESS) || (ServiceConfig->dwServiceType & SERVICE_WIN32_SHARE_PROCESS)) { if ( _tcslen(ServiceConfig->lpBinaryPathName) >= MAX_PATH ) { goto KillService_Exit; } // parse out the different parts and take only the filename.ext TCHAR pfilename_only[ MAX_PATH ]; TCHAR pextention_only[ MAX_PATH ]; _tsplitpath( ServiceConfig->lpBinaryPathName, NULL, NULL, pfilename_only, pextention_only); if (pextention_only) {_tcscat(pfilename_only,pextention_only);} if ( _tcsicmp( pfilename_only, _T("lsass") ) == 0 ) { // No matter what service it is, lets not kill lsass.exe goto KillService_Exit; } // Convert it to ansi for our "kill" function char szFile[ MAX_PATH ]; #if defined(UNICODE) || defined(_UNICODE) WideCharToMultiByte( CP_ACP, 0, (WCHAR*)pfilename_only, -1, szFile, MAX_PATH, NULL, NULL ); #else _tcscpy(szFile, pfilename_only); #endif // Some of these services have some action to do if the service is killed. // like IISADMIN has some restart function which will automagically restart the // Service if the process is not properly shutdown. // We need to disable this deal because We can't have this service just startup by itself again. iFlagPutItBack = FALSE; if (_tcsicmp(ServiceConfig->lpServiceStartName,_T("IISADMIN")) == 0) { // Go lookup the registry for "FailureCommands" and save that information. // retrieve from registry CString csFailureCommand; CRegKey regIISADMINParam(HKEY_LOCAL_MACHINE, REG_IISADMIN); if ( (HKEY)regIISADMINParam ) { regIISADMINParam.m_iDisplayWarnings = FALSE; if (ERROR_SUCCESS == regIISADMINParam.QueryValue(_T("FailureCommands"), csFailureCommand)) { // Kool, we got it. // Set it to do nothing. regIISADMINParam.SetValue(_T("FailureCommands"), _T("")); iFlagPutItBack = TRUE; } } // kill the service's process if (KillProcessNameReturn0(szFile) == 0) {iReturn = TRUE;} if (TRUE == iFlagPutItBack) { CRegKey regIISADMINParam(HKEY_LOCAL_MACHINE, REG_IISADMIN); if ( (HKEY)regIISADMINParam ) { regIISADMINParam.SetValue(_T("FailureCommands"), csFailureCommand); } } } else { if (KillProcessNameReturn0(szFile) == 0) {iReturn = TRUE;} } } KillService_Exit: if (ServiceConfig) {free(ServiceConfig);} return iReturn; } INT CheckifServiceMarkedForDeletion( LPCTSTR lpServiceName ) { INT iReturn = FALSE; INT err = 0; SC_HANDLE hScManager = NULL; SC_HANDLE hService = NULL; // set up the service first if ((hScManager = OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL ) { err = GetLastError(); goto CheckifServiceMarkedForDeletion_Exit; } SERVICE_STATUS svcStatus; if ( !QueryServiceStatus( hService, &svcStatus )) { err = ::GetLastError(); goto CheckifServiceMarkedForDeletion_Exit; } if ( svcStatus.dwCurrentState == SERVICE_RUNNING ) { // We will only get this ERROR_SERVICE_MARKED_FOR_DELETE // message if the service is already running. if ( !::StartService( hService, 0, NULL )) { err = ::GetLastError(); if (err == ERROR_SERVICE_MARKED_FOR_DELETE) {iReturn = TRUE;} goto CheckifServiceMarkedForDeletion_Exit; } } CheckifServiceMarkedForDeletion_Exit: if (hService) CloseServiceHandle(hService); if (hScManager) CloseServiceHandle(hScManager); return iReturn; } // // warning: This will leave the lpServiceToValidate in the started mode upon exit! // int ValidateDependentService(LPCTSTR lpServiceToValidate, LPCTSTR lpServiceWhichIsDependent) { iisDebugOut_Start1(_T("ValidateDependentService"),(LPTSTR) lpServiceToValidate); int iReturn = FALSE; INT err = 0; int iFailFlag = FALSE; SC_HANDLE hScManager = NULL; SC_HANDLE hService = NULL; LPQUERY_SERVICE_CONFIG ServiceConfig=NULL; // Let's validate that the lpServiceToValidate is installed fine. // Check if the lpServiceToValidate service EVEN exists err = CheckifServiceExistAndDependencies(lpServiceToValidate); if ( err != 0 ) { MyMessageBox(NULL, IDS_DEPENDENT_UPON_THIS_SVC_ERR, lpServiceWhichIsDependent,lpServiceWhichIsDependent,err, MB_OK | MB_SETFOREGROUND); } else { // Try to start the service err = InetStartService(lpServiceToValidate); if (err == 0 || err == ERROR_SERVICE_ALREADY_RUNNING) { err = NERR_Success; iReturn = TRUE; goto ValidateDependentService_Exit; } // Service returned an error when we tried to start it. // Check if the error = ERROR_SERVICE_DEPENDENCY_FAIL if (err == ERROR_SERVICE_DEPENDENCY_FAIL) { // Loop thru this services dependencies and try to // start them, to find out which one failed to start. iFailFlag = FALSE; if ((hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = ::OpenService( hScManager, lpServiceToValidate, GENERIC_ALL )) == NULL ) {iFailFlag = TRUE;} // Get the existing Service information if (iFailFlag != TRUE) {if(RetrieveServiceConfig(hService, &ServiceConfig) != NO_ERROR) {iFailFlag = TRUE;}} if (iFailFlag != TRUE) {if(!ServiceConfig){iFailFlag = TRUE;}} // Get the dependencies if (iFailFlag != TRUE) { TCHAR * pdest = NULL; long RightMostNull = 0; pdest = ServiceConfig->lpDependencies; do { if (*pdest != _T('\0')) { RightMostNull = RightMostNull + _tcslen(pdest) + 1; // Try to start the service... err = InetStartService(pdest); if (err) { if (err != ERROR_SERVICE_ALREADY_RUNNING) { // The pdest // Service was unable to start because... // MyMessageBox(NULL, IDS_UNABLE_TO_START, pdest, err, MB_OK | MB_SETFOREGROUND); iisDebugOut((LOG_TYPE_ERROR, _T("ValidateDependentService():Unable to start ServiceName=%s.\n"), pdest)); } } pdest = _tcschr(pdest, _T('\0')); pdest++; } else { break; } } while (TRUE); } } else { MyMessageBox(NULL, IDS_UNABLE_TO_START, lpServiceToValidate, err, MB_OK | MB_SETFOREGROUND); } } ValidateDependentService_Exit: if (ServiceConfig) {free(ServiceConfig);} if (hService) {CloseServiceHandle(hService);} if (hScManager) {CloseServiceHandle(hScManager);} iisDebugOut_End1(_T("ValidateDependentService"), lpServiceToValidate, LOG_TYPE_TRACE); return iReturn; } int LogEnumServicesStatus(void) { int iReturn = FALSE; #ifndef _CHICAGO_ BOOL success = 0; SC_HANDLE scm = NULL; LPENUM_SERVICE_STATUS status = NULL; DWORD numServices=0, sizeNeeded=0, resume=0; // Open a connection to the SCM //scm = OpenSCManager(0, 0, GENERIC_ALL); scm = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS); if (!scm) { iisDebugOut((LOG_TYPE_ERROR, _T("CallEnumServicesStatus():OpenSCManager. FAILED. err=0x%x\n"), GetLastError())); goto CallEnumServicesStatus_Exit; } // get the number of bytes to allocate // MAKE SURE resume starts at 0 resume = 0; success = EnumServicesStatus(scm, SERVICE_WIN32 | SERVICE_DRIVER, SERVICE_ACTIVE | SERVICE_INACTIVE, 0, 0, &sizeNeeded, &numServices, &resume); if (GetLastError() != ERROR_MORE_DATA) { iisDebugOut((LOG_TYPE_ERROR, _T("CallEnumServicesStatus():EnumServicesStatus0. FAILED. err=0x%x\n"), GetLastError())); goto CallEnumServicesStatus_Exit; } // Allocate space status = (LPENUM_SERVICE_STATUS) LocalAlloc(LPTR, sizeNeeded); if( status == NULL ) { goto CallEnumServicesStatus_Exit; } // Get the status records. Making an assumption // here that no new services get added during // the allocation (could lock the database to // guarantee that...) resume = 0; success = EnumServicesStatus(scm, SERVICE_WIN32,SERVICE_ACTIVE | SERVICE_INACTIVE,status, sizeNeeded, &sizeNeeded,&numServices, &resume); if (!success) { iisDebugOut((LOG_TYPE_ERROR, _T("CallEnumServicesStatus():EnumServicesStatus. FAILED. err=0x%x\n"), GetLastError())); goto CallEnumServicesStatus_Exit; } DWORD i; for (i=0; i < numServices; i++) { switch(status[i].ServiceStatus.dwCurrentState) { case SERVICE_STOPPED: iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("SERVICE_STOPPED [%s].\n"), status[i].lpServiceName)); break; case SERVICE_START_PENDING: iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("SERVICE_START_PENDING [%s].\n"), status[i].lpServiceName)); break; case SERVICE_STOP_PENDING: iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("SERVICE_STOP_PENDING [%s].\n"), status[i].lpServiceName)); break; case SERVICE_RUNNING: iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("SERVICE_RUNNING [%s].\n"), status[i].lpServiceName)); break; case SERVICE_CONTINUE_PENDING: iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("SERVICE_CONTINUE_PENDING [%s].\n"), status[i].lpServiceName)); break; case SERVICE_PAUSE_PENDING: iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("SERVICE_PAUSE_PENDING [%s].\n"), status[i].lpServiceName)); break; case SERVICE_PAUSED: iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("SERVICE_PAUSED [%s].\n"), status[i].lpServiceName)); break; } } iReturn = TRUE; CallEnumServicesStatus_Exit: if (status){LocalFree(status);} if (scm) {CloseServiceHandle(scm);} #endif return iReturn; } int InetIsThisExeAService(LPCTSTR lpFileNameToCheck, LPTSTR lpReturnServiceName) { int iReturn = FALSE; #ifndef _CHICAGO_ BOOL success = 0; SC_HANDLE scm = NULL; LPENUM_SERVICE_STATUS status = NULL; DWORD numServices=0, sizeNeeded=0, resume=0; _tcscpy(lpReturnServiceName, _T("")); // Open a connection to the SCM //scm = OpenSCManager(0, 0, GENERIC_ALL); scm = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS); if (!scm) { iisDebugOut((LOG_TYPE_ERROR, _T("InetIsThisExeAService():OpenSCManager. FAILED. err=0x%x\n"), GetLastError())); goto InetIsThisExeAService_Exit; } // get the number of bytes to allocate // MAKE SURE resume starts at 0 resume = 0; success = EnumServicesStatus(scm, SERVICE_WIN32 | SERVICE_DRIVER, SERVICE_ACTIVE | SERVICE_INACTIVE, 0, 0, &sizeNeeded, &numServices, &resume); if (GetLastError() != ERROR_MORE_DATA) { iisDebugOut((LOG_TYPE_ERROR, _T("InetIsThisExeAService():EnumServicesStatus0. FAILED. err=0x%x\n"), GetLastError())); goto InetIsThisExeAService_Exit; } // Allocate space status = (LPENUM_SERVICE_STATUS) LocalAlloc(LPTR, sizeNeeded); if( status == NULL ) { goto InetIsThisExeAService_Exit; } // Get the status records. Making an assumption // here that no new services get added during // the allocation (could lock the database to // guarantee that...) resume = 0; success = EnumServicesStatus(scm, SERVICE_WIN32,SERVICE_ACTIVE | SERVICE_INACTIVE,status, sizeNeeded, &sizeNeeded,&numServices, &resume); if (!success) { iisDebugOut((LOG_TYPE_ERROR, _T("InetIsThisExeAService():EnumServicesStatus. FAILED. err=0x%x\n"), GetLastError())); goto InetIsThisExeAService_Exit; } DWORD i; for (i=0; i < numServices; i++) { // Use the status[i].lpServiceName // to query the service and find out it's binary filename if (TRUE == InetIsThisExeAService_Worker(status[i].lpServiceName, lpFileNameToCheck)) { iReturn = TRUE; // copy in the service name into the return string. _tcscpy(lpReturnServiceName, status[i].lpServiceName); goto InetIsThisExeAService_Exit; } } InetIsThisExeAService_Exit: if (status){LocalFree(status);} if (scm) {CloseServiceHandle(scm);} #endif return iReturn; } int InetIsThisExeAService_Worker(LPCTSTR lpServiceName, LPCTSTR lpFileNameToCheck) { int iReturn = FALSE; INT err = 0; SC_HANDLE hScManager = NULL; SC_HANDLE hService = NULL; LPQUERY_SERVICE_CONFIG ServiceConfig=NULL; BYTE ConfigBuffer[4096]; LPENUM_SERVICE_STATUS ServiceConfigEnum = (LPENUM_SERVICE_STATUS) &ConfigBuffer; if (( hScManager = OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL ) { // Failed, or more likely the service doesn't exist //iReturn = GetLastError(); goto InetIsThisExeAService_Worker_Exit; } if(RetrieveServiceConfig(hService, &ServiceConfig) != NO_ERROR) { //iReturn = GetLastError(); goto InetIsThisExeAService_Worker_Exit; } if(!ServiceConfig) { goto InetIsThisExeAService_Worker_Exit; } if ( (ServiceConfig->dwServiceType & SERVICE_WIN32_OWN_PROCESS) || (ServiceConfig->dwServiceType & SERVICE_WIN32_SHARE_PROCESS)) { if (ServiceConfig->lpBinaryPathName) { if (_tcsicmp(lpFileNameToCheck, ServiceConfig->lpBinaryPathName) == 0) { //We found a match!!!!! iReturn = TRUE; } else { // we did not find a match, based on c:\path\filename and c:\path\filename // maybe we try "filename.exe" and "filename.exe"???? TCHAR szBinaryNameOnly[_MAX_FNAME]; TCHAR szFileNameToCheckNameOnly[_MAX_FNAME]; if (TRUE == ReturnFileNameOnly((LPCTSTR) ServiceConfig->lpBinaryPathName, szBinaryNameOnly)) { if (TRUE == ReturnFileNameOnly((LPCTSTR) lpFileNameToCheck, szFileNameToCheckNameOnly)) { if (_tcsicmp(szFileNameToCheckNameOnly, szBinaryNameOnly) == 0) { //We found a match!!!!! iReturn = TRUE; } } } } } } InetIsThisExeAService_Worker_Exit: if (ServiceConfig) {free(ServiceConfig);} if (hService) {CloseServiceHandle(hService);} if (hScManager) {CloseServiceHandle(hScManager);} return iReturn; } int IsThisServiceADriver(LPCTSTR lpServiceName) { int iReturn = FALSE; SC_HANDLE hScManager = NULL; SC_HANDLE hService = NULL; LPQUERY_SERVICE_CONFIG ServiceConfig=NULL; BYTE ConfigBuffer[4096]; LPENUM_SERVICE_STATUS ServiceConfigEnum = (LPENUM_SERVICE_STATUS) &ConfigBuffer; if ((hScManager = OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL ) { // Failed, or more likely the service doesn't exist //iReturn = GetLastError(); goto IsThisServiceADriver_Exit; } if(RetrieveServiceConfig(hService, &ServiceConfig) != NO_ERROR) { //iReturn = GetLastError(); goto IsThisServiceADriver_Exit; } if(!ServiceConfig) { //iReturn = GetLastError(); goto IsThisServiceADriver_Exit; } if ( (ServiceConfig->dwServiceType & SERVICE_KERNEL_DRIVER) || (ServiceConfig->dwServiceType & SERVICE_FILE_SYSTEM_DRIVER)) { iReturn = TRUE; } IsThisServiceADriver_Exit: if (ServiceConfig) {free(ServiceConfig);} if (hService) {CloseServiceHandle(hService);} if (hScManager) {CloseServiceHandle(hScManager);} return iReturn; } int CreateDriver(CString csDriverName, CString csDisplayName, CString csFileName) { DWORD dwReturn = ERROR_SUCCESS; CString csBinPath; CString csFile; iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("CreateDriver:%s:%s start.\n"), csDriverName, csFileName)); csBinPath = _T("\\SystemRoot\\System32\\drivers\\"); csBinPath += csFileName; // Check if the file even exists first. csFile = g_pTheApp->m_csSysDir; csFile += _T("\\Drivers\\"); csFile += csFileName; if (!IsFileExist(csFile)) { dwReturn = ERROR_FILE_NOT_FOUND; goto CreateDriver_Exit; } // // Attempt to create the service, could fail if this is an // Refresh Install will leave the driver from the prior // Install, becuse if we delete in the remove phase it will // get marked for deletion and not get readded now. // this could happen in a upgrade as well.... // dwReturn = InetCreateDriver(csDriverName, (LPCTSTR)csDisplayName, (LPCTSTR)csBinPath, SERVICE_DEMAND_START); if ( dwReturn != ERROR_SUCCESS ) { if (dwReturn == ERROR_SERVICE_EXISTS) { iisDebugOut((LOG_TYPE_TRACE, _T("CreateDriver:%s:Service exists.\n"), csDriverName)); dwReturn = ERROR_SUCCESS; } else { iisDebugOut((LOG_TYPE_ERROR, _T("CreateDriver:%s:failed to create service Err=0x%x.\n"), csDriverName, dwReturn)); MyMessageBox(NULL, IDS_UNABLE_TO_CREATE_DRIVER, csDriverName, dwReturn, MB_OK | MB_SETFOREGROUND); } } else { iisDebugOut((LOG_TYPE_TRACE, _T("CreateDriver:%s:Successfully created.\n"), csDriverName)); } CreateDriver_Exit: return dwReturn; } DWORD CreateDriver_Wrap(CString csDriverName, CString csDisplayName, CString csFileName,BOOL bDisplayMsgOnErrFlag) { int bFinishedFlag = FALSE; UINT iMsg = NULL; DWORD dwReturn = ERROR_SUCCESS; // Create or Config driver spud.sys, NT Server product onloy!!! if (g_pTheApp->m_eOS != OS_W95) { do { dwReturn = CreateDriver(csDriverName, csDisplayName, csFileName); if (dwReturn == ERROR_SUCCESS) { break; } else { if (bDisplayMsgOnErrFlag == TRUE) { iMsg = MyMessageBox( NULL, IDS_RETRY, MB_ABORTRETRYIGNORE | MB_SETFOREGROUND ); switch ( iMsg ) { case IDIGNORE: dwReturn = ERROR_SUCCESS; goto CreateDriver_Wrap_Exit; case IDABORT: dwReturn = ERROR_OPERATION_ABORTED; goto CreateDriver_Wrap_Exit; case IDRETRY: break; default: break; } } else { // return whatever err happened goto CreateDriver_Wrap_Exit; } } } while (dwReturn != ERROR_SUCCESS); } CreateDriver_Wrap_Exit: return dwReturn; } INT InetConfigServiceInteractive(LPCTSTR lpServiceName, int AddInteractive) { iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("InetConfigServiceInteractive(%i):ServiceName=%s\n"),AddInteractive,(LPTSTR) lpServiceName)); INT err = 0; SC_HANDLE hScManager = NULL; SC_HANDLE hService = NULL; LPQUERY_SERVICE_CONFIG ServiceConfig = NULL; DWORD dwNewServiceType = 0; BOOL bDoStuff = FALSE; do { if ((hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL ) { err = GetLastError(); // if error = ERROR_SERVICE_DOES_NOT_EXIST if (ERROR_SERVICE_DOES_NOT_EXIST != err) { iisDebugOut((LOG_TYPE_ERROR, _T("InetConfigServiceInteractive():OpenSCManager or OpenService: Service=%s Err=0x%x FAILED\n"), lpServiceName,err)); } break; } if(RetrieveServiceConfig(hService, &ServiceConfig) != NO_ERROR) { err = GetLastError(); break; } if(!ServiceConfig) { err = GetLastError(); break; } // Interactive flag can only work on own_process or share_process types if ( (ServiceConfig->dwServiceType & SERVICE_WIN32_OWN_PROCESS) || (ServiceConfig->dwServiceType & SERVICE_WIN32_SHARE_PROCESS)) { // default it incase someone changes code below and logic gets messed up dwNewServiceType = ServiceConfig->dwServiceType; // if the interactive flag is already there // then don't do jack, otherwise, add it on if (ServiceConfig->dwServiceType & SERVICE_INTERACTIVE_PROCESS) { // only do stuff if we're asked to remove it! if (FALSE == AddInteractive) { // Remove it from the mask! dwNewServiceType = ServiceConfig->dwServiceType & (~SERVICE_INTERACTIVE_PROCESS); bDoStuff = TRUE; } } else { if (TRUE == AddInteractive) { dwNewServiceType = ServiceConfig->dwServiceType | SERVICE_INTERACTIVE_PROCESS; bDoStuff = TRUE; } } if (TRUE == bDoStuff) { if ( !::ChangeServiceConfig(hService, dwNewServiceType, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL) ) { err = GetLastError(); iisDebugOut((LOG_TYPE_ERROR, _T("InetConfigServiceInteractive():ChangeServiceConfig: Service=%s Err=0x%x FAILED\n"), lpServiceName, err)); break; } } else { break; } } else { break; } } while ( FALSE ); if (ServiceConfig) {free(ServiceConfig);} if (hService) {CloseServiceHandle(hService);} if (hScManager) {CloseServiceHandle(hScManager);} iisDebugOut((LOG_TYPE_TRACE, _T("InetConfigServiceInteractive():ServiceName=%s. Return=0x%x.\n"), lpServiceName, err)); return(err); } // This function trys to create the www service int MyCreateService(CString csServiceName, CString csDisplayName, CString csBinPath, CString csDependencies, CString csDescription) { int iReturn = !ERROR_SUCCESS; int err = NERR_Success; TSTR strDependencies2( MAX_PATH ); iisDebugOut((LOG_TYPE_TRACE, _T("MyCreateService:%s,%s,%s,%s.\n"),csServiceName, csDisplayName, csBinPath, csDependencies)); if ( !strDependencies2.Copy( csDependencies.GetBuffer(0) ) || !strDependencies2.Append( _T(":") ) ) { return iReturn; } // make sure it ends with a ":" // and then replace all the ":", with a "\0" null.... TCHAR *p = (LPTSTR) strDependencies2.QueryStr(); while (*p) { // change ":" to a null "\0" if (*p == _T(':')){*p = _T('\0');} p = _tcsinc(p); } err = InetCreateService(csServiceName, (LPCTSTR)csDisplayName, (LPCTSTR)csBinPath, SERVICE_AUTO_START, strDependencies2.QueryStr()); if ( err != NERR_Success ) { // check if the error is because the service already exists... if (err == ERROR_SERVICE_EXISTS) { // Since the service should exist by the time we get here, // let's make sure it has the dependency we want it to have. err = InetConfigService(csServiceName, (LPCTSTR)csDisplayName, (LPCTSTR)csBinPath, strDependencies2.QueryStr()); if (err != NERR_Success) { SetLastError(err); goto MyCreateService_Exit; } } else { SetLastError(err); goto MyCreateService_Exit; } } // Use newer api to add the description field. err = InetConfigService2(csServiceName, (LPCTSTR)csDescription); if (err != NERR_Success) { SetLastError(err); goto MyCreateService_Exit; } // there was no error in the InetCreateService call. // so everything is hunky dory iReturn = ERROR_SUCCESS; MyCreateService_Exit: return iReturn; } DWORD CreateService_wrap(CString csServiceName, CString csDisplayName, CString csBinPath, CString csDependencies, CString csDescription, BOOL bDisplayMsgOnErrFlag) { int bFinishedFlag = FALSE; UINT iMsg = NULL; DWORD dwReturn = ERROR_SUCCESS; do { dwReturn = MyCreateService(csServiceName, csDisplayName, csBinPath, csDependencies, csDescription); if (dwReturn == ERROR_SUCCESS) { break; } else { if (bDisplayMsgOnErrFlag == TRUE) { iMsg = MyMessageBox( NULL, IDS_RETRY, MB_ABORTRETRYIGNORE | MB_SETFOREGROUND ); switch ( iMsg ) { case IDIGNORE: dwReturn = ERROR_SUCCESS; goto CreateService_wrap_Exit; case IDABORT: dwReturn = ERROR_OPERATION_ABORTED; goto CreateService_wrap_Exit; case IDRETRY: break; default: break; } } else { // return whatever err happened goto CreateService_wrap_Exit; } } } while (dwReturn != ERROR_SUCCESS); CreateService_wrap_Exit: return dwReturn; } // function: ChangeServiceDepenedency // // Change the dependency of a particular service, to either add or remove another service name // from it // // ex. ChangeServiceDependency( W3SSL, TRUE, IISADMIN ) - Would make W3SSL dependant on IISADMIN // // Parameters: // szServiceName - The service to modify // bAddDependency - Add or remove dependency // szDependantService - The service that you wand to add as the depenedency // BOOL ChangeServiceDependency(LPTSTR szServiceName, BOOL bAddDependency, LPTSTR szDependantService) { SC_HANDLE hService; SC_HANDLE hSCManager; BOOL bRet = FALSE; BOOL bChange = FALSE; BUFFER buffConfig; DWORD dwSizeRequired; TSTR_MSZ mszDependencies; hSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT | GENERIC_READ ); if ( hSCManager == NULL ) { return FALSE; } hService = OpenService( hSCManager, szServiceName, SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG ); if ( hService == NULL ) { CloseServiceHandle( hSCManager ); return FALSE; } if ( !QueryServiceConfig( hService, NULL, 0, &dwSizeRequired ) && ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) && buffConfig.Resize( dwSizeRequired ) && QueryServiceConfig( hService, (LPQUERY_SERVICE_CONFIG) buffConfig.QueryPtr(), buffConfig.QuerySize(), &dwSizeRequired ) ) { // We have successfully retrieved the service info, so lets modify it if ( mszDependencies.Copy( ((LPQUERY_SERVICE_CONFIG) buffConfig.QueryPtr())->lpDependencies ) ) { if ( bAddDependency ) { if ( !mszDependencies.IsPresent(szDependantService, FALSE) ) { bRet = mszDependencies.Add( szDependantService ); bChange = TRUE; } else { // It is already present, so we don't need to add again bRet = TRUE; } } else { if ( mszDependencies.IsPresent(szDependantService, FALSE) ) { bRet = mszDependencies.Remove( szDependantService, FALSE ); bChange = TRUE; } else { // Since it is not there, lets not worry about it bRet = TRUE; } } if ( bRet && bChange ) { bRet = ChangeServiceConfig( hService, // Service Handle SERVICE_NO_CHANGE, // Service Type SERVICE_NO_CHANGE, // Startup Type SERVICE_NO_CHANGE, // Error Control NULL, // Binary Path NULL, // Load Order Group NULL, // TagID mszDependencies.QueryMultiSz(), // Dependencies NULL, // Service Start Name NULL, // Password NULL ); // Display Name } } } CloseServiceHandle( hSCManager ); CloseServiceHandle( hService ); return bRet; }