mirror of
https://github.com/reactos/reactos.git
synced 2024-12-30 19:14:31 +00:00
Fireball patch for fixing RtlUnicodeStringToInteger and RtlCharToInteger
<Fireball> Imported WINE's RtlUnicodeStringToInteger and RtlCharToInteger - they were seriously broken in our revision. Thanks to GreatLord for his help pointing out this bug with me :) svn path=/trunk/; revision=15092
This commit is contained in:
parent
456be5d16b
commit
f6b87bd320
1 changed files with 166 additions and 121 deletions
|
@ -154,51 +154,96 @@ RtlAppendUnicodeStringToString(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**************************************************************************
|
||||||
|
* RtlCharToInteger (NTDLL.@)
|
||||||
* @implemented
|
* @implemented
|
||||||
|
* Converts a character string into its integer equivalent.
|
||||||
|
*
|
||||||
|
* RETURNS
|
||||||
|
* Success: STATUS_SUCCESS. value contains the converted number
|
||||||
|
* Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
|
||||||
|
* STATUS_ACCESS_VIOLATION, if value is NULL.
|
||||||
|
*
|
||||||
|
* NOTES
|
||||||
|
* For base 0 it uses 10 as base and the string should be in the format
|
||||||
|
* "{whitespace} [+|-] [0[x|o|b]] {digits}".
|
||||||
|
* For other bases the string should be in the format
|
||||||
|
* "{whitespace} [+|-] {digits}".
|
||||||
|
* No check is made for value overflow, only the lower 32 bits are assigned.
|
||||||
|
* If str is NULL it crashes, as the native function does.
|
||||||
|
*
|
||||||
|
* DIFFERENCES
|
||||||
|
* This function does not read garbage behind '\0' as the native version does.
|
||||||
*/
|
*/
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
STDCALL
|
STDCALL
|
||||||
RtlCharToInteger(
|
RtlCharToInteger(
|
||||||
IN PCSZ String,
|
PCSZ str, /* [I] '\0' terminated single-byte string containing a number */
|
||||||
IN ULONG Base,
|
ULONG base, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
|
||||||
IN OUT PULONG Value)
|
PULONG value) /* [O] Destination for the converted value */
|
||||||
{
|
{
|
||||||
ULONG Val;
|
CHAR chCurrent;
|
||||||
|
int digit;
|
||||||
|
ULONG RunningTotal = 0;
|
||||||
|
char bMinus = 0;
|
||||||
|
|
||||||
*Value = 0;
|
while (*str != '\0' && *str <= ' ') {
|
||||||
|
str++;
|
||||||
|
} /* while */
|
||||||
|
|
||||||
if (Base == 0)
|
if (*str == '+') {
|
||||||
{
|
str++;
|
||||||
Base = 10;
|
} else if (*str == '-') {
|
||||||
if (*String == '0')
|
bMinus = 1;
|
||||||
{
|
str++;
|
||||||
Base = 8;
|
} /* if */
|
||||||
String++;
|
|
||||||
if ((*String == 'x') && isxdigit (String[1]))
|
|
||||||
{
|
|
||||||
String++;
|
|
||||||
Base = 16;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isxdigit (*String))
|
if (base == 0) {
|
||||||
return STATUS_INVALID_PARAMETER;
|
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 */
|
||||||
|
|
||||||
while (isxdigit (*String) &&
|
if (value == NULL) {
|
||||||
(Val = isdigit (*String) ? * String - '0' : (islower (*String)
|
return STATUS_ACCESS_VIOLATION;
|
||||||
? toupper (*String) : *String) - 'A' + 10) < Base)
|
} /* if */
|
||||||
{
|
|
||||||
*Value = *Value * Base + Val;
|
|
||||||
String++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
|
@ -807,113 +852,113 @@ RtlPrefixUnicodeString(
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* RtlUnicodeStringToInteger (NTDLL.@)
|
||||||
/*
|
|
||||||
* @implemented
|
* @implemented
|
||||||
|
* Converts an unicode string into its integer equivalent.
|
||||||
*
|
*
|
||||||
* Note that regardless of success or failure status, we should leave the
|
* RETURNS
|
||||||
* partial value in Value. An error is never returned based on the chars
|
* Success: STATUS_SUCCESS. value contains the converted number
|
||||||
* in the string.
|
* Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
|
||||||
|
* STATUS_ACCESS_VIOLATION, if value is NULL.
|
||||||
*
|
*
|
||||||
* This function does check the base. Only 2, 8, 10, 16 are permitted,
|
* NOTES
|
||||||
* else STATUS_INVALID_PARAMETER is returned.
|
* For base 0 it uses 10 as base and the string should be in the format
|
||||||
|
* "{whitespace} [+|-] [0[x|o|b]] {digits}".
|
||||||
|
* For other bases the string should be in the format
|
||||||
|
* "{whitespace} [+|-] {digits}".
|
||||||
|
* No check is made for value overflow, only the lower 32 bits are assigned.
|
||||||
|
* If str is NULL it crashes, as the native function does.
|
||||||
|
*
|
||||||
|
* Note that regardless of success or failure status, we should leave the
|
||||||
|
* partial value in Value. An error is never returned based on the chars
|
||||||
|
* in the string.
|
||||||
|
*
|
||||||
|
* DIFFERENCES
|
||||||
|
* This function does not read garbage on string length 0 as the native
|
||||||
|
* version does.
|
||||||
*/
|
*/
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
STDCALL
|
STDCALL
|
||||||
RtlUnicodeStringToInteger(
|
RtlUnicodeStringToInteger(
|
||||||
IN PUNICODE_STRING String,
|
PUNICODE_STRING str, /* [I] Unicode string to be converted */
|
||||||
IN ULONG Base,
|
ULONG base, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
|
||||||
OUT PULONG Value)
|
PULONG value) /* [O] Destination for the converted value */
|
||||||
{
|
{
|
||||||
PWCHAR Str;
|
LPWSTR lpwstr = str->Buffer;
|
||||||
ULONG lenmin = 0;
|
USHORT CharsRemaining = str->Length / sizeof(WCHAR);
|
||||||
ULONG i;
|
WCHAR wchCurrent;
|
||||||
ULONG Val;
|
int digit;
|
||||||
BOOLEAN addneg = FALSE;
|
ULONG RunningTotal = 0;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
char bMinus = 0;
|
||||||
|
|
||||||
*Value = 0;
|
while (CharsRemaining >= 1 && *lpwstr <= ' ') {
|
||||||
Str = String->Buffer;
|
lpwstr++;
|
||||||
|
CharsRemaining--;
|
||||||
|
} /* while */
|
||||||
|
|
||||||
if( Base && Base != 2 && Base != 8 && Base != 10 && Base != 16 )
|
if (CharsRemaining >= 1) {
|
||||||
return STATUS_INVALID_PARAMETER;
|
if (*lpwstr == '+') {
|
||||||
|
lpwstr++;
|
||||||
|
CharsRemaining--;
|
||||||
|
} else if (*lpwstr == '-') {
|
||||||
|
bMinus = 1;
|
||||||
|
lpwstr++;
|
||||||
|
CharsRemaining--;
|
||||||
|
} /* if */
|
||||||
|
} /* if */
|
||||||
|
|
||||||
for (i = 0; i < String->Length / sizeof(WCHAR); i++)
|
if (base == 0) {
|
||||||
{
|
base = 10;
|
||||||
if (*Str == L'b')
|
if (CharsRemaining >= 2 && lpwstr[0] == '0') {
|
||||||
{
|
if (lpwstr[1] == 'b') {
|
||||||
Base = 2;
|
lpwstr += 2;
|
||||||
lenmin++;
|
CharsRemaining -= 2;
|
||||||
}
|
base = 2;
|
||||||
else if (*Str == L'o')
|
} else if (lpwstr[1] == 'o') {
|
||||||
{
|
lpwstr += 2;
|
||||||
Base = 8;
|
CharsRemaining -= 2;
|
||||||
lenmin++;
|
base = 8;
|
||||||
}
|
} else if (lpwstr[1] == 'x') {
|
||||||
else if (*Str == L'd')
|
lpwstr += 2;
|
||||||
{
|
CharsRemaining -= 2;
|
||||||
Base = 10;
|
base = 16;
|
||||||
lenmin++;
|
} /* if */
|
||||||
}
|
} /* if */
|
||||||
else if (*Str == L'x')
|
} else if (base != 2 && base != 8 && base != 10 && base != 16) {
|
||||||
{
|
return STATUS_INVALID_PARAMETER;
|
||||||
Base = 16;
|
} /* if */
|
||||||
lenmin++;
|
|
||||||
}
|
|
||||||
else if (*Str == L'+')
|
|
||||||
{
|
|
||||||
lenmin++;
|
|
||||||
}
|
|
||||||
else if (*Str == L'-')
|
|
||||||
{
|
|
||||||
addneg = TRUE;
|
|
||||||
lenmin++;
|
|
||||||
}
|
|
||||||
else if ((*Str > L'1') && (Base == 2))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (((*Str > L'7') || (*Str < L'0')) && (Base == 8))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (((*Str > L'9') || (*Str < L'0')) && (Base == 10))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if ( ((*Str > L'9') || (*Str < L'0')) &&
|
|
||||||
((towupper (*Str) > L'F') || (towupper (*Str) < L'A')) &&
|
|
||||||
(Base == 16))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Str++;
|
|
||||||
}
|
|
||||||
|
|
||||||
Str = String->Buffer + lenmin;
|
if (value == NULL) {
|
||||||
|
return STATUS_ACCESS_VIOLATION;
|
||||||
|
} /* if */
|
||||||
|
|
||||||
if (Base == 0)
|
while (CharsRemaining >= 1) {
|
||||||
Base = 10;
|
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 */
|
||||||
|
|
||||||
while (iswxdigit (*Str) &&
|
RunningTotal = RunningTotal * base + digit;
|
||||||
(Val =
|
lpwstr++;
|
||||||
iswdigit (*Str) ?
|
CharsRemaining--;
|
||||||
*Str - L'0' :
|
} /* while */
|
||||||
(towupper (*Str) - L'A' + 10)) < Base)
|
|
||||||
{
|
|
||||||
*Value = *Value * Base + Val;
|
|
||||||
Str++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addneg == TRUE)
|
*value = bMinus ? -RunningTotal : RunningTotal;
|
||||||
*Value *= -1;
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue