Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers into modules, and delete rossubsys.

This commit is contained in:
Colin Finck 2017-10-03 07:45:34 +00:00
parent b94e2d8ca0
commit c2c66aff7d
24198 changed files with 0 additions and 37285 deletions

View file

@ -0,0 +1,14 @@
list(APPEND SOURCE
pager.c
screen.c
stream.c
utils.c
# conutils.h
)
add_library(conutils ${SOURCE})
# add_pch(conutils conutils.h SOURCE)
add_dependencies(conutils xdk)
target_link_libraries(conutils ${PSEH_LIB})
add_importlibs(conutils msvcrt kernel32)

View file

@ -0,0 +1,43 @@
The ReactOS Console Utilities Library v0.1
==========================================
COPYRIGHT: Under GPLv2, see COPYING in the top level directory.
CREDITS: Thanks to the many people who originally wrote the code that finally
ended up inside this library, with more or less refactoring, or
whose code served as a basis for some functions of the library.
INTRODUCTION
~-~-~-~-~-~-
This library contains common functions used in many places inside the ReactOS
console utilities and the ReactOS Command-Line Interpreter. Most of these
functions are related with internationalisation and the problem of correctly
displaying Unicode text on the console. Besides those, helpful functions for
retrieving strings and messages from application resources are provided,
together with printf-like functionality.
CONTENTS
~-~-~-~-
0. 'conutils_base' (utils.c and utils.h): Base set of functions for loading
string resources and message strings, and handle type identification.
1. 'conutils_stream' (stream.c and stream.h): Console Stream API (CON_STREAM):
Stream initialization, basic ConStreamRead/Write. Stream utility functions:
ConPuts/Printf, ConResPuts/Printf, ConMsgPuts/Printf.
Depends on 'conutils_base'.
2. 'conutils_screen' (screen.c and screen.h): Console Screen API (CON_SCREEN):
Introduces the notion of console/terminal screen around the streams. Manages
console/terminal screen metrics for Win32 consoles and TTYs (serial...).
Additional Screen utility functions.
Depends on 'conutils_stream', and indirectly on 'conutils_base'.
3. 'conutils_pager' (pager.c and pager.h): Console Pager API (CON_PAGER):
Implements core console/terminal paging functionality around console screens.
Depends on 'conutils_screen' and indirectly on 'conutils_stream' and
'conutils_base'.
4. More to come!

View file

@ -0,0 +1,25 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Console Utilities Library
* FILE: sdk/lib/conutils/conutils.h
* PURPOSE: Provides simple abstraction wrappers around CRT streams or
* Win32 console API I/O functions, to deal with i18n + Unicode
* related problems.
* PROGRAMMERS: - Hermes Belusca-Maito (for the library);
* - All programmers who wrote the different console applications
* from which I took those functions and improved them.
*/
#ifndef __CONUTILS_H__
#define __CONUTILS_H__
#ifndef _UNICODE
#error The ConUtils library only supports compilation with _UNICODE defined, at the moment!
#endif
#include "utils.h"
#include "stream.h"
#include "screen.h"
#include "pager.h"
#endif /* __CONUTILS_H__ */

160
sdk/lib/conutils/pager.c Normal file
View file

