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(); }