ReactOS  0.4.15-dev-1177-g6cb3b62
more.c File Reference
#include <stdio.h>
#include <windef.h>
#include <winbase.h>
#include <winnls.h>
#include <winuser.h>
#include <conutils.h>
#include "resource.h"
Include dependency graph for more.c:

Go to the source code of this file.

Macros

#define IS_TEXT_UNKNOWN_FLAGS_MASK   ((7 << 13) | (1 << 11))
 
#define FileCacheBufferSize   4096
 

Enumerations

enum  ENCODING {
  ENCODING_ANSI = 0, ENCODING_UTF16LE = 1, ENCODING_UTF16BE = 2, ENCODING_UTF8 = 3,
  ENCODING_AUTO = -1, ENCODING_ANSI = 0, ENCODING_UTF16LE = 1, ENCODING_UTF16BE = 2,
  ENCODING_UTF8 = 3, ENCODING_ANSI = 0, ENCODING_UTF16LE = 1, ENCODING_UTF16BE = 2,
  ENCODING_UTF8 = 3, ENCODING_ANSI = 1, ENCODING_UTF8, ENCODING_UTF16LE,
  ENCODING_UTF16BE
}
 

Functions

static BOOL __stdcall PagePrompt (PCON_PAGER Pager, DWORD Done, DWORD Total)
 
static BOOL IsDataUnicode (IN PVOID Buffer, IN DWORD BufferSize, OUT ENCODING *Encoding OPTIONAL, OUT PDWORD SkipBytes OPTIONAL)
 
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)
 
int wmain (int argc, WCHAR *argv[])
 

Variables

DWORD dwFileSize
 
DWORD dwSumReadBytes
 
DWORD dwSumReadChars
 
HANDLE hFile = INVALID_HANDLE_VALUE
 
HANDLE hStdIn
 
HANDLE hStdOut
 
HANDLE hKeyboard
 

Macro Definition Documentation

◆ FileCacheBufferSize

#define FileCacheBufferSize   4096

◆ IS_TEXT_UNKNOWN_FLAGS_MASK

#define IS_TEXT_UNKNOWN_FLAGS_MASK   ((7 << 13) | (1 << 11))

Enumeration Type Documentation

◆ ENCODING

Enumerator
ENCODING_ANSI 
ENCODING_UTF16LE 
ENCODING_UTF16BE 
ENCODING_UTF8 
ENCODING_AUTO 
ENCODING_ANSI 
ENCODING_UTF16LE 
ENCODING_UTF16BE 
ENCODING_UTF8 
ENCODING_ANSI 
ENCODING_UTF16LE 
ENCODING_UTF16BE 
ENCODING_UTF8 
ENCODING_ANSI 
ENCODING_UTF8 
ENCODING_UTF16LE 
ENCODING_UTF16BE 

Definition at line 168 of file more.c.

169 {
170  ENCODING_ANSI = 0,
171  ENCODING_UTF16LE = 1,
172  ENCODING_UTF16BE = 2,
173  ENCODING_UTF8 = 3
174 } ENCODING;
ENCODING
Definition: more.c:168

Function Documentation

◆ FileGetString()

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 
)
static

Definition at line 329 of file more.c.