@ -0,0 +1,160 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Console Utilities Library
* FILE: sdk/lib/conutils/pager.c
* PURPOSE: Console/terminal paging functionality.
* PROGRAMMERS: - Hermes Belusca-Maito (for the library);
* - All programmers who wrote the different console applications
* from which I took those functions and improved them.
*/
/* FIXME: Temporary HACK before we cleanly support UNICODE functions */
#define UNICODE
#define _UNICODE
#include <stdlib.h> // limits.h // For MB_LEN_MAX
#include <windef.h>
#include <winbase.h>
// #include <winnls.h>
#include <wincon.h> // Console APIs (only if kernel32 support included)
#include <strsafe.h>
#include "conutils.h"
#include "stream.h"
#include "screen.h"
#include "pager.h"
// Temporary HACK
#define CON_STREAM_WRITE ConStreamWrite
/* Returns TRUE when all the text is displayed, and FALSE if display is stopped */
BOOL
ConWritePaging(
IN PCON_PAGER Pager,
IN PAGE_PROMPT PagePrompt,
IN BOOL StartPaging,
IN PTCHAR szStr,
IN DWORD len)
{
CONSOLE_SCREEN_BUFFER_INFO csbi;
/* Used to see how big the screen is */
DWORD ScreenLines = 0;
/* Chars since start of line */
DWORD CharSL;
DWORD from = 0, i = 0;
/* Parameters validation */
if (!Pager)
return FALSE;
/* Reset LineCount and return if no string has been given */
if (StartPaging == TRUE)
Pager->LineCount = 0;
if (szStr == NULL)
return TRUE;
/* Get the size of the visual screen that can be printed to */
if (!ConGetScreenInfo(Pager->Screen, &csbi))
{
/* We assume it's a file handle */
CON_STREAM_WRITE(Pager->Screen->Stream, szStr, len);
return TRUE;
}
/*
* Get the number of lines currently displayed on screen, minus 1
* to account for the "press any key..." prompt from PagePrompt().
*/
ScreenLines = (csbi.srWindow.Bottom - csbi.srWindow.Top);
CharSL = csbi.dwCursorPosition.X;
/* Make sure the user doesn't have the screen too small */
if (ScreenLines < 4)
{
CON_STREAM_WRITE(Pager->Screen->Stream, szStr, len);
return TRUE;
}
while (i < len)
{
/* Search until the end of a line is reached */
if (szStr[i++] != TEXT('\n') && ++CharSL < csbi.dwSize.X)
continue;
Pager->LineCount++;
CharSL = 0;
if (Pager->LineCount >= ScreenLines)
{
CON_STREAM_WRITE(Pager->Screen->Stream, &szStr[from], i-from);
from = i;
/* Prompt the user; give him some values for statistics */
// FIXME TODO: The prompt proc can also take ScreenLines ??
if (!PagePrompt(Pager, from, len))
return FALSE;
// TODO: Recalculate 'ScreenLines' in case the user redimensions
// the window during the prompt.
/* Reset the number of lines being printed */
Pager->LineCount = 0;
}
}
if (i > from)
CON_STREAM_WRITE(Pager->Screen->Stream, &szStr[from], i-from);
return TRUE;
}
BOOL
ConPutsPaging(
IN PCON_PAGER Pager,
IN PAGE_PROMPT PagePrompt,
IN BOOL StartPaging,
IN LPTSTR szStr)
{
DWORD len;
/* Return if no string has been given */
if (szStr == NULL)
return TRUE;
len = wcslen(szStr);
return ConWritePaging(Pager, PagePrompt, StartPaging, szStr, len);
}
BOOL
ConResPagingEx(
IN PCON_PAGER Pager,
IN PAGE_PROMPT PagePrompt,
IN BOOL StartPaging,
IN HINSTANCE hInstance OPTIONAL,
IN UINT uID)
{
INT Len;
PWCHAR szStr = NULL;
Len = K32LoadStringW(hInstance, uID, (PWSTR)&szStr, 0);
if (szStr && Len)
return ConWritePaging(Pager, PagePrompt, StartPaging, szStr, Len);
else
return TRUE;
}
BOOL
ConResPaging(
IN PCON_PAGER Pager,
IN PAGE_PROMPT PagePrompt,
IN BOOL StartPaging,
IN UINT uID)
{
return ConResPagingEx(Pager, PagePrompt, StartPaging,
NULL /*GetModuleHandleW(NULL)*/, uID);
}

74
sdk/lib/conutils/pager.h Normal file
View file

