diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/rtl/cnvint.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/ntos/rtl/cnvint.c')
-rw-r--r-- | private/ntos/rtl/cnvint.c | 455 |
1 files changed, 455 insertions, 0 deletions
diff --git a/private/ntos/rtl/cnvint.c b/private/ntos/rtl/cnvint.c new file mode 100644 index 000000000..41ade42bb --- /dev/null +++ b/private/ntos/rtl/cnvint.c @@ -0,0 +1,455 @@ +/*++ + +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,RtlIntegerToUnicodeString) +#pragma alloc_text(PAGE,RtlLargeIntegerToChar) +#endif + +CHAR RtlpIntegerChars[] = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', '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; + + 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 = &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 { + RtlMoveMemory( 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; + + 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 PUNICODE_STRING String, + IN ULONG Base OPTIONAL, + OUT PULONG Value + ) +{ + PCWSTR s; + WCHAR c, Sign; + ULONG nChars, Result, Digit, Shift; + + 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 +RtlIntegerToUnicodeString ( + IN ULONG Value, + IN ULONG Base OPTIONAL, + IN OUT PUNICODE_STRING String + ) +{ + NTSTATUS Status; + UCHAR ResultBuffer[ 16 ]; + ANSI_STRING AnsiString; + + 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; + + 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 = &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 { + RtlMoveMemory( String, s, Length ); + + if ((LONG)Length < OutputLength) { + String[ Length ] = '\0'; + } + } + except( EXCEPTION_EXECUTE_HANDLER ) { + return( GetExceptionCode() ); + } + + return( STATUS_SUCCESS ); + } +} |