ReactOS  0.4.13-dev-479-gec9c8fd
metadatahandler.c
Go to the documentation of this file.
1 /*
2  * Copyright 2012 Vincent Povirk for CodeWeavers
3  * Copyright 2012 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 "config.h"
21 
22 #include <stdarg.h>
23 #include <stdio.h>
24 
25 #define COBJMACROS
26 #define NONAMELESSUNION
27 
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wine/winternl.h"
31 #include "objbase.h"
32 #include "propvarutil.h"
33 
34 #include "wincodecs_private.h"
35 
36 #include "wine/debug.h"
37 
39 
40 typedef struct MetadataHandler {
49 
51 {
52  return CONTAINING_RECORD(iface, MetadataHandler, IWICMetadataWriter_iface);
53 }
54 
56 {
57  return CONTAINING_RECORD(iface, MetadataHandler, IWICPersistStream_iface);
58 }
59 
61 {
62  DWORD i;
63 
64  for (i=0; i<This->item_count; i++)
65  {
66  PropVariantClear(&This->items[i].schema);
67  PropVariantClear(&This->items[i].id);
68  PropVariantClear(&This->items[i].value);
69  }
70 
71  HeapFree(GetProcessHeap(), 0, This->items);
72 }
73 
75  IWICEnumMetadataItem **ppIEnumMetadataItem);
76 
78  void **ppv)
79 {
81  TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
82 
83  if (!ppv) return E_INVALIDARG;
84 
85  if (IsEqualIID(&IID_IUnknown, iid) ||
86  IsEqualIID(&IID_IWICMetadataReader, iid) ||
87  (IsEqualIID(&IID_IWICMetadataWriter, iid) && This->vtable->is_writer))
88  {
89  *ppv = &This->IWICMetadataWriter_iface;
90  }
91  else if (IsEqualIID(&IID_IPersist, iid) ||
93  IsEqualIID(&IID_IWICPersistStream, iid))
94  {
95  *ppv = &This->IWICPersistStream_iface;
96  }
97  else
98  {
99  *ppv = NULL;
100  return E_NOINTERFACE;
101  }
102 
103  IUnknown_AddRef((IUnknown*)*ppv);
104  return S_OK;
105 }
106 
108 {
111 
112  TRACE("(%p) refcount=%u\n", iface, ref);
113 
114  return ref;
115 }
116 
118 {
121 
122  TRACE("(%p) refcount=%u\n", iface, ref);
123 
124  if (ref == 0)
125  {
127  This->lock.DebugInfo->Spare[0] = 0;
128  DeleteCriticalSection(&This->lock);
130  }
131 
132  return ref;
133 }
134 
136  IWICMetadataHandlerInfo **ppIHandler)
137 {
138  HRESULT hr;
139  IWICComponentInfo *component_info;
141 
142  TRACE("%p,%p\n", iface, ppIHandler);
143 
144  hr = CreateComponentInfo(This->vtable->clsid, &component_info);
145  if (FAILED(hr)) return hr;
146 
147  hr = IWICComponentInfo_QueryInterface(component_info, &IID_IWICMetadataHandlerInfo,
148  (void **)ppIHandler);
149 
150  IWICComponentInfo_Release(component_info);
151  return hr;
152 }
153 
155  GUID *pguidMetadataFormat)
156 {
157  HRESULT hr;
158  IWICMetadataHandlerInfo *metadata_info;
159 
160  TRACE("%p,%p\n", iface, pguidMetadataFormat);
161 
162  if (!pguidMetadataFormat) return E_INVALIDARG;
163 
164  hr = MetadataHandler_GetMetadataHandlerInfo(iface, &metadata_info);
165  if (FAILED(hr)) return hr;
166 
167  hr = IWICMetadataHandlerInfo_GetMetadataFormat(metadata_info, pguidMetadataFormat);
168  IWICMetadataHandlerInfo_Release(metadata_info);
169 
170  return hr;
171 }
172 
174  UINT *pcCount)
175 {
177 
178  TRACE("%p,%p\n", iface, pcCount);
179 
180  if (!pcCount) return E_INVALIDARG;
181 
182  *pcCount = This->item_count;
183  return S_OK;
184 }
185 
187  UINT index, PROPVARIANT *schema, PROPVARIANT *id, PROPVARIANT *value)
188 {
189  HRESULT hr = S_OK;
191 
192  TRACE("%p,%u,%p,%p,%p\n", iface, index, schema, id, value);
193 
194  EnterCriticalSection(&This->lock);
195 
196  if (index >= This->item_count)
197  {
198  LeaveCriticalSection(&This->lock);
199  return E_INVALIDARG;
200  }
201 
202  if (schema)
203  hr = PropVariantCopy(schema, &This->items[index].schema);
204 
205  if (SUCCEEDED(hr) && id)
206  hr = PropVariantCopy(id, &This->items[index].id);
207 
208  if (SUCCEEDED(hr) && value)
209  hr = PropVariantCopy(value, &This->items[index].value);
210 
211  LeaveCriticalSection(&This->lock);
212  return hr;
213 }
214 
216  const PROPVARIANT *schema, const PROPVARIANT *id, PROPVARIANT *value)
217 {
218  UINT i;
221 
222  TRACE("(%p,%s,%s,%p)\n", iface, wine_dbgstr_variant((const VARIANT *)schema), wine_dbgstr_variant((const VARIANT *)id), value);
223 
224  if (!id) return E_INVALIDARG;
225 
226  EnterCriticalSection(&This->lock);
227 
228  for (i = 0; i < This->item_count; i++)
229  {
230  if (schema && This->items[i].schema.vt != VT_EMPTY)
231  {
232  if (PropVariantCompareEx(schema, &This->items[i].schema, 0, PVCF_USESTRCMPI) != 0) continue;
233  }
234 
235  if (PropVariantCompareEx(id, &This->items[i].id, 0, PVCF_USESTRCMPI) != 0) continue;
236 
237  hr = value ? PropVariantCopy(value, &This->items[i].value) : S_OK;
238  break;
239  }
240 
241  LeaveCriticalSection(&This->lock);
242  return hr;
243 }
244 
246  IWICEnumMetadataItem **ppIEnumMetadata)
247 {
249  TRACE("(%p,%p)\n", iface, ppIEnumMetadata);
250  return MetadataHandlerEnum_Create(This, 0, ppIEnumMetadata);
251 }
252 
254  const PROPVARIANT *pvarSchema, const PROPVARIANT *pvarId, const PROPVARIANT *pvarValue)
255 {
256  FIXME("(%p,%p,%p,%p): stub\n", iface, pvarSchema, pvarId, pvarValue);
257  return E_NOTIMPL;
258 }
259 
261  UINT nIndex, const PROPVARIANT *pvarSchema, const PROPVARIANT *pvarId, const PROPVARIANT *pvarValue)
262 {
263  FIXME("(%p,%u,%p,%p,%p): stub\n", iface, nIndex, pvarSchema, pvarId, pvarValue);
264  return E_NOTIMPL;
265 }
266 
268  const PROPVARIANT *pvarSchema, const PROPVARIANT *pvarId)
269 {
270  FIXME("(%p,%p,%p): stub\n", iface, pvarSchema, pvarId);
271  return E_NOTIMPL;
272 }
273 
275  UINT nIndex)
276 {
277  FIXME("(%p,%u): stub\n", iface, nIndex);
278  return E_NOTIMPL;
279 }
280 
281 static const IWICMetadataWriterVtbl MetadataHandler_Vtbl = {
295 };
296 
298  REFIID iid, void **ppv)
299 {
301  return IWICMetadataWriter_QueryInterface(&This->IWICMetadataWriter_iface, iid, ppv);
302 }
303 
305 {
307  return IWICMetadataWriter_AddRef(&This->IWICMetadataWriter_iface);
308 }
309 
311 {
313  return IWICMetadataWriter_Release(&This->IWICMetadataWriter_iface);
314 }
315 
317  CLSID *pClassID)
318 {
319  FIXME("(%p,%p): stub\n", iface, pClassID);
320  return E_NOTIMPL;
321 }
322 
324 {
325  FIXME("(%p): stub\n", iface);
326  return E_NOTIMPL;
327 }
328 
330  IStream *pStm)
331 {
333  TRACE("(%p,%p)\n", iface, pStm);
334  return IWICPersistStream_LoadEx(&This->IWICPersistStream_iface, pStm, NULL, WICPersistOptionDefault);
335 }
336 
338  IStream *pStm, BOOL fClearDirty)
339 {
340  FIXME("(%p,%p,%i): stub\n", iface, pStm, fClearDirty);
341  return E_NOTIMPL;
342 }
343 
345  ULARGE_INTEGER *pcbSize)
346 {
347  FIXME("(%p,%p): stub\n", iface, pcbSize);
348  return E_NOTIMPL;
349 }
350 
352  IStream *pIStream, const GUID *pguidPreferredVendor, DWORD dwPersistOptions)
353 {
355  HRESULT hr;
356  MetadataItem *new_items=NULL;
357  DWORD item_count=0;
358 
359  TRACE("(%p,%p,%s,%x)\n", iface, pIStream, debugstr_guid(pguidPreferredVendor), dwPersistOptions);
360 
361  EnterCriticalSection(&This->lock);
362 
363  hr = This->vtable->fnLoad(pIStream, pguidPreferredVendor, dwPersistOptions,
364  &new_items, &item_count);
365 
366  if (SUCCEEDED(hr))
367  {
369  This->items = new_items;
370  This->item_count = item_count;
371  }
372 
373  LeaveCriticalSection(&This->lock);
374 
375  return hr;
376 }
377 
379  IStream *pIStream, DWORD dwPersistOptions, BOOL fClearDirty)
380 {
381  FIXME("(%p,%p,%x,%i): stub\n", iface, pIStream, dwPersistOptions, fClearDirty);
382  return E_NOTIMPL;
383 }
384 
385 static const IWICPersistStreamVtbl MetadataHandler_PersistStream_Vtbl = {
396 };
397 
399 {
401  HRESULT hr;
402 
403  TRACE("%s\n", debugstr_guid(vtable->clsid));
404 
405  *ppv = NULL;
406 
407  This = HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataHandler));
408  if (!This) return E_OUTOFMEMORY;
409 
410  This->IWICMetadataWriter_iface.lpVtbl = &MetadataHandler_Vtbl;
411  This->IWICPersistStream_iface.lpVtbl = &MetadataHandler_PersistStream_Vtbl;
412  This->ref = 1;
413  This->vtable = vtable;
414  This->items = NULL;
415  This->item_count = 0;
416 
418  This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": MetadataHandler.lock");
419 
420  hr = IWICMetadataWriter_QueryInterface(&This->IWICMetadataWriter_iface, iid, ppv);
421 
422  IWICMetadataWriter_Release(&This->IWICMetadataWriter_iface);
423 
424  return hr;
425 }
426 
427 typedef struct MetadataHandlerEnum {
433 
435 {
436  return CONTAINING_RECORD(iface, MetadataHandlerEnum, IWICEnumMetadataItem_iface);
437 }
438 
440  void **ppv)
441 {
443  TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
444 
445  if (!ppv) return E_INVALIDARG;
446 
447  if (IsEqualIID(&IID_IUnknown, iid) ||
448  IsEqualIID(&IID_IWICEnumMetadataItem, iid))
449  {
450  *ppv = &This->IWICEnumMetadataItem_iface;
451  }
452  else
453  {
454  *ppv = NULL;
455  return E_NOINTERFACE;
456  }
457 
458  IUnknown_AddRef((IUnknown*)*ppv);
459  return S_OK;
460 }
461 
463 {
466 
467  TRACE("(%p) refcount=%u\n", iface, ref);
468 
469  return ref;
470 }
471 
473 {
476 
477  TRACE("(%p) refcount=%u\n", iface, ref);
478 
479  if (ref == 0)
480  {
481  IWICMetadataWriter_Release(&This->parent->IWICMetadataWriter_iface);
483  }
484 
485  return ref;
486 }
487 
489  ULONG celt, PROPVARIANT *rgeltSchema, PROPVARIANT *rgeltId,
490  PROPVARIANT *rgeltValue, ULONG *pceltFetched)
491 {
493  ULONG new_index;
495  ULONG i;
496 
497  TRACE("(%p,%i)\n", iface, celt);
498 
499  EnterCriticalSection(&This->parent->lock);
500 
501  if (This->index >= This->parent->item_count)
502  {
503  *pceltFetched = 0;
504  LeaveCriticalSection(&This->parent->lock);
505  return S_FALSE;
506  }
507 
508  new_index = min(This->parent->item_count, This->index + celt);
509  *pceltFetched = new_index - This->index;
510 
511  if (rgeltSchema)
512  {
513  for (i=0; SUCCEEDED(hr) && i < *pceltFetched; i++)
514  hr = PropVariantCopy(&rgeltSchema[i], &This->parent->items[i+This->index].schema);
515  }
516 
517  for (i=0; SUCCEEDED(hr) && i < *pceltFetched; i++)
518  hr = PropVariantCopy(&rgeltId[i], &This->parent->items[i+This->index].id);
519 
520  if (rgeltValue)
521  {
522  for (i=0; SUCCEEDED(hr) && i < *pceltFetched; i++)
523  hr = PropVariantCopy(&rgeltValue[i], &This->parent->items[i+This->index].value);
524  }
525 
526  if (SUCCEEDED(hr))
527  {
528  This->index = new_index;
529  }
530 
531  LeaveCriticalSection(&This->parent->lock);
532 
533  return hr;
534 }
535 
537  ULONG celt)
538 {
540 
541  EnterCriticalSection(&This->parent->lock);
542 
543  This->index += celt;
544 
545  LeaveCriticalSection(&This->parent->lock);
546 
547  return S_OK;
548 }
549 
551 {
553 
554  EnterCriticalSection(&This->parent->lock);
555 
556  This->index = 0;
557 
558  LeaveCriticalSection(&This->parent->lock);
559 
560  return S_OK;
561 }
562 
564  IWICEnumMetadataItem **ppIEnumMetadataItem)
565 {
567  HRESULT hr;
568 
569  EnterCriticalSection(&This->parent->lock);
570 
571  hr = MetadataHandlerEnum_Create(This->parent, This->index, ppIEnumMetadataItem);
572 
573  LeaveCriticalSection(&This->parent->lock);
574 
575  return hr;
576 }
577 
578 static const IWICEnumMetadataItemVtbl MetadataHandlerEnum_Vtbl = {
586 };
587 
589  IWICEnumMetadataItem **ppIEnumMetadataItem)
590 {
592 
593  if (!ppIEnumMetadataItem) return E_INVALIDARG;
594 
595  *ppIEnumMetadataItem = NULL;
596 
598  if (!This) return E_OUTOFMEMORY;
599 
600  IWICMetadataWriter_AddRef(&parent->IWICMetadataWriter_iface);
601 
602  This->IWICEnumMetadataItem_iface.lpVtbl = &MetadataHandlerEnum_Vtbl;
603  This->ref = 1;
604  This->parent = parent;
605  This->index = index;
606 
607  *ppIEnumMetadataItem = &This->IWICEnumMetadataItem_iface;
608 
609  return S_OK;
610 }
611 
612 static HRESULT LoadUnknownMetadata(IStream *input, const GUID *preferred_vendor,
613  DWORD persist_options, MetadataItem **items, DWORD *item_count)
614 {
615  HRESULT hr;
617  STATSTG stat;
618  BYTE *data;
619  ULONG bytesread;
620 
621  TRACE("\n");
622 
623  hr = IStream_Stat(input, &stat, STATFLAG_NONAME);
624  if (FAILED(hr))
625  return hr;
626 
627  data = HeapAlloc(GetProcessHeap(), 0, stat.cbSize.QuadPart);
628  if (!data) return E_OUTOFMEMORY;
629 
630  hr = IStream_Read(input, data, stat.cbSize.QuadPart, &bytesread);
631  if (bytesread != stat.cbSize.QuadPart) hr = E_FAIL;
632  if (hr != S_OK)
633  {
635  return hr;
636  }
637 
639  if (!result)
640  {
642  return E_OUTOFMEMORY;
643  }
644 
645  PropVariantInit(&result[0].schema);
646  PropVariantInit(&result[0].id);
647  PropVariantInit(&result[0].value);
648 
649  result[0].value.vt = VT_BLOB;
650  result[0].value.u.blob.cbSize = bytesread;
651  result[0].value.u.blob.pBlobData = data;
652 
653  *items = result;
654  *item_count = 1;
655 
656  return S_OK;
657 }
658 
660  0,
661  &CLSID_WICUnknownMetadataReader,
663 };
664 
666 {
668 }
669 
670 #define SWAP_USHORT(x) do { if (!native_byte_order) (x) = RtlUshortByteSwap(x); } while(0)
671 #define SWAP_ULONG(x) do { if (!native_byte_order) (x) = RtlUlongByteSwap(x); } while(0)
672 #define SWAP_ULONGLONG(x) do { if (!native_byte_order) (x) = RtlUlonglongByteSwap(x); } while(0)
673 
674 struct IFD_entry
675 {
680 };
681 
682 #define IFD_BYTE 1
683 #define IFD_ASCII 2
684 #define IFD_SHORT 3
685 #define IFD_LONG 4
686 #define IFD_RATIONAL 5
687 #define IFD_SBYTE 6
688 #define IFD_UNDEFINED 7
689 #define IFD_SSHORT 8
690 #define IFD_SLONG 9
691 #define IFD_SRATIONAL 10
692 #define IFD_FLOAT 11
693 #define IFD_DOUBLE 12
694 #define IFD_IFD 13
695 
696 static int tag_to_vt(SHORT tag)
697 {
698  static const int tag2vt[] =
699  {
700  VT_EMPTY, /* 0 */
701  VT_UI1, /* IFD_BYTE 1 */
702  VT_LPSTR, /* IFD_ASCII 2 */
703  VT_UI2, /* IFD_SHORT 3 */
704  VT_UI4, /* IFD_LONG 4 */
705  VT_UI8, /* IFD_RATIONAL 5 */
706  VT_I1, /* IFD_SBYTE 6 */
707  VT_BLOB, /* IFD_UNDEFINED 7 */
708  VT_I2, /* IFD_SSHORT 8 */
709  VT_I4, /* IFD_SLONG 9 */
710  VT_I8, /* IFD_SRATIONAL 10 */
711  VT_R4, /* IFD_FLOAT 11 */
712  VT_R8, /* IFD_DOUBLE 12 */
713  VT_BLOB, /* IFD_IFD 13 */
714  };
715  return (tag > 0 && tag <= 13) ? tag2vt[tag] : VT_BLOB;
716 }
717 
719  MetadataItem *item, BOOL native_byte_order)
720 {
721  ULONG count, value, i;
722  SHORT type;
724  HRESULT hr;
725 
726  item->schema.vt = VT_EMPTY;
727  item->id.vt = VT_UI2;
728  item->id.u.uiVal = entry->id;
729  SWAP_USHORT(item->id.u.uiVal);
730 
731  count = entry->count;
732  SWAP_ULONG(count);
733  type = entry->type;
734  SWAP_USHORT(type);
735  item->value.vt = tag_to_vt(type);
736  value = entry->value;
737  SWAP_ULONG(value);
738 
739  switch (type)
740  {
741  case IFD_BYTE:
742  case IFD_SBYTE:
743  if (!count) count = 1;
744 
745  if (count <= 4)
746  {
747  const BYTE *data = (const BYTE *)&entry->value;
748 
749  if (count == 1)
750  item->value.u.bVal = data[0];
751  else
752  {
753  item->value.vt |= VT_VECTOR;
754  item->value.u.caub.cElems = count;
755  item->value.u.caub.pElems = HeapAlloc(GetProcessHeap(), 0, count);
756  memcpy(item->value.u.caub.pElems, data, count);
757  }
758  break;
759  }
760 
761  item->value.vt |= VT_VECTOR;
762  item->value.u.caub.cElems = count;
763  item->value.u.caub.pElems = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, count);
764  if (!item->value.u.caub.pElems) return E_OUTOFMEMORY;
765 
766  pos.QuadPart = value;
767  hr = IStream_Seek(input, pos, SEEK_SET, NULL);
768  if (FAILED(hr))
769  {
770  HeapFree(GetProcessHeap(), 0, item->value.u.caub.pElems);
771  return hr;
772  }
773  hr = IStream_Read(input, item->value.u.caub.pElems, count, NULL);
774  if (FAILED(hr))
775  {
776  HeapFree(GetProcessHeap(), 0, item->value.u.caub.pElems);
777  return hr;
778  }
779  break;
780  case IFD_SHORT:
781  case IFD_SSHORT:
782  if (!count) count = 1;
783 
784  if (count <= 2)
785  {
786  const SHORT *data = (const SHORT *)&entry->value;
787 
788  if (count == 1)
789  {
790  item->value.u.uiVal = data[0];
791  SWAP_USHORT(item->value.u.uiVal);
792  }
793  else
794  {
795  item->value.vt |= VT_VECTOR;
796  item->value.u.caui.cElems = count;
797  item->value.u.caui.pElems = HeapAlloc(GetProcessHeap(), 0, count * 2);
798  memcpy(item->value.u.caui.pElems, data, count * 2);
799  for (i = 0; i < count; i++)
800  SWAP_USHORT(item->value.u.caui.pElems[i]);
801  }
802  break;
803  }
804 
805  item->value.vt |= VT_VECTOR;
806  item->value.u.caui.cElems = count;
807  item->value.u.caui.pElems = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, count * 2);
808  if (!item->value.u.caui.pElems) return E_OUTOFMEMORY;
809 
810  pos.QuadPart = value;
811  hr = IStream_Seek(input, pos, SEEK_SET, NULL);
812  if (FAILED(hr))
813  {
814  HeapFree(GetProcessHeap(), 0, item->value.u.caui.pElems);
815  return hr;
816  }
817  hr = IStream_Read(input, item->value.u.caui.pElems, count * 2, NULL);
818  if (FAILED(hr))
819  {
820  HeapFree(GetProcessHeap(), 0, item->value.u.caui.pElems);
821  return hr;
822  }
823  for (i = 0; i < count; i++)
824  SWAP_USHORT(item->value.u.caui.pElems[i]);
825  break;
826  case IFD_LONG:
827  case IFD_SLONG:
828  case IFD_FLOAT:
829  if (!count) count = 1;
830 
831  if (count == 1)
832  {
833  item->value.u.ulVal = value;
834  break;
835  }
836 
837  item->value.vt |= VT_VECTOR;
838  item->value.u.caul.cElems = count;
839  item->value.u.caul.pElems = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, count * 4);
840  if (!item->value.u.caul.pElems) return E_OUTOFMEMORY;
841 
842  pos.QuadPart = value;
843  hr = IStream_Seek(input, pos, SEEK_SET, NULL);
844  if (FAILED(hr))
845  {
846  HeapFree(GetProcessHeap(), 0, item->value.u.caul.pElems);
847  return hr;
848  }
849  hr = IStream_Read(input, item->value.u.caul.pElems, count * 4, NULL);
850  if (FAILED(hr))
851  {
852  HeapFree(GetProcessHeap(), 0, item->value.u.caul.pElems);
853  return hr;
854  }
855  for (i = 0; i < count; i++)
856  SWAP_ULONG(item->value.u.caul.pElems[i]);
857  break;
858  case IFD_RATIONAL:
859  case IFD_SRATIONAL:
860  case IFD_DOUBLE:
861  if (!count)
862  {
863  FIXME("IFD field type %d, count 0\n", type);
864  item->value.vt = VT_EMPTY;
865  break;
866  }
867 
868  if (count == 1)
869  {
870  ULONGLONG ull;
871 
872  pos.QuadPart = value;
873  hr = IStream_Seek(input, pos, SEEK_SET, NULL);
874  if (FAILED(hr)) return hr;
875 
876  hr = IStream_Read(input, &ull, sizeof(ull), NULL);
877  if (hr != S_OK) return hr;
878 
879  item->value.u.uhVal.QuadPart = ull;
880 
881  if (type == IFD_DOUBLE)
882  SWAP_ULONGLONG(item->value.u.uhVal.QuadPart);
883  else
884  {
885  SWAP_ULONG(item->value.u.uhVal.u.LowPart);
886  SWAP_ULONG(item->value.u.uhVal.u.HighPart);
887  }
888  break;
889  }
890  else
891  {
892  item->value.vt |= VT_VECTOR;
893  item->value.u.cauh.cElems = count;
894  item->value.u.cauh.pElems = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, count * 8);
895  if (!item->value.u.cauh.pElems) return E_OUTOFMEMORY;
896 
897  pos.QuadPart = value;
898  hr = IStream_Seek(input, pos, SEEK_SET, NULL);
899  if (FAILED(hr))
900  {
901  HeapFree(GetProcessHeap(), 0, item->value.u.cauh.pElems);
902  return hr;
903  }
904  hr = IStream_Read(input, item->value.u.cauh.pElems, count * 8, NULL);
905  if (FAILED(hr))
906  {
907  HeapFree(GetProcessHeap(), 0, item->value.u.cauh.pElems);
908  return hr;
909  }
910  for (i = 0; i < count; i++)
911  {
912  if (type == IFD_DOUBLE)
913  SWAP_ULONGLONG(item->value.u.cauh.pElems[i].QuadPart);
914  else
915  {
916  SWAP_ULONG(item->value.u.cauh.pElems[i].u.LowPart);
917  SWAP_ULONG(item->value.u.cauh.pElems[i].u.HighPart);
918  }
919  }
920  }
921  break;
922  case IFD_ASCII:
923  item->value.u.pszVal = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, count + 1);
924  if (!item->value.u.pszVal) return E_OUTOFMEMORY;
925 
926  if (count <= 4)
927  {
928  const char *data = (const char *)&entry->value;
929  memcpy(item->value.u.pszVal, data, count);
930  item->value.u.pszVal[count] = 0;
931  break;
932  }
933 
934  pos.QuadPart = value;
935  hr = IStream_Seek(input, pos, SEEK_SET, NULL);
936  if (FAILED(hr))
937  {
938  HeapFree(GetProcessHeap(), 0, item->value.u.pszVal);
939  return hr;
940  }
941  hr = IStream_Read(input, item->value.u.pszVal, count, NULL);
942  if (FAILED(hr))
943  {
944  HeapFree(GetProcessHeap(), 0, item->value.u.pszVal);
945  return hr;
946  }
947  item->value.u.pszVal[count] = 0;
948  break;
949  case IFD_UNDEFINED:
950  if (!count)
951  {
952  FIXME("IFD field type %d, count 0\n", type);
953  item->value.vt = VT_EMPTY;
954  break;
955  }
956 
957  item->value.u.blob.pBlobData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, count);
958  if (!item->value.u.blob.pBlobData) return E_OUTOFMEMORY;
959 
960  item->value.u.blob.cbSize = count;
961 
962  if (count <= 4)
963  {
964  const char *data = (const char *)&entry->value;
965  memcpy(item->value.u.blob.pBlobData, data, count);
966  break;
967  }
968 
969  pos.QuadPart = value;
970  hr = IStream_Seek(input, pos, SEEK_SET, NULL);
971  if (FAILED(hr))
972  {
973  HeapFree(GetProcessHeap(), 0, item->value.u.blob.pBlobData);
974  return hr;
975  }
976  hr = IStream_Read(input, item->value.u.blob.pBlobData, count, NULL);
977  if (FAILED(hr))
978  {
979  HeapFree(GetProcessHeap(), 0, item->value.u.blob.pBlobData);
980  return hr;
981  }
982  break;
983  default:
984  FIXME("loading field of type %d, count %u is not implemented\n", type, count);
985  break;
986  }
987  return S_OK;
988 }
989 
990 static HRESULT LoadIfdMetadata(IStream *input, const GUID *preferred_vendor,
991  DWORD persist_options, MetadataItem **items, DWORD *item_count)
992 {
993  HRESULT hr;
995  USHORT count, i;
996  struct IFD_entry *entry;
997  BOOL native_byte_order = TRUE;
998  ULONG bytesread;
999 
1000  TRACE("\n");
1001 
1002 #ifdef WORDS_BIGENDIAN
1003  if (persist_options & WICPersistOptionLittleEndian)
1004 #else
1005  if (persist_options & WICPersistOptionBigEndian)
1006 #endif
1007  native_byte_order = FALSE;
1008 
1009  hr = IStream_Read(input, &count, sizeof(count), &bytesread);
1010  if (bytesread != sizeof(count)) hr = E_FAIL;
1011  if (hr != S_OK) return hr;
1012 
1013  SWAP_USHORT(count);
1014 
1015  entry = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*entry));
1016  if (!entry) return E_OUTOFMEMORY;
1017 
1018  hr = IStream_Read(input, entry, count * sizeof(*entry), &bytesread);
1019  if (bytesread != count * sizeof(*entry)) hr = E_FAIL;
1020  if (hr != S_OK)
1021  {
1022  HeapFree(GetProcessHeap(), 0, entry);
1023  return hr;
1024  }
1025 
1026  /* limit number of IFDs to 4096 to avoid infinite loop */
1027  for (i = 0; i < 4096; i++)
1028  {
1029  ULONG next_ifd_offset;
1031  USHORT next_ifd_count;
1032 
1033  hr = IStream_Read(input, &next_ifd_offset, sizeof(next_ifd_offset), &bytesread);
1034  if (bytesread != sizeof(next_ifd_offset)) hr = E_FAIL;
1035  if (hr != S_OK) break;
1036 
1037  SWAP_ULONG(next_ifd_offset);
1038  if (!next_ifd_offset) break;
1039 
1040  pos.QuadPart = next_ifd_offset;
1041  hr = IStream_Seek(input, pos, SEEK_SET, NULL);
1042  if (FAILED(hr)) break;
1043 
1044  hr = IStream_Read(input, &next_ifd_count, sizeof(next_ifd_count), &bytesread);
1045  if (bytesread != sizeof(next_ifd_count)) hr = E_FAIL;
1046  if (hr != S_OK) break;
1047 
1048  SWAP_USHORT(next_ifd_count);
1049 
1050  pos.QuadPart = next_ifd_count * sizeof(*entry);
1051  hr = IStream_Seek(input, pos, SEEK_CUR, NULL);
1052  if (FAILED(hr)) break;
1053  }
1054 
1055  if (hr != S_OK || i == 4096)
1056  {
1057  HeapFree(GetProcessHeap(), 0, entry);
1059  }
1060 
1062  if (!result)
1063  {
1064  HeapFree(GetProcessHeap(), 0, entry);
1065  return E_OUTOFMEMORY;
1066  }
1067 
1068  for (i = 0; i < count; i++)
1069  {
1070  hr = load_IFD_entry(input, &entry[i], &result[i], native_byte_order);
1071  if (FAILED(hr))
1072  {
1073  HeapFree(GetProcessHeap(), 0, entry);
1075  return hr;
1076  }
1077  }
1078 
1079  HeapFree(GetProcessHeap(), 0, entry);
1080 
1081  *items = result;
1082  *item_count = count;
1083 
1084  return S_OK;
1085 }
1086 
1088  0,
1089  &CLSID_WICIfdMetadataReader,
1091 };
1092 
1094 {
1096 }
#define SEEK_CUR
Definition: util.h:63
ULONG count
const MetadataHandlerVtbl * vtable
#define REFIID
Definition: guiddef.h:113
#define TRUE
Definition: types.h:120
#define IFD_FLOAT
static const IWICMetadataWriterVtbl MetadataHandler_Vtbl
#define E_NOINTERFACE
Definition: winerror.h:2364
#define IFD_SSHORT
Definition: compat.h:1939
#define IFD_DOUBLE
static HRESULT WINAPI MetadataHandler_GetMetadataFormat(IWICMetadataWriter *iface, GUID *pguidMetadataFormat)
static const MetadataHandlerVtbl UnknownMetadataReader_Vtbl
#define WINCODEC_ERR_BADMETADATAHEADER
Definition: winerror.h:3294
static void * vtable[]
Definition: typelib.c:1231
#define DWORD_PTR
Definition: treelist.c:76
Definition: compat.h:1955
HRESULT hr
Definition: shlfolder.c:183
HRESULT MetadataReader_Create(const MetadataHandlerVtbl *vtable, REFIID iid, void **ppv)
Definition: compat.h:1951
HRESULT WINAPI PropVariantClear(PROPVARIANT *pvar)
Definition: ole2.c:2952
static HRESULT WINAPI MetadataHandler_SetValue(IWICMetadataWriter *iface, const PROPVARIANT *pvarSchema, const PROPVARIANT *pvarId, const PROPVARIANT *pvarValue)
GLuint GLuint GLsizei count
Definition: gl.h:1545
static HRESULT WINAPI MetadataHandler_GetClassID(IWICPersistStream *iface, CLSID *pClassID)
const GUID IID_IPersist
Definition: proxy.cpp:14
static HRESULT WINAPI MetadataHandler_SaveEx(IWICPersistStream *iface, IStream *pIStream, DWORD dwPersistOptions, BOOL fClearDirty)
struct MetadataHandlerEnum MetadataHandlerEnum
REFIID LPVOID * ppv
Definition: atlbase.h:39
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
static HRESULT WINAPI MetadataHandlerEnum_Next(IWICEnumMetadataItem *iface, ULONG celt, PROPVARIANT *rgeltSchema, PROPVARIANT *rgeltId, PROPVARIANT *rgeltValue, ULONG *pceltFetched)
Definition: ecma_167.h:138
struct MetadataHandler MetadataHandler
WINE_DEFAULT_DEBUG_CHANNEL(wincodecs)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
static const MetadataHandlerVtbl IfdMetadataReader_Vtbl
#define E_FAIL
Definition: ddrawi.h:102
INT WINAPI PropVariantCompareEx(REFPROPVARIANT propvar1, REFPROPVARIANT propvar2, PROPVAR_COMPARE_UNIT unit, PROPVAR_COMPARE_FLAGS flags)
Definition: propvar.c:741
IWICPersistStream IWICPersistStream_iface
Definition: send.c:47
static ULONG WINAPI MetadataHandler_Release(IWICMetadataWriter *iface)
static HRESULT LoadUnknownMetadata(IStream *input, const GUID *preferred_vendor, DWORD persist_options, MetadataItem **items, DWORD *item_count)
static HRESULT WINAPI MetadataHandler_IsDirty(IWICPersistStream *iface)
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
#define IFD_LONG
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
static HRESULT MetadataHandlerEnum_Create(MetadataHandler *parent, DWORD index, IWICEnumMetadataItem **ppIEnumMetadataItem)
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
static const IWICPersistStreamVtbl MetadataHandler_PersistStream_Vtbl
short SHORT
Definition: pedump.c:59
SHORT id
GLenum GLint ref
Definition: glext.h:6028
#define FIXME(fmt,...)
Definition: debug.h:110
static HRESULT WINAPI MetadataHandler_Save(IWICPersistStream *iface, IStream *pStm, BOOL fClearDirty)
static HRESULT WINAPI MetadataHandler_GetValueByIndex(IWICMetadataWriter *iface, UINT index, PROPVARIANT *schema, PROPVARIANT *id, PROPVARIANT *value)
static int tag_to_vt(SHORT tag)
static HRESULT WINAPI MetadataHandler_RemoveValue(IWICMetadataWriter *iface, const PROPVARIANT *pvarSchema, const PROPVARIANT *pvarId)
#define S_FALSE
Definition: winerror.h:2357
#define E_INVALIDARG
Definition: ddrawi.h:101
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:697
#define IFD_SRATIONAL
smooth NULL
Definition: ftsmooth.c:416
#define SWAP_ULONGLONG(x)
static ULONG WINAPI MetadataHandlerEnum_AddRef(IWICEnumMetadataItem *iface)
static HRESULT WINAPI MetadataHandler_GetMetadataHandlerInfo(IWICMetadataWriter *iface, IWICMetadataHandlerInfo **ppIHandler)
GLuint index
Definition: glext.h:6031
#define debugstr_guid
Definition: kernel32.h:35
static HRESULT WINAPI MetadataHandler_SetValueByIndex(IWICMetadataWriter *iface, UINT nIndex, const PROPVARIANT *pvarSchema, const PROPVARIANT *pvarId, const PROPVARIANT *pvarValue)
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
LONG value
HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo)
Definition: info.c:2075
#define SWAP_ULONG(x)
HRESULT WINAPI PropVariantCopy(PROPVARIANT *pvarDest, const PROPVARIANT *pvarSrc)
Definition: ole2.c:3068
#define SEEK_SET
Definition: jmemansi.c:26
MetadataItem * items
#define TRACE(s)
Definition: solgame.cpp:4
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
MetadataHandler * parent
r parent
Definition: btrfs.c:2708
if(!(yy_init))
Definition: macro.lex.yy.c:714
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
static HRESULT WINAPI MetadataHandlerEnum_Skip(IWICEnumMetadataItem *iface, ULONG celt)
static HRESULT WINAPI MetadataHandlerEnum_QueryInterface(IWICEnumMetadataItem *iface, REFIID iid, void **ppv)
LONG HRESULT
Definition: typedefs.h:77
static HRESULT WINAPI MetadataHandlerEnum_Reset(IWICEnumMetadataItem *iface)
static ULONG WINAPI MetadataHandler_PersistStream_AddRef(IWICPersistStream *iface)
uint64_t ULONGLONG
Definition: typedefs.h:65
const GUID IID_IUnknown
#define IFD_UNDEFINED
#define WINAPI
Definition: msvc.h:8
static HRESULT WINAPI MetadataHandler_GetValue(IWICMetadataWriter *iface, const PROPVARIANT *schema, const PROPVARIANT *id, PROPVARIANT *value)
unsigned long DWORD
Definition: ntddk_ex.h:95
static HRESULT WINAPI MetadataHandlerEnum_Clone(IWICEnumMetadataItem *iface, IWICEnumMetadataItem **ppIEnumMetadataItem)
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
static HRESULT WINAPI MetadataHandler_GetSizeMax(IWICPersistStream *iface, ULARGE_INTEGER *pcbSize)
const GUID IID_IPersistStream
Definition: proxy.cpp:13
static HRESULT LoadIfdMetadata(IStream *input, const GUID *preferred_vendor, DWORD persist_options, MetadataItem **items, DWORD *item_count)
#define IFD_RATIONAL
#define SWAP_USHORT(x)
Definition: compat.h:1940
#define index(s, c)
Definition: various.h:29
static ULONG WINAPI MetadataHandlerEnum_Release(IWICEnumMetadataItem *iface)
#define InterlockedDecrement
Definition: armddk.h:52
#define IFD_SBYTE
Definition: stat.h:55
static MetadataHandler * impl_from_IWICMetadataWriter(IWICMetadataWriter *iface)
uint32_t entry
Definition: isohybrid.c:63
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
unsigned char BYTE
Definition: mem.h:68
static ULONG WINAPI MetadataHandler_PersistStream_Release(IWICPersistStream *iface)
CRITICAL_SECTION lock
GLsizei const GLfloat * value
Definition: glext.h:6069
static HRESULT WINAPI MetadataHandler_LoadEx(IWICPersistStream *iface, IStream *pIStream, const GUID *pguidPreferredVendor, DWORD dwPersistOptions)
static MetadataHandlerEnum * impl_from_IWICEnumMetadataItem(IWICEnumMetadataItem *iface)
static HRESULT load_IFD_entry(IStream *input, const struct IFD_entry *entry, MetadataItem *item, BOOL native_byte_order)
static HRESULT WINAPI MetadataHandler_GetEnumerator(IWICMetadataWriter *iface, IWICEnumMetadataItem **ppIEnumMetadata)
HRESULT UnknownMetadataReader_CreateInstance(REFIID iid, void **ppv)
_CRTIMP int __cdecl stat(const char *_Filename, struct stat *_Stat)
Definition: stat.h:345
#define S_OK
Definition: intsafe.h:59
#define InterlockedIncrement
Definition: armddk.h:53
static ATOM item
Definition: dde.c:856
GLenum GLenum GLenum input
Definition: glext.h:9031
static MetadataHandler * impl_from_IWICPersistStream(IWICPersistStream *iface)
unsigned short USHORT
Definition: pedump.c:61
static HRESULT WINAPI MetadataHandler_RemoveValueByIndex(IWICMetadataWriter *iface, UINT nIndex)
#define E_NOTIMPL
Definition: ddrawi.h:99
#define IFD_SHORT
#define min(a, b)
Definition: monoChain.cc:55
static HRESULT WINAPI MetadataHandler_GetCount(IWICMetadataWriter *iface, UINT *pcCount)
static HRESULT WINAPI MetadataHandler_QueryInterface(IWICMetadataWriter *iface, REFIID iid, void **ppv)
unsigned int UINT
Definition: ndis.h:50
#define IFD_BYTE
static HRESULT WINAPI MetadataHandler_PersistStream_QueryInterface(IWICPersistStream *iface, REFIID iid, void **ppv)
#define IFD_ASCII
const WCHAR * schema
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
static const IWICEnumMetadataItemVtbl MetadataHandlerEnum_Vtbl
IWICMetadataWriter IWICMetadataWriter_iface
unsigned int ULONG
Definition: retypes.h:1
IWICEnumMetadataItem IWICEnumMetadataItem_iface
static HRESULT WINAPI MetadataHandler_Load(IWICPersistStream *iface, IStream *pStm)
static ULONG WINAPI MetadataHandler_AddRef(IWICMetadataWriter *iface)
#define WINCODEC_ERR_PROPERTYNOTFOUND
Definition: winerror.h:3279
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
HRESULT IfdMetadataReader_CreateInstance(REFIID iid, void **ppv)
static TCHAR * items[]
Definition: page1.c:45
GLuint64EXT * result
Definition: glext.h:11304
#define IFD_SLONG
static void MetadataHandler_FreeItems(MetadataHandler *This)
#define HeapFree(x, y, z)
Definition: compat.h:394
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:90
Definition: compat.h:1941
Definition: compat.h:1938
#define SUCCEEDED(hr)
Definition: intsafe.h:57
SHORT type
char * tag
Definition: main.c:59