[rtl]
[reactos.git] / reactos / lib / rtl / unicode.c
index ee64f36..bafe8c5 100644 (file)
 #define NDEBUG
 #include <debug.h>
 
+#include <wine/unicode.h>
+
 /* GLOBALS *******************************************************************/
 
 extern BOOLEAN NlsMbCodePageTag;
 extern BOOLEAN NlsMbOemCodePageTag;
 extern PUSHORT NlsLeadByteInfo;
 
+extern USHORT NlsOemDefaultChar;
+extern USHORT NlsUnicodeDefaultChar;
+
 /* FUNCTIONS *****************************************************************/
 
 /*
 * @implemented
 */
 WCHAR
-STDCALL
+NTAPI
 RtlAnsiCharToUnicodeChar(IN PUCHAR *AnsiChar)
 {
     ULONG Size;
     NTSTATUS Status;
-    WCHAR UnicodeChar = 0x20;
+    WCHAR UnicodeChar = L' ';
 
     Size = (NlsLeadByteInfo[**AnsiChar] == 0) ? 1 : 2;
 
     Status = RtlMultiByteToUnicodeN(&UnicodeChar,
                                     sizeof(WCHAR),
                                     NULL,
-                                    *AnsiChar,
+                                    (PCHAR)*AnsiChar,
                                     Size);
 
     if (!NT_SUCCESS(Status))
     {
-        UnicodeChar = 0x20;
+        UnicodeChar = L' ';
     }
 
     *AnsiChar += Size;
@@ -59,7 +64,7 @@ RtlAnsiCharToUnicodeChar(IN PUCHAR *AnsiChar)
  *  If the dest buffer is too small a partial copy is NOT performed!
  */
 NTSTATUS
-STDCALL
+NTAPI
 RtlAnsiStringToUnicodeString(
    IN OUT PUNICODE_STRING UniDest,
    IN PANSI_STRING AnsiSource,
@@ -69,19 +74,21 @@ RtlAnsiStringToUnicodeString(
     ULONG Length;
     ULONG Index;
 
+    PAGED_CODE_RTL();
+
     Length = RtlAnsiStringToUnicodeSize(AnsiSource);
     if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2;
     UniDest->Length = (USHORT)Length - sizeof(WCHAR);
 
-    if (AllocateDestinationString == TRUE)
+    if (AllocateDestinationString)
     {
         UniDest->Buffer = RtlpAllocateStringMemory(Length, TAG_USTR);
         UniDest->MaximumLength = Length;
         if (!UniDest->Buffer) return STATUS_NO_MEMORY;
     }
-    else if (Length >= UniDest->MaximumLength)
+    else if (UniDest->Length >= UniDest->MaximumLength)
     {
-        return STATUS_BUFFER_TOO_SMALL;
+        return STATUS_BUFFER_OVERFLOW;
     }
 
     Status = RtlMultiByteToUnicodeN(UniDest->Buffer,
@@ -90,9 +97,13 @@ RtlAnsiStringToUnicodeString(
                                     AnsiSource->Buffer,
                                     AnsiSource->Length);
 
-    if (!NT_SUCCESS(Status) && AllocateDestinationString)
+    if (!NT_SUCCESS(Status))
     {
-        RtlpFreeStringMemory(UniDest->Buffer, TAG_USTR);
+        if (AllocateDestinationString)
+        {
+            RtlpFreeStringMemory(UniDest->Buffer, TAG_USTR);
+            UniDest->Buffer = NULL;
+        }
         return Status;
     }
 
@@ -107,7 +118,7 @@ RtlAnsiStringToUnicodeString(
  *  The calculated size in bytes including nullterm.
  */
 ULONG
-STDCALL
+NTAPI
 RtlxAnsiStringToUnicodeSize(IN PCANSI_STRING AnsiString)
 {
     ULONG Size;
@@ -129,7 +140,7 @@ RtlxAnsiStringToUnicodeSize(IN PCANSI_STRING AnsiString)
  *  Dest is never nullterminated.
  */
 NTSTATUS
-STDCALL
+NTAPI
 RtlAppendStringToString(IN PSTRING Destination,
                         IN PSTRING Source)
 {
@@ -161,7 +172,7 @@ RtlAppendStringToString(IN PSTRING Destination,
  *  When dest fits exactly in MaximumLength characters the nullterm is ommitted.
  */
 NTSTATUS
-STDCALL
+NTAPI
 RtlAppendUnicodeStringToString(
    IN OUT PUNICODE_STRING Destination,
    IN PCUNICODE_STRING Source)
@@ -211,7 +222,7 @@ RtlAppendUnicodeStringToString(
  *  This function does not read garbage behind '\0' as the native version does.
  */
 NTSTATUS
-STDCALL
+NTAPI
 RtlCharToInteger(
     PCSZ str,      /* [I] '\0' terminated single-byte string containing a number */
     ULONG base,    /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
@@ -223,56 +234,56 @@ RtlCharToInteger(
     char bMinus = 0;
 
     while (*str != '\0' && *str <= ' ') {
-       str++;
+    str++;
     } /* while */
 
     if (*str == '+') {
-       str++;
+    str++;
     } else if (*str == '-') {
-       bMinus = 1;
-       str++;
+    bMinus = 1;
+    str++;
     } /* if */
 
     if (base == 0) {
-       base = 10;
-       if (str[0] == '0') {
-           if (str[1] == 'b') {
-               str += 2;
-               base = 2;
-           } else if (str[1] == 'o') {
-               str += 2;
-               base = 8;
-           } else if (str[1] == 'x') {
-               str += 2;
-               base = 16;
-           } /* if */
-       } /* if */
+    base = 10;
+    if (str[0] == '0') {
+        if (str[1] == 'b') {
+        str += 2;
+        base = 2;
+        } else if (str[1] == 'o') {
+        str += 2;
+        base = 8;
+        } else if (str[1] == 'x') {
+        str += 2;
+        base = 16;
+        } /* if */
+    } /* if */
     } else if (base != 2 && base != 8 && base != 10 && base != 16) {
-       return STATUS_INVALID_PARAMETER;
+    return STATUS_INVALID_PARAMETER;
     } /* if */
 
     if (value == NULL) {
-       return STATUS_ACCESS_VIOLATION;
+    return STATUS_ACCESS_VIOLATION;
     } /* if */
 
     while (*str != '\0') {
-       chCurrent = *str;
-       if (chCurrent >= '0' && chCurrent <= '9') {
-           digit = chCurrent - '0';
-       } else if (chCurrent >= 'A' && chCurrent <= 'Z') {
-           digit = chCurrent - 'A' + 10;
-       } else if (chCurrent >= 'a' && chCurrent <= 'z') {
-           digit = chCurrent - 'a' + 10;
-       } else {
-           digit = -1;
-       } /* if */
-       if (digit < 0 || digit >= (int)base) {
-           *value = bMinus ? -RunningTotal : RunningTotal;
-           return STATUS_SUCCESS;
-       } /* if */
-
-       RunningTotal = RunningTotal * base + digit;
-       str++;
+    chCurrent = *str;
+    if (chCurrent >= '0' && chCurrent <= '9') {
+        digit = chCurrent - '0';
+    } else if (chCurrent >= 'A' && chCurrent <= 'Z') {
+        digit = chCurrent - 'A' + 10;
+    } else if (chCurrent >= 'a' && chCurrent <= 'z') {
+        digit = chCurrent - 'a' + 10;
+    } else {
+        digit = -1;
+    } /* if */
+    if (digit < 0 || digit >= (int)base) {
+        *value = bMinus ? -RunningTotal : RunningTotal;
+        return STATUS_SUCCESS;
+    } /* if */
+
+    RunningTotal = RunningTotal * base + digit;
+    str++;
     } /* while */
 
     *value = bMinus ? -RunningTotal : RunningTotal;
@@ -283,7 +294,7 @@ RtlCharToInteger(
  * @implemented
  */
 LONG
-STDCALL
+NTAPI
 RtlCompareString(
    IN PSTRING s1,
    IN PSTRING s2,
@@ -316,7 +327,7 @@ RtlCompareString(
  *  TRUE if strings are equal.
  */
 BOOLEAN
-STDCALL
+NTAPI
 RtlEqualString(
    IN PSTRING s1,
    IN PSTRING s2,
@@ -333,7 +344,7 @@ RtlEqualString(
  *  TRUE if strings are equal.
  */
 BOOLEAN
-STDCALL
+NTAPI
 RtlEqualUnicodeString(
    IN CONST UNICODE_STRING *s1,
    IN CONST UNICODE_STRING *s2,
@@ -347,9 +358,11 @@ RtlEqualUnicodeString(
  * @implemented
  */
 VOID
-STDCALL
+NTAPI
 RtlFreeAnsiString(IN PANSI_STRING AnsiString)
 {
+    PAGED_CODE_RTL();
+
     if (AnsiString->Buffer)
     {
         RtlpFreeStringMemory(AnsiString->Buffer, TAG_ASTR);
@@ -361,9 +374,11 @@ RtlFreeAnsiString(IN PANSI_STRING AnsiString)
  * @implemented
  */
 VOID
-STDCALL
+NTAPI
 RtlFreeOemString(IN POEM_STRING OemString)
 {
+   PAGED_CODE_RTL();
+
    if (OemString->Buffer) RtlpFreeStringMemory(OemString->Buffer, TAG_OSTR);
 }
 
@@ -371,21 +386,62 @@ RtlFreeOemString(IN POEM_STRING OemString)
  * @implemented
  */
 VOID
-STDCALL
+NTAPI
 RtlFreeUnicodeString(IN PUNICODE_STRING UnicodeString)
 {
+    PAGED_CODE_RTL();
+
     if (UnicodeString->Buffer)
     {
-        RtlpFreeStringMemory(UnicodeString->Buffer, TAG_ASTR);
+        RtlpFreeStringMemory(UnicodeString->Buffer, TAG_USTR);
         RtlZeroMemory(UnicodeString, sizeof(UNICODE_STRING));
     }
 }
 
+
+/*
+ * @implemented
+ * 
+ * NOTES
+ *  Check the oem-string to match the uincoded-string.
+ *
+ *  Functions who convert unicode strings to oem strings will set a DefaultChar from 
+ *  the OemCodepage when the character are unknown. So check it against the unicode string
+ *  and return false when the unicode string not contain an TransDefaultChar.
+ */
+BOOLEAN
+NTAPI
+RtlpDidUnicodeToOemWork(IN PCUNICODE_STRING UnicodeString,
+                        IN POEM_STRING OemString)
+{
+   ULONG i = 0;
+
+   /* Go through all characters of a string */
+   while (i < OemString->Length)
+   {
+       /* Check if it got translated into '?', but source char
+          wasn't '?' equivalent */
+       if ((OemString->Buffer[i] != 0) &&
+           (OemString->Buffer[i] == NlsOemDefaultChar) &&
+           (UnicodeString->Buffer[i] != NlsUnicodeDefaultChar))
+       {
+           /* Yes, it means unmappable characters were found */
+           return FALSE;
+       }
+
+       /* Move to the next char */
+       i++;
+   }
+
+   /* All chars were translated successfuly */
+   return TRUE;
+}
+
 /*
 * @unimplemented
 */
 BOOLEAN
-STDCALL
+NTAPI
 RtlIsValidOemCharacter(IN PWCHAR Char)
 {
     UNIMPLEMENTED;
@@ -399,7 +455,7 @@ RtlIsValidOemCharacter(IN PWCHAR Char)
  *  If source is NULL the length of source is assumed to be 0.
  */
 VOID
-STDCALL
+NTAPI
 RtlInitAnsiString(IN OUT PANSI_STRING DestinationString,
                   IN PCSZ SourceString)
 {
@@ -420,6 +476,30 @@ RtlInitAnsiString(IN OUT PANSI_STRING DestinationString,
     DestinationString->Buffer = (PCHAR)SourceString;
 }
 
+NTSTATUS
+NTAPI
+RtlInitAnsiStringEx(IN OUT PANSI_STRING DestinationString,
+                    IN PCSZ SourceString)
+{
+    ULONG DestSize;
+
+    if(SourceString)
+    {
+        DestSize = strlen(SourceString);
+        if (DestSize >= 0xFFFF) return STATUS_NAME_TOO_LONG;
+        DestinationString->Length = (USHORT)DestSize;
+        DestinationString->MaximumLength = (USHORT)DestSize + sizeof(CHAR);
+    }
+    else
+    {
+        DestinationString->Length = 0;
+        DestinationString->MaximumLength = 0;
+    }
+
+    DestinationString->Buffer = (PCHAR)SourceString;
+    return STATUS_SUCCESS;
+
+}
 /*
  * @implemented
  *
@@ -427,7 +507,7 @@ RtlInitAnsiString(IN OUT PANSI_STRING DestinationString,
  *  If source is NULL the length of source is assumed to be 0.
  */
 VOID
-STDCALL
+NTAPI
 RtlInitString(
    IN OUT PSTRING DestinationString,
    IN PCSZ SourceString)
@@ -442,7 +522,7 @@ RtlInitString(
  *  If source is NULL the length of source is assumed to be 0.
  */
 VOID
-STDCALL
+NTAPI
 RtlInitUnicodeString(IN OUT PUNICODE_STRING DestinationString,
                      IN PCWSTR SourceString)
 {
@@ -467,7 +547,7 @@ RtlInitUnicodeString(IN OUT PUNICODE_STRING DestinationString,
  * @implemented
  */
 NTSTATUS
-STDCALL
+NTAPI
 RtlInitUnicodeStringEx(OUT PUNICODE_STRING DestinationString,
                        IN PCWSTR SourceString)
 {
@@ -476,7 +556,7 @@ RtlInitUnicodeStringEx(OUT PUNICODE_STRING DestinationString,
     if(SourceString)
     {
         DestSize = wcslen(SourceString) * sizeof(WCHAR);
-        if (DestSize > 0xFFFC) return STATUS_NAME_TOO_LONG;
+        if (DestSize >= 0xFFFC) return STATUS_NAME_TOO_LONG;
         DestinationString->Length = (USHORT)DestSize;
         DestinationString->MaximumLength = (USHORT)DestSize + sizeof(WCHAR);
     }
@@ -498,61 +578,55 @@ RtlInitUnicodeStringEx(OUT PUNICODE_STRING DestinationString,
  *  Str is nullterminated when length allowes it.
  *  When str fits exactly in length characters the nullterm is ommitted.
  */
-NTSTATUS
-STDCALL
-RtlIntegerToChar(
-   IN ULONG Value,
-   IN ULONG Base,
-   IN ULONG Length,
-   IN OUT PCHAR String)
+NTSTATUS NTAPI RtlIntegerToChar(
+    ULONG value,   /* [I] Value to be converted */
+    ULONG base,    /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
+    ULONG length,  /* [I] Length of the str buffer in bytes */
+    PCHAR str)     /* [O] Destination for the converted value */
 {
-   ULONG Radix;
-   CHAR  temp[33];
-   ULONG v = Value;
-   ULONG i;
-   PCHAR tp;
-   PCHAR sp;
-
-   Radix = Base;
-   if (Radix == 0)
-      Radix = 10;
-
-   if ((Radix != 2) && (Radix != 8) &&
-       (Radix != 10) && (Radix != 16))
-   {
-      return STATUS_INVALID_PARAMETER;
-   }
+    CHAR buffer[33];
+    PCHAR pos;
+    CHAR digit;
+    ULONG len;
 
-   tp = temp;
-   while (v || tp == temp)
-   {
-      i = v % Radix;
-      v = v / Radix;
-      if (i < 10)
-         *tp = i + '0';
-      else
-         *tp = i + 'a' - 10;
-      tp++;
-   }
-
-   if ((ULONG)((ULONG_PTR)tp - (ULONG_PTR)temp) >= Length)
-   {
-      return STATUS_BUFFER_TOO_SMALL;
-   }
-
-   sp = String;
-   while (tp > temp)
-      *sp++ = *--tp;
-   *sp = 0;
+    if (base == 0) {
+    base = 10;
+    } else if (base != 2 && base != 8 && base != 10 && base != 16) {
+    return STATUS_INVALID_PARAMETER;
+    } /* if */
 
-   return STATUS_SUCCESS;
+    pos = &buffer[32];
+    *pos = '\0';
+
+    do {
+    pos--;
+    digit = value % base;
+    value = value / base;
+    if (digit < 10) {
+        *pos = '0' + digit;
+    } else {
+        *pos = 'A' + digit - 10;
+    } /* if */
+    } while (value != 0L);
+
+    len = &buffer[32] - pos;
+    if (len > length) {
+    return STATUS_BUFFER_OVERFLOW;
+    } else if (str == NULL) {
+    return STATUS_ACCESS_VIOLATION;
+    } else if (len == length) {
+    memcpy(str, pos, len);
+    } else {
+    memcpy(str, pos, len + 1);
+    } /* if */
+    return STATUS_SUCCESS;
 }
 
 /*
  * @implemented
  */
 NTSTATUS
-STDCALL
+NTAPI
 RtlIntegerToUnicode(
     IN ULONG Value,
     IN ULONG Base  OPTIONAL,
@@ -606,14 +680,14 @@ RtlIntegerToUnicode(
  * @implemented
  */
 NTSTATUS
-STDCALL
+NTAPI
 RtlIntegerToUnicodeString(
    IN ULONG Value,
    IN ULONG Base OPTIONAL,
    IN OUT PUNICODE_STRING String)
 {
     ANSI_STRING AnsiString;
-    CHAR Buffer[16];
+    CHAR Buffer[33];
     NTSTATUS Status;
 
     Status = RtlIntegerToChar(Value, Base, sizeof(Buffer), Buffer);
@@ -633,7 +707,7 @@ RtlIntegerToUnicodeString(
  * @implemented
  */
 NTSTATUS
-STDCALL
+NTAPI
 RtlInt64ToUnicodeString (
     IN ULONGLONG Value,
     IN ULONG Base OPTIONAL,
@@ -641,7 +715,7 @@ RtlInt64ToUnicodeString (
 {
     LARGE_INTEGER LargeInt;
     ANSI_STRING AnsiString;
-    CHAR Buffer[32];
+    CHAR Buffer[65];
     NTSTATUS Status;
 
     LargeInt.QuadPart = Value;
@@ -666,7 +740,7 @@ RtlInt64ToUnicodeString (
  *  TRUE if String2 contains String1 as a prefix.
  */
 BOOLEAN
-STDCALL
+NTAPI
 RtlPrefixString(
    PANSI_STRING String1,
    PANSI_STRING String2,
@@ -713,7 +787,7 @@ RtlPrefixString(
  *  TRUE if String2 contains String1 as a prefix.
  */
 BOOLEAN
-STDCALL
+NTAPI
 RtlPrefixUnicodeString(
    PCUNICODE_STRING String1,
    PCUNICODE_STRING String2,
@@ -753,112 +827,82 @@ RtlPrefixUnicodeString(
    }
    return FALSE;
 }
-
-/**************************************************************************
- *      RtlUnicodeStringToInteger (NTDLL.@)
+/*
  * @implemented
- * Converts an unicode string into its integer equivalent.
- *
- * RETURNS
- *  Success: STATUS_SUCCESS. value contains the converted number
- *  Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
- *           STATUS_ACCESS_VIOLATION, if value is NULL.
- *
- * NOTES
- *  For base 0 it uses 10 as base and the string should be in the format
- *      "{whitespace} [+|-] [0[x|o|b]] {digits}".
- *  For other bases the string should be in the format
- *      "{whitespace} [+|-] {digits}".
- *  No check is made for value overflow, only the lower 32 bits are assigned.
- *  If str is NULL it crashes, as the native function does.
- *
- *  Note that regardless of success or failure status, we should leave the
- *  partial value in Value.  An error is never returned based on the chars
- *  in the string.
- *
- * DIFFERENCES
- *  This function does not read garbage on string length 0 as the native
- *  version does.
  */
 NTSTATUS
-STDCALL
-RtlUnicodeStringToInteger(
-    PCUNICODE_STRING str, /* [I] Unicode string to be converted */
+NTAPI
+RtlUnicodeStringToInteger(const UNICODE_STRING *str, /* [I] Unicode string to be converted */
     ULONG base,                /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
-    PULONG value)              /* [O] Destination for the converted value */
+    ULONG *value)              /* [O] Destination for the converted value */
 {
     LPWSTR lpwstr = str->Buffer;
     USHORT CharsRemaining = str->Length / sizeof(WCHAR);
     WCHAR wchCurrent;
     int digit;
-    ULONG newbase = 0;
     ULONG RunningTotal = 0;
     char bMinus = 0;
 
-    while (CharsRemaining >= 1 && *lpwstr <= L' ') {
-       lpwstr++;
-       CharsRemaining--;
+    while (CharsRemaining >= 1 && *lpwstr <= ' ') {
+    lpwstr++;
+    CharsRemaining--;
     } /* while */
 
     if (CharsRemaining >= 1) {
-       if (*lpwstr == L'+') {
-           lpwstr++;
-           CharsRemaining--;
-       } else if (*lpwstr == L'-') {
-           bMinus = 1;
-           lpwstr++;
-           CharsRemaining--;
-       } /* if */
+    if (*lpwstr == '+') {
+        lpwstr++;
+        CharsRemaining--;
+    } else if (*lpwstr == '-') {
+        bMinus = 1;
+        lpwstr++;
+        CharsRemaining--;
+    } /* if */
     } /* if */
 
-    if (CharsRemaining >= 2 && lpwstr[0] == L'0') {
-        if (lpwstr[1] == L'b' || lpwstr[1] == L'B') {
-           lpwstr += 2;
-           CharsRemaining -= 2;
-           newbase = 2;
-       } else if (lpwstr[1] == L'o' || lpwstr[1] == L'O') {
-           lpwstr += 2;
-           CharsRemaining -= 2;
-           newbase = 8;
-        } else if (lpwstr[1] == L'x' || lpwstr[1] == L'X') {
-           lpwstr += 2;
-           CharsRemaining -= 2;
-           newbase = 16;
-       } /* if */
-    }
-    if (base == 0 && newbase == 0) {
-        base = 10;
-    } else if (base == 0 && newbase != 0) {
-        base = newbase;
-    } else if ((newbase != 0 && base != newbase) ||
-               (base != 2 && base != 8 && base != 10 && base != 16)) {
-       return STATUS_INVALID_PARAMETER;
-
+    if (base == 0) {
+    base = 10;
+    if (CharsRemaining >= 2 && lpwstr[0] == '0') {
+        if (lpwstr[1] == 'b') {
+        lpwstr += 2;
+        CharsRemaining -= 2;
+        base = 2;
+        } else if (lpwstr[1] == 'o') {
+        lpwstr += 2;
+        CharsRemaining -= 2;
+        base = 8;
+        } else if (lpwstr[1] == 'x') {
+        lpwstr += 2;
+        CharsRemaining -= 2;
+        base = 16;
+        } /* if */
+    } /* if */
+    } else if (base != 2 && base != 8 && base != 10 && base != 16) {
+    return STATUS_INVALID_PARAMETER;
     } /* if */
 
     if (value == NULL) {
-       return STATUS_ACCESS_VIOLATION;
+    return STATUS_ACCESS_VIOLATION;
     } /* if */
 
     while (CharsRemaining >= 1) {
-       wchCurrent = *lpwstr;
-       if (wchCurrent >= L'0' && wchCurrent <= L'9') {
-           digit = wchCurrent - L'0';
-       } else if (wchCurrent >= L'A' && wchCurrent <= L'Z') {
-           digit = wchCurrent - L'A' + 10;
-       } else if (wchCurrent >= L'a' && wchCurrent <= L'z') {
-           digit = wchCurrent - L'a' + 10;
-       } else {
-           digit = -1;
-       } /* if */
-       if (digit < 0 || digit >= (int)base) {
-           *value = bMinus ? -RunningTotal : RunningTotal;
-           return STATUS_SUCCESS;
-       } /* if */
-
-       RunningTotal = RunningTotal * base + digit;
-       lpwstr++;
-       CharsRemaining--;
+    wchCurrent = *lpwstr;
+    if (wchCurrent >= '0' && wchCurrent <= '9') {
+        digit = wchCurrent - '0';
+    } else if (wchCurrent >= 'A' && wchCurrent <= 'Z') {
+        digit = wchCurrent - 'A' + 10;
+    } else if (wchCurrent >= 'a' && wchCurrent <= 'z') {
+        digit = wchCurrent - 'a' + 10;
+    } else {
+        digit = -1;
+    } /* if */
+    if (digit < 0 || digit >= base) {
+        *value = bMinus ? -RunningTotal : RunningTotal;
+        return STATUS_SUCCESS;
+    } /* if */
+
+    RunningTotal = RunningTotal * base + digit;
+    lpwstr++;
+    CharsRemaining--;
     } /* while */
 
     *value = bMinus ? -RunningTotal : RunningTotal;
@@ -872,7 +916,7 @@ RtlUnicodeStringToInteger(
  *  Bytes necessary for the conversion including nullterm.
  */
 ULONG
-STDCALL
+NTAPI
 RtlxUnicodeStringToOemSize(IN PCUNICODE_STRING UnicodeString)
 {
     ULONG Size;
@@ -894,7 +938,7 @@ RtlxUnicodeStringToOemSize(IN PCUNICODE_STRING UnicodeString)
  *  It performs a partial copy if ansi is too small.
  */
 NTSTATUS
-STDCALL
+NTAPI
 RtlUnicodeStringToAnsiString(
    IN OUT PANSI_STRING AnsiDest,
    IN PCUNICODE_STRING UniSource,
@@ -905,6 +949,8 @@ RtlUnicodeStringToAnsiString(
     ULONG Length;
     ULONG Index;
 
+    PAGED_CODE_RTL();
+
     Length = RtlUnicodeStringToAnsiSize(UniSource);
     if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2;
 
@@ -948,7 +994,7 @@ RtlUnicodeStringToAnsiString(
  *  Does NOT perform a partial copy if unicode is too small!
  */
 NTSTATUS
-STDCALL
+NTAPI
 RtlOemStringToUnicodeString(
    IN OUT PUNICODE_STRING UniDest,
    IN PCOEM_STRING OemSource,
@@ -958,6 +1004,8 @@ RtlOemStringToUnicodeString(
     ULONG Length;
     ULONG Index;
 
+    PAGED_CODE_RTL();
+
     Length = RtlOemStringToUnicodeSize(OemSource);
     if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2;
 
@@ -998,7 +1046,7 @@ RtlOemStringToUnicodeString(
  *   This function always '\0' terminates the string returned.
  */
 NTSTATUS
-STDCALL
+NTAPI
 RtlUnicodeStringToOemString(
    IN OUT POEM_STRING OemDest,
    IN PCUNICODE_STRING UniSource,
@@ -1008,6 +1056,8 @@ RtlUnicodeStringToOemString(
     ULONG Length;
     ULONG Index;
 
+    PAGED_CODE_RTL();
+
     Length = RtlUnicodeStringToOemSize(UniSource);
     if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2;
 
@@ -1049,58 +1099,111 @@ RtlUnicodeStringToOemString(
  * RETURNS
  *  The length of the string if all tests were passed, 0 otherwise.
  */
-ULONG STDCALL
-RtlIsTextUnicode (PVOID Buffer,
-                  ULONG Length,
-                  ULONG *Flags)
+BOOLEAN
+NTAPI
+RtlIsTextUnicode( PVOID buf, INT len, INT *pf )
 {
-   PWSTR s = Buffer;
-   ULONG in_flags = (ULONG)-1;
-   ULONG out_flags = 0;
-
-   if (Length == 0)
-      goto done;
+    static const WCHAR std_control_chars[] = {'\r','\n','\t',' ',0x3000,0};
+    static const WCHAR byterev_control_chars[] = {0x0d00,0x0a00,0x0900,0x2000,0};
+    const WCHAR *s = buf;
+    int i;
+    unsigned int flags = MAXULONG, out_flags = 0;
 
-   if (Flags != 0)
-      in_flags = *Flags;
-
-   /*
-    * Apply various tests to the text string. According to the
-    * docs, each test "passed" sets the corresponding flag in
-    * the output flags. But some of the tests are mutually
-    * exclusive, so I don't see how you could pass all tests ...
-    */
-
-   /* Check for an odd length ... pass if even. */
-   if (!(Length & 1))
-      out_flags |= IS_TEXT_UNICODE_ODD_LENGTH;
-
-   /* Check for the BOM (byte order mark). */
-   if (*s == 0xFEFF)
-      out_flags |= IS_TEXT_UNICODE_SIGNATURE;
-
-#if 0
-   /* Check for the reverse BOM (byte order mark). */
-   if (*s == 0xFFFE)
-      out_flags |= IS_TEXT_UNICODE_REVERSE_SIGNATURE;
-#endif
+    if (len < sizeof(WCHAR))
+    {
+        /* FIXME: MSDN documents IS_TEXT_UNICODE_BUFFER_TOO_SMALL but there is no such thing... */
+        if (pf) *pf = 0;
+        return FALSE;
+    }
+    if (pf)
+        flags = *pf;
+    /*
+     * Apply various tests to the text string. According to the
+     * docs, each test "passed" sets the corresponding flag in
+     * the output flags. But some of the tests are mutually
+     * exclusive, so I don't see how you could pass all tests ...
+     */
+
+    /* Check for an odd length ... pass if even. */
+    if (len & 1) out_flags |= IS_TEXT_UNICODE_ODD_LENGTH;
+
+    if (((char *)buf)[len - 1] == 0)
+        len--;  /* Windows seems to do something like that to avoid e.g. false IS_TEXT_UNICODE_NULL_BYTES  */
+
+    len /= sizeof(WCHAR);
+    /* Windows only checks the first 256 characters */
+    if (len > 256) len = 256;
+
+    /* Check for the special byte order unicode marks. */
+    if (*s == 0xFEFF) out_flags |= IS_TEXT_UNICODE_SIGNATURE;
+    if (*s == 0xFFFE) out_flags |= IS_TEXT_UNICODE_REVERSE_SIGNATURE;
+
+    /* apply some statistical analysis */
+    if (flags & IS_TEXT_UNICODE_STATISTICS)
+    {
+        int stats = 0;
+        /* FIXME: checks only for ASCII characters in the unicode stream */
+        for (i = 0; i < len; i++)
+        {
+            if (s[i] <= 255) stats++;
+        }
+        if (stats > len / 2)
+            out_flags |= IS_TEXT_UNICODE_STATISTICS;
+    }
 
-   /* FIXME: Add more tests */
+    /* Check for unicode NULL chars */
+    if (flags & IS_TEXT_UNICODE_NULL_BYTES)
+    {
+        for (i = 0; i < len; i++)
+        {
+            if (!(s[i] & 0xff) || !(s[i] >> 8))
+            {
+                out_flags |= IS_TEXT_UNICODE_NULL_BYTES;
+                break;
+            }
+        }
+    }
 
-   /*
-    * Check whether the string passed all of the tests.
-    */
-   in_flags &= ITU_IMPLEMENTED_TESTS;
-   if ((out_flags & in_flags) != in_flags)
-      Length = 0;
+    if (flags & IS_TEXT_UNICODE_CONTROLS)
+    {
+        for (i = 0; i < len; i++)
+        {
+            if (strchrW(std_control_chars, s[i]))
+            {
+                out_flags |= IS_TEXT_UNICODE_CONTROLS;
+                break;
+            }
+        }
+    }
 
-done:
-   if (Flags != 0)
-      *Flags = out_flags;
+    if (flags & IS_TEXT_UNICODE_REVERSE_CONTROLS)
+    {
+        for (i = 0; i < len; i++)
+        {
+            if (strchrW(byterev_control_chars, s[i]))
+            {
+                out_flags |= IS_TEXT_UNICODE_REVERSE_CONTROLS;
+                break;
+            }
+        }
+    }
 
-   return Length;
+    if (pf)
+    {
+        out_flags &= *pf;
+        *pf = out_flags;
+    }
+    /* check for flags that indicate it's definitely not valid Unicode */
+    if (out_flags & (IS_TEXT_UNICODE_REVERSE_MASK | IS_TEXT_UNICODE_NOT_UNICODE_MASK)) return FALSE;
+    /* now check for invalid ASCII, and assume Unicode if so */
+    if (out_flags & IS_TEXT_UNICODE_NOT_ASCII_MASK) return TRUE;
+    /* now check for Unicode flags */
+    if (out_flags & IS_TEXT_UNICODE_UNICODE_MASK) return TRUE;
+    /* no flags set */
+    return FALSE;
 }
 
+
 /*
  * @implemented
  *
@@ -1109,7 +1212,7 @@ done:
  *  A partial copy is NOT performed if the dest buffer is too small!
  */
 NTSTATUS
-STDCALL
+NTAPI
 RtlOemStringToCountedUnicodeString(
    IN OUT PUNICODE_STRING UniDest,
    IN PCOEM_STRING OemSource,
@@ -1119,29 +1222,37 @@ RtlOemStringToCountedUnicodeString(
     ULONG Length;
     ULONG Index;
 
+    PAGED_CODE_RTL();
+
+    /* Calculate size of the string */
     Length = RtlOemStringToCountedUnicodeSize(OemSource);
 
+    /* If it's 0 then zero out dest string and return */
     if (!Length)
     {
         RtlZeroMemory(UniDest, sizeof(UNICODE_STRING));
         return STATUS_SUCCESS;
     }
 
+    /* Check if length is a sane value */
     if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2;
 
+    /* Store it in dest string */
     UniDest->Length = (USHORT)Length;
 
+    /* If we're asked to alloc the string - do so */
     if (AllocateDestinationString)
     {
         UniDest->Buffer = RtlpAllocateStringMemory(Length, TAG_USTR);
         UniDest->MaximumLength = Length;
         if (!UniDest->Buffer) return STATUS_NO_MEMORY;
     }
-    else if (UniDest->Length >= UniDest->MaximumLength)
+    else if (UniDest->Length > UniDest->MaximumLength)
     {
         return STATUS_BUFFER_OVERFLOW;
     }
 
+    /* Do the conversion */
     Status = RtlOemToUnicodeN(UniDest->Buffer,
                               UniDest->Length,
                               &Index,
@@ -1150,6 +1261,7 @@ RtlOemStringToCountedUnicodeString(
 
     if (!NT_SUCCESS(Status) && AllocateDestinationString)
     {
+        /* Conversion failed, free dest string and return status code */
         RtlpFreeStringMemory(UniDest->Buffer, TAG_USTR);
         UniDest->Buffer = NULL;
         return Status;
@@ -1168,7 +1280,7 @@ RtlOemStringToCountedUnicodeString(
  *  The comparison is case insensitive.
  */
 BOOLEAN
-STDCALL
+NTAPI
 RtlEqualComputerName(
    IN PUNICODE_STRING ComputerName1,
    IN PUNICODE_STRING ComputerName2)
@@ -1204,7 +1316,7 @@ RtlEqualComputerName(
  *  The comparison is case insensitive.
  */
 BOOLEAN
-STDCALL
+NTAPI
 RtlEqualDomainName (
    IN PUNICODE_STRING DomainName1,
    IN PUNICODE_STRING DomainName2
@@ -1232,7 +1344,7 @@ RtlEqualDomainName (
  *  See RtlStringFromGUID.
  */
 NTSTATUS
-STDCALL
+NTAPI
 RtlGUIDFromString(
    IN UNICODE_STRING *str,
    OUT GUID* guid
@@ -1247,7 +1359,7 @@ RtlGUIDFromString(
    /* Convert string: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
     * to memory:       DWORD... WORD WORD BYTES............
     */
-   while (i < 37)
+   while (i <= 37)
    {
       switch (i)
       {
@@ -1346,7 +1458,7 @@ RtlGUIDFromString(
  * @implemented
  */
 VOID
-STDCALL
+NTAPI
 RtlEraseUnicodeString(
    IN PUNICODE_STRING String)
 {
@@ -1361,7 +1473,7 @@ RtlEraseUnicodeString(
 * @implemented
 */
 NTSTATUS
-STDCALL
+NTAPI
 RtlHashUnicodeString(
   IN CONST UNICODE_STRING *String,
   IN BOOLEAN CaseInSensitive,
@@ -1417,7 +1529,7 @@ RtlHashUnicodeString(
  *  Does a partial copy if the dest buffer is too small
  */
 NTSTATUS
-STDCALL
+NTAPI
 RtlUnicodeStringToCountedOemString(
    IN OUT POEM_STRING OemDest,
    IN PUNICODE_STRING UniSource,
@@ -1427,38 +1539,50 @@ RtlUnicodeStringToCountedOemString(
     ULONG Length;
     ULONG Index;
 
+    PAGED_CODE_RTL();
+
+    /* Calculate size of the string */
     Length = RtlUnicodeStringToCountedOemSize(UniSource);
 
+    /* If it's 0 then zero out dest string and return */
     if (!Length)
     {
-        RtlZeroMemory(OemDest, sizeof(UNICODE_STRING));
+        RtlZeroMemory(OemDest, sizeof(OEM_STRING));
+        return STATUS_SUCCESS;
     }
 
+    /* Check if length is a sane value */
     if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2;
 
+    /* Store it in dest string */
     OemDest->Length = (USHORT)Length;
 
+    /* If we're asked to alloc the string - do so */
     if (AllocateDestinationString)
     {
         OemDest->Buffer = RtlpAllocateStringMemory(Length, TAG_OSTR);
         OemDest->MaximumLength = Length;
         if (!OemDest->Buffer) return STATUS_NO_MEMORY;
     }
-    else if (OemDest->Length >= OemDest->MaximumLength)
+    else if (OemDest->Length > OemDest->MaximumLength)
     {
         return STATUS_BUFFER_OVERFLOW;
     }
 
+    /* Do the conversion */
     Status = RtlUnicodeToOemN(OemDest->Buffer,
                               OemDest->Length,
                               &Index,
                               UniSource->Buffer,
                               UniSource->Length);
 
-    /* FIXME: Special check needed and return STATUS_UNMAPPABLE_CHARACTER */
+    /* Check for unmapped character */
+    if (NT_SUCCESS(Status) && !RtlpDidUnicodeToOemWork(UniSource, OemDest))
+        Status = STATUS_UNMAPPABLE_CHARACTER;
 
     if (!NT_SUCCESS(Status) && AllocateDestinationString)
     {
+        /* Conversion failed, free dest string and return status code */
         RtlpFreeStringMemory(OemDest->Buffer, TAG_OSTR);
         OemDest->Buffer = NULL;
         return Status;
@@ -1471,49 +1595,74 @@ RtlUnicodeStringToCountedOemString(
  * @implemented
  */
 NTSTATUS
-STDCALL
+NTAPI
 RtlLargeIntegerToChar(
    IN PLARGE_INTEGER Value,
    IN ULONG  Base,
    IN ULONG  Length,
    IN OUT PCHAR  String)
 {
-   ULONG Radix;
-   CHAR  temp[65];
-   ULONGLONG v = Value->QuadPart;
-   ULONG i;
-   PCHAR tp;
-   PCHAR sp;
+    ULONGLONG Val = Value->QuadPart;
+    NTSTATUS Status = STATUS_SUCCESS;
+    CHAR Buffer[65];
+    CHAR Digit;
+    ULONG Len;
+    PCHAR Pos;
 
-   Radix = Base;
-   if (Radix == 0)
-      Radix = 10;
+    if (Base == 0) Base = 10;
 
-   if ((Radix != 2) && (Radix != 8) &&
-         (Radix != 10) && (Radix != 16))
-      return STATUS_INVALID_PARAMETER;
+    if ((Base != 2) && (Base != 8) &&
+        (Base != 10) && (Base != 16))
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
 
-   tp = temp;
-   while (v || tp == temp)
-   {
-      i = v % Radix;
-      v = v / Radix;
-      if (i < 10)
-         *tp = i + '0';
-      else
-         *tp = i + 'a' - 10;
-      tp++;
-   }
+    Pos = &Buffer[64];
+    *Pos = '\0';
 
-   if ((ULONG)((ULONG_PTR)tp - (ULONG_PTR)temp) >= Length)
-      return STATUS_BUFFER_TOO_SMALL;
+    do
+    {
+        Pos--;
+        Digit = Val % Base;
+        Val = Val / Base;
+        if (Digit < 10)
+            *Pos = '0' + Digit;
+        else
+            *Pos = 'A' + Digit - 10;
+    }
+    while (Val != 0L);
 
-   sp = String;
-   while (tp > temp)
-      *sp++ = *--tp;
-   *sp = 0;
+    Len = &Buffer[64] - Pos;
 
-   return STATUS_SUCCESS;
+    if (Len > Length)
+        return STATUS_BUFFER_OVERFLOW;
+
+#if 1 /* It needs to be removed, when will probably use SEH in rtl */
+    if (String == NULL)
+    {
+        return STATUS_ACCESS_VIOLATION;
+    }
+#endif
+
+#if 0
+    _SEH2_TRY
+    {
+#endif
+        if (Len == Length)
+            RtlCopyMemory(String, Pos, Len);
+        else
+            RtlCopyMemory(String, Pos, Len + 1);
+#if 0
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        /* Get the error code */
+        Status = _SEH2_GetExceptionCode();
+    }
+    _SEH2_END;
+#endif
+
+    return Status;
 }
 
 /*
@@ -1524,7 +1673,7 @@ RtlLargeIntegerToChar(
  *  might not be '\0' terminated. dest->Length is only set upon success.
  */
 NTSTATUS
-STDCALL
+NTAPI
 RtlUpcaseUnicodeString(
    IN OUT PUNICODE_STRING UniDest,
    IN PCUNICODE_STRING UniSource,
@@ -1532,6 +1681,8 @@ RtlUpcaseUnicodeString(
 {
     ULONG i, j;
 
+    PAGED_CODE_RTL();
+
     if (AllocateDestinationString == TRUE)
     {
         UniDest->MaximumLength = UniSource->Length;
@@ -1562,7 +1713,7 @@ RtlUpcaseUnicodeString(
  *  It performs a partial copy if ansi is too small.
  */
 NTSTATUS
-STDCALL
+NTAPI
 RtlUpcaseUnicodeStringToAnsiString(
    IN OUT PANSI_STRING AnsiDest,
    IN PUNICODE_STRING UniSource,
@@ -1572,6 +1723,8 @@ RtlUpcaseUnicodeStringToAnsiString(
     ULONG Length;
     ULONG Index;
 
+    PAGED_CODE_RTL();
+
     Length = RtlUnicodeStringToAnsiSize(UniSource);
     if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2;
 
@@ -1613,7 +1766,7 @@ RtlUpcaseUnicodeStringToAnsiString(
  *  It performs a partial copy if ansi is too small.
  */
 NTSTATUS
-STDCALL
+NTAPI
 RtlUpcaseUnicodeStringToCountedOemString(
    IN OUT POEM_STRING OemDest,
    IN PCUNICODE_STRING UniSource,
@@ -1623,11 +1776,13 @@ RtlUpcaseUnicodeStringToCountedOemString(
     ULONG Length;
     ULONG Index;
 
+    PAGED_CODE_RTL();
+
     Length = RtlUnicodeStringToCountedOemSize(UniSource);
 
     if (!Length)
     {
-        RtlZeroMemory(OemDest, sizeof(UNICODE_STRING));
+        RtlZeroMemory(OemDest, sizeof(OEM_STRING));
     }
 
     if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2;
@@ -1640,7 +1795,7 @@ RtlUpcaseUnicodeStringToCountedOemString(
         OemDest->MaximumLength = Length;
         if (!OemDest->Buffer) return STATUS_NO_MEMORY;
     }
-    else if (OemDest->Length >= OemDest->MaximumLength)
+    else if (OemDest->Length > OemDest->MaximumLength)
     {
         return STATUS_BUFFER_OVERFLOW;
     }
@@ -1651,7 +1806,9 @@ RtlUpcaseUnicodeStringToCountedOemString(
                                     UniSource->Buffer,
                                     UniSource->Length);
 
-    /* FIXME: Special check needed and return STATUS_UNMAPPABLE_CHARACTER */
+    /* Check for unmapped characters */
+    if (NT_SUCCESS(Status) && !RtlpDidUnicodeToOemWork(UniSource, OemDest))
+        Status = STATUS_UNMAPPABLE_CHARACTER;
 
     if (!NT_SUCCESS(Status) && AllocateDestinationString)
     {
@@ -1670,7 +1827,7 @@ RtlUpcaseUnicodeStringToCountedOemString(
  *  It performs a partial copy if oem is too small.
  */
 NTSTATUS
-STDCALL
+NTAPI
 RtlUpcaseUnicodeStringToOemString (
    IN OUT POEM_STRING OemDest,
    IN PCUNICODE_STRING UniSource,
@@ -1680,6 +1837,8 @@ RtlUpcaseUnicodeStringToOemString (
     ULONG Length;
     ULONG Index;
 
+    PAGED_CODE_RTL();
+
     Length = RtlUnicodeStringToOemSize(UniSource);
     if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2;
 
@@ -1702,7 +1861,9 @@ RtlUpcaseUnicodeStringToOemString (
                                     UniSource->Buffer,
                                     UniSource->Length);
 
-    /* FIXME: Special check needed and return STATUS_UNMAPPABLE_CHARACTER */
+    /* Check for unmapped characters */
+    if (NT_SUCCESS(Status) && !RtlpDidUnicodeToOemWork(UniSource, OemDest))
+        Status = STATUS_UNMAPPABLE_CHARACTER;
 
     if (!NT_SUCCESS(Status) && AllocateDestinationString)
     {
@@ -1722,7 +1883,7 @@ RtlUpcaseUnicodeStringToOemString (
  *  Bytes calculated including nullterm
  */
 ULONG
-STDCALL
+NTAPI
 RtlxOemStringToUnicodeSize(IN PCOEM_STRING OemString)
 {
     ULONG Size;
@@ -1740,40 +1901,32 @@ RtlxOemStringToUnicodeSize(IN PCOEM_STRING OemString)
  * @implemented
  */
 NTSTATUS
-STDCALL
+NTAPI
 RtlStringFromGUID (IN REFGUID Guid,
                    OUT PUNICODE_STRING GuidString)
 {
-   STATIC CONST PWCHAR Hex = L"0123456789ABCDEF";
-   WCHAR Buffer[40];
-   PWCHAR BufferPtr;
-   ULONG i;
-
-   if (Guid == NULL)
-   {
-      return STATUS_INVALID_PARAMETER;
-   }
-
-   swprintf (Buffer,
-             L"{%08lX-%04X-%04X-%02X%02X-",
+    /* Setup the string */
+    GuidString->Length = 38 * sizeof(WCHAR);
+    GuidString->MaximumLength = GuidString->Length + sizeof(UNICODE_NULL);
+    GuidString->Buffer = RtlpAllocateStringMemory(GuidString->MaximumLength,
+                                                  TAG_USTR);
+    if (!GuidString->Buffer) return STATUS_NO_MEMORY;
+
+    /* Now format the GUID */
+    swprintf(GuidString->Buffer,
+             L"{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
              Guid->Data1,
              Guid->Data2,
              Guid->Data3,
              Guid->Data4[0],
-             Guid->Data4[1]);
-   BufferPtr = Buffer + 25;
-
-   /* 6 hex bytes */
-   for (i = 2; i < 8; i++)
-   {
-      *BufferPtr++ = Hex[Guid->Data4[i] >> 4];
-      *BufferPtr++ = Hex[Guid->Data4[i] & 0xf];
-   }
-
-   *BufferPtr++ = L'}';
-   *BufferPtr++ = L'\0';
-
-   return RtlCreateUnicodeString (GuidString, Buffer);
+             Guid->Data4[1],
+             Guid->Data4[2],
+             Guid->Data4[3],
+             Guid->Data4[4],
+             Guid->Data4[5],
+             Guid->Data4[6],
+             Guid->Data4[7]);
+    return STATUS_SUCCESS;
 }
 
 /*
@@ -1783,7 +1936,7 @@ RtlStringFromGUID (IN REFGUID Guid,
  *  Bytes calculated including nullterm
  */
 ULONG
-STDCALL
+NTAPI
 RtlxUnicodeStringToAnsiSize(IN PCUNICODE_STRING UnicodeString)
 {
     ULONG Size;
@@ -1801,7 +1954,7 @@ RtlxUnicodeStringToAnsiSize(IN PCUNICODE_STRING UnicodeString)
  * @implemented
  */
 LONG
-STDCALL
+NTAPI
 RtlCompareUnicodeString(
    IN PCUNICODE_STRING s1,
    IN PCUNICODE_STRING s2,
@@ -1831,7 +1984,7 @@ RtlCompareUnicodeString(
  * @implemented
  */
 VOID
-STDCALL
+NTAPI
 RtlCopyString(
    IN OUT PSTRING DestinationString,
    IN PSTRING SourceString OPTIONAL)
@@ -1872,7 +2025,7 @@ RtlCopyString(
  * @implemented
  */
 VOID
-STDCALL
+NTAPI
 RtlCopyUnicodeString(
    IN OUT PUNICODE_STRING DestinationString,
    IN PCUNICODE_STRING SourceString)
@@ -1907,19 +2060,23 @@ RtlCopyUnicodeString(
  * Creates a nullterminated UNICODE_STRING
  */
 BOOLEAN
-STDCALL
+NTAPI
 RtlCreateUnicodeString(
    IN OUT PUNICODE_STRING UniDest,
    IN PCWSTR  Source)
 {
     ULONG Length;
 
+    PAGED_CODE_RTL();
+
     Length = (wcslen(Source) + 1) * sizeof(WCHAR);
+    if (Length > 0xFFFE) return FALSE;
+
     UniDest->Buffer = RtlpAllocateStringMemory(Length, TAG_USTR);
 
     if (UniDest->Buffer == NULL) return FALSE;
 
-    RtlMoveMemory(UniDest->Buffer, Source, Length);
+    RtlCopyMemory(UniDest->Buffer, Source, Length);
     UniDest->MaximumLength = (USHORT)Length;
     UniDest->Length = Length - sizeof (WCHAR);
 
@@ -1930,7 +2087,7 @@ RtlCreateUnicodeString(
  * @implemented
  */
 BOOLEAN
-STDCALL
+NTAPI
 RtlCreateUnicodeStringFromAsciiz(
    OUT PUNICODE_STRING Destination,
    IN PCSZ Source)
@@ -1956,7 +2113,7 @@ RtlCreateUnicodeStringFromAsciiz(
  *  Dest->Length is only set upon success.
  */
 NTSTATUS
-STDCALL
+NTAPI
 RtlDowncaseUnicodeString(
    IN OUT PUNICODE_STRING UniDest,
    IN PCUNICODE_STRING UniSource,
@@ -1965,6 +2122,8 @@ RtlDowncaseUnicodeString(
     ULONG i;
     ULONG StopGap;
 
+    PAGED_CODE_RTL();
+
     if (AllocateDestinationString)
     {
         UniDest->MaximumLength = UniSource->Length;
@@ -2007,7 +2166,7 @@ RtlDowncaseUnicodeString(
  *  When dest fits exactly in MaximumLength characters the '\0' is ommitted.
  */
 NTSTATUS
-STDCALL
+NTAPI
 RtlAppendUnicodeToString(IN OUT PUNICODE_STRING Destination,
                          IN PCWSTR Source)
 {
@@ -2048,7 +2207,7 @@ RtlAppendUnicodeToString(IN OUT PUNICODE_STRING Destination,
  *  dest is never '\0' terminated.
  */
 NTSTATUS
-STDCALL
+NTAPI
 RtlAppendAsciizToString(
    IN OUT   PSTRING  Destination,
    IN PCSZ  Source)
@@ -2075,7 +2234,7 @@ RtlAppendAsciizToString(
  * @implemented
  */
 VOID
-STDCALL
+NTAPI
 RtlUpperString(PSTRING DestinationString,
                PSTRING SourceString)
 {
@@ -2083,7 +2242,7 @@ RtlUpperString(PSTRING DestinationString,
     PCHAR Src, Dest;
 
     Length = min(SourceString->Length,
-                 DestinationString->MaximumLength - 1);
+                 DestinationString->MaximumLength);
 
     Src = SourceString->Buffer;
     Dest = DestinationString->Buffer;
@@ -2102,18 +2261,24 @@ RtlUpperString(PSTRING DestinationString,
  *  See RtlpDuplicateUnicodeString
  */
 NTSTATUS
-STDCALL
+NTAPI
 RtlDuplicateUnicodeString(
    IN ULONG Flags,
    IN PCUNICODE_STRING SourceString,
    OUT PUNICODE_STRING DestinationString)
 {
-   if (SourceString == NULL || DestinationString == NULL)
-      return STATUS_INVALID_PARAMETER;
+   PAGED_CODE_RTL();
+
+    if (SourceString == NULL || DestinationString == NULL ||
+        SourceString->Length > SourceString->MaximumLength ||
+        (SourceString->Length == 0 && SourceString->MaximumLength > 0 && SourceString->Buffer == NULL) ||
+        Flags == RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING || Flags >= 4) {
+        return STATUS_INVALID_PARAMETER;
+    }
 
 
-   if ((SourceString->Length == 0) && 
-       (Flags != (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE | 
+   if ((SourceString->Length == 0) &&
+       (Flags != (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE |
                   RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING)))
    {
       DestinationString->Length = 0;
@@ -2145,9 +2310,9 @@ RtlDuplicateUnicodeString(
 /*
  * @implemented
  */
-NTSTATUS STDCALL
+NTSTATUS NTAPI
 RtlValidateUnicodeString(IN ULONG Flags,
-                         IN PUNICODE_STRING UnicodeString)
+                         IN PCUNICODE_STRING UnicodeString)
 {
   /* currently no flags are supported! */
   ASSERT(Flags == 0);
@@ -2170,4 +2335,92 @@ RtlValidateUnicodeString(IN ULONG Flags,
   }
 }
 
-/* EOF */
+NTSTATUS
+NTAPI
+RtlFindCharInUnicodeString(IN ULONG Flags,
+                           IN PUNICODE_STRING SearchString,
+                           IN PCUNICODE_STRING MatchString,
+                           OUT PUSHORT Position)
+{
+    int main_idx;
+    unsigned int search_idx;
+
+    switch (Flags)
+    {
+        case 0:
+        {
+            for (main_idx = 0; main_idx < SearchString->Length / sizeof(WCHAR); main_idx++)
+            {
+                for (search_idx = 0; search_idx < MatchString->Length / sizeof(WCHAR); search_idx++)
+                {
+                    if (SearchString->Buffer[main_idx] == MatchString->Buffer[search_idx])
+                    {
+                        *Position = (main_idx + 1) * sizeof(WCHAR);
+                        return STATUS_SUCCESS;
+                    }
+                }
+            }
+            *Position = 0;
+            return STATUS_NOT_FOUND;
+        }
+
+        case 1:
+        {
+            for (main_idx = SearchString->Length / sizeof(WCHAR) - 1; main_idx >= 0; main_idx--)
+            {
+                for (search_idx = 0; search_idx < MatchString->Length / sizeof(WCHAR); search_idx++)
+                {
+                    if (SearchString->Buffer[main_idx] == MatchString->Buffer[search_idx])
+                    {
+                        *Position = main_idx * sizeof(WCHAR);
+                        return STATUS_SUCCESS;
+                    }
+                }
+            }
+            *Position = 0;
+            return STATUS_NOT_FOUND;
+        }
+
+        case 2:
+        {
+            for (main_idx = 0; main_idx < SearchString->Length / sizeof(WCHAR); main_idx++)
+            {
+                search_idx = 0;
+                while (search_idx < MatchString->Length / sizeof(WCHAR) &&
+                       SearchString->Buffer[main_idx] != MatchString->Buffer[search_idx])
+                {
+                    search_idx++;
+                }
+                if (search_idx >= MatchString->Length / sizeof(WCHAR))
+                {
+                    *Position = (main_idx + 1) * sizeof(WCHAR);
+                    return STATUS_SUCCESS;
+                }
+            }
+            *Position = 0;
+            return STATUS_NOT_FOUND;
+        }
+
+        case 3:
+        {
+            for (main_idx = SearchString->Length / sizeof(WCHAR) - 1; main_idx >= 0; main_idx--)
+            {
+                search_idx = 0;
+                while (search_idx < MatchString->Length / sizeof(WCHAR) &&
+                       SearchString->Buffer[main_idx] != MatchString->Buffer[search_idx])
+                {
+                    search_idx++;
+                }
+                if (search_idx >= MatchString->Length / sizeof(WCHAR))
+                {
+                    *Position = main_idx * sizeof(WCHAR);
+                    return STATUS_SUCCESS;
+                }
+            }
+            *Position = 0;
+            return STATUS_NOT_FOUND;
+        }
+    } /* switch */
+
+    return STATUS_NOT_FOUND;
+}