Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/devenum/createdevenum.c | 22 ---------------------- dlls/devenum/tests/devenum.c | 2 -- 2 files changed, 24 deletions(-)
diff --git a/dlls/devenum/createdevenum.c b/dlls/devenum/createdevenum.c index 7cfdbff..7c03852 100644 --- a/dlls/devenum/createdevenum.c +++ b/dlls/devenum/createdevenum.c @@ -547,12 +547,6 @@ static void register_vfw_codecs(void) RegCloseKey(basekey); }
-static HANDLE DEVENUM_populate_handle; -static const WCHAR DEVENUM_populate_handle_nameW[] = - {'_','_','W','I','N','E','_', - 'D','e','v','e','n','u','m','_', - 'P','o','p','u','l','a','t','e',0}; - static HRESULT register_codecs(void) { HRESULT res; @@ -566,21 +560,6 @@ static HRESULT register_codecs(void) REGFILTERPINS2 rfp2; HKEY basekey;
- if (DEVENUM_populate_handle) - return S_OK; - DEVENUM_populate_handle = CreateEventW(NULL, TRUE, FALSE, DEVENUM_populate_handle_nameW); - if (GetLastError() == ERROR_ALREADY_EXISTS) - { - /* Webcams can take some time to scan if the driver is badly written and it enables them, - * so have a 10 s timeout here - */ - if (WaitForSingleObject(DEVENUM_populate_handle, 10000) == WAIT_TIMEOUT) - WARN("Waiting for object timed out\n"); - TRACE("No need to rescan\n"); - return S_OK; - } - TRACE("Scanning for devices\n"); - /* 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 */ @@ -878,6 +857,5 @@ static HRESULT register_codecs(void)
register_vfw_codecs();
- SetEvent(DEVENUM_populate_handle); return res; } diff --git a/dlls/devenum/tests/devenum.c b/dlls/devenum/tests/devenum.c index 7e3270f..a08dece 100644 --- a/dlls/devenum/tests/devenum.c +++ b/dlls/devenum/tests/devenum.c @@ -445,11 +445,9 @@ static void test_codec(void)
/* unlike DirectShow filters, these are automatically generated, so * enumerating them will destroy the key */ -todo_wine ok(!find_moniker(&CLSID_AudioRendererCategory, mon), "codec should not be registered\n");
hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL); -todo_wine ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got %#x\n", hr);
IPropertyBag_Release(prop_bag);
Since quartz can't read back version 1.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/devenum/createdevenum.c | 78 +++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 40 deletions(-)
diff --git a/dlls/devenum/createdevenum.c b/dlls/devenum/createdevenum.c index 7c03852..c1e29fc 100644 --- a/dlls/devenum/createdevenum.c +++ b/dlls/devenum/createdevenum.c @@ -124,7 +124,7 @@ static HKEY open_special_category_key(const CLSID *clsid, BOOL create) return ret; }
-static void DEVENUM_ReadPinTypes(HKEY hkeyPinKey, REGFILTERPINS *rgPin) +static void DEVENUM_ReadPinTypes(HKEY hkeyPinKey, REGFILTERPINS2 *rgPin) { HKEY hkeyTypes = NULL; DWORD dwMajorTypes, i; @@ -221,7 +221,11 @@ static void DEVENUM_ReadPins(HKEY hkeyFilterClass, REGFILTER2 *rgf2) { HKEY hkeyPins = NULL; DWORD dwPinsSubkeys, i; - REGFILTERPINS *rgPins = NULL; + REGFILTERPINS2 *rgPins = NULL; + + rgf2->dwVersion = 2; + rgf2->u.s2.cPins2 = 0; + rgf2->u.s2.rgPins2 = NULL;
if (RegOpenKeyExW(hkeyFilterClass, wszPins, 0, KEY_READ, &hkeyPins) != ERROR_SUCCESS) return ; @@ -235,7 +239,7 @@ static void DEVENUM_ReadPins(HKEY hkeyFilterClass, REGFILTER2 *rgf2)
if (dwPinsSubkeys) { - rgPins = CoTaskMemAlloc(sizeof(REGFILTERPINS) * dwPinsSubkeys); + rgPins = CoTaskMemAlloc(sizeof(REGFILTERPINS2) * dwPinsSubkeys); if (!rgPins) { RegCloseKey(hkeyPins); @@ -248,65 +252,64 @@ static void DEVENUM_ReadPins(HKEY hkeyFilterClass, REGFILTER2 *rgf2) HKEY hkeyPinKey = NULL; WCHAR wszPinName[MAX_PATH]; DWORD cName = sizeof(wszPinName) / sizeof(WCHAR); - DWORD Type, cbData; - REGFILTERPINS *rgPin = &rgPins[rgf2->u.s1.cPins]; + REGFILTERPINS2 *rgPin = &rgPins[rgf2->u.s2.cPins2]; + DWORD value, size, Type; LONG lRet;
- rgPin->strName = NULL; - rgPin->clsConnectsToFilter = &GUID_NULL; - rgPin->strConnectsToPin = NULL; - rgPin->nMediaTypes = 0; - rgPin->lpMediaType = NULL; + memset(rgPin, 0, sizeof(*rgPin));
if (RegEnumKeyExW(hkeyPins, i, wszPinName, &cName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) continue;
if (RegOpenKeyExW(hkeyPins, wszPinName, 0, KEY_READ, &hkeyPinKey) != ERROR_SUCCESS) continue;
- rgPin->strName = CoTaskMemAlloc((strlenW(wszPinName) + 1) * sizeof(WCHAR)); - if (!rgPin->strName) goto error_cleanup; - - strcpyW(rgPin->strName, wszPinName); - - cbData = sizeof(rgPin->bMany); - lRet = RegQueryValueExW(hkeyPinKey, wszAllowedMany, NULL, &Type, (LPBYTE)&rgPin->bMany, &cbData); + size = sizeof(DWORD); + lRet = RegQueryValueExW(hkeyPinKey, wszAllowedMany, NULL, &Type, (BYTE *)&value, &size); if (lRet != ERROR_SUCCESS || Type != REG_DWORD) goto error_cleanup; + if (value) + rgPin->dwFlags |= REG_PINFLAG_B_MANY;
- cbData = sizeof(rgPin->bZero); - lRet = RegQueryValueExW(hkeyPinKey, wszAllowedZero, NULL, &Type, (LPBYTE)&rgPin->bZero, &cbData); + size = sizeof(DWORD); + lRet = RegQueryValueExW(hkeyPinKey, wszAllowedZero, NULL, &Type, (BYTE *)&value, &size); if (lRet != ERROR_SUCCESS || Type != REG_DWORD) goto error_cleanup; + if (value) + rgPin->dwFlags |= REG_PINFLAG_B_ZERO;
- cbData = sizeof(rgPin->bOutput); - lRet = RegQueryValueExW(hkeyPinKey, wszDirection, NULL, &Type, (LPBYTE)&rgPin->bOutput, &cbData); + size = sizeof(DWORD); + lRet = RegQueryValueExW(hkeyPinKey, wszDirection, NULL, &Type, (BYTE *)&value, &size); if (lRet != ERROR_SUCCESS || Type != REG_DWORD) goto error_cleanup; + if (value) + rgPin->dwFlags |= REG_PINFLAG_B_OUTPUT; +
- cbData = sizeof(rgPin->bRendered); - lRet = RegQueryValueExW(hkeyPinKey, wszIsRendered, NULL, &Type, (LPBYTE)&rgPin->bRendered, &cbData); + size = sizeof(DWORD); + lRet = RegQueryValueExW(hkeyPinKey, wszIsRendered, NULL, &Type, (BYTE *)&value, &size); if (lRet != ERROR_SUCCESS || Type != REG_DWORD) goto error_cleanup; + if (value) + rgPin->dwFlags |= REG_PINFLAG_B_RENDERER;
DEVENUM_ReadPinTypes(hkeyPinKey, rgPin);
- ++rgf2->u.s1.cPins; + ++rgf2->u.s2.cPins2; continue;
error_cleanup:
RegCloseKey(hkeyPinKey); - CoTaskMemFree(rgPin->strName); }
RegCloseKey(hkeyPins);
- if (rgPins && !rgf2->u.s1.cPins) + if (rgPins && !rgf2->u.s2.cPins2) { CoTaskMemFree(rgPins); rgPins = NULL; }
- rgf2->u.s1.rgPins = rgPins; + rgf2->u.s2.rgPins2 = rgPins; }
static HRESULT DEVENUM_RegisterLegacyAmFilters(void) @@ -374,10 +377,7 @@ static HRESULT DEVENUM_RegisterLegacyAmFilters(void) if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszRegKey, 0, KEY_READ, &hkeyFilterClass) != ERROR_SUCCESS) continue;
- rgf2.dwVersion = 1; rgf2.dwMerit = 0; - rgf2.u.s1.cPins = 0; - rgf2.u.s1.rgPins = NULL;
cbData = sizeof(wszFilterName); if (RegQueryValueExW(hkeyFilterClass, NULL, NULL, &Type, (LPBYTE)wszFilterName, &cbData) != ERROR_SUCCESS || @@ -403,29 +403,27 @@ static HRESULT DEVENUM_RegisterLegacyAmFilters(void)
if (hkeyFilterClass) RegCloseKey(hkeyFilterClass);
- if (rgf2.u.s1.rgPins) + if (rgf2.u.s2.rgPins2) { UINT iPin;
- for (iPin = 0; iPin < rgf2.u.s1.cPins; iPin++) + for (iPin = 0; iPin < rgf2.u.s2.cPins2; iPin++) { - CoTaskMemFree(rgf2.u.s1.rgPins[iPin].strName); - - if (rgf2.u.s1.rgPins[iPin].lpMediaType) + if (rgf2.u.s2.rgPins2[iPin].lpMediaType) { UINT iType;
- for (iType = 0; iType < rgf2.u.s1.rgPins[iPin].nMediaTypes; iType++) + for (iType = 0; iType < rgf2.u.s2.rgPins2[iPin].nMediaTypes; iType++) { - CoTaskMemFree((void*)rgf2.u.s1.rgPins[iPin].lpMediaType[iType].clsMajorType); - CoTaskMemFree((void*)rgf2.u.s1.rgPins[iPin].lpMediaType[iType].clsMinorType); + CoTaskMemFree((void*)rgf2.u.s2.rgPins2[iPin].lpMediaType[iType].clsMajorType); + CoTaskMemFree((void*)rgf2.u.s2.rgPins2[iPin].lpMediaType[iType].clsMinorType); }
- CoTaskMemFree((void*)rgf2.u.s1.rgPins[iPin].lpMediaType); + CoTaskMemFree((void*)rgf2.u.s2.rgPins2[iPin].lpMediaType); } }
- CoTaskMemFree((void*)rgf2.u.s1.rgPins); + CoTaskMemFree((void*)rgf2.u.s2.rgPins2); } } }
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- This fixes one facet of the error originally reported here: https://www.winehq.org/pipermail/wine-devel/2018-March/123533.html
dlls/devenum/Makefile.in | 4 +- dlls/devenum/createdevenum.c | 240 ++++++++++++++++++++++++++------------- dlls/devenum/fil_data.idl | 47 ++++++++ dlls/devenum/tests/devenum.c | 76 ++++++++++++- dlls/quartz/tests/filtermapper.c | 18 +++ 5 files changed, 300 insertions(+), 85 deletions(-) create mode 100644 dlls/devenum/fil_data.idl
diff --git a/dlls/devenum/Makefile.in b/dlls/devenum/Makefile.in index 38ca83d..0a7e903 100644 --- a/dlls/devenum/Makefile.in +++ b/dlls/devenum/Makefile.in @@ -9,6 +9,8 @@ C_SRCS = \ mediacatenum.c \ parsedisplayname.c
-IDL_SRCS = devenum_classes.idl +IDL_SRCS = \ + devenum_classes.idl \ + fil_data.idl
RC_SRCS = devenum.rc diff --git a/dlls/devenum/createdevenum.c b/dlls/devenum/createdevenum.c index c1e29fc..15602e7 100644 --- a/dlls/devenum/createdevenum.c +++ b/dlls/devenum/createdevenum.c @@ -32,8 +32,12 @@
#include "wine/debug.h" #include "wine/unicode.h" +#include "wine/heap.h" #include "mmddk.h"
+#include "initguid.h" +#include "fil_data.h" + WINE_DEFAULT_DEBUG_CHANNEL(devenum);
extern HINSTANCE DEVENUM_hInstance; @@ -50,9 +54,11 @@ static const WCHAR wszTypes[] = {'T','y','p','e','s',0}; static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0}; static const WCHAR wszWaveInID[] = {'W','a','v','e','I','n','I','D',0}; static const WCHAR wszWaveOutID[] = {'W','a','v','e','O','u','t','I','D',0}; +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 HRESULT DEVENUM_CreateAMCategoryKey(const CLSID * clsidCategory);
/********************************************************************** * DEVENUM_ICreateDevEnum_QueryInterface (also IUnknown) @@ -124,6 +130,36 @@ static HKEY open_special_category_key(const CLSID *clsid, BOOL create) return ret; }
+static HRESULT register_codec(const CLSID *class, const WCHAR *name, IMoniker **ret) +{ + static const WCHAR deviceW[] = {'@','d','e','v','i','c','e',':','c','m',':',0}; + IParseDisplayName *parser; + WCHAR *buffer; + ULONG eaten; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (void **)&parser); + if (FAILED(hr)) + return hr; + + buffer = heap_alloc((strlenW(deviceW) + CHARS_IN_GUID + strlenW(name) + 1) * sizeof(WCHAR)); + if (!buffer) + { + IParseDisplayName_Release(parser); + return E_OUTOFMEMORY; + } + + strcpyW(buffer, deviceW); + StringFromGUID2(class, buffer + strlenW(buffer), CHARS_IN_GUID); + strcatW(buffer, backslashW); + strcatW(buffer, name); + + hr = IParseDisplayName_ParseDisplayName(parser, NULL, buffer, &eaten, ret); + IParseDisplayName_Release(parser); + heap_free(buffer); + return hr; +} + static void DEVENUM_ReadPinTypes(HKEY hkeyPinKey, REGFILTERPINS2 *rgPin) { HKEY hkeyTypes = NULL; @@ -312,21 +348,42 @@ static void DEVENUM_ReadPins(HKEY hkeyFilterClass, REGFILTER2 *rgf2) rgf2->u.s2.rgPins2 = rgPins; }
-static HRESULT DEVENUM_RegisterLegacyAmFilters(void) +static void free_regfilter2(REGFILTER2 *rgf) { + if (rgf->u.s2.rgPins2) + { + UINT iPin; + + for (iPin = 0; iPin < rgf->u.s2.cPins2; iPin++) + { + if (rgf->u.s2.rgPins2[iPin].lpMediaType) + { + UINT iType; + + for (iType = 0; iType < rgf->u.s2.rgPins2[iPin].nMediaTypes; iType++) + { + CoTaskMemFree((void *)rgf->u.s2.rgPins2[iPin].lpMediaType[iType].clsMajorType); + CoTaskMemFree((void *)rgf->u.s2.rgPins2[iPin].lpMediaType[iType].clsMinorType); + } + + CoTaskMemFree((void *)rgf->u.s2.rgPins2[iPin].lpMediaType); + } + } + + CoTaskMemFree((void *)rgf->u.s2.rgPins2); + } +} + +static void DEVENUM_RegisterLegacyAmFilters(void) +{ + IAMFilterData *fildata = NULL; HKEY hkeyFilter = NULL; DWORD dwFilterSubkeys, i; LONG lRet; - IFilterMapper2 *pMapper = NULL; HRESULT hr;
- hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC, - &IID_IFilterMapper2, (void **) &pMapper); - if (SUCCEEDED(hr)) - { - lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszFilterKeyName, 0, KEY_READ, &hkeyFilter); - hr = HRESULT_FROM_WIN32(lRet); - } + lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszFilterKeyName, 0, KEY_READ, &hkeyFilter); + hr = HRESULT_FROM_WIN32(lRet);
if (SUCCEEDED(hr)) { @@ -335,106 +392,123 @@ static HRESULT DEVENUM_RegisterLegacyAmFilters(void) }
if (SUCCEEDED(hr)) + hr = DEVENUM_CreateAMCategoryKey(&CLSID_LegacyAmFilterCategory); + + if (SUCCEEDED(hr)) + hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC, &IID_IAMFilterData, (void **)&fildata); + + if (SUCCEEDED(hr)) { for (i = 0; i < dwFilterSubkeys; i++) { WCHAR wszFilterSubkeyName[64]; DWORD cName = sizeof(wszFilterSubkeyName) / sizeof(WCHAR); + IPropertyBag *prop_bag = NULL; WCHAR wszRegKey[MAX_PATH]; - HKEY hkeyInstance = NULL; + SAFEARRAYBOUND sabound; + HKEY classkey = NULL; + IMoniker *mon = NULL; + BYTE *data, *array; + VARIANT var = {0}; + REGFILTER2 rgf2; + DWORD Type, len; + ULONG size;
if (RegEnumKeyExW(hkeyFilter, i, wszFilterSubkeyName, &cName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) continue;
- strcpyW(wszRegKey, wszActiveMovieKey); - StringFromGUID2(&CLSID_LegacyAmFilterCategory, wszRegKey + strlenW(wszRegKey), CHARS_IN_GUID); + TRACE("Registering %s\n", debugstr_w(wszFilterSubkeyName));
- strcatW(wszRegKey, wszRegSeparator); + strcpyW(wszRegKey, clsidW); strcatW(wszRegKey, wszFilterSubkeyName);
- if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszRegKey, 0, KEY_READ, &hkeyInstance) == ERROR_SUCCESS) + 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)) { - RegCloseKey(hkeyInstance); + WCHAR *friendlyname = heap_alloc(len); + if (!friendlyname) + { + hr = E_OUTOFMEMORY; + goto cleanup; + } + RegQueryValueExW(classkey, NULL, NULL, &Type, (BYTE *)friendlyname, &len); + V_BSTR(&var) = SysAllocStringLen(friendlyname, len/sizeof(WCHAR)); + heap_free(friendlyname); } else - { - /* Filter is registered the IFilterMapper(1)-way in HKCR\Filter. Needs to be added to - * legacy am filter category. */ - HKEY hkeyFilterClass = NULL; - REGFILTER2 rgf2; - CLSID clsidFilter; - WCHAR wszFilterName[MAX_PATH]; - DWORD Type; - DWORD cbData; - HRESULT res; - IMoniker *pMoniker = NULL; - - TRACE("Registering %s\n", debugstr_w(wszFilterSubkeyName)); - - strcpyW(wszRegKey, clsid_keyname); - strcatW(wszRegKey, wszRegSeparator); - strcatW(wszRegKey, wszFilterSubkeyName); - - if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszRegKey, 0, KEY_READ, &hkeyFilterClass) != ERROR_SUCCESS) - continue; - - rgf2.dwMerit = 0; - - cbData = sizeof(wszFilterName); - if (RegQueryValueExW(hkeyFilterClass, NULL, NULL, &Type, (LPBYTE)wszFilterName, &cbData) != ERROR_SUCCESS || - Type != REG_SZ) - goto cleanup; - - cbData = sizeof(rgf2.dwMerit); - if (RegQueryValueExW(hkeyFilterClass, wszMeritName, NULL, &Type, (LPBYTE)&rgf2.dwMerit, &cbData) != ERROR_SUCCESS || - Type != REG_DWORD) - goto cleanup; - - DEVENUM_ReadPins(hkeyFilterClass, &rgf2); + V_BSTR(&var) = SysAllocString(wszFilterSubkeyName);
- res = CLSIDFromString(wszFilterSubkeyName, &clsidFilter); - if (FAILED(res)) goto cleanup; - - IFilterMapper2_RegisterFilter(pMapper, &clsidFilter, wszFilterName, &pMoniker, NULL, NULL, &rgf2); - - if (pMoniker) - IMoniker_Release(pMoniker); - - cleanup: + if (!V_BSTR(&var)) + { + hr = E_OUTOFMEMORY; + goto cleanup; + } + hr = IPropertyBag_Write(prop_bag, wszFriendlyName, &var); + if (FAILED(hr)) goto cleanup; + VariantClear(&var);
- if (hkeyFilterClass) RegCloseKey(hkeyFilterClass); + /* write clsid */ + V_VT(&var) = VT_BSTR; + if (!(V_BSTR(&var) = SysAllocString(wszFilterSubkeyName))) + { + hr = E_OUTOFMEMORY; + goto cleanup; + } + hr = IPropertyBag_Write(prop_bag, clsid_keyname, &var); + if (FAILED(hr)) goto cleanup; + VariantClear(&var);
- if (rgf2.u.s2.rgPins2) - { - UINT iPin; + /* write filter data */ + rgf2.dwMerit = MERIT_NORMAL;
- for (iPin = 0; iPin < rgf2.u.s2.cPins2; iPin++) - { - if (rgf2.u.s2.rgPins2[iPin].lpMediaType) - { - UINT iType; + len = sizeof(rgf2.dwMerit); + RegQueryValueExW(classkey, wszMeritName, NULL, &Type, (BYTE *)&rgf2.dwMerit, &len);
- for (iType = 0; iType < rgf2.u.s2.rgPins2[iPin].nMediaTypes; iType++) - { - CoTaskMemFree((void*)rgf2.u.s2.rgPins2[iPin].lpMediaType[iType].clsMajorType); - CoTaskMemFree((void*)rgf2.u.s2.rgPins2[iPin].lpMediaType[iType].clsMinorType); - } + DEVENUM_ReadPins(classkey, &rgf2);
- CoTaskMemFree((void*)rgf2.u.s2.rgPins2[iPin].lpMediaType); - } - } + hr = IAMFilterData_CreateFilterData(fildata, &rgf2, &data, &size); + if (FAILED(hr)) goto cleanup;
- CoTaskMemFree((void*)rgf2.u.s2.rgPins2); - } + V_VT(&var) = VT_ARRAY | VT_UI1; + sabound.lLbound = 0; + sabound.cElements = size; + if (!(V_ARRAY(&var) = SafeArrayCreate(VT_UI1, 1, &sabound))) + { + hr = E_OUTOFMEMORY; + goto cleanup; } + hr = SafeArrayAccessData(V_ARRAY(&var), (void *)&array); + if (FAILED(hr)) goto cleanup; + + memcpy(array, data, size); + hr = SafeArrayUnaccessData(V_ARRAY(&var)); + if (FAILED(hr)) goto cleanup; + + hr = IPropertyBag_Write(prop_bag, wszFilterData, &var); + if (FAILED(hr)) goto cleanup; + +cleanup: + if (prop_bag) IPropertyBag_Release(prop_bag); + if (mon) IMoniker_Release(mon); + RegCloseKey(classkey); + VariantClear(&var); + free_regfilter2(&rgf2); } }
+ if (fildata) IAMFilterData_Release(fildata); + if (hkeyFilter) RegCloseKey(hkeyFilter); - - if (pMapper) - IFilterMapper2_Release(pMapper); - - return S_OK; }
/********************************************************************** @@ -562,6 +636,8 @@ static HRESULT register_codecs(void) * 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); diff --git a/dlls/devenum/fil_data.idl b/dlls/devenum/fil_data.idl new file mode 100644 index 0000000..7e37a75 --- /dev/null +++ b/dlls/devenum/fil_data.idl @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2009 Vitaliy Margolen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma makedep header + +import "objidl.idl"; +import "strmif.idl"; +import "unknwn.idl"; + + +/***************************************************************************** + * IAMFilterData interface + */ +[ + object, + uuid(97f7c4d4-547b-4a5f-8332-536430ad2e4d), + pointer_default(unique) +] +interface IAMFilterData : IUnknown +{ + typedef [unique] IAMFilterData *LPIAMFILTERDATA; + + HRESULT ParseFilterData( + [in] BYTE * rgbFilterData, + [in] ULONG cb, + [out] BYTE ** prgbRegFilter2); + + HRESULT CreateFilterData( + [in] REGFILTER2 * prf2, + [out] BYTE ** prgbFilterData, + [out] ULONG * pcb); +} diff --git a/dlls/devenum/tests/devenum.c b/dlls/devenum/tests/devenum.c index a08dece..8662c9f 100644 --- a/dlls/devenum/tests/devenum.c +++ b/dlls/devenum/tests/devenum.c @@ -27,11 +27,16 @@ #include "ole2.h" #include "strmif.h" #include "uuids.h" +#include "vfwmsgs.h"
static const WCHAR friendly_name[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0}; static const WCHAR fcc_handlerW[] = {'F','c','c','H','a','n','d','l','e','r',0}; +static const WCHAR deviceW[] = {'@','d','e','v','i','c','e',':',0}; static const WCHAR clsidW[] = {'C','L','S','I','D',0}; static const WCHAR mrleW[] = {'m','r','l','e',0}; +static const WCHAR swW[] = {'s','w',':',0}; +static const WCHAR cmW[] = {'c','m',':',0}; +static const WCHAR backslashW[] = {'\',0};
static void test_devenum(IBindCtx *bind_ctx) { @@ -304,7 +309,6 @@ static IMoniker *check_display_name_(int line, IParseDisplayName *parser, WCHAR
static void test_directshow_filter(void) { - static const WCHAR deviceW[] = {'@','d','e','v','i','c','e',':','s','w',':',0}; static const WCHAR instanceW[] = {'\','I','n','s','t','a','n','c','e',0}; static const WCHAR clsidW[] = {'C','L','S','I','D','\',0}; static WCHAR testW[] = {'\','t','e','s','t',0}; @@ -321,6 +325,7 @@ static void test_directshow_filter(void) ok(hr == S_OK, "Failed to create ParseDisplayName: %#x\n", hr);
lstrcpyW(buffer, deviceW); + lstrcatW(buffer, swW); StringFromGUID2(&CLSID_AudioRendererCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID); lstrcatW(buffer, testW); mon = check_display_name(parser, buffer); @@ -367,6 +372,7 @@ static void test_directshow_filter(void) /* name can be anything */
lstrcpyW(buffer, deviceW); + lstrcatW(buffer, swW); lstrcatW(buffer, testW+1); mon = check_display_name(parser, buffer);
@@ -405,7 +411,6 @@ static void test_directshow_filter(void)
static void test_codec(void) { - static const WCHAR deviceW[] = {'@','d','e','v','i','c','e',':','c','m',':',0}; static WCHAR testW[] = {'\','t','e','s','t',0}; IParseDisplayName *parser; IPropertyBag *prop_bag; @@ -419,6 +424,7 @@ static void test_codec(void) ok(hr == S_OK, "Failed to create ParseDisplayName: %#x\n", hr);
lstrcpyW(buffer, deviceW); + lstrcatW(buffer, cmW); StringFromGUID2(&CLSID_AudioRendererCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID); lstrcatW(buffer, testW); mon = check_display_name(parser, buffer); @@ -456,6 +462,70 @@ static void test_codec(void) IParseDisplayName_Release(parser); }
+static void test_legacy_filter(void) +{ + static const WCHAR nameW[] = {'l','e','g','a','c','y',' ','t','e','s','t',0}; + IParseDisplayName *parser; + IPropertyBag *prop_bag; + IFilterMapper *mapper; + IMoniker *mon; + WCHAR buffer[200]; + VARIANT var; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (void **)&parser); + ok(hr == S_OK, "Failed to create ParseDisplayName: %#x\n", hr); + + hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC, &IID_IFilterMapper, (void **)&mapper); + ok(hr == S_OK, "Failed to create FilterMapper: %#x\n", hr); + + hr = IFilterMapper_RegisterFilter(mapper, CLSID_TestFilter, nameW, 0xdeadbeef); + if (hr == VFW_E_BAD_KEY) + { + win_skip("not enough permissions to register filters\n"); + goto end; + } + ok(hr == S_OK, "RegisterFilter failed: %#x\n", hr); + + lstrcpyW(buffer, deviceW); + lstrcatW(buffer, cmW); + StringFromGUID2(&CLSID_LegacyAmFilterCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID); + lstrcatW(buffer, backslashW); + StringFromGUID2(&CLSID_TestFilter, buffer + lstrlenW(buffer), CHARS_IN_GUID); + + mon = check_display_name(parser, buffer); + ok(find_moniker(&CLSID_LegacyAmFilterCategory, mon), "filter should be registered\n"); + + hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); + ok(hr == S_OK, "BindToStorage failed: %#x\n", hr); + + VariantInit(&var); + hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL); + ok(hr == S_OK, "Read failed: %#x\n", hr); + + StringFromGUID2(&CLSID_TestFilter, buffer, CHARS_IN_GUID); + ok(!lstrcmpW(buffer, V_BSTR(&var)), "expected %s, got %s\n", + wine_dbgstr_w(buffer), wine_dbgstr_w(V_BSTR(&var))); + + VariantClear(&var); + hr = IPropertyBag_Read(prop_bag, clsidW, &var, NULL); + ok(hr == S_OK, "Read failed: %#x\n", hr); + ok(!lstrcmpW(buffer, V_BSTR(&var)), "expected %s, got %s\n", + wine_dbgstr_w(buffer), wine_dbgstr_w(V_BSTR(&var))); + + IPropertyBag_Release(prop_bag); + + hr = IFilterMapper_UnregisterFilter(mapper, CLSID_TestFilter); + ok(hr == S_OK, "UnregisterFilter failed: %#x\n", hr); + + ok(!find_moniker(&CLSID_LegacyAmFilterCategory, mon), "filter should not be registered\n"); + IMoniker_Release(mon); + +end: + IFilterMapper_Release(mapper); + IParseDisplayName_Release(parser); +} + START_TEST(devenum) { IBindCtx *bind_ctx = NULL; @@ -478,5 +548,7 @@ START_TEST(devenum) test_directshow_filter(); test_codec();
+ test_legacy_filter(); + CoUninitialize(); } diff --git a/dlls/quartz/tests/filtermapper.c b/dlls/quartz/tests/filtermapper.c index 829e89b..46a93eb 100644 --- a/dlls/quartz/tests/filtermapper.c +++ b/dlls/quartz/tests/filtermapper.c @@ -294,6 +294,24 @@ static void test_legacy_filter_registration(void) hr = IFilterMapper_UnregisterFilter(mapper, clsid); ok(hr == S_OK, "FilterMapper_UnregisterFilter failed with %x\n", hr);
+ hr = IFilterMapper2_EnumMatchingFilters(mapper2, &enum_mon, 0, TRUE, MERIT_UNLIKELY, TRUE, + 0, NULL, NULL, &GUID_NULL, FALSE, FALSE, 0, NULL, NULL, &GUID_NULL); + ok(hr == S_OK, "IFilterMapper2_EnumMatchingFilters failed: %x\n", hr); + ok(!enum_find_filter(testfilterW, enum_mon), "IFilterMapper2 shouldn't find filter\n"); + IEnumMoniker_Release(enum_mon); + + found = FALSE; + hr = IFilterMapper_EnumMatchingFilters(mapper, &enum_reg, MERIT_UNLIKELY, TRUE, GUID_NULL, GUID_NULL, + FALSE, FALSE, GUID_NULL, GUID_NULL); + ok(hr == S_OK, "IFilterMapper_EnumMatchingFilters failed with %x\n", hr); + while(!found && IEnumRegFilters_Next(enum_reg, 1, ®filter, &count) == S_OK) + { + if (!lstrcmpW(regfilter->Name, testfilterW) && IsEqualGUID(&clsid, ®filter->Clsid)) + found = TRUE; + } + IEnumRegFilters_Release(enum_reg); + ok(!found, "IFilterMapper shouldn't find filter\n"); + ret = RegDeleteKeyW(HKEY_CLASSES_ROOT, key_name); ok(!ret, "RegDeleteKeyA failed: %lu\n", ret);
On 08/03/18 12:37, Zebediah Figura wrote:
Signed-off-by: Zebediah Figura z.figura12@gmail.com
This fixes one facet of the error originally reported here: https://www.winehq.org/pipermail/wine-devel/2018-March/123533.html
dlls/devenum/Makefile.in | 4 +- dlls/devenum/createdevenum.c | 240 ++++++++++++++++++++++++++------------- dlls/devenum/fil_data.idl | 47 ++++++++ dlls/devenum/tests/devenum.c | 76 ++++++++++++- dlls/quartz/tests/filtermapper.c | 18 +++ 5 files changed, 300 insertions(+), 85 deletions(-) create mode 100644 dlls/devenum/fil_data.idl
Apologies, this isn't quite correct. I'll send an updated patch.