Fixed Rtl* string functions for proper MBCS/codepage support. Added a
few more functions.

diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index cfe546d..9142a03 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -272,12 +272,12 @@
 @ stdcall RtlAllocateAndInitializeSid (ptr long long long long long long long long long ptr) RtlAllocateAndInitializeSid
 @ stdcall RtlAllocateHeap(long long long) RtlAllocateHeap
 @ stub RtlAnsiCharToUnicodeChar
-@ stub RtlAnsiStringToUnicodeSize
+@ stdcall RtlAnsiStringToUnicodeSize(ptr) RtlAnsiStringToUnicodeSize
 @ stdcall RtlAnsiStringToUnicodeString(ptr ptr long) RtlAnsiStringToUnicodeString
-@ stub RtlAppendAsciizToString
-@ stub RtlAppendStringToString
-@ stub RtlAppendUnicodeStringToString
-@ stub RtlAppendUnicodeToString
+@ stdcall RtlAppendAsciizToString(ptr str) RtlAppendAsciizToString
+@ stdcall RtlAppendStringToString(ptr ptr) RtlAppendStringToString
+@ stdcall RtlAppendUnicodeStringToString(ptr ptr) RtlAppendUnicodeStringToString
+@ stdcall RtlAppendUnicodeToString(ptr wstr) RtlAppendUnicodeToString
 @ stub RtlApplyRXact
 @ stub RtlApplyRXactNoFlush
 @ stub RtlAreAllAccessesGranted
@@ -293,7 +293,7 @@
 @ stub RtlCompactHeap
 @ stdcall RtlCompareMemory(ptr ptr long) RtlCompareMemory
 @ stub RtlCompareMemoryUlong
-@ stub RtlCompareString
+@ stdcall RtlCompareString(ptr ptr long) RtlCompareString
 @ stdcall RtlCompareUnicodeString (ptr ptr long) RtlCompareUnicodeString
 @ stub RtlCompressBuffer
 @ stub RtlConsoleMultiByteToUnicodeN
@@ -308,8 +308,8 @@
 @ stub RtlCopySecurityDescriptor
 @ stdcall RtlCopySid(long ptr ptr) RtlCopySid
 @ stub RtlCopySidAndAttributesArray
-@ stub RtlCopyString
-@ stub RtlCopyUnicodeString
+@ stdcall RtlCopyString(ptr ptr) RtlCopyString
+@ stdcall RtlCopyUnicodeString(ptr ptr) RtlCopyUnicodeString
 @ stdcall RtlCreateAcl(ptr long long) RtlCreateAcl
 @ stub RtlCreateAndSetSD
 @ stdcall RtlCreateEnvironment(long long) RtlCreateEnvironment
@@ -319,8 +319,8 @@
 @ stub RtlCreateRegistryKey
 @ stdcall RtlCreateSecurityDescriptor(ptr long) RtlCreateSecurityDescriptor
 @ stub RtlCreateTagHeap
-@ stub RtlCreateUnicodeString
-@ stub RtlCreateUnicodeStringFromAsciiz
+@ stdcall RtlCreateUnicodeString(ptr wstr) RtlCreateUnicodeString
+@ stdcall RtlCreateUnicodeStringFromAsciiz(ptr str) RtlCreateUnicodeStringFromAsciiz
 @ stub RtlCreateUserProcess
 @ stub RtlCreateUserSecurityObject
 @ stub RtlCreateUserThread
@@ -357,9 +357,9 @@
 @ stub RtlEqualLuid
 @ stdcall RtlEqualPrefixSid(ptr ptr) RtlEqualPrefixSid
 @ stdcall RtlEqualSid (long long) RtlEqualSid
-@ stub RtlEqualString
-@ stdcall RtlEqualUnicodeString(long long long) RtlEqualUnicodeString
-@ stub RtlEraseUnicodeString
+@ stdcall RtlEqualString(ptr ptr long) RtlEqualString
+@ stdcall RtlEqualUnicodeString(ptr ptr long) RtlEqualUnicodeString
+@ stdcall RtlEraseUnicodeString(ptr) RtlEraseUnicodeString
 @ stub RtlExpandEnvironmentStrings_U
 @ stub RtlExtendHeap
 @ stdcall RtlExtendedIntegerMultiply(long long long) RtlExtendedIntegerMultiply
@@ -379,7 +379,7 @@
 @ stub RtlFormatMessage
 @ stdcall RtlFreeAnsiString(long) RtlFreeAnsiString
 @ stdcall RtlFreeHeap(long long long) RtlFreeHeap
-@ stub RtlFreeOemString
+@ stdcall RtlFreeOemString(ptr) RtlFreeOemString
 @ stdcall RtlFreeSid (long) RtlFreeSid
 @ stdcall RtlFreeUnicodeString(ptr) RtlFreeUnicodeString
 @ stub RtlGenerate8dot3Name
@@ -441,7 +441,7 @@
 @ stub RtlMapGenericMask
 @ stdcall RtlMoveMemory(ptr ptr long) RtlMoveMemory
 @ stdcall RtlMultiByteToUnicodeN(ptr long ptr ptr long) RtlMultiByteToUnicodeN
-@ stub RtlMultiByteToUnicodeSize
+@ stdcall RtlMultiByteToUnicodeSize(ptr str long) RtlMultiByteToUnicodeSize
 @ stub RtlNewInstanceSecurityObject
 @ stub RtlNewSecurityGrantedAccess
 @ stdcall RtlNewSecurityObject(long long long long long long) RtlNewSecurityObject
@@ -450,12 +450,12 @@
 @ stub RtlNumberGenericTableElements
 @ stub RtlNumberOfClearBits
 @ stub RtlNumberOfSetBits
-@ stub RtlOemStringToUnicodeSize
+@ stdcall RtlOemStringToUnicodeSize(ptr) RtlOemStringToUnicodeSize
 @ stdcall RtlOemStringToUnicodeString(ptr ptr long) RtlOemStringToUnicodeString
 @ stdcall RtlOemToUnicodeN(ptr long ptr ptr long) RtlOemToUnicodeN
 @ stdcall RtlOpenCurrentUser(long ptr) RtlOpenCurrentUser
 @ stub RtlPcToFileHeader
-@ stub RtlPrefixString
+@ stdcall RtlPrefixString(ptr ptr long) RtlPrefixString
 @ stdcall RtlPrefixUnicodeString(ptr ptr long) RtlPrefixUnicodeString
 @ stub RtlProtectHeap
 @ stdcall RtlQueryEnvironmentVariable_U(long long long) RtlQueryEnvironmentVariable_U
@@ -510,29 +510,29 @@
 @ stdcall RtlTimeToSecondsSince1970(ptr ptr) RtlTimeToSecondsSince1970
 @ stdcall RtlTimeToSecondsSince1980(ptr ptr) RtlTimeToSecondsSince1980
 @ stdcall RtlTimeToTimeFields (long long) RtlTimeToTimeFields
-@ stub RtlUnicodeStringToAnsiSize
+@ stdcall RtlUnicodeStringToAnsiSize(ptr) RtlUnicodeStringToAnsiSize
 @ stdcall RtlUnicodeStringToAnsiString(ptr ptr long) RtlUnicodeStringToAnsiString
 @ stub RtlUnicodeStringToCountedOemString
 @ stub RtlUnicodeStringToInteger
-@ stub RtlUnicodeStringToOemSize
+@ stdcall RtlUnicodeStringToOemSize(ptr) RtlUnicodeStringToOemSize
 @ stdcall RtlUnicodeStringToOemString(ptr ptr long) RtlUnicodeStringToOemString
 @ stub RtlUnicodeToCustomCPN
 @ stdcall RtlUnicodeToMultiByteN(ptr long ptr ptr long) RtlUnicodeToMultiByteN
