[CONUTILS] Split stream.c into input and output stream modules.
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Mon, 16 Oct 2017 21:58:23 +0000 (23:58 +0200)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Wed, 31 Jan 2018 01:10:41 +0000 (02:10 +0100)
As code grows, this will allow for better maintenance of the console
stream code. In particular the input stream module will contain special
code for handling TTYs, and this is something not all console programs
will need. Having this code in a separate module will allow for the linker
to possibly remove this code when it is unused.

16 files changed:
sdk/lib/conutils/CMakeLists.txt
sdk/lib/conutils/README.txt
sdk/lib/conutils/conutils.h
sdk/lib/conutils/instream.c [new file with mode: 0644]
sdk/lib/conutils/instream.h [new file with mode: 0644]
sdk/lib/conutils/outstream.c [new file with mode: 0644]
sdk/lib/conutils/outstream.h [new file with mode: 0644]
sdk/lib/conutils/pager.c
sdk/lib/conutils/pager.h
sdk/lib/conutils/screen.c
sdk/lib/conutils/screen.h
sdk/lib/conutils/stream.c
sdk/lib/conutils/stream.h
sdk/lib/conutils/stream_private.h [new file with mode: 0644]
sdk/lib/conutils/utils.c
sdk/lib/conutils/utils.h

index 8b978d8..90d8dfb 100644 (file)
@@ -1,5 +1,7 @@
 
 list(APPEND SOURCE
+    # instream.c
+    outstream.c
     pager.c
     screen.c
     stream.c
index 680512c..4a4a7a7 100644 (file)
@@ -1,7 +1,9 @@
-The ReactOS Console Utilities Library v0.1
+The ReactOS Console Utilities Library v0.2
 ==========================================
 
-COPYRIGHT:  Under GPLv2, see COPYING in the top level directory.
+LICENSE:    GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+COPYRIGHT:  Copyright 2017-2018 ReactOS Team
+            Copyright 2017-2018 Hermes Belusca-Maito
 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.
@@ -21,23 +23,22 @@ together with printf-like functionality.
 CONTENTS
 ~-~-~-~-
 
-0. 'conutils_base' (utils.c and utils.h): Base set of functions for loading
+-- Main ConUtils Library --
+
+0. "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):
+1. "STREAM" (stream.c and stream.h, instream.c and instream.h, outstream.c
+   and outstream.h): Console Stream API (CON_STREAM):
    Stream initialization, basic ConStreamRead/Write. Stream utility functions:
-   ConPuts/Printf, ConResPuts/Printf, ConMsgPuts/Printf.
-   Depends on 'conutils_base'.
+   ConPuts/Printf, ConResPuts/Printf, ConMsgPuts/Printf. Depends on "BASE".
 
-2. 'conutils_screen' (screen.c and screen.h): Console Screen API (CON_SCREEN):
+2. "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'.
+   Depends on "STREAM", and indirectly on "BASE".
 
-3. 'conutils_pager' (pager.c and pager.h): Console Pager API (CON_PAGER):
+3. "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!
+   Depends on "SCREEN", and indirectly on "STREAM" and "BASE".
index 2857bd4..93d79e8 100644 (file)
@@ -1,25 +1,29 @@
 /*
- * 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.
+ * PROJECT:     ReactOS Console Utilities Library
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Provides simple abstraction wrappers around CRT streams or
+ *              Win32 console API I/O functions, to deal with i18n + Unicode
+ *              related problems.
+ * COPYRIGHT:   Copyright 2017-2018 ReactOS Team
+ *              Copyright 2017-2018 Hermes Belusca-Maito
  */
 
 #ifndef __CONUTILS_H__
 #define __CONUTILS_H__
 
+#pragma once
+
 #ifndef _UNICODE
 #error The ConUtils library only supports compilation with _UNICODE defined, at the moment!
 #endif
 
 #include "utils.h"
 #include "stream.h"
+// #include "instream.h"
+#include "outstream.h"
 #include "screen.h"
 #include "pager.h"
 
 #endif  /* __CONUTILS_H__ */
+
+/* EOF */
diff --git a/sdk/lib/conutils/instream.c b/sdk/lib/conutils/instream.c
new file mode 100644 (file)
index 0000000..a9fa105
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * PROJECT:     ReactOS Console Utilities Library
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Provides basic abstraction wrappers around CRT streams or
+ *              Win32 console API I/O functions, to deal with i18n + Unicode
+ *              related problems.
+ * COPYRIGHT:   Copyright 2017-2018 ReactOS Team
+ *              Copyright 2017-2018 Hermes Belusca-Maito
+ */
+
+/*
+ * 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
+
+/* FIXME: Temporary HACK before we cleanly support UNICODE functions */
+#define UNICODE
+#define _UNICODE
+
+#ifdef USE_CRT
+#include <fcntl.h>
+#include <io.h>
+#endif /* USE_CRT */
+
+#include <stdlib.h> // limits.h // For MB_LEN_MAX
+
+#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 "stream.h"
+#include "stream_private.h"
+
+
+/*
+ * Console I/O utility API -- Input
+ */
+
+/* EOF */
diff --git a/sdk/lib/conutils/instream.h b/sdk/lib/conutils/instream.h
new file mode 100644 (file)
index 0000000..d16a9c3
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * PROJECT:     ReactOS Console Utilities Library
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Provides basic abstraction wrappers around CRT streams or
+ *              Win32 console API I/O functions, to deal with i18n + Unicode
+ *              related problems.
+ * COPYRIGHT:   Copyright 2017-2018 ReactOS Team
+ *              Copyright 2017-2018 Hermes Belusca-Maito
+ */
+
+#ifndef __INSTREAM_H__
+#define __INSTREAM_H__
+
+#pragma once
+
+/*
+ * 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
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Shadow type, implementation-specific
+typedef struct _CON_STREAM CON_STREAM, *PCON_STREAM;
+
+/*
+ * Console I/O utility API -- Input
+ */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* __INSTREAM_H__ */
+
+/* EOF */
diff --git a/sdk/lib/conutils/outstream.c b/sdk/lib/conutils/outstream.c
new file mode 100644 (file)
index 0000000..63adaf3
--- /dev/null
@@ -0,0 +1,762 @@
+/*
+ * PROJECT:     ReactOS Console Utilities Library
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Provides basic abstraction wrappers around CRT streams or
+ *              Win32 console API I/O functions, to deal with i18n + Unicode
+ *              related problems.
+ * COPYRIGHT:   Copyright 2017-2018 ReactOS Team
+ *              Copyright 2017-2018 Hermes Belusca-Maito
+ */
+
+/*
+ * 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
+
+/* FIXME: Temporary HACK before we cleanly support UNICODE functions */
+#define UNICODE
+#define _UNICODE
+
+#ifdef USE_CRT
+#include <fcntl.h>
+#include <io.h>
+#endif /* USE_CRT */
+
+#include <stdlib.h> // limits.h // For MB_LEN_MAX
+
+#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 "stream.h"
+#include "stream_private.h"
+
+
+// #define RC_STRING_MAX_SIZE  4096
+#define CON_RC_STRING_MAX_SIZE  4096
+// #define MAX_BUFFER_SIZE     4096    // Some programs (wlanconf, shutdown) set it to 5024
+// #define OUTPUT_BUFFER_SIZE  4096    // Name given in cmd/console.c
+// MAX_STRING_SIZE  // Name given in diskpart
+
+// #define MAX_MESSAGE_SIZE    512     // See shutdown...
+
+
+/*
+ * Console I/O utility API -- Output
+ */
+
+// NOTE: Should be called with the stream locked.
+INT
+__stdcall
+ConWrite(
+    IN PCON_STREAM Stream,
+    IN PTCHAR szStr,
+    IN DWORD len)
+{
+#ifndef USE_CRT
+    DWORD TotalLen = len, dwNumBytes = 0;
+    PVOID p;
+
+    // CHAR strOem[CON_RC_STRING_MAX_SIZE]; // Some static buffer...
+
+    /* If we do not write anything, just return */
+    if (!szStr || len == 0)
+        return 0;
+
+    /* Check whether we are writing to a console */
+    // if (IsConsoleHandle(Stream->hHandle))
+    if (Stream->IsConsole)
+    {
+        // TODO: Check if (ConStream->Mode == WideText or UTF16Text) ??
+
+        /*
+         * This code is inspired from _cputws, in particular from the fact that,
+         * according to MSDN: https://msdn.microsoft.com/en-us/library/ms687401(v=vs.85).aspx
+         * the buffer size must be less than 64 KB.
+         *
+         * A similar code can be used for implementing _cputs too.
+         */
+
+        DWORD cchWrite;
+        TotalLen = len, dwNumBytes = 0;
+
+        while (len > 0)
+        {
+            cchWrite = min(len, 65535 / sizeof(WCHAR));
+
+            // FIXME: Check return value!
+            WriteConsole(Stream->hHandle, szStr, cchWrite, &dwNumBytes, NULL);
+
+            szStr += cchWrite;
+            len -= cchWrite;
+        }
+
+        return (INT)TotalLen; // FIXME: Really return the number of chars written!
+    }
+
+    /*
+     * We are redirected and writing to a file or pipe instead of the console.
+     * Convert the string from TCHARs to the desired output format, if the two differ.
+     *
+     * Implementation NOTE:
+     *   MultiByteToWideChar (resp. WideCharToMultiByte) are equivalent to
+     *   OemToCharBuffW (resp. CharToOemBuffW), but the latters uselessly
+     *   depend on user32.dll, while MultiByteToWideChar and WideCharToMultiByte
+     *   only need kernel32.dll.
+     */
+    if ((Stream->Mode == WideText) || (Stream->Mode == UTF16Text))
+    {
+#ifndef _UNICODE // UNICODE means that TCHAR == WCHAR == UTF-16
+        /* Convert from the current process/thread's codepage to UTF-16 */
+        WCHAR *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
+        if (!buffer)
+        {
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            return 0;
+        }
+        len = (DWORD)MultiByteToWideChar(CP_THREAD_ACP, // CP_ACP, CP_OEMCP
+                                         0, szStr, (INT)len, buffer, (INT)len);
+        szStr = (PVOID)buffer;
+#else
+        /*
+         * Do not perform any conversion since we are already in UTF-16,
+         * that is the same encoding as the stream.
+         */
+#endif
+
+        /*
+         * Find any newline character in the buffer,
+         * write the part BEFORE the newline, then write
+         * a carriage-return + newline, and then write
+         * the remaining part of the buffer.
+         *
+         * This fixes output in files and serial console.
+         */
+        while (len > 0)
+        {
+            /* Loop until we find a \r or \n character */
+            // FIXME: What about the pair \r\n ?
+            p = szStr;
+            while (len > 0 && *(PWCHAR)p != L'\r' && *(PWCHAR)p != L'\n')
+            {
+                /* Advance one character */
+                p = (PVOID)((PWCHAR)p + 1);
+                len--;
+            }
+
+            /* Write everything up to \r or \n */
+            dwNumBytes = ((PWCHAR)p - (PWCHAR)szStr) * sizeof(WCHAR);
+            WriteFile(Stream->hHandle, szStr, dwNumBytes, &dwNumBytes, NULL);
+
+            /* If we hit \r or \n ... */
+            if (len > 0 && (*(PWCHAR)p == L'\r' || *(PWCHAR)p == L'\n'))
+            {
+                /* ... send a carriage-return + newline sequence and skip \r or \n */
+                WriteFile(Stream->hHandle, L"\r\n", 2 * sizeof(WCHAR), &dwNumBytes, NULL);
+                szStr = (PVOID)((PWCHAR)p + 1);
+                len--;
+            }
+        }
+
+#ifndef _UNICODE
+        HeapFree(GetProcessHeap(), 0, buffer);
+#endif
+    }
+    else if ((Stream->Mode == UTF8Text) || (Stream->Mode == AnsiText))
+    {
+        CHAR *buffer;
+
+        /*
+         * Resolve the codepage cache if it was not assigned yet
+         * (only if the stream is in ANSI mode; in UTF8 mode the
+         * codepage was already set to CP_UTF8).
+         */
+        if (/*(Stream->Mode == AnsiText) &&*/ (Stream->CodePage == INVALID_CP))
+            Stream->CodePage = GetConsoleOutputCP(); // CP_ACP, CP_OEMCP
+
+#ifdef _UNICODE // UNICODE means that TCHAR == WCHAR == UTF-16
+        /* Convert from UTF-16 to either UTF-8 or ANSI, using stream codepage */
+        // NOTE: MB_LEN_MAX defined either in limits.h or in stdlib.h .
+        buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * MB_LEN_MAX);
+        if (!buffer)
+        {
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            return 0;
+        }
+        len = WideCharToMultiByte(Stream->CodePage, 0,
+                                  szStr, len, buffer, len * MB_LEN_MAX,
+                                  NULL, NULL);
+        szStr = (PVOID)buffer;
+#else
+        /*
+         * Convert from the current process/thread's codepage to either
+         * UTF-8 or ANSI, using stream codepage.
+         * We need to perform a double conversion, by going through UTF-16.
+         */
+        // TODO!
+        #error "Need to implement double conversion!"
+#endif
+
+        /*
+         * Find any newline character in the buffer,
+         * write the part BEFORE the newline, then write
+         * a carriage-return + newline, and then write
+         * the remaining part of the buffer.
+         *
+         * This fixes output in files and serial console.
+         */
+        while (len > 0)
+        {
+            /* Loop until we find a \r or \n character */
+            // FIXME: What about the pair \r\n ?
+            p = szStr;
+            while (len > 0 && *(PCHAR)p != '\r' && *(PCHAR)p != '\n')
+            {
+                /* Advance one character */
+                p = (PVOID)((PCHAR)p + 1);
+                len--;
+            }
+
+            /* Write everything up to \r or \n */
+            dwNumBytes = ((PCHAR)p - (PCHAR)szStr) * sizeof(CHAR);
+            WriteFile(Stream->hHandle, szStr, dwNumBytes, &dwNumBytes, NULL);
+
+            /* If we hit \r or \n ... */
+            if (len > 0 && (*(PCHAR)p == '\r' || *(PCHAR)p == '\n'))
+            {
+                /* ... send a carriage-return + newline sequence and skip \r or \n */
+                WriteFile(Stream->hHandle, "\r\n", 2, &dwNumBytes, NULL);
+                szStr = (PVOID)((PCHAR)p + 1);
+                len--;
+            }
+        }
+
+#ifdef _UNICODE
+        HeapFree(GetProcessHeap(), 0, buffer);
+#else
+        // TODO!
+#endif
+    }
+    else // if (Stream->Mode == Binary)
+    {
+        /* Directly output the string */
+        WriteFile(Stream->hHandle, szStr, len, &dwNumBytes, NULL);
+    }
+
+    // FIXME!
+    return (INT)TotalLen;
+
+#else /* defined(USE_CRT) */
+
+    DWORD total = len;
+    DWORD written = 0;
+
+    /* If we do not write anything, just return */
+    if (!szStr || len == 0)
+        return 0;
+
+#if 1
+    /*
+     * There is no "counted" printf-to-stream or puts-like function, therefore
+     * we use this trick to output the counted string to the stream.
+     */
+    while (1)
+    {
+        written = fwprintf(Stream->fStream, L"%.*s", total, szStr);
+        if (written < total)
+        {
+            /*
+             * Some embedded NULL or special character
+             * was encountered, print it apart.
+             */
+            if (written == 0)
+            {
+                fputwc(*szStr, Stream->fStream);
+                written++;
+            }
+
+            szStr += written;
+            total -= written;
+        }
+        else
+        {
+            break;
+        }
+    }
+    return (INT)len;
+#else
+    /* ANSI text or Binary output only */
+    _setmode(_fileno(Stream->fStream), _O_TEXT); // _O_BINARY
+    return fwrite(szStr, sizeof(*szStr), len, Stream->fStream);
+#endif
+
+#endif /* defined(USE_CRT) */
+}
+
+
+#define CON_STREAM_WRITE_CALL(Stream, Str, Len) \
+    (Stream)->WriteFunc((Stream), (Str), (Len));
+
+/* Lock the stream only in non-USE_CRT mode (otherwise use the CRT stream lock) */
+#ifndef USE_CRT
+
+#define CON_STREAM_WRITE2(Stream, Str, Len, RetLen) \
+do { \
+    EnterCriticalSection(&(Stream)->Lock); \
+    (RetLen) = CON_STREAM_WRITE_CALL((Stream), (Str), (Len)); \
+    LeaveCriticalSection(&(Stream)->Lock); \
+} while(0)
+
+#define CON_STREAM_WRITE(Stream, Str, Len) \
+do { \
+    EnterCriticalSection(&(Stream)->Lock); \
+    CON_STREAM_WRITE_CALL((Stream), (Str), (Len)); \
+    LeaveCriticalSection(&(Stream)->Lock); \
+} while(0)
+
+#else
+
+#define CON_STREAM_WRITE2(Stream, Str, Len, RetLen) \
+do { \
+    (RetLen) = CON_STREAM_WRITE_CALL((Stream), (Str), (Len)); \
+} while(0)
+
+#define CON_STREAM_WRITE(Stream, Str, Len) \
+do { \
+    CON_STREAM_WRITE_CALL((Stream), (Str), (Len)); \
+} while(0)
+
+#endif
+
+
+INT
+ConStreamWrite(
+    IN PCON_STREAM Stream,
+    IN PTCHAR szStr,
+    IN DWORD len)
+{
+    INT Len;
+    CON_STREAM_WRITE2(Stream, szStr, len, Len);
+    return Len;
+}
+
+INT
+ConPuts(
+    IN PCON_STREAM Stream,
+    IN LPWSTR szStr)
+{
+    INT Len;
+
+    Len = wcslen(szStr);
+    CON_STREAM_WRITE2(Stream, szStr, Len, Len);
+
+    /* Fixup returned length in case of errors */
+    if (Len < 0)
+        Len = 0;
+
+    return Len;
+}
+
+INT
+ConPrintfV(
+    IN PCON_STREAM Stream,
+    IN LPWSTR  szStr,
+    IN va_list args) // arg_ptr
+{
+    INT Len;
+    WCHAR bufSrc[CON_RC_STRING_MAX_SIZE];
+
+    // Len = vfwprintf(Stream->fStream, szStr, args); // vfprintf for direct ANSI
+
+    /*
+     * Reuse szStr as the pointer to end-of-string, to compute
+     * the string length instead of calling wcslen().
+     */
+    // StringCchVPrintfW(bufSrc, ARRAYSIZE(bufSrc), szStr, args);
+    // Len = wcslen(bufSrc);
+    StringCchVPrintfExW(bufSrc, ARRAYSIZE(bufSrc), &szStr, NULL, 0, szStr, args);
+    Len = szStr - bufSrc;
+
+    CON_STREAM_WRITE2(Stream, bufSrc, Len, Len);
+
+    /* Fixup returned length in case of errors */
+    if (Len < 0)
+        Len = 0;
+
+    return Len;
+}
+
+INT
+__cdecl
+ConPrintf(
+    IN PCON_STREAM Stream,
+    IN LPWSTR szStr,
+    ...)
+{
+    INT Len;
+    va_list args;
+
+    // Len = vfwprintf(Stream->fStream, szMsgBuf, args); // vfprintf for direct ANSI
+
+    // StringCchPrintfW
+    va_start(args, szStr);
+    Len = ConPrintfV(Stream, szStr, args);
+    va_end(args);
+
+    return Len;
+}
+
+INT
+ConResPutsEx(
+    IN PCON_STREAM Stream,
+    IN HINSTANCE hInstance OPTIONAL,
+    IN UINT uID)
+{
+    INT Len;
+    PWCHAR szStr = NULL;
+
+    Len = K32LoadStringW(hInstance, uID, (PWSTR)&szStr, 0);
+    if (szStr && Len)
+        // Len = ConPuts(Stream, szStr);
+        CON_STREAM_WRITE2(Stream, szStr, Len, Len);
+
+    /* Fixup returned length in case of errors */
+    if (Len < 0)
+        Len = 0;
+
+    return Len;
+}
+
+INT
+ConResPuts(
+    IN PCON_STREAM Stream,
+    IN UINT uID)
+{
+    return ConResPutsEx(Stream, NULL /*GetModuleHandleW(NULL)*/, uID);
+}
+
+INT
+ConResPrintfExV(
+    IN PCON_STREAM Stream,
+    IN HINSTANCE hInstance OPTIONAL,
+    IN UINT    uID,
+    IN va_list args) // arg_ptr
+{
+    INT Len;
+    WCHAR bufSrc[CON_RC_STRING_MAX_SIZE];
+
+    // NOTE: We may use the special behaviour where nBufMaxSize == 0
+    Len = K32LoadStringW(hInstance, uID, bufSrc, ARRAYSIZE(bufSrc));
+    if (Len)
+        Len = ConPrintfV(Stream, bufSrc, args);
+
+    return Len;
+}
+
+INT
+ConResPrintfV(
+    IN PCON_STREAM Stream,
+    IN UINT    uID,
+    IN va_list args) // arg_ptr
+{
+    return ConResPrintfExV(Stream, NULL /*GetModuleHandleW(NULL)*/, uID, args);
+}
+
+INT
+__cdecl
+ConResPrintfEx(
+    IN PCON_STREAM Stream,
+    IN HINSTANCE hInstance OPTIONAL,
+    IN UINT uID,
+    ...)
+{
+    INT Len;
+    va_list args;
+
+    va_start(args, uID);
+    Len = ConResPrintfExV(Stream, hInstance, uID, args);
+    va_end(args);
+
+    return Len;
+}
+
+INT
+__cdecl
+ConResPrintf(
+    IN PCON_STREAM Stream,
+    IN UINT uID,
+    ...)
+{
+    INT Len;
+    va_list args;
+
+    va_start(args, uID);
+    Len = ConResPrintfV(Stream, uID, args);
+    va_end(args);
+
+    return Len;
+}
+
+INT
+ConMsgPuts(
+    IN PCON_STREAM Stream,
+    IN DWORD   dwFlags,
+    IN LPCVOID lpSource OPTIONAL,
+    IN DWORD   dwMessageId,
+    IN DWORD   dwLanguageId)
+{
+    INT Len;
+    DWORD dwLength  = 0;
+    LPWSTR lpMsgBuf = NULL;
+
+    /*
+     * Sanitize dwFlags. This version always ignore explicitely the inserts
+     * as we emulate the behaviour of the *puts function.
+     */
+    dwFlags |= FORMAT_MESSAGE_ALLOCATE_BUFFER; // Always allocate an internal buffer.
+    dwFlags |= FORMAT_MESSAGE_IGNORE_INSERTS;  // Ignore inserts for FormatMessage.
+    dwFlags &= ~FORMAT_MESSAGE_ARGUMENT_ARRAY;
+
+    dwFlags |= FORMAT_MESSAGE_MAX_WIDTH_MASK;
+
+    /*
+     * Retrieve the message string without appending extra newlines.
+     * Wrap in SEH to protect from invalid string parameters.
+     */
+    _SEH2_TRY
+    {
+        dwLength = FormatMessageW(dwFlags,
+                                  lpSource,
+                                  dwMessageId,
+                                  dwLanguageId,
+                                  (LPWSTR)&lpMsgBuf,
+                                  0, NULL);
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+    }
+    _SEH2_END;
+
+    Len = (INT)dwLength;
+
+    if (!lpMsgBuf)
+    {
+        // ASSERT(dwLength == 0);
+    }
+    else
+    {
+        // ASSERT(dwLength != 0);
+
+        /* lpMsgBuf is NULL-terminated by FormatMessage */
+        // Len = ConPuts(Stream, lpMsgBuf);
+        CON_STREAM_WRITE2(Stream, lpMsgBuf, dwLength, Len);
+
+        /* Fixup returned length in case of errors */
+        if (Len < 0)
+            Len = 0;
+
+        /* Free the buffer allocated by FormatMessage */
+        LocalFree(lpMsgBuf);
+    }
+
+    return Len;
+}
+
+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 Len;
+    DWORD dwLength  = 0;
+    LPWSTR lpMsgBuf = NULL;
+
+    /*
+     * Sanitize dwFlags. This version always ignore explicitely the inserts.
+     * The string that we will return to the user will not be pre-formatted.
+     */
+    dwFlags |= FORMAT_MESSAGE_ALLOCATE_BUFFER; // Always allocate an internal buffer.
+    dwFlags |= FORMAT_MESSAGE_IGNORE_INSERTS;  // Ignore inserts for FormatMessage.
+    dwFlags &= ~FORMAT_MESSAGE_ARGUMENT_ARRAY;
+
+    dwFlags |= FORMAT_MESSAGE_MAX_WIDTH_MASK;
+
+    /*
+     * Retrieve the message string without appending extra newlines.
+     * Wrap in SEH to protect from invalid string parameters.
+     */
+    _SEH2_TRY
+    {
+        dwLength = FormatMessageW(dwFlags,
+                                  lpSource,
+                                  dwMessageId,
+                                  dwLanguageId,
+                                  (LPWSTR)&lpMsgBuf,
+                                  0, NULL);
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+    }
+    _SEH2_END;
+
+    Len = (INT)dwLength;
+
+    if (!lpMsgBuf)
+    {
+        // ASSERT(dwLength == 0);
+    }
+    else
+    {
+        // ASSERT(dwLength != 0);
+
+        /* lpMsgBuf is NULL-terminated by FormatMessage */
+        Len = ConPrintfV(Stream, lpMsgBuf, args);
+        // CON_STREAM_WRITE2(Stream, lpMsgBuf, dwLength, Len);
+
+        /* Fixup returned length in case of errors */
+        if (Len < 0)
+            Len = 0;
+
+        /* Free the buffer allocated by FormatMessage */
+        LocalFree(lpMsgBuf);
+    }
+
+    return Len;
+}
+
+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 Len;
+    DWORD dwLength  = 0;
+    LPWSTR lpMsgBuf = NULL;
+
+    /* Sanitize dwFlags */
+    dwFlags |= FORMAT_MESSAGE_ALLOCATE_BUFFER; // Always allocate an internal buffer.
+//  dwFlags &= ~FORMAT_MESSAGE_IGNORE_INSERTS; // We always use arguments.
+    dwFlags &= ~FORMAT_MESSAGE_ARGUMENT_ARRAY; // We always use arguments of type 'va_list'.
+
+    //
+    // NOTE: Technique taken from eventvwr.c!GetMessageStringFromDll()
+    //
+
+    dwFlags |= FORMAT_MESSAGE_MAX_WIDTH_MASK;
+
+    /*
+     * Retrieve the message string without appending extra newlines.
+     * Use the "safe" FormatMessage version (SEH-protected) to protect
+     * from invalid string parameters.
+     */
+    dwLength = FormatMessageSafeW(dwFlags,
+                                  lpSource,
+                                  dwMessageId,
+                                  dwLanguageId,
+                                  (LPWSTR)&lpMsgBuf,
+                                  0, &args);
+
+    Len = (INT)dwLength;
+
+    if (!lpMsgBuf)
+    {
+        // ASSERT(dwLength == 0);
+    }
+    else
+    {
+        // ASSERT(dwLength != 0);
+
+        // Len = ConPrintfV(Stream, lpMsgBuf, args);
+        CON_STREAM_WRITE2(Stream, lpMsgBuf, dwLength, Len);
+
+        /* Fixup returned length in case of errors */
+        if (Len < 0)
+            Len = 0;
+
+        /* Free the buffer allocated by FormatMessage */
+        LocalFree(lpMsgBuf);
+    }
+
+    return Len;
+}
+
+INT
+__cdecl
+ConMsgPrintf(
+    IN PCON_STREAM Stream,
+    IN DWORD   dwFlags,
+    IN LPCVOID lpSource OPTIONAL,
+    IN DWORD   dwMessageId,
+    IN DWORD   dwLanguageId,
+    ...)
+{
+    INT Len;
+    va_list args;
+
+    va_start(args, dwLanguageId);
+    // ConMsgPrintf2V
+    Len = ConMsgPrintfV(Stream,
+                        dwFlags,
+                        lpSource,
+                        dwMessageId,
+                        dwLanguageId,
+                        args);
+    va_end(args);
+
+    return Len;
+}
+
+
+
+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
+}
+
+/* EOF */
diff --git a/sdk/lib/conutils/outstream.h b/sdk/lib/conutils/outstream.h
new file mode 100644 (file)
index 0000000..a4099e2
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * PROJECT:     ReactOS Console Utilities Library
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Provides basic abstraction wrappers around CRT streams or
+ *              Win32 console API I/O functions, to deal with i18n + Unicode
+ *              related problems.
+ * COPYRIGHT:   Copyright 2017-2018 ReactOS Team
+ *              Copyright 2017-2018 Hermes Belusca-Maito
+ */
+
+#ifndef __OUTSTREAM_H__
+#define __OUTSTREAM_H__
+
+#pragma once
+
+/*
+ * 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
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// 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);
+
+
+/*
+ * Console I/O utility API -- 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);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* __OUTSTREAM_H__ */
+
+/* EOF */
index cc2c2c4..ac6bd3f 100644 (file)
@@ -1,19 +1,15 @@
 /*
- * 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.
+ * PROJECT:     ReactOS Console Utilities Library
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Console/terminal paging functionality.
+ * COPYRIGHT:   Copyright 2017-2018 ReactOS Team
+ *              Copyright 2017-2018 Hermes Belusca-Maito
  */
 
 /* 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>
@@ -158,3 +154,5 @@ ConResPaging(
     return ConResPagingEx(Pager, PagePrompt, StartPaging,
                           NULL /*GetModuleHandleW(NULL)*/, uID);
 }
