|
Packit |
90a5c9 |
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
Packit |
90a5c9 |
* contributor license agreements. See the NOTICE file distributed with
|
|
Packit |
90a5c9 |
* this work for additional information regarding copyright ownership.
|
|
Packit |
90a5c9 |
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
Packit |
90a5c9 |
* (the "License"); you may not use this file except in compliance with
|
|
Packit |
90a5c9 |
* the License. You may obtain a copy of the License at
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* http://www.apache.org/licenses/LICENSE-2.0
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* Unless required by applicable law or agreed to in writing, software
|
|
Packit |
90a5c9 |
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
Packit |
90a5c9 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
Packit |
90a5c9 |
* See the License for the specific language governing permissions and
|
|
Packit |
90a5c9 |
* limitations under the License.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* --------------------------------------------------------------------
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* wintty : a Apache/WinNT support utility for monitoring and
|
|
Packit |
90a5c9 |
* reflecting user feedback from the Apache process via
|
|
Packit |
90a5c9 |
* stdin/stdout, even as running within the service context.
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* Originally contributed by William Rowe <wrowe covalent.net>
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* Note: this implementation is _very_ experimental, and error handling
|
|
Packit |
90a5c9 |
* is far from complete. Using it as a cgi or pipe process allows the
|
|
Packit |
90a5c9 |
* programmer to discover if facilities such as reliable piped logs
|
|
Packit |
90a5c9 |
* are working as expected, or answer operator prompts that would
|
|
Packit |
90a5c9 |
* otherwise be discarded by the service process.
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* Also note the isservice detection semantics, which far exceed any
|
|
Packit |
90a5c9 |
* mechanism we have discovered thus far.
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* --------------------------------------------------------------------
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#define WIN32_LEAN_AND_MEAN
|
|
Packit |
90a5c9 |
#include <windows.h>
|
|
Packit |
90a5c9 |
#include <stdlib.h>
|
|
Packit |
90a5c9 |
#include <stdio.h>
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
|
Packit |
90a5c9 |
#define _CRT_SECURE_NO_DEPRECATE
|
|
Packit |
90a5c9 |
#pragma warning(disable: 4996)
|
|
Packit |
90a5c9 |
#endif
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
const char *options =
|
|
Packit |
90a5c9 |
"\nwintty: a utility for echoing the stdin stream to a new console window,\n"
|
|
Packit |
90a5c9 |
"\teven when invoked from within a service (such as the Apache server.)\n"
|
|
Packit |
90a5c9 |
"\tAlso reflects the console input back to the stdout stream, allowing\n"
|
|
Packit |
90a5c9 |
"\tthe operator to respond to prompts from the context of a service.\n\n"
|
|
Packit |
90a5c9 |
"Syntax: %s [opts] [-t \"Window Title\"]\n\n"
|
|
Packit |
90a5c9 |
" opts: -c{haracter} or -l{ine} input\n"
|
|
Packit |
90a5c9 |
"\t-q{uiet} or -e{cho} input\n"
|
|
Packit |
90a5c9 |
"\t-u{nprocessed} or -p{rocessed} input\n"
|
|
Packit |
90a5c9 |
"\t-n{owrap} or -w{rap} output lines\n"
|
|
Packit |
90a5c9 |
"\t-f{ormatted} or -r{aw} output lines\n"
|
|
Packit |
90a5c9 |
"\t-O{output} [number of seconds]\n"
|
|
Packit |
90a5c9 |
"\t-v{erbose} error reporting (for debugging)\n"
|
|
Packit |
90a5c9 |
"\t-? for this message\n\n";
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
BOOL verbose = FALSE;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
void printerr(char *fmt, ...)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
char str[1024];
|
|
Packit |
90a5c9 |
va_list args;
|
|
Packit |
90a5c9 |
if (!verbose)
|
|
Packit |
90a5c9 |
return;
|
|
Packit |
90a5c9 |
va_start(args, fmt);
|
|
Packit |
90a5c9 |
wvsprintf(str, fmt, args);
|
|
Packit |
90a5c9 |
OutputDebugString(str);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
DWORD WINAPI feedback(LPVOID args);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
typedef struct feedback_args_t {
|
|
Packit |
90a5c9 |
HANDLE in;
|
|
Packit |
90a5c9 |
HANDLE out;
|
|
Packit |
90a5c9 |
} feedback_args_t;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
int main(int argc, char** argv)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
char str[1024], *contitle = NULL;
|
|
Packit |
90a5c9 |
HANDLE hproc, thread;
|
|
Packit |
90a5c9 |
HANDLE hwinsta = NULL, hsavewinsta;
|
|
Packit |
90a5c9 |
HANDLE hdesk = NULL, hsavedesk = NULL;
|
|
Packit |
90a5c9 |
HANDLE conin, conout;
|
|
Packit |
90a5c9 |
HANDLE hstdin, hstdout, hstderr, hdup;
|
|
Packit |
90a5c9 |
feedback_args_t feed;
|
|
Packit |
90a5c9 |
DWORD conmode;
|
|
Packit |
90a5c9 |
DWORD newinmode = 0, notinmode = 0;
|
|
Packit |
90a5c9 |
DWORD newoutmode = 0, notoutmode = 0;
|
|
Packit |
90a5c9 |
DWORD tid;
|
|
Packit |
90a5c9 |
DWORD len;
|
|
Packit |
90a5c9 |
DWORD timeout = INFINITE;
|
|
Packit |
90a5c9 |
BOOL isservice = FALSE;
|
|
Packit |
90a5c9 |
char *arg0 = argv[0];
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
while (--argc) {
|
|
Packit |
90a5c9 |
++argv;
|
|
Packit |
90a5c9 |
if (**argv == '/' || **argv == '-') {
|
|
Packit |
90a5c9 |
switch (tolower((*argv)[1])) {
|
|
Packit |
90a5c9 |
case 'c':
|
|
Packit |
90a5c9 |
notinmode |= ENABLE_LINE_INPUT; break;
|
|
Packit |
90a5c9 |
case 'l':
|
|
Packit |
90a5c9 |
newinmode |= ENABLE_LINE_INPUT; break;
|
|
Packit |
90a5c9 |
case 'q':
|
|
Packit |
90a5c9 |
notinmode |= ENABLE_ECHO_INPUT; break;
|
|
Packit |
90a5c9 |
case 'e':
|
|
Packit |
90a5c9 |
newinmode |= ENABLE_ECHO_INPUT; break;
|
|
Packit |
90a5c9 |
case 'u':
|
|
Packit |
90a5c9 |
notinmode |= ENABLE_PROCESSED_INPUT; break;
|
|
Packit |
90a5c9 |
case 'p':
|
|
Packit |
90a5c9 |
newinmode |= ENABLE_PROCESSED_INPUT; break;
|
|
Packit |
90a5c9 |
case 'n':
|
|
Packit |
90a5c9 |
notoutmode |= ENABLE_WRAP_AT_EOL_OUTPUT; break;
|
|
Packit |
90a5c9 |
case 'w':
|
|
Packit |
90a5c9 |
newoutmode |= ENABLE_WRAP_AT_EOL_OUTPUT; break;
|
|
Packit |
90a5c9 |
case 'r':
|
|
Packit |
90a5c9 |
notoutmode |= ENABLE_PROCESSED_OUTPUT; break;
|
|
Packit |
90a5c9 |
case 'f':
|
|
Packit |
90a5c9 |
newoutmode |= ENABLE_PROCESSED_OUTPUT; break;
|
|
Packit |
90a5c9 |
case 'o':
|
|
Packit |
90a5c9 |
if (*(argv + 1) && *(argv + 1)[0] != '-') {
|
|
Packit |
90a5c9 |
*(++argv);
|
|
Packit |
90a5c9 |
timeout = atoi(*argv) / 1000;
|
|
Packit |
90a5c9 |
--argc;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
timeout = 0;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
case 'v':
|
|
Packit |
90a5c9 |
verbose = TRUE;
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
case 't':
|
|
Packit |
90a5c9 |
contitle = *(++argv);
|
|
Packit |
90a5c9 |
--argc;
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
case '?':
|
|
Packit |
90a5c9 |
printf(options, arg0);
|
|
Packit |
90a5c9 |
exit(1);
|
|
Packit |
90a5c9 |
default:
|
|
Packit |
90a5c9 |
printf("wintty option %s not recognized, use -? for help.\n\n", *argv);
|
|
Packit |
90a5c9 |
exit(1);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
printf("wintty argument %s not understood, use -? for help.\n\n", *argv);
|
|
Packit |
90a5c9 |
exit(1);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
hproc = GetCurrentProcess();
|
|
Packit |
90a5c9 |
hsavewinsta = GetProcessWindowStation();
|
|
Packit |
90a5c9 |
if (!hsavewinsta || hsavewinsta == INVALID_HANDLE_VALUE) {
|
|
Packit |
90a5c9 |
printerr("GetProcessWindowStation() failed (%d)\n", GetLastError());
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (!GetUserObjectInformation(hsavewinsta, UOI_NAME, str, sizeof(str), &len)) {
|
|
Packit |
90a5c9 |
printerr("GetUserObjectInfoformation(hWinSta) failed (%d)\n", GetLastError());
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (strnicmp(str, "Service-", 8) == 0) {
|
|
Packit |
90a5c9 |
printerr("WindowStation Name %s is a service\n", str);
|
|
Packit |
90a5c9 |
isservice = TRUE;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
SetLastError(0);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
hstdin = GetStdHandle(STD_INPUT_HANDLE);
|
|
Packit |
90a5c9 |
if (!hstdin || hstdin == INVALID_HANDLE_VALUE) {
|
|
Packit |
90a5c9 |
printerr("GetStdHandle(STD_INPUT_HANDLE) failed (%d)\n",
|
|
Packit |
90a5c9 |
GetLastError());
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (DuplicateHandle(hproc, hstdin, hproc, &hdup, 0,
|
|
Packit |
90a5c9 |
isservice, DUPLICATE_SAME_ACCESS)) {
|
|
Packit |
90a5c9 |
CloseHandle(hstdin);
|
|
Packit |
90a5c9 |
hstdin = hdup;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
printerr("DupHandle(stdin [%x]) failed (%d)\n",
|
|
Packit |
90a5c9 |
hstdin, GetLastError());
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
Packit |
90a5c9 |
if (!hstdout || hstdout == INVALID_HANDLE_VALUE) {
|
|
Packit |
90a5c9 |
printerr("GetStdHandle(STD_OUTPUT_HANDLE) failed (%d)\n",
|
|
Packit |
90a5c9 |
GetLastError());
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (DuplicateHandle(hproc, hstdout, hproc, &hdup, 0,
|
|
Packit |
90a5c9 |
isservice, DUPLICATE_SAME_ACCESS)) {
|
|
Packit |
90a5c9 |
CloseHandle(hstdout);
|
|
Packit |
90a5c9 |
hstdout = hdup;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
printerr("DupHandle(stdout [%x]) failed (%d)\n",
|
|
Packit |
90a5c9 |
hstdout, GetLastError());
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
hstderr = GetStdHandle(STD_ERROR_HANDLE);
|
|
Packit |
90a5c9 |
if (!hstderr || hstderr == INVALID_HANDLE_VALUE) {
|
|
Packit |
90a5c9 |
printerr("GetStdHandle(STD_ERROR_HANDLE) failed (%d)\n",
|
|
Packit |
90a5c9 |
GetLastError());
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (DuplicateHandle(hproc, hstderr, hproc, &hdup, 0,
|
|
Packit |
90a5c9 |
isservice, DUPLICATE_SAME_ACCESS)) {
|
|
Packit |
90a5c9 |
CloseHandle(hstderr);
|
|
Packit |
90a5c9 |
hstderr = hdup;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
printerr("DupHandle(stderr [%x]) failed (%d)\n",
|
|
Packit |
90a5c9 |
hstderr, GetLastError());
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* You can't close the console till all the handles above were
|
|
Packit |
90a5c9 |
* rescued by DuplicateHandle()
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
if (!FreeConsole())
|
|
Packit |
90a5c9 |
printerr("FreeConsole() failed (%d)\n", GetLastError());
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (isservice) {
|
|
Packit |
90a5c9 |
#ifdef WE_EVER_FIGURE_OUT_WHY_THIS_DOESNT_WORK
|
|
Packit |
90a5c9 |
hsavedesk = GetThreadDesktop(GetCurrentThreadId());
|
|
Packit |
90a5c9 |
if (!hsavedesk || hsavedesk == INVALID_HANDLE_VALUE) {
|
|
Packit |
90a5c9 |
printerr("GetThreadDesktop(GetTID()) failed (%d)\n", GetLastError());
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
CloseWindowStation(hwinsta);
|
|
Packit |
90a5c9 |
hwinsta = OpenWindowStation("WinSta0", TRUE, MAXIMUM_ALLOWED);
|
|
Packit |
90a5c9 |
if (!hwinsta || hwinsta == INVALID_HANDLE_VALUE) {
|
|
Packit |
90a5c9 |
printerr("OpenWinSta(WinSta0) failed (%d)\n", GetLastError());
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (!SetProcessWindowStation(hwinsta)) {
|
|
Packit |
90a5c9 |
printerr("SetProcWinSta(WinSta0) failed (%d)\n", GetLastError());
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
hdesk = OpenDesktop("Default", 0, TRUE, MAXIMUM_ALLOWED);
|
|
Packit |
90a5c9 |
if (!hdesk || hdesk == INVALID_HANDLE_VALUE) {
|
|
Packit |
90a5c9 |
printerr("OpenDesktop(Default) failed (%d)\n", GetLastError());
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (!SetThreadDesktop(hdesk)) {
|
|
Packit |
90a5c9 |
printerr("SetThreadDesktop(Default) failed (%d)\n", GetLastError());
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
#else
|
|
Packit |
90a5c9 |
PROCESS_INFORMATION pi;
|
|
Packit |
90a5c9 |
STARTUPINFO si;
|
|
Packit |
90a5c9 |
DWORD exitcode = 1;
|
|
Packit |
90a5c9 |
char appbuff[MAX_PATH];
|
|
Packit |
90a5c9 |
char *appname = NULL;
|
|
Packit |
90a5c9 |
char *cmdline = GetCommandLine();
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!GetModuleFileName(NULL, appbuff, sizeof(appbuff))) {
|
|
Packit |
90a5c9 |
appname = appbuff;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
memset(&si, 0, sizeof(si));
|
|
Packit |
90a5c9 |
si.cb = sizeof(si);
|
|
Packit |
90a5c9 |
si.dwFlags = STARTF_USESHOWWINDOW
|
|
Packit |
90a5c9 |
| STARTF_USESTDHANDLES;
|
|
Packit |
90a5c9 |
si.lpDesktop = "WinSta0\\Default";
|
|
Packit |
90a5c9 |
si.wShowWindow = 1; /* SW_SHOWNORMAL */
|
|
Packit |
90a5c9 |
si.hStdInput = hstdin;
|
|
Packit |
90a5c9 |
si.hStdOutput = hstdout;
|
|
Packit |
90a5c9 |
si.hStdError = hstderr;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* Instantly, upon creating the new process, we will close our
|
|
Packit |
90a5c9 |
* copies of the handles so our parent isn't confused when the
|
|
Packit |
90a5c9 |
* child closes their copy of the handle. Without this action,
|
|
Packit |
90a5c9 |
* we would hold a copy of the handle, and the parent would not
|
|
Packit |
90a5c9 |
* receive their EOF notification.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
if (CreateProcess(appname, cmdline, NULL, NULL, TRUE,
|
|
Packit |
90a5c9 |
CREATE_SUSPENDED | CREATE_NEW_CONSOLE,
|
|
Packit |
90a5c9 |
NULL, NULL, &si, &pi)) {
|
|
Packit |
90a5c9 |
CloseHandle(si.hStdInput);
|
|
Packit |
90a5c9 |
CloseHandle(si.hStdOutput);
|
|
Packit |
90a5c9 |
CloseHandle(si.hStdError);
|
|
Packit |
90a5c9 |
ResumeThread(pi.hThread);
|
|
Packit |
90a5c9 |
CloseHandle(pi.hThread);
|
|
Packit |
90a5c9 |
WaitForSingleObject(pi.hProcess, INFINITE);
|
|
Packit |
90a5c9 |
GetExitCodeProcess(pi.hProcess, &exitcode);
|
|
Packit |
90a5c9 |
CloseHandle(pi.hProcess);
|
|
Packit |
90a5c9 |
return exitcode;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return 1;
|
|
Packit |
90a5c9 |
#endif
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!AllocConsole()) {
|
|
Packit |
90a5c9 |
printerr("AllocConsole(Default) failed (%d)\n", GetLastError());
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (contitle && !SetConsoleTitle(contitle)) {
|
|
Packit |
90a5c9 |
printerr("SetConsoleTitle() failed (%d)\n", GetLastError());
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
conout = CreateFile("CONOUT$", GENERIC_READ | GENERIC_WRITE,
|
|
Packit |
90a5c9 |
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
Packit |
90a5c9 |
FALSE, OPEN_EXISTING, 0, NULL);
|
|
Packit |
90a5c9 |
if (!conout || conout == INVALID_HANDLE_VALUE) {
|
|
Packit |
90a5c9 |
printerr("CreateFile(CONOUT$) failed (%d)\n", GetLastError());
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (!GetConsoleMode(conout, &conmode)) {
|
|
Packit |
90a5c9 |
printerr("GetConsoleMode(CONOUT) failed (%d)\n", GetLastError());
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (!SetConsoleMode(conout, conmode = ((conmode | newoutmode)
|
|
Packit |
90a5c9 |
& ~notoutmode))) {
|
|
Packit |
90a5c9 |
printerr("SetConsoleMode(CONOUT, 0x%x) failed (%d)\n",
|
|
Packit |
90a5c9 |
conmode, GetLastError());
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
conin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
|
|
Packit |
90a5c9 |
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
Packit |
90a5c9 |
FALSE, OPEN_EXISTING, 0, NULL);
|
|
Packit |
90a5c9 |
if (!conin || conin == INVALID_HANDLE_VALUE) {
|
|
Packit |
90a5c9 |
printerr("CreateFile(CONIN$) failed (%d)\n", GetLastError());
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (!GetConsoleMode(conin, &conmode)) {
|
|
Packit |
90a5c9 |
printerr("GetConsoleMode(CONIN) failed (%d)\n", GetLastError());
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (!SetConsoleMode(conin, conmode = ((conmode | newinmode)
|
|
Packit |
90a5c9 |
& ~notinmode))) {
|
|
Packit |
90a5c9 |
printerr("SetConsoleMode(CONIN, 0x%x) failed (%d)\n",
|
|
Packit |
90a5c9 |
conmode, GetLastError());
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
feed.in = conin;
|
|
Packit |
90a5c9 |
feed.out = hstdout;
|
|
Packit |
90a5c9 |
thread = CreateThread(NULL, 0, feedback, (LPVOID)&feed, 0, &tid;;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
while (ReadFile(hstdin, str, sizeof(str), &len, NULL))
|
|
Packit |
90a5c9 |
if (!len || !WriteFile(conout, str, len, &len, NULL))
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
printerr("[EOF] from stdin (%d)\n", GetLastError());
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
CloseHandle(stdout);
|
|
Packit |
90a5c9 |
if (!GetConsoleTitle(str, sizeof(str))) {
|
|
Packit |
90a5c9 |
printerr("SetConsoleTitle() failed (%d)\n", GetLastError());
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
strcat(str, " - [Finished]");
|
|
Packit |
90a5c9 |
if (!SetConsoleTitle(str)) {
|
|
Packit |
90a5c9 |
printerr("SetConsoleTitle() failed (%d)\n", GetLastError());
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
WaitForSingleObject(thread, timeout);
|
|
Packit |
90a5c9 |
FreeConsole();
|
|
Packit |
90a5c9 |
if (isservice) {
|
|
Packit |
90a5c9 |
if (!SetProcessWindowStation(hsavewinsta)) {
|
|
Packit |
90a5c9 |
len = GetLastError();
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (!SetThreadDesktop(hsavedesk)) {
|
|
Packit |
90a5c9 |
len = GetLastError();
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
CloseDesktop(hdesk);
|
|
Packit |
90a5c9 |
CloseWindowStation(hwinsta);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return 0;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
DWORD WINAPI feedback(LPVOID arg)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
feedback_args_t *feed = (feedback_args_t*)arg;
|
|
Packit |
90a5c9 |
char *str[1024];
|
|
Packit |
90a5c9 |
DWORD len;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
while (ReadFile(feed->in, str, sizeof(str), &len, NULL))
|
|
Packit |
90a5c9 |
if (!len || !WriteFile(feed->out, str, len, &len, NULL))
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
printerr("[EOF] from Console (%d)\n", GetLastError());
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return 0;
|
|
Packit |
90a5c9 |
}
|