@ -0,0 +1,74 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Console Utilities Library
* FILE: sdk/lib/conutils/pager.h
* PURPOSE: Console/terminal paging functionality.
* PROGRAMMERS: - Hermes Belusca-Maito (for the library);
* - All programmers who wrote the different console applications
* from which I took those functions and improved them.
*/
#ifndef __PAGER_H__
#define __PAGER_H__
#ifndef _UNICODE
#error The ConUtils library at the moment only supports compilation with _UNICODE defined!
#endif
// #include <wincon.h>
typedef struct _CON_PAGER
{
PCON_SCREEN Screen;
// TODO: Add more properties. Maybe those extra parameters
// of PAGE_PROMPT could go there?
/* Used to count number of lines since last pause */
DWORD LineCount;
} CON_PAGER, *PCON_PAGER;
#define INIT_CON_PAGER(pScreen) {(pScreen), 0}
#define InitializeConPager(pPager, pScreen) \
do { \
(pPager)->Screen = (pScreen); \
(pPager)->LineCount = 0; \
} while (0)
// Pager, Done, Total
typedef BOOL (__stdcall *PAGE_PROMPT)(IN PCON_PAGER, IN DWORD, IN DWORD);
BOOL
ConWritePaging(
IN PCON_PAGER Pager,
IN PAGE_PROMPT PagePrompt,
IN BOOL StartPaging,
IN PTCHAR szStr,
IN DWORD len);
BOOL
ConPutsPaging(
IN PCON_PAGER Pager,
IN PAGE_PROMPT PagePrompt,
IN BOOL StartPaging,
IN LPTSTR szStr);
BOOL
ConResPagingEx(
IN PCON_PAGER Pager,
IN PAGE_PROMPT PagePrompt,
IN BOOL StartPaging,
IN HINSTANCE hInstance OPTIONAL,
IN UINT uID);
BOOL
ConResPaging(
IN PCON_PAGER Pager,
IN PAGE_PROMPT PagePrompt,
IN BOOL StartPaging,
IN UINT uID);
#endif /* __PAGER_H__ */

175
sdk/lib/conutils/screen.c Normal file
View file

@ -0,0 +1,175 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Console Utilities Library
* FILE: sdk/lib/conutils/screen.c
* PURPOSE: Console/terminal screen management.
* PROGRAMMERS: - Hermes Belusca-Maito (for the library);
* - All programmers who wrote the different console applications
* from which I took those functions and improved them.
*/
/* FIXME: Temporary HACK before we cleanly support UNICODE functions */
#define UNICODE
#define _UNICODE
#include <stdlib.h> // limits.h // For MB_LEN_MAX
#include <windef.h>
#include <winbase.h>
// #include <winnls.h>
#include <wincon.h> // Console APIs (only if kernel32 support included)
#include <strsafe.h>
#include "conutils.h"
#include "stream.h"
#include "screen.h"
// Temporary HACK
#define CON_STREAM_WRITE ConStreamWrite
#if 0
VOID
ConClearLine(IN PCON_STREAM Stream)
{
HANDLE hOutput = ConStreamGetOSHandle(Stream);
/*
* Erase the full line where the cursor is, and move
* the cursor back to the beginning of the line.
*/
if (IsConsoleHandle(hOutput))
{
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD dwWritten;
GetConsoleScreenBufferInfo(hOutput, &csbi);
csbi.dwCursorPosition.X = 0;
// csbi.dwCursorPosition.Y;
FillConsoleOutputCharacterW(hOutput, L' ',
csbi.dwSize.X,
csbi.dwCursorPosition,
&dwWritten);
SetConsoleCursorPosition(hOutput, csbi.dwCursorPosition);
}
else if (IsTTYHandle(hOutput))
{
ConPuts(Stream, L"\x1B[2K\x1B[1G"); // FIXME: Just use WriteFile
}
// else, do nothing for files
}
#endif
BOOL
ConGetScreenInfo(
IN PCON_SCREEN Screen,
OUT PCONSOLE_SCREEN_BUFFER_INFO pcsbi)
{
BOOL Success;
HANDLE hOutput;
/* Parameters validation */
if (!Screen || !pcsbi)
return FALSE;
hOutput = ConStreamGetOSHandle(Screen->Stream);
/* Screen handle must be of TTY type (console or TTY) */
if (!IsTTYHandle(hOutput))
return FALSE;
/* Update cached screen information */
if (IsConsoleHandle(hOutput))
{
Success = GetConsoleScreenBufferInfo(hOutput, &Screen->csbi);
}
else
{
#if 0
/* TODO: Do something adequate for TTYs */
// FIXME: At the moment we return hardcoded info.
Screen->csbi.dwSize.X = 80;
Screen->csbi.dwSize.Y = 25;
// Screen->csbi.dwCursorPosition;
// Screen->csbi.wAttributes;
// Screen->csbi.srWindow;
Screen->csbi.dwMaximumWindowSize = Screen->csbi.dwSize;
#else
hOutput = CreateFileW(L"CONOUT$", GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, NULL);
Success = IsConsoleHandle(hOutput) &&
GetConsoleScreenBufferInfo(hOutput, &Screen->csbi);
CloseHandle(hOutput);
#endif
}
if (Success)
{
/* Return it to the caller */
*pcsbi = Screen->csbi;
}
return Success;
}
// For real consoles, erase everything, otherwise (TTY) erase just the "screen".
// FIXME: Or we can add a BOOL flag?
VOID
ConClearScreen(IN PCON_SCREEN Screen)
{
HANDLE hOutput;
/* Parameters validation */
if (!Screen) return;
#if 0
/* Get the size of the visual screen */
if (!ConGetScreenInfo(Screen, &csbi))
{
/* We assume it's a file handle */
return;
}
#endif
hOutput = ConStreamGetOSHandle(Screen->Stream);
if (IsConsoleHandle(hOutput))
{
CONSOLE_SCREEN_BUFFER_INFO csbi;
COORD coPos;
DWORD dwWritten;
GetConsoleScreenBufferInfo(hOutput, &csbi);
coPos.X = 0;
coPos.Y = 0;
FillConsoleOutputAttribute(hOutput, csbi.wAttributes,
csbi.dwSize.X * csbi.dwSize.Y,
coPos, &dwWritten);
FillConsoleOutputCharacterW(hOutput, L' ',
csbi.dwSize.X * csbi.dwSize.Y,
coPos, &dwWritten);
SetConsoleCursorPosition(hOutput, coPos);
}
else if (IsTTYHandle(hOutput))
{
/* Clear the full screen and move the cursor to (0,0) */
ConPuts(Screen->Stream, L"\x1B[2J\x1B[1;1H");
}
else
{
/* Issue a Form-Feed control */
WCHAR ch = L'\f';
CON_STREAM_WRITE(Screen->Stream, &ch, 1);
}
}

