From 2f2ac792427348b9172a8d269780002a484ab16e Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Fri, 15 May 2020 16:09:19 -0500 Subject: [PATCH] devenum: Return filter data for DMO monikers. Signed-off-by: Zebediah Figura Signed-off-by: Alexandre Julliard --- dlls/devenum/createdevenum.c | 54 +++++++++++--------- dlls/devenum/devenum_private.h | 1 + dlls/devenum/mediacatenum.c | 93 ++++++++++++++++++++++++++++++++++ 3 files changed, 123 insertions(+), 25 deletions(-) diff --git a/dlls/devenum/createdevenum.c b/dlls/devenum/createdevenum.c index a3b9447144a..c72bb683f96 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; - - 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; - - memcpy(array, data, size); - hr = SafeArrayUnaccessData(V_ARRAY(&var)); - if (FAILED(hr)) goto cleanup; - - hr = IPropertyBag_Write(prop_bag, L"FilterData", &var); - if (FAILED(hr)) goto cleanup; - -cleanup: - VariantClear(&var); - CoTaskMemFree(data); IAMFilterData_Release(fildata); + if (FAILED(hr)) + return hr; + + V_VT(var) = VT_ARRAY | VT_UI1; + if (!(V_ARRAY(var) = SafeArrayCreateVector(VT_UI1, 1, size))) + { + VariantClear(var); + CoTaskMemFree(data); + return E_OUTOFMEMORY; + } + + memcpy(V_ARRAY(var)->pvData, data, size); + CoTaskMemFree(data); + return S_OK; +} + +static void write_filter_data(IPropertyBag *prop_bag, REGFILTER2 *rgf) +{ + VARIANT var; + + 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); }