mfplat/tests: Allocate test callbacks.

It's not safe to use stack variables for async callbacks.
Diagnosed by Bernhard Übelacker.

Signed-off-by: Bernhard Übelacker <bernhardu@mailbox.org>
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2021-12-14 09:49:18 +03:00 committed by Alexandre Julliard
parent 6f8debb11f
commit 4b69a997e9
1 changed files with 104 additions and 74 deletions

View File

@ -369,7 +369,12 @@ static ULONG WINAPI testcallback_AddRef(IMFAsyncCallback *iface)
static ULONG WINAPI testcallback_Release(IMFAsyncCallback *iface) static ULONG WINAPI testcallback_Release(IMFAsyncCallback *iface)
{ {
struct test_callback *callback = impl_from_IMFAsyncCallback(iface); struct test_callback *callback = impl_from_IMFAsyncCallback(iface);
return InterlockedDecrement(&callback->refcount); ULONG refcount = InterlockedDecrement(&callback->refcount);
if (!refcount)
free(callback);
return refcount;
} }
static HRESULT WINAPI testcallback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue) static HRESULT WINAPI testcallback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue)
@ -378,7 +383,6 @@ static HRESULT WINAPI testcallback_GetParameters(IMFAsyncCallback *iface, DWORD
return E_NOTIMPL; return E_NOTIMPL;
} }
static BOOL check_clsid(CLSID *clsids, UINT32 count) static BOOL check_clsid(CLSID *clsids, UINT32 count)
{ {
int i; int i;
@ -597,23 +601,35 @@ static const IMFAsyncCallbackVtbl events_callback_vtbl =
source_events_callback_Invoke, source_events_callback_Invoke,
}; };
static const IMFAsyncCallbackVtbl testcallbackvtbl;
static struct test_callback * create_test_callback(const IMFAsyncCallbackVtbl *vtbl)
{
struct test_callback *callback = calloc(1, sizeof(*callback));
callback->IMFAsyncCallback_iface.lpVtbl = vtbl ? vtbl : &testcallbackvtbl;
callback->refcount = 1;
return callback;
}
static BOOL get_event(IMFMediaEventGenerator *generator, MediaEventType expected_event_type, PROPVARIANT *value) static BOOL get_event(IMFMediaEventGenerator *generator, MediaEventType expected_event_type, PROPVARIANT *value)
{ {
struct test_callback callback = {{ 0 }}; struct test_callback *callback;
MediaEventType event_type; MediaEventType event_type;
BOOL ret = FALSE; BOOL ret = FALSE;
HRESULT hr; HRESULT hr;
callback.IMFAsyncCallback_iface.lpVtbl = &events_callback_vtbl; callback = create_test_callback(&events_callback_vtbl);
callback.event = CreateEventA(NULL, FALSE, FALSE, NULL); callback->event = CreateEventA(NULL, FALSE, FALSE, NULL);
for (;;) for (;;)
{ {
hr = IMFMediaEventGenerator_BeginGetEvent(generator, &callback.IMFAsyncCallback_iface, hr = IMFMediaEventGenerator_BeginGetEvent(generator, &callback->IMFAsyncCallback_iface,
(IUnknown *)generator); (IUnknown *)generator);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr); ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
if (WaitForSingleObject(callback.event, 1000) == WAIT_TIMEOUT) if (WaitForSingleObject(callback->event, 1000) == WAIT_TIMEOUT)
{ {
ok(0, "timeout\n"); ok(0, "timeout\n");
break; break;
@ -621,14 +637,14 @@ static BOOL get_event(IMFMediaEventGenerator *generator, MediaEventType expected
Sleep(10); Sleep(10);
hr = IMFMediaEvent_GetType(callback.media_event, &event_type); hr = IMFMediaEvent_GetType(callback->media_event, &event_type);
ok(hr == S_OK, "Failed to event type, hr %#x.\n", hr); ok(hr == S_OK, "Failed to event type, hr %#x.\n", hr);
if ((ret = (event_type == expected_event_type))) if ((ret = (event_type == expected_event_type)))
{ {
if (value) if (value)
{ {
hr = IMFMediaEvent_GetValue(callback.media_event, value); hr = IMFMediaEvent_GetValue(callback->media_event, value);
ok(hr == S_OK, "Failed to get value of event, hr %#x.\n", hr); ok(hr == S_OK, "Failed to get value of event, hr %#x.\n", hr);
} }
@ -636,17 +652,17 @@ static BOOL get_event(IMFMediaEventGenerator *generator, MediaEventType expected
} }
} }
CloseHandle(callback.event); CloseHandle(callback->event);
if (callback.media_event) if (callback->media_event)
IMFMediaEvent_Release(callback.media_event); IMFMediaEvent_Release(callback->media_event);
IMFAsyncCallback_Release(&callback->IMFAsyncCallback_iface);
return ret; return ret;
} }
static void test_source_resolver(void) static void test_source_resolver(void)
{ {
struct test_callback callback = { { &test_create_from_url_callback_vtbl } }; struct test_callback *callback, *callback2;
struct test_callback callback2 = { { &test_create_from_file_handler_callback_vtbl } };
IMFSourceResolver *resolver, *resolver2; IMFSourceResolver *resolver, *resolver2;
IMFPresentationDescriptor *descriptor; IMFPresentationDescriptor *descriptor;
IMFSchemeHandler *scheme_handler; IMFSchemeHandler *scheme_handler;
@ -677,6 +693,9 @@ static void test_source_resolver(void)
return; return;
} }
callback = create_test_callback(&test_create_from_url_callback_vtbl);
callback2 = create_test_callback(&test_create_from_file_handler_callback_vtbl);
hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
ok(hr == S_OK, "got 0x%08x\n", hr); ok(hr == S_OK, "got 0x%08x\n", hr);
@ -713,7 +732,7 @@ static void test_source_resolver(void)
IMFByteStream_Release(stream); IMFByteStream_Release(stream);
/* Create from URL. */ /* Create from URL. */
callback.event = CreateEventA(NULL, FALSE, FALSE, NULL); callback->event = CreateEventA(NULL, FALSE, FALSE, NULL);
hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"nonexisting.mp4", MF_RESOLUTION_BYTESTREAM, NULL, &obj_type, hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"nonexisting.mp4", MF_RESOLUTION_BYTESTREAM, NULL, &obj_type,
(IUnknown **)&stream); (IUnknown **)&stream);
@ -725,13 +744,13 @@ static void test_source_resolver(void)
IMFByteStream_Release(stream); IMFByteStream_Release(stream);
hr = IMFSourceResolver_BeginCreateObjectFromURL(resolver, filename, MF_RESOLUTION_BYTESTREAM, NULL, hr = IMFSourceResolver_BeginCreateObjectFromURL(resolver, filename, MF_RESOLUTION_BYTESTREAM, NULL,
&cancel_cookie, &callback.IMFAsyncCallback_iface, (IUnknown *)resolver); &cancel_cookie, &callback->IMFAsyncCallback_iface, (IUnknown *)resolver);
ok(hr == S_OK, "Create request failed, hr %#x.\n", hr); ok(hr == S_OK, "Create request failed, hr %#x.\n", hr);
ok(cancel_cookie != NULL, "Unexpected cancel object.\n"); ok(cancel_cookie != NULL, "Unexpected cancel object.\n");
IUnknown_Release(cancel_cookie); IUnknown_Release(cancel_cookie);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
WaitForSingleObject(callback.event, INFINITE); WaitForSingleObject(callback->event, INFINITE);
/* With explicit scheme. */ /* With explicit scheme. */
lstrcpyW(pathW, fileschemeW); lstrcpyW(pathW, fileschemeW);
@ -962,28 +981,31 @@ todo_wine
(void **)&scheme_handler); (void **)&scheme_handler);
ok(hr == S_OK, "Failed to create handler object, hr %#x.\n", hr); ok(hr == S_OK, "Failed to create handler object, hr %#x.\n", hr);
callback2.event = callback.event; callback2->event = callback->event;
cancel_cookie = NULL; cancel_cookie = NULL;
hr = IMFSchemeHandler_BeginCreateObject(scheme_handler, pathW, MF_RESOLUTION_MEDIASOURCE, NULL, &cancel_cookie, hr = IMFSchemeHandler_BeginCreateObject(scheme_handler, pathW, MF_RESOLUTION_MEDIASOURCE, NULL, &cancel_cookie,
&callback2.IMFAsyncCallback_iface, (IUnknown *)scheme_handler); &callback2->IMFAsyncCallback_iface, (IUnknown *)scheme_handler);
ok(hr == S_OK, "Create request failed, hr %#x.\n", hr); ok(hr == S_OK, "Create request failed, hr %#x.\n", hr);
ok(!!cancel_cookie, "Unexpected cancel object.\n"); ok(!!cancel_cookie, "Unexpected cancel object.\n");
IUnknown_Release(cancel_cookie); IUnknown_Release(cancel_cookie);
WaitForSingleObject(callback2.event, INFINITE); WaitForSingleObject(callback2->event, INFINITE);
IMFSchemeHandler_Release(scheme_handler); IMFSchemeHandler_Release(scheme_handler);
if (do_uninit) if (do_uninit)
CoUninitialize(); CoUninitialize();
CloseHandle(callback.event); CloseHandle(callback->event);
IMFSourceResolver_Release(resolver); IMFSourceResolver_Release(resolver);
hr = MFShutdown(); hr = MFShutdown();
ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr); ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
IMFAsyncCallback_Release(&callback->IMFAsyncCallback_iface);
IMFAsyncCallback_Release(&callback2->IMFAsyncCallback_iface);
DeleteFileW(filename); DeleteFileW(filename);
} }
@ -2548,17 +2570,10 @@ static const IMFAsyncCallbackVtbl testcallbackvtbl =
testcallback_Invoke, testcallback_Invoke,
}; };
static void init_test_callback(struct test_callback *callback)
{
callback->IMFAsyncCallback_iface.lpVtbl = &testcallbackvtbl;
callback->event = NULL;
callback->refcount = 1;
}
static void test_MFCreateAsyncResult(void) static void test_MFCreateAsyncResult(void)
{ {
IMFAsyncResult *result, *result2; IMFAsyncResult *result, *result2;
struct test_callback callback; struct test_callback *callback;
IUnknown *state, *object; IUnknown *state, *object;
MFASYNCRESULT *data; MFASYNCRESULT *data;
ULONG refcount; ULONG refcount;
@ -2567,7 +2582,7 @@ static void test_MFCreateAsyncResult(void)
HRESULT hr; HRESULT hr;
BOOL ret; BOOL ret;
init_test_callback(&callback); callback = create_test_callback(NULL);
hr = MFCreateAsyncResult(NULL, NULL, NULL, NULL); hr = MFCreateAsyncResult(NULL, NULL, NULL, NULL);
ok(FAILED(hr), "Unexpected hr %#x.\n", hr); ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
@ -2612,11 +2627,11 @@ static void test_MFCreateAsyncResult(void)
ok(state == NULL, "Unexpected state.\n"); ok(state == NULL, "Unexpected state.\n");
/* Object. */ /* Object. */
hr = MFCreateAsyncResult((IUnknown *)result, &callback.IMFAsyncCallback_iface, NULL, &result2); hr = MFCreateAsyncResult((IUnknown *)result, &callback->IMFAsyncCallback_iface, NULL, &result2);
ok(hr == S_OK, "Failed to create object, hr %#x.\n", hr); ok(hr == S_OK, "Failed to create object, hr %#x.\n", hr);
data = (MFASYNCRESULT *)result2; data = (MFASYNCRESULT *)result2;
ok(data->pCallback == &callback.IMFAsyncCallback_iface, "Unexpected callback value.\n"); ok(data->pCallback == &callback->IMFAsyncCallback_iface, "Unexpected callback value.\n");
ok(data->hrStatusResult == S_OK, "Unexpected status %#x.\n", data->hrStatusResult); ok(data->hrStatusResult == S_OK, "Unexpected status %#x.\n", data->hrStatusResult);
ok(data->dwBytesTransferred == 0, "Unexpected byte length %u.\n", data->dwBytesTransferred); ok(data->dwBytesTransferred == 0, "Unexpected byte length %u.\n", data->dwBytesTransferred);
ok(data->hEvent == NULL, "Unexpected event.\n"); ok(data->hEvent == NULL, "Unexpected event.\n");
@ -2630,11 +2645,11 @@ static void test_MFCreateAsyncResult(void)
IMFAsyncResult_Release(result2); IMFAsyncResult_Release(result2);
/* State object. */ /* State object. */
hr = MFCreateAsyncResult(NULL, &callback.IMFAsyncCallback_iface, (IUnknown *)result, &result2); hr = MFCreateAsyncResult(NULL, &callback->IMFAsyncCallback_iface, (IUnknown *)result, &result2);
ok(hr == S_OK, "Failed to create object, hr %#x.\n", hr); ok(hr == S_OK, "Failed to create object, hr %#x.\n", hr);
data = (MFASYNCRESULT *)result2; data = (MFASYNCRESULT *)result2;
ok(data->pCallback == &callback.IMFAsyncCallback_iface, "Unexpected callback value.\n"); ok(data->pCallback == &callback->IMFAsyncCallback_iface, "Unexpected callback value.\n");
ok(data->hrStatusResult == S_OK, "Unexpected status %#x.\n", data->hrStatusResult); ok(data->hrStatusResult == S_OK, "Unexpected status %#x.\n", data->hrStatusResult);
ok(data->dwBytesTransferred == 0, "Unexpected byte length %u.\n", data->dwBytesTransferred); ok(data->dwBytesTransferred == 0, "Unexpected byte length %u.\n", data->dwBytesTransferred);
ok(data->hEvent == NULL, "Unexpected event.\n"); ok(data->hEvent == NULL, "Unexpected event.\n");
@ -2668,7 +2683,7 @@ static void test_MFCreateAsyncResult(void)
ret = GetHandleInformation(event, &flags); ret = GetHandleInformation(event, &flags);
ok(!ret, "Expected handle to be closed.\n"); ok(!ret, "Expected handle to be closed.\n");
hr = MFCreateAsyncResult(NULL, &callback.IMFAsyncCallback_iface, NULL, &result); hr = MFCreateAsyncResult(NULL, &callback->IMFAsyncCallback_iface, NULL, &result);
ok(hr == S_OK, "Failed to create object, hr %#x.\n", hr); ok(hr == S_OK, "Failed to create object, hr %#x.\n", hr);
data = (MFASYNCRESULT *)result; data = (MFASYNCRESULT *)result;
@ -2681,6 +2696,8 @@ static void test_MFCreateAsyncResult(void)
ok(!refcount, "Unexpected refcount %u.\n", refcount); ok(!refcount, "Unexpected refcount %u.\n", refcount);
ret = GetHandleInformation(event, &flags); ret = GetHandleInformation(event, &flags);
ok(!ret, "Expected handle to be closed.\n"); ok(!ret, "Expected handle to be closed.\n");
IMFAsyncCallback_Release(&callback->IMFAsyncCallback_iface);
} }
static void test_startup(void) static void test_startup(void)
@ -2934,17 +2951,17 @@ static void test_MFHeapAlloc(void)
static void test_scheduled_items(void) static void test_scheduled_items(void)
{ {
struct test_callback callback; struct test_callback *callback;
IMFAsyncResult *result; IMFAsyncResult *result;
MFWORKITEM_KEY key, key2; MFWORKITEM_KEY key, key2;
HRESULT hr; HRESULT hr;
init_test_callback(&callback); callback = create_test_callback(NULL);
hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
ok(hr == S_OK, "Failed to start up, hr %#x.\n", hr); ok(hr == S_OK, "Failed to start up, hr %#x.\n", hr);
hr = MFScheduleWorkItem(&callback.IMFAsyncCallback_iface, NULL, -5000, &key); hr = MFScheduleWorkItem(&callback->IMFAsyncCallback_iface, NULL, -5000, &key);
ok(hr == S_OK, "Failed to schedule item, hr %#x.\n", hr); ok(hr == S_OK, "Failed to schedule item, hr %#x.\n", hr);
hr = MFCancelWorkItem(key); hr = MFCancelWorkItem(key);
@ -2959,7 +2976,7 @@ static void test_scheduled_items(void)
return; return;
} }
hr = MFCreateAsyncResult(NULL, &callback.IMFAsyncCallback_iface, NULL, &result); hr = MFCreateAsyncResult(NULL, &callback->IMFAsyncCallback_iface, NULL, &result);
ok(hr == S_OK, "Failed to create result, hr %#x.\n", hr); ok(hr == S_OK, "Failed to create result, hr %#x.\n", hr);
hr = pMFPutWaitingWorkItem(NULL, 0, result, &key); hr = pMFPutWaitingWorkItem(NULL, 0, result, &key);
@ -2976,7 +2993,7 @@ static void test_scheduled_items(void)
IMFAsyncResult_Release(result); IMFAsyncResult_Release(result);
hr = MFScheduleWorkItem(&callback.IMFAsyncCallback_iface, NULL, -5000, &key); hr = MFScheduleWorkItem(&callback->IMFAsyncCallback_iface, NULL, -5000, &key);
ok(hr == S_OK, "Failed to schedule item, hr %#x.\n", hr); ok(hr == S_OK, "Failed to schedule item, hr %#x.\n", hr);
hr = MFCancelWorkItem(key); hr = MFCancelWorkItem(key);
@ -2984,6 +3001,8 @@ static void test_scheduled_items(void)
hr = MFShutdown(); hr = MFShutdown();
ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr); ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
IMFAsyncCallback_Release(&callback->IMFAsyncCallback_iface);
} }
static void test_serial_queue(void) static void test_serial_queue(void)
@ -3089,15 +3108,15 @@ static void test_periodic_callback(void)
static void test_event_queue(void) static void test_event_queue(void)
{ {
struct test_callback callback, callback2; struct test_callback *callback, *callback2;
IMFMediaEvent *event, *event2; IMFMediaEvent *event, *event2;
IMFMediaEventQueue *queue; IMFMediaEventQueue *queue;
IMFAsyncResult *result; IMFAsyncResult *result;
HRESULT hr; HRESULT hr;
DWORD ret; DWORD ret;
init_test_callback(&callback); callback = create_test_callback(NULL);
init_test_callback(&callback2); callback2 = create_test_callback(NULL);
hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
ok(hr == S_OK, "Failed to start up, hr %#x.\n", hr); ok(hr == S_OK, "Failed to start up, hr %#x.\n", hr);
@ -3133,38 +3152,38 @@ static void test_event_queue(void)
hr = IMFMediaEventQueue_BeginGetEvent(queue, NULL, NULL); hr = IMFMediaEventQueue_BeginGetEvent(queue, NULL, NULL);
ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
hr = IMFMediaEventQueue_BeginGetEvent(queue, &callback.IMFAsyncCallback_iface, (IUnknown *)queue); hr = IMFMediaEventQueue_BeginGetEvent(queue, &callback->IMFAsyncCallback_iface, (IUnknown *)queue);
ok(hr == S_OK, "Failed to Begin*, hr %#x.\n", hr); ok(hr == S_OK, "Failed to Begin*, hr %#x.\n", hr);
/* Same callback, same state. */ /* Same callback, same state. */
hr = IMFMediaEventQueue_BeginGetEvent(queue, &callback.IMFAsyncCallback_iface, (IUnknown *)queue); hr = IMFMediaEventQueue_BeginGetEvent(queue, &callback->IMFAsyncCallback_iface, (IUnknown *)queue);
ok(hr == MF_S_MULTIPLE_BEGIN, "Unexpected hr %#x.\n", hr); ok(hr == MF_S_MULTIPLE_BEGIN, "Unexpected hr %#x.\n", hr);
/* Same callback, different state. */ /* Same callback, different state. */
hr = IMFMediaEventQueue_BeginGetEvent(queue, &callback.IMFAsyncCallback_iface, (IUnknown *)&callback.IMFAsyncCallback_iface); hr = IMFMediaEventQueue_BeginGetEvent(queue, &callback->IMFAsyncCallback_iface, (IUnknown *)&callback->IMFAsyncCallback_iface);
ok(hr == MF_E_MULTIPLE_BEGIN, "Unexpected hr %#x.\n", hr); ok(hr == MF_E_MULTIPLE_BEGIN, "Unexpected hr %#x.\n", hr);
/* Different callback, same state. */ /* Different callback, same state. */
hr = IMFMediaEventQueue_BeginGetEvent(queue, &callback2.IMFAsyncCallback_iface, (IUnknown *)queue); hr = IMFMediaEventQueue_BeginGetEvent(queue, &callback2->IMFAsyncCallback_iface, (IUnknown *)queue);
ok(hr == MF_E_MULTIPLE_SUBSCRIBERS, "Unexpected hr %#x.\n", hr); ok(hr == MF_E_MULTIPLE_SUBSCRIBERS, "Unexpected hr %#x.\n", hr);
/* Different callback, different state. */ /* Different callback, different state. */
hr = IMFMediaEventQueue_BeginGetEvent(queue, &callback2.IMFAsyncCallback_iface, (IUnknown *)&callback.IMFAsyncCallback_iface); hr = IMFMediaEventQueue_BeginGetEvent(queue, &callback2->IMFAsyncCallback_iface, (IUnknown *)&callback->IMFAsyncCallback_iface);
ok(hr == MF_E_MULTIPLE_SUBSCRIBERS, "Unexpected hr %#x.\n", hr); ok(hr == MF_E_MULTIPLE_SUBSCRIBERS, "Unexpected hr %#x.\n", hr);
callback.event = CreateEventA(NULL, FALSE, FALSE, NULL); callback->event = CreateEventA(NULL, FALSE, FALSE, NULL);
hr = IMFMediaEventQueue_QueueEvent(queue, event); hr = IMFMediaEventQueue_QueueEvent(queue, event);
ok(hr == S_OK, "Failed to queue event, hr %#x.\n", hr); ok(hr == S_OK, "Failed to queue event, hr %#x.\n", hr);
ret = WaitForSingleObject(callback.event, 500); ret = WaitForSingleObject(callback->event, 500);
ok(ret == WAIT_OBJECT_0, "Unexpected return value %#x.\n", ret); ok(ret == WAIT_OBJECT_0, "Unexpected return value %#x.\n", ret);
CloseHandle(callback.event); CloseHandle(callback->event);
IMFMediaEvent_Release(event); IMFMediaEvent_Release(event);
hr = MFCreateAsyncResult(NULL, &callback.IMFAsyncCallback_iface, NULL, &result); hr = MFCreateAsyncResult(NULL, &callback->IMFAsyncCallback_iface, NULL, &result);
ok(hr == S_OK, "Failed to create result, hr %#x.\n", hr); ok(hr == S_OK, "Failed to create result, hr %#x.\n", hr);
hr = IMFMediaEventQueue_EndGetEvent(queue, result, &event); hr = IMFMediaEventQueue_EndGetEvent(queue, result, &event);
@ -3189,7 +3208,7 @@ static void test_event_queue(void)
hr = IMFMediaEventQueue_QueueEventParamVar(queue, MEError, &GUID_NULL, E_FAIL, NULL); hr = IMFMediaEventQueue_QueueEventParamVar(queue, MEError, &GUID_NULL, E_FAIL, NULL);
ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr); ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
hr = IMFMediaEventQueue_BeginGetEvent(queue, &callback.IMFAsyncCallback_iface, NULL); hr = IMFMediaEventQueue_BeginGetEvent(queue, &callback->IMFAsyncCallback_iface, NULL);
ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr); ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
hr = IMFMediaEventQueue_BeginGetEvent(queue, NULL, NULL); hr = IMFMediaEventQueue_BeginGetEvent(queue, NULL, NULL);
@ -3204,21 +3223,23 @@ static void test_event_queue(void)
ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr); ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
IMFMediaEventQueue_Release(queue); IMFMediaEventQueue_Release(queue);
IMFAsyncCallback_Release(&callback->IMFAsyncCallback_iface);
/* Release while subscribed. */ /* Release while subscribed. */
init_test_callback(&callback); callback = create_test_callback(NULL);
hr = MFCreateEventQueue(&queue); hr = MFCreateEventQueue(&queue);
ok(hr == S_OK, "Failed to create event queue, hr %#x.\n", hr); ok(hr == S_OK, "Failed to create event queue, hr %#x.\n", hr);
hr = IMFMediaEventQueue_BeginGetEvent(queue, &callback.IMFAsyncCallback_iface, NULL); hr = IMFMediaEventQueue_BeginGetEvent(queue, &callback->IMFAsyncCallback_iface, NULL);
ok(hr == S_OK, "Failed to Begin*, hr %#x.\n", hr); ok(hr == S_OK, "Failed to Begin*, hr %#x.\n", hr);
EXPECT_REF(&callback.IMFAsyncCallback_iface, 2); EXPECT_REF(&callback->IMFAsyncCallback_iface, 2);
IMFMediaEventQueue_Release(queue); IMFMediaEventQueue_Release(queue);
ret = get_refcount(&callback.IMFAsyncCallback_iface); ret = get_refcount(&callback->IMFAsyncCallback_iface);
ok(ret == 1 || broken(ret == 2) /* Vista */, ok(ret == 1 || broken(ret == 2) /* Vista */,
"Unexpected refcount %d, expected 1.\n", ret); "Unexpected refcount %d, expected 1.\n", ret);
IMFAsyncCallback_Release(&callback->IMFAsyncCallback_iface);
hr = MFShutdown(); hr = MFShutdown();
ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr); ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
@ -3736,7 +3757,7 @@ static void test_system_time_source(void)
static void test_MFInvokeCallback(void) static void test_MFInvokeCallback(void)
{ {
struct test_callback callback; struct test_callback *callback;
IMFAsyncResult *result; IMFAsyncResult *result;
MFASYNCRESULT *data; MFASYNCRESULT *data;
ULONG refcount; ULONG refcount;
@ -3746,9 +3767,9 @@ static void test_MFInvokeCallback(void)
hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
ok(hr == S_OK, "Failed to start up, hr %#x.\n", hr); ok(hr == S_OK, "Failed to start up, hr %#x.\n", hr);
init_test_callback(&callback); callback = create_test_callback(NULL);
hr = MFCreateAsyncResult(NULL, &callback.IMFAsyncCallback_iface, NULL, &result); hr = MFCreateAsyncResult(NULL, &callback->IMFAsyncCallback_iface, NULL, &result);
ok(hr == S_OK, "Failed to create object, hr %#x.\n", hr); ok(hr == S_OK, "Failed to create object, hr %#x.\n", hr);
data = (MFASYNCRESULT *)result; data = (MFASYNCRESULT *)result;
@ -3764,6 +3785,8 @@ static void test_MFInvokeCallback(void)
refcount = IMFAsyncResult_Release(result); refcount = IMFAsyncResult_Release(result);
ok(!refcount, "Unexpected refcount %u.\n", refcount); ok(!refcount, "Unexpected refcount %u.\n", refcount);
IMFAsyncCallback_Release(&callback->IMFAsyncCallback_iface);
hr = MFShutdown(); hr = MFShutdown();
ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr); ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
} }
@ -4440,34 +4463,38 @@ static const IMFAsyncCallbackVtbl test_create_file_callback_vtbl =
static void test_async_create_file(void) static void test_async_create_file(void)
{ {
struct test_callback callback = { { &test_create_file_callback_vtbl } };
WCHAR pathW[MAX_PATH], fileW[MAX_PATH]; WCHAR pathW[MAX_PATH], fileW[MAX_PATH];
struct test_callback *callback;
IUnknown *cancel_cookie; IUnknown *cancel_cookie;
HRESULT hr; HRESULT hr;
BOOL ret; BOOL ret;
callback = create_test_callback(&test_create_file_callback_vtbl);
hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
ok(hr == S_OK, "Fail to start up, hr %#x.\n", hr); ok(hr == S_OK, "Fail to start up, hr %#x.\n", hr);
callback.event = CreateEventA(NULL, FALSE, FALSE, NULL); callback->event = CreateEventA(NULL, FALSE, FALSE, NULL);
GetTempPathW(ARRAY_SIZE(pathW), pathW); GetTempPathW(ARRAY_SIZE(pathW), pathW);
GetTempFileNameW(pathW, NULL, 0, fileW); GetTempFileNameW(pathW, NULL, 0, fileW);
hr = MFBeginCreateFile(MF_ACCESSMODE_READWRITE, MF_OPENMODE_DELETE_IF_EXIST, MF_FILEFLAGS_NONE, fileW, hr = MFBeginCreateFile(MF_ACCESSMODE_READWRITE, MF_OPENMODE_DELETE_IF_EXIST, MF_FILEFLAGS_NONE, fileW,
&callback.IMFAsyncCallback_iface, (IUnknown *)&callback.IMFAsyncCallback_iface, &cancel_cookie); &callback->IMFAsyncCallback_iface, (IUnknown *)&callback->IMFAsyncCallback_iface, &cancel_cookie);
ok(hr == S_OK, "Async create request failed, hr %#x.\n", hr); ok(hr == S_OK, "Async create request failed, hr %#x.\n", hr);
ok(cancel_cookie != NULL, "Unexpected cancellation object.\n"); ok(cancel_cookie != NULL, "Unexpected cancellation object.\n");
WaitForSingleObject(callback.event, INFINITE); WaitForSingleObject(callback->event, INFINITE);
IUnknown_Release(cancel_cookie); IUnknown_Release(cancel_cookie);
CloseHandle(callback.event); CloseHandle(callback->event);
hr = MFShutdown(); hr = MFShutdown();
ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr); ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
IMFAsyncCallback_Release(&callback->IMFAsyncCallback_iface);
ret = DeleteFileW(fileW); ret = DeleteFileW(fileW);
ok(ret, "Failed to delete test file.\n"); ok(ret, "Failed to delete test file.\n");
} }
@ -5336,21 +5363,22 @@ static const IMFAsyncCallbackVtbl test_queue_com_state_callback_vtbl =
static void test_queue_com_state(const char *name) static void test_queue_com_state(const char *name)
{ {
struct test_callback callback = { { &test_queue_com_state_callback_vtbl } }; struct test_callback *callback;
DWORD queue, queue_type; DWORD queue, queue_type;
HRESULT hr; HRESULT hr;
callback.event = CreateEventA(NULL, FALSE, FALSE, NULL); callback = create_test_callback(&test_queue_com_state_callback_vtbl);
callback->event = CreateEventA(NULL, FALSE, FALSE, NULL);
hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
ok(hr == S_OK, "Failed to start up, hr %#x.\n", hr); ok(hr == S_OK, "Failed to start up, hr %#x.\n", hr);
if (name[0] == 's') if (name[0] == 's')
{ {
callback.param = name[1] - '0'; callback->param = name[1] - '0';
hr = MFPutWorkItem(callback.param, &callback.IMFAsyncCallback_iface, NULL); hr = MFPutWorkItem(callback->param, &callback->IMFAsyncCallback_iface, NULL);
ok(SUCCEEDED(hr), "Failed to queue work item, hr %#x.\n", hr); ok(SUCCEEDED(hr), "Failed to queue work item, hr %#x.\n", hr);
WaitForSingleObject(callback.event, INFINITE); WaitForSingleObject(callback->event, INFINITE);
} }
else if (name[0] == 'u') else if (name[0] == 'u')
{ {
@ -5362,20 +5390,22 @@ static void test_queue_com_state(const char *name)
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
callback.param = queue; callback->param = queue;
hr = MFPutWorkItem(queue, &callback.IMFAsyncCallback_iface, NULL); hr = MFPutWorkItem(queue, &callback->IMFAsyncCallback_iface, NULL);
ok(SUCCEEDED(hr), "Failed to queue work item, hr %#x.\n", hr); ok(SUCCEEDED(hr), "Failed to queue work item, hr %#x.\n", hr);
WaitForSingleObject(callback.event, INFINITE); WaitForSingleObject(callback->event, INFINITE);
hr = MFUnlockWorkQueue(queue); hr = MFUnlockWorkQueue(queue);
ok(hr == S_OK, "Failed to unlock the queue, hr %#x.\n", hr); ok(hr == S_OK, "Failed to unlock the queue, hr %#x.\n", hr);
} }
} }
CloseHandle(callback.event); CloseHandle(callback->event);
hr = MFShutdown(); hr = MFShutdown();
ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr); ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
IMFAsyncCallback_Release(&callback->IMFAsyncCallback_iface);
} }
static void test_MFGetStrideForBitmapInfoHeader(void) static void test_MFGetStrideForBitmapInfoHeader(void)