ReactOS 0.4.16-dev-980-g00983aa
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 <stdarg.h>
21#include <stdio.h>
22
23#define COBJMACROS
24#include "windef.h"
25#include "winbase.h"
26#include "winternl.h"
27#include "objbase.h"
28#include "propvarutil.h"
29
30#include "wincodecs_private.h"
31
32#include "wine/debug.h"
33
35
36typedef struct MetadataHandler {
46
48{
49 return CONTAINING_RECORD(iface, MetadataHandler, IWICMetadataWriter_iface);
50}
51
53{
54 return CONTAINING_RECORD(iface, MetadataHandler, IWICPersistStream_iface);
55}
56
58{
59 return CONTAINING_RECORD(iface, MetadataHandler, IWICStreamProvider_iface);
60}
61
63{
64 DWORD i;
65
66 for (i=0; i<This->item_count; i++)
67 {
68 PropVariantClear(&This->items[i].schema);
69 PropVariantClear(&This->items[i].id);
70 PropVariantClear(&This->items[i].value);
71 }
72
73 free(This->items);
74 This->items = NULL;
75 This->item_count = 0;
76}
77
79 IWICEnumMetadataItem **ppIEnumMetadataItem);
80
82 void **ppv)
83{
85 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
86
87 if (!ppv) return E_INVALIDARG;
88
89 if (IsEqualIID(&IID_IUnknown, iid) ||
90 IsEqualIID(&IID_IWICMetadataReader, iid) ||
91 (IsEqualIID(&IID_IWICMetadataWriter, iid) && This->vtable->is_writer))
92 {
93 *ppv = &This->IWICMetadataWriter_iface;
94 }
95 else if (IsEqualIID(&IID_IPersist, iid) ||
97 IsEqualIID(&IID_IWICPersistStream, iid))
98 {
99 *ppv = &This->IWICPersistStream_iface;
100 }
101 else if (IsEqualIID(&IID_IWICStreamProvider, iid))
102 {
103 *ppv = &This->IWICStreamProvider_iface;
104 }
105 else
106 {
107 *ppv = NULL;
108 return E_NOINTERFACE;
109 }
110
111 IUnknown_AddRef((IUnknown*)*ppv);
112 return S_OK;
113}
114
116{
119
120 TRACE("(%p) refcount=%lu\n", iface, ref);
121
122 return ref;
123}
124
126{
129
130 TRACE("(%p) refcount=%lu\n", iface, ref);
131
132 if (ref == 0)
133 {
135 This->lock.DebugInfo->Spare[0] = 0;
137 free(This);
138 }
139
140 return ref;
141}
142
144 IWICMetadataHandlerInfo **ppIHandler)
145{
146 HRESULT hr;
147 IWICComponentInfo *component_info;
149
150 TRACE("%p,%p\n", iface, ppIHandler);
151
152 hr = CreateComponentInfo(This->vtable->clsid, &component_info);
153 if (FAILED(hr)) return hr;
154
155 hr = IWICComponentInfo_QueryInterface(component_info, &IID_IWICMetadataHandlerInfo,
156 (void **)ppIHandler);
157
158 IWICComponentInfo_Release(component_info);
159 return hr;
160}
161
163 GUID *pguidMetadataFormat)
164{
165 HRESULT hr;
166 IWICMetadataHandlerInfo *metadata_info;
167
168 TRACE("%p,%p\n", iface, pguidMetadataFormat);
169
170 if (!pguidMetadataFormat) return E_INVALIDARG;
171
172 hr = MetadataHandler_GetMetadataHandlerInfo(iface, &metadata_info);
173 if (FAILED(hr)) return hr;
174
175 hr = IWICMetadataHandlerInfo_GetMetadataFormat(metadata_info, pguidMetadataFormat);
176 IWICMetadataHandlerInfo_Release(metadata_info);
177
178 return hr;
179}
180
182 UINT *pcCount)
183{
185
186 TRACE("%p,%p\n", iface, pcCount);
187
188 if (!pcCount) return E_INVALIDARG;
189
190 *pcCount = This->item_count;
191 return S_OK;
192}
193
195 UINT index, PROPVARIANT *schema, PROPVARIANT *id, PROPVARIANT *value)
196{
197 HRESULT hr = S_OK;
199
200 TRACE("%p,%u,%p,%p,%p\n", iface, index, schema, id, value);
201
203
204 if (index >= This->item_count)
205 {
207 return E_INVALIDARG;
208 }
209
210 if (schema)
211 hr = PropVariantCopy(schema, &This->items[index].schema);
212
213 if (SUCCEEDED(hr) && id)
214 hr = PropVariantCopy(id, &This->items[index].id);
215
216 if (SUCCEEDED(hr) && value)
217 hr = PropVariantCopy(value, &This->items[index].value);
218
220 return hr;
221}
222
224 const PROPVARIANT *schema, const PROPVARIANT *id, PROPVARIANT *value)
225{
226 UINT i;
229
230 TRACE("(%p,%s,%s,%p)\n", iface, wine_dbgstr_variant((const VARIANT *)schema), wine_dbgstr_variant((const VARIANT *)id), value);
231
232 if (!id) return E_INVALIDARG;
233
235
236 for (i = 0; i < This->item_count; i++)
237 {
238 if (schema && This->items[i].schema.vt != VT_EMPTY)
239 {
240 if (PropVariantCompareEx(schema, &This->items[i].schema, 0, PVCF_USESTRCMPI) != 0) continue;
241 }
242
243 if (PropVariantCompareEx(id, &This->items[i].id, 0, PVCF_USESTRCMPI) != 0) continue;
244
245 hr = value ? PropVariantCopy(value, &This->items[i].value) : S_OK;
246 break;
247 }
248
250 return hr;
251}
252
254 IWICEnumMetadataItem **ppIEnumMetadata)
255{
257 TRACE("(%p,%p)\n", iface, ppIEnumMetadata);
258 return MetadataHandlerEnum_Create(This, 0, ppIEnumMetadata);
259}
260
262 const PROPVARIANT *pvarSchema, const PROPVARIANT *pvarId, const PROPVARIANT *pvarValue)
263{
264 FIXME("(%p,%p,%p,%p): stub\n", iface, pvarSchema, pvarId, pvarValue);
265 return E_NOTIMPL;
266}
267
269 UINT nIndex, const PROPVARIANT *pvarSchema, const PROPVARIANT *pvarId, const PROPVARIANT *pvarValue)
270{
271 FIXME("(%p,%u,%p,%p,%p): stub\n", iface, nIndex, pvarSchema, pvarId, pvarValue);
272 return E_NOTIMPL;
273}
274
276 const PROPVARIANT *pvarSchema, const PROPVARIANT *pvarId)
277{
278 FIXME("(%p,%p,%p): stub\n", iface, pvarSchema, pvarId);
279 return E_NOTIMPL;
280}
281
283 UINT nIndex)
284{
285 FIXME("(%p,%u): stub\n", iface, nIndex);
286 return E_NOTIMPL;
287}
288
289static const IWICMetadataWriterVtbl MetadataHandler_Vtbl = {
303};
304
306 REFIID iid, void **ppv)
307{
309 return IWICMetadataWriter_QueryInterface(&This->IWICMetadataWriter_iface, iid, ppv);
310}
311
313{
315 return IWICMetadataWriter_AddRef(&This->IWICMetadataWriter_iface);
316}
317
319{
321 return IWICMetadataWriter_Release(&This->IWICMetadataWriter_iface);
322}
323
325 CLSID *pClassID)
326{
327 FIXME("(%p,%p): stub\n", iface, pClassID);
328 return E_NOTIMPL;
329}
330
332{
333 FIXME("(%p): stub\n", iface);
334 return E_NOTIMPL;
335}
336
338 IStream *pStm)
339{
341 TRACE("(%p,%p)\n", iface, pStm);
342 return IWICPersistStream_LoadEx(&This->IWICPersistStream_iface, pStm, NULL, WICPersistOptionDefault);
343}
344
346 IStream *pStm, BOOL fClearDirty)
347{
348 FIXME("(%p,%p,%i): stub\n", iface, pStm, fClearDirty);
349 return E_NOTIMPL;
350}
351
353 ULARGE_INTEGER *pcbSize)
354{
355 FIXME("(%p,%p): stub\n", iface, pcbSize);
356 return E_NOTIMPL;
357}
358
360 IStream *stream, const GUID *pguidPreferredVendor, DWORD dwPersistOptions)
361{
363 HRESULT hr = S_OK;
364 MetadataItem *new_items=NULL;
365 DWORD item_count=0;
366
367 TRACE("(%p,%p,%s,%lx)\n", iface, stream, debugstr_guid(pguidPreferredVendor), dwPersistOptions);
368
370
371 if (stream)
372 {
373 hr = This->vtable->fnLoad(stream, pguidPreferredVendor, dwPersistOptions,
374 &new_items, &item_count);
375 }
376
377 if (SUCCEEDED(hr))
378 {
380 This->items = new_items;
381 This->item_count = item_count;
382 }
383
385
386 return hr;
387}
388
390 IStream *pIStream, DWORD dwPersistOptions, BOOL fClearDirty)
391{
392 FIXME("(%p,%p,%lx,%i): stub\n", iface, pIStream, dwPersistOptions, fClearDirty);
393 return E_NOTIMPL;
394}
395
396static const IWICPersistStreamVtbl MetadataHandler_PersistStream_Vtbl = {
407};
408
410{
412 return IWICMetadataWriter_QueryInterface(&handler->IWICMetadataWriter_iface, iid, ppv);
413}
414
416{
418 return IWICMetadataWriter_AddRef(&handler->IWICMetadataWriter_iface);
419}
420
422{
424 return IWICMetadataWriter_Release(&handler->IWICMetadataWriter_iface);
425}
426
428{
429 FIXME("%p, %p stub\n", iface, stream);
430
431 return E_NOTIMPL;
432}
433
435{
436 FIXME("%p, %p stub\n", iface, options);
437
438 return E_NOTIMPL;
439}
440
442{
443 FIXME("%p, %p stub\n", iface, guid);
444
445 return E_NOTIMPL;
446}
447
449{
450 FIXME("%p stub\n", iface);
451
452 return E_NOTIMPL;
453}
454
455static const IWICStreamProviderVtbl MetadataHandler_StreamProvider_Vtbl =
456{
464};
465
467{
469 HRESULT hr;
470
471 TRACE("%s\n", debugstr_guid(vtable->clsid));
472
473 *ppv = NULL;
474
475 This = malloc(sizeof(MetadataHandler));
476 if (!This) return E_OUTOFMEMORY;
477
478 This->IWICMetadataWriter_iface.lpVtbl = &MetadataHandler_Vtbl;
479 This->IWICPersistStream_iface.lpVtbl = &MetadataHandler_PersistStream_Vtbl;
480 This->IWICStreamProvider_iface.lpVtbl = &MetadataHandler_StreamProvider_Vtbl;
481 This->ref = 1;
482 This->vtable = vtable;
483 This->items = NULL;
484 This->item_count = 0;
485
486#ifdef __REACTOS__
488#else
490#endif
491 This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": MetadataHandler.lock");
492
493 hr = IWICMetadataWriter_QueryInterface(&This->IWICMetadataWriter_iface, iid, ppv);
494
495 IWICMetadataWriter_Release(&This->IWICMetadataWriter_iface);
496
497 return hr;
498}
499
500typedef struct MetadataHandlerEnum {
506
508{
509 return CONTAINING_RECORD(iface, MetadataHandlerEnum, IWICEnumMetadataItem_iface);
510}
511
513 void **ppv)
514{
516 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
517
518 if (!ppv) return E_INVALIDARG;
519
520 if (IsEqualIID(&IID_IUnknown, iid) ||
521 IsEqualIID(&IID_IWICEnumMetadataItem, iid))
522 {
523 *ppv = &This->IWICEnumMetadataItem_iface;
524 }
525 else
526 {
527 *ppv = NULL;
528 return E_NOINTERFACE;
529 }
530
531 IUnknown_AddRef((IUnknown*)*ppv);
532 return S_OK;
533}
534
536{
539
540 TRACE("(%p) refcount=%lu\n", iface, ref);
541
542 return ref;
543}
544
546{
549
550 TRACE("(%p) refcount=%lu\n", iface, ref);
551
552 if (ref == 0)
553 {
554 IWICMetadataWriter_Release(&This->parent->IWICMetadataWriter_iface);
555 free(This);
556 }
557
558 return ref;
559}
560
562 ULONG celt, PROPVARIANT *rgeltSchema, PROPVARIANT *rgeltId,
563 PROPVARIANT *rgeltValue, ULONG *pceltFetched)
564{
566 ULONG new_index;
568 ULONG i;
569 ULONG fetched;
570
571 TRACE("(%p,%li)\n", iface, celt);
572
573 if (!pceltFetched)
574 pceltFetched = &fetched;
575
576 EnterCriticalSection(&This->parent->lock);
577
578 if (This->index >= This->parent->item_count)
579 {
580 *pceltFetched = 0;
581 LeaveCriticalSection(&This->parent->lock);
582 return S_FALSE;
583 }
584
585 new_index = min(This->parent->item_count, This->index + celt);
586 *pceltFetched = new_index - This->index;
587
588 if (rgeltSchema)
589 {
590 for (i=0; SUCCEEDED(hr) && i < *pceltFetched; i++)
591 hr = PropVariantCopy(&rgeltSchema[i], &This->parent->items[i+This->index].schema);
592 }
593
594 for (i=0; SUCCEEDED(hr) && i < *pceltFetched; i++)
595 hr = PropVariantCopy(&rgeltId[i], &This->parent->items[i+This->index].id);
596
597 if (rgeltValue)
598 {
599 for (i=0; SUCCEEDED(hr) && i < *pceltFetched; i++)
600 hr = PropVariantCopy(&rgeltValue[i], &This->parent->items[i+This->index].value);
601 }
602
603 if (SUCCEEDED(hr))
604 {
605 This->index = new_index;
606 }
607
608 LeaveCriticalSection(&This->parent->lock);
609
610 return hr;
611}
612
614 ULONG celt)
615{
617
618 EnterCriticalSection(&This->parent->lock);
619
620 This->index += celt;
621
622 LeaveCriticalSection(&This->parent->lock);
623
624 return S_OK;
625}
626
628{
630
631 EnterCriticalSection(&This->parent->lock);
632
633 This->index = 0;
634
635 LeaveCriticalSection(&This->parent->lock);
636
637 return S_OK;
638}
639
641 IWICEnumMetadataItem **ppIEnumMetadataItem)
642{
644 HRESULT hr;
645
646 EnterCriticalSection(&This->parent->lock);
647
648 hr = MetadataHandlerEnum_Create(This->parent, This->index, ppIEnumMetadataItem);
649
650 LeaveCriticalSection(&This->parent->lock);
651
652 return hr;
653}
654
655static const IWICEnumMetadataItemVtbl MetadataHandlerEnum_Vtbl = {
663};
664
666 IWICEnumMetadataItem **ppIEnumMetadataItem)
667{
669
670 if (!ppIEnumMetadataItem) return E_INVALIDARG;
671
672 *ppIEnumMetadataItem = NULL;
673
675 if (!This) return E_OUTOFMEMORY;
676
677 IWICMetadataWriter_AddRef(&parent->IWICMetadataWriter_iface);
678
679 This->IWICEnumMetadataItem_iface.lpVtbl = &MetadataHandlerEnum_Vtbl;
680 This->ref = 1;
681 This->parent = parent;
682 This->index = index;
683
684 *ppIEnumMetadataItem = &This->IWICEnumMetadataItem_iface;
685
686 return S_OK;
687}
688
689static HRESULT LoadUnknownMetadata(IStream *input, const GUID *preferred_vendor,
690 DWORD persist_options, MetadataItem **items, DWORD *item_count)
691{
692 HRESULT hr;
694 STATSTG stat;
695 BYTE *data;
696 ULONG bytesread;
697
698 TRACE("\n");
699
700 hr = IStream_Stat(input, &stat, STATFLAG_NONAME);
701 if (FAILED(hr))
702 return hr;
703
704 data = CoTaskMemAlloc(stat.cbSize.QuadPart);
705 if (!data) return E_OUTOFMEMORY;
706
707 hr = IStream_Read(input, data, stat.cbSize.QuadPart, &bytesread);
708 if (bytesread != stat.cbSize.QuadPart) hr = E_FAIL;
709 if (hr != S_OK)
710 {
712 return hr;
713 }
714
715 result = calloc(1, sizeof(MetadataItem));
716 if (!result)
717 {
719 return E_OUTOFMEMORY;
720 }
721
722 PropVariantInit(&result[0].schema);
723 PropVariantInit(&result[0].id);
724 PropVariantInit(&result[0].value);
725
726 result[0].value.vt = VT_BLOB;
727 result[0].value.blob.cbSize = bytesread;
728 result[0].value.blob.pBlobData = data;
729
730 *items = result;
731 *item_count = 1;
732
733 return S_OK;
734}
735
737 0,
738 &CLSID_WICUnknownMetadataReader,
740};
741
743{
745}
746
747#define SWAP_USHORT(x) do { if (!native_byte_order) (x) = RtlUshortByteSwap(x); } while(0)
748#define SWAP_ULONG(x) do { if (!native_byte_order) (x) = RtlUlongByteSwap(x); } while(0)
749#define SWAP_ULONGLONG(x) do { if (!native_byte_order) (x) = RtlUlonglongByteSwap(x); } while(0)
750
752{
757};
758
759#define IFD_BYTE 1
760#define IFD_ASCII 2
761#define IFD_SHORT 3
762#define IFD_LONG 4
763#define IFD_RATIONAL 5
764#define IFD_SBYTE 6
765#define IFD_UNDEFINED 7
766#define IFD_SSHORT 8
767#define IFD_SLONG 9
768#define IFD_SRATIONAL 10
769#define IFD_FLOAT 11
770#define IFD_DOUBLE 12
771#define IFD_IFD 13
772
773static int tag_to_vt(SHORT tag)
774{
775 static const int tag2vt[] =
776 {
777 VT_EMPTY, /* 0 */
778 VT_UI1, /* IFD_BYTE 1 */
779 VT_LPSTR, /* IFD_ASCII 2 */
780 VT_UI2, /* IFD_SHORT 3 */
781 VT_UI4, /* IFD_LONG 4 */
782 VT_UI8, /* IFD_RATIONAL 5 */
783 VT_I1, /* IFD_SBYTE 6 */
784 VT_BLOB, /* IFD_UNDEFINED 7 */
785 VT_I2, /* IFD_SSHORT 8 */
786 VT_I4, /* IFD_SLONG 9 */
787 VT_I8, /* IFD_SRATIONAL 10 */
788 VT_R4, /* IFD_FLOAT 11 */
789 VT_R8, /* IFD_DOUBLE 12 */
790 VT_BLOB, /* IFD_IFD 13 */
791 };
792 return (tag > 0 && tag <= 13) ? tag2vt[tag] : VT_BLOB;
793}
794
796 MetadataItem *item, BOOL native_byte_order)
797{
798 ULONG count, value, i, bytesread;
799 SHORT type;
801 HRESULT hr;
802
803 item->schema.vt = VT_EMPTY;
804 item->id.vt = VT_UI2;
805 item->id.uiVal = entry->id;
806 SWAP_USHORT(item->id.uiVal);
807
808 count = entry->count;
810 type = entry->type;
812 item->value.vt = tag_to_vt(type);
813 value = entry->value;
815
816 switch (type)
817 {
818 case IFD_BYTE:
819 case IFD_SBYTE:
820 if (!count) count = 1;
821
822 if (count <= 4)
823 {
824 const BYTE *data = (const BYTE *)&entry->value;
825
826 if (count == 1)
827 item->value.bVal = data[0];
828 else
829 {
830 item->value.vt |= VT_VECTOR;
831 item->value.caub.cElems = count;
832 item->value.caub.pElems = CoTaskMemAlloc(count);
833 memcpy(item->value.caub.pElems, data, count);
834 }
835 break;
836 }
837
838 item->value.vt |= VT_VECTOR;
839 item->value.caub.cElems = count;
840 item->value.caub.pElems = CoTaskMemAlloc(count);
841 if (!item->value.caub.pElems) return E_OUTOFMEMORY;
842
843 pos.QuadPart = value;
844 hr = IStream_Seek(input, pos, SEEK_SET, NULL);
845 if (FAILED(hr))
846 {
847 CoTaskMemFree(item->value.caub.pElems);
848 return hr;
849 }
850 hr = IStream_Read(input, item->value.caub.pElems, count, &bytesread);
851 if (bytesread != count) hr = E_FAIL;
852 if (hr != S_OK)
853 {
854 CoTaskMemFree(item->value.caub.pElems);
855 return hr;
856 }
857 break;
858 case IFD_SHORT:
859 case IFD_SSHORT:
860 if (!count) count = 1;
861
862 if (count <= 2)
863 {
864 const SHORT *data = (const SHORT *)&entry->value;
865
866 if (count == 1)
867 {
868 item->value.uiVal = data[0];
869 SWAP_USHORT(item->value.uiVal);
870 }
871 else
872 {
873 item->value.vt |= VT_VECTOR;
874 item->value.caui.cElems = count;
875 item->value.caui.pElems = CoTaskMemAlloc(count * 2);
876 memcpy(item->value.caui.pElems, data, count * 2);
877 for (i = 0; i < count; i++)
878 SWAP_USHORT(item->value.caui.pElems[i]);
879 }
880 break;
881 }
882
883 item->value.vt |= VT_VECTOR;
884 item->value.caui.cElems = count;
885 item->value.caui.pElems = CoTaskMemAlloc(count * 2);
886 if (!item->value.caui.pElems) return E_OUTOFMEMORY;
887
888 pos.QuadPart = value;
889 hr = IStream_Seek(input, pos, SEEK_SET, NULL);
890 if (FAILED(hr))
891 {
892 CoTaskMemFree(item->value.caui.pElems);
893 return hr;
894 }
895 hr = IStream_Read(input, item->value.caui.pElems, count * 2, &bytesread);
896 if (bytesread != count * 2) hr = E_FAIL;
897 if (hr != S_OK)
898 {
899 CoTaskMemFree(item->value.caui.pElems);
900 return hr;
901 }
902 for (i = 0; i < count; i++)
903 SWAP_USHORT(item->value.caui.pElems[i]);
904 break;
905 case IFD_LONG:
906 case IFD_SLONG:
907 case IFD_FLOAT:
908 if (!count) count = 1;
909
910 if (count == 1)
911 {
912 item->value.ulVal = value;
913 break;
914 }
915
916 item->value.vt |= VT_VECTOR;
917 item->value.caul.cElems = count;
918 item->value.caul.pElems = CoTaskMemAlloc(count * 4);
919 if (!item->value.caul.pElems) return E_OUTOFMEMORY;
920
921 pos.QuadPart = value;
922 hr = IStream_Seek(input, pos, SEEK_SET, NULL);
923 if (FAILED(hr))
924 {
925 CoTaskMemFree(item->value.caul.pElems);
926 return hr;
927 }
928 hr = IStream_Read(input, item->value.caul.pElems, count * 4, &bytesread);
929 if (bytesread != count * 4) hr = E_FAIL;
930 if (hr != S_OK)
931 {
932 CoTaskMemFree(item->value.caul.pElems);
933 return hr;
934 }
935 for (i = 0; i < count; i++)
936 SWAP_ULONG(item->value.caul.pElems[i]);
937 break;
938 case IFD_RATIONAL:
939 case IFD_SRATIONAL:
940 case IFD_DOUBLE:
941 if (!count)
942 {
943 FIXME("IFD field type %d, count 0\n", type);
944 item->value.vt = VT_EMPTY;
945 break;
946 }
947
948 if (count == 1)
949 {
950 ULONGLONG ull;
951
952 pos.QuadPart = value;
953 hr = IStream_Seek(input, pos, SEEK_SET, NULL);
954 if (FAILED(hr)) return hr;
955
956 hr = IStream_Read(input, &ull, sizeof(ull), &bytesread);
957 if (bytesread != sizeof(ull)) hr = E_FAIL;
958 if (hr != S_OK) return hr;
959
960 item->value.uhVal.QuadPart = ull;
961
962 if (type == IFD_DOUBLE)
963 SWAP_ULONGLONG(item->value.uhVal.QuadPart);
964 else
965 {
966 SWAP_ULONG(item->value.uhVal.LowPart);
967 SWAP_ULONG(item->value.uhVal.HighPart);
968 }
969 break;
970 }
971 else
972 {
973 item->value.vt |= VT_VECTOR;
974 item->value.cauh.cElems = count;
975 item->value.cauh.pElems = CoTaskMemAlloc(count * 8);
976 if (!item->value.cauh.pElems) return E_OUTOFMEMORY;
977
978 pos.QuadPart = value;
979 hr = IStream_Seek(input, pos, SEEK_SET, NULL);
980 if (FAILED(hr))
981 {
982 CoTaskMemFree(item->value.cauh.pElems);
983 return hr;
984 }
985 hr = IStream_Read(input, item->value.cauh.pElems, count * 8, &bytesread);
986 if (bytesread != count * 8) hr = E_FAIL;
987 if (hr != S_OK)
988 {
989 CoTaskMemFree(item->value.cauh.pElems);
990 return hr;
991 }
992 for (i = 0; i < count; i++)
993 {
994 if (type == IFD_DOUBLE)
995 SWAP_ULONGLONG(item->value.cauh.pElems[i].QuadPart);
996 else
997 {
998 SWAP_ULONG(item->value.cauh.pElems[i].LowPart);
999 SWAP_ULONG(item->value.cauh.pElems[i].HighPart);
1000 }
1001 }
1002 }
1003 break;
1004 case IFD_ASCII:
1005 item->value.pszVal = CoTaskMemAlloc(count + 1);
1006 if (!item->value.pszVal) return E_OUTOFMEMORY;
1007
1008 if (count <= 4)
1009 {
1010 const char *data = (const char *)&entry->value;
1011 memcpy(item->value.pszVal, data, count);
1012 item->value.pszVal[count] = 0;
1013 break;
1014 }
1015
1016 pos.QuadPart = value;
1017 hr = IStream_Seek(input, pos, SEEK_SET, NULL);
1018 if (FAILED(hr))
1019 {
1020 CoTaskMemFree(item->value.pszVal);
1021 return hr;
1022 }
1023 hr = IStream_Read(input, item->value.pszVal, count, &bytesread);
1024 if (bytesread != count) hr = E_FAIL;
1025 if (hr != S_OK)
1026 {
1027 CoTaskMemFree(item->value.pszVal);
1028 return hr;
1029 }
1030 item->value.pszVal[count] = 0;
1031 break;
1032 case IFD_UNDEFINED:
1033 if (!count)
1034 {
1035 FIXME("IFD field type %d, count 0\n", type);
1036 item->value.vt = VT_EMPTY;
1037 break;
1038 }
1039
1040 item->value.blob.pBlobData = CoTaskMemAlloc(count);
1041 if (!item->value.blob.pBlobData) return E_OUTOFMEMORY;
1042
1043 item->value.blob.cbSize = count;
1044
1045 if (count <= 4)
1046 {
1047 const char *data = (const char *)&entry->value;
1048 memcpy(item->value.blob.pBlobData, data, count);
1049 break;
1050 }
1051
1052 pos.QuadPart = value;
1053 hr = IStream_Seek(input, pos, SEEK_SET, NULL);
1054 if (FAILED(hr))
1055 {
1056 CoTaskMemFree(item->value.blob.pBlobData);
1057 return hr;
1058 }
1059 hr = IStream_Read(input, item->value.blob.pBlobData, count, &bytesread);
1060 if (bytesread != count) hr = E_FAIL;
1061 if (hr != S_OK)
1062 {
1063 CoTaskMemFree(item->value.blob.pBlobData);
1064 return hr;
1065 }
1066 break;
1067 default:
1068 FIXME("loading field of type %d, count %lu is not implemented\n", type, count);
1069 break;
1070 }
1071 return S_OK;
1072}
1073
1074static HRESULT LoadIfdMetadata(IStream *input, const GUID *preferred_vendor,
1075 DWORD persist_options, MetadataItem **items, DWORD *item_count)
1076{
1077 HRESULT hr;
1079 USHORT count, i;
1080 struct IFD_entry *entry;
1081 BOOL native_byte_order = TRUE;
1082 ULONG bytesread;
1083
1084 TRACE("\n");
1085
1086#ifdef WORDS_BIGENDIAN
1087 if (persist_options & WICPersistOptionLittleEndian)
1088#else
1089 if (persist_options & WICPersistOptionBigEndian)
1090#endif
1091 native_byte_order = FALSE;
1092
1093 hr = IStream_Read(input, &count, sizeof(count), &bytesread);
1094 if (bytesread != sizeof(count)) hr = E_FAIL;
1095 if (hr != S_OK) return hr;
1096
1098
1099 entry = malloc(count * sizeof(*entry));
1100 if (!entry) return E_OUTOFMEMORY;
1101
1102 hr = IStream_Read(input, entry, count * sizeof(*entry), &bytesread);
1103 if (bytesread != count * sizeof(*entry)) hr = E_FAIL;
1104 if (hr != S_OK)
1105 {
1106 free(entry);
1107 return hr;
1108 }
1109
1110 /* limit number of IFDs to 4096 to avoid infinite loop */
1111 for (i = 0; i < 4096; i++)
1112 {
1113 ULONG next_ifd_offset;
1115 USHORT next_ifd_count;
1116
1117 hr = IStream_Read(input, &next_ifd_offset, sizeof(next_ifd_offset), &bytesread);
1118 if (bytesread != sizeof(next_ifd_offset)) hr = E_FAIL;
1119 if (hr != S_OK) break;
1120
1121 SWAP_ULONG(next_ifd_offset);
1122 if (!next_ifd_offset) break;
1123
1124 pos.QuadPart = next_ifd_offset;
1125 hr = IStream_Seek(input, pos, SEEK_SET, NULL);
1126 if (FAILED(hr)) break;
1127
1128 hr = IStream_Read(input, &next_ifd_count, sizeof(next_ifd_count), &bytesread);
1129 if (bytesread != sizeof(next_ifd_count)) hr = E_FAIL;
1130 if (hr != S_OK) break;
1131
1132 SWAP_USHORT(next_ifd_count);
1133
1134 pos.QuadPart = next_ifd_count * sizeof(*entry);
1135 hr = IStream_Seek(input, pos, SEEK_CUR, NULL);
1136 if (FAILED(hr)) break;
1137 }
1138
1139 if (hr != S_OK || i == 4096)
1140 {
1141 free(entry);
1143 }
1144
1145 result = calloc(count, sizeof(*result));
1146 if (!result)
1147 {
1148 free(entry);
1149 return E_OUTOFMEMORY;
1150 }
1151
1152 for (i = 0; i < count; i++)
1153 {
1154 hr = load_IFD_entry(input, &entry[i], &result[i], native_byte_order);
1155 if (FAILED(hr))
1156 {
1157 free(entry);
1158 free(result);
1159 return hr;
1160 }
1161 }
1162
1163 free(entry);
1164
1165 *items = result;
1166 *item_count = count;
1167
1168 return S_OK;
1169}
1170
1172 0,
1173 &CLSID_WICIfdMetadataReader,
1175};
1176
1178{
1180}
1181
#define stat
Definition: acwin.h:99
#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 FIXME(fmt,...)
Definition: precomp.h:53
const GUID IID_IUnknown
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_NOTIMPL
Definition: ddrawi.h:99
#define E_FAIL
Definition: ddrawi.h:102
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
@ VT_BLOB
Definition: compat.h:2330
@ VT_UI8
Definition: compat.h:2315
@ VT_LPSTR
Definition: compat.h:2324
@ VT_R4
Definition: compat.h:2299
@ VT_UI2
Definition: compat.h:2312
@ 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_I2
Definition: compat.h:2297
@ VT_UI4
Definition: compat.h:2313
@ VT_EMPTY
Definition: compat.h:2295
@ VT_VECTOR
Definition: compat.h:2340
@ VT_UI1
Definition: compat.h:2311
BOOL WINAPI InitializeCriticalSectionEx(OUT LPCRITICAL_SECTION lpCriticalSection, IN DWORD dwSpinCount, IN DWORD flags)
Definition: sync.c:107
UINT(* handler)(MSIPACKAGE *)
Definition: action.c:7512
HRESULT WINAPI PropVariantClear(PROPVARIANT *pvar)
Definition: ole2.c:2968
HRESULT WINAPI PropVariantCopy(PROPVARIANT *pvarDest, const PROPVARIANT *pvarSrc)
Definition: ole2.c:3086
INT WINAPI PropVariantCompareEx(REFPROPVARIANT propvar1, REFPROPVARIANT propvar2, PROPVAR_COMPARE_UNIT unit, PROPVAR_COMPARE_FLAGS flags)
Definition: propvar.c:961
HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo)
Definition: info.c:2030
r parent
Definition: btrfs.c:3010
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLuint index
Definition: glext.h:6031
GLuint64EXT * result
Definition: glext.h:11304
GLenum GLenum GLenum input
Definition: glext.h:9031
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
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:442
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:426
REFIID LPVOID * ppv
Definition: atlbase.h:39
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
uint32_t entry
Definition: isohybrid.c:63
#define SEEK_SET
Definition: jmemansi.c:26
#define debugstr_guid
Definition: kernel32.h:35
if(dx< 0)
Definition: linetemp.h:194
#define SWAP_USHORT(x)
#define SWAP_ULONGLONG(x)
static MetadataHandler * impl_from_IWICStreamProvider(IWICStreamProvider *iface)
static MetadataHandler * impl_from_IWICMetadataWriter(IWICMetadataWriter *iface)
static const IWICStreamProviderVtbl MetadataHandler_StreamProvider_Vtbl
static HRESULT WINAPI metadatahandler_stream_provider_GetPreferredVendorGUID(IWICStreamProvider *iface, GUID *guid)
static HRESULT WINAPI MetadataHandlerEnum_Reset(IWICEnumMetadataItem *iface)
static HRESULT WINAPI MetadataHandlerEnum_Next(IWICEnumMetadataItem *iface, ULONG celt, PROPVARIANT *rgeltSchema, PROPVARIANT *rgeltId, PROPVARIANT *rgeltValue, ULONG *pceltFetched)
static HRESULT WINAPI metadatahandler_stream_provider_GetStream(IWICStreamProvider *iface, IStream **stream)
HRESULT MetadataReader_Create(const MetadataHandlerVtbl *vtable, REFIID iid, void **ppv)
#define IFD_BYTE
static HRESULT WINAPI MetadataHandler_SaveEx(IWICPersistStream *iface, IStream *pIStream, DWORD dwPersistOptions, BOOL fClearDirty)
static HRESULT LoadIfdMetadata(IStream *input, const GUID *preferred_vendor, DWORD persist_options, MetadataItem **items, DWORD *item_count)
#define IFD_SBYTE
static const IWICEnumMetadataItemVtbl MetadataHandlerEnum_Vtbl
static HRESULT WINAPI MetadataHandler_PersistStream_QueryInterface(IWICPersistStream *iface, REFIID iid, void **ppv)
static ULONG WINAPI MetadataHandlerEnum_AddRef(IWICEnumMetadataItem *iface)
static const MetadataHandlerVtbl UnknownMetadataReader_Vtbl
static HRESULT WINAPI MetadataHandler_RemoveValue(IWICMetadataWriter *iface, const PROPVARIANT *pvarSchema, const PROPVARIANT *pvarId)
static HRESULT WINAPI MetadataHandler_GetValue(IWICMetadataWriter *iface, const PROPVARIANT *schema, const PROPVARIANT *id, PROPVARIANT *value)
#define IFD_UNDEFINED
static HRESULT WINAPI MetadataHandlerEnum_Clone(IWICEnumMetadataItem *iface, IWICEnumMetadataItem **ppIEnumMetadataItem)
static HRESULT WINAPI MetadataHandler_QueryInterface(IWICMetadataWriter *iface, REFIID iid, void **ppv)
static HRESULT load_IFD_entry(IStream *input, const struct IFD_entry *entry, MetadataItem *item, BOOL native_byte_order)
static const MetadataHandlerVtbl IfdMetadataReader_Vtbl
static HRESULT WINAPI metadatahandler_stream_provider_QueryInterface(IWICStreamProvider *iface, REFIID iid, void **ppv)
static HRESULT WINAPI MetadataHandler_GetValueByIndex(IWICMetadataWriter *iface, UINT index, PROPVARIANT *schema, PROPVARIANT *id, PROPVARIANT *value)
static ULONG WINAPI metadatahandler_stream_provider_AddRef(IWICStreamProvider *iface)
static void MetadataHandler_FreeItems(MetadataHandler *This)
static HRESULT WINAPI MetadataHandler_GetClassID(IWICPersistStream *iface, CLSID *pClassID)
static int tag_to_vt(SHORT tag)
static HRESULT WINAPI MetadataHandler_Save(IWICPersistStream *iface, IStream *pStm, BOOL fClearDirty)
#define IFD_SRATIONAL
static HRESULT WINAPI MetadataHandlerEnum_QueryInterface(IWICEnumMetadataItem *iface, REFIID iid, void **ppv)
static ULONG WINAPI MetadataHandlerEnum_Release(IWICEnumMetadataItem *iface)
static MetadataHandlerEnum * impl_from_IWICEnumMetadataItem(IWICEnumMetadataItem *iface)
static HRESULT WINAPI metadatahandler_stream_provider_RefreshStream(IWICStreamProvider *iface)
#define IFD_SLONG
#define IFD_SHORT
static const IWICPersistStreamVtbl MetadataHandler_PersistStream_Vtbl
static HRESULT WINAPI MetadataHandler_GetCount(IWICMetadataWriter *iface, UINT *pcCount)
#define IFD_SSHORT
static const IWICMetadataWriterVtbl MetadataHandler_Vtbl
static MetadataHandler * impl_from_IWICPersistStream(IWICPersistStream *iface)
static ULONG WINAPI MetadataHandler_Release(IWICMetadataWriter *iface)
HRESULT IfdMetadataReader_CreateInstance(REFIID iid, void **ppv)
static HRESULT WINAPI MetadataHandler_IsDirty(IWICPersistStream *iface)
static HRESULT WINAPI MetadataHandler_GetEnumerator(IWICMetadataWriter *iface, IWICEnumMetadataItem **ppIEnumMetadata)
static HRESULT WINAPI metadatahandler_stream_provider_GetPersistOptions(IWICStreamProvider *iface, DWORD *options)
static HRESULT WINAPI MetadataHandler_RemoveValueByIndex(IWICMetadataWriter *iface, UINT nIndex)
static ULONG WINAPI metadatahandler_stream_provider_Release(IWICStreamProvider *iface)
#define IFD_DOUBLE
static HRESULT WINAPI MetadataHandler_LoadEx(IWICPersistStream *iface, IStream *stream, const GUID *pguidPreferredVendor, DWORD dwPersistOptions)
#define SWAP_ULONG(x)
static ULONG WINAPI MetadataHandler_AddRef(IWICMetadataWriter *iface)
static HRESULT WINAPI MetadataHandlerEnum_Skip(IWICEnumMetadataItem *iface, ULONG celt)
static HRESULT WINAPI MetadataHandler_SetValue(IWICMetadataWriter *iface, const PROPVARIANT *pvarSchema, const PROPVARIANT *pvarId, const PROPVARIANT *pvarValue)
static HRESULT MetadataHandlerEnum_Create(MetadataHandler *parent, DWORD index, IWICEnumMetadataItem **ppIEnumMetadataItem)
static HRESULT WINAPI MetadataHandler_SetValueByIndex(IWICMetadataWriter *iface, UINT nIndex, const PROPVARIANT *pvarSchema, const PROPVARIANT *pvarId, const PROPVARIANT *pvarValue)
static HRESULT WINAPI MetadataHandler_Load(IWICPersistStream *iface, IStream *pStm)
static ULONG WINAPI MetadataHandler_PersistStream_AddRef(IWICPersistStream *iface)
#define IFD_RATIONAL
static HRESULT WINAPI MetadataHandler_GetMetadataHandlerInfo(IWICMetadataWriter *iface, IWICMetadataHandlerInfo **ppIHandler)
static HRESULT WINAPI MetadataHandler_GetMetadataFormat(IWICMetadataWriter *iface, GUID *pguidMetadataFormat)
static ULONG WINAPI MetadataHandler_PersistStream_Release(IWICPersistStream *iface)
HRESULT UnknownMetadataReader_CreateInstance(REFIID iid, void **ppv)
static HRESULT WINAPI MetadataHandler_GetSizeMax(IWICPersistStream *iface, ULARGE_INTEGER *pcbSize)
#define IFD_ASCII
#define IFD_LONG
static HRESULT LoadUnknownMetadata(IStream *input, const GUID *preferred_vendor, DWORD persist_options, MetadataItem **items, DWORD *item_count)
#define IFD_FLOAT
const WCHAR * schema
const GUID * guid
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define SEEK_CUR
Definition: util.h:63
static void * vtable[]
Definition: typelib.c:1231
static ATOM item
Definition: dde.c:856
#define min(a, b)
Definition: monoChain.cc:55
unsigned int UINT
Definition: ndis.h:50
static TCHAR * items[]
Definition: page1.c:45
short SHORT
Definition: pedump.c:59
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
@ PVCF_USESTRCMPI
Definition: propvarutil.h:70
const GUID IID_IPersist
Definition: proxy.cpp:14
const GUID IID_IPersistStream
Definition: proxy.cpp:13
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define REFIID
Definition: guiddef.h:118
#define calloc
Definition: rosglue.h:14
HRESULT hr
Definition: shlfolder.c:183
#define TRACE(s)
Definition: solgame.cpp:4
LONG value
SHORT id
SHORT type
ULONG count
IWICEnumMetadataItem IWICEnumMetadataItem_iface
MetadataHandler * parent
MetadataItem * items
IWICPersistStream IWICPersistStream_iface
IWICStreamProvider IWICStreamProvider_iface
CRITICAL_SECTION lock
IWICMetadataWriter IWICMetadataWriter_iface
const MetadataHandlerVtbl * vtable
Definition: send.c:48
Definition: stat.h:55
Definition: parse.h:23
Definition: ecma_167.h:138
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
#define DWORD_PTR
Definition: treelist.c:76
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
Definition: pdh_main.c:96
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
@ WICPersistOptionBigEndian
Definition: wincodecsdk.idl:25
@ WICPersistOptionDefault
Definition: wincodecsdk.idl:23
@ WICPersistOptionLittleEndian
Definition: wincodecsdk.idl:24
#define WINAPI
Definition: msvc.h:6
#define S_FALSE
Definition: winerror.h:2357
#define E_NOINTERFACE
Definition: winerror.h:2364
#define WINCODEC_ERR_BADMETADATAHEADER
Definition: winerror.h:3302
#define WINCODEC_ERR_PROPERTYNOTFOUND
Definition: winerror.h:3287
#define RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO
Definition: winnt_old.h:1116
unsigned char BYTE
Definition: xxhash.c:193