/*++

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 ()

/*++

Routine Description:

    This routine stops the LPC thread and cleans up LPC-related resources.

Arguments:

    NONE

Return Value:

    NONE

--*/

{
    ElfDbgPrint(( "[ELF] Stop the LPC thread\n" ));

    //
    // Close communication port handle
    //

    NtClose ( ElfCommunicationPortHandle );

    //
    // Close connection port handle
    //

    NtClose ( ElfConnectionPortHandle );

    //
    // Terminate the LPC thread.
    //

    if (!TerminateThread(LPCThreadHandle,NO_ERROR)) {
        ElfDbgPrint(("[ELF] LPC Thread termination failed %d\n",GetLastError()));
    }
    CloseHandle ( LPCThreadHandle );

    return;
}




VOID
FreeModuleAndLogFileStructs ( )

/*++

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;

    ElfDbgPrint (("[ELF] Freeing module and log file structs\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
    //

    while (!IsListEmpty (&LogFilesHead) ) {

        pLogFile = (PLOGFILE)
            CONTAINING_RECORD(LogFilesHead.Flink, LOGFILE, FileList);

        Status = ElfpCloseLogFile ( pLogFile, ELF_LOG_CLOSE_NORMAL);

        UnlinkLogFile(pLogFile); // Unlink the structure
        RtlDeleteResource ( &pLogFile->Resource );
        ElfpFreeBuffer (pLogFile->LogFileName);
        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;


    ElfDbgPrint (("[ELF] ElfpCleanUp.\n"));

    //
    // Notify the Service Controller for the first time that we are
    // about to stop the service.
    //
    // *** STATUS UPDATE ***
    ElfStatusUpdate(STOPPING);


    //
    // Stop the RPC Server
    //
    if (EventFlags & ELF_STARTED_RPC_SERVER) {
        ElfDbgPrint (("[ELF] Stopping the RPC Server.\n"));

        status = ElfGlobalData->StopRpcServer(eventlog_ServerIfHandle);
        if (status != NO_ERROR) {
            ElfDbgPrint (("[ELF] Stopping RpcServer Failed %d\n",status));
        }
    }

    //
    // Stop the LPC thread
    //
    if (EventFlags & ELF_STARTED_LPC_THREAD)
        StopLPCThread();

    //
    // Tell service controller that we are making progress
    //
    // *** STATUS UPDATE ***
    ElfStatusUpdate(STOPPING);

    //
    // Flush all the log files to disk.
    //
    ElfDbgPrint (("[ELF] Flushing Files.\n"));
    ElfpFlushFiles();

    //
    // Tell service controller that we are making progress
    //
    ElfStatusUpdate(STOPPING);

    //
    // Clean up any resources that were allocated
    //
    FreeModuleAndLogFileStructs();

    //
    // Free up memory
    //

    if (LocalComputerName) {
        ElfpFreeBuffer(LocalComputerName);
    }

    //
    // If we queued up any events, flush them
    //

    ElfDbgPrint (("[ELF] Flushing QueuedEvents.\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_LOGHANDLE_CRIT_SEC)
        RtlDeleteCriticalSection((PRTL_CRITICAL_SECTION)&LogHandleCritSec);

    if (EventFlags & ELF_INIT_LOGFILE_CRIT_SEC)
        RtlDeleteCriticalSection((PRTL_CRITICAL_SECTION)&LogFileCritSec);

    if (EventFlags & ELF_INIT_QUEUED_EVENT_CRIT_SEC)
        RtlDeleteCriticalSection((PRTL_CRITICAL_SECTION)&QueuedEventCritSec);

    // *** STATUS UPDATE ***
    ElfDbgPrint(("[ELF] Leaving the Eventlog service\n"));
    ElfStatusUpdate(STOPPED);
    ElCleanupStatus();
    return;
}
