windowscodecs: Implement IWICMetadataWriter::GetEnumerator.
[wine] / dlls / windowscodecs / tests / metadata.c
1 /*
2  * Copyright 2011 Vincent Povirk for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include <stdio.h>
20 #include <stdarg.h>
21 #include <math.h>
22
23 #define COBJMACROS
24
25 #include "windef.h"
26 #include "objbase.h"
27 #include "wincodec.h"
28 #include "wincodecsdk.h"
29 #include "wine/test.h"
30
31 #define expect_blob(propvar, data, length) do { \
32     ok((propvar).vt == VT_BLOB, "unexpected vt: %i\n", (propvar).vt); \
33     if ((propvar).vt == VT_BLOB) { \
34         ok(U(propvar).blob.cbSize == (length), "expected size %u, got %u\n", (ULONG)(length), U(propvar).blob.cbSize); \
35         if (U(propvar).blob.cbSize == (length)) { \
36             ok(!memcmp(U(propvar).blob.pBlobData, (data), (length)), "unexpected data\n"); \
37         } \
38     } \
39 } while (0)
40
41 static const char metadata_unknown[] = "lalala";
42
43 static const char metadata_tEXt[] = {
44     0,0,0,14, /* chunk length */
45     't','E','X','t', /* chunk type */
46     'w','i','n','e','t','e','s','t',0, /* keyword */
47     'v','a','l','u','e', /* text */
48     0x3f,0x64,0x19,0xf3 /* chunk CRC */
49 };
50
51 static const char *debugstr_guid(REFIID riid)
52 {
53     static char buf[50];
54
55     if(!riid)
56         return "(null)";
57
58     sprintf(buf, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
59             riid->Data1, riid->Data2, riid->Data3, riid->Data4[0],
60             riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4],
61             riid->Data4[5], riid->Data4[6], riid->Data4[7]);
62
63     return buf;
64 }
65
66 static IStream *create_stream(const char *data, int data_size)
67 {
68     HRESULT hr;
69     IStream *stream;
70     HGLOBAL hdata;
71     void *locked_data;
72
73     hdata = GlobalAlloc(GMEM_MOVEABLE, data_size);
74     ok(hdata != 0, "GlobalAlloc failed\n");
75     if (!hdata) return NULL;
76
77     locked_data = GlobalLock(hdata);
78     memcpy(locked_data, data, data_size);
79     GlobalUnlock(hdata);
80
81     hr = CreateStreamOnHGlobal(hdata, TRUE, &stream);
82     ok(hr == S_OK, "CreateStreamOnHGlobal failed, hr=%x\n", hr);
83
84     return stream;
85 }
86
87 static void load_stream(IUnknown *reader, const char *data, int data_size)
88 {
89     HRESULT hr;
90     IWICPersistStream *persist;
91     IStream *stream;
92
93     stream = create_stream(data, data_size);
94     if (!stream)
95         return;
96
97     hr = IUnknown_QueryInterface(reader, &IID_IWICPersistStream, (void**)&persist);
98     ok(hr == S_OK, "QueryInterface failed, hr=%x\n", hr);
99
100     if (SUCCEEDED(hr))
101     {
102         hr = IWICPersistStream_LoadEx(persist, stream, NULL, WICPersistOptionsDefault);
103         ok(hr == S_OK, "LoadEx failed, hr=%x\n", hr);
104
105         IWICPersistStream_Release(persist);
106     }
107
108     IStream_Release(stream);
109 }
110
111 static void test_metadata_unknown(void)
112 {
113     HRESULT hr;
114     IWICMetadataReader *reader;
115     IWICEnumMetadataItem *enumerator;
116     PROPVARIANT schema, id, value;
117     ULONG items_returned;
118
119     hr = CoCreateInstance(&CLSID_WICUnknownMetadataReader, NULL, CLSCTX_INPROC_SERVER,
120         &IID_IWICMetadataReader, (void**)&reader);
121     ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
122     if (FAILED(hr)) return;
123
124     load_stream((IUnknown*)reader, metadata_unknown, sizeof(metadata_unknown));
125
126     hr = IWICMetadataReader_GetEnumerator(reader, &enumerator);
127     ok(hr == S_OK, "GetEnumerator failed, hr=%x\n", hr);
128
129     if (SUCCEEDED(hr))
130     {
131         PropVariantInit(&schema);
132         PropVariantInit(&id);
133         PropVariantInit(&value);
134
135         hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
136         ok(hr == S_OK, "Next failed, hr=%x\n", hr);
137         ok(items_returned == 1, "unexpected item count %i\n", items_returned);
138
139         if (hr == S_OK && items_returned == 1)
140         {
141             ok(schema.vt == VT_EMPTY, "unexpected vt: %i\n", schema.vt);
142             ok(id.vt == VT_EMPTY, "unexpected vt: %i\n", id.vt);
143             expect_blob(value, metadata_unknown, sizeof(metadata_unknown));
144
145             PropVariantClear(&schema);
146             PropVariantClear(&id);
147             PropVariantClear(&value);
148         }
149
150         hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
151         ok(hr == S_FALSE, "Next failed, hr=%x\n", hr);
152         ok(items_returned == 0, "unexpected item count %i\n", items_returned);
153
154         IWICEnumMetadataItem_Release(enumerator);
155     }
156
157     IWICMetadataReader_Release(reader);
158 }
159
160 static void test_metadata_tEXt(void)
161 {
162     HRESULT hr;
163     IWICMetadataReader *reader;
164     IWICEnumMetadataItem *enumerator;
165     PROPVARIANT schema, id, value;
166     ULONG items_returned, count;
167     GUID format;
168
169     PropVariantInit(&schema);
170     PropVariantInit(&id);
171     PropVariantInit(&value);
172
173     hr = CoCreateInstance(&CLSID_WICPngTextMetadataReader, NULL, CLSCTX_INPROC_SERVER,
174         &IID_IWICMetadataReader, (void**)&reader);
175     todo_wine ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
176     if (FAILED(hr)) return;
177
178     hr = IWICMetadataReader_GetCount(reader, NULL);
179     ok(hr == E_INVALIDARG, "GetCount failed, hr=%x\n", hr);
180
181     hr = IWICMetadataReader_GetCount(reader, &count);
182     ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
183     ok(count == 0, "unexpected count %i\n", count);
184
185     load_stream((IUnknown*)reader, metadata_tEXt, sizeof(metadata_tEXt));
186
187     hr = IWICMetadataReader_GetCount(reader, &count);
188     ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
189     ok(count == 1, "unexpected count %i\n", count);
190
191     hr = IWICMetadataReader_GetEnumerator(reader, NULL);
192     ok(hr == E_INVALIDARG, "GetEnumerator failed, hr=%x\n", hr);
193
194     hr = IWICMetadataReader_GetEnumerator(reader, &enumerator);
195     ok(hr == S_OK, "GetEnumerator failed, hr=%x\n", hr);
196
197     if (SUCCEEDED(hr))
198     {
199         hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
200         ok(hr == S_OK, "Next failed, hr=%x\n", hr);
201         ok(items_returned == 1, "unexpected item count %i\n", items_returned);
202
203         if (hr == S_OK && items_returned == 1)
204         {
205             ok(schema.vt == VT_EMPTY, "unexpected vt: %i\n", schema.vt);
206             ok(id.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt);
207             ok(!strcmp(U(id).pszVal, "winetest"), "unexpected id: %s\n", U(id).pszVal);
208             ok(value.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt);
209             ok(!strcmp(U(value).pszVal, "value"), "unexpected value: %s\n", U(id).pszVal);
210
211             PropVariantClear(&schema);
212             PropVariantClear(&id);
213             PropVariantClear(&value);
214         }
215
216         hr = IWICEnumMetadataItem_Next(enumerator, 1, &schema, &id, &value, &items_returned);
217         ok(hr == S_FALSE, "Next failed, hr=%x\n", hr);
218         ok(items_returned == 0, "unexpected item count %i\n", items_returned);
219
220         IWICEnumMetadataItem_Release(enumerator);
221     }
222
223     hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
224     ok(hr == S_OK, "GetMetadataFormat failed, hr=%x\n", hr);
225     ok(IsEqualGUID(&format, &GUID_MetadataFormatChunktEXt), "unexpected format %s\n", debugstr_guid(&format));
226
227     hr = IWICMetadataReader_GetMetadataFormat(reader, NULL);
228     ok(hr == E_INVALIDARG, "GetMetadataFormat failed, hr=%x\n", hr);
229
230     id.vt = VT_LPSTR;
231     U(id).pszVal = CoTaskMemAlloc(strlen("winetest") + 1);
232     strcpy(U(id).pszVal, "winetest");
233
234     hr = IWICMetadataReader_GetValue(reader, NULL, &id, NULL);
235     ok(hr == S_OK, "GetValue failed, hr=%x\n", hr);
236
237     hr = IWICMetadataReader_GetValue(reader, &schema, NULL, &value);
238     ok(hr == E_INVALIDARG, "GetValue failed, hr=%x\n", hr);
239
240     hr = IWICMetadataReader_GetValue(reader, &schema, &id, &value);
241     ok(hr == S_OK, "GetValue failed, hr=%x\n", hr);
242     ok(value.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt);
243     ok(!strcmp(U(value).pszVal, "value"), "unexpected value: %s\n", U(id).pszVal);
244     PropVariantClear(&value);
245
246     strcpy(U(id).pszVal, "test");
247
248     hr = IWICMetadataReader_GetValue(reader, &schema, &id, &value);
249     ok(hr == WINCODEC_ERR_PROPERTYNOTFOUND, "GetValue failed, hr=%x\n", hr);
250
251     PropVariantClear(&id);
252
253     hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, NULL, NULL);
254     ok(hr == S_OK, "GetValueByIndex failed, hr=%x\n", hr);
255
256     hr = IWICMetadataReader_GetValueByIndex(reader, 0, &schema, NULL, NULL);
257     ok(hr == S_OK, "GetValueByIndex failed, hr=%x\n", hr);
258     ok(schema.vt == VT_EMPTY, "unexpected vt: %i\n", schema.vt);
259
260     hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, &id, NULL);
261     ok(hr == S_OK, "GetValueByIndex failed, hr=%x\n", hr);
262     ok(id.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt);
263     ok(!strcmp(U(id).pszVal, "winetest"), "unexpected id: %s\n", U(id).pszVal);
264     PropVariantClear(&id);
265
266     hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, NULL, &value);
267     ok(hr == S_OK, "GetValueByIndex failed, hr=%x\n", hr);
268     ok(value.vt == VT_LPSTR, "unexpected vt: %i\n", id.vt);
269     ok(!strcmp(U(value).pszVal, "value"), "unexpected value: %s\n", U(id).pszVal);
270     PropVariantClear(&value);
271
272     hr = IWICMetadataReader_GetValueByIndex(reader, 1, NULL, NULL, NULL);
273     ok(hr == E_INVALIDARG, "GetValueByIndex failed, hr=%x\n", hr);
274
275     IWICMetadataReader_Release(reader);
276 }
277
278 static void test_create_reader(void)
279 {
280     HRESULT hr;
281     IWICComponentFactory *factory;
282     IStream *stream;
283     IWICMetadataReader *reader;
284     UINT count=0;
285     GUID format;
286
287     hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
288         &IID_IWICComponentFactory, (void**)&factory);
289     todo_wine ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
290     if (FAILED(hr)) return;
291
292     stream = create_stream(metadata_tEXt, sizeof(metadata_tEXt));
293
294     hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
295         &GUID_ContainerFormatPng, NULL, WICPersistOptionsDefault,
296         stream, &reader);
297     ok(hr == S_OK, "CreateMetadataReaderFromContainer failed, hr=%x\n", hr);
298
299     if (SUCCEEDED(hr))
300     {
301         hr = IWICMetadataReader_GetCount(reader, &count);
302         ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
303         ok(count == 1, "unexpected count %i\n", count);
304
305         hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
306         ok(hr == S_OK, "GetMetadataFormat failed, hr=%x\n", hr);
307         ok(IsEqualGUID(&format, &GUID_MetadataFormatChunktEXt), "unexpected format %s\n", debugstr_guid(&format));
308
309         IWICMetadataReader_Release(reader);
310     }
311
312     hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
313         &GUID_ContainerFormatWmp, NULL, WICPersistOptionsDefault,
314         stream, &reader);
315     ok(hr == S_OK, "CreateMetadataReaderFromContainer failed, hr=%x\n", hr);
316
317     if (SUCCEEDED(hr))
318     {
319         hr = IWICMetadataReader_GetCount(reader, &count);
320         ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
321         ok(count == 1, "unexpected count %i\n", count);
322
323         hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
324         ok(hr == S_OK, "GetMetadataFormat failed, hr=%x\n", hr);
325         ok(IsEqualGUID(&format, &GUID_MetadataFormatUnknown), "unexpected format %s\n", debugstr_guid(&format));
326
327         IWICMetadataReader_Release(reader);
328     }
329
330     IStream_Release(stream);
331
332     IWICComponentFactory_Release(factory);
333 }
334
335 START_TEST(metadata)
336 {
337     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
338
339     test_metadata_unknown();
340     test_metadata_tEXt();
341     test_create_reader();
342
343     CoUninitialize();
344 }