|
|
//
// Copyright (C) 1993-1997 Microsoft Corporation. All Rights Reserved.
//
// MODULE: nmmgr.cpp
//
// PURPOSE: Implements the body of the service.
//
// FUNCTIONS:
// MNMServiceStart(DWORD dwArgc, LPTSTR *lpszArgv);
// MNMServiceStop( );
//
// COMMENTS: The functions implemented in nmmgr.c are
// prototyped in nmmgr.h
//
//
// AUTHOR: Claus Giloi
//
#include <precomp.h>
#include <tsecctrl.h>
#define NMSRVC_TEXT "NMSrvc"
// DEBUG only -- Define debug zone
#ifdef DEBUG
HDBGZONE ghZone = NULL; static PTCHAR rgZones[] = { NMSRVC_TEXT, "Warning", "Trace", "Function" }; #endif // DEBUG
extern INmSysInfo2 * g_pNmSysInfo; // Interface to SysInfo
extern BOOL InitT120Credentials(VOID);
// this event is signaled when the
// service should end
const int STOP_EVENT = 0; HANDLE hServerStopEvent = NULL;
// this event is signaled when the
// service should be paused or continued
const int PAUSE_EVENT = 1; HANDLE hServerPauseEvent = NULL;
const int CONTINUE_EVENT = 2; HANDLE hServerContinueEvent = NULL;
const int numEventHandles = 3;
HANDLE hServerActiveEvent = NULL;
DWORD g_dwActiveState = STATE_INACTIVE;
//
// FUNCTION: CreateWatcherProcess
//
// PURPOSE: This launches a rundll32.exe which loads msconf.dll which will then wait for
// us to terminate and make sure that the mnmdd display driver was properly deactivated.
//
// PARAMETERS:
//
// RETURN VALUE:
//
// COMMENTS:
//
BOOL CreateWatcherProcess() { BOOL bRet = FALSE; HANDLE hProcess;
// open a handle to ourselves that the watcher process can inherit
hProcess = OpenProcess(SYNCHRONIZE, TRUE, GetCurrentProcessId()); if (hProcess) { TCHAR szWindir[MAX_PATH];
if (GetSystemDirectory(szWindir, sizeof(szWindir)/sizeof(szWindir[0]))) { TCHAR szCmdLine[MAX_PATH * 2]; PROCESS_INFORMATION pi = {0}; STARTUPINFO si = {0};
si.cb = sizeof(si); wsprintf(szCmdLine, "\"%s\\rundll32.exe\" msconf.dll,CleanupNetMeetingDispDriver %ld", szWindir, HandleToLong(hProcess));
if (CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, // we want the watcher to inherit hProcess, so we must set bInheritHandles = TRUE
0, NULL, NULL, &si, &pi)) { bRet = TRUE;
CloseHandle(pi.hThread); CloseHandle(pi.hProcess); } }
CloseHandle(hProcess); }
return bRet; }
//
// FUNCTION: MNMServiceStart
//
// PURPOSE: Actual code of the service
// that does the work.
//
// PARAMETERS:
// dwArgc - number of command line arguments
// lpszArgv - array of command line arguments
//
// RETURN VALUE:
// none
//
// COMMENTS:
//
VOID MNMServiceStart (DWORD dwArgc, LPTSTR *lpszArgv) { HRESULT hRet; BOOL fWaitForEvent = TRUE; DWORD dwResult; MSG msg; LPCTSTR lpServiceStopEvent = TEXT("ServiceStopEvent"); LPCTSTR lpServiceBusyEvent = TEXT("ServiceBusyEvent"); const int MaxWaitTime = 5; HANDLE hConfEvent; DWORD dwError = NO_ERROR; HANDLE hShuttingDown; int i; RegEntry Re( REMOTECONTROL_KEY, HKEY_LOCAL_MACHINE );
// Initialization
DBGINIT(&ghZone, rgZones); InitDebugModule(NMSRVC_TEXT);
DebugEntry(MNMServiceStart);
if (!Re.GetNumber(REMOTE_REG_RUNSERVICE, DEFAULT_REMOTE_RUNSERVICE)) { TRACE_OUT(("Try to start mnmsrvc without no registry setting")); goto cleanup; } ///////////////////////////////////////////////////
//
// Service initialization
//
// report the status to the service control manager.
//
if (!ReportStatusToSCMgr( SERVICE_START_PENDING, NO_ERROR, 30000)) { ERROR_OUT(("ReportStatusToSCMgr failed")); dwError = GetLastError(); goto cleanup; } HANDLE pEventHandles[numEventHandles]; // create the event object. The control handler function signals
// this event when it receives the "stop" control code.
//
hServerStopEvent = CreateEvent( NULL, // no security attributes
TRUE, // manual reset event
FALSE, // not-signalled
SERVICE_STOP_EVENT); // no name
if ( hServerStopEvent == NULL) { ERROR_OUT(("CreateEvent failed")); dwError = GetLastError(); goto cleanup; } pEventHandles[STOP_EVENT] = hServerStopEvent;
hServerPauseEvent = CreateEvent( NULL, FALSE, FALSE, SERVICE_PAUSE_EVENT);
if (hServerPauseEvent == NULL) { ERROR_OUT(("CreateEvent failed")); dwError = GetLastError(); goto cleanup; }
pEventHandles[PAUSE_EVENT] = hServerPauseEvent;
hServerContinueEvent = CreateEvent( NULL, FALSE, FALSE, SERVICE_CONTINUE_EVENT);
if (hServerContinueEvent == NULL) { ERROR_OUT(("CreateEvent failed")); dwError = GetLastError(); goto cleanup; }
pEventHandles[CONTINUE_EVENT] = hServerContinueEvent; CoInitialize(NULL);
//
// End of initialization
//
////////////////////////////////////////////////////////
// report the status to the service control manager.
//
if (!ReportStatusToSCMgr( SERVICE_RUNNING, // service state
NO_ERROR, // exit code
0)) // wait hint
{ ERROR_OUT(("ReportStatusToSCMgr failed")); goto cleanup; } SetConsoleCtrlHandler(ServiceCtrlHandler, TRUE);
CreateWatcherProcess();
AddTaskbarIcon();
////////////////////////////////////////////////////////
//
// Service is now running, perform work until shutdown
//
if (IS_NT) { AddToMessageLog(EVENTLOG_INFORMATION_TYPE, 0, MSG_INF_START, NULL); }
//
// Check if the service should start up activated
//
if ( Re.GetNumber(REMOTE_REG_ACTIVATESERVICE, DEFAULT_REMOTE_ACTIVATESERVICE)) { MNMServiceActivate(); } else { if (!ReportStatusToSCMgr( SERVICE_PAUSED, // service state
NO_ERROR, // exit code
0)) // wait hint
{ ERROR_OUT(("ReportStatusToSCMgr failed")); goto cleanup; } }
while (fWaitForEvent) { dwResult = MsgWaitForMultipleObjects( numEventHandles, pEventHandles, FALSE, INFINITE, QS_ALLINPUT);
switch (dwResult) { case WAIT_OBJECT_0 + numEventHandles: { while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (WM_QUIT != msg.message) { TranslateMessage(&msg); DispatchMessage(&msg); } else { TRACE_OUT(("received WM_QUIT")); fWaitForEvent = FALSE; break; } } break; } case WAIT_OBJECT_0 + PAUSE_EVENT: { if (STATE_ACTIVE == g_dwActiveState) { MNMServiceDeActivate(); } ReportStatusToSCMgr( SERVICE_PAUSED, NO_ERROR, 0); break; } case WAIT_OBJECT_0 + CONTINUE_EVENT: { HANDLE hInit = OpenEvent(EVENT_ALL_ACCESS, FALSE, _TEXT("CONF:Init")); if (STATE_INACTIVE == g_dwActiveState && NULL == hInit) { MNMServiceActivate(); } CloseHandle(hInit); ReportStatusToSCMgr( SERVICE_RUNNING, NO_ERROR, 0); break; } case WAIT_OBJECT_0 + STOP_EVENT: { RemoveTaskbarIcon(); if (STATE_ACTIVE == g_dwActiveState) { MNMServiceDeActivate(); } fWaitForEvent = FALSE; break; } } }
cleanup:
if ( STATE_ACTIVE == g_dwActiveState ) { MNMServiceDeActivate(); } if (hServerStopEvent) CloseHandle(hServerStopEvent); if (hServerPauseEvent) CloseHandle(hServerPauseEvent); if (hServerContinueEvent) CloseHandle(hServerContinueEvent);
TRACE_OUT(("Reporting SERVICE_STOPPED")); ReportStatusToSCMgr( SERVICE_STOPPED, dwError, 0);
DebugExitVOID(MNMServiceStart);
CoUninitialize();
DBGDEINIT(&ghZone); ExitDebugModule(); } BOOL MNMServiceActivate ( VOID ) { DebugEntry(MNMServiceActivate);
if ( STATE_INACTIVE != g_dwActiveState ) { WARNING_OUT(("MNMServiceActivate: g_dwActiveState:%d", g_dwActiveState)); return FALSE; }
g_dwActiveState = STATE_BUSY;
if (!IS_NT) { ASSERT(NULL == hServerActiveEvent); hServerActiveEvent = CreateEvent(NULL, FALSE, FALSE, SERVICE_ACTIVE_EVENT); } HRESULT hRet = InitConfMgr(); if (FAILED(hRet)) { ERROR_OUT(("ERROR %x initializing nmmanger", hRet)); FreeConfMgr(); g_dwActiveState = STATE_INACTIVE; if (!IS_NT) { CloseHandle ( hServerActiveEvent ); } DebugExitBOOL(MNMServiceActivate,FALSE); return FALSE; }
if ( g_pNmSysInfo ) { //
// Attempt to initialize T.120 security, if this fails
// bail out since we won't be able to receive any calls
//
if ( !InitT120Credentials() ) { FreeConfMgr(); g_dwActiveState = STATE_INACTIVE; if (!IS_NT) { CloseHandle ( hServerActiveEvent ); } DebugExitBOOL(MNMServiceActivate,FALSE); return FALSE; } } g_dwActiveState = STATE_ACTIVE; DebugExitBOOL(MNMServiceActivate,TRUE); return TRUE; }
BOOL MNMServiceDeActivate ( VOID ) { DebugEntry(MNMServiceDeActivate);
if (STATE_ACTIVE != g_dwActiveState) { WARNING_OUT(("MNMServiceDeActivate: g_dwActiveState:%d", g_dwActiveState)); DebugExitBOOL(MNMServiceDeActivate,FALSE); return FALSE; }
g_dwActiveState = STATE_BUSY;
//
// Leave Conference
//
if (NULL != g_pConference) { if (g_pNmSysInfo) { g_pNmSysInfo->ProcessSecurityData(UNLOADFTAPPLET,0,0,NULL); } if ( FAILED(g_pConference->Leave())) { ERROR_OUT(("Conference Leave failed"));; } }
//
// Free the conference
//
FreeConference();
//
// Free the AS interface
//
ASSERT(g_pAS); UINT ret = g_pAS->Release(); g_pAS = NULL; TRACE_OUT(("AS interface freed, ref %d after Release", ret));
// can we have a way not to create this event?
HANDLE hevt = ::CreateEvent(NULL, FALSE, FALSE, NULL); ASSERT(NULL != hevt); const DWORD dwTimeout = 1000; DWORD dwStartTime = ::GetTickCount(); DWORD dwCurrTimeout = dwTimeout; DWORD dwRet; BOOL fContinue = TRUE;
while (fContinue && WAIT_OBJECT_0 != (dwRet = ::MsgWaitForMultipleObjects(1, &hevt, FALSE, dwCurrTimeout, QS_ALLINPUT))) { if (WAIT_TIMEOUT != dwRet) { DWORD dwCurrTime = ::GetTickCount(); if (dwCurrTime < dwStartTime + dwTimeout) { dwCurrTimeout = dwStartTime + dwTimeout - dwCurrTime;
MSG msg; while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (WM_QUIT != msg.message) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } else { ::PostQuitMessage(0); fContinue = FALSE; } } continue; } // timeout here
} // exit the loop
break; } ::CloseHandle(hevt);
// not to call FreeConfMfr imediately after FreeConference to avoid
// a bug in t120 will remove this sleep call after fix the bug in t120
FreeConfMgr();
// BUGBUG remove h323cc.dll should be done in nmcom. Once the bug in nmcom is fixed, this part will be removed.
HMODULE hmodH323CC = GetModuleHandle("h323cc.dll"); if (hmodH323CC) { if (FreeLibrary(hmodH323CC)) { TRACE_OUT(("CmdInActivate -- Unloaded h323cc.dll")); } else { WARNING_OUT(("CmdInActivate -- Failed to unload h323cc.dll %d", GetLastError())); } } if (!IS_NT) { ASSERT(hServerActiveEvent); if (hServerActiveEvent) { CloseHandle(hServerActiveEvent); hServerActiveEvent = NULL; } } g_dwActiveState = STATE_INACTIVE; DebugExitBOOL(MNMServiceDeActivate,TRUE); return TRUE; }
//
// FUNCTION: MNMServiceStop
//
// PURPOSE: Stops the service
//
// PARAMETERS:
// none
//
// RETURN VALUE:
// none
//
// COMMENTS:
// If a ServiceStop procedure is going to
// take longer than 3 seconds to execute,
// it should spawn a thread to execute the
// stop code, and return. Otherwise, the
// ServiceControlManager will believe that
// the service has stopped responding.
//
VOID MNMServiceStop() { DebugEntry(MNMServiceStop);
RemoveTaskbarIcon();
if ( hServerStopEvent ) { TRACE_OUT(("MNMServiceStop: setting server stop event")); SetEvent(hServerStopEvent); }
if (IS_NT) { AddToMessageLog(EVENTLOG_INFORMATION_TYPE, 0, MSG_INF_STOP, NULL); }
DebugExitVOID(MNMServiceStop); }
VOID MNMServicePause() { DebugEntry(MNMServicePause);
if ( hServerPauseEvent ) SetEvent(hServerPauseEvent);
DebugExitVOID(MNMServicePause); }
VOID MNMServiceContinue() { DebugEntry(MNMServiceContinue);
if ( hServerContinueEvent ) SetEvent(hServerContinueEvent);
DebugExitVOID(MNMServiceContinue); }
|