ReactOS 0.4.15-dev-7788-g1ad9096
createdevenum.c
Go to the documentation of this file.
1/*
2 * ICreateDevEnum implementation for DEVENUM.dll
3 *
4 * Copyright (C) 2002 Robert Shearman
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 *
20 * NOTES ON THIS FILE:
21 * - Implements ICreateDevEnum interface which creates an IEnumMoniker
22 * implementation
23 * - Also creates the special registry keys created at run-time
24 */
25
26#define NONAMELESSSTRUCT
27#define NONAMELESSUNION
28
29#include "devenum_private.h"
30#include "vfw.h"
31#include "aviriff.h"
32#include "dsound.h"
33
34#include "wine/debug.h"
35#include "wine/heap.h"
36#include "mmddk.h"
37
38#include "initguid.h"
39#include "wine/fil_data.h"
40
42
43static const WCHAR wszFilterKeyName[] = {'F','i','l','t','e','r',0};
44static const WCHAR wszMeritName[] = {'M','e','r','i','t',0};
45static const WCHAR wszPins[] = {'P','i','n','s',0};
46static const WCHAR wszAllowedMany[] = {'A','l','l','o','w','e','d','M','a','n','y',0};
47static const WCHAR wszAllowedZero[] = {'A','l','l','o','w','e','d','Z','e','r','o',0};
48static const WCHAR wszDirection[] = {'D','i','r','e','c','t','i','o','n',0};
49static const WCHAR wszIsRendered[] = {'I','s','R','e','n','d','e','r','e','d',0};
50static const WCHAR wszTypes[] = {'T','y','p','e','s',0};
51static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
52static const WCHAR wszFilterData[] = {'F','i','l','t','e','r','D','a','t','a',0};
53
55static HRESULT DEVENUM_CreateAMCategoryKey(const CLSID * clsidCategory);
56
57/**********************************************************************
58 * DEVENUM_ICreateDevEnum_QueryInterface (also IUnknown)
59 */
61 void **ppv)
62{
63 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
64
65 if (!ppv)
66 return E_POINTER;
67
69 IsEqualGUID(riid, &IID_ICreateDevEnum))
70 {
71 *ppv = iface;
73 return S_OK;
74 }
75
76 FIXME("- no interface IID: %s\n", debugstr_guid(riid));
77 *ppv = NULL;
78 return E_NOINTERFACE;
79}
80
81/**********************************************************************
82 * DEVENUM_ICreateDevEnum_AddRef (also IUnknown)
83 */
85{
86 TRACE("\n");
87
89
90 return 2; /* non-heap based object */
91}
92
93/**********************************************************************
94 * DEVENUM_ICreateDevEnum_Release (also IUnknown)
95 */
97{
98 TRACE("\n");
99
101
102 return 1; /* non-heap based object */
103}
104
105static HRESULT register_codec(const GUID *class, const WCHAR *name,
106 const GUID *clsid, const WCHAR *friendly_name, IPropertyBag **ret)
107{
108 static const WCHAR deviceW[] = {'@','d','e','v','i','c','e',':','c','m',':',0};
109 WCHAR guidstr[CHARS_IN_GUID];
111 IPropertyBag *propbag;
112 IMoniker *mon;
113 WCHAR *buffer;
114 VARIANT var;
115 ULONG eaten;
116 HRESULT hr;
117
118 hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (void **)&parser);
119 if (FAILED(hr))
120 return hr;
121
123 if (!buffer)
124 {
125 IParseDisplayName_Release(parser);
126 return E_OUTOFMEMORY;
127 }
128
133
134 IParseDisplayName_ParseDisplayName(parser, NULL, buffer, &eaten, &mon);
135 IParseDisplayName_Release(parser);
137
138 IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&propbag);
139 IMoniker_Release(mon);
140
141 V_VT(&var) = VT_BSTR;
143 hr = IPropertyBag_Write(propbag, wszFriendlyName, &var);
145 if (FAILED(hr))
146 {
147 IPropertyBag_Release(propbag);
148 return hr;
149 }
150
151 V_VT(&var) = VT_BSTR;
152 StringFromGUID2(clsid, guidstr, ARRAY_SIZE(guidstr));
153 V_BSTR(&var) = SysAllocString(guidstr);
154 hr = IPropertyBag_Write(propbag, clsidW, &var);
156 if (FAILED(hr))
157 {
158 IPropertyBag_Release(propbag);
159 return hr;
160 }
161
162 *ret = propbag;
163 return S_OK;
164}
165
166static void DEVENUM_ReadPinTypes(HKEY hkeyPinKey, REGFILTERPINS2 *rgPin)
167{
168 HKEY hkeyTypes = NULL;
169 DWORD dwMajorTypes, i;
170 REGPINTYPES *lpMediaType = NULL;
171 DWORD dwMediaTypeSize = 0;
172
173 if (RegOpenKeyExW(hkeyPinKey, wszTypes, 0, KEY_READ, &hkeyTypes) != ERROR_SUCCESS)
174 return ;
175
176 if (RegQueryInfoKeyW(hkeyTypes, NULL, NULL, NULL, &dwMajorTypes, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
177 != ERROR_SUCCESS)
178 {
179 RegCloseKey(hkeyTypes);
180 return ;
181 }
182
183 for (i = 0; i < dwMajorTypes; i++)
184 {
185 HKEY hkeyMajorType = NULL;
186 WCHAR wszMajorTypeName[64];
187 DWORD cName = ARRAY_SIZE(wszMajorTypeName);
188 DWORD dwMinorTypes, i1;
189
190 if (RegEnumKeyExW(hkeyTypes, i, wszMajorTypeName, &cName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) continue;
191
192 if (RegOpenKeyExW(hkeyTypes, wszMajorTypeName, 0, KEY_READ, &hkeyMajorType) != ERROR_SUCCESS) continue;
193
194 if (RegQueryInfoKeyW(hkeyMajorType, NULL, NULL, NULL, &dwMinorTypes, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
195 != ERROR_SUCCESS)
196 {
197 RegCloseKey(hkeyMajorType);
198 continue;
199 }
200
201 for (i1 = 0; i1 < dwMinorTypes; i1++)
202 {
203 WCHAR wszMinorTypeName[64];
204 CLSID *clsMajorType = NULL, *clsMinorType = NULL;
205 HRESULT hr;
206
207 cName = ARRAY_SIZE(wszMinorTypeName);
208 if (RegEnumKeyExW(hkeyMajorType, i1, wszMinorTypeName, &cName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) continue;
209
211 if (!clsMinorType) continue;
212
213 clsMajorType = CoTaskMemAlloc(sizeof(CLSID));
214 if (!clsMajorType) goto error_cleanup_types;
215
216 hr = CLSIDFromString(wszMinorTypeName, clsMinorType);
217 if (FAILED(hr)) goto error_cleanup_types;
218
219 hr = CLSIDFromString(wszMajorTypeName, clsMajorType);
220 if (FAILED(hr)) goto error_cleanup_types;
221
222 if (rgPin->nMediaTypes == dwMediaTypeSize)
223 {
224 DWORD dwNewSize = dwMediaTypeSize + (dwMediaTypeSize < 2 ? 1 : dwMediaTypeSize / 2);
225 REGPINTYPES *lpNewMediaType;
226
227 lpNewMediaType = CoTaskMemRealloc(lpMediaType, sizeof(REGPINTYPES) * dwNewSize);
228 if (!lpNewMediaType) goto error_cleanup_types;
229
230 lpMediaType = lpNewMediaType;
231 dwMediaTypeSize = dwNewSize;
232 }
233
234 lpMediaType[rgPin->nMediaTypes].clsMajorType = clsMajorType;
235 lpMediaType[rgPin->nMediaTypes].clsMinorType = clsMinorType;
236 rgPin->nMediaTypes++;
237 continue;
238
239 error_cleanup_types:
240
241 CoTaskMemFree(clsMajorType);
243 }
244
245 RegCloseKey(hkeyMajorType);
246 }
247
248 RegCloseKey(hkeyTypes);
249
250 if (lpMediaType && !rgPin->nMediaTypes)
251 {
252 CoTaskMemFree(lpMediaType);
253 lpMediaType = NULL;
254 }
255
256 rgPin->lpMediaType = lpMediaType;
257}
258
259static void DEVENUM_ReadPins(HKEY hkeyFilterClass, REGFILTER2 *rgf2)
260{
261 HKEY hkeyPins = NULL;
262 DWORD dwPinsSubkeys, i;
263 REGFILTERPINS2 *rgPins = NULL;
264
265 rgf2->dwVersion = 2;
266 rgf2->u.s2.cPins2 = 0;
267 rgf2->u.s2.rgPins2 = NULL;
268
269 if (RegOpenKeyExW(hkeyFilterClass, wszPins, 0, KEY_READ, &hkeyPins) != ERROR_SUCCESS)
270 return ;
271
272 if (RegQueryInfoKeyW(hkeyPins, NULL, NULL, NULL, &dwPinsSubkeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
273 != ERROR_SUCCESS)
274 {
275 RegCloseKey(hkeyPins);
276 return ;
277 }
278
279 if (dwPinsSubkeys)
280 {
281 rgPins = CoTaskMemAlloc(sizeof(REGFILTERPINS2) * dwPinsSubkeys);
282 if (!rgPins)
283 {
284 RegCloseKey(hkeyPins);
285 return ;
286 }
287 }
288
289 for (i = 0; i < dwPinsSubkeys; i++)
290 {
291 HKEY hkeyPinKey = NULL;
292 WCHAR wszPinName[MAX_PATH];
293 DWORD cName = ARRAY_SIZE(wszPinName);
294 REGFILTERPINS2 *rgPin = &rgPins[rgf2->u.s2.cPins2];
296 LONG lRet;
297
298 memset(rgPin, 0, sizeof(*rgPin));
299
300 if (RegEnumKeyExW(hkeyPins, i, wszPinName, &cName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) continue;
301
302 if (RegOpenKeyExW(hkeyPins, wszPinName, 0, KEY_READ, &hkeyPinKey) != ERROR_SUCCESS) continue;
303
304 size = sizeof(DWORD);
305 lRet = RegQueryValueExW(hkeyPinKey, wszAllowedMany, NULL, &Type, (BYTE *)&value, &size);
306 if (lRet != ERROR_SUCCESS || Type != REG_DWORD)
307 goto error_cleanup;
308 if (value)
309 rgPin->dwFlags |= REG_PINFLAG_B_MANY;
310
311 size = sizeof(DWORD);
312 lRet = RegQueryValueExW(hkeyPinKey, wszAllowedZero, NULL, &Type, (BYTE *)&value, &size);
313 if (lRet != ERROR_SUCCESS || Type != REG_DWORD)
314 goto error_cleanup;
315 if (value)
316 rgPin->dwFlags |= REG_PINFLAG_B_ZERO;
317
318 size = sizeof(DWORD);
319 lRet = RegQueryValueExW(hkeyPinKey, wszDirection, NULL, &Type, (BYTE *)&value, &size);
320 if (lRet != ERROR_SUCCESS || Type != REG_DWORD)
321 goto error_cleanup;
322 if (value)
324
325
326 size = sizeof(DWORD);
327 lRet = RegQueryValueExW(hkeyPinKey, wszIsRendered, NULL, &Type, (BYTE *)&value, &size);
328 if (lRet != ERROR_SUCCESS || Type != REG_DWORD)
329 goto error_cleanup;
330 if (value)
332
333 DEVENUM_ReadPinTypes(hkeyPinKey, rgPin);
334
335 ++rgf2->u.s2.cPins2;
336 continue;
337
338 error_cleanup:
339
340 RegCloseKey(hkeyPinKey);
341 }
342
343 RegCloseKey(hkeyPins);
344
345 if (rgPins && !rgf2->u.s2.cPins2)
346 {
347 CoTaskMemFree(rgPins);
348 rgPins = NULL;
349 }
350
351 rgf2->u.s2.rgPins2 = rgPins;
352}
353
355{
356 if (rgf->u.s2.rgPins2)
357 {
358 UINT iPin;
359
360 for (iPin = 0; iPin < rgf->u.s2.cPins2; iPin++)
361 {
362 if (rgf->u.s2.rgPins2[iPin].lpMediaType)
363 {
364 UINT iType;
365
366 for (iType = 0; iType < rgf->u.s2.rgPins2[iPin].nMediaTypes; iType++)
367 {
368 CoTaskMemFree((void *)rgf->u.s2.rgPins2[iPin].lpMediaType[iType].clsMajorType);
369 CoTaskMemFree((void *)rgf->u.s2.rgPins2[iPin].lpMediaType[iType].clsMinorType);
370 }
371
372 CoTaskMemFree((void *)rgf->u.s2.rgPins2[iPin].lpMediaType);
373 }
374 }
375
376 CoTaskMemFree((void *)rgf->u.s2.rgPins2);
377 }
378}
379
380static void write_filter_data(IPropertyBag *prop_bag, REGFILTER2 *rgf)
381{
382 BYTE *data = NULL, *array;
383 IAMFilterData *fildata;
384 SAFEARRAYBOUND sabound;
385 VARIANT var;
386 ULONG size;
387 HRESULT hr;
388
389 hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC, &IID_IAMFilterData, (void **)&fildata);
390 if (FAILED(hr)) goto cleanup;
391
392 hr = IAMFilterData_CreateFilterData(fildata, rgf, &data, &size);
393 if (FAILED(hr)) goto cleanup;
394
395 V_VT(&var) = VT_ARRAY | VT_UI1;
396 sabound.lLbound = 0;
397 sabound.cElements = size;
398 if (!(V_ARRAY(&var) = SafeArrayCreate(VT_UI1, 1, &sabound)))
399 goto cleanup;
400 hr = SafeArrayAccessData(V_ARRAY(&var), (void *)&array);
401 if (FAILED(hr)) goto cleanup;
402
405 if (FAILED(hr)) goto cleanup;
406
407 hr = IPropertyBag_Write(prop_bag, wszFilterData, &var);
408 if (FAILED(hr)) goto cleanup;
409
410cleanup:
413 IAMFilterData_Release(fildata);
414}
415
416static void register_legacy_filters(void)
417{
418 HKEY hkeyFilter = NULL;
419 DWORD dwFilterSubkeys, i;
420 LONG lRet;
421 HRESULT hr;
422
424 hr = HRESULT_FROM_WIN32(lRet);
425
426 if (SUCCEEDED(hr))
427 {
428 lRet = RegQueryInfoKeyW(hkeyFilter, NULL, NULL, NULL, &dwFilterSubkeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
429 hr = HRESULT_FROM_WIN32(lRet);
430 }
431
432 if (SUCCEEDED(hr))
433 hr = DEVENUM_CreateAMCategoryKey(&CLSID_LegacyAmFilterCategory);
434
435 if (SUCCEEDED(hr))
436 {
437 for (i = 0; i < dwFilterSubkeys; i++)
438 {
439 WCHAR wszFilterSubkeyName[64];
440 DWORD cName = ARRAY_SIZE(wszFilterSubkeyName);
441 IPropertyBag *prop_bag = NULL;
442 WCHAR wszRegKey[MAX_PATH];
443 HKEY classkey = NULL;
444 REGFILTER2 rgf2;
445 DWORD Type, len;
446 GUID clsid;
447
448 if (RegEnumKeyExW(hkeyFilter, i, wszFilterSubkeyName, &cName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) continue;
449
450 TRACE("Registering %s\n", debugstr_w(wszFilterSubkeyName));
451
452 hr = CLSIDFromString(wszFilterSubkeyName, &clsid);
453 if (FAILED(hr))
454 continue;
455
456 lstrcpyW(wszRegKey, clsidW);
457 lstrcatW(wszRegKey, backslashW);
458 lstrcatW(wszRegKey, wszFilterSubkeyName);
459
460 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszRegKey, 0, KEY_READ, &classkey) != ERROR_SUCCESS)
461 continue;
462
463 len = 0;
464 if (!RegQueryValueExW(classkey, NULL, NULL, &Type, NULL, &len))
465 {
466 WCHAR *friendlyname = heap_alloc(len);
467 if (!friendlyname)
468 {
469 RegCloseKey(classkey);
470 continue;
471 }
472 RegQueryValueExW(classkey, NULL, NULL, &Type, (BYTE *)friendlyname, &len);
473
474 hr = register_codec(&CLSID_LegacyAmFilterCategory, wszFilterSubkeyName,
475 &clsid, friendlyname, &prop_bag);
476
477 heap_free(friendlyname);
478 }
479 else
480 hr = register_codec(&CLSID_LegacyAmFilterCategory, wszFilterSubkeyName,
481 &clsid, wszFilterSubkeyName, &prop_bag);
482 if (FAILED(hr))
483 {
484 RegCloseKey(classkey);
485 continue;
486 }
487
488 /* write filter data */
489 rgf2.dwMerit = MERIT_NORMAL;
490
491 len = sizeof(rgf2.dwMerit);
492 RegQueryValueExW(classkey, wszMeritName, NULL, &Type, (BYTE *)&rgf2.dwMerit, &len);
493
494 DEVENUM_ReadPins(classkey, &rgf2);
495
496 write_filter_data(prop_bag, &rgf2);
497
498 IPropertyBag_Release(prop_bag);
499 RegCloseKey(classkey);
500 free_regfilter2(&rgf2);
501 }
502 }
503
504 if (hkeyFilter) RegCloseKey(hkeyFilter);
505}
506
508{
509 static const WCHAR defaultW[] = {'D','e','f','a','u','l','t',' ','D','i','r','e','c','t','S','o','u','n','d',' ','D','e','v','i','c','e',0};
510 static const WCHAR directsoundW[] = {'D','i','r','e','c','t','S','o','u','n','d',':',' ',0};
511 static const WCHAR dsguidW[] = {'D','S','G','u','i','d',0};
512 IPropertyBag *prop_bag = NULL;
513 REGFILTERPINS2 rgpins = {0};
514 REGPINTYPES rgtypes = {0};
515 REGFILTER2 rgf = {0};
517 VARIANT var;
518 HRESULT hr;
519
520 hr = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory);
521 if (FAILED(hr))
522 return FALSE;
523
524 if (guid)
525 {
526 WCHAR *name = heap_alloc(sizeof(defaultW) + lstrlenW(desc) * sizeof(WCHAR));
527 if (!name)
528 return FALSE;
529 lstrcpyW(name, directsoundW);
531
532 hr = register_codec(&CLSID_AudioRendererCategory, name,
533 &CLSID_DSoundRender, name, &prop_bag);
535 }
536 else
537 hr = register_codec(&CLSID_AudioRendererCategory, defaultW,
538 &CLSID_DSoundRender, defaultW, &prop_bag);
539 if (FAILED(hr))
540 return FALSE;
541
542 /* write filter data */
543 rgf.dwVersion = 2;
544 rgf.dwMerit = guid ? MERIT_DO_NOT_USE : MERIT_PREFERRED;
545 rgf.u.s2.cPins2 = 1;
546 rgf.u.s2.rgPins2 = &rgpins;
548 /* FIXME: native registers many more formats */
549 rgpins.nMediaTypes = 1;
550 rgpins.lpMediaType = &rgtypes;
551 rgtypes.clsMajorType = &MEDIATYPE_Audio;
552 rgtypes.clsMinorType = &MEDIASUBTYPE_PCM;
553
554 write_filter_data(prop_bag, &rgf);
555
556 /* write DSound guid */
557 V_VT(&var) = VT_BSTR;
559 if ((V_BSTR(&var) = SysAllocString(clsid)))
560 hr = IPropertyBag_Write(prop_bag, dsguidW, &var);
561
563 IPropertyBag_Release(prop_bag);
564 return TRUE;
565}
566
568{
569 static const WCHAR defaultW[] = {'D','e','f','a','u','l','t',' ','W','a','v','e','O','u','t',' ','D','e','v','i','c','e',0};
570 static const WCHAR waveoutidW[] = {'W','a','v','e','O','u','t','I','d',0};
571 IPropertyBag *prop_bag = NULL;
572 REGFILTERPINS2 rgpins = {0};
573 REGPINTYPES rgtypes = {0};
574 REGFILTER2 rgf = {0};
575 WAVEOUTCAPSW caps;
576 const WCHAR *name;
577 int i, count;
578 VARIANT var;
579 HRESULT hr;
580
581 hr = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory);
582 if (FAILED(hr)) return;
583
585
586 for (i = -1; i < count; i++)
587 {
588 waveOutGetDevCapsW(i, &caps, sizeof(caps));
589
590 name = (i == -1) ? defaultW : caps.szPname;
591
592 hr = register_codec(&CLSID_AudioRendererCategory, name,
593 &CLSID_AudioRender, name, &prop_bag);
594 if (FAILED(hr))
595 continue;
596
597 /* write filter data */
598 rgf.dwVersion = 2;
600 rgf.u.s2.cPins2 = 1;
601 rgf.u.s2.rgPins2 = &rgpins;
603 rgpins.nMediaTypes = 1;
604 rgpins.lpMediaType = &rgtypes;
605 rgtypes.clsMajorType = &MEDIATYPE_Audio;
606 rgtypes.clsMinorType = &MEDIASUBTYPE_NULL;
607
608 write_filter_data(prop_bag, &rgf);
609
610 /* write WaveOutId */
611 V_VT(&var) = VT_I4;
612 V_I4(&var) = i;
613 IPropertyBag_Write(prop_bag, waveoutidW, &var);
614
616 if (prop_bag) IPropertyBag_Release(prop_bag);
617 }
618}
619
620static void register_wavein_devices(void)
621{
622 static const WCHAR waveinidW[] = {'W','a','v','e','I','n','I','d',0};
623 IPropertyBag *prop_bag = NULL;
624 REGFILTER2 rgf = {0};
625 WAVEINCAPSW caps;
626 int i, count;
627 VARIANT var;
628 HRESULT hr;
629
630 hr = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory);
631 if (FAILED(hr)) return;
632
634
635 for (i = 0; i < count; i++)
636 {
637 waveInGetDevCapsW(i, &caps, sizeof(caps));
638
639 hr = register_codec(&CLSID_AudioInputDeviceCategory, caps.szPname,
640 &CLSID_AudioRecord, caps.szPname, &prop_bag);
641 if (FAILED(hr))
642 continue;
643
644 /* write filter data */
645 rgf.dwVersion = 2;
647
648 write_filter_data(prop_bag, &rgf);
649
650 /* write WaveInId */
651 V_VT(&var) = VT_I4;
652 V_I4(&var) = i;
653 IPropertyBag_Write(prop_bag, waveinidW, &var);
654
656 IPropertyBag_Release(prop_bag);
657 }
658}
659
661{
662 static const WCHAR defaultW[] = {'D','e','f','a','u','l','t',' ','M','i','d','i','O','u','t',' ','D','e','v','i','c','e',0};
663 static const WCHAR midioutidW[] = {'M','i','d','i','O','u','t','I','d',0};
664 IPropertyBag *prop_bag = NULL;
665 REGFILTERPINS2 rgpins = {0};
666 REGPINTYPES rgtypes = {0};
667 REGFILTER2 rgf = {0};
668 MIDIOUTCAPSW caps;
669 const WCHAR *name;
670 int i, count;
671 VARIANT var;
672 HRESULT hr;
673
674 hr = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory);
675 if (FAILED(hr)) return;
676
678
679 for (i = -1; i < count; i++)
680 {
681 midiOutGetDevCapsW(i, &caps, sizeof(caps));
682
683 name = (i == -1) ? defaultW : caps.szPname;
684
685 hr = register_codec(&CLSID_MidiRendererCategory, name,
686 &CLSID_AVIMIDIRender, name, &prop_bag);
687 if (FAILED(hr))
688 continue;
689
690 /* write filter data */
691 rgf.dwVersion = 2;
692 rgf.dwMerit = (i == -1) ? MERIT_PREFERRED : MERIT_DO_NOT_USE;
693 rgf.u.s2.cPins2 = 1;
694 rgf.u.s2.rgPins2 = &rgpins;
696 rgpins.nMediaTypes = 1;
697 rgpins.lpMediaType = &rgtypes;
698 rgtypes.clsMajorType = &MEDIATYPE_Midi;
699 rgtypes.clsMinorType = &MEDIASUBTYPE_NULL;
700
701 write_filter_data(prop_bag, &rgf);
702
703 /* write MidiOutId */
704 V_VT(&var) = VT_I4;
705 V_I4(&var) = i;
706 IPropertyBag_Write(prop_bag, midioutidW, &var);
707
709 IPropertyBag_Release(prop_bag);
710 }
711}
712
713static void register_vfw_codecs(void)
714{
715 static const WCHAR fcchandlerW[] = {'F','c','c','H','a','n','d','l','e','r',0};
716 REGFILTERPINS2 rgpins[2] = {{0}};
717 IPropertyBag *prop_bag = NULL;
718 REGPINTYPES rgtypes[2];
719 REGFILTER2 rgf;
720 GUID typeguid;
721 ICINFO info;
722 VARIANT var;
723 HRESULT hr;
724 int i = 0;
725 HIC hic;
726
727 hr = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory);
728 if (FAILED(hr)) return;
729
730 while (ICInfo(ICTYPE_VIDEO, i++, &info))
731 {
732 WCHAR name[5] = {LOBYTE(LOWORD(info.fccHandler)), HIBYTE(LOWORD(info.fccHandler)),
733 LOBYTE(HIWORD(info.fccHandler)), HIBYTE(HIWORD(info.fccHandler))};
734
735 hic = ICOpen(ICTYPE_VIDEO, info.fccHandler, ICMODE_QUERY);
736 ICGetInfo(hic, &info, sizeof(info));
737 ICClose(hic);
738
739 hr = register_codec(&CLSID_VideoCompressorCategory, name,
740 &CLSID_AVICo, info.szDescription, &prop_bag);
741 if (FAILED(hr))
742 continue;
743
744 /* write filter data */
745 rgf.dwVersion = 2;
747 rgf.u.s2.cPins2 = 2;
748 rgf.u.s2.rgPins2 = rgpins;
749 rgpins[0].dwFlags = 0;
750 rgpins[0].nMediaTypes = 1;
751 rgpins[0].lpMediaType = &rgtypes[0];
752 rgtypes[0].clsMajorType = &MEDIATYPE_Video;
753 typeguid = MEDIASUBTYPE_PCM;
754 typeguid.Data1 = info.fccHandler;
755 rgtypes[0].clsMinorType = &typeguid;
756 rgpins[1].dwFlags = REG_PINFLAG_B_OUTPUT;
757 rgpins[1].nMediaTypes = 1;
758 rgpins[1].lpMediaType = &rgtypes[1];
759 rgtypes[1].clsMajorType = &MEDIATYPE_Video;
760 rgtypes[1].clsMinorType = &GUID_NULL;
761
762 write_filter_data(prop_bag, &rgf);
763
764 /* write WaveInId */
765 V_VT(&var) = VT_BSTR;
767 IPropertyBag_Write(prop_bag, fcchandlerW, &var);
768
770 IPropertyBag_Release(prop_bag);
771 }
772}
773
774static void register_avicap_devices(void)
775{
776 static const WCHAR vfwindexW[] = {'V','F','W','I','n','d','e','x',0};
777 WCHAR name[] = {'v','i','d','e','o','0',0};
778 WCHAR friendlyname[32], version[32];
779 IPropertyBag *prop_bag = NULL;
780 REGFILTERPINS2 rgpins = {0};
781 REGPINTYPES rgtypes;
782 REGFILTER2 rgf;
783 VARIANT var;
784 HRESULT hr;
785 int i = 0;
786
787 hr = DEVENUM_CreateAMCategoryKey(&CLSID_VideoInputDeviceCategory);
788 if (FAILED(hr))
789 return;
790
791 for (i = 0; i < 10; ++i)
792 {
793 if (!capGetDriverDescriptionW(i, friendlyname, ARRAY_SIZE(friendlyname),
795 continue;
796
797 name[5] = '0' + i;
798
799 hr = register_codec(&CLSID_VideoInputDeviceCategory, name,
800 &CLSID_VfwCapture, friendlyname, &prop_bag);
801 if (FAILED(hr))
802 continue;
803
804 rgf.dwVersion = 2;
806 rgf.u.s2.cPins2 = 1;
807 rgf.u.s2.rgPins2 = &rgpins;
808 rgpins.dwFlags = 0;
809 rgpins.nMediaTypes = 1;
810 rgpins.lpMediaType = &rgtypes;
811 rgtypes.clsMajorType = &MEDIATYPE_Video;
812 rgtypes.clsMinorType = &MEDIASUBTYPE_None;
813
814 write_filter_data(prop_bag, &rgf);
815
816 /* write VFWIndex */
817 V_VT(&var) = VT_I4;
818 V_I4(&var) = i;
819 IPropertyBag_Write(prop_bag, vfwindexW, &var);
820
822 IPropertyBag_Release(prop_bag);
823 }
824}
825
826/**********************************************************************
827 * DEVENUM_ICreateDevEnum_CreateClassEnumerator
828 */
831{
832 WCHAR guidstr[CHARS_IN_GUID];
833 HRESULT hr;
834 HKEY key;
835
836 TRACE("iface %p, class %s, out %p, flags %#x.\n", iface, debugstr_guid(class), out, flags);
837
838 if (!out)
839 return E_POINTER;
840
841 *out = NULL;
842
844 {
845 StringFromGUID2(class, guidstr, ARRAY_SIZE(guidstr));
846 RegDeleteTreeW(key, guidstr);
847 }
848
849 if (IsEqualGUID(class, &CLSID_LegacyAmFilterCategory))
851 else if (IsEqualGUID(class, &CLSID_AudioRendererCategory))
852 {
854 if (FAILED(hr)) return hr;
857 }
858 else if (IsEqualGUID(class, &CLSID_AudioInputDeviceCategory))
860 else if (IsEqualGUID(class, &CLSID_VideoCompressorCategory))
862 else if (IsEqualGUID(class, &CLSID_VideoInputDeviceCategory))
864
865 if (SUCCEEDED(hr = create_EnumMoniker(class, out)))
866 {
867 IMoniker *mon;
868 hr = IEnumMoniker_Next(*out, 1, &mon, NULL);
869 if (hr == S_OK)
870 {
871 IMoniker_Release(mon);
872 IEnumMoniker_Reset(*out);
873 }
874 else
875 {
876 IEnumMoniker_Release(*out);
877 *out = NULL;
878 }
879 }
880
881 return hr;
882}
883
884/**********************************************************************
885 * ICreateDevEnum_Vtbl
886 */
887static const ICreateDevEnumVtbl ICreateDevEnum_Vtbl =
888{
893};
894
895/**********************************************************************
896 * static CreateDevEnum instance
897 */
899
900/**********************************************************************
901 * DEVENUM_CreateAMCategoryKey (INTERNAL)
902 *
903 * Creates a registry key for a category at HKEY_CURRENT_USER\Software\
904 * Microsoft\ActiveMovie\devenum\{clsid}
905 */
906static HRESULT DEVENUM_CreateAMCategoryKey(const CLSID * clsidCategory)
907{
908 WCHAR wszRegKey[MAX_PATH];
909 HRESULT res = S_OK;
910 HKEY hkeyDummy = NULL;
911
912 lstrcpyW(wszRegKey, wszActiveMovieKey);
913
914 if (!StringFromGUID2(clsidCategory, wszRegKey + lstrlenW(wszRegKey), ARRAY_SIZE(wszRegKey) - lstrlenW(wszRegKey)))
916
917 if (SUCCEEDED(res))
918 {
919 LONG lRes = RegCreateKeyW(HKEY_CURRENT_USER, wszRegKey, &hkeyDummy);
920 res = HRESULT_FROM_WIN32(lRes);
921 }
922
923 if (hkeyDummy)
924 RegCloseKey(hkeyDummy);
925
926 if (FAILED(res))
927 ERR("Failed to create key HKEY_CURRENT_USER\\%s\n", debugstr_w(wszRegKey));
928
929 return res;
930}
Type
Definition: Type.h:7
static void * heap_alloc(size_t len)
Definition: appwiz.h:66
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
BOOL VFWAPI capGetDriverDescriptionW(WORD wDriverIndex, LPWSTR lpszName, INT cbName, LPWSTR lpszVer, INT cbVer)
Definition: avicap32.c:142
REGPINTYPES
Definition: axextend.idl:192
@ REG_PINFLAG_B_RENDERER
Definition: axextend.idl:217
@ REG_PINFLAG_B_OUTPUT
Definition: axextend.idl:219
@ REG_PINFLAG_B_ZERO
Definition: axextend.idl:216
const CLSID * clsMinorType
Definition: axextend.idl:191
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define ARRAY_SIZE(A)
Definition: main.h:33
const GUID IID_IUnknown
#define FIXME(fmt,...)
Definition: debug.h:111
#define ERR(fmt,...)
Definition: debug.h:110
#define RegCloseKey(hKey)
Definition: registry.h:49
return
Definition: dirsup.c:529
LSTATUS WINAPI RegDeleteTreeW(_In_ HKEY, _In_opt_ LPCWSTR)
#define CHARS_IN_GUID
static const WCHAR wszDirection[]
Definition: createdevenum.c:48
static ULONG WINAPI DEVENUM_ICreateDevEnum_Release(ICreateDevEnum *iface)
Definition: createdevenum.c:96
static const WCHAR wszFilterKeyName[]
Definition: createdevenum.c:43
static void register_vfw_codecs(void)
static const WCHAR wszFilterData[]
Definition: createdevenum.c:52
static HRESULT DEVENUM_CreateAMCategoryKey(const CLSID *clsidCategory)
static HRESULT register_codec(const GUID *class, const WCHAR *name, const GUID *clsid, const WCHAR *friendly_name, IPropertyBag **ret)
static const WCHAR wszTypes[]
Definition: createdevenum.c:50
static void register_wavein_devices(void)
static void register_legacy_filters(void)
static void register_midiout_devices(void)
static const WCHAR wszAllowedMany[]
Definition: createdevenum.c:46
static HRESULT WINAPI DEVENUM_ICreateDevEnum_QueryInterface(ICreateDevEnum *iface, REFIID riid, void **ppv)
Definition: createdevenum.c:60
ICreateDevEnum DEVENUM_CreateDevEnum
static void free_regfilter2(REGFILTER2 *rgf)
static void DEVENUM_ReadPins(HKEY hkeyFilterClass, REGFILTER2 *rgf2)
static ULONG WINAPI DEVENUM_ICreateDevEnum_AddRef(ICreateDevEnum *iface)
Definition: createdevenum.c:84
static const WCHAR wszMeritName[]
Definition: createdevenum.c:44
static void write_filter_data(IPropertyBag *prop_bag, REGFILTER2 *rgf)
static const WCHAR wszPins[]
Definition: createdevenum.c:45
static void DEVENUM_ReadPinTypes(HKEY hkeyPinKey, REGFILTERPINS2 *rgPin)
static const ICreateDevEnumVtbl ICreateDevEnum_Vtbl
static HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator(ICreateDevEnum *iface, REFCLSID class, IEnumMoniker **out, DWORD flags)
static const WCHAR wszAllowedZero[]
Definition: createdevenum.c:47
static void register_avicap_devices(void)
static void register_waveout_devices(void)
static const WCHAR wszFriendlyName[]
Definition: createdevenum.c:51
static const WCHAR wszIsRendered[]
Definition: createdevenum.c:49
static BOOL CALLBACK register_dsound_devices(GUID *guid, const WCHAR *desc, const WCHAR *module, void *context)
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define ERROR_SUCCESS
Definition: deptool.c:10
static const WCHAR wszActiveMovieKey[]
static const WCHAR deviceW[]
static void DEVENUM_UnlockModule(void)
HRESULT create_EnumMoniker(REFCLSID class, IEnumMoniker **enum_mon) DECLSPEC_HIDDEN
static const WCHAR backslashW[]
static void DEVENUM_LockModule(void)
static const WCHAR clsidW[]
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
HRESULT WINAPI DirectSoundEnumerateW(LPDSENUMCALLBACKW lpDSEnumCallback, LPVOID lpContext)
Definition: enum.c:210
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3362
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:2533
LONG WINAPI RegOpenKeyW(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3297
LONG WINAPI RegQueryInfoKeyW(HKEY hKey, LPWSTR lpClass, LPDWORD lpcClass, LPDWORD lpReserved, LPDWORD lpcSubKeys, LPDWORD lpcMaxSubKeyLen, LPDWORD lpcMaxClassLen, LPDWORD lpcValues, LPDWORD lpcMaxValueNameLen, LPDWORD lpcMaxValueLen, LPDWORD lpcbSecurityDescriptor, PFILETIME lpftLastWriteTime)
Definition: reg.c:3691
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4132
LONG WINAPI RegCreateKeyW(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:1201
#define MAX_PATH
Definition: compat.h:34
#define CALLBACK
Definition: compat.h:35
#define lstrcpyW
Definition: compat.h:749
@ VT_BSTR
Definition: compat.h:2303
@ VT_ARRAY
Definition: compat.h:2341
@ VT_I4
Definition: compat.h:2298
@ VT_UI1
Definition: compat.h:2311
#define lstrlenW
Definition: compat.h:750
static const WCHAR version[]
Definition: asmname.c:66
static void cleanup(void)
Definition: main.c:1335
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3325
HRESULT WINAPI CLSIDFromString(LPCOLESTR idstr, LPCLSID id)
Definition: compobj.c:2338
INT WINAPI StringFromGUID2(REFGUID id, LPOLESTR str, INT cmax)
Definition: compobj.c:2434
HRESULT WINAPI SafeArrayAccessData(SAFEARRAY *psa, void **ppvData)
Definition: safearray.c:1137
HRESULT WINAPI SafeArrayUnaccessData(SAFEARRAY *psa)
Definition: safearray.c:1168
SAFEARRAY *WINAPI SafeArrayCreate(VARTYPE vt, UINT cDims, SAFEARRAYBOUND *rgsabound)
Definition: safearray.c:600
#define REG_PINFLAG_B_MANY
Definition: precomp.h:17
#define MERIT_DO_NOT_USE
Definition: precomp.h:18
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLsizeiptr size
Definition: glext.h:5919
GLuint res
Definition: glext.h:9613
GLuint buffer
Definition: glext.h:5915
GLbitfield flags
Definition: glext.h:7161
GLenum GLsizei len
Definition: glext.h:6722
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
LPVOID WINAPI CoTaskMemRealloc(LPVOID pvOld, SIZE_T size)
Definition: ifs.c:460
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:442
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:426
REFIID riid
Definition: atlbase.h:39
REFIID LPVOID * ppv
Definition: atlbase.h:39
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
#define LOBYTE(W)
Definition: jmemdos.c:487
#define HIBYTE(W)
Definition: jmemdos.c:486
#define debugstr_guid
Definition: kernel32.h:35
#define debugstr_w
Definition: kernel32.h:32
#define GUID_NULL
Definition: ks.h:106
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
const GUID * guid
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define ICTYPE_VIDEO
Definition: mmreg.h:531
static const WCHAR desc[]
Definition: protectdata.c:36
const char * var
Definition: shader.c:5666
static const WCHAR friendly_name[]
Definition: devenum.c:40
REFCLSID clsid
Definition: msctf.c:82
HIC VFWAPI ICOpen(DWORD fccType, DWORD fccHandler, UINT wMode)
Definition: msvideo_main.c:441
LRESULT VFWAPI ICGetInfo(HIC hic, ICINFO *picinfo, DWORD cb)
Definition: msvideo_main.c:594
BOOL VFWAPI ICInfo(DWORD type, DWORD handler, ICINFO *info)
Definition: msvideo_main.c:270
LRESULT WINAPI ICClose(HIC hic)
unsigned int UINT
Definition: ndis.h:50
#define KEY_READ
Definition: nt_native.h:1023
#define DWORD
Definition: nt_native.h:44
BSTR WINAPI SysAllocString(LPCOLESTR str)
Definition: oleaut.c:238
#define V_ARRAY(A)
Definition: oleauto.h:222
#define V_VT(A)
Definition: oleauto.h:211
#define V_BSTR(A)
Definition: oleauto.h:226
#define V_I4(A)
Definition: oleauto.h:247
const GUID IID_IParseDisplayName
const GUID IID_IPropertyBag
#define LOWORD(l)
Definition: pedump.c:82
long LONG
Definition: pedump.c:60
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define REFIID
Definition: guiddef.h:118
#define REFCLSID
Definition: guiddef.h:117
static FILE * out
Definition: regtests2xml.c:44
#define REG_DWORD
Definition: sdbapi.c:596
#define memset(x, y, z)
Definition: compat.h:39
HRESULT hr
Definition: shlfolder.c:183
#define TRACE(s)
Definition: solgame.cpp:4
Definition: vfw.h:280
DWORD dwVersion
Definition: axextend.idl:236
DWORD dwMerit
Definition: axextend.idl:237
const REGFILTERPINS2 * rgPins2
Definition: axextend.idl:251
ULONG cPins2
Definition: axextend.idl:250
const REGPINTYPES * lpMediaType
Definition: axextend.idl:228
Definition: http.c:7252
Definition: copy.c:22
Definition: name.c:39
Definition: import.c:81
WCHAR szPname[MAXPNAMELEN]
Definition: mmsystem.h:1126
WCHAR szPname[MAXPNAMELEN]
Definition: mmsystem.h:1060
WCHAR szPname[MAXPNAMELEN]
Definition: mmsystem.h:1039
uint32_t ULONG
Definition: typedefs.h:59
#define HIWORD(l)
Definition: typedefs.h:247
Definition: pdh_main.c:94
#define MEDIASUBTYPE_NULL
Definition: uuids.h:25
HRESULT WINAPI DECLSPEC_HOTPATCH VariantClear(VARIANTARG *pVarg)
Definition: variant.c:648
static const WCHAR defaultW[]
Definition: lex.c:42
#define ICMODE_QUERY
Definition: vfw.h:271
int ret
_In_ ULONG iType
Definition: winddi.h:3748
#define WINAPI
Definition: msvc.h:6
#define E_NOINTERFACE
Definition: winerror.h:2364
#define HRESULT_FROM_WIN32(x)
Definition: winerror.h:92
#define E_POINTER
Definition: winerror.h:2365
UINT WINAPI midiOutGetNumDevs(void)
Definition: winmm.c:806
UINT WINAPI waveOutGetNumDevs(void)
Definition: winmm.c:2137
UINT WINAPI waveOutGetDevCapsW(UINT_PTR uDeviceID, LPWAVEOUTCAPSW lpCaps, UINT uSize)
Definition: winmm.c:2173
UINT WINAPI waveInGetNumDevs(void)
Definition: winmm.c:2565
UINT WINAPI midiOutGetDevCapsW(UINT_PTR uDeviceID, LPMIDIOUTCAPSW lpCaps, UINT uSize)
Definition: winmm.c:814
UINT WINAPI waveInGetDevCapsW(UINT_PTR uDeviceID, LPWAVEINCAPSW lpCaps, UINT uSize)
Definition: winmm.c:2573
#define HKEY_CURRENT_USER
Definition: winreg.h:11
#define HKEY_CLASSES_ROOT
Definition: winreg.h:10
__wchar_t WCHAR
Definition: xmlstorage.h:180
unsigned char BYTE
Definition: xxhash.c:193