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 rational
;
71 { 0xfe, IFD_SHORT
, 1, 1 },
72 { 0x100, IFD_LONG
, 1, 222 },
73 { 0x101, IFD_LONG
, 1, 333 },
74 { 0x102, IFD_SHORT
, 1, 24 },
75 { 0x103, IFD_LONG
, 1, 32773 },
76 { 0x11a, IFD_RATIONAL
, 1, sizeof(USHORT
) + sizeof(struct IFD_entry
) * 6 + sizeof(ULONG
) }
83 static const char metadata_unknown
[] = "lalala";
85 static const char metadata_tEXt
[] = {
86 0,0,0,14, /* chunk length */
87 't','E','X','t', /* chunk type */
88 'w','i','n','e','t','e','s','t',0, /* keyword */
89 'v','a','l','u','e', /* text */
90 0x3f,0x64,0x19,0xf3 /* chunk CRC */
93 static const char *debugstr_guid(REFIID riid
)
100 sprintf(buf
, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
101 riid
->Data1
, riid
->Data2
, riid
->Data3
, riid
->Data4
[0],
102 riid
->Data4
[1], riid
->Data4
[2], riid
->Data4
[3], riid
->Data4
[4],
103 riid
->Data4
[5], riid
->Data4
[6], riid
->Data4
[7]);
108 static IStream
*create_stream(const char *data
, int data_size
)
115 hdata
= GlobalAlloc(GMEM_MOVEABLE
, data_size
);
116 ok(hdata
!= 0, "GlobalAlloc failed\n");
117 if (!hdata
) return NULL
;
119 locked_data
= GlobalLock(hdata
);
120 memcpy(locked_data
, data
, data_size
);
123 hr
= CreateStreamOnHGlobal(hdata
, TRUE
, &stream
);
124 ok(hr
== S_OK
, "CreateStreamOnHGlobal failed, hr=%x\n", hr
);
129 static void load_stream(IUnknown
*reader
, const char *data
, int data_size
)
132 IWICPersistStream
*persist
;
135 stream
= create_stream(data
, data_size
);
139 hr
= IUnknown_QueryInterface(reader
, &IID_IWICPersistStream
, (void**)&persist
);
140 ok(hr
== S_OK
, "QueryInterface failed, hr=%x\n", hr
);
144 hr
= IWICPersistStream_LoadEx(persist
, stream
, NULL
, WICPersistOptionsDefault
);
145 ok(hr
== S_OK
, "LoadEx failed, hr=%x\n", hr
);
147 IWICPersistStream_Release(persist
);
150 IStream_Release(stream
);
153 static void test_metadata_unknown(void)
156 IWICMetadataReader
*reader
;
157 IWICEnumMetadataItem
*enumerator
;
158 PROPVARIANT schema
, id
, value
;
159 ULONG items_returned
;
161 hr
= CoCreateInstance(&CLSID_WICUnknownMetadataReader
, NULL
, CLSCTX_INPROC_SERVER
,
162 &IID_IWICMetadataReader
, (void**)&reader
);
163 ok(hr
== S_OK
, "CoCreateInstance failed, hr=%x\n", hr
);
164 if (FAILED(hr
)) return;
166 load_stream((IUnknown
*)reader
, metadata_unknown
, sizeof(metadata_unknown
));
168 hr
= IWICMetadataReader_GetEnumerator(reader
, &enumerator
);
169 ok(hr
== S_OK
, "GetEnumerator failed, hr=%x\n", hr
);
173 PropVariantInit(&schema
);
174 PropVariantInit(&id
);
175 PropVariantInit(&value
);
177 hr
= IWICEnumMetadataItem_Next(enumerator
, 1, &schema
, &id
, &value
, &items_returned
);
178 ok(hr
== S_OK
, "Next failed, hr=%x\n", hr
);
179 ok(items_returned
== 1, "unexpected item count %i\n", items_returned
);
181 if (hr
== S_OK
&& items_returned
== 1)
183 ok(schema
.vt
== VT_EMPTY
, "unexpected vt: %i\n", schema
.vt
);
184 ok(id
.vt
== VT_EMPTY
, "unexpected vt: %i\n", id
.vt
);
185 expect_blob(value
, metadata_unknown
, sizeof(metadata_unknown
));
187 PropVariantClear(&schema
);
188 PropVariantClear(&id
);
189 PropVariantClear(&value
);
192 hr
= IWICEnumMetadataItem_Next(enumerator
, 1, &schema
, &id
, &value
, &items_returned
);
193 ok(hr
== S_FALSE
, "Next failed, hr=%x\n", hr
);
194 ok(items_returned
== 0, "unexpected item count %i\n", items_returned
);
196 IWICEnumMetadataItem_Release(enumerator
);
199 IWICMetadataReader_Release(reader
);
202 static void test_metadata_tEXt(void)
205 IWICMetadataReader
*reader
;
206 IWICEnumMetadataItem
*enumerator
;
207 PROPVARIANT schema
, id
, value
;
208 ULONG items_returned
, count
;
211 PropVariantInit(&schema
);
212 PropVariantInit(&id
);
213 PropVariantInit(&value
);
215 hr
= CoCreateInstance(&CLSID_WICPngTextMetadataReader
, NULL
, CLSCTX_INPROC_SERVER
,
216 &IID_IWICMetadataReader
, (void**)&reader
);
217 todo_wine
ok(hr
== S_OK
, "CoCreateInstance failed, hr=%x\n", hr
);
218 if (FAILED(hr
)) return;
220 hr
= IWICMetadataReader_GetCount(reader
, NULL
);
221 ok(hr
== E_INVALIDARG
, "GetCount failed, hr=%x\n", hr
);
223 hr
= IWICMetadataReader_GetCount(reader
, &count
);
224 ok(hr
== S_OK
, "GetCount failed, hr=%x\n", hr
);
225 ok(count
== 0, "unexpected count %i\n", count
);
227 load_stream((IUnknown
*)reader
, metadata_tEXt
, sizeof(metadata_tEXt
));
229 hr
= IWICMetadataReader_GetCount(reader
, &count
);
230 ok(hr
== S_OK
, "GetCount failed, hr=%x\n", hr
);
231 ok(count
== 1, "unexpected count %i\n", count
);
233 hr
= IWICMetadataReader_GetEnumerator(reader
, NULL
);
234 ok(hr
== E_INVALIDARG
, "GetEnumerator failed, hr=%x\n", hr
);
236 hr
= IWICMetadataReader_GetEnumerator(reader
, &enumerator
);
237 ok(hr
== S_OK
, "GetEnumerator failed, hr=%x\n", hr
);
241 hr
= IWICEnumMetadataItem_Next(enumerator
, 1, &schema
, &id
, &value
, &items_returned
);
242 ok(hr
== S_OK
, "Next failed, hr=%x\n", hr
);
243 ok(items_returned
== 1, "unexpected item count %i\n", items_returned
);
245 if (hr
== S_OK
&& items_returned
== 1)
247 ok(schema
.vt
== VT_EMPTY
, "unexpected vt: %i\n", schema
.vt
);
248 ok(id
.vt
== VT_LPSTR
, "unexpected vt: %i\n", id
.vt
);
249 ok(!strcmp(U(id
).pszVal
, "winetest"), "unexpected id: %s\n", U(id
).pszVal
);
250 ok(value
.vt
== VT_LPSTR
, "unexpected vt: %i\n", value
.vt
);
251 ok(!strcmp(U(value
).pszVal
, "value"), "unexpected value: %s\n", U(value
).pszVal
);
253 PropVariantClear(&schema
);
254 PropVariantClear(&id
);
255 PropVariantClear(&value
);
258 hr
= IWICEnumMetadataItem_Next(enumerator
, 1, &schema
, &id
, &value
, &items_returned
);
259 ok(hr
== S_FALSE
, "Next failed, hr=%x\n", hr
);
260 ok(items_returned
== 0, "unexpected item count %i\n", items_returned
);
262 IWICEnumMetadataItem_Release(enumerator
);
265 hr
= IWICMetadataReader_GetMetadataFormat(reader
, &format
);
266 ok(hr
== S_OK
, "GetMetadataFormat failed, hr=%x\n", hr
);
267 ok(IsEqualGUID(&format
, &GUID_MetadataFormatChunktEXt
), "unexpected format %s\n", debugstr_guid(&format
));
269 hr
= IWICMetadataReader_GetMetadataFormat(reader
, NULL
);
270 ok(hr
== E_INVALIDARG
, "GetMetadataFormat failed, hr=%x\n", hr
);
273 U(id
).pszVal
= CoTaskMemAlloc(strlen("winetest") + 1);
274 strcpy(U(id
).pszVal
, "winetest");
276 hr
= IWICMetadataReader_GetValue(reader
, NULL
, &id
, NULL
);
277 ok(hr
== S_OK
, "GetValue failed, hr=%x\n", hr
);
279 hr
= IWICMetadataReader_GetValue(reader
, &schema
, NULL
, &value
);
280 ok(hr
== E_INVALIDARG
, "GetValue failed, hr=%x\n", hr
);
282 hr
= IWICMetadataReader_GetValue(reader
, &schema
, &id
, &value
);
283 ok(hr
== S_OK
, "GetValue failed, hr=%x\n", hr
);
284 ok(value
.vt
== VT_LPSTR
, "unexpected vt: %i\n", id
.vt
);
285 ok(!strcmp(U(value
).pszVal
, "value"), "unexpected value: %s\n", U(value
).pszVal
);
286 PropVariantClear(&value
);
288 strcpy(U(id
).pszVal
, "test");
290 hr
= IWICMetadataReader_GetValue(reader
, &schema
, &id
, &value
);
291 ok(hr
== WINCODEC_ERR_PROPERTYNOTFOUND
, "GetValue failed, hr=%x\n", hr
);
293 PropVariantClear(&id
);
295 hr
= IWICMetadataReader_GetValueByIndex(reader
, 0, NULL
, NULL
, NULL
);
296 ok(hr
== S_OK
, "GetValueByIndex failed, hr=%x\n", hr
);
298 hr
= IWICMetadataReader_GetValueByIndex(reader
, 0, &schema
, NULL
, NULL
);
299 ok(hr
== S_OK
, "GetValueByIndex failed, hr=%x\n", hr
);
300 ok(schema
.vt
== VT_EMPTY
, "unexpected vt: %i\n", schema
.vt
);
302 hr
= IWICMetadataReader_GetValueByIndex(reader
, 0, NULL
, &id
, NULL
);
303 ok(hr
== S_OK
, "GetValueByIndex failed, hr=%x\n", hr
);
304 ok(id
.vt
== VT_LPSTR
, "unexpected vt: %i\n", id
.vt
);
305 ok(!strcmp(U(id
).pszVal
, "winetest"), "unexpected id: %s\n", U(id
).pszVal
);
306 PropVariantClear(&id
);
308 hr
= IWICMetadataReader_GetValueByIndex(reader
, 0, NULL
, NULL
, &value
);
309 ok(hr
== S_OK
, "GetValueByIndex failed, hr=%x\n", hr
);
310 ok(value
.vt
== VT_LPSTR
, "unexpected vt: %i\n", value
.vt
);
311 ok(!strcmp(U(value
).pszVal
, "value"), "unexpected value: %s\n", U(value
).pszVal
);
312 PropVariantClear(&value
);
314 hr
= IWICMetadataReader_GetValueByIndex(reader
, 1, NULL
, NULL
, NULL
);
315 ok(hr
== E_INVALIDARG
, "GetValueByIndex failed, hr=%x\n", hr
);
317 IWICMetadataReader_Release(reader
);
320 static void test_metadata_IFD(void)
322 static const struct test_data
324 ULONG type
, id
, value
;
328 { VT_UI4
, 0x100, 222 },
329 { VT_UI4
, 0x101, 333 },
330 { VT_UI2
, 0x102, 24 },
331 { VT_UI4
, 0x103, 32773 },
332 { VT_UI8
, 0x11a, 300 }
335 IWICMetadataReader
*reader
;
336 IWICEnumMetadataItem
*enumerator
;
337 PROPVARIANT schema
, id
, value
;
338 ULONG items_returned
, count
, i
;
341 PropVariantInit(&schema
);
342 PropVariantInit(&id
);
343 PropVariantInit(&value
);
345 hr
= CoCreateInstance(&CLSID_WICIfdMetadataReader
, NULL
, CLSCTX_INPROC_SERVER
,
346 &IID_IWICMetadataReader
, (void**)&reader
);
347 todo_wine
ok(hr
== S_OK
, "CoCreateInstance error %#x\n", hr
);
348 if (FAILED(hr
)) return;
350 hr
= IWICMetadataReader_GetCount(reader
, NULL
);
351 ok(hr
== E_INVALIDARG
, "GetCount error %#x\n", hr
);
353 hr
= IWICMetadataReader_GetCount(reader
, &count
);
354 ok(hr
== S_OK
, "GetCount error %#x\n", hr
);
355 ok(count
== 0, "unexpected count %u\n", count
);
357 load_stream((IUnknown
*)reader
, (const char *)&IFD_data
, sizeof(IFD_data
));
359 hr
= IWICMetadataReader_GetCount(reader
, &count
);
360 ok(hr
== S_OK
, "GetCount error %#x\n", hr
);
361 ok(count
== 6, "unexpected count %u\n", count
);
363 hr
= IWICMetadataReader_GetEnumerator(reader
, NULL
);
364 ok(hr
== E_INVALIDARG
, "GetEnumerator error %#x\n", hr
);
366 hr
= IWICMetadataReader_GetEnumerator(reader
, &enumerator
);
367 ok(hr
== S_OK
, "GetEnumerator error %#x\n", hr
);
369 for (i
= 0; i
< count
; i
++)
371 hr
= IWICEnumMetadataItem_Next(enumerator
, 1, &schema
, &id
, &value
, &items_returned
);
372 ok(hr
== S_OK
, "Next error %#x\n", hr
);
373 ok(items_returned
== 1, "unexpected item count %u\n", items_returned
);
375 ok(schema
.vt
== VT_EMPTY
, "%u: unexpected vt: %u\n", i
, schema
.vt
);
376 ok(id
.vt
== VT_UI2
, "%u: unexpected vt: %u\n", i
, id
.vt
);
377 ok(U(id
).uiVal
== td
[i
].id
, "%u: unexpected id: %#x\n", i
, U(id
).uiVal
);
378 ok(value
.vt
== td
[i
].type
, "%u: unexpected vt: %u\n", i
, value
.vt
);
379 ok(U(value
).ulVal
== td
[i
].value
, "%u: unexpected id: %u\n", i
, U(value
).ulVal
);
381 PropVariantClear(&schema
);
382 PropVariantClear(&id
);
383 PropVariantClear(&value
);
386 hr
= IWICEnumMetadataItem_Next(enumerator
, 1, &schema
, &id
, &value
, &items_returned
);
387 ok(hr
== S_FALSE
, "Next should fail\n");
388 ok(items_returned
== 0, "unexpected item count %u\n", items_returned
);
390 IWICEnumMetadataItem_Release(enumerator
);
392 hr
= IWICMetadataReader_GetMetadataFormat(reader
, &format
);
393 ok(hr
== S_OK
, "GetMetadataFormat error %#x\n", hr
);
394 ok(IsEqualGUID(&format
, &GUID_MetadataFormatIfd
), "unexpected format %s\n", debugstr_guid(&format
));
396 hr
= IWICMetadataReader_GetMetadataFormat(reader
, NULL
);
397 ok(hr
== E_INVALIDARG
, "GetMetadataFormat should fail\n");
399 hr
= IWICMetadataReader_GetValueByIndex(reader
, 0, NULL
, NULL
, NULL
);
400 ok(hr
== S_OK
, "GetValueByIndex error %#x\n", hr
);
402 hr
= IWICMetadataReader_GetValueByIndex(reader
, count
- 1, NULL
, NULL
, NULL
);
403 ok(hr
== S_OK
, "GetValueByIndex error %#x\n", hr
);
405 hr
= IWICMetadataReader_GetValueByIndex(reader
, 0, &schema
, NULL
, NULL
);
406 ok(hr
== S_OK
, "GetValueByIndex error %#x\n", hr
);
407 ok(schema
.vt
== VT_EMPTY
, "unexpected vt: %u\n", schema
.vt
);
409 hr
= IWICMetadataReader_GetValueByIndex(reader
, count
- 1, &schema
, NULL
, NULL
);
410 ok(hr
== S_OK
, "GetValueByIndex error %#x\n", hr
);
411 ok(schema
.vt
== VT_EMPTY
, "unexpected vt: %u\n", schema
.vt
);
413 hr
= IWICMetadataReader_GetValueByIndex(reader
, 0, NULL
, &id
, NULL
);
414 ok(hr
== S_OK
, "GetValueByIndex error %#x\n", hr
);
415 ok(id
.vt
== VT_UI2
, "unexpected vt: %u\n", id
.vt
);
416 ok(U(id
).uiVal
== 0xfe, "unexpected id: %#x\n", U(id
).uiVal
);
417 PropVariantClear(&id
);
419 hr
= IWICMetadataReader_GetValueByIndex(reader
, 0, NULL
, NULL
, &value
);
420 ok(hr
== S_OK
, "GetValueByIndex error %#x\n", hr
);
421 ok(value
.vt
== VT_UI2
, "unexpected vt: %u\n", value
.vt
);
422 ok(U(value
).ulVal
== 1, "unexpected id: %u\n", U(value
).ulVal
);
423 PropVariantClear(&value
);
425 hr
= IWICMetadataReader_GetValueByIndex(reader
, count
, &schema
, NULL
, NULL
);
426 ok(hr
== E_INVALIDARG
, "GetValueByIndex should fail\n");
428 IWICMetadataReader_Release(reader
);
431 static void test_create_reader(void)
434 IWICComponentFactory
*factory
;
436 IWICMetadataReader
*reader
;
440 hr
= CoCreateInstance(&CLSID_WICImagingFactory
, NULL
, CLSCTX_INPROC_SERVER
,
441 &IID_IWICComponentFactory
, (void**)&factory
);
442 todo_wine
ok(hr
== S_OK
, "CoCreateInstance failed, hr=%x\n", hr
);
443 if (FAILED(hr
)) return;
445 stream
= create_stream(metadata_tEXt
, sizeof(metadata_tEXt
));
447 hr
= IWICComponentFactory_CreateMetadataReaderFromContainer(factory
,
448 &GUID_ContainerFormatPng
, NULL
, WICPersistOptionsDefault
,
450 ok(hr
== S_OK
, "CreateMetadataReaderFromContainer failed, hr=%x\n", hr
);
454 hr
= IWICMetadataReader_GetCount(reader
, &count
);
455 ok(hr
== S_OK
, "GetCount failed, hr=%x\n", hr
);
456 ok(count
== 1, "unexpected count %i\n", count
);
458 hr
= IWICMetadataReader_GetMetadataFormat(reader
, &format
);
459 ok(hr
== S_OK
, "GetMetadataFormat failed, hr=%x\n", hr
);
460 ok(IsEqualGUID(&format
, &GUID_MetadataFormatChunktEXt
), "unexpected format %s\n", debugstr_guid(&format
));
462 IWICMetadataReader_Release(reader
);
465 hr
= IWICComponentFactory_CreateMetadataReaderFromContainer(factory
,
466 &GUID_ContainerFormatWmp
, NULL
, WICPersistOptionsDefault
,
468 ok(hr
== S_OK
, "CreateMetadataReaderFromContainer failed, hr=%x\n", hr
);
472 hr
= IWICMetadataReader_GetCount(reader
, &count
);
473 ok(hr
== S_OK
, "GetCount failed, hr=%x\n", hr
);
474 ok(count
== 1, "unexpected count %i\n", count
);
476 hr
= IWICMetadataReader_GetMetadataFormat(reader
, &format
);
477 ok(hr
== S_OK
, "GetMetadataFormat failed, hr=%x\n", hr
);
478 ok(IsEqualGUID(&format
, &GUID_MetadataFormatUnknown
), "unexpected format %s\n", debugstr_guid(&format
));
480 IWICMetadataReader_Release(reader
);
483 IStream_Release(stream
);
485 IWICComponentFactory_Release(factory
);
490 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
492 test_metadata_unknown();
493 test_metadata_tEXt();
495 test_create_reader();