Index: /trunk/include/iprt/base64.h
===================================================================
--- /trunk/include/iprt/base64.h	(revision 84285)
+++ /trunk/include/iprt/base64.h	(revision 84286)
@@ -143,8 +143,18 @@
  * data produced by RTBase64Encode().
  *
- * @returns The Base64 string length.
+ * @returns The Base64 string length, excluding the terminator.
  * @param   cbData      The number of bytes to encode.
  */
 RTDECL(size_t) RTBase64EncodedLength(size_t cbData);
+
+/**
+ * Calculates the UTF-16 length of the Base64 encoding of a given number of
+ * bytes of data produced by RTBase64EncodeUtf16().
+ *
+ * @returns The Base64 UTF-16 string length (in RTUTF16 units), excluding the
+ *          terminator.
+ * @param   cbData      The number of bytes to encode.
+ */
+RTDECL(size_t) RTBase64EncodedUtf16Length(size_t cbData);
 
 /**
@@ -152,9 +162,20 @@
  * data produced by RTBase64EncodeEx() with the same @a fFlags.
  *
- * @returns The Base64 string length.
+ * @returns The Base64 string length, excluding the terminator.
  * @param   cbData      The number of bytes to encode.
  * @param   fFlags      Flags, any combination of the RTBASE64_FLAGS \#defines.
  */
 RTDECL(size_t) RTBase64EncodedLengthEx(size_t cbData, uint32_t fFlags);
+
+/**
+ * Calculates the UTF-16 length of the Base64 encoding of a given number of
+ * bytes of data produced by RTBase64EncodeUtf16Ex() with the same @a fFlags.
+ *
+ * @returns The Base64 UTF-16 string length (in RTUTF16 units), excluding the
+ *          terminator.
+ * @param   cbData      The number of bytes to encode.
+ * @param   fFlags      Flags, any combination of the RTBASE64_FLAGS \#defines.
+ */
+RTDECL(size_t) RTBase64EncodedUtf16LengthEx(size_t cbData, uint32_t fFlags);
 
 /**
@@ -177,4 +198,24 @@
 
 /**
+ * Encodes the specifed data into a Base64 UTF-16 string, the caller supplies
+ * the output buffer.
+ *
+ * This is equivalent to calling RTBase64EncodeUtf16Ex() with no flags.
+ *
+ * @returns IRPT status code.
+ * @retval  VERR_BUFFER_OVERFLOW if the output buffer is too small. The buffer
+ *          may contain an invalid Base64 string.
+ *
+ * @param   pvData      The data to encode.
+ * @param   cbData      The number of bytes to encode.
+ * @param   pwszBuf     Where to put the Base64 UTF-16 string.
+ * @param   cwcBuf      The size of the output buffer in RTUTF16 units,
+ *                      including the terminator.
+ * @param   pcwcActual  The actual number of characters returned (excluding the
+ *                      terminator).  Optional.
+ */
+RTDECL(int) RTBase64EncodeUtf16(const void *pvData, size_t cbData, PRTUTF16 pwszBuf, size_t cwcBuf, size_t *pcwcActual);
+
+/**
  * Encodes the specifed data into a Base64 string, the caller supplies the
  * output buffer.
@@ -189,9 +230,31 @@
  * @param   pszBuf      Where to put the Base64 string.
  * @param   cbBuf       The size of the output buffer, including the terminator.
- * @param   pcchActual  The actual number of characters returned.
+ * @param   pcchActual  The actual number of characters returned (excluding the
+ *                      terminator).  Optional.
  */
 RTDECL(int) RTBase64EncodeEx(const void *pvData, size_t cbData, uint32_t fFlags,
                              char *pszBuf, size_t cbBuf, size_t *pcchActual);
 