+
+/* EOF */
index 6c62ab9..486b520 100644 (file)
@@ -1,16 +1,16 @@
 /*
- * 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.
+ * PROJECT:     ReactOS Console Utilities Library
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Console/terminal paging functionality.
+ * COPYRIGHT:   Copyright 2017-2018 ReactOS Team
+ *              Copyright 2017-2018 Hermes Belusca-Maito
  */
 
 #ifndef __PAGER_H__
 #define __PAGER_H__
 
+#pragma once
+
 #ifndef _UNICODE
 #error The ConUtils library at the moment only supports compilation with _UNICODE defined!
 #endif
@@ -42,6 +42,7 @@ do { \
     (pPager)->LineCount = 0;        \
 } while (0)
 
+
                                       // Pager,         Done,     Total
 typedef BOOL (__stdcall *PAGE_PROMPT)(IN PCON_PAGER, IN DWORD, IN DWORD);
 
@@ -78,4 +79,7 @@ ConResPaging(
 #ifdef __cplusplus
 }
 #endif
+
 #endif  /* __PAGER_H__ */
+
+/* EOF */
index b6bc868..04f0b6e 100644 (file)
@@ -1,19 +1,15 @@
 /*
- * 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.
+ * PROJECT:     ReactOS Console Utilities Library
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Console/terminal screen management.
+ * COPYRIGHT:   Copyright 2017-2018 ReactOS Team
+ *              Copyright 2017-2018 Hermes Belusca-Maito
  */
 
 /* 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>
@@ -173,3 +169,5 @@ ConClearScreen(IN PCON_SCREEN Screen)
         CON_STREAM_WRITE(Screen->Stream, &ch, 1);
     }
 }
+
+/* EOF */
index bc2cce9..2ab11a7 100644 (file)
@@ -1,16 +1,16 @@
 /*
- * 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.
+ * PROJECT:     ReactOS Console Utilities Library
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Console/terminal screen management.
+ * COPYRIGHT:   Copyright 2017-2018 ReactOS Team
+ *              Copyright 2017-2018 Hermes Belusca-Maito
  */
 
 #ifndef __SCREEN_H__
 #define __SCREEN_H__
 
