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