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
30 #include "wincodecs_private.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs
);
37 IWICMetadataQueryReader IWICMetadataQueryReader_iface
;
41 IWICMetadataBlockReader
*block
;
44 static inline QueryReader
*impl_from_IWICMetadataQueryReader(IWICMetadataQueryReader
*iface
)
46 return CONTAINING_RECORD(iface
, QueryReader
, IWICMetadataQueryReader_iface
);
49 static HRESULT WINAPI
mqr_QueryInterface(IWICMetadataQueryReader
*iface
, REFIID riid
,
52 QueryReader
*This
= impl_from_IWICMetadataQueryReader(iface
);
54 TRACE("(%p,%s,%p)\n", This
, debugstr_guid(riid
), ppvObject
);
56 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
57 IsEqualGUID(riid
, &IID_IWICMetadataQueryReader
))
58 *ppvObject
= &This
->IWICMetadataQueryReader_iface
;
64 IUnknown_AddRef((IUnknown
*)*ppvObject
);
71 static ULONG WINAPI
mqr_AddRef(IWICMetadataQueryReader
*iface
)
73 QueryReader
*This
= impl_from_IWICMetadataQueryReader(iface
);
74 ULONG ref
= InterlockedIncrement(&This
->ref
);
75 TRACE("(%p) refcount=%u\n", This
, ref
);
79 static ULONG WINAPI
mqr_Release(IWICMetadataQueryReader
*iface
)
81 QueryReader
*This
= impl_from_IWICMetadataQueryReader(iface
);
82 ULONG ref
= InterlockedDecrement(&This
->ref
);
83 TRACE("(%p) refcount=%u\n", This
, ref
);
86 IWICMetadataBlockReader_Release(This
->block
);
87 HeapFree(GetProcessHeap(), 0, This
);
92 static HRESULT WINAPI
mqr_GetContainerFormat(IWICMetadataQueryReader
*iface
, GUID
*format
)
94 QueryReader
*This
= impl_from_IWICMetadataQueryReader(iface
);
96 TRACE("(%p,%p)\n", This
, format
);
98 return IWICMetadataBlockReader_GetContainerFormat(This
->block
, format
);
101 static HRESULT WINAPI
mqr_GetLocation(IWICMetadataQueryReader
*iface
,
102 UINT cchMaxLength
, WCHAR
*wzNamespace
, UINT
*pcchActualLength
)
104 QueryReader
*This
= impl_from_IWICMetadataQueryReader(iface
);
105 FIXME("(%p,%u,%p,%p)\n", This
, cchMaxLength
, wzNamespace
, pcchActualLength
);
109 static HRESULT WINAPI
mqr_GetMetadataByName(IWICMetadataQueryReader
*iface
,
110 LPCWSTR wzName
, PROPVARIANT
*pvarValue
)
112 QueryReader
*This
= impl_from_IWICMetadataQueryReader(iface
);
113 FIXME("(%p,%s,%p)\n", This
, wine_dbgstr_w(wzName
), pvarValue
);
117 static HRESULT WINAPI
mqr_GetEnumerator(IWICMetadataQueryReader
*iface
,
118 IEnumString
**ppIEnumString
)
120 QueryReader
*This
= impl_from_IWICMetadataQueryReader(iface
);
121 FIXME("(%p,%p)\n", This
, ppIEnumString
);
125 static IWICMetadataQueryReaderVtbl mqr_vtbl
= {
129 mqr_GetContainerFormat
,
131 mqr_GetMetadataByName
,
135 HRESULT
MetadataQueryReader_CreateInstance(IWICMetadataBlockReader
*mbr
, IWICMetadataQueryReader
**out
)
139 obj
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*obj
));
141 return E_OUTOFMEMORY
;
143 obj
->IWICMetadataQueryReader_iface
.lpVtbl
= &mqr_vtbl
;
146 IWICMetadataBlockReader_AddRef(mbr
);
149 *out
= &obj
->IWICMetadataQueryReader_iface
;
154 static const WCHAR bmpW
[] = { 'b','m','p',0 };
155 static const WCHAR pngW
[] = { 'p','n','g',0 };
156 static const WCHAR icoW
[] = { 'i','c','o',0 };
157 static const WCHAR jpgW
[] = { 'j','p','g',0 };
158 static const WCHAR tiffW
[] = { 't','i','f','f',0 };
159 static const WCHAR gifW
[] = { 'g','i','f',0 };
160 static const WCHAR wmphotoW
[] = { 'w','m','p','h','o','t','o',0 };
161 static const WCHAR unknownW
[] = { 'u','n','k','n','o','w','n',0 };
162 static const WCHAR ifdW
[] = { 'i','f','d',0 };
163 static const WCHAR subW
[] = { 's','u','b',0 };
164 static const WCHAR exifW
[] = { 'e','x','i','f',0 };
165 static const WCHAR gpsW
[] = { 'g','p','s',0 };
166 static const WCHAR interopW
[] = { 'i','n','t','e','r','o','p',0 };
167 static const WCHAR app0W
[] = { 'a','p','p','0',0 };
168 static const WCHAR app1W
[] = { 'a','p','p','1',0 };
169 static const WCHAR app13W
[] = { 'a','p','p','1','3',0 };
170 static const WCHAR iptcW
[] = { 'i','p','t','c',0 };
171 static const WCHAR irbW
[] = { 'i','r','b',0 };
172 static const WCHAR _8bimiptcW
[] = { '8','b','i','m','i','p','t','c',0 };
173 static const WCHAR _8bimResInfoW
[] = { '8','b','i','m','R','e','s','I','n','f','o',0 };
174 static const WCHAR _8bimiptcdigestW
[] = { '8','b','i','m','i','p','t','c','d','i','g','e','s','t',0 };
175 static const WCHAR xmpW
[] = { 'x','m','p',0 };
176 static const WCHAR thumbW
[] = { 't','h','u','m','b',0 };
177 static const WCHAR tEXtW
[] = { 't','E','X','t',0 };
178 static const WCHAR xmpstructW
[] = { 'x','m','p','s','t','r','u','c','t',0 };
179 static const WCHAR xmpbagW
[] = { 'x','m','p','b','a','g',0 };
180 static const WCHAR xmpseqW
[] = { 'x','m','p','s','e','q',0 };
181 static const WCHAR xmpaltW
[] = { 'x','m','p','a','l','t',0 };
182 static const WCHAR logscrdescW
[] = { 'l','o','g','s','c','r','d','e','s','c',0 };
183 static const WCHAR imgdescW
[] = { 'i','m','g','d','e','s','c',0 };
184 static const WCHAR grctlextW
[] = { 'g','r','c','t','l','e','x','t',0 };
185 static const WCHAR appextW
[] = { 'a','p','p','e','x','t',0 };
186 static const WCHAR chrominanceW
[] = { 'c','h','r','o','m','i','n','a','n','c','e',0 };
187 static const WCHAR luminanceW
[] = { 'l','u','m','i','n','a','n','c','e',0 };
188 static const WCHAR comW
[] = { 'c','o','m',0 };
189 static const WCHAR commentextW
[] = { 'c','o','m','m','e','n','t','e','x','t',0 };
190 static const WCHAR gAMAW
[] = { 'g','A','M','A',0 };
191 static const WCHAR bKGDW
[] = { 'b','K','G','D',0 };
192 static const WCHAR iTXtW
[] = { 'i','T','X','t',0 };
193 static const WCHAR cHRMW
[] = { 'c','H','R','M',0 };
194 static const WCHAR hISTW
[] = { 'h','I','S','T',0 };
195 static const WCHAR iCCPW
[] = { 'i','C','C','P',0 };
196 static const WCHAR sRGBW
[] = { 's','R','G','B',0 };
197 static const WCHAR tIMEW
[] = { 't','I','M','E',0 };
205 { &GUID_ContainerFormatBmp
, bmpW
},
206 { &GUID_ContainerFormatPng
, pngW
},
207 { &GUID_ContainerFormatIco
, icoW
},
208 { &GUID_ContainerFormatJpeg
, jpgW
},
209 { &GUID_ContainerFormatTiff
, tiffW
},
210 { &GUID_ContainerFormatGif
, gifW
},
211 { &GUID_ContainerFormatWmp
, wmphotoW
},
212 { &GUID_MetadataFormatUnknown
, unknownW
},
213 { &GUID_MetadataFormatIfd
, ifdW
},
214 { &GUID_MetadataFormatSubIfd
, subW
},
215 { &GUID_MetadataFormatExif
, exifW
},
216 { &GUID_MetadataFormatGps
, gpsW
},
217 { &GUID_MetadataFormatInterop
, interopW
},
218 { &GUID_MetadataFormatApp0
, app0W
},
219 { &GUID_MetadataFormatApp1
, app1W
},
220 { &GUID_MetadataFormatApp13
, app13W
},
221 { &GUID_MetadataFormatIPTC
, iptcW
},
222 { &GUID_MetadataFormatIRB
, irbW
},
223 { &GUID_MetadataFormat8BIMIPTC
, _8bimiptcW
},
224 { &GUID_MetadataFormat8BIMResolutionInfo
, _8bimResInfoW
},
225 { &GUID_MetadataFormat8BIMIPTCDigest
, _8bimiptcdigestW
},
226 { &GUID_MetadataFormatXMP
, xmpW
},
227 { &GUID_MetadataFormatThumbnail
, thumbW
},
228 { &GUID_MetadataFormatChunktEXt
, tEXtW
},
229 { &GUID_MetadataFormatXMPStruct
, xmpstructW
},
230 { &GUID_MetadataFormatXMPBag
, xmpbagW
},
231 { &GUID_MetadataFormatXMPSeq
, xmpseqW
},
232 { &GUID_MetadataFormatXMPAlt
, xmpaltW
},
233 { &GUID_MetadataFormatLSD
, logscrdescW
},
234 { &GUID_MetadataFormatIMD
, imgdescW
},
235 { &GUID_MetadataFormatGCE
, grctlextW
},
236 { &GUID_MetadataFormatAPE
, appextW
},
237 { &GUID_MetadataFormatJpegChrominance
, chrominanceW
},
238 { &GUID_MetadataFormatJpegLuminance
, luminanceW
},
239 { &GUID_MetadataFormatJpegComment
, comW
},
240 { &GUID_MetadataFormatGifComment
, commentextW
},
241 { &GUID_MetadataFormatChunkgAMA
, gAMAW
},
242 { &GUID_MetadataFormatChunkbKGD
, bKGDW
},
243 { &GUID_MetadataFormatChunkiTXt
, iTXtW
},
244 { &GUID_MetadataFormatChunkcHRM
, cHRMW
},
245 { &GUID_MetadataFormatChunkhIST
, hISTW
},
246 { &GUID_MetadataFormatChunkiCCP
, iCCPW
},
247 { &GUID_MetadataFormatChunksRGB
, sRGBW
},
248 { &GUID_MetadataFormatChunktIME
, tIMEW
}
251 HRESULT WINAPI
WICMapGuidToShortName(REFGUID guid
, UINT len
, WCHAR
*name
, UINT
*ret_len
)
255 TRACE("%s,%u,%p,%p\n", wine_dbgstr_guid(guid
), len
, name
, ret_len
);
257 if (!guid
) return E_INVALIDARG
;
259 for (i
= 0; i
< sizeof(guid2name
)/sizeof(guid2name
[0]); i
++)
261 if (IsEqualGUID(guid
, guid2name
[i
].guid
))
265 if (!len
) return E_INVALIDARG
;
267 len
= min(len
- 1, lstrlenW(guid2name
[i
].name
));
268 memcpy(name
, guid2name
[i
].name
, len
* sizeof(WCHAR
));
271 if (len
< lstrlenW(guid2name
[i
].name
))
272 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
);
274 if (ret_len
) *ret_len
= lstrlenW(guid2name
[i
].name
) + 1;
279 return WINCODEC_ERR_PROPERTYNOTFOUND
;
282 HRESULT WINAPI
WICMapShortNameToGuid(PCWSTR name
, GUID
*guid
)
286 TRACE("%s,%p\n", debugstr_w(name
), guid
);
288 if (!name
|| !guid
) return E_INVALIDARG
;
290 for (i
= 0; i
< sizeof(guid2name
)/sizeof(guid2name
[0]); i
++)
292 if (!lstrcmpiW(name
, guid2name
[i
].name
))
294 *guid
= *guid2name
[i
].guid
;
299 return WINCODEC_ERR_PROPERTYNOTFOUND
;
302 static const WCHAR rdf
[] = { 'r','d','f',0 };
303 static const 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 };
304 static const WCHAR dc
[] = { 'd','c',0 };
305 static const 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 };
306 static const WCHAR xmp
[] = { 'x','m','p',0 };
307 static const WCHAR xmp_scheme
[] = { 'h','t','t','p',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','x','a','p','/','1','.','0','/',0 };
308 static const WCHAR xmpidq
[] = { 'x','m','p','i','d','q',0 };
309 static const 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 };
310 static const WCHAR xmpRights
[] = { 'x','m','p','R','i','g','h','t','s',0 };
311 static const 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 };
312 static const WCHAR xmpMM
[] = { 'x','m','p','M','M',0 };
313 static const 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 };
314 static const WCHAR xmpBJ
[] = { 'x','m','p','B','J',0 };
315 static const 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 };
316 static const WCHAR xmpTPg
[] = { 'x','m','p','T','P','g',0 };
317 static const 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 };
318 static const WCHAR pdf
[] = { 'p','d','f',0 };
319 static const WCHAR pdf_scheme
[] = { 'h','t','t','p',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','p','d','f','/','1','.','3','/',0 };
320 static const WCHAR photoshop
[] = { 'p','h','o','t','o','s','h','o','p',0 };
321 static const 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 };
322 static const WCHAR tiff
[] = { 't','i','f','f',0 };
323 static const WCHAR tiff_scheme
[] = { 'h','t','t','p',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','t','i','f','f','/','1','.','0','/',0 };
324 static const WCHAR exif
[] = { 'e','x','i','f',0 };
325 static const WCHAR exif_scheme
[] = { 'h','t','t','p',':','/','/','n','s','.','a','d','o','b','e','.','c','o','m','/','e','x','i','f','/','1','.','0','/',0 };
326 static const WCHAR stDim
[] = { 's','t','D','i','m',0 };
327 static const 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 };
328 static const WCHAR xapGImg
[] = { 'x','a','p','G','I','m','g',0 };
329 static const 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 };
330 static const WCHAR stEvt
[] = { 's','t','E','v','t',0 };
331 static const 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 };
332 static const WCHAR stRef
[] = { 's','t','R','e','f',0 };
333 static const 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 };
334 static const WCHAR stVer
[] = { 's','t','V','e','r',0 };
335 static const 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 };
336 static const WCHAR stJob
[] = { 's','t','J','o','b',0 };
337 static const 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 };
338 static const WCHAR aux
[] = { 'a','u','x',0 };
339 static const 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 };
340 static const WCHAR crs
[] = { 'c','r','s',0 };
341 static const 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 };
342 static const WCHAR xmpDM
[] = { 'x','m','p','D','M',0 };
343 static const 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 };
344 static const WCHAR Iptc4xmpCore
[] = { 'I','p','t','c','4','x','m','p','C','o','r','e',0 };
345 static const 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 };
346 static const WCHAR MicrosoftPhoto
[] = { 'M','i','c','r','o','s','o','f','t','P','h','o','t','o',0 };
347 static const 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 };
348 static const WCHAR MP
[] = { 'M','P',0 };
349 static const 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 };
350 static const WCHAR MPRI
[] = { 'M','P','R','I',0 };
351 static const 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 };
352 static const WCHAR MPReg
[] = { 'M','P','R','e','g',0 };
353 static const 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 };
364 { xmpidq
, xmpidq_scheme
},
365 { xmpRights
, xmpRights_scheme
},
366 { xmpMM
, xmpMM_scheme
},
367 { xmpBJ
, xmpBJ_scheme
},
368 { xmpTPg
, xmpTPg_scheme
},
370 { photoshop
, photoshop_scheme
},
371 { tiff
, tiff_scheme
},
372 { exif
, exif_scheme
},
373 { stDim
, stDim_scheme
},
374 { xapGImg
, xapGImg_scheme
},
375 { stEvt
, stEvt_scheme
},
376 { stRef
, stRef_scheme
},
377 { stVer
, stVer_scheme
},
378 { stJob
, stJob_scheme
},
381 { xmpDM
, xmpDM_scheme
},
382 { Iptc4xmpCore
, Iptc4xmpCore_scheme
},
383 { MicrosoftPhoto
, MicrosoftPhoto_scheme
},
385 { MPRI
, MPRI_scheme
},
386 { MPReg
, MPReg_scheme
}
389 HRESULT WINAPI
WICMapSchemaToName(REFGUID format
, LPWSTR schema
, UINT len
, WCHAR
*name
, UINT
*ret_len
)
393 TRACE("%s,%s,%u,%p,%p\n", wine_dbgstr_guid(format
), debugstr_w(schema
), len
, name
, ret_len
);
395 if (!format
|| !schema
|| !ret_len
)
398 /* It appears that the only metadata formats
399 * that support schemas are xmp and xmpstruct.
401 if (!IsEqualGUID(format
, &GUID_MetadataFormatXMP
) &&
402 !IsEqualGUID(format
, &GUID_MetadataFormatXMPStruct
))
403 return WINCODEC_ERR_PROPERTYNOTFOUND
;
405 for (i
= 0; i
< sizeof(name2schema
)/sizeof(name2schema
[0]); i
++)
407 if (!lstrcmpW(name2schema
[i
].schema
, schema
))
411 if (!len
) return E_INVALIDARG
;
413 len
= min(len
- 1, lstrlenW(name2schema
[i
].name
));
414 memcpy(name
, name2schema
[i
].name
, len
* sizeof(WCHAR
));
417 if (len
< lstrlenW(name2schema
[i
].name
))
418 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
);
421 if (ret_len
) *ret_len
= lstrlenW(name2schema
[i
].name
) + 1;
426 return WINCODEC_ERR_PROPERTYNOTFOUND
;