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