/*
 * Copyright (c) 2004 TransGaming Technologies
 */

#include "winbase.h"
#include "winuser.h"
#include "wingdi.h"

#include "oleauto.h"
#include "htmlguid.h"
#include "mshtml.h"

#include "wine/debug.h"
#include "wine/unicode.h"

#include "mshtml_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(mshtml);

/**********************************************************
 * Implement to class factory
 */

typedef struct
{
    /* IUnknown fields */
    ICOM_VFIELD(IClassFactory);
    DWORD ref;
    /* IClassFactory fields */
    HRESULT (*pfnCreateInstance)(IUnknown *pOuter, REFIID riid,
                                 LPVOID *ppobj);
} IClassFactoryImpl;

/**********************************************************************
 * CF_QueryInterface (IUnknown)
 */
static HRESULT WINAPI CF_QueryInterface(LPCLASSFACTORY iface,
                                        REFIID riid, LPVOID *ppobj)
{
    ICOM_THIS(IClassFactoryImpl, iface);

    FIXME("(%p)->(%s, %p): stub\n", iface, debugstr_guid(riid), ppobj);

    /*
     * Perform a sanity check on the parameters.
     */
    if ((This == NULL) || (ppobj == NULL) )
        return E_INVALIDARG;

    return E_NOINTERFACE;
}

/************************************************************************
 * CF_AddRef (IUnknown)
 */
static ULONG WINAPI CF_AddRef(LPCLASSFACTORY iface)
{
    ICOM_THIS(IClassFactoryImpl, iface);

    TRACE("(%p)->()\n", iface);

    return ++(This->ref);
}

/************************************************************************
 * CF_Release (IUnknown)
 */
static ULONG WINAPI CF_Release(LPCLASSFACTORY iface)
{
    ICOM_THIS(IClassFactoryImpl, iface);

    TRACE("(%p)->()\n", iface);

    /* static class, won't be freed */
    return --(This->ref);
}

/************************************************************************
 * CF_CreateInstance (IClassFactory)
 */
static HRESULT WINAPI CF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter,
                                        REFIID riid, LPVOID *ppobj)
{
    ICOM_THIS(IClassFactoryImpl, iface);

    TRACE("(%p)->(%p,%s,%p)\n", iface, pOuter, debugstr_guid(riid), ppobj);

    /* Don't support aggregation (yet?) */
    if (pOuter)
    {
        TRACE ("Failed attempt to aggregate\n");
        return CLASS_E_NOAGGREGATION;
    }

    return This->pfnCreateInstance(pOuter, riid, ppobj);
}

/************************************************************************
 * CF_LockServer (IClassFactory)
 */
static HRESULT WINAPI CF_LockServer(LPCLASSFACTORY iface, BOOL dolock)
{
    /*ICOM_THIS(IClassFactoryImpl, iface);*/
    FIXME("(%p)->(%d),stub!\n", iface, dolock);
    return S_OK;
}

static ICOM_VTABLE(IClassFactory) CF_Vtbl =
{
    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
    CF_QueryInterface,
    CF_AddRef,
    CF_Release,
    CF_CreateInstance,
    CF_LockServer
};

static IClassFactoryImpl MSHTML_CF_HTMLDocument = { &CF_Vtbl, 1, html_CreateDocument };

/*************************************************************************
 *              DllGetClassObject (MSHTML.@)
 */
HRESULT WINAPI MSHTML_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
{
    TRACE("(%s, %s, %p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);

    if (!IsEqualGUID(riid, &IID_IClassFactory) &&
        !IsEqualGUID(riid, &IID_IUnknown))
    {
        ERR("(%s, %s, %p): no interface found.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
        return CLASS_E_CLASSNOTAVAILABLE;
    }

    if (IsEqualGUID(rclsid, &CLSID_HTMLViewer))
    {
        *ppv = &MSHTML_CF_HTMLDocument;
        CF_AddRef((IClassFactory*)*ppv);
        return S_OK;
    }

    ERR("(%s, %s, %p): no class found.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
    return CLASS_E_CLASSNOTAVAILABLE;
}

