From 6dc7503b2370b68fbdacc51f6db90c06cc108986 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Thu, 21 Mar 2019 10:42:58 +0300 Subject: [PATCH] mfplat: Implement attributes deserialization. Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- 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 69746f2a686..899aca73d9c 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 730e64b675f..4272a206e67 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 258895f3bea..85fc1760467 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 5d6d1e79d7d..b082f9c2dd0 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);