/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#if (defined(WIN32) || defined(_WIN32)) && !defined(_WIN32_WCE)

#include <apr_strings.h>

#include <log4cxx/nt/nteventlogappender.h>
#include <log4cxx/spi/loggingevent.h>
#include <log4cxx/helpers/loglog.h>
#include <log4cxx/level.h>
#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/helpers/transcoder.h>
#include <log4cxx/helpers/pool.h>

using namespace log4cxx;
using namespace log4cxx::spi;
using namespace log4cxx::helpers;
using namespace log4cxx::nt;

class CCtUserSIDHelper
{
    public:
        static bool FreeSid(SID* pSid)
        {
            return ::HeapFree(GetProcessHeap(), 0, (LPVOID)pSid) != 0;
        }

        static bool CopySid(SID * * ppDstSid, SID* pSrcSid)
        {
            bool bSuccess = false;

            DWORD dwLength = ::GetLengthSid(pSrcSid);
            *ppDstSid = (SID*) ::HeapAlloc(GetProcessHeap(),
                                           HEAP_ZERO_MEMORY, dwLength);

            if (::CopySid(dwLength, *ppDstSid, pSrcSid))
            {
                bSuccess = true;
            }
            else
            {
                FreeSid(*ppDstSid);
            }

            return bSuccess;
        }

        static bool GetCurrentUserSID(SID * * ppSid)
        {
            bool bSuccess = false;

            // Pseudohandle so don't need to close it
            HANDLE hProcess = ::GetCurrentProcess();
            HANDLE hToken = NULL;

            if (::OpenProcessToken(hProcess, TOKEN_QUERY, &hToken))
            {
                // Get the required size
                DWORD tusize = 0;
                GetTokenInformation(hToken, TokenUser, NULL, 0, &tusize);
                TOKEN_USER* ptu = (TOKEN_USER*)new BYTE[tusize];

                if (GetTokenInformation(hToken, TokenUser, (LPVOID)ptu, tusize, &tusize))
                {
                    bSuccess = CopySid(ppSid, (SID*)ptu->User.Sid);
                }

                CloseHandle(hToken);
                delete [] ptu;
            }

            return bSuccess;
        }
};

IMPLEMENT_LOG4CXX_OBJECT(NTEventLogAppender)

NTEventLogAppender::NTEventLogAppender() : hEventLog(NULL), pCurrentUserSID(NULL)
{
}

NTEventLogAppender::NTEventLogAppender(const LogString& server, const LogString& log, const LogString& source, const LayoutPtr& layout)
    : server(server), log(log), source(source), hEventLog(NULL), pCurrentUserSID(NULL)
{
    this->layout = layout;
    Pool pool;
    activateOptions(pool);
}

NTEventLogAppender::~NTEventLogAppender()
{
    finalize();
}


void NTEventLogAppender::close()
{
    if (hEventLog != NULL)
    {
        ::DeregisterEventSource(hEventLog);
        hEventLog = NULL;
    }

    if (pCurrentUserSID != NULL)
    {
        CCtUserSIDHelper::FreeSid((::SID*) pCurrentUserSID);
        pCurrentUserSID = NULL;
    }
}

void NTEventLogAppender::setOption(const LogString& option, const LogString& value)
{
    if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("SERVER"), LOG4CXX_STR("server")))
    {
        server = value;
    }
    else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("LOG"), LOG4CXX_STR("log")))
    {
        log = value;
    }
    else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("SOURCE"), LOG4CXX_STR("source")))
    {
        source = value;
    }
    else
    {
        AppenderSkeleton::setOption(option, value);
    }
}

void NTEventLogAppender::activateOptions(Pool&)
{
    if (source.empty())
    {
        LogLog::warn(
            ((LogString) LOG4CXX_STR("Source option not set for appender ["))
            + name + LOG4CXX_STR("]."));
        return;
    }

    if (log.empty())
    {
        log = LOG4CXX_STR("Application");
    }

    close();

    // current user security identifier
    CCtUserSIDHelper::GetCurrentUserSID((::SID**) &pCurrentUserSID);

    addRegistryInfo();

    LOG4CXX_ENCODE_WCHAR(wsource, source);
    LOG4CXX_ENCODE_WCHAR(wserver, server);
    hEventLog = ::RegisterEventSourceW(
                    wserver.empty() ? NULL : wserver.c_str(),
                    wsource.c_str());

    if (hEventLog == NULL)
    {
        LogString msg(LOG4CXX_STR("Cannot register NT EventLog -- server: '"));
        msg.append(server);
        msg.append(LOG4CXX_STR("' source: '"));
        msg.append(source);
        LogLog::error(msg);
        LogLog::error(getErrorString(LOG4CXX_STR("RegisterEventSource")));
    }
}

