/*
 * Copyright (c) Likewise Software.  All rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.  You should have received a copy of the GNU General
 * Public License along with this program.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING
 * TERMS AS WELL.  IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT
 * WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE
 * TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU
 * GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE.  IF YOU
 * HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING
 * TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT
 * license@likewisesoftware.com
 */

/*
 * Module Name:
 *
 *        eventlog.c
 *
 * Abstract:
 *
 *        Event log glue
 *
 * Authors: Brian Koropoff (bkoropoff@likewise.com)
 *
 */

#include "includes.h"

#ifdef HAVE_EVENTLOG_H
typedef struct _LOG_CONTEXT
{
    LW_RTL_EVENTLOG_COMPLETE_CALLBACK Complete;
    PVOID pContext;
} LOG_CONTEXT, *PLOG_CONTEXT;

PLW_EVENTLOG_CONNECTION gpConn = NULL;

static
VOID
LwSmEventlogComplete(
    PVOID pContext,
    DWORD Error
    )
{
    PLOG_CONTEXT pLog = pContext;
    pLog->Complete(pLog->pContext, LwWin32ErrorToNtStatus(Error));
    LwRtlMemoryFree(pLog);
}

static
NTSTATUS
LwSmEventlogPostCallback(
    ULONG RecordCount,
    PLW_RTL_EVENTLOG_RECORD pRecords,
    LW_RTL_EVENTLOG_COMPLETE_CALLBACK Complete,
    PVOID pContext
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    DWORD error = ERROR_SUCCESS;
    PLOG_CONTEXT pLog = NULL;

    if (Complete)
    {
        status = LW_RTL_ALLOCATE(&pLog, LOG_CONTEXT, sizeof(*pLog));
        BAIL_ON_ERROR(status);

        pLog->Complete = Complete;
        pLog->pContext = pContext;

        error = LwEvtWriteRecordsAsync(gpConn, RecordCount, pRecords, LwSmEventlogComplete, pLog);
    }
    else
    {
        error = LwEvtWriteRecords(gpConn, RecordCount, pRecords);
    }
    status = LwWin32ErrorToNtStatus(error);
    BAIL_ON_ERROR(status);

error:

    if (status != STATUS_PENDING && pLog)
    {
        LwRtlMemoryFree(pLog);
    }

    return status;
}

static
NTSTATUS
LwSmEventlogRegisterCallback(
    LW_IN LW_PCGUID pGuid,
    LW_IN LW_RTL_EVENTLOG_TYPE_INFO_FORMAT Format,
    LW_IN PLW_RTL_EVENTLOG_TYPE_INFO pTypeInfo
    )
{
    return LwWin32ErrorToNtStatus(LwEvtRegisterEventType(pGuid, Format, pTypeInfo));
}

DWORD
LwSmEventlogInit(
    VOID
    )
{
    DWORD error = ERROR_SUCCESS;

    error = LwEvtOpenEventlog(NULL, &gpConn);
    BAIL_ON_ERROR(error);

    error = LwNtStatusToWin32Error(LwRtlEventlogSetCallbacks(LwSmEventlogPostCallback, LwSmEventlogRegisterCallback));
    BAIL_ON_ERROR(error);

error:

    return error;
}

VOID
LwSmEventlogShutdown(
    VOID
    )
{
    if (gpConn)
    {
        LwEvtCloseEventlog(gpConn);
        gpConn = NULL;
    }
}
#else
DWORD
LwSmEventlogInit(
    VOID
    )
{
    DWORD error = ERROR_SUCCESS;

    return error;
}

VOID
LwSmEventlogShutdown(
    VOID
    )
{
}
#endif
