api: check the stdout reader thread exit status for failures
...and refactor the ExecuteRunDll32(). Reported-by: Jason A. Donenfeld <Jason@zx2c4.com> Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
parent
44568f81cb
commit
fb6d5b62f1
@ -1279,13 +1279,13 @@ ProcessStdout(_Inout_ PROCESS_STDOUT_STATE *State)
|
|||||||
{
|
{
|
||||||
DWORD SizeRead;
|
DWORD SizeRead;
|
||||||
if (!ReadFile(State->Stdout, State->Response + Offset, sizeof(WCHAR) * (MaxLen - Offset), &SizeRead, NULL))
|
if (!ReadFile(State->Stdout, State->Response + Offset, sizeof(WCHAR) * (MaxLen - Offset), &SizeRead, NULL))
|
||||||
return 0;
|
return ERROR_SUCCESS;
|
||||||
if (SizeRead % sizeof(WCHAR))
|
if (SizeRead % sizeof(WCHAR))
|
||||||
return 1;
|
return ERROR_INVALID_DATA;
|
||||||
Offset += SizeRead / sizeof(WCHAR);
|
Offset += SizeRead / sizeof(WCHAR);
|
||||||
State->Response[Offset] = 0;
|
State->Response[Offset] = 0;
|
||||||
}
|
}
|
||||||
return 2;
|
return ERROR_BUFFER_OVERFLOW;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DWORD WINAPI
|
static DWORD WINAPI
|
||||||
@ -1308,9 +1308,9 @@ ProcessStderr(_In_ HANDLE Stderr)
|
|||||||
WCHAR Buf[0x200];
|
WCHAR Buf[0x200];
|
||||||
DWORD SizeRead;
|
DWORD SizeRead;
|
||||||
if (!ReadFile(Stderr, Buf, sizeof(Buf), &SizeRead, NULL))
|
if (!ReadFile(Stderr, Buf, sizeof(Buf), &SizeRead, NULL))
|
||||||
return 0;
|
return ERROR_SUCCESS;
|
||||||
if (SizeRead % sizeof(WCHAR))
|
if (SizeRead % sizeof(WCHAR))
|
||||||
return 1;
|
return ERROR_INVALID_DATA;
|
||||||
SizeRead /= sizeof(WCHAR);
|
SizeRead /= sizeof(WCHAR);
|
||||||
for (DWORD i = 0; i < SizeRead; ++i)
|
for (DWORD i = 0; i < SizeRead; ++i)
|
||||||
{
|
{
|
||||||
@ -1401,33 +1401,27 @@ ExecuteRunDll32(
|
|||||||
.bInheritHandle = TRUE,
|
.bInheritHandle = TRUE,
|
||||||
.lpSecurityDescriptor =
|
.lpSecurityDescriptor =
|
||||||
SecurityAttributes ? SecurityAttributes->lpSecurityDescriptor : NULL };
|
SecurityAttributes ? SecurityAttributes->lpSecurityDescriptor : NULL };
|
||||||
typedef enum
|
HANDLE StreamRStdout = INVALID_HANDLE_VALUE, StreamRStderr = INVALID_HANDLE_VALUE,
|
||||||
{
|
StreamWStdout = INVALID_HANDLE_VALUE, StreamWStderr = INVALID_HANDLE_VALUE;
|
||||||
Stdout = 0,
|
if (!CreatePipe(&StreamRStdout, &StreamWStdout, &sa, 0) || !CreatePipe(&StreamRStderr, &StreamWStderr, &sa, 0))
|
||||||
Stderr
|
|
||||||
} stdid_t;
|
|
||||||
HANDLE StreamR[] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE },
|
|
||||||
StreamW[] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
|
|
||||||
if (!CreatePipe(&StreamR[Stdout], &StreamW[Stdout], &sa, 0) ||
|
|
||||||
!CreatePipe(&StreamR[Stderr], &StreamW[Stderr], &sa, 0))
|
|
||||||
{
|
{
|
||||||
Result = LOG_LAST_ERROR(L"Failed to create pipes");
|
Result = LOG_LAST_ERROR(L"Failed to create pipes");
|
||||||
goto cleanupPipes;
|
goto cleanupPipes;
|
||||||
}
|
}
|
||||||
if (!SetHandleInformation(StreamR[Stdout], HANDLE_FLAG_INHERIT, 0) ||
|
if (!SetHandleInformation(StreamRStdout, HANDLE_FLAG_INHERIT, 0) ||
|
||||||
!SetHandleInformation(StreamR[Stderr], HANDLE_FLAG_INHERIT, 0))
|
!SetHandleInformation(StreamRStderr, HANDLE_FLAG_INHERIT, 0))
|
||||||
{
|
{
|
||||||
Result = LOG_LAST_ERROR(L"Failed to set handle info");
|
Result = LOG_LAST_ERROR(L"Failed to set handle info");
|
||||||
goto cleanupPipes;
|
goto cleanupPipes;
|
||||||
}
|
}
|
||||||
if (ResponseCapacity)
|
if (ResponseCapacity)
|
||||||
Response[0] = 0;
|
Response[0] = 0;
|
||||||
PROCESS_STDOUT_STATE ProcessStdoutState = { .Stdout = StreamR[Stdout],
|
PROCESS_STDOUT_STATE ProcessStdoutState = { .Stdout = StreamRStdout,
|
||||||
.Response = Response,
|
.Response = Response,
|
||||||
.ResponseCapacity = ResponseCapacity };
|
.ResponseCapacity = ResponseCapacity };
|
||||||
HANDLE Thread[] = { NULL, NULL };
|
HANDLE ThreadStdout = NULL, ThreadStderr = NULL;
|
||||||
if ((Thread[Stdout] = CreateThread(SecurityAttributes, 0, ProcessStdout, &ProcessStdoutState, 0, NULL)) == NULL ||
|
if ((ThreadStdout = CreateThread(SecurityAttributes, 0, ProcessStdout, &ProcessStdoutState, 0, NULL)) == NULL ||
|
||||||
(Thread[Stderr] = CreateThread(SecurityAttributes, 0, ProcessStderr, StreamR[Stderr], 0, NULL)) == NULL)
|
(ThreadStderr = CreateThread(SecurityAttributes, 0, ProcessStderr, StreamRStderr, 0, NULL)) == NULL)
|
||||||
{
|
{
|
||||||
Result = LOG_LAST_ERROR(L"Failed to spawn reader threads");
|
Result = LOG_LAST_ERROR(L"Failed to spawn reader threads");
|
||||||
goto cleanupThreads;
|
goto cleanupThreads;
|
||||||
@ -1435,8 +1429,8 @@ ExecuteRunDll32(
|
|||||||
STARTUPINFOW si = { .cb = sizeof(STARTUPINFO),
|
STARTUPINFOW si = { .cb = sizeof(STARTUPINFO),
|
||||||
.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES,
|
.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES,
|
||||||
.wShowWindow = SW_HIDE,
|
.wShowWindow = SW_HIDE,
|
||||||
.hStdOutput = StreamW[Stdout],
|
.hStdOutput = StreamWStdout,
|
||||||
.hStdError = StreamW[Stderr] };
|
.hStdError = StreamWStderr };
|
||||||
PROCESS_INFORMATION pi;
|
PROCESS_INFORMATION pi;
|
||||||
if (!CreateProcessW(RunDll32Path, CommandLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
|
if (!CreateProcessW(RunDll32Path, CommandLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
|
||||||
{
|
{
|
||||||
@ -1447,19 +1441,29 @@ ExecuteRunDll32(
|
|||||||
CloseHandle(pi.hProcess);
|
CloseHandle(pi.hProcess);
|
||||||
CloseHandle(pi.hThread);
|
CloseHandle(pi.hThread);
|
||||||
cleanupThreads:
|
cleanupThreads:
|
||||||
for (size_t i = _countof(Thread); i--;)
|
if (ThreadStderr)
|
||||||
if (Thread[i])
|
{
|
||||||
{
|
CloseHandle(StreamWStderr);
|
||||||
CloseHandle(StreamW[i]);
|
StreamWStderr = INVALID_HANDLE_VALUE;
|
||||||
StreamW[i] = INVALID_HANDLE_VALUE;
|
WaitForSingleObject(ThreadStderr, INFINITE);
|
||||||
WaitForSingleObject(Thread[i], INFINITE);
|
CloseHandle(ThreadStderr);
|
||||||
CloseHandle(Thread[i]);
|
}
|
||||||
}
|
if (ThreadStdout)
|
||||||
|
{
|
||||||
|
CloseHandle(StreamWStdout);
|
||||||
|
StreamWStdout = INVALID_HANDLE_VALUE;
|
||||||
|
WaitForSingleObject(ThreadStdout, INFINITE);
|
||||||
|
if (!GetExitCodeThread(ThreadStdout, &Result))
|
||||||
|
Result = LOG_LAST_ERROR(L"Failed to retrieve thread result");
|
||||||
|
else if (Result != ERROR_SUCCESS)
|
||||||
|
LOG_ERROR(L"Failed to read process output", Result);
|
||||||
|
CloseHandle(ThreadStdout);
|
||||||
|
}
|
||||||
cleanupPipes:
|
cleanupPipes:
|
||||||
CloseHandle(StreamR[Stderr]);
|
CloseHandle(StreamRStderr);
|
||||||
CloseHandle(StreamW[Stderr]);
|
CloseHandle(StreamWStderr);
|
||||||
CloseHandle(StreamR[Stdout]);
|
CloseHandle(StreamRStdout);
|
||||||
CloseHandle(StreamW[Stdout]);
|
CloseHandle(StreamWStdout);
|
||||||
HeapFree(ModuleHeap, 0, CommandLine);
|
HeapFree(ModuleHeap, 0, CommandLine);
|
||||||
cleanupDelete:
|
cleanupDelete:
|
||||||
DeleteFileW(DllPath);
|
DeleteFileW(DllPath);
|
||||||
|
Loading…
Reference in New Issue
Block a user