From 31be8a19d97682dbd633cef50d9d6fdcbeee8e83 Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Wed, 11 Jan 2012 17:16:41 -0600 Subject: [PATCH] windowscodecs: Implement IWICMetadataWriter::GetEnumerator. --- dlls/windowscodecs/metadatahandler.c | 191 ++++++++++++++++++++++++++- dlls/windowscodecs/tests/metadata.c | 2 +- 2 files changed, 190 insertions(+), 3 deletions(-) diff --git a/dlls/windowscodecs/metadatahandler.c b/dlls/windowscodecs/metadatahandler.c index 0e916f2105c..23854d8c0bd 100644 --- a/dlls/windowscodecs/metadatahandler.c +++ b/dlls/windowscodecs/metadatahandler.c @@ -68,6 +68,9 @@ static void MetadataHandler_FreeItems(MetadataHandler *This) HeapFree(GetProcessHeap(), 0, This->items); } +static HRESULT MetadataHandlerEnum_Create(MetadataHandler *parent, DWORD index, + IWICEnumMetadataItem **ppIEnumMetadataItem); + static HRESULT WINAPI MetadataHandler_QueryInterface(IWICMetadataWriter *iface, REFIID iid, void **ppv) { @@ -164,8 +167,9 @@ static HRESULT WINAPI MetadataHandler_GetValue(IWICMetadataWriter *iface, static HRESULT WINAPI MetadataHandler_GetEnumerator(IWICMetadataWriter *iface, IWICEnumMetadataItem **ppIEnumMetadata) { - FIXME("(%p,%p): stub\n", iface, ppIEnumMetadata); - return E_NOTIMPL; + MetadataHandler *This = impl_from_IWICMetadataWriter(iface); + TRACE("(%p,%p)\n", iface, ppIEnumMetadata); + return MetadataHandlerEnum_Create(This, 0, ppIEnumMetadata); } static HRESULT WINAPI MetadataHandler_SetValue(IWICMetadataWriter *iface, @@ -343,6 +347,189 @@ HRESULT MetadataReader_Create(const MetadataHandlerVtbl *vtable, IUnknown *pUnkO return hr; } +typedef struct MetadataHandlerEnum { + IWICEnumMetadataItem IWICEnumMetadataItem_iface; + LONG ref; + MetadataHandler *parent; + DWORD index; +} MetadataHandlerEnum; + +static inline MetadataHandlerEnum *impl_from_IWICEnumMetadataItem(IWICEnumMetadataItem *iface) +{ + return CONTAINING_RECORD(iface, MetadataHandlerEnum, IWICEnumMetadataItem_iface); +} + +static HRESULT WINAPI MetadataHandlerEnum_QueryInterface(IWICEnumMetadataItem *iface, REFIID iid, + void **ppv) +{ + MetadataHandlerEnum *This = impl_from_IWICEnumMetadataItem(iface); + TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); + + if (!ppv) return E_INVALIDARG; + + if (IsEqualIID(&IID_IUnknown, iid) || + IsEqualIID(&IID_IWICEnumMetadataItem, iid)) + { + *ppv = &This->IWICEnumMetadataItem_iface; + } + else + { + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI MetadataHandlerEnum_AddRef(IWICEnumMetadataItem *iface) +{ + MetadataHandlerEnum *This = impl_from_IWICEnumMetadataItem(iface); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) refcount=%u\n", iface, ref); + + return ref; +} + +static ULONG WINAPI MetadataHandlerEnum_Release(IWICEnumMetadataItem *iface) +{ + MetadataHandlerEnum *This = impl_from_IWICEnumMetadataItem(iface); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) refcount=%u\n", iface, ref); + + if (ref == 0) + { + IWICMetadataWriter_Release(&This->parent->IWICMetadataWriter_iface); + HeapFree(GetProcessHeap(), 0, This); + } + + return ref; +} + +static HRESULT WINAPI MetadataHandlerEnum_Next(IWICEnumMetadataItem *iface, + ULONG celt, PROPVARIANT *rgeltSchema, PROPVARIANT *rgeltId, + PROPVARIANT *rgeltValue, ULONG *pceltFetched) +{ + MetadataHandlerEnum *This = impl_from_IWICEnumMetadataItem(iface); + ULONG new_index; + HRESULT hr=S_FALSE; + int i; + + TRACE("(%p,%i)\n", iface, celt); + + EnterCriticalSection(&This->parent->lock); + + if (This->index >= This->parent->item_count) + { + *pceltFetched = 0; + LeaveCriticalSection(&This->parent->lock); + return S_FALSE; + } + + new_index = min(This->parent->item_count, This->index + celt); + *pceltFetched = new_index - This->index; + + if (rgeltSchema) + { + for (i=0; SUCCEEDED(hr) && i < *pceltFetched; i++) + hr = PropVariantCopy(&rgeltSchema[i], &This->parent->items[i+This->index].schema); + } + + for (i=0; SUCCEEDED(hr) && i < *pceltFetched; i++) + hr = PropVariantCopy(&rgeltId[i], &This->parent->items[i+This->index].id); + + if (rgeltValue) + { + for (i=0; SUCCEEDED(hr) && i < *pceltFetched; i++) + hr = PropVariantCopy(&rgeltValue[i], &This->parent->items[i+This->index].value); + } + + if (SUCCEEDED(hr)) + { + This->index = new_index; + } + + LeaveCriticalSection(&This->parent->lock); + + return hr; +} + +static HRESULT WINAPI MetadataHandlerEnum_Skip(IWICEnumMetadataItem *iface, + ULONG celt) +{ + MetadataHandlerEnum *This = impl_from_IWICEnumMetadataItem(iface); + + EnterCriticalSection(&This->parent->lock); + + This->index += celt; + + LeaveCriticalSection(&This->parent->lock); + + return S_OK; +} + +static HRESULT WINAPI MetadataHandlerEnum_Reset(IWICEnumMetadataItem *iface) +{ + MetadataHandlerEnum *This = impl_from_IWICEnumMetadataItem(iface); + + EnterCriticalSection(&This->parent->lock); + + This->index = 0; + + LeaveCriticalSection(&This->parent->lock); + + return S_OK; +} + +static HRESULT WINAPI MetadataHandlerEnum_Clone(IWICEnumMetadataItem *iface, + IWICEnumMetadataItem **ppIEnumMetadataItem) +{ + MetadataHandlerEnum *This = impl_from_IWICEnumMetadataItem(iface); + HRESULT hr; + + EnterCriticalSection(&This->parent->lock); + + hr = MetadataHandlerEnum_Create(This->parent, This->index, ppIEnumMetadataItem); + + LeaveCriticalSection(&This->parent->lock); + + return hr; +} + +static const IWICEnumMetadataItemVtbl MetadataHandlerEnum_Vtbl = { + MetadataHandlerEnum_QueryInterface, + MetadataHandlerEnum_AddRef, + MetadataHandlerEnum_Release, + MetadataHandlerEnum_Next, + MetadataHandlerEnum_Skip, + MetadataHandlerEnum_Reset, + MetadataHandlerEnum_Clone +}; + +static HRESULT MetadataHandlerEnum_Create(MetadataHandler *parent, DWORD index, + IWICEnumMetadataItem **ppIEnumMetadataItem) +{ + MetadataHandlerEnum *This; + + *ppIEnumMetadataItem = NULL; + + This = HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataHandlerEnum)); + if (!This) return E_OUTOFMEMORY; + + IWICMetadataWriter_AddRef(&parent->IWICMetadataWriter_iface); + + This->IWICEnumMetadataItem_iface.lpVtbl = &MetadataHandlerEnum_Vtbl; + This->ref = 1; + This->parent = parent; + This->index = index; + + *ppIEnumMetadataItem = &This->IWICEnumMetadataItem_iface; + + return S_OK; +} + static HRESULT LoadUnknownMetadata(IStream *input, const GUID *preferred_vendor, DWORD persist_options, MetadataItem **items, DWORD *item_count) { diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index 43c6f4802d1..4cfc53c4823 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -124,7 +124,7 @@ static void test_metadata_unknown(void) load_stream((IUnknown*)reader, metadata_unknown, sizeof(metadata_unknown)); hr = IWICMetadataReader_GetEnumerator(reader, &enumerator); - todo_wine ok(hr == S_OK, "GetEnumerator failed, hr=%x\n", hr); + ok(hr == S_OK, "GetEnumerator failed, hr=%x\n", hr); if (SUCCEEDED(hr)) {