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
10 KiB
293 lines
10 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);
|
|
}
|
|
|