[PATCH 7/7] mfplat: Implement attributes deserialization.

Nikolay Sivov nsivov at codeweavers.com
Thu Mar 21 02:42:58 CDT 2019


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/mfplat/main.c         | 117 +++++++++++++++++++++++++++++++++++--
 dlls/mfplat/mfplat.spec    |   2 +-
 dlls/mfplat/tests/mfplat.c |  72 ++++++++++++++++++++++-
 include/mfapi.h            |   1 +
 4 files changed, 184 insertions(+), 8 deletions(-)

diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c
index 69746f2a68..899aca73d9 100644
--- a/dlls/mfplat/main.c
+++ b/dlls/mfplat/main.c
@@ -1509,6 +1509,7 @@ struct attributes_store_item
     union
     {
         double f;
+        UINT32 i32;
         UINT64 i64;
         struct
         {
@@ -1587,7 +1588,7 @@ static void attributes_serialize_write(struct attr_serialize_context *context, c
     context->ptr += size;
 }
 
-static void attributes_serialize_write_item(struct attr_serialize_context *context, struct attributes_store_item *item,
+static BOOL attributes_serialize_write_item(struct attr_serialize_context *context, struct attributes_store_item *item,
         const void *value)
 {
     switch (item->type)
@@ -1606,8 +1607,10 @@ static void attributes_serialize_write_item(struct attr_serialize_context *conte
             context->size -= item->u.subheader.size;
             break;
         default:
-            ;
+            return FALSE;
     }
+
+    return TRUE;
 }
 
 /***********************************************************************
@@ -1619,6 +1622,7 @@ HRESULT WINAPI MFGetAttributesAsBlob(IMFAttributes *attributes, UINT8 *buffer, U
     struct attr_serialize_context context;
     unsigned int required_size, i;
     PROPVARIANT value;
+    UINT32 count;
     HRESULT hr;
 
     TRACE("%p, %p, %u.\n", attributes, buffer, size);
@@ -1636,11 +1640,12 @@ HRESULT WINAPI MFGetAttributesAsBlob(IMFAttributes *attributes, UINT8 *buffer, U
     IMFAttributes_LockStore(attributes);
 
     header.magic = ATTRIBUTES_STORE_MAGIC;
-    IMFAttributes_GetCount(attributes, &header.count);
+    header.count = 0; /* Will be updated later */
+    IMFAttributes_GetCount(attributes, &count);
 
     attributes_serialize_write(&context, &header, sizeof(header));
 
-    for (i = 0; i < header.count; ++i)
+    for (i = 0; i < count; ++i)
     {
         struct attributes_store_item item;
         const void *data = NULL;
@@ -1678,16 +1683,118 @@ HRESULT WINAPI MFGetAttributesAsBlob(IMFAttributes *attributes, UINT8 *buffer, U
                 WARN("Unknown attribute type %#x.\n", value.vt);
         }
 
-        attributes_serialize_write_item(&context, &item, data);
+        if (attributes_serialize_write_item(&context, &item, data))
+            header.count++;
 
         PropVariantClear(&value);
     }
 
+    memcpy(context.buffer, &header, sizeof(header));
+
     IMFAttributes_UnlockStore(attributes);
 
     return S_OK;
 }
 
+static HRESULT attributes_deserialize_read(struct attr_serialize_context *context, void *value, unsigned int size)
+{
+    if (context->size < (context->ptr - context->buffer) + size)
+        return E_INVALIDARG;
+
+    memcpy(value, context->ptr, size);
+    context->ptr += size;
+
+    return S_OK;
+}
+
+/***********************************************************************
+ *      MFInitAttributesFromBlob (mfplat.@)
+ */
+HRESULT WINAPI MFInitAttributesFromBlob(IMFAttributes *dest, const UINT8 *buffer, UINT size)
+{
+    struct attr_serialize_context context;
+    struct attributes_store_header header;
+    struct attributes_store_item item;
+    IMFAttributes *attributes;
+    unsigned int i;
+    HRESULT hr;
+
+    TRACE("%p, %p, %u.\n", dest, buffer, size);
+
+    context.buffer = (UINT8 *)buffer;
+    context.ptr = (UINT8 *)buffer;
+    context.size = size;
+
+    /* Validate buffer structure. */
+    if (FAILED(hr = attributes_deserialize_read(&context, &header, sizeof(header))))
+        return hr;
+
+    if (header.magic != ATTRIBUTES_STORE_MAGIC)
+        return E_UNEXPECTED;
+
+    if (FAILED(hr = MFCreateAttributes(&attributes, header.count)))
+        return hr;
+
+    for (i = 0; i < header.count; ++i)
+    {
+        if (FAILED(hr = attributes_deserialize_read(&context, &item, sizeof(item))))
+            break;
+
+        hr = E_UNEXPECTED;
+
+        switch (item.type)
+        {
+            case MF_ATTRIBUTE_UINT32:
+                hr = IMFAttributes_SetUINT32(attributes, &item.key, item.u.i32);
+                break;
+            case MF_ATTRIBUTE_UINT64:
+                hr = IMFAttributes_SetUINT64(attributes, &item.key, item.u.i64);
+                break;
+            case MF_ATTRIBUTE_DOUBLE:
+                hr = IMFAttributes_SetDouble(attributes, &item.key, item.u.f);
+                break;
+            case MF_ATTRIBUTE_GUID:
+                if (item.u.subheader.size == sizeof(GUID) &&
+                        item.u.subheader.offset + item.u.subheader.size <= context.size)
+                {
+                    hr = IMFAttributes_SetGUID(attributes, &item.key,
+                            (const GUID *)(context.buffer + item.u.subheader.offset));
+                }
+                break;
+            case MF_ATTRIBUTE_STRING:
+                if (item.u.subheader.size >= sizeof(WCHAR) &&
+                        item.u.subheader.offset + item.u.subheader.size <= context.size)
+                {
+                    hr = IMFAttributes_SetString(attributes, &item.key,
+                            (const WCHAR *)(context.buffer + item.u.subheader.offset));
+                }
+                break;
+            case MF_ATTRIBUTE_BLOB:
+                if (item.u.subheader.size > 0 && item.u.subheader.offset + item.u.subheader.size <= context.size)
+                {
+                    hr = IMFAttributes_SetBlob(attributes, &item.key, context.buffer + item.u.subheader.offset,
+                            item.u.subheader.size);
+                }
+                break;
+            default:
+                ;
+        }
+
+        if (FAILED(hr))
+            break;
+    }
+
+    if (SUCCEEDED(hr))
+    {
+        IMFAttributes_DeleteAllItems(dest);
+        hr = IMFAttributes_CopyAllItems(attributes, dest);
+    }
+
+    IMFAttributes_Release(attributes);
+
+    return hr;
+}
+
 typedef struct _mfbytestream
 {
     mfattributes attributes;
diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec
index 730e64b675..4272a206e6 100644
--- a/dlls/mfplat/mfplat.spec
+++ b/dlls/mfplat/mfplat.spec
@@ -107,7 +107,7 @@
 @ stdcall MFHeapAlloc(long long str long long)
 @ stdcall MFHeapFree(ptr)
 @ stub MFInitAMMediaTypeFromMFMediaType
-@ stub MFInitAttributesFromBlob
+@ stdcall MFInitAttributesFromBlob(ptr ptr long)
 @ stub MFInitMediaTypeFromAMMediaType
 @ stub MFInitMediaTypeFromMFVideoFormat
 @ stub MFInitMediaTypeFromMPEG1VideoInfo
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index 258895f3be..85fc176046 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -2523,14 +2523,24 @@ static void test_MFCompareFullToPartialMediaType(void)
 
 static void test_attributes_serialization(void)
 {
-    IMFAttributes *attributes;
+    static const WCHAR textW[] = {'T','e','x','t',0};
+    static const UINT8 blob[] = {1,2,3};
+    IMFAttributes *attributes, *dest;
+    UINT32 size, count, value32;
+    double value_dbl;
+    UINT64 value64;
     UINT8 *buffer;
-    UINT32 size;
+    IUnknown *obj;
     HRESULT hr;
+    WCHAR *str;
+    GUID guid;
 
     hr = MFCreateAttributes(&attributes, 0);
     ok(hr == S_OK, "Failed to create object, hr %#x.\n", hr);
 
+    hr = MFCreateAttributes(&dest, 0);
+    ok(hr == S_OK, "Failed to create object, hr %#x.\n", hr);
+
     hr = MFGetAttributesAsBlobSize(attributes, &size);
     ok(hr == S_OK, "Failed to get blob size, hr %#x.\n", hr);
     ok(size == 8, "Got size %u.\n", size);
@@ -2543,9 +2553,67 @@ static void test_attributes_serialization(void)
     hr = MFGetAttributesAsBlob(attributes, buffer, size - 1);
     ok(hr == MF_E_BUFFERTOOSMALL, "Unexpected hr %#x.\n", hr);
 
+    hr = MFInitAttributesFromBlob(dest, buffer, size - 1);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFAttributes_SetUINT32(dest, &MF_MT_MAJOR_TYPE, 1);
+    ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
+
+    hr = MFInitAttributesFromBlob(dest, buffer, size);
+    ok(hr == S_OK, "Failed to deserialize, hr %#x.\n", hr);
+
+    /* Previous items are cleared. */
+    hr = IMFAttributes_GetCount(dest, &count);
+    ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
+    ok(count == 0, "Unexpected count %u.\n", count);
+
     heap_free(buffer);
 
+    /* Set some attributes of various types. */
+    IMFAttributes_SetUINT32(attributes, &MF_MT_MAJOR_TYPE, 456);
+    IMFAttributes_SetUINT64(attributes, &MF_MT_SUBTYPE, 123);
+    IMFAttributes_SetDouble(attributes, &IID_IUnknown, 0.5);
+    IMFAttributes_SetUnknown(attributes, &IID_IMFAttributes, (IUnknown *)attributes);
+    IMFAttributes_SetGUID(attributes, &GUID_NULL, &IID_IUnknown);
+    IMFAttributes_SetString(attributes, &DUMMY_CLSID, textW);
+    IMFAttributes_SetBlob(attributes, &DUMMY_GUID1, blob, sizeof(blob));
+
+    hr = MFGetAttributesAsBlobSize(attributes, &size);
+    ok(hr == S_OK, "Failed to get blob size, hr %#x.\n", hr);
+    ok(size > 8, "Got unexpected size %u.\n", size);
+
+    buffer = heap_alloc(size);
+    hr = MFGetAttributesAsBlob(attributes, buffer, size);
+    ok(hr == S_OK, "Failed to serialize, hr %#x.\n", hr);
+    hr = MFInitAttributesFromBlob(dest, buffer, size);
+    ok(hr == S_OK, "Failed to deserialize, hr %#x.\n", hr);
+    heap_free(buffer);
+
+    hr = IMFAttributes_GetUINT32(dest, &MF_MT_MAJOR_TYPE, &value32);
+    ok(hr == S_OK, "Failed to get get uint32 value, hr %#x.\n", hr);
+    ok(value32 == 456, "Unexpected value %u.\n", value32);
+    hr = IMFAttributes_GetUINT64(dest, &MF_MT_SUBTYPE, &value64);
+    ok(hr == S_OK, "Failed to get get uint64 value, hr %#x.\n", hr);
+    ok(value64 == 123, "Unexpected value.\n");
+    hr = IMFAttributes_GetDouble(dest, &IID_IUnknown, &value_dbl);
+    ok(hr == S_OK, "Failed to get get double value, hr %#x.\n", hr);
+    ok(value_dbl == 0.5, "Unexpected value.\n");
+    hr = IMFAttributes_GetUnknown(dest, &IID_IMFAttributes, &IID_IUnknown, (void **)&obj);
+    ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#x.\n", hr);
+    hr = IMFAttributes_GetGUID(dest, &GUID_NULL, &guid);
+    ok(hr == S_OK, "Failed to get guid value, hr %#x.\n", hr);
+    ok(IsEqualGUID(&guid, &IID_IUnknown), "Unexpected guid.\n");
+    hr = IMFAttributes_GetAllocatedString(dest, &DUMMY_CLSID, &str, &size);
+    ok(hr == S_OK, "Failed to get string value, hr %#x.\n", hr);
+    ok(!lstrcmpW(str, textW), "Unexpected string.\n");
+    CoTaskMemFree(str);
+    hr = IMFAttributes_GetAllocatedBlob(dest, &DUMMY_GUID1, &buffer, &size);
+    ok(hr == S_OK, "Failed to get blob value, hr %#x.\n", hr);
+    ok(!memcmp(buffer, blob, sizeof(blob)), "Unexpected blob.\n");
+    CoTaskMemFree(buffer);
+
     IMFAttributes_Release(attributes);
+    IMFAttributes_Release(dest);
 }
 
 START_TEST(mfplat)
diff --git a/include/mfapi.h b/include/mfapi.h
index 5d6d1e79d7..b082f9c2dd 100644
--- a/include/mfapi.h
+++ b/include/mfapi.h
@@ -213,6 +213,7 @@ HRESULT WINAPI MFTEnum(GUID category, UINT32 flags, MFT_REGISTER_TYPE_INFO *inpu
 HRESULT WINAPI MFTEnumEx(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
                          const MFT_REGISTER_TYPE_INFO *output_type, IMFActivate ***activate,
                          UINT32 *pcount);
+HRESULT WINAPI MFInitAttributesFromBlob(IMFAttributes *attributes, const UINT8 *buffer, UINT size);
 HRESULT WINAPI MFInvokeCallback(IMFAsyncResult *result);
 HRESULT WINAPI MFLockPlatform(void);
 HRESULT WINAPI MFPutWorkItem(DWORD queue, IMFAsyncCallback *callback, IUnknown *state);
-- 
2.20.1




More information about the wine-devel mailing list