-@ stub RtlUnicodeToMultiByteSize
+@ stdcall RtlUnicodeToMultiByteSize(ptr wstr long) RtlUnicodeToMultiByteSize
 @ stdcall RtlUnicodeToOemN(ptr long ptr ptr long) RtlUnicodeToOemN
 @ stub RtlUniform
 @ stub RtlUnlockHeap
 @ stdcall RtlUnwind(ptr ptr ptr long) RtlUnwind
 @ stub RtlUpcaseUnicodeChar
 @ stdcall RtlUpcaseUnicodeString(ptr ptr long) RtlUpcaseUnicodeString
-@ stub RtlUpcaseUnicodeStringToAnsiString
+@ stdcall RtlUpcaseUnicodeStringToAnsiString(ptr ptr long) RtlUpcaseUnicodeStringToAnsiString
 @ stub RtlUpcaseUnicodeStringToCountedOemString
 @ stdcall RtlUpcaseUnicodeStringToOemString(ptr ptr long) RtlUpcaseUnicodeStringToOemString
 @ stub RtlUpcaseUnicodeToCustomCPN
-@ stub RtlUpcaseUnicodeToMultiByteN
+@ stdcall RtlUpcaseUnicodeToMultiByteN(ptr long ptr ptr long) RtlUpcaseUnicodeToMultiByteN
 @ stdcall RtlUpcaseUnicodeToOemN(ptr long ptr ptr long) RtlUpcaseUnicodeToOemN
 @ stub RtlUpperChar
-@ stub RtlUpperString
+@ stdcall RtlUpperString(ptr ptr) RtlUpperString
 @ stub RtlUsageHeap
 @ stub RtlValidAcl
 @ stdcall RtlValidSecurityDescriptor(ptr) RtlValidSecurityDescriptor
@@ -552,10 +552,10 @@
 @ stub RtlpNtSetValueKey
 @ stub RtlpUnWaitCriticalSection
 @ stub RtlpWaitForCriticalSection
-@ stdcall RtlxAnsiStringToUnicodeSize(ptr) RtlxAnsiStringToUnicodeSize
-@ stdcall RtlxOemStringToUnicodeSize(ptr) RtlxOemStringToUnicodeSize
-@ stub RtlxUnicodeStringToAnsiSize
-@ stdcall RtlxUnicodeStringToOemSize(ptr) RtlxUnicodeStringToOemSize
+@ stdcall RtlxAnsiStringToUnicodeSize(ptr) RtlAnsiStringToUnicodeSize
+@ stdcall RtlxOemStringToUnicodeSize(ptr) RtlOemStringToUnicodeSize
+@ stdcall RtlxUnicodeStringToAnsiSize(ptr) RtlUnicodeStringToAnsiSize
+@ stdcall RtlxUnicodeStringToOemSize(ptr) RtlUnicodeStringToOemSize
 @ stub SaveEm87Context
 @ stdcall ZwAcceptConnectPort(long long long long long long) NtAcceptConnectPort
 @ stub ZwAccessCheck
diff --git a/dlls/ntdll/rtlstr.c b/dlls/ntdll/rtlstr.c
index 7e269bf..86227a5 100644
--- a/dlls/ntdll/rtlstr.c
+++ b/dlls/ntdll/rtlstr.c
@@ -1,7 +1,8 @@
 /*
- *	Rtl string functions
+ * Rtl string functions
  *
- *	Copyright 1996-1998 Marcus Meissner
+ * Copyright (C) 1996-1998 Marcus Meissner
+ * Copyright (C) 2000      Alexandre Julliard
  */
 
 #include "config.h"
@@ -19,538 +20,726 @@
 
 DEFAULT_DEBUG_CHANNEL(ntdll);
 
-/*	STRING FUNCTIONS	*/
+/* STRING CREATION FUNCTIONS */
 
 /**************************************************************************
- *	RtlInitString
+ *	RtlInitAnsiString   (NTDLL.@)
  */
-VOID WINAPI RtlInitString(PSTRING target,LPCSTR source)
+void WINAPI RtlInitAnsiString( PSTRING target, LPCSTR source)
 {
-	TRACE("%p %p(%s)\n", target, source, debugstr_a(source));
-
-	target->Buffer = (LPSTR)source;
-	if (source)
-	{
-	  target->Length = strlen(source);
-	  target->MaximumLength = target->Length+1;
-	}
-	else
-	{
-	  target->Length = target->MaximumLength = 0;
-	}
+    if ((target->Buffer = (LPSTR)source))
+    {
+        target->Length = strlen(source);
+        target->MaximumLength = target->Length + 1;
+    }
+    else target->Length = target->MaximumLength = 0;
 }
 
 
-
-/*	ANSI FUNCTIONS	*/
-
 /**************************************************************************
- *	RtlInitAnsiString
+ *	RtlInitString   (NTDLL.@)
  */
-VOID WINAPI RtlInitAnsiString(
-	PANSI_STRING target,
-	LPCSTR source)
+void WINAPI RtlInitString( PSTRING target, LPCSTR source )
 {
-	TRACE("%p %p(%s)\n", target, source, debugstr_a(source));
-
-	target->Buffer = (LPSTR)source;
-	if (source)
-	{
-	  target->Length = strlen(source);
-	  target->MaximumLength = target->Length+1;
-	}
-	else
-	{
-	  target->Length = target->MaximumLength = 0;
-	}
-}
-
-/**************************************************************************
- *	RtlFreeAnsiString
- */
-VOID WINAPI RtlFreeAnsiString(
-	PANSI_STRING AnsiString)
-{
-	TRACE("%p\n", AnsiString);
-	dump_AnsiString(AnsiString, TRUE);
-
-	if( AnsiString->Buffer )
-	  HeapFree( GetProcessHeap(),0,AnsiString->Buffer );
+    return RtlInitAnsiString( target, source );
 }
 
 
-
-/*	UNICODE FUNCTIONS	*/
-
 /**************************************************************************
- *	RtlInitUnicodeString			[NTDLL.403]
+ *	RtlFreeAnsiString   (NTDLL.@)
  */
-VOID WINAPI RtlInitUnicodeString(
-	PUNICODE_STRING target,
-	LPCWSTR source)
+void WINAPI RtlFreeAnsiString( PSTRING str )
 {
-	TRACE("%p %p(%s)\n", target, source, debugstr_w(source));
-	
-	target->Buffer = (LPWSTR)source;
-	if (source)
-	{
-	  target->Length = strlenW(source)*2;
-	  target->MaximumLength = target->Length + 2;
-	}
-	else
-	{
-	  target->Length = target->MaximumLength = 0;
-	}
+    if (str->Buffer) HeapFree( GetProcessHeap(), 0, str->Buffer );
 }
 
