(Resend) some ntdll functions (part 1: functions)

thomas.mertes at gmx.at thomas.mertes at gmx.at
Tue Feb 18 06:21:28 CST 2003


Hello

This time (hopefully) not as html mail.
Here are implementations of some ntdll functions.
I have tested the functions a lot on w2k (see part2: tests).

Changelog:

	* dlls/ntdll/ntdll.spec, dlls/ntdll/large_int.c,
	  dlls/ntdll/rtl.c, dlls/ntdll/rtlstr.c,
	  include/winternl.h:
	Thomas Mertes <thomas.mertes at t-mobile.at>
	- Implement RtlCharToInteger, RtlExtendedMagicDivide, RtlUpperChar,
	  RtlInt64ToUnicodeString, RtlIntegerToChar, RtlIntegerToUnicodeString,
	  RtlLargeIntegerToChar, RtlUnicodeStringToInteger and
	  RtlUpcaseUnicodeChar
	- Use toupperW instead of toupper in RtlCompareUnicodeString

Greetings
Thomas Mertes


-- 
+++ GMX - Mail, Messaging & more  http://www.gmx.net +++
Bitte lächeln! Fotogalerie online mit GMX ohne eigene Homepage!
-------------- next part --------------
diff -urN old_wine-20030115/dlls/ntdll/large_int.c new_wine-20030115/dlls/ntdll/large_int.c
--- old_wine-20030115/dlls/ntdll/large_int.c	Tue Dec 10 23:56:45 2002
+++ new_wine-20030115/dlls/ntdll/large_int.c	Wed Feb 12 00:31:34 2003
@@ -2,6 +2,7 @@
  * Large integer functions
  *
  * Copyright 2000 Alexandre Julliard
+ * Copyright 2003 Thomas Mertes
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -191,13 +192,174 @@
  * must be chosen such that b = 2^(64+shift) / c.
  * Then we have RtlExtendedMagicDivide(a,b,shift) == a * b / 2^(64+shift) == a / c.
  *
- * I'm too lazy to implement it right now...
- */
-/* LONGLONG WINAPI RtlExtendedMagicDivide( LONGLONG a, LONGLONG b, INT shift )
- * {
- *     return 0;
- * }
+ * Parameter b altrough defined as LONGLONG is used as ULONGLONG.
  */
