367 lines
8.3 KiB
C
367 lines
8.3 KiB
C
/*++
|
||
|
||
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;
|
||
}
|
||
|