ReactOS 0.4.15-dev-7788-g1ad9096
metadata.c
Go to the documentation of this file.
1/*
2 * Copyright 2011 Vincent Povirk for CodeWeavers
3 * Copyright 2012,2017 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#include <assert.h>
24
25#define COBJMACROS
26#ifdef __REACTOS__
27#define CONST_VTABLE
28#endif
29
30#include "windef.h"
31#include "objbase.h"
32#include "wincodec.h"
33#include "wincodecsdk.h"
34#include "propvarutil.h"
35#include "wine/test.h"
36
37#include "initguid.h"
38DEFINE_GUID(IID_MdbrUnknown, 0x00240e6f,0x3f23,0x4432,0xb0,0xcc,0x48,0xd5,0xbb,0xff,0x6c,0x36);
39
40#define expect_blob(propvar, data, length) do { \
41 ok((propvar).vt == VT_BLOB, "unexpected vt: %i\n", (propvar).vt); \
42 if ((propvar).vt == VT_BLOB) { \
43 ok(U(propvar).blob.cbSize == (length), "expected size %u, got %u\n", (ULONG)(length), U(propvar).blob.cbSize); \
44 if (U(propvar).blob.cbSize == (length)) { \
45 ok(!memcmp(U(propvar).blob.pBlobData, (data), (length)), "unexpected data\n"); \
46 } \
47 } \
48} while (0)
49
50#define IFD_BYTE 1
51#define IFD_ASCII 2
52#define IFD_SHORT 3
53#define IFD_LONG 4
54#define IFD_RATIONAL 5
55#define IFD_SBYTE 6
56#define IFD_UNDEFINED 7
57#define IFD_SSHORT 8
58#define IFD_SLONG 9
59#define IFD_SRATIONAL 10
60#define IFD_FLOAT 11
61#define IFD_DOUBLE 12
62#define IFD_IFD 13
63
64#include "pshpack2.h"
65struct IFD_entry
66{
67 SHORT id;
68 SHORT type;
70 LONG value;
71};
72
73struct IFD_rational
74{
77};
78
79static const struct ifd_data
80{
82 struct IFD_entry entry[40];
87 char string[14];
92} IFD_data =
93{
94 28,
95 {
96 { 0xfe, IFD_SHORT, 1, 1 }, /* NEWSUBFILETYPE */
97 { 0x100, IFD_LONG, 1, 222 }, /* IMAGEWIDTH */
98 { 0x101, IFD_LONG, 1, 333 }, /* IMAGELENGTH */
99 { 0x102, IFD_SHORT, 1, 24 }, /* BITSPERSAMPLE */
100 { 0x103, IFD_LONG, 1, 32773 }, /* COMPRESSION: packbits */
101 { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct ifd_data, xres) },
102 { 0xf001, IFD_BYTE, 1, 0x11223344 },
103 { 0xf002, IFD_BYTE, 4, 0x11223344 },
104 { 0xf003, IFD_SBYTE, 1, 0x11223344 },
105 { 0xf004, IFD_SSHORT, 1, 0x11223344 },
106 { 0xf005, IFD_SSHORT, 2, 0x11223344 },
107 { 0xf006, IFD_SLONG, 1, 0x11223344 },
108 { 0xf007, IFD_FLOAT, 1, 0x11223344 },
109 { 0xf008, IFD_DOUBLE, 1, FIELD_OFFSET(struct ifd_data, double_val) },
110 { 0xf009, IFD_SRATIONAL, 1, FIELD_OFFSET(struct ifd_data, srational_val) },
111 { 0xf00a, IFD_BYTE, 13, FIELD_OFFSET(struct ifd_data, string) },
112 { 0xf00b, IFD_SSHORT, 4, FIELD_OFFSET(struct ifd_data, short_val) },
113 { 0xf00c, IFD_SLONG, 2, FIELD_OFFSET(struct ifd_data, long_val) },
114 { 0xf00d, IFD_FLOAT, 2, FIELD_OFFSET(struct ifd_data, float_val) },
115 { 0xf00e, IFD_ASCII, 13, FIELD_OFFSET(struct ifd_data, string) },
116 { 0xf00f, IFD_ASCII, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 },
117 { 0xf010, IFD_UNDEFINED, 13, FIELD_OFFSET(struct ifd_data, string) },
118 { 0xf011, IFD_UNDEFINED, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 },
119 { 0xf012, IFD_BYTE, 0, 0x11223344 },
120 { 0xf013, IFD_SHORT, 0, 0x11223344 },
121 { 0xf014, IFD_LONG, 0, 0x11223344 },
122 { 0xf015, IFD_FLOAT, 0, 0x11223344 },
123 { 0xf016, IFD_SRATIONAL, 3, FIELD_OFFSET(struct ifd_data, rational) },
124 },
125 0,
126 { 900, 3 },
127 1234567890.0987654321,
128 { 0x1a2b3c4d, 0x5a6b7c8d },
129 "Hello World!",
130 { 0x0101, 0x0202, 0x0303, 0x0404 },
131 { 0x11223344, 0x55667788 },
132 { (FLOAT)1234.5678, (FLOAT)8765.4321 },
133 { { 0x01020304, 0x05060708 }, { 0x10203040, 0x50607080 }, { 0x11223344, 0x55667788 } },
135#include "poppack.h"
136
137static const char metadata_unknown[] = "lalala";
138
139static const char metadata_tEXt[] = {
140 0,0,0,14, /* chunk length */
141 't','E','X','t', /* chunk type */
142 'w','i','n','e','t','e','s','t',0, /* keyword */
143 'v','a','l','u','e', /* text */
144 0x3f,0x64,0x19,0xf3 /* chunk CRC */
145};
146
147static const char metadata_gAMA[] = {
148 0,0,0,4, /* chunk length */
149 'g','A','M','A', /* chunk type */
150 0,0,130,53, /* gamma */
151 0xff,0xff,0xff,0xff /* chunk CRC */
152};
153
154static const char metadata_cHRM[] = {
155 0,0,0,32, /* chunk length */
156 'c','H','R','M', /* chunk type */
157 0,0,122,38, 0,0,128,132, /* white point */
158 0,0,250,0, 0,0,128,232, /* red */
159 0,0,117,48, 0,0,234,96, /* green */
160 0,0,58,152, 0,0,23,112, /* blue */
161 0xff,0xff,0xff,0xff /* chunk CRC */
162};
163
164static const char pngimage[285] = {
1650x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
1660x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
1670xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
1680x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
1690x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
1700x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
1710xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
172};
173
174/* 1x1 pixel gif */
175static const char gifimage[35] = {
1760x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff,
1770xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,
1780x01,0x00,0x3b
179};
180
181/* 1x1 pixel gif, 2 frames; first frame is white, second is black */
182static const char animatedgif[] = {
183'G','I','F','8','9','a',0x01,0x00,0x01,0x00,0xA1,0x00,0x00,
1840x6F,0x6F,0x6F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
185/*0x21,0xFF,0x0B,'N','E','T','S','C','A','P','E','2','.','0',*/
1860x21,0xFF,0x0B,'A','N','I','M','E','X','T','S','1','.','0',
1870x03,0x01,0x05,0x00,0x00,
1880x21,0xFE,0x0C,'H','e','l','l','o',' ','W','o','r','l','d','!',0x00,
1890x21,0x01,0x0D,'a','n','i','m','a','t','i','o','n','.','g','i','f',0x00,
1900x21,0xF9,0x04,0x00,0x0A,0x00,0xFF,0x00,0x2C,
1910x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x81,
1920xDE,0xDE,0xDE,0x00,0x00,0x00,
1930x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x4C,0x01,0x00,
1940x21,0xFE,0x08,'i','m','a','g','e',' ','#','1',0x00,
1950x21,0x01,0x0C,'p','l','a','i','n','t','e','x','t',' ','#','1',0x00,
1960x21,0xF9,0x04,0x01,0x0A,0x00,0x01,0x00,0x2C,
1970x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x81,
1980x4D,0x4D,0x4D,0x00,0x00,0x00,
1990x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x44,0x01,0x00,
2000x21,0xFE,0x08,'i','m','a','g','e',' ','#','2',0x00,
2010x21,0x01,0x0C,'p','l','a','i','n','t','e','x','t',' ','#','2',0x00,0x3B
202};
203
204static IStream *create_stream(const char *data, int data_size)
205{
206 HRESULT hr;
208 HGLOBAL hdata;
209 void *locked_data;
210
211 hdata = GlobalAlloc(GMEM_MOVEABLE, data_size);
212 ok(hdata != 0, "GlobalAlloc failed\n");
213 if (!hdata) return NULL;
214
215 locked_data = GlobalLock(hdata);
216 memcpy(locked_data, data, data_size);
217 GlobalUnlock(hdata);
218
220 ok(hr == S_OK, "CreateStreamOnHGlobal failed, hr=%x\n", hr);
221
222 return stream;
223}
224
225static void load_stream(IUnknown *reader, const char *data, int data_size, DWORD persist_options)
226{
227 HRESULT hr;
228 IWICPersistStream *persist;
231 ULARGE_INTEGER cur_pos;
232
233 stream = create_stream(data, data_size);
234 if (!stream)
235 return;
236
237 hr = IUnknown_QueryInterface(reader, &IID_IWICPersistStream, (void**)&persist);
238 ok(hr == S_OK, "QueryInterface failed, hr=%x\n", hr);
239
240 if (SUCCEEDED(hr))
241 {
242 hr = IWICPersistStream_LoadEx(persist, stream, NULL, persist_options);
243 ok(hr == S_OK, "LoadEx failed, hr=%x\n", hr);
244
245 IWICPersistStream_Release(persist);
246 }
247
248 pos.QuadPart = 0;
249 hr = IStream_Seek(stream, pos, SEEK_CUR, &cur_pos);
250 ok(hr == S_OK, "IStream_Seek error %#x\n", hr);
251 /* IFD metadata reader doesn't rewind the stream to the start */
252 ok(cur_pos.QuadPart == 0 || cur_pos.QuadPart <= data_size,
253 "current stream pos is at %x/%x, data size %x\n", cur_pos.u.LowPart, cur_pos.u.HighPart, data_size);
254
255 IStream_Release(stream);
256}
257
258static void test_metadata_unknown(void)
259{
260 HRESULT hr;
262 IWICEnumMetadataItem *enumerator;
263 IWICMetadataBlockReader *blockreader;
264 PROPVARIANT schema, id, value;
265 ULONG items_returned;
266
267 hr = CoCreateInstance(&CLSID_WICUnknownMetadataReader, NULL, CLSCTX_INPROC_SERVER,
268 &IID_IWICMetadataReader, (void**)&reader);
269 ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
270 if (FAILED(hr)) return;
271
273
274 hr = IWICMetadataReader_GetEnumerator(reader, &enumerator);
275 ok(hr == S_OK, "GetEnumerator failed, hr=%x\n", hr);
276
277 if (SUCCEEDED(hr))
278 {
279 PropVariantInit(&schema);
280 PropVariantInit(&id);
281 PropVariantInit(&value);
282
283 hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
284 ok(hr == S_OK, "Next failed, hr=%x\n", hr);
285 ok(items_returned == 1, "unexpected item count %i\n", items_returned);
286
287 if (hr == S_OK && items_returned == 1)
288 {
289 ok(schema.vt == VT_EMPTY, "unexpected vt: %i\n", schema.vt);
290 ok(id.vt == VT_EMPTY, "unexpected vt: %i\n", id.vt);
292
294 PropVariantClear(&id);
296 }
297
298 hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
299 ok(hr == S_FALSE, "Next failed, hr=%x\n", hr);
300 ok(items_returned == 0, "unexpected item count %i\n", items_returned);
301
302 IWICEnumMetadataItem_Release(enumerator);
303 }
304
305 hr = IWICMetadataReader_QueryInterface(reader, &IID_IWICMetadataBlockReader, (void**)&blockreader);
306 ok(hr == E_NOINTERFACE, "QueryInterface failed, hr=%x\n", hr);
307
308 if (SUCCEEDED(hr))
309 IWICMetadataBlockReader_Release(blockreader);
310
311 IWICMetadataReader_Release(reader);
312}
313
314static void test_metadata_tEXt(void)
315{
316 HRESULT hr;
318 IWICEnumMetadataItem *enumerator;
319 PROPVARIANT schema, id, value;
320 ULONG items_returned, count;
321 GUID format;
322
323 PropVariantInit(&schema);
324 PropVariantInit(&id);
325 PropVariantInit(&value);
326
327 hr = CoCreateInstance(&CLSID_WICPngTextMetadataReader, NULL, CLSCTX_INPROC_SERVER,
328 &IID_IWICMetadataReader, (void**)&reader);
329 ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
330 if (FAILED(hr)) return;
331
332 hr = IWICMetadataReader_GetCount(reader, NULL);
333 ok(hr == E_INVALIDARG, "GetCount failed, hr=%x\n", hr);
334
335 hr = IWICMetadataReader_GetCount(reader, &count);
336 ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
337 ok(count == 0, "unexpected count %i\n", count);
338
340
341 hr = IWICMetadataReader_GetCount(reader, &count);
342 ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
343 ok(count == 1, "unexpected count %i\n", count);
344
345 hr = IWICMetadataReader_GetEnumerator(reader, NULL);
346 ok(hr == E_INVALIDARG, "GetEnumerator failed, hr=%x\n", hr);
347
348 hr = IWICMetadataReader_GetEnumerator(reader, &enumerator);
349 ok(hr == S_OK, "GetEnumerator failed, hr=%x\n", hr);
350
351 if (SUCCEEDED(hr))
352 {
353 hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
354 ok(hr == S_OK, "Next failed, hr=%x\n", hr);
355 ok(items_returned == 1, "unexpected item count %i\n", items_returned);
356
357 if (hr == S_OK && items_returned == 1)
358 {
359 ok(schema.vt == VT_EMPTY, "unexpected vt: %i\n", schema.vt);
360 ok(id.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt);
361 ok(!strcmp(U(id).pszVal, "winetest"), "unexpected id: %s\n", U(id).pszVal);
362 ok(value.vt == VT_LPSTR, "unexpected vt: %i\n", value.vt);
363 ok(!strcmp(U(value).pszVal, "value"), "unexpected value: %s\n", U(value).pszVal);
364
366 PropVariantClear(&id);
368 }
369
370 hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
371 ok(hr == S_FALSE, "Next failed, hr=%x\n", hr);
372 ok(items_returned == 0, "unexpected item count %i\n", items_returned);
373
374 IWICEnumMetadataItem_Release(enumerator);
375 }
376
377 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
378 ok(hr == S_OK, "GetMetadataFormat failed, hr=%x\n", hr);
379 ok(IsEqualGUID(&format, &GUID_MetadataFormatChunktEXt), "unexpected format %s\n", wine_dbgstr_guid(&format));
380
381 hr = IWICMetadataReader_GetMetadataFormat(reader, NULL);
382 ok(hr == E_INVALIDARG, "GetMetadataFormat failed, hr=%x\n", hr);
383
384 id.vt = VT_LPSTR;
385 U(id).pszVal = CoTaskMemAlloc(strlen("winetest") + 1);
386 strcpy(U(id).pszVal, "winetest");
387
388 hr = IWICMetadataReader_GetValue(reader, NULL, &id, NULL);
389 ok(hr == S_OK, "GetValue failed, hr=%x\n", hr);
390
391 hr = IWICMetadataReader_GetValue(reader, &schema, NULL, &value);
392 ok(hr == E_INVALIDARG, "GetValue failed, hr=%x\n", hr);
393
394 hr = IWICMetadataReader_GetValue(reader, &schema, &id, &value);
395 ok(hr == S_OK, "GetValue failed, hr=%x\n", hr);
396 ok(value.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt);
397 ok(!strcmp(U(value).pszVal, "value"), "unexpected value: %s\n", U(value).pszVal);
399
400 strcpy(U(id).pszVal, "test");
401
402 hr = IWICMetadataReader_GetValue(reader, &schema, &id, &value);
403 ok(hr == WINCODEC_ERR_PROPERTYNOTFOUND, "GetValue failed, hr=%x\n", hr);
404
405 PropVariantClear(&id);
406
407 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, NULL, NULL);
408 ok(hr == S_OK, "GetValueByIndex failed, hr=%x\n", hr);
409
410 hr = IWICMetadataReader_GetValueByIndex(reader, 0, &schema, NULL, NULL);
411 ok(hr == S_OK, "GetValueByIndex failed, hr=%x\n", hr);
412 ok(schema.vt == VT_EMPTY, "unexpected vt: %i\n", schema.vt);
413
414 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, &id, NULL);
415 ok(hr == S_OK, "GetValueByIndex failed, hr=%x\n", hr);
416 ok(id.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt);
417 ok(!strcmp(U(id).pszVal, "winetest"), "unexpected id: %s\n", U(id).pszVal);
418 PropVariantClear(&id);
419
420 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, NULL, &value);
421 ok(hr == S_OK, "GetValueByIndex failed, hr=%x\n", hr);
422 ok(value.vt == VT_LPSTR, "unexpected vt: %i\n", value.vt);
423 ok(!strcmp(U(value).pszVal, "value"), "unexpected value: %s\n", U(value).pszVal);
425
426 hr = IWICMetadataReader_GetValueByIndex(reader, 1, NULL, NULL, NULL);
427 ok(hr == E_INVALIDARG, "GetValueByIndex failed, hr=%x\n", hr);
428
429 IWICMetadataReader_Release(reader);
430}
431
432static void test_metadata_gAMA(void)
433{
434 HRESULT hr;
436 PROPVARIANT schema, id, value;
437 ULONG count;
438 GUID format;
439 static const WCHAR ImageGamma[] = {'I','m','a','g','e','G','a','m','m','a',0};
440
441 PropVariantInit(&schema);
442 PropVariantInit(&id);
443 PropVariantInit(&value);
444
445 hr = CoCreateInstance(&CLSID_WICPngGamaMetadataReader, NULL, CLSCTX_INPROC_SERVER,
446 &IID_IWICMetadataReader, (void**)&reader);
447 ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG) /*winxp*/, "CoCreateInstance failed, hr=%x\n", hr);
448 if (FAILED(hr)) return;
449
451
452 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
453 ok(hr == S_OK, "GetMetadataFormat failed, hr=%x\n", hr);
454 ok(IsEqualGUID(&format, &GUID_MetadataFormatChunkgAMA), "unexpected format %s\n", wine_dbgstr_guid(&format));
455
456 hr = IWICMetadataReader_GetCount(reader, &count);
457 ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
458 ok(count == 1, "unexpected count %i\n", count);
459
460 hr = IWICMetadataReader_GetValueByIndex(reader, 0, &schema, &id, &value);
461 ok(hr == S_OK, "GetValue failed, hr=%x\n", hr);
462
463 ok(schema.vt == VT_EMPTY, "unexpected vt: %i\n", schema.vt);
465
466 ok(id.vt == VT_LPWSTR, "unexpected vt: %i\n", id.vt);
467 ok(!lstrcmpW(U(id).pwszVal, ImageGamma), "unexpected value: %s\n", wine_dbgstr_w(U(id).pwszVal));
468 PropVariantClear(&id);
469
470 ok(value.vt == VT_UI4, "unexpected vt: %i\n", value.vt);
471 ok(U(value).ulVal == 33333, "unexpected value: %u\n", U(value).ulVal);
473
474 IWICMetadataReader_Release(reader);
475}
476
477static void test_metadata_cHRM(void)
478{
479 HRESULT hr;
481 PROPVARIANT schema, id, value;
482 ULONG count;
483 GUID format;
484 int i;
485 static const WCHAR expected_names[8][12] = {
486 {'W','h','i','t','e','P','o','i','n','t','X',0},
487 {'W','h','i','t','e','P','o','i','n','t','Y',0},
488 {'R','e','d','X',0},
489 {'R','e','d','Y',0},
490 {'G','r','e','e','n','X',0},
491 {'G','r','e','e','n','Y',0},
492 {'B','l','u','e','X',0},
493 {'B','l','u','e','Y',0},
494 };
495 static const ULONG expected_vals[8] = {
496 31270,32900, 64000,33000, 30000,60000, 15000,6000
497 };
498
499 PropVariantInit(&schema);
500 PropVariantInit(&id);
501 PropVariantInit(&value);
502
503 hr = CoCreateInstance(&CLSID_WICPngChrmMetadataReader, NULL, CLSCTX_INPROC_SERVER,
504 &IID_IWICMetadataReader, (void**)&reader);
505 ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG) /*winxp*/, "CoCreateInstance failed, hr=%x\n", hr);
506 if (FAILED(hr)) return;
507
509
510 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
511 ok(hr == S_OK, "GetMetadataFormat failed, hr=%x\n", hr);
512 ok(IsEqualGUID(&format, &GUID_MetadataFormatChunkcHRM), "unexpected format %s\n", wine_dbgstr_guid(&format));
513
514 hr = IWICMetadataReader_GetCount(reader, &count);
515 ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
516 ok(count == 8, "unexpected count %i\n", count);
517
518 for (i=0; i<8; i++)
519 {
520 hr = IWICMetadataReader_GetValueByIndex(reader, i, &schema, &id, &value);
521 ok(hr == S_OK, "GetValue failed, hr=%x\n", hr);
522
523 ok(schema.vt == VT_EMPTY, "unexpected vt: %i\n", schema.vt);
525
526 ok(id.vt == VT_LPWSTR, "unexpected vt: %i\n", id.vt);
527 ok(!lstrcmpW(U(id).pwszVal, expected_names[i]), "got %s, expected %s\n", wine_dbgstr_w(U(id).pwszVal), wine_dbgstr_w(expected_names[i]));
528 PropVariantClear(&id);
529
530 ok(value.vt == VT_UI4, "unexpected vt: %i\n", value.vt);
531 ok(U(value).ulVal == expected_vals[i], "got %u, expected %u\n", U(value).ulVal, expected_vals[i]);
533 }
534
535 IWICMetadataReader_Release(reader);
536}
537
539{
540 return (s >> 8) | (s << 8);
541}
542
543static inline ULONG ulong_bswap(ULONG l)
544{
545 return ((ULONG)ushort_bswap((USHORT)l) << 16) | ushort_bswap((USHORT)(l >> 16));
546}
547
549{
550 return ((ULONGLONG)ulong_bswap((ULONG)ll) << 32) | ulong_bswap((ULONG)(ll >> 32));
551}
552
553static void byte_swap_ifd_data(char *data)
554{
555 USHORT number_of_entries, i;
556 struct IFD_entry *entry;
557 char *data_start = data;
558
559 number_of_entries = *(USHORT *)data;
561 data += sizeof(USHORT);
562
563 for (i = 0; i < number_of_entries; i++)
564 {
565 entry = (struct IFD_entry *)data;
566
567 switch (entry->type)
568 {
569 case IFD_BYTE:
570 case IFD_SBYTE:
571 case IFD_ASCII:
572 case IFD_UNDEFINED:
573 if (entry->count > 4)
574 entry->value = ulong_bswap(entry->value);
575 break;
576
577 case IFD_SHORT:
578 case IFD_SSHORT:
579 if (entry->count > 2)
580 {
581 ULONG j, count = entry->count;
582 USHORT *us = (USHORT *)(data_start + entry->value);
583 if (!count) count = 1;
584 for (j = 0; j < count; j++)
585 us[j] = ushort_bswap(us[j]);
586
587 entry->value = ulong_bswap(entry->value);
588 }
589 else
590 {
591 ULONG j, count = entry->count;
592 USHORT *us = (USHORT *)&entry->value;
593 if (!count) count = 1;
594 for (j = 0; j < count; j++)
595 us[j] = ushort_bswap(us[j]);
596 }
597 break;
598
599 case IFD_LONG:
600 case IFD_SLONG:
601 case IFD_FLOAT:
602 if (entry->count > 1)
603 {
604 ULONG j, count = entry->count;
605 ULONG *ul = (ULONG *)(data_start + entry->value);
606 if (!count) count = 1;
607 for (j = 0; j < count; j++)
608 ul[j] = ulong_bswap(ul[j]);
609 }
610 entry->value = ulong_bswap(entry->value);
611 break;
612
613 case IFD_RATIONAL:
614 case IFD_SRATIONAL:
615 {
616 ULONG j;
617 ULONG *ul = (ULONG *)(data_start + entry->value);
618 for (j = 0; j < entry->count * 2; j++)
619 ul[j] = ulong_bswap(ul[j]);
620 }
621 entry->value = ulong_bswap(entry->value);
622 break;
623
624 case IFD_DOUBLE:
625 {
626 ULONG j;
627 ULONGLONG *ull = (ULONGLONG *)(data_start + entry->value);
628 for (j = 0; j < entry->count; j++)
629 ull[j] = ulonglong_bswap(ull[j]);
630 }
631 entry->value = ulong_bswap(entry->value);
632 break;
633
634 default:
635 assert(0);
636 break;
637 }
638
639 entry->id = ushort_bswap(entry->id);
640 entry->type = ushort_bswap(entry->type);
641 entry->count = ulong_bswap(entry->count);
642 data += sizeof(*entry);
643 }
644}
645
646struct test_data
647{
649 int count; /* if VT_VECTOR */
651 const char *string;
652 const WCHAR id_string[32];
653};
654
656{
657 HRESULT hr;
658 IWICEnumMetadataItem *enumerator;
659 PROPVARIANT schema, id, value;
660 ULONG items_returned, i;
661
662 hr = IWICMetadataReader_GetEnumerator(reader, NULL);
663 ok(hr == E_INVALIDARG, "GetEnumerator error %#x\n", hr);
664
665 hr = IWICMetadataReader_GetEnumerator(reader, &enumerator);
666 ok(hr == S_OK, "GetEnumerator error %#x\n", hr);
667
668 PropVariantInit(&schema);
669 PropVariantInit(&id);
670 PropVariantInit(&value);
671
672 for (i = 0; i < count; i++)
673 {
674 hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
675 ok(hr == S_OK, "Next error %#x\n", hr);
676 ok(items_returned == 1, "unexpected item count %u\n", items_returned);
677
678 ok(schema.vt == VT_EMPTY, "%u: unexpected vt: %u\n", i, schema.vt);
679 ok(id.vt == VT_UI2 || id.vt == VT_LPWSTR || id.vt == VT_EMPTY, "%u: unexpected vt: %u\n", i, id.vt);
680 if (id.vt == VT_UI2)
681 ok(U(id).uiVal == td[i].id, "%u: expected id %#x, got %#x\n", i, td[i].id, U(id).uiVal);
682 else if (id.vt == VT_LPWSTR)
683 ok(!lstrcmpW(td[i].id_string, U(id).pwszVal),
684 "%u: expected %s, got %s\n", i, wine_dbgstr_w(td[i].id_string), wine_dbgstr_w(U(id).pwszVal));
685
686 ok(value.vt == td[i].type, "%u: expected vt %#x, got %#x\n", i, td[i].type, value.vt);
687 if (value.vt & VT_VECTOR)
688 {
689 ULONG j;
690 switch (value.vt & ~VT_VECTOR)
691 {
692 case VT_I1:
693 case VT_UI1:
694 ok(td[i].count == U(value).caub.cElems, "%u: expected cElems %d, got %d\n", i, td[i].count, U(value).caub.cElems);
695 for (j = 0; j < U(value).caub.cElems; j++)
696 ok(td[i].value[j] == U(value).caub.pElems[j], "%u: expected value[%d] %#x/%#x, got %#x\n", i, j, (ULONG)td[i].value[j], (ULONG)(td[i].value[j] >> 32), U(value).caub.pElems[j]);
697 break;
698 case VT_I2:
699 case VT_UI2:
700 ok(td[i].count == U(value).caui.cElems, "%u: expected cElems %d, got %d\n", i, td[i].count, U(value).caui.cElems);
701 for (j = 0; j < U(value).caui.cElems; j++)
702 ok(td[i].value[j] == U(value).caui.pElems[j], "%u: expected value[%d] %#x/%#x, got %#x\n", i, j, (ULONG)td[i].value[j], (ULONG)(td[i].value[j] >> 32), U(value).caui.pElems[j]);
703 break;
704 case VT_I4:
705 case VT_UI4:
706 case VT_R4:
707 ok(td[i].count == U(value).caul.cElems, "%u: expected cElems %d, got %d\n", i, td[i].count, U(value).caul.cElems);
708 for (j = 0; j < U(value).caul.cElems; j++)
709 ok(td[i].value[j] == U(value).caul.pElems[j], "%u: expected value[%d] %#x/%#x, got %#x\n", i, j, (ULONG)td[i].value[j], (ULONG)(td[i].value[j] >> 32), U(value).caul.pElems[j]);
710 break;
711 case VT_I8:
712 case VT_UI8:
713 case VT_R8:
714 ok(td[i].count == U(value).cauh.cElems, "%u: expected cElems %d, got %d\n", i, td[i].count, U(value).cauh.cElems);
715 for (j = 0; j < U(value).cauh.cElems; j++)
716 ok(td[i].value[j] == U(value).cauh.pElems[j].QuadPart, "%u: expected value[%d] %08x/%08x, got %08x/%08x\n", i, j, (ULONG)td[i].value[j], (ULONG)(td[i].value[j] >> 32), U(value).cauh.pElems[j].u.LowPart, U(value).cauh.pElems[j].u.HighPart);
717 break;
718 case VT_LPSTR:
719 ok(td[i].count == U(value).calpstr.cElems, "%u: expected cElems %d, got %d\n", i, td[i].count, U(value).caub.cElems);
720 for (j = 0; j < U(value).calpstr.cElems; j++)
721 trace("%u: %s\n", j, U(value).calpstr.pElems[j]);
722 /* fall through to not handled message */
723 default:
724 ok(0, "%u: array of type %d is not handled\n", i, value.vt & ~VT_VECTOR);
725 break;
726 }
727 }
728 else if (value.vt == VT_LPSTR)
729 {
730 ok(td[i].count == strlen(U(value).pszVal) ||
731 broken(td[i].count == strlen(U(value).pszVal) + 1), /* before Win7 */
732 "%u: expected count %d, got %d\n", i, td[i].count, lstrlenA(U(value).pszVal));
733 if (td[i].count == strlen(U(value).pszVal))
734 ok(!strcmp(td[i].string, U(value).pszVal),
735 "%u: expected %s, got %s\n", i, td[i].string, U(value).pszVal);
736 }
737 else if (value.vt == VT_BLOB)
738 {
739 ok(td[i].count == U(value).blob.cbSize, "%u: expected count %d, got %d\n", i, td[i].count, U(value).blob.cbSize);
740 ok(!memcmp(td[i].string, U(value).blob.pBlobData, td[i].count), "%u: expected %s, got %s\n", i, td[i].string, U(value).blob.pBlobData);
741 }
742 else
743 ok(U(value).uhVal.QuadPart == td[i].value[0], "%u: expected value %#x/%#x got %#x/%#x\n",
744 i, (UINT)td[i].value[0], (UINT)(td[i].value[0] >> 32), U(value).uhVal.u.LowPart, U(value).uhVal.u.HighPart);
745
747 PropVariantClear(&id);
749 }
750
751 hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
752 ok(hr == S_FALSE, "Next should fail\n");
753 ok(items_returned == 0, "unexpected item count %u\n", items_returned);
754
755 IWICEnumMetadataItem_Release(enumerator);
756}
757
758static void test_metadata_IFD(void)
759{
760 static const struct test_data td[28] =
761 {
762 { VT_UI2, 0xfe, 0, { 1 } },
763 { VT_UI4, 0x100, 0, { 222 } },
764 { VT_UI4, 0x101, 0, { 333 } },
765 { VT_UI2, 0x102, 0, { 24 } },
766 { VT_UI4, 0x103, 0, { 32773 } },
767 { VT_UI8, 0x11a, 0, { ((LONGLONG)3 << 32) | 900 } },
768 { VT_UI1, 0xf001, 0, { 0x44 } },
769 { VT_UI1|VT_VECTOR, 0xf002, 4, { 0x44, 0x33, 0x22, 0x11 } },
770 { VT_I1, 0xf003, 0, { 0x44 } },
771 { VT_I2, 0xf004, 0, { 0x3344 } },
772 { VT_I2|VT_VECTOR, 0xf005, 2, { 0x3344, 0x1122 } },
773 { VT_I4, 0xf006, 0, { 0x11223344 } },
774 { VT_R4, 0xf007, 0, { 0x11223344 } },
775 { VT_R8, 0xf008, 0, { ((LONGLONG)0x41d26580 << 32) | 0xb486522c } },
776 { VT_I8, 0xf009, 0, { ((LONGLONG)0x5a6b7c8d << 32) | 0x1a2b3c4d } },
777 { VT_UI1|VT_VECTOR, 0xf00a, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
778 { VT_I2|VT_VECTOR, 0xf00b, 4, { 0x0101, 0x0202, 0x0303, 0x0404 } },
779 { VT_I4|VT_VECTOR, 0xf00c, 2, { 0x11223344, 0x55667788 } },
780 { VT_R4|VT_VECTOR, 0xf00d, 2, { 0x449a522b, 0x4608f5ba } },
781 { VT_LPSTR, 0xf00e, 12, { 0 }, "Hello World!" },
782 { VT_LPSTR, 0xf00f, 4, { 0 }, "abcd" },
783 { VT_BLOB, 0xf010, 13, { 0 }, "Hello World!" },
784 { VT_BLOB, 0xf011, 4, { 0 }, "abcd" },
785 { VT_UI1, 0xf012, 0, { 0x44 } },
786 { VT_UI2, 0xf013, 0, { 0x3344 } },
787 { VT_UI4, 0xf014, 0, { 0x11223344 } },
788 { VT_R4, 0xf015, 0, { 0x11223344 } },
789 { VT_I8|VT_VECTOR, 0xf016, 3,
790 { ((LONGLONG)0x05060708 << 32) | 0x01020304,
791 ((LONGLONG)0x50607080 << 32) | 0x10203040,
792 ((LONGLONG)0x55667788 << 32) | 0x11223344 } },
793 };
794 HRESULT hr;
796 IWICMetadataBlockReader *blockreader;
797 PROPVARIANT schema, id, value;
798 ULONG count;
799 GUID format;
800 char *IFD_data_swapped;
801#ifdef WORDS_BIGENDIAN
802 DWORD persist_options = WICPersistOptionBigEndian;
803#else
804 DWORD persist_options = WICPersistOptionLittleEndian;
805#endif
806
807 hr = CoCreateInstance(&CLSID_WICIfdMetadataReader, NULL, CLSCTX_INPROC_SERVER,
808 &IID_IWICMetadataReader, (void**)&reader);
809 ok(hr == S_OK, "CoCreateInstance error %#x\n", hr);
810
811 hr = IWICMetadataReader_GetCount(reader, NULL);
812 ok(hr == E_INVALIDARG, "GetCount error %#x\n", hr);
813
814 hr = IWICMetadataReader_GetCount(reader, &count);
815 ok(hr == S_OK, "GetCount error %#x\n", hr);
816 ok(count == 0, "unexpected count %u\n", count);
817
818 load_stream((IUnknown*)reader, (const char *)&IFD_data, sizeof(IFD_data), persist_options);
819
820 hr = IWICMetadataReader_GetCount(reader, &count);
821 ok(hr == S_OK, "GetCount error %#x\n", hr);
822 ok(count == ARRAY_SIZE(td), "unexpected count %u\n", count);
823
825
826 /* test IFD data with different endianness */
827 if (persist_options == WICPersistOptionLittleEndian)
828 persist_options = WICPersistOptionBigEndian;
829 else
830 persist_options = WICPersistOptionLittleEndian;
831
832 IFD_data_swapped = HeapAlloc(GetProcessHeap(), 0, sizeof(IFD_data));
833 memcpy(IFD_data_swapped, &IFD_data, sizeof(IFD_data));
834 byte_swap_ifd_data(IFD_data_swapped);
835 load_stream((IUnknown *)reader, IFD_data_swapped, sizeof(IFD_data), persist_options);
836 hr = IWICMetadataReader_GetCount(reader, &count);
837 ok(hr == S_OK, "GetCount error %#x\n", hr);
838 ok(count == ARRAY_SIZE(td), "unexpected count %u\n", count);
840 HeapFree(GetProcessHeap(), 0, IFD_data_swapped);
841
842 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
843 ok(hr == S_OK, "GetMetadataFormat error %#x\n", hr);
844 ok(IsEqualGUID(&format, &GUID_MetadataFormatIfd), "unexpected format %s\n", wine_dbgstr_guid(&format));
845
846 hr = IWICMetadataReader_GetMetadataFormat(reader, NULL);
847 ok(hr == E_INVALIDARG, "GetMetadataFormat should fail\n");
848
849 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, NULL, NULL);
850 ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
851
852 PropVariantInit(&schema);
853 PropVariantInit(&id);
854 PropVariantInit(&value);
855
856 hr = IWICMetadataReader_GetValueByIndex(reader, count - 1, NULL, NULL, NULL);
857 ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
858
859 hr = IWICMetadataReader_GetValueByIndex(reader, 0, &schema, NULL, NULL);
860 ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
861 ok(schema.vt == VT_EMPTY, "unexpected vt: %u\n", schema.vt);
862
863 hr = IWICMetadataReader_GetValueByIndex(reader, count - 1, &schema, NULL, NULL);
864 ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
865 ok(schema.vt == VT_EMPTY, "unexpected vt: %u\n", schema.vt);
866
867 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, &id, NULL);
868 ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
869 ok(id.vt == VT_UI2, "unexpected vt: %u\n", id.vt);
870 ok(U(id).uiVal == 0xfe, "unexpected id: %#x\n", U(id).uiVal);
871 PropVariantClear(&id);
872
873 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, NULL, &value);
874 ok(hr == S_OK, "GetValueByIndex error %#x\n", hr);
875 ok(value.vt == VT_UI2, "unexpected vt: %u\n", value.vt);
876 ok(U(value).uiVal == 1, "unexpected id: %#x\n", U(value).uiVal);
878
879 hr = IWICMetadataReader_GetValueByIndex(reader, count, &schema, NULL, NULL);
880 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr);
881
882 PropVariantInit(&schema);
883 PropVariantInit(&id);
884 PropVariantInit(&value);
885
886 hr = IWICMetadataReader_GetValue(reader, &schema, &id, &value);
887 ok(hr == WINCODEC_ERR_PROPERTYNOTFOUND, "expected WINCODEC_ERR_PROPERTYNOTFOUND, got %#x\n", hr);
888
889 hr = IWICMetadataReader_GetValue(reader, NULL, &id, NULL);
890 ok(hr == WINCODEC_ERR_PROPERTYNOTFOUND, "expected WINCODEC_ERR_PROPERTYNOTFOUND, got %#x\n", hr);
891
892 hr = IWICMetadataReader_GetValue(reader, &schema, NULL, NULL);
893 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr);
894
895 hr = IWICMetadataReader_GetValue(reader, &schema, &id, NULL);
896 ok(hr == WINCODEC_ERR_PROPERTYNOTFOUND, "expected WINCODEC_ERR_PROPERTYNOTFOUND, got %#x\n", hr);
897
898 hr = IWICMetadataReader_GetValue(reader, &schema, NULL, &value);
899 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr);
900
901 id.vt = VT_UI2;
902 U(id).uiVal = 0xf00e;
903 hr = IWICMetadataReader_GetValue(reader, NULL, &id, NULL);
904 ok(hr == S_OK, "GetValue error %#x\n", hr);
905
906 /* schema is ignored by Ifd metadata reader */
907 schema.vt = VT_UI4;
908 U(schema).ulVal = 0xdeadbeef;
909 hr = IWICMetadataReader_GetValue(reader, &schema, &id, &value);
910 ok(hr == S_OK, "GetValue error %#x\n", hr);
911 ok(value.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt);
912 ok(!strcmp(U(value).pszVal, "Hello World!"), "unexpected value: %s\n", U(value).pszVal);
914
915 hr = IWICMetadataReader_GetValue(reader, NULL, &id, &value);
916 ok(hr == S_OK, "GetValue error %#x\n", hr);
917 ok(value.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt);
918 ok(!strcmp(U(value).pszVal, "Hello World!"), "unexpected value: %s\n", U(value).pszVal);
920
921 hr = IWICMetadataReader_QueryInterface(reader, &IID_IWICMetadataBlockReader, (void**)&blockreader);
922 ok(hr == E_NOINTERFACE, "QueryInterface failed, hr=%x\n", hr);
923
924 if (SUCCEEDED(hr))
925 IWICMetadataBlockReader_Release(blockreader);
926
927 IWICMetadataReader_Release(reader);
928}
929
930static void test_metadata_Exif(void)
931{
932 HRESULT hr;
934 IWICMetadataBlockReader *blockreader;
935 UINT count=0;
936
937 hr = CoCreateInstance(&CLSID_WICExifMetadataReader, NULL, CLSCTX_INPROC_SERVER,
938 &IID_IWICMetadataReader, (void**)&reader);
939 todo_wine ok(hr == S_OK, "CoCreateInstance error %#x\n", hr);
940 if (FAILED(hr)) return;
941
942 hr = IWICMetadataReader_GetCount(reader, NULL);
943 ok(hr == E_INVALIDARG, "GetCount error %#x\n", hr);
944
945 hr = IWICMetadataReader_GetCount(reader, &count);
946 ok(hr == S_OK, "GetCount error %#x\n", hr);
947 ok(count == 0, "unexpected count %u\n", count);
948
949 hr = IWICMetadataReader_QueryInterface(reader, &IID_IWICMetadataBlockReader, (void**)&blockreader);
950 ok(hr == E_NOINTERFACE, "QueryInterface failed, hr=%x\n", hr);
951
952 if (SUCCEEDED(hr))
953 IWICMetadataBlockReader_Release(blockreader);
954
955 IWICMetadataReader_Release(reader);
956}
957
958static void test_create_reader(void)
959{
960 HRESULT hr;
964 UINT count=0;
965 GUID format;
966
967 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
968 &IID_IWICComponentFactory, (void**)&factory);
969 ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
970
972
973 hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
975 stream, &reader);
976 ok(hr == E_INVALIDARG, "CreateMetadataReaderFromContainer failed, hr=%x\n", hr);
977
978 hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
979 &GUID_ContainerFormatPng, NULL, WICPersistOptionDefault,
980 NULL, &reader);
981 ok(hr == E_INVALIDARG, "CreateMetadataReaderFromContainer failed, hr=%x\n", hr);
982
983 hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
984 &GUID_ContainerFormatPng, NULL, WICPersistOptionDefault,
985 stream, NULL);
986 ok(hr == E_INVALIDARG, "CreateMetadataReaderFromContainer failed, hr=%x\n", hr);
987
988 hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
989 &GUID_ContainerFormatPng, NULL, WICPersistOptionDefault,
990 stream, &reader);
991 ok(hr == S_OK, "CreateMetadataReaderFromContainer failed, hr=%x\n", hr);
992
993 if (SUCCEEDED(hr))
994 {
995 hr = IWICMetadataReader_GetCount(reader, &count);
996 ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
997 ok(count == 1, "unexpected count %i\n", count);
998
999 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
1000 ok(hr == S_OK, "GetMetadataFormat failed, hr=%x\n", hr);
1001 ok(IsEqualGUID(&format, &GUID_MetadataFormatChunktEXt), "unexpected format %s\n", wine_dbgstr_guid(&format));
1002
1003 IWICMetadataReader_Release(reader);
1004 }
1005
1006 hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
1007 &GUID_ContainerFormatWmp, NULL, WICPersistOptionDefault,
1008 stream, &reader);
1009 ok(hr == S_OK, "CreateMetadataReaderFromContainer failed, hr=%x\n", hr);
1010
1011 if (SUCCEEDED(hr))
1012 {
1013 hr = IWICMetadataReader_GetCount(reader, &count);
1014 ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
1015 ok(count == 1, "unexpected count %i\n", count);
1016
1017 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
1018 ok(hr == S_OK, "GetMetadataFormat failed, hr=%x\n", hr);
1019 ok(IsEqualGUID(&format, &GUID_MetadataFormatUnknown), "unexpected format %s\n", wine_dbgstr_guid(&format));
1020
1021 IWICMetadataReader_Release(reader);
1022 }
1023
1024 IStream_Release(stream);
1025
1026 IWICComponentFactory_Release(factory);
1027}
1028
1029static void test_metadata_png(void)
1030{
1031 static const struct test_data td[6] =
1032 {
1033 { VT_UI2, 0, 0, { 2005 }, NULL, { 'Y','e','a','r',0 } },
1034 { VT_UI1, 0, 0, { 6 }, NULL, { 'M','o','n','t','h',0 } },
1035 { VT_UI1, 0, 0, { 3 }, NULL, { 'D','a','y',0 } },
1036 { VT_UI1, 0, 0, { 15 }, NULL, { 'H','o','u','r',0 } },
1037 { VT_UI1, 0, 0, { 7 }, NULL, { 'M','i','n','u','t','e',0 } },
1038 { VT_UI1, 0, 0, { 45 }, NULL, { 'S','e','c','o','n','d',0 } }
1039 };
1040 IStream *stream;
1041 IWICBitmapDecoder *decoder;
1042 IWICBitmapFrameDecode *frame;
1043 IWICMetadataBlockReader *blockreader;
1045 IWICMetadataQueryReader *queryreader;
1047 GUID containerformat;
1048 HRESULT hr;
1049 UINT count=0xdeadbeef;
1050
1051 hr = CoCreateInstance(&CLSID_WICPngDecoder, NULL, CLSCTX_INPROC_SERVER,
1052 &IID_IWICBitmapDecoder, (void**)&decoder);
1053 ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
1054
1055 if (FAILED(hr)) return;
1056
1058
1059 hr = IWICBitmapDecoder_Initialize(decoder, stream, WICDecodeMetadataCacheOnLoad);
1060 ok(hr == S_OK, "Initialize failed, hr=%x\n", hr);
1061
1062 hr = IWICBitmapDecoder_QueryInterface(decoder, &IID_IWICMetadataBlockReader, (void**)&blockreader);
1063 ok(hr == E_NOINTERFACE, "QueryInterface failed, hr=%x\n", hr);
1064
1065 hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
1066 ok(hr == S_OK, "GetFrame failed, hr=%x\n", hr);
1067
1068 hr = IWICBitmapFrameDecode_QueryInterface(frame, &IID_IWICMetadataBlockReader, (void**)&blockreader);
1069 ok(hr == S_OK, "QueryInterface failed, hr=%x\n", hr);
1070
1071 if (SUCCEEDED(hr))
1072 {
1073 hr = IWICMetadataBlockReader_GetContainerFormat(blockreader, NULL);
1074 ok(hr == E_INVALIDARG, "GetContainerFormat failed, hr=%x\n", hr);
1075
1076 hr = IWICMetadataBlockReader_GetContainerFormat(blockreader, &containerformat);
1077 ok(hr == S_OK, "GetContainerFormat failed, hr=%x\n", hr);
1078 ok(IsEqualGUID(&containerformat, &GUID_ContainerFormatPng), "unexpected container format\n");
1079
1080 hr = IWICMetadataBlockReader_GetCount(blockreader, NULL);
1081 ok(hr == E_INVALIDARG, "GetCount failed, hr=%x\n", hr);
1082
1083 hr = IWICMetadataBlockReader_GetCount(blockreader, &count);
1084 ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
1085 ok(count == 1, "unexpected count %d\n", count);
1086
1087 if (0)
1088 {
1089 /* Crashes on Windows XP */
1090 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 0, NULL);
1091 ok(hr == E_INVALIDARG, "GetReaderByIndex failed, hr=%x\n", hr);
1092 }
1093
1094 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 0, &reader);
1095 ok(hr == S_OK, "GetReaderByIndex failed, hr=%x\n", hr);
1096
1097 if (SUCCEEDED(hr))
1098 {
1099 hr = IWICMetadataReader_GetMetadataFormat(reader, &containerformat);
1100 ok(hr == S_OK, "GetMetadataFormat failed, hr=%#x\n", hr);
1101 todo_wine ok(IsEqualGUID(&containerformat, &GUID_MetadataFormatChunktIME) ||
1102 broken(IsEqualGUID(&containerformat, &GUID_MetadataFormatUnknown)) /* Windows XP */,
1103 "unexpected container format\n");
1104
1105 hr = IWICMetadataReader_GetCount(reader, &count);
1106 ok(hr == S_OK, "GetCount error %#x\n", hr);
1107 todo_wine ok(count == 6 || broken(count == 1) /* XP */, "expected 6, got %u\n", count);
1108 if (count == 6)
1110
1111 IWICMetadataReader_Release(reader);
1112 }
1113
1114 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 1, &reader);
1115 todo_wine ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE, "GetReaderByIndex failed, hr=%x\n", hr);
1116
1117 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
1118 &IID_IWICComponentFactory, (void**)&factory);
1119 ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
1120
1121 hr = IWICComponentFactory_CreateQueryReaderFromBlockReader(factory, NULL, &queryreader);
1122 ok(hr == E_INVALIDARG, "CreateQueryReaderFromBlockReader should have failed: %08x\n", hr);
1123
1124 hr = IWICComponentFactory_CreateQueryReaderFromBlockReader(factory, blockreader, NULL);
1125 ok(hr == E_INVALIDARG, "CreateQueryReaderFromBlockReader should have failed: %08x\n", hr);
1126
1127 hr = IWICComponentFactory_CreateQueryReaderFromBlockReader(factory, blockreader, &queryreader);
1128 ok(hr == S_OK, "CreateQueryReaderFromBlockReader failed: %08x\n", hr);
1129
1130 IWICMetadataQueryReader_Release(queryreader);
1131
1132 IWICComponentFactory_Release(factory);
1133
1134 IWICMetadataBlockReader_Release(blockreader);
1135 }
1136
1137 hr = IWICBitmapFrameDecode_GetMetadataQueryReader(frame, &queryreader);
1138 ok(hr == S_OK, "GetMetadataQueryReader failed: %08x\n", hr);
1139
1140 if (SUCCEEDED(hr))
1141 {
1142 IWICMetadataQueryReader_Release(queryreader);
1143 }
1144
1145 IWICBitmapFrameDecode_Release(frame);
1146
1147 IWICBitmapDecoder_Release(decoder);
1148
1149 IStream_Release(stream);
1150}
1151
1152static void test_metadata_gif(void)
1153{
1154 static const struct test_data gif_LSD[9] =
1155 {
1156 { VT_UI1|VT_VECTOR, 0, 6, {'G','I','F','8','7','a'}, NULL, { 'S','i','g','n','a','t','u','r','e',0 } },
1157 { VT_UI2, 0, 0, { 1 }, NULL, { 'W','i','d','t','h',0 } },
1158 { VT_UI2, 0, 0, { 1 }, NULL, { 'H','e','i','g','h','t',0 } },
1159 { VT_BOOL, 0, 0, { 1 }, NULL, { 'G','l','o','b','a','l','C','o','l','o','r','T','a','b','l','e','F','l','a','g',0 } },
1160 { VT_UI1, 0, 0, { 0 }, NULL, { 'C','o','l','o','r','R','e','s','o','l','u','t','i','o','n',0 } },
1161 { VT_BOOL, 0, 0, { 0 }, NULL, { 'S','o','r','t','F','l','a','g',0 } },
1162 { VT_UI1, 0, 0, { 0 }, NULL, { 'G','l','o','b','a','l','C','o','l','o','r','T','a','b','l','e','S','i','z','e',0 } },
1163 { VT_UI1, 0, 0, { 0 }, NULL, { 'B','a','c','k','g','r','o','u','n','d','C','o','l','o','r','I','n','d','e','x',0 } },
1164 { VT_UI1, 0, 0, { 0 }, NULL, { 'P','i','x','e','l','A','s','p','e','c','t','R','a','t','i','o',0 } }
1165 };
1166 static const struct test_data gif_IMD[8] =
1167 {
1168 { VT_UI2, 0, 0, { 0 }, NULL, { 'L','e','f','t',0 } },
1169 { VT_UI2, 0, 0, { 0 }, NULL, { 'T','o','p',0 } },
1170 { VT_UI2, 0, 0, { 1 }, NULL, { 'W','i','d','t','h',0 } },
1171 { VT_UI2, 0, 0, { 1 }, NULL, { 'H','e','i','g','h','t',0 } },
1172 { VT_BOOL, 0, 0, { 0 }, NULL, { 'L','o','c','a','l','C','o','l','o','r','T','a','b','l','e','F','l','a','g',0 } },
1173 { VT_BOOL, 0, 0, { 0 }, NULL, { 'I','n','t','e','r','l','a','c','e','F','l','a','g',0 } },
1174 { VT_BOOL, 0, 0, { 0 }, NULL, { 'S','o','r','t','F','l','a','g',0 } },
1175 { VT_UI1, 0, 0, { 0 }, NULL, { 'L','o','c','a','l','C','o','l','o','r','T','a','b','l','e','S','i','z','e',0 } }
1176 };
1177 static const struct test_data animated_gif_LSD[9] =
1178 {
1179 { VT_UI1|VT_VECTOR, 0, 6, {'G','I','F','8','9','a'}, NULL, { 'S','i','g','n','a','t','u','r','e',0 } },
1180 { VT_UI2, 0, 0, { 1 }, NULL, { 'W','i','d','t','h',0 } },
1181 { VT_UI2, 0, 0, { 1 }, NULL, { 'H','e','i','g','h','t',0 } },
1182 { VT_BOOL, 0, 0, { 1 }, NULL, { 'G','l','o','b','a','l','C','o','l','o','r','T','a','b','l','e','F','l','a','g',0 } },
1183 { VT_UI1, 0, 0, { 2 }, NULL, { 'C','o','l','o','r','R','e','s','o','l','u','t','i','o','n',0 } },
1184 { VT_BOOL, 0, 0, { 0 }, NULL, { 'S','o','r','t','F','l','a','g',0 } },
1185 { VT_UI1, 0, 0, { 1 }, NULL, { 'G','l','o','b','a','l','C','o','l','o','r','T','a','b','l','e','S','i','z','e',0 } },
1186 { VT_UI1, 0, 0, { 0 }, NULL, { 'B','a','c','k','g','r','o','u','n','d','C','o','l','o','r','I','n','d','e','x',0 } },
1187 { VT_UI1, 0, 0, { 0 }, NULL, { 'P','i','x','e','l','A','s','p','e','c','t','R','a','t','i','o',0 } }
1188 };
1189 static const struct test_data animated_gif_IMD[8] =
1190 {
1191 { VT_UI2, 0, 0, { 0 }, NULL, { 'L','e','f','t',0 } },
1192 { VT_UI2, 0, 0, { 0 }, NULL, { 'T','o','p',0 } },
1193 { VT_UI2, 0, 0, { 1 }, NULL, { 'W','i','d','t','h',0 } },
1194 { VT_UI2, 0, 0, { 1 }, NULL, { 'H','e','i','g','h','t',0 } },
1195 { VT_BOOL, 0, 0, { 1 }, NULL, { 'L','o','c','a','l','C','o','l','o','r','T','a','b','l','e','F','l','a','g',0 } },
1196 { VT_BOOL, 0, 0, { 0 }, NULL, { 'I','n','t','e','r','l','a','c','e','F','l','a','g',0 } },
1197 { VT_BOOL, 0, 0, { 0 }, NULL, { 'S','o','r','t','F','l','a','g',0 } },
1198 { VT_UI1, 0, 0, { 1 }, NULL, { 'L','o','c','a','l','C','o','l','o','r','T','a','b','l','e','S','i','z','e',0 } }
1199 };
1200 static const struct test_data animated_gif_GCE[5] =
1201 {
1202 { VT_UI1, 0, 0, { 0 }, NULL, { 'D','i','s','p','o','s','a','l',0 } },
1203 { VT_BOOL, 0, 0, { 0 }, NULL, { 'U','s','e','r','I','n','p','u','t','F','l','a','g',0 } },
1204 { VT_BOOL, 0, 0, { 1 }, NULL, { 'T','r','a','n','s','p','a','r','e','n','c','y','F','l','a','g',0 } },
1205 { VT_UI2, 0, 0, { 10 }, NULL, { 'D','e','l','a','y',0 } },
1206 { VT_UI1, 0, 0, { 1 }, NULL, { 'T','r','a','n','s','p','a','r','e','n','t','C','o','l','o','r','I','n','d','e','x',0 } }
1207 };
1208 static const struct test_data animated_gif_APE[2] =
1209 {
1210 { VT_UI1|VT_VECTOR, 0, 11, { 'A','N','I','M','E','X','T','S','1','.','0' }, NULL, { 'A','p','p','l','i','c','a','t','i','o','n',0 } },
1211 { VT_UI1|VT_VECTOR, 0, 4, { 0x03,0x01,0x05,0x00 }, NULL, { 'D','a','t','a',0 } }
1212 };
1213 static const struct test_data animated_gif_comment_1[1] =
1214 {
1215 { VT_LPSTR, 0, 12, { 0 }, "Hello World!", { 'T','e','x','t','E','n','t','r','y',0 } }
1216 };
1217 static const struct test_data animated_gif_comment_2[1] =
1218 {
1219 { VT_LPSTR, 0, 8, { 0 }, "image #1", { 'T','e','x','t','E','n','t','r','y',0 } }
1220 };
1221 static const struct test_data animated_gif_plain_1[1] =
1222 {
1223 { VT_BLOB, 0, 17, { 0 }, "\x21\x01\x0d\x61nimation.gif" }
1224 };
1225 static const struct test_data animated_gif_plain_2[1] =
1226 {
1227 { VT_BLOB, 0, 16, { 0 }, "\x21\x01\x0cplaintext #1" }
1228 };
1229 IStream *stream;
1230 IWICBitmapDecoder *decoder;
1231 IWICBitmapFrameDecode *frame;
1232 IWICMetadataBlockReader *blockreader;
1234 IWICMetadataQueryReader *queryreader;
1235 GUID format;
1236 HRESULT hr;
1237 UINT count;
1238
1239 /* 1x1 pixel gif */
1241
1242 hr = CoCreateInstance(&CLSID_WICGifDecoder, NULL, CLSCTX_INPROC_SERVER,
1243 &IID_IWICBitmapDecoder, (void **)&decoder);
1244 ok(hr == S_OK, "CoCreateInstance error %#x\n", hr);
1245 hr = IWICBitmapDecoder_Initialize(decoder, stream, WICDecodeMetadataCacheOnLoad);
1246 ok(hr == S_OK, "Initialize error %#x\n", hr);
1247
1248 IStream_Release(stream);
1249
1250 /* global metadata block */
1251 hr = IWICBitmapDecoder_QueryInterface(decoder, &IID_IWICMetadataBlockReader, (void **)&blockreader);
1252 ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* before Win7 */, "QueryInterface error %#x\n", hr);
1253
1254 if (SUCCEEDED(hr))
1255 {
1256 hr = IWICMetadataBlockReader_GetContainerFormat(blockreader, &format);
1257 ok(hr == S_OK, "GetContainerFormat error %#x\n", hr);
1258 ok(IsEqualGUID(&format, &GUID_ContainerFormatGif),
1259 "wrong container format %s\n", wine_dbgstr_guid(&format));
1260
1261 hr = IWICMetadataBlockReader_GetCount(blockreader, &count);
1262 ok(hr == S_OK, "GetCount error %#x\n", hr);
1263 ok(count == 1, "expected 1, got %u\n", count);
1264
1265 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 0, &reader);
1266 ok(hr == S_OK, "GetReaderByIndex error %#x\n", hr);
1267
1268 if (SUCCEEDED(hr))
1269 {
1270 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
1271 ok(hr == S_OK, "GetMetadataFormat failed, hr=%#x\n", hr);
1272 ok(IsEqualGUID(&format, &GUID_MetadataFormatLSD), /* Logical Screen Descriptor */
1273 "wrong metadata format %s\n", wine_dbgstr_guid(&format));
1274
1275 hr = IWICMetadataReader_GetCount(reader, &count);
1276 ok(hr == S_OK, "GetCount error %#x\n", hr);
1277 ok(count == ARRAY_SIZE(gif_LSD), "unexpected count %u\n", count);
1278
1279 compare_metadata(reader, gif_LSD, count);
1280
1281 IWICMetadataReader_Release(reader);
1282 }
1283
1284 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 1, &reader);
1285 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr);
1286
1287 IWICMetadataBlockReader_Release(blockreader);
1288 }
1289
1290 /* frame metadata block */
1291 hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
1292 ok(hr == S_OK, "GetFrame error %#x\n", hr);
1293
1294 hr = IWICBitmapFrameDecode_QueryInterface(frame, &IID_IWICMetadataBlockReader, (void **)&blockreader);
1295 ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* before Win7 */, "QueryInterface error %#x\n", hr);
1296
1297 if (SUCCEEDED(hr))
1298 {
1299 hr = IWICMetadataBlockReader_GetContainerFormat(blockreader, NULL);
1300 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr);
1301
1302 hr = IWICMetadataBlockReader_GetContainerFormat(blockreader, &format);
1303 ok(hr == S_OK, "GetContainerFormat error %#x\n", hr);
1304 ok(IsEqualGUID(&format, &GUID_ContainerFormatGif),
1305 "wrong container format %s\n", wine_dbgstr_guid(&format));
1306
1307 hr = IWICMetadataBlockReader_GetCount(blockreader, NULL);
1308 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr);
1309
1310 hr = IWICMetadataBlockReader_GetCount(blockreader, &count);
1311 ok(hr == S_OK, "GetCount error %#x\n", hr);
1312 ok(count == 1, "expected 1, got %u\n", count);
1313
1314 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 0, &reader);
1315 ok(hr == S_OK, "GetReaderByIndex error %#x\n", hr);
1316
1317 if (SUCCEEDED(hr))
1318 {
1319 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
1320 ok(hr == S_OK, "GetMetadataFormat failed, hr=%#x\n", hr);
1321 ok(IsEqualGUID(&format, &GUID_MetadataFormatIMD), /* Image Descriptor */
1322 "wrong metadata format %s\n", wine_dbgstr_guid(&format));
1323
1324 hr = IWICMetadataReader_GetCount(reader, &count);
1325 ok(hr == S_OK, "GetCount error %#x\n", hr);
1326 ok(count == ARRAY_SIZE(gif_IMD), "unexpected count %u\n", count);
1327
1328 compare_metadata(reader, gif_IMD, count);
1329
1330 IWICMetadataReader_Release(reader);
1331 }
1332
1333 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 1, &reader);
1334 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr);
1335
1336 IWICMetadataBlockReader_Release(blockreader);
1337 }
1338
1339 IWICBitmapFrameDecode_Release(frame);
1340 IWICBitmapDecoder_Release(decoder);
1341
1342 /* 1x1 pixel gif, 2 frames */
1344
1345 hr = CoCreateInstance(&CLSID_WICGifDecoder, NULL, CLSCTX_INPROC_SERVER,
1346 &IID_IWICBitmapDecoder, (void **)&decoder);
1347 ok(hr == S_OK, "CoCreateInstance error %#x\n", hr);
1348 hr = IWICBitmapDecoder_Initialize(decoder, stream, WICDecodeMetadataCacheOnLoad);
1349 ok(hr == S_OK, "Initialize error %#x\n", hr);
1350
1351 IStream_Release(stream);
1352
1353 /* global metadata block */
1354 hr = IWICBitmapDecoder_QueryInterface(decoder, &IID_IWICMetadataBlockReader, (void **)&blockreader);
1355 ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* before Win7 */, "QueryInterface error %#x\n", hr);
1356
1357 if (SUCCEEDED(hr))
1358 {
1359 hr = IWICMetadataBlockReader_GetContainerFormat(blockreader, &format);
1360 ok(hr == S_OK, "GetContainerFormat error %#x\n", hr);
1361 ok(IsEqualGUID(&format, &GUID_ContainerFormatGif),
1362 "wrong container format %s\n", wine_dbgstr_guid(&format));
1363
1364 hr = IWICMetadataBlockReader_GetCount(blockreader, &count);
1365 ok(hr == S_OK, "GetCount error %#x\n", hr);
1366 ok(count == 4, "expected 4, got %u\n", count);
1367
1368 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 0, &reader);
1369 ok(hr == S_OK, "GetReaderByIndex error %#x\n", hr);
1370
1371 if (SUCCEEDED(hr))
1372 {
1373 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
1374 ok(hr == S_OK, "GetMetadataFormat failed, hr=%#x\n", hr);
1375 ok(IsEqualGUID(&format, &GUID_MetadataFormatLSD), /* Logical Screen Descriptor */
1376 "wrong metadata format %s\n", wine_dbgstr_guid(&format));
1377
1378 hr = IWICMetadataReader_GetCount(reader, &count);
1379 ok(hr == S_OK, "GetCount error %#x\n", hr);
1380 ok(count == ARRAY_SIZE(animated_gif_LSD), "unexpected count %u\n", count);
1381
1382 compare_metadata(reader, animated_gif_LSD, count);
1383
1384 IWICMetadataReader_Release(reader);
1385 }
1386
1387 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 1, &reader);
1388 ok(hr == S_OK, "GetReaderByIndex error %#x\n", hr);
1389
1390 if (SUCCEEDED(hr))
1391 {
1392 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
1393 ok(hr == S_OK, "GetMetadataFormat failed, hr=%#x\n", hr);
1394 ok(IsEqualGUID(&format, &GUID_MetadataFormatAPE), /* Application Extension */
1395 "wrong metadata format %s\n", wine_dbgstr_guid(&format));
1396
1397 hr = IWICMetadataReader_GetCount(reader, &count);
1398 ok(hr == S_OK, "GetCount error %#x\n", hr);
1399 ok(count == ARRAY_SIZE(animated_gif_APE), "unexpected count %u\n", count);
1400
1401 compare_metadata(reader, animated_gif_APE, count);
1402
1403 IWICMetadataReader_Release(reader);
1404 }
1405
1406 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 2, &reader);
1407 ok(hr == S_OK, "GetReaderByIndex error %#x\n", hr);
1408
1409 if (SUCCEEDED(hr))
1410 {
1411 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
1412 ok(hr == S_OK, "GetMetadataFormat failed, hr=%#x\n", hr);
1413 ok(IsEqualGUID(&format, &GUID_MetadataFormatGifComment), /* Comment Extension */
1414 "wrong metadata format %s\n", wine_dbgstr_guid(&format));
1415
1416 hr = IWICMetadataReader_GetCount(reader, &count);
1417 ok(hr == S_OK, "GetCount error %#x\n", hr);
1418 ok(count == ARRAY_SIZE(animated_gif_comment_1), "unexpected count %u\n", count);
1419
1420 compare_metadata(reader, animated_gif_comment_1, count);
1421
1422 IWICMetadataReader_Release(reader);
1423 }
1424
1425 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 3, &reader);
1426 ok(hr == S_OK, "GetReaderByIndex error %#x\n", hr);
1427
1428 if (SUCCEEDED(hr))
1429 {
1430 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
1431 ok(hr == S_OK, "GetMetadataFormat failed, hr=%#x\n", hr);
1432 ok(IsEqualGUID(&format, &GUID_MetadataFormatUnknown),
1433 "wrong metadata format %s\n", wine_dbgstr_guid(&format));
1434
1435 hr = IWICMetadataReader_GetCount(reader, &count);
1436 ok(hr == S_OK, "GetCount error %#x\n", hr);
1437 ok(count == ARRAY_SIZE(animated_gif_plain_1), "unexpected count %u\n", count);
1438
1439 compare_metadata(reader, animated_gif_plain_1, count);
1440
1441 IWICMetadataReader_Release(reader);
1442 }
1443
1444 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 4, &reader);
1445 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr);
1446
1447 IWICMetadataBlockReader_Release(blockreader);
1448 }
1449
1450 /* frame metadata block */
1451 hr = IWICBitmapDecoder_GetFrame(decoder, 1, &frame);
1452 ok(hr == S_OK, "GetFrame error %#x\n", hr);
1453
1454 hr = IWICBitmapFrameDecode_QueryInterface(frame, &IID_IWICMetadataBlockReader, (void **)&blockreader);
1455 ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* before Win7 */, "QueryInterface error %#x\n", hr);
1456
1457 if (SUCCEEDED(hr))
1458 {
1459 hr = IWICMetadataBlockReader_GetContainerFormat(blockreader, NULL);
1460 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr);
1461
1462 hr = IWICMetadataBlockReader_GetContainerFormat(blockreader, &format);
1463 ok(hr == S_OK, "GetContainerFormat error %#x\n", hr);
1464 ok(IsEqualGUID(&format, &GUID_ContainerFormatGif),
1465 "wrong container format %s\n", wine_dbgstr_guid(&format));
1466
1467 hr = IWICMetadataBlockReader_GetCount(blockreader, NULL);
1468 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr);
1469
1470 hr = IWICMetadataBlockReader_GetCount(blockreader, &count);
1471 ok(hr == S_OK, "GetCount error %#x\n", hr);
1472 ok(count == 4, "expected 4, got %u\n", count);
1473
1474 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 0, &reader);
1475 ok(hr == S_OK, "GetReaderByIndex error %#x\n", hr);
1476
1477 if (SUCCEEDED(hr))
1478 {
1479 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
1480 ok(hr == S_OK, "GetMetadataFormat failed, hr=%#x\n", hr);
1481 ok(IsEqualGUID(&format, &GUID_MetadataFormatIMD), /* Image Descriptor */
1482 "wrong metadata format %s\n", wine_dbgstr_guid(&format));
1483
1484 hr = IWICMetadataReader_GetCount(reader, &count);
1485 ok(hr == S_OK, "GetCount error %#x\n", hr);
1486 ok(count == ARRAY_SIZE(animated_gif_IMD), "unexpected count %u\n", count);
1487
1488 compare_metadata(reader, animated_gif_IMD, count);
1489
1490 IWICMetadataReader_Release(reader);
1491 }
1492
1493 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 1, &reader);
1494 ok(hr == S_OK, "GetReaderByIndex error %#x\n", hr);
1495
1496 if (SUCCEEDED(hr))
1497 {
1498 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
1499 ok(hr == S_OK, "GetMetadataFormat failed, hr=%#x\n", hr);
1500 ok(IsEqualGUID(&format, &GUID_MetadataFormatGifComment), /* Comment Extension */
1501 "wrong metadata format %s\n", wine_dbgstr_guid(&format));
1502
1503 hr = IWICMetadataReader_GetCount(reader, &count);
1504 ok(hr == S_OK, "GetCount error %#x\n", hr);
1505 ok(count == ARRAY_SIZE(animated_gif_comment_2), "unexpected count %u\n", count);
1506
1507 if (count == 1)
1508 compare_metadata(reader, animated_gif_comment_2, count);
1509
1510 IWICMetadataReader_Release(reader);
1511 }
1512
1513 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 2, &reader);
1514 ok(hr == S_OK, "GetReaderByIndex error %#x\n", hr);
1515
1516 if (SUCCEEDED(hr))
1517 {
1518 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
1519 ok(hr == S_OK, "GetMetadataFormat failed, hr=%#x\n", hr);
1520 ok(IsEqualGUID(&format, &GUID_MetadataFormatUnknown),
1521 "wrong metadata format %s\n", wine_dbgstr_guid(&format));
1522
1523 hr = IWICMetadataReader_GetCount(reader, &count);
1524 ok(hr == S_OK, "GetCount error %#x\n", hr);
1525 ok(count == ARRAY_SIZE(animated_gif_plain_2), "unexpected count %u\n", count);
1526
1527 compare_metadata(reader, animated_gif_plain_2, count);
1528
1529 IWICMetadataReader_Release(reader);
1530 }
1531
1532 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 3, &reader);
1533 ok(hr == S_OK, "GetReaderByIndex error %#x\n", hr);
1534
1535 if (SUCCEEDED(hr))
1536 {
1537 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
1538 ok(hr == S_OK, "GetMetadataFormat failed, hr=%#x\n", hr);
1539 ok(IsEqualGUID(&format, &GUID_MetadataFormatGCE), /* Graphic Control Extension */
1540 "wrong metadata format %s\n", wine_dbgstr_guid(&format));
1541
1542 hr = IWICMetadataReader_GetCount(reader, &count);
1543 ok(hr == S_OK, "GetCount error %#x\n", hr);
1544 ok(count == ARRAY_SIZE(animated_gif_GCE), "unexpected count %u\n", count);
1545
1546 compare_metadata(reader, animated_gif_GCE, count);
1547
1548 IWICMetadataReader_Release(reader);
1549 }
1550
1551 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 4, &reader);
1552 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr);
1553
1554 IWICMetadataBlockReader_Release(blockreader);
1555 }
1556
1557 hr = IWICBitmapDecoder_GetMetadataQueryReader(decoder, &queryreader);
1558 ok(hr == S_OK || broken(hr == WINCODEC_ERR_UNSUPPORTEDOPERATION) /* before Vista */,
1559 "GetMetadataQueryReader error %#x\n", hr);
1560 if (SUCCEEDED(hr))
1561 {
1562 static const struct
1563 {
1564 const char *query;
1565 HRESULT hr;
1566 UINT vt;
1567 } decoder_data[] =
1568 {
1569 { "/logscrdesc/Signature", S_OK, VT_UI1 | VT_VECTOR },
1570 { "/[0]logscrdesc/Signature", S_OK, VT_UI1 | VT_VECTOR },
1571 { "/logscrdesc/\\Signature", S_OK, VT_UI1 | VT_VECTOR },
1572 { "/Logscrdesc/\\signature", S_OK, VT_UI1 | VT_VECTOR },
1573 { "/logscrdesc/{str=signature}", S_OK, VT_UI1 | VT_VECTOR },
1574 { "/[0]logscrdesc/{str=signature}", S_OK, VT_UI1 | VT_VECTOR },
1575 { "/logscrdesc/{wstr=signature}", S_OK, VT_UI1 | VT_VECTOR },
1576 { "/[0]logscrdesc/{wstr=signature}", S_OK, VT_UI1 | VT_VECTOR },
1577 { "/appext/Application", S_OK, VT_UI1 | VT_VECTOR },
1578 { "/appext/{STR=APPlication}", S_OK, VT_UI1 | VT_VECTOR },
1579 { "/appext/{WSTR=APPlication}", S_OK, VT_UI1 | VT_VECTOR },
1580 { "/LogSCRdesC", S_OK, VT_UNKNOWN },
1581 { "/[0]LogSCRdesC", S_OK, VT_UNKNOWN },
1582 { "/appEXT", S_OK, VT_UNKNOWN },
1583 { "/[0]appEXT", S_OK, VT_UNKNOWN },
1584 { "grctlext", WINCODEC_ERR_PROPERTYNOTSUPPORTED, 0 },
1585 { "/imgdesc", WINCODEC_ERR_PROPERTYNOTFOUND, 0 },
1586 };
1587 static const WCHAR rootW[] = {'/',0};
1588 WCHAR name[256];
1589 UINT len, i, j;
1590 PROPVARIANT value;
1591 IWICMetadataQueryReader *meta_reader;
1592
1593 hr = IWICMetadataQueryReader_GetContainerFormat(queryreader, &format);
1594 ok(hr == S_OK, "GetContainerFormat error %#x\n", hr);
1595 ok(IsEqualGUID(&format, &GUID_ContainerFormatGif),
1596 "wrong container format %s\n", wine_dbgstr_guid(&format));
1597
1598 name[0] = 0;
1599 len = 0xdeadbeef;
1600 hr = IWICMetadataQueryReader_GetLocation(queryreader, 256, name, &len);
1601 ok(hr == S_OK, "GetLocation error %#x\n", hr);
1602 ok(len == 2, "expected 2, got %u\n", len);
1603 ok(!lstrcmpW(name, rootW), "expected '/', got %s\n", wine_dbgstr_w(name));
1604
1605 for (i = 0; i < ARRAY_SIZE(decoder_data); i++)
1606 {
1607 WCHAR queryW[256];
1608
1609 if (winetest_debug > 1)
1610 trace("query: %s\n", decoder_data[i].query);
1611 MultiByteToWideChar(CP_ACP, 0, decoder_data[i].query, -1, queryW, 256);
1612
1613 hr = IWICMetadataQueryReader_GetMetadataByName(queryreader, queryW, NULL);
1614 ok(hr == decoder_data[i].hr, "GetMetadataByName(%s) returned %#x, expected %#x\n", wine_dbgstr_w(queryW), hr, decoder_data[i].hr);
1615
1616 PropVariantInit(&value);
1617 hr = IWICMetadataQueryReader_GetMetadataByName(queryreader, queryW, &value);
1618 ok(hr == decoder_data[i].hr, "GetMetadataByName(%s) returned %#x, expected %#x\n", wine_dbgstr_w(queryW), hr, decoder_data[i].hr);
1619 ok(value.vt == decoder_data[i].vt, "expected %#x, got %#x\n", decoder_data[i].vt, value.vt);
1620 if (hr == S_OK && value.vt == VT_UNKNOWN)
1621 {
1622 hr = IUnknown_QueryInterface(value.punkVal, &IID_IWICMetadataQueryReader, (void **)&meta_reader);
1623 ok(hr == S_OK, "QueryInterface error %#x\n", hr);
1624
1625 name[0] = 0;
1626 len = 0xdeadbeef;
1627 hr = IWICMetadataQueryReader_GetLocation(meta_reader, 256, name, &len);
1628 ok(hr == S_OK, "GetLocation error %#x\n", hr);
1629 ok(len == lstrlenW(queryW) + 1, "expected %u, got %u\n", lstrlenW(queryW) + 1, len);
1630 ok(!lstrcmpW(name, queryW), "expected %s, got %s\n", wine_dbgstr_w(queryW), wine_dbgstr_w(name));
1631
1632 for (j = 0; j < ARRAY_SIZE(decoder_data); j++)
1633 {
1634 MultiByteToWideChar(CP_ACP, 0, decoder_data[j].query, -1, queryW, 256);
1635
1636 if (CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, queryW, len-1, name, len-1) == CSTR_EQUAL && decoder_data[j].query[len - 1] != 0)
1637 {
1638 if (winetest_debug > 1)
1639 trace("query: %s\n", wine_dbgstr_w(queryW + len - 1));
1641 hr = IWICMetadataQueryReader_GetMetadataByName(meta_reader, queryW + len - 1, &value);
1642 ok(hr == decoder_data[j].hr, "GetMetadataByName(%s) returned %#x, expected %#x\n", wine_dbgstr_w(queryW + len - 1), hr, decoder_data[j].hr);
1643 ok(value.vt == decoder_data[j].vt, "expected %#x, got %#x\n", decoder_data[j].vt, value.vt);
1644 }
1645 }
1646
1647 IWICMetadataQueryReader_Release(meta_reader);
1648 }
1649
1651 }
1652
1653 IWICMetadataQueryReader_Release(queryreader);
1654 }
1655
1656 hr = IWICBitmapFrameDecode_GetMetadataQueryReader(frame, &queryreader);
1657 ok(hr == S_OK || broken(hr == WINCODEC_ERR_UNSUPPORTEDOPERATION) /* before Vista */,
1658 "GetMetadataQueryReader error %#x\n", hr);
1659 if (SUCCEEDED(hr))
1660 {
1661 static const struct
1662 {
1663 const char *query;
1664 HRESULT hr;
1665 UINT vt;
1666 } frame_data[] =
1667 {
1668 { "/grctlext/Delay", S_OK, VT_UI2 },
1669 { "/[0]grctlext/Delay", S_OK, VT_UI2 },
1670 { "/grctlext/{str=delay}", S_OK, VT_UI2 },
1671 { "/[0]grctlext/{str=delay}", S_OK, VT_UI2 },
1672 { "/grctlext/{wstr=delay}", S_OK, VT_UI2 },
1673 { "/[0]grctlext/{wstr=delay}", S_OK, VT_UI2 },
1674 { "/imgdesc/InterlaceFlag", S_OK, VT_BOOL },
1675 { "/imgdesc/{STR=interlaceFLAG}", S_OK, VT_BOOL },
1676 { "/imgdesc/{WSTR=interlaceFLAG}", S_OK, VT_BOOL },
1677 { "/grctlext", S_OK, VT_UNKNOWN },
1678 { "/[0]grctlext", S_OK, VT_UNKNOWN },
1679 { "/imgdesc", S_OK, VT_UNKNOWN },
1680 { "/[0]imgdesc", S_OK, VT_UNKNOWN },
1681 { "/LogSCRdesC", WINCODEC_ERR_PROPERTYNOTFOUND, 0 },
1682 { "/appEXT", WINCODEC_ERR_PROPERTYNOTFOUND, 0 },
1683 { "/grctlext/{\\str=delay}", WINCODEC_ERR_WRONGSTATE, 0 },
1684 { "/grctlext/{str=\\delay}", S_OK, VT_UI2 },
1685 { "grctlext/Delay", WINCODEC_ERR_PROPERTYNOTSUPPORTED, 0 },
1686 };
1687 static const WCHAR rootW[] = {'/',0};
1688 static const WCHAR guidW[] = {'/','{','g','u','i','d','=','\\',0};
1689 static const WCHAR imgdescW[] = {'i','m','g','d','e','s','c',0};
1690 static const WCHAR ImgDescW[] = {'I','m','g','D','e','s','c',0};
1691 WCHAR name[256], queryW[256];
1692 UINT len, i;
1693 PROPVARIANT value;
1694 IWICMetadataQueryReader *meta_reader;
1695
1696 hr = IWICMetadataQueryReader_GetContainerFormat(queryreader, &format);
1697 ok(hr == S_OK, "GetContainerFormat error %#x\n", hr);
1698 ok(IsEqualGUID(&format, &GUID_ContainerFormatGif),
1699 "wrong container format %s\n", wine_dbgstr_guid(&format));
1700
1701 name[0] = 0;
1702 len = 0xdeadbeef;
1703 hr = IWICMetadataQueryReader_GetLocation(queryreader, 256, name, &len);
1704 ok(hr == S_OK, "GetLocation error %#x\n", hr);
1705 ok(len == 2, "expected 2, got %u\n", len);
1706 ok(!lstrcmpW(name, rootW), "expected '/', got %s\n", wine_dbgstr_w(name));
1707
1708 for (i = 0; i < ARRAY_SIZE(frame_data); i++)
1709 {
1710 if (winetest_debug > 1)
1711 trace("query: %s\n", frame_data[i].query);
1712 MultiByteToWideChar(CP_ACP, 0, frame_data[i].query, -1, queryW, 256);
1713 PropVariantInit(&value);
1714 hr = IWICMetadataQueryReader_GetMetadataByName(queryreader, queryW, &value);
1715 ok(hr == frame_data[i].hr, "GetMetadataByName(%s) returned %#x, expected %#x\n", wine_dbgstr_w(queryW), hr, frame_data[i].hr);
1716 ok(value.vt == frame_data[i].vt, "expected %#x, got %#x\n", frame_data[i].vt, value.vt);
1717 if (hr == S_OK && value.vt == VT_UNKNOWN)
1718 {
1719 hr = IUnknown_QueryInterface(value.punkVal, &IID_IWICMetadataQueryReader, (void **)&meta_reader);
1720 ok(hr == S_OK, "QueryInterface error %#x\n", hr);
1721
1722 name[0] = 0;
1723 len = 0xdeadbeef;
1724 hr = IWICMetadataQueryReader_GetLocation(meta_reader, 256, name, &len);
1725 ok(hr == S_OK, "GetLocation error %#x\n", hr);
1726 ok(len == lstrlenW(queryW) + 1, "expected %u, got %u\n", lstrlenW(queryW) + 1, len);
1727 ok(!lstrcmpW(name, queryW), "expected %s, got %s\n", wine_dbgstr_w(queryW), wine_dbgstr_w(name));
1728
1729 IWICMetadataQueryReader_Release(meta_reader);
1730 }
1731
1733 }
1734
1735 name[0] = 0;
1736 len = 0xdeadbeef;
1737 hr = WICMapGuidToShortName(&GUID_MetadataFormatIMD, 256, name, &len);
1738 ok(hr == S_OK, "WICMapGuidToShortName error %#x\n", hr);
1739 ok(!lstrcmpW(name, imgdescW), "wrong short name %s\n", wine_dbgstr_w(name));
1740
1741 format = GUID_NULL;
1743 ok(hr == S_OK, "WICMapGuidToShortName error %#x\n", hr);
1744 ok(IsEqualGUID(&format, &GUID_MetadataFormatIMD), "wrong guid %s\n", wine_dbgstr_guid(&format));
1745
1746 format = GUID_NULL;
1747 hr = WICMapShortNameToGuid(ImgDescW, &format);
1748 ok(hr == S_OK, "WICMapGuidToShortName error %#x\n", hr);
1749 ok(IsEqualGUID(&format, &GUID_MetadataFormatIMD), "wrong guid %s\n", wine_dbgstr_guid(&format));
1750
1751 lstrcpyW(queryW, guidW);
1752 StringFromGUID2(&GUID_MetadataFormatIMD, queryW + lstrlenW(queryW) - 1, 39);
1753 memcpy(queryW, guidW, sizeof(guidW) - 2);
1754 if (winetest_debug > 1)
1755 trace("query: %s\n", wine_dbgstr_w(queryW));
1756 PropVariantInit(&value);
1757 hr = IWICMetadataQueryReader_GetMetadataByName(queryreader, queryW, &value);
1758 ok(hr == S_OK, "GetMetadataByName(%s) error %#x\n", wine_dbgstr_w(queryW), hr);
1759 ok(value.vt == VT_UNKNOWN, "expected VT_UNKNOWN, got %#x\n", value.vt);
1761
1762 IWICMetadataQueryReader_Release(queryreader);
1763 }
1764
1765 IWICBitmapFrameDecode_Release(frame);
1766 IWICBitmapDecoder_Release(decoder);
1767}
1768
1769static void test_metadata_LSD(void)
1770{
1771 static const WCHAR LSD_name[] = {'L','o','g','i','c','a','l',' ','S','c','r','e','e','n',' ','D','e','s','c','r','i','p','t','o','r',' ','R','e','a','d','e','r',0};
1772 static const char LSD_data[] = "hello world!\x1\x2\x3\x4\xab\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf";
1773 static const struct test_data td[9] =
1774 {
1775 { VT_UI1|VT_VECTOR, 0, 6, {'w','o','r','l','d','!'}, NULL, { 'S','i','g','n','a','t','u','r','e',0 } },
1776 { VT_UI2, 0, 0, { 0x201 }, NULL, { 'W','i','d','t','h',0 } },
1777 { VT_UI2, 0, 0, { 0x403 }, NULL, { 'H','e','i','g','h','t',0 } },
1778 { VT_BOOL, 0, 0, { 1 }, NULL, { 'G','l','o','b','a','l','C','o','l','o','r','T','a','b','l','e','F','l','a','g',0 } },
1779 { VT_UI1, 0, 0, { 2 }, NULL, { 'C','o','l','o','r','R','e','s','o','l','u','t','i','o','n',0 } },
1780 { VT_BOOL, 0, 0, { 1 }, NULL, { 'S','o','r','t','F','l','a','g',0 } },
1781 { VT_UI1, 0, 0, { 3 }, NULL, { 'G','l','o','b','a','l','C','o','l','o','r','T','a','b','l','e','S','i','z','e',0 } },
1782 { VT_UI1, 0, 0, { 6 }, NULL, { 'B','a','c','k','g','r','o','u','n','d','C','o','l','o','r','I','n','d','e','x',0 } },
1783 { VT_UI1, 0, 0, { 7 }, NULL, { 'P','i','x','e','l','A','s','p','e','c','t','R','a','t','i','o',0 } }
1784 };
1786 HRESULT hr;
1787 IStream *stream;
1788 IWICPersistStream *persist;
1791 WCHAR name[64];
1792 UINT count, dummy;
1793 GUID format;
1794 CLSID id;
1795
1796 hr = CoCreateInstance(&CLSID_WICLSDMetadataReader, NULL, CLSCTX_INPROC_SERVER,
1797 &IID_IWICMetadataReader, (void **)&reader);
1798 ok(hr == S_OK || broken(hr == E_NOINTERFACE || hr == REGDB_E_CLASSNOTREG) /* before Win7 */,
1799 "CoCreateInstance error %#x\n", hr);
1800
1801 stream = create_stream(LSD_data, sizeof(LSD_data));
1802
1803 if (SUCCEEDED(hr))
1804 {
1805 pos.QuadPart = 6;
1806 hr = IStream_Seek(stream, pos, SEEK_SET, NULL);
1807 ok(hr == S_OK, "IStream_Seek error %#x\n", hr);
1808
1809 hr = IUnknown_QueryInterface(reader, &IID_IWICPersistStream, (void **)&persist);
1810 ok(hr == S_OK, "QueryInterface error %#x\n", hr);
1811
1812 hr = IWICPersistStream_Load(persist, stream);
1813 ok(hr == S_OK, "Load error %#x\n", hr);
1814
1815 IWICPersistStream_Release(persist);
1816 }
1817
1818 if (SUCCEEDED(hr))
1819 {
1820 hr = IWICMetadataReader_GetCount(reader, &count);
1821 ok(hr == S_OK, "GetCount error %#x\n", hr);
1822 ok(count == ARRAY_SIZE(td), "unexpected count %u\n", count);
1823
1825
1826 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
1827 ok(hr == S_OK, "GetMetadataFormat error %#x\n", hr);
1828 ok(IsEqualGUID(&format, &GUID_MetadataFormatLSD), "wrong format %s\n", wine_dbgstr_guid(&format));
1829
1830 hr = IWICMetadataReader_GetMetadataHandlerInfo(reader, &info);
1831 ok(hr == S_OK, "GetMetadataHandlerInfo error %#x\n", hr);
1832
1833 hr = IWICMetadataHandlerInfo_GetCLSID(info, &id);
1834 ok(hr == S_OK, "GetCLSID error %#x\n", hr);
1835 ok(IsEqualGUID(&id, &CLSID_WICLSDMetadataReader), "wrong CLSID %s\n", wine_dbgstr_guid(&id));
1836
1837 hr = IWICMetadataHandlerInfo_GetFriendlyName(info, 64, name, &dummy);
1838 ok(hr == S_OK, "GetFriendlyName error %#x\n", hr);
1839 ok(lstrcmpW(name, LSD_name) == 0, "wrong LSD reader name %s\n", wine_dbgstr_w(name));
1840
1841 IWICMetadataHandlerInfo_Release(info);
1842 IWICMetadataReader_Release(reader);
1843 }
1844
1845 IStream_Release(stream);
1846}
1847
1848static void test_metadata_IMD(void)
1849{
1850 static const WCHAR IMD_name[] = {'I','m','a','g','e',' ','D','e','s','c','r','i','p','t','o','r',' ','R','e','a','d','e','r',0};
1851 static const char IMD_data[] = "hello world!\x1\x2\x3\x4\x5\x6\x7\x8\xed\xa\xb\xc\xd\xe\xf";
1852 static const struct test_data td[8] =
1853 {
1854 { VT_UI2, 0, 0, { 0x201 }, NULL, { 'L','e','f','t',0 } },
1855 { VT_UI2, 0, 0, { 0x403 }, NULL, { 'T','o','p',0 } },
1856 { VT_UI2, 0, 0, { 0x605 }, NULL, { 'W','i','d','t','h',0 } },
1857 { VT_UI2, 0, 0, { 0x807 }, NULL, { 'H','e','i','g','h','t',0 } },
1858 { VT_BOOL, 0, 0, { 1 }, NULL, { 'L','o','c','a','l','C','o','l','o','r','T','a','b','l','e','F','l','a','g',0 } },
1859 { VT_BOOL, 0, 0, { 1 }, NULL, { 'I','n','t','e','r','l','a','c','e','F','l','a','g',0 } },
1860 { VT_BOOL, 0, 0, { 1 }, NULL, { 'S','o','r','t','F','l','a','g',0 } },
1861 { VT_UI1, 0, 0, { 5 }, NULL, { 'L','o','c','a','l','C','o','l','o','r','T','a','b','l','e','S','i','z','e',0 } }
1862 };
1864 HRESULT hr;
1865 IStream *stream;
1866 IWICPersistStream *persist;
1869 WCHAR name[64];
1870 UINT count, dummy;
1871 GUID format;
1872 CLSID id;
1873
1874 hr = CoCreateInstance(&CLSID_WICIMDMetadataReader, NULL, CLSCTX_INPROC_SERVER,
1875 &IID_IWICMetadataReader, (void **)&reader);
1876 ok(hr == S_OK || broken(hr == E_NOINTERFACE || hr == REGDB_E_CLASSNOTREG) /* before Win7 */,
1877 "CoCreateInstance error %#x\n", hr);
1878
1879 stream = create_stream(IMD_data, sizeof(IMD_data));
1880
1881 if (SUCCEEDED(hr))
1882 {
1883 pos.QuadPart = 12;
1884 hr = IStream_Seek(stream, pos, SEEK_SET, NULL);
1885 ok(hr == S_OK, "IStream_Seek error %#x\n", hr);
1886
1887 hr = IUnknown_QueryInterface(reader, &IID_IWICPersistStream, (void **)&persist);
1888 ok(hr == S_OK, "QueryInterface error %#x\n", hr);
1889
1890 hr = IWICPersistStream_Load(persist, stream);
1891 ok(hr == S_OK, "Load error %#x\n", hr);
1892
1893 IWICPersistStream_Release(persist);
1894 }
1895
1896 if (SUCCEEDED(hr))
1897 {
1898 hr = IWICMetadataReader_GetCount(reader, &count);
1899 ok(hr == S_OK, "GetCount error %#x\n", hr);
1900 ok(count == ARRAY_SIZE(td), "unexpected count %u\n", count);
1901
1903
1904 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
1905 ok(hr == S_OK, "GetMetadataFormat error %#x\n", hr);
1906 ok(IsEqualGUID(&format, &GUID_MetadataFormatIMD), "wrong format %s\n", wine_dbgstr_guid(&format));
1907
1908 hr = IWICMetadataReader_GetMetadataHandlerInfo(reader, &info);
1909 ok(hr == S_OK, "GetMetadataHandlerInfo error %#x\n", hr);
1910
1911 hr = IWICMetadataHandlerInfo_GetCLSID(info, &id);
1912 ok(hr == S_OK, "GetCLSID error %#x\n", hr);
1913 ok(IsEqualGUID(&id, &CLSID_WICIMDMetadataReader), "wrong CLSID %s\n", wine_dbgstr_guid(&id));
1914
1915 hr = IWICMetadataHandlerInfo_GetFriendlyName(info, 64, name, &dummy);
1916 ok(hr == S_OK, "GetFriendlyName error %#x\n", hr);
1917 ok(lstrcmpW(name, IMD_name) == 0, "wrong IMD reader name %s\n", wine_dbgstr_w(name));
1918
1919 IWICMetadataHandlerInfo_Release(info);
1920 IWICMetadataReader_Release(reader);
1921 }
1922
1923 IStream_Release(stream);
1924}
1925
1926static void test_metadata_GCE(void)
1927{
1928 static const WCHAR GCE_name[] = {'G','r','a','p','h','i','c',' ','C','o','n','t','r','o','l',' ','E','x','t','e','n','s','i','o','n',' ','R','e','a','d','e','r',0};
1929 static const char GCE_data[] = "hello world!\xa\x2\x3\x4\x5\x6\x7\x8\xed\xa\xb\xc\xd\xe\xf";
1930 static const struct test_data td[5] =
1931 {
1932 { VT_UI1, 0, 0, { 2 }, NULL, { 'D','i','s','p','o','s','a','l',0 } },
1933 { VT_BOOL, 0, 0, { 1 }, NULL, { 'U','s','e','r','I','n','p','u','t','F','l','a','g',0 } },
1934 { VT_BOOL, 0, 0, { 0 }, NULL, { 'T','r','a','n','s','p','a','r','e','n','c','y','F','l','a','g',0 } },
1935 { VT_UI2, 0, 0, { 0x302 }, NULL, { 'D','e','l','a','y',0 } },
1936 { VT_UI1, 0, 0, { 4 }, NULL, { 'T','r','a','n','s','p','a','r','e','n','t','C','o','l','o','r','I','n','d','e','x',0 } }
1937 };
1939 HRESULT hr;
1940 IStream *stream;
1941 IWICPersistStream *persist;
1944 WCHAR name[64];
1945 UINT count, dummy;
1946 GUID format;
1947 CLSID id;
1948
1949 hr = CoCreateInstance(&CLSID_WICGCEMetadataReader, NULL, CLSCTX_INPROC_SERVER,
1950 &IID_IWICMetadataReader, (void **)&reader);
1951 ok(hr == S_OK || broken(hr == E_NOINTERFACE || hr == REGDB_E_CLASSNOTREG) /* before Win7 */,
1952 "CoCreateInstance error %#x\n", hr);
1953
1954 stream = create_stream(GCE_data, sizeof(GCE_data));
1955
1956 if (SUCCEEDED(hr))
1957 {
1958 pos.QuadPart = 12;
1959 hr = IStream_Seek(stream, pos, SEEK_SET, NULL);
1960 ok(hr == S_OK, "IStream_Seek error %#x\n", hr);
1961
1962 hr = IUnknown_QueryInterface(reader, &IID_IWICPersistStream, (void **)&persist);
1963 ok(hr == S_OK, "QueryInterface error %#x\n", hr);
1964
1965 hr = IWICPersistStream_Load(persist, stream);
1966 ok(hr == S_OK, "Load error %#x\n", hr);
1967
1968 IWICPersistStream_Release(persist);
1969 }
1970
1971 if (SUCCEEDED(hr))
1972 {
1973 hr = IWICMetadataReader_GetCount(reader, &count);
1974 ok(hr == S_OK, "GetCount error %#x\n", hr);
1975 ok(count == ARRAY_SIZE(td), "unexpected count %u\n", count);
1976
1978
1979 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
1980 ok(hr == S_OK, "GetMetadataFormat error %#x\n", hr);
1981 ok(IsEqualGUID(&format, &GUID_MetadataFormatGCE), "wrong format %s\n", wine_dbgstr_guid(&format));
1982
1983 hr = IWICMetadataReader_GetMetadataHandlerInfo(reader, &info);
1984 ok(hr == S_OK, "GetMetadataHandlerInfo error %#x\n", hr);
1985
1986 hr = IWICMetadataHandlerInfo_GetCLSID(info, &id);
1987 ok(hr == S_OK, "GetCLSID error %#x\n", hr);
1988 ok(IsEqualGUID(&id, &CLSID_WICGCEMetadataReader), "wrong CLSID %s\n", wine_dbgstr_guid(&id));
1989
1990 hr = IWICMetadataHandlerInfo_GetFriendlyName(info, 64, name, &dummy);
1991 ok(hr == S_OK, "GetFriendlyName error %#x\n", hr);
1992 ok(lstrcmpW(name, GCE_name) == 0, "wrong GCE reader name %s\n", wine_dbgstr_w(name));
1993
1994 IWICMetadataHandlerInfo_Release(info);
1995 IWICMetadataReader_Release(reader);
1996 }
1997
1998 IStream_Release(stream);
1999}
2000
2001static void test_metadata_APE(void)
2002{
2003 static const WCHAR APE_name[] = {'A','p','p','l','i','c','a','t','i','o','n',' ','E','x','t','e','n','s','i','o','n',' ','R','e','a','d','e','r',0};
2004 static const char APE_data[] = { 0x21,0xff,0x0b,'H','e','l','l','o',' ','W','o','r','l','d',
2005 /*sub-block*/1,0x11,
2006 /*sub-block*/2,0x22,0x33,
2007 /*sub-block*/4,0x44,0x55,0x66,0x77,
2008 /*terminator*/0 };
2009 static const struct test_data td[2] =
2010 {
2011 { VT_UI1|VT_VECTOR, 0, 11, { 'H','e','l','l','o',' ','W','o','r','l','d' }, NULL, { 'A','p','p','l','i','c','a','t','i','o','n',0 } },
2012 { VT_UI1|VT_VECTOR, 0, 10, { 1,0x11,2,0x22,0x33,4,0x44,0x55,0x66,0x77 }, NULL, { 'D','a','t','a',0 } }
2013 };
2014 WCHAR dataW[] = { 'd','a','t','a',0 };
2015 HRESULT hr;
2016 IStream *stream;
2017 IWICPersistStream *persist;
2020 WCHAR name[64];
2021 UINT count, dummy, i;
2022 GUID format;
2023 CLSID clsid;
2024 PROPVARIANT id, value;
2025
2026 hr = CoCreateInstance(&CLSID_WICAPEMetadataReader, NULL, CLSCTX_INPROC_SERVER,
2027 &IID_IWICMetadataReader, (void **)&reader);
2028 ok(hr == S_OK || broken(hr == E_NOINTERFACE || hr == REGDB_E_CLASSNOTREG) /* before Win7 */,
2029 "CoCreateInstance error %#x\n", hr);
2030
2031 stream = create_stream(APE_data, sizeof(APE_data));
2032
2033 if (SUCCEEDED(hr))
2034 {
2035 hr = IUnknown_QueryInterface(reader, &IID_IWICPersistStream, (void **)&persist);
2036 ok(hr == S_OK, "QueryInterface error %#x\n", hr);
2037
2038 hr = IWICPersistStream_Load(persist, stream);
2039 ok(hr == S_OK, "Load error %#x\n", hr);
2040
2041 IWICPersistStream_Release(persist);
2042 }
2043
2044 if (SUCCEEDED(hr))
2045 {
2046 hr = IWICMetadataReader_GetCount(reader, &count);
2047 ok(hr == S_OK, "GetCount error %#x\n", hr);
2048 ok(count == ARRAY_SIZE(td), "unexpected count %u\n", count);
2049
2051
2052 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
2053 ok(hr == S_OK, "GetMetadataFormat error %#x\n", hr);
2054 ok(IsEqualGUID(&format, &GUID_MetadataFormatAPE), "wrong format %s\n", wine_dbgstr_guid(&format));
2055
2056 PropVariantInit(&value);
2057 id.vt = VT_LPWSTR;
2058 U(id).pwszVal = dataW;
2059
2060 hr = IWICMetadataReader_GetValue(reader, NULL, &id, &value);
2061 ok(hr == S_OK, "GetValue error %#x\n", hr);
2062 ok(value.vt == (VT_UI1|VT_VECTOR), "unexpected vt: %i\n", id.vt);
2063 ok(td[1].count == U(value).caub.cElems, "expected cElems %d, got %d\n", td[1].count, U(value).caub.cElems);
2064 for (i = 0; i < U(value).caub.cElems; i++)
2065 ok(td[1].value[i] == U(value).caub.pElems[i], "%u: expected value %#x/%#x, got %#x\n", i, (ULONG)td[1].value[i], (ULONG)(td[1].value[i] >> 32), U(value).caub.pElems[i]);
2067
2068 hr = IWICMetadataReader_GetMetadataHandlerInfo(reader, &info);
2069 ok(hr == S_OK, "GetMetadataHandlerInfo error %#x\n", hr);
2070
2071 hr = IWICMetadataHandlerInfo_GetCLSID(info, &clsid);
2072 ok(hr == S_OK, "GetCLSID error %#x\n", hr);
2073 ok(IsEqualGUID(&clsid, &CLSID_WICAPEMetadataReader), "wrong CLSID %s\n", wine_dbgstr_guid(&clsid));
2074
2075 hr = IWICMetadataHandlerInfo_GetFriendlyName(info, 64, name, &dummy);
2076 ok(hr == S_OK, "GetFriendlyName error %#x\n", hr);
2077 ok(lstrcmpW(name, APE_name) == 0, "wrong APE reader name %s\n", wine_dbgstr_w(name));
2078
2079 IWICMetadataHandlerInfo_Release(info);
2080 IWICMetadataReader_Release(reader);
2081 }
2082
2083 IStream_Release(stream);
2084}
2085
2087{
2088 static const WCHAR GIF_comment_name[] = {'C','o','m','m','e','n','t',' ','E','x','t','e','n','s','i','o','n',' ','R','e','a','d','e','r',0};
2089 static const char GIF_comment_data[] = { 0x21,0xfe,
2090 /*sub-block*/5,'H','e','l','l','o',
2091 /*sub-block*/1,' ',
2092 /*sub-block*/6,'W','o','r','l','d','!',
2093 /*terminator*/0 };
2094 static const struct test_data td[1] =
2095 {
2096 { VT_LPSTR, 0, 12, { 0 }, "Hello World!", { 'T','e','x','t','E','n','t','r','y',0 } }
2097 };
2098 WCHAR text_entryW[] = { 'T','E','X','T','E','N','T','R','Y',0 };
2099 HRESULT hr;
2100 IStream *stream;
2101 IWICPersistStream *persist;
2104 WCHAR name[64];
2105 UINT count, dummy;
2106 GUID format;
2107 CLSID clsid;
2108 PROPVARIANT id, value;
2109
2110 hr = CoCreateInstance(&CLSID_WICGifCommentMetadataReader, NULL, CLSCTX_INPROC_SERVER,
2111 &IID_IWICMetadataReader, (void **)&reader);
2112 ok(hr == S_OK || broken(hr == E_NOINTERFACE || hr == REGDB_E_CLASSNOTREG) /* before Win7 */,
2113 "CoCreateInstance error %#x\n", hr);
2114
2115 stream = create_stream(GIF_comment_data, sizeof(GIF_comment_data));
2116
2117 if (SUCCEEDED(hr))
2118 {
2119 hr = IUnknown_QueryInterface(reader, &IID_IWICPersistStream, (void **)&persist);
2120 ok(hr == S_OK, "QueryInterface error %#x\n", hr);
2121
2122 hr = IWICPersistStream_Load(persist, stream);
2123 ok(hr == S_OK, "Load error %#x\n", hr);
2124
2125 IWICPersistStream_Release(persist);
2126 }
2127
2128 if (SUCCEEDED(hr))
2129 {
2130 hr = IWICMetadataReader_GetCount(reader, &count);
2131 ok(hr == S_OK, "GetCount error %#x\n", hr);
2132 ok(count == ARRAY_SIZE(td), "unexpected count %u\n", count);
2133
2135
2136 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
2137 ok(hr == S_OK, "GetMetadataFormat error %#x\n", hr);
2138 ok(IsEqualGUID(&format, &GUID_MetadataFormatGifComment), "wrong format %s\n", wine_dbgstr_guid(&format));
2139
2140 PropVariantInit(&value);
2141 id.vt = VT_LPWSTR;
2142 U(id).pwszVal = text_entryW;
2143
2144 hr = IWICMetadataReader_GetValue(reader, NULL, &id, &value);
2145 ok(hr == S_OK, "GetValue error %#x\n", hr);
2146 ok(value.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt);
2147 ok(!strcmp(U(value).pszVal, "Hello World!"), "unexpected value: %s\n", U(value).pszVal);
2149
2150 hr = IWICMetadataReader_GetMetadataHandlerInfo(reader, &info);
2151 ok(hr == S_OK, "GetMetadataHandlerInfo error %#x\n", hr);
2152
2153 hr = IWICMetadataHandlerInfo_GetCLSID(info, &clsid);
2154 ok(hr == S_OK, "GetCLSID error %#x\n", hr);
2155 ok(IsEqualGUID(&clsid, &CLSID_WICGifCommentMetadataReader), "wrong CLSID %s\n", wine_dbgstr_guid(&clsid));
2156
2157 hr = IWICMetadataHandlerInfo_GetFriendlyName(info, 64, name, &dummy);
2158 ok(hr == S_OK, "GetFriendlyName error %#x\n", hr);
2159 ok(lstrcmpW(name, GIF_comment_name) == 0, "wrong APE reader name %s\n", wine_dbgstr_w(name));
2160
2161 IWICMetadataHandlerInfo_Release(info);
2162 IWICMetadataReader_Release(reader);
2163 }
2164
2165 IStream_Release(stream);
2166}
2167
2169{
2170 static const WCHAR unkW[] = { 'u','n','k',0 };
2171 static const WCHAR unknownW[] = { 'u','n','k','n','o','w','n',0 };
2172 HRESULT hr;
2173 UINT len;
2174 WCHAR name[16];
2175
2176 name[0] = 0;
2177 len = 0xdeadbeef;
2178 hr = WICMapGuidToShortName(&GUID_MetadataFormatUnknown, 8, name, &len);
2179 ok(hr == S_OK, "got %#x\n", hr);
2180 ok(len == 8, "got %u\n", len);
2181 ok(!lstrcmpW(name, unknownW), "got %s\n", wine_dbgstr_w(name));
2182
2183 name[0] = 0;
2184 hr = WICMapGuidToShortName(&GUID_MetadataFormatUnknown, 8, name, NULL);
2185 ok(hr == S_OK, "got %#x\n", hr);
2186 ok(!lstrcmpW(name, unknownW), "got %s\n", wine_dbgstr_w(name));
2187
2188 len = 0xdeadbeef;
2189 hr = WICMapGuidToShortName(&GUID_MetadataFormatUnknown, 8, NULL, &len);
2190 ok(hr == S_OK, "got %#x\n", hr);
2191 ok(len == 8, "got %u\n", len);
2192
2193 len = 0xdeadbeef;
2194 hr = WICMapGuidToShortName(&GUID_MetadataFormatUnknown, 0, NULL, &len);
2195 ok(hr == S_OK, "got %#x\n", hr);
2196 ok(len == 8, "got %u\n", len);
2197
2198 hr = WICMapGuidToShortName(&GUID_MetadataFormatUnknown, 0, NULL, NULL);
2199 ok(hr == S_OK, "got %#x\n", hr);
2200
2201 hr = WICMapGuidToShortName(&GUID_MetadataFormatUnknown, 8, NULL, NULL);
2202 ok(hr == S_OK, "got %#x\n", hr);
2203
2205 ok(hr == WINCODEC_ERR_PROPERTYNOTFOUND, "got %#x\n", hr);
2206
2207 name[0] = 0;
2208 len = 0xdeadbeef;
2209 hr = WICMapGuidToShortName(&GUID_MetadataFormatUnknown, 4, name, &len);
2211 ok(len == 0xdeadbeef, "got %u\n", len);
2212 ok(!lstrcmpW(name, unkW), "got %s\n", wine_dbgstr_w(name));
2213
2214 name[0] = 0;
2215 len = 0xdeadbeef;
2216 hr = WICMapGuidToShortName(&GUID_MetadataFormatUnknown, 0, name, &len);
2217 ok(hr == E_INVALIDARG, "got %#x\n", hr);
2218 ok(len == 0xdeadbeef, "got %u\n", len);
2219 ok(!name[0], "got %s\n", wine_dbgstr_w(name));
2220
2222 ok(hr == E_INVALIDARG, "got %#x\n", hr);
2223}
2224
2226{
2227 static const WCHAR unkW[] = { 'u','n','k',0 };
2228 static const WCHAR xmpW[] = { 'x','m','p',0 };
2229 static const WCHAR XmPW[] = { 'X','m','P',0 };
2230 static const WCHAR unknownW[] = { 'u','n','k','n','o','w','n',0 };
2231 HRESULT hr;
2232 GUID guid;
2233
2235 ok(hr == E_INVALIDARG, "got %#x\n", hr);
2236
2238 ok(hr == E_INVALIDARG, "got %#x\n", hr);
2239
2241 ok(hr == E_INVALIDARG, "got %#x\n", hr);
2242
2243 hr = WICMapShortNameToGuid(unkW, &guid);
2244 ok(hr == WINCODEC_ERR_PROPERTYNOTFOUND, "got %#x\n", hr);
2245
2247 ok(hr == S_OK, "got %#x\n", hr);
2248 ok(IsEqualGUID(&guid, &GUID_MetadataFormatUnknown), "got %s\n", wine_dbgstr_guid(&guid));
2249
2251 ok(hr == S_OK, "got %#x\n", hr);
2252 ok(IsEqualGUID(&guid, &GUID_MetadataFormatXMP), "got %s\n", wine_dbgstr_guid(&guid));
2253
2254 guid = GUID_NULL;
2255 hr = WICMapShortNameToGuid(XmPW, &guid);
2256 ok(hr == S_OK, "got %#x\n", hr);
2257 ok(IsEqualGUID(&guid, &GUID_MetadataFormatXMP), "got %s\n", wine_dbgstr_guid(&guid));
2258}
2259
2260static const GUID *guid_list[] =
2261{
2262 &GUID_ContainerFormatBmp,
2263 &GUID_ContainerFormatPng,
2264 &GUID_ContainerFormatIco,
2265 &GUID_ContainerFormatJpeg,
2266 &GUID_ContainerFormatTiff,
2267 &GUID_ContainerFormatGif,
2268 &GUID_ContainerFormatWmp,
2269 &GUID_MetadataFormatUnknown,
2270 &GUID_MetadataFormatIfd,
2271 &GUID_MetadataFormatSubIfd,
2272 &GUID_MetadataFormatExif,
2273 &GUID_MetadataFormatGps,
2274 &GUID_MetadataFormatInterop,
2275 &GUID_MetadataFormatApp0,
2276 &GUID_MetadataFormatApp1,
2277 &GUID_MetadataFormatApp13,
2278 &GUID_MetadataFormatIPTC,
2279 &GUID_MetadataFormatIRB,
2280 &GUID_MetadataFormat8BIMIPTC,
2281 &GUID_MetadataFormat8BIMResolutionInfo,
2282 &GUID_MetadataFormat8BIMIPTCDigest,
2283 &GUID_MetadataFormatXMP,
2284 &GUID_MetadataFormatThumbnail,
2285 &GUID_MetadataFormatChunktEXt,
2286 &GUID_MetadataFormatXMPStruct,
2287 &GUID_MetadataFormatXMPBag,
2288 &GUID_MetadataFormatXMPSeq,
2289 &GUID_MetadataFormatXMPAlt,
2290 &GUID_MetadataFormatLSD,
2291 &GUID_MetadataFormatIMD,
2292 &GUID_MetadataFormatGCE,
2293 &GUID_MetadataFormatAPE,
2294 &GUID_MetadataFormatJpegChrominance,
2295 &GUID_MetadataFormatJpegLuminance,
2296 &GUID_MetadataFormatJpegComment,
2297 &GUID_MetadataFormatGifComment,
2298 &GUID_MetadataFormatChunkgAMA,
2299 &GUID_MetadataFormatChunkbKGD,
2300 &GUID_MetadataFormatChunkiTXt,
2301 &GUID_MetadataFormatChunkcHRM,
2302 &GUID_MetadataFormatChunkhIST,
2303 &GUID_MetadataFormatChunkiCCP,
2304 &GUID_MetadataFormatChunksRGB,
2305 &GUID_MetadataFormatChunktIME
2306};
2307
2308static WCHAR rdf_scheme[] = { 'h','t','t','p',':','/','/','w','w','w','.','w','3','.','o','r','g','/','1','9','9','9','/','0','2','/','2','2','-','r','d','f','-','s','y','n','t','a','x','-','n','s','#',0 };
2309static WCHAR dc_scheme[] = { 'h','t','t','p',':','/','/','p','u','r','l','.','o','r','g','/','d','c','/','e','l','e','m','e','n','t','s','/','1','.','1','/',0 };
2310static WCHAR xmp_scheme[] = { 'h','t','t','p',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','x','a','p','/','1','.','0','/',0 };
2311static WCHAR xmpidq_scheme[] = { 'h','t','t','p',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','x','m','p','/','I','d','e','n','t','i','f','i','e','r','/','q','u','a','l','/','1','.','0','/',0 };
2312static WCHAR xmpRights_scheme[] = { 'h','t','t','p',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','x','a','p','/','1','.','0','/','r','i','g','h','t','s','/',0 };
2313static WCHAR xmpMM_scheme[] = { 'h','t','t','p',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','x','a','p','/','1','.','0','/','m','m','/',0 };
2314static WCHAR xmpBJ_scheme[] = { 'h','t','t','p',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','x','a','p','/','1','.','0','/','b','j','/',0 };
2315static WCHAR xmpTPg_scheme[] = { 'h','t','t','p',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','x','a','p','/','1','.','0','/','t','/','p','g','/',0 };
2316static WCHAR pdf_scheme[] = { 'h','t','t','p',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','p','d','f','/','1','.','3','/',0 };
2317static WCHAR photoshop_scheme[] = { 'h','t','t','p',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','p','h','o','t','o','s','h','o','p','/','1','.','0','/',0 };
2318static WCHAR tiff_scheme[] = { 'h','t','t','p',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','t','i','f','f','/','1','.','0','/',0 };
2319static WCHAR exif_scheme[] = { 'h','t','t','p',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','e','x','i','f','/','1','.','0','/',0 };
2320static WCHAR stDim_scheme[] = { 'h','t','t','p',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','x','a','p','/','1','.','0','/','s','T','y','p','e','/','D','i','m','e','n','s','i','o','n','s','#',0 };
2321static WCHAR xapGImg_scheme[] = { 'h','t','t','p',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','x','a','p','/','1','.','0','/','g','/','i','m','g','/',0 };
2322static WCHAR stEvt_scheme[] = { 'h','t','t','p',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','x','a','p','/','1','.','0','/','s','T','y','p','e','/','R','e','s','o','u','r','c','e','E','v','e','n','t','#',0 };
2323static WCHAR stRef_scheme[] = { 'h','t','t','p',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','x','a','p','/','1','.','0','/','s','T','y','p','e','/','R','e','s','o','u','r','c','e','R','e','f','#',0 };
2324static WCHAR stVer_scheme[] = { 'h','t','t','p',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','x','a','p','/','1','.','0','/','s','T','y','p','e','/','V','e','r','s','i','o','n','#',0 };
2325static WCHAR stJob_scheme[] = { 'h','t','t','p',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','x','a','p','/','1','.','0','/','s','T','y','p','e','/','J','o','b','#',0 };
2326static WCHAR aux_scheme[] = { 'h','t','t','p',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','e','x','i','f','/','1','.','0','/','a','u','x','/',0 };
2327static WCHAR crs_scheme[] = { 'h','t','t','p',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','c','a','m','e','r','a','-','r','a','w','-','s','e','t','t','i','n','g','s','/','1','.','0','/',0 };
2328static WCHAR xmpDM_scheme[] = { 'h','t','t','p',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','x','m','p','/','1','.','0','/','D','y','n','a','m','i','c','M','e','d','i','a','/',0 };
2329static WCHAR Iptc4xmpCore_scheme[] = { 'h','t','t','p',':','/','/','i','p','t','c','.','o','r','g','/','s','t','d','/','I','p','t','c','4','x','m','p','C','o','r','e','/','1','.','0','/','x','m','l','n','s','/',0 };
2330static WCHAR MicrosoftPhoto_scheme[] = { 'h','t','t','p',':','/','/','n','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','p','h','o','t','o','/','1','.','0','/',0 };
2331static WCHAR MP_scheme[] = { 'h','t','t','p',':','/','/','n','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','p','h','o','t','o','/','1','.','2','/',0 };
2332static WCHAR MPRI_scheme[] = { 'h','t','t','p',':','/','/','n','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','p','h','o','t','o','/','1','.','2','/','t','/','R','e','g','i','o','n','I','n','f','o','#',0 };
2333static WCHAR MPReg_scheme[] = { 'h','t','t','p',':','/','/','n','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','p','h','o','t','o','/','1','.','2','/','t','/','R','e','g','i','o','n','#',0 };
2334
2336{
2337 aux_scheme,
2338 rdf_scheme,
2339 dc_scheme,
2340 xmp_scheme,
2346 pdf_scheme,
2356 crs_scheme,
2360 MP_scheme,
2363};
2364
2366{
2367 static const WCHAR xmW[] = { 'x','m',0 };
2368 static const WCHAR xmpW[] = { 'x','m','p',0 };
2369 static WCHAR schemaW[] = { 'h','t','t','p',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','x','a','p','/','1','.','0','/',0 };
2370 static WCHAR SCHEMAW[] = { 'H','T','T','P',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','x','a','p','/','1','.','0','/',0 };
2371 HRESULT hr;
2372 UINT len, i, j;
2373 WCHAR name[16];
2374
2375 hr = WICMapSchemaToName(&GUID_MetadataFormatUnknown, NULL, 0, NULL, NULL);
2376 ok(hr == E_INVALIDARG, "got %#x\n", hr);
2377
2378 hr = WICMapSchemaToName(&GUID_MetadataFormatUnknown, schemaW, 0, NULL, NULL);
2379 ok(hr == E_INVALIDARG, "got %#x\n", hr);
2380
2381 hr = WICMapSchemaToName(&GUID_MetadataFormatUnknown, schemaW, 0, NULL, &len);
2382 ok(hr == WINCODEC_ERR_PROPERTYNOTFOUND, "got %#x\n", hr);
2383
2384 hr = WICMapSchemaToName(NULL, schemaW, 0, NULL, &len);
2385 ok(hr == E_INVALIDARG, "got %#x\n", hr);
2386
2387 hr = WICMapSchemaToName(&GUID_MetadataFormatXMP, schemaW, 0, NULL, NULL);
2388 ok(hr == E_INVALIDARG, "got %#x\n", hr);
2389
2390 len = 0xdeadbeef;
2391 hr = WICMapSchemaToName(&GUID_MetadataFormatXMP, schemaW, 0, NULL, &len);
2392 ok(hr == S_OK, "got %#x\n", hr);
2393 ok(len == 4, "got %u\n", len);
2394
2395 len = 0xdeadbeef;
2396 hr = WICMapSchemaToName(&GUID_MetadataFormatXMP, schemaW, 4, NULL, &len);
2397 ok(hr == S_OK, "got %#x\n", hr);
2398 ok(len == 4, "got %u\n", len);
2399
2400 len = 0xdeadbeef;
2401 hr = WICMapSchemaToName(&GUID_MetadataFormatXMP, SCHEMAW, 0, NULL, &len);
2402 ok(hr == WINCODEC_ERR_PROPERTYNOTFOUND, "got %#x\n", hr);
2403 ok(len == 0xdeadbeef, "got %u\n", len);
2404
2405 name[0] = 0;
2406 len = 0xdeadbeef;
2407 hr = WICMapSchemaToName(&GUID_MetadataFormatXMP, schemaW, 4, name, &len);
2408 ok(hr == S_OK, "got %#x\n", hr);
2409 ok(len == 4, "got %u\n", len);
2410 ok(!lstrcmpW(name, xmpW), "got %s\n", wine_dbgstr_w(name));
2411
2412 len = 0xdeadbeef;
2413 hr = WICMapSchemaToName(&GUID_MetadataFormatXMP, schemaW, 0, name, &len);
2414 ok(hr == E_INVALIDARG, "got %#x\n", hr);
2415 ok(len == 0xdeadbeef, "got %u\n", len);
2416
2417 name[0] = 0;
2418 len = 0xdeadbeef;
2419 hr = WICMapSchemaToName(&GUID_MetadataFormatXMP, schemaW, 3, name, &len);
2421 ok(len == 0xdeadbeef, "got %u\n", len);
2422 ok(!lstrcmpW(name, xmW), "got %s\n", wine_dbgstr_w(name));
2423
2424 hr = WICMapSchemaToName(&GUID_MetadataFormatXMP, schemaW, 4, name, NULL);
2425 ok(hr == E_INVALIDARG, "got %#x\n", hr);
2426
2427 /* Check whether modern schemas are supported */
2428 hr = WICMapSchemaToName(&GUID_MetadataFormatXMP, schema_list[0], 0, NULL, &len);
2430 {
2431 win_skip("Modern schemas are not supported\n");
2432 return;
2433 }
2434
2435 for (i = 0; i < ARRAY_SIZE(guid_list); i++)
2436 {
2437 for (j = 0; j < ARRAY_SIZE(schema_list); j++)
2438 {
2440 if (IsEqualGUID(guid_list[i], &GUID_MetadataFormatXMP) ||
2441 IsEqualGUID(guid_list[i], &GUID_MetadataFormatXMPStruct))
2442 {
2443 ok(hr == S_OK, "%u: %u: format %s does not support schema %s\n",
2445 }
2446 else
2447 {
2448 ok(hr == WINCODEC_ERR_PROPERTYNOTFOUND, "%u: %u: format %s supports schema %s\n",
2450 }
2451 }
2452 }
2453}
2454
2456{
2457 const char *schema, *id_str;
2459};
2460
2462{
2465 const struct metadata_item *item;
2466};
2467
2469{
2472 const struct metadata_block *block;
2473};
2474
2475static const struct metadata *current_metadata;
2477
2478static char the_best[] = "The Best";
2479static char the_worst[] = "The Worst";
2480
2482{
2483 trace("%p,%s,%p\n", iface, wine_dbgstr_guid(iid), out);
2484
2485 if (IsEqualIID(iid, &IID_IUnknown) ||
2486 IsEqualIID(iid, &IID_IWICMetadataReader))
2487 {
2488 *out = iface;
2489 return S_OK;
2490 }
2491
2492 ok(0, "unknown iid %s\n", wine_dbgstr_guid(iid));
2493
2494 *out = NULL;
2495 return E_NOINTERFACE;
2496}
2497
2499{
2500 return 2;
2501}
2502
2504{
2505 return 1;
2506}
2507
2509{
2510 trace("%p,%p\n", iface, format);
2511
2512 ok(current_metadata_block != NULL, "current_metadata_block can't be NULL\n");
2513 if (!current_metadata_block) return E_POINTER;
2514
2515 *format = *current_metadata_block->metadata_format;
2516 return S_OK;
2517}
2518
2520{
2521 ok(0, "not implemented\n");
2522 return E_NOTIMPL;
2523}
2524
2526{
2527 trace("%p,%p\n", iface, count);
2528
2529 ok(current_metadata_block != NULL, "current_metadata_block can't be NULL\n");
2530 if (!current_metadata_block) return E_POINTER;
2531
2532 *count = current_metadata_block->count;
2533 return S_OK;
2534}
2535
2536static HRESULT WINAPI mdr_GetValueByIndex(IWICMetadataReader *iface, UINT index, PROPVARIANT *schema, PROPVARIANT *id, PROPVARIANT *value)
2537{
2538 ok(0, "not implemented\n");
2539 return E_NOTIMPL;
2540}
2541
2542static char *get_temp_buffer(int size)
2543{
2544 static char buf[16][256];
2545 static int idx;
2546 char *p;
2547
2548 assert(size < 256);
2549
2550 p = buf[idx & 0x0f];
2551 idx++;
2552 return p;
2553}
2554
2555static const char *wine_dbgstr_propvariant(const PROPVARIANT *var)
2556{
2557 char *ret;
2558
2559 if (!var) return "(null)";
2560
2561 switch (var->vt)
2562 {
2563 case VT_LPWSTR:
2564 ret = get_temp_buffer(lstrlenW(U(*var).pwszVal) + 16);
2565 sprintf(ret, "(VT_LPWSTR:%s)", wine_dbgstr_w(U(*var).pwszVal));
2566 break;
2567
2568 case VT_LPSTR:
2569 ret = get_temp_buffer(lstrlenA(U(*var).pszVal) + 16);
2570 sprintf(ret, "(VT_LPSTR:%s)", U(*var).pszVal);
2571 break;
2572
2573 default:
2574 ret = get_temp_buffer(16);
2575 sprintf(ret, "(vt:%u)", var->vt);
2576 break;
2577 }
2578
2579 return ret;
2580}
2581
2582static int propvar_cmp(const PROPVARIANT *v1, LONGLONG value2)
2583{
2584 LONGLONG value1;
2585
2586 if (PropVariantToInt64(v1, &value1) != S_OK) return -1;
2587
2588 value1 -= value2;
2589 if (value1) return value1 < 0 ? -1 : 1;
2590 return 0;
2591}
2592
2593static HRESULT WINAPI mdr_GetValue(IWICMetadataReader *iface, const PROPVARIANT *schema, const PROPVARIANT *id, PROPVARIANT *value)
2594{
2595 UINT i;
2596
2598
2599 ok(current_metadata_block != NULL, "current_metadata_block can't be NULL\n");
2600 if (!current_metadata_block) return E_POINTER;
2601
2602 ok(schema != NULL && id != NULL && value != NULL, "%p, %p, %p should not be NULL\n", schema, id, value);
2603
2604 for (i = 0; i < current_metadata_block->count; i++)
2605 {
2606 if (schema->vt != VT_EMPTY)
2607 {
2608 if (!current_metadata_block->item[i].schema)
2609 continue;
2610
2611 switch (schema->vt)
2612 {
2613 case VT_LPSTR:
2614 if (lstrcmpA(U(*schema).pszVal, current_metadata_block->item[i].schema) != 0)
2615 continue;
2616 break;
2617
2618 case VT_LPWSTR:
2619 {
2620 char schemaA[256];
2621 WideCharToMultiByte(CP_ACP, 0, U(*schema).pwszVal, -1, schemaA, sizeof(schemaA), NULL, NULL);
2622 if (lstrcmpA(schemaA, current_metadata_block->item[i].schema) != 0)
2623 continue;
2624 break;
2625 }
2626
2627 default:
2628 ok(0, "unsupported schema vt %u\n", schema->vt);
2629 continue;
2630 }
2631 }
2632 else if (current_metadata_block->item[i].schema)
2633 continue;
2634
2635 switch (id->vt)
2636 {
2637 case VT_LPSTR:
2638 if (current_metadata_block->item[i].id_str)
2639 {
2640 if (!lstrcmpA(U(*id).pszVal, current_metadata_block->item[i].id_str))
2641 {
2642 value->vt = VT_LPSTR;
2643 U(*value).pszVal = the_best;
2644 return S_OK;
2645 }
2646 break;
2647 }
2648 break;
2649
2650 case VT_LPWSTR:
2651 if (current_metadata_block->item[i].id_str)
2652 {
2653 char idA[256];
2654 WideCharToMultiByte(CP_ACP, 0, U(*id).pwszVal, -1, idA, sizeof(idA), NULL, NULL);
2655 if (!lstrcmpA(idA, current_metadata_block->item[i].id_str))
2656 {
2657 value->vt = VT_LPSTR;
2658 U(*value).pszVal = the_worst;
2659 return S_OK;
2660 }
2661 break;
2662 }
2663 break;
2664
2665 case VT_CLSID:
2666 if (IsEqualGUID(U(*id).puuid, &GUID_MetadataFormatXMP) ||
2667 IsEqualGUID(U(*id).puuid, &GUID_ContainerFormatTiff))
2668 {
2669 value->vt = VT_UNKNOWN;
2670 value->punkVal = (IUnknown *)iface;
2671 return S_OK;
2672 }
2673 break;
2674
2675 default:
2676 if (!propvar_cmp(id, current_metadata_block->item[i].id))
2677 {
2678 value->vt = current_metadata_block->item[i].type;
2679 U(*value).uiVal = current_metadata_block->item[i].value;
2680 return S_OK;
2681 }
2682 break;
2683 }
2684 }
2685
2686 return 0xdeadbeef;
2687}
2688
2690{
2691 ok(0, "not implemented\n");
2692 return E_NOTIMPL;
2693}
2694
2695static const IWICMetadataReaderVtbl mdr_vtbl =
2696{
2698 mdr_AddRef,
2706};
2707
2709
2711{
2712 if (IsEqualIID(iid, &IID_IUnknown) ||
2713 IsEqualIID(iid, &IID_IWICMetadataBlockReader))
2714 {
2715 *out = iface;
2716 return S_OK;
2717 }
2718
2719 /* Windows 8/10 query for some undocumented IID */
2720 if (!IsEqualIID(iid, &IID_MdbrUnknown))
2721 ok(0, "unknown iid %s\n", wine_dbgstr_guid(iid));
2722
2723 *out = NULL;
2724 return E_NOINTERFACE;
2725}
2726
2728{
2729 return 2;
2730}
2731
2733{
2734 return 1;
2735}
2736
2738{
2739 trace("%p,%p\n", iface, format);
2740
2741 ok(current_metadata != NULL, "current_metadata can't be NULL\n");
2742 if (!current_metadata) return E_POINTER;
2743
2744 *format = *current_metadata->container_format;
2745 return S_OK;
2746}
2747
2749{
2750 trace("%p,%p\n", iface, count);
2751
2752 ok(current_metadata != NULL, "current_metadata can't be NULL\n");
2753 if (!current_metadata) return E_POINTER;
2754
2755 *count = current_metadata->count;
2756 return S_OK;
2757}
2758
2760{
2761 trace("%p,%u,%p\n", iface, index, out);
2762
2763 *out = NULL;
2764
2765 ok(current_metadata != NULL, "current_metadata can't be NULL\n");
2766 if (!current_metadata) return E_POINTER;
2767
2768 if (index < current_metadata->count)
2769 {
2771 *out = &mdr;
2772 return S_OK;
2773 }
2774
2776 return E_INVALIDARG;
2777}
2778
2780{
2781 ok(0, "not implemented\n");
2782 return E_NOTIMPL;
2783}
2784
2785static const IWICMetadataBlockReaderVtbl mdbr_vtbl =
2786{
2794};
2795
2797
2798static const char xmp[] = "http://ns.adobe.com/xap/1.0/";
2799static const char dc[] = "http://purl.org/dc/elements/1.1/";
2800static const char tiff[] = "http://ns.adobe.com/tiff/1.0/";
2801
2802static const struct metadata_item item1[] =
2803{
2804 { NULL, NULL, 1, 2, 3 }
2805};
2806
2807static const struct metadata_item item2[] =
2808{
2809 { NULL, NULL, 1, 2, 3 },
2810 { "xmp", "Rating", 4, 5, 6 },
2811 { NULL, "Rating", 7, 8, 9 }
2812};
2813
2814static const struct metadata_item item3[] =
2815{
2816 { NULL, NULL, 1, 2, 3 },
2817 { NULL, NULL, 4, 5, 6 },
2818 { NULL, NULL, 7, 8, 9 },
2819 { NULL, NULL, 10, 11, 12 }
2820};
2821
2822static const struct metadata_item item4[] =
2823{
2824 { NULL, NULL, 1, 2, 3 },
2825 { xmp, "Rating", 4, 5, 6 },
2826 { dc, NULL, 7, 8, 9 },
2827 { tiff, NULL, 10, 11, 12 },
2828 { NULL, "RATING", 13, 14, 15 },
2829 { NULL, "R}ATING", 16, 17, 18 },
2830 { NULL, "xmp", 19, 20, 21 }
2831};
2832
2833static const struct metadata_block block1[] =
2834{
2835 { &GUID_MetadataFormatIfd, 1, item1 }
2836};
2837
2838static const struct metadata_block block2[] =
2839{
2840 { &GUID_MetadataFormatXMP, 1, item1 },
2841 { &GUID_MetadataFormatIfd, 3, item2 }
2842};
2843
2844static const struct metadata_block block3[] =
2845{
2846 { &GUID_MetadataFormatXMP, 1, item1 },
2847 { &GUID_MetadataFormatIfd, 3, item2 },
2848 { &GUID_MetadataFormatXMP, 4, item3 },
2849 { &GUID_MetadataFormatXMP, 7, item4 },
2850 { &GUID_MetadataFormatIfd, 7, item4 }
2851};
2852
2853static const struct metadata data1 =
2854{
2855 &GUID_ContainerFormatGif,
2856 1, block1
2857};
2858
2859static const struct metadata data2 =
2860{
2861 &GUID_ContainerFormatTiff,
2862 2, block2
2863};
2864
2865static const struct metadata data3 =
2866{
2867 &GUID_ContainerFormatPng,
2868 5, block3
2869};
2870
2871static void test_queryreader(void)
2872{
2873 static const char q1[] = "/ifd/{uchar=1}";
2874 static const char q2[] = "/ifd/xmp:{long=4}";
2875 static const char q3[] = "/ifd/{str=xmp}:{uint=4}";
2876 static const char q4[] = "/xmp/{char=7}";
2877 static const char q5[] = "/[1]xmp/{short=7}";
2878 static const char q6[] = "/[1]ifd/{str=dc}:{uint=7}";
2879 static const char q7[] = "/[1]ifd/{str=http://purl.org/dc/elements/1.1/}:{longlong=7}";
2880 static const char q8[] = "/[1]ifd/{str=http://ns.adobe.com/tiff/1.0/}:{int=10}";
2881 static const char q9[] = "/[2]xmp/xmp:{ulong=4}";
2882 static const char q10[] = "/[2]xmp/{str=xmp}:{ulong=4}";
2883 static const char q11[] = "/xmp";
2884 static const char q12[] = "/ifd/xmp";
2885 static const char q13[] = "/ifd/xmp/tiff";
2886 static const char q14[] = "/[0]ifd/[0]xmp/[0]tiff";
2887 static const char q15[] = "/[*]xmp";
2888
2889 static const char q20[] = "/ifd/\\Rating";
2890 static const char q21[] = "/[0]ifd/Rating";
2891 static const char q22[] = "/[2]xmp/xmp:{str=Rating}";
2892 static const char q23[] = "/[2]xmp/xmp:Rating";
2893
2894 static const char q24[] = "/[1]ifd/{str=http://ns.adobe.com/xap/1.0/}:Rating";
2895 static const char q25[] = "/[1]ifd/{str=http://ns.adobe.com/xap/1.0/}:{str=Rating}";
2896 static const char q26[] = "/[1]ifd/{wstr=\\RATING}";
2897 static const char q27[] = "/[1]ifd/{str=R\\ATING}";
2898 static const char q28[] = "/[1]ifd/{str=R\\}ATING}";
2899
2900 static const char q40[] = "[0]/ifd/Rating";
2901 static const char q41[] = "/[+1]ifd/Rating";
2902 static const char q42[] = "/[-1]ifd/Rating";
2903 static const char q43[] = "/ifd/{\\str=Rating}";
2904 static const char q44[] = "/ifd/{badtype=0}";
2905 static const char q45[] = "/ifd/{uint=0x1234}";
2906 static const char q46[] = "/ifd/[0]Rating";
2907 static const char q47[] = "/ifd/[*]Rating";
2908 static const struct
2909 {
2910 BOOL todo;
2911 const struct metadata *data;
2912 const char *query;
2913 HRESULT hr;
2914 UINT vt, value;
2915 const char *str_value;
2916 } test_data[] =
2917 {
2918 { FALSE, &data1, q1, S_OK, 2, 3, NULL },
2919 { FALSE, &data2, q2, S_OK, 5, 6, NULL },
2920 { FALSE, &data2, q3, S_OK, 5, 6, NULL },
2921 { FALSE, &data3, q4, 0xdeadbeef },
2922 { FALSE, &data3, q5, S_OK, 8, 9, NULL },
2923 { FALSE, &data3, q6, 0xdeadbeef },
2924 { FALSE, &data3, q7, S_OK, 8, 9, NULL },
2925 { FALSE, &data3, q8, S_OK, 11, 12, NULL },
2926 { FALSE, &data3, q9, S_OK, 5, 6, NULL },
2927 { FALSE, &data3, q10, 0xdeadbeef },
2928
2929 { FALSE, &data3, q11, S_OK, VT_UNKNOWN, 0, NULL },
2930 { FALSE, &data3, q12, S_OK, VT_UNKNOWN, 0, NULL },
2931 { FALSE, &data3, q13, S_OK, VT_UNKNOWN, 0, NULL },
2932 { FALSE, &data3, q14, S_OK, VT_UNKNOWN, 0, NULL },
2933 { TRUE, &data3, q15, S_OK, VT_LPSTR, 0, the_worst },
2934
2935 { FALSE, &data3, q20, S_OK, VT_LPSTR, 0, the_worst },
2936 { FALSE, &data3, q21, S_OK, VT_LPSTR, 0, the_worst },
2937 { FALSE, &data3, q22, S_OK, VT_LPSTR, 0, the_best },
2938 { FALSE, &data3, q23, S_OK, VT_LPSTR, 0, the_worst },
2939 { FALSE, &data3, q24, S_OK, VT_LPSTR, 0, the_worst },
2940 { FALSE, &data3, q25, S_OK, VT_LPSTR, 0, the_best },
2941 { FALSE, &data3, q26, S_OK, VT_LPSTR, 0, the_worst },
2942 { FALSE, &data3, q27, S_OK, VT_LPSTR, 0, the_best },
2943 { FALSE, &data3, q28, S_OK, VT_LPSTR, 0, the_best },
2944
2950 { TRUE, &data1, q45, DISP_E_TYPEMISMATCH },
2951 { TRUE, &data1, q46, E_INVALIDARG },
2953 };
2954 WCHAR queryW[256];
2955 HRESULT hr;
2958 GUID format;
2959 PROPVARIANT value;
2960 UINT i;
2961
2962 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
2963 &IID_IWICComponentFactory, (void **)&factory);
2964 ok(hr == S_OK, "CoCreateInstance error %#x\n", hr);
2965
2966 hr = IWICComponentFactory_CreateQueryReaderFromBlockReader(factory, &mdbr, &reader);
2967 ok(hr == S_OK, "CreateQueryReaderFromBlockReader error %#x\n", hr);
2968
2969 for (i = 0; i < ARRAY_SIZE(test_data); i++)
2970 {
2972
2973 hr = IWICMetadataQueryReader_GetContainerFormat(reader, &format);
2974 ok(hr == S_OK, "%u: GetContainerFormat error %#x\n", i, hr);
2975 ok(IsEqualGUID(&format, test_data[i].data->container_format), "%u: expected %s, got %s\n",
2976 i, wine_dbgstr_guid(test_data[i].data->container_format), wine_dbgstr_guid(&format));
2977
2978 MultiByteToWideChar(CP_ACP, 0, test_data[i].query, -1, queryW, 256);
2979 PropVariantInit(&value);
2980 hr = IWICMetadataQueryReader_GetMetadataByName(reader, queryW, &value);
2982 ok(hr == test_data[i].hr, "%u: expected %#x, got %#x\n", i, test_data[i].hr, hr);
2983 if (hr == S_OK)
2984 {
2985 ok(value.vt == test_data[i].vt, "%u: expected %u, got %u\n", i, test_data[i].vt, value.vt);
2986 if (test_data[i].vt == value.vt)
2987 {
2988 if (value.vt == VT_UNKNOWN)
2989 {
2990 IWICMetadataQueryReader *new_reader;
2991 WCHAR location[256];
2992 UINT len;
2993
2994 hr = IUnknown_QueryInterface(value.punkVal, &IID_IWICMetadataQueryReader, (void **)&new_reader);
2995 ok(hr == S_OK, "QueryInterface error %#x\n", hr);
2996
2997 location[0] = 0;
2998 len = 0xdeadbeef;
2999 hr = IWICMetadataQueryReader_GetLocation(new_reader, 256, location, &len);
3000 ok(hr == S_OK, "GetLocation error %#x\n", hr);
3001 ok(len == lstrlenW(queryW) + 1, "expected %u, got %u\n", lstrlenW(queryW) + 1, len);
3002 ok(!lstrcmpW(location, queryW), "expected %s, got %s\n", wine_dbgstr_w(queryW), wine_dbgstr_w(location));
3003
3004 hr = IWICMetadataQueryReader_GetLocation(new_reader, 256, location, NULL);
3005 ok(hr == E_INVALIDARG, "got %#x\n", hr);
3006
3007 location[0] = 0;
3008 len = 0xdeadbeef;
3009 hr = IWICMetadataQueryReader_GetLocation(new_reader, 3, location, &len);
3010 ok(hr == WINCODEC_ERR_INSUFFICIENTBUFFER, "got %#x\n", hr);
3011 ok(len == 0xdeadbeef, "got %u\n", len);
3012 ok(!location[0], "got %s\n", wine_dbgstr_w(location));
3013
3014 location[0] = 0;
3015 len = 0xdeadbeef;
3016 hr = IWICMetadataQueryReader_GetLocation(new_reader, 0, location, &len);
3017 ok(hr == WINCODEC_ERR_INSUFFICIENTBUFFER, "got %#x\n", hr);
3018 ok(len == 0xdeadbeef, "got %u\n", len);
3019 ok(!location[0], "got %s\n", wine_dbgstr_w(location));
3020
3021 len = 0xdeadbeef;
3022 hr = IWICMetadataQueryReader_GetLocation(new_reader, 0, NULL, &len);
3023 ok(hr == S_OK, "GetLocation error %#x\n", hr);
3024 ok(len == lstrlenW(queryW) + 1, "expected %u, got %u\n", lstrlenW(queryW) + 1, len);
3025
3026 len = 0xdeadbeef;
3027 hr = IWICMetadataQueryReader_GetLocation(new_reader, 3, NULL, &len);
3028 ok(hr == S_OK, "GetLocation error %#x\n", hr);
3029 ok(len == lstrlenW(queryW) + 1, "expected %u, got %u\n", lstrlenW(queryW) + 1, len);
3030
3031 hr = IWICMetadataQueryReader_GetLocation(new_reader, 0, NULL, NULL);
3032 ok(hr == E_INVALIDARG, "got %#x\n", hr);
3033
3034 IWICMetadataQueryReader_Release(new_reader);
3036 }
3037 else if (value.vt == VT_LPSTR)
3038 ok(!lstrcmpA(U(value).pszVal, test_data[i].str_value), "%u: expected %s, got %s\n",
3039 i, test_data[i].str_value, U(value).pszVal);
3040 else
3041 ok(U(value).uiVal == test_data[i].value, "%u: expected %u, got %u\n",
3042 i, test_data[i].value, U(value).uiVal);
3043 }
3044
3045 /*
3046 * Do NOT call PropVariantClear(&value) for fake value types.
3047 */
3048 }
3049 }
3050
3051 IWICMetadataQueryReader_Release(reader);
3052 IWICComponentFactory_Release(factory);
3053}
3054
3056{
3058
3077
3079}
#define broken(x)
Definition: _sntprintf.h:21
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define START_TEST(x)
Definition: atltest.h:75
#define index(s, c)
Definition: various.h:29
#define ARRAY_SIZE(A)
Definition: main.h:33
#define U(x)
Definition: wordpad.c:45
const GUID IID_IUnknown
w ll
Definition: byte_order.h:167
r l[0]
Definition: byte_order.h:168
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_NOTIMPL
Definition: ddrawi.h:99
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
unsigned int idx
Definition: utils.c:41
static const WCHAR rootW[]
Definition: chain.c:69
#define GetProcessHeap()
Definition: compat.h:736
#define CP_ACP
Definition: compat.h:109
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
#define lstrcpyW
Definition: compat.h:749
#define WideCharToMultiByte
Definition: compat.h:111
#define MultiByteToWideChar
Definition: compat.h:110
@ VT_BLOB
Definition: compat.h:2330
@ VT_UI8
Definition: compat.h:2315
@ VT_LPSTR
Definition: compat.h:2324
@ VT_R4
Definition: compat.h:2299
@ VT_UNKNOWN
Definition: compat.h:2308
@ VT_UI2
Definition: compat.h:2312
@ VT_CLSID
Definition: compat.h:2337
@ VT_LPWSTR
Definition: compat.h:2325
@ VT_R8
Definition: compat.h:2300
@ VT_I8
Definition: compat.h:2314
@ VT_I1
Definition: compat.h:2310
@ VT_I4
Definition: compat.h:2298
@ VT_BOOL
Definition: compat.h:2306
@ VT_I2
Definition: compat.h:2297
@ VT_UI4
Definition: compat.h:2313
@ VT_EMPTY
Definition: compat.h:2295
@ VT_VECTOR
Definition: compat.h:2340
@ VT_UI1
Definition: compat.h:2311
#define lstrlenW
Definition: compat.h:750
UINT(* handler)(MSIPACKAGE *)
Definition: action.c:7482
static REFPROPVARIANT PROPVAR_CHANGE_FLAGS VARTYPE vt
Definition: suminfo.c:86
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3325
HRESULT WINAPI DECLSPEC_HOTPATCH CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit)
Definition: compobj.c:2002
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
Definition: compobj.c:2067
INT WINAPI StringFromGUID2(REFGUID id, LPOLESTR str, INT cmax)
Definition: compobj.c:2434
HRESULT WINAPI CreateStreamOnHGlobal(HGLOBAL hGlobal, BOOL fDeleteOnRelease, LPSTREAM *ppstm)
HRESULT WINAPI PropVariantClear(PROPVARIANT *pvar)
Definition: ole2.c:2968
HRESULT WINAPI PropVariantToInt64(REFPROPVARIANT propvarIn, LONGLONG *ret)
Definition: propvar.c:198
#define assert(x)
Definition: debug.h:53
static LPSTR get_temp_buffer(void)
Definition: dplayx.c:88
static const WCHAR unknownW[]
Definition: engine.c:40
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLdouble s
Definition: gl.h:2039
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
GLsizeiptr size
Definition: glext.h:5919
GLuint index
Definition: glext.h:6031
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLfloat GLfloat v1
Definition: glext.h:6062
GLuint id
Definition: glext.h:5910
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
LPVOID NTAPI GlobalLock(HGLOBAL hMem)
Definition: heapmem.c:755
BOOL NTAPI GlobalUnlock(HGLOBAL hMem)
Definition: heapmem.c:1190
HGLOBAL NTAPI GlobalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:368
#define FLOAT
Definition: i386-dis.c:525
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:426
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
uint32_t entry
Definition: isohybrid.c:63
#define SEEK_SET
Definition: jmemansi.c:26
#define wine_dbgstr_w
Definition: kernel32.h:34
#define GUID_NULL
Definition: ks.h:106
INT WINAPI CompareStringW(LCID lcid, DWORD flags, LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
Definition: lang.c:2671
if(dx< 0)
Definition: linetemp.h:194
int WINAPI lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:170
int WINAPI lstrcmpA(LPCSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:18
int WINAPI lstrlenA(LPCSTR lpString)
Definition: lstring.c:145
HRESULT WINAPI WICMapGuidToShortName(REFGUID guid, UINT len, WCHAR *name, UINT *ret_len)
static const WCHAR imgdescW[]
HRESULT WINAPI WICMapSchemaToName(REFGUID format, LPWSTR schema, UINT len, WCHAR *name, UINT *ret_len)
const WCHAR * schema
const GUID * guid
HRESULT WINAPI WICMapShortNameToGuid(PCWSTR name, GUID *guid)
static const WCHAR xmpW[]
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define SEEK_CUR
Definition: util.h:63
#define sprintf(buf, format,...)
Definition: sprintf.c:55
BOOL todo
Definition: filedlg.c:313
static const BYTE us[]
Definition: encode.c:689
const char * var
Definition: shader.c:5666
#define todo_wine_if(is_todo)
Definition: custom.c:76
#define todo_wine
Definition: custom.c:79
static const struct metadata_item item3[]
Definition: metadata.c:2814
static const char * wine_dbgstr_propvariant(const PROPVARIANT *var)
Definition: metadata.c:2555
static WCHAR crs_scheme[]
Definition: metadata.c:2327
static HRESULT WINAPI mdbr_GetCount(IWICMetadataBlockReader *iface, UINT *count)
Definition: metadata.c:2748
static void test_metadata_IMD(void)
Definition: metadata.c:1848
static char the_worst[]
Definition: metadata.c:2479
static WCHAR tiff_scheme[]
Definition: metadata.c:2318
static WCHAR xmpMM_scheme[]
Definition: metadata.c:2313
static int propvar_cmp(const PROPVARIANT *v1, LONGLONG value2)
Definition: metadata.c:2582
static void test_create_reader(void)
Definition: metadata.c:958
static void test_metadata_GCE(void)
Definition: metadata.c:1926
static HRESULT WINAPI mdr_QueryInterface(IWICMetadataReader *iface, REFIID iid, void **out)
Definition: metadata.c:2481
static WCHAR xmpDM_scheme[]
Definition: metadata.c:2328
static HRESULT WINAPI mdr_GetValueByIndex(IWICMetadataReader *iface, UINT index, PROPVARIANT *schema, PROPVARIANT *id, PROPVARIANT *value)
Definition: metadata.c:2536
static const struct metadata data2
Definition: metadata.c:2859
static void test_metadata_GIF_comment(void)
Definition: metadata.c:2086
static WCHAR rdf_scheme[]
Definition: metadata.c:2308
#define IFD_BYTE
Definition: metadata.c:50
static WCHAR MP_scheme[]
Definition: metadata.c:2331
static void load_stream(IUnknown *reader, const char *data, int data_size, DWORD persist_options)
Definition: metadata.c:225
#define IFD_SBYTE
Definition: metadata.c:55
static const struct metadata_block block1[]
Definition: metadata.c:2833
static HRESULT WINAPI mdbr_GetReaderByIndex(IWICMetadataBlockReader *iface, UINT index, IWICMetadataReader **out)
Definition: metadata.c:2759
static HRESULT WINAPI mdr_GetEnumerator(IWICMetadataReader *iface, IWICEnumMetadataItem **enumerator)
Definition: metadata.c:2689
static void test_metadata_Exif(void)
Definition: metadata.c:930
static WCHAR * schema_list[]
Definition: metadata.c:2335
static const struct metadata_item item4[]
Definition: metadata.c:2822
static const struct metadata_block block3[]
Definition: metadata.c:2844
static const struct metadata_item item1[]
Definition: metadata.c:2802
static WCHAR MPReg_scheme[]
Definition: metadata.c:2333
static WCHAR stDim_scheme[]
Definition: metadata.c:2320
static const struct metadata data1
Definition: metadata.c:2853
static const char dc[]
Definition: metadata.c:2799
static IStream * create_stream(const char *data, int data_size)
Definition: metadata.c:204
#define IFD_UNDEFINED
Definition: metadata.c:56
static char the_best[]
Definition: metadata.c:2478
static const char pngimage[285]
Definition: metadata.c:164
static const char gifimage[35]
Definition: metadata.c:175
static ULONG WINAPI mdbr_AddRef(IWICMetadataBlockReader *iface)
Definition: metadata.c:2727
static ULONG WINAPI mdr_AddRef(IWICMetadataReader *iface)
Definition: metadata.c:2498
static void test_queryreader(void)
Definition: metadata.c:2871
static ULONG WINAPI mdr_Release(IWICMetadataReader *iface)
Definition: metadata.c:2503
static WCHAR aux_scheme[]
Definition: metadata.c:2326
static ULONG ulong_bswap(ULONG l)
Definition: metadata.c:543
static WCHAR stVer_scheme[]
Definition: metadata.c:2324
static HRESULT WINAPI mdr_GetMetadataFormat(IWICMetadataReader *iface, GUID *format)
Definition: metadata.c:2508
static ULONG WINAPI mdbr_Release(IWICMetadataBlockReader *iface)
Definition: metadata.c:2732
static HRESULT WINAPI mdbr_QueryInterface(IWICMetadataBlockReader *iface, REFIID iid, void **out)
Definition: metadata.c:2710
static void compare_metadata(IWICMetadataReader *reader, const struct test_data *td, ULONG count)
Definition: metadata.c:655
static WCHAR exif_scheme[]
Definition: metadata.c:2319
static void test_WICMapSchemaToName(void)
Definition: metadata.c:2365
#define IFD_SRATIONAL
Definition: metadata.c:59
#define IFD_SLONG
Definition: metadata.c:58
static void test_metadata_png(void)
Definition: metadata.c:1029
#define IFD_SHORT
Definition: metadata.c:52
static HRESULT WINAPI mdbr_GetContainerFormat(IWICMetadataBlockReader *iface, GUID *format)
Definition: metadata.c:2737
static const struct metadata * current_metadata
Definition: metadata.c:2475
static WCHAR MicrosoftPhoto_scheme[]
Definition: metadata.c:2330
#define IFD_SSHORT
Definition: metadata.c:57
static void test_WICMapShortNameToGuid(void)
Definition: metadata.c:2225
static WCHAR stRef_scheme[]
Definition: metadata.c:2323
static void test_metadata_gAMA(void)
Definition: metadata.c:432
static IWICMetadataBlockReader mdbr
Definition: metadata.c:2796
static HRESULT WINAPI mdr_GetValue(IWICMetadataReader *iface, const PROPVARIANT *schema, const PROPVARIANT *id, PROPVARIANT *value)
Definition: metadata.c:2593
static const char xmp[]
Definition: metadata.c:2798
static WCHAR xmp_scheme[]
Definition: metadata.c:2310
static WCHAR xmpTPg_scheme[]
Definition: metadata.c:2315
static void test_metadata_unknown(void)
Definition: metadata.c:258
static void test_metadata_APE(void)
Definition: metadata.c:2001
static const char metadata_cHRM[]
Definition: metadata.c:154
static void test_metadata_tEXt(void)
Definition: metadata.c:314
static USHORT ushort_bswap(USHORT s)
Definition: metadata.c:538
static const struct ifd_data IFD_data
static HRESULT WINAPI mdr_GetMetadataHandlerInfo(IWICMetadataReader *iface, IWICMetadataHandlerInfo **handler)
Definition: metadata.c:2519
static HRESULT WINAPI mdbr_GetEnumerator(IWICMetadataBlockReader *iface, IEnumUnknown **enumerator)
Definition: metadata.c:2779
#define expect_blob(propvar, data, length)
Definition: metadata.c:40
static const struct metadata data3
Definition: metadata.c:2865
static void test_metadata_cHRM(void)
Definition: metadata.c:477
static IWICMetadataReader mdr
Definition: metadata.c:2708
static WCHAR pdf_scheme[]
Definition: metadata.c:2316
static WCHAR Iptc4xmpCore_scheme[]
Definition: metadata.c:2329
static const char metadata_gAMA[]
Definition: metadata.c:147
static const struct metadata_block * current_metadata_block
Definition: metadata.c:2476
static const GUID * guid_list[]
Definition: metadata.c:2260
static void test_metadata_IFD(void)
Definition: metadata.c:758
#define IFD_DOUBLE
Definition: metadata.c:61
static WCHAR photoshop_scheme[]
Definition: metadata.c:2317
static const char metadata_unknown[]
Definition: metadata.c:137
static WCHAR dc_scheme[]
Definition: metadata.c:2309
#define IFD_RATIONAL
Definition: metadata.c:54
static const struct metadata_item item2[]
Definition: metadata.c:2807
static void byte_swap_ifd_data(char *data)
Definition: metadata.c:553
static WCHAR stEvt_scheme[]
Definition: metadata.c:2322
static WCHAR stJob_scheme[]
Definition: metadata.c:2325
static const IWICMetadataReaderVtbl mdr_vtbl
Definition: metadata.c:2695
static WCHAR xapGImg_scheme[]
Definition: metadata.c:2321
static const IWICMetadataBlockReaderVtbl mdbr_vtbl
Definition: metadata.c:2785
static ULONGLONG ulonglong_bswap(ULONGLONG ll)
Definition: metadata.c:548
static void test_metadata_LSD(void)
Definition: metadata.c:1769
static const char metadata_tEXt[]
Definition: metadata.c:139
static WCHAR MPRI_scheme[]
Definition: metadata.c:2332
static WCHAR xmpidq_scheme[]
Definition: metadata.c:2311
static const char animatedgif[]
Definition: metadata.c:182
#define IFD_ASCII
Definition: metadata.c:51
static WCHAR xmpBJ_scheme[]
Definition: metadata.c:2314
static WCHAR xmpRights_scheme[]
Definition: metadata.c:2312
static const struct metadata_block block2[]
Definition: metadata.c:2838
#define IFD_LONG
Definition: metadata.c:53
static void test_WICMapGuidToShortName(void)
Definition: metadata.c:2168
static void test_metadata_gif(void)
Definition: metadata.c:1152
static HRESULT WINAPI mdr_GetCount(IWICMetadataReader *iface, UINT *count)
Definition: metadata.c:2525
static const char tiff[]
Definition: metadata.c:2800
#define IFD_FLOAT
Definition: metadata.c:60
REFCLSID clsid
Definition: msctf.c:82
unsigned int UINT
Definition: ndis.h:50
#define LOCALE_NEUTRAL
@ COINIT_APARTMENTTHREADED
Definition: objbase.h:278
short SHORT
Definition: pedump.c:59
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)
Definition: guiddef.h:68
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define REFIID
Definition: guiddef.h:118
static FILE * out
Definition: regtests2xml.c:44
static __inline const char * wine_dbgstr_guid(const GUID *id)
Definition: debug.h:197
int winetest_debug
#define win_skip
Definition: test.h:160
HRESULT hr
Definition: shlfolder.c:183
LONG value
SHORT id
SHORT type
ULONG count
LONG denominator
Definition: image.c:3499
LONG numerator
Definition: image.c:3498
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
struct _ULARGE_INTEGER::@4135 u
Definition: image.c:134
Definition: tftpd.h:126
Definition: tftpd.h:138
Definition: main.c:439
struct IFD_rational srational_val
Definition: metadata.c:86
LONG long_val[2]
Definition: metadata.c:89
struct IFD_entry entry[40]
Definition: metadata.c:82
struct IFD_rational xres
Definition: metadata.c:84
DOUBLE double_val
Definition: metadata.c:85
USHORT number_of_entries
Definition: metadata.c:81
struct IFD_rational rational[3]
Definition: metadata.c:91
FLOAT float_val[2]
Definition: metadata.c:90
ULONG next_IFD
Definition: metadata.c:83
SHORT short_val[4]
Definition: metadata.c:88
const struct metadata_item * item
Definition: metadata.c:2465
const GUID * metadata_format
Definition: metadata.c:2463
const char * schema
Definition: metadata.c:2457
const char * id_str
Definition: metadata.c:2457
UINT count
Definition: metadata.c:2471
const struct metadata_block * block
Definition: metadata.c:2472
const GUID * container_format
Definition: metadata.c:2470
Definition: name.c:39
Definition: reader.h:84
Definition: parse.h:23
LONGLONG value[13]
Definition: metadata.c:650
const WCHAR id_string[32]
Definition: metadata.c:652
const char * string
Definition: metadata.c:651
int count
Definition: metadata.c:649
ULONG id
Definition: metadata.c:648
ULONG type
Definition: metadata.c:648
Definition: tiffiop.h:115
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
float FLOAT
Definition: typedefs.h:69
int64_t LONGLONG
Definition: typedefs.h:68
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
double DOUBLE
Definition: typedefs.h:70
Definition: pdh_main.c:94
int ret
#define GMEM_MOVEABLE
Definition: winbase.h:294
@ WICDecodeMetadataCacheOnLoad
Definition: wincodec.idl:29
@ WICPersistOptionBigEndian
Definition: wincodecsdk.idl:25
@ WICPersistOptionDefault
Definition: wincodecsdk.idl:23
@ WICPersistOptionLittleEndian
Definition: wincodecsdk.idl:24
#define WINAPI
Definition: msvc.h:6
#define REGDB_E_CLASSNOTREG
Definition: winerror.h:2696
#define S_FALSE
Definition: winerror.h:2357
#define WINCODEC_ERR_WRONGSTATE
Definition: winerror.h:3281
#define WINCODEC_ERR_UNSUPPORTEDOPERATION
Definition: winerror.h:3308
#define E_NOINTERFACE
Definition: winerror.h:2364
#define WINCODEC_ERR_INVALIDQUERYCHARACTER
Definition: winerror.h:3318
#define WINCODEC_ERR_PROPERTYNOTSUPPORTED
Definition: winerror.h:3288
#define HRESULT_FROM_WIN32(x)
Definition: winerror.h:92
#define E_POINTER
Definition: winerror.h:2365
#define WINCODEC_ERR_VALUEOUTOFRANGE
Definition: winerror.h:3282
#define DISP_E_TYPEMISMATCH
Definition: winerror.h:2514
#define WINCODEC_ERR_INSUFFICIENTBUFFER
Definition: winerror.h:3311
#define WINCODEC_ERR_REQUESTONLYVALIDATMETADATAROOT
Definition: winerror.h:3317
#define WINCODEC_ERR_PROPERTYNOTFOUND
Definition: winerror.h:3287
#define NORM_IGNORECASE
Definition: winnls.h:176
#define CSTR_EQUAL
Definition: winnls.h:456
__wchar_t WCHAR
Definition: xmlstorage.h:180