Index: /trunk/include/iprt/mangling.h
===================================================================
--- /trunk/include/iprt/mangling.h	(revision 50791)
+++ /trunk/include/iprt/mangling.h	(revision 50792)
@@ -1765,4 +1765,5 @@
 # define RTUtf16GetCpInternal                           RT_MANGLER(RTUtf16GetCpInternal)
 # define RTUtf16ICmp                                    RT_MANGLER(RTUtf16ICmp)
+# define RTUtf16IsValidEncoding                         RT_MANGLER(RTUtf16IsValidEncoding)
 # define RTUtf16Len                                     RT_MANGLER(RTUtf16Len)
 # define RTUtf16LocaleICmp                              RT_MANGLER(RTUtf16LocaleICmp)
@@ -1775,4 +1776,6 @@
 # define RTUtf16ToUtf8ExTag                             RT_MANGLER(RTUtf16ToUtf8ExTag)
 # define RTUtf16ToUtf8Tag                               RT_MANGLER(RTUtf16ToUtf8Tag)
+# define RTUtf16ValidateEncoding                        RT_MANGLER(RTUtf16ValidateEncoding)
+# define RTUtf16ValidateEncodingEx                      RT_MANGLER(RTUtf16ValidateEncodingEx)
 # define RTUuidClear                                    RT_MANGLER(RTUuidClear)
 # define RTUuidCompare                                  RT_MANGLER(RTUuidCompare)
Index: /trunk/include/iprt/string.h
===================================================================
--- /trunk/include/iprt/string.h	(revision 50791)
+++ /trunk/include/iprt/string.h	(revision 50792)
@@ -672,5 +672,5 @@
 RTDECL(int) RTStrValidateEncoding(const char *psz);
 
-/** @name Flags for RTStrValidateEncodingEx
+/** @name Flags for RTStrValidateEncodingEx and RTUtf16ValidateEncodingEx
  */
 /** Check that the string is zero terminated within the given size.
@@ -685,5 +685,5 @@
  * @param   psz         The string.
  * @param   cch         The max string length. Use RTSTR_MAX to process the entire string.
- * @param   fFlags      Reserved for future. Pass 0.
+ * @param   fFlags      Combination of RTSTR_VALIDATE_ENCODING_XXX flags.
  */
 RTDECL(int) RTStrValidateEncodingEx(const char *psz, size_t cch, uint32_t fFlags);
