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)