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