/* dpnet.dll
 *
 * Copyright 2002, 2003 TransGaming Technologies
 *
 * David Hammerton (david@transgaming.com)
 */

#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "winreg.h"
#include "objbase.h"
#include "wine/debug.h"
#include "winerror.h"

#include "dplay8.h"
#include "dplobby8.h"
#include "dplay8_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(dplay);

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

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

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

static ULONG WINAPI DPCF_AddRef(LPCLASSFACTORY iface)
{
    ICOM_THIS(IClassFactoryImpl,iface);
    return ++(This->ref);
}

static ULONG WINAPI DPCF_Release(LPCLASSFACTORY iface)
{
    ICOM_THIS(IClassFactoryImpl,iface);
    /* static class, won't be  freed */
    return --(This->ref);
}

static HRESULT WINAPI
DPCF_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);
    return This->pfnCreateInstance(pOuter, riid, ppobj);
}

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

static ICOM_VTABLE(IClassFactory) DPCF_Vtbl =
{
    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
    DPCF_QueryInterface,
    DPCF_AddRef,
    DPCF_Release,
    DPCF_CreateInstance,
    DPCF_LockServer
};

static IClassFactoryImpl DPNET_CF_Client = {&DPCF_Vtbl, 1, DPNET_CreateDirectPlay8Client };
static IClassFactoryImpl DPNET_CF_Server = {&DPCF_Vtbl, 1, DPNET_CreateDirectPlay8Server };
static IClassFactoryImpl DPNET_CF_Peer   = {&DPCF_Vtbl, 1, DPNET_CreateDirectPlay8Peer   };

static IClassFactoryImpl DPNET_CF_LobbiedApplication = {&DPCF_Vtbl, 1, DPNET_CreateDirectPlay8LobbiedApplication };
static IClassFactoryImpl DPNET_CF_LobbyClient        = {&DPCF_Vtbl, 1, DPNET_CreateDirectPlay8LobbyClient        };

static IClassFactoryImpl DPNET_CF_Address = {&DPCF_Vtbl, 1, DPNET_CreateDirectPlay8Address };

static IClassFactoryImpl DPNET_CF_ThreadPool = {&DPCF_Vtbl, 1, DPNET_CreateDirectPlay8ThreadPool };

static IClassFactoryImpl DPNET_CF_SP_TCP = {&DPCF_Vtbl, 1, DPNET_CreateDirectPlay8SP_TCP };

/***********************************************************************
 *             DllGetClassObject (DPNET.@)
 */
HRESULT WINAPI DPNET_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_DirectPlay8Client))
    {
        DPCF_AddRef((IClassFactory*)&DPNET_CF_Client);
        *ppv = &DPNET_CF_Client;
        return S_OK;
    }
    else if (IsEqualGUID(rclsid, &CLSID_DirectPlay8Server))
    {
        DPCF_AddRef((IClassFactory*)&DPNET_CF_Server);
        *ppv = &DPNET_CF_Server;
        return S_OK;
    }
    else if (IsEqualGUID(rclsid, &CLSID_DirectPlay8Peer))
    {
        DPCF_AddRef((IClassFactory*)&DPNET_CF_Peer);
        *ppv = &DPNET_CF_Peer;
        return S_OK;
    }
    else if (IsEqualGUID(rclsid, &CLSID_DirectPlay8LobbiedApplication))
    {
        DPCF_AddRef((IClassFactory*)&DPNET_CF_LobbiedApplication);
        *ppv = &DPNET_CF_LobbiedApplication;
        return S_OK;
    }
    else if (IsEqualGUID(rclsid, &CLSID_DirectPlay8LobbyClient))
    {
        DPCF_AddRef((IClassFactory*)&DPNET_CF_LobbyClient);
        *ppv = &DPNET_CF_LobbyClient;
        return S_OK;
    }
    else if (IsEqualGUID(rclsid, &CLSID_DirectPlay8Address))
    {
        DPCF_AddRef((IClassFactory*)&DPNET_CF_Address);
        *ppv = &DPNET_CF_Address;
        return S_OK;
    }
    else if (IsEqualGUID(rclsid, &CLSID_DirectPlay8ThreadPool))
    {
        DPCF_AddRef((IClassFactory*)&DPNET_CF_ThreadPool);
        *ppv = &DPNET_CF_ThreadPool;
        return S_OK;
    }
    else if (IsEqualGUID(rclsid, &CLSID_DP8SP_TCPIP))
    {
        DPCF_AddRef((IClassFactory*)&DPNET_CF_SP_TCP);
        *ppv = &DPNET_CF_SP_TCP;
        return S_OK;
    }
    ERR("(%s, %s, %p): no interface found.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
    return CLASS_E_CLASSNOTAVAILABLE;
}

