ReactOS 0.4.16-dev-747-gbc52d5f
more.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS More Command
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Displays text stream from STDIN or from an arbitrary number
5 * of files to STDOUT, with screen capabilities (more than CAT,
6 * but less than LESS ^^).
7 * COPYRIGHT: Copyright 1999 Paolo Pantaleo
8 * Copyright 2003 Timothy Schepens
9 * Copyright 2016-2021 Hermes Belusca-Maito
10 * Copyright 2021 Katayama Hirofumi MZ
11 */
12/*
13 * MORE.C - external command.
14 *
15 * clone from 4nt more command
16 *
17 * 26 Sep 1999 - Paolo Pantaleo <paolopan@freemail.it>
18 * started
19 *
20 * Oct 2003 - Timothy Schepens <tischepe at fastmail dot fm>
21 * use window size instead of buffer size.
22 */
23
24#include <stdio.h>
25#include <stdlib.h>
26
27#include <windef.h>
28#include <winbase.h>
29#include <winnt.h>
30#include <winnls.h>
31#include <winreg.h>
32#include <winuser.h>
33
34#include <conutils.h>
35#include <strsafe.h>
36
37#include "resource.h"
38
39/* PagePrompt statistics for the current file */
40DWORD dwFileSize; // In bytes
42// The average number of bytes per character is equal to
43// dwSumReadBytes / dwSumReadChars. Note that dwSumReadChars
44// will never be == 0 when ConWritePaging (and possibly PagePrompt)
45// is called.
46
47/* Handles for file and console */
51
52/* Enable/Disable extensions */
53BOOL bEnableExtensions = TRUE; // FIXME: By default, it should be FALSE.
54
55/* Parser flags */
56#define FLAG_HELP (1 << 0)
57#define FLAG_E (1 << 1)
58#define FLAG_C (1 << 2)
59#define FLAG_P (1 << 3)
60#define FLAG_S (1 << 4)
61#define FLAG_Tn (1 << 5)
62#define FLAG_PLUSn (1 << 6)
63
64/* Prompt flags */
65#define PROMPT_PERCENT (1 << 0)
66#define PROMPT_LINE_AT (1 << 1)
67#define PROMPT_OPTIONS (1 << 2)
68#define PROMPT_LINES (1 << 3)
69
70static DWORD s_dwFlags = 0;
71static LONG s_nTabWidth = 8;
74static WORD s_fPrompt = 0;
76
78{
79 DWORD ich;
80 WORD wType;
81 for (ich = 0; ich < cch; ++ich)
82 {
83 /*
84 * Explicitly exclude FORM-FEED from the check,
85 * so that the pager can handle it.
86 */
87 if (line[ich] == L'\f')
88 return FALSE;
89
90 /*
91 * Otherwise do the extended blanks check.
92 * Note that MS MORE.COM only checks for spaces (\x20) and TABs (\x09).
93 * See http://archives.miloush.net/michkap/archive/2007/06/11/3230072.html
94 * for more information.
95 */
96 wType = 0;
97 GetStringTypeW(CT_CTYPE1, &line[ich], 1, &wType);
98 if (!(wType & (C1_BLANK | C1_SPACE)))
99 return FALSE;
100 }
101 return TRUE;
102}
103
104static BOOL
107 IN OUT PCON_PAGER Pager,
108 IN PCWCH line,
109 IN DWORD cch)
110{
111 if (s_dwFlags & FLAG_PLUSn) /* Skip lines */
112 {
113 if (Pager->lineno < s_nNextLineNo)
114 {
116 return TRUE; /* Handled */
117 }
118 s_dwFlags &= ~FLAG_PLUSn;
119 }
120
121 if (s_dwFlags & FLAG_S) /* Shrink blank lines */
122 {
123 if (IsBlankLine(line, cch))
124 {
126 return TRUE; /* Handled */
127
128 /*
129 * Display a single blank line, independently of the actual size
130 * of the current line, by displaying just one space: this is
131 * especially needed in order to force line wrapping when the
132 * ENABLE_VIRTUAL_TERMINAL_PROCESSING or DISABLE_NEWLINE_AUTO_RETURN
133 * console modes are enabled.
134 * Then, reposition the cursor to the next line, first column.
135 */
136 if (Pager->PageColumns > 0)
137 ConStreamWrite(Pager->Screen->Stream, TEXT(" "), 1);
138 ConStreamWrite(Pager->Screen->Stream, TEXT("\n"), 1);
139 Pager->iLine++;
140 Pager->iColumn = 0;
141
143 s_nNextLineNo = 0;
144
145 return TRUE; /* Handled */
146 }
147 else
148 {
150 }
151 }
152
153 s_nNextLineNo = 0;
154 /* Not handled, let the pager do the default action */
155 return FALSE;
156}
157
158static BOOL
160PagePrompt(PCON_PAGER Pager, DWORD Done, DWORD Total)
161{
163 HANDLE hOutput = ConStreamGetOSHandle(Pager->Screen->Stream);
165 COORD orgCursorPosition;
166 DWORD dwMode;
167
168 KEY_EVENT_RECORD KeyEvent;
169 BOOL fCtrl;
170 DWORD nLines;
171 WCHAR chSubCommand = 0;
172
173 /* Prompt strings (small size since the prompt should
174 * hold ideally on one <= 80-character line) */
175 static WCHAR StrPercent[80] = L"";
176 static WCHAR StrLineAt[80] = L"";
177 static WCHAR StrOptions[80] = L"";
178 static WCHAR StrLines[80] = L"";
179 static BOOL AreStrLoaded = FALSE;
180
181 WCHAR szPercent[80] = L"";
182 WCHAR szLineAt[80] = L"";
183
184 /* Load the prompt strings */
185 if (!AreStrLoaded)
186 {
187 K32LoadStringW(NULL, IDS_CONTINUE_PERCENT, StrPercent, ARRAYSIZE(StrPercent));
188 K32LoadStringW(NULL, IDS_CONTINUE_LINE_AT, StrLineAt, ARRAYSIZE(StrLineAt));
189 K32LoadStringW(NULL, IDS_CONTINUE_OPTIONS, StrOptions, ARRAYSIZE(StrOptions));
190 K32LoadStringW(NULL, IDS_CONTINUE_LINES, StrLines, ARRAYSIZE(StrLines));
191 AreStrLoaded = TRUE;
192 }
193
194 /*
195 * Check whether the pager is prompting, but we have actually finished
196 * to display a given file, or no data is present in STDIN anymore.
197 * In this case, skip the prompt altogether. The only exception is when
198 * we are displaying other files.
199 */
200 // TODO: Implement!
201
202Restart:
203 nLines = 0;
204
205 /* Do not show the progress percentage when STDIN is being displayed */
206 if (s_fPrompt & PROMPT_PERCENT) // && (hFile != hStdIn)
207 {
208 /*
209 * The progress percentage is evaluated as follows.
210 * So far we have read a total of 'dwSumReadBytes' bytes from the file.
211 * Amongst those is the latest read chunk of 'dwReadBytes' bytes, to which
212 * correspond a number of 'dwReadChars' characters with which we have called
213 * ConWritePaging who called PagePrompt. We then have: Total == dwReadChars.
214 * During this ConWritePaging call the PagePrompt was called after 'Done'
215 * number of characters over 'Total'.
216 * It should be noted that for 'dwSumReadBytes' number of bytes read it
217 * *roughly* corresponds 'dwSumReadChars' number of characters. This is
218 * because there may be some failures happening during the conversion of
219 * the bytes read to the character string for a given encoding.
220 * Therefore the number of characters displayed on screen is equal to:
221 * dwSumReadChars - Total + Done ,
222 * but the best corresponding approximed number of bytes would be:
223 * dwSumReadBytes - (Total - Done) * (dwSumReadBytes / dwSumReadChars) ,
224 * where the ratio is the average number of bytes per character.
225 * The percentage is then computed relative to the total file size.
226 */
227 DWORD dwPercent = (dwSumReadBytes - (Total - Done) *
229 StringCchPrintfW(szPercent, ARRAYSIZE(szPercent), StrPercent, dwPercent);
230 }
232 {
233 StringCchPrintfW(szLineAt, ARRAYSIZE(szLineAt), StrLineAt, Pager->lineno);
234 }
235
236 /* Suitably format and display the prompt */
239 (s_fPrompt & PROMPT_LINE_AT ? szLineAt : L""),
240 (s_fPrompt & PROMPT_OPTIONS ? StrOptions : L""),
241 (s_fPrompt & PROMPT_LINES ? StrLines : L""));
242
243 /* Reset the prompt to a default state */
245
246 /* RemoveBreakHandler */
248 /* ConInDisable */
249 GetConsoleMode(hInput, &dwMode);
250 dwMode &= ~ENABLE_PROCESSED_INPUT;
251 SetConsoleMode(hInput, dwMode);
252
253 // FIXME: Does not support TTY yet!
254 ConGetScreenInfo(Pager->Screen, &csbi);
255 orgCursorPosition = csbi.dwCursorPosition;
256 for (;;)
257 {
258 INPUT_RECORD ir = {0};
259 DWORD dwRead;
260 WCHAR ch;
261
262 do
263 {
264 ReadConsoleInput(hInput, &ir, 1, &dwRead);
265 }
266 while ((ir.EventType != KEY_EVENT) || (!ir.Event.KeyEvent.bKeyDown));
267
268 /* Got our key */
269 KeyEvent = ir.Event.KeyEvent;
270
271 /* Ignore any unsupported keyboard press */
272 if ((KeyEvent.wVirtualKeyCode == VK_SHIFT) ||
273 (KeyEvent.wVirtualKeyCode == VK_MENU) ||
274 (KeyEvent.wVirtualKeyCode == VK_CONTROL))
275 {
276 continue;
277 }
278
279 /* Ctrl key is pressed? */
280 fCtrl = !!(KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED));
281
282 /* Ctrl+C or Ctrl+Esc? */
283 if (fCtrl && ((KeyEvent.wVirtualKeyCode == VK_ESCAPE) ||
284 (KeyEvent.wVirtualKeyCode == L'C')))
285 {
286 chSubCommand = 0;
287 break;
288 }
289
290 /* If extended features are unavailable, or no
291 * pending commands, don't do more processing. */
292 if (!(s_dwFlags & FLAG_E) || (chSubCommand == 0))
293 break;
294
295 ch = KeyEvent.uChar.UnicodeChar;
296 if (L'0' <= ch && ch <= L'9')
297 {
298 nLines *= 10;
299 nLines += ch - L'0';
300 ConStreamWrite(Pager->Screen->Stream, &ch, 1);
301 continue;
302 }
303 else if (KeyEvent.wVirtualKeyCode == VK_RETURN)
304 {
305 /* Validate the line number */
306 break;
307 }
308 else if (KeyEvent.wVirtualKeyCode == VK_ESCAPE)
309 {
310 /* Cancel the current command */
311 chSubCommand = 0;
312 break;
313 }
314 else if (KeyEvent.wVirtualKeyCode == VK_BACK)
315 {
316 if (nLines != 0)
317 nLines /= 10;
318
319 /* Erase the current character */
320 ConGetScreenInfo(Pager->Screen, &csbi);
321 if ( (csbi.dwCursorPosition.Y > orgCursorPosition.Y) ||
322 ((csbi.dwCursorPosition.Y == orgCursorPosition.Y) &&
323 (csbi.dwCursorPosition.X > orgCursorPosition.X)) )
324 {
325 if (csbi.dwCursorPosition.X > 0)
326 {
327 csbi.dwCursorPosition.X = csbi.dwCursorPosition.X - 1;
328 }
329 else if (csbi.dwCursorPosition.Y > 0)
330 {
331 csbi.dwCursorPosition.Y = csbi.dwCursorPosition.Y - 1;
332 csbi.dwCursorPosition.X = (csbi.dwSize.X ? csbi.dwSize.X - 1 : 0);
333 }
334
336
337 ch = L' ';
338 ConStreamWrite(Pager->Screen->Stream, &ch, 1);
340 }
341
342 continue;
343 }
344 }
345
346 /* AddBreakHandler */
348 /* ConInEnable */
349 GetConsoleMode(hInput, &dwMode);
350 dwMode |= ENABLE_PROCESSED_INPUT;
351 SetConsoleMode(hInput, dwMode);
352
353 /* Refresh the screen information, as the console may have been
354 * redimensioned. Update also the default number of lines to scroll. */
355 ConGetScreenInfo(Pager->Screen, &csbi);
356 Pager->ScrollRows = csbi.srWindow.Bottom - csbi.srWindow.Top;
357
358 /*
359 * Erase the full line where the cursor is, and move
360 * the cursor back to the beginning of the line.
361 */
362 ConClearLine(Pager->Screen->Stream);
363
364 /* Ctrl+C or Ctrl+Esc: Control Break */
365 if (fCtrl && ((KeyEvent.wVirtualKeyCode == VK_ESCAPE) ||
366 (KeyEvent.wVirtualKeyCode == L'C')))
367 {
368 /* We break, output a newline */
369 WCHAR ch = L'\n';
370 ConStreamWrite(Pager->Screen->Stream, &ch, 1);
371 return FALSE;
372 }
373
374 switch (chSubCommand)
375 {
376 case L'P':
377 {
378 /* If we don't display other lines, just restart the prompt */
379 if (nLines == 0)
380 {
381 chSubCommand = 0;
382 goto Restart;
383 }
384 /* Otherwise tell the pager to display them */
385 Pager->ScrollRows = nLines;
386 return TRUE;
387 }
388 case L'S':
389 {
391 s_nNextLineNo = Pager->lineno + nLines;
392 /* Use the default Pager->ScrollRows value */
393 return TRUE;
394 }
395 default:
396 chSubCommand = 0;
397 break;
398 }
399
400 /* If extended features are available */
401 if (s_dwFlags & FLAG_E)
402 {
403 /* Ignore any key presses if Ctrl is pressed */
404 if (fCtrl)
405 {
406 chSubCommand = 0;
407 goto Restart;
408 }
409
410 /* 'Q': Quit */
411 if (KeyEvent.wVirtualKeyCode == L'Q')
412 {
413 /* We break, output a newline */
414 WCHAR ch = L'\n';
415 ConStreamWrite(Pager->Screen->Stream, &ch, 1);
416 return FALSE;
417 }
418
419 /* 'F': Next file */
420 if (KeyEvent.wVirtualKeyCode == L'F')
421 {
423 return FALSE;
424 }
425
426 /* '?': Show Options */
427 if (KeyEvent.uChar.UnicodeChar == L'?')
428 {
430 goto Restart;
431 }
432
433 /* [Enter] key: Display one line */
434 if (KeyEvent.wVirtualKeyCode == VK_RETURN)
435 {
436 Pager->ScrollRows = 1;
437 return TRUE;
438 }
439
440 /* [Space] key: Display one page */
441 if (KeyEvent.wVirtualKeyCode == VK_SPACE)
442 {
443 if (s_dwFlags & FLAG_C)
444 {
445 /* Clear the screen */
446 ConClearScreen(Pager->Screen);
447 }
448 /* Use the default Pager->ScrollRows value */
449 return TRUE;
450 }
451
452 /* 'P': Display n lines */
453 if (KeyEvent.wVirtualKeyCode == L'P')
454 {
456 chSubCommand = L'P';
457 goto Restart;
458 }
459
460 /* 'S': Skip n lines */
461 if (KeyEvent.wVirtualKeyCode == L'S')
462 {
464 chSubCommand = L'S';
465 goto Restart;
466 }
467
468 /* '=': Show current line number */
469 if (KeyEvent.uChar.UnicodeChar == L'=')
470 {
472 goto Restart;
473 }
474
475 chSubCommand = 0;
476 goto Restart;
477 }
478 else
479 {
480 /* Extended features are unavailable: display one page */
481 /* Use the default Pager->ScrollRows value */
482 return TRUE;
483 }
484}
485
486/*
487 * See base/applications/cmdutils/clip/clip.c!IsDataUnicode()
488 * and base/applications/notepad/text.c!ReadText() for more details.
489 * Also some good code example can be found at:
490 * https://github.com/AutoItConsulting/text-encoding-detect
491 */
492typedef enum
493{
497 ENCODING_UTF8 = 3
499
500static BOOL
504 OUT ENCODING* Encoding OPTIONAL,
506{
507 PBYTE pBytes = Buffer;
508 ENCODING encFile = ENCODING_ANSI;
509 DWORD dwPos = 0;
510
511 /*
512 * See http://archives.miloush.net/michkap/archive/2007/04/22/2239345.html
513 * for more details about the algorithm and the pitfalls behind it.
514 * Of course it would be actually great to make a nice function that
515 * would work, once and for all, and put it into a library.
516 */
517
518 /* Look for Byte Order Marks */
519 if ((BufferSize >= 2) && (pBytes[0] == 0xFF) && (pBytes[1] == 0xFE))
520 {
521 encFile = ENCODING_UTF16LE;
522 dwPos = 2;
523 }
524 else if ((BufferSize >= 2) && (pBytes[0] == 0xFE) && (pBytes[1] == 0xFF))
525 {
526 encFile = ENCODING_UTF16BE;
527 dwPos = 2;
528 }
529 else if ((BufferSize >= 3) && (pBytes[0] == 0xEF) && (pBytes[1] == 0xBB) && (pBytes[2] == 0xBF))
530 {
531 encFile = ENCODING_UTF8;
532 dwPos = 3;
533 }
534 else
535 {
536 /*
537 * Try using statistical analysis. Do not rely on the return value of
538 * IsTextUnicode as we can get FALSE even if the text is in UTF-16 BE
539 * (i.e. we have some of the IS_TEXT_UNICODE_REVERSE_MASK bits set).
540 * Instead, set all the tests we want to perform, then just check
541 * the passed tests and try to deduce the string properties.
542 */
543
544/*
545 * This mask contains the 3 highest bits from IS_TEXT_UNICODE_NOT_ASCII_MASK
546 * and the 1st highest bit from IS_TEXT_UNICODE_NOT_UNICODE_MASK.
547 */
548#define IS_TEXT_UNKNOWN_FLAGS_MASK ((7 << 13) | (1 << 11))
549
550 /* Flag out the unknown flags here, the passed tests will not have them either */
555 INT Results;
556
558 Results = Tests;
559
560 /*
561 * As the IS_TEXT_UNICODE_NULL_BYTES or IS_TEXT_UNICODE_ILLEGAL_CHARS
562 * flags are expected to be potentially present in the result without
563 * modifying our expectations, filter them out now.
564 */
566
567 /*
568 * NOTE: The flags IS_TEXT_UNICODE_ASCII16 and
569 * IS_TEXT_UNICODE_REVERSE_ASCII16 are not reliable.
570 *
571 * NOTE2: Check for potential "bush hid the facts" effect by also
572 * checking the original results (in 'Tests') for the absence of
573 * the IS_TEXT_UNICODE_NULL_BYTES flag, as we may presumably expect
574 * that in UTF-16 text there will be at some point some NULL bytes.
575 * If not, fall back to ANSI. This shows the limitations of using the
576 * IsTextUnicode API to perform such tests, and the usage of a more
577 * improved encoding detection algorithm would be really welcome.
578 */
579 if (!(Results & IS_TEXT_UNICODE_NOT_UNICODE_MASK) &&
580 !(Results & IS_TEXT_UNICODE_REVERSE_MASK) &&
581 (Results & IS_TEXT_UNICODE_UNICODE_MASK) &&
583 {
584 encFile = ENCODING_UTF16LE;
585 dwPos = (Results & IS_TEXT_UNICODE_SIGNATURE) ? 2 : 0;
586 }
587 else
588 if (!(Results & IS_TEXT_UNICODE_NOT_UNICODE_MASK) &&
589 !(Results & IS_TEXT_UNICODE_UNICODE_MASK) &&
590 (Results & IS_TEXT_UNICODE_REVERSE_MASK) &&
592 {
593 encFile = ENCODING_UTF16BE;
594 dwPos = (Results & IS_TEXT_UNICODE_REVERSE_SIGNATURE) ? 2 : 0;
595 }
596 else
597 {
598 /*
599 * Either 'Results' has neither of those masks set, as it can be
600 * the case for UTF-8 text (or ANSI), or it has both as can be the
601 * case when analysing pure binary data chunk. This is therefore
602 * invalid and we fall back to ANSI encoding.
603 * FIXME: In case of failure, assume ANSI (as long as we do not have
604 * correct tests for UTF8, otherwise we should do them, and at the
605 * very end, assume ANSI).
606 */
607 encFile = ENCODING_ANSI; // ENCODING_UTF8;
608 dwPos = 0;
609 }
610 }
611
612 if (Encoding)
613 *Encoding = encFile;
614 if (SkipBytes)
615 *SkipBytes = dwPos;
616
617 return (encFile != ENCODING_ANSI);
618}
619
620/*
621 * Adapted from base/shell/cmd/misc.c!FileGetString(), but with correct
622 * text encoding support. Also please note that similar code should be
623 * also used in the CMD.EXE 'TYPE' command.
624 * Contrary to CMD's FileGetString() we do not stop at new-lines.
625 *
626 * Read text data from a file and convert it from a given encoding to UTF-16.
627 *
628 * IN OUT PVOID pCacheBuffer and IN DWORD CacheBufferLength :
629 * Implementation detail so that the function uses an external user-provided
630 * buffer to store the data temporarily read from the file. The function
631 * could have used an internal buffer instead. The length is in number of bytes.
632 *
633 * IN OUT PWSTR* pBuffer and IN OUT PDWORD pnBufferLength :
634 * Reallocated buffer containing the string data converted to UTF-16.
635 * In input, contains a pointer to the original buffer and its length.
636 * In output, contains a pointer to the reallocated buffer and its length.
637 * The length is in number of characters.
638 *
639 * At first call to this function, pBuffer can be set to NULL, in which case
640 * when the function returns the pointer will point to a valid buffer.
641 * After the last call to this function, free the pBuffer pointer with:
642 * HeapFree(GetProcessHeap(), 0, *pBuffer);
643 *
644 * If Encoding is set to ENCODING_UTF16LE or ENCODING_UTF16BE, since we are
645 * compiled in UNICODE, no extra conversion is performed and therefore
646 * pBuffer is unused (remains unallocated) and one can directly use the
647 * contents of pCacheBuffer as it is expected to contain valid UTF-16 text.
648 *
649 * OUT PDWORD pdwReadBytes : Number of bytes read from the file (optional).
650 * OUT PDWORD pdwReadChars : Corresponding number of characters read (optional).
651 */
652static BOOL
655 IN ENCODING Encoding,
656 IN OUT PVOID pCacheBuffer,
657 IN DWORD CacheBufferLength,
659 IN OUT PDWORD pnBufferLength,
660 OUT PDWORD pdwReadBytes OPTIONAL,
661 OUT PDWORD pdwReadChars OPTIONAL)
662{
664 UINT CodePage = (UINT)-1;
665 DWORD dwReadBytes;
666 INT len;
667
668 // ASSERT(pCacheBuffer && (CacheBufferLength > 0));
669 // ASSERT(CacheBufferLength % 2 == 0); // Cache buffer length MUST BE even!
670 // ASSERT(pBuffer && pnBufferLength);
671
672 /* Always reset the retrieved number of bytes/characters */
673 if (pdwReadBytes) *pdwReadBytes = 0;
674 if (pdwReadChars) *pdwReadChars = 0;
675
676 Success = ReadFile(hFile, pCacheBuffer, CacheBufferLength, &dwReadBytes, NULL);
677 if (!Success || dwReadBytes == 0)
678 return FALSE;
679
680 if (pdwReadBytes) *pdwReadBytes = dwReadBytes;
681
682 if ((Encoding == ENCODING_ANSI) || (Encoding == ENCODING_UTF8))
683 {
684 /* Conversion is needed */
685
686 if (Encoding == ENCODING_ANSI)
687 CodePage = GetConsoleCP(); // CP_ACP; // FIXME: Cache GetConsoleCP() value.
688 else // if (Encoding == ENCODING_UTF8)
689 CodePage = CP_UTF8;
690
691 /* Retrieve the needed buffer size */
692 len = MultiByteToWideChar(CodePage, 0, pCacheBuffer, dwReadBytes,
693 NULL, 0);
694 if (len == 0)
695 {
696 /* Failure, bail out */
697 return FALSE;
698 }
699
700 /* Initialize the conversion buffer if needed... */
701 if (*pBuffer == NULL)
702 {
703 *pnBufferLength = len;
704 *pBuffer = HeapAlloc(GetProcessHeap(), 0, *pnBufferLength * sizeof(WCHAR));
705 if (*pBuffer == NULL)
706 {
707 // *pBuffer = NULL;
708 *pnBufferLength = 0;
709 // WARN("DEBUG: Cannot allocate memory for *pBuffer!\n");
710 // ConErrFormatMessage(GetLastError());
711 return FALSE;
712 }
713 }
714 /* ... or reallocate only if the new length is greater than the old one */
715 else if (len > *pnBufferLength)
716 {
717 PWSTR OldBuffer = *pBuffer;
718
719 *pnBufferLength = len;
720 *pBuffer = HeapReAlloc(GetProcessHeap(), 0, *pBuffer, *pnBufferLength * sizeof(WCHAR));
721 if (*pBuffer == NULL)
722 {
723 /* Do not leak old buffer */
724 HeapFree(GetProcessHeap(), 0, OldBuffer);
725 // *pBuffer = NULL;
726 *pnBufferLength = 0;
727 // WARN("DEBUG: Cannot reallocate memory for *pBuffer!\n");
728 // ConErrFormatMessage(GetLastError());
729 return FALSE;
730 }
731 }
732
733 /* Now perform the conversion proper */
734 len = MultiByteToWideChar(CodePage, 0, pCacheBuffer, dwReadBytes,
735 *pBuffer, len);
736 dwReadBytes = len;
737 }
738 else
739 {
740 /*
741 * No conversion needed, just convert from big to little endian if needed.
742 * pBuffer and pnBufferLength are left untouched and pCacheBuffer can be
743 * directly used.
744 */
745 PWCHAR pWChars = pCacheBuffer;
746 DWORD i;
747
748 dwReadBytes /= sizeof(WCHAR);
749
750 if (Encoding == ENCODING_UTF16BE)
751 {
752 for (i = 0; i < dwReadBytes; i++)
753 {
754 /* Equivalent to RtlUshortByteSwap: reverse high/low bytes */
755 pWChars[i] = MAKEWORD(HIBYTE(pWChars[i]), LOBYTE(pWChars[i]));
756 }
757 }
758 // else if (Encoding == ENCODING_UTF16LE), we are good, nothing to do.
759 }
760
761 /* Return the number of characters (dwReadBytes is converted) */
762 if (pdwReadChars) *pdwReadChars = dwReadBytes;
763
764 return TRUE;
765}
766
767static VOID
769{
770 LONG lRet;
771 HKEY hKey;
772 DWORD dwType, len;
773 /*
774 * Buffer big enough to hold the string L"4294967295",
775 * corresponding to the literal 0xFFFFFFFF (MAXULONG) in decimal.
776 */
777 WCHAR Buffer[sizeof("4294967295")];
778 C_ASSERT(sizeof(Buffer) >= sizeof(DWORD));
779
780 lRet = RegOpenKeyExW(hKeyRoot,
781 L"Software\\Microsoft\\Command Processor",
782 0,
784 &hKey);
785 if (lRet != ERROR_SUCCESS)
786 return;
787
788 len = sizeof(Buffer);
789 lRet = RegQueryValueExW(hKey,
790 L"EnableExtensions",
791 NULL,
792 &dwType,
793 (PBYTE)&Buffer,
794 &len);
795 if (lRet == ERROR_SUCCESS)
796 {
797 /* Overwrite the default setting */
798 if (dwType == REG_DWORD)
800 else if (dwType == REG_SZ)
802 }
803 // else, use the default setting set globally.
804
806}
807
809{
810 PCWSTR pch;
811 PWCHAR endptr;
812
813 if (param[0] == L'/')
814 return TRUE;
815
816 if (param[0] == L'+')
817 {
818 pch = param + 1;
819 if (*pch)
820 {
821 (void)wcstol(pch, &endptr, 10);
822 return (*endptr == 0);
823 }
824 }
825 return FALSE;
826}
827
828static BOOL ParseArgument(PCWSTR arg, BOOL* pbHasFiles)
829{
830 PWCHAR endptr;
831
832 if (arg[0] == L'/')
833 {
834 switch (towupper(arg[1]))
835 {
836 case L'?':
837 if (arg[2] == 0)
838 {
840 return TRUE;
841 }
842 break;
843 case L'E':
844 if (arg[2] == 0)
845 {
846 s_dwFlags |= FLAG_E;
847 return TRUE;
848 }
849 break;
850 case L'C':
851 if (arg[2] == 0)
852 {
853 s_dwFlags |= FLAG_C;
854 return TRUE;
855 }
856 break;
857 case L'P':
858 if (arg[2] == 0)
859 {
860 s_dwFlags |= FLAG_P;
861 return TRUE;
862 }
863 break;
864 case L'S':
865 if (arg[2] == 0)
866 {
867 s_dwFlags |= FLAG_S;
868 return TRUE;
869 }
870 break;
871 case L'T':
872 if (arg[2] != 0)
873 {
875 s_nTabWidth = wcstol(&arg[2], &endptr, 10);
876 if (*endptr == 0)
877 return TRUE;
878 }
879 break;
880 default:
881 break;
882 }
883 }
884 else if (arg[0] == L'+')
885 {
886 if (arg[1] != 0)
887 {
889 s_nNextLineNo = wcstol(&arg[1], &endptr, 10) + 1;
890 if (*endptr == 0)
891 return TRUE;
892 }
893 }
894
895 if (IsFlag(arg))
896 {
898 return FALSE;
899 }
900 else
901 {
902 *pbHasFiles = TRUE;
903 }
904
905 return TRUE;
906}
907
908static BOOL ParseMoreVariable(BOOL* pbHasFiles)
909{
910 BOOL ret = TRUE;
911 PWSTR psz;
912 PWCHAR pch;
913 DWORD cch;
914
915 cch = GetEnvironmentVariableW(L"MORE", NULL, 0);
916 if (cch == 0)
917 return TRUE;
918
919 psz = (PWSTR)malloc((cch + 1) * sizeof(WCHAR));
920 if (!psz)
921 return TRUE;
922
923 if (!GetEnvironmentVariableW(L"MORE", psz, cch + 1))
924 {
925 free(psz);
926 return TRUE;
927 }
928
929 for (pch = wcstok(psz, L" "); pch; pch = wcstok(NULL, L" "))
930 {
931 ret = ParseArgument(pch, pbHasFiles);
932 if (!ret)
933 break;
934 }
935
936 free(psz);
937 return ret;
938}
939
940// INT CommandMore(LPTSTR cmd, LPTSTR param)
941int wmain(int argc, WCHAR* argv[])
942{
943 // FIXME this stuff!
945 CON_PAGER Pager = {&Screen, 0};
946
947 int i;
948
949 BOOL bRet, bContinue;
950
951 ENCODING Encoding;
952 DWORD SkipBytes = 0;
953 BOOL HasFiles;
954
955#define FileCacheBufferSize 4096
956 PVOID FileCacheBuffer = NULL;
958 DWORD StringBufferLength = 0;
959 DWORD dwReadBytes = 0, dwReadChars = 0;
960
961 TCHAR szFullPath[MAX_PATH];
962
965
966 /* Initialize the Console Standard Streams */
970
971 /*
972 * Bad usage (too much options) or we use the /? switch.
973 * Display help for the MORE command.
974 */
975 if (argc > 1 && wcscmp(argv[1], L"/?") == 0)
976 {
978 return 0;
979 }
980
981 /* Load the registry settings */
985 s_dwFlags |= FLAG_E;
986
987 // NOTE: We might try to duplicate the ConOut for read access... ?
990 OPEN_EXISTING, 0, NULL);
993
994 FileCacheBuffer = HeapAlloc(GetProcessHeap(), 0, FileCacheBufferSize);
995 if (!FileCacheBuffer)
996 {
997 ConPuts(StdErr, L"Error: no memory\n");
999 return 1;
1000 }
1001
1002 /* First, load the "MORE" environment variable and parse it,
1003 * then parse the command-line parameters. */
1004 HasFiles = FALSE;
1005 if (!ParseMoreVariable(&HasFiles))
1006 return 1;
1007 for (i = 1; i < argc; i++)
1008 {
1009 if (!ParseArgument(argv[i], &HasFiles))
1010 return 1;
1011 }
1012
1013 if (s_dwFlags & FLAG_HELP)
1014 {
1016 return 0;
1017 }
1018
1019 Pager.PagerLine = MorePagerLine;
1021 if (s_dwFlags & FLAG_P)
1023 Pager.nTabWidth = s_nTabWidth;
1024
1025 /* Special case where we run 'MORE' without any argument: we use STDIN */
1026 if (!HasFiles)
1027 {
1028 /*
1029 * Assign STDIN handle to hFile so that the page prompt function will
1030 * know the data comes from STDIN, and will take different actions.
1031 */
1032 hFile = hStdIn;
1033
1034 /* Update the statistics for PagePrompt */
1035 dwFileSize = 0;
1037
1038 /* We suppose we read text from the file */
1039
1040 /* For STDIN we always suppose we are in ANSI mode */
1041 // SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
1042 Encoding = ENCODING_ANSI; // ENCODING_UTF8;
1043
1044 /* Start paging */
1045 bContinue = ConWritePaging(&Pager, PagePrompt, TRUE, NULL, 0);
1046 if (!bContinue)
1047 goto Quit;
1048
1049 do
1050 {
1051 bRet = FileGetString(hFile, Encoding,
1052 FileCacheBuffer, FileCacheBufferSize,
1053 &StringBuffer, &StringBufferLength,
1054 &dwReadBytes, &dwReadChars);
1055 if (!bRet || dwReadBytes == 0 || dwReadChars == 0)
1056 {
1057 /* We failed at reading the file, bail out */
1058 break;
1059 }
1060
1061 /* Update the statistics for PagePrompt */
1062 dwSumReadBytes += dwReadBytes;
1063 dwSumReadChars += dwReadChars;
1064
1065 bContinue = ConWritePaging(&Pager, PagePrompt, FALSE,
1066 StringBuffer, dwReadChars);
1067 /* If we Ctrl-C/Ctrl-Break, stop everything */
1068 if (!bContinue)
1069 break;
1070 }
1071 while (bRet && dwReadBytes > 0);
1072
1073 /* Flush any cached pager buffers */
1074 if (bContinue)
1075 bContinue = ConWritePaging(&Pager, PagePrompt, FALSE, NULL, 0);
1076
1077 goto Quit;
1078 }
1079
1080 /* We have files: read them and output them to STDOUT */
1081 for (i = 1; i < argc; i++)
1082 {
1083 if (IsFlag(argv[i]))
1084 continue;
1085
1086 GetFullPathNameW(argv[i], ARRAYSIZE(szFullPath), szFullPath, NULL);
1087 hFile = CreateFileW(szFullPath,
1090 NULL,
1092 0, // FILE_ATTRIBUTE_NORMAL,
1093 NULL);
1095 {
1096 ConResPrintf(StdErr, IDS_FILE_ACCESS, szFullPath);
1097 goto Quit;
1098 }
1099
1100 /* We currently do not support files too big */
1103 {
1104 ConPuts(StdErr, L"ERROR: Invalid file size!\n");
1106 continue;
1107 }
1108
1109 /* We suppose we read text from the file */
1110
1111 /* Check whether the file is UNICODE and retrieve its encoding */
1113 bRet = ReadFile(hFile, FileCacheBuffer, FileCacheBufferSize, &dwReadBytes, NULL);
1114 IsDataUnicode(FileCacheBuffer, dwReadBytes, &Encoding, &SkipBytes);
1116
1117 /* Reset state for paging */
1118 s_nNextLineNo = 0;
1122
1123 /* Update the statistics for PagePrompt */
1125
1126 /* Start paging */
1127 bContinue = ConWritePaging(&Pager, PagePrompt, TRUE, NULL, 0);
1128 if (!bContinue)
1129 {
1130 /* We stop displaying this file */
1132 if (s_bDoNextFile)
1133 {
1134 /* Bail out and continue with the other files */
1135 continue;
1136 }
1137
1138 /* We Ctrl-C/Ctrl-Break, stop everything */
1139 goto Quit;
1140 }
1141
1142 do
1143 {
1144 bRet = FileGetString(hFile, Encoding,
1145 FileCacheBuffer, FileCacheBufferSize,
1146 &StringBuffer, &StringBufferLength,
1147 &dwReadBytes, &dwReadChars);
1148 if (!bRet || dwReadBytes == 0 || dwReadChars == 0)
1149 {
1150 /*
1151 * We failed at reading the file, bail out
1152 * and continue with the other files.
1153 */
1154 break;
1155 }
1156
1157 /* Update the statistics for PagePrompt */
1158 dwSumReadBytes += dwReadBytes;
1159 dwSumReadChars += dwReadChars;
1160
1161 if ((Encoding == ENCODING_UTF16LE) || (Encoding == ENCODING_UTF16BE))
1162 {
1163 bContinue = ConWritePaging(&Pager, PagePrompt, FALSE,
1164 FileCacheBuffer, dwReadChars);
1165 }
1166 else
1167 {
1168 bContinue = ConWritePaging(&Pager, PagePrompt, FALSE,
1169 StringBuffer, dwReadChars);
1170 }
1171 if (!bContinue)
1172 {
1173 /* We stop displaying this file */
1174 break;
1175 }
1176 }
1177 while (bRet && dwReadBytes > 0);
1178
1179 /* Flush any cached pager buffers */
1180 if (bContinue)
1181 bContinue = ConWritePaging(&Pager, PagePrompt, FALSE, NULL, 0);
1182
1184
1185 /* Check whether we should stop displaying this file */
1186 if (!bContinue)
1187 {
1188 if (s_bDoNextFile)
1189 {
1190 /* Bail out and continue with the other files */
1191 continue;
1192 }
1193
1194 /* We Ctrl-C/Ctrl-Break, stop everything */
1195 goto Quit;
1196 }
1197 }
1198
1199Quit:
1201 HeapFree(GetProcessHeap(), 0, FileCacheBuffer);
1203 return 0;
1204}
1205
1206/* EOF */
struct test_data Tests[]
static int argc
Definition: ServiceArgs.c:12
#define IDS_USAGE
Definition: resource.h:3
void ConPuts(FILE *fp, LPCWSTR psz)
Definition: fc.c:16
#define StdOut
Definition: fc.c:14
void ConResPrintf(FILE *fp, UINT nID,...)
Definition: fc.c:33
#define StdErr
Definition: fc.c:15
void ConResPuts(FILE *fp, UINT nID)
Definition: fc.c:27
#define IDS_CONTINUE_OPTIONS
Definition: resource.h:10
#define IDS_CONTINUE_LINES
Definition: resource.h:11
#define IDS_CONTINUE_LINE_AT
Definition: resource.h:9
#define IDS_FILE_ACCESS
Definition: resource.h:5
#define IDS_CONTINUE_PROMPT
Definition: resource.h:7
#define IDS_BAD_FLAG
Definition: resource.h:4
#define IDS_CONTINUE_PERCENT
Definition: resource.h:8
BOOL WINAPI FlushConsoleInputBuffer(IN HANDLE hConsoleInput)
Definition: console.c:220
BOOL WINAPI SetConsoleCursorPosition(IN HANDLE hConsoleOutput, IN COORD dwCursorPosition)
Definition: console.c:641
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:203
#define RegCloseKey(hKey)
Definition: registry.h:49
Definition: bufpool.h:45
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
@ Screen
Definition: console.h:34
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
BOOL WINAPI IsTextUnicode(IN CONST VOID *lpv, IN INT iSize, IN OUT LPINT lpiResult OPTIONAL)
Definition: unicode.c:27
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3333
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4103
#define CloseHandle
Definition: compat.h:739
#define GetProcessHeap()
Definition: compat.h:736
#define FILE_BEGIN
Definition: compat.h:761
#define GetEnvironmentVariableW(x, y, z)
Definition: compat.h:755
#define OPEN_EXISTING
Definition: compat.h:775
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742
#define SetFilePointer
Definition: compat.h:743
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define HeapAlloc
Definition: compat.h:733
#define HeapReAlloc
Definition: compat.h:734
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define CreateFileW
Definition: compat.h:741
#define MultiByteToWideChar
Definition: compat.h:110
#define FILE_SHARE_READ
Definition: compat.h:136
BOOL WINAPI GetConsoleMode(HANDLE hConsoleHandle, LPDWORD lpMode)
Definition: console.c:1569
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleMode(HANDLE hConsoleHandle, DWORD dwMode)
Definition: console.c:1606
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, BOOL Add)
Definition: console.c:2109
UINT WINAPI DECLSPEC_HOTPATCH GetConsoleCP(VOID)
Definition: console.c:2391
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:331
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1106
BOOL WINAPI GetStringTypeW(DWORD type, LPCWSTR src, INT count, LPWORD chartype)
Definition: locale.c:3095
static const WCHAR szPercent[]
Definition: varformat.c:393
@ Success
Definition: eventcreate.c:712
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
FxAutoRegKey hKey
GLfloat param
Definition: glext.h:5796
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define C1_SPACE
Definition: unicode.h:34
#define C1_BLANK
Definition: unicode.h:37
_Check_return_ long __cdecl wcstol(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
_Check_return_ _CRTIMP long __cdecl _wtol(_In_z_ const wchar_t *_Str)
#define C_ASSERT(e)
Definition: intsafe.h:73
#define LOBYTE(W)
Definition: jmemdos.c:487
#define HIBYTE(W)
Definition: jmemdos.c:486
#define TEXT(s)
Definition: k32.h:26
#define REG_SZ
Definition: layer.c:22
WCHAR StringBuffer[156]
Definition: ldrinit.c:41
#define pch(ap)
Definition: match.c:418
static DWORD DWORD void LPSTR DWORD cch
Definition: str.c:202
#define FLAG_Tn
Definition: more.c:61
static BOOL __stdcall MorePagerLine(IN OUT PCON_PAGER Pager, IN PCWCH line, IN DWORD cch)
Definition: more.c:106
#define PROMPT_PERCENT
Definition: more.c:65
static VOID LoadRegistrySettings(HKEY hKeyRoot)
Definition: more.c:768
static BOOL ParseMoreVariable(BOOL *pbHasFiles)
Definition: more.c:908
static BOOL FileGetString(IN HANDLE hFile, IN ENCODING Encoding, IN OUT PVOID pCacheBuffer, IN DWORD CacheBufferLength, IN OUT PWCHAR *pBuffer, IN OUT PDWORD pnBufferLength, OUT PDWORD pdwReadBytes OPTIONAL, OUT PDWORD pdwReadChars OPTIONAL)
Definition: more.c:653
#define IS_TEXT_UNKNOWN_FLAGS_MASK
#define FLAG_P
Definition: more.c:59
DWORD dwSumReadBytes
Definition: more.c:41
static BOOL s_bPrevLineIsBlank
Definition: more.c:73
static BOOL __stdcall PagePrompt(PCON_PAGER Pager, DWORD Done, DWORD Total)
Definition: more.c:160
#define PROMPT_LINE_AT
Definition: more.c:66
HANDLE hStdOut
Definition: more.c:49
ENCODING
Definition: more.c:493
@ ENCODING_UTF16BE
Definition: more.c:496
@ ENCODING_UTF8
Definition: more.c:497
@ ENCODING_UTF16LE
Definition: more.c:495
@ ENCODING_ANSI
Definition: more.c:494
#define FileCacheBufferSize
static BOOL IsBlankLine(IN PCWCH line, IN DWORD cch)
Definition: more.c:77
#define PROMPT_LINES
Definition: more.c:68
DWORD dwFileSize
Definition: more.c:40
#define PROMPT_OPTIONS
Definition: more.c:67
BOOL bEnableExtensions
Definition: more.c:53
HANDLE hStdIn
Definition: more.c:49
#define FLAG_S
Definition: more.c:60
#define FLAG_PLUSn
Definition: more.c:62
static LONG s_nTabWidth
Definition: more.c:71
static DWORD s_nNextLineNo
Definition: more.c:72
static BOOL IsFlag(PCWSTR param)
Definition: more.c:808
HANDLE hKeyboard
Definition: more.c:50
static BOOL IsDataUnicode(IN PVOID Buffer, IN DWORD BufferSize, OUT ENCODING *Encoding OPTIONAL, OUT PDWORD SkipBytes OPTIONAL)
Definition: more.c:501
static DWORD s_dwFlags
Definition: more.c:70
#define FLAG_C
Definition: more.c:58
#define FLAG_HELP
Definition: more.c:56
static BOOL ParseArgument(PCWSTR arg, BOOL *pbHasFiles)
Definition: more.c:828
DWORD dwSumReadChars
Definition: more.c:41
#define FLAG_E
Definition: more.c:57
static BOOL s_bDoNextFile
Definition: more.c:75
static WORD s_fPrompt
Definition: more.c:74
#define argv
Definition: mplay32.c:18
_In_ HANDLE hFile
Definition: mswsock.h:90
unsigned int UINT
Definition: ndis.h:50
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
#define GENERIC_WRITE
Definition: nt_native.h:90
CONST WCHAR * PCWCH
Definition: ntbasedef.h:419
#define L(x)
Definition: ntvdm.h:50
INT __cdecl ConResMsgPrintf(IN PCON_STREAM Stream, IN DWORD dwFlags, IN UINT uID,...)
Definition: outstream.c:1461
VOID ConClearLine(IN PCON_STREAM Stream)
Definition: outstream.c:1483
INT ConStreamWrite(IN PCON_STREAM Stream, IN PCTCH szStr, IN DWORD len)
Definition: outstream.c:398
#define CON_PAGER_EXPAND_TABS
Definition: pager.h:40
#define CON_PAGER_CACHE_INCOMPLETE_LINE
Definition: pager.h:43
#define CON_PAGER_EXPAND_FF
Definition: pager.h:41
BYTE * PBYTE
Definition: pedump.c:66
DWORD * PDWORD
Definition: pedump.c:68
long LONG
Definition: pedump.c:60
PVOID pBuffer
int wmain()
@ Restart
Definition: sacdrv.h:269
#define REG_DWORD
Definition: sdbapi.c:596
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
_CRT_RESTORE_GCC_WARNINGS _Check_return_ _CRTIMP wchar_t *__cdecl wcstok(_Inout_opt_z_ wchar_t *_Str, _In_z_ const wchar_t *_Delim)
#define CP_UTF8
Definition: nls.h:20
BOOL ConWritePaging(IN PCON_PAGER Pager, IN PAGE_PROMPT PagePrompt, IN BOOL StartPaging, IN PCTCH szStr, IN DWORD len)
Definition: pager.c:549
BOOL ConGetScreenInfo(IN PCON_SCREEN Screen, OUT PCONSOLE_SCREEN_BUFFER_INFO pcsbi)
Definition: screen.c:73
VOID ConClearScreen(IN PCON_SCREEN Screen)
Definition: screen.c:131
BOOL ConStreamSetOSHandle(IN PCON_STREAM Stream, IN HANDLE Handle)
Definition: stream.c:263
BOOL ConStreamInit(OUT PCON_STREAM Stream, IN PVOID Handle, IN CON_STREAM_MODE Mode, IN UINT CacheCodePage OPTIONAL)
Definition: stream.c:185
HANDLE ConStreamGetOSHandle(IN PCON_STREAM Stream)
Definition: stream.c:240
#define StdIn
Definition: stream.h:81
@ UTF8Text
Definition: stream.h:50
#define INVALID_CP
Definition: stream.h:53
INT WINAPI K32LoadStringW(IN HINSTANCE hInstance OPTIONAL, IN UINT uID, OUT LPWSTR lpBuffer, IN INT nBufferMax)
Definition: utils.c:173
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
STRSAFEAPI StringCchPrintfW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:530
DWORD dwFlags
Definition: pager.h:54
DWORD lineno
Definition: pager.h:70
LONG nTabWidth
Definition: pager.h:55
DWORD ScrollRows
Definition: pager.h:56
CON_PAGER_LINE_FN PagerLine
Definition: pager.h:53
PCON_SCREEN Screen
Definition: pager.h:48
PCON_STREAM Stream
Definition: screen.h:43
Definition: bl.h:1338
ULONG Y
Definition: bl.h:1340
ULONG X
Definition: bl.h:1339
WORD EventType
Definition: wincon.h:273
union _INPUT_RECORD::@3298 Event
KEY_EVENT_RECORD KeyEvent
Definition: wincon.h:275
union _KEY_EVENT_RECORD::@3297 uChar
DWORD dwControlKeyState
Definition: wincon.h:248
WORD wVirtualKeyCode
Definition: wincon.h:242
WCHAR UnicodeChar
Definition: wincon.h:245
Definition: parser.c:49
SHORT Y
Definition: blue.h:27
SHORT X
Definition: blue.h:26
SHORT Top
Definition: blue.h:33
SHORT Bottom
Definition: blue.h:35
#define towupper(c)
Definition: wctype.h:99
uint16_t * PWSTR
Definition: typedefs.h:56
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define MAKEWORD(a, b)
Definition: typedefs.h:248
int32_t INT
Definition: typedefs.h:58
#define __stdcall
Definition: typedefs.h:25
#define IN
Definition: typedefs.h:39
uint16_t * PWCHAR
Definition: typedefs.h:56
#define OUT
Definition: typedefs.h:40
int ret
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
#define STD_OUTPUT_HANDLE
Definition: winbase.h:294
#define STD_INPUT_HANDLE
Definition: winbase.h:293
#define STD_ERROR_HANDLE
Definition: winbase.h:295
#define INVALID_FILE_SIZE
Definition: winbase.h:574
#define LEFT_CTRL_PRESSED
Definition: wincon.h:140
#define ReadConsoleInput
Definition: wincon.h:778
#define KEY_EVENT
Definition: wincon.h:128
#define RIGHT_CTRL_PRESSED
Definition: wincon.h:139
#define ENABLE_PROCESSED_INPUT
Definition: wincon.h:78
#define CT_CTYPE1
Definition: winnls.h:239
#define IS_TEXT_UNICODE_ILLEGAL_CHARS
Definition: winnt_old.h:923
#define IS_TEXT_UNICODE_UNICODE_MASK
Definition: winnt_old.h:927
#define IS_TEXT_UNICODE_NOT_ASCII_MASK
Definition: winnt_old.h:930
#define IS_TEXT_UNICODE_NULL_BYTES
Definition: winnt_old.h:926
#define IS_TEXT_UNICODE_REVERSE_MASK
Definition: winnt_old.h:928
#define IS_TEXT_UNICODE_REVERSE_SIGNATURE
Definition: winnt_old.h:922
#define IS_TEXT_UNICODE_NOT_UNICODE_MASK
Definition: winnt_old.h:929
#define IS_TEXT_UNICODE_SIGNATURE
Definition: winnt_old.h:921
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define HKEY_CURRENT_USER
Definition: winreg.h:11
#define VK_SPACE
Definition: winuser.h:2222
#define VK_CONTROL
Definition: winuser.h:2206
#define VK_RETURN
Definition: winuser.h:2204
#define VK_BACK
Definition: winuser.h:2201
#define VK_SHIFT
Definition: winuser.h:2205
#define VK_ESCAPE
Definition: winuser.h:2217
#define VK_MENU
Definition: winuser.h:2207
_Must_inspect_result_ _In_ PHYSICAL_ADDRESS _In_ PHYSICAL_ADDRESS SkipBytes
Definition: mmfuncs.h:227
char TCHAR
Definition: xmlstorage.h:189
__wchar_t WCHAR
Definition: xmlstorage.h:180