Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/scrrun/filesystem.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-)
diff --git a/dlls/scrrun/filesystem.c b/dlls/scrrun/filesystem.c index 4794437a71d..0e51929ea54 100644 --- a/dlls/scrrun/filesystem.c +++ b/dlls/scrrun/filesystem.c @@ -609,11 +609,14 @@ static HRESULT WINAPI textstream_ReadAll(ITextStream *iface, BSTR *text) return read_from_buffer(This, This->read_buf_size, text, 0) ? S_FALSE : E_OUTOFMEMORY; }
-static HRESULT textstream_writestr(struct textstream *stream, BSTR text) +static HRESULT textstream_write(struct textstream *stream, BSTR text) { DWORD written = 0; BOOL ret;
+ if (textstream_check_iomode(stream, IOWrite)) + return CTL_E_BADFILEMODE; + if (stream->unicode) { ret = WriteFile(stream->file, text, SysStringByteLen(text), &written, NULL); return (ret && written == SysStringByteLen(text)) ? S_OK : create_error(GetLastError()); @@ -636,14 +639,11 @@ static HRESULT textstream_writestr(struct textstream *stream, BSTR text)
static HRESULT WINAPI textstream_Write(ITextStream *iface, BSTR text) { - struct textstream *This = impl_from_ITextStream(iface); - - TRACE("(%p)->(%s)\n", This, debugstr_w(text)); + struct textstream *stream = impl_from_ITextStream(iface);
- if (textstream_check_iomode(This, IOWrite)) - return CTL_E_BADFILEMODE; + TRACE("%p, %s.\n", iface, debugstr_w(text));
- return textstream_writestr(This, text); + return textstream_write(stream, text); }
static HRESULT textstream_writecrlf(struct textstream *stream) @@ -669,17 +669,14 @@ static HRESULT textstream_writecrlf(struct textstream *stream)
static HRESULT WINAPI textstream_WriteLine(ITextStream *iface, BSTR text) { - struct textstream *This = impl_from_ITextStream(iface); + struct textstream *stream = impl_from_ITextStream(iface); HRESULT hr;
- TRACE("(%p)->(%s)\n", This, debugstr_w(text)); - - if (textstream_check_iomode(This, IOWrite)) - return CTL_E_BADFILEMODE; + TRACE("%p, %s.\n", iface, debugstr_w(text));
- hr = textstream_writestr(This, text); + hr = textstream_write(stream, text); if (SUCCEEDED(hr)) - hr = textstream_writecrlf(This); + hr = textstream_writecrlf(stream); return hr; }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/scrrun/filesystem.c | 6 ++++-- dlls/scrrun/tests/filesystem.c | 2 -- 2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/dlls/scrrun/filesystem.c b/dlls/scrrun/filesystem.c index 0e51929ea54..d7ad255e517 100644 --- a/dlls/scrrun/filesystem.c +++ b/dlls/scrrun/filesystem.c @@ -791,9 +791,11 @@ static HRESULT WINAPI pipestream_ReadAll(ITextStream *iface, BSTR *text)
static HRESULT WINAPI pipestream_Write(ITextStream *iface, BSTR text) { - FIXME("%p, %s.\n", iface, debugstr_w(text)); + struct textstream *stream = impl_from_ITextStream(iface);
- return E_NOTIMPL; + TRACE("%p, %s.\n", iface, debugstr_w(text)); + + return textstream_write(stream, text); }
static HRESULT WINAPI pipestream_WriteLine(ITextStream *iface, BSTR text) diff --git a/dlls/scrrun/tests/filesystem.c b/dlls/scrrun/tests/filesystem.c index 894b6251f34..79af87591ff 100644 --- a/dlls/scrrun/tests/filesystem.c +++ b/dlls/scrrun/tests/filesystem.c @@ -2656,11 +2656,9 @@ static void test_DoOpenPipeStream(void) { str = SysAllocString(L"data"); hr = ITextStream_Write(stream_write, str); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = ITextStream_Write(stream_read, str); - todo_wine ok(hr == CTL_E_BADFILEMODE, "Unexpected hr %#lx.\n", hr);
SysFreeString(str);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/scrrun/Makefile.in | 1 + dlls/wshom.ocx/Makefile.in | 2 +- dlls/wshom.ocx/shell.c | 116 +++++++++++++++++++++++++++++++++---- 3 files changed, 106 insertions(+), 13 deletions(-)
diff --git a/dlls/scrrun/Makefile.in b/dlls/scrrun/Makefile.in index 31ef016f48e..12be899162b 100644 --- a/dlls/scrrun/Makefile.in +++ b/dlls/scrrun/Makefile.in @@ -1,4 +1,5 @@ MODULE = scrrun.dll +IMPORTLIB = scrrun IMPORTS = uuid oleaut32 version advapi32
EXTRADLLFLAGS = -Wb,--prefer-native diff --git a/dlls/wshom.ocx/Makefile.in b/dlls/wshom.ocx/Makefile.in index fed2babda33..1264e9c96a5 100644 --- a/dlls/wshom.ocx/Makefile.in +++ b/dlls/wshom.ocx/Makefile.in @@ -1,5 +1,5 @@ MODULE = wshom.ocx -IMPORTS = uuid oleaut32 ole32 shell32 user32 advapi32 +IMPORTS = uuid oleaut32 ole32 shell32 user32 advapi32 scrrun
EXTRADLLFLAGS = -Wb,--prefer-native
diff --git a/dlls/wshom.ocx/shell.c b/dlls/wshom.ocx/shell.c index 82d618b1142..d1942c73cea 100644 --- a/dlls/wshom.ocx/shell.c +++ b/dlls/wshom.ocx/shell.c @@ -25,6 +25,8 @@
#include "wine/debug.h"
+extern HRESULT WINAPI DoOpenPipeStream(HANDLE pipe, IOMode mode, ITextStream **stream); + WINE_DEFAULT_DEBUG_CHANNEL(wshom);
typedef struct @@ -64,6 +66,9 @@ typedef struct IWshExec IWshExec_iface; LONG ref; PROCESS_INFORMATION info; + ITextStream *stdin_stream; + ITextStream *stdout_stream; + ITextStream *stderr_stream; } WshExecImpl;
static inline WshCollection *impl_from_IWshCollection( IWshCollection *iface ) @@ -122,14 +127,22 @@ static ULONG WINAPI WshExec_AddRef(IWshExec *iface)
static ULONG WINAPI WshExec_Release(IWshExec *iface) { - WshExecImpl *This = impl_from_IWshExec(iface); - LONG ref = InterlockedDecrement(&This->ref); + WshExecImpl *exec = impl_from_IWshExec(iface); + LONG ref = InterlockedDecrement(&exec->ref); + TRACE("%p, refcount %ld.\n", iface, ref);
- if (!ref) { - CloseHandle(This->info.hThread); - CloseHandle(This->info.hProcess); - free(This); + if (!ref) + { + CloseHandle(exec->info.hThread); + CloseHandle(exec->info.hProcess); + if (exec->stdin_stream) + ITextStream_Release(exec->stdin_stream); + if (exec->stdout_stream) + ITextStream_Release(exec->stdout_stream); + if (exec->stderr_stream) + ITextStream_Release(exec->stderr_stream); + free(exec); }
return ref; @@ -314,10 +327,35 @@ static const IWshExecVtbl WshExecVtbl = { WshExec_Terminate };
+static HRESULT create_pipe(HANDLE *hread, HANDLE *hwrite) +{ + SECURITY_ATTRIBUTES sa; + + sa.nLength = sizeof(sa); + sa.bInheritHandle = TRUE; + sa.lpSecurityDescriptor = NULL; + + *hread = *hwrite = NULL; + if (!CreatePipe(hread, hwrite, &sa, 0)) + return HRESULT_FROM_WIN32(GetLastError()); + return S_OK; +} + +static void close_pipe(HANDLE *hread, HANDLE *hwrite) +{ + CloseHandle(*hread); + CloseHandle(*hwrite); + *hread = *hwrite = NULL; +} + static HRESULT WshExec_create(BSTR command, IWshExec **ret) { + HANDLE stdout_read, stdout_write; + HANDLE stderr_read, stderr_write; + HANDLE stdin_read, stdin_write; STARTUPINFOW si = {0}; WshExecImpl *object; + HRESULT hr;
*ret = NULL;
@@ -326,17 +364,71 @@ static HRESULT WshExec_create(BSTR command, IWshExec **ret)
object->IWshExec_iface.lpVtbl = &WshExecVtbl; object->ref = 1; + init_classinfo(&CLSID_WshExec, (IUnknown *)&object->IWshExec_iface, &object->classinfo);
- if (!CreateProcessW(NULL, command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &object->info)) + if (FAILED(hr = create_pipe(&stdin_read, &stdin_write))) { - free(object); - return HRESULT_FROM_WIN32(GetLastError()); + WARN("Failed to create stdin pipe.\n"); + goto failed; }
- init_classinfo(&CLSID_WshExec, (IUnknown *)&object->IWshExec_iface, &object->classinfo); - *ret = &object->IWshExec_iface; + if (FAILED(hr = create_pipe(&stdout_read, &stdout_write))) + { + close_pipe(&stdin_read, &stdin_write); + WARN("Failed to create stdout pipe.\n"); + goto failed; + }
- return S_OK; + if (FAILED(hr = create_pipe(&stderr_read, &stderr_write))) + { + close_pipe(&stdin_read, &stdin_write); + close_pipe(&stdout_read, &stdout_write); + WARN("Failed to create stderr pipe.\n"); + goto failed; + } + + if (SUCCEEDED(hr)) + { + SetHandleInformation(stdin_write, HANDLE_FLAG_INHERIT, 0); + SetHandleInformation(stdout_read, HANDLE_FLAG_INHERIT, 0); + SetHandleInformation(stderr_read, HANDLE_FLAG_INHERIT, 0); + } + + if (SUCCEEDED(hr)) + hr = DoOpenPipeStream(stdin_write, ForWriting, &object->stdin_stream); + if (SUCCEEDED(hr)) + hr = DoOpenPipeStream(stdout_read, ForReading, &object->stdout_stream); + if (SUCCEEDED(hr)) + hr = DoOpenPipeStream(stderr_read, ForReading, &object->stderr_stream); + + si.cb = sizeof(si); + si.hStdError = stderr_write; + si.hStdOutput = stdout_write; + si.hStdInput = stdin_read; + si.dwFlags = STARTF_USESTDHANDLES; + + if (SUCCEEDED(hr)) + { + if (!CreateProcessW(NULL, command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &object->info)) + hr = HRESULT_FROM_WIN32(GetLastError()); + } + + CloseHandle(stderr_write); + CloseHandle(stdout_write); + CloseHandle(stdin_read); + + if (SUCCEEDED(hr)) + { + *ret = &object->IWshExec_iface; + + return S_OK; + } + +failed: + + IWshExec_Release(&object->IWshExec_iface); + + return hr; }
static HRESULT WINAPI WshEnvironment_QueryInterface(IWshEnvironment *iface, REFIID riid, void **obj)
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=38210 Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/wshom.ocx/shell.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-)
diff --git a/dlls/wshom.ocx/shell.c b/dlls/wshom.ocx/shell.c index d1942c73cea..e04844458b1 100644 --- a/dlls/wshom.ocx/shell.c +++ b/dlls/wshom.ocx/shell.c @@ -230,29 +230,38 @@ static HRESULT WINAPI WshExec_get_Status(IWshExec *iface, WshExecStatus *status)
static HRESULT WINAPI WshExec_get_StdIn(IWshExec *iface, ITextStream **stream) { - WshExecImpl *This = impl_from_IWshExec(iface); + WshExecImpl *exec = impl_from_IWshExec(iface);
- FIXME("(%p)->(%p): stub\n", This, stream); + TRACE("%p, %p.\n", iface, stream);
- return E_NOTIMPL; + *stream = exec->stdin_stream; + ITextStream_AddRef(*stream); + + return S_OK; }
static HRESULT WINAPI WshExec_get_StdOut(IWshExec *iface, ITextStream **stream) { - WshExecImpl *This = impl_from_IWshExec(iface); + WshExecImpl *exec = impl_from_IWshExec(iface);
- FIXME("(%p)->(%p): stub\n", This, stream); + TRACE("%p, %p.\n", iface, stream);
- return E_NOTIMPL; + *stream = exec->stdout_stream; + ITextStream_AddRef(*stream); + + return S_OK; }
static HRESULT WINAPI WshExec_get_StdErr(IWshExec *iface, ITextStream **stream) { - WshExecImpl *This = impl_from_IWshExec(iface); + WshExecImpl *exec = impl_from_IWshExec(iface);
- FIXME("(%p)->(%p): stub\n", This, stream); + TRACE("%p, %p.\n", iface, stream);
- return E_NOTIMPL; + *stream = exec->stderr_stream; + ITextStream_AddRef(*stream); + + return S_OK; }
static HRESULT WINAPI WshExec_get_ProcessID(IWshExec *iface, DWORD *pid)