[PATCH 4/4] mmdevapi: Implement IMMDevice, try 2
Maarten Lankhorst
m.b.lankhorst at gmail.com
Sun Jan 17 06:38:34 CST 2010
---
dlls/mmdevapi/devenum.c | 193 ++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 189 insertions(+), 4 deletions(-)
diff --git a/dlls/mmdevapi/devenum.c b/dlls/mmdevapi/devenum.c
index a708573..0b534ac 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"
@@ -53,6 +54,20 @@ static const WCHAR reg_alname[] =
static const WCHAR reg_properties[] =
{ 'P','r','o','p','e','r','t','i','e','s',0 };
+typedef struct MMDevice {
+ const IMMDeviceVtbl *lpVtbl;
+ LONG ref;
+
+ CRITICAL_SECTION crst;
+
+ EDataFlow flow;
+ DWORD state;
+ struct list entry;
+ GUID devguid;
+ WCHAR *alname;
+ HKEY key;
+} MMDevice;
+
typedef struct MMDevEnumImpl
{
const IMMDeviceEnumeratorVtbl *lpVtbl;
@@ -60,8 +75,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
{
@@ -77,9 +94,156 @@ typedef struct MMDevColImpl
*/
static void MMDevice_Create(WCHAR *name, GUID *id, EDataFlow flow, DWORD state)
{
- FIXME("stub\n");
+ HKEY key;
+ MMDevice *cur;
+ WCHAR guidstr[39];
+ 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;
+ cur->key = NULL;
+ if (!id)
+ {
+ id = &cur->devguid;
+ CoCreateGuid(id);
+ }
+ StringFromGUID2(id, guidstr, sizeof(guidstr)/sizeof(*guidstr));
+ if (!RegCreateKeyExW(HKEY_LOCAL_MACHINE, software_mmdevapi, 0, NULL, 0, KEY_WRITE, NULL, &key, NULL))
+ {
+ HKEY key2, key3, keyprop;
+ if (!RegCreateKeyExW(key, flow == eRender ? reg_render : reg_capture, 0, NULL, 0, KEY_WRITE, NULL, &key2, NULL))
+ {
+ if (!RegCreateKeyExW(key2, guidstr, 0, NULL, 0, KEY_WRITE, NULL, &key3, NULL))
+ {
+ RegSetValueExW(key3, reg_devicestate, 0, REG_DWORD, (const BYTE*)&state, sizeof(DWORD));
+ RegSetValueExW(key3, reg_alname, 0, REG_SZ, (const BYTE*)name, (lstrlenW(name)+1)*sizeof(*name));
+ if (!RegCreateKeyExW(key3, reg_properties, 0, NULL, 0, KEY_WRITE, NULL, &keyprop, NULL))
+ RegCloseKey(keyprop);
+ cur->key = key3;
+ }
+ 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);
+ RegCloseKey(This->key);
+ 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;
@@ -139,19 +303,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;
}
@@ -229,6 +411,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