d3drm: Handle texture associated with the material when loading a mesh.
[wine] / dlls / windowscodecs / tests / metadata.c
1 /*
2  * Copyright 2011 Vincent Povirk for CodeWeavers
3  * Copyright 2012 Dmitry Timoshkov
4  *
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.
9  *
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.
14  *
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
18  */
19
20 #include <stdio.h>
21 #include <stdarg.h>
22 #include <math.h>
23
24 #define COBJMACROS
25
26 #include "windef.h"
27 #include "objbase.h"
28 #include "wincodec.h"
29 #include "wincodecsdk.h"
30 #include "wine/test.h"
31
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)
41
42 #define IFD_SHORT 3
43 #define IFD_LONG 4
44 #define IFD_RATIONAL 5
45
46 #include "pshpack2.h"
47 struct IFD_entry
48 {
49     SHORT id;
50     SHORT type;
51     ULONG length;
52     LONG  value;
53 };
54
55 struct IFD_rational
56 {
57     LONG numerator;
58     LONG denominator;
59 };
60
61 static const struct
62 {
63     USHORT number_of_entries;
64     struct IFD_entry entry[6];
65     ULONG next_IFD;
66     struct IFD_rational xres;
67 } IFD_data =
68 {
69     6,
70     {
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) }
78     },
79     0,
80     { 900, 3 }
81 };
82 #include "poppack.h"
83
84 static const char metadata_unknown[] = "lalala";
85
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 */
92 };
93
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
102 };
103
104 static const char *debugstr_guid(REFIID riid)
105 {
106     static char buf[50];
107
108     if(!riid)
109         return "(null)";
110
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]);
115
116     return buf;
117 }
118
119 static IStream *create_stream(const char *data, int data_size)
120 {
121     HRESULT hr;
122     IStream *stream;
123     HGLOBAL hdata;
124     void *locked_data;
125
126     hdata = GlobalAlloc(GMEM_MOVEABLE, data_size);
127     ok(hdata != 0, "GlobalAlloc failed\n");
128     if (!hdata) return NULL;
129
130     locked_data = GlobalLock(hdata);
131     memcpy(locked_data, data, data_size);
132     GlobalUnlock(hdata);
133
134     hr = CreateStreamOnHGlobal(hdata, TRUE, &stream);
135     ok(hr == S_OK, "CreateStreamOnHGlobal failed, hr=%x\n", hr);
136
137     return stream;
138 }
139
140 static void load_stream(IUnknown *reader, const char *data, int data_size)
141 {
142     HRESULT hr;
143     IWICPersistStream *persist;
144     IStream *stream;
145
146     stream = create_stream(data, data_size);
147     if (!stream)
148         return;
149
150     hr = IUnknown_QueryInterface(reader, &IID_IWICPersistStream, (void**)&persist);
151     ok(hr == S_OK, "QueryInterface failed, hr=%x\n", hr);
152
153     if (SUCCEEDED(hr))
154     {
155         hr = IWICPersistStream_LoadEx(persist, stream, NULL, WICPersistOptionsDefault);
156         ok(hr == S_OK, "LoadEx failed, hr=%x\n", hr);
157
158         IWICPersistStream_Release(persist);
159     }
160
161     IStream_Release(stream);
162 }
163
164 static void test_metadata_unknown(void)
165 {
166     HRESULT hr;
167     IWICMetadataReader *reader;
168     IWICEnumMetadataItem *enumerator;
169     IWICMetadataBlockReader *blockreader;
170     PROPVARIANT schema, id, value;
171     ULONG items_returned;
172
173     hr = CoCreateInstance(&CLSID_WICUnknownMetadataReader, NULL, CLSCTX_INPROC_SERVER,
174         &IID_IWICMetadataReader, (void**)&reader);
175     ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
176     if (FAILED(hr)) return;
177
178     load_stream((IUnknown*)reader, metadata_unknown, sizeof(metadata_unknown));
179
180     hr = IWICMetadataReader_GetEnumerator(reader, &enumerator);
181     ok(hr == S_OK, "GetEnumerator failed, hr=%x\n", hr);
182
183     if (SUCCEEDED(hr))
184     {
185         PropVariantInit(&schema);
186         PropVariantInit(&id);
187         PropVariantInit(&value);
188
189         hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
190         ok(hr == S_OK, "Next failed, hr=%x\n", hr);
191         ok(items_returned == 1, "unexpected item count %i\n", items_returned);
192
193         if (hr == S_OK && items_returned == 1)
194         {
195             ok(schema.vt == VT_EMPTY, "unexpected vt: %i\n", schema.vt);
196             ok(id.vt == VT_EMPTY, "unexpected vt: %i\n", id.vt);
197             expect_blob(value, metadata_unknown, sizeof(metadata_unknown));
198
199             PropVariantClear(&schema);
200             PropVariantClear(&id);
201             PropVariantClear(&value);
202         }
203
204         hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
205         ok(hr == S_FALSE, "Next failed, hr=%x\n", hr);
206         ok(items_returned == 0, "unexpected item count %i\n", items_returned);
207
208         IWICEnumMetadataItem_Release(enumerator);
209     }
210
211     hr = IWICMetadataReader_QueryInterface(reader, &IID_IWICMetadataBlockReader, (void**)&blockreader);
212     ok(hr == E_NOINTERFACE, "QueryInterface failed, hr=%x\n", hr);
213
214     if (SUCCEEDED(hr))
215         IWICMetadataBlockReader_Release(blockreader);
216
217     IWICMetadataReader_Release(reader);
218 }
219
220 static void test_metadata_tEXt(void)
221 {
222     HRESULT hr;
223     IWICMetadataReader *reader;
224     IWICEnumMetadataItem *enumerator;
225     PROPVARIANT schema, id, value;
226     ULONG items_returned, count;
227     GUID format;
228
229     PropVariantInit(&schema);
230     PropVariantInit(&id);
231     PropVariantInit(&value);
232
233     hr = CoCreateInstance(&CLSID_WICPngTextMetadataReader, NULL, CLSCTX_INPROC_SERVER,
234         &IID_IWICMetadataReader, (void**)&reader);
235     todo_wine ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
236     if (FAILED(hr)) return;
237
238     hr = IWICMetadataReader_GetCount(reader, NULL);
239     ok(hr == E_INVALIDARG, "GetCount failed, hr=%x\n", hr);
240
241     hr = IWICMetadataReader_GetCount(reader, &count);
242     ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
243     ok(count == 0, "unexpected count %i\n", count);
244
245     load_stream((IUnknown*)reader, metadata_tEXt, sizeof(metadata_tEXt));
246
247     hr = IWICMetadataReader_GetCount(reader, &count);
248     ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
249     ok(count == 1, "unexpected count %i\n", count);
250
251     hr = IWICMetadataReader_GetEnumerator(reader, NULL);
252     ok(hr == E_INVALIDARG, "GetEnumerator failed, hr=%x\n", hr);
253
254     hr = IWICMetadataReader_GetEnumerator(reader, &enumerator);
255     ok(hr == S_OK, "GetEnumerator failed, hr=%x\n", hr);
256
257     if (SUCCEEDED(hr))
258     {
259         hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
260         ok(hr == S_OK, "Next failed, hr=%x\n", hr);
261         ok(items_returned == 1, "unexpected item count %i\n", items_returned);
262
263         if (hr == S_OK && items_returned == 1)
264         {
265             ok(schema.vt == VT_EMPTY, "unexpected vt: %i\n", schema.vt);
266             ok(id.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt);
267             ok(!strcmp(U(id).pszVal, "winetest"), "unexpected id: %s\n", U(id).pszVal);
268             ok(value.vt == VT_LPSTR, "unexpected vt: %i\n", value.vt);
269             ok(!strcmp(U(value).pszVal, "value"), "unexpected value: %s\n", U(value).pszVal);
270
271             PropVariantClear(&schema);
272             PropVariantClear(&id);
273             PropVariantClear(&value);
274         }
275
276         hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
277         ok(hr == S_FALSE, "Next failed, hr=%x\n", hr);
278         ok(items_returned == 0, "unexpected item count %i\n", items_returned);
279
280         IWICEnumMetadataItem_Release(enumerator);
281     }
282
283     hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
284     ok(hr == S_OK, "GetMetadataFormat failed, hr=%x\n", hr);
285     ok(IsEqualGUID(&format, &GUID_MetadataFormatChunktEXt), "unexpected format %s\n", debugstr_guid(&format));
286
287     hr = IWICMetadataReader_GetMetadataFormat(reader, NULL);
288     ok(hr == E_INVALIDARG, "GetMetadataFormat failed, hr=%x\n", hr);
289
290     id.vt = VT_LPSTR;
291     U(id).pszVal = CoTaskMemAlloc(strlen("winetest") + 1);
292     strcpy(U(id).pszVal, "winetest");
293
294     hr = IWICMetadataReader_GetValue(reader, NULL, &id, NULL);
295     ok(hr == S_OK, "GetValue failed, hr=%x\n", hr);
296
297     hr = IWICMetadataReader_GetValue(reader, &schema, NULL, &value);
298     ok(hr == E_INVALIDARG, "GetValue failed, hr=%x\n", hr);
299
300     hr = IWICMetadataReader_GetValue(reader, &schema, &id, &value);
301     ok(hr == S_OK, "GetValue failed, hr=%x\n", hr);
302     ok(value.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt);
303     ok(!strcmp(U(value).pszVal, "value"), "unexpected value: %s\n", U(value).pszVal);
304     PropVariantClear(&value);
305
306     strcpy(U(id).pszVal, "test");
307
308     hr = IWICMetadataReader_GetValue(reader, &schema, &id, &value);
309     ok(hr == WINCODEC_ERR_PROPERTYNOTFOUND, "GetValue failed, hr=%x\n", hr);
310
311     PropVariantClear(&id);
312
313     hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, NULL, NULL);
314     ok(hr == S_OK, "GetValueByIndex failed, hr=%x\n", hr);
315
316     hr = IWICMetadataReader_GetValueByIndex(reader, 0, &schema, NULL, NULL);
317     ok(hr == S_OK, "GetValueByIndex failed, hr=%x\n", hr);
318     ok(schema.vt == VT_EMPTY, "unexpected vt: %i\n", schema.vt);
319
320     hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, &id, NULL);
321     ok(hr == S_OK, "GetValueByIndex failed, hr=%x\n", hr);
322     ok(id.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt);
323     ok(!strcmp(U(id).pszVal, "winetest"), "unexpected id: %s\n", U(id).pszVal);
324     PropVariantClear(&id);
325
326     hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, NULL, &value);
327     ok(hr == S_OK, "GetValueByIndex failed, hr=%x\n", hr);
328     ok(value.vt == VT_LPSTR, "unexpected vt: %i\n", value.vt);
329     ok(!strcmp(U(value).pszVal, "value"), "unexpected value: %s\n", U(value).pszVal);
330     PropVariantClear(&value);
331
332     hr = IWICMetadataReader_GetValueByIndex(reader, 1, NULL, NULL, NULL);
333     ok(hr == E_INVALIDARG, "GetValueByIndex failed, hr=%x\n", hr);
334
335     IWICMetadataReader_Release(reader);
336 }
337
338 static void test_metadata_IFD(void)
339 {
340     static const struct test_data
341     {
342         ULONG type, id;
343         LONGLONG value;
344     } td[6] =
345     {
346         { VT_UI2, 0xfe, 1 },
347         { VT_UI4, 0x100, 222 },
348         { VT_UI4, 0x101, 333 },
349         { VT_UI2, 0x102, 24 },
350         { VT_UI4, 0x103, 32773 },
351         { VT_UI8, 0x11a,  ((LONGLONG)3 << 32) | 900 }
352     };
353     HRESULT hr;
354     IWICMetadataReader *reader;
355     IWICMetadataBlockReader *blockreader;
356     IWICEnumMetadataItem *enumerator;
357     PROPVARIANT schema, id, value;
358     ULONG items_returned, count, i;
359     GUID format;
360
361     PropVariantInit(&schema);
362     PropVariantInit(&id);
363     PropVariantInit(&value);
364
365     hr = CoCreateInstance(&CLSID_WICIfdMetadataReader, NULL, CLSCTX_INPROC_SERVER,
366         &IID_IWICMetadataReader, (void**)&reader);
367     ok(hr == S_OK, "CoCreateInstance error %#x\n", hr);
368
369     hr = IWICMetadataReader_GetCount(reader, NULL);
370     ok(hr == E_INVALIDARG, "GetCount error %#x\n", hr);
371
372     hr = IWICMetadataReader_GetCount(reader, &count);
373     ok(hr == S_OK, "GetCount error %#x\n", hr);
374     ok(count == 0, "unexpected count %u\n", count);
375
376     load_stream((IUnknown*)reader, (const char *)&IFD_data, sizeof(IFD_data));
377
378     hr = IWICMetadataReader_GetCount(reader, &count);
379     ok(hr == S_OK, "GetCount error %#x\n", hr);
380 todo_wine
381     ok(count == 6, "unexpected count %u\n", count);
382
383     hr = IWICMetadataReader_GetEnumerator(reader, NULL);
384     ok(hr == E_INVALIDARG, "GetEnumerator error %#x\n", hr);
385
386     hr = IWICMetadataReader_GetEnumerator(reader, &enumerator);
387     ok(hr == S_OK, "GetEnumerator error %#x\n", hr);
388
389     for (i = 0; i < count; i++)
390     {
391         hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
392         ok(hr == S_OK, "Next error %#x\n", hr);
393         ok(items_returned == 1, "unexpected item count %u\n", items_returned);
394
395         ok(schema.vt == VT_EMPTY, "%u: unexpected vt: %u\n", i, schema.vt);
396         ok(id.vt == VT_UI2, "%u: unexpected vt: %u\n", i, id.vt);
397         ok(U(id).uiVal == td[i].id, "%u: unexpected id: %#x\n", i, U(id).uiVal);
398         ok(value.vt == td[i].type, "%u: unexpected vt: %u\n", i, value.vt);
399         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);
400
401         PropVariantClear(&schema);
402         PropVariantClear(&id);
403         PropVariantClear(&value);
404     }
405
406     hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
407     ok(hr == S_FALSE, "Next should fail\n");
408     ok(items_returned == 0, "unexpected item count %u\n", items_returned);
409
410     IWICEnumMetadataItem_Release(enumerator);
411
412     hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
413 todo_wine
414     ok(hr == S_OK, "GetMetadataFormat error %#x\n", hr);
415 todo_wine
416     ok(IsEqualGUID(&format, &GUID_MetadataFormatIfd), "unexpected format %s\n", debugstr_guid(&format));
417
418     hr = IWICMetadataReader_GetMetadataFormat(reader, NULL);
419     ok(hr == E_INVALIDARG, "GetMetadataFormat should fail\n");
420
421     hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, NULL, NULL);
422 todo_wine
423     ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
424     if (FAILED(hr))
425     {
426         IWICMetadataReader_Release(reader);
427         return;
428     }
429
430     hr = IWICMetadataReader_GetValueByIndex(reader, count - 1, NULL, NULL, NULL);
431     ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
432
433     hr = IWICMetadataReader_GetValueByIndex(reader, 0, &schema, NULL, NULL);
434     ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
435     ok(schema.vt == VT_EMPTY, "unexpected vt: %u\n", schema.vt);
436
437     hr = IWICMetadataReader_GetValueByIndex(reader, count - 1, &schema, NULL, NULL);
438     ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
439     ok(schema.vt == VT_EMPTY, "unexpected vt: %u\n", schema.vt);
440
441     hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, &id, NULL);
442     ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
443     ok(id.vt == VT_UI2, "unexpected vt: %u\n", id.vt);
444     ok(U(id).uiVal == 0xfe, "unexpected id: %#x\n", U(id).uiVal);
445     PropVariantClear(&id);
446
447     hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, NULL, &value);
448     ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
449     ok(value.vt == VT_UI2, "unexpected vt: %u\n", value.vt);
450     ok(U(value).ulVal == 1, "unexpected id: %u\n", U(value).ulVal);
451     PropVariantClear(&value);
452
453     hr = IWICMetadataReader_GetValueByIndex(reader, count, &schema, NULL, NULL);
454     ok(hr == E_INVALIDARG, "GetValueByIndex should fail\n");
455
456     hr = IWICMetadataReader_QueryInterface(reader, &IID_IWICMetadataBlockReader, (void**)&blockreader);
457     ok(hr == E_NOINTERFACE, "QueryInterface failed, hr=%x\n", hr);
458
459     if (SUCCEEDED(hr))
460         IWICMetadataBlockReader_Release(blockreader);
461
462     IWICMetadataReader_Release(reader);
463 }
464
465 static void test_metadata_Exif(void)
466 {
467     HRESULT hr;
468     IWICMetadataReader *reader;
469     IWICMetadataBlockReader *blockreader;
470     UINT count=0;
471
472     hr = CoCreateInstance(&CLSID_WICExifMetadataReader, NULL, CLSCTX_INPROC_SERVER,
473         &IID_IWICMetadataReader, (void**)&reader);
474     todo_wine ok(hr == S_OK, "CoCreateInstance error %#x\n", hr);
475     if (FAILED(hr)) return;
476
477     hr = IWICMetadataReader_GetCount(reader, NULL);
478     ok(hr == E_INVALIDARG, "GetCount error %#x\n", hr);
479
480     hr = IWICMetadataReader_GetCount(reader, &count);
481     ok(hr == S_OK, "GetCount error %#x\n", hr);
482     ok(count == 0, "unexpected count %u\n", count);
483
484     hr = IWICMetadataReader_QueryInterface(reader, &IID_IWICMetadataBlockReader, (void**)&blockreader);
485     ok(hr == E_NOINTERFACE, "QueryInterface failed, hr=%x\n", hr);
486
487     if (SUCCEEDED(hr))
488         IWICMetadataBlockReader_Release(blockreader);
489
490     IWICMetadataReader_Release(reader);
491 }
492
493 static void test_create_reader(void)
494 {
495     HRESULT hr;
496     IWICComponentFactory *factory;
497     IStream *stream;
498     IWICMetadataReader *reader;
499     UINT count=0;
500     GUID format;
501
502     hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
503         &IID_IWICComponentFactory, (void**)&factory);
504     ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
505
506     stream = create_stream(metadata_tEXt, sizeof(metadata_tEXt));
507
508     hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
509         &GUID_ContainerFormatPng, NULL, WICPersistOptionsDefault,
510         stream, &reader);
511 todo_wine
512     ok(hr == S_OK, "CreateMetadataReaderFromContainer failed, hr=%x\n", hr);
513     if (FAILED(hr)) return;
514
515     if (SUCCEEDED(hr))
516     {
517         hr = IWICMetadataReader_GetCount(reader, &count);
518         ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
519         ok(count == 1, "unexpected count %i\n", count);
520
521         hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
522         ok(hr == S_OK, "GetMetadataFormat failed, hr=%x\n", hr);
523         ok(IsEqualGUID(&format, &GUID_MetadataFormatChunktEXt), "unexpected format %s\n", debugstr_guid(&format));
524
525         IWICMetadataReader_Release(reader);
526     }
527
528     hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
529         &GUID_ContainerFormatWmp, NULL, WICPersistOptionsDefault,
530         stream, &reader);
531     ok(hr == S_OK, "CreateMetadataReaderFromContainer failed, hr=%x\n", hr);
532
533     if (SUCCEEDED(hr))
534     {
535         hr = IWICMetadataReader_GetCount(reader, &count);
536         ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
537         ok(count == 1, "unexpected count %i\n", count);
538
539         hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
540         ok(hr == S_OK, "GetMetadataFormat failed, hr=%x\n", hr);
541         ok(IsEqualGUID(&format, &GUID_MetadataFormatUnknown), "unexpected format %s\n", debugstr_guid(&format));
542
543         IWICMetadataReader_Release(reader);
544     }
545
546     IStream_Release(stream);
547
548     IWICComponentFactory_Release(factory);
549 }
550
551 static void test_metadata_png(void)
552 {
553     IStream *stream;
554     IWICBitmapDecoder *decoder;
555     IWICBitmapFrameDecode *frame;
556     IWICMetadataBlockReader *blockreader;
557     IWICMetadataReader *reader;
558     GUID containerformat;
559     HRESULT hr;
560     UINT count;
561
562     hr = CoCreateInstance(&CLSID_WICPngDecoder, NULL, CLSCTX_INPROC_SERVER,
563         &IID_IWICBitmapDecoder, (void**)&decoder);
564     ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
565
566     if (FAILED(hr)) return;
567
568     stream = create_stream(pngimage, sizeof(pngimage));
569
570     hr = IWICBitmapDecoder_Initialize(decoder, stream, WICDecodeMetadataCacheOnLoad);
571     ok(hr == S_OK, "Initialize failed, hr=%x\n", hr);
572
573     hr = IWICBitmapDecoder_QueryInterface(decoder, &IID_IWICMetadataBlockReader, (void**)&blockreader);
574     ok(hr == E_NOINTERFACE, "QueryInterface failed, hr=%x\n", hr);
575
576     hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
577     ok(hr == S_OK, "GetFrame failed, hr=%x\n", hr);
578
579     hr = IWICBitmapFrameDecode_QueryInterface(frame, &IID_IWICMetadataBlockReader, (void**)&blockreader);
580     ok(hr == S_OK, "QueryInterface failed, hr=%x\n", hr);
581
582     if (SUCCEEDED(hr))
583     {
584         hr = IWICMetadataBlockReader_GetContainerFormat(blockreader, NULL);
585         ok(hr == E_INVALIDARG, "GetContainerFormat failed, hr=%x\n", hr);
586
587         hr = IWICMetadataBlockReader_GetContainerFormat(blockreader, &containerformat);
588         ok(hr == S_OK, "GetContainerFormat failed, hr=%x\n", hr);
589         ok(IsEqualGUID(&containerformat, &GUID_ContainerFormatPng), "unexpected container format\n");
590
591         hr = IWICMetadataBlockReader_GetCount(blockreader, NULL);
592         todo_wine ok(hr == E_INVALIDARG, "GetCount failed, hr=%x\n", hr);
593
594         hr = IWICMetadataBlockReader_GetCount(blockreader, &count);
595         todo_wine ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
596         todo_wine ok(count == 1, "unexpected count %d\n", count);
597
598         if (0)
599         {
600             /* Crashes on Windows XP */
601             hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 0, NULL);
602             ok(hr == E_INVALIDARG, "GetReaderByIndex failed, hr=%x\n", hr);
603         }
604
605         hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 0, &reader);
606         todo_wine ok(hr == S_OK, "GetReaderByIndex failed, hr=%x\n", hr);
607
608         if (SUCCEEDED(hr))
609         {
610             hr = IWICMetadataReader_GetMetadataFormat(reader, &containerformat);
611             ok(IsEqualGUID(&containerformat, &GUID_MetadataFormatChunktIME) ||
612                broken(IsEqualGUID(&containerformat, &GUID_MetadataFormatUnknown)) /* Windows XP */,
613                "unexpected container format\n");
614
615             IWICMetadataReader_Release(reader);
616         }
617
618         hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 1, &reader);
619         todo_wine ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE, "GetReaderByIndex failed, hr=%x\n", hr);
620
621         IWICMetadataBlockReader_Release(blockreader);
622     }
623
624     IWICBitmapFrameDecode_Release(frame);
625
626     IWICBitmapDecoder_Release(decoder);
627
628     IWICStream_Release(stream);
629 }
630
631 START_TEST(metadata)
632 {
633     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
634
635     test_metadata_unknown();
636     test_metadata_tEXt();
637     test_metadata_IFD();
638     test_metadata_Exif();
639     test_create_reader();
640     test_metadata_png();
641
642     CoUninitialize();
643 }