Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/devenum/createdevenum.c | 307 ++++++++++++++----------------------------- 1 file changed, 98 insertions(+), 209 deletions(-)
diff --git a/dlls/devenum/createdevenum.c b/dlls/devenum/createdevenum.c index 8fbf323..ad1022e 100644 --- a/dlls/devenum/createdevenum.c +++ b/dlls/devenum/createdevenum.c @@ -104,11 +104,16 @@ static ULONG WINAPI DEVENUM_ICreateDevEnum_Release(ICreateDevEnum * iface) return 1; /* non-heap based object */ }
-static HRESULT register_codec(const CLSID *class, const WCHAR *name, IMoniker **ret) +static HRESULT register_codec(const GUID *class, const WCHAR *name, + const GUID *clsid, const WCHAR *friendly_name, IPropertyBag **ret) { static const WCHAR deviceW[] = {'@','d','e','v','i','c','e',':','c','m',':',0}; + WCHAR guidstr[CHARS_IN_GUID]; IParseDisplayName *parser; + IPropertyBag *propbag; + IMoniker *mon; WCHAR *buffer; + VARIANT var; ULONG eaten; HRESULT hr;
@@ -128,10 +133,36 @@ static HRESULT register_codec(const CLSID *class, const WCHAR *name, IMoniker ** strcatW(buffer, backslashW); strcatW(buffer, name);
- hr = IParseDisplayName_ParseDisplayName(parser, NULL, buffer, &eaten, ret); + IParseDisplayName_ParseDisplayName(parser, NULL, buffer, &eaten, &mon); IParseDisplayName_Release(parser); heap_free(buffer); - return hr; + + IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&propbag); + IMoniker_Release(mon); + + V_VT(&var) = VT_BSTR; + V_BSTR(&var) = SysAllocString(friendly_name); + hr = IPropertyBag_Write(propbag, wszFriendlyName, &var); + VariantClear(&var); + if (FAILED(hr)) + { + IPropertyBag_Release(propbag); + return hr; + } + + V_VT(&var) = VT_BSTR; + StringFromGUID2(clsid, guidstr, ARRAY_SIZE(guidstr)); + V_BSTR(&var) = SysAllocString(guidstr); + hr = IPropertyBag_Write(propbag, clsidW, &var); + VariantClear(&var); + if (FAILED(hr)) + { + IPropertyBag_Release(propbag); + return hr; + } + + *ret = propbag; + return S_OK; }
static void DEVENUM_ReadPinTypes(HKEY hkeyPinKey, REGFILTERPINS2 *rgPin) @@ -412,15 +443,18 @@ static void register_legacy_filters(void) IPropertyBag *prop_bag = NULL; WCHAR wszRegKey[MAX_PATH]; HKEY classkey = NULL; - IMoniker *mon = NULL; - VARIANT var = {}; REGFILTER2 rgf2; DWORD Type, len; + GUID clsid;
if (RegEnumKeyExW(hkeyFilter, i, wszFilterSubkeyName, &cName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) continue;
TRACE("Registering %s\n", debugstr_w(wszFilterSubkeyName));
+ hr = CLSIDFromString(wszFilterSubkeyName, &clsid); + if (FAILED(hr)) + continue; + strcpyW(wszRegKey, clsidW); strcatW(wszRegKey, backslashW); strcatW(wszRegKey, wszFilterSubkeyName); @@ -428,40 +462,30 @@ static void register_legacy_filters(void) if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszRegKey, 0, KEY_READ, &classkey) != ERROR_SUCCESS) continue;
- hr = register_codec(&CLSID_LegacyAmFilterCategory, wszFilterSubkeyName, &mon); - if (FAILED(hr)) goto cleanup; - - hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); - if (FAILED(hr)) goto cleanup; - - /* write friendly name */ len = 0; - V_VT(&var) = VT_BSTR; if (!RegQueryValueExW(classkey, NULL, NULL, &Type, NULL, &len)) { WCHAR *friendlyname = heap_alloc(len); if (!friendlyname) - goto cleanup; + { + RegCloseKey(classkey); + continue; + } RegQueryValueExW(classkey, NULL, NULL, &Type, (BYTE *)friendlyname, &len); - V_BSTR(&var) = SysAllocStringLen(friendlyname, len/sizeof(WCHAR)); + + hr = register_codec(&CLSID_LegacyAmFilterCategory, wszFilterSubkeyName, + &clsid, friendlyname, &prop_bag); + heap_free(friendlyname); } else - V_BSTR(&var) = SysAllocString(wszFilterSubkeyName); - - if (!V_BSTR(&var)) - goto cleanup; - hr = IPropertyBag_Write(prop_bag, wszFriendlyName, &var); - if (FAILED(hr)) goto cleanup; - VariantClear(&var); - - /* write clsid */ - V_VT(&var) = VT_BSTR; - if (!(V_BSTR(&var) = SysAllocString(wszFilterSubkeyName))) - goto cleanup; - hr = IPropertyBag_Write(prop_bag, clsidW, &var); - if (FAILED(hr)) goto cleanup; - VariantClear(&var); + hr = register_codec(&CLSID_LegacyAmFilterCategory, wszFilterSubkeyName, + &clsid, wszFilterSubkeyName, &prop_bag); + if (FAILED(hr)) + { + RegCloseKey(classkey); + continue; + }
/* write filter data */ rgf2.dwMerit = MERIT_NORMAL; @@ -473,11 +497,8 @@ static void register_legacy_filters(void)
write_filter_data(prop_bag, &rgf2);
-cleanup: - if (prop_bag) IPropertyBag_Release(prop_bag); - if (mon) IMoniker_Release(mon); + IPropertyBag_Release(prop_bag); RegCloseKey(classkey); - VariantClear(&var); free_regfilter2(&rgf2); } } @@ -495,50 +516,30 @@ static BOOL CALLBACK register_dsound_devices(GUID *guid, const WCHAR *desc, cons REGPINTYPES rgtypes = {0}; REGFILTER2 rgf = {0}; WCHAR clsid[CHARS_IN_GUID]; - IMoniker *mon = NULL; VARIANT var; HRESULT hr;
hr = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory); - if (FAILED(hr)) goto cleanup; + if (FAILED(hr)) + return FALSE;
- V_VT(&var) = VT_BSTR; if (guid) { WCHAR *name = heap_alloc(sizeof(defaultW) + strlenW(desc) * sizeof(WCHAR)); if (!name) - goto cleanup; + return FALSE; strcpyW(name, directsoundW); strcatW(name, desc);
- V_BSTR(&var) = SysAllocString(name); + hr = register_codec(&CLSID_AudioRendererCategory, name, + &CLSID_DSoundRender, name, &prop_bag); heap_free(name); } else - V_BSTR(&var) = SysAllocString(defaultW); - - if (!V_BSTR(&var)) - goto cleanup; - - hr = register_codec(&CLSID_AudioRendererCategory, V_BSTR(&var), &mon); - if (FAILED(hr)) goto cleanup; - - hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); - if (FAILED(hr)) goto cleanup; - - /* write friendly name */ - hr = IPropertyBag_Write(prop_bag, wszFriendlyName, &var); - if (FAILED(hr)) goto cleanup; - VariantClear(&var); - - /* write clsid */ - V_VT(&var) = VT_BSTR; - StringFromGUID2(&CLSID_DSoundRender, clsid, CHARS_IN_GUID); - if (!(V_BSTR(&var) = SysAllocString(clsid))) - goto cleanup; - hr = IPropertyBag_Write(prop_bag, clsidW, &var); - if (FAILED(hr)) goto cleanup; - VariantClear(&var); + hr = register_codec(&CLSID_AudioRendererCategory, defaultW, + &CLSID_DSoundRender, defaultW, &prop_bag); + if (FAILED(hr)) + return FALSE;
/* write filter data */ rgf.dwVersion = 2; @@ -557,16 +558,11 @@ static BOOL CALLBACK register_dsound_devices(GUID *guid, const WCHAR *desc, cons /* write DSound guid */ V_VT(&var) = VT_BSTR; StringFromGUID2(guid ? guid : &GUID_NULL, clsid, CHARS_IN_GUID); - if (!(V_BSTR(&var) = SysAllocString(clsid))) - goto cleanup; - hr = IPropertyBag_Write(prop_bag, dsguidW, &var); - if (FAILED(hr)) goto cleanup; + if ((V_BSTR(&var) = SysAllocString(clsid))) + hr = IPropertyBag_Write(prop_bag, dsguidW, &var);
-cleanup: VariantClear(&var); - if (prop_bag) IPropertyBag_Release(prop_bag); - if (mon) IMoniker_Release(mon); - + IPropertyBag_Release(prop_bag); return TRUE; }
@@ -578,9 +574,8 @@ static void register_waveout_devices(void) REGFILTERPINS2 rgpins = {0}; REGPINTYPES rgtypes = {0}; REGFILTER2 rgf = {0}; - WCHAR clsid[CHARS_IN_GUID]; - IMoniker *mon = NULL; WAVEOUTCAPSW caps; + const WCHAR *name; int i, count; VARIANT var; HRESULT hr; @@ -594,34 +589,12 @@ static void register_waveout_devices(void) { waveOutGetDevCapsW(i, &caps, sizeof(caps));
- V_VT(&var) = VT_BSTR; + name = (i == -1) ? defaultW : caps.szPname;
- if (i == -1) /* WAVE_MAPPER */ - V_BSTR(&var) = SysAllocString(defaultW); - else - V_BSTR(&var) = SysAllocString(caps.szPname); - if (!(V_BSTR(&var))) - goto cleanup; - - hr = register_codec(&CLSID_AudioRendererCategory, V_BSTR(&var), &mon); - if (FAILED(hr)) goto cleanup; - - hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); - if (FAILED(hr)) goto cleanup; - - /* write friendly name */ - hr = IPropertyBag_Write(prop_bag, wszFriendlyName, &var); - if (FAILED(hr)) goto cleanup; - VariantClear(&var); - - /* write clsid */ - V_VT(&var) = VT_BSTR; - StringFromGUID2(&CLSID_AudioRender, clsid, CHARS_IN_GUID); - if (!(V_BSTR(&var) = SysAllocString(clsid))) - goto cleanup; - hr = IPropertyBag_Write(prop_bag, clsidW, &var); - if (FAILED(hr)) goto cleanup; - VariantClear(&var); + hr = register_codec(&CLSID_AudioRendererCategory, name, + &CLSID_AudioRender, name, &prop_bag); + if (FAILED(hr)) + continue;
/* write filter data */ rgf.dwVersion = 2; @@ -639,13 +612,10 @@ static void register_waveout_devices(void) /* write WaveOutId */ V_VT(&var) = VT_I4; V_I4(&var) = i; - hr = IPropertyBag_Write(prop_bag, waveoutidW, &var); - if (FAILED(hr)) goto cleanup; + IPropertyBag_Write(prop_bag, waveoutidW, &var);
-cleanup: VariantClear(&var); if (prop_bag) IPropertyBag_Release(prop_bag); - if (mon) IMoniker_Release(mon); } }
@@ -654,8 +624,6 @@ static void register_wavein_devices(void) static const WCHAR waveinidW[] = {'W','a','v','e','I','n','I','d',0}; IPropertyBag *prop_bag = NULL; REGFILTER2 rgf = {0}; - WCHAR clsid[CHARS_IN_GUID]; - IMoniker *mon = NULL; WAVEINCAPSW caps; int i, count; VARIANT var; @@ -670,31 +638,10 @@ static void register_wavein_devices(void) { waveInGetDevCapsW(i, &caps, sizeof(caps));
- V_VT(&var) = VT_BSTR; - - V_BSTR(&var) = SysAllocString(caps.szPname); - if (!(V_BSTR(&var))) - goto cleanup; - - hr = register_codec(&CLSID_AudioInputDeviceCategory, V_BSTR(&var), &mon); - if (FAILED(hr)) goto cleanup; - - hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); - if (FAILED(hr)) goto cleanup; - - /* write friendly name */ - hr = IPropertyBag_Write(prop_bag, wszFriendlyName, &var); - if (FAILED(hr)) goto cleanup; - VariantClear(&var); - - /* write clsid */ - V_VT(&var) = VT_BSTR; - StringFromGUID2(&CLSID_AudioRecord, clsid, CHARS_IN_GUID); - if (!(V_BSTR(&var) = SysAllocString(clsid))) - goto cleanup; - hr = IPropertyBag_Write(prop_bag, clsidW, &var); - if (FAILED(hr)) goto cleanup; - VariantClear(&var); + hr = register_codec(&CLSID_AudioInputDeviceCategory, caps.szPname, + &CLSID_AudioRecord, caps.szPname, &prop_bag); + if (FAILED(hr)) + continue;
/* write filter data */ rgf.dwVersion = 2; @@ -705,13 +652,10 @@ static void register_wavein_devices(void) /* write WaveInId */ V_VT(&var) = VT_I4; V_I4(&var) = i; - hr = IPropertyBag_Write(prop_bag, waveinidW, &var); - if (FAILED(hr)) goto cleanup; + IPropertyBag_Write(prop_bag, waveinidW, &var);
-cleanup: VariantClear(&var); - if (prop_bag) IPropertyBag_Release(prop_bag); - if (mon) IMoniker_Release(mon); + IPropertyBag_Release(prop_bag); } }
@@ -723,9 +667,8 @@ static void register_midiout_devices(void) REGFILTERPINS2 rgpins = {0}; REGPINTYPES rgtypes = {0}; REGFILTER2 rgf = {0}; - WCHAR clsid[CHARS_IN_GUID]; - IMoniker *mon = NULL; MIDIOUTCAPSW caps; + const WCHAR *name; int i, count; VARIANT var; HRESULT hr; @@ -739,34 +682,12 @@ static void register_midiout_devices(void) { midiOutGetDevCapsW(i, &caps, sizeof(caps));
- V_VT(&var) = VT_BSTR; + name = (i == -1) ? defaultW : caps.szPname;
- if (i == -1) /* MIDI_MAPPER */ - V_BSTR(&var) = SysAllocString(defaultW); - else - V_BSTR(&var) = SysAllocString(caps.szPname); - if (!(V_BSTR(&var))) - goto cleanup; - - hr = register_codec(&CLSID_MidiRendererCategory, V_BSTR(&var), &mon); - if (FAILED(hr)) goto cleanup; - - hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); - if (FAILED(hr)) goto cleanup; - - /* write friendly name */ - hr = IPropertyBag_Write(prop_bag, wszFriendlyName, &var); - if (FAILED(hr)) goto cleanup; - VariantClear(&var); - - /* write clsid */ - V_VT(&var) = VT_BSTR; - StringFromGUID2(&CLSID_AVIMIDIRender, clsid, CHARS_IN_GUID); - if (!(V_BSTR(&var) = SysAllocString(clsid))) - goto cleanup; - hr = IPropertyBag_Write(prop_bag, clsidW, &var); - if (FAILED(hr)) goto cleanup; - VariantClear(&var); + hr = register_codec(&CLSID_MidiRendererCategory, name, + &CLSID_AVIMIDIRender, name, &prop_bag); + if (FAILED(hr)) + continue;
/* write filter data */ rgf.dwVersion = 2; @@ -784,13 +705,10 @@ static void register_midiout_devices(void) /* write MidiOutId */ V_VT(&var) = VT_I4; V_I4(&var) = i; - hr = IPropertyBag_Write(prop_bag, midioutidW, &var); - if (FAILED(hr)) goto cleanup; + IPropertyBag_Write(prop_bag, midioutidW, &var);
-cleanup: VariantClear(&var); - if (prop_bag) IPropertyBag_Release(prop_bag); - if (mon) IMoniker_Release(mon); + IPropertyBag_Release(prop_bag); } }
@@ -801,8 +719,6 @@ static void register_vfw_codecs(void) IPropertyBag *prop_bag = NULL; REGPINTYPES rgtypes[2]; REGFILTER2 rgf; - WCHAR clsid[CHARS_IN_GUID]; - IMoniker *mon = NULL; GUID typeguid; ICINFO info; VARIANT var; @@ -822,40 +738,10 @@ static void register_vfw_codecs(void) ICGetInfo(hic, &info, sizeof(info)); ICClose(hic);
- V_VT(&var) = VT_BSTR; - - V_BSTR(&var) = SysAllocString(name); - if (!(V_BSTR(&var))) - goto cleanup; - - hr = register_codec(&CLSID_VideoCompressorCategory, V_BSTR(&var), &mon); - if (FAILED(hr)) goto cleanup; - - hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); - if (FAILED(hr)) goto cleanup; - - /* write WaveInId */ - hr = IPropertyBag_Write(prop_bag, fcchandlerW, &var); - if (FAILED(hr)) goto cleanup; - VariantClear(&var); - - /* write friendly name */ - V_VT(&var) = VT_BSTR; - if (!(V_BSTR(&var) = SysAllocString(info.szDescription))) - goto cleanup; - - hr = IPropertyBag_Write(prop_bag, wszFriendlyName, &var); - if (FAILED(hr)) goto cleanup; - VariantClear(&var); - - /* write clsid */ - V_VT(&var) = VT_BSTR; - StringFromGUID2(&CLSID_AVICo, clsid, CHARS_IN_GUID); - if (!(V_BSTR(&var) = SysAllocString(clsid))) - goto cleanup; - hr = IPropertyBag_Write(prop_bag, clsidW, &var); - if (FAILED(hr)) goto cleanup; - VariantClear(&var); + hr = register_codec(&CLSID_VideoCompressorCategory, name, + &CLSID_AVICo, info.szDescription, &prop_bag); + if (FAILED(hr)) + continue;
/* write filter data */ rgf.dwVersion = 2; @@ -877,10 +763,13 @@ static void register_vfw_codecs(void)
write_filter_data(prop_bag, &rgf);
-cleanup: + /* write WaveInId */ + V_VT(&var) = VT_BSTR; + V_BSTR(&var) = SysAllocString(name); + IPropertyBag_Write(prop_bag, fcchandlerW, &var); + VariantClear(&var); - if (prop_bag) IPropertyBag_Release(prop_bag); - if (mon) IMoniker_Release(mon); + IPropertyBag_Release(prop_bag); } }
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/devenum/createdevenum.c | 139 +++++++++++++++++-------------------------- 1 file changed, 54 insertions(+), 85 deletions(-)
diff --git a/dlls/devenum/createdevenum.c b/dlls/devenum/createdevenum.c index ad1022e..fa096be 100644 --- a/dlls/devenum/createdevenum.c +++ b/dlls/devenum/createdevenum.c @@ -53,7 +53,7 @@ static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a', static const WCHAR wszFilterData[] = {'F','i','l','t','e','r','D','a','t','a',0};
static ULONG WINAPI DEVENUM_ICreateDevEnum_AddRef(ICreateDevEnum * iface); -static HRESULT register_codecs(void); +static void register_codecs(void); static HRESULT DEVENUM_CreateAMCategoryKey(const CLSID * clsidCategory);
/********************************************************************** @@ -773,6 +773,57 @@ static void register_vfw_codecs(void) } }
+static void register_avicap_devices(void) +{ + static const WCHAR vfwindexW[] = {'V','F','W','I','n','d','e','x',0}; + WCHAR friendlyname[] = {'v','i','d','e','o','0',0}; + IPropertyBag *prop_bag = NULL; + WCHAR name[32], version[32]; + REGFILTERPINS2 rgpins; + REGPINTYPES rgtypes; + REGFILTER2 rgf; + VARIANT var; + HRESULT hr; + int i = 0; + + hr = DEVENUM_CreateAMCategoryKey(&CLSID_VideoInputDeviceCategory); + if (FAILED(hr)) + return; + + for (i = 0; i < 10; ++i) + { + if (!capGetDriverDescriptionW(i, name, sizeof(name), version, sizeof(version))) + break; + + friendlyname[5] = '0' + i; + + hr = register_codec(&CLSID_VideoInputDeviceCategory, name, + &CLSID_VfwCapture, friendlyname, &prop_bag); + if (FAILED(hr)) + continue; + + rgf.dwVersion = 2; + rgf.dwMerit = MERIT_DO_NOT_USE; + rgf.u.s2.cPins2 = 1; + rgf.u.s2.rgPins2 = &rgpins; + rgpins.dwFlags = 0; + rgpins.nMediaTypes = 1; + rgpins.lpMediaType = &rgtypes; + rgtypes.clsMajorType = &MEDIATYPE_Video; + rgtypes.clsMinorType = &MEDIASUBTYPE_None; + + write_filter_data(prop_bag, &rgf); + + /* write VFWIndex */ + V_VT(&var) = VT_I4; + V_I4(&var) = i; + IPropertyBag_Write(prop_bag, vfwindexW, &var); + + VariantClear(&var); + IPropertyBag_Release(prop_bag); + } +} + /********************************************************************** * DEVENUM_ICreateDevEnum_CreateClassEnumerator */ @@ -799,6 +850,7 @@ static HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator( register_wavein_devices(); register_midiout_devices(); register_vfw_codecs(); + register_avicap_devices();
return create_EnumMoniker(clsidDeviceClass, ppEnumMoniker); } @@ -851,14 +903,9 @@ static HRESULT DEVENUM_CreateAMCategoryKey(const CLSID * clsidCategory) return res; }
-static HRESULT register_codecs(void) +static void register_codecs(void) { - HRESULT res; WCHAR class[CHARS_IN_GUID]; - DWORD iDefaultDevice = -1; - IFilterMapper2 * pMapper = NULL; - REGFILTER2 rf2; - REGFILTERPINS2 rfp2; HKEY basekey;
/* Since devices can change between session, for example because you just plugged in a webcam @@ -878,82 +925,4 @@ static HRESULT register_codecs(void) StringFromGUID2(&CLSID_VideoCompressorCategory, class, CHARS_IN_GUID); RegDeleteTreeW(basekey, class); RegCloseKey(basekey); - - rf2.dwVersion = 2; - rf2.dwMerit = MERIT_PREFERRED; - rf2.u.s2.cPins2 = 1; - rf2.u.s2.rgPins2 = &rfp2; - rfp2.cInstances = 1; - rfp2.nMediums = 0; - rfp2.lpMedium = NULL; - rfp2.clsPinCategory = &IID_NULL; - - res = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC, - &IID_IFilterMapper2, (void **) &pMapper); - /* - * Fill in info for devices - */ - if (SUCCEEDED(res)) - { - UINT i; - REGPINTYPES * pTypes; - IPropertyBag * pPropBag = NULL; - - res = DEVENUM_CreateAMCategoryKey(&CLSID_VideoInputDeviceCategory); - if (SUCCEEDED(res)) - for (i = 0; i < 10; i++) - { - WCHAR szDeviceName[32], szDeviceVersion[32], szDevicePath[10]; - - if (capGetDriverDescriptionW (i, szDeviceName, ARRAY_SIZE(szDeviceName), - szDeviceVersion, ARRAY_SIZE(szDeviceVersion))) - { - IMoniker * pMoniker = NULL; - WCHAR dprintf[] = { 'v','i','d','e','o','%','d',0 }; - snprintfW(szDevicePath, ARRAY_SIZE(szDevicePath), dprintf, i); - /* The above code prevents 1 device with a different ID overwriting another */ - - rfp2.nMediaTypes = 1; - pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES)); - if (!pTypes) { - IFilterMapper2_Release(pMapper); - return E_OUTOFMEMORY; - } - - pTypes[0].clsMajorType = &MEDIATYPE_Video; - pTypes[0].clsMinorType = &MEDIASUBTYPE_None; - - rfp2.lpMediaType = pTypes; - - res = IFilterMapper2_RegisterFilter(pMapper, - &CLSID_VfwCapture, - szDeviceName, - &pMoniker, - &CLSID_VideoInputDeviceCategory, - szDevicePath, - &rf2); - - if (pMoniker) { - OLECHAR wszVfwIndex[] = { 'V','F','W','I','n','d','e','x',0 }; - VARIANT var; - V_VT(&var) = VT_I4; - V_I4(&var) = i; - res = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID)&pPropBag); - if (SUCCEEDED(res)) { - res = IPropertyBag_Write(pPropBag, wszVfwIndex, &var); - IPropertyBag_Release(pPropBag); - } - IMoniker_Release(pMoniker); - } - - if (i == iDefaultDevice) FIXME("Default device\n"); - CoTaskMemFree(pTypes); - } - } - } - - if (pMapper) - IFilterMapper2_Release(pMapper); - - return res; }
This matches native behaviour, and greatly reduces the overhead of IFilterMapper2_EnumMatchingFilters().
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/devenum/createdevenum.c | 70 ++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 42 deletions(-)
diff --git a/dlls/devenum/createdevenum.c b/dlls/devenum/createdevenum.c index fa096be..9b7ee3f 100644 --- a/dlls/devenum/createdevenum.c +++ b/dlls/devenum/createdevenum.c @@ -53,7 +53,6 @@ static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a', static const WCHAR wszFilterData[] = {'F','i','l','t','e','r','D','a','t','a',0};
static ULONG WINAPI DEVENUM_ICreateDevEnum_AddRef(ICreateDevEnum * iface); -static void register_codecs(void); static HRESULT DEVENUM_CreateAMCategoryKey(const CLSID * clsidCategory);
/********************************************************************** @@ -828,31 +827,42 @@ static void register_avicap_devices(void) * DEVENUM_ICreateDevEnum_CreateClassEnumerator */ static HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator( - ICreateDevEnum * iface, - REFCLSID clsidDeviceClass, - IEnumMoniker **ppEnumMoniker, - DWORD dwFlags) + ICreateDevEnum *iface, REFCLSID class, IEnumMoniker **out, DWORD flags) { + WCHAR guidstr[CHARS_IN_GUID]; HRESULT hr; + HKEY key;
- TRACE("(%p)->(%s, %p, %x)\n", iface, debugstr_guid(clsidDeviceClass), ppEnumMoniker, dwFlags); + TRACE("iface %p, class %s, out %p, flags %#x.\n", iface, debugstr_guid(class), out, flags);
- if (!ppEnumMoniker) + if (!out) return E_POINTER;
- *ppEnumMoniker = NULL; + *out = NULL;
- register_codecs(); - register_legacy_filters(); - hr = DirectSoundEnumerateW(®ister_dsound_devices, NULL); - if (FAILED(hr)) return hr; - register_waveout_devices(); - register_wavein_devices(); - register_midiout_devices(); - register_vfw_codecs(); - register_avicap_devices(); + if (!RegOpenKeyW(HKEY_CURRENT_USER, wszActiveMovieKey, &key)) + { + StringFromGUID2(class, guidstr, ARRAY_SIZE(guidstr)); + RegDeleteTreeW(key, guidstr); + }
- return create_EnumMoniker(clsidDeviceClass, ppEnumMoniker); + if (IsEqualGUID(class, &CLSID_LegacyAmFilterCategory)) + register_legacy_filters(); + else if (IsEqualGUID(class, &CLSID_AudioRendererCategory)) + { + hr = DirectSoundEnumerateW(®ister_dsound_devices, NULL); + if (FAILED(hr)) return hr; + register_waveout_devices(); + register_midiout_devices(); + } + else if (IsEqualGUID(class, &CLSID_AudioInputDeviceCategory)) + register_wavein_devices(); + else if (IsEqualGUID(class, &CLSID_VideoCompressorCategory)) + register_vfw_codecs(); + else if (IsEqualGUID(class, &CLSID_VideoInputDeviceCategory)) + register_avicap_devices(); + + return create_EnumMoniker(class, out); }
/********************************************************************** @@ -902,27 +912,3 @@ static HRESULT DEVENUM_CreateAMCategoryKey(const CLSID * clsidCategory)
return res; } - -static void register_codecs(void) -{ - WCHAR class[CHARS_IN_GUID]; - HKEY basekey; - - /* Since devices can change between session, for example because you just plugged in a webcam - * or switched from pulseaudio to alsa, delete all old devices first - */ - RegOpenKeyW(HKEY_CURRENT_USER, wszActiveMovieKey, &basekey); - StringFromGUID2(&CLSID_LegacyAmFilterCategory, class, CHARS_IN_GUID); - RegDeleteTreeW(basekey, class); - StringFromGUID2(&CLSID_AudioRendererCategory, class, CHARS_IN_GUID); - RegDeleteTreeW(basekey, class); - StringFromGUID2(&CLSID_AudioInputDeviceCategory, class, CHARS_IN_GUID); - RegDeleteTreeW(basekey, class); - StringFromGUID2(&CLSID_VideoInputDeviceCategory, class, CHARS_IN_GUID); - RegDeleteTreeW(basekey, class); - StringFromGUID2(&CLSID_MidiRendererCategory, class, CHARS_IN_GUID); - RegDeleteTreeW(basekey, class); - StringFromGUID2(&CLSID_VideoCompressorCategory, class, CHARS_IN_GUID); - RegDeleteTreeW(basekey, class); - RegCloseKey(basekey); -}
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/filtergraph.c | 15 +++++++++--- dlls/quartz/tests/filtergraph.c | 51 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 60 insertions(+), 6 deletions(-)
diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c index 0468cb5..7148990 100644 --- a/dlls/quartz/filtergraph.c +++ b/dlls/quartz/filtergraph.c @@ -1181,8 +1181,17 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut,
/* Try direct connection first */ hr = IPin_Connect(ppinOut, ppinIn, NULL); - if (SUCCEEDED(hr)) - goto out; + + /* If direct connection succeeded, we should propagate that return value. + * If it returned VFW_E_NOT_CONNECTED or VFW_E_NO_AUDIO_HARDWARE, then don't + * even bother trying intermediate filters, since they won't succeed. */ + if (SUCCEEDED(hr) || hr == VFW_E_NOT_CONNECTED || hr == VFW_E_NO_AUDIO_HARDWARE) + { + --This->recursioncount; + LeaveCriticalSection(&This->cs); + TRACE("--> %#x\n", hr); + return hr; + }
TRACE("Direct connection failed, trying to render using extra filters\n");
@@ -1391,7 +1400,7 @@ out: --This->recursioncount; LeaveCriticalSection(&This->cs); TRACE("--> %08x\n", hr); - return SUCCEEDED(hr) ? S_OK : hr; + return SUCCEEDED(hr) ? S_OK : VFW_E_CANNOT_CONNECT; }
/* Render all output pins of the given filter. Helper for FilterGraph2_Render(). */ diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c index 6c8b9fa..b40145a 100644 --- a/dlls/quartz/tests/filtergraph.c +++ b/dlls/quartz/tests/filtergraph.c @@ -609,7 +609,6 @@ static void test_render_run(const WCHAR *file) ok(!refs, "Graph has %u references\n", refs);
hr = test_graph_builder_connect_file(filename); -todo_wine ok(hr == VFW_E_CANNOT_CONNECT, "got %#x\n", hr); } else @@ -776,6 +775,7 @@ struct testpin unsigned int type_count, enum_idx; AM_MEDIA_TYPE *request_mt, *accept_mt;
+ HRESULT Connect_hr; HRESULT QueryInternalConnections_hr; };
@@ -1063,6 +1063,7 @@ static void testpin_init(struct testpin *pin, const IPinVtbl *vtbl, PIN_DIRECTIO pin->IEnumMediaTypes_iface.lpVtbl = &testenummt_vtbl; pin->ref = 1; pin->dir = dir; + pin->Connect_hr = S_OK; pin->QueryInternalConnections_hr = E_NOTIMPL; }
@@ -1077,12 +1078,16 @@ static HRESULT WINAPI testsource_Connect(IPin *iface, IPin *peer, const AM_MEDIA HRESULT hr; if (winetest_debug > 1) trace("%p->Connect(%p)\n", pin, peer);
+ if (FAILED(pin->Connect_hr)) + return pin->Connect_hr; + ok(!mt, "Got media type %p.\n", mt);
if (SUCCEEDED(hr = IPin_ReceiveConnection(peer, &pin->IPin_iface, pin->request_mt))) { pin->peer = peer; IPin_AddRef(peer); + return pin->Connect_hr; } return hr; } @@ -1711,12 +1716,39 @@ static void test_graph_builder_connect(void) IFilterGraph2_Disconnect(graph, source_pin.peer); IFilterGraph2_Disconnect(graph, &source_pin.IPin_iface);
+ for (source_pin.Connect_hr = 0x00040200; source_pin.Connect_hr <= 0x000402ff; + ++source_pin.Connect_hr) + { + hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface); + ok(hr == source_pin.Connect_hr, "Got hr %#x for Connect() hr %#x.\n", + hr, source_pin.Connect_hr); + ok(source_pin.peer == &sink_pin.IPin_iface, "Got peer %p.\n", source_pin.peer); + IFilterGraph2_Disconnect(graph, source_pin.peer); + IFilterGraph2_Disconnect(graph, &source_pin.IPin_iface); + } + source_pin.Connect_hr = S_OK; + sink_pin.accept_mt = &sink_type; hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface); -todo_wine ok(hr == VFW_E_CANNOT_CONNECT, "Got hr %#x.\n", hr); ok(!source_pin.peer, "Got peer %p.\n", source_pin.peer);
+ for (source_pin.Connect_hr = 0x80040200; source_pin.Connect_hr <= 0x800402ff; + ++source_pin.Connect_hr) + { + hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface); + if (source_pin.Connect_hr == VFW_E_NOT_CONNECTED + || source_pin.Connect_hr == VFW_E_NO_AUDIO_HARDWARE) + ok(hr == source_pin.Connect_hr, "Got hr %#x for Connect() hr %#x.\n", + hr, source_pin.Connect_hr); + else + ok(hr == VFW_E_CANNOT_CONNECT, "Got hr %#x for Connect() hr %#x.\n", + hr, source_pin.Connect_hr); + ok(!source_pin.peer, "Got peer %p.\n", source_pin.peer); + ok(!sink_pin.peer, "Got peer %p.\n", sink_pin.peer); + } + source_pin.Connect_hr = S_OK; + /* Test usage of intermediate filters. Similarly to Render(), filters are * simply tried in enumeration order. */
@@ -1740,6 +1772,20 @@ todo_wine IFilterGraph2_Disconnect(graph, sink_pin.peer); IFilterGraph2_Disconnect(graph, &sink_pin.IPin_iface);
+ for (source_pin.Connect_hr = 0x00040200; source_pin.Connect_hr <= 0x000402ff; + ++source_pin.Connect_hr) + { + hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface); + ok(hr == S_OK, "Got hr %#x for Connect() hr %#x.\n", hr, source_pin.Connect_hr); + ok(source_pin.peer == &parser2_pins[0].IPin_iface, "Got peer %p.\n", source_pin.peer); + ok(sink_pin.peer == &parser2_pins[1].IPin_iface, "Got peer %p.\n", sink_pin.peer); + IFilterGraph2_Disconnect(graph, source_pin.peer); + IFilterGraph2_Disconnect(graph, &source_pin.IPin_iface); + IFilterGraph2_Disconnect(graph, sink_pin.peer); + IFilterGraph2_Disconnect(graph, &sink_pin.IPin_iface); + } + source_pin.Connect_hr = S_OK; + IFilterGraph2_RemoveFilter(graph, &parser1.IBaseFilter_iface); IFilterGraph2_AddFilter(graph, &parser1.IBaseFilter_iface, NULL);
@@ -1805,7 +1851,6 @@ todo_wine
parser1_pins[1].name[0] = '~'; hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface); -todo_wine ok(hr == VFW_E_CANNOT_CONNECT, "Got hr %#x.\n", hr); ok(!source_pin.peer, "Got peer %p.\n", source_pin.peer);
Zebediah Figura z.figura12@gmail.com writes:
Signed-off-by: Zebediah Figura z.figura12@gmail.com
dlls/quartz/filtergraph.c | 15 +++++++++--- dlls/quartz/tests/filtergraph.c | 51 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 60 insertions(+), 6 deletions(-)
It still fails for me:
../../../tools/runtest -q -P wine -T ../../.. -M qcap.dll -p qcap_test.exe.so smartteefilter && touch smartteefilter.ok smartteefilter.c:1570: Test failed: connecting Capture pin without first connecting Input pin returned 0x80040217 smartteefilter.c:1572: Test failed: connecting Preview pin without first connecting Input pin returned 0x80040217 make: *** [Makefile:227: smartteefilter.ok] Error 2