Leaked source code of windows server 2003
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.

606 lines
16 KiB

  1. //
  2. // Copyright (C) 1993-1997 Microsoft Corporation. All Rights Reserved.
  3. //
  4. // MODULE: nmmgr.cpp
  5. //
  6. // PURPOSE: Implements the body of the service.
  7. //
  8. // FUNCTIONS:
  9. // MNMServiceStart(DWORD dwArgc, LPTSTR *lpszArgv);
  10. // MNMServiceStop( );
  11. //
  12. // COMMENTS: The functions implemented in nmmgr.c are
  13. // prototyped in nmmgr.h
  14. //
  15. //
  16. // AUTHOR: Claus Giloi
  17. //
  18. #include <precomp.h>
  19. #include <tsecctrl.h>
  20. #define NMSRVC_TEXT "NMSrvc"
  21. // DEBUG only -- Define debug zone
  22. #ifdef DEBUG
  23. HDBGZONE ghZone = NULL;
  24. static PTCHAR rgZones[] = {
  25. NMSRVC_TEXT,
  26. "Warning",
  27. "Trace",
  28. "Function"
  29. };
  30. #endif // DEBUG
  31. extern INmSysInfo2 * g_pNmSysInfo; // Interface to SysInfo
  32. extern BOOL InitT120Credentials(VOID);
  33. // this event is signaled when the
  34. // service should end
  35. const int STOP_EVENT = 0;
  36. HANDLE hServerStopEvent = NULL;
  37. // this event is signaled when the
  38. // service should be paused or continued
  39. const int PAUSE_EVENT = 1;
  40. HANDLE hServerPauseEvent = NULL;
  41. const int CONTINUE_EVENT = 2;
  42. HANDLE hServerContinueEvent = NULL;
  43. const int numEventHandles = 3;
  44. HANDLE hServerActiveEvent = NULL;
  45. DWORD g_dwActiveState = STATE_INACTIVE;
  46. //
  47. // FUNCTION: CreateWatcherProcess
  48. //
  49. // PURPOSE: This launches a rundll32.exe which loads msconf.dll which will then wait for
  50. // us to terminate and make sure that the mnmdd display driver was properly deactivated.
  51. //
  52. // PARAMETERS:
  53. //
  54. // RETURN VALUE:
  55. //
  56. // COMMENTS:
  57. //
  58. BOOL CreateWatcherProcess()
  59. {
  60. BOOL bRet = FALSE;
  61. HANDLE hProcess;
  62. // open a handle to ourselves that the watcher process can inherit
  63. hProcess = OpenProcess(SYNCHRONIZE,
  64. TRUE,
  65. GetCurrentProcessId());
  66. if (hProcess)
  67. {
  68. TCHAR szWindir[MAX_PATH];
  69. if (GetSystemDirectory(szWindir, sizeof(szWindir)/sizeof(szWindir[0])))
  70. {
  71. TCHAR szCmdLine[MAX_PATH * 2];
  72. PROCESS_INFORMATION pi = {0};
  73. STARTUPINFO si = {0};
  74. si.cb = sizeof(si);
  75. wsprintf(szCmdLine, "\"%s\\rundll32.exe\" msconf.dll,CleanupNetMeetingDispDriver %ld", szWindir, HandleToLong(hProcess));
  76. if (CreateProcess(NULL,
  77. szCmdLine,
  78. NULL,
  79. NULL,
  80. TRUE, // we want the watcher to inherit hProcess, so we must set bInheritHandles = TRUE
  81. 0,
  82. NULL,
  83. NULL,
  84. &si,
  85. &pi))
  86. {
  87. bRet = TRUE;
  88. CloseHandle(pi.hThread);
  89. CloseHandle(pi.hProcess);
  90. }
  91. }
  92. CloseHandle(hProcess);
  93. }
  94. return bRet;
  95. }
  96. //
  97. // FUNCTION: MNMServiceStart
  98. //
  99. // PURPOSE: Actual code of the service
  100. // that does the work.
  101. //
  102. // PARAMETERS:
  103. // dwArgc - number of command line arguments
  104. // lpszArgv - array of command line arguments
  105. //
  106. // RETURN VALUE:
  107. // none
  108. //
  109. // COMMENTS:
  110. //
  111. VOID MNMServiceStart (DWORD dwArgc, LPTSTR *lpszArgv)
  112. {
  113. HRESULT hRet;
  114. BOOL fWaitForEvent = TRUE;
  115. DWORD dwResult;
  116. MSG msg;
  117. LPCTSTR lpServiceStopEvent = TEXT("ServiceStopEvent");
  118. LPCTSTR lpServiceBusyEvent = TEXT("ServiceBusyEvent");
  119. const int MaxWaitTime = 5;
  120. HANDLE hConfEvent;
  121. DWORD dwError = NO_ERROR;
  122. HANDLE hShuttingDown;
  123. int i;
  124. RegEntry Re( REMOTECONTROL_KEY, HKEY_LOCAL_MACHINE );
  125. // Initialization
  126. DBGINIT(&ghZone, rgZones);
  127. InitDebugModule(NMSRVC_TEXT);
  128. DebugEntry(MNMServiceStart);
  129. if (!Re.GetNumber(REMOTE_REG_RUNSERVICE, DEFAULT_REMOTE_RUNSERVICE))
  130. {
  131. TRACE_OUT(("Try to start mnmsrvc without no registry setting"));
  132. goto cleanup;
  133. }
  134. ///////////////////////////////////////////////////
  135. //
  136. // Service initialization
  137. //
  138. // report the status to the service control manager.
  139. //
  140. if (!ReportStatusToSCMgr( SERVICE_START_PENDING, NO_ERROR, 30000))
  141. {
  142. ERROR_OUT(("ReportStatusToSCMgr failed"));
  143. dwError = GetLastError();
  144. goto cleanup;
  145. }
  146. HANDLE pEventHandles[numEventHandles];
  147. // create the event object. The control handler function signals
  148. // this event when it receives the "stop" control code.
  149. //
  150. hServerStopEvent = CreateEvent(
  151. NULL, // no security attributes
  152. TRUE, // manual reset event
  153. FALSE, // not-signalled
  154. SERVICE_STOP_EVENT); // no name
  155. if ( hServerStopEvent == NULL)
  156. {
  157. ERROR_OUT(("CreateEvent failed"));
  158. dwError = GetLastError();
  159. goto cleanup;
  160. }
  161. pEventHandles[STOP_EVENT] = hServerStopEvent;
  162. hServerPauseEvent = CreateEvent(
  163. NULL,
  164. FALSE,
  165. FALSE,
  166. SERVICE_PAUSE_EVENT);
  167. if (hServerPauseEvent == NULL)
  168. {
  169. ERROR_OUT(("CreateEvent failed"));
  170. dwError = GetLastError();
  171. goto cleanup;
  172. }
  173. pEventHandles[PAUSE_EVENT] = hServerPauseEvent;
  174. hServerContinueEvent = CreateEvent(
  175. NULL,
  176. FALSE,
  177. FALSE,
  178. SERVICE_CONTINUE_EVENT);
  179. if (hServerContinueEvent == NULL)
  180. {
  181. ERROR_OUT(("CreateEvent failed"));
  182. dwError = GetLastError();
  183. goto cleanup;
  184. }
  185. pEventHandles[CONTINUE_EVENT] = hServerContinueEvent;
  186. CoInitialize(NULL);
  187. //
  188. // End of initialization
  189. //
  190. ////////////////////////////////////////////////////////
  191. // report the status to the service control manager.
  192. //
  193. if (!ReportStatusToSCMgr(
  194. SERVICE_RUNNING, // service state
  195. NO_ERROR, // exit code
  196. 0)) // wait hint
  197. {
  198. ERROR_OUT(("ReportStatusToSCMgr failed"));
  199. goto cleanup;
  200. }
  201. SetConsoleCtrlHandler(ServiceCtrlHandler, TRUE);
  202. CreateWatcherProcess();
  203. AddTaskbarIcon();
  204. ////////////////////////////////////////////////////////
  205. //
  206. // Service is now running, perform work until shutdown
  207. //
  208. if (IS_NT)
  209. {
  210. AddToMessageLog(EVENTLOG_INFORMATION_TYPE,
  211. 0,
  212. MSG_INF_START,
  213. NULL);
  214. }
  215. //
  216. // Check if the service should start up activated
  217. //
  218. if ( Re.GetNumber(REMOTE_REG_ACTIVATESERVICE,
  219. DEFAULT_REMOTE_ACTIVATESERVICE))
  220. {
  221. MNMServiceActivate();
  222. }
  223. else
  224. {
  225. if (!ReportStatusToSCMgr(
  226. SERVICE_PAUSED, // service state
  227. NO_ERROR, // exit code
  228. 0)) // wait hint
  229. {
  230. ERROR_OUT(("ReportStatusToSCMgr failed"));
  231. goto cleanup;
  232. }
  233. }
  234. while (fWaitForEvent)
  235. {
  236. dwResult = MsgWaitForMultipleObjects( numEventHandles,
  237. pEventHandles,
  238. FALSE,
  239. INFINITE,
  240. QS_ALLINPUT);
  241. switch (dwResult)
  242. {
  243. case WAIT_OBJECT_0 + numEventHandles:
  244. {
  245. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  246. {
  247. if (WM_QUIT != msg.message)
  248. {
  249. TranslateMessage(&msg);
  250. DispatchMessage(&msg);
  251. }
  252. else
  253. {
  254. TRACE_OUT(("received WM_QUIT"));
  255. fWaitForEvent = FALSE;
  256. break;
  257. }
  258. }
  259. break;
  260. }
  261. case WAIT_OBJECT_0 + PAUSE_EVENT:
  262. {
  263. if (STATE_ACTIVE == g_dwActiveState)
  264. {
  265. MNMServiceDeActivate();
  266. }
  267. ReportStatusToSCMgr( SERVICE_PAUSED, NO_ERROR, 0);
  268. break;
  269. }
  270. case WAIT_OBJECT_0 + CONTINUE_EVENT:
  271. {
  272. HANDLE hInit = OpenEvent(EVENT_ALL_ACCESS, FALSE, _TEXT("CONF:Init"));
  273. if (STATE_INACTIVE == g_dwActiveState && NULL == hInit)
  274. {
  275. MNMServiceActivate();
  276. }
  277. CloseHandle(hInit);
  278. ReportStatusToSCMgr( SERVICE_RUNNING, NO_ERROR, 0);
  279. break;
  280. }
  281. case WAIT_OBJECT_0 + STOP_EVENT:
  282. {
  283. RemoveTaskbarIcon();
  284. if (STATE_ACTIVE == g_dwActiveState)
  285. {
  286. MNMServiceDeActivate();
  287. }
  288. fWaitForEvent = FALSE;
  289. break;
  290. }
  291. }
  292. }
  293. cleanup:
  294. if ( STATE_ACTIVE == g_dwActiveState )
  295. {
  296. MNMServiceDeActivate();
  297. }
  298. if (hServerStopEvent)
  299. CloseHandle(hServerStopEvent);
  300. if (hServerPauseEvent)
  301. CloseHandle(hServerPauseEvent);
  302. if (hServerContinueEvent)
  303. CloseHandle(hServerContinueEvent);
  304. TRACE_OUT(("Reporting SERVICE_STOPPED"));
  305. ReportStatusToSCMgr( SERVICE_STOPPED, dwError, 0);
  306. DebugExitVOID(MNMServiceStart);
  307. CoUninitialize();
  308. DBGDEINIT(&ghZone);
  309. ExitDebugModule();
  310. }
  311. BOOL MNMServiceActivate ( VOID )
  312. {
  313. DebugEntry(MNMServiceActivate);
  314. if ( STATE_INACTIVE != g_dwActiveState )
  315. {
  316. WARNING_OUT(("MNMServiceActivate: g_dwActiveState:%d",
  317. g_dwActiveState));
  318. return FALSE;
  319. }
  320. g_dwActiveState = STATE_BUSY;
  321. if (!IS_NT)
  322. {
  323. ASSERT(NULL == hServerActiveEvent);
  324. hServerActiveEvent = CreateEvent(NULL, FALSE, FALSE, SERVICE_ACTIVE_EVENT);
  325. }
  326. HRESULT hRet = InitConfMgr();
  327. if (FAILED(hRet))
  328. {
  329. ERROR_OUT(("ERROR %x initializing nmmanger", hRet));
  330. FreeConfMgr();
  331. g_dwActiveState = STATE_INACTIVE;
  332. if (!IS_NT)
  333. {
  334. CloseHandle ( hServerActiveEvent );
  335. }
  336. DebugExitBOOL(MNMServiceActivate,FALSE);
  337. return FALSE;
  338. }
  339. if ( g_pNmSysInfo )
  340. {
  341. //
  342. // Attempt to initialize T.120 security, if this fails
  343. // bail out since we won't be able to receive any calls
  344. //
  345. if ( !InitT120Credentials() )
  346. {
  347. FreeConfMgr();
  348. g_dwActiveState = STATE_INACTIVE;
  349. if (!IS_NT)
  350. {
  351. CloseHandle ( hServerActiveEvent );
  352. }
  353. DebugExitBOOL(MNMServiceActivate,FALSE);
  354. return FALSE;
  355. }
  356. }
  357. g_dwActiveState = STATE_ACTIVE;
  358. DebugExitBOOL(MNMServiceActivate,TRUE);
  359. return TRUE;
  360. }
  361. BOOL MNMServiceDeActivate ( VOID )
  362. {
  363. DebugEntry(MNMServiceDeActivate);
  364. if (STATE_ACTIVE != g_dwActiveState)
  365. {
  366. WARNING_OUT(("MNMServiceDeActivate: g_dwActiveState:%d",
  367. g_dwActiveState));
  368. DebugExitBOOL(MNMServiceDeActivate,FALSE);
  369. return FALSE;
  370. }
  371. g_dwActiveState = STATE_BUSY;
  372. //
  373. // Leave Conference
  374. //
  375. if (NULL != g_pConference)
  376. {
  377. if (g_pNmSysInfo)
  378. {
  379. g_pNmSysInfo->ProcessSecurityData(UNLOADFTAPPLET,0,0,NULL);
  380. }
  381. if ( FAILED(g_pConference->Leave()))
  382. {
  383. ERROR_OUT(("Conference Leave failed"));;
  384. }
  385. }
  386. //
  387. // Free the conference
  388. //
  389. FreeConference();
  390. //
  391. // Free the AS interface
  392. //
  393. ASSERT(g_pAS);
  394. UINT ret = g_pAS->Release();
  395. g_pAS = NULL;
  396. TRACE_OUT(("AS interface freed, ref %d after Release", ret));
  397. // can we have a way not to create this event?
  398. HANDLE hevt = ::CreateEvent(NULL, FALSE, FALSE, NULL);
  399. ASSERT(NULL != hevt);
  400. const DWORD dwTimeout = 1000;
  401. DWORD dwStartTime = ::GetTickCount();
  402. DWORD dwCurrTimeout = dwTimeout;
  403. DWORD dwRet;
  404. BOOL fContinue = TRUE;
  405. while (fContinue && WAIT_OBJECT_0 != (dwRet = ::MsgWaitForMultipleObjects(1, &hevt, FALSE, dwCurrTimeout, QS_ALLINPUT)))
  406. {
  407. if (WAIT_TIMEOUT != dwRet)
  408. {
  409. DWORD dwCurrTime = ::GetTickCount();
  410. if (dwCurrTime < dwStartTime + dwTimeout)
  411. {
  412. dwCurrTimeout = dwStartTime + dwTimeout - dwCurrTime;
  413. MSG msg;
  414. while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  415. {
  416. if (WM_QUIT != msg.message)
  417. {
  418. ::TranslateMessage(&msg);
  419. ::DispatchMessage(&msg);
  420. }
  421. else
  422. {
  423. ::PostQuitMessage(0);
  424. fContinue = FALSE;
  425. }
  426. }
  427. continue;
  428. }
  429. // timeout here
  430. }
  431. // exit the loop
  432. break;
  433. }
  434. ::CloseHandle(hevt);
  435. // not to call FreeConfMfr imediately after FreeConference to avoid
  436. // a bug in t120 will remove this sleep call after fix the bug in t120
  437. FreeConfMgr();
  438. // BUGBUG remove h323cc.dll should be done in nmcom. Once the bug in nmcom is fixed, this part will be removed.
  439. HMODULE hmodH323CC = GetModuleHandle("h323cc.dll");
  440. if (hmodH323CC)
  441. {
  442. if (FreeLibrary(hmodH323CC))
  443. {
  444. TRACE_OUT(("CmdInActivate -- Unloaded h323cc.dll"));
  445. }
  446. else
  447. {
  448. WARNING_OUT(("CmdInActivate -- Failed to unload h323cc.dll %d", GetLastError()));
  449. }
  450. }
  451. if (!IS_NT)
  452. {
  453. ASSERT(hServerActiveEvent);
  454. if (hServerActiveEvent)
  455. {
  456. CloseHandle(hServerActiveEvent);
  457. hServerActiveEvent = NULL;
  458. }
  459. }
  460. g_dwActiveState = STATE_INACTIVE;
  461. DebugExitBOOL(MNMServiceDeActivate,TRUE);
  462. return TRUE;
  463. }
  464. //
  465. // FUNCTION: MNMServiceStop
  466. //
  467. // PURPOSE: Stops the service
  468. //
  469. // PARAMETERS:
  470. // none
  471. //
  472. // RETURN VALUE:
  473. // none
  474. //
  475. // COMMENTS:
  476. // If a ServiceStop procedure is going to
  477. // take longer than 3 seconds to execute,
  478. // it should spawn a thread to execute the
  479. // stop code, and return. Otherwise, the
  480. // ServiceControlManager will believe that
  481. // the service has stopped responding.
  482. //
  483. VOID MNMServiceStop()
  484. {
  485. DebugEntry(MNMServiceStop);
  486. RemoveTaskbarIcon();
  487. if ( hServerStopEvent )
  488. {
  489. TRACE_OUT(("MNMServiceStop: setting server stop event"));
  490. SetEvent(hServerStopEvent);
  491. }
  492. if (IS_NT)
  493. {
  494. AddToMessageLog(EVENTLOG_INFORMATION_TYPE,
  495. 0,
  496. MSG_INF_STOP,
  497. NULL);
  498. }
  499. DebugExitVOID(MNMServiceStop);
  500. }
  501. VOID MNMServicePause()
  502. {
  503. DebugEntry(MNMServicePause);
  504. if ( hServerPauseEvent )
  505. SetEvent(hServerPauseEvent);
  506. DebugExitVOID(MNMServicePause);
  507. }
  508. VOID MNMServiceContinue()
  509. {
  510. DebugEntry(MNMServiceContinue);
  511. if ( hServerContinueEvent )
  512. SetEvent(hServerContinueEvent);
  513. DebugExitVOID(MNMServiceContinue);
  514. }