2 * CONSOLE.C - console input/output functions.
7 * 20-Jan-1999 (Eric Kohl)
10 * 03-Apr-2005 (Magnus Olsen <magnus@greatlord.com>)
11 * Remove all hardcoded strings in En.rc
13 * 01-Jul-2005 (Brandon Turner <turnerb7@msu.edu>)
14 * Added ConPrintfPaging and ConOutPrintfPaging
16 * 02-Feb-2007 (Paolo Devoti <devotip at gmail.com>)
17 * Fixed ConPrintfPaging
22 #define OUTPUT_BUFFER_SIZE 4096
29 BOOL
IsConsoleHandle(HANDLE hHandle
)
33 /* Check whether the handle may be that of a console... */
34 if ((GetFileType(hHandle
) & ~FILE_TYPE_REMOTE
) != FILE_TYPE_CHAR
)
38 * It may be. Perform another test... The idea comes from the
39 * MSDN description of the WriteConsole API:
41 * "WriteConsole fails if it is used with a standard handle
42 * that is redirected to a file. If an application processes
43 * multilingual output that can be redirected, determine whether
44 * the output handle is a console handle (one method is to call
45 * the GetConsoleMode function and check whether it succeeds).
46 * If the handle is a console handle, call WriteConsole. If the
47 * handle is not a console handle, the output is redirected and
48 * you should call WriteFile to perform the I/O."
50 return GetConsoleMode(hHandle
, &dwMode
);
53 VOID
ConInDisable(VOID
)
55 HANDLE hInput
= GetStdHandle(STD_INPUT_HANDLE
);
58 GetConsoleMode(hInput
, &dwMode
);
59 dwMode
&= ~ENABLE_PROCESSED_INPUT
;
60 SetConsoleMode(hInput
, dwMode
);
64 VOID
ConInEnable(VOID
)
66 HANDLE hInput
= GetStdHandle(STD_INPUT_HANDLE
);
69 GetConsoleMode(hInput
, &dwMode
);
70 dwMode
|= ENABLE_PROCESSED_INPUT
;
71 SetConsoleMode(hInput
, dwMode
);
75 VOID
ConInFlush (VOID
)
77 FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE
));
81 VOID
ConInKey(PINPUT_RECORD lpBuffer
)
83 HANDLE hInput
= GetStdHandle(STD_INPUT_HANDLE
);
86 if (hInput
== INVALID_HANDLE_VALUE
)
87 WARN ("Invalid input handle!!!\n");
91 ReadConsoleInput(hInput
, lpBuffer
, 1, &dwRead
);
92 if ((lpBuffer
->EventType
== KEY_EVENT
) &&
93 (lpBuffer
->Event
.KeyEvent
.bKeyDown
== TRUE
))
100 VOID
ConInString(LPTSTR lpInput
, DWORD dwLength
)
110 pBuf
= (PCHAR
)cmd_alloc(dwLength
- 1);
114 ZeroMemory(lpInput
, dwLength
* sizeof(TCHAR
));
115 hFile
= GetStdHandle(STD_INPUT_HANDLE
);
116 GetConsoleMode(hFile
, &dwOldMode
);
118 SetConsoleMode(hFile
, ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
);
120 ReadFile(hFile
, (PVOID
)pBuf
, dwLength
- 1, &dwRead
, NULL
);
123 MultiByteToWideChar(InputCodePage
, 0, pBuf
, dwRead
, lpInput
, dwLength
- 1);
126 for (p
= lpInput
; *p
; p
++)
128 if (*p
== _T('\x0d'))
135 SetConsoleMode(hFile
, dwOldMode
);
138 static VOID
ConWrite(TCHAR
*str
, DWORD len
, DWORD nStdHandle
)
141 HANDLE hOutput
= GetStdHandle(nStdHandle
);
144 /* Check whether we are writing to a console and if so, write to it */
145 if (IsConsoleHandle(hOutput
))
147 if (WriteConsole(hOutput
, str
, len
, &dwWritten
, NULL
))
151 /* We're writing to a file or pipe instead of the console. Convert the
152 * string from TCHARs to the desired output format, if the two differ */
156 WCHAR
*buffer
= cmd_alloc(len
* sizeof(WCHAR
));
159 error_out_of_memory();
162 len
= (DWORD
)MultiByteToWideChar(OutputCodePage
, 0, str
, (INT
)len
, buffer
, (INT
)len
);
166 * Find any newline character in the buffer,
167 * send the part BEFORE the newline, then send
168 * a carriage-return + newline, and then send
169 * the remaining part of the buffer.
171 * This fixes output in files and serial console.
173 while (str
&& *(PWCHAR
)str
&& len
> 0)
175 p
= wcspbrk((PWCHAR
)str
, L
"\r\n");
178 len
-= ((PWCHAR
)p
- (PWCHAR
)str
) + 1;
179 WriteFile(hOutput
, str
, ((PWCHAR
)p
- (PWCHAR
)str
) * sizeof(WCHAR
), &dwWritten
, NULL
);
180 WriteFile(hOutput
, L
"\r\n", 2 * sizeof(WCHAR
), &dwWritten
, NULL
);
181 str
= (PVOID
)((PWCHAR
)p
+ 1);
185 WriteFile(hOutput
, str
, len
* sizeof(WCHAR
), &dwWritten
, NULL
);
190 // WriteFile(hOutput, str, len * sizeof(WCHAR), &dwWritten, NULL);
198 CHAR
*buffer
= cmd_alloc(len
* MB_LEN_MAX
* sizeof(CHAR
));
201 error_out_of_memory();
204 len
= WideCharToMultiByte(OutputCodePage
, 0, str
, len
, buffer
, len
* MB_LEN_MAX
, NULL
, NULL
);
208 * Find any newline character in the buffer,
209 * send the part BEFORE the newline, then send
210 * a carriage-return + newline, and then send
211 * the remaining part of the buffer.
213 * This fixes output in files and serial console.
215 while (str
&& *(PCHAR
)str
&& len
> 0)
217 p
= strpbrk((PCHAR
)str
, "\r\n");
220 len
-= ((PCHAR
)p
- (PCHAR
)str
) + 1;
221 WriteFile(hOutput
, str
, ((PCHAR
)p
- (PCHAR
)str
), &dwWritten
, NULL
);
222 WriteFile(hOutput
, "\r\n", 2, &dwWritten
, NULL
);
223 str
= (PVOID
)((PCHAR
)p
+ 1);
227 WriteFile(hOutput
, str
, len
, &dwWritten
, NULL
);
232 // WriteFile(hOutput, str, len, &dwWritten, NULL);
239 VOID
ConOutChar(TCHAR c
)
241 ConWrite(&c
, 1, STD_OUTPUT_HANDLE
);
244 VOID
ConPuts(LPTSTR szText
, DWORD nStdHandle
)
246 ConWrite(szText
, (DWORD
)_tcslen(szText
), nStdHandle
);
249 VOID
ConOutResPaging(BOOL NewPage
, UINT resID
)
251 TCHAR szMsg
[RC_STRING_MAX_SIZE
];
252 LoadString(CMD_ModuleHandle
, resID
, szMsg
, RC_STRING_MAX_SIZE
);
253 ConOutPrintfPaging(NewPage
, szMsg
);
256 VOID
ConOutResPuts(UINT resID
)
258 TCHAR szMsg
[RC_STRING_MAX_SIZE
];
259 LoadString(CMD_ModuleHandle
, resID
, szMsg
, RC_STRING_MAX_SIZE
);
260 ConPuts(szMsg
, STD_OUTPUT_HANDLE
);
263 VOID
ConOutPuts(LPTSTR szText
)
265 ConPuts(szText
, STD_OUTPUT_HANDLE
);
269 VOID
ConPrintf(LPTSTR szFormat
, va_list arg_ptr
, DWORD nStdHandle
)
271 TCHAR szOut
[OUTPUT_BUFFER_SIZE
];
274 len
= (DWORD
)_vstprintf(szOut
, szFormat
, arg_ptr
);
275 ConWrite(szOut
, len
, nStdHandle
);
278 INT
ConPrintfPaging(BOOL NewPage
, LPTSTR szFormat
, va_list arg_ptr
, DWORD nStdHandle
)
281 CONSOLE_SCREEN_BUFFER_INFO csbi
;
282 TCHAR szOut
[OUTPUT_BUFFER_SIZE
];
284 HANDLE hOutput
= GetStdHandle(nStdHandle
);
286 /* used to count number of lines since last pause */
287 static int LineCount
= 0;
289 /* used to see how big the screen is */
292 /* chars since start of line */
300 /* rest LineCount and return if no string have been given */
301 if (szFormat
== NULL
)
304 /* Get the size of the visual screen that can be printed too */
305 if (!IsConsoleHandle(hOutput
) || !GetConsoleScreenBufferInfo(hOutput
, &csbi
))
307 /* We assume it's a file handle */
308 ConPrintf(szFormat
, arg_ptr
, nStdHandle
);
311 /* Subtract 2 to account for "press any key..." and for the blank line at the end of PagePrompt() */
312 ScreenLines
= (csbi
.srWindow
.Bottom
- csbi
.srWindow
.Top
) - 4;
313 CharSL
= csbi
.dwCursorPosition
.X
;
315 /* Make sure they didn't make the screen to small */
318 ConPrintf(szFormat
, arg_ptr
, nStdHandle
);
322 len
= _vstprintf(szOut
, szFormat
, arg_ptr
);
326 /* Search until the end of a line is reached */
327 if (szOut
[i
++] != _T('\n') && ++CharSL
< csbi
.dwSize
.X
)
333 if (LineCount
>= ScreenLines
)
335 WriteConsole(hOutput
, &szOut
[from
], i
-from
, &dwWritten
, NULL
);
338 if (PagePrompt() != PROMPT_YES
)
342 /* Reset the number of lines being printed */
347 WriteConsole(hOutput
, &szOut
[from
], i
-from
, &dwWritten
, NULL
);
352 VOID
ConErrFormatMessage(DWORD MessageId
, ...)
354 TCHAR szMsg
[RC_STRING_MAX_SIZE
];
359 va_start(arg_ptr
, MessageId
);
360 ret
= FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
,
363 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
376 LoadString(CMD_ModuleHandle
, STRING_CONSOLE_ERROR
, szMsg
, RC_STRING_MAX_SIZE
);
381 VOID
ConOutFormatMessage(DWORD MessageId
, ...)
383 TCHAR szMsg
[RC_STRING_MAX_SIZE
];
388 va_start(arg_ptr
, MessageId
);
389 ret
= FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
,
392 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
405 LoadString(CMD_ModuleHandle
, STRING_CONSOLE_ERROR
, szMsg
, RC_STRING_MAX_SIZE
);
410 VOID
ConOutResPrintf(UINT resID
, ...)
412 TCHAR szMsg
[RC_STRING_MAX_SIZE
];
415 va_start(arg_ptr
, resID
);
416 LoadString(CMD_ModuleHandle
, resID
, szMsg
, RC_STRING_MAX_SIZE
);
417 ConPrintf(szMsg
, arg_ptr
, STD_OUTPUT_HANDLE
);
421 VOID
ConOutPrintf(LPTSTR szFormat
, ...)
425 va_start(arg_ptr
, szFormat
);
426 ConPrintf(szFormat
, arg_ptr
, STD_OUTPUT_HANDLE
);
430 INT
ConOutPrintfPaging(BOOL NewPage
, LPTSTR szFormat
, ...)
435 va_start(arg_ptr
, szFormat
);
436 iReturn
= ConPrintfPaging(NewPage
, szFormat
, arg_ptr
, STD_OUTPUT_HANDLE
);
441 VOID
ConErrChar(TCHAR c
)
443 ConWrite(&c
, 1, STD_ERROR_HANDLE
);
447 VOID
ConErrResPuts(UINT resID
)
449 TCHAR szMsg
[RC_STRING_MAX_SIZE
];
450 LoadString(CMD_ModuleHandle
, resID
, szMsg
, RC_STRING_MAX_SIZE
);
451 ConPuts(szMsg
, STD_ERROR_HANDLE
);
454 VOID
ConErrPuts(LPTSTR szText
)
456 ConPuts(szText
, STD_ERROR_HANDLE
);
460 VOID
ConErrResPrintf(UINT resID
, ...)
462 TCHAR szMsg
[RC_STRING_MAX_SIZE
];
465 va_start(arg_ptr
, resID
);
466 LoadString(CMD_ModuleHandle
, resID
, szMsg
, RC_STRING_MAX_SIZE
);
467 ConPrintf(szMsg
, arg_ptr
, STD_ERROR_HANDLE
);
471 VOID
ConErrPrintf(LPTSTR szFormat
, ...)
475 va_start(arg_ptr
, szFormat
);
476 ConPrintf(szFormat
, arg_ptr
, STD_ERROR_HANDLE
);
481 VOID
SetCursorXY(SHORT x
, SHORT y
)
487 SetConsoleCursorPosition(GetStdHandle (STD_OUTPUT_HANDLE
), coPos
);
490 VOID
GetCursorXY(PSHORT x
, PSHORT y
)
492 CONSOLE_SCREEN_BUFFER_INFO csbi
;
494 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE
), &csbi
);
496 *x
= csbi
.dwCursorPosition
.X
;
497 *y
= csbi
.dwCursorPosition
.Y
;
500 SHORT
GetCursorX(VOID
)
502 CONSOLE_SCREEN_BUFFER_INFO csbi
;
504 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE
), &csbi
);
505 return csbi
.dwCursorPosition
.X
;
508 SHORT
GetCursorY(VOID
)
510 CONSOLE_SCREEN_BUFFER_INFO csbi
;
512 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE
), &csbi
);
513 return csbi
.dwCursorPosition
.Y
;
516 VOID
SetCursorType(BOOL bInsert
, BOOL bVisible
)
518 CONSOLE_CURSOR_INFO cci
;
520 cci
.dwSize
= bInsert
? 10 : 99;
521 cci
.bVisible
= bVisible
;
523 SetConsoleCursorInfo(GetStdHandle (STD_OUTPUT_HANDLE
), &cci
);
526 VOID
GetScreenSize(PSHORT maxx
, PSHORT maxy
)
528 CONSOLE_SCREEN_BUFFER_INFO csbi
;
530 if (!GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE
), &csbi
))
536 if (maxx
) *maxx
= csbi
.dwSize
.X
;
537 if (maxy
) *maxy
= csbi
.dwSize
.Y
;