| /* | |
| * Copyright 2009 Maarten Lankhorst | |
| * | |
| * 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 <stdarg.h> | |
| #define CINTERFACE | |
| #define COBJMACROS | |
| #include "windef.h" | |
| #include "winbase.h" | |
| #include "wine/debug.h" | |
| #include "initguid.h" | |
| #include "ole2.h" | |
| #include "mmdeviceapi.h" | |
| #include "mmdevapi.h" | |
| WINE_DEFAULT_DEBUG_CHANNEL(mmdevapi); | |
| BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) | |
| { | |
| TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved); | |
| switch (fdwReason) | |
| { | |
| case DLL_PROCESS_ATTACH: | |
| 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 { | |
| const IClassFactoryVtbl *lpVtbl; | |
| REFCLSID rclsid; | |
| FnCreateInstance pfnCreateInstance; | |
| } IClassFactoryImpl; | |
| static HRESULT WINAPI | |
| MMCF_QueryInterface(LPCLASSFACTORY iface, REFIID riid, LPVOID *ppobj) | |
| { | |
| IClassFactoryImpl *This = (IClassFactoryImpl *)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 = (IClassFactoryImpl *)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 = (IClassFactoryImpl *)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 (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((IClassFactory*) &MMDEVAPI_CF[i]); | |
| *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; | |
| } |