- Fix a bunch of various bugs in the Rtl String routines, mostly subtle (ie: fail AFTER writing maximum length, not before (some apps might depend on it), fix completely broken RtlAnsiCharToUnicodeChar prototype and functionality, don't clear buffers when we shouldn't/clear buffers when we should...)
- Also cleanup formatting of the file
- Use Index member from Rtl...To...N API when null-terminating the strings.
- Various optimizations and simplifications in some of the loops.
- Remove some duplicated code.
- Notes about special handling where required, also implement it in some parts.
- Add more failure cases.
- Return correct status codes on failures.
Modified: trunk/reactos/lib/rtl/unicode.c

Modified: trunk/reactos/lib/rtl/unicode.c
--- trunk/reactos/lib/rtl/unicode.c	2005-09-23 06:32:47 UTC (rev 18001)
+++ trunk/reactos/lib/rtl/unicode.c	2005-09-23 06:37:14 UTC (rev 18002)
@@ -3,7 +3,9 @@
  * PROJECT:           ReactOS system libraries
  * PURPOSE:           Unicode Conversion Routines
  * FILE:              lib/rtl/unicode.c
- * PROGRAMMER:        
+ * PROGRAMMER:        Alex Ionescu (alex@relsoft.net)
+ *                    Emanuele Aliberti
+ *                    Gunnar Dalsnes
  */
 
 /* INCLUDES *****************************************************************/
@@ -17,35 +19,87 @@
 
 extern BOOLEAN NlsMbCodePageTag;
 extern BOOLEAN NlsMbOemCodePageTag;
+extern PUSHORT NlsLeadByteInfo;
 
 /* FUNCTIONS *****************************************************************/
 
-
 /*
 * @implemented
 */
-WCHAR STDCALL
-RtlAnsiCharToUnicodeChar (IN CHAR AnsiChar)
+WCHAR
+STDCALL
+RtlAnsiCharToUnicodeChar(IN PUCHAR *AnsiChar)
 {
-   ULONG Size;
-   WCHAR UnicodeChar;
+    ULONG Size;
+    NTSTATUS Status;
+    WCHAR UnicodeChar = 0x20;
 
-   Size = 1;
-#if 0
+    Size = (NlsLeadByteInfo[**AnsiChar] == 0) ? 1 : 2;
 
-   Size = (NlsLeadByteInfo[AnsiChar] == 0) ? 1 : 2;
-#endif
+    Status = RtlMultiByteToUnicodeN(&UnicodeChar,
+                                    sizeof(WCHAR),
+                                    NULL,
+                                    *AnsiChar,
+                                    Size);
 
-   RtlMultiByteToUnicodeN (&UnicodeChar,
-                           sizeof(WCHAR),
-                           NULL,
-                           &AnsiChar,
-                           Size);
+    if (!NT_SUCCESS(Status))
+    {
+        UnicodeChar = 0x20;
+    }
 
-   return UnicodeChar;
+    *AnsiChar += Size;
+    return UnicodeChar;
 }
 
+/*
+ * @implemented
+ *
+ * NOTES
+ *  This function always writes a terminating '\0'.
+ *  If the dest buffer is too small a partial copy is NOT performed!
+ */
+NTSTATUS
+STDCALL
+RtlAnsiStringToUnicodeString(
+   IN OUT PUNICODE_STRING UniDest,
+   IN PANSI_STRING AnsiSource,
+   IN BOOLEAN AllocateDestinationString)
+{
+    NTSTATUS Status;
+    ULONG Length;
+    ULONG Index;
 
+    Length = RtlAnsiStringToUnicodeSize(AnsiSource);
+    if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2;
+    UniDest->Length = (USHORT)Length - sizeof(WCHAR);
+
+    if (AllocateDestinationString == TRUE)
+    {
+        UniDest->Buffer = RtlpAllocateStringMemory(Length, TAG_USTR);
+        UniDest->MaximumLength = Length;
+        if (!UniDest->Buffer) return STATUS_NO_MEMORY;
+    }
+    else if (Length >= UniDest->MaximumLength)
+    {
+        return STATUS_BUFFER_TOO_SMALL;
+    }
+
+    Status = RtlMultiByteToUnicodeN(UniDest->Buffer,
+                                    UniDest->Length,
+                                    &Index,
+                                    AnsiSource->Buffer,
+                                    AnsiSource->Length);
+
+    if (!NT_SUCCESS(Status) && AllocateDestinationString)
+    {
+        RtlpFreeStringMemory(UniDest->Buffer, TAG_USTR);
+        return Status;
+    }
+
+    UniDest->Buffer[Index / sizeof(WCHAR)] = UNICODE_NULL;
+    return Status;
+}
+
 /*
  * @implemented
  *
@@ -67,8 +121,6 @@
     return(Size + sizeof(WCHAR));
 }
 
-
-
 /*
  * @implemented
  *
@@ -78,31 +130,28 @@
  */
 NTSTATUS
 STDCALL
