Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

657 lines
14 KiB

/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
cnvint.c
Abstract:
Text to integer and integer to text converion routines.
Author:
Steve Wood (stevewo) 23-Aug-1990
Revision History:
--*/
#include <ntrtlp.h>
#if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
#pragma alloc_text(PAGE,RtlIntegerToChar)
#pragma alloc_text(PAGE,RtlCharToInteger)
#pragma alloc_text(PAGE,RtlUnicodeStringToInteger)
#pragma alloc_text(PAGE,RtlIntegerToUnicode)
#pragma alloc_text(PAGE,RtlIntegerToUnicodeString)
#pragma alloc_text(PAGE,RtlLargeIntegerToChar)
#pragma alloc_text(PAGE,RtlLargeIntegerToUnicode)
#pragma alloc_text(PAGE,RtlInt64ToUnicodeString)
#endif
#if defined(ALLOC_DATA_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
#pragma const_seg("PAGECONST")
#endif
const CHAR RtlpIntegerChars[] = {'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
const WCHAR RtlpIntegerWChars[] = { L'0', L'1', L'2', L'3', L'4', L'5',
L'6', L'7', L'8', L'9', L'A', L'B',
L'C', L'D', L'E', L'F' };
NTSTATUS
RtlIntegerToChar (
IN ULONG Value,
IN ULONG Base OPTIONAL,
IN LONG OutputLength,
OUT PSZ String
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
CHAR Result[33], *s;
ULONG Shift, Mask, Digit, Length;
RTL_PAGED_CODE();
Shift = 0;
switch( Base ) {
case 16: Shift = 4; break;
case 8: Shift = 3; break;
case 2: Shift = 1; break;
case 0: Base = 10;
case 10: Shift = 0; break;
default: return( STATUS_INVALID_PARAMETER );
}
if (Shift != 0) {
Mask = (1 << Shift) - 1;
}
s = &Result[33];
do {
if (Shift != 0) {
Digit = Value & Mask;
Value >>= Shift;
} else {
Digit = Value % Base;
Value = Value / Base;
}
*--s = RtlpIntegerChars[Digit];
} while (Value != 0);
Length = (ULONG) (&Result[33] - s);
if (OutputLength < 0) {
OutputLength = -OutputLength;
while ((LONG)Length < OutputLength) {
*String++ = '0';
OutputLength--;
}
}
if ((LONG)Length > OutputLength) {
return (STATUS_BUFFER_OVERFLOW);
} else {
try {
RtlCopyMemory (String, s, Length);
if ((LONG)Length < OutputLength) {
String[Length] = '\0';
}
} except (EXCEPTION_EXECUTE_HANDLER) {
return (GetExceptionCode ());
}
return (STATUS_SUCCESS);
}
}
NTSTATUS
RtlCharToInteger (
IN PCSZ String,
IN ULONG Base OPTIONAL,
OUT PULONG Value
)
{
CHAR c, Sign;
ULONG Result, Digit, Shift;
RTL_PAGED_CODE();
while ((Sign = *String++) <= ' ') {
if (!*String) {
String--;
break;
}
}
c = Sign;
if (c == '-' || c == '+') {
c = *String++;
}
if (!ARGUMENT_PRESENT( Base )) {
Base = 10;
Shift = 0;
if (c == '0') {
c = *String++;
if (c == 'x') {
Base = 16;
Shift = 4;
} else if (c == 'o') {
Base = 8;
Shift = 3;
} else if (c == 'b') {
Base = 2;
Shift = 1;
} else {
String--;
}
c = *String++;
}
} else {
switch( Base ) {
case 16: Shift = 4; break;
case 8: Shift = 3; break;
case 2: Shift = 1; break;
case 10: Shift = 0; break;
default: return( STATUS_INVALID_PARAMETER );
}
}
Result = 0;
while (c) {
if (c >= '0' && c <= '9') {
Digit = c - '0';
} else if (c >= 'A' && c <= 'F') {
Digit = c - 'A' + 10;
} else if (c >= 'a' && c <= 'f') {
Digit = c - 'a' + 10;
} else {
break;
}
if (Digit >= Base) {
break;
}
if (Shift == 0) {
Result = (Base * Result) + Digit;
} else {
Result = (Result << Shift) | Digit;
}
c = *String++;
}
if (Sign == '-') {
Result = (ULONG)(-(LONG)Result);
}
try {
*Value = Result;
} except( EXCEPTION_EXECUTE_HANDLER ) {
return( GetExceptionCode() );
}
return( STATUS_SUCCESS );
}
NTSTATUS
RtlUnicodeStringToInteger (
IN PCUNICODE_STRING String,
IN ULONG Base OPTIONAL,
OUT PULONG Value
)
{
PCWSTR s;
WCHAR c, Sign;
ULONG nChars, Result, Digit, Shift;
RTL_PAGED_CODE();
s = String->Buffer;
nChars = String->Length / sizeof( WCHAR );
while (nChars-- && (Sign = *s++) <= ' ') {
if (!nChars) {
Sign = UNICODE_NULL;
break;
}
}
c = Sign;
if (c == L'-' || c == L'+') {
if (nChars) {
nChars--;
c = *s++;
}
else {
c = UNICODE_NULL;
}
}
if (!ARGUMENT_PRESENT( Base )) {
Base = 10;
Shift = 0;
if (c == L'0') {
if (nChars) {
nChars--;
c = *s++;
if (c == L'x') {
Base = 16;
Shift = 4;
}
else
if (c == L'o') {
Base = 8;
Shift = 3;
}
else
if (c == L'b') {
Base = 2;
Shift = 1;
}
else {
nChars++;
s--;
}
}
if (nChars) {
nChars--;
c = *s++;
}
else {
c = UNICODE_NULL;
}
}
}
else {
switch( Base ) {
case 16: Shift = 4; break;
case 8: Shift = 3; break;
case 2: Shift = 1; break;
case 10: Shift = 0; break;
default: return( STATUS_INVALID_PARAMETER );
}
}
Result = 0;
while (c != UNICODE_NULL) {
if (c >= L'0' && c <= L'9') {
Digit = c - L'0';
}
else
if (c >= L'A' && c <= L'F') {
Digit = c - L'A' + 10;
}
else
if (c >= L'a' && c <= L'f') {
Digit = c - L'a' + 10;
}
else {
break;
}
if (Digit >= Base) {
break;
}
if (Shift == 0) {
Result = (Base * Result) + Digit;
}
else {
Result = (Result << Shift) | Digit;
}
if (!nChars) {
break;
}
nChars--;
c = *s++;
}
if (Sign == L'-') {
Result = (ULONG)(-(LONG)Result);
}
try {
*Value = Result;
}
except( EXCEPTION_EXECUTE_HANDLER ) {
return( GetExceptionCode() );
}
return( STATUS_SUCCESS );
}
NTSTATUS
RtlIntegerToUnicode (
IN ULONG Value,
IN ULONG Base OPTIONAL,
IN LONG OutputLength,
OUT PWSTR String
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
WCHAR Result[33], *s;
ULONG Shift, Mask, Digit, Length;
RTL_PAGED_CODE();
Shift = 0;
switch( Base ) {
case 16: Shift = 4; break;
case 8: Shift = 3; break;
case 2: Shift = 1; break;
case 0: Base = 10;
case 10: Shift = 0; break;
default: return (STATUS_INVALID_PARAMETER);
}
if (Shift != 0) {
Mask = (1 << Shift) - 1;
}
s = &Result[33];
do {
if (Shift != 0) {
Digit = Value & Mask;
Value >>= Shift;
} else {
Digit = Value % Base;
Value = Value / Base;
}
*--s = RtlpIntegerWChars[ Digit ];
} while (Value != 0);
Length = (ULONG) (&Result[33] - s);
if (OutputLength < 0) {
OutputLength = -OutputLength;
while ((LONG)Length < OutputLength) {
*String++ = L'0';
OutputLength--;
}
}
if ((LONG)Length > OutputLength) {
return (STATUS_BUFFER_OVERFLOW);
} else {
try {
RtlCopyMemory (String, s, Length * sizeof (WCHAR));
if ((LONG)Length < OutputLength) {
String[Length] = L'\0';
}
} except (EXCEPTION_EXECUTE_HANDLER) {
return (GetExceptionCode ());
}
return (STATUS_SUCCESS);
}
}
NTSTATUS
RtlIntegerToUnicodeString (
IN ULONG Value,
IN ULONG Base OPTIONAL,
IN OUT PUNICODE_STRING String
)
{
NTSTATUS Status;
UCHAR ResultBuffer[16];
ANSI_STRING AnsiString;
RTL_PAGED_CODE();
Status = RtlIntegerToChar (Value, Base, sizeof (ResultBuffer), ResultBuffer);
if (NT_SUCCESS (Status)) {
AnsiString.Buffer = ResultBuffer;
AnsiString.MaximumLength = sizeof (ResultBuffer);
AnsiString.Length = (USHORT)strlen (ResultBuffer);
Status = RtlAnsiStringToUnicodeString (String, &AnsiString, FALSE);
}
return( Status );
}
#define MAX_DIGITS 65
NTSTATUS
RtlLargeIntegerToChar (
IN PLARGE_INTEGER Value,
IN ULONG Base OPTIONAL,
IN LONG OutputLength,
OUT PSZ String
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
CHAR Result[MAX_DIGITS], *s;
ULONG Shift, Mask, Digit, Length;
RTL_PAGED_CODE();
Shift = 0;
switch (Base) {
case 16: Shift = 4; break;
case 8: Shift = 3; break;
case 2: Shift = 1; break;
case 0:
case 10: Shift = 0; break;
default: return (STATUS_INVALID_PARAMETER);
}
if (Shift != 0) {
Mask = (1 << Shift) - 1;
}
s = &Result[MAX_DIGITS];
if (Shift != 0) {
ULONGLONG tValue;
tValue = (ULONGLONG) Value->QuadPart;
do {
Digit = (ULONG) (tValue & Mask);
tValue = tValue >> Shift;
*--s = RtlpIntegerChars[Digit];
} while (tValue != 0);
} else {
LARGE_INTEGER TempValue = *Value;
do {
TempValue = RtlExtendedLargeIntegerDivide (TempValue, Base, &Digit);
*--s = RtlpIntegerChars [Digit];
} while (TempValue.QuadPart != 0);
}
Length = (ULONG)(&Result[MAX_DIGITS] - s);
if (OutputLength < 0) {
OutputLength = -OutputLength;
while ((LONG)Length < OutputLength) {
*String++ = '0';
OutputLength--;
}
}
if ((LONG)Length > OutputLength) {
return (STATUS_BUFFER_OVERFLOW);
} else {
try {
RtlCopyMemory (String, s, Length);
if ((LONG)Length < OutputLength) {
String[Length] = '\0';
}
} except (EXCEPTION_EXECUTE_HANDLER) {
return (GetExceptionCode ());
}
return (STATUS_SUCCESS);
}
}
NTSTATUS
RtlLargeIntegerToUnicode (
IN PLARGE_INTEGER Value,
IN ULONG Base OPTIONAL,
IN LONG OutputLength,
OUT PWSTR String
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
WCHAR Result [MAX_DIGITS], *s;
ULONG Shift, Mask, Digit, Length;
RTL_PAGED_CODE();
Shift = 0;
switch (Base) {
case 16: Shift = 4; break;
case 8: Shift = 3; break;
case 2: Shift = 1; break;
case 0:
case 10: Shift = 0; break;
default: return (STATUS_INVALID_PARAMETER);
}
if (Shift != 0) {
Mask = (1 << Shift) - 1;
}
s = &Result [MAX_DIGITS];
if (Shift != 0) {
ULONGLONG tValue;
tValue = (ULONGLONG) Value->QuadPart;
do {
Digit = (ULONG) (tValue & Mask);
tValue = tValue >> Shift;
*--s = RtlpIntegerWChars[Digit];
} while (tValue != 0);
} else {
LARGE_INTEGER TempValue = *Value;
do {
TempValue = RtlExtendedLargeIntegerDivide (TempValue, Base, &Digit);
*--s = RtlpIntegerWChars[Digit];
} while (TempValue.QuadPart != 0);
}
Length = (ULONG)(&Result[MAX_DIGITS] - s);
ASSERT (Length <= MAX_DIGITS);
if (OutputLength < 0) {
OutputLength = -OutputLength;
while ((LONG)Length < OutputLength) {
*String++ = L'0';
OutputLength--;
}
}
if ((LONG)Length > OutputLength) {
return (STATUS_BUFFER_OVERFLOW);
} else {
try {
RtlCopyMemory (String, s, Length * sizeof(WCHAR));
if ((LONG)Length < OutputLength) {
String [Length] = L'\0';
}
} except (EXCEPTION_EXECUTE_HANDLER) {
return (GetExceptionCode ());
}
return (STATUS_SUCCESS);
}
}
NTSTATUS
RtlInt64ToUnicodeString (
IN ULONGLONG Value,
IN ULONG Base OPTIONAL,
IN OUT PUNICODE_STRING String
)
{
NTSTATUS Status;
UCHAR ResultBuffer[32];
ANSI_STRING AnsiString;
LARGE_INTEGER Temp;
RTL_PAGED_CODE();
Temp.QuadPart = Value;
Status = RtlLargeIntegerToChar(&Temp,
Base,
sizeof(ResultBuffer),
ResultBuffer);
if (NT_SUCCESS(Status)) {
AnsiString.Buffer = ResultBuffer;
AnsiString.MaximumLength = sizeof(ResultBuffer);
AnsiString.Length = (USHORT)strlen(ResultBuffer);
Status = RtlAnsiStringToUnicodeString(String, &AnsiString, FALSE);
}
return Status;
}
#if defined(ALLOC_DATA_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
#pragma const_seg()
#endif