+#define LOWER_32(A) ((A) & 0xffffffff)
+#define UPPER_32(A) ((A) >> 32)
+LONGLONG WINAPI RtlExtendedMagicDivide(
+	LONGLONG a,
+	LONGLONG b,
+	INT shift)
+{
+    ULONGLONG a_high;
+    ULONGLONG a_low;
+    ULONGLONG b_high;
+    ULONGLONG b_low;
+    ULONGLONG ah_bl;
+    ULONGLONG al_bh;
+    LONGLONG result;
+    int positive;
+
+    if (a < 0) {
+	a_high = UPPER_32((ULONGLONG) -a);
+	a_low =  LOWER_32((ULONGLONG) -a);
+	positive = 0;
+    } else {
+	a_high = UPPER_32((ULONGLONG) a);
+	a_low =  LOWER_32((ULONGLONG) a);
+	positive = 1;
+    } /* if */
+    b_high = UPPER_32((ULONGLONG) b);
+    b_low =  LOWER_32((ULONGLONG) b);
+
+    ah_bl = a_high * b_low;
+    al_bh = a_low * b_high;
+
+    result = (LONGLONG) ((a_high * b_high +
+	    UPPER_32(ah_bl) +
+	    UPPER_32(al_bh) +
+	    UPPER_32(LOWER_32(ah_bl) + LOWER_32(al_bh) + UPPER_32(a_low * b_low))) >> shift);
+
+    if (positive) {
+	return result;
+    } else {
+	return -result;
+    } /* if */
+}
+
+
+/******************************************************************************
+ *      RtlLargeIntegerToChar	[NTDLL.@]
+ *
+ * Convert an unsigned large integer to a character string.
+ *
+ * On success assign a string and return STATUS_SUCCESS.
+ * If base is not 0 (=10), 2, 8, 10 or 16 return STATUS_INVALID_PARAMETER
+ * Writes at most length characters to the string str.
+ * Str is '\0' terminated when length allowes it.
+ * When str fits exactly in length characters the '\0' is ommitted.
+ * When str would be larger than length: return STATUS_BUFFER_OVERFLOW
+ * For str == NULL return STATUS_ACCESS_VIOLATION.
+ * Do not check for value_ptr != NULL (as native DLL).
+ *
+ * Difference:
+ * - Accept base 0 as 10 instead of crashing as native DLL does.
+ * - The native DLL does produce garbage or STATUS_BUFFER_OVERFLOW for
+ *   base 2, 8 and 16 when the value is larger than 0xFFFFFFFF. 
+ */
+NTSTATUS WINAPI RtlLargeIntegerToChar(
+	ULONGLONG *value_ptr,
+	ULONG base,
+	ULONG length,
+	PCHAR str)
+{
+    ULONGLONG value = *value_ptr;
+    CHAR buffer[65];
+    PCHAR pos;
+    CHAR digit;
+    ULONG len;
+
+    if (base == 0) {
+	base = 10;
+    } else if (base != 2 && base != 8 && base != 10 && base != 16) {
+	return STATUS_INVALID_PARAMETER;
+    } /* if */
+
+    pos = &buffer[64];
+    *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[64] - 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;
+}
+
+
+/**************************************************************************
+ *      RtlInt64ToUnicodeString (NTDLL.@)
+ *
+ * Convert a large unsigned integer to a NULL terminated unicode string.
+ *
+ * On success assign a NULL terminated string and return STATUS_SUCCESS.
+ * If base is not 0 (=10), 2, 8, 10 or 16 return STATUS_INVALID_PARAMETER.
+ * If str is too small to hold the string (with the NULL termination):
+ * Set str->Length to the length the string would have (which can be
+ * larger than the MaximumLength) and return STATUS_BUFFER_OVERFLOW.
+ * Do not check for str != NULL (as native DLL).
+ *
+ * Difference:
+ * - Accept base 0 as 10 instead of crashing as native DLL does.
+ * - Do not return STATUS_BUFFER_OVERFLOW when the string is long enough.
+ *   The native DLL does this when the string would be longer than 31
+ *   characters even when the string parameter is long enough.
+ * - The native DLL does produce garbage or STATUS_BUFFER_OVERFLOW for
+ *   base 2, 8 and 16 when the value is larger than 0xFFFFFFFF. 
+ */
+NTSTATUS WINAPI RtlInt64ToUnicodeString(
+	ULONGLONG value,
+	ULONG base,
+	UNICODE_STRING *str)
+{
+    WCHAR buffer[65];
+    PWCHAR pos;
+    WCHAR digit;
+
+    if (base == 0) {
+	base = 10;
+    } else if (base != 2 && base != 8 && base != 10 && base != 16) {
+	return STATUS_INVALID_PARAMETER;
+    } /* if */
+
+    pos = &buffer[64];
+    *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);
+
+    str->Length = (&buffer[64] - pos) * sizeof(WCHAR);
+    if (str->Length >= str->MaximumLength) {
+	return STATUS_BUFFER_OVERFLOW;
+    } else {
+	memcpy(str->Buffer, pos, str->Length + 1);
+    } /* if */
+    return STATUS_SUCCESS;
+}
 
 
 /******************************************************************************
diff -urN old_wine-20030115/dlls/ntdll/ntdll.spec new_wine-20030115/dlls/ntdll/ntdll.spec
--- old_wine-20030115/dlls/ntdll/ntdll.spec	Mon Jan 13 21:44:14 2003
+++ new_wine-20030115/dlls/ntdll/ntdll.spec	Wed Feb 12 00:32:12 2003
@@ -289,7 +289,7 @@
 @ stdcall RtlAreBitsSet(ptr long long) RtlAreBitsSet
 @ stdcall RtlAssert(ptr ptr long long) RtlAssert
 @ stub RtlCaptureStackBackTrace
-@ stub RtlCharToInteger
+@ stdcall RtlCharToInteger(ptr long ptr) RtlCharToInteger
 @ stub RtlCheckRegistryKey
 @ stdcall RtlClearAllBits(ptr) RtlClearAllBits
 @ stdcall RtlClearBits(ptr long long) RtlClearBits
@@ -367,7 +367,7 @@
 @ stub RtlExtendHeap
 @ stdcall -ret64 RtlExtendedIntegerMultiply(long long long) RtlExtendedIntegerMultiply
 @ stdcall -ret64 RtlExtendedLargeIntegerDivide(long long long ptr) RtlExtendedLargeIntegerDivide
-@ stub RtlExtendedMagicDivide
+@ stdcall -ret64 RtlExtendedMagicDivide(long long long long long) RtlExtendedMagicDivide
 @ stdcall RtlFillMemory(ptr long long) RtlFillMemory
 @ stdcall RtlFillMemoryUlong(ptr long long) RtlFillMemoryUlong
 @ stdcall RtlFindClearBits(ptr long long) RtlFindClearBits
@@ -432,8 +432,9 @@
 @ stdcall RtlInitializeResource(ptr) RtlInitializeResource
 @ stdcall RtlInitializeSid(ptr ptr long) RtlInitializeSid
 @ stub RtlInsertElementGenericTable
-@ stdcall RtlIntegerToChar(long long long long) RtlIntegerToChar
-@ stub RtlIntegerToUnicodeString
+@ stdcall RtlInt64ToUnicodeString(long long long ptr) RtlInt64ToUnicodeString
+@ stdcall RtlIntegerToChar(long long long ptr) RtlIntegerToChar
+@ stdcall RtlIntegerToUnicodeString(long long ptr) RtlIntegerToUnicodeString
 @ stub RtlIsDosDeviceName_U
 @ stub RtlIsGenericTableEmpty
 @ stub RtlIsNameLegalDOS8Dot3
@@ -445,7 +446,7 @@
 @ stdcall -ret64 RtlLargeIntegerShiftLeft(long long long) RtlLargeIntegerShiftLeft
 @ stdcall -ret64 RtlLargeIntegerShiftRight(long long long) RtlLargeIntegerShiftRight
 @ stdcall -ret64 RtlLargeIntegerSubtract(long long long long) RtlLargeIntegerSubtract
-@ stub RtlLargeIntegerToChar
+@ stdcall RtlLargeIntegerToChar(ptr long long ptr) RtlLargeIntegerToChar
 @ stdcall RtlLeaveCriticalSection(ptr) RtlLeaveCriticalSection
 @ stdcall RtlLengthRequiredSid(long) RtlLengthRequiredSid
 @ stdcall RtlLengthSecurityDescriptor(ptr) RtlLengthSecurityDescriptor
@@ -540,7 +541,7 @@
 @ stub RtlUniform
 @ stdcall RtlUnlockHeap(long) RtlUnlockHeap
 @ stdcall RtlUnwind(ptr ptr ptr long) RtlUnwind
-@ stub RtlUpcaseUnicodeChar
+@ stdcall RtlUpcaseUnicodeChar(long) RtlUpcaseUnicodeChar
 @ stdcall RtlUpcaseUnicodeString(ptr ptr long) RtlUpcaseUnicodeString
 @ stdcall RtlUpcaseUnicodeStringToAnsiString(ptr ptr long) RtlUpcaseUnicodeStringToAnsiString
 @ stub RtlUpcaseUnicodeStringToCountedOemString
@@ -548,7 +549,7 @@
 @ stub RtlUpcaseUnicodeToCustomCPN
 @ stdcall RtlUpcaseUnicodeToMultiByteN(ptr long ptr ptr long) RtlUpcaseUnicodeToMultiByteN
 @ stdcall RtlUpcaseUnicodeToOemN(ptr long ptr ptr long) RtlUpcaseUnicodeToOemN
-@ stub RtlUpperChar
+@ stdcall RtlUpperChar(long) RtlUpperChar
 @ stdcall RtlUpperString(ptr ptr) RtlUpperString
 @ stub RtlUsageHeap
 @ stub RtlValidAcl
diff -urN old_wine-20030115/dlls/ntdll/rtl.c new_wine-20030115/dlls/ntdll/rtl.c
--- old_wine-20030115/dlls/ntdll/rtl.c	Thu Nov 21 04:45:03 2002
+++ new_wine-20030115/dlls/ntdll/rtl.c	Wed Feb 12 00:31:49 2003
@@ -262,13 +262,6 @@
 }
 
 /******************************************************************************
- *  RtlIntegerToChar	[NTDLL.@]
- */
-DWORD WINAPI RtlIntegerToChar(DWORD x1,DWORD x2,DWORD x3,DWORD x4) {
-	FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4);
-	return 0;
-}
-/******************************************************************************
  *  RtlSetEnvironmentVariable		[NTDLL.@]
  */
 DWORD WINAPI RtlSetEnvironmentVariable(DWORD x1,PUNICODE_STRING key,PUNICODE_STRING val) {
diff -urN old_wine-20030115/dlls/ntdll/rtlstr.c new_wine-20030115/dlls/ntdll/rtlstr.c
--- old_wine-20030115/dlls/ntdll/rtlstr.c	Tue Nov 12 03:17:34 2002
+++ new_wine-20030115/dlls/ntdll/rtlstr.c	Wed Feb 12 00:31:41 2003
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 1996-1998 Marcus Meissner
  * Copyright (C) 2000      Alexandre Julliard
+ * Copyright (C) 2003      Thomas Mertes
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -198,10 +199,12 @@
     }
 }
 
