Index: trunk/src/VBox/Runtime/common/err/errmsg-sorter.cpp
===================================================================
--- trunk/src/VBox/Runtime/common/err/errmsg-sorter.cpp	(revision 83984)
+++ trunk/src/VBox/Runtime/common/err/errmsg-sorter.cpp	(revision 84054)
@@ -38,8 +38,59 @@
 
 
+#define ERRMSG_WITH_STRTAB
+#ifdef ERRMSG_WITH_STRTAB
+/*
+ * Include the string table code.
+ */
+# define BLDPROG_STRTAB_MAX_STRLEN           512
+# define BLDPROG_STRTAB_WITH_COMPRESSION
+# define BLDPROG_STRTAB_PURE_ASCII
+# define BLDPROG_STRTAB_WITH_CAMEL_WORDS
+# include <iprt/bldprog-strtab-template.cpp.h>
+#endif
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+/** Used for raw-input and sorting. */
+typedef struct RTSTATUSMSGINT1
+{
+    /** Pointer to the short message string. */
+    const char     *pszMsgShort;
+    /** Pointer to the full message string. */
+    const char     *pszMsgFull;
+    /** Pointer to the define string. */
+    const char     *pszDefine;
+    /** Status code number. */
+    int             iCode;
+    /** Set if duplicate. */
+    bool            fDuplicate;
+} RTSTATUSMSGINT1;
+typedef RTSTATUSMSGINT1 *PRTSTATUSMSGINT1;
+
+
+/** This is used when building the string table and printing it. */
+typedef struct RTSTATUSMSGINT2
+{
+    /** The short message string. */
+    BLDPROGSTRING   MsgShort;
+    /** The full message string. */
+    BLDPROGSTRING   MsgFull;
+    /** The define string. */
+    BLDPROGSTRING   Define;
+    /** Pointer to the define string. */
+    const char     *pszDefine;
+    /** Status code number. */
+    int             iCode;
+} RTSTATUSMSGINT2;
+typedef RTSTATUSMSGINT2 *PRTSTATUSMSGINT2;
+
+
 /*********************************************************************************************************************************
 *   Global Variables                                                                                                             *
 *********************************************************************************************************************************/
