From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/imgfactory.c | 96 ++++++++++++++++++++++++++++- dlls/windowscodecs/tests/metadata.c | 32 +++++----- 2 files changed, 109 insertions(+), 19 deletions(-)
diff --git a/dlls/windowscodecs/imgfactory.c b/dlls/windowscodecs/imgfactory.c index 676d24134c4..2f5617cedc1 100644 --- a/dlls/windowscodecs/imgfactory.c +++ b/dlls/windowscodecs/imgfactory.c @@ -1322,6 +1322,71 @@ static enum iterator_result create_metadata_reader_from_container_iterator(IUnkn return ITER_SKIP; }
+static enum iterator_result create_metadata_reader_iterator(IUnknown *item, + struct iterator_context *context) +{ + IWICPersistStream *persist_stream = NULL; + IWICMetadataReaderInfo *readerinfo; + IWICMetadataReader *reader = NULL; + LARGE_INTEGER zero = {{0}}; + HRESULT hr; + GUID guid; + + if (FAILED(IUnknown_QueryInterface(item, &IID_IWICMetadataReaderInfo, (void **)&readerinfo))) + return ITER_SKIP; + + if (context->vendor) + { + hr = IWICMetadataReaderInfo_GetVendorGUID(readerinfo, &guid); + + if (FAILED(hr) || !IsEqualIID(context->vendor, &guid)) + { + IWICMetadataReaderInfo_Release(readerinfo); + return ITER_SKIP; + } + } + + hr = IWICMetadataReaderInfo_GetMetadataFormat(readerinfo, &guid); + + if (FAILED(hr) || !IsEqualIID(context->format, &guid)) + { + IWICMetadataReaderInfo_Release(readerinfo); + return ITER_SKIP; + } + + if (SUCCEEDED(hr)) + hr = IWICMetadataReaderInfo_CreateInstance(readerinfo, &reader); + + IWICMetadataReaderInfo_Release(readerinfo); + + if (context->stream) + { + if (SUCCEEDED(hr)) + hr = IStream_Seek(context->stream, zero, STREAM_SEEK_SET, NULL); + + if (SUCCEEDED(hr)) + hr = IWICMetadataReader_QueryInterface(reader, &IID_IWICPersistStream, (void **)&persist_stream); + + if (SUCCEEDED(hr)) + hr = IWICPersistStream_LoadEx(persist_stream, context->stream, context->vendor, + context->options & WICPersistOptionMask); + + if (persist_stream) + IWICPersistStream_Release(persist_stream); + } + + if (SUCCEEDED(hr)) + { + *context->result = reader; + return ITER_DONE; + } + + if (reader) + IWICMetadataReader_Release(reader); + + return ITER_SKIP; +} + static HRESULT foreach_component(DWORD mask, iterator_func func, struct iterator_context *context) { enum iterator_result ret; @@ -1382,9 +1447,36 @@ static HRESULT create_unknown_metadata_reader(IStream *stream, DWORD options, IW static HRESULT WINAPI ComponentFactory_CreateMetadataReader(IWICComponentFactory *iface, REFGUID format, const GUID *vendor, DWORD options, IStream *stream, IWICMetadataReader **reader) { - FIXME("%p,%s,%s,%lx,%p,%p: stub\n", iface, debugstr_guid(format), debugstr_guid(vendor), + struct iterator_context context = { 0 }; + HRESULT hr; + + TRACE("%p,%s,%s,%lx,%p,%p\n", iface, debugstr_guid(format), debugstr_guid(vendor), options, stream, reader); - return E_NOTIMPL; + + if (!format || !reader) + return E_INVALIDARG; + + context.format = format; + context.vendor = vendor; + context.options = options; + context.stream = stream; + context.result = (void **)reader; + + hr = foreach_component(WICMetadataReader, create_metadata_reader_iterator, &context); + + if (FAILED(hr) && vendor) + { + context.vendor = NULL; + hr = foreach_component(WICMetadataReader, create_metadata_reader_iterator, &context); + } + + if (FAILED(hr)) + WARN("Failed to create a metadata reader instance, hr %#lx.\n", hr); + + if (!*reader && !(options & WICMetadataCreationFailUnknown)) + hr = create_unknown_metadata_reader(stream, options, reader); + + return *reader ? S_OK : WINCODEC_ERR_COMPONENTNOTFOUND; }
static HRESULT WINAPI ComponentFactory_CreateMetadataReaderFromContainer(IWICComponentFactory *iface, diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index ca52211eb78..14d24c1d0f9 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -1405,62 +1405,51 @@ static void test_create_reader(void) stream = create_stream(metadata_tEXt, sizeof(metadata_tEXt));
hr = IWICComponentFactory_CreateMetadataReader(factory, NULL, NULL, 0, stream, &reader); - todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
memset(&format, 0xcc, sizeof(format)); hr = IWICComponentFactory_CreateMetadataReader(factory, &format, NULL, 0, stream, &reader); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); -if (SUCCEEDED(hr)) -{ + hr = IWICMetadataReader_GetMetadataFormat(reader, &format); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(IsEqualGUID(&format, &GUID_MetadataFormatUnknown), "Unexpected format %s.\n", wine_dbgstr_guid(&format)); IWICMetadataReader_Release(reader); -}
memset(&format, 0xcc, sizeof(format)); hr = IWICComponentFactory_CreateMetadataReader(factory, &format, NULL, WICMetadataCreationFailUnknown, stream, &reader); - todo_wine ok(hr == WINCODEC_ERR_COMPONENTNOTFOUND, "Unexpected hr %#lx.\n", hr);
hr = IWICComponentFactory_CreateMetadataReader(factory, &GUID_MetadataFormatChunktEXt, NULL, 0, NULL, &reader); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); -if (SUCCEEDED(hr)) -{ + hr = IWICMetadataReader_GetMetadataFormat(reader, &format); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(IsEqualGUID(&format, &GUID_MetadataFormatChunktEXt), "Unexpected format %s.\n", wine_dbgstr_guid(&format)); IWICMetadataReader_Release(reader); -}
pos.QuadPart = 0; hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IWICComponentFactory_CreateMetadataReader(factory, &GUID_MetadataFormatChunktEXt, NULL, 0, stream, NULL); - todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IWICComponentFactory_CreateMetadataReader(factory, &GUID_ContainerFormatPng, NULL, 0, stream, &reader); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); -if (SUCCEEDED(hr)) + hr = IWICMetadataReader_GetMetadataFormat(reader, &format); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(IsEqualGUID(&format, &GUID_MetadataFormatUnknown), "Unexpected format %s.\n", wine_dbgstr_guid(&format)); IWICMetadataReader_Release(reader);
hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IWICComponentFactory_CreateMetadataReader(factory, &GUID_MetadataFormatChunktEXt, NULL, 0, stream, &reader); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
-if (SUCCEEDED(hr)) -{ check_interface(reader, &IID_IWICMetadataReader, TRUE); check_interface(reader, &IID_IWICMetadataWriter, FALSE); check_interface(reader, &IID_IPersist, TRUE); @@ -1477,7 +1466,16 @@ if (SUCCEEDED(hr)) ok(IsEqualGUID(&format, &GUID_MetadataFormatChunktEXt), "Unexpected format %s.\n", wine_dbgstr_guid(&format));
IWICMetadataReader_Release(reader); -} + + /* Invalid vendor. */ + hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IWICComponentFactory_CreateMetadataReader(factory, &GUID_MetadataFormatChunktEXt, &IID_IUnknown, 0, stream, &reader); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IWICMetadataReader_GetMetadataFormat(reader, &format); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(IsEqualGUID(&format, &GUID_MetadataFormatChunktEXt), "Unexpected format %s.\n", wine_dbgstr_guid(&format)); + IWICMetadataReader_Release(reader);
/* Mismatching metadata format. */ hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);