windowscodecs: Implement partial loading of IFD metadata.
[wine/multimedia.git] / dlls / windowscodecs / tests / metadata.c
blobcf00f1f9afa9718ab25d3e3991b83acb8aa7f60b
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 ok(count == 6, "unexpected count %u\n", count);
391 hr = IWICMetadataReader_GetEnumerator(reader, NULL);
392 ok(hr == E_INVALIDARG, "GetEnumerator error %#x\n", hr);
394 hr = IWICMetadataReader_GetEnumerator(reader, &enumerator);
395 ok(hr == S_OK, "GetEnumerator error %#x\n", hr);
397 for (i = 0; i < count; i++)
399 hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
400 ok(hr == S_OK, "Next error %#x\n", hr);
401 ok(items_returned == 1, "unexpected item count %u\n", items_returned);
403 ok(schema.vt == VT_EMPTY, "%u: unexpected vt: %u\n", i, schema.vt);
404 ok(id.vt == VT_UI2, "%u: unexpected vt: %u\n", i, id.vt);
405 ok(U(id).uiVal == td[i].id, "%u: unexpected id: %#x\n", i, U(id).uiVal);
406 ok(value.vt == td[i].type, "%u: unexpected vt: %u\n", i, value.vt);
407 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);
409 PropVariantClear(&schema);
410 PropVariantClear(&id);
411 PropVariantClear(&value);
414 hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
415 ok(hr == S_FALSE, "Next should fail\n");
416 ok(items_returned == 0, "unexpected item count %u\n", items_returned);
418 IWICEnumMetadataItem_Release(enumerator);
420 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
421 todo_wine
422 ok(hr == S_OK, "GetMetadataFormat error %#x\n", hr);
423 todo_wine
424 ok(IsEqualGUID(&format, &GUID_MetadataFormatIfd), "unexpected format %s\n", debugstr_guid(&format));
426 hr = IWICMetadataReader_GetMetadataFormat(reader, NULL);
427 ok(hr == E_INVALIDARG, "GetMetadataFormat should fail\n");
429 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, NULL, NULL);
430 todo_wine
431 ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
432 if (FAILED(hr))
434 IWICMetadataReader_Release(reader);
435 return;
438 hr = IWICMetadataReader_GetValueByIndex(reader, count - 1, NULL, NULL, NULL);
439 ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
441 hr = IWICMetadataReader_GetValueByIndex(reader, 0, &schema, NULL, NULL);
442 ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
443 ok(schema.vt == VT_EMPTY, "unexpected vt: %u\n", schema.vt);
445 hr = IWICMetadataReader_GetValueByIndex(reader, count - 1, &schema, NULL, NULL);
446 ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
447 ok(schema.vt == VT_EMPTY, "unexpected vt: %u\n", schema.vt);
449 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, &id, NULL);
450 ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
451 ok(id.vt == VT_UI2, "unexpected vt: %u\n", id.vt);
452 ok(U(id).uiVal == 0xfe, "unexpected id: %#x\n", U(id).uiVal);
453 PropVariantClear(&id);
455 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, NULL, &value);
456 ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
457 ok(value.vt == VT_UI2, "unexpected vt: %u\n", value.vt);
458 ok(U(value).ulVal == 1, "unexpected id: %u\n", U(value).ulVal);
459 PropVariantClear(&value);
461 hr = IWICMetadataReader_GetValueByIndex(reader, count, &schema, NULL, NULL);
462 ok(hr == E_INVALIDARG, "GetValueByIndex should fail\n");
464 hr = IWICMetadataReader_QueryInterface(reader, &IID_IWICMetadataBlockReader, (void**)&blockreader);
465 ok(hr == E_NOINTERFACE, "QueryInterface failed, hr=%x\n", hr);
467 if (SUCCEEDED(hr))
468 IWICMetadataBlockReader_Release(blockreader);
470 IWICMetadataReader_Release(reader);
473 static void test_metadata_Exif(void)
475 HRESULT hr;
476 IWICMetadataReader *reader;
477 IWICMetadataBlockReader *blockreader;
478 UINT count=0;
480 hr = CoCreateInstance(&CLSID_WICExifMetadataReader, NULL, CLSCTX_INPROC_SERVER,
481 &IID_IWICMetadataReader, (void**)&reader);
482 todo_wine ok(hr == S_OK, "CoCreateInstance error %#x\n", hr);
483 if (FAILED(hr)) return;
485 hr = IWICMetadataReader_GetCount(reader, NULL);
486 ok(hr == E_INVALIDARG, "GetCount error %#x\n", hr);
488 hr = IWICMetadataReader_GetCount(reader, &count);
489 ok(hr == S_OK, "GetCount error %#x\n", hr);
490 ok(count == 0, "unexpected count %u\n", count);
492 hr = IWICMetadataReader_QueryInterface(reader, &IID_IWICMetadataBlockReader, (void**)&blockreader);
493 ok(hr == E_NOINTERFACE, "QueryInterface failed, hr=%x\n", hr);
495 if (SUCCEEDED(hr))
496 IWICMetadataBlockReader_Release(blockreader);
498 IWICMetadataReader_Release(reader);
501 static void test_create_reader(void)
503 HRESULT hr;
504 IWICComponentFactory *factory;
505 IStream *stream;
506 IWICMetadataReader *reader;
507 UINT count=0;
508 GUID format;
510 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
511 &IID_IWICComponentFactory, (void**)&factory);
512 ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
514 stream = create_stream(metadata_tEXt, sizeof(metadata_tEXt));
516 hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
517 &GUID_ContainerFormatPng, NULL, WICPersistOptionsDefault,
518 stream, &reader);
519 todo_wine
520 ok(hr == S_OK, "CreateMetadataReaderFromContainer failed, hr=%x\n", hr);
521 if (FAILED(hr)) return;
523 if (SUCCEEDED(hr))
525 hr = IWICMetadataReader_GetCount(reader, &count);
526 ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
527 ok(count == 1, "unexpected count %i\n", count);
529 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
530 ok(hr == S_OK, "GetMetadataFormat failed, hr=%x\n", hr);
531 ok(IsEqualGUID(&format, &GUID_MetadataFormatChunktEXt), "unexpected format %s\n", debugstr_guid(&format));
533 IWICMetadataReader_Release(reader);
536 hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
537 &GUID_ContainerFormatWmp, NULL, WICPersistOptionsDefault,
538 stream, &reader);
539 ok(hr == S_OK, "CreateMetadataReaderFromContainer failed, hr=%x\n", hr);
541 if (SUCCEEDED(hr))
543 hr = IWICMetadataReader_GetCount(reader, &count);
544 ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
545 ok(count == 1, "unexpected count %i\n", count);
547 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
548 ok(hr == S_OK, "GetMetadataFormat failed, hr=%x\n", hr);
549 ok(IsEqualGUID(&format, &GUID_MetadataFormatUnknown), "unexpected format %s\n", debugstr_guid(&format));
551 IWICMetadataReader_Release(reader);
554 IStream_Release(stream);
556 IWICComponentFactory_Release(factory);
559 static void test_metadata_png(void)
561 IStream *stream;
562 IWICBitmapDecoder *decoder;
563 IWICBitmapFrameDecode *frame;
564 IWICMetadataBlockReader *blockreader;
565 IWICMetadataReader *reader;
566 GUID containerformat;
567 HRESULT hr;
568 UINT count;
570 hr = CoCreateInstance(&CLSID_WICPngDecoder, NULL, CLSCTX_INPROC_SERVER,
571 &IID_IWICBitmapDecoder, (void**)&decoder);
572 ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
574 if (FAILED(hr)) return;
576 stream = create_stream(pngimage, sizeof(pngimage));
578 hr = IWICBitmapDecoder_Initialize(decoder, stream, WICDecodeMetadataCacheOnLoad);
579 ok(hr == S_OK, "Initialize failed, hr=%x\n", hr);
581 hr = IWICBitmapDecoder_QueryInterface(decoder, &IID_IWICMetadataBlockReader, (void**)&blockreader);
582 ok(hr == E_NOINTERFACE, "QueryInterface failed, hr=%x\n", hr);
584 hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
585 ok(hr == S_OK, "GetFrame failed, hr=%x\n", hr);
587 hr = IWICBitmapFrameDecode_QueryInterface(frame, &IID_IWICMetadataBlockReader, (void**)&blockreader);
588 ok(hr == S_OK, "QueryInterface failed, hr=%x\n", hr);
590 if (SUCCEEDED(hr))
592 hr = IWICMetadataBlockReader_GetContainerFormat(blockreader, NULL);
593 ok(hr == E_INVALIDARG, "GetContainerFormat failed, hr=%x\n", hr);
595 hr = IWICMetadataBlockReader_GetContainerFormat(blockreader, &containerformat);
596 ok(hr == S_OK, "GetContainerFormat failed, hr=%x\n", hr);
597 ok(IsEqualGUID(&containerformat, &GUID_ContainerFormatPng), "unexpected container format\n");
599 hr = IWICMetadataBlockReader_GetCount(blockreader, NULL);
600 todo_wine ok(hr == E_INVALIDARG, "GetCount failed, hr=%x\n", hr);
602 hr = IWICMetadataBlockReader_GetCount(blockreader, &count);
603 todo_wine ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
604 todo_wine ok(count == 1, "unexpected count %d\n", count);
606 if (0)
608 /* Crashes on Windows XP */
609 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 0, NULL);
610 ok(hr == E_INVALIDARG, "GetReaderByIndex failed, hr=%x\n", hr);
613 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 0, &reader);
614 todo_wine ok(hr == S_OK, "GetReaderByIndex failed, hr=%x\n", hr);
616 if (SUCCEEDED(hr))
618 hr = IWICMetadataReader_GetMetadataFormat(reader, &containerformat);
619 ok(IsEqualGUID(&containerformat, &GUID_MetadataFormatChunktIME) ||
620 broken(IsEqualGUID(&containerformat, &GUID_MetadataFormatUnknown)) /* Windows XP */,
621 "unexpected container format\n");
623 IWICMetadataReader_Release(reader);
626 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 1, &reader);
627 todo_wine ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE, "GetReaderByIndex failed, hr=%x\n", hr);
629 IWICMetadataBlockReader_Release(blockreader);
632 IWICBitmapFrameDecode_Release(frame);
634 IWICBitmapDecoder_Release(decoder);
636 IWICStream_Release(stream);
639 START_TEST(metadata)
641 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
643 test_metadata_unknown();
644 test_metadata_tEXt();
645 test_metadata_IFD();
646 test_metadata_Exif();
647 test_create_reader();
648 test_metadata_png();
650 CoUninitialize();