/*
 * Copyright 2009 Maarten Lankhorst
 * Copyright 2011 Andrew Eikum 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 "config.h"
#include "wine/port.h"

#include <stdarg.h>

#define COBJMACROS
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "wine/library.h"

#include "ole2.h"
#include "olectl.h"
#include "rpcproxy.h"
#include "propsys.h"
#include "initguid.h"
#include "propkeydef.h"
#include "mmdeviceapi.h"
#include "dshow.h"
#include "dsound.h"
#include "audioclient.h"
#include "endpointvolume.h"
#include "audiopolicy.h"
#include "devpkey.h"
#include "winreg.h"

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

WINE_DEFAULT_DEBUG_CHANNEL(mmdevapi);

static HINSTANCE instance;

DriverFuncs drvs;

static BOOL load_driver(const WCHAR *name)
{
    WCHAR driver_module[264];
    static const WCHAR wineW[] = {'w','i','n','e',0};
    static const WCHAR dotdrvW[] = {'.','d','r','v',0};

    lstrcpyW(driver_module, wineW);
    lstrcatW(driver_module, name);
    lstrcatW(driver_module, dotdrvW);

    TRACE("Attempting to load %s\n", wine_dbgstr_w(driver_module));

    drvs.module = LoadLibraryW(driver_module);
    if(!drvs.module){
        TRACE("Unable to load %s: %u\n", wine_dbgstr_w(driver_module),
                GetLastError());
        return FALSE;
    }

#define LDFC(n) do { drvs.p##n = (void*)GetProcAddress(drvs.module, #n);\
        if(!drvs.p##n) { FreeLibrary(drvs.module); return FALSE; } } while(0)
    LDFC(GetEndpointIDs);
    LDFC(GetAudioEndpoint);
    LDFC(GetAudioSessionManager);
#undef LDFC

    TRACE("Successfully loaded %s\n", wine_dbgstr_w(driver_module));

    return TRUE;
}

static BOOL init_driver(void)
{
    static const WCHAR alsaW[] = {'a','l','s','a',0};
    static const WCHAR ossW[] = {'o','s','s',0};
    static const WCHAR coreaudioW[] = {'c','o','r','e','a','u','d','i','o',0};
    static const WCHAR *default_drivers[] = { alsaW, coreaudioW, ossW };
    static const WCHAR drv_key[] = {'S','o','f','t','w','a','r','e','\\',
        'W','i','n','e','\\','D','r','i','v','e','r','s',0};
    static const WCHAR drv_value[] = {'A','u','d','i','o',0};
    HKEY key;
    UINT i;

    if(drvs.module)
        return TRUE;

    if(RegOpenKeyW(HKEY_CURRENT_USER, drv_key, &key) == ERROR_SUCCESS){
        WCHAR driver_name[256], *p, *next;
        DWORD size = sizeof(driver_name);

        if(RegQueryValueExW(key, drv_value, 0, NULL, (BYTE*)driver_name,
                    &size) == ERROR_SUCCESS && driver_name[0] != '\0'){
            RegCloseKey(key);

            for(next = p = driver_name; next; p = next + 1){
                next = strchrW(p, ',');
                if(next)
                    *next = '\0';

                if(load_driver(p))
                    return TRUE;

                TRACE("Failed to load driver: %s\n", wine_dbgstr_w(driver_name));
            }

            ERR("No drivers in the registry loaded successfully!\n");
            return FALSE;
        }

        RegCloseKey(key);
    }

    for(i = 0; i < sizeof(default_drivers)/sizeof(*default_drivers); ++i)
        if(load_driver(default_drivers[i]))
            return TRUE;

    return FALSE;
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);

    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
            instance = hinstDLL;
            DisableThreadLibraryCalls(hinstDLL);
            break;
        case DLL_PROCESS_DETACH:
            MMDevEnum_Free();
            break;
    }

    return TRUE;
}

HRESULT WINAPI DllCanUnloadNow(void)
{
    return S_FALSE;
}

typedef HRESULT (*FnCreateInstance)(REFIID riid, LPVOID *ppobj);

typedef struct {
    IClassFactory IClassFactory_iface;
    REFCLSID rclsid;
    FnCreateInstance pfnCreateInstance;
} IClassFactoryImpl;

static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
{
    return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
}

static HRESULT WINAPI
MMCF_QueryInterface(LPCLASSFACTORY iface, REFIID riid, LPVOID *ppobj)
{
    IClassFactoryImpl *This = impl_from_IClassFactory(iface);
    TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppobj);
    if (ppobj == NULL)
        return E_POINTER;
    if (IsEqualIID(riid, &IID_IUnknown) ||
        IsEqualIID(riid, &IID_IClassFactory))
    {
        *ppobj = iface;
        IUnknown_AddRef(iface);
        return S_OK;
    }
    *ppobj = NULL;
    return E_NOINTERFACE;
}

static ULONG WINAPI MMCF_AddRef(LPCLASSFACTORY iface)
{
    return 2;
}

static ULONG WINAPI MMCF_Release(LPCLASSFACTORY iface)
{
    /* static class, won't be freed */
    return 1;
}

