Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/windowscodecs/encoder.c | 120 ++++++++++++++++++++++++- dlls/windowscodecs/libjpeg.c | 2 +- dlls/windowscodecs/libpng.c | 2 +- dlls/windowscodecs/libtiff.c | 2 +- dlls/windowscodecs/wincodecs_private.h | 1 + 5 files changed, 122 insertions(+), 5 deletions(-)
diff --git a/dlls/windowscodecs/encoder.c b/dlls/windowscodecs/encoder.c index 8e05048d1df..e72ceb0735c 100644 --- a/dlls/windowscodecs/encoder.c +++ b/dlls/windowscodecs/encoder.c @@ -58,6 +58,7 @@ typedef struct CommonEncoder {
typedef struct CommonEncoderFrame { IWICBitmapFrameEncode IWICBitmapFrameEncode_iface; + IWICMetadataBlockWriter IWICMetadataBlockWriter_iface; LONG ref; CommonEncoder *parent; struct encoder_frame encoder_frame; @@ -77,10 +78,15 @@ static inline CommonEncoderFrame *impl_from_IWICBitmapFrameEncode(IWICBitmapFram return CONTAINING_RECORD(iface, CommonEncoderFrame, IWICBitmapFrameEncode_iface); }
+static inline CommonEncoderFrame *impl_from_IWICMetadataBlockWriter(IWICMetadataBlockWriter *iface) +{ + return CONTAINING_RECORD(iface, CommonEncoderFrame, IWICMetadataBlockWriter_iface); +} + static HRESULT WINAPI CommonEncoderFrame_QueryInterface(IWICBitmapFrameEncode *iface, REFIID iid, void **ppv) { - CommonEncoderFrame *This = impl_from_IWICBitmapFrameEncode(iface); + CommonEncoderFrame *object = impl_from_IWICBitmapFrameEncode(iface); TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
if (!ppv) return E_INVALIDARG; @@ -88,7 +94,12 @@ static HRESULT WINAPI CommonEncoderFrame_QueryInterface(IWICBitmapFrameEncode *i if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IWICBitmapFrameEncode, iid)) { - *ppv = &This->IWICBitmapFrameEncode_iface; + *ppv = &object->IWICBitmapFrameEncode_iface; + } + else if (object->parent->encoder_info.flags & ENCODER_FLAGS_SUPPORTS_METADATA + && IsEqualIID(&IID_IWICMetadataBlockWriter, iid)) + { + *ppv = &object->IWICMetadataBlockWriter_iface; } else { @@ -628,6 +639,110 @@ static HRESULT WINAPI CommonEncoder_SetPreview(IWICBitmapEncoder *iface, IWICBit return WINCODEC_ERR_UNSUPPORTEDOPERATION; }
+static HRESULT WINAPI CommonEncoderFrame_Block_QueryInterface(IWICMetadataBlockWriter *iface, REFIID iid, void **ppv) +{ + CommonEncoderFrame *encoder = impl_from_IWICMetadataBlockWriter(iface); + + return IWICBitmapFrameEncode_QueryInterface(&encoder->IWICBitmapFrameEncode_iface, iid, ppv); +} + +static ULONG WINAPI CommonEncoderFrame_Block_AddRef(IWICMetadataBlockWriter *iface) +{ + CommonEncoderFrame *encoder = impl_from_IWICMetadataBlockWriter(iface); + + return IWICBitmapFrameEncode_AddRef(&encoder->IWICBitmapFrameEncode_iface); +} + +static ULONG WINAPI CommonEncoderFrame_Block_Release(IWICMetadataBlockWriter *iface) +{ + CommonEncoderFrame *encoder = impl_from_IWICMetadataBlockWriter(iface); + + return IWICBitmapFrameEncode_Release(&encoder->IWICBitmapFrameEncode_iface); +} + +static HRESULT WINAPI CommonEncoderFrame_Block_GetContainerFormat(IWICMetadataBlockWriter *iface, GUID *container_format) +{ + FIXME("iface %p, container_format %p stub.\n", iface, container_format); + + return E_NOTIMPL; +} + +static HRESULT WINAPI CommonEncoderFrame_Block_GetCount(IWICMetadataBlockWriter *iface, UINT *count) +{ + FIXME("iface %p, count %p stub.\n", iface, count); + + return E_NOTIMPL; +} + +static HRESULT WINAPI CommonEncoderFrame_Block_GetReaderByIndex(IWICMetadataBlockWriter *iface, + UINT index, IWICMetadataReader **metadata_reader) +{ + FIXME("iface %p, index %d, metadata_reader %p stub.\n", iface, index, metadata_reader); + + return E_NOTIMPL; +} + +static HRESULT WINAPI CommonEncoderFrame_Block_GetEnumerator(IWICMetadataBlockWriter *iface, IEnumUnknown **enum_metadata) +{ + FIXME("iface %p, ppIEnumMetadata %p stub.\n", iface, enum_metadata); + + return E_NOTIMPL; +} + +static HRESULT WINAPI CommonEncoderFrame_Block_InitializeFromBlockReader(IWICMetadataBlockWriter *iface, + IWICMetadataBlockReader *metadata_block_reader) +{ + FIXME("iface %p, metadata_block_reader %p stub.\n", iface, metadata_block_reader); + + return E_NOTIMPL; +} + +static HRESULT WINAPI CommonEncoderFrame_Block_GetWriterByIndex(IWICMetadataBlockWriter *iface, UINT index, + IWICMetadataWriter **metadata_writer) +{ + FIXME("iface %p, index %u, metadata_writer %p stub.\n", iface, index, metadata_writer); + + return E_NOTIMPL; +} + +static HRESULT WINAPI CommonEncoderFrame_Block_AddWriter(IWICMetadataBlockWriter *iface, IWICMetadataWriter *metadata_writer) +{ + FIXME("iface %p, metadata_writer %p.\n", iface, metadata_writer); + + return E_NOTIMPL; +} + +static HRESULT WINAPI CommonEncoderFrame_Block_SetWriterByIndex(IWICMetadataBlockWriter *iface, UINT index, + IWICMetadataWriter *metadata_writer) +{ + FIXME("iface %p, index %u, metadata_writer %p stub.\n", iface, index, metadata_writer); + + return E_NOTIMPL; +} + +static HRESULT WINAPI CommonEncoderFrame_Block_RemoveWriterByIndex(IWICMetadataBlockWriter *iface, UINT index) +{ + FIXME("iface %p, index %u.\n", iface, index); + + return E_NOTIMPL; +} + +static const IWICMetadataBlockWriterVtbl CommonEncoderFrame_BlockVtbl = +{ + CommonEncoderFrame_Block_QueryInterface, + CommonEncoderFrame_Block_AddRef, + CommonEncoderFrame_Block_Release, + CommonEncoderFrame_Block_GetContainerFormat, + CommonEncoderFrame_Block_GetCount, + CommonEncoderFrame_Block_GetReaderByIndex, + CommonEncoderFrame_Block_GetEnumerator, + CommonEncoderFrame_Block_InitializeFromBlockReader, + CommonEncoderFrame_Block_GetWriterByIndex, + CommonEncoderFrame_Block_AddWriter, + CommonEncoderFrame_Block_SetWriterByIndex, + CommonEncoderFrame_Block_RemoveWriterByIndex, +}; + static HRESULT WINAPI CommonEncoder_CreateNewFrame(IWICBitmapEncoder *iface, IWICBitmapFrameEncode **ppIFrameEncode, IPropertyBag2 **ppIEncoderOptions) { @@ -661,6 +776,7 @@ static HRESULT WINAPI CommonEncoder_CreateNewFrame(IWICBitmapEncoder *iface, }
result->IWICBitmapFrameEncode_iface.lpVtbl = &CommonEncoderFrame_Vtbl; + result->IWICMetadataBlockWriter_iface.lpVtbl = &CommonEncoderFrame_BlockVtbl; result->ref = 1; result->parent = This;
diff --git a/dlls/windowscodecs/libjpeg.c b/dlls/windowscodecs/libjpeg.c index 84e4df5e007..96a9b79f358 100644 --- a/dlls/windowscodecs/libjpeg.c +++ b/dlls/windowscodecs/libjpeg.c @@ -746,7 +746,7 @@ HRESULT CDECL jpeg_encoder_create(struct encoder_info *info, struct encoder **re This->cinfo_initialized = FALSE; *result = &This->encoder;
- info->flags = 0; + info->flags = ENCODER_FLAGS_SUPPORTS_METADATA; info->container_format = GUID_ContainerFormatJpeg; info->clsid = CLSID_WICJpegEncoder; info->encoder_options[0] = ENCODER_OPTION_IMAGE_QUALITY; diff --git a/dlls/windowscodecs/libpng.c b/dlls/windowscodecs/libpng.c index a5068c20349..0571f5a2aad 100644 --- a/dlls/windowscodecs/libpng.c +++ b/dlls/windowscodecs/libpng.c @@ -997,7 +997,7 @@ HRESULT CDECL png_encoder_create(struct encoder_info *info, struct encoder **res This->data = NULL; *result = &This->encoder;
- info->flags = 0; + info->flags = ENCODER_FLAGS_SUPPORTS_METADATA; info->container_format = GUID_ContainerFormatPng; info->clsid = CLSID_WICPngEncoder; info->encoder_options[0] = ENCODER_OPTION_INTERLACE; diff --git a/dlls/windowscodecs/libtiff.c b/dlls/windowscodecs/libtiff.c index 6f5cfc53c62..25d8c1c6081 100644 --- a/dlls/windowscodecs/libtiff.c +++ b/dlls/windowscodecs/libtiff.c @@ -1414,7 +1414,7 @@ HRESULT CDECL tiff_encoder_create(struct encoder_info *info, struct encoder **re This->tiff = NULL; This->num_frames = 0;
- info->flags = ENCODER_FLAGS_MULTI_FRAME; + info->flags = ENCODER_FLAGS_MULTI_FRAME | ENCODER_FLAGS_SUPPORTS_METADATA; info->container_format = GUID_ContainerFormatTiff; info->clsid = CLSID_WICTiffEncoder; info->encoder_options[0] = ENCODER_OPTION_COMPRESSION_METHOD; diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h index 85d057cc278..997bdee3446 100644 --- a/dlls/windowscodecs/wincodecs_private.h +++ b/dlls/windowscodecs/wincodecs_private.h @@ -355,6 +355,7 @@ enum encoder_option
#define ENCODER_FLAGS_MULTI_FRAME 0x1 #define ENCODER_FLAGS_ICNS_SIZE 0x2 +#define ENCODER_FLAGS_SUPPORTS_METADATA 0x4
struct encoder_info {
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/windowscodecs/gifformat.c | 128 +++++++++++++++++++++++++++++++-- 1 file changed, 124 insertions(+), 4 deletions(-)
diff --git a/dlls/windowscodecs/gifformat.c b/dlls/windowscodecs/gifformat.c index 8ebba7b5a88..c807a7ee7db 100644 --- a/dlls/windowscodecs/gifformat.c +++ b/dlls/windowscodecs/gifformat.c @@ -1473,6 +1473,7 @@ static inline GifEncoder *impl_from_IWICBitmapEncoder(IWICBitmapEncoder *iface) typedef struct GifFrameEncode { IWICBitmapFrameEncode IWICBitmapFrameEncode_iface; + IWICMetadataBlockWriter IWICMetadataBlockWriter_iface; LONG ref; GifEncoder *encoder; BOOL initialized, interlace, committed; @@ -1488,8 +1489,15 @@ static inline GifFrameEncode *impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEnc return CONTAINING_RECORD(iface, GifFrameEncode, IWICBitmapFrameEncode_iface); }
+static inline GifFrameEncode *impl_from_IWICMetadataBlockWriter(IWICMetadataBlockWriter *iface) +{ + return CONTAINING_RECORD(iface, GifFrameEncode, IWICMetadataBlockWriter_iface); +} + static HRESULT WINAPI GifFrameEncode_QueryInterface(IWICBitmapFrameEncode *iface, REFIID iid, void **ppv) { + GifFrameEncode *encoder = impl_from_IWICBitmapFrameEncode(iface); + TRACE("%p,%s,%p\n", iface, debugstr_guid(iid), ppv);
if (!ppv) return E_INVALIDARG; @@ -1497,13 +1505,20 @@ static HRESULT WINAPI GifFrameEncode_QueryInterface(IWICBitmapFrameEncode *iface if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IWICBitmapFrameEncode, iid)) { - IWICBitmapFrameEncode_AddRef(iface); *ppv = iface; - return S_OK; + } + else if (IsEqualIID(&IID_IWICMetadataBlockWriter, iid)) + { + *ppv = &encoder->IWICMetadataBlockWriter_iface; + } + else + { + *ppv = NULL; + return E_NOINTERFACE; }
- *ppv = NULL; - return E_NOINTERFACE; + IUnknown_AddRef((IUnknown *)*ppv); + return S_OK; }
static ULONG WINAPI GifFrameEncode_AddRef(IWICBitmapFrameEncode *iface) @@ -2259,6 +2274,109 @@ static HRESULT WINAPI GifEncoder_SetPreview(IWICBitmapEncoder *iface, IWICBitmap return WINCODEC_ERR_UNSUPPORTEDOPERATION; }
+static HRESULT WINAPI GifEncoderFrame_Block_QueryInterface(IWICMetadataBlockWriter *iface, REFIID iid, void **ppv) +{ + GifFrameEncode *frame_encoder = impl_from_IWICMetadataBlockWriter(iface); + + return IWICBitmapFrameEncode_QueryInterface(&frame_encoder->IWICBitmapFrameEncode_iface, iid, ppv); +} + +static ULONG WINAPI GifEncoderFrame_Block_AddRef(IWICMetadataBlockWriter *iface) +{ + GifFrameEncode *frame_encoder = impl_from_IWICMetadataBlockWriter(iface); + + return IWICBitmapFrameEncode_AddRef(&frame_encoder->IWICBitmapFrameEncode_iface); +} + +static ULONG WINAPI GifEncoderFrame_Block_Release(IWICMetadataBlockWriter *iface) +{ + GifFrameEncode *frame_encoder = impl_from_IWICMetadataBlockWriter(iface); + + return IWICBitmapFrameEncode_Release(&frame_encoder->IWICBitmapFrameEncode_iface); +} + +static HRESULT WINAPI GifEncoderFrame_Block_GetContainerFormat(IWICMetadataBlockWriter *iface, GUID *container_format) +{ + FIXME("iface %p, container_format %p stub.\n", iface, container_format); + + return E_NOTIMPL; +} + +static HRESULT WINAPI GifEncoderFrame_Block_GetCount(IWICMetadataBlockWriter *iface, UINT *count) +{ + FIXME("iface %p, count %p stub.\n", iface, count); + + return E_NOTIMPL; +} + +static HRESULT WINAPI GifEncoderFrame_Block_GetReaderByIndex(IWICMetadataBlockWriter *iface, + UINT index, IWICMetadataReader **metadata_reader) +{ + FIXME("iface %p, index %d, metadata_reader %p stub.\n", iface, index, metadata_reader); + + return E_NOTIMPL; +} + +static HRESULT WINAPI GifEncoderFrame_Block_GetEnumerator(IWICMetadataBlockWriter *iface, IEnumUnknown **enum_metadata) +{ + FIXME("iface %p, enum_metadata %p stub.\n", iface, enum_metadata); + + return E_NOTIMPL; +} + +static HRESULT WINAPI GifEncoderFrame_Block_InitializeFromBlockReader(IWICMetadataBlockWriter *iface, + IWICMetadataBlockReader *block_reader) +{ + FIXME("iface %p, block_reader %p stub.\n", iface, block_reader); + + return E_NOTIMPL; +} + +static HRESULT WINAPI GifEncoderFrame_Block_GetWriterByIndex(IWICMetadataBlockWriter *iface, UINT index, + IWICMetadataWriter **metadata_writer) +{ + FIXME("iface %p, index %u, metadata_writer %p stub.\n", iface, index, metadata_writer); + + return E_NOTIMPL; +} + +static HRESULT WINAPI GifEncoderFrame_Block_AddWriter(IWICMetadataBlockWriter *iface, IWICMetadataWriter *metadata_writer) +{ + FIXME("iface %p, metadata_writer %p stub.\n", iface, metadata_writer); + + return E_NOTIMPL; +} + +static HRESULT WINAPI GifEncoderFrame_Block_SetWriterByIndex(IWICMetadataBlockWriter *iface, UINT index, + IWICMetadataWriter *metadata_writer) +{ + FIXME("iface %p, index %u, metadata_writer %p stub.\n", iface, index, metadata_writer); + + return E_NOTIMPL; +} + +static HRESULT WINAPI GifEncoderFrame_Block_RemoveWriterByIndex(IWICMetadataBlockWriter *iface, UINT index) +{ + FIXME("iface %p, index %u stub.\n", iface, index); + + return E_NOTIMPL; +} + +static const IWICMetadataBlockWriterVtbl GifFrameEncode_BlockVtbl = { + GifEncoderFrame_Block_QueryInterface, + GifEncoderFrame_Block_AddRef, + GifEncoderFrame_Block_Release, + GifEncoderFrame_Block_GetContainerFormat, + GifEncoderFrame_Block_GetCount, + GifEncoderFrame_Block_GetReaderByIndex, + GifEncoderFrame_Block_GetEnumerator, + GifEncoderFrame_Block_InitializeFromBlockReader, + GifEncoderFrame_Block_GetWriterByIndex, + GifEncoderFrame_Block_AddWriter, + GifEncoderFrame_Block_SetWriterByIndex, + GifEncoderFrame_Block_RemoveWriterByIndex, +}; + static HRESULT WINAPI GifEncoder_CreateNewFrame(IWICBitmapEncoder *iface, IWICBitmapFrameEncode **frame, IPropertyBag2 **options) { GifEncoder *This = impl_from_IWICBitmapEncoder(iface); @@ -2278,6 +2396,8 @@ static HRESULT WINAPI GifEncoder_CreateNewFrame(IWICBitmapEncoder *iface, IWICBi This->n_frames++;
ret->IWICBitmapFrameEncode_iface.lpVtbl = &GifFrameEncode_Vtbl; + ret->IWICMetadataBlockWriter_iface.lpVtbl = &GifFrameEncode_BlockVtbl; + ret->ref = 1; ret->encoder = This; ret->initialized = FALSE;
Signed-off-by: Esme Povirk esme@codeweavers.com
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/windowscodecs/tests/metadata.c | 87 +++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+)
diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index a955702c82c..cc627fc195f 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -3049,6 +3049,92 @@ static void test_queryreader(void) IWICComponentFactory_Release(factory); }
+static void test_metadata_writer(void) +{ + static struct + { + REFCLSID rclsid; + BOOL wine_supports_encoder; + BOOL metadata_supported; + BOOL succeeds_unitialized; + } + tests[] = + { + {&CLSID_WICBmpEncoder, TRUE, FALSE}, + {&CLSID_WICPngEncoder, TRUE, TRUE}, + {&CLSID_WICJpegEncoder, TRUE, TRUE}, + {&CLSID_WICGifEncoder, TRUE, TRUE}, + {&CLSID_WICTiffEncoder, TRUE, TRUE}, + {&CLSID_WICWmpEncoder, FALSE, TRUE, TRUE}, + }; + + IWICMetadataQueryWriter *querywriter, *querywriter2; + IWICMetadataBlockWriter *blockwriter; + IWICBitmapFrameEncode *frameencode; + IWICComponentFactory *factory; + IWICBitmapEncoder *encoder; + IStream *stream; + unsigned int i; + HRESULT hr; + + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + hr = CoCreateInstance(tests[i].rclsid, NULL, CLSCTX_INPROC_SERVER, + &IID_IWICBitmapEncoder, (void **)&encoder); + todo_wine_if(!tests[i].wine_supports_encoder) ok(hr == S_OK, "Got unexpected hr %#x, i %u.\n", hr, i); + if (FAILED(hr)) + continue; + + blockwriter = NULL; + querywriter = querywriter2 = NULL; + + hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); + ok(hr == S_OK, "Got unexpected hr %#x, i %u.\n", hr, i); + hr = IWICBitmapEncoder_Initialize(encoder, stream, WICBitmapEncoderNoCache); + ok(hr == S_OK, "Got unexpected hr %#x, i %u.\n", hr, i); + hr = IWICBitmapEncoder_CreateNewFrame(encoder, &frameencode, NULL); + ok(hr == S_OK, "Got unexpected hr %#x, i %u.\n", hr, i); + + hr = IWICBitmapFrameEncode_QueryInterface(frameencode, &IID_IWICMetadataBlockWriter, (void**)&blockwriter); + ok(hr == (tests[i].metadata_supported ? S_OK : E_NOINTERFACE), "Got unexpected hr %#x, i %u.\n", hr, i); + + hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, + &IID_IWICComponentFactory, (void**)&factory); + ok(hr == S_OK, "Got unexpected hr %#x, i %u.\n", hr, i); + + hr = IWICComponentFactory_CreateQueryWriterFromBlockWriter(factory, blockwriter, &querywriter); + todo_wine ok(hr == (tests[i].metadata_supported ? S_OK : E_INVALIDARG), "Got unexpected hr %#x, i %u.\n", hr, i); + + hr = IWICBitmapFrameEncode_GetMetadataQueryWriter(frameencode, &querywriter2); + todo_wine + ok(hr == (tests[i].succeeds_unitialized ? S_OK : WINCODEC_ERR_NOTINITIALIZED), + "Got unexpected hr %#x, i %u.\n", hr, i); + if (hr == S_OK) + IWICMetadataQueryWriter_Release(querywriter2); + + hr = IWICBitmapFrameEncode_Initialize(frameencode, NULL); + ok(hr == S_OK, "Got unexpected hr %#x, i %u.\n", hr, i); + + hr = IWICBitmapFrameEncode_GetMetadataQueryWriter(frameencode, &querywriter2); + todo_wine ok(hr == (tests[i].metadata_supported ? S_OK : WINCODEC_ERR_UNSUPPORTEDOPERATION), + "Got unexpected hr %#x, i %u.\n", hr, i); + + if (tests[i].metadata_supported) + todo_wine ok(querywriter2 != querywriter, "Got unexpected interfaces %p, %p, i %u.\n", querywriter, querywriter2, i); + + IWICComponentFactory_Release(factory); + if (querywriter) + { + IWICMetadataQueryWriter_Release(querywriter); + IWICMetadataQueryWriter_Release(querywriter2); + IWICMetadataBlockWriter_Release(blockwriter); + } + IWICBitmapFrameEncode_Release(frameencode); + IStream_Release(stream); + IWICBitmapEncoder_Release(encoder); + } +} + START_TEST(metadata) { CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); @@ -3071,6 +3157,7 @@ START_TEST(metadata) test_metadata_GCE(); test_metadata_APE(); test_metadata_GIF_comment(); + test_metadata_writer();
CoUninitialize(); }
Signed-off-by: Esme Povirk esme@codeweavers.com
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/windowscodecs/imgfactory.c | 8 +- dlls/windowscodecs/metadataquery.c | 140 +++++++++++++++++++++++++ dlls/windowscodecs/tests/metadata.c | 7 +- dlls/windowscodecs/wincodecs_private.h | 1 + 4 files changed, 151 insertions(+), 5 deletions(-)
diff --git a/dlls/windowscodecs/imgfactory.c b/dlls/windowscodecs/imgfactory.c index df180681af1..7e10fc37875 100644 --- a/dlls/windowscodecs/imgfactory.c +++ b/dlls/windowscodecs/imgfactory.c @@ -1410,8 +1410,12 @@ static HRESULT WINAPI ComponentFactory_CreateQueryReaderFromBlockReader(IWICComp static HRESULT WINAPI ComponentFactory_CreateQueryWriterFromBlockWriter(IWICComponentFactory *iface, IWICMetadataBlockWriter *block_writer, IWICMetadataQueryWriter **query_writer) { - FIXME("%p,%p,%p: stub\n", iface, block_writer, query_writer); - return E_NOTIMPL; + TRACE("%p,%p,%p\n", iface, block_writer, query_writer); + + if (!block_writer || !query_writer) + return E_INVALIDARG; + + return MetadataQueryWriter_CreateInstance(block_writer, NULL, query_writer); }
static HRESULT WINAPI ComponentFactory_CreateEncoderPropertyBag(IWICComponentFactory *iface, diff --git a/dlls/windowscodecs/metadataquery.c b/dlls/windowscodecs/metadataquery.c index 2761a520083..2e3652c1f7e 100644 --- a/dlls/windowscodecs/metadataquery.c +++ b/dlls/windowscodecs/metadataquery.c @@ -635,6 +635,146 @@ HRESULT MetadataQueryReader_CreateInstance(IWICMetadataBlockReader *mbr, const W return S_OK; }
+typedef struct +{ + IWICMetadataQueryWriter IWICMetadataQueryWriter_iface; + LONG ref; + IWICMetadataBlockWriter *block; + WCHAR *root; +} +QueryWriter; + +static inline QueryWriter *impl_from_IWICMetadataQueryWriter(IWICMetadataQueryWriter *iface) +{ + return CONTAINING_RECORD(iface, QueryWriter, IWICMetadataQueryWriter_iface); +} + +static HRESULT WINAPI mqw_QueryInterface(IWICMetadataQueryWriter *iface, REFIID riid, + void **object) +{ + QueryWriter *writer = impl_from_IWICMetadataQueryWriter(iface); + + TRACE("writer %p, riid %s, object %p.\n", writer, debugstr_guid(riid), object); + + if (IsEqualGUID(riid, &IID_IUnknown) + || IsEqualGUID(riid, &IID_IWICMetadataQueryWriter) + || IsEqualGUID(riid, &IID_IWICMetadataQueryReader)) + *object = &writer->IWICMetadataQueryWriter_iface; + else + *object = NULL; + + if (*object) + { + IUnknown_AddRef((IUnknown *)*object); + return S_OK; + } + + return E_NOINTERFACE; +} + +static ULONG WINAPI mqw_AddRef(IWICMetadataQueryWriter *iface) +{ + QueryWriter *writer = impl_from_IWICMetadataQueryWriter(iface); + ULONG ref = InterlockedIncrement(&writer->ref); + + TRACE("writer %p, refcount=%u\n", writer, ref); + + return ref; +} + +static ULONG WINAPI mqw_Release(IWICMetadataQueryWriter *iface) +{ + QueryWriter *writer = impl_from_IWICMetadataQueryWriter(iface); + ULONG ref = InterlockedDecrement(&writer->ref); + + TRACE("writer %p, refcount=%u.\n", writer, ref); + + if (!ref) + { + IWICMetadataBlockWriter_Release(writer->block); + HeapFree(GetProcessHeap(), 0, writer->root); + HeapFree(GetProcessHeap(), 0, writer); + } + return ref; +} + +static HRESULT WINAPI mqw_GetContainerFormat(IWICMetadataQueryWriter *iface, GUID *container_format) +{ + FIXME("iface %p, container_format %p stub.\n", iface, container_format); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mqw_GetEnumerator(IWICMetadataQueryWriter *iface, IEnumString **enum_string) +{ + FIXME("iface %p, enum_string %p stub.\n", iface, enum_string); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mqw_GetLocation(IWICMetadataQueryWriter *iface, UINT max_length, WCHAR *namespace, UINT *actual_length) +{ + FIXME("iface %p, max_length %u, namespace %s, actual_length %p stub.\n", + iface, max_length, debugstr_w(namespace), actual_length); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mqw_GetMetadataByName(IWICMetadataQueryWriter *iface, LPCWSTR name, PROPVARIANT *value) +{ + FIXME("name %s, value %p stub.\n", debugstr_w(name), value); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mqw_SetMetadataByName(IWICMetadataQueryWriter *iface, LPCWSTR name, const PROPVARIANT *value) +{ + FIXME("iface %p, name %s, value %p stub.\n", iface, debugstr_w(name), value); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mqw_RemoveMetadataByName(IWICMetadataQueryWriter *iface, LPCWSTR name) +{ + FIXME("iface %p, name %s stub.\n", iface, debugstr_w(name)); + + return E_NOTIMPL; +} + +static const IWICMetadataQueryWriterVtbl mqw_vtbl = +{ + mqw_QueryInterface, + mqw_AddRef, + mqw_Release, + mqw_GetContainerFormat, + mqw_GetLocation, + mqw_GetMetadataByName, + mqw_GetEnumerator, + mqw_SetMetadataByName, + mqw_RemoveMetadataByName, +}; + +HRESULT MetadataQueryWriter_CreateInstance(IWICMetadataBlockWriter *mbw, const WCHAR *root, IWICMetadataQueryWriter **out) +{ + QueryWriter *obj; + + obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*obj)); + if (!obj) + return E_OUTOFMEMORY; + + obj->IWICMetadataQueryWriter_iface.lpVtbl = &mqw_vtbl; + obj->ref = 1; + + IWICMetadataBlockWriter_AddRef(mbw); + obj->block = mbw; + + obj->root = root ? heap_strdupW(root) : NULL; + + *out = &obj->IWICMetadataQueryWriter_iface; + + return S_OK; +} + static const struct { const GUID *guid; diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index cc627fc195f..aaa733380fa 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -3103,7 +3103,7 @@ static void test_metadata_writer(void) ok(hr == S_OK, "Got unexpected hr %#x, i %u.\n", hr, i);
hr = IWICComponentFactory_CreateQueryWriterFromBlockWriter(factory, blockwriter, &querywriter); - todo_wine ok(hr == (tests[i].metadata_supported ? S_OK : E_INVALIDARG), "Got unexpected hr %#x, i %u.\n", hr, i); + ok(hr == (tests[i].metadata_supported ? S_OK : E_INVALIDARG), "Got unexpected hr %#x, i %u.\n", hr, i);
hr = IWICBitmapFrameEncode_GetMetadataQueryWriter(frameencode, &querywriter2); todo_wine @@ -3120,13 +3120,14 @@ static void test_metadata_writer(void) "Got unexpected hr %#x, i %u.\n", hr, i);
if (tests[i].metadata_supported) - todo_wine ok(querywriter2 != querywriter, "Got unexpected interfaces %p, %p, i %u.\n", querywriter, querywriter2, i); + ok(querywriter2 != querywriter, "Got unexpected interfaces %p, %p, i %u.\n", querywriter, querywriter2, i);
IWICComponentFactory_Release(factory); if (querywriter) { IWICMetadataQueryWriter_Release(querywriter); - IWICMetadataQueryWriter_Release(querywriter2); + if (querywriter2) + IWICMetadataQueryWriter_Release(querywriter2); IWICMetadataBlockWriter_Release(blockwriter); } IWICBitmapFrameEncode_Release(frameencode); diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h index 997bdee3446..453bc58cca6 100644 --- a/dlls/windowscodecs/wincodecs_private.h +++ b/dlls/windowscodecs/wincodecs_private.h @@ -230,6 +230,7 @@ extern HRESULT GCEReader_CreateInstance(REFIID iid, void **ppv) DECLSPEC_HIDDEN; extern HRESULT APEReader_CreateInstance(REFIID iid, void **ppv) DECLSPEC_HIDDEN; extern HRESULT GifCommentReader_CreateInstance(REFIID iid, void **ppv) DECLSPEC_HIDDEN; extern HRESULT MetadataQueryReader_CreateInstance(IWICMetadataBlockReader *, const WCHAR *, IWICMetadataQueryReader **) DECLSPEC_HIDDEN; +extern HRESULT MetadataQueryWriter_CreateInstance(IWICMetadataBlockWriter *, const WCHAR *, IWICMetadataQueryWriter **) DECLSPEC_HIDDEN; extern HRESULT stream_initialize_from_filehandle(IWICStream *iface, HANDLE hfile) DECLSPEC_HIDDEN;
static inline WCHAR *heap_strdupW(const WCHAR *src)
Signed-off-by: Esme Povirk esme@codeweavers.com
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/windowscodecs/encoder.c | 16 ++++++++++++++-- dlls/windowscodecs/gifformat.c | 13 +++++++++++-- dlls/windowscodecs/tests/metadata.c | 8 +++----- 3 files changed, 28 insertions(+), 9 deletions(-)
diff --git a/dlls/windowscodecs/encoder.c b/dlls/windowscodecs/encoder.c index e72ceb0735c..a213e7d14d0 100644 --- a/dlls/windowscodecs/encoder.c +++ b/dlls/windowscodecs/encoder.c @@ -467,8 +467,20 @@ static HRESULT WINAPI CommonEncoderFrame_Commit(IWICBitmapFrameEncode *iface) static HRESULT WINAPI CommonEncoderFrame_GetMetadataQueryWriter(IWICBitmapFrameEncode *iface, IWICMetadataQueryWriter **ppIMetadataQueryWriter) { - FIXME("(%p, %p): stub\n", iface, ppIMetadataQueryWriter); - return E_NOTIMPL; + CommonEncoderFrame *encoder = impl_from_IWICBitmapFrameEncode(iface); + + TRACE("iface, %p, ppIMetadataQueryWriter %p.\n", iface, ppIMetadataQueryWriter); + + if (!ppIMetadataQueryWriter) + return E_INVALIDARG; + + if (!encoder->initialized) + return WINCODEC_ERR_NOTINITIALIZED; + + if (!(encoder->parent->encoder_info.flags & ENCODER_FLAGS_SUPPORTS_METADATA)) + return WINCODEC_ERR_UNSUPPORTEDOPERATION; + + return MetadataQueryWriter_CreateInstance(&encoder->IWICMetadataBlockWriter_iface, NULL, ppIMetadataQueryWriter); }
static const IWICBitmapFrameEncodeVtbl CommonEncoderFrame_Vtbl = { diff --git a/dlls/windowscodecs/gifformat.c b/dlls/windowscodecs/gifformat.c index c807a7ee7db..53aeaec7e8d 100644 --- a/dlls/windowscodecs/gifformat.c +++ b/dlls/windowscodecs/gifformat.c @@ -2117,8 +2117,17 @@ static HRESULT WINAPI GifFrameEncode_Commit(IWICBitmapFrameEncode *iface)
static HRESULT WINAPI GifFrameEncode_GetMetadataQueryWriter(IWICBitmapFrameEncode *iface, IWICMetadataQueryWriter **writer) { - FIXME("%p, %p: stub\n", iface, writer); - return E_NOTIMPL; + GifFrameEncode *encode = impl_from_IWICBitmapFrameEncode(iface); + + TRACE("iface, %p, writer %p.\n", iface, writer); + + if (!writer) + return E_INVALIDARG; + + if (!encode->initialized) + return WINCODEC_ERR_NOTINITIALIZED; + + return MetadataQueryWriter_CreateInstance(&encode->IWICMetadataBlockWriter_iface, NULL, writer); }
static const IWICBitmapFrameEncodeVtbl GifFrameEncode_Vtbl = diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index aaa733380fa..c1339e4bd1d 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -3106,8 +3106,7 @@ static void test_metadata_writer(void) ok(hr == (tests[i].metadata_supported ? S_OK : E_INVALIDARG), "Got unexpected hr %#x, i %u.\n", hr, i);
hr = IWICBitmapFrameEncode_GetMetadataQueryWriter(frameencode, &querywriter2); - todo_wine - ok(hr == (tests[i].succeeds_unitialized ? S_OK : WINCODEC_ERR_NOTINITIALIZED), + todo_wine_if(!i) ok(hr == (tests[i].succeeds_unitialized ? S_OK : WINCODEC_ERR_NOTINITIALIZED), "Got unexpected hr %#x, i %u.\n", hr, i); if (hr == S_OK) IWICMetadataQueryWriter_Release(querywriter2); @@ -3116,7 +3115,7 @@ static void test_metadata_writer(void) ok(hr == S_OK, "Got unexpected hr %#x, i %u.\n", hr, i);
hr = IWICBitmapFrameEncode_GetMetadataQueryWriter(frameencode, &querywriter2); - todo_wine ok(hr == (tests[i].metadata_supported ? S_OK : WINCODEC_ERR_UNSUPPORTEDOPERATION), + todo_wine_if(!i) ok(hr == (tests[i].metadata_supported ? S_OK : WINCODEC_ERR_UNSUPPORTEDOPERATION), "Got unexpected hr %#x, i %u.\n", hr, i);
if (tests[i].metadata_supported) @@ -3126,8 +3125,7 @@ static void test_metadata_writer(void) if (querywriter) { IWICMetadataQueryWriter_Release(querywriter); - if (querywriter2) - IWICMetadataQueryWriter_Release(querywriter2); + IWICMetadataQueryWriter_Release(querywriter2); IWICMetadataBlockWriter_Release(blockwriter); } IWICBitmapFrameEncode_Release(frameencode);
Forgot to mention, this fixes saving screenshots in Fallout 76 (this one also crashes at character creation otherwise) and Path of Exile.
On 1/27/21 20:33, Paul Gofman wrote:
Signed-off-by: Paul Gofman pgofman@codeweavers.com
dlls/windowscodecs/encoder.c | 16 ++++++++++++++-- dlls/windowscodecs/gifformat.c | 13 +++++++++++-- dlls/windowscodecs/tests/metadata.c | 8 +++----- 3 files changed, 28 insertions(+), 9 deletions(-)
diff --git a/dlls/windowscodecs/encoder.c b/dlls/windowscodecs/encoder.c index e72ceb0735c..a213e7d14d0 100644 --- a/dlls/windowscodecs/encoder.c +++ b/dlls/windowscodecs/encoder.c @@ -467,8 +467,20 @@ static HRESULT WINAPI CommonEncoderFrame_Commit(IWICBitmapFrameEncode *iface) static HRESULT WINAPI CommonEncoderFrame_GetMetadataQueryWriter(IWICBitmapFrameEncode *iface, IWICMetadataQueryWriter **ppIMetadataQueryWriter) {
- FIXME("(%p, %p): stub\n", iface, ppIMetadataQueryWriter);
- return E_NOTIMPL;
- CommonEncoderFrame *encoder = impl_from_IWICBitmapFrameEncode(iface);
- TRACE("iface, %p, ppIMetadataQueryWriter %p.\n", iface, ppIMetadataQueryWriter);
- if (!ppIMetadataQueryWriter)
return E_INVALIDARG;
- if (!encoder->initialized)
return WINCODEC_ERR_NOTINITIALIZED;
- if (!(encoder->parent->encoder_info.flags & ENCODER_FLAGS_SUPPORTS_METADATA))
return WINCODEC_ERR_UNSUPPORTEDOPERATION;
- return MetadataQueryWriter_CreateInstance(&encoder->IWICMetadataBlockWriter_iface, NULL, ppIMetadataQueryWriter);
}
static const IWICBitmapFrameEncodeVtbl CommonEncoderFrame_Vtbl = { diff --git a/dlls/windowscodecs/gifformat.c b/dlls/windowscodecs/gifformat.c index c807a7ee7db..53aeaec7e8d 100644 --- a/dlls/windowscodecs/gifformat.c +++ b/dlls/windowscodecs/gifformat.c @@ -2117,8 +2117,17 @@ static HRESULT WINAPI GifFrameEncode_Commit(IWICBitmapFrameEncode *iface)
static HRESULT WINAPI GifFrameEncode_GetMetadataQueryWriter(IWICBitmapFrameEncode *iface, IWICMetadataQueryWriter **writer) {
- FIXME("%p, %p: stub\n", iface, writer);
- return E_NOTIMPL;
- GifFrameEncode *encode = impl_from_IWICBitmapFrameEncode(iface);
- TRACE("iface, %p, writer %p.\n", iface, writer);
- if (!writer)
return E_INVALIDARG;
- if (!encode->initialized)
return WINCODEC_ERR_NOTINITIALIZED;
- return MetadataQueryWriter_CreateInstance(&encode->IWICMetadataBlockWriter_iface, NULL, writer);
}
static const IWICBitmapFrameEncodeVtbl GifFrameEncode_Vtbl = diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index aaa733380fa..c1339e4bd1d 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -3106,8 +3106,7 @@ static void test_metadata_writer(void) ok(hr == (tests[i].metadata_supported ? S_OK : E_INVALIDARG), "Got unexpected hr %#x, i %u.\n", hr, i);
hr = IWICBitmapFrameEncode_GetMetadataQueryWriter(frameencode, &querywriter2);
todo_wine
ok(hr == (tests[i].succeeds_unitialized ? S_OK : WINCODEC_ERR_NOTINITIALIZED),
todo_wine_if(!i) ok(hr == (tests[i].succeeds_unitialized ? S_OK : WINCODEC_ERR_NOTINITIALIZED), "Got unexpected hr %#x, i %u.\n", hr, i); if (hr == S_OK) IWICMetadataQueryWriter_Release(querywriter2);
@@ -3116,7 +3115,7 @@ static void test_metadata_writer(void) ok(hr == S_OK, "Got unexpected hr %#x, i %u.\n", hr, i);
hr = IWICBitmapFrameEncode_GetMetadataQueryWriter(frameencode, &querywriter2);
todo_wine ok(hr == (tests[i].metadata_supported ? S_OK : WINCODEC_ERR_UNSUPPORTEDOPERATION),
todo_wine_if(!i) ok(hr == (tests[i].metadata_supported ? S_OK : WINCODEC_ERR_UNSUPPORTEDOPERATION), "Got unexpected hr %#x, i %u.\n", hr, i); if (tests[i].metadata_supported)
@@ -3126,8 +3125,7 @@ static void test_metadata_writer(void) if (querywriter) { IWICMetadataQueryWriter_Release(querywriter);
if (querywriter2)
IWICMetadataQueryWriter_Release(querywriter2);
IWICMetadataQueryWriter_Release(querywriter2); IWICMetadataBlockWriter_Release(blockwriter); } IWICBitmapFrameEncode_Release(frameencode);
Signed-off-by: Esme Povirk esme@codeweavers.com
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/windowscodecs/bmpencode.c | 12 +++++++++--- dlls/windowscodecs/tests/metadata.c | 4 ++-- 2 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/dlls/windowscodecs/bmpencode.c b/dlls/windowscodecs/bmpencode.c index 30b1f361c98..e87d66a2e63 100644 --- a/dlls/windowscodecs/bmpencode.c +++ b/dlls/windowscodecs/bmpencode.c @@ -397,10 +397,16 @@ static HRESULT WINAPI BmpFrameEncode_Commit(IWICBitmapFrameEncode *iface) }
static HRESULT WINAPI BmpFrameEncode_GetMetadataQueryWriter(IWICBitmapFrameEncode *iface, - IWICMetadataQueryWriter **ppIMetadataQueryWriter) + IWICMetadataQueryWriter **query_writer) { - FIXME("(%p, %p): stub\n", iface, ppIMetadataQueryWriter); - return E_NOTIMPL; + BmpFrameEncode *encoder = impl_from_IWICBitmapFrameEncode(iface); + + TRACE("iface %p, query_writer %p.\n", iface, query_writer); + + if (!encoder->initialized) + return WINCODEC_ERR_NOTINITIALIZED; + + return WINCODEC_ERR_UNSUPPORTEDOPERATION; }
static const IWICBitmapFrameEncodeVtbl BmpFrameEncode_Vtbl = { diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index c1339e4bd1d..e6e46c389f9 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -3106,7 +3106,7 @@ static void test_metadata_writer(void) ok(hr == (tests[i].metadata_supported ? S_OK : E_INVALIDARG), "Got unexpected hr %#x, i %u.\n", hr, i);
hr = IWICBitmapFrameEncode_GetMetadataQueryWriter(frameencode, &querywriter2); - todo_wine_if(!i) ok(hr == (tests[i].succeeds_unitialized ? S_OK : WINCODEC_ERR_NOTINITIALIZED), + ok(hr == (tests[i].succeeds_unitialized ? S_OK : WINCODEC_ERR_NOTINITIALIZED), "Got unexpected hr %#x, i %u.\n", hr, i); if (hr == S_OK) IWICMetadataQueryWriter_Release(querywriter2); @@ -3115,7 +3115,7 @@ static void test_metadata_writer(void) ok(hr == S_OK, "Got unexpected hr %#x, i %u.\n", hr, i);
hr = IWICBitmapFrameEncode_GetMetadataQueryWriter(frameencode, &querywriter2); - todo_wine_if(!i) ok(hr == (tests[i].metadata_supported ? S_OK : WINCODEC_ERR_UNSUPPORTEDOPERATION), + ok(hr == (tests[i].metadata_supported ? S_OK : WINCODEC_ERR_UNSUPPORTEDOPERATION), "Got unexpected hr %#x, i %u.\n", hr, i);
if (tests[i].metadata_supported)
Signed-off-by: Esme Povirk esme@codeweavers.com
Why did you rename the variable?