Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

293 lines
9.8 KiB

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
net\routing\ipx\sap\svcsif.c
Abstract:
SAP interface with service controller
(API for standalone SAP agent part of services.exe)
Author:
Vadim Eydelman 05-15-1995
Revision History:
--*/
#include "sapp.h"
// SAP service status (when operating standalone outside of router)
SERVICE_STATUS_HANDLE ServiceStatusHandle;
SERVICE_STATUS ServiceStatus;
volatile HANDLE ServiceThreadHdl;
VOID
ServiceMain (
DWORD argc,
LPTSTR argv[]
);
VOID APIENTRY
ResumeServiceThread (
ULONG_PTR param
) {
return ;
}
VOID
ServiceHandler (
DWORD fdwControl
) {
ASSERT (ServiceStatusHandle!=0);
EnterCriticalSection (&OperationalStateLock);
switch (fdwControl) {
case SERVICE_CONTROL_STOP:
case SERVICE_CONTROL_SHUTDOWN:
#if DBG
DbgPrint ("IPXSAP: Service control stop/shutdown.\n");
#endif
if (ServiceIfActive) {
ServiceIfActive = FALSE;
if (ServiceThreadHdl!=NULL) {
BOOL res;
HANDLE localHdl = ServiceThreadHdl;
ServiceThreadHdl = NULL;
#if DBG
DbgPrint ("IPXSAP: Resuming service thread.\n");
#endif
res = QueueUserAPC (
ResumeServiceThread,
localHdl,
0);
ASSERTMSG ("Could not queue APC to service thread ", res);
CloseHandle (localHdl);
}
ServiceStatus.dwCheckPoint += 1;
ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
}
else
Trace (DEBUG_FAILURES,
"SAP service has already been told to stop.");
break;
case SERVICE_CONTROL_INTERROGATE:
#if DBG
DbgPrint ("IPXSAP: Service control interrogate.\n");
#endif
switch (OperationalState) {
case OPER_STATE_UP:
if (ServiceIfActive)
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
else
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
break;
case OPER_STATE_STARTING:
if (ServiceIfActive) {
ServiceStatus.dwCheckPoint += 1;
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
}
else
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
break;
case OPER_STATE_STOPPING:
if (ServiceIfActive)
// This is the case when router is being stopped
// SAP will be restarted soon
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
else {
ServiceStatus.dwCheckPoint += 1;
ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
}
break;
case OPER_STATE_DOWN:
if (ServiceIfActive) {
// This is the case when service is being started
ServiceStatus.dwCheckPoint += 1;
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
}
else
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
break;
default:
ASSERTMSG ("SAP is in unknown state ", FALSE);
}
break;
default:
Trace (DEBUG_FAILURES,
"Service control handler called with unknown"
" or unsupported code %d.", fdwControl);
break;
}
#if DBG
DbgPrint ("IPXSAP: Service control setting current state to %d.\n",
ServiceStatus.dwCurrentState);
#endif
SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
LeaveCriticalSection (&OperationalStateLock);
}
/*++
*******************************************************************
S e r v i c e M a i n
Routine Description:
Entry point to be called by service controller to start SAP agent
(when SAP is not part of the router but is a standalone service,
though running in the router process)
Arguments:
argc - number of string arguments passed to service
argv - array of string arguments passed to service
Return Value:
None
*******************************************************************
--*/
VOID
ServiceMain (
DWORD argc,
LPWSTR argv[]
) {
DWORD rc;
ServiceStatusHandle = RegisterServiceCtrlHandler (
TEXT("nwsapagent"), ServiceHandler);
if (!ServiceStatusHandle)
{
return;
}
ServiceStatus.dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
rc = DuplicateHandle (GetCurrentProcess (),
GetCurrentThread (),
GetCurrentProcess (),
(HANDLE *)&ServiceThreadHdl,
0,
FALSE,
DUPLICATE_SAME_ACCESS );
ASSERTMSG ("Could not duplicate service thread handle ", rc);
EnterCriticalSection (&OperationalStateLock);
ServiceIfActive = TRUE;
if (RouterIfActive) {
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP
| SERVICE_ACCEPT_SHUTDOWN;
SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
LeaveCriticalSection (&OperationalStateLock);
#if DBG
DbgPrint ("IPXSAP: Suspending service thread.\n");
#endif
while (ServiceThreadHdl!=NULL) {
SleepEx (INFINITE, TRUE);
#if DBG
DbgPrint ("IPXSAP: Service thread awakened.\n");
#endif
}
#if DBG
DbgPrint ("IPXSAP: Service thread resumed.\n");
#endif
EnterCriticalSection (&OperationalStateLock);
if (!RouterIfActive) {
if (OperationalState==OPER_STATE_UP)
StopSAP ();
LeaveCriticalSection (&OperationalStateLock);
#if DBG
DbgPrint ("IPXSAP: Waiting for main thread to exit.\n");
#endif
rc = WaitForSingleObject (MainThreadHdl, INFINITE);
ASSERTMSG ("Unexpected result from wait for sap main thread ",
rc== WAIT_OBJECT_0);
EnterCriticalSection (&OperationalStateLock);
CloseHandle (MainThreadHdl);
MainThreadHdl = NULL;
}
}
else {
BOOL bInternalNetNumOk;
// [pmay]
// We use this scheme to automatically select the internal network
// number of the machine we're running on. If the net number is configured
// as zero, this function will automatically select a random net num and
// verify it's uniqueness on the net that this machine is attached to.
DbgInitialize (hDLLInstance);
if (AutoValidateInternalNetNum(&bInternalNetNumOk, DEBUG_ADAPTERS) == NO_ERROR) {
if (!bInternalNetNumOk) {
if (PnpAutoSelectInternalNetNumber(DEBUG_ADAPTERS) != NO_ERROR)
Trace(DEBUG_ADAPTERS, "StartRouter: Auto selection of net number failed.");
else
AutoWaitForValidIntNetNum (10, NULL);
}
}
ServiceStatus.dwWin32ExitCode = CreateAllComponents (NULL);
if (ServiceStatus.dwWin32ExitCode==NO_ERROR) {
// We use the thread that we were launched in
// as IO thread
ServiceStatus.dwWin32ExitCode = StartSAP ();
if (ServiceStatus.dwWin32ExitCode==NO_ERROR) {
LeaveCriticalSection (&OperationalStateLock);
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP
| SERVICE_ACCEPT_SHUTDOWN;
SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
#if DBG
DbgPrint ("IPXSAP: Suspending service thread.\n");
#endif
while (ServiceThreadHdl!=NULL) {
SleepEx (INFINITE, TRUE);
#if DBG
DbgPrint ("IPXSAP: Service thread awakened.\n");
#endif
}
#if DBG
DbgPrint ("IPXSAP: Service thread resumed.\n");
#endif
EnterCriticalSection (&OperationalStateLock);
ServiceIfActive = FALSE;
if (!RouterIfActive) {
if (OperationalState==OPER_STATE_UP)
StopSAP ();
LeaveCriticalSection (&OperationalStateLock);
#if DBG
DbgPrint ("IPXSAP: Waiting for main thread to exit.\n");
#endif
rc = WaitForSingleObject (MainThreadHdl, INFINITE);
ASSERTMSG ("Unexpected result from wait for sap main thread ",
rc== WAIT_OBJECT_0);
EnterCriticalSection (&OperationalStateLock);
}
CloseHandle (MainThreadHdl);
MainThreadHdl = NULL;
}
else {
DeleteAllComponents ();
}
}
}
ServiceIfActive = FALSE;
LeaveCriticalSection (&OperationalStateLock);
#if DBG
DbgPrint ("IPXSAP: Service stopped.\n");
#endif
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
}