ReactOS  0.4.15-dev-3441-g67ad4e7
more.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <windef.h>
#include <winbase.h>
#include <winnt.h>
#include <winnls.h>
#include <winreg.h>
#include <winuser.h>
#include <conutils.h>
#include <strsafe.h>
#include "resource.h"
Include dependency graph for more.c:

Go to the source code of this file.

Macros

#define FLAG_HELP   (1 << 0)
 
#define FLAG_E   (1 << 1)
 
#define FLAG_C   (1 << 2)
 
#define FLAG_P   (1 << 3)
 
#define FLAG_S   (1 << 4)
 
#define FLAG_Tn   (1 << 5)
 
#define FLAG_PLUSn   (1 << 6)
 
#define PROMPT_PERCENT   (1 << 0)
 
#define PROMPT_LINE_AT   (1 << 1)
 
#define PROMPT_OPTIONS   (1 << 2)
 
#define PROMPT_LINES   (1 << 3)
 
#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 IsBlankLine (IN PCWCH line, IN DWORD cch)
 
static BOOL __stdcall MorePagerLine (IN OUT PCON_PAGER Pager, IN PCWCH line, IN DWORD cch)
 
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)
 
static VOID LoadRegistrySettings (HKEY hKeyRoot)
 
static BOOL IsFlag (PCWSTR param)
 
static BOOL ParseArgument (PCWSTR arg, BOOL *pbHasFiles)
 
static BOOL ParseMoreVariable (BOOL *pbHasFiles)
 
int wmain (int argc, WCHAR *argv[])
 

Variables

DWORD dwFileSize
 
DWORD dwSumReadBytes
 
DWORD dwSumReadChars
 
HANDLE hFile = INVALID_HANDLE_VALUE
 
HANDLE hStdIn
 
HANDLE hStdOut
 
HANDLE hKeyboard
 
BOOL bEnableExtensions = TRUE
 
static DWORD s_dwFlags = 0
 
static LONG s_nTabWidth = 8
 
static DWORD s_nNextLineNo = 0
 
static BOOL s_bPrevLineIsBlank = FALSE
 
static WORD s_fPrompt = 0
 
static BOOL s_bDoNextFile = FALSE
 

Macro Definition Documentation

◆ FileCacheBufferSize

#define FileCacheBufferSize   4096

◆ FLAG_C

#define FLAG_C   (1 << 2)

Definition at line 58 of file more.c.

◆ FLAG_E

#define FLAG_E   (1 << 1)

Definition at line 57 of file more.c.

◆ FLAG_HELP

#define FLAG_HELP   (1 << 0)

Definition at line 56 of file more.c.

◆ FLAG_P

#define FLAG_P   (1 << 3)

Definition at line 59 of file more.c.

◆ FLAG_PLUSn

#define FLAG_PLUSn   (1 << 6)

Definition at line 62 of file more.c.

◆ FLAG_S

#define FLAG_S   (1 << 4)

Definition at line 60 of file more.c.

◆ FLAG_Tn

#define FLAG_Tn   (1 << 5)

Definition at line 61 of file more.c.

◆ IS_TEXT_UNKNOWN_FLAGS_MASK

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

◆ PROMPT_LINE_AT

#define PROMPT_LINE_AT   (1 << 1)

Definition at line 66 of file more.c.

◆ PROMPT_LINES

#define PROMPT_LINES   (1 << 3)

Definition at line 68 of file more.c.

◆ PROMPT_OPTIONS

#define PROMPT_OPTIONS   (1 << 2)

Definition at line 67 of file more.c.

◆ PROMPT_PERCENT

#define PROMPT_PERCENT   (1 << 0)

Definition at line 65 of file more.c.

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 491 of file more.c.

492 {
493  ENCODING_ANSI = 0,
494  ENCODING_UTF16LE = 1,
495  ENCODING_UTF16BE = 2,
496  ENCODING_UTF8 = 3
497 } ENCODING;
ENCODING
Definition: more.c:491

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 652 of file more.c.

661 {
662  BOOL Success;
663  UINT CodePage = (UINT)-1;
664  DWORD dwReadBytes;
665  INT len;
666 
667  // ASSERT(pCacheBuffer && (CacheBufferLength > 0));
668  // ASSERT(CacheBufferLength % 2 == 0); // Cache buffer length MUST BE even!
669  // ASSERT(pBuffer && pnBufferLength);
670 
671  /* Always reset the retrieved number of bytes/characters */
672  if (pdwReadBytes) *pdwReadBytes = 0;
673  if (pdwReadChars) *pdwReadChars = 0;
674 
675  Success = ReadFile(hFile, pCacheBuffer, CacheBufferLength, &dwReadBytes, NULL);
676  if (!Success || dwReadBytes == 0)
677  return FALSE;
678 
679  if (pdwReadBytes) *pdwReadBytes = dwReadBytes;
680 
681  if ((Encoding == ENCODING_ANSI) || (Encoding == ENCODING_UTF8))
682  {
683  /* Conversion is needed */
684 
685  if (Encoding == ENCODING_ANSI)
686  CodePage = GetConsoleCP(); // CP_ACP; // FIXME: Cache GetConsoleCP() value.
687  else // if (Encoding == ENCODING_UTF8)
688  CodePage = CP_UTF8;
689 
690  /* Retrieve the needed buffer size */
691  len = MultiByteToWideChar(CodePage, 0, pCacheBuffer, dwReadBytes,
692  NULL, 0);
693  if (len == 0)
694  {
695  /* Failure, bail out */
696  return FALSE;
697  }
698 
699  /* Initialize the conversion buffer if needed... */
700  if (*pBuffer == NULL)
701  {
702  *pnBufferLength = len;
703  *pBuffer = HeapAlloc(GetProcessHeap(), 0, *pnBufferLength * sizeof(WCHAR));
704  if (*pBuffer == NULL)
705  {
706  // *pBuffer = NULL;
707  *pnBufferLength = 0;
708  // WARN("DEBUG: Cannot allocate memory for *pBuffer!\n");
709  // ConErrFormatMessage(GetLastError());
710  return FALSE;
711  }
712  }
713  /* ... or reallocate only if the new length is greater than the old one */
714  else if (len > *pnBufferLength)
715  {
716  PWSTR OldBuffer = *pBuffer;
717 
718  *pnBufferLength = len;
719  *pBuffer = HeapReAlloc(GetProcessHeap(), 0, *pBuffer, *pnBufferLength * sizeof(WCHAR));
720  if (*pBuffer == NULL)
721  {
722  /* Do not leak old buffer */
723  HeapFree(GetProcessHeap(), 0, OldBuffer);
724  // *pBuffer = NULL;
725  *pnBufferLength = 0;
726  // WARN("DEBUG: Cannot reallocate memory for *pBuffer!\n");
727  // ConErrFormatMessage(GetLastError());
728  return FALSE;
729  }
730  }
731 
732  /* Now perform the conversion proper */
733  len = MultiByteToWideChar(CodePage, 0, pCacheBuffer, dwReadBytes,
734  *pBuffer, len);
735  dwReadBytes = len;
736  }
737  else
738  {
739  /*
740  * No conversion needed, just convert from big to little endian if needed.
741  * pBuffer and pnBufferLength are left untouched and pCacheBuffer can be
742  * directly used.
743  */
744  PWCHAR pWChars = pCacheBuffer;
745  DWORD i;
746 
747  dwReadBytes /= sizeof(WCHAR);
748 
749  if (Encoding == ENCODING_UTF16BE)
750  {
751  for (i = 0; i < dwReadBytes; i++)
752  {
753  /* Equivalent to RtlUshortByteSwap: reverse high/low bytes */
754  pWChars[i] = MAKEWORD(HIBYTE(pWChars[i]), LOBYTE(pWChars[i]));
755  }
756  }
757  // else if (Encoding == ENCODING_UTF16LE), we are good, nothing to do.
758  }
759 
760  /* Return the number of characters (dwReadBytes is converted) */
761  if (pdwReadChars) *pdwReadChars = dwReadBytes;
762 
763  return TRUE;
764 }
#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
#define CP_UTF8
Definition: nls.h:20
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
PVOID pBuffer
UINT WINAPI DECLSPEC_HOTPATCH GetConsoleCP(VOID)
Definition: console.c:2393
#define GetProcessHeap()
Definition: compat.h:595
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
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 HeapReAlloc
Definition: compat.h:593
#define ReadFile(a, b, c, d, e)
Definition: compat.h:601
unsigned int UINT
Definition: ndis.h:50
#define NULL
Definition: types.h:112
#define MultiByteToWideChar
Definition: compat.h:110
#define HeapFree(x, y, z)
Definition: compat.h:594

