ReactOS 0.4.16-dev-306-g647d351
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_UTF8BOM = 4 , 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_UTF8BOM 
ENCODING_ANSI 
ENCODING_UTF16LE 
ENCODING_UTF16BE 
ENCODING_UTF8 
ENCODING_ANSI 
ENCODING_UTF8 
ENCODING_UTF16LE 
ENCODING_UTF16BE 

Definition at line 492 of file more.c.

493{
494 ENCODING_ANSI = 0,
497 ENCODING_UTF8 = 3
498} ENCODING;
ENCODING
Definition: more.c:493
@ ENCODING_UTF16BE
Definition: more.c:496
@ ENCODING_UTF8
Definition: more.c:497
@ ENCODING_UTF16LE
Definition: more.c:495
@ ENCODING_ANSI
Definition: more.c:494

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

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

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}
BOOL WINAPI GetStringTypeW(DWORD type, LPCWSTR src, INT count, LPWORD chartype)
Definition: locale.c:3095
unsigned short WORD
Definition: ntddk_ex.h:93
#define C1_SPACE
Definition: unicode.h:34
#define C1_BLANK
Definition: unicode.h:37
static DWORD DWORD void LPSTR DWORD cch
Definition: str.c:202
#define L(x)
Definition: ntvdm.h:50
Definition: parser.c:49
#define CT_CTYPE1
Definition: winnls.h:239

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

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

Referenced by wmain().

◆ IsFlag()

static BOOL IsFlag ( PCWSTR  param)
static

Definition at line 808 of file more.c.

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

Referenced by ParseArgument(), and wmain().

◆ LoadRegistrySettings()

static VOID LoadRegistrySettings ( HKEY  hKeyRoot)
static

Definition at line 768 of file more.c.

769{
770 LONG lRet;
771 HKEY hKey;
772 DWORD dwType, len;
773 /*
774 * Buffer big enough to hold the string L"4294967295",
775 * corresponding to the literal 0xFFFFFFFF (MAXULONG) in decimal.
776 */
777 WCHAR Buffer[sizeof("4294967295")];
778 C_ASSERT(sizeof(Buffer) >= sizeof(DWORD));
779
780 lRet = RegOpenKeyExW(hKeyRoot,
781 L"Software\\Microsoft\\Command Processor",
782 0,
784 &hKey);
785 if (lRet != ERROR_SUCCESS)
786 return;
787
788 len = sizeof(Buffer);
789 lRet = RegQueryValueExW(hKey,
790 L"EnableExtensions",
791 NULL,
792 &dwType,
793 (PBYTE)&Buffer,
794 &len);
795 if (lRet == ERROR_SUCCESS)
796 {
797 /* Overwrite the default setting */
798 if (dwType == REG_DWORD)
800 else if (dwType == REG_SZ)
802 }
803 // else, use the default setting set globally.
804
806}
#define RegCloseKey(hKey)
Definition: registry.h:49
#define ERROR_SUCCESS
Definition: deptool.c:10
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3333
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4103
FxAutoRegKey hKey
_Check_return_ _CRTIMP long __cdecl _wtol(_In_z_ const wchar_t *_Str)
#define C_ASSERT(e)
Definition: intsafe.h:73
#define REG_SZ
Definition: layer.c:22
BOOL bEnableExtensions
Definition: more.c:53
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
DWORD * PDWORD
Definition: pedump.c:68
long LONG
Definition: pedump.c:60
#define REG_DWORD
Definition: sdbapi.c:596

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

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

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

◆ ParseArgument()

static BOOL ParseArgument ( PCWSTR  arg,
BOOL pbHasFiles 
)
static

Definition at line 828 of file more.c.

829{
830 PWCHAR endptr;
831
832 if (arg[0] == L'/')
833 {
834 switch (towupper(arg[1]))
835 {
836 case L'?':
837 if (arg[2] == 0)
838 {
840 return TRUE;
841 }
842 break;
843 case L'E':
844 if (arg[2] == 0)
845 {
846 s_dwFlags |= FLAG_E;
847 return TRUE;
848 }
849 break;
850 case L'C':
851 if (arg[2] == 0)
852 {
853 s_dwFlags |= FLAG_C;
854 return TRUE;
855 }
856 break;
857 case L'P':
858 if (arg[2] == 0)
859 {
860 s_dwFlags |= FLAG_P;
861 return TRUE;
862 }
863 break;
864 case L'S':
865 if (arg[2] == 0)
866 {
867 s_dwFlags |= FLAG_S;
868 return TRUE;
869 }
870 break;
871 case L'T':
872 if (arg[2] != 0)
873 {
875 s_nTabWidth = wcstol(&arg[2], &endptr, 10);
876 if (*endptr == 0)
877 return TRUE;
878 }
879 break;
880 default:
881 break;
882 }
883 }
884 else if (arg[0] == L'+')
885 {
886 if (arg[1] != 0)
887 {
889 s_nNextLineNo = wcstol(&arg[1], &endptr, 10) + 1;
890 if (*endptr == 0)
891 return TRUE;
892 }
893 }
894
895 if (IsFlag(arg))
896 {
898 return FALSE;
899 }
900 else
901 {
902 *pbHasFiles = TRUE;
903 }
904
905 return TRUE;
906}
void ConResPrintf(FILE *fp, UINT nID,...)
Definition: fc.c:33
#define StdErr
Definition: fc.c:15
#define IDS_BAD_FLAG
Definition: resource.h:4
#define FLAG_Tn
Definition: more.c:61
#define FLAG_P
Definition: more.c:59
static LONG s_nTabWidth
Definition: more.c:71
static BOOL IsFlag(PCWSTR param)
Definition: more.c:808
#define FLAG_HELP
Definition: more.c:56
#define towupper(c)
Definition: wctype.h:99

