ReactOS 0.4.16-dev-106-g10b08aa
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
40typedef 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;
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
195
196 if (index >= This->item_count)
197 {
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
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
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
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
281static 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
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
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
385static 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
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
427typedef 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
578static 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
612static 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
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
696static 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;
733 type = entry->type;
735 item->value.vt = tag_to_vt(type);
736 value = entry->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
990static 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
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 {
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 {
1059 }
1060
1062 if (!result)
1063 {
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 {
1075 return hr;
1076 }
1077 }
1078
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 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 NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
@ 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
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:814
HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo)
Definition: info.c:2075
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 GLenum type
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLuint index
Definition: glext.h:6031
GLenum GLenum GLenum input
Definition: glext.h:9031
GLuint64EXT * result
Definition: glext.h:11304
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
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_IWICMetadataWriter(IWICMetadataWriter *iface)
static HRESULT WINAPI MetadataHandlerEnum_Reset(IWICEnumMetadataItem *iface)
static HRESULT WINAPI MetadataHandlerEnum_Next(IWICEnumMetadataItem *iface, ULONG celt, PROPVARIANT *rgeltSchema, PROPVARIANT *rgeltId, PROPVARIANT *rgeltValue, ULONG *pceltFetched)
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_GetValueByIndex(IWICMetadataWriter *iface, UINT index, PROPVARIANT *schema, PROPVARIANT *id, PROPVARIANT *value)
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_LoadEx(IWICPersistStream *iface, IStream *pIStream, const GUID *pguidPreferredVendor, DWORD dwPersistOptions)
#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_RemoveValueByIndex(IWICMetadataWriter *iface, UINT nIndex)
#define IFD_DOUBLE
#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
#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:60
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
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
CRITICAL_SECTION lock
IWICMetadataWriter IWICMetadataWriter_iface
const MetadataHandlerVtbl * vtable
Definition: send.c:48
Definition: stat.h:55
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:94
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
unsigned char BYTE
Definition: xxhash.c:193