Referenced by wmain().

◆ IsBlankLine()

static BOOL IsBlankLine ( IN PCWCH  line,
IN DWORD  cch 
)
static

Definition at line 77 of file more.c.

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 }
#define TRUE
Definition: types.h:120
#define C1_BLANK
Definition: unicode.h:37
#define L(x)
Definition: ntvdm.h:50
#define FALSE
Definition: types.h:117
Definition: parser.c:48
BOOL WINAPI GetStringTypeW(DWORD type, LPCWSTR src, INT count, LPWORD chartype)
Definition: lang.c:1703
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned long DWORD
Definition: ntddk_ex.h:95
#define CT_CTYPE1
Definition: winnls.h:237
#define C1_SPACE
Definition: unicode.h:34
IN PCTCH IN DWORD cch
Definition: pager.h:36

Referenced by MorePagerLine().

◆ IsDataUnicode()

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

Definition at line 500 of file more.c.

505 {
506  PBYTE pBytes = Buffer;
507  ENCODING encFile = ENCODING_ANSI;
508  DWORD dwPos = 0;
509 
510  /*
511  * See http://archives.miloush.net/michkap/archive/2007/04/22/2239345.html
512  * for more details about the algorithm and the pitfalls behind it.
513  * Of course it would be actually great to make a nice function that
514  * would work, once and for all, and put it into a library.
515  */
516 
517  /* Look for Byte Order Marks */
518  if ((BufferSize >= 2) && (pBytes[0] == 0xFF) && (pBytes[1] == 0xFE))
519  {
520  encFile = ENCODING_UTF16LE;
521  dwPos = 2;
522  }
523  else if ((BufferSize >= 2) && (pBytes[0] == 0xFE) && (pBytes[1] == 0xFF))
524  {
525  encFile = ENCODING_UTF16BE;
526  dwPos = 2;
527  }
528  else if ((BufferSize >= 3) && (pBytes[0] == 0xEF) && (pBytes[1] == 0xBB) && (pBytes[2] == 0xBF))
529  {
530  encFile = ENCODING_UTF8;
531  dwPos = 3;
532  }
533  else
534  {
535  /*
536  * Try using statistical analysis. Do not rely on the return value of
537  * IsTextUnicode as we can get FALSE even if the text is in UTF-16 BE
538  * (i.e. we have some of the IS_TEXT_UNICODE_REVERSE_MASK bits set).
539  * Instead, set all the tests we want to perform, then just check
540  * the passed tests and try to deduce the string properties.
541  */
542 
543 /*
544  * This mask contains the 3 highest bits from IS_TEXT_UNICODE_NOT_ASCII_MASK
545  * and the 1st highest bit from IS_TEXT_UNICODE_NOT_UNICODE_MASK.
546  */
547 #define IS_TEXT_UNKNOWN_FLAGS_MASK ((7 << 13) | (1 << 11))
548 
549  /* Flag out the unknown flags here, the passed tests will not have them either */
554  INT Results;
555 
557  Results = Tests;
558 
559  /*
560  * As the IS_TEXT_UNICODE_NULL_BYTES or IS_TEXT_UNICODE_ILLEGAL_CHARS
561  * flags are expected to be potentially present in the result without
562  * modifying our expectations, filter them out now.
563  */
565 
566  /*
567  * NOTE: The flags IS_TEXT_UNICODE_ASCII16 and
568  * IS_TEXT_UNICODE_REVERSE_ASCII16 are not reliable.
569  *
570  * NOTE2: Check for potential "bush hid the facts" effect by also
571  * checking the original results (in 'Tests') for the absence of
572  * the IS_TEXT_UNICODE_NULL_BYTES flag, as we may presumably expect
573  * that in UTF-16 text there will be at some point some NULL bytes.
574  * If not, fall back to ANSI. This shows the limitations of using the
575  * IsTextUnicode API to perform such tests, and the usage of a more
576  * improved encoding detection algorithm would be really welcome.
577  */
578  if (!(Results & IS_TEXT_UNICODE_NOT_UNICODE_MASK) &&
579  !(Results & IS_TEXT_UNICODE_REVERSE_MASK) &&
580  (Results & IS_TEXT_UNICODE_UNICODE_MASK) &&
582  {
583  encFile = ENCODING_UTF16LE;
584  dwPos = (Results & IS_TEXT_UNICODE_SIGNATURE) ? 2 : 0;
585  }
586  else
587  if (!(Results & IS_TEXT_UNICODE_NOT_UNICODE_MASK) &&
588  !(Results & IS_TEXT_UNICODE_UNICODE_MASK) &&
589  (Results & IS_TEXT_UNICODE_REVERSE_MASK) &&
591  {
592  encFile = ENCODING_UTF16BE;
593  dwPos = (Results & IS_TEXT_UNICODE_REVERSE_SIGNATURE) ? 2 : 0;
594  }
595  else
596  {
597  /*
598  * Either 'Results' has neither of those masks set, as it can be
599  * the case for UTF-8 text (or ANSI), or it has both as can be the
600  * case when analysing pure binary data chunk. This is therefore
601  * invalid and we fall back to ANSI encoding.
602  * FIXME: In case of failure, assume ANSI (as long as we do not have
603  * correct tests for UTF8, otherwise we should do them, and at the
604  * very end, assume ANSI).
605  */
606  encFile = ENCODING_ANSI; // ENCODING_UTF8;
607  dwPos = 0;
608  }
609  }
610 
611  if (Encoding)
612  *Encoding = encFile;
613  if (SkipBytes)
614  *SkipBytes = dwPos;
615 
616  return (encFile != ENCODING_ANSI);
617 }
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
#define IS_TEXT_UNICODE_NOT_ASCII_MASK
Definition: winnt_old.h:935
#define IS_TEXT_UNKNOWN_FLAGS_MASK
int32_t INT
Definition: typedefs.h:58
#define IS_TEXT_UNICODE_SIGNATURE
Definition: winnt_old.h:926
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:927
BOOL WINAPI IsTextUnicode(IN CONST VOID *lpv, IN INT iSize, IN OUT LPINT lpiResult OPTIONAL)
Definition: unicode.c:27
unsigned long DWORD
Definition: ntddk_ex.h:95
#define IS_TEXT_UNICODE_ILLEGAL_CHARS
Definition: winnt_old.h:928
ENCODING
Definition: more.c:491
#define IS_TEXT_UNICODE_REVERSE_MASK
Definition: winnt_old.h:933
#define IS_TEXT_UNICODE_NULL_BYTES
Definition: winnt_old.h:931
BYTE * PBYTE
Definition: pedump.c:66
#define IS_TEXT_UNICODE_UNICODE_MASK
Definition: winnt_old.h:932
struct test_data Tests[]
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:251
#define IS_TEXT_UNICODE_NOT_UNICODE_MASK
Definition: winnt_old.h:934

Referenced by wmain().

◆ IsFlag()

static BOOL IsFlag ( PCWSTR  param)
static

Definition at line 807 of file more.c.

808 {
809  PCWSTR pch;
810  PWCHAR endptr;
811 
812  if (param[0] == L'/')
813  return TRUE;
814 
815  if (param[0] == L'+')
816  {
817  pch = param + 1;
818  if (*pch)
819  {
820  (void)wcstol(pch, &endptr, 10);
821  return (*endptr == 0);
822  }
823  }
824  return FALSE;
825 }
const uint16_t * PCWSTR
Definition: typedefs.h:57
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
#define TRUE
Definition: types.h:120
_Check_return_ long __cdecl wcstol(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
uint16_t * PWCHAR
Definition: typedefs.h:56
#define pch(ap)
Definition: match.c:418
#define L(x)
Definition: ntvdm.h:50
#define FALSE
Definition: types.h:117
GLfloat param
Definition: glext.h:5796

Referenced by ParseArgument(), and wmain().

◆ LoadRegistrySettings()

static VOID LoadRegistrySettings ( HKEY  hKeyRoot)
static

Definition at line 767 of file more.c.

768 {
769  LONG lRet;
770  HKEY hKey;
771  DWORD dwType, len;
772  /*
773  * Buffer big enough to hold the string L"4294967295",
774  * corresponding to the literal 0xFFFFFFFF (MAXULONG) in decimal.
775  */
776  WCHAR Buffer[sizeof("4294967295")];
777  C_ASSERT(sizeof(Buffer) >= sizeof(DWORD));
778 
779  lRet = RegOpenKeyExW(hKeyRoot,
780  L"Software\\Microsoft\\Command Processor",
781  0,
783  &hKey);
784  if (lRet != ERROR_SUCCESS)
785  return;
786 
787  len = sizeof(Buffer);
788  lRet = RegQueryValueExW(hKey,
789  L"EnableExtensions",
790  NULL,
791  &dwType,
792  (PBYTE)&Buffer,
793  &len);
794  if (lRet == ERROR_SUCCESS)
795  {
796  /* Overwrite the default setting */
797  if (dwType == REG_DWORD)
799  else if (dwType == REG_SZ)
800  bEnableExtensions = (_wtol((PWSTR)Buffer) == 1);
801  }
802  // else, use the default setting set globally.
803 
804  RegCloseKey(hKey);
805 }
#define ERROR_SUCCESS
Definition: deptool.c:10
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
uint16_t * PWSTR
Definition: typedefs.h:56
#define L(x)
Definition: ntvdm.h:50
long LONG
Definition: pedump.c:60
Definition: bufpool.h:45
#define C_ASSERT(e)
Definition: intsafe.h:73
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4120
__wchar_t WCHAR
Definition: xmlstorage.h:180
unsigned long DWORD
Definition: ntddk_ex.h:95
GLenum GLsizei len
Definition: glext.h:6722
BOOL bEnableExtensions
Definition: more.c:53
FxAutoRegKey hKey
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
_Check_return_ _CRTIMP long __cdecl _wtol(_In_z_ const wchar_t *_Str)
#define NULL
Definition: types.h:112
DWORD * PDWORD
Definition: pedump.c:68
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3356
#define REG_DWORD
Definition: sdbapi.c:596
BYTE * PBYTE
Definition: pedump.c:66
#define RegCloseKey(hKey)
Definition: registry.h:40
#define REG_SZ
Definition: layer.c:22

Referenced by wmain().

◆ MorePagerLine()

static BOOL __stdcall MorePagerLine ( IN OUT PCON_PAGER  Pager,
IN PCWCH  line,
IN DWORD  cch 
)
static

Definition at line 106 of file more.c.

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  {
125  if (s_bPrevLineIsBlank)
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 }
#define TRUE
Definition: types.h:120
#define FLAG_S
Definition: more.c:60
static BOOL s_bPrevLineIsBlank
Definition: more.c:73
#define FLAG_PLUSn
Definition: more.c:62
#define FALSE
Definition: types.h:117
INT ConStreamWrite(IN PCON_STREAM Stream, IN PCTCH szStr, IN DWORD len)
Definition: outstream.c:398
Definition: parser.c:48
static BOOL IsBlankLine(IN PCWCH line, IN DWORD cch)
Definition: more.c:77
static DWORD s_dwFlags
Definition: more.c:70
static DWORD s_nNextLineNo
Definition: more.c:72
#define TEXT(s)
Definition: k32.h:26
IN PCTCH IN DWORD cch
Definition: pager.h:36

Referenced by wmain().

◆ PagePrompt()

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

Definition at line 160 of file more.c.

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 
180  WCHAR szPercent[80] = L"";
181  WCHAR szLineAt[80] = L"";
182 
183  /* Load the prompt strings */
184  if (!*StrPercent)
185  K32LoadStringW(NULL, IDS_CONTINUE_PERCENT, StrPercent, ARRAYSIZE(StrPercent));
186  if (!*StrLineAt)
187  K32LoadStringW(NULL, IDS_CONTINUE_LINE_AT, StrLineAt, ARRAYSIZE(StrLineAt));
188  if (!*StrOptions)
189  K32LoadStringW(NULL, IDS_CONTINUE_OPTIONS, StrOptions, ARRAYSIZE(StrOptions));
190  if (!*StrLines)
191  K32LoadStringW(NULL, IDS_CONTINUE_LINES, StrLines, ARRAYSIZE(StrLines));
192 
193  /*
194  * Check whether the pager is prompting, but we have actually finished
195  * to display a given file, or no data is present in STDIN anymore.
196  * In this case, skip the prompt altogether. The only exception is when
197  * we are displaying other files.
198  */
199  // TODO: Implement!
200 
201 Restart:
202  nLines = 0;
203 
204  /* Do not show the progress percentage when STDIN is being displayed */
205  if (s_fPrompt & PROMPT_PERCENT) // && (hFile != hStdIn)
206  {
207  /*
208  * The progress percentage is evaluated as follows.
209  * So far we have read a total of 'dwSumReadBytes' bytes from the file.
210  * Amongst those is the latest read chunk of 'dwReadBytes' bytes, to which
211  * correspond a number of 'dwReadChars' characters with which we have called
212  * ConWritePaging who called PagePrompt. We then have: Total == dwReadChars.
213  * During this ConWritePaging call the PagePrompt was called after 'Done'
214  * number of characters over 'Total'.
215  * It should be noted that for 'dwSumReadBytes' number of bytes read it
216  * *roughly* corresponds 'dwSumReadChars' number of characters. This is
217  * because there may be some failures happening during the conversion of
218  * the bytes read to the character string for a given encoding.
219  * Therefore the number of characters displayed on screen is equal to:
220  * dwSumReadChars - Total + Done ,
221  * but the best corresponding approximed number of bytes would be:
222  * dwSumReadBytes - (Total - Done) * (dwSumReadBytes / dwSumReadChars) ,
223  * where the ratio is the average number of bytes per character.
224  * The percentage is then computed relative to the total file size.
225  */
226  DWORD dwPercent = (dwSumReadBytes - (Total - Done) *
228  StringCchPrintfW(szPercent, ARRAYSIZE(szPercent), StrPercent, dwPercent);
229  }
231  {
232  StringCchPrintfW(szLineAt, ARRAYSIZE(szLineAt), StrLineAt, Pager->lineno);
233  }
234 
235  /* Suitably format and display the prompt */
238  (s_fPrompt & PROMPT_LINE_AT ? szLineAt : L""),
239  (s_fPrompt & PROMPT_OPTIONS ? StrOptions : L""),
240  (s_fPrompt & PROMPT_LINES ? StrLines : L""));
241 
242  /* Reset the prompt to a default state */
244 
245  /* RemoveBreakHandler */
247  /* ConInDisable */
248  GetConsoleMode(hInput, &dwMode);
249  dwMode &= ~ENABLE_PROCESSED_INPUT;
250  SetConsoleMode(hInput, dwMode);
251 
252  // FIXME: Does not support TTY yet!
253  ConGetScreenInfo(Pager->Screen, &csbi);
254  orgCursorPosition = csbi.dwCursorPosition;
255  for (;;)
256  {
257  INPUT_RECORD ir = {0};
258  DWORD dwRead;
259  WCHAR ch;
260 
261  do
262  {
263  ReadConsoleInput(hInput, &ir, 1, &dwRead);
264  }
265  while ((ir.EventType != KEY_EVENT) || (!ir.Event.KeyEvent.bKeyDown));
266 
267  /* Got our key */
268  KeyEvent = ir.Event.KeyEvent;
269 
270  /* Ignore any unsupported keyboard press */
271  if ((KeyEvent.wVirtualKeyCode == VK_SHIFT) ||
272  (KeyEvent.wVirtualKeyCode == VK_MENU) ||
273  (KeyEvent.wVirtualKeyCode == VK_CONTROL))
274  {
275  continue;
276  }
277 
278  /* Ctrl key is pressed? */
279  fCtrl = !!(KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED));
280 
281  /* Ctrl+C or Ctrl+Esc? */
282  if (fCtrl && ((KeyEvent.wVirtualKeyCode == VK_ESCAPE) ||
283  (KeyEvent.wVirtualKeyCode == L'C')))
284  {
285  chSubCommand = 0;
286  break;
287  }
288 
289  /* If extended features are unavailable, or no
290  * pending commands, don't do more processing. */
291  if (!(s_dwFlags & FLAG_E) || (chSubCommand == 0))
292  break;
293 
294  ch = KeyEvent.uChar.UnicodeChar;
295  if (L'0' <= ch && ch <= L'9')
296  {
297  nLines *= 10;
298  nLines += ch - L'0';
299  ConStreamWrite(Pager->Screen->Stream, &ch, 1);
300  continue;
301  }
302  else if (KeyEvent.wVirtualKeyCode == VK_RETURN)
303  {
304  /* Validate the line number */
305  break;
306  }
307  else if (KeyEvent.wVirtualKeyCode == VK_ESCAPE)
308  {
309  /* Cancel the current command */
310  chSubCommand = 0;
311  break;
312  }
313  else if (KeyEvent.wVirtualKeyCode == VK_BACK)
314  {
315  if (nLines != 0)
316  nLines /= 10;
317 
318  /* Erase the current character */
319  ConGetScreenInfo(Pager->Screen, &csbi);
320  if ( (csbi.dwCursorPosition.Y > orgCursorPosition.Y) ||
321  ((csbi.dwCursorPosition.Y == orgCursorPosition.Y) &&
322  (csbi.dwCursorPosition.X > orgCursorPosition.X)) )
323  {
324  if (csbi.dwCursorPosition.X > 0)
325  {
326  csbi.dwCursorPosition.X = csbi.dwCursorPosition.X - 1;
327  }
328  else if (csbi.dwCursorPosition.Y > 0)
329  {
330  csbi.dwCursorPosition.Y = csbi.dwCursorPosition.Y - 1;
331  csbi.dwCursorPosition.X = (csbi.dwSize.X ? csbi.dwSize.X - 1 : 0);
332  }
333 
335 
336  ch = L' ';
337  ConStreamWrite(Pager->Screen->Stream, &ch, 1);
339  }
340 
341  continue;
342  }
343  }
344 
345  /* AddBreakHandler */
347  /* ConInEnable */
348  GetConsoleMode(hInput, &dwMode);
349  dwMode |= ENABLE_PROCESSED_INPUT;
350  SetConsoleMode(hInput, dwMode);
351 
352  /* Refresh the screen information, as the console may have been
353  * redimensioned. Update also the default number of lines to scroll. */
354  ConGetScreenInfo(Pager->Screen, &csbi);
355  Pager->ScrollRows = csbi.srWindow.Bottom - csbi.srWindow.Top;
356 
357  /*
358  * Erase the full line where the cursor is, and move
359  * the cursor back to the beginning of the line.
360  */
361  ConClearLine(Pager->Screen->Stream);
362 
363  /* Ctrl+C or Ctrl+Esc: Control Break */
364  if (fCtrl && ((KeyEvent.wVirtualKeyCode == VK_ESCAPE) ||
365  (KeyEvent.wVirtualKeyCode == L'C')))
366  {
367  /* We break, output a newline */
368  WCHAR ch = L'\n';
369  ConStreamWrite(Pager->Screen->Stream, &ch, 1);
370  return FALSE;
371  }
372 
373  switch (chSubCommand)
374  {
375  case L'P':
376  {
377  /* If we don't display other lines, just restart the prompt */
378  if (nLines == 0)
379  {
380  chSubCommand = 0;
381  goto Restart;
382  }
383  /* Otherwise tell the pager to display them */
384  Pager->ScrollRows = nLines;
385  return TRUE;
386  }
387  case L'S':
388  {
390  s_nNextLineNo = Pager->lineno + nLines;
391  /* Use the default Pager->ScrollRows value */
392  return TRUE;
393  }
394  default:
395  chSubCommand = 0;
396  break;
397  }
398 
399  /* If extended features are available */
400  if (s_dwFlags & FLAG_E)
401  {
402  /* Ignore any key presses if Ctrl is pressed */
403  if (fCtrl)
404  {
405  chSubCommand = 0;
406  goto Restart;
407  }
408 
409  /* 'Q': Quit */
410  if (KeyEvent.wVirtualKeyCode == L'Q')
411  {
412  /* We break, output a newline */
413  WCHAR ch = L'\n';
414  ConStreamWrite(Pager->Screen->Stream, &ch, 1);
415  return FALSE;
416  }
417 
418  /* 'F': Next file */
419  if (KeyEvent.wVirtualKeyCode == L'F')
420  {
422  return FALSE;
423  }
424 
425  /* '?': Show Options */
426  if (KeyEvent.uChar.UnicodeChar == L'?')
427  {
429  goto Restart;
430  }
431 
432  /* [Enter] key: Display one line */
433  if (KeyEvent.wVirtualKeyCode == VK_RETURN)
434  {
435  Pager->ScrollRows = 1;
436  return TRUE;
437  }
438 
439  /* [Space] key: Display one page */
440  if (KeyEvent.wVirtualKeyCode == VK_SPACE)
441  {
442  if (s_dwFlags & FLAG_C)
443  {
444  /* Clear the screen */
445  ConClearScreen(Pager->Screen);
446  }
447  /* Use the default Pager->ScrollRows value */
448  return TRUE;
449  }
450 
451  /* 'P': Display n lines */
452  if (KeyEvent.wVirtualKeyCode == L'P')
453  {
455  chSubCommand = L'P';
456  goto Restart;
457  }
458 
459  /* 'S': Skip n lines */
460  if (KeyEvent.wVirtualKeyCode == L'S')
461  {
463  chSubCommand = L'S';
464  goto Restart;
465  }
466 
467  /* '=': Show current line number */
468  if (KeyEvent.uChar.UnicodeChar == L'=')
469  {
471  goto Restart;
472  }
473 
474  chSubCommand = 0;
475  goto Restart;
476  }
477  else
478  {
479  /* Extended features are unavailable: display one page */
480  /* Use the default Pager->ScrollRows value */
481  return TRUE;
482  }
483 }
PCON_STREAM Stream
Definition: screen.h:43
#define IDS_CONTINUE_OPTIONS
Definition: resource.h:10
WCHAR UnicodeChar
Definition: wincon.h:245
BOOL ConGetScreenInfo(IN PCON_SCREEN Screen, OUT PCONSOLE_SCREEN_BUFFER_INFO pcsbi)
Definition: screen.c:73
static WORD s_fPrompt
Definition: more.c:74
#define TRUE
Definition: types.h:120
DWORD dwSumReadBytes
Definition: more.c:41
BOOL WINAPI GetConsoleMode(HANDLE hConsoleHandle, LPDWORD lpMode)
Definition: console.c:1571
DWORD dwFileSize
Definition: more.c:40
static const WCHAR szPercent[]
Definition: varformat.c:393
DWORD dwControlKeyState
Definition: wincon.h:248
#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
INT WINAPI K32LoadStringW(IN HINSTANCE hInstance OPTIONAL, IN UINT uID, OUT LPWSTR lpBuffer, IN INT nBufferMax)
Definition: utils.c:173
#define VK_MENU
Definition: winuser.h:2184
#define VK_ESCAPE
Definition: winuser.h:2194
#define VK_RETURN
Definition: winuser.h:2181
#define FLAG_PLUSn
Definition: more.c:62
WORD wVirtualKeyCode
Definition: wincon.h:242
union _KEY_EVENT_RECORD::@3205 uChar
PCON_SCREEN Screen
Definition: pager.h:48
#define FLAG_E
Definition: more.c:57
#define L(x)
Definition: ntvdm.h:50
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
#define ReadConsoleInput
Definition: wincon.h:778
#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 KEY_EVENT
Definition: wincon.h:128
#define PROMPT_LINES
Definition: more.c:68
#define VK_SHIFT
Definition: winuser.h:2182
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
ULONG X
Definition: bl.h:1340
HANDLE ConStreamGetOSHandle(IN PCON_STREAM Stream)
Definition: stream.c:240
SHORT Bottom
Definition: blue.h:35
__wchar_t WCHAR
Definition: xmlstorage.h:180
static BOOL s_bDoNextFile
Definition: more.c:75
KEY_EVENT_RECORD KeyEvent
Definition: wincon.h:275
unsigned long DWORD
Definition: ntddk_ex.h:95
#define IDS_CONTINUE_PERCENT
Definition: resource.h:8
SHORT Top
Definition: blue.h:33
#define IDS_CONTINUE_LINES
Definition: resource.h:11
static DWORD s_dwFlags
Definition: more.c:70
#define LEFT_CTRL_PRESSED
Definition: wincon.h:140
DWORD ScrollRows
Definition: pager.h:56
VOID ConClearScreen(IN PCON_SCREEN Screen)
Definition: screen.c:131
#define VK_BACK
Definition: winuser.h:2178
static DWORD s_nNextLineNo
Definition: more.c:72
Definition: bl.h:1338
DWORD dwSumReadChars
Definition: more.c:41
#define ENABLE_PROCESSED_INPUT
Definition: wincon.h:78
STRSAFEAPI StringCchPrintfW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:530
DWORD lineno
Definition: pager.h:70
union _INPUT_RECORD::@3206 Event
#define NULL
Definition: types.h:112
#define VK_SPACE
Definition: winuser.h:2199
#define VK_CONTROL
Definition: winuser.h:2183
WORD EventType
Definition: wincon.h:273
#define IDS_CONTINUE_LINE_AT
Definition: resource.h:9
#define RIGHT_CTRL_PRESSED
Definition: wincon.h:139
#define IDS_CONTINUE_PROMPT
Definition: resource.h:7
#define PROMPT_PERCENT
Definition: more.c:65
ULONG Y
Definition: bl.h:1341
#define StdIn
Definition: stream.h:81
INT __cdecl ConResMsgPrintf(IN PCON_STREAM Stream, IN DWORD dwFlags, IN UINT uID,...)
Definition: outstream.c:1461

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

◆ ParseArgument()

static BOOL ParseArgument ( PCWSTR  arg,
BOOL pbHasFiles 
)
static

Definition at line 827 of file more.c.

828 {
829  PWCHAR endptr;
830 
831  if (arg[0] == L'/')
832  {
833  switch (towupper(arg[1]))
834  {
835  case L'?':
836  if (arg[2] == 0)
837  {
838  s_dwFlags |= FLAG_HELP;
839  return TRUE;
840  }
841  break;
842  case L'E':
843  if (arg[2] == 0)
844  {
845  s_dwFlags |= FLAG_E;
846  return TRUE;
847  }
848  break;
849  case L'C':
850  if (arg[2] == 0)
851  {
852  s_dwFlags |= FLAG_C;
853  return TRUE;
854  }
855  break;
856  case L'P':
857  if (arg[2] == 0)
858  {
859  s_dwFlags |= FLAG_P;
860  return TRUE;
861  }
862  break;
863  case L'S':
864  if (arg[2] == 0)
865  {
866  s_dwFlags |= FLAG_S;
867  return TRUE;
868  }
869  break;
870  case L'T':
871  if (arg[2] != 0)
872  {
873  s_dwFlags |= FLAG_Tn;
874  s_nTabWidth = wcstol(&arg[2], &endptr, 10);
875  if (*endptr == 0)
876  return TRUE;
877  }
878  break;
879  default:
880  break;
881  }
882  }
883  else if (arg[0] == L'+')
884  {
885  if (arg[1] != 0)
886  {
888  s_nNextLineNo = wcstol(&arg[1], &endptr, 10) + 1;
889  if (*endptr == 0)
890  return TRUE;
891  }
892  }
893 
894  if (IsFlag(arg))
895  {
897  return FALSE;
898  }
899  else
900  {
901  *pbHasFiles = TRUE;
902  }
903 
904  return TRUE;
905 }
#define FLAG_HELP
Definition: more.c:56
#define FLAG_Tn
Definition: more.c:61
#define TRUE
Definition: types.h:120
#define FLAG_S
Definition: more.c:60
#define IDS_BAD_FLAG
Definition: resource.h:4
_Check_return_ long __cdecl wcstol(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
uint16_t * PWCHAR
Definition: typedefs.h:56
#define FLAG_PLUSn
Definition: more.c:62
#define FLAG_P
Definition: more.c:59
#define FLAG_E
Definition: more.c:57
#define L(x)
Definition: ntvdm.h:50
#define FALSE
Definition: types.h:117
#define FLAG_C
Definition: more.c:58
void ConResPrintf(FILE *fp, UINT nID,...)
Definition: fc.c:33
static BOOL IsFlag(PCWSTR param)
Definition: more.c:807
static DWORD s_dwFlags
Definition: more.c:70
static DWORD s_nNextLineNo
Definition: more.c:72
static LONG s_nTabWidth
Definition: more.c:71
#define towupper(c)
Definition: wctype.h:99
#define StdErr
Definition: fc.c:15

Referenced by ParseMoreVariable(), and wmain().

◆ ParseMoreVariable()

static BOOL ParseMoreVariable ( BOOL pbHasFiles)
static

Definition at line 907 of file more.c.

908 {
909  BOOL ret = TRUE;
910  PWSTR psz;
911  PWCHAR pch;
912  DWORD cch;
913 
914  cch = GetEnvironmentVariableW(L"MORE", NULL, 0);
915  if (cch == 0)
916  return TRUE;
917 
918  psz = (PWSTR)malloc((cch + 1) * sizeof(WCHAR));
919  if (!psz)
920  return TRUE;
921 
922  if (!GetEnvironmentVariableW(L"MORE", psz, cch + 1))
923  {
924  free(psz);
925  return TRUE;
926  }
927 
928  for (pch = wcstok(psz, L" "); pch; pch = wcstok(NULL, L" "))
929  {
930  ret = ParseArgument(pch, pbHasFiles);
931  if (!ret)
932  break;
933  }
934 
935  free(psz);
936  return ret;
937 }
#define TRUE
Definition: types.h:120
uint16_t * PWSTR
Definition: typedefs.h:56
#define free
Definition: debug_ros.c:5
_Check_return_ _CRTIMP wchar_t *__cdecl wcstok(_Inout_opt_z_ wchar_t *_Str, _In_z_ const wchar_t *_Delim)
uint16_t * PWCHAR
Definition: typedefs.h:56
#define pch(ap)
Definition: match.c:418
#define L(x)
Definition: ntvdm.h:50
unsigned int BOOL
Definition: ntddk_ex.h:94
__wchar_t WCHAR
Definition: xmlstorage.h:180
unsigned long DWORD
Definition: ntddk_ex.h:95
int ret
static BOOL ParseArgument(PCWSTR arg, BOOL *pbHasFiles)
Definition: more.c:827
#define NULL
Definition: types.h:112
#define malloc
Definition: debug_ros.c:4
IN PCTCH IN DWORD cch
Definition: pager.h:36
#define GetEnvironmentVariableW(x, y, z)
Definition: compat.h:614

Referenced by wmain().

◆ wmain()

int wmain ( int  argc,
WCHAR argv[] 
)

Definition at line 940 of file more.c.

941 {
942  // FIXME this stuff!
944  CON_PAGER Pager = {&Screen, 0};
945 
946  int i;
947 
948  BOOL bRet, bContinue;
949 
950  ENCODING Encoding;
951  DWORD SkipBytes = 0;
952  BOOL HasFiles;
953 
954 #define FileCacheBufferSize 4096
955  PVOID FileCacheBuffer = NULL;
957  DWORD StringBufferLength = 0;
958  DWORD dwReadBytes = 0, dwReadChars = 0;
959 
960  TCHAR szFullPath[MAX_PATH];
961 
964 
965  /* Initialize the Console Standard Streams */
969 
970  /*
971  * Bad usage (too much options) or we use the /? switch.
972  * Display help for the MORE command.
973  */
974  if (argc > 1 && wcscmp(argv[1], L"/?") == 0)
975  {
977  return 0;
978  }
979 
980  /* Load the registry settings */
983  if (bEnableExtensions)
984  s_dwFlags |= FLAG_E;
985 
986  // NOTE: We might try to duplicate the ConOut for read access... ?
989  OPEN_EXISTING, 0, NULL);
992 
993  FileCacheBuffer = HeapAlloc(GetProcessHeap(), 0, FileCacheBufferSize);
994  if (!FileCacheBuffer)
995  {
996  ConPuts(StdErr, L"Error: no memory\n");
998  return 1;
999  }
1000 
1001  /* First, load the "MORE" environment variable and parse it,
1002  * then parse the command-line parameters. */
1003  HasFiles = FALSE;
1004  if (!ParseMoreVariable(&HasFiles))
1005  return 1;
1006  for (i = 1; i < argc; i++)
1007  {
1008  if (!ParseArgument(argv[i], &HasFiles))
1009  return 1;
1010  }
1011 
1012  if (s_dwFlags & FLAG_HELP)
1013  {
1015  return 0;
1016  }
1017 
1018  Pager.PagerLine = MorePagerLine;
1020  if (s_dwFlags & FLAG_P)
1021  Pager.dwFlags |= CON_PAGER_EXPAND_FF;
1022  Pager.nTabWidth = s_nTabWidth;
1023 
1024  /* Special case where we run 'MORE' without any argument: we use STDIN */
1025  if (!HasFiles)
1026  {
1027  /*
1028  * Assign STDIN handle to hFile so that the page prompt function will
1029  * know the data comes from STDIN, and will take different actions.
1030  */
1031  hFile = hStdIn;
1032 
1033  /* Update the statistics for PagePrompt */
1034  dwFileSize = 0;
1036 
1037  /* We suppose we read text from the file */
1038 
1039  /* For STDIN we always suppose we are in ANSI mode */
1040  // SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
1041  Encoding = ENCODING_ANSI; // ENCODING_UTF8;
1042 
1043  /* Start paging */
1044  bContinue = ConWritePaging(&Pager, PagePrompt, TRUE, NULL, 0);
1045  if (!bContinue)
1046  goto Quit;
1047 
1048  do
1049  {
1050  bRet = FileGetString(hFile, Encoding,
1051  FileCacheBuffer, FileCacheBufferSize,
1052  &StringBuffer, &StringBufferLength,
1053  &dwReadBytes, &dwReadChars);
1054  if (!bRet || dwReadBytes == 0 || dwReadChars == 0)
1055  {
1056  /* We failed at reading the file, bail out */
1057  break;
1058  }
1059 
1060  /* Update the statistics for PagePrompt */
1061  dwSumReadBytes += dwReadBytes;
1062  dwSumReadChars += dwReadChars;
1063 
1064  bContinue = ConWritePaging(&Pager, PagePrompt, FALSE,
1065  StringBuffer, dwReadChars);
1066  /* If we Ctrl-C/Ctrl-Break, stop everything */
1067  if (!bContinue)
1068  break;
1069  }
1070  while (bRet && dwReadBytes > 0);
1071 
1072  /* Flush any cached pager buffers */
1073  if (bContinue)
1074  bContinue = ConWritePaging(&Pager, PagePrompt, FALSE, NULL, 0);
1075 
1076  goto Quit;
1077  }
1078 
1079  /* We have files: read them and output them to STDOUT */
1080  for (i = 1; i < argc; i++)
1081  {
1082  if (IsFlag(argv[i]))
1083  continue;
1084 
1085  GetFullPathNameW(argv[i], ARRAYSIZE(szFullPath), szFullPath, NULL);
1086  hFile = CreateFileW(szFullPath,
1087  GENERIC_READ,
1089  NULL,
1090  OPEN_EXISTING,
1091  0, // FILE_ATTRIBUTE_NORMAL,
1092  NULL);
1093  if (hFile == INVALID_HANDLE_VALUE)
1094  {
1095  ConResPrintf(StdErr, IDS_FILE_ACCESS, szFullPath);
1096  goto Quit;
1097  }
1098 
1099  /* We currently do not support files too big */
1102  {
1103  ConPuts(StdErr, L"ERROR: Invalid file size!\n");
1104  CloseHandle(hFile);
1105  continue;
1106  }
1107 
1108  /* We suppose we read text from the file */
1109 
1110  /* Check whether the file is UNICODE and retrieve its encoding */
1112  bRet = ReadFile(hFile, FileCacheBuffer, FileCacheBufferSize, &dwReadBytes, NULL);
1113  IsDataUnicode(FileCacheBuffer, dwReadBytes, &Encoding, &SkipBytes);
1115 
1116  /* Reset state for paging */
1117  s_nNextLineNo = 0;
1120  s_bDoNextFile = FALSE;
1121 
1122  /* Update the statistics for PagePrompt */
1124 
1125  /* Start paging */
1126  bContinue = ConWritePaging(&Pager, PagePrompt, TRUE, NULL, 0);
1127  if (!bContinue)
1128  {
1129  /* We stop displaying this file */
1130  CloseHandle(hFile);
1131  if (s_bDoNextFile)
1132  {
1133  /* Bail out and continue with the other files */
1134  continue;
1135  }
1136 
1137  /* We Ctrl-C/Ctrl-Break, stop everything */
1138  goto Quit;
1139  }
1140 
1141  do
1142  {
1143  bRet = FileGetString(hFile, Encoding,
1144  FileCacheBuffer, FileCacheBufferSize,
1145  &StringBuffer, &StringBufferLength,
1146  &dwReadBytes, &dwReadChars);
1147  if (!bRet || dwReadBytes == 0 || dwReadChars == 0)
1148  {
1149  /*
1150  * We failed at reading the file, bail out
1151  * and continue with the other files.
1152  */
1153  break;
1154  }
1155 
1156  /* Update the statistics for PagePrompt */
1157  dwSumReadBytes += dwReadBytes;
1158  dwSumReadChars += dwReadChars;
1159 
1160  if ((Encoding == ENCODING_UTF16LE) || (Encoding == ENCODING_UTF16BE))
1161  {
1162  bContinue = ConWritePaging(&Pager, PagePrompt, FALSE,
1163  FileCacheBuffer, dwReadChars);
1164  }
1165  else
1166  {
1167  bContinue = ConWritePaging(&Pager, PagePrompt, FALSE,
1168  StringBuffer, dwReadChars);
1169  }
1170  if (!bContinue)
1171  {
1172  /* We stop displaying this file */
1173  break;
1174  }
1175  }
1176  while (bRet && dwReadBytes > 0);
1177 
1178  /* Flush any cached pager buffers */
1179  if (bContinue)
1180  bContinue = ConWritePaging(&Pager, PagePrompt, FALSE, NULL, 0);
1181 
1182  CloseHandle(hFile);
1183 
1184  /* Check whether we should stop displaying this file */
1185  if (!bContinue)
1186  {
1187  if (s_bDoNextFile)
1188  {
1189  /* Bail out and continue with the other files */
1190  continue;
1191  }
1192 
1193  /* We Ctrl-C/Ctrl-Break, stop everything */
1194  goto Quit;
1195  }
1196  }
1197 
1198 Quit:
1200  HeapFree(GetProcessHeap(), 0, FileCacheBuffer);
1202  return 0;
1203 }
#define FLAG_HELP
Definition: more.c:56
static int argc
Definition: ServiceArgs.c:12
static BOOL __stdcall PagePrompt(PCON_PAGER Pager, DWORD Done, DWORD Total)
Definition: more.c:160
#define CloseHandle
Definition: compat.h:598
BOOL ConWritePaging(IN PCON_PAGER Pager, IN PAGE_PROMPT PagePrompt, IN BOOL StartPaging, IN PCTCH szStr, IN DWORD len)
Definition: pager.c:549
static WORD s_fPrompt
Definition: more.c:74
#define TRUE
Definition: types.h:120
DWORD dwSumReadBytes
Definition: more.c:41
#define HKEY_CURRENT_USER
Definition: winreg.h:11
DWORD dwFileSize
Definition: more.c:40
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#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
static BOOL ParseMoreVariable(BOOL *pbHasFiles)
Definition: more.c:907
#define IDS_USAGE
Definition: resource.h:3
#define INVALID_FILE_SIZE
Definition: winbase.h:545
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 CON_PAGER_EXPAND_TABS
Definition: pager.h:40
#define argv
Definition: mplay32.c:18
#define FILE_SHARE_READ
Definition: compat.h:136
void ConPuts(FILE *fp, LPCWSTR psz)
Definition: fc.c:16
#define FLAG_P
Definition: more.c:59
#define FLAG_E
Definition: more.c:57
LONG nTabWidth
Definition: pager.h:55
#define L(x)
Definition: ntvdm.h:50
DWORD dwFlags
Definition: pager.h:54
#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:49
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
CON_PAGER_LINE_FN PagerLine
Definition: pager.h:53
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
#define CON_PAGER_EXPAND_FF
Definition: pager.h:41
static BOOL IsDataUnicode(IN PVOID Buffer, IN DWORD BufferSize, OUT ENCODING *Encoding OPTIONAL, OUT PDWORD SkipBytes OPTIONAL)
Definition: more.c:500
void ConResPrintf(FILE *fp, UINT nID,...)
Definition: fc.c:33
#define GetProcessHeap()
Definition: compat.h:595
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
static BOOL s_bDoNextFile
Definition: more.c:75
#define STD_ERROR_HANDLE
Definition: winbase.h:266
#define MAX_PATH
Definition: compat.h:34
static BOOL IsFlag(PCWSTR param)
Definition: more.c:807
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:652
#define INVALID_CP
Definition: stream.h:53
static DWORD s_dwFlags
Definition: more.c:70
static BOOL ParseArgument(PCWSTR arg, BOOL *pbHasFiles)
Definition: more.c:827
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
static VOID LoadRegistrySettings(HKEY hKeyRoot)
Definition: more.c:767
_In_ HANDLE hFile
Definition: mswsock.h:90
static DWORD s_nNextLineNo
Definition: more.c:72
static LONG s_nTabWidth
Definition: more.c:71
#define CON_PAGER_CACHE_INCOMPLETE_LINE
Definition: pager.h:43
DWORD dwSumReadChars
Definition: more.c:41
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
ENCODING
Definition: more.c:491
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
#define ReadFile(a, b, c, d, e)
Definition: compat.h:601
#define NULL
Definition: types.h:112
#define CreateFileW
Definition: compat.h:600
#define StdOut
Definition: fc.c:14
#define IDS_FILE_ACCESS
Definition: resource.h:5
Definition: console.h:34
HANDLE hKeyboard
Definition: more.c:50
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
WCHAR StringBuffer[156]
Definition: ldrinit.c:41
#define HeapFree(x, y, z)
Definition: compat.h:594
#define SetFilePointer
Definition: compat.h:602
#define StdIn
Definition: stream.h:81
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define StdErr
Definition: fc.c:15

Variable Documentation

◆ bEnableExtensions

◆ dwFileSize

◆ dwSumReadBytes

DWORD dwSumReadBytes

Definition at line 41 of file more.c.

Referenced by PagePrompt(), and wmain().

◆ dwSumReadChars

DWORD dwSumReadChars

Definition at line 41 of file more.c.

Referenced by PagePrompt(), and wmain().

◆ hFile

Definition at line 48 of file more.c.

◆ hKeyboard

HANDLE hKeyboard

Definition at line 50 of file more.c.

Referenced by wmain().

◆ hStdIn

HANDLE hStdIn

Definition at line 49 of file more.c.

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

◆ hStdOut

HANDLE hStdOut

Definition at line 49 of file more.c.

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

◆ s_bDoNextFile

BOOL s_bDoNextFile = FALSE
static

Definition at line 75 of file more.c.

Referenced by PagePrompt(), and wmain().

◆ s_bPrevLineIsBlank

BOOL s_bPrevLineIsBlank = FALSE
static

Definition at line 73 of file more.c.

Referenced by MorePagerLine(), and wmain().

◆ s_dwFlags

DWORD s_dwFlags = 0
static

Definition at line 70 of file more.c.

Referenced by MorePagerLine(), PagePrompt(), ParseArgument(), and wmain().

◆ s_fPrompt

WORD s_fPrompt = 0
static

Definition at line 74 of file more.c.

Referenced by PagePrompt(), and wmain().

◆ s_nNextLineNo

DWORD s_nNextLineNo = 0
static

Definition at line 72 of file more.c.

Referenced by MorePagerLine(), PagePrompt(), ParseArgument(), and wmain().

◆ s_nTabWidth

LONG s_nTabWidth = 8
static

Definition at line 71 of file more.c.

Referenced by ParseArgument(), and wmain().