56
sdk/lib/conutils/screen.h Normal file
View file

@ -0,0 +1,56 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Console Utilities Library
* FILE: sdk/lib/conutils/screen.h
* PURPOSE: Console/terminal screen management.
* PROGRAMMERS: - Hermes Belusca-Maito (for the library);
* - All programmers who wrote the different console applications
* from which I took those functions and improved them.
*/
#ifndef __SCREEN_H__
#define __SCREEN_H__
#ifndef _UNICODE
#error The ConUtils library at the moment only supports compilation with _UNICODE defined!
#endif
#if 0
VOID
ConClearLine(IN PCON_STREAM Stream);
#endif
#include <wincon.h>
typedef struct _CON_SCREEN
{
PCON_STREAM Stream; // Out
// PCON_STREAM In;
CONSOLE_SCREEN_BUFFER_INFO csbi;
CONSOLE_CURSOR_INFO cci;
} CON_SCREEN, *PCON_SCREEN;
#define INIT_CON_SCREEN(pStream) {(pStream)} /* {(pStream), {{}}, {{}}} */
#define InitializeConScreen(pScreen, pStream) \
do { \
(pScreen)->Stream = (pStream); \
RtlZeroMemory(&(pScreen)->csbi, sizeof((pScreen)->csbi)); \
RtlZeroMemory(&(pScreen)->cci , sizeof((pScreen)->cci )); \
} while (0)
BOOL
ConGetScreenInfo(
IN PCON_SCREEN Screen,
OUT PCONSOLE_SCREEN_BUFFER_INFO pcsbi);
VOID
ConClearScreen(IN PCON_SCREEN Screen);
#endif /* __SCREEN_H__ */

1051
sdk/lib/conutils/stream.c Normal file

File diff suppressed because it is too large Load diff

267
sdk/lib/conutils/stream.h Normal file
View file

