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 const MetadataHandlerVtbl
*vtable
;
45 CRITICAL_SECTION lock
;
48 static inline MetadataHandler
*impl_from_IWICMetadataWriter(IWICMetadataWriter
*iface
)
50 return CONTAINING_RECORD(iface
, MetadataHandler
, IWICMetadataWriter_iface
);
53 static inline MetadataHandler
*impl_from_IWICPersistStream(IWICPersistStream
*iface
)
55 return CONTAINING_RECORD(iface
, MetadataHandler
, IWICPersistStream_iface
);
58 static void MetadataHandler_FreeItems(MetadataHandler
*This
)
62 for (i
=0; i
<This
->item_count
; i
++)
64 PropVariantClear(&This
->items
[i
].schema
);
65 PropVariantClear(&This
->items
[i
].id
);
66 PropVariantClear(&This
->items
[i
].value
);
69 HeapFree(GetProcessHeap(), 0, This
->items
);
72 static HRESULT
MetadataHandlerEnum_Create(MetadataHandler
*parent
, DWORD index
,
73 IWICEnumMetadataItem
**ppIEnumMetadataItem
);
75 static HRESULT WINAPI
MetadataHandler_QueryInterface(IWICMetadataWriter
*iface
, REFIID iid
,
78 MetadataHandler
*This
= impl_from_IWICMetadataWriter(iface
);
79 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
81 if (!ppv
) return E_INVALIDARG
;
83 if (IsEqualIID(&IID_IUnknown
, iid
) ||
84 IsEqualIID(&IID_IWICMetadataReader
, iid
) ||
85 (IsEqualIID(&IID_IWICMetadataWriter
, iid
) && This
->vtable
->is_writer
))
87 *ppv
= &This
->IWICMetadataWriter_iface
;
89 else if (IsEqualIID(&IID_IPersist
, iid
) ||
90 IsEqualIID(&IID_IPersistStream
, iid
) ||
91 IsEqualIID(&IID_IWICPersistStream
, iid
))
93 *ppv
= &This
->IWICPersistStream_iface
;
101 IUnknown_AddRef((IUnknown
*)*ppv
);
105 static ULONG WINAPI
MetadataHandler_AddRef(IWICMetadataWriter
*iface
)
107 MetadataHandler
*This
= impl_from_IWICMetadataWriter(iface
);
108 ULONG ref
= InterlockedIncrement(&This
->ref
);
110 TRACE("(%p) refcount=%u\n", iface
, ref
);
115 static ULONG WINAPI
MetadataHandler_Release(IWICMetadataWriter
*iface
)
117 MetadataHandler
*This
= impl_from_IWICMetadataWriter(iface
);
118 ULONG ref
= InterlockedDecrement(&This
->ref
);
120 TRACE("(%p) refcount=%u\n", iface
, ref
);
124 MetadataHandler_FreeItems(This
);
125 This
->lock
.DebugInfo
->Spare
[0] = 0;
126 DeleteCriticalSection(&This
->lock
);
127 HeapFree(GetProcessHeap(), 0, This
);
133 static HRESULT WINAPI
MetadataHandler_GetMetadataFormat(IWICMetadataWriter
*iface
,
134 GUID
*pguidMetadataFormat
)
136 if (!pguidMetadataFormat
) return E_INVALIDARG
;
138 FIXME("(%p,%s): stub\n", iface
, debugstr_guid(pguidMetadataFormat
));
142 static HRESULT WINAPI
MetadataHandler_GetMetadataHandlerInfo(IWICMetadataWriter
*iface
,
143 IWICMetadataHandlerInfo
**ppIHandler
)
145 FIXME("(%p,%p): stub\n", iface
, ppIHandler
);
149 static HRESULT WINAPI
MetadataHandler_GetCount(IWICMetadataWriter
*iface
,
152 MetadataHandler
*This
= impl_from_IWICMetadataWriter(iface
);
154 TRACE("%p,%p\n", iface
, pcCount
);
156 if (!pcCount
) return E_INVALIDARG
;
158 *pcCount
= This
->item_count
;
162 static HRESULT WINAPI
MetadataHandler_GetValueByIndex(IWICMetadataWriter
*iface
,
163 UINT nIndex
, PROPVARIANT
*pvarSchema
, PROPVARIANT
*pvarId
, PROPVARIANT
*pvarValue
)
165 FIXME("(%p,%u,%p,%p,%p): stub\n", iface
, nIndex
, pvarSchema
, pvarId
, pvarValue
);
169 static HRESULT WINAPI
MetadataHandler_GetValue(IWICMetadataWriter
*iface
,
170 const PROPVARIANT
*pvarSchema
, const PROPVARIANT
*pvarId
, PROPVARIANT
*pvarValue
)
172 FIXME("(%p,%p,%p,%p): stub\n", iface
, pvarSchema
, pvarId
, pvarValue
);
176 static HRESULT WINAPI
MetadataHandler_GetEnumerator(IWICMetadataWriter
*iface
,
177 IWICEnumMetadataItem
**ppIEnumMetadata
)
179 MetadataHandler
*This
= impl_from_IWICMetadataWriter(iface
);
180 TRACE("(%p,%p)\n", iface
, ppIEnumMetadata
);
181 return MetadataHandlerEnum_Create(This
, 0, ppIEnumMetadata
);
184 static HRESULT WINAPI
MetadataHandler_SetValue(IWICMetadataWriter
*iface
,
185 const PROPVARIANT
*pvarSchema
, const PROPVARIANT
*pvarId
, const PROPVARIANT
*pvarValue
)
187 FIXME("(%p,%p,%p,%p): stub\n", iface
, pvarSchema
, pvarId
, pvarValue
);
191 static HRESULT WINAPI
MetadataHandler_SetValueByIndex(IWICMetadataWriter
*iface
,
192 UINT nIndex
, const PROPVARIANT
*pvarSchema
, const PROPVARIANT
*pvarId
, const PROPVARIANT
*pvarValue
)
194 FIXME("(%p,%u,%p,%p,%p): stub\n", iface
, nIndex
, pvarSchema
, pvarId
, pvarValue
);
198 static HRESULT WINAPI
MetadataHandler_RemoveValue(IWICMetadataWriter
*iface
,
199 const PROPVARIANT
*pvarSchema
, const PROPVARIANT
*pvarId
)
201 FIXME("(%p,%p,%p): stub\n", iface
, pvarSchema
, pvarId
);
205 static HRESULT WINAPI
MetadataHandler_RemoveValueByIndex(IWICMetadataWriter
*iface
,
208 FIXME("(%p,%u): stub\n", iface
, nIndex
);
212 static const IWICMetadataWriterVtbl MetadataHandler_Vtbl
= {
213 MetadataHandler_QueryInterface
,
214 MetadataHandler_AddRef
,
215 MetadataHandler_Release
,
216 MetadataHandler_GetMetadataFormat
,
217 MetadataHandler_GetMetadataHandlerInfo
,
218 MetadataHandler_GetCount
,
219 MetadataHandler_GetValueByIndex
,
220 MetadataHandler_GetValue
,
221 MetadataHandler_GetEnumerator
,
222 MetadataHandler_SetValue
,
223 MetadataHandler_SetValueByIndex
,
224 MetadataHandler_RemoveValue
,
225 MetadataHandler_RemoveValueByIndex
228 static HRESULT WINAPI
MetadataHandler_PersistStream_QueryInterface(IWICPersistStream
*iface
,
229 REFIID iid
, void **ppv
)
231 MetadataHandler
*This
= impl_from_IWICPersistStream(iface
);
232 return IWICMetadataWriter_QueryInterface(&This
->IWICMetadataWriter_iface
, iid
, ppv
);
235 static ULONG WINAPI
MetadataHandler_PersistStream_AddRef(IWICPersistStream
*iface
)
237 MetadataHandler
*This
= impl_from_IWICPersistStream(iface
);
238 return IWICMetadataWriter_AddRef(&This
->IWICMetadataWriter_iface
);
241 static ULONG WINAPI
MetadataHandler_PersistStream_Release(IWICPersistStream
*iface
)
243 MetadataHandler
*This
= impl_from_IWICPersistStream(iface
);
244 return IWICMetadataWriter_Release(&This
->IWICMetadataWriter_iface
);
247 static HRESULT WINAPI
MetadataHandler_GetClassID(IWICPersistStream
*iface
,
250 FIXME("(%p,%p): stub\n", iface
, pClassID
);
254 static HRESULT WINAPI
MetadataHandler_IsDirty(IWICPersistStream
*iface
)
256 FIXME("(%p): stub\n", iface
);
260 static HRESULT WINAPI
MetadataHandler_Load(IWICPersistStream
*iface
,
263 FIXME("(%p,%p): stub\n", iface
, pStm
);
267 static HRESULT WINAPI
MetadataHandler_Save(IWICPersistStream
*iface
,
268 IStream
*pStm
, BOOL fClearDirty
)
270 FIXME("(%p,%p,%i): stub\n", iface
, pStm
, fClearDirty
);
274 static HRESULT WINAPI
MetadataHandler_GetSizeMax(IWICPersistStream
*iface
,
275 ULARGE_INTEGER
*pcbSize
)
277 FIXME("(%p,%p): stub\n", iface
, pcbSize
);
281 static HRESULT WINAPI
MetadataHandler_LoadEx(IWICPersistStream
*iface
,
282 IStream
*pIStream
, const GUID
*pguidPreferredVendor
, DWORD dwPersistOptions
)
284 MetadataHandler
*This
= impl_from_IWICPersistStream(iface
);
286 MetadataItem
*new_items
=NULL
;
289 TRACE("(%p,%p,%s,%x)\n", iface
, pIStream
, debugstr_guid(pguidPreferredVendor
), dwPersistOptions
);
291 EnterCriticalSection(&This
->lock
);
293 hr
= This
->vtable
->fnLoad(pIStream
, pguidPreferredVendor
, dwPersistOptions
,
294 &new_items
, &item_count
);
298 MetadataHandler_FreeItems(This
);
299 This
->items
= new_items
;
300 This
->item_count
= item_count
;
303 LeaveCriticalSection(&This
->lock
);
308 static HRESULT WINAPI
MetadataHandler_SaveEx(IWICPersistStream
*iface
,
309 IStream
*pIStream
, DWORD dwPersistOptions
, BOOL fClearDirty
)
311 FIXME("(%p,%p,%x,%i): stub\n", iface
, pIStream
, dwPersistOptions
, fClearDirty
);
315 static const IWICPersistStreamVtbl MetadataHandler_PersistStream_Vtbl
= {
316 MetadataHandler_PersistStream_QueryInterface
,
317 MetadataHandler_PersistStream_AddRef
,
318 MetadataHandler_PersistStream_Release
,
319 MetadataHandler_GetClassID
,
320 MetadataHandler_IsDirty
,
321 MetadataHandler_Load
,
322 MetadataHandler_Save
,
323 MetadataHandler_GetSizeMax
,
324 MetadataHandler_LoadEx
,
325 MetadataHandler_SaveEx
328 HRESULT
MetadataReader_Create(const MetadataHandlerVtbl
*vtable
, IUnknown
*pUnkOuter
, REFIID iid
, void** ppv
)
330 MetadataHandler
*This
;
333 TRACE("%s\n", debugstr_guid(vtable
->clsid
));
337 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
339 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataHandler
));
340 if (!This
) return E_OUTOFMEMORY
;
342 This
->IWICMetadataWriter_iface
.lpVtbl
= &MetadataHandler_Vtbl
;
343 This
->IWICPersistStream_iface
.lpVtbl
= &MetadataHandler_PersistStream_Vtbl
;
345 This
->vtable
= vtable
;
347 This
->item_count
= 0;
349 InitializeCriticalSection(&This
->lock
);
350 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": MetadataHandler.lock");
352 hr
= IWICMetadataWriter_QueryInterface(&This
->IWICMetadataWriter_iface
, iid
, ppv
);
354 IWICMetadataWriter_Release(&This
->IWICMetadataWriter_iface
);
359 typedef struct MetadataHandlerEnum
{
360 IWICEnumMetadataItem IWICEnumMetadataItem_iface
;
362 MetadataHandler
*parent
;
364 } MetadataHandlerEnum
;
366 static inline MetadataHandlerEnum
*impl_from_IWICEnumMetadataItem(IWICEnumMetadataItem
*iface
)
368 return CONTAINING_RECORD(iface
, MetadataHandlerEnum
, IWICEnumMetadataItem_iface
);
371 static HRESULT WINAPI
MetadataHandlerEnum_QueryInterface(IWICEnumMetadataItem
*iface
, REFIID iid
,
374 MetadataHandlerEnum
*This
= impl_from_IWICEnumMetadataItem(iface
);
375 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
377 if (!ppv
) return E_INVALIDARG
;
379 if (IsEqualIID(&IID_IUnknown
, iid
) ||
380 IsEqualIID(&IID_IWICEnumMetadataItem
, iid
))
382 *ppv
= &This
->IWICEnumMetadataItem_iface
;
387 return E_NOINTERFACE
;
390 IUnknown_AddRef((IUnknown
*)*ppv
);
394 static ULONG WINAPI
MetadataHandlerEnum_AddRef(IWICEnumMetadataItem
*iface
)
396 MetadataHandlerEnum
*This
= impl_from_IWICEnumMetadataItem(iface
);
397 ULONG ref
= InterlockedIncrement(&This
->ref
);
399 TRACE("(%p) refcount=%u\n", iface
, ref
);
404 static ULONG WINAPI
MetadataHandlerEnum_Release(IWICEnumMetadataItem
*iface
)
406 MetadataHandlerEnum
*This
= impl_from_IWICEnumMetadataItem(iface
);
407 ULONG ref
= InterlockedDecrement(&This
->ref
);
409 TRACE("(%p) refcount=%u\n", iface
, ref
);
413 IWICMetadataWriter_Release(&This
->parent
->IWICMetadataWriter_iface
);
414 HeapFree(GetProcessHeap(), 0, This
);
420 static HRESULT WINAPI
MetadataHandlerEnum_Next(IWICEnumMetadataItem
*iface
,
421 ULONG celt
, PROPVARIANT
*rgeltSchema
, PROPVARIANT
*rgeltId
,
422 PROPVARIANT
*rgeltValue
, ULONG
*pceltFetched
)
424 MetadataHandlerEnum
*This
= impl_from_IWICEnumMetadataItem(iface
);
429 TRACE("(%p,%i)\n", iface
, celt
);
431 EnterCriticalSection(&This
->parent
->lock
);
433 if (This
->index
>= This
->parent
->item_count
)
436 LeaveCriticalSection(&This
->parent
->lock
);
440 new_index
= min(This
->parent
->item_count
, This
->index
+ celt
);
441 *pceltFetched
= new_index
- This
->index
;
445 for (i
=0; SUCCEEDED(hr
) && i
< *pceltFetched
; i
++)
446 hr
= PropVariantCopy(&rgeltSchema
[i
], &This
->parent
->items
[i
+This
->index
].schema
);
449 for (i
=0; SUCCEEDED(hr
) && i
< *pceltFetched
; i
++)
450 hr
= PropVariantCopy(&rgeltId
[i
], &This
->parent
->items
[i
+This
->index
].id
);
454 for (i
=0; SUCCEEDED(hr
) && i
< *pceltFetched
; i
++)
455 hr
= PropVariantCopy(&rgeltValue
[i
], &This
->parent
->items
[i
+This
->index
].value
);
460 This
->index
= new_index
;
463 LeaveCriticalSection(&This
->parent
->lock
);
468 static HRESULT WINAPI
MetadataHandlerEnum_Skip(IWICEnumMetadataItem
*iface
,
471 MetadataHandlerEnum
*This
= impl_from_IWICEnumMetadataItem(iface
);
473 EnterCriticalSection(&This
->parent
->lock
);
477 LeaveCriticalSection(&This
->parent
->lock
);
482 static HRESULT WINAPI
MetadataHandlerEnum_Reset(IWICEnumMetadataItem
*iface
)
484 MetadataHandlerEnum
*This
= impl_from_IWICEnumMetadataItem(iface
);
486 EnterCriticalSection(&This
->parent
->lock
);
490 LeaveCriticalSection(&This
->parent
->lock
);
495 static HRESULT WINAPI
MetadataHandlerEnum_Clone(IWICEnumMetadataItem
*iface
,
496 IWICEnumMetadataItem
**ppIEnumMetadataItem
)
498 MetadataHandlerEnum
*This
= impl_from_IWICEnumMetadataItem(iface
);
501 EnterCriticalSection(&This
->parent
->lock
);
503 hr
= MetadataHandlerEnum_Create(This
->parent
, This
->index
, ppIEnumMetadataItem
);
505 LeaveCriticalSection(&This
->parent
->lock
);
510 static const IWICEnumMetadataItemVtbl MetadataHandlerEnum_Vtbl
= {
511 MetadataHandlerEnum_QueryInterface
,
512 MetadataHandlerEnum_AddRef
,
513 MetadataHandlerEnum_Release
,
514 MetadataHandlerEnum_Next
,
515 MetadataHandlerEnum_Skip
,
516 MetadataHandlerEnum_Reset
,
517 MetadataHandlerEnum_Clone
520 static HRESULT
MetadataHandlerEnum_Create(MetadataHandler
*parent
, DWORD index
,
521 IWICEnumMetadataItem
**ppIEnumMetadataItem
)
523 MetadataHandlerEnum
*This
;
525 if (!ppIEnumMetadataItem
) return E_INVALIDARG
;
527 *ppIEnumMetadataItem
= NULL
;
529 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataHandlerEnum
));
530 if (!This
) return E_OUTOFMEMORY
;
532 IWICMetadataWriter_AddRef(&parent
->IWICMetadataWriter_iface
);
534 This
->IWICEnumMetadataItem_iface
.lpVtbl
= &MetadataHandlerEnum_Vtbl
;
536 This
->parent
= parent
;
539 *ppIEnumMetadataItem
= &This
->IWICEnumMetadataItem_iface
;
544 static HRESULT
LoadUnknownMetadata(IStream
*input
, const GUID
*preferred_vendor
,
545 DWORD persist_options
, MetadataItem
**items
, DWORD
*item_count
)
548 MetadataItem
*result
;
555 hr
= IStream_Stat(input
, &stat
, STATFLAG_NONAME
);
559 data
= HeapAlloc(GetProcessHeap(), 0, stat
.cbSize
.QuadPart
);
560 if (!data
) return E_OUTOFMEMORY
;
562 hr
= IStream_Read(input
, data
, stat
.cbSize
.QuadPart
, &bytesread
);
565 HeapFree(GetProcessHeap(), 0, data
);
569 result
= HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataItem
));
572 HeapFree(GetProcessHeap(), 0, data
);
573 return E_OUTOFMEMORY
;
576 PropVariantInit(&result
[0].schema
);
577 PropVariantInit(&result
[0].id
);
578 PropVariantInit(&result
[0].value
);
580 result
[0].value
.vt
= VT_BLOB
;
581 result
[0].value
.u
.blob
.cbSize
= bytesread
;
582 result
[0].value
.u
.blob
.pBlobData
= data
;
590 static const MetadataHandlerVtbl UnknownMetadataReader_Vtbl
= {
592 &CLSID_WICUnknownMetadataReader
,
596 HRESULT
UnknownMetadataReader_CreateInstance(IUnknown
*pUnkOuter
, REFIID iid
, void** ppv
)
598 return MetadataReader_Create(&UnknownMetadataReader_Vtbl
, pUnkOuter
, iid
, ppv
);