TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags
[wireshark-sm.git] / wsutil / console_win32.c
blob9701abd72a526fd50f96361d8deab8f510071ba9
1 /* console_win32.c
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
9 */
11 #ifdef _WIN32
13 #include <string.h>
14 #include <stdio.h>
15 #include <stdlib.h>
17 #include <glib.h>
19 #include <wsutil/application_flavor.h>
20 #include <wsutil/file_util.h>
22 #include "console_win32.h"
24 #include <fcntl.h>
25 #include <conio.h>
26 #include <windows.h>
27 #include <tchar.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.
48 static bool
49 needs_redirection(int std_handle)
51 HANDLE fd;
52 DWORD handle_type;
53 DWORD error;
55 fd = GetStdHandle(std_handle);
56 if (fd == NULL) {
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.
70 return true;
72 if (fd == INVALID_HANDLE_VALUE) {
74 * OK, I'm not when this would happen; return
75 * "no redirection" for now.
77 return false;
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
86 * console.
88 return true;
93 * Assume no redirection is needed for all other cases.
95 return false;
99 * If this application has no console window to which its standard output
100 * would go, create one.
102 void
103 create_console(void)
105 bool must_redirect_stdin;
106 bool must_redirect_stdout;
107 bool must_redirect_stderr;
109 if (stdin_capture) {
110 /* We've been handed "-i -". Don't mess with stdio. */
111 return;
114 if (has_console) {
115 return;
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)
125 return;
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
132 * command prompt).
134 if (!AttachConsole(ATTACH_PARENT_PROCESS)) {
135 /* Probably not, as we couldn't attach to the parent process's
136 console.
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
145 Wayback Machine)
147 and according to
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
152 Machine)
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. */
162 FreeConsole();
163 if (AllocConsole()) {
164 /* That succeeded. */
165 console_wait = true;
166 if (application_flavor_is_wireshark()) {
167 SetConsoleTitle(_T("Wireshark Debug Console"));
168 } else {
169 SetConsoleTitle(_T("Stratoshark Debug Console"));
171 } else {
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. */
197 has_console = true;
200 void
201 restore_pipes(void)
203 bool must_redirect_stdin;
204 bool must_redirect_stdout;
205 bool must_redirect_stderr;
207 HANDLE fd;
209 if (stdin_capture) {
210 /* We've been handed "-i -". Don't mess with stdio. */
211 return;
214 if (has_console) {
215 return;
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)
225 return;
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
235 * command prompt).
237 if (!AttachConsole(ATTACH_PARENT_PROCESS)) {
238 FreeConsole();
239 return; /* No parent - cleanup and exit */
242 if (must_redirect_stdin) {
243 ws_freopen("CONIN$", "r", stdin);
244 } else {
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. */
264 has_console = true;
267 void
268 destroy_console(void)
270 if (console_wait) {
271 printf("\n\nPress any key to exit\n");
272 _getch();
274 FreeConsole();
277 void
278 set_console_wait(bool set_console_wait)
280 console_wait = set_console_wait;
283 bool
284 get_console_wait(void)
286 return console_wait;
289 void
290 set_stdin_capture(bool set_stdin_capture)
292 stdin_capture = set_stdin_capture;
295 bool
296 get_stdin_capture(void)
298 return stdin_capture;
301 #endif /* _WIN32 */