windows-nt/Source/XPSP1/NT/base/eventlog/server/terminat.c
2020-09-26 16:20:57 +08:00

327 lines
6.3 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
TERMINAT.C
Abstract:
This file contains all the cleanup routines for the Eventlog service.
These routines are called when the service is terminating.
Author:
Rajen Shah (rajens) 09-Aug-1991
Revision History:
--*/
//
// INCLUDES
//
#include <eventp.h>
#include <ntrpcp.h>
VOID
StopLPCThread(
VOID
)
/*++
Routine Description:
This routine stops the LPC thread and cleans up LPC-related resources.
Arguments:
NONE
Return Value:
NONE
--*/
{
ELF_LOG0(TRACE,
"StopLpcThread: Clean up LPC thread and global data\n");
//
// Close communication port handle
//
NtClose(ElfCommunicationPortHandle);
//
// Close connection port handle
//
NtClose(ElfConnectionPortHandle);
//
// Terminate the LPC thread.
//
if (!TerminateThread(LPCThreadHandle, NO_ERROR))
{
ELF_LOG1(ERROR,
"StopLpcThread: TerminateThread failed %d\n",
GetLastError());
}
CloseHandle(LPCThreadHandle);
return;
}
VOID
FreeModuleAndLogFileStructs(
VOID
)
/*++
Routine Description:
This routine walks the module and log file list and frees all the
data structures.
Arguments:
NONE
Return Value:
NONE
Note:
The file header and ditry bits must have been dealt with before
this routine is called. Also, the file must have been unmapped and
the handle closed.
--*/
{
NTSTATUS Status;
PLOGMODULE pModule;
PLOGFILE pLogFile;
ELF_LOG0(TRACE,
"FreeModuleAndLogFileStructs: Emptying log module list\n");
//
// First free all the modules
//
while (!IsListEmpty(&LogModuleHead))
{
pModule = (PLOGMODULE) CONTAINING_RECORD(LogModuleHead.Flink, LOGMODULE, ModuleList);
UnlinkLogModule(pModule); // Remove from linked list
ElfpFreeBuffer (pModule); // Free module memory
}
//
// Now free all the logfiles
//
ELF_LOG0(TRACE,
"FreeModuleAndLogFileStructs: Emptying log file list\n");
while (!IsListEmpty(&LogFilesHead))
{
pLogFile = (PLOGFILE) CONTAINING_RECORD(LogFilesHead.Flink, LOGFILE, FileList);
Status = ElfpCloseLogFile(pLogFile, ELF_LOG_CLOSE_NORMAL);
if (!NT_SUCCESS(Status))
{
ELF_LOG2(FILES,
"FreeModuleAndLogFileStructs: ElfpCloseLogFile on %ws failed %#x\n",
pLogFile->LogModuleName->Buffer,
Status);
}
UnlinkLogFile(pLogFile);
RtlDeleteResource(&pLogFile->Resource);
ElfpFreeBuffer(pLogFile->LogFileName);
ElfpFreeBuffer(pLogFile->LogModuleName);
ElfpFreeBuffer(pLogFile);
}
}
VOID
ElfpCleanUp (
ULONG EventFlags
)
/*++
Routine Description:
This routine cleans up before the service terminates. It cleans up
based on the parameter passed in (which indicates what has been allocated
and/or started.
Arguments:
Bit-mask indicating what needs to be cleaned up.
Return Value:
NONE
Note:
It is expected that the RegistryMonitor has already
been notified of Shutdown prior to calling this routine.
--*/
{
DWORD status = NO_ERROR;
//
// Notify the Service Controller for the first time that we are
// about to stop the service.
//
ElfStatusUpdate(STOPPING);
ELF_LOG0(TRACE, "ElfpCleanUp: Cleaning up so service can exit\n");
//
// Give the ElfpSendMessage thread a 1 second chance to exit before
// we free the QueuedMessageCritSec critical section
//
if( MBThreadHandle != NULL )
{
ELF_LOG0(TRACE, "ElfpCleanUp: Waiting for ElfpSendMessage thread to exit\n");
status = WaitForSingleObject(MBThreadHandle, 1000);
if (status != WAIT_OBJECT_0)
{
ELF_LOG1(ERROR,
"ElfpCleanUp: NtWaitForSingleObject status = %d\n",
status);
}
}
//
// Stop the RPC Server
//
if (EventFlags & ELF_STARTED_RPC_SERVER)
{
ELF_LOG0(TRACE,
"ElfpCleanUp: Stopping the RPC server\n");
status = ElfGlobalData->StopRpcServer(eventlog_ServerIfHandle);
if (status != NO_ERROR)
{
ELF_LOG1(ERROR,
"ElfpCleanUp: StopRpcServer failed %d\n",
status);
}
}
//
// Stop the LPC thread
//
if (EventFlags & ELF_STARTED_LPC_THREAD)
{
StopLPCThread();
}
//
// Tell service controller that we are making progress
//
ElfStatusUpdate(STOPPING);
//
// Flush all the log files to disk.
//
ELF_LOG0(TRACE,
"ElfpCleanUp: Flushing log files\n");
ElfpFlushFiles();
//
// Tell service controller that we are making progress
//
ElfStatusUpdate(STOPPING);
//
// Clean up any resources that were allocated
//
FreeModuleAndLogFileStructs();
//
// If we queued up any events, flush them
//
ELF_LOG0(TRACE,
"ElfpCleanUp: Flushing queued events\n");
FlushQueuedEvents();
//
// Tell service controller of that we are making progress
//
ElfStatusUpdate(STOPPING);
if (EventFlags & ELF_INIT_GLOBAL_RESOURCE)
{
RtlDeleteResource(&GlobalElfResource);
}
if (EventFlags & ELF_INIT_CLUS_CRIT_SEC)
{
RtlDeleteCriticalSection(&gClPropCritSec);
}
if (EventFlags & ELF_INIT_LOGHANDLE_CRIT_SEC)
{
RtlDeleteCriticalSection(&LogHandleCritSec);
}
if (EventFlags & ELF_INIT_QUEUED_MESSAGE_CRIT_SEC)
{
RtlDeleteCriticalSection(&QueuedMessageCritSec);
}
if (EventFlags & ELF_INIT_QUEUED_EVENT_CRIT_SEC)
{
RtlDeleteCriticalSection(&QueuedEventCritSec);
}
if (EventFlags & ELF_INIT_LOGMODULE_CRIT_SEC)
{
RtlDeleteCriticalSection(&LogModuleCritSec);
}
if (EventFlags & ELF_INIT_LOGFILE_CRIT_SEC)
{
RtlDeleteCriticalSection(&LogFileCritSec);
}
LocalFree(GlobalMessageBoxTitle);
GlobalMessageBoxTitle = NULL;
//
// *** STATUS UPDATE ***
//
ELF_LOG0(TRACE,
"ElfpCleanUp: The Eventlog service has left the building\n");
ElfStatusUpdate(STOPPED);
ElCleanupStatus();
return;
}