338 {
339  BOOL Success;
340  UINT CodePage = (UINT)-1;
341  DWORD dwReadBytes;
342  INT len;
343 
344  // ASSERT(pCacheBuffer && (CacheBufferLength > 0));
345  // ASSERT(CacheBufferLength % 2 == 0); // Cache buffer length MUST BE even!
346  // ASSERT(pBuffer && pnBufferLength);
347 
348  /* Always reset the retrieved number of bytes/characters */
349  if (pdwReadBytes) *pdwReadBytes = 0;
350  if (pdwReadChars) *pdwReadChars = 0;
351 
352  Success = ReadFile(hFile, pCacheBuffer, CacheBufferLength, &dwReadBytes, NULL);
353  if (!Success || dwReadBytes == 0)
354  return FALSE;
355 
356  if (pdwReadBytes) *pdwReadBytes = dwReadBytes;
357 
358  if ((Encoding == ENCODING_ANSI) || (Encoding == ENCODING_UTF8))
359  {
360  /* Conversion is needed */
361 
362  if (Encoding == ENCODING_ANSI)
363  CodePage = GetConsoleCP(); // CP_ACP; // FIXME: Cache GetConsoleCP() value.
364  else // if (Encoding == ENCODING_UTF8)
365  CodePage = CP_UTF8;
366 
367  /* Retrieve the needed buffer size */
368  len = MultiByteToWideChar(CodePage, 0, pCacheBuffer, dwReadBytes,
369  NULL, 0);
370  if (len == 0)
371  {
372  /* Failure, bail out */
373  return FALSE;
374  }
375 
376  /* Initialize the conversion buffer if needed... */
377  if (*pBuffer == NULL)
378  {
379  *pnBufferLength = len;
380  *pBuffer = HeapAlloc(GetProcessHeap(), 0, *pnBufferLength * sizeof(WCHAR));
381  if (*pBuffer == NULL)
382  {
383  // *pBuffer = NULL;
384  *pnBufferLength = 0;
385  // WARN("DEBUG: Cannot allocate memory for *pBuffer!\n");
386  // ConErrFormatMessage(GetLastError());
387  return FALSE;
388  }
389  }
390  /* ... or reallocate only if the new length is greater than the old one */
391  else if (len > *pnBufferLength)
392  {
393  PWSTR OldBuffer = *pBuffer;
394 
395  *pnBufferLength = len;
396  *pBuffer = HeapReAlloc(GetProcessHeap(), 0, *pBuffer, *pnBufferLength * sizeof(WCHAR));
397  if (*pBuffer == NULL)
398  {
399  /* Do not leak old buffer */
400  HeapFree(GetProcessHeap(), 0, OldBuffer);
401  // *pBuffer = NULL;
402  *pnBufferLength = 0;
403  // WARN("DEBUG: Cannot reallocate memory for *pBuffer!\n");
404  // ConErrFormatMessage(GetLastError());
405  return FALSE;
406  }
407  }
408 
409  /* Now perform the conversion proper */
410  len = MultiByteToWideChar(CodePage, 0, pCacheBuffer, dwReadBytes,
411  *pBuffer, len);
412  dwReadBytes = len;
413  }
414  else
415  {
416  /*
417  * No conversion needed, just convert from big to little endian if needed.
418  * pBuffer and pnBufferLength are left untouched and pCacheBuffer can be
419  * directly used.
420  */
421  PWCHAR pWChars = pCacheBuffer;
422  DWORD i;
423 
424  dwReadBytes /= sizeof(WCHAR);
425 
426  if (Encoding == ENCODING_UTF16BE)
427  {
428  for (i = 0; i < dwReadBytes; i++)
429  {
430  /* Equivalent to RtlUshortByteSwap: reverse high/low bytes */
431  pWChars[i] = MAKEWORD(HIBYTE(pWChars[i]), LOBYTE(pWChars[i]));
432  }
433  }
434  // else if (Encoding == ENCODING_UTF16LE), we are good, nothing to do.
435  }
436 
437  /* Return the number of characters (dwReadBytes is converted) */
438  if (pdwReadChars) *pdwReadChars = dwReadBytes;
439 
440  return TRUE;
441 }
#define LOBYTE(W)
Definition: jmemdos.c:487
#define MAKEWORD(a, b)
Definition: typedefs.h:248
#define TRUE
Definition: types.h:120
uint16_t * PWSTR
Definition: typedefs.h:56
#define HIBYTE(W)
Definition: jmemdos.c:486
uint16_t * PWCHAR
Definition: typedefs.h:56
int32_t INT
Definition: typedefs.h:58
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 CP_UTF8
Definition: nls.h:20
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
smooth NULL
Definition: ftsmooth.c:416
PVOID pBuffer
UINT WINAPI DECLSPEC_HOTPATCH GetConsoleCP(VOID)
Definition: console.c:2393
#define GetProcessHeap()
Definition: compat.h:484
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
__wchar_t WCHAR
Definition: xmlstorage.h:180
unsigned long DWORD
Definition: ntddk_ex.h:95
GLenum GLsizei len
Definition: glext.h:6722
_In_ HANDLE hFile
Definition: mswsock.h:90
#define HeapReAlloc
Definition: compat.h:482
#define ReadFile(a, b, c, d, e)
Definition: compat.h:490
unsigned int UINT
Definition: ndis.h:50
#define MultiByteToWideChar
Definition: compat.h:110
#define HeapFree(x, y, z)
Definition: compat.h:483

