From: Jeff Smith whydoubt@gmail.com
--- dlls/windowscodecs/tests/metadata.c | 224 ++++++++++++++-------------- 1 file changed, 112 insertions(+), 112 deletions(-)
diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index a50edbb2412..11b6dfebb5c 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -270,6 +270,118 @@ static void load_stream(IUnknown *reader, const char *data, int data_size, DWORD IStream_Release(stream); }
+struct test_data +{ + ULONG type, id; + int count; /* if VT_VECTOR */ + LONGLONG value[13]; + const char *string; + const WCHAR id_string[32]; +}; + +static void compare_metadata(IWICMetadataReader *reader, const struct test_data *td, ULONG count) +{ + HRESULT hr; + IWICEnumMetadataItem *enumerator; + PROPVARIANT schema, id, value; + ULONG items_returned, i; + + hr = IWICMetadataReader_GetEnumerator(reader, NULL); + ok(hr == E_INVALIDARG, "GetEnumerator error %#lx\n", hr); + + hr = IWICMetadataReader_GetEnumerator(reader, &enumerator); + ok(hr == S_OK, "GetEnumerator error %#lx\n", hr); + + PropVariantInit(&schema); + PropVariantInit(&id); + PropVariantInit(&value); + + for (i = 0; i < count; i++) + { + hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned); + ok(hr == S_OK, "Next error %#lx\n", hr); + ok(items_returned == 1, "unexpected item count %lu\n", items_returned); + + ok(schema.vt == VT_EMPTY, "%lu: unexpected vt: %u\n", i, schema.vt); + ok(id.vt == VT_UI2 || id.vt == VT_LPWSTR || id.vt == VT_EMPTY, "%lu: unexpected vt: %u\n", i, id.vt); + if (id.vt == VT_UI2) + ok(id.uiVal == td[i].id, "%lu: expected id %#lx, got %#x\n", i, td[i].id, id.uiVal); + else if (id.vt == VT_LPWSTR) + ok(!lstrcmpW(td[i].id_string, id.pwszVal), + "%lu: expected %s, got %s\n", i, wine_dbgstr_w(td[i].id_string), wine_dbgstr_w(id.pwszVal)); + + ok(value.vt == td[i].type, "%lu: expected vt %#lx, got %#x\n", i, td[i].type, value.vt); + if (value.vt & VT_VECTOR) + { + ULONG j; + switch (value.vt & ~VT_VECTOR) + { + case VT_I1: + case VT_UI1: + ok(td[i].count == value.caub.cElems, "%lu: expected cElems %d, got %ld\n", i, td[i].count, value.caub.cElems); + for (j = 0; j < value.caub.cElems; j++) + ok(td[i].value[j] == value.caub.pElems[j], "%lu: expected value[%ld] %#I64x, got %#x\n", i, j, td[i].value[j], value.caub.pElems[j]); + break; + case VT_I2: + case VT_UI2: + ok(td[i].count == value.caui.cElems, "%lu: expected cElems %d, got %ld\n", i, td[i].count, value.caui.cElems); + for (j = 0; j < value.caui.cElems; j++) + ok(td[i].value[j] == value.caui.pElems[j], "%lu: expected value[%ld] %#I64x, got %#x\n", i, j, td[i].value[j], value.caui.pElems[j]); + break; + case VT_I4: + case VT_UI4: + case VT_R4: + ok(td[i].count == value.caul.cElems, "%lu: expected cElems %d, got %ld\n", i, td[i].count, value.caul.cElems); + for (j = 0; j < value.caul.cElems; j++) + ok(td[i].value[j] == value.caul.pElems[j], "%lu: expected value[%ld] %#I64x, got %#lx\n", i, j, td[i].value[j], value.caul.pElems[j]); + break; + case VT_I8: + case VT_UI8: + case VT_R8: + ok(td[i].count == value.cauh.cElems, "%lu: expected cElems %d, got %ld\n", i, td[i].count, value.cauh.cElems); + for (j = 0; j < value.cauh.cElems; j++) + ok(td[i].value[j] == value.cauh.pElems[j].QuadPart, "%lu: expected value[%ld] %I64x, got %08lx/%08lx\n", i, j, td[i].value[j], value.cauh.pElems[j].u.LowPart, value.cauh.pElems[j].u.HighPart); + break; + case VT_LPSTR: + ok(td[i].count == value.calpstr.cElems, "%lu: expected cElems %d, got %ld\n", i, td[i].count, value.caub.cElems); + for (j = 0; j < value.calpstr.cElems; j++) + trace("%lu: %s\n", j, value.calpstr.pElems[j]); + /* fall through to not handled message */ + default: + ok(0, "%lu: array of type %d is not handled\n", i, value.vt & ~VT_VECTOR); + break; + } + } + else if (value.vt == VT_LPSTR) + { + ok(td[i].count == strlen(value.pszVal) || + broken(td[i].count == strlen(value.pszVal) + 1), /* before Win7 */ + "%lu: expected count %d, got %d\n", i, td[i].count, lstrlenA(value.pszVal)); + if (td[i].count == strlen(value.pszVal)) + ok(!strcmp(td[i].string, value.pszVal), + "%lu: expected %s, got %s\n", i, td[i].string, value.pszVal); + } + else if (value.vt == VT_BLOB) + { + ok(td[i].count == value.blob.cbSize, "%lu: expected count %d, got %ld\n", i, td[i].count, value.blob.cbSize); + ok(!memcmp(td[i].string, value.blob.pBlobData, td[i].count), "%lu: expected %s, got %s\n", i, td[i].string, value.blob.pBlobData); + } + else + ok(value.uhVal.QuadPart == td[i].value[0], "%lu: expected value %#I64x got %#lx/%#lx\n", + i, td[i].value[0], value.uhVal.u.LowPart, value.uhVal.u.HighPart); + + PropVariantClear(&schema); + PropVariantClear(&id); + PropVariantClear(&value); + } + + hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned); + ok(hr == S_FALSE, "Next should fail\n"); + ok(items_returned == 0, "unexpected item count %lu\n", items_returned); + + IWICEnumMetadataItem_Release(enumerator); +} + static void test_metadata_unknown(void) { HRESULT hr; @@ -721,118 +833,6 @@ static void byte_swap_ifd_data(char *data) } }
-struct test_data -{ - ULONG type, id; - int count; /* if VT_VECTOR */ - LONGLONG value[13]; - const char *string; - const WCHAR id_string[32]; -}; - -static void compare_metadata(IWICMetadataReader *reader, const struct test_data *td, ULONG count) -{ - HRESULT hr; - IWICEnumMetadataItem *enumerator; - PROPVARIANT schema, id, value; - ULONG items_returned, i; - - hr = IWICMetadataReader_GetEnumerator(reader, NULL); - ok(hr == E_INVALIDARG, "GetEnumerator error %#lx\n", hr); - - hr = IWICMetadataReader_GetEnumerator(reader, &enumerator); - ok(hr == S_OK, "GetEnumerator error %#lx\n", hr); - - PropVariantInit(&schema); - PropVariantInit(&id); - PropVariantInit(&value); - - for (i = 0; i < count; i++) - { - hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned); - ok(hr == S_OK, "Next error %#lx\n", hr); - ok(items_returned == 1, "unexpected item count %lu\n", items_returned); - - ok(schema.vt == VT_EMPTY, "%lu: unexpected vt: %u\n", i, schema.vt); - ok(id.vt == VT_UI2 || id.vt == VT_LPWSTR || id.vt == VT_EMPTY, "%lu: unexpected vt: %u\n", i, id.vt); - if (id.vt == VT_UI2) - ok(id.uiVal == td[i].id, "%lu: expected id %#lx, got %#x\n", i, td[i].id, id.uiVal); - else if (id.vt == VT_LPWSTR) - ok(!lstrcmpW(td[i].id_string, id.pwszVal), - "%lu: expected %s, got %s\n", i, wine_dbgstr_w(td[i].id_string), wine_dbgstr_w(id.pwszVal)); - - ok(value.vt == td[i].type, "%lu: expected vt %#lx, got %#x\n", i, td[i].type, value.vt); - if (value.vt & VT_VECTOR) - { - ULONG j; - switch (value.vt & ~VT_VECTOR) - { - case VT_I1: - case VT_UI1: - ok(td[i].count == value.caub.cElems, "%lu: expected cElems %d, got %ld\n", i, td[i].count, value.caub.cElems); - for (j = 0; j < value.caub.cElems; j++) - ok(td[i].value[j] == value.caub.pElems[j], "%lu: expected value[%ld] %#I64x, got %#x\n", i, j, td[i].value[j], value.caub.pElems[j]); - break; - case VT_I2: - case VT_UI2: - ok(td[i].count == value.caui.cElems, "%lu: expected cElems %d, got %ld\n", i, td[i].count, value.caui.cElems); - for (j = 0; j < value.caui.cElems; j++) - ok(td[i].value[j] == value.caui.pElems[j], "%lu: expected value[%ld] %#I64x, got %#x\n", i, j, td[i].value[j], value.caui.pElems[j]); - break; - case VT_I4: - case VT_UI4: - case VT_R4: - ok(td[i].count == value.caul.cElems, "%lu: expected cElems %d, got %ld\n", i, td[i].count, value.caul.cElems); - for (j = 0; j < value.caul.cElems; j++) - ok(td[i].value[j] == value.caul.pElems[j], "%lu: expected value[%ld] %#I64x, got %#lx\n", i, j, td[i].value[j], value.caul.pElems[j]); - break; - case VT_I8: - case VT_UI8: - case VT_R8: - ok(td[i].count == value.cauh.cElems, "%lu: expected cElems %d, got %ld\n", i, td[i].count, value.cauh.cElems); - for (j = 0; j < value.cauh.cElems; j++) - ok(td[i].value[j] == value.cauh.pElems[j].QuadPart, "%lu: expected value[%ld] %I64x, got %08lx/%08lx\n", i, j, td[i].value[j], value.cauh.pElems[j].u.LowPart, value.cauh.pElems[j].u.HighPart); - break; - case VT_LPSTR: - ok(td[i].count == value.calpstr.cElems, "%lu: expected cElems %d, got %ld\n", i, td[i].count, value.caub.cElems); - for (j = 0; j < value.calpstr.cElems; j++) - trace("%lu: %s\n", j, value.calpstr.pElems[j]); - /* fall through to not handled message */ - default: - ok(0, "%lu: array of type %d is not handled\n", i, value.vt & ~VT_VECTOR); - break; - } - } - else if (value.vt == VT_LPSTR) - { - ok(td[i].count == strlen(value.pszVal) || - broken(td[i].count == strlen(value.pszVal) + 1), /* before Win7 */ - "%lu: expected count %d, got %d\n", i, td[i].count, lstrlenA(value.pszVal)); - if (td[i].count == strlen(value.pszVal)) - ok(!strcmp(td[i].string, value.pszVal), - "%lu: expected %s, got %s\n", i, td[i].string, value.pszVal); - } - else if (value.vt == VT_BLOB) - { - ok(td[i].count == value.blob.cbSize, "%lu: expected count %d, got %ld\n", i, td[i].count, value.blob.cbSize); - ok(!memcmp(td[i].string, value.blob.pBlobData, td[i].count), "%lu: expected %s, got %s\n", i, td[i].string, value.blob.pBlobData); - } - else - ok(value.uhVal.QuadPart == td[i].value[0], "%lu: expected value %#I64x got %#lx/%#lx\n", - i, td[i].value[0], value.uhVal.u.LowPart, value.uhVal.u.HighPart); - - PropVariantClear(&schema); - PropVariantClear(&id); - PropVariantClear(&value); - } - - hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned); - ok(hr == S_FALSE, "Next should fail\n"); - ok(items_returned == 0, "unexpected item count %lu\n", items_returned); - - IWICEnumMetadataItem_Release(enumerator); -} - static void test_metadata_IFD(void) { static const struct test_data td[28] =
From: Jeff Smith whydoubt@gmail.com
--- dlls/windowscodecs/clsfactory.c | 1 + dlls/windowscodecs/pngformat.c | 86 +++++++++++++++++++ dlls/windowscodecs/regsvr.c | 25 ++++++ dlls/windowscodecs/tests/metadata.c | 61 +++++++++++-- dlls/windowscodecs/wincodecs_private.h | 1 + dlls/windowscodecs/windowscodecs_wincodec.idl | 7 ++ 6 files changed, 173 insertions(+), 8 deletions(-)
diff --git a/dlls/windowscodecs/clsfactory.c b/dlls/windowscodecs/clsfactory.c index 5065c8f2ca4..54cc154bb22 100644 --- a/dlls/windowscodecs/clsfactory.c +++ b/dlls/windowscodecs/clsfactory.c @@ -67,6 +67,7 @@ static const classinfo wic_classes[] = { {&CLSID_WICPngGamaMetadataReader, PngGamaReader_CreateInstance}, {&CLSID_WICPngHistMetadataReader, PngHistReader_CreateInstance}, {&CLSID_WICPngTextMetadataReader, PngTextReader_CreateInstance}, + {&CLSID_WICPngTimeMetadataReader, PngTimeReader_CreateInstance}, {&CLSID_WICLSDMetadataReader, LSDReader_CreateInstance}, {&CLSID_WICIMDMetadataReader, IMDReader_CreateInstance}, {&CLSID_WICGCEMetadataReader, GCEReader_CreateInstance}, diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c index 4c1e1f8463c..4751db7939d 100644 --- a/dlls/windowscodecs/pngformat.c +++ b/dlls/windowscodecs/pngformat.c @@ -311,6 +311,92 @@ HRESULT PngHistReader_CreateInstance(REFIID iid, void** ppv) return MetadataReader_Create(&HistReader_Vtbl, iid, ppv); }
+static HRESULT LoadTimeMetadata(IStream *stream, const GUID *preferred_vendor, + DWORD persist_options, MetadataItem **items, DWORD *item_count) +{ + HRESULT hr; + BYTE type[4]; + BYTE *data; + ULONG data_size, i; + MetadataItem *result; + static const WCHAR *names[6] = + { + L"Year", + L"Month", + L"Day", + L"Hour", + L"Minute", + L"Second", + }; + LPWSTR id_values[6] = {0}; + + + hr = read_png_chunk(stream, type, &data, &data_size); + if (FAILED(hr)) return hr; + + if (data_size != 7) + { + HeapFree(GetProcessHeap(), 0, data); + return E_FAIL; + } + + result = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MetadataItem) * 6); + for (i = 0; i < 6; i++) + { + SHStrDupW(names[i], &id_values[i]); + if (!id_values[i]) break; + } + if (!result || i < 6) + { + HeapFree(GetProcessHeap(), 0, result); + for (i = 0; i < 6; i++) + CoTaskMemFree(id_values[i]); + HeapFree(GetProcessHeap(), 0, data); + return E_OUTOFMEMORY; + } + + for (i = 0; i < 6; i++) + { + PropVariantInit(&result[i].schema); + PropVariantInit(&result[i].id); + PropVariantInit(&result[i].value); + + result[i].id.vt = VT_LPWSTR; + result[i].id.pwszVal = id_values[i]; + } + + result[0].value.vt = VT_UI2; + result[0].value.uiVal = read_ushort_be(data); + result[1].value.vt = VT_UI1; + result[1].value.bVal = data[2]; + result[2].value.vt = VT_UI1; + result[2].value.bVal = data[3]; + result[3].value.vt = VT_UI1; + result[3].value.bVal = data[4]; + result[4].value.vt = VT_UI1; + result[4].value.bVal = data[5]; + result[5].value.vt = VT_UI1; + result[5].value.bVal = data[6]; + + *items = result; + *item_count = 6; + + HeapFree(GetProcessHeap(), 0, data); + + return S_OK; +} + +static const MetadataHandlerVtbl TimeReader_Vtbl = { + 0, + &CLSID_WICPngTimeMetadataReader, + LoadTimeMetadata +}; + +HRESULT PngTimeReader_CreateInstance(REFIID iid, void** ppv) +{ + return MetadataReader_Create(&TimeReader_Vtbl, iid, ppv); +} + HRESULT PngDecoder_CreateInstance(REFIID iid, void** ppv) { HRESULT hr; diff --git a/dlls/windowscodecs/regsvr.c b/dlls/windowscodecs/regsvr.c index 113fac21603..c74fcecb3a2 100644 --- a/dlls/windowscodecs/regsvr.c +++ b/dlls/windowscodecs/regsvr.c @@ -1635,6 +1635,21 @@ static const struct reader_containers pnghist_containers[] = { { NULL } /* list terminator */ };
+static const BYTE tIME[] = "tIME"; + +static const struct metadata_pattern pngtime_metadata_pattern[] = { + { 4, 4, tIME, mask_all, 4 }, + { 0 } +}; + +static const struct reader_containers pngtime_containers[] = { + { + &GUID_ContainerFormatPng, + pngtime_metadata_pattern + }, + { NULL } /* list terminator */ +}; + static const struct metadata_pattern lsd_metadata_patterns[] = { { 0, 6, gif87a_magic, mask_all, 0 }, { 0, 6, gif89a_magic, mask_all, 0 }, @@ -1770,6 +1785,16 @@ static struct regsvr_metadatareader const metadatareader_list[] = { 0, 0, 0, pngtext_containers }, + { &CLSID_WICPngTimeMetadataReader, + "The Wine Project", + "Chunk tIME Reader", + "1.0.0.0", + "1.0.0.0", + &GUID_VendorMicrosoft, + &GUID_MetadataFormatChunktIME, + 0, 0, 0, + pngtime_containers + }, { &CLSID_WICLSDMetadataReader, "The Wine Project", "Logical Screen Descriptor Reader", diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index 11b6dfebb5c..5dac90a8e63 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -169,6 +169,14 @@ static const char metadata_hIST[] = { 0xff,0xff,0xff,0xff };
+static const char metadata_tIME[] = { + 0,0,0,7, /* chunk length */ + 't','I','M','E', /* chunk type */ + 0x07,0xd0,0x01,0x02, /* year (2 bytes), month, day */ + 0x0c,0x22,0x38, /* hour, minute, second */ + 0xff,0xff,0xff,0xff +}; + static const char pngimage[285] = { 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52, 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53, @@ -725,6 +733,42 @@ static void test_metadata_hIST(void) IWICMetadataReader_Release(reader); }
+static void test_metadata_tIME(void) +{ + HRESULT hr; + IWICMetadataReader *reader; + UINT count; + GUID format; + static const struct test_data td[] = + { + { VT_UI2, 0, 0, { 2000 }, NULL, L"Year" }, + { VT_UI1, 0, 0, { 1 }, NULL, L"Month" }, + { VT_UI1, 0, 0, { 2 }, NULL, L"Day" }, + { VT_UI1, 0, 0, { 12 }, NULL, L"Hour" }, + { VT_UI1, 0, 0, { 34 }, NULL, L"Minute" }, + { VT_UI1, 0, 0, { 56 }, NULL, L"Second" }, + }; + + hr = CoCreateInstance(&CLSID_WICPngTimeMetadataReader, NULL, CLSCTX_INPROC_SERVER, + &IID_IWICMetadataReader, (void**)&reader); + ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG) /*winxp*/, "CoCreateInstance failed, hr=%lx\n", hr); + if (FAILED(hr)) return; + + load_stream((IUnknown*)reader, metadata_tIME, sizeof(metadata_tIME), WICPersistOptionDefault); + + hr = IWICMetadataReader_GetMetadataFormat(reader, &format); + ok(hr == S_OK, "GetMetadataFormat failed, hr=%lx\n", hr); + ok(IsEqualGUID(&format, &GUID_MetadataFormatChunktIME), "unexpected format %s\n", wine_dbgstr_guid(&format)); + + hr = IWICMetadataReader_GetCount(reader, &count); + ok(hr == S_OK, "GetCount failed, hr=%lx\n", hr); + ok(count == ARRAY_SIZE(td), "unexpected count %i\n", count); + + compare_metadata(reader, td, count); + + IWICMetadataReader_Release(reader); +} + static inline USHORT ushort_bswap(USHORT s) { return (s >> 8) | (s << 8); @@ -1108,12 +1152,12 @@ static void test_metadata_png(void) { static const struct test_data td[6] = { - { VT_UI2, 0, 0, { 2005 }, NULL, { 'Y','e','a','r',0 } }, - { VT_UI1, 0, 0, { 6 }, NULL, { 'M','o','n','t','h',0 } }, - { VT_UI1, 0, 0, { 3 }, NULL, { 'D','a','y',0 } }, - { VT_UI1, 0, 0, { 15 }, NULL, { 'H','o','u','r',0 } }, - { VT_UI1, 0, 0, { 7 }, NULL, { 'M','i','n','u','t','e',0 } }, - { VT_UI1, 0, 0, { 45 }, NULL, { 'S','e','c','o','n','d',0 } } + { VT_UI2, 0, 0, { 2005 }, NULL, L"Year" }, + { VT_UI1, 0, 0, { 6 }, NULL, L"Month" }, + { VT_UI1, 0, 0, { 3 }, NULL, L"Day" }, + { VT_UI1, 0, 0, { 15 }, NULL, L"Hour" }, + { VT_UI1, 0, 0, { 7 }, NULL, L"Minute" }, + { VT_UI1, 0, 0, { 45 }, NULL, L"Second" } }; IStream *stream; IWICBitmapDecoder *decoder; @@ -1176,13 +1220,13 @@ static void test_metadata_png(void) { hr = IWICMetadataReader_GetMetadataFormat(reader, &containerformat); ok(hr == S_OK, "GetMetadataFormat failed, hr=%#lx\n", hr); - todo_wine ok(IsEqualGUID(&containerformat, &GUID_MetadataFormatChunktIME) || + ok(IsEqualGUID(&containerformat, &GUID_MetadataFormatChunktIME) || broken(IsEqualGUID(&containerformat, &GUID_MetadataFormatUnknown)) /* Windows XP */, "unexpected container format\n");
hr = IWICMetadataReader_GetCount(reader, &count); ok(hr == S_OK, "GetCount error %#lx\n", hr); - todo_wine ok(count == 6 || broken(count == 1) /* XP */, "expected 6, got %u\n", count); + ok(count == 6 || broken(count == 1) /* XP */, "expected 6, got %u\n", count); if (count == 6) compare_metadata(reader, td, count);
@@ -3272,6 +3316,7 @@ START_TEST(metadata) test_metadata_gAMA(); test_metadata_cHRM(); test_metadata_hIST(); + test_metadata_tIME(); test_metadata_IFD(); test_metadata_Exif(); test_create_reader(); diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h index 3dcb20786f2..9da717fc345 100644 --- a/dlls/windowscodecs/wincodecs_private.h +++ b/dlls/windowscodecs/wincodecs_private.h @@ -221,6 +221,7 @@ extern HRESULT PngChrmReader_CreateInstance(REFIID iid, void** ppv); extern HRESULT PngGamaReader_CreateInstance(REFIID iid, void** ppv); extern HRESULT PngHistReader_CreateInstance(REFIID iid, void** ppv); extern HRESULT PngTextReader_CreateInstance(REFIID iid, void** ppv); +extern HRESULT PngTimeReader_CreateInstance(REFIID iid, void** ppv); extern HRESULT LSDReader_CreateInstance(REFIID iid, void **ppv); extern HRESULT IMDReader_CreateInstance(REFIID iid, void **ppv); extern HRESULT GCEReader_CreateInstance(REFIID iid, void **ppv); diff --git a/dlls/windowscodecs/windowscodecs_wincodec.idl b/dlls/windowscodecs/windowscodecs_wincodec.idl index e60111ed19c..b54dde77c16 100644 --- a/dlls/windowscodecs/windowscodecs_wincodec.idl +++ b/dlls/windowscodecs/windowscodecs_wincodec.idl @@ -189,6 +189,13 @@ coclass WICPngHistMetadataReader { interface IWICMetadataReader; } ] coclass WICPngTextMetadataReader { interface IWICMetadataReader; }
+[ + helpstring("WIC Png tIME Metadata Reader"), + threading(both), + uuid(d94edf02-efe5-4f0d-85c8-f5a68b3000b1) +] +coclass WICPngTimeMetadataReader { interface IWICMetadataReader; } + [ helpstring("WIC LSD Metadata Reader"), threading(both),
This merge request was approved by Esme Povirk.