Maarten Lankhorst : mmdevapi: Add stubs for MMDevEnum with tests.

Alexandre Julliard julliard at winehq.org
Mon Jan 4 10:54:20 CST 2010


Module: wine
Branch: master
Commit: 3410ab8b7ce434bfbccb1429c0d802c2e53bb8ce
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=3410ab8b7ce434bfbccb1429c0d802c2e53bb8ce

Author: Maarten Lankhorst <m.b.lankhorst at gmail.com>
Date:   Mon Dec 14 16:04:04 2009 +0100

mmdevapi: Add stubs for MMDevEnum with tests.

---

 dlls/mmdevapi/devenum.c         |  122 ++++++++++++++++++++++++++++++++++++++-
 dlls/mmdevapi/main.c            |    1 +
 dlls/mmdevapi/mmdevapi.h        |    1 +
 dlls/mmdevapi/tests/mmdevenum.c |   19 ++++++-
 4 files changed, 140 insertions(+), 3 deletions(-)

diff --git a/dlls/mmdevapi/devenum.c b/dlls/mmdevapi/devenum.c
index e34c824..90347b1 100644
--- a/dlls/mmdevapi/devenum.c
+++ b/dlls/mmdevapi/devenum.c
@@ -33,8 +33,128 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(mmdevapi);
 
+typedef struct MMDevEnumImpl
+{
+    IMMDeviceEnumeratorVtbl *lpVtbl;
+    LONG ref;
+} MMDevEnumImpl;
+
+static MMDevEnumImpl *MMDevEnumerator;
+static IMMDeviceEnumeratorVtbl MMDevEnumVtbl;
+
 HRESULT MMDevEnum_Create(REFIID riid, void **ppv)
 {
+    MMDevEnumImpl *This = MMDevEnumerator;
+
+    if (!This)
+    {
+        This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
+        *ppv = NULL;
+        if (!This)
+            return E_OUTOFMEMORY;
+        This->ref = 1;
+        This->lpVtbl = &MMDevEnumVtbl;
+        MMDevEnumerator = This;
+    }
+    return IUnknown_QueryInterface((IUnknown*)This, riid, ppv);
+}
+
+void MMDevEnum_Free(void)
+{
+    HeapFree(GetProcessHeap(), 0, MMDevEnumerator);
+    MMDevEnumerator = NULL;
+}
+
+static HRESULT WINAPI MMDevEnum_QueryInterface(IMMDeviceEnumerator *iface, REFIID riid, void **ppv)
+{
+    MMDevEnumImpl *This = (MMDevEnumImpl*)iface;
+
+    if (!ppv)
+        return E_POINTER;
+    if (IsEqualIID(riid, &IID_IUnknown)
+        || IsEqualIID(riid, &IID_IMMDeviceEnumerator))
+        *ppv = This;
+    else
+        *ppv = NULL;
+    if (!*ppv)
+        return E_NOINTERFACE;
+    IUnknown_AddRef((IUnknown*)*ppv);
+    return S_OK;
+}
+
+static ULONG WINAPI MMDevEnum_AddRef(IMMDeviceEnumerator *iface)
+{
+    MMDevEnumImpl *This = (MMDevEnumImpl*)iface;
+    LONG ref = InterlockedIncrement(&This->ref);
+    TRACE("Refcount now %i\n", ref);
+    return ref;
+}
+
+static ULONG WINAPI MMDevEnum_Release(IMMDeviceEnumerator *iface)
+{
+    MMDevEnumImpl *This = (MMDevEnumImpl*)iface;
+    LONG ref = InterlockedDecrement(&This->ref);
+    if (!ref)
+        MMDevEnum_Free();
+    TRACE("Refcount now %i\n", ref);
+    return ref;
+}
+
+static HRESULT WINAPI MMDevEnum_EnumAudioEndpoints(IMMDeviceEnumerator *iface, EDataFlow flow, DWORD mask, IMMDeviceCollection **devices)
+{
+    MMDevEnumImpl *This = (MMDevEnumImpl*)iface;
+    TRACE("(%p)->(%u,%u,%p)\n", This, flow, mask, devices);
+    if (!devices)
+        return E_POINTER;
+    *devices = NULL;
+    if (flow >= EDataFlow_enum_count)
+        return E_INVALIDARG;
+    if (mask & ~DEVICE_STATEMASK_ALL)
+        return E_INVALIDARG;
+    FIXME("stub\n");
+    return E_NOTFOUND;
+}
+
+static HRESULT WINAPI MMDevEnum_GetDefaultAudioEndpoint(IMMDeviceEnumerator *iface, EDataFlow flow, ERole role, IMMDevice **device)
+{
+    MMDevEnumImpl *This = (MMDevEnumImpl*)iface;
+    TRACE("(%p)->(%u,%u,%p)\n", This, flow, role, device);
     FIXME("stub\n");
-    return CLASS_E_CLASSNOTAVAILABLE;
+    return E_NOTFOUND;
 }
