[PATCH 2/2] mmdevapi: Implement IMMDevice

Maarten Lankhorst m.b.lankhorst at gmail.com
Thu Jan 7 02:46:43 CST 2010


---
 dlls/mmdevapi/devenum.c |  186 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 182 insertions(+), 4 deletions(-)

diff --git a/dlls/mmdevapi/devenum.c b/dlls/mmdevapi/devenum.c
index 91eb028..0ffd1e9 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 "ole2.h"
 #include "mmdeviceapi.h"
@@ -42,6 +43,19 @@ static const WCHAR inputguidstr[] =
 static const WCHAR outputguidstr[] =
     { 'O','u','t','p','u','t','G','u','i','d',0 };
 
+typedef struct MMDevice {
+    const IMMDeviceVtbl *lpVtbl;
+    LONG ref;
+
+    CRITICAL_SECTION crst;
+
+    EDataFlow flow;
+    DWORD state;
+    struct list entry;
+    GUID devguid;
+    WCHAR *alname;
+} MMDevice;
+
 typedef struct MMDevEnumImpl
 {
     const IMMDeviceEnumeratorVtbl *lpVtbl;
@@ -49,8 +63,10 @@ typedef struct MMDevEnumImpl
 } MMDevEnumImpl;
 
 static MMDevEnumImpl *MMDevEnumerator;
+struct list MMDevice_head = LIST_INIT(MMDevice_head);
 static const IMMDeviceEnumeratorVtbl MMDevEnumVtbl;
 static const IMMDeviceCollectionVtbl MMDevColVtbl;
+static const IMMDeviceVtbl MMDeviceVtbl;
 
 typedef struct MMDevColImpl
 {
@@ -65,9 +81,150 @@ typedef struct MMDevColImpl
  */
 static void MMDevice_Create(WCHAR *name, GUID *guid, EDataFlow flow, DWORD state)
 {
-    FIXME("stub\n");
+    MMDevice *cur;
+    LIST_FOR_EACH_ENTRY(cur, &MMDevice_head, MMDevice, entry)
+    {
+        if (cur->flow == flow && !lstrcmpW(cur->alname, name))
+        {
+            /* Same device */
+            cur->state = state;
+            return;
+        }
+    }
+
+    /* No device found, allocate new one */
+    cur = HeapAlloc(GetProcessHeap(), 0, sizeof(*cur));
+    if (!cur)
+        return;
+    cur->alname = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(name)+1)*sizeof(WCHAR));
+    if (!cur->alname)
+    {
+        HeapFree(GetProcessHeap(), 0, cur);
+        return;
+    }
+    lstrcpyW(cur->alname, name);
+    cur->lpVtbl = &MMDeviceVtbl;
+    cur->ref = 0;
+    InitializeCriticalSection(&cur->crst);
+    cur->crst.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": MMDevice.crst");
+    cur->flow = flow;
+    cur->state = state;
+    if (guid)
+        cur->devguid = *guid;
+    else
+    {
+        HKEY key, key2;
+
+        CoCreateGuid(&cur->devguid);
+        if (!RegCreateKeyExW(HKEY_CURRENT_USER, software_wine_mmdevapi, 0, NULL, 0, KEY_WRITE, NULL, &key, NULL))
+        {
+            if (!RegCreateKeyExW(key, name, 0, NULL, 0, KEY_WRITE, NULL, &key2, NULL))
+            {
+                WCHAR guidstr[39];
+                StringFromGUID2(&cur->devguid, guidstr, sizeof(guidstr)/sizeof(*guidstr));
+                RegSetValueExW(key2,
+                               flow == eRender ? outputguidstr : inputguidstr,
+                               0, REG_SZ, (const BYTE*)guidstr, sizeof(guidstr));
+                RegCloseKey(key2);
+            }
+            RegCloseKey(key);
+        }
+    }
+    list_add_tail(&MMDevice_head, &cur->entry);
+}
+
+static void MMDevice_Destroy(MMDevice *This)
+{
+    TRACE("Freeing %s\n", debugstr_w(This->alname));
+    list_remove(&This->entry);
+    This->crst.DebugInfo->Spare[0] = 0;
+    DeleteCriticalSection(&This->crst);
+    HeapFree(GetProcessHeap(), 0, This->alname);
+    HeapFree(GetProcessHeap(), 0, This);
 }
 