-/**************************************************************************
- *	RtlFreeUnicodeString			[NTDLL.377]
- */
-VOID WINAPI RtlFreeUnicodeString(
-	PUNICODE_STRING UnicodeString)
-{
-	TRACE("%p\n", UnicodeString);
-	dump_UnicodeString(UnicodeString, TRUE);
 
-	if (UnicodeString->Buffer)
-	  HeapFree(GetProcessHeap(),0,UnicodeString->Buffer);
+/**************************************************************************
+ *	RtlFreeOemString   (NTDLL.@)
+ */
+void WINAPI RtlFreeOemString( PSTRING str )
+{
+    RtlFreeAnsiString( str );
+}
+
+
+/**************************************************************************
+ *	RtlCopyString   (NTDLL.@)
+ */
+void WINAPI RtlCopyString( STRING *dst, const STRING *src )
+{
+    if (src)
+    {
+        unsigned int len = min( src->Length, dst->MaximumLength );
+        memcpy( dst->Buffer, src->Buffer, len );
+        dst->Length = len;
+    }
+    else dst->Length = 0;
+}
+
+
+/**************************************************************************
+ *	RtlInitUnicodeString   (NTDLL.@)
+ */
+void WINAPI RtlInitUnicodeString( PUNICODE_STRING target, LPCWSTR source )
+{
+    if ((target->Buffer = (LPWSTR)source))
+    {
+        target->Length = strlenW(source) * sizeof(WCHAR);
+        target->MaximumLength = target->Length + sizeof(WCHAR);
+    }
+    else target->Length = target->MaximumLength = 0;
+}
+
+
+/**************************************************************************
+ *	RtlCreateUnicodeString   (NTDLL.@)
+ */
+BOOLEAN WINAPI RtlCreateUnicodeString( PUNICODE_STRING target, LPCWSTR src )
+{
+    int len = (strlenW(src) + 1) * sizeof(WCHAR);
+    if (!(target->Buffer = HeapAlloc( GetProcessHeap(), 0, len ))) return FALSE;
+    memcpy( target->Buffer, src, len );
+    target->MaximumLength = len;
+    target->Length = len - 2;
+    return TRUE;
+}
+
+
+/**************************************************************************
+ *	RtlCreateUnicodeStringFromAsciiz   (NTDLL.@)
+ */
+BOOLEAN WINAPI RtlCreateUnicodeStringFromAsciiz( PUNICODE_STRING target, LPCSTR src )
+{
+    STRING ansi;
+    RtlInitAnsiString( &ansi, src );
+    return !RtlAnsiStringToUnicodeString( target, &ansi, TRUE );
+}
+
+
+/**************************************************************************
+ *	RtlFreeUnicodeString   (NTDLL.@)
+ */
+void WINAPI RtlFreeUnicodeString( PUNICODE_STRING str )
+{
+    if (str->Buffer) HeapFree( GetProcessHeap(), 0, str->Buffer );
+}
+
+
+/**************************************************************************
+ *	RtlCopyUnicodeString   (NTDLL.@)
+ */
+void WINAPI RtlCopyUnicodeString( UNICODE_STRING *dst, const UNICODE_STRING *src )
+{
+    if (src)
+    {
+        unsigned int len = min( src->Length, dst->MaximumLength );
+        memcpy( dst->Buffer, src->Buffer, len );
+        dst->Length = len;
+        /* append terminating NULL if enough space */
+        if (len < dst->MaximumLength) dst->Buffer[len / sizeof(WCHAR)] = 0;
+    }
+    else dst->Length = 0;
+}
+
+
+/**************************************************************************
+ *	RtlEraseUnicodeString   (NTDLL.@)
+ */
+void WINAPI RtlEraseUnicodeString( UNICODE_STRING *str )
+{
+    if (str->Buffer)
+    {
+        memset( str->Buffer, 0, str->MaximumLength );
+        str->Length = 0;
+    }
 }
 
 /*
-	 COMPARE FUNCTIONS
+    COMPARISON FUNCTIONS
 */
 
-/**************************************************************************
- *	RtlEqualUnicodeString
+/******************************************************************************
+ *	RtlCompareString   (NTDLL.@)
  */
-BOOLEAN WINAPI RtlEqualUnicodeString(
-	IN PUNICODE_STRING s1,
-	IN PUNICODE_STRING s2,
-        IN BOOLEAN CaseInsensitive) 
+LONG WINAPI RtlCompareString( const STRING *s1, const STRING *s2, BOOLEAN CaseInsensitive )
 {
-	BOOLEAN ret;
-	TRACE("(%p,%p,%x)\n",s1,s2,CaseInsensitive);
-	dump_UnicodeString(s1, TRUE);
-	dump_UnicodeString(s2, TRUE);
+    unsigned int len;
+    LONG ret = 0;
+    LPCSTR p1, p2;
 
-	if(!s1 || !s2 || !s1->Buffer || !s2->Buffer) return FALSE;
-	if (s1->Length != s2->Length) return FALSE;
+    len = min(s1->Length, s2->Length);
+    p1 = s1->Buffer;
+    p2 = s2->Buffer;
 
-	if (CaseInsensitive)
-	  ret = !strncmpiW(s1->Buffer,s2->Buffer,s1->Length/sizeof(WCHAR));
-	else	
-	  ret = !strncmpW(s1->Buffer,s2->Buffer,s1->Length/sizeof(WCHAR));
-	return ret;
+    if (CaseInsensitive)
+    {
+        while (!ret && len--) ret = toupper(*p1++) - toupper(*p2++);
+    }
+    else
+    {
+        while (!ret && len--) ret = *p1++ - *p2++;
+    }
+    if (!ret) ret = s1->Length - s2->Length;
+    return ret;
 }
 
+
 /******************************************************************************
- *	RtlCompareUnicodeString
+ *	RtlCompareUnicodeString   (NTDLL.@)
  */
-LONG WINAPI RtlCompareUnicodeString(
-	PUNICODE_STRING s1,
-	PUNICODE_STRING s2,
-	BOOLEAN CaseInsensitive) 
+LONG WINAPI RtlCompareUnicodeString( const UNICODE_STRING *s1, const UNICODE_STRING *s2,
+                                     BOOLEAN CaseInsensitive )
 {
-	LONG ret;
+    unsigned int len;
+    LONG ret = 0;
+    LPCWSTR p1, p2;
 
-	TRACE("(%p,%p,%x)\n",s1,s2,CaseInsensitive);
-	dump_UnicodeString(s1, TRUE);
-	dump_UnicodeString(s2, TRUE);
+    len = min(s1->Length, s2->Length) / sizeof(WCHAR);
+    p1 = s1->Buffer;
+    p2 = s2->Buffer;
 
-	if(!s1 || !s2 || !s1->Buffer || !s2->Buffer) return FALSE;
-	
-	if (s1->Length != s2->Length) return (s1->Length - s2->Length);
-
-	if (CaseInsensitive)
-	  ret = strncmpiW(s1->Buffer,s2->Buffer,s1->Length/sizeof(WCHAR));
-	else	
-	  ret = strncmpW(s1->Buffer,s2->Buffer,s1->Length/sizeof(WCHAR));
-	return ret;
+    if (CaseInsensitive)
+    {
+        while (!ret && len--) ret = toupperW(*p1++) - toupperW(*p2++);
+    }
+    else
+    {
+        while (!ret && len--) ret = *p1++ - *p2++;
+    }
+    if (!ret) ret = s1->Length - s2->Length;
+    return ret;
 }
 
+
+/**************************************************************************
+ *	RtlEqualString   (NTDLL.@)
+ */
+BOOLEAN WINAPI RtlEqualString( const STRING *s1, const STRING *s2, BOOLEAN CaseInsensitive )
+{
+    if (s1->Length != s2->Length) return FALSE;
+    return !RtlCompareString( s1, s2, CaseInsensitive );
+}
+
+
+/**************************************************************************
+ *	RtlEqualUnicodeString   (NTDLL.@)
+ */
+BOOLEAN WINAPI RtlEqualUnicodeString( const UNICODE_STRING *s1, const UNICODE_STRING *s2,
+                                      BOOLEAN CaseInsensitive )
+{
+    if (s1->Length != s2->Length) return FALSE;
+    return !RtlCompareUnicodeString( s1, s2, CaseInsensitive );
+}
+
+
+/**************************************************************************
+ *	RtlPrefixString   (NTDLL.@)
+ *
+ * Test if s1 is a prefix in s2
+ */
+BOOLEAN WINAPI RtlPrefixString( const STRING *s1, const STRING *s2, BOOLEAN ignore_case )
+{
+    unsigned int i;
+
+    if (s1->Length > s2->Length) return FALSE;
+    if (ignore_case)
+    {
+        for (i = 0; i < s1->Length; i++)
+            if (toupper(s1->Buffer[i]) != toupper(s2->Buffer[i])) return FALSE;
+    }
+    else
+    {
+        for (i = 0; i < s1->Length; i++)
+            if (s1->Buffer[i] != s2->Buffer[i]) return FALSE;
+    }
+    return TRUE;
+}
+
+
+/**************************************************************************
+ *	RtlPrefixUnicodeString   (NTDLL.@)
+ *
+ * Test if s1 is a prefix in s2
+ */
+BOOLEAN WINAPI RtlPrefixUnicodeString( const UNICODE_STRING *s1,
+                                       const UNICODE_STRING *s2,
+                                       BOOLEAN ignore_case )
+{
+    unsigned int i;
+
+    if (s1->Length > s2->Length) return FALSE;
+    if (ignore_case)
+    {
+        for (i = 0; i < s1->Length / sizeof(WCHAR); i++)
+            if (toupper(s1->Buffer[i]) != toupper(s2->Buffer[i])) return FALSE;
+    }
+    else
+    {
+        for (i = 0; i < s1->Length / sizeof(WCHAR); i++)
+            if (s1->Buffer[i] != s2->Buffer[i]) return FALSE;
+    }
+    return TRUE;
+}
+
+
 /*
 	COPY BETWEEN ANSI_STRING or UNICODE_STRING
 	there is no parameter checking, it just crashes
 */
 
+
 /**************************************************************************
- *	RtlAnsiStringToUnicodeString
+ *	RtlAnsiStringToUnicodeString   (NTDLL.@)
  *
  * NOTES:
  *  writes terminating 0
  */
-NTSTATUS
-WINAPI RtlAnsiStringToUnicodeString(
-	PUNICODE_STRING uni,
-	PANSI_STRING ansi,
-	BOOLEAN doalloc)
+NTSTATUS WINAPI RtlAnsiStringToUnicodeString( UNICODE_STRING *uni,
+                                              const STRING *ansi,
+                                              BOOLEAN doalloc )
 {
-	int len = ansi->Length * sizeof(WCHAR);
+    DWORD len = MultiByteToWideChar( CP_ACP, 0, ansi->Buffer, ansi->Length, NULL, 0 );
+    DWORD total = (len + 1) * sizeof(WCHAR);
 
-	TRACE("%p %p %u\n",uni, ansi, doalloc);
-	dump_AnsiString(ansi, TRUE);
-	dump_UnicodeString(uni, FALSE);
+    if (total > 0xffff) return STATUS_INVALID_PARAMETER_2;
+    uni->Length = len * sizeof(WCHAR);
+    if (doalloc)
+    {
+        uni->MaximumLength = total;
+        if (!(uni->Buffer = HeapAlloc( GetProcessHeap(), 0, total ))) return STATUS_NO_MEMORY;
+    }
+    else if (total > uni->MaximumLength) return STATUS_BUFFER_OVERFLOW;
 
-	if (len>0xfffe) return STATUS_INVALID_PARAMETER_2;
-	uni->Length = len;
-	if (doalloc) 
-	{
-	  uni->MaximumLength = len + sizeof(WCHAR);
-	  uni->Buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,uni->MaximumLength);
-	  if (!uni->Buffer) return STATUS_NO_MEMORY;
-	}
-	else if (len+sizeof(WCHAR) > uni->MaximumLength)
-	{
-	  return STATUS_BUFFER_OVERFLOW;
-	}
-	lstrcpynAtoW(uni->Buffer,ansi->Buffer,ansi->Length+1);
-	return STATUS_SUCCESS;
+    MultiByteToWideChar( CP_ACP, 0, ansi->Buffer, ansi->Length, uni->Buffer, len );
+    uni->Buffer[len] = 0;
+    return STATUS_SUCCESS;
 }
 
