|
|
/*++
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
|