Referenced by ParseMoreVariable(), and wmain().

◆ ParseMoreVariable()

static BOOL ParseMoreVariable ( BOOL pbHasFiles)
static

Definition at line 908 of file more.c.

909{
910 BOOL ret = TRUE;
911 PWSTR psz;
912 PWCHAR pch;
913 DWORD cch;
914
915 cch = GetEnvironmentVariableW(L"MORE", NULL, 0);
916 if (cch == 0)
917 return TRUE;
918
919 psz = (PWSTR)malloc((cch + 1) * sizeof(WCHAR));
920 if (!psz)
921 return TRUE;
922
923 if (!GetEnvironmentVariableW(L"MORE", psz, cch + 1))
924 {
925 free(psz);
926 return TRUE;
927 }
928
929 for (pch = wcstok(psz, L" "); pch; pch = wcstok(NULL, L" "))
930 {
931 ret = ParseArgument(pch, pbHasFiles);
932 if (!ret)
933 break;
934 }
935
936 free(psz);
937 return ret;
938}
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define GetEnvironmentVariableW(x, y, z)
Definition: compat.h:755
static BOOL ParseArgument(PCWSTR arg, BOOL *pbHasFiles)
Definition: more.c:828
_CRT_RESTORE_GCC_WARNINGS _Check_return_ _CRTIMP wchar_t *__cdecl wcstok(_Inout_opt_z_ wchar_t *_Str, _In_z_ const wchar_t *_Delim)
int ret

Referenced by wmain().

◆ wmain()

int wmain ( int  argc,
WCHAR argv[] 
)

Definition at line 941 of file more.c.