+
 /**************************************************************************
- *	RtlUpcaseUnicodeString
+ *	RtlOemStringToUnicodeString   (NTDLL.@)
+ *
+ * NOTES
+ *  writes terminating 0
+ *  if resulting length > 0xffff it returns STATUS_INVALID_PARAMETER_2
+ */
+NTSTATUS WINAPI RtlOemStringToUnicodeString( UNICODE_STRING *uni,
+                                             const STRING *oem,
+                                             BOOLEAN doalloc )
+{
+    DWORD len = MultiByteToWideChar( CP_OEMCP, 0, oem->Buffer, oem->Length, NULL, 0 );
+    DWORD total = (len + 1) * sizeof(WCHAR);
+
+    if (total > 0xffff) return STATUS_INVALID_PARAMETER_2;
+    uni->Length = len * sizeof(WCHAR);
+    if (doalloc)
+    {
+        uni->MaximumLength = total;
+        if (!(uni->Buffer = HeapAlloc( GetProcessHeap(), 0, total ))) return STATUS_NO_MEMORY;
+    }
+    else if (total > uni->MaximumLength) return STATUS_BUFFER_OVERFLOW;
+
+    MultiByteToWideChar( CP_OEMCP, 0, oem->Buffer, oem->Length, uni->Buffer, len );
+    uni->Buffer[len] = 0;
+    return STATUS_SUCCESS;
+}
+
+
+/**************************************************************************
+ *	RtlUnicodeStringToAnsiString   (NTDLL.@)
+ *
+ * NOTES
+ *  writes terminating 0
+ *  copies a part if the buffer is too small
+ */
+NTSTATUS WINAPI RtlUnicodeStringToAnsiString( STRING *ansi,
+                                              const UNICODE_STRING *uni,
+                                              BOOLEAN doalloc )
+{
+    NTSTATUS ret = STATUS_SUCCESS;
+    DWORD len = RtlUnicodeStringToAnsiSize( uni );
+
+    ansi->Length = len;
+    if (doalloc)
+    {
+        ansi->MaximumLength = len + 1;
+        if (!(ansi->Buffer = HeapAlloc( GetProcessHeap(), 0, len + 1 ))) return STATUS_NO_MEMORY;
+    }
+    else if (ansi->MaximumLength <= len)
+    {
+        if (!ansi->MaximumLength) return STATUS_BUFFER_OVERFLOW;
+        ansi->Length = ansi->MaximumLength - 1;
+        ret = STATUS_BUFFER_OVERFLOW;
+    }
+
+    WideCharToMultiByte( CP_ACP, 0, uni->Buffer, uni->Length / sizeof(WCHAR),
+                         ansi->Buffer, ansi->Length, NULL, NULL );
+    ansi->Buffer[ansi->Length] = 0;
+    return ret;
+}
+
+
+/**************************************************************************
+ *	RtlUnicodeStringToOemString   (NTDLL.@)
+ *
+ * NOTES
+ *   allocates uni->Length+1
+ *   writes terminating 0
+ */
+NTSTATUS WINAPI RtlUnicodeStringToOemString( STRING *oem,
+                                             const UNICODE_STRING *uni,
+                                             BOOLEAN doalloc )
+{
+    NTSTATUS ret = STATUS_SUCCESS;
+    DWORD len = RtlUnicodeStringToOemSize( uni );
+
+    oem->Length = len;
+    if (doalloc)
+    {
+        oem->MaximumLength = len + 1;
+        if (!(oem->Buffer = HeapAlloc( GetProcessHeap(), 0, len + 1 ))) return STATUS_NO_MEMORY;
+    }
+    else if (oem->MaximumLength <= len)
+    {
+        if (!oem->MaximumLength) return STATUS_BUFFER_OVERFLOW;
+        oem->Length = oem->MaximumLength - 1;
+        ret = STATUS_BUFFER_OVERFLOW;
+    }
+
+    WideCharToMultiByte( CP_OEMCP, 0, uni->Buffer, uni->Length / sizeof(WCHAR),
+                         oem->Buffer, oem->Length, NULL, NULL );
+    oem->Buffer[oem->Length] = 0;
+    return ret;
+}
+
+
+/**************************************************************************
+ *	RtlMultiByteToUnicodeN   (NTDLL.@)
+ *
+ * NOTES
+ *  if unistr is too small a part is copied
+ */
+NTSTATUS WINAPI RtlMultiByteToUnicodeN( LPWSTR dst, DWORD dstlen, LPDWORD reslen,
+                                        LPCSTR src, DWORD srclen )
+{
+    DWORD res = MultiByteToWideChar( CP_ACP, 0, src, srclen, dst, dstlen/sizeof(WCHAR) );
+    if (reslen)
+        *reslen = res ? res * sizeof(WCHAR) : dstlen; /* overflow -> we filled up to dstlen */
+    return STATUS_SUCCESS;
+}
+
+
+/**************************************************************************
+ *	RtlOemToUnicodeN   (NTDLL.@)
+ */
+NTSTATUS WINAPI RtlOemToUnicodeN( LPWSTR dst, DWORD dstlen, LPDWORD reslen,
+                                  LPCSTR src, DWORD srclen )
+{
+    DWORD res = MultiByteToWideChar( CP_OEMCP, 0, src, srclen, dst, dstlen/sizeof(WCHAR) );
+    if (reslen)
+        *reslen = res ? res * sizeof(WCHAR) : dstlen; /* overflow -> we filled up to dstlen */
+    return STATUS_SUCCESS;
+}
+
+
+/**************************************************************************
+ *	RtlUnicodeToMultiByteN   (NTDLL.@)
+ */
+NTSTATUS WINAPI RtlUnicodeToMultiByteN( LPSTR dst, DWORD dstlen, LPDWORD reslen,
+                                        LPCWSTR src, DWORD srclen )
+{
+    DWORD res = WideCharToMultiByte( CP_ACP, 0, src, srclen/sizeof(WCHAR),
+                                     dst, dstlen, NULL, NULL );
+    if (reslen)
+        *reslen = res ? res * sizeof(WCHAR) : dstlen; /* overflow -> we filled up to dstlen */
+    return STATUS_SUCCESS;
+}
+
+
+/**************************************************************************
+ *	RtlUnicodeToOemN   (NTDLL.@)
+ */
+NTSTATUS WINAPI RtlUnicodeToOemN( LPSTR dst, DWORD dstlen, LPDWORD reslen,
+                                  LPCWSTR src, DWORD srclen )
+{
+    DWORD res = WideCharToMultiByte( CP_OEMCP, 0, src, srclen/sizeof(WCHAR),
+                                     dst, dstlen, NULL, NULL );
+    if (reslen)
+        *reslen = res ? res * sizeof(WCHAR) : dstlen; /* overflow -> we filled up to dstlen */
+    return STATUS_SUCCESS;
+}
+
+
+/*
+     CASE CONVERSIONS
+*/
+
+/**************************************************************************
+ *	RtlUpperString   (NTDLL.@)
+ */
+void WINAPI RtlUpperString( STRING *dst, const STRING *src, BOOLEAN doalloc )
+{
+    unsigned int i, len = min(src->Length, dst->MaximumLength);
+
+    for (i = 0; i < len; i++) dst->Buffer[i] = toupper(src->Buffer[i]);
+    dst->Length = len;
+}
+
+
+/**************************************************************************
+ *	RtlUpcaseUnicodeString   (NTDLL.@)
  *
  * NOTES:
  *  destination string is never 0-terminated because dest can be equal to src
  *  and src might be not 0-terminated
  *  dest.Length only set when success
  */