-static RTSTATUSMSG g_aStatusMsgs[] =
+static const char *g_pszProgName = "errmsg-sorter";
+static RTSTATUSMSGINT1 g_aStatusMsgs[] =
 {
 #if !defined(IPRT_NO_ERROR_DATA) && !defined(DOXYGEN_RUNNING)
@@ -51,9 +102,20 @@
 
 
+static RTEXITCODE error(const char *pszFormat,  ...)
+{
+    va_list va;
+    va_start(va, pszFormat);
+    fprintf(stderr, "%s: error: ", g_pszProgName);
+    vfprintf(stderr, pszFormat, va);
+    va_end(va);
+    return RTEXITCODE_FAILURE;
+}
+
+
 /** qsort callback. */
 static int CompareErrMsg(const void *pv1, const void *pv2)
 {
-    PCRTSTATUSMSG p1 = (PCRTSTATUSMSG)pv1;
-    PCRTSTATUSMSG p2 = (PCRTSTATUSMSG)pv2;
+    PRTSTATUSMSGINT1 p1 = (PRTSTATUSMSGINT1)pv1;
+    PRTSTATUSMSGINT1 p2 = (PRTSTATUSMSGINT1)pv2;
     int iDiff;
     if (p1->iCode < p2->iCode)
@@ -103,73 +165,95 @@
 
 
-/**
- * Escapes @a pszString using @a pszBuf as needed.
- * @note Duplicated in errmsg-sorter.cpp.
- */
-static const char *EscapeString(const char *pszString, char *pszBuf, size_t cbBuf)
-{
-    if (strpbrk(pszString, "\n\t\r\"\\") == NULL)
-        return pszString;
-
-    char *pszDst = pszBuf;
-    char  ch;
-    do
-    {
-        ch = *pszString++;
-        switch (ch)
-        {
-            default:
-                *pszDst++ = ch;
-                break;
-            case '\\':
-            case '"':
-                *pszDst++ = '\\';
-                *pszDst++ = ch;
-                break;
-            case '\n':
-                *pszDst++ = '\\';
-                *pszDst++ = 'n';
-                break;
-            case '\t':
-                *pszDst++ = '\\';
-                *pszDst++ = 't';
-                break;
-            case '\r':
-                break; /* drop it */
-        }
-    } while (ch);
-
-    if ((uintptr_t)(pszDst - pszBuf) > cbBuf)
-        fprintf(stderr, "Escape buffer overrun!\n");
-
-    return pszBuf;
-}
-
-
 int main(int argc, char **argv)
 {
     /*
-     * Argument check.
+     * Parse arguments.
      */
-    if (argc != 1 && argc != 2)
+    enum { kMode_All, kMode_NoFullMsg, kMode_OnlyDefines } enmMode;
+    if (argc == 3 && strcmp(argv[1], "--all") == 0)
+        enmMode = kMode_All;
+    else if (argc == 3 && strcmp(argv[1], "--no-full-msg") == 0)
+        enmMode = kMode_NoFullMsg;
+    else if (argc == 3 && strcmp(argv[1], "--only-defines") == 0)
+        enmMode = kMode_OnlyDefines;
+    else
     {
         fprintf(stderr,
                 "syntax error!\n"
-                "Usage: %s [outfile]\n", argv[0]);
+                "Usage: %s <--all|--no-full-msg|--only-defines> <outfile>\n", argv[0]);
         return RTEXITCODE_SYNTAX;
     }
+    const char * const pszOutFile = argv[2];
 
     /*
-     * Sort the table.
+     * Sort the table and mark duplicates.
      */
     qsort(g_aStatusMsgs, RT_ELEMENTS(g_aStatusMsgs), sizeof(g_aStatusMsgs[0]), CompareErrMsg);
+
+    int rcExit = RTEXITCODE_SUCCESS;
+    int iPrev  = INT32_MAX;
+    for (size_t i = 0; i < RT_ELEMENTS(g_aStatusMsgs); i++)
+    {
+        /* Deal with duplicates, trying to eliminate unnecessary *_FIRST, *_LAST,
+           *_LOWEST, and *_HIGHEST entries as well as some deliberate duplicate entries.
+           This means we need to look forward and backwards here. */
+        PRTSTATUSMSGINT1 pMsg = &g_aStatusMsgs[i];
+        if (pMsg->iCode == iPrev && i != 0)
+        {
+            if (IgnoreDuplicateDefine(pMsg->pszDefine))
+            {
+                pMsg->fDuplicate = true;
+                continue;
+            }
+            PRTSTATUSMSGINT1 pPrev = &g_aStatusMsgs[i - 1];
+            rcExit = error("Duplicate value %d - %s and %s\n", iPrev, pMsg->pszDefine, pPrev->pszDefine);
+        }
+        else if (i + 1 < RT_ELEMENTS(g_aStatusMsgs))
+        {
+            PRTSTATUSMSGINT1 pNext = &g_aStatusMsgs[i];
+            if (   pMsg->iCode == pNext->iCode
+                && IgnoreDuplicateDefine(pMsg->pszDefine))
+            {
+                pMsg->fDuplicate = true;
+                continue;
+            }
+        }
+        iPrev = pMsg->iCode;
+        pMsg->fDuplicate = false;
+    }
+
+    /*
+     * Create a string table for it all.
+     */
+    BLDPROGSTRTAB StrTab;
+    if (!BldProgStrTab_Init(&StrTab, RT_ELEMENTS(g_aStatusMsgs) * 3))
+        return error("Out of memory!\n");
+
+    static RTSTATUSMSGINT2 s_aStatusMsgs2[RT_ELEMENTS(g_aStatusMsgs)];
+    size_t                 cStatusMsgs = 0;
+    for (size_t i = 0; i < RT_ELEMENTS(g_aStatusMsgs); i++)
+    {
+        if (!g_aStatusMsgs[i].fDuplicate)
+        {
+            s_aStatusMsgs2[cStatusMsgs].iCode     = g_aStatusMsgs[i].iCode;
+            s_aStatusMsgs2[cStatusMsgs].pszDefine = g_aStatusMsgs[i].pszDefine;
+            BldProgStrTab_AddStringDup(&StrTab, &s_aStatusMsgs2[cStatusMsgs].Define, g_aStatusMsgs[i].pszDefine);
+            if (enmMode != kMode_OnlyDefines)
+            {
+                BldProgStrTab_AddStringDup(&StrTab, &s_aStatusMsgs2[cStatusMsgs].MsgShort, g_aStatusMsgs[i].pszMsgShort);
+                if (enmMode == kMode_All)
+                    BldProgStrTab_AddStringDup(&StrTab, &s_aStatusMsgs2[cStatusMsgs].MsgFull, g_aStatusMsgs[i].pszMsgFull);
+            }
+            cStatusMsgs++;
+        }
+    }
+
+    if (!BldProgStrTab_CompileIt(&StrTab, true))
+        return error("BldProgStrTab_CompileIt failed!\n");
 
     /*
      * Prepare output file.
      */
-    int rcExit = RTEXITCODE_FAILURE;
-    FILE *pOut = stdout;
-    if (argc > 1)
-        pOut = fopen(argv[1], "wt");
+    FILE *pOut = fopen(pszOutFile, "wt");
     if (pOut)
     {
@@ -177,50 +261,72 @@
          * Print the table.
          */
-        static char s_szMsgTmp1[_32K];
-        static char s_szMsgTmp2[_64K];
-        int iPrev = INT32_MAX;
-        for (size_t i = 0; i < RT_ELEMENTS(g_aStatusMsgs); i++)
-        {
-            PCRTSTATUSMSG pMsg = &g_aStatusMsgs[i];
-
-            /* Deal with duplicates, trying to eliminate unnecessary *_FIRST, *_LAST,
-               *_LOWEST, and *_HIGHEST entries as well as some deliberate duplicate entries.
-               This means we need to look forward and backwards here. */
-            if (pMsg->iCode == iPrev && i != 0)
-            {
-                if (IgnoreDuplicateDefine(pMsg->pszDefine))
-                    continue;
-                PCRTSTATUSMSG pPrev = &g_aStatusMsgs[i - 1];
-                fprintf(stderr, "%s: warning: Duplicate value %d - %s and %s\n",
-                        argv[0], iPrev, pMsg->pszDefine, pPrev->pszDefine);
-            }
-            else if (i + 1 < RT_ELEMENTS(g_aStatusMsgs))
-            {
-                PCRTSTATUSMSG pNext = &g_aStatusMsgs[i];
-                if (   pMsg->iCode == pNext->iCode
-                    && IgnoreDuplicateDefine(pMsg->pszDefine))
-                    continue;
-            }
-            iPrev = pMsg->iCode;
-
-            /* Produce the output: */
-            fprintf(pOut, "/*%8d:*/ ENTRY(\"%s\", \"%s\", \"%s\", %s),\n",
-                    pMsg->iCode,
-                    EscapeString(pMsg->pszMsgShort, s_szMsgTmp1, sizeof(s_szMsgTmp1)),
-                    EscapeString(pMsg->pszMsgFull, s_szMsgTmp2, sizeof(s_szMsgTmp2)),
-                    pMsg->pszDefine, pMsg->pszDefine);
-
-        }
+        fprintf(pOut,
+                "\n"
+                "typedef struct RTMSGENTRYINT\n"
+                "{\n"
+                "    uint32_t offDefine : 20;\n"
+                "    uint32_t cchDefine : 9;\n"
+                "%s"
+                "%s"
+                "    int32_t  iCode;\n"
+                "} RTMSGENTRYINT;\n"
+                "typedef RTMSGENTRYINT *PCRTMSGENTRYINT;\n"
+                "\n"
+                "static const RTMSGENTRYINT g_aStatusMsgs[] =\n"
+                "{\n"
+                ,
+                enmMode != kMode_OnlyDefines
+                ? "    uint32_t offMsgShort : 23;\n"
+                  "    uint32_t cchMsgShort : 9;\n" : "",
+                enmMode == kMode_All
+                ? "    uint32_t offMsgFull  : 23;\n"
+                  "    uint32_t cchMsgFull  : 9;\n" : "");
+
+        if (enmMode == kMode_All)
+            for (size_t i = 0; i < cStatusMsgs; i++)
+                fprintf(pOut, "/*%8d:*/ { %#08x, %3u, %#08x, %3u, %#08x, %3u, %s },\n",
+                        s_aStatusMsgs2[i].iCode,
+                        s_aStatusMsgs2[i].Define.offStrTab,
+                        (unsigned)s_aStatusMsgs2[i].Define.cchString,
+                        s_aStatusMsgs2[i].MsgShort.offStrTab,
+                        (unsigned)s_aStatusMsgs2[i].MsgShort.cchString,
+                        s_aStatusMsgs2[i].MsgFull.offStrTab,
+                        (unsigned)s_aStatusMsgs2[i].MsgFull.cchString,
+                        s_aStatusMsgs2[i].pszDefine);
+        else if (enmMode == kMode_NoFullMsg)
+            for (size_t i = 0; i < cStatusMsgs; i++)
+                fprintf(pOut, "/*%8d:*/ { %#08x, %3u, %#08x, %3u, %s },\n",
+                        s_aStatusMsgs2[i].iCode,
+                        s_aStatusMsgs2[i].Define.offStrTab,
+                        (unsigned)s_aStatusMsgs2[i].Define.cchString,
+                        s_aStatusMsgs2[i].MsgShort.offStrTab,
+                        (unsigned)s_aStatusMsgs2[i].MsgShort.cchString,
+                        s_aStatusMsgs2[i].pszDefine);
+        else if (enmMode == kMode_OnlyDefines)
+            for (size_t i = 0; i < cStatusMsgs; i++)
+                fprintf(pOut, "/*%8d:*/ { %#08x, %3u, %s },\n",
+                        s_aStatusMsgs2[i].iCode,
+                        s_aStatusMsgs2[i].Define.offStrTab,
+                        (unsigned)s_aStatusMsgs2[i].Define.cchString,
+                        s_aStatusMsgs2[i].pszDefine);
+        else
+            return error("Unsupported message selection (%d)!\n", enmMode);
+        fprintf(pOut,
+                "};\n"
+                "\n");
+
+        BldProgStrTab_WriteStringTable(&StrTab, pOut, "static ", "g_", "StatusMsgStrTab");
 
         /*
          * Close the output file and we're done.
          */
-        if (fclose(pOut) == 0)
-            rcExit = RTEXITCODE_SUCCESS;
-        else
-            fprintf(stderr, "%s: Failed to flush/close '%s' after writing it!\n", argv[0], argv[1]);
+        fflush(pOut);
+        if (ferror(pOut))
+            rcExit = error("Error writing '%s'!\n", pszOutFile);
+        if (fclose(pOut) != 0)
+            rcExit = error("Failed to close '%s' after writing it!\n", pszOutFile);
     }
     else
-        fprintf(stderr, "%s: Failed to open '%s' for writing!\n", argv[0], argv[1]);
+        rcExit = error("Failed to open '%s' for writing!\n", pszOutFile);
     return rcExit;
 }
Index: trunk/src/VBox/Runtime/common/err/errmsg.cpp
===================================================================
--- trunk/src/VBox/Runtime/common/err/errmsg.cpp	(revision 83984)
+++ trunk/src/VBox/Runtime/common/err/errmsg.cpp	(revision 84054)
@@ -36,17 +36,14 @@
 #include <VBox/err.h>
 
+#include <iprt/bldprog-strtab.h>
+
 
 /*********************************************************************************************************************************
 *   Defined Constants And Macros                                                                                                 *
 *********************************************************************************************************************************/
-#ifdef IPRT_ERRMSG_DEFINES_ONLY
-# define ENTRY(a_pszMsgShort, a_pszMsgFull, a_pszDefine, a_iCode) \
-    { a_pszDefine, a_pszDefine, a_pszDefine, a_iCode }
-#elif defined(IN_RT_STATIC) /* Skip the full message in static builds to save space. */
-# define ENTRY(a_pszMsgShort, a_pszMsgFull, a_pszDefine, a_iCode) \
-    { a_pszMsgShort, a_pszMsgShort, a_pszDefine, a_iCode }
-#else
-# define ENTRY(a_pszMsgShort, a_pszMsgFull, a_pszDefine, a_iCode) \
-    { a_pszMsgShort, a_pszMsgFull, a_pszDefine, a_iCode }
+#if (defined(IN_RT_STATIC) || defined(IPRT_ERRMSG_DEFINES_ONLY)) && !defined(IPRT_ERRMSG_NO_FULL_MSG)
+/** Skip the full message in static builds to save space.
+ * This is defined when IPRT_ERRMSG_DEFINES_ONLY is defined. */
+# define IPRT_ERRMSG_NO_FULL_MSG
 #endif
 
@@ -55,44 +52,37 @@
 *   Global Variables                                                                                                             *
 *********************************************************************************************************************************/
-/** Array of messages.
- * The data is generated by a sed script.
- */
-static const RTSTATUSMSG  g_aStatusMsgs[] =
-{
-#if !defined(IPRT_NO_ERROR_DATA) && !defined(DOXYGEN_RUNNING)
-# include "errmsgdata-sorted.h"
-#else
-    { "Success.", "Success.", "VINF_SUCCESS", 0 },
-#endif
+#ifdef IPRT_NO_ERROR_DATA
+/* Cook data just for VINF_SUCCESS so that code below compiles fine. */
+static const char            g_achStrTabData[] = { "VINF_SUCCESS" };
+static const RTBLDPROGSTRTAB g_StatusMsgStrTab = { g_achStrTabData, sizeof(g_achStrTabData) - 1, 0, NULL };
+static const struct
+{
+    int16_t     iCode;
+    uint8_t     offDefine;
+    uint8_t     cchDefine;
+    uint8_t     offMsgShort;
+    uint8_t     cchMsgShort;
+    uint8_t     offMsgFull;
+    uint8_t     cchMsgFull;
+} g_aStatusMsgs[] =
+{
+    { VINF_SUCCESS, 0, 12, 0, 12, 0, 12, },
 };
-
-
-/** Temporary buffers to format unknown messages in.
- * @{
- */
-static char                 g_aszUnknownStr[8][64];
-static RTSTATUSMSG          g_aUnknownMsgs[8] =
-{
-    { &g_aszUnknownStr[0][0], &g_aszUnknownStr[0][0], &g_aszUnknownStr[0][0], 0 },
-    { &g_aszUnknownStr[1][0], &g_aszUnknownStr[1][0], &g_aszUnknownStr[1][0], 0 },
-    { &g_aszUnknownStr[2][0], &g_aszUnknownStr[2][0], &g_aszUnknownStr[2][0], 0 },
-    { &g_aszUnknownStr[3][0], &g_aszUnknownStr[3][0], &g_aszUnknownStr[3][0], 0 },
-    { &g_aszUnknownStr[4][0], &g_aszUnknownStr[4][0], &g_aszUnknownStr[4][0], 0 },
-    { &g_aszUnknownStr[5][0], &g_aszUnknownStr[5][0], &g_aszUnknownStr[5][0], 0 },
-    { &g_aszUnknownStr[6][0], &g_aszUnknownStr[6][0], &g_aszUnknownStr[6][0], 0 },
-    { &g_aszUnknownStr[7][0], &g_aszUnknownStr[7][0], &g_aszUnknownStr[7][0], 0 },
-};
-/** Last used index in g_aUnknownMsgs. */
-static volatile uint32_t    g_iUnknownMsgs;
-/** @} */
+#elif defined(IPRT_ERRMSG_DEFINES_ONLY)
+# include "errmsgdata-only-defines.h"
+#elif defined(IPRT_ERRMSG_NO_FULL_MSG)
+# include "errmsgdata-no-full-msg.h"
+#else
+# include "errmsgdata-all.h"
+#endif
 
 
 /**
- * Get the message corresponding to a given status code.
+ * Looks up the message table entry for @a rc.
  *
- * @returns Pointer to read-only message description.
- * @param   rc      The status code.
- */
-RTDECL(PCRTSTATUSMSG) RTErrGet(int rc)
+ * @returns index into g_aStatusMsgs on success, ~(size_t)0 if not found.
+ * @param   rc      The status code to locate the entry for.
+ */
+static size_t rtErrLookup(int rc)
 {
     /*
@@ -121,5 +111,5 @@
         }
         else
-            return &g_aStatusMsgs[i];
+            return i;
     }
 
@@ -129,11 +119,210 @@
 #endif
 
-    /*
-     * Need to use the temporary stuff.
-     */
-    int iMsg = ASMAtomicXchgU32(&g_iUnknownMsgs, (g_iUnknownMsgs + 1) % RT_ELEMENTS(g_aUnknownMsgs));
-    RTStrPrintf(&g_aszUnknownStr[iMsg][0], sizeof(g_aszUnknownStr[iMsg]), "Unknown Status %d (%#x)", rc, rc);
-    return &g_aUnknownMsgs[iMsg];
-}
-RT_EXPORT_SYMBOL(RTErrGet);
-
+    return ~(size_t)0;
+}
+
+
+RTDECL(bool)  RTErrIsKnown(int rc)
+{
+    return rtErrLookup(rc) != ~(size_t)0;
+}
+RT_EXPORT_SYMBOL(RTErrIsKnown);
+
+
+RTDECL(ssize_t) RTErrQueryDefine(int rc, char *pszBuf, size_t cbBuf, bool fFailIfUnknown)
+{
+    size_t idx = rtErrLookup(rc);
+    if (idx != ~(size_t)0)
+        return RTBldProgStrTabQueryString(&g_StatusMsgStrTab,
+                                          g_aStatusMsgs[idx].offDefine, g_aStatusMsgs[idx].cchDefine,
+                                          pszBuf, cbBuf);
+    if (fFailIfUnknown)
+        return VERR_NOT_FOUND;
+    return RTStrFormatU32(pszBuf, cbBuf, rc, 10, 0, 0, RTSTR_F_VALSIGNED);
+}
+RT_EXPORT_SYMBOL(RTErrQueryDefine);
+
+
+/**
+ * Helper for rtErrQueryMsgNotFound.
+ */
+DECLINLINE(ssize_t) rtErrQueryCopyHelper(char **ppszBuf, size_t *pcbBuf, const char *pszSrc, size_t cchSrc, ssize_t cchRet)
+{
+    char   *pszDst = *ppszBuf;
+    size_t  cbDst  = *pcbBuf;
+    if (cbDst > cchSrc)
+    {
+        memcpy(pszDst, pszSrc, cchSrc);
+        cbDst   -= cchSrc;
+        pszDst  += cchSrc;
+        cchRet  += cchSrc;
+        *pszDst  = '\0';
+    }
+    else
+    {
+        while (cbDst > 1 && cchSrc > 0)
+        {
+            *pszDst++ = *pszSrc++;
+            cchSrc--;
+            cbDst--;
+        }
+        if (cbDst > 0)
+            *pszDst = '\0';
+        cchRet = VERR_BUFFER_OVERFLOW;
+    }
+    *ppszBuf = pszDst;
+    *pcbBuf  = cbDst;
+    return cchRet;
+}
+
+
+/**
+ * RTErrQueryMsgShort & RTErrQueryMsgFull helper.
+ */
+DECL_NO_INLINE(static, ssize_t) rtErrQueryMsgNotFound(int rc, char *pszBuf, size_t cbBuf)
+{
+    /* Unknown Status %d (%#x) */
+    ssize_t cchRet = rtErrQueryCopyHelper(&pszBuf, &cbBuf, RT_STR_TUPLE("Unknown Status "), 0);
+    char   szValue[64];
+    size_t cchValue = (size_t)RTStrFormatU32(szValue, sizeof(szValue), rc, 10, 0, 0, RTSTR_F_VALSIGNED);
+    cchRet = rtErrQueryCopyHelper(&pszBuf, &cbBuf, szValue, cchValue, cchRet);
+    cchRet = rtErrQueryCopyHelper(&pszBuf, &cbBuf, RT_STR_TUPLE(" ("), cchRet);
+    cchValue = (size_t)RTStrFormatU32(szValue, sizeof(szValue), rc, 16, 0, 0, RTSTR_F_SPECIAL);
+    cchRet = rtErrQueryCopyHelper(&pszBuf, &cbBuf, szValue, cchValue, cchRet);
+    cchRet = rtErrQueryCopyHelper(&pszBuf, &cbBuf, RT_STR_TUPLE(")"), cchRet);
+    return cchRet;
+}
+
+
+RTDECL(ssize_t) RTErrQueryMsgShort(int rc, char *pszBuf, size_t cbBuf, bool fFailIfUnknown)
+{
+    size_t idx = rtErrLookup(rc);
+    if (idx != ~(size_t)0)
+#ifdef IPRT_ERRMSG_DEFINES_ONLY
+        return RTBldProgStrTabQueryString(&g_StatusMsgStrTab,
+                                          g_aStatusMsgs[idx].offDefine, g_aStatusMsgs[idx].cchDefine,
+                                          pszBuf, cbBuf);
+#else
+    return RTBldProgStrTabQueryString(&g_StatusMsgStrTab,
+                                      g_aStatusMsgs[idx].offMsgShort, g_aStatusMsgs[idx].cchMsgShort,
+                                      pszBuf, cbBuf);
+#endif
+    if (fFailIfUnknown)
+        return VERR_NOT_FOUND;
+    return rtErrQueryMsgNotFound(rc, pszBuf, cbBuf);
+}
+RT_EXPORT_SYMBOL(RTErrQueryMsgShort);
+
+
+RTDECL(ssize_t) RTErrQueryMsgFull(int rc, char *pszBuf, size_t cbBuf, bool fFailIfUnknown)
+{
+#if defined(IPRT_ERRMSG_DEFINES_ONLY) || defined(IPRT_ERRMSG_NO_FULL_MSG)
+    return RTErrQueryMsgShort(rc, pszBuf, cbBuf, fFailIfUnknown);
+#else
+    size_t idx = rtErrLookup(rc);
+    if (idx != ~(size_t)0)
+        return RTBldProgStrTabQueryString(&g_StatusMsgStrTab,
+                                          g_aStatusMsgs[idx].offMsgFull, g_aStatusMsgs[idx].cchMsgFull,
+                                          pszBuf, cbBuf);
+    if (fFailIfUnknown)
+        return VERR_NOT_FOUND;
+    return rtErrQueryMsgNotFound(rc, pszBuf, cbBuf);
+#endif
+}
+RT_EXPORT_SYMBOL(RTErrQueryMsgShort);
+
+
+RTDECL(size_t) RTErrFormatDefine(int rc, PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, char *pszTmp, size_t cbTmp)
+{
+    size_t idx = rtErrLookup(rc);
+    if (idx != ~(size_t)0)
+        return RTBldProgStrTabQueryOutput(&g_StatusMsgStrTab,
+                                          g_aStatusMsgs[idx].offDefine, g_aStatusMsgs[idx].cchDefine,
+                                          pfnOutput, pvArgOutput);
+    size_t cchValue = (size_t)RTStrFormatU32(pszTmp, cbTmp, rc, 10, 0, 0, RTSTR_F_VALSIGNED);
+    return pfnOutput(pvArgOutput, pszTmp, cchValue);
+}
+RT_EXPORT_SYMBOL(RTErrFormatDefine);
+
+
+/**
+ * RTErrFormatMsgShort & RTErrFormatMsgFull helper.
+ */
+static size_t rtErrFormatMsgNotFound(int rc, PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, char *pszTmp, size_t cbTmp)
+{
+    size_t cchRet = pfnOutput(pvArgOutput, RT_STR_TUPLE("Unknown Status "));
+    size_t cchValue = (size_t)RTStrFormatU32(pszTmp, cbTmp, rc, 10, 0, 0, RTSTR_F_VALSIGNED);
+    cchRet  += pfnOutput(pvArgOutput, pszTmp, cchValue);
+    cchRet  += pfnOutput(pvArgOutput, RT_STR_TUPLE(" ("));
+    cchValue = (size_t)RTStrFormatU32(pszTmp, cbTmp, rc, 16, 0, 0, RTSTR_F_SPECIAL);
+    cchRet  += pfnOutput(pvArgOutput, pszTmp, cchValue);
+    cchRet  += pfnOutput(pvArgOutput, RT_STR_TUPLE(")"));
+    return cchRet;
+}
+
+
+RTDECL(size_t) RTErrFormatMsgShort(int rc, PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, char *pszTmp, size_t cbTmp)
+{
+    size_t idx = rtErrLookup(rc);
+    if (idx != ~(size_t)0)
+#ifndef IPRT_ERRMSG_DEFINES_ONLY
+        return RTBldProgStrTabQueryOutput(&g_StatusMsgStrTab,
+                                          g_aStatusMsgs[idx].offMsgShort, g_aStatusMsgs[idx].cchMsgShort,
+                                          pfnOutput, pvArgOutput);
+#else
+        return RTBldProgStrTabQueryOutput(&g_StatusMsgStrTab,
+                                          g_aStatusMsgs[idx].offDefine, g_aStatusMsgs[idx].cchDefine,
+                                          pfnOutput, pvArgOutput);
+#endif
+    return rtErrFormatMsgNotFound(rc, pfnOutput, pvArgOutput, pszTmp, cbTmp);
+}
+RT_EXPORT_SYMBOL(RTErrFormatMsgShort);
+
+
+RTDECL(size_t) RTErrFormatMsgFull(int rc, PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, char *pszTmp, size_t cbTmp)
+{
+#ifdef IPRT_ERRMSG_NO_FULL_MSG
+    return RTErrFormatMsgShort(rc, pfnOutput, pvArgOutput, pszTmp, cbTmp);
+#else
+    size_t idx = rtErrLookup(rc);
+    if (idx != ~(size_t)0)
+        return RTBldProgStrTabQueryOutput(&g_StatusMsgStrTab,
+                                          g_aStatusMsgs[idx].offMsgFull, g_aStatusMsgs[idx].cchMsgFull,
+                                          pfnOutput, pvArgOutput);
+    return rtErrFormatMsgNotFound(rc, pfnOutput, pvArgOutput, pszTmp, cbTmp);
+#endif
+}
+RT_EXPORT_SYMBOL(RTErrFormatMsgFull);
+
+
+RTDECL(size_t) RTErrFormatMsgAll(int rc, PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, char *pszTmp, size_t cbTmp)
+{
+    size_t idx = rtErrLookup(rc);
+    if (idx != ~(size_t)0)
+    {
+        size_t cchValue;
+        size_t cchRet = RTBldProgStrTabQueryOutput(&g_StatusMsgStrTab,
+                                                   g_aStatusMsgs[idx].offDefine, g_aStatusMsgs[idx].cchDefine,
+                                                   pfnOutput, pvArgOutput);
+        cchRet += pfnOutput(pvArgOutput, RT_STR_TUPLE(" ("));
+        cchValue = (size_t)RTStrFormatU32(pszTmp, cbTmp, rc, 10, 0, 0, RTSTR_F_VALSIGNED);
+        cchRet += pfnOutput(pvArgOutput, pszTmp, cchValue);
+#ifdef IPRT_ERRMSG_DEFINES_ONLY
+        cchRet += pfnOutput(pvArgOutput, RT_STR_TUPLE(")"));
+#elif defined(IPRT_ERRMSG_NO_FULL_MSG)
+        cchRet += pfnOutput(pvArgOutput, RT_STR_TUPLE(") - "));
+        cchRet += RTBldProgStrTabQueryOutput(&g_StatusMsgStrTab,
+                                             g_aStatusMsgs[idx].offMsgShort, g_aStatusMsgs[idx].cchMsgShort,
+                                             pfnOutput, pvArgOutput);
+#else
+        cchRet += pfnOutput(pvArgOutput, RT_STR_TUPLE(") - "));
+        cchRet += RTBldProgStrTabQueryOutput(&g_StatusMsgStrTab,
+                                             g_aStatusMsgs[idx].offMsgFull, g_aStatusMsgs[idx].cchMsgFull,
+                                             pfnOutput, pvArgOutput);
+#endif
+        return cchRet;
+    }
+    return rtErrFormatMsgNotFound(rc, pfnOutput, pvArgOutput, pszTmp, cbTmp);
+}
+RT_EXPORT_SYMBOL(RTErrFormatMsgAll);
+
