mfplat: Implement CreatePropertyStore().
Signed-off-by: Zebediah Figura <zfigura@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
926e94f466
commit
748565df50
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
@ stub ValidateWaveFormat
|
||||
@ stub CopyPropVariant
|
||||
@ stub CreatePropVariant
|
||||
@ stub CreatePropertyStore
|
||||
@ stdcall CreatePropertyStore(ptr)
|
||||
@ stub DestroyPropVariant
|
||||
@ stub GetAMSubtypeFromD3DFormat
|
||||
@ stub GetD3DFormatFromMFSubtype
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);")
|
||||
|
|
Loading…
Reference in New Issue