[PATCH v2 2/2] mfplat: Implement CreatePropertyStore().

Zebediah Figura zfigura at codeweavers.com
Mon Jul 15 10:28:16 CDT 2019


Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
 dlls/mfplat/main.c         | 202 +++++++++++++++++++++++++++++++++++++
 dlls/mfplat/mfplat.spec    |   2 +-
 dlls/mfplat/tests/mfplat.c | 102 +++++++++++++++++++
 include/mfidl.idl          |   1 +
 4 files changed, 306 insertions(+), 1 deletion(-)

diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c
index eec54ae3f6a..e946bc79f50 100644
--- a/dlls/mfplat/main.c
+++ b/dlls/mfplat/main.c
@@ -7415,3 +7415,205 @@ failed:
 
     return hr;
 }
+
+struct property_store
+{
+    IPropertyStore IPropertyStore_iface;
+    LONG refcount;
+    CRITICAL_SECTION cs;
+    size_t count, capacity;
+    struct
+    {
+        PROPERTYKEY key;
+        PROPVARIANT value;
+    } *values;
+};
+
+static struct property_store *impl_from_IPropertyStore(IPropertyStore *iface)
+{
+    return CONTAINING_RECORD(iface, struct property_store, IPropertyStore_iface);
+}
+
+static HRESULT WINAPI property_store_QueryInterface(IPropertyStore *iface, REFIID riid, void **obj)
+{
+    TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
+
+    if (IsEqualIID(riid, &IID_IPropertyStore) || IsEqualIID(riid, &IID_IUnknown))
+    {
+        *obj = iface;
+        IPropertyStore_AddRef(iface);
+        return S_OK;
+    }
+
+    *obj = NULL;
+    WARN("Unsupported interface %s.\n", debugstr_guid(riid));
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI property_store_AddRef(IPropertyStore *iface)
+{
+    struct property_store *store = impl_from_IPropertyStore(iface);
+    ULONG refcount = InterlockedIncrement(&store->refcount);
+
+    TRACE("%p, refcount %d.\n", iface, refcount);
+
+    return refcount;
+}
+
+static ULONG WINAPI property_store_Release(IPropertyStore *iface)
+{
+    struct property_store *store = impl_from_IPropertyStore(iface);
+    ULONG refcount = InterlockedDecrement(&store->refcount);
+
+    TRACE("%p, refcount %d.\n", iface, refcount);
+
+    if (!refcount)
+    {
+        DeleteCriticalSection(&store->cs);
+        heap_free(store->values);
+        heap_free(store);
+    }
+
+    return refcount;
+}
+
+static HRESULT WINAPI property_store_GetCount(IPropertyStore *iface, DWORD *count)
+{
+    struct property_store *store = impl_from_IPropertyStore(iface);
+
+    TRACE("%p, %p.\n", iface, count);
+
+    if (!count)
+        return E_INVALIDARG;
+
+    EnterCriticalSection(&store->cs);
+    *count = store->count;
+    LeaveCriticalSection(&store->cs);
+    return S_OK;
+}
+
+static HRESULT WINAPI property_store_GetAt(IPropertyStore *iface, DWORD index, PROPERTYKEY *key)
+{
+    struct property_store *store = impl_from_IPropertyStore(iface);
+
+    TRACE("%p, %u, %p.\n", iface, index, key);
+
+    EnterCriticalSection(&store->cs);
+
+    if (index >= store->count)
+    {
+        LeaveCriticalSection(&store->cs);
+        return E_INVALIDARG;
+    }
+
+    *key = store->values[index].key;
+
+    LeaveCriticalSection(&store->cs);
+    return S_OK;
+}
+
+static HRESULT WINAPI property_store_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value)
+{
+    struct property_store *store = impl_from_IPropertyStore(iface);
+    unsigned int i;
+
+    TRACE("%p, %p, %p.\n", iface, key, value);
+
+    if (!value)
+        return E_INVALIDARG;
+
+    if (!key)
+        return S_FALSE;
+
+    EnterCriticalSection(&store->cs);
+
+    for (i = 0; i < store->count; ++i)
+    {
+        if (!memcmp(key, &store->values[i].key, sizeof(PROPERTYKEY)))
+        {
+            PropVariantCopy(value, &store->values[i].value);
+            LeaveCriticalSection(&store->cs);
+            return S_OK;
+        }
+    }
+
+    LeaveCriticalSection(&store->cs);
+    return S_FALSE;
+}
+
+static HRESULT WINAPI property_store_SetValue(IPropertyStore *iface, REFPROPERTYKEY key, REFPROPVARIANT value)
+{
+    struct property_store *store = impl_from_IPropertyStore(iface);
+    unsigned int i;
+
+    TRACE("%p, %p, %p.\n", iface, key, value);
+
+    EnterCriticalSection(&store->cs);
+
+    for (i = 0; i < store->count; ++i)
+    {
+        if (!memcmp(key, &store->values[i].key, sizeof(PROPERTYKEY)))
+        {
+            PropVariantCopy(&store->values[i].value, value);
+            LeaveCriticalSection(&store->cs);
+            return S_OK;
+        }
+    }
+
+    if (!mf_array_reserve((void **)&store->values, &store->capacity, store->count + 1, sizeof(*store->values)))
+    {
+        LeaveCriticalSection(&store->cs);
+        return E_OUTOFMEMORY;
+    }
+
+    store->values[store->count].key = *key;
+    PropVariantCopy(&store->values[store->count].value, value);
+    ++store->count;
+
+    LeaveCriticalSection(&store->cs);
+    return S_OK;
+}
+
+static HRESULT WINAPI property_store_Commit(IPropertyStore *iface)
+{
+    TRACE("%p.\n", iface);
+
+    return E_NOTIMPL;
+}
+
+static const IPropertyStoreVtbl property_store_vtbl =
+{
+    property_store_QueryInterface,
+    property_store_AddRef,
+    property_store_Release,
+    property_store_GetCount,
+    property_store_GetAt,
+    property_store_GetValue,
+    property_store_SetValue,
+    property_store_Commit,
+};
+
+/***********************************************************************
+ *      CreatePropertyStore (mfplat.@)
+ */
+HRESULT WINAPI CreatePropertyStore(IPropertyStore **store)
+{
+    struct property_store *object;
+
+    TRACE("%p.\n", store);
+
+    if (!store)
+        return E_INVALIDARG;
+
+    if (!(object = heap_alloc_zero(sizeof(*object))))
+        return E_OUTOFMEMORY;
+
+    object->IPropertyStore_iface.lpVtbl = &property_store_vtbl;
+    object->refcount = 1;
+    InitializeCriticalSection(&object->cs);
+
+    TRACE("Created store %p.\n", object);
+    *store = &object->IPropertyStore_iface;
+
+    return S_OK;
+}
diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec
index 1ae0927f513..2f16bbd1973 100644
--- a/dlls/mfplat/mfplat.spec
+++ b/dlls/mfplat/mfplat.spec
@@ -10,7 +10,7 @@
 @ stub ValidateWaveFormat
 @ stub CopyPropVariant
 @ stub CreatePropVariant