-RtlAppendStringToString(IN OUT PSTRING Destination,
+RtlAppendStringToString(IN PSTRING Destination,
                         IN PSTRING Source)
 {
-   PCHAR Ptr;
+    USHORT SourceLength = Source->Length;
 
-   if (Source->Length == 0)
-      return(STATUS_SUCCESS);
+    if (SourceLength)
+    {
+        if (Destination->Length + SourceLength > Destination->MaximumLength)
+        {
+            return STATUS_BUFFER_TOO_SMALL;
+        }
 
-   if (Destination->Length + Source->Length >= Destination->MaximumLength)
-      return(STATUS_BUFFER_TOO_SMALL);
+        RtlMoveMemory(&Destination->Buffer[Destination->Length],
+                      Source->Buffer,
+                      SourceLength);
 
-   Ptr = Destination->Buffer + Destination->Length;
-   memmove(Ptr,
-           Source->Buffer,
-           Source->Length);
-   Ptr += Source->Length;
-   *Ptr = 0;
+        Destination->Length += SourceLength;
+    }
 
-   Destination->Length += Source->Length;
-
-   return(STATUS_SUCCESS);
+    return STATUS_SUCCESS;
 }
 
-
-
 /*
  * @implemented
  *
@@ -117,20 +166,29 @@
    IN OUT PUNICODE_STRING Destination,
    IN PCUNICODE_STRING Source)
 {
+    USHORT SourceLength = Source->Length;
+    PWCHAR Buffer = &Destination->Buffer[Destination->Length / sizeof(WCHAR)];
 
-   if ((Source->Length + Destination->Length) > Destination->MaximumLength)
-      return STATUS_BUFFER_TOO_SMALL;
+    if (SourceLength)
+    {
+        if ((SourceLength+ Destination->Length) > Destination->MaximumLength)
+        {
+            return STATUS_BUFFER_TOO_SMALL;
+        }
 
-   memcpy((char*)Destination->Buffer + Destination->Length, Source->Buffer, Source->Length);
-   Destination->Length += Source->Length;
-   /* append terminating '\0' if enough space */
-   if( Destination->MaximumLength > Destination->Length )
-      Destination->Buffer[Destination->Length / sizeof(WCHAR)] = 0;
+        RtlMoveMemory(Buffer, Source->Buffer, SourceLength);
+        Destination->Length += SourceLength;
 
-   return STATUS_SUCCESS;
+        /* append terminating '\0' if enough space */
+        if (Destination->MaximumLength > Destination->Length)
+        {
+            Buffer[SourceLength / sizeof(WCHAR)] = UNICODE_NULL;
+        }
+    }
+
+    return STATUS_SUCCESS;
 }
 
-
 /**************************************************************************
  *      RtlCharToInteger   (NTDLL.@)
  * @implemented
@@ -251,7 +309,6 @@
    return ret;
 }
 
-
 /*
  * @implemented
  *
@@ -265,11 +322,10 @@
    IN PSTRING s2,
    IN BOOLEAN CaseInsensitive)
 {
-   if (s1->Length != s2->Length) return FALSE;
-   return !RtlCompareString(s1, s2, CaseInsensitive );
+    if (s1->Length != s2->Length) return FALSE;
+    return !RtlCompareString(s1, s2, CaseInsensitive);
 }
 
-
 /*
  * @implemented
  *
@@ -283,11 +339,10 @@
    IN CONST UNICODE_STRING *s2,
    IN BOOLEAN  CaseInsensitive)
 {
-   if (s1->Length != s2->Length) return FALSE;
-   return !RtlCompareUnicodeString((PUNICODE_STRING)s1, (PUNICODE_STRING)s2, CaseInsensitive );
+    if (s1->Length != s2->Length) return FALSE;
+    return !RtlCompareUnicodeString(s1, s2, CaseInsensitive );
 }
 
-
 /*
  * @implemented
  */
