2 * Copyright 2011 Vincent Povirk for CodeWeavers
3 * Copyright 2012 Dmitry Timoshkov
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include "wincodecsdk.h"
30 #include "wine/test.h"
32 #define expect_blob(propvar, data, length) do { \
33 ok((propvar).vt == VT_BLOB, "unexpected vt: %i\n", (propvar).vt); \
34 if ((propvar).vt == VT_BLOB) { \
35 ok(U(propvar).blob.cbSize == (length), "expected size %u, got %u\n", (ULONG)(length), U(propvar).blob.cbSize); \
36 if (U(propvar).blob.cbSize == (length)) { \
37 ok(!memcmp(U(propvar).blob.pBlobData, (data), (length)), "unexpected data\n"); \
46 #define IFD_RATIONAL 5
48 #define IFD_UNDEFINED 7
51 #define IFD_SRATIONAL 10
71 static const struct ifd_data
73 USHORT number_of_entries
;
74 struct IFD_entry entry
[40];
76 struct IFD_rational xres
;
78 struct IFD_rational srational_val
;
87 { 0xfe, IFD_SHORT
, 1, 1 }, /* NEWSUBFILETYPE */
88 { 0x100, IFD_LONG
, 1, 222 }, /* IMAGEWIDTH */
89 { 0x101, IFD_LONG
, 1, 333 }, /* IMAGELENGTH */
90 { 0x102, IFD_SHORT
, 1, 24 }, /* BITSPERSAMPLE */
91 { 0x103, IFD_LONG
, 1, 32773 }, /* COMPRESSION: packbits */
92 { 0x11a, IFD_RATIONAL
, 1, FIELD_OFFSET(struct ifd_data
, xres
) },
93 { 0xf001, IFD_BYTE
, 1, 0x11223344 },
94 { 0xf002, IFD_BYTE
, 4, 0x11223344 },
95 { 0xf003, IFD_SBYTE
, 1, 0x11223344 },
96 { 0xf004, IFD_SSHORT
, 1, 0x11223344 },
97 { 0xf005, IFD_SSHORT
, 2, 0x11223344 },
98 { 0xf006, IFD_SLONG
, 1, 0x11223344 },
99 { 0xf007, IFD_FLOAT
, 1, 0x11223344 },
100 { 0xf008, IFD_DOUBLE
, 1, FIELD_OFFSET(struct ifd_data
, double_val
) },
101 { 0xf009, IFD_SRATIONAL
, 1, FIELD_OFFSET(struct ifd_data
, srational_val
) },
102 { 0xf00a, IFD_BYTE
, 13, FIELD_OFFSET(struct ifd_data
, string
) },
103 { 0xf00b, IFD_SSHORT
, 4, FIELD_OFFSET(struct ifd_data
, short_val
) },
104 { 0xf00c, IFD_SLONG
, 2, FIELD_OFFSET(struct ifd_data
, long_val
) },
105 { 0xf00d, IFD_FLOAT
, 2, FIELD_OFFSET(struct ifd_data
, float_val
) },
106 { 0xf00e, IFD_ASCII
, 13, FIELD_OFFSET(struct ifd_data
, string
) },
107 { 0xf00f, IFD_ASCII
, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 },
108 { 0xf010, IFD_UNDEFINED
, 13, FIELD_OFFSET(struct ifd_data
, string
) },
109 { 0xf011, IFD_UNDEFINED
, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 },
110 { 0xf012, IFD_BYTE
, 0, 0x11223344 },
111 { 0xf013, IFD_SHORT
, 0, 0x11223344 },
112 { 0xf014, IFD_LONG
, 0, 0x11223344 },
113 { 0xf015, IFD_FLOAT
, 0, 0x11223344 },
117 1234567890.0987654321,
118 { 0x1a2b3c4d, 0x5a6b7c8d },
120 { 0x0101, 0x0202, 0x0303, 0x0404 },
121 { 0x11223344, 0x55667788 },
122 { (FLOAT
)1234.5678, (FLOAT
)8765.4321 },
126 static const char metadata_unknown
[] = "lalala";
128 static const char metadata_tEXt
[] = {
129 0,0,0,14, /* chunk length */
130 't','E','X','t', /* chunk type */
131 'w','i','n','e','t','e','s','t',0, /* keyword */
132 'v','a','l','u','e', /* text */
133 0x3f,0x64,0x19,0xf3 /* chunk CRC */
136 static const char pngimage
[285] = {
137 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
138 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
139 0xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
140 0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
141 0x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
142 0x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
143 0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
146 static const char *debugstr_guid(REFIID riid
)
153 sprintf(buf
, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
154 riid
->Data1
, riid
->Data2
, riid
->Data3
, riid
->Data4
[0],
155 riid
->Data4
[1], riid
->Data4
[2], riid
->Data4
[3], riid
->Data4
[4],
156 riid
->Data4
[5], riid
->Data4
[6], riid
->Data4
[7]);
161 static IStream
*create_stream(const char *data
, int data_size
)
168 hdata
= GlobalAlloc(GMEM_MOVEABLE
, data_size
);
169 ok(hdata
!= 0, "GlobalAlloc failed\n");
170 if (!hdata
) return NULL
;
172 locked_data
= GlobalLock(hdata
);
173 memcpy(locked_data
, data
, data_size
);
176 hr
= CreateStreamOnHGlobal(hdata
, TRUE
, &stream
);
177 ok(hr
== S_OK
, "CreateStreamOnHGlobal failed, hr=%x\n", hr
);
182 static void load_stream(IUnknown
*reader
, const char *data
, int data_size
)
185 IWICPersistStream
*persist
;
188 ULARGE_INTEGER cur_pos
;
190 stream
= create_stream(data
, data_size
);
194 hr
= IUnknown_QueryInterface(reader
, &IID_IWICPersistStream
, (void**)&persist
);
195 ok(hr
== S_OK
, "QueryInterface failed, hr=%x\n", hr
);
199 hr
= IWICPersistStream_LoadEx(persist
, stream
, NULL
, WICPersistOptionsDefault
);
200 ok(hr
== S_OK
, "LoadEx failed, hr=%x\n", hr
);
202 IWICPersistStream_Release(persist
);
206 hr
= IStream_Seek(stream
, pos
, SEEK_CUR
, &cur_pos
);
207 ok(hr
== S_OK
, "IStream_Seek error %#x\n", hr
);
208 /* IFD metadata reader doesn't rewind the stream to the start */
209 ok(cur_pos
.QuadPart
== 0 || cur_pos
.QuadPart
<= data_size
,
210 "current stream pos is at %x/%x, data size %x\n", cur_pos
.u
.LowPart
, cur_pos
.u
.HighPart
, data_size
);
212 IStream_Release(stream
);
215 static void test_metadata_unknown(void)
218 IWICMetadataReader
*reader
;
219 IWICEnumMetadataItem
*enumerator
;
220 IWICMetadataBlockReader
*blockreader
;
221 PROPVARIANT schema
, id
, value
;
222 ULONG items_returned
;
224 hr
= CoCreateInstance(&CLSID_WICUnknownMetadataReader
, NULL
, CLSCTX_INPROC_SERVER
,
225 &IID_IWICMetadataReader
, (void**)&reader
);
226 ok(hr
== S_OK
, "CoCreateInstance failed, hr=%x\n", hr
);
227 if (FAILED(hr
)) return;
229 load_stream((IUnknown
*)reader
, metadata_unknown
, sizeof(metadata_unknown
));
231 hr
= IWICMetadataReader_GetEnumerator(reader
, &enumerator
);
232 ok(hr
== S_OK
, "GetEnumerator failed, hr=%x\n", hr
);
236 PropVariantInit(&schema
);
237 PropVariantInit(&id
);
238 PropVariantInit(&value
);
240 hr
= IWICEnumMetadataItem_Next(enumerator
, 1, &schema
, &id
, &value
, &items_returned
);
241 ok(hr
== S_OK
, "Next failed, hr=%x\n", hr
);
242 ok(items_returned
== 1, "unexpected item count %i\n", items_returned
);
244 if (hr
== S_OK
&& items_returned
== 1)
246 ok(schema
.vt
== VT_EMPTY
, "unexpected vt: %i\n", schema
.vt
);
247 ok(id
.vt
== VT_EMPTY
, "unexpected vt: %i\n", id
.vt
);
248 expect_blob(value
, metadata_unknown
, sizeof(metadata_unknown
));
250 PropVariantClear(&schema
);
251 PropVariantClear(&id
);
252 PropVariantClear(&value
);
255 hr
= IWICEnumMetadataItem_Next(enumerator
, 1, &schema
, &id
, &value
, &items_returned
);
256 ok(hr
== S_FALSE
, "Next failed, hr=%x\n", hr
);
257 ok(items_returned
== 0, "unexpected item count %i\n", items_returned
);
259 IWICEnumMetadataItem_Release(enumerator
);
262 hr
= IWICMetadataReader_QueryInterface(reader
, &IID_IWICMetadataBlockReader
, (void**)&blockreader
);
263 ok(hr
== E_NOINTERFACE
, "QueryInterface failed, hr=%x\n", hr
);
266 IWICMetadataBlockReader_Release(blockreader
);
268 IWICMetadataReader_Release(reader
);
271 static void test_metadata_tEXt(void)
274 IWICMetadataReader
*reader
;
275 IWICEnumMetadataItem
*enumerator
;
276 PROPVARIANT schema
, id
, value
;
277 ULONG items_returned
, count
;
280 PropVariantInit(&schema
);
281 PropVariantInit(&id
);
282 PropVariantInit(&value
);
284 hr
= CoCreateInstance(&CLSID_WICPngTextMetadataReader
, NULL
, CLSCTX_INPROC_SERVER
,
285 &IID_IWICMetadataReader
, (void**)&reader
);
286 todo_wine
ok(hr
== S_OK
, "CoCreateInstance failed, hr=%x\n", hr
);
287 if (FAILED(hr
)) return;
289 hr
= IWICMetadataReader_GetCount(reader
, NULL
);
290 ok(hr
== E_INVALIDARG
, "GetCount failed, hr=%x\n", hr
);
292 hr
= IWICMetadataReader_GetCount(reader
, &count
);
293 ok(hr
== S_OK
, "GetCount failed, hr=%x\n", hr
);
294 ok(count
== 0, "unexpected count %i\n", count
);
296 load_stream((IUnknown
*)reader
, metadata_tEXt
, sizeof(metadata_tEXt
));
298 hr
= IWICMetadataReader_GetCount(reader
, &count
);
299 ok(hr
== S_OK
, "GetCount failed, hr=%x\n", hr
);
300 ok(count
== 1, "unexpected count %i\n", count
);
302 hr
= IWICMetadataReader_GetEnumerator(reader
, NULL
);
303 ok(hr
== E_INVALIDARG
, "GetEnumerator failed, hr=%x\n", hr
);
305 hr
= IWICMetadataReader_GetEnumerator(reader
, &enumerator
);
306 ok(hr
== S_OK
, "GetEnumerator failed, hr=%x\n", hr
);
310 hr
= IWICEnumMetadataItem_Next(enumerator
, 1, &schema
, &id
, &value
, &items_returned
);
311 ok(hr
== S_OK
, "Next failed, hr=%x\n", hr
);
312 ok(items_returned
== 1, "unexpected item count %i\n", items_returned
);
314 if (hr
== S_OK
&& items_returned
== 1)
316 ok(schema
.vt
== VT_EMPTY
, "unexpected vt: %i\n", schema
.vt
);
317 ok(id
.vt
== VT_LPSTR
, "unexpected vt: %i\n", id
.vt
);
318 ok(!strcmp(U(id
).pszVal
, "winetest"), "unexpected id: %s\n", U(id
).pszVal
);
319 ok(value
.vt
== VT_LPSTR
, "unexpected vt: %i\n", value
.vt
);
320 ok(!strcmp(U(value
).pszVal
, "value"), "unexpected value: %s\n", U(value
).pszVal
);
322 PropVariantClear(&schema
);
323 PropVariantClear(&id
);
324 PropVariantClear(&value
);
327 hr
= IWICEnumMetadataItem_Next(enumerator
, 1, &schema
, &id
, &value
, &items_returned
);
328 ok(hr
== S_FALSE
, "Next failed, hr=%x\n", hr
);
329 ok(items_returned
== 0, "unexpected item count %i\n", items_returned
);
331 IWICEnumMetadataItem_Release(enumerator
);
334 hr
= IWICMetadataReader_GetMetadataFormat(reader
, &format
);
335 ok(hr
== S_OK
, "GetMetadataFormat failed, hr=%x\n", hr
);
336 ok(IsEqualGUID(&format
, &GUID_MetadataFormatChunktEXt
), "unexpected format %s\n", debugstr_guid(&format
));
338 hr
= IWICMetadataReader_GetMetadataFormat(reader
, NULL
);
339 ok(hr
== E_INVALIDARG
, "GetMetadataFormat failed, hr=%x\n", hr
);
342 U(id
).pszVal
= CoTaskMemAlloc(strlen("winetest") + 1);
343 strcpy(U(id
).pszVal
, "winetest");
345 hr
= IWICMetadataReader_GetValue(reader
, NULL
, &id
, NULL
);
346 ok(hr
== S_OK
, "GetValue failed, hr=%x\n", hr
);
348 hr
= IWICMetadataReader_GetValue(reader
, &schema
, NULL
, &value
);
349 ok(hr
== E_INVALIDARG
, "GetValue failed, hr=%x\n", hr
);
351 hr
= IWICMetadataReader_GetValue(reader
, &schema
, &id
, &value
);
352 ok(hr
== S_OK
, "GetValue failed, hr=%x\n", hr
);
353 ok(value
.vt
== VT_LPSTR
, "unexpected vt: %i\n", id
.vt
);
354 ok(!strcmp(U(value
).pszVal
, "value"), "unexpected value: %s\n", U(value
).pszVal
);
355 PropVariantClear(&value
);
357 strcpy(U(id
).pszVal
, "test");
359 hr
= IWICMetadataReader_GetValue(reader
, &schema
, &id
, &value
);
360 ok(hr
== WINCODEC_ERR_PROPERTYNOTFOUND
, "GetValue failed, hr=%x\n", hr
);
362 PropVariantClear(&id
);
364 hr
= IWICMetadataReader_GetValueByIndex(reader
, 0, NULL
, NULL
, NULL
);
365 ok(hr
== S_OK
, "GetValueByIndex failed, hr=%x\n", hr
);
367 hr
= IWICMetadataReader_GetValueByIndex(reader
, 0, &schema
, NULL
, NULL
);
368 ok(hr
== S_OK
, "GetValueByIndex failed, hr=%x\n", hr
);
369 ok(schema
.vt
== VT_EMPTY
, "unexpected vt: %i\n", schema
.vt
);
371 hr
= IWICMetadataReader_GetValueByIndex(reader
, 0, NULL
, &id
, NULL
);
372 ok(hr
== S_OK
, "GetValueByIndex failed, hr=%x\n", hr
);
373 ok(id
.vt
== VT_LPSTR
, "unexpected vt: %i\n", id
.vt
);
374 ok(!strcmp(U(id
).pszVal
, "winetest"), "unexpected id: %s\n", U(id
).pszVal
);
375 PropVariantClear(&id
);
377 hr
= IWICMetadataReader_GetValueByIndex(reader
, 0, NULL
, NULL
, &value
);
378 ok(hr
== S_OK
, "GetValueByIndex failed, hr=%x\n", hr
);
379 ok(value
.vt
== VT_LPSTR
, "unexpected vt: %i\n", value
.vt
);
380 ok(!strcmp(U(value
).pszVal
, "value"), "unexpected value: %s\n", U(value
).pszVal
);
381 PropVariantClear(&value
);
383 hr
= IWICMetadataReader_GetValueByIndex(reader
, 1, NULL
, NULL
, NULL
);
384 ok(hr
== E_INVALIDARG
, "GetValueByIndex failed, hr=%x\n", hr
);
386 IWICMetadataReader_Release(reader
);
389 static void test_metadata_IFD(void)
391 static const struct test_data
394 int count
; /* if VT_VECTOR */
399 { VT_UI2
, 0xfe, 0, { 1 } },
400 { VT_UI4
, 0x100, 0, { 222 } },
401 { VT_UI4
, 0x101, 0, { 333 } },
402 { VT_UI2
, 0x102, 0, { 24 } },
403 { VT_UI4
, 0x103, 0, { 32773 } },
404 { VT_UI8
, 0x11a, 0, { ((LONGLONG
)3 << 32) | 900 } },
405 { VT_UI1
, 0xf001, 0, { 0x44 } },
406 { VT_UI1
|VT_VECTOR
, 0xf002, 4, { 0x44, 0x33, 0x22, 0x11 } },
407 { VT_I1
, 0xf003, 0, { 0x44 } },
408 { VT_I2
, 0xf004, 0, { 0x3344 } },
409 { VT_I2
|VT_VECTOR
, 0xf005, 2, { 0x3344, 0x1122 } },
410 { VT_I4
, 0xf006, 0, { 0x11223344 } },
411 { VT_R4
, 0xf007, 0, { 0x11223344 } },
412 { VT_R8
, 0xf008, 0, { ((LONGLONG
)0x41d26580 << 32) | 0xb486522c } },
413 { VT_I8
, 0xf009, 0, { ((LONGLONG
)0x5a6b7c8d << 32) | 0x1a2b3c4d } },
414 { VT_UI1
|VT_VECTOR
, 0xf00a, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
415 { VT_I2
|VT_VECTOR
, 0xf00b, 4, { 0x0101, 0x0202, 0x0303, 0x0404 } },
416 { VT_I4
|VT_VECTOR
, 0xf00c, 2, { 0x11223344, 0x55667788 } },
417 { VT_R4
|VT_VECTOR
, 0xf00d, 2, { 0x449a522b, 0x4608f5ba } },
418 { VT_LPSTR
, 0xf00e, 12, { 0 }, "Hello World!" },
419 { VT_LPSTR
, 0xf00f, 4, { 0 }, "abcd" },
420 { VT_BLOB
, 0xf010, 13, { 0 }, "Hello World!" },
421 { VT_BLOB
, 0xf011, 4, { 0 }, "abcd" },
422 { VT_UI1
, 0xf012, 0, { 0x44 } },
423 { VT_UI2
, 0xf013, 0, { 0x3344 } },
424 { VT_UI4
, 0xf014, 0, { 0x11223344 } },
425 { VT_R4
, 0xf015, 0, { 0x11223344 } },
428 IWICMetadataReader
*reader
;
429 IWICMetadataBlockReader
*blockreader
;
430 IWICEnumMetadataItem
*enumerator
;
431 PROPVARIANT schema
, id
, value
;
432 ULONG items_returned
, count
, i
;
435 PropVariantInit(&schema
);
436 PropVariantInit(&id
);
437 PropVariantInit(&value
);
439 hr
= CoCreateInstance(&CLSID_WICIfdMetadataReader
, NULL
, CLSCTX_INPROC_SERVER
,
440 &IID_IWICMetadataReader
, (void**)&reader
);
441 ok(hr
== S_OK
, "CoCreateInstance error %#x\n", hr
);
443 hr
= IWICMetadataReader_GetCount(reader
, NULL
);
444 ok(hr
== E_INVALIDARG
, "GetCount error %#x\n", hr
);
446 hr
= IWICMetadataReader_GetCount(reader
, &count
);
447 ok(hr
== S_OK
, "GetCount error %#x\n", hr
);
448 ok(count
== 0, "unexpected count %u\n", count
);
450 load_stream((IUnknown
*)reader
, (const char *)&IFD_data
, sizeof(IFD_data
));
452 hr
= IWICMetadataReader_GetCount(reader
, &count
);
453 ok(hr
== S_OK
, "GetCount error %#x\n", hr
);
454 ok(count
== sizeof(td
)/sizeof(td
[0]), "unexpected count %u\n", count
);
456 hr
= IWICMetadataReader_GetEnumerator(reader
, NULL
);
457 ok(hr
== E_INVALIDARG
, "GetEnumerator error %#x\n", hr
);
459 hr
= IWICMetadataReader_GetEnumerator(reader
, &enumerator
);
460 ok(hr
== S_OK
, "GetEnumerator error %#x\n", hr
);
462 for (i
= 0; i
< count
; i
++)
464 hr
= IWICEnumMetadataItem_Next(enumerator
, 1, &schema
, &id
, &value
, &items_returned
);
465 ok(hr
== S_OK
, "Next error %#x\n", hr
);
466 ok(items_returned
== 1, "unexpected item count %u\n", items_returned
);
468 ok(schema
.vt
== VT_EMPTY
, "%u: unexpected vt: %u\n", i
, schema
.vt
);
469 ok(id
.vt
== VT_UI2
, "%u: unexpected vt: %u\n", i
, id
.vt
);
470 ok(U(id
).uiVal
== td
[i
].id
, "%u: expected id %#x, got %#x\n", i
, td
[i
].id
, U(id
).uiVal
);
471 ok(value
.vt
== td
[i
].type
, "%u: expected vt %#x, got %#x\n", i
, td
[i
].type
, value
.vt
);
472 if (value
.vt
& VT_VECTOR
)
475 switch (value
.vt
& ~VT_VECTOR
)
479 ok(td
[i
].count
== U(value
).caub
.cElems
, "%u: expected cElems %d, got %d\n", i
, td
[i
].count
, U(value
).caub
.cElems
);
480 for (j
= 0; j
< U(value
).caub
.cElems
; j
++)
481 ok(td
[i
].value
[j
] == U(value
).caub
.pElems
[j
], "%u: expected value[%d] %#x/%#x, got %#x\n", i
, j
, (ULONG
)td
[i
].value
[j
], (ULONG
)(td
[i
].value
[j
] >> 32), U(value
).caub
.pElems
[j
]);
485 ok(td
[i
].count
== U(value
).caui
.cElems
, "%u: expected cElems %d, got %d\n", i
, td
[i
].count
, U(value
).caui
.cElems
);
486 for (j
= 0; j
< U(value
).caui
.cElems
; j
++)
487 ok(td
[i
].value
[j
] == U(value
).caui
.pElems
[j
], "%u: expected value[%d] %#x/%#x, got %#x\n", i
, j
, (ULONG
)td
[i
].value
[j
], (ULONG
)(td
[i
].value
[j
] >> 32), U(value
).caui
.pElems
[j
]);
492 ok(td
[i
].count
== U(value
).caul
.cElems
, "%u: expected cElems %d, got %d\n", i
, td
[i
].count
, U(value
).caui
.cElems
);
493 for (j
= 0; j
< U(value
).caul
.cElems
; j
++)
494 ok(td
[i
].value
[j
] == U(value
).caul
.pElems
[j
], "%u: expected value[%d] %#x/%#x, got %#x\n", i
, j
, (ULONG
)td
[i
].value
[j
], (ULONG
)(td
[i
].value
[j
] >> 32), U(value
).caul
.pElems
[j
]);
497 ok(td
[i
].count
== U(value
).calpstr
.cElems
, "%u: expected cElems %d, got %d\n", i
, td
[i
].count
, U(value
).caub
.cElems
);
498 for (j
= 0; j
< U(value
).calpstr
.cElems
; j
++)
499 trace("%u: %s\n", j
, U(value
).calpstr
.pElems
[j
]);
500 /* fall through to not handled message */
502 ok(0, "%u: array of type %d is not handled\n", i
, value
.vt
& ~VT_VECTOR
);
506 else if (value
.vt
== VT_LPSTR
)
508 ok(td
[i
].count
== strlen(U(value
).pszVal
) ||
509 broken(td
[i
].count
== strlen(U(value
).pszVal
) + 1), /* before Win7 */
510 "%u: expected count %d, got %d\n", i
, td
[i
].count
, lstrlenA(U(value
).pszVal
));
511 if (td
[i
].count
== strlen(U(value
).pszVal
))
512 ok(!strcmp(td
[i
].string
, U(value
).pszVal
),
513 "%u: expected %s, got %s\n", i
, td
[i
].string
, U(value
).pszVal
);
515 else if (value
.vt
== VT_BLOB
)
517 ok(td
[i
].count
== U(value
).blob
.cbSize
, "%u: expected count %d, got %d\n", i
, td
[i
].count
, U(value
).blob
.cbSize
);
518 ok(!memcmp(td
[i
].string
, U(value
).blob
.pBlobData
, td
[i
].count
), "%u: expected %s, got %s\n", i
, td
[i
].string
, U(value
).blob
.pBlobData
);
521 ok(U(value
).uhVal
.QuadPart
== td
[i
].value
[0], "%u: unexpected value: %d/%d\n", i
, U(value
).uhVal
.u
.LowPart
, U(value
).uhVal
.u
.HighPart
);
523 PropVariantClear(&schema
);
524 PropVariantClear(&id
);
525 PropVariantClear(&value
);
528 hr
= IWICEnumMetadataItem_Next(enumerator
, 1, &schema
, &id
, &value
, &items_returned
);
529 ok(hr
== S_FALSE
, "Next should fail\n");
530 ok(items_returned
== 0, "unexpected item count %u\n", items_returned
);
532 IWICEnumMetadataItem_Release(enumerator
);
534 hr
= IWICMetadataReader_GetMetadataFormat(reader
, &format
);
535 ok(hr
== S_OK
, "GetMetadataFormat error %#x\n", hr
);
536 ok(IsEqualGUID(&format
, &GUID_MetadataFormatIfd
), "unexpected format %s\n", debugstr_guid(&format
));
538 hr
= IWICMetadataReader_GetMetadataFormat(reader
, NULL
);
539 ok(hr
== E_INVALIDARG
, "GetMetadataFormat should fail\n");
541 hr
= IWICMetadataReader_GetValueByIndex(reader
, 0, NULL
, NULL
, NULL
);
542 ok(hr
== S_OK
, "GetValueByIndex error %#x\n", hr
);
544 hr
= IWICMetadataReader_GetValueByIndex(reader
, count
- 1, NULL
, NULL
, NULL
);
545 ok(hr
== S_OK
, "GetValueByIndex error %#x\n", hr
);
547 hr
= IWICMetadataReader_GetValueByIndex(reader
, 0, &schema
, NULL
, NULL
);
548 ok(hr
== S_OK
, "GetValueByIndex error %#x\n", hr
);
549 ok(schema
.vt
== VT_EMPTY
, "unexpected vt: %u\n", schema
.vt
);
551 hr
= IWICMetadataReader_GetValueByIndex(reader
, count
- 1, &schema
, NULL
, NULL
);
552 ok(hr
== S_OK
, "GetValueByIndex error %#x\n", hr
);
553 ok(schema
.vt
== VT_EMPTY
, "unexpected vt: %u\n", schema
.vt
);
555 hr
= IWICMetadataReader_GetValueByIndex(reader
, 0, NULL
, &id
, NULL
);
556 ok(hr
== S_OK
, "GetValueByIndex error %#x\n", hr
);
557 ok(id
.vt
== VT_UI2
, "unexpected vt: %u\n", id
.vt
);
558 ok(U(id
).uiVal
== 0xfe, "unexpected id: %#x\n", U(id
).uiVal
);
559 PropVariantClear(&id
);
561 hr
= IWICMetadataReader_GetValueByIndex(reader
, 0, NULL
, NULL
, &value
);
562 ok(hr
== S_OK
, "GetValueByIndex error %#x\n", hr
);
563 ok(value
.vt
== VT_UI2
, "unexpected vt: %u\n", value
.vt
);
564 ok(U(value
).ulVal
== 1, "unexpected id: %u\n", U(value
).ulVal
);
565 PropVariantClear(&value
);
567 hr
= IWICMetadataReader_GetValueByIndex(reader
, count
, &schema
, NULL
, NULL
);
568 ok(hr
== E_INVALIDARG
, "GetValueByIndex should fail\n");
570 hr
= IWICMetadataReader_QueryInterface(reader
, &IID_IWICMetadataBlockReader
, (void**)&blockreader
);
571 ok(hr
== E_NOINTERFACE
, "QueryInterface failed, hr=%x\n", hr
);
574 IWICMetadataBlockReader_Release(blockreader
);
576 IWICMetadataReader_Release(reader
);
579 static void test_metadata_Exif(void)
582 IWICMetadataReader
*reader
;
583 IWICMetadataBlockReader
*blockreader
;
586 hr
= CoCreateInstance(&CLSID_WICExifMetadataReader
, NULL
, CLSCTX_INPROC_SERVER
,
587 &IID_IWICMetadataReader
, (void**)&reader
);
588 todo_wine
ok(hr
== S_OK
, "CoCreateInstance error %#x\n", hr
);
589 if (FAILED(hr
)) return;
591 hr
= IWICMetadataReader_GetCount(reader
, NULL
);
592 ok(hr
== E_INVALIDARG
, "GetCount error %#x\n", hr
);
594 hr
= IWICMetadataReader_GetCount(reader
, &count
);
595 ok(hr
== S_OK
, "GetCount error %#x\n", hr
);
596 ok(count
== 0, "unexpected count %u\n", count
);
598 hr
= IWICMetadataReader_QueryInterface(reader
, &IID_IWICMetadataBlockReader
, (void**)&blockreader
);
599 ok(hr
== E_NOINTERFACE
, "QueryInterface failed, hr=%x\n", hr
);
602 IWICMetadataBlockReader_Release(blockreader
);
604 IWICMetadataReader_Release(reader
);
607 static void test_create_reader(void)
610 IWICComponentFactory
*factory
;
612 IWICMetadataReader
*reader
;
616 hr
= CoCreateInstance(&CLSID_WICImagingFactory
, NULL
, CLSCTX_INPROC_SERVER
,
617 &IID_IWICComponentFactory
, (void**)&factory
);
618 ok(hr
== S_OK
, "CoCreateInstance failed, hr=%x\n", hr
);
620 stream
= create_stream(metadata_tEXt
, sizeof(metadata_tEXt
));
622 hr
= IWICComponentFactory_CreateMetadataReaderFromContainer(factory
,
623 &GUID_ContainerFormatPng
, NULL
, WICPersistOptionsDefault
,
626 ok(hr
== S_OK
, "CreateMetadataReaderFromContainer failed, hr=%x\n", hr
);
627 if (FAILED(hr
)) return;
631 hr
= IWICMetadataReader_GetCount(reader
, &count
);
632 ok(hr
== S_OK
, "GetCount failed, hr=%x\n", hr
);
633 ok(count
== 1, "unexpected count %i\n", count
);
635 hr
= IWICMetadataReader_GetMetadataFormat(reader
, &format
);
636 ok(hr
== S_OK
, "GetMetadataFormat failed, hr=%x\n", hr
);
637 ok(IsEqualGUID(&format
, &GUID_MetadataFormatChunktEXt
), "unexpected format %s\n", debugstr_guid(&format
));
639 IWICMetadataReader_Release(reader
);
642 hr
= IWICComponentFactory_CreateMetadataReaderFromContainer(factory
,
643 &GUID_ContainerFormatWmp
, NULL
, WICPersistOptionsDefault
,
645 ok(hr
== S_OK
, "CreateMetadataReaderFromContainer failed, hr=%x\n", hr
);
649 hr
= IWICMetadataReader_GetCount(reader
, &count
);
650 ok(hr
== S_OK
, "GetCount failed, hr=%x\n", hr
);
651 ok(count
== 1, "unexpected count %i\n", count
);
653 hr
= IWICMetadataReader_GetMetadataFormat(reader
, &format
);
654 ok(hr
== S_OK
, "GetMetadataFormat failed, hr=%x\n", hr
);
655 ok(IsEqualGUID(&format
, &GUID_MetadataFormatUnknown
), "unexpected format %s\n", debugstr_guid(&format
));
657 IWICMetadataReader_Release(reader
);
660 IStream_Release(stream
);
662 IWICComponentFactory_Release(factory
);
665 static void test_metadata_png(void)
668 IWICBitmapDecoder
*decoder
;
669 IWICBitmapFrameDecode
*frame
;
670 IWICMetadataBlockReader
*blockreader
;
671 IWICMetadataReader
*reader
;
672 GUID containerformat
;
676 hr
= CoCreateInstance(&CLSID_WICPngDecoder
, NULL
, CLSCTX_INPROC_SERVER
,
677 &IID_IWICBitmapDecoder
, (void**)&decoder
);
678 ok(hr
== S_OK
, "CoCreateInstance failed, hr=%x\n", hr
);
680 if (FAILED(hr
)) return;
682 stream
= create_stream(pngimage
, sizeof(pngimage
));
684 hr
= IWICBitmapDecoder_Initialize(decoder
, stream
, WICDecodeMetadataCacheOnLoad
);
685 ok(hr
== S_OK
, "Initialize failed, hr=%x\n", hr
);
687 hr
= IWICBitmapDecoder_QueryInterface(decoder
, &IID_IWICMetadataBlockReader
, (void**)&blockreader
);
688 ok(hr
== E_NOINTERFACE
, "QueryInterface failed, hr=%x\n", hr
);
690 hr
= IWICBitmapDecoder_GetFrame(decoder
, 0, &frame
);
691 ok(hr
== S_OK
, "GetFrame failed, hr=%x\n", hr
);
693 hr
= IWICBitmapFrameDecode_QueryInterface(frame
, &IID_IWICMetadataBlockReader
, (void**)&blockreader
);
694 ok(hr
== S_OK
, "QueryInterface failed, hr=%x\n", hr
);
698 hr
= IWICMetadataBlockReader_GetContainerFormat(blockreader
, NULL
);
699 ok(hr
== E_INVALIDARG
, "GetContainerFormat failed, hr=%x\n", hr
);
701 hr
= IWICMetadataBlockReader_GetContainerFormat(blockreader
, &containerformat
);
702 ok(hr
== S_OK
, "GetContainerFormat failed, hr=%x\n", hr
);
703 ok(IsEqualGUID(&containerformat
, &GUID_ContainerFormatPng
), "unexpected container format\n");
705 hr
= IWICMetadataBlockReader_GetCount(blockreader
, NULL
);
706 todo_wine
ok(hr
== E_INVALIDARG
, "GetCount failed, hr=%x\n", hr
);
708 hr
= IWICMetadataBlockReader_GetCount(blockreader
, &count
);
709 todo_wine
ok(hr
== S_OK
, "GetCount failed, hr=%x\n", hr
);
710 todo_wine
ok(count
== 1, "unexpected count %d\n", count
);
714 /* Crashes on Windows XP */
715 hr
= IWICMetadataBlockReader_GetReaderByIndex(blockreader
, 0, NULL
);
716 ok(hr
== E_INVALIDARG
, "GetReaderByIndex failed, hr=%x\n", hr
);
719 hr
= IWICMetadataBlockReader_GetReaderByIndex(blockreader
, 0, &reader
);
720 todo_wine
ok(hr
== S_OK
, "GetReaderByIndex failed, hr=%x\n", hr
);
724 hr
= IWICMetadataReader_GetMetadataFormat(reader
, &containerformat
);
725 ok(IsEqualGUID(&containerformat
, &GUID_MetadataFormatChunktIME
) ||
726 broken(IsEqualGUID(&containerformat
, &GUID_MetadataFormatUnknown
)) /* Windows XP */,
727 "unexpected container format\n");
729 IWICMetadataReader_Release(reader
);
732 hr
= IWICMetadataBlockReader_GetReaderByIndex(blockreader
, 1, &reader
);
733 todo_wine
ok(hr
== WINCODEC_ERR_VALUEOUTOFRANGE
, "GetReaderByIndex failed, hr=%x\n", hr
);
735 IWICMetadataBlockReader_Release(blockreader
);
738 IWICBitmapFrameDecode_Release(frame
);
740 IWICBitmapDecoder_Release(decoder
);
742 IWICStream_Release(stream
);
747 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
749 test_metadata_unknown();
750 test_metadata_tEXt();
752 test_metadata_Exif();
753 test_create_reader();