windowscodecs: Add tests for IWICMetadataBlockReader on handler classes.
[wine/multimedia.git] / dlls / windowscodecs / tests / metadata.c
blob5cde4946c2439892b70b738d387df67e117c88e9
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 *debugstr_guid(REFIID riid)
96 static char buf[50];
98 if(!riid)
99 return "(null)";
101 sprintf(buf, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
102 riid->Data1, riid->Data2, riid->Data3, riid->Data4[0],
103 riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4],
104 riid->Data4[5], riid->Data4[6], riid->Data4[7]);
106 return buf;
109 static IStream *create_stream(const char *data, int data_size)
111 HRESULT hr;
112 IStream *stream;
113 HGLOBAL hdata;
114 void *locked_data;
116 hdata = GlobalAlloc(GMEM_MOVEABLE, data_size);
117 ok(hdata != 0, "GlobalAlloc failed\n");
118 if (!hdata) return NULL;
120 locked_data = GlobalLock(hdata);
121 memcpy(locked_data, data, data_size);
122 GlobalUnlock(hdata);
124 hr = CreateStreamOnHGlobal(hdata, TRUE, &stream);
125 ok(hr == S_OK, "CreateStreamOnHGlobal failed, hr=%x\n", hr);
127 return stream;
130 static void load_stream(IUnknown *reader, const char *data, int data_size)
132 HRESULT hr;
133 IWICPersistStream *persist;
134 IStream *stream;
136 stream = create_stream(data, data_size);
137 if (!stream)
138 return;
140 hr = IUnknown_QueryInterface(reader, &IID_IWICPersistStream, (void**)&persist);
141 ok(hr == S_OK, "QueryInterface failed, hr=%x\n", hr);
143 if (SUCCEEDED(hr))
145 hr = IWICPersistStream_LoadEx(persist, stream, NULL, WICPersistOptionsDefault);
146 ok(hr == S_OK, "LoadEx failed, hr=%x\n", hr);
148 IWICPersistStream_Release(persist);
151 IStream_Release(stream);
154 static void test_metadata_unknown(void)
156 HRESULT hr;
157 IWICMetadataReader *reader;
158 IWICEnumMetadataItem *enumerator;
159 IWICMetadataBlockReader *blockreader;
160 PROPVARIANT schema, id, value;
161 ULONG items_returned;
163 hr = CoCreateInstance(&CLSID_WICUnknownMetadataReader, NULL, CLSCTX_INPROC_SERVER,
164 &IID_IWICMetadataReader, (void**)&reader);
165 ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
166 if (FAILED(hr)) return;
168 load_stream((IUnknown*)reader, metadata_unknown, sizeof(metadata_unknown));
170 hr = IWICMetadataReader_GetEnumerator(reader, &enumerator);
171 ok(hr == S_OK, "GetEnumerator failed, hr=%x\n", hr);
173 if (SUCCEEDED(hr))
175 PropVariantInit(&schema);
176 PropVariantInit(&id);
177 PropVariantInit(&value);
179 hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
180 ok(hr == S_OK, "Next failed, hr=%x\n", hr);
181 ok(items_returned == 1, "unexpected item count %i\n", items_returned);
183 if (hr == S_OK && items_returned == 1)
185 ok(schema.vt == VT_EMPTY, "unexpected vt: %i\n", schema.vt);
186 ok(id.vt == VT_EMPTY, "unexpected vt: %i\n", id.vt);
187 expect_blob(value, metadata_unknown, sizeof(metadata_unknown));
189 PropVariantClear(&schema);
190 PropVariantClear(&id);
191 PropVariantClear(&value);
194 hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
195 ok(hr == S_FALSE, "Next failed, hr=%x\n", hr);
196 ok(items_returned == 0, "unexpected item count %i\n", items_returned);
198 IWICEnumMetadataItem_Release(enumerator);
201 hr = IWICMetadataReader_QueryInterface(reader, &IID_IWICMetadataBlockReader, (void**)&blockreader);
202 todo_wine ok(hr == E_NOINTERFACE, "QueryInterface failed, hr=%x\n", hr);
204 if (SUCCEEDED(hr))
205 IWICMetadataBlockReader_Release(blockreader);
207 IWICMetadataReader_Release(reader);
210 static void test_metadata_tEXt(void)
212 HRESULT hr;
213 IWICMetadataReader *reader;
214 IWICEnumMetadataItem *enumerator;
215 PROPVARIANT schema, id, value;
216 ULONG items_returned, count;
217 GUID format;
219 PropVariantInit(&schema);
220 PropVariantInit(&id);
221 PropVariantInit(&value);
223 hr = CoCreateInstance(&CLSID_WICPngTextMetadataReader, NULL, CLSCTX_INPROC_SERVER,
224 &IID_IWICMetadataReader, (void**)&reader);
225 todo_wine ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
226 if (FAILED(hr)) return;
228 hr = IWICMetadataReader_GetCount(reader, NULL);
229 ok(hr == E_INVALIDARG, "GetCount failed, hr=%x\n", hr);
231 hr = IWICMetadataReader_GetCount(reader, &count);
232 ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
233 ok(count == 0, "unexpected count %i\n", count);
235 load_stream((IUnknown*)reader, metadata_tEXt, sizeof(metadata_tEXt));
237 hr = IWICMetadataReader_GetCount(reader, &count);
238 ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
239 ok(count == 1, "unexpected count %i\n", count);
241 hr = IWICMetadataReader_GetEnumerator(reader, NULL);
242 ok(hr == E_INVALIDARG, "GetEnumerator failed, hr=%x\n", hr);
244 hr = IWICMetadataReader_GetEnumerator(reader, &enumerator);
245 ok(hr == S_OK, "GetEnumerator failed, hr=%x\n", hr);
247 if (SUCCEEDED(hr))
249 hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
250 ok(hr == S_OK, "Next failed, hr=%x\n", hr);
251 ok(items_returned == 1, "unexpected item count %i\n", items_returned);
253 if (hr == S_OK && items_returned == 1)
255 ok(schema.vt == VT_EMPTY, "unexpected vt: %i\n", schema.vt);
256 ok(id.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt);
257 ok(!strcmp(U(id).pszVal, "winetest"), "unexpected id: %s\n", U(id).pszVal);
258 ok(value.vt == VT_LPSTR, "unexpected vt: %i\n", value.vt);
259 ok(!strcmp(U(value).pszVal, "value"), "unexpected value: %s\n", U(value).pszVal);
261 PropVariantClear(&schema);
262 PropVariantClear(&id);
263 PropVariantClear(&value);
266 hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
267 ok(hr == S_FALSE, "Next failed, hr=%x\n", hr);
268 ok(items_returned == 0, "unexpected item count %i\n", items_returned);
270 IWICEnumMetadataItem_Release(enumerator);
273 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
274 ok(hr == S_OK, "GetMetadataFormat failed, hr=%x\n", hr);
275 ok(IsEqualGUID(&format, &GUID_MetadataFormatChunktEXt), "unexpected format %s\n", debugstr_guid(&format));
277 hr = IWICMetadataReader_GetMetadataFormat(reader, NULL);
278 ok(hr == E_INVALIDARG, "GetMetadataFormat failed, hr=%x\n", hr);
280 id.vt = VT_LPSTR;
281 U(id).pszVal = CoTaskMemAlloc(strlen("winetest") + 1);
282 strcpy(U(id).pszVal, "winetest");
284 hr = IWICMetadataReader_GetValue(reader, NULL, &id, NULL);
285 ok(hr == S_OK, "GetValue failed, hr=%x\n", hr);
287 hr = IWICMetadataReader_GetValue(reader, &schema, NULL, &value);
288 ok(hr == E_INVALIDARG, "GetValue failed, hr=%x\n", hr);
290 hr = IWICMetadataReader_GetValue(reader, &schema, &id, &value);
291 ok(hr == S_OK, "GetValue failed, hr=%x\n", hr);
292 ok(value.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt);
293 ok(!strcmp(U(value).pszVal, "value"), "unexpected value: %s\n", U(value).pszVal);
294 PropVariantClear(&value);
296 strcpy(U(id).pszVal, "test");
298 hr = IWICMetadataReader_GetValue(reader, &schema, &id, &value);
299 ok(hr == WINCODEC_ERR_PROPERTYNOTFOUND, "GetValue failed, hr=%x\n", hr);
301 PropVariantClear(&id);
303 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, NULL, NULL);
304 ok(hr == S_OK, "GetValueByIndex failed, hr=%x\n", hr);
306 hr = IWICMetadataReader_GetValueByIndex(reader, 0, &schema, NULL, NULL);
307 ok(hr == S_OK, "GetValueByIndex failed, hr=%x\n", hr);
308 ok(schema.vt == VT_EMPTY, "unexpected vt: %i\n", schema.vt);
310 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, &id, NULL);
311 ok(hr == S_OK, "GetValueByIndex failed, hr=%x\n", hr);
312 ok(id.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt);
313 ok(!strcmp(U(id).pszVal, "winetest"), "unexpected id: %s\n", U(id).pszVal);
314 PropVariantClear(&id);
316 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, NULL, &value);
317 ok(hr == S_OK, "GetValueByIndex failed, hr=%x\n", hr);
318 ok(value.vt == VT_LPSTR, "unexpected vt: %i\n", value.vt);
319 ok(!strcmp(U(value).pszVal, "value"), "unexpected value: %s\n", U(value).pszVal);
320 PropVariantClear(&value);
322 hr = IWICMetadataReader_GetValueByIndex(reader, 1, NULL, NULL, NULL);
323 ok(hr == E_INVALIDARG, "GetValueByIndex failed, hr=%x\n", hr);
325 IWICMetadataReader_Release(reader);
328 static void test_metadata_IFD(void)
330 static const struct test_data
332 ULONG type, id;
333 LONGLONG value;
334 } td[6] =
336 { VT_UI2, 0xfe, 1 },
337 { VT_UI4, 0x100, 222 },
338 { VT_UI4, 0x101, 333 },
339 { VT_UI2, 0x102, 24 },
340 { VT_UI4, 0x103, 32773 },
341 { VT_UI8, 0x11a, ((LONGLONG)3 << 32) | 900 }
343 HRESULT hr;
344 IWICMetadataReader *reader;
345 IWICMetadataBlockReader *blockreader;
346 IWICEnumMetadataItem *enumerator;
347 PROPVARIANT schema, id, value;
348 ULONG items_returned, count, i;
349 GUID format;
351 PropVariantInit(&schema);
352 PropVariantInit(&id);
353 PropVariantInit(&value);
355 hr = CoCreateInstance(&CLSID_WICIfdMetadataReader, NULL, CLSCTX_INPROC_SERVER,
356 &IID_IWICMetadataReader, (void**)&reader);
357 todo_wine ok(hr == S_OK, "CoCreateInstance error %#x\n", hr);
358 if (FAILED(hr)) return;
360 hr = IWICMetadataReader_GetCount(reader, NULL);
361 ok(hr == E_INVALIDARG, "GetCount error %#x\n", hr);
363 hr = IWICMetadataReader_GetCount(reader, &count);
364 ok(hr == S_OK, "GetCount error %#x\n", hr);
365 ok(count == 0, "unexpected count %u\n", count);
367 load_stream((IUnknown*)reader, (const char *)&IFD_data, sizeof(IFD_data));
369 hr = IWICMetadataReader_GetCount(reader, &count);
370 ok(hr == S_OK, "GetCount error %#x\n", hr);
371 ok(count == 6, "unexpected count %u\n", count);
373 hr = IWICMetadataReader_GetEnumerator(reader, NULL);
374 ok(hr == E_INVALIDARG, "GetEnumerator error %#x\n", hr);
376 hr = IWICMetadataReader_GetEnumerator(reader, &enumerator);
377 ok(hr == S_OK, "GetEnumerator error %#x\n", hr);
379 for (i = 0; i < count; i++)
381 hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
382 ok(hr == S_OK, "Next error %#x\n", hr);
383 ok(items_returned == 1, "unexpected item count %u\n", items_returned);
385 ok(schema.vt == VT_EMPTY, "%u: unexpected vt: %u\n", i, schema.vt);
386 ok(id.vt == VT_UI2, "%u: unexpected vt: %u\n", i, id.vt);
387 ok(U(id).uiVal == td[i].id, "%u: unexpected id: %#x\n", i, U(id).uiVal);
388 ok(value.vt == td[i].type, "%u: unexpected vt: %u\n", i, value.vt);
389 ok(U(value).uhVal.QuadPart == td[i].value, "%u: unexpected id: %d/%d\n", i, U(value).uhVal.LowPart, U(value).uhVal.HighPart);
391 PropVariantClear(&schema);
392 PropVariantClear(&id);
393 PropVariantClear(&value);
396 hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
397 ok(hr == S_FALSE, "Next should fail\n");
398 ok(items_returned == 0, "unexpected item count %u\n", items_returned);
400 IWICEnumMetadataItem_Release(enumerator);
402 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
403 ok(hr == S_OK, "GetMetadataFormat error %#x\n", hr);
404 ok(IsEqualGUID(&format, &GUID_MetadataFormatIfd), "unexpected format %s\n", debugstr_guid(&format));
406 hr = IWICMetadataReader_GetMetadataFormat(reader, NULL);
407 ok(hr == E_INVALIDARG, "GetMetadataFormat should fail\n");
409 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, NULL, NULL);
410 ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
412 hr = IWICMetadataReader_GetValueByIndex(reader, count - 1, NULL, NULL, NULL);
413 ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
415 hr = IWICMetadataReader_GetValueByIndex(reader, 0, &schema, NULL, NULL);
416 ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
417 ok(schema.vt == VT_EMPTY, "unexpected vt: %u\n", schema.vt);
419 hr = IWICMetadataReader_GetValueByIndex(reader, count - 1, &schema, NULL, NULL);
420 ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
421 ok(schema.vt == VT_EMPTY, "unexpected vt: %u\n", schema.vt);
423 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, &id, NULL);
424 ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
425 ok(id.vt == VT_UI2, "unexpected vt: %u\n", id.vt);
426 ok(U(id).uiVal == 0xfe, "unexpected id: %#x\n", U(id).uiVal);
427 PropVariantClear(&id);
429 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, NULL, &value);
430 ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
431 ok(value.vt == VT_UI2, "unexpected vt: %u\n", value.vt);
432 ok(U(value).ulVal == 1, "unexpected id: %u\n", U(value).ulVal);
433 PropVariantClear(&value);
435 hr = IWICMetadataReader_GetValueByIndex(reader, count, &schema, NULL, NULL);
436 ok(hr == E_INVALIDARG, "GetValueByIndex should fail\n");
438 hr = IWICMetadataReader_QueryInterface(reader, &IID_IWICMetadataBlockReader, (void**)&blockreader);
439 ok(hr == E_NOINTERFACE, "QueryInterface failed, hr=%x\n", hr);
441 if (SUCCEEDED(hr))
442 IWICMetadataBlockReader_Release(blockreader);
444 IWICMetadataReader_Release(reader);
447 static void test_metadata_Exif(void)
449 HRESULT hr;
450 IWICMetadataReader *reader;
451 IWICMetadataBlockReader *blockreader;
452 UINT count=0;
454 hr = CoCreateInstance(&CLSID_WICExifMetadataReader, NULL, CLSCTX_INPROC_SERVER,
455 &IID_IWICMetadataReader, (void**)&reader);
456 todo_wine ok(hr == S_OK, "CoCreateInstance error %#x\n", hr);
457 if (FAILED(hr)) return;
459 hr = IWICMetadataReader_GetCount(reader, NULL);
460 ok(hr == E_INVALIDARG, "GetCount error %#x\n", hr);
462 hr = IWICMetadataReader_GetCount(reader, &count);
463 ok(hr == S_OK, "GetCount error %#x\n", hr);
464 ok(count == 0, "unexpected count %u\n", count);
466 hr = IWICMetadataReader_QueryInterface(reader, &IID_IWICMetadataBlockReader, (void**)&blockreader);
467 ok(hr == E_NOINTERFACE, "QueryInterface failed, hr=%x\n", hr);
469 if (SUCCEEDED(hr))
470 IWICMetadataBlockReader_Release(blockreader);
472 IWICMetadataReader_Release(reader);
475 static void test_create_reader(void)
477 HRESULT hr;
478 IWICComponentFactory *factory;
479 IStream *stream;
480 IWICMetadataReader *reader;
481 UINT count=0;
482 GUID format;
484 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
485 &IID_IWICComponentFactory, (void**)&factory);
486 ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
488 stream = create_stream(metadata_tEXt, sizeof(metadata_tEXt));
490 hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
491 &GUID_ContainerFormatPng, NULL, WICPersistOptionsDefault,
492 stream, &reader);
493 todo_wine
494 ok(hr == S_OK, "CreateMetadataReaderFromContainer failed, hr=%x\n", hr);
495 if (FAILED(hr)) return;
497 if (SUCCEEDED(hr))
499 hr = IWICMetadataReader_GetCount(reader, &count);
500 ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
501 ok(count == 1, "unexpected count %i\n", count);
503 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
504 ok(hr == S_OK, "GetMetadataFormat failed, hr=%x\n", hr);
505 ok(IsEqualGUID(&format, &GUID_MetadataFormatChunktEXt), "unexpected format %s\n", debugstr_guid(&format));
507 IWICMetadataReader_Release(reader);
510 hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
511 &GUID_ContainerFormatWmp, NULL, WICPersistOptionsDefault,
512 stream, &reader);
513 ok(hr == S_OK, "CreateMetadataReaderFromContainer failed, hr=%x\n", hr);
515 if (SUCCEEDED(hr))
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);
521 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
522 ok(hr == S_OK, "GetMetadataFormat failed, hr=%x\n", hr);
523 ok(IsEqualGUID(&format, &GUID_MetadataFormatUnknown), "unexpected format %s\n", debugstr_guid(&format));
525 IWICMetadataReader_Release(reader);
528 IStream_Release(stream);
530 IWICComponentFactory_Release(factory);
533 START_TEST(metadata)
535 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
537 test_metadata_unknown();
538 test_metadata_tEXt();
539 test_metadata_IFD();
540 test_metadata_Exif();
541 test_create_reader();
543 CoUninitialize();