[PATCH 04/11] mfplat: Implement IMFAttributes::{SetItem,GetItem}.

Jactry Zeng jzeng at codeweavers.com
Fri Dec 28 09:42:14 CST 2018


Signed-off-by: Jactry Zeng <jzeng at codeweavers.com>
---
 dlls/mfplat/main.c            | 142 ++++++++++++++++++++++++++++++++--
 dlls/mfplat/tests/Makefile.in |   2 +-
 dlls/mfplat/tests/mfplat.c    |  69 +++++++++++++++++
 3 files changed, 207 insertions(+), 6 deletions(-)

diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c
index c7c346512f..6e056b3609 100644
--- a/dlls/mfplat/main.c
+++ b/dlls/mfplat/main.c
@@ -35,6 +35,7 @@
 #include "wine/heap.h"
 #include "wine/debug.h"
 #include "wine/unicode.h"
+#include "wine/list.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
 
@@ -448,10 +449,19 @@ HRESULT WINAPI MFCopyImage(BYTE *dest, LONG deststride, const BYTE *src, LONG sr
     return E_NOTIMPL;
 }
 
+struct mfattribute
+{
+    struct list entry;
+    GUID key;
+    PROPVARIANT value;
+};
+
 typedef struct _mfattributes
 {
     IMFAttributes IMFAttributes_iface;
     LONG ref;
+    CRITICAL_SECTION lock;
+    struct list attributes;
 } mfattributes;
 
 static inline mfattributes *impl_from_IMFAttributes(IMFAttributes *iface)
@@ -491,6 +501,8 @@ static ULONG WINAPI mfattributes_AddRef(IMFAttributes *iface)
     return ref;
 }
 
+static void free_attribute_object(mfattributes *object);
+
 static ULONG WINAPI mfattributes_Release(IMFAttributes *iface)
 {
     mfattributes *This = impl_from_IMFAttributes(iface);
@@ -500,19 +512,50 @@ static ULONG WINAPI mfattributes_Release(IMFAttributes *iface)
 
     if (!ref)
     {
+        free_attribute_object(This);
         HeapFree(GetProcessHeap(), 0, This);
     }
 
     return ref;
 }
 
+static HRESULT mfattributes_getitem(mfattributes *object, REFGUID key, PROPVARIANT *value, BOOL verify_type)
+{
+    struct mfattribute *attribute, *attribute2;
+    HRESULT hres;
+
+    EnterCriticalSection(&object->lock);
+
+    LIST_FOR_EACH_ENTRY_SAFE(attribute, attribute2, &object->attributes, struct mfattribute, entry)
+    {
+        if(IsEqualGUID(key, &attribute->key))
+        {
+            if(verify_type && ((value->vt && attribute->value.vt != value->vt) ||
+                              (value->vt == VT_UNKNOWN && !attribute->value.punkVal)))
+                hres = MF_E_INVALIDTYPE;
+            else
+            {
+                PropVariantCopy(value, &attribute->value);
+                hres = S_OK;
+            }
+            break;
+        }
+        else
+            hres = MF_E_ATTRIBUTENOTFOUND;
+    }
+
+    LeaveCriticalSection(&object->lock);
+
+    return hres;
+}
+
 static HRESULT WINAPI mfattributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
 {
     mfattributes *This = impl_from_IMFAttributes(iface);
 
-    FIXME("%p, %s, %p\n", This, debugstr_guid(key), value);
+    TRACE("(%p, %s, %p)\n", This, debugstr_guid(key), value);
 
-    return E_NOTIMPL;
+    return mfattributes_getitem(This, key, value, FALSE);
 }
 
 static HRESULT WINAPI mfattributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
@@ -645,13 +688,71 @@ static HRESULT WINAPI mfattributes_GetUnknown(IMFAttributes *iface, REFGUID key,
     return E_NOTIMPL;
 }
 
