Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/filtermapper.c | 40 ++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+)
diff --git a/dlls/quartz/tests/filtermapper.c b/dlls/quartz/tests/filtermapper.c index 923257bed1e..cdfe964b98d 100644 --- a/dlls/quartz/tests/filtermapper.c +++ b/dlls/quartz/tests/filtermapper.c @@ -27,6 +27,15 @@ #include "initguid.h" #include "wine/fil_data.h"
+static IFilterMapper3 *create_mapper(void) +{ + IFilterMapper3 *ret; + HRESULT hr; + hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterMapper3, (void **)&ret); + ok(hr == S_OK, "Failed to create filter mapper, hr %#x.\n", hr); + return ret; +} + static ULONG get_refcount(void *iface) { IUnknown *unknown = iface; @@ -34,6 +43,36 @@ static ULONG get_refcount(void *iface) return IUnknown_Release(unknown); }
+#define check_interface(a, b, c) check_interface_(__LINE__, a, b, c) +static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported) +{ + IUnknown *iface = iface_ptr; + HRESULT hr, expected_hr; + IUnknown *unk; + + expected_hr = supported ? S_OK : E_NOINTERFACE; + + hr = IUnknown_QueryInterface(iface, iid, (void **)&unk); + ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x, expected %#x.\n", hr, expected_hr); + if (SUCCEEDED(hr)) + IUnknown_Release(unk); +} + +static void test_interfaces(void) +{ + IFilterMapper3 *mapper = create_mapper(); + + check_interface(mapper, &IID_IAMFilterData, TRUE); + check_interface(mapper, &IID_IFilterMapper, TRUE); + check_interface(mapper, &IID_IFilterMapper2, TRUE); + check_interface(mapper, &IID_IFilterMapper3, TRUE); + check_interface(mapper, &IID_IUnknown, TRUE); + + check_interface(mapper, &IID_IFilterGraph, FALSE); + + IFilterMapper3_Release(mapper); +} + /* Helper function, checks if filter with given name was enumerated. */ static BOOL enum_find_filter(const WCHAR *wszFilterName, IEnumMoniker *pEnum) { @@ -624,6 +663,7 @@ START_TEST(filtermapper) { CoInitialize(NULL);
+ test_interfaces(); test_fm2_enummatchingfilters(); test_legacy_filter_registration(); test_ifiltermapper_from_filtergraph();
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/filtermapper.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/dlls/quartz/tests/filtermapper.c b/dlls/quartz/tests/filtermapper.c index cdfe964b98d..62a632f5801 100644 --- a/dlls/quartz/tests/filtermapper.c +++ b/dlls/quartz/tests/filtermapper.c @@ -119,7 +119,7 @@ static void test_fm2_enummatchingfilters(void) IEnumMoniker *pEnum = NULL; BOOL found, registered = TRUE; REGFILTER *regfilter; - ULONG count; + ULONG count, ref;
ZeroMemory(&rgf2, sizeof(rgf2));
@@ -227,6 +227,8 @@ static void test_fm2_enummatchingfilters(void) } IEnumRegFilters_Release(enum_reg); ok(found, "IFilterMapper didn't find filter\n"); + + IFilterMapper_Release(mapper); }
if (pEnum) IEnumMoniker_Release(pEnum); @@ -256,7 +258,8 @@ static void test_fm2_enummatchingfilters(void) out:
if (pEnum) IEnumMoniker_Release(pEnum); - if (pMapper) IFilterMapper2_Release(pMapper); + ref = IFilterMapper2_Release(pMapper); + ok(!ref, "Got outstanding refcount %d.\n", ref); }
static void test_legacy_filter_registration(void)
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/filtermapper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/quartz/filtermapper.c b/dlls/quartz/filtermapper.c index db162c01339..2068131b9eb 100644 --- a/dlls/quartz/filtermapper.c +++ b/dlls/quartz/filtermapper.c @@ -1087,7 +1087,7 @@ static HRESULT WINAPI FilterMapper_EnumMatchingFilters(
if (SUCCEEDED(hr)) { - hr = IEnumRegFiltersImpl_Construct(regfilters, nb_mon, ppEnum); + hr = IEnumRegFiltersImpl_Construct(regfilters, idx, ppEnum); }
for (idx = 0; idx < nb_mon; idx++)
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/devenum/createdevenum.c | 48 ++++++++++-------- dlls/devenum/devenum_private.h | 1 + dlls/devenum/mediacatenum.c | 93 ++++++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+), 22 deletions(-)
diff --git a/dlls/devenum/createdevenum.c b/dlls/devenum/createdevenum.c index 9c3d08cf5e4..91bcfb3b4c0 100644 --- a/dlls/devenum/createdevenum.c +++ b/dlls/devenum/createdevenum.c @@ -351,40 +351,44 @@ static void free_regfilter2(REGFILTER2 *rgf) } }
-static void write_filter_data(IPropertyBag *prop_bag, REGFILTER2 *rgf) +HRESULT create_filter_data(VARIANT *var, REGFILTER2 *rgf) { - BYTE *data = NULL, *array; IAMFilterData *fildata; - SAFEARRAYBOUND sabound; - VARIANT var = {}; + BYTE *data = NULL; ULONG size; HRESULT hr;
hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC, &IID_IAMFilterData, (void **)&fildata); - if (FAILED(hr)) goto cleanup; + if (FAILED(hr)) + return hr;
hr = IAMFilterData_CreateFilterData(fildata, rgf, &data, &size); - if (FAILED(hr)) goto cleanup; + IAMFilterData_Release(fildata); + if (FAILED(hr)) + return hr;
- V_VT(&var) = VT_ARRAY | VT_UI1; - sabound.lLbound = 0; - sabound.cElements = size; - if (!(V_ARRAY(&var) = SafeArrayCreate(VT_UI1, 1, &sabound))) - goto cleanup; - hr = SafeArrayAccessData(V_ARRAY(&var), (void *)&array); - if (FAILED(hr)) goto cleanup; + V_VT(var) = VT_ARRAY | VT_UI1; + if (!(V_ARRAY(var) = SafeArrayCreateVector(VT_UI1, 1, size))) + { + VariantClear(var); + CoTaskMemFree(data); + return E_OUTOFMEMORY; + }
- memcpy(array, data, size); - hr = SafeArrayUnaccessData(V_ARRAY(&var)); - if (FAILED(hr)) goto cleanup; + memcpy(V_ARRAY(var)->pvData, data, size); + CoTaskMemFree(data); + return S_OK; +}
- hr = IPropertyBag_Write(prop_bag, L"FilterData", &var); - if (FAILED(hr)) goto cleanup; +static void write_filter_data(IPropertyBag *prop_bag, REGFILTER2 *rgf) +{ + VARIANT var;
-cleanup: - VariantClear(&var); - CoTaskMemFree(data); - IAMFilterData_Release(fildata); + if (SUCCEEDED(create_filter_data(&var, rgf))) + { + IPropertyBag_Write(prop_bag, L"FilterData", &var); + VariantClear(&var); + } }
static void register_legacy_filters(void) diff --git a/dlls/devenum/devenum_private.h b/dlls/devenum/devenum_private.h index bd018a42a01..15c41afd570 100644 --- a/dlls/devenum/devenum_private.h +++ b/dlls/devenum/devenum_private.h @@ -54,6 +54,7 @@ struct moniker IPropertyBag IPropertyBag_iface; };
+HRESULT create_filter_data(VARIANT *var, REGFILTER2 *rgf) DECLSPEC_HIDDEN; struct moniker *dmo_moniker_create(const GUID class, const GUID clsid) DECLSPEC_HIDDEN; struct moniker *codec_moniker_create(const GUID *class, const WCHAR *name) DECLSPEC_HIDDEN; struct moniker *filter_moniker_create(const GUID *class, const WCHAR *name) DECLSPEC_HIDDEN; diff --git a/dlls/devenum/mediacatenum.c b/dlls/devenum/mediacatenum.c index 85634ead1ad..16b729ab1fd 100644 --- a/dlls/devenum/mediacatenum.c +++ b/dlls/devenum/mediacatenum.c @@ -28,6 +28,35 @@
WINE_DEFAULT_DEBUG_CHANNEL(devenum);
+BOOL array_reserve(void **elements, unsigned int *capacity, unsigned int count, unsigned int size) +{ + unsigned int max_capacity, new_capacity; + void *new_elements; + + if (count <= *capacity) + return TRUE; + + max_capacity = ~0u / size; + if (count > max_capacity) + return FALSE; + + new_capacity = max(8, *capacity); + while (new_capacity < count && new_capacity <= max_capacity / 2) + new_capacity *= 2; + if (new_capacity < count) + new_capacity = count; + + if (!(new_elements = realloc(*elements, new_capacity * size))) + { + ERR("Failed to allocate memory.\n"); + return FALSE; + } + + *elements = new_elements; + *capacity = new_capacity; + return TRUE; +} + typedef struct { IEnumMoniker IEnumMoniker_iface; @@ -106,6 +135,70 @@ static HRESULT WINAPI property_bag_Read(IPropertyBag *iface, } return hr; } + else if (!wcscmp(name, L"FilterData")) + { + REGFILTERPINS2 reg_pins[2] = {{0}}; + REGFILTER2 reg_filter = + { + .dwVersion = 2, + .dwMerit = MERIT_NORMAL + 0x800, + .cPins2 = 2, + .rgPins2 = reg_pins, + }; + + unsigned int count = 1, input_count, output_count, i; + DMO_PARTIAL_MEDIATYPE *types = NULL; + REGPINTYPES *reg_types; + HRESULT hr; + + if (!(types = malloc(2 * count * sizeof(*types)))) + return E_OUTOFMEMORY; + + while ((hr = DMOGetTypes(&moniker->clsid, count, &input_count, types, + count, &output_count, types + count)) == S_FALSE) + { + count *= 2; + if (!(types = realloc(types, count * sizeof(*types)))) + { + free(types); + return E_OUTOFMEMORY; + } + } + if (hr != S_OK) + { + free(types); + return hr; + } + + if (!(reg_types = malloc(2 * count * sizeof(*reg_types)))) + { + free(types); + return hr; + } + + for (i = 0; i < input_count; ++i) + { + reg_types[i].clsMajorType = &types[i].type; + reg_types[i].clsMinorType = &types[i].subtype; + } + for (i = 0; i < output_count; ++i) + { + reg_types[count + i].clsMajorType = &types[count + i].type; + reg_types[count + i].clsMinorType = &types[count + i].subtype; + } + reg_pins[0].cInstances = 1; + reg_pins[0].nMediaTypes = input_count; + reg_pins[0].lpMediaType = reg_types; + reg_pins[1].dwFlags = REG_PINFLAG_B_OUTPUT; + reg_pins[1].cInstances = 1; + reg_pins[1].nMediaTypes = output_count; + reg_pins[1].lpMediaType = reg_types + count; + + hr = create_filter_data(var, ®_filter); + free(reg_types); + free(types); + return hr; + } return HRESULT_FROM_WIN32(ERROR_NOT_FOUND); }
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/Makefile.in | 2 +- dlls/quartz/tests/filtermapper.c | 72 +++++++++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 2 deletions(-)
diff --git a/dlls/quartz/tests/Makefile.in b/dlls/quartz/tests/Makefile.in index 7609f4db6c8..7652baf274e 100644 --- a/dlls/quartz/tests/Makefile.in +++ b/dlls/quartz/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = quartz.dll -IMPORTS = strmbase advapi32 d3d9 msvfw32 ole32 oleaut32 user32 uuid +IMPORTS = strmbase advapi32 d3d9 msdmo msvfw32 ole32 oleaut32 user32 uuid
C_SRCS = \ acmwrapper.c \ diff --git a/dlls/quartz/tests/filtermapper.c b/dlls/quartz/tests/filtermapper.c index 62a632f5801..41b933275d6 100644 --- a/dlls/quartz/tests/filtermapper.c +++ b/dlls/quartz/tests/filtermapper.c @@ -23,10 +23,13 @@ #include "wine/test.h" #include "winbase.h" #include "dshow.h" -#include "winternl.h" +#include "mediaobj.h" #include "initguid.h" +#include "dmo.h" #include "wine/fil_data.h"
+static const GUID testclsid = {0x77777777}; + static IFilterMapper3 *create_mapper(void) { IFilterMapper3 *ret; @@ -662,6 +665,72 @@ static void test_aggregation(void) ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref); }
+static void test_dmo(void) +{ + DMO_PARTIAL_MEDIATYPE mt = {MEDIATYPE_Audio, MEDIASUBTYPE_PCM}; + IEnumRegFilters *enumerator1; + IEnumMoniker *enumerator; + IFilterMapper3 *mapper; + IFilterMapper *mapper1; + REGFILTER *regfilter; + IMoniker *moniker; + WCHAR *name; + HRESULT hr; + BOOL found; + ULONG ref; + + hr = DMORegister(L"dmo test", &testclsid, &DMOCATEGORY_AUDIO_DECODER, 0, 1, &mt, 1, &mt); + if (hr == E_FAIL) + { + skip("Not enough permissions to register DMOs.\n"); + return; + } + ok(hr == S_OK, "Got hr %#x.\n", hr); + + mapper = create_mapper(); + IFilterMapper3_QueryInterface(mapper, &IID_IFilterMapper, (void **)&mapper1); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IFilterMapper3_EnumMatchingFilters(mapper, &enumerator, 0, FALSE, 0, + FALSE, 0, NULL, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + found = FALSE; + while (IEnumMoniker_Next(enumerator, 1, &moniker, NULL) == S_OK) + { + hr = IMoniker_GetDisplayName(moniker, NULL, NULL, &name); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + if (!wcscmp(name, L"@device:dmo:{77777777-0000-0000-0000-000000000000}{57F2DB8B-E6BB-4513-9D43-DCD2A6593125}")) + found = TRUE; + + CoTaskMemFree(name); + IMoniker_Release(moniker); + } + IEnumMoniker_Release(enumerator); + ok(found, "DMO should be enumerated.\n"); + + /* DMOs lack a CLSID property and are therefore not enumerated by IFilterMapper. */ + + hr = IFilterMapper_EnumMatchingFilters(mapper1, &enumerator1, 0, FALSE, + GUID_NULL, GUID_NULL, FALSE, FALSE, GUID_NULL, GUID_NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + while (IEnumRegFilters_Next(enumerator1, 1, ®filter, NULL) == S_OK) + { + ok(!IsEqualGUID(®filter->Clsid, &testclsid), "DMO should not be enumerated.\n"); + ok(wcscmp(regfilter->Name, L"dmo test"), "DMO should not be enumerated.\n"); + } + IEnumRegFilters_Release(enumerator1); + + IFilterMapper_Release(mapper1); + ref = IFilterMapper3_Release(mapper); + ok(!ref, "Got outstanding refcount %d.\n", ref); + + hr = DMOUnregister(&testclsid, &DMOCATEGORY_AUDIO_DECODER); + ok(hr == S_OK, "Got hr %#x.\n", hr); +} + START_TEST(filtermapper) { CoInitialize(NULL); @@ -673,6 +742,7 @@ START_TEST(filtermapper) test_register_filter_with_null_clsMinorType(); test_parse_filter_data(); test_aggregation(); + test_dmo();
CoUninitialize(); }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=71856
Your paranoid android.
=== w8 (32 bit report) ===
quartz: filtermapper.c:721: Test failed: DMO should not be enumerated. filtermapper.c:722: Test failed: DMO should not be enumerated.
=== w1064v1507 (32 bit report) ===
quartz: filtermapper.c:721: Test failed: DMO should not be enumerated. filtermapper.c:722: Test failed: DMO should not be enumerated.
=== w1064v1809 (32 bit report) ===
quartz: filtermapper.c:721: Test failed: DMO should not be enumerated. filtermapper.c:722: Test failed: DMO should not be enumerated.
=== w1064v1809_2scr (32 bit report) ===
quartz: filtermapper.c:721: Test failed: DMO should not be enumerated. filtermapper.c:722: Test failed: DMO should not be enumerated.
=== w1064v1809_ar (32 bit report) ===
quartz: filtermapper.c:721: Test failed: DMO should not be enumerated. filtermapper.c:722: Test failed: DMO should not be enumerated.
=== w1064v1809_he (32 bit report) ===
quartz: filtermapper.c:721: Test failed: DMO should not be enumerated. filtermapper.c:722: Test failed: DMO should not be enumerated.
=== w1064v1809_ja (32 bit report) ===
quartz: filtermapper.c:721: Test failed: DMO should not be enumerated. filtermapper.c:722: Test failed: DMO should not be enumerated.
=== w1064v1809_zh_CN (32 bit report) ===
quartz: filtermapper.c:721: Test failed: DMO should not be enumerated. filtermapper.c:722: Test failed: DMO should not be enumerated.
=== w864 (64 bit report) ===
quartz: filtermapper.c:721: Test failed: DMO should not be enumerated. filtermapper.c:722: Test failed: DMO should not be enumerated.
=== w1064v1507 (64 bit report) ===
quartz: filtermapper.c:721: Test failed: DMO should not be enumerated. filtermapper.c:722: Test failed: DMO should not be enumerated.
=== w1064v1809 (64 bit report) ===
quartz: filtermapper.c:721: Test failed: DMO should not be enumerated. filtermapper.c:722: Test failed: DMO should not be enumerated.