@ -0,0 +1,267 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Console Utilities Library
* FILE: sdk/lib/conutils/stream.h
* PURPOSE: Provides basic abstraction wrappers around CRT streams or
* Win32 console API I/O functions, to deal with i18n + Unicode
* related problems.
* PROGRAMMERS: - Hermes Belusca-Maito (for the library);
* - All programmers who wrote the different console applications
* from which I took those functions and improved them.
*/
#ifndef __STREAM_H__
#define __STREAM_H__
/*
* Enable this define if you want to only use CRT functions to output
* UNICODE stream to the console, as in the way explained by
* http://archives.miloush.net/michkap/archive/2008/03/18/8306597.html
*/
/** NOTE: Experimental! Don't use USE_CRT yet because output to console is a bit broken **/
// #define USE_CRT
#ifndef _UNICODE
#error The ConUtils library at the moment only supports compilation with _UNICODE defined!
#endif
/*
* Console I/O streams
*/
/*
* See http://archives.miloush.net/michkap/archive/2009/08/14/9869928.html
* for more information.
*/
typedef enum _CON_STREAM_MODE
{
Binary = 0, // #define _O_BINARY 0x8000 // file mode is binary (untranslated)
// #define _O_RAW _O_BINARY
AnsiText, // #define _O_TEXT 0x4000 // file mode is text (translated) -- "ANSI"
WideText, // #define _O_WTEXT 0x10000 // file mode is UTF16 with BOM (translated) -- "Unicode" of Windows
UTF16Text, // #define _O_U16TEXT 0x20000 // file mode is UTF16 no BOM (translated) -- "" ""
UTF8Text, // #define _O_U8TEXT 0x40000 // file mode is UTF8 no BOM (translated)
} CON_STREAM_MODE, *PCON_STREAM_MODE;
#define INVALID_CP ((UINT)-1)
// Shadow type, implementation-specific
typedef struct _CON_STREAM CON_STREAM, *PCON_STREAM;
// typedef INT (__stdcall *CON_READ_FUNC)(IN PCON_STREAM, IN PTCHAR, IN DWORD);
// Stream, szStr, len
typedef INT (__stdcall *CON_WRITE_FUNC)(IN PCON_STREAM, IN PTCHAR, IN DWORD);
/*
* Standard console streams, initialized by
* calls to ConStreamInit/ConInitStdStreams.
*/
#if 0 // FIXME!
extern CON_STREAM StdStreams[3];
#define StdIn (&StdStreams[0])
#define StdOut (&StdStreams[1])
#define StdErr (&StdStreams[2])
#else
extern CON_STREAM csStdIn;
extern CON_STREAM csStdOut;
extern CON_STREAM csStdErr;
#define StdIn (&csStdIn )
#define StdOut (&csStdOut)
#define StdErr (&csStdErr)
#endif
BOOL
ConStreamInitEx(
OUT PCON_STREAM Stream,
IN PVOID Handle,
IN CON_STREAM_MODE Mode,
IN UINT CacheCodePage OPTIONAL,
// IN ReadWriteMode ????
// IN CON_READ_FUNC ReadFunc OPTIONAL,
IN CON_WRITE_FUNC WriteFunc OPTIONAL);
BOOL
ConStreamInit(
OUT PCON_STREAM Stream,
IN PVOID Handle,
// IN ReadWriteMode ????
IN CON_STREAM_MODE Mode,
IN UINT CacheCodePage OPTIONAL);
/* Console Standard Streams initialization helpers */
#ifdef USE_CRT
#define ConInitStdStreamsAndMode(Mode, CacheCodePage) \
do { \
ConStreamInit(StdIn , stdin , (Mode), (CacheCodePage)); \
ConStreamInit(StdOut, stdout, (Mode), (CacheCodePage)); \
ConStreamInit(StdErr, stderr, (Mode), (CacheCodePage)); \
} while(0)
#else
#define ConInitStdStreamsAndMode(Mode, CacheCodePage) \
do { \
ConStreamInit(StdIn , GetStdHandle(STD_INPUT_HANDLE) , (Mode), (CacheCodePage)); \
ConStreamInit(StdOut, GetStdHandle(STD_OUTPUT_HANDLE), (Mode), (CacheCodePage)); \
ConStreamInit(StdErr, GetStdHandle(STD_ERROR_HANDLE) , (Mode), (CacheCodePage)); \
} while(0)
#endif /* defined(USE_CRT) */
#ifdef _UNICODE
/*
* Use UTF8 by default for file output, because this mode is back-compatible
* with ANSI, and it displays nice on terminals that support UTF8 by default
* (not many terminals support UTF16 on the contrary).
*/
#define ConInitStdStreams() \
ConInitStdStreamsAndMode(UTF8Text, INVALID_CP); // Cache code page unused
#else
/* Use ANSI by default for file output */
#define ConInitStdStreams() \
ConInitStdStreamsAndMode(AnsiText, INVALID_CP);
#endif /* defined(_UNICODE) */
/* Stream translation modes */
BOOL
ConStreamSetMode(
IN PCON_STREAM Stream,
IN CON_STREAM_MODE Mode,
IN UINT CacheCodePage OPTIONAL);
#ifdef USE_CRT
// FIXME!
#warning The ConStreamSetCacheCodePage function does not make much sense with the CRT!
#else
BOOL
ConStreamSetCacheCodePage(
IN PCON_STREAM Stream,
IN UINT CacheCodePage);
#endif
HANDLE
ConStreamGetOSHandle(
IN PCON_STREAM Stream);
BOOL
ConStreamSetOSHandle(
IN PCON_STREAM Stream,
IN HANDLE Handle);
/*
* Console I/O utility API
* (for the moment, only Output)
*/
INT
__stdcall
ConWrite(
IN PCON_STREAM Stream,
IN PTCHAR szStr,
IN DWORD len);
INT
ConStreamWrite(
IN PCON_STREAM Stream,
IN PTCHAR szStr,
IN DWORD len);
INT
ConPuts(
IN PCON_STREAM Stream,
IN LPWSTR szStr);
INT
ConPrintfV(
IN PCON_STREAM Stream,
IN LPWSTR szStr,
IN va_list args); // arg_ptr
INT
__cdecl
ConPrintf(
IN PCON_STREAM Stream,
IN LPWSTR szStr,
...);
INT
ConResPutsEx(
IN PCON_STREAM Stream,
IN HINSTANCE hInstance OPTIONAL,
IN UINT uID);
INT
ConResPuts(
IN PCON_STREAM Stream,
IN UINT uID);
INT
ConResPrintfExV(
IN PCON_STREAM Stream,
IN HINSTANCE hInstance OPTIONAL,
IN UINT uID,
IN va_list args); // arg_ptr
INT
ConResPrintfV(
IN PCON_STREAM Stream,
IN UINT uID,
IN va_list args); // arg_ptr
INT
__cdecl
ConResPrintfEx(
IN PCON_STREAM Stream,
IN HINSTANCE hInstance OPTIONAL,
IN UINT uID,
...);
INT
__cdecl
ConResPrintf(
IN PCON_STREAM Stream,
IN UINT uID,
...);
INT
ConMsgPuts(
IN PCON_STREAM Stream,
IN DWORD dwFlags,
IN LPCVOID lpSource OPTIONAL,
IN DWORD dwMessageId,
IN DWORD dwLanguageId);
INT
ConMsgPrintf2V(
IN PCON_STREAM Stream,
IN DWORD dwFlags,
IN LPCVOID lpSource OPTIONAL,
IN DWORD dwMessageId,
IN DWORD dwLanguageId,
IN va_list args); // arg_ptr
INT
ConMsgPrintfV(
IN PCON_STREAM Stream,
IN DWORD dwFlags,
IN LPCVOID lpSource OPTIONAL,
IN DWORD dwMessageId,
IN DWORD dwLanguageId,
IN va_list args); // arg_ptr
INT
__cdecl
ConMsgPrintf(
IN PCON_STREAM Stream,
IN DWORD dwFlags,
IN LPCVOID lpSource OPTIONAL,
IN DWORD dwMessageId,
IN DWORD dwLanguageId,
...);
VOID
ConClearLine(IN PCON_STREAM Stream);
#endif /* __STREAM_H__ */

