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"); \
44 #define IFD_RATIONAL 5
63 USHORT number_of_entries
;
64 struct IFD_entry entry
[6];
66 struct IFD_rational xres
;
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
) }
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
)
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]);
109 static IStream
*create_stream(const char *data
, int data_size
)
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
);
124 hr
= CreateStreamOnHGlobal(hdata
, TRUE
, &stream
);
125 ok(hr
== S_OK
, "CreateStreamOnHGlobal failed, hr=%x\n", hr
);
130 static void load_stream(IUnknown
*reader
, const char *data
, int data_size
)
133 IWICPersistStream
*persist
;
136 stream
= create_stream(data
, data_size
);
140 hr
= IUnknown_QueryInterface(reader
, &IID_IWICPersistStream
, (void**)&persist
);
141 ok(hr
== S_OK
, "QueryInterface failed, hr=%x\n", 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)
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
);
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
);
205 IWICMetadataBlockReader_Release(blockreader
);
207 IWICMetadataReader_Release(reader
);
210 static void test_metadata_tEXt(void)
213 IWICMetadataReader
*reader
;
214 IWICEnumMetadataItem
*enumerator
;
215 PROPVARIANT schema
, id
, value
;
216 ULONG items_returned
, count
;
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
);
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
);
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
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 }
344 IWICMetadataReader
*reader
;
345 IWICMetadataBlockReader
*blockreader
;
346 IWICEnumMetadataItem
*enumerator
;
347 PROPVARIANT schema
, id
, value
;
348 ULONG items_returned
, count
, i
;
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
);
442 IWICMetadataBlockReader_Release(blockreader
);
444 IWICMetadataReader_Release(reader
);
447 static void test_metadata_Exif(void)
450 IWICMetadataReader
*reader
;
451 IWICMetadataBlockReader
*blockreader
;
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
);
470 IWICMetadataBlockReader_Release(blockreader
);
472 IWICMetadataReader_Release(reader
);
475 static void test_create_reader(void)
478 IWICComponentFactory
*factory
;
480 IWICMetadataReader
*reader
;
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
,
494 ok(hr
== S_OK
, "CreateMetadataReaderFromContainer failed, hr=%x\n", hr
);
495 if (FAILED(hr
)) return;
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
,
513 ok(hr
== S_OK
, "CreateMetadataReaderFromContainer failed, hr=%x\n", 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
);
535 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
537 test_metadata_unknown();
538 test_metadata_tEXt();
540 test_metadata_Exif();
541 test_create_reader();