2 * Copyright 2012 Vincent Povirk for CodeWeavers
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.
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.
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
24 #define NONAMELESSUNION
30 #include "wincodecsdk.h"
32 #include "wincodecs_private.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
38 typedef struct MetadataHandler {
39 IWICMetadataWriter IWICMetadataWriter_iface;
41 IWICPersistStream IWICPersistStream_iface;
42 IWICMetadataBlockReader IWICMetadataBlockReader_iface;
43 const MetadataHandlerVtbl *vtable;
46 CRITICAL_SECTION lock;
49 static inline MetadataHandler *impl_from_IWICMetadataWriter(IWICMetadataWriter *iface)
51 return CONTAINING_RECORD(iface, MetadataHandler, IWICMetadataWriter_iface);
54 static inline MetadataHandler *impl_from_IWICPersistStream(IWICPersistStream *iface)
56 return CONTAINING_RECORD(iface, MetadataHandler, IWICPersistStream_iface);
59 static inline MetadataHandler *impl_from_IWICMetadataBlockReader(IWICMetadataBlockReader *iface)
61 return CONTAINING_RECORD(iface, MetadataHandler, IWICMetadataBlockReader_iface);
64 static void MetadataHandler_FreeItems(MetadataHandler *This)
68 for (i=0; i<This->item_count; i++)
70 PropVariantClear(&This->items[i].schema);
71 PropVariantClear(&This->items[i].id);
72 PropVariantClear(&This->items[i].value);
75 HeapFree(GetProcessHeap(), 0, This->items);
78 static HRESULT MetadataHandlerEnum_Create(MetadataHandler *parent, DWORD index,
79 IWICEnumMetadataItem **ppIEnumMetadataItem);
81 static HRESULT WINAPI MetadataHandler_QueryInterface(IWICMetadataWriter *iface, REFIID iid,
84 MetadataHandler *This = impl_from_IWICMetadataWriter(iface);
85 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
87 if (!ppv) return E_INVALIDARG;
89 if (IsEqualIID(&IID_IUnknown, iid) ||
90 IsEqualIID(&IID_IWICMetadataReader, iid) ||
91 (IsEqualIID(&IID_IWICMetadataWriter, iid) && This->vtable->is_writer))
93 *ppv = &This->IWICMetadataWriter_iface;
95 else if (IsEqualIID(&IID_IPersist, iid) ||
96 IsEqualIID(&IID_IPersistStream, iid) ||
97 IsEqualIID(&IID_IWICPersistStream, iid))
99 *ppv = &This->IWICPersistStream_iface;
101 else if (IsEqualIID(&IID_IWICMetadataBlockReader, iid))
103 *ppv = &This->IWICMetadataBlockReader_iface;
108 return E_NOINTERFACE;
111 IUnknown_AddRef((IUnknown*)*ppv);
115 static ULONG WINAPI MetadataHandler_AddRef(IWICMetadataWriter *iface)
117 MetadataHandler *This = impl_from_IWICMetadataWriter(iface);
118 ULONG ref = InterlockedIncrement(&This->ref);
120 TRACE("(%p) refcount=%u\n", iface, ref);
125 static ULONG WINAPI MetadataHandler_Release(IWICMetadataWriter *iface)
127 MetadataHandler *This = impl_from_IWICMetadataWriter(iface);
128 ULONG ref = InterlockedDecrement(&This->ref);
130 TRACE("(%p) refcount=%u\n", iface, ref);
134 MetadataHandler_FreeItems(This);
135 This->lock.DebugInfo->Spare[0] = 0;
136 DeleteCriticalSection(&This->lock);
137 HeapFree(GetProcessHeap(), 0, This);
143 static HRESULT WINAPI MetadataHandler_GetMetadataFormat(IWICMetadataWriter *iface,
144 GUID *pguidMetadataFormat)
146 FIXME("(%p,%s): stub\n", iface, debugstr_guid(pguidMetadataFormat));
150 static HRESULT WINAPI MetadataHandler_GetMetadataHandlerInfo(IWICMetadataWriter *iface,
151 IWICMetadataHandlerInfo **ppIHandler)
153 FIXME("(%p,%p): stub\n", iface, ppIHandler);
157 static HRESULT WINAPI MetadataHandler_GetCount(IWICMetadataWriter *iface,
160 FIXME("(%p,%p): stub\n", iface, pcCount);
164 static HRESULT WINAPI MetadataHandler_GetValueByIndex(IWICMetadataWriter *iface,
165 UINT nIndex, PROPVARIANT *pvarSchema, PROPVARIANT *pvarId, PROPVARIANT *pvarValue)
167 FIXME("(%p,%u,%p,%p,%p): stub\n", iface, nIndex, pvarSchema, pvarId, pvarValue);
171 static HRESULT WINAPI MetadataHandler_GetValue(IWICMetadataWriter *iface,
172 const PROPVARIANT *pvarSchema, const PROPVARIANT *pvarId, PROPVARIANT *pvarValue)
174 FIXME("(%p,%p,%p,%p): stub\n", iface, pvarSchema, pvarId, pvarValue);
178 static HRESULT WINAPI MetadataHandler_GetEnumerator(IWICMetadataWriter *iface,
179 IWICEnumMetadataItem **ppIEnumMetadata)
181 MetadataHandler *This = impl_from_IWICMetadataWriter(iface);
182 TRACE("(%p,%p)\n", iface, ppIEnumMetadata);
183 return MetadataHandlerEnum_Create(This, 0, ppIEnumMetadata);
186 static HRESULT WINAPI MetadataHandler_SetValue(IWICMetadataWriter *iface,
187 const PROPVARIANT *pvarSchema, const PROPVARIANT *pvarId, const PROPVARIANT *pvarValue)
189 FIXME("(%p,%p,%p,%p): stub\n", iface, pvarSchema, pvarId, pvarValue);
193 static HRESULT WINAPI MetadataHandler_SetValueByIndex(IWICMetadataWriter *iface,
194 UINT nIndex, const PROPVARIANT *pvarSchema, const PROPVARIANT *pvarId, const PROPVARIANT *pvarValue)
196 FIXME("(%p,%u,%p,%p,%p): stub\n", iface, nIndex, pvarSchema, pvarId, pvarValue);
200 static HRESULT WINAPI MetadataHandler_RemoveValue(IWICMetadataWriter *iface,
201 const PROPVARIANT *pvarSchema, const PROPVARIANT *pvarId)
203 FIXME("(%p,%p,%p): stub\n", iface, pvarSchema, pvarId);
207 static HRESULT WINAPI MetadataHandler_RemoveValueByIndex(IWICMetadataWriter *iface,
210 FIXME("(%p,%u): stub\n", iface, nIndex);
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
230 static HRESULT WINAPI MetadataHandler_PersistStream_QueryInterface(IWICPersistStream *iface,
231 REFIID iid, void **ppv)
233 MetadataHandler *This = impl_from_IWICPersistStream(iface);
234 return IWICMetadataWriter_QueryInterface(&This->IWICMetadataWriter_iface, iid, ppv);
237 static ULONG WINAPI MetadataHandler_PersistStream_AddRef(IWICPersistStream *iface)
239 MetadataHandler *This = impl_from_IWICPersistStream(iface);
240 return IWICMetadataWriter_AddRef(&This->IWICMetadataWriter_iface);
243 static ULONG WINAPI MetadataHandler_PersistStream_Release(IWICPersistStream *iface)
245 MetadataHandler *This = impl_from_IWICPersistStream(iface);
246 return IWICMetadataWriter_Release(&This->IWICMetadataWriter_iface);
249 static HRESULT WINAPI MetadataHandler_GetClassID(IWICPersistStream *iface,
252 FIXME("(%p,%p): stub\n", iface, pClassID);
256 static HRESULT WINAPI MetadataHandler_IsDirty(IWICPersistStream *iface)
258 FIXME("(%p): stub\n", iface);
262 static HRESULT WINAPI MetadataHandler_Load(IWICPersistStream *iface,
265 FIXME("(%p,%p): stub\n", iface, pStm);
269 static HRESULT WINAPI MetadataHandler_Save(IWICPersistStream *iface,
270 IStream *pStm, BOOL fClearDirty)
272 FIXME("(%p,%p,%i): stub\n", iface, pStm, fClearDirty);
276 static HRESULT WINAPI MetadataHandler_GetSizeMax(IWICPersistStream *iface,
277 ULARGE_INTEGER *pcbSize)
279 FIXME("(%p,%p): stub\n", iface, pcbSize);
283 static HRESULT WINAPI MetadataHandler_LoadEx(IWICPersistStream *iface,
284 IStream *pIStream, const GUID *pguidPreferredVendor, DWORD dwPersistOptions)
286 MetadataHandler *This = impl_from_IWICPersistStream(iface);
288 MetadataItem *new_items=NULL;
291 TRACE("(%p,%p,%s,%x)\n", iface, pIStream, debugstr_guid(pguidPreferredVendor), dwPersistOptions);
293 EnterCriticalSection(&This->lock);
295 hr = This->vtable->fnLoad(pIStream, pguidPreferredVendor, dwPersistOptions,
296 &new_items, &item_count);
300 MetadataHandler_FreeItems(This);
301 This->items = new_items;
302 This->item_count = item_count;
305 LeaveCriticalSection(&This->lock);
310 static HRESULT WINAPI MetadataHandler_SaveEx(IWICPersistStream *iface,
311 IStream *pIStream, DWORD dwPersistOptions, BOOL fClearDirty)
313 FIXME("(%p,%p,%x,%i): stub\n", iface, pIStream, dwPersistOptions, fClearDirty);
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
330 static HRESULT WINAPI MetadataHandler_MetadataBlockReader_QueryInterface(IWICMetadataBlockReader *iface,
331 REFIID iid, void **ppv)
333 MetadataHandler *This = impl_from_IWICMetadataBlockReader(iface);
334 return IWICMetadataWriter_QueryInterface(&This->IWICMetadataWriter_iface, iid, ppv);
337 static ULONG WINAPI MetadataHandler_MetadataBlockReader_AddRef(IWICMetadataBlockReader *iface)
339 MetadataHandler *This = impl_from_IWICMetadataBlockReader(iface);
340 return IWICMetadataWriter_AddRef(&This->IWICMetadataWriter_iface);
343 static ULONG WINAPI MetadataHandler_MetadataBlockReader_Release(IWICMetadataBlockReader *iface)
345 MetadataHandler *This = impl_from_IWICMetadataBlockReader(iface);
346 return IWICMetadataWriter_Release(&This->IWICMetadataWriter_iface);
349 static HRESULT WINAPI MetadataHandler_MetadataBlockReader_GetContainerFormat(
350 IWICMetadataBlockReader *iface, GUID *guid)
352 FIXME("(%p,%p): stub\n", iface, guid);
356 static HRESULT WINAPI MetadataHandler_MetadataBlockReader_GetCount(
357 IWICMetadataBlockReader *iface, UINT *count)
359 FIXME("(%p,%p): stub\n", iface, count);
363 static HRESULT WINAPI MetadataHandler_MetadataBlockReader_GetReaderByIndex(
364 IWICMetadataBlockReader *iface, UINT index, IWICMetadataReader **reader)
366 FIXME("(%p,%u,%p): stub\n", iface, index, reader);
370 static HRESULT WINAPI MetadataHandler_MetadataBlockReader_GetEnumerator(
371 IWICMetadataBlockReader *iface, IEnumUnknown **enum_metadata)
373 FIXME("(%p,%p): stub\n", iface, enum_metadata);
377 static const IWICMetadataBlockReaderVtbl MetadataHandler_MetadataBlockReader_Vtbl =
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
388 HRESULT MetadataReader_Create(const MetadataHandlerVtbl *vtable, IUnknown *pUnkOuter, REFIID iid, void** ppv)
390 MetadataHandler *This;
393 TRACE("%s\n", debugstr_guid(vtable->clsid));
397 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
399 This = HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataHandler));
400 if (!This) return E_OUTOFMEMORY;
402 This->IWICMetadataWriter_iface.lpVtbl = &MetadataHandler_Vtbl;
403 This->IWICPersistStream_iface.lpVtbl = &MetadataHandler_PersistStream_Vtbl;
404 This->IWICMetadataBlockReader_iface.lpVtbl = &MetadataHandler_MetadataBlockReader_Vtbl;
406 This->vtable = vtable;
408 This->item_count = 0;
410 InitializeCriticalSection(&This->lock);
411 This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": MetadataHandler.lock");
413 hr = IWICMetadataWriter_QueryInterface(&This->IWICMetadataWriter_iface, iid, ppv);
415 IWICMetadataWriter_Release(&This->IWICMetadataWriter_iface);
420 typedef struct MetadataHandlerEnum {
421 IWICEnumMetadataItem IWICEnumMetadataItem_iface;
423 MetadataHandler *parent;
425 } MetadataHandlerEnum;
427 static inline MetadataHandlerEnum *impl_from_IWICEnumMetadataItem(IWICEnumMetadataItem *iface)
429 return CONTAINING_RECORD(iface, MetadataHandlerEnum, IWICEnumMetadataItem_iface);
432 static HRESULT WINAPI MetadataHandlerEnum_QueryInterface(IWICEnumMetadataItem *iface, REFIID iid,
435 MetadataHandlerEnum *This = impl_from_IWICEnumMetadataItem(iface);
436 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
438 if (!ppv) return E_INVALIDARG;
440 if (IsEqualIID(&IID_IUnknown, iid) ||
441 IsEqualIID(&IID_IWICEnumMetadataItem, iid))
443 *ppv = &This->IWICEnumMetadataItem_iface;
448 return E_NOINTERFACE;
451 IUnknown_AddRef((IUnknown*)*ppv);
455 static ULONG WINAPI MetadataHandlerEnum_AddRef(IWICEnumMetadataItem *iface)
457 MetadataHandlerEnum *This = impl_from_IWICEnumMetadataItem(iface);
458 ULONG ref = InterlockedIncrement(&This->ref);
460 TRACE("(%p) refcount=%u\n", iface, ref);
465 static ULONG WINAPI MetadataHandlerEnum_Release(IWICEnumMetadataItem *iface)
467 MetadataHandlerEnum *This = impl_from_IWICEnumMetadataItem(iface);
468 ULONG ref = InterlockedDecrement(&This->ref);
470 TRACE("(%p) refcount=%u\n", iface, ref);
474 IWICMetadataWriter_Release(&This->parent->IWICMetadataWriter_iface);
475 HeapFree(GetProcessHeap(), 0, This);
481 static HRESULT WINAPI MetadataHandlerEnum_Next(IWICEnumMetadataItem *iface,
482 ULONG celt, PROPVARIANT *rgeltSchema, PROPVARIANT *rgeltId,
483 PROPVARIANT *rgeltValue, ULONG *pceltFetched)
485 MetadataHandlerEnum *This = impl_from_IWICEnumMetadataItem(iface);
490 TRACE("(%p,%i)\n", iface, celt);
492 EnterCriticalSection(&This->parent->lock);
494 if (This->index >= This->parent->item_count)
497 LeaveCriticalSection(&This->parent->lock);
501 new_index = min(This->parent->item_count, This->index + celt);
502 *pceltFetched = new_index - This->index;
506 for (i=0; SUCCEEDED(hr) && i < *pceltFetched; i++)
507 hr = PropVariantCopy(&rgeltSchema[i], &This->parent->items[i+This->index].schema);
510 for (i=0; SUCCEEDED(hr) && i < *pceltFetched; i++)
511 hr = PropVariantCopy(&rgeltId[i], &This->parent->items[i+This->index].id);
515 for (i=0; SUCCEEDED(hr) && i < *pceltFetched; i++)
516 hr = PropVariantCopy(&rgeltValue[i], &This->parent->items[i+This->index].value);
521 This->index = new_index;
524 LeaveCriticalSection(&This->parent->lock);
529 static HRESULT WINAPI MetadataHandlerEnum_Skip(IWICEnumMetadataItem *iface,
532 MetadataHandlerEnum *This = impl_from_IWICEnumMetadataItem(iface);
534 EnterCriticalSection(&This->parent->lock);
538 LeaveCriticalSection(&This->parent->lock);
543 static HRESULT WINAPI MetadataHandlerEnum_Reset(IWICEnumMetadataItem *iface)
545 MetadataHandlerEnum *This = impl_from_IWICEnumMetadataItem(iface);
547 EnterCriticalSection(&This->parent->lock);
551 LeaveCriticalSection(&This->parent->lock);
556 static HRESULT WINAPI MetadataHandlerEnum_Clone(IWICEnumMetadataItem *iface,
557 IWICEnumMetadataItem **ppIEnumMetadataItem)
559 MetadataHandlerEnum *This = impl_from_IWICEnumMetadataItem(iface);
562 EnterCriticalSection(&This->parent->lock);
564 hr = MetadataHandlerEnum_Create(This->parent, This->index, ppIEnumMetadataItem);
566 LeaveCriticalSection(&This->parent->lock);
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
581 static HRESULT MetadataHandlerEnum_Create(MetadataHandler *parent, DWORD index,
582 IWICEnumMetadataItem **ppIEnumMetadataItem)
584 MetadataHandlerEnum *This;
586 *ppIEnumMetadataItem = NULL;
588 This = HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataHandlerEnum));
589 if (!This) return E_OUTOFMEMORY;
591 IWICMetadataWriter_AddRef(&parent->IWICMetadataWriter_iface);
593 This->IWICEnumMetadataItem_iface.lpVtbl = &MetadataHandlerEnum_Vtbl;
595 This->parent = parent;
598 *ppIEnumMetadataItem = &This->IWICEnumMetadataItem_iface;
603 static HRESULT LoadUnknownMetadata(IStream *input, const GUID *preferred_vendor,
604 DWORD persist_options, MetadataItem **items, DWORD *item_count)
607 MetadataItem *result;
614 hr = IStream_Stat(input, &stat, STATFLAG_NONAME);
618 data = HeapAlloc(GetProcessHeap(), 0, stat.cbSize.QuadPart);
619 if (!data) return E_OUTOFMEMORY;
621 hr = IStream_Read(input, data, stat.cbSize.QuadPart, &bytesread);
624 HeapFree(GetProcessHeap(), 0, data);
628 result = HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataItem));
631 HeapFree(GetProcessHeap(), 0, data);
632 return E_OUTOFMEMORY;
635 PropVariantInit(&result[0].schema);
636 PropVariantInit(&result[0].id);
637 PropVariantInit(&result[0].value);
639 result[0].value.vt = VT_BLOB;
640 result[0].value.u.blob.cbSize = bytesread;
641 result[0].value.u.blob.pBlobData = data;
649 static const MetadataHandlerVtbl UnknownMetadataReader_Vtbl = {
651 &CLSID_WICUnknownMetadataReader,
655 HRESULT UnknownMetadataReader_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
657 return MetadataReader_Create(&UnknownMetadataReader_Vtbl, pUnkOuter, iid, ppv);