-static HRESULT WINAPI mfattributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT Value)
+static HRESULT mfattribute_setitem(mfattributes *object, REFGUID key, REFPROPVARIANT value)
+{
+    struct mfattribute *attribute, *attribute2, *new_attribute = NULL;
+
+    EnterCriticalSection(&object->lock);
+
+    LIST_FOR_EACH_ENTRY_SAFE(attribute, attribute2, &object->attributes, struct mfattribute, entry)
+        if(IsEqualGUID(key, &attribute->key))
+        {
+            new_attribute = attribute;
+            PropVariantClear(&new_attribute->value);
+            break;
+        }
+
+    if(!new_attribute)
+    {
+        new_attribute = heap_alloc(sizeof(struct mfattribute));
+        if(!new_attribute)
+        {
+            LeaveCriticalSection(&object->lock);
+            return E_OUTOFMEMORY;
+        }
+        new_attribute->key = *key;
+        list_add_tail(&object->attributes, &new_attribute->entry);
+    }
+    PropVariantCopy(&new_attribute->value, value);
+
+    LeaveCriticalSection(&object->lock);
+
+    return S_OK;
+ }
+
+static BOOL is_type_valid(DWORD type)
+{
+    switch(type)
+    {
+        case MF_ATTRIBUTE_UINT32:
+        case MF_ATTRIBUTE_UINT64:
+        case MF_ATTRIBUTE_DOUBLE:
+        case MF_ATTRIBUTE_GUID:
+        case MF_ATTRIBUTE_STRING:
+        case MF_ATTRIBUTE_BLOB:
+        case MF_ATTRIBUTE_IUNKNOWN:
+            return TRUE;
+        default:
+            return FALSE;
+    }
+}
+
+static HRESULT WINAPI mfattributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
 {
     mfattributes *This = impl_from_IMFAttributes(iface);
 
-    FIXME("%p, %s, %p\n", This, debugstr_guid(key), Value);
+    TRACE("(%p, %s, %p)\n", This, debugstr_guid(key), value);
 
-    return E_NOTIMPL;
+    if(!is_type_valid(value->vt))
+    {
+        PROPVARIANT empty_value;
+
+        PropVariantClear(&empty_value);
+        mfattribute_setitem(This, key, &empty_value);
+        return MF_E_INVALIDTYPE;
+    }
+    else
+        return mfattribute_setitem(This, key, value);
 }
 
 static HRESULT WINAPI mfattributes_DeleteItem(IMFAttributes *iface, REFGUID key)