234
sdk/lib/conutils/utils.c Normal file
View file

@ -0,0 +1,234 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Console Utilities Library
* FILE: sdk/lib/conutils/utils.c
* PURPOSE: Base set of functions for loading string resources
* and message strings, and handle type identification.
* PROGRAMMERS: - Hermes Belusca-Maito (for the library);
* - All programmers who wrote the different console applications
* from which I took those functions and improved them.
*/
/* FIXME: Temporary HACK before we cleanly support UNICODE functions */
#define UNICODE
#define _UNICODE
#include <windef.h>
#include <winbase.h>
#include <winnls.h>
#include <winuser.h> // MAKEINTRESOURCEW, RT_STRING
#include <wincon.h> // Console APIs (only if kernel32 support included)
#include <strsafe.h>
/* PSEH for SEH Support */
#include <pseh/pseh2.h>
// #include "conutils.h"
#include "utils.h"
/*
* General-purpose utility functions (wrappers around,
* or reimplementations of, Win32 APIs).
*/
#if 0 // The following function may be useful in the future...
// Performs MultiByteToWideChar then WideCharToMultiByte .
// See https://github.com/pcman-bbs/pcman-windows/blob/master/Lite/StrUtils.h#l33
// and http://www.openfoundry.org/svn/pcman/branches/OpenPCMan_2009/Lite/StrUtils.cpp
// for the idea.
int
MultiByteToMultiByte(
// IN WORD wTranslations,
IN DWORD dwFlags,
IN UINT SrcCodePage,
IN LPCSTR lpSrcString,
IN int cbSrcChar,
IN UINT DestCodePage,
OUT LPSTR wDestString OPTIONAL,
IN int cbDestChar
);
#endif
/*
* 'LoadStringW' API ripped from user32.dll to remove
* any dependency of this library from user32.dll
*/
INT
WINAPI
K32LoadStringW(
IN HINSTANCE hInstance OPTIONAL,
IN UINT uID,
OUT LPWSTR lpBuffer,
IN INT nBufferMax)
{
HRSRC hrsrc;
HGLOBAL hmem;
WCHAR *p;
UINT i;
if (!lpBuffer)
return 0;
/* Use LOWORD (incremented by 1) as ResourceID */
/* There are always blocks of 16 strings */
// FindResourceExW(hInstance, RT_STRING, name, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL));
// NOTE: Instead of using LANG_NEUTRAL, one might use LANG_USER_DEFAULT...
hrsrc = FindResourceW(hInstance,
MAKEINTRESOURCEW((LOWORD(uID) >> 4) + 1),
(LPWSTR)RT_STRING);
if (!hrsrc) return 0;
hmem = LoadResource(hInstance, hrsrc);
if (!hmem) return 0;
p = LockResource(hmem);
// FreeResource(hmem);
/* Find the string we're looking for */
uID &= 0x000F; /* Position in the block, same as % 16 */
for (i = 0; i < uID; i++)
p += *p + 1;
/*
* If nBufferMax == 0, then return a read-only pointer
* to the resource itself in lpBuffer it is assumed that
* lpBuffer is actually a (LPWSTR *).
*/
if (nBufferMax == 0)
{
*((LPWSTR*)lpBuffer) = p + 1;
return *p;
}
i = min(nBufferMax - 1, *p);
if (i > 0)
{
memcpy(lpBuffer, p + 1, i * sizeof(WCHAR));
lpBuffer[i] = L'\0';
}
else
{
if (nBufferMax > 1)
{
lpBuffer[0] = L'\0';
return 0;
}
}
return i;
}
/*
* "Safe" version of FormatMessageW, that does not crash if a malformed
* source string is retrieved and then being used for formatting.
* It basically wraps calls to FormatMessageW within SEH.
*/
DWORD
WINAPI
FormatMessageSafeW(
IN DWORD dwFlags,
IN LPCVOID lpSource OPTIONAL,
IN DWORD dwMessageId,
IN DWORD dwLanguageId,
OUT LPWSTR lpBuffer,
IN DWORD nSize,
IN va_list *Arguments OPTIONAL)
{
DWORD dwLength = 0;
_SEH2_TRY
{
/*
* Retrieve the message string. Wrap in SEH
* to protect from invalid string parameters.
*/
_SEH2_TRY
{
dwLength = FormatMessageW(dwFlags,
lpSource,
dwMessageId,
dwLanguageId,
lpBuffer,
nSize,
Arguments);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
dwLength = 0;
/*
* An exception occurred while calling FormatMessage, this is usually
* the sign that a parameter was invalid, either 'lpBuffer' was NULL
* but we did not pass the flag FORMAT_MESSAGE_ALLOCATE_BUFFER, or the
* array pointer 'Arguments' was NULL or did not contain enough elements,
* and we did not pass the flag FORMAT_MESSAGE_IGNORE_INSERTS, and the
* message string expected too many inserts.
* In this last case only, we can call again FormatMessage but ignore
* explicitely the inserts. The string that we will return to the user
* will not be pre-formatted.
*/
if (((dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) || lpBuffer) &&
!(dwFlags & FORMAT_MESSAGE_IGNORE_INSERTS))
{
/* Remove any possible harmful flags and always ignore inserts */
dwFlags &= ~FORMAT_MESSAGE_ARGUMENT_ARRAY;
dwFlags |= FORMAT_MESSAGE_IGNORE_INSERTS;
/* If this call also throws an exception, we are really dead */
dwLength = FormatMessageW(dwFlags,
lpSource,
dwMessageId,
dwLanguageId,
lpBuffer,
nSize,
NULL /* Arguments */);
}
}
_SEH2_END;
}
_SEH2_FINALLY
{
}
_SEH2_END;
return dwLength;
}
BOOL
IsTTYHandle(IN HANDLE hHandle)
{
/*
* More general test than IsConsoleHandle. Consoles, as well as
* serial ports, etc... verify this test, but only consoles verify
* the IsConsoleHandle test: indeed the latter checks whether
* the handle is really handled by the console subsystem.
*/
return ((GetFileType(hHandle) & ~FILE_TYPE_REMOTE) == FILE_TYPE_CHAR);
}
BOOL
IsConsoleHandle(IN HANDLE hHandle)
{
DWORD dwMode;
/* Check whether the handle may be that of a console... */
if ((GetFileType(hHandle) & ~FILE_TYPE_REMOTE) != FILE_TYPE_CHAR)
return FALSE;
/*
* It may be. Perform another test. The idea comes from the
* MSDN description of the WriteConsole API:
*
* "WriteConsole fails if it is used with a standard handle
* that is redirected to a file. If an application processes
* multilingual output that can be redirected, determine whether
* the output handle is a console handle (one method is to call
* the GetConsoleMode function and check whether it succeeds).
* If the handle is a console handle, call WriteConsole. If the
* handle is not a console handle, the output is redirected and
* you should call WriteFile to perform the I/O."
*/
return GetConsoleMode(hHandle, &dwMode);
}

