mirror of https://github.com/lianthony/NT4.0
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.
382 lines
8.0 KiB
382 lines
8.0 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Start.c
|
|
|
|
Abstract:
|
|
|
|
Process init and service controller interaction for dcomss.exe
|
|
|
|
Author:
|
|
|
|
Mario Goertzel [MarioGo]
|
|
|
|
Revision History:
|
|
|
|
MarioGo 06-14-95 Cloned from the old endpoint mapper.
|
|
|
|
--*/
|
|
|
|
#include <dcomss.h>
|
|
#include <debnot.h>
|
|
#include <olesem.hxx>
|
|
|
|
|
|
|
|
// Array of service status blocks and pointers to service control
|
|
// functions for each component service.
|
|
|
|
#define SERVICE_NAME L"RPCSS"
|
|
|
|
VOID WINAPI ServiceMain(DWORD, PWSTR[]);
|
|
|
|
SERVICE_TABLE_ENTRY gaServiceEntryTable[] = {
|
|
{ SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)ServiceMain},
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
static SERVICE_STATUS gServiceStatus;
|
|
static SERVICE_STATUS_HANDLE ghServiceHandle;
|
|
|
|
BOOL gfDebugMode = FALSE;
|
|
|
|
BOOL gfRegisteredAuthInfo = FALSE;
|
|
|
|
|
|
|
|
void
|
|
ServiceHandler(
|
|
DWORD opCode
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Lowest level callback from the service controller to
|
|
cause this service to change our status. (stop, start, pause, etc).
|
|
|
|
Arguments:
|
|
|
|
opCode - One of the service "Controls" value.
|
|
SERVICE_CONTROL_{STOP, PAUSE, CONTINUE, INTERROGATE, SHUTDOWN}.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
RPC_STATUS status;
|
|
|
|
switch(opCode) {
|
|
|
|
case SERVICE_CONTROL_STOP:
|
|
case SERVICE_CONTROL_PAUSE:
|
|
case SERVICE_CONTROL_CONTINUE:
|
|
default:
|
|
#ifdef DEBUGRPC
|
|
DbgPrint("%S: Unexpected service control message %d.\n", SERVICE_NAME, opCode);
|
|
#endif
|
|
ASSERT(0);
|
|
break;
|
|
|
|
case SERVICE_CONTROL_INTERROGATE:
|
|
// Service controller wants us to call SetServiceStatus.
|
|
|
|
UpdateState(gServiceStatus.dwCurrentState);
|
|
break ;
|
|
|
|
case SERVICE_CONTROL_SHUTDOWN:
|
|
// The machine is shutting down. We'll be killed once we return.
|
|
// Note, currently we don't register for these messages.
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
UpdateState(
|
|
DWORD dwNewState
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Updates this services state with the service controller.
|
|
|
|
Arguments:
|
|
|
|
dwNewState - The next start for this service. One of
|
|
SERVICE_START_PENDING
|
|
SERVICE_RUNNING
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
DWORD status = ERROR_SUCCESS;
|
|
|
|
if (gfDebugMode == TRUE)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ASSERT( (dwNewState == SERVICE_RUNNING) ||
|
|
(gServiceStatus.dwCurrentState != SERVICE_RUNNING) );
|
|
|
|
switch (dwNewState)
|
|
{
|
|
|
|
case SERVICE_RUNNING:
|
|
case SERVICE_STOPPED:
|
|
gServiceStatus.dwCheckPoint = 0;
|
|
gServiceStatus.dwWaitHint = 0;
|
|
break;
|
|
|
|
case SERVICE_START_PENDING:
|
|
case SERVICE_STOP_PENDING:
|
|
++gServiceStatus.dwCheckPoint;
|
|
gServiceStatus.dwWaitHint = 30000L;
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0);
|
|
status = ERROR_INVALID_SERVICE_CONTROL;
|
|
break;
|
|
}
|
|
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
gServiceStatus.dwCurrentState = dwNewState;
|
|
if (!SetServiceStatus(ghServiceHandle, &gServiceStatus))
|
|
{
|
|
status = GetLastError();
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUGRPC
|
|
if (status != ERROR_SUCCESS)
|
|
{
|
|
DbgPrint("%S: Failed to update service state: %d\n", SERVICE_NAME, status);
|
|
}
|
|
#endif
|
|
|
|
// We could return a status but how would we recover? Ignore it, the
|
|
// worst thing is that services will kill us and there's nothing
|
|
// we can about it if this call fails.
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
VOID WINAPI
|
|
ServiceMain(
|
|
DWORD argc,
|
|
PWSTR argv[]
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Callback by the service controller when starting this service.
|
|
|
|
Arguments:
|
|
|
|
argc - number of arguments, usually 1
|
|
|
|
argv - argv[0] is the name of the service.
|
|
argv[>0] are arguments passed to the service.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
DWORD status = ERROR_SUCCESS;
|
|
|
|
const DWORD RPCSS_CONTROLS = 0; // SERVER_ACCEPT_STOP - we don't stop.
|
|
|
|
ASSERT( (argc >= 1 && lstrcmpiW(argv[0], SERVICE_NAME) == 0)
|
|
|| (argc == 0 && argv == 0));
|
|
|
|
#if DBG==1
|
|
|
|
// Note that we've completed running the static constructors
|
|
|
|
ASSERT(g_fDllState == DLL_STATE_STATIC_CONSTRUCTING);
|
|
|
|
g_fDllState = DLL_STATE_NORMAL;
|
|
|
|
#endif
|
|
|
|
|
|
// Initialize the mutex package
|
|
|
|
InitializeCriticalSection (&g_OleMutexCreationSem);
|
|
|
|
|
|
if (FALSE == gfDebugMode)
|
|
{
|
|
gServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
|
gServiceStatus.dwCurrentState = SERVICE_START_PENDING;
|
|
gServiceStatus.dwControlsAccepted = RPCSS_CONTROLS;
|
|
gServiceStatus.dwWin32ExitCode = 0;
|
|
gServiceStatus.dwServiceSpecificExitCode = 0;
|
|
gServiceStatus.dwCheckPoint = 0;
|
|
gServiceStatus.dwWaitHint = 3000L;
|
|
|
|
ghServiceHandle = RegisterServiceCtrlHandler(SERVICE_NAME,
|
|
ServiceHandler);
|
|
|
|
if (0 == ghServiceHandle)
|
|
{
|
|
status = GetLastError();
|
|
ASSERT(status != ERROR_SUCCESS);
|
|
}
|
|
}
|
|
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
UpdateState(SERVICE_START_PENDING);
|
|
}
|
|
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
// epts.c
|
|
status = InitializeEndpointManager();
|
|
}
|
|
|
|
// Start Ep Mapper.
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
// ..\epmap\server.c
|
|
UpdateState(SERVICE_START_PENDING);
|
|
status = StartEndpointMapper();
|
|
}
|
|
|
|
// Start object resolver
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
// ..\objex\objex.cxx
|
|
UpdateState(SERVICE_START_PENDING);
|
|
status = StartObjectExporter();
|
|
}
|
|
|
|
// Start OLESCM
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
// ..\olescm\scmsvc.cxx
|
|
UpdateState(SERVICE_START_PENDING);
|
|
status = InitializeSCM();
|
|
}
|
|
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
// We continue if this fails, not the end of the world.
|
|
(void) RegisterAuthInfoIfNecessary();
|
|
}
|
|
|
|
// Start listening for RPC requests
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
status = RpcServerListen(1, 1234, TRUE);
|
|
|
|
if (status == RPC_S_OK)
|
|
{
|
|
while (RpcMgmtIsServerListening(0) == RPC_S_NOT_LISTENING)
|
|
{
|
|
Sleep(100);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// There is some initialization that must be done after we
|
|
// have done the RpcServerListen.
|
|
//
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
// ..\olescm\scmsvc.cxx
|
|
UpdateState(SERVICE_START_PENDING);
|
|
InitializeSCMAfterListen();
|
|
}
|
|
|
|
// Trim our working set - free space now at the cost of time later.
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
// Since we auto-start it is unlikely that may of our pages
|
|
// will be needed anytime soon.
|
|
|
|
UpdateState(SERVICE_RUNNING);
|
|
|
|
if (FALSE == SetProcessWorkingSetSize(GetCurrentProcess(), ~0UL, ~0UL))
|
|
{
|
|
status = GetLastError();
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUGRPC
|
|
if (status != ERROR_SUCCESS)
|
|
{
|
|
DbgPrint("RPCSS ServiceMain failed %d (%08x)\n", status, status);
|
|
}
|
|
#endif
|
|
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
ObjectExporterWorkerThread(0);
|
|
ASSERT(0);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
int
|
|
main(
|
|
int argc,
|
|
char *argv[]
|
|
)
|
|
{
|
|
DWORD status;
|
|
|
|
//DebugBreak(); // Makes debugging as a service during startup possible.
|
|
|
|
if (argc == 2 && _stricmp(argv[1], "noservice") == 0)
|
|
{
|
|
gfDebugMode = TRUE;
|
|
}
|
|
|
|
if (gfDebugMode == FALSE)
|
|
{
|
|
if (StartServiceCtrlDispatcher(gaServiceEntryTable) == FALSE)
|
|
{
|
|
#ifdef DEBUGRPC
|
|
DbgPrint("%S: StartServiceCtrlDispatcher failed %d\n",
|
|
SERVICE_NAME,
|
|
GetLastError()
|
|
);
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Debug only.
|
|
ServiceMain(0, 0);
|
|
}
|
|
|
|
#ifdef DEBUGRPC
|
|
DbgPrint("RPCSS: Service stopped.\n");
|
|
#endif
|
|
|
|
return(0);
|
|
}
|
|
|