From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/metadatahandler.c | 74 +++++++++++++++++++++----- dlls/windowscodecs/tests/metadata.c | 45 +++++++++++++++- dlls/windowscodecs/wincodecs_private.h | 1 + 3 files changed, 107 insertions(+), 13 deletions(-)
diff --git a/dlls/windowscodecs/metadatahandler.c b/dlls/windowscodecs/metadatahandler.c index b68b6656980..eb69903d589 100644 --- a/dlls/windowscodecs/metadatahandler.c +++ b/dlls/windowscodecs/metadatahandler.c @@ -228,13 +228,14 @@ static HRESULT WINAPI MetadataHandler_GetValueByIndex(IWICMetadataWriter *iface, }
static MetadataItem *metadatahandler_get_item(MetadataHandler *handler, const PROPVARIANT *schema, - const PROPVARIANT *id) + const PROPVARIANT *id, unsigned int *item_index) { PROPVARIANT index; GUID format; HRESULT hr; UINT i;
+ if (item_index) *item_index = 0; PropVariantInit(&index); if (id->vt == VT_CLSID && SUCCEEDED(PropVariantChangeType(&index, schema, 0, VT_UI4))) { @@ -254,7 +255,11 @@ static MetadataItem *metadatahandler_get_item(MetadataHandler *handler, const PR { if (IsEqualGUID(&format, id->puuid)) { - if (!index.ulVal) return &handler->items[i]; + if (!index.ulVal) + { + if (item_index) *item_index = i; + return &handler->items[i]; + } --index.ulVal; } } @@ -271,12 +276,22 @@ static MetadataItem *metadatahandler_get_item(MetadataHandler *handler, const PR
if (PropVariantCompareEx(id, &handler->items[i].id, 0, PVCF_USESTRCMPI) != 0) continue;
+ if (item_index) *item_index = i; return &handler->items[i]; }
return NULL; }
+static void metadata_handler_remove_item(MetadataHandler *handler, unsigned int index) +{ + clear_metadata_item(&handler->items[index]); + handler->item_count--; + if (index != handler->item_count) + memmove(&handler->items[index], &handler->items[index + 1], + (handler->item_count - index) * sizeof(*handler->items)); +} + static HRESULT WINAPI MetadataHandler_GetValue(IWICMetadataWriter *iface, const PROPVARIANT *schema, const PROPVARIANT *id, PROPVARIANT *value) { @@ -290,7 +305,7 @@ static HRESULT WINAPI MetadataHandler_GetValue(IWICMetadataWriter *iface,
EnterCriticalSection(&This->lock);
- if ((item = metadatahandler_get_item(This, schema, id))) + if ((item = metadatahandler_get_item(This, schema, id, NULL))) { hr = value ? PropVariantCopy(value, &item->value) : S_OK; } @@ -323,7 +338,7 @@ static HRESULT WINAPI MetadataHandler_SetValue(IWICMetadataWriter *iface,
EnterCriticalSection(&This->lock);
- if ((item = metadatahandler_get_item(This, schema, id))) + if ((item = metadatahandler_get_item(This, schema, id, NULL))) { PropVariantClear(&item->value); hr = PropVariantCopy(&item->value, value); @@ -370,17 +385,52 @@ static HRESULT WINAPI MetadataHandler_SetValueByIndex(IWICMetadataWriter *iface, }
static HRESULT WINAPI MetadataHandler_RemoveValue(IWICMetadataWriter *iface, - const PROPVARIANT *pvarSchema, const PROPVARIANT *pvarId) + const PROPVARIANT *schema, const PROPVARIANT *id) { - FIXME("(%p,%p,%p): stub\n", iface, pvarSchema, pvarId); - return E_NOTIMPL; + MetadataHandler *handler = impl_from_IWICMetadataWriter(iface); + unsigned int index; + HRESULT hr = S_OK; + + TRACE("(%p,%p,%p)\n", iface, schema, id); + + if (handler->vtable->flags & METADATAHANDLER_FIXED_ITEMS) + return WINCODEC_ERR_UNSUPPORTEDOPERATION; + + EnterCriticalSection(&handler->lock); + + if (metadatahandler_get_item(handler, schema, id, &index)) + { + metadata_handler_remove_item(handler, index); + } + else + { + hr = WINCODEC_ERR_PROPERTYNOTFOUND; + } + + LeaveCriticalSection(&handler->lock); + + return hr; }
-static HRESULT WINAPI MetadataHandler_RemoveValueByIndex(IWICMetadataWriter *iface, - UINT nIndex) +static HRESULT WINAPI MetadataHandler_RemoveValueByIndex(IWICMetadataWriter *iface, UINT index) { - FIXME("(%p,%u): stub\n", iface, nIndex); - return E_NOTIMPL; + MetadataHandler *handler = impl_from_IWICMetadataWriter(iface); + HRESULT hr = S_OK; + + TRACE("(%p,%u)\n", iface, index); + + EnterCriticalSection(&handler->lock); + + if (index >= handler->item_count) + hr = E_INVALIDARG; + else if (handler->vtable->flags & METADATAHANDLER_FIXED_ITEMS) + hr = WINCODEC_ERR_UNSUPPORTEDOPERATION; + else + metadata_handler_remove_item(handler, index); + + LeaveCriticalSection(&handler->lock); + + return hr; }
static const IWICMetadataWriterVtbl MetadataHandler_Vtbl = { @@ -882,7 +932,7 @@ HRESULT UnknownMetadataReader_CreateInstance(REFIID iid, void** ppv)
static const MetadataHandlerVtbl UnknownMetadataWriter_Vtbl = { - .flags = METADATAHANDLER_IS_WRITER, + .flags = METADATAHANDLER_IS_WRITER | METADATAHANDLER_FIXED_ITEMS, .clsid = &CLSID_WICUnknownMetadataWriter, .fnLoad = LoadUnknownMetadata }; diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index 97fa186cf00..fb73451524e 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -837,8 +837,16 @@ static void test_metadata_unknown(void) todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
+ PropVariantInit(&id); + PropVariantInit(&schema); + hr = IWICMetadataWriter_RemoveValue(writer, &schema, &id); + ok(hr == WINCODEC_ERR_UNSUPPORTEDOPERATION, "Unexpected hr %#lx.\n", hr); + + id.vt = VT_UI4; + hr = IWICMetadataWriter_RemoveValue(writer, &schema, &id); + ok(hr == WINCODEC_ERR_UNSUPPORTEDOPERATION, "Unexpected hr %#lx.\n", hr); + hr = IWICMetadataWriter_RemoveValueByIndex(writer, 0); - todo_wine ok(hr == WINCODEC_ERR_UNSUPPORTEDOPERATION, "Unexpected hr %#lx.\n", hr);
hr = IWICMetadataWriter_GetCount(writer, &count); @@ -1829,6 +1837,7 @@ static void test_metadata_Exif(void)
static void test_metadata_Gps(void) { + PROPVARIANT schema, id, value; IWICMetadataReader *reader; IWICMetadataWriter *writer; UINT count=0; @@ -1877,6 +1886,31 @@ static void test_metadata_Gps(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(!count, "Unexpected count %u.\n", count);
+ id.vt = VT_UI2; + id.uiVal = 0x300; + value.vt = VT_UI2; + value.ulVal = 555; + PropVariantInit(&schema); + 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.uiVal = 1; + hr = IWICMetadataWriter_RemoveValue(writer, &schema, &id); + ok(hr == WINCODEC_ERR_PROPERTYNOTFOUND, "Unexpected hr %#lx.\n", hr); + + schema.vt = VT_UI4; + id.uiVal = 0x300; + hr = IWICMetadataWriter_RemoveValue(writer, &schema, &id); + 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, "Unexpected count %u.\n", count); + load_stream(writer, (const char *)&IFD_data, sizeof(IFD_data), 0); load_stream(writer, (const char *)&IFD_data, sizeof(IFD_data), WICPersistOptionNoCacheStream);
@@ -5377,6 +5411,15 @@ static void test_metadata_App1(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(!count, "Unexpected count %u.\n", count);
+ id.vt = VT_UI2; + id.uiVal = 0x300; + value.vt = VT_UI2; + value.ulVal = 555; + PropVariantInit(&schema); + hr = IWICMetadataWriter_SetValue(writer, &schema, &id, &value); + todo_wine + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + IWICMetadataWriter_Release(writer);
IWICComponentFactory_Release(factory); diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h index fb3ef312851..c255df06f84 100644 --- a/dlls/windowscodecs/wincodecs_private.h +++ b/dlls/windowscodecs/wincodecs_private.h @@ -208,6 +208,7 @@ typedef struct _MetadataItem enum metadatahandler_flags { METADATAHANDLER_IS_WRITER = 0x1, + METADATAHANDLER_FIXED_ITEMS = 0x2, /* Items cannot be added or removed. */ };
typedef struct _MetadataHandlerVtbl