53
sdk/lib/conutils/utils.h Normal file
View file

@ -0,0 +1,53 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Console Utilities Library
* FILE: sdk/lib/conutils/utils.h
* PURPOSE: Base set of functions for loading string resources
* and message strings, and handle type identification.
* PROGRAMMERS: - Hermes Belusca-Maito (for the library);
* - All programmers who wrote the different console applications
* from which I took those functions and improved them.
*/
#ifndef __UTILS_H__
#define __UTILS_H__
#ifndef _UNICODE
#error The ConUtils library at the moment only supports compilation with _UNICODE defined!
#endif
/*
* General-purpose utility functions (wrappers around,
* or reimplementations of, Win32 APIs).
*/
INT
WINAPI
K32LoadStringW(
IN HINSTANCE hInstance OPTIONAL,
IN UINT uID,
OUT LPWSTR lpBuffer,
IN INT nBufferMax);
DWORD
WINAPI
FormatMessageSafeW(
IN DWORD dwFlags,
IN LPCVOID lpSource OPTIONAL,
IN DWORD dwMessageId,
IN DWORD dwLanguageId,
OUT LPWSTR lpBuffer,
IN DWORD nSize,
IN va_list *Arguments OPTIONAL);
BOOL
IsTTYHandle(IN HANDLE hHandle);
BOOL
IsConsoleHandle(IN HANDLE hHandle);
// #include <wincon.h>
#endif /* __UTILS_H__ */