/*++ Copyright (c) 1996 Microsoft Corporation Module Name: service.c Abstract: Functions for restarting fax and spooler services Environment: Windows NT fax configuration DLL Revision History: 05/28/96 -davidx- Created it. mm/dd/yy -author- description --*/ #include "faxcpl.h" // // Name of fax and spooler services // #define FAX_SERVICE_NAME TEXT("Fax") #define SPOOLER_SERVICE_NAME TEXT("Spooler") // // Information about list of dependent services which we stopped // typedef struct { PVOID pNext; TCHAR serviceName[1]; } DEPENDENT_SERVICE_LIST, *PDEPENDENT_SERVICE_LIST; BOOL MyStartService( LPTSTR pServerName, LPTSTR pServiceName ) /*++ Routine Description: Start the specified service on the specified server and wait for the service to be in the running state Arguments: pServerName - Specifies the name of the server computer, NULL for local machine pServiceName - Specifies the name of the service to be started Return Value: TRUE if successful, FALSE if there is an error --*/ { SC_HANDLE hSvcMgr = NULL; SC_HANDLE hService = NULL; SERVICE_STATUS serviceStatus; BOOL success = FALSE; Verbose(("Starting service '%ws' ...\n", pServiceName)); // // Find the specified service and start executing it // if ((hSvcMgr = OpenSCManager(pServerName, NULL, SC_MANAGER_ALL_ACCESS)) && (hService = OpenService(hSvcMgr, pServiceName, SERVICE_ALL_ACCESS)) && (StartService(hService, 0, NULL) || GetLastError() == ERROR_SERVICE_ALREADY_RUNNING) && QueryServiceStatus(hService, &serviceStatus)) { while (serviceStatus.dwCurrentState != SERVICE_RUNNING) { DWORD checkPoint = serviceStatus.dwCheckPoint; Verbose(("Waiting for service '%ws' to run: state = %d\n", pServiceName, serviceStatus.dwCurrentState)); Sleep(serviceStatus.dwWaitHint); if (!QueryServiceStatus(hService, &serviceStatus) || checkPoint == serviceStatus.dwCheckPoint) { break; } } success = (serviceStatus.dwCurrentState == SERVICE_RUNNING); } // // Cleanup before returning to the caller // if (! success) Error(("Failed to start service '%ws': %d\n", pServiceName, GetLastError())); if (hService) CloseServiceHandle(hService); if (hSvcMgr) CloseServiceHandle(hSvcMgr); return success; } BOOL MyStopService( LPTSTR pServerName, LPTSTR pServiceName, PDEPENDENT_SERVICE_LIST *ppDependentList ) /*++ Routine Description: Stop the specified service (as well as any services that depend on it) on the specified server and wait for the service to be in a non-running state Arguments: pServerName - Specifies the name of the server computer, NULL for local machine pServiceName - Specifies the name of the service to be stopped ppDependentList - Remember the list of dependent services which we stopped Return Value: TRUE if successful, FALSE if there is an error --*/ { SC_HANDLE hSvcMgr; SC_HANDLE hService; BOOL success = FALSE; Verbose(("Stopping service '%ws' ...\n", pServiceName)); if ((hSvcMgr = OpenSCManager(pServerName, NULL, SC_MANAGER_ALL_ACCESS)) && (hService = OpenService(hSvcMgr, pServiceName, SERVICE_ALL_ACCESS))) { LPENUM_SERVICE_STATUS pEnumStatus = NULL; DWORD cb, count, index; SERVICE_STATUS serviceStatus; // // Find all active services which depend on the current service // and call ourselves recursively to stop those services first // success = TRUE; if (! EnumDependentServices(hService, SERVICE_ACTIVE, NULL, 0, &cb, &count)) { if (GetLastError() == ERROR_MORE_DATA && (pEnumStatus = (LPENUM_SERVICE_STATUS) MemAlloc(cb)) && EnumDependentServices(hService, SERVICE_ACTIVE, pEnumStatus, cb, &cb, &count)) { for (index=0; success && index < count; index++) { success = MyStopService(pServerName, pEnumStatus[index].lpServiceName, ppDependentList); } } MemFree(pEnumStatus); } // // Stop the current service and wait for it to die // if (success) { ControlService(hService, SERVICE_CONTROL_STOP, &serviceStatus); if (success = QueryServiceStatus(hService, &serviceStatus)) { while (serviceStatus.dwCurrentState != SERVICE_STOPPED) { DWORD checkPoint = serviceStatus.dwCheckPoint; Verbose(("Waiting for service '%ws' to stop: state = %d\n", pServiceName, serviceStatus.dwCurrentState)); Sleep(serviceStatus.dwWaitHint); if (!QueryServiceStatus(hService, &serviceStatus) || checkPoint == serviceStatus.dwCheckPoint) { break; } } success = (serviceStatus.dwCurrentState == SERVICE_STOPPED); } } } // // If the service has been successfully stopped, remember its name // so that we can restart it later. // if (success) { PDEPENDENT_SERVICE_LIST p; if (p = MemAlloc(offsetof(DEPENDENT_SERVICE_LIST, serviceName) + SizeOfString(pServiceName))) { _tcscpy(p->serviceName, pServiceName); p->pNext = *ppDependentList; *ppDependentList = p; } success = (p != NULL); } // // Cleanup before returning to the caller // if (! success) Error(("Failed to stop service '%ws': %d\n", pServiceName, GetLastError())); if (hService) CloseServiceHandle(hService); if (hSvcMgr) CloseServiceHandle(hSvcMgr); return success; } BOOL StartFaxService( LPTSTR pServerName ) /*++ Routine Description: Start the fax service and Arguments: pServerName - Specifies the name of the server computer, NULL for local machine Return Value: TRUE if successful, FALSE if there is an error --*/ { BOOL success = FALSE; // // Start the fax service and wait for it to be in the running state // if (MyStartService(pServerName, FAX_SERVICE_NAME)) { HANDLE hFaxServerEvent; // // Wait for the fax service to complete its initialization // if (hFaxServerEvent = OpenEvent(SYNCHRONIZE, FALSE, TEXT("FaxServerEvent"))) { WaitForSingleObject(hFaxServerEvent, INFINITE); CloseHandle(hFaxServerEvent); success = TRUE; } else Error(("Couldn't open a handle to the fax service event: %d\n", GetLastError())); } return success; } BOOL RestartFaxAndSpoolerServices( LPTSTR pServerName ) /*++ Routine Description: Restart fax and spooler services after fax configuration settings are changed Arguments: pServerName - Specifies the name of the server computer, NULL for local machine Return Value: TRUE if successful, FALSE if there is an error --*/ { PDEPENDENT_SERVICE_LIST p, pDependents = NULL; BOOL result; // // Fax service must be stopped after the spooler service // because it's a dependent service of the spooler. // // Start the fax and spooler services in the opposite order, // i.e., first start the fax service and then the spooler service. // result = MyStopService(pServerName, SPOOLER_SERVICE_NAME, &pDependents) && MyStopService(pServerName, FAX_SERVICE_NAME, &pDependents) && StartFaxService(pServerName); // // Start other services which we have stopped above // while (pDependents) { if (result) result = MyStartService(pServerName, pDependents->serviceName); p = pDependents; pDependents = p->pNext; MemFree(p); } return result; }