+
 /*
     COMPARISON FUNCTIONS
 */
 
+
 /******************************************************************************
  *	RtlCompareString   (NTDLL.@)
  */
@@ -315,7 +318,7 @@
     if (ignore_case)
     {
         for (i = 0; i < s1->Length / sizeof(WCHAR); i++)
-            if (toupper(s1->Buffer[i]) != toupper(s2->Buffer[i])) return FALSE;
+            if (toupperW(s1->Buffer[i]) != toupperW(s2->Buffer[i])) return FALSE;
     }
     else
     {
@@ -515,6 +518,20 @@
      CASE CONVERSIONS
 */
 
+
+/**************************************************************************
+ *	RtlUpperChar   (NTDLL.@)
+ */
+CHAR WINAPI RtlUpperChar( CHAR ch )
+{
+    if (ch >= 'a' && ch <= 'z') {
+        return ch - 'a' + 'A';
+    } else {
+        return ch;
+    }
+}
+
+
 /**************************************************************************
  *	RtlUpperString   (NTDLL.@)
  */
@@ -522,12 +539,21 @@
 {
     unsigned int i, len = min(src->Length, dst->MaximumLength);
 
-    for (i = 0; i < len; i++) dst->Buffer[i] = toupper(src->Buffer[i]);
+    for (i = 0; i < len; i++) dst->Buffer[i] = RtlUpperChar(src->Buffer[i]);
     dst->Length = len;
 }
 
 
 /**************************************************************************
+ *	RtlUpcaseUnicodeChar   (NTDLL.@)
+ */
+WCHAR WINAPI RtlUpcaseUnicodeChar( WCHAR wch )
+{
+    return toupperW(wch);
+}
+
+
+/**************************************************************************
  *	RtlUpcaseUnicodeString   (NTDLL.@)
  *
  * NOTES:
@@ -638,6 +664,7 @@
 	STRING SIZE
 */
 
+
 /**************************************************************************
  *      RtlOemStringToUnicodeSize   (NTDLL.@)
  *      RtlxOemStringToUnicodeSize  (NTDLL.@)
@@ -790,6 +817,7 @@
 	MISC
 */
 
+
 /**************************************************************************
  *	RtlIsTextUnicode (NTDLL.@)
  *
@@ -836,75 +864,295 @@
 	return len;
 }
 
+
 /**************************************************************************
- *	RtlUnicodeStringToInteger (NTDLL.@)
+ *      RtlCharToInteger   (NTDLL.@)
+ *
+ * Convert a character string into its integer equivalent.
  *
- *	Convert a text buffer into its integer form
+ * On success assign an integer value and return STATUS_SUCCESS.
+ * For base 0 accept: {whitespace} [+|-] [0[x|o|b]] {digits}
+ * For bases 2, 8, 10 and 16 accept: {whitespace} [+|-] {digits}
+ * For other bases return STATUS_INVALID_PARAMETER.
+ * For value == NULL return STATUS_ACCESS_VIOLATION.
+ * No check of value overflow: Just assign lower 32 bits (as native DLL).
+ * Do not check for str != NULL (as native DLL).
+ *
+ * Difference:
+ * - Do not read garbage behind '\0' as native DLL does.
+ */
+NTSTATUS WINAPI RtlCharToInteger(
+	PCSZ str,
+	ULONG base,
+	ULONG *value)
+{
+    CHAR chCurrent;
+    int digit;
+    ULONG RunningTotal = 0;
+    char bMinus = 0;
+
+    while (*str != '\0' && *str <= ' ') {
+	str++;
+    } /* while */
+
+    if (*str == '+') {
+	str++;
+    } else if (*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 */
+    } else if (base != 2 && base != 8 && base != 10 && base != 16) {
+	return STATUS_INVALID_PARAMETER;
+    } /* if */
+
+    if (value == NULL) {
+	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 >= base) {
+	    *value = bMinus ? -RunningTotal : RunningTotal;
+	    return STATUS_SUCCESS;
+	} /* if */
+
+	RunningTotal = RunningTotal * base + digit;
+	str++;
+    } /* while */
+
+    *value = bMinus ? -RunningTotal : RunningTotal;
+    return STATUS_SUCCESS;
+}
+
+
+/**************************************************************************
+ *      RtlIntegerToChar   (NTDLL.@)
+ *
+ * Convert an unsigned integer to a character string.
+ *
+ * On success assign a string and return STATUS_SUCCESS.
+ * If base is not 0 (=10), 2, 8, 10 or 16 return STATUS_INVALID_PARAMETER
+ * Writes at most length characters to the string str.
+ * Str is '\0' terminated when length allowes it.
+ * When str fits exactly in length characters the '\0' is ommitted.
+ * When str would be larger than length: return STATUS_BUFFER_OVERFLOW
+ * For str == NULL return STATUS_ACCESS_VIOLATION.
+ */
+NTSTATUS WINAPI RtlIntegerToChar(
+	ULONG value,
+	ULONG base,
+	ULONG length,
+	PCHAR str)
+{
+    CHAR buffer[33];
+    PCHAR pos;
+    CHAR digit;
+    ULONG len;
+
+    if (base == 0) {
+	base = 10;
+    } else if (base != 2 && base != 8 && base != 10 && base != 16) {
+	return STATUS_INVALID_PARAMETER;
+    } /* if */
+
+    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;
+}
+
+
+/**************************************************************************
+ *      RtlUnicodeStringToInteger (NTDLL.@)
+ *
+ * Convert an unicode string into its integer equivalent.
+ *
+ * On success assign an integer value and return STATUS_SUCCESS.
+ * For base 0 accept: {whitespace} [+|-] [0[x|o|b]] {digits}
+ * For bases 2, 8, 10 and 16 accept: {whitespace} [+|-] {digits}
+ * For other bases return STATUS_INVALID_PARAMETER.
+ * For value == NULL return STATUS_ACCESS_VIOLATION.
+ * No check of value overflow: Just assign lower 32 bits (as native DLL).
+ * Do not check for str != NULL (as native DLL).
+ *
+ * Difference:
+ * - Do not read garbage on string length 0 as native DLL does.
  */
 NTSTATUS WINAPI RtlUnicodeStringToInteger(
 	const UNICODE_STRING *str,
-	int base,
-	int * pdest)
+	ULONG base,
+	ULONG *value)
 {
-	LPWSTR lpwstr = str->Buffer;
-	WCHAR wchCurrent = 0;
-	int CharsParsed = 0;
-	int RunningTotal = 0;
-	char bMinus = 0;
-
-	/* no checking done on UNICODE_STRING and int* in native DLL either */
-	TRACE("(%p, %d, %p)", str, base, pdest);
-
-	switch (base)
-	{
-		case 0:
-			base = 10;
-			break;
-		case 2:
-		case 8:
-		case 10:
-		case 16:
-			break;
-		default:
-			return STATUS_INVALID_PARAMETER;
-	}
-
-	if ((str->Length) >= 4 && (base == 10) && (*lpwstr == '0') && (*(lpwstr+1) == 'x'))
-	{
-		lpwstr+=2;
+    LPWSTR lpwstr = str->Buffer;
+    USHORT CharsRemaining = str->Length / sizeof(WCHAR);
+    WCHAR wchCurrent;
+    int digit;
+    ULONG RunningTotal = 0;
+    char bMinus = 0;
+
+    while (CharsRemaining >= 1 && *lpwstr <= ' ') {
+	lpwstr++;
+	CharsRemaining--;
+    } /* while */
+
+    if (CharsRemaining >= 1) {
+	if (*lpwstr == '+') {
+	    lpwstr++;
+	    CharsRemaining--;
+	} else if (*lpwstr == '-') {
+	    bMinus = 1;
+	    lpwstr++;
+	    CharsRemaining--;
+	} /* if */
+    } /* if */
+
+    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;
+    } /* if */
+
+    while (CharsRemaining >= 1) {
+	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 */
 
-	*pdest = 0;
-	for (; (CharsParsed*sizeof(WCHAR) < str->Length) && (*lpwstr <= ' '); lpwstr++)
-		CharsParsed++;
-
-	if (*lpwstr == '+')
-		lpwstr++;
-	else if (*lpwstr == '-')
-	{
-		bMinus = 1;
-		lpwstr++;
-	}
-
-	for (; (CharsParsed*sizeof(WCHAR) < str->Length) && (*lpwstr != '\0'); lpwstr++)
-	{
-		CharsParsed++;
-		wchCurrent = *lpwstr;
-		if (wchCurrent >= 'A')
-			wchCurrent = '0' + 10 + wchCurrent - 'A';
-		if ((wchCurrent - '0') >= base || wchCurrent < '0')
-		{
-			*pdest = bMinus ? -RunningTotal: RunningTotal;
-			return STATUS_SUCCESS;
-		}
-		/*
-		 * increase significance of previous digits each time
-		 * we find another valid one and add on this valid one
-		 */
-		RunningTotal = wchCurrent - '0' + RunningTotal * base;
-	}
+    *value = bMinus ? -RunningTotal : RunningTotal;
+    return STATUS_SUCCESS;
+}
 
-	*pdest = bMinus ? -RunningTotal : RunningTotal;
-	return STATUS_SUCCESS;
+
+/**************************************************************************
+ *	RtlIntegerToUnicodeString (NTDLL.@)
+ *
+ * Convert an unsigned integer to a NULL terminated unicode string.
+ *
+ * On success assign a NULL terminated string and return STATUS_SUCCESS.
+ * If base is not 0 (=10), 2, 8, 10 or 16 return STATUS_INVALID_PARAMETER.
+ * If str is too small to hold the string (with the NULL termination):
+ * Set str->Length to the length the string would have (which can be
+ * larger than the MaximumLength) and return STATUS_BUFFER_OVERFLOW.
+ * Do not check for str != NULL (as native DLL).
+ *
+ * Difference:
+ * - Do not return STATUS_BUFFER_OVERFLOW when the string is long enough.
+ *   The native DLL does this when the string would be longer than 16
+ *   characters even when the string parameter is long enough.
+ */
+NTSTATUS WINAPI RtlIntegerToUnicodeString(
+	ULONG value,
+	ULONG base,
+	UNICODE_STRING *str)
+{
+    WCHAR buffer[33];
+    PWCHAR pos;
+    WCHAR digit;
+
+    if (base == 0) {
+	base = 10;
+    } else if (base != 2 && base != 8 && base != 10 && base != 16) {
+	return STATUS_INVALID_PARAMETER;
+    } /* if */
+
+    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);
+
+    str->Length = (&buffer[32] - pos) * sizeof(WCHAR);
+    if (str->Length >= str->MaximumLength) {
+	return STATUS_BUFFER_OVERFLOW;
+    } else {
+	memcpy(str->Buffer, pos, str->Length + 1);
+    } /* if */
+    return STATUS_SUCCESS;
 }
