Andrew Eikum : mmdevapi: Implement (Un)RegisterEndpointNotificationCallback .

Alexandre Julliard julliard at winehq.org
Mon Dec 17 13:58:22 CST 2012


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

Author: Andrew Eikum <aeikum at codeweavers.com>
Date:   Fri Dec 14 11:41:53 2012 -0600

mmdevapi: Implement (Un)RegisterEndpointNotificationCallback.

---

 dlls/mmdevapi/devenum.c         |   59 ++++++++++++++++++++++++-
 dlls/mmdevapi/tests/mmdevenum.c |   91 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 147 insertions(+), 3 deletions(-)

diff --git a/dlls/mmdevapi/devenum.c b/dlls/mmdevapi/devenum.c
index d7c5a44..f9b9172 100644
--- a/dlls/mmdevapi/devenum.c
+++ b/dlls/mmdevapi/devenum.c
@@ -27,6 +27,7 @@
 #include "winnls.h"
 #include "winreg.h"
 #include "wine/debug.h"
+#include "wine/list.h"
 #include "wine/unicode.h"
 
 #include "initguid.h"
@@ -1035,20 +1036,72 @@ static HRESULT WINAPI MMDevEnum_GetDevice(IMMDeviceEnumerator *iface, const WCHA
     return E_INVALIDARG;
 }
 
+struct NotificationClientWrapper {
+    IMMNotificationClient *client;
+    struct list entry;
+};
+
+static struct list g_notif_clients = LIST_INIT(g_notif_clients);
+
+static CRITICAL_SECTION g_notif_lock;
+static CRITICAL_SECTION_DEBUG g_notif_lock_debug =
+{
+    0, 0, &g_notif_lock,
+    { &g_notif_lock_debug.ProcessLocksList, &g_notif_lock_debug.ProcessLocksList },
+      0, 0, { (DWORD_PTR)(__FILE__ ": g_notif_lock") }
+};
+static CRITICAL_SECTION g_notif_lock = { &g_notif_lock_debug, -1, 0, 0, 0, 0 };
+
 static HRESULT WINAPI MMDevEnum_RegisterEndpointNotificationCallback(IMMDeviceEnumerator *iface, IMMNotificationClient *client)
 {
     MMDevEnumImpl *This = impl_from_IMMDeviceEnumerator(iface);
+    struct NotificationClientWrapper *wrapper;
+
     TRACE("(%p)->(%p)\n", This, client);
-    FIXME("stub\n");
+
+    if(!client)
+        return E_POINTER;
+
+    wrapper = HeapAlloc(GetProcessHeap(), 0, sizeof(*wrapper));
+    if(!wrapper)
+        return E_OUTOFMEMORY;
+
+    wrapper->client = client;
+
+    EnterCriticalSection(&g_notif_lock);
+
+    list_add_tail(&g_notif_clients, &wrapper->entry);
+
+    LeaveCriticalSection(&g_notif_lock);
+
     return S_OK;
 }
 
 static HRESULT WINAPI MMDevEnum_UnregisterEndpointNotificationCallback(IMMDeviceEnumerator *iface, IMMNotificationClient *client)
 {
     MMDevEnumImpl *This = impl_from_IMMDeviceEnumerator(iface);
+    struct NotificationClientWrapper *wrapper, *wrapper2;
+
     TRACE("(%p)->(%p)\n", This, client);
-    FIXME("stub\n");
-    return S_OK;
+
+    if(!client)
+        return E_POINTER;
+
+    EnterCriticalSection(&g_notif_lock);
+
+    LIST_FOR_EACH_ENTRY_SAFE(wrapper, wrapper2, &g_notif_clients,
+            struct NotificationClientWrapper, entry){
+        if(wrapper->client == client){
+            list_remove(&wrapper->entry);
+            HeapFree(GetProcessHeap(), 0, wrapper);
+            LeaveCriticalSection(&g_notif_lock);
+            return S_OK;
+        }
+    }
+
+    LeaveCriticalSection(&g_notif_lock);
+
+    return E_NOTFOUND;
 }
 
 static const IMMDeviceEnumeratorVtbl MMDevEnumVtbl =
diff --git a/dlls/mmdevapi/tests/mmdevenum.c b/dlls/mmdevapi/tests/mmdevenum.c
index 82dda40..12e2156 100644
--- a/dlls/mmdevapi/tests/mmdevenum.c
+++ b/dlls/mmdevapi/tests/mmdevenum.c
@@ -118,6 +118,73 @@ static void test_collection(IMMDeviceEnumerator *mme, IMMDeviceCollection *col)
     IMMDeviceCollection_Release(col);
 }
 