+/**
+ * Encodes the specifed data into a Base64 UTF-16 string, the caller supplies
+ * the output buffer.
+ *
+ * @returns IRPT status code.
+ * @retval  VERR_BUFFER_OVERFLOW if the output buffer is too small. The buffer
+ *          may contain an invalid Base64 string.
+ *
+ * @param   pvData      The data to encode.
+ * @param   cbData      The number of bytes to encode.
+ * @param   fFlags      Flags, any combination of the RTBASE64_FLAGS \#defines.
+ * @param   pwszBuf     Where to put the Base64 UTF-16 string.
+ * @param   cwcBuf      The size of the output buffer in RTUTF16 units,
+ *                      including the terminator.
+ * @param   pcwcActual  The actual number of characters returned (excluding the
+ *                      terminator).  Optional.
+ */
+RTDECL(int) RTBase64EncodeUtf16Ex(const void *pvData, size_t cbData, uint32_t fFlags,
+                                  PRTUTF16 pwszBuf, size_t cwcBuf, size_t *pcwcActual);
+
+
 /** @}  */
 
Index: /trunk/include/iprt/mangling.h
===================================================================
--- /trunk/include/iprt/mangling.h	(revision 84285)
+++ /trunk/include/iprt/mangling.h	(revision 84286)
@@ -581,4 +581,8 @@
 # define RTBase64EncodedLength                          RT_MANGLER(RTBase64EncodedLength)
 # define RTBase64EncodedLengthEx                        RT_MANGLER(RTBase64EncodedLengthEx)
+# define RTBase64EncodeUtf16                            RT_MANGLER(RTBase64EncodeUtf16)
+# define RTBase64EncodeUtf16Ex                          RT_MANGLER(RTBase64EncodeUtf16Ex)
+# define RTBase64EncodedUtf16Length                     RT_MANGLER(RTBase64EncodedUtf16Length)
+# define RTBase64EncodedUtf16LengthEx                   RT_MANGLER(RTBase64EncodedUtf16LengthEx)
 # define RTBldCfgCompiler                               RT_MANGLER(RTBldCfgCompiler)
 # define RTBldCfgRevision                               RT_MANGLER(RTBldCfgRevision)