+#pragma once
+
 #ifndef _UNICODE
 #error The ConUtils library at the moment only supports compilation with _UNICODE defined!
 #endif
@@ -60,4 +60,7 @@ ConClearScreen(IN PCON_SCREEN Screen);
 #ifdef __cplusplus
 }
 #endif
+
 #endif  /* __SCREEN_H__ */
+
+/* EOF */
index f31d397..5b843c1 100644 (file)
@@ -1,13 +1,11 @@
 /*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS Console Utilities Library
- * FILE:            sdk/lib/conutils/stream.c
- * 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.
+ * PROJECT:     ReactOS Console Utilities Library
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Provides basic abstraction wrappers around CRT streams or
+ *              Win32 console API I/O functions, to deal with i18n + Unicode
+ *              related problems.
+ * COPYRIGHT:   Copyright 2017-2018 ReactOS Team
+ *              Copyright 2017-2018 Hermes Belusca-Maito
  */
 
 /*
 #include <io.h>
 #endif /* USE_CRT */
 
-#include <stdlib.h> // limits.h // For MB_LEN_MAX
-
 #include <windef.h>
 #include <winbase.h>
 #include <winnls.h>
-#include <winuser.h> // MAKEINTRESOURCEW, RT_STRING
+// #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 "stream.h"
-
-
-// #define RC_STRING_MAX_SIZE  4096
-#define CON_RC_STRING_MAX_SIZE  4096
-// #define MAX_BUFFER_SIZE     4096    // Some programs (wlanconf, shutdown) set it to 5024
-// #define OUTPUT_BUFFER_SIZE  4096    // Name given in cmd/console.c
-// MAX_STRING_SIZE  // Name given in diskpart
-
-// #define MAX_MESSAGE_SIZE    512     // See shutdown...
+#include "stream_private.h"
 
 
 /*
  * Console I/O streams
  */
 
