/*
 * Configuration file parsing
 *
 * Copyright 2010 Vincent Povirk
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#define COBJMACROS

#include <stdarg.h>

#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "ole2.h"
#include "msxml2.h"
#include "mscoree.h"
#include "corhdr.h"
#include "metahost.h"
#include "cordebug.h"
#include "wine/list.h"
#include "mscoree_private.h"
#include "shlwapi.h"

#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL( mscoree );

enum parse_state
{
    STATE_ASSEMBLY_BINDING,
    STATE_ROOT,
    STATE_CONFIGURATION,
    STATE_PROBING,
    STATE_RUNTIME,
    STATE_STARTUP,
    STATE_UNKNOWN
};

typedef struct ConfigFileHandler
{
    ISAXContentHandler ISAXContentHandler_iface;
    ISAXErrorHandler ISAXErrorHandler_iface;
    LONG ref;
    enum parse_state states[16];
    int statenum;
    parsed_config_file *result;
} ConfigFileHandler;

static inline ConfigFileHandler *impl_from_ISAXContentHandler(ISAXContentHandler *iface)
{
    return CONTAINING_RECORD(iface, ConfigFileHandler, ISAXContentHandler_iface);
}

static inline ConfigFileHandler *impl_from_ISAXErrorHandler(ISAXErrorHandler *iface)
{
    return CONTAINING_RECORD(iface, ConfigFileHandler, ISAXErrorHandler_iface);
}

static HRESULT WINAPI ConfigFileHandler_QueryInterface(ISAXContentHandler *iface,
    REFIID riid, void **ppvObject)
{
    if (IsEqualGUID(riid, &IID_ISAXContentHandler) ||
        IsEqualGUID(riid, &IID_IUnknown))
    {
        *ppvObject = iface;
    }
    else
    {
        WARN("Unsupported interface %s\n", debugstr_guid(riid));
        return E_NOINTERFACE;
    }

    ISAXContentHandler_AddRef(iface);

    return S_OK;
}

static ULONG WINAPI ConfigFileHandler_AddRef(ISAXContentHandler *iface)
{
    ConfigFileHandler *This = impl_from_ISAXContentHandler(iface);
    return InterlockedIncrement(&This->ref);
}

static ULONG WINAPI ConfigFileHandler_Release(ISAXContentHandler *iface)
{
    ConfigFileHandler *This = impl_from_ISAXContentHandler(iface);
    ULONG ref = InterlockedDecrement(&This->ref);

    if (ref == 0)
        HeapFree(GetProcessHeap(), 0, This);

    return ref;
}

static HRESULT WINAPI ConfigFileHandler_putDocumentLocator(ISAXContentHandler *iface,
    ISAXLocator *pLocator)
{
    return S_OK;
}

static HRESULT WINAPI ConfigFileHandler_startDocument(ISAXContentHandler *iface)
{
    return S_OK;
}

static HRESULT WINAPI ConfigFileHandler_endDocument(ISAXContentHandler *iface)
{
    return S_OK;
}

static HRESULT WINAPI ConfigFileHandler_startPrefixMapping(ISAXContentHandler *iface,
    const WCHAR *pPrefix, int nPrefix, const WCHAR *pUri, int nUri)
{
    return S_OK;
}

static HRESULT WINAPI ConfigFileHandler_endPrefixMapping(ISAXContentHandler *iface,
    const WCHAR *pPrefix, int nPrefix)
{
    return S_OK;
}

static HRESULT parse_startup(ConfigFileHandler *This, ISAXAttributes *pAttr)
{
    static const WCHAR legacy[] = {'u','s','e','L','e','g','a','c','y','V','2','R','u','n','t','i','m','e','A','c','t','i','v','a','t','i','o','n','P','o','l','i','c','y',0};
    static const WCHAR empty[] = {0};
    LPCWSTR value;
    int value_size;
    HRESULT hr;

    hr = ISAXAttributes_getValueFromName(pAttr, empty, 0, legacy, lstrlenW(legacy), &value, &value_size);
    if (SUCCEEDED(hr))
        FIXME("useLegacyV2RuntimeActivationPolicy=%s not implemented\n", debugstr_wn(value, value_size));
    hr = S_OK;

    return hr;
}

static HRESULT parse_probing(ConfigFileHandler *This, ISAXAttributes *pAttr)
{
    static const WCHAR privatePath[] = {'p','r','i','v','a','t','e','P','a','t','h',0};
    static const WCHAR empty[] = {0};
    LPCWSTR value;
    int value_size;
    HRESULT hr;

    hr = ISAXAttributes_getValueFromName(pAttr, empty, 0, privatePath, lstrlenW(privatePath), &value, &value_size);
    if (SUCCEEDED(hr))
        FIXME("privatePath=%s not implemented\n", debugstr_wn(value, value_size));
    hr = S_OK;

    return hr;
}


static HRESULT parse_supported_runtime(ConfigFileHandler *This, ISAXAttributes *pAttr)
{
    static const WCHAR version[] = {'v','e','r','s','i','o','n',0};
    static const WCHAR sku[] = {'s','k','u',0};
    static const WCHAR empty[] = {0};
    LPCWSTR value;
    int value_size;
    HRESULT hr;
    supported_runtime *entry;

    hr = ISAXAttributes_getValueFromName(pAttr, empty, 0, version, lstrlenW(version), &value, &value_size);
    if (SUCCEEDED(hr))
    {
        TRACE("%s\n", debugstr_wn(value, value_size));
        entry = HeapAlloc(GetProcessHeap(), 0, sizeof(supported_runtime));
        if (entry)
        {
            entry->version = HeapAlloc(GetProcessHeap(), 0, (value_size + 1) * sizeof(WCHAR));
            if (entry->version)
            {
                lstrcpyW(entry->version, value);
                list_add_tail(&This->result->supported_runtimes, &entry->entry);
            }
            else
            {
                HeapFree(GetProcessHeap(), 0, entry);
                hr = E_OUTOFMEMORY;
            }
        }
        else
            hr = E_OUTOFMEMORY;
    }
    else
        WARN("Missing version attribute\n");

    if (SUCCEEDED(hr))
    {
        hr = ISAXAttributes_getValueFromName(pAttr, empty, 0, sku, lstrlenW(sku), &value, &value_size);
        if (SUCCEEDED(hr))
            FIXME("sku=%s not implemented\n", debugstr_wn(value, value_size));
        hr = S_OK;
    }

    return hr;
}

static HRESULT WINAPI ConfigFileHandler_startElement(ISAXContentHandler *iface,
    const WCHAR *pNamespaceUri, int nNamespaceUri, const WCHAR *pLocalName,
    int nLocalName, const WCHAR *pQName, int nQName, ISAXAttributes *pAttr)
{
    ConfigFileHandler *This = impl_from_ISAXContentHandler(iface);
    static const WCHAR configuration[] = {'c','o','n','f','i','g','u','r','a','t','i','o','n',0};
    static const WCHAR assemblyBinding[] = {'a','s','s','e','m','b','l','y','B','i','n','d','i','n','g',0};
    static const WCHAR probing[] = {'p','r','o','b','i','n','g',0};
    static const WCHAR runtime[] = {'r','u','n','t','i','m','e',0};
    static const WCHAR startup[] = {'s','t','a','r','t','u','p',0};
    static const WCHAR supportedRuntime[] = {'s','u','p','p','o','r','t','e','d','R','u','n','t','i','m','e',0};

    HRESULT hr = S_OK;

    TRACE("%s %s %s\n", debugstr_wn(pNamespaceUri,nNamespaceUri),
        debugstr_wn(pLocalName,nLocalName), debugstr_wn(pQName,nQName));

    if (This->statenum == sizeof(This->states) / sizeof(This->states[0]) - 1)
    {
        ERR("file has too much nesting\n");
        return E_FAIL;
    }

    switch (This->states[This->statenum])
    {
    case STATE_ROOT:
        if (nLocalName == sizeof(configuration)/sizeof(WCHAR)-1 &&
            lstrcmpW(pLocalName, configuration) == 0)
        {
            This->states[++This->statenum] = STATE_CONFIGURATION;
            break;
        }
        else
            goto unknown;
    case STATE_CONFIGURATION:
        if (nLocalName == sizeof(startup)/sizeof(WCHAR)-1 &&
            lstrcmpW(pLocalName, startup) == 0)
        {
            hr = parse_startup(This, pAttr);
            This->states[++This->statenum] = STATE_STARTUP;
            break;
        }
        else if (nLocalName == sizeof(runtime)/sizeof(WCHAR)-1 &&
            lstrcmpW(pLocalName, runtime) == 0)
        {
            This->states[++This->statenum] = STATE_RUNTIME;
            break;
        }
        else
            goto unknown;
    case STATE_RUNTIME:
        if (nLocalName == sizeof(assemblyBinding)/sizeof(WCHAR)-1 &&
            lstrcmpW(pLocalName, assemblyBinding) == 0)
        {
            This->states[++This->statenum] = STATE_ASSEMBLY_BINDING;
            break;
        }
        else
            goto unknown;
    case STATE_ASSEMBLY_BINDING:
        if (nLocalName == sizeof(probing)/sizeof(WCHAR)-1 &&
            lstrcmpW(pLocalName, probing) == 0)
        {
            hr = parse_probing(This, pAttr);
            This->states[++This->statenum] = STATE_PROBING;
            break;
        }
        else
            goto unknown;
    case STATE_STARTUP:
        if (nLocalName == sizeof(supportedRuntime)/sizeof(WCHAR)-1 &&
            lstrcmpW(pLocalName, supportedRuntime) == 0)
        {
            hr = parse_supported_runtime(This, pAttr);
            This->states[++This->statenum] = STATE_UNKNOWN;
            break;
        }
        else
            goto unknown;
    default:
        goto unknown;
    }

    return hr;

unknown:
    FIXME("Unknown element %s in state %u\n", debugstr_wn(pLocalName,nLocalName),
        This->states[This->statenum]);

    This->states[++This->statenum] = STATE_UNKNOWN;

    return S_OK;
}

static HRESULT WINAPI ConfigFileHandler_endElement(ISAXContentHandler *iface,
    const WCHAR *pNamespaceUri, int nNamespaceUri, const WCHAR *pLocalName,
    int nLocalName, const WCHAR *pQName, int nQName)
{
    ConfigFileHandler *This = impl_from_ISAXContentHandler(iface);

    TRACE("%s %s %s\n", debugstr_wn(pNamespaceUri,nNamespaceUri),
        debugstr_wn(pLocalName,nLocalName), debugstr_wn(pQName,nQName));

    if (This->statenum > 0)
    {
        This->statenum--;
    }
    else
    {
        ERR("element end does not match a start\n");
        return E_FAIL;
    }

    return S_OK;
}

static HRESULT WINAPI ConfigFileHandler_characters(ISAXContentHandler *iface,
    const WCHAR *pChars, int nChars)
{
    TRACE("%s\n", debugstr_wn(pChars,nChars));

    return S_OK;
}

static HRESULT WINAPI ConfigFileHandler_ignorableWhitespace(ISAXContentHandler *iface,
    const WCHAR *pChars, int nChars)
{
    return S_OK;
}

static HRESULT WINAPI ConfigFileHandler_processingInstruction(ISAXContentHandler *iface,
    const WCHAR *pTarget, int nTarget, const WCHAR *pData, int nData)
{
    return S_OK;
}

static HRESULT WINAPI ConfigFileHandler_skippedEntity(ISAXContentHandler *iface,
    const WCHAR * pName, int nName)
{
    TRACE("%s\n", debugstr_wn(pName,nName));
    return S_OK;
}

static const struct ISAXContentHandlerVtbl ConfigFileHandlerVtbl =
{
    ConfigFileHandler_QueryInterface,
    ConfigFileHandler_AddRef,
    ConfigFileHandler_Release,
    ConfigFileHandler_putDocumentLocator,
    ConfigFileHandler_startDocument,
    ConfigFileHandler_endDocument,
    ConfigFileHandler_startPrefixMapping,
    ConfigFileHandler_endPrefixMapping,
    ConfigFileHandler_startElement,
    ConfigFileHandler_endElement,
    ConfigFileHandler_characters,
    ConfigFileHandler_ignorableWhitespace,
    ConfigFileHandler_processingInstruction,
    ConfigFileHandler_skippedEntity
};

static HRESULT WINAPI ConfigFileHandler_Error_QueryInterface(ISAXErrorHandler *iface,
    REFIID riid, void **ppvObject)
{
    if (IsEqualGUID(riid, &IID_ISAXErrorHandler) ||
        IsEqualGUID(riid, &IID_IUnknown))
    {
        *ppvObject = iface;
    }
    else
    {
        WARN("Unsupported interface %s\n", debugstr_guid(riid));
        return E_NOINTERFACE;
    }

    ISAXErrorHandler_AddRef(iface);

    return S_OK;
}

static ULONG WINAPI ConfigFileHandler_Error_AddRef(ISAXErrorHandler *iface)
{
    ConfigFileHandler *This = impl_from_ISAXErrorHandler(iface);
    return IUnknown_AddRef((IUnknown*)This);
}

static ULONG WINAPI ConfigFileHandler_Error_Release(ISAXErrorHandler *iface)
{
    ConfigFileHandler *This = impl_from_ISAXErrorHandler(iface);
    return IUnknown_Release((IUnknown*)This);
}

static HRESULT WINAPI ConfigFileHandler_error(ISAXErrorHandler *iface,
    ISAXLocator * pLocator, const WCHAR * pErrorMessage, HRESULT hrErrorCode)
{
    WARN("%s,%x\n", debugstr_w(pErrorMessage), hrErrorCode);
    return S_OK;
}

static HRESULT WINAPI ConfigFileHandler_fatalError(ISAXErrorHandler *iface,
    ISAXLocator * pLocator, const WCHAR * pErrorMessage, HRESULT hrErrorCode)
{
    WARN("%s,%x\n", debugstr_w(pErrorMessage), hrErrorCode);
    return S_OK;
}

static HRESULT WINAPI ConfigFileHandler_ignorableWarning(ISAXErrorHandler *iface,
    ISAXLocator * pLocator, const WCHAR * pErrorMessage, HRESULT hrErrorCode)
{
    WARN("%s,%x\n", debugstr_w(pErrorMessage), hrErrorCode);
    return S_OK;
}

static const struct ISAXErrorHandlerVtbl ConfigFileHandlerErrorVtbl =
{
    ConfigFileHandler_Error_QueryInterface,
    ConfigFileHandler_Error_AddRef,
    ConfigFileHandler_Error_Release,
    ConfigFileHandler_error,
    ConfigFileHandler_fatalError,
    ConfigFileHandler_ignorableWarning
};

static void init_config(parsed_config_file *config)
{
    list_init(&config->supported_runtimes);
}

static HRESULT parse_config(VARIANT input, parsed_config_file *result)
{
    ISAXXMLReader *reader;
    ConfigFileHandler *handler;
    HRESULT hr;

    handler = HeapAlloc(GetProcessHeap(), 0, sizeof(ConfigFileHandler));
    if (!handler)
        return E_OUTOFMEMORY;

    handler->ISAXContentHandler_iface.lpVtbl = &ConfigFileHandlerVtbl;
    handler->ISAXErrorHandler_iface.lpVtbl = &ConfigFileHandlerErrorVtbl;
    handler->ref = 1;
    handler->states[0] = STATE_ROOT;
    handler->statenum = 0;
    handler->result = result;

    hr = CoCreateInstance(&CLSID_SAXXMLReader, NULL, CLSCTX_INPROC_SERVER,
        &IID_ISAXXMLReader, (LPVOID*)&reader);

    if (SUCCEEDED(hr))
    {
        hr = ISAXXMLReader_putContentHandler(reader, &handler->ISAXContentHandler_iface);

        if (SUCCEEDED(hr))
            hr = ISAXXMLReader_putErrorHandler(reader, &handler->ISAXErrorHandler_iface);

        if (SUCCEEDED(hr))
            hr = ISAXXMLReader_parse(reader, input);

        ISAXXMLReader_Release(reader);
    }

    ISAXContentHandler_Release(&handler->ISAXContentHandler_iface);

    return S_OK;
}

HRESULT parse_config_file(LPCWSTR filename, parsed_config_file *result)
{
    IStream *stream;
    VARIANT var;
    HRESULT hr;
    HRESULT initresult;

    init_config(result);

    initresult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);

    hr = SHCreateStreamOnFileW(filename, STGM_SHARE_DENY_WRITE | STGM_READ | STGM_FAILIFTHERE, &stream);

    if (SUCCEEDED(hr))
    {
        V_VT(&var) = VT_UNKNOWN;
        V_UNKNOWN(&var) = (IUnknown*)stream;

        hr = parse_config(var, result);

        IStream_Release(stream);
    }

    if (SUCCEEDED(initresult))
        CoUninitialize();

    return hr;
}

void free_parsed_config_file(parsed_config_file *file)
{
    supported_runtime *cursor, *cursor2;

    LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &file->supported_runtimes, supported_runtime, entry)
    {
        HeapFree(GetProcessHeap(), 0, cursor->version);
        list_remove(&cursor->entry);
        HeapFree(GetProcessHeap(), 0, cursor);
    }
}