+static HRESULT WINAPI notif_QueryInterface(IMMNotificationClient *iface,
+        const GUID *riid, void **obj)
+{
+    ok(0, "Unexpected QueryInterface call\n");
+    return E_NOTIMPL;
+}
+
+static ULONG WINAPI notif_AddRef(IMMNotificationClient *iface)
+{
+    ok(0, "Unexpected AddRef call\n");
+    return 2;
+}
+
+static ULONG WINAPI notif_Release(IMMNotificationClient *iface)
+{
+    ok(0, "Unexpected Release call\n");
+    return 1;
+}
+
+static HRESULT WINAPI notif_OnDeviceStateChanged(IMMNotificationClient *iface,
+        const WCHAR *device_id, DWORD new_state)
+{
+    ok(0, "Unexpected OnDeviceStateChanged call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI notif_OnDeviceAdded(IMMNotificationClient *iface,
+        const WCHAR *device_id)
+{
+    ok(0, "Unexpected OnDeviceAdded call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI notif_OnDeviceRemoved(IMMNotificationClient *iface,
+        const WCHAR *device_id)
+{
+    ok(0, "Unexpected OnDeviceRemoved call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI notif_OnDefaultDeviceChanged(IMMNotificationClient *iface,
+        EDataFlow flow, ERole role, const WCHAR *device_id)
+{
+    ok(0, "Unexpected OnDefaultDeviceChanged call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI notif_OnPropertyValueChanged(IMMNotificationClient *iface,
+        const WCHAR *device_id, const PROPERTYKEY key)
+{
+    ok(0, "Unexpected OnPropertyValueChanged call\n");
+    return E_NOTIMPL;
+}
+
+static IMMNotificationClientVtbl notif_vtbl = {
+    notif_QueryInterface,
+    notif_AddRef,
+    notif_Release,
+    notif_OnDeviceStateChanged,
+    notif_OnDeviceAdded,
+    notif_OnDeviceRemoved,
+    notif_OnDefaultDeviceChanged,
+    notif_OnPropertyValueChanged
+};
+
+static IMMNotificationClient notif = { &notif_vtbl };
+
 /* Only do parameter tests here, the actual MMDevice testing should be a separate test */
 START_TEST(mmdevenum)
 {
@@ -192,5 +259,29 @@ START_TEST(mmdevenum)
             test_collection(mme, col);
     }
 
+    hr = IMMDeviceEnumerator_RegisterEndpointNotificationCallback(mme, NULL);
+    ok(hr == E_POINTER, "RegisterEndpointNotificationCallback failed: %08x\n", hr);
+
+    hr = IMMDeviceEnumerator_RegisterEndpointNotificationCallback(mme, &notif);
+    ok(hr == S_OK, "RegisterEndpointNotificationCallback failed: %08x\n", hr);
+
+    hr = IMMDeviceEnumerator_RegisterEndpointNotificationCallback(mme, &notif);
+    ok(hr == S_OK, "RegisterEndpointNotificationCallback failed: %08x\n", hr);
+
+    hr = IMMDeviceEnumerator_UnregisterEndpointNotificationCallback(mme, NULL);
+    ok(hr == E_POINTER, "UnregisterEndpointNotificationCallback failed: %08x\n", hr);
+
+    hr = IMMDeviceEnumerator_UnregisterEndpointNotificationCallback(mme, (IMMNotificationClient*)0xdeadbeef);
+    ok(hr == E_NOTFOUND, "UnregisterEndpointNotificationCallback failed: %08x\n", hr);
+
+    hr = IMMDeviceEnumerator_UnregisterEndpointNotificationCallback(mme, &notif);
+    ok(hr == S_OK, "UnregisterEndpointNotificationCallback failed: %08x\n", hr);
+
+    hr = IMMDeviceEnumerator_UnregisterEndpointNotificationCallback(mme, &notif);
+    ok(hr == S_OK, "UnregisterEndpointNotificationCallback failed: %08x\n", hr);
+
+    hr = IMMDeviceEnumerator_UnregisterEndpointNotificationCallback(mme, &notif);
+    ok(hr == E_NOTFOUND, "UnregisterEndpointNotificationCallback failed: %08x\n", hr);
+
     IMMDeviceEnumerator_Release(mme);
 }




More information about the wine-cvs mailing list