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;
|
|||
|
}
|
|||
|
|