diff -urN old_wine-20030115/include/winternl.h new_wine-20030115/include/winternl.h
--- old_wine-20030115/include/winternl.h	Sat Jan  4 01:52:19 2003
+++ new_wine-20030115/include/winternl.h	Wed Feb 12 00:32:53 2003
@@ -977,7 +977,9 @@
 void      WINAPI RtlInitializeResource(LPRTL_RWLOCK);
 BOOL      WINAPI RtlInitializeSid(PSID,PSID_IDENTIFIER_AUTHORITY,BYTE);
 
-DWORD     WINAPI RtlIntegerToChar(DWORD,DWORD,DWORD,DWORD);
+NTSTATUS  WINAPI RtlInt64ToUnicodeString(ULONGLONG,ULONG,UNICODE_STRING *);
+NTSTATUS  WINAPI RtlIntegerToChar(ULONG,ULONG,ULONG,PCHAR);
+NTSTATUS  WINAPI RtlIntegerToUnicodeString(ULONG,ULONG,UNICODE_STRING *);
 BOOLEAN   WINAPI RtlIsNameLegalDOS8Dot3(PUNICODE_STRING,POEM_STRING,PBOOLEAN);
 DWORD     WINAPI RtlIsTextUnicode(LPVOID,DWORD,DWORD *);
 