@@ -3346,4 +3346,30 @@
 
 /**
+ * Validates the UTF-16 encoding of the string.
+ *
+ * @returns iprt status code.
+ * @param   pwsz        The string.
+ */
+RTDECL(int) RTUtf16ValidateEncoding(PCRTUTF16 pwsz);
+
+/**
+ * Validates the UTF-16 encoding of the string.
+ *
+ * @returns iprt status code.
+ * @param   pwsz        The string.
+ * @param   cch         The max string length. Use RTSTR_MAX to process the entire string.
+ * @param   fFlags      Combination of RTSTR_VALIDATE_ENCODING_XXX flags.
+ */
+RTDECL(int) RTUtf16ValidateEncodingEx(PCRTUTF16 pwsz, size_t cwc, uint32_t fFlags);
+
+/**
+ * Checks if the UTF-16 encoding is valid.
+ *
+ * @returns true / false.
+ * @param   pwsz        The string.
+ */
+RTDECL(bool) RTUtf16IsValidEncoding(PCRTUTF16 pwsz);
+
+/**
  * Sanitise a (valid) UTF-16 string by replacing all characters outside a white
  * list in-place by an ASCII replacement character.  Multi-byte characters will
Index: /trunk/src/VBox/Runtime/common/string/utf-16.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/string/utf-16.cpp	(revision 50791)
+++ /trunk/src/VBox/Runtime/common/string/utf-16.cpp	(revision 50792)
@@ -39,4 +39,64 @@
 
 
+/**
+ * Get get length in code points of an UTF-16 encoded string, validating the
+ * string while doing so.
+ *
+ * @returns IPRT status code.
+ * @param   pwsz            Pointer to the UTF-16 string.
+ * @param   cwc             The max length of the string in UTF-16 units.  Use
+ *                          RTSTR_MAX if all of the string is to be examined.
+ * @param   pcuc            Where to store the length in unicode code points.
+ * @param   pcwcActual      Where to store the actual size of the UTF-16 string
+ *                          on success. Optional.
+ */
+static int rtUtf16Length(PCRTUTF16 pwsz, size_t cwc, size_t *pcuc, size_t *pcwcActual)
+{
+    PCRTUTF16 pwszStart   = pwsz;
+    size_t    cCodePoints = 0;
+    while (cwc > 0)
+    {
+        RTUTF16 wc = *pwsz;
+        if (!wc)
+            break;
+        if (wc < 0xd800 || wc > 0xdfff)
+        {
+            cCodePoints++;
+            pwsz++;
+            cwc--;
+        }
+        /* Surrogate pair: */
+        else if (wc >= 0xdc00)
+        {
+            RTStrAssertMsgFailed(("Lone UTF-16 trail surrogate: %#x (%.*Rhxs)\n", wc, RT_MIN(cwc * 2, 10), pwsz));
+            return VERR_INVALID_UTF16_ENCODING;
+        }
+        else if (cwc < 2)
+        {
+            RTStrAssertMsgFailed(("Lone UTF-16 lead surrogate: %#x\n", wc));
+            return VERR_INVALID_UTF16_ENCODING;
+        }
+        else
+        {
+            RTUTF16 wcTrail = pwsz[1];
+            if (wcTrail < 0xdc00 || wcTrail > 0xdfff)
+            {
+                RTStrAssertMsgFailed(("Invalid UTF-16 trail surrogate: %#x (lead %#x)\n", wcTrail, wc));
+                return VERR_INVALID_UTF16_ENCODING;
+            }
+
+            cCodePoints++;
+            pwsz += 2;
+            cwc -= 2;
+        }
+    }
+
+    /* done */
+    *pcuc = cCodePoints;
+    if (pcwcActual)
+        *pcwcActual = pwsz - pwszStart;
+    return VINF_SUCCESS;
+}
+
 
 RTDECL(void)  RTUtf16Free(PRTUTF16 pwszString)
@@ -248,4 +308,41 @@
 }
 RT_EXPORT_SYMBOL(RTUtf16ToUpper);
+
+
+RTDECL(int) RTUtf16ValidateEncoding(PCRTUTF16 pwsz)
+{
+    return RTUtf16ValidateEncodingEx(pwsz, RTSTR_MAX, 0);
+}
+RT_EXPORT_SYMBOL(RTUtf16ValidateEncoding);
+
+
+RTDECL(int) RTUtf16ValidateEncodingEx(PCRTUTF16 pwsz, size_t cwc, uint32_t fFlags)
+{
+    AssertReturn(!(fFlags & ~(RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED)), VERR_INVALID_PARAMETER);
+    AssertPtr(pwsz);
+
+    /*
+     * Use rtUtf16Length for the job.
+     */
+    size_t cwcActual;
+    size_t cCpsIgnored;
+    int rc = rtUtf16Length(pwsz, cwc, &cCpsIgnored, &cwcActual);
+    if (RT_SUCCESS(rc))
+    {
+        if (    (fFlags & RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED)
+            &&  cwcActual >= cwc)
+            rc = VERR_BUFFER_OVERFLOW;
+    }
+    return rc;
+}
+RT_EXPORT_SYMBOL(RTUtf16ValidateEncodingEx);
+
+
+RTDECL(bool) RTUtf16IsValidEncoding(PCRTUTF16 pwsz)
+{
+    int rc = RTUtf16ValidateEncodingEx(pwsz, RTSTR_MAX, 0);
+    return RT_SUCCESS(rc);
+}
+RT_EXPORT_SYMBOL(RTUtf16IsValidEncoding);
 
 
