/*		DirectMusic
 *
 * Copyright 2002 TransGaming Technologies Inc. 
 *
 */

#include "config.h"
#include <assert.h>
#include <string.h>

#include "wine/debug.h"
#include "winbase.h"
#include "winerror.h"
#include "windef.h"
#include "wingdi.h"
#include "winuser.h"
#include "winnls.h"
#include "mmsystem.h"
#include "ole2.h"
#include "strmif.h"
#include "control.h"
#include "uuids.h"
#include "errors.h"
#include "dsound.h"
#include "dmusicc.h"
#include "dmusics.h"
#include "dmsynth_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(dmusic);

DEFINE_GUID(CLSID_DirectMusicSynthSink,0xAEC17CE3,0xA514,0x11D1,0xAF,0xA6,0x00,0xAA,0x00,0x24,0xD8,0xB6);

/***********************************************************************
 *		DllCanUnloadNow (DMSYNTH.@)
 */
HRESULT WINAPI DMSYNTH_DllCanUnloadNow(void)
{
    FIXME("(void): stub\n");

    return S_FALSE;
}


/*******************************************************************************
 * DirectMusic ClassFactory
 */
typedef struct
{
    /* IUnknown fields */
    ICOM_VFIELD(IClassFactory);
    DWORD                       ref;
    /* IClassFactory fields */
    REFCLSID			rclsid;
    DMSYNTH_ClassCreator		creator;
} IClassFactoryImpl;

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

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

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

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

static HRESULT WINAPI DMCF_CreateInstance(
	LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
) {
	ICOM_THIS(IClassFactoryImpl,iface);
	IUnknown *obj = NULL;
	HRESULT hres;

	TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
	hres = This->creator(riid, &obj, pOuter);
	if (FAILED(hres)) return hres;
	hres = IUnknown_QueryInterface(obj, riid, ppobj);
	IUnknown_Release(obj);
	return hres;
}

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

static ICOM_VTABLE(IClassFactory) DMCF_Vtbl = {
	ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
	DMCF_QueryInterface,
	DMCF_AddRef,
	DMCF_Release,
	DMCF_CreateInstance,
	DMCF_LockServer
};
static IClassFactoryImpl DMSYNTH_Classes[] = {
/* Not available yet
    {&DMCF_Vtbl, 1, &CLSID_DirectMusicSynth,       DirectMusicSynthCreate},
    {&DMCF_Vtbl, 1, &CLSID_DirectMusicSynthSink,   DirectMusicSynthSinkCreate}
*/
};

/*******************************************************************************
 * DllGetClassObject [DMSYNTH.@]
 * Retrieves class object from a DLL object
 *
 * PARAMS
 *    rclsid [I] CLSID for the class object
 *    riid   [I] Reference to identifier of interface for class object
 *    ppv    [O] Address of variable to receive interface pointer for riid
 *
 * RETURNS
 *    Success: S_OK
 *    Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
 *             E_UNEXPECTED
 */
DWORD WINAPI DMSYNTH_DllGetClassObject(REFCLSID rclsid,REFIID riid,LPVOID *ppv)
{
    TRACE("(%p,%p,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
    if ( IsEqualIID( &IID_IClassFactory, riid ) ) {
        unsigned u;
        for (u=0; u<(sizeof(DMSYNTH_Classes)/sizeof(IClassFactoryImpl)); u++)
            if ( IsEqualCLSID( DMSYNTH_Classes[u].rclsid, rclsid ) ) {
                *ppv = (LPVOID)&DMSYNTH_Classes[u];
                IClassFactory_AddRef((IClassFactory*)*ppv);
                return S_OK;
            }
        return CLASS_E_CLASSNOTAVAILABLE;
    }

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



/***********************************************************************
 *		DllRegisterServer (DMSYNTH.@)
 */
HRESULT WINAPI DMSYNTH_DllRegisterServer(void)
{
    FIXME("(void): stub\n");

    return S_OK;
}

/***********************************************************************
 *		DllUnregisterServer (DMSYNTH.@)
 */
HRESULT WINAPI DMSYNTH_DllUnregisterServer(void)
{
    FIXME("(void): stub\n");

    return S_OK;
}