@@ -988,6 +990,7 @@
 LONGLONG  WINAPI RtlLargeIntegerShiftLeft(LONGLONG,INT);
 LONGLONG  WINAPI RtlLargeIntegerShiftRight(LONGLONG,INT);
 LONGLONG  WINAPI RtlLargeIntegerSubtract(LONGLONG,LONGLONG);
+NTSTATUS  WINAPI RtlLargeIntegerToChar(ULONGLONG *,ULONG,ULONG,PCHAR);
 NTSTATUS  WINAPI RtlLeaveCriticalSection(RTL_CRITICAL_SECTION *);
 DWORD     WINAPI RtlLengthRequiredSid(DWORD);
 ULONG     WINAPI RtlLengthSecurityDescriptor(PSECURITY_DESCRIPTOR);
@@ -1045,6 +1048,7 @@
 
 DWORD     WINAPI RtlUnicodeStringToAnsiSize(const UNICODE_STRING*);
 NTSTATUS  WINAPI RtlUnicodeStringToAnsiString(PANSI_STRING,PCUNICODE_STRING,BOOLEAN);
+NTSTATUS  WINAPI RtlUnicodeStringToInteger(const UNICODE_STRING *,ULONG,ULONG *);
 DWORD     WINAPI RtlUnicodeStringToOemSize(const UNICODE_STRING*);
 NTSTATUS  WINAPI RtlUnicodeStringToOemString(POEM_STRING,PCUNICODE_STRING,BOOLEAN);
 NTSTATUS  WINAPI RtlUnicodeToMultiByteN(LPSTR,DWORD,LPDWORD,LPCWSTR,DWORD);
@@ -1057,11 +1061,14 @@
 void      WINAPI RtlUnwind2(FRAME_POINTERS,PVOID,PEXCEPTION_RECORD,PVOID,PCONTEXT);
 void      WINAPI RtlUnwindEx(FRAME_POINTERS,PVOID,PEXCEPTION_RECORD,PVOID,PCONTEXT,PUNWIND_HISTORY_TABLE);
 #endif
+WCHAR     WINAPI RtlUpcaseUnicodeChar(WCHAR);
 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);
+CHAR      WINAPI RtlUpperChar(CHAR);
+void      WINAPI RtlUpperString(STRING *,const STRING *);
 
 NTSTATUS  WINAPI RtlValidSecurityDescriptor(PSECURITY_DESCRIPTOR);
 BOOL      WINAPI RtlValidSid(PSID);


More information about the wine-patches mailing list