@@ -824,6 +925,31 @@ static void init_attribute_object(mfattributes *object, UINT32 size)
 {
     object->ref = 1;
     object->IMFAttributes_iface.lpVtbl = &mfattributes_vtbl;
+    InitializeCriticalSection(&object->lock);
+    object->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IMFAttributes.lock");
+    list_init(&object->attributes);
+}
+
+static void free_attribute_object(mfattributes *object)
+{
+    EnterCriticalSection(&object->lock);
+
+    if (!list_empty(&object->attributes))
+    {
+        struct mfattribute *attribute, *attribute2;
+
+        LIST_FOR_EACH_ENTRY_SAFE(attribute, attribute2, &object->attributes, struct mfattribute, entry)
+        {
+            PropVariantClear(&attribute->value);
+            list_remove(&attribute->entry);
+            heap_free(attribute);
+        }
+    }
+
+    LeaveCriticalSection(&object->lock);
+
+    object->lock.DebugInfo->Spare[0] = 0;
+    DeleteCriticalSection(&object->lock);
 }
 
 /***********************************************************************
@@ -901,6 +1027,7 @@ static ULONG WINAPI mfbytestream_Release(IMFByteStream *iface)
 
     if (!ref)
     {
+        free_attribute_object(&This->attributes);
         HeapFree(GetProcessHeap(), 0, This);
     }
 
@@ -1368,6 +1495,7 @@ static ULONG WINAPI mfpresentationdescriptor_Release(IMFPresentationDescriptor *
 
     if (!ref)
     {
+        free_attribute_object(&This->attributes);
         HeapFree(GetProcessHeap(), 0, This);
     }
 
@@ -2064,6 +2192,7 @@ static ULONG WINAPI mediatype_Release(IMFMediaType *iface)
 
     if (!ref)
     {
+        free_attribute_object(&This->attributes);
         HeapFree(GetProcessHeap(), 0, This);
     }
 
@@ -2426,6 +2555,7 @@ static ULONG WINAPI mfmediaevent_Release(IMFMediaEvent *iface)
 
     if (!ref)
     {
+        free_attribute_object(&This->attributes);
         HeapFree(GetProcessHeap(), 0, This);
     }
 
@@ -2940,6 +3070,7 @@ static ULONG WINAPI mfdescriptor_Release(IMFStreamDescriptor *iface)
 
     if (!ref)
     {
+        free_attribute_object(&This->attributes);
         heap_free(This);
     }
 
@@ -3437,6 +3568,7 @@ static ULONG WINAPI mfsample_Release(IMFSample *iface)
 
     if (!ref)
     {
+        free_attribute_object(&This->attributes);
         heap_free(This);
     }
 
diff --git a/dlls/mfplat/tests/Makefile.in b/dlls/mfplat/tests/Makefile.in
index 07cf328ad2..e80a3b7cfc 100644
--- a/dlls/mfplat/tests/Makefile.in
+++ b/dlls/mfplat/tests/Makefile.in
@@ -1,5 +1,5 @@
 TESTDLL   = mfplat.dll
-IMPORTS   = ole32 mfplat
+IMPORTS   = ole32 mfplat propsys
 
 C_SRCS = \
 	mfplat.c
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index 3fa59f4816..fff424e798 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -33,6 +33,7 @@
 #include "mfidl.h"
 #include "mferror.h"
 #include "mfreadwrite.h"
+#include "propvarutil.h"
 
 #include "wine/test.h"
 
@@ -693,6 +694,73 @@ static void test_MFSample(void)
     IMFSample_Release(sample);
 }
 
+static void test_IMFAttributes_item(void)
+{
+    IMFAttributes *attributes;
+    HRESULT hr;
+    PROPVARIANT propvar, ret_propvar;
+
+    hr = MFCreateAttributes(&attributes, 2);
+    ok(hr == S_OK, "MFCreateAttributes failed: 0x%08x.\n", hr);
+
+    PropVariantInit(&propvar);
+    propvar.vt = MF_ATTRIBUTE_UINT32;
+    U(propvar).ulVal = 123;
+    hr = IMFAttributes_SetItem(attributes, &DUMMY_GUID1, &propvar);
+    ok(hr == S_OK, "IMFAttributes_SetItem failed: 0x%08x.\n", hr);
+    PropVariantInit(&ret_propvar);
+    ret_propvar.vt = MF_ATTRIBUTE_UINT32;
+    U(ret_propvar).ulVal = 0xdeadbeef;
+    hr = IMFAttributes_GetItem(attributes, &DUMMY_GUID1, &ret_propvar);
+    ok(hr == S_OK, "IMFAttributes_GetItem failed: 0x%08x.\n", hr);
+    ok(!PropVariantCompareEx(&propvar, &ret_propvar, 0, 0), "Returned wrong property: (vt: %x, ulVal: %d).\n",
+       ret_propvar.vt, U(ret_propvar).ulVal);
+    PropVariantClear(&ret_propvar);
+
+    PropVariantInit(&ret_propvar);
+    ret_propvar.vt = MF_ATTRIBUTE_STRING;
+    U(ret_propvar).pwszVal = NULL;
+    hr = IMFAttributes_GetItem(attributes, &DUMMY_GUID1, &ret_propvar);
+    ok(hr == S_OK, "IMFAttributes_GetItem failed: 0x%08x.\n", hr);
+    ok(!PropVariantCompareEx(&propvar, &ret_propvar, 0, 0), "Returned wrong property: (vt: %x, ulVal: %d).\n",
+       ret_propvar.vt, U(ret_propvar).ulVal);
+    PropVariantClear(&ret_propvar);
+
+    PropVariantClear(&propvar);
+
+    PropVariantInit(&propvar);
+    propvar.vt = MF_ATTRIBUTE_UINT64;
+    U(propvar).uhVal.QuadPart = 65536;
+    hr = IMFAttributes_SetItem(attributes, &DUMMY_GUID1, &propvar);
+    ok(hr == S_OK, "IMFAttributes_SetItem failed: 0x%08x.\n", hr);
+    PropVariantInit(&ret_propvar);
+    ret_propvar.vt = MF_ATTRIBUTE_UINT32;
+    U(ret_propvar).ulVal = 0xdeadbeef;
+    hr = IMFAttributes_GetItem(attributes, &DUMMY_GUID1, &ret_propvar);
+    ok(hr == S_OK, "IMFAttributes_GetItem failed: 0x%08x.\n", hr);
+    ok(!PropVariantCompareEx(&propvar, &ret_propvar, 0, 0), "Returned wrong property: (vt: %x, ulVal: %d).\n",
+       ret_propvar.vt, U(ret_propvar).ulVal);
+    PropVariantClear(&ret_propvar);
+    PropVariantClear(&propvar);
+
+    PropVariantInit(&propvar);
+    propvar.vt = VT_I4;
+    U(propvar).lVal = 123;
+    hr = IMFAttributes_SetItem(attributes, &DUMMY_GUID2, &propvar);
+    ok(hr == MF_E_INVALIDTYPE, "IMFAttributes_SetItem should failed: 0x%08x.\n", hr);
+    PropVariantInit(&ret_propvar);
+    ret_propvar.vt = MF_ATTRIBUTE_UINT32;
+    U(ret_propvar).lVal = 0xdeadbeef;
+    hr = IMFAttributes_GetItem(attributes, &DUMMY_GUID2, &ret_propvar);
+    ok(hr == S_OK, "IMFAttributes_GetItem failed: 0x%08x.\n", hr);
+    PropVariantClear(&propvar);
+    ok(!PropVariantCompareEx(&propvar, &ret_propvar, 0, 0), "Returned wrong property: (vt: %x, ulVal: %d).\n",
+       ret_propvar.vt, U(ret_propvar).ulVal);
+    PropVariantClear(&ret_propvar);
+
+    IMFAttributes_Release(attributes);
+}
+
 START_TEST(mfplat)
 {
     CoInitialize(NULL);
@@ -708,6 +776,7 @@ START_TEST(mfplat)
     test_MFCreateMFByteStreamOnStream();
     test_MFCreateMemoryBuffer();
     test_source_resolver();
+    test_IMFAttributes_item();
 
     CoUninitialize();
 }
-- 
2.19.2





More information about the wine-devel mailing list