Signed-off-by: Bernhard Kölbl besentv@gmail.com
-- v2: windows.media.speech/tests: Add some recognition tests. windows.media.speech/tests: Make use of a helper function for IAsyncInfo checking. windows.media.speech/tests: Add await helper for IAsyncOperation. windows.media.speech/tests: Retype AsyncOperationCompletedHandler to IInspectable. windows.media.speech: Rename impl_from_IAsyncInfo to async_inspectable_impl_from_IAsyncInfo. windows.media.speech: Rename async_operation to async_inspectable. windows.media.speech/tests: Add a test for IAsyncOperation_get_Completed. windows.media.speech/tests: Make the IAsyncInfo_Close block test more consistent. windows.media.speech: Add a missing trace to async_operation_create.
From: Bernhard Kölbl besentv@gmail.com
Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/windows.media.speech/async.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/dlls/windows.media.speech/async.c b/dlls/windows.media.speech/async.c index 64a095a0134..e7547225c1c 100644 --- a/dlls/windows.media.speech/async.c +++ b/dlls/windows.media.speech/async.c @@ -367,6 +367,8 @@ HRESULT async_operation_create( const GUID *iid, IInspectable *invoker, async_op { struct async_operation *impl;
+ TRACE("iid %s, invoker %p, callback %p, out %p.\n", debugstr_guid(iid), invoker, callback, out); + *out = NULL; if (!(impl = calloc(1, sizeof(*impl)))) return E_OUTOFMEMORY; impl->IAsyncOperation_IInspectable_iface.lpVtbl = &async_operation_vtbl;
From: Bernhard Kölbl besentv@gmail.com
By waiting for an additional event, instead of the return of a thread.
Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/windows.media.speech/tests/speech.c | 41 +++++++++++++----------- 1 file changed, 22 insertions(+), 19 deletions(-)
diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c index 9ef49b160cd..6803a43ea9c 100644 --- a/dlls/windows.media.speech/tests/speech.c +++ b/dlls/windows.media.speech/tests/speech.c @@ -240,6 +240,7 @@ struct compilation_handler LONG ref;
HANDLE event_block; + HANDLE event_unblock; HANDLE event_finished; DWORD thread_id; }; @@ -294,6 +295,8 @@ HRESULT WINAPI compilation_handler_Invoke( IAsyncHandler_Compilation *iface, if (impl->event_finished) SetEvent(impl->event_finished); /* Block handler until event is set. */ if (impl->event_block) WaitForSingleObject(impl->event_block, INFINITE); + /* Signal unblock of the handler. */ + if (impl->event_unblock) SetEvent(impl->event_unblock);
return S_OK; } @@ -815,15 +818,15 @@ static void test_VoiceInformation(void) RoUninitialize(); }
-struct async_operation_block_param +struct op_put_completed_thread_param { IAsyncOperationCompletedHandler_SpeechRecognitionCompilationResult *handler; IAsyncOperation_SpeechRecognitionCompilationResult *operation; };
-static DWORD WINAPI async_operation_block_thread(void *arg) +static DWORD WINAPI put_completed_thread(void *arg) { - struct async_operation_block_param *param = arg; + struct op_put_completed_thread_param *param = arg; HRESULT hr;
hr = IAsyncOperation_SpeechRecognitionCompilationResult_put_Completed(param->operation, param->handler); @@ -849,15 +852,15 @@ static void test_SpeechRecognizer(void) IInspectable *inspectable = NULL; ILanguage *language = NULL; IAsyncInfo *info = NULL; + struct op_put_completed_thread_param put_completed_param; struct completed_event_handler completed_handler; struct recognition_result_handler result_handler; - struct async_operation_block_param block_param; struct compilation_handler compilation_handler; SpeechRecognitionResultStatus result_status; EventRegistrationToken token = { .value = 0 }; AsyncStatus async_status; HSTRING hstr, hstr_lang; - HANDLE blocked_thread; + HANDLE put_thread; HRESULT hr, error_code; UINT32 id; LONG ref; @@ -1123,23 +1126,22 @@ static void test_SpeechRecognizer(void) compilation_handler_create_static(&compilation_handler); compilation_handler.event_block = CreateEventW(NULL, FALSE, FALSE, NULL); compilation_handler.event_finished = CreateEventW(NULL, FALSE, FALSE, NULL); + compilation_handler.event_unblock = CreateEventW(NULL, FALSE, FALSE, NULL); compilation_handler.thread_id = GetCurrentThreadId();
- ok(compilation_handler.event_finished != NULL, "Finished event wasn't created.\n"); + ok(!!compilation_handler.event_finished, "event_block wasn't created.\n"); + ok(!!compilation_handler.event_finished, "event_finished wasn't created.\n"); + ok(!!compilation_handler.event_finished, "event_unblock wasn't created.\n");
hr = ISpeechRecognizer_CompileConstraintsAsync(recognizer, &operation); ok(hr == S_OK, "ISpeechRecognizer_CompileConstraintsAsync failed, hr %#lx.\n", hr);
- block_param.handler = &compilation_handler.IAsyncHandler_Compilation_iface; - block_param.operation = operation; - blocked_thread = CreateThread(NULL, 0, async_operation_block_thread, &block_param, 0, NULL); + put_completed_param.handler = &compilation_handler.IAsyncHandler_Compilation_iface; + put_completed_param.operation = operation; + put_thread = CreateThread(NULL, 0, put_completed_thread, &put_completed_param, 0, NULL);
ok(!WaitForSingleObject(compilation_handler.event_finished, 5000), "Wait for event_finished failed.\n"); - - ok(WaitForSingleObject(blocked_thread, 100) == WAIT_TIMEOUT, "Wait for block_thread didn't time out.\n"); - - todo_wine ok(compilation_handler.ref == 3, "Got unexpected ref %lu.\n", compilation_handler.ref); - todo_wine check_refcount(operation, 3); + ok(WaitForSingleObject(compilation_handler.event_unblock, 100) == WAIT_TIMEOUT, "Wait for event_unblock didn't time out.\n");
hr = IAsyncOperation_SpeechRecognitionCompilationResult_QueryInterface(operation, &IID_IAsyncInfo, (void **)&info); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); @@ -1148,18 +1150,19 @@ static void test_SpeechRecognizer(void) ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
SetEvent(compilation_handler.event_block); - ok(!WaitForSingleObject(blocked_thread, 1000), "Wait for block_thread failed.\n"); + ok(!WaitForSingleObject(compilation_handler.event_unblock, 1000), "Wait for event_unblock failed.\n");
- CloseHandle(blocked_thread); + CloseHandle(put_thread); CloseHandle(compilation_handler.event_block); CloseHandle(compilation_handler.event_finished); - + CloseHandle(compilation_handler.event_unblock); + ref = IAsyncInfo_Release(info); - ok(ref == 1, "Got unexpected ref %lu.\n", ref); + ok(ref == 1 || broken(ref >= 1), "Got unexpected ref %lu.\n", ref);
skip_operation: ref = IAsyncOperation_SpeechRecognitionCompilationResult_Release(operation); - ok(!ref, "Got unexpected ref %lu.\n", ref); + ok(!ref || broken(ref >= 0), "Got unexpected ref %lu.\n", ref);
ref = ISpeechRecognizer_Release(recognizer); ok(ref == 1, "Got unexpected ref %lu.\n", ref);
From: Bernhard Kölbl besentv@gmail.com
This one actually retrieves a handler.
Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/windows.media.speech/tests/speech.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c index 6803a43ea9c..6be02948809 100644 --- a/dlls/windows.media.speech/tests/speech.c +++ b/dlls/windows.media.speech/tests/speech.c @@ -863,7 +863,7 @@ static void test_SpeechRecognizer(void) HANDLE put_thread; HRESULT hr, error_code; UINT32 id; - LONG ref; + LONG ref, old_ref;
hr = RoInitialize(RO_INIT_MULTITHREADED); ok(hr == S_OK, "RoInitialize failed, hr %#lx.\n", hr); @@ -1143,6 +1143,16 @@ static void test_SpeechRecognizer(void) ok(!WaitForSingleObject(compilation_handler.event_finished, 5000), "Wait for event_finished failed.\n"); ok(WaitForSingleObject(compilation_handler.event_unblock, 100) == WAIT_TIMEOUT, "Wait for event_unblock didn't time out.\n");
+ handler = (void*)0xdeadbeef; + old_ref = compilation_handler.ref; + hr = IAsyncOperation_SpeechRecognitionCompilationResult_get_Completed(operation, &handler); + ok(hr == S_OK, "IAsyncOperation_SpeechRecognitionCompilationResult_get_Completed failed, hr %#lx.\n", hr); + todo_wine ok(handler == &compilation_handler.IAsyncHandler_Compilation_iface, "Handler was %p.\n", handler); + + ref = compilation_handler.ref - old_ref; + todo_wine ok(ref == 1, "The ref was increased by %lu.\n", ref); + if (handler) IAsyncOperationCompletedHandler_SpeechRecognitionCompilationResult_Release(handler); + hr = IAsyncOperation_SpeechRecognitionCompilationResult_QueryInterface(operation, &IID_IAsyncInfo, (void **)&info); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=114570
Your paranoid android.
=== debian11 (32 bit Chinese:China report) ===
windows.media.speech: speech.c:1067: Test failed: Got unexpected ref 2.
From: Bernhard Kölbl besentv@gmail.com
Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/windows.media.speech/async.c | 125 +++++++++++++------------ dlls/windows.media.speech/private.h | 5 +- dlls/windows.media.speech/recognizer.c | 2 +- 3 files changed, 68 insertions(+), 64 deletions(-)
diff --git a/dlls/windows.media.speech/async.c b/dlls/windows.media.speech/async.c index e7547225c1c..79510d61dc7 100644 --- a/dlls/windows.media.speech/async.c +++ b/dlls/windows.media.speech/async.c @@ -32,7 +32,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(speech); * */
-struct async_operation +struct async_inspectable { IAsyncOperation_IInspectable IAsyncOperation_IInspectable_iface; IAsyncInfo IAsyncInfo_iface; @@ -42,7 +42,7 @@ struct async_operation IAsyncOperationCompletedHandler_IInspectable *handler; IInspectable *result;
- async_operation_callback callback; + async_operation_inspectable_callback callback; TP_WORK *async_run_work; IInspectable *invoker;
@@ -51,14 +51,14 @@ struct async_operation HRESULT hr; };
-static inline struct async_operation *impl_from_IAsyncOperation_IInspectable(IAsyncOperation_IInspectable *iface) +static inline struct async_inspectable *impl_from_IAsyncOperation_IInspectable(IAsyncOperation_IInspectable *iface) { - return CONTAINING_RECORD(iface, struct async_operation, IAsyncOperation_IInspectable_iface); + return CONTAINING_RECORD(iface, struct async_inspectable, IAsyncOperation_IInspectable_iface); }
-static HRESULT WINAPI async_operation_QueryInterface( IAsyncOperation_IInspectable *iface, REFIID iid, void **out ) +static HRESULT WINAPI async_inspectable_QueryInterface( IAsyncOperation_IInspectable *iface, REFIID iid, void **out ) { - struct async_operation *impl = impl_from_IAsyncOperation_IInspectable(iface); + struct async_inspectable *impl = impl_from_IAsyncOperation_IInspectable(iface);
TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
@@ -82,17 +82,17 @@ static HRESULT WINAPI async_operation_QueryInterface( IAsyncOperation_IInspectab return E_NOINTERFACE; }
-static ULONG WINAPI async_operation_AddRef( IAsyncOperation_IInspectable *iface ) +static ULONG WINAPI async_inspectable_AddRef( IAsyncOperation_IInspectable *iface ) { - struct async_operation *impl = impl_from_IAsyncOperation_IInspectable(iface); + struct async_inspectable *impl = impl_from_IAsyncOperation_IInspectable(iface); ULONG ref = InterlockedIncrement(&impl->ref); TRACE("iface %p, ref %lu.\n", iface, ref); return ref; }
-static ULONG WINAPI async_operation_Release( IAsyncOperation_IInspectable *iface ) +static ULONG WINAPI async_inspectable_Release( IAsyncOperation_IInspectable *iface ) { - struct async_operation *impl = impl_from_IAsyncOperation_IInspectable(iface); + struct async_inspectable *impl = impl_from_IAsyncOperation_IInspectable(iface);
ULONG ref = InterlockedDecrement(&impl->ref); TRACE("iface %p, ref %lu.\n", iface, ref); @@ -115,28 +115,28 @@ static ULONG WINAPI async_operation_Release( IAsyncOperation_IInspectable *iface return ref; }
-static HRESULT WINAPI async_operation_GetIids( IAsyncOperation_IInspectable *iface, ULONG *iid_count, IID **iids ) +static HRESULT WINAPI async_inspectable_GetIids( IAsyncOperation_IInspectable *iface, ULONG *iid_count, IID **iids ) { FIXME("iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids); return E_NOTIMPL; }
-static HRESULT WINAPI async_operation_GetRuntimeClassName( IAsyncOperation_IInspectable *iface, HSTRING *class_name ) +static HRESULT WINAPI async_inspectable_GetRuntimeClassName( IAsyncOperation_IInspectable *iface, HSTRING *class_name ) { FIXME("iface %p, class_name %p stub!\n", iface, class_name); return E_NOTIMPL; }
-static HRESULT WINAPI async_operation_GetTrustLevel( IAsyncOperation_IInspectable *iface, TrustLevel *trust_level ) +static HRESULT WINAPI async_inspectable_GetTrustLevel( IAsyncOperation_IInspectable *iface, TrustLevel *trust_level ) { FIXME("iface %p, trust_level %p stub!\n", iface, trust_level); return E_NOTIMPL; }
-static HRESULT WINAPI async_operation_put_Completed( IAsyncOperation_IInspectable *iface, - IAsyncOperationCompletedHandler_IInspectable *handler ) +static HRESULT WINAPI async_inspectable_put_Completed( IAsyncOperation_IInspectable *iface, + IAsyncOperationCompletedHandler_IInspectable *handler ) { - struct async_operation *impl = impl_from_IAsyncOperation_IInspectable(iface); + struct async_inspectable *impl = impl_from_IAsyncOperation_IInspectable(iface); HRESULT hr = S_OK;
TRACE("iface %p, handler %p.\n", iface, handler); @@ -147,7 +147,7 @@ static HRESULT WINAPI async_operation_put_Completed( IAsyncOperation_IInspectabl else if (impl->handler != HANDLER_NOT_SET) hr = E_ILLEGAL_DELEGATE_ASSIGNMENT; /* - impl->handler can only be set once with async_operation_put_Completed, + impl->handler can only be set once with async_inspectable_put_Completed, so by default we set a non HANDLER_NOT_SET value, in this case handler. */ else if ((impl->handler = handler)) @@ -172,10 +172,10 @@ static HRESULT WINAPI async_operation_put_Completed( IAsyncOperation_IInspectabl return hr; }
-static HRESULT WINAPI async_operation_get_Completed( IAsyncOperation_IInspectable *iface, - IAsyncOperationCompletedHandler_IInspectable **handler ) +static HRESULT WINAPI async_inspectable_get_Completed( IAsyncOperation_IInspectable *iface, + IAsyncOperationCompletedHandler_IInspectable **handler ) { - struct async_operation *impl = impl_from_IAsyncOperation_IInspectable(iface); + struct async_inspectable *impl = impl_from_IAsyncOperation_IInspectable(iface); HRESULT hr = S_OK;
FIXME("iface %p, handler %p semi stub!\n", iface, handler); @@ -189,10 +189,10 @@ static HRESULT WINAPI async_operation_get_Completed( IAsyncOperation_IInspectabl return hr; }
-static HRESULT WINAPI async_operation_GetResults( IAsyncOperation_IInspectable *iface, IInspectable **results ) +static HRESULT WINAPI async_inspectable_GetResults( IAsyncOperation_IInspectable *iface, IInspectable **results ) { /* NOTE: Despite the name, this function only returns one result! */ - struct async_operation *impl = impl_from_IAsyncOperation_IInspectable(iface); + struct async_inspectable *impl = impl_from_IAsyncOperation_IInspectable(iface); HRESULT hr;
TRACE("iface %p, results %p.\n", iface, results); @@ -213,20 +213,20 @@ static HRESULT WINAPI async_operation_GetResults( IAsyncOperation_IInspectable * return hr; }
-static const struct IAsyncOperation_IInspectableVtbl async_operation_vtbl = +static const struct IAsyncOperation_IInspectableVtbl async_inspectable_vtbl = { /* IUnknown methods */ - async_operation_QueryInterface, - async_operation_AddRef, - async_operation_Release, + async_inspectable_QueryInterface, + async_inspectable_AddRef, + async_inspectable_Release, /* IInspectable methods */ - async_operation_GetIids, - async_operation_GetRuntimeClassName, - async_operation_GetTrustLevel, + async_inspectable_GetIids, + async_inspectable_GetRuntimeClassName, + async_inspectable_GetTrustLevel, /* IAsyncOperation<IInspectable*> */ - async_operation_put_Completed, - async_operation_get_Completed, - async_operation_GetResults + async_inspectable_put_Completed, + async_inspectable_get_Completed, + async_inspectable_GetResults };
/* @@ -235,17 +235,17 @@ static const struct IAsyncOperation_IInspectableVtbl async_operation_vtbl = * */
-DEFINE_IINSPECTABLE(async_operation_info, IAsyncInfo, struct async_operation, IAsyncOperation_IInspectable_iface) +DEFINE_IINSPECTABLE(async_inspectable_info, IAsyncInfo, struct async_inspectable, IAsyncOperation_IInspectable_iface)
-static HRESULT WINAPI async_operation_info_get_Id( IAsyncInfo *iface, UINT32 *id ) +static HRESULT WINAPI async_inspectable_info_get_Id( IAsyncInfo *iface, UINT32 *id ) { FIXME("iface %p, id %p stub!\n", iface, id); return E_NOTIMPL; }
-static HRESULT WINAPI async_operation_info_get_Status( IAsyncInfo *iface, AsyncStatus *status ) +static HRESULT WINAPI async_inspectable_info_get_Status( IAsyncInfo *iface, AsyncStatus *status ) { - struct async_operation *impl = impl_from_IAsyncInfo(iface); + struct async_inspectable *impl = impl_from_IAsyncInfo(iface); HRESULT hr = S_OK;
TRACE("iface %p, status %p.\n", iface, status); @@ -259,9 +259,9 @@ static HRESULT WINAPI async_operation_info_get_Status( IAsyncInfo *iface, AsyncS return hr; }
-static HRESULT WINAPI async_operation_info_get_ErrorCode( IAsyncInfo *iface, HRESULT *error_code ) +static HRESULT WINAPI async_inspectable_info_get_ErrorCode( IAsyncInfo *iface, HRESULT *error_code ) { - struct async_operation *impl = impl_from_IAsyncInfo(iface); + struct async_inspectable *impl = impl_from_IAsyncInfo(iface); HRESULT hr = S_OK;
TRACE("iface %p, error_code %p.\n", iface, error_code); @@ -276,9 +276,9 @@ static HRESULT WINAPI async_operation_info_get_ErrorCode( IAsyncInfo *iface, HRE return hr; }
-static HRESULT WINAPI async_operation_info_Cancel( IAsyncInfo *iface ) +static HRESULT WINAPI async_inspectable_info_Cancel( IAsyncInfo *iface ) { - struct async_operation *impl = impl_from_IAsyncInfo(iface); + struct async_inspectable *impl = impl_from_IAsyncInfo(iface); HRESULT hr = S_OK;
TRACE("iface %p.\n", iface); @@ -293,9 +293,9 @@ static HRESULT WINAPI async_operation_info_Cancel( IAsyncInfo *iface ) return hr; }
-static HRESULT WINAPI async_operation_info_Close( IAsyncInfo *iface ) +static HRESULT WINAPI async_inspectable_info_Close( IAsyncInfo *iface ) { - struct async_operation *impl = impl_from_IAsyncInfo(iface); + struct async_inspectable *impl = impl_from_IAsyncInfo(iface); HRESULT hr = S_OK;
TRACE("iface %p.\n", iface); @@ -314,29 +314,29 @@ static HRESULT WINAPI async_operation_info_Close( IAsyncInfo *iface ) return hr; }
-static const struct IAsyncInfoVtbl async_operation_info_vtbl = +static const struct IAsyncInfoVtbl async_inspectable_info_vtbl = { /* IUnknown methods */ - async_operation_info_QueryInterface, - async_operation_info_AddRef, - async_operation_info_Release, + async_inspectable_info_QueryInterface, + async_inspectable_info_AddRef, + async_inspectable_info_Release, /* IInspectable methods */ - async_operation_info_GetIids, - async_operation_info_GetRuntimeClassName, - async_operation_info_GetTrustLevel, + async_inspectable_info_GetIids, + async_inspectable_info_GetRuntimeClassName, + async_inspectable_info_GetTrustLevel, /* IAsyncInfo */ - async_operation_info_get_Id, - async_operation_info_get_Status, - async_operation_info_get_ErrorCode, - async_operation_info_Cancel, - async_operation_info_Close + async_inspectable_info_get_Id, + async_inspectable_info_get_Status, + async_inspectable_info_get_ErrorCode, + async_inspectable_info_Cancel, + async_inspectable_info_Close };
-static void CALLBACK async_run_cb(TP_CALLBACK_INSTANCE *instance, void *data, TP_WORK *work) +static void CALLBACK async_inspectable_run_cb(TP_CALLBACK_INSTANCE *instance, void *data, TP_WORK *work) { IAsyncOperation_IInspectable *operation = data; IInspectable *result = NULL; - struct async_operation *impl = impl_from_IAsyncOperation_IInspectable(operation); + struct async_inspectable *impl = impl_from_IAsyncOperation_IInspectable(operation); HRESULT hr;
hr = impl->callback(impl->invoker, &result); @@ -363,16 +363,19 @@ static void CALLBACK async_run_cb(TP_CALLBACK_INSTANCE *instance, void *data, TP IAsyncOperation_IInspectable_Release(operation); }
-HRESULT async_operation_create( const GUID *iid, IInspectable *invoker, async_operation_callback callback, IAsyncOperation_IInspectable **out ) +HRESULT async_operation_inspectable_create( const GUID *iid, + IInspectable *invoker, + async_operation_inspectable_callback callback, + IAsyncOperation_IInspectable **out ) { - struct async_operation *impl; + struct async_inspectable *impl;
TRACE("iid %s, invoker %p, callback %p, out %p.\n", debugstr_guid(iid), invoker, callback, out);
*out = NULL; if (!(impl = calloc(1, sizeof(*impl)))) return E_OUTOFMEMORY; - impl->IAsyncOperation_IInspectable_iface.lpVtbl = &async_operation_vtbl; - impl->IAsyncInfo_iface.lpVtbl = &async_operation_info_vtbl; + impl->IAsyncOperation_IInspectable_iface.lpVtbl = &async_inspectable_vtbl; + impl->IAsyncInfo_iface.lpVtbl = &async_inspectable_info_vtbl; impl->iid = iid; impl->ref = 1;
@@ -380,7 +383,7 @@ HRESULT async_operation_create( const GUID *iid, IInspectable *invoker, async_op impl->callback = callback; impl->status = Started;
- if (!(impl->async_run_work = CreateThreadpoolWork(async_run_cb, &impl->IAsyncOperation_IInspectable_iface, NULL))) + if (!(impl->async_run_work = CreateThreadpoolWork(async_inspectable_run_cb, &impl->IAsyncOperation_IInspectable_iface, NULL))) { free(impl); return HRESULT_FROM_WIN32(GetLastError()); diff --git a/dlls/windows.media.speech/private.h b/dlls/windows.media.speech/private.h index 4b55a5cbfa7..97afa4d3499 100644 --- a/dlls/windows.media.speech/private.h +++ b/dlls/windows.media.speech/private.h @@ -69,9 +69,10 @@ struct vector_iids const GUID *view; };
-typedef HRESULT (WINAPI *async_operation_callback)( IInspectable *invoker, IInspectable **result ); +typedef HRESULT (WINAPI *async_operation_inspectable_callback)( IInspectable *invoker, IInspectable **result );
-HRESULT async_operation_create( const GUID *iid, IInspectable *invoker, async_operation_callback callback, IAsyncOperation_IInspectable **out ); +HRESULT async_operation_inspectable_create( const GUID *iid, IInspectable *invoker, async_operation_inspectable_callback callback, + IAsyncOperation_IInspectable **out );
HRESULT typed_event_handlers_append( struct list *list, ITypedEventHandler_IInspectable_IInspectable *handler, EventRegistrationToken *token ); HRESULT typed_event_handlers_remove( struct list *list, EventRegistrationToken *token ); diff --git a/dlls/windows.media.speech/recognizer.c b/dlls/windows.media.speech/recognizer.c index 39813ef5607..c78f69b0a67 100644 --- a/dlls/windows.media.speech/recognizer.c +++ b/dlls/windows.media.speech/recognizer.c @@ -480,7 +480,7 @@ static HRESULT WINAPI recognizer_CompileConstraintsAsync( ISpeechRecognizer *ifa { IAsyncOperation_IInspectable **value = (IAsyncOperation_IInspectable **)operation; FIXME("iface %p, operation %p semi-stub!\n", iface, operation); - return async_operation_create(&IID_IAsyncOperation_SpeechRecognitionCompilationResult, NULL, compile_callback, value); + return async_operation_inspectable_create(&IID_IAsyncOperation_SpeechRecognitionCompilationResult, NULL, compile_callback, value); }
static HRESULT WINAPI recognizer_RecognizeAsync( ISpeechRecognizer *iface,
From: Bernhard Kölbl besentv@gmail.com
Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/windows.media.speech/async.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/dlls/windows.media.speech/async.c b/dlls/windows.media.speech/async.c index 79510d61dc7..eceda4338b3 100644 --- a/dlls/windows.media.speech/async.c +++ b/dlls/windows.media.speech/async.c @@ -231,11 +231,12 @@ static const struct IAsyncOperation_IInspectableVtbl async_inspectable_vtbl =
/* * - * IAsyncInfo + * IAsyncInfo for IAsyncOperation<IInspectable*> * */
-DEFINE_IINSPECTABLE(async_inspectable_info, IAsyncInfo, struct async_inspectable, IAsyncOperation_IInspectable_iface) +DEFINE_IINSPECTABLE_(async_inspectable_info, IAsyncInfo, struct async_inspectable, + async_inspectable_impl_from_IAsyncInfo, IAsyncInfo_iface, &impl->IAsyncOperation_IInspectable_iface)
static HRESULT WINAPI async_inspectable_info_get_Id( IAsyncInfo *iface, UINT32 *id ) { @@ -245,7 +246,7 @@ static HRESULT WINAPI async_inspectable_info_get_Id( IAsyncInfo *iface, UINT32 *
static HRESULT WINAPI async_inspectable_info_get_Status( IAsyncInfo *iface, AsyncStatus *status ) { - struct async_inspectable *impl = impl_from_IAsyncInfo(iface); + struct async_inspectable *impl = async_inspectable_impl_from_IAsyncInfo(iface); HRESULT hr = S_OK;
TRACE("iface %p, status %p.\n", iface, status); @@ -261,7 +262,7 @@ static HRESULT WINAPI async_inspectable_info_get_Status( IAsyncInfo *iface, Asyn
static HRESULT WINAPI async_inspectable_info_get_ErrorCode( IAsyncInfo *iface, HRESULT *error_code ) { - struct async_inspectable *impl = impl_from_IAsyncInfo(iface); + struct async_inspectable *impl = async_inspectable_impl_from_IAsyncInfo(iface); HRESULT hr = S_OK;
TRACE("iface %p, error_code %p.\n", iface, error_code); @@ -278,7 +279,7 @@ static HRESULT WINAPI async_inspectable_info_get_ErrorCode( IAsyncInfo *iface, H
static HRESULT WINAPI async_inspectable_info_Cancel( IAsyncInfo *iface ) { - struct async_inspectable *impl = impl_from_IAsyncInfo(iface); + struct async_inspectable *impl = async_inspectable_impl_from_IAsyncInfo(iface); HRESULT hr = S_OK;
TRACE("iface %p.\n", iface); @@ -295,7 +296,7 @@ static HRESULT WINAPI async_inspectable_info_Cancel( IAsyncInfo *iface )
static HRESULT WINAPI async_inspectable_info_Close( IAsyncInfo *iface ) { - struct async_inspectable *impl = impl_from_IAsyncInfo(iface); + struct async_inspectable *impl = async_inspectable_impl_from_IAsyncInfo(iface); HRESULT hr = S_OK;
TRACE("iface %p.\n", iface);
From: Bernhard Kölbl besentv@gmail.com
So it can be used more generic.
Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/windows.media.speech/tests/speech.c | 84 ++++++++++++------------ 1 file changed, 42 insertions(+), 42 deletions(-)
diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c index 6be02948809..164f8541267 100644 --- a/dlls/windows.media.speech/tests/speech.c +++ b/dlls/windows.media.speech/tests/speech.c @@ -54,11 +54,7 @@ #define impl_from_IHandler_RecognitionCompleted impl_from_ITypedEventHandler_SpeechContinuousRecognitionSession_SpeechContinuousRecognitionCompletedEventArgs #define IHandler_RecognitionCompleted_iface ITypedEventHandler_SpeechContinuousRecognitionSession_SpeechContinuousRecognitionCompletedEventArgs_iface
-#define IAsyncHandler_Compilation IAsyncOperationCompletedHandler_SpeechRecognitionCompilationResult -#define IAsyncHandler_CompilationVtbl IAsyncOperationCompletedHandler_SpeechRecognitionCompilationResultVtbl -#define IID_IAsyncHandler_Compilation IID_IAsyncOperationCompletedHandler_SpeechRecognitionCompilationResult -#define impl_from_IAsyncHandler_Compilation impl_from_IAsyncOperationCompletedHandler_SpeechRecognitionCompilationResult -#define IAsyncHandler_Compilation_iface IAsyncOperationCompletedHandler_SpeechRecognitionCompilationResult_iface +#define IAsyncHandler_IInspectable_iface IAsyncOperationCompletedHandler_IInspectable_iface
HRESULT WINAPI (*pDllGetActivationFactory)(HSTRING, IActivationFactory **); static BOOL is_win10_1507 = FALSE; @@ -234,9 +230,10 @@ static HRESULT WINAPI recognition_result_handler_create_static( struct recogniti return S_OK; }
-struct compilation_handler +struct async_inspectable_handler { - IAsyncHandler_Compilation IAsyncHandler_Compilation_iface; + IAsyncOperationCompletedHandler_IInspectable IAsyncHandler_IInspectable_iface; + const GUID *iid; LONG ref;
HANDLE event_block; @@ -245,18 +242,20 @@ struct compilation_handler DWORD thread_id; };
-static inline struct compilation_handler *impl_from_IAsyncHandler_Compilation( IAsyncHandler_Compilation *iface ) +static inline struct async_inspectable_handler *impl_from_IAsyncOperationCompletedHandler_IInspectable( IAsyncOperationCompletedHandler_IInspectable *iface ) { - return CONTAINING_RECORD(iface, struct compilation_handler, IAsyncHandler_Compilation_iface); + return CONTAINING_RECORD(iface, struct async_inspectable_handler, IAsyncHandler_IInspectable_iface); }
-HRESULT WINAPI compilation_handler_QueryInterface( IAsyncHandler_Compilation *iface, - REFIID iid, - void **out ) +HRESULT WINAPI async_inspectable_handler_QueryInterface( IAsyncOperationCompletedHandler_IInspectable *iface, + REFIID iid, + void **out ) { + struct async_inspectable_handler *impl = impl_from_IAsyncOperationCompletedHandler_IInspectable(iface); + if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IAgileObject) || - IsEqualGUID(iid, &IID_IAsyncHandler_Compilation)) + IsEqualGUID(iid, impl->iid)) { IUnknown_AddRef(iface); *out = iface; @@ -268,27 +267,27 @@ HRESULT WINAPI compilation_handler_QueryInterface( IAsyncHandler_Compilation *if return E_NOINTERFACE; }
-ULONG WINAPI compilation_handler_AddRef( IAsyncHandler_Compilation *iface ) +ULONG WINAPI async_inspectable_handler_AddRef( IAsyncOperationCompletedHandler_IInspectable *iface ) { - struct compilation_handler *impl = impl_from_IAsyncHandler_Compilation(iface); + struct async_inspectable_handler *impl = impl_from_IAsyncOperationCompletedHandler_IInspectable(iface); ULONG ref = InterlockedIncrement(&impl->ref); return ref; }
-ULONG WINAPI compilation_handler_Release( IAsyncHandler_Compilation *iface ) +ULONG WINAPI async_inspectable_handler_Release( IAsyncOperationCompletedHandler_IInspectable *iface ) { - struct compilation_handler *impl = impl_from_IAsyncHandler_Compilation(iface); + struct async_inspectable_handler *impl = impl_from_IAsyncOperationCompletedHandler_IInspectable(iface); ULONG ref = InterlockedDecrement(&impl->ref); return ref; }
-HRESULT WINAPI compilation_handler_Invoke( IAsyncHandler_Compilation *iface, - IAsyncOperation_SpeechRecognitionCompilationResult *info, - AsyncStatus status ) +HRESULT WINAPI async_inspectable_handler_Invoke( IAsyncOperationCompletedHandler_IInspectable *iface, + IAsyncOperation_IInspectable *sender, + AsyncStatus status ) { - struct compilation_handler *impl = impl_from_IAsyncHandler_Compilation(iface); + struct async_inspectable_handler *impl = impl_from_IAsyncOperationCompletedHandler_IInspectable(iface); DWORD id = GetCurrentThreadId(); - trace("Iface %p, info %p, status %d.\n", iface, info, status); + trace("Iface %p, sender %p, status %d.\n", iface, sender, status); trace("Caller thread id %lu callback thread id %lu.\n", impl->thread_id, id);
/* Signal finishing of the handler. */ @@ -301,20 +300,21 @@ HRESULT WINAPI compilation_handler_Invoke( IAsyncHandler_Compilation *iface, return S_OK; }
-static const struct IAsyncHandler_CompilationVtbl compilation_handler_vtbl = +static const struct IAsyncOperationCompletedHandler_IInspectableVtbl asnyc_inspectable_handler_vtbl = { /* IUnknown methods */ - compilation_handler_QueryInterface, - compilation_handler_AddRef, - compilation_handler_Release, - /* IAsyncOperationCompletedHandler<SpeechRecognitionCompilationResult* > methods */ - compilation_handler_Invoke + async_inspectable_handler_QueryInterface, + async_inspectable_handler_AddRef, + async_inspectable_handler_Release, + /* IAsyncOperationCompletedHandler<IInspectable* > methods */ + async_inspectable_handler_Invoke };
-static HRESULT WINAPI compilation_handler_create_static( struct compilation_handler *impl ) +static HRESULT WINAPI async_inspectable_handler_create_static( struct async_inspectable_handler *impl, const GUID *iid ) { - impl->IAsyncHandler_Compilation_iface.lpVtbl = &compilation_handler_vtbl; + impl->IAsyncOperationCompletedHandler_IInspectable_iface.lpVtbl = &asnyc_inspectable_handler_vtbl; + impl->iid = iid; impl->ref = 1;
return S_OK; @@ -820,8 +820,8 @@ static void test_VoiceInformation(void)
struct op_put_completed_thread_param { - IAsyncOperationCompletedHandler_SpeechRecognitionCompilationResult *handler; - IAsyncOperation_SpeechRecognitionCompilationResult *operation; + IAsyncOperationCompletedHandler_IInspectable *handler; + IAsyncOperation_IInspectable *operation; };
static DWORD WINAPI put_completed_thread(void *arg) @@ -829,7 +829,7 @@ static DWORD WINAPI put_completed_thread(void *arg) struct op_put_completed_thread_param *param = arg; HRESULT hr;
- hr = IAsyncOperation_SpeechRecognitionCompilationResult_put_Completed(param->operation, param->handler); + hr = IAsyncOperation_IInspectable_put_Completed(param->operation, param->handler); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
return 0; @@ -853,9 +853,9 @@ static void test_SpeechRecognizer(void) ILanguage *language = NULL; IAsyncInfo *info = NULL; struct op_put_completed_thread_param put_completed_param; + struct async_inspectable_handler compilation_handler; struct completed_event_handler completed_handler; struct recognition_result_handler result_handler; - struct compilation_handler compilation_handler; SpeechRecognitionResultStatus result_status; EventRegistrationToken token = { .value = 0 }; AsyncStatus async_status; @@ -975,7 +975,7 @@ static void test_SpeechRecognizer(void) ref = IVector_ISpeechRecognitionConstraint_Release(constraints); ok(ref == 1, "Got unexpected ref %lu.\n", ref);
- compilation_handler_create_static(&compilation_handler); + async_inspectable_handler_create_static(&compilation_handler, &IID_IAsyncOperationCompletedHandler_SpeechRecognitionCompilationResult); compilation_handler.event_finished = CreateEventW(NULL, FALSE, FALSE, NULL); compilation_handler.thread_id = GetCurrentThreadId();
@@ -994,7 +994,7 @@ static void test_SpeechRecognizer(void) ok(hr == E_ILLEGAL_METHOD_CALL, "Got unexpected hr %#lx.\n", hr); ok(compilation_result == (void*)0xdeadbeef, "Compilation result had value %p.\n", compilation_result);
- hr = IAsyncOperation_SpeechRecognitionCompilationResult_put_Completed(operation, &compilation_handler.IAsyncHandler_Compilation_iface); + hr = IAsyncOperation_IInspectable_put_Completed((IAsyncOperation_IInspectable *) operation, &compilation_handler.IAsyncHandler_IInspectable_iface); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
ok(!WaitForSingleObject(compilation_handler.event_finished, 1000), "Wait for event_finished failed.\n"); @@ -1076,7 +1076,7 @@ static void test_SpeechRecognizer(void) IAsyncOperation_SpeechRecognitionCompilationResult_Release(operation);
/* Test if AsyncOperation is started immediately. */ - compilation_handler_create_static(&compilation_handler); + async_inspectable_handler_create_static(&compilation_handler, &IID_IAsyncOperationCompletedHandler_SpeechRecognitionCompilationResult); compilation_handler.event_finished = CreateEventW(NULL, FALSE, FALSE, NULL); compilation_handler.thread_id = GetCurrentThreadId();
@@ -1094,7 +1094,7 @@ static void test_SpeechRecognizer(void) ok(hr == S_OK, "IAsyncInfo_get_Status failed, hr %#lx.\n", hr); ok(async_status != AsyncStatus_Closed, "Status was %#x.\n", async_status);
- hr = IAsyncOperation_SpeechRecognitionCompilationResult_put_Completed(operation, &compilation_handler.IAsyncHandler_Compilation_iface); + hr = IAsyncOperation_IInspectable_put_Completed((IAsyncOperation_IInspectable *) operation, &compilation_handler.IAsyncHandler_IInspectable_iface); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
ok(!WaitForSingleObject(compilation_handler.event_finished, 1000), "Wait for event_finished failed.\n"); @@ -1123,7 +1123,7 @@ static void test_SpeechRecognizer(void) hr = IInspectable_QueryInterface(inspectable, &IID_ISpeechRecognizer, (void **)&recognizer); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
- compilation_handler_create_static(&compilation_handler); + async_inspectable_handler_create_static(&compilation_handler, &IID_IAsyncOperationCompletedHandler_SpeechRecognitionCompilationResult); compilation_handler.event_block = CreateEventW(NULL, FALSE, FALSE, NULL); compilation_handler.event_finished = CreateEventW(NULL, FALSE, FALSE, NULL); compilation_handler.event_unblock = CreateEventW(NULL, FALSE, FALSE, NULL); @@ -1136,8 +1136,8 @@ static void test_SpeechRecognizer(void) hr = ISpeechRecognizer_CompileConstraintsAsync(recognizer, &operation); ok(hr == S_OK, "ISpeechRecognizer_CompileConstraintsAsync failed, hr %#lx.\n", hr);
- put_completed_param.handler = &compilation_handler.IAsyncHandler_Compilation_iface; - put_completed_param.operation = operation; + put_completed_param.handler = &compilation_handler.IAsyncHandler_IInspectable_iface; + put_completed_param.operation = (IAsyncOperation_IInspectable *)operation; put_thread = CreateThread(NULL, 0, put_completed_thread, &put_completed_param, 0, NULL);
ok(!WaitForSingleObject(compilation_handler.event_finished, 5000), "Wait for event_finished failed.\n"); @@ -1147,7 +1147,7 @@ static void test_SpeechRecognizer(void) old_ref = compilation_handler.ref; hr = IAsyncOperation_SpeechRecognitionCompilationResult_get_Completed(operation, &handler); ok(hr == S_OK, "IAsyncOperation_SpeechRecognitionCompilationResult_get_Completed failed, hr %#lx.\n", hr); - todo_wine ok(handler == &compilation_handler.IAsyncHandler_Compilation_iface, "Handler was %p.\n", handler); + todo_wine ok(handler == (void *)&compilation_handler.IAsyncHandler_IInspectable_iface, "Handler was %p.\n", handler);
ref = compilation_handler.ref - old_ref; todo_wine ok(ref == 1, "The ref was increased by %lu.\n", ref);
From: Bernhard Kölbl besentv@gmail.com
Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/windows.media.speech/tests/speech.c | 44 +++++++++++++----------- 1 file changed, 23 insertions(+), 21 deletions(-)
diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c index 164f8541267..b458c33eb11 100644 --- a/dlls/windows.media.speech/tests/speech.c +++ b/dlls/windows.media.speech/tests/speech.c @@ -310,7 +310,6 @@ static const struct IAsyncOperationCompletedHandler_IInspectableVtbl asnyc_inspe async_inspectable_handler_Invoke };
- static HRESULT WINAPI async_inspectable_handler_create_static( struct async_inspectable_handler *impl, const GUID *iid ) { impl->IAsyncOperationCompletedHandler_IInspectable_iface.lpVtbl = &asnyc_inspectable_handler_vtbl; @@ -320,6 +319,23 @@ static HRESULT WINAPI async_inspectable_handler_create_static( struct async_insp return S_OK; }
+#define await_async_inspectable(operation, handler, iid) await_async_inspectable_(__LINE__, operation, handler, iid) +static void await_async_inspectable_( unsigned int line, IAsyncOperation_IInspectable *operation, struct async_inspectable_handler *handler, const GUID *handler_iid ) +{ + HRESULT hr; + + async_inspectable_handler_create_static(handler, handler_iid); + handler->event_block = NULL; + handler->event_unblock = NULL; + handler->event_finished = CreateEventW(NULL, FALSE, FALSE, NULL); + ok_(__FILE__, line)(!!handler->event_finished, "event_finished wasn't created.\n"); + + hr = IAsyncOperation_IInspectable_put_Completed(operation, &handler->IAsyncHandler_IInspectable_iface); + ok_(__FILE__, line)(hr == S_OK, "IAsyncOperation_IInspectable_put_Completed failed, hr %#lx.\n", hr); + ok_(__FILE__, line)(!WaitForSingleObject(handler->event_finished , 5000), "Wait for event_finished failed.\n"); + CloseHandle(handler->event_finished); +} + struct iterator_hstring { IIterator_HSTRING IIterator_HSTRING_iface; @@ -975,10 +991,6 @@ static void test_SpeechRecognizer(void) ref = IVector_ISpeechRecognitionConstraint_Release(constraints); ok(ref == 1, "Got unexpected ref %lu.\n", ref);
- async_inspectable_handler_create_static(&compilation_handler, &IID_IAsyncOperationCompletedHandler_SpeechRecognitionCompilationResult); - compilation_handler.event_finished = CreateEventW(NULL, FALSE, FALSE, NULL); - compilation_handler.thread_id = GetCurrentThreadId(); - hr = ISpeechRecognizer_CompileConstraintsAsync(recognizer, &operation); ok(hr == S_OK, "ISpeechRecognizer_CompileConstraintsAsync failed, hr %#lx.\n", hr);
@@ -994,11 +1006,9 @@ static void test_SpeechRecognizer(void) ok(hr == E_ILLEGAL_METHOD_CALL, "Got unexpected hr %#lx.\n", hr); ok(compilation_result == (void*)0xdeadbeef, "Compilation result had value %p.\n", compilation_result);
- hr = IAsyncOperation_IInspectable_put_Completed((IAsyncOperation_IInspectable *) operation, &compilation_handler.IAsyncHandler_IInspectable_iface); - ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - - ok(!WaitForSingleObject(compilation_handler.event_finished, 1000), "Wait for event_finished failed.\n"); - CloseHandle(compilation_handler.event_finished); + await_async_inspectable((IAsyncOperation_IInspectable *)operation, + &compilation_handler, + &IID_IAsyncOperationCompletedHandler_SpeechRecognitionCompilationResult);
hr = IAsyncOperation_SpeechRecognitionCompilationResult_put_Completed(operation, NULL); ok(hr == E_ILLEGAL_DELEGATE_ASSIGNMENT, "Got unexpected hr %#lx.\n", hr); @@ -1076,12 +1086,6 @@ static void test_SpeechRecognizer(void) IAsyncOperation_SpeechRecognitionCompilationResult_Release(operation);
/* Test if AsyncOperation is started immediately. */ - async_inspectable_handler_create_static(&compilation_handler, &IID_IAsyncOperationCompletedHandler_SpeechRecognitionCompilationResult); - compilation_handler.event_finished = CreateEventW(NULL, FALSE, FALSE, NULL); - compilation_handler.thread_id = GetCurrentThreadId(); - - ok(compilation_handler.event_finished != NULL, "Finished event wasn't created.\n"); - hr = ISpeechRecognizer_CompileConstraintsAsync(recognizer, &operation); ok(hr == S_OK, "ISpeechRecognizer_CompileConstraintsAsync failed, hr %#lx.\n", hr); check_interface(operation, &IID_IAgileObject, TRUE); @@ -1094,11 +1098,9 @@ static void test_SpeechRecognizer(void) ok(hr == S_OK, "IAsyncInfo_get_Status failed, hr %#lx.\n", hr); ok(async_status != AsyncStatus_Closed, "Status was %#x.\n", async_status);
- hr = IAsyncOperation_IInspectable_put_Completed((IAsyncOperation_IInspectable *) operation, &compilation_handler.IAsyncHandler_IInspectable_iface); - ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - - ok(!WaitForSingleObject(compilation_handler.event_finished, 1000), "Wait for event_finished failed.\n"); - CloseHandle(compilation_handler.event_finished); + await_async_inspectable((IAsyncOperation_IInspectable *)operation, + &compilation_handler, + &IID_IAsyncOperationCompletedHandler_SpeechRecognitionCompilationResult);
async_status = 0xdeadbeef; hr = IAsyncInfo_get_Status(info, &async_status);
From: Bernhard Kölbl besentv@gmail.com
Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/windows.media.speech/tests/speech.c | 81 ++++++++++++------------ 1 file changed, 42 insertions(+), 39 deletions(-)
diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c index b458c33eb11..3c5744d6aa6 100644 --- a/dlls/windows.media.speech/tests/speech.c +++ b/dlls/windows.media.speech/tests/speech.c @@ -336,6 +336,39 @@ static void await_async_inspectable_( unsigned int line, IAsyncOperation_IInspec CloseHandle(handler->event_finished); }
+#define check_async_info(obj, exp_id, exp_status, exp_hr) check_asnyc_info_(__LINE__, obj, exp_id, exp_status, exp_hr) +static void check_asnyc_info_( unsigned int line, IInspectable *async_obj, UINT32 expect_id, AsyncStatus expect_status, HRESULT expect_hr) +{ + IAsyncInfo *async_info; + AsyncStatus async_status; + UINT32 async_id; + HRESULT hr, async_hr; + + hr = IInspectable_QueryInterface(async_obj, &IID_IAsyncInfo, (void **)&async_info); + ok_(__FILE__, line)(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + async_id = 0xdeadbeef; + hr = IAsyncInfo_get_Id(async_info, &async_id); + if (expect_status < 4) todo_wine ok_(__FILE__, line)(hr == S_OK, "IAsyncInfo_get_Id returned %#lx\n", hr); + else todo_wine ok_(__FILE__, line)(hr == E_ILLEGAL_METHOD_CALL, "IAsyncInfo_get_Id returned %#lx\n", hr); + todo_wine ok_(__FILE__, line)(async_id == expect_id, "got async_id %#x\n", async_id); + + async_status = 0xdeadbeef; + hr = IAsyncInfo_get_Status(async_info, &async_status); + if (expect_status < 4) ok_(__FILE__, line)(hr == S_OK, "IAsyncInfo_get_Status returned %#lx\n", hr); + else ok_(__FILE__, line)(hr == E_ILLEGAL_METHOD_CALL, "IAsyncInfo_get_Status returned %#lx\n", hr); + ok_(__FILE__, line)(async_status == expect_status, "got async_status %#x\n", async_status); + + async_hr = 0xdeadbeef; + hr = IAsyncInfo_get_ErrorCode(async_info, &async_hr); + if (expect_status < 4) ok_(__FILE__, line)(hr == S_OK, "IAsyncInfo_get_ErrorCode returned %#lx\n", hr); + else ok_(__FILE__, line)(hr == E_ILLEGAL_METHOD_CALL, "IAsyncInfo_get_ErrorCode returned %#lx\n", hr); + if (expect_status < 4) todo_wine_if(FAILED(expect_hr)) ok_(__FILE__, line)(async_hr == expect_hr, "got async_hr %#lx\n", async_hr); + else ok_(__FILE__, line)(async_hr == E_ILLEGAL_METHOD_CALL, "got async_hr %#lx\n", async_hr); + + IAsyncInfo_Release(async_info); +} + struct iterator_hstring { IIterator_HSTRING IIterator_HSTRING_iface; @@ -877,9 +910,8 @@ static void test_SpeechRecognizer(void) AsyncStatus async_status; HSTRING hstr, hstr_lang; HANDLE put_thread; - HRESULT hr, error_code; - UINT32 id; LONG ref, old_ref; + HRESULT hr;
hr = RoInitialize(RO_INIT_MULTITHREADED); ok(hr == S_OK, "RoInitialize failed, hr %#lx.\n", hr); @@ -1009,6 +1041,7 @@ static void test_SpeechRecognizer(void) await_async_inspectable((IAsyncOperation_IInspectable *)operation, &compilation_handler, &IID_IAsyncOperationCompletedHandler_SpeechRecognitionCompilationResult); + check_async_info((IInspectable *)operation, 1, Completed, S_OK);
hr = IAsyncOperation_SpeechRecognitionCompilationResult_put_Completed(operation, NULL); ok(hr == E_ILLEGAL_DELEGATE_ASSIGNMENT, "Got unexpected hr %#lx.\n", hr); @@ -1035,43 +1068,17 @@ static void test_SpeechRecognizer(void) hr = IAsyncOperation_SpeechRecognitionCompilationResult_QueryInterface(operation, &IID_IAsyncInfo, (void **)&info); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
- id = 0xdeadbeef; - hr = IAsyncInfo_get_Id(info, &id); - todo_wine ok(hr == S_OK, "IAsyncInfo_get_Id failed, hr %#lx.\n", hr); - todo_wine ok(id != 0xdeadbeef, "Id was %#x.\n", id); - - async_status = 0xdeadbeef; - hr = IAsyncInfo_get_Status(info, &async_status); - ok(hr == S_OK, "IAsyncInfo_get_Status failed, hr %#lx.\n", hr); - ok(async_status == Completed, "Status was %#x.\n", async_status); - - error_code = 0xdeadbeef; - hr = IAsyncInfo_get_ErrorCode(info, &error_code); - ok(hr == S_OK, "IAsyncInfo_get_ErrorCode failed, hr %#lx.\n", hr); - ok(error_code == S_OK, "ErrorCode was %#lx.\n", error_code); - hr = IAsyncInfo_Cancel(info); ok(hr == S_OK, "IAsyncInfo_Cancel failed, hr %#lx.\n", hr); - - async_status = 0xdeadbeef; - hr = IAsyncInfo_get_Status(info, &async_status); - ok(hr == S_OK, "IAsyncInfo_get_Status failed, hr %#lx.\n", hr); - ok(async_status == Completed, "Status was %#x.\n", async_status); + check_async_info((IInspectable *)operation, 1, Completed, S_OK);
hr = IAsyncInfo_Close(info); ok(hr == S_OK, "IAsyncInfo_Close failed, hr %#lx.\n", hr); + check_async_info((IInspectable *)operation, 1, AsyncStatus_Closed, S_OK); + hr = IAsyncInfo_Close(info); ok(hr == S_OK, "IAsyncInfo_Close failed, hr %#lx.\n", hr); - - async_status = 0xdeadbeef; - hr = IAsyncInfo_get_Status(info, &async_status); - ok(hr == E_ILLEGAL_METHOD_CALL, "IAsyncInfo_get_Status failed, hr %#lx.\n", hr); - ok(async_status == AsyncStatus_Closed, "Status was %#x.\n", async_status); - - error_code = 0xdeadbeef; - hr = IAsyncInfo_get_ErrorCode(info, &error_code); - ok(hr == E_ILLEGAL_METHOD_CALL, "IAsyncInfo_get_ErrorCode failed, hr %#lx.\n", hr); - ok(error_code == E_ILLEGAL_METHOD_CALL, "ErrorCode was %#lx.\n", error_code); + check_async_info((IInspectable *)operation, 1, AsyncStatus_Closed, S_OK);
ref = IAsyncInfo_Release(info); ok(ref == 1, "Got unexpected ref %lu.\n", ref); @@ -1097,18 +1104,13 @@ static void test_SpeechRecognizer(void) hr = IAsyncInfo_get_Status(info, &async_status); ok(hr == S_OK, "IAsyncInfo_get_Status failed, hr %#lx.\n", hr); ok(async_status != AsyncStatus_Closed, "Status was %#x.\n", async_status); + IAsyncInfo_Release(info);
await_async_inspectable((IAsyncOperation_IInspectable *)operation, &compilation_handler, &IID_IAsyncOperationCompletedHandler_SpeechRecognitionCompilationResult); + check_async_info((IInspectable *)operation, 2, Completed, S_OK);
- async_status = 0xdeadbeef; - hr = IAsyncInfo_get_Status(info, &async_status); - ok(hr == S_OK, "IAsyncInfo_get_Status failed, hr %#lx.\n", hr); - ok(async_status == Completed, "Status was %#x.\n", async_status); - - ref = IAsyncInfo_Release(info); - ok(ref >= 1, "Got unexpected ref %lu.\n", ref); ref = IAsyncOperation_SpeechRecognitionCompilationResult_Release(operation); ok(ref >= 0, "Got unexpected ref %lu.\n", ref);
@@ -1163,6 +1165,7 @@ static void test_SpeechRecognizer(void)
SetEvent(compilation_handler.event_block); ok(!WaitForSingleObject(compilation_handler.event_unblock, 1000), "Wait for event_unblock failed.\n"); + check_async_info((IInspectable *)operation, 1, AsyncStatus_Closed, S_OK);
CloseHandle(put_thread); CloseHandle(compilation_handler.event_block);
From: Bernhard Kölbl besentv@gmail.com
Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/windows.media.speech/tests/speech.c | 359 +++++++++++++++++++++++ 1 file changed, 359 insertions(+)
diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c index 3c5744d6aa6..1f04f75fabb 100644 --- a/dlls/windows.media.speech/tests/speech.c +++ b/dlls/windows.media.speech/tests/speech.c @@ -230,6 +230,103 @@ static HRESULT WINAPI recognition_result_handler_create_static( struct recogniti return S_OK; }
+struct async_void_handler +{ + IAsyncActionCompletedHandler IAsyncActionCompletedHandler_iface; + LONG ref; + + HANDLE event_block; + HANDLE event_unblock; + HANDLE event_finished; +}; + +static inline struct async_void_handler *impl_from_IAsyncActionCompletedHandler(IAsyncActionCompletedHandler *iface) +{ + return CONTAINING_RECORD(iface, struct async_void_handler, IAsyncActionCompletedHandler_iface); +} + +HRESULT WINAPI async_void_handler_QueryInterface( IAsyncActionCompletedHandler *iface, REFIID iid, void **out ) +{ + if (IsEqualGUID(iid, &IID_IUnknown) || + IsEqualGUID(iid, &IID_IAgileObject) || + IsEqualGUID(iid, &IID_IAsyncActionCompletedHandler)) + { + IUnknown_AddRef(iface); + *out = iface; + return S_OK; + } + + trace("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + *out = NULL; + return E_NOINTERFACE; +} + +ULONG WINAPI async_void_handler_AddRef( IAsyncActionCompletedHandler *iface ) +{ + struct async_void_handler *impl = impl_from_IAsyncActionCompletedHandler(iface); + ULONG ref = InterlockedIncrement(&impl->ref); + return ref; +} + +ULONG WINAPI async_void_handler_Release( IAsyncActionCompletedHandler *iface ) +{ + struct async_void_handler *impl = impl_from_IAsyncActionCompletedHandler(iface); + ULONG ref = InterlockedDecrement(&impl->ref); + return ref; +} + +HRESULT WINAPI async_void_handler_Invoke( IAsyncActionCompletedHandler *iface, IAsyncAction *sender, AsyncStatus status ) +{ + struct async_void_handler *impl = impl_from_IAsyncActionCompletedHandler(iface); + + trace("iface %p, sender %p, status %d.\n", iface, sender, status); + + /* Signal finishing of the handler. */ + if (impl->event_finished) SetEvent(impl->event_finished); + /* Block handler until event is set. */ + if (impl->event_block) WaitForSingleObject(impl->event_block, INFINITE); + /* Signal unblock of the handler. */ + if (impl->event_unblock) SetEvent(impl->event_unblock); + + return S_OK; +} + +static const struct IAsyncActionCompletedHandlerVtbl async_void_handler_vtbl = +{ + /* IUnknown methods */ + async_void_handler_QueryInterface, + async_void_handler_AddRef, + async_void_handler_Release, + /* IAsyncActionCompletedHandler methods */ + async_void_handler_Invoke +}; + + +static HRESULT WINAPI async_void_handler_create_static( struct async_void_handler *impl ) +{ + impl->IAsyncActionCompletedHandler_iface.lpVtbl = &async_void_handler_vtbl; + impl->ref = 1; + + return S_OK; +} + +#define await_async_void(operation, handler) await_async_void_(__LINE__, operation, handler) +static void await_async_void_( unsigned int line, IAsyncAction *action, struct async_void_handler *handler ) +{ + HRESULT hr; + + async_void_handler_create_static(handler); + handler->event_block = NULL; + handler->event_unblock = NULL; + handler->event_finished = CreateEventW(NULL, FALSE, FALSE, NULL); + ok_(__FILE__, line)(!!handler->event_finished, "event_finished wasn't created.\n"); + + hr = IAsyncAction_put_Completed(action, &handler->IAsyncActionCompletedHandler_iface); + ok_(__FILE__, line)(hr == S_OK, "IAsyncAction_put_Completed failed, hr %#lx.\n", hr); + ok_(__FILE__, line)(!WaitForSingleObject(handler->event_finished , 5000), "Wait for event_finished failed.\n"); + CloseHandle(handler->event_finished); +} + struct async_inspectable_handler { IAsyncOperationCompletedHandler_IInspectable IAsyncHandler_IInspectable_iface; @@ -1349,6 +1446,267 @@ done: RoUninitialize(); }
+struct action_put_completed_thread_param +{ + IAsyncActionCompletedHandler *handler; + IAsyncAction *action; +}; + +static DWORD WINAPI action_put_completed_thread(void *arg) +{ + struct action_put_completed_thread_param *param = arg; + HRESULT hr; + + hr = IAsyncAction_put_Completed(param->action, param->handler); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + return 0; +} + +static void test_Recognition(void) +{ + static const WCHAR *list_constraint_name = L"Windows.Media.SpeechRecognition.SpeechRecognitionListConstraint"; + static const WCHAR *recognizer_name = L"Windows.Media.SpeechRecognition.SpeechRecognizer"; + static const WCHAR *speech_constraint_tag = L"test_message"; + static const WCHAR *speech_constraints[] = { L"This is a test.", L"Number 5!", L"What time is it?" }; + ISpeechRecognitionListConstraintFactory *listconstraint_factory = NULL; + IAsyncOperation_SpeechRecognitionCompilationResult *operation = NULL; + IVector_ISpeechRecognitionConstraint *constraints = NULL; + ISpeechContinuousRecognitionSession *session = NULL; + ISpeechRecognitionListConstraint *listconstraint = NULL; + ISpeechRecognitionConstraint *constraint = NULL; + ISpeechRecognizer *recognizer = NULL; + ISpeechRecognizer2 *recognizer2 = NULL; + IAsyncActionCompletedHandler *handler = NULL; + IAsyncAction *action = NULL, *action2 = NULL; + IInspectable *inspectable = NULL; + IAsyncInfo *info = NULL; + struct async_inspectable_handler compilation_handler; + struct action_put_completed_thread_param put_param; + struct recognition_result_handler result_handler; + struct async_void_handler action_handler; + struct iterator_hstring iterator_hstring; + struct iterable_hstring iterable_hstring; + EventRegistrationToken token = { .value = 0 }; + HSTRING commands[3], hstr, tag; + HANDLE put_thread; + LONG ref, old_ref; + HRESULT hr; + UINT32 i; + BOOL set; + + hr = RoInitialize(RO_INIT_MULTITHREADED); + ok(hr == S_OK, "RoInitialize failed, hr %#lx.\n", hr); + + for (i = 0; i < ARRAY_SIZE(commands); i++) + { + hr = WindowsCreateString(speech_constraints[i], wcslen(speech_constraints[i]), &commands[i]); + ok(hr == S_OK, "WindowsCreateString failed, hr %#lx.\n", hr); + } + + /* The create functions for ListConstraint are broken on Win10 1507 x32 - abort early.*/ + if (broken(is_win10_1507 && (sizeof(void*) == 4))) + { + win_skip("SpeechRecognitionListConstraint object creation broken on Win10 1507 x32!\n"); + goto done; + } + + hr = WindowsCreateString(recognizer_name, wcslen(recognizer_name), &hstr); + ok(hr == S_OK, "WindowsCreateString failed, hr %#lx.\n", hr); + + hr = RoActivateInstance(hstr, &inspectable); + ok(hr == S_OK || broken(hr == SPERR_WINRT_INTERNAL_ERROR || hr == REGDB_E_CLASSNOTREG), "Got unexpected hr %#lx.\n", hr); + WindowsDeleteString(hstr); + + if (FAILED(hr)) /* Win 8 and 8.1 and Win10 without enabled SR. */ + { + win_skip("SpeechRecognizer cannot be activated!\n"); + goto done; + } + + hr = WindowsCreateString(list_constraint_name, wcslen(list_constraint_name), &hstr); + ok(hr == S_OK, "WindowsCreateString failed, hr %#lx.\n", hr); + + hr = RoGetActivationFactory(hstr, &IID_ISpeechRecognitionListConstraintFactory, (void **)&listconstraint_factory); + ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG), "RoGetActivationFactory failed, hr %#lx.\n", hr); + WindowsDeleteString(hstr); + + hr = WindowsCreateString(speech_constraint_tag, wcslen(speech_constraint_tag), &tag); + ok(hr == S_OK, "WindowsCreateString failed, hr %#lx.\n", hr); + + iterator_hstring_create_static(&iterator_hstring, commands, ARRAY_SIZE(commands)); + iterable_hstring_create_static(&iterable_hstring, &iterator_hstring); + hr = ISpeechRecognitionListConstraintFactory_CreateWithTag(listconstraint_factory, &iterable_hstring.IIterable_HSTRING_iface, tag, &listconstraint); + ok(hr == S_OK, "ISpeechRecognitionListConstraintFactory_Create failed, hr %#lx.\n", hr); + WindowsDeleteString(tag); + + ref = ISpeechRecognitionListConstraintFactory_Release(listconstraint_factory); + ok(ref == 1, "Got unexpected ref %lu.\n", ref); + + hr = ISpeechRecognitionListConstraint_QueryInterface(listconstraint, &IID_ISpeechRecognitionConstraint, (void **)&constraint); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = ISpeechRecognitionConstraint_put_IsEnabled(constraint, TRUE); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = IInspectable_QueryInterface(inspectable, &IID_ISpeechRecognizer, (void **)&recognizer); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = IInspectable_QueryInterface(inspectable, &IID_ISpeechRecognizer2, (void **)&recognizer2); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = ISpeechRecognizer2_get_ContinuousRecognitionSession(recognizer2, &session); + ok(hr == S_OK, "ISpeechRecognizer2_get_ContinuousRecognitionSession failed, hr %#lx.\n", hr); + + hr = ISpeechRecognizer_get_Constraints(recognizer, &constraints); + ok(hr == S_OK, "ISpeechContinuousRecognitionSession_get_Constraints failed, hr %#lx.\n", hr); + + hr = IVector_ISpeechRecognitionConstraint_Clear(constraints); + ok(hr == S_OK, "IVector_ISpeechRecognitionConstraint_Clear failed, hr %#lx.\n", hr); + + hr = IVector_ISpeechRecognitionConstraint_Append(constraints, constraint); + ok(hr == S_OK, "IVector_ISpeechRecognitionConstraint_Append failed, hr %#lx.\n", hr); + + ref = IVector_ISpeechRecognitionConstraint_Release(constraints); + ok(ref == 1, "Got unexpected ref %lu.\n", ref); + + ref = ISpeechRecognitionConstraint_Release(constraint); + ok(ref == 2, "Got unexpected ref %lu.\n", ref); + + ref = ISpeechRecognitionListConstraint_Release(listconstraint); + ok(ref == 1, "Got unexpected ref %lu.\n", ref); + + token.value = 0xdeadbeef; + recognition_result_handler_create_static(&result_handler); + hr = ISpeechContinuousRecognitionSession_add_ResultGenerated(session, &result_handler.IHandler_RecognitionResult_iface, &token); + ok(hr == S_OK, "ISpeechContinuousRecognitionSession_add_ResultGenerated failed, hr %#lx.\n", hr); + ok(token.value != 0xdeadbeef, "Got unexpexted token: %#I64x.\n", token.value); + + ISpeechRecognizer_CompileConstraintsAsync(recognizer, &operation); + ok(hr == S_OK, "ISpeechRecognizer_CompileConstraintsAsync failed, hr %#lx.\n", hr); + await_async_inspectable((IAsyncOperation_IInspectable *)operation, + &compilation_handler, + &IID_IAsyncOperationCompletedHandler_SpeechRecognitionCompilationResult); + + ref = IAsyncOperation_IInspectable_Release((IAsyncOperation_IInspectable *)operation); + ok(!ref, "Got unexpected ref %lu.\n", ref); + + hr = ISpeechContinuousRecognitionSession_StartAsync(session, &action); + todo_wine ok(hr == S_OK, "ISpeechContinuousRecognitionSession_StartAsync failed, hr %#lx.\n", hr); + + if (FAILED(hr)) goto skip_action; + + await_async_void(action, &action_handler); + check_async_info((IInspectable *)action, 1, Completed, S_OK); + + handler = (void *)0xdeadbeef; + hr = IAsyncAction_get_Completed(action, &handler); + todo_wine ok(hr == S_OK, "IAsyncAction_put_Completed failed, hr %#lx.\n", hr); + todo_wine ok(handler == NULL, "Handler was %p.\n", handler); + + hr = IAsyncAction_QueryInterface(action, &IID_IAsyncInfo, (void **)&info); + todo_wine ok(hr == S_OK, "IAsyncAction_QueryInterface failed, hr %#lx.\n", hr); + + hr = IAsyncInfo_Cancel(info); + todo_wine ok(hr == S_OK, "IAsyncInfo_Cancel failed, hr %#lx.\n", hr); + check_async_info((IInspectable *)action, 1, Completed, S_OK); + + hr = IAsyncInfo_Close(info); + todo_wine ok(hr == S_OK, "IAsyncInfo_Close failed, hr %#lx.\n", hr); + check_async_info((IInspectable *)action, 1, AsyncStatus_Closed, S_OK); + + hr = IAsyncInfo_Close(info); + todo_wine ok(hr == S_OK, "IAsyncInfo_Close failed, hr %#lx.\n", hr); + check_async_info((IInspectable *)action, 1, AsyncStatus_Closed, S_OK); + + hr = IAsyncInfo_Cancel(info); + todo_wine ok(hr == S_OK, "IAsyncInfo_Cancel failed, hr %#lx.\n", hr); + check_async_info((IInspectable *)action, 1, AsyncStatus_Closed, S_OK); + + ref = IAsyncInfo_Release(info); + todo_wine ok(ref == 1, "Got unexpected ref %lu.\n", ref); + + /* + * TODO: Use a loopback device together with prerecorded audio files to test the recognizer's functionality. + */ + + hr = ISpeechContinuousRecognitionSession_StopAsync(session, &action2); + todo_wine ok(hr == S_OK, "ISpeechContinuousRecognitionSession_StopAsync failed, hr %#lx.\n", hr); + + async_void_handler_create_static(&action_handler); + action_handler.event_block = CreateEventW(NULL, FALSE, FALSE, NULL); + action_handler.event_finished = CreateEventW(NULL, FALSE, FALSE, NULL); + action_handler.event_unblock = CreateEventW(NULL, FALSE, FALSE, NULL); + ok(!!action_handler.event_block, "Block event wasn't created.\n"); + ok(!!action_handler.event_finished, "Finished event wasn't created.\n"); + + /* Check if IAsyncInfo_Close is non blocking. */ + put_param.handler = &action_handler.IAsyncActionCompletedHandler_iface; + put_param.action = action2; + put_thread = CreateThread(NULL, 0, action_put_completed_thread, &put_param, 0, NULL); + todo_wine ok(!WaitForSingleObject(action_handler.event_finished , 5000), "Wait for event_finished failed.\n"); + todo_wine ok(WaitForSingleObject(action_handler.event_unblock, 100) == WAIT_TIMEOUT, "Wait for event_unblock didn't time out.\n"); + + handler = (void *)0xdeadbeef; + old_ref = action_handler.ref; + hr = IAsyncAction_get_Completed(action2, &handler); + todo_wine ok(hr == S_OK, "IAsyncAction_get_Completed failed, hr %#lx.\n", hr); + + todo_wine ok(handler == &action_handler.IAsyncActionCompletedHandler_iface || /* Broken on 1507. */ + broken(handler != NULL && handler != (void *)0xdeadbeef), "Handler was %p.\n", handler); + + ref = action_handler.ref - old_ref; + todo_wine ok(ref == 1, "The ref was increased by %lu.\n", ref); + IAsyncActionCompletedHandler_Release(handler); + + hr = IAsyncAction_QueryInterface(action2, &IID_IAsyncInfo, (void **)&info); + todo_wine ok(hr == S_OK, "IAsyncAction_QueryInterface failed, hr %#lx.\n", hr); + + hr = IAsyncInfo_Close(info); /* If IAsyncInfo_Close would wait for the handler to finish, the test would get stuck here. */ + todo_wine ok(hr == S_OK, "IAsyncInfo_Close failed, hr %#lx.\n", hr); + check_async_info((IInspectable *)action2, 3, AsyncStatus_Closed, S_OK); + + set = SetEvent(action_handler.event_block); + todo_wine ok(set == TRUE, "Event 'event_block' wasn't set.\n"); + todo_wine ok(!WaitForSingleObject(action_handler.event_unblock , 1000), "Wait for event_unblock failed.\n"); + IAsyncInfo_Release(info); + + CloseHandle(action_handler.event_finished); + CloseHandle(action_handler.event_block); + CloseHandle(action_handler.event_unblock); + CloseHandle(put_thread); + + todo_wine ok(action != action2, "actions were the same!\n"); + + ref = IAsyncAction_Release(action2); + todo_wine ok(!ref || broken(ref >= 0), "Got unexpected ref %lu.\n", ref); + + ref = IAsyncAction_Release(action); + todo_wine ok(!ref || broken(ref >= 0), "Got unexpected ref %lu.\n", ref); + +skip_action: + hr = ISpeechContinuousRecognitionSession_remove_ResultGenerated(session, token); + ok(hr == S_OK, "ISpeechContinuousRecognitionSession_remove_ResultGenerated failed, hr %#lx.\n", hr); + + ref = ISpeechContinuousRecognitionSession_Release(session); + ok(ref == 1, "Got unexpected ref %lu.\n", ref); + + ref = ISpeechRecognizer2_Release(recognizer2); + ok(ref == 2, "Got unexpected ref %lu.\n", ref); + + ref = ISpeechRecognizer_Release(recognizer); + ok(ref == 1, "Got unexpected ref %lu.\n", ref); + + ref = IInspectable_Release(inspectable); + ok(!ref, "Got unexpected ref %lu.\n", ref); + +done: + for (i = 0; i < ARRAY_SIZE(commands); i++) + WindowsDeleteString(commands[i]); + + RoUninitialize(); +} + START_TEST(speech) { test_ActivationFactory(); @@ -1356,4 +1714,5 @@ START_TEST(speech) test_VoiceInformation(); test_SpeechRecognizer(); test_SpeechRecognitionListConstraint(); + test_Recognition(); }