Index: /trunk/src/VBox/Runtime/common/string/base64.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/string/base64.cpp	(revision 84285)
+++ /trunk/src/VBox/Runtime/common/string/base64.cpp	(revision 84286)
@@ -416,11 +416,4 @@
 
 
-/**
- * Calculates the length of the Base64 encoding of a given number of bytes of
- * data produced by RTBase64Encode().
- *
- * @returns The Base64 string length.
- * @param   cbData      The number of bytes to encode.
- */
 RTDECL(size_t) RTBase64EncodedLength(size_t cbData)
 {
@@ -430,12 +423,4 @@
 
 
-/**
- * Calculates the length of the Base64 encoding of a given number of bytes of
- * data produced by RTBase64EncodeEx() with the same @a fFlags.
- *
- * @returns The Base64 string length.
- * @param   cbData      The number of bytes to encode.
- * @param   fFlags      Flags, any combination of the RTBASE64_FLAGS \#defines.
- */
 RTDECL(size_t) RTBase64EncodedLengthEx(size_t cbData, uint32_t fFlags)
 {
@@ -463,20 +448,4 @@
 
 
-/**
- * Encodes the specifed data into a Base64 string, the caller supplies the
- * output buffer.
- *
- * This is equivalent to calling RTBase64EncodeEx() with no flags.
- *
- * @returns IRPT status code.
- * @retval  VERR_BUFFER_OVERFLOW if the output buffer is too small. The buffer
- *          may contain an invalid Base64 string.
- *
- * @param   pvData      The data to encode.
- * @param   cbData      The number of bytes to encode.
- * @param   pszBuf      Where to put the Base64 string.
- * @param   cbBuf       The size of the output buffer, including the terminator.
- * @param   pcchActual  The actual number of characters returned.
- */
 RTDECL(int) RTBase64Encode(const void *pvData, size_t cbData, char *pszBuf, size_t cbBuf, size_t *pcchActual)
 {
@@ -486,17 +455,8 @@
 
 
-/**
- * Encodes the specifed data into a Base64 string, the caller supplies the
- * output buffer.
- *
- * @returns IRPT status code.
- * @retval  VERR_BUFFER_OVERFLOW if the output buffer is too small. The buffer
- *          may contain an invalid Base64 string.
- *
- * @param   pvData      The data to encode.
- * @param   cbData      The number of bytes to encode.
- * @param   pszBuf      Where to put the Base64 string.
- * @param   cbBuf       The size of the output buffer, including the terminator.
- * @param   pcchActual  The actual number of characters returned.
+/*
+ * Please note that RTBase64EncodeUtf16Ex contains an almost exact copy of
+ * this code, just using different output character type and variable prefixes.
+ * So, all fixes must be applied to both versions of the code.
  */
 RTDECL(int) RTBase64EncodeEx(const void *pvData, size_t cbData, uint32_t fFlags,
@@ -515,5 +475,5 @@
     uint8_t         u8B;
     uint8_t         u8C;
-    size_t          cbLineFeed = cbBuf - RTBASE64_LINE_LEN;
+    size_t          cbLineFeed = cchEol ? cbBuf - RTBASE64_LINE_LEN : ~(size_t)0;
     const uint8_t  *pbSrc      = (const uint8_t *)pvData;
     char           *pchDst     = pszBuf;
@@ -538,17 +498,14 @@
         pbSrc  += 3;
 
-        if (cchEol > 0)
-        {
-            /* deal out end-of-line */
-            if (cbBuf == cbLineFeed && cbData)
-            {
-                if (cbBuf < cchEol + 1)
-                    return VERR_BUFFER_OVERFLOW;
-                cbBuf -= cchEol;
-                *pchDst++ = chEol0;
-                if (chEol1)
-                    *pchDst++ = chEol1;
-                cbLineFeed = cbBuf - RTBASE64_LINE_LEN;
-            }
+        /* deal out end-of-line */
+        if (cbBuf == cbLineFeed && cbData && cchEol)
+        {
+            if (cbBuf < cchEol + 1)
+                return VERR_BUFFER_OVERFLOW;
+            cbBuf -= cchEol;
+            *pchDst++ = chEol0;
+            if (chEol1)
+                *pchDst++ = chEol1;
+            cbLineFeed = cbBuf - RTBASE64_LINE_LEN;
         }
     }
@@ -589,2 +546,117 @@
 }
 RT_EXPORT_SYMBOL(RTBase64EncodeEx);
+
+
+/*
+ * Please note that RTBase64EncodeEx contains an almost exact copy of
+ * this code, just using different output character type and variable prefixes.
+ * So, all fixes must be applied to both versions of the code.
+ */
+RTDECL(int) RTBase64EncodeUtf16Ex(const void *pvData, size_t cbData, uint32_t fFlags,
+                                  PRTUTF16 pwszBuf, size_t cwcBuf, size_t *pcwcActual)
+{
+    /* Expand the EOL style flags: */
+    size_t const    cchEol = g_acchEolStyles[fFlags & RTBASE64_FLAGS_EOL_STYLE_MASK];
+    char const      chEol0 = g_aachEolStyles[fFlags & RTBASE64_FLAGS_EOL_STYLE_MASK][0];
+    char const      chEol1 = g_aachEolStyles[fFlags & RTBASE64_FLAGS_EOL_STYLE_MASK][1];
+    Assert(cchEol == (chEol0 != '\0' ? 1U : 0U) + (chEol1 != '\0' ? 1U : 0U));
+
+    /*
+     * Process whole "trios" of input data.
+     */
+    uint8_t         u8A;
+    uint8_t         u8B;
+    uint8_t         u8C;
+    size_t          cwcLineFeed = cchEol ? cwcBuf - RTBASE64_LINE_LEN : ~(size_t)0;
+    const uint8_t  *pbSrc       = (const uint8_t *)pvData;
+    PRTUTF16        pwcDst      = pwszBuf;
+    while (cbData >= 3)
+    {
+        if (cwcBuf < 4 + 1)
+            return VERR_BUFFER_OVERFLOW;
+
+        /* encode */
+        u8A = pbSrc[0];
+        pwcDst[0] = g_szValToChar[u8A >> 2];
+        u8B = pbSrc[1];
+        pwcDst[1] = g_szValToChar[((u8A << 4) & 0x3f) | (u8B >> 4)];
+        u8C = pbSrc[2];
+        pwcDst[2] = g_szValToChar[((u8B << 2) & 0x3f) | (u8C >> 6)];
+        pwcDst[3] = g_szValToChar[u8C & 0x3f];
+
+        /* advance */
+        cwcBuf -= 4;
+        pwcDst += 4;
+        cbData -= 3;
+        pbSrc  += 3;
+
+        /* deal out end-of-line */
+        if (cwcBuf == cwcLineFeed && cbData && cchEol)
+        {
+            if (cwcBuf < cchEol + 1)
+                return VERR_BUFFER_OVERFLOW;
+            cwcBuf -= cchEol;
+            *pwcDst++ = chEol0;
+            if (chEol1)
+                *pwcDst++ = chEol1;
+            cwcLineFeed = cwcBuf - RTBASE64_LINE_LEN;
+        }
+    }
+
+    /*
+     * Deal with the odd bytes and string termination.
+     */
+    if (cbData)
+    {
+        if (cwcBuf < 4 + 1)
+            return VERR_BUFFER_OVERFLOW;
+        switch (cbData)
+        {
+            case 1:
+                u8A = pbSrc[0];
+                pwcDst[0] = g_szValToChar[u8A >> 2];
+                pwcDst[1] = g_szValToChar[(u8A << 4) & 0x3f];
+                pwcDst[2] = '=';
+                pwcDst[3] = '=';
+                break;
+            case 2:
+                u8A = pbSrc[0];
+                pwcDst[0] = g_szValToChar[u8A >> 2];
+                u8B = pbSrc[1];
+                pwcDst[1] = g_szValToChar[((u8A << 4) & 0x3f) | (u8B >> 4)];
+                pwcDst[2] = g_szValToChar[(u8B << 2) & 0x3f];
+                pwcDst[3] = '=';
+                break;
+        }
+        pwcDst += 4;
+    }
+
+    *pwcDst = '\0';
+
+    if (pcwcActual)
+        *pcwcActual = pwcDst - pwszBuf;
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTBase64EncodeUtf16Ex);
+
+
+RTDECL(int) RTBase64EncodeUtf16(const void *pvData, size_t cbData, PRTUTF16 pwszBuf, size_t cwcBuf, size_t *pcwcActual)
+{
+    return RTBase64EncodeUtf16Ex(pvData, cbData, 0, pwszBuf, cwcBuf, pcwcActual);
+}
+RT_EXPORT_SYMBOL(RTBase64EncodeUtf16);
+
+
+RTDECL(size_t) RTBase64EncodedUtf16Length(size_t cbData)
+{
+    return RTBase64EncodedLengthEx(cbData, 0);
+}
+RT_EXPORT_SYMBOL(RTBase64EncodedUtf16Length);
+
+
+RTDECL(size_t) RTBase64EncodedUtf16LengthEx(size_t cbData, uint32_t fFlags)
+{
+    return RTBase64EncodedLengthEx(cbData, fFlags);
+}
+RT_EXPORT_SYMBOL(RTBase64EncodedUtf16LengthEx);
+
Index: /trunk/src/VBox/Runtime/testcase/tstRTBase64.cpp
===================================================================
--- /trunk/src/VBox/Runtime/testcase/tstRTBase64.cpp	(revision 84285)
+++ /trunk/src/VBox/Runtime/testcase/tstRTBase64.cpp	(revision 84286)
@@ -36,4 +36,5 @@
 #include <iprt/stream.h>
 #include <iprt/string.h>
+#include <iprt/utf16.h>
 #include <iprt/test.h>
 
@@ -58,5 +59,9 @@
                       int fTextData, int fNormalEnc)
 {
-    char    szOut[0x10000];
+    union
+    {
+        char    szOut[0x10000];
+        RTUTF16 wszOut[0x10000];
+    };
     size_t  cchOut = 0;
 
@@ -103,4 +108,26 @@
 
     /** @todo negative testing. */
+
+    /*
+     * Same as above, but using the UTF-16 variant of the code.
+     */
+
+    /* Decoding: later */
+
+    /* Encoding UTF-16: */
+    memset(wszOut, 0xaa, sizeof(wszOut));
+    wszOut[sizeof(wszOut) / sizeof(wszOut[0]) - 1] = '\0';
+    size_t cwcOut = 0;
+    rc = RTBase64EncodeUtf16(pvData, cbData, wszOut, cchEnc + 1, &cwcOut);
+    if (RT_FAILURE(rc))
+        RTTestIFailed("RTBase64EncodeUtf16 -> %Rrc\n", rc);
+    else if (fNormalEnc && cwcOut != cchEnc)
+        RTTestIFailed("RTBase64EncodeUtf16 returned %zu bytes, expected %zu.\n", cwcOut, cchEnc);
+    else if (fNormalEnc && RTUtf16CmpUtf8(wszOut, pszEnc))
+        RTTestIFailed("RTBase64EncodeUtf16 returned:\n%s\nexpected:\n%s\n", wszOut, pszEnc);
+
+    size_t cwcOut2 = RTBase64EncodedUtf16Length(cbData);
+    if (cwcOut != cwcOut2)
+        RTTestIFailed("RTBase64EncodedLength returned %zu RTUTF16 units, expected %zu.\n", cwcOut2, cwcOut);
 }
 
@@ -182,9 +209,13 @@
     for (size_t cbSrc = 1; cbSrc <= sizeof(s_abData4); cbSrc++)
     {
-        char szEnc[49152];
+        union
+        {
+            char    szEnc[49152];
+            RTUTF16 wszEnc[49152];
+        };
         memset(szEnc, '\0', sizeof(szEnc));
         size_t cchEnc = RTBase64EncodedLength(cbSrc);
         if (cchEnc >= sizeof(szEnc))
-            RTTestIFailed("RTBase64EncodedLength(%zu) returned %zu bytes, too big\n", cbSrc, cchEnc);
+            RTTestIFailed("RTBase64EncodedLength(%zu) returned %zu bytes - too big\n", cbSrc, cchEnc);
         size_t cchOut = 0;
         rc = RTBase64Encode(s_abData4, cbSrc, szEnc, cchEnc, &cchOut);
@@ -197,8 +228,29 @@
             RTTestIFailed("RTBase64EncodedLength(%zu) returned %zu bytes, expected %zu.\n",
                           cbSrc, cchEnc, cchOut);
-        if (szEnc[cchOut + 1] != '\0')
+        if (szEnc[cchOut] != '\0')
             RTTestIFailed("RTBase64Encode(,%zu,) returned string which is not zero terminated\n", cbSrc);
         if (strlen(szEnc) != cchOut)
             RTTestIFailed("RTBase64Encode(,%zu,) returned incorrect string, length %lu\n", cbSrc, cchOut);
+
+        /* Ditto for UTF-16: */
+        memset(wszEnc, '\0', sizeof(wszEnc));
+        size_t cwcEnc = RTBase64EncodedUtf16Length(cbSrc);
+        if (cwcEnc >= RT_ELEMENTS(wszEnc))
+            RTTestIFailed("RTBase64EncodedUtf16Length(%zu) returned %zu RTUTF16 units - too big\n", cbSrc, cwcEnc);
+        size_t cwcOut = 0;
+        rc = RTBase64EncodeUtf16(s_abData4, cbSrc, wszEnc, cwcEnc, &cwcOut);
+        if (rc != VERR_BUFFER_OVERFLOW)
+            RTTestIFailed("RTBase64EncodeUtf16(,%zu,) has no buffer overflow with too small buffer -> %Rrc\n", cbSrc, rc);
+        cwcOut = ~(size_t)0;
+        rc = RTBase64EncodeUtf16(s_abData4, cbSrc, wszEnc, cwcEnc + 1, &cwcOut);
+        if (RT_FAILURE(rc))
+            RTTestIFailed("RTBase64EncodeUtf16 -> %Rrc\n", rc);
+        if (cchOut != cchEnc)
+            RTTestIFailed("RTBase64EncodedUtf16Length(%zu) returned %zu bytes, expected %zu.\n",
+                          cbSrc, cwcEnc, cwcOut);
+        if (wszEnc[cwcOut] != '\0')
+            RTTestIFailed("RTBase64EncodeUtf16(,%zu,) returned string which is not zero terminated\n", cbSrc);
+        if (RTUtf16Len(wszEnc) != cwcOut)
+            RTTestIFailed("RTBase64EncodeUtf16(,%zu,) returned incorrect string, length %lu\n", cbSrc, cwcOut);
     }
 
