2014-01-02 04:26:22 +00:00
|
|
|
/*
|
|
|
|
* conredir, a hack to get working console IO with Windows GUI applications
|
|
|
|
*
|
|
|
|
* Copyright (c) 2013, Martin Herkt
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <windows.h>
|
|
|
|
|
2019-05-10 11:01:48 +00:00
|
|
|
int wmain(int argc, wchar_t **argv, wchar_t **envp);
|
|
|
|
|
|
|
|
static void cr_perror(const wchar_t *prefix)
|
2014-01-02 04:26:22 +00:00
|
|
|
{
|
|
|
|
wchar_t *error;
|
|
|
|
|
|
|
|
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
|
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
|
|
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
|
|
NULL, GetLastError(),
|
|
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
|
|
(LPWSTR)&error, 0, NULL);
|
|
|
|
|
|
|
|
fwprintf(stderr, L"%s: %s", prefix, error);
|
|
|
|
LocalFree(error);
|
|
|
|
}
|
|
|
|
|
2019-05-10 11:01:48 +00:00
|
|
|
static int cr_runproc(wchar_t *name, wchar_t *cmdline)
|
2014-01-02 04:26:22 +00:00
|
|
|
{
|
2016-11-17 12:05:17 +00:00
|
|
|
STARTUPINFOW si;
|
|
|
|
STARTUPINFOW our_si;
|
2014-01-02 04:26:22 +00:00
|
|
|
PROCESS_INFORMATION pi;
|
2014-01-06 12:31:15 +00:00
|
|
|
DWORD retval = 1;
|
2014-01-02 04:26:22 +00:00
|
|
|
|
|
|
|
ZeroMemory(&si, sizeof(si));
|
|
|
|
si.cb = sizeof(si);
|
|
|
|
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
|
|
|
|
si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
|
|
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
|
|
|
|
si.dwFlags |= STARTF_USESTDHANDLES;
|
|
|
|
|
2016-01-06 12:08:13 +00:00
|
|
|
// Copy the list of inherited CRT file descriptors to the new process
|
|
|
|
our_si.cb = sizeof(our_si);
|
2016-11-17 12:05:17 +00:00
|
|
|
GetStartupInfoW(&our_si);
|
2016-01-06 12:08:13 +00:00
|
|
|
si.lpReserved2 = our_si.lpReserved2;
|
|
|
|
si.cbReserved2 = our_si.cbReserved2;
|
|
|
|
|
2014-01-02 04:26:22 +00:00
|
|
|
ZeroMemory(&pi, sizeof(pi));
|
|
|
|
|
|
|
|
if (!CreateProcessW(name, cmdline, NULL, NULL, TRUE, 0,
|
|
|
|
NULL, NULL, &si, &pi)) {
|
|
|
|
|
|
|
|
cr_perror(L"CreateProcess");
|
|
|
|
} else {
|
|
|
|
WaitForSingleObject(pi.hProcess, INFINITE);
|
2014-01-06 12:31:15 +00:00
|
|
|
GetExitCodeProcess(pi.hProcess, &retval);
|
2014-01-02 04:26:22 +00:00
|
|
|
CloseHandle(pi.hProcess);
|
|
|
|
CloseHandle(pi.hThread);
|
|
|
|
}
|
2014-01-06 12:31:15 +00:00
|
|
|
|
|
|
|
return (int)retval;
|
2014-01-02 04:26:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int wmain(int argc, wchar_t **argv, wchar_t **envp)
|
|
|
|
{
|
2014-01-06 12:18:02 +00:00
|
|
|
wchar_t *cmd;
|
2014-01-02 04:26:22 +00:00
|
|
|
wchar_t exe[MAX_PATH];
|
|
|
|
|
|
|
|
cmd = GetCommandLineW();
|
|
|
|
GetModuleFileNameW(NULL, exe, MAX_PATH);
|
|
|
|
wcscpy(wcsrchr(exe, '.') + 1, L"exe");
|
|
|
|
|
2015-03-29 14:19:29 +00:00
|
|
|
// Set an environment variable so the child process can tell whether it
|
|
|
|
// was started from this wrapper and attach to the console accordingly
|
|
|
|
SetEnvironmentVariableW(L"_started_from_console", L"yes");
|
|
|
|
|
2014-01-06 12:31:15 +00:00
|
|
|
return cr_runproc(exe, cmd);
|
2014-01-02 04:26:22 +00:00
|
|
|
}
|