@@ -295,17 +350,13 @@
 STDCALL
 RtlFreeAnsiString(IN PANSI_STRING AnsiString)
 {
-   if (AnsiString->Buffer != NULL)
-   {
-      RtlpFreeStringMemory(AnsiString->Buffer, TAG_ASTR);
-
-      AnsiString->Buffer = NULL;
-      AnsiString->Length = 0;
-      AnsiString->MaximumLength = 0;
-   }
+    if (AnsiString->Buffer)
+    {
+        RtlpFreeStringMemory(AnsiString->Buffer, TAG_ASTR);
+        RtlZeroMemory(AnsiString, sizeof(ANSI_STRING));
+    }
 }
 
-
 /*
  * @implemented
  */
@@ -313,17 +364,9 @@
 STDCALL
 RtlFreeOemString(IN POEM_STRING OemString)
 {
-   if (OemString->Buffer != NULL)
-   {
-      RtlpFreeStringMemory(OemString->Buffer, TAG_OSTR);
-
-      OemString->Buffer = NULL;
-      OemString->Length = 0;
-      OemString->MaximumLength = 0;
-   }
+   if (OemString->Buffer) RtlpFreeStringMemory(OemString->Buffer, TAG_OSTR);
 }
 
-
 /*
  * @implemented
  */
@@ -331,14 +374,11 @@
 STDCALL
 RtlFreeUnicodeString(IN PUNICODE_STRING UnicodeString)
 {
-   if (UnicodeString->Buffer != NULL)
-   {
-      RtlpFreeStringMemory(UnicodeString->Buffer, TAG_USTR);
-
-      UnicodeString->Buffer = NULL;
-      UnicodeString->Length = 0;
-      UnicodeString->MaximumLength = 0;
-   }
+    if (UnicodeString->Buffer)
+    {
+        RtlpFreeStringMemory(UnicodeString->Buffer, TAG_ASTR);
+        RtlZeroMemory(UnicodeString, sizeof(UNICODE_STRING));
+    }
 }
 
 /*
@@ -346,12 +386,10 @@
 */
 BOOLEAN
 STDCALL