-DWORD WINAPI RtlUpcaseUnicodeString(
-	PUNICODE_STRING dest,
-	PUNICODE_STRING src,
-	BOOLEAN doalloc)
+NTSTATUS WINAPI RtlUpcaseUnicodeString( UNICODE_STRING *dest,
+                                        const UNICODE_STRING *src,
+                                        BOOLEAN doalloc )
 {
-	int i, len = src->Length;
+    DWORD i, len = src->Length;
 
-	TRACE("(%p,%p,%x)\n",dest, src, doalloc);
-	dump_UnicodeString(dest, FALSE);
-	dump_UnicodeString(src, TRUE);
+    if (doalloc)
+    {
+        dest->MaximumLength = len;
+        if (!(dest->Buffer = HeapAlloc( GetProcessHeap(), 0, len ))) return STATUS_NO_MEMORY;
+    }
+    else if (len > dest->MaximumLength) return STATUS_BUFFER_OVERFLOW;
 
-	if (doalloc)
-	{
-	  dest->Buffer = (LPWSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
-	  if (!dest->Buffer) return STATUS_NO_MEMORY;
-	  dest->MaximumLength = len; 
-	}
-	else if (len > dest->MaximumLength)
-	{
-	  return STATUS_BUFFER_OVERFLOW;
-	}
-
-	for (i=0; i < len/sizeof(WCHAR); i++)
-	{
-	  dest->Buffer[i] = toupperW(src->Buffer[i]);
-	}
-	dest->Length = len;
-	return STATUS_SUCCESS;
+    for (i = 0; i < len/sizeof(WCHAR); i++) dest->Buffer[i] = toupperW(src->Buffer[i]);
+    dest->Length = len;
+    return STATUS_SUCCESS;
 }
 
-/**************************************************************************
- *	RtlOemStringToUnicodeString
- *
- * NOTES
- *  writes terminating 0
- *  buffer must be bigger than (ansi->Length+1)*2
- *  if astr.Length > 0x7ffe it returns STATUS_INVALID_PARAMETER_2
- *
- * FIXME
- *  OEM to unicode
- */
-NTSTATUS
-WINAPI RtlOemStringToUnicodeString(
-	PUNICODE_STRING uni,
-	PSTRING ansi,
-	BOOLEAN doalloc)
-{
-	int len = ansi->Length * sizeof(WCHAR);
-
-	if (len > 0xfffe) return STATUS_INVALID_PARAMETER_2;
-
-	uni->Length = len;
-	if (doalloc) 
-	{
-	  uni->Buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, len + sizeof(WCHAR));
-	  if (!uni->Buffer) return STATUS_NO_MEMORY;
-	  uni->MaximumLength = len + sizeof(WCHAR);
-	}
-	else if (len+1 > uni->MaximumLength )
-	{
-	  return STATUS_BUFFER_OVERFLOW;
-	}
-	lstrcpynAtoW(uni->Buffer,ansi->Buffer,ansi->Length+1);
-	return STATUS_SUCCESS;
-}
 
 /**************************************************************************
- *	RtlUnicodeStringToOemString
- *
- * NOTES
- *   allocates uni->Length+1
- *   writes terminating 0
- */
-NTSTATUS
-WINAPI RtlUnicodeStringToOemString(
-	PANSI_STRING oem,
-	PUNICODE_STRING uni,
-	BOOLEAN doalloc)
-{
-	int len = uni->Length/sizeof(WCHAR);
-
-	TRACE("%p %s %i\n", oem, debugstr_us(uni), doalloc);
-
-	oem->Length = len;
-	if (doalloc)
-	{
-	  oem->Buffer = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len+1);
-	  if (! oem->Buffer) return STATUS_NO_MEMORY;
-	  oem->MaximumLength = len + 1;
-	}
-	else if (oem->MaximumLength <= len)
-	{
-	  return STATUS_BUFFER_OVERFLOW;
-	}
-	lstrcpynWtoA(oem->Buffer, uni->Buffer, len+1);
-	return STATUS_SUCCESS;
-}
-
-/**************************************************************************
- *	RtlUpcaseUnicodeStringToOemString
+ *	RtlUpcaseUnicodeStringToAnsiString   (NTDLL.@)
  *
  * NOTES
  *  writes terminating 0
  */
