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
29 #include "wincodecsdk.h"
31 #include "wincodecs_private.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs
);
37 typedef struct MetadataHandler
{
38 IWICMetadataWriter IWICMetadataWriter_iface
;
40 IWICPersistStream IWICPersistStream_iface
;
41 const MetadataHandlerVtbl
*vtable
;
44 CRITICAL_SECTION lock
;
47 static inline MetadataHandler
*impl_from_IWICMetadataWriter(IWICMetadataWriter
*iface
)
49 return CONTAINING_RECORD(iface
, MetadataHandler
, IWICMetadataWriter_iface
);
52 static inline MetadataHandler
*impl_from_IWICPersistStream(IWICPersistStream
*iface
)
54 return CONTAINING_RECORD(iface
, MetadataHandler
, IWICPersistStream_iface
);
57 static void MetadataHandler_FreeItems(MetadataHandler
*This
)
61 for (i
=0; i
<This
->item_count
; i
++)
63 PropVariantClear(&This
->items
[i
].schema
);
64 PropVariantClear(&This
->items
[i
].id
);
65 PropVariantClear(&This
->items
[i
].value
);
68 HeapFree(GetProcessHeap(), 0, This
->items
);
71 static HRESULT
MetadataHandlerEnum_Create(MetadataHandler
*parent
, DWORD index
,
72 IWICEnumMetadataItem
**ppIEnumMetadataItem
);
74 static HRESULT WINAPI
MetadataHandler_QueryInterface(IWICMetadataWriter
*iface
, REFIID iid
,
77 MetadataHandler
*This
= impl_from_IWICMetadataWriter(iface
);
78 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
80 if (!ppv
) return E_INVALIDARG
;
82 if (IsEqualIID(&IID_IUnknown
, iid
) ||
83 IsEqualIID(&IID_IWICMetadataReader
, iid
) ||
84 (IsEqualIID(&IID_IWICMetadataWriter
, iid
) && This
->vtable
->is_writer
))
86 *ppv
= &This
->IWICMetadataWriter_iface
;
88 else if (IsEqualIID(&IID_IPersist
, iid
) ||
89 IsEqualIID(&IID_IPersistStream
, iid
) ||
90 IsEqualIID(&IID_IWICPersistStream
, iid
))
92 *ppv
= &This
->IWICPersistStream_iface
;
100 IUnknown_AddRef((IUnknown
*)*ppv
);
104 static ULONG WINAPI
MetadataHandler_AddRef(IWICMetadataWriter
*iface
)
106 MetadataHandler
*This
= impl_from_IWICMetadataWriter(iface
);
107 ULONG ref
= InterlockedIncrement(&This
->ref
);
109 TRACE("(%p) refcount=%u\n", iface
, ref
);
114 static ULONG WINAPI
MetadataHandler_Release(IWICMetadataWriter
*iface
)
116 MetadataHandler
*This
= impl_from_IWICMetadataWriter(iface
);
117 ULONG ref
= InterlockedDecrement(&This
->ref
);
119 TRACE("(%p) refcount=%u\n", iface
, ref
);
123 MetadataHandler_FreeItems(This
);
124 This
->lock
.DebugInfo
->Spare
[0] = 0;
125 DeleteCriticalSection(&This
->lock
);
126 HeapFree(GetProcessHeap(), 0, This
);
132 static HRESULT WINAPI
MetadataHandler_GetMetadataFormat(IWICMetadataWriter
*iface
,
133 GUID
*pguidMetadataFormat
)
135 FIXME("(%p,%s): stub\n", iface
, debugstr_guid(pguidMetadataFormat
));
139 static HRESULT WINAPI
MetadataHandler_GetMetadataHandlerInfo(IWICMetadataWriter
*iface
,
140 IWICMetadataHandlerInfo
**ppIHandler
)
142 FIXME("(%p,%p): stub\n", iface
, ppIHandler
);
146 static HRESULT WINAPI
MetadataHandler_GetCount(IWICMetadataWriter
*iface
,
149 FIXME("(%p,%p): stub\n", iface
, pcCount
);
153 static HRESULT WINAPI
MetadataHandler_GetValueByIndex(IWICMetadataWriter
*iface
,
154 UINT nIndex
, PROPVARIANT
*pvarSchema
, PROPVARIANT
*pvarId
, PROPVARIANT
*pvarValue
)
156 FIXME("(%p,%u,%p,%p,%p): stub\n", iface
, nIndex
, pvarSchema
, pvarId
, pvarValue
);
160 static HRESULT WINAPI
MetadataHandler_GetValue(IWICMetadataWriter
*iface
,
161 const PROPVARIANT
*pvarSchema
, const PROPVARIANT
*pvarId
, PROPVARIANT
*pvarValue
)
163 FIXME("(%p,%p,%p,%p): stub\n", iface
, pvarSchema
, pvarId
, pvarValue
);
167 static HRESULT WINAPI
MetadataHandler_GetEnumerator(IWICMetadataWriter
*iface
,
168 IWICEnumMetadataItem
**ppIEnumMetadata
)
170 MetadataHandler
*This
= impl_from_IWICMetadataWriter(iface
);
171 TRACE("(%p,%p)\n", iface
, ppIEnumMetadata
);
172 return MetadataHandlerEnum_Create(This
, 0, ppIEnumMetadata
);
175 static HRESULT WINAPI
MetadataHandler_SetValue(IWICMetadataWriter
*iface
,
176 const PROPVARIANT
*pvarSchema
, const PROPVARIANT
*pvarId
, const PROPVARIANT
*pvarValue
)
178 FIXME("(%p,%p,%p,%p): stub\n", iface
, pvarSchema
, pvarId
, pvarValue
);
182 static HRESULT WINAPI
MetadataHandler_SetValueByIndex(IWICMetadataWriter
*iface
,
183 UINT nIndex
, const PROPVARIANT
*pvarSchema
, const PROPVARIANT
*pvarId
, const PROPVARIANT
*pvarValue
)
185 FIXME("(%p,%u,%p,%p,%p): stub\n", iface
, nIndex
, pvarSchema
, pvarId
, pvarValue
);
189 static HRESULT WINAPI
MetadataHandler_RemoveValue(IWICMetadataWriter
*iface
,
190 const PROPVARIANT
*pvarSchema
, const PROPVARIANT
*pvarId
)
192 FIXME("(%p,%p,%p): stub\n", iface
, pvarSchema
, pvarId
);
196 static HRESULT WINAPI
MetadataHandler_RemoveValueByIndex(IWICMetadataWriter
*iface
,
199 FIXME("(%p,%u): stub\n", iface
, nIndex
);
203 static const IWICMetadataWriterVtbl MetadataHandler_Vtbl
= {
204 MetadataHandler_QueryInterface
,
205 MetadataHandler_AddRef
,
206 MetadataHandler_Release
,
207 MetadataHandler_GetMetadataFormat
,
208 MetadataHandler_GetMetadataHandlerInfo
,
209 MetadataHandler_GetCount
,
210 MetadataHandler_GetValueByIndex
,
211 MetadataHandler_GetValue
,
212 MetadataHandler_GetEnumerator
,
213 MetadataHandler_SetValue
,
214 MetadataHandler_SetValueByIndex
,
215 MetadataHandler_RemoveValue
,
216 MetadataHandler_RemoveValueByIndex
219 static HRESULT WINAPI
MetadataHandler_PersistStream_QueryInterface(IWICPersistStream
*iface
,
220 REFIID iid
, void **ppv
)
222 MetadataHandler
*This
= impl_from_IWICPersistStream(iface
);
223 return IWICMetadataWriter_QueryInterface(&This
->IWICMetadataWriter_iface
, iid
, ppv
);
226 static ULONG WINAPI
MetadataHandler_PersistStream_AddRef(IWICPersistStream
*iface
)
228 MetadataHandler
*This
= impl_from_IWICPersistStream(iface
);
229 return IWICMetadataWriter_AddRef(&This
->IWICMetadataWriter_iface
);
232 static ULONG WINAPI
MetadataHandler_PersistStream_Release(IWICPersistStream
*iface
)
234 MetadataHandler
*This
= impl_from_IWICPersistStream(iface
);
235 return IWICMetadataWriter_Release(&This
->IWICMetadataWriter_iface
);
238 static HRESULT WINAPI
MetadataHandler_GetClassID(IWICPersistStream
*iface
,
241 FIXME("(%p,%p): stub\n", iface
, pClassID
);
245 static HRESULT WINAPI
MetadataHandler_IsDirty(IWICPersistStream
*iface
)
247 FIXME("(%p): stub\n", iface
);
251 static HRESULT WINAPI
MetadataHandler_Load(IWICPersistStream
*iface
,
254 FIXME("(%p,%p): stub\n", iface
, pStm
);
258 static HRESULT WINAPI
MetadataHandler_Save(IWICPersistStream
*iface
,
259 IStream
*pStm
, BOOL fClearDirty
)
261 FIXME("(%p,%p,%i): stub\n", iface
, pStm
, fClearDirty
);
265 static HRESULT WINAPI
MetadataHandler_GetSizeMax(IWICPersistStream
*iface
,
266 ULARGE_INTEGER
*pcbSize
)
268 FIXME("(%p,%p): stub\n", iface
, pcbSize
);
272 static HRESULT WINAPI
MetadataHandler_LoadEx(IWICPersistStream
*iface
,
273 IStream
*pIStream
, const GUID
*pguidPreferredVendor
, DWORD dwPersistOptions
)
275 MetadataHandler
*This
= impl_from_IWICPersistStream(iface
);
277 MetadataItem
*new_items
=NULL
;
280 TRACE("(%p,%p,%s,%x)\n", iface
, pIStream
, debugstr_guid(pguidPreferredVendor
), dwPersistOptions
);
282 EnterCriticalSection(&This
->lock
);
284 hr
= This
->vtable
->fnLoad(pIStream
, pguidPreferredVendor
, dwPersistOptions
,
285 &new_items
, &item_count
);
289 MetadataHandler_FreeItems(This
);
290 This
->items
= new_items
;
291 This
->item_count
= item_count
;
294 LeaveCriticalSection(&This
->lock
);
299 static HRESULT WINAPI
MetadataHandler_SaveEx(IWICPersistStream
*iface
,
300 IStream
*pIStream
, DWORD dwPersistOptions
, BOOL fClearDirty
)
302 FIXME("(%p,%p,%x,%i): stub\n", iface
, pIStream
, dwPersistOptions
, fClearDirty
);
306 static const IWICPersistStreamVtbl MetadataHandler_PersistStream_Vtbl
= {
307 MetadataHandler_PersistStream_QueryInterface
,
308 MetadataHandler_PersistStream_AddRef
,
309 MetadataHandler_PersistStream_Release
,
310 MetadataHandler_GetClassID
,
311 MetadataHandler_IsDirty
,
312 MetadataHandler_Load
,
313 MetadataHandler_Save
,
314 MetadataHandler_GetSizeMax
,
315 MetadataHandler_LoadEx
,
316 MetadataHandler_SaveEx
319 HRESULT
MetadataReader_Create(const MetadataHandlerVtbl
*vtable
, IUnknown
*pUnkOuter
, REFIID iid
, void** ppv
)
321 MetadataHandler
*This
;
324 TRACE("%s\n", debugstr_guid(vtable
->clsid
));
328 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
330 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataHandler
));
331 if (!This
) return E_OUTOFMEMORY
;
333 This
->IWICMetadataWriter_iface
.lpVtbl
= &MetadataHandler_Vtbl
;
334 This
->IWICPersistStream_iface
.lpVtbl
= &MetadataHandler_PersistStream_Vtbl
;
336 This
->vtable
= vtable
;
338 This
->item_count
= 0;
340 InitializeCriticalSection(&This
->lock
);
341 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": MetadataHandler.lock");
343 hr
= IWICMetadataWriter_QueryInterface(&This
->IWICMetadataWriter_iface
, iid
, ppv
);
345 IWICMetadataWriter_Release(&This
->IWICMetadataWriter_iface
);
350 typedef struct MetadataHandlerEnum
{
351 IWICEnumMetadataItem IWICEnumMetadataItem_iface
;
353 MetadataHandler
*parent
;
355 } MetadataHandlerEnum
;
357 static inline MetadataHandlerEnum
*impl_from_IWICEnumMetadataItem(IWICEnumMetadataItem
*iface
)
359 return CONTAINING_RECORD(iface
, MetadataHandlerEnum
, IWICEnumMetadataItem_iface
);
362 static HRESULT WINAPI
MetadataHandlerEnum_QueryInterface(IWICEnumMetadataItem
*iface
, REFIID iid
,
365 MetadataHandlerEnum
*This
= impl_from_IWICEnumMetadataItem(iface
);
366 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
368 if (!ppv
) return E_INVALIDARG
;
370 if (IsEqualIID(&IID_IUnknown
, iid
) ||
371 IsEqualIID(&IID_IWICEnumMetadataItem
, iid
))
373 *ppv
= &This
->IWICEnumMetadataItem_iface
;
378 return E_NOINTERFACE
;
381 IUnknown_AddRef((IUnknown
*)*ppv
);
385 static ULONG WINAPI
MetadataHandlerEnum_AddRef(IWICEnumMetadataItem
*iface
)
387 MetadataHandlerEnum
*This
= impl_from_IWICEnumMetadataItem(iface
);
388 ULONG ref
= InterlockedIncrement(&This
->ref
);
390 TRACE("(%p) refcount=%u\n", iface
, ref
);
395 static ULONG WINAPI
MetadataHandlerEnum_Release(IWICEnumMetadataItem
*iface
)
397 MetadataHandlerEnum
*This
= impl_from_IWICEnumMetadataItem(iface
);
398 ULONG ref
= InterlockedDecrement(&This
->ref
);
400 TRACE("(%p) refcount=%u\n", iface
, ref
);
404 IWICMetadataWriter_Release(&This
->parent
->IWICMetadataWriter_iface
);
405 HeapFree(GetProcessHeap(), 0, This
);
411 static HRESULT WINAPI
MetadataHandlerEnum_Next(IWICEnumMetadataItem
*iface
,
412 ULONG celt
, PROPVARIANT
*rgeltSchema
, PROPVARIANT
*rgeltId
,
413 PROPVARIANT
*rgeltValue
, ULONG
*pceltFetched
)
415 MetadataHandlerEnum
*This
= impl_from_IWICEnumMetadataItem(iface
);
420 TRACE("(%p,%i)\n", iface
, celt
);
422 EnterCriticalSection(&This
->parent
->lock
);
424 if (This
->index
>= This
->parent
->item_count
)
427 LeaveCriticalSection(&This
->parent
->lock
);
431 new_index
= min(This
->parent
->item_count
, This
->index
+ celt
);
432 *pceltFetched
= new_index
- This
->index
;
436 for (i
=0; SUCCEEDED(hr
) && i
< *pceltFetched
; i
++)
437 hr
= PropVariantCopy(&rgeltSchema
[i
], &This
->parent
->items
[i
+This
->index
].schema
);
440 for (i
=0; SUCCEEDED(hr
) && i
< *pceltFetched
; i
++)
441 hr
= PropVariantCopy(&rgeltId
[i
], &This
->parent
->items
[i
+This
->index
].id
);
445 for (i
=0; SUCCEEDED(hr
) && i
< *pceltFetched
; i
++)
446 hr
= PropVariantCopy(&rgeltValue
[i
], &This
->parent
->items
[i
+This
->index
].value
);
451 This
->index
= new_index
;
454 LeaveCriticalSection(&This
->parent
->lock
);
459 static HRESULT WINAPI
MetadataHandlerEnum_Skip(IWICEnumMetadataItem
*iface
,
462 MetadataHandlerEnum
*This
= impl_from_IWICEnumMetadataItem(iface
);
464 EnterCriticalSection(&This
->parent
->lock
);
468 LeaveCriticalSection(&This
->parent
->lock
);
473 static HRESULT WINAPI
MetadataHandlerEnum_Reset(IWICEnumMetadataItem
*iface
)
475 MetadataHandlerEnum
*This
= impl_from_IWICEnumMetadataItem(iface
);
477 EnterCriticalSection(&This
->parent
->lock
);
481 LeaveCriticalSection(&This
->parent
->lock
);
486 static HRESULT WINAPI
MetadataHandlerEnum_Clone(IWICEnumMetadataItem
*iface
,
487 IWICEnumMetadataItem
**ppIEnumMetadataItem
)
489 MetadataHandlerEnum
*This
= impl_from_IWICEnumMetadataItem(iface
);
492 EnterCriticalSection(&This
->parent
->lock
);
494 hr
= MetadataHandlerEnum_Create(This
->parent
, This
->index
, ppIEnumMetadataItem
);
496 LeaveCriticalSection(&This
->parent
->lock
);
501 static const IWICEnumMetadataItemVtbl MetadataHandlerEnum_Vtbl
= {
502 MetadataHandlerEnum_QueryInterface
,
503 MetadataHandlerEnum_AddRef
,
504 MetadataHandlerEnum_Release
,
505 MetadataHandlerEnum_Next
,
506 MetadataHandlerEnum_Skip
,
507 MetadataHandlerEnum_Reset
,
508 MetadataHandlerEnum_Clone
511 static HRESULT
MetadataHandlerEnum_Create(MetadataHandler
*parent
, DWORD index
,
512 IWICEnumMetadataItem
**ppIEnumMetadataItem
)
514 MetadataHandlerEnum
*This
;
516 *ppIEnumMetadataItem
= NULL
;
518 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataHandlerEnum
));
519 if (!This
) return E_OUTOFMEMORY
;
521 IWICMetadataWriter_AddRef(&parent
->IWICMetadataWriter_iface
);
523 This
->IWICEnumMetadataItem_iface
.lpVtbl
= &MetadataHandlerEnum_Vtbl
;
525 This
->parent
= parent
;
528 *ppIEnumMetadataItem
= &This
->IWICEnumMetadataItem_iface
;
533 static HRESULT
LoadUnknownMetadata(IStream
*input
, const GUID
*preferred_vendor
,
534 DWORD persist_options
, MetadataItem
**items
, DWORD
*item_count
)
537 MetadataItem
*result
;
544 hr
= IStream_Stat(input
, &stat
, STATFLAG_NONAME
);
548 data
= HeapAlloc(GetProcessHeap(), 0, stat
.cbSize
.QuadPart
);
549 if (!data
) return E_OUTOFMEMORY
;
551 hr
= IStream_Read(input
, data
, stat
.cbSize
.QuadPart
, &bytesread
);
554 HeapFree(GetProcessHeap(), 0, data
);
558 result
= HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataItem
));
561 HeapFree(GetProcessHeap(), 0, data
);
562 return E_OUTOFMEMORY
;
565 PropVariantInit(&result
[0].schema
);
566 PropVariantInit(&result
[0].id
);
567 PropVariantInit(&result
[0].value
);
569 result
[0].value
.vt
= VT_BLOB
;
570 result
[0].value
.blob
.cbSize
= bytesread
;
571 result
[0].value
.blob
.pBlobData
= data
;
579 static const MetadataHandlerVtbl UnknownMetadataReader_Vtbl
= {
581 &CLSID_WICUnknownMetadataReader
,
585 HRESULT
UnknownMetadataReader_CreateInstance(IUnknown
*pUnkOuter
, REFIID iid
, void** ppv
)
587 return MetadataReader_Create(&UnknownMetadataReader_Vtbl
, pUnkOuter
, iid
, ppv
);