Needed for Diablo 4's screen reader.
From: Shaun Ren sren@codeweavers.com
--- dlls/sapi/stream.c | 3 +++ dlls/sapi/tests/stream.c | 27 ++++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/dlls/sapi/stream.c b/dlls/sapi/stream.c index 5cd64125ade..c3ecdf42697 100644 --- a/dlls/sapi/stream.c +++ b/dlls/sapi/stream.c @@ -52,6 +52,9 @@ static HRESULT WINAPI spstream_QueryInterface(ISpStream *iface, REFIID iid, void TRACE("(%p, %s, %p).\n", iface, debugstr_guid(iid), obj);
if (IsEqualIID(iid, &IID_IUnknown) || + IsEqualIID(iid, &IID_ISequentialStream) || + IsEqualIID(iid, &IID_IStream) || + IsEqualIID(iid, &IID_ISpStreamFormat) || IsEqualIID(iid, &IID_ISpStream)) *obj = &This->ISpStream_iface; else diff --git a/dlls/sapi/tests/stream.c b/dlls/sapi/tests/stream.c index ea2608eed36..ee9a7648aa8 100644 --- a/dlls/sapi/tests/stream.c +++ b/dlls/sapi/tests/stream.c @@ -36,14 +36,17 @@ static void _expect_ref(IUnknown *obj, ULONG ref, int line)
static void test_interfaces(void) { + ISpStreamFormat *stream_format; + ISequentialStream *seq_stream; ISpStream *speech_stream; IDispatch *dispatch; + IStream *stream; IUnknown *unk; HRESULT hr;
hr = CoCreateInstance(&CLSID_SpStream, NULL, CLSCTX_INPROC_SERVER, &IID_ISpStream, (void **)&speech_stream); - ok(hr == S_OK, "Failed to create ISpeechVoice interface: %#lx.\n", hr); + ok(hr == S_OK, "Failed to create ISpStream interface: %#lx.\n", hr); EXPECT_REF(speech_stream, 1);
hr = CoCreateInstance(&CLSID_SpStream, NULL, CLSCTX_INPROC_SERVER, @@ -58,6 +61,28 @@ static void test_interfaces(void) ok(hr == E_NOINTERFACE, "Succeeded to create IDispatch interface: %#lx.\n", hr); ok(!dispatch, "Expected NULL dispatch, got %p.", dispatch);
+ hr = CoCreateInstance(&CLSID_SpStream, NULL, CLSCTX_INPROC_SERVER, + &IID_ISequentialStream, (void **)&seq_stream); + ok(hr == S_OK, "Failed to create ISequentialStream interface: %#lx.\n", hr); + EXPECT_REF(seq_stream, 1); + EXPECT_REF(speech_stream, 1); + ISequentialStream_Release(seq_stream); + + hr = CoCreateInstance(&CLSID_SpStream, NULL, CLSCTX_INPROC_SERVER, + &IID_IStream, (void **)&stream); + ok(hr == S_OK, "Failed to create IStream interface: %#lx.\n", hr); + EXPECT_REF(stream, 1); + EXPECT_REF(speech_stream, 1); + IStream_Release(stream); + + hr = CoCreateInstance(&CLSID_SpStream, NULL, CLSCTX_INPROC_SERVER, + &IID_ISpStreamFormat, (void **)&stream_format); + ok(hr == S_OK, "Failed to create ISpStreamFormat interface: %#lx.\n", hr); + EXPECT_REF(stream_format, 1); + EXPECT_REF(speech_stream, 1); + ISpStreamFormat_Release(stream_format); + + ISpStream_Release(speech_stream); }
From: Shaun Ren sren@codeweavers.com
--- dlls/sapi/stream.c | 52 ++++++++++++++++++++++++++++++---- dlls/sapi/tests/stream.c | 61 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 5 deletions(-)
diff --git a/dlls/sapi/stream.c b/dlls/sapi/stream.c index c3ecdf42697..ae0e8c048c9 100644 --- a/dlls/sapi/stream.c +++ b/dlls/sapi/stream.c @@ -27,6 +27,7 @@ #include "objbase.h"
#include "sapiddk.h" +#include "sperror.h"
#include "wine/debug.h"
@@ -38,6 +39,10 @@ struct spstream { ISpStream ISpStream_iface; LONG ref; + + IStream *base_stream; + GUID format; + WAVEFORMATEX *wfx; };
static inline struct spstream *impl_from_ISpStream(ISpStream *iface) @@ -87,6 +92,8 @@ static ULONG WINAPI spstream_Release(ISpStream *iface)
if (!ref) { + if (This->base_stream) IStream_Release(This->base_stream); + free(This->wfx); free(This); }
@@ -182,18 +189,49 @@ static HRESULT WINAPI spstream_GetFormat(ISpStream *iface, GUID *format, WAVEFOR }
static HRESULT WINAPI spstream_SetBaseStream(ISpStream *iface, IStream *stream, REFGUID format, - const WAVEFORMATEX *wave) + const WAVEFORMATEX *wfx) { - FIXME("(%p, %p, %s, %p): stub.\n", iface, stream, debugstr_guid(format), wave); + struct spstream *This = impl_from_ISpStream(iface);
- return E_NOTIMPL; + TRACE("(%p, %p, %s, %p).\n", iface, stream, debugstr_guid(format), wfx); + + if (!stream || !format) + return E_INVALIDARG; + + if (This->base_stream) + return SPERR_ALREADY_INITIALIZED; + + This->format = *format; + if (IsEqualGUID(format, &SPDFID_WaveFormatEx)) + { + if (!wfx) + return E_INVALIDARG; + if (!(This->wfx = malloc(sizeof(WAVEFORMATEX) + wfx->cbSize))) + return E_OUTOFMEMORY; + memcpy(This->wfx, wfx, sizeof(WAVEFORMATEX) + wfx->cbSize); + } + + IStream_AddRef(stream); + This->base_stream = stream; + return S_OK; }
static HRESULT WINAPI spstream_GetBaseStream(ISpStream *iface, IStream **stream) { - FIXME("(%p, %p): stub.\n", iface, stream); + struct spstream *This = impl_from_ISpStream(iface);
- return E_NOTIMPL; + TRACE("(%p, %p).\n", iface, stream); + + if (!stream) + return E_INVALIDARG; + + if (!This->base_stream) + return SPERR_UNINITIALIZED; + + *stream = This->base_stream; + if (*stream) + IStream_AddRef(*stream); + return S_OK; }
static HRESULT WINAPI spstream_BindToFile(ISpStream *iface, LPCWSTR filename, SPFILEMODE mode, @@ -245,6 +283,10 @@ HRESULT speech_stream_create(IUnknown *outer, REFIID iid, void **obj) This->ISpStream_iface.lpVtbl = &spstream_vtbl; This->ref = 1;
+ This->base_stream = NULL; + This->format = GUID_NULL; + This->wfx = NULL; + hr = ISpStream_QueryInterface(&This->ISpStream_iface, iid, obj);
ISpStream_Release(&This->ISpStream_iface); diff --git a/dlls/sapi/tests/stream.c b/dlls/sapi/tests/stream.c index ee9a7648aa8..1cdff241e0b 100644 --- a/dlls/sapi/tests/stream.c +++ b/dlls/sapi/tests/stream.c @@ -86,9 +86,70 @@ static void test_interfaces(void) ISpStream_Release(speech_stream); }
+static void test_spstream(void) +{ + ISpStream *stream; + ISpMMSysAudio *mmaudio; + IStream *base_stream, *base_stream2; + GUID fmtid; + WAVEFORMATEX *wfx = NULL; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_SpMMAudioOut, NULL, CLSCTX_INPROC_SERVER, + &IID_ISpMMSysAudio, (void **)&mmaudio); + ok(hr == S_OK, "Failed to create ISpMMSysAudio interface: %#lx.\n", hr); + + hr = ISpMMSysAudio_GetFormat(mmaudio, &fmtid, &wfx); + ok(hr == S_OK, "got %#lx.\n", hr); + ok(IsEqualGUID(&fmtid, &SPDFID_WaveFormatEx), "got %s.\n", wine_dbgstr_guid(&fmtid)); + + hr = ISpMMSysAudio_QueryInterface(mmaudio, &IID_IStream, (void **)&base_stream); + ok(hr == S_OK, "Failed to get IStream interface from mmaudio: %#lx.\n", hr); + + hr = CoCreateInstance(&CLSID_SpStream, NULL, CLSCTX_INPROC_SERVER, + &IID_ISpStream, (void **)&stream); + ok(hr == S_OK, "Failed to create ISpStream interface: %#lx.\n", hr); + + hr = ISpStream_SetBaseStream(stream, NULL, NULL, NULL); + ok(hr == E_INVALIDARG, "got %#lx.\n", hr); + + hr = ISpStream_SetBaseStream(stream, base_stream, NULL, NULL); + ok(hr == E_INVALIDARG, "got %#lx.\n", hr); + + hr = ISpStream_GetBaseStream(stream, &base_stream2); + ok(hr == SPERR_UNINITIALIZED, "got %#lx.\n", hr); + + hr = ISpStream_SetBaseStream(stream, base_stream, &SPDFID_Text, NULL); + ok(hr == S_OK, "got %#lx.\n", hr); + + hr = ISpStream_SetBaseStream(stream, base_stream, &fmtid, wfx); + ok(hr == SPERR_ALREADY_INITIALIZED, "got %#lx.\n", hr); + + ISpStream_Release(stream); + + hr = CoCreateInstance(&CLSID_SpStream, NULL, CLSCTX_INPROC_SERVER, + &IID_ISpStream, (void **)&stream); + ok(hr == S_OK, "Failed to create ISpStream interface: %#lx.\n", hr); + + hr = ISpStream_SetBaseStream(stream, base_stream, &SPDFID_WaveFormatEx, NULL); + ok(hr == E_INVALIDARG, "got %#lx.\n", hr); + + hr = ISpStream_SetBaseStream(stream, base_stream, &SPDFID_WaveFormatEx, wfx); + ok(hr == S_OK, "got %#lx.\n", hr); + + hr = ISpStream_GetBaseStream(stream, &base_stream2); + ok(hr == S_OK, "got %#lx.\n", hr); + ok(base_stream2 == base_stream, "got %p.\n", base_stream2); + + ISpStream_Release(stream); + IStream_Release(base_stream); + ISpMMSysAudio_Release(mmaudio); +} + START_TEST(stream) { CoInitialize(NULL); test_interfaces(); + test_spstream(); CoUninitialize(); }
From: Shaun Ren sren@codeweavers.com
--- dlls/sapi/stream.c | 22 ++++++++++++++++++---- dlls/sapi/tests/stream.c | 12 ++++++++++++ 2 files changed, 30 insertions(+), 4 deletions(-)
diff --git a/dlls/sapi/stream.c b/dlls/sapi/stream.c index ae0e8c048c9..f0b4e2cd595 100644 --- a/dlls/sapi/stream.c +++ b/dlls/sapi/stream.c @@ -43,6 +43,7 @@ struct spstream IStream *base_stream; GUID format; WAVEFORMATEX *wfx; + BOOL closed; };
static inline struct spstream *impl_from_ISpStream(ISpStream *iface) @@ -198,7 +199,7 @@ static HRESULT WINAPI spstream_SetBaseStream(ISpStream *iface, IStream *stream, if (!stream || !format) return E_INVALIDARG;
- if (This->base_stream) + if (This->base_stream || This->closed) return SPERR_ALREADY_INITIALIZED;
This->format = *format; @@ -225,7 +226,9 @@ static HRESULT WINAPI spstream_GetBaseStream(ISpStream *iface, IStream **stream) if (!stream) return E_INVALIDARG;
- if (!This->base_stream) + if (This->closed) + return SPERR_STREAM_CLOSED; + else if (!This->base_stream) return SPERR_UNINITIALIZED;
*stream = This->base_stream; @@ -246,9 +249,19 @@ static HRESULT WINAPI spstream_BindToFile(ISpStream *iface, LPCWSTR filename, SP
static HRESULT WINAPI spstream_Close(ISpStream *iface) { - FIXME("(%p): stub.\n", iface); + struct spstream *This = impl_from_ISpStream(iface);
- return E_NOTIMPL; + TRACE("(%p).\n", iface); + + if (This->closed) + return SPERR_STREAM_CLOSED; + else if (!This->base_stream) + return SPERR_UNINITIALIZED; + + IStream_Release(This->base_stream); + This->base_stream = NULL; + This->closed = TRUE; + return S_OK; }
const static ISpStreamVtbl spstream_vtbl = @@ -286,6 +299,7 @@ HRESULT speech_stream_create(IUnknown *outer, REFIID iid, void **obj) This->base_stream = NULL; This->format = GUID_NULL; This->wfx = NULL; + This->closed = FALSE;
hr = ISpStream_QueryInterface(&This->ISpStream_iface, iid, obj);
diff --git a/dlls/sapi/tests/stream.c b/dlls/sapi/tests/stream.c index 1cdff241e0b..e07bbdb50c6 100644 --- a/dlls/sapi/tests/stream.c +++ b/dlls/sapi/tests/stream.c @@ -141,6 +141,18 @@ static void test_spstream(void) ok(hr == S_OK, "got %#lx.\n", hr); ok(base_stream2 == base_stream, "got %p.\n", base_stream2);
+ hr = ISpStream_Close(stream); + ok(hr == S_OK, "got %#lx.\n", hr); + + hr = ISpStream_SetBaseStream(stream, base_stream, &fmtid, wfx); + ok(hr == SPERR_ALREADY_INITIALIZED, "got %#lx.\n", hr); + + hr = ISpStream_GetBaseStream(stream, &base_stream2); + ok(hr == SPERR_STREAM_CLOSED, "got %#lx.\n", hr); + + hr = ISpStream_Close(stream); + ok(hr == SPERR_STREAM_CLOSED, "got %#lx.\n", hr); + ISpStream_Release(stream); IStream_Release(base_stream); ISpMMSysAudio_Release(mmaudio);
From: Shaun Ren sren@codeweavers.com
--- dlls/sapi/stream.c | 27 ++++++++++++++++++++++++--- dlls/sapi/tests/stream.c | 21 +++++++++++++++++++-- 2 files changed, 43 insertions(+), 5 deletions(-)
diff --git a/dlls/sapi/stream.c b/dlls/sapi/stream.c index f0b4e2cd595..4fe86b19014 100644 --- a/dlls/sapi/stream.c +++ b/dlls/sapi/stream.c @@ -182,11 +182,32 @@ static HRESULT WINAPI spstream_Clone(ISpStream *iface, IStream **stream) return E_NOTIMPL; }
-static HRESULT WINAPI spstream_GetFormat(ISpStream *iface, GUID *format, WAVEFORMATEX **wave) +static HRESULT WINAPI spstream_GetFormat(ISpStream *iface, GUID *format, WAVEFORMATEX **wfx) { - FIXME("(%p, %p, %p): stub.\n", iface, format, wave); + struct spstream *This = impl_from_ISpStream(iface);
- return E_NOTIMPL; + TRACE("(%p, %p, %p).\n", iface, format, wfx); + + if (!format) + return E_POINTER; + + if (This->closed) + return SPERR_STREAM_CLOSED; + else if (!This->base_stream) + return SPERR_UNINITIALIZED; + + if (This->wfx) + { + if (!wfx) + return E_POINTER; + if (!(*wfx = malloc(sizeof(WAVEFORMATEX) + This->wfx->cbSize))) + return E_OUTOFMEMORY; + memcpy(*wfx, This->wfx, sizeof(WAVEFORMATEX) + This->wfx->cbSize); + } + + *format = This->format; + + return S_OK; }
static HRESULT WINAPI spstream_SetBaseStream(ISpStream *iface, IStream *stream, REFGUID format, diff --git a/dlls/sapi/tests/stream.c b/dlls/sapi/tests/stream.c index e07bbdb50c6..6613f7ea723 100644 --- a/dlls/sapi/tests/stream.c +++ b/dlls/sapi/tests/stream.c @@ -91,8 +91,8 @@ static void test_spstream(void) ISpStream *stream; ISpMMSysAudio *mmaudio; IStream *base_stream, *base_stream2; - GUID fmtid; - WAVEFORMATEX *wfx = NULL; + GUID fmtid, fmtid2; + WAVEFORMATEX *wfx = NULL, *wfx2 = NULL; HRESULT hr;
hr = CoCreateInstance(&CLSID_SpMMAudioOut, NULL, CLSCTX_INPROC_SERVER, @@ -131,6 +131,9 @@ static void test_spstream(void) &IID_ISpStream, (void **)&stream); ok(hr == S_OK, "Failed to create ISpStream interface: %#lx.\n", hr);
+ hr = ISpStream_GetFormat(stream, &fmtid2, &wfx2); + ok(hr == SPERR_UNINITIALIZED, "got %#lx.\n", hr); + hr = ISpStream_SetBaseStream(stream, base_stream, &SPDFID_WaveFormatEx, NULL); ok(hr == E_INVALIDARG, "got %#lx.\n", hr);
@@ -141,6 +144,17 @@ static void test_spstream(void) ok(hr == S_OK, "got %#lx.\n", hr); ok(base_stream2 == base_stream, "got %p.\n", base_stream2);
+ hr = ISpStream_GetFormat(stream, NULL, NULL); + ok(hr == E_POINTER, "got %#lx.\n", hr); + + hr = ISpStream_GetFormat(stream, &fmtid2, NULL); + ok(hr == E_POINTER, "got %#lx.\n", hr); + + hr = ISpStream_GetFormat(stream, &fmtid2, &wfx2); + ok(hr == S_OK, "got %#lx.\n", hr); + ok(IsEqualGUID(&fmtid2, &SPDFID_WaveFormatEx), "got %s.\n", wine_dbgstr_guid(&fmtid2)); + ok(!memcmp(wfx, wfx2, sizeof(WAVEFORMATEX)), "wfx mismatch.\n"); + hr = ISpStream_Close(stream); ok(hr == S_OK, "got %#lx.\n", hr);
@@ -150,6 +164,9 @@ static void test_spstream(void) hr = ISpStream_GetBaseStream(stream, &base_stream2); ok(hr == SPERR_STREAM_CLOSED, "got %#lx.\n", hr);
+ hr = ISpStream_GetFormat(stream, &fmtid2, &wfx2); + ok(hr == SPERR_STREAM_CLOSED, "got %#lx.\n", hr); + hr = ISpStream_Close(stream); ok(hr == SPERR_STREAM_CLOSED, "got %#lx.\n", hr);
From: Shaun Ren sren@codeweavers.com
--- dlls/sapi/stream.c | 113 +++++++++++++++++++++++++++++++-------- dlls/sapi/tests/stream.c | 112 +++++++++++++++++++++++++++++++++++--- 2 files changed, 197 insertions(+), 28 deletions(-)
diff --git a/dlls/sapi/stream.c b/dlls/sapi/stream.c index 4fe86b19014..9037bf52334 100644 --- a/dlls/sapi/stream.c +++ b/dlls/sapi/stream.c @@ -103,81 +103,150 @@ static ULONG WINAPI spstream_Release(ISpStream *iface)
static HRESULT WINAPI spstream_Read(ISpStream *iface, void *pv, ULONG cb, ULONG *read) { - FIXME("(%p, %p, %ld, %p): stub.\n", iface, pv, cb, read); + struct spstream *This = impl_from_ISpStream(iface);
- return E_NOTIMPL; + TRACE("(%p, %p, %ld, %p).\n", iface, pv, cb, read); + + if (This->closed) + return SPERR_STREAM_CLOSED; + else if (!This->base_stream) + return SPERR_UNINITIALIZED; + + return IStream_Read(This->base_stream, pv, cb, read); }
static HRESULT WINAPI spstream_Write(ISpStream *iface, const void *pv, ULONG cb, ULONG *written) { - FIXME("(%p, %p, %ld, %p): stub.\n", iface, pv, cb, written); + struct spstream *This = impl_from_ISpStream(iface);
- return E_NOTIMPL; + TRACE("(%p, %p, %ld, %p).\n", iface, pv, cb, written); + + if (This->closed) + return SPERR_STREAM_CLOSED; + else if (!This->base_stream) + return SPERR_UNINITIALIZED; + + return IStream_Write(This->base_stream, pv, cb, written); }
static HRESULT WINAPI spstream_Seek(ISpStream *iface, LARGE_INTEGER mode, DWORD origin, ULARGE_INTEGER *position) { - FIXME("(%p, %s, %ld, %p): stub.\n", iface, wine_dbgstr_longlong(mode.QuadPart), origin, position); + struct spstream *This = impl_from_ISpStream(iface);
- return E_NOTIMPL; + TRACE("(%p, %s, %ld, %p).\n", iface, wine_dbgstr_longlong(mode.QuadPart), origin, position); + + if (This->closed) + return SPERR_STREAM_CLOSED; + else if (!This->base_stream) + return SPERR_UNINITIALIZED; + + return IStream_Seek(This->base_stream, mode, origin, position); }
static HRESULT WINAPI spstream_SetSize(ISpStream *iface, ULARGE_INTEGER size) { - FIXME("(%p, %s): stub.\n", iface, wine_dbgstr_longlong(size.QuadPart)); + struct spstream *This = impl_from_ISpStream(iface);
- return E_NOTIMPL; + TRACE("(%p, %s).\n", iface, wine_dbgstr_longlong(size.QuadPart)); + + if (This->closed) + return SPERR_STREAM_CLOSED; + else if (!This->base_stream) + return SPERR_UNINITIALIZED; + + return IStream_SetSize(This->base_stream, size); }
static HRESULT WINAPI spstream_CopyTo(ISpStream *iface, IStream *stream, ULARGE_INTEGER cb, ULARGE_INTEGER *read, ULARGE_INTEGER *written) { - FIXME("(%p, %p, %s, %p, %p): stub.\n", iface, stream, wine_dbgstr_longlong(cb.QuadPart), - read, written); + struct spstream *This = impl_from_ISpStream(iface);
- return E_NOTIMPL; + TRACE("(%p, %p, %s, %p, %p).\n", iface, stream, wine_dbgstr_longlong(cb.QuadPart), read, written); + + if (This->closed) + return SPERR_STREAM_CLOSED; + else if (!This->base_stream) + return SPERR_UNINITIALIZED; + + return IStream_CopyTo(This->base_stream, stream, cb, read, written); }
static HRESULT WINAPI spstream_Commit(ISpStream *iface, DWORD flag) { - FIXME("(%p, %ld): stub.\n", iface, flag); + struct spstream *This = impl_from_ISpStream(iface);
- return E_NOTIMPL; + TRACE("(%p, %ld).\n", iface, flag); + + if (This->closed) + return SPERR_STREAM_CLOSED; + else if (!This->base_stream) + return SPERR_UNINITIALIZED; + + return IStream_Commit(This->base_stream, flag); }
static HRESULT WINAPI spstream_Revert(ISpStream *iface) { - FIXME("(%p): stub.\n", iface); + struct spstream *This = impl_from_ISpStream(iface);
- return E_NOTIMPL; + TRACE("(%p).\n", iface); + + if (This->closed) + return SPERR_STREAM_CLOSED; + else if (!This->base_stream) + return SPERR_UNINITIALIZED; + + return IStream_Revert(This->base_stream); }
static HRESULT WINAPI spstream_LockRegion(ISpStream *iface, ULARGE_INTEGER offset, ULARGE_INTEGER cb, DWORD type) { - FIXME("(%p, %s, %s, %ld): stub.\n", iface, wine_dbgstr_longlong(offset.QuadPart), + struct spstream *This = impl_from_ISpStream(iface); + + TRACE("(%p, %s, %s, %ld).\n", iface, wine_dbgstr_longlong(offset.QuadPart), wine_dbgstr_longlong(cb.QuadPart), type);
- return E_NOTIMPL; + if (This->closed) + return SPERR_STREAM_CLOSED; + else if (!This->base_stream) + return SPERR_UNINITIALIZED; + + return IStream_LockRegion(This->base_stream, offset, cb, type); }
static HRESULT WINAPI spstream_UnlockRegion(ISpStream *iface, ULARGE_INTEGER offset, ULARGE_INTEGER cb, DWORD type) { - FIXME("(%p, %s, %s, %ld): stub.\n", iface, wine_dbgstr_longlong(offset.QuadPart), + struct spstream *This = impl_from_ISpStream(iface); + + TRACE("(%p, %s, %s, %ld).\n", iface, wine_dbgstr_longlong(offset.QuadPart), wine_dbgstr_longlong(cb.QuadPart), type);
- return E_NOTIMPL; + if (This->closed) + return SPERR_STREAM_CLOSED; + else if (!This->base_stream) + return SPERR_UNINITIALIZED; + + return IStream_UnlockRegion(This->base_stream, offset, cb, type); }
static HRESULT WINAPI spstream_Stat(ISpStream *iface, STATSTG *statstg, DWORD flag) { - FIXME("(%p, %p, %ld): stub.\n", iface, statstg, flag); + struct spstream *This = impl_from_ISpStream(iface);
- return E_NOTIMPL; + TRACE("(%p, %p, %ld).\n", iface, statstg, flag); + + if (This->closed) + return SPERR_STREAM_CLOSED; + else if (!This->base_stream) + return SPERR_UNINITIALIZED; + + return IStream_Stat(This->base_stream, statstg, flag); }
static HRESULT WINAPI spstream_Clone(ISpStream *iface, IStream **stream) { - FIXME("(%p, %p): stub.\n", iface, stream); + TRACE("(%p, %p).\n", iface, stream);
return E_NOTIMPL; } diff --git a/dlls/sapi/tests/stream.c b/dlls/sapi/tests/stream.c index 6613f7ea723..7920eed9b7f 100644 --- a/dlls/sapi/tests/stream.c +++ b/dlls/sapi/tests/stream.c @@ -93,6 +93,11 @@ static void test_spstream(void) IStream *base_stream, *base_stream2; GUID fmtid, fmtid2; WAVEFORMATEX *wfx = NULL, *wfx2 = NULL; + char buf[4] = {0}; + ULONG read, written; + LARGE_INTEGER zero = {0}; + ULARGE_INTEGER uzero = {0}, size, pos; + STATSTG statstg; HRESULT hr;
hr = CoCreateInstance(&CLSID_SpMMAudioOut, NULL, CLSCTX_INPROC_SERVER, @@ -110,12 +115,6 @@ static void test_spstream(void) &IID_ISpStream, (void **)&stream); ok(hr == S_OK, "Failed to create ISpStream interface: %#lx.\n", hr);
- hr = ISpStream_SetBaseStream(stream, NULL, NULL, NULL); - ok(hr == E_INVALIDARG, "got %#lx.\n", hr); - - hr = ISpStream_SetBaseStream(stream, base_stream, NULL, NULL); - ok(hr == E_INVALIDARG, "got %#lx.\n", hr); - hr = ISpStream_GetBaseStream(stream, &base_stream2); ok(hr == SPERR_UNINITIALIZED, "got %#lx.\n", hr);
@@ -131,6 +130,40 @@ static void test_spstream(void) &IID_ISpStream, (void **)&stream); ok(hr == S_OK, "Failed to create ISpStream interface: %#lx.\n", hr);
+ hr = ISpStream_Read(stream, buf, sizeof(buf), &read); + ok(hr == SPERR_UNINITIALIZED, "got %#lx.\n", hr); + + hr = ISpStream_Write(stream, buf, sizeof(buf), &written); + ok(hr == SPERR_UNINITIALIZED, "got %#lx.\n", hr); + + hr = ISpStream_Seek(stream, zero, STREAM_SEEK_CUR, &pos); + ok(hr == SPERR_UNINITIALIZED, "got %#lx.\n", hr); + + size.QuadPart = 4; + hr = ISpStream_SetSize(stream, size); + ok(hr == SPERR_UNINITIALIZED, "got %#lx.\n", hr); + + hr = ISpStream_CopyTo(stream, NULL, size, NULL, NULL); + ok(hr == SPERR_UNINITIALIZED, "got %#lx.\n", hr); + + hr = ISpStream_Commit(stream, 0); + ok(hr == SPERR_UNINITIALIZED, "got %#lx.\n", hr); + + hr = ISpStream_Revert(stream); + ok(hr == SPERR_UNINITIALIZED, "got %#lx.\n", hr); + + hr = ISpStream_LockRegion(stream, uzero, size, LOCK_WRITE); + ok(hr == SPERR_UNINITIALIZED, "got %#lx.\n", hr); + + hr = ISpStream_UnlockRegion(stream, uzero, size, LOCK_WRITE); + ok(hr == SPERR_UNINITIALIZED, "got %#lx.\n", hr); + + hr = ISpStream_Stat(stream, &statstg, 0); + ok(hr == SPERR_UNINITIALIZED, "got %#lx.\n", hr); + + hr = ISpStream_Clone(stream, NULL); + ok(hr == E_NOTIMPL, "got %#lx.\n", hr); + hr = ISpStream_GetFormat(stream, &fmtid2, &wfx2); ok(hr == SPERR_UNINITIALIZED, "got %#lx.\n", hr);
@@ -155,6 +188,40 @@ static void test_spstream(void) ok(IsEqualGUID(&fmtid2, &SPDFID_WaveFormatEx), "got %s.\n", wine_dbgstr_guid(&fmtid2)); ok(!memcmp(wfx, wfx2, sizeof(WAVEFORMATEX)), "wfx mismatch.\n");
+ /* TODO: Many IStream methods are not yet implemented in SpMMSysAudio. */ + hr = ISpStream_Read(stream, buf, sizeof(buf), &read); + todo_wine ok(hr == STG_E_ACCESSDENIED, "got %#lx.\n", hr); + + hr = ISpStream_Write(stream, buf, sizeof(buf), &written); + ok(hr == SP_AUDIO_STOPPED, "got %#lx.\n", hr); + + hr = ISpStream_Seek(stream, zero, STREAM_SEEK_CUR, &pos); + todo_wine ok(hr == S_OK, "got %#lx.\n", hr); + + hr = ISpStream_SetSize(stream, size); + todo_wine ok(hr == S_OK, "got %#lx.\n", hr); + + hr = ISpStream_CopyTo(stream, NULL, size, NULL, NULL); + todo_wine ok(hr == STG_E_ACCESSDENIED, "got %#lx.\n", hr); + + hr = ISpStream_Commit(stream, 0); + todo_wine ok(hr == S_OK, "got %#lx.\n", hr); + + hr = ISpStream_Revert(stream); + ok(hr == E_NOTIMPL, "got %#lx.\n", hr); + + hr = ISpStream_LockRegion(stream, uzero, size, LOCK_WRITE); + ok(hr == E_NOTIMPL, "got %#lx.\n", hr); + + hr = ISpStream_UnlockRegion(stream, uzero, size, LOCK_WRITE); + ok(hr == E_NOTIMPL, "got %#lx.\n", hr); + + hr = ISpStream_Stat(stream, &statstg, 0); + todo_wine ok(hr == S_OK, "got %#lx.\n", hr); + + hr = ISpStream_Clone(stream, NULL); + ok(hr == E_NOTIMPL, "got %#lx.\n", hr); + hr = ISpStream_Close(stream); ok(hr == S_OK, "got %#lx.\n", hr);
@@ -167,6 +234,39 @@ static void test_spstream(void) hr = ISpStream_GetFormat(stream, &fmtid2, &wfx2); ok(hr == SPERR_STREAM_CLOSED, "got %#lx.\n", hr);
+ hr = ISpStream_Read(stream, buf, sizeof(buf), &read); + ok(hr == SPERR_STREAM_CLOSED, "got %#lx.\n", hr); + + hr = ISpStream_Write(stream, buf, sizeof(buf), &written); + ok(hr == SPERR_STREAM_CLOSED, "got %#lx.\n", hr); + + hr = ISpStream_Seek(stream, zero, STREAM_SEEK_CUR, &pos); + ok(hr == SPERR_STREAM_CLOSED, "got %#lx.\n", hr); + + hr = ISpStream_SetSize(stream, size); + ok(hr == SPERR_STREAM_CLOSED, "got %#lx.\n", hr); + + hr = ISpStream_CopyTo(stream, NULL, size, NULL, NULL); + ok(hr == SPERR_STREAM_CLOSED, "got %#lx.\n", hr); + + hr = ISpStream_Commit(stream, 0); + ok(hr == SPERR_STREAM_CLOSED, "got %#lx.\n", hr); + + hr = ISpStream_Revert(stream); + ok(hr == SPERR_STREAM_CLOSED, "got %#lx.\n", hr); + + hr = ISpStream_LockRegion(stream, uzero, size, LOCK_WRITE); + ok(hr == SPERR_STREAM_CLOSED, "got %#lx.\n", hr); + + hr = ISpStream_UnlockRegion(stream, uzero, size, LOCK_WRITE); + ok(hr == SPERR_STREAM_CLOSED, "got %#lx.\n", hr); + + hr = ISpStream_Stat(stream, &statstg, 0); + ok(hr == SPERR_STREAM_CLOSED, "got %#lx.\n", hr); + + hr = ISpStream_Clone(stream, NULL); + ok(hr == E_NOTIMPL, "got %#lx.\n", hr); + hr = ISpStream_Close(stream); ok(hr == SPERR_STREAM_CLOSED, "got %#lx.\n", hr);