-RtlIsValidOemCharacter (
-	IN PWCHAR Char
-	)
+RtlIsValidOemCharacter(IN PWCHAR Char)
 {
-	UNIMPLEMENTED;
-	return FALSE;
+    UNIMPLEMENTED;
+    return FALSE;
 }
 
 /*
@@ -365,24 +403,23 @@
 RtlInitAnsiString(IN OUT PANSI_STRING DestinationString,
                   IN PCSZ SourceString)
 {
-   ULONG DestSize;
+    ULONG DestSize;
 
-   if (SourceString == NULL)
-   {
-      DestinationString->Length = 0;
-      DestinationString->MaximumLength = 0;
-   }
-   else
-   {
-      DestSize = strlen ((const char *)SourceString);
-      DestinationString->Length = DestSize;
-      DestinationString->MaximumLength = DestSize + sizeof(CHAR);
-   }
-   DestinationString->Buffer = (PCHAR)SourceString;
+    if(SourceString)
+    {
+        DestSize = strlen(SourceString);
+        DestinationString->Length = (USHORT)DestSize;
+        DestinationString->MaximumLength = (USHORT)DestSize + sizeof(CHAR);
+    }
+    else
+    {
+        DestinationString->Length = 0;
+        DestinationString->MaximumLength = 0;
+    }
+
+    DestinationString->Buffer = (PCHAR)SourceString;
 }
 
-
-
 /*
  * @implemented
  *
@@ -395,23 +432,9 @@
    IN OUT PSTRING DestinationString,
    IN PCSZ SourceString)
 {
-   ULONG DestSize;
-
-   if (SourceString == NULL)
-   {
-      DestinationString->Length = 0;
-      DestinationString->MaximumLength = 0;
-   }
-   else
-   {
-      DestSize = strlen((const char *)SourceString);
-      DestinationString->Length = DestSize;
-      DestinationString->MaximumLength = DestSize + sizeof(CHAR);
-   }
-   DestinationString->Buffer = (PCHAR)SourceString;
+    RtlInitAnsiString(DestinationString, SourceString);
 }
 
-
 /*
  * @implemented
  *
@@ -423,53 +446,48 @@
 RtlInitUnicodeString(IN OUT PUNICODE_STRING DestinationString,
                      IN PCWSTR SourceString)
 {
-   ULONG DestSize;
+    ULONG DestSize;
 
-   DPRINT("RtlInitUnicodeString(DestinationString 0x%p, SourceString 0x%p)\n",
-          DestinationString,
-          SourceString);
+    if(SourceString)
+    {
+        DestSize = wcslen(SourceString) * sizeof(WCHAR);
+        DestinationString->Length = (USHORT)DestSize;
+        DestinationString->MaximumLength = (USHORT)DestSize + sizeof(WCHAR);
+    }
+    else
+    {
+        DestinationString->Length = 0;
+        DestinationString->MaximumLength = 0;
+    }
 
-   if (SourceString == NULL)
-   {
-      DestinationString->Length = 0;
-      DestinationString->MaximumLength = 0;
-   }
-   else
-   {
-      DestSize = wcslen((PWSTR)SourceString) * sizeof(WCHAR);
-      DestinationString->Length = DestSize;
-      DestinationString->MaximumLength = DestSize + sizeof(WCHAR);
-   }
-   DestinationString->Buffer = (PWSTR)SourceString;
+    DestinationString->Buffer = (PWCHAR)SourceString;
 }
 
 /*
  * @implemented
  */
-NTSTATUS STDCALL
+NTSTATUS
+STDCALL
 RtlInitUnicodeStringEx(OUT PUNICODE_STRING DestinationString,
                        IN PCWSTR SourceString)
 {
-   ULONG Length;
+    ULONG DestSize;
 
-   if (SourceString != NULL)
-   {
-      Length = wcslen(SourceString) * sizeof(WCHAR);
-      if (Length > 0xFFFC)
-         return STATUS_NAME_TOO_LONG;
+    if(SourceString)
+    {
+        DestSize = wcslen(SourceString) * sizeof(WCHAR);
+        if (DestSize > 0xFFFC) return STATUS_NAME_TOO_LONG;
+        DestinationString->Length = (USHORT)DestSize;
+        DestinationString->MaximumLength = (USHORT)DestSize + sizeof(WCHAR);
+    }
+    else
+    {
+        DestinationString->Length = 0;
+        DestinationString->MaximumLength = 0;
+    }
 
-      DestinationString->Length = Length;
-      DestinationString->MaximumLength = Length + sizeof(WCHAR);
-      DestinationString->Buffer = (PWSTR)SourceString;
-   }
-   else
-   {
-      DestinationString->Length = 0;
-      DestinationString->MaximumLength = 0;
-      DestinationString->Buffer = NULL;
-   }
-
-   return STATUS_SUCCESS;
+    DestinationString->Buffer = (PWCHAR)SourceString;
+    return STATUS_SUCCESS;
 }
 
 /*
@@ -530,7 +548,6 @@
    return STATUS_SUCCESS;
 }
 
-
 /*
  * @implemented
  */
@@ -585,78 +602,63 @@
    return STATUS_SUCCESS;
 }
 
-
-
 /*
  * @implemented
  */
 NTSTATUS
 STDCALL
 RtlIntegerToUnicodeString(
-   IN ULONG  Value,
-   IN ULONG  Base, /* optional */
+   IN ULONG Value,
+   IN ULONG Base OPTIONAL,
    IN OUT PUNICODE_STRING String)
 {
-   ANSI_STRING AnsiString;
-   CHAR Buffer[33];
-   NTSTATUS Status;
+    ANSI_STRING AnsiString;
+    CHAR Buffer[16];
+    NTSTATUS Status;
 
-   Status = RtlIntegerToChar (Value,
-                              Base,
-                              sizeof(Buffer),
-                              Buffer);
-   if (NT_SUCCESS(Status))
-   {
-      AnsiString.Buffer = Buffer;
-      AnsiString.Length = strlen (Buffer);
-      AnsiString.MaximumLength = sizeof(Buffer);
+    Status = RtlIntegerToChar(Value, Base, sizeof(Buffer), Buffer);
+    if (NT_SUCCESS(Status))
+    {
+        AnsiString.Buffer = Buffer;
+        AnsiString.Length = (USHORT)strlen(Buffer);
+        AnsiString.MaximumLength = sizeof(Buffer);
 
-      Status = RtlAnsiStringToUnicodeString (String,
-                                             &AnsiString,
-                                             FALSE);
-   }
+        Status = RtlAnsiStringToUnicodeString(String, &AnsiString, FALSE);
+    }
 
-   return Status;
+    return Status;
 }
 
-
 /*
-* @implemented
-*/
+ * @implemented
+ */
 NTSTATUS
 STDCALL
 RtlInt64ToUnicodeString (
-	IN ULONGLONG Value,
-	IN ULONG Base OPTIONAL,
-	IN OUT PUNICODE_STRING String
-	)
+    IN ULONGLONG Value,
+    IN ULONG Base OPTIONAL,
+    IN OUT PUNICODE_STRING String)
 {
-   LARGE_INTEGER LargeInt;
-   ANSI_STRING AnsiString;
-   CHAR Buffer[33];
-   NTSTATUS Status;
+    LARGE_INTEGER LargeInt;
+    ANSI_STRING AnsiString;
+    CHAR Buffer[32];
+    NTSTATUS Status;
 
-   LargeInt.QuadPart = Value;
+    LargeInt.QuadPart = Value;
 
-   Status = RtlLargeIntegerToChar (&LargeInt,
-                                   Base,
-                                   sizeof(Buffer),
-                                   Buffer);
-   if (NT_SUCCESS(Status))
-   {
-      AnsiString.Buffer = Buffer;
-      AnsiString.Length = strlen (Buffer);
-      AnsiString.MaximumLength = sizeof(Buffer);
+    Status = RtlLargeIntegerToChar(&LargeInt, Base, sizeof(Buffer), Buffer);
+    if (NT_SUCCESS(Status))
+    {
+        AnsiString.Buffer = Buffer;
+        AnsiString.Length = (USHORT)strlen(Buffer);
+        AnsiString.MaximumLength = sizeof(Buffer);
 
-      Status = RtlAnsiStringToUnicodeString (String,
-                                             &AnsiString,
-                                             FALSE);
-   }
+        Status = RtlAnsiStringToUnicodeString(String, &AnsiString, FALSE);
+    }
 
-   return Status;
+    return Status;
 }
 
-
 /*
  * @implemented
  *
@@ -704,7 +706,6 @@
    return FALSE;
 }
 
-
 /*
  * @implemented
  *
@@ -864,7 +865,6 @@
     return STATUS_SUCCESS;
 }
 
-
 /*
  * @implemented
  *
@@ -889,7 +889,6 @@
 /*
  * @implemented
  *
-
  * NOTES
  *  This function always writes a terminating '\0'.
  *  It performs a partial copy if ansi is too small.
@@ -901,47 +900,46 @@
    IN PCUNICODE_STRING UniSource,
    IN BOOLEAN AllocateDestinationString)
 {
-   NTSTATUS Status = STATUS_SUCCESS;
-   ULONG Length; /* including nullterm */
+    NTSTATUS Status = STATUS_SUCCESS;
+    NTSTATUS RealStatus;
+    ULONG Length;
+    ULONG Index;
 
-   Length = RtlUnicodeStringToAnsiSize(UniSource);
-   AnsiDest->Length = Length - sizeof(CHAR);
+    Length = RtlUnicodeStringToAnsiSize(UniSource);
+    if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2;
 
-   if (AllocateDestinationString)
-   {
-      AnsiDest->Buffer = RtlpAllocateStringMemory(Length, TAG_ASTR);
-      if (AnsiDest->Buffer == NULL)
-         return STATUS_NO_MEMORY;
+    AnsiDest->Length = (USHORT)Length - sizeof(CHAR);
 
-      AnsiDest->MaximumLength = Length;
-   }
-   else if (AnsiDest->MaximumLength == 0)
-   {
-      return STATUS_BUFFER_TOO_SMALL;
-   }
-   else if (Length > AnsiDest->MaximumLength)
-   {
-      /* make room for nullterm */
-      AnsiDest->Length = AnsiDest->MaximumLength - sizeof(CHAR);
-   }
+    if (AllocateDestinationString)
+    {
+        AnsiDest->Buffer = RtlpAllocateStringMemory(Length, TAG_ASTR);
+        AnsiDest->MaximumLength = Length;
+        if (!AnsiDest->Buffer) return STATUS_NO_MEMORY;
+    }
+    else if (AnsiDest->Length >= AnsiDest->MaximumLength)
+    {
+        if (!AnsiDest->MaximumLength) return STATUS_BUFFER_OVERFLOW;
 
-   Status = RtlUnicodeToMultiByteN (AnsiDest->Buffer,
-                                    AnsiDest->Length,
-                                    NULL,
-                                    UniSource->Buffer,
-                                    UniSource->Length);
+        Status = STATUS_BUFFER_OVERFLOW;
+        AnsiDest->Length = AnsiDest->MaximumLength - 1;
+    }
 
-   if (!NT_SUCCESS(Status) && AllocateDestinationString)
-   {
-      RtlpFreeStringMemory(AnsiDest->Buffer, TAG_ASTR);
-      return Status;
-   }
+    RealStatus = RtlUnicodeToMultiByteN(AnsiDest->Buffer,
+                                        AnsiDest->Length,
+                                        &Index,
+                                        UniSource->Buffer,
+                                        UniSource->Length);
 
-   AnsiDest->Buffer[AnsiDest->Length] = 0;
-   return Status;
+    if (!NT_SUCCESS(RealStatus) && AllocateDestinationString)
+    {
+        RtlpFreeStringMemory(AnsiDest->Buffer, TAG_ASTR);
+        return RealStatus;
+    }
+
+    AnsiDest->Buffer[Index] = ANSI_NULL;
+    return Status;
 }
 
-
 /*
  * @implemented
  *
@@ -956,50 +954,43 @@
    IN PCOEM_STRING OemSource,
    IN BOOLEAN AllocateDestinationString)
 {
-   NTSTATUS Status;
-   ULONG Length; /* including nullterm */
+    NTSTATUS Status;
+    ULONG Length;
+    ULONG Index;
 
-   Length = RtlOemStringToUnicodeSize(OemSource);
-   if (Length > 0xffff)
-      return STATUS_INVALID_PARAMETER_2;
+    Length = RtlOemStringToUnicodeSize(OemSource);
+    if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2;
 
-   UniDest->Length = (WORD)(Length - sizeof(WCHAR));
+    UniDest->Length = (USHORT)Length - sizeof(WCHAR);
 
-   if (AllocateDestinationString)
-   {
-      UniDest->Buffer = RtlpAllocateStringMemory(Length, TAG_USTR);
-      if (UniDest->Buffer == NULL)
-         return STATUS_NO_MEMORY;
+    if (AllocateDestinationString)
+    {
+        UniDest->Buffer = RtlpAllocateStringMemory(Length, TAG_USTR);
+        UniDest->MaximumLength = Length;
+        if (!UniDest->Buffer) return STATUS_NO_MEMORY;
+    }
+    else if (UniDest->Length >= UniDest->MaximumLength)
+    {
+        return STATUS_BUFFER_OVERFLOW;
+    }
 
-      UniDest->MaximumLength = Length;
-   }
-   else if (Length > UniDest->MaximumLength)
-   {
-      DPRINT("STATUS_BUFFER_TOO_SMALL\n");
-      return STATUS_BUFFER_TOO_SMALL;
-   }
-
-   /* FIXME: Do we need this????? -Gunnar */
-   RtlZeroMemory (UniDest->Buffer,
-                  UniDest->Length);
-
-   Status = RtlOemToUnicodeN (UniDest->Buffer,
+    Status = RtlOemToUnicodeN(UniDest->Buffer,
                               UniDest->Length,
-                              NULL,
+                              &Index,
                               OemSource->Buffer,
                               OemSource->Length);
 
-   if (!NT_SUCCESS(Status) && AllocateDestinationString)
-   {
-      RtlpFreeStringMemory(UniDest->Buffer, TAG_USTR);
-      return Status;
-   }
+    if (!NT_SUCCESS(Status) && AllocateDestinationString)
+    {
+        RtlpFreeStringMemory(UniDest->Buffer, TAG_USTR);
+        UniDest->Buffer = NULL;
+        return Status;
+    }
 
-   UniDest->Buffer[UniDest->Length / sizeof(WCHAR)] = 0;
-   return STATUS_SUCCESS;
+    UniDest->Buffer[Index / sizeof(WCHAR)] = UNICODE_NULL;
+    return Status;
 }
 
-
 /*
  * @implemented
  *
@@ -1013,52 +1004,45 @@
    IN PCUNICODE_STRING UniSource,
    IN BOOLEAN  AllocateDestinationString)
 {
-   NTSTATUS Status = STATUS_SUCCESS;
-   ULONG Length; //including nullterm
+    NTSTATUS Status;
+    ULONG Length;
+    ULONG Index;
 
-   Length = RtlUnicodeStringToAnsiSize(UniSource);
-   if (Length > 0x0000FFFF)
-      return STATUS_INVALID_PARAMETER_2;
+    Length = RtlUnicodeStringToOemSize(UniSource);
+    if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2;
 
-   OemDest->Length = (WORD)(Length - sizeof(CHAR));
+    OemDest->Length = (USHORT)Length - sizeof(CHAR);
 
-   if (AllocateDestinationString)
-   {
-      OemDest->Buffer = RtlpAllocateStringMemory(Length, TAG_OSTR);
-      if (OemDest->Buffer == NULL)
-         return STATUS_NO_MEMORY;
+    if (AllocateDestinationString)
+    {
+        OemDest->Buffer = RtlpAllocateStringMemory(Length, TAG_OSTR);
+        OemDest->MaximumLength = Length;
+        if (!OemDest->Buffer) return STATUS_NO_MEMORY;
+    }
+    else if (OemDest->Length >= OemDest->MaximumLength)
+    {
+        return STATUS_BUFFER_OVERFLOW;
+    }
 
-      OemDest->MaximumLength = Length;
-   }
-   else if (OemDest->MaximumLength == 0)
-   {
-      return STATUS_BUFFER_TOO_SMALL;
-   }
-   else if (Length > OemDest->MaximumLength)
-   {
-      //make room for nullterm
-      OemDest->Length = OemDest->MaximumLength - sizeof(CHAR);
-   }
-
-   Status = RtlUnicodeToOemN (OemDest->Buffer,
+    Status = RtlUnicodeToOemN(OemDest->Buffer,
                               OemDest->Length,
-                              NULL,
+                              &Index,
                               UniSource->Buffer,
                               UniSource->Length);
 
-   if (!NT_SUCCESS(Status) && AllocateDestinationString)
-   {
-      RtlpFreeStringMemory(OemDest->Buffer, TAG_OSTR);
-      return Status;
-   }
+    if (!NT_SUCCESS(Status) && AllocateDestinationString)
+    {
+        RtlpFreeStringMemory(OemDest->Buffer, TAG_OSTR);
+        OemDest->Buffer = NULL;
+        return Status;
+    }
 
-   OemDest->Buffer[OemDest->Length] = 0;
-   return Status;
+    OemDest->Buffer[Index] = ANSI_NULL;
+    return Status;
 }
 
 #define ITU_IMPLEMENTED_TESTS (IS_TEXT_UNICODE_ODD_LENGTH|IS_TEXT_UNICODE_SIGNATURE)
 
-
 /*
  * @implemented
  *
@@ -1117,7 +1101,6 @@
    return Length;
 }
 
-
 /*
  * @implemented
  *
@@ -1132,41 +1115,47 @@
    IN PCOEM_STRING OemSource,
    IN BOOLEAN AllocateDestinationString)
 {
-   NTSTATUS Status;
-   ULONG Length; /* excluding nullterm */
+    NTSTATUS Status;
+    ULONG Length;
+    ULONG Index;
 
