From: Nikolay Sivov nsivov@codeweavers.com
--- dlls/windowscodecs/imgfactory.c | 81 +++++++++++++++++++++++------ dlls/windowscodecs/tests/metadata.c | 32 ++++++++++++ 2 files changed, 97 insertions(+), 16 deletions(-)
diff --git a/dlls/windowscodecs/imgfactory.c b/dlls/windowscodecs/imgfactory.c index 9316beedb04..0608be76c08 100644 --- a/dlls/windowscodecs/imgfactory.c +++ b/dlls/windowscodecs/imgfactory.c @@ -1622,8 +1622,59 @@ static HRESULT WINAPI ComponentFactory_CreateMetadataWriter(IWICComponentFactory return create_metadata_writer(format, vendor, options, writer); }
-static HRESULT WINAPI ComponentFactory_CreateMetadataWriterFromReader(IWICComponentFactory *iface, - IWICMetadataReader *reader, const GUID *vendor, IWICMetadataWriter **out_writer) +static HRESULT create_metadata_writer_from_reader(IWICMetadataReader *reader, const GUID *vendor, + IWICMetadataWriter **out_writer); + +static HRESULT metadata_writer_copy_items_from_reader(IWICMetadataWriter *writer, const GUID *vendor, IWICMetadataReader *reader) +{ + IWICMetadataReader *sub_reader; + IWICMetadataWriter *sub_writer; + PROPVARIANT schema, id, value; + UINT i, count; + HRESULT hr; + + if (FAILED(hr = IWICMetadataReader_GetCount(reader, &count))) + return hr; + + for (i = 0; i < count; ++i) + { + PropVariantInit(&schema); + PropVariantInit(&id); + PropVariantInit(&value); + if (FAILED(hr = IWICMetadataReader_GetValueByIndex(reader, i, &schema, &id, &value))) + break; + + /* Recursively create writers from the nested readers. */ + if (value.vt == VT_UNKNOWN) + { + if (SUCCEEDED(IUnknown_QueryInterface(value.punkVal, &IID_IWICMetadataReader, (void **)&sub_reader))) + { + hr = create_metadata_writer_from_reader(sub_reader, vendor, &sub_writer); + if (SUCCEEDED(hr)) + { + IUnknown_Release(value.punkVal); + value.punkVal = (IUnknown *)sub_writer; + } + + IWICMetadataReader_Release(sub_reader); + } + } + + if (SUCCEEDED(hr)) + hr = IWICMetadataWriter_SetValue(writer, &schema, &id, &value); + + PropVariantClear(&schema); + PropVariantClear(&id); + PropVariantClear(&value); + if (FAILED(hr)) + break; + } + + return hr; +} + +static HRESULT create_metadata_writer_from_reader(IWICMetadataReader *reader, const GUID *vendor, + IWICMetadataWriter **out_writer) { IWICStreamProvider *stream_provider = NULL; IWICMetadataWriter *writer = NULL; @@ -1632,11 +1683,6 @@ static HRESULT WINAPI ComponentFactory_CreateMetadataWriterFromReader(IWICCompon GUID format; HRESULT hr;
- TRACE("%p,%p,%s,%p\n", iface, reader, debugstr_guid(vendor), out_writer); - - if (!reader || !out_writer) - return E_INVALIDARG; - hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
if (SUCCEEDED(hr)) @@ -1683,15 +1729,7 @@ static HRESULT WINAPI ComponentFactory_CreateMetadataWriterFromReader(IWICCompon } else { - UINT count; - - hr = IWICMetadataReader_GetCount(reader, &count); - - if (SUCCEEDED(hr)) - { - if (count) - FIXME("Copy metadata items to the writer.\n"); - } + hr = metadata_writer_copy_items_from_reader(writer, vendor, reader); } }
@@ -1712,6 +1750,17 @@ static HRESULT WINAPI ComponentFactory_CreateMetadataWriterFromReader(IWICCompon return hr; }
+static HRESULT WINAPI ComponentFactory_CreateMetadataWriterFromReader(IWICComponentFactory *iface, + IWICMetadataReader *reader, const GUID *vendor, IWICMetadataWriter **writer) +{ + TRACE("%p,%p,%s,%p\n", iface, reader, debugstr_guid(vendor), writer); + + if (!reader || !writer) + return E_INVALIDARG; + + return create_metadata_writer_from_reader(reader, vendor, writer); +} + static HRESULT WINAPI ComponentFactory_CreateQueryReaderFromBlockReader(IWICComponentFactory *iface, IWICMetadataBlockReader *block_reader, IWICMetadataQueryReader **query_reader) { diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index 922e1738b7a..db16a67f1aa 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -4417,6 +4417,38 @@ static void test_CreateMetadataWriterFromReader(void) IWICMetadataReader_Release(reader); IStream_Release(stream);
+ /* App1, reader without stream caching. */ + stream = create_stream((const char *)&app1_data, sizeof(app1_data)); + hr = IWICComponentFactory_CreateMetadataReader(factory, &GUID_MetadataFormatApp1, + NULL, WICPersistOptionNoCacheStream, stream, &reader); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_persist_options(reader, WICPersistOptionNoCacheStream); + + hr = IWICComponentFactory_CreateMetadataWriterFromReader(factory, reader, NULL, &writer); + 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_MetadataFormatApp1), "Unexpected format %s.\n", wine_dbgstr_guid(&format)); + + hr = IWICMetadataWriter_GetCount(writer, &count); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(count == 1, "Unexpected count %u.\n", count); + + PropVariantInit(&id); + PropVariantInit(&value); + hr = IWICMetadataWriter_GetValueByIndex(writer, 0, NULL, &id, &value); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(id.vt == VT_UI2, "Unexpected id type %u.\n", id.vt); + ok(value.vt == VT_UNKNOWN, "Unexpected value type %u.\n", value.vt); + check_interface(value.punkVal, &IID_IWICMetadataReader, TRUE); + check_interface(value.punkVal, &IID_IWICMetadataWriter, TRUE); + PropVariantClear(&value); + + IWICMetadataWriter_Release(writer); + IWICMetadataReader_Release(reader); + IStream_Release(stream); + /* Big-endian IFD */ data = malloc(sizeof(IFD_data)); memcpy(data, &IFD_data, sizeof(IFD_data));