mfplat: Implement CreatePropertyStore().

Signed-off-by: Zebediah Figura <zfigura@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
stable
Zebediah Figura 2019-07-15 10:28:16 -05:00 committed by Alexandre Julliard
parent 926e94f466
commit 748565df50
4 changed files with 306 additions and 1 deletions

View File

@ -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;
}

View File

@ -10,7 +10,7 @@
@ stub ValidateWaveFormat
@ stub CopyPropVariant
@ stub CreatePropVariant
@ stub CreatePropertyStore
@ stdcall CreatePropertyStore(ptr)
@ stub DestroyPropVariant
@ stub GetAMSubtypeFromD3DFormat
@ stub GetD3DFormatFromMFSubtype

View File

@ -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();
}

View File

@ -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);")