From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/imgfactory.c | 238 +++++++++++++++++++------------- 1 file changed, 140 insertions(+), 98 deletions(-)
diff --git a/dlls/windowscodecs/imgfactory.c b/dlls/windowscodecs/imgfactory.c index a4b8137d35b..676d24134c4 100644 --- a/dlls/windowscodecs/imgfactory.c +++ b/dlls/windowscodecs/imgfactory.c @@ -1244,140 +1244,182 @@ static HRESULT WINAPI ComponentFactory_CreateQueryWriterFromReader(IWICComponent return IWICImagingFactory2_CreateQueryWriterFromReader(&This->IWICImagingFactory2_iface, reader, vendor, writer); }
-static HRESULT WINAPI ComponentFactory_CreateMetadataReader(IWICComponentFactory *iface, - REFGUID format, const GUID *vendor, DWORD options, IStream *stream, IWICMetadataReader **reader) +enum iterator_result { - FIXME("%p,%s,%s,%lx,%p,%p: stub\n", iface, debugstr_guid(format), debugstr_guid(vendor), - options, stream, reader); - return E_NOTIMPL; -} + ITER_SKIP, + ITER_DONE, +};
-static HRESULT WINAPI ComponentFactory_CreateMetadataReaderFromContainer(IWICComponentFactory *iface, - REFGUID format, const GUID *vendor, DWORD options, IStream *stream, IWICMetadataReader **reader) +struct iterator_context { - HRESULT hr; - IEnumUnknown *enumreaders; - IUnknown *unkreaderinfo; + const GUID *format; + const GUID *vendor; + DWORD options; + IStream *stream; + + void **result; +}; + +typedef enum iterator_result (*iterator_func)(IUnknown *item, struct iterator_context *context); + +static enum iterator_result create_metadata_reader_from_container_iterator(IUnknown *item, + struct iterator_context *context) +{ + IWICPersistStream *persist_stream = NULL; IWICMetadataReaderInfo *readerinfo; - IWICPersistStream *wicpersiststream; - ULONG num_fetched; - GUID decoder_vendor; + IWICMetadataReader *reader = NULL; + LARGE_INTEGER zero = {{0}}; BOOL matches; - LARGE_INTEGER zero; - - TRACE("%p,%s,%s,%lx,%p,%p\n", iface, debugstr_guid(format), debugstr_guid(vendor), - options, stream, reader); + HRESULT hr; + GUID guid;
- if (!format || !stream || !reader) - return E_INVALIDARG; + if (FAILED(IUnknown_QueryInterface(item, &IID_IWICMetadataReaderInfo, (void **)&readerinfo))) + return ITER_SKIP;
- zero.QuadPart = 0; + if (context->vendor) + { + hr = IWICMetadataReaderInfo_GetVendorGUID(readerinfo, &guid);
- hr = CreateComponentEnumerator(WICMetadataReader, WICComponentEnumerateDefault, &enumreaders); - if (FAILED(hr)) return hr; + if (FAILED(hr) || !IsEqualIID(context->vendor, &guid)) + { + IWICMetadataReaderInfo_Release(readerinfo); + return ITER_SKIP; + } + }
- *reader = NULL; + hr = IWICMetadataReaderInfo_MatchesPattern(readerinfo, context->format, context->stream, &matches);
-start: - while (!*reader) + if (SUCCEEDED(hr) && matches) { - hr = IEnumUnknown_Next(enumreaders, 1, &unkreaderinfo, &num_fetched); + hr = IStream_Seek(context->stream, zero, STREAM_SEEK_SET, NULL);
- if (hr == S_OK) - { - hr = IUnknown_QueryInterface(unkreaderinfo, &IID_IWICMetadataReaderInfo, (void**)&readerinfo); + if (SUCCEEDED(hr)) + hr = IWICMetadataReaderInfo_CreateInstance(readerinfo, &reader);
- if (SUCCEEDED(hr)) - { - if (vendor) - { - hr = IWICMetadataReaderInfo_GetVendorGUID(readerinfo, &decoder_vendor); + if (SUCCEEDED(hr)) + hr = IWICMetadataReader_QueryInterface(reader, &IID_IWICPersistStream, (void **)&persist_stream);
- if (FAILED(hr) || !IsEqualIID(vendor, &decoder_vendor)) - { - IWICMetadataReaderInfo_Release(readerinfo); - IUnknown_Release(unkreaderinfo); - continue; - } - } + if (SUCCEEDED(hr)) + hr = IWICPersistStream_LoadEx(persist_stream, context->stream, context->vendor, + context->options & WICPersistOptionMask);
- hr = IWICMetadataReaderInfo_MatchesPattern(readerinfo, format, stream, &matches); + if (persist_stream) + IWICPersistStream_Release(persist_stream);
- if (SUCCEEDED(hr) && matches) - { - hr = IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL); + if (SUCCEEDED(hr)) + { + *context->result = reader; + IWICMetadataReaderInfo_Release(readerinfo); + return ITER_DONE; + }
- if (SUCCEEDED(hr)) - hr = IWICMetadataReaderInfo_CreateInstance(readerinfo, reader); + if (reader) + IWICMetadataReader_Release(reader); + }
- if (SUCCEEDED(hr)) - { - hr = IWICMetadataReader_QueryInterface(*reader, &IID_IWICPersistStream, (void**)&wicpersiststream); + IWICMetadataReaderInfo_Release(readerinfo);
- if (SUCCEEDED(hr)) - { - hr = IWICPersistStream_LoadEx(wicpersiststream, - stream, vendor, options & WICPersistOptionMask); + return ITER_SKIP; +}
- IWICPersistStream_Release(wicpersiststream); - } +static HRESULT foreach_component(DWORD mask, iterator_func func, struct iterator_context *context) +{ + enum iterator_result ret; + IEnumUnknown *enumerator; + IUnknown *item; + HRESULT hr;
- if (FAILED(hr)) - { - IWICMetadataReader_Release(*reader); - *reader = NULL; - } - } - } + if (FAILED(hr = CreateComponentEnumerator(mask, WICComponentEnumerateDefault, &enumerator))) + return hr;
- IUnknown_Release(readerinfo); - } + while (IEnumUnknown_Next(enumerator, 1, &item, NULL) == S_OK) + { + *context->result = NULL;
- IUnknown_Release(unkreaderinfo); - } - else - break; + ret = func(item, context); + IUnknown_Release(item); + + if (ret == ITER_SKIP) + continue; + + break; }
- if (!*reader && vendor) + IEnumUnknown_Release(enumerator); + + return *context->result ? S_OK : WINCODEC_ERR_COMPONENTNOTFOUND; +} + +static HRESULT create_unknown_metadata_reader(IStream *stream, DWORD options, IWICMetadataReader **reader) +{ + IWICPersistStream *persist_stream = NULL; + LARGE_INTEGER zero = {{0}}; + HRESULT hr; + + hr = IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL); + + if (SUCCEEDED(hr)) + hr = UnknownMetadataReader_CreateInstance(&IID_IWICMetadataReader, (void **)reader); + + if (SUCCEEDED(hr)) + hr = IWICMetadataReader_QueryInterface(*reader, &IID_IWICPersistStream, (void **)&persist_stream); + + if (SUCCEEDED(hr)) + hr = IWICPersistStream_LoadEx(persist_stream, stream, NULL, options & WICPersistOptionMask); + + if (persist_stream) + IWICPersistStream_Release(persist_stream); + + if (FAILED(hr)) { - vendor = NULL; - IEnumUnknown_Reset(enumreaders); - goto start; + IWICMetadataReader_Release(*reader); + *reader = NULL; }
- IEnumUnknown_Release(enumreaders); + return hr; +}
- if (!*reader && !(options & WICMetadataCreationFailUnknown)) - { - hr = IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL); +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), + options, stream, reader); + return E_NOTIMPL; +}
- if (SUCCEEDED(hr)) - hr = UnknownMetadataReader_CreateInstance(&IID_IWICMetadataReader, (void**)reader); +static HRESULT WINAPI ComponentFactory_CreateMetadataReaderFromContainer(IWICComponentFactory *iface, + REFGUID format, const GUID *vendor, DWORD options, IStream *stream, IWICMetadataReader **reader) +{ + struct iterator_context context = { 0 }; + HRESULT hr;
- if (SUCCEEDED(hr)) - { - hr = IWICMetadataReader_QueryInterface(*reader, &IID_IWICPersistStream, (void**)&wicpersiststream); + TRACE("%p,%s,%s,%lx,%p,%p\n", iface, debugstr_guid(format), debugstr_guid(vendor), + options, stream, reader);
- if (SUCCEEDED(hr)) - { - hr = IWICPersistStream_LoadEx(wicpersiststream, stream, NULL, options & WICPersistOptionMask); + if (!format || !stream || !reader) + return E_INVALIDARG;
- IWICPersistStream_Release(wicpersiststream); - } + context.format = format; + context.vendor = vendor; + context.options = options; + context.stream = stream; + context.result = (void **)reader;
- if (FAILED(hr)) - { - IWICMetadataReader_Release(*reader); - *reader = NULL; - } - } + hr = foreach_component(WICMetadataReader, create_metadata_reader_from_container_iterator, &context); + + if (FAILED(hr) && vendor) + { + context.vendor = NULL; + hr = foreach_component(WICMetadataReader, create_metadata_reader_from_container_iterator, &context); }
- if (*reader) - return S_OK; - else - return WINCODEC_ERR_COMPONENTNOTFOUND; + 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_CreateMetadataWriter(IWICComponentFactory *iface,