static HRESULT WINAPI MMCF_CreateInstance(
    LPCLASSFACTORY iface,
    LPUNKNOWN pOuter,
    REFIID riid,
    LPVOID *ppobj)
{
    IClassFactoryImpl *This = impl_from_IClassFactory(iface);
    TRACE("(%p, %p, %s, %p)\n", This, pOuter, debugstr_guid(riid), ppobj);

    if (pOuter)
        return CLASS_E_NOAGGREGATION;

    if (ppobj == NULL) {
        WARN("invalid parameter\n");
        return E_POINTER;
    }
    *ppobj = NULL;
    return This->pfnCreateInstance(riid, ppobj);
}

static HRESULT WINAPI MMCF_LockServer(LPCLASSFACTORY iface, BOOL dolock)
{
    IClassFactoryImpl *This = impl_from_IClassFactory(iface);
    FIXME("(%p, %d) stub!\n", This, dolock);
    return S_OK;
}

static const IClassFactoryVtbl MMCF_Vtbl = {
    MMCF_QueryInterface,
    MMCF_AddRef,
    MMCF_Release,
    MMCF_CreateInstance,
    MMCF_LockServer
};

static IClassFactoryImpl MMDEVAPI_CF[] = {
    { { &MMCF_Vtbl }, &CLSID_MMDeviceEnumerator, (FnCreateInstance)MMDevEnum_Create }
};

HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
{
    int i = 0;
    TRACE("(%s, %s, %p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);

    if(!init_driver()){
        ERR("Driver initialization failed\n");
        return E_FAIL;
    }

    if (ppv == NULL) {
        WARN("invalid parameter\n");
        return E_INVALIDARG;
    }

    *ppv = NULL;

    if (!IsEqualIID(riid, &IID_IClassFactory) &&
        !IsEqualIID(riid, &IID_IUnknown)) {
        WARN("no interface for %s\n", debugstr_guid(riid));
        return E_NOINTERFACE;
    }

    for (i = 0; i < sizeof(MMDEVAPI_CF)/sizeof(MMDEVAPI_CF[0]); ++i)
    {
        if (IsEqualGUID(rclsid, MMDEVAPI_CF[i].rclsid)) {
            IUnknown_AddRef(&MMDEVAPI_CF[i].IClassFactory_iface);
            *ppv = &MMDEVAPI_CF[i];
            return S_OK;
        }
        i++;
    }

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

/***********************************************************************
 *		DllRegisterServer (MMDEVAPI.@)
 */
HRESULT WINAPI DllRegisterServer(void)
{
    return __wine_register_resources( instance, NULL );
}

/***********************************************************************
 *		DllUnregisterServer (MMDEVAPI.@)
 */
HRESULT WINAPI DllUnregisterServer(void)
{
    return __wine_unregister_resources( instance, NULL );
}