-@ stub CreatePropertyStore
+@ stdcall CreatePropertyStore(ptr)
 @ stub DestroyPropVariant
 @ stub GetAMSubtypeFromD3DFormat
 @ stub GetD3DFormatFromMFSubtype
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index cf3099506ec..b4ba6b6c572 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -3603,6 +3603,107 @@ static void test_local_handlers(void)
     ok(hr == S_OK, "Failed to register stream handler, hr %#x.\n", hr);
 }
 
+static void test_create_property_store(void)
+{
+    static const PROPERTYKEY test_pkey = {{0x12345678}, 9};
+    IPropertyStore *store, *store2;
+    PROPVARIANT value = {0};
+    PROPERTYKEY key;
+    ULONG refcount;
+    IUnknown *unk;
+    DWORD count;
+    HRESULT hr;
+
+    hr = CreatePropertyStore(NULL);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = CreatePropertyStore(&store);
+    ok(hr == S_OK, "Failed to create property store, hr %#x.\n", hr);
+
+    hr = CreatePropertyStore(&store2);
+    ok(hr == S_OK, "Failed to create property store, hr %#x.\n", hr);
+    ok(store2 != store, "Expected different store objects.\n");
+    IPropertyStore_Release(store2);
+
+    hr = IPropertyStore_QueryInterface(store, &IID_IPropertyStoreCache, (void **)&unk);
+    ok(hr == E_NOINTERFACE, "Unexpected hr %#x.\n", hr);
+    hr = IPropertyStore_QueryInterface(store, &IID_IPersistSerializedPropStorage, (void **)&unk);
+    ok(hr == E_NOINTERFACE, "Unexpected hr %#x.\n", hr);
+
+    hr = IPropertyStore_GetCount(store, NULL);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    count = 0xdeadbeef;
+    hr = IPropertyStore_GetCount(store, &count);
+    ok(hr == S_OK, "Failed to get count, hr %#x.\n", hr);
+    ok(!count, "Unexpected count %u.\n", count);
+
+    hr = IPropertyStore_Commit(store);
+    ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
+
+    hr = IPropertyStore_GetAt(store, 0, &key);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = IPropertyStore_GetValue(store, NULL, &value);
+    ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
+
+    hr = IPropertyStore_GetValue(store, &test_pkey, NULL);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = IPropertyStore_GetValue(store, &test_pkey, &value);
+    ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
+
+    memset(&value, 0, sizeof(PROPVARIANT));
+    value.vt = VT_I4;
+    value.lVal = 0xdeadbeef;
+    hr = IPropertyStore_SetValue(store, &test_pkey, &value);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+if (0)
+{
+    /* crashes on Windows */
+    hr = IPropertyStore_SetValue(store, NULL, &value);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+}
+
+    hr = IPropertyStore_GetCount(store, &count);
+    ok(hr == S_OK, "Failed to get count, hr %#x.\n", hr);
+    ok(count == 1, "Unexpected count %u.\n", count);
+
+    hr = IPropertyStore_Commit(store);
+    ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
+
+    hr = IPropertyStore_GetAt(store, 0, &key);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(!memcmp(&key, &test_pkey, sizeof(PROPERTYKEY)), "Keys didn't match.\n");
+
+    hr = IPropertyStore_GetAt(store, 1, &key);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    memset(&value, 0xcc, sizeof(PROPVARIANT));
+    hr = IPropertyStore_GetValue(store, &test_pkey, &value);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(value.vt == VT_I4, "Unexpected type %u.\n", value.vt);
+    ok(value.lVal == 0xdeadbeef, "Unexpected value %#x.\n", value.lVal);
+
+    memset(&value, 0, sizeof(PROPVARIANT));
+    hr = IPropertyStore_SetValue(store, &test_pkey, &value);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IPropertyStore_GetCount(store, &count);
+    ok(hr == S_OK, "Failed to get count, hr %#x.\n", hr);
+    ok(count == 1, "Unexpected count %u.\n", count);
+
+    memset(&value, 0xcc, sizeof(PROPVARIANT));
+    hr = IPropertyStore_GetValue(store, &test_pkey, &value);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(value.vt == VT_EMPTY, "Unexpected type %u.\n", value.vt);
+    ok(!value.lVal, "Unexpected value %#x.\n", value.lVal);
+
+    refcount = IPropertyStore_Release(store);
+    ok(!refcount, "Unexpected refcount %u.\n", refcount);
+}
+
 START_TEST(mfplat)
 {
     CoInitialize(NULL);
@@ -3639,6 +3740,7 @@ START_TEST(mfplat)
     test_MFCreateWaveFormatExFromMFMediaType();
     test_async_create_file();
     test_local_handlers();
+    test_create_property_store();
 
     CoUninitialize();
 }
diff --git a/include/mfidl.idl b/include/mfidl.idl
index 1ed63bea126..5f8913384cc 100644
--- a/include/mfidl.idl
+++ b/include/mfidl.idl
@@ -566,6 +566,7 @@ interface IMFSampleGrabberSinkCallback2 : IMFSampleGrabberSinkCallback
         [in] IMFAttributes *attributes);
 }
 
+cpp_quote("HRESULT WINAPI CreatePropertyStore(IPropertyStore **store);")
 cpp_quote("HRESULT WINAPI MFCreateMediaSession(IMFAttributes *config, IMFMediaSession **session);")
 cpp_quote("HRESULT WINAPI MFCreateMFByteStreamOnStream(IStream *stream, IMFByteStream **bytestream);" )
 cpp_quote("HRESULT WINAPI MFCreateMFByteStreamOnStreamEx(IUnknown *stream, IMFByteStream **bytestream);")
-- 
2.20.1




More information about the wine-devel mailing list