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
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
|
|
|