Signed-off-by: Jactry Zeng jzeng@codeweavers.com --- dlls/mfplat/buffer.c | 7 +- dlls/mfplat/main.c | 161 +++++++++++++++++++++++++++++++--- dlls/mfplat/mediatype.c | 17 +++- dlls/mfplat/mfplat_private.h | 13 ++- dlls/mfplat/tests/Makefile.in | 2 +- dlls/mfplat/tests/mfplat.c | 89 +++++++++++++++++++ 6 files changed, 272 insertions(+), 17 deletions(-)
diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c index 833ec041a9..afdb525dea 100644 --- a/dlls/mfplat/buffer.c +++ b/dlls/mfplat/buffer.c @@ -273,6 +273,7 @@ static ULONG WINAPI sample_Release(IMFSample *iface) IMFMediaBuffer_Release(sample->buffers[i]); DeleteCriticalSection(&sample->cs); heap_free(sample->buffers); + clear_attributes_object(&sample->attributes); heap_free(sample); }
@@ -706,7 +707,11 @@ HRESULT WINAPI MFCreateSample(IMFSample **sample) if (!object) return E_OUTOFMEMORY;
- init_attribute_object(&object->attributes, 0); + if (FAILED(init_attributes_object(&object->attributes, 0))) + { + heap_free(object); + return E_OUTOFMEMORY; + } object->IMFSample_iface.lpVtbl = &samplevtbl; InitializeCriticalSection(&object->cs);
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index 6bec41884e..22803dc1b4 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -577,19 +577,48 @@ static ULONG WINAPI mfattributes_Release(IMFAttributes *iface)
if (!ref) { + clear_attributes_object(This); HeapFree(GetProcessHeap(), 0, This); }
return ref; }
+static struct mfattribute *mfattributes_find_item(mfattributes *object, REFGUID key, size_t *item_index) +{ + size_t index; + + for (index = 0; index < object->count; index++) + { + if (IsEqualGUID(key, &object->attributes[index].key)) + { + if (item_index) + *item_index = index; + return &object->attributes[index]; + } + } + return NULL; +} + static HRESULT WINAPI mfattributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value) { mfattributes *This = impl_from_IMFAttributes(iface); + HRESULT hr; + struct mfattribute *attribute = NULL;
- FIXME("%p, %s, %p\n", This, debugstr_guid(key), value); + TRACE("(%p, %s, %p)\n", This, debugstr_guid(key), value);
- return E_NOTIMPL; + EnterCriticalSection(&This->lock); + + attribute = mfattributes_find_item(This, key, NULL); + if (!attribute) + hr = MF_E_ATTRIBUTENOTFOUND; + else + hr = PropVariantCopy(value, &attribute->value); + + LeaveCriticalSection(&This->lock); + + return hr; }
static HRESULT WINAPI mfattributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type) @@ -722,13 +751,68 @@ 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 mfattributes_set_item(mfattributes *object, REFGUID key, REFPROPVARIANT value) +{ + struct mfattribute *attribute = NULL; + + EnterCriticalSection(&object->lock); + + attribute = mfattributes_find_item(object, key, NULL); + if (!attribute) + { + if (!mf_array_reserve((void **)&object->attributes, &object->capacity, object->count + 1, + sizeof(*object->attributes))) + { + LeaveCriticalSection(&object->lock); + return E_OUTOFMEMORY; + } + object->attributes[object->count].key = *key; + attribute = &object->attributes[object->count]; + object->count++; + } + else + PropVariantClear(&attribute->value); + + PropVariantCopy(&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); + mfattributes_set_item(This, key, &empty_value); + return MF_E_INVALIDTYPE; + } + else + return mfattributes_set_item(This, key, value); }
static HRESULT WINAPI mfattributes_DeleteItem(IMFAttributes *iface, REFGUID key) @@ -897,10 +981,42 @@ static const IMFAttributesVtbl mfattributes_vtbl = mfattributes_CopyAllItems };
-void init_attribute_object(mfattributes *object, UINT32 size) +HRESULT init_attributes_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"); + + object->attributes = NULL; + object->count = 0; + object->capacity = 0; + if (!mf_array_reserve((void **)&object->attributes, &object->capacity, size, + sizeof(*object->attributes))) + { + object->lock.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&object->lock); + return E_OUTOFMEMORY; + } + + return S_OK; +} + +void clear_attributes_object(mfattributes *object) +{ + size_t i; + + EnterCriticalSection(&object->lock); + + for (i = 0; i < object->count; i++) + PropVariantClear(&object->attributes[i].value); + + heap_free(object->attributes); + + LeaveCriticalSection(&object->lock); + + object->lock.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&object->lock); }
/*********************************************************************** @@ -916,7 +1032,11 @@ HRESULT WINAPI MFCreateAttributes(IMFAttributes **attributes, UINT32 size) if(!object) return E_OUTOFMEMORY;
- init_attribute_object(object, size); + if (FAILED(init_attributes_object(object, size))) + { + heap_free(object); + return E_OUTOFMEMORY; + } *attributes = &object->IMFAttributes_iface;
return S_OK; @@ -978,6 +1098,7 @@ static ULONG WINAPI mfbytestream_Release(IMFByteStream *iface)
if (!ref) { + clear_attributes_object(&This->attributes); HeapFree(GetProcessHeap(), 0, This); }
@@ -1218,7 +1339,11 @@ HRESULT WINAPI MFCreateMFByteStreamOnStream(IStream *stream, IMFByteStream **byt if(!object) return E_OUTOFMEMORY;
- init_attribute_object(&object->attributes, 0); + if (FAILED(init_attributes_object(&object->attributes, 0))) + { + heap_free(object); + return E_OUTOFMEMORY; + } object->IMFByteStream_iface.lpVtbl = &mfbytestream_vtbl; object->attributes.IMFAttributes_iface.lpVtbl = &mfbytestream_attributes_vtbl;
@@ -1289,7 +1414,11 @@ HRESULT WINAPI MFCreateFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE open if(!object) return E_OUTOFMEMORY;
- init_attribute_object(&object->attributes, 0); + if (FAILED(init_attributes_object(&object->attributes, 0))) + { + heap_free(object); + return E_OUTOFMEMORY; + } object->IMFByteStream_iface.lpVtbl = &mfbytestream_vtbl; object->attributes.IMFAttributes_iface.lpVtbl = &mfbytestream_attributes_vtbl;
@@ -1445,6 +1574,7 @@ static ULONG WINAPI mfpresentationdescriptor_Release(IMFPresentationDescriptor *
if (!ref) { + clear_attributes_object(&This->attributes); HeapFree(GetProcessHeap(), 0, This); }
@@ -1843,7 +1973,11 @@ static HRESULT WINAPI mfsource_CreatePresentationDescriptor(IMFMediaSource *ifac if (!object) return E_OUTOFMEMORY;
- init_attribute_object(&object->attributes, 0); + if (FAILED(init_attributes_object(&object->attributes, 0))) + { + heap_free(object); + return E_OUTOFMEMORY; + } object->IMFPresentationDescriptor_iface.lpVtbl = &mfpresentationdescriptor_vtbl;
*descriptor = &object->IMFPresentationDescriptor_iface; @@ -2146,6 +2280,7 @@ static ULONG WINAPI mfmediaevent_Release(IMFMediaEvent *iface)
if (!ref) { + clear_attributes_object(&This->attributes); HeapFree(GetProcessHeap(), 0, This); }
@@ -2436,7 +2571,11 @@ HRESULT WINAPI MFCreateMediaEvent(MediaEventType type, REFGUID extended_type, HR if(!object) return E_OUTOFMEMORY;
- init_attribute_object(&object->attributes, 0); + if (FAILED(init_attributes_object(&object->attributes, 0))) + { + heap_free(object); + return E_OUTOFMEMORY; + } object->IMFMediaEvent_iface.lpVtbl = &mfmediaevent_vtbl;
object->type = type; diff --git a/dlls/mfplat/mediatype.c b/dlls/mfplat/mediatype.c index 7abbf31796..88e34e23e2 100644 --- a/dlls/mfplat/mediatype.c +++ b/dlls/mfplat/mediatype.c @@ -116,6 +116,7 @@ static ULONG WINAPI mediatype_Release(IMFMediaType *iface)
if (!refcount) { + clear_attributes_object(&media_type->attributes); heap_free(media_type); }
@@ -400,7 +401,11 @@ HRESULT WINAPI MFCreateMediaType(IMFMediaType **media_type) if (!object) return E_OUTOFMEMORY;
- init_attribute_object(&object->attributes, 0); + if (FAILED(init_attributes_object(&object->attributes, 0))) + { + heap_free(object); + return E_OUTOFMEMORY; + } object->IMFMediaType_iface.lpVtbl = &mediatypevtbl;
*media_type = &object->IMFMediaType_iface; @@ -456,6 +461,7 @@ static ULONG WINAPI stream_descriptor_Release(IMFStreamDescriptor *iface) if (stream_desc->current_type) IMFMediaType_Release(stream_desc->current_type); DeleteCriticalSection(&stream_desc->cs); + clear_attributes_object(&stream_desc->attributes); heap_free(stream_desc); }
@@ -855,7 +861,11 @@ HRESULT WINAPI MFCreateStreamDescriptor(DWORD identifier, DWORD count, if (!object) return E_OUTOFMEMORY;
- init_attribute_object(&object->attributes, 0); + if (FAILED(init_attributes_object(&object->attributes, 0))) + { + heap_free(object); + return E_OUTOFMEMORY; + } object->IMFStreamDescriptor_iface.lpVtbl = &streamdescriptorvtbl; object->IMFMediaTypeHandler_iface.lpVtbl = &mediatypehandlervtbl; object->identifier = identifier; @@ -1264,7 +1274,8 @@ static const IMFPresentationDescriptorVtbl presentationdescriptorvtbl =
static HRESULT presentation_descriptor_init(struct presentation_desc *object, DWORD count) { - init_attribute_object(&object->attributes, 0); + if (FAILED(init_attributes_object(&object->attributes, 0))) + return E_OUTOFMEMORY; object->IMFPresentationDescriptor_iface.lpVtbl = &presentationdescriptorvtbl; object->descriptors = heap_alloc_zero(count * sizeof(*object->descriptors)); if (!object->descriptors) diff --git a/dlls/mfplat/mfplat_private.h b/dlls/mfplat/mfplat_private.h index 72f8f684f6..4ad71e225d 100644 --- a/dlls/mfplat/mfplat_private.h +++ b/dlls/mfplat/mfplat_private.h @@ -22,13 +22,24 @@
#include "wine/heap.h"
+struct mfattribute +{ + GUID key; + PROPVARIANT value; +}; + typedef struct attributes { IMFAttributes IMFAttributes_iface; LONG ref; + CRITICAL_SECTION lock; + struct mfattribute *attributes; + size_t capacity; + size_t count; } mfattributes;
-extern void init_attribute_object(mfattributes *object, UINT32 size) DECLSPEC_HIDDEN; +extern HRESULT init_attributes_object(mfattributes *object, UINT32 size) DECLSPEC_HIDDEN; +extern void clear_attributes_object(mfattributes *object) DECLSPEC_HIDDEN;
extern void init_system_queues(void) DECLSPEC_HIDDEN; extern void shutdown_system_queues(void) DECLSPEC_HIDDEN; 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 2f4db9b219..95f13725bf 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"
@@ -58,6 +59,7 @@ DEFINE_GUID(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, 0xa634a91c, 0x822b, 0x41b9, DEFINE_GUID(DUMMY_CLSID, 0x12345678,0x1234,0x1234,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19); DEFINE_GUID(DUMMY_GUID1, 0x12345678,0x1234,0x1234,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21); DEFINE_GUID(DUMMY_GUID2, 0x12345678,0x1234,0x1234,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22); +DEFINE_GUID(DUMMY_GUID3, 0x12345678,0x1234,0x1234,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23);
static const WCHAR mp4file[] = {'t','e','s','t','.','m','p','4',0};
@@ -419,6 +421,8 @@ static void test_MFCreateAttributes(void) IMFAttributes *attributes; HRESULT hr; UINT32 count; + PROPVARIANT propvar, ret_propvar; + GUID key;
hr = MFCreateAttributes( &attributes, 3 ); ok(hr == S_OK, "got 0x%08x\n", hr); @@ -436,6 +440,91 @@ static void test_MFCreateAttributes(void) todo_wine ok(count == 1, "got %d\n", count);
IMFAttributes_Release(attributes); + + hr = MFCreateAttributes(&attributes, 0); + 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), "got wrong property.\n"); + 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), "got wrong property.\n"); + 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), "got wrong property.\n"); + 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), "got wrong property.\n"); + PropVariantClear(&ret_propvar); + + PropVariantInit(&propvar); + propvar.vt = MF_ATTRIBUTE_UINT32; + U(propvar).ulVal = 123; + hr = IMFAttributes_SetItem(attributes, &DUMMY_GUID3, &propvar); + ok(hr == S_OK, "IMFAttributes_SetItem failed: 0x%08x.\n", hr); + + hr = IMFAttributes_DeleteItem(attributes, &DUMMY_GUID2); + todo_wine ok(hr == S_OK, "IMFAttributes_DeleteItem failed: 0x%08x.\n", hr); + key = GUID_NULL; + if (is_win8_plus) + hr = IMFAttributes_GetItemByIndex(attributes, 0, &key, &ret_propvar); + else + hr = IMFAttributes_GetItemByIndex(attributes, 1, &key, &ret_propvar); + todo_wine ok(hr == S_OK, "IMFAttributes_GetItemByIndex failed: 0x%08x.\n", hr); + todo_wine ok(!PropVariantCompareEx(&propvar, &ret_propvar, 0, 0), "got wrong property.\n"); + todo_wine ok(IsEqualIID(&key, &DUMMY_GUID3), "got wrong key: %s.\n", wine_dbgstr_guid(&key)); + PropVariantClear(&ret_propvar); + PropVariantClear(&propvar); + propvar.vt = MF_ATTRIBUTE_UINT64; + U(propvar).uhVal.QuadPart = 65536; + key = GUID_NULL; + if (is_win8_plus) + hr = IMFAttributes_GetItemByIndex(attributes, 1, &key, &ret_propvar); + else + hr = IMFAttributes_GetItemByIndex(attributes, 0, &key, &ret_propvar); + todo_wine ok(hr == S_OK, "IMFAttributes_GetItemByIndex failed: 0x%08x.\n", hr); + todo_wine ok(!PropVariantCompareEx(&propvar, &ret_propvar, 0, 0), "got wrong property.\n"); + todo_wine ok(IsEqualIID(&key, &DUMMY_GUID1), "got wrong key: %s.\n", wine_dbgstr_guid(&key)); + + IMFAttributes_Release(attributes); }
static void test_MFCreateMFByteStreamOnStream(void)