d3drm: Implement IDirect3DRMMeshImpl_GetGroupMaterial.
[wine] / dlls / windowscodecs / metadatahandler.c
1 /*
2  * Copyright 2012 Vincent Povirk for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include "config.h"
20
21 #include <stdarg.h>
22
23 #define COBJMACROS
24 #define NONAMELESSUNION
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "objbase.h"
29 #include "wincodec.h"
30 #include "wincodecsdk.h"
31
32 #include "wincodecs_private.h"
33
34 #include "wine/debug.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
37
38 typedef struct MetadataHandler {
39     IWICMetadataWriter IWICMetadataWriter_iface;
40     LONG ref;
41     IWICPersistStream IWICPersistStream_iface;
42     IWICMetadataBlockReader IWICMetadataBlockReader_iface;
43     const MetadataHandlerVtbl *vtable;
44     MetadataItem *items;
45     DWORD item_count;
46     CRITICAL_SECTION lock;
47 } MetadataHandler;
48
49 static inline MetadataHandler *impl_from_IWICMetadataWriter(IWICMetadataWriter *iface)
50 {
51     return CONTAINING_RECORD(iface, MetadataHandler, IWICMetadataWriter_iface);
52 }
53
54 static inline MetadataHandler *impl_from_IWICPersistStream(IWICPersistStream *iface)
55 {
56     return CONTAINING_RECORD(iface, MetadataHandler, IWICPersistStream_iface);
57 }
58
59 static inline MetadataHandler *impl_from_IWICMetadataBlockReader(IWICMetadataBlockReader *iface)
60 {
61     return CONTAINING_RECORD(iface, MetadataHandler, IWICMetadataBlockReader_iface);
62 }
63
64 static void MetadataHandler_FreeItems(MetadataHandler *This)
65 {
66     int i;
67
68     for (i=0; i<This->item_count; i++)
69     {
70         PropVariantClear(&This->items[i].schema);
71         PropVariantClear(&This->items[i].id);
72         PropVariantClear(&This->items[i].value);
73     }
74
75     HeapFree(GetProcessHeap(), 0, This->items);
76 }
77
78 static HRESULT MetadataHandlerEnum_Create(MetadataHandler *parent, DWORD index,
79     IWICEnumMetadataItem **ppIEnumMetadataItem);
80
81 static HRESULT WINAPI MetadataHandler_QueryInterface(IWICMetadataWriter *iface, REFIID iid,
82     void **ppv)
83 {
84     MetadataHandler *This = impl_from_IWICMetadataWriter(iface);
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) ||
96              IsEqualIID(&IID_IPersistStream, iid) ||
97              IsEqualIID(&IID_IWICPersistStream, iid))
98     {
99         *ppv = &This->IWICPersistStream_iface;
100     }
101     else if (IsEqualIID(&IID_IWICMetadataBlockReader, iid))
102     {
103         *ppv = &This->IWICMetadataBlockReader_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
115 static ULONG WINAPI MetadataHandler_AddRef(IWICMetadataWriter *iface)
116 {
117     MetadataHandler *This = impl_from_IWICMetadataWriter(iface);
118     ULONG ref = InterlockedIncrement(&This->ref);
119
120     TRACE("(%p) refcount=%u\n", iface, ref);
121
122     return ref;
123 }
124
125 static ULONG WINAPI MetadataHandler_Release(IWICMetadataWriter *iface)
126 {
127     MetadataHandler *This = impl_from_IWICMetadataWriter(iface);
128     ULONG ref = InterlockedDecrement(&This->ref);
129
130     TRACE("(%p) refcount=%u\n", iface, ref);
131
132     if (ref == 0)
133     {
134         MetadataHandler_FreeItems(This);
135         This->lock.DebugInfo->Spare[0] = 0;
136         DeleteCriticalSection(&This->lock);
137         HeapFree(GetProcessHeap(), 0, This);
138     }
139
140     return ref;
141 }
142
143 static HRESULT WINAPI MetadataHandler_GetMetadataFormat(IWICMetadataWriter *iface,
144     GUID *pguidMetadataFormat)
145 {
146     FIXME("(%p,%s): stub\n", iface, debugstr_guid(pguidMetadataFormat));
147     return E_NOTIMPL;
148 }
149
150 static HRESULT WINAPI MetadataHandler_GetMetadataHandlerInfo(IWICMetadataWriter *iface,
151     IWICMetadataHandlerInfo **ppIHandler)
152 {
153     FIXME("(%p,%p): stub\n", iface, ppIHandler);
154     return E_NOTIMPL;
155 }
156
157 static HRESULT WINAPI MetadataHandler_GetCount(IWICMetadataWriter *iface,
158     UINT *pcCount)
159 {
160     FIXME("(%p,%p): stub\n", iface, pcCount);
161     return E_NOTIMPL;
162 }
163
164 static HRESULT WINAPI MetadataHandler_GetValueByIndex(IWICMetadataWriter *iface,
165     UINT nIndex, PROPVARIANT *pvarSchema, PROPVARIANT *pvarId, PROPVARIANT *pvarValue)
166 {
167     FIXME("(%p,%u,%p,%p,%p): stub\n", iface, nIndex, pvarSchema, pvarId, pvarValue);
168     return E_NOTIMPL;
169 }
170
171 static HRESULT WINAPI MetadataHandler_GetValue(IWICMetadataWriter *iface,
172     const PROPVARIANT *pvarSchema, const PROPVARIANT *pvarId, PROPVARIANT *pvarValue)
173 {
174     FIXME("(%p,%p,%p,%p): stub\n", iface, pvarSchema, pvarId, pvarValue);
175     return E_NOTIMPL;
176 }
177
178 static HRESULT WINAPI MetadataHandler_GetEnumerator(IWICMetadataWriter *iface,
179     IWICEnumMetadataItem **ppIEnumMetadata)
180 {
181     MetadataHandler *This = impl_from_IWICMetadataWriter(iface);
182     TRACE("(%p,%p)\n", iface, ppIEnumMetadata);
183     return MetadataHandlerEnum_Create(This, 0, ppIEnumMetadata);
184 }
185
186 static HRESULT WINAPI MetadataHandler_SetValue(IWICMetadataWriter *iface,
187     const PROPVARIANT *pvarSchema, const PROPVARIANT *pvarId, const PROPVARIANT *pvarValue)
188 {
189     FIXME("(%p,%p,%p,%p): stub\n", iface, pvarSchema, pvarId, pvarValue);
190     return E_NOTIMPL;
191 }
192
193 static HRESULT WINAPI MetadataHandler_SetValueByIndex(IWICMetadataWriter *iface,
194     UINT nIndex, const PROPVARIANT *pvarSchema, const PROPVARIANT *pvarId, const PROPVARIANT *pvarValue)
195 {
196     FIXME("(%p,%u,%p,%p,%p): stub\n", iface, nIndex, pvarSchema, pvarId, pvarValue);
197     return E_NOTIMPL;
198 }
199
200 static HRESULT WINAPI MetadataHandler_RemoveValue(IWICMetadataWriter *iface,
201     const PROPVARIANT *pvarSchema, const PROPVARIANT *pvarId)
202 {
203     FIXME("(%p,%p,%p): stub\n", iface, pvarSchema, pvarId);
204     return E_NOTIMPL;
205 }
206
207 static HRESULT WINAPI MetadataHandler_RemoveValueByIndex(IWICMetadataWriter *iface,
208     UINT nIndex)
209 {
210     FIXME("(%p,%u): stub\n", iface, nIndex);
211     return E_NOTIMPL;
212 }
213
214 static const IWICMetadataWriterVtbl MetadataHandler_Vtbl = {
215     MetadataHandler_QueryInterface,
216     MetadataHandler_AddRef,
217     MetadataHandler_Release,
218     MetadataHandler_GetMetadataFormat,
219     MetadataHandler_GetMetadataHandlerInfo,
220     MetadataHandler_GetCount,
221     MetadataHandler_GetValueByIndex,
222     MetadataHandler_GetValue,
223     MetadataHandler_GetEnumerator,
224     MetadataHandler_SetValue,
225     MetadataHandler_SetValueByIndex,
226     MetadataHandler_RemoveValue,
227     MetadataHandler_RemoveValueByIndex
228 };
229
230 static HRESULT WINAPI MetadataHandler_PersistStream_QueryInterface(IWICPersistStream *iface,
231     REFIID iid, void **ppv)
232 {
233     MetadataHandler *This = impl_from_IWICPersistStream(iface);
234     return IWICMetadataWriter_QueryInterface(&This->IWICMetadataWriter_iface, iid, ppv);
235 }
236
237 static ULONG WINAPI MetadataHandler_PersistStream_AddRef(IWICPersistStream *iface)
238 {
239     MetadataHandler *This = impl_from_IWICPersistStream(iface);
240     return IWICMetadataWriter_AddRef(&This->IWICMetadataWriter_iface);
241 }
242
243 static ULONG WINAPI MetadataHandler_PersistStream_Release(IWICPersistStream *iface)
244 {
245     MetadataHandler *This = impl_from_IWICPersistStream(iface);
246     return IWICMetadataWriter_Release(&This->IWICMetadataWriter_iface);
247 }
248
249 static HRESULT WINAPI MetadataHandler_GetClassID(IWICPersistStream *iface,
250     CLSID *pClassID)
251 {
252     FIXME("(%p,%p): stub\n", iface, pClassID);
253     return E_NOTIMPL;
254 }
255
256 static HRESULT WINAPI MetadataHandler_IsDirty(IWICPersistStream *iface)
257 {
258     FIXME("(%p): stub\n", iface);
259     return E_NOTIMPL;
260 }
261
262 static HRESULT WINAPI MetadataHandler_Load(IWICPersistStream *iface,
263     IStream *pStm)
264 {
265     FIXME("(%p,%p): stub\n", iface, pStm);
266     return E_NOTIMPL;
267 }
268
269 static HRESULT WINAPI MetadataHandler_Save(IWICPersistStream *iface,
270     IStream *pStm, BOOL fClearDirty)
271 {
272     FIXME("(%p,%p,%i): stub\n", iface, pStm, fClearDirty);
273     return E_NOTIMPL;
274 }
275
276 static HRESULT WINAPI MetadataHandler_GetSizeMax(IWICPersistStream *iface,
277     ULARGE_INTEGER *pcbSize)
278 {
279     FIXME("(%p,%p): stub\n", iface, pcbSize);
280     return E_NOTIMPL;
281 }
282
283 static HRESULT WINAPI MetadataHandler_LoadEx(IWICPersistStream *iface,
284     IStream *pIStream, const GUID *pguidPreferredVendor, DWORD dwPersistOptions)
285 {
286     MetadataHandler *This = impl_from_IWICPersistStream(iface);
287     HRESULT hr;
288     MetadataItem *new_items=NULL;
289     DWORD item_count=0;
290
291     TRACE("(%p,%p,%s,%x)\n", iface, pIStream, debugstr_guid(pguidPreferredVendor), dwPersistOptions);
292
293     EnterCriticalSection(&This->lock);
294
295     hr = This->vtable->fnLoad(pIStream, pguidPreferredVendor, dwPersistOptions,
296         &new_items, &item_count);
297
298     if (SUCCEEDED(hr))
299     {
300         MetadataHandler_FreeItems(This);
301         This->items = new_items;
302         This->item_count = item_count;
303     }
304
305     LeaveCriticalSection(&This->lock);
306
307     return hr;
308 }
309
310 static HRESULT WINAPI MetadataHandler_SaveEx(IWICPersistStream *iface,
311     IStream *pIStream, DWORD dwPersistOptions, BOOL fClearDirty)
312 {
313     FIXME("(%p,%p,%x,%i): stub\n", iface, pIStream, dwPersistOptions, fClearDirty);
314     return E_NOTIMPL;
315 }
316
317 static const IWICPersistStreamVtbl MetadataHandler_PersistStream_Vtbl = {
318     MetadataHandler_PersistStream_QueryInterface,
319     MetadataHandler_PersistStream_AddRef,
320     MetadataHandler_PersistStream_Release,
321     MetadataHandler_GetClassID,
322     MetadataHandler_IsDirty,
323     MetadataHandler_Load,
324     MetadataHandler_Save,
325     MetadataHandler_GetSizeMax,
326     MetadataHandler_LoadEx,
327     MetadataHandler_SaveEx
328 };
329
330 static HRESULT WINAPI MetadataHandler_MetadataBlockReader_QueryInterface(IWICMetadataBlockReader *iface,
331     REFIID iid, void **ppv)
332 {
333     MetadataHandler *This = impl_from_IWICMetadataBlockReader(iface);
334     return IWICMetadataWriter_QueryInterface(&This->IWICMetadataWriter_iface, iid, ppv);
335 }
336
337 static ULONG WINAPI MetadataHandler_MetadataBlockReader_AddRef(IWICMetadataBlockReader *iface)
338 {
339     MetadataHandler *This = impl_from_IWICMetadataBlockReader(iface);
340     return IWICMetadataWriter_AddRef(&This->IWICMetadataWriter_iface);
341 }
342
343 static ULONG WINAPI MetadataHandler_MetadataBlockReader_Release(IWICMetadataBlockReader *iface)
344 {
345     MetadataHandler *This = impl_from_IWICMetadataBlockReader(iface);
346     return IWICMetadataWriter_Release(&This->IWICMetadataWriter_iface);
347 }
348
349 static HRESULT WINAPI MetadataHandler_MetadataBlockReader_GetContainerFormat(
350         IWICMetadataBlockReader *iface, GUID *guid)
351 {
352     FIXME("(%p,%p): stub\n", iface, guid);
353     return E_NOTIMPL;
354 }
355
356 static HRESULT WINAPI MetadataHandler_MetadataBlockReader_GetCount(
357         IWICMetadataBlockReader *iface, UINT *count)
358 {
359     FIXME("(%p,%p): stub\n", iface, count);
360     return E_NOTIMPL;
361 }
362
363 static HRESULT WINAPI MetadataHandler_MetadataBlockReader_GetReaderByIndex(
364         IWICMetadataBlockReader *iface, UINT index, IWICMetadataReader **reader)
365 {
366     FIXME("(%p,%u,%p): stub\n", iface, index, reader);
367     return E_NOTIMPL;
368 }
369
370 static HRESULT WINAPI MetadataHandler_MetadataBlockReader_GetEnumerator(
371         IWICMetadataBlockReader *iface, IEnumUnknown **enum_metadata)
372 {
373     FIXME("(%p,%p): stub\n", iface, enum_metadata);
374     return E_NOTIMPL;
375 }
376
377 static const IWICMetadataBlockReaderVtbl MetadataHandler_MetadataBlockReader_Vtbl =
378 {
379     MetadataHandler_MetadataBlockReader_QueryInterface,
380     MetadataHandler_MetadataBlockReader_AddRef,
381     MetadataHandler_MetadataBlockReader_Release,
382     MetadataHandler_MetadataBlockReader_GetContainerFormat,
383     MetadataHandler_MetadataBlockReader_GetCount,
384     MetadataHandler_MetadataBlockReader_GetReaderByIndex,
385     MetadataHandler_MetadataBlockReader_GetEnumerator
386 };
387
388 HRESULT MetadataReader_Create(const MetadataHandlerVtbl *vtable, IUnknown *pUnkOuter, REFIID iid, void** ppv)
389 {
390     MetadataHandler *This;
391     HRESULT hr;
392
393     TRACE("%s\n", debugstr_guid(vtable->clsid));
394
395     *ppv = NULL;
396
397     if (pUnkOuter) return CLASS_E_NOAGGREGATION;
398
399     This = HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataHandler));
400     if (!This) return E_OUTOFMEMORY;
401
402     This->IWICMetadataWriter_iface.lpVtbl = &MetadataHandler_Vtbl;
403     This->IWICPersistStream_iface.lpVtbl = &MetadataHandler_PersistStream_Vtbl;
404     This->IWICMetadataBlockReader_iface.lpVtbl = &MetadataHandler_MetadataBlockReader_Vtbl;
405     This->ref = 1;
406     This->vtable = vtable;
407     This->items = NULL;
408     This->item_count = 0;
409
410     InitializeCriticalSection(&This->lock);
411     This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": MetadataHandler.lock");
412
413     hr = IWICMetadataWriter_QueryInterface(&This->IWICMetadataWriter_iface, iid, ppv);
414
415     IWICMetadataWriter_Release(&This->IWICMetadataWriter_iface);
416
417     return hr;
418 }
419
420 typedef struct MetadataHandlerEnum {
421     IWICEnumMetadataItem IWICEnumMetadataItem_iface;
422     LONG ref;
423     MetadataHandler *parent;
424     DWORD index;
425 } MetadataHandlerEnum;
426
427 static inline MetadataHandlerEnum *impl_from_IWICEnumMetadataItem(IWICEnumMetadataItem *iface)
428 {
429     return CONTAINING_RECORD(iface, MetadataHandlerEnum, IWICEnumMetadataItem_iface);
430 }
431
432 static HRESULT WINAPI MetadataHandlerEnum_QueryInterface(IWICEnumMetadataItem *iface, REFIID iid,
433     void **ppv)
434 {
435     MetadataHandlerEnum *This = impl_from_IWICEnumMetadataItem(iface);
436     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
437
438     if (!ppv) return E_INVALIDARG;
439
440     if (IsEqualIID(&IID_IUnknown, iid) ||
441         IsEqualIID(&IID_IWICEnumMetadataItem, iid))
442     {
443         *ppv = &This->IWICEnumMetadataItem_iface;
444     }
445     else
446     {
447         *ppv = NULL;
448         return E_NOINTERFACE;
449     }
450
451     IUnknown_AddRef((IUnknown*)*ppv);
452     return S_OK;
453 }
454
455 static ULONG WINAPI MetadataHandlerEnum_AddRef(IWICEnumMetadataItem *iface)
456 {
457     MetadataHandlerEnum *This = impl_from_IWICEnumMetadataItem(iface);
458     ULONG ref = InterlockedIncrement(&This->ref);
459
460     TRACE("(%p) refcount=%u\n", iface, ref);
461
462     return ref;
463 }
464
465 static ULONG WINAPI MetadataHandlerEnum_Release(IWICEnumMetadataItem *iface)
466 {
467     MetadataHandlerEnum *This = impl_from_IWICEnumMetadataItem(iface);
468     ULONG ref = InterlockedDecrement(&This->ref);
469
470     TRACE("(%p) refcount=%u\n", iface, ref);
471
472     if (ref == 0)
473     {
474         IWICMetadataWriter_Release(&This->parent->IWICMetadataWriter_iface);
475         HeapFree(GetProcessHeap(), 0, This);
476     }
477
478     return ref;
479 }
480
481 static HRESULT WINAPI MetadataHandlerEnum_Next(IWICEnumMetadataItem *iface,
482     ULONG celt, PROPVARIANT *rgeltSchema, PROPVARIANT *rgeltId,
483     PROPVARIANT *rgeltValue, ULONG *pceltFetched)
484 {
485     MetadataHandlerEnum *This = impl_from_IWICEnumMetadataItem(iface);
486     ULONG new_index;
487     HRESULT hr=S_FALSE;
488     int i;
489
490     TRACE("(%p,%i)\n", iface, celt);
491
492     EnterCriticalSection(&This->parent->lock);
493
494     if (This->index >= This->parent->item_count)
495     {
496         *pceltFetched = 0;
497         LeaveCriticalSection(&This->parent->lock);
498         return S_FALSE;
499     }
500
501     new_index = min(This->parent->item_count, This->index + celt);
502     *pceltFetched = new_index - This->index;
503
504     if (rgeltSchema)
505     {
506         for (i=0; SUCCEEDED(hr) && i < *pceltFetched; i++)
507             hr = PropVariantCopy(&rgeltSchema[i], &This->parent->items[i+This->index].schema);
508     }
509
510     for (i=0; SUCCEEDED(hr) && i < *pceltFetched; i++)
511         hr = PropVariantCopy(&rgeltId[i], &This->parent->items[i+This->index].id);
512
513     if (rgeltValue)
514     {
515         for (i=0; SUCCEEDED(hr) && i < *pceltFetched; i++)
516             hr = PropVariantCopy(&rgeltValue[i], &This->parent->items[i+This->index].value);
517     }
518
519     if (SUCCEEDED(hr))
520     {
521         This->index = new_index;
522     }
523
524     LeaveCriticalSection(&This->parent->lock);
525
526     return hr;
527 }
528
529 static HRESULT WINAPI MetadataHandlerEnum_Skip(IWICEnumMetadataItem *iface,
530     ULONG celt)
531 {
532     MetadataHandlerEnum *This = impl_from_IWICEnumMetadataItem(iface);
533
534     EnterCriticalSection(&This->parent->lock);
535
536     This->index += celt;
537
538     LeaveCriticalSection(&This->parent->lock);
539
540     return S_OK;
541 }
542
543 static HRESULT WINAPI MetadataHandlerEnum_Reset(IWICEnumMetadataItem *iface)
544 {
545     MetadataHandlerEnum *This = impl_from_IWICEnumMetadataItem(iface);
546
547     EnterCriticalSection(&This->parent->lock);
548
549     This->index = 0;
550
551     LeaveCriticalSection(&This->parent->lock);
552
553     return S_OK;
554 }
555
556 static HRESULT WINAPI MetadataHandlerEnum_Clone(IWICEnumMetadataItem *iface,
557     IWICEnumMetadataItem **ppIEnumMetadataItem)
558 {
559     MetadataHandlerEnum *This = impl_from_IWICEnumMetadataItem(iface);
560     HRESULT hr;
561
562     EnterCriticalSection(&This->parent->lock);
563
564     hr = MetadataHandlerEnum_Create(This->parent, This->index, ppIEnumMetadataItem);
565
566     LeaveCriticalSection(&This->parent->lock);
567
568     return hr;
569 }
570
571 static const IWICEnumMetadataItemVtbl MetadataHandlerEnum_Vtbl = {
572     MetadataHandlerEnum_QueryInterface,
573     MetadataHandlerEnum_AddRef,
574     MetadataHandlerEnum_Release,
575     MetadataHandlerEnum_Next,
576     MetadataHandlerEnum_Skip,
577     MetadataHandlerEnum_Reset,
578     MetadataHandlerEnum_Clone
579 };
580
581 static HRESULT MetadataHandlerEnum_Create(MetadataHandler *parent, DWORD index,
582     IWICEnumMetadataItem **ppIEnumMetadataItem)
583 {
584     MetadataHandlerEnum *This;
585
586     *ppIEnumMetadataItem = NULL;
587
588     This = HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataHandlerEnum));
589     if (!This) return E_OUTOFMEMORY;
590
591     IWICMetadataWriter_AddRef(&parent->IWICMetadataWriter_iface);
592
593     This->IWICEnumMetadataItem_iface.lpVtbl = &MetadataHandlerEnum_Vtbl;
594     This->ref = 1;
595     This->parent = parent;
596     This->index = index;
597
598     *ppIEnumMetadataItem = &This->IWICEnumMetadataItem_iface;
599
600     return S_OK;
601 }
602
603 static HRESULT LoadUnknownMetadata(IStream *input, const GUID *preferred_vendor,
604     DWORD persist_options, MetadataItem **items, DWORD *item_count)
605 {
606     HRESULT hr;
607     MetadataItem *result;
608     STATSTG stat;
609     BYTE *data;
610     ULONG bytesread;
611
612     TRACE("\n");
613
614     hr = IStream_Stat(input, &stat, STATFLAG_NONAME);
615     if (FAILED(hr))
616         return hr;
617
618     data = HeapAlloc(GetProcessHeap(), 0, stat.cbSize.QuadPart);
619     if (!data) return E_OUTOFMEMORY;
620
621     hr = IStream_Read(input, data, stat.cbSize.QuadPart, &bytesread);
622     if (FAILED(hr))
623     {
624         HeapFree(GetProcessHeap(), 0, data);
625         return hr;
626     }
627
628     result = HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataItem));
629     if (!result)
630     {
631         HeapFree(GetProcessHeap(), 0, data);
632         return E_OUTOFMEMORY;
633     }
634
635     PropVariantInit(&result[0].schema);
636     PropVariantInit(&result[0].id);
637     PropVariantInit(&result[0].value);
638
639     result[0].value.vt = VT_BLOB;
640     result[0].value.u.blob.cbSize = bytesread;
641     result[0].value.u.blob.pBlobData = data;
642
643     *items = result;
644     *item_count = 1;
645
646     return S_OK;
647 }
648
649 static const MetadataHandlerVtbl UnknownMetadataReader_Vtbl = {
650     0,
651     &CLSID_WICUnknownMetadataReader,
652     LoadUnknownMetadata
653 };
654
655 HRESULT UnknownMetadataReader_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
656 {
657     return MetadataReader_Create(&UnknownMetadataReader_Vtbl, pUnkOuter, iid, ppv);
658 }