+
+static HRESULT WINAPI MMDevEnum_GetDevice(IMMDeviceEnumerator *iface, const WCHAR *name, IMMDevice **device)
+{
+    MMDevEnumImpl *This = (MMDevEnumImpl*)iface;
+    TRACE("(%p)->(%s,%p)\n", This, debugstr_w(name), device);
+    FIXME("stub\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI MMDevEnum_RegisterEndpointNotificationCallback(IMMDeviceEnumerator *iface, IMMNotificationClient *client)
+{
+    MMDevEnumImpl *This = (MMDevEnumImpl*)iface;
+    TRACE("(%p)->(%p)\n", This, client);
+    FIXME("stub\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI MMDevEnum_UnregisterEndpointNotificationCallback(IMMDeviceEnumerator *iface, IMMNotificationClient *client)
+{
+    MMDevEnumImpl *This = (MMDevEnumImpl*)iface;
+    TRACE("(%p)->(%p)\n", This, client);
+    FIXME("stub\n");
+    return E_NOTIMPL;
+}
+
+static IMMDeviceEnumeratorVtbl MMDevEnumVtbl =
+{
+    MMDevEnum_QueryInterface,
+    MMDevEnum_AddRef,
+    MMDevEnum_Release,
+    MMDevEnum_EnumAudioEndpoints,
+    MMDevEnum_GetDefaultAudioEndpoint,
+    MMDevEnum_GetDevice,
+    MMDevEnum_RegisterEndpointNotificationCallback,
+    MMDevEnum_UnregisterEndpointNotificationCallback
+};
diff --git a/dlls/mmdevapi/main.c b/dlls/mmdevapi/main.c
index d167d80..df5f9e7 100644
--- a/dlls/mmdevapi/main.c
+++ b/dlls/mmdevapi/main.c
@@ -44,6 +44,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
             DisableThreadLibraryCalls(hinstDLL);
             break;
         case DLL_PROCESS_DETACH:
+            MMDevEnum_Free();
             break;
     }
 
diff --git a/dlls/mmdevapi/mmdevapi.h b/dlls/mmdevapi/mmdevapi.h
index e6b878a..bab3af5 100644
--- a/dlls/mmdevapi/mmdevapi.h
+++ b/dlls/mmdevapi/mmdevapi.h
@@ -17,3 +17,4 @@
  */
 
 extern HRESULT MMDevEnum_Create(REFIID riid, void **ppv);
+extern void MMDevEnum_Free(void);
diff --git a/dlls/mmdevapi/tests/mmdevenum.c b/dlls/mmdevapi/tests/mmdevenum.c
index 5ebd32a..06c106f 100644
--- a/dlls/mmdevapi/tests/mmdevenum.c
+++ b/dlls/mmdevapi/tests/mmdevenum.c
@@ -26,6 +26,8 @@
 #include "dshow.h"
 #include "dsound.h"
 
+DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
+
 /* Some of the QueryInterface tests are really just to check if I got the IID's right :) */
 
 /* IMMDeviceCollection appears to have no QueryInterface method and instead forwards to mme */
@@ -82,11 +84,12 @@ static void test_collection(IMMDeviceEnumerator *mme, IMMDeviceCollection *col)
     if (dev) IUnknown_Release(dev);
 }
 
+/* Only do parameter tests here, the actual MMDevice testing should be a separate test */
 START_TEST(mmdevenum)
 {
     HRESULT hr;
     IUnknown *unk = NULL;
-    IMMDeviceEnumerator *mme;
+    IMMDeviceEnumerator *mme, *mme2;
     ULONG ref;
     IMMDeviceCollection *col;
 
@@ -110,6 +113,18 @@ START_TEST(mmdevenum)
     ok( (LONG_PTR)mme == (LONG_PTR)unk, "Pointers are unequal %p/%p\n", unk, mme);
     IUnknown_Release(unk);
 
+    /* Proving that it is static.. */
+    hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&mme2);
+    IUnknown_Release(mme2);
+    ok(mme == mme2, "Pointers are not equal!\n");
+
+    hr = IUnknown_QueryInterface(mme, &IID_IUnknown, NULL);
+    ok(hr == E_POINTER, "Null pointer on QueryInterface returned %08x\n", hr);
+
+    hr = IUnknown_QueryInterface(mme, &GUID_NULL, (void**)&unk);
+    ok(!unk, "Unk not reset to null after invalid QI\n");
+    ok(hr == E_NOINTERFACE, "Invalid hr %08x returned on IID_NULL\n", hr);
+
     col = (void*)(LONG_PTR)0x12345678;
     hr = IMMDeviceEnumerator_EnumAudioEndpoints(mme, 0xffff, DEVICE_STATEMASK_ALL, &col);
     ok(hr == E_INVALIDARG, "Setting invalid data flow returned 0x%08x\n", hr);
@@ -122,7 +137,7 @@ START_TEST(mmdevenum)
     ok(hr == E_POINTER, "Invalid pointer returned: 0x%08x\n", hr);
 
     hr = IMMDeviceEnumerator_EnumAudioEndpoints(mme, eAll, DEVICE_STATEMASK_ALL, &col);
-    ok(hr == S_OK, "Valid EnumAudioEndpoints returned 0x%08x\n", hr);
+    todo_wine ok(hr == S_OK, "Valid EnumAudioEndpoints returned 0x%08x\n", hr);
     if (hr == S_OK)
     {
         ok(!!col, "Returned null pointer\n");




More information about the wine-cvs mailing list