2 * Console support for MSWindows
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 2002, Jeffrey C. Foster <jfoste@woodward.com>
8 * SPDX-License-Identifier: GPL-2.0-or-later
19 #include <wsutil/application_flavor.h>
20 #include <wsutil/file_util.h>
22 #include "console_win32.h"
29 static bool has_console
; /* true if app has console */
30 static bool console_wait
; /* "Press any key..." */
31 static bool stdin_capture
; /* Don't grab stdin & stdout if true */
34 * Check whether a given standard handle needs to be redirected.
36 * If you run a Windows-subsystem program from cmd.exe on Windows XP,
37 * and you haven't redirected the handle in question, GetStdHandle()
38 * succeeds (so it doesn't return INVALID_HANDLE_VALUE or NULL), but
39 * GetFile_type fails on the results with ERROR_INVALID_HANDLE.
40 * In that case, redirection to a console is necessary.
42 * If you run it from the shell prompt in "mintty" in at least some
43 * versions of Cygwin on Windows XP, and you haven't redirected the
44 * handle in question, GetStdHandle() succeeds and returns a handle
45 * that's a pipe or socket; it appears mintty reads from it and outputs
46 * what it reads to the console.
49 needs_redirection(int std_handle
)
55 fd
= GetStdHandle(std_handle
);
58 * No standard handle. According to Microsoft's
59 * documentation for GetStdHandle(), one reason for
60 * this would be that the process is "a service on
61 * an interactive desktop"; I'm not sure whether
62 * such a process should be popping up a console.
64 * However, it also appears to be the case for
65 * the standard input and standard error, but
66 * *not* the standard output, for something run
67 * with a double-click in Windows Explorer,
68 * sow we'll say it needs redirection.
72 if (fd
== INVALID_HANDLE_VALUE
) {
74 * OK, I'm not when this would happen; return
75 * "no redirection" for now.
79 handle_type
= GetFileType(fd
);
80 if (handle_type
== FILE_TYPE_UNKNOWN
) {
81 error
= GetLastError();
82 if (error
== ERROR_INVALID_HANDLE
) {
84 * OK, this appears to be the case where we're
85 * running something in a mode that needs a
93 * Assume no redirection is needed for all other cases.
99 * If this application has no console window to which its standard output
100 * would go, create one.
105 bool must_redirect_stdin
;
106 bool must_redirect_stdout
;
107 bool must_redirect_stderr
;
110 /* We've been handed "-i -". Don't mess with stdio. */
118 /* Are the standard input, output, and error invalid handles? */
119 must_redirect_stdin
= needs_redirection(STD_INPUT_HANDLE
);
120 must_redirect_stdout
= needs_redirection(STD_OUTPUT_HANDLE
);
121 must_redirect_stderr
= needs_redirection(STD_ERROR_HANDLE
);
123 /* If none of them are invalid, we don't need to do anything. */
124 if (!must_redirect_stdin
&& !must_redirect_stdout
&& !must_redirect_stderr
)
127 /* OK, at least one of them needs to be redirected to a console;
128 try to attach to the parent process's console and, if that fails,
129 try to create one. */
131 * See if we have an existing console (i.e. we were run from a
134 if (!AttachConsole(ATTACH_PARENT_PROCESS
)) {
135 /* Probably not, as we couldn't attach to the parent process's
137 Try to create a console.
139 According to a comment on
141 http://msdn.microsoft.com/en-us/library/windows/desktop/ms681952(v=vs.85).aspx
143 (which now redirects to a docs.microsoft.com page that is
144 devoid of comments, and which is not available on the
149 http://connect.microsoft.com/VisualStudio/feedback/details/689696/installing-security-update-kb2507938-prevents-console-allocation
151 (which has disappeared, and isn't available on the Wayback
156 https://answers.microsoft.com/en-us/windows/forum/windows_xp-windows_update/kb2567680-andor-kb2507938-breaks-attachconsole-api/e8191280-2d49-4be4-9918-18486fba0afa
158 even a failed attempt to attach to another process's console
159 will cause subsequent AllocConsole() calls to fail, possibly due
160 to bugs introduced by a security patch. To work around this, we
161 do a FreeConsole() first. */
163 if (AllocConsole()) {
164 /* That succeeded. */
166 if (application_flavor_is_wireshark()) {
167 SetConsoleTitle(_T("Wireshark Debug Console"));
169 SetConsoleTitle(_T("Stratoshark Debug Console"));
172 /* On Windows XP, this still fails; FreeConsole() apparently
173 doesn't clear the state, as it does on Windows 7. */
174 return; /* couldn't create console */
178 if (must_redirect_stdin
)
179 ws_freopen("CONIN$", "r", stdin
);
180 if (must_redirect_stdout
) {
181 ws_freopen("CONOUT$", "w", stdout
);
182 fprintf(stdout
, "\n");
184 if (must_redirect_stderr
) {
185 ws_freopen("CONOUT$", "w", stderr
);
186 fprintf(stderr
, "\n");
189 /* Now register "destroy_console()" as a routine to be called just
190 before the application exits, so that we can destroy the console
191 after the user has typed a key (so that the console doesn't just
192 disappear out from under them, giving the user no chance to see
193 the message(s) we put in there). */
194 atexit(destroy_console
);
196 /* Well, we have a console now. */
203 bool must_redirect_stdin
;
204 bool must_redirect_stdout
;
205 bool must_redirect_stderr
;
210 /* We've been handed "-i -". Don't mess with stdio. */
218 /* Are the standard input, output, and error invalid handles? */
219 must_redirect_stdin
= needs_redirection(STD_INPUT_HANDLE
);
220 must_redirect_stdout
= needs_redirection(STD_OUTPUT_HANDLE
);
221 must_redirect_stderr
= needs_redirection(STD_ERROR_HANDLE
);
223 /* If none of them are invalid, we don't need to do anything. */
224 if (!must_redirect_stdin
&& !must_redirect_stdout
&& !must_redirect_stderr
)
227 if (!must_redirect_stdin
)
228 fd
= GetStdHandle(STD_INPUT_HANDLE
);
230 /* OK, at least one of them needs to be redirected to a console;
231 try to attach to the parent process's console and, if that fails,
232 cleanup and return. */
234 * See if we have an existing console (i.e. we were run from a
237 if (!AttachConsole(ATTACH_PARENT_PROCESS
)) {
239 return; /* No parent - cleanup and exit */
242 if (must_redirect_stdin
) {
243 ws_freopen("CONIN$", "r", stdin
);
245 SetStdHandle(STD_INPUT_HANDLE
, fd
);
247 if (must_redirect_stdout
) {
248 ws_freopen("CONOUT$", "w", stdout
);
249 fprintf(stdout
, "\n");
251 if (must_redirect_stderr
) {
252 ws_freopen("CONOUT$", "w", stderr
);
253 fprintf(stderr
, "\n");
256 /* Now register "destroy_console()" as a routine to be called just
257 before the application exits, so that we can destroy the console
258 after the user has typed a key (so that the console doesn't just
259 disappear out from under them, giving the user no chance to see
260 the message(s) we put in there). */
261 atexit(destroy_console
);
263 /* Well, we have a console now. */
268 destroy_console(void)
271 printf("\n\nPress any key to exit\n");
278 set_console_wait(bool set_console_wait
)
280 console_wait
= set_console_wait
;
284 get_console_wait(void)
290 set_stdin_capture(bool set_stdin_capture
)
292 stdin_capture
= set_stdin_capture
;
296 get_stdin_capture(void)
298 return stdin_capture
;