-NTSTATUS
-WINAPI RtlUpcaseUnicodeStringToOemString(
-	PANSI_STRING oem,
-	PUNICODE_STRING uni,
-	BOOLEAN doalloc)
+NTSTATUS WINAPI RtlUpcaseUnicodeStringToAnsiString( STRING *dst,
+                                                    const UNICODE_STRING *src,
+                                                    BOOLEAN doalloc )
 {
-	int i, len = uni->Length/sizeof(WCHAR);
+    NTSTATUS ret;
+    UNICODE_STRING upcase;
 
-	TRACE("%p %s %i\n", oem, debugstr_us(uni), doalloc);
-
-	oem->Length = len;
-	if (doalloc)
-	{
-	  oem->Buffer = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len+1);
-	  if (! oem->Buffer) return STATUS_NO_MEMORY;
-	  oem->MaximumLength = len + 1;
-	}
-	else if (oem->MaximumLength <= len)
-	{
-	  return STATUS_BUFFER_OVERFLOW;
-	}
-
-	for (i=0; i < len; i++)
-	{
-	  oem->Buffer[i] = toupperW((char)(uni->Buffer[i]));
-	}
-	oem->Buffer[i] = 0;
-	return STATUS_SUCCESS;
+    if (!(ret = RtlUpcaseUnicodeString( &upcase, src, TRUE )))
+    {
+        ret = RtlUnicodeStringToAnsiString( dst, &upcase, doalloc );
+        RtlFreeUnicodeString( &upcase );
+    }
+    return ret;
 }
 
+
 /**************************************************************************
- *	RtlUnicodeStringToAnsiString
+ *	RtlUpcaseUnicodeStringToOemString   (NTDLL.@)
  *
  * NOTES
  *  writes terminating 0
- *  copys a part if the buffer is to small
  */
-NTSTATUS
-WINAPI RtlUnicodeStringToAnsiString(
-	PANSI_STRING ansi,
-	PUNICODE_STRING uni,
-	BOOLEAN doalloc)
+NTSTATUS WINAPI RtlUpcaseUnicodeStringToOemString( STRING *dst,
+                                                   const UNICODE_STRING *src,
+                                                   BOOLEAN doalloc )
 {
-	int len = uni->Length/sizeof(WCHAR);
-	NTSTATUS ret = STATUS_SUCCESS;
+    NTSTATUS ret;
+    UNICODE_STRING upcase;
 
-	TRACE("%p %s %i\n", ansi, debugstr_us(uni), doalloc);
-
-	ansi->Length = len;
-	if (doalloc)
-	{
-	  ansi->Buffer = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len+1);
-	  if (! ansi->Buffer) return STATUS_NO_MEMORY;
-	  ansi->MaximumLength = len + 1;
-	}
-	else if (ansi->MaximumLength <= len)
-	{
-	  ansi->Length = ansi->MaximumLength - 1;
-	  ret = STATUS_BUFFER_OVERFLOW;
-	}
-	lstrcpynWtoA(ansi->Buffer, uni->Buffer, ansi->Length+1);
-	return ret;
-}
-
-/*
-	COPY BETWEEN ANSI/UNICODE_STRING AND MULTIBYTE STRINGS
-*/
-/**************************************************************************
- *	RtlMultiByteToUnicodeN
- *
- * NOTES
- *  dest can be equal to src
- *  if unistr is to small a part is copyed
- *
- * FIXME
- *  multibyte support
- */
-NTSTATUS
-WINAPI RtlMultiByteToUnicodeN(
-	LPWSTR unistr,
-	DWORD unilen,
-	LPDWORD reslen,
-	LPSTR oemstr,
-	DWORD oemlen)
-{
-	UINT len;
-	int i;
-
-	TRACE("%p %lu, %p, %s, %lu\n", oemstr, oemlen, reslen, debugstr_w(unistr), unilen);
-
-	len = (unilen/sizeof(WCHAR) < oemlen) ? unilen/sizeof(WCHAR) : oemlen;
-
-	for (i = len-1; i>=0; i--)
-	  unistr[i] = (WCHAR)oemstr[i];
-
-	if (reslen) *reslen = len * 2;
-	return 0;
-}
-
-/**************************************************************************
- *	RtlOemToUnicodeN
- */
-NTSTATUS
-WINAPI RtlOemToUnicodeN(
-	LPWSTR unistr,
-	DWORD unilen,
-	LPDWORD reslen,
-	LPSTR oemstr,
-	DWORD oemlen)
-{
-	UINT len;
-	int i;
-
-	TRACE("%p %lu, %p, %s, %lu\n", oemstr, oemlen, reslen, debugstr_w(unistr), unilen);
-
-	len = (unilen/sizeof(WCHAR) < oemlen) ? unilen/sizeof(WCHAR) : oemlen;
-
-	for (i = len-1; i>=0; i--)
-	  unistr[i] = (WCHAR)oemstr[i];
-
-	if (reslen) *reslen = len * 2;
-	return 0;
+    if (!(ret = RtlUpcaseUnicodeString( &upcase, src, TRUE )))
+    {
+        ret = RtlUnicodeStringToOemString( dst, &upcase, doalloc );
+        RtlFreeUnicodeString( &upcase );
+    }
+    return ret;
 }
 
 
 /**************************************************************************
- *	RtlUnicodeToOemN
+ *	RtlUpcaseUnicodeToMultiByteN   (NTDLL.@)
  */
-NTSTATUS
-WINAPI RtlUnicodeToOemN(
-	LPSTR oemstr,
-	DWORD oemlen,
-	LPDWORD reslen,
-	LPWSTR unistr,
-	DWORD unilen)
+NTSTATUS WINAPI RtlUpcaseUnicodeToMultiByteN( LPSTR dst, DWORD dstlen, LPDWORD reslen,
+                                              LPCWSTR src, DWORD srclen )
 {
-	UINT len;
-	int i;
+    NTSTATUS ret;
+    LPWSTR upcase;
+    DWORD i;
 
-	TRACE("%p %lu, %p, %s, %lu\n", oemstr, oemlen, reslen, debugstr_w(unistr), unilen);
-
-	len = (oemlen < unilen/sizeof(WCHAR)) ? unilen/sizeof(WCHAR) : oemlen;
-
-	for (i = len-1; i>=0; i--)
-	  oemstr[i] = (CHAR)unistr[i];
-
-	if (reslen) *reslen = len * 2;
-	return 0;
+    if (!(upcase = HeapAlloc( GetProcessHeap(), 0, srclen ))) return STATUS_NO_MEMORY;
+    for (i = 0; i < srclen/sizeof(WCHAR); i++) upcase[i] = toupperW(src[i]);
+    ret = RtlUnicodeToMultiByteN( dst, dstlen, reslen, upcase, srclen );
+    HeapFree( GetProcessHeap(), 0, upcase );
+    return ret;
 }
 
+
 /**************************************************************************
- *	RtlUpcaseUnicodeToOemN
+ *	RtlUpcaseUnicodeToOemN   (NTDLL.@)
  */
-NTSTATUS
-WINAPI RtlUpcaseUnicodeToOemN(
-	LPSTR oemstr,
-	DWORD oemlen,
-	LPDWORD reslen,
-	LPWSTR unistr,
-	DWORD unilen)
+NTSTATUS WINAPI RtlUpcaseUnicodeToOemN( LPSTR dst, DWORD dstlen, LPDWORD reslen,
+                                        LPCWSTR src, DWORD srclen )
 {
-	UINT len;
-	int i;
+    NTSTATUS ret;
+    LPWSTR upcase;
+    DWORD i;
 
-	TRACE("%p %lu, %p, %s, %lu\n", oemstr, oemlen, reslen, debugstr_w(unistr), unilen);
-
-	len = (oemlen < unilen/sizeof(WCHAR)) ? unilen/sizeof(WCHAR) : oemlen;
-
-	for (i = len-1; i>=0; i--)
-	  oemstr[i] = toupper((CHAR)unistr[i]);
-
-	if (reslen) *reslen = len * 2;
-	return 0;
+    if (!(upcase = HeapAlloc( GetProcessHeap(), 0, srclen ))) return STATUS_NO_MEMORY;
+    for (i = 0; i < srclen/sizeof(WCHAR); i++) upcase[i] = toupperW(src[i]);
+    ret = RtlUnicodeToOemN( dst, dstlen, reslen, upcase, srclen );
+    HeapFree( GetProcessHeap(), 0, upcase );
+    return ret;
 }
 