-typedef struct _CON_STREAM
-{
-    CON_WRITE_FUNC WriteFunc;
-
-#ifdef USE_CRT
-    FILE* fStream;
-#else
-    BOOL IsInitialized;
-    CRITICAL_SECTION Lock;
-
-    HANDLE hHandle;
-
-    /*
-     * TRUE if 'hHandle' refers to a console, in which case I/O UTF-16
-     * is directly used. If 'hHandle' refers to a file or a pipe, the
-     * 'Mode' flag is used.
-     */
-    BOOL IsConsole;
-
-    /*
-     * The 'Mode' flag is used to know the translation mode
-     * when 'hHandle' refers to a file or a pipe.
-     */
-    CON_STREAM_MODE Mode;
-    UINT CodePage;  // Used to convert UTF-16 text to some ANSI codepage.
-#endif /* defined(USE_CRT) */
-} CON_STREAM, *PCON_STREAM;
-
 /*
  * Standard console streams, initialized by
  * calls to ConStreamInit/ConInitStdStreams.
@@ -339,713 +296,4 @@ ConStreamSetOSHandle(
 #endif
 }
 
-
-/*
- * Console I/O utility API
- * (for the moment, only Output)
- */
-
-// NOTE: Should be called with the stream locked.
-INT
-__stdcall
-ConWrite(
-    IN PCON_STREAM Stream,
-    IN PTCHAR szStr,
-    IN DWORD len)
-{
-#ifndef USE_CRT
-    DWORD TotalLen = len, dwNumBytes = 0;
-    PVOID p;
-
-    // CHAR strOem[CON_RC_STRING_MAX_SIZE]; // Some static buffer...
-
-    /* If we do not write anything, just return */
-    if (!szStr || len == 0)
-        return 0;
-
-    /* Check whether we are writing to a console */
-    // if (IsConsoleHandle(Stream->hHandle))
-    if (Stream->IsConsole)
-    {
-        // TODO: Check if (ConStream->Mode == WideText or UTF16Text) ??
-
-        /*
-         * This code is inspired from _cputws, in particular from the fact that,
-         * according to MSDN: https://msdn.microsoft.com/en-us/library/ms687401(v=vs.85).aspx
-         * the buffer size must be less than 64 KB.
-         *
-         * A similar code can be used for implementing _cputs too.
-         */
-
-        DWORD cchWrite;
-        TotalLen = len, dwNumBytes = 0;
-
-        while (len > 0)
-        {
-            cchWrite = min(len, 65535 / sizeof(WCHAR));
-
-            // FIXME: Check return value!
-            WriteConsole(Stream->hHandle, szStr, cchWrite, &dwNumBytes, NULL);
-
-            szStr += cchWrite;
-            len -= cchWrite;
-        }
-
-        return (INT)TotalLen; // FIXME: Really return the number of chars written!
-    }
-
-    /*
-     * We are redirected and writing to a file or pipe instead of the console.
-     * Convert the string from TCHARs to the desired output format, if the two differ.
-     *
-     * Implementation NOTE:
-     *   MultiByteToWideChar (resp. WideCharToMultiByte) are equivalent to
-     *   OemToCharBuffW (resp. CharToOemBuffW), but the latters uselessly
-     *   depend on user32.dll, while MultiByteToWideChar and WideCharToMultiByte
-     *   only need kernel32.dll.
-     */
-    if ((Stream->Mode == WideText) || (Stream->Mode == UTF16Text))
-    {
-#ifndef _UNICODE // UNICODE means that TCHAR == WCHAR == UTF-16
-        /* Convert from the current process/thread's codepage to UTF-16 */
-        WCHAR *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
-        if (!buffer)
-        {
-            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-            return 0;
-        }
-        len = (DWORD)MultiByteToWideChar(CP_THREAD_ACP, // CP_ACP, CP_OEMCP
-                                         0, szStr, (INT)len, buffer, (INT)len);
-        szStr = (PVOID)buffer;
-#else
-        /*
-         * Do not perform any conversion since we are already in UTF-16,
-         * that is the same encoding as the stream.
-         */
-#endif
-
-        /*
-         * Find any newline character in the buffer,
-         * write the part BEFORE the newline, then write
-         * a carriage-return + newline, and then write
-         * the remaining part of the buffer.
-         *
-         * This fixes output in files and serial console.
-         */
-        while (len > 0)
-        {
-            /* Loop until we find a \r or \n character */
-            // FIXME: What about the pair \r\n ?
-            p = szStr;
-            while (len > 0 && *(PWCHAR)p != L'\r' && *(PWCHAR)p != L'\n')
-            {
-                /* Advance one character */
-                p = (PVOID)((PWCHAR)p + 1);
-                len--;
-            }
-
-            /* Write everything up to \r or \n */
-            dwNumBytes = ((PWCHAR)p - (PWCHAR)szStr) * sizeof(WCHAR);
-            WriteFile(Stream->hHandle, szStr, dwNumBytes, &dwNumBytes, NULL);
-
-            /* If we hit \r or \n ... */
-            if (len > 0 && (*(PWCHAR)p == L'\r' || *(PWCHAR)p == L'\n'))
-            {
-                /* ... send a carriage-return + newline sequence and skip \r or \n */
-                WriteFile(Stream->hHandle, L"\r\n", 2 * sizeof(WCHAR), &dwNumBytes, NULL);
-                szStr = (PVOID)((PWCHAR)p + 1);
-                len--;
-            }
-        }
-
-#ifndef _UNICODE
-        HeapFree(GetProcessHeap(), 0, buffer);
-#endif
-    }
-    else if ((Stream->Mode == UTF8Text) || (Stream->Mode == AnsiText))
-    {
-        CHAR *buffer;
-
-        /*
-         * Resolve the codepage cache if it was not assigned yet
-         * (only if the stream is in ANSI mode; in UTF8 mode the
-         * codepage was already set to CP_UTF8).
-         */
-        if (/*(Stream->Mode == AnsiText) &&*/ (Stream->CodePage == INVALID_CP))
-            Stream->CodePage = GetConsoleOutputCP(); // CP_ACP, CP_OEMCP
-
-#ifdef _UNICODE // UNICODE means that TCHAR == WCHAR == UTF-16
-        /* Convert from UTF-16 to either UTF-8 or ANSI, using stream codepage */
-        // NOTE: MB_LEN_MAX defined either in limits.h or in stdlib.h .
-        buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * MB_LEN_MAX);
-        if (!buffer)
-        {
-            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-            return 0;
-        }
-        len = WideCharToMultiByte(Stream->CodePage, 0,
-                                  szStr, len, buffer, len * MB_LEN_MAX,
-                                  NULL, NULL);
-        szStr = (PVOID)buffer;
-#else
-        /*
-         * Convert from the current process/thread's codepage to either
-         * UTF-8 or ANSI, using stream codepage.
-         * We need to perform a double conversion, by going through UTF-16.
-         */
-        // TODO!
-        #error "Need to implement double conversion!"
-#endif
-
-        /*
-         * Find any newline character in the buffer,
-         * write the part BEFORE the newline, then write
-         * a carriage-return + newline, and then write
-         * the remaining part of the buffer.
-         *
-         * This fixes output in files and serial console.
-         */
-        while (len > 0)
-        {
-            /* Loop until we find a \r or \n character */
-            // FIXME: What about the pair \r\n ?
-            p = szStr;
-            while (len > 0 && *(PCHAR)p != '\r' && *(PCHAR)p != '\n')
-            {
-                /* Advance one character */
-                p = (PVOID)((PCHAR)p + 1);
-                len--;
-            }
-
-            /* Write everything up to \r or \n */
-            dwNumBytes = ((PCHAR)p - (PCHAR)szStr) * sizeof(CHAR);
-            WriteFile(Stream->hHandle, szStr, dwNumBytes, &dwNumBytes, NULL);
-
-            /* If we hit \r or \n ... */
-            if (len > 0 && (*(PCHAR)p == '\r' || *(PCHAR)p == '\n'))
-            {
-                /* ... send a carriage-return + newline sequence and skip \r or \n */
-                WriteFile(Stream->hHandle, "\r\n", 2, &dwNumBytes, NULL);
-                szStr = (PVOID)((PCHAR)p + 1);
-                len--;
-            }
-        }
-
-#ifdef _UNICODE
-        HeapFree(GetProcessHeap(), 0, buffer);
-#else
-        // TODO!
-#endif
-    }
-    else // if (Stream->Mode == Binary)
-    {
-        /* Directly output the string */
-        WriteFile(Stream->hHandle, szStr, len, &dwNumBytes, NULL);
-    }
-
-    // FIXME!
-    return (INT)TotalLen;
-
-#else /* defined(USE_CRT) */
-
-    DWORD total = len;
-    DWORD written = 0;
-
-    /* If we do not write anything, just return */
-    if (!szStr || len == 0)
-        return 0;
-
-#if 1
-    /*
-     * There is no "counted" printf-to-stream or puts-like function, therefore
-     * we use this trick to output the counted string to the stream.
-     */
-    while (1)
-    {
-        written = fwprintf(Stream->fStream, L"%.*s", total, szStr);
-        if (written < total)
-        {
-            /*
-             * Some embedded NULL or special character
-             * was encountered, print it apart.
-             */
-            if (written == 0)
-            {
-                fputwc(*szStr, Stream->fStream);
-                written++;
-            }
-
-            szStr += written;
-            total -= written;
-        }
-        else
-        {
-            break;
-        }
-    }
-    return (INT)len;
-#else
-    /* ANSI text or Binary output only */
-    _setmode(_fileno(Stream->fStream), _O_TEXT); // _O_BINARY
-    return fwrite(szStr, sizeof(*szStr), len, Stream->fStream);
-#endif
-
-#endif /* defined(USE_CRT) */
-}
-
-
-#define CON_STREAM_WRITE_CALL(Stream, Str, Len) \
-    (Stream)->WriteFunc((Stream), (Str), (Len));
-
-/* Lock the stream only in non-USE_CRT mode (otherwise use the CRT stream lock) */
-#ifndef USE_CRT
-
-#define CON_STREAM_WRITE2(Stream, Str, Len, RetLen) \
-do { \
-    EnterCriticalSection(&(Stream)->Lock); \
-    (RetLen) = CON_STREAM_WRITE_CALL((Stream), (Str), (Len)); \
-    LeaveCriticalSection(&(Stream)->Lock); \
-} while(0)
-
-#define CON_STREAM_WRITE(Stream, Str, Len) \
-do { \
-    EnterCriticalSection(&(Stream)->Lock); \
-    CON_STREAM_WRITE_CALL((Stream), (Str), (Len)); \
-    LeaveCriticalSection(&(Stream)->Lock); \
-} while(0)
-
-#else
-
-#define CON_STREAM_WRITE2(Stream, Str, Len, RetLen) \
-do { \
-    (RetLen) = CON_STREAM_WRITE_CALL((Stream), (Str), (Len)); \
-} while(0)
-
-#define CON_STREAM_WRITE(Stream, Str, Len) \
-do { \
-    CON_STREAM_WRITE_CALL((Stream), (Str), (Len)); \
-} while(0)
-
-#endif
-
-
-INT
-ConStreamWrite(
-    IN PCON_STREAM Stream,
-    IN PTCHAR szStr,
-    IN DWORD len)
-{
-    INT Len;
-    CON_STREAM_WRITE2(Stream, szStr, len, Len);
-    return Len;
-}
-
-INT
-ConPuts(
-    IN PCON_STREAM Stream,
-    IN LPWSTR szStr)
-{
-    INT Len;
-
-    Len = wcslen(szStr);
-    CON_STREAM_WRITE2(Stream, szStr, Len, Len);
-
-    /* Fixup returned length in case of errors */
-    if (Len < 0)
-        Len = 0;
-
-    return Len;
-}
-
-INT
-ConPrintfV(
-    IN PCON_STREAM Stream,
-    IN LPWSTR  szStr,
-    IN va_list args) // arg_ptr
-{
-    INT Len;
-    WCHAR bufSrc[CON_RC_STRING_MAX_SIZE];
-
-    // Len = vfwprintf(Stream->fStream, szStr, args); // vfprintf for direct ANSI
-
-    /*
-     * Reuse szStr as the pointer to end-of-string, to compute
-     * the string length instead of calling wcslen().
-     */
-    // StringCchVPrintfW(bufSrc, ARRAYSIZE(bufSrc), szStr, args);
-    // Len = wcslen(bufSrc);
-    StringCchVPrintfExW(bufSrc, ARRAYSIZE(bufSrc), &szStr, NULL, 0, szStr, args);
-    Len = szStr - bufSrc;
-
-    CON_STREAM_WRITE2(Stream, bufSrc, Len, Len);
-
-    /* Fixup returned length in case of errors */
-    if (Len < 0)
-        Len = 0;
-
-    return Len;
-}
-
-INT
-__cdecl
-ConPrintf(
-    IN PCON_STREAM Stream,
-    IN LPWSTR szStr,
-    ...)
-{
-    INT Len;
-    va_list args;
-
-    // Len = vfwprintf(Stream->fStream, szMsgBuf, args); // vfprintf for direct ANSI
-
-    // StringCchPrintfW
-    va_start(args, szStr);
-    Len = ConPrintfV(Stream, szStr, args);
-    va_end(args);
-
-    return Len;
-}
-
-INT
-ConResPutsEx(
-    IN PCON_STREAM Stream,
-    IN HINSTANCE hInstance OPTIONAL,
-    IN UINT uID)
-{
-    INT Len;
-    PWCHAR szStr = NULL;
-
-    Len = K32LoadStringW(hInstance, uID, (PWSTR)&szStr, 0);
-    if (szStr && Len)
-        // Len = ConPuts(Stream, szStr);
-        CON_STREAM_WRITE2(Stream, szStr, Len, Len);
-
-    /* Fixup returned length in case of errors */
-    if (Len < 0)
-        Len = 0;
-
-    return Len;
-}
-
-INT
-ConResPuts(
-    IN PCON_STREAM Stream,
-    IN UINT uID)
-{
-    return ConResPutsEx(Stream, NULL /*GetModuleHandleW(NULL)*/, uID);
-}
-
-INT
-ConResPrintfExV(
-    IN PCON_STREAM Stream,
-    IN HINSTANCE hInstance OPTIONAL,
-    IN UINT    uID,
-    IN va_list args) // arg_ptr
-{
-    INT Len;
-    WCHAR bufSrc[CON_RC_STRING_MAX_SIZE];
-
-    // NOTE: We may use the special behaviour where nBufMaxSize == 0
-    Len = K32LoadStringW(hInstance, uID, bufSrc, ARRAYSIZE(bufSrc));
-    if (Len)
-        Len = ConPrintfV(Stream, bufSrc, args);
-
-    return Len;
-}
-
-INT
-ConResPrintfV(
-    IN PCON_STREAM Stream,
-    IN UINT    uID,
-    IN va_list args) // arg_ptr
-{
-    return ConResPrintfExV(Stream, NULL /*GetModuleHandleW(NULL)*/, uID, args);
-}
-
-INT
-__cdecl
-ConResPrintfEx(
-    IN PCON_STREAM Stream,
-    IN HINSTANCE hInstance OPTIONAL,
-    IN UINT uID,
-    ...)
-{
-    INT Len;
-    va_list args;
-
-    va_start(args, uID);
-    Len = ConResPrintfExV(Stream, hInstance, uID, args);
-    va_end(args);
-
-    return Len;
-}
-
-INT
-__cdecl
-ConResPrintf(
-    IN PCON_STREAM Stream,
-    IN UINT uID,
-    ...)
-{
-    INT Len;
-    va_list args;
-
-    va_start(args, uID);
-    Len = ConResPrintfV(Stream, uID, args);
-    va_end(args);
-
-    return Len;
-}
-
-INT
-ConMsgPuts(
-    IN PCON_STREAM Stream,
-    IN DWORD   dwFlags,
-    IN LPCVOID lpSource OPTIONAL,
-    IN DWORD   dwMessageId,
-    IN DWORD   dwLanguageId)
-{
-    INT Len;
-    DWORD dwLength  = 0;
-    LPWSTR lpMsgBuf = NULL;
-
-    /*
-     * Sanitize dwFlags. This version always ignore explicitely the inserts
-     * as we emulate the behaviour of the *puts function.
-     */
-    dwFlags |= FORMAT_MESSAGE_ALLOCATE_BUFFER; // Always allocate an internal buffer.
-    dwFlags |= FORMAT_MESSAGE_IGNORE_INSERTS;  // Ignore inserts for FormatMessage.
-    dwFlags &= ~FORMAT_MESSAGE_ARGUMENT_ARRAY;
-
-    dwFlags |= FORMAT_MESSAGE_MAX_WIDTH_MASK;
-
-    /*
-     * Retrieve the message string without appending extra newlines.
-     * Wrap in SEH to protect from invalid string parameters.
-     */
-    _SEH2_TRY
-    {
-        dwLength = FormatMessageW(dwFlags,
-                                  lpSource,
-                                  dwMessageId,
-                                  dwLanguageId,
-                                  (LPWSTR)&lpMsgBuf,
-                                  0, NULL);
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-    }
-    _SEH2_END;
-
-    Len = (INT)dwLength;
-
-    if (!lpMsgBuf)
-    {
-        // ASSERT(dwLength == 0);
-    }
-    else
-    {
-        // ASSERT(dwLength != 0);
-
-        /* lpMsgBuf is NULL-terminated by FormatMessage */
-        // Len = ConPuts(Stream, lpMsgBuf);
-        CON_STREAM_WRITE2(Stream, lpMsgBuf, dwLength, Len);
-
-        /* Fixup returned length in case of errors */
-        if (Len < 0)
-            Len = 0;
-
-        /* Free the buffer allocated by FormatMessage */
-        LocalFree(lpMsgBuf);
-    }
-
-    return Len;
-}
-
-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 Len;
-    DWORD dwLength  = 0;
-    LPWSTR lpMsgBuf = NULL;
-
-    /*
-     * Sanitize dwFlags. This version always ignore explicitely the inserts.
-     * The string that we will return to the user will not be pre-formatted.
-     */
-    dwFlags |= FORMAT_MESSAGE_ALLOCATE_BUFFER; // Always allocate an internal buffer.
-    dwFlags |= FORMAT_MESSAGE_IGNORE_INSERTS;  // Ignore inserts for FormatMessage.
-    dwFlags &= ~FORMAT_MESSAGE_ARGUMENT_ARRAY;
-
-    dwFlags |= FORMAT_MESSAGE_MAX_WIDTH_MASK;
-
-    /*
-     * Retrieve the message string without appending extra newlines.
-     * Wrap in SEH to protect from invalid string parameters.
-     */
-    _SEH2_TRY
-    {
-        dwLength = FormatMessageW(dwFlags,
-                                  lpSource,
-                                  dwMessageId,
-                                  dwLanguageId,
-                                  (LPWSTR)&lpMsgBuf,
-                                  0, NULL);
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-    }
-    _SEH2_END;
-
-    Len = (INT)dwLength;
-
-    if (!lpMsgBuf)
-    {
-        // ASSERT(dwLength == 0);
-    }
-    else
-    {
-        // ASSERT(dwLength != 0);
-
-        /* lpMsgBuf is NULL-terminated by FormatMessage */
-        Len = ConPrintfV(Stream, lpMsgBuf, args);
-        // CON_STREAM_WRITE2(Stream, lpMsgBuf, dwLength, Len);
-
-        /* Fixup returned length in case of errors */
-        if (Len < 0)
-            Len = 0;
-
-        /* Free the buffer allocated by FormatMessage */
-        LocalFree(lpMsgBuf);
-    }
-
-    return Len;
-}
-
-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 Len;
-    DWORD dwLength  = 0;
-    LPWSTR lpMsgBuf = NULL;
-
-    /* Sanitize dwFlags */
-    dwFlags |= FORMAT_MESSAGE_ALLOCATE_BUFFER; // Always allocate an internal buffer.
-//  dwFlags &= ~FORMAT_MESSAGE_IGNORE_INSERTS; // We always use arguments.
-    dwFlags &= ~FORMAT_MESSAGE_ARGUMENT_ARRAY; // We always use arguments of type 'va_list'.
-
-    //
-    // NOTE: Technique taken from eventvwr.c!GetMessageStringFromDll()
-    //
-
-    dwFlags |= FORMAT_MESSAGE_MAX_WIDTH_MASK;
-
-    /*
-     * Retrieve the message string without appending extra newlines.
-     * Use the "safe" FormatMessage version (SEH-protected) to protect
-     * from invalid string parameters.
-     */
-    dwLength = FormatMessageSafeW(dwFlags,
-                                  lpSource,
-                                  dwMessageId,
-                                  dwLanguageId,
-                                  (LPWSTR)&lpMsgBuf,
-                                  0, &args);
-
-    Len = (INT)dwLength;
-
-    if (!lpMsgBuf)
-    {
-        // ASSERT(dwLength == 0);
-    }
-    else
-    {
-        // ASSERT(dwLength != 0);
-
-        // Len = ConPrintfV(Stream, lpMsgBuf, args);
-        CON_STREAM_WRITE2(Stream, lpMsgBuf, dwLength, Len);
-
-        /* Fixup returned length in case of errors */
-        if (Len < 0)
-            Len = 0;
-
-        /* Free the buffer allocated by FormatMessage */
-        LocalFree(lpMsgBuf);
-    }
-
-    return Len;
-}
-
-INT
-__cdecl
-ConMsgPrintf(
-    IN PCON_STREAM Stream,
-    IN DWORD   dwFlags,
-    IN LPCVOID lpSource OPTIONAL,
-    IN DWORD   dwMessageId,
-    IN DWORD   dwLanguageId,
-    ...)
-{
-    INT Len;
-    va_list args;
-
-    va_start(args, dwLanguageId);
-    // ConMsgPrintf2V
-    Len = ConMsgPrintfV(Stream,
-                        dwFlags,
-                        lpSource,
-                        dwMessageId,
-                        dwLanguageId,
-                        args);
-    va_end(args);
-
-    return Len;
-}
-
-
-
-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
-}
-
+/* EOF */
index 7b60387..f3804b6 100644 (file)
@@ -1,18 +1,18 @@
 /*
- * 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.
+ * PROJECT:     ReactOS Console Utilities Library
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Provides basic abstraction wrappers around CRT streams or
+ *              Win32 console API I/O functions, to deal with i18n + Unicode
+ *              related problems.
+ * COPYRIGHT:   Copyright 2017-2018 ReactOS Team
+ *              Copyright 2017-2018 Hermes Belusca-Maito
  */
 
 #ifndef __STREAM_H__
 #define __STREAM_H__
 