void NTEventLogAppender::append(const LoggingEventPtr& event, Pool& p)
{
    if (hEventLog == NULL)
    {
        LogLog::warn(LOG4CXX_STR("NT EventLog not opened."));
        return;
    }

    LogString oss;
    layout->format(oss, event, p);
    wchar_t* msgs = Transcoder::wencode(oss, p);
    BOOL bSuccess = ::ReportEventW(
                        hEventLog,
                        getEventType(event),
                        getEventCategory(event),
                        0x1000,
                        pCurrentUserSID,
                        1,
                        0,
                        (LPCWSTR*) &msgs,
                        NULL);

    if (!bSuccess)
    {
        LogLog::error(getErrorString(LOG4CXX_STR("ReportEvent")));
    }
}

/*
 * Add this source with appropriate configuration keys to the registry.
 */
void NTEventLogAppender::addRegistryInfo()
{
    DWORD disposition = 0;
    ::HKEY hkey = 0;
    LogString subkey(LOG4CXX_STR("SYSTEM\\CurrentControlSet\\Services\\EventLog\\"));
    subkey.append(log);
    subkey.append(1, (logchar) 0x5C /* '\\' */);
    subkey.append(source);
    LOG4CXX_ENCODE_WCHAR(wsubkey, subkey);

    long stat = RegCreateKeyExW(HKEY_LOCAL_MACHINE, wsubkey.c_str(), 0, NULL,
                                REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL,
                                &hkey, &disposition);

    if (stat == ERROR_SUCCESS && disposition == REG_CREATED_NEW_KEY)
    {
        HMODULE hmodule = GetModuleHandleW(L"log4cxx");

        if (hmodule == NULL)
        {
            hmodule = GetModuleHandleW(0);
        }

        wchar_t modpath[_MAX_PATH];
        DWORD modlen = GetModuleFileNameW(hmodule, modpath, _MAX_PATH - 1);

        if (modlen > 0)
        {
            modpath[modlen] = 0;
            RegSetValueExW(hkey, L"EventMessageFile", 0, REG_SZ,
                           (LPBYTE) modpath, wcslen(modpath) * sizeof(wchar_t));
            RegSetValueExW(hkey, L"CategoryMessageFile", 0, REG_SZ,
                           (LPBYTE) modpath, wcslen(modpath) * sizeof(wchar_t));
            DWORD typesSupported = 7;
            DWORD categoryCount = 6;
            RegSetValueExW(hkey, L"TypesSupported", 0, REG_DWORD,
                           (LPBYTE)&typesSupported, sizeof(DWORD));
            RegSetValueExW(hkey, L"CategoryCount", 0, REG_DWORD,
                           (LPBYTE)&categoryCount, sizeof(DWORD));
        }
    }

    RegCloseKey(hkey);
    return;
}

WORD NTEventLogAppender::getEventType(const LoggingEventPtr& event)
{
    int priority = event->getLevel()->toInt();
    WORD type = EVENTLOG_SUCCESS;

    if (priority >= Level::INFO_INT)
    {
        type = EVENTLOG_INFORMATION_TYPE;

        if (priority >= Level::WARN_INT)
        {
            type = EVENTLOG_WARNING_TYPE;

            if (priority >= Level::ERROR_INT)
            {
                type = EVENTLOG_ERROR_TYPE;
            }
        }
    }

    return type;
}

WORD NTEventLogAppender::getEventCategory(const LoggingEventPtr& event)
{
    int priority = event->getLevel()->toInt();
    WORD category = 1;

    if (priority >= Level::DEBUG_INT)
    {
        category = 2;

        if (priority >= Level::INFO_INT)
        {
            category = 3;

            if (priority >= Level::WARN_INT)
            {
                category = 4;

                if (priority >= Level::ERROR_INT)
                {
                    category = 5;

                    if (priority >= Level::FATAL_INT)
                    {
                        category = 6;
                    }
                }
            }
        }
    }

    return category;
}

LogString NTEventLogAppender::getErrorString(const LogString& function)
{
    Pool p;
    enum { MSGSIZE = 5000 };

    wchar_t* lpMsgBuf = (wchar_t*) p.palloc(MSGSIZE * sizeof(wchar_t));
    DWORD dw = GetLastError();

    FormatMessageW(
        FORMAT_MESSAGE_FROM_SYSTEM,
        NULL,
        dw,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        lpMsgBuf,
        MSGSIZE, NULL );

    LogString msg(function);
    msg.append(LOG4CXX_STR(" failed with error "));
    StringHelper::toString((size_t) dw, p, msg);
    msg.append(LOG4CXX_STR(": "));
    Transcoder::decode(lpMsgBuf, msg);

    return msg;
}

#endif // WIN32
