2 * ICreateDevEnum implementation for DEVENUM.dll
4 * Copyright (C) 2002 Robert Shearman
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.
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.
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
21 * - Implements ICreateDevEnum interface which creates an IEnumMoniker
23 * - Also creates the special registry keys created at run-time
26 #include "devenum_private.h"
31 #include "wine/debug.h"
35 #include "wine/fil_data.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(devenum
);
39 static HRESULT WINAPI
devenum_factory_QueryInterface(ICreateDevEnum
*iface
, REFIID riid
, void **ppv
)
41 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
46 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
47 IsEqualGUID(riid
, &IID_ICreateDevEnum
))
50 ICreateDevEnum_AddRef(iface
);
54 FIXME("- no interface IID: %s\n", debugstr_guid(riid
));
59 static ULONG WINAPI
devenum_factory_AddRef(ICreateDevEnum
*iface
)
63 return 2; /* non-heap based object */
66 static ULONG WINAPI
devenum_factory_Release(ICreateDevEnum
*iface
)
70 return 1; /* non-heap based object */
73 static HRESULT
register_codec(const GUID
*class, const WCHAR
*name
,
74 const GUID
*clsid
, const WCHAR
*friendly_name
, IPropertyBag
**ret
)
76 WCHAR guidstr
[CHARS_IN_GUID
];
77 IParseDisplayName
*parser
;
78 IPropertyBag
*propbag
;
85 hr
= CoCreateInstance(&CLSID_CDeviceMoniker
, NULL
, CLSCTX_INPROC
, &IID_IParseDisplayName
, (void **)&parser
);
89 if (!(buffer
= malloc((wcslen(L
"@device:cm:") + CHARS_IN_GUID
+ wcslen(name
) + 1) * sizeof(WCHAR
))))
91 IParseDisplayName_Release(parser
);
95 wcscpy(buffer
, L
"@device:cm:");
96 StringFromGUID2(class, buffer
+ wcslen(buffer
), CHARS_IN_GUID
);
97 wcscat(buffer
, L
"\\");
100 IParseDisplayName_ParseDisplayName(parser
, NULL
, buffer
, &eaten
, &mon
);
101 IParseDisplayName_Release(parser
);
104 IMoniker_BindToStorage(mon
, NULL
, NULL
, &IID_IPropertyBag
, (void **)&propbag
);
105 IMoniker_Release(mon
);
107 V_VT(&var
) = VT_BSTR
;
108 V_BSTR(&var
) = SysAllocString(friendly_name
);
109 hr
= IPropertyBag_Write(propbag
, L
"FriendlyName", &var
);
113 IPropertyBag_Release(propbag
);
117 V_VT(&var
) = VT_BSTR
;
118 StringFromGUID2(clsid
, guidstr
, ARRAY_SIZE(guidstr
));
119 V_BSTR(&var
) = SysAllocString(guidstr
);
120 hr
= IPropertyBag_Write(propbag
, L
"CLSID", &var
);
124 IPropertyBag_Release(propbag
);
132 static void DEVENUM_ReadPinTypes(HKEY hkeyPinKey
, REGFILTERPINS2
*rgPin
)
134 HKEY hkeyTypes
= NULL
;
135 DWORD dwMajorTypes
, i
;
136 REGPINTYPES
*lpMediaType
= NULL
;
137 DWORD dwMediaTypeSize
= 0;
139 if (RegOpenKeyExW(hkeyPinKey
, L
"Types", 0, KEY_READ
, &hkeyTypes
) != ERROR_SUCCESS
)
142 if (RegQueryInfoKeyW(hkeyTypes
, NULL
, NULL
, NULL
, &dwMajorTypes
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
)
145 RegCloseKey(hkeyTypes
);
149 for (i
= 0; i
< dwMajorTypes
; i
++)
151 HKEY hkeyMajorType
= NULL
;
152 WCHAR wszMajorTypeName
[64];
153 DWORD cName
= ARRAY_SIZE(wszMajorTypeName
);
154 DWORD dwMinorTypes
, i1
;
156 if (RegEnumKeyExW(hkeyTypes
, i
, wszMajorTypeName
, &cName
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
) continue;
158 if (RegOpenKeyExW(hkeyTypes
, wszMajorTypeName
, 0, KEY_READ
, &hkeyMajorType
) != ERROR_SUCCESS
) continue;
160 if (RegQueryInfoKeyW(hkeyMajorType
, NULL
, NULL
, NULL
, &dwMinorTypes
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
)
163 RegCloseKey(hkeyMajorType
);
167 for (i1
= 0; i1
< dwMinorTypes
; i1
++)
169 WCHAR wszMinorTypeName
[64];
170 CLSID
*clsMajorType
= NULL
, *clsMinorType
= NULL
;
173 cName
= ARRAY_SIZE(wszMinorTypeName
);
174 if (RegEnumKeyExW(hkeyMajorType
, i1
, wszMinorTypeName
, &cName
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
) continue;
176 clsMinorType
= CoTaskMemAlloc(sizeof(CLSID
));
177 if (!clsMinorType
) continue;
179 clsMajorType
= CoTaskMemAlloc(sizeof(CLSID
));
180 if (!clsMajorType
) goto error_cleanup_types
;
182 hr
= CLSIDFromString(wszMinorTypeName
, clsMinorType
);
183 if (FAILED(hr
)) goto error_cleanup_types
;
185 hr
= CLSIDFromString(wszMajorTypeName
, clsMajorType
);
186 if (FAILED(hr
)) goto error_cleanup_types
;
188 if (rgPin
->nMediaTypes
== dwMediaTypeSize
)
190 DWORD dwNewSize
= dwMediaTypeSize
+ (dwMediaTypeSize
< 2 ? 1 : dwMediaTypeSize
/ 2);
191 REGPINTYPES
*lpNewMediaType
;
193 lpNewMediaType
= CoTaskMemRealloc(lpMediaType
, sizeof(REGPINTYPES
) * dwNewSize
);
194 if (!lpNewMediaType
) goto error_cleanup_types
;
196 lpMediaType
= lpNewMediaType
;
197 dwMediaTypeSize
= dwNewSize
;
200 lpMediaType
[rgPin
->nMediaTypes
].clsMajorType
= clsMajorType
;
201 lpMediaType
[rgPin
->nMediaTypes
].clsMinorType
= clsMinorType
;
202 rgPin
->nMediaTypes
++;
207 CoTaskMemFree(clsMajorType
);
208 CoTaskMemFree(clsMinorType
);
211 RegCloseKey(hkeyMajorType
);
214 RegCloseKey(hkeyTypes
);
216 if (lpMediaType
&& !rgPin
->nMediaTypes
)
218 CoTaskMemFree(lpMediaType
);
222 rgPin
->lpMediaType
= lpMediaType
;
225 static void DEVENUM_ReadPins(HKEY hkeyFilterClass
, REGFILTER2
*rgf2
)
227 HKEY hkeyPins
= NULL
;
228 DWORD dwPinsSubkeys
, i
;
229 REGFILTERPINS2
*rgPins
= NULL
;
233 rgf2
->rgPins2
= NULL
;
235 if (RegOpenKeyExW(hkeyFilterClass
, L
"Pins", 0, KEY_READ
, &hkeyPins
) != ERROR_SUCCESS
)
238 if (RegQueryInfoKeyW(hkeyPins
, NULL
, NULL
, NULL
, &dwPinsSubkeys
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
)
241 RegCloseKey(hkeyPins
);
247 rgPins
= CoTaskMemAlloc(sizeof(REGFILTERPINS2
) * dwPinsSubkeys
);
250 RegCloseKey(hkeyPins
);
255 for (i
= 0; i
< dwPinsSubkeys
; i
++)
257 HKEY hkeyPinKey
= NULL
;
258 WCHAR wszPinName
[MAX_PATH
];
259 DWORD cName
= ARRAY_SIZE(wszPinName
);
260 REGFILTERPINS2
*rgPin
= &rgPins
[rgf2
->cPins2
];
261 DWORD value
, size
, Type
;
264 memset(rgPin
, 0, sizeof(*rgPin
));
266 if (RegEnumKeyExW(hkeyPins
, i
, wszPinName
, &cName
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
) continue;
268 if (RegOpenKeyExW(hkeyPins
, wszPinName
, 0, KEY_READ
, &hkeyPinKey
) != ERROR_SUCCESS
) continue;
270 size
= sizeof(DWORD
);
271 lRet
= RegQueryValueExW(hkeyPinKey
, L
"AllowedMany", NULL
, &Type
, (BYTE
*)&value
, &size
);
272 if (lRet
!= ERROR_SUCCESS
|| Type
!= REG_DWORD
)
275 rgPin
->dwFlags
|= REG_PINFLAG_B_MANY
;
277 size
= sizeof(DWORD
);
278 lRet
= RegQueryValueExW(hkeyPinKey
, L
"AllowedZero", NULL
, &Type
, (BYTE
*)&value
, &size
);
279 if (lRet
!= ERROR_SUCCESS
|| Type
!= REG_DWORD
)
282 rgPin
->dwFlags
|= REG_PINFLAG_B_ZERO
;
284 size
= sizeof(DWORD
);
285 lRet
= RegQueryValueExW(hkeyPinKey
, L
"Direction", NULL
, &Type
, (BYTE
*)&value
, &size
);
286 if (lRet
!= ERROR_SUCCESS
|| Type
!= REG_DWORD
)
289 rgPin
->dwFlags
|= REG_PINFLAG_B_OUTPUT
;
292 size
= sizeof(DWORD
);
293 lRet
= RegQueryValueExW(hkeyPinKey
, L
"IsRendered", NULL
, &Type
, (BYTE
*)&value
, &size
);
294 if (lRet
!= ERROR_SUCCESS
|| Type
!= REG_DWORD
)
297 rgPin
->dwFlags
|= REG_PINFLAG_B_RENDERER
;
299 DEVENUM_ReadPinTypes(hkeyPinKey
, rgPin
);
306 RegCloseKey(hkeyPinKey
);
309 RegCloseKey(hkeyPins
);
311 if (rgPins
&& !rgf2
->cPins2
)
313 CoTaskMemFree(rgPins
);
317 rgf2
->rgPins2
= rgPins
;
320 static void free_regfilter2(REGFILTER2
*rgf
)
326 for (iPin
= 0; iPin
< rgf
->cPins2
; iPin
++)
328 if (rgf
->rgPins2
[iPin
].lpMediaType
)
332 for (iType
= 0; iType
< rgf
->rgPins2
[iPin
].nMediaTypes
; iType
++)
334 CoTaskMemFree((void *)rgf
->rgPins2
[iPin
].lpMediaType
[iType
].clsMajorType
);
335 CoTaskMemFree((void *)rgf
->rgPins2
[iPin
].lpMediaType
[iType
].clsMinorType
);
338 CoTaskMemFree((void *)rgf
->rgPins2
[iPin
].lpMediaType
);
342 CoTaskMemFree((void *)rgf
->rgPins2
);
346 HRESULT
create_filter_data(VARIANT
*var
, REGFILTER2
*rgf
)
348 IAMFilterData
*fildata
;
353 hr
= CoCreateInstance(&CLSID_FilterMapper2
, NULL
, CLSCTX_INPROC
, &IID_IAMFilterData
, (void **)&fildata
);
357 hr
= IAMFilterData_CreateFilterData(fildata
, rgf
, &data
, &size
);
358 IAMFilterData_Release(fildata
);
362 V_VT(var
) = VT_ARRAY
| VT_UI1
;
363 if (!(V_ARRAY(var
) = SafeArrayCreateVector(VT_UI1
, 1, size
)))
367 return E_OUTOFMEMORY
;
370 memcpy(V_ARRAY(var
)->pvData
, data
, size
);
375 static void write_filter_data(IPropertyBag
*prop_bag
, REGFILTER2
*rgf
)
379 if (SUCCEEDED(create_filter_data(&var
, rgf
)))
381 IPropertyBag_Write(prop_bag
, L
"FilterData", &var
);
386 static void register_legacy_filters(void)
388 HKEY hkeyFilter
= NULL
;
389 DWORD dwFilterSubkeys
, i
;
393 lRet
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, L
"Filter", 0, KEY_READ
, &hkeyFilter
);
394 hr
= HRESULT_FROM_WIN32(lRet
);
398 lRet
= RegQueryInfoKeyW(hkeyFilter
, NULL
, NULL
, NULL
, &dwFilterSubkeys
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
399 hr
= HRESULT_FROM_WIN32(lRet
);
404 for (i
= 0; i
< dwFilterSubkeys
; i
++)
406 WCHAR wszFilterSubkeyName
[64];
407 DWORD cName
= ARRAY_SIZE(wszFilterSubkeyName
);
408 IPropertyBag
*prop_bag
= NULL
;
409 WCHAR wszRegKey
[MAX_PATH
];
410 HKEY classkey
= NULL
;
415 if (RegEnumKeyExW(hkeyFilter
, i
, wszFilterSubkeyName
, &cName
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
) continue;
417 TRACE("Registering %s\n", debugstr_w(wszFilterSubkeyName
));
419 hr
= CLSIDFromString(wszFilterSubkeyName
, &clsid
);
423 swprintf(wszRegKey
, ARRAY_SIZE(wszRegKey
), L
"CLSID\\%s", wszFilterSubkeyName
);
424 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, wszRegKey
, 0, KEY_READ
, &classkey
) != ERROR_SUCCESS
)
428 if (!RegQueryValueExW(classkey
, NULL
, NULL
, &Type
, NULL
, &len
))
430 WCHAR
*friendlyname
= malloc(len
);
433 RegCloseKey(classkey
);
436 RegQueryValueExW(classkey
, NULL
, NULL
, &Type
, (BYTE
*)friendlyname
, &len
);
438 hr
= register_codec(&CLSID_LegacyAmFilterCategory
, wszFilterSubkeyName
,
439 &clsid
, friendlyname
, &prop_bag
);
444 hr
= register_codec(&CLSID_LegacyAmFilterCategory
, wszFilterSubkeyName
,
445 &clsid
, wszFilterSubkeyName
, &prop_bag
);
448 RegCloseKey(classkey
);
452 /* write filter data */
453 rgf2
.dwMerit
= MERIT_NORMAL
;
455 len
= sizeof(rgf2
.dwMerit
);
456 RegQueryValueExW(classkey
, L
"Merit", NULL
, &Type
, (BYTE
*)&rgf2
.dwMerit
, &len
);
458 DEVENUM_ReadPins(classkey
, &rgf2
);
460 write_filter_data(prop_bag
, &rgf2
);
462 IPropertyBag_Release(prop_bag
);
463 RegCloseKey(classkey
);
464 free_regfilter2(&rgf2
);
468 if (hkeyFilter
) RegCloseKey(hkeyFilter
);
471 static BOOL CALLBACK
register_dsound_devices(GUID
*guid
, const WCHAR
*desc
, const WCHAR
*module
, void *context
)
473 static const WCHAR defaultW
[] = L
"Default DirectSound Device";
474 IPropertyBag
*prop_bag
= NULL
;
475 REGFILTERPINS2 rgpins
= {0};
476 REGPINTYPES rgtypes
= {0};
477 REGFILTER2 rgf
= {0};
478 WCHAR clsid
[CHARS_IN_GUID
];
484 WCHAR
*name
= malloc(sizeof(defaultW
) + wcslen(desc
) * sizeof(WCHAR
));
487 wcscpy(name
, L
"DirectSound: ");
490 hr
= register_codec(&CLSID_AudioRendererCategory
, name
,
491 &CLSID_DSoundRender
, name
, &prop_bag
);
495 hr
= register_codec(&CLSID_AudioRendererCategory
, defaultW
,
496 &CLSID_DSoundRender
, defaultW
, &prop_bag
);
500 /* write filter data */
502 rgf
.dwMerit
= guid
? MERIT_DO_NOT_USE
: MERIT_PREFERRED
;
504 rgf
.rgPins2
= &rgpins
;
505 rgpins
.dwFlags
= REG_PINFLAG_B_RENDERER
;
506 /* FIXME: native registers many more formats */
507 rgpins
.nMediaTypes
= 1;
508 rgpins
.lpMediaType
= &rgtypes
;
509 rgtypes
.clsMajorType
= &MEDIATYPE_Audio
;
510 rgtypes
.clsMinorType
= &MEDIASUBTYPE_PCM
;
512 write_filter_data(prop_bag
, &rgf
);
514 /* write DSound guid */
515 V_VT(&var
) = VT_BSTR
;
516 StringFromGUID2(guid
? guid
: &GUID_NULL
, clsid
, CHARS_IN_GUID
);
517 if ((V_BSTR(&var
) = SysAllocString(clsid
)))
518 hr
= IPropertyBag_Write(prop_bag
, L
"DSGuid", &var
);
521 IPropertyBag_Release(prop_bag
);
525 static void register_waveout_devices(void)
527 IPropertyBag
*prop_bag
= NULL
;
528 REGFILTERPINS2 rgpins
= {0};
529 REGPINTYPES rgtypes
= {0};
530 REGFILTER2 rgf
= {0};
537 count
= waveOutGetNumDevs();
539 for (i
= -1; i
< count
; i
++)
541 waveOutGetDevCapsW(i
, &caps
, sizeof(caps
));
543 name
= (i
== -1) ? L
"Default WaveOut Device" : caps
.szPname
;
545 hr
= register_codec(&CLSID_AudioRendererCategory
, name
,
546 &CLSID_AudioRender
, name
, &prop_bag
);
550 /* write filter data */
552 rgf
.dwMerit
= MERIT_DO_NOT_USE
;
554 rgf
.rgPins2
= &rgpins
;
555 rgpins
.dwFlags
= REG_PINFLAG_B_RENDERER
;
556 rgpins
.nMediaTypes
= 1;
557 rgpins
.lpMediaType
= &rgtypes
;
558 rgtypes
.clsMajorType
= &MEDIATYPE_Audio
;
559 rgtypes
.clsMinorType
= &MEDIASUBTYPE_NULL
;
561 write_filter_data(prop_bag
, &rgf
);
563 /* write WaveOutId */
566 IPropertyBag_Write(prop_bag
, L
"WaveOutId", &var
);
569 if (prop_bag
) IPropertyBag_Release(prop_bag
);
573 static void register_wavein_devices(void)
575 IPropertyBag
*prop_bag
= NULL
;
576 REGFILTER2 rgf
= {0};
582 count
= waveInGetNumDevs();
584 for (i
= 0; i
< count
; i
++)
586 waveInGetDevCapsW(i
, &caps
, sizeof(caps
));
588 hr
= register_codec(&CLSID_AudioInputDeviceCategory
, caps
.szPname
,
589 &CLSID_AudioRecord
, caps
.szPname
, &prop_bag
);
593 /* write filter data */
595 rgf
.dwMerit
= MERIT_DO_NOT_USE
;
597 write_filter_data(prop_bag
, &rgf
);
602 IPropertyBag_Write(prop_bag
, L
"WaveInId", &var
);
605 IPropertyBag_Release(prop_bag
);
609 static void register_midiout_devices(void)
611 IPropertyBag
*prop_bag
= NULL
;
612 REGFILTERPINS2 rgpins
= {0};
613 REGPINTYPES rgtypes
= {0};
614 REGFILTER2 rgf
= {0};
621 count
= midiOutGetNumDevs();
623 for (i
= -1; i
< count
; i
++)
625 midiOutGetDevCapsW(i
, &caps
, sizeof(caps
));
627 name
= (i
== -1) ? L
"Default MidiOut Device" : caps
.szPname
;
629 hr
= register_codec(&CLSID_MidiRendererCategory
, name
,
630 &CLSID_AVIMIDIRender
, name
, &prop_bag
);
634 /* write filter data */
636 rgf
.dwMerit
= (i
== -1) ? MERIT_PREFERRED
: MERIT_DO_NOT_USE
;
638 rgf
.rgPins2
= &rgpins
;
639 rgpins
.dwFlags
= REG_PINFLAG_B_RENDERER
;
640 rgpins
.nMediaTypes
= 1;
641 rgpins
.lpMediaType
= &rgtypes
;
642 rgtypes
.clsMajorType
= &MEDIATYPE_Midi
;
643 rgtypes
.clsMinorType
= &MEDIASUBTYPE_NULL
;
645 write_filter_data(prop_bag
, &rgf
);
647 /* write MidiOutId */
650 IPropertyBag_Write(prop_bag
, L
"MidiOutId", &var
);
653 IPropertyBag_Release(prop_bag
);
657 static void register_vfw_codecs(void)
659 REGFILTERPINS2 rgpins
[2] = {};
660 IPropertyBag
*prop_bag
= NULL
;
661 REGPINTYPES rgtypes
[2];
670 while (ICInfo(ICTYPE_VIDEO
, i
++, &info
))
672 WCHAR name
[5] = {LOBYTE(LOWORD(info
.fccHandler
)), HIBYTE(LOWORD(info
.fccHandler
)),
673 LOBYTE(HIWORD(info
.fccHandler
)), HIBYTE(HIWORD(info
.fccHandler
))};
675 hic
= ICOpen(ICTYPE_VIDEO
, info
.fccHandler
, ICMODE_QUERY
);
676 ICGetInfo(hic
, &info
, sizeof(info
));
679 hr
= register_codec(&CLSID_VideoCompressorCategory
, name
,
680 &CLSID_AVICo
, info
.szDescription
, &prop_bag
);
684 /* write filter data */
686 rgf
.dwMerit
= MERIT_DO_NOT_USE
;
688 rgf
.rgPins2
= rgpins
;
689 rgpins
[0].dwFlags
= 0;
690 rgpins
[0].nMediaTypes
= 1;
691 rgpins
[0].lpMediaType
= &rgtypes
[0];
692 rgtypes
[0].clsMajorType
= &MEDIATYPE_Video
;
693 typeguid
= MEDIASUBTYPE_PCM
;
694 typeguid
.Data1
= info
.fccHandler
;
695 rgtypes
[0].clsMinorType
= &typeguid
;
696 rgpins
[1].dwFlags
= REG_PINFLAG_B_OUTPUT
;
697 rgpins
[1].nMediaTypes
= 1;
698 rgpins
[1].lpMediaType
= &rgtypes
[1];
699 rgtypes
[1].clsMajorType
= &MEDIATYPE_Video
;
700 rgtypes
[1].clsMinorType
= &GUID_NULL
;
702 write_filter_data(prop_bag
, &rgf
);
705 V_VT(&var
) = VT_BSTR
;
706 V_BSTR(&var
) = SysAllocString(name
);
707 IPropertyBag_Write(prop_bag
, L
"FccHandler", &var
);
710 IPropertyBag_Release(prop_bag
);
714 static void register_avicap_devices(void)
716 WCHAR friendlyname
[32], version
[32];
717 IPropertyBag
*prop_bag
= NULL
;
718 REGFILTERPINS2 rgpins
= {0};
726 for (i
= 0; i
< 10; ++i
)
728 if (!capGetDriverDescriptionW(i
, friendlyname
, ARRAY_SIZE(friendlyname
),
729 version
, ARRAY_SIZE(version
)))
732 swprintf(name
, ARRAY_SIZE(name
), L
"video%d", i
);
734 hr
= register_codec(&CLSID_VideoInputDeviceCategory
, name
,
735 &CLSID_VfwCapture
, friendlyname
, &prop_bag
);
740 rgf
.dwMerit
= MERIT_DO_NOT_USE
;
742 rgf
.rgPins2
= &rgpins
;
744 rgpins
.nMediaTypes
= 1;
745 rgpins
.lpMediaType
= &rgtypes
;
746 rgtypes
.clsMajorType
= &MEDIATYPE_Video
;
747 rgtypes
.clsMinorType
= &MEDIASUBTYPE_None
;
749 write_filter_data(prop_bag
, &rgf
);
754 IPropertyBag_Write(prop_bag
, L
"VFWIndex", &var
);
757 IPropertyBag_Release(prop_bag
);
761 static HRESULT WINAPI
devenum_factory_CreateClassEnumerator(ICreateDevEnum
*iface
,
762 REFCLSID
class, IEnumMoniker
**out
, DWORD flags
)
764 WCHAR guidstr
[CHARS_IN_GUID
];
768 TRACE("iface %p, class %s, out %p, flags %#lx.\n", iface
, debugstr_guid(class), out
, flags
);
775 if (!RegOpenKeyW(HKEY_CURRENT_USER
, L
"Software\\Microsoft\\ActiveMovie\\devenum", &key
))
777 StringFromGUID2(class, guidstr
, ARRAY_SIZE(guidstr
));
778 RegDeleteTreeW(key
, guidstr
);
781 if (IsEqualGUID(class, &CLSID_LegacyAmFilterCategory
))
782 register_legacy_filters();
783 else if (IsEqualGUID(class, &CLSID_AudioRendererCategory
))
785 hr
= DirectSoundEnumerateW(®ister_dsound_devices
, NULL
);
786 if (FAILED(hr
)) return hr
;
787 register_waveout_devices();
788 register_midiout_devices();
790 else if (IsEqualGUID(class, &CLSID_AudioInputDeviceCategory
))
791 register_wavein_devices();
792 else if (IsEqualGUID(class, &CLSID_VideoCompressorCategory
))
793 register_vfw_codecs();
794 else if (IsEqualGUID(class, &CLSID_VideoInputDeviceCategory
))
795 register_avicap_devices();
797 if (SUCCEEDED(hr
= enum_moniker_create(class, out
)))
800 hr
= IEnumMoniker_Next(*out
, 1, &mon
, NULL
);
803 IMoniker_Release(mon
);
804 IEnumMoniker_Reset(*out
);
808 IEnumMoniker_Release(*out
);
816 /**********************************************************************
817 * ICreateDevEnum_Vtbl
819 static const ICreateDevEnumVtbl ICreateDevEnum_Vtbl
=
821 devenum_factory_QueryInterface
,
822 devenum_factory_AddRef
,
823 devenum_factory_Release
,
824 devenum_factory_CreateClassEnumerator
,
827 /**********************************************************************
828 * static CreateDevEnum instance
830 ICreateDevEnum devenum_factory
= { &ICreateDevEnum_Vtbl
};