+#pragma once
+
 /*
  * Enable this define if you want to only use CRT functions to output
  * UNICODE stream to the console, as in the way explained by
@@ -152,124 +152,10 @@ ConStreamSetOSHandle(
     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);
-
-
 #ifdef __cplusplus
 }
 #endif
+
 #endif  /* __STREAM_H__ */
+
+/* EOF */
diff --git a/sdk/lib/conutils/stream_private.h b/sdk/lib/conutils/stream_private.h
new file mode 100644 (file)
index 0000000..6b801df
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * PROJECT:     ReactOS Console Utilities Library
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Provides basic abstraction wrappers around CRT streams or
+ *              Win32 console API I/O functions, to deal with i18n + Unicode
+ *              related problems.
+ * COPYRIGHT:   Copyright 2017-2018 ReactOS Team
+ *              Copyright 2017-2018 Hermes Belusca-Maito
+ */
+
+#ifndef __STREAM_PRIVATE_H__
+#define __STREAM_PRIVATE_H__
+
+#pragma once
+
+/*
+ * Console I/O streams
+ */
+
+#if 0
+// Shadow type, implementation-specific
+typedef struct _CON_STREAM CON_STREAM, *PCON_STREAM;
+#endif
+
+typedef struct _CON_STREAM
+{
+    CON_WRITE_FUNC WriteFunc;
+
+#ifdef USE_CRT
+    FILE* fStream;
+#else
+    BOOL IsInitialized;
+    CRITICAL_SECTION Lock;
+
+    HANDLE hHandle;
+
+    /*
+     * TRUE if 'hHandle' refers to a console, in which case I/O UTF-16
+     * is directly used. If 'hHandle' refers to a file or a pipe, the
+     * 'Mode' flag is used.
+     */
+    BOOL IsConsole;
+
+    /*
+     * The 'Mode' flag is used to know the translation mode
+     * when 'hHandle' refers to a file or a pipe.
+     */
+    CON_STREAM_MODE Mode;
+    UINT CodePage;  // Used to convert UTF-16 text to some ANSI codepage.
+#endif /* defined(USE_CRT) */
+} CON_STREAM, *PCON_STREAM;
+
+#endif  /* __STREAM_PRIVATE_H__ */
+
+/* EOF */
index b46ee91..b5dfdee 100644 (file)
@@ -1,12 +1,10 @@
 /*
- * 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.
+ * PROJECT:     ReactOS Console Utilities Library
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Base set of functions for loading string resources
+ *              and message strings, and handle type identification.
+ * COPYRIGHT:   Copyright 2017-2018 ReactOS Team
+ *              Copyright 2017-2018 Hermes Belusca-Maito
  */
 
 /* FIXME: Temporary HACK before we cleanly support UNICODE functions */
@@ -232,3 +230,5 @@ IsConsoleHandle(IN HANDLE hHandle)
      */
     return GetConsoleMode(hHandle, &dwMode);
 }
+
+/* EOF */
index 52063c2..9f414ab 100644 (file)
@@ -1,17 +1,17 @@
 /*
- * 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.
+ * PROJECT:     ReactOS Console Utilities Library
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Base set of functions for loading string resources
+ *              and message strings, and handle type identification.
+ * COPYRIGHT:   Copyright 2017-2018 ReactOS Team
+ *              Copyright 2017-2018 Hermes Belusca-Maito
  */
 
 #ifndef __UTILS_H__
 #define __UTILS_H__
 
+#pragma once
+
 #ifndef _UNICODE
 #error The ConUtils library at the moment only supports compilation with _UNICODE defined!
 #endif
@@ -57,4 +57,7 @@ IsConsoleHandle(IN HANDLE hHandle);
 #ifdef __cplusplus
 }
 #endif
+
 #endif  /* __UTILS_H__ */
+
+/* EOF */