942{
943 // FIXME this stuff!
945 CON_PAGER Pager = {&Screen, 0};
946
947 int i;
948
949 BOOL bRet, bContinue;
950
951 ENCODING Encoding;
952 DWORD SkipBytes = 0;
953 BOOL HasFiles;
954
955#define FileCacheBufferSize 4096
956 PVOID FileCacheBuffer = NULL;
958 DWORD StringBufferLength = 0;
959 DWORD dwReadBytes = 0, dwReadChars = 0;
960
961 TCHAR szFullPath[MAX_PATH];
962
965
966 /* Initialize the Console Standard Streams */
970
971 /*
972 * Bad usage (too much options) or we use the /? switch.
973 * Display help for the MORE command.
974 */
975 if (argc > 1 && wcscmp(argv[1], L"/?") == 0)
976 {
978 return 0;
979 }
980
981 /* Load the registry settings */
985 s_dwFlags |= FLAG_E;
986
987 // NOTE: We might try to duplicate the ConOut for read access... ?
990 OPEN_EXISTING, 0, NULL);
993
994 FileCacheBuffer = HeapAlloc(GetProcessHeap(), 0, FileCacheBufferSize);
995 if (!FileCacheBuffer)
996 {
997 ConPuts(StdErr, L"Error: no memory\n");
999 return 1;
1000 }
1001
1002 /* First, load the "MORE" environment variable and parse it,
1003 * then parse the command-line parameters. */
1004 HasFiles = FALSE;
1005 if (!ParseMoreVariable(&HasFiles))
1006 return 1;
1007 for (i = 1; i < argc; i++)
1008 {
1009 if (!ParseArgument(argv[i], &HasFiles))
1010 return 1;
1011 }
1012
1013 if (s_dwFlags & FLAG_HELP)
1014 {
1016 return 0;
1017 }
1018
1019 Pager.PagerLine = MorePagerLine;
1021 if (s_dwFlags & FLAG_P)
1023 Pager.nTabWidth = s_nTabWidth;
1024
1025 /* Special case where we run 'MORE' without any argument: we use STDIN */
1026 if (!HasFiles)
1027 {
1028 /*
1029 * Assign STDIN handle to hFile so that the page prompt function will
1030 * know the data comes from STDIN, and will take different actions.
1031 */
1032 hFile = hStdIn;
1033
1034 /* Update the statistics for PagePrompt */
1035 dwFileSize = 0;
1037
1038 /* We suppose we read text from the file */
1039
1040 /* For STDIN we always suppose we are in ANSI mode */
1041 // SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
1042 Encoding = ENCODING_ANSI; // ENCODING_UTF8;
1043
1044 /* Start paging */
1045 bContinue = ConWritePaging(&Pager, PagePrompt, TRUE, NULL, 0);
1046 if (!bContinue)
1047 goto Quit;
1048
1049 do
1050 {
1051 bRet = FileGetString(hFile, Encoding,
1052 FileCacheBuffer, FileCacheBufferSize,
1053 &StringBuffer, &StringBufferLength,
1054 &dwReadBytes, &dwReadChars);
1055 if (!bRet || dwReadBytes == 0 || dwReadChars == 0)
1056 {
1057 /* We failed at reading the file, bail out */
1058 break;
1059 }
1060
1061 /* Update the statistics for PagePrompt */
1062 dwSumReadBytes += dwReadBytes;
1063 dwSumReadChars += dwReadChars;
1064
1065 bContinue = ConWritePaging(&Pager, PagePrompt, FALSE,
1066 StringBuffer, dwReadChars);
1067 /* If we Ctrl-C/Ctrl-Break, stop everything */
1068 if (!bContinue)
1069 break;
1070 }
1071 while (bRet && dwReadBytes > 0);
1072
1073 /* Flush any cached pager buffers */
1074 if (bContinue)
1075 bContinue = ConWritePaging(&Pager, PagePrompt, FALSE, NULL, 0);
1076
1077 goto Quit;
1078 }
1079
1080 /* We have files: read them and output them to STDOUT */
1081 for (i = 1; i < argc; i++)
1082 {
1083 if (IsFlag(argv[i]))
1084 continue;
1085
1086 GetFullPathNameW(argv[i], ARRAYSIZE(szFullPath), szFullPath, NULL);
1087 hFile = CreateFileW(szFullPath,
1090 NULL,
1092 0, // FILE_ATTRIBUTE_NORMAL,
1093 NULL);
1095 {
1096 ConResPrintf(StdErr, IDS_FILE_ACCESS, szFullPath);
1097 goto Quit;
1098 }
1099
1100 /* We currently do not support files too big */
1103 {
1104 ConPuts(StdErr, L"ERROR: Invalid file size!\n");
1106 continue;
1107 }
1108
1109 /* We suppose we read text from the file */
1110
1111 /* Check whether the file is UNICODE and retrieve its encoding */
1113 bRet = ReadFile(hFile, FileCacheBuffer, FileCacheBufferSize, &dwReadBytes, NULL);
1114 IsDataUnicode(FileCacheBuffer, dwReadBytes, &Encoding, &SkipBytes);
1116
1117 /* Reset state for paging */
1118 s_nNextLineNo = 0;
1122
1123 /* Update the statistics for PagePrompt */
1125
1126 /* Start paging */
1127 bContinue = ConWritePaging(&Pager, PagePrompt, TRUE, NULL, 0);
1128 if (!bContinue)
1129 {
1130 /* We stop displaying this file */
1132 if (s_bDoNextFile)
1133 {
1134 /* Bail out and continue with the other files */
1135 continue;
1136 }
1137
1138 /* We Ctrl-C/Ctrl-Break, stop everything */
1139 goto Quit;
1140 }
1141
1142 do
1143 {
1144 bRet = FileGetString(hFile, Encoding,
1145 FileCacheBuffer, FileCacheBufferSize,
1146 &StringBuffer, &StringBufferLength,
1147 &dwReadBytes, &dwReadChars);
1148 if (!bRet || dwReadBytes == 0 || dwReadChars == 0)
1149 {
1150 /*
1151 * We failed at reading the file, bail out
1152 * and continue with the other files.
1153 */
1154 break;
1155 }
1156
1157 /* Update the statistics for PagePrompt */
1158 dwSumReadBytes += dwReadBytes;
1159 dwSumReadChars += dwReadChars;
1160
1161 if ((Encoding == ENCODING_UTF16LE) || (Encoding == ENCODING_UTF16BE))
1162 {
1163 bContinue = ConWritePaging(&Pager, PagePrompt, FALSE,
1164 FileCacheBuffer, dwReadChars);
1165 }
1166 else
1167 {
1168 bContinue = ConWritePaging(&Pager, PagePrompt, FALSE,
1169 StringBuffer, dwReadChars);
1170 }
1171 if (!bContinue)
1172 {
1173 /* We stop displaying this file */
1174 break;
1175 }
1176 }
1177 while (bRet && dwReadBytes > 0);
1178
1179 /* Flush any cached pager buffers */
1180 if (bContinue)
1181 bContinue = ConWritePaging(&Pager, PagePrompt, FALSE, NULL, 0);
1182
1184
1185 /* Check whether we should stop displaying this file */
1186 if (!bContinue)
1187 {
1188 if (s_bDoNextFile)
1189 {
1190 /* Bail out and continue with the other files */
1191 continue;
1192 }
1193
1194 /* We Ctrl-C/Ctrl-Break, stop everything */
1195 goto Quit;
1196 }
1197 }
1198
1199Quit:
1201 HeapFree(GetProcessHeap(), 0, FileCacheBuffer);
1203 return 0;
1204}
static int argc
Definition: ServiceArgs.c:12
#define IDS_USAGE
Definition: resource.h:3
void ConPuts(FILE *fp, LPCWSTR psz)
Definition: fc.c:16
#define StdOut
Definition: fc.c:14
void ConResPuts(FILE *fp, UINT nID)
Definition: fc.c:27
#define IDS_FILE_ACCESS
Definition: resource.h:5
BOOL WINAPI FlushConsoleInputBuffer(IN HANDLE hConsoleInput)
Definition: console.c:220
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:203
@ Screen
Definition: console.h:34
#define CloseHandle
Definition: compat.h:739
#define FILE_BEGIN
Definition: compat.h:761
#define OPEN_EXISTING
Definition: compat.h:775
#define SetFilePointer
Definition: compat.h:743
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#define CreateFileW
Definition: compat.h:741
#define FILE_SHARE_READ
Definition: compat.h:136
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:331
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1106
WCHAR StringBuffer[156]
Definition: ldrinit.c:41
static BOOL __stdcall MorePagerLine(IN OUT PCON_PAGER Pager, IN PCWCH line, IN DWORD cch)
Definition: more.c:106
static VOID LoadRegistrySettings(HKEY hKeyRoot)
Definition: more.c:768
static BOOL ParseMoreVariable(BOOL *pbHasFiles)
Definition: more.c:908
static BOOL FileGetString(IN HANDLE hFile, IN ENCODING Encoding, IN OUT PVOID pCacheBuffer, IN DWORD CacheBufferLength, IN OUT PWCHAR *pBuffer, IN OUT PDWORD pnBufferLength, OUT PDWORD pdwReadBytes OPTIONAL, OUT PDWORD pdwReadChars OPTIONAL)
Definition: more.c:653
static BOOL __stdcall PagePrompt(PCON_PAGER Pager, DWORD Done, DWORD Total)
Definition: more.c:160
HANDLE hStdOut
Definition: more.c:49
#define FileCacheBufferSize
HANDLE hStdIn
Definition: more.c:49
HANDLE hKeyboard
Definition: more.c:50
static BOOL IsDataUnicode(IN PVOID Buffer, IN DWORD BufferSize, OUT ENCODING *Encoding OPTIONAL, OUT PDWORD SkipBytes OPTIONAL)
Definition: more.c:501
#define argv
Definition: mplay32.c:18
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define GENERIC_WRITE
Definition: nt_native.h:90
#define CON_PAGER_EXPAND_TABS
Definition: pager.h:40
#define CON_PAGER_CACHE_INCOMPLETE_LINE
Definition: pager.h:43
#define CON_PAGER_EXPAND_FF
Definition: pager.h:41
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
BOOL ConWritePaging(IN PCON_PAGER Pager, IN PAGE_PROMPT PagePrompt, IN BOOL StartPaging, IN PCTCH szStr, IN DWORD len)
Definition: pager.c:549
BOOL ConStreamSetOSHandle(IN PCON_STREAM Stream, IN HANDLE Handle)
Definition: stream.c:263
BOOL ConStreamInit(OUT PCON_STREAM Stream, IN PVOID Handle, IN CON_STREAM_MODE Mode, IN UINT CacheCodePage OPTIONAL)
Definition: stream.c:185
@ UTF8Text
Definition: stream.h:50
#define INVALID_CP
Definition: stream.h:53
DWORD dwFlags
Definition: pager.h:54
LONG nTabWidth
Definition: pager.h:55
CON_PAGER_LINE_FN PagerLine
Definition: pager.h:53
#define STD_OUTPUT_HANDLE
Definition: winbase.h:294
#define STD_INPUT_HANDLE
Definition: winbase.h:293
#define STD_ERROR_HANDLE
Definition: winbase.h:295
#define INVALID_FILE_SIZE
Definition: winbase.h:574
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define HKEY_CURRENT_USER
Definition: winreg.h:11
char TCHAR
Definition: xmlstorage.h:189

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().