Based on a patch by Fabian Maurer.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51748 Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/windowscodecs/metadataquery.c | 120 ++++++++++++++++++++++++++++- 1 file changed, 116 insertions(+), 4 deletions(-)
diff --git a/dlls/windowscodecs/metadataquery.c b/dlls/windowscodecs/metadataquery.c index 29ec6fd5160..7ef2c10cf07 100644 --- a/dlls/windowscodecs/metadataquery.c +++ b/dlls/windowscodecs/metadataquery.c @@ -596,14 +596,126 @@ static HRESULT WINAPI mqr_GetMetadataByName(IWICMetadataQueryReader *iface, LPCW return hr; }
-static HRESULT WINAPI mqr_GetEnumerator(IWICMetadataQueryReader *iface, - IEnumString **ppIEnumString) +struct string_enumerator { - QueryReader *This = impl_from_IWICMetadataQueryReader(iface); - FIXME("(%p,%p)\n", This, ppIEnumString); + IEnumString IEnumString_iface; + LONG ref; +}; + +static struct string_enumerator *impl_from_IEnumString(IEnumString *iface) +{ + return CONTAINING_RECORD(iface, struct string_enumerator, IEnumString_iface); +} + +static HRESULT WINAPI string_enumerator_QueryInterface(IEnumString *iface, REFIID riid, void **ppv) +{ + struct string_enumerator *this = impl_from_IEnumString(iface); + + TRACE("iface %p, riid %s, ppv %p.\n", iface, debugstr_guid(riid), ppv); + + if (IsEqualGUID(riid, &IID_IEnumString) || IsEqualGUID(riid, &IID_IUnknown)) + *ppv = &this->IEnumString_iface; + else + { + WARN("Unknown riid %s.\n", debugstr_guid(riid)); + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef(&this->IEnumString_iface); + return S_OK; +} + +static ULONG WINAPI string_enumerator_AddRef(IEnumString *iface) +{ + struct string_enumerator *this = impl_from_IEnumString(iface); + ULONG ref = InterlockedIncrement(&this->ref); + + TRACE("iface %p, ref %u.\n", iface, ref); + + return ref; +} + +static ULONG WINAPI string_enumerator_Release(IEnumString *iface) +{ + struct string_enumerator *this = impl_from_IEnumString(iface); + ULONG ref = InterlockedDecrement(&this->ref); + + TRACE("iface %p, ref %u.\n", iface, ref); + + if (!ref) + free(this); + + return ref; +} + +static HRESULT WINAPI string_enumerator_Next(IEnumString *iface, ULONG count, LPOLESTR *strings, ULONG *ret) +{ + FIXME("iface %p, count %u, strings %p, ret %p stub.\n", iface, count, strings, ret); + + if (!strings || !ret) + return E_INVALIDARG; + + *ret = 0; + return count ? S_FALSE : S_OK; +} + +static HRESULT WINAPI string_enumerator_Reset(IEnumString *iface) +{ + TRACE("iface %p.\n", iface); + + return S_OK; +} + +static HRESULT WINAPI string_enumerator_Skip(IEnumString *iface, ULONG count) +{ + FIXME("iface %p, count %u stub.\n", iface, count); + + return count ? S_FALSE : S_OK; +} + +static HRESULT WINAPI string_enumerator_Clone(IEnumString *iface, IEnumString **out) +{ + FIXME("iface %p, out %p stub.\n", iface, out); + + *out = NULL; return E_NOTIMPL; }
+static const IEnumStringVtbl string_enumerator_vtbl = +{ + string_enumerator_QueryInterface, + string_enumerator_AddRef, + string_enumerator_Release, + string_enumerator_Next, + string_enumerator_Skip, + string_enumerator_Reset, + string_enumerator_Clone +}; + +static HRESULT string_enumerator_create(IEnumString **enum_string) +{ + struct string_enumerator *object; + + if (!(object = calloc(1, sizeof(*object)))) + return E_OUTOFMEMORY; + + object->IEnumString_iface.lpVtbl = &string_enumerator_vtbl; + object->ref = 1; + + *enum_string = &object->IEnumString_iface; + + return S_OK; +} + +static HRESULT WINAPI mqr_GetEnumerator(IWICMetadataQueryReader *iface, + IEnumString **enum_string) +{ + TRACE("iface %p, enum_string %p.\n", iface, enum_string); + + return string_enumerator_create(enum_string); +} + static IWICMetadataQueryReaderVtbl mqr_vtbl = { mqr_QueryInterface, mqr_AddRef,
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/windowscodecs/metadataquery.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/windowscodecs/metadataquery.c b/dlls/windowscodecs/metadataquery.c index 7ef2c10cf07..ed80d26d54f 100644 --- a/dlls/windowscodecs/metadataquery.c +++ b/dlls/windowscodecs/metadataquery.c @@ -819,9 +819,9 @@ static HRESULT WINAPI mqw_GetContainerFormat(IWICMetadataQueryWriter *iface, GUI
static HRESULT WINAPI mqw_GetEnumerator(IWICMetadataQueryWriter *iface, IEnumString **enum_string) { - FIXME("iface %p, enum_string %p stub.\n", iface, enum_string); + TRACE("iface %p, enum_string %p.\n", iface, enum_string);
- return E_NOTIMPL; + return string_enumerator_create(enum_string); }
static HRESULT WINAPI mqw_GetLocation(IWICMetadataQueryWriter *iface, UINT max_length, WCHAR *namespace, UINT *actual_length)
Signed-off-by: Esme Povirk esme@codeweavers.com
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/windowscodecs/tests/metadata.c | 51 +++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+)
diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index b597e5490c6..bec8bb08c76 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -198,6 +198,13 @@ static const char animatedgif[] = { 0x21,0x01,0x0C,'p','l','a','i','n','t','e','x','t',' ','#','2',0x00,0x3B };
+static ULONG get_refcount(void *iface) +{ + IUnknown *unknown = iface; + IUnknown_AddRef(unknown); + return IUnknown_Release(unknown); +} + static IStream *create_stream(const char *data, int data_size) { HRESULT hr; @@ -3073,6 +3080,9 @@ static void test_metadata_writer(void) IWICBitmapFrameEncode *frameencode; IWICComponentFactory *factory; IWICBitmapEncoder *encoder; + IEnumString *enumstring; + LPOLESTR olestring; + ULONG ref, count; IStream *stream; unsigned int i; HRESULT hr; @@ -3124,6 +3134,47 @@ static void test_metadata_writer(void) IWICComponentFactory_Release(factory); if (querywriter) { + ref = get_refcount(querywriter); + ok(ref == 1, "Got unexpected ref %u, i %u.\n", ref, i); + + hr = IWICMetadataQueryWriter_QueryInterface(querywriter, &IID_IEnumString, (void **)&enumstring); + ok(hr == E_NOINTERFACE, "Got unexpected hr %#x, i %u.\n", hr, i); + + hr = IWICMetadataQueryWriter_GetEnumerator(querywriter, &enumstring); + ok(hr == S_OK, "Got unexpected hr %#x, i %u.\n", hr, i); + + ref = get_refcount(querywriter); + ok(ref == 1, "Got unexpected ref %u, i %u.\n", ref, i); + + hr = IEnumString_Skip(enumstring, 0); + ok(hr == S_OK, "Got unexpected hr %#x, i %u.\n", hr, i); + + count = 0xdeadbeef; + hr = IEnumString_Next(enumstring, 0, NULL, &count); + ok(hr == E_INVALIDARG, "Got unexpected hr %#x, i %u.\n", hr, i); + ok(count == 0xdeadbeef, "Got unexpected count %u, i %u.\n", count, i); + + hr = IEnumString_Next(enumstring, 0, &olestring, &count); + ok(hr == S_OK || hr == WINCODEC_ERR_VALUEOUTOFRANGE, "Got unexpected hr %#x, i %u.\n", hr, i); + + count = 0xdeadbeef; + hr = IEnumString_Next(enumstring, 1, &olestring, &count); + ok(hr == S_OK || hr == S_FALSE, "Got unexpected hr %#x, i %u.\n", hr, i); + ok((hr && !count) || (!hr && count == 1), "Got unexpected hr %#x, count %u, i %u.\n", hr, count, i); + if (count) + { + CoTaskMemFree(olestring); + + /* IEnumString_Skip() crashes at least on Win7 when + * trying to skip past the string count. */ + hr = IEnumString_Reset(enumstring); + ok(hr == S_OK, "Got unexpected hr %#x, i %u.\n", hr, i); + + hr = IEnumString_Skip(enumstring, 1); + ok(hr == S_OK, "Got unexpected hr %#x, i %u.\n", hr, i); + } + IEnumString_Release(enumstring); + IWICMetadataQueryWriter_Release(querywriter); IWICMetadataQueryWriter_Release(querywriter2); IWICMetadataBlockWriter_Release(blockwriter);
Signed-off-by: Esme Povirk esme@codeweavers.com