[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