Needed for Diablo 4's screen reader.
-- v3: sapi: Implement IStream methods for SpStream. sapi: Implement ISpStream::GetFormat.
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 | 62 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 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..6cb21851ee4 100644 --- a/dlls/sapi/tests/stream.c +++ b/dlls/sapi/tests/stream.c @@ -86,9 +86,71 @@ 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); + IStream_Release(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 6cb21851ee4..f7190db202b 100644 --- a/dlls/sapi/tests/stream.c +++ b/dlls/sapi/tests/stream.c @@ -142,6 +142,18 @@ static void test_spstream(void) ok(base_stream2 == base_stream, "got %p.\n", base_stream2); IStream_Release(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 | 22 ++++++++++++++++++++-- 2 files changed, 44 insertions(+), 5 deletions(-)
diff --git a/dlls/sapi/stream.c b/dlls/sapi/stream.c index f0b4e2cd595..b0e5c2d5d0a 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 = CoTaskMemAlloc(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 f7190db202b..5d28ab13d95 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);
@@ -142,6 +145,18 @@ static void test_spstream(void) ok(base_stream2 == base_stream, "got %p.\n", base_stream2); IStream_Release(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"); + CoTaskMemFree(wfx2); + hr = ISpStream_Close(stream); ok(hr == S_OK, "got %#lx.\n", hr);
@@ -151,6 +166,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 b0e5c2d5d0a..41826b8c949 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 5d28ab13d95..cd90cb00399 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);
@@ -157,6 +190,40 @@ static void test_spstream(void) ok(!memcmp(wfx, wfx2, sizeof(WAVEFORMATEX)), "wfx mismatch.\n"); CoTaskMemFree(wfx2);
+ /* 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);
@@ -169,6 +236,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);
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=150890
Your paranoid android.
=== debian11b (64 bit WoW report) ===
user32: input.c:4305: Test succeeded inside todo block: button_down_hwnd_todo 1: got MSG_TEST_WIN hwnd 0000000000CE00F4, msg WM_LBUTTONDOWN, wparam 0x1, lparam 0x320032
This merge request was approved by Huw Davies.