From 3a06c15dd203e80629b19477cc96428c493aa5ec Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Fri, 17 Sep 2021 14:17:46 +1000 Subject: [PATCH] Added sapi-ISpObjectToken-CreateInstance patchset --- patches/patchinstall.sh | 19 ++ .../0001-include-Add-ISpAudio-interface.patch | 60 ++++ ...Token-SetId-Support-create-parameter.patch | 29 ++ ...kenCategory-SetId-Support-create-par.patch | 32 ++ ...oken-CreateInstance-support-ISpAudio.patch | 308 ++++++++++++++++++ .../definition | 2 + 6 files changed, 450 insertions(+) create mode 100644 patches/sapi-ISpObjectToken-CreateInstance/0001-include-Add-ISpAudio-interface.patch create mode 100644 patches/sapi-ISpObjectToken-CreateInstance/0002-sapi-ISpObjectToken-SetId-Support-create-parameter.patch create mode 100644 patches/sapi-ISpObjectToken-CreateInstance/0003-sapi-ISpObjectTokenCategory-SetId-Support-create-par.patch create mode 100644 patches/sapi-ISpObjectToken-CreateInstance/0004-sapi-ISpObjectToken-CreateInstance-support-ISpAudio.patch create mode 100644 patches/sapi-ISpObjectToken-CreateInstance/definition diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 100138e0..04ef166e 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -185,6 +185,7 @@ patch_enable_all () enable_programs_systeminfo="$1" enable_riched20_Class_Tests="$1" enable_riched20_IText_Interface="$1" + enable_sapi_ISpObjectToken_CreateInstance="$1" enable_secur32_InitializeSecurityContextW="$1" enable_server_File_Permissions="$1" enable_server_Key_State="$1" @@ -594,6 +595,9 @@ patch_enable () riched20-IText_Interface) enable_riched20_IText_Interface="$2" ;; + sapi-ISpObjectToken-CreateInstance) + enable_sapi_ISpObjectToken_CreateInstance="$2" + ;; secur32-InitializeSecurityContextW) enable_secur32_InitializeSecurityContextW="$2" ;; @@ -3016,6 +3020,21 @@ if test "$enable_riched20_IText_Interface" -eq 1; then patch_apply riched20-IText_Interface/0010-riched20-Silence-repeated-FIXMEs-triggered-by-Adobe-.patch fi +# Patchset sapi-ISpObjectToken-CreateInstance +# | +# | This patchset fixes the following Wine bugs: +# | * [#49641] sapi: Implement ISpObjectToken-CreateInstance +# | +# | Modified files: +# | * dlls/sapi/token.c, include/sapi.idl +# | +if test "$enable_sapi_ISpObjectToken_CreateInstance" -eq 1; then + patch_apply sapi-ISpObjectToken-CreateInstance/0001-include-Add-ISpAudio-interface.patch + patch_apply sapi-ISpObjectToken-CreateInstance/0002-sapi-ISpObjectToken-SetId-Support-create-parameter.patch + patch_apply sapi-ISpObjectToken-CreateInstance/0003-sapi-ISpObjectTokenCategory-SetId-Support-create-par.patch + patch_apply sapi-ISpObjectToken-CreateInstance/0004-sapi-ISpObjectToken-CreateInstance-support-ISpAudio.patch +fi + # Patchset secur32-InitializeSecurityContextW # | # | This patchset fixes the following Wine bugs: diff --git a/patches/sapi-ISpObjectToken-CreateInstance/0001-include-Add-ISpAudio-interface.patch b/patches/sapi-ISpObjectToken-CreateInstance/0001-include-Add-ISpAudio-interface.patch new file mode 100644 index 00000000..9eb0a6ac --- /dev/null +++ b/patches/sapi-ISpObjectToken-CreateInstance/0001-include-Add-ISpAudio-interface.patch @@ -0,0 +1,60 @@ +From 51c747ba5e32109ed5d5b03e3bf5b67aecd8130c Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Wed, 15 Sep 2021 18:55:10 +1000 +Subject: [PATCH 1/4] include: Add ISpAudio interface + +Signed-off-by: Alistair Leslie-Hughes +--- + include/sapi.idl | 29 +++++++++++++++++++++++++++++ + 1 file changed, 29 insertions(+) + +diff --git a/include/sapi.idl b/include/sapi.idl +index 5120e379450..b9bc05c5be4 100644 +--- a/include/sapi.idl ++++ b/include/sapi.idl +@@ -492,6 +492,13 @@ typedef [hidden] enum SPFILEMODE + SPFM_NUM_MODES + } SPFILEMODE; + ++typedef [restricted, hidden] struct SPAUDIOBUFFERINFO ++{ ++ ULONG ulMsMinNotification; ++ ULONG ulMsBufferSize; ++ ULONG ulMsEventBias; ++} SPAUDIOBUFFERINFO; ++ + cpp_quote("#if defined(__GNUC__)") + + cpp_quote("#define SPCAT_AUDIOOUT (const WCHAR []){ 'H','K','E','Y','_','L','O','C','A','L','_','M','A','C','H','I','N','E','\\\\','S','O','F','T','W','A','R','E','\\\\','M','i','c','r','o','s','o','f','t','\\\\','S','p','e','e','c','h','\\\\','A','u','d','i','o','O','u','t','p','u','t',0 }") +@@ -993,6 +1000,28 @@ interface ISpStreamFormat : IStream + HRESULT GetFormat(GUID *format, WAVEFORMATEX **wave); + } + ++[ ++ object, ++ uuid(c05c768f-fae8-4ec2-8e07-338321c12452), ++ pointer_default(unique), ++ local, ++ restricted ++] ++interface ISpAudio : ISpStreamFormat ++{ ++ HRESULT SetState([in] SPAUDIOSTATE state, [in] ULONGLONG reserved); ++ HRESULT SetFormat([in] REFGUID guid, [in] const WAVEFORMATEX *wave); ++ HRESULT GetStatus([out] SPAUDIOSTATUS *status); ++ HRESULT SetBufferInfo([in] const SPAUDIOBUFFERINFO *buffer); ++ HRESULT GetBufferInfo([out] SPAUDIOBUFFERINFO *buffer); ++ HRESULT GetDefaultFormat([out] GUID *guid, [out] WAVEFORMATEX **wave); ++ HANDLE EventHandle(); ++ HRESULT GetVolumeLevel([out] ULONG *level); ++ HRESULT SetVolumeLevel([in] ULONG level); ++ HRESULT GetBufferNotifySize([out] ULONG *size); ++ HRESULT SetBufferNotifySize([in] ULONG size); ++}; ++ + [ + object, + uuid(5b4fb971-b115-4de1-ad97-e482e3bf6ee4), +-- +2.33.0 + diff --git a/patches/sapi-ISpObjectToken-CreateInstance/0002-sapi-ISpObjectToken-SetId-Support-create-parameter.patch b/patches/sapi-ISpObjectToken-CreateInstance/0002-sapi-ISpObjectToken-SetId-Support-create-parameter.patch new file mode 100644 index 00000000..643ca217 --- /dev/null +++ b/patches/sapi-ISpObjectToken-CreateInstance/0002-sapi-ISpObjectToken-SetId-Support-create-parameter.patch @@ -0,0 +1,29 @@ +From dd0c16513f9c2be494327875915e7e7520b9d9e2 Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Wed, 15 Sep 2021 18:55:11 +1000 +Subject: [PATCH 2/4] sapi: ISpObjectToken SetId - Support create parameter + +Signed-off-by: Alistair Leslie-Hughes +--- + dlls/sapi/token.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/dlls/sapi/token.c b/dlls/sapi/token.c +index 04fa3a25d6a..ec1cce5f462 100644 +--- a/dlls/sapi/token.c ++++ b/dlls/sapi/token.c +@@ -942,7 +942,10 @@ static HRESULT WINAPI token_SetId( ISpObjectToken *iface, + hr = parse_cat_id( token_id, &root, &subkey ); + if (hr != S_OK) return SPERR_NOT_FOUND; + +- res = RegOpenKeyExW( root, subkey, 0, KEY_ALL_ACCESS, &key ); ++ if (create) ++ res = RegCreateKeyExW( root, subkey, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &key, NULL); ++ else ++ res = RegOpenKeyExW( root, subkey, 0, KEY_ALL_ACCESS, &key ); + if (res) return SPERR_NOT_FOUND; + + This->token_key = key; +-- +2.33.0 + diff --git a/patches/sapi-ISpObjectToken-CreateInstance/0003-sapi-ISpObjectTokenCategory-SetId-Support-create-par.patch b/patches/sapi-ISpObjectToken-CreateInstance/0003-sapi-ISpObjectTokenCategory-SetId-Support-create-par.patch new file mode 100644 index 00000000..7bcdba4b --- /dev/null +++ b/patches/sapi-ISpObjectToken-CreateInstance/0003-sapi-ISpObjectTokenCategory-SetId-Support-create-par.patch @@ -0,0 +1,32 @@ +From e00a0d24dbb7c28c5e0de1b957b872ed9fdcdc90 Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Wed, 15 Sep 2021 18:55:11 +1000 +Subject: [PATCH 3/4] sapi: ISpObjectTokenCategory SetId - Support create + parameter + +Signed-off-by: Alistair Leslie-Hughes +--- + dlls/sapi/token.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/dlls/sapi/token.c b/dlls/sapi/token.c +index ec1cce5f462..ba91a425e9e 100644 +--- a/dlls/sapi/token.c ++++ b/dlls/sapi/token.c +@@ -416,9 +416,10 @@ static HRESULT WINAPI token_category_SetId( ISpObjectTokenCategory *iface, + hr = parse_cat_id( id, &root, &subkey ); + if (hr != S_OK) return SPERR_INVALID_REGISTRY_KEY; + +- if (create) FIXME( "Ignoring create\n" ); +- +- res = RegOpenKeyExW( root, subkey, 0, KEY_ALL_ACCESS, &key ); ++ if (create) ++ res = RegCreateKeyExW( root, subkey, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &key, NULL ); ++ else ++ res = RegOpenKeyExW( root, subkey, 0, KEY_ALL_ACCESS, &key ); + if (res) return SPERR_INVALID_REGISTRY_KEY; + + hr = CoCreateInstance( &CLSID_SpDataKey, NULL, CLSCTX_ALL, +-- +2.33.0 + diff --git a/patches/sapi-ISpObjectToken-CreateInstance/0004-sapi-ISpObjectToken-CreateInstance-support-ISpAudio.patch b/patches/sapi-ISpObjectToken-CreateInstance/0004-sapi-ISpObjectToken-CreateInstance-support-ISpAudio.patch new file mode 100644 index 00000000..10679550 --- /dev/null +++ b/patches/sapi-ISpObjectToken-CreateInstance/0004-sapi-ISpObjectToken-CreateInstance-support-ISpAudio.patch @@ -0,0 +1,308 @@ +From ac7314c8ec757deacc97e9945bd549ad75206c47 Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Thu, 16 Sep 2021 15:27:51 +1000 +Subject: [PATCH 4/4] sapi: ISpObjectToken CreateInstance support ISpAudio + +--- + dlls/sapi/token.c | 279 +++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 278 insertions(+), 1 deletion(-) + +diff --git a/dlls/sapi/token.c b/dlls/sapi/token.c +index ba91a425e9e..ab94a148c7e 100644 +--- a/dlls/sapi/token.c ++++ b/dlls/sapi/token.c +@@ -968,13 +968,290 @@ static HRESULT WINAPI token_GetCategory( ISpObjectToken *iface, + return E_NOTIMPL; + } + ++struct speech_audio ++{ ++ ISpAudio ISpAudio_iface; ++ LONG ref; ++}; ++ ++static inline struct speech_audio *impl_from_ISpAudio(ISpAudio *iface) ++{ ++ return CONTAINING_RECORD(iface, struct speech_audio, ISpAudio_iface); ++} ++ ++static HRESULT WINAPI spaudio_QueryInterface(ISpAudio *iface, REFIID iid, void **obj) ++{ ++ struct speech_audio *audio = impl_from_ISpAudio(iface); ++ ++ TRACE("(%p, %s %p).\n", audio, debugstr_guid(iid), obj); ++ ++ if (IsEqualIID(iid, &IID_IUnknown) || ++ IsEqualIID(iid, &IID_ISequentialStream) || ++ IsEqualIID(iid, &IID_IStream) || ++ IsEqualIID(iid, &IID_ISpStreamFormat) || ++ IsEqualIID(iid, &IID_ISpAudio)) ++ *obj = &audio->ISpAudio_iface; ++ else ++ { ++ *obj = NULL; ++ FIXME("interface %s not implemented.\n", debugstr_guid(iid)); ++ return E_NOINTERFACE; ++ } ++ ++ IUnknown_AddRef((IUnknown *)*obj); ++ return S_OK; ++} ++ ++static ULONG WINAPI spaudio_AddRef(ISpAudio *iface) ++{ ++ struct speech_audio *audio = impl_from_ISpAudio(iface); ++ ULONG ref = InterlockedIncrement(&audio->ref); ++ ++ TRACE("(%p): ref=%u.\n", audio, ref); ++ ++ return ref; ++} ++ ++static ULONG WINAPI spaudio_Release(ISpAudio *iface) ++{ ++ struct speech_audio *audio = impl_from_ISpAudio(iface); ++ ULONG ref = InterlockedDecrement(&audio->ref); ++ ++ TRACE("(%p): ref=%u.\n", audio, ref); ++ ++ if (!ref) ++ { ++ heap_free(audio); ++ } ++ ++ return ref; ++} ++ ++static HRESULT WINAPI spaudio_Read(ISpAudio *iface,void *pv, ULONG cb, ULONG *pcbRead) ++{ ++ struct speech_audio *audio = impl_from_ISpAudio(iface); ++ ++ FIXME("%p, %p, %d %p\n", audio, pv, cb, pcbRead); ++ ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI spaudio_Write(ISpAudio *iface, const void *pv, ULONG cb, ULONG *pcbWritten) ++{ ++ struct speech_audio *audio = impl_from_ISpAudio(iface); ++ ++ FIXME("%p, %p, %d %p\n", audio, pv, cb, pcbWritten); ++ ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI spaudio_Seek(ISpAudio *iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition) ++{ ++ struct speech_audio *audio = impl_from_ISpAudio(iface); ++ FIXME("%p, %s, %d, %p\n", audio, wine_dbgstr_longlong(dlibMove.QuadPart), dwOrigin, plibNewPosition); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI spaudio_SetSize(ISpAudio *iface, ULARGE_INTEGER libNewSize) ++{ ++ struct speech_audio *audio = impl_from_ISpAudio(iface); ++ FIXME("(%p, %s)\n", audio, wine_dbgstr_longlong(libNewSize.QuadPart)); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI spaudio_CopyTo(ISpAudio *iface,IStream *pstm, ULARGE_INTEGER cb, ++ ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten) ++{ ++ struct speech_audio *audio = impl_from_ISpAudio(iface); ++ FIXME("(%p, %p, %s, %p, %p)\n", audio, pstm, wine_dbgstr_longlong(cb.QuadPart), pcbRead, pcbWritten); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI spaudio_Commit(ISpAudio *iface,DWORD grfCommitFlags) ++{ ++ struct speech_audio *audio = impl_from_ISpAudio(iface); ++ FIXME("(%p, %#x)\n", audio, grfCommitFlags); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI spaudio_Revert(ISpAudio *iface) ++{ ++ struct speech_audio *audio = impl_from_ISpAudio(iface); ++ FIXME("(%p)\n", audio); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI spaudio_LockRegion(ISpAudio *iface, ULARGE_INTEGER offset, ULARGE_INTEGER cb, DWORD dwLockType) ++{ ++ struct speech_audio *audio = impl_from_ISpAudio(iface); ++ FIXME("(%p, %s, %s, %d)\n", audio, wine_dbgstr_longlong(offset.QuadPart), ++ wine_dbgstr_longlong(cb.QuadPart), dwLockType); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI spaudio_UnlockRegion(ISpAudio *iface,ULARGE_INTEGER offset, ULARGE_INTEGER cb, DWORD dwLockType) ++{ ++ struct speech_audio *audio = impl_from_ISpAudio(iface); ++ FIXME("(%p, %s, %s, %d)\n", audio, wine_dbgstr_longlong(offset.QuadPart), ++ wine_dbgstr_longlong(cb.QuadPart), dwLockType); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI spaudio_Stat(ISpAudio *iface, STATSTG *stg, DWORD flag) ++{ ++ struct speech_audio *audio = impl_from_ISpAudio(iface); ++ FIXME("%p, %p, %d\n", audio, stg, flag); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI spaudio_Clone(ISpAudio *iface, IStream **ppstm) ++{ ++ struct speech_audio *audio = impl_from_ISpAudio(iface); ++ FIXME("%p, %p\n", audio, ppstm); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI spaudio_GetFormat(ISpAudio *iface, GUID *format, WAVEFORMATEX **wave) ++{ ++ struct speech_audio *audio = impl_from_ISpAudio(iface); ++ FIXME("%p, %p, %p\n", audio, format, wave); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI spaudio_SetState(ISpAudio *iface, SPAUDIOSTATE state, ULONGLONG reserved) ++{ ++ struct speech_audio *audio = impl_from_ISpAudio(iface); ++ FIXME("%p, %d, %s\n", audio, state, wine_dbgstr_longlong(reserved)); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI spaudio_SetFormat(ISpAudio *iface, REFGUID guid, const WAVEFORMATEX *wave) ++{ ++ struct speech_audio *audio = impl_from_ISpAudio(iface); ++ FIXME("%p, %s, %p\n", audio, debugstr_guid(guid), wave); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI spaudio_GetStatus(ISpAudio *iface, SPAUDIOSTATUS *status) ++{ ++ struct speech_audio *audio = impl_from_ISpAudio(iface); ++ FIXME("%p, %p\n", audio, status); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI spaudio_SetBufferInfo(ISpAudio *iface,const SPAUDIOBUFFERINFO *buffer) ++{ ++ struct speech_audio *audio = impl_from_ISpAudio(iface); ++ FIXME("%p, %p\n", audio, buffer); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI spaudio_GetBufferInfo(ISpAudio *iface, SPAUDIOBUFFERINFO *buffer) ++{ ++ struct speech_audio *audio = impl_from_ISpAudio(iface); ++ FIXME("%p, %p\n", audio, buffer); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI spaudio_GetDefaultFormat(ISpAudio *iface, GUID *guid, WAVEFORMATEX **wave) ++{ ++ struct speech_audio *audio = impl_from_ISpAudio(iface); ++ FIXME("%p, %p, %p\n", audio, guid, wave); ++ return E_NOTIMPL; ++} ++ ++static HANDLE WINAPI spaudio_EventHandle(ISpAudio *iface) ++{ ++ struct speech_audio *audio = impl_from_ISpAudio(iface); ++ FIXME("%p\n", audio); ++ return NULL; ++} ++ ++static HRESULT WINAPI spaudio_GetVolumeLevel(ISpAudio *iface, ULONG *level) ++{ ++ struct speech_audio *audio = impl_from_ISpAudio(iface); ++ FIXME("%p, %p\n", audio, level); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI spaudio_SetVolumeLevel(ISpAudio *iface, ULONG level) ++{ ++ struct speech_audio *audio = impl_from_ISpAudio(iface); ++ FIXME("%p, %d\n", audio, level); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI spaudio_GetBufferNotifySize(ISpAudio *iface, ULONG *size) ++{ ++ struct speech_audio *audio = impl_from_ISpAudio(iface); ++ FIXME("%p, %p\n", audio, size); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI spaudio_SetBufferNotifySize(ISpAudio *iface, ULONG size) ++{ ++ struct speech_audio *audio = impl_from_ISpAudio(iface); ++ FIXME("%p, %d\n", audio, size); ++ return E_NOTIMPL; ++} ++ ++const struct ISpAudioVtbl spaudio_vtbl = ++{ ++ spaudio_QueryInterface, ++ spaudio_AddRef, ++ spaudio_Release, ++ spaudio_Read, ++ spaudio_Write, ++ spaudio_Seek, ++ spaudio_SetSize, ++ spaudio_CopyTo, ++ spaudio_Commit, ++ spaudio_Revert, ++ spaudio_LockRegion, ++ spaudio_UnlockRegion, ++ spaudio_Stat, ++ spaudio_Clone, ++ spaudio_GetFormat, ++ spaudio_SetState, ++ spaudio_SetFormat, ++ spaudio_GetStatus, ++ spaudio_SetBufferInfo, ++ spaudio_GetBufferInfo, ++ spaudio_GetDefaultFormat, ++ spaudio_EventHandle, ++ spaudio_GetVolumeLevel, ++ spaudio_SetVolumeLevel, ++ spaudio_GetBufferNotifySize, ++ spaudio_SetBufferNotifySize ++}; ++ ++static HRESULT speech_audio_create(void **obj) ++{ ++ struct speech_audio *This = heap_alloc(sizeof(*This)); ++ ++ if (!This) ++ return E_OUTOFMEMORY; ++ This->ISpAudio_iface.lpVtbl = &spaudio_vtbl; ++ This->ref = 1; ++ ++ *obj = &This->ISpAudio_iface; ++ return S_OK; ++} ++ + static HRESULT WINAPI token_CreateInstance( ISpObjectToken *iface, + IUnknown *outer, + DWORD class_context, + REFIID riid, + void **object ) + { +- FIXME( "stub\n" ); ++ struct object_token *This = impl_from_ISpObjectToken( iface ); ++ ++ FIXME( "(%p)->(%p 0x%08x %s, %p): semi-stub\n", This, outer, class_context, debugstr_guid( riid ), object); ++ ++ if (IsEqualIID(riid, &IID_ISpAudio)) ++ { ++ return speech_audio_create(object); ++ } + return E_NOTIMPL; + } + +-- +2.33.0 + diff --git a/patches/sapi-ISpObjectToken-CreateInstance/definition b/patches/sapi-ISpObjectToken-CreateInstance/definition new file mode 100644 index 00000000..252cc275 --- /dev/null +++ b/patches/sapi-ISpObjectToken-CreateInstance/definition @@ -0,0 +1,2 @@ +Fixes: [49641] sapi: Implement ISpObjectToken-CreateInstance +