Nikolay Sivov : wshom: Create standard streams when starting new process with Exec().
Alexandre Julliard
julliard at winehq.org
Mon Feb 21 16:15:12 CST 2022
Module: wine
Branch: master
Commit: a51400101905a21f65151d8ef879348ff5e50942
URL: https://source.winehq.org/git/wine.git/?a=commit;h=a51400101905a21f65151d8ef879348ff5e50942
Author: Nikolay Sivov <nsivov at codeweavers.com>
Date: Sun Feb 20 17:09:16 2022 +0300
wshom: Create standard streams when starting new process with Exec().
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
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)
More information about the wine-cvs
mailing list