/*
 *    Gameux library IClassFactory implementation
 *
 * Copyright (C) 2010 Mariusz Pluciński
 *
 * 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 "config.h"

#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "ole2.h"

#include "gameux.h"
#include "gameux_private.h"

#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(gameux);

typedef HRESULT (*fnCreateInstance)(IUnknown *pUnkOuter, IUnknown **ppObj);

/***************************************************************
 * gameux ClassFactory
 */
typedef struct _gameuxcf
{
    const struct IClassFactoryVtbl *lpVtbl;
    fnCreateInstance pfnCreateInstance;
} gameuxcf;

static inline gameuxcf *impl_from_IClassFactory(IClassFactory *iface)
{
    return (gameuxcf*)((char*)iface - FIELD_OFFSET(gameuxcf, lpVtbl));
}

static HRESULT WINAPI gameuxcf_QueryInterface(
        IClassFactory *iface,
        REFIID riid,
        LPVOID *ppObj)
{
    TRACE("(%p, %s, %p)\n", iface, debugstr_guid(riid), ppObj);

    *ppObj = NULL;

    if(IsEqualGUID(riid, &IID_IUnknown) ||
       IsEqualGUID(riid, &IID_IClassFactory))
    {
        IClassFactory_AddRef(iface);
        *ppObj = iface;
        return S_OK;
    }

    FIXME("interface %s not implemented\n", debugstr_guid(riid));
    return E_NOINTERFACE;
}

static ULONG WINAPI gameuxcf_AddRef(
        IClassFactory *iface)
{
    TRACE("(%p)\n", iface);
    return 2;
}

static ULONG WINAPI gameuxcf_Release(
        IClassFactory *iface)
{
    TRACE("(%p)\n", iface);
    return 1;
}

static HRESULT WINAPI gameuxcf_CreateInstance(
        IClassFactory *iface,
        LPUNKNOWN pUnkOuter,
        REFIID riid,
        LPVOID *ppObj)
{
    gameuxcf *This = impl_from_IClassFactory(iface);
    HRESULT hr;
    IUnknown *pUnk;

    TRACE("(%p, %p, %s, %p)\n", iface, pUnkOuter, debugstr_guid(riid), ppObj);

    *ppObj = NULL;

    if(pUnkOuter)
        return CLASS_E_NOAGGREGATION;

    hr = This->pfnCreateInstance(pUnkOuter, &pUnk);
    if(FAILED(hr))
        return hr;

    hr = IUnknown_QueryInterface(pUnk, riid, ppObj);
    IUnknown_Release(pUnk);
    return hr;
}

static HRESULT WINAPI gameuxcf_LockServer(
        IClassFactory *iface,
        BOOL dolock)
{
    gameuxcf *This = impl_from_IClassFactory(iface);
    TRACE("(%p, %d)\n", This, dolock);
    FIXME("stub\n");
    return S_OK;
}

static const struct IClassFactoryVtbl gameuxcf_vtbl =
{
    gameuxcf_QueryInterface,
    gameuxcf_AddRef,
    gameuxcf_Release,
    gameuxcf_CreateInstance,
    gameuxcf_LockServer
};

static gameuxcf gameexplorercf = { &gameuxcf_vtbl, GameExplorer_create };
static gameuxcf gamestatisticscf  = { &gameuxcf_vtbl, GameStatistics_create };

/***************************************************************
 * gameux ClassFactory
 */
HRESULT WINAPI DllGetClassObject(
        REFCLSID rclsid,
        REFIID riid,
        LPVOID *ppv)
{
    IClassFactory *cf = NULL;

    TRACE("(%s, %s, %p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);

    if(IsEqualCLSID(rclsid, &CLSID_GameExplorer))
    {
        cf = (IClassFactory*)&gameexplorercf.lpVtbl;
    }
    else if( IsEqualCLSID( rclsid, &CLSID_GameStatistics ))
    {
        cf = (IClassFactory*) &gamestatisticscf.lpVtbl;
    }

    if(!cf)
        return CLASS_E_CLASSNOTAVAILABLE;

    return IClassFactory_QueryInterface(cf, riid, ppv);
}
