/*
 * IMetaDataDispenserEx - dynamic creation/editing of assemblies
 *
 * Copyright 2010 Vincent Povirk for CodeWeavers
 *
 * 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
 */

#include <stdio.h>
#include <stdarg.h>
#include <assert.h>

#define COBJMACROS

#include "wine/library.h"
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "ole2.h"

#include "cor.h"
#include "metahost.h"
#include "wine/list.h"
#include "mscoree_private.h"

#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL( mscoree );

typedef struct MetaDataDispenser
{
    IMetaDataDispenserEx IMetaDataDispenserEx_iface;
    LONG ref;
} MetaDataDispenser;

static inline MetaDataDispenser *impl_from_IMetaDataDispenserEx(IMetaDataDispenserEx *iface)
{
    return CONTAINING_RECORD(iface, MetaDataDispenser, IMetaDataDispenserEx_iface);
}

static HRESULT WINAPI MetaDataDispenser_QueryInterface(IMetaDataDispenserEx* iface,
    REFIID riid, void **ppvObject)
{
    TRACE("%p %s %p\n", iface, debugstr_guid(riid), ppvObject);

    if (IsEqualGUID(riid, &IID_IMetaDataDispenserEx) ||
        IsEqualGUID(riid, &IID_IMetaDataDispenser) ||
        IsEqualGUID(riid, &IID_IUnknown))
    {
        *ppvObject = iface;
    }
    else
    {
        FIXME("Unsupported interface %s\n", debugstr_guid(riid));
        return E_NOINTERFACE;
    }

    IMetaDataDispenserEx_AddRef( iface );

    return S_OK;
}

static ULONG WINAPI MetaDataDispenser_AddRef(IMetaDataDispenserEx* iface)
{
    MetaDataDispenser *This = impl_from_IMetaDataDispenserEx(iface);
    ULONG ref = InterlockedIncrement(&This->ref);

    TRACE("%p ref=%u\n", This, ref);

    return ref;
}

static ULONG WINAPI MetaDataDispenser_Release(IMetaDataDispenserEx* iface)
{
    MetaDataDispenser *This = impl_from_IMetaDataDispenserEx(iface);
    ULONG ref = InterlockedDecrement(&This->ref);

    TRACE("%p ref=%u\n", This, ref);

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

    return ref;
}

static HRESULT WINAPI MetaDataDispenser_DefineScope(IMetaDataDispenserEx* iface,
    REFCLSID rclsid, DWORD dwCreateFlags, REFIID riid, IUnknown **ppIUnk)
{
    FIXME("%p %s %x %s %p\n", iface, debugstr_guid(rclsid), dwCreateFlags,
        debugstr_guid(riid), ppIUnk);
    return E_NOTIMPL;
}

static HRESULT WINAPI MetaDataDispenser_OpenScope(IMetaDataDispenserEx* iface,
    LPCWSTR szScope, DWORD dwOpenFlags, REFIID riid, IUnknown **ppIUnk)
{
    FIXME("%p %s %x %s %p\n", iface, debugstr_w(szScope), dwOpenFlags,
        debugstr_guid(riid), ppIUnk);
    return E_NOTIMPL;
}

static HRESULT WINAPI MetaDataDispenser_OpenScopeOnMemory(IMetaDataDispenserEx* iface,
    const void *pData, ULONG cbData, DWORD dwOpenFlags, REFIID riid, IUnknown **ppIUnk)
{
    FIXME("%p %p %u %x %s %p\n", iface, pData, cbData, dwOpenFlags,
        debugstr_guid(riid), ppIUnk);
    return E_NOTIMPL;
}

static HRESULT WINAPI MetaDataDispenser_SetOption(IMetaDataDispenserEx* iface,
    REFGUID optionid, const VARIANT *value)
{
    FIXME("%p %s\n", iface, debugstr_guid(optionid));
    return E_NOTIMPL;
}

static HRESULT WINAPI MetaDataDispenser_GetOption(IMetaDataDispenserEx* iface,
    REFGUID optionid, VARIANT *pvalue)
{
    FIXME("%p %s\n", iface, debugstr_guid(optionid));
    return E_NOTIMPL;
}

static HRESULT WINAPI MetaDataDispenser_OpenScopeOnITypeInfo(IMetaDataDispenserEx* iface,
    ITypeInfo *pITI, DWORD dwOpenFlags, REFIID riid, IUnknown **ppIUnk)
{
    FIXME("%p %p %u %s %p\n", iface, pITI, dwOpenFlags, debugstr_guid(riid), ppIUnk);
    return E_NOTIMPL;
}

static HRESULT WINAPI MetaDataDispenser_GetCORSystemDirectory(IMetaDataDispenserEx* iface,
    LPWSTR szBuffer, DWORD cchBuffer, DWORD *pchBuffer)
{
    FIXME("%p %p %u %p\n", iface, szBuffer, cchBuffer, pchBuffer);
    return E_NOTIMPL;
}

static HRESULT WINAPI MetaDataDispenser_FindAssembly(IMetaDataDispenserEx* iface,
    LPCWSTR szAppBase, LPCWSTR szPrivateBin, LPCWSTR szGlobalBin, LPCWSTR szAssemblyName,
    LPWSTR szName, ULONG cchName, ULONG *pcName)
{
    FIXME("%p %s %s %s %s %p %u %p\n", iface, debugstr_w(szAppBase),
        debugstr_w(szPrivateBin), debugstr_w(szGlobalBin),
        debugstr_w(szAssemblyName), szName, cchName, pcName);
    return E_NOTIMPL;
}

static HRESULT WINAPI MetaDataDispenser_FindAssemblyModule(IMetaDataDispenserEx* iface,
    LPCWSTR szAppBase, LPCWSTR szPrivateBin, LPCWSTR szGlobalBin, LPCWSTR szAssemblyName,
    LPCWSTR szModuleName, LPWSTR szName, ULONG cchName, ULONG *pcName)
{
    FIXME("%p %s %s %s %s %s %p %u %p\n", iface, debugstr_w(szAppBase),
        debugstr_w(szPrivateBin), debugstr_w(szGlobalBin), debugstr_w(szAssemblyName),
        debugstr_w(szModuleName), szName, cchName, pcName);
    return E_NOTIMPL;
}

static const struct IMetaDataDispenserExVtbl MetaDataDispenserVtbl =
{
    MetaDataDispenser_QueryInterface,
    MetaDataDispenser_AddRef,
    MetaDataDispenser_Release,
    MetaDataDispenser_DefineScope,
    MetaDataDispenser_OpenScope,
    MetaDataDispenser_OpenScopeOnMemory,
    MetaDataDispenser_SetOption,
    MetaDataDispenser_GetOption,
    MetaDataDispenser_OpenScopeOnITypeInfo,
    MetaDataDispenser_GetCORSystemDirectory,
    MetaDataDispenser_FindAssembly,
    MetaDataDispenser_FindAssemblyModule
};

HRESULT MetaDataDispenser_CreateInstance(IUnknown **ppUnk)
{
    MetaDataDispenser *This;

    This = HeapAlloc(GetProcessHeap(), 0, sizeof(MetaDataDispenser));

    if (!This)
        return E_OUTOFMEMORY;

    This->IMetaDataDispenserEx_iface.lpVtbl = &MetaDataDispenserVtbl;
    This->ref = 1;

    *ppUnk = (IUnknown*)This;

    return S_OK;
}
