2 * Copyright 2016 Andrew Eikum for CodeWeavers
3 * Copyright 2017 Dmitry Timoshkov
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define NONAMELESSUNION
29 #include "propvarutil.h"
31 #include "wincodecs_private.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs
);
37 static const WCHAR
*map_shortname_to_schema(const GUID
*format
, const WCHAR
*name
);
40 IWICMetadataQueryReader IWICMetadataQueryReader_iface
;
42 IWICMetadataBlockReader
*block
;
46 static inline QueryReader
*impl_from_IWICMetadataQueryReader(IWICMetadataQueryReader
*iface
)
48 return CONTAINING_RECORD(iface
, QueryReader
, IWICMetadataQueryReader_iface
);
51 static HRESULT WINAPI
mqr_QueryInterface(IWICMetadataQueryReader
*iface
, REFIID riid
,
54 QueryReader
*This
= impl_from_IWICMetadataQueryReader(iface
);
56 TRACE("(%p,%s,%p)\n", This
, debugstr_guid(riid
), ppvObject
);
58 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
59 IsEqualGUID(riid
, &IID_IWICMetadataQueryReader
))
60 *ppvObject
= &This
->IWICMetadataQueryReader_iface
;
66 IUnknown_AddRef((IUnknown
*)*ppvObject
);
73 static ULONG WINAPI
mqr_AddRef(IWICMetadataQueryReader
*iface
)
75 QueryReader
*This
= impl_from_IWICMetadataQueryReader(iface
);
76 ULONG ref
= InterlockedIncrement(&This
->ref
);
77 TRACE("(%p) refcount=%lu\n", This
, ref
);
81 static ULONG WINAPI
mqr_Release(IWICMetadataQueryReader
*iface
)
83 QueryReader
*This
= impl_from_IWICMetadataQueryReader(iface
);
84 ULONG ref
= InterlockedDecrement(&This
->ref
);
85 TRACE("(%p) refcount=%lu\n", This
, ref
);
88 IWICMetadataBlockReader_Release(This
->block
);
89 HeapFree(GetProcessHeap(), 0, This
->root
);
90 HeapFree(GetProcessHeap(), 0, This
);
95 static HRESULT WINAPI
mqr_GetContainerFormat(IWICMetadataQueryReader
*iface
, GUID
*format
)
97 QueryReader
*This
= impl_from_IWICMetadataQueryReader(iface
);
99 TRACE("(%p,%p)\n", This
, format
);
101 return IWICMetadataBlockReader_GetContainerFormat(This
->block
, format
);
104 static HRESULT WINAPI
mqr_GetLocation(IWICMetadataQueryReader
*iface
, UINT len
, WCHAR
*location
, UINT
*ret_len
)
106 QueryReader
*This
= impl_from_IWICMetadataQueryReader(iface
);
110 TRACE("(%p,%u,%p,%p)\n", This
, len
, location
, ret_len
);
112 if (!ret_len
) return E_INVALIDARG
;
114 root
= This
->root
? This
->root
: L
"/";
115 actual_len
= lstrlenW(root
) + 1;
119 if (len
< actual_len
)
120 return WINCODEC_ERR_INSUFFICIENTBUFFER
;
122 memcpy(location
, root
, actual_len
* sizeof(WCHAR
));
125 *ret_len
= actual_len
;
143 { 4, {'c','h','a','r'}, VT_I1
},
144 { 5, {'u','c','h','a','r'}, VT_UI1
},
145 { 5, {'s','h','o','r','t'}, VT_I2
},
146 { 6, {'u','s','h','o','r','t'}, VT_UI2
},
147 { 4, {'l','o','n','g'}, VT_I4
},
148 { 5, {'u','l','o','n','g'}, VT_UI4
},
149 { 3, {'i','n','t'}, VT_I4
},
150 { 4, {'u','i','n','t'}, VT_UI4
},
151 { 8, {'l','o','n','g','l','o','n','g'}, VT_I8
},
152 { 9, {'u','l','o','n','g','l','o','n','g'}, VT_UI8
},
153 { 5, {'f','l','o','a','t'}, VT_R4
},
154 { 6, {'d','o','u','b','l','e'}, VT_R8
},
155 { 3, {'s','t','r'}, VT_LPSTR
},
156 { 4, {'w','s','t','r'}, VT_LPWSTR
},
157 { 4, {'g','u','i','d'}, VT_CLSID
},
158 { 4, {'b','o','o','l'}, VT_BOOL
}
161 static VARTYPE
map_type(struct string_t
*str
)
165 for (i
= 0; i
< ARRAY_SIZE(str2vt
); i
++)
167 if (str2vt
[i
].len
== str
->len
)
169 if (CompareStringW(LOCALE_SYSTEM_DEFAULT
, NORM_IGNORECASE
,
170 str
->str
, str
->len
, str2vt
[i
].str
, str2vt
[i
].len
) == CSTR_EQUAL
)
175 WARN("type %s is not recognized\n", wine_dbgstr_wn(str
->str
, str
->len
));
180 static HRESULT
get_token(struct string_t
*elem
, PROPVARIANT
*id
, PROPVARIANT
*schema
, int *idx
)
182 const WCHAR
*start
, *end
, *p
;
184 struct string_t next_elem
;
187 TRACE("%s, len %d\n", wine_dbgstr_wn(elem
->str
, elem
->len
), elem
->len
);
190 PropVariantInit(schema
);
192 if (!elem
->len
) return S_OK
;
200 if (start
[1] < '0' || start
[1] > '9') return DISP_E_TYPEMISMATCH
;
202 *idx
= wcstol(start
+ 1, &idx_end
, 10);
203 if (idx_end
> elem
->str
+ elem
->len
) return WINCODEC_ERR_INVALIDQUERYREQUEST
;
204 if (*idx_end
!= ']') return WINCODEC_ERR_INVALIDQUERYREQUEST
;
205 if (*idx
< 0) return WINCODEC_ERR_INVALIDQUERYREQUEST
;
209 next_elem
.len
= elem
->len
- (end
- start
);
210 hr
= get_token(&next_elem
, id
, schema
, idx
);
213 TRACE("get_token error %#lx\n", hr
);
216 elem
->len
= (end
- start
) + next_elem
.len
;
218 TRACE("indexed %s [%d]\n", wine_dbgstr_wn(elem
->str
, elem
->len
), *idx
);
221 else if (*start
== '{')
224 PROPVARIANT next_token
;
226 end
= wmemchr(start
+ 1, '=', elem
->len
- 1);
227 if (!end
) return WINCODEC_ERR_INVALIDQUERYREQUEST
;
228 if (end
> elem
->str
+ elem
->len
) return WINCODEC_ERR_INVALIDQUERYREQUEST
;
230 next_elem
.str
= start
+ 1;
231 next_elem
.len
= end
- start
- 1;
232 vt
= map_type(&next_elem
);
233 TRACE("type %s => %d\n", wine_dbgstr_wn(next_elem
.str
, next_elem
.len
), vt
);
234 if (vt
== VT_ILLEGAL
) return WINCODEC_ERR_WRONGSTATE
;
236 next_token
.vt
= VT_BSTR
;
237 next_token
.bstrVal
= SysAllocStringLen(NULL
, elem
->len
- (end
- start
) + 1);
238 if (!next_token
.bstrVal
) return E_OUTOFMEMORY
;
240 bstr
= next_token
.bstrVal
;
243 while (*end
&& *end
!= '}' && end
- start
< elem
->len
)
245 if (*end
== '\\') end
++;
250 PropVariantClear(&next_token
);
251 return WINCODEC_ERR_INVALIDQUERYREQUEST
;
254 TRACE("schema/id %s\n", wine_dbgstr_w(next_token
.bstrVal
));
259 id
->puuid
= CoTaskMemAlloc(sizeof(GUID
));
262 PropVariantClear(&next_token
);
263 return E_OUTOFMEMORY
;
266 hr
= UuidFromStringW(next_token
.bstrVal
, id
->puuid
);
269 hr
= PropVariantChangeType(id
, &next_token
, 0, vt
);
270 PropVariantClear(&next_token
);
273 PropVariantClear(id
);
274 PropVariantClear(schema
);
281 PROPVARIANT next_id
, next_schema
;
284 next_elem
.str
= end
+ 1;
285 next_elem
.len
= elem
->len
- (end
- start
+ 1);
286 hr
= get_token(&next_elem
, &next_id
, &next_schema
, &next_idx
);
289 TRACE("get_token error %#lx\n", hr
);
292 elem
->len
= (end
- start
+ 1) + next_elem
.len
;
294 TRACE("id %s [%d]\n", wine_dbgstr_wn(elem
->str
, elem
->len
), *idx
);
296 if (next_schema
.vt
!= VT_EMPTY
)
298 PropVariantClear(&next_id
);
299 PropVariantClear(&next_schema
);
300 return WINCODEC_ERR_WRONGSTATE
;
309 elem
->len
= end
- start
;
313 end
= wmemchr(start
, '/', elem
->len
);
314 if (!end
) end
= start
+ elem
->len
;
316 p
= wmemchr(start
, ':', end
- start
);
319 next_elem
.str
= p
+ 1;
320 next_elem
.len
= end
- p
- 1;
322 elem
->len
= p
- start
;
325 elem
->len
= end
- start
;
328 id
->bstrVal
= SysAllocStringLen(NULL
, elem
->len
+ 1);
329 if (!id
->bstrVal
) return E_OUTOFMEMORY
;
333 while (p
- elem
->str
< elem
->len
)
339 TRACE("%s [%d]\n", wine_dbgstr_variant((VARIANT
*)id
), *idx
);
343 PROPVARIANT next_id
, next_schema
;
346 hr
= get_token(&next_elem
, &next_id
, &next_schema
, &next_idx
);
349 TRACE("get_token error %#lx\n", hr
);
350 PropVariantClear(id
);
351 PropVariantClear(schema
);
354 elem
->len
+= next_elem
.len
+ 1;
356 TRACE("id %s [%d]\n", wine_dbgstr_wn(elem
->str
, elem
->len
), *idx
);
358 if (next_schema
.vt
!= VT_EMPTY
)
360 PropVariantClear(&next_id
);
361 PropVariantClear(&next_schema
);
362 PropVariantClear(id
);
363 PropVariantClear(schema
);
364 return WINCODEC_ERR_WRONGSTATE
;
374 static HRESULT
find_reader_from_block(IWICMetadataBlockReader
*block_reader
, UINT index
,
375 GUID
*guid
, IWICMetadataReader
**reader
)
379 IWICMetadataReader
*new_reader
;
380 UINT count
, i
, matched_index
;
384 hr
= IWICMetadataBlockReader_GetCount(block_reader
, &count
);
385 if (hr
!= S_OK
) return hr
;
389 for (i
= 0; i
< count
; i
++)
391 hr
= IWICMetadataBlockReader_GetReaderByIndex(block_reader
, i
, &new_reader
);
392 if (hr
!= S_OK
) return hr
;
394 hr
= IWICMetadataReader_GetMetadataFormat(new_reader
, &format
);
397 if (IsEqualGUID(&format
, guid
))
399 if (matched_index
== index
)
401 *reader
= new_reader
;
409 IWICMetadataReader_Release(new_reader
);
410 if (hr
!= S_OK
) return hr
;
413 return WINCODEC_ERR_PROPERTYNOTFOUND
;
416 static HRESULT
get_next_reader(IWICMetadataReader
*reader
, UINT index
,
417 GUID
*guid
, IWICMetadataReader
**new_reader
)
420 PROPVARIANT schema
, id
, value
;
424 PropVariantInit(&schema
);
425 PropVariantInit(&id
);
426 PropVariantInit(&value
);
431 schema
.uiVal
= index
;
436 hr
= IWICMetadataReader_GetValue(reader
, &schema
, &id
, &value
);
437 if (hr
!= S_OK
) return hr
;
439 if (value
.vt
== VT_UNKNOWN
)
440 hr
= IUnknown_QueryInterface(value
.punkVal
, &IID_IWICMetadataReader
, (void **)new_reader
);
442 hr
= WINCODEC_ERR_UNEXPECTEDMETADATATYPE
;
444 PropVariantClear(&value
);
448 static HRESULT WINAPI
mqr_GetMetadataByName(IWICMetadataQueryReader
*iface
, LPCWSTR query
, PROPVARIANT
*value
)
450 QueryReader
*This
= impl_from_IWICMetadataQueryReader(iface
);
451 struct string_t elem
;
455 PROPVARIANT tk_id
, tk_schema
, new_value
;
457 IWICMetadataReader
*reader
;
460 TRACE("(%p,%s,%p)\n", This
, wine_dbgstr_w(query
), value
);
462 len
= lstrlenW(query
) + 1;
463 if (This
->root
) len
+= lstrlenW(This
->root
);
464 full_query
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
467 lstrcpyW(full_query
, This
->root
);
468 lstrcatW(full_query
, query
);
470 PropVariantInit(&tk_id
);
471 PropVariantInit(&tk_schema
);
472 PropVariantInit(&new_value
);
481 WARN("query should start with '/'\n");
482 hr
= WINCODEC_ERR_PROPERTYNOTSUPPORTED
;
490 elem
.len
= lstrlenW(p
);
491 hr
= get_token(&elem
, &tk_id
, &tk_schema
, &index
);
494 WARN("get_token error %#lx\n", hr
);
497 TRACE("parsed %d characters: %s, index %d\n", elem
.len
, wine_dbgstr_wn(elem
.str
, elem
.len
), index
);
498 TRACE("id %s, schema %s\n", wine_dbgstr_variant((VARIANT
*)&tk_id
), wine_dbgstr_variant((VARIANT
*)&tk_schema
));
500 if (!elem
.len
) break;
502 if (tk_id
.vt
== VT_CLSID
|| (tk_id
.vt
== VT_BSTR
&& WICMapShortNameToGuid(tk_id
.bstrVal
, &guid
) == S_OK
))
506 if (tk_schema
.vt
!= VT_EMPTY
)
508 FIXME("unsupported schema vt %u\n", tk_schema
.vt
);
509 PropVariantClear(&tk_schema
);
512 if (tk_id
.vt
== VT_CLSID
) guid
= *tk_id
.puuid
;
516 IWICMetadataReader
*new_reader
;
518 hr
= get_next_reader(reader
, index
, &guid
, &new_reader
);
519 IWICMetadataReader_Release(reader
);
523 hr
= find_reader_from_block(This
->block
, index
, &guid
, &reader
);
525 if (hr
!= S_OK
) break;
527 root
= SysAllocStringLen(NULL
, elem
.str
+ elem
.len
- full_query
+ 2);
533 lstrcpynW(root
, full_query
, p
- full_query
+ elem
.len
+ 1);
535 PropVariantClear(&new_value
);
536 new_value
.vt
= VT_UNKNOWN
;
537 hr
= MetadataQueryReader_CreateInstance(This
->block
, root
, (IWICMetadataQueryReader
**)&new_value
.punkVal
);
539 if (hr
!= S_OK
) break;
543 PROPVARIANT schema
, id
;
547 hr
= WINCODEC_ERR_INVALIDQUERYREQUEST
;
551 if (tk_schema
.vt
== VT_BSTR
)
553 hr
= IWICMetadataReader_GetMetadataFormat(reader
, &guid
);
554 if (hr
!= S_OK
) break;
556 schema
.vt
= VT_LPWSTR
;
557 schema
.pwszVal
= (LPWSTR
)map_shortname_to_schema(&guid
, tk_schema
.bstrVal
);
559 schema
.pwszVal
= tk_schema
.bstrVal
;
564 if (tk_id
.vt
== VT_BSTR
)
567 id
.pwszVal
= tk_id
.bstrVal
;
572 PropVariantClear(&new_value
);
573 hr
= IWICMetadataReader_GetValue(reader
, &schema
, &id
, &new_value
);
574 if (hr
!= S_OK
) break;
579 PropVariantClear(&tk_id
);
580 PropVariantClear(&tk_schema
);
584 IWICMetadataReader_Release(reader
);
586 PropVariantClear(&tk_id
);
587 PropVariantClear(&tk_schema
);
589 if (hr
== S_OK
&& value
)
592 PropVariantClear(&new_value
);
594 HeapFree(GetProcessHeap(), 0, full_query
);
599 struct string_enumerator
601 IEnumString IEnumString_iface
;
605 static struct string_enumerator
*impl_from_IEnumString(IEnumString
*iface
)
607 return CONTAINING_RECORD(iface
, struct string_enumerator
, IEnumString_iface
);
610 static HRESULT WINAPI
string_enumerator_QueryInterface(IEnumString
*iface
, REFIID riid
, void **ppv
)
612 struct string_enumerator
*this = impl_from_IEnumString(iface
);
614 TRACE("iface %p, riid %s, ppv %p.\n", iface
, debugstr_guid(riid
), ppv
);
616 if (IsEqualGUID(riid
, &IID_IEnumString
) || IsEqualGUID(riid
, &IID_IUnknown
))
617 *ppv
= &this->IEnumString_iface
;
620 WARN("Unknown riid %s.\n", debugstr_guid(riid
));
622 return E_NOINTERFACE
;
625 IUnknown_AddRef(&this->IEnumString_iface
);
629 static ULONG WINAPI
string_enumerator_AddRef(IEnumString
*iface
)
631 struct string_enumerator
*this = impl_from_IEnumString(iface
);
632 ULONG ref
= InterlockedIncrement(&this->ref
);
634 TRACE("iface %p, ref %lu.\n", iface
, ref
);
639 static ULONG WINAPI
string_enumerator_Release(IEnumString
*iface
)
641 struct string_enumerator
*this = impl_from_IEnumString(iface
);
642 ULONG ref
= InterlockedDecrement(&this->ref
);
644 TRACE("iface %p, ref %lu.\n", iface
, ref
);
652 static HRESULT WINAPI
string_enumerator_Next(IEnumString
*iface
, ULONG count
, LPOLESTR
*strings
, ULONG
*ret
)
654 FIXME("iface %p, count %lu, strings %p, ret %p stub.\n", iface
, count
, strings
, ret
);
656 if (!strings
|| !ret
)
660 return count
? S_FALSE
: S_OK
;
663 static HRESULT WINAPI
string_enumerator_Reset(IEnumString
*iface
)
665 TRACE("iface %p.\n", iface
);
670 static HRESULT WINAPI
string_enumerator_Skip(IEnumString
*iface
, ULONG count
)
672 FIXME("iface %p, count %lu stub.\n", iface
, count
);
674 return count
? S_FALSE
: S_OK
;
677 static HRESULT WINAPI
string_enumerator_Clone(IEnumString
*iface
, IEnumString
**out
)
679 FIXME("iface %p, out %p stub.\n", iface
, out
);
685 static const IEnumStringVtbl string_enumerator_vtbl
=
687 string_enumerator_QueryInterface
,
688 string_enumerator_AddRef
,
689 string_enumerator_Release
,
690 string_enumerator_Next
,
691 string_enumerator_Skip
,
692 string_enumerator_Reset
,
693 string_enumerator_Clone
696 static HRESULT
string_enumerator_create(IEnumString
**enum_string
)
698 struct string_enumerator
*object
;
700 if (!(object
= calloc(1, sizeof(*object
))))
701 return E_OUTOFMEMORY
;
703 object
->IEnumString_iface
.lpVtbl
= &string_enumerator_vtbl
;
706 *enum_string
= &object
->IEnumString_iface
;
711 static HRESULT WINAPI
mqr_GetEnumerator(IWICMetadataQueryReader
*iface
,
712 IEnumString
**enum_string
)
714 TRACE("iface %p, enum_string %p.\n", iface
, enum_string
);
716 return string_enumerator_create(enum_string
);
719 static IWICMetadataQueryReaderVtbl mqr_vtbl
= {
723 mqr_GetContainerFormat
,
725 mqr_GetMetadataByName
,
729 HRESULT
MetadataQueryReader_CreateInstance(IWICMetadataBlockReader
*mbr
, const WCHAR
*root
, IWICMetadataQueryReader
**out
)
733 obj
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*obj
));
735 return E_OUTOFMEMORY
;
737 obj
->IWICMetadataQueryReader_iface
.lpVtbl
= &mqr_vtbl
;
740 IWICMetadataBlockReader_AddRef(mbr
);
743 obj
->root
= root
? heap_strdupW(root
) : NULL
;
745 *out
= &obj
->IWICMetadataQueryReader_iface
;
752 IWICMetadataQueryWriter IWICMetadataQueryWriter_iface
;
754 IWICMetadataBlockWriter
*block
;
759 static inline QueryWriter
*impl_from_IWICMetadataQueryWriter(IWICMetadataQueryWriter
*iface
)
761 return CONTAINING_RECORD(iface
, QueryWriter
, IWICMetadataQueryWriter_iface
);
764 static HRESULT WINAPI
mqw_QueryInterface(IWICMetadataQueryWriter
*iface
, REFIID riid
,
767 QueryWriter
*writer
= impl_from_IWICMetadataQueryWriter(iface
);
769 TRACE("writer %p, riid %s, object %p.\n", writer
, debugstr_guid(riid
), object
);
771 if (IsEqualGUID(riid
, &IID_IUnknown
)
772 || IsEqualGUID(riid
, &IID_IWICMetadataQueryWriter
)
773 || IsEqualGUID(riid
, &IID_IWICMetadataQueryReader
))
774 *object
= &writer
->IWICMetadataQueryWriter_iface
;
780 IUnknown_AddRef((IUnknown
*)*object
);
784 return E_NOINTERFACE
;
787 static ULONG WINAPI
mqw_AddRef(IWICMetadataQueryWriter
*iface
)
789 QueryWriter
*writer
= impl_from_IWICMetadataQueryWriter(iface
);
790 ULONG ref
= InterlockedIncrement(&writer
->ref
);
792 TRACE("writer %p, refcount=%lu\n", writer
, ref
);
797 static ULONG WINAPI
mqw_Release(IWICMetadataQueryWriter
*iface
)
799 QueryWriter
*writer
= impl_from_IWICMetadataQueryWriter(iface
);
800 ULONG ref
= InterlockedDecrement(&writer
->ref
);
802 TRACE("writer %p, refcount=%lu.\n", writer
, ref
);
806 IWICMetadataBlockWriter_Release(writer
->block
);
807 HeapFree(GetProcessHeap(), 0, writer
->root
);
808 HeapFree(GetProcessHeap(), 0, writer
);
813 static HRESULT WINAPI
mqw_GetContainerFormat(IWICMetadataQueryWriter
*iface
, GUID
*container_format
)
815 FIXME("iface %p, container_format %p stub.\n", iface
, container_format
);
820 static HRESULT WINAPI
mqw_GetEnumerator(IWICMetadataQueryWriter
*iface
, IEnumString
**enum_string
)
822 TRACE("iface %p, enum_string %p.\n", iface
, enum_string
);
824 return string_enumerator_create(enum_string
);
827 static HRESULT WINAPI
mqw_GetLocation(IWICMetadataQueryWriter
*iface
, UINT max_length
, WCHAR
*namespace, UINT
*actual_length
)
829 FIXME("iface %p, max_length %u, namespace %s, actual_length %p stub.\n",
830 iface
, max_length
, debugstr_w(namespace), actual_length
);
835 static HRESULT WINAPI
mqw_GetMetadataByName(IWICMetadataQueryWriter
*iface
, LPCWSTR name
, PROPVARIANT
*value
)
837 FIXME("name %s, value %p stub.\n", debugstr_w(name
), value
);
842 static HRESULT WINAPI
mqw_SetMetadataByName(IWICMetadataQueryWriter
*iface
, LPCWSTR name
, const PROPVARIANT
*value
)
844 FIXME("iface %p, name %s, value %p stub.\n", iface
, debugstr_w(name
), value
);
849 static HRESULT WINAPI
mqw_RemoveMetadataByName(IWICMetadataQueryWriter
*iface
, LPCWSTR name
)
851 FIXME("iface %p, name %s stub.\n", iface
, debugstr_w(name
));
856 static const IWICMetadataQueryWriterVtbl mqw_vtbl
=
861 mqw_GetContainerFormat
,
863 mqw_GetMetadataByName
,
865 mqw_SetMetadataByName
,
866 mqw_RemoveMetadataByName
,
869 HRESULT
MetadataQueryWriter_CreateInstance(IWICMetadataBlockWriter
*mbw
, const WCHAR
*root
, IWICMetadataQueryWriter
**out
)
873 obj
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*obj
));
875 return E_OUTOFMEMORY
;
877 obj
->IWICMetadataQueryWriter_iface
.lpVtbl
= &mqw_vtbl
;
880 IWICMetadataBlockWriter_AddRef(mbw
);
883 obj
->root
= root
? heap_strdupW(root
) : NULL
;
885 *out
= &obj
->IWICMetadataQueryWriter_iface
;
896 { &GUID_ContainerFormatBmp
, L
"bmp" },
897 { &GUID_ContainerFormatPng
, L
"png" },
898 { &GUID_ContainerFormatIco
, L
"ico" },
899 { &GUID_ContainerFormatJpeg
, L
"jpg" },
900 { &GUID_ContainerFormatTiff
, L
"tiff" },
901 { &GUID_ContainerFormatGif
, L
"gif" },
902 { &GUID_ContainerFormatWmp
, L
"wmphoto" },
903 { &GUID_MetadataFormatUnknown
, L
"unknown" },
904 { &GUID_MetadataFormatIfd
, L
"ifd" },
905 { &GUID_MetadataFormatSubIfd
, L
"sub" },
906 { &GUID_MetadataFormatExif
, L
"exif" },
907 { &GUID_MetadataFormatGps
, L
"gps" },
908 { &GUID_MetadataFormatInterop
, L
"interop" },
909 { &GUID_MetadataFormatApp0
, L
"app0" },
910 { &GUID_MetadataFormatApp1
, L
"app1" },
911 { &GUID_MetadataFormatApp13
, L
"app13" },
912 { &GUID_MetadataFormatIPTC
, L
"iptc" },
913 { &GUID_MetadataFormatIRB
, L
"irb" },
914 { &GUID_MetadataFormat8BIMIPTC
, L
"8bimiptc" },
915 { &GUID_MetadataFormat8BIMResolutionInfo
, L
"8bimResInfo" },
916 { &GUID_MetadataFormat8BIMIPTCDigest
, L
"8bimiptcdigest" },
917 { &GUID_MetadataFormatXMP
, L
"xmp" },
918 { &GUID_MetadataFormatThumbnail
, L
"thumb" },
919 { &GUID_MetadataFormatChunktEXt
, L
"tEXt" },
920 { &GUID_MetadataFormatXMPStruct
, L
"xmpstruct" },
921 { &GUID_MetadataFormatXMPBag
, L
"xmpbag" },
922 { &GUID_MetadataFormatXMPSeq
, L
"xmpseq" },
923 { &GUID_MetadataFormatXMPAlt
, L
"xmpalt" },
924 { &GUID_MetadataFormatLSD
, L
"logscrdesc" },
925 { &GUID_MetadataFormatIMD
, L
"imgdesc" },
926 { &GUID_MetadataFormatGCE
, L
"grctlext" },
927 { &GUID_MetadataFormatAPE
, L
"appext" },
928 { &GUID_MetadataFormatJpegChrominance
, L
"chrominance" },
929 { &GUID_MetadataFormatJpegLuminance
, L
"luminance" },
930 { &GUID_MetadataFormatJpegComment
, L
"com" },
931 { &GUID_MetadataFormatGifComment
, L
"commentext" },
932 { &GUID_MetadataFormatChunkgAMA
, L
"gAMA" },
933 { &GUID_MetadataFormatChunkbKGD
, L
"bKGD" },
934 { &GUID_MetadataFormatChunkiTXt
, L
"iTXt" },
935 { &GUID_MetadataFormatChunkcHRM
, L
"cHRM" },
936 { &GUID_MetadataFormatChunkhIST
, L
"hIST" },
937 { &GUID_MetadataFormatChunkiCCP
, L
"iCCP" },
938 { &GUID_MetadataFormatChunksRGB
, L
"sRGB" },
939 { &GUID_MetadataFormatChunktIME
, L
"tIME" }
942 HRESULT WINAPI
WICMapGuidToShortName(REFGUID guid
, UINT len
, WCHAR
*name
, UINT
*ret_len
)
946 TRACE("%s,%u,%p,%p\n", wine_dbgstr_guid(guid
), len
, name
, ret_len
);
948 if (!guid
) return E_INVALIDARG
;
950 for (i
= 0; i
< ARRAY_SIZE(guid2name
); i
++)
952 if (IsEqualGUID(guid
, guid2name
[i
].guid
))
956 if (!len
) return E_INVALIDARG
;
958 len
= min(len
- 1, lstrlenW(guid2name
[i
].name
));
959 memcpy(name
, guid2name
[i
].name
, len
* sizeof(WCHAR
));
962 if (len
< lstrlenW(guid2name
[i
].name
))
963 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
);
965 if (ret_len
) *ret_len
= lstrlenW(guid2name
[i
].name
) + 1;
970 return WINCODEC_ERR_PROPERTYNOTFOUND
;
973 HRESULT WINAPI
WICMapShortNameToGuid(PCWSTR name
, GUID
*guid
)
977 TRACE("%s,%p\n", debugstr_w(name
), guid
);
979 if (!name
|| !guid
) return E_INVALIDARG
;
981 for (i
= 0; i
< ARRAY_SIZE(guid2name
); i
++)
983 if (!lstrcmpiW(name
, guid2name
[i
].name
))
985 *guid
= *guid2name
[i
].guid
;
990 return WINCODEC_ERR_PROPERTYNOTFOUND
;
999 { L
"rdf", L
"http://www.w3.org/1999/02/22-rdf-syntax-ns#" },
1000 { L
"dc", L
"http://purl.org/dc/elements/1.1/" },
1001 { L
"xmp", L
"http://ns.adobe.com/xap/1.0/" },
1002 { L
"xmpidq", L
"http://ns.adobe.com/xmp/Identifier/qual/1.0/" },
1003 { L
"xmpRights", L
"http://ns.adobe.com/xap/1.0/rights/" },
1004 { L
"xmpMM", L
"http://ns.adobe.com/xap/1.0/mm/" },
1005 { L
"xmpBJ", L
"http://ns.adobe.com/xap/1.0/bj/" },
1006 { L
"xmpTPg", L
"http://ns.adobe.com/xap/1.0/t/pg/" },
1007 { L
"pdf", L
"http://ns.adobe.com/pdf/1.3/" },
1008 { L
"photoshop", L
"http://ns.adobe.com/photoshop/1.0/" },
1009 { L
"tiff", L
"http://ns.adobe.com/tiff/1.0/" },
1010 { L
"exif", L
"http://ns.adobe.com/exif/1.0/" },
1011 { L
"stDim", L
"http://ns.adobe.com/xap/1.0/sType/Dimensions#" },
1012 { L
"xapGImg", L
"http://ns.adobe.com/xap/1.0/g/img/" },
1013 { L
"stEvt", L
"http://ns.adobe.com/xap/1.0/sType/ResourceEvent#" },
1014 { L
"stRef", L
"http://ns.adobe.com/xap/1.0/sType/ResourceRef#" },
1015 { L
"stVer", L
"http://ns.adobe.com/xap/1.0/sType/Version#" },
1016 { L
"stJob", L
"http://ns.adobe.com/xap/1.0/sType/Job#" },
1017 { L
"aux", L
"http://ns.adobe.com/exif/1.0/aux/" },
1018 { L
"crs", L
"http://ns.adobe.com/camera-raw-settings/1.0/" },
1019 { L
"xmpDM", L
"http://ns.adobe.com/xmp/1.0/DynamicMedia/" },
1020 { L
"Iptc4xmpCore", L
"http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/" },
1021 { L
"MicrosoftPhoto", L
"http://ns.microsoft.com/photo/1.0/" },
1022 { L
"MP", L
"http://ns.microsoft.com/photo/1.2/" },
1023 { L
"MPRI", L
"http://ns.microsoft.com/photo/1.2/t/RegionInfo#" },
1024 { L
"MPReg", L
"http://ns.microsoft.com/photo/1.2/t/Region#" }
1027 static const WCHAR
*map_shortname_to_schema(const GUID
*format
, const WCHAR
*name
)
1031 /* It appears that the only metadata formats
1032 * that support schemas are xmp and xmpstruct.
1034 if (!IsEqualGUID(format
, &GUID_MetadataFormatXMP
) &&
1035 !IsEqualGUID(format
, &GUID_MetadataFormatXMPStruct
))
1038 for (i
= 0; i
< ARRAY_SIZE(name2schema
); i
++)
1040 if (!wcscmp(name2schema
[i
].name
, name
))
1041 return name2schema
[i
].schema
;
1047 HRESULT WINAPI
WICMapSchemaToName(REFGUID format
, LPWSTR schema
, UINT len
, WCHAR
*name
, UINT
*ret_len
)
1051 TRACE("%s,%s,%u,%p,%p\n", wine_dbgstr_guid(format
), debugstr_w(schema
), len
, name
, ret_len
);
1053 if (!format
|| !schema
|| !ret_len
)
1054 return E_INVALIDARG
;
1056 /* It appears that the only metadata formats
1057 * that support schemas are xmp and xmpstruct.
1059 if (!IsEqualGUID(format
, &GUID_MetadataFormatXMP
) &&
1060 !IsEqualGUID(format
, &GUID_MetadataFormatXMPStruct
))
1061 return WINCODEC_ERR_PROPERTYNOTFOUND
;
1063 for (i
= 0; i
< ARRAY_SIZE(name2schema
); i
++)
1065 if (!wcscmp(name2schema
[i
].schema
, schema
))
1069 if (!len
) return E_INVALIDARG
;
1071 len
= min(len
- 1, lstrlenW(name2schema
[i
].name
));
1072 memcpy(name
, name2schema
[i
].name
, len
* sizeof(WCHAR
));
1075 if (len
< lstrlenW(name2schema
[i
].name
))
1076 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
);
1079 *ret_len
= lstrlenW(name2schema
[i
].name
) + 1;
1084 return WINCODEC_ERR_PROPERTYNOTFOUND
;