|
|
/*++
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 = 0xF >> (4 - Shift); }
s = &Result[ 32 ]; *s = '\0'; 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[ 32 ] - s); if (OutputLength < 0) { OutputLength = -OutputLength; while ((LONG)Length < OutputLength) { *--s = '0'; Length++; } }
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( (ULONG_PTR)(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( (ULONG_PTR)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 = 0xF >> (4 - Shift); }
s = &Result[ 32 ]; *s = L'\0'; 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[ 32 ] - s); if (OutputLength < 0) { OutputLength = -OutputLength; while ((LONG)Length < OutputLength) { *--s = L'0'; Length++; } }
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 ); }
NTSTATUS RtlLargeIntegerToChar ( IN PLARGE_INTEGER Value, IN ULONG Base OPTIONAL, IN LONG OutputLength, OUT PSZ String )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ CHAR Result[ 100 ], *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 = 0xF >> (4 - Shift); }
s = &Result[ 99 ]; *s = '\0'; if (Shift != 0) { ULONG LowValue,HighValue,HighShift,HighMask;
LowValue = Value->LowPart; HighValue = Value->HighPart; HighShift = Shift - (sizeof(ULONG) % Shift); HighMask = 0xF >> (4 - HighShift); do { Digit = LowValue & Mask; LowValue = (LowValue >> Shift) | ((HighValue & HighMask) << (sizeof(ULONG) - HighShift)); HighValue = HighValue >> HighShift; *--s = RtlpIntegerChars[ Digit ]; } while ((LowValue | HighValue) != 0); } else { LARGE_INTEGER TempValue=*Value; do { TempValue = RtlExtendedLargeIntegerDivide(TempValue,Base,&Digit); *--s = RtlpIntegerChars[ Digit ]; } while (TempValue.HighPart != 0 || TempValue.LowPart != 0); }
Length = (ULONG)(&Result[ 99 ] - s); if (OutputLength < 0) { OutputLength = -OutputLength; while ((LONG)Length < OutputLength) { *--s = '0'; Length++; } }
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[ 100 ], *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 = 0xF >> (4 - Shift); }
s = &Result[ 99 ]; *s = L'\0'; if (Shift != 0) { ULONG LowValue,HighValue,HighShift,HighMask;
LowValue = Value->LowPart; HighValue = Value->HighPart; HighShift = Shift - (sizeof(ULONG) % Shift); HighMask = 0xF >> (4 - HighShift); do { Digit = LowValue & Mask; LowValue = (LowValue >> Shift) | ((HighValue & HighMask) << (sizeof(ULONG) - HighShift)); HighValue = HighValue >> HighShift; *--s = RtlpIntegerWChars[ Digit ]; } while ((LowValue | HighValue) != 0); } else { LARGE_INTEGER TempValue=*Value; do { TempValue = RtlExtendedLargeIntegerDivide(TempValue,Base,&Digit); *--s = RtlpIntegerWChars[ Digit ]; } while (TempValue.HighPart != 0 || TempValue.LowPart != 0); }
Length = (ULONG)(&Result[ 99 ] - s); if (OutputLength < 0) { OutputLength = -OutputLength; while ((LONG)Length < OutputLength) { *--s = L'0'; Length++; } }
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; }
|