ReactOS  0.4.14-dev-556-g4c5b21f
devenum.c
Go to the documentation of this file.
1 /*
2  * Copyright 2009 Maarten Lankhorst
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 
19 #include <stdarg.h>
20 
21 #define NONAMELESSUNION
22 #define COBJMACROS
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winnls.h"
26 #include "winreg.h"
27 #include "wine/debug.h"
28 #include "wine/list.h"
29 
30 #include "initguid.h"
31 #include "ole2.h"
32 #include "mmdeviceapi.h"
33 #include "dshow.h"
34 #include "dsound.h"
35 #include "audioclient.h"
36 #include "endpointvolume.h"
37 #include "audiopolicy.h"
38 
39 #include "mmdevapi.h"
40 #include "devpkey.h"
41 
43 
44 static const WCHAR software_mmdevapi[] =
45  { 'S','o','f','t','w','a','r','e','\\',
46  'M','i','c','r','o','s','o','f','t','\\',
47  'W','i','n','d','o','w','s','\\',
48  'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
49  'M','M','D','e','v','i','c','e','s','\\',
50  'A','u','d','i','o',0};
51 static const WCHAR reg_render[] =
52  { 'R','e','n','d','e','r',0 };
53 static const WCHAR reg_capture[] =
54  { 'C','a','p','t','u','r','e',0 };
55 static const WCHAR reg_devicestate[] =
56  { 'D','e','v','i','c','e','S','t','a','t','e',0 };
57 static const WCHAR reg_properties[] =
58  { 'P','r','o','p','e','r','t','i','e','s',0 };
59 static const WCHAR slashW[] = {'\\',0};
60 static const WCHAR reg_out_nameW[] = {'D','e','f','a','u','l','t','O','u','t','p','u','t',0};
61 static const WCHAR reg_vout_nameW[] = {'D','e','f','a','u','l','t','V','o','i','c','e','O','u','t','p','u','t',0};
62 static const WCHAR reg_in_nameW[] = {'D','e','f','a','u','l','t','I','n','p','u','t',0};
63 static const WCHAR reg_vin_nameW[] = {'D','e','f','a','u','l','t','V','o','i','c','e','I','n','p','u','t',0};
64 
67 
68 typedef struct MMDevPropStoreImpl
69 {
75 
76 typedef struct MMDevEnumImpl
77 {
81 
86 static const IMMDeviceEnumeratorVtbl MMDevEnumVtbl;
87 static const IMMDeviceCollectionVtbl MMDevColVtbl;
88 static const IMMDeviceVtbl MMDeviceVtbl;
89 static const IPropertyStoreVtbl MMDevPropVtbl;
90 static const IMMEndpointVtbl MMEndpointVtbl;
91 
93 
94 typedef struct MMDevColImpl
95 {
100 } MMDevColImpl;
101 
102 typedef struct IPropertyBagImpl {
106 
107 static const IPropertyBagVtbl PB_Vtbl;
108 
110 
112 {
113  return CONTAINING_RECORD(iface, MMDevPropStore, IPropertyStore_iface);
114 }
115 
117 {
118  return CONTAINING_RECORD(iface, MMDevEnumImpl, IMMDeviceEnumerator_iface);
119 }
120 
122 {
123  return CONTAINING_RECORD(iface, MMDevColImpl, IMMDeviceCollection_iface);
124 }
125 
127 {
128  return CONTAINING_RECORD(iface, IPropertyBagImpl, IPropertyBag_iface);
129 }
130 
131 static const WCHAR propkey_formatW[] = {
132  '{','%','0','8','X','-','%','0','4','X','-',
133  '%','0','4','X','-','%','0','2','X','%','0','2','X','-',
134  '%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X',
135  '%','0','2','X','%','0','2','X','}',',','%','d',0 };
136 
137 static HRESULT MMDevPropStore_OpenPropKey(const GUID *guid, DWORD flow, HKEY *propkey)
138 {
139  WCHAR buffer[39];
140  LONG ret;
141  HKEY key;
144  {
145  WARN("Opening key %s failed with %u\n", debugstr_w(buffer), ret);
146  return E_FAIL;
147  }
149  RegCloseKey(key);
150  if (ret != ERROR_SUCCESS)
151  {
152  WARN("Opening key %s failed with %u\n", debugstr_w(reg_properties), ret);
153  return E_FAIL;
154  }
155  return S_OK;
156 }
157 
158 static HRESULT MMDevice_GetPropValue(const GUID *devguid, DWORD flow, REFPROPERTYKEY key, PROPVARIANT *pv)
159 {
160  WCHAR buffer[80];
161  const GUID *id = &key->fmtid;
162  DWORD type, size;
163  HRESULT hr = S_OK;
164  HKEY regkey;
165  LONG ret;
166 
167  hr = MMDevPropStore_OpenPropKey(devguid, flow, &regkey);
168  if (FAILED(hr))
169  return hr;
170  wsprintfW( buffer, propkey_formatW, id->Data1, id->Data2, id->Data3,
171  id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3],
172  id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7], key->pid );
173  ret = RegGetValueW(regkey, NULL, buffer, RRF_RT_ANY, &type, NULL, &size);
174  if (ret != ERROR_SUCCESS)
175  {
176  WARN("Reading %s returned %d\n", debugstr_w(buffer), ret);
177  RegCloseKey(regkey);
178  PropVariantClear(pv);
179  return S_OK;
180  }
181 
182  switch (type)
183  {
184  case REG_SZ:
185  {
186  pv->vt = VT_LPWSTR;
187  pv->u.pwszVal = CoTaskMemAlloc(size);
188  if (!pv->u.pwszVal)
189  hr = E_OUTOFMEMORY;
190  else
191  RegGetValueW(regkey, NULL, buffer, RRF_RT_REG_SZ, NULL, (BYTE*)pv->u.pwszVal, &size);
192  break;
193  }
194  case REG_DWORD:
195  {
196  pv->vt = VT_UI4;
197  RegGetValueW(regkey, NULL, buffer, RRF_RT_REG_DWORD, NULL, (BYTE*)&pv->u.ulVal, &size);
198  break;
199  }
200  case REG_BINARY:
201  {
202  pv->vt = VT_BLOB;
203  pv->u.blob.cbSize = size;
204  pv->u.blob.pBlobData = CoTaskMemAlloc(size);
205  if (!pv->u.blob.pBlobData)
206  hr = E_OUTOFMEMORY;
207  else
208  RegGetValueW(regkey, NULL, buffer, RRF_RT_REG_BINARY, NULL, (BYTE*)pv->u.blob.pBlobData, &size);
209  break;
210  }
211  default:
212  ERR("Unknown/unhandled type: %u\n", type);
213  PropVariantClear(pv);
214  break;
215  }
216  RegCloseKey(regkey);
217  return hr;
218 }
219 
220 static HRESULT MMDevice_SetPropValue(const GUID *devguid, DWORD flow, REFPROPERTYKEY key, REFPROPVARIANT pv)
221 {
222  WCHAR buffer[80];
223  const GUID *id = &key->fmtid;
224  HRESULT hr;
225  HKEY regkey;
226  LONG ret;
227 
228  hr = MMDevPropStore_OpenPropKey(devguid, flow, &regkey);
229  if (FAILED(hr))
230  return hr;
231  wsprintfW( buffer, propkey_formatW, id->Data1, id->Data2, id->Data3,
232  id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3],
233  id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7], key->pid );
234  switch (pv->vt)
235  {
236  case VT_UI4:
237  {
238  ret = RegSetValueExW(regkey, buffer, 0, REG_DWORD, (const BYTE*)&pv->u.ulVal, sizeof(DWORD));
239  break;
240  }
241  case VT_BLOB:
242  {
243  ret = RegSetValueExW(regkey, buffer, 0, REG_BINARY, pv->u.blob.pBlobData, pv->u.blob.cbSize);
244  TRACE("Blob %p %u\n", pv->u.blob.pBlobData, pv->u.blob.cbSize);
245 
246  break;
247  }
248  case VT_LPWSTR:
249  {
250  ret = RegSetValueExW(regkey, buffer, 0, REG_SZ, (const BYTE*)pv->u.pwszVal, sizeof(WCHAR)*(1+lstrlenW(pv->u.pwszVal)));
251  break;
252  }
253  default:
254  ret = 0;
255  FIXME("Unhandled type %u\n", pv->vt);
256  hr = E_INVALIDARG;
257  break;
258  }
259  RegCloseKey(regkey);
260  TRACE("Writing %s returned %u\n", debugstr_w(buffer), ret);
261  return hr;
262 }
263 
264 static HRESULT set_driver_prop_value(GUID *id, const EDataFlow flow, const PROPERTYKEY *prop)
265 {
266  HRESULT hr;
267  PROPVARIANT pv;
268 
269  if (!drvs.pGetPropValue)
270  return E_NOTIMPL;
271 
272  hr = drvs.pGetPropValue(id, prop, &pv);
273 
274  if (SUCCEEDED(hr))
275  {
276  MMDevice_SetPropValue(id, flow, prop, &pv);
277  PropVariantClear(&pv);
278  }
279 
280  return hr;
281 }
282 
283 /* Creates or updates the state of a device
284  * If GUID is null, a random guid will be assigned
285  * and the device will be created
286  */
287 static MMDevice *MMDevice_Create(WCHAR *name, GUID *id, EDataFlow flow, DWORD state, BOOL setdefault)
288 {
289  HKEY key, root;
290  MMDevice *cur = NULL;
291  WCHAR guidstr[39];
292  DWORD i;
293 
294  static const PROPERTYKEY deviceinterface_key = {
295  {0x233164c8, 0x1b2c, 0x4c7d, {0xbc, 0x68, 0xb6, 0x71, 0x68, 0x7a, 0x25, 0x67}}, 1
296  };
297 
298  static const PROPERTYKEY devicepath_key = {
299  {0xb3f8fa53, 0x0004, 0x438e, {0x90, 0x03, 0x51, 0xa4, 0x6e, 0x13, 0x9b, 0xfc}}, 2
300  };
301 
302  for (i = 0; i < MMDevice_count; ++i)
303  {
305  if (device->flow == flow && IsEqualGUID(&device->devguid, id)){
306  cur = device;
307  break;
308  }
309  }
310 
311  if(!cur){
312  /* No device found, allocate new one */
313  cur = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*cur));
314  if (!cur)
315  return NULL;
316 
317  cur->IMMDevice_iface.lpVtbl = &MMDeviceVtbl;
318  cur->IMMEndpoint_iface.lpVtbl = &MMEndpointVtbl;
319 
321  cur->crst.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": MMDevice.crst");
322 
323  if (!MMDevice_head)
325  else
327  MMDevice_head[MMDevice_count++] = cur;
328  }else if(cur->ref > 0)
329  WARN("Modifying an MMDevice with postitive reference count!\n");
330 
331  HeapFree(GetProcessHeap(), 0, cur->drv_id);
332  cur->drv_id = name;
333 
334  cur->flow = flow;
335  cur->state = state;
336  cur->devguid = *id;
337 
338  StringFromGUID2(&cur->devguid, guidstr, ARRAY_SIZE(guidstr));
339 
340  if (flow == eRender)
341  root = key_render;
342  else
343  root = key_capture;
344 
346  {
347  HKEY keyprop;
348  RegSetValueExW(key, reg_devicestate, 0, REG_DWORD, (const BYTE*)&state, sizeof(DWORD));
350  {
351  PROPVARIANT pv;
352 
353  pv.vt = VT_LPWSTR;
354  pv.u.pwszVal = name;
355  MMDevice_SetPropValue(id, flow, (const PROPERTYKEY*)&DEVPKEY_Device_FriendlyName, &pv);
356  MMDevice_SetPropValue(id, flow, (const PROPERTYKEY*)&DEVPKEY_DeviceInterface_FriendlyName, &pv);
357  MMDevice_SetPropValue(id, flow, (const PROPERTYKEY*)&DEVPKEY_Device_DeviceDesc, &pv);
358 
359  pv.u.pwszVal = guidstr;
360  MMDevice_SetPropValue(id, flow, &deviceinterface_key, &pv);
361 
362  set_driver_prop_value(id, flow, &devicepath_key);
363 
364  if (FAILED(set_driver_prop_value(id, flow, &PKEY_AudioEndpoint_FormFactor)))
365  {
366  pv.vt = VT_UI4;
367  pv.u.ulVal = (flow == eCapture) ? Microphone : Speakers;
368 
369  MMDevice_SetPropValue(id, flow, &PKEY_AudioEndpoint_FormFactor, &pv);
370  }
371 
372  if (flow != eCapture)
373  {
374  PROPVARIANT pv2;
375 
376  PropVariantInit(&pv2);
377 
378  /* make read-write by not overwriting if already set */
379  if (FAILED(MMDevice_GetPropValue(id, flow, &PKEY_AudioEndpoint_PhysicalSpeakers, &pv2)) || pv2.vt != VT_UI4)
380  set_driver_prop_value(id, flow, &PKEY_AudioEndpoint_PhysicalSpeakers);
381 
383  }
384 
385  RegCloseKey(keyprop);
386  }
387  RegCloseKey(key);
388  }
389 
390  if (setdefault)
391  {
392  if (flow == eRender)
393  MMDevice_def_play = cur;
394  else
395  MMDevice_def_rec = cur;
396  }
397  return cur;
398 }
399 
401 {
402  DWORD i = 0;
403  HKEY root, cur;
404  LONG ret;
405  DWORD curflow;
406 
408  if (ret == ERROR_SUCCESS)
410  if (ret == ERROR_SUCCESS)
412  RegCloseKey(root);
413  cur = key_capture;
414  curflow = eCapture;
415  if (ret != ERROR_SUCCESS)
416  {
419  WARN("Couldn't create key: %u\n", ret);
420  return E_FAIL;
421  }
422 
423  do {
424  WCHAR guidvalue[39];
425  GUID guid;
426  DWORD len;
427  PROPVARIANT pv = { VT_EMPTY };
428 
429  len = ARRAY_SIZE(guidvalue);
430  ret = RegEnumKeyExW(cur, i++, guidvalue, &len, NULL, NULL, NULL, NULL);
431  if (ret == ERROR_NO_MORE_ITEMS)
432  {
433  if (cur == key_capture)
434  {
435  cur = key_render;
436  curflow = eRender;
437  i = 0;
438  continue;
439  }
440  break;
441  }
442  if (ret != ERROR_SUCCESS)
443  continue;
444  if (SUCCEEDED(CLSIDFromString(guidvalue, &guid))
445  && SUCCEEDED(MMDevice_GetPropValue(&guid, curflow, (const PROPERTYKEY*)&DEVPKEY_Device_FriendlyName, &pv))
446  && pv.vt == VT_LPWSTR)
447  {
448  DWORD size_bytes = (lstrlenW(pv.u.pwszVal) + 1) * sizeof(WCHAR);
449  WCHAR *name = HeapAlloc(GetProcessHeap(), 0, size_bytes);
450  memcpy(name, pv.u.pwszVal, size_bytes);
451  MMDevice_Create(name, &guid, curflow,
452  DEVICE_STATE_NOTPRESENT, FALSE);
453  CoTaskMemFree(pv.u.pwszVal);
454  }
455  } while (1);
456 
457  return S_OK;
458 }
459 
461 {
462  HRESULT hr;
464  WAVEFORMATEX *fmt;
465  PROPVARIANT pv = { VT_EMPTY };
466 
467  hr = drvs.pGetAudioEndpoint(&dev->devguid, &dev->IMMDevice_iface, &client);
468  if(FAILED(hr))
469  return hr;
470 
471  hr = IAudioClient_GetMixFormat(client, &fmt);
472  if(FAILED(hr)){
473  IAudioClient_Release(client);
474  return hr;
475  }
476 
477  IAudioClient_Release(client);
478 
479  pv.vt = VT_BLOB;
480  pv.u.blob.cbSize = sizeof(WAVEFORMATEX) + fmt->cbSize;
481  pv.u.blob.pBlobData = (BYTE*)fmt;
482  MMDevice_SetPropValue(&dev->devguid, dev->flow,
483  &PKEY_AudioEngine_DeviceFormat, &pv);
484  MMDevice_SetPropValue(&dev->devguid, dev->flow,
485  &PKEY_AudioEngine_OEMFormat, &pv);
487 
488  return S_OK;
489 }
490 
492 {
493  WCHAR **ids;
494  GUID *guids;
495  UINT num, def, i;
496  HRESULT hr;
497 
498  if(!drvs.pGetEndpointIDs)
499  return S_OK;
500 
501  hr = drvs.pGetEndpointIDs(flow, &ids, &guids, &num, &def);
502  if(FAILED(hr))
503  return hr;
504 
505  for(i = 0; i < num; ++i){
506  MMDevice *dev;
507  dev = MMDevice_Create(ids[i], &guids[i], flow, DEVICE_STATE_ACTIVE,
508  def == i);
509  set_format(dev);
510  }
511 
512  HeapFree(GetProcessHeap(), 0, guids);
513  HeapFree(GetProcessHeap(), 0, ids);
514 
515  return S_OK;
516 }
517 
519 {
520  DWORD i;
521  TRACE("Freeing %s\n", debugstr_w(This->drv_id));
522  /* Since this function is called at destruction time, reordering of the list is unimportant */
523  for (i = 0; i < MMDevice_count; ++i)
524  {
525  if (MMDevice_head[i] == This)
526  {
528  break;
529  }
530  }
531  This->crst.DebugInfo->Spare[0] = 0;
532  DeleteCriticalSection(&This->crst);
533  HeapFree(GetProcessHeap(), 0, This->drv_id);
535 }
536 
537 static inline MMDevice *impl_from_IMMDevice(IMMDevice *iface)
538 {
539  return CONTAINING_RECORD(iface, MMDevice, IMMDevice_iface);
540 }
541 
543 {
545  TRACE("(%p)->(%s,%p)\n", iface, debugstr_guid(riid), ppv);
546 
547  if (!ppv)
548  return E_POINTER;
549  *ppv = NULL;
551  || IsEqualIID(riid, &IID_IMMDevice))
552  *ppv = &This->IMMDevice_iface;
553  else if (IsEqualIID(riid, &IID_IMMEndpoint))
554  *ppv = &This->IMMEndpoint_iface;
555  if (*ppv)
556  {
557  IUnknown_AddRef((IUnknown*)*ppv);
558  return S_OK;
559  }
560  WARN("Unknown interface %s\n", debugstr_guid(riid));
561  return E_NOINTERFACE;
562 }
563 
565 {
567  LONG ref;
568 
569  ref = InterlockedIncrement(&This->ref);
570  TRACE("Refcount now %i\n", ref);
571  return ref;
572 }
573 
575 {
577  LONG ref;
578 
579  ref = InterlockedDecrement(&This->ref);
580  TRACE("Refcount now %i\n", ref);
581  return ref;
582 }
583 
584 static HRESULT WINAPI MMDevice_Activate(IMMDevice *iface, REFIID riid, DWORD clsctx, PROPVARIANT *params, void **ppv)
585 {
588 
589  TRACE("(%p)->(%s, %x, %p, %p)\n", iface, debugstr_guid(riid), clsctx, params, ppv);
590 
591  if (!ppv)
592  return E_POINTER;
593 
594  if (IsEqualIID(riid, &IID_IAudioClient)){
595  hr = drvs.pGetAudioEndpoint(&This->devguid, iface, (IAudioClient**)ppv);
596  }else if (IsEqualIID(riid, &IID_IAudioEndpointVolume) ||
597  IsEqualIID(riid, &IID_IAudioEndpointVolumeEx))
599  else if (IsEqualIID(riid, &IID_IAudioSessionManager)
600  || IsEqualIID(riid, &IID_IAudioSessionManager2))
601  {
602  hr = drvs.pGetAudioSessionManager(iface, (IAudioSessionManager2**)ppv);
603  }
604  else if (IsEqualIID(riid, &IID_IBaseFilter))
605  {
606  if (This->flow == eRender)
607  hr = CoCreateInstance(&CLSID_DSoundRender, NULL, clsctx, riid, ppv);
608  else
609  ERR("Not supported for recording?\n");
610  if (SUCCEEDED(hr))
611  {
612  IPersistPropertyBag *ppb;
613  hr = IUnknown_QueryInterface((IUnknown*)*ppv, &IID_IPersistPropertyBag, (void **)&ppb);
614  if (SUCCEEDED(hr))
615  {
616  /* ::Load cannot assume the interface stays alive after the function returns,
617  * so just create the interface on the stack, saves a lot of complicated code */
618  IPropertyBagImpl bag = { { &PB_Vtbl } };
619  bag.devguid = This->devguid;
620  hr = IPersistPropertyBag_Load(ppb, &bag.IPropertyBag_iface, NULL);
621  IPersistPropertyBag_Release(ppb);
622  if (FAILED(hr))
623  IBaseFilter_Release((IBaseFilter*)*ppv);
624  }
625  else
626  {
627  FIXME("Wine doesn't support IPersistPropertyBag on DSoundRender yet, ignoring..\n");
628  hr = S_OK;
629  }
630  }
631  }
632  else if (IsEqualIID(riid, &IID_IDeviceTopology))
633  {
634  FIXME("IID_IDeviceTopology unsupported\n");
635  }
636  else if (IsEqualIID(riid, &IID_IDirectSound)
637  || IsEqualIID(riid, &IID_IDirectSound8))
638  {
639  if (This->flow == eRender)
640  hr = CoCreateInstance(&CLSID_DirectSound8, NULL, clsctx, riid, ppv);
641  if (SUCCEEDED(hr))
642  {
643  hr = IDirectSound_Initialize((IDirectSound*)*ppv, &This->devguid);
644  if (FAILED(hr))
645  IDirectSound_Release((IDirectSound*)*ppv);
646  }
647  }
648  else if (IsEqualIID(riid, &IID_IDirectSoundCapture))
649  {
650  if (This->flow == eCapture)
651  hr = CoCreateInstance(&CLSID_DirectSoundCapture8, NULL, clsctx, riid, ppv);
652  if (SUCCEEDED(hr))
653  {
654  hr = IDirectSoundCapture_Initialize((IDirectSoundCapture*)*ppv, &This->devguid);
655  if (FAILED(hr))
656  IDirectSoundCapture_Release((IDirectSoundCapture*)*ppv);
657  }
658  }
659  else
660  ERR("Invalid/unknown iid %s\n", debugstr_guid(riid));
661 
662  if (FAILED(hr))
663  *ppv = NULL;
664 
665  TRACE("Returning %08x\n", hr);
666  return hr;
667 }
668 
670 {
672  TRACE("(%p)->(%x,%p)\n", This, access, ppv);
673 
674  if (!ppv)
675  return E_POINTER;
677 }
678 
679 static HRESULT WINAPI MMDevice_GetId(IMMDevice *iface, WCHAR **itemid)
680 {
682  WCHAR *str;
683  GUID *id = &This->devguid;
684  static const WCHAR formatW[] = { '{','0','.','0','.','%','u','.','0','0','0','0','0','0','0','0','}','.',
685  '{','%','0','8','X','-','%','0','4','X','-',
686  '%','0','4','X','-','%','0','2','X','%','0','2','X','-',
687  '%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X',
688  '%','0','2','X','%','0','2','X','}',0 };
689 
690  TRACE("(%p)->(%p)\n", This, itemid);
691  if (!itemid)
692  return E_POINTER;
693  *itemid = str = CoTaskMemAlloc(56 * sizeof(WCHAR));
694  if (!str)
695  return E_OUTOFMEMORY;
696  wsprintfW( str, formatW, This->flow, id->Data1, id->Data2, id->Data3,
697  id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3],
698  id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7] );
699  TRACE("returning %s\n", wine_dbgstr_w(str));
700  return S_OK;
701 }
702 
704 {
706  TRACE("(%p)->(%p)\n", iface, state);
707 
708  if (!state)
709  return E_POINTER;
710  *state = This->state;
711  return S_OK;
712 }
713 
714 static const IMMDeviceVtbl MMDeviceVtbl =
715 {
723 };
724 
726 {
727  return CONTAINING_RECORD(iface, MMDevice, IMMEndpoint_iface);
728 }
729 
731 {
733  TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
734  return IMMDevice_QueryInterface(&This->IMMDevice_iface, riid, ppv);
735 }
736 
738 {
740  TRACE("(%p)\n", This);
741  return IMMDevice_AddRef(&This->IMMDevice_iface);
742 }
743 
745 {
747  TRACE("(%p)\n", This);
748  return IMMDevice_Release(&This->IMMDevice_iface);
749 }
750 
752 {
754  TRACE("(%p)->(%p)\n", This, flow);
755  if (!flow)
756  return E_POINTER;
757  *flow = This->flow;
758  return S_OK;
759 }
760 
761 static const IMMEndpointVtbl MMEndpointVtbl =
762 {
767 };
768 
770 {
772 
773  This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
774  *ppv = NULL;
775  if (!This)
776  return E_OUTOFMEMORY;
777  This->IMMDeviceCollection_iface.lpVtbl = &MMDevColVtbl;
778  This->ref = 1;
779  This->flow = flow;
780  This->state = state;
781  *ppv = &This->IMMDeviceCollection_iface;
782  return S_OK;
783 }
784 
786 {
788 }
789 
791 {
793  TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
794 
795  if (!ppv)
796  return E_POINTER;
798  || IsEqualIID(riid, &IID_IMMDeviceCollection))
799  *ppv = &This->IMMDeviceCollection_iface;
800  else
801  *ppv = NULL;
802  if (!*ppv)
803  return E_NOINTERFACE;
804  IUnknown_AddRef((IUnknown*)*ppv);
805  return S_OK;
806 }
807 
809 {
812  TRACE("Refcount now %i\n", ref);
813  return ref;
814 }
815 
817 {
820  TRACE("Refcount now %i\n", ref);
821  if (!ref)
823  return ref;
824 }
825 
827 {
829  DWORD i;
830 
831  TRACE("(%p)->(%p)\n", This, numdevs);
832  if (!numdevs)
833  return E_POINTER;
834 
835  *numdevs = 0;
836  for (i = 0; i < MMDevice_count; ++i)
837  {
838  MMDevice *cur = MMDevice_head[i];
839  if ((cur->flow == This->flow || This->flow == eAll)
840  && (cur->state & This->state))
841  ++(*numdevs);
842  }
843  return S_OK;
844 }
845 
847 {
849  DWORD i = 0, j = 0;
850 
851  TRACE("(%p)->(%u, %p)\n", This, n, dev);
852  if (!dev)
853  return E_POINTER;
854 
855  for (j = 0; j < MMDevice_count; ++j)
856  {
857  MMDevice *cur = MMDevice_head[j];
858  if ((cur->flow == This->flow || This->flow == eAll)
859  && (cur->state & This->state)
860  && i++ == n)
861  {
862  *dev = &cur->IMMDevice_iface;
863  IMMDevice_AddRef(*dev);
864  return S_OK;
865  }
866  }
867  WARN("Could not obtain item %u\n", n);
868  *dev = NULL;
869  return E_INVALIDARG;
870 }
871 
872 static const IMMDeviceCollectionVtbl MMDevColVtbl =
873 {
879 };
880 
882 {
884 
885  if (!This)
886  {
887  This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
888  *ppv = NULL;
889  if (!This)
890  return E_OUTOFMEMORY;
891  This->ref = 1;
892  This->IMMDeviceEnumerator_iface.lpVtbl = &MMDevEnumVtbl;
894 
898  }
899  return IMMDeviceEnumerator_QueryInterface(&This->IMMDeviceEnumerator_iface, riid, ppv);
900 }
901 
902 void MMDevEnum_Free(void)
903 {
904  while (MMDevice_count)
911 }
912 
914 {
916  TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
917 
918  if (!ppv)
919  return E_POINTER;
921  || IsEqualIID(riid, &IID_IMMDeviceEnumerator))
922  *ppv = &This->IMMDeviceEnumerator_iface;
923  else
924  *ppv = NULL;
925  if (!*ppv)
926  return E_NOINTERFACE;
927  IUnknown_AddRef((IUnknown*)*ppv);
928  return S_OK;
929 }
930 
932 {
935  TRACE("Refcount now %i\n", ref);
936  return ref;
937 }
938 
940 {
943  if (!ref)
944  MMDevEnum_Free();
945  TRACE("Refcount now %i\n", ref);
946  return ref;
947 }
948 
950 {
952  TRACE("(%p)->(%u,%u,%p)\n", This, flow, mask, devices);
953  if (!devices)
954  return E_POINTER;
955  *devices = NULL;
956  if (flow >= EDataFlow_enum_count)
957  return E_INVALIDARG;
958  if (mask & ~DEVICE_STATEMASK_ALL)
959  return E_INVALIDARG;
960  return MMDevCol_Create(devices, flow, mask);
961 }
962 
964 {
966  WCHAR reg_key[256];
967  HKEY key;
968  HRESULT hr;
969 
970  TRACE("(%p)->(%u,%u,%p)\n", This, flow, role, device);
971 
972  if (!device)
973  return E_POINTER;
974 
975  if((flow != eRender && flow != eCapture) ||
976  (role != eConsole && role != eMultimedia && role != eCommunications)){
977  WARN("Unknown flow (%u) or role (%u)\n", flow, role);
978  return E_INVALIDARG;
979  }
980 
981  *device = NULL;
982 
983  if(!drvs.module_name[0])
984  return E_NOTFOUND;
985 
986  lstrcpyW(reg_key, drv_keyW);
987  lstrcatW(reg_key, slashW);
988  lstrcatW(reg_key, drvs.module_name);
989 
990  if(RegOpenKeyW(HKEY_CURRENT_USER, reg_key, &key) == ERROR_SUCCESS){
991  const WCHAR *reg_x_name, *reg_vx_name;
992  WCHAR def_id[256];
993  DWORD size = sizeof(def_id), state;
994 
995  if(flow == eRender){
996  reg_x_name = reg_out_nameW;
997  reg_vx_name = reg_vout_nameW;
998  }else{
999  reg_x_name = reg_in_nameW;
1000  reg_vx_name = reg_vin_nameW;
1001  }
1002 
1003  if(role == eCommunications &&
1004  RegQueryValueExW(key, reg_vx_name, 0, NULL,
1005  (BYTE*)def_id, &size) == ERROR_SUCCESS){
1006  hr = IMMDeviceEnumerator_GetDevice(iface, def_id, device);
1007  if(SUCCEEDED(hr)){
1008  if(SUCCEEDED(IMMDevice_GetState(*device, &state)) &&
1009  state == DEVICE_STATE_ACTIVE){
1010  RegCloseKey(key);
1011  return S_OK;
1012  }
1013  }
1014 
1015  TRACE("Unable to find voice device %s\n", wine_dbgstr_w(def_id));
1016  }
1017 
1018  if(RegQueryValueExW(key, reg_x_name, 0, NULL,
1019  (BYTE*)def_id, &size) == ERROR_SUCCESS){
1020  hr = IMMDeviceEnumerator_GetDevice(iface, def_id, device);
1021  if(SUCCEEDED(hr)){
1022  if(SUCCEEDED(IMMDevice_GetState(*device, &state)) &&
1023  state == DEVICE_STATE_ACTIVE){
1024  RegCloseKey(key);
1025  return S_OK;
1026  }
1027  }
1028 
1029  TRACE("Unable to find device %s\n", wine_dbgstr_w(def_id));
1030  }
1031 
1032  RegCloseKey(key);
1033  }
1034 
1035  if (flow == eRender)
1037  else
1039 
1040  if (!*device)
1041  return E_NOTFOUND;
1042  IMMDevice_AddRef(*device);
1043  return S_OK;
1044 }
1045 
1047 {
1049  DWORD i=0;
1050  IMMDevice *dev = NULL;
1051 
1052  static const WCHAR wine_info_deviceW[] = {'W','i','n','e',' ',
1053  'i','n','f','o',' ','d','e','v','i','c','e',0};
1054 
1055  TRACE("(%p)->(%s,%p)\n", This, debugstr_w(name), device);
1056 
1057  if(!name || !device)
1058  return E_POINTER;
1059 
1060  if(!lstrcmpW(name, wine_info_deviceW)){
1061  *device = &info_device;
1062  return S_OK;
1063  }
1064 
1065  for (i = 0; i < MMDevice_count; ++i)
1066  {
1067  HRESULT hr;
1068  WCHAR *str;
1070  hr = IMMDevice_GetId(dev, &str);
1071  if (FAILED(hr))
1072  {
1073  WARN("GetId failed: %08x\n", hr);
1074  continue;
1075  }
1076 
1077  if (str && !lstrcmpW(str, name))
1078  {
1079  CoTaskMemFree(str);
1080  IMMDevice_AddRef(dev);
1081  *device = dev;
1082  return S_OK;
1083  }
1084  CoTaskMemFree(str);
1085  }
1086  TRACE("Could not find device %s\n", debugstr_w(name));
1087  return E_INVALIDARG;
1088 }
1089 
1092  struct list entry;
1093 };
1094 
1097 
1100 {
1101  0, 0, &g_notif_lock,
1103  0, 0, { (DWORD_PTR)(__FILE__ ": g_notif_lock") }
1104 };
1105 static CRITICAL_SECTION g_notif_lock = { &g_notif_lock_debug, -1, 0, 0, 0, 0 };
1106 
1107 static void notify_clients(EDataFlow flow, ERole role, const WCHAR *id)
1108 {
1109  struct NotificationClientWrapper *wrapper;
1112  IMMNotificationClient_OnDefaultDeviceChanged(wrapper->client, flow,
1113  role, id);
1114 
1115  /* Windows 7 treats changes to eConsole as changes to eMultimedia */
1116  if(role == eConsole)
1117  notify_clients(flow, eMultimedia, id);
1118 }
1119 
1121  const WCHAR *val_name, WCHAR *old_val, IMMDevice *def_dev)
1122 {
1123  WCHAR new_val[64], *id;
1124  DWORD size;
1125  HRESULT hr;
1126 
1127  size = sizeof(new_val);
1128  if(RegQueryValueExW(key, val_name, 0, NULL,
1129  (BYTE*)new_val, &size) != ERROR_SUCCESS){
1130  if(old_val[0] != 0){
1131  /* set by user -> system default */
1132  if(def_dev){
1133  hr = IMMDevice_GetId(def_dev, &id);
1134  if(FAILED(hr)){
1135  ERR("GetId failed: %08x\n", hr);
1136  return FALSE;
1137  }
1138  }else
1139  id = NULL;
1140 
1141  notify_clients(flow, role, id);
1142  old_val[0] = 0;
1143  CoTaskMemFree(id);
1144 
1145  return TRUE;
1146  }
1147 
1148  /* system default -> system default, noop */
1149  return FALSE;
1150  }
1151 
1152  if(!lstrcmpW(old_val, new_val)){
1153  /* set by user -> same value */
1154  return FALSE;
1155  }
1156 
1157  if(new_val[0] != 0){
1158  /* set by user -> different value */
1159  notify_clients(flow, role, new_val);
1160  memcpy(old_val, new_val, sizeof(new_val));
1161  return TRUE;
1162  }
1163 
1164  /* set by user -> system default */
1165  if(def_dev){
1166  hr = IMMDevice_GetId(def_dev, &id);
1167  if(FAILED(hr)){
1168  ERR("GetId failed: %08x\n", hr);
1169  return FALSE;
1170  }
1171  }else
1172  id = NULL;
1173 
1174  notify_clients(flow, role, id);
1175  old_val[0] = 0;
1176  CoTaskMemFree(id);
1177 
1178  return TRUE;
1179 }
1180 
1182 {
1183  HKEY key;
1184  WCHAR reg_key[256];
1185  WCHAR out_name[64], vout_name[64], in_name[64], vin_name[64];
1186  DWORD size;
1187 
1188  lstrcpyW(reg_key, drv_keyW);
1189  lstrcatW(reg_key, slashW);
1190  lstrcatW(reg_key, drvs.module_name);
1191 
1192  if(RegCreateKeyExW(HKEY_CURRENT_USER, reg_key, 0, NULL, 0,
1194  ERR("RegCreateKeyEx failed: %u\n", GetLastError());
1195  return 1;
1196  }
1197 
1198  size = sizeof(out_name);
1200  (BYTE*)out_name, &size) != ERROR_SUCCESS)
1201  out_name[0] = 0;
1202 
1203  size = sizeof(vout_name);
1205  (BYTE*)vout_name, &size) != ERROR_SUCCESS)
1206  vout_name[0] = 0;
1207 
1208  size = sizeof(in_name);
1210  (BYTE*)in_name, &size) != ERROR_SUCCESS)
1211  in_name[0] = 0;
1212 
1213  size = sizeof(vin_name);
1215  (BYTE*)vin_name, &size) != ERROR_SUCCESS)
1216  vin_name[0] = 0;
1217 
1218  while(1){
1220  NULL, FALSE) != ERROR_SUCCESS){
1221  ERR("RegNotifyChangeKeyValue failed: %u\n", GetLastError());
1222  RegCloseKey(key);
1223  g_notif_thread = NULL;
1224  return 1;
1225  }
1226 
1228 
1230  out_name, &MMDevice_def_play->IMMDevice_iface);
1232  vout_name, &MMDevice_def_play->IMMDevice_iface);
1234  in_name, &MMDevice_def_rec->IMMDevice_iface);
1236  vin_name, &MMDevice_def_rec->IMMDevice_iface);
1237 
1239  }
1240 
1241  RegCloseKey(key);
1242 
1243  g_notif_thread = NULL;
1244 
1245  return 0;
1246 }
1247 
1249 {
1251  struct NotificationClientWrapper *wrapper;
1252 
1253  TRACE("(%p)->(%p)\n", This, client);
1254 
1255  if(!client)
1256  return E_POINTER;
1257 
1258  wrapper = HeapAlloc(GetProcessHeap(), 0, sizeof(*wrapper));
1259  if(!wrapper)
1260  return E_OUTOFMEMORY;
1261 
1262  wrapper->client = client;
1263 
1265 
1266  list_add_tail(&g_notif_clients, &wrapper->entry);
1267 
1268  if(!g_notif_thread){
1270  if(!g_notif_thread)
1271  ERR("CreateThread failed: %u\n", GetLastError());
1272  }
1273 
1275 
1276  return S_OK;
1277 }
1278 
1280 {
1282  struct NotificationClientWrapper *wrapper;
1283 
1284  TRACE("(%p)->(%p)\n", This, client);
1285 
1286  if(!client)
1287  return E_POINTER;
1288 
1290 
1292  if(wrapper->client == client){
1293  list_remove(&wrapper->entry);
1294  HeapFree(GetProcessHeap(), 0, wrapper);
1296  return S_OK;
1297  }
1298  }
1299 
1301 
1302  return E_NOTFOUND;
1303 }
1304 
1305 static const IMMDeviceEnumeratorVtbl MMDevEnumVtbl =
1306 {
1315 };
1316 
1318 {
1320  if (access != STGM_READ
1321  && access != STGM_WRITE
1322  && access != STGM_READWRITE)
1323  {
1324  WARN("Invalid access %08x\n", access);
1325  return E_INVALIDARG;
1326  }
1327  This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1328  *ppv = &This->IPropertyStore_iface;
1329  if (!This)
1330  return E_OUTOFMEMORY;
1331  This->IPropertyStore_iface.lpVtbl = &MMDevPropVtbl;
1332  This->ref = 1;
1333  This->parent = parent;
1334  This->access = access;
1335  return S_OK;
1336 }
1337 
1339 {
1340  HeapFree(GetProcessHeap(), 0, This);
1341 }
1342 
1344 {
1346  TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
1347 
1348  if (!ppv)
1349  return E_POINTER;
1351  || IsEqualIID(riid, &IID_IPropertyStore))
1352  *ppv = &This->IPropertyStore_iface;
1353  else
1354  *ppv = NULL;
1355  if (!*ppv)
1356  return E_NOINTERFACE;
1357  IUnknown_AddRef((IUnknown*)*ppv);
1358  return S_OK;
1359 }
1360 
1362 {
1364  LONG ref = InterlockedIncrement(&This->ref);
1365  TRACE("Refcount now %i\n", ref);
1366  return ref;
1367 }
1368 
1370 {
1372  LONG ref = InterlockedDecrement(&This->ref);
1373  TRACE("Refcount now %i\n", ref);
1374  if (!ref)
1376  return ref;
1377 }
1378 
1380 {
1382  WCHAR buffer[50];
1383  DWORD i = 0;
1384  HKEY propkey;
1385  HRESULT hr;
1386 
1387  TRACE("(%p)->(%p)\n", iface, nprops);
1388  if (!nprops)
1389  return E_POINTER;
1390  hr = MMDevPropStore_OpenPropKey(&This->parent->devguid, This->parent->flow, &propkey);
1391  if (FAILED(hr))
1392  return hr;
1393  *nprops = 0;
1394  do {
1396  if (RegEnumValueW(propkey, i, buffer, &len, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
1397  break;
1398  i++;
1399  } while (1);
1400  RegCloseKey(propkey);
1401  TRACE("Returning %i\n", i);
1402  *nprops = i;
1403  return S_OK;
1404 }
1405 
1406 static HRESULT WINAPI MMDevPropStore_GetAt(IPropertyStore *iface, DWORD prop, PROPERTYKEY *key)
1407 {
1409  WCHAR buffer[50];
1411  HRESULT hr;
1412  HKEY propkey;
1413 
1414  TRACE("(%p)->(%u,%p)\n", iface, prop, key);
1415  if (!key)
1416  return E_POINTER;
1417 
1418  hr = MMDevPropStore_OpenPropKey(&This->parent->devguid, This->parent->flow, &propkey);
1419  if (FAILED(hr))
1420  return hr;
1421 
1422  if (RegEnumValueW(propkey, prop, buffer, &len, NULL, NULL, NULL, NULL) != ERROR_SUCCESS
1423  || len <= 39)
1424  {
1425  WARN("GetAt %u failed\n", prop);
1426  return E_INVALIDARG;
1427  }
1428  RegCloseKey(propkey);
1429  buffer[38] = 0;
1430  CLSIDFromString(buffer, &key->fmtid);
1431  key->pid = wcstol(&buffer[39], NULL, 10);
1432  return S_OK;
1433 }
1434 
1436 {
1438  TRACE("(%p)->(\"%s,%u\", %p)\n", This, key ? debugstr_guid(&key->fmtid) : NULL, key ? key->pid : 0, pv);
1439 
1440  if (!key || !pv)
1441  return E_POINTER;
1442  if (This->access != STGM_READ
1443  && This->access != STGM_READWRITE)
1444  return STG_E_ACCESSDENIED;
1445 
1446  /* Special case */
1447  if (IsEqualPropertyKey(*key, PKEY_AudioEndpoint_GUID))
1448  {
1449  pv->vt = VT_LPWSTR;
1450  pv->u.pwszVal = CoTaskMemAlloc(39 * sizeof(WCHAR));
1451  if (!pv->u.pwszVal)
1452  return E_OUTOFMEMORY;
1453  StringFromGUID2(&This->parent->devguid, pv->u.pwszVal, 39);
1454  return S_OK;
1455  }
1456 
1457  return MMDevice_GetPropValue(&This->parent->devguid, This->parent->flow, key, pv);
1458 }
1459 
1461 {
1463  TRACE("(%p)->(\"%s,%u\", %p)\n", This, key ? debugstr_guid(&key->fmtid) : NULL, key ? key->pid : 0, pv);
1464 
1465  if (!key || !pv)
1466  return E_POINTER;
1467 
1468  if (This->access != STGM_WRITE
1469  && This->access != STGM_READWRITE)
1470  return STG_E_ACCESSDENIED;
1471  return MMDevice_SetPropValue(&This->parent->devguid, This->parent->flow, key, pv);
1472 }
1473 
1475 {
1477  TRACE("(%p)\n", iface);
1478 
1479  if (This->access != STGM_WRITE
1480  && This->access != STGM_READWRITE)
1481  return STG_E_ACCESSDENIED;
1482 
1483  /* Does nothing - for mmdevapi, the propstore values are written on SetValue,
1484  * not on Commit. */
1485 
1486  return S_OK;
1487 }
1488 
1489 static const IPropertyStoreVtbl MMDevPropVtbl =
1490 {
1499 };
1500 
1501 
1502 /* Property bag for IBaseFilter activation */
1504 {
1505  ERR("Should not be called\n");
1506  *ppv = NULL;
1507  return E_NOINTERFACE;
1508 }
1509 
1511 {
1512  ERR("Should not be called\n");
1513  return 2;
1514 }
1515 
1517 {
1518  ERR("Should not be called\n");
1519  return 1;
1520 }
1521 
1522 static HRESULT WINAPI PB_Read(IPropertyBag *iface, LPCOLESTR name, VARIANT *var, IErrorLog *log)
1523 {
1524  static const WCHAR dsguid[] = { 'D','S','G','u','i','d', 0 };
1526  TRACE("Trying to read %s, type %u\n", debugstr_w(name), var->n1.n2.vt);
1527  if (!lstrcmpW(name, dsguid))
1528  {
1529  WCHAR guidstr[39];
1530  StringFromGUID2(&This->devguid, guidstr,ARRAY_SIZE(guidstr));
1531  var->n1.n2.vt = VT_BSTR;
1532  var->n1.n2.n3.bstrVal = SysAllocString(guidstr);
1533  return S_OK;
1534  }
1535  ERR("Unknown property '%s' queried\n", debugstr_w(name));
1536  return E_FAIL;
1537 }
1538 
1539 static HRESULT WINAPI PB_Write(IPropertyBag *iface, LPCOLESTR name, VARIANT *var)
1540 {
1541  ERR("Should not be called\n");
1542  return E_FAIL;
1543 }
1544 
1545 static const IPropertyBagVtbl PB_Vtbl =
1546 {
1548  PB_AddRef,
1549  PB_Release,
1550  PB_Read,
1551  PB_Write
1552 };
1553 
1555 {
1556  return 2;
1557 }
1558 
1560 {
1561  return 1;
1562 }
1563 
1565  REFPROPERTYKEY key, PROPVARIANT *pv)
1566 {
1567  TRACE("(static)->(\"%s,%u\", %p)\n", debugstr_guid(&key->fmtid), key ? key->pid : 0, pv);
1568 
1569  if (!key || !pv)
1570  return E_POINTER;
1571 
1572  if (IsEqualPropertyKey(*key, DEVPKEY_Device_Driver))
1573  {
1574  INT size = (lstrlenW(drvs.module_name) + 1) * sizeof(WCHAR);
1575  pv->vt = VT_LPWSTR;
1576  pv->u.pwszVal = CoTaskMemAlloc(size);
1577  if (!pv->u.pwszVal)
1578  return E_OUTOFMEMORY;
1579  memcpy(pv->u.pwszVal, drvs.module_name, size);
1580  return S_OK;
1581  }
1582 
1583  return E_INVALIDARG;
1584 }
1585 
1586 static const IPropertyStoreVtbl info_device_ps_Vtbl =
1587 {
1588  NULL,
1591  NULL,
1592  NULL,
1594  NULL,
1595  NULL
1596 };
1597 
1600 };
1601 
1603 {
1604  return 2;
1605 }
1606 
1608 {
1609  return 1;
1610 }
1611 
1614 {
1615  TRACE("(static)->(%x, %p)\n", access, ppv);
1616  *ppv = &info_device_ps;
1617  return S_OK;
1618 }
1619 
1620 static const IMMDeviceVtbl info_device_Vtbl =
1621 {
1622  NULL,
1625  NULL,
1627  NULL,
1628  NULL
1629 };
1630 
1631 static IMMDevice info_device = {
1633 };
LSTATUS WINAPI RegGetValueW(HKEY hKey, LPCWSTR pszSubKey, LPCWSTR pszValue, DWORD dwFlags, LPDWORD pdwType, PVOID pvData, LPDWORD pcbData)
Definition: reg.c:1965
int WINAPIV wsprintfW(_Out_ LPWSTR, _In_ _Printf_format_string_ LPCWSTR,...)
static const WCHAR software_mmdevapi[]
Definition: devenum.c:44
static HRESULT WINAPI MMDevice_Activate(IMMDevice *iface, REFIID riid, DWORD clsctx, PROPVARIANT *params, void **ppv)
Definition: devenum.c:584
static HRESULT WINAPI info_device_OpenPropertyStore(IMMDevice *iface, DWORD access, IPropertyStore **ppv)
Definition: devenum.c:1612
const GUID IID_IBaseFilter
#define MAXIMUM_ALLOWED
Definition: nt_native.h:83
void MMDevEnum_Free(void)
Definition: devenum.c:902
static const WCHAR reg_render[]
Definition: devenum.c:51
static HRESULT WINAPI info_device_ps_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *pv)
Definition: devenum.c:1564
#define IsEqualPropertyKey(a, b)
Definition: propkeydef.h:52
static ULONG WINAPI MMDevCol_AddRef(IMMDeviceCollection *iface)
Definition: devenum.c:808
IMMEndpoint IMMEndpoint_iface
Definition: mmdevapi.h:63
#define REFIID
Definition: guiddef.h:118
#define TRUE
Definition: types.h:120
static HRESULT WINAPI MMDevEnum_GetDefaultAudioEndpoint(IMMDeviceEnumerator *iface, EDataFlow flow, ERole role, IMMDevice **device)
Definition: devenum.c:963
struct IPropertyBagImpl IPropertyBagImpl
MMDevice * parent
Definition: devenum.c:72
#define E_NOINTERFACE
Definition: winerror.h:2364
HRESULT MMDevEnum_Create(REFIID riid, void **ppv)
Definition: devenum.c:881
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:420
static HRESULT WINAPI MMDevPropStore_GetCount(IPropertyStore *iface, DWORD *nprops)
Definition: devenum.c:1379
static CRITICAL_SECTION g_notif_lock
Definition: devenum.c:1098
#define ERROR_SUCCESS
Definition: deptool.c:10
#define DWORD_PTR
Definition: treelist.c:76
#define IDirectSound_Initialize(p, a)
Definition: dsound.h:462
HRESULT hr
Definition: shlfolder.c:183
static ULONG WINAPI MMDevPropStore_AddRef(IPropertyStore *iface)
Definition: devenum.c:1361
static HRESULT WINAPI MMDevPropStore_QueryInterface(IPropertyStore *iface, REFIID riid, void **ppv)
Definition: devenum.c:1343
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:95
#define IDirectSoundCapture_Release(p)
Definition: dsound.h:736
#define REG_BINARY
Definition: nt_native.h:1496
#define KEY_READ
Definition: nt_native.h:1023
REFIID riid
Definition: precomp.h:44
HRESULT WINAPI PropVariantClear(PROPVARIANT *pvar)
Definition: ole2.c:2968
char * wine_dbgstr_w(const wchar_t *wstr)
Definition: atltest.h:87
static HRESULT set_driver_prop_value(GUID *id, const EDataFlow flow, const PROPERTYKEY *prop)
Definition: devenum.c:264
int WINAPI lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:170
static HRESULT WINAPI MMDevEnum_RegisterEndpointNotificationCallback(IMMDeviceEnumerator *iface, IMMNotificationClient *client)
Definition: devenum.c:1248
#define HKEY_CURRENT_USER
Definition: winreg.h:11
static const IPropertyStoreVtbl MMDevPropVtbl
Definition: devenum.c:89
struct _root root
const char * devices
Definition: diskspace.c:793
IMMDevice IMMDevice_iface
Definition: mmdevapi.h:62
#define WARN(fmt,...)
Definition: debug.h:111
static IPropertyBagImpl * impl_from_IPropertyBag(IPropertyBag *iface)
Definition: devenum.c:126
struct MMDevColImpl MMDevColImpl
const char * fmt
Definition: wsprintf.c:30
REFIID LPVOID * ppv
Definition: atlbase.h:39
GLdouble n
Definition: glext.h:7729
static HRESULT WINAPI MMDevice_GetState(IMMDevice *iface, DWORD *state)
Definition: devenum.c:703
static void MMDevice_Destroy(MMDevice *This)
Definition: devenum.c:518
static HRESULT MMDevCol_Create(IMMDeviceCollection **ppv, EDataFlow flow, DWORD state)
Definition: devenum.c:769
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
static ULONG WINAPI MMDevice_Release(IMMDevice *iface)
Definition: devenum.c:574
#define RRF_RT_REG_SZ
Definition: driver.c:575
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
GLuint buffer
Definition: glext.h:5915
struct tWAVEFORMATEX WAVEFORMATEX
Definition: austream.idl:23
enum _ERole ERole
static CRITICAL_SECTION_DEBUG g_notif_lock_debug
Definition: devenum.c:1099
_Check_return_ long __cdecl wcstol(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
LONG ref
Definition: devenum.c:97
static void MMDevPropStore_Destroy(MMDevPropStore *This)
Definition: devenum.c:1338
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
static ULONG WINAPI info_device_Release(IMMDevice *iface)
Definition: devenum.c:1607
#define lstrlenW
Definition: compat.h:415
#define E_FAIL
Definition: ddrawi.h:102
int32_t INT
Definition: typedefs.h:56
static ULONG WINAPI MMDevCol_Release(IMMDeviceCollection *iface)
Definition: devenum.c:816
Definition: send.c:47
static int dev
Definition: mkdosfs.c:536
static void MMDevCol_Destroy(MMDevColImpl *This)
Definition: devenum.c:785
LONG WINAPI RegCreateKeyExW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ DWORD Reserved, _In_opt_ LPWSTR lpClass, _In_ DWORD dwOptions, _In_ REGSAM samDesired, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _Out_ PHKEY phkResult, _Out_opt_ LPDWORD lpdwDisposition)
Definition: reg.c:1091
static const IPropertyBagVtbl PB_Vtbl
Definition: devenum.c:107
struct MMDevPropStoreImpl MMDevPropStore
static ULONG WINAPI info_device_AddRef(IMMDevice *iface)
Definition: devenum.c:1602
static HRESULT WINAPI MMEndpoint_GetDataFlow(IMMEndpoint *iface, EDataFlow *flow)
Definition: devenum.c:751
static ULONG WINAPI info_device_ps_Release(IPropertyStore *iface)
Definition: devenum.c:1559
__WINE_SERVER_LIST_INLINE void list_add_tail(struct list *list, struct list *elem)
Definition: list.h:102
GLuint * ids
Definition: glext.h:5907
DWORD state
Definition: devenum.c:99
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
static HRESULT WINAPI PB_Write(IPropertyBag *iface, LPCOLESTR name, VARIANT *var)
Definition: devenum.c:1539
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static ULONG WINAPI MMEndpoint_Release(IMMEndpoint *iface)
Definition: devenum.c:744
const GUID * guid
GLenum GLint GLuint mask
Definition: glext.h:6028
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
static DWORD WINAPI notif_thread_proc(void *user)
Definition: devenum.c:1181
static const WCHAR reg_out_nameW[]
Definition: devenum.c:60
static HRESULT MMDevPropStore_Create(MMDevice *This, DWORD access, IPropertyStore **ppv)
Definition: devenum.c:1317
GLenum const GLfloat * params
Definition: glext.h:5645
static const IMMDeviceCollectionVtbl MMDevColVtbl
Definition: devenum.c:87
#define STG_E_ACCESSDENIED
Definition: winerror.h:2568
static ULONG WINAPI PB_AddRef(IPropertyBag *iface)
Definition: devenum.c:1510
static HRESULT load_devices_from_reg(void)
Definition: devenum.c:400
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
Definition: devices.h:37
const GUID IID_IPersistPropertyBag
Definition: proxy.cpp:11
LONG WINAPI RegOpenKeyW(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3296
#define debugstr_w
Definition: kernel32.h:32
static IPropertyStore info_device_ps
Definition: devenum.c:1598
GLenum GLint ref
Definition: glext.h:6028
#define FIXME(fmt,...)
Definition: debug.h:110
enum _EDataFlow EDataFlow
#define E_INVALIDARG
Definition: ddrawi.h:101
const WCHAR * str
LONG WINAPI RegEnumValueW(_In_ HKEY hKey, _In_ DWORD index, _Out_ LPWSTR value, _Inout_ PDWORD val_count, _Reserved_ PDWORD reserved, _Out_opt_ PDWORD type, _Out_opt_ LPBYTE data, _Inout_opt_ PDWORD count)
Definition: reg.c:2853
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:136
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
smooth NULL
Definition: ftsmooth.c:416
#define STGM_WRITE
Definition: objbase.h:917
#define REG_NOTIFY_CHANGE_LAST_SET
Definition: winreg.h:40
BSTR WINAPI SysAllocString(LPCOLESTR str)
Definition: oleaut.c:238
static MMDevice * MMDevice_def_play
Definition: devenum.c:84
static HRESULT set_format(MMDevice *dev)
Definition: devenum.c:460
static MMDevice * impl_from_IMMDevice(IMMDevice *iface)
Definition: devenum.c:537
#define debugstr_guid
Definition: kernel32.h:35
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
static const WCHAR reg_properties[]
Definition: devenum.c:57
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define STGM_READ
Definition: objbase.h:916
static MMDevice ** MMDevice_head
Definition: devenum.c:83
#define KEY_WRITE
Definition: nt_native.h:1031
#define KEY_WOW64_64KEY
Definition: cmtypes.h:46
LONG WINAPI RegSetValueExW(_In_ HKEY hKey, _In_ LPCWSTR lpValueName, _In_ DWORD Reserved, _In_ DWORD dwType, _In_ CONST BYTE *lpData, _In_ DWORD cbData)
Definition: reg.c:4895
__WINE_SERVER_LIST_INLINE void list_remove(struct list *elem)
Definition: list.h:108
static MMDevice * MMDevice_def_rec
Definition: devenum.c:84
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
#define GetProcessHeap()
Definition: compat.h:403
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
static HRESULT WINAPI MMDevPropStore_SetValue(IPropertyStore *iface, REFPROPERTYKEY key, REFPROPVARIANT pv)
Definition: devenum.c:1460
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4116
r parent
Definition: btrfs.c:2869
WCHAR * drv_id
Definition: mmdevapi.h:71
static HRESULT WINAPI MMDevPropStore_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *pv)
Definition: devenum.c:1435
static void notify_clients(EDataFlow flow, ERole role, const WCHAR *id)
Definition: devenum.c:1107
#define LIST_INIT(head)
Definition: queue.h:197
__wchar_t WCHAR
Definition: xmlstorage.h:180
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
static ULONG WINAPI MMDevEnum_Release(IMMDeviceEnumerator *iface)
Definition: devenum.c:939
LONG HRESULT
Definition: typedefs.h:77
static HRESULT WINAPI MMDevEnum_GetDevice(IMMDeviceEnumerator *iface, const WCHAR *name, IMMDevice **device)
Definition: devenum.c:1046
const GUID IID_IUnknown
static HKEY key_capture
Definition: devenum.c:66
#define WINAPI
Definition: msvc.h:8
INT WINAPI StringFromGUID2(REFGUID id, LPOLESTR str, INT cmax)
Definition: compobj.c:2434
#define IDirectSoundCapture_Initialize(p, a)
Definition: dsound.h:740
static FILE * client
Definition: client.c:41
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint num
Definition: glext.h:9618
static HANDLE g_notif_thread
Definition: devenum.c:1096
static HRESULT WINAPI MMDevEnum_EnumAudioEndpoints(IMMDeviceEnumerator *iface, EDataFlow flow, DWORD mask, IMMDeviceCollection **devices)
Definition: devenum.c:949
DWORD state
Definition: mmdevapi.h:69
static HRESULT WINAPI PB_Read(IPropertyBag *iface, LPCOLESTR name, VARIANT *var, IErrorLog *log)
Definition: devenum.c:1522
LONG ref
Definition: devenum.c:79
static HRESULT WINAPI MMDevice_QueryInterface(IMMDevice *iface, REFIID riid, void **ppv)
Definition: devenum.c:542
PCRITICAL_SECTION_DEBUG DebugInfo
Definition: winbase.h:866
static MMDevice * impl_from_IMMEndpoint(IMMEndpoint *iface)
Definition: devenum.c:725
static HRESULT WINAPI MMDevPropStore_Commit(IPropertyStore *iface)
Definition: devenum.c:1474
static const WCHAR reg_in_nameW[]
Definition: devenum.c:62
int ret
static const WCHAR reg_capture[]
Definition: devenum.c:53
static HRESULT WINAPI MMEndpoint_QueryInterface(IMMEndpoint *iface, REFIID riid, void **ppv)
Definition: devenum.c:730
static const IPropertyStoreVtbl info_device_ps_Vtbl
Definition: devenum.c:1586
static HRESULT WINAPI MMDevCol_GetCount(IMMDeviceCollection *iface, UINT *numdevs)
Definition: devenum.c:826
#define InterlockedDecrement
Definition: armddk.h:52
static MMDevice * MMDevice_Create(WCHAR *name, GUID *id, EDataFlow flow, DWORD state, BOOL setdefault)
Definition: devenum.c:287
static HRESULT WINAPI MMDevice_GetId(IMMDevice *iface, WCHAR **itemid)
Definition: devenum.c:679
static const WCHAR propkey_formatW[]
Definition: devenum.c:131
HKEY key
Definition: reg.c:42
static int state
Definition: maze.c:121
uint32_t entry
Definition: isohybrid.c:63
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
unsigned char BYTE
Definition: mem.h:68
static HRESULT MMDevice_GetPropValue(const GUID *devguid, DWORD flow, REFPROPERTYKEY key, PROPVARIANT *pv)
Definition: devenum.c:158
Definition: _list.h:228
static HRESULT WINAPI MMDevCol_Item(IMMDeviceCollection *iface, UINT n, IMMDevice **dev)
Definition: devenum.c:846
static const IMMDeviceVtbl info_device_Vtbl
Definition: devenum.c:1620
LIST_ENTRY ProcessLocksList
Definition: winbase.h:855
const WCHAR drv_keyW[]
Definition: main.c:50
CRITICAL_SECTION crst
Definition: mmdevapi.h:66
#define STGM_READWRITE
Definition: objbase.h:918
static const IMMDeviceEnumeratorVtbl MMDevEnumVtbl
Definition: devenum.c:86
static HRESULT WINAPI MMDevEnum_UnregisterEndpointNotificationCallback(IMMDeviceEnumerator *iface, IMMNotificationClient *client)
Definition: devenum.c:1279
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3325
static ULONG WINAPI MMDevPropStore_Release(IPropertyStore *iface)
Definition: devenum.c:1369
#define ERR(fmt,...)
Definition: debug.h:109
PSSTDAPI typedef PROPERTYKEY * REFPROPERTYKEY
Definition: propsys.idl:30
IMMDeviceEnumerator IMMDeviceEnumerator_iface
Definition: devenum.c:78
IMMNotificationClient * client
Definition: devenum.c:1091
static HKEY key_render
Definition: devenum.c:65
#define S_OK
Definition: intsafe.h:59
LONG WINAPI RegNotifyChangeKeyValue(HKEY hKey, BOOL bWatchSubtree, DWORD dwNotifyFilter, HANDLE hEvent, BOOL fAsynchronous)
Definition: reg.c:3175
IMMDeviceCollection IMMDeviceCollection_iface
Definition: devenum.c:96
HRESULT AudioEndpointVolume_Create(MMDevice *parent, IAudioEndpointVolumeEx **ppv)
Definition: audiovolume.c:305
#define InterlockedIncrement
Definition: armddk.h:53
#define IDirectSound_Release(p)
Definition: dsound.h:453
#define lstrcpyW
Definition: compat.h:414
GLuint GLint GLboolean GLint GLenum access
Definition: glext.h:7866
const void * pv2
Definition: winddi.h:2453
#define ARRAY_SIZE(a)
Definition: main.h:24
IPropertyBag IPropertyBag_iface
Definition: devenum.c:103
DriverFuncs drvs
Definition: main.c:48
static HRESULT MMDevice_SetPropValue(const GUID *devguid, DWORD flow, REFPROPERTYKEY key, REFPROPVARIANT pv)
Definition: devenum.c:220
static const WCHAR reg_vout_nameW[]
Definition: devenum.c:61
#define HeapReAlloc
Definition: compat.h:401
#define E_NOTIMPL
Definition: ddrawi.h:99
static HRESULT WINAPI MMDevEnum_QueryInterface(IMMDeviceEnumerator *iface, REFIID riid, void **ppv)
Definition: devenum.c:913
static HRESULT WINAPI MMDevPropStore_GetAt(IPropertyStore *iface, DWORD prop, PROPERTYKEY *key)
Definition: devenum.c:1406
static const WCHAR reg_devicestate[]
Definition: devenum.c:55
unsigned int UINT
Definition: ndis.h:50
BOOL WINAPI IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
Definition: compobj.c:4112
IPropertyStore IPropertyStore_iface
Definition: devenum.c:70
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
VARTYPE vt
Definition: compat.h:2030
EDataFlow flow
Definition: mmdevapi.h:68
static const IMMDeviceVtbl MMDeviceVtbl
Definition: devenum.c:88
static ULONG WINAPI MMEndpoint_AddRef(IMMEndpoint *iface)
Definition: devenum.c:737
EDataFlow flow
Definition: devenum.c:98
Definition: name.c:38
HRESULT WINAPI CLSIDFromString(LPCOLESTR idstr, LPCLSID id)
Definition: compobj.c:2338
WINE_DEFAULT_DEBUG_CHANNEL(mmdevapi)
unsigned int ULONG
Definition: retypes.h:1
GLenum GLuint id
Definition: glext.h:5579
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3366
LONG ref
Definition: mmdevapi.h:64
static HRESULT WINAPI PB_QueryInterface(IPropertyBag *iface, REFIID riid, void **ppv)
Definition: devenum.c:1503
static HRESULT WINAPI MMDevice_OpenPropertyStore(IMMDevice *iface, DWORD access, IPropertyStore **ppv)
Definition: devenum.c:669
WCHAR module_name[64]
Definition: mmdevapi.h:35
static const WCHAR reg_vin_nameW[]
Definition: devenum.c:63
static HRESULT MMDevPropStore_OpenPropKey(const GUID *guid, DWORD flow, HKEY *propkey)
Definition: devenum.c:137
#define RRF_RT_ANY
Definition: winreg.h:64
static BOOL notify_if_changed(EDataFlow flow, ERole role, HKEY key, const WCHAR *val_name, WCHAR *old_val, IMMDevice *def_dev)
Definition: devenum.c:1120
LONG WINAPI RegEnumKeyExW(_In_ HKEY hKey, _In_ DWORD dwIndex, _Out_ LPWSTR lpName, _Inout_ LPDWORD lpcbName, _Reserved_ LPDWORD lpReserved, _Out_opt_ LPWSTR lpClass, _Inout_opt_ LPDWORD lpcbClass, _Out_opt_ PFILETIME lpftLastWriteTime)
Definition: reg.c:2527
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
static ULONG WINAPI MMDevEnum_AddRef(IMMDeviceEnumerator *iface)
Definition: devenum.c:931
struct MMDevEnumImpl MMDevEnumImpl
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
static HRESULT load_driver_devices(EDataFlow flow)
Definition: devenum.c:491
static ULONG WINAPI PB_Release(IPropertyBag *iface)
Definition: devenum.c:1516
static MMDevEnumImpl * MMDevEnumerator
Definition: devenum.c:82
static DWORD MMDevice_count
Definition: devenum.c:85
BSTR bstrVal
Definition: compat.h:2048
#define E_POINTER
Definition: winerror.h:2365
static ULONG WINAPI MMDevice_AddRef(IMMDevice *iface)
Definition: devenum.c:564
static MMDevColImpl * impl_from_IMMDeviceCollection(IMMDeviceCollection *iface)
Definition: devenum.c:121
#define REG_DWORD
Definition: sdbapi.c:596
#define RRF_RT_REG_DWORD
Definition: driver.c:578
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:404
void user(int argc, const char *argv[])
Definition: cmds.c:1350
Definition: dsound.c:943
static const IMMEndpointVtbl MMEndpointVtbl
Definition: devenum.c:90
#define HeapFree(x, y, z)
Definition: compat.h:402
static MMDevPropStore * impl_from_IPropertyStore(IPropertyStore *iface)
Definition: devenum.c:111
static MMDevEnumImpl * impl_from_IMMDeviceEnumerator(IMMDeviceEnumerator *iface)
Definition: devenum.c:116
#define log(outFile, fmt,...)
Definition: util.h:15
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
static struct list g_notif_clients
Definition: devenum.c:1095
#define SUCCEEDED(hr)
Definition: intsafe.h:57
static HRESULT WINAPI MMDevCol_QueryInterface(IMMDeviceCollection *iface, REFIID riid, void **ppv)
Definition: devenum.c:790
static IMMDevice info_device
Definition: devenum.c:92
GUID devguid
Definition: mmdevapi.h:70
DWORD_PTR Spare[8/sizeof(DWORD_PTR)]
Definition: winbase.h:859
static ULONG WINAPI info_device_ps_AddRef(IPropertyStore *iface)
Definition: devenum.c:1554
Definition: path.c:42
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define RRF_RT_REG_BINARY
Definition: driver.c:577
#define REG_SZ
Definition: layer.c:22
GLuint const GLchar * name
Definition: glext.h:6031
static const WCHAR slashW[]
Definition: devenum.c:59