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 FIXME("(%p,%s): stub\n", iface
, debugstr_guid(pguidMetadataFormat
));
140 static HRESULT WINAPI
MetadataHandler_GetMetadataHandlerInfo(IWICMetadataWriter
*iface
,
141 IWICMetadataHandlerInfo
**ppIHandler
)
143 FIXME("(%p,%p): stub\n", iface
, ppIHandler
);
147 static HRESULT WINAPI
MetadataHandler_GetCount(IWICMetadataWriter
*iface
,
150 FIXME("(%p,%p): stub\n", iface
, pcCount
);
154 static HRESULT WINAPI
MetadataHandler_GetValueByIndex(IWICMetadataWriter
*iface
,
155 UINT nIndex
, PROPVARIANT
*pvarSchema
, PROPVARIANT
*pvarId
, PROPVARIANT
*pvarValue
)
157 FIXME("(%p,%u,%p,%p,%p): stub\n", iface
, nIndex
, pvarSchema
, pvarId
, pvarValue
);
161 static HRESULT WINAPI
MetadataHandler_GetValue(IWICMetadataWriter
*iface
,
162 const PROPVARIANT
*pvarSchema
, const PROPVARIANT
*pvarId
, PROPVARIANT
*pvarValue
)
164 FIXME("(%p,%p,%p,%p): stub\n", iface
, pvarSchema
, pvarId
, pvarValue
);
168 static HRESULT WINAPI
MetadataHandler_GetEnumerator(IWICMetadataWriter
*iface
,
169 IWICEnumMetadataItem
**ppIEnumMetadata
)
171 MetadataHandler
*This
= impl_from_IWICMetadataWriter(iface
);
172 TRACE("(%p,%p)\n", iface
, ppIEnumMetadata
);
173 return MetadataHandlerEnum_Create(This
, 0, ppIEnumMetadata
);
176 static HRESULT WINAPI
MetadataHandler_SetValue(IWICMetadataWriter
*iface
,
177 const PROPVARIANT
*pvarSchema
, const PROPVARIANT
*pvarId
, const PROPVARIANT
*pvarValue
)
179 FIXME("(%p,%p,%p,%p): stub\n", iface
, pvarSchema
, pvarId
, pvarValue
);
183 static HRESULT WINAPI
MetadataHandler_SetValueByIndex(IWICMetadataWriter
*iface
,
184 UINT nIndex
, const PROPVARIANT
*pvarSchema
, const PROPVARIANT
*pvarId
, const PROPVARIANT
*pvarValue
)
186 FIXME("(%p,%u,%p,%p,%p): stub\n", iface
, nIndex
, pvarSchema
, pvarId
, pvarValue
);
190 static HRESULT WINAPI
MetadataHandler_RemoveValue(IWICMetadataWriter
*iface
,
191 const PROPVARIANT
*pvarSchema
, const PROPVARIANT
*pvarId
)
193 FIXME("(%p,%p,%p): stub\n", iface
, pvarSchema
, pvarId
);
197 static HRESULT WINAPI
MetadataHandler_RemoveValueByIndex(IWICMetadataWriter
*iface
,
200 FIXME("(%p,%u): stub\n", iface
, nIndex
);
204 static const IWICMetadataWriterVtbl MetadataHandler_Vtbl
= {
205 MetadataHandler_QueryInterface
,
206 MetadataHandler_AddRef
,
207 MetadataHandler_Release
,
208 MetadataHandler_GetMetadataFormat
,
209 MetadataHandler_GetMetadataHandlerInfo
,
210 MetadataHandler_GetCount
,
211 MetadataHandler_GetValueByIndex
,
212 MetadataHandler_GetValue
,
213 MetadataHandler_GetEnumerator
,
214 MetadataHandler_SetValue
,
215 MetadataHandler_SetValueByIndex
,
216 MetadataHandler_RemoveValue
,
217 MetadataHandler_RemoveValueByIndex
220 static HRESULT WINAPI
MetadataHandler_PersistStream_QueryInterface(IWICPersistStream
*iface
,
221 REFIID iid
, void **ppv
)
223 MetadataHandler
*This
= impl_from_IWICPersistStream(iface
);
224 return IWICMetadataWriter_QueryInterface(&This
->IWICMetadataWriter_iface
, iid
, ppv
);
227 static ULONG WINAPI
MetadataHandler_PersistStream_AddRef(IWICPersistStream
*iface
)
229 MetadataHandler
*This
= impl_from_IWICPersistStream(iface
);
230 return IWICMetadataWriter_AddRef(&This
->IWICMetadataWriter_iface
);
233 static ULONG WINAPI
MetadataHandler_PersistStream_Release(IWICPersistStream
*iface
)
235 MetadataHandler
*This
= impl_from_IWICPersistStream(iface
);
236 return IWICMetadataWriter_Release(&This
->IWICMetadataWriter_iface
);
239 static HRESULT WINAPI
MetadataHandler_GetClassID(IWICPersistStream
*iface
,
242 FIXME("(%p,%p): stub\n", iface
, pClassID
);
246 static HRESULT WINAPI
MetadataHandler_IsDirty(IWICPersistStream
*iface
)
248 FIXME("(%p): stub\n", iface
);
252 static HRESULT WINAPI
MetadataHandler_Load(IWICPersistStream
*iface
,
255 FIXME("(%p,%p): stub\n", iface
, pStm
);
259 static HRESULT WINAPI
MetadataHandler_Save(IWICPersistStream
*iface
,
260 IStream
*pStm
, BOOL fClearDirty
)
262 FIXME("(%p,%p,%i): stub\n", iface
, pStm
, fClearDirty
);
266 static HRESULT WINAPI
MetadataHandler_GetSizeMax(IWICPersistStream
*iface
,
267 ULARGE_INTEGER
*pcbSize
)
269 FIXME("(%p,%p): stub\n", iface
, pcbSize
);
273 static HRESULT WINAPI
MetadataHandler_LoadEx(IWICPersistStream
*iface
,
274 IStream
*pIStream
, const GUID
*pguidPreferredVendor
, DWORD dwPersistOptions
)
276 MetadataHandler
*This
= impl_from_IWICPersistStream(iface
);
278 MetadataItem
*new_items
=NULL
;
281 TRACE("(%p,%p,%s,%x)\n", iface
, pIStream
, debugstr_guid(pguidPreferredVendor
), dwPersistOptions
);
283 EnterCriticalSection(&This
->lock
);
285 hr
= This
->vtable
->fnLoad(pIStream
, pguidPreferredVendor
, dwPersistOptions
,
286 &new_items
, &item_count
);
290 MetadataHandler_FreeItems(This
);
291 This
->items
= new_items
;
292 This
->item_count
= item_count
;
295 LeaveCriticalSection(&This
->lock
);
300 static HRESULT WINAPI
MetadataHandler_SaveEx(IWICPersistStream
*iface
,
301 IStream
*pIStream
, DWORD dwPersistOptions
, BOOL fClearDirty
)
303 FIXME("(%p,%p,%x,%i): stub\n", iface
, pIStream
, dwPersistOptions
, fClearDirty
);
307 static const IWICPersistStreamVtbl MetadataHandler_PersistStream_Vtbl
= {
308 MetadataHandler_PersistStream_QueryInterface
,
309 MetadataHandler_PersistStream_AddRef
,
310 MetadataHandler_PersistStream_Release
,
311 MetadataHandler_GetClassID
,
312 MetadataHandler_IsDirty
,
313 MetadataHandler_Load
,
314 MetadataHandler_Save
,
315 MetadataHandler_GetSizeMax
,
316 MetadataHandler_LoadEx
,
317 MetadataHandler_SaveEx
320 HRESULT
MetadataReader_Create(const MetadataHandlerVtbl
*vtable
, IUnknown
*pUnkOuter
, REFIID iid
, void** ppv
)
322 MetadataHandler
*This
;
325 TRACE("%s\n", debugstr_guid(vtable
->clsid
));
329 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
331 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataHandler
));
332 if (!This
) return E_OUTOFMEMORY
;
334 This
->IWICMetadataWriter_iface
.lpVtbl
= &MetadataHandler_Vtbl
;
335 This
->IWICPersistStream_iface
.lpVtbl
= &MetadataHandler_PersistStream_Vtbl
;
337 This
->vtable
= vtable
;
339 This
->item_count
= 0;
341 InitializeCriticalSection(&This
->lock
);
342 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": MetadataHandler.lock");
344 hr
= IWICMetadataWriter_QueryInterface(&This
->IWICMetadataWriter_iface
, iid
, ppv
);
346 IWICMetadataWriter_Release(&This
->IWICMetadataWriter_iface
);
351 typedef struct MetadataHandlerEnum
{
352 IWICEnumMetadataItem IWICEnumMetadataItem_iface
;
354 MetadataHandler
*parent
;
356 } MetadataHandlerEnum
;
358 static inline MetadataHandlerEnum
*impl_from_IWICEnumMetadataItem(IWICEnumMetadataItem
*iface
)
360 return CONTAINING_RECORD(iface
, MetadataHandlerEnum
, IWICEnumMetadataItem_iface
);
363 static HRESULT WINAPI
MetadataHandlerEnum_QueryInterface(IWICEnumMetadataItem
*iface
, REFIID iid
,
366 MetadataHandlerEnum
*This
= impl_from_IWICEnumMetadataItem(iface
);
367 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
369 if (!ppv
) return E_INVALIDARG
;
371 if (IsEqualIID(&IID_IUnknown
, iid
) ||
372 IsEqualIID(&IID_IWICEnumMetadataItem
, iid
))
374 *ppv
= &This
->IWICEnumMetadataItem_iface
;
379 return E_NOINTERFACE
;
382 IUnknown_AddRef((IUnknown
*)*ppv
);
386 static ULONG WINAPI
MetadataHandlerEnum_AddRef(IWICEnumMetadataItem
*iface
)
388 MetadataHandlerEnum
*This
= impl_from_IWICEnumMetadataItem(iface
);
389 ULONG ref
= InterlockedIncrement(&This
->ref
);
391 TRACE("(%p) refcount=%u\n", iface
, ref
);
396 static ULONG WINAPI
MetadataHandlerEnum_Release(IWICEnumMetadataItem
*iface
)
398 MetadataHandlerEnum
*This
= impl_from_IWICEnumMetadataItem(iface
);
399 ULONG ref
= InterlockedDecrement(&This
->ref
);
401 TRACE("(%p) refcount=%u\n", iface
, ref
);
405 IWICMetadataWriter_Release(&This
->parent
->IWICMetadataWriter_iface
);
406 HeapFree(GetProcessHeap(), 0, This
);
412 static HRESULT WINAPI
MetadataHandlerEnum_Next(IWICEnumMetadataItem
*iface
,
413 ULONG celt
, PROPVARIANT
*rgeltSchema
, PROPVARIANT
*rgeltId
,
414 PROPVARIANT
*rgeltValue
, ULONG
*pceltFetched
)
416 MetadataHandlerEnum
*This
= impl_from_IWICEnumMetadataItem(iface
);
421 TRACE("(%p,%i)\n", iface
, celt
);
423 EnterCriticalSection(&This
->parent
->lock
);
425 if (This
->index
>= This
->parent
->item_count
)
428 LeaveCriticalSection(&This
->parent
->lock
);
432 new_index
= min(This
->parent
->item_count
, This
->index
+ celt
);
433 *pceltFetched
= new_index
- This
->index
;
437 for (i
=0; SUCCEEDED(hr
) && i
< *pceltFetched
; i
++)
438 hr
= PropVariantCopy(&rgeltSchema
[i
], &This
->parent
->items
[i
+This
->index
].schema
);
441 for (i
=0; SUCCEEDED(hr
) && i
< *pceltFetched
; i
++)
442 hr
= PropVariantCopy(&rgeltId
[i
], &This
->parent
->items
[i
+This
->index
].id
);
446 for (i
=0; SUCCEEDED(hr
) && i
< *pceltFetched
; i
++)
447 hr
= PropVariantCopy(&rgeltValue
[i
], &This
->parent
->items
[i
+This
->index
].value
);
452 This
->index
= new_index
;
455 LeaveCriticalSection(&This
->parent
->lock
);
460 static HRESULT WINAPI
MetadataHandlerEnum_Skip(IWICEnumMetadataItem
*iface
,
463 MetadataHandlerEnum
*This
= impl_from_IWICEnumMetadataItem(iface
);
465 EnterCriticalSection(&This
->parent
->lock
);
469 LeaveCriticalSection(&This
->parent
->lock
);
474 static HRESULT WINAPI
MetadataHandlerEnum_Reset(IWICEnumMetadataItem
*iface
)
476 MetadataHandlerEnum
*This
= impl_from_IWICEnumMetadataItem(iface
);
478 EnterCriticalSection(&This
->parent
->lock
);
482 LeaveCriticalSection(&This
->parent
->lock
);
487 static HRESULT WINAPI
MetadataHandlerEnum_Clone(IWICEnumMetadataItem
*iface
,
488 IWICEnumMetadataItem
**ppIEnumMetadataItem
)
490 MetadataHandlerEnum
*This
= impl_from_IWICEnumMetadataItem(iface
);
493 EnterCriticalSection(&This
->parent
->lock
);
495 hr
= MetadataHandlerEnum_Create(This
->parent
, This
->index
, ppIEnumMetadataItem
);
497 LeaveCriticalSection(&This
->parent
->lock
);
502 static const IWICEnumMetadataItemVtbl MetadataHandlerEnum_Vtbl
= {
503 MetadataHandlerEnum_QueryInterface
,
504 MetadataHandlerEnum_AddRef
,
505 MetadataHandlerEnum_Release
,
506 MetadataHandlerEnum_Next
,
507 MetadataHandlerEnum_Skip
,
508 MetadataHandlerEnum_Reset
,
509 MetadataHandlerEnum_Clone
512 static HRESULT
MetadataHandlerEnum_Create(MetadataHandler
*parent
, DWORD index
,
513 IWICEnumMetadataItem
**ppIEnumMetadataItem
)
515 MetadataHandlerEnum
*This
;
517 *ppIEnumMetadataItem
= NULL
;
519 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataHandlerEnum
));
520 if (!This
) return E_OUTOFMEMORY
;
522 IWICMetadataWriter_AddRef(&parent
->IWICMetadataWriter_iface
);
524 This
->IWICEnumMetadataItem_iface
.lpVtbl
= &MetadataHandlerEnum_Vtbl
;
526 This
->parent
= parent
;
529 *ppIEnumMetadataItem
= &This
->IWICEnumMetadataItem_iface
;
534 static HRESULT
LoadUnknownMetadata(IStream
*input
, const GUID
*preferred_vendor
,
535 DWORD persist_options
, MetadataItem
**items
, DWORD
*item_count
)
538 MetadataItem
*result
;
545 hr
= IStream_Stat(input
, &stat
, STATFLAG_NONAME
);
549 data
= HeapAlloc(GetProcessHeap(), 0, stat
.cbSize
.QuadPart
);
550 if (!data
) return E_OUTOFMEMORY
;
552 hr
= IStream_Read(input
, data
, stat
.cbSize
.QuadPart
, &bytesread
);
555 HeapFree(GetProcessHeap(), 0, data
);
559 result
= HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataItem
));
562 HeapFree(GetProcessHeap(), 0, data
);
563 return E_OUTOFMEMORY
;
566 PropVariantInit(&result
[0].schema
);
567 PropVariantInit(&result
[0].id
);
568 PropVariantInit(&result
[0].value
);
570 result
[0].value
.vt
= VT_BLOB
;
571 result
[0].value
.u
.blob
.cbSize
= bytesread
;
572 result
[0].value
.u
.blob
.pBlobData
= data
;
580 static const MetadataHandlerVtbl UnknownMetadataReader_Vtbl
= {
582 &CLSID_WICUnknownMetadataReader
,
586 HRESULT
UnknownMetadataReader_CreateInstance(IUnknown
*pUnkOuter
, REFIID iid
, void** ppv
)
588 return MetadataReader_Create(&UnknownMetadataReader_Vtbl
, pUnkOuter
, iid
, ppv
);