From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/imgfactory.c | 84 ++++++++++++++++++++++++++++- dlls/windowscodecs/tests/metadata.c | 7 +-- 2 files changed, 83 insertions(+), 8 deletions(-)
diff --git a/dlls/windowscodecs/imgfactory.c b/dlls/windowscodecs/imgfactory.c index 7c9fe6a8920..3813843544f 100644 --- a/dlls/windowscodecs/imgfactory.c +++ b/dlls/windowscodecs/imgfactory.c @@ -1399,6 +1399,50 @@ static enum iterator_result create_metadata_reader_iterator(IUnknown *item, return ITER_SKIP; }
+static enum iterator_result create_metadata_writer_iterator(IUnknown *item, + struct iterator_context *context) +{ + IWICMetadataWriterInfo *writerinfo; + IWICMetadataWriter *writer = NULL; + HRESULT hr; + GUID guid; + + if (FAILED(IUnknown_QueryInterface(item, &IID_IWICMetadataWriterInfo, (void **)&writerinfo))) + return ITER_SKIP; + + if (context->vendor) + { + hr = IWICMetadataWriterInfo_GetVendorGUID(writerinfo, &guid); + + if (FAILED(hr) || !IsEqualIID(context->vendor, &guid)) + { + IWICMetadataWriterInfo_Release(writerinfo); + return ITER_SKIP; + } + } + + hr = IWICMetadataWriterInfo_GetMetadataFormat(writerinfo, &guid); + + if (FAILED(hr) || !IsEqualIID(context->format, &guid)) + { + IWICMetadataWriterInfo_Release(writerinfo); + return ITER_SKIP; + } + + if (SUCCEEDED(hr)) + hr = IWICMetadataWriterInfo_CreateInstance(writerinfo, &writer); + + IWICMetadataWriterInfo_Release(writerinfo); + + if (SUCCEEDED(hr)) + { + *context->result = writer; + return ITER_DONE; + } + + return ITER_SKIP; +} + static HRESULT foreach_component(DWORD mask, iterator_func func, struct iterator_context *context) { enum iterator_result ret; @@ -1532,11 +1576,47 @@ static HRESULT WINAPI ComponentFactory_CreateMetadataReaderFromContainer(IWICCom return *reader ? S_OK : WINCODEC_ERR_COMPONENTNOTFOUND; }
+static HRESULT create_metadata_writer(REFGUID format, const GUID *vendor, DWORD options, + IWICMetadataWriter **writer) +{ + struct iterator_context context = { 0 }; + IWICMetadataWriter *object = NULL; + HRESULT hr; + + context.format = format; + context.vendor = vendor; + context.options = options; + context.result = (void **)&object; + + hr = foreach_component(WICMetadataWriter, create_metadata_writer_iterator, &context); + + if (FAILED(hr) && vendor) + { + context.vendor = NULL; + hr = foreach_component(WICMetadataWriter, create_metadata_writer_iterator, &context); + } + + if (FAILED(hr)) + WARN("Failed to create a metadata writer instance, hr %#lx.\n", hr); + + if (!object && !(options & WICMetadataCreationFailUnknown)) + hr = UnknownMetadataWriter_CreateInstance(&IID_IWICMetadataWriter, (void **)&object); + + if (SUCCEEDED(hr)) + *writer = object; + + return object ? S_OK : WINCODEC_ERR_COMPONENTNOTFOUND; +} + static HRESULT WINAPI ComponentFactory_CreateMetadataWriter(IWICComponentFactory *iface, REFGUID format, const GUID *vendor, DWORD options, IWICMetadataWriter **writer) { - FIXME("%p,%s,%s,%lx,%p: stub\n", iface, debugstr_guid(format), debugstr_guid(vendor), options, writer); - return E_NOTIMPL; + TRACE("%p,%s,%s,%lx,%p\n", iface, debugstr_guid(format), debugstr_guid(vendor), options, writer); + + if (!format || !writer) + return E_INVALIDARG; + + return create_metadata_writer(format, vendor, options, writer); }
static HRESULT WINAPI ComponentFactory_CreateMetadataWriterFromReader(IWICComponentFactory *iface, diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index 1ff564d2e80..3141eb412c7 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -4448,13 +4448,7 @@ static void test_CreateMetadataWriter(void) }
hr = IWICComponentFactory_CreateMetadataWriter(factory, &GUID_MetadataFormatChunktEXt, NULL, 0, &writer); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (FAILED(hr)) - { - IWICComponentFactory_Release(factory); - return; - } check_persist_options(writer, 0);
hr = IWICMetadataWriter_QueryInterface(writer, &IID_IWICStreamProvider, (void **)&stream_provider); @@ -4469,6 +4463,7 @@ static void test_CreateMetadataWriter(void)
hr = IWICMetadataWriter_GetMetadataFormat(writer, &format); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine ok(IsEqualGUID(&format, &GUID_MetadataFormatChunktEXt), "Unexpected format %s.\n", wine_dbgstr_guid(&format));
IWICMetadataWriter_Release(writer);
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/imgfactory.c | 2 +- dlls/windowscodecs/metadatahandler.c | 32 +++++++++++++++++++++----- dlls/windowscodecs/tests/metadata.c | 7 ++++++ dlls/windowscodecs/wincodecs_private.h | 2 ++ 4 files changed, 36 insertions(+), 7 deletions(-)
diff --git a/dlls/windowscodecs/imgfactory.c b/dlls/windowscodecs/imgfactory.c index 3813843544f..c941344f1aa 100644 --- a/dlls/windowscodecs/imgfactory.c +++ b/dlls/windowscodecs/imgfactory.c @@ -1576,7 +1576,7 @@ static HRESULT WINAPI ComponentFactory_CreateMetadataReaderFromContainer(IWICCom return *reader ? S_OK : WINCODEC_ERR_COMPONENTNOTFOUND; }
-static HRESULT create_metadata_writer(REFGUID format, const GUID *vendor, DWORD options, +HRESULT create_metadata_writer(REFGUID format, const GUID *vendor, DWORD options, IWICMetadataWriter **writer) { struct iterator_context context = { 0 }; diff --git a/dlls/windowscodecs/metadatahandler.c b/dlls/windowscodecs/metadatahandler.c index 469fdf9b8ca..d464472b48e 100644 --- a/dlls/windowscodecs/metadatahandler.c +++ b/dlls/windowscodecs/metadatahandler.c @@ -871,11 +871,10 @@ static HRESULT create_stream_wrapper(IStream *input, ULONG offset, IStream **wra }
static HRESULT load_IFD_entry(IStream *input, const GUID *vendor, DWORD options, const struct IFD_entry *entry, - MetadataItem *item, BOOL resolve_pointer_tags) + MetadataItem *item, bool resolve_pointer_tags, bool is_writer) { BOOL native_byte_order = !(options & WICPersistOptionBigEndian); ULONG count, value, i, bytesread; - IWICMetadataReader *sub_reader; IStream *sub_stream; SHORT type; LARGE_INTEGER pos; @@ -1154,6 +1153,9 @@ static HRESULT load_IFD_entry(IStream *input, const GUID *vendor, DWORD options, { case IFD_EXIF_TAG: case IFD_GPS_TAG: + { + IWICPersistStream *persist_stream = NULL; + IWICMetadataReader *sub_reader;
if (!resolve_pointer_tags) break; @@ -1168,8 +1170,25 @@ static HRESULT load_IFD_entry(IStream *input, const GUID *vendor, DWORD options, hr = IStream_Seek(sub_stream, pos, STREAM_SEEK_SET, NULL);
if (SUCCEEDED(hr)) - hr = create_metadata_reader(item->id.uiVal == IFD_EXIF_TAG ? &GUID_MetadataFormatExif : &GUID_MetadataFormatGps, - vendor, options | WICMetadataCreationFailUnknown, sub_stream, &sub_reader); + { + const GUID *format = item->id.uiVal == IFD_EXIF_TAG ? &GUID_MetadataFormatExif : &GUID_MetadataFormatGps; + + if (is_writer) + hr = create_metadata_writer(format, vendor, options | WICMetadataCreationFailUnknown, + (IWICMetadataWriter **)&sub_reader); + else + hr = create_metadata_reader(format, vendor, options | WICMetadataCreationFailUnknown, + NULL, &sub_reader); + } + + if (SUCCEEDED(hr)) + hr = IWICMetadataReader_QueryInterface(sub_reader, &IID_IWICPersistStream, (void **)&persist_stream); + + if (SUCCEEDED(hr)) + hr = IWICPersistStream_LoadEx(persist_stream, sub_stream, vendor, options); + + if (persist_stream) + IWICPersistStream_Release(persist_stream);
if (SUCCEEDED(hr)) { @@ -1181,6 +1200,7 @@ static HRESULT load_IFD_entry(IStream *input, const GUID *vendor, DWORD options, IStream_Release(sub_stream);
break; + } default: break; } @@ -1189,7 +1209,7 @@ static HRESULT load_IFD_entry(IStream *input, const GUID *vendor, DWORD options, }
static HRESULT load_ifd_metadata_internal(IStream *input, const GUID *vendor, - DWORD persist_options, bool resolve_pointer_tags, bool writer, MetadataItem **items, DWORD *item_count) + DWORD persist_options, bool resolve_pointer_tags, bool is_writer, MetadataItem **items, DWORD *item_count) { HRESULT hr; MetadataItem *result; @@ -1268,7 +1288,7 @@ static HRESULT load_ifd_metadata_internal(IStream *input, const GUID *vendor,
for (i = 0; i < count; i++) { - hr = load_IFD_entry(input, vendor, persist_options, &entry[i], &result[i], resolve_pointer_tags); + hr = load_IFD_entry(input, vendor, persist_options, &entry[i], &result[i], resolve_pointer_tags, is_writer); if (FAILED(hr)) { free(entry); diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index 3141eb412c7..736923b8146 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -4485,12 +4485,19 @@ static void test_CreateMetadataWriter(void) hr = IWICComponentFactory_CreateMetadataWriter(factory, &GUID_MetadataFormatApp1, NULL, 0, &writer); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); check_persist_options(writer, 0); + hr = IWICMetadataWriter_GetMetadataFormat(writer, &format); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine + ok(IsEqualGUID(&format, &GUID_MetadataFormatApp1), "Unexpected format %s.\n", wine_dbgstr_guid(&format)); IWICMetadataWriter_Release(writer);
/* Ifd */ hr = IWICComponentFactory_CreateMetadataWriter(factory, &GUID_MetadataFormatIfd, NULL, 0, &writer); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); check_persist_options(writer, 0); + hr = IWICMetadataWriter_GetMetadataFormat(writer, &format); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(IsEqualGUID(&format, &GUID_MetadataFormatIfd), "Unexpected format %s.\n", wine_dbgstr_guid(&format)); IWICMetadataWriter_Release(writer);
IWICComponentFactory_Release(factory); diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h index f23ec9a85ee..028c167687d 100644 --- a/dlls/windowscodecs/wincodecs_private.h +++ b/dlls/windowscodecs/wincodecs_private.h @@ -326,6 +326,8 @@ void CDECL decoder_destroy(struct decoder *This);
HRESULT create_metadata_reader(REFGUID format, const GUID *vendor, DWORD options, IStream *stream, IWICMetadataReader **reader); +HRESULT create_metadata_writer(REFGUID format, const GUID *vendor, DWORD options, + IWICMetadataWriter **writer);
struct encoder_funcs;
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/clsfactory.c | 1 + dlls/windowscodecs/metadatahandler.c | 90 ++++++++++++++----- dlls/windowscodecs/regsvr.c | 9 ++ dlls/windowscodecs/tests/metadata.c | 3 - dlls/windowscodecs/wincodecs_private.h | 1 + dlls/windowscodecs/windowscodecs_wincodec.idl | 7 ++ 6 files changed, 87 insertions(+), 24 deletions(-)
diff --git a/dlls/windowscodecs/clsfactory.c b/dlls/windowscodecs/clsfactory.c index 5e8912db26a..a306d4fc7d6 100644 --- a/dlls/windowscodecs/clsfactory.c +++ b/dlls/windowscodecs/clsfactory.c @@ -70,6 +70,7 @@ static const classinfo wic_classes[] = { {&CLSID_WICExifMetadataReader, ExifMetadataReader_CreateInstance}, {&CLSID_WICExifMetadataWriter, ExifMetadataWriter_CreateInstance}, {&CLSID_WICApp1MetadataReader, App1MetadataReader_CreateInstance}, + {&CLSID_WICApp1MetadataWriter, App1MetadataWriter_CreateInstance}, {&CLSID_WICPngChrmMetadataReader, PngChrmReader_CreateInstance}, {&CLSID_WICPngGamaMetadataReader, PngGamaReader_CreateInstance}, {&CLSID_WICPngHistMetadataReader, PngHistReader_CreateInstance}, diff --git a/dlls/windowscodecs/metadatahandler.c b/dlls/windowscodecs/metadatahandler.c index d464472b48e..7e00f678e4e 100644 --- a/dlls/windowscodecs/metadatahandler.c +++ b/dlls/windowscodecs/metadatahandler.c @@ -870,6 +870,41 @@ static HRESULT create_stream_wrapper(IStream *input, ULONG offset, IStream **wra return hr; }
+static HRESULT create_metadata_handler(IStream *stream, const GUID *format, const GUID *vendor, + DWORD options, bool is_writer, IWICMetadataReader **handler) +{ + IWICPersistStream *persist_stream = NULL; + IWICMetadataReader *reader = NULL; + HRESULT hr; + + if (is_writer) + hr = create_metadata_writer(format, vendor, options | WICMetadataCreationFailUnknown, + (IWICMetadataWriter **)&reader); + else + hr = create_metadata_reader(format, vendor, options | WICMetadataCreationFailUnknown, + NULL, &reader); + + if (SUCCEEDED(hr)) + hr = IWICMetadataReader_QueryInterface(reader, &IID_IWICPersistStream, (void **)&persist_stream); + + if (SUCCEEDED(hr)) + hr = IWICPersistStream_LoadEx(persist_stream, stream, vendor, options); + + if (persist_stream) + IWICPersistStream_Release(persist_stream); + + if (SUCCEEDED(hr)) + { + *handler = reader; + IWICMetadataReader_AddRef(*handler); + } + + if (reader) + IWICMetadataReader_Release(reader); + + return hr; +} + static HRESULT load_IFD_entry(IStream *input, const GUID *vendor, DWORD options, const struct IFD_entry *entry, MetadataItem *item, bool resolve_pointer_tags, bool is_writer) { @@ -1154,8 +1189,7 @@ static HRESULT load_IFD_entry(IStream *input, const GUID *vendor, DWORD options, case IFD_EXIF_TAG: case IFD_GPS_TAG: { - IWICPersistStream *persist_stream = NULL; - IWICMetadataReader *sub_reader; + IWICMetadataReader *sub_reader = NULL;
if (!resolve_pointer_tags) break; @@ -1173,23 +1207,10 @@ static HRESULT load_IFD_entry(IStream *input, const GUID *vendor, DWORD options, { const GUID *format = item->id.uiVal == IFD_EXIF_TAG ? &GUID_MetadataFormatExif : &GUID_MetadataFormatGps;
- if (is_writer) - hr = create_metadata_writer(format, vendor, options | WICMetadataCreationFailUnknown, - (IWICMetadataWriter **)&sub_reader); - else - hr = create_metadata_reader(format, vendor, options | WICMetadataCreationFailUnknown, - NULL, &sub_reader); + hr = create_metadata_handler(sub_stream, format, vendor, options | WICMetadataCreationFailUnknown, + is_writer, &sub_reader); }
- if (SUCCEEDED(hr)) - hr = IWICMetadataReader_QueryInterface(sub_reader, &IID_IWICPersistStream, (void **)&persist_stream); - - if (SUCCEEDED(hr)) - hr = IWICPersistStream_LoadEx(persist_stream, sub_stream, vendor, options); - - if (persist_stream) - IWICPersistStream_Release(persist_stream); - if (SUCCEEDED(hr)) { item->value.vt = VT_UNKNOWN; @@ -1351,10 +1372,11 @@ static HRESULT LoadGpsMetadataWriter(IStream *input, const GUID *vendor, return load_ifd_metadata_internal(input, vendor, options, false, true, items, item_count); }
-static HRESULT LoadApp1Metadata(IStream *input, const GUID *vendor, DWORD options, MetadataItem **items, DWORD *item_count) +static HRESULT load_app1_metadata_internal(IStream *input, const GUID *vendor, DWORD options, + bool is_writer, MetadataItem **items, DWORD *item_count) { static const char exif_header[] = {'E','x','i','f',0,0}; - IWICMetadataReader *ifd_reader; + IWICMetadataReader *ifd_reader = NULL; BOOL native_byte_order; LARGE_INTEGER move;
@@ -1411,7 +1433,9 @@ static HRESULT LoadApp1Metadata(IStream *input, const GUID *vendor, DWORD option return hr; }
- hr = create_metadata_reader(&GUID_MetadataFormatIfd, vendor, options, ifd_stream, &ifd_reader); + if (SUCCEEDED(hr)) + hr = create_metadata_handler(ifd_stream, &GUID_MetadataFormatIfd, vendor, options, is_writer, &ifd_reader); + IStream_Release(ifd_stream);
if (FAILED(hr)) @@ -1435,6 +1459,18 @@ static HRESULT LoadApp1Metadata(IStream *input, const GUID *vendor, DWORD option return S_OK; }
+static HRESULT LoadApp1MetadataReader(IStream *input, const GUID *vendor, DWORD options, + MetadataItem **items, DWORD *item_count) +{ + return load_app1_metadata_internal(input, vendor, options, false, items, item_count); +} + +static HRESULT LoadApp1MetadataWriter(IStream *input, const GUID *vendor, DWORD options, + MetadataItem **items, DWORD *item_count) +{ + return load_app1_metadata_internal(input, vendor, options, true, items, item_count); +} + static const MetadataHandlerVtbl IfdMetadataReader_Vtbl = { 0, &CLSID_WICIfdMetadataReader, @@ -1510,10 +1546,22 @@ static const MetadataHandlerVtbl App1MetadataReader_Vtbl = { 0, &CLSID_WICApp1MetadataReader, - LoadApp1Metadata + LoadApp1MetadataReader };
HRESULT App1MetadataReader_CreateInstance(REFIID iid, void **ppv) { return MetadataReader_Create(&App1MetadataReader_Vtbl, iid, ppv); } + +static const MetadataHandlerVtbl App1MetadataWriter_Vtbl = +{ + .is_writer = true, + &CLSID_WICApp1MetadataWriter, + LoadApp1MetadataWriter +}; + +HRESULT App1MetadataWriter_CreateInstance(REFIID iid, void **ppv) +{ + return MetadataReader_Create(&App1MetadataWriter_Vtbl, iid, ppv); +} diff --git a/dlls/windowscodecs/regsvr.c b/dlls/windowscodecs/regsvr.c index 03e1cd19c47..94a1fb7d070 100644 --- a/dlls/windowscodecs/regsvr.c +++ b/dlls/windowscodecs/regsvr.c @@ -2119,6 +2119,15 @@ static struct regsvr_metadatawriter const metadatawriters_list[] = &GUID_VendorMicrosoft, &GUID_MetadataFormatIfd, }, + { + &CLSID_WICApp1MetadataWriter, + "The Wine Project", + "App1 Metadata Writer", + "1.0.0.0", + "1.0.0.0", + &GUID_VendorMicrosoft, + &GUID_MetadataFormatApp1, + }, { NULL } /* list terminator */ };
diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index 736923b8146..61a3fb42a96 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -4221,9 +4221,7 @@ static void test_metadata_App1(void)
hr = CoCreateInstance(&CLSID_WICApp1MetadataWriter, NULL, CLSCTX_INPROC_SERVER, &IID_IWICMetadataWriter, (void **)&writer); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (FAILED(hr)) return;
check_interface(writer, &IID_IWICMetadataWriter, TRUE); check_interface(writer, &IID_IWICMetadataReader, TRUE); @@ -4487,7 +4485,6 @@ static void test_CreateMetadataWriter(void) check_persist_options(writer, 0); hr = IWICMetadataWriter_GetMetadataFormat(writer, &format); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(IsEqualGUID(&format, &GUID_MetadataFormatApp1), "Unexpected format %s.\n", wine_dbgstr_guid(&format)); IWICMetadataWriter_Release(writer);
diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h index 028c167687d..bbdb4c36f73 100644 --- a/dlls/windowscodecs/wincodecs_private.h +++ b/dlls/windowscodecs/wincodecs_private.h @@ -226,6 +226,7 @@ extern HRESULT GpsMetadataWriter_CreateInstance(REFIID iid, void **ppv); extern HRESULT ExifMetadataReader_CreateInstance(REFIID iid, void **ppv); extern HRESULT ExifMetadataWriter_CreateInstance(REFIID iid, void **ppv); extern HRESULT App1MetadataReader_CreateInstance(REFIID iid, void **ppv); +extern HRESULT App1MetadataWriter_CreateInstance(REFIID iid, void **ppv); extern HRESULT PngChrmReader_CreateInstance(REFIID iid, void** ppv); extern HRESULT PngGamaReader_CreateInstance(REFIID iid, void** ppv); extern HRESULT PngHistReader_CreateInstance(REFIID iid, void** ppv); diff --git a/dlls/windowscodecs/windowscodecs_wincodec.idl b/dlls/windowscodecs/windowscodecs_wincodec.idl index 438a39fd2be..84bc2d73f79 100644 --- a/dlls/windowscodecs/windowscodecs_wincodec.idl +++ b/dlls/windowscodecs/windowscodecs_wincodec.idl @@ -209,6 +209,13 @@ coclass WICExifMetadataWriter { interface IWICMetadataWriter; } ] coclass WICApp1MetadataReader { interface IWICMetadataReader; }
+[ + helpstring("WIC App1 Metadata Writer"), + threading(both), + uuid(ee366069-1832-420f-b381-0479ad066f19) +] +coclass WICApp1MetadataWriter { interface IWICMetadataWriter; } + [ helpstring("WIC Png cHRM Metadata Reader"), threading(both),
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/imgfactory.c | 3 +++ dlls/windowscodecs/tests/metadata.c | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/dlls/windowscodecs/imgfactory.c b/dlls/windowscodecs/imgfactory.c index c941344f1aa..e0b863f5cd4 100644 --- a/dlls/windowscodecs/imgfactory.c +++ b/dlls/windowscodecs/imgfactory.c @@ -1616,6 +1616,9 @@ static HRESULT WINAPI ComponentFactory_CreateMetadataWriter(IWICComponentFactory if (!format || !writer) return E_INVALIDARG;
+ if (options & WICPersistOptionMask) + return E_INVALIDARG; + return create_metadata_writer(format, vendor, options, writer); }
diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index 61a3fb42a96..9ad9e38372c 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -4423,6 +4423,7 @@ static void test_CreateMetadataWriter(void) { &GUID_MetadataFormatIfd, WICPersistOptionNoCacheStream }, { &GUID_MetadataFormatChunktEXt, WICPersistOptionNoCacheStream }, { &GUID_MetadataFormatApp1, 0x100 }, + { &GUID_MetadataFormatApp1, 0x1000 }, }; IWICStreamProvider *stream_provider; IWICComponentFactory *factory; @@ -4440,9 +4441,10 @@ static void test_CreateMetadataWriter(void) { const struct options_test *test = &options_tests[i];
+ writer = (void *)0xdeadbeef; hr = IWICComponentFactory_CreateMetadataWriter(factory, test->clsid, NULL, test->options, &writer); - todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + ok(writer == (void *)0xdeadbeef, "Unexpected value %p.\n", writer); }
hr = IWICComponentFactory_CreateMetadataWriter(factory, &GUID_MetadataFormatChunktEXt, NULL, 0, &writer);
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/imgfactory.c | 89 +++++++++++++++++++++++++- dlls/windowscodecs/metadatahandler.c | 2 +- dlls/windowscodecs/tests/metadata.c | 37 ++++++++--- dlls/windowscodecs/wincodecs_private.h | 2 + 4 files changed, 116 insertions(+), 14 deletions(-)
diff --git a/dlls/windowscodecs/imgfactory.c b/dlls/windowscodecs/imgfactory.c index e0b863f5cd4..9316beedb04 100644 --- a/dlls/windowscodecs/imgfactory.c +++ b/dlls/windowscodecs/imgfactory.c @@ -1623,10 +1623,93 @@ static HRESULT WINAPI ComponentFactory_CreateMetadataWriter(IWICComponentFactory }
static HRESULT WINAPI ComponentFactory_CreateMetadataWriterFromReader(IWICComponentFactory *iface, - IWICMetadataReader *reader, const GUID *vendor, IWICMetadataWriter **writer) + IWICMetadataReader *reader, const GUID *vendor, IWICMetadataWriter **out_writer) { - FIXME("%p,%p,%s,%p: stub\n", iface, reader, debugstr_guid(vendor), writer); - return E_NOTIMPL; + IWICStreamProvider *stream_provider = NULL; + IWICMetadataWriter *writer = NULL; + IStream *stream = NULL; + DWORD options = 0; + 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)) + hr = create_metadata_writer(&format, vendor, 0, &writer); + + if (SUCCEEDED(hr)) + hr = IWICMetadataReader_QueryInterface(reader, &IID_IWICStreamProvider, (void **)&stream_provider); + + if (SUCCEEDED(hr)) + { + IStream *cached_stream = NULL; + + hr = IWICStreamProvider_GetStream(stream_provider, &cached_stream); + + /* Reader does not have to provide a stream. */ + if (hr == WINCODEC_ERR_STREAMNOTAVAILABLE) + { + hr = S_OK; + } + + if (cached_stream) + { + hr = create_stream_wrapper(cached_stream, 0, &stream); + IStream_Release(cached_stream); + } + } + + if (SUCCEEDED(hr)) + hr = IWICStreamProvider_GetPersistOptions(stream_provider, &options); + + if (SUCCEEDED(hr)) + { + if (stream) + { + IWICPersistStream *persist_stream; + + /* TODO: probably need to check for a dirty stream */ + + if (SUCCEEDED(hr = IWICMetadataWriter_QueryInterface(writer, &IID_IWICPersistStream, (void **)&persist_stream))) + { + hr = IWICPersistStream_LoadEx(persist_stream, stream, vendor, options); + IWICPersistStream_Release(persist_stream); + } + } + else + { + UINT count; + + hr = IWICMetadataReader_GetCount(reader, &count); + + if (SUCCEEDED(hr)) + { + if (count) + FIXME("Copy metadata items to the writer.\n"); + } + } + } + + if (stream_provider) + IWICStreamProvider_Release(stream_provider); + + if (SUCCEEDED(hr)) + { + *out_writer = writer; + IWICMetadataWriter_AddRef(*out_writer); + } + + if (writer) + IWICMetadataWriter_Release(writer); + if (stream) + IStream_Release(stream); + + return hr; }
static HRESULT WINAPI ComponentFactory_CreateQueryReaderFromBlockReader(IWICComponentFactory *iface, diff --git a/dlls/windowscodecs/metadatahandler.c b/dlls/windowscodecs/metadatahandler.c index 7e00f678e4e..71f81900395 100644 --- a/dlls/windowscodecs/metadatahandler.c +++ b/dlls/windowscodecs/metadatahandler.c @@ -847,7 +847,7 @@ static int tag_to_vt(SHORT tag) return (tag > 0 && tag <= 13) ? tag2vt[tag] : VT_BLOB; }
-static HRESULT create_stream_wrapper(IStream *input, ULONG offset, IStream **wrapper) +HRESULT create_stream_wrapper(IStream *input, ULONG offset, IStream **wrapper) { ULARGE_INTEGER start, maxsize; IWICStream *wic_stream = NULL; diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index 9ad9e38372c..7904547114b 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -4111,6 +4111,7 @@ static void test_metadata_App1(void)
hr = get_persist_stream(ifd_reader, &stream2); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_interface(stream2, &IID_IWICStream, TRUE); ok(!!stream2 && app1_stream != stream2, "Unexpected stream.\n"); IStream_Release(stream2);
@@ -4158,6 +4159,7 @@ static void test_metadata_App1(void)
hr = get_persist_stream(exif_reader, &stream2); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_interface(stream2, &IID_IWICStream, TRUE); ok(!!stream2 && stream2 != app1_stream, "Unexpected stream.\n"); IStream_Release(stream2);
@@ -4195,6 +4197,7 @@ static void test_metadata_App1(void)
hr = get_persist_stream(gps_reader, &stream2); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_interface(stream2, &IID_IWICStream, TRUE); ok(!!stream2 && stream2 != app1_stream, "Unexpected stream.\n"); IStream_Release(stream2);
@@ -4256,14 +4259,7 @@ static void test_CreateMetadataWriterFromReader(void) check_persist_options(reader, 0);
hr = IWICComponentFactory_CreateMetadataWriterFromReader(factory, reader, NULL, &writer); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (FAILED(hr)) - { - IWICMetadataReader_Release(reader); - IWICComponentFactory_Release(factory); - return; - }
IWICMetadataReader_Release(reader);
@@ -4276,7 +4272,6 @@ static void test_CreateMetadataWriterFromReader(void) NULL, 0, stream, &reader); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); check_persist_options(reader, 0); - IStream_Release(stream);
hr = IWICComponentFactory_CreateMetadataWriterFromReader(factory, NULL, NULL, NULL); ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); @@ -4309,6 +4304,7 @@ static void test_CreateMetadataWriterFromReader(void)
hr = IWICMetadataWriter_GetMetadataFormat(writer, &format); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine ok(IsEqualGUID(&format, &GUID_MetadataFormatChunktEXt), "Unexpected format %s.\n", wine_dbgstr_guid(&format));
hr = IWICMetadataWriter_GetCount(writer, &count); @@ -4319,15 +4315,26 @@ static void test_CreateMetadataWriterFromReader(void) PropVariantInit(&value); hr = IWICMetadataWriter_GetValueByIndex(writer, 0, NULL, &id, &value); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine ok(id.vt == VT_LPSTR, "Unexpected id type %u.\n", id.vt); - ok(!strcmp(id.pszVal, "winetest"), "Unexpected id %s.\n", wine_dbgstr_a(id.pszVal)); + if (id.vt == VT_LPSTR) + ok(!strcmp(id.pszVal, "winetest"), "Unexpected id %s.\n", wine_dbgstr_a(id.pszVal)); + todo_wine ok(value.vt == VT_LPSTR, "Unexpected value type %u.\n", value.vt); - ok(!strcmp(value.pszVal, "value"), "Unexpected value %s.\n", wine_dbgstr_a(value.pszVal)); + if (value.vt == VT_LPSTR) + ok(!strcmp(value.pszVal, "value"), "Unexpected value %s.\n", wine_dbgstr_a(value.pszVal)); PropVariantClear(&id); PropVariantClear(&value);
+ hr = get_persist_stream(writer, &stream2); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(stream2 != stream, "Unexpected stream.\n"); + check_interface(stream2, &IID_IWICStream, TRUE); + IStream_Release(stream2); + IWICMetadataWriter_Release(writer); IWICMetadataReader_Release(reader); + IStream_Release(stream);
/* App1 reader */ stream = create_stream((const char *)&app1_data, sizeof(app1_data)); @@ -4378,6 +4385,7 @@ static void test_CreateMetadataWriterFromReader(void) hr = get_persist_stream(writer, &stream2); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(stream2 != stream, "Unexpected stream.\n"); + check_interface(stream2, &IID_IWICStream, TRUE); IStream_Release(stream2);
IWICMetadataWriter_Release(writer); @@ -4397,9 +4405,18 @@ static void test_CreateMetadataWriterFromReader(void) check_persist_options(reader, WICPersistOptionBigEndian); free(data);
+ hr = IWICMetadataReader_GetMetadataFormat(reader, &format); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(IsEqualGUID(&format, &GUID_MetadataFormatIfd), "Unexpected format %s.\n", wine_dbgstr_guid(&format)); + hr = IWICComponentFactory_CreateMetadataWriterFromReader(factory, reader, NULL, &writer); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); check_persist_options(writer, WICPersistOptionBigEndian); + + hr = IWICMetadataWriter_GetMetadataFormat(writer, &format); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(IsEqualGUID(&format, &GUID_MetadataFormatIfd), "Unexpected format %s.\n", wine_dbgstr_guid(&format)); + IWICMetadataWriter_Release(writer);
IWICMetadataReader_Release(reader); diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h index bbdb4c36f73..9858a1fdebb 100644 --- a/dlls/windowscodecs/wincodecs_private.h +++ b/dlls/windowscodecs/wincodecs_private.h @@ -164,6 +164,8 @@ extern HRESULT ColorContext_Create(IWICColorContext **context); extern HRESULT ColorTransform_Create(IWICColorTransform **transform); extern HRESULT BitmapClipper_Create(IWICBitmapClipper **clipper);
+extern HRESULT create_stream_wrapper(IStream *input, ULONG offset, IStream **wrapper); + extern HRESULT copy_pixels(UINT bpp, const BYTE *srcbuffer, UINT srcwidth, UINT srcheight, INT srcstride, const WICRect *rc, UINT dststride, UINT dstbuffersize, BYTE *dstbuffer);
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/tests/metadata.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index 7904547114b..253a525c5c9 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -4047,9 +4047,11 @@ app1_data = static void test_metadata_App1(void) { IWICMetadataReader *reader, *ifd_reader, *exif_reader, *gps_reader; + IWICEnumMetadataItem *enumerator; IStream *app1_stream, *stream2; IWICMetadataWriter *writer; PROPVARIANT id, value; + ULONG fetched; GUID format; HRESULT hr; UINT count; @@ -4088,6 +4090,29 @@ static void test_metadata_App1(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(count == 1, "Unexpected count %u.\n", count);
+ /* Enumerator returns top level item. */ + hr = IWICMetadataReader_GetEnumerator(reader, &enumerator); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + PropVariantInit(&id); + PropVariantInit(&value); + hr = IWICEnumMetadataItem_Next(enumerator, 1, NULL, &id, &value, &fetched); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(fetched == 1, "Unexpected count %lu.\n", fetched); + ok(id.vt == VT_UI2, "Unexpected id type: %u.\n", id.vt); + ok(id.uiVal == 0, "Unexpected id %u.\n", id.uiVal); + ok(value.vt == VT_UNKNOWN, "Unexpected value type: %u.\n", value.vt); + ok(!!value.punkVal, "Unexpected value.\n"); + PropVariantClear(&value); + + PropVariantInit(&id); + PropVariantInit(&value); + hr = IWICEnumMetadataItem_Next(enumerator, 1, NULL, &id, &value, &fetched); + ok(hr == S_FALSE, "Unexpected hr %#lx.\n", hr); + ok(!fetched, "Unexpected count %lu.\n", fetched); + + IWICEnumMetadataItem_Release(enumerator); + PropVariantInit(&id); PropVariantInit(&value); hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, &id, &value);
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/metadatahandler.c | 88 +++++++++++++++++++---- dlls/windowscodecs/tests/metadata.c | 103 ++++++++++++++++++++++++++- 2 files changed, 174 insertions(+), 17 deletions(-)
diff --git a/dlls/windowscodecs/metadatahandler.c b/dlls/windowscodecs/metadatahandler.c index 71f81900395..7214ea27a16 100644 --- a/dlls/windowscodecs/metadatahandler.c +++ b/dlls/windowscodecs/metadatahandler.c @@ -224,12 +224,32 @@ static HRESULT WINAPI MetadataHandler_GetValueByIndex(IWICMetadataWriter *iface, return hr; }
+static MetadataItem *metadatahandler_get_item(MetadataHandler *handler, const PROPVARIANT *schema, + const PROPVARIANT *id) +{ + UINT i; + + for (i = 0; i < handler->item_count; i++) + { + if (schema && handler->items[i].schema.vt != VT_EMPTY) + { + if (PropVariantCompareEx(schema, &handler->items[i].schema, 0, PVCF_USESTRCMPI) != 0) continue; + } + + if (PropVariantCompareEx(id, &handler->items[i].id, 0, PVCF_USESTRCMPI) != 0) continue; + + return &handler->items[i]; + } + + return NULL; +} + static HRESULT WINAPI MetadataHandler_GetValue(IWICMetadataWriter *iface, const PROPVARIANT *schema, const PROPVARIANT *id, PROPVARIANT *value) { - UINT i; - HRESULT hr = WINCODEC_ERR_PROPERTYNOTFOUND; MetadataHandler *This = impl_from_IWICMetadataWriter(iface); + HRESULT hr = WINCODEC_ERR_PROPERTYNOTFOUND; + MetadataItem *item;
TRACE("(%p,%s,%s,%p)\n", iface, wine_dbgstr_variant((const VARIANT *)schema), wine_dbgstr_variant((const VARIANT *)id), value);
@@ -237,17 +257,9 @@ static HRESULT WINAPI MetadataHandler_GetValue(IWICMetadataWriter *iface,
EnterCriticalSection(&This->lock);
- for (i = 0; i < This->item_count; i++) + if ((item = metadatahandler_get_item(This, schema, id))) { - if (schema && This->items[i].schema.vt != VT_EMPTY) - { - if (PropVariantCompareEx(schema, &This->items[i].schema, 0, PVCF_USESTRCMPI) != 0) continue; - } - - if (PropVariantCompareEx(id, &This->items[i].id, 0, PVCF_USESTRCMPI) != 0) continue; - - hr = value ? PropVariantCopy(value, &This->items[i].value) : S_OK; - break; + hr = value ? PropVariantCopy(value, &item->value) : S_OK; }
LeaveCriticalSection(&This->lock); @@ -263,10 +275,56 @@ static HRESULT WINAPI MetadataHandler_GetEnumerator(IWICMetadataWriter *iface, }
static HRESULT WINAPI MetadataHandler_SetValue(IWICMetadataWriter *iface, - const PROPVARIANT *pvarSchema, const PROPVARIANT *pvarId, const PROPVARIANT *pvarValue) + const PROPVARIANT *schema, const PROPVARIANT *id, const PROPVARIANT *value) { - FIXME("(%p,%p,%p,%p): stub\n", iface, pvarSchema, pvarId, pvarValue); - return E_NOTIMPL; + MetadataHandler *This = impl_from_IWICMetadataWriter(iface); + MetadataItem *item, *new_items; + HRESULT hr; + + TRACE("(%p,%p,%p,%p)\n", iface, schema, id, value); + + if (!value) + return E_INVALIDARG; + + /* Replace value of an existing item, or append a new one. */ + + EnterCriticalSection(&This->lock); + + if ((item = metadatahandler_get_item(This, schema, id))) + { + PropVariantClear(&item->value); + hr = PropVariantCopy(&item->value, value); + } + else + { + new_items = realloc(This->items, (This->item_count + 1) * sizeof(*new_items)); + if (new_items) + { + This->items = new_items; + + item = &This->items[This->item_count]; + + PropVariantInit(&item->schema); + PropVariantInit(&item->id); + PropVariantInit(&item->value); + + /* Skip setting the schema value, it's probably format-dependent. */ + hr = PropVariantCopy(&item->id, id); + if (SUCCEEDED(hr)) + hr = PropVariantCopy(&item->value, value); + + if (SUCCEEDED(hr)) + ++This->item_count; + } + else + { + hr = E_OUTOFMEMORY; + } + } + + LeaveCriticalSection(&This->lock); + + return hr; }
static HRESULT WINAPI MetadataHandler_SetValueByIndex(IWICMetadataWriter *iface, diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index 253a525c5c9..ddd0e4ede0c 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -3853,7 +3853,7 @@ static void test_queryreader(void) IWICComponentFactory_Release(factory); }
-static void test_metadata_writer(void) +static void test_metadata_query_writer(void) { static struct { @@ -4544,6 +4544,104 @@ static void test_CreateMetadataWriter(void) IWICComponentFactory_Release(factory); }
+static void test_metadata_writer(void) +{ + IWICComponentFactory *factory; + IWICMetadataWriter *writer; + GUID format; + HRESULT hr; + UINT count; + PROPVARIANT schema, id, value; + + hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, + &IID_IWICComponentFactory, (void **)&factory); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IWICComponentFactory_CreateMetadataWriter(factory, &GUID_MetadataFormatIfd, NULL, 0, &writer); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IWICMetadataWriter_GetMetadataFormat(writer, &format); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(IsEqualGUID(&format, &GUID_MetadataFormatIfd), "Unexpected format %s.\n", wine_dbgstr_guid(&format)); + + hr = IWICMetadataWriter_GetCount(writer, &count); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!count, "Unexpected count %u.\n", count); + + schema.vt = VT_I4; + schema.lVal = 100; + id.vt = VT_UI2; + id.uiVal = 200; + value.vt = VT_UI4; + value.ulVal = 300; + hr = IWICMetadataWriter_SetValueByIndex(writer, 0, &schema, &id, &value); + todo_wine + ok(hr == WINCODEC_ERR_UNSUPPORTEDOPERATION, "Unexpected hr %#lx.\n", hr); + + hr = IWICMetadataWriter_SetValue(writer, &schema, &id, NULL); + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + + hr = IWICMetadataWriter_SetValue(writer, &schema, &id, &value); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IWICMetadataWriter_GetCount(writer, &count); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(count == 1, "Unexpected count %u.\n", count); + + id.vt = VT_UI2; + id.uiVal = 201; + hr = IWICMetadataWriter_SetValue(writer, &schema, &id, &value); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IWICMetadataWriter_GetCount(writer, &count); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(count == 2, "Unexpected count %u.\n", count); + + /* Same id with differing schema does not add a new item. */ + schema.vt = VT_I4; + schema.lVal = 101; + hr = IWICMetadataWriter_SetValue(writer, &schema, &id, &value); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IWICMetadataWriter_GetCount(writer, &count); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(count == 2, "Unexpected count %u.\n", count); + + PropVariantInit(&schema); + PropVariantInit(&id); + PropVariantInit(&value); + hr = IWICMetadataWriter_GetValueByIndex(writer, 0, &schema, &id, &value); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(schema.vt == VT_EMPTY, "Unexpected type %u.\n", schema.vt); + ok(!schema.lVal, "Unexpected value %lu.\n", schema.lVal); + ok(id.vt == VT_UI2, "Unexpected type %u.\n", id.vt); + ok(id.uiVal == 200, "Unexpected value %u.\n", id.uiVal); + ok(value.vt == VT_UI4, "Unexpected type %u.\n", value.vt); + ok(value.uiVal == 300, "Unexpected value %lu.\n", value.ulVal); + + PropVariantInit(&schema); + PropVariantInit(&id); + PropVariantInit(&value); + hr = IWICMetadataWriter_GetValueByIndex(writer, 1, &schema, &id, &value); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(schema.vt == VT_EMPTY, "Unexpected type %u.\n", schema.vt); + ok(!schema.lVal, "Unexpected value %lu.\n", schema.lVal); + ok(id.vt == VT_UI2, "Unexpected type %u.\n", id.vt); + ok(id.uiVal == 201, "Unexpected value %u.\n", id.uiVal); + ok(value.vt == VT_UI4, "Unexpected type %u.\n", value.vt); + ok(value.uiVal == 300, "Unexpected value %lu.\n", value.ulVal); + + value.vt = VT_UI4; + value.ulVal = 301; + hr = IWICMetadataWriter_SetValueByIndex(writer, 1, &schema, &id, &value); + todo_wine + ok(hr == WINCODEC_ERR_UNSUPPORTEDOPERATION, "Unexpected hr %#lx.\n", hr); + + IWICMetadataWriter_Release(writer); + + IWICComponentFactory_Release(factory); +} + START_TEST(metadata) { CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); @@ -4570,10 +4668,11 @@ START_TEST(metadata) test_metadata_GCE(); test_metadata_APE(); test_metadata_GIF_comment(); - test_metadata_writer(); + test_metadata_query_writer(); test_metadata_App1(); test_CreateMetadataWriterFromReader(); test_CreateMetadataWriter(); + test_metadata_writer();
CoUninitialize(); }
Esme Povirk (@madewokherd) commented about dlls/windowscodecs/metadatahandler.c:
if (SUCCEEDED(hr))
hr = create_metadata_reader(item->id.uiVal == IFD_EXIF_TAG ? &GUID_MetadataFormatExif : &GUID_MetadataFormatGps,
vendor, options | WICMetadataCreationFailUnknown, sub_stream, &sub_reader);
{
const GUID *format = item->id.uiVal == IFD_EXIF_TAG ? &GUID_MetadataFormatExif : &GUID_MetadataFormatGps;
if (is_writer)
hr = create_metadata_writer(format, vendor, options | WICMetadataCreationFailUnknown,
(IWICMetadataWriter **)&sub_reader);
else
hr = create_metadata_reader(format, vendor, options | WICMetadataCreationFailUnknown,
NULL, &sub_reader);
}
if (SUCCEEDED(hr))
hr = IWICMetadataReader_QueryInterface(sub_reader, &IID_IWICPersistStream, (void **)&persist_stream);
This isn't a new problem with the change, but I think sub_reader may be leaked if this fails.
On Thu Feb 6 17:10:48 2025 +0000, Esme Povirk wrote:
This isn't a new problem with the change, but I think sub_reader may be leaked if this fails.
Oh, wait, it is a new problem because previously the assignment to value.punkVal immediately followed the creation of sub_reader.
On Thu Feb 6 17:11:50 2025 +0000, Esme Povirk wrote:
Oh, wait, it is a new problem because previously the assignment to value.punkVal immediately followed the creation of sub_reader.
I guess it's fixed in the next patch. Not sure how much we need to worry about it then.
On Thu Feb 6 17:25:46 2025 +0000, Esme Povirk wrote:
I guess it's fixed in the next patch. Not sure how much we need to worry about it then.
No problem. I’ll fix it up, so that it’s correct on every commit.
Esme Povirk (@madewokherd) commented about dlls/windowscodecs/metadatahandler.c:
}
static HRESULT WINAPI MetadataHandler_SetValue(IWICMetadataWriter *iface,
- const PROPVARIANT *pvarSchema, const PROPVARIANT *pvarId, const PROPVARIANT *pvarValue)
const PROPVARIANT *schema, const PROPVARIANT *id, const PROPVARIANT *value)
{
- FIXME("(%p,%p,%p,%p): stub\n", iface, pvarSchema, pvarId, pvarValue);
- return E_NOTIMPL;
- MetadataHandler *This = impl_from_IWICMetadataWriter(iface);
- MetadataItem *item, *new_items;
- HRESULT hr;
- TRACE("(%p,%p,%p,%p)\n", iface, schema, id, value);
- if (!value)
Is there a reason we don't check for NULL id here?
Esme Povirk (@madewokherd) commented about dlls/windowscodecs/metadatahandler.c:
- {
new_items = realloc(This->items, (This->item_count + 1) * sizeof(*new_items));
if (new_items)
{
This->items = new_items;
item = &This->items[This->item_count];
PropVariantInit(&item->schema);
PropVariantInit(&item->id);
PropVariantInit(&item->value);
/* Skip setting the schema value, it's probably format-dependent. */
hr = PropVariantCopy(&item->id, id);
if (SUCCEEDED(hr))
hr = PropVariantCopy(&item->value, value);
If copying the value fails, we may leak the id.