Commit a5140010 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

wshom: Create standard streams when starting new process with Exec().

parent 0faf9c1f
MODULE = scrrun.dll MODULE = scrrun.dll
IMPORTLIB = scrrun
IMPORTS = uuid oleaut32 version advapi32 IMPORTS = uuid oleaut32 version advapi32
EXTRADLLFLAGS = -Wb,--prefer-native EXTRADLLFLAGS = -Wb,--prefer-native
......
MODULE = wshom.ocx MODULE = wshom.ocx
IMPORTS = uuid oleaut32 ole32 shell32 user32 advapi32 IMPORTS = uuid oleaut32 ole32 shell32 user32 advapi32 scrrun
EXTRADLLFLAGS = -Wb,--prefer-native EXTRADLLFLAGS = -Wb,--prefer-native
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include "wine/debug.h" #include "wine/debug.h"
extern HRESULT WINAPI DoOpenPipeStream(HANDLE pipe, IOMode mode, ITextStream **stream);
WINE_DEFAULT_DEBUG_CHANNEL(wshom); WINE_DEFAULT_DEBUG_CHANNEL(wshom);
typedef struct typedef struct
...@@ -64,6 +66,9 @@ typedef struct ...@@ -64,6 +66,9 @@ typedef struct
IWshExec IWshExec_iface; IWshExec IWshExec_iface;
LONG ref; LONG ref;
PROCESS_INFORMATION info; PROCESS_INFORMATION info;
ITextStream *stdin_stream;
ITextStream *stdout_stream;
ITextStream *stderr_stream;
} WshExecImpl; } WshExecImpl;
static inline WshCollection *impl_from_IWshCollection( IWshCollection *iface ) static inline WshCollection *impl_from_IWshCollection( IWshCollection *iface )
...@@ -122,14 +127,22 @@ static ULONG WINAPI WshExec_AddRef(IWshExec *iface) ...@@ -122,14 +127,22 @@ static ULONG WINAPI WshExec_AddRef(IWshExec *iface)
static ULONG WINAPI WshExec_Release(IWshExec *iface) static ULONG WINAPI WshExec_Release(IWshExec *iface)
{ {
WshExecImpl *This = impl_from_IWshExec(iface); WshExecImpl *exec = impl_from_IWshExec(iface);
LONG ref = InterlockedDecrement(&This->ref); LONG ref = InterlockedDecrement(&exec->ref);
TRACE("%p, refcount %ld.\n", iface, ref); TRACE("%p, refcount %ld.\n", iface, ref);
if (!ref) { if (!ref)
CloseHandle(This->info.hThread); {
CloseHandle(This->info.hProcess); CloseHandle(exec->info.hThread);
free(This); 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; return ref;
...@@ -314,10 +327,35 @@ static const IWshExecVtbl WshExecVtbl = { ...@@ -314,10 +327,35 @@ static const IWshExecVtbl WshExecVtbl = {
WshExec_Terminate 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) 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}; STARTUPINFOW si = {0};
WshExecImpl *object; WshExecImpl *object;
HRESULT hr;
*ret = NULL; *ret = NULL;
...@@ -326,17 +364,71 @@ static HRESULT WshExec_create(BSTR command, IWshExec **ret) ...@@ -326,17 +364,71 @@ static HRESULT WshExec_create(BSTR command, IWshExec **ret)
object->IWshExec_iface.lpVtbl = &WshExecVtbl; object->IWshExec_iface.lpVtbl = &WshExecVtbl;
object->ref = 1; 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); WARN("Failed to create stdin pipe.\n");
return HRESULT_FROM_WIN32(GetLastError()); goto failed;
} }
init_classinfo(&CLSID_WshExec, (IUnknown *)&object->IWshExec_iface, &object->classinfo); if (FAILED(hr = create_pipe(&stdout_read, &stdout_write)))
*ret = &object->IWshExec_iface; {
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) static HRESULT WINAPI WshEnvironment_QueryInterface(IWshEnvironment *iface, REFIID riid, void **obj)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment