[CONUTILS] Diverse improvements: start doxygenating and add some resource messsage...
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Thu, 1 Feb 2018 23:35:08 +0000 (00:35 +0100)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Thu, 1 Feb 2018 23:41:54 +0000 (00:41 +0100)
- Start to doxygenate the library, focusing in great details on the
  functions of the "outstream" module.
- Add a K32LoadStringEx function that expands (K32)LoadString by
  allowing a LanguageId parameter to be able to load strings from other
  languages than the current one.
- Add "ConResMsg*" helper functions to be able to (format and) print
  message strings with inserts that come *NOT* from a message table (as
  usual) *BUT* from resource string tables.
  Will be helpful for CORE-14265 in particular.

[CMD] Fix the call to ConMsgPrintfV().

14 files changed:
base/shell/cmd/console.c
sdk/lib/conutils/conutils.h
sdk/lib/conutils/instream.c
sdk/lib/conutils/instream.h
sdk/lib/conutils/outstream.c
sdk/lib/conutils/outstream.h
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/utils.c
sdk/lib/conutils/utils.h

index 45e6257..9d14d27 100644 (file)
@@ -141,7 +141,7 @@ VOID __cdecl ConFormatMessage(PCON_STREAM Stream, DWORD MessageId, ...)
                         NULL,
                         MessageId,
                         LANG_USER_DEFAULT,
-                        arg_ptr);
+                        &arg_ptr);
     va_end(arg_ptr);
 
     if (Len <= 0)
index 93d79e8..3ad7849 100644 (file)
@@ -8,6 +8,21 @@
  *              Copyright 2017-2018 Hermes Belusca-Maito
  */
 
+/**
+ * @file    conutils.h
+ * @ingroup ConUtils
+ *
+ * @defgroup ConUtils   ReactOS Console Utilities Library
+ *
+ * @brief   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.
+ **/
+
 #ifndef __CONUTILS_H__
 #define __CONUTILS_H__
 
index a9fa105..73e4038 100644 (file)
@@ -8,6 +8,13 @@
  *              Copyright 2017-2018 Hermes Belusca-Maito
  */
 
+/**
+ * @file    instream.c
+ * @ingroup ConUtils
+ *
+ * @brief   Console I/O utility API -- Input
+ **/
+
 /*
  * Enable this define if you want to only use CRT functions to output
  * UNICODE stream to the console, as in the way explained by
@@ -42,8 +49,4 @@
 #include "stream_private.h"
 
 
-/*
- * Console I/O utility API -- Input
- */
-
 /* EOF */
index d16a9c3..087e163 100644 (file)
@@ -8,6 +8,13 @@
  *              Copyright 2017-2018 Hermes Belusca-Maito
  */
 
+/**
+ * @file    instream.h
+ * @ingroup ConUtils
+ *
+ * @brief   Console I/O utility API -- Input
+ **/
+
 #ifndef __INSTREAM_H__
 #define __INSTREAM_H__
 
@@ -32,10 +39,6 @@ extern "C" {
 // Shadow type, implementation-specific
 typedef struct _CON_STREAM CON_STREAM, *PCON_STREAM;
 
-/*
- * Console I/O utility API -- Input
- */
-
 
 #ifdef __cplusplus
 }
index 63adaf3..ce25d51 100644 (file)
@@ -8,6 +8,13 @@
  *              Copyright 2017-2018 Hermes Belusca-Maito
  */
 
+/**
+ * @file    outstream.c
+ * @ingroup ConUtils
+ *
+ * @brief   Console I/O utility API -- Output
+ **/
+
 /*
  * Enable this define if you want to only use CRT functions to output
  * UNICODE stream to the console, as in the way explained by
 // #define MAX_MESSAGE_SIZE    512     // See shutdown...
 
 
-/*
- * Console I/O utility API -- Output
- */
-
-// NOTE: Should be called with the stream locked.
+/**
+ * @name ConWrite
+ *     Writes a counted string to a stream.
+ *
+ * @param[in]   Stream
+ *     Stream to which the write operation is issued.
+ *
+ * @param[in]   szStr
+ *     Pointer to the counted string to write.
+ *
+ * @param[in]   len
+ *     Length of the string pointed by @p szStr, specified
+ *     in number of characters.
+ *
+ * @return
+ *     Numbers of characters successfully written to @p Stream.
+ *
+ * @note
+ *     This function is used as an internal function.
+ *     Use the ConStreamWrite() function instead.
+ *
+ * @remark
+ *     Should be called with the stream locked.
+ **/
 INT
 __stdcall
 ConWrite(
     IN PCON_STREAM Stream,
     IN PTCHAR szStr,
-    IN DWORD len)
+    IN DWORD  len)
 {
 #ifndef USE_CRT
     DWORD TotalLen = len, dwNumBytes = 0;
@@ -339,17 +365,52 @@ do { \
 #endif
 
 
+/**
+ * @name ConStreamWrite
+ *     Writes a counted string to a stream.
+ *
+ * @param[in]   Stream
+ *     Stream to which the write operation is issued.
+ *
+ * @param[in]   szStr
+ *     Pointer to the counted string to write.
+ *
+ * @param[in]   len
+ *     Length of the string pointed by @p szStr, specified
+ *     in number of characters.
+ *
+ * @return
+ *     Numbers of characters successfully written to @p Stream.
+ **/
 INT
 ConStreamWrite(
     IN PCON_STREAM Stream,
     IN PTCHAR szStr,
-    IN DWORD len)
+    IN DWORD  len)
 {
     INT Len;
     CON_STREAM_WRITE2(Stream, szStr, len, Len);
     return Len;
 }
 
+/**
+ * @name ConPuts
+ *     Writes a NULL-terminated string to a stream.
+ *
+ * @param[in]   Stream
+ *     Stream to which the write operation is issued.
+ *
+ * @param[in]   szStr
+ *     Pointer to the NULL-terminated string to write.
+ *
+ * @return
+ *     Numbers of characters successfully written to @p Stream.
+ *
+ * @remark
+ *     Contrary to the CRT puts() function, ConPuts() does not append
+ *     a terminating new-line character. In this way it behaves more like
+ *     the CRT fputs() function.
+ **/
 INT
 ConPuts(
     IN PCON_STREAM Stream,
@@ -367,11 +428,33 @@ ConPuts(
     return Len;
 }
 
+/**
+ * @name ConPrintfV
+ *     Formats and writes a NULL-terminated string to a stream.
+ *
+ * @param[in]   Stream
+ *     Stream to which the write operation is issued.
+ *
+ * @param[in]   szStr
+ *     Pointer to the NULL-terminated format string, that follows the same
+ *     specifications as the @a szStr format string in ConPrintf().
+ *
+ * @param[in]   args
+ *     Parameter describing a variable number of arguments,
+ *     initialized with va_start(), that can be expected by the function,
+ *     depending on the @p szStr format string. Each argument is used to
+ *     replace a <em>format specifier</em> in the format string.
+ *
+ * @return
+ *     Numbers of characters successfully written to @p Stream.
+ *
+ * @see ConPrintf(), printf(), vprintf()
+ **/
 INT
 ConPrintfV(
     IN PCON_STREAM Stream,
     IN LPWSTR  szStr,
-    IN va_list args) // arg_ptr
+    IN va_list args)
 {
     INT Len;
     WCHAR bufSrc[CON_RC_STRING_MAX_SIZE];
@@ -396,6 +479,30 @@ ConPrintfV(
     return Len;
 }
 
+/**
+ * @name ConPrintf
+ *     Formats and writes a NULL-terminated string to a stream.
+ *
+ * @param[in]   Stream
+ *     Stream to which the write operation is issued.
+ *
+ * @param[in]   szStr
+ *     Pointer to the NULL-terminated format string, that follows the same
+ *     specifications as the @a format string in printf(). This string can
+ *     optionally contain embedded <em>format specifiers</em> that are
+ *     replaced by the values specified in subsequent additional arguments
+ *     and formatted as requested.
+ *
+ * @param[in]   ...
+ *     Additional arguments that can be expected by the function, depending
+ *     on the @p szStr format string. Each argument is used to replace a
+ *     <em>format specifier</em> in the format string.
+ *
+ * @return
+ *     Numbers of characters successfully written to @p Stream.
+ *
+ * @see ConPrintfV(), printf(), vprintf()
+ **/
 INT
 __cdecl
 ConPrintf(
@@ -416,16 +523,47 @@ ConPrintf(
     return Len;
 }
 
+/**
+ * @name ConResPutsEx
+ *     Writes a string resource to a stream.
+ *
+ * @param[in]   Stream
+ *     Stream to which the write operation is issued.
+ *
+ * @param[in]   hInstance
+ *     Optional handle to an instance of the module whose executable file
+ *     contains the string resource. Can be set to NULL to get the handle
+ *     to the application itself.
+ *
+ * @param[in]   uID
+ *     The identifier of the string to be written.
+ *
+ * @param[in]   LanguageId
+ *     The language identifier of the resource. If this parameter is
+ *     <tt>MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)</tt>, the current language
+ *     associated with the calling thread is used. To specify a language other
+ *     than the current language, use the @c MAKELANGID macro to create this
+ *     parameter.
+ *
+ * @return
+ *     Numbers of characters successfully written to @p Stream.
+ *
+ * @remark
+ *     Similarly to ConPuts(), no terminating new-line character is appended.
+ *
+ * @see ConPuts(), ConResPuts()
+ **/
 INT
 ConResPutsEx(
     IN PCON_STREAM Stream,
     IN HINSTANCE hInstance OPTIONAL,
-    IN UINT uID)
+    IN UINT   uID,
+    IN LANGID LanguageId)
 {
     INT Len;
     PWCHAR szStr = NULL;
 
-    Len = K32LoadStringW(hInstance, uID, (PWSTR)&szStr, 0);
+    Len = K32LoadStringExW(hInstance, uID, LanguageId, (PWSTR)&szStr, 0);
     if (szStr && Len)
         // Len = ConPuts(Stream, szStr);
         CON_STREAM_WRITE2(Stream, szStr, Len, Len);
@@ -437,59 +575,195 @@ ConResPutsEx(
     return Len;
 }
 
+/**
+ * @name ConResPuts
+ *     Writes a string resource contained in the current application
+ *     to a stream.
+ *
+ * @param[in]   Stream
+ *     Stream to which the write operation is issued.
+ *
+ * @param[in]   uID
+ *     The identifier of the string to be written.
+ *
+ * @return
+ *     Numbers of characters successfully written to @p Stream.
+ *
+ * @remark
+ *     Similarly to ConPuts(), no terminating new-line character is appended.
+ *
+ * @see ConPuts(), ConResPutsEx()
+ **/
 INT
 ConResPuts(
     IN PCON_STREAM Stream,
     IN UINT uID)
 {
-    return ConResPutsEx(Stream, NULL /*GetModuleHandleW(NULL)*/, uID);
+    return ConResPutsEx(Stream, NULL /*GetModuleHandleW(NULL)*/,
+                        uID, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL));
 }
 
+/**
+ * @name ConResPrintfExV
+ *     Formats and writes a string resource to a stream.
+ *
+ * @param[in]   Stream
+ *     Stream to which the write operation is issued.
+ *
+ * @param[in]   hInstance
+ *     Optional handle to an instance of the module whose executable file
+ *     contains the string resource. Can be set to NULL to get the handle
+ *     to the application itself.
+ *
+ * @param[in]   uID
+ *     The identifier of the format string. The format string follows the
+ *     same specifications as the @a szStr format string in ConPrintf().
+ *
+ * @param[in]   LanguageId
+ *     The language identifier of the resource. If this parameter is
+ *     <tt>MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)</tt>, the current language
+ *     associated with the calling thread is used. To specify a language other
+ *     than the current language, use the @c MAKELANGID macro to create this
+ *     parameter.
+ *
+ * @param[in]   args
+ *     Parameter describing a variable number of arguments,
+ *     initialized with va_start(), that can be expected by the function,
+ *     depending on the @p szStr format string. Each argument is used to
+ *     replace a <em>format specifier</em> in the format string.
+ *
+ * @return
+ *     Numbers of characters successfully written to @p Stream.
+ *
+ * @see ConPrintf(), ConResPrintfEx(), ConResPrintfV(), ConResPrintf()
+ **/
 INT
 ConResPrintfExV(
     IN PCON_STREAM Stream,
     IN HINSTANCE hInstance OPTIONAL,
     IN UINT    uID,
-    IN va_list args) // arg_ptr
+    IN LANGID  LanguageId,
+    IN va_list args)
 {
     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));
+    Len = K32LoadStringExW(hInstance, uID, LanguageId, bufSrc, ARRAYSIZE(bufSrc));
     if (Len)
         Len = ConPrintfV(Stream, bufSrc, args);
 
     return Len;
 }
 
+/**
+ * @name ConResPrintfV
+ *     Formats and writes a string resource contained in the
+ *     current application to a stream.
+ *
+ * @param[in]   Stream
+ *     Stream to which the write operation is issued.
+ *
+ * @param[in]   uID
+ *     The identifier of the format string. The format string follows the
+ *     same specifications as the @a szStr format string in ConPrintf().
+ *
+ * @param[in]   args
+ *     Parameter describing a variable number of arguments,
+ *     initialized with va_start(), that can be expected by the function,
+ *     depending on the @p szStr format string. Each argument is used to
+ *     replace a <em>format specifier</em> in the format string.
+ *
+ * @return
+ *     Numbers of characters successfully written to @p Stream.
+ *
+ * @see ConPrintf(), ConResPrintfExV(), ConResPrintfEx(), ConResPrintf()
+ **/
 INT
 ConResPrintfV(
     IN PCON_STREAM Stream,
     IN UINT    uID,
-    IN va_list args) // arg_ptr
+    IN va_list args)
 {
-    return ConResPrintfExV(Stream, NULL /*GetModuleHandleW(NULL)*/, uID, args);
+    return ConResPrintfExV(Stream, NULL /*GetModuleHandleW(NULL)*/,
+                           uID, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
+                           args);
 }
 
+/**
+ * @name ConResPrintfEx
+ *     Formats and writes a string resource to a stream.
+ *
+ * @param[in]   Stream
+ *     Stream to which the write operation is issued.
+ *
+ * @param[in]   hInstance
+ *     Optional handle to an instance of the module whose executable file
+ *     contains the string resource. Can be set to NULL to get the handle
+ *     to the application itself.
+ *
+ * @param[in]   uID
+ *     The identifier of the format string. The format string follows the
+ *     same specifications as the @a szStr format string in ConPrintf().
+ *
+ * @param[in]   LanguageId
+ *     The language identifier of the resource. If this parameter is
+ *     <tt>MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)</tt>, the current language
+ *     associated with the calling thread is used. To specify a language other
+ *     than the current language, use the @c MAKELANGID macro to create this
+ *     parameter.
+ *
+ * @param[in]   ...
+ *     Additional arguments that can be expected by the function, depending
+ *     on the @p szStr format string. Each argument is used to replace a
+ *     <em>format specifier</em> in the format string.
+ *
+ * @return
+ *     Numbers of characters successfully written to @p Stream.
+ *
+ * @see ConPrintf(), ConResPrintfExV(), ConResPrintfV(), ConResPrintf()
+ **/
 INT
 __cdecl
 ConResPrintfEx(
     IN PCON_STREAM Stream,
     IN HINSTANCE hInstance OPTIONAL,
-    IN UINT uID,
+    IN UINT   uID,
+    IN LANGID LanguageId,
     ...)
 {
     INT Len;
     va_list args;
 
-    va_start(args, uID);
-    Len = ConResPrintfExV(Stream, hInstance, uID, args);
+    va_start(args, LanguageId);
+    Len = ConResPrintfExV(Stream, hInstance, uID, LanguageId, args);
     va_end(args);
 
     return Len;
 }
 
+/**
+ * @name ConResPrintf
+ *     Formats and writes a string resource contained in the
+ *     current application to a stream.
+ *
+ * @param[in]   Stream
+ *     Stream to which the write operation is issued.
+ *
+ * @param[in]   uID
+ *     The identifier of the format string. The format string follows the
+ *     same specifications as the @a szStr format string in ConPrintf().
+ *
+ * @param[in]   ...
+ *     Additional arguments that can be expected by the function, depending
+ *     on the @p szStr format string. Each argument is used to replace a
+ *     <em>format specifier</em> in the format string.
+ *
+ * @return
+ *     Numbers of characters successfully written to @p Stream.
+ *
+ * @see ConPrintf(), ConResPrintfExV(), ConResPrintfEx(), ConResPrintfV()
+ **/
 INT
 __cdecl
 ConResPrintf(
@@ -507,6 +781,46 @@ ConResPrintf(
     return Len;
 }
 
+/**
+ * @name ConMsgPuts
+ *     Writes a message string to a stream without formatting. The function
+ *     requires a message definition as input. The message definition can come
+ *     from a buffer passed to the function. It can come from a message table
+ *     resource in an already-loaded module, or the caller can ask the function
+ *     to search the system's message table resource(s) for the message definition.
+ *     Please refer to the Win32 FormatMessage() function for more details.
+ *
+ * @param[in]   Stream
+ *     Stream to which the write operation is issued.
+ *
+ * @param[in]   dwFlags
+ *     The formatting options, and how to interpret the @p lpSource parameter.
+ *     See FormatMessage() for more details. The @b@c FORMAT_MESSAGE_ALLOCATE_BUFFER
+ *     and @b@c FORMAT_MESSAGE_ARGUMENT_ARRAY flags are always ignored.
+ *     The function implicitly uses the @b@c FORMAT_MESSAGE_IGNORE_INSERTS and
+ *     @b@c FORMAT_MESSAGE_MAX_WIDTH_MASK flags to implement its behaviour.
+ *
+ * @param[in]   lpSource
+ *     The location of the message definition. The type of this parameter
+ *     depends upon the settings in the @p dwFlags parameter.
+ *
+ * @param[in]   dwMessageId
+ *     The message identifier for the requested message. This parameter
+ *     is ignored if @p dwFlags includes @b@c FORMAT_MESSAGE_FROM_STRING.
+ *
+ * @param[in]   dwLanguageId
+ *     The language identifier for the requested message. This parameter
+ *     is ignored if @p dwFlags includes @b@c FORMAT_MESSAGE_FROM_STRING.
+ *
+ * @return
+ *     Numbers of characters successfully written to @p Stream.
+ *
+ * @remark
+ *     Similarly to ConPuts(), no terminating new-line character is appended.
+ *
+ * @see ConPuts(), ConResPuts() and associated functions,
+ *      <a href="FormatMessage() (on MSDN)">https://msdn.microsoft.com/en-us/library/windows/desktop/ms679351(v=vs.85).aspx</a>
+ **/
 INT
 ConMsgPuts(
     IN PCON_STREAM Stream,
@@ -521,7 +835,7 @@ ConMsgPuts(
 
     /*
      * Sanitize dwFlags. This version always ignore explicitely the inserts
-     * as we emulate the behaviour of the *puts function.
+     * as we emulate the behaviour of the (f)puts function.
      */
     dwFlags |= FORMAT_MESSAGE_ALLOCATE_BUFFER; // Always allocate an internal buffer.
     dwFlags |= FORMAT_MESSAGE_IGNORE_INSERTS;  // Ignore inserts for FormatMessage.
@@ -540,7 +854,8 @@ ConMsgPuts(
                                   dwMessageId,
                                   dwLanguageId,
                                   (LPWSTR)&lpMsgBuf,
-                                  0, NULL);
+                                  0,
+                                  NULL);
     }
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
@@ -572,6 +887,14 @@ ConMsgPuts(
     return Len;
 }
 
+/**
+ * @name ConMsgPrintf2V
+ *     Formats and writes a message string to a stream.
+ *
+ * @remark For internal use only.
+ *
+ * @see ConMsgPrintfV()
+ **/
 INT
 ConMsgPrintf2V(
     IN PCON_STREAM Stream,
@@ -579,7 +902,7 @@ ConMsgPrintf2V(
     IN LPCVOID lpSource OPTIONAL,
     IN DWORD   dwMessageId,
     IN DWORD   dwLanguageId,
-    IN va_list args) // arg_ptr
+    IN va_list args)
 {
     INT Len;
     DWORD dwLength  = 0;
@@ -606,7 +929,8 @@ ConMsgPrintf2V(
                                   dwMessageId,
                                   dwLanguageId,
                                   (LPWSTR)&lpMsgBuf,
-                                  0, NULL);
+                                  0,
+                                  NULL);
     }
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
@@ -638,6 +962,63 @@ ConMsgPrintf2V(
     return Len;
 }
 
+/**
+ * @name ConMsgPrintfV
+ *     Formats and writes a message string to a stream. The function requires
+ *     a message definition as input. The message definition can come from a
+ *     buffer passed to the function. It can come from a message table resource
+ *     in an already-loaded module, or the caller can ask the function to search
+ *     the system's message table resource(s) for the message definition.
+ *     Please refer to the Win32 FormatMessage() function for more details.
+ *
+ * @param[in]   Stream
+ *     Stream to which the write operation is issued.
+ *
+ * @param[in]   dwFlags
+ *     The formatting options, and how to interpret the @p lpSource parameter.
+ *     See FormatMessage() for more details. The @b@c FORMAT_MESSAGE_ALLOCATE_BUFFER
+ *     flags is always ignored. The function implicitly uses the
+ *     @b@c FORMAT_MESSAGE_MAX_WIDTH_MASK flag to implement its behaviour.
+ *
+ * @param[in]   lpSource
+ *     The location of the message definition. The type of this parameter
+ *     depends upon the settings in the @p dwFlags parameter.
+ *
+ * @param[in]   dwMessageId
+ *     The message identifier for the requested message. This parameter
+ *     is ignored if @p dwFlags includes @b@c FORMAT_MESSAGE_FROM_STRING.
+ *
+ * @param[in]   dwLanguageId
+ *     The language identifier for the requested message. This parameter
+ *     is ignored if @p dwFlags includes @b@c FORMAT_MESSAGE_FROM_STRING.
+ *
+ * @param[in]   Arguments
+ *     Optional pointer to an array of values describing a variable number of
+ *     arguments, depending on the message string. Each argument is used to
+ *     replace an <em>insert sequence</em> in the message string.
+ *     By default, the @p Arguments parameter is of type @c va_list*, initialized
+ *     with va_start(). The state of the @c va_list argument is undefined upon
+ *     return from the function. To use the @c va_list again, destroy the variable
+ *     argument list pointer using va_end() and reinitialize it with va_start().
+ *     If you do not have a pointer of type @c va_list*, then specify the
+ *     @b@c FORMAT_MESSAGE_ARGUMENT_ARRAY flag and pass a pointer to an array
+ *     of @c DWORD_PTR values; those values are input to the message formatted
+ *     as the insert values. Each insert must have a corresponding element in
+ *     the array.
+ *
+ * @remark
+ *     Contrary to printf(), ConPrintf(), ConResPrintf() and associated functions,
+ *     the ConMsg* functions work on format strings that contain <em>insert sequences</em>.
+ *     These sequences extend the standard <em>format specifiers</em> as they
+ *     allow to specify an <em>insert number</em> referring which precise value
+ *     given in arguments to use.
+ *
+ * @return
+ *     Numbers of characters successfully written to @p Stream.
+ *
+ * @see ConPrintf(), ConResPrintf() and associated functions, ConMsgPrintf(),
+ *      <a href="FormatMessage() (on MSDN)">https://msdn.microsoft.com/en-us/library/windows/desktop/ms679351(v=vs.85).aspx</a>
+ **/
 INT
 ConMsgPrintfV(
     IN PCON_STREAM Stream,
@@ -645,7 +1026,7 @@ ConMsgPrintfV(
     IN LPCVOID lpSource OPTIONAL,
     IN DWORD   dwMessageId,
     IN DWORD   dwLanguageId,
-    IN va_list args) // arg_ptr
+    IN va_list *Arguments OPTIONAL)
 {
     INT Len;
     DWORD dwLength  = 0;
@@ -653,13 +1034,9 @@ ConMsgPrintfV(
 
     /* 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;
 
     /*
@@ -672,7 +1049,8 @@ ConMsgPrintfV(
                                   dwMessageId,
                                   dwLanguageId,
                                   (LPWSTR)&lpMsgBuf,
-                                  0, &args);
+                                  0,
+                                  Arguments);
 
     Len = (INT)dwLength;
 
@@ -684,7 +1062,6 @@ ConMsgPrintfV(
     {
         // ASSERT(dwLength != 0);
 
-        // Len = ConPrintfV(Stream, lpMsgBuf, args);
         CON_STREAM_WRITE2(Stream, lpMsgBuf, dwLength, Len);
 
         /* Fixup returned length in case of errors */
@@ -698,6 +1075,55 @@ ConMsgPrintfV(
     return Len;
 }
 
+/**
+ * @name ConMsgPrintf
+ *     Formats and writes a message string to a stream. The function requires
+ *     a message definition as input. The message definition can come from a
+ *     buffer passed to the function. It can come from a message table resource
+ *     in an already-loaded module, or the caller can ask the function to search
+ *     the system's message table resource(s) for the message definition.
+ *     Please refer to the Win32 FormatMessage() function for more details.
+ *
+ * @param[in]   Stream
+ *     Stream to which the write operation is issued.
+ *
+ * @param[in]   dwFlags
+ *     The formatting options, and how to interpret the @p lpSource parameter.
+ *     See FormatMessage() for more details. The @b@c FORMAT_MESSAGE_ALLOCATE_BUFFER
+ *     and @b@c FORMAT_MESSAGE_ARGUMENT_ARRAY flags are always ignored.
+ *     The function implicitly uses the @b@c FORMAT_MESSAGE_MAX_WIDTH_MASK flag
+ *     to implement its behaviour.
+ *
+ * @param[in]   lpSource
+ *     The location of the message definition. The type of this parameter
+ *     depends upon the settings in the @p dwFlags parameter.
+ *
+ * @param[in]   dwMessageId
+ *     The message identifier for the requested message. This parameter
+ *     is ignored if @p dwFlags includes @b@c FORMAT_MESSAGE_FROM_STRING.
+ *
+ * @param[in]   dwLanguageId
+ *     The language identifier for the requested message. This parameter
+ *     is ignored if @p dwFlags includes @b@c FORMAT_MESSAGE_FROM_STRING.
+ *
+ * @param[in]   ...
+ *     Additional arguments that can be expected by the function, depending
+ *     on the message string. Each argument is used to replace an
+ *     <em>insert sequence</em> in the message string.
+ *
+ * @remark
+ *     Contrary to printf(), ConPrintf(), ConResPrintf() and associated functions,
+ *     the ConMsg* functions work on format strings that contain <em>insert sequences</em>.
+ *     These sequences extend the standard <em>format specifiers</em> as they
+ *     allow to specify an <em>insert number</em> referring which precise value
+ *     given in arguments to use.
+ *
+ * @return
+ *     Numbers of characters successfully written to @p Stream.
+ *
+ * @see ConPrintf(), ConResPrintf() and associated functions, ConMsgPrintfV(),
+ *      <a href="FormatMessage() (on MSDN)">https://msdn.microsoft.com/en-us/library/windows/desktop/ms679351(v=vs.85).aspx</a>
+ **/
 INT
 __cdecl
 ConMsgPrintf(
@@ -711,14 +1137,334 @@ ConMsgPrintf(
     INT Len;
     va_list args;
 
+    /* Sanitize dwFlags */
+    dwFlags &= ~FORMAT_MESSAGE_ARGUMENT_ARRAY;
+
     va_start(args, dwLanguageId);
-    // ConMsgPrintf2V
     Len = ConMsgPrintfV(Stream,
                         dwFlags,
                         lpSource,
                         dwMessageId,
                         dwLanguageId,
-                        args);
+                        &args);
+    va_end(args);
+
+    return Len;
+}
+
+/**
+ * @name ConResMsgPrintfExV
+ *     Formats and writes a message string to a stream. The function requires
+ *     a message definition as input. Contrary to the ConMsg* or the Win32
+ *     FormatMessage() functions, the message definition comes from a resource
+ *     string table, much like the strings for ConResPrintf(), but is formatted
+ *     according to the rules of ConMsgPrintf().
+ *
+ * @param[in]   Stream
+ *     Stream to which the write operation is issued.
+ *
+ * @param[in]   hInstance
+ *     Optional handle to an instance of the module whose executable file
+ *     contains the string resource. Can be set to NULL to get the handle
+ *     to the application itself.
+ *
+ * @param[in]   dwFlags
+ *     The formatting options, see FormatMessage() for more details.
+ *     The only valid flags are @b@c FORMAT_MESSAGE_ARGUMENT_ARRAY and
+ *     @b@c FORMAT_MESSAGE_IGNORE_INSERTS. All the other flags are internally
+ *     overridden by the function to implement its behaviour.
+ *
+ * @param[in]   uID
+ *     The identifier of the message string. The format string follows the
+ *     same specifications as the @a lpSource format string in ConMsgPrintf().
+ *
+ * @param[in]   LanguageId
+ *     The language identifier of the resource. If this parameter is
+ *     <tt>MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)</tt>, the current language
+ *     associated with the calling thread is used. To specify a language other
+ *     than the current language, use the @c MAKELANGID macro to create this
+ *     parameter.
+ *
+ * @param[in]   args
+ *     Parameter describing a variable number of arguments, initialized
+ *     with va_start(), that can be expected by the function, depending
+ *     on the message string. Each argument is used to replace an
+ *     <em>insert sequence</em> in the message string.
+ *
+ * @remark
+ *     Contrary to printf(), ConPrintf(), ConResPrintf() and associated functions,
+ *     the ConMsg* functions work on format strings that contain <em>insert sequences</em>.
+ *     These sequences extend the standard <em>format specifiers</em> as they
+ *     allow to specify an <em>insert number</em> referring which precise value
+ *     given in arguments to use.
+ *
+ * @return
+ *     Numbers of characters successfully written to @p Stream.
+ *
+ * @see ConPrintf(), ConResPrintf() and associated functions, ConMsgPrintf(),
+ *      <a href="FormatMessage() (on MSDN)">https://msdn.microsoft.com/en-us/library/windows/desktop/ms679351(v=vs.85).aspx</a>
+ **/
+INT
+ConResMsgPrintfExV(
+    IN PCON_STREAM Stream,
+    IN HINSTANCE hInstance OPTIONAL,
+    IN DWORD   dwFlags,
+    IN UINT    uID,
+    IN LANGID  LanguageId,
+    IN va_list *Arguments OPTIONAL)
+{
+    INT Len;
+    DWORD dwLength  = 0;
+    LPWSTR lpMsgBuf = NULL;
+    WCHAR bufSrc[CON_RC_STRING_MAX_SIZE];
+
+    /* Retrieve the string from the resource string table */
+    // NOTE: We may use the special behaviour where nBufMaxSize == 0
+    Len = K32LoadStringExW(hInstance, uID, LanguageId, bufSrc, ARRAYSIZE(bufSrc));
+    if (Len == 0)
+        return Len;
+
+    /* Sanitize dwFlags */
+    dwFlags |= FORMAT_MESSAGE_ALLOCATE_BUFFER; // Always allocate an internal buffer.
+    //
+    // NOTE: Technique taken from eventvwr.c!GetMessageStringFromDll()
+    //
+    dwFlags |= FORMAT_MESSAGE_MAX_WIDTH_MASK;
+
+    /* The string has already been manually loaded */
+    dwFlags &= ~(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM);
+    dwFlags |= FORMAT_MESSAGE_FROM_STRING;
+
+    /*
+     * Retrieve the message string without appending extra newlines.
+     * Use the "safe" FormatMessage version (SEH-protected) to protect
+     * from invalid string parameters.
+     */
+    dwLength = FormatMessageSafeW(dwFlags,
+                                  bufSrc,
+                                  0, 0,
+                                  (LPWSTR)&lpMsgBuf,
+                                  0,
+                                  Arguments);
+
+    Len = (INT)dwLength;
+
+    if (!lpMsgBuf)
+    {
+        // ASSERT(dwLength == 0);
+    }
+    else
+    {
+        // ASSERT(dwLength != 0);
+
+        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;
+}
+
+/**
+ * @name ConResMsgPrintfV
+ *     Formats and writes a message string to a stream. The function requires
+ *     a message definition as input. Contrary to the ConMsg* or the Win32
+ *     FormatMessage() functions, the message definition comes from a resource
+ *     string table, much like the strings for ConResPrintf(), but is formatted
+ *     according to the rules of ConMsgPrintf().
+ *
+ * @param[in]   Stream
+ *     Stream to which the write operation is issued.
+ *
+ * @param[in]   dwFlags
+ *     The formatting options, see FormatMessage() for more details.
+ *     The only valid flags are @b@c FORMAT_MESSAGE_ARGUMENT_ARRAY and
+ *     @b@c FORMAT_MESSAGE_IGNORE_INSERTS. All the other flags are internally
+ *     overridden by the function to implement its behaviour.
+ *
+ * @param[in]   uID
+ *     The identifier of the message string. The format string follows the
+ *     same specifications as the @a lpSource format string in ConMsgPrintf().
+ *
+ * @param[in]   Arguments
+ *     Optional pointer to an array of values describing a variable number of
+ *     arguments, depending on the message string. Each argument is used to
+ *     replace an <em>insert sequence</em> in the message string.
+ *     By default, the @p Arguments parameter is of type @c va_list*, initialized
+ *     with va_start(). The state of the @c va_list argument is undefined upon
+ *     return from the function. To use the @c va_list again, destroy the variable
+ *     argument list pointer using va_end() and reinitialize it with va_start().
+ *     If you do not have a pointer of type @c va_list*, then specify the
+ *     @b@c FORMAT_MESSAGE_ARGUMENT_ARRAY flag and pass a pointer to an array
+ *     of @c DWORD_PTR values; those values are input to the message formatted
+ *     as the insert values. Each insert must have a corresponding element in
+ *     the array.
+ *
+ * @remark
+ *     Contrary to printf(), ConPrintf(), ConResPrintf() and associated functions,
+ *     the ConMsg* functions work on format strings that contain <em>insert sequences</em>.
+ *     These sequences extend the standard <em>format specifiers</em> as they
+ *     allow to specify an <em>insert number</em> referring which precise value
+ *     given in arguments to use.
+ *
+ * @return
+ *     Numbers of characters successfully written to @p Stream.
+ *
+ * @see ConPrintf(), ConResPrintf() and associated functions, ConMsgPrintf(),
+ *      <a href="FormatMessage() (on MSDN)">https://msdn.microsoft.com/en-us/library/windows/desktop/ms679351(v=vs.85).aspx</a>
+ **/
+INT
+ConResMsgPrintfV(
+    IN PCON_STREAM Stream,
+    IN DWORD   dwFlags,
+    IN UINT    uID,
+    IN va_list *Arguments OPTIONAL)
+{
+    return ConResMsgPrintfExV(Stream, NULL /*GetModuleHandleW(NULL)*/,
+                              dwFlags, uID,
+                              MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
+                              Arguments);
+}
+
+/**
+ * @name ConResMsgPrintfEx
+ *     Formats and writes a message string to a stream. The function requires
+ *     a message definition as input. Contrary to the ConMsg* or the Win32
+ *     FormatMessage() functions, the message definition comes from a resource
+ *     string table, much like the strings for ConResPrintf(), but is formatted
+ *     according to the rules of ConMsgPrintf().
+ *
+ * @param[in]   Stream
+ *     Stream to which the write operation is issued.
+ *
+ * @param[in]   hInstance
+ *     Optional handle to an instance of the module whose executable file
+ *     contains the string resource. Can be set to NULL to get the handle
+ *     to the application itself.
+ *
+ * @param[in]   dwFlags
+ *     The formatting options, see FormatMessage() for more details.
+ *     The only valid flag is @b@c FORMAT_MESSAGE_IGNORE_INSERTS.
+ *     All the other flags are internally overridden by the function
+ *     to implement its behaviour.
+ *
+ * @param[in]   uID
+ *     The identifier of the message string. The format string follows the
+ *     same specifications as the @a lpSource format string in ConMsgPrintf().
+ *
+ * @param[in]   LanguageId
+ *     The language identifier of the resource. If this parameter is
+ *     <tt>MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)</tt>, the current language
+ *     associated with the calling thread is used. To specify a language other
+ *     than the current language, use the @c MAKELANGID macro to create this
+ *     parameter.
+ *
+ * @param[in]   ...
+ *     Additional arguments that can be expected by the function, depending
+ *     on the message string. Each argument is used to replace an
+ *     <em>insert sequence</em> in the message string.
+ *
+ * @remark
+ *     Contrary to printf(), ConPrintf(), ConResPrintf() and associated functions,
+ *     the ConMsg* functions work on format strings that contain <em>insert sequences</em>.
+ *     These sequences extend the standard <em>format specifiers</em> as they
+ *     allow to specify an <em>insert number</em> referring which precise value
+ *     given in arguments to use.
+ *
+ * @return
+ *     Numbers of characters successfully written to @p Stream.
+ *
+ * @see ConPrintf(), ConResPrintf() and associated functions, ConMsgPrintf(),
+ *      <a href="FormatMessage() (on MSDN)">https://msdn.microsoft.com/en-us/library/windows/desktop/ms679351(v=vs.85).aspx</a>
+ **/
+INT
+__cdecl
+ConResMsgPrintfEx(
+    IN PCON_STREAM Stream,
+    IN HINSTANCE hInstance OPTIONAL,
+    IN DWORD  dwFlags,
+    IN UINT   uID,
+    IN LANGID LanguageId,
+    ...)
+{
+    INT Len;
+    va_list args;
+
+    /* Sanitize dwFlags */
+    dwFlags &= ~FORMAT_MESSAGE_ARGUMENT_ARRAY;
+
+    va_start(args, LanguageId);
+    Len = ConResMsgPrintfExV(Stream,
+                             hInstance,
+                             dwFlags,
+                             uID,
+                             LanguageId,
+                             &args);
+    va_end(args);
+
+    return Len;
+}
+
+/**
+ * @name ConResMsgPrintf
+ *     Formats and writes a message string to a stream. The function requires
+ *     a message definition as input. Contrary to the ConMsg* or the Win32
+ *     FormatMessage() functions, the message definition comes from a resource
+ *     string table, much like the strings for ConResPrintf(), but is formatted
+ *     according to the rules of ConMsgPrintf().
+ *
+ * @param[in]   Stream
+ *     Stream to which the write operation is issued.
+ *
+ * @param[in]   dwFlags
+ *     The formatting options, see FormatMessage() for more details.
+ *     The only valid flag is @b@c FORMAT_MESSAGE_IGNORE_INSERTS.
+ *     All the other flags are internally overridden by the function
+ *     to implement its behaviour.
+ *
+ * @param[in]   uID
+ *     The identifier of the message string. The format string follows the
+ *     same specifications as the @a lpSource format string in ConMsgPrintf().
+ *
+ * @param[in]   ...
+ *     Additional arguments that can be expected by the function, depending
+ *     on the message string. Each argument is used to replace an
+ *     <em>insert sequence</em> in the message string.
+ *
+ * @remark
+ *     Contrary to printf(), ConPrintf(), ConResPrintf() and associated functions,
+ *     the ConMsg* functions work on format strings that contain <em>insert sequences</em>.
+ *     These sequences extend the standard <em>format specifiers</em> as they
+ *     allow to specify an <em>insert number</em> referring which precise value
+ *     given in arguments to use.
+ *
+ * @return
+ *     Numbers of characters successfully written to @p Stream.
+ *
+ * @see ConPrintf(), ConResPrintf() and associated functions, ConMsgPrintf(),
+ *      <a href="FormatMessage() (on MSDN)">https://msdn.microsoft.com/en-us/library/windows/desktop/ms679351(v=vs.85).aspx</a>
+ **/
+INT
+__cdecl
+ConResMsgPrintf(
+    IN PCON_STREAM Stream,
+    IN DWORD dwFlags,
+    IN UINT  uID,
+    ...)
+{
+    INT Len;
+    va_list args;
+
+    /* Sanitize dwFlags */
+    dwFlags &= ~FORMAT_MESSAGE_ARGUMENT_ARRAY;
+
+    va_start(args, uID);
+    Len = ConResMsgPrintfV(Stream, dwFlags, uID, &args);
     va_end(args);
 
     return Len;
index a4099e2..47a3e06 100644 (file)
@@ -8,6 +8,13 @@
  *              Copyright 2017-2018 Hermes Belusca-Maito
  */
 
+/**
+ * @file    outstream.h
+ * @ingroup ConUtils
+ *
+ * @brief   Console I/O utility API -- Output
+ **/
+
 #ifndef __OUTSTREAM_H__
 #define __OUTSTREAM_H__
 
@@ -37,22 +44,18 @@ typedef struct _CON_STREAM CON_STREAM, *PCON_STREAM;
 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);
+    IN DWORD  len);
 
 INT
 ConStreamWrite(
     IN PCON_STREAM Stream,
     IN PTCHAR szStr,
-    IN DWORD len);
+    IN DWORD  len);
 
 INT
 ConPuts(
@@ -63,7 +66,7 @@ INT
 ConPrintfV(
     IN PCON_STREAM Stream,
     IN LPWSTR  szStr,
-    IN va_list args); // arg_ptr
+    IN va_list args);
 
 INT
 __cdecl
@@ -76,7 +79,8 @@ INT
 ConResPutsEx(
     IN PCON_STREAM Stream,
     IN HINSTANCE hInstance OPTIONAL,
-    IN UINT uID);
+    IN UINT   uID,
+    IN LANGID LanguageId);
 
 INT
 ConResPuts(
@@ -88,20 +92,22 @@ ConResPrintfExV(
     IN PCON_STREAM Stream,
     IN HINSTANCE hInstance OPTIONAL,
     IN UINT    uID,
-    IN va_list args); // arg_ptr
+    IN LANGID  LanguageId,
+    IN va_list args);
 
 INT
 ConResPrintfV(
     IN PCON_STREAM Stream,
     IN UINT    uID,
-    IN va_list args); // arg_ptr
+    IN va_list args);
 
 INT
 __cdecl
 ConResPrintfEx(
     IN PCON_STREAM Stream,
     IN HINSTANCE hInstance OPTIONAL,
-    IN UINT uID,
+    IN UINT   uID,
+    IN LANGID LanguageId,
     ...);
 
 INT
@@ -126,7 +132,7 @@ ConMsgPrintf2V(
     IN LPCVOID lpSource OPTIONAL,
     IN DWORD   dwMessageId,
     IN DWORD   dwLanguageId,
-    IN va_list args); // arg_ptr
+    IN va_list args);
 
 INT
 ConMsgPrintfV(
@@ -135,7 +141,7 @@ ConMsgPrintfV(
     IN LPCVOID lpSource OPTIONAL,
     IN DWORD   dwMessageId,
     IN DWORD   dwLanguageId,
-    IN va_list args); // arg_ptr
+    IN va_list *Arguments OPTIONAL);
 
 INT
 __cdecl
@@ -147,6 +153,40 @@ ConMsgPrintf(
     IN DWORD   dwLanguageId,
     ...);
 
+INT
+ConResMsgPrintfExV(
+    IN PCON_STREAM Stream,
+    IN HINSTANCE hInstance OPTIONAL,
+    IN DWORD   dwFlags,
+    IN UINT    uID,
+    IN LANGID  LanguageId,
+    IN va_list *Arguments OPTIONAL);
+
+INT
+ConResMsgPrintfV(
+    IN PCON_STREAM Stream,
+    IN DWORD   dwFlags,
+    IN UINT    uID,
+    IN va_list *Arguments OPTIONAL);
+
+INT
+__cdecl
+ConResMsgPrintfEx(
+    IN PCON_STREAM Stream,
+    IN HINSTANCE hInstance OPTIONAL,
+    IN DWORD  dwFlags,
+    IN UINT   uID,
+    IN LANGID LanguageId,
+    ...);
+
+INT
+__cdecl
+ConResMsgPrintf(
+    IN PCON_STREAM Stream,
+    IN DWORD dwFlags,
+    IN UINT  uID,
+    ...);
+
 
 
 VOID
index ac6bd3f..27cbd72 100644 (file)
@@ -6,6 +6,13 @@
  *              Copyright 2017-2018 Hermes Belusca-Maito
  */
 
+/**
+ * @file    pager.c
+ * @ingroup ConUtils
+ *
+ * @brief   Console/terminal paging functionality.
+ **/
+
 /* FIXME: Temporary HACK before we cleanly support UNICODE functions */
 #define UNICODE
 #define _UNICODE
index 486b520..2773722 100644 (file)
@@ -6,6 +6,13 @@
  *              Copyright 2017-2018 Hermes Belusca-Maito
  */
 
+/**
+ * @file    pager.h
+ * @ingroup ConUtils
+ *
+ * @brief   Console/terminal paging functionality.
+ **/
+
 #ifndef __PAGER_H__
 #define __PAGER_H__
 
index 04f0b6e..b3d1c01 100644 (file)
@@ -6,6 +6,13 @@
  *              Copyright 2017-2018 Hermes Belusca-Maito
  */
 
+/**
+ * @file    screen.c
+ * @ingroup ConUtils
+ *
+ * @brief   Console/terminal screen management.
+ **/
+
 /* FIXME: Temporary HACK before we cleanly support UNICODE functions */
 #define UNICODE
 #define _UNICODE
index 2ab11a7..f2e9714 100644 (file)
@@ -6,6 +6,13 @@
  *              Copyright 2017-2018 Hermes Belusca-Maito
  */
 
+/**
+ * @file    screen.h
+ * @ingroup ConUtils
+ *
+ * @brief   Console/terminal screen management.
+ **/
+
 #ifndef __SCREEN_H__
 #define __SCREEN_H__
 
index 5b843c1..0b137ea 100644 (file)
@@ -8,6 +8,13 @@
  *              Copyright 2017-2018 Hermes Belusca-Maito
  */
 
+/**
+ * @file    stream.c
+ * @ingroup ConUtils
+ *
+ * @brief   Console I/O streams
+ **/
+
 /*
  * Enable this define if you want to only use CRT functions to output
  * UNICODE stream to the console, as in the way explained by
 #include "stream_private.h"
 
 
-/*
- * Console I/O streams
- */
-
 /*
  * Standard console streams, initialized by
  * calls to ConStreamInit/ConInitStdStreams.
index f3804b6..8a2746a 100644 (file)
@@ -8,6 +8,13 @@
  *              Copyright 2017-2018 Hermes Belusca-Maito
  */
 
+/**
+ * @file    stream.h
+ * @ingroup ConUtils
+ *
+ * @brief   Console I/O streams
+ **/
+
 #ifndef __STREAM_H__
 #define __STREAM_H__
 
 extern "C" {
 #endif
 
-/*
- * Console I/O streams
- */
-
 /*
  * See http://archives.miloush.net/michkap/archive/2009/08/14/9869928.html
  * for more information.
index b5dfdee..e6e6fb8 100644 (file)
@@ -7,6 +7,14 @@
  *              Copyright 2017-2018 Hermes Belusca-Maito
  */
 
+/**
+ * @file    utils.c
+ * @ingroup ConUtils
+ *
+ * @brief   General-purpose utility functions (wrappers around
+ *          or reimplementations of Win32 APIs).
+ **/
+
 /* FIXME: Temporary HACK before we cleanly support UNICODE functions */
 #define UNICODE
 #define _UNICODE
 // #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 .
@@ -55,9 +58,10 @@ MultiByteToMultiByte(
  */
 INT
 WINAPI
-K32LoadStringW(
+K32LoadStringExW(
     IN  HINSTANCE hInstance OPTIONAL,
     IN  UINT   uID,
+    IN  LANGID LanguageId,
     OUT LPWSTR lpBuffer,
     IN  INT    nBufferMax)
 {
@@ -71,11 +75,10 @@ K32LoadStringW(
 
     /* 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);
+    hrsrc = FindResourceExW(hInstance,
+                            (LPCWSTR)RT_STRING,
+                            MAKEINTRESOURCEW((LOWORD(uID) >> 4) + 1),
+                            LanguageId);
     if (!hrsrc) return 0;
 
     hmem = LoadResource(hInstance, hrsrc);
@@ -118,6 +121,20 @@ K32LoadStringW(
     return i;
 }
 
+INT
+WINAPI
+K32LoadStringW(
+    IN  HINSTANCE hInstance OPTIONAL,
+    IN  UINT   uID,
+    OUT LPWSTR lpBuffer,
+    IN  INT    nBufferMax)
+{
+    // NOTE: Instead of using LANG_NEUTRAL, one might use LANG_USER_DEFAULT...
+    return K32LoadStringExW(hInstance, uID,
+                            MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
+                            lpBuffer, nBufferMax);
+}
+
 /*
  * "Safe" version of FormatMessageW, that does not crash if a malformed
  * source string is retrieved and then being used for formatting.
@@ -194,18 +211,50 @@ FormatMessageSafeW(
     return dwLength;
 }
 
+/**
+ * @name IsTTYHandle
+ *     Checks whether a handle refers to a valid TTY object.
+ *     A TTY object may be a console or a "communications" (e.g. serial) port.
+ *
+ * @param[in]   hHandle
+ *     Handle to the TTY object to check for.
+ *
+ * @return
+ *     @b@c TRUE when the handle refers to a valid TTY object,
+ *     @b@c FALSE if it does not.
+ *
+ * @remark
+ *     This test is more general than IsConsoleHandle() as it is not limited
+ *     to Win32 console objects only.
+ *
+ * @see IsConsoleHandle()
+ **/
 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
+     * More general test than IsConsoleHandle(). Consoles, as well as serial
+     * (communications) 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);
 }
 
+/**
+ * @name IsConsoleHandle
+ *     Checks whether a handle refers to a valid Win32 console object.
+ *
+ * @param[in]   hHandle
+ *     Handle to the Win32 console object to check for:
+ *     console input buffer, console output buffer.
+ *
+ * @return
+ *     @b@c TRUE when the handle refers to a valid Win32 console object,
+ *     @b@c FALSE if it does not.
+ *
+ * @see IsTTYHandle()
+ **/
 BOOL
 IsConsoleHandle(IN HANDLE hHandle)
 {
index 9f414ab..7985480 100644 (file)
@@ -7,6 +7,14 @@
  *              Copyright 2017-2018 Hermes Belusca-Maito
  */
 
+/**
+ * @file    utils.h
+ * @ingroup ConUtils
+ *
+ * @brief   General-purpose utility functions (wrappers around
+ *          or reimplementations of Win32 APIs).
+ **/
+
 #ifndef __UTILS_H__
 #define __UTILS_H__
 
 extern "C" {
 #endif
 
-/*
- * General-purpose utility functions (wrappers around,
- * or reimplementations of, Win32 APIs).
- */
+INT
+WINAPI
+K32LoadStringExW(
+    IN  HINSTANCE hInstance OPTIONAL,
+    IN  UINT   uID,
+    IN  LANGID LanguageId,
+    OUT LPWSTR lpBuffer,
+    IN  INT    nBufferMax);
 
 INT
 WINAPI