Signed-off-by: Alistair Leslie-Hughes leslie_alistair@hotmail.com --- dlls/sapi/tests/token.c | 22 ++++ dlls/sapi/token.c | 283 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 304 insertions(+), 1 deletion(-)
diff --git a/dlls/sapi/tests/token.c b/dlls/sapi/tests/token.c index 47196d42dc7..fdb30975b1b 100644 --- a/dlls/sapi/tests/token.c +++ b/dlls/sapi/tests/token.c @@ -297,6 +297,27 @@ static void test_object_token(void) ISpObjectToken_Release( token ); }
+static void test_token_create_instance(void) +{ + ISpObjectToken *token; + HRESULT hr; + ISpAudio *audio; + + hr = CoCreateInstance( &CLSID_SpObjectToken, NULL, CLSCTX_INPROC_SERVER, + &IID_ISpObjectToken, (void **)&token ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = ISpObjectToken_SetId( token, NULL, L"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\AudioOutput\TokenEnums\MMAudioOut\", FALSE ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = ISpObjectToken_CreateInstance( token, NULL, CLSCTX_ALL, &IID_ISpAudio, (void**)&audio); + ok( hr == S_OK, "got %08x\n", hr ); + if (hr == S_OK) + ISpAudio_Release(audio); + + ISpObjectToken_Release( token ); +} + START_TEST(token) { CoInitialize( NULL ); @@ -305,5 +326,6 @@ START_TEST(token) test_token_enum(); test_default_token_id(); test_object_token(); + test_token_create_instance(); CoUninitialize(); } diff --git a/dlls/sapi/token.c b/dlls/sapi/token.c index ba91a425e9e..c7ab034c94f 100644 --- a/dlls/sapi/token.c +++ b/dlls/sapi/token.c @@ -968,13 +968,294 @@ 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 *audio; + + audio = heap_alloc(sizeof(*audio)); + if (!audio) + return E_OUTOFMEMORY; + + audio->ISpAudio_iface.lpVtbl = &spaudio_vtbl; + audio->ref = 1; + + *obj = &audio->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 ); + + TRACE( "(%p)->(%p 0x%08x %s, %p)\n", This, outer, class_context, debugstr_guid( riid ), object); + + if (IsEqualIID(riid, &IID_ISpAudio)) + { + return speech_audio_create(object); + } + + FIXME( "Unsupported interface %s\n", debugstr_guid( riid )); return E_NOTIMPL; }
On 9/28/21 12:36 PM, Alistair Leslie-Hughes wrote:
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 );
- TRACE( "(%p)->(%p 0x%08x %s, %p)\n", This, outer, class_context, debugstr_guid( riid ), object);
- if (IsEqualIID(riid, &IID_ISpAudio))
- {
return speech_audio_create(object);
- }
- FIXME( "Unsupported interface %s\n", debugstr_guid( riid )); return E_NOTIMPL;
}
This doesn't look right. I think it should do normal object activation, on a CLSID stored one way or another (indirectly via SetID maybe?).