-   Length = RtlOemStringToCountedUnicodeSize(OemSource);
-   if (Length > 65535)
-      return STATUS_INVALID_PARAMETER_2;
+    Length = RtlOemStringToCountedUnicodeSize(OemSource);
 
-   if (AllocateDestinationString == TRUE)
-   {
-      UniDest->Buffer = RtlpAllocateStringMemory (Length, TAG_USTR);
-      if (UniDest->Buffer == NULL)
-         return STATUS_NO_MEMORY;
+    if (!Length)
+    {
+        RtlZeroMemory(UniDest, sizeof(UNICODE_STRING));
+        return STATUS_SUCCESS;
+    }
 
-      UniDest->MaximumLength = Length;
-   }
-   else if (Length > UniDest->MaximumLength)
-   {
-      return STATUS_BUFFER_TOO_SMALL;
-   }
+    if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2;
 
-   UniDest->Length = Length;
+    UniDest->Length = (USHORT)Length;
 
-   Status = RtlOemToUnicodeN (UniDest->Buffer,
+    if (AllocateDestinationString)
+    {
+        UniDest->Buffer = RtlpAllocateStringMemory(Length, TAG_USTR);
+        UniDest->MaximumLength = Length;
+        if (!UniDest->Buffer) return STATUS_NO_MEMORY;
+    }
+    else if (UniDest->Length >= UniDest->MaximumLength)
+    {
+        return STATUS_BUFFER_OVERFLOW;
+    }
+
+    Status = RtlOemToUnicodeN(UniDest->Buffer,
                               UniDest->Length,
-                              NULL,
+                              &Index,
                               OemSource->Buffer,
                               OemSource->Length);
 
-   if (!NT_SUCCESS(Status) && AllocateDestinationString)
-   {
-      RtlpFreeStringMemory(UniDest->Buffer, TAG_USTR);
-      return Status;
-   }
+    if (!NT_SUCCESS(Status) && AllocateDestinationString)
+    {
+        RtlpFreeStringMemory(UniDest->Buffer, TAG_USTR);
+        UniDest->Buffer = NULL;
+        return Status;
+    }
 
-   return Status;
+    return STATUS_SUCCESS;
 }
 
 /*
@@ -1184,21 +1173,25 @@
    IN PUNICODE_STRING ComputerName1,
    IN PUNICODE_STRING ComputerName2)
 {
-   OEM_STRING OemString1;
-   OEM_STRING OemString2;
-   BOOLEAN Result = FALSE;
+    OEM_STRING OemString1;
+    OEM_STRING OemString2;
+    BOOLEAN Result = FALSE;
 
-   if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString( &OemString1, ComputerName1, TRUE )))
-   {
-      if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString( &OemString2, ComputerName2, TRUE )))
-      {
-         Result = RtlEqualString( &OemString1, &OemString2, TRUE );
-         RtlFreeOemString( &OemString2 );
-      }
-      RtlFreeOemString( &OemString1 );
-   }
+    if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString(&OemString1,
+                                                     ComputerName1,
+                                                     TRUE)))
+    {
+        if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString(&OemString2,
+                                                         ComputerName2,
+                                                         TRUE)))
+        {
+            Result = RtlEqualString(&OemString1, &OemString2, FALSE);
+            RtlFreeOemString(&OemString2);
+        }
+        RtlFreeOemString(&OemString1);
+    }
 
-   return Result;
+    return Result;
 }
 
 /*
@@ -1217,46 +1210,11 @@
    IN PUNICODE_STRING DomainName2
 )
 {
-   return RtlEqualComputerName(DomainName1, DomainName2);
+    return RtlEqualComputerName(DomainName1, DomainName2);
 }
 
-
 /*
  * @implemented
- */
-/*
-BOOLEAN
-STDCALL
-RtlEqualDomainName (
-   IN PUNICODE_STRING DomainName1,
-   IN PUNICODE_STRING DomainName2
-)
-{
-   OEM_STRING OemString1;
-   OEM_STRING OemString2;
-   BOOLEAN Result;
-
-   RtlUpcaseUnicodeStringToOemString (&OemString1,
-                                      DomainName1,
[truncated at 1000 lines; 877 more skipped]