Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/windows.media.speech/main.c | 26 +-------------- dlls/windows.media.speech/private.h | 52 +++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 25 deletions(-) create mode 100644 dlls/windows.media.speech/private.h
diff --git a/dlls/windows.media.speech/main.c b/dlls/windows.media.speech/main.c index d14d06773f7..f81c1bbfedd 100644 --- a/dlls/windows.media.speech/main.c +++ b/dlls/windows.media.speech/main.c @@ -17,35 +17,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
-#include <stdarg.h> - -#define COBJMACROS -#include "windef.h" -#include "winbase.h" -#include "winstring.h" -#include "wine/debug.h" -#include "objbase.h" - #include "initguid.h" -#include "activation.h" - -#define WIDL_using_Windows_Foundation -#define WIDL_using_Windows_Foundation_Collections -#include "windows.foundation.h" -#define WIDL_using_Windows_Media_SpeechSynthesis -#include "windows.media.speechsynthesis.h" +#include "private.h"
WINE_DEFAULT_DEBUG_CHANNEL(speech);
-static const char *debugstr_hstring(HSTRING hstr) -{ - const WCHAR *str; - UINT32 len; - if (hstr && !((ULONG_PTR)hstr >> 16)) return "(invalid)"; - str = WindowsGetStringRawBuffer(hstr, &len); - return wine_dbgstr_wn(str, len); -} - struct voice_information_vector { IVectorView_VoiceInformation IVectorView_VoiceInformation_iface; diff --git a/dlls/windows.media.speech/private.h b/dlls/windows.media.speech/private.h new file mode 100644 index 00000000000..8162ca45094 --- /dev/null +++ b/dlls/windows.media.speech/private.h @@ -0,0 +1,52 @@ +/* WinRT Windows.Media.Speech private header + * + * Copyright 2022 Bernhard Kölbl + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_WINDOWS_MEDIA_SPEECH_PRIVATE_H +#define __WINE_WINDOWS_MEDIA_SPEECH_PRIVATE_H + +#include <stdarg.h> + +#define COBJMACROS +#include "windef.h" +#include "winbase.h" +#include "winstring.h" +#include "objbase.h" + +#include "activation.h" + +#define WIDL_using_Windows_Foundation +#define WIDL_using_Windows_Foundation_Collections +#include "windows.foundation.h" +#define WIDL_using_Windows_Globalization +#include "windows.globalization.h" +#define WIDL_using_Windows_Media_SpeechSynthesis +#include "windows.media.speechsynthesis.h" + +#include "wine/debug.h" + +static inline const char *debugstr_hstring(HSTRING hstr) +{ + const WCHAR *str; + UINT32 len; + if (hstr && !((ULONG_PTR)hstr >> 16)) return "(invalid)"; + str = WindowsGetStringRawBuffer(hstr, &len); + return wine_dbgstr_wn(str, len); +} + +#endif
Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/windows.media.speech/Makefile.in | 3 +- dlls/windows.media.speech/main.c | 544 +--------------------- dlls/windows.media.speech/private.h | 8 + dlls/windows.media.speech/synthesizer.c | 569 ++++++++++++++++++++++++ 4 files changed, 580 insertions(+), 544 deletions(-) create mode 100644 dlls/windows.media.speech/synthesizer.c
diff --git a/dlls/windows.media.speech/Makefile.in b/dlls/windows.media.speech/Makefile.in index 9fbff8e132f..74eb7b93fea 100644 --- a/dlls/windows.media.speech/Makefile.in +++ b/dlls/windows.media.speech/Makefile.in @@ -2,6 +2,7 @@ MODULE = windows.media.speech.dll IMPORTS = combase uuid
C_SRCS = \ - main.c + main.c \ + synthesizer.c
IDL_SRCS = classes.idl diff --git a/dlls/windows.media.speech/main.c b/dlls/windows.media.speech/main.c index f81c1bbfedd..d11a0e6c6e1 100644 --- a/dlls/windows.media.speech/main.c +++ b/dlls/windows.media.speech/main.c @@ -22,548 +22,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(speech);
-struct voice_information_vector -{ - IVectorView_VoiceInformation IVectorView_VoiceInformation_iface; - LONG ref; -}; - -static inline struct voice_information_vector *impl_from_IVectorView_VoiceInformation(IVectorView_VoiceInformation *iface) -{ - return CONTAINING_RECORD(iface, struct voice_information_vector, IVectorView_VoiceInformation_iface); -} - -static HRESULT STDMETHODCALLTYPE vector_view_voice_information_QueryInterface( - IVectorView_VoiceInformation *iface, REFIID iid, void **out) -{ - TRACE("iface %p, iid %s, out %p stub!\n", iface, debugstr_guid(iid), out); - - if (IsEqualGUID(iid, &IID_IUnknown) || - IsEqualGUID(iid, &IID_IInspectable) || - IsEqualGUID(iid, &IID_IVectorView_VoiceInformation)) - { - IUnknown_AddRef(iface); - *out = iface; - return S_OK; - } - - WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); - *out = NULL; - return E_NOINTERFACE; -} - -static ULONG STDMETHODCALLTYPE vector_view_voice_information_AddRef( - IVectorView_VoiceInformation *iface) -{ - struct voice_information_vector *impl = impl_from_IVectorView_VoiceInformation(iface); - ULONG ref = InterlockedIncrement(&impl->ref); - TRACE("iface %p, ref %lu.\n", iface, ref); - return ref; -} - -static ULONG STDMETHODCALLTYPE vector_view_voice_information_Release( - IVectorView_VoiceInformation *iface) -{ - struct voice_information_vector *impl = impl_from_IVectorView_VoiceInformation(iface); - ULONG ref = InterlockedDecrement(&impl->ref); - TRACE("iface %p, ref %lu.\n", iface, ref); - return ref; -} - -static HRESULT STDMETHODCALLTYPE vector_view_voice_information_GetIids( - IVectorView_VoiceInformation *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 STDMETHODCALLTYPE vector_view_voice_information_GetRuntimeClassName( - IVectorView_VoiceInformation *iface, HSTRING *class_name) -{ - FIXME("iface %p, class_name %p stub!\n", iface, class_name); - return E_NOTIMPL; -} - -static HRESULT STDMETHODCALLTYPE vector_view_voice_information_GetTrustLevel( - IVectorView_VoiceInformation *iface, TrustLevel *trust_level) -{ - FIXME("iface %p, trust_level %p stub!\n", iface, trust_level); - return E_NOTIMPL; -} - -static HRESULT STDMETHODCALLTYPE vector_view_voice_information_GetAt( - IVectorView_VoiceInformation *iface, UINT32 index, IVoiceInformation **value) -{ - FIXME("iface %p, index %#x, value %p stub!\n", iface, index, value); - *value = NULL; - return E_BOUNDS; -} - -static HRESULT STDMETHODCALLTYPE vector_view_voice_information_get_Size( - IVectorView_VoiceInformation *iface, UINT32 *value) -{ - FIXME("iface %p, value %p stub!\n", iface, value); - *value = 0; - return S_OK; -} - -static HRESULT STDMETHODCALLTYPE vector_view_voice_information_IndexOf( - IVectorView_VoiceInformation *iface, IVoiceInformation *element, UINT32 *index, BOOLEAN *found) -{ - FIXME("iface %p, element %p, index %p, found %p stub!\n", iface, element, index, found); - *index = 0; - *found = FALSE; - return S_OK; -} - -static HRESULT STDMETHODCALLTYPE vector_view_voice_information_GetMany( - IVectorView_VoiceInformation *iface, UINT32 start_index, - UINT32 items_size, IVoiceInformation **items, UINT *value) -{ - FIXME("iface %p, start_index %#x, items %p, value %p stub!\n", iface, start_index, items, value); - *value = 0; - return S_OK; -} - -static const struct IVectorView_VoiceInformationVtbl vector_view_voice_information_vtbl = -{ - vector_view_voice_information_QueryInterface, - vector_view_voice_information_AddRef, - vector_view_voice_information_Release, - /* IInspectable methods */ - vector_view_voice_information_GetIids, - vector_view_voice_information_GetRuntimeClassName, - vector_view_voice_information_GetTrustLevel, - /* IVectorView<VoiceInformation> methods */ - vector_view_voice_information_GetAt, - vector_view_voice_information_get_Size, - vector_view_voice_information_IndexOf, - vector_view_voice_information_GetMany, -}; - -static struct voice_information_vector all_voices = -{ - {&vector_view_voice_information_vtbl}, - 0 -}; - -struct speech_synthesizer -{ - ISpeechSynthesizer ISpeechSynthesizer_iface; - IClosable IClosable_iface; - LONG ref; -}; - -static inline struct speech_synthesizer *impl_from_ISpeechSynthesizer(ISpeechSynthesizer *iface) -{ - return CONTAINING_RECORD(iface, struct speech_synthesizer, ISpeechSynthesizer_iface); -} - -static inline struct speech_synthesizer *impl_from_IClosable(IClosable *iface) -{ - return CONTAINING_RECORD(iface, struct speech_synthesizer, IClosable_iface); -} - -static HRESULT STDMETHODCALLTYPE speech_synthesizer_QueryInterface( - ISpeechSynthesizer *iface, REFIID iid, void **out) -{ - struct speech_synthesizer *impl = impl_from_ISpeechSynthesizer(iface); - - TRACE("iface %p, iid %s, out %p stub!\n", iface, debugstr_guid(iid), out); - - if (IsEqualGUID(iid, &IID_IUnknown) || - IsEqualGUID(iid, &IID_IInspectable) || - IsEqualGUID(iid, &IID_ISpeechSynthesizer)) - { - IUnknown_AddRef(iface); - *out = iface; - return S_OK; - } - - if (IsEqualGUID(iid, &IID_IClosable)) - { - IUnknown_AddRef(iface); - *out = &impl->IClosable_iface; - return S_OK; - } - - FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); - *out = NULL; - return E_NOINTERFACE; -} - -static ULONG STDMETHODCALLTYPE speech_synthesizer_AddRef( - ISpeechSynthesizer *iface) -{ - struct speech_synthesizer *impl = impl_from_ISpeechSynthesizer(iface); - ULONG ref = InterlockedIncrement(&impl->ref); - - TRACE("iface %p, ref %lu.\n", iface, ref); - - return ref; -} - -static ULONG STDMETHODCALLTYPE speech_synthesizer_Release( - ISpeechSynthesizer *iface) -{ - struct speech_synthesizer *impl = impl_from_ISpeechSynthesizer(iface); - ULONG ref = InterlockedDecrement(&impl->ref); - - TRACE("iface %p, ref %lu.\n", iface, ref); - - if (!ref) - free(impl); - - return ref; -} - -static HRESULT STDMETHODCALLTYPE speech_synthesizer_GetIids( - ISpeechSynthesizer *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 STDMETHODCALLTYPE speech_synthesizer_GetRuntimeClassName( - ISpeechSynthesizer *iface, HSTRING *class_name) -{ - FIXME("iface %p, class_name %p stub.\n", iface, class_name); - - return E_NOTIMPL; -} - -static HRESULT STDMETHODCALLTYPE speech_synthesizer_GetTrustLevel( - ISpeechSynthesizer *iface, TrustLevel *trust_level) -{ - FIXME("iface %p, trust_level %p stub.\n", iface, trust_level); - - return E_NOTIMPL; -} - -static HRESULT STDMETHODCALLTYPE speech_synthesizer_SynthesizeTextToStreamAsync(ISpeechSynthesizer *iface, - HSTRING text, IAsyncOperation_SpeechSynthesisStream **operation) -{ - FIXME("iface %p, text %p, operation %p stub.\n", iface, text, operation); - - return E_NOTIMPL; -} - -static HRESULT STDMETHODCALLTYPE speech_synthesizer_SynthesizeSsmlToStreamAsync(ISpeechSynthesizer *iface, - HSTRING ssml, IAsyncOperation_SpeechSynthesisStream **operation) -{ - FIXME("iface %p, text %p, operation %p stub.\n", iface, ssml, operation); - - return E_NOTIMPL; -} - -static HRESULT STDMETHODCALLTYPE speech_synthesizer_put_Voice(ISpeechSynthesizer *iface, IVoiceInformation *value) -{ - FIXME("iface %p, value %p stub.\n", iface, value); - - return E_NOTIMPL; -} - -static HRESULT STDMETHODCALLTYPE speech_synthesizer_get_Voice(ISpeechSynthesizer *iface, IVoiceInformation **value) -{ - FIXME("iface %p, value %p stub.\n", iface, value); - - return E_NOTIMPL; -} - -static const struct ISpeechSynthesizerVtbl speech_synthesizer_vtbl = -{ - /* IUnknown methods */ - speech_synthesizer_QueryInterface, - speech_synthesizer_AddRef, - speech_synthesizer_Release, - /* IInspectable methods */ - speech_synthesizer_GetIids, - speech_synthesizer_GetRuntimeClassName, - speech_synthesizer_GetTrustLevel, - /* ISpeechSynthesizer methods */ - speech_synthesizer_SynthesizeTextToStreamAsync, - speech_synthesizer_SynthesizeSsmlToStreamAsync, - speech_synthesizer_put_Voice, - speech_synthesizer_get_Voice, -}; - -static HRESULT STDMETHODCALLTYPE closable_QueryInterface( - IClosable *iface, REFIID iid, void **out) -{ - struct speech_synthesizer *impl = impl_from_IClosable(iface); - - return speech_synthesizer_QueryInterface(&impl->ISpeechSynthesizer_iface, iid, out); -} - -static ULONG STDMETHODCALLTYPE closable_AddRef( - IClosable *iface) -{ - struct speech_synthesizer *impl = impl_from_IClosable(iface); - ULONG ref = InterlockedIncrement(&impl->ref); - - TRACE("iface %p, ref %lu.\n", iface, ref); - - return ref; -} - -static ULONG STDMETHODCALLTYPE closable_Release( - IClosable *iface) -{ - struct speech_synthesizer *impl = impl_from_IClosable(iface); - ULONG ref = InterlockedDecrement(&impl->ref); - - TRACE("iface %p, ref %lu.\n", iface, ref); - - if (!ref) - free(impl); - - return ref; -} - -static HRESULT STDMETHODCALLTYPE closable_GetIids( - IClosable *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 STDMETHODCALLTYPE closable_GetRuntimeClassName( - IClosable *iface, HSTRING *class_name) -{ - FIXME("iface %p, class_name %p stub.\n", iface, class_name); - - return E_NOTIMPL; -} - -static HRESULT STDMETHODCALLTYPE closable_GetTrustLevel( - IClosable *iface, TrustLevel *trust_level) -{ - FIXME("iface %p, trust_level %p stub.\n", iface, trust_level); - - return E_NOTIMPL; -} - -static HRESULT STDMETHODCALLTYPE closable_Close( - IClosable *iface) -{ - FIXME("iface %p stub.\n", iface); - - return E_NOTIMPL; -} - -static const struct IClosableVtbl closable_vtbl = -{ - /* IUnknown methods */ - closable_QueryInterface, - closable_AddRef, - closable_Release, - /* IInspectable methods */ - closable_GetIids, - closable_GetRuntimeClassName, - closable_GetTrustLevel, - /* IClosable methods */ - closable_Close, -}; - -struct windows_media_speech -{ - IActivationFactory IActivationFactory_iface; - IInstalledVoicesStatic IInstalledVoicesStatic_iface; - LONG ref; -}; - -static inline struct windows_media_speech *impl_from_IActivationFactory(IActivationFactory *iface) -{ - return CONTAINING_RECORD(iface, struct windows_media_speech, IActivationFactory_iface); -} - -static inline struct windows_media_speech *impl_from_IInstalledVoicesStatic(IInstalledVoicesStatic *iface) -{ - return CONTAINING_RECORD(iface, struct windows_media_speech, IInstalledVoicesStatic_iface); -} - -static HRESULT STDMETHODCALLTYPE windows_media_speech_QueryInterface( - IActivationFactory *iface, REFIID iid, void **out) -{ - struct windows_media_speech *impl = impl_from_IActivationFactory(iface); - - TRACE("iface %p, iid %s, out %p stub!\n", iface, debugstr_guid(iid), out); - - if (IsEqualGUID(iid, &IID_IUnknown) || - IsEqualGUID(iid, &IID_IInspectable) || - IsEqualGUID(iid, &IID_IAgileObject) || - IsEqualGUID(iid, &IID_IActivationFactory)) - { - IUnknown_AddRef(iface); - *out = iface; - return S_OK; - } - - if (IsEqualGUID(iid, &IID_IInstalledVoicesStatic)) - { - IUnknown_AddRef(iface); - *out = &impl->IInstalledVoicesStatic_iface; - return S_OK; - } - - FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); - *out = NULL; - return E_NOINTERFACE; -} - -static ULONG STDMETHODCALLTYPE windows_media_speech_AddRef( - IActivationFactory *iface) -{ - struct windows_media_speech *impl = impl_from_IActivationFactory(iface); - ULONG ref = InterlockedIncrement(&impl->ref); - TRACE("iface %p, ref %lu.\n", iface, ref); - return ref; -} - -static ULONG STDMETHODCALLTYPE windows_media_speech_Release( - IActivationFactory *iface) -{ - struct windows_media_speech *impl = impl_from_IActivationFactory(iface); - ULONG ref = InterlockedDecrement(&impl->ref); - TRACE("iface %p, ref %lu.\n", iface, ref); - return ref; -} - -static HRESULT STDMETHODCALLTYPE windows_media_speech_GetIids( - IActivationFactory *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 STDMETHODCALLTYPE windows_media_speech_GetRuntimeClassName( - IActivationFactory *iface, HSTRING *class_name) -{ - FIXME("iface %p, class_name %p stub!\n", iface, class_name); - return E_NOTIMPL; -} - -static HRESULT STDMETHODCALLTYPE windows_media_speech_GetTrustLevel( - IActivationFactory *iface, TrustLevel *trust_level) -{ - FIXME("iface %p, trust_level %p stub!\n", iface, trust_level); - return E_NOTIMPL; -} - -static HRESULT STDMETHODCALLTYPE windows_media_speech_ActivateInstance( - IActivationFactory *iface, IInspectable **instance) -{ - struct speech_synthesizer *obj; - - TRACE("iface %p, instance %p.\n", iface, instance); - - if (!(obj = calloc(1, sizeof(*obj)))) - { - *instance = NULL; - return E_OUTOFMEMORY; - } - - obj->ISpeechSynthesizer_iface.lpVtbl = &speech_synthesizer_vtbl; - obj->IClosable_iface.lpVtbl = &closable_vtbl; - obj->ref = 1; - *instance = (IInspectable *)&obj->ISpeechSynthesizer_iface; - return S_OK; -} - -static const struct IActivationFactoryVtbl activation_factory_vtbl = -{ - windows_media_speech_QueryInterface, - windows_media_speech_AddRef, - windows_media_speech_Release, - /* IInspectable methods */ - windows_media_speech_GetIids, - windows_media_speech_GetRuntimeClassName, - windows_media_speech_GetTrustLevel, - /* IActivationFactory methods */ - windows_media_speech_ActivateInstance, -}; - -static HRESULT STDMETHODCALLTYPE installed_voices_static_QueryInterface( - IInstalledVoicesStatic *iface, REFIID iid, void **out) -{ - struct windows_media_speech *impl = impl_from_IInstalledVoicesStatic(iface); - return windows_media_speech_QueryInterface(&impl->IActivationFactory_iface, iid, out); -} - -static ULONG STDMETHODCALLTYPE installed_voices_static_AddRef( - IInstalledVoicesStatic *iface) -{ - struct windows_media_speech *impl = impl_from_IInstalledVoicesStatic(iface); - return windows_media_speech_AddRef(&impl->IActivationFactory_iface); -} - -static ULONG STDMETHODCALLTYPE installed_voices_static_Release( - IInstalledVoicesStatic *iface) -{ - struct windows_media_speech *impl = impl_from_IInstalledVoicesStatic(iface); - return windows_media_speech_Release(&impl->IActivationFactory_iface); -} - -static HRESULT STDMETHODCALLTYPE installed_voices_static_GetIids( - IInstalledVoicesStatic *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 STDMETHODCALLTYPE installed_voices_static_GetRuntimeClassName( - IInstalledVoicesStatic *iface, HSTRING *class_name) -{ - FIXME("iface %p, class_name %p stub!\n", iface, class_name); - return E_NOTIMPL; -} - -static HRESULT STDMETHODCALLTYPE installed_voices_static_GetTrustLevel( - IInstalledVoicesStatic *iface, TrustLevel *trust_level) -{ - FIXME("iface %p, trust_level %p stub!\n", iface, trust_level); - return E_NOTIMPL; -} - -static HRESULT STDMETHODCALLTYPE installed_voices_static_get_AllVoices( - IInstalledVoicesStatic *iface, IVectorView_VoiceInformation **value) -{ - TRACE("iface %p, value %p.\n", iface, value); - *value = &all_voices.IVectorView_VoiceInformation_iface; - IVectorView_VoiceInformation_AddRef(*value); - return S_OK; -} - -static HRESULT STDMETHODCALLTYPE installed_voices_static_get_DefaultVoice( - IInstalledVoicesStatic *iface, IVoiceInformation **value) -{ - FIXME("iface %p, value %p stub!\n", iface, value); - return E_NOTIMPL; -} - -static const struct IInstalledVoicesStaticVtbl installed_voices_static_vtbl = -{ - installed_voices_static_QueryInterface, - installed_voices_static_AddRef, - installed_voices_static_Release, - /* IInspectable methods */ - installed_voices_static_GetIids, - installed_voices_static_GetRuntimeClassName, - installed_voices_static_GetTrustLevel, - /* IInstalledVoicesStatic methods */ - installed_voices_static_get_AllVoices, - installed_voices_static_get_DefaultVoice, -}; - -static struct windows_media_speech windows_media_speech = -{ - {&activation_factory_vtbl}, - {&installed_voices_static_vtbl}, - 1 -}; - HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void **out) { FIXME("clsid %s, riid %s, out %p stub!\n", debugstr_guid(clsid), debugstr_guid(riid), out); @@ -580,7 +38,7 @@ HRESULT WINAPI DllGetActivationFactory(HSTRING classid, IActivationFactory **fac return CLASS_E_CLASSNOTAVAILABLE; }
- *factory = &windows_media_speech.IActivationFactory_iface; + speech_synthesizer_get_activation_factory(factory); IUnknown_AddRef(*factory); return S_OK; } diff --git a/dlls/windows.media.speech/private.h b/dlls/windows.media.speech/private.h index 8162ca45094..df464c369bf 100644 --- a/dlls/windows.media.speech/private.h +++ b/dlls/windows.media.speech/private.h @@ -49,4 +49,12 @@ static inline const char *debugstr_hstring(HSTRING hstr) return wine_dbgstr_wn(str, len); }
+/* + * + * Windows.Media.SpeechSynthesis + * + */ + +void STDMETHODCALLTYPE speech_synthesizer_get_activation_factory(IActivationFactory **factory) DECLSPEC_HIDDEN; + #endif diff --git a/dlls/windows.media.speech/synthesizer.c b/dlls/windows.media.speech/synthesizer.c new file mode 100644 index 00000000000..b2719e46f8b --- /dev/null +++ b/dlls/windows.media.speech/synthesizer.c @@ -0,0 +1,569 @@ +/* WinRT Windows.Media.Speech implementation + * + * Copyright 2021 Rémi Bernon for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(speech); + +struct voice_information_vector +{ + IVectorView_VoiceInformation IVectorView_VoiceInformation_iface; + LONG ref; +}; + +static inline struct voice_information_vector *impl_from_IVectorView_VoiceInformation(IVectorView_VoiceInformation *iface) +{ + return CONTAINING_RECORD(iface, struct voice_information_vector, IVectorView_VoiceInformation_iface); +} + +static HRESULT STDMETHODCALLTYPE vector_view_voice_information_QueryInterface( + IVectorView_VoiceInformation *iface, REFIID iid, void **out) +{ + TRACE("iface %p, iid %s, out %p stub!\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown) || + IsEqualGUID(iid, &IID_IInspectable) || + IsEqualGUID(iid, &IID_IVectorView_VoiceInformation)) + { + IUnknown_AddRef(iface); + *out = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE vector_view_voice_information_AddRef( + IVectorView_VoiceInformation *iface) +{ + struct voice_information_vector *impl = impl_from_IVectorView_VoiceInformation(iface); + ULONG ref = InterlockedIncrement(&impl->ref); + TRACE("iface %p, ref %lu.\n", iface, ref); + return ref; +} + +static ULONG STDMETHODCALLTYPE vector_view_voice_information_Release( + IVectorView_VoiceInformation *iface) +{ + struct voice_information_vector *impl = impl_from_IVectorView_VoiceInformation(iface); + ULONG ref = InterlockedDecrement(&impl->ref); + TRACE("iface %p, ref %lu.\n", iface, ref); + return ref; +} + +static HRESULT STDMETHODCALLTYPE vector_view_voice_information_GetIids( + IVectorView_VoiceInformation *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 STDMETHODCALLTYPE vector_view_voice_information_GetRuntimeClassName( + IVectorView_VoiceInformation *iface, HSTRING *class_name) +{ + FIXME("iface %p, class_name %p stub!\n", iface, class_name); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE vector_view_voice_information_GetTrustLevel( + IVectorView_VoiceInformation *iface, TrustLevel *trust_level) +{ + FIXME("iface %p, trust_level %p stub!\n", iface, trust_level); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE vector_view_voice_information_GetAt( + IVectorView_VoiceInformation *iface, UINT32 index, IVoiceInformation **value) +{ + FIXME("iface %p, index %#x, value %p stub!\n", iface, index, value); + *value = NULL; + return E_BOUNDS; +} + +static HRESULT STDMETHODCALLTYPE vector_view_voice_information_get_Size( + IVectorView_VoiceInformation *iface, UINT32 *value) +{ + FIXME("iface %p, value %p stub!\n", iface, value); + *value = 0; + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE vector_view_voice_information_IndexOf( + IVectorView_VoiceInformation *iface, IVoiceInformation *element, UINT32 *index, BOOLEAN *found) +{ + FIXME("iface %p, element %p, index %p, found %p stub!\n", iface, element, index, found); + *index = 0; + *found = FALSE; + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE vector_view_voice_information_GetMany( + IVectorView_VoiceInformation *iface, UINT32 start_index, + UINT32 items_size, IVoiceInformation **items, UINT *value) +{ + FIXME("iface %p, start_index %#x, items %p, value %p stub!\n", iface, start_index, items, value); + *value = 0; + return S_OK; +} + +static const struct IVectorView_VoiceInformationVtbl vector_view_voice_information_vtbl = +{ + vector_view_voice_information_QueryInterface, + vector_view_voice_information_AddRef, + vector_view_voice_information_Release, + /* IInspectable methods */ + vector_view_voice_information_GetIids, + vector_view_voice_information_GetRuntimeClassName, + vector_view_voice_information_GetTrustLevel, + /* IVectorView<VoiceInformation> methods */ + vector_view_voice_information_GetAt, + vector_view_voice_information_get_Size, + vector_view_voice_information_IndexOf, + vector_view_voice_information_GetMany, +}; + +static struct voice_information_vector all_voices = +{ + {&vector_view_voice_information_vtbl}, + 0 +}; + +struct speech_synthesizer +{ + ISpeechSynthesizer ISpeechSynthesizer_iface; + IClosable IClosable_iface; + LONG ref; +}; + +static inline struct speech_synthesizer *impl_from_ISpeechSynthesizer(ISpeechSynthesizer *iface) +{ + return CONTAINING_RECORD(iface, struct speech_synthesizer, ISpeechSynthesizer_iface); +} + +static inline struct speech_synthesizer *impl_from_IClosable(IClosable *iface) +{ + return CONTAINING_RECORD(iface, struct speech_synthesizer, IClosable_iface); +} + +static HRESULT STDMETHODCALLTYPE speech_synthesizer_QueryInterface( + ISpeechSynthesizer *iface, REFIID iid, void **out) +{ + struct speech_synthesizer *impl = impl_from_ISpeechSynthesizer(iface); + + TRACE("iface %p, iid %s, out %p stub!\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown) || + IsEqualGUID(iid, &IID_IInspectable) || + IsEqualGUID(iid, &IID_ISpeechSynthesizer)) + { + IUnknown_AddRef(iface); + *out = iface; + return S_OK; + } + + if (IsEqualGUID(iid, &IID_IClosable)) + { + IUnknown_AddRef(iface); + *out = &impl->IClosable_iface; + return S_OK; + } + + FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE speech_synthesizer_AddRef( + ISpeechSynthesizer *iface) +{ + struct speech_synthesizer *impl = impl_from_ISpeechSynthesizer(iface); + ULONG ref = InterlockedIncrement(&impl->ref); + + TRACE("iface %p, ref %lu.\n", iface, ref); + + return ref; +} + +static ULONG STDMETHODCALLTYPE speech_synthesizer_Release( + ISpeechSynthesizer *iface) +{ + struct speech_synthesizer *impl = impl_from_ISpeechSynthesizer(iface); + ULONG ref = InterlockedDecrement(&impl->ref); + + TRACE("iface %p, ref %lu.\n", iface, ref); + + if (!ref) + free(impl); + + return ref; +} + +static HRESULT STDMETHODCALLTYPE speech_synthesizer_GetIids( + ISpeechSynthesizer *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 STDMETHODCALLTYPE speech_synthesizer_GetRuntimeClassName( + ISpeechSynthesizer *iface, HSTRING *class_name) +{ + FIXME("iface %p, class_name %p stub.\n", iface, class_name); + + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE speech_synthesizer_GetTrustLevel( + ISpeechSynthesizer *iface, TrustLevel *trust_level) +{ + FIXME("iface %p, trust_level %p stub.\n", iface, trust_level); + + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE speech_synthesizer_SynthesizeTextToStreamAsync(ISpeechSynthesizer *iface, + HSTRING text, IAsyncOperation_SpeechSynthesisStream **operation) +{ + FIXME("iface %p, text %p, operation %p stub.\n", iface, text, operation); + + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE speech_synthesizer_SynthesizeSsmlToStreamAsync(ISpeechSynthesizer *iface, + HSTRING ssml, IAsyncOperation_SpeechSynthesisStream **operation) +{ + FIXME("iface %p, text %p, operation %p stub.\n", iface, ssml, operation); + + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE speech_synthesizer_put_Voice(ISpeechSynthesizer *iface, IVoiceInformation *value) +{ + FIXME("iface %p, value %p stub.\n", iface, value); + + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE speech_synthesizer_get_Voice(ISpeechSynthesizer *iface, IVoiceInformation **value) +{ + FIXME("iface %p, value %p stub.\n", iface, value); + + return E_NOTIMPL; +} + +static const struct ISpeechSynthesizerVtbl speech_synthesizer_vtbl = +{ + /* IUnknown methods */ + speech_synthesizer_QueryInterface, + speech_synthesizer_AddRef, + speech_synthesizer_Release, + /* IInspectable methods */ + speech_synthesizer_GetIids, + speech_synthesizer_GetRuntimeClassName, + speech_synthesizer_GetTrustLevel, + /* ISpeechSynthesizer methods */ + speech_synthesizer_SynthesizeTextToStreamAsync, + speech_synthesizer_SynthesizeSsmlToStreamAsync, + speech_synthesizer_put_Voice, + speech_synthesizer_get_Voice, +}; + +static HRESULT STDMETHODCALLTYPE closable_QueryInterface( + IClosable *iface, REFIID iid, void **out) +{ + struct speech_synthesizer *impl = impl_from_IClosable(iface); + + return speech_synthesizer_QueryInterface(&impl->ISpeechSynthesizer_iface, iid, out); +} + +static ULONG STDMETHODCALLTYPE closable_AddRef( + IClosable *iface) +{ + struct speech_synthesizer *impl = impl_from_IClosable(iface); + ULONG ref = InterlockedIncrement(&impl->ref); + + TRACE("iface %p, ref %lu.\n", iface, ref); + + return ref; +} + +static ULONG STDMETHODCALLTYPE closable_Release( + IClosable *iface) +{ + struct speech_synthesizer *impl = impl_from_IClosable(iface); + ULONG ref = InterlockedDecrement(&impl->ref); + + TRACE("iface %p, ref %lu.\n", iface, ref); + + if (!ref) + free(impl); + + return ref; +} + +static HRESULT STDMETHODCALLTYPE closable_GetIids( + IClosable *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 STDMETHODCALLTYPE closable_GetRuntimeClassName( + IClosable *iface, HSTRING *class_name) +{ + FIXME("iface %p, class_name %p stub.\n", iface, class_name); + + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE closable_GetTrustLevel( + IClosable *iface, TrustLevel *trust_level) +{ + FIXME("iface %p, trust_level %p stub.\n", iface, trust_level); + + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE closable_Close( + IClosable *iface) +{ + FIXME("iface %p stub.\n", iface); + + return E_NOTIMPL; +} + +static const struct IClosableVtbl closable_vtbl = +{ + /* IUnknown methods */ + closable_QueryInterface, + closable_AddRef, + closable_Release, + /* IInspectable methods */ + closable_GetIids, + closable_GetRuntimeClassName, + closable_GetTrustLevel, + /* IClosable methods */ + closable_Close, +}; + +struct windows_media_speech +{ + IActivationFactory IActivationFactory_iface; + IInstalledVoicesStatic IInstalledVoicesStatic_iface; + LONG ref; +}; + +static inline struct windows_media_speech *impl_from_IActivationFactory(IActivationFactory *iface) +{ + return CONTAINING_RECORD(iface, struct windows_media_speech, IActivationFactory_iface); +} + +static inline struct windows_media_speech *impl_from_IInstalledVoicesStatic(IInstalledVoicesStatic *iface) +{ + return CONTAINING_RECORD(iface, struct windows_media_speech, IInstalledVoicesStatic_iface); +} + +static HRESULT STDMETHODCALLTYPE windows_media_speech_QueryInterface( + IActivationFactory *iface, REFIID iid, void **out) +{ + struct windows_media_speech *impl = impl_from_IActivationFactory(iface); + + TRACE("iface %p, iid %s, out %p stub!\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown) || + IsEqualGUID(iid, &IID_IInspectable) || + IsEqualGUID(iid, &IID_IAgileObject) || + IsEqualGUID(iid, &IID_IActivationFactory)) + { + IUnknown_AddRef(iface); + *out = iface; + return S_OK; + } + + if (IsEqualGUID(iid, &IID_IInstalledVoicesStatic)) + { + IUnknown_AddRef(iface); + *out = &impl->IInstalledVoicesStatic_iface; + return S_OK; + } + + FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE windows_media_speech_AddRef( + IActivationFactory *iface) +{ + struct windows_media_speech *impl = impl_from_IActivationFactory(iface); + ULONG ref = InterlockedIncrement(&impl->ref); + TRACE("iface %p, ref %lu.\n", iface, ref); + return ref; +} + +static ULONG STDMETHODCALLTYPE windows_media_speech_Release( + IActivationFactory *iface) +{ + struct windows_media_speech *impl = impl_from_IActivationFactory(iface); + ULONG ref = InterlockedDecrement(&impl->ref); + TRACE("iface %p, ref %lu.\n", iface, ref); + return ref; +} + +static HRESULT STDMETHODCALLTYPE windows_media_speech_GetIids( + IActivationFactory *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 STDMETHODCALLTYPE windows_media_speech_GetRuntimeClassName( + IActivationFactory *iface, HSTRING *class_name) +{ + FIXME("iface %p, class_name %p stub!\n", iface, class_name); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE windows_media_speech_GetTrustLevel( + IActivationFactory *iface, TrustLevel *trust_level) +{ + FIXME("iface %p, trust_level %p stub!\n", iface, trust_level); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE windows_media_speech_ActivateInstance( + IActivationFactory *iface, IInspectable **instance) +{ + struct speech_synthesizer *obj; + + TRACE("iface %p, instance %p.\n", iface, instance); + + if (!(obj = calloc(1, sizeof(*obj)))) + { + *instance = NULL; + return E_OUTOFMEMORY; + } + + obj->ISpeechSynthesizer_iface.lpVtbl = &speech_synthesizer_vtbl; + obj->IClosable_iface.lpVtbl = &closable_vtbl; + obj->ref = 1; + *instance = (IInspectable *)&obj->ISpeechSynthesizer_iface; + return S_OK; +} + +static const struct IActivationFactoryVtbl activation_factory_vtbl = +{ + windows_media_speech_QueryInterface, + windows_media_speech_AddRef, + windows_media_speech_Release, + /* IInspectable methods */ + windows_media_speech_GetIids, + windows_media_speech_GetRuntimeClassName, + windows_media_speech_GetTrustLevel, + /* IActivationFactory methods */ + windows_media_speech_ActivateInstance, +}; + +static HRESULT STDMETHODCALLTYPE installed_voices_static_QueryInterface( + IInstalledVoicesStatic *iface, REFIID iid, void **out) +{ + struct windows_media_speech *impl = impl_from_IInstalledVoicesStatic(iface); + return windows_media_speech_QueryInterface(&impl->IActivationFactory_iface, iid, out); +} + +static ULONG STDMETHODCALLTYPE installed_voices_static_AddRef( + IInstalledVoicesStatic *iface) +{ + struct windows_media_speech *impl = impl_from_IInstalledVoicesStatic(iface); + return windows_media_speech_AddRef(&impl->IActivationFactory_iface); +} + +static ULONG STDMETHODCALLTYPE installed_voices_static_Release( + IInstalledVoicesStatic *iface) +{ + struct windows_media_speech *impl = impl_from_IInstalledVoicesStatic(iface); + return windows_media_speech_Release(&impl->IActivationFactory_iface); +} + +static HRESULT STDMETHODCALLTYPE installed_voices_static_GetIids( + IInstalledVoicesStatic *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 STDMETHODCALLTYPE installed_voices_static_GetRuntimeClassName( + IInstalledVoicesStatic *iface, HSTRING *class_name) +{ + FIXME("iface %p, class_name %p stub!\n", iface, class_name); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE installed_voices_static_GetTrustLevel( + IInstalledVoicesStatic *iface, TrustLevel *trust_level) +{ + FIXME("iface %p, trust_level %p stub!\n", iface, trust_level); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE installed_voices_static_get_AllVoices( + IInstalledVoicesStatic *iface, IVectorView_VoiceInformation **value) +{ + TRACE("iface %p, value %p.\n", iface, value); + *value = &all_voices.IVectorView_VoiceInformation_iface; + IVectorView_VoiceInformation_AddRef(*value); + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE installed_voices_static_get_DefaultVoice( + IInstalledVoicesStatic *iface, IVoiceInformation **value) +{ + FIXME("iface %p, value %p stub!\n", iface, value); + return E_NOTIMPL; +} + +static const struct IInstalledVoicesStaticVtbl installed_voices_static_vtbl = +{ + installed_voices_static_QueryInterface, + installed_voices_static_AddRef, + installed_voices_static_Release, + /* IInspectable methods */ + installed_voices_static_GetIids, + installed_voices_static_GetRuntimeClassName, + installed_voices_static_GetTrustLevel, + /* IInstalledVoicesStatic methods */ + installed_voices_static_get_AllVoices, + installed_voices_static_get_DefaultVoice, +}; + +static struct windows_media_speech windows_media_speech = +{ + {&activation_factory_vtbl}, + {&installed_voices_static_vtbl}, + 1 +}; + +void STDMETHODCALLTYPE speech_synthesizer_get_activation_factory(IActivationFactory **factory) +{ + *factory = &windows_media_speech.IActivationFactory_iface; +}
Hi Bernhard,
On 3/5/22 20:54, Bernhard Kölbl wrote:
+void STDMETHODCALLTYPE
speech_synthesizer_get_activation_factory(IActivationFactory **factory)
+{
- *factory = &windows_media_speech.IActivationFactory_iface;
+}
I'd suggest to make a global extern pointer variable to one of the factory interface directly, it'll be shorter. For instance something like "synthesizer_factory" or "synthesizer_statics" seems short and explicit enough.
HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void
**out)
{ FIXME("clsid %s, riid %s, out %p stub!\n",
debugstr_guid(clsid), debugstr_guid(riid), out);
@@ -580,7 +38,7 @@ HRESULT WINAPI DllGetActivationFactory(HSTRING
classid, IActivationFactory **fac
return CLASS_E_CLASSNOTAVAILABLE; }
- *factory = &windows_media_speech.IActivationFactory_iface;
- speech_synthesizer_get_activation_factory(factory); IUnknown_AddRef(*factory); return S_OK; }
And here, you can then also use IInspectable_QueryInterface to retrieve the IActivationFactory iface from the pointer while increasing the refcount at the same time, and getting an HRESULT too.
Of course, if you expose the IActivationFactory pointer, QueryInterface isn't really needed, but I found that sometimes exposing another of the statics iface can be useful, and DllGetActivationFactory is the only place where the IActivationFactory is needed.
Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/windows.media.speech/main.c | 13 +++++++------ dlls/windows.media.speech/private.h | 2 ++ 2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/dlls/windows.media.speech/main.c b/dlls/windows.media.speech/main.c index d11a0e6c6e1..db0840f9fdd 100644 --- a/dlls/windows.media.speech/main.c +++ b/dlls/windows.media.speech/main.c @@ -32,13 +32,14 @@ HRESULT WINAPI DllGetActivationFactory(HSTRING classid, IActivationFactory **fac { TRACE("classid %s, factory %p.\n", debugstr_hstring(classid), factory);
- if (wcscmp(WindowsGetStringRawBuffer(classid, NULL), L"Windows.Media.SpeechSynthesis.SpeechSynthesizer")) + if (IsEqualClassID(WindowsGetStringRawBuffer(classid, NULL), + L"Windows.Media.SpeechSynthesis.SpeechSynthesizer")) { - ERR("Unknown classid %s.\n", debugstr_hstring(classid)); - return CLASS_E_CLASSNOTAVAILABLE; + speech_synthesizer_get_activation_factory(factory); + IUnknown_AddRef(*factory); + return S_OK; }
- speech_synthesizer_get_activation_factory(factory); - IUnknown_AddRef(*factory); - return S_OK; + ERR("Unknown classid %s.\n", debugstr_hstring(classid)); + return CLASS_E_CLASSNOTAVAILABLE; } diff --git a/dlls/windows.media.speech/private.h b/dlls/windows.media.speech/private.h index df464c369bf..26a832b5db7 100644 --- a/dlls/windows.media.speech/private.h +++ b/dlls/windows.media.speech/private.h @@ -40,6 +40,8 @@
#include "wine/debug.h"
+#define IsEqualClassID(classid1, classid2) (!wcscmp(classid1, classid2)) + static inline const char *debugstr_hstring(HSTRING hstr) { const WCHAR *str;
Hi Bernhard,
On 3/5/22 20:54, Bernhard Kölbl wrote:
Signed-off-by: Bernhard Kölbl besentv@gmail.com
dlls/windows.media.speech/main.c | 13 +++++++------ dlls/windows.media.speech/private.h | 2 ++ 2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/dlls/windows.media.speech/main.c b/dlls/windows.media.speech/main.c index d11a0e6c6e1..db0840f9fdd 100644 --- a/dlls/windows.media.speech/main.c +++ b/dlls/windows.media.speech/main.c @@ -32,13 +32,14 @@ HRESULT WINAPI DllGetActivationFactory(HSTRING classid, IActivationFactory **fac { TRACE("classid %s, factory %p.\n", debugstr_hstring(classid), factory);
- if (wcscmp(WindowsGetStringRawBuffer(classid, NULL), L"Windows.Media.SpeechSynthesis.SpeechSynthesizer"))
- if (IsEqualClassID(WindowsGetStringRawBuffer(classid, NULL),
L"Windows.Media.SpeechSynthesis.SpeechSynthesizer")) {
ERR("Unknown classid %s.\n", debugstr_hstring(classid));
return CLASS_E_CLASSNOTAVAILABLE;
speech_synthesizer_get_activation_factory(factory);
IUnknown_AddRef(*factory);
return S_OK; }
- speech_synthesizer_get_activation_factory(factory);
- IUnknown_AddRef(*factory);
- return S_OK;
- ERR("Unknown classid %s.\n", debugstr_hstring(classid));
- return CLASS_E_CLASSNOTAVAILABLE; }
diff --git a/dlls/windows.media.speech/private.h b/dlls/windows.media.speech/private.h index df464c369bf..26a832b5db7 100644 --- a/dlls/windows.media.speech/private.h +++ b/dlls/windows.media.speech/private.h @@ -40,6 +40,8 @@
#include "wine/debug.h"
+#define IsEqualClassID(classid1, classid2) (!wcscmp(classid1, classid2))
- static inline const char *debugstr_hstring(HSTRING hstr) { const WCHAR *str;
I'm not sure this helper is really useful, it only adds an indirection imho.
Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/windows.media.speech/synthesizer.c | 66 ++++++++++++------------- 1 file changed, 33 insertions(+), 33 deletions(-)
diff --git a/dlls/windows.media.speech/synthesizer.c b/dlls/windows.media.speech/synthesizer.c index b2719e46f8b..6af198817c5 100644 --- a/dlls/windows.media.speech/synthesizer.c +++ b/dlls/windows.media.speech/synthesizer.c @@ -366,27 +366,27 @@ static const struct IClosableVtbl closable_vtbl = closable_Close, };
-struct windows_media_speech +struct activation_factory { IActivationFactory IActivationFactory_iface; IInstalledVoicesStatic IInstalledVoicesStatic_iface; LONG ref; };
-static inline struct windows_media_speech *impl_from_IActivationFactory(IActivationFactory *iface) +static inline struct activation_factory *impl_from_IActivationFactory(IActivationFactory *iface) { - return CONTAINING_RECORD(iface, struct windows_media_speech, IActivationFactory_iface); + return CONTAINING_RECORD(iface, struct activation_factory, IActivationFactory_iface); }
-static inline struct windows_media_speech *impl_from_IInstalledVoicesStatic(IInstalledVoicesStatic *iface) +static inline struct activation_factory *impl_from_IInstalledVoicesStatic(IInstalledVoicesStatic *iface) { - return CONTAINING_RECORD(iface, struct windows_media_speech, IInstalledVoicesStatic_iface); + return CONTAINING_RECORD(iface, struct activation_factory, IInstalledVoicesStatic_iface); }
-static HRESULT STDMETHODCALLTYPE windows_media_speech_QueryInterface( +static HRESULT STDMETHODCALLTYPE activation_factory_QueryInterface( IActivationFactory *iface, REFIID iid, void **out) { - struct windows_media_speech *impl = impl_from_IActivationFactory(iface); + struct activation_factory *impl = impl_from_IActivationFactory(iface);
TRACE("iface %p, iid %s, out %p stub!\n", iface, debugstr_guid(iid), out);
@@ -412,46 +412,46 @@ static HRESULT STDMETHODCALLTYPE windows_media_speech_QueryInterface( return E_NOINTERFACE; }
-static ULONG STDMETHODCALLTYPE windows_media_speech_AddRef( +static ULONG STDMETHODCALLTYPE activation_factory_AddRef( IActivationFactory *iface) { - struct windows_media_speech *impl = impl_from_IActivationFactory(iface); + struct activation_factory *impl = impl_from_IActivationFactory(iface); ULONG ref = InterlockedIncrement(&impl->ref); TRACE("iface %p, ref %lu.\n", iface, ref); return ref; }
-static ULONG STDMETHODCALLTYPE windows_media_speech_Release( +static ULONG STDMETHODCALLTYPE activation_factory_Release( IActivationFactory *iface) { - struct windows_media_speech *impl = impl_from_IActivationFactory(iface); + struct activation_factory *impl = impl_from_IActivationFactory(iface); ULONG ref = InterlockedDecrement(&impl->ref); TRACE("iface %p, ref %lu.\n", iface, ref); return ref; }
-static HRESULT STDMETHODCALLTYPE windows_media_speech_GetIids( +static HRESULT STDMETHODCALLTYPE activation_factory_GetIids( IActivationFactory *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 STDMETHODCALLTYPE windows_media_speech_GetRuntimeClassName( +static HRESULT STDMETHODCALLTYPE activation_factory_GetRuntimeClassName( IActivationFactory *iface, HSTRING *class_name) { FIXME("iface %p, class_name %p stub!\n", iface, class_name); return E_NOTIMPL; }
-static HRESULT STDMETHODCALLTYPE windows_media_speech_GetTrustLevel( +static HRESULT STDMETHODCALLTYPE activation_factory_GetTrustLevel( IActivationFactory *iface, TrustLevel *trust_level) { FIXME("iface %p, trust_level %p stub!\n", iface, trust_level); return E_NOTIMPL; }
-static HRESULT STDMETHODCALLTYPE windows_media_speech_ActivateInstance( +static HRESULT STDMETHODCALLTYPE activation_factory_ActivateInstance( IActivationFactory *iface, IInspectable **instance) { struct speech_synthesizer *obj; @@ -473,36 +473,36 @@ static HRESULT STDMETHODCALLTYPE windows_media_speech_ActivateInstance(
static const struct IActivationFactoryVtbl activation_factory_vtbl = { - windows_media_speech_QueryInterface, - windows_media_speech_AddRef, - windows_media_speech_Release, + activation_factory_QueryInterface, + activation_factory_AddRef, + activation_factory_Release, /* IInspectable methods */ - windows_media_speech_GetIids, - windows_media_speech_GetRuntimeClassName, - windows_media_speech_GetTrustLevel, + activation_factory_GetIids, + activation_factory_GetRuntimeClassName, + activation_factory_GetTrustLevel, /* IActivationFactory methods */ - windows_media_speech_ActivateInstance, + activation_factory_ActivateInstance, };
static HRESULT STDMETHODCALLTYPE installed_voices_static_QueryInterface( IInstalledVoicesStatic *iface, REFIID iid, void **out) { - struct windows_media_speech *impl = impl_from_IInstalledVoicesStatic(iface); - return windows_media_speech_QueryInterface(&impl->IActivationFactory_iface, iid, out); + struct activation_factory *impl = impl_from_IInstalledVoicesStatic(iface); + return activation_factory_QueryInterface(&impl->IActivationFactory_iface, iid, out); }
static ULONG STDMETHODCALLTYPE installed_voices_static_AddRef( IInstalledVoicesStatic *iface) { - struct windows_media_speech *impl = impl_from_IInstalledVoicesStatic(iface); - return windows_media_speech_AddRef(&impl->IActivationFactory_iface); + struct activation_factory *impl = impl_from_IInstalledVoicesStatic(iface); + return activation_factory_AddRef(&impl->IActivationFactory_iface); }
static ULONG STDMETHODCALLTYPE installed_voices_static_Release( IInstalledVoicesStatic *iface) { - struct windows_media_speech *impl = impl_from_IInstalledVoicesStatic(iface); - return windows_media_speech_Release(&impl->IActivationFactory_iface); + struct activation_factory *impl = impl_from_IInstalledVoicesStatic(iface); + return activation_factory_Release(&impl->IActivationFactory_iface); }
static HRESULT STDMETHODCALLTYPE installed_voices_static_GetIids( @@ -556,14 +556,14 @@ static const struct IInstalledVoicesStaticVtbl installed_voices_static_vtbl = installed_voices_static_get_DefaultVoice, };
-static struct windows_media_speech windows_media_speech = +static struct activation_factory speechsynthesizer_af = { - {&activation_factory_vtbl}, - {&installed_voices_static_vtbl}, - 1 + .IActivationFactory_iface = {&activation_factory_vtbl}, + .IInstalledVoicesStatic_iface = {&installed_voices_static_vtbl}, + .ref = 1 };
void STDMETHODCALLTYPE speech_synthesizer_get_activation_factory(IActivationFactory **factory) { - *factory = &windows_media_speech.IActivationFactory_iface; + *factory = &speechsynthesizer_af.IActivationFactory_iface; }
Hi Bernhard,
On 3/5/22 20:54, Bernhard Kölbl wrote:
Signed-off-by: Bernhard Kölbl besentv@gmail.com
dlls/windows.media.speech/synthesizer.c | 66 ++++++++++++------------- 1 file changed, 33 insertions(+), 33 deletions(-)
diff --git a/dlls/windows.media.speech/synthesizer.c b/dlls/windows.media.speech/synthesizer.c index b2719e46f8b..6af198817c5 100644 --- a/dlls/windows.media.speech/synthesizer.c +++ b/dlls/windows.media.speech/synthesizer.c @@ -366,27 +366,27 @@ static const struct IClosableVtbl closable_vtbl = closable_Close, };
-struct windows_media_speech +struct activation_factory { IActivationFactory IActivationFactory_iface; IInstalledVoicesStatic IInstalledVoicesStatic_iface; LONG ref; };
I'd suggest something like synthesizer_statics or synthesizer_factory for the struct name, the "activation" is really just one aspect of the type.
-static inline struct windows_media_speech *impl_from_IActivationFactory(IActivationFactory *iface) +static inline struct activation_factory *impl_from_IActivationFactory(IActivationFactory *iface) {
- return CONTAINING_RECORD(iface, struct windows_media_speech, IActivationFactory_iface);
- return CONTAINING_RECORD(iface, struct activation_factory, IActivationFactory_iface); }
-static inline struct windows_media_speech *impl_from_IInstalledVoicesStatic(IInstalledVoicesStatic *iface) +static inline struct activation_factory *impl_from_IInstalledVoicesStatic(IInstalledVoicesStatic *iface) {
- return CONTAINING_RECORD(iface, struct windows_media_speech, IInstalledVoicesStatic_iface);
- return CONTAINING_RECORD(iface, struct activation_factory, IInstalledVoicesStatic_iface); }
-static HRESULT STDMETHODCALLTYPE windows_media_speech_QueryInterface( +static HRESULT STDMETHODCALLTYPE activation_factory_QueryInterface( IActivationFactory *iface, REFIID iid, void **out) {
- struct windows_media_speech *impl = impl_from_IActivationFactory(iface);
struct activation_factory *impl = impl_from_IActivationFactory(iface);
TRACE("iface %p, iid %s, out %p stub!\n", iface, debugstr_guid(iid), out);
@@ -412,46 +412,46 @@ static HRESULT STDMETHODCALLTYPE windows_media_speech_QueryInterface( return E_NOINTERFACE; }
To make things shorter, I think it's possible to use WINAPI instead of STDMETHODCALLTYPE.
Then, I'd suggest to use even shorter prefixes, such as activation_ or factory_, and later statics_ for the statics iface.
Of course unless this would cause ambiguities later on.
-static struct windows_media_speech windows_media_speech = +static struct activation_factory speechsynthesizer_af = {
- {&activation_factory_vtbl},
- {&installed_voices_static_vtbl},
- 1
- .IActivationFactory_iface = {&activation_factory_vtbl},
- .IInstalledVoicesStatic_iface = {&installed_voices_static_vtbl},
- .ref = 1 };
I think the variable could also be named synthesizer_statics or something matching the struct.
To test, if the ifaces are static and if each activatable class has it's own activation factory.
Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/windows.media.speech/tests/speech.c | 120 +++++++++++++++++++++++ 1 file changed, 120 insertions(+)
diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c index 38fd5c90dd0..0d9564d4a65 100644 --- a/dlls/windows.media.speech/tests/speech.c +++ b/dlls/windows.media.speech/tests/speech.c @@ -29,6 +29,8 @@ #define WIDL_using_Windows_Foundation #define WIDL_using_Windows_Foundation_Collections #include "windows.foundation.h" +#define WIDL_using_Windows_Media_SpeechRecognition +#include "windows.media.speechrecognition.h" #define WIDL_using_Windows_Media_SpeechSynthesis #include "windows.media.speechsynthesis.h"
@@ -36,6 +38,123 @@
HRESULT WINAPI (*pDllGetActivationFactory)(HSTRING, IActivationFactory **);
+static void test_ActivationFactory(void) +{ + static const WCHAR *synthesizer_name = L"Windows.Media.SpeechSynthesis.SpeechSynthesizer"; + static const WCHAR *recognizer_name = L"Windows.Media.SpeechRecognition.SpeechRecognizer"; + IInspectable *inspectable = NULL, *inspectable2 = NULL; + IAgileObject *agile_object = NULL, *agile_object2 = NULL; + IActivationFactory *afactory = NULL, *afactory2 = NULL, *afactory3 = NULL; + ISpeechRecognizerFactory *sr_factory = NULL; + ISpeechRecognizerStatics *sr_statics = NULL; + ISpeechRecognizerStatics2 *sr_statics2 = NULL; + IInstalledVoicesStatic *installed_voices = NULL; + HSTRING str, str2; + HRESULT hr; + ULONG ref; + + hr = RoInitialize(RO_INIT_MULTITHREADED); + ok(hr == S_OK, "RoInitialize failed, hr %#x.\n", hr); + + hr = WindowsCreateString(synthesizer_name, wcslen(synthesizer_name), &str); + ok(hr == S_OK, "WindowsCreateString failed, hr %#x.\n", hr); + + hr = WindowsCreateString(recognizer_name, wcslen(recognizer_name), &str2); + ok(hr == S_OK, "WindowsCreateString failed, hr %#x.\n", hr); + + hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&afactory); + ok(hr == S_OK, "RoGetActivationFactory failed, hr %#x.\n", hr); + + ref = IActivationFactory_AddRef(afactory); + ok(ref == 3, "Got unexpected refcount: %u.\n", ref); + + ref = IActivationFactory_Release(afactory); + ok(ref == 2, "Got unexpected refcount: %u.\n", ref); + + hr = IActivationFactory_QueryInterface(afactory, &IID_ISpeechRecognizerFactory, (void**)&sr_factory); + ok(hr == E_NOINTERFACE, "IActivationFactory_QueryInterface failed, hr %#x.\n", hr); + + hr = IActivationFactory_QueryInterface(afactory, &IID_IInspectable, (void**)&inspectable); + ok(hr == S_OK, "IActivationFactory_QueryInterface failed, hr %#x.\n", hr); + + hr = IActivationFactory_QueryInterface(afactory, &IID_IAgileObject, (void**)&agile_object); + ok(hr == S_OK, "IActivationFactory_QueryInterface failed, hr %#x.\n", hr); + + hr = IActivationFactory_QueryInterface(afactory, &IID_IInstalledVoicesStatic, (void**)&installed_voices); + ok(hr == S_OK, "IActivationFactory_QueryInterface failed, hr %#x.\n", hr); + + ref = IInstalledVoicesStatic_Release(installed_voices); + ok(ref == 4, "Got unexpected refcount: %u.\n", ref); + + ref = IAgileObject_Release(agile_object); + ok(ref == 3, "Got unexpected refcount: %u.\n", ref); + + ref = IInspectable_Release(inspectable); + ok(ref == 2, "Got unexpected refcount: %u.\n", ref); + + hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&afactory2); + ok(hr == S_OK, "RoGetActivationFactory failed, hr %#x.\n", hr); + ok(afactory == afactory2, "Factories pointed at afactory %p afactory2 %p.\n", afactory, afactory2); + + hr = RoGetActivationFactory(str2, &IID_IActivationFactory, (void **)&afactory3); + todo_wine ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG), "RoGetActivationFactory failed, hr %#x.\n", hr); + + if(hr == S_OK) /* Win10+ only */ + { + ok(afactory != afactory3, "Factories pointed at afactory %p afactory3 %p.\n", afactory, afactory3); + + hr = IActivationFactory_QueryInterface(afactory3, &IID_IInspectable, (void**)&inspectable2); + ok(hr == S_OK, "IActivationFactory_QueryInterface failed, hr %#x.\n", hr); + + hr = IActivationFactory_QueryInterface(afactory3, &IID_IAgileObject, (void**)&agile_object2); + ok(hr == S_OK, "IActivationFactory_QueryInterface failed, hr %#x.\n", hr); + + hr = IActivationFactory_QueryInterface(afactory3, &IID_ISpeechRecognizerFactory, (void**)&sr_factory); + ok(hr == S_OK, "IActivationFactory_QueryInterface failed, hr %#x.\n", hr); + + hr = IActivationFactory_QueryInterface(afactory3, &IID_ISpeechRecognizerStatics, (void**)&sr_statics); + ok(hr == S_OK, "IActivationFactory_QueryInterface failed, hr %#x.\n", hr); + + ref = ISpeechRecognizerStatics_Release(sr_statics); + ok(ref == 5, "Got unexpected refcount: %u.\n", ref); + + ref = ISpeechRecognizerFactory_Release(sr_factory); + ok(ref == 4, "Got unexpected refcount: %u.\n", ref); + + ref = IAgileObject_Release(agile_object2); + ok(ref == 3, "Got unexpected refcount: %u.\n", ref); + + ref = IInspectable_Release(inspectable2); + ok(ref == 2, "Got unexpected refcount: %u.\n", ref); + + hr = IActivationFactory_QueryInterface(afactory3, &IID_ISpeechRecognizerStatics2, (void**)&sr_statics2); + ok(hr == S_OK || broken(hr == E_NOINTERFACE), "IActivationFactory_QueryInterface failed, hr %#x.\n", hr); + + if(hr == S_OK) /* ISpeechRecognizerStatics2 not available in Win10 1507 */ + { + ref = ISpeechRecognizerStatics2_Release(sr_statics2); + ok(ref == 2, "Got unexpected refcount: %u.\n", ref); + } + + hr = IActivationFactory_QueryInterface(afactory3, &IID_IInstalledVoicesStatic, (void**)&installed_voices); + ok(hr == E_NOINTERFACE, "IActivationFactory_QueryInterface failed, hr %#x.\n", hr); + + ref = IActivationFactory_Release(afactory3); + ok(ref == 1, "Got unexpected refcount: %u.\n", ref); + } + + ref = IActivationFactory_Release(afactory2); + ok(ref == 2, "Got unexpected refcount: %u.\n", ref); + + ref = IActivationFactory_Release(afactory); + ok(ref == 1, "Got unexpected refcount: %u.\n", ref); + + WindowsDeleteString(str); + WindowsDeleteString(str2); + + RoUninitialize(); +} + static void test_SpeechSynthesizer(void) { static const WCHAR *speech_synthesizer_name = L"Windows.Media.SpeechSynthesis.SpeechSynthesizer"; @@ -203,6 +322,7 @@ static void test_VoiceInformation(void)
START_TEST(speech) { + test_ActivationFactory(); test_SpeechSynthesizer(); test_VoiceInformation(); }
Hi Bernhard,
On 3/5/22 20:54, Bernhard Kölbl wrote:
To test, if the ifaces are static and if each activatable class has it's own activation factory.
Signed-off-by: Bernhard Kölbl besentv@gmail.com
dlls/windows.media.speech/tests/speech.c | 120 +++++++++++++++++++++++ 1 file changed, 120 insertions(+)
diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c index 38fd5c90dd0..0d9564d4a65 100644 --- a/dlls/windows.media.speech/tests/speech.c +++ b/dlls/windows.media.speech/tests/speech.c @@ -29,6 +29,8 @@ #define WIDL_using_Windows_Foundation #define WIDL_using_Windows_Foundation_Collections #include "windows.foundation.h" +#define WIDL_using_Windows_Media_SpeechRecognition +#include "windows.media.speechrecognition.h" #define WIDL_using_Windows_Media_SpeechSynthesis #include "windows.media.speechsynthesis.h"
@@ -36,6 +38,123 @@
HRESULT WINAPI (*pDllGetActivationFactory)(HSTRING, IActivationFactory **);
+static void test_ActivationFactory(void) +{
- static const WCHAR *synthesizer_name = L"Windows.Media.SpeechSynthesis.SpeechSynthesizer";
- static const WCHAR *recognizer_name = L"Windows.Media.SpeechRecognition.SpeechRecognizer";
- IInspectable *inspectable = NULL, *inspectable2 = NULL;
- IAgileObject *agile_object = NULL, *agile_object2 = NULL;
- IActivationFactory *afactory = NULL, *afactory2 = NULL, *afactory3 = NULL;
- ISpeechRecognizerFactory *sr_factory = NULL;
- ISpeechRecognizerStatics *sr_statics = NULL;
- ISpeechRecognizerStatics2 *sr_statics2 = NULL;
Regarding names, it doesn't matter too much but I'd rename "afactoryX" to "factoryX" instead. The "sr_" prefix is also a little bit cryptic, and "recognizer_" looks short enough and more readable.
- IInstalledVoicesStatic *installed_voices = NULL;
- HSTRING str, str2;
- HRESULT hr;
- ULONG ref;
- hr = RoInitialize(RO_INIT_MULTITHREADED);
- ok(hr == S_OK, "RoInitialize failed, hr %#x.\n", hr);
- hr = WindowsCreateString(synthesizer_name, wcslen(synthesizer_name), &str);
- ok(hr == S_OK, "WindowsCreateString failed, hr %#x.\n", hr);
- hr = WindowsCreateString(recognizer_name, wcslen(recognizer_name), &str2);
- ok(hr == S_OK, "WindowsCreateString failed, hr %#x.\n", hr);
- hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&afactory);
- ok(hr == S_OK, "RoGetActivationFactory failed, hr %#x.\n", hr);
Unless you need the strings for some reason, I think it's shorter to just do WindowsCreateString, RoGetActivationFactory, WindowsDeleteString in sequence, you will only need one HSTRING variable.
- ref = IActivationFactory_AddRef(afactory);
- ok(ref == 3, "Got unexpected refcount: %u.\n", ref);
- ref = IActivationFactory_Release(afactory);
- ok(ref == 2, "Got unexpected refcount: %u.\n", ref);
- hr = IActivationFactory_QueryInterface(afactory, &IID_ISpeechRecognizerFactory, (void**)&sr_factory);
- ok(hr == E_NOINTERFACE, "IActivationFactory_QueryInterface failed, hr %#x.\n", hr);
- hr = IActivationFactory_QueryInterface(afactory, &IID_IInspectable, (void**)&inspectable);
- ok(hr == S_OK, "IActivationFactory_QueryInterface failed, hr %#x.\n", hr);
- hr = IActivationFactory_QueryInterface(afactory, &IID_IAgileObject, (void**)&agile_object);
- ok(hr == S_OK, "IActivationFactory_QueryInterface failed, hr %#x.\n", hr);
- hr = IActivationFactory_QueryInterface(afactory, &IID_IInstalledVoicesStatic, (void**)&installed_voices);
- ok(hr == S_OK, "IActivationFactory_QueryInterface failed, hr %#x.\n", hr);
- ref = IInstalledVoicesStatic_Release(installed_voices);
- ok(ref == 4, "Got unexpected refcount: %u.\n", ref);
- ref = IAgileObject_Release(agile_object);
- ok(ref == 3, "Got unexpected refcount: %u.\n", ref);
- ref = IInspectable_Release(inspectable);
- ok(ref == 2, "Got unexpected refcount: %u.\n", ref);
I'm not sure checking the refcount extensively is very useful, I know I probably did it for the stubs, to check how things were supposed to work, but maybe now we have a better idea it's not necessary to do it for every factory.
To check the available interfaces it's shorter and convenient to use the check_interface test helper that's copied around, just copy whichever version of if you like best there too and you can then check the interfaces you want easily.
If you really want to check refcount, there's also an "EXPECT_REF" or "check_ref" helpers lying around as well, which may do it in a shorter way.
- hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&afactory2);
- ok(hr == S_OK, "RoGetActivationFactory failed, hr %#x.\n", hr);
- ok(afactory == afactory2, "Factories pointed at afactory %p afactory2 %p.\n", afactory, afactory2);
- hr = RoGetActivationFactory(str2, &IID_IActivationFactory, (void **)&afactory3);
- todo_wine ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG), "RoGetActivationFactory failed, hr %#x.\n", hr);
- if(hr == S_OK) /* Win10+ only */
- {
Instead of a big if like this, I'd suggest to have a done label and "goto done" here. Anything that doesn't require this factory can be tested before. If it makes things more complicated, maybe a dedicated test function for this factory is better.
Freeing the str before checking hr, as suggested above also saves you the need of handling the remaining HSTRING at the bottom.
ok(afactory != afactory3, "Factories pointed at afactory %p afactory3 %p.\n", afactory, afactory3);
hr = IActivationFactory_QueryInterface(afactory3, &IID_IInspectable, (void**)&inspectable2);
ok(hr == S_OK, "IActivationFactory_QueryInterface failed, hr %#x.\n", hr);
hr = IActivationFactory_QueryInterface(afactory3, &IID_IAgileObject, (void**)&agile_object2);
ok(hr == S_OK, "IActivationFactory_QueryInterface failed, hr %#x.\n", hr);
hr = IActivationFactory_QueryInterface(afactory3, &IID_ISpeechRecognizerFactory, (void**)&sr_factory);
ok(hr == S_OK, "IActivationFactory_QueryInterface failed, hr %#x.\n", hr);
hr = IActivationFactory_QueryInterface(afactory3, &IID_ISpeechRecognizerStatics, (void**)&sr_statics);
ok(hr == S_OK, "IActivationFactory_QueryInterface failed, hr %#x.\n", hr);
ref = ISpeechRecognizerStatics_Release(sr_statics);
ok(ref == 5, "Got unexpected refcount: %u.\n", ref);
ref = ISpeechRecognizerFactory_Release(sr_factory);
ok(ref == 4, "Got unexpected refcount: %u.\n", ref);
ref = IAgileObject_Release(agile_object2);
ok(ref == 3, "Got unexpected refcount: %u.\n", ref);
ref = IInspectable_Release(inspectable2);
ok(ref == 2, "Got unexpected refcount: %u.\n", ref);
hr = IActivationFactory_QueryInterface(afactory3, &IID_ISpeechRecognizerStatics2, (void**)&sr_statics2);
ok(hr == S_OK || broken(hr == E_NOINTERFACE), "IActivationFactory_QueryInterface failed, hr %#x.\n", hr);
if(hr == S_OK) /* ISpeechRecognizerStatics2 not available in Win10 1507 */
{
ref = ISpeechRecognizerStatics2_Release(sr_statics2);
ok(ref == 2, "Got unexpected refcount: %u.\n", ref);
}
Again, I think checking refs everywhere makes this a little bit too verbose. If you want to assert there's no leak, doing it only when it's expected to reach 0 could be interesting and better. For static objects I don't think it's really useful.
hr = IActivationFactory_QueryInterface(afactory3, &IID_IInstalledVoicesStatic, (void**)&installed_voices);
ok(hr == E_NOINTERFACE, "IActivationFactory_QueryInterface failed, hr %#x.\n", hr);
ref = IActivationFactory_Release(afactory3);
ok(ref == 1, "Got unexpected refcount: %u.\n", ref);
- }
- ref = IActivationFactory_Release(afactory2);
- ok(ref == 2, "Got unexpected refcount: %u.\n", ref);
- ref = IActivationFactory_Release(afactory);
- ok(ref == 1, "Got unexpected refcount: %u.\n", ref);
- WindowsDeleteString(str);
- WindowsDeleteString(str2);
- RoUninitialize();
+}
- static void test_SpeechSynthesizer(void) { static const WCHAR *speech_synthesizer_name = L"Windows.Media.SpeechSynthesis.SpeechSynthesizer";
@@ -203,6 +322,7 @@ static void test_VoiceInformation(void)
START_TEST(speech) {
- test_ActivationFactory(); test_SpeechSynthesizer(); test_VoiceInformation(); }
Cheers,