From: Bernhard Kölbl <bkoelbl@codeweavers.com> The vector view might be uninitialized by the time ISpeechSynthesizer_put_Voice is called, so get it via the "official" way through IInstalledVoicesStatic. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=59694 --- dlls/windows.media.speech/synthesizer.c | 17 +++++++++++++---- dlls/windows.media.speech/tests/speech.c | 20 +++++++++++++++++--- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/dlls/windows.media.speech/synthesizer.c b/dlls/windows.media.speech/synthesizer.c index 587463c0444..d9fec2c651b 100644 --- a/dlls/windows.media.speech/synthesizer.c +++ b/dlls/windows.media.speech/synthesizer.c @@ -1472,19 +1472,27 @@ static HRESULT WINAPI synthesizer_SynthesizeSsmlToStreamAsync( ISpeechSynthesize static HRESULT WINAPI synthesizer_put_Voice( ISpeechSynthesizer *iface, IVoiceInformation *value ) { struct synthesizer *impl = impl_from_ISpeechSynthesizer(iface); + IVectorView_VoiceInformation *all_voices_vector; + IInstalledVoicesStatic *installed_voices; IVoiceInformation *voice; - HSTRING id, id2; + HSTRING id = NULL, id2; HRESULT hr; INT32 cmp, idx; TRACE("iface %p, value %p semi-stub.\n", iface, value); - if (FAILED(hr = IVoiceInformation_get_Id(value, &id))) - return hr; + if (SUCCEEDED(hr = IActivationFactory_QueryInterface(synthesizer_factory, &IID_IInstalledVoicesStatic, (void **)&installed_voices))) + { + hr = IInstalledVoicesStatic_get_AllVoices(installed_voices, &all_voices_vector); + IInstalledVoicesStatic_Release(installed_voices); + } + if (FAILED(hr)) return hr; + + hr = IVoiceInformation_get_Id(value, &id); for (idx = 0; ; idx++) { - if (SUCCEEDED(hr = IVectorView_VoiceInformation_GetAt(&all_voices.IVectorView_VoiceInformation_iface, idx, &voice))) + if (SUCCEEDED(hr = IVectorView_VoiceInformation_GetAt(all_voices_vector, idx, &voice))) { if (SUCCEEDED(hr = IVoiceInformation_get_Id(voice, &id2))) { @@ -1496,6 +1504,7 @@ static HRESULT WINAPI synthesizer_put_Voice( ISpeechSynthesizer *iface, IVoiceIn if (FAILED(hr) || cmp == 0) break; } WindowsDeleteString(id); + IVectorView_VoiceInformation_Release(all_voices_vector); if (SUCCEEDED(hr)) { diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c index fbd2873330c..5fff0728832 100644 --- a/dlls/windows.media.speech/tests/speech.c +++ b/dlls/windows.media.speech/tests/speech.c @@ -1012,9 +1012,6 @@ static void test_SpeechSynthesizer(void) ref = IVoiceInformation_Release(voice); ok(ref == 0, "Got unexpected ref %lu.\n", ref); - ref = IVectorView_VoiceInformation_Release(voices); - ok(!ref, "Got unexpected ref %lu.\n", ref); - skip_voices: IInstalledVoicesStatic_Release(voices_static); IAgileObject_Release(agile_object); @@ -1051,6 +1048,23 @@ skip_voices: hr = WindowsDeleteString(default_voice_id); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + if (voices) + { + voice = (IVoiceInformation *)0xdeadbeef; + hr = IVectorView_VoiceInformation_GetAt(voices, 0, &voice); + ok(hr == S_OK, "IVectorView_VoiceInformation_GetAt failed, hr %#lx\n", hr); + ok(voice != (IVoiceInformation *)0xdeadbeef, "IVectorView_VoiceInformation_GetAt returned %p\n", voice); + + ref = IVectorView_VoiceInformation_Release(voices); + ok(!ref, "Got unexpected ref %lu.\n", ref); + + hr = ISpeechSynthesizer_put_Voice(synthesizer, voice); + ok(hr == S_OK, "ISpeechSynthesizer_put_Voice failed, hr %#lx\n", hr); + + ref = IVoiceInformation_Release(voice); + ok(ref == 1, "Got unexpected ref %lu.\n", ref); + } + /* Test SynthesizeTextToStreamAsync */ hr = WindowsCreateString(simple_synth_text, wcslen(simple_synth_text), &str); ok(hr == S_OK, "WindowsCreateString failed, hr %#lx\n", hr); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10773