-/**************************************************************************
- *	RtlUnicodeToMultiByteN
- */
-NTSTATUS WINAPI RtlUnicodeToMultiByteN(
-	PCHAR  MbString,
-	ULONG  MbSize,
-	PULONG ResultSize,
-	PWCHAR UnicodeString,
-	ULONG  UnicodeSize)
-{
-        int Size = 0, i;
-
-	TRACE("(%p,%lu,%p,%p(%s),%lu)\n",
-	MbString, MbSize, ResultSize, UnicodeString, debugstr_w(UnicodeString), UnicodeSize);
-
-	Size = (UnicodeSize > (MbSize*sizeof(WCHAR))) ? MbSize: UnicodeSize/sizeof(WCHAR);
-
-	if (ResultSize != NULL) *ResultSize = Size;
-
-	for(i = 0; i < Size; i++)
-	{
-	  *(MbString++) = *(UnicodeString++);
-        }
-	return STATUS_SUCCESS;      
-}
 
 /*
 	STRING SIZE
-
-	Rtlx* supports multibyte
 */
 
 /**************************************************************************
- *	RtlxOemStringToUnicodeSize
- */
-UINT WINAPI RtlxOemStringToUnicodeSize(PSTRING str)
-{
-	return str->Length*2+2;
-}
-
-/**************************************************************************
- *	RtlxAnsiStringToUnicodeSize
- */
-UINT WINAPI RtlxAnsiStringToUnicodeSize(PANSI_STRING str)
-{
-	return str->Length*2+2;
-}
-
-/**************************************************************************
- *	RtlxUnicodeStringToOemSize
+ *      RtlOemStringToUnicodeSize   (NTDLL.@)
  *
+ * Return the size in bytes necessary for the Unicode conversion of 'str',
+ * including the terminating NULL.
  */
-UINT WINAPI RtlxUnicodeStringToOemSize(PUNICODE_STRING str)
+UINT WINAPI RtlOemStringToUnicodeSize(PSTRING str)
 {
-	return str->Length+1;
+    DWORD ret = MultiByteToWideChar( CP_OEMCP, 0, str->Buffer, str->Length, NULL, 0 );
+    return (ret + 1) * sizeof(WCHAR);
 }
 
+
+/**************************************************************************
+ *      RtlAnsiStringToUnicodeSize   (NTDLL.@)
+ *
+ * Return the size in bytes necessary for the Unicode conversion of 'str',
+ * including the terminating NULL.
+ */
+DWORD WINAPI RtlAnsiStringToUnicodeSize(PSTRING str)
+{
+    DWORD ret = MultiByteToWideChar( CP_ACP, 0, str->Buffer, str->Length, NULL, 0 );
+    return (ret + 1) * sizeof(WCHAR);
+}
+
+
+/**************************************************************************
+ *      RtlMultiByteToUnicodeSize   (NTDLL.@)
+ *
+ * Compute the size in bytes necessary for the Unicode conversion of 'str',
+ * without the terminating NULL.
+ */
+NTSTATUS WINAPI RtlMultiByteToUnicodeSize( DWORD *size, LPCSTR str, UINT len )
+{
+    *size = MultiByteToWideChar( CP_ACP, 0, str, len, NULL, 0 ) * sizeof(WCHAR);
+    return 0;
+}
+
+
+/**************************************************************************
+ *      RtlUnicodeToMultiByteSize   (NTDLL.@)
+ *
+ * Compute the size necessary for the multibyte conversion of 'str',
+ * without the terminating NULL.
+ */
+NTSTATUS WINAPI RtlUnicodeToMultiByteSize( DWORD *size, LPCWSTR str, UINT len )
+{
+    *size = WideCharToMultiByte( CP_ACP, 0, str, len / sizeof(WCHAR), NULL, 0, NULL, NULL );
+    return 0;
+}
+
+
+/**************************************************************************
+ *      RtlUnicodeStringToAnsiSize   (NTDLL.@)
+ *
+ * Return the size in bytes necessary for the Ansi conversion of 'str',
+ * including the terminating NULL.
+ */
+DWORD WINAPI RtlUnicodeStringToAnsiSize( const UNICODE_STRING *str )
+{
+    return WideCharToMultiByte( CP_ACP, 0, str->Buffer, str->Length / sizeof(WCHAR),
+                                NULL, 0, NULL, NULL ) + 1;
+}
+
+
+/**************************************************************************
+ *      RtlUnicodeStringToOemSize   (NTDLL.@)
+ *
+ * Return the size in bytes necessary for the OEM conversion of 'str',
+ * including the terminating NULL.
+ */
+DWORD WINAPI RtlUnicodeStringToOemSize( const UNICODE_STRING *str )
+{
+    return WideCharToMultiByte( CP_OEMCP, 0, str->Buffer, str->Length / sizeof(WCHAR),
+                                NULL, 0, NULL, NULL ) + 1;
+}
+
+
+/**************************************************************************
+ *      RtlAppendStringToString   (NTDLL.@)
+ */
+NTSTATUS WINAPI RtlAppendStringToString( STRING *dst, const STRING *src )
+{
+    unsigned int len = src->Length + dst->Length;
+    if (len > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
+    memcpy( dst->Buffer + dst->Length, src->Buffer, src->Length );
+    dst->Length = len;
+    return STATUS_SUCCESS;
+}
+
+
+/**************************************************************************
+ *      RtlAppendAsciizToString   (NTDLL.@)
+ */
+NTSTATUS WINAPI RtlAppendAsciizToString( STRING *dst, LPCSTR src )
+{
+    if (src)
+    {
+        unsigned int srclen = strlen(src);
+        unsigned int total  = srclen + dst->Length;
+        if (total > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
+        memcpy( dst->Buffer + dst->Length, src, srclen );
+        dst->Length = total;
+    }
+    return STATUS_SUCCESS;
+}
+
+
+/**************************************************************************
+ *      RtlAppendUnicodeToString   (NTDLL.@)
+ */
+NTSTATUS WINAPI RtlAppendUnicodeToString( UNICODE_STRING *dst, LPCWSTR src )
+{
+    if (src)
+    {
+        unsigned int srclen = strlenW(src) * sizeof(WCHAR);
+        unsigned int total  = srclen + dst->Length;
+        if (total > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
+        memcpy( dst->Buffer + dst->Length/sizeof(WCHAR), src, srclen );
+        dst->Length = total;
+        /* append terminating NULL if enough space */
+        if (total < dst->MaximumLength) dst->Buffer[total / sizeof(WCHAR)] = 0;
+    }
+    return STATUS_SUCCESS;
+}
+
+
+/**************************************************************************
+ *      RtlAppendUnicodeStringToString   (NTDLL.@)
+ */
+NTSTATUS WINAPI RtlAppendUnicodeStringToString( UNICODE_STRING *dst, const UNICODE_STRING *src )
+{
+    unsigned int len = src->Length + dst->Length;
+    if (len > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
+    memcpy( dst->Buffer + dst->Length/sizeof(WCHAR), src->Buffer, src->Length );
+    dst->Length = len;
+    /* append terminating NULL if enough space */
+    if (len < dst->MaximumLength) dst->Buffer[len / sizeof(WCHAR)] = 0;
+    return STATUS_SUCCESS;
+}
+
+
 /*
 	MISC
 */
@@ -600,16 +789,3 @@
 		*pf = out_flags;
 	return len;
 }
-
-/**************************************************************************
- *	RtlPrefixUnicodeString
- */
-NTSTATUS WINAPI RtlPrefixUnicodeString(
-	PUNICODE_STRING a,
-	PUNICODE_STRING b,
-	DWORD x)
-{
-	TRACE("(%s,%s,%lx)\n",debugstr_us(a),debugstr_us(b),x);
-	return STATUS_SUCCESS;
-}
-
diff --git a/include/ntddk.h b/include/ntddk.h
index f73b1ef..be4d954 100644
--- a/include/ntddk.h
+++ b/include/ntddk.h
@@ -585,91 +585,52 @@
 
 /*	string functions */
 
-VOID WINAPI RtlInitAnsiString(
-	PANSI_STRING target,
-	LPCSTR source);
-	
-VOID WINAPI RtlInitString(
-	PSTRING target,
-	LPCSTR source);
-	
-VOID WINAPI RtlInitUnicodeString(
-	PUNICODE_STRING target,
-	LPCWSTR source);
-	
-VOID WINAPI RtlFreeUnicodeString(
-	PUNICODE_STRING str);
-	
-VOID WINAPI RtlFreeAnsiString(
-	PANSI_STRING AnsiString);
-
-NTSTATUS WINAPI RtlAnsiStringToUnicodeString(
-	PUNICODE_STRING uni,
-	PANSI_STRING ansi,
-	BOOLEAN doalloc);
-
-NTSTATUS WINAPI RtlOemStringToUnicodeString(
-	PUNICODE_STRING uni,
-	PSTRING ansi,
-	BOOLEAN doalloc);
-	
-NTSTATUS WINAPI RtlMultiByteToUnicodeN(
-	LPWSTR unistr,
-	DWORD unilen,
-	LPDWORD reslen,
-	LPSTR oemstr,
-	DWORD oemlen);
-	
-NTSTATUS WINAPI RtlOemToUnicodeN(
-	LPWSTR unistr,
-	DWORD unilen,
-	LPDWORD reslen,
-	LPSTR oemstr,
-	DWORD oemlen);
-	
-NTSTATUS WINAPI RtlUnicodeToOemN(
-	LPSTR oemstr,
-	DWORD oemlen,
-	LPDWORD reslen,
-	LPWSTR unistr,
-	DWORD unilen);
-
-NTSTATUS WINAPI RtlUnicodeStringToOemString(
-	PANSI_STRING oem,
-	PUNICODE_STRING uni,
-	BOOLEAN alloc);
-
-NTSTATUS WINAPI RtlUnicodeStringToAnsiString(
-	PANSI_STRING oem,
-	PUNICODE_STRING uni,
-	BOOLEAN alloc);
-
-BOOLEAN WINAPI RtlEqualUnicodeString(
-	PUNICODE_STRING s1,
-	PUNICODE_STRING s2,
-	BOOLEAN x);
-
-DWORD WINAPI RtlUpcaseUnicodeString(
-	PUNICODE_STRING dest,
-	PUNICODE_STRING src,
-	BOOLEAN doalloc);
-
-UINT WINAPI RtlxOemStringToUnicodeSize(
-	PSTRING str);
-
-UINT WINAPI RtlxAnsiStringToUnicodeSize(
-	PANSI_STRING str);
+DWORD       WINAPI RtlAnsiStringToUnicodeSize(PSTRING);
+NTSTATUS    WINAPI RtlAnsiStringToUnicodeString(UNICODE_STRING*,const STRING *,BOOLEAN);
+NTSTATUS    WINAPI RtlAppendAsciizToString(STRING*,LPCSTR);
+NTSTATUS    WINAPI RtlAppendStringToString(STRING*,const STRING*);
+NTSTATUS    WINAPI RtlAppendUnicodeStringToString(UNICODE_STRING*,const UNICODE_STRING*);
+NTSTATUS    WINAPI RtlAppendUnicodeToString(UNICODE_STRING*,LPCWSTR);
+LONG        WINAPI RtlCompareString(const STRING*,const STRING*,BOOLEAN);
+LONG        WINAPI RtlCompareUnicodeString(const UNICODE_STRING*,const UNICODE_STRING*,BOOLEAN);
+void        WINAPI RtlCopyString(STRING*,const STRING*);
+void        WINAPI RtlCopyUnicodeString(UNICODE_STRING*,const UNICODE_STRING*);
+BOOLEAN     WINAPI RtlCreateUnicodeString(PUNICODE_STRING,LPCWSTR);
+BOOLEAN     WINAPI RtlCreateUnicodeStringFromAsciiz(PUNICODE_STRING,LPCSTR);
+void        WINAPI RtlEraseUnicodeString(UNICODE_STRING*);
+BOOLEAN     WINAPI RtlEqualString(const STRING*,const STRING*,BOOLEAN);
+BOOLEAN     WINAPI RtlEqualUnicodeString(const UNICODE_STRING*,const UNICODE_STRING*,BOOLEAN);
+void        WINAPI RtlFreeAnsiString(PSTRING);
+void        WINAPI RtlFreeOemString(PSTRING);
+void        WINAPI RtlFreeUnicodeString(PUNICODE_STRING);
+void        WINAPI RtlInitAnsiString(PSTRING,LPCSTR);
+void        WINAPI RtlInitString(PSTRING,LPCSTR);
+void        WINAPI RtlInitUnicodeString(PUNICODE_STRING,LPCWSTR);
+NTSTATUS    WINAPI RtlMultiByteToUnicodeN(LPWSTR,DWORD,LPDWORD,LPCSTR,DWORD);
+NTSTATUS    WINAPI RtlMultiByteToUnicodeSize(DWORD*,LPCSTR,UINT);
+UINT        WINAPI RtlOemStringToUnicodeSize(PSTRING);
+NTSTATUS    WINAPI RtlOemStringToUnicodeString(UNICODE_STRING*,const STRING*,BOOLEAN);
+NTSTATUS    WINAPI RtlOemToUnicodeN(LPWSTR,DWORD,LPDWORD,LPCSTR,DWORD);
+BOOLEAN     WINAPI RtlPrefixString(const STRING*,const STRING*,BOOLEAN);
+BOOLEAN     WINAPI RtlPrefixUnicodeString(const UNICODE_STRING*,const UNICODE_STRING*,BOOLEAN);
+DWORD       WINAPI RtlUnicodeStringToAnsiSize(const UNICODE_STRING*);
+NTSTATUS    WINAPI RtlUnicodeStringToAnsiString(STRING*,const UNICODE_STRING*,BOOLEAN);
+DWORD       WINAPI RtlUnicodeStringToOemSize(const UNICODE_STRING*);
+NTSTATUS    WINAPI RtlUnicodeStringToOemString(STRING*,const UNICODE_STRING*,BOOLEAN);
+NTSTATUS    WINAPI RtlUnicodeToMultiByteN(LPSTR,DWORD,LPDWORD,LPCWSTR,DWORD);
+NTSTATUS    WINAPI RtlUnicodeToMultiByteSize(DWORD*,LPCWSTR,UINT);
+NTSTATUS    WINAPI RtlUnicodeToOemN(LPSTR,DWORD,LPDWORD,LPCWSTR,DWORD);
+NTSTATUS    WINAPI RtlUpcaseUnicodeString(UNICODE_STRING*,const UNICODE_STRING *,BOOLEAN);
+NTSTATUS    WINAPI RtlUpcaseUnicodeStringToAnsiString(STRING*,const UNICODE_STRING*,BOOLEAN);
+NTSTATUS    WINAPI RtlUpcaseUnicodeStringToOemString(STRING*,const UNICODE_STRING*,BOOLEAN);
+NTSTATUS    WINAPI RtlUpcaseUnicodeToMultiByteN(LPSTR,DWORD,LPDWORD,LPCWSTR,DWORD);
+NTSTATUS    WINAPI RtlUpcaseUnicodeToOemN(LPSTR,DWORD,LPDWORD,LPCWSTR,DWORD);
 
 DWORD WINAPI RtlIsTextUnicode(
 	LPVOID buf,
 	DWORD len,
 	DWORD *pf);
 
-NTSTATUS WINAPI RtlCompareUnicodeString(
-	PUNICODE_STRING String1,
-	PUNICODE_STRING String2,
-	BOOLEAN CaseInSensitive);
-
 /*	resource functions */
 
 typedef struct _RTL_RWLOCK {