ReactOS 0.4.16-dev-979-g79f281e
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_ref(obj,ref) expect_ref_((IUnknown *)obj, ref, __LINE__)
41static void expect_ref_(IUnknown *obj, ULONG ref, int line)
42{
43 ULONG refcount;
44 IUnknown_AddRef(obj);
45 refcount = IUnknown_Release(obj);
46 ok_(__FILE__, line)(refcount == ref, "Expected refcount %ld, got %ld.\n", ref, refcount);
47}
48
49#define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
50static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported)
51{
52 IUnknown *iface = iface_ptr;
53 HRESULT hr, expected_hr;
54 IUnknown *unk;
55
56 expected_hr = supported ? S_OK : E_NOINTERFACE;
57
58 hr = IUnknown_QueryInterface(iface, iid, (void **)&unk);
59 ok_(__FILE__, line)(hr == expected_hr, "Got hr %#lx, expected %#lx.\n", hr, expected_hr);
60 if (SUCCEEDED(hr))
61 IUnknown_Release(unk);
62}
63
64#define check_persist_options(a, b) check_persist_options_(__LINE__, a, b)
65static void check_persist_options_(unsigned int line, void *iface_ptr, DWORD expected_options)
66{
67 IWICStreamProvider *stream_provider;
68 IUnknown *iface = iface_ptr;
70 HRESULT hr;
71
72 if (SUCCEEDED(IUnknown_QueryInterface(iface, &IID_IWICStreamProvider, (void **)&stream_provider)))
73 {
74 hr = IWICStreamProvider_GetPersistOptions(stream_provider, &options);
75 ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
76 if (hr == S_OK)
77 ok_(__FILE__, line)(options == expected_options, "Unexpected options %#lx.\n", options);
78 IWICStreamProvider_Release(stream_provider);
79 }
80 else
81 ok_(__FILE__, line)(0, "IWICStreamProvider is not supported.\n");
82}
83
84static HRESULT get_persist_stream(void *iface_ptr, IStream **stream)
85{
86 IWICStreamProvider *stream_provider;
87 IUnknown *iface = iface_ptr;
89
90 if (SUCCEEDED(IUnknown_QueryInterface(iface, &IID_IWICStreamProvider, (void **)&stream_provider)))
91 {
92 hr = IWICStreamProvider_GetStream(stream_provider, stream);
93 IWICStreamProvider_Release(stream_provider);
94 }
95
96 return hr;
97}
98
99#define compare_blob(a,b,c) compare_blob_(__LINE__,a,b,c)
100static void compare_blob_(unsigned int line, const PROPVARIANT *propvar, const char *data, ULONG length)
101{
102 ok_(__FILE__, line)(propvar->vt == VT_BLOB, "Unexpected vt: %i\n", propvar->vt);
103 if (propvar->vt == VT_BLOB)
104 {
105 ok_(__FILE__, line)(propvar->blob.cbSize == length, "Expected size %lu, got %lu.\n", length, propvar->blob.cbSize);
106 if (propvar->blob.cbSize == length)
107 ok_(__FILE__, line)(!memcmp(propvar->blob.pBlobData, data, length), "Unexpected data.\n");
108 }
109}
110
112{
126};
127
128#include "pshpack2.h"
129struct IFD_entry
130{
131 SHORT id;
132 SHORT type;
133 ULONG count;
134 LONG value;
135};
136
137struct IFD_rational
138{
141};
142
143static const struct ifd_data
144{
146 struct IFD_entry entry[40];
151 char string[14];
156} IFD_data =
157{
158 28,
159 {
160 { 0xfe, IFD_SHORT, 1, 1 }, /* NEWSUBFILETYPE */
161 { 0x100, IFD_LONG, 1, 222 }, /* IMAGEWIDTH */
162 { 0x101, IFD_LONG, 1, 333 }, /* IMAGELENGTH */
163 { 0x102, IFD_SHORT, 1, 24 }, /* BITSPERSAMPLE */
164 { 0x103, IFD_LONG, 1, 32773 }, /* COMPRESSION: packbits */
165 { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct ifd_data, xres) },
166 { 0xf001, IFD_BYTE, 1, 0x11223344 },
167 { 0xf002, IFD_BYTE, 4, 0x11223344 },
168 { 0xf003, IFD_SBYTE, 1, 0x11223344 },
169 { 0xf004, IFD_SSHORT, 1, 0x11223344 },
170 { 0xf005, IFD_SSHORT, 2, 0x11223344 },
171 { 0xf006, IFD_SLONG, 1, 0x11223344 },
172 { 0xf007, IFD_FLOAT, 1, 0x11223344 },
173 { 0xf008, IFD_DOUBLE, 1, FIELD_OFFSET(struct ifd_data, double_val) },
174 { 0xf009, IFD_SRATIONAL, 1, FIELD_OFFSET(struct ifd_data, srational_val) },
175 { 0xf00a, IFD_BYTE, 13, FIELD_OFFSET(struct ifd_data, string) },
176 { 0xf00b, IFD_SSHORT, 4, FIELD_OFFSET(struct ifd_data, short_val) },
177 { 0xf00c, IFD_SLONG, 2, FIELD_OFFSET(struct ifd_data, long_val) },
178 { 0xf00d, IFD_FLOAT, 2, FIELD_OFFSET(struct ifd_data, float_val) },
179 { 0xf00e, IFD_ASCII, 13, FIELD_OFFSET(struct ifd_data, string) },
180 { 0xf00f, IFD_ASCII, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 },
181 { 0xf010, IFD_UNDEFINED, 13, FIELD_OFFSET(struct ifd_data, string) },
182 { 0xf011, IFD_UNDEFINED, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 },
183 { 0xf012, IFD_BYTE, 0, 0x11223344 },
184 { 0xf013, IFD_SHORT, 0, 0x11223344 },
185 { 0xf014, IFD_LONG, 0, 0x11223344 },
186 { 0xf015, IFD_FLOAT, 0, 0x11223344 },
187 { 0xf016, IFD_SRATIONAL, 3, FIELD_OFFSET(struct ifd_data, rational) },
188 },
189 0,
190 { 900, 3 },
191 1234567890.0987654321,
192 { 0x1a2b3c4d, 0x5a6b7c8d },
193 "Hello World!",
194 { 0x0101, 0x0202, 0x0303, 0x0404 },
195 { 0x11223344, 0x55667788 },
196 { (FLOAT)1234.5678, (FLOAT)8765.4321 },
197 { { 0x01020304, 0x05060708 }, { 0x10203040, 0x50607080 }, { 0x11223344, 0x55667788 } },
199#include "poppack.h"
200
201static const char metadata_unknown[] = "lalala";
202
203static const char metadata_tEXt[] = {
204 0,0,0,14, /* chunk length */
205 't','E','X','t', /* chunk type */
206 'w','i','n','e','t','e','s','t',0, /* keyword */
207 'v','a','l','u','e', /* text */
208 0x3f,0x64,0x19,0xf3 /* chunk CRC */
209};
210
211static const char metadata_gAMA[] = {
212 0,0,0,4, /* chunk length */
213 'g','A','M','A', /* chunk type */
214 0,0,130,53, /* gamma */
215 0xff,0xff,0xff,0xff /* chunk CRC */
216};
217
218static const char metadata_cHRM[] = {
219 0,0,0,32, /* chunk length */
220 'c','H','R','M', /* chunk type */
221 0,0,122,38, 0,0,128,132, /* white point */
222 0,0,250,0, 0,0,128,232, /* red */
223 0,0,117,48, 0,0,234,96, /* green */
224 0,0,58,152, 0,0,23,112, /* blue */
225 0xff,0xff,0xff,0xff /* chunk CRC */
226};
227
228static const char metadata_hIST[] = {
229 0,0,0,40, /* chunk length */
230 'h','I','S','T', /* chunk type */
231 0,1, 0,2, 0,3, 0,4,
232 0,5, 0,6, 0,7, 0,8,
233 0,9, 0,10, 0,11, 0,12,
234 0,13, 0,14, 0,15, 0,16,
235 0,17, 0,18, 0,19, 0,20,
236 0xff,0xff,0xff,0xff
237};
238
239static const char metadata_tIME[] = {
240 0,0,0,7, /* chunk length */
241 't','I','M','E', /* chunk type */
242 0x07,0xd0,0x01,0x02, /* year (2 bytes), month, day */
243 0x0c,0x22,0x38, /* hour, minute, second */
244 0xff,0xff,0xff,0xff
245};
246
247static const char pngimage[285] = {
2480x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
2490x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
2500xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
2510x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
2520x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
2530x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
2540xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
255};
256
257/* 1x1 pixel gif */
258static const char gifimage[35] = {
2590x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff,
2600xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,
2610x01,0x00,0x3b
262};
263
264/* 1x1 pixel gif, 2 frames; first frame is white, second is black */
265static const char animatedgif[] = {
266'G','I','F','8','9','a',0x01,0x00,0x01,0x00,0xA1,0x00,0x00,
2670x6F,0x6F,0x6F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
268/*0x21,0xFF,0x0B,'N','E','T','S','C','A','P','E','2','.','0',*/
2690x21,0xFF,0x0B,'A','N','I','M','E','X','T','S','1','.','0',
2700x03,0x01,0x05,0x00,0x00,
2710x21,0xFE,0x0C,'H','e','l','l','o',' ','W','o','r','l','d','!',0x00,
2720x21,0x01,0x0D,'a','n','i','m','a','t','i','o','n','.','g','i','f',0x00,
2730x21,0xF9,0x04,0x00,0x0A,0x00,0xFF,0x00,0x2C,
2740x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x81,
2750xDE,0xDE,0xDE,0x00,0x00,0x00,
2760x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x4C,0x01,0x00,
2770x21,0xF9,0x04,0x01,0x0A,0x00,0x01,0x00,
2780x21,0xFE,0x08,'i','m','a','g','e',' ','#','1',0x00,
2790x21,0x01,0x0C,'p','l','a','i','n','t','e','x','t',' ','#','1',0x00,
2800x2C,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x81,
2810x4D,0x4D,0x4D,0x00,0x00,0x00,
2820x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x44,0x01,0x00,
2830x21,0xFE,0x08,'i','m','a','g','e',' ','#','2',0x00,
2840x21,0x01,0x0C,'p','l','a','i','n','t','e','x','t',' ','#','2',0x00,0x3B
285};
286
287static ULONG get_refcount(void *iface)
288{
289 IUnknown *unknown = iface;
290 IUnknown_AddRef(unknown);
291 return IUnknown_Release(unknown);
292}
293
294static IStream *create_stream(const char *data, int data_size)
295{
296 HRESULT hr;
298 HGLOBAL hdata;
299 void *locked_data;
300
301 hdata = GlobalAlloc(GMEM_MOVEABLE, data_size);
302 ok(hdata != 0, "GlobalAlloc failed\n");
303 if (!hdata) return NULL;
304
305 locked_data = GlobalLock(hdata);
306 memcpy(locked_data, data, data_size);
307 GlobalUnlock(hdata);
308
310 ok(hr == S_OK, "CreateStreamOnHGlobal failed, hr=%lx\n", hr);
311
312 return stream;
313}
314
315static void load_stream(void *iface_ptr, const char *data, int data_size, DWORD persist_options)
316{
317 IWICStreamProvider *stream_provider;
318 IUnknown *iface = iface_ptr;
319 HRESULT hr;
320 IWICPersistStream *persist;
321 IStream *stream, *stream2;
323 ULARGE_INTEGER cur_pos;
324 DWORD flags;
325 GUID guid;
326
327 stream = create_stream(data, data_size);
328 if (!stream)
329 return;
330
331 hr = IUnknown_QueryInterface(iface, &IID_IWICPersistStream, (void **)&persist);
332 ok(hr == S_OK, "QueryInterface failed, hr=%lx\n", hr);
333
334 hr = IWICPersistStream_LoadEx(persist, NULL, NULL, 0);
335 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
336
337 hr = IUnknown_QueryInterface(iface, &IID_IWICStreamProvider, (void **)&stream_provider);
338 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
339
340 memset(&guid, 0, sizeof(guid));
341 hr = IWICStreamProvider_GetPreferredVendorGUID(stream_provider, &guid);
343 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
345 ok(IsEqualGUID(&guid, &GUID_VendorMicrosoft), "Unexpected vendor %s.\n", wine_dbgstr_guid(&guid));
346
347 hr = IWICStreamProvider_GetPreferredVendorGUID(stream_provider, NULL);
349 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
350
351 hr = IWICStreamProvider_GetPersistOptions(stream_provider, NULL);
353 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
354
355 flags = 123;
356 hr = IWICStreamProvider_GetPersistOptions(stream_provider, &flags);
358 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
360 ok(!flags, "Unexpected options %#lx.\n", flags);
361
362 stream2 = (void *)0xdeadbeef;
363 hr = IWICStreamProvider_GetStream(stream_provider, &stream2);
365 ok(hr == WINCODEC_ERR_STREAMNOTAVAILABLE, "Unexpected hr %#lx.\n", hr);
366 ok(stream2 == (void *)0xdeadbeef, "Unexpected stream pointer.\n");
367
368 hr = IWICPersistStream_LoadEx(persist, stream, NULL, persist_options);
369 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
370
371 memset(&guid, 0, sizeof(guid));
372 hr = IWICStreamProvider_GetPreferredVendorGUID(stream_provider, &guid);
374 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
376 ok(IsEqualGUID(&guid, &GUID_VendorMicrosoft), "Unexpected vendor %s.\n", wine_dbgstr_guid(&guid));
377
378 flags = ~persist_options;
379 hr = IWICStreamProvider_GetPersistOptions(stream_provider, &flags);
381 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
383 ok(flags == persist_options, "Unexpected options %#lx.\n", flags);
384
385 if (persist_options & WICPersistOptionNoCacheStream)
386 {
387 stream2 = (void *)0xdeadbeef;
388 hr = IWICStreamProvider_GetStream(stream_provider, &stream2);
390 ok(hr == WINCODEC_ERR_STREAMNOTAVAILABLE, "Unexpected hr %#lx.\n", hr);
391 ok(stream2 == (void *)0xdeadbeef, "Unexpected stream pointer.\n");
392 }
393 else
394 {
395 stream2 = NULL;
396 hr = IWICStreamProvider_GetStream(stream_provider, &stream2);
398 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
400 ok(stream2 == stream, "Unexpected stream pointer.\n");
401 if (stream2)
402 IStream_Release(stream2);
403 }
404
405 IWICStreamProvider_Release(stream_provider);
406 IWICPersistStream_Release(persist);
407
408 pos.QuadPart = 0;
409 hr = IStream_Seek(stream, pos, SEEK_CUR, &cur_pos);
410 ok(hr == S_OK, "IStream_Seek error %#lx\n", hr);
411 /* IFD metadata reader doesn't rewind the stream to the start */
412 ok(cur_pos.QuadPart == 0 || cur_pos.QuadPart <= data_size,
413 "current stream pos is at %lx/%lx, data size %x\n", cur_pos.u.LowPart, cur_pos.u.HighPart, data_size);
414
415 IStream_Release(stream);
416}
417
418struct test_data
419{
421 int count; /* if VT_VECTOR */
423 const char *string;
424 const WCHAR id_string[32];
425};
426
428{
429 HRESULT hr;
430 IWICEnumMetadataItem *enumerator;
431 PROPVARIANT schema, id, value;
432 ULONG items_returned, i;
433
434 hr = IWICMetadataReader_GetEnumerator(reader, NULL);
435 ok(hr == E_INVALIDARG, "GetEnumerator error %#lx\n", hr);
436
437 hr = IWICMetadataReader_GetEnumerator(reader, &enumerator);
438 ok(hr == S_OK, "GetEnumerator error %#lx\n", hr);
439
440 PropVariantInit(&schema);
441 PropVariantInit(&id);
442 PropVariantInit(&value);
443
444 for (i = 0; i < count; i++)
445 {
446 winetest_push_context("%lu", i);
447
448 hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
449 ok(hr == S_OK, "Next error %#lx\n", hr);
450 ok(items_returned == 1, "unexpected item count %lu\n", items_returned);
451
452 ok(schema.vt == VT_EMPTY, "Unexpected vt: %u\n", schema.vt);
453 ok(id.vt == VT_UI2 || id.vt == VT_LPWSTR || id.vt == VT_EMPTY, "Unexpected vt: %u\n", id.vt);
454 if (id.vt == VT_UI2)
455 ok(id.uiVal == td[i].id, "Expected id %#lx, got %#x\n", td[i].id, id.uiVal);
456 else if (id.vt == VT_LPWSTR)
457 ok(!lstrcmpW(td[i].id_string, id.pwszVal),
458 "Expected %s, got %s\n", wine_dbgstr_w(td[i].id_string), wine_dbgstr_w(id.pwszVal));
459
460 ok(value.vt == td[i].type, "Expected vt %#lx, got %#x\n", td[i].type, value.vt);
461 if (value.vt & VT_VECTOR)
462 {
463 ULONG j;
464 switch (value.vt & ~VT_VECTOR)
465 {
466 case VT_I1:
467 case VT_UI1:
468 ok(td[i].count == value.caub.cElems, "Expected cElems %d, got %ld\n", td[i].count, value.caub.cElems);
469 for (j = 0; j < value.caub.cElems; j++)
470 ok(td[i].value[j] == value.caub.pElems[j], "Expected value[%ld] %#I64x, got %#x\n", j, td[i].value[j], value.caub.pElems[j]);
471 break;
472 case VT_I2:
473 case VT_UI2:
474 ok(td[i].count == value.caui.cElems, "Expected cElems %d, got %ld\n", td[i].count, value.caui.cElems);
475 for (j = 0; j < value.caui.cElems; j++)
476 ok(td[i].value[j] == value.caui.pElems[j], "Expected value[%ld] %#I64x, got %#x\n", j, td[i].value[j], value.caui.pElems[j]);
477 break;
478 case VT_I4:
479 case VT_UI4:
480 case VT_R4:
481 ok(td[i].count == value.caul.cElems, "Expected cElems %d, got %ld\n", td[i].count, value.caul.cElems);
482 for (j = 0; j < value.caul.cElems; j++)
483 ok(td[i].value[j] == value.caul.pElems[j], "Expected value[%ld] %#I64x, got %#lx\n", j, td[i].value[j], value.caul.pElems[j]);
484 break;
485 case VT_I8:
486 case VT_UI8:
487 case VT_R8:
488 ok(td[i].count == value.cauh.cElems, "Expected cElems %d, got %ld\n", td[i].count, value.cauh.cElems);
489 for (j = 0; j < value.cauh.cElems; j++)
490 ok(td[i].value[j] == value.cauh.pElems[j].QuadPart, "Expected value[%ld] %I64x, got %08lx/%08lx\n", j, td[i].value[j], value.cauh.pElems[j].u.LowPart, value.cauh.pElems[j].u.HighPart);
491 break;
492 case VT_LPSTR:
493 ok(td[i].count == value.calpstr.cElems, "Expected cElems %d, got %ld\n", td[i].count, value.caub.cElems);
494 for (j = 0; j < value.calpstr.cElems; j++)
495 trace("%lu: %s\n", j, value.calpstr.pElems[j]);
496 /* fall through to not handled message */
497 default:
498 ok(0, "vector of type %d is not handled\n", value.vt & ~VT_VECTOR);
499 break;
500 }
501 }
502 else if (value.vt == VT_LPSTR)
503 {
504 ok(td[i].count == strlen(value.pszVal) ||
505 broken(td[i].count == strlen(value.pszVal) + 1), /* before Win7 */
506 "Expected count %d, got %d\n", td[i].count, lstrlenA(value.pszVal));
507 if (td[i].count == strlen(value.pszVal))
508 ok(!strcmp(td[i].string, value.pszVal),
509 "Expected %s, got %s\n", td[i].string, value.pszVal);
510 }
511 else if (value.vt == VT_BLOB)
512 {
513 ok(td[i].count == value.blob.cbSize, "Expected count %d, got %ld\n", td[i].count, value.blob.cbSize);
514 ok(!memcmp(td[i].string, value.blob.pBlobData, td[i].count), "Expected %s, got %s\n", td[i].string, value.blob.pBlobData);
515 }
516 else
517 ok(value.uhVal.QuadPart == td[i].value[0], "Eexpected value %#I64x got %#lx/%#lx\n",
518 td[i].value[0], value.uhVal.u.LowPart, value.uhVal.u.HighPart);
519
521 PropVariantClear(&id);
523
525 }
526
527 hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
528 ok(hr == S_FALSE, "Next should fail\n");
529 ok(items_returned == 0, "unexpected item count %lu\n", items_returned);
530
531 IWICEnumMetadataItem_Release(enumerator);
532}
533
534#define test_reader_container_format(a, b) _test_reader_container_format(a, b, __LINE__)
536{
538 BOOL found = FALSE;
539 GUID formats[8];
540 UINT count;
541 HRESULT hr;
542
543 hr = IWICMetadataReader_GetMetadataHandlerInfo(reader, &info);
544 ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
545
546 hr = IWICMetadataHandlerInfo_GetContainerFormats(info, ARRAY_SIZE(formats), formats, &count);
547 ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
548 ok_(__FILE__, line)(count > 0, "Unexpected count.\n");
549
550 for (unsigned i = 0; i < count; ++i)
551 {
552 if (IsEqualGUID(&formats[i], format))
553 {
554 found = TRUE;
555 break;
556 }
557 }
558 ok_(__FILE__, line)(found, "Container format %s was not found.\n", wine_dbgstr_guid(format));
559
560 if (!found)
561 {
562 for (unsigned i = 0; i < count; ++i)
563 ok_(__FILE__, line)(0, "Available format %s.\n", wine_dbgstr_guid(&formats[i]));
564 }
565
566 IWICMetadataHandlerInfo_Release(info);
567}
568
569
570static void test_metadata_unknown(void)
571{
572 HRESULT hr;
574 IWICEnumMetadataItem *enumerator;
575 PROPVARIANT schema, id, value;
576 IWICMetadataWriter *writer;
577 IWICPersistStream *persist;
578 ULONG items_returned;
579 UINT count;
580
581 hr = CoCreateInstance(&CLSID_WICUnknownMetadataReader, NULL, CLSCTX_INPROC_SERVER,
582 &IID_IWICMetadataReader, (void**)&reader);
583 ok(hr == S_OK, "CoCreateInstance failed, hr=%lx\n", hr);
584 if (FAILED(hr)) return;
585
586 check_interface(reader, &IID_IWICMetadataReader, TRUE);
589 check_interface(reader, &IID_IWICPersistStream, TRUE);
590 check_interface(reader, &IID_IWICStreamProvider, TRUE);
591 check_interface(reader, &IID_IWICMetadataBlockReader, FALSE);
592
594
595 hr = IWICMetadataReader_GetEnumerator(reader, &enumerator);
596 ok(hr == S_OK, "GetEnumerator failed, hr=%lx\n", hr);
597
598 if (SUCCEEDED(hr))
599 {
600 PropVariantInit(&schema);
601 PropVariantInit(&id);
602 PropVariantInit(&value);
603
604 hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
605 ok(hr == S_OK, "Next failed, hr=%lx\n", hr);
606 ok(items_returned == 1, "unexpected item count %li\n", items_returned);
607
608 if (hr == S_OK && items_returned == 1)
609 {
610 ok(schema.vt == VT_EMPTY, "unexpected vt: %i\n", schema.vt);
611 ok(id.vt == VT_EMPTY, "unexpected vt: %i\n", id.vt);
613
615 PropVariantClear(&id);
617 }
618
619 hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
620 ok(hr == S_FALSE, "Next failed, hr=%lx\n", hr);
621 ok(items_returned == 0, "unexpected item count %li\n", items_returned);
622
623 hr = IWICEnumMetadataItem_Reset(enumerator);
624 ok(hr == S_OK, "Reset failed, hr=%lx\n", hr);
625
626 hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, NULL, NULL);
627 ok(hr == S_OK, "Next failed, hr=%lx\n", hr);
628
629 if (hr == S_OK)
630 {
631 ok(schema.vt == VT_EMPTY, "unexpected vt: %i\n", schema.vt);
632 ok(id.vt == VT_EMPTY, "unexpected vt: %i\n", id.vt);
633
635 PropVariantClear(&id);
636 }
637
638 IWICEnumMetadataItem_Release(enumerator);
639 }
640
641 hr = IWICMetadataReader_QueryInterface(reader, &IID_IWICPersistStream, (void **)&persist);
642 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
643 hr = IWICMetadataReader_GetCount(reader, &count);
644 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
645 ok(count == 1, "Unexpected count %u.\n", count);
646 hr = IWICPersistStream_LoadEx(persist, NULL, NULL, 0);
647 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
648 hr = IWICMetadataReader_GetCount(reader, &count);
649 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
651 ok(count == 1, "Unexpected count %u.\n", count);
652 IWICPersistStream_Release(persist);
653
654 IWICMetadataReader_Release(reader);
655
656 hr = CoCreateInstance(&CLSID_WICUnknownMetadataWriter, NULL, CLSCTX_INPROC_SERVER,
657 &IID_IWICMetadataWriter, (void **)&writer);
659 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
660 if (FAILED(hr)) return;
661
662 check_interface(writer, &IID_IWICMetadataWriter, TRUE);
663 check_interface(writer, &IID_IWICMetadataReader, TRUE);
666 check_interface(writer, &IID_IWICPersistStream, TRUE);
667 check_interface(writer, &IID_IWICStreamProvider, TRUE);
668
669 load_stream(writer, metadata_unknown, sizeof(metadata_unknown), 0);
671
672 IWICMetadataWriter_Release(writer);
673}
674
675static void test_metadata_tEXt(void)
676{
678 HRESULT hr;
680 IWICEnumMetadataItem *enumerator;
681 PROPVARIANT schema, id, value;
682 IWICMetadataWriter *writer;
683 ULONG items_returned;
684 UINT count;
685 GUID format;
686
687 PropVariantInit(&schema);
688 PropVariantInit(&id);
689 PropVariantInit(&value);
690
691 hr = CoCreateInstance(&CLSID_WICPngTextMetadataReader, NULL, CLSCTX_INPROC_SERVER,
692 &IID_IWICMetadataReader, (void**)&reader);
693 ok(hr == S_OK, "CoCreateInstance failed, hr=%lx\n", hr);
694 if (FAILED(hr)) return;
695
696 check_interface(reader, &IID_IWICMetadataReader, TRUE);
699 check_interface(reader, &IID_IWICPersistStream, TRUE);
700 check_interface(reader, &IID_IWICStreamProvider, TRUE);
701
702 hr = IWICMetadataReader_GetCount(reader, NULL);
703 ok(hr == E_INVALIDARG, "GetCount failed, hr=%lx\n", hr);
704
705 hr = IWICMetadataReader_GetCount(reader, &count);
706 ok(hr == S_OK, "GetCount failed, hr=%lx\n", hr);
707 ok(count == 0, "unexpected count %i\n", count);
708
710
711 hr = IWICMetadataReader_GetMetadataHandlerInfo(reader, &info);
713 ok(hr == WINCODEC_ERR_COMPONENTNOTFOUND, "Unexpected hr %#lx.\n", hr);
714 if (SUCCEEDED(hr))
715 IWICMetadataHandlerInfo_Release(info);
716
717 hr = IWICMetadataReader_GetCount(reader, &count);
718 ok(hr == S_OK, "GetCount failed, hr=%lx\n", hr);
719 ok(count == 1, "unexpected count %i\n", count);
720
721 hr = IWICMetadataReader_GetEnumerator(reader, NULL);
722 ok(hr == E_INVALIDARG, "GetEnumerator failed, hr=%lx\n", hr);
723
724 hr = IWICMetadataReader_GetEnumerator(reader, &enumerator);
725 ok(hr == S_OK, "GetEnumerator failed, hr=%lx\n", hr);
726
727 if (SUCCEEDED(hr))
728 {
729 hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
730 ok(hr == S_OK, "Next failed, hr=%lx\n", hr);
731 ok(items_returned == 1, "unexpected item count %li\n", items_returned);
732
733 if (hr == S_OK && items_returned == 1)
734 {
735 ok(schema.vt == VT_EMPTY, "unexpected vt: %i\n", schema.vt);
736 ok(id.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt);
737 ok(!strcmp(id.pszVal, "winetest"), "unexpected id: %s\n", id.pszVal);
738 ok(value.vt == VT_LPSTR, "unexpected vt: %i\n", value.vt);
739 ok(!strcmp(value.pszVal, "value"), "unexpected value: %s\n", value.pszVal);
740
742 PropVariantClear(&id);
744 }
745
746 hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
747 ok(hr == S_FALSE, "Next failed, hr=%lx\n", hr);
748 ok(items_returned == 0, "unexpected item count %li\n", items_returned);
749
750 IWICEnumMetadataItem_Release(enumerator);
751 }
752
753 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
754 ok(hr == S_OK, "GetMetadataFormat failed, hr=%lx\n", hr);
755 ok(IsEqualGUID(&format, &GUID_MetadataFormatChunktEXt), "unexpected format %s\n", wine_dbgstr_guid(&format));
756
757 hr = IWICMetadataReader_GetMetadataFormat(reader, NULL);
758 ok(hr == E_INVALIDARG, "GetMetadataFormat failed, hr=%lx\n", hr);
759
760 id.vt = VT_LPSTR;
761 id.pszVal = CoTaskMemAlloc(strlen("winetest") + 1);
762 strcpy(id.pszVal, "winetest");
763
764 hr = IWICMetadataReader_GetValue(reader, NULL, &id, NULL);
765 ok(hr == S_OK, "GetValue failed, hr=%lx\n", hr);
766
767 hr = IWICMetadataReader_GetValue(reader, &schema, NULL, &value);
768 ok(hr == E_INVALIDARG, "GetValue failed, hr=%lx\n", hr);
769
770 hr = IWICMetadataReader_GetValue(reader, &schema, &id, &value);
771 ok(hr == S_OK, "GetValue failed, hr=%lx\n", hr);
772 ok(value.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt);
773 ok(!strcmp(value.pszVal, "value"), "unexpected value: %s\n", value.pszVal);
775
776 strcpy(id.pszVal, "test");
777
778 hr = IWICMetadataReader_GetValue(reader, &schema, &id, &value);
779 ok(hr == WINCODEC_ERR_PROPERTYNOTFOUND, "GetValue failed, hr=%lx\n", hr);
780
781 PropVariantClear(&id);
782
783 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, NULL, NULL);
784 ok(hr == S_OK, "GetValueByIndex failed, hr=%lx\n", hr);
785
786 hr = IWICMetadataReader_GetValueByIndex(reader, 0, &schema, NULL, NULL);
787 ok(hr == S_OK, "GetValueByIndex failed, hr=%lx\n", hr);
788 ok(schema.vt == VT_EMPTY, "unexpected vt: %i\n", schema.vt);
789
790 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, &id, NULL);
791 ok(hr == S_OK, "GetValueByIndex failed, hr=%lx\n", hr);
792 ok(id.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt);
793 ok(!strcmp(id.pszVal, "winetest"), "unexpected id: %s\n", id.pszVal);
794 PropVariantClear(&id);
795
796 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, NULL, &value);
797 ok(hr == S_OK, "GetValueByIndex failed, hr=%lx\n", hr);
798 ok(value.vt == VT_LPSTR, "unexpected vt: %i\n", value.vt);
799 ok(!strcmp(value.pszVal, "value"), "unexpected value: %s\n", value.pszVal);
801
802 hr = IWICMetadataReader_GetValueByIndex(reader, 1, NULL, NULL, NULL);
803 ok(hr == E_INVALIDARG, "GetValueByIndex failed, hr=%lx\n", hr);
804
805 IWICMetadataReader_Release(reader);
806
807 hr = CoCreateInstance(&CLSID_WICPngTextMetadataWriter, NULL, CLSCTX_INPROC_SERVER,
808 &IID_IWICMetadataWriter, (void **)&writer);
810 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
811 if (FAILED(hr)) return;
812
813 check_interface(writer, &IID_IWICMetadataWriter, TRUE);
814 check_interface(writer, &IID_IWICMetadataReader, TRUE);
817 check_interface(writer, &IID_IWICPersistStream, TRUE);
818 check_interface(writer, &IID_IWICStreamProvider, TRUE);
819
820 load_stream(writer, metadata_tEXt, sizeof(metadata_tEXt), 0);
822
823 IWICMetadataWriter_Release(writer);
824}
825
826static void test_metadata_gAMA(void)
827{
829 HRESULT hr;
831 PROPVARIANT schema, id, value;
832 IWICMetadataWriter *writer;
833 UINT count;
834 GUID format;
835
836 PropVariantInit(&schema);
837 PropVariantInit(&id);
838 PropVariantInit(&value);
839
840 hr = CoCreateInstance(&CLSID_WICPngGamaMetadataReader, NULL, CLSCTX_INPROC_SERVER,
841 &IID_IWICMetadataReader, (void**)&reader);
842 ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG) /*winxp*/, "CoCreateInstance failed, hr=%lx\n", hr);
843 if (FAILED(hr)) return;
844
845 check_interface(reader, &IID_IWICMetadataReader, TRUE);
848 check_interface(reader, &IID_IWICPersistStream, TRUE);
849 check_interface(reader, &IID_IWICStreamProvider, TRUE);
850
852
853 hr = IWICMetadataReader_GetMetadataHandlerInfo(reader, &info);
855 ok(hr == WINCODEC_ERR_COMPONENTNOTFOUND, "Unexpected hr %#lx.\n", hr);
856 if (SUCCEEDED(hr))
857 IWICMetadataHandlerInfo_Release(info);
858
859 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
860 ok(hr == S_OK, "GetMetadataFormat failed, hr=%lx\n", hr);
861 ok(IsEqualGUID(&format, &GUID_MetadataFormatChunkgAMA), "unexpected format %s\n", wine_dbgstr_guid(&format));
862
863 hr = IWICMetadataReader_GetCount(reader, &count);
864 ok(hr == S_OK, "GetCount failed, hr=%lx\n", hr);
865 ok(count == 1, "unexpected count %i\n", count);
866
867 hr = IWICMetadataReader_GetValueByIndex(reader, 0, &schema, &id, &value);
868 ok(hr == S_OK, "GetValue failed, hr=%lx\n", hr);
869
870 ok(schema.vt == VT_EMPTY, "unexpected vt: %i\n", schema.vt);
872
873 ok(id.vt == VT_LPWSTR, "unexpected vt: %i\n", id.vt);
874 ok(!lstrcmpW(id.pwszVal, L"ImageGamma"), "unexpected value: %s\n", wine_dbgstr_w(id.pwszVal));
875 PropVariantClear(&id);
876
877 ok(value.vt == VT_UI4, "unexpected vt: %i\n", value.vt);
878 ok(value.ulVal == 33333, "unexpected value: %lu\n", value.ulVal);
880
881 IWICMetadataReader_Release(reader);
882
883 hr = CoCreateInstance(&CLSID_WICPngGamaMetadataWriter, NULL, CLSCTX_INPROC_SERVER,
884 &IID_IWICMetadataWriter, (void **)&writer);
886 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
887 if (FAILED(hr)) return;
888
889 check_interface(writer, &IID_IWICMetadataWriter, TRUE);
890 check_interface(writer, &IID_IWICMetadataReader, TRUE);
893 check_interface(writer, &IID_IWICPersistStream, TRUE);
894 check_interface(writer, &IID_IWICStreamProvider, TRUE);
895
896 load_stream(writer, metadata_gAMA, sizeof(metadata_gAMA), 0);
898
899 IWICMetadataWriter_Release(writer);
900}
901
902static void test_metadata_cHRM(void)
903{
904 HRESULT hr;
906 PROPVARIANT schema, id, value;
907 IWICMetadataWriter *writer;
908 UINT count;
909 GUID format;
910 int i;
911 static const WCHAR *expected_names[8] =
912 {
913 L"WhitePointX",
914 L"WhitePointY",
915 L"RedX",
916 L"RedY",
917 L"GreenX",
918 L"GreenY",
919 L"BlueX",
920 L"BlueY",
921 };
922 static const ULONG expected_vals[8] = {
923 31270,32900, 64000,33000, 30000,60000, 15000,6000
924 };
925
926 PropVariantInit(&schema);
927 PropVariantInit(&id);
928 PropVariantInit(&value);
929
930 hr = CoCreateInstance(&CLSID_WICPngChrmMetadataReader, NULL, CLSCTX_INPROC_SERVER,
931 &IID_IWICMetadataReader, (void**)&reader);
932 ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG) /*winxp*/, "CoCreateInstance failed, hr=%lx\n", hr);
933 if (FAILED(hr)) return;
934
935 check_interface(reader, &IID_IWICMetadataReader, TRUE);
938 check_interface(reader, &IID_IWICPersistStream, TRUE);
939 check_interface(reader, &IID_IWICStreamProvider, TRUE);
940
942
943 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
944 ok(hr == S_OK, "GetMetadataFormat failed, hr=%lx\n", hr);
945 ok(IsEqualGUID(&format, &GUID_MetadataFormatChunkcHRM), "unexpected format %s\n", wine_dbgstr_guid(&format));
946
947 hr = IWICMetadataReader_GetCount(reader, &count);
948 ok(hr == S_OK, "GetCount failed, hr=%lx\n", hr);
949 ok(count == 8, "unexpected count %i\n", count);
950
951 for (i=0; i<8; i++)
952 {
953 hr = IWICMetadataReader_GetValueByIndex(reader, i, &schema, &id, &value);
954 ok(hr == S_OK, "GetValue failed, hr=%lx\n", hr);
955
956 ok(schema.vt == VT_EMPTY, "unexpected vt: %i\n", schema.vt);
958
959 ok(id.vt == VT_LPWSTR, "unexpected vt: %i\n", id.vt);
960 ok(!lstrcmpW(id.pwszVal, expected_names[i]), "got %s, expected %s\n", wine_dbgstr_w(id.pwszVal), wine_dbgstr_w(expected_names[i]));
961 PropVariantClear(&id);
962
963 ok(value.vt == VT_UI4, "unexpected vt: %i\n", value.vt);
964 ok(value.ulVal == expected_vals[i], "got %lu, expected %lu\n", value.ulVal, expected_vals[i]);
966 }
967
968 IWICMetadataReader_Release(reader);
969
970 hr = CoCreateInstance(&CLSID_WICPngChrmMetadataWriter, NULL, CLSCTX_INPROC_SERVER,
971 &IID_IWICMetadataWriter, (void **)&writer);
973 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
974 if (FAILED(hr)) return;
975
976 check_interface(writer, &IID_IWICMetadataWriter, TRUE);
977 check_interface(writer, &IID_IWICMetadataReader, TRUE);
980 check_interface(writer, &IID_IWICPersistStream, TRUE);
981 check_interface(writer, &IID_IWICStreamProvider, TRUE);
982
983 load_stream(writer, metadata_cHRM, sizeof(metadata_cHRM), 0);
985
986 IWICMetadataWriter_Release(writer);
987}
988
989static void test_metadata_hIST(void)
990{
991 HRESULT hr;
993 PROPVARIANT schema, id, value;
994 IWICMetadataWriter *writer;
995 UINT count, i;
996 GUID format;
997
998 PropVariantInit(&schema);
999 PropVariantInit(&id);
1000 PropVariantInit(&value);
1001
1002 hr = CoCreateInstance(&CLSID_WICPngHistMetadataReader, NULL, CLSCTX_INPROC_SERVER,
1003 &IID_IWICMetadataReader, (void**)&reader);
1004 ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG) /*winxp*/, "CoCreateInstance failed, hr=%lx\n", hr);
1005 if (FAILED(hr)) return;
1006
1007 check_interface(reader, &IID_IWICMetadataReader, TRUE);
1010 check_interface(reader, &IID_IWICPersistStream, TRUE);
1011 check_interface(reader, &IID_IWICStreamProvider, TRUE);
1012
1014
1015 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
1016 ok(hr == S_OK, "GetMetadataFormat failed, hr=%lx\n", hr);
1017 ok(IsEqualGUID(&format, &GUID_MetadataFormatChunkhIST), "unexpected format %s\n", wine_dbgstr_guid(&format));
1018
1019 hr = IWICMetadataReader_GetCount(reader, &count);
1020 ok(hr == S_OK, "GetCount failed, hr=%lx\n", hr);
1021 ok(count == 1, "unexpected count %i\n", count);
1022
1023 hr = IWICMetadataReader_GetValueByIndex(reader, 0, &schema, &id, &value);
1024 ok(hr == S_OK, "GetValue failed, hr=%lx\n", hr);
1025
1026 ok(schema.vt == VT_EMPTY, "unexpected vt: %i\n", schema.vt);
1028
1029 ok(id.vt == VT_LPWSTR, "unexpected vt: %i\n", id.vt);
1030 ok(!lstrcmpW(id.pwszVal, L"Frequencies"), "unexpected value: %s\n", wine_dbgstr_w(id.pwszVal));
1031 PropVariantClear(&id);
1032
1033 ok(value.vt == (VT_UI2|VT_VECTOR), "unexpected vt: %i\n", value.vt);
1034 ok(20 == value.caui.cElems, "expected cElems %d, got %ld\n", 20, value.caub.cElems);
1035 for (i = 0; i < value.caui.cElems; i++)
1036 ok(i+1 == value.caui.pElems[i], "%u: expected value %u, got %u\n", i, i+1, value.caui.pElems[i]);
1038
1039 IWICMetadataReader_Release(reader);
1040
1041 hr = CoCreateInstance(&CLSID_WICPngHistMetadataWriter, NULL, CLSCTX_INPROC_SERVER,
1042 &IID_IWICMetadataWriter, (void **)&writer);
1043 todo_wine
1044 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1045 if (FAILED(hr)) return;
1046
1047 check_interface(writer, &IID_IWICMetadataWriter, TRUE);
1048 check_interface(writer, &IID_IWICMetadataReader, TRUE);
1051 check_interface(writer, &IID_IWICPersistStream, TRUE);
1052 check_interface(writer, &IID_IWICStreamProvider, TRUE);
1053
1054 load_stream(writer, metadata_hIST, sizeof(metadata_hIST), 0);
1056
1057 IWICMetadataWriter_Release(writer);
1058}
1059
1060static void test_metadata_tIME(void)
1061{
1062 HRESULT hr;
1064 IWICMetadataWriter *writer;
1065 UINT count;
1066 GUID format;
1067 static const struct test_data td[] =
1068 {
1069 { VT_UI2, 0, 0, { 2000 }, NULL, L"Year" },
1070 { VT_UI1, 0, 0, { 1 }, NULL, L"Month" },
1071 { VT_UI1, 0, 0, { 2 }, NULL, L"Day" },
1072 { VT_UI1, 0, 0, { 12 }, NULL, L"Hour" },
1073 { VT_UI1, 0, 0, { 34 }, NULL, L"Minute" },
1074 { VT_UI1, 0, 0, { 56 }, NULL, L"Second" },
1075 };
1076
1077 hr = CoCreateInstance(&CLSID_WICPngTimeMetadataReader, NULL, CLSCTX_INPROC_SERVER,
1078 &IID_IWICMetadataReader, (void**)&reader);
1079 ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG) /*winxp*/, "CoCreateInstance failed, hr=%lx\n", hr);
1080 if (FAILED(hr)) return;
1081
1082 check_interface(reader, &IID_IWICMetadataReader, TRUE);
1085 check_interface(reader, &IID_IWICPersistStream, TRUE);
1086 check_interface(reader, &IID_IWICStreamProvider, TRUE);
1087
1089
1090 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
1091 ok(hr == S_OK, "GetMetadataFormat failed, hr=%lx\n", hr);
1092 ok(IsEqualGUID(&format, &GUID_MetadataFormatChunktIME), "unexpected format %s\n", wine_dbgstr_guid(&format));
1093
1094 hr = IWICMetadataReader_GetCount(reader, &count);
1095 ok(hr == S_OK, "GetCount failed, hr=%lx\n", hr);
1096 ok(count == ARRAY_SIZE(td), "unexpected count %i\n", count);
1097
1099
1100 IWICMetadataReader_Release(reader);
1101
1102 hr = CoCreateInstance(&CLSID_WICPngTimeMetadataWriter, NULL, CLSCTX_INPROC_SERVER,
1103 &IID_IWICMetadataWriter, (void **)&writer);
1104 todo_wine
1105 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1106 if (FAILED(hr)) return;
1107
1108 check_interface(writer, &IID_IWICMetadataWriter, TRUE);
1109 check_interface(writer, &IID_IWICMetadataReader, TRUE);
1112 check_interface(writer, &IID_IWICPersistStream, TRUE);
1113 check_interface(writer, &IID_IWICStreamProvider, TRUE);
1114
1115 load_stream(writer, metadata_tIME, sizeof(metadata_tIME), 0);
1117
1118 IWICMetadataWriter_Release(writer);
1119}
1120
1122{
1123 return (s >> 8) | (s << 8);
1124}
1125
1126static inline ULONG ulong_bswap(ULONG l)
1127{
1128 return ((ULONG)ushort_bswap((USHORT)l) << 16) | ushort_bswap((USHORT)(l >> 16));
1129}
1130
1132{
1133 return ((ULONGLONG)ulong_bswap((ULONG)ll) << 32) | ulong_bswap((ULONG)(ll >> 32));
1134}
1135
1136static void byte_swap_ifd_data(char *data)
1137{
1138 USHORT number_of_entries, i;
1139 struct IFD_entry *entry;
1140 char *data_start = data;
1141
1142 number_of_entries = *(USHORT *)data;
1143 *(USHORT *)data = ushort_bswap(*(USHORT *)data);
1144 data += sizeof(USHORT);
1145
1146 for (i = 0; i < number_of_entries; i++)
1147 {
1148 entry = (struct IFD_entry *)data;
1149
1150 switch (entry->type)
1151 {
1152 case IFD_BYTE:
1153 case IFD_SBYTE:
1154 case IFD_ASCII:
1155 case IFD_UNDEFINED:
1156 if (entry->count > 4)
1157 entry->value = ulong_bswap(entry->value);
1158 break;
1159
1160 case IFD_SHORT:
1161 case IFD_SSHORT:
1162 if (entry->count > 2)
1163 {
1164 ULONG j, count = entry->count;
1165 USHORT *us = (USHORT *)(data_start + entry->value);
1166 if (!count) count = 1;
1167 for (j = 0; j < count; j++)
1168 us[j] = ushort_bswap(us[j]);
1169
1170 entry->value = ulong_bswap(entry->value);
1171 }
1172 else
1173 {
1174 ULONG j, count = entry->count;
1175 USHORT *us = (USHORT *)&entry->value;
1176 if (!count) count = 1;
1177 for (j = 0; j < count; j++)
1178 us[j] = ushort_bswap(us[j]);
1179 }
1180 break;
1181
1182 case IFD_LONG:
1183 case IFD_SLONG:
1184 case IFD_FLOAT:
1185 if (entry->count > 1)
1186 {
1187 ULONG j, count = entry->count;
1188 ULONG *ul = (ULONG *)(data_start + entry->value);
1189 if (!count) count = 1;
1190 for (j = 0; j < count; j++)
1191 ul[j] = ulong_bswap(ul[j]);
1192 }
1193 entry->value = ulong_bswap(entry->value);
1194 break;
1195
1196 case IFD_RATIONAL:
1197 case IFD_SRATIONAL:
1198 {
1199 ULONG j;
1200 ULONG *ul = (ULONG *)(data_start + entry->value);
1201 for (j = 0; j < entry->count * 2; j++)
1202 ul[j] = ulong_bswap(ul[j]);
1203 }
1204 entry->value = ulong_bswap(entry->value);
1205 break;
1206
1207 case IFD_DOUBLE:
1208 {
1209 ULONG j;
1210 ULONGLONG *ull = (ULONGLONG *)(data_start + entry->value);
1211 for (j = 0; j < entry->count; j++)
1212 ull[j] = ulonglong_bswap(ull[j]);
1213 }
1214 entry->value = ulong_bswap(entry->value);
1215 break;
1216
1217 default:
1218 assert(0);
1219 break;
1220 }
1221
1222 entry->id = ushort_bswap(entry->id);
1223 entry->type = ushort_bswap(entry->type);
1224 entry->count = ulong_bswap(entry->count);
1225 data += sizeof(*entry);
1226 }
1227}
1228
1230{
1231 static const struct test_data td[28] =
1232 {
1233 { VT_UI2, 0xfe, 0, { 1 } },
1234 { VT_UI4, 0x100, 0, { 222 } },
1235 { VT_UI4, 0x101, 0, { 333 } },
1236 { VT_UI2, 0x102, 0, { 24 } },
1237 { VT_UI4, 0x103, 0, { 32773 } },
1238 { VT_UI8, 0x11a, 0, { ((LONGLONG)3 << 32) | 900 } },
1239 { VT_UI1, 0xf001, 0, { 0x44 } },
1240 { VT_UI1|VT_VECTOR, 0xf002, 4, { 0x44, 0x33, 0x22, 0x11 } },
1241 { VT_I1, 0xf003, 0, { 0x44 } },
1242 { VT_I2, 0xf004, 0, { 0x3344 } },
1243 { VT_I2|VT_VECTOR, 0xf005, 2, { 0x3344, 0x1122 } },
1244 { VT_I4, 0xf006, 0, { 0x11223344 } },
1245 { VT_R4, 0xf007, 0, { 0x11223344 } },
1246 { VT_R8, 0xf008, 0, { ((LONGLONG)0x41d26580 << 32) | 0xb486522c } },
1247 { VT_I8, 0xf009, 0, { ((LONGLONG)0x5a6b7c8d << 32) | 0x1a2b3c4d } },
1248 { VT_UI1|VT_VECTOR, 0xf00a, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
1249 { VT_I2|VT_VECTOR, 0xf00b, 4, { 0x0101, 0x0202, 0x0303, 0x0404 } },
1250 { VT_I4|VT_VECTOR, 0xf00c, 2, { 0x11223344, 0x55667788 } },
1251 { VT_R4|VT_VECTOR, 0xf00d, 2, { 0x449a522b, 0x4608f5ba } },
1252 { VT_LPSTR, 0xf00e, 12, { 0 }, "Hello World!" },
1253 { VT_LPSTR, 0xf00f, 4, { 0 }, "abcd" },
1254 { VT_BLOB, 0xf010, 13, { 0 }, "Hello World!" },
1255 { VT_BLOB, 0xf011, 4, { 0 }, "abcd" },
1256 { VT_UI1, 0xf012, 0, { 0x44 } },
1257 { VT_UI2, 0xf013, 0, { 0x3344 } },
1258 { VT_UI4, 0xf014, 0, { 0x11223344 } },
1259 { VT_R4, 0xf015, 0, { 0x11223344 } },
1260 { VT_I8|VT_VECTOR, 0xf016, 3,
1261 { ((LONGLONG)0x05060708 << 32) | 0x01020304,
1262 ((LONGLONG)0x50607080 << 32) | 0x10203040,
1263 ((LONGLONG)0x55667788 << 32) | 0x11223344 } },
1264 };
1265 PROPVARIANT schema, id, value;
1266 char *IFD_data_swapped;
1267 UINT count;
1268 HRESULT hr;
1269
1270 hr = IWICMetadataReader_GetCount(reader, &count);
1271 ok(hr == S_OK, "GetCount error %#lx\n", hr);
1272 ok(count == 0, "unexpected count %u\n", count);
1273
1275
1276 hr = IWICMetadataReader_GetCount(reader, &count);
1277 ok(hr == S_OK, "GetCount error %#lx\n", hr);
1278 ok(count == ARRAY_SIZE(td), "unexpected count %u\n", count);
1279
1281
1282 /* Test big-endian IFD data */
1283 IFD_data_swapped = HeapAlloc(GetProcessHeap(), 0, sizeof(IFD_data));
1284 memcpy(IFD_data_swapped, &IFD_data, sizeof(IFD_data));
1285 byte_swap_ifd_data(IFD_data_swapped);
1286 load_stream(reader, IFD_data_swapped, sizeof(IFD_data), WICPersistOptionBigEndian);
1287 todo_wine
1289 hr = IWICMetadataReader_GetCount(reader, &count);
1290 ok(hr == S_OK, "GetCount error %#lx\n", hr);
1291 ok(count == ARRAY_SIZE(td), "unexpected count %u\n", count);
1293 HeapFree(GetProcessHeap(), 0, IFD_data_swapped);
1294
1295 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, NULL, NULL);
1296 ok(hr == S_OK, "GetValueByIndex error %#lx\n", hr);
1297
1298 PropVariantInit(&schema);
1299 PropVariantInit(&id);
1300 PropVariantInit(&value);
1301
1302 hr = IWICMetadataReader_GetValueByIndex(reader, count - 1, NULL, NULL, NULL);
1303 ok(hr == S_OK, "GetValueByIndex error %#lx\n", hr);
1304
1305 hr = IWICMetadataReader_GetValueByIndex(reader, 0, &schema, NULL, NULL);
1306 ok(hr == S_OK, "GetValueByIndex error %#lx\n", hr);
1307 ok(schema.vt == VT_EMPTY, "unexpected vt: %u\n", schema.vt);
1308
1309 hr = IWICMetadataReader_GetValueByIndex(reader, count - 1, &schema, NULL, NULL);
1310 ok(hr == S_OK, "GetValueByIndex error %#lx\n", hr);
1311 ok(schema.vt == VT_EMPTY, "unexpected vt: %u\n", schema.vt);
1312
1313 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, &id, NULL);
1314 ok(hr == S_OK, "GetValueByIndex error %#lx\n", hr);
1315 ok(id.vt == VT_UI2, "unexpected vt: %u\n", id.vt);
1316 ok(id.uiVal == 0xfe, "unexpected id: %#x\n", id.uiVal);
1317 PropVariantClear(&id);
1318
1319 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, NULL, &value);
1320 ok(hr == S_OK, "GetValueByIndex error %#lx\n", hr);
1321 ok(value.vt == VT_UI2, "unexpected vt: %u\n", value.vt);
1322 ok(value.uiVal == 1, "unexpected id: %#x\n", value.uiVal);
1324
1325 hr = IWICMetadataReader_GetValueByIndex(reader, count, &schema, NULL, NULL);
1326 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#lx\n", hr);
1327
1328 PropVariantInit(&schema);
1329 PropVariantInit(&id);
1330 PropVariantInit(&value);
1331
1332 hr = IWICMetadataReader_GetValue(reader, &schema, &id, &value);
1333 ok(hr == WINCODEC_ERR_PROPERTYNOTFOUND, "expected WINCODEC_ERR_PROPERTYNOTFOUND, got %#lx\n", hr);
1334
1335 hr = IWICMetadataReader_GetValue(reader, NULL, &id, NULL);
1336 ok(hr == WINCODEC_ERR_PROPERTYNOTFOUND, "expected WINCODEC_ERR_PROPERTYNOTFOUND, got %#lx\n", hr);
1337
1338 hr = IWICMetadataReader_GetValue(reader, &schema, NULL, NULL);
1339 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#lx\n", hr);
1340
1341 hr = IWICMetadataReader_GetValue(reader, &schema, &id, NULL);
1342 ok(hr == WINCODEC_ERR_PROPERTYNOTFOUND, "expected WINCODEC_ERR_PROPERTYNOTFOUND, got %#lx\n", hr);
1343
1344 hr = IWICMetadataReader_GetValue(reader, &schema, NULL, &value);
1345 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#lx\n", hr);
1346
1347 id.vt = VT_UI2;
1348 id.uiVal = 0xf00e;
1349 hr = IWICMetadataReader_GetValue(reader, NULL, &id, NULL);
1350 ok(hr == S_OK, "GetValue error %#lx\n", hr);
1351
1352 /* schema is ignored by Ifd metadata reader */
1353 schema.vt = VT_UI4;
1354 schema.ulVal = 0xdeadbeef;
1355 hr = IWICMetadataReader_GetValue(reader, &schema, &id, &value);
1356 ok(hr == S_OK, "GetValue error %#lx\n", hr);
1357 ok(value.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt);
1358 ok(!strcmp(value.pszVal, "Hello World!"), "unexpected value: %s\n", value.pszVal);
1360
1361 hr = IWICMetadataReader_GetValue(reader, NULL, &id, &value);
1362 ok(hr == S_OK, "GetValue error %#lx\n", hr);
1363 ok(value.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt);
1364 ok(!strcmp(value.pszVal, "Hello World!"), "unexpected value: %s\n", value.pszVal);
1366}
1367
1368static void test_metadata_Ifd(void)
1369{
1371 IWICMetadataWriter *writer;
1372 GUID format;
1373 UINT count;
1374 HRESULT hr;
1375
1376 hr = CoCreateInstance(&CLSID_WICIfdMetadataReader, NULL, CLSCTX_INPROC_SERVER,
1377 &IID_IWICMetadataReader, (void**)&reader);
1378 ok(hr == S_OK, "CoCreateInstance error %#lx\n", hr);
1379
1380 check_interface(reader, &IID_IWICMetadataReader, TRUE);
1383 check_interface(reader, &IID_IWICPersistStream, TRUE);
1384 check_interface(reader, &IID_IWICStreamProvider, TRUE);
1385 check_interface(reader, &IID_IWICMetadataBlockReader, FALSE);
1386
1387 hr = IWICMetadataReader_GetCount(reader, NULL);
1388 ok(hr == E_INVALIDARG, "GetCount error %#lx\n", hr);
1389
1390 hr = IWICMetadataReader_GetCount(reader, &count);
1391 ok(hr == S_OK, "GetCount error %#lx\n", hr);
1392 ok(count == 0, "unexpected count %u\n", count);
1393
1395
1396 test_reader_container_format(reader, &GUID_ContainerFormatTiff);
1397
1398 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
1399 ok(hr == S_OK, "GetMetadataFormat error %#lx\n", hr);
1400 ok(IsEqualGUID(&format, &GUID_MetadataFormatIfd), "unexpected format %s\n", wine_dbgstr_guid(&format));
1401
1402 hr = IWICMetadataReader_GetMetadataFormat(reader, NULL);
1403 ok(hr == E_INVALIDARG, "GetMetadataFormat should fail\n");
1404
1405 IWICMetadataReader_Release(reader);
1406
1407 hr = CoCreateInstance(&CLSID_WICIfdMetadataWriter, NULL, CLSCTX_INPROC_SERVER,
1408 &IID_IWICMetadataWriter, (void **)&writer);
1409 todo_wine
1410 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1411 if (FAILED(hr)) return;
1412
1413 check_interface(writer, &IID_IWICMetadataWriter, TRUE);
1414 check_interface(writer, &IID_IWICMetadataReader, TRUE);
1417 check_interface(writer, &IID_IWICPersistStream, TRUE);
1418 check_interface(writer, &IID_IWICStreamProvider, TRUE);
1419
1420 load_stream(writer, (const char *)&IFD_data, sizeof(IFD_data), 0);
1421 load_stream(writer, (const char *)&IFD_data, sizeof(IFD_data), WICPersistOptionNoCacheStream);
1422
1423 IWICMetadataWriter_Release(writer);
1424}
1425
1426static void test_metadata_Exif(void)
1427{
1428 HRESULT hr;
1430 IWICMetadataWriter *writer;
1431 UINT count=0;
1432 GUID format;
1433
1434 hr = CoCreateInstance(&CLSID_WICExifMetadataReader, NULL, CLSCTX_INPROC_SERVER,
1435 &IID_IWICMetadataReader, (void**)&reader);
1436 todo_wine ok(hr == S_OK, "CoCreateInstance error %#lx\n", hr);
1437 if (FAILED(hr)) return;
1438
1439 check_interface(reader, &IID_IWICMetadataReader, TRUE);
1442 check_interface(reader, &IID_IWICPersistStream, TRUE);
1443 check_interface(reader, &IID_IWICStreamProvider, TRUE);
1444 check_interface(reader, &IID_IWICMetadataBlockReader, FALSE);
1445
1446 hr = IWICMetadataReader_GetCount(reader, NULL);
1447 ok(hr == E_INVALIDARG, "GetCount error %#lx\n", hr);
1448
1449 hr = IWICMetadataReader_GetCount(reader, &count);
1450 ok(hr == S_OK, "GetCount error %#lx\n", hr);
1451 ok(count == 0, "unexpected count %u\n", count);
1452
1453 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
1454 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1455 ok(IsEqualGUID(&format, &GUID_MetadataFormatExif), "Unexpected format %s.\n", wine_dbgstr_guid(&format));
1456
1457 test_reader_container_format(reader, &GUID_MetadataFormatIfd);
1459
1460 IWICMetadataReader_Release(reader);
1461
1462 hr = CoCreateInstance(&CLSID_WICExifMetadataWriter, NULL, CLSCTX_INPROC_SERVER,
1463 &IID_IWICMetadataWriter, (void **)&writer);
1464 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1465 if (FAILED(hr)) return;
1466
1467 check_interface(writer, &IID_IWICMetadataWriter, TRUE);
1468 check_interface(writer, &IID_IWICMetadataReader, TRUE);
1471 check_interface(writer, &IID_IWICPersistStream, TRUE);
1472 todo_wine
1473 check_interface(writer, &IID_IWICStreamProvider, TRUE);
1474
1475 load_stream(writer, (const char *)&IFD_data, sizeof(IFD_data), 0);
1476 load_stream(writer, (const char *)&IFD_data, sizeof(IFD_data), WICPersistOptionNoCacheStream);
1477
1478 IWICMetadataWriter_Release(writer);
1479}
1480
1481static void test_metadata_Gps(void)
1482{
1484 IWICMetadataWriter *writer;
1485 UINT count=0;
1486 GUID format;
1487 HRESULT hr;
1488
1489 hr = CoCreateInstance(&CLSID_WICGpsMetadataReader, NULL, CLSCTX_INPROC_SERVER,
1490 &IID_IWICMetadataReader, (void **)&reader);
1491 todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1492 if (FAILED(hr)) return;
1493
1494 check_interface(reader, &IID_IWICMetadataReader, TRUE);
1497 check_interface(reader, &IID_IWICPersistStream, TRUE);
1498 check_interface(reader, &IID_IWICStreamProvider, TRUE);
1499 check_interface(reader, &IID_IWICMetadataBlockReader, FALSE);
1500
1501 hr = IWICMetadataReader_GetCount(reader, NULL);
1502 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1503
1504 hr = IWICMetadataReader_GetCount(reader, &count);
1505 ok(hr == S_OK, "GetCount error %#lx\n", hr);
1506 ok(!count, "Unexpected count %u.\n", count);
1507
1508 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
1509 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1510 ok(IsEqualGUID(&format, &GUID_MetadataFormatGps), "Unexpected format %s.\n", wine_dbgstr_guid(&format));
1511
1512 test_reader_container_format(reader, &GUID_MetadataFormatIfd);
1514
1515 IWICMetadataReader_Release(reader);
1516
1517 hr = CoCreateInstance(&CLSID_WICGpsMetadataWriter, NULL, CLSCTX_INPROC_SERVER,
1518 &IID_IWICMetadataWriter, (void **)&writer);
1519 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1520 if (FAILED(hr)) return;
1521
1522 check_interface(writer, &IID_IWICMetadataWriter, TRUE);
1523 check_interface(writer, &IID_IWICMetadataReader, TRUE);
1526 check_interface(writer, &IID_IWICPersistStream, TRUE);
1527 check_interface(writer, &IID_IWICStreamProvider, TRUE);
1528
1529 load_stream(writer, (const char *)&IFD_data, sizeof(IFD_data), 0);
1530 load_stream(writer, (const char *)&IFD_data, sizeof(IFD_data), WICPersistOptionNoCacheStream);
1531
1532 IWICMetadataWriter_Release(writer);
1533}
1534
1536{
1537 HRESULT hr;
1539 IStream *stream;
1541 UINT count=0;
1542 GUID format;
1543
1544 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
1545 &IID_IWICComponentFactory, (void**)&factory);
1546 ok(hr == S_OK, "CoCreateInstance failed, hr=%lx\n", hr);
1547
1549
1550 hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
1552 stream, &reader);
1553 ok(hr == E_INVALIDARG, "CreateMetadataReaderFromContainer failed, hr=%lx\n", hr);
1554
1555 hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
1556 &GUID_ContainerFormatPng, NULL, WICPersistOptionDefault,
1557 NULL, &reader);
1558 ok(hr == E_INVALIDARG, "CreateMetadataReaderFromContainer failed, hr=%lx\n", hr);
1559
1560 hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
1561 &GUID_ContainerFormatPng, NULL, WICPersistOptionDefault,
1562 stream, NULL);
1563 ok(hr == E_INVALIDARG, "CreateMetadataReaderFromContainer failed, hr=%lx\n", hr);
1564
1565 hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
1566 &GUID_ContainerFormatPng, NULL, WICPersistOptionDefault,
1567 stream, &reader);
1568 ok(hr == S_OK, "CreateMetadataReaderFromContainer failed, hr=%lx\n", hr);
1569
1570 check_interface(reader, &IID_IWICMetadataReader, TRUE);
1573 check_interface(reader, &IID_IWICPersistStream, TRUE);
1574 check_interface(reader, &IID_IWICStreamProvider, TRUE);
1575
1576 if (SUCCEEDED(hr))
1577 {
1578 hr = IWICMetadataReader_GetCount(reader, &count);
1579 ok(hr == S_OK, "GetCount failed, hr=%lx\n", hr);
1580 ok(count == 1, "unexpected count %i\n", count);
1581
1582 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
1583 ok(hr == S_OK, "GetMetadataFormat failed, hr=%lx\n", hr);
1584 ok(IsEqualGUID(&format, &GUID_MetadataFormatChunktEXt), "unexpected format %s\n", wine_dbgstr_guid(&format));
1585
1586 IWICMetadataReader_Release(reader);
1587 }
1588
1589 hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
1590 &GUID_ContainerFormatWmp, NULL, WICPersistOptionDefault,
1591 stream, &reader);
1592 ok(hr == S_OK, "CreateMetadataReaderFromContainer failed, hr=%lx\n", hr);
1593
1594 if (SUCCEEDED(hr))
1595 {
1596 hr = IWICMetadataReader_GetCount(reader, &count);
1597 ok(hr == S_OK, "GetCount failed, hr=%lx\n", hr);
1598 ok(count == 1, "unexpected count %i\n", count);
1599
1600 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
1601 ok(hr == S_OK, "GetMetadataFormat failed, hr=%lx\n", hr);
1602 ok(IsEqualGUID(&format, &GUID_MetadataFormatUnknown), "unexpected format %s\n", wine_dbgstr_guid(&format));
1603
1604 IWICMetadataReader_Release(reader);
1605 }
1606
1607 hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory, &GUID_ContainerFormatWmp,
1609 ok(hr == WINCODEC_ERR_COMPONENTNOTFOUND, "Unexpected hr %#lx.\n", hr);
1610
1611 IStream_Release(stream);
1612
1613 IWICComponentFactory_Release(factory);
1614}
1615
1617{
1618 IWICPersistStream *persist_stream;
1621 IStream *stream, *stream2;
1623 UINT count = 0;
1624 GUID format;
1625 HRESULT hr;
1626
1627 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
1628 &IID_IWICComponentFactory, (void **)&factory);
1629 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1630
1632
1633 hr = IWICComponentFactory_CreateMetadataReader(factory, NULL, NULL, 0, stream, &reader);
1634 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1635
1636 memset(&format, 0xcc, sizeof(format));
1637 hr = IWICComponentFactory_CreateMetadataReader(factory, &format, NULL, 0, stream, &reader);
1638 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1639
1640 hr = get_persist_stream(reader, &stream2);
1641 todo_wine
1642 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1643 if (SUCCEEDED(hr))
1644 {
1645 ok(stream == stream2, "Unexpected stream.\n");
1646 IStream_Release(stream2);
1647 }
1648
1649 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
1650 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1651 ok(IsEqualGUID(&format, &GUID_MetadataFormatUnknown), "Unexpected format %s.\n", wine_dbgstr_guid(&format));
1652 IWICMetadataReader_Release(reader);
1653
1654 memset(&format, 0xcc, sizeof(format));
1655 hr = IWICComponentFactory_CreateMetadataReader(factory, &format, NULL, WICMetadataCreationFailUnknown, stream, &reader);
1656 ok(hr == WINCODEC_ERR_COMPONENTNOTFOUND, "Unexpected hr %#lx.\n", hr);
1657
1658 hr = IWICComponentFactory_CreateMetadataReader(factory, &GUID_MetadataFormatChunktEXt,
1659 NULL, 0, NULL, &reader);
1660 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1661
1662 hr = get_persist_stream(reader, &stream2);
1663 todo_wine
1664 ok(hr == WINCODEC_ERR_STREAMNOTAVAILABLE, "Unexpected hr %#lx.\n", hr);
1665
1666 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
1667 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1668 ok(IsEqualGUID(&format, &GUID_MetadataFormatChunktEXt), "Unexpected format %s.\n", wine_dbgstr_guid(&format));
1669 IWICMetadataReader_Release(reader);
1670
1671 pos.QuadPart = 0;
1672 hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
1673 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1674 hr = IWICComponentFactory_CreateMetadataReader(factory, &GUID_MetadataFormatChunktEXt, NULL, 0,
1675 stream, NULL);
1676 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1677
1678 hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
1679 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1680 hr = IWICComponentFactory_CreateMetadataReader(factory, &GUID_ContainerFormatPng, NULL, 0, stream, &reader);
1681 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1682 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
1683 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1684 ok(IsEqualGUID(&format, &GUID_MetadataFormatUnknown), "Unexpected format %s.\n", wine_dbgstr_guid(&format));
1685 IWICMetadataReader_Release(reader);
1686
1687 hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
1688 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1689 hr = IWICComponentFactory_CreateMetadataReader(factory, &GUID_MetadataFormatChunktEXt, NULL, 0, stream, &reader);
1690 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1691
1692 check_interface(reader, &IID_IWICMetadataReader, TRUE);
1693 check_interface(reader, &IID_IWICMetadataWriter, FALSE);
1696 check_interface(reader, &IID_IWICPersistStream, TRUE);
1697 check_interface(reader, &IID_IWICStreamProvider, TRUE);
1698
1699 hr = IWICMetadataReader_GetCount(reader, &count);
1700 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1701 ok(count == 1, "Unexpected count %u.\n", count);
1702
1703 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
1704 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1705 ok(IsEqualGUID(&format, &GUID_MetadataFormatChunktEXt), "Unexpected format %s.\n", wine_dbgstr_guid(&format));
1706
1707 IWICMetadataReader_Release(reader);
1708
1709 /* Invalid vendor. */
1710 hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
1711 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1712 hr = IWICComponentFactory_CreateMetadataReader(factory, &GUID_MetadataFormatChunktEXt, &IID_IUnknown, 0, stream, &reader);
1713 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1714 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
1715 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1716 ok(IsEqualGUID(&format, &GUID_MetadataFormatChunktEXt), "Unexpected format %s.\n", wine_dbgstr_guid(&format));
1717 IWICMetadataReader_Release(reader);
1718
1719 /* Mismatching metadata format. */
1720 hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
1721 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1722 hr = IWICComponentFactory_CreateMetadataReader(factory, &GUID_MetadataFormatApp1, NULL, 0, stream, &reader);
1723 todo_wine
1724 ok(hr == WINCODEC_ERR_BADMETADATAHEADER, "Unexpected hr %#lx.\n", hr);
1725
1726 /* With and without caching */
1727 hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
1728 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1729 hr = IWICComponentFactory_CreateMetadataReader(factory, &GUID_MetadataFormatChunktEXt, NULL,
1731 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1732
1733 hr = IWICMetadataReader_GetCount(reader, &count);
1734 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1735 ok(count == 1, "Unexpected count %u.\n", count);
1736
1737 hr = get_persist_stream(reader, &stream2);
1738 todo_wine
1739 ok(hr == WINCODEC_ERR_STREAMNOTAVAILABLE, "Unexpected hr %#lx.\n", hr);
1740
1741 hr = IWICMetadataReader_QueryInterface(reader, &IID_IWICPersistStream, (void **)&persist_stream);
1742 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1743
1744 hr = IWICPersistStream_LoadEx(persist_stream, stream, NULL, 0);
1745 todo_wine
1746 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1747
1748 hr = get_persist_stream(reader, &stream2);
1749 todo_wine
1750 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1751 if (SUCCEEDED(hr))
1752 {
1753 ok(stream == stream2, "Unexpected stream.\n");
1754 IStream_Release(stream2);
1755 }
1756
1757 /* Going from caching to no caching. */
1758 hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
1759 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1760 hr = IWICPersistStream_LoadEx(persist_stream, stream, NULL, WICPersistOptionNoCacheStream);
1761 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1762
1763 hr = get_persist_stream(reader, &stream2);
1764 todo_wine
1765 ok(hr == WINCODEC_ERR_STREAMNOTAVAILABLE, "Unexpected hr %#lx.\n", hr);
1766 todo_wine
1768
1769 IWICPersistStream_Release(persist_stream);
1770
1771 IWICMetadataReader_Release(reader);
1772
1773 IStream_Release(stream);
1774
1775 IWICComponentFactory_Release(factory);
1776}
1777
1778static void test_metadata_png(void)
1779{
1780 static const struct test_data td[6] =
1781 {
1782 { VT_UI2, 0, 0, { 2005 }, NULL, L"Year" },
1783 { VT_UI1, 0, 0, { 6 }, NULL, L"Month" },
1784 { VT_UI1, 0, 0, { 3 }, NULL, L"Day" },
1785 { VT_UI1, 0, 0, { 15 }, NULL, L"Hour" },
1786 { VT_UI1, 0, 0, { 7 }, NULL, L"Minute" },
1787 { VT_UI1, 0, 0, { 45 }, NULL, L"Second" }
1788 };
1789 IStream *stream;
1791 IWICBitmapFrameDecode *frame;
1792 IWICMetadataBlockReader *blockreader;
1794 IWICMetadataQueryReader *queryreader;
1796 GUID containerformat;
1797 HRESULT hr;
1798 UINT count=0xdeadbeef;
1799
1800 hr = CoCreateInstance(&CLSID_WICPngDecoder, NULL, CLSCTX_INPROC_SERVER,
1801 &IID_IWICBitmapDecoder, (void**)&decoder);
1802 ok(hr == S_OK, "CoCreateInstance failed, hr=%lx\n", hr);
1803
1804 if (FAILED(hr)) return;
1805
1807
1808 hr = IWICBitmapDecoder_Initialize(decoder, stream, WICDecodeMetadataCacheOnLoad);
1809 ok(hr == S_OK, "Initialize failed, hr=%lx\n", hr);
1810
1811 check_interface(decoder, &IID_IWICMetadataBlockReader, FALSE);
1812
1813 hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
1814 ok(hr == S_OK, "GetFrame failed, hr=%lx\n", hr);
1815
1816 hr = IWICBitmapFrameDecode_QueryInterface(frame, &IID_IWICMetadataBlockReader, (void**)&blockreader);
1817 ok(hr == S_OK, "QueryInterface failed, hr=%lx\n", hr);
1818
1819 if (SUCCEEDED(hr))
1820 {
1821 hr = IWICMetadataBlockReader_GetContainerFormat(blockreader, NULL);
1822 ok(hr == E_INVALIDARG, "GetContainerFormat failed, hr=%lx\n", hr);
1823
1824 hr = IWICMetadataBlockReader_GetContainerFormat(blockreader, &containerformat);
1825 ok(hr == S_OK, "GetContainerFormat failed, hr=%lx\n", hr);
1826 ok(IsEqualGUID(&containerformat, &GUID_ContainerFormatPng), "unexpected container format\n");
1827
1828 hr = IWICMetadataBlockReader_GetCount(blockreader, NULL);
1829 ok(hr == E_INVALIDARG, "GetCount failed, hr=%lx\n", hr);
1830
1831 hr = IWICMetadataBlockReader_GetCount(blockreader, &count);
1832 ok(hr == S_OK, "GetCount failed, hr=%lx\n", hr);
1833 ok(count == 1, "unexpected count %d\n", count);
1834
1835 if (0)
1836 {
1837 /* Crashes on Windows XP */
1838 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 0, NULL);
1839 ok(hr == E_INVALIDARG, "GetReaderByIndex failed, hr=%lx\n", hr);
1840 }
1841
1842 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 0, &reader);
1843 ok(hr == S_OK, "GetReaderByIndex failed, hr=%lx\n", hr);
1844
1845 if (SUCCEEDED(hr))
1846 {
1847 hr = IWICMetadataReader_GetMetadataFormat(reader, &containerformat);
1848 ok(hr == S_OK, "GetMetadataFormat failed, hr=%#lx\n", hr);
1849 ok(IsEqualGUID(&containerformat, &GUID_MetadataFormatChunktIME) ||
1850 broken(IsEqualGUID(&containerformat, &GUID_MetadataFormatUnknown)) /* Windows XP */,
1851 "unexpected container format\n");
1852
1853 test_reader_container_format(reader, &GUID_ContainerFormatPng);
1854
1855 hr = IWICMetadataReader_GetCount(reader, &count);
1856 ok(hr == S_OK, "GetCount error %#lx\n", hr);
1857 ok(count == 6 || broken(count == 1) /* XP */, "expected 6, got %u\n", count);
1858 if (count == 6)
1860
1861 IWICMetadataReader_Release(reader);
1862 }
1863
1864 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 1, &reader);
1865 todo_wine ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE, "GetReaderByIndex failed, hr=%lx\n", hr);
1866
1867 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
1868 &IID_IWICComponentFactory, (void**)&factory);
1869 ok(hr == S_OK, "CoCreateInstance failed, hr=%lx\n", hr);
1870
1871 hr = IWICComponentFactory_CreateQueryReaderFromBlockReader(factory, NULL, &queryreader);
1872 ok(hr == E_INVALIDARG, "CreateQueryReaderFromBlockReader should have failed: %08lx\n", hr);
1873
1874 hr = IWICComponentFactory_CreateQueryReaderFromBlockReader(factory, blockreader, NULL);
1875 ok(hr == E_INVALIDARG, "CreateQueryReaderFromBlockReader should have failed: %08lx\n", hr);
1876
1877 hr = IWICComponentFactory_CreateQueryReaderFromBlockReader(factory, blockreader, &queryreader);
1878 ok(hr == S_OK, "CreateQueryReaderFromBlockReader failed: %08lx\n", hr);
1879
1880 IWICMetadataQueryReader_Release(queryreader);
1881
1882 IWICComponentFactory_Release(factory);
1883
1884 IWICMetadataBlockReader_Release(blockreader);
1885 }
1886
1887 hr = IWICBitmapFrameDecode_GetMetadataQueryReader(frame, &queryreader);
1888 ok(hr == S_OK, "GetMetadataQueryReader failed: %08lx\n", hr);
1889
1890 if (SUCCEEDED(hr))
1891 {
1892 IWICMetadataQueryReader_Release(queryreader);
1893 }
1894
1895 IWICBitmapFrameDecode_Release(frame);
1896
1897 IWICBitmapDecoder_Release(decoder);
1898
1899 IStream_Release(stream);
1900}
1901
1902static void test_metadata_gif(void)
1903{
1904 static const struct test_data gif_LSD[9] =
1905 {
1906 { VT_UI1|VT_VECTOR, 0, 6, {'G','I','F','8','7','a'}, NULL, { 'S','i','g','n','a','t','u','r','e',0 } },
1907 { VT_UI2, 0, 0, { 1 }, NULL, { 'W','i','d','t','h',0 } },
1908 { VT_UI2, 0, 0, { 1 }, NULL, { 'H','e','i','g','h','t',0 } },
1909 { 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 } },
1910 { VT_UI1, 0, 0, { 0 }, NULL, { 'C','o','l','o','r','R','e','s','o','l','u','t','i','o','n',0 } },
1911 { VT_BOOL, 0, 0, { 0 }, NULL, { 'S','o','r','t','F','l','a','g',0 } },
1912 { 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 } },
1913 { 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 } },
1914 { VT_UI1, 0, 0, { 0 }, NULL, { 'P','i','x','e','l','A','s','p','e','c','t','R','a','t','i','o',0 } }
1915 };
1916 static const struct test_data gif_IMD[8] =
1917 {
1918 { VT_UI2, 0, 0, { 0 }, NULL, { 'L','e','f','t',0 } },
1919 { VT_UI2, 0, 0, { 0 }, NULL, { 'T','o','p',0 } },
1920 { VT_UI2, 0, 0, { 1 }, NULL, { 'W','i','d','t','h',0 } },
1921 { VT_UI2, 0, 0, { 1 }, NULL, { 'H','e','i','g','h','t',0 } },
1922 { 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 } },
1923 { VT_BOOL, 0, 0, { 0 }, NULL, { 'I','n','t','e','r','l','a','c','e','F','l','a','g',0 } },
1924 { VT_BOOL, 0, 0, { 0 }, NULL, { 'S','o','r','t','F','l','a','g',0 } },
1925 { 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 } }
1926 };
1927 static const struct test_data animated_gif_LSD[9] =
1928 {
1929 { VT_UI1|VT_VECTOR, 0, 6, {'G','I','F','8','9','a'}, NULL, { 'S','i','g','n','a','t','u','r','e',0 } },
1930 { VT_UI2, 0, 0, { 1 }, NULL, { 'W','i','d','t','h',0 } },
1931 { VT_UI2, 0, 0, { 1 }, NULL, { 'H','e','i','g','h','t',0 } },
1932 { 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 } },
1933 { VT_UI1, 0, 0, { 2 }, NULL, { 'C','o','l','o','r','R','e','s','o','l','u','t','i','o','n',0 } },
1934 { VT_BOOL, 0, 0, { 0 }, NULL, { 'S','o','r','t','F','l','a','g',0 } },
1935 { 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 } },
1936 { 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 } },
1937 { VT_UI1, 0, 0, { 0 }, NULL, { 'P','i','x','e','l','A','s','p','e','c','t','R','a','t','i','o',0 } }
1938 };
1939 static const struct test_data animated_gif_IMD[8] =
1940 {
1941 { VT_UI2, 0, 0, { 0 }, NULL, { 'L','e','f','t',0 } },
1942 { VT_UI2, 0, 0, { 0 }, NULL, { 'T','o','p',0 } },
1943 { VT_UI2, 0, 0, { 1 }, NULL, { 'W','i','d','t','h',0 } },
1944 { VT_UI2, 0, 0, { 1 }, NULL, { 'H','e','i','g','h','t',0 } },
1945 { 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 } },
1946 { VT_BOOL, 0, 0, { 0 }, NULL, { 'I','n','t','e','r','l','a','c','e','F','l','a','g',0 } },
1947 { VT_BOOL, 0, 0, { 0 }, NULL, { 'S','o','r','t','F','l','a','g',0 } },
1948 { 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 } }
1949 };
1950 static const struct test_data animated_gif_GCE[5] =
1951 {
1952 { VT_UI1, 0, 0, { 0 }, NULL, { 'D','i','s','p','o','s','a','l',0 } },
1953 { VT_BOOL, 0, 0, { 0 }, NULL, { 'U','s','e','r','I','n','p','u','t','F','l','a','g',0 } },
1954 { VT_BOOL, 0, 0, { 1 }, NULL, { 'T','r','a','n','s','p','a','r','e','n','c','y','F','l','a','g',0 } },
1955 { VT_UI2, 0, 0, { 10 }, NULL, { 'D','e','l','a','y',0 } },
1956 { 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 } }
1957 };
1958 static const struct test_data animated_gif_APE[2] =
1959 {
1960 { 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 } },
1961 { VT_UI1|VT_VECTOR, 0, 4, { 0x03,0x01,0x05,0x00 }, NULL, { 'D','a','t','a',0 } }
1962 };
1963 static const struct test_data animated_gif_comment_1[1] =
1964 {
1965 { VT_LPSTR, 0, 12, { 0 }, "Hello World!", { 'T','e','x','t','E','n','t','r','y',0 } }
1966 };
1967 static const struct test_data animated_gif_comment_2[1] =
1968 {
1969 { VT_LPSTR, 0, 8, { 0 }, "image #1", { 'T','e','x','t','E','n','t','r','y',0 } }
1970 };
1971 static const struct test_data animated_gif_plain_1[1] =
1972 {
1973 { VT_BLOB, 0, 17, { 0 }, "\x21\x01\x0d\x61nimation.gif" }
1974 };
1975 static const struct test_data animated_gif_plain_2[1] =
1976 {
1977 { VT_BLOB, 0, 16, { 0 }, "\x21\x01\x0cplaintext #1" }
1978 };
1979 IStream *stream;
1981 IWICBitmapFrameDecode *frame;
1982 IWICMetadataBlockReader *blockreader;
1984 IWICMetadataQueryReader *queryreader;
1985 GUID format;
1986 HRESULT hr;
1987 UINT count;
1988
1989 /* 1x1 pixel gif */
1991
1992 hr = CoCreateInstance(&CLSID_WICGifDecoder, NULL, CLSCTX_INPROC_SERVER,
1993 &IID_IWICBitmapDecoder, (void **)&decoder);
1994 ok(hr == S_OK, "CoCreateInstance error %#lx\n", hr);
1995 hr = IWICBitmapDecoder_Initialize(decoder, stream, WICDecodeMetadataCacheOnLoad);
1996 ok(hr == S_OK, "Initialize error %#lx\n", hr);
1997
1998 IStream_Release(stream);
1999
2000 /* global metadata block */
2001 hr = IWICBitmapDecoder_QueryInterface(decoder, &IID_IWICMetadataBlockReader, (void **)&blockreader);
2002 ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* before Win7 */, "QueryInterface error %#lx\n", hr);
2003
2004 if (SUCCEEDED(hr))
2005 {
2006 hr = IWICMetadataBlockReader_GetContainerFormat(blockreader, &format);
2007 ok(hr == S_OK, "GetContainerFormat error %#lx\n", hr);
2008 ok(IsEqualGUID(&format, &GUID_ContainerFormatGif),
2009 "wrong container format %s\n", wine_dbgstr_guid(&format));
2010
2011 hr = IWICMetadataBlockReader_GetCount(blockreader, &count);
2012 ok(hr == S_OK, "GetCount error %#lx\n", hr);
2013 ok(count == 1, "expected 1, got %u\n", count);
2014
2015 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 0, &reader);
2016 ok(hr == S_OK, "GetReaderByIndex error %#lx\n", hr);
2017
2018 if (SUCCEEDED(hr))
2019 {
2020 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
2021 ok(hr == S_OK, "GetMetadataFormat failed, hr=%#lx\n", hr);
2022 ok(IsEqualGUID(&format, &GUID_MetadataFormatLSD), /* Logical Screen Descriptor */
2023 "wrong metadata format %s\n", wine_dbgstr_guid(&format));
2024
2025 test_reader_container_format(reader, &GUID_ContainerFormatGif);
2026
2027 hr = IWICMetadataReader_GetCount(reader, &count);
2028 ok(hr == S_OK, "GetCount error %#lx\n", hr);
2029 ok(count == ARRAY_SIZE(gif_LSD), "unexpected count %u\n", count);
2030
2031 compare_metadata(reader, gif_LSD, count);
2032
2033 IWICMetadataReader_Release(reader);
2034 }
2035
2036 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 1, &reader);
2037 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#lx\n", hr);
2038
2039 IWICMetadataBlockReader_Release(blockreader);
2040 }
2041
2042 /* frame metadata block */
2043 hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
2044 ok(hr == S_OK, "GetFrame error %#lx\n", hr);
2045
2046 hr = IWICBitmapFrameDecode_QueryInterface(frame, &IID_IWICMetadataBlockReader, (void **)&blockreader);
2047 ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* before Win7 */, "QueryInterface error %#lx\n", hr);
2048
2049 if (SUCCEEDED(hr))
2050 {
2051 hr = IWICMetadataBlockReader_GetContainerFormat(blockreader, NULL);
2052 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#lx\n", hr);
2053
2054 hr = IWICMetadataBlockReader_GetContainerFormat(blockreader, &format);
2055 ok(hr == S_OK, "GetContainerFormat error %#lx\n", hr);
2056 ok(IsEqualGUID(&format, &GUID_ContainerFormatGif),
2057 "wrong container format %s\n", wine_dbgstr_guid(&format));
2058
2059 hr = IWICMetadataBlockReader_GetCount(blockreader, NULL);
2060 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#lx\n", hr);
2061
2062 hr = IWICMetadataBlockReader_GetCount(blockreader, &count);
2063 ok(hr == S_OK, "GetCount error %#lx\n", hr);
2064 ok(count == 1, "expected 1, got %u\n", count);
2065
2066 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 0, &reader);
2067 ok(hr == S_OK, "GetReaderByIndex error %#lx\n", hr);
2068
2069 if (SUCCEEDED(hr))
2070 {
2071 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
2072 ok(hr == S_OK, "GetMetadataFormat failed, hr=%#lx\n", hr);
2073 ok(IsEqualGUID(&format, &GUID_MetadataFormatIMD), /* Image Descriptor */
2074 "wrong metadata format %s\n", wine_dbgstr_guid(&format));
2075
2076 hr = IWICMetadataReader_GetCount(reader, &count);
2077 ok(hr == S_OK, "GetCount error %#lx\n", hr);
2078 ok(count == ARRAY_SIZE(gif_IMD), "unexpected count %u\n", count);
2079
2080 compare_metadata(reader, gif_IMD, count);
2081
2082 IWICMetadataReader_Release(reader);
2083 }
2084
2085 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 1, &reader);
2086 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#lx\n", hr);
2087
2088 IWICMetadataBlockReader_Release(blockreader);
2089 }
2090
2091 IWICBitmapFrameDecode_Release(frame);
2092 IWICBitmapDecoder_Release(decoder);
2093
2094 /* 1x1 pixel gif, 2 frames */
2096
2097 hr = CoCreateInstance(&CLSID_WICGifDecoder, NULL, CLSCTX_INPROC_SERVER,
2098 &IID_IWICBitmapDecoder, (void **)&decoder);
2099 ok(hr == S_OK, "CoCreateInstance error %#lx\n", hr);
2100 hr = IWICBitmapDecoder_Initialize(decoder, stream, WICDecodeMetadataCacheOnLoad);
2101 ok(hr == S_OK, "Initialize error %#lx\n", hr);
2102
2103 IStream_Release(stream);
2104
2105 /* global metadata block */
2106 hr = IWICBitmapDecoder_QueryInterface(decoder, &IID_IWICMetadataBlockReader, (void **)&blockreader);
2107 ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* before Win7 */, "QueryInterface error %#lx\n", hr);
2108
2109 if (SUCCEEDED(hr))
2110 {
2111 hr = IWICMetadataBlockReader_GetContainerFormat(blockreader, &format);
2112 ok(hr == S_OK, "GetContainerFormat error %#lx\n", hr);
2113 ok(IsEqualGUID(&format, &GUID_ContainerFormatGif),
2114 "wrong container format %s\n", wine_dbgstr_guid(&format));
2115
2116 hr = IWICMetadataBlockReader_GetCount(blockreader, &count);
2117 ok(hr == S_OK, "GetCount error %#lx\n", hr);
2118 ok(count == 4, "expected 4, got %u\n", count);
2119
2120 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 0, &reader);
2121 ok(hr == S_OK, "GetReaderByIndex error %#lx\n", hr);
2122
2123 if (SUCCEEDED(hr))
2124 {
2125 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
2126 ok(hr == S_OK, "GetMetadataFormat failed, hr=%#lx\n", hr);
2127 ok(IsEqualGUID(&format, &GUID_MetadataFormatLSD), /* Logical Screen Descriptor */
2128 "wrong metadata format %s\n", wine_dbgstr_guid(&format));
2129
2130 hr = IWICMetadataReader_GetCount(reader, &count);
2131 ok(hr == S_OK, "GetCount error %#lx\n", hr);
2132 ok(count == ARRAY_SIZE(animated_gif_LSD), "unexpected count %u\n", count);
2133
2134 compare_metadata(reader, animated_gif_LSD, count);
2135
2136 IWICMetadataReader_Release(reader);
2137 }
2138
2139 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 1, &reader);
2140 ok(hr == S_OK, "GetReaderByIndex error %#lx\n", hr);
2141
2142 if (SUCCEEDED(hr))
2143 {
2144 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
2145 ok(hr == S_OK, "GetMetadataFormat failed, hr=%#lx\n", hr);
2146 ok(IsEqualGUID(&format, &GUID_MetadataFormatAPE), /* Application Extension */
2147 "wrong metadata format %s\n", wine_dbgstr_guid(&format));
2148
2149 hr = IWICMetadataReader_GetCount(reader, &count);
2150 ok(hr == S_OK, "GetCount error %#lx\n", hr);
2151 ok(count == ARRAY_SIZE(animated_gif_APE), "unexpected count %u\n", count);
2152
2153 compare_metadata(reader, animated_gif_APE, count);
2154
2155 IWICMetadataReader_Release(reader);
2156 }
2157
2158 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 2, &reader);
2159 ok(hr == S_OK, "GetReaderByIndex error %#lx\n", hr);
2160
2161 if (SUCCEEDED(hr))
2162 {
2163 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
2164 ok(hr == S_OK, "GetMetadataFormat failed, hr=%#lx\n", hr);
2165 ok(IsEqualGUID(&format, &GUID_MetadataFormatGifComment), /* Comment Extension */
2166 "wrong metadata format %s\n", wine_dbgstr_guid(&format));
2167
2168 hr = IWICMetadataReader_GetCount(reader, &count);
2169 ok(hr == S_OK, "GetCount error %#lx\n", hr);
2170 ok(count == ARRAY_SIZE(animated_gif_comment_1), "unexpected count %u\n", count);
2171
2172 compare_metadata(reader, animated_gif_comment_1, count);
2173
2174 IWICMetadataReader_Release(reader);
2175 }
2176
2177 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 3, &reader);
2178 ok(hr == S_OK, "GetReaderByIndex error %#lx\n", hr);
2179
2180 if (SUCCEEDED(hr))
2181 {
2182 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
2183 ok(hr == S_OK, "GetMetadataFormat failed, hr=%#lx\n", hr);
2184 ok(IsEqualGUID(&format, &GUID_MetadataFormatUnknown),
2185 "wrong metadata format %s\n", wine_dbgstr_guid(&format));
2186
2187 hr = IWICMetadataReader_GetCount(reader, &count);
2188 ok(hr == S_OK, "GetCount error %#lx\n", hr);
2189 ok(count == ARRAY_SIZE(animated_gif_plain_1), "unexpected count %u\n", count);
2190
2191 compare_metadata(reader, animated_gif_plain_1, count);
2192
2193 IWICMetadataReader_Release(reader);
2194 }
2195
2196 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 4, &reader);
2197 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#lx\n", hr);
2198
2199 IWICMetadataBlockReader_Release(blockreader);
2200 }
2201
2202 /* frame metadata block */
2203 hr = IWICBitmapDecoder_GetFrame(decoder, 1, &frame);
2204 ok(hr == S_OK, "GetFrame error %#lx\n", hr);
2205
2206 hr = IWICBitmapFrameDecode_QueryInterface(frame, &IID_IWICMetadataBlockReader, (void **)&blockreader);
2207 ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* before Win7 */, "QueryInterface error %#lx\n", hr);
2208
2209 if (SUCCEEDED(hr))
2210 {
2211 hr = IWICMetadataBlockReader_GetContainerFormat(blockreader, NULL);
2212 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#lx\n", hr);
2213
2214 hr = IWICMetadataBlockReader_GetContainerFormat(blockreader, &format);
2215 ok(hr == S_OK, "GetContainerFormat error %#lx\n", hr);
2216 ok(IsEqualGUID(&format, &GUID_ContainerFormatGif),
2217 "wrong container format %s\n", wine_dbgstr_guid(&format));
2218
2219 hr = IWICMetadataBlockReader_GetCount(blockreader, NULL);
2220 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#lx\n", hr);
2221
2222 hr = IWICMetadataBlockReader_GetCount(blockreader, &count);
2223 ok(hr == S_OK, "GetCount error %#lx\n", hr);
2224 ok(count == 4, "expected 4, got %u\n", count);
2225
2226 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 0, &reader);
2227 ok(hr == S_OK, "GetReaderByIndex error %#lx\n", hr);
2228
2229 if (SUCCEEDED(hr))
2230 {
2231 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
2232 ok(hr == S_OK, "GetMetadataFormat failed, hr=%#lx\n", hr);
2233 ok(IsEqualGUID(&format, &GUID_MetadataFormatIMD), /* Image Descriptor */
2234 "wrong metadata format %s\n", wine_dbgstr_guid(&format));
2235
2236 hr = IWICMetadataReader_GetCount(reader, &count);
2237 ok(hr == S_OK, "GetCount error %#lx\n", hr);
2238 ok(count == ARRAY_SIZE(animated_gif_IMD), "unexpected count %u\n", count);
2239
2240 compare_metadata(reader, animated_gif_IMD, count);
2241
2242 IWICMetadataReader_Release(reader);
2243 }
2244
2245 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 1, &reader);
2246 ok(hr == S_OK, "GetReaderByIndex error %#lx\n", hr);
2247
2248 if (SUCCEEDED(hr))
2249 {
2250 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
2251 ok(hr == S_OK, "GetMetadataFormat failed, hr=%#lx\n", hr);
2252 ok(IsEqualGUID(&format, &GUID_MetadataFormatGCE), /* Graphic Control Extension */
2253 "wrong metadata format %s\n", wine_dbgstr_guid(&format));
2254
2255 hr = IWICMetadataReader_GetCount(reader, &count);
2256 ok(hr == S_OK, "GetCount error %#lx\n", hr);
2257 ok(count == ARRAY_SIZE(animated_gif_GCE), "unexpected count %u\n", count);
2258
2259 compare_metadata(reader, animated_gif_GCE, count);
2260
2261 IWICMetadataReader_Release(reader);
2262 }
2263
2264 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 2, &reader);
2265 ok(hr == S_OK, "GetReaderByIndex error %#lx\n", hr);
2266
2267 if (SUCCEEDED(hr))
2268 {
2269 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
2270 ok(hr == S_OK, "GetMetadataFormat failed, hr=%#lx\n", hr);
2271 ok(IsEqualGUID(&format, &GUID_MetadataFormatGifComment), /* Comment Extension */
2272 "wrong metadata format %s\n", wine_dbgstr_guid(&format));
2273
2274 hr = IWICMetadataReader_GetCount(reader, &count);
2275 ok(hr == S_OK, "GetCount error %#lx\n", hr);
2276 ok(count == ARRAY_SIZE(animated_gif_comment_2), "unexpected count %u\n", count);
2277
2278 if (count == 1)
2279 compare_metadata(reader, animated_gif_comment_2, count);
2280
2281 IWICMetadataReader_Release(reader);
2282 }
2283
2284 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 3, &reader);
2285 ok(hr == S_OK, "GetReaderByIndex error %#lx\n", hr);
2286
2287 if (SUCCEEDED(hr))
2288 {
2289 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
2290 ok(hr == S_OK, "GetMetadataFormat failed, hr=%#lx\n", hr);
2291 ok(IsEqualGUID(&format, &GUID_MetadataFormatUnknown),
2292 "wrong metadata format %s\n", wine_dbgstr_guid(&format));
2293
2294 hr = IWICMetadataReader_GetCount(reader, &count);
2295 ok(hr == S_OK, "GetCount error %#lx\n", hr);
2296 ok(count == ARRAY_SIZE(animated_gif_plain_2), "unexpected count %u\n", count);
2297
2298 compare_metadata(reader, animated_gif_plain_2, count);
2299
2300 IWICMetadataReader_Release(reader);
2301 }
2302
2303 hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 4, &reader);
2304 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#lx\n", hr);
2305
2306 IWICMetadataBlockReader_Release(blockreader);
2307 }
2308
2309 hr = IWICBitmapDecoder_GetMetadataQueryReader(decoder, &queryreader);
2310 ok(hr == S_OK || broken(hr == WINCODEC_ERR_UNSUPPORTEDOPERATION) /* before Vista */,
2311 "GetMetadataQueryReader error %#lx\n", hr);
2312 if (SUCCEEDED(hr))
2313 {
2314 static const struct
2315 {
2316 const char *query;
2317 HRESULT hr;
2318 UINT vt;
2319 } decoder_data[] =
2320 {
2321 { "/logscrdesc/Signature", S_OK, VT_UI1 | VT_VECTOR },
2322 { "/[0]logscrdesc/Signature", S_OK, VT_UI1 | VT_VECTOR },
2323 { "/logscrdesc/\\Signature", S_OK, VT_UI1 | VT_VECTOR },
2324 { "/Logscrdesc/\\signature", S_OK, VT_UI1 | VT_VECTOR },
2325 { "/logscrdesc/{str=signature}", S_OK, VT_UI1 | VT_VECTOR },
2326 { "/[0]logscrdesc/{str=signature}", S_OK, VT_UI1 | VT_VECTOR },
2327 { "/logscrdesc/{wstr=signature}", S_OK, VT_UI1 | VT_VECTOR },
2328 { "/[0]logscrdesc/{wstr=signature}", S_OK, VT_UI1 | VT_VECTOR },
2329 { "/appext/Application", S_OK, VT_UI1 | VT_VECTOR },
2330 { "/appext/{STR=APPlication}", S_OK, VT_UI1 | VT_VECTOR },
2331 { "/appext/{WSTR=APPlication}", S_OK, VT_UI1 | VT_VECTOR },
2332 { "/LogSCRdesC", S_OK, VT_UNKNOWN },
2333 { "/[0]LogSCRdesC", S_OK, VT_UNKNOWN },
2334 { "/appEXT", S_OK, VT_UNKNOWN },
2335 { "/[0]appEXT", S_OK, VT_UNKNOWN },
2336 { "grctlext", WINCODEC_ERR_PROPERTYNOTSUPPORTED, 0 },
2337 { "/imgdesc", WINCODEC_ERR_PROPERTYNOTFOUND, 0 },
2338 };
2339 WCHAR name[256];
2340 UINT len, i, j;
2341 PROPVARIANT value;
2342 IWICMetadataQueryReader *meta_reader;
2343
2344 hr = IWICMetadataQueryReader_GetContainerFormat(queryreader, &format);
2345 ok(hr == S_OK, "GetContainerFormat error %#lx\n", hr);
2346 ok(IsEqualGUID(&format, &GUID_ContainerFormatGif),
2347 "wrong container format %s\n", wine_dbgstr_guid(&format));
2348
2349 name[0] = 0;
2350 len = 0xdeadbeef;
2351 hr = IWICMetadataQueryReader_GetLocation(queryreader, 256, name, &len);
2352 ok(hr == S_OK, "GetLocation error %#lx\n", hr);
2353 ok(len == 2, "expected 2, got %u\n", len);
2354 ok(!lstrcmpW(name, L"/"), "expected '/', got %s\n", wine_dbgstr_w(name));
2355
2356 for (i = 0; i < ARRAY_SIZE(decoder_data); i++)
2357 {
2358 WCHAR queryW[256];
2359
2360 if (winetest_debug > 1)
2361 trace("query: %s\n", decoder_data[i].query);
2362 MultiByteToWideChar(CP_ACP, 0, decoder_data[i].query, -1, queryW, 256);
2363
2364 hr = IWICMetadataQueryReader_GetMetadataByName(queryreader, queryW, NULL);
2365 ok(hr == decoder_data[i].hr, "GetMetadataByName(%s) returned %#lx, expected %#lx\n", wine_dbgstr_w(queryW), hr, decoder_data[i].hr);
2366
2367 PropVariantInit(&value);
2368 hr = IWICMetadataQueryReader_GetMetadataByName(queryreader, queryW, &value);
2369 ok(hr == decoder_data[i].hr, "GetMetadataByName(%s) returned %#lx, expected %#lx\n", wine_dbgstr_w(queryW), hr, decoder_data[i].hr);
2370 ok(value.vt == decoder_data[i].vt, "expected %#x, got %#x\n", decoder_data[i].vt, value.vt);
2371 if (hr == S_OK && value.vt == VT_UNKNOWN)
2372 {
2373 hr = IUnknown_QueryInterface(value.punkVal, &IID_IWICMetadataQueryReader, (void **)&meta_reader);
2374 ok(hr == S_OK, "QueryInterface error %#lx\n", hr);
2375
2376 name[0] = 0;
2377 len = 0xdeadbeef;
2378 hr = IWICMetadataQueryReader_GetLocation(meta_reader, 256, name, &len);
2379 ok(hr == S_OK, "GetLocation error %#lx\n", hr);
2380 ok(len == lstrlenW(queryW) + 1, "expected %u, got %u\n", lstrlenW(queryW) + 1, len);
2381 ok(!lstrcmpW(name, queryW), "expected %s, got %s\n", wine_dbgstr_w(queryW), wine_dbgstr_w(name));
2382
2383 for (j = 0; j < ARRAY_SIZE(decoder_data); j++)
2384 {
2385 MultiByteToWideChar(CP_ACP, 0, decoder_data[j].query, -1, queryW, 256);
2386
2387 if (CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, queryW, len-1, name, len-1) == CSTR_EQUAL && decoder_data[j].query[len - 1] != 0)
2388 {
2389 if (winetest_debug > 1)
2390 trace("query: %s\n", wine_dbgstr_w(queryW + len - 1));
2392 hr = IWICMetadataQueryReader_GetMetadataByName(meta_reader, queryW + len - 1, &value);
2393 ok(hr == decoder_data[j].hr, "GetMetadataByName(%s) returned %#lx, expected %#lx\n", wine_dbgstr_w(queryW + len - 1), hr, decoder_data[j].hr);
2394 ok(value.vt == decoder_data[j].vt, "expected %#x, got %#x\n", decoder_data[j].vt, value.vt);
2395 }
2396 }
2397
2398 IWICMetadataQueryReader_Release(meta_reader);
2399 }
2400
2402 }
2403
2404 IWICMetadataQueryReader_Release(queryreader);
2405 }
2406
2407 hr = IWICBitmapFrameDecode_GetMetadataQueryReader(frame, &queryreader);
2408 ok(hr == S_OK || broken(hr == WINCODEC_ERR_UNSUPPORTEDOPERATION) /* before Vista */,
2409 "GetMetadataQueryReader error %#lx\n", hr);
2410 if (SUCCEEDED(hr))
2411 {
2412 static const struct
2413 {
2414 const char *query;
2415 HRESULT hr;
2416 UINT vt;
2417 } frame_data[] =
2418 {
2419 { "/grctlext/Delay", S_OK, VT_UI2 },
2420 { "/[0]grctlext/Delay", S_OK, VT_UI2 },
2421 { "/grctlext/{str=delay}", S_OK, VT_UI2 },
2422 { "/[0]grctlext/{str=delay}", S_OK, VT_UI2 },
2423 { "/grctlext/{wstr=delay}", S_OK, VT_UI2 },
2424 { "/[0]grctlext/{wstr=delay}", S_OK, VT_UI2 },
2425 { "/imgdesc/InterlaceFlag", S_OK, VT_BOOL },
2426 { "/imgdesc/{STR=interlaceFLAG}", S_OK, VT_BOOL },
2427 { "/imgdesc/{WSTR=interlaceFLAG}", S_OK, VT_BOOL },
2428 { "/grctlext", S_OK, VT_UNKNOWN },
2429 { "/[0]grctlext", S_OK, VT_UNKNOWN },
2430 { "/imgdesc", S_OK, VT_UNKNOWN },
2431 { "/[0]imgdesc", S_OK, VT_UNKNOWN },
2432 { "/LogSCRdesC", WINCODEC_ERR_PROPERTYNOTFOUND, 0 },
2433 { "/appEXT", WINCODEC_ERR_PROPERTYNOTFOUND, 0 },
2434 { "/grctlext/{\\str=delay}", WINCODEC_ERR_WRONGSTATE, 0 },
2435 { "/grctlext/{str=\\delay}", S_OK, VT_UI2 },
2436 { "grctlext/Delay", WINCODEC_ERR_PROPERTYNOTSUPPORTED, 0 },
2437 };
2438 static const WCHAR guidW[] = {'/','{','g','u','i','d','=','\\',0};
2439 WCHAR name[256], queryW[256];
2440 UINT len, i;
2441 PROPVARIANT value;
2442 IWICMetadataQueryReader *meta_reader;
2443
2444 hr = IWICMetadataQueryReader_GetContainerFormat(queryreader, &format);
2445 ok(hr == S_OK, "GetContainerFormat error %#lx\n", hr);
2446 ok(IsEqualGUID(&format, &GUID_ContainerFormatGif),
2447 "wrong container format %s\n", wine_dbgstr_guid(&format));
2448
2449 name[0] = 0;
2450 len = 0xdeadbeef;
2451 hr = IWICMetadataQueryReader_GetLocation(queryreader, 256, name, &len);
2452 ok(hr == S_OK, "GetLocation error %#lx\n", hr);
2453 ok(len == 2, "expected 2, got %u\n", len);
2454 ok(!lstrcmpW(name, L"/"), "expected '/', got %s\n", wine_dbgstr_w(name));
2455
2456 for (i = 0; i < ARRAY_SIZE(frame_data); i++)
2457 {
2458 if (winetest_debug > 1)
2459 trace("query: %s\n", frame_data[i].query);
2460 MultiByteToWideChar(CP_ACP, 0, frame_data[i].query, -1, queryW, 256);
2461 PropVariantInit(&value);
2462 hr = IWICMetadataQueryReader_GetMetadataByName(queryreader, queryW, &value);
2463 ok(hr == frame_data[i].hr, "GetMetadataByName(%s) returned %#lx, expected %#lx\n", wine_dbgstr_w(queryW), hr, frame_data[i].hr);
2464 ok(value.vt == frame_data[i].vt, "expected %#x, got %#x\n", frame_data[i].vt, value.vt);
2465 if (hr == S_OK && value.vt == VT_UNKNOWN)
2466 {
2467 hr = IUnknown_QueryInterface(value.punkVal, &IID_IWICMetadataQueryReader, (void **)&meta_reader);
2468 ok(hr == S_OK, "QueryInterface error %#lx\n", hr);
2469
2470 name[0] = 0;
2471 len = 0xdeadbeef;
2472 hr = IWICMetadataQueryReader_GetLocation(meta_reader, 256, name, &len);
2473 ok(hr == S_OK, "GetLocation error %#lx\n", hr);
2474 ok(len == lstrlenW(queryW) + 1, "expected %u, got %u\n", lstrlenW(queryW) + 1, len);
2475 ok(!lstrcmpW(name, queryW), "expected %s, got %s\n", wine_dbgstr_w(queryW), wine_dbgstr_w(name));
2476
2477 IWICMetadataQueryReader_Release(meta_reader);
2478 }
2479
2481 }
2482
2483 name[0] = 0;
2484 len = 0xdeadbeef;
2485 hr = WICMapGuidToShortName(&GUID_MetadataFormatIMD, 256, name, &len);
2486 ok(hr == S_OK, "WICMapGuidToShortName error %#lx\n", hr);
2487 ok(!lstrcmpW(name, L"imgdesc"), "wrong short name %s\n", wine_dbgstr_w(name));
2488
2489 format = GUID_NULL;
2490 hr = WICMapShortNameToGuid(L"imgdesc", &format);
2491 ok(hr == S_OK, "WICMapGuidToShortName error %#lx\n", hr);
2492 ok(IsEqualGUID(&format, &GUID_MetadataFormatIMD), "wrong guid %s\n", wine_dbgstr_guid(&format));
2493
2494 format = GUID_NULL;
2495 hr = WICMapShortNameToGuid(L"ImgDesc", &format);
2496 ok(hr == S_OK, "WICMapGuidToShortName error %#lx\n", hr);
2497 ok(IsEqualGUID(&format, &GUID_MetadataFormatIMD), "wrong guid %s\n", wine_dbgstr_guid(&format));
2498
2499 lstrcpyW(queryW, guidW);
2500 StringFromGUID2(&GUID_MetadataFormatIMD, queryW + lstrlenW(queryW) - 1, 39);
2501 memcpy(queryW, guidW, sizeof(guidW) - 2);
2502 if (winetest_debug > 1)
2503 trace("query: %s\n", wine_dbgstr_w(queryW));
2504 PropVariantInit(&value);
2505 hr = IWICMetadataQueryReader_GetMetadataByName(queryreader, queryW, &value);
2506 ok(hr == S_OK, "GetMetadataByName(%s) error %#lx\n", wine_dbgstr_w(queryW), hr);
2507 ok(value.vt == VT_UNKNOWN, "expected VT_UNKNOWN, got %#x\n", value.vt);
2509
2510 IWICMetadataQueryReader_Release(queryreader);
2511 }
2512
2513 IWICBitmapFrameDecode_Release(frame);
2514 IWICBitmapDecoder_Release(decoder);
2515}
2516
2517static void test_metadata_LSD(void)
2518{
2519 static const char LSD_data[] = "hello world!\x1\x2\x3\x4\xab\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf";
2520 static const struct test_data td[9] =
2521 {
2522 { VT_UI1|VT_VECTOR, 0, 6, {'w','o','r','l','d','!'}, NULL, L"Signature" },
2523 { VT_UI2, 0, 0, { 0x201 }, NULL, L"Width" },
2524 { VT_UI2, 0, 0, { 0x403 }, NULL, L"Height" },
2525 { VT_BOOL, 0, 0, { 1 }, NULL, L"GlobalColorTableFlag" },
2526 { VT_UI1, 0, 0, { 2 }, NULL, L"ColorResolution" },
2527 { VT_BOOL, 0, 0, { 1 }, NULL, L"SortFlag" },
2528 { VT_UI1, 0, 0, { 3 }, NULL, L"GlobalColorTableSize" },
2529 { VT_UI1, 0, 0, { 6 }, NULL, L"BackgroundColorIndex" },
2530 { VT_UI1, 0, 0, { 7 }, NULL, L"PixelAspectRatio" }
2531 };
2533 HRESULT hr;
2534 IStream *stream;
2535 IWICPersistStream *persist;
2537 IWICMetadataWriter *writer;
2539 WCHAR name[64];
2540 UINT count, dummy;
2541 GUID format;
2542 CLSID id;
2543
2544 hr = CoCreateInstance(&CLSID_WICLSDMetadataReader, NULL, CLSCTX_INPROC_SERVER,
2545 &IID_IWICMetadataReader, (void **)&reader);
2546 ok(hr == S_OK || broken(hr == E_NOINTERFACE || hr == REGDB_E_CLASSNOTREG) /* before Win7 */,
2547 "CoCreateInstance error %#lx\n", hr);
2548 if (FAILED(hr)) return;
2549
2550 check_interface(reader, &IID_IWICMetadataReader, TRUE);
2553 check_interface(reader, &IID_IWICPersistStream, TRUE);
2554 check_interface(reader, &IID_IWICStreamProvider, TRUE);
2555
2556 stream = create_stream(LSD_data, sizeof(LSD_data));
2557
2558 test_reader_container_format(reader, &GUID_ContainerFormatGif);
2559
2560 pos.QuadPart = 6;
2561 hr = IStream_Seek(stream, pos, SEEK_SET, NULL);
2562 ok(hr == S_OK, "IStream_Seek error %#lx\n", hr);
2563
2564 hr = IUnknown_QueryInterface(reader, &IID_IWICPersistStream, (void **)&persist);
2565 ok(hr == S_OK, "QueryInterface error %#lx\n", hr);
2566
2567 hr = IWICPersistStream_Load(persist, stream);
2568 ok(hr == S_OK, "Load error %#lx\n", hr);
2569 todo_wine
2571
2572 IWICPersistStream_Release(persist);
2573
2574 hr = IWICMetadataReader_GetCount(reader, &count);
2575 ok(hr == S_OK, "GetCount error %#lx\n", hr);
2576 ok(count == ARRAY_SIZE(td), "unexpected count %u\n", count);
2577
2579
2580 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
2581 ok(hr == S_OK, "GetMetadataFormat error %#lx\n", hr);
2582 ok(IsEqualGUID(&format, &GUID_MetadataFormatLSD), "wrong format %s\n", wine_dbgstr_guid(&format));
2583
2584 hr = IWICMetadataReader_GetMetadataHandlerInfo(reader, &info);
2585 ok(hr == S_OK, "GetMetadataHandlerInfo error %#lx\n", hr);
2586
2587 hr = IWICMetadataHandlerInfo_GetCLSID(info, &id);
2588 ok(hr == S_OK, "GetCLSID error %#lx\n", hr);
2589 ok(IsEqualGUID(&id, &CLSID_WICLSDMetadataReader), "wrong CLSID %s\n", wine_dbgstr_guid(&id));
2590
2591 hr = IWICMetadataHandlerInfo_GetFriendlyName(info, 64, name, &dummy);
2592 ok(hr == S_OK, "GetFriendlyName error %#lx\n", hr);
2593 ok(!lstrcmpW(name, L"Logical Screen Descriptor Reader"), "wrong LSD reader name %s\n", wine_dbgstr_w(name));
2594
2595 IWICMetadataHandlerInfo_Release(info);
2596 IWICMetadataReader_Release(reader);
2597
2598 IStream_Release(stream);
2599
2600 hr = CoCreateInstance(&CLSID_WICLSDMetadataWriter, NULL, CLSCTX_INPROC_SERVER,
2601 &IID_IWICMetadataWriter, (void **)&writer);
2602 todo_wine
2603 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2604 if (FAILED(hr)) return;
2605
2606 check_interface(writer, &IID_IWICMetadataWriter, TRUE);
2607 check_interface(writer, &IID_IWICMetadataReader, TRUE);
2610 check_interface(writer, &IID_IWICPersistStream, TRUE);
2611 check_interface(writer, &IID_IWICStreamProvider, TRUE);
2612
2613 load_stream(writer, LSD_data, sizeof(LSD_data), 0);
2614 load_stream(writer, LSD_data, sizeof(LSD_data), WICPersistOptionNoCacheStream);
2615
2616 IWICMetadataWriter_Release(writer);
2617}
2618
2619static void test_metadata_IMD(void)
2620{
2621 static const char IMD_data[] = "hello world!\x1\x2\x3\x4\x5\x6\x7\x8\xed\xa\xb\xc\xd\xe\xf";
2622 static const struct test_data td[8] =
2623 {
2624 { VT_UI2, 0, 0, { 0x201 }, NULL, L"Left" },
2625 { VT_UI2, 0, 0, { 0x403 }, NULL, L"Top" },
2626 { VT_UI2, 0, 0, { 0x605 }, NULL, L"Width" },
2627 { VT_UI2, 0, 0, { 0x807 }, NULL, L"Height" },
2628 { VT_BOOL, 0, 0, { 1 }, NULL, L"LocalColorTableFlag" },
2629 { VT_BOOL, 0, 0, { 1 }, NULL, L"InterlaceFlag" },
2630 { VT_BOOL, 0, 0, { 1 }, NULL, L"SortFlag" },
2631 { VT_UI1, 0, 0, { 5 }, NULL, L"LocalColorTableSize" }
2632 };
2634 HRESULT hr;
2635 IStream *stream;
2636 IWICPersistStream *persist;
2638 IWICMetadataWriter *writer;
2640 WCHAR name[64];
2641 UINT count, dummy;
2642 GUID format;
2643 CLSID id;
2644
2645 hr = CoCreateInstance(&CLSID_WICIMDMetadataReader, NULL, CLSCTX_INPROC_SERVER,
2646 &IID_IWICMetadataReader, (void **)&reader);
2647 ok(hr == S_OK || broken(hr == E_NOINTERFACE || hr == REGDB_E_CLASSNOTREG) /* before Win7 */,
2648 "CoCreateInstance error %#lx\n", hr);
2649 if (FAILED(hr)) return;
2650
2651 check_interface(reader, &IID_IWICMetadataReader, TRUE);
2654 check_interface(reader, &IID_IWICPersistStream, TRUE);
2655 check_interface(reader, &IID_IWICStreamProvider, TRUE);
2656
2657 test_reader_container_format(reader, &GUID_ContainerFormatGif);
2658
2659 stream = create_stream(IMD_data, sizeof(IMD_data));
2660
2661 pos.QuadPart = 12;
2662 hr = IStream_Seek(stream, pos, SEEK_SET, NULL);
2663 ok(hr == S_OK, "IStream_Seek error %#lx\n", hr);
2664
2665 hr = IUnknown_QueryInterface(reader, &IID_IWICPersistStream, (void **)&persist);
2666 ok(hr == S_OK, "QueryInterface error %#lx\n", hr);
2667
2668 hr = IWICPersistStream_Load(persist, stream);
2669 ok(hr == S_OK, "Load error %#lx\n", hr);
2670 todo_wine
2672
2673 IWICPersistStream_Release(persist);
2674
2675 hr = IWICMetadataReader_GetCount(reader, &count);
2676 ok(hr == S_OK, "GetCount error %#lx\n", hr);
2677 ok(count == ARRAY_SIZE(td), "unexpected count %u\n", count);
2678
2680
2681 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
2682 ok(hr == S_OK, "GetMetadataFormat error %#lx\n", hr);
2683 ok(IsEqualGUID(&format, &GUID_MetadataFormatIMD), "wrong format %s\n", wine_dbgstr_guid(&format));
2684
2685 hr = IWICMetadataReader_GetMetadataHandlerInfo(reader, &info);
2686 ok(hr == S_OK, "GetMetadataHandlerInfo error %#lx\n", hr);
2687
2688 hr = IWICMetadataHandlerInfo_GetCLSID(info, &id);
2689 ok(hr == S_OK, "GetCLSID error %#lx\n", hr);
2690 ok(IsEqualGUID(&id, &CLSID_WICIMDMetadataReader), "wrong CLSID %s\n", wine_dbgstr_guid(&id));
2691
2692 hr = IWICMetadataHandlerInfo_GetFriendlyName(info, 64, name, &dummy);
2693 ok(hr == S_OK, "GetFriendlyName error %#lx\n", hr);
2694 ok(!lstrcmpW(name, L"Image Descriptor Reader"), "wrong IMD reader name %s\n", wine_dbgstr_w(name));
2695
2696 IWICMetadataHandlerInfo_Release(info);
2697 IWICMetadataReader_Release(reader);
2698
2699 IStream_Release(stream);
2700
2701 hr = CoCreateInstance(&CLSID_WICIMDMetadataWriter, NULL, CLSCTX_INPROC_SERVER,
2702 &IID_IWICMetadataWriter, (void **)&writer);
2703 todo_wine
2704 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2705 if (FAILED(hr)) return;
2706
2707 check_interface(writer, &IID_IWICMetadataWriter, TRUE);
2708 check_interface(writer, &IID_IWICMetadataReader, TRUE);
2711 check_interface(writer, &IID_IWICPersistStream, TRUE);
2712 check_interface(writer, &IID_IWICStreamProvider, TRUE);
2713
2714 load_stream(writer, IMD_data, sizeof(IMD_data), 0);
2715 load_stream(writer, IMD_data, sizeof(IMD_data), WICPersistOptionNoCacheStream);
2716
2717 IWICMetadataWriter_Release(writer);
2718}
2719
2720static void test_metadata_GCE(void)
2721{
2722 static const char GCE_data[] = "hello world!\xa\x2\x3\x4\x5\x6\x7\x8\xed\xa\xb\xc\xd\xe\xf";
2723 static const struct test_data td[5] =
2724 {
2725 { VT_UI1, 0, 0, { 2 }, NULL, L"Disposal" },
2726 { VT_BOOL, 0, 0, { 1 }, NULL, L"UserInputFlag" },
2727 { VT_BOOL, 0, 0, { 0 }, NULL, L"TransparencyFlag" },
2728 { VT_UI2, 0, 0, { 0x302 }, NULL, L"Delay" },
2729 { VT_UI1, 0, 0, { 4 }, NULL, L"TransparentColorIndex" }
2730 };
2732 HRESULT hr;
2733 IStream *stream;
2734 IWICPersistStream *persist;
2736 IWICMetadataWriter *writer;
2738 WCHAR name[64];
2739 UINT count, dummy;
2740 GUID format;
2741 CLSID id;
2742
2743 hr = CoCreateInstance(&CLSID_WICGCEMetadataReader, NULL, CLSCTX_INPROC_SERVER,
2744 &IID_IWICMetadataReader, (void **)&reader);
2745 ok(hr == S_OK || broken(hr == E_NOINTERFACE || hr == REGDB_E_CLASSNOTREG) /* before Win7 */,
2746 "CoCreateInstance error %#lx\n", hr);
2747 if (FAILED(hr)) return;
2748
2749 check_interface(reader, &IID_IWICMetadataReader, TRUE);
2752 check_interface(reader, &IID_IWICPersistStream, TRUE);
2753 check_interface(reader, &IID_IWICStreamProvider, TRUE);
2754
2755 test_reader_container_format(reader, &GUID_ContainerFormatGif);
2756
2757 stream = create_stream(GCE_data, sizeof(GCE_data));
2758
2759 pos.QuadPart = 12;
2760 hr = IStream_Seek(stream, pos, SEEK_SET, NULL);
2761 ok(hr == S_OK, "IStream_Seek error %#lx\n", hr);
2762
2763 hr = IUnknown_QueryInterface(reader, &IID_IWICPersistStream, (void **)&persist);
2764 ok(hr == S_OK, "QueryInterface error %#lx\n", hr);
2765
2766 hr = IWICPersistStream_Load(persist, stream);
2767 ok(hr == S_OK, "Load error %#lx\n", hr);
2768 todo_wine
2770
2771 IWICPersistStream_Release(persist);
2772
2773 hr = IWICMetadataReader_GetCount(reader, &count);
2774 ok(hr == S_OK, "GetCount error %#lx\n", hr);
2775 ok(count == ARRAY_SIZE(td), "unexpected count %u\n", count);
2776
2778
2779 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
2780 ok(hr == S_OK, "GetMetadataFormat error %#lx\n", hr);
2781 ok(IsEqualGUID(&format, &GUID_MetadataFormatGCE), "wrong format %s\n", wine_dbgstr_guid(&format));
2782
2783 hr = IWICMetadataReader_GetMetadataHandlerInfo(reader, &info);
2784 ok(hr == S_OK, "GetMetadataHandlerInfo error %#lx\n", hr);
2785
2786 hr = IWICMetadataHandlerInfo_GetCLSID(info, &id);
2787 ok(hr == S_OK, "GetCLSID error %#lx\n", hr);
2788 ok(IsEqualGUID(&id, &CLSID_WICGCEMetadataReader), "wrong CLSID %s\n", wine_dbgstr_guid(&id));
2789
2790 hr = IWICMetadataHandlerInfo_GetFriendlyName(info, 64, name, &dummy);
2791 ok(hr == S_OK, "GetFriendlyName error %#lx\n", hr);
2792 ok(!lstrcmpW(name, L"Graphic Control Extension Reader"), "wrong GCE reader name %s\n", wine_dbgstr_w(name));
2793
2794 IWICMetadataHandlerInfo_Release(info);
2795 IWICMetadataReader_Release(reader);
2796
2797 IStream_Release(stream);
2798
2799 hr = CoCreateInstance(&CLSID_WICGCEMetadataWriter, NULL, CLSCTX_INPROC_SERVER,
2800 &IID_IWICMetadataWriter, (void **)&writer);
2801 todo_wine
2802 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2803 if (FAILED(hr)) return;
2804
2805 check_interface(writer, &IID_IWICMetadataWriter, TRUE);
2806 check_interface(writer, &IID_IWICMetadataReader, TRUE);
2809 check_interface(writer, &IID_IWICPersistStream, TRUE);
2810 check_interface(writer, &IID_IWICStreamProvider, TRUE);
2811
2812 load_stream(writer, GCE_data, sizeof(GCE_data), 0);
2813 load_stream(writer, GCE_data, sizeof(GCE_data), WICPersistOptionNoCacheStream);
2814
2815 IWICMetadataWriter_Release(writer);
2816}
2817
2818static void test_metadata_APE(void)
2819{
2820 static const char APE_data[] = { 0x21,0xff,0x0b,'H','e','l','l','o',' ','W','o','r','l','d',
2821 /*sub-block*/1,0x11,
2822 /*sub-block*/2,0x22,0x33,
2823 /*sub-block*/4,0x44,0x55,0x66,0x77,
2824 /*terminator*/0 };
2825 static const struct test_data td[2] =
2826 {
2827 { VT_UI1|VT_VECTOR, 0, 11, { 'H','e','l','l','o',' ','W','o','r','l','d' }, NULL, L"Application" },
2828 { VT_UI1|VT_VECTOR, 0, 10, { 1,0x11,2,0x22,0x33,4,0x44,0x55,0x66,0x77 }, NULL, L"Data" }
2829 };
2830 WCHAR dataW[] = { 'd','a','t','a',0 };
2831 HRESULT hr;
2832 IStream *stream;
2833 IWICPersistStream *persist;
2835 IWICMetadataWriter *writer;
2837 WCHAR name[64];
2838 UINT count, dummy, i;
2839 GUID format;
2840 CLSID clsid;
2841 PROPVARIANT id, value;
2842
2843 hr = CoCreateInstance(&CLSID_WICAPEMetadataReader, NULL, CLSCTX_INPROC_SERVER,
2844 &IID_IWICMetadataReader, (void **)&reader);
2845 ok(hr == S_OK || broken(hr == E_NOINTERFACE || hr == REGDB_E_CLASSNOTREG) /* before Win7 */,
2846 "CoCreateInstance error %#lx\n", hr);
2847 if (FAILED(hr)) return;
2848
2849 check_interface(reader, &IID_IWICMetadataReader, TRUE);
2852 check_interface(reader, &IID_IWICPersistStream, TRUE);
2853 check_interface(reader, &IID_IWICStreamProvider, TRUE);
2854
2855 test_reader_container_format(reader, &GUID_ContainerFormatGif);
2856
2857 stream = create_stream(APE_data, sizeof(APE_data));
2858
2859 hr = IUnknown_QueryInterface(reader, &IID_IWICPersistStream, (void **)&persist);
2860 ok(hr == S_OK, "QueryInterface error %#lx\n", hr);
2861
2862 hr = IWICPersistStream_Load(persist, stream);
2863 ok(hr == S_OK, "Load error %#lx\n", hr);
2864 todo_wine
2866
2867 IWICPersistStream_Release(persist);
2868
2869 hr = IWICMetadataReader_GetCount(reader, &count);
2870 ok(hr == S_OK, "GetCount error %#lx\n", hr);
2871 ok(count == ARRAY_SIZE(td), "unexpected count %u\n", count);
2872
2874
2875 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
2876 ok(hr == S_OK, "GetMetadataFormat error %#lx\n", hr);
2877 ok(IsEqualGUID(&format, &GUID_MetadataFormatAPE), "wrong format %s\n", wine_dbgstr_guid(&format));
2878
2879 PropVariantInit(&value);
2880 id.vt = VT_LPWSTR;
2881 id.pwszVal = dataW;
2882
2883 hr = IWICMetadataReader_GetValue(reader, NULL, &id, &value);
2884 ok(hr == S_OK, "GetValue error %#lx\n", hr);
2885 ok(value.vt == (VT_UI1|VT_VECTOR), "unexpected vt: %i\n", id.vt);
2886 ok(td[1].count == value.caub.cElems, "expected cElems %d, got %ld\n", td[1].count, value.caub.cElems);
2887 for (i = 0; i < value.caub.cElems; i++)
2888 ok(td[1].value[i] == value.caub.pElems[i], "%u: expected value %#I64x, got %#x\n", i, td[1].value[i], value.caub.pElems[i]);
2890
2891 hr = IWICMetadataReader_GetMetadataHandlerInfo(reader, &info);
2892 ok(hr == S_OK, "GetMetadataHandlerInfo error %#lx\n", hr);
2893
2894 hr = IWICMetadataHandlerInfo_GetCLSID(info, &clsid);
2895 ok(hr == S_OK, "GetCLSID error %#lx\n", hr);
2896 ok(IsEqualGUID(&clsid, &CLSID_WICAPEMetadataReader), "wrong CLSID %s\n", wine_dbgstr_guid(&clsid));
2897
2898 hr = IWICMetadataHandlerInfo_GetFriendlyName(info, 64, name, &dummy);
2899 ok(hr == S_OK, "GetFriendlyName error %#lx\n", hr);
2900 ok(!lstrcmpW(name, L"Application Extension Reader"), "wrong APE reader name %s\n", wine_dbgstr_w(name));
2901
2902 IWICMetadataHandlerInfo_Release(info);
2903 IWICMetadataReader_Release(reader);
2904
2905 IStream_Release(stream);
2906
2907 hr = CoCreateInstance(&CLSID_WICAPEMetadataWriter, NULL, CLSCTX_INPROC_SERVER,
2908 &IID_IWICMetadataWriter, (void **)&writer);
2909 todo_wine
2910 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2911 if (FAILED(hr)) return;
2912
2913 check_interface(writer, &IID_IWICMetadataWriter, TRUE);
2914 check_interface(writer, &IID_IWICMetadataReader, TRUE);
2917 check_interface(writer, &IID_IWICPersistStream, TRUE);
2918 check_interface(writer, &IID_IWICStreamProvider, TRUE);
2919
2920 load_stream(writer, APE_data, sizeof(APE_data), 0);
2921 load_stream(writer, APE_data, sizeof(APE_data), WICPersistOptionNoCacheStream);
2922
2923 IWICMetadataWriter_Release(writer);
2924}
2925
2927{
2928 static const char GIF_comment_data[] = { 0x21,0xfe,
2929 /*sub-block*/5,'H','e','l','l','o',
2930 /*sub-block*/1,' ',
2931 /*sub-block*/6,'W','o','r','l','d','!',
2932 /*terminator*/0 };
2933 static const struct test_data td[1] =
2934 {
2935 { VT_LPSTR, 0, 12, { 0 }, "Hello World!", L"TextEntry" }
2936 };
2937 WCHAR text_entryW[] = L"TEXTENTRY";
2938 HRESULT hr;
2939 IStream *stream;
2940 IWICPersistStream *persist;
2942 IWICMetadataWriter *writer;
2944 WCHAR name[64];
2945 UINT count, dummy;
2946 GUID format;
2947 CLSID clsid;
2948 PROPVARIANT id, value;
2949
2950 hr = CoCreateInstance(&CLSID_WICGifCommentMetadataReader, NULL, CLSCTX_INPROC_SERVER,
2951 &IID_IWICMetadataReader, (void **)&reader);
2952 ok(hr == S_OK || broken(hr == E_NOINTERFACE || hr == REGDB_E_CLASSNOTREG) /* before Win7 */,
2953 "CoCreateInstance error %#lx\n", hr);
2954 if (FAILED(hr)) return;
2955
2956 check_interface(reader, &IID_IWICMetadataReader, TRUE);
2959 check_interface(reader, &IID_IWICPersistStream, TRUE);
2960 check_interface(reader, &IID_IWICStreamProvider, TRUE);
2961
2962 test_reader_container_format(reader, &GUID_ContainerFormatGif);
2963
2964 stream = create_stream(GIF_comment_data, sizeof(GIF_comment_data));
2965
2966 hr = IUnknown_QueryInterface(reader, &IID_IWICPersistStream, (void **)&persist);
2967 ok(hr == S_OK, "QueryInterface error %#lx\n", hr);
2968
2969 hr = IWICPersistStream_Load(persist, stream);
2970 ok(hr == S_OK, "Load error %#lx\n", hr);
2971 todo_wine
2973
2974 IWICPersistStream_Release(persist);
2975
2976 hr = IWICMetadataReader_GetCount(reader, &count);
2977 ok(hr == S_OK, "GetCount error %#lx\n", hr);
2978 ok(count == ARRAY_SIZE(td), "unexpected count %u\n", count);
2979
2981
2982 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
2983 ok(hr == S_OK, "GetMetadataFormat error %#lx\n", hr);
2984 ok(IsEqualGUID(&format, &GUID_MetadataFormatGifComment), "wrong format %s\n", wine_dbgstr_guid(&format));
2985
2986 PropVariantInit(&value);
2987 id.vt = VT_LPWSTR;
2988 id.pwszVal = text_entryW;
2989
2990 hr = IWICMetadataReader_GetValue(reader, NULL, &id, &value);
2991 ok(hr == S_OK, "GetValue error %#lx\n", hr);
2992 ok(value.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt);
2993 ok(!strcmp(value.pszVal, "Hello World!"), "unexpected value: %s\n", value.pszVal);
2995
2996 hr = IWICMetadataReader_GetMetadataHandlerInfo(reader, &info);
2997 ok(hr == S_OK, "GetMetadataHandlerInfo error %#lx\n", hr);
2998
2999 hr = IWICMetadataHandlerInfo_GetCLSID(info, &clsid);
3000 ok(hr == S_OK, "GetCLSID error %#lx\n", hr);
3001 ok(IsEqualGUID(&clsid, &CLSID_WICGifCommentMetadataReader), "wrong CLSID %s\n", wine_dbgstr_guid(&clsid));
3002
3003 hr = IWICMetadataHandlerInfo_GetFriendlyName(info, 64, name, &dummy);
3004 ok(hr == S_OK, "GetFriendlyName error %#lx\n", hr);
3005 ok(!lstrcmpW(name, L"Comment Extension Reader"), "wrong APE reader name %s\n", wine_dbgstr_w(name));
3006
3007 IWICMetadataHandlerInfo_Release(info);
3008 IWICMetadataReader_Release(reader);
3009
3010 IStream_Release(stream);
3011
3012 hr = CoCreateInstance(&CLSID_WICGifCommentMetadataWriter, NULL, CLSCTX_INPROC_SERVER,
3013 &IID_IWICMetadataWriter, (void **)&writer);
3014 todo_wine
3015 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3016 if (FAILED(hr)) return;
3017
3018 check_interface(writer, &IID_IWICMetadataWriter, TRUE);
3019 check_interface(writer, &IID_IWICMetadataReader, TRUE);
3022 check_interface(writer, &IID_IWICPersistStream, TRUE);
3023 check_interface(writer, &IID_IWICStreamProvider, TRUE);
3024
3025 load_stream(writer, GIF_comment_data, sizeof(GIF_comment_data), 0);
3026 load_stream(writer, GIF_comment_data, sizeof(GIF_comment_data), WICPersistOptionNoCacheStream);
3027
3028 IWICMetadataWriter_Release(writer);
3029}
3030
3032{
3033 HRESULT hr;
3034 UINT len;
3035 WCHAR name[16];
3036
3037 name[0] = 0;
3038 len = 0xdeadbeef;
3039 hr = WICMapGuidToShortName(&GUID_MetadataFormatUnknown, 8, name, &len);
3040 ok(hr == S_OK, "got %#lx\n", hr);
3041 ok(len == 8, "got %u\n", len);
3042 ok(!lstrcmpW(name, L"unknown"), "got %s\n", wine_dbgstr_w(name));
3043
3044 name[0] = 0;
3045 hr = WICMapGuidToShortName(&GUID_MetadataFormatUnknown, 8, name, NULL);
3046 ok(hr == S_OK, "got %#lx\n", hr);
3047 ok(!lstrcmpW(name, L"unknown"), "got %s\n", wine_dbgstr_w(name));
3048
3049 len = 0xdeadbeef;
3050 hr = WICMapGuidToShortName(&GUID_MetadataFormatUnknown, 8, NULL, &len);
3051 ok(hr == S_OK, "got %#lx\n", hr);
3052 ok(len == 8, "got %u\n", len);
3053
3054 len = 0xdeadbeef;
3055 hr = WICMapGuidToShortName(&GUID_MetadataFormatUnknown, 0, NULL, &len);
3056 ok(hr == S_OK, "got %#lx\n", hr);
3057 ok(len == 8, "got %u\n", len);
3058
3059 hr = WICMapGuidToShortName(&GUID_MetadataFormatUnknown, 0, NULL, NULL);
3060 ok(hr == S_OK, "got %#lx\n", hr);
3061
3062 hr = WICMapGuidToShortName(&GUID_MetadataFormatUnknown, 8, NULL, NULL);
3063 ok(hr == S_OK, "got %#lx\n", hr);
3064
3066 ok(hr == WINCODEC_ERR_PROPERTYNOTFOUND, "got %#lx\n", hr);
3067
3068 name[0] = 0;
3069 len = 0xdeadbeef;
3070 hr = WICMapGuidToShortName(&GUID_MetadataFormatUnknown, 4, name, &len);
3072 ok(len == 0xdeadbeef, "got %u\n", len);
3073 ok(!lstrcmpW(name, L"unk"), "got %s\n", wine_dbgstr_w(name));
3074
3075 name[0] = 0;
3076 len = 0xdeadbeef;
3077 hr = WICMapGuidToShortName(&GUID_MetadataFormatUnknown, 0, name, &len);
3078 ok(hr == E_INVALIDARG, "got %#lx\n", hr);
3079 ok(len == 0xdeadbeef, "got %u\n", len);
3080 ok(!name[0], "got %s\n", wine_dbgstr_w(name));
3081
3083 ok(hr == E_INVALIDARG, "got %#lx\n", hr);
3084}
3085
3087{
3088 HRESULT hr;
3089 GUID guid;
3090
3092 ok(hr == E_INVALIDARG, "got %#lx\n", hr);
3093
3095 ok(hr == E_INVALIDARG, "got %#lx\n", hr);
3096
3097 hr = WICMapShortNameToGuid(L"unknown", NULL);
3098 ok(hr == E_INVALIDARG, "got %#lx\n", hr);
3099
3100 hr = WICMapShortNameToGuid(L"unk", &guid);
3101 ok(hr == WINCODEC_ERR_PROPERTYNOTFOUND, "got %#lx\n", hr);
3102
3103 hr = WICMapShortNameToGuid(L"unknown", &guid);
3104 ok(hr == S_OK, "got %#lx\n", hr);
3105 ok(IsEqualGUID(&guid, &GUID_MetadataFormatUnknown), "got %s\n", wine_dbgstr_guid(&guid));
3106
3107 hr = WICMapShortNameToGuid(L"xmp", &guid);
3108 ok(hr == S_OK, "got %#lx\n", hr);
3109 ok(IsEqualGUID(&guid, &GUID_MetadataFormatXMP), "got %s\n", wine_dbgstr_guid(&guid));
3110
3111 guid = GUID_NULL;
3112 hr = WICMapShortNameToGuid(L"XmP", &guid);
3113 ok(hr == S_OK, "got %#lx\n", hr);
3114 ok(IsEqualGUID(&guid, &GUID_MetadataFormatXMP), "got %s\n", wine_dbgstr_guid(&guid));
3115}
3116
3117static const GUID *guid_list[] =
3118{
3119 &GUID_ContainerFormatBmp,
3120 &GUID_ContainerFormatPng,
3121 &GUID_ContainerFormatIco,
3122 &GUID_ContainerFormatJpeg,
3123 &GUID_ContainerFormatTiff,
3124 &GUID_ContainerFormatGif,
3125 &GUID_ContainerFormatWmp,
3126 &GUID_MetadataFormatUnknown,
3127 &GUID_MetadataFormatIfd,
3128 &GUID_MetadataFormatSubIfd,
3129 &GUID_MetadataFormatExif,
3130 &GUID_MetadataFormatGps,
3131 &GUID_MetadataFormatInterop,
3132 &GUID_MetadataFormatApp0,
3133 &GUID_MetadataFormatApp1,
3134 &GUID_MetadataFormatApp13,
3135 &GUID_MetadataFormatIPTC,
3136 &GUID_MetadataFormatIRB,
3137 &GUID_MetadataFormat8BIMIPTC,
3138 &GUID_MetadataFormat8BIMResolutionInfo,
3139 &GUID_MetadataFormat8BIMIPTCDigest,
3140 &GUID_MetadataFormatXMP,
3141 &GUID_MetadataFormatThumbnail,
3142 &GUID_MetadataFormatChunktEXt,
3143 &GUID_MetadataFormatXMPStruct,
3144 &GUID_MetadataFormatXMPBag,
3145 &GUID_MetadataFormatXMPSeq,
3146 &GUID_MetadataFormatXMPAlt,
3147 &GUID_MetadataFormatLSD,
3148 &GUID_MetadataFormatIMD,
3149 &GUID_MetadataFormatGCE,
3150 &GUID_MetadataFormatAPE,
3151 &GUID_MetadataFormatJpegChrominance,
3152 &GUID_MetadataFormatJpegLuminance,
3153 &GUID_MetadataFormatJpegComment,
3154 &GUID_MetadataFormatGifComment,
3155 &GUID_MetadataFormatChunkgAMA,
3156 &GUID_MetadataFormatChunkbKGD,
3157 &GUID_MetadataFormatChunkiTXt,
3158 &GUID_MetadataFormatChunkcHRM,
3159 &GUID_MetadataFormatChunkhIST,
3160 &GUID_MetadataFormatChunkiCCP,
3161 &GUID_MetadataFormatChunksRGB,
3162 &GUID_MetadataFormatChunktIME
3163};
3164
3165static 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 };
3166static 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 };
3167static WCHAR xmp_scheme[] = { 'h','t','t','p',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','x','a','p','/','1','.','0','/',0 };
3168static 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 };
3169static 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 };
3170static 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 };
3171static 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 };
3172static 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 };
3173static WCHAR pdf_scheme[] = { 'h','t','t','p',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','p','d','f','/','1','.','3','/',0 };
3174static 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 };
3175static WCHAR tiff_scheme[] = { 'h','t','t','p',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','t','i','f','f','/','1','.','0','/',0 };
3176static WCHAR exif_scheme[] = { 'h','t','t','p',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','e','x','i','f','/','1','.','0','/',0 };
3177static 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 };
3178static 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 };
3179static 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 };
3180static 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 };
3181static 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 };
3182static 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 };
3183static 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 };
3184static 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 };
3185static 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 };
3186static 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 };
3187static 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 };
3188static 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 };
3189static 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 };
3190static 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 };
3191
3193{
3194 aux_scheme,
3195 rdf_scheme,
3196 dc_scheme,
3197 xmp_scheme,
3203 pdf_scheme,
3213 crs_scheme,
3217 MP_scheme,
3220};
3221
3223{
3224 static WCHAR schemaW[] = L"http://ns.adobe.com/xap/1.0/";
3225 static WCHAR SCHEMAW[] = L"HTTP://ns.adobe.com/xap/1.0/";
3226 HRESULT hr;
3227 UINT len, i, j;
3228 WCHAR name[16];
3229
3230 hr = WICMapSchemaToName(&GUID_MetadataFormatUnknown, NULL, 0, NULL, NULL);
3231 ok(hr == E_INVALIDARG, "got %#lx\n", hr);
3232
3233 hr = WICMapSchemaToName(&GUID_MetadataFormatUnknown, schemaW, 0, NULL, NULL);
3234 ok(hr == E_INVALIDARG, "got %#lx\n", hr);
3235
3236 hr = WICMapSchemaToName(&GUID_MetadataFormatUnknown, schemaW, 0, NULL, &len);
3237 ok(hr == WINCODEC_ERR_PROPERTYNOTFOUND, "got %#lx\n", hr);
3238
3239 hr = WICMapSchemaToName(NULL, schemaW, 0, NULL, &len);
3240 ok(hr == E_INVALIDARG, "got %#lx\n", hr);
3241
3242 hr = WICMapSchemaToName(&GUID_MetadataFormatXMP, schemaW, 0, NULL, NULL);
3243 ok(hr == E_INVALIDARG, "got %#lx\n", hr);
3244
3245 len = 0xdeadbeef;
3246 hr = WICMapSchemaToName(&GUID_MetadataFormatXMP, schemaW, 0, NULL, &len);
3247 ok(hr == S_OK, "got %#lx\n", hr);
3248 ok(len == 4, "got %u\n", len);
3249
3250 len = 0xdeadbeef;
3251 hr = WICMapSchemaToName(&GUID_MetadataFormatXMP, schemaW, 4, NULL, &len);
3252 ok(hr == S_OK, "got %#lx\n", hr);
3253 ok(len == 4, "got %u\n", len);
3254
3255 len = 0xdeadbeef;
3256 hr = WICMapSchemaToName(&GUID_MetadataFormatXMP, SCHEMAW, 0, NULL, &len);
3257 ok(hr == WINCODEC_ERR_PROPERTYNOTFOUND, "got %#lx\n", hr);
3258 ok(len == 0xdeadbeef, "got %u\n", len);
3259
3260 name[0] = 0;
3261 len = 0xdeadbeef;
3262 hr = WICMapSchemaToName(&GUID_MetadataFormatXMP, schemaW, 4, name, &len);
3263 ok(hr == S_OK, "got %#lx\n", hr);
3264 ok(len == 4, "got %u\n", len);
3265 ok(!lstrcmpW(name, L"xmp"), "got %s\n", wine_dbgstr_w(name));
3266
3267 len = 0xdeadbeef;
3268 hr = WICMapSchemaToName(&GUID_MetadataFormatXMP, schemaW, 0, name, &len);
3269 ok(hr == E_INVALIDARG, "got %#lx\n", hr);
3270 ok(len == 0xdeadbeef, "got %u\n", len);
3271
3272 name[0] = 0;
3273 len = 0xdeadbeef;
3274 hr = WICMapSchemaToName(&GUID_MetadataFormatXMP, schemaW, 3, name, &len);
3276 ok(len == 0xdeadbeef, "got %u\n", len);
3277 ok(!lstrcmpW(name, L"xm"), "got %s\n", wine_dbgstr_w(name));
3278
3279 hr = WICMapSchemaToName(&GUID_MetadataFormatXMP, schemaW, 4, name, NULL);
3280 ok(hr == E_INVALIDARG, "got %#lx\n", hr);
3281
3282 /* Check whether modern schemas are supported */
3283 hr = WICMapSchemaToName(&GUID_MetadataFormatXMP, schema_list[0], 0, NULL, &len);
3285 {
3286 win_skip("Modern schemas are not supported\n");
3287 return;
3288 }
3289
3290 for (i = 0; i < ARRAY_SIZE(guid_list); i++)
3291 {
3292 for (j = 0; j < ARRAY_SIZE(schema_list); j++)
3293 {
3295 if (IsEqualGUID(guid_list[i], &GUID_MetadataFormatXMP) ||
3296 IsEqualGUID(guid_list[i], &GUID_MetadataFormatXMPStruct))
3297 {
3298 ok(hr == S_OK, "%u: %u: format %s does not support schema %s\n",
3300 }
3301 else
3302 {
3303 ok(hr == WINCODEC_ERR_PROPERTYNOTFOUND, "%u: %u: format %s supports schema %s\n",
3305 }
3306 }
3307 }
3308}
3309
3311{
3312 const char *schema, *id_str;
3314};
3315
3317{
3320 const struct metadata_item *item;
3321};
3322
3324{
3327 const struct metadata_block *block;
3328};
3329
3330static const struct metadata *current_metadata;
3332
3333static char the_best[] = "The Best";
3334static char the_worst[] = "The Worst";
3335
3337{
3338 if (IsEqualIID(iid, &IID_IUnknown) ||
3339 IsEqualIID(iid, &IID_IWICMetadataReader))
3340 {
3341 *out = iface;
3342 return S_OK;
3343 }
3344
3345 ok(0, "unknown iid %s\n", wine_dbgstr_guid(iid));
3346
3347 *out = NULL;
3348 return E_NOINTERFACE;
3349}
3350
3352{
3353 return 2;
3354}
3355
3357{
3358 return 1;
3359}
3360
3362{
3363 ok(current_metadata_block != NULL, "current_metadata_block can't be NULL\n");
3364 if (!current_metadata_block) return E_POINTER;
3365
3366 *format = *current_metadata_block->metadata_format;
3367 return S_OK;
3368}
3369
3371{
3372 ok(0, "not implemented\n");
3373 return E_NOTIMPL;
3374}
3375
3377{
3378 ok(current_metadata_block != NULL, "current_metadata_block can't be NULL\n");
3379 if (!current_metadata_block) return E_POINTER;
3380
3381 *count = current_metadata_block->count;
3382 return S_OK;
3383}
3384
3385static HRESULT WINAPI mdr_GetValueByIndex(IWICMetadataReader *iface, UINT index, PROPVARIANT *schema, PROPVARIANT *id, PROPVARIANT *value)
3386{
3387 ok(0, "not implemented\n");
3388 return E_NOTIMPL;
3389}
3390
3391static int propvar_cmp(const PROPVARIANT *v1, LONGLONG value2)
3392{
3393 LONGLONG value1;
3394
3395 if (PropVariantToInt64(v1, &value1) != S_OK) return -1;
3396
3397 value1 -= value2;
3398 if (value1) return value1 < 0 ? -1 : 1;
3399 return 0;
3400}
3401
3402static HRESULT WINAPI mdr_GetValue(IWICMetadataReader *iface, const PROPVARIANT *schema, const PROPVARIANT *id, PROPVARIANT *value)
3403{
3404 UINT i;
3405
3406 ok(current_metadata_block != NULL, "current_metadata_block can't be NULL\n");
3407 if (!current_metadata_block) return E_POINTER;
3408
3409 ok(schema != NULL && id != NULL && value != NULL, "%p, %p, %p should not be NULL\n", schema, id, value);
3410
3411 for (i = 0; i < current_metadata_block->count; i++)
3412 {
3413 if (schema->vt != VT_EMPTY)
3414 {
3415 if (!current_metadata_block->item[i].schema)
3416 continue;
3417
3418 switch (schema->vt)
3419 {
3420 case VT_LPSTR:
3421 if (lstrcmpA(schema->pszVal, current_metadata_block->item[i].schema) != 0)
3422 continue;
3423 break;
3424
3425 case VT_LPWSTR:
3426 {
3427 char schemaA[256];
3428 WideCharToMultiByte(CP_ACP, 0, schema->pwszVal, -1, schemaA, sizeof(schemaA), NULL, NULL);
3429 if (lstrcmpA(schemaA, current_metadata_block->item[i].schema) != 0)
3430 continue;
3431 break;
3432 }
3433
3434 default:
3435 ok(0, "unsupported schema vt %u\n", schema->vt);
3436 continue;
3437 }
3438 }
3439 else if (current_metadata_block->item[i].schema)
3440 continue;
3441
3442 switch (id->vt)
3443 {
3444 case VT_LPSTR:
3445 if (current_metadata_block->item[i].id_str)
3446 {
3447 if (!lstrcmpA(id->pszVal, current_metadata_block->item[i].id_str))
3448 {
3449 value->vt = VT_LPSTR;
3450 value->pszVal = the_best;
3451 return S_OK;
3452 }
3453 break;
3454 }
3455 break;
3456
3457 case VT_LPWSTR:
3458 if (current_metadata_block->item[i].id_str)
3459 {
3460 char idA[256];
3461 WideCharToMultiByte(CP_ACP, 0, id->pwszVal, -1, idA, sizeof(idA), NULL, NULL);
3462 if (!lstrcmpA(idA, current_metadata_block->item[i].id_str))
3463 {
3464 value->vt = VT_LPSTR;
3465 value->pszVal = the_worst;
3466 return S_OK;
3467 }
3468 break;
3469 }
3470 break;
3471
3472 case VT_CLSID:
3473 if (IsEqualGUID(id->puuid, &GUID_MetadataFormatXMP) ||
3474 IsEqualGUID(id->puuid, &GUID_ContainerFormatTiff))
3475 {
3476 value->vt = VT_UNKNOWN;
3477 value->punkVal = (IUnknown *)iface;
3478 return S_OK;
3479 }
3480 break;
3481
3482 default:
3483 if (!propvar_cmp(id, current_metadata_block->item[i].id))
3484 {
3485 value->vt = current_metadata_block->item[i].type;
3486 value->uiVal = current_metadata_block->item[i].value;
3487 return S_OK;
3488 }
3489 break;
3490 }
3491 }
3492
3493 return 0xdeadbeef;
3494}
3495
3497{
3498 ok(0, "not implemented\n");
3499 return E_NOTIMPL;
3500}
3501
3502static const IWICMetadataReaderVtbl mdr_vtbl =
3503{
3505 mdr_AddRef,
3513};
3514
3516
3518{
3519 if (IsEqualIID(iid, &IID_IUnknown) ||
3520 IsEqualIID(iid, &IID_IWICMetadataBlockReader))
3521 {
3522 *out = iface;
3523 return S_OK;
3524 }
3525
3526 /* Windows 8/10 query for some undocumented IID */
3527 if (!IsEqualIID(iid, &IID_MdbrUnknown))
3528 ok(0, "unknown iid %s\n", wine_dbgstr_guid(iid));
3529
3530 *out = NULL;
3531 return E_NOINTERFACE;
3532}
3533
3535{
3536 return 2;
3537}
3538
3540{
3541 return 1;
3542}
3543
3545{
3546 ok(current_metadata != NULL, "current_metadata can't be NULL\n");
3547 if (!current_metadata) return E_POINTER;
3548
3549 *format = *current_metadata->container_format;
3550 return S_OK;
3551}
3552
3554{
3555 ok(current_metadata != NULL, "current_metadata can't be NULL\n");
3556 if (!current_metadata) return E_POINTER;
3557
3558 *count = current_metadata->count;
3559 return S_OK;
3560}
3561
3563{
3564 *out = NULL;
3565
3566 ok(current_metadata != NULL, "current_metadata can't be NULL\n");
3567 if (!current_metadata) return E_POINTER;
3568
3569 if (index < current_metadata->count)
3570 {
3572 *out = &mdr;
3573 return S_OK;
3574 }
3575
3577 return E_INVALIDARG;
3578}
3579
3581{
3582 ok(0, "not implemented\n");
3583 return E_NOTIMPL;
3584}
3585
3586static const IWICMetadataBlockReaderVtbl mdbr_vtbl =
3587{
3595};
3596
3598
3599static const char xmp[] = "http://ns.adobe.com/xap/1.0/";
3600static const char dc[] = "http://purl.org/dc/elements/1.1/";
3601static const char tiff[] = "http://ns.adobe.com/tiff/1.0/";
3602
3603static const struct metadata_item item1[] =
3604{
3605 { NULL, NULL, 1, 2, 3 }
3606};
3607
3608static const struct metadata_item item2[] =
3609{
3610 { NULL, NULL, 1, 2, 3 },
3611 { "xmp", "Rating", 4, 5, 6 },
3612 { NULL, "Rating", 7, 8, 9 }
3613};
3614
3615static const struct metadata_item item3[] =
3616{
3617 { NULL, NULL, 1, 2, 3 },
3618 { NULL, NULL, 4, 5, 6 },
3619 { NULL, NULL, 7, 8, 9 },
3620 { NULL, NULL, 10, 11, 12 }
3621};
3622
3623static const struct metadata_item item4[] =
3624{
3625 { NULL, NULL, 1, 2, 3 },
3626 { xmp, "Rating", 4, 5, 6 },
3627 { dc, NULL, 7, 8, 9 },
3628 { tiff, NULL, 10, 11, 12 },
3629 { NULL, "RATING", 13, 14, 15 },
3630 { NULL, "R}ATING", 16, 17, 18 },
3631 { NULL, "xmp", 19, 20, 21 }
3632};
3633
3634static const struct metadata_block block1[] =
3635{
3636 { &GUID_MetadataFormatIfd, 1, item1 }
3637};
3638
3639static const struct metadata_block block2[] =
3640{
3641 { &GUID_MetadataFormatXMP, 1, item1 },
3642 { &GUID_MetadataFormatIfd, 3, item2 }
3643};
3644
3645static const struct metadata_block block3[] =
3646{
3647 { &GUID_MetadataFormatXMP, 1, item1 },
3648 { &GUID_MetadataFormatIfd, 3, item2 },
3649 { &GUID_MetadataFormatXMP, 4, item3 },
3650 { &GUID_MetadataFormatXMP, 7, item4 },
3651 { &GUID_MetadataFormatIfd, 7, item4 }
3652};
3653
3654static const struct metadata data1 =
3655{
3656 &GUID_ContainerFormatGif,
3657 1, block1
3658};
3659
3660static const struct metadata data2 =
3661{
3662 &GUID_ContainerFormatTiff,
3663 2, block2
3664};
3665
3666static const struct metadata data3 =
3667{
3668 &GUID_ContainerFormatPng,
3669 5, block3
3670};
3671
3672static void test_queryreader(void)
3673{
3674 static const struct
3675 {
3676 BOOL todo;
3677 const struct metadata *data;
3678 const WCHAR *query;
3679 HRESULT hr;
3680 UINT vt, value;
3681 const char *str_value;
3682 } test_data[] =
3683 {
3684 { FALSE, &data1, L"/ifd/{uchar=1}", S_OK, 2, 3, NULL },
3685 { FALSE, &data2, L"/ifd/xmp:{long=4}", S_OK, 5, 6, NULL },
3686 { FALSE, &data2, L"/ifd/{str=xmp}:{uint=4}", S_OK, 5, 6, NULL },
3687 { FALSE, &data3, L"/xmp/{char=7}", 0xdeadbeef },
3688 { FALSE, &data3, L"/[1]xmp/{short=7}", S_OK, 8, 9, NULL },
3689 { FALSE, &data3, L"/[1]ifd/{str=dc}:{uint=7}", 0xdeadbeef },
3690 { FALSE, &data3, L"/[1]ifd/{str=http://purl.org/dc/elements/1.1/}:{longlong=7}", S_OK, 8, 9, NULL },
3691 { FALSE, &data3, L"/[1]ifd/{str=http://ns.adobe.com/tiff/1.0/}:{int=10}", S_OK, 11, 12, NULL },
3692 { FALSE, &data3, L"/[2]xmp/xmp:{ulong=4}", S_OK, 5, 6, NULL },
3693 { FALSE, &data3, L"/[2]xmp/{str=xmp}:{ulong=4}", 0xdeadbeef },
3694
3695 { FALSE, &data3, L"/xmp", S_OK, VT_UNKNOWN, 0, NULL },
3696 { FALSE, &data3, L"/ifd/xmp", S_OK, VT_UNKNOWN, 0, NULL },
3697 { FALSE, &data3, L"/ifd/xmp/tiff", S_OK, VT_UNKNOWN, 0, NULL },
3698 { FALSE, &data3, L"/[0]ifd/[0]xmp/[0]tiff", S_OK, VT_UNKNOWN, 0, NULL },
3699 { TRUE, &data3, L"/[*]xmp", S_OK, VT_LPSTR, 0, the_worst },
3700
3701 { FALSE, &data3, L"/ifd/\\Rating", S_OK, VT_LPSTR, 0, the_worst },
3702 { FALSE, &data3, L"/[0]ifd/Rating", S_OK, VT_LPSTR, 0, the_worst },
3703 { FALSE, &data3, L"/[2]xmp/xmp:{str=Rating}", S_OK, VT_LPSTR, 0, the_best },
3704 { FALSE, &data3, L"/[2]xmp/xmp:Rating", S_OK, VT_LPSTR, 0, the_worst },
3705 { FALSE, &data3, L"/[1]ifd/{str=http://ns.adobe.com/xap/1.0/}:Rating", S_OK, VT_LPSTR, 0, the_worst },
3706 { FALSE, &data3, L"/[1]ifd/{str=http://ns.adobe.com/xap/1.0/}:{str=Rating}", S_OK, VT_LPSTR, 0, the_best },
3707 { FALSE, &data3, L"/[1]ifd/{wstr=\\RATING}", S_OK, VT_LPSTR, 0, the_worst },
3708 { FALSE, &data3, L"/[1]ifd/{str=R\\ATING}", S_OK, VT_LPSTR, 0, the_best },
3709 { FALSE, &data3, L"/[1]ifd/{str=R\\}ATING}", S_OK, VT_LPSTR, 0, the_best },
3710
3711 { FALSE, &data1, L"[0]/ifd/Rating", WINCODEC_ERR_PROPERTYNOTSUPPORTED },
3712 { TRUE, &data1, L"/[+1]ifd/Rating", WINCODEC_ERR_INVALIDQUERYCHARACTER },
3713 { TRUE, &data1, L"/[-1]ifd/Rating", WINCODEC_ERR_INVALIDQUERYCHARACTER },
3714 { FALSE, &data1, L"/ifd/{\\str=Rating}", WINCODEC_ERR_WRONGSTATE },
3715 { FALSE, &data1, L"/ifd/{badtype=0}", WINCODEC_ERR_WRONGSTATE },
3716 { TRUE, &data1, L"/ifd/{uint=0x1234}", DISP_E_TYPEMISMATCH },
3717 { TRUE, &data1, L"/ifd/[0]Rating", E_INVALIDARG },
3719 };
3720 HRESULT hr;
3723 GUID format;
3724 PROPVARIANT value;
3725 UINT i;
3726
3727 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
3728 &IID_IWICComponentFactory, (void **)&factory);
3729 ok(hr == S_OK, "CoCreateInstance error %#lx\n", hr);
3730
3731 hr = IWICComponentFactory_CreateQueryReaderFromBlockReader(factory, &mdbr, &reader);
3732 ok(hr == S_OK, "CreateQueryReaderFromBlockReader error %#lx\n", hr);
3733
3734 for (i = 0; i < ARRAY_SIZE(test_data); i++)
3735 {
3736 winetest_push_context("%u", i);
3737
3739
3740 hr = IWICMetadataQueryReader_GetContainerFormat(reader, &format);
3741 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3742 ok(IsEqualGUID(&format, test_data[i].data->container_format), "Expected %s, got %s.\n",
3743 wine_dbgstr_guid(test_data[i].data->container_format), wine_dbgstr_guid(&format));
3744
3745 PropVariantInit(&value);
3746 hr = IWICMetadataQueryReader_GetMetadataByName(reader, test_data[i].query, &value);
3748 ok(hr == test_data[i].hr, "Expected %#lx, got %#lx.\n", test_data[i].hr, hr);
3749 if (hr == S_OK)
3750 {
3751 ok(value.vt == test_data[i].vt, "Expected %u, got %u.\n", test_data[i].vt, value.vt);
3752 if (test_data[i].vt == value.vt)
3753 {
3754 if (value.vt == VT_UNKNOWN)
3755 {
3756 IWICMetadataQueryReader *new_reader;
3757 WCHAR location[256];
3758 UINT len;
3759
3760 hr = IUnknown_QueryInterface(value.punkVal, &IID_IWICMetadataQueryReader, (void **)&new_reader);
3761 ok(hr == S_OK, "QueryInterface error %#lx\n", hr);
3762
3763 location[0] = 0;
3764 len = 0xdeadbeef;
3765 hr = IWICMetadataQueryReader_GetLocation(new_reader, 256, location, &len);
3766 ok(hr == S_OK, "GetLocation error %#lx\n", hr);
3767 ok(len == lstrlenW(test_data[i].query) + 1, "expected %u, got %u\n", lstrlenW(test_data[i].query) + 1, len);
3769
3770 hr = IWICMetadataQueryReader_GetLocation(new_reader, 256, location, NULL);
3771 ok(hr == E_INVALIDARG, "got %#lx\n", hr);
3772
3773 location[0] = 0;
3774 len = 0xdeadbeef;
3775 hr = IWICMetadataQueryReader_GetLocation(new_reader, 3, location, &len);
3776 ok(hr == WINCODEC_ERR_INSUFFICIENTBUFFER, "got %#lx\n", hr);
3777 ok(len == 0xdeadbeef, "got %u\n", len);
3778 ok(!location[0], "got %s\n", wine_dbgstr_w(location));
3779
3780 location[0] = 0;
3781 len = 0xdeadbeef;
3782 hr = IWICMetadataQueryReader_GetLocation(new_reader, 0, location, &len);
3783 ok(hr == WINCODEC_ERR_INSUFFICIENTBUFFER, "got %#lx\n", hr);
3784 ok(len == 0xdeadbeef, "got %u\n", len);
3785 ok(!location[0], "got %s\n", wine_dbgstr_w(location));
3786
3787 len = 0xdeadbeef;
3788 hr = IWICMetadataQueryReader_GetLocation(new_reader, 0, NULL, &len);
3789 ok(hr == S_OK, "GetLocation error %#lx\n", hr);
3790 ok(len == lstrlenW(test_data[i].query) + 1, "expected %u, got %u\n", lstrlenW(test_data[i].query) + 1, len);
3791
3792 len = 0xdeadbeef;
3793 hr = IWICMetadataQueryReader_GetLocation(new_reader, 3, NULL, &len);
3794 ok(hr == S_OK, "GetLocation error %#lx\n", hr);
3795 ok(len == lstrlenW(test_data[i].query) + 1, "expected %u, got %u\n", lstrlenW(test_data[i].query) + 1, len);
3796
3797 hr = IWICMetadataQueryReader_GetLocation(new_reader, 0, NULL, NULL);
3798 ok(hr == E_INVALIDARG, "got %#lx\n", hr);
3799
3800 IWICMetadataQueryReader_Release(new_reader);
3802 }
3803 else if (value.vt == VT_LPSTR)
3804 ok(!lstrcmpA(value.pszVal, test_data[i].str_value), "Expected %s, got %s.\n",
3805 test_data[i].str_value, value.pszVal);
3806 else
3807 ok(value.uiVal == test_data[i].value, "Expected %u, got %u\n",
3808 test_data[i].value, value.uiVal);
3809 }
3810
3811 /*
3812 * Do NOT call PropVariantClear(&value) for fake value types.
3813 */
3814 }
3815
3817 }
3818
3819 IWICMetadataQueryReader_Release(reader);
3820 IWICComponentFactory_Release(factory);
3821}
3822
3823static void test_metadata_writer(void)
3824{
3825 static struct
3826 {
3827 REFCLSID rclsid;
3828 BOOL wine_supports_encoder;
3829 BOOL metadata_supported;
3830 BOOL succeeds_uninitialized;
3831 }
3832 tests[] =
3833 {
3834 {&CLSID_WICBmpEncoder, TRUE, FALSE},
3835 {&CLSID_WICPngEncoder, TRUE, TRUE},
3836 {&CLSID_WICJpegEncoder, TRUE, TRUE},
3837 {&CLSID_WICGifEncoder, TRUE, TRUE},
3838 {&CLSID_WICTiffEncoder, TRUE, TRUE},
3839 {&CLSID_WICWmpEncoder, FALSE, TRUE, TRUE},
3840 };
3841
3842 IWICMetadataQueryWriter *querywriter, *querywriter2;
3843 IWICMetadataBlockWriter *blockwriter;
3844 IWICBitmapFrameEncode *frameencode;
3847 IEnumString *enumstring;
3848 LPOLESTR olestring;
3849 ULONG ref, count;
3850 IStream *stream;
3851 unsigned int i;
3852 HRESULT hr;
3853
3854 for (i = 0; i < ARRAY_SIZE(tests); ++i)
3855 {
3856 winetest_push_context("%u", i);
3857
3858 hr = CoCreateInstance(tests[i].rclsid, NULL, CLSCTX_INPROC_SERVER,
3859 &IID_IWICBitmapEncoder, (void **)&encoder);
3860 todo_wine_if(!tests[i].wine_supports_encoder) ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3861 if (FAILED(hr))
3862 {
3864 continue;
3865 }
3866
3867 blockwriter = NULL;
3868 querywriter = querywriter2 = NULL;
3869
3871 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3872 hr = IWICBitmapEncoder_Initialize(encoder, stream, WICBitmapEncoderNoCache);
3873 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3874 hr = IWICBitmapEncoder_CreateNewFrame(encoder, &frameencode, NULL);
3875 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3876
3877 hr = IWICBitmapFrameEncode_QueryInterface(frameencode, &IID_IWICMetadataBlockWriter, (void**)&blockwriter);
3878 ok(hr == (tests[i].metadata_supported ? S_OK : E_NOINTERFACE), "Got unexpected hr %#lx.\n", hr);
3879
3880 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
3881 &IID_IWICComponentFactory, (void**)&factory);
3882 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3883
3884 hr = IWICComponentFactory_CreateQueryWriterFromBlockWriter(factory, blockwriter, &querywriter);
3885 ok(hr == (tests[i].metadata_supported ? S_OK : E_INVALIDARG), "Got unexpected hr %#lx.\n", hr);
3886
3887 hr = IWICBitmapFrameEncode_GetMetadataQueryWriter(frameencode, &querywriter2);
3888 ok(hr == (tests[i].succeeds_uninitialized ? S_OK : WINCODEC_ERR_NOTINITIALIZED),
3889 "Got unexpected hr %#lx.\n", hr);
3890 if (hr == S_OK)
3891 IWICMetadataQueryWriter_Release(querywriter2);
3892
3893 hr = IWICBitmapFrameEncode_Initialize(frameencode, NULL);
3894 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3895
3896 hr = IWICBitmapFrameEncode_GetMetadataQueryWriter(frameencode, &querywriter2);
3897 ok(hr == (tests[i].metadata_supported ? S_OK : WINCODEC_ERR_UNSUPPORTEDOPERATION),
3898 "Got unexpected hr %#lx.\n", hr);
3899
3900 if (tests[i].metadata_supported)
3901 ok(querywriter2 != querywriter, "Got unexpected interfaces %p, %p.\n", querywriter, querywriter2);
3902
3903 IWICComponentFactory_Release(factory);
3904 if (querywriter)
3905 {
3906 ref = get_refcount(querywriter);
3907 ok(ref == 1, "Got unexpected ref %lu.\n", ref);
3908
3909 hr = IWICMetadataQueryWriter_QueryInterface(querywriter, &IID_IEnumString, (void **)&enumstring);
3910 ok(hr == E_NOINTERFACE, "Got unexpected hr %#lx.\n", hr);
3911
3912 hr = IWICMetadataQueryWriter_GetEnumerator(querywriter, &enumstring);
3913 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3914
3915 ref = get_refcount(querywriter);
3916 ok(ref == 1, "Got unexpected ref %lu.\n", ref);
3917
3918 hr = IEnumString_Skip(enumstring, 0);
3919 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3920
3921 count = 0xdeadbeef;
3922 hr = IEnumString_Next(enumstring, 0, NULL, &count);
3923 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
3924 ok(count == 0xdeadbeef, "Got unexpected count %lu.\n", count);
3925
3926 hr = IEnumString_Next(enumstring, 0, &olestring, &count);
3927 ok(hr == S_OK || hr == WINCODEC_ERR_VALUEOUTOFRANGE, "Got unexpected hr %#lx.\n", hr);
3928
3929 count = 0xdeadbeef;
3930 hr = IEnumString_Next(enumstring, 1, &olestring, &count);
3931 ok(hr == S_OK || hr == S_FALSE, "Got unexpected hr %#lx, i %u.\n", hr, i);
3932 ok((hr && !count) || (!hr && count == 1), "Got unexpected hr %#lx, count %lu.\n", hr, count);
3933 if (count)
3934 {
3935 CoTaskMemFree(olestring);
3936
3937 /* IEnumString_Skip() crashes at least on Win7 when
3938 * trying to skip past the string count. */
3939 hr = IEnumString_Reset(enumstring);
3940 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3941
3942 hr = IEnumString_Skip(enumstring, 1);
3943 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3944 }
3945 IEnumString_Release(enumstring);
3946
3947 IWICMetadataQueryWriter_Release(querywriter);
3948 IWICMetadataQueryWriter_Release(querywriter2);
3949 IWICMetadataBlockWriter_Release(blockwriter);
3950 }
3951 IWICBitmapFrameEncode_Release(frameencode);
3952 IStream_Release(stream);
3953 IWICBitmapEncoder_Release(encoder);
3954
3956 }
3957}
3958
3959#include "pshpack2.h"
3960static const struct app1_data
3961{
3966
3968 struct IFD_entry ifd0[4];
3970
3974
3978}
3979app1_data =
3980{
3981 { 'E','x','i','f',0,0 },
3982 { 'I','I' },
3983 0x002a,
3984 0x8,
3985
3986 /* IFD 0 */
3987 4,
3988 {
3989 { 0x100, IFD_LONG, 1, 222 }, /* IMAGEWIDTH */
3990 { 0x101, IFD_LONG, 1, 333 }, /* IMAGELENGTH */
3991 /* Exif IFD pointer */
3992 { 0x8769, IFD_LONG, 1, FIELD_OFFSET(struct app1_data, exif_ifd_count) - 6 },
3993 /* GPS IFD pointer */
3994 { 0x8825, IFD_LONG, 1, FIELD_OFFSET(struct app1_data, gps_ifd_count) - 6 },
3995 },
3996 0,
3997
3998 /* Exif IFD */
3999 1,
4000 {
4001 { 0x200, IFD_SHORT, 1, 444 },
4002 },
4003 0,
4004
4005 /* GPS IFD */
4006 1,
4007 {
4008 { 0x300, IFD_SHORT, 1, 555 },
4009 },
4010 0,
4012#include "poppack.h"
4013
4014static void test_metadata_App1(void)
4015{
4016 IWICMetadataReader *reader, *ifd_reader, *exif_reader, *gps_reader;
4017 IStream *app1_stream, *stream2;
4018 IWICMetadataWriter *writer;
4019 PROPVARIANT id, value;
4020 GUID format;
4021 HRESULT hr;
4022 UINT count;
4023
4024 hr = CoCreateInstance(&CLSID_WICApp1MetadataReader, NULL, CLSCTX_INPROC_SERVER,
4025 &IID_IWICMetadataReader, (void **)&reader);
4026 todo_wine
4027 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4028 if (FAILED(hr)) return;
4029
4030 check_interface(reader, &IID_IWICMetadataReader, TRUE);
4033 check_interface(reader, &IID_IWICPersistStream, TRUE);
4034 check_interface(reader, &IID_IWICStreamProvider, TRUE);
4035 check_interface(reader, &IID_IWICMetadataBlockReader, FALSE);
4036
4037 hr = IWICMetadataReader_GetCount(reader, NULL);
4038 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
4039
4040 count = 1;
4041 hr = IWICMetadataReader_GetCount(reader, &count);
4042 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4043 ok(!count, "Unexpected count %u.\n", count);
4044
4045 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
4046 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4047 ok(IsEqualGUID(&format, &GUID_MetadataFormatApp1), "Unexpected format %s.\n", wine_dbgstr_guid(&format));
4048
4049 test_reader_container_format(reader, &GUID_ContainerFormatJpeg);
4050
4051 load_stream(reader, (const char *)&app1_data, sizeof(app1_data), 0);
4053 hr = get_persist_stream(reader, &app1_stream);
4054 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4055
4056 hr = IWICMetadataReader_GetCount(reader, &count);
4057 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4058 ok(count == 1, "Unexpected count %u.\n", count);
4059
4060 PropVariantInit(&id);
4061 PropVariantInit(&value);
4062 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, &id, &value);
4063 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4064
4065 /* Top level IFD reader. */
4066 ok(id.vt == VT_UI2, "Unexpected id type: %u.\n", id.vt);
4067 ok(id.uiVal == 0, "Unexpected id %u.\n", id.uiVal);
4068
4069 ok(value.vt == VT_UNKNOWN, "Unexpected value type: %u.\n", value.vt);
4070 ok(!!value.punkVal, "Unexpected value.\n");
4071
4072 hr = IUnknown_QueryInterface(value.punkVal, &IID_IWICMetadataReader, (void **)&ifd_reader);
4073 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4075
4076 hr = IWICMetadataReader_GetMetadataFormat(ifd_reader, &format);
4077 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4078 ok(IsEqualGUID(&format, &GUID_MetadataFormatIfd), "Unexpected format %s.\n", wine_dbgstr_guid(&format));
4079 check_persist_options(ifd_reader, 0);
4080
4081 hr = get_persist_stream(ifd_reader, &stream2);
4082 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4083 ok(!!stream2 && stream2 != app1_stream, "Unexpected stream %p.\n", stream2);
4084 IStream_Release(stream2);
4085
4086 hr = IWICMetadataReader_GetCount(ifd_reader, &count);
4087 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4088 ok(count == 4, "Unexpected count %u.\n", count);
4089
4090 PropVariantInit(&id);
4091 PropVariantInit(&value);
4092 hr = IWICMetadataReader_GetValueByIndex(ifd_reader, 0, NULL, &id, &value);
4093 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4094
4095 ok(id.vt == VT_UI2, "Unexpected id type: %u.\n", id.vt);
4096 ok(id.uiVal == 0x100, "Unexpected id %#x.\n", id.uiVal);
4097 ok(value.vt == VT_UI4, "Unexpected value type: %u.\n", value.vt);
4098 ok(value.ulVal == 222, "Unexpected value %lu.\n", value.ulVal);
4099
4100 PropVariantInit(&id);
4101 PropVariantInit(&value);
4102 hr = IWICMetadataReader_GetValueByIndex(ifd_reader, 1, NULL, &id, &value);
4103 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4104
4105 ok(id.vt == VT_UI2, "Unexpected id type: %u.\n", id.vt);
4106 ok(id.uiVal == 0x101, "Unexpected id %#x.\n", id.uiVal);
4107 ok(value.vt == VT_UI4, "Unexpected value type: %u.\n", value.vt);
4108 ok(value.ulVal == 333, "Unexpected value %lu.\n", value.ulVal);
4109
4110 PropVariantInit(&id);
4111 PropVariantInit(&value);
4112 hr = IWICMetadataReader_GetValueByIndex(ifd_reader, 2, NULL, &id, &value);
4113 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4114
4115 ok(id.vt == VT_UI2, "Unexpected id type: %u.\n", id.vt);
4116 ok(id.uiVal == 0x8769, "Unexpected id %#x.\n", id.uiVal);
4117 ok(value.vt == VT_UNKNOWN, "Unexpected value type: %u.\n", value.vt);
4118 hr = IUnknown_QueryInterface(value.punkVal, &IID_IWICMetadataReader, (void **)&exif_reader);
4119 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4121
4122 /* Exif IFD */
4123 hr = IWICMetadataReader_GetMetadataFormat(exif_reader, &format);
4124 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4125 ok(IsEqualGUID(&format, &GUID_MetadataFormatExif), "Unexpected format %s.\n", wine_dbgstr_guid(&format));
4126 check_persist_options(exif_reader, 0);
4127
4128 hr = get_persist_stream(exif_reader, &stream2);
4129 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4130 ok(!!stream2 && stream2 != app1_stream, "Unexpected stream.\n");
4131 IStream_Release(stream2);
4132
4133 hr = IWICMetadataReader_GetCount(exif_reader, &count);
4134 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4135 ok(count == 1, "Unexpected count %u.\n", count);
4136
4137 PropVariantInit(&id);
4138 PropVariantInit(&value);
4139 hr = IWICMetadataReader_GetValueByIndex(exif_reader, 0, NULL, &id, &value);
4140 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4141
4142 ok(id.vt == VT_UI2, "Unexpected id type: %u.\n", id.vt);
4143 ok(id.uiVal == 0x200, "Unexpected id %#x.\n", id.uiVal);
4144 ok(value.vt == VT_UI2, "Unexpected value type: %u.\n", value.vt);
4145 ok(value.ulVal == 444, "Unexpected value %lu.\n", value.ulVal);
4146
4147 PropVariantInit(&id);
4148 PropVariantInit(&value);
4149 hr = IWICMetadataReader_GetValueByIndex(ifd_reader, 3, NULL, &id, &value);
4150 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4151
4152 ok(id.vt == VT_UI2, "Unexpected id type: %u.\n", id.vt);
4153 ok(id.uiVal == 0x8825, "Unexpected id %#x.\n", id.uiVal);
4154 ok(value.vt == VT_UNKNOWN, "Unexpected value type: %u.\n", value.vt);
4155 hr = IUnknown_QueryInterface(value.punkVal, &IID_IWICMetadataReader, (void **)&gps_reader);
4156 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4158
4159 /* GPS IFD */
4160 hr = IWICMetadataReader_GetMetadataFormat(gps_reader, &format);
4161 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4162 ok(IsEqualGUID(&format, &GUID_MetadataFormatGps), "Unexpected format %s.\n", wine_dbgstr_guid(&format));
4163 check_persist_options(gps_reader, 0);
4164
4165 hr = get_persist_stream(gps_reader, &stream2);
4166 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4167 ok(!!stream2 && stream2 != app1_stream, "Unexpected stream.\n");
4168 IStream_Release(stream2);
4169
4170 hr = IWICMetadataReader_GetCount(gps_reader, &count);
4171 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4172 ok(count == 1, "Unexpected count %u.\n", count);
4173
4174 PropVariantInit(&id);
4175 PropVariantInit(&value);
4176 hr = IWICMetadataReader_GetValueByIndex(gps_reader, 0, NULL, &id, &value);
4177 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4178
4179 ok(id.vt == VT_UI2, "Unexpected id type: %u.\n", id.vt);
4180 ok(id.uiVal == 0x300, "Unexpected id %#x.\n", id.uiVal);
4181 ok(value.vt == VT_UI2, "Unexpected value type: %u.\n", value.vt);
4182 ok(value.ulVal == 555, "Unexpected value %lu.\n", value.ulVal);
4183
4184 IWICMetadataReader_Release(gps_reader);
4185 IWICMetadataReader_Release(exif_reader);
4186 IWICMetadataReader_Release(ifd_reader);
4187
4188 IStream_Release(app1_stream);
4189 IWICMetadataReader_Release(reader);
4190
4191 hr = CoCreateInstance(&CLSID_WICApp1MetadataWriter, NULL, CLSCTX_INPROC_SERVER,
4192 &IID_IWICMetadataWriter, (void **)&writer);
4193 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4194 if (FAILED(hr)) return;
4195
4196 check_interface(writer, &IID_IWICMetadataWriter, TRUE);
4197 check_interface(writer, &IID_IWICMetadataReader, TRUE);
4200 check_interface(writer, &IID_IWICPersistStream, TRUE);
4201 check_interface(writer, &IID_IWICStreamProvider, TRUE);
4202
4203 IWICMetadataWriter_Release(writer);
4204}
4205
4207{
4210 IWICMetadataWriter *writer;
4211 IStream *stream, *stream2;
4212 PROPVARIANT id, value;
4213 GUID format;
4214 HRESULT hr;
4215 UINT count;
4216 char *data;
4217
4218 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
4219 &IID_IWICComponentFactory, (void **)&factory);
4220 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4221
4222 /* tEXt, uninitialized */
4223 hr = IWICComponentFactory_CreateMetadataReader(factory, &GUID_MetadataFormatChunktEXt,
4224 NULL, 0, NULL, &reader);
4225 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4226 todo_wine
4228
4229 hr = IWICComponentFactory_CreateMetadataWriterFromReader(factory, reader, NULL, &writer);
4230 todo_wine
4231 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4232 if (FAILED(hr))
4233 {
4234 IWICMetadataReader_Release(reader);
4235 IWICComponentFactory_Release(factory);
4236 return;
4237 }
4238
4239 IWICMetadataReader_Release(reader);
4240
4241 check_persist_options(writer, 0);
4242 IWICMetadataWriter_Release(writer);
4243
4244 /* tEXt, loaded */
4246 hr = IWICComponentFactory_CreateMetadataReader(factory, &GUID_MetadataFormatChunktEXt,
4247 NULL, 0, stream, &reader);
4248 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4250 IStream_Release(stream);
4251
4252 hr = IWICComponentFactory_CreateMetadataWriterFromReader(factory, NULL, NULL, NULL);
4253 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
4254
4255 hr = IWICComponentFactory_CreateMetadataWriterFromReader(factory, NULL, NULL, &writer);
4256 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
4257
4258 hr = IWICComponentFactory_CreateMetadataWriterFromReader(factory, reader, NULL, NULL);
4259 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
4260
4261 expect_ref(reader, 1);
4262 hr = IWICComponentFactory_CreateMetadataWriterFromReader(factory, reader, NULL, &writer);
4263 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4264 expect_ref(reader, 1);
4265
4266 hr = IWICMetadataReader_GetCount(reader, &count);
4267 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4268 ok(count == 1, "Unexpected count %u.\n", count);
4269
4270 PropVariantInit(&id);
4271 PropVariantInit(&value);
4272 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, &id, &value);
4273 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4274 ok(id.vt == VT_LPSTR, "Unexpected id type %u.\n", id.vt);
4275 ok(!strcmp(id.pszVal, "winetest"), "Unexpected id %s.\n", wine_dbgstr_a(id.pszVal));
4276 ok(value.vt == VT_LPSTR, "Unexpected value type %u.\n", value.vt);
4277 ok(!strcmp(value.pszVal, "value"), "Unexpected value %s.\n", wine_dbgstr_a(value.pszVal));
4278 PropVariantClear(&id);
4280
4281 hr = IWICMetadataWriter_GetMetadataFormat(writer, &format);
4282 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4283 ok(IsEqualGUID(&format, &GUID_MetadataFormatChunktEXt), "Unexpected format %s.\n", wine_dbgstr_guid(&format));
4284
4285 hr = IWICMetadataWriter_GetCount(writer, &count);
4286 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4287 ok(count == 1, "Unexpected count %u.\n", count);
4288
4289 PropVariantInit(&id);
4290 PropVariantInit(&value);
4291 hr = IWICMetadataWriter_GetValueByIndex(writer, 0, NULL, &id, &value);
4292 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4293 ok(id.vt == VT_LPSTR, "Unexpected id type %u.\n", id.vt);
4294 ok(!strcmp(id.pszVal, "winetest"), "Unexpected id %s.\n", wine_dbgstr_a(id.pszVal));
4295 ok(value.vt == VT_LPSTR, "Unexpected value type %u.\n", value.vt);
4296 ok(!strcmp(value.pszVal, "value"), "Unexpected value %s.\n", wine_dbgstr_a(value.pszVal));
4297 PropVariantClear(&id);
4299
4300 IWICMetadataWriter_Release(writer);
4301 IWICMetadataReader_Release(reader);
4302
4303 /* App1 reader */
4304 stream = create_stream((const char *)&app1_data, sizeof(app1_data));
4305 hr = IWICComponentFactory_CreateMetadataReader(factory, &GUID_MetadataFormatApp1,
4306 NULL, 0, stream, &reader);
4307 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4308
4309 hr = IWICComponentFactory_CreateMetadataWriterFromReader(factory, reader, NULL, &writer);
4310 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4311
4312 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
4313 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4314 ok(IsEqualGUID(&format, &GUID_MetadataFormatApp1), "Unexpected format %s.\n", wine_dbgstr_guid(&format));
4315
4316 hr = IWICMetadataWriter_GetCount(writer, &count);
4317 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4318 ok(count == 1, "Unexpected count %u.\n", count);
4319
4320 PropVariantInit(&id);
4321 PropVariantInit(&value);
4322 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, &id, &value);
4323 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4324 ok(id.vt == VT_UI2, "Unexpected id type %u.\n", id.vt);
4325 ok(value.vt == VT_UNKNOWN, "Unexpected value type %u.\n", value.vt);
4326 check_interface(value.punkVal, &IID_IWICMetadataReader, TRUE);
4327 check_interface(value.punkVal, &IID_IWICMetadataWriter, FALSE);
4329
4330 hr = IWICMetadataWriter_GetMetadataFormat(writer, &format);
4331 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4332 ok(IsEqualGUID(&format, &GUID_MetadataFormatApp1), "Unexpected format %s.\n", wine_dbgstr_guid(&format));
4333
4334 hr = IWICMetadataWriter_GetCount(writer, &count);
4335 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4336 ok(count == 1, "Unexpected count %u.\n", count);
4337
4338 PropVariantInit(&id);
4339 PropVariantInit(&value);
4340 hr = IWICMetadataWriter_GetValueByIndex(writer, 0, NULL, &id, &value);
4341 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4342 ok(id.vt == VT_UI2, "Unexpected id type %u.\n", id.vt);
4343 ok(value.vt == VT_UNKNOWN, "Unexpected value type %u.\n", value.vt);
4344 check_interface(value.punkVal, &IID_IWICMetadataReader, TRUE);
4345 check_interface(value.punkVal, &IID_IWICMetadataWriter, TRUE);
4346 check_persist_options(value.punkVal, 0);
4348
4349 hr = get_persist_stream(writer, &stream2);
4350 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4351 ok(stream2 != stream, "Unexpected stream.\n");
4352 IStream_Release(stream2);
4353
4354 IWICMetadataWriter_Release(writer);
4355 IWICMetadataReader_Release(reader);
4356 IStream_Release(stream);
4357
4358 /* Big-endian IFD */
4359 data = malloc(sizeof(IFD_data));
4360 memcpy(data, &IFD_data, sizeof(IFD_data));
4362
4363 hr = IWICComponentFactory_CreateMetadataReader(factory, &GUID_MetadataFormatIfd,
4364 NULL, 0, NULL, &reader);
4365 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4366
4369 free(data);
4370
4371 hr = IWICComponentFactory_CreateMetadataWriterFromReader(factory, reader, NULL, &writer);
4372 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4374 IWICMetadataWriter_Release(writer);
4375
4376 IWICMetadataReader_Release(reader);
4377
4378 IWICComponentFactory_Release(factory);
4379}
4380
4382{
4383 static const struct options_test
4384 {
4385 const GUID *clsid;
4386 DWORD options;
4387 }
4388 options_tests[] =
4389 {
4390 { &GUID_MetadataFormatApp1, WICPersistOptionBigEndian },
4391 { &GUID_MetadataFormatIfd, WICPersistOptionBigEndian },
4392 { &GUID_MetadataFormatChunktEXt, WICPersistOptionBigEndian },
4393 { &GUID_MetadataFormatApp1, WICPersistOptionNoCacheStream },
4394 { &GUID_MetadataFormatIfd, WICPersistOptionNoCacheStream },
4395 { &GUID_MetadataFormatChunktEXt, WICPersistOptionNoCacheStream },
4396 { &GUID_MetadataFormatApp1, 0x100 },
4397 };
4398 IWICStreamProvider *stream_provider;
4400 IWICMetadataWriter *writer;
4401 IStream *stream;
4402 unsigned int i;
4403 GUID format;
4404 HRESULT hr;
4405
4406 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
4407 &IID_IWICComponentFactory, (void **)&factory);
4408 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4409
4410 for (i = 0; i < ARRAY_SIZE(options_tests); ++i)
4411 {
4412 const struct options_test *test = &options_tests[i];
4413
4414 hr = IWICComponentFactory_CreateMetadataWriter(factory, test->clsid, NULL, test->options, &writer);
4415 todo_wine
4416 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
4417 }
4418
4419 hr = IWICComponentFactory_CreateMetadataWriter(factory, &GUID_MetadataFormatChunktEXt, NULL, 0, &writer);
4420 todo_wine
4421 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4422 if (FAILED(hr))
4423 {
4424 IWICComponentFactory_Release(factory);
4425 return;
4426 }
4427 check_persist_options(writer, 0);
4428
4429 hr = IWICMetadataWriter_QueryInterface(writer, &IID_IWICStreamProvider, (void **)&stream_provider);
4430 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4431
4432 stream = (void *)0xdeadbeef;
4433 hr = IWICStreamProvider_GetStream(stream_provider, &stream);
4434 ok(hr == WINCODEC_ERR_STREAMNOTAVAILABLE, "Unexpected hr %#lx.\n", hr);
4435 ok(stream == (void *)0xdeadbeef, "Unexpected stream.\n");
4436
4437 IWICStreamProvider_Release(stream_provider);
4438
4439 hr = IWICMetadataWriter_GetMetadataFormat(writer, &format);
4440 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4441 ok(IsEqualGUID(&format, &GUID_MetadataFormatChunktEXt), "Unexpected format %s.\n", wine_dbgstr_guid(&format));
4442
4443 IWICMetadataWriter_Release(writer);
4444
4445 /* Invalid format */
4446 hr = IWICComponentFactory_CreateMetadataWriter(factory, &IID_IUnknown, NULL, 0, &writer);
4447 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4448 hr = IWICMetadataWriter_GetMetadataFormat(writer, &format);
4449 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4450 ok(IsEqualGUID(&format, &GUID_MetadataFormatUnknown), "Unexpected format %s.\n", wine_dbgstr_guid(&format));
4451 IWICMetadataWriter_Release(writer);
4452
4453 writer = (void *)0xdeadbeef;
4454 hr = IWICComponentFactory_CreateMetadataWriter(factory, &IID_IUnknown, NULL, WICMetadataCreationFailUnknown, &writer);
4455 ok(hr == WINCODEC_ERR_COMPONENTNOTFOUND, "Unexpected hr %#lx.\n", hr);
4456 ok(writer == (void *)0xdeadbeef, "Unexpected pointer.\n");
4457
4458 /* App1 */
4459 hr = IWICComponentFactory_CreateMetadataWriter(factory, &GUID_MetadataFormatApp1, NULL, 0, &writer);
4460 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4461 check_persist_options(writer, 0);
4462 IWICMetadataWriter_Release(writer);
4463
4464 /* Ifd */
4465 hr = IWICComponentFactory_CreateMetadataWriter(factory, &GUID_MetadataFormatIfd, NULL, 0, &writer);
4466 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4467 check_persist_options(writer, 0);
4468 IWICMetadataWriter_Release(writer);
4469
4470 IWICComponentFactory_Release(factory);
4471}
4472
4474{
4476
4503
4505}
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
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define broken(x)
Definition: atltest.h:178
#define START_TEST(x)
Definition: atltest.h:75
#define ok_(x1, x2)
Definition: atltest.h:61
#define index(s, c)
Definition: various.h:29
#define ARRAY_SIZE(A)
Definition: main.h:20
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 free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static const struct pixel_format_desc formats[]
Definition: util.c:59
static WCHAR unknown[MAX_STRING_RESOURCE_LEN]
Definition: object.c:1605
#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
int WINAPI lstrcmpW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4243
INT WINAPI CompareStringW(LCID lcid, DWORD flags, LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
Definition: locale.c:4014
int WINAPI lstrcmpA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4195
UINT(* handler)(MSIPACKAGE *)
Definition: action.c:7512
static REFPROPVARIANT PROPVAR_CHANGE_FLAGS VARTYPE vt
Definition: suminfo.c:91
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:220
#define assert(x)
Definition: debug.h:53
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLdouble s
Definition: gl.h:2039
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLuint index
Definition: glext.h:6031
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
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
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:442
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
if(dx< 0)
Definition: linetemp.h:194
int WINAPI lstrlenA(LPCSTR lpString)
Definition: lstring.c:145
HRESULT WINAPI WICMapGuidToShortName(REFGUID guid, UINT len, WCHAR *name, UINT *ret_len)
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)
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define SEEK_CUR
Definition: util.h:63
static struct test_info tests[]
BOOL todo
Definition: filedlg.c:313
static const BYTE us[]
Definition: encode.c:689
#define todo_wine_if(is_todo)
Definition: custom.c:86
#define todo_wine
Definition: custom.c:89
static LPOLESTR
Definition: stg_prop.c:27
static const struct metadata_item item3[]
Definition: metadata.c:3615
static WCHAR crs_scheme[]
Definition: metadata.c:3184
#define check_persist_options(a, b)
Definition: metadata.c:64
static HRESULT WINAPI mdbr_GetCount(IWICMetadataBlockReader *iface, UINT *count)
Definition: metadata.c:3553
static void test_metadata_Gps(void)
Definition: metadata.c:1481
static void test_metadata_Ifd(void)
Definition: metadata.c:1368
static void check_persist_options_(unsigned int line, void *iface_ptr, DWORD expected_options)
Definition: metadata.c:65
#define compare_blob(a, b, c)
Definition: metadata.c:99
static void test_metadata_IMD(void)
Definition: metadata.c:2619
static char the_worst[]
Definition: metadata.c:3334
static WCHAR tiff_scheme[]
Definition: metadata.c:3175
static WCHAR xmpMM_scheme[]
Definition: metadata.c:3170
static int propvar_cmp(const PROPVARIANT *v1, LONGLONG value2)
Definition: metadata.c:3391
static void test_metadata_GCE(void)
Definition: metadata.c:2720
static HRESULT WINAPI mdr_QueryInterface(IWICMetadataReader *iface, REFIID iid, void **out)
Definition: metadata.c:3336
static WCHAR xmpDM_scheme[]
Definition: metadata.c:3185
static HRESULT WINAPI mdr_GetValueByIndex(IWICMetadataReader *iface, UINT index, PROPVARIANT *schema, PROPVARIANT *id, PROPVARIANT *value)
Definition: metadata.c:3385
static const struct metadata data2
Definition: metadata.c:3660
static void test_metadata_GIF_comment(void)
Definition: metadata.c:2926
#define test_reader_container_format(a, b)
Definition: metadata.c:534
static WCHAR rdf_scheme[]
Definition: metadata.c:3165
static void test_CreateMetadataWriterFromReader(void)
Definition: metadata.c:4206
static WCHAR MP_scheme[]
Definition: metadata.c:3188
static void _test_reader_container_format(IWICMetadataReader *reader, const GUID *format, unsigned int line)
Definition: metadata.c:535
ifd_entry_type
Definition: metadata.c:112
@ IFD_LONG
Definition: metadata.c:116
@ IFD_SRATIONAL
Definition: metadata.c:122
@ IFD_UNDEFINED
Definition: metadata.c:119
@ IFD_SBYTE
Definition: metadata.c:118
@ IFD_FLOAT
Definition: metadata.c:123
@ IFD_SSHORT
Definition: metadata.c:120
@ IFD_ASCII
Definition: metadata.c:114
@ IFD_BYTE
Definition: metadata.c:113
@ IFD_RATIONAL
Definition: metadata.c:117
@ IFD_SHORT
Definition: metadata.c:115
@ IFD_SLONG
Definition: metadata.c:121
@ IFD_DOUBLE
Definition: metadata.c:124
@ IFD_IFD
Definition: metadata.c:125
static const struct metadata_block block1[]
Definition: metadata.c:3634
static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported)
Definition: metadata.c:50
static HRESULT WINAPI mdbr_GetReaderByIndex(IWICMetadataBlockReader *iface, UINT index, IWICMetadataReader **out)
Definition: metadata.c:3562
static HRESULT WINAPI mdr_GetEnumerator(IWICMetadataReader *iface, IWICEnumMetadataItem **enumerator)
Definition: metadata.c:3496
static void test_metadata_tIME(void)
Definition: metadata.c:1060
static void test_metadata_Exif(void)
Definition: metadata.c:1426
static WCHAR * schema_list[]
Definition: metadata.c:3192
static const struct metadata_item item4[]
Definition: metadata.c:3623
static const struct metadata_block block3[]
Definition: metadata.c:3645
static const struct metadata_item item1[]
Definition: metadata.c:3603
static WCHAR MPReg_scheme[]
Definition: metadata.c:3190
static void test_metadata_App1(void)
Definition: metadata.c:4014
static WCHAR stDim_scheme[]
Definition: metadata.c:3177
static const struct metadata data1
Definition: metadata.c:3654
static void test_metadata_writer(void)
Definition: metadata.c:3823
static const char dc[]
Definition: metadata.c:3600
static void load_stream(void *iface_ptr, const char *data, int data_size, DWORD persist_options)
Definition: metadata.c:315
static IStream * create_stream(const char *data, int data_size)
Definition: metadata.c:294
static void test_metadata_hIST(void)
Definition: metadata.c:989
static char the_best[]
Definition: metadata.c:3333
static const char metadata_hIST[]
Definition: metadata.c:228
static ULONG get_refcount(void *iface)
Definition: metadata.c:287
static const char pngimage[285]
Definition: metadata.c:247
static const char gifimage[35]
Definition: metadata.c:258
static ULONG WINAPI mdbr_AddRef(IWICMetadataBlockReader *iface)
Definition: metadata.c:3534
static ULONG WINAPI mdr_AddRef(IWICMetadataReader *iface)
Definition: metadata.c:3351
static void test_queryreader(void)
Definition: metadata.c:3672
static ULONG WINAPI mdr_Release(IWICMetadataReader *iface)
Definition: metadata.c:3356
static WCHAR aux_scheme[]
Definition: metadata.c:3183
static ULONG ulong_bswap(ULONG l)
Definition: metadata.c:1126
static WCHAR stVer_scheme[]
Definition: metadata.c:3181
static HRESULT WINAPI mdr_GetMetadataFormat(IWICMetadataReader *iface, GUID *format)
Definition: metadata.c:3361
static void compare_blob_(unsigned int line, const PROPVARIANT *propvar, const char *data, ULONG length)
Definition: metadata.c:100
static ULONG WINAPI mdbr_Release(IWICMetadataBlockReader *iface)
Definition: metadata.c:3539
static HRESULT WINAPI mdbr_QueryInterface(IWICMetadataBlockReader *iface, REFIID iid, void **out)
Definition: metadata.c:3517
static void compare_metadata(IWICMetadataReader *reader, const struct test_data *td, ULONG count)
Definition: metadata.c:427
static WCHAR exif_scheme[]
Definition: metadata.c:3176
static void test_WICMapSchemaToName(void)
Definition: metadata.c:3222
static void test_metadata_png(void)
Definition: metadata.c:1778
static HRESULT WINAPI mdbr_GetContainerFormat(IWICMetadataBlockReader *iface, GUID *format)
Definition: metadata.c:3544
static const struct metadata * current_metadata
Definition: metadata.c:3330
static WCHAR MicrosoftPhoto_scheme[]
Definition: metadata.c:3187
#define expect_ref(obj, ref)
Definition: metadata.c:40
static void test_create_reader_from_container(void)
Definition: metadata.c:1535
static void test_WICMapShortNameToGuid(void)
Definition: metadata.c:3086
static WCHAR stRef_scheme[]
Definition: metadata.c:3180
static void test_metadata_gAMA(void)
Definition: metadata.c:826
static IWICMetadataBlockReader mdbr
Definition: metadata.c:3597
static HRESULT WINAPI mdr_GetValue(IWICMetadataReader *iface, const PROPVARIANT *schema, const PROPVARIANT *id, PROPVARIANT *value)
Definition: metadata.c:3402
static const char xmp[]
Definition: metadata.c:3599
static WCHAR xmp_scheme[]
Definition: metadata.c:3167
static WCHAR xmpTPg_scheme[]
Definition: metadata.c:3172
static void test_metadata_unknown(void)
Definition: metadata.c:570
static void test_metadata_APE(void)
Definition: metadata.c:2818
static const char metadata_cHRM[]
Definition: metadata.c:218
static void test_metadata_tEXt(void)
Definition: metadata.c:675
static USHORT ushort_bswap(USHORT s)
Definition: metadata.c:1121
static const struct ifd_data IFD_data
static HRESULT WINAPI mdr_GetMetadataHandlerInfo(IWICMetadataReader *iface, IWICMetadataHandlerInfo **handler)
Definition: metadata.c:3370
static HRESULT WINAPI mdbr_GetEnumerator(IWICMetadataBlockReader *iface, IEnumUnknown **enumerator)
Definition: metadata.c:3580
static const struct metadata data3
Definition: metadata.c:3666
static void test_metadata_cHRM(void)
Definition: metadata.c:902
static IWICMetadataReader mdr
Definition: metadata.c:3515
static WCHAR pdf_scheme[]
Definition: metadata.c:3173
static WCHAR Iptc4xmpCore_scheme[]
Definition: metadata.c:3186
static const char metadata_gAMA[]
Definition: metadata.c:211
static const struct metadata_block * current_metadata_block
Definition: metadata.c:3331
static const GUID * guid_list[]
Definition: metadata.c:3117
static void test_CreateMetadataWriter(void)
Definition: metadata.c:4381
static void expect_ref_(IUnknown *obj, ULONG ref, int line)
Definition: metadata.c:41
static const char metadata_tIME[]
Definition: metadata.c:239
static WCHAR photoshop_scheme[]
Definition: metadata.c:3174
static const char metadata_unknown[]
Definition: metadata.c:201
#define check_interface(a, b, c)
Definition: metadata.c:49
static WCHAR dc_scheme[]
Definition: metadata.c:3166
static void test_CreateMetadataReader(void)
Definition: metadata.c:1616
static const struct metadata_item item2[]
Definition: metadata.c:3608
static void byte_swap_ifd_data(char *data)
Definition: metadata.c:1136
static WCHAR stEvt_scheme[]
Definition: metadata.c:3179
static WCHAR stJob_scheme[]
Definition: metadata.c:3182
static const IWICMetadataReaderVtbl mdr_vtbl
Definition: metadata.c:3502
static WCHAR xapGImg_scheme[]
Definition: metadata.c:3178
static const IWICMetadataBlockReaderVtbl mdbr_vtbl
Definition: metadata.c:3586
static ULONGLONG ulonglong_bswap(ULONGLONG ll)
Definition: metadata.c:1131
static void test_ifd_content(IWICMetadataReader *reader)
Definition: metadata.c:1229
static void test_metadata_LSD(void)
Definition: metadata.c:2517
static const char metadata_tEXt[]
Definition: metadata.c:203
static WCHAR MPRI_scheme[]
Definition: metadata.c:3189
static WCHAR xmpidq_scheme[]
Definition: metadata.c:3168
static const char animatedgif[]
Definition: metadata.c:265
static WCHAR xmpBJ_scheme[]
Definition: metadata.c:3171
static WCHAR xmpRights_scheme[]
Definition: metadata.c:3169
static const struct metadata_block block2[]
Definition: metadata.c:3639
static void test_WICMapGuidToShortName(void)
Definition: metadata.c:3031
static void test_metadata_gif(void)
Definition: metadata.c:1902
static HRESULT WINAPI mdr_GetCount(IWICMetadataReader *iface, UINT *count)
Definition: metadata.c:3376
static HRESULT get_persist_stream(void *iface_ptr, IStream **stream)
Definition: metadata.c:84
static const char tiff[]
Definition: metadata.c:3601
REFCLSID clsid
Definition: msctf.c:82
unsigned int UINT
Definition: ndis.h:50
#define LOCALE_NEUTRAL
#define L(x)
Definition: ntvdm.h:50
@ COINIT_APARTMENTTHREADED
Definition: objbase.h:278
const GUID IID_IEnumString
short SHORT
Definition: pedump.c:59
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
const GUID IID_IPersist
Definition: proxy.cpp:14
const GUID IID_IPersistStream
Definition: proxy.cpp:13
#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
#define REFCLSID
Definition: guiddef.h:117
#define test
Definition: rosglue.h:37
const char int int int static __inline const char * wine_dbgstr_a(const char *s)
Definition: debug.h:187
static __inline const char * wine_dbgstr_guid(const GUID *id)
Definition: debug.h:197
int winetest_debug
void __winetest_cdecl winetest_push_context(const char *fmt,...)
#define win_skip
Definition: test.h:164
void winetest_pop_context(void)
strcpy
Definition: string.h:131
#define memset(x, y, z)
Definition: compat.h:39
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
struct _ULARGE_INTEGER::@4266 u
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
USHORT marker
Definition: metadata.c:3964
ULONG next_IFD_2
Definition: metadata.c:3973
struct IFD_entry exif_ifd[1]
Definition: metadata.c:3972
ULONG next_IFD_3
Definition: metadata.c:3977
USHORT ifd0_count
Definition: metadata.c:3967
BYTE bom[2]
Definition: metadata.c:3963
ULONG ifd0_offset
Definition: metadata.c:3965
USHORT exif_ifd_count
Definition: metadata.c:3971
struct IFD_entry gps_ifd[1]
Definition: metadata.c:3976
BYTE exif_header[6]
Definition: metadata.c:3962
USHORT gps_ifd_count
Definition: metadata.c:3975
struct IFD_entry ifd0[4]
Definition: metadata.c:3968
ULONG next_IFD
Definition: metadata.c:3969
Definition: tftpd.h:126
Definition: tftpd.h:138
Definition: main.c:439
Definition: format.c:58
struct IFD_rational srational_val
Definition: metadata.c:150
LONG long_val[2]
Definition: metadata.c:153
struct IFD_entry entry[40]
Definition: metadata.c:146
struct IFD_rational xres
Definition: metadata.c:148
DOUBLE double_val
Definition: metadata.c:149
USHORT number_of_entries
Definition: metadata.c:145
struct IFD_rational rational[3]
Definition: metadata.c:155
FLOAT float_val[2]
Definition: metadata.c:154
ULONG next_IFD
Definition: metadata.c:147
SHORT short_val[4]
Definition: metadata.c:152
Definition: parser.c:49
const struct metadata_item * item
Definition: metadata.c:3320
const GUID * metadata_format
Definition: metadata.c:3318
const char * schema
Definition: metadata.c:3312
const char * id_str
Definition: metadata.c:3312
UINT count
Definition: metadata.c:3326
const struct metadata_block * block
Definition: metadata.c:3327
const GUID * container_format
Definition: metadata.c:3325
Definition: name.c:39
Definition: reader.h:84
Definition: send.c:48
Definition: parse.h:23
LONGLONG value[13]
Definition: metadata.c:422
const WCHAR id_string[32]
Definition: metadata.c:424
const char * string
Definition: metadata.c:423
int count
Definition: metadata.c:421
BYTE * data
Definition: ddsformat.c:392
ULONG id
Definition: metadata.c:420
ULONG type
Definition: metadata.c:420
Definition: tiffiop.h:115
static IWICImagingFactory * factory
Definition: tiffformat.c:324
#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:96
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383
#define GMEM_MOVEABLE
Definition: winbase.h:320
@ WICBitmapEncoderNoCache
Definition: wincodec.idl:73
@ WICDecodeMetadataCacheOnLoad
Definition: wincodec.idl:30
@ WICMetadataCreationFailUnknown
Definition: wincodecsdk.idl:35
@ WICPersistOptionBigEndian
Definition: wincodecsdk.idl:25
@ WICPersistOptionDefault
Definition: wincodecsdk.idl:23
@ WICPersistOptionLittleEndian
Definition: wincodecsdk.idl:24
@ WICPersistOptionNoCacheStream
Definition: wincodecsdk.idl:27
#define WINAPI
Definition: msvc.h:6
#define REGDB_E_CLASSNOTREG
Definition: winerror.h:2696
#define S_FALSE
Definition: winerror.h:2357
#define WINCODEC_ERR_COMPONENTNOTFOUND
Definition: winerror.h:3296
#define WINCODEC_ERR_WRONGSTATE
Definition: winerror.h:3281
#define WINCODEC_ERR_UNSUPPORTEDOPERATION
Definition: winerror.h:3308
#define WINCODEC_ERR_NOTINITIALIZED
Definition: winerror.h:3285
#define E_NOINTERFACE
Definition: winerror.h:2364
#define WINCODEC_ERR_INVALIDQUERYCHARACTER
Definition: winerror.h:3318
#define WINCODEC_ERR_PROPERTYNOTSUPPORTED
Definition: winerror.h:3288
#define E_UNEXPECTED
Definition: winerror.h:2456
#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_BADMETADATAHEADER
Definition: winerror.h:3302
#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 WINCODEC_ERR_STREAMNOTAVAILABLE
Definition: winerror.h:3306
#define NORM_IGNORECASE
Definition: winnls.h:178
#define CSTR_EQUAL
Definition: winnls.h:458
__wchar_t WCHAR
Definition: xmlstorage.h:180
unsigned char BYTE
Definition: xxhash.c:193