ReactOS 0.4.16-dev-975-g3b8cfa4
metadataquery.c
Go to the documentation of this file.
1/*
2 * Copyright 2016 Andrew Eikum for CodeWeavers
3 * Copyright 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 <stdarg.h>
21#include <wchar.h>
22
23#define COBJMACROS
24#include "windef.h"
25#include "winbase.h"
26#include "objbase.h"
27#include "propvarutil.h"
28
29#include "wincodecs_private.h"
30
31#include "wine/debug.h"
32
34
35static const WCHAR *map_shortname_to_schema(const GUID *format, const WCHAR *name);
36
37typedef struct {
43
45{
46 return CONTAINING_RECORD(iface, QueryReader, IWICMetadataQueryReader_iface);
47}
48
50 void **ppvObject)
51{
53
54 TRACE("(%p,%s,%p)\n", This, debugstr_guid(riid), ppvObject);
55
57 IsEqualGUID(riid, &IID_IWICMetadataQueryReader))
58 *ppvObject = &This->IWICMetadataQueryReader_iface;
59 else
60 *ppvObject = NULL;
61
62 if (*ppvObject)
63 {
64 IUnknown_AddRef((IUnknown*)*ppvObject);
65 return S_OK;
66 }
67
68 return E_NOINTERFACE;
69}
70
72{
75 TRACE("(%p) refcount=%lu\n", This, ref);
76 return ref;
77}
78
80{
83 TRACE("(%p) refcount=%lu\n", This, ref);
84 if (!ref)
85 {
86 IWICMetadataBlockReader_Release(This->block);
87 free(This->root);
88 free(This);
89 }
90 return ref;
91}
92
94{
96
97 TRACE("(%p,%p)\n", This, format);
98
99 return IWICMetadataBlockReader_GetContainerFormat(This->block, format);
100}
101
103{
105 const WCHAR *root;
106 UINT actual_len;
107
108 TRACE("(%p,%u,%p,%p)\n", This, len, location, ret_len);
109
110 if (!ret_len) return E_INVALIDARG;
111
112 root = This->root ? This->root : L"/";
113 actual_len = lstrlenW(root) + 1;
114
115 if (location)
116 {
117 if (len < actual_len)
119
120 memcpy(location, root, actual_len * sizeof(WCHAR));
121 }
122
123 *ret_len = actual_len;
124
125 return S_OK;
126}
127
129{
130 const WCHAR *str;
131 int len;
132};
133
134static const struct
135{
136 int len;
139} str2vt[] =
140{
141 { 4, {'c','h','a','r'}, VT_I1 },
142 { 5, {'u','c','h','a','r'}, VT_UI1 },
143 { 5, {'s','h','o','r','t'}, VT_I2 },
144 { 6, {'u','s','h','o','r','t'}, VT_UI2 },
145 { 4, {'l','o','n','g'}, VT_I4 },
146 { 5, {'u','l','o','n','g'}, VT_UI4 },
147 { 3, {'i','n','t'}, VT_I4 },
148 { 4, {'u','i','n','t'}, VT_UI4 },
149 { 8, {'l','o','n','g','l','o','n','g'}, VT_I8 },
150 { 9, {'u','l','o','n','g','l','o','n','g'}, VT_UI8 },
151 { 5, {'f','l','o','a','t'}, VT_R4 },
152 { 6, {'d','o','u','b','l','e'}, VT_R8 },
153 { 3, {'s','t','r'}, VT_LPSTR },
154 { 4, {'w','s','t','r'}, VT_LPWSTR },
155 { 4, {'g','u','i','d'}, VT_CLSID },
156 { 4, {'b','o','o','l'}, VT_BOOL }
158
160{
161 UINT i;
162
163 for (i = 0; i < ARRAY_SIZE(str2vt); i++)
164 {
165 if (str2vt[i].len == str->len)
166 {
168 str->str, str->len, str2vt[i].str, str2vt[i].len) == CSTR_EQUAL)
169 return str2vt[i].vt;
170 }
171 }
172
173 WARN("type %s is not recognized\n", wine_dbgstr_wn(str->str, str->len));
174
175 return VT_ILLEGAL;
176}
177
178static HRESULT get_token(struct string_t *elem, PROPVARIANT *id, PROPVARIANT *schema, int *idx)
179{
180 const WCHAR *start, *end, *p;
181 WCHAR *bstr;
182 struct string_t next_elem;
183 HRESULT hr;
184
185 TRACE("%s, len %d\n", wine_dbgstr_wn(elem->str, elem->len), elem->len);
186
187 PropVariantInit(id);
188 PropVariantInit(schema);
189
190 if (!elem->len) return S_OK;
191
192 start = elem->str;
193
194 if (*start == '[')
195 {
196 WCHAR *idx_end;
197
198 if (start[1] < '0' || start[1] > '9') return DISP_E_TYPEMISMATCH;
199
200 *idx = wcstol(start + 1, &idx_end, 10);
201 if (idx_end > elem->str + elem->len) return WINCODEC_ERR_INVALIDQUERYREQUEST;
202 if (*idx_end != ']') return WINCODEC_ERR_INVALIDQUERYREQUEST;
203 if (*idx < 0) return WINCODEC_ERR_INVALIDQUERYREQUEST;
204 end = idx_end + 1;
205
206 next_elem.str = end;
207 next_elem.len = elem->len - (end - start);
208 hr = get_token(&next_elem, id, schema, idx);
209 if (hr != S_OK)
210 {
211 TRACE("get_token error %#lx\n", hr);
212 return hr;
213 }
214 elem->len = (end - start) + next_elem.len;
215
216 TRACE("indexed %s [%d]\n", wine_dbgstr_wn(elem->str, elem->len), *idx);
217 return S_OK;
218 }
219 else if (*start == '{')
220 {
221 VARTYPE vt;
222 PROPVARIANT next_token;
223
224 end = wmemchr(start + 1, '=', elem->len - 1);
226 if (end > elem->str + elem->len) return WINCODEC_ERR_INVALIDQUERYREQUEST;
227
228 next_elem.str = start + 1;
229 next_elem.len = end - start - 1;
230 vt = map_type(&next_elem);
231 TRACE("type %s => %d\n", wine_dbgstr_wn(next_elem.str, next_elem.len), vt);
233
234 next_token.vt = VT_BSTR;
235 next_token.bstrVal = SysAllocStringLen(NULL, elem->len - (end - start) + 1);
236 if (!next_token.bstrVal) return E_OUTOFMEMORY;
237
238 bstr = next_token.bstrVal;
239
240 end++;
241 while (*end && *end != '}' && end - start < elem->len)
242 {
243 if (*end == '\\') end++;
244 *bstr++ = *end++;
245 }
246 if (*end != '}')
247 {
250 }
251 *bstr = 0;
252 TRACE("schema/id %s\n", wine_dbgstr_w(next_token.bstrVal));
253
254 if (vt == VT_CLSID)
255 {
256 id->vt = VT_CLSID;
257 id->puuid = CoTaskMemAlloc(sizeof(GUID));
258 if (!id->puuid)
259 {
261 return E_OUTOFMEMORY;
262 }
263
264 hr = UuidFromStringW(next_token.bstrVal, id->puuid);
265 }
266 else
269 if (hr != S_OK)
270 {
273 return hr;
274 }
275
276 end++;
277 if (*end == ':')
278 {
279 PROPVARIANT next_id, next_schema;
280 int next_idx = 0;
281
282 next_elem.str = end + 1;
283 next_elem.len = elem->len - (end - start + 1);
284 hr = get_token(&next_elem, &next_id, &next_schema, &next_idx);
285 if (hr != S_OK)
286 {
287 TRACE("get_token error %#lx\n", hr);
288 return hr;
289 }
290 elem->len = (end - start + 1) + next_elem.len;
291
292 TRACE("id %s [%d]\n", wine_dbgstr_wn(elem->str, elem->len), *idx);
293
294 if (next_schema.vt != VT_EMPTY)
295 {
296 PropVariantClear(&next_id);
297 PropVariantClear(&next_schema);
299 }
300
301 *schema = *id;
302 *id = next_id;
303
304 return S_OK;
305 }
306
307 elem->len = end - start;
308 return S_OK;
309 }
310
311 end = wmemchr(start, '/', elem->len);
312 if (!end) end = start + elem->len;
313
314 p = wmemchr(start, ':', end - start);
315 if (p)
316 {
317 next_elem.str = p + 1;
318 next_elem.len = end - p - 1;
319
320 elem->len = p - start;
321 }
322 else
323 elem->len = end - start;
324
325 id->vt = VT_BSTR;
326 id->bstrVal = SysAllocStringLen(NULL, elem->len + 1);
327 if (!id->bstrVal) return E_OUTOFMEMORY;
328
329 bstr = id->bstrVal;
330 p = elem->str;
331 while (p - elem->str < elem->len)
332 {
333 if (*p == '\\') p++;
334 *bstr++ = *p++;
335 }
336 *bstr = 0;
337 TRACE("%s [%d]\n", wine_dbgstr_variant((VARIANT *)id), *idx);
338
339 if (*p == ':')
340 {
341 PROPVARIANT next_id, next_schema;
342 int next_idx = 0;
343
344 hr = get_token(&next_elem, &next_id, &next_schema, &next_idx);
345 if (hr != S_OK)
346 {
347 TRACE("get_token error %#lx\n", hr);
350 return hr;
351 }
352 elem->len += next_elem.len + 1;
353
354 TRACE("id %s [%d]\n", wine_dbgstr_wn(elem->str, elem->len), *idx);
355
356 if (next_schema.vt != VT_EMPTY)
357 {
358 PropVariantClear(&next_id);
359 PropVariantClear(&next_schema);
363 }
364
365 *schema = *id;
366 *id = next_id;
367 }
368
369 return S_OK;
370}
371
374{
375 HRESULT hr;
376 GUID format;
377 IWICMetadataReader *new_reader;
378 UINT count, i, matched_index;
379
380 *reader = NULL;
381
382 hr = IWICMetadataBlockReader_GetCount(block_reader, &count);
383 if (hr != S_OK) return hr;
384
385 matched_index = 0;
386
387 for (i = 0; i < count; i++)
388 {
389 hr = IWICMetadataBlockReader_GetReaderByIndex(block_reader, i, &new_reader);
390 if (hr != S_OK) return hr;
391
392 hr = IWICMetadataReader_GetMetadataFormat(new_reader, &format);
393 if (hr == S_OK)
394 {
395 if (IsEqualGUID(&format, guid))
396 {
397 if (matched_index == index)
398 {
399 *reader = new_reader;
400 return S_OK;
401 }
402
403 matched_index++;
404 }
405 }
406
407 IWICMetadataReader_Release(new_reader);
408 if (hr != S_OK) return hr;
409 }
410
412}
413
415 GUID *guid, IWICMetadataReader **new_reader)
416{
417 HRESULT hr;
418 PROPVARIANT schema, id, value;
419
420 *new_reader = NULL;
421
422 PropVariantInit(&schema);
423 PropVariantInit(&id);
424 PropVariantInit(&value);
425
426 if (index)
427 {
428 schema.vt = VT_UI2;
429 schema.uiVal = index;
430 }
431
432 id.vt = VT_CLSID;
433 id.puuid = guid;
434 hr = IWICMetadataReader_GetValue(reader, &schema, &id, &value);
435 if (hr != S_OK) return hr;
436
437 if (value.vt == VT_UNKNOWN)
438 hr = IUnknown_QueryInterface(value.punkVal, &IID_IWICMetadataReader, (void **)new_reader);
439 else
441
443 return hr;
444}
445
447{
449 struct string_t elem;
450 WCHAR *full_query;
451 const WCHAR *p;
452 int index, len;
453 PROPVARIANT tk_id, tk_schema, new_value;
454 GUID guid;
456 HRESULT hr = S_OK;
457
458 TRACE("(%p,%s,%p)\n", This, wine_dbgstr_w(query), value);
459
460 len = lstrlenW(query) + 1;
461 if (This->root) len += lstrlenW(This->root);
462 full_query = malloc(len * sizeof(WCHAR));
463 full_query[0] = 0;
464 if (This->root)
465 lstrcpyW(full_query, This->root);
466 lstrcatW(full_query, query);
467
468 PropVariantInit(&tk_id);
469 PropVariantInit(&tk_schema);
470 PropVariantInit(&new_value);
471
472 reader = NULL;
473 p = full_query;
474
475 while (*p)
476 {
477 if (*p != '/')
478 {
479 WARN("query should start with '/'\n");
481 break;
482 }
483
484 p++;
485
486 index = 0;
487 elem.str = p;
488 elem.len = lstrlenW(p);
489 hr = get_token(&elem, &tk_id, &tk_schema, &index);
490 if (hr != S_OK)
491 {
492 WARN("get_token error %#lx\n", hr);
493 break;
494 }
495 TRACE("parsed %d characters: %s, index %d\n", elem.len, wine_dbgstr_wn(elem.str, elem.len), index);
496 TRACE("id %s, schema %s\n", wine_dbgstr_variant((VARIANT *)&tk_id), wine_dbgstr_variant((VARIANT *)&tk_schema));
497
498 if (!elem.len) break;
499
500 if (tk_id.vt == VT_CLSID || (tk_id.vt == VT_BSTR && WICMapShortNameToGuid(tk_id.bstrVal, &guid) == S_OK))
501 {
502 WCHAR *root;
503
504 if (tk_schema.vt != VT_EMPTY)
505 {
506 FIXME("unsupported schema vt %u\n", tk_schema.vt);
507 PropVariantClear(&tk_schema);
508 }
509
510 if (tk_id.vt == VT_CLSID) guid = *tk_id.puuid;
511
512 if (reader)
513 {
514 IWICMetadataReader *new_reader;
515
516 hr = get_next_reader(reader, index, &guid, &new_reader);
517 IWICMetadataReader_Release(reader);
518 reader = new_reader;
519 }
520 else
522
523 if (hr != S_OK) break;
524
525 root = SysAllocStringLen(NULL, elem.str + elem.len - full_query + 2);
526 if (!root)
527 {
529 break;
530 }
531 lstrcpynW(root, full_query, p - full_query + elem.len + 1);
532
533 PropVariantClear(&new_value);
534 new_value.vt = VT_UNKNOWN;
535 hr = MetadataQueryReader_CreateInstance(This->block, root, (IWICMetadataQueryReader **)&new_value.punkVal);
537 if (hr != S_OK) break;
538 }
539 else
540 {
541 PROPVARIANT schema, id;
542
543 if (!reader)
544 {
546 break;
547 }
548
549 if (tk_schema.vt == VT_BSTR)
550 {
551 hr = IWICMetadataReader_GetMetadataFormat(reader, &guid);
552 if (hr != S_OK) break;
553
554 schema.vt = VT_LPWSTR;
555 schema.pwszVal = (LPWSTR)map_shortname_to_schema(&guid, tk_schema.bstrVal);
556 if (!schema.pwszVal)
557 schema.pwszVal = tk_schema.bstrVal;
558 }
559 else
560 schema = tk_schema;
561
562 if (tk_id.vt == VT_BSTR)
563 {
564 id.vt = VT_LPWSTR;
565 id.pwszVal = tk_id.bstrVal;
566 }
567 else
568 id = tk_id;
569
570 PropVariantClear(&new_value);
571 hr = IWICMetadataReader_GetValue(reader, &schema, &id, &new_value);
572 if (hr != S_OK) break;
573 }
574
575 p += elem.len;
576
577 PropVariantClear(&tk_id);
578 PropVariantClear(&tk_schema);
579 }
580
581 if (reader)
582 IWICMetadataReader_Release(reader);
583
584 PropVariantClear(&tk_id);
585 PropVariantClear(&tk_schema);
586
587 if (hr == S_OK && value)
588 *value = new_value;
589 else
590 PropVariantClear(&new_value);
591
592 free(full_query);
593
594 return hr;
595}
596
598{
601};
602
604{
606}
607
609{
610 struct string_enumerator *this = impl_from_IEnumString(iface);
611
612 TRACE("iface %p, riid %s, ppv %p.\n", iface, debugstr_guid(riid), ppv);
613
615 *ppv = &this->IEnumString_iface;
616 else
617 {
618 WARN("Unknown riid %s.\n", debugstr_guid(riid));
619 *ppv = NULL;
620 return E_NOINTERFACE;
621 }
622
623 IUnknown_AddRef(&this->IEnumString_iface);
624 return S_OK;
625}
626
628{
629 struct string_enumerator *this = impl_from_IEnumString(iface);
630 ULONG ref = InterlockedIncrement(&this->ref);
631
632 TRACE("iface %p, ref %lu.\n", iface, ref);
633
634 return ref;
635}
636
638{
639 struct string_enumerator *this = impl_from_IEnumString(iface);
640 ULONG ref = InterlockedDecrement(&this->ref);
641
642 TRACE("iface %p, ref %lu.\n", iface, ref);
643
644 if (!ref)
645 free(this);
646
647 return ref;
648}
649
651{
652 FIXME("iface %p, count %lu, strings %p, ret %p stub.\n", iface, count, strings, ret);
653
654 if (!strings || !ret)
655 return E_INVALIDARG;
656
657 *ret = 0;
658 return count ? S_FALSE : S_OK;
659}
660
662{
663 TRACE("iface %p.\n", iface);
664
665 return S_OK;
666}
667
669{
670 FIXME("iface %p, count %lu stub.\n", iface, count);
671
672 return count ? S_FALSE : S_OK;
673}
674
676{
677 FIXME("iface %p, out %p stub.\n", iface, out);
678
679 *out = NULL;
680 return E_NOTIMPL;
681}
682
683static const IEnumStringVtbl string_enumerator_vtbl =
684{
692};
693
695{
697
698 if (!(object = calloc(1, sizeof(*object))))
699 return E_OUTOFMEMORY;
700
701 object->IEnumString_iface.lpVtbl = &string_enumerator_vtbl;
702 object->ref = 1;
703
704 *enum_string = &object->IEnumString_iface;
705
706 return S_OK;
707}
708
710 IEnumString **enum_string)
711{
712 TRACE("iface %p, enum_string %p.\n", iface, enum_string);
713
714 return string_enumerator_create(enum_string);
715}
716
717static IWICMetadataQueryReaderVtbl mqr_vtbl = {
725};
726
728{
730
731 obj = calloc(1, sizeof(*obj));
732 if (!obj)
733 return E_OUTOFMEMORY;
734
735 obj->IWICMetadataQueryReader_iface.lpVtbl = &mqr_vtbl;
736 obj->ref = 1;
737
738 IWICMetadataBlockReader_AddRef(mbr);
739 obj->block = mbr;
740
741 obj->root = wcsdup(root);
742
743 *out = &obj->IWICMetadataQueryReader_iface;
744
745 return S_OK;
746}
747
748typedef struct
749{
754}
756
758{
759 return CONTAINING_RECORD(iface, QueryWriter, IWICMetadataQueryWriter_iface);
760}
761
763 void **object)
764{
766
767 TRACE("writer %p, riid %s, object %p.\n", writer, debugstr_guid(riid), object);
768
770 || IsEqualGUID(riid, &IID_IWICMetadataQueryWriter)
771 || IsEqualGUID(riid, &IID_IWICMetadataQueryReader))
772 *object = &writer->IWICMetadataQueryWriter_iface;
773 else
774 *object = NULL;
775
776 if (*object)
777 {
778 IUnknown_AddRef((IUnknown *)*object);
779 return S_OK;
780 }
781
782 return E_NOINTERFACE;
783}
784
786{
788 ULONG ref = InterlockedIncrement(&writer->ref);
789
790 TRACE("writer %p, refcount=%lu\n", writer, ref);
791
792 return ref;
793}
794
796{
798 ULONG ref = InterlockedDecrement(&writer->ref);
799
800 TRACE("writer %p, refcount=%lu.\n", writer, ref);
801
802 if (!ref)
803 {
804 IWICMetadataBlockWriter_Release(writer->block);
805 free(writer->root);
806 free(writer);
807 }
808 return ref;
809}
810
812{
813 FIXME("iface %p, container_format %p stub.\n", iface, container_format);
814
815 return E_NOTIMPL;
816}
817
819{
820 TRACE("iface %p, enum_string %p.\n", iface, enum_string);
821
822 return string_enumerator_create(enum_string);
823}
824
825static HRESULT WINAPI mqw_GetLocation(IWICMetadataQueryWriter *iface, UINT max_length, WCHAR *namespace, UINT *actual_length)
826{
827 FIXME("iface %p, max_length %u, namespace %s, actual_length %p stub.\n",
828 iface, max_length, debugstr_w(namespace), actual_length);
829
830 return E_NOTIMPL;
831}
832
834{
835 FIXME("name %s, value %p stub.\n", debugstr_w(name), value);
836
837 return E_NOTIMPL;
838}
839
841{
842 FIXME("iface %p, name %s, value %p stub.\n", iface, debugstr_w(name), value);
843
844 return S_OK;
845}
846
848{
849 FIXME("iface %p, name %s stub.\n", iface, debugstr_w(name));
850
851 return E_NOTIMPL;
852}
853
854static const IWICMetadataQueryWriterVtbl mqw_vtbl =
855{
865};
866
868{
870
871 obj = calloc(1, sizeof(*obj));
872 if (!obj)
873 return E_OUTOFMEMORY;
874
875 obj->IWICMetadataQueryWriter_iface.lpVtbl = &mqw_vtbl;
876 obj->ref = 1;
877
878 IWICMetadataBlockWriter_AddRef(mbw);
879 obj->block = mbw;
880
881 obj->root = wcsdup(root);
882
883 *out = &obj->IWICMetadataQueryWriter_iface;
884
885 return S_OK;
886}
887
888static const struct
889{
890 const GUID *guid;
891 const WCHAR *name;
892} guid2name[] =
893{
894 { &GUID_ContainerFormatBmp, L"bmp" },
895 { &GUID_ContainerFormatPng, L"png" },
896 { &GUID_ContainerFormatIco, L"ico" },
897 { &GUID_ContainerFormatJpeg, L"jpg" },
898 { &GUID_ContainerFormatTiff, L"tiff" },
899 { &GUID_ContainerFormatGif, L"gif" },
900 { &GUID_ContainerFormatWmp, L"wmphoto" },
901 { &GUID_MetadataFormatUnknown, L"unknown" },
902 { &GUID_MetadataFormatIfd, L"ifd" },
903 { &GUID_MetadataFormatSubIfd, L"sub" },
904 { &GUID_MetadataFormatExif, L"exif" },
905 { &GUID_MetadataFormatGps, L"gps" },
906 { &GUID_MetadataFormatInterop, L"interop" },
907 { &GUID_MetadataFormatApp0, L"app0" },
908 { &GUID_MetadataFormatApp1, L"app1" },
909 { &GUID_MetadataFormatApp13, L"app13" },
910 { &GUID_MetadataFormatIPTC, L"iptc" },
911 { &GUID_MetadataFormatIRB, L"irb" },
912 { &GUID_MetadataFormat8BIMIPTC, L"8bimiptc" },
913 { &GUID_MetadataFormat8BIMResolutionInfo, L"8bimResInfo" },
914 { &GUID_MetadataFormat8BIMIPTCDigest, L"8bimiptcdigest" },
915 { &GUID_MetadataFormatXMP, L"xmp" },
916 { &GUID_MetadataFormatThumbnail, L"thumb" },
917 { &GUID_MetadataFormatChunktEXt, L"tEXt" },
918 { &GUID_MetadataFormatXMPStruct, L"xmpstruct" },
919 { &GUID_MetadataFormatXMPBag, L"xmpbag" },
920 { &GUID_MetadataFormatXMPSeq, L"xmpseq" },
921 { &GUID_MetadataFormatXMPAlt, L"xmpalt" },
922 { &GUID_MetadataFormatLSD, L"logscrdesc" },
923 { &GUID_MetadataFormatIMD, L"imgdesc" },
924 { &GUID_MetadataFormatGCE, L"grctlext" },
925 { &GUID_MetadataFormatAPE, L"appext" },
926 { &GUID_MetadataFormatJpegChrominance, L"chrominance" },
927 { &GUID_MetadataFormatJpegLuminance, L"luminance" },
928 { &GUID_MetadataFormatJpegComment, L"com" },
929 { &GUID_MetadataFormatGifComment, L"commentext" },
930 { &GUID_MetadataFormatChunkgAMA, L"gAMA" },
931 { &GUID_MetadataFormatChunkbKGD, L"bKGD" },
932 { &GUID_MetadataFormatChunkiTXt, L"iTXt" },
933 { &GUID_MetadataFormatChunkcHRM, L"cHRM" },
934 { &GUID_MetadataFormatChunkhIST, L"hIST" },
935 { &GUID_MetadataFormatChunkiCCP, L"iCCP" },
936 { &GUID_MetadataFormatChunksRGB, L"sRGB" },
937 { &GUID_MetadataFormatChunktIME, L"tIME" }
939
941{
942 UINT i;
943
944 TRACE("%s,%u,%p,%p\n", wine_dbgstr_guid(guid), len, name, ret_len);
945
946 if (!guid) return E_INVALIDARG;
947
948 for (i = 0; i < ARRAY_SIZE(guid2name); i++)
949 {
951 {
952 if (name)
953 {
954 if (!len) return E_INVALIDARG;
955
956 len = min(len - 1, lstrlenW(guid2name[i].name));
957 memcpy(name, guid2name[i].name, len * sizeof(WCHAR));
958 name[len] = 0;
959
960 if (len < lstrlenW(guid2name[i].name))
962 }
963 if (ret_len) *ret_len = lstrlenW(guid2name[i].name) + 1;
964 return S_OK;
965 }
966 }
967
969}
970
972{
973 UINT i;
974
975 TRACE("%s,%p\n", debugstr_w(name), guid);
976
977 if (!name || !guid) return E_INVALIDARG;
978
979 for (i = 0; i < ARRAY_SIZE(guid2name); i++)
980 {
981 if (!lstrcmpiW(name, guid2name[i].name))
982 {
983 *guid = *guid2name[i].guid;
984 return S_OK;
985 }
986 }
987
989}
990
991static const struct
992{
993 const WCHAR *name;
994 const WCHAR *schema;
995} name2schema[] =
996{
997 { L"rdf", L"http://www.w3.org/1999/02/22-rdf-syntax-ns#" },
998 { L"dc", L"http://purl.org/dc/elements/1.1/" },
999 { L"xmp", L"http://ns.adobe.com/xap/1.0/" },
1000 { L"xmpidq", L"http://ns.adobe.com/xmp/Identifier/qual/1.0/" },
1001 { L"xmpRights", L"http://ns.adobe.com/xap/1.0/rights/" },
1002 { L"xmpMM", L"http://ns.adobe.com/xap/1.0/mm/" },
1003 { L"xmpBJ", L"http://ns.adobe.com/xap/1.0/bj/" },
1004 { L"xmpTPg", L"http://ns.adobe.com/xap/1.0/t/pg/" },
1005 { L"pdf", L"http://ns.adobe.com/pdf/1.3/" },
1006 { L"photoshop", L"http://ns.adobe.com/photoshop/1.0/" },
1007 { L"tiff", L"http://ns.adobe.com/tiff/1.0/" },
1008 { L"exif", L"http://ns.adobe.com/exif/1.0/" },
1009 { L"stDim", L"http://ns.adobe.com/xap/1.0/sType/Dimensions#" },
1010 { L"xapGImg", L"http://ns.adobe.com/xap/1.0/g/img/" },
1011 { L"stEvt", L"http://ns.adobe.com/xap/1.0/sType/ResourceEvent#" },
1012 { L"stRef", L"http://ns.adobe.com/xap/1.0/sType/ResourceRef#" },
1013 { L"stVer", L"http://ns.adobe.com/xap/1.0/sType/Version#" },
1014 { L"stJob", L"http://ns.adobe.com/xap/1.0/sType/Job#" },
1015 { L"aux", L"http://ns.adobe.com/exif/1.0/aux/" },
1016 { L"crs", L"http://ns.adobe.com/camera-raw-settings/1.0/" },
1017 { L"xmpDM", L"http://ns.adobe.com/xmp/1.0/DynamicMedia/" },
1018 { L"Iptc4xmpCore", L"http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/" },
1019 { L"MicrosoftPhoto", L"http://ns.microsoft.com/photo/1.0/" },
1020 { L"MP", L"http://ns.microsoft.com/photo/1.2/" },
1021 { L"MPRI", L"http://ns.microsoft.com/photo/1.2/t/RegionInfo#" },
1022 { L"MPReg", L"http://ns.microsoft.com/photo/1.2/t/Region#" }
1024
1025static const WCHAR *map_shortname_to_schema(const GUID *format, const WCHAR *name)
1026{
1027 UINT i;
1028
1029 /* It appears that the only metadata formats
1030 * that support schemas are xmp and xmpstruct.
1031 */
1032 if (!IsEqualGUID(format, &GUID_MetadataFormatXMP) &&
1033 !IsEqualGUID(format, &GUID_MetadataFormatXMPStruct))
1034 return NULL;
1035
1036 for (i = 0; i < ARRAY_SIZE(name2schema); i++)
1037 {
1038 if (!wcscmp(name2schema[i].name, name))
1039 return name2schema[i].schema;
1040 }
1041
1042 return NULL;
1043}
1044
1046{
1047 UINT i;
1048
1049 TRACE("%s,%s,%u,%p,%p\n", wine_dbgstr_guid(format), debugstr_w(schema), len, name, ret_len);
1050
1051 if (!format || !schema || !ret_len)
1052 return E_INVALIDARG;
1053
1054 /* It appears that the only metadata formats
1055 * that support schemas are xmp and xmpstruct.
1056 */
1057 if (!IsEqualGUID(format, &GUID_MetadataFormatXMP) &&
1058 !IsEqualGUID(format, &GUID_MetadataFormatXMPStruct))
1060
1061 for (i = 0; i < ARRAY_SIZE(name2schema); i++)
1062 {
1064 {
1065 if (name)
1066 {
1067 if (!len) return E_INVALIDARG;
1068
1069 len = min(len - 1, lstrlenW(name2schema[i].name));
1070 memcpy(name, name2schema[i].name, len * sizeof(WCHAR));
1071 name[len] = 0;
1072
1073 if (len < lstrlenW(name2schema[i].name))
1075 }
1076
1078 return S_OK;
1079 }
1080 }
1081
1083}
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define index(s, c)
Definition: various.h:29
#define ARRAY_SIZE(A)
Definition: main.h:20
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
const GUID IID_IUnknown
struct _root root
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#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
int next_token(char **, FILE *)
#define NULL
Definition: types.h:112
unsigned int idx
Definition: utils.c:41
unsigned short VARTYPE
Definition: compat.h:2254
#define lstrcpyW
Definition: compat.h:749
@ VT_UI8
Definition: compat.h:2315
@ VT_BSTR
Definition: compat.h:2303
@ 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_ILLEGAL
Definition: compat.h:2344
@ 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_UI1
Definition: compat.h:2311
#define lstrcpynW
Definition: compat.h:738
#define lstrlenW
Definition: compat.h:750
INT WINAPI CompareStringW(LCID lcid, DWORD flags, LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
Definition: locale.c:4014
int WINAPI lstrcmpiW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4262
HRESULT WINAPI PropVariantClear(PROPVARIANT *pvar)
Definition: ole2.c:2968
HRESULT WINAPI PropVariantChangeType(PROPVARIANT *ppropvarDest, REFPROPVARIANT propvarSrc, PROPVAR_CHANGE_FLAGS flags, VARTYPE vt)
Definition: propvar.c:537
GLuint start
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint GLuint end
Definition: gl.h:1545
GLsizei const GLchar *const * strings
Definition: glext.h:7622
GLuint index
Definition: glext.h:6031
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
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
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:426
_Check_return_ long __cdecl wcstol(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
_CONST_RETURN wchar_t *__cdecl wmemchr(_In_reads_(_N) const wchar_t *_S, _In_ wchar_t _C, _In_ size_t _N)
Definition: wchar.h:2606
REFIID riid
Definition: atlbase.h:39
REFIID LPVOID * ppv
Definition: atlbase.h:39
#define S_OK
Definition: intsafe.h:52
#define debugstr_guid
Definition: kernel32.h:35
#define debugstr_w
Definition: kernel32.h:32
#define wine_dbgstr_w
Definition: kernel32.h:34
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
static HRESULT WINAPI string_enumerator_Clone(IEnumString *iface, IEnumString **out)
static const struct @625 str2vt[]
HRESULT MetadataQueryWriter_CreateInstance(IWICMetadataBlockWriter *mbw, const WCHAR *root, IWICMetadataQueryWriter **out)
static ULONG WINAPI string_enumerator_AddRef(IEnumString *iface)
static ULONG WINAPI mqr_AddRef(IWICMetadataQueryReader *iface)
Definition: metadataquery.c:71
HRESULT WINAPI WICMapGuidToShortName(REFGUID guid, UINT len, WCHAR *name, UINT *ret_len)
static VARTYPE map_type(struct string_t *str)
static HRESULT get_token(struct string_t *elem, PROPVARIANT *id, PROPVARIANT *schema, int *idx)
static ULONG WINAPI mqr_Release(IWICMetadataQueryReader *iface)
Definition: metadataquery.c:79
static HRESULT string_enumerator_create(IEnumString **enum_string)
static HRESULT WINAPI string_enumerator_QueryInterface(IEnumString *iface, REFIID riid, void **ppv)
static QueryReader * impl_from_IWICMetadataQueryReader(IWICMetadataQueryReader *iface)
Definition: metadataquery.c:44
static HRESULT WINAPI mqw_GetContainerFormat(IWICMetadataQueryWriter *iface, GUID *container_format)
static struct string_enumerator * impl_from_IEnumString(IEnumString *iface)
static QueryWriter * impl_from_IWICMetadataQueryWriter(IWICMetadataQueryWriter *iface)
static HRESULT WINAPI mqr_GetLocation(IWICMetadataQueryReader *iface, UINT len, WCHAR *location, UINT *ret_len)
WCHAR str[10]
HRESULT WINAPI WICMapSchemaToName(REFGUID format, LPWSTR schema, UINT len, WCHAR *name, UINT *ret_len)
static ULONG WINAPI mqw_AddRef(IWICMetadataQueryWriter *iface)
static ULONG WINAPI mqw_Release(IWICMetadataQueryWriter *iface)
const WCHAR * schema
const WCHAR * name
static HRESULT WINAPI mqw_GetEnumerator(IWICMetadataQueryWriter *iface, IEnumString **enum_string)
static const WCHAR * map_shortname_to_schema(const GUID *format, const WCHAR *name)
static HRESULT WINAPI mqw_RemoveMetadataByName(IWICMetadataQueryWriter *iface, LPCWSTR name)
static HRESULT WINAPI mqw_SetMetadataByName(IWICMetadataQueryWriter *iface, LPCWSTR name, const PROPVARIANT *value)
HRESULT MetadataQueryReader_CreateInstance(IWICMetadataBlockReader *mbr, const WCHAR *root, IWICMetadataQueryReader **out)
const GUID * guid
HRESULT WINAPI WICMapShortNameToGuid(PCWSTR name, GUID *guid)
static HRESULT get_next_reader(IWICMetadataReader *reader, UINT index, GUID *guid, IWICMetadataReader **new_reader)
static HRESULT WINAPI mqw_GetMetadataByName(IWICMetadataQueryWriter *iface, LPCWSTR name, PROPVARIANT *value)
static HRESULT WINAPI mqr_GetEnumerator(IWICMetadataQueryReader *iface, IEnumString **enum_string)
static const IWICMetadataQueryWriterVtbl mqw_vtbl
static const IEnumStringVtbl string_enumerator_vtbl
static HRESULT WINAPI mqw_GetLocation(IWICMetadataQueryWriter *iface, UINT max_length, WCHAR *namespace, UINT *actual_length)
static HRESULT WINAPI string_enumerator_Skip(IEnumString *iface, ULONG count)
static HRESULT find_reader_from_block(IWICMetadataBlockReader *block_reader, UINT index, GUID *guid, IWICMetadataReader **reader)
static const struct @626 guid2name[]
static ULONG WINAPI string_enumerator_Release(IEnumString *iface)
static HRESULT WINAPI string_enumerator_Next(IEnumString *iface, ULONG count, LPOLESTR *strings, ULONG *ret)
static const struct @627 name2schema[]
static HRESULT WINAPI mqr_GetMetadataByName(IWICMetadataQueryReader *iface, LPCWSTR query, PROPVARIANT *value)
static HRESULT WINAPI mqr_QueryInterface(IWICMetadataQueryReader *iface, REFIID riid, void **ppvObject)
Definition: metadataquery.c:49
static IWICMetadataQueryReaderVtbl mqr_vtbl
static HRESULT WINAPI mqw_QueryInterface(IWICMetadataQueryWriter *iface, REFIID riid, void **object)
static HRESULT WINAPI string_enumerator_Reset(IEnumString *iface)
static HRESULT WINAPI mqr_GetContainerFormat(IWICMetadataQueryReader *iface, GUID *format)
Definition: metadataquery.c:93
VARTYPE vt
int len
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static JOBOBJECTINFOCLASS LPVOID DWORD LPDWORD ret_len
Definition: process.c:79
static size_t elem
Definition: string.c:69
static LPOLESTR
Definition: stg_prop.c:27
#define min(a, b)
Definition: monoChain.cc:55
unsigned int UINT
Definition: ndis.h:50
#define LOCALE_SYSTEM_DEFAULT
#define L(x)
Definition: ntvdm.h:50
void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
Definition: oleaut.c:271
BSTR WINAPI SysAllocStringLen(const OLECHAR *str, unsigned int len)
Definition: oleaut.c:339
const GUID IID_IEnumString
long LONG
Definition: pedump.c:60
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define REFIID
Definition: guiddef.h:118
#define calloc
Definition: rosglue.h:14
#define wine_dbgstr_wn
Definition: testlist.c:2
RPC_STATUS WINAPI UuidFromStringW(RPC_WSTR s, UUID *uuid)
Definition: rpcrt4_main.c:614
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
_Check_return_ _CRTIMP wchar_t *__cdecl wcsdup(_In_z_ const wchar_t *_Str)
static __inline const char * wine_dbgstr_guid(const GUID *id)
Definition: debug.h:197
HRESULT hr
Definition: shlfolder.c:183
#define TRACE(s)
Definition: solgame.cpp:4
IWICMetadataQueryReader IWICMetadataQueryReader_iface
Definition: metadataquery.c:38
IWICMetadataBlockReader * block
Definition: metadataquery.c:40
WCHAR * root
Definition: metadataquery.c:41
WCHAR * root
IWICMetadataQueryWriter IWICMetadataQueryWriter_iface
IWICMetadataBlockWriter * block
Definition: scsiwmi.h:51
Definition: format.c:58
Definition: name.c:39
Definition: reader.h:84
Definition: send.c:48
IEnumString IEnumString_iface
const WCHAR * str
BSTR bstrVal
Definition: compat.h:2399
VARTYPE vt
Definition: compat.h:2381
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
Definition: pdh_main.c:96
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383
int ret
_In_ void _In_ PCCERT_CONTEXT _In_opt_ LPFILETIME _In_ DWORD _In_ DWORD _Outptr_opt_ void ** ppvObject
Definition: wincrypt.h:6082
#define WINAPI
Definition: msvc.h:6
#define S_FALSE
Definition: winerror.h:2357
#define WINCODEC_ERR_WRONGSTATE
Definition: winerror.h:3281
#define E_NOINTERFACE
Definition: winerror.h:2364
#define WINCODEC_ERR_UNEXPECTEDMETADATATYPE
Definition: winerror.h:3316
#define WINCODEC_ERR_INVALIDQUERYREQUEST
Definition: winerror.h:3315
#define WINCODEC_ERR_PROPERTYNOTSUPPORTED
Definition: winerror.h:3288
#define HRESULT_FROM_WIN32(x)
Definition: winerror.h:92
#define DISP_E_TYPEMISMATCH
Definition: winerror.h:2514
#define WINCODEC_ERR_INSUFFICIENTBUFFER
Definition: winerror.h:3311
#define WINCODEC_ERR_PROPERTYNOTFOUND
Definition: winerror.h:3287
#define NORM_IGNORECASE
Definition: winnls.h:178
#define CSTR_EQUAL
Definition: winnls.h:458
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185