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.

365 lines
8.1 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. TERMINAT.C
  5. Abstract:
  6. This file contains all the cleanup routines for the Eventlog service.
  7. These routines are called when the service is terminating.
  8. Author:
  9. Rajen Shah (rajens) 09-Aug-1991
  10. Revision History:
  11. --*/
  12. //
  13. // INCLUDES
  14. //
  15. #include <eventp.h>
  16. #include <ntrpcp.h>
  17. #include <elfcfg.h>
  18. PORT_MESSAGE TerminateMsg;
  19. VOID
  20. StopLPCThread(
  21. VOID
  22. )
  23. /*++
  24. Routine Description:
  25. This routine stops the LPC thread and cleans up LPC-related resources.
  26. Arguments:
  27. NONE
  28. Return Value:
  29. NONE
  30. --*/
  31. {
  32. NTSTATUS status;
  33. BOOL bThreadExitedGracefully = FALSE;
  34. ELF_LOG0(TRACE,
  35. "StopLpcThread: Clean up LPC thread and global data\n");
  36. // Terminate the LPC thread. Send it a stop message
  37. TerminateMsg.u1.s1.DataLength = 0;
  38. TerminateMsg.u1.s1.TotalLength = sizeof(PORT_MESSAGE);
  39. TerminateMsg.u2.s2.Type = 0;
  40. status = NtRequestPort(
  41. ElfConnectionPortHandle,
  42. &TerminateMsg);
  43. if(NT_SUCCESS(status))
  44. {
  45. DWORD dwRet = WaitForSingleObject(LPCThreadHandle, 10000);
  46. if(dwRet == WAIT_OBJECT_0)
  47. bThreadExitedGracefully = TRUE;
  48. }
  49. //
  50. // Close communication port handle
  51. //
  52. /// NtClose(ElfCommunicationPortHandle);
  53. //
  54. // Close connection port handle
  55. //
  56. NtClose(ElfConnectionPortHandle);
  57. //
  58. // Terminate the LPC thread.
  59. //
  60. if(!bThreadExitedGracefully)
  61. {
  62. if (!TerminateThread(LPCThreadHandle, NO_ERROR))
  63. {
  64. ELF_LOG1(ERROR,
  65. "StopLpcThread: TerminateThread failed %d\n",
  66. GetLastError());
  67. }
  68. }
  69. CloseHandle(LPCThreadHandle);
  70. return;
  71. }
  72. VOID
  73. FreeModuleAndLogFileStructs(
  74. VOID
  75. )
  76. /*++
  77. Routine Description:
  78. This routine walks the module and log file list and frees all the
  79. data structures.
  80. Arguments:
  81. NONE
  82. Return Value:
  83. NONE
  84. Note:
  85. The file header and ditry bits must have been dealt with before
  86. this routine is called. Also, the file must have been unmapped and
  87. the handle closed.
  88. --*/
  89. {
  90. NTSTATUS Status;
  91. PLOGMODULE pModule;
  92. PLOGFILE pLogFile;
  93. ELF_LOG0(TRACE,
  94. "FreeModuleAndLogFileStructs: Emptying log module list\n");
  95. //
  96. // First free all the modules
  97. //
  98. while (!IsListEmpty(&LogModuleHead))
  99. {
  100. pModule = (PLOGMODULE) CONTAINING_RECORD(LogModuleHead.Flink, LOGMODULE, ModuleList);
  101. UnlinkLogModule(pModule); // Remove from linked list
  102. ElfpFreeBuffer (pModule); // Free module memory
  103. }
  104. //
  105. // Now free all the logfiles
  106. //
  107. ELF_LOG0(TRACE,
  108. "FreeModuleAndLogFileStructs: Emptying log file list\n");
  109. while (!IsListEmpty(&LogFilesHead))
  110. {
  111. pLogFile = (PLOGFILE) CONTAINING_RECORD(LogFilesHead.Flink, LOGFILE, FileList);
  112. Status = ElfpCloseLogFile(pLogFile, ELF_LOG_CLOSE_NORMAL, TRUE);
  113. if (!NT_SUCCESS(Status))
  114. {
  115. ELF_LOG2(FILES,
  116. "FreeModuleAndLogFileStructs: ElfpCloseLogFile on %ws failed %#x\n",
  117. pLogFile->LogModuleName->Buffer,
  118. Status);
  119. }
  120. }
  121. }
  122. VOID
  123. ElfpCleanUp (
  124. ULONG EventFlags
  125. )
  126. /*++
  127. Routine Description:
  128. This routine cleans up before the service terminates. It cleans up
  129. based on the parameter passed in (which indicates what has been allocated
  130. and/or started.
  131. Arguments:
  132. Bit-mask indicating what needs to be cleaned up.
  133. Return Value:
  134. NONE
  135. Note:
  136. It is expected that the RegistryMonitor has already
  137. been notified of Shutdown prior to calling this routine.
  138. --*/
  139. {
  140. DWORD status = NO_ERROR;
  141. //
  142. // Notify the Service Controller for the first time that we are
  143. // about to stop the service.
  144. //
  145. ElfStatusUpdate(STOPPING);
  146. ELF_LOG0(TRACE, "ElfpCleanUp: Cleaning up so service can exit\n");
  147. //
  148. // Give the ElfpSendMessage thread a 1 second chance to exit before
  149. // we free the QueuedMessageCritSec critical section
  150. //
  151. if( MBThreadHandle != NULL )
  152. {
  153. ELF_LOG0(TRACE, "ElfpCleanUp: Waiting for ElfpSendMessage thread to exit\n");
  154. status = WaitForSingleObject(MBThreadHandle, 1000);
  155. if (status != WAIT_OBJECT_0)
  156. {
  157. ELF_LOG1(ERROR,
  158. "ElfpCleanUp: NtWaitForSingleObject status = %d\n",
  159. status);
  160. }
  161. }
  162. //
  163. // Stop the RPC Server
  164. //
  165. if (EventFlags & ELF_STARTED_RPC_SERVER)
  166. {
  167. ELF_LOG0(TRACE,
  168. "ElfpCleanUp: Stopping the RPC server\n");
  169. status = ElfGlobalData->StopRpcServer(eventlog_ServerIfHandle);
  170. if (status != NO_ERROR)
  171. {
  172. ELF_LOG1(ERROR,
  173. "ElfpCleanUp: StopRpcServer failed %d\n",
  174. status);
  175. }
  176. }
  177. //
  178. // Stop the LPC thread
  179. //
  180. if (EventFlags & ELF_STARTED_LPC_THREAD)
  181. {
  182. StopLPCThread();
  183. }
  184. //
  185. // Tell service controller that we are making progress
  186. //
  187. ElfStatusUpdate(STOPPING);
  188. //
  189. // Flush all the log files to disk.
  190. //
  191. ELF_LOG0(TRACE,
  192. "ElfpCleanUp: Flushing log files\n");
  193. ElfpFlushFiles(TRUE);
  194. //
  195. // Tell service controller that we are making progress
  196. //
  197. ElfStatusUpdate(STOPPING);
  198. //
  199. // Clean up any resources that were allocated
  200. //
  201. FreeModuleAndLogFileStructs();
  202. //
  203. // If we queued up any events, flush them
  204. //
  205. ELF_LOG0(TRACE,
  206. "ElfpCleanUp: Flushing queued events\n");
  207. if (EventFlags & ELF_INIT_QUEUED_EVENT_CRIT_SEC)
  208. FlushQueuedEvents();
  209. //
  210. // Tell service controller of that we are making progress
  211. //
  212. ElfStatusUpdate(STOPPING);
  213. if (EventFlags & ELF_INIT_GLOBAL_RESOURCE)
  214. {
  215. RtlDeleteResource(&GlobalElfResource);
  216. }
  217. if (EventFlags & ELF_INIT_CLUS_CRIT_SEC)
  218. {
  219. #if 0
  220. //
  221. // Chittur Subbaraman (chitturs) - 09/25/2001
  222. //
  223. // We can't handle the critsec deletion without adding code here to delete the timer
  224. // thread spawned for batching support (ElfpBatchEventsAndPropagate). If we call
  225. // DeleteTimerQueueTimer from here which will fully block until that timer thread
  226. // goes away, we introduce a dependency on the eventlog service shutdown on the
  227. // quick disappearence of the timer thread which may not happen (since ApiPropPendingEvents
  228. // is hung because clussvc is in the debugger). So, since the eventlog service cannot be
  229. // stopped by the user and can be stopped only by SCM on windows shutdown, it is not worth
  230. // waiting here just to delete the gClPropCritsec.
  231. //
  232. RtlDeleteCriticalSection(&gClPropCritSec);
  233. #endif
  234. }
  235. if (EventFlags & ELF_INIT_LOGHANDLE_CRIT_SEC)
  236. {
  237. RtlDeleteCriticalSection(&LogHandleCritSec);
  238. }
  239. if (EventFlags & ELF_INIT_QUEUED_MESSAGE_CRIT_SEC)
  240. {
  241. RtlDeleteCriticalSection(&QueuedMessageCritSec);
  242. }
  243. if (EventFlags & ELF_INIT_QUEUED_EVENT_CRIT_SEC)
  244. {
  245. RtlDeleteCriticalSection(&QueuedEventCritSec);
  246. }
  247. if (EventFlags & ELF_INIT_LOGMODULE_CRIT_SEC)
  248. {
  249. RtlDeleteCriticalSection(&LogModuleCritSec);
  250. }
  251. if (EventFlags & ELF_INIT_LOGFILE_CRIT_SEC)
  252. {
  253. #if 0
  254. //
  255. // Same comment as above
  256. //
  257. RtlDeleteCriticalSection(&LogFileCritSec);
  258. #endif
  259. }
  260. if(GlobalMessageBoxTitle && bGlobalMessageBoxTitleNeedFree)
  261. LocalFree(GlobalMessageBoxTitle);
  262. GlobalMessageBoxTitle = NULL;
  263. //
  264. // *** STATUS UPDATE ***
  265. //
  266. ELF_LOG0(TRACE,
  267. "ElfpCleanUp: The Eventlog service has left the building\n");
  268. ElfStatusUpdate(STOPPED);
  269. ElCleanupStatus();
  270. return;
  271. }