Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)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;
}
--
2.33.0