Vincent Povirk : windowscodecs: Implement IWICMetadataWriter::GetEnumerator .

Alexandre Julliard julliard at winehq.org
Thu Jan 12 13:19:20 CST 2012


Module: wine
Branch: master
Commit: 31be8a19d97682dbd633cef50d9d6fdcbeee8e83
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=31be8a19d97682dbd633cef50d9d6fdcbeee8e83

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Wed Jan 11 17:16:41 2012 -0600

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 0e916f2..23854d8 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 43c6f48..4cfc53c 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))
     {




More information about the wine-cvs mailing list