From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/metadataquery.c | 377 +++++++++++++++++++++++++--- dlls/windowscodecs/tests/metadata.c | 35 +-- 2 files changed, 350 insertions(+), 62 deletions(-)
diff --git a/dlls/windowscodecs/metadataquery.c b/dlls/windowscodecs/metadataquery.c index 1fd75bbff00..276f8725e75 100644 --- a/dlls/windowscodecs/metadataquery.c +++ b/dlls/windowscodecs/metadataquery.c @@ -167,22 +167,22 @@ static const struct VARTYPE vt; } str2vt[] = { - { 4, {'c','h','a','r'}, VT_I1 }, - { 5, {'u','c','h','a','r'}, VT_UI1 }, - { 5, {'s','h','o','r','t'}, VT_I2 }, - { 6, {'u','s','h','o','r','t'}, VT_UI2 }, - { 4, {'l','o','n','g'}, VT_I4 }, - { 5, {'u','l','o','n','g'}, VT_UI4 }, - { 3, {'i','n','t'}, VT_I4 }, - { 4, {'u','i','n','t'}, VT_UI4 }, - { 8, {'l','o','n','g','l','o','n','g'}, VT_I8 }, - { 9, {'u','l','o','n','g','l','o','n','g'}, VT_UI8 }, - { 5, {'f','l','o','a','t'}, VT_R4 }, - { 6, {'d','o','u','b','l','e'}, VT_R8 }, - { 3, {'s','t','r'}, VT_LPSTR }, - { 4, {'w','s','t','r'}, VT_LPWSTR }, - { 4, {'g','u','i','d'}, VT_CLSID }, - { 4, {'b','o','o','l'}, VT_BOOL } + { 4, L"char", VT_I1 }, + { 5, L"uchar", VT_UI1 }, + { 5, L"short", VT_I2 }, + { 6, L"ushort", VT_UI2 }, + { 4, L"long", VT_I4 }, + { 5, L"ulong", VT_UI4 }, + { 3, L"int", VT_I4 }, + { 4, L"uint", VT_UI4 }, + { 8, L"longlong", VT_I8 }, + { 9, L"ulonglong", VT_UI8 }, + { 5, L"float", VT_R4 }, + { 6, L"double", VT_R8 }, + { 3, L"str", VT_LPSTR }, + { 4, L"wstr", VT_LPWSTR }, + { 4, L"guid", VT_CLSID }, + { 4, L"bool", VT_BOOL } };
static VARTYPE map_type(struct string_t *str) @@ -204,6 +204,19 @@ static VARTYPE map_type(struct string_t *str) return VT_ILLEGAL; }
+static const WCHAR *get_type_name(VARTYPE vt) +{ + UINT i; + + for (i = 0; i < ARRAY_SIZE(str2vt); i++) + { + if (str2vt[i].vt == vt) + return str2vt[i].str; + } + + return NULL; +} + struct query_component { unsigned int index; @@ -730,9 +743,9 @@ static HRESULT WINAPI query_handler_GetMetadataByName(IWICMetadataQueryWriter *i return hr; }
-static WCHAR *query_get_guid_item_string(WCHAR *str, unsigned int len, const GUID *guid) +static WCHAR *query_get_guid_item_string(WCHAR *str, unsigned int len, const GUID *guid, bool resolve) { - if (SUCCEEDED(WICMapGuidToShortName(guid, len, str, NULL))) + if (resolve && SUCCEEDED(WICMapGuidToShortName(guid, len, str, NULL))) return str;
swprintf(str, len, L"{guid=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", @@ -745,6 +758,20 @@ struct string_enumerator { IEnumString IEnumString_iface; LONG ref; + + struct + { + struct + { + GUID guid; + unsigned int index; + } *entries; + size_t count; + size_t capacity; + } guids; + + IEnumUnknown *object_enumerator; + IWICEnumMetadataItem *metadata_enumerator; };
static struct string_enumerator *impl_from_IEnumString(IEnumString *iface) @@ -783,48 +810,299 @@ static ULONG WINAPI string_enumerator_AddRef(IEnumString *iface)
static ULONG WINAPI string_enumerator_Release(IEnumString *iface) { - struct string_enumerator *this = impl_from_IEnumString(iface); - ULONG ref = InterlockedDecrement(&this->ref); + struct string_enumerator *enumerator = impl_from_IEnumString(iface); + ULONG ref = InterlockedDecrement(&enumerator->ref);
TRACE("iface %p, ref %lu.\n", iface, ref);
if (!ref) - free(this); + { + if (enumerator->object_enumerator) + IEnumUnknown_Release(enumerator->object_enumerator); + if (enumerator->metadata_enumerator) + IWICEnumMetadataItem_Release(enumerator->metadata_enumerator); + free(enumerator->guids.entries); + free(enumerator); + }
return ref; }
-static HRESULT WINAPI string_enumerator_Next(IEnumString *iface, ULONG count, LPOLESTR *strings, ULONG *ret) +static HRESULT string_enumerator_update_guid_index(struct string_enumerator *enumerator, + GUID *guid, unsigned int *index, IUnknown *object) { - FIXME("iface %p, count %lu, strings %p, ret %p stub.\n", iface, count, strings, ret); + IWICMetadataReader *reader = NULL; + HRESULT hr; + size_t i; + + *index = 0; + + hr = IUnknown_QueryInterface(object, &IID_IWICMetadataReader, (void **)&reader); + + if (SUCCEEDED(hr)) + hr = IWICMetadataReader_GetMetadataFormat(reader, guid); + + if (reader) + IWICMetadataReader_Release(reader); + + if (SUCCEEDED(hr)) + { + for (i = 0; i < enumerator->guids.count; ++i) + { + if (IsEqualGUID(&enumerator->guids.entries[i].guid, guid)) + { + *index = ++enumerator->guids.entries[i].index; + return S_OK; + } + } + + if (!wincodecs_array_reserve((void **)&enumerator->guids.entries, &enumerator->guids.capacity, + enumerator->guids.count + 1, sizeof(*enumerator->guids.entries))) + { + return E_OUTOFMEMORY; + } + enumerator->guids.entries[enumerator->guids.count].guid = *guid; + enumerator->guids.entries[enumerator->guids.count].index = 0; + enumerator->guids.count++; + } + + return hr; +}
- if (!strings || !ret) +static HRESULT get_query_item_name(const PROPVARIANT *var, WCHAR **name) +{ + const WCHAR *type; + WCHAR buffer[64]; + PROPVARIANT dest; + HRESULT hr; + size_t len; + + if (var->vt == VT_CLSID) + { + const WCHAR *value = query_get_guid_item_string(buffer, ARRAY_SIZE(buffer), var->puuid, false); + if (!(*name = wcsdup(value))) + return E_OUTOFMEMORY; + return S_OK; + } + + PropVariantInit(&dest); + type = get_type_name(var->vt); + if (type) + { + if (FAILED(hr = PropVariantChangeType(&dest, var, 0, VT_LPWSTR))) return hr; + } + + len = 4; + if (type) len += wcslen(type); + if (dest.pwszVal) len += wcslen(dest.pwszVal); + if (!(*name = malloc(len * sizeof(WCHAR)))) + { + PropVariantClear(&dest); + return E_OUTOFMEMORY; + } + + if (type) + swprintf(*name, len, L"{%s=%s}", type, dest.pwszVal); + else + wcscpy(*name, L"{}"); + PropVariantClear(&dest); + + return S_OK; +} + +static HRESULT WINAPI string_enumerator_Next(IEnumString *iface, ULONG count, + LPOLESTR *strings, ULONG *fetched) +{ + struct string_enumerator *enumerator = impl_from_IEnumString(iface); + WCHAR *str, name[64]; + unsigned int index; + IUnknown **objects; + HRESULT hr; + GUID guid; + ULONG tmp; + + TRACE("iface %p, count %lu, strings %p, fetched %p.\n", iface, count, strings, fetched); + + if (!strings) return E_INVALIDARG;
- *ret = 0; - return count ? S_FALSE : S_OK; + if (!fetched) fetched = &tmp; + *fetched = 0; + + if (enumerator->object_enumerator) + { + if (!(objects = calloc(count, sizeof(*objects)))) + return E_OUTOFMEMORY; + + if (SUCCEEDED(hr = IEnumUnknown_Next(enumerator->object_enumerator, count, objects, fetched))) + { + for (ULONG i = 0; i < *fetched; ++i) + { + index = 0; + hr = string_enumerator_update_guid_index(enumerator, &guid, &index, objects[i]); + if (FAILED(hr)) break; + + if (!(str = CoTaskMemAlloc(64 * sizeof(WCHAR)))) + { + hr = E_OUTOFMEMORY; + break; + } + + query_get_guid_item_string(name, ARRAY_SIZE(name), &guid, true); + + if (index) + swprintf(str, 64, L"/[%u]%s", index, name); + else + swprintf(str, 64, L"/%s", name); + + strings[i] = str; + } + + for (ULONG i = 0; i < *fetched; ++i) + IUnknown_Release(objects[i]); + } + + free(objects); + } + else if (enumerator->metadata_enumerator) + { + PROPVARIANT *vars, *schemas, *ids; + ULONG vars_count = max(count, 1); + + if (!(vars = calloc(vars_count * 2, sizeof(*vars)))) + return E_OUTOFMEMORY; + schemas = vars; + ids = vars + vars_count; + + if (SUCCEEDED(hr = IWICEnumMetadataItem_Next(enumerator->metadata_enumerator, count, schemas, ids, NULL, fetched))) + { + for (ULONG i = 0; i < *fetched; ++i) + { + WCHAR *schema_name = NULL, *id_name = NULL; + size_t size; + + if (schemas[i].vt != VT_EMPTY) + hr = get_query_item_name(&schemas[i], &schema_name); + if (SUCCEEDED(hr)) + hr = get_query_item_name(&ids[i], &id_name); + + if (SUCCEEDED(hr)) + { + size = 4; + if (schema_name) + size += wcslen(schema_name); + if (id_name) + size += wcslen(id_name); + + if (!(strings[i] = CoTaskMemAlloc(size * sizeof(WCHAR)))) + hr = E_OUTOFMEMORY; + + if (SUCCEEDED(hr)) + { + wcscpy(strings[i], L"/"); + if (schema_name) + { + wcscat(strings[i], schema_name); + wcscat(strings[i], L":"); + } + wcscat(strings[i], id_name); + } + } + + free(schema_name); + free(id_name); + PropVariantClear(&schemas[i]); + PropVariantClear(&ids[i]); + } + } + + free(vars); + } + + return *fetched < count ? S_FALSE : S_OK; }
static HRESULT WINAPI string_enumerator_Reset(IEnumString *iface) { + struct string_enumerator *enumerator = impl_from_IEnumString(iface); + TRACE("iface %p.\n", iface);
+ enumerator->guids.count = 0; + if (enumerator->object_enumerator) + return IEnumUnknown_Reset(enumerator->object_enumerator); + else if (enumerator->metadata_enumerator) + return IWICEnumMetadataItem_Reset(enumerator->metadata_enumerator); + return S_OK; }
static HRESULT WINAPI string_enumerator_Skip(IEnumString *iface, ULONG count) { - FIXME("iface %p, count %lu stub.\n", iface, count); + struct string_enumerator *enumerator = impl_from_IEnumString(iface); + unsigned int index; + HRESULT hr = S_OK; + IUnknown *object; + ULONG fetched; + GUID guid; + + TRACE("iface %p, count %lu.\n", iface, count);
- return count ? S_FALSE : S_OK; + if (enumerator->object_enumerator) + { + while (count-- && IEnumUnknown_Next(enumerator->object_enumerator, 1, &object, &fetched) == S_OK) + { + string_enumerator_update_guid_index(enumerator, &guid, &index, object); + IUnknown_Release(object); + } + } + else if (enumerator->metadata_enumerator) + { + hr = IWICEnumMetadataItem_Skip(enumerator->metadata_enumerator, count); + } + + return hr; }
+static void string_enumerator_init(struct string_enumerator *object, IEnumUnknown *object_enumerator, + IWICEnumMetadataItem *metadata_enumerator); + static HRESULT WINAPI string_enumerator_Clone(IEnumString *iface, IEnumString **out) { - FIXME("iface %p, out %p stub.\n", iface, out); + struct string_enumerator *enumerator = impl_from_IEnumString(iface); + IWICEnumMetadataItem *metadata_enumerator = NULL; + IEnumUnknown *object_enumerator = NULL; + struct string_enumerator *object; + HRESULT hr = S_OK; + + TRACE("iface %p, out %p.\n", iface, out);
*out = NULL; - return E_NOTIMPL; + + if (!(object = calloc(1, sizeof(*object)))) + return E_OUTOFMEMORY; + + if (enumerator->object_enumerator) + hr = IEnumUnknown_Clone(enumerator->object_enumerator, &object_enumerator); + else if (enumerator->metadata_enumerator) + hr = IWICEnumMetadataItem_Clone(enumerator->metadata_enumerator, &metadata_enumerator); + + if (FAILED(hr)) + { + free(object); + return hr; + } + + string_enumerator_init(object, object_enumerator, metadata_enumerator); + + if (metadata_enumerator) + IWICEnumMetadataItem_Release(metadata_enumerator); + if (object_enumerator) + IEnumUnknown_Release(object_enumerator); + + *out = &object->IEnumString_iface; + + return hr; }
static const IEnumStringVtbl string_enumerator_vtbl = @@ -838,15 +1116,42 @@ static const IEnumStringVtbl string_enumerator_vtbl = string_enumerator_Clone };
-static HRESULT string_enumerator_create(IEnumString **enum_string) +static void string_enumerator_init(struct string_enumerator *object, IEnumUnknown *object_enumerator, + IWICEnumMetadataItem *metadata_enumerator) { + object->IEnumString_iface.lpVtbl = &string_enumerator_vtbl; + object->ref = 1; + + object->object_enumerator = object_enumerator; + if (object->object_enumerator) + IEnumUnknown_AddRef(object->object_enumerator); + object->metadata_enumerator = metadata_enumerator; + if (object->metadata_enumerator) + IWICEnumMetadataItem_AddRef(object->metadata_enumerator); +} + +static HRESULT string_enumerator_create(struct query_handler *handler, IEnumString **enum_string) +{ + IWICEnumMetadataItem *metadata_enumerator = NULL; + IEnumUnknown *object_enumerator = NULL; struct string_enumerator *object;
if (!(object = calloc(1, sizeof(*object)))) return E_OUTOFMEMORY;
- object->IEnumString_iface.lpVtbl = &string_enumerator_vtbl; - object->ref = 1; + if (is_block_handler(handler)) + { + IWICMetadataBlockReader_GetEnumerator(handler->object.block_reader, &object_enumerator); + } + else + { + IWICMetadataReader_GetEnumerator(handler->object.reader, &metadata_enumerator); + } + + string_enumerator_init(object, object_enumerator, metadata_enumerator); + + if (object_enumerator) + IEnumUnknown_Release(object_enumerator);
*enum_string = &object->IEnumString_iface;
@@ -856,9 +1161,11 @@ static HRESULT string_enumerator_create(IEnumString **enum_string) static HRESULT WINAPI query_handler_GetEnumerator(IWICMetadataQueryWriter *iface, IEnumString **enum_string) { + struct query_handler *handler = impl_from_IWICMetadataQueryWriter(iface); + TRACE("iface %p, enum_string %p.\n", iface, enum_string);
- return string_enumerator_create(enum_string); + return string_enumerator_create(handler, enum_string); }
static HRESULT WINAPI query_handler_SetMetadataByName(IWICMetadataQueryWriter *iface, LPCWSTR name, const PROPVARIANT *value) @@ -941,7 +1248,7 @@ static HRESULT create_query_handler(IUnknown *block_handler, enum metadata_objec }
buff[0] = '/'; - query_get_guid_item_string(buff + 1, ARRAY_SIZE(buff) - 1, &guid); + query_get_guid_item_string(buff + 1, ARRAY_SIZE(buff) - 1, &guid, true); root = buff; } } diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index 039bbdb6079..f6f10b94adf 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -767,15 +767,10 @@ static void test_metadata_unknown(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); str = NULL; hr = IEnumString_Next(enum_string, 1, &str, &fetched); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(fetched == 1, "Unexpected count %lu.\n", fetched); - if (hr == S_OK) - { - ok(!wcscmp(str, L"/{}"), "Unexpected query %s.\n", wine_dbgstr_w(str)); - CoTaskMemFree(str); - } + ok(!wcscmp(str, L"/{}"), "Unexpected query %s.\n", wine_dbgstr_w(str)); + CoTaskMemFree(str); IEnumString_Release(enum_string);
PropVariantInit(&value); @@ -4639,15 +4634,10 @@ static void test_queryreader(void) hr = IWICMetadataQueryReader_GetEnumerator(reader, &enum_string); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IEnumString_Next(enum_string, 1, &str, NULL); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (hr == S_OK) - { - ok(!wcscmp(str, L"/ifd"), "Unexpected query %s.\n", wine_dbgstr_w(str)); - CoTaskMemFree(str); - } + ok(!wcscmp(str, L"/ifd"), "Unexpected query %s.\n", wine_dbgstr_w(str)); + CoTaskMemFree(str); hr = IEnumString_Next(enum_string, 1, &str, NULL); - todo_wine ok(hr == S_FALSE, "Unexpected hr %#lx.\n", hr);
hr = IWICComponentFactory_CreateMetadataWriter(factory, &GUID_MetadataFormatApp1, NULL, 0, &writer); @@ -4661,28 +4651,19 @@ static void test_queryreader(void)
/* Existing enumerator does not pick it up. */ hr = IEnumString_Next(enum_string, 1, &str, NULL); - todo_wine ok(hr == S_FALSE, "Unexpected hr %#lx.\n", hr); IEnumString_Release(enum_string);
hr = IWICMetadataQueryReader_GetEnumerator(reader, &enum_string); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IEnumString_Next(enum_string, 1, &str, NULL); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (hr == S_OK) - { - ok(!wcscmp(str, L"/ifd"), "Unexpected query %s.\n", wine_dbgstr_w(str)); - CoTaskMemFree(str); - } + ok(!wcscmp(str, L"/ifd"), "Unexpected query %s.\n", wine_dbgstr_w(str)); + CoTaskMemFree(str); hr = IEnumString_Next(enum_string, 1, &str, NULL); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (hr == S_OK) - { - ok(!wcscmp(str, L"/app1"), "Unexpected query %s.\n", wine_dbgstr_w(str)); - CoTaskMemFree(str); - } + ok(!wcscmp(str, L"/app1"), "Unexpected query %s.\n", wine_dbgstr_w(str)); + CoTaskMemFree(str);
IEnumString_Release(enum_string);
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/tests/metadata.c | 94 +++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+)
diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index f6f10b94adf..994f9647d33 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -1345,10 +1345,16 @@ static void test_metadata_hIST(void)
static void test_metadata_tIME(void) { + IWICMetadataQueryReader *query_reader, *query_reader2; + IWICComponentFactory *factory; HRESULT hr; IWICMetadataReader *reader; IWICMetadataWriter *writer; + IEnumString *enum_string; + PROPVARIANT value; UINT i, count; + ULONG fetched; + WCHAR *str; GUID format; static const struct test_data td[] = { @@ -1374,6 +1380,10 @@ static void test_metadata_tIME(void) ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG) /*winxp*/, "CoCreateInstance failed, hr=%lx\n", hr); if (FAILED(hr)) return;
+ hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, + &IID_IWICComponentFactory, (void **)&factory); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_interface(reader, &IID_IWICMetadataReader, TRUE); check_interface(reader, &IID_IPersist, TRUE); check_interface(reader, &IID_IPersistStream, TRUE); @@ -1392,6 +1402,62 @@ static void test_metadata_tIME(void)
compare_metadata(reader, td, count);
+ /* Query reader. */ + hr = create_query_reader_from_metadata_reader(factory, reader, &GUID_ContainerFormatPng, &query_reader); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IWICMetadataQueryReader_GetEnumerator(query_reader, &enum_string); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IEnumString_Next(enum_string, 1, &str, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine + ok(!wcscmp(str, L"/tIME"), "Unexpected query %s.\n", wine_dbgstr_w(str)); + CoTaskMemFree(str); + IEnumString_Release(enum_string); + + PropVariantInit(&value); + hr = IWICMetadataQueryReader_GetMetadataByName(query_reader, L"/tIME", &value); + todo_wine + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); +if (hr == S_OK) +{ + ok(value.vt == VT_UNKNOWN, "Unexpected value type %d.\n", value.vt); + hr = IUnknown_QueryInterface(value.punkVal, &IID_IWICMetadataQueryReader, (void **)&query_reader2); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + PropVariantClear(&value); + + hr = IWICMetadataQueryReader_GetEnumerator(query_reader2, &enum_string); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + for (i = 0; i < ARRAY_SIZE(td); ++i) + { + WCHAR buff[16]; + + str = NULL; + hr = IEnumString_Next(enum_string, 1, &str, &fetched); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(fetched == 1, "Unexpected count %lu.\n", fetched); + + wcscpy(buff, L"/"); + wcscat(buff, td[i].id_string); + + ok(!wcscmp(str, buff), "Unexpected query %s.\n", wine_dbgstr_w(str)); + CoTaskMemFree(str); + } + + IEnumString_Release(enum_string); + + PropVariantInit(&value); + hr = IWICMetadataQueryReader_GetMetadataByName(query_reader2, L"/Day", &value); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(value.vt == VT_UI1, "Unexpected type %d.\n", value.vt); + ok(value.bVal == 2, "Unexpected value %u.\n", value.bVal); + PropVariantClear(&value); + + IWICMetadataQueryReader_Release(query_reader2); +} + IWICMetadataQueryReader_Release(query_reader); + IWICMetadataReader_Release(reader);
hr = CoCreateInstance(&CLSID_WICPngTimeMetadataWriter, NULL, CLSCTX_INPROC_SERVER, @@ -1425,6 +1491,7 @@ static void test_metadata_tIME(void) load_stream(writer, metadata_tIME, sizeof(metadata_tIME), WICPersistOptionNoCacheStream);
IWICMetadataWriter_Release(writer); + IWICComponentFactory_Release(factory); }
static inline USHORT ushort_bswap(USHORT s) @@ -5918,10 +5985,12 @@ static void test_CreateQueryWriterFromReader(void) IWICComponentFactory *factory; IWICBitmapDecoder *decoder; IWICMetadataReader *reader; + IEnumString *enum_string; PROPVARIANT value; IStream *stream; WCHAR buff[64]; UINT count, len; + WCHAR *str; HRESULT hr;
hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, @@ -5959,6 +6028,31 @@ if (hr == S_OK) hr = IWICMetadataQueryWriter_GetLocation(query_writer, ARRAY_SIZE(buff), buff, &len); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(!wcscmp(buff, L"/ifd"), "Unexpected location %s.\n", wine_dbgstr_w(buff)); + + hr = IWICMetadataQueryWriter_RemoveMetadataByName(query_writer, L"/"); + ok(hr == WINCODEC_ERR_PROPERTYNOTFOUND, "Unexpected hr %#lx.\n", hr); + + hr = IWICMetadataQueryWriter_RemoveMetadataByName(query_writer, L"/exif"); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IWICMetadataQueryWriter_GetEnumerator(query_writer, &enum_string); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IEnumString_Next(enum_string, 1, &str, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!wcscmp(str, L"/{ushort=256}"), "Unexpected query %s.\n", debugstr_w(str)); + CoTaskMemFree(str); + hr = IEnumString_Next(enum_string, 1, &str, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!wcscmp(str, L"/{ushort=257}"), "Unexpected query %s.\n", debugstr_w(str)); + CoTaskMemFree(str); + hr = IEnumString_Next(enum_string, 1, &str, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!wcscmp(str, L"/{ushort=34853}"), "Unexpected query %s.\n", debugstr_w(str)); + CoTaskMemFree(str); + hr = IEnumString_Next(enum_string, 1, &str, NULL); + ok(hr == S_FALSE, "Unexpected hr %#lx.\n", hr); + IEnumString_Release(enum_string); + IWICMetadataQueryWriter_Release(query_writer); }
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/metadataquery.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/dlls/windowscodecs/metadataquery.c b/dlls/windowscodecs/metadataquery.c index 276f8725e75..43b9a782581 100644 --- a/dlls/windowscodecs/metadataquery.c +++ b/dlls/windowscodecs/metadataquery.c @@ -902,9 +902,16 @@ static HRESULT get_query_item_name(const PROPVARIANT *var, WCHAR **name) }
if (type) - swprintf(*name, len, L"{%s=%s}", type, dest.pwszVal); + { + if (var->vt == VT_LPWSTR) + swprintf(*name, len, L"%s", dest.pwszVal); + else + swprintf(*name, len, L"{%s=%s}", type, dest.pwszVal); + } else + { wcscpy(*name, L"{}"); + } PropVariantClear(&dest);
return S_OK;
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/imgfactory.c | 14 ++++------ dlls/windowscodecs/metadataquery.c | 37 ++++++++++++++++++++++++++ dlls/windowscodecs/tests/metadata.c | 8 +----- dlls/windowscodecs/wincodecs_private.h | 4 +++ 4 files changed, 47 insertions(+), 16 deletions(-)
diff --git a/dlls/windowscodecs/imgfactory.c b/dlls/windowscodecs/imgfactory.c index 8de1d370a38..29f91e6cbbd 100644 --- a/dlls/windowscodecs/imgfactory.c +++ b/dlls/windowscodecs/imgfactory.c @@ -1020,12 +1020,11 @@ static HRESULT WINAPI ImagingFactory_CreateQueryWriter(IWICImagingFactory2 *ifac }
static HRESULT WINAPI ImagingFactory_CreateQueryWriterFromReader(IWICImagingFactory2 *iface, - IWICMetadataQueryReader *pIQueryReader, const GUID *pguidVendor, - IWICMetadataQueryWriter **ppIQueryWriter) + IWICMetadataQueryReader *query_reader, const GUID *vendor, IWICMetadataQueryWriter **query_writer) { - FIXME("(%p,%p,%s,%p): stub\n", iface, pIQueryReader, debugstr_guid(pguidVendor), - ppIQueryWriter); - return E_NOTIMPL; + TRACE("(%p,%p,%s,%p)\n", iface, query_reader, debugstr_guid(vendor), query_writer); + + return create_metadata_query_writer_from_reader(query_reader, vendor, query_writer); }
static HRESULT WINAPI ImagingFactory_CreateImageEncoder(IWICImagingFactory2 *iface, ID2D1Device *device, IWICImageEncoder **encoder) @@ -1633,9 +1632,6 @@ static HRESULT WINAPI ComponentFactory_CreateMetadataWriter(IWICComponentFactory return create_metadata_writer(format, vendor, options, writer); }
-static HRESULT create_metadata_writer_from_reader(IWICMetadataReader *reader, const GUID *vendor, - IWICMetadataWriter **out_writer); - static HRESULT metadata_writer_copy_items_from_reader(IWICMetadataWriter *writer, const GUID *vendor, IWICMetadataReader *reader) { IWICMetadataReader *sub_reader; @@ -1684,7 +1680,7 @@ static HRESULT metadata_writer_copy_items_from_reader(IWICMetadataWriter *writer return hr; }
-static HRESULT create_metadata_writer_from_reader(IWICMetadataReader *reader, const GUID *vendor, +HRESULT create_metadata_writer_from_reader(IWICMetadataReader *reader, const GUID *vendor, IWICMetadataWriter **out_writer) { IWICStreamProvider *stream_provider = NULL; diff --git a/dlls/windowscodecs/metadataquery.c b/dlls/windowscodecs/metadataquery.c index 43b9a782581..62456047593 100644 --- a/dlls/windowscodecs/metadataquery.c +++ b/dlls/windowscodecs/metadataquery.c @@ -1223,6 +1223,18 @@ static IWICMetadataQueryWriterVtbl query_handler_vtbl = query_handler_RemoveMetadataByName, };
+static struct query_handler *unsafe_impl_from_IWICMetadataQueryReader(IWICMetadataQueryReader *iface) +{ + if (!iface) + return NULL; + if (iface->lpVtbl != (IWICMetadataQueryReaderVtbl *)&query_handler_vtbl) + { + WARN("External query reader implementations are not supported.\n"); + return NULL; + } + return CONTAINING_RECORD(iface, struct query_handler, IWICMetadataQueryWriter_iface); +} + static HRESULT create_query_handler(IUnknown *block_handler, enum metadata_object_type object_type, const WCHAR *root, IWICMetadataQueryWriter **ret) { @@ -1289,6 +1301,31 @@ HRESULT MetadataQueryWriter_CreateInstance(IWICMetadataWriter *writer, IWICMetad return create_query_handler((IUnknown *)writer, WRITER, NULL, out); }
+HRESULT create_metadata_query_writer_from_reader(IWICMetadataQueryReader *query_reader, const GUID *vendor, + IWICMetadataQueryWriter **query_writer) +{ + struct query_handler *query_reader_obj = unsafe_impl_from_IWICMetadataQueryReader(query_reader); + IWICMetadataWriter *writer; + HRESULT hr; + + *query_writer = NULL; + + if (!query_reader_obj) + return E_FAIL; + + if (is_block_handler(query_reader_obj)) + return WINCODEC_ERR_UNEXPECTEDMETADATATYPE; + + hr = create_metadata_writer_from_reader(query_reader_obj->object.reader, vendor, &writer); + if (SUCCEEDED(hr)) + { + hr = create_query_handler((IUnknown *)writer, WRITER, NULL, query_writer); + IWICMetadataWriter_Release(writer); + } + + return hr; +} + static const struct { const GUID *guid; diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index 994f9647d33..9717015a153 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -6009,7 +6009,6 @@ static void test_CreateQueryWriterFromReader(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IWICComponentFactory_CreateQueryWriterFromReader(factory, query_reader, NULL, &query_writer); - todo_wine ok(hr == WINCODEC_ERR_UNEXPECTEDMETADATATYPE, "Unexpected hr %#lx.\n", hr);
PropVariantInit(&value); @@ -6067,7 +6066,6 @@ if (hr == S_OK)
hr = IWICComponentFactory_CreateQueryWriterFromReader(factory, (IWICMetadataQueryReader *)query_writer, NULL, &query_writer2); - todo_wine ok(hr == WINCODEC_ERR_UNEXPECTEDMETADATATYPE, "Unexpected hr %#lx.\n", hr); IWICMetadataQueryWriter_Release(query_writer);
@@ -6077,10 +6075,8 @@ if (hr == S_OK)
hr = IWICComponentFactory_CreateQueryWriterFromReader(factory, (IWICMetadataQueryReader *)query_writer, NULL, &query_writer2); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (hr == S_OK) - IWICMetadataQueryWriter_Release(query_writer2); + IWICMetadataQueryWriter_Release(query_writer2); if (query_writer) IWICMetadataQueryWriter_Release(query_writer);
@@ -6103,7 +6099,6 @@ if (hr == S_OK) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IWICComponentFactory_CreateQueryWriterFromReader(factory, query_reader, &GUID_VendorMicrosoft, &query_writer); - todo_wine ok(hr == WINCODEC_ERR_UNEXPECTEDMETADATATYPE, "Unexpected hr %#lx.\n", hr);
IWICMetadataQueryReader_Release(query_reader); @@ -6118,7 +6113,6 @@ if (hr == S_OK) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IWICComponentFactory_CreateQueryWriterFromReader(factory, query_reader, &GUID_VendorMicrosoft, &query_writer); - todo_wine ok(hr == WINCODEC_ERR_UNEXPECTEDMETADATATYPE, "Unexpected hr %#lx.\n", hr); IWICMetadataQueryReader_Release(query_reader);
diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h index 156b013a53f..9cf842721f7 100644 --- a/dlls/windowscodecs/wincodecs_private.h +++ b/dlls/windowscodecs/wincodecs_private.h @@ -344,6 +344,10 @@ HRESULT create_metadata_reader(REFGUID format, const GUID *vendor, DWORD options IWICMetadataReader **reader); HRESULT create_metadata_writer(REFGUID format, const GUID *vendor, DWORD options, IWICMetadataWriter **writer); +HRESULT create_metadata_query_writer_from_reader(IWICMetadataQueryReader *query_reader, const GUID *vendor, + IWICMetadataQueryWriter **query_writer); +HRESULT create_metadata_writer_from_reader(IWICMetadataReader *reader, const GUID *vendor, + IWICMetadataWriter **writer);
struct encoder_funcs;
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/tests/metadata.c | 128 ++++++++++++++++++++++++---- 1 file changed, 113 insertions(+), 15 deletions(-)
diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index 9717015a153..b3cb16527af 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -5023,14 +5023,17 @@ app1_data =
static void test_metadata_App1(void) { - IWICMetadataReader *reader, *ifd_reader, *exif_reader, *gps_reader; + IWICMetadataReader *reader, *reader2, *ifd_reader, *exif_reader, *gps_reader; + IStream *app1_stream, *stream, *ifd_stream, *gps_stream, *exif_stream; IWICMetadataQueryReader *query_reader, *query_reader2; IWICMetadataQueryWriter *query_writer, *query_writer2; + IWICPersistStream *persist_stream; IWICEnumMetadataItem *enumerator; - IStream *app1_stream, *stream2; IWICComponentFactory *factory; PROPVARIANT schema, id, value; IWICMetadataWriter *writer; + ULARGE_INTEGER pos; + LARGE_INTEGER move; UINT length, count; WCHAR path[64]; ULONG fetched; @@ -5119,11 +5122,69 @@ static void test_metadata_App1(void) ok(IsEqualGUID(&format, &GUID_MetadataFormatIfd), "Unexpected format %s.\n", wine_dbgstr_guid(&format)); check_persist_options(ifd_reader, 0);
- hr = get_persist_stream(ifd_reader, &stream2); + hr = get_persist_stream(ifd_reader, &ifd_stream); 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); + check_interface(ifd_stream, &IID_IWICStream, TRUE); + ok(!!ifd_stream && app1_stream != ifd_stream, "Unexpected stream.\n"); + + /* Stream is positioned right after header, and point to Ifd data. It's not + possible to make this offset an origin, as following data contains relative offsets. */ + move.QuadPart = 0; + hr = IStream_Seek(ifd_stream, move, STREAM_SEEK_CUR, &pos); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine + ok(pos.QuadPart == 8, "Unexpected position %s.\n", wine_dbgstr_longlong(pos.QuadPart)); + + hr = CoCreateInstance(&CLSID_WICIfdMetadataReader, NULL, CLSCTX_INPROC_SERVER, + &IID_IWICMetadataReader, (void **)&reader2); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IWICMetadataReader_QueryInterface(reader2, &IID_IWICPersistStream, (void **)&persist_stream); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IWICPersistStream_LoadEx(persist_stream, ifd_stream, NULL, 0); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + /* Reader does not rewind. */ + hr = IStream_Seek(ifd_stream, move, STREAM_SEEK_CUR, &pos); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(pos.QuadPart > 8, "Unexpected position %s.\n", wine_dbgstr_longlong(pos.QuadPart)); + + hr = get_persist_stream(reader2, &stream); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(ifd_stream == stream, "Unexpected stream.\n"); + IStream_Release(stream); + + /* GetStream() is what triggers position reset. */ + hr = IStream_Seek(ifd_stream, move, STREAM_SEEK_CUR, &pos); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine + ok(pos.QuadPart == 8, "Unexpected position %s.\n", wine_dbgstr_longlong(pos.QuadPart)); + + hr = IWICComponentFactory_CreateMetadataWriterFromReader(factory, reader2, NULL, &writer); + todo_wine + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + +if (hr == S_OK) +{ + 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 = get_persist_stream(writer, &stream); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!stream && ifd_stream != stream, "Unexpected stream.\n"); + + hr = IStream_Seek(stream, move, STREAM_SEEK_CUR, &pos); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(pos.QuadPart == 8, "Unexpected position %s.\n", wine_dbgstr_longlong(pos.QuadPart)); + + IStream_Release(stream); + IWICMetadataWriter_Release(writer); +} + + IWICMetadataReader_Release(reader2); + IStream_Release(ifd_stream);
hr = IWICMetadataReader_GetCount(ifd_reader, &count); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -5180,11 +5241,11 @@ static void test_metadata_App1(void) ok(IsEqualGUID(&format, &GUID_MetadataFormatExif), "Unexpected format %s.\n", wine_dbgstr_guid(&format)); check_persist_options(exif_reader, 0);
- hr = get_persist_stream(exif_reader, &stream2); + hr = get_persist_stream(exif_reader, &exif_stream); 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); + check_interface(exif_stream, &IID_IWICStream, TRUE); + ok(!!exif_stream && exif_stream != app1_stream, "Unexpected stream.\n"); + IStream_Release(exif_stream);
hr = IWICMetadataReader_GetCount(exif_reader, &count); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -5218,11 +5279,11 @@ static void test_metadata_App1(void) ok(IsEqualGUID(&format, &GUID_MetadataFormatGps), "Unexpected format %s.\n", wine_dbgstr_guid(&format)); check_persist_options(gps_reader, 0);
- hr = get_persist_stream(gps_reader, &stream2); + hr = get_persist_stream(gps_reader, &gps_stream); 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); + check_interface(gps_stream, &IID_IWICStream, TRUE); + ok(!!gps_stream && gps_stream != app1_stream, "Unexpected stream.\n"); + IStream_Release(gps_stream);
hr = IWICMetadataReader_GetCount(gps_reader, &count); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -5478,8 +5539,8 @@ static void test_metadata_App1(void)
static void test_CreateMetadataWriterFromReader(void) { + IWICMetadataReader *reader, *ifd_reader; IWICComponentFactory *factory; - IWICMetadataReader *reader; IWICMetadataWriter *writer; IStream *stream, *stream2; PROPVARIANT id, value; @@ -5632,6 +5693,43 @@ static void test_CreateMetadataWriterFromReader(void) IWICMetadataReader_Release(reader); IStream_Release(stream);
+ /* App1 reader, writer is created from nested readers instead of a root level. */ + stream = create_stream((const char *)&app1_data, sizeof(app1_data)); + hr = IWICComponentFactory_CreateMetadataReader(factory, &GUID_MetadataFormatApp1, + NULL, 0, stream, &reader); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + PropVariantInit(&id); + PropVariantInit(&value); + hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, &id, &value); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(value.vt == VT_UNKNOWN, "Unexpected value type %u.\n", value.vt); + hr = IUnknown_QueryInterface(value.punkVal, &IID_IWICMetadataReader, (void **)&ifd_reader); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + PropVariantClear(&value); + + hr = IWICMetadataReader_GetMetadataFormat(ifd_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, ifd_reader, NULL, &writer); + todo_wine + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + +if (hr == S_OK) +{ + 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 == 4, "Unexpected count %u.\n", count); + IWICMetadataWriter_Release(writer); +} + IWICMetadataReader_Release(ifd_reader); + IWICMetadataReader_Release(reader); + IStream_Release(stream); + /* App1, reader without stream caching. */ stream = create_stream((const char *)&app1_data, sizeof(app1_data)); hr = IWICComponentFactory_CreateMetadataReader(factory, &GUID_MetadataFormatApp1,
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/metadatahandler.c | 17 +++++++++++++---- dlls/windowscodecs/tests/metadata.c | 2 -- 2 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/dlls/windowscodecs/metadatahandler.c b/dlls/windowscodecs/metadatahandler.c index eb69903d589..3218f763ca9 100644 --- a/dlls/windowscodecs/metadatahandler.c +++ b/dlls/windowscodecs/metadatahandler.c @@ -43,6 +43,7 @@ typedef struct MetadataHandler { DWORD item_count; DWORD persist_options; IStream *stream; + ULARGE_INTEGER origin; CRITICAL_SECTION lock; } MetadataHandler;
@@ -510,15 +511,20 @@ static HRESULT WINAPI MetadataHandler_LoadEx(IWICPersistStream *iface, HRESULT hr = S_OK; MetadataItem *new_items=NULL; DWORD item_count=0; + LARGE_INTEGER move;
TRACE("(%p,%p,%s,%lx)\n", iface, stream, debugstr_guid(pguidPreferredVendor), dwPersistOptions);
EnterCriticalSection(&This->lock);
+ This->origin.QuadPart = 0; if (stream) { - hr = This->vtable->fnLoad(stream, pguidPreferredVendor, dwPersistOptions, - &new_items, &item_count); + move.QuadPart = 0; + hr = IStream_Seek(stream, move, STREAM_SEEK_CUR, &This->origin); + if (SUCCEEDED(hr)) + hr = This->vtable->fnLoad(stream, pguidPreferredVendor, dwPersistOptions, + &new_items, &item_count); }
if (This->stream) @@ -597,8 +603,11 @@ static HRESULT WINAPI metadatahandler_stream_provider_GetStream(IWICStreamProvid
if (handler->stream) { - *stream = handler->stream; - IStream_AddRef(*stream); + if (SUCCEEDED(hr = IStream_Seek(handler->stream, *(LARGE_INTEGER *)&handler->origin, STREAM_SEEK_SET, NULL))) + { + *stream = handler->stream; + IStream_AddRef(*stream); + } } else { diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index b3cb16527af..edfff5fc8d0 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -5132,7 +5132,6 @@ static void test_metadata_App1(void) move.QuadPart = 0; hr = IStream_Seek(ifd_stream, move, STREAM_SEEK_CUR, &pos); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(pos.QuadPart == 8, "Unexpected position %s.\n", wine_dbgstr_longlong(pos.QuadPart));
hr = CoCreateInstance(&CLSID_WICIfdMetadataReader, NULL, CLSCTX_INPROC_SERVER, @@ -5158,7 +5157,6 @@ static void test_metadata_App1(void) /* GetStream() is what triggers position reset. */ hr = IStream_Seek(ifd_stream, move, STREAM_SEEK_CUR, &pos); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(pos.QuadPart == 8, "Unexpected position %s.\n", wine_dbgstr_longlong(pos.QuadPart));
hr = IWICComponentFactory_CreateMetadataWriterFromReader(factory, reader2, NULL, &writer);
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/imgfactory.c | 20 +++++++++++++++++++- dlls/windowscodecs/tests/metadata.c | 24 +++++++++++------------- 2 files changed, 30 insertions(+), 14 deletions(-)
diff --git a/dlls/windowscodecs/imgfactory.c b/dlls/windowscodecs/imgfactory.c index 29f91e6cbbd..f9446245c4e 100644 --- a/dlls/windowscodecs/imgfactory.c +++ b/dlls/windowscodecs/imgfactory.c @@ -1712,7 +1712,25 @@ HRESULT create_metadata_writer_from_reader(IWICMetadataReader *reader, const GUI
if (cached_stream) { - hr = create_stream_wrapper(cached_stream, 0, &stream); + LARGE_INTEGER move; + ULARGE_INTEGER pos; + + /* Move wrapper stream to match original stream position. */ + move.QuadPart = 0; + hr = IStream_Seek(cached_stream, move, STREAM_SEEK_CUR, &pos); + + if (SUCCEEDED(hr)) + hr = IStream_Seek(cached_stream, move, STREAM_SEEK_SET, NULL); + + if (SUCCEEDED(hr)) + hr = create_stream_wrapper(cached_stream, 0, &stream); + + if (SUCCEEDED(hr)) + { + move.QuadPart = pos.QuadPart; + hr = IStream_Seek(stream, move, STREAM_SEEK_SET, NULL); + } + IStream_Release(cached_stream); } } diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index edfff5fc8d0..97e4ad9b5ea 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -5160,11 +5160,8 @@ static void test_metadata_App1(void) ok(pos.QuadPart == 8, "Unexpected position %s.\n", wine_dbgstr_longlong(pos.QuadPart));
hr = IWICComponentFactory_CreateMetadataWriterFromReader(factory, reader2, NULL, &writer); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
-if (hr == S_OK) -{ 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)); @@ -5179,7 +5176,6 @@ if (hr == S_OK)
IStream_Release(stream); IWICMetadataWriter_Release(writer); -}
IWICMetadataReader_Release(reader2); IStream_Release(ifd_stream); @@ -5537,10 +5533,10 @@ if (hr == S_OK)
static void test_CreateMetadataWriterFromReader(void) { + IStream *stream, *stream2, *ifd_stream, *writer_stream; IWICMetadataReader *reader, *ifd_reader; IWICComponentFactory *factory; IWICMetadataWriter *writer; - IStream *stream, *stream2; PROPVARIANT id, value; GUID format; HRESULT hr; @@ -5711,11 +5707,16 @@ static void test_CreateMetadataWriterFromReader(void) ok(IsEqualGUID(&format, &GUID_MetadataFormatIfd), "Unexpected format %s.\n", wine_dbgstr_guid(&format));
hr = IWICComponentFactory_CreateMetadataWriterFromReader(factory, ifd_reader, NULL, &writer); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
-if (hr == S_OK) -{ + hr = get_persist_stream(ifd_reader, &ifd_stream); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = get_persist_stream(writer, &writer_stream); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(ifd_stream != writer_stream, "Unexpected stream.\n"); + IStream_Release(ifd_stream); + IStream_Release(writer_stream); + 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)); @@ -5723,7 +5724,7 @@ if (hr == S_OK) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(count == 4, "Unexpected count %u.\n", count); IWICMetadataWriter_Release(writer); -} + IWICMetadataReader_Release(ifd_reader); IWICMetadataReader_Release(reader); IStream_Release(stream); @@ -6116,10 +6117,8 @@ static void test_CreateQueryWriterFromReader(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IWICComponentFactory_CreateQueryWriterFromReader(factory, query_reader2, NULL, &query_writer); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); -if (hr == S_OK) -{ + hr = IWICMetadataQueryWriter_GetLocation(query_writer, ARRAY_SIZE(buff), buff, &len); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(!wcscmp(buff, L"/ifd"), "Unexpected location %s.\n", wine_dbgstr_w(buff)); @@ -6149,7 +6148,6 @@ if (hr == S_OK) IEnumString_Release(enum_string);
IWICMetadataQueryWriter_Release(query_writer); -}
IWICMetadataQueryReader_Release(query_reader); IWICMetadataQueryReader_Release(query_reader2);
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/tests/metadata.c | 54 +++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+)
diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index 97e4ad9b5ea..9cef27c7430 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -90,6 +90,30 @@ static HRESULT get_persist_stream(void *iface_ptr, IStream **stream) return hr; }
+#define check_persist_classid(a, b) check_persist_classid_(__LINE__, a, b) +static void check_persist_classid_(unsigned int line, void *iface_ptr, const CLSID *check_clsid) +{ + IWICPersistStream *persist_stream; + IUnknown *iface = iface_ptr; + HRESULT hr; + GUID clsid; + + hr = IUnknown_QueryInterface(iface, &IID_IWICPersistStream, (void **)&persist_stream); + ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IWICPersistStream_GetClassID(persist_stream, NULL); + todo_wine + ok_(__FILE__, line)(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + hr = IWICPersistStream_GetClassID(persist_stream, &clsid); + todo_wine + ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr); + if (hr == S_OK) + ok_(__FILE__, line)(IsEqualCLSID(&clsid, check_clsid), "Unexpected class id %s vs %s.\n", + wine_dbgstr_guid(&clsid), wine_dbgstr_guid(check_clsid)); + + IWICPersistStream_Release(persist_stream); +} + static HRESULT create_query_reader_from_metadata_reader(IWICComponentFactory *factory, IWICMetadataReader *metadata_reader, const GUID *container_format, IWICMetadataQueryReader **query_reader);
@@ -687,6 +711,7 @@ static void test_metadata_unknown(void) check_interface(reader, &IID_IWICPersistStream, TRUE); check_interface(reader, &IID_IWICStreamProvider, TRUE); check_interface(reader, &IID_IWICMetadataBlockReader, FALSE); + check_persist_classid(reader, &CLSID_WICUnknownMetadataReader);
load_stream(reader, metadata_unknown, sizeof(metadata_unknown), WICPersistOptionDefault);
@@ -801,6 +826,7 @@ static void test_metadata_unknown(void) check_interface(writer, &IID_IPersistStream, TRUE); check_interface(writer, &IID_IWICPersistStream, TRUE); check_interface(writer, &IID_IWICStreamProvider, TRUE); + check_persist_classid(writer, &CLSID_WICUnknownMetadataWriter);
hr = IWICMetadataWriter_GetCount(writer, &count); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -899,6 +925,7 @@ static void test_metadata_tEXt(void) check_interface(reader, &IID_IPersistStream, TRUE); check_interface(reader, &IID_IWICPersistStream, TRUE); check_interface(reader, &IID_IWICStreamProvider, TRUE); + check_persist_classid(reader, &CLSID_WICPngTextMetadataReader);
hr = IWICMetadataReader_GetCount(reader, NULL); ok(hr == E_INVALIDARG, "GetCount failed, hr=%lx\n", hr); @@ -1021,6 +1048,7 @@ static void test_metadata_tEXt(void) check_interface(writer, &IID_IPersistStream, TRUE); check_interface(writer, &IID_IWICPersistStream, TRUE); check_interface(writer, &IID_IWICStreamProvider, TRUE); + check_persist_classid(writer, &CLSID_WICPngTextMetadataWriter);
load_stream(writer, metadata_tEXt, sizeof(metadata_tEXt), 0); load_stream(writer, metadata_tEXt, sizeof(metadata_tEXt), WICPersistOptionNoCacheStream); @@ -1052,6 +1080,7 @@ static void test_metadata_gAMA(void) check_interface(reader, &IID_IPersistStream, TRUE); check_interface(reader, &IID_IWICPersistStream, TRUE); check_interface(reader, &IID_IWICStreamProvider, TRUE); + check_persist_classid(reader, &CLSID_WICPngGamaMetadataReader);
load_stream(reader, metadata_gAMA, sizeof(metadata_gAMA), WICPersistOptionDefault);
@@ -1097,6 +1126,7 @@ static void test_metadata_gAMA(void) check_interface(writer, &IID_IPersistStream, TRUE); check_interface(writer, &IID_IWICPersistStream, TRUE); check_interface(writer, &IID_IWICStreamProvider, TRUE); + check_persist_classid(writer, &CLSID_WICPngGamaMetadataWriter);
hr = IWICMetadataWriter_GetCount(writer, &count); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -1171,6 +1201,7 @@ static void test_metadata_cHRM(void) check_interface(reader, &IID_IPersistStream, TRUE); check_interface(reader, &IID_IWICPersistStream, TRUE); check_interface(reader, &IID_IWICStreamProvider, TRUE); + check_persist_classid(reader, &CLSID_WICPngChrmMetadataReader);
load_stream(reader, metadata_cHRM, sizeof(metadata_cHRM), WICPersistOptionDefault);
@@ -1213,6 +1244,7 @@ static void test_metadata_cHRM(void) check_interface(writer, &IID_IPersistStream, TRUE); check_interface(writer, &IID_IWICPersistStream, TRUE); check_interface(writer, &IID_IWICStreamProvider, TRUE); + check_persist_classid(writer, &CLSID_WICPngChrmMetadataWriter);
hr = IWICMetadataWriter_GetCount(writer, &count); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -1273,6 +1305,7 @@ static void test_metadata_hIST(void) check_interface(reader, &IID_IPersistStream, TRUE); check_interface(reader, &IID_IWICPersistStream, TRUE); check_interface(reader, &IID_IWICStreamProvider, TRUE); + check_persist_classid(reader, &CLSID_WICPngHistMetadataReader);
load_stream(reader, metadata_hIST, sizeof(metadata_hIST), WICPersistOptionDefault);
@@ -1314,6 +1347,7 @@ static void test_metadata_hIST(void) check_interface(writer, &IID_IPersistStream, TRUE); check_interface(writer, &IID_IWICPersistStream, TRUE); check_interface(writer, &IID_IWICStreamProvider, TRUE); + check_persist_classid(writer, &CLSID_WICPngHistMetadataWriter);
hr = IWICMetadataWriter_GetCount(writer, &count); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -1389,6 +1423,7 @@ static void test_metadata_tIME(void) check_interface(reader, &IID_IPersistStream, TRUE); check_interface(reader, &IID_IWICPersistStream, TRUE); check_interface(reader, &IID_IWICStreamProvider, TRUE); + check_persist_classid(reader, &CLSID_WICPngTimeMetadataReader);
load_stream(reader, metadata_tIME, sizeof(metadata_tIME), WICPersistOptionDefault);
@@ -1472,6 +1507,7 @@ if (hr == S_OK) check_interface(writer, &IID_IPersistStream, TRUE); check_interface(writer, &IID_IWICPersistStream, TRUE); check_interface(writer, &IID_IWICStreamProvider, TRUE); + check_persist_classid(writer, &CLSID_WICPngTimeMetadataWriter);
hr = IWICMetadataWriter_GetCount(writer, &count); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -1778,6 +1814,7 @@ static void test_metadata_Ifd(void) check_interface(reader, &IID_IWICPersistStream, TRUE); check_interface(reader, &IID_IWICStreamProvider, TRUE); check_interface(reader, &IID_IWICMetadataBlockReader, FALSE); + check_persist_classid(reader, &CLSID_WICIfdMetadataReader);
hr = IWICMetadataReader_GetCount(reader, NULL); ok(hr == E_INVALIDARG, "GetCount error %#lx\n", hr); @@ -1829,6 +1866,7 @@ static void test_metadata_Ifd(void) check_interface(writer, &IID_IPersistStream, TRUE); check_interface(writer, &IID_IWICPersistStream, TRUE); check_interface(writer, &IID_IWICStreamProvider, TRUE); + check_persist_classid(writer, &CLSID_WICIfdMetadataWriter);
hr = IWICMetadataWriter_GetCount(writer, &count); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -1858,6 +1896,7 @@ static void test_metadata_Exif(void) check_interface(reader, &IID_IWICPersistStream, TRUE); check_interface(reader, &IID_IWICStreamProvider, TRUE); check_interface(reader, &IID_IWICMetadataBlockReader, FALSE); + check_persist_classid(reader, &CLSID_WICExifMetadataReader);
hr = IWICMetadataReader_GetCount(reader, NULL); ok(hr == E_INVALIDARG, "GetCount error %#lx\n", hr); @@ -1885,6 +1924,7 @@ static void test_metadata_Exif(void) check_interface(writer, &IID_IPersistStream, TRUE); check_interface(writer, &IID_IWICPersistStream, TRUE); check_interface(writer, &IID_IWICStreamProvider, TRUE); + check_persist_classid(writer, &CLSID_WICExifMetadataWriter);
hr = IWICMetadataWriter_GetCount(writer, &count); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -1915,6 +1955,7 @@ static void test_metadata_Gps(void) check_interface(reader, &IID_IWICPersistStream, TRUE); check_interface(reader, &IID_IWICStreamProvider, TRUE); check_interface(reader, &IID_IWICMetadataBlockReader, FALSE); + check_persist_classid(reader, &CLSID_WICGpsMetadataReader);
hr = IWICMetadataReader_GetCount(reader, NULL); ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); @@ -1942,6 +1983,7 @@ static void test_metadata_Gps(void) check_interface(writer, &IID_IPersistStream, TRUE); check_interface(writer, &IID_IWICPersistStream, TRUE); check_interface(writer, &IID_IWICStreamProvider, TRUE); + check_persist_classid(writer, &CLSID_WICGpsMetadataWriter);
hr = IWICMetadataWriter_GetCount(writer, &count); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -2987,6 +3029,7 @@ static void test_metadata_LSD(void) check_interface(reader, &IID_IPersistStream, TRUE); check_interface(reader, &IID_IWICPersistStream, TRUE); check_interface(reader, &IID_IWICStreamProvider, TRUE); + check_persist_classid(reader, &CLSID_WICLSDMetadataReader);
stream = create_stream(LSD_data, sizeof(LSD_data));
@@ -3043,6 +3086,7 @@ static void test_metadata_LSD(void) check_interface(writer, &IID_IPersistStream, TRUE); check_interface(writer, &IID_IWICPersistStream, TRUE); check_interface(writer, &IID_IWICStreamProvider, TRUE); + check_persist_classid(writer, &CLSID_WICLSDMetadataWriter);
hr = IWICMetadataWriter_GetCount(writer, &count); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -3091,6 +3135,7 @@ static void test_metadata_IMD(void) check_interface(reader, &IID_IPersistStream, TRUE); check_interface(reader, &IID_IWICPersistStream, TRUE); check_interface(reader, &IID_IWICStreamProvider, TRUE); + check_persist_classid(reader, &CLSID_WICIMDMetadataReader);
test_reader_container_format(reader, &GUID_ContainerFormatGif);
@@ -3147,6 +3192,7 @@ static void test_metadata_IMD(void) check_interface(writer, &IID_IPersistStream, TRUE); check_interface(writer, &IID_IWICPersistStream, TRUE); check_interface(writer, &IID_IWICStreamProvider, TRUE); + check_persist_classid(writer, &CLSID_WICIMDMetadataWriter);
hr = IWICMetadataWriter_GetCount(writer, &count); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -3200,6 +3246,7 @@ static void test_metadata_GCE(void) check_interface(reader, &IID_IPersistStream, TRUE); check_interface(reader, &IID_IWICPersistStream, TRUE); check_interface(reader, &IID_IWICStreamProvider, TRUE); + check_persist_classid(reader, &CLSID_WICGCEMetadataReader);
test_reader_container_format(reader, &GUID_ContainerFormatGif);
@@ -3256,6 +3303,7 @@ static void test_metadata_GCE(void) check_interface(writer, &IID_IPersistStream, TRUE); check_interface(writer, &IID_IWICPersistStream, TRUE); check_interface(writer, &IID_IWICStreamProvider, TRUE); + check_persist_classid(writer, &CLSID_WICGCEMetadataWriter);
hr = IWICMetadataWriter_GetCount(writer, &count); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -3318,6 +3366,7 @@ static void test_metadata_APE(void) check_interface(reader, &IID_IPersistStream, TRUE); check_interface(reader, &IID_IWICPersistStream, TRUE); check_interface(reader, &IID_IWICStreamProvider, TRUE); + check_persist_classid(reader, &CLSID_WICAPEMetadataReader);
test_reader_container_format(reader, &GUID_ContainerFormatGif);
@@ -3382,6 +3431,7 @@ static void test_metadata_APE(void) check_interface(writer, &IID_IPersistStream, TRUE); check_interface(writer, &IID_IWICPersistStream, TRUE); check_interface(writer, &IID_IWICStreamProvider, TRUE); + check_persist_classid(writer, &CLSID_WICAPEMetadataWriter);
hr = IWICMetadataWriter_GetCount(writer, &count); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -3442,6 +3492,7 @@ static void test_metadata_GIF_comment(void) check_interface(reader, &IID_IPersistStream, TRUE); check_interface(reader, &IID_IWICPersistStream, TRUE); check_interface(reader, &IID_IWICStreamProvider, TRUE); + check_persist_classid(reader, &CLSID_WICGifCommentMetadataReader);
test_reader_container_format(reader, &GUID_ContainerFormatGif);
@@ -3504,6 +3555,7 @@ static void test_metadata_GIF_comment(void) check_interface(writer, &IID_IPersistStream, TRUE); check_interface(writer, &IID_IWICPersistStream, TRUE); check_interface(writer, &IID_IWICStreamProvider, TRUE); + check_persist_classid(writer, &CLSID_WICGifCommentMetadataWriter);
hr = IWICMetadataWriter_GetCount(writer, &count); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -5054,6 +5106,7 @@ static void test_metadata_App1(void) check_interface(reader, &IID_IWICPersistStream, TRUE); check_interface(reader, &IID_IWICStreamProvider, TRUE); check_interface(reader, &IID_IWICMetadataBlockReader, FALSE); + check_persist_classid(reader, &CLSID_WICApp1MetadataReader);
hr = IWICMetadataReader_GetCount(reader, NULL); ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); @@ -5512,6 +5565,7 @@ static void test_metadata_App1(void) check_interface(writer, &IID_IPersistStream, TRUE); check_interface(writer, &IID_IWICPersistStream, TRUE); check_interface(writer, &IID_IWICStreamProvider, TRUE); + check_persist_classid(writer, &CLSID_WICApp1MetadataWriter);
hr = IWICMetadataWriter_GetCount(writer, &count); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/metadatahandler.c | 15 +++++++++++---- dlls/windowscodecs/tests/metadata.c | 7 ++----- 2 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/dlls/windowscodecs/metadatahandler.c b/dlls/windowscodecs/metadatahandler.c index 3218f763ca9..9b8ba2d2c91 100644 --- a/dlls/windowscodecs/metadatahandler.c +++ b/dlls/windowscodecs/metadatahandler.c @@ -469,11 +469,18 @@ static ULONG WINAPI MetadataHandler_PersistStream_Release(IWICPersistStream *ifa return IWICMetadataWriter_Release(&This->IWICMetadataWriter_iface); }
-static HRESULT WINAPI MetadataHandler_GetClassID(IWICPersistStream *iface, - CLSID *pClassID) +static HRESULT WINAPI MetadataHandler_GetClassID(IWICPersistStream *iface, CLSID *clsid) { - FIXME("(%p,%p): stub\n", iface, pClassID); - return E_NOTIMPL; + MetadataHandler *handler = impl_from_IWICPersistStream(iface); + + TRACE("(%p,%p)\n", iface, clsid); + + if (!clsid) + return E_INVALIDARG; + + *clsid = *handler->vtable->clsid; + + return S_OK; }
static HRESULT WINAPI MetadataHandler_IsDirty(IWICPersistStream *iface) diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index 9cef27c7430..025f60d7da8 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -102,14 +102,11 @@ static void check_persist_classid_(unsigned int line, void *iface_ptr, const CLS ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IWICPersistStream_GetClassID(persist_stream, NULL); - todo_wine ok_(__FILE__, line)(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); hr = IWICPersistStream_GetClassID(persist_stream, &clsid); - todo_wine ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (hr == S_OK) - ok_(__FILE__, line)(IsEqualCLSID(&clsid, check_clsid), "Unexpected class id %s vs %s.\n", - wine_dbgstr_guid(&clsid), wine_dbgstr_guid(check_clsid)); + ok_(__FILE__, line)(IsEqualCLSID(&clsid, check_clsid), "Unexpected class id %s vs %s.\n", + wine_dbgstr_guid(&clsid), wine_dbgstr_guid(check_clsid));
IWICPersistStream_Release(persist_stream); }
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/metadatahandler.c | 8 ++++++-- dlls/windowscodecs/tests/metadata.c | 5 ----- 2 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/dlls/windowscodecs/metadatahandler.c b/dlls/windowscodecs/metadatahandler.c index 9b8ba2d2c91..a33abb48ce1 100644 --- a/dlls/windowscodecs/metadatahandler.c +++ b/dlls/windowscodecs/metadatahandler.c @@ -642,9 +642,13 @@ static HRESULT WINAPI metadatahandler_stream_provider_GetPersistOptions(IWICStre
static HRESULT WINAPI metadatahandler_stream_provider_GetPreferredVendorGUID(IWICStreamProvider *iface, GUID *guid) { - FIXME("%p, %p stub\n", iface, guid); + TRACE("%p, %p.\n", iface, guid);
- return E_NOTIMPL; + if (!guid) + return E_INVALIDARG; + + memcpy(guid, &GUID_VendorMicrosoft, sizeof(*guid)); + return S_OK; }
static HRESULT WINAPI metadatahandler_stream_provider_RefreshStream(IWICStreamProvider *iface) diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index 025f60d7da8..00120a53991 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -457,13 +457,10 @@ static void load_stream(void *iface_ptr, const char *data, int data_size, DWORD
memset(&guid, 0, sizeof(guid)); hr = IWICStreamProvider_GetPreferredVendorGUID(stream_provider, &guid); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(IsEqualGUID(&guid, &GUID_VendorMicrosoft), "Unexpected vendor %s.\n", wine_dbgstr_guid(&guid));
hr = IWICStreamProvider_GetPreferredVendorGUID(stream_provider, NULL); - todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
hr = IWICStreamProvider_GetPersistOptions(stream_provider, NULL); @@ -487,9 +484,7 @@ static void load_stream(void *iface_ptr, const char *data, int data_size, DWORD
memset(&guid, 0, sizeof(guid)); hr = IWICStreamProvider_GetPreferredVendorGUID(stream_provider, &guid); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(IsEqualGUID(&guid, &GUID_VendorMicrosoft), "Unexpected vendor %s.\n", wine_dbgstr_guid(&guid));
flags = ~persist_options;
This may take me some time to review as I'll soon be out until March 1.
On Mon Feb 24 20:19:28 2025 +0000, Esme Povirk wrote:
This may take me some time to review as I'll soon be out until March 1.
Sure. This is the last MR that I have planned.
Esme Povirk (@madewokherd) commented about dlls/windowscodecs/metadataquery.c:
- if (SUCCEEDED(hr))
hr = IWICMetadataReader_GetMetadataFormat(reader, guid);
- if (reader)
IWICMetadataReader_Release(reader);
- if (SUCCEEDED(hr))
- {
for (i = 0; i < enumerator->guids.count; ++i)
{
if (IsEqualGUID(&enumerator->guids.entries[i].guid, guid))
{
*index = ++enumerator->guids.entries[i].index;
return S_OK;
}
For this to make sense, I think you must be using the `index` field to mean "number of instances of this guid minus one", in which case the name `index` is confusing.
On Sat Mar 1 18:33:03 2025 +0000, Esme Povirk wrote:
For this to make sense, I think you must be using the `index` field to mean "number of instances of this guid minus one", in which case the name `index` is confusing.
Right, I called it index because it's used in the index portion of the query item, but I see what you mean. I'll make it more obvious.
Esme Povirk (@madewokherd) commented about dlls/windowscodecs/metadataquery.c:
const WCHAR *value = query_get_guid_item_string(buffer, ARRAY_SIZE(buffer), var->puuid, false);
if (!(*name = wcsdup(value)))
return E_OUTOFMEMORY;
return S_OK;
- }
- PropVariantInit(&dest);
- type = get_type_name(var->vt);
- if (type)
- {
if (FAILED(hr = PropVariantChangeType(&dest, var, 0, VT_LPWSTR))) return hr;
- }
- len = 4;
- if (type) len += wcslen(type);
- if (dest.pwszVal) len += wcslen(dest.pwszVal);
I think this is equivalent to `if (type)` and can be combined with the previous line? If it's not, we'll have problems later when formatting a string with `dest.pwszVal`.
Esme Povirk (@madewokherd) commented about dlls/windowscodecs/metadataquery.c:
if (!(objects = calloc(count, sizeof(*objects))))
return E_OUTOFMEMORY;
if (SUCCEEDED(hr = IEnumUnknown_Next(enumerator->object_enumerator, count, objects, fetched)))
{
for (ULONG i = 0; i < *fetched; ++i)
{
index = 0;
hr = string_enumerator_update_guid_index(enumerator, &guid, &index, objects[i]);
if (FAILED(hr)) break;
if (!(str = CoTaskMemAlloc(64 * sizeof(WCHAR))))
{
hr = E_OUTOFMEMORY;
break;
}
I don't think the error path here quite works. If we exit the loop early, `*fetched` will be the number of IUnknown pointers we got from `object_enumerator`, but we won't return that many items in `strings`.
Esme Povirk (@madewokherd) commented about dlls/windowscodecs/metadataquery.c:
static HRESULT WINAPI string_enumerator_Skip(IEnumString *iface, ULONG count) {
- FIXME("iface %p, count %lu stub.\n", iface, count);
- struct string_enumerator *enumerator = impl_from_IEnumString(iface);
- unsigned int index;
- HRESULT hr = S_OK;
- IUnknown *object;
- ULONG fetched;
- GUID guid;
- TRACE("iface %p, count %lu.\n", iface, count);
- if (enumerator->object_enumerator)
- {
while (count-- && IEnumUnknown_Next(enumerator->object_enumerator, 1, &object, &fetched) == S_OK)
I think you want to assign `hr` here so we can pass `S_FALSE` or an error to the caller.
Esme Povirk (@madewokherd) commented about dlls/windowscodecs/metadataquery.c:
struct string_enumerator *enumerator = impl_from_IEnumString(iface);
IWICEnumMetadataItem *metadata_enumerator = NULL;
IEnumUnknown *object_enumerator = NULL;
struct string_enumerator *object;
HRESULT hr = S_OK;
TRACE("iface %p, out %p.\n", iface, out);
*out = NULL;
- return E_NOTIMPL;
- if (!(object = calloc(1, sizeof(*object))))
return E_OUTOFMEMORY;
- if (enumerator->object_enumerator)
hr = IEnumUnknown_Clone(enumerator->object_enumerator, &object_enumerator);
I think we need to also make a copy of `guids` in this case.
Esme Povirk (@madewokherd) commented about dlls/windowscodecs/metadataquery.c:
IWICEnumMetadataItem *metadata_enumerator = NULL;
IEnumUnknown *object_enumerator = NULL; struct string_enumerator *object;
if (!(object = calloc(1, sizeof(*object)))) return E_OUTOFMEMORY;
- object->IEnumString_iface.lpVtbl = &string_enumerator_vtbl;
- object->ref = 1;
- if (is_block_handler(handler))
- {
IWICMetadataBlockReader_GetEnumerator(handler->object.block_reader, &object_enumerator);
- }
- else
- {
IWICMetadataReader_GetEnumerator(handler->object.reader, &metadata_enumerator);
`metadata_enumerator` needs to be released.