Reactos

[CONUTILS] Split stream.c into input and output stream modules.

As code grows, this will allow for better maintenance of the console
stream code. In particular the input stream module will contain special
code for handling TTYs, and this is something not all console programs
will need. Having this code in a separate module will allow for the linker
to possibly remove this code when it is unused.

+1179 -958
+2
sdk/lib/conutils/CMakeLists.txt
··· 1 1 2 2 list(APPEND SOURCE 3 + # instream.c 4 + outstream.c 3 5 pager.c 4 6 screen.c 5 7 stream.c
+14 -13
sdk/lib/conutils/README.txt
··· 1 - The ReactOS Console Utilities Library v0.1 1 + The ReactOS Console Utilities Library v0.2 2 2 ========================================== 3 3 4 - COPYRIGHT: Under GPLv2, see COPYING in the top level directory. 4 + LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 5 + COPYRIGHT: Copyright 2017-2018 ReactOS Team 6 + Copyright 2017-2018 Hermes Belusca-Maito 5 7 CREDITS: Thanks to the many people who originally wrote the code that finally 6 8 ended up inside this library, with more or less refactoring, or 7 9 whose code served as a basis for some functions of the library. ··· 21 23 CONTENTS 22 24 ~-~-~-~- 23 25 24 - 0. 'conutils_base' (utils.c and utils.h): Base set of functions for loading 26 + -- Main ConUtils Library -- 27 + 28 + 0. "BASE" (utils.c and utils.h): Base set of functions for loading 25 29 string resources and message strings, and handle type identification. 26 30 27 - 1. 'conutils_stream' (stream.c and stream.h): Console Stream API (CON_STREAM): 31 + 1. "STREAM" (stream.c and stream.h, instream.c and instream.h, outstream.c 32 + and outstream.h): Console Stream API (CON_STREAM): 28 33 Stream initialization, basic ConStreamRead/Write. Stream utility functions: 29 - ConPuts/Printf, ConResPuts/Printf, ConMsgPuts/Printf. 30 - Depends on 'conutils_base'. 34 + ConPuts/Printf, ConResPuts/Printf, ConMsgPuts/Printf. Depends on "BASE". 31 35 32 - 2. 'conutils_screen' (screen.c and screen.h): Console Screen API (CON_SCREEN): 36 + 2. "SCREEN" (screen.c and screen.h): Console Screen API (CON_SCREEN): 33 37 Introduces the notion of console/terminal screen around the streams. Manages 34 38 console/terminal screen metrics for Win32 consoles and TTYs (serial...). 35 39 Additional Screen utility functions. 36 - Depends on 'conutils_stream', and indirectly on 'conutils_base'. 40 + Depends on "STREAM", and indirectly on "BASE". 37 41 38 - 3. 'conutils_pager' (pager.c and pager.h): Console Pager API (CON_PAGER): 42 + 3. "PAGER" (pager.c and pager.h): Console Pager API (CON_PAGER): 39 43 Implements core console/terminal paging functionality around console screens. 40 - Depends on 'conutils_screen' and indirectly on 'conutils_stream' and 41 - 'conutils_base'. 42 - 43 - 4. More to come! 44 + Depends on "SCREEN", and indirectly on "STREAM" and "BASE".
+13 -9
sdk/lib/conutils/conutils.h
··· 1 1 /* 2 - * COPYRIGHT: See COPYING in the top level directory 3 - * PROJECT: ReactOS Console Utilities Library 4 - * FILE: sdk/lib/conutils/conutils.h 5 - * PURPOSE: Provides simple abstraction wrappers around CRT streams or 6 - * Win32 console API I/O functions, to deal with i18n + Unicode 7 - * related problems. 8 - * PROGRAMMERS: - Hermes Belusca-Maito (for the library); 9 - * - All programmers who wrote the different console applications 10 - * from which I took those functions and improved them. 2 + * PROJECT: ReactOS Console Utilities Library 3 + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 + * PURPOSE: Provides simple abstraction wrappers around CRT streams or 5 + * Win32 console API I/O functions, to deal with i18n + Unicode 6 + * related problems. 7 + * COPYRIGHT: Copyright 2017-2018 ReactOS Team 8 + * Copyright 2017-2018 Hermes Belusca-Maito 11 9 */ 12 10 13 11 #ifndef __CONUTILS_H__ 14 12 #define __CONUTILS_H__ 15 13 14 + #pragma once 15 + 16 16 #ifndef _UNICODE 17 17 #error The ConUtils library only supports compilation with _UNICODE defined, at the moment! 18 18 #endif 19 19 20 20 #include "utils.h" 21 21 #include "stream.h" 22 + // #include "instream.h" 23 + #include "outstream.h" 22 24 #include "screen.h" 23 25 #include "pager.h" 24 26 25 27 #endif /* __CONUTILS_H__ */ 28 + 29 + /* EOF */
+49
sdk/lib/conutils/instream.c
··· 1 + /* 2 + * PROJECT: ReactOS Console Utilities Library 3 + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 + * PURPOSE: Provides basic abstraction wrappers around CRT streams or 5 + * Win32 console API I/O functions, to deal with i18n + Unicode 6 + * related problems. 7 + * COPYRIGHT: Copyright 2017-2018 ReactOS Team 8 + * Copyright 2017-2018 Hermes Belusca-Maito 9 + */ 10 + 11 + /* 12 + * Enable this define if you want to only use CRT functions to output 13 + * UNICODE stream to the console, as in the way explained by 14 + * http://archives.miloush.net/michkap/archive/2008/03/18/8306597.html 15 + */ 16 + /** NOTE: Experimental! Don't use USE_CRT yet because output to console is a bit broken **/ 17 + // #define USE_CRT 18 + 19 + /* FIXME: Temporary HACK before we cleanly support UNICODE functions */ 20 + #define UNICODE 21 + #define _UNICODE 22 + 23 + #ifdef USE_CRT 24 + #include <fcntl.h> 25 + #include <io.h> 26 + #endif /* USE_CRT */ 27 + 28 + #include <stdlib.h> // limits.h // For MB_LEN_MAX 29 + 30 + #include <windef.h> 31 + #include <winbase.h> 32 + #include <winnls.h> 33 + #include <winuser.h> // MAKEINTRESOURCEW, RT_STRING 34 + #include <wincon.h> // Console APIs (only if kernel32 support included) 35 + #include <strsafe.h> 36 + 37 + /* PSEH for SEH Support */ 38 + #include <pseh/pseh2.h> 39 + 40 + #include "conutils.h" 41 + #include "stream.h" 42 + #include "stream_private.h" 43 + 44 + 45 + /* 46 + * Console I/O utility API -- Input 47 + */ 48 + 49 + /* EOF */
+46
sdk/lib/conutils/instream.h
··· 1 + /* 2 + * PROJECT: ReactOS Console Utilities Library 3 + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 + * PURPOSE: Provides basic abstraction wrappers around CRT streams or 5 + * Win32 console API I/O functions, to deal with i18n + Unicode 6 + * related problems. 7 + * COPYRIGHT: Copyright 2017-2018 ReactOS Team 8 + * Copyright 2017-2018 Hermes Belusca-Maito 9 + */ 10 + 11 + #ifndef __INSTREAM_H__ 12 + #define __INSTREAM_H__ 13 + 14 + #pragma once 15 + 16 + /* 17 + * Enable this define if you want to only use CRT functions to output 18 + * UNICODE stream to the console, as in the way explained by 19 + * http://archives.miloush.net/michkap/archive/2008/03/18/8306597.html 20 + */ 21 + /** NOTE: Experimental! Don't use USE_CRT yet because output to console is a bit broken **/ 22 + // #define USE_CRT 23 + 24 + #ifndef _UNICODE 25 + #error The ConUtils library at the moment only supports compilation with _UNICODE defined! 26 + #endif 27 + 28 + #ifdef __cplusplus 29 + extern "C" { 30 + #endif 31 + 32 + // Shadow type, implementation-specific 33 + typedef struct _CON_STREAM CON_STREAM, *PCON_STREAM; 34 + 35 + /* 36 + * Console I/O utility API -- Input 37 + */ 38 + 39 + 40 + #ifdef __cplusplus 41 + } 42 + #endif 43 + 44 + #endif /* __INSTREAM_H__ */ 45 + 46 + /* EOF */
+762
sdk/lib/conutils/outstream.c
··· 1 + /* 2 + * PROJECT: ReactOS Console Utilities Library 3 + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 + * PURPOSE: Provides basic abstraction wrappers around CRT streams or 5 + * Win32 console API I/O functions, to deal with i18n + Unicode 6 + * related problems. 7 + * COPYRIGHT: Copyright 2017-2018 ReactOS Team 8 + * Copyright 2017-2018 Hermes Belusca-Maito 9 + */ 10 + 11 + /* 12 + * Enable this define if you want to only use CRT functions to output 13 + * UNICODE stream to the console, as in the way explained by 14 + * http://archives.miloush.net/michkap/archive/2008/03/18/8306597.html 15 + */ 16 + /** NOTE: Experimental! Don't use USE_CRT yet because output to console is a bit broken **/ 17 + // #define USE_CRT 18 + 19 + /* FIXME: Temporary HACK before we cleanly support UNICODE functions */ 20 + #define UNICODE 21 + #define _UNICODE 22 + 23 + #ifdef USE_CRT 24 + #include <fcntl.h> 25 + #include <io.h> 26 + #endif /* USE_CRT */ 27 + 28 + #include <stdlib.h> // limits.h // For MB_LEN_MAX 29 + 30 + #include <windef.h> 31 + #include <winbase.h> 32 + #include <winnls.h> 33 + #include <winuser.h> // MAKEINTRESOURCEW, RT_STRING 34 + #include <wincon.h> // Console APIs (only if kernel32 support included) 35 + #include <strsafe.h> 36 + 37 + /* PSEH for SEH Support */ 38 + #include <pseh/pseh2.h> 39 + 40 + #include "conutils.h" 41 + #include "stream.h" 42 + #include "stream_private.h" 43 + 44 + 45 + // #define RC_STRING_MAX_SIZE 4096 46 + #define CON_RC_STRING_MAX_SIZE 4096 47 + // #define MAX_BUFFER_SIZE 4096 // Some programs (wlanconf, shutdown) set it to 5024 48 + // #define OUTPUT_BUFFER_SIZE 4096 // Name given in cmd/console.c 49 + // MAX_STRING_SIZE // Name given in diskpart 50 + 51 + // #define MAX_MESSAGE_SIZE 512 // See shutdown... 52 + 53 + 54 + /* 55 + * Console I/O utility API -- Output 56 + */ 57 + 58 + // NOTE: Should be called with the stream locked. 59 + INT 60 + __stdcall 61 + ConWrite( 62 + IN PCON_STREAM Stream, 63 + IN PTCHAR szStr, 64 + IN DWORD len) 65 + { 66 + #ifndef USE_CRT 67 + DWORD TotalLen = len, dwNumBytes = 0; 68 + PVOID p; 69 + 70 + // CHAR strOem[CON_RC_STRING_MAX_SIZE]; // Some static buffer... 71 + 72 + /* If we do not write anything, just return */ 73 + if (!szStr || len == 0) 74 + return 0; 75 + 76 + /* Check whether we are writing to a console */ 77 + // if (IsConsoleHandle(Stream->hHandle)) 78 + if (Stream->IsConsole) 79 + { 80 + // TODO: Check if (ConStream->Mode == WideText or UTF16Text) ?? 81 + 82 + /* 83 + * This code is inspired from _cputws, in particular from the fact that, 84 + * according to MSDN: https://msdn.microsoft.com/en-us/library/ms687401(v=vs.85).aspx 85 + * the buffer size must be less than 64 KB. 86 + * 87 + * A similar code can be used for implementing _cputs too. 88 + */ 89 + 90 + DWORD cchWrite; 91 + TotalLen = len, dwNumBytes = 0; 92 + 93 + while (len > 0) 94 + { 95 + cchWrite = min(len, 65535 / sizeof(WCHAR)); 96 + 97 + // FIXME: Check return value! 98 + WriteConsole(Stream->hHandle, szStr, cchWrite, &dwNumBytes, NULL); 99 + 100 + szStr += cchWrite; 101 + len -= cchWrite; 102 + } 103 + 104 + return (INT)TotalLen; // FIXME: Really return the number of chars written! 105 + } 106 + 107 + /* 108 + * We are redirected and writing to a file or pipe instead of the console. 109 + * Convert the string from TCHARs to the desired output format, if the two differ. 110 + * 111 + * Implementation NOTE: 112 + * MultiByteToWideChar (resp. WideCharToMultiByte) are equivalent to 113 + * OemToCharBuffW (resp. CharToOemBuffW), but the latters uselessly 114 + * depend on user32.dll, while MultiByteToWideChar and WideCharToMultiByte 115 + * only need kernel32.dll. 116 + */ 117 + if ((Stream->Mode == WideText) || (Stream->Mode == UTF16Text)) 118 + { 119 + #ifndef _UNICODE // UNICODE means that TCHAR == WCHAR == UTF-16 120 + /* Convert from the current process/thread's codepage to UTF-16 */ 121 + WCHAR *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR)); 122 + if (!buffer) 123 + { 124 + SetLastError(ERROR_NOT_ENOUGH_MEMORY); 125 + return 0; 126 + } 127 + len = (DWORD)MultiByteToWideChar(CP_THREAD_ACP, // CP_ACP, CP_OEMCP 128 + 0, szStr, (INT)len, buffer, (INT)len); 129 + szStr = (PVOID)buffer; 130 + #else 131 + /* 132 + * Do not perform any conversion since we are already in UTF-16, 133 + * that is the same encoding as the stream. 134 + */ 135 + #endif 136 + 137 + /* 138 + * Find any newline character in the buffer, 139 + * write the part BEFORE the newline, then write 140 + * a carriage-return + newline, and then write 141 + * the remaining part of the buffer. 142 + * 143 + * This fixes output in files and serial console. 144 + */ 145 + while (len > 0) 146 + { 147 + /* Loop until we find a \r or \n character */ 148 + // FIXME: What about the pair \r\n ? 149 + p = szStr; 150 + while (len > 0 && *(PWCHAR)p != L'\r' && *(PWCHAR)p != L'\n') 151 + { 152 + /* Advance one character */ 153 + p = (PVOID)((PWCHAR)p + 1); 154 + len--; 155 + } 156 + 157 + /* Write everything up to \r or \n */ 158 + dwNumBytes = ((PWCHAR)p - (PWCHAR)szStr) * sizeof(WCHAR); 159 + WriteFile(Stream->hHandle, szStr, dwNumBytes, &dwNumBytes, NULL); 160 + 161 + /* If we hit \r or \n ... */ 162 + if (len > 0 && (*(PWCHAR)p == L'\r' || *(PWCHAR)p == L'\n')) 163 + { 164 + /* ... send a carriage-return + newline sequence and skip \r or \n */ 165 + WriteFile(Stream->hHandle, L"\r\n", 2 * sizeof(WCHAR), &dwNumBytes, NULL); 166 + szStr = (PVOID)((PWCHAR)p + 1); 167 + len--; 168 + } 169 + } 170 + 171 + #ifndef _UNICODE 172 + HeapFree(GetProcessHeap(), 0, buffer); 173 + #endif 174 + } 175 + else if ((Stream->Mode == UTF8Text) || (Stream->Mode == AnsiText)) 176 + { 177 + CHAR *buffer; 178 + 179 + /* 180 + * Resolve the codepage cache if it was not assigned yet 181 + * (only if the stream is in ANSI mode; in UTF8 mode the 182 + * codepage was already set to CP_UTF8). 183 + */ 184 + if (/*(Stream->Mode == AnsiText) &&*/ (Stream->CodePage == INVALID_CP)) 185 + Stream->CodePage = GetConsoleOutputCP(); // CP_ACP, CP_OEMCP 186 + 187 + #ifdef _UNICODE // UNICODE means that TCHAR == WCHAR == UTF-16 188 + /* Convert from UTF-16 to either UTF-8 or ANSI, using stream codepage */ 189 + // NOTE: MB_LEN_MAX defined either in limits.h or in stdlib.h . 190 + buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * MB_LEN_MAX); 191 + if (!buffer) 192 + { 193 + SetLastError(ERROR_NOT_ENOUGH_MEMORY); 194 + return 0; 195 + } 196 + len = WideCharToMultiByte(Stream->CodePage, 0, 197 + szStr, len, buffer, len * MB_LEN_MAX, 198 + NULL, NULL); 199 + szStr = (PVOID)buffer; 200 + #else 201 + /* 202 + * Convert from the current process/thread's codepage to either 203 + * UTF-8 or ANSI, using stream codepage. 204 + * We need to perform a double conversion, by going through UTF-16. 205 + */ 206 + // TODO! 207 + #error "Need to implement double conversion!" 208 + #endif 209 + 210 + /* 211 + * Find any newline character in the buffer, 212 + * write the part BEFORE the newline, then write 213 + * a carriage-return + newline, and then write 214 + * the remaining part of the buffer. 215 + * 216 + * This fixes output in files and serial console. 217 + */ 218 + while (len > 0) 219 + { 220 + /* Loop until we find a \r or \n character */ 221 + // FIXME: What about the pair \r\n ? 222 + p = szStr; 223 + while (len > 0 && *(PCHAR)p != '\r' && *(PCHAR)p != '\n') 224 + { 225 + /* Advance one character */ 226 + p = (PVOID)((PCHAR)p + 1); 227 + len--; 228 + } 229 + 230 + /* Write everything up to \r or \n */ 231 + dwNumBytes = ((PCHAR)p - (PCHAR)szStr) * sizeof(CHAR); 232 + WriteFile(Stream->hHandle, szStr, dwNumBytes, &dwNumBytes, NULL); 233 + 234 + /* If we hit \r or \n ... */ 235 + if (len > 0 && (*(PCHAR)p == '\r' || *(PCHAR)p == '\n')) 236 + { 237 + /* ... send a carriage-return + newline sequence and skip \r or \n */ 238 + WriteFile(Stream->hHandle, "\r\n", 2, &dwNumBytes, NULL); 239 + szStr = (PVOID)((PCHAR)p + 1); 240 + len--; 241 + } 242 + } 243 + 244 + #ifdef _UNICODE 245 + HeapFree(GetProcessHeap(), 0, buffer); 246 + #else 247 + // TODO! 248 + #endif 249 + } 250 + else // if (Stream->Mode == Binary) 251 + { 252 + /* Directly output the string */ 253 + WriteFile(Stream->hHandle, szStr, len, &dwNumBytes, NULL); 254 + } 255 + 256 + // FIXME! 257 + return (INT)TotalLen; 258 + 259 + #else /* defined(USE_CRT) */ 260 + 261 + DWORD total = len; 262 + DWORD written = 0; 263 + 264 + /* If we do not write anything, just return */ 265 + if (!szStr || len == 0) 266 + return 0; 267 + 268 + #if 1 269 + /* 270 + * There is no "counted" printf-to-stream or puts-like function, therefore 271 + * we use this trick to output the counted string to the stream. 272 + */ 273 + while (1) 274 + { 275 + written = fwprintf(Stream->fStream, L"%.*s", total, szStr); 276 + if (written < total) 277 + { 278 + /* 279 + * Some embedded NULL or special character 280 + * was encountered, print it apart. 281 + */ 282 + if (written == 0) 283 + { 284 + fputwc(*szStr, Stream->fStream); 285 + written++; 286 + } 287 + 288 + szStr += written; 289 + total -= written; 290 + } 291 + else 292 + { 293 + break; 294 + } 295 + } 296 + return (INT)len; 297 + #else 298 + /* ANSI text or Binary output only */ 299 + _setmode(_fileno(Stream->fStream), _O_TEXT); // _O_BINARY 300 + return fwrite(szStr, sizeof(*szStr), len, Stream->fStream); 301 + #endif 302 + 303 + #endif /* defined(USE_CRT) */ 304 + } 305 + 306 + 307 + #define CON_STREAM_WRITE_CALL(Stream, Str, Len) \ 308 + (Stream)->WriteFunc((Stream), (Str), (Len)); 309 + 310 + /* Lock the stream only in non-USE_CRT mode (otherwise use the CRT stream lock) */ 311 + #ifndef USE_CRT 312 + 313 + #define CON_STREAM_WRITE2(Stream, Str, Len, RetLen) \ 314 + do { \ 315 + EnterCriticalSection(&(Stream)->Lock); \ 316 + (RetLen) = CON_STREAM_WRITE_CALL((Stream), (Str), (Len)); \ 317 + LeaveCriticalSection(&(Stream)->Lock); \ 318 + } while(0) 319 + 320 + #define CON_STREAM_WRITE(Stream, Str, Len) \ 321 + do { \ 322 + EnterCriticalSection(&(Stream)->Lock); \ 323 + CON_STREAM_WRITE_CALL((Stream), (Str), (Len)); \ 324 + LeaveCriticalSection(&(Stream)->Lock); \ 325 + } while(0) 326 + 327 + #else 328 + 329 + #define CON_STREAM_WRITE2(Stream, Str, Len, RetLen) \ 330 + do { \ 331 + (RetLen) = CON_STREAM_WRITE_CALL((Stream), (Str), (Len)); \ 332 + } while(0) 333 + 334 + #define CON_STREAM_WRITE(Stream, Str, Len) \ 335 + do { \ 336 + CON_STREAM_WRITE_CALL((Stream), (Str), (Len)); \ 337 + } while(0) 338 + 339 + #endif 340 + 341 + 342 + INT 343 + ConStreamWrite( 344 + IN PCON_STREAM Stream, 345 + IN PTCHAR szStr, 346 + IN DWORD len) 347 + { 348 + INT Len; 349 + CON_STREAM_WRITE2(Stream, szStr, len, Len); 350 + return Len; 351 + } 352 + 353 + INT 354 + ConPuts( 355 + IN PCON_STREAM Stream, 356 + IN LPWSTR szStr) 357 + { 358 + INT Len; 359 + 360 + Len = wcslen(szStr); 361 + CON_STREAM_WRITE2(Stream, szStr, Len, Len); 362 + 363 + /* Fixup returned length in case of errors */ 364 + if (Len < 0) 365 + Len = 0; 366 + 367 + return Len; 368 + } 369 + 370 + INT 371 + ConPrintfV( 372 + IN PCON_STREAM Stream, 373 + IN LPWSTR szStr, 374 + IN va_list args) // arg_ptr 375 + { 376 + INT Len; 377 + WCHAR bufSrc[CON_RC_STRING_MAX_SIZE]; 378 + 379 + // Len = vfwprintf(Stream->fStream, szStr, args); // vfprintf for direct ANSI 380 + 381 + /* 382 + * Reuse szStr as the pointer to end-of-string, to compute 383 + * the string length instead of calling wcslen(). 384 + */ 385 + // StringCchVPrintfW(bufSrc, ARRAYSIZE(bufSrc), szStr, args); 386 + // Len = wcslen(bufSrc); 387 + StringCchVPrintfExW(bufSrc, ARRAYSIZE(bufSrc), &szStr, NULL, 0, szStr, args); 388 + Len = szStr - bufSrc; 389 + 390 + CON_STREAM_WRITE2(Stream, bufSrc, Len, Len); 391 + 392 + /* Fixup returned length in case of errors */ 393 + if (Len < 0) 394 + Len = 0; 395 + 396 + return Len; 397 + } 398 + 399 + INT 400 + __cdecl 401 + ConPrintf( 402 + IN PCON_STREAM Stream, 403 + IN LPWSTR szStr, 404 + ...) 405 + { 406 + INT Len; 407 + va_list args; 408 + 409 + // Len = vfwprintf(Stream->fStream, szMsgBuf, args); // vfprintf for direct ANSI 410 + 411 + // StringCchPrintfW 412 + va_start(args, szStr); 413 + Len = ConPrintfV(Stream, szStr, args); 414 + va_end(args); 415 + 416 + return Len; 417 + } 418 + 419 + INT 420 + ConResPutsEx( 421 + IN PCON_STREAM Stream, 422 + IN HINSTANCE hInstance OPTIONAL, 423 + IN UINT uID) 424 + { 425 + INT Len; 426 + PWCHAR szStr = NULL; 427 + 428 + Len = K32LoadStringW(hInstance, uID, (PWSTR)&szStr, 0); 429 + if (szStr && Len) 430 + // Len = ConPuts(Stream, szStr); 431 + CON_STREAM_WRITE2(Stream, szStr, Len, Len); 432 + 433 + /* Fixup returned length in case of errors */ 434 + if (Len < 0) 435 + Len = 0; 436 + 437 + return Len; 438 + } 439 + 440 + INT 441 + ConResPuts( 442 + IN PCON_STREAM Stream, 443 + IN UINT uID) 444 + { 445 + return ConResPutsEx(Stream, NULL /*GetModuleHandleW(NULL)*/, uID); 446 + } 447 + 448 + INT 449 + ConResPrintfExV( 450 + IN PCON_STREAM Stream, 451 + IN HINSTANCE hInstance OPTIONAL, 452 + IN UINT uID, 453 + IN va_list args) // arg_ptr 454 + { 455 + INT Len; 456 + WCHAR bufSrc[CON_RC_STRING_MAX_SIZE]; 457 + 458 + // NOTE: We may use the special behaviour where nBufMaxSize == 0 459 + Len = K32LoadStringW(hInstance, uID, bufSrc, ARRAYSIZE(bufSrc)); 460 + if (Len) 461 + Len = ConPrintfV(Stream, bufSrc, args); 462 + 463 + return Len; 464 + } 465 + 466 + INT 467 + ConResPrintfV( 468 + IN PCON_STREAM Stream, 469 + IN UINT uID, 470 + IN va_list args) // arg_ptr 471 + { 472 + return ConResPrintfExV(Stream, NULL /*GetModuleHandleW(NULL)*/, uID, args); 473 + } 474 + 475 + INT 476 + __cdecl 477 + ConResPrintfEx( 478 + IN PCON_STREAM Stream, 479 + IN HINSTANCE hInstance OPTIONAL, 480 + IN UINT uID, 481 + ...) 482 + { 483 + INT Len; 484 + va_list args; 485 + 486 + va_start(args, uID); 487 + Len = ConResPrintfExV(Stream, hInstance, uID, args); 488 + va_end(args); 489 + 490 + return Len; 491 + } 492 + 493 + INT 494 + __cdecl 495 + ConResPrintf( 496 + IN PCON_STREAM Stream, 497 + IN UINT uID, 498 + ...) 499 + { 500 + INT Len; 501 + va_list args; 502 + 503 + va_start(args, uID); 504 + Len = ConResPrintfV(Stream, uID, args); 505 + va_end(args); 506 + 507 + return Len; 508 + } 509 + 510 + INT 511 + ConMsgPuts( 512 + IN PCON_STREAM Stream, 513 + IN DWORD dwFlags, 514 + IN LPCVOID lpSource OPTIONAL, 515 + IN DWORD dwMessageId, 516 + IN DWORD dwLanguageId) 517 + { 518 + INT Len; 519 + DWORD dwLength = 0; 520 + LPWSTR lpMsgBuf = NULL; 521 + 522 + /* 523 + * Sanitize dwFlags. This version always ignore explicitely the inserts 524 + * as we emulate the behaviour of the *puts function. 525 + */ 526 + dwFlags |= FORMAT_MESSAGE_ALLOCATE_BUFFER; // Always allocate an internal buffer. 527 + dwFlags |= FORMAT_MESSAGE_IGNORE_INSERTS; // Ignore inserts for FormatMessage. 528 + dwFlags &= ~FORMAT_MESSAGE_ARGUMENT_ARRAY; 529 + 530 + dwFlags |= FORMAT_MESSAGE_MAX_WIDTH_MASK; 531 + 532 + /* 533 + * Retrieve the message string without appending extra newlines. 534 + * Wrap in SEH to protect from invalid string parameters. 535 + */ 536 + _SEH2_TRY 537 + { 538 + dwLength = FormatMessageW(dwFlags, 539 + lpSource, 540 + dwMessageId, 541 + dwLanguageId, 542 + (LPWSTR)&lpMsgBuf, 543 + 0, NULL); 544 + } 545 + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 546 + { 547 + } 548 + _SEH2_END; 549 + 550 + Len = (INT)dwLength; 551 + 552 + if (!lpMsgBuf) 553 + { 554 + // ASSERT(dwLength == 0); 555 + } 556 + else 557 + { 558 + // ASSERT(dwLength != 0); 559 + 560 + /* lpMsgBuf is NULL-terminated by FormatMessage */ 561 + // Len = ConPuts(Stream, lpMsgBuf); 562 + CON_STREAM_WRITE2(Stream, lpMsgBuf, dwLength, Len); 563 + 564 + /* Fixup returned length in case of errors */ 565 + if (Len < 0) 566 + Len = 0; 567 + 568 + /* Free the buffer allocated by FormatMessage */ 569 + LocalFree(lpMsgBuf); 570 + } 571 + 572 + return Len; 573 + } 574 + 575 + INT 576 + ConMsgPrintf2V( 577 + IN PCON_STREAM Stream, 578 + IN DWORD dwFlags, 579 + IN LPCVOID lpSource OPTIONAL, 580 + IN DWORD dwMessageId, 581 + IN DWORD dwLanguageId, 582 + IN va_list args) // arg_ptr 583 + { 584 + INT Len; 585 + DWORD dwLength = 0; 586 + LPWSTR lpMsgBuf = NULL; 587 + 588 + /* 589 + * Sanitize dwFlags. This version always ignore explicitely the inserts. 590 + * The string that we will return to the user will not be pre-formatted. 591 + */ 592 + dwFlags |= FORMAT_MESSAGE_ALLOCATE_BUFFER; // Always allocate an internal buffer. 593 + dwFlags |= FORMAT_MESSAGE_IGNORE_INSERTS; // Ignore inserts for FormatMessage. 594 + dwFlags &= ~FORMAT_MESSAGE_ARGUMENT_ARRAY; 595 + 596 + dwFlags |= FORMAT_MESSAGE_MAX_WIDTH_MASK; 597 + 598 + /* 599 + * Retrieve the message string without appending extra newlines. 600 + * Wrap in SEH to protect from invalid string parameters. 601 + */ 602 + _SEH2_TRY 603 + { 604 + dwLength = FormatMessageW(dwFlags, 605 + lpSource, 606 + dwMessageId, 607 + dwLanguageId, 608 + (LPWSTR)&lpMsgBuf, 609 + 0, NULL); 610 + } 611 + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 612 + { 613 + } 614 + _SEH2_END; 615 + 616 + Len = (INT)dwLength; 617 + 618 + if (!lpMsgBuf) 619 + { 620 + // ASSERT(dwLength == 0); 621 + } 622 + else 623 + { 624 + // ASSERT(dwLength != 0); 625 + 626 + /* lpMsgBuf is NULL-terminated by FormatMessage */ 627 + Len = ConPrintfV(Stream, lpMsgBuf, args); 628 + // CON_STREAM_WRITE2(Stream, lpMsgBuf, dwLength, Len); 629 + 630 + /* Fixup returned length in case of errors */ 631 + if (Len < 0) 632 + Len = 0; 633 + 634 + /* Free the buffer allocated by FormatMessage */ 635 + LocalFree(lpMsgBuf); 636 + } 637 + 638 + return Len; 639 + } 640 + 641 + INT 642 + ConMsgPrintfV( 643 + IN PCON_STREAM Stream, 644 + IN DWORD dwFlags, 645 + IN LPCVOID lpSource OPTIONAL, 646 + IN DWORD dwMessageId, 647 + IN DWORD dwLanguageId, 648 + IN va_list args) // arg_ptr 649 + { 650 + INT Len; 651 + DWORD dwLength = 0; 652 + LPWSTR lpMsgBuf = NULL; 653 + 654 + /* Sanitize dwFlags */ 655 + dwFlags |= FORMAT_MESSAGE_ALLOCATE_BUFFER; // Always allocate an internal buffer. 656 + // dwFlags &= ~FORMAT_MESSAGE_IGNORE_INSERTS; // We always use arguments. 657 + dwFlags &= ~FORMAT_MESSAGE_ARGUMENT_ARRAY; // We always use arguments of type 'va_list'. 658 + 659 + // 660 + // NOTE: Technique taken from eventvwr.c!GetMessageStringFromDll() 661 + // 662 + 663 + dwFlags |= FORMAT_MESSAGE_MAX_WIDTH_MASK; 664 + 665 + /* 666 + * Retrieve the message string without appending extra newlines. 667 + * Use the "safe" FormatMessage version (SEH-protected) to protect 668 + * from invalid string parameters. 669 + */ 670 + dwLength = FormatMessageSafeW(dwFlags, 671 + lpSource, 672 + dwMessageId, 673 + dwLanguageId, 674 + (LPWSTR)&lpMsgBuf, 675 + 0, &args); 676 + 677 + Len = (INT)dwLength; 678 + 679 + if (!lpMsgBuf) 680 + { 681 + // ASSERT(dwLength == 0); 682 + } 683 + else 684 + { 685 + // ASSERT(dwLength != 0); 686 + 687 + // Len = ConPrintfV(Stream, lpMsgBuf, args); 688 + CON_STREAM_WRITE2(Stream, lpMsgBuf, dwLength, Len); 689 + 690 + /* Fixup returned length in case of errors */ 691 + if (Len < 0) 692 + Len = 0; 693 + 694 + /* Free the buffer allocated by FormatMessage */ 695 + LocalFree(lpMsgBuf); 696 + } 697 + 698 + return Len; 699 + } 700 + 701 + INT 702 + __cdecl 703 + ConMsgPrintf( 704 + IN PCON_STREAM Stream, 705 + IN DWORD dwFlags, 706 + IN LPCVOID lpSource OPTIONAL, 707 + IN DWORD dwMessageId, 708 + IN DWORD dwLanguageId, 709 + ...) 710 + { 711 + INT Len; 712 + va_list args; 713 + 714 + va_start(args, dwLanguageId); 715 + // ConMsgPrintf2V 716 + Len = ConMsgPrintfV(Stream, 717 + dwFlags, 718 + lpSource, 719 + dwMessageId, 720 + dwLanguageId, 721 + args); 722 + va_end(args); 723 + 724 + return Len; 725 + } 726 + 727 + 728 + 729 + VOID 730 + ConClearLine(IN PCON_STREAM Stream) 731 + { 732 + HANDLE hOutput = ConStreamGetOSHandle(Stream); 733 + 734 + /* 735 + * Erase the full line where the cursor is, and move 736 + * the cursor back to the beginning of the line. 737 + */ 738 + 739 + if (IsConsoleHandle(hOutput)) 740 + { 741 + CONSOLE_SCREEN_BUFFER_INFO csbi; 742 + DWORD dwWritten; 743 + 744 + GetConsoleScreenBufferInfo(hOutput, &csbi); 745 + 746 + csbi.dwCursorPosition.X = 0; 747 + // csbi.dwCursorPosition.Y; 748 + 749 + FillConsoleOutputCharacterW(hOutput, L' ', 750 + csbi.dwSize.X, 751 + csbi.dwCursorPosition, 752 + &dwWritten); 753 + SetConsoleCursorPosition(hOutput, csbi.dwCursorPosition); 754 + } 755 + else if (IsTTYHandle(hOutput)) 756 + { 757 + ConPuts(Stream, L"\x1B[2K\x1B[1G"); // FIXME: Just use WriteFile 758 + } 759 + // else, do nothing for files 760 + } 761 + 762 + /* EOF */
+162
sdk/lib/conutils/outstream.h
··· 1 + /* 2 + * PROJECT: ReactOS Console Utilities Library 3 + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 + * PURPOSE: Provides basic abstraction wrappers around CRT streams or 5 + * Win32 console API I/O functions, to deal with i18n + Unicode 6 + * related problems. 7 + * COPYRIGHT: Copyright 2017-2018 ReactOS Team 8 + * Copyright 2017-2018 Hermes Belusca-Maito 9 + */ 10 + 11 + #ifndef __OUTSTREAM_H__ 12 + #define __OUTSTREAM_H__ 13 + 14 + #pragma once 15 + 16 + /* 17 + * Enable this define if you want to only use CRT functions to output 18 + * UNICODE stream to the console, as in the way explained by 19 + * http://archives.miloush.net/michkap/archive/2008/03/18/8306597.html 20 + */ 21 + /** NOTE: Experimental! Don't use USE_CRT yet because output to console is a bit broken **/ 22 + // #define USE_CRT 23 + 24 + #ifndef _UNICODE 25 + #error The ConUtils library at the moment only supports compilation with _UNICODE defined! 26 + #endif 27 + 28 + #ifdef __cplusplus 29 + extern "C" { 30 + #endif 31 + 32 + // Shadow type, implementation-specific 33 + typedef struct _CON_STREAM CON_STREAM, *PCON_STREAM; 34 + 35 + // typedef INT (__stdcall *CON_READ_FUNC)(IN PCON_STREAM, IN PTCHAR, IN DWORD); 36 + // Stream, szStr, len 37 + typedef INT (__stdcall *CON_WRITE_FUNC)(IN PCON_STREAM, IN PTCHAR, IN DWORD); 38 + 39 + 40 + /* 41 + * Console I/O utility API -- Output 42 + */ 43 + 44 + INT 45 + __stdcall 46 + ConWrite( 47 + IN PCON_STREAM Stream, 48 + IN PTCHAR szStr, 49 + IN DWORD len); 50 + 51 + INT 52 + ConStreamWrite( 53 + IN PCON_STREAM Stream, 54 + IN PTCHAR szStr, 55 + IN DWORD len); 56 + 57 + INT 58 + ConPuts( 59 + IN PCON_STREAM Stream, 60 + IN LPWSTR szStr); 61 + 62 + INT 63 + ConPrintfV( 64 + IN PCON_STREAM Stream, 65 + IN LPWSTR szStr, 66 + IN va_list args); // arg_ptr 67 + 68 + INT 69 + __cdecl 70 + ConPrintf( 71 + IN PCON_STREAM Stream, 72 + IN LPWSTR szStr, 73 + ...); 74 + 75 + INT 76 + ConResPutsEx( 77 + IN PCON_STREAM Stream, 78 + IN HINSTANCE hInstance OPTIONAL, 79 + IN UINT uID); 80 + 81 + INT 82 + ConResPuts( 83 + IN PCON_STREAM Stream, 84 + IN UINT uID); 85 + 86 + INT 87 + ConResPrintfExV( 88 + IN PCON_STREAM Stream, 89 + IN HINSTANCE hInstance OPTIONAL, 90 + IN UINT uID, 91 + IN va_list args); // arg_ptr 92 + 93 + INT 94 + ConResPrintfV( 95 + IN PCON_STREAM Stream, 96 + IN UINT uID, 97 + IN va_list args); // arg_ptr 98 + 99 + INT 100 + __cdecl 101 + ConResPrintfEx( 102 + IN PCON_STREAM Stream, 103 + IN HINSTANCE hInstance OPTIONAL, 104 + IN UINT uID, 105 + ...); 106 + 107 + INT 108 + __cdecl 109 + ConResPrintf( 110 + IN PCON_STREAM Stream, 111 + IN UINT uID, 112 + ...); 113 + 114 + INT 115 + ConMsgPuts( 116 + IN PCON_STREAM Stream, 117 + IN DWORD dwFlags, 118 + IN LPCVOID lpSource OPTIONAL, 119 + IN DWORD dwMessageId, 120 + IN DWORD dwLanguageId); 121 + 122 + INT 123 + ConMsgPrintf2V( 124 + IN PCON_STREAM Stream, 125 + IN DWORD dwFlags, 126 + IN LPCVOID lpSource OPTIONAL, 127 + IN DWORD dwMessageId, 128 + IN DWORD dwLanguageId, 129 + IN va_list args); // arg_ptr 130 + 131 + INT 132 + ConMsgPrintfV( 133 + IN PCON_STREAM Stream, 134 + IN DWORD dwFlags, 135 + IN LPCVOID lpSource OPTIONAL, 136 + IN DWORD dwMessageId, 137 + IN DWORD dwLanguageId, 138 + IN va_list args); // arg_ptr 139 + 140 + INT 141 + __cdecl 142 + ConMsgPrintf( 143 + IN PCON_STREAM Stream, 144 + IN DWORD dwFlags, 145 + IN LPCVOID lpSource OPTIONAL, 146 + IN DWORD dwMessageId, 147 + IN DWORD dwLanguageId, 148 + ...); 149 + 150 + 151 + 152 + VOID 153 + ConClearLine(IN PCON_STREAM Stream); 154 + 155 + 156 + #ifdef __cplusplus 157 + } 158 + #endif 159 + 160 + #endif /* __OUTSTREAM_H__ */ 161 + 162 + /* EOF */
+7 -9
sdk/lib/conutils/pager.c
··· 1 1 /* 2 - * COPYRIGHT: See COPYING in the top level directory 3 - * PROJECT: ReactOS Console Utilities Library 4 - * FILE: sdk/lib/conutils/pager.c 5 - * PURPOSE: Console/terminal paging functionality. 6 - * PROGRAMMERS: - Hermes Belusca-Maito (for the library); 7 - * - All programmers who wrote the different console applications 8 - * from which I took those functions and improved them. 2 + * PROJECT: ReactOS Console Utilities Library 3 + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 + * PURPOSE: Console/terminal paging functionality. 5 + * COPYRIGHT: Copyright 2017-2018 ReactOS Team 6 + * Copyright 2017-2018 Hermes Belusca-Maito 9 7 */ 10 8 11 9 /* FIXME: Temporary HACK before we cleanly support UNICODE functions */ 12 10 #define UNICODE 13 11 #define _UNICODE 14 - 15 - #include <stdlib.h> // limits.h // For MB_LEN_MAX 16 12 17 13 #include <windef.h> 18 14 #include <winbase.h> ··· 158 154 return ConResPagingEx(Pager, PagePrompt, StartPaging, 159 155 NULL /*GetModuleHandleW(NULL)*/, uID); 160 156 } 157 + 158 + /* EOF */
+11 -7
sdk/lib/conutils/pager.h
··· 1 1 /* 2 - * COPYRIGHT: See COPYING in the top level directory 3 - * PROJECT: ReactOS Console Utilities Library 4 - * FILE: sdk/lib/conutils/pager.h 5 - * PURPOSE: Console/terminal paging functionality. 6 - * PROGRAMMERS: - Hermes Belusca-Maito (for the library); 7 - * - All programmers who wrote the different console applications 8 - * from which I took those functions and improved them. 2 + * PROJECT: ReactOS Console Utilities Library 3 + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 + * PURPOSE: Console/terminal paging functionality. 5 + * COPYRIGHT: Copyright 2017-2018 ReactOS Team 6 + * Copyright 2017-2018 Hermes Belusca-Maito 9 7 */ 10 8 11 9 #ifndef __PAGER_H__ 12 10 #define __PAGER_H__ 11 + 12 + #pragma once 13 13 14 14 #ifndef _UNICODE 15 15 #error The ConUtils library at the moment only supports compilation with _UNICODE defined! ··· 42 42 (pPager)->LineCount = 0; \ 43 43 } while (0) 44 44 45 + 45 46 // Pager, Done, Total 46 47 typedef BOOL (__stdcall *PAGE_PROMPT)(IN PCON_PAGER, IN DWORD, IN DWORD); 47 48 ··· 78 79 #ifdef __cplusplus 79 80 } 80 81 #endif 82 + 81 83 #endif /* __PAGER_H__ */ 84 + 85 + /* EOF */
+7 -9
sdk/lib/conutils/screen.c
··· 1 1 /* 2 - * COPYRIGHT: See COPYING in the top level directory 3 - * PROJECT: ReactOS Console Utilities Library 4 - * FILE: sdk/lib/conutils/screen.c 5 - * PURPOSE: Console/terminal screen management. 6 - * PROGRAMMERS: - Hermes Belusca-Maito (for the library); 7 - * - All programmers who wrote the different console applications 8 - * from which I took those functions and improved them. 2 + * PROJECT: ReactOS Console Utilities Library 3 + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 + * PURPOSE: Console/terminal screen management. 5 + * COPYRIGHT: Copyright 2017-2018 ReactOS Team 6 + * Copyright 2017-2018 Hermes Belusca-Maito 9 7 */ 10 8 11 9 /* FIXME: Temporary HACK before we cleanly support UNICODE functions */ 12 10 #define UNICODE 13 11 #define _UNICODE 14 - 15 - #include <stdlib.h> // limits.h // For MB_LEN_MAX 16 12 17 13 #include <windef.h> 18 14 #include <winbase.h> ··· 173 169 CON_STREAM_WRITE(Screen->Stream, &ch, 1); 174 170 } 175 171 } 172 + 173 + /* EOF */
+10 -7
sdk/lib/conutils/screen.h
··· 1 1 /* 2 - * COPYRIGHT: See COPYING in the top level directory 3 - * PROJECT: ReactOS Console Utilities Library 4 - * FILE: sdk/lib/conutils/screen.h 5 - * PURPOSE: Console/terminal screen management. 6 - * PROGRAMMERS: - Hermes Belusca-Maito (for the library); 7 - * - All programmers who wrote the different console applications 8 - * from which I took those functions and improved them. 2 + * PROJECT: ReactOS Console Utilities Library 3 + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 + * PURPOSE: Console/terminal screen management. 5 + * COPYRIGHT: Copyright 2017-2018 ReactOS Team 6 + * Copyright 2017-2018 Hermes Belusca-Maito 9 7 */ 10 8 11 9 #ifndef __SCREEN_H__ 12 10 #define __SCREEN_H__ 11 + 12 + #pragma once 13 13 14 14 #ifndef _UNICODE 15 15 #error The ConUtils library at the moment only supports compilation with _UNICODE defined! ··· 60 60 #ifdef __cplusplus 61 61 } 62 62 #endif 63 + 63 64 #endif /* __SCREEN_H__ */ 65 + 66 + /* EOF */
+10 -762
sdk/lib/conutils/stream.c
··· 1 1 /* 2 - * COPYRIGHT: See COPYING in the top level directory 3 - * PROJECT: ReactOS Console Utilities Library 4 - * FILE: sdk/lib/conutils/stream.c 5 - * PURPOSE: Provides basic abstraction wrappers around CRT streams or 6 - * Win32 console API I/O functions, to deal with i18n + Unicode 7 - * related problems. 8 - * PROGRAMMERS: - Hermes Belusca-Maito (for the library); 9 - * - All programmers who wrote the different console applications 10 - * from which I took those functions and improved them. 2 + * PROJECT: ReactOS Console Utilities Library 3 + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 + * PURPOSE: Provides basic abstraction wrappers around CRT streams or 5 + * Win32 console API I/O functions, to deal with i18n + Unicode 6 + * related problems. 7 + * COPYRIGHT: Copyright 2017-2018 ReactOS Team 8 + * Copyright 2017-2018 Hermes Belusca-Maito 11 9 */ 12 10 13 11 /* ··· 27 25 #include <io.h> 28 26 #endif /* USE_CRT */ 29 27 30 - #include <stdlib.h> // limits.h // For MB_LEN_MAX 31 - 32 28 #include <windef.h> 33 29 #include <winbase.h> 34 30 #include <winnls.h> 35 - #include <winuser.h> // MAKEINTRESOURCEW, RT_STRING 31 + // #include <winuser.h> // MAKEINTRESOURCEW, RT_STRING 36 32 #include <wincon.h> // Console APIs (only if kernel32 support included) 37 33 #include <strsafe.h> 38 34 39 - /* PSEH for SEH Support */ 40 - #include <pseh/pseh2.h> 41 - 42 35 #include "conutils.h" 43 36 #include "stream.h" 44 - 45 - 46 - // #define RC_STRING_MAX_SIZE 4096 47 - #define CON_RC_STRING_MAX_SIZE 4096 48 - // #define MAX_BUFFER_SIZE 4096 // Some programs (wlanconf, shutdown) set it to 5024 49 - // #define OUTPUT_BUFFER_SIZE 4096 // Name given in cmd/console.c 50 - // MAX_STRING_SIZE // Name given in diskpart 51 - 52 - // #define MAX_MESSAGE_SIZE 512 // See shutdown... 37 + #include "stream_private.h" 53 38 54 39 55 40 /* 56 41 * Console I/O streams 57 42 */ 58 - 59 - typedef struct _CON_STREAM 60 - { 61 - CON_WRITE_FUNC WriteFunc; 62 - 63 - #ifdef USE_CRT 64 - FILE* fStream; 65 - #else 66 - BOOL IsInitialized; 67 - CRITICAL_SECTION Lock; 68 - 69 - HANDLE hHandle; 70 - 71 - /* 72 - * TRUE if 'hHandle' refers to a console, in which case I/O UTF-16 73 - * is directly used. If 'hHandle' refers to a file or a pipe, the 74 - * 'Mode' flag is used. 75 - */ 76 - BOOL IsConsole; 77 - 78 - /* 79 - * The 'Mode' flag is used to know the translation mode 80 - * when 'hHandle' refers to a file or a pipe. 81 - */ 82 - CON_STREAM_MODE Mode; 83 - UINT CodePage; // Used to convert UTF-16 text to some ANSI codepage. 84 - #endif /* defined(USE_CRT) */ 85 - } CON_STREAM, *PCON_STREAM; 86 43 87 44 /* 88 45 * Standard console streams, initialized by ··· 339 296 #endif 340 297 } 341 298 342 - 343 - /* 344 - * Console I/O utility API 345 - * (for the moment, only Output) 346 - */ 347 - 348 - // NOTE: Should be called with the stream locked. 349 - INT 350 - __stdcall 351 - ConWrite( 352 - IN PCON_STREAM Stream, 353 - IN PTCHAR szStr, 354 - IN DWORD len) 355 - { 356 - #ifndef USE_CRT 357 - DWORD TotalLen = len, dwNumBytes = 0; 358 - PVOID p; 359 - 360 - // CHAR strOem[CON_RC_STRING_MAX_SIZE]; // Some static buffer... 361 - 362 - /* If we do not write anything, just return */ 363 - if (!szStr || len == 0) 364 - return 0; 365 - 366 - /* Check whether we are writing to a console */ 367 - // if (IsConsoleHandle(Stream->hHandle)) 368 - if (Stream->IsConsole) 369 - { 370 - // TODO: Check if (ConStream->Mode == WideText or UTF16Text) ?? 371 - 372 - /* 373 - * This code is inspired from _cputws, in particular from the fact that, 374 - * according to MSDN: https://msdn.microsoft.com/en-us/library/ms687401(v=vs.85).aspx 375 - * the buffer size must be less than 64 KB. 376 - * 377 - * A similar code can be used for implementing _cputs too. 378 - */ 379 - 380 - DWORD cchWrite; 381 - TotalLen = len, dwNumBytes = 0; 382 - 383 - while (len > 0) 384 - { 385 - cchWrite = min(len, 65535 / sizeof(WCHAR)); 386 - 387 - // FIXME: Check return value! 388 - WriteConsole(Stream->hHandle, szStr, cchWrite, &dwNumBytes, NULL); 389 - 390 - szStr += cchWrite; 391 - len -= cchWrite; 392 - } 393 - 394 - return (INT)TotalLen; // FIXME: Really return the number of chars written! 395 - } 396 - 397 - /* 398 - * We are redirected and writing to a file or pipe instead of the console. 399 - * Convert the string from TCHARs to the desired output format, if the two differ. 400 - * 401 - * Implementation NOTE: 402 - * MultiByteToWideChar (resp. WideCharToMultiByte) are equivalent to 403 - * OemToCharBuffW (resp. CharToOemBuffW), but the latters uselessly 404 - * depend on user32.dll, while MultiByteToWideChar and WideCharToMultiByte 405 - * only need kernel32.dll. 406 - */ 407 - if ((Stream->Mode == WideText) || (Stream->Mode == UTF16Text)) 408 - { 409 - #ifndef _UNICODE // UNICODE means that TCHAR == WCHAR == UTF-16 410 - /* Convert from the current process/thread's codepage to UTF-16 */ 411 - WCHAR *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR)); 412 - if (!buffer) 413 - { 414 - SetLastError(ERROR_NOT_ENOUGH_MEMORY); 415 - return 0; 416 - } 417 - len = (DWORD)MultiByteToWideChar(CP_THREAD_ACP, // CP_ACP, CP_OEMCP 418 - 0, szStr, (INT)len, buffer, (INT)len); 419 - szStr = (PVOID)buffer; 420 - #else 421 - /* 422 - * Do not perform any conversion since we are already in UTF-16, 423 - * that is the same encoding as the stream. 424 - */ 425 - #endif 426 - 427 - /* 428 - * Find any newline character in the buffer, 429 - * write the part BEFORE the newline, then write 430 - * a carriage-return + newline, and then write 431 - * the remaining part of the buffer. 432 - * 433 - * This fixes output in files and serial console. 434 - */ 435 - while (len > 0) 436 - { 437 - /* Loop until we find a \r or \n character */ 438 - // FIXME: What about the pair \r\n ? 439 - p = szStr; 440 - while (len > 0 && *(PWCHAR)p != L'\r' && *(PWCHAR)p != L'\n') 441 - { 442 - /* Advance one character */ 443 - p = (PVOID)((PWCHAR)p + 1); 444 - len--; 445 - } 446 - 447 - /* Write everything up to \r or \n */ 448 - dwNumBytes = ((PWCHAR)p - (PWCHAR)szStr) * sizeof(WCHAR); 449 - WriteFile(Stream->hHandle, szStr, dwNumBytes, &dwNumBytes, NULL); 450 - 451 - /* If we hit \r or \n ... */ 452 - if (len > 0 && (*(PWCHAR)p == L'\r' || *(PWCHAR)p == L'\n')) 453 - { 454 - /* ... send a carriage-return + newline sequence and skip \r or \n */ 455 - WriteFile(Stream->hHandle, L"\r\n", 2 * sizeof(WCHAR), &dwNumBytes, NULL); 456 - szStr = (PVOID)((PWCHAR)p + 1); 457 - len--; 458 - } 459 - } 460 - 461 - #ifndef _UNICODE 462 - HeapFree(GetProcessHeap(), 0, buffer); 463 - #endif 464 - } 465 - else if ((Stream->Mode == UTF8Text) || (Stream->Mode == AnsiText)) 466 - { 467 - CHAR *buffer; 468 - 469 - /* 470 - * Resolve the codepage cache if it was not assigned yet 471 - * (only if the stream is in ANSI mode; in UTF8 mode the 472 - * codepage was already set to CP_UTF8). 473 - */ 474 - if (/*(Stream->Mode == AnsiText) &&*/ (Stream->CodePage == INVALID_CP)) 475 - Stream->CodePage = GetConsoleOutputCP(); // CP_ACP, CP_OEMCP 476 - 477 - #ifdef _UNICODE // UNICODE means that TCHAR == WCHAR == UTF-16 478 - /* Convert from UTF-16 to either UTF-8 or ANSI, using stream codepage */ 479 - // NOTE: MB_LEN_MAX defined either in limits.h or in stdlib.h . 480 - buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * MB_LEN_MAX); 481 - if (!buffer) 482 - { 483 - SetLastError(ERROR_NOT_ENOUGH_MEMORY); 484 - return 0; 485 - } 486 - len = WideCharToMultiByte(Stream->CodePage, 0, 487 - szStr, len, buffer, len * MB_LEN_MAX, 488 - NULL, NULL); 489 - szStr = (PVOID)buffer; 490 - #else 491 - /* 492 - * Convert from the current process/thread's codepage to either 493 - * UTF-8 or ANSI, using stream codepage. 494 - * We need to perform a double conversion, by going through UTF-16. 495 - */ 496 - // TODO! 497 - #error "Need to implement double conversion!" 498 - #endif 499 - 500 - /* 501 - * Find any newline character in the buffer, 502 - * write the part BEFORE the newline, then write 503 - * a carriage-return + newline, and then write 504 - * the remaining part of the buffer. 505 - * 506 - * This fixes output in files and serial console. 507 - */ 508 - while (len > 0) 509 - { 510 - /* Loop until we find a \r or \n character */ 511 - // FIXME: What about the pair \r\n ? 512 - p = szStr; 513 - while (len > 0 && *(PCHAR)p != '\r' && *(PCHAR)p != '\n') 514 - { 515 - /* Advance one character */ 516 - p = (PVOID)((PCHAR)p + 1); 517 - len--; 518 - } 519 - 520 - /* Write everything up to \r or \n */ 521 - dwNumBytes = ((PCHAR)p - (PCHAR)szStr) * sizeof(CHAR); 522 - WriteFile(Stream->hHandle, szStr, dwNumBytes, &dwNumBytes, NULL); 523 - 524 - /* If we hit \r or \n ... */ 525 - if (len > 0 && (*(PCHAR)p == '\r' || *(PCHAR)p == '\n')) 526 - { 527 - /* ... send a carriage-return + newline sequence and skip \r or \n */ 528 - WriteFile(Stream->hHandle, "\r\n", 2, &dwNumBytes, NULL); 529 - szStr = (PVOID)((PCHAR)p + 1); 530 - len--; 531 - } 532 - } 533 - 534 - #ifdef _UNICODE 535 - HeapFree(GetProcessHeap(), 0, buffer); 536 - #else 537 - // TODO! 538 - #endif 539 - } 540 - else // if (Stream->Mode == Binary) 541 - { 542 - /* Directly output the string */ 543 - WriteFile(Stream->hHandle, szStr, len, &dwNumBytes, NULL); 544 - } 545 - 546 - // FIXME! 547 - return (INT)TotalLen; 548 - 549 - #else /* defined(USE_CRT) */ 550 - 551 - DWORD total = len; 552 - DWORD written = 0; 553 - 554 - /* If we do not write anything, just return */ 555 - if (!szStr || len == 0) 556 - return 0; 557 - 558 - #if 1 559 - /* 560 - * There is no "counted" printf-to-stream or puts-like function, therefore 561 - * we use this trick to output the counted string to the stream. 562 - */ 563 - while (1) 564 - { 565 - written = fwprintf(Stream->fStream, L"%.*s", total, szStr); 566 - if (written < total) 567 - { 568 - /* 569 - * Some embedded NULL or special character 570 - * was encountered, print it apart. 571 - */ 572 - if (written == 0) 573 - { 574 - fputwc(*szStr, Stream->fStream); 575 - written++; 576 - } 577 - 578 - szStr += written; 579 - total -= written; 580 - } 581 - else 582 - { 583 - break; 584 - } 585 - } 586 - return (INT)len; 587 - #else 588 - /* ANSI text or Binary output only */ 589 - _setmode(_fileno(Stream->fStream), _O_TEXT); // _O_BINARY 590 - return fwrite(szStr, sizeof(*szStr), len, Stream->fStream); 591 - #endif 592 - 593 - #endif /* defined(USE_CRT) */ 594 - } 595 - 596 - 597 - #define CON_STREAM_WRITE_CALL(Stream, Str, Len) \ 598 - (Stream)->WriteFunc((Stream), (Str), (Len)); 599 - 600 - /* Lock the stream only in non-USE_CRT mode (otherwise use the CRT stream lock) */ 601 - #ifndef USE_CRT 602 - 603 - #define CON_STREAM_WRITE2(Stream, Str, Len, RetLen) \ 604 - do { \ 605 - EnterCriticalSection(&(Stream)->Lock); \ 606 - (RetLen) = CON_STREAM_WRITE_CALL((Stream), (Str), (Len)); \ 607 - LeaveCriticalSection(&(Stream)->Lock); \ 608 - } while(0) 609 - 610 - #define CON_STREAM_WRITE(Stream, Str, Len) \ 611 - do { \ 612 - EnterCriticalSection(&(Stream)->Lock); \ 613 - CON_STREAM_WRITE_CALL((Stream), (Str), (Len)); \ 614 - LeaveCriticalSection(&(Stream)->Lock); \ 615 - } while(0) 616 - 617 - #else 618 - 619 - #define CON_STREAM_WRITE2(Stream, Str, Len, RetLen) \ 620 - do { \ 621 - (RetLen) = CON_STREAM_WRITE_CALL((Stream), (Str), (Len)); \ 622 - } while(0) 623 - 624 - #define CON_STREAM_WRITE(Stream, Str, Len) \ 625 - do { \ 626 - CON_STREAM_WRITE_CALL((Stream), (Str), (Len)); \ 627 - } while(0) 628 - 629 - #endif 630 - 631 - 632 - INT 633 - ConStreamWrite( 634 - IN PCON_STREAM Stream, 635 - IN PTCHAR szStr, 636 - IN DWORD len) 637 - { 638 - INT Len; 639 - CON_STREAM_WRITE2(Stream, szStr, len, Len); 640 - return Len; 641 - } 642 - 643 - INT 644 - ConPuts( 645 - IN PCON_STREAM Stream, 646 - IN LPWSTR szStr) 647 - { 648 - INT Len; 649 - 650 - Len = wcslen(szStr); 651 - CON_STREAM_WRITE2(Stream, szStr, Len, Len); 652 - 653 - /* Fixup returned length in case of errors */ 654 - if (Len < 0) 655 - Len = 0; 656 - 657 - return Len; 658 - } 659 - 660 - INT 661 - ConPrintfV( 662 - IN PCON_STREAM Stream, 663 - IN LPWSTR szStr, 664 - IN va_list args) // arg_ptr 665 - { 666 - INT Len; 667 - WCHAR bufSrc[CON_RC_STRING_MAX_SIZE]; 668 - 669 - // Len = vfwprintf(Stream->fStream, szStr, args); // vfprintf for direct ANSI 670 - 671 - /* 672 - * Reuse szStr as the pointer to end-of-string, to compute 673 - * the string length instead of calling wcslen(). 674 - */ 675 - // StringCchVPrintfW(bufSrc, ARRAYSIZE(bufSrc), szStr, args); 676 - // Len = wcslen(bufSrc); 677 - StringCchVPrintfExW(bufSrc, ARRAYSIZE(bufSrc), &szStr, NULL, 0, szStr, args); 678 - Len = szStr - bufSrc; 679 - 680 - CON_STREAM_WRITE2(Stream, bufSrc, Len, Len); 681 - 682 - /* Fixup returned length in case of errors */ 683 - if (Len < 0) 684 - Len = 0; 685 - 686 - return Len; 687 - } 688 - 689 - INT 690 - __cdecl 691 - ConPrintf( 692 - IN PCON_STREAM Stream, 693 - IN LPWSTR szStr, 694 - ...) 695 - { 696 - INT Len; 697 - va_list args; 698 - 699 - // Len = vfwprintf(Stream->fStream, szMsgBuf, args); // vfprintf for direct ANSI 700 - 701 - // StringCchPrintfW 702 - va_start(args, szStr); 703 - Len = ConPrintfV(Stream, szStr, args); 704 - va_end(args); 705 - 706 - return Len; 707 - } 708 - 709 - INT 710 - ConResPutsEx( 711 - IN PCON_STREAM Stream, 712 - IN HINSTANCE hInstance OPTIONAL, 713 - IN UINT uID) 714 - { 715 - INT Len; 716 - PWCHAR szStr = NULL; 717 - 718 - Len = K32LoadStringW(hInstance, uID, (PWSTR)&szStr, 0); 719 - if (szStr && Len) 720 - // Len = ConPuts(Stream, szStr); 721 - CON_STREAM_WRITE2(Stream, szStr, Len, Len); 722 - 723 - /* Fixup returned length in case of errors */ 724 - if (Len < 0) 725 - Len = 0; 726 - 727 - return Len; 728 - } 729 - 730 - INT 731 - ConResPuts( 732 - IN PCON_STREAM Stream, 733 - IN UINT uID) 734 - { 735 - return ConResPutsEx(Stream, NULL /*GetModuleHandleW(NULL)*/, uID); 736 - } 737 - 738 - INT 739 - ConResPrintfExV( 740 - IN PCON_STREAM Stream, 741 - IN HINSTANCE hInstance OPTIONAL, 742 - IN UINT uID, 743 - IN va_list args) // arg_ptr 744 - { 745 - INT Len; 746 - WCHAR bufSrc[CON_RC_STRING_MAX_SIZE]; 747 - 748 - // NOTE: We may use the special behaviour where nBufMaxSize == 0 749 - Len = K32LoadStringW(hInstance, uID, bufSrc, ARRAYSIZE(bufSrc)); 750 - if (Len) 751 - Len = ConPrintfV(Stream, bufSrc, args); 752 - 753 - return Len; 754 - } 755 - 756 - INT 757 - ConResPrintfV( 758 - IN PCON_STREAM Stream, 759 - IN UINT uID, 760 - IN va_list args) // arg_ptr 761 - { 762 - return ConResPrintfExV(Stream, NULL /*GetModuleHandleW(NULL)*/, uID, args); 763 - } 764 - 765 - INT 766 - __cdecl 767 - ConResPrintfEx( 768 - IN PCON_STREAM Stream, 769 - IN HINSTANCE hInstance OPTIONAL, 770 - IN UINT uID, 771 - ...) 772 - { 773 - INT Len; 774 - va_list args; 775 - 776 - va_start(args, uID); 777 - Len = ConResPrintfExV(Stream, hInstance, uID, args); 778 - va_end(args); 779 - 780 - return Len; 781 - } 782 - 783 - INT 784 - __cdecl 785 - ConResPrintf( 786 - IN PCON_STREAM Stream, 787 - IN UINT uID, 788 - ...) 789 - { 790 - INT Len; 791 - va_list args; 792 - 793 - va_start(args, uID); 794 - Len = ConResPrintfV(Stream, uID, args); 795 - va_end(args); 796 - 797 - return Len; 798 - } 799 - 800 - INT 801 - ConMsgPuts( 802 - IN PCON_STREAM Stream, 803 - IN DWORD dwFlags, 804 - IN LPCVOID lpSource OPTIONAL, 805 - IN DWORD dwMessageId, 806 - IN DWORD dwLanguageId) 807 - { 808 - INT Len; 809 - DWORD dwLength = 0; 810 - LPWSTR lpMsgBuf = NULL; 811 - 812 - /* 813 - * Sanitize dwFlags. This version always ignore explicitely the inserts 814 - * as we emulate the behaviour of the *puts function. 815 - */ 816 - dwFlags |= FORMAT_MESSAGE_ALLOCATE_BUFFER; // Always allocate an internal buffer. 817 - dwFlags |= FORMAT_MESSAGE_IGNORE_INSERTS; // Ignore inserts for FormatMessage. 818 - dwFlags &= ~FORMAT_MESSAGE_ARGUMENT_ARRAY; 819 - 820 - dwFlags |= FORMAT_MESSAGE_MAX_WIDTH_MASK; 821 - 822 - /* 823 - * Retrieve the message string without appending extra newlines. 824 - * Wrap in SEH to protect from invalid string parameters. 825 - */ 826 - _SEH2_TRY 827 - { 828 - dwLength = FormatMessageW(dwFlags, 829 - lpSource, 830 - dwMessageId, 831 - dwLanguageId, 832 - (LPWSTR)&lpMsgBuf, 833 - 0, NULL); 834 - } 835 - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 836 - { 837 - } 838 - _SEH2_END; 839 - 840 - Len = (INT)dwLength; 841 - 842 - if (!lpMsgBuf) 843 - { 844 - // ASSERT(dwLength == 0); 845 - } 846 - else 847 - { 848 - // ASSERT(dwLength != 0); 849 - 850 - /* lpMsgBuf is NULL-terminated by FormatMessage */ 851 - // Len = ConPuts(Stream, lpMsgBuf); 852 - CON_STREAM_WRITE2(Stream, lpMsgBuf, dwLength, Len); 853 - 854 - /* Fixup returned length in case of errors */ 855 - if (Len < 0) 856 - Len = 0; 857 - 858 - /* Free the buffer allocated by FormatMessage */ 859 - LocalFree(lpMsgBuf); 860 - } 861 - 862 - return Len; 863 - } 864 - 865 - INT 866 - ConMsgPrintf2V( 867 - IN PCON_STREAM Stream, 868 - IN DWORD dwFlags, 869 - IN LPCVOID lpSource OPTIONAL, 870 - IN DWORD dwMessageId, 871 - IN DWORD dwLanguageId, 872 - IN va_list args) // arg_ptr 873 - { 874 - INT Len; 875 - DWORD dwLength = 0; 876 - LPWSTR lpMsgBuf = NULL; 877 - 878 - /* 879 - * Sanitize dwFlags. This version always ignore explicitely the inserts. 880 - * The string that we will return to the user will not be pre-formatted. 881 - */ 882 - dwFlags |= FORMAT_MESSAGE_ALLOCATE_BUFFER; // Always allocate an internal buffer. 883 - dwFlags |= FORMAT_MESSAGE_IGNORE_INSERTS; // Ignore inserts for FormatMessage. 884 - dwFlags &= ~FORMAT_MESSAGE_ARGUMENT_ARRAY; 885 - 886 - dwFlags |= FORMAT_MESSAGE_MAX_WIDTH_MASK; 887 - 888 - /* 889 - * Retrieve the message string without appending extra newlines. 890 - * Wrap in SEH to protect from invalid string parameters. 891 - */ 892 - _SEH2_TRY 893 - { 894 - dwLength = FormatMessageW(dwFlags, 895 - lpSource, 896 - dwMessageId, 897 - dwLanguageId, 898 - (LPWSTR)&lpMsgBuf, 899 - 0, NULL); 900 - } 901 - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 902 - { 903 - } 904 - _SEH2_END; 905 - 906 - Len = (INT)dwLength; 907 - 908 - if (!lpMsgBuf) 909 - { 910 - // ASSERT(dwLength == 0); 911 - } 912 - else 913 - { 914 - // ASSERT(dwLength != 0); 915 - 916 - /* lpMsgBuf is NULL-terminated by FormatMessage */ 917 - Len = ConPrintfV(Stream, lpMsgBuf, args); 918 - // CON_STREAM_WRITE2(Stream, lpMsgBuf, dwLength, Len); 919 - 920 - /* Fixup returned length in case of errors */ 921 - if (Len < 0) 922 - Len = 0; 923 - 924 - /* Free the buffer allocated by FormatMessage */ 925 - LocalFree(lpMsgBuf); 926 - } 927 - 928 - return Len; 929 - } 930 - 931 - INT 932 - ConMsgPrintfV( 933 - IN PCON_STREAM Stream, 934 - IN DWORD dwFlags, 935 - IN LPCVOID lpSource OPTIONAL, 936 - IN DWORD dwMessageId, 937 - IN DWORD dwLanguageId, 938 - IN va_list args) // arg_ptr 939 - { 940 - INT Len; 941 - DWORD dwLength = 0; 942 - LPWSTR lpMsgBuf = NULL; 943 - 944 - /* Sanitize dwFlags */ 945 - dwFlags |= FORMAT_MESSAGE_ALLOCATE_BUFFER; // Always allocate an internal buffer. 946 - // dwFlags &= ~FORMAT_MESSAGE_IGNORE_INSERTS; // We always use arguments. 947 - dwFlags &= ~FORMAT_MESSAGE_ARGUMENT_ARRAY; // We always use arguments of type 'va_list'. 948 - 949 - // 950 - // NOTE: Technique taken from eventvwr.c!GetMessageStringFromDll() 951 - // 952 - 953 - dwFlags |= FORMAT_MESSAGE_MAX_WIDTH_MASK; 954 - 955 - /* 956 - * Retrieve the message string without appending extra newlines. 957 - * Use the "safe" FormatMessage version (SEH-protected) to protect 958 - * from invalid string parameters. 959 - */ 960 - dwLength = FormatMessageSafeW(dwFlags, 961 - lpSource, 962 - dwMessageId, 963 - dwLanguageId, 964 - (LPWSTR)&lpMsgBuf, 965 - 0, &args); 966 - 967 - Len = (INT)dwLength; 968 - 969 - if (!lpMsgBuf) 970 - { 971 - // ASSERT(dwLength == 0); 972 - } 973 - else 974 - { 975 - // ASSERT(dwLength != 0); 976 - 977 - // Len = ConPrintfV(Stream, lpMsgBuf, args); 978 - CON_STREAM_WRITE2(Stream, lpMsgBuf, dwLength, Len); 979 - 980 - /* Fixup returned length in case of errors */ 981 - if (Len < 0) 982 - Len = 0; 983 - 984 - /* Free the buffer allocated by FormatMessage */ 985 - LocalFree(lpMsgBuf); 986 - } 987 - 988 - return Len; 989 - } 990 - 991 - INT 992 - __cdecl 993 - ConMsgPrintf( 994 - IN PCON_STREAM Stream, 995 - IN DWORD dwFlags, 996 - IN LPCVOID lpSource OPTIONAL, 997 - IN DWORD dwMessageId, 998 - IN DWORD dwLanguageId, 999 - ...) 1000 - { 1001 - INT Len; 1002 - va_list args; 1003 - 1004 - va_start(args, dwLanguageId); 1005 - // ConMsgPrintf2V 1006 - Len = ConMsgPrintfV(Stream, 1007 - dwFlags, 1008 - lpSource, 1009 - dwMessageId, 1010 - dwLanguageId, 1011 - args); 1012 - va_end(args); 1013 - 1014 - return Len; 1015 - } 1016 - 1017 - 1018 - 1019 - VOID 1020 - ConClearLine(IN PCON_STREAM Stream) 1021 - { 1022 - HANDLE hOutput = ConStreamGetOSHandle(Stream); 1023 - 1024 - /* 1025 - * Erase the full line where the cursor is, and move 1026 - * the cursor back to the beginning of the line. 1027 - */ 1028 - 1029 - if (IsConsoleHandle(hOutput)) 1030 - { 1031 - CONSOLE_SCREEN_BUFFER_INFO csbi; 1032 - DWORD dwWritten; 1033 - 1034 - GetConsoleScreenBufferInfo(hOutput, &csbi); 1035 - 1036 - csbi.dwCursorPosition.X = 0; 1037 - // csbi.dwCursorPosition.Y; 1038 - 1039 - FillConsoleOutputCharacterW(hOutput, L' ', 1040 - csbi.dwSize.X, 1041 - csbi.dwCursorPosition, 1042 - &dwWritten); 1043 - SetConsoleCursorPosition(hOutput, csbi.dwCursorPosition); 1044 - } 1045 - else if (IsTTYHandle(hOutput)) 1046 - { 1047 - ConPuts(Stream, L"\x1B[2K\x1B[1G"); // FIXME: Just use WriteFile 1048 - } 1049 - // else, do nothing for files 1050 - } 1051 - 299 + /* EOF */
+12 -126
sdk/lib/conutils/stream.h
··· 1 1 /* 2 - * COPYRIGHT: See COPYING in the top level directory 3 - * PROJECT: ReactOS Console Utilities Library 4 - * FILE: sdk/lib/conutils/stream.h 5 - * PURPOSE: Provides basic abstraction wrappers around CRT streams or 6 - * Win32 console API I/O functions, to deal with i18n + Unicode 7 - * related problems. 8 - * PROGRAMMERS: - Hermes Belusca-Maito (for the library); 9 - * - All programmers who wrote the different console applications 10 - * from which I took those functions and improved them. 2 + * PROJECT: ReactOS Console Utilities Library 3 + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 + * PURPOSE: Provides basic abstraction wrappers around CRT streams or 5 + * Win32 console API I/O functions, to deal with i18n + Unicode 6 + * related problems. 7 + * COPYRIGHT: Copyright 2017-2018 ReactOS Team 8 + * Copyright 2017-2018 Hermes Belusca-Maito 11 9 */ 12 10 13 11 #ifndef __STREAM_H__ 14 12 #define __STREAM_H__ 13 + 14 + #pragma once 15 15 16 16 /* 17 17 * Enable this define if you want to only use CRT functions to output ··· 152 152 IN HANDLE Handle); 153 153 154 154 155 - /* 156 - * Console I/O utility API 157 - * (for the moment, only Output) 158 - */ 159 - 160 - INT 161 - __stdcall 162 - ConWrite( 163 - IN PCON_STREAM Stream, 164 - IN PTCHAR szStr, 165 - IN DWORD len); 166 - 167 - INT 168 - ConStreamWrite( 169 - IN PCON_STREAM Stream, 170 - IN PTCHAR szStr, 171 - IN DWORD len); 172 - 173 - INT 174 - ConPuts( 175 - IN PCON_STREAM Stream, 176 - IN LPWSTR szStr); 177 - 178 - INT 179 - ConPrintfV( 180 - IN PCON_STREAM Stream, 181 - IN LPWSTR szStr, 182 - IN va_list args); // arg_ptr 183 - 184 - INT 185 - __cdecl 186 - ConPrintf( 187 - IN PCON_STREAM Stream, 188 - IN LPWSTR szStr, 189 - ...); 190 - 191 - INT 192 - ConResPutsEx( 193 - IN PCON_STREAM Stream, 194 - IN HINSTANCE hInstance OPTIONAL, 195 - IN UINT uID); 196 - 197 - INT 198 - ConResPuts( 199 - IN PCON_STREAM Stream, 200 - IN UINT uID); 201 - 202 - INT 203 - ConResPrintfExV( 204 - IN PCON_STREAM Stream, 205 - IN HINSTANCE hInstance OPTIONAL, 206 - IN UINT uID, 207 - IN va_list args); // arg_ptr 208 - 209 - INT 210 - ConResPrintfV( 211 - IN PCON_STREAM Stream, 212 - IN UINT uID, 213 - IN va_list args); // arg_ptr 214 - 215 - INT 216 - __cdecl 217 - ConResPrintfEx( 218 - IN PCON_STREAM Stream, 219 - IN HINSTANCE hInstance OPTIONAL, 220 - IN UINT uID, 221 - ...); 222 - 223 - INT 224 - __cdecl 225 - ConResPrintf( 226 - IN PCON_STREAM Stream, 227 - IN UINT uID, 228 - ...); 229 - 230 - INT 231 - ConMsgPuts( 232 - IN PCON_STREAM Stream, 233 - IN DWORD dwFlags, 234 - IN LPCVOID lpSource OPTIONAL, 235 - IN DWORD dwMessageId, 236 - IN DWORD dwLanguageId); 237 - 238 - INT 239 - ConMsgPrintf2V( 240 - IN PCON_STREAM Stream, 241 - IN DWORD dwFlags, 242 - IN LPCVOID lpSource OPTIONAL, 243 - IN DWORD dwMessageId, 244 - IN DWORD dwLanguageId, 245 - IN va_list args); // arg_ptr 246 - 247 - INT 248 - ConMsgPrintfV( 249 - IN PCON_STREAM Stream, 250 - IN DWORD dwFlags, 251 - IN LPCVOID lpSource OPTIONAL, 252 - IN DWORD dwMessageId, 253 - IN DWORD dwLanguageId, 254 - IN va_list args); // arg_ptr 255 - 256 - INT 257 - __cdecl 258 - ConMsgPrintf( 259 - IN PCON_STREAM Stream, 260 - IN DWORD dwFlags, 261 - IN LPCVOID lpSource OPTIONAL, 262 - IN DWORD dwMessageId, 263 - IN DWORD dwLanguageId, 264 - ...); 265 - 266 - 267 - 268 - VOID 269 - ConClearLine(IN PCON_STREAM Stream); 270 - 271 - 272 155 #ifdef __cplusplus 273 156 } 274 157 #endif 158 + 275 159 #endif /* __STREAM_H__ */ 160 + 161 + /* EOF */
+55
sdk/lib/conutils/stream_private.h
··· 1 + /* 2 + * PROJECT: ReactOS Console Utilities Library 3 + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 + * PURPOSE: Provides basic abstraction wrappers around CRT streams or 5 + * Win32 console API I/O functions, to deal with i18n + Unicode 6 + * related problems. 7 + * COPYRIGHT: Copyright 2017-2018 ReactOS Team 8 + * Copyright 2017-2018 Hermes Belusca-Maito 9 + */ 10 + 11 + #ifndef __STREAM_PRIVATE_H__ 12 + #define __STREAM_PRIVATE_H__ 13 + 14 + #pragma once 15 + 16 + /* 17 + * Console I/O streams 18 + */ 19 + 20 + #if 0 21 + // Shadow type, implementation-specific 22 + typedef struct _CON_STREAM CON_STREAM, *PCON_STREAM; 23 + #endif 24 + 25 + typedef struct _CON_STREAM 26 + { 27 + CON_WRITE_FUNC WriteFunc; 28 + 29 + #ifdef USE_CRT 30 + FILE* fStream; 31 + #else 32 + BOOL IsInitialized; 33 + CRITICAL_SECTION Lock; 34 + 35 + HANDLE hHandle; 36 + 37 + /* 38 + * TRUE if 'hHandle' refers to a console, in which case I/O UTF-16 39 + * is directly used. If 'hHandle' refers to a file or a pipe, the 40 + * 'Mode' flag is used. 41 + */ 42 + BOOL IsConsole; 43 + 44 + /* 45 + * The 'Mode' flag is used to know the translation mode 46 + * when 'hHandle' refers to a file or a pipe. 47 + */ 48 + CON_STREAM_MODE Mode; 49 + UINT CodePage; // Used to convert UTF-16 text to some ANSI codepage. 50 + #endif /* defined(USE_CRT) */ 51 + } CON_STREAM, *PCON_STREAM; 52 + 53 + #endif /* __STREAM_PRIVATE_H__ */ 54 + 55 + /* EOF */
+8 -8
sdk/lib/conutils/utils.c
··· 1 1 /* 2 - * COPYRIGHT: See COPYING in the top level directory 3 - * PROJECT: ReactOS Console Utilities Library 4 - * FILE: sdk/lib/conutils/utils.c 5 - * PURPOSE: Base set of functions for loading string resources 6 - * and message strings, and handle type identification. 7 - * PROGRAMMERS: - Hermes Belusca-Maito (for the library); 8 - * - All programmers who wrote the different console applications 9 - * from which I took those functions and improved them. 2 + * PROJECT: ReactOS Console Utilities Library 3 + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 + * PURPOSE: Base set of functions for loading string resources 5 + * and message strings, and handle type identification. 6 + * COPYRIGHT: Copyright 2017-2018 ReactOS Team 7 + * Copyright 2017-2018 Hermes Belusca-Maito 10 8 */ 11 9 12 10 /* FIXME: Temporary HACK before we cleanly support UNICODE functions */ ··· 232 230 */ 233 231 return GetConsoleMode(hHandle, &dwMode); 234 232 } 233 + 234 + /* EOF */
+11 -8
sdk/lib/conutils/utils.h
··· 1 1 /* 2 - * COPYRIGHT: See COPYING in the top level directory 3 - * PROJECT: ReactOS Console Utilities Library 4 - * FILE: sdk/lib/conutils/utils.h 5 - * PURPOSE: Base set of functions for loading string resources 6 - * and message strings, and handle type identification. 7 - * PROGRAMMERS: - Hermes Belusca-Maito (for the library); 8 - * - All programmers who wrote the different console applications 9 - * from which I took those functions and improved them. 2 + * PROJECT: ReactOS Console Utilities Library 3 + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 + * PURPOSE: Base set of functions for loading string resources 5 + * and message strings, and handle type identification. 6 + * COPYRIGHT: Copyright 2017-2018 ReactOS Team 7 + * Copyright 2017-2018 Hermes Belusca-Maito 10 8 */ 11 9 12 10 #ifndef __UTILS_H__ 13 11 #define __UTILS_H__ 12 + 13 + #pragma once 14 14 15 15 #ifndef _UNICODE 16 16 #error The ConUtils library at the moment only supports compilation with _UNICODE defined! ··· 57 57 #ifdef __cplusplus 58 58 } 59 59 #endif 60 + 60 61 #endif /* __UTILS_H__ */ 62 + 63 + /* EOF */