Referenced by wmain().

◆ IsDataUnicode()

static BOOL IsDataUnicode ( IN PVOID  Buffer,
IN DWORD  BufferSize,
OUT ENCODING *Encoding  OPTIONAL,
OUT PDWORD SkipBytes  OPTIONAL 
)
static

Definition at line 177 of file more.c.

182 {
183  PBYTE pBytes = Buffer;
184  ENCODING encFile = ENCODING_ANSI;
185  DWORD dwPos = 0;
186 
187  /*
188  * See http://archives.miloush.net/michkap/archive/2007/04/22/2239345.html
189  * for more details about the algorithm and the pitfalls behind it.
190  * Of course it would be actually great to make a nice function that
191  * would work, once and for all, and put it into a library.
192  */
193 
194  /* Look for Byte Order Marks */
195  if ((BufferSize >= 2) && (pBytes[0] == 0xFF) && (pBytes[1] == 0xFE))
196  {
197  encFile = ENCODING_UTF16LE;
198  dwPos = 2;
199  }
200  else if ((BufferSize >= 2) && (pBytes[0] == 0xFE) && (pBytes[1] == 0xFF))
201  {
202  encFile = ENCODING_UTF16BE;
203  dwPos = 2;
204  }
205  else if ((BufferSize >= 3) && (pBytes[0] == 0xEF) && (pBytes[1] == 0xBB) && (pBytes[2] == 0xBF))
206  {
207  encFile = ENCODING_UTF8;
208  dwPos = 3;
209  }
210  else
211  {
212  /*
213  * Try using statistical analysis. Do not rely on the return value of
214  * IsTextUnicode as we can get FALSE even if the text is in UTF-16 BE
215  * (i.e. we have some of the IS_TEXT_UNICODE_REVERSE_MASK bits set).
216  * Instead, set all the tests we want to perform, then just check
217  * the passed tests and try to deduce the string properties.
218  */
219 
220 /*
221  * This mask contains the 3 highest bits from IS_TEXT_UNICODE_NOT_ASCII_MASK
222  * and the 1st highest bit from IS_TEXT_UNICODE_NOT_UNICODE_MASK.
223  */
224 #define IS_TEXT_UNKNOWN_FLAGS_MASK ((7 << 13) | (1 << 11))
225 
226  /* Flag out the unknown flags here, the passed tests will not have them either */
231  INT Results;
232 
234  Results = Tests;
235 
236  /*
237  * As the IS_TEXT_UNICODE_NULL_BYTES or IS_TEXT_UNICODE_ILLEGAL_CHARS
238  * flags are expected to be potentially present in the result without
239  * modifying our expectations, filter them out now.
240  */
242 
243  /*
244  * NOTE: The flags IS_TEXT_UNICODE_ASCII16 and
245  * IS_TEXT_UNICODE_REVERSE_ASCII16 are not reliable.
246  *
247  * NOTE2: Check for potential "bush hid the facts" effect by also
248  * checking the original results (in 'Tests') for the absence of
249  * the IS_TEXT_UNICODE_NULL_BYTES flag, as we may presumably expect
250  * that in UTF-16 text there will be at some point some NULL bytes.
251  * If not, fall back to ANSI. This shows the limitations of using the
252  * IsTextUnicode API to perform such tests, and the usage of a more
253  * improved encoding detection algorithm would be really welcome.
254  */
255  if (!(Results & IS_TEXT_UNICODE_NOT_UNICODE_MASK) &&
256  !(Results & IS_TEXT_UNICODE_REVERSE_MASK) &&
257  (Results & IS_TEXT_UNICODE_UNICODE_MASK) &&
259  {
260  encFile = ENCODING_UTF16LE;
261  dwPos = (Results & IS_TEXT_UNICODE_SIGNATURE) ? 2 : 0;
262  }
263  else
264  if (!(Results & IS_TEXT_UNICODE_NOT_UNICODE_MASK) &&
265  !(Results & IS_TEXT_UNICODE_UNICODE_MASK) &&
266  (Results & IS_TEXT_UNICODE_REVERSE_MASK) &&
268  {
269  encFile = ENCODING_UTF16BE;
270  dwPos = (Results & IS_TEXT_UNICODE_REVERSE_SIGNATURE) ? 2 : 0;
271  }
272  else
273  {
274  /*
275  * Either 'Results' has neither of those masks set, as it can be
276  * the case for UTF-8 text (or ANSI), or it has both as can be the
277  * case when analysing pure binary data chunk. This is therefore
278  * invalid and we fall back to ANSI encoding.
279  * FIXME: In case of failure, assume ANSI (as long as we do not have
280  * correct tests for UTF8, otherwise we should do them, and at the
281  * very end, assume ANSI).
282  */
283  encFile = ENCODING_ANSI; // ENCODING_UTF8;
284  dwPos = 0;
285  }
286  }
287 
288  if (Encoding)
289  *Encoding = encFile;
290  if (SkipBytes)
291  *SkipBytes = dwPos;
292 
293  return (encFile != ENCODING_ANSI);
294 }
#define IS_TEXT_UNICODE_NOT_ASCII_MASK
Definition: winnt_old.h:934
#define IS_TEXT_UNKNOWN_FLAGS_MASK
int32_t INT
Definition: typedefs.h:58
#define IS_TEXT_UNICODE_SIGNATURE
Definition: winnt_old.h:925
Definition: bufpool.h:45
_Must_inspect_result_ _In_ PHYSICAL_ADDRESS _In_ PHYSICAL_ADDRESS SkipBytes
Definition: mmfuncs.h:226
#define IS_TEXT_UNICODE_REVERSE_SIGNATURE
Definition: winnt_old.h:926
BOOL WINAPI IsTextUnicode(IN CONST VOID *lpv, IN INT iSize, IN OUT LPINT lpiResult OPTIONAL)
Definition: unicode.c:27
#define BufferSize
Definition: mmc.h:75
unsigned long DWORD
Definition: ntddk_ex.h:95
#define IS_TEXT_UNICODE_ILLEGAL_CHARS
Definition: winnt_old.h:927
ENCODING
Definition: more.c:168
#define IS_TEXT_UNICODE_REVERSE_MASK
Definition: winnt_old.h:932
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
#define IS_TEXT_UNICODE_NULL_BYTES
Definition: winnt_old.h:930
BYTE * PBYTE
Definition: pedump.c:66
#define IS_TEXT_UNICODE_UNICODE_MASK
Definition: winnt_old.h:931
struct test_data Tests[]
#define IS_TEXT_UNICODE_NOT_UNICODE_MASK
Definition: winnt_old.h:933

Referenced by wmain().

◆ PagePrompt()

static BOOL __stdcall PagePrompt ( PCON_PAGER  Pager,
DWORD  Done,
DWORD  Total 
)
static

Definition at line 52 of file more.c.

53 {
55  DWORD dwMode;
56  KEY_EVENT_RECORD KeyEvent;
57 
58  /*
59  * Just use the simple prompt if the file being displayed is the STDIN,
60  * otherwise use the prompt with progress percentage.
61  *
62  * The progress percentage is evaluated as follows.
63  * So far we have read a total of 'dwSumReadBytes' bytes from the file.
64  * Amongst those is the latest read chunk of 'dwReadBytes' bytes, to which
65  * correspond a number of 'dwReadChars' characters with which we have called
66  * ConWritePaging who called PagePrompt. We then have: Total == dwReadChars.
67  * During this ConWritePaging call the PagePrompt was called after 'Done'
68  * number of characters over 'Total'.
69  * It should be noted that for 'dwSumReadBytes' number of bytes read it
70  * *roughly* corresponds 'dwSumReadChars' number of characters. This is
71  * because there may be some failures happening during the conversion of
72  * the bytes read to the character string for a given encoding.
73  * Therefore the number of characters displayed on screen is equal to:
74  * dwSumReadChars - Total + Done ,
75  * but the best corresponding approximed number of bytes would be:
76  * dwSumReadBytes - (Total - Done) * (dwSumReadBytes / dwSumReadChars) ,
77  * where the ratio is the average number of bytes per character.
78  * The percentage is then computed relative to the total file size.
79  */
80  if (hFile == hStdIn)
81  {
83  }
84  else
85  {
87  // (dwSumReadChars - Total + Done) * 100 / dwFileSize
88  (dwSumReadBytes - (Total - Done) *
90  );
91  }
92 
93  // TODO: Implement prompt read line!
94 
95  // FIXME: Does not support TTY yet!
96 
97  /* RemoveBreakHandler */
99  /* ConInDisable */
100  GetConsoleMode(hInput, &dwMode);
101  dwMode &= ~ENABLE_PROCESSED_INPUT;
102  SetConsoleMode(hInput, dwMode);
103 
104  do
105  {
106  // FIXME: Does not support TTY yet!
107 
108  // ConInKey(&KeyEvent);
109  INPUT_RECORD ir;
110  DWORD dwRead;
111  do
112  {
113  ReadConsoleInput(hInput, &ir, 1, &dwRead);
114  }
115  while ((ir.EventType != KEY_EVENT) || (!ir.Event.KeyEvent.bKeyDown));
116 
117  /* Got our key, return to caller */
118  KeyEvent = ir.Event.KeyEvent;
119  }
120  while ((KeyEvent.wVirtualKeyCode == VK_SHIFT) ||
121  (KeyEvent.wVirtualKeyCode == VK_MENU) ||
122  (KeyEvent.wVirtualKeyCode == VK_CONTROL));
123 
124  /* AddBreakHandler */
126  /* ConInEnable */
127  GetConsoleMode(hInput, &dwMode);
128  dwMode |= ENABLE_PROCESSED_INPUT;
129  SetConsoleMode(hInput, dwMode);
130 
131  /*
132  * Erase the full line where the cursor is, and move
133  * the cursor back to the beginning of the line.
134  */
135  ConClearLine(Pager->Screen->Stream);
136 
137  /* Ctrl+C or Ctrl+Esc: Control Break */
138  if ((KeyEvent.wVirtualKeyCode == VK_ESCAPE) ||
139  ((KeyEvent.wVirtualKeyCode == L'C') &&
141  {
142  /* We break, output a newline */
143  WCHAR ch = L'\n';
144  ConStreamWrite(Pager->Screen->Stream, &ch, 1);
145  return FALSE;
146  }
147 
148  /* 'Q': Quit */
149  // FIXME: Available only when command extensions are enabled.
150  if ((KeyEvent.wVirtualKeyCode == L'Q') &&
152  {
153  /* We break, output a newline */
154  WCHAR ch = L'\n';
155  ConStreamWrite(Pager->Screen->Stream, &ch, 1);
156  return FALSE;
157  }
158 
159  return TRUE;
160 }
PCON_STREAM Stream
Definition: screen.h:43
#define IDS_CONTINUE
Definition: resource.h:4
#define TRUE
Definition: types.h:120
DWORD dwSumReadBytes
Definition: more.c:38
BOOL WINAPI GetConsoleMode(HANDLE hConsoleHandle, LPDWORD lpMode)
Definition: console.c:1571
DWORD dwFileSize
Definition: more.c:37
DWORD dwControlKeyState
Definition: wincon.h:248
VOID ConClearLine(IN PCON_STREAM Stream)
Definition: outstream.c:1483
#define VK_MENU
Definition: winuser.h:2179
#define VK_ESCAPE
Definition: winuser.h:2189
WORD wVirtualKeyCode
Definition: wincon.h:242
PCON_SCREEN Screen
Definition: pager.h:35
#define FALSE
Definition: types.h:117
#define ReadConsoleInput
Definition: wincon.h:781
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 KEY_EVENT
Definition: wincon.h:128
#define VK_SHIFT
Definition: winuser.h:2177
smooth NULL
Definition: ftsmooth.c:416
INT ConStreamWrite(IN PCON_STREAM Stream, IN PCTCH szStr, IN DWORD len)
Definition: outstream.c:398
INT __cdecl ConResPrintf(IN PCON_STREAM Stream, IN UINT uID,...)
Definition: outstream.c:781
HANDLE ConStreamGetOSHandle(IN PCON_STREAM Stream)
Definition: stream.c:240
__wchar_t WCHAR
Definition: xmlstorage.h:180
KEY_EVENT_RECORD KeyEvent
Definition: wincon.h:278
unsigned long DWORD
Definition: ntddk_ex.h:95
INT ConResPuts(IN PCON_STREAM Stream, IN UINT uID)
Definition: outstream.c:610
#define LEFT_CTRL_PRESSED
Definition: wincon.h:140
static const WCHAR L[]
Definition: oid.c:1250
_In_ HANDLE hFile
Definition: mswsock.h:90
DWORD dwSumReadChars
Definition: more.c:38
#define ENABLE_PROCESSED_INPUT
Definition: wincon.h:78
HANDLE hStdIn
Definition: more.c:46
#define VK_CONTROL
Definition: winuser.h:2178
WORD EventType
Definition: wincon.h:276
union _INPUT_RECORD::@3242 Event
#define RIGHT_CTRL_PRESSED
Definition: wincon.h:139
#define IDS_CONTINUE_PROGRESS
Definition: resource.h:5
#define StdIn
Definition: stream.h:81

Referenced by ConOutResPaging(), ConPrintfVPaging(), ConPutsPaging(), ConResPaging(), ConResPagingEx(), ConWritePaging(), and wmain().

◆ wmain()

int wmain ( int  argc,
WCHAR argv[] 
)

Definition at line 444 of file more.c.

445 {
446  // FIXME this stuff!
448  CON_PAGER Pager = {&Screen, 0};
449 
450  int i;
451 
452  BOOL bRet, bContinue;
453 
454  ENCODING Encoding;
455  DWORD SkipBytes = 0;
456 
457 #define FileCacheBufferSize 4096
458  PVOID FileCacheBuffer = NULL;
460  DWORD StringBufferLength = 0;
461  DWORD dwReadBytes, dwReadChars;
462 
463  TCHAR szFullPath[MAX_PATH];
464 
467 
468  /* Initialize the Console Standard Streams */
472 
473  /*
474  * Bad usage (too much options) or we use the /? switch.
475  * Display help for the MORE command.
476  */
477  if (argc > 1 && wcscmp(argv[1], L"/?") == 0)
478  {
480  return 0;
481  }
482 
483  // FIXME: Parse all the remaining parameters.
484  // Then the file list can be found at the very end.
485  // FIXME2: Use the PARSER api that can be found in EVENTCREATE.
486 
487  // NOTE: We might try to duplicate the ConOut for read access... ?
490  OPEN_EXISTING, 0, NULL);
493 
494 
495  FileCacheBuffer = HeapAlloc(GetProcessHeap(), 0, FileCacheBufferSize);
496  if (!FileCacheBuffer)
497  {
498  ConPuts(StdErr, L"Error: no memory\n");
500  return 1;
501  }
502 
503  /* Special case where we run 'MORE' without any argument: we use STDIN */
504  if (argc <= 1)
505  {
506  /*
507  * Assign STDIN handle to hFile so that the page prompt function will
508  * know the data comes from STDIN, and will take different actions.
509  */
510  hFile = hStdIn;
511 
512  /* Update the statistics for PagePrompt */
513  dwFileSize = 0;
515 
516  /* We suppose we read text from the file */
517 
518  /* For STDIN we always suppose we are in ANSI mode */
519  // SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
520  Encoding = ENCODING_ANSI; // ENCODING_UTF8;
521 
522  bContinue = ConPutsPaging(&Pager, PagePrompt, TRUE, L"");
523  if (!bContinue)
524  goto Quit;
525 
526  do
527  {
528  bRet = FileGetString(hFile, Encoding,
529  FileCacheBuffer, FileCacheBufferSize,
530  &StringBuffer, &StringBufferLength,
531  &dwReadBytes, &dwReadChars);
532  if (!bRet || dwReadBytes == 0 || dwReadChars == 0)
533  {
534  /* We failed at reading the file, bail out */
535  break;
536  }
537 
538  /* Update the statistics for PagePrompt */
539  dwSumReadBytes += dwReadBytes;
540  dwSumReadChars += dwReadChars;
541 
542  bContinue = ConWritePaging(&Pager, PagePrompt, FALSE,
543  StringBuffer, dwReadChars);
544  /* If we Ctrl-C/Ctrl-Break, stop everything */
545  if (!bContinue)
546  goto Quit;
547  }
548  while (bRet && dwReadBytes > 0);
549  goto Quit;
550  }
551 
552  /* We have files: read them and output them to STDOUT */
553  for (i = 1; i < argc; i++)
554  {
555  GetFullPathNameW(argv[i], ARRAYSIZE(szFullPath), szFullPath, NULL);
556  hFile = CreateFileW(szFullPath,
557  GENERIC_READ,
559  NULL,
561  0, // FILE_ATTRIBUTE_NORMAL,
562  NULL);
564  {
565  ConResPrintf(StdErr, IDS_FILE_ACCESS, szFullPath);
566  continue;
567  }
568 
569  /* We currently do not support files too big */
572  {
573  ConPuts(StdErr, L"ERROR: Invalid file size!\n");
575  continue;
576  }
577 
578  /* We suppose we read text from the file */
579 
580  /* Check whether the file is UNICODE and retrieve its encoding */
582  bRet = ReadFile(hFile, FileCacheBuffer, FileCacheBufferSize, &dwReadBytes, NULL);
583  IsDataUnicode(FileCacheBuffer, dwReadBytes, &Encoding, &SkipBytes);
585 
586  /* Update the statistics for PagePrompt */
588 
589  bContinue = ConPutsPaging(&Pager, PagePrompt, TRUE, L"");
590  if (!bContinue)
591  {
593  goto Quit;
594  }
595 
596  do
597  {
598  bRet = FileGetString(hFile, Encoding,
599  FileCacheBuffer, FileCacheBufferSize,
600  &StringBuffer, &StringBufferLength,
601  &dwReadBytes, &dwReadChars);
602  if (!bRet || dwReadBytes == 0 || dwReadChars == 0)
603  {
604  /*
605  * We failed at reading the file, bail out and
606  * continue with the other files.
607  */
608  break;
609  }
610 
611  /* Update the statistics for PagePrompt */
612  dwSumReadBytes += dwReadBytes;
613  dwSumReadChars += dwReadChars;
614 
615  if ((Encoding == ENCODING_UTF16LE) || (Encoding == ENCODING_UTF16BE))
616  {
617  bContinue = ConWritePaging(&Pager, PagePrompt, FALSE,
618  FileCacheBuffer, dwReadChars);
619  }
620  else
621  {
622  bContinue = ConWritePaging(&Pager, PagePrompt, FALSE,
623  StringBuffer, dwReadChars);
624  }
625  /* If we Ctrl-C/Ctrl-Break, stop everything */
626  if (!bContinue)
627  {
629  goto Quit;
630  }
631  }
632  while (bRet && dwReadBytes > 0);
633 
635  }
636 
637 Quit:
639  HeapFree(GetProcessHeap(), 0, FileCacheBuffer);
641  return 0;
642 }
static int argc
Definition: ServiceArgs.c:12
static BOOL __stdcall PagePrompt(PCON_PAGER Pager, DWORD Done, DWORD Total)
Definition: more.c:52
#define CloseHandle
Definition: compat.h:487
BOOL ConWritePaging(IN PCON_PAGER Pager, IN PAGE_PROMPT PagePrompt, IN BOOL StartPaging, IN PCTCH szStr, IN DWORD len)
Definition: pager.c:38
#define TRUE
Definition: types.h:120
DWORD dwSumReadBytes
Definition: more.c:38
DWORD dwFileSize
Definition: more.c:37
INT ConPuts(IN PCON_STREAM Stream, IN PCWSTR szStr)
Definition: outstream.c:427
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define INVALID_HANDLE_VALUE
Definition: compat.h:479
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 IDS_USAGE
Definition: resource.h:3
#define INVALID_FILE_SIZE
Definition: winbase.h:529
#define FILE_BEGIN
Definition: compat.h:509
uint16_t * PWCHAR
Definition: typedefs.h:56
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define argv
Definition: mplay32.c:18
#define FILE_SHARE_READ
Definition: compat.h:136
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 FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
#define GENERIC_WRITE
Definition: nt_native.h:90
HANDLE hStdOut
Definition: more.c:46
smooth NULL
Definition: ftsmooth.c:416
#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:523
INT __cdecl ConResPrintf(IN PCON_STREAM Stream, IN UINT uID,...)
Definition: outstream.c:781
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:177
#define GetProcessHeap()
Definition: compat.h:484
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
#define STD_ERROR_HANDLE
Definition: winbase.h:266
#define MAX_PATH
Definition: compat.h:34
unsigned long DWORD
Definition: ntddk_ex.h:95
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:331
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:329
#define StdErr
Definition: stream.h:83
#define INVALID_CP
Definition: stream.h:53
INT ConResPuts(IN PCON_STREAM Stream, IN UINT uID)
Definition: outstream.c:610
static const WCHAR L[]
Definition: oid.c:1250
BOOL ConStreamSetOSHandle(IN PCON_STREAM Stream, IN HANDLE Handle)
Definition: stream.c:263
#define GENERIC_READ
Definition: compat.h:135
#define STD_OUTPUT_HANDLE
Definition: winbase.h:265
_In_ HANDLE hFile
Definition: mswsock.h:90
BOOL ConPutsPaging(IN PCON_PAGER Pager, IN PAGE_PROMPT PagePrompt, IN BOOL StartPaging, IN PCTSTR szStr)
Definition: pager.c:120
DWORD dwSumReadChars
Definition: more.c:38
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
ENCODING
Definition: more.c:168
HANDLE hStdIn
Definition: more.c:46
#define ReadFile(a, b, c, d, e)
Definition: compat.h:490
#define CreateFileW
Definition: compat.h:489
#define StdOut
Definition: stream.h:82
#define IDS_FILE_ACCESS
Definition: resource.h:6
Definition: console.h:34
HANDLE hKeyboard
Definition: more.c:47
WCHAR StringBuffer[156]
Definition: ldrinit.c:41
#define HeapFree(x, y, z)
Definition: compat.h:483
#define SetFilePointer
Definition: compat.h:491
#define StdIn
Definition: stream.h:81

Variable Documentation

◆ dwFileSize

◆ dwSumReadBytes

DWORD dwSumReadBytes

Definition at line 38 of file more.c.

Referenced by PagePrompt(), and wmain().

◆ dwSumReadChars

DWORD dwSumReadChars

Definition at line 38 of file more.c.

Referenced by PagePrompt(), and wmain().

◆ hFile

Definition at line 45 of file more.c.

◆ hKeyboard

HANDLE hKeyboard

Definition at line 47 of file more.c.

Referenced by wmain().

◆ hStdIn

HANDLE hStdIn

Definition at line 46 of file more.c.

Referenced by ConsolePager(), doChild(), InputChar(), PagePrompt(), and wmain().

◆ hStdOut

HANDLE hStdOut

Definition at line 46 of file more.c.

Referenced by ConsolePager(), doChild(), and wmain().