+static HRESULT WINAPI MMDevice_QueryInterface(IMMDevice *iface, REFIID riid, void **ppv)
+{
+    MMDevice *This = (MMDevice *)iface;
+    TRACE("(%p)->(%s,%p)\n", iface, debugstr_guid(riid), ppv);
+
+    if (!ppv)
+        return E_POINTER;
+    *ppv = NULL;
+    if (IsEqualIID(riid, &IID_IUnknown)
+        || IsEqualIID(riid, &IID_IMMDevice))
+        *ppv = This;
+    if (*ppv)
+    {
+        IUnknown_AddRef((IUnknown*)*ppv);
+        return S_OK;
+    }
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI MMDevice_AddRef(IMMDevice *iface)
+{
+    MMDevice *This = (MMDevice *)iface;
+    LONG ref;
+
+    ref = InterlockedIncrement(&This->ref);
+    TRACE("Refcount now %i\n", ref);
+    if (ref == 1)
+    {
+        /* TODO: code */
+    }
+    return ref;
+}
+
+static ULONG WINAPI MMDevice_Release(IMMDevice *iface)
+{
+    MMDevice *This = (MMDevice *)iface;
+    LONG ref;
+
+    ref = InterlockedDecrement(&This->ref);
+    TRACE("Refcount now %i\n", ref);
+    if (!ref)
+    {
+        /* TODO: code */
+    }
+    return ref;
+}
+
+static HRESULT WINAPI MMDevice_Activate(IMMDevice *iface, REFIID riid, DWORD clsctx, PROPVARIANT *params, void **ppv)
+{
+    FIXME("(%p)->(%s,%u,%p,%p) stub\n", iface, debugstr_guid(riid), clsctx, params, ppv);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI MMDevice_OpenPropertyStore(IMMDevice *iface, DWORD access, IPropertyStore **ppv)
+{
+    FIXME("(%p)->(%x,%p) stub\n", iface, access, ppv);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI MMDevice_GetId(IMMDevice *iface, WCHAR **id)
+{
+    FIXME("(%p)->(%p) stub\n", iface, id);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI MMDevice_GetState(IMMDevice *iface, DWORD *state)
+{
+    FIXME("(%p)->(%p) stub\n", iface, state);
+    return E_NOTIMPL;
+}
+
+static const IMMDeviceVtbl MMDeviceVtbl =
+{
+    MMDevice_QueryInterface,
+    MMDevice_AddRef,
+    MMDevice_Release,
+    MMDevice_Activate,
+    MMDevice_OpenPropertyStore,
+    MMDevice_GetId,
+    MMDevice_GetState
+};
+
 static HRESULT MMDevCol_Create(IMMDeviceCollection **ppv, EDataFlow flow, DWORD state)
 {
     MMDevColImpl *This;
@@ -127,19 +284,37 @@ static ULONG WINAPI MMDevCol_Release(IMMDeviceCollection *iface)
 static HRESULT WINAPI MMDevCol_GetCount(IMMDeviceCollection *iface, UINT *numdevs)
 {
     MMDevColImpl *This = (MMDevColImpl*)iface;
+    MMDevice *cur;
+    DWORD i = 0;
+
     TRACE("(%p)->(%p)\n", This, numdevs);
     if (!numdevs)
         return E_POINTER;
-    *numdevs = 0;
+    LIST_FOR_EACH_ENTRY(cur, &MMDevice_head, MMDevice, entry)
+        ++i;
+    *numdevs = i;
     return S_OK;
 }
 
-static HRESULT WINAPI MMDevCol_Item(IMMDeviceCollection *iface, UINT i, IMMDevice **dev)
+static HRESULT WINAPI MMDevCol_Item(IMMDeviceCollection *iface, UINT n, IMMDevice **dev)
 {
     MMDevColImpl *This = (MMDevColImpl*)iface;
-    TRACE("(%p)->(%u, %p)\n", This, i, dev);
+    MMDevice *cur;
+    DWORD i = 0;
+
+    TRACE("(%p)->(%u, %p)\n", This, n, dev);
     if (!dev)
         return E_POINTER;
+
+    LIST_FOR_EACH_ENTRY(cur, &MMDevice_head, MMDevice, entry)
+    {
+        if (i++ == n)
+        {
+            *dev = (IMMDevice *)cur;
+            IMMDevice_AddRef(*dev);
+            return S_OK;
+        }
+    }
     *dev = NULL;
     return E_INVALIDARG;
 }
@@ -201,6 +376,9 @@ HRESULT MMDevEnum_Create(REFIID riid, void **ppv)
 
 void MMDevEnum_Free(void)
 {
+    MMDevice *cur, *next;
+    LIST_FOR_EACH_ENTRY_SAFE(cur, next, &MMDevice_head, MMDevice, entry)
+        MMDevice_Destroy(cur);
     HeapFree(GetProcessHeap(), 0, MMDevEnumerator);
     MMDevEnumerator = NULL;
 }
-- 
1.6.6




More information about the wine-patches mailing list