windowscodecs: Add a test to show that metadata reader may not rewind the stream...
[wine/wine-gecko.git] / dlls / windowscodecs / tests / metadata.c
blob6b25963f37f368d804e30c6a401e513d71d7fac3
1 /*
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
20 #include <stdio.h>
21 #include <stdarg.h>
22 #include <math.h>
24 #define COBJMACROS
26 #include "windef.h"
27 #include "objbase.h"
28 #include "wincodec.h"
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"); \
38 } \
39 } \
40 } while (0)
42 #define IFD_SHORT 3
43 #define IFD_LONG 4
44 #define IFD_RATIONAL 5
46 #include "pshpack2.h"
47 struct IFD_entry
49 SHORT id;
50 SHORT type;
51 ULONG length;
52 LONG value;
55 struct IFD_rational
57 LONG numerator;
58 LONG denominator;
61 static const struct
63 USHORT number_of_entries;
64 struct IFD_entry entry[6];
65 ULONG next_IFD;
66 struct IFD_rational xres;
67 } IFD_data =
71 { 0xfe, IFD_SHORT, 1, 1 }, /* NEWSUBFILETYPE */
72 { 0x100, IFD_LONG, 1, 222 }, /* IMAGEWIDTH */
73 { 0x101, IFD_LONG, 1, 333 }, /* IMAGELENGTH */
74 { 0x102, IFD_SHORT, 1, 24 }, /* BITSPERSAMPLE */
75 { 0x103, IFD_LONG, 1, 32773 }, /* COMPRESSION: packbits */
76 { 0x11a, IFD_RATIONAL, 1, /* XRESOLUTION */
77 sizeof(USHORT) + sizeof(struct IFD_entry) * 6 + sizeof(ULONG) }
80 { 900, 3 }
82 #include "poppack.h"
84 static const char metadata_unknown[] = "lalala";
86 static const char metadata_tEXt[] = {
87 0,0,0,14, /* chunk length */
88 't','E','X','t', /* chunk type */
89 'w','i','n','e','t','e','s','t',0, /* keyword */
90 'v','a','l','u','e', /* text */
91 0x3f,0x64,0x19,0xf3 /* chunk CRC */
94 static const char pngimage[285] = {
95 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
96 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
97 0xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
98 0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
99 0x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
100 0x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
101 0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
104 static const char *debugstr_guid(REFIID riid)
106 static char buf[50];
108 if(!riid)
109 return "(null)";
111 sprintf(buf, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
112 riid->Data1, riid->Data2, riid->Data3, riid->Data4[0],
113 riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4],
114 riid->Data4[5], riid->Data4[6], riid->Data4[7]);
116 return buf;
119 static IStream *create_stream(const char *data, int data_size)
121 HRESULT hr;
122 IStream *stream;
123 HGLOBAL hdata;
124 void *locked_data;
126 hdata = GlobalAlloc(GMEM_MOVEABLE, data_size);
127 ok(hdata != 0, "GlobalAlloc failed\n");
128 if (!hdata) return NULL;
130 locked_data = GlobalLock(hdata);
131 memcpy(locked_data, data, data_size);
132 GlobalUnlock(hdata);
134 hr = CreateStreamOnHGlobal(hdata, TRUE, &stream);
135 ok(hr == S_OK, "CreateStreamOnHGlobal failed, hr=%x\n", hr);
137 return stream;
140 static void load_stream(IUnknown *reader, const char *data, int data_size)
142 HRESULT hr;
143 IWICPersistStream *persist;
144 IStream *stream;
145 LARGE_INTEGER pos;
146 ULARGE_INTEGER cur_pos;
148 stream = create_stream(data, data_size);
149 if (!stream)
150 return;
152 hr = IUnknown_QueryInterface(reader, &IID_IWICPersistStream, (void**)&persist);
153 ok(hr == S_OK, "QueryInterface failed, hr=%x\n", hr);
155 if (SUCCEEDED(hr))
157 hr = IWICPersistStream_LoadEx(persist, stream, NULL, WICPersistOptionsDefault);
158 ok(hr == S_OK, "LoadEx failed, hr=%x\n", hr);
160 IWICPersistStream_Release(persist);
163 pos.QuadPart = 0;
164 hr = IStream_Seek(stream, pos, SEEK_CUR, &cur_pos);
165 ok(hr == S_OK, "IStream_Seek error %#x\n", hr);
166 /* IFD metadata reader doesn't rewind the stream to the start */
167 ok(cur_pos.QuadPart == 0 || cur_pos.QuadPart <= data_size,
168 "current stream pos is at %x/%x, data size %x\n", cur_pos.u.LowPart, cur_pos.u.HighPart, data_size);
170 IStream_Release(stream);
173 static void test_metadata_unknown(void)
175 HRESULT hr;
176 IWICMetadataReader *reader;
177 IWICEnumMetadataItem *enumerator;
178 IWICMetadataBlockReader *blockreader;
179 PROPVARIANT schema, id, value;
180 ULONG items_returned;
182 hr = CoCreateInstance(&CLSID_WICUnknownMetadataReader, NULL, CLSCTX_INPROC_SERVER,
183 &IID_IWICMetadataReader, (void**)&reader);
184 ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
185 if (FAILED(hr)) return;
187 load_stream((IUnknown*)reader, metadata_unknown, sizeof(metadata_unknown));
189 hr = IWICMetadataReader_GetEnumerator(reader, &enumerator);
190 ok(hr == S_OK, "GetEnumerator failed, hr=%x\n", hr);
192 if (SUCCEEDED(hr))
194 PropVariantInit(&schema);
195 PropVariantInit(&id);
196 PropVariantInit(&value);
198 hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
199 ok(hr == S_OK, "Next failed, hr=%x\n", hr);
200 ok(items_returned == 1, "unexpected item count %i\n", items_returned);
202 if (hr == S_OK && items_returned == 1)
204 ok(schema.vt == VT_EMPTY, "unexpected vt: %i\n", schema.vt);
205 ok(id.vt == VT_EMPTY, "unexpected vt: %i\n", id.vt);
206 expect_blob(value, metadata_unknown, sizeof(metadata_unknown));
208 PropVariantClear(&schema);
209 PropVariantClear(&id);
210 PropVariantClear(&value);
213 hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
214 ok(hr == S_FALSE, "Next failed, hr=%x\n", hr);
215 ok(items_returned == 0, "unexpected item count %i\n", items_returned);
217 IWICEnumMetadataItem_Release(enumerator);
220 hr = IWICMetadataReader_QueryInterface(reader, &IID_IWICMetadataBlockReader, (void**)&blockreader);
221 ok(hr == E_NOINTERFACE, "QueryInterface failed, hr=%x\n", hr);
223 if (SUCCEEDED(hr))
224 IWICMetadataBlockReader_Release(blockreader);
226 IWICMetadataReader_Release(reader);
229 static void test_metadata_tEXt(void)
231 HRESULT hr;
232 IWICMetadataReader *reader;
233 IWICEnumMetadataItem *enumerator;
234 PROPVARIANT schema, id, value;
235 ULONG items_returned, count;
236 GUID format;
238 PropVariantInit(&schema);
239 PropVariantInit(&id);
240 PropVariantInit(&value);
242 hr = CoCreateInstance(&CLSID_WICPngTextMetadataReader, NULL, CLSCTX_INPROC_SERVER,
243 &IID_IWICMetadataReader, (void**)&reader);
244 todo_wine ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
245 if (FAILED(hr)) return;
247 hr = IWICMetadataReader_GetCount(reader, NULL);
248 ok(hr == E_INVALIDARG, "GetCount failed, hr=%x\n", hr);
250 hr = IWICMetadataReader_GetCount(reader, &count);
251 ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
252 ok(count == 0, "unexpected count %i\n", count);
254 load_stream((IUnknown*)reader, metadata_tEXt, sizeof(metadata_tEXt));
256 hr = IWICMetadataReader_GetCount(reader, &count);
257 ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
258 ok(count == 1, "unexpected count %i\n", count);
260 hr = IWICMetadataReader_GetEnumerator(reader, NULL);
261 ok(hr == E_INVALIDARG, "GetEnumerator failed, hr=%x\n", hr);
263 hr = IWICMetadataReader_GetEnumerator(reader, &enumerator);
264 ok(hr == S_OK, "GetEnumerator failed, hr=%x\n", hr);
266 if (SUCCEEDED(hr))
268 hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
269 ok(hr == S_OK, "Next failed, hr=%x\n", hr);
270 ok(items_returned == 1, "unexpected item count %i\n", items_returned);
272 if (hr == S_OK && items_returned == 1)
274 ok(schema.vt == VT_EMPTY, "unexpected vt: %i\n", schema.vt);
275 ok(id.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt);
276 ok(!strcmp(U(id).pszVal, "winetest"), "unexpected id: %s\n", U(id).pszVal);
277 ok(value.vt == VT_LPSTR, "unexpected vt: %i\n", value.vt);
278 ok(!strcmp(U(value).pszVal, "value"), "unexpected value: %s\n", U(value).pszVal);
280 PropVariantClear(&schema);
281 PropVariantClear(&id);
282 PropVariantClear(&value);
285 hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
286 ok(hr == S_FALSE, "Next failed, hr=%x\n", hr);
287 ok(items_returned == 0, "unexpected item count %i\n", items_returned);
289 IWICEnumMetadataItem_Release(enumerator);
292 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
293 ok(hr == S_OK, "GetMetadataFormat failed, hr=%x\n", hr);
294 ok(IsEqualGUID(&format, &GUID_MetadataFormatChunktEXt), "unexpected format %s\n", debugstr_guid(&format));
296 hr = IWICMetadataReader_GetMetadataFormat(reader, NULL);
297 ok(hr == E_INVALIDARG, "GetMetadataFormat failed, hr=%x\n", hr);
299 id.vt = VT_LPSTR;
300 U(id).pszVal = CoTaskMemAlloc(strlen("winetest") + 1);
301 strcpy(U(id).pszVal, "winetest");
303 hr = IWICMetadataReader_GetValue(reader, NULL, &id, NULL);
304 ok(hr == S_OK, "GetValue failed, hr=%x\n", hr);
306 hr = IWICMetadataReader_GetValue(reader, &schema, NULL, &value);
307 ok(hr == E_INVALIDARG, "GetValue failed, hr=%x\n", hr);
309 hr = IWICMetadataReader_GetValue(reader, &schema, &id, &value);
310 ok(hr == S_OK, "GetValue failed, hr=%x\n", hr);
311 ok(value.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt);
312 ok(!strcmp(U(value).pszVal, "value"), "unexpected value: %s\n", U(value).pszVal);
313 PropVariantClear(&value);
315 strcpy(U(id).pszVal, "test");
317 hr = IWICMetadataReader_GetValue(reader, &schema, &id, &value);
318 ok(hr == WINCODEC_ERR_PROPERTYNOTFOUND, "GetValue failed, hr=%x\n", hr);
320 PropVariantClear(&id);
322 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, NULL, NULL);
323 ok(hr == S_OK, "GetValueByIndex failed, hr=%x\n", hr);
325 hr = IWICMetadataReader_GetValueByIndex(reader, 0, &schema, NULL, NULL);
326 ok(hr == S_OK, "GetValueByIndex failed, hr=%x\n", hr);
327 ok(schema.vt == VT_EMPTY, "unexpected vt: %i\n", schema.vt);
329 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, &id, NULL);
330 ok(hr == S_OK, "GetValueByIndex failed, hr=%x\n", hr);
331 ok(id.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt);
332 ok(!strcmp(U(id).pszVal, "winetest"), "unexpected id: %s\n", U(id).pszVal);
333 PropVariantClear(&id);
335 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, NULL, &value);
336 ok(hr == S_OK, "GetValueByIndex failed, hr=%x\n", hr);
337 ok(value.vt == VT_LPSTR, "unexpected vt: %i\n", value.vt);
338 ok(!strcmp(U(value).pszVal, "value"), "unexpected value: %s\n", U(value).pszVal);
339 PropVariantClear(&value);
341 hr = IWICMetadataReader_GetValueByIndex(reader, 1, NULL, NULL, NULL);
342 ok(hr == E_INVALIDARG, "GetValueByIndex failed, hr=%x\n", hr);
344 IWICMetadataReader_Release(reader);
347 static void test_metadata_IFD(void)
349 static const struct test_data
351 ULONG type, id;
352 LONGLONG value;
353 } td[6] =
355 { VT_UI2, 0xfe, 1 },
356 { VT_UI4, 0x100, 222 },
357 { VT_UI4, 0x101, 333 },
358 { VT_UI2, 0x102, 24 },
359 { VT_UI4, 0x103, 32773 },
360 { VT_UI8, 0x11a, ((LONGLONG)3 << 32) | 900 }
362 HRESULT hr;
363 IWICMetadataReader *reader;
364 IWICMetadataBlockReader *blockreader;
365 IWICEnumMetadataItem *enumerator;
366 PROPVARIANT schema, id, value;
367 ULONG items_returned, count, i;
368 GUID format;
370 PropVariantInit(&schema);
371 PropVariantInit(&id);
372 PropVariantInit(&value);
374 hr = CoCreateInstance(&CLSID_WICIfdMetadataReader, NULL, CLSCTX_INPROC_SERVER,
375 &IID_IWICMetadataReader, (void**)&reader);
376 ok(hr == S_OK, "CoCreateInstance error %#x\n", hr);
378 hr = IWICMetadataReader_GetCount(reader, NULL);
379 ok(hr == E_INVALIDARG, "GetCount error %#x\n", hr);
381 hr = IWICMetadataReader_GetCount(reader, &count);
382 ok(hr == S_OK, "GetCount error %#x\n", hr);
383 ok(count == 0, "unexpected count %u\n", count);
385 load_stream((IUnknown*)reader, (const char *)&IFD_data, sizeof(IFD_data));
387 hr = IWICMetadataReader_GetCount(reader, &count);
388 ok(hr == S_OK, "GetCount error %#x\n", hr);
389 todo_wine
390 ok(count == 6, "unexpected count %u\n", count);
392 hr = IWICMetadataReader_GetEnumerator(reader, NULL);
393 ok(hr == E_INVALIDARG, "GetEnumerator error %#x\n", hr);
395 hr = IWICMetadataReader_GetEnumerator(reader, &enumerator);
396 ok(hr == S_OK, "GetEnumerator error %#x\n", hr);
398 for (i = 0; i < count; i++)
400 hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
401 ok(hr == S_OK, "Next error %#x\n", hr);
402 ok(items_returned == 1, "unexpected item count %u\n", items_returned);
404 ok(schema.vt == VT_EMPTY, "%u: unexpected vt: %u\n", i, schema.vt);
405 ok(id.vt == VT_UI2, "%u: unexpected vt: %u\n", i, id.vt);
406 ok(U(id).uiVal == td[i].id, "%u: unexpected id: %#x\n", i, U(id).uiVal);
407 ok(value.vt == td[i].type, "%u: unexpected vt: %u\n", i, value.vt);
408 ok(U(value).uhVal.QuadPart == td[i].value, "%u: unexpected id: %d/%d\n", i, U(value).uhVal.u.LowPart, U(value).uhVal.u.HighPart);
410 PropVariantClear(&schema);
411 PropVariantClear(&id);
412 PropVariantClear(&value);
415 hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
416 ok(hr == S_FALSE, "Next should fail\n");
417 ok(items_returned == 0, "unexpected item count %u\n", items_returned);
419 IWICEnumMetadataItem_Release(enumerator);
421 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
422 todo_wine
423 ok(hr == S_OK, "GetMetadataFormat error %#x\n", hr);
424 todo_wine
425 ok(IsEqualGUID(&format, &GUID_MetadataFormatIfd), "unexpected format %s\n", debugstr_guid(&format));
427 hr = IWICMetadataReader_GetMetadataFormat(reader, NULL);
428 ok(hr == E_INVALIDARG, "GetMetadataFormat should fail\n");
430 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, NULL, NULL);
431 todo_wine
432 ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
433 if (FAILED(hr))
435 IWICMetadataReader_Release(reader);
436 return;
439 hr = IWICMetadataReader_GetValueByIndex(reader, count - 1, NULL, NULL, NULL);
440 ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
442 hr = IWICMetadataReader_GetValueByIndex(reader, 0, &schema, NULL, NULL);
443 ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
444 ok(schema.vt == VT_EMPTY, "unexpected vt: %u\n", schema.vt);
446 hr = IWICMetadataReader_GetValueByIndex(reader, count - 1, &schema, NULL, NULL);
447 ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
448 ok(schema.vt == VT_EMPTY, "unexpected vt: %u\n", schema.vt);
450 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, &id, NULL);
451 ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
452 ok(id.vt == VT_UI2, "unexpected vt: %u\n", id.vt);
453 ok(U(id).uiVal == 0xfe, "unexpected id: %#x\n", U(id).uiVal);
454 PropVariantClear(&id);
456 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, NULL, &value);
457 ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
458 ok(value.vt == VT_UI2, "unexpected vt: %u\n", value.vt);
459 ok(U(value).ulVal == 1, "unexpected id: %u\n", U(value).ulVal);
460 PropVariantClear(&value);
462 hr = IWICMetadataReader_GetValueByIndex(reader, count, &schema, NULL, NULL);
463 ok(hr == E_INVALIDARG, "GetValueByIndex should fail\n");
465 hr = IWICMetadataReader_QueryInterface(reader, &IID_IWICMetadataBlockReader, (void**)&blockreader);
466 ok(hr == E_NOINTERFACE, "QueryInterface failed, hr=%x\n", hr);
468 if (SUCCEEDED(hr))
469 IWICMetadataBlockReader_Release(blockreader);
471 IWICMetadataReader_Release(reader);
474 static void test_metadata_Exif(void)
476 HRESULT hr;
477 IWICMetadataReader *reader;
478 IWICMetadataBlockReader *blockreader;
479 UINT count=0;
481 hr = CoCreateInstance(&CLSID_WICExifMetadataReader, NULL, CLSCTX_INPROC_SERVER,
482 &IID_IWICMetadataReader, (void**)&reader);
483 todo_wine ok(hr == S_OK, "CoCreateInstance error %#x\n", hr);
484 if (FAILED(hr)) return;
486 hr = IWICMetadataReader_GetCount(reader, NULL);
487 ok(hr == E_INVALIDARG, "GetCount error %#x\n", hr);
489 hr = IWICMetadataReader_GetCount(reader, &count);
490 ok(hr == S_OK, "GetCount error %#x\n", hr);
491 ok(count == 0, "unexpected count %u\n", count);
493 hr = IWICMetadataReader_QueryInterface(reader, &IID_IWICMetadataBlockReader, (void**)&blockreader);
494 ok(hr == E_NOINTERFACE, "QueryInterface failed, hr=%x\n", hr);
496 if (SUCCEEDED(hr))
497 IWICMetadataBlockReader_Release(blockreader);
499 IWICMetadataReader_Release(reader);
502 static void test_create_reader(void)
504 HRESULT hr;
505 IWICComponentFactory *factory;
506 IStream *stream;
507 IWICMetadataReader *reader;
508 UINT count=0;
509 GUID format;
511 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
512 &IID_IWICComponentFactory, (void**)&factory);
513 ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
515 stream = create_stream(metadata_tEXt, sizeof(metadata_tEXt));
517 hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
518 &GUID_ContainerFormatPng, NULL, WICPersistOptionsDefault,
519 stream, &reader);
520 todo_wine
521 ok(hr == S_OK, "CreateMetadataReaderFromContainer failed, hr=%x\n", hr);
522 if (FAILED(hr)) return;
524 if (SUCCEEDED(hr))
526 hr = IWICMetadataReader_GetCount(reader, &count);
527 ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
528 ok(count == 1, "unexpected count %i\n", count);
530 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
531 ok(hr == S_OK, "GetMetadataFormat failed, hr=%x\n", hr);
532 ok(IsEqualGUID(&format, &GUID_MetadataFormatChunktEXt), "unexpected format %s\n", debugstr_guid(&format));
534 IWICMetadataReader_Release(reader);
537 hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
538 &GUID_ContainerFormatWmp, NULL, WICPersistOptionsDefault,
539 stream, &reader);
540 ok(hr == S_OK, "CreateMetadataReaderFromContainer failed, hr=%x\n", hr);
542 if (SUCCEEDED(hr))
544 hr = IWICMetadataReader_GetCount(reader, &count);
545 ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
546 ok(count == 1, "unexpected count %i\n", count);
548 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
549 ok(hr == S_OK, "GetMetadataFormat failed, hr=%x\n", hr);
550 ok(IsEqualGUID(&format, &GUID_MetadataFormatUnknown), "unexpected format %s\n", debugstr_guid(&format));
552 IWICMetadataReader_Release(reader);
555 IStream_Release(stream);
557 IWICComponentFactory_Release(factory);
560 static void test_metadata_png(void)
562 IStream *stream;
563 IWICBitmapDecoder *decoder;
564 IWICBitmapFrameDecode *frame;
565 IWICMetadataBlockReader *blockreader;
566 IWICMetadataReader *reader;
567 GUID containerformat;
568 HRESULT hr;
569 UINT count;
571 hr = CoCreateInstance(&CLSID_WICPngDecoder, NULL, CLSCTX_INPROC_SERVER,
572 &IID_IWICBitmapDecoder, (void**)&decoder);
573 ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
575 if (FAILED(hr)) return;
577 stream = create_stream(pngimage, sizeof(pngimage));
579 hr = IWICBitmapDecoder_Initialize(decoder, stream, WICDecodeMetadataCacheOnLoad);
580 ok(hr == S_OK, "Initialize failed, hr=%x\n", hr);
582 hr = IWICBitmapDecoder_QueryInterface(decoder, &IID_IWICMetadataBlockReader, (void**)&blockreader);
583 ok(hr == E_NOINTERFACE, "QueryInterface failed, hr=%x\n", hr);
585 hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
586 ok(hr == S_OK, "GetFrame failed, hr=%x\n", hr);
588 hr = IWICBitmapFrameDecode_QueryInterface(frame, &IID_IWICMetadataBlockReader, (void**)&blockreader);
589 ok(hr == S_OK, "QueryInterface failed, hr=%x\n", hr);
591 if (SUCCEEDED(hr))
593 hr = IWICMetadataBlockReader_GetContainerFormat(blockreader, NULL);
594 ok(hr == E_INVALIDARG, "GetContainerFormat failed, hr=%x\n", hr);
596 hr = IWICMetadataBlockReader_GetContainerFormat(blockreader, &containerformat);
597 ok(hr == S_OK, "GetContainerFormat failed, hr=%x\n", hr);
598 ok(IsEqualGUID(&containerformat, &GUID_ContainerFormatPng), "unexpected container format\n");
600 hr = IWICMetadataBlockReader_GetCount(blockreader, NULL);
601 todo_wine ok(hr == E_INVALIDARG, "GetCount failed, hr=%x\n", hr);
603 hr = IWICMetadataBlockReader_GetCount(blockreader, &count);
604 todo_wine ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
605 todo_wine ok(count == 1, "unexpected count %d\n", count);
607 if (0)
609 /* Crashes on Windows XP */
610 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 0, NULL);
611 ok(hr == E_INVALIDARG, "GetReaderByIndex failed, hr=%x\n", hr);
614 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 0, &reader);
615 todo_wine ok(hr == S_OK, "GetReaderByIndex failed, hr=%x\n", hr);
617 if (SUCCEEDED(hr))
619 hr = IWICMetadataReader_GetMetadataFormat(reader, &containerformat);
620 ok(IsEqualGUID(&containerformat, &GUID_MetadataFormatChunktIME) ||
621 broken(IsEqualGUID(&containerformat, &GUID_MetadataFormatUnknown)) /* Windows XP */,
622 "unexpected container format\n");
624 IWICMetadataReader_Release(reader);
627 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 1, &reader);
628 todo_wine ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE, "GetReaderByIndex failed, hr=%x\n", hr);
630 IWICMetadataBlockReader_Release(blockreader);
633 IWICBitmapFrameDecode_Release(frame);
635 IWICBitmapDecoder_Release(decoder);
637 IWICStream_Release(stream);
640 START_TEST(metadata)
642 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
644 test_metadata_unknown();
645 test_metadata_tEXt();
646 test_metadata_IFD();
647 test_metadata_Exif();
648 test_create_reader();
649 test_metadata_png();
651 CoUninitialize();