ReactOS  0.4.14-dev-41-g31d7680
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 "config.h"
20 
21 #include <stdarg.h>
22 
23 #define NONAMELESSUNION
24 #define COBJMACROS
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winnls.h"
28 #include "winreg.h"
29 #include "wine/debug.h"
30 #include "wine/list.h"
31 #include "wine/unicode.h"
32 
33 #include "initguid.h"
34 #include "ole2.h"
35 #include "mmdeviceapi.h"
36 #include "dshow.h"
37 #include "dsound.h"
38 #include "audioclient.h"
39 #include "endpointvolume.h"
40 #include "audiopolicy.h"
41 
42 #include "mmdevapi.h"
43 #include "devpkey.h"
44 
46 
47 static const WCHAR software_mmdevapi[] =
48  { 'S','o','f','t','w','a','r','e','\\',
49  'M','i','c','r','o','s','o','f','t','\\',
50  'W','i','n','d','o','w','s','\\',
51  'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
52  'M','M','D','e','v','i','c','e','s','\\',
53  'A','u','d','i','o',0};
54 static const WCHAR reg_render[] =
55  { 'R','e','n','d','e','r',0 };
56 static const WCHAR reg_capture[] =
57  { 'C','a','p','t','u','r','e',0 };
58 static const WCHAR reg_devicestate[] =
59  { 'D','e','v','i','c','e','S','t','a','t','e',0 };
60 static const WCHAR reg_properties[] =
61  { 'P','r','o','p','e','r','t','i','e','s',0 };
62 static const WCHAR slashW[] = {'\\',0};
63 static const WCHAR reg_out_nameW[] = {'D','e','f','a','u','l','t','O','u','t','p','u','t',0};
64 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};
65 static const WCHAR reg_in_nameW[] = {'D','e','f','a','u','l','t','I','n','p','u','t',0};
66 static const WCHAR reg_vin_nameW[] = {'D','e','f','a','u','l','t','V','o','i','c','e','I','n','p','u','t',0};
67 
70 
71 typedef struct MMDevPropStoreImpl
72 {
78 
79 typedef struct MMDevEnumImpl
80 {
84 
89 static const IMMDeviceEnumeratorVtbl MMDevEnumVtbl;
90 static const IMMDeviceCollectionVtbl MMDevColVtbl;
91 static const IMMDeviceVtbl MMDeviceVtbl;
92 static const IPropertyStoreVtbl MMDevPropVtbl;
93 static const IMMEndpointVtbl MMEndpointVtbl;
94 
96 
97 typedef struct MMDevColImpl
98 {
103 } MMDevColImpl;
104 
105 typedef struct IPropertyBagImpl {
109 
110 static const IPropertyBagVtbl PB_Vtbl;
111 
113 
115 {
116  return CONTAINING_RECORD(iface, MMDevPropStore, IPropertyStore_iface);
117 }
118 
120 {
121  return CONTAINING_RECORD(iface, MMDevEnumImpl, IMMDeviceEnumerator_iface);
122 }
123 
125 {
126  return CONTAINING_RECORD(iface, MMDevColImpl, IMMDeviceCollection_iface);
127 }
128 
130 {
131  return CONTAINING_RECORD(iface, IPropertyBagImpl, IPropertyBag_iface);
132 }
133 
134 static const WCHAR propkey_formatW[] = {
135  '{','%','0','8','X','-','%','0','4','X','-',
136  '%','0','4','X','-','%','0','2','X','%','0','2','X','-',
137  '%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X',
138  '%','0','2','X','%','0','2','X','}',',','%','d',0 };
139 
140 static HRESULT MMDevPropStore_OpenPropKey(const GUID *guid, DWORD flow, HKEY *propkey)
141 {
142  WCHAR buffer[39];
143  LONG ret;
144  HKEY key;
147  {
148  WARN("Opening key %s failed with %u\n", debugstr_w(buffer), ret);
149  return E_FAIL;
150  }
152  RegCloseKey(key);
153  if (ret != ERROR_SUCCESS)
154  {
155  WARN("Opening key %s failed with %u\n", debugstr_w(reg_properties), ret);
156  return E_FAIL;
157  }
158  return S_OK;
159 }
160 
161 static HRESULT MMDevice_GetPropValue(const GUID *devguid, DWORD flow, REFPROPERTYKEY key, PROPVARIANT *pv)
162 {
163  WCHAR buffer[80];
164  const GUID *id = &key->fmtid;
165  DWORD type, size;
166  HRESULT hr = S_OK;
167  HKEY regkey;
168  LONG ret;
169 
170  hr = MMDevPropStore_OpenPropKey(devguid, flow, &regkey);
171  if (FAILED(hr))
172  return hr;
173  wsprintfW( buffer, propkey_formatW, id->Data1, id->Data2, id->Data3,
174  id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3],
175  id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7], key->pid );
176  ret = RegGetValueW(regkey, NULL, buffer, RRF_RT_ANY, &type, NULL, &size);
177  if (ret != ERROR_SUCCESS)
178  {
179  WARN("Reading %s returned %d\n", debugstr_w(buffer), ret);
180  RegCloseKey(regkey);
181  PropVariantClear(pv);
182  return S_OK;
183  }
184 
185  switch (type)
186  {
187  case REG_SZ:
188  {
189  pv->vt = VT_LPWSTR;
190  pv->u.pwszVal = CoTaskMemAlloc(size);
191  if (!pv->u.pwszVal)
192  hr = E_OUTOFMEMORY;
193  else
194  RegGetValueW(regkey, NULL, buffer, RRF_RT_REG_SZ, NULL, (BYTE*)pv->u.pwszVal, &size);
195  break;
196  }
197  case REG_DWORD:
198  {
199  pv->vt = VT_UI4;
200  RegGetValueW(regkey, NULL, buffer, RRF_RT_REG_DWORD, NULL, (BYTE*)&pv->u.ulVal, &size);
201  break;
202  }
203  case REG_BINARY:
204  {
205  pv->vt = VT_BLOB;
206  pv->u.blob.cbSize = size;
207  pv->u.blob.pBlobData = CoTaskMemAlloc(size);
208  if (!pv->u.blob.pBlobData)
209  hr = E_OUTOFMEMORY;
210  else
211  RegGetValueW(regkey, NULL, buffer, RRF_RT_REG_BINARY, NULL, (BYTE*)pv->u.blob.pBlobData, &size);
212  break;
213  }
214  default:
215  ERR("Unknown/unhandled type: %u\n", type);
216  PropVariantClear(pv);
217  break;
218  }
219  RegCloseKey(regkey);
220  return hr;
221 }
222 
223 static HRESULT MMDevice_SetPropValue(const GUID *devguid, DWORD flow, REFPROPERTYKEY key, REFPROPVARIANT pv)
224 {
225  WCHAR buffer[80];
226  const GUID *id = &key->fmtid;
227  HRESULT hr;
228  HKEY regkey;
229  LONG ret;
230 
231  hr = MMDevPropStore_OpenPropKey(devguid, flow, &regkey);
232  if (FAILED(hr))
233  return hr;
234  wsprintfW( buffer, propkey_formatW, id->Data1, id->Data2, id->Data3,
235  id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3],
236  id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7], key->pid );
237  switch (pv->vt)
238  {
239  case VT_UI4:
240  {
241  ret = RegSetValueExW(regkey, buffer, 0, REG_DWORD, (const BYTE*)&pv->u.ulVal, sizeof(DWORD));
242  break;
243  }
244  case VT_BLOB:
245  {
246  ret = RegSetValueExW(regkey, buffer, 0, REG_BINARY, pv->u.blob.pBlobData, pv->u.blob.cbSize);
247  TRACE("Blob %p %u\n", pv->u.blob.pBlobData, pv->u.blob.cbSize);
248 
249  break;
250  }
251  case VT_LPWSTR:
252  {
253  ret = RegSetValueExW(regkey, buffer, 0, REG_SZ, (const BYTE*)pv->u.pwszVal, sizeof(WCHAR)*(1+lstrlenW(pv->u.pwszVal)));
254  break;
255  }
256  default:
257  ret = 0;
258  FIXME("Unhandled type %u\n", pv->vt);
259  hr = E_INVALIDARG;
260  break;
261  }
262  RegCloseKey(regkey);
263  TRACE("Writing %s returned %u\n", debugstr_w(buffer), ret);
264  return hr;
265 }
266 
267 static HRESULT set_driver_prop_value(GUID *id, const EDataFlow flow, const PROPERTYKEY *prop)
268 {
269  HRESULT hr;
270  PROPVARIANT pv;
271 
272  if (!drvs.pGetPropValue)
273  return E_NOTIMPL;
274 
275  hr = drvs.pGetPropValue(id, prop, &pv);
276 
277  if (SUCCEEDED(hr))
278  {
279  MMDevice_SetPropValue(id, flow, prop, &pv);
280  PropVariantClear(&pv);
281  }
282 
283  return hr;
284 }
285 
286 /* Creates or updates the state of a device
287  * If GUID is null, a random guid will be assigned
288  * and the device will be created
289  */
290 static MMDevice *MMDevice_Create(WCHAR *name, GUID *id, EDataFlow flow, DWORD state, BOOL setdefault)
291 {
292  HKEY key, root;
293  MMDevice *cur = NULL;
294  WCHAR guidstr[39];
295  DWORD i;
296 
297  static const PROPERTYKEY deviceinterface_key = {
298  {0x233164c8, 0x1b2c, 0x4c7d, {0xbc, 0x68, 0xb6, 0x71, 0x68, 0x7a, 0x25, 0x67}}, 1
299  };
300 
301  static const PROPERTYKEY devicepath_key = {
302  {0xb3f8fa53, 0x0004, 0x438e, {0x90, 0x03, 0x51, 0xa4, 0x6e, 0x13, 0x9b, 0xfc}}, 2
303  };
304 
305  for (i = 0; i < MMDevice_count; ++i)
306  {
308  if (device->flow == flow && IsEqualGUID(&device->devguid, id)){
309  cur = device;
310  break;
311  }
312  }
313 
314  if(!cur){
315  /* No device found, allocate new one */
316  cur = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*cur));
317  if (!cur)
318  return NULL;
319 
320  cur->IMMDevice_iface.lpVtbl = &MMDeviceVtbl;
321  cur->IMMEndpoint_iface.lpVtbl = &MMEndpointVtbl;
322 
324  cur->crst.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": MMDevice.crst");
325 
326  if (!MMDevice_head)
328  else
330  MMDevice_head[MMDevice_count++] = cur;
331  }else if(cur->ref > 0)
332  WARN("Modifying an MMDevice with postitive reference count!\n");
333 
334  HeapFree(GetProcessHeap(), 0, cur->drv_id);
335  cur->drv_id = name;
336 
337  cur->flow = flow;
338  cur->state = state;
339  cur->devguid = *id;
340 
341  StringFromGUID2(&cur->devguid, guidstr, ARRAY_SIZE(guidstr));
342 
343  if (flow == eRender)
344  root = key_render;
345  else
346  root = key_capture;
347 
349  {
350  HKEY keyprop;
351  RegSetValueExW(key, reg_devicestate, 0, REG_DWORD, (const BYTE*)&state, sizeof(DWORD));
353  {
354  PROPVARIANT pv;
355 
356  pv.vt = VT_LPWSTR;
357  pv.u.pwszVal = name;
358  MMDevice_SetPropValue(id, flow, (const PROPERTYKEY*)&DEVPKEY_Device_FriendlyName, &pv);
359  MMDevice_SetPropValue(id, flow, (const PROPERTYKEY*)&DEVPKEY_DeviceInterface_FriendlyName, &pv);
360  MMDevice_SetPropValue(id, flow, (const PROPERTYKEY*)&DEVPKEY_Device_DeviceDesc, &pv);
361 
362  pv.u.pwszVal = guidstr;
363  MMDevice_SetPropValue(id, flow, &deviceinterface_key, &pv);
364 
365  set_driver_prop_value(id, flow, &devicepath_key);
366 
367  if (FAILED(set_driver_prop_value(id, flow, &PKEY_AudioEndpoint_FormFactor)))
368  {
369  pv.vt = VT_UI4;
370  pv.u.ulVal = (flow == eCapture) ? Microphone : Speakers;
371 
372  MMDevice_SetPropValue(id, flow, &PKEY_AudioEndpoint_FormFactor, &pv);
373  }
374 
375  if (flow != eCapture)
376  {
377  PROPVARIANT pv2;
378 
379  PropVariantInit(&pv2);
380 
381  /* make read-write by not overwriting if already set */
382  if (FAILED(MMDevice_GetPropValue(id, flow, &PKEY_AudioEndpoint_PhysicalSpeakers, &pv2)) || pv2.vt != VT_UI4)
383  set_driver_prop_value(id, flow, &PKEY_AudioEndpoint_PhysicalSpeakers);
384 
386  }
387 
388  RegCloseKey(keyprop);
389  }
390  RegCloseKey(key);
391  }
392 
393  if (setdefault)
394  {
395  if (flow == eRender)
396  MMDevice_def_play = cur;
397  else
398  MMDevice_def_rec = cur;
399  }
400  return cur;
401 }
402 
404 {
405  DWORD i = 0;
406  HKEY root, cur;
407  LONG ret;
408  DWORD curflow;
409 
411  if (ret == ERROR_SUCCESS)
413  if (ret == ERROR_SUCCESS)
415  RegCloseKey(root);
416  cur = key_capture;
417  curflow = eCapture;
418  if (ret != ERROR_SUCCESS)
419  {
422  WARN("Couldn't create key: %u\n", ret);
423  return E_FAIL;
424  }
425 
426  do {
427  WCHAR guidvalue[39];
428  GUID guid;
429  DWORD len;
430  PROPVARIANT pv = { VT_EMPTY };
431 
432  len = ARRAY_SIZE(guidvalue);
433  ret = RegEnumKeyExW(cur, i++, guidvalue, &len, NULL, NULL, NULL, NULL);
434  if (ret == ERROR_NO_MORE_ITEMS)
435  {
436  if (cur == key_capture)
437  {
438  cur = key_render;
439  curflow = eRender;
440  i = 0;
441  continue;
442  }
443  break;
444  }
445  if (ret != ERROR_SUCCESS)
446  continue;
447  if (SUCCEEDED(CLSIDFromString(guidvalue, &guid))
448  && SUCCEEDED(MMDevice_GetPropValue(&guid, curflow, (const PROPERTYKEY*)&DEVPKEY_Device_FriendlyName, &pv))
449  && pv.vt == VT_LPWSTR)
450  {
451  DWORD size_bytes = (strlenW(pv.u.pwszVal) + 1) * sizeof(WCHAR);
452  WCHAR *name = HeapAlloc(GetProcessHeap(), 0, size_bytes);
453  memcpy(name, pv.u.pwszVal, size_bytes);
454  MMDevice_Create(name, &guid, curflow,
455  DEVICE_STATE_NOTPRESENT, FALSE);
456  CoTaskMemFree(pv.u.pwszVal);
457  }
458  } while (1);
459 
460  return S_OK;
461 }
462 
464 {
465  HRESULT hr;
467  WAVEFORMATEX *fmt;
468  PROPVARIANT pv = { VT_EMPTY };
469 
470  hr = drvs.pGetAudioEndpoint(&dev->devguid, &dev->IMMDevice_iface, &client);
471  if(FAILED(hr))
472  return hr;
473 
474  hr = IAudioClient_GetMixFormat(client, &fmt);
475  if(FAILED(hr)){
476  IAudioClient_Release(client);
477  return hr;
478  }
479 
480  IAudioClient_Release(client);
481 
482  pv.vt = VT_BLOB;
483  pv.u.blob.cbSize = sizeof(WAVEFORMATEX) + fmt->cbSize;
484  pv.u.blob.pBlobData = (BYTE*)fmt;
485  MMDevice_SetPropValue(&dev->devguid, dev->flow,
486  &PKEY_AudioEngine_DeviceFormat, &pv);
487  MMDevice_SetPropValue(&dev->devguid, dev->flow,
488  &PKEY_AudioEngine_OEMFormat, &pv);
490 
491  return S_OK;
492 }
493 
495 {
496  WCHAR **ids;
497  GUID *guids;
498  UINT num, def, i;
499  HRESULT hr;
500 
501  if(!drvs.pGetEndpointIDs)
502  return S_OK;
503 
504  hr = drvs.pGetEndpointIDs(flow, &ids, &guids, &num, &def);
505  if(FAILED(hr))
506  return hr;
507 
508  for(i = 0; i < num; ++i){
509  MMDevice *dev;
510  dev = MMDevice_Create(ids[i], &guids[i], flow, DEVICE_STATE_ACTIVE,
511  def == i);
512  set_format(dev);
513  }
514 
515  HeapFree(GetProcessHeap(), 0, guids);
516  HeapFree(GetProcessHeap(), 0, ids);
517 
518  return S_OK;
519 }
520 
522 {
523  DWORD i;
524  TRACE("Freeing %s\n", debugstr_w(This->drv_id));
525  /* Since this function is called at destruction time, reordering of the list is unimportant */
526  for (i = 0; i < MMDevice_count; ++i)
527  {
528  if (MMDevice_head[i] == This)
529  {
531  break;
532  }
533  }
534  This->crst.DebugInfo->Spare[0] = 0;
535  DeleteCriticalSection(&This->crst);
536  HeapFree(GetProcessHeap(), 0, This->drv_id);
538 }
539 
540 static inline MMDevice *impl_from_IMMDevice(IMMDevice *iface)
541 {
542  return CONTAINING_RECORD(iface, MMDevice, IMMDevice_iface);
543 }
544 
546 {
548  TRACE("(%p)->(%s,%p)\n", iface, debugstr_guid(riid), ppv);
549 
550  if (!ppv)
551  return E_POINTER;
552  *ppv = NULL;
554  || IsEqualIID(riid, &IID_IMMDevice))
555  *ppv = &This->IMMDevice_iface;
556  else if (IsEqualIID(riid, &IID_IMMEndpoint))
557  *ppv = &This->IMMEndpoint_iface;
558  if (*ppv)
559  {
560  IUnknown_AddRef((IUnknown*)*ppv);
561  return S_OK;
562  }
563  WARN("Unknown interface %s\n", debugstr_guid(riid));
564  return E_NOINTERFACE;
565 }
566 
568 {
570  LONG ref;
571 
572  ref = InterlockedIncrement(&This->ref);
573  TRACE("Refcount now %i\n", ref);
574  return ref;
575 }
576 
578 {
580  LONG ref;
581 
582  ref = InterlockedDecrement(&This->ref);
583  TRACE("Refcount now %i\n", ref);
584  return ref;
585 }
586 
587 static HRESULT WINAPI MMDevice_Activate(IMMDevice *iface, REFIID riid, DWORD clsctx, PROPVARIANT *params, void **ppv)
588 {
591 
592  TRACE("(%p)->(%s, %x, %p, %p)\n", iface, debugstr_guid(riid), clsctx, params, ppv);
593 
594  if (!ppv)
595  return E_POINTER;
596 
597  if (IsEqualIID(riid, &IID_IAudioClient)){
598  hr = drvs.pGetAudioEndpoint(&This->devguid, iface, (IAudioClient**)ppv);
599  }else if (IsEqualIID(riid, &IID_IAudioEndpointVolume) ||
600  IsEqualIID(riid, &IID_IAudioEndpointVolumeEx))
602  else if (IsEqualIID(riid, &IID_IAudioSessionManager)
603  || IsEqualIID(riid, &IID_IAudioSessionManager2))
604  {
605  hr = drvs.pGetAudioSessionManager(iface, (IAudioSessionManager2**)ppv);
606  }
607  else if (IsEqualIID(riid, &IID_IBaseFilter))
608  {
609  if (This->flow == eRender)
610  hr = CoCreateInstance(&CLSID_DSoundRender, NULL, clsctx, riid, ppv);
611  else
612  ERR("Not supported for recording?\n");
613  if (SUCCEEDED(hr))
614  {
615  IPersistPropertyBag *ppb;
616  hr = IUnknown_QueryInterface((IUnknown*)*ppv, &IID_IPersistPropertyBag, (void **)&ppb);
617  if (SUCCEEDED(hr))
618  {
619  /* ::Load cannot assume the interface stays alive after the function returns,
620  * so just create the interface on the stack, saves a lot of complicated code */
621  IPropertyBagImpl bag = { { &PB_Vtbl } };
622  bag.devguid = This->devguid;
623  hr = IPersistPropertyBag_Load(ppb, &bag.IPropertyBag_iface, NULL);
624  IPersistPropertyBag_Release(ppb);
625  if (FAILED(hr))
626  IBaseFilter_Release((IBaseFilter*)*ppv);
627  }
628  else
629  {
630  FIXME("Wine doesn't support IPersistPropertyBag on DSoundRender yet, ignoring..\n");
631  hr = S_OK;
632  }
633  }
634  }
635  else if (IsEqualIID(riid, &IID_IDeviceTopology))
636  {
637  FIXME("IID_IDeviceTopology unsupported\n");
638  }
639  else if (IsEqualIID(riid, &IID_IDirectSound)
640  || IsEqualIID(riid, &IID_IDirectSound8))
641  {
642  if (This->flow == eRender)
643  hr = CoCreateInstance(&CLSID_DirectSound8, NULL, clsctx, riid, ppv);
644  if (SUCCEEDED(hr))
645  {
646  hr = IDirectSound_Initialize((IDirectSound*)*ppv, &This->devguid);
647  if (FAILED(hr))
648  IDirectSound_Release((IDirectSound*)*ppv);
649  }
650  }
651  else if (IsEqualIID(riid, &IID_IDirectSoundCapture))
652  {
653  if (This->flow == eCapture)
654  hr = CoCreateInstance(&CLSID_DirectSoundCapture8, NULL, clsctx, riid, ppv);
655  if (SUCCEEDED(hr))
656  {
657  hr = IDirectSoundCapture_Initialize((IDirectSoundCapture*)*ppv, &This->devguid);
658  if (FAILED(hr))
659  IDirectSoundCapture_Release((IDirectSoundCapture*)*ppv);
660  }
661  }
662  else
663  ERR("Invalid/unknown iid %s\n", debugstr_guid(riid));
664 
665  if (FAILED(hr))
666  *ppv = NULL;
667 
668  TRACE("Returning %08x\n", hr);
669  return hr;
670 }
671 
673 {
675  TRACE("(%p)->(%x,%p)\n", This, access, ppv);
676 
677  if (!ppv)
678  return E_POINTER;
680 }
681 
682 static HRESULT WINAPI MMDevice_GetId(IMMDevice *iface, WCHAR **itemid)
683 {
685  WCHAR *str;
686  GUID *id = &This->devguid;
687  static const WCHAR formatW[] = { '{','0','.','0','.','%','u','.','0','0','0','0','0','0','0','0','}','.',
688  '{','%','0','8','X','-','%','0','4','X','-',
689  '%','0','4','X','-','%','0','2','X','%','0','2','X','-',
690  '%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X',
691  '%','0','2','X','%','0','2','X','}',0 };
692 
693  TRACE("(%p)->(%p)\n", This, itemid);
694  if (!itemid)
695  return E_POINTER;
696  *itemid = str = CoTaskMemAlloc(56 * sizeof(WCHAR));
697  if (!str)
698  return E_OUTOFMEMORY;
699  wsprintfW( str, formatW, This->flow, id->Data1, id->Data2, id->Data3,
700  id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3],
701  id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7] );
702  TRACE("returning %s\n", wine_dbgstr_w(str));
703  return S_OK;
704 }
705 
707 {
709  TRACE("(%p)->(%p)\n", iface, state);
710 
711  if (!state)
712  return E_POINTER;
713  *state = This->state;
714  return S_OK;
715 }
716 
717 static const IMMDeviceVtbl MMDeviceVtbl =
718 {
726 };
727 
729 {
730  return CONTAINING_RECORD(iface, MMDevice, IMMEndpoint_iface);
731 }
732 
734 {
736  TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
737  return IMMDevice_QueryInterface(&This->IMMDevice_iface, riid, ppv);
738 }
739 
741 {
743  TRACE("(%p)\n", This);
744  return IMMDevice_AddRef(&This->IMMDevice_iface);
745 }
746 
748 {
750  TRACE("(%p)\n", This);
751  return IMMDevice_Release(&This->IMMDevice_iface);
752 }
753 
755 {
757  TRACE("(%p)->(%p)\n", This, flow);
758  if (!flow)
759  return E_POINTER;
760  *flow = This->flow;
761  return S_OK;
762 }
763 
764 static const IMMEndpointVtbl MMEndpointVtbl =
765 {
770 };
771 
773 {
775 
776  This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
777  *ppv = NULL;
778  if (!This)
779  return E_OUTOFMEMORY;
780  This->IMMDeviceCollection_iface.lpVtbl = &MMDevColVtbl;
781  This->ref = 1;
782  This->flow = flow;
783  This->state = state;
784  *ppv = &This->IMMDeviceCollection_iface;
785  return S_OK;
786 }
787 
789 {
791 }
792 
794 {
796  TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
797 
798  if (!ppv)
799  return E_POINTER;
801  || IsEqualIID(riid, &IID_IMMDeviceCollection))
802  *ppv = &This->IMMDeviceCollection_iface;
803  else
804  *ppv = NULL;
805  if (!*ppv)
806  return E_NOINTERFACE;
807  IUnknown_AddRef((IUnknown*)*ppv);
808  return S_OK;
809 }
810 
812 {
815  TRACE("Refcount now %i\n", ref);
816  return ref;
817 }
818 
820 {
823  TRACE("Refcount now %i\n", ref);
824  if (!ref)
826  return ref;
827 }
828 
830 {
832  DWORD i;
833 
834  TRACE("(%p)->(%p)\n", This, numdevs);
835  if (!numdevs)
836  return E_POINTER;
837 
838  *numdevs = 0;
839  for (i = 0; i < MMDevice_count; ++i)
840  {
841  MMDevice *cur = MMDevice_head[i];
842  if ((cur->flow == This->flow || This->flow == eAll)
843  && (cur->state & This->state))
844  ++(*numdevs);
845  }
846  return S_OK;
847 }
848 
850 {
852  DWORD i = 0, j = 0;
853 
854  TRACE("(%p)->(%u, %p)\n", This, n, dev);
855  if (!dev)
856  return E_POINTER;
857 
858  for (j = 0; j < MMDevice_count; ++j)
859  {
860  MMDevice *cur = MMDevice_head[j];
861  if ((cur->flow == This->flow || This->flow == eAll)
862  && (cur->state & This->state)
863  && i++ == n)
864  {
865  *dev = &cur->IMMDevice_iface;
866  IMMDevice_AddRef(*dev);
867  return S_OK;
868  }
869  }
870  WARN("Could not obtain item %u\n", n);
871  *dev = NULL;
872  return E_INVALIDARG;
873 }
874 
875 static const IMMDeviceCollectionVtbl MMDevColVtbl =
876 {
882 };
883 
885 {
887 
888  if (!This)
889  {
890  This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
891  *ppv = NULL;
892  if (!This)
893  return E_OUTOFMEMORY;
894  This->ref = 1;
895  This->IMMDeviceEnumerator_iface.lpVtbl = &MMDevEnumVtbl;
897 
901  }
902  return IMMDeviceEnumerator_QueryInterface(&This->IMMDeviceEnumerator_iface, riid, ppv);
903 }
904 
905 void MMDevEnum_Free(void)
906 {
907  while (MMDevice_count)
914 }
915 
917 {
919  TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
920 
921  if (!ppv)
922  return E_POINTER;
924  || IsEqualIID(riid, &IID_IMMDeviceEnumerator))
925  *ppv = &This->IMMDeviceEnumerator_iface;
926  else
927  *ppv = NULL;
928  if (!*ppv)
929  return E_NOINTERFACE;
930  IUnknown_AddRef((IUnknown*)*ppv);
931  return S_OK;
932 }
933 
935 {
938  TRACE("Refcount now %i\n", ref);
939  return ref;
940 }
941 
943 {
946  if (!ref)
947  MMDevEnum_Free();
948  TRACE("Refcount now %i\n", ref);
949  return ref;
950 }
951 
953 {
955  TRACE("(%p)->(%u,%u,%p)\n", This, flow, mask, devices);
956  if (!devices)
957  return E_POINTER;
958  *devices = NULL;
959  if (flow >= EDataFlow_enum_count)
960  return E_INVALIDARG;
961  if (mask & ~DEVICE_STATEMASK_ALL)
962  return E_INVALIDARG;
963  return MMDevCol_Create(devices, flow, mask);
964 }
965 
967 {
969  WCHAR reg_key[256];
970  HKEY key;
971  HRESULT hr;
972 
973  TRACE("(%p)->(%u,%u,%p)\n", This, flow, role, device);
974 
975  if (!device)
976  return E_POINTER;
977 
978  if((flow != eRender && flow != eCapture) ||
979  (role != eConsole && role != eMultimedia && role != eCommunications)){
980  WARN("Unknown flow (%u) or role (%u)\n", flow, role);
981  return E_INVALIDARG;
982  }
983 
984  *device = NULL;
985 
986  if(!drvs.module_name[0])
987  return E_NOTFOUND;
988 
989  lstrcpyW(reg_key, drv_keyW);
990  lstrcatW(reg_key, slashW);
991  lstrcatW(reg_key, drvs.module_name);
992 
993  if(RegOpenKeyW(HKEY_CURRENT_USER, reg_key, &key) == ERROR_SUCCESS){
994  const WCHAR *reg_x_name, *reg_vx_name;
995  WCHAR def_id[256];
996  DWORD size = sizeof(def_id), state;
997 
998  if(flow == eRender){
999  reg_x_name = reg_out_nameW;
1000  reg_vx_name = reg_vout_nameW;
1001  }else{
1002  reg_x_name = reg_in_nameW;
1003  reg_vx_name = reg_vin_nameW;
1004  }
1005 
1006  if(role == eCommunications &&
1007  RegQueryValueExW(key, reg_vx_name, 0, NULL,
1008  (BYTE*)def_id, &size) == ERROR_SUCCESS){
1009  hr = IMMDeviceEnumerator_GetDevice(iface, def_id, device);
1010  if(SUCCEEDED(hr)){
1011  if(SUCCEEDED(IMMDevice_GetState(*device, &state)) &&
1012  state == DEVICE_STATE_ACTIVE){
1013  RegCloseKey(key);
1014  return S_OK;
1015  }
1016  }
1017 
1018  TRACE("Unable to find voice device %s\n", wine_dbgstr_w(def_id));
1019  }
1020 
1021  if(RegQueryValueExW(key, reg_x_name, 0, NULL,
1022  (BYTE*)def_id, &size) == ERROR_SUCCESS){
1023  hr = IMMDeviceEnumerator_GetDevice(iface, def_id, device);
1024  if(SUCCEEDED(hr)){
1025  if(SUCCEEDED(IMMDevice_GetState(*device, &state)) &&
1026  state == DEVICE_STATE_ACTIVE){
1027  RegCloseKey(key);
1028  return S_OK;
1029  }
1030  }
1031 
1032  TRACE("Unable to find device %s\n", wine_dbgstr_w(def_id));
1033  }
1034 
1035  RegCloseKey(key);
1036  }
1037 
1038  if (flow == eRender)
1040  else
1042 
1043  if (!*device)
1044  return E_NOTFOUND;
1045  IMMDevice_AddRef(*device);
1046  return S_OK;
1047 }
1048 
1050 {
1052  DWORD i=0;
1053  IMMDevice *dev = NULL;
1054 
1055  static const WCHAR wine_info_deviceW[] = {'W','i','n','e',' ',
1056  'i','n','f','o',' ','d','e','v','i','c','e',0};
1057 
1058  TRACE("(%p)->(%s,%p)\n", This, debugstr_w(name), device);
1059 
1060  if(!name || !device)
1061  return E_POINTER;
1062 
1063  if(!lstrcmpW(name, wine_info_deviceW)){
1064  *device = &info_device;
1065  return S_OK;
1066  }
1067 
1068  for (i = 0; i < MMDevice_count; ++i)
1069  {
1070  HRESULT hr;
1071  WCHAR *str;
1073  hr = IMMDevice_GetId(dev, &str);
1074  if (FAILED(hr))
1075  {
1076  WARN("GetId failed: %08x\n", hr);
1077  continue;
1078  }
1079 
1080  if (str && !lstrcmpW(str, name))
1081  {
1082  CoTaskMemFree(str);
1083  IMMDevice_AddRef(dev);
1084  *device = dev;
1085  return S_OK;
1086  }
1087  CoTaskMemFree(str);
1088  }
1089  TRACE("Could not find device %s\n", debugstr_w(name));
1090  return E_INVALIDARG;
1091 }
1092 
1095  struct list entry;
1096 };
1097 
1100 
1103 {
1104  0, 0, &g_notif_lock,
1106  0, 0, { (DWORD_PTR)(__FILE__ ": g_notif_lock") }
1107 };
1108 static CRITICAL_SECTION g_notif_lock = { &g_notif_lock_debug, -1, 0, 0, 0, 0 };
1109 
1110 static void notify_clients(EDataFlow flow, ERole role, const WCHAR *id)
1111 {
1112  struct NotificationClientWrapper *wrapper;
1115  IMMNotificationClient_OnDefaultDeviceChanged(wrapper->client, flow,
1116  role, id);
1117 
1118  /* Windows 7 treats changes to eConsole as changes to eMultimedia */
1119  if(role == eConsole)
1120  notify_clients(flow, eMultimedia, id);
1121 }
1122 
1124  const WCHAR *val_name, WCHAR *old_val, IMMDevice *def_dev)
1125 {
1126  WCHAR new_val[64], *id;
1127  DWORD size;
1128  HRESULT hr;
1129 
1130  size = sizeof(new_val);
1131  if(RegQueryValueExW(key, val_name, 0, NULL,
1132  (BYTE*)new_val, &size) != ERROR_SUCCESS){
1133  if(old_val[0] != 0){
1134  /* set by user -> system default */
1135  if(def_dev){
1136  hr = IMMDevice_GetId(def_dev, &id);
1137  if(FAILED(hr)){
1138  ERR("GetId failed: %08x\n", hr);
1139  return FALSE;
1140  }
1141  }else
1142  id = NULL;
1143 
1144  notify_clients(flow, role, id);
1145  old_val[0] = 0;
1146  CoTaskMemFree(id);
1147 
1148  return TRUE;
1149  }
1150 
1151  /* system default -> system default, noop */
1152  return FALSE;
1153  }
1154 
1155  if(!lstrcmpW(old_val, new_val)){
1156  /* set by user -> same value */
1157  return FALSE;
1158  }
1159 
1160  if(new_val[0] != 0){
1161  /* set by user -> different value */
1162  notify_clients(flow, role, new_val);
1163  memcpy(old_val, new_val, sizeof(new_val));
1164  return TRUE;
1165  }
1166 
1167  /* set by user -> system default */
1168  if(def_dev){
1169  hr = IMMDevice_GetId(def_dev, &id);
1170  if(FAILED(hr)){
1171  ERR("GetId failed: %08x\n", hr);
1172  return FALSE;
1173  }
1174  }else
1175  id = NULL;
1176 
1177  notify_clients(flow, role, id);
1178  old_val[0] = 0;
1179  CoTaskMemFree(id);
1180 
1181  return TRUE;
1182 }
1183 
1185 {
1186  HKEY key;
1187  WCHAR reg_key[256];
1188  WCHAR out_name[64], vout_name[64], in_name[64], vin_name[64];
1189  DWORD size;
1190 
1191  lstrcpyW(reg_key, drv_keyW);
1192  lstrcatW(reg_key, slashW);
1193  lstrcatW(reg_key, drvs.module_name);
1194 
1195  if(RegCreateKeyExW(HKEY_CURRENT_USER, reg_key, 0, NULL, 0,
1197  ERR("RegCreateKeyEx failed: %u\n", GetLastError());
1198  return 1;
1199  }
1200 
1201  size = sizeof(out_name);
1203  (BYTE*)out_name, &size) != ERROR_SUCCESS)
1204  out_name[0] = 0;
1205 
1206  size = sizeof(vout_name);
1208  (BYTE*)vout_name, &size) != ERROR_SUCCESS)
1209  vout_name[0] = 0;
1210 
1211  size = sizeof(in_name);
1213  (BYTE*)in_name, &size) != ERROR_SUCCESS)
1214  in_name[0] = 0;
1215 
1216  size = sizeof(vin_name);
1218  (BYTE*)vin_name, &size) != ERROR_SUCCESS)
1219  vin_name[0] = 0;
1220 
1221  while(1){
1223  NULL, FALSE) != ERROR_SUCCESS){
1224  ERR("RegNotifyChangeKeyValue failed: %u\n", GetLastError());
1225  RegCloseKey(key);
1226  g_notif_thread = NULL;
1227  return 1;
1228  }
1229 
1231 
1233  out_name, &MMDevice_def_play->IMMDevice_iface);
1235  vout_name, &MMDevice_def_play->IMMDevice_iface);
1237  in_name, &MMDevice_def_rec->IMMDevice_iface);
1239  vin_name, &MMDevice_def_rec->IMMDevice_iface);
1240 
1242  }
1243 
1244  RegCloseKey(key);
1245 
1246  g_notif_thread = NULL;
1247 
1248  return 0;
1249 }
1250 
1252 {
1254  struct NotificationClientWrapper *wrapper;
1255 
1256  TRACE("(%p)->(%p)\n", This, client);
1257 
1258  if(!client)
1259  return E_POINTER;
1260 
1261  wrapper = HeapAlloc(GetProcessHeap(), 0, sizeof(*wrapper));
1262  if(!wrapper)
1263  return E_OUTOFMEMORY;
1264 
1265  wrapper->client = client;
1266 
1268 
1269  list_add_tail(&g_notif_clients, &wrapper->entry);
1270 
1271  if(!g_notif_thread){
1273  if(!g_notif_thread)
1274  ERR("CreateThread failed: %u\n", GetLastError());
1275  }
1276 
1278 
1279  return S_OK;
1280 }
1281 
1283 {
1285  struct NotificationClientWrapper *wrapper;
1286 
1287  TRACE("(%p)->(%p)\n", This, client);
1288 
1289  if(!client)
1290  return E_POINTER;
1291 
1293 
1295  if(wrapper->client == client){
1296  list_remove(&wrapper->entry);
1297  HeapFree(GetProcessHeap(), 0, wrapper);
1299  return S_OK;
1300  }
1301  }
1302 
1304 
1305  return E_NOTFOUND;
1306 }
1307 
1308 static const IMMDeviceEnumeratorVtbl MMDevEnumVtbl =
1309 {
1318 };
1319 
1321 {
1323  if (access != STGM_READ
1324  && access != STGM_WRITE
1325  && access != STGM_READWRITE)
1326  {
1327  WARN("Invalid access %08x\n", access);
1328  return E_INVALIDARG;
1329  }
1330  This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1331  *ppv = &This->IPropertyStore_iface;
1332  if (!This)
1333  return E_OUTOFMEMORY;
1334  This->IPropertyStore_iface.lpVtbl = &MMDevPropVtbl;
1335  This->ref = 1;
1336  This->parent = parent;
1337  This->access = access;
1338  return S_OK;
1339 }
1340 
1342 {
1343  HeapFree(GetProcessHeap(), 0, This);
1344 }
1345 
1347 {
1349  TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
1350 
1351  if (!ppv)
1352  return E_POINTER;
1354  || IsEqualIID(riid, &IID_IPropertyStore))
1355  *ppv = &This->IPropertyStore_iface;
1356  else
1357  *ppv = NULL;
1358  if (!*ppv)
1359  return E_NOINTERFACE;
1360  IUnknown_AddRef((IUnknown*)*ppv);
1361  return S_OK;
1362 }
1363 
1365 {
1367  LONG ref = InterlockedIncrement(&This->ref);
1368  TRACE("Refcount now %i\n", ref);
1369  return ref;
1370 }
1371 
1373 {
1375  LONG ref = InterlockedDecrement(&This->ref);
1376  TRACE("Refcount now %i\n", ref);
1377  if (!ref)
1379  return ref;
1380 }
1381 
1383 {
1385  WCHAR buffer[50];
1386  DWORD i = 0;
1387  HKEY propkey;
1388  HRESULT hr;
1389 
1390  TRACE("(%p)->(%p)\n", iface, nprops);
1391  if (!nprops)
1392  return E_POINTER;
1393  hr = MMDevPropStore_OpenPropKey(&This->parent->devguid, This->parent->flow, &propkey);
1394  if (FAILED(hr))
1395  return hr;
1396  *nprops = 0;
1397  do {
1399  if (RegEnumValueW(propkey, i, buffer, &len, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
1400  break;
1401  i++;
1402  } while (1);
1403  RegCloseKey(propkey);
1404  TRACE("Returning %i\n", i);
1405  *nprops = i;
1406  return S_OK;
1407 }
1408 
1409 static HRESULT WINAPI MMDevPropStore_GetAt(IPropertyStore *iface, DWORD prop, PROPERTYKEY *key)
1410 {
1412  WCHAR buffer[50];
1414  HRESULT hr;
1415  HKEY propkey;
1416 
1417  TRACE("(%p)->(%u,%p)\n", iface, prop, key);
1418  if (!key)
1419  return E_POINTER;
1420 
1421  hr = MMDevPropStore_OpenPropKey(&This->parent->devguid, This->parent->flow, &propkey);
1422  if (FAILED(hr))
1423  return hr;
1424 
1425  if (RegEnumValueW(propkey, prop, buffer, &len, NULL, NULL, NULL, NULL) != ERROR_SUCCESS
1426  || len <= 39)
1427  {
1428  WARN("GetAt %u failed\n", prop);
1429  return E_INVALIDARG;
1430  }
1431  RegCloseKey(propkey);
1432  buffer[38] = 0;
1433  CLSIDFromString(buffer, &key->fmtid);
1434  key->pid = atoiW(&buffer[39]);
1435  return S_OK;
1436 }
1437 
1439 {
1441  TRACE("(%p)->(\"%s,%u\", %p)\n", This, key ? debugstr_guid(&key->fmtid) : NULL, key ? key->pid : 0, pv);
1442 
1443  if (!key || !pv)
1444  return E_POINTER;
1445  if (This->access != STGM_READ
1446  && This->access != STGM_READWRITE)
1447  return STG_E_ACCESSDENIED;
1448 
1449  /* Special case */
1450  if (IsEqualPropertyKey(*key, PKEY_AudioEndpoint_GUID))
1451  {
1452  pv->vt = VT_LPWSTR;
1453  pv->u.pwszVal = CoTaskMemAlloc(39 * sizeof(WCHAR));
1454  if (!pv->u.pwszVal)
1455  return E_OUTOFMEMORY;
1456  StringFromGUID2(&This->parent->devguid, pv->u.pwszVal, 39);
1457  return S_OK;
1458  }
1459 
1460  return MMDevice_GetPropValue(&This->parent->devguid, This->parent->flow, key, pv);
1461 }
1462 
1464 {
1466  TRACE("(%p)->(\"%s,%u\", %p)\n", This, key ? debugstr_guid(&key->fmtid) : NULL, key ? key->pid : 0, pv);
1467 
1468  if (!key || !pv)
1469  return E_POINTER;
1470 
1471  if (This->access != STGM_WRITE
1472  && This->access != STGM_READWRITE)
1473  return STG_E_ACCESSDENIED;
1474  return MMDevice_SetPropValue(&This->parent->devguid, This->parent->flow, key, pv);
1475 }
1476 
1478 {
1480  TRACE("(%p)\n", iface);
1481 
1482  if (This->access != STGM_WRITE
1483  && This->access != STGM_READWRITE)
1484  return STG_E_ACCESSDENIED;
1485 
1486  /* Does nothing - for mmdevapi, the propstore values are written on SetValue,
1487  * not on Commit. */
1488 
1489  return S_OK;
1490 }
1491 
1492 static const IPropertyStoreVtbl MMDevPropVtbl =
1493 {
1502 };
1503 
1504 
1505 /* Property bag for IBaseFilter activation */
1507 {
1508  ERR("Should not be called\n");
1509  *ppv = NULL;
1510  return E_NOINTERFACE;
1511 }
1512 
1514 {
1515  ERR("Should not be called\n");
1516  return 2;
1517 }
1518 
1520 {
1521  ERR("Should not be called\n");
1522  return 1;
1523 }
1524 
1525 static HRESULT WINAPI PB_Read(IPropertyBag *iface, LPCOLESTR name, VARIANT *var, IErrorLog *log)
1526 {
1527  static const WCHAR dsguid[] = { 'D','S','G','u','i','d', 0 };
1529  TRACE("Trying to read %s, type %u\n", debugstr_w(name), var->n1.n2.vt);
1530  if (!lstrcmpW(name, dsguid))
1531  {
1532  WCHAR guidstr[39];
1533  StringFromGUID2(&This->devguid, guidstr,ARRAY_SIZE(guidstr));
1534  var->n1.n2.vt = VT_BSTR;
1535  var->n1.n2.n3.bstrVal = SysAllocString(guidstr);
1536  return S_OK;
1537  }
1538  ERR("Unknown property '%s' queried\n", debugstr_w(name));
1539  return E_FAIL;
1540 }
1541 
1542 static HRESULT WINAPI PB_Write(IPropertyBag *iface, LPCOLESTR name, VARIANT *var)
1543 {
1544  ERR("Should not be called\n");
1545  return E_FAIL;
1546 }
1547 
1548 static const IPropertyBagVtbl PB_Vtbl =
1549 {
1551  PB_AddRef,
1552  PB_Release,
1553  PB_Read,
1554  PB_Write
1555 };
1556 
1558 {
1559  return 2;
1560 }
1561 
1563 {
1564  return 1;
1565 }
1566 
1568  REFPROPERTYKEY key, PROPVARIANT *pv)
1569 {
1570  TRACE("(static)->(\"%s,%u\", %p)\n", debugstr_guid(&key->fmtid), key ? key->pid : 0, pv);
1571 
1572  if (!key || !pv)
1573  return E_POINTER;
1574 
1575  if (IsEqualPropertyKey(*key, DEVPKEY_Device_Driver))
1576  {
1577  INT size = (lstrlenW(drvs.module_name) + 1) * sizeof(WCHAR);
1578  pv->vt = VT_LPWSTR;
1579  pv->u.pwszVal = CoTaskMemAlloc(size);
1580  if (!pv->u.pwszVal)
1581  return E_OUTOFMEMORY;
1582  memcpy(pv->u.pwszVal, drvs.module_name, size);
1583  return S_OK;
1584  }
1585 
1586  return E_INVALIDARG;
1587 }
1588 
1589 static const IPropertyStoreVtbl info_device_ps_Vtbl =
1590 {
1591  NULL,
1594  NULL,
1595  NULL,
1597  NULL,
1598  NULL
1599 };
1600 
1603 };
1604 
1606 {
1607  return 2;
1608 }
1609 
1611 {
1612  return 1;
1613 }
1614 
1617 {
1618  TRACE("(static)->(%x, %p)\n", access, ppv);
1619  *ppv = &info_device_ps;
1620  return S_OK;
1621 }
1622 
1623 static const IMMDeviceVtbl info_device_Vtbl =
1624 {
1625  NULL,
1628  NULL,
1630  NULL,
1631  NULL
1632 };
1633 
1634 static IMMDevice info_device = {
1636 };
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:47
static HRESULT WINAPI MMDevice_Activate(IMMDevice *iface, REFIID riid, DWORD clsctx, PROPVARIANT *params, void **ppv)
Definition: devenum.c:587
static HRESULT WINAPI info_device_OpenPropertyStore(IMMDevice *iface, DWORD access, IPropertyStore **ppv)
Definition: devenum.c:1615
const GUID IID_IBaseFilter
#define MAXIMUM_ALLOWED
Definition: nt_native.h:83
void MMDevEnum_Free(void)
Definition: devenum.c:905
static const WCHAR reg_render[]
Definition: devenum.c:54
static HRESULT WINAPI info_device_ps_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *pv)
Definition: devenum.c:1567
#define IsEqualPropertyKey(a, b)
Definition: propkeydef.h:52
static ULONG WINAPI MMDevCol_AddRef(IMMDeviceCollection *iface)
Definition: devenum.c:811
IMMEndpoint IMMEndpoint_iface
Definition: mmdevapi.h:67
#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:966
struct IPropertyBagImpl IPropertyBagImpl
MMDevice * parent
Definition: devenum.c:75
#define E_NOINTERFACE
Definition: winerror.h:2364
HRESULT MMDevEnum_Create(REFIID riid, void **ppv)
Definition: devenum.c:884
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:422
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
static HRESULT WINAPI MMDevPropStore_GetCount(IPropertyStore *iface, DWORD *nprops)
Definition: devenum.c:1382
static CRITICAL_SECTION g_notif_lock
Definition: devenum.c:1101
#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:1364
static HRESULT WINAPI MMDevPropStore_QueryInterface(IPropertyStore *iface, REFIID riid, void **ppv)
Definition: devenum.c:1346
#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:2952
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:267
int WINAPI lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:170
static HRESULT WINAPI MMDevEnum_RegisterEndpointNotificationCallback(IMMDeviceEnumerator *iface, IMMNotificationClient *client)
Definition: devenum.c:1251
#define HKEY_CURRENT_USER
Definition: winreg.h:11
static const IPropertyStoreVtbl MMDevPropVtbl
Definition: devenum.c:92
struct _root root
const char * devices
Definition: diskspace.c:793
IMMDevice IMMDevice_iface
Definition: mmdevapi.h:66
#define WARN(fmt,...)
Definition: debug.h:111
static IPropertyBagImpl * impl_from_IPropertyBag(IPropertyBag *iface)
Definition: devenum.c:129
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:706
static void MMDevice_Destroy(MMDevice *This)
Definition: devenum.c:521
static HRESULT MMDevCol_Create(IMMDeviceCollection **ppv, EDataFlow flow, DWORD state)
Definition: devenum.c:772
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
static ULONG WINAPI MMDevice_Release(IMMDevice *iface)
Definition: devenum.c:577
#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:1102
LONG ref
Definition: devenum.c:100
static void MMDevPropStore_Destroy(MMDevPropStore *This)
Definition: devenum.c:1341
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
static ULONG WINAPI info_device_Release(IMMDevice *iface)
Definition: devenum.c:1610
#define lstrlenW
Definition: compat.h:407
#define E_FAIL
Definition: ddrawi.h:102
int32_t INT
Definition: typedefs.h:56
static ULONG WINAPI MMDevCol_Release(IMMDeviceCollection *iface)
Definition: devenum.c:819
Definition: send.c:47
static int dev
Definition: mkdosfs.c:536
static void MMDevCol_Destroy(MMDevColImpl *This)
Definition: devenum.c:788
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:110
struct MMDevPropStoreImpl MMDevPropStore
static ULONG WINAPI info_device_AddRef(IMMDevice *iface)
Definition: devenum.c:1605
static HRESULT WINAPI MMEndpoint_GetDataFlow(IMMEndpoint *iface, EDataFlow *flow)
Definition: devenum.c:754
static ULONG WINAPI info_device_ps_Release(IPropertyStore *iface)
Definition: devenum.c:1562
__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:102
#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:1542
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:747
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:1184
static const WCHAR reg_out_nameW[]
Definition: devenum.c:63
static HRESULT MMDevPropStore_Create(MMDevice *This, DWORD access, IPropertyStore **ppv)
Definition: devenum.c:1320
GLenum const GLfloat * params
Definition: glext.h:5645
static const IMMDeviceCollectionVtbl MMDevColVtbl
Definition: devenum.c:90
#define STG_E_ACCESSDENIED
Definition: winerror.h:2568
static ULONG WINAPI PB_AddRef(IPropertyBag *iface)
Definition: devenum.c:1513
static HRESULT load_devices_from_reg(void)
Definition: devenum.c:403
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:1601
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:241
static MMDevice * MMDevice_def_play
Definition: devenum.c:87
static HRESULT set_format(MMDevice *dev)
Definition: devenum.c:463
static MMDevice * impl_from_IMMDevice(IMMDevice *iface)
Definition: devenum.c:540
#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:60
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:86
#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:87
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
static HRESULT WINAPI MMDevPropStore_SetValue(IPropertyStore *iface, REFPROPERTYKEY key, REFPROPVARIANT pv)
Definition: devenum.c:1463
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:2897
WCHAR * drv_id
Definition: mmdevapi.h:75
static HRESULT WINAPI MMDevPropStore_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *pv)
Definition: devenum.c:1438
static void notify_clients(EDataFlow flow, ERole role, const WCHAR *id)
Definition: devenum.c:1110
#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:942
LONG HRESULT
Definition: typedefs.h:77
static HRESULT WINAPI MMDevEnum_GetDevice(IMMDeviceEnumerator *iface, const WCHAR *name, IMMDevice **device)
Definition: devenum.c:1049
const GUID IID_IUnknown
static HKEY key_capture
Definition: devenum.c:69
#define WINAPI
Definition: msvc.h:8
INT WINAPI StringFromGUID2(REFGUID id, LPOLESTR str, INT cmax)
Definition: compobj.c:2343
#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:1099
static HRESULT WINAPI MMDevEnum_EnumAudioEndpoints(IMMDeviceEnumerator *iface, EDataFlow flow, DWORD mask, IMMDeviceCollection **devices)
Definition: devenum.c:952
DWORD state
Definition: mmdevapi.h:73
static HRESULT WINAPI PB_Read(IPropertyBag *iface, LPCOLESTR name, VARIANT *var, IErrorLog *log)
Definition: devenum.c:1525
LONG ref
Definition: devenum.c:82
static HRESULT WINAPI MMDevice_QueryInterface(IMMDevice *iface, REFIID riid, void **ppv)
Definition: devenum.c:545
PCRITICAL_SECTION_DEBUG DebugInfo
Definition: winbase.h:859
static MMDevice * impl_from_IMMEndpoint(IMMEndpoint *iface)
Definition: devenum.c:728
static HRESULT WINAPI MMDevPropStore_Commit(IPropertyStore *iface)
Definition: devenum.c:1477
static const WCHAR reg_in_nameW[]
Definition: devenum.c:65
int ret
static const WCHAR reg_capture[]
Definition: devenum.c:56
static HRESULT WINAPI MMEndpoint_QueryInterface(IMMEndpoint *iface, REFIID riid, void **ppv)
Definition: devenum.c:733
static const IPropertyStoreVtbl info_device_ps_Vtbl
Definition: devenum.c:1589
static HRESULT WINAPI MMDevCol_GetCount(IMMDeviceCollection *iface, UINT *numdevs)
Definition: devenum.c:829
#define InterlockedDecrement
Definition: armddk.h:52
static MMDevice * MMDevice_Create(WCHAR *name, GUID *id, EDataFlow flow, DWORD state, BOOL setdefault)
Definition: devenum.c:290
static HRESULT WINAPI MMDevice_GetId(IMMDevice *iface, WCHAR **itemid)
Definition: devenum.c:682
static const WCHAR propkey_formatW[]
Definition: devenum.c:134
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:161
Definition: _list.h:228
static HRESULT WINAPI MMDevCol_Item(IMMDeviceCollection *iface, UINT n, IMMDevice **dev)
Definition: devenum.c:849
static const IMMDeviceVtbl info_device_Vtbl
Definition: devenum.c:1623
LIST_ENTRY ProcessLocksList
Definition: winbase.h:848
const WCHAR drv_keyW[]
Definition: main.c:55
CRITICAL_SECTION crst
Definition: mmdevapi.h:70
#define STGM_READWRITE
Definition: objbase.h:918
static const IMMDeviceEnumeratorVtbl MMDevEnumVtbl
Definition: devenum.c:89
static HRESULT WINAPI MMDevEnum_UnregisterEndpointNotificationCallback(IMMDeviceEnumerator *iface, IMMNotificationClient *client)
Definition: devenum.c:1282
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3234
static ULONG WINAPI MMDevPropStore_Release(IPropertyStore *iface)
Definition: devenum.c:1372
#define ERR(fmt,...)
Definition: debug.h:109
PSSTDAPI typedef PROPERTYKEY * REFPROPERTYKEY
Definition: propsys.idl:30
IMMDeviceEnumerator IMMDeviceEnumerator_iface
Definition: devenum.c:81
IMMNotificationClient * client
Definition: devenum.c:1094
static HKEY key_render
Definition: devenum.c:68
#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:99
HRESULT AudioEndpointVolume_Create(MMDevice *parent, IAudioEndpointVolumeEx **ppv)
Definition: audiovolume.c:307
#define InterlockedIncrement
Definition: armddk.h:53
#define IDirectSound_Release(p)
Definition: dsound.h:453
#define lstrcpyW
Definition: compat.h:406
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:106
DriverFuncs drvs
Definition: main.c:53
static HRESULT MMDevice_SetPropValue(const GUID *devguid, DWORD flow, REFPROPERTYKEY key, REFPROPVARIANT pv)
Definition: devenum.c:223
static const WCHAR reg_vout_nameW[]
Definition: devenum.c:64
#define HeapReAlloc
Definition: compat.h:393
#define E_NOTIMPL
Definition: ddrawi.h:99
static HRESULT WINAPI MMDevEnum_QueryInterface(IMMDeviceEnumerator *iface, REFIID riid, void **ppv)
Definition: devenum.c:916
static HRESULT WINAPI MMDevPropStore_GetAt(IPropertyStore *iface, DWORD prop, PROPERTYKEY *key)
Definition: devenum.c:1409
static const WCHAR reg_devicestate[]
Definition: devenum.c:58
unsigned int UINT
Definition: ndis.h:50
BOOL WINAPI IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
Definition: compobj.c:4021
IPropertyStore IPropertyStore_iface
Definition: devenum.c:73
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
VARTYPE vt
Definition: compat.h:2022
EDataFlow flow
Definition: mmdevapi.h:72
static const IMMDeviceVtbl MMDeviceVtbl
Definition: devenum.c:91
static ULONG WINAPI MMEndpoint_AddRef(IMMEndpoint *iface)
Definition: devenum.c:740
EDataFlow flow
Definition: devenum.c:101
Definition: name.c:36
HRESULT WINAPI CLSIDFromString(LPCOLESTR idstr, LPCLSID id)
Definition: compobj.c:2247
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:68
static HRESULT WINAPI PB_QueryInterface(IPropertyBag *iface, REFIID riid, void **ppv)
Definition: devenum.c:1506
static HRESULT WINAPI MMDevice_OpenPropertyStore(IMMDevice *iface, DWORD access, IPropertyStore **ppv)
Definition: devenum.c:672
WCHAR module_name[64]
Definition: mmdevapi.h:39
static const WCHAR reg_vin_nameW[]
Definition: devenum.c:66
static HRESULT MMDevPropStore_OpenPropKey(const GUID *guid, DWORD flow, HKEY *propkey)
Definition: devenum.c:140
#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:1123
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:934
struct MMDevEnumImpl MMDevEnumImpl
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
static HRESULT load_driver_devices(EDataFlow flow)
Definition: devenum.c:494
static ULONG WINAPI PB_Release(IPropertyBag *iface)
Definition: devenum.c:1519
static MMDevEnumImpl * MMDevEnumerator
Definition: devenum.c:85
static DWORD MMDevice_count
Definition: devenum.c:88
BSTR bstrVal
Definition: compat.h:2040
#define E_POINTER
Definition: winerror.h:2365
static ULONG WINAPI MMDevice_AddRef(IMMDevice *iface)
Definition: devenum.c:567
static MMDevColImpl * impl_from_IMMDeviceCollection(IMMDeviceCollection *iface)
Definition: devenum.c:124
#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:406
void user(int argc, const char *argv[])
Definition: cmds.c:1350
Definition: dsound.c:943
static const IMMEndpointVtbl MMEndpointVtbl
Definition: devenum.c:93
#define HeapFree(x, y, z)
Definition: compat.h:394
static MMDevPropStore * impl_from_IPropertyStore(IPropertyStore *iface)
Definition: devenum.c:114
static MMDevEnumImpl * impl_from_IMMDeviceEnumerator(IMMDeviceEnumerator *iface)
Definition: devenum.c:119
#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:1098
#define SUCCEEDED(hr)
Definition: intsafe.h:57
static HRESULT WINAPI MMDevCol_QueryInterface(IMMDeviceCollection *iface, REFIID riid, void **ppv)
Definition: devenum.c:793
static IMMDevice info_device
Definition: devenum.c:95
WINE_UNICODE_INLINE int atoiW(const WCHAR *str)
Definition: unicode.h:315
GUID devguid
Definition: mmdevapi.h:74
DWORD_PTR Spare[8/sizeof(DWORD_PTR)]
Definition: winbase.h:852
static ULONG WINAPI info_device_ps_AddRef(IPropertyStore *iface)
Definition: devenum.c:1557
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:62