From 1c94f9ff02aa0a4c69b0afd25c63a682857c325f Mon Sep 17 00:00:00 2001 From: Rafal Kupiec Date: Wed, 6 Dec 2023 22:47:54 +0100 Subject: [PATCH] Improvements in string and wide string support * Implement RtlCompareString(), RtlCompareStringInsensitive(), RtlCompareWideString() and RtlCompareWideStringInsensitive() * Rename some routines t omatch naming conventions * Switch to CHAR in string operations --- sdk/xtdk/rtlfuncs.h | 54 ++++++++---- xtldr/efiutil.c | 12 +-- xtldr/modules/xtos/xtos.c | 2 +- xtldr/xtldr.c | 2 +- xtoskrnl/rtl/string.c | 131 +++++++++++++++++++++++++++-- xtoskrnl/rtl/widestr.c | 171 ++++++++++++++++++++++++++------------ xtoskrnl/xtoskrnl.spec | 9 +- 7 files changed, 294 insertions(+), 87 deletions(-) diff --git a/sdk/xtdk/rtlfuncs.h b/sdk/xtdk/rtlfuncs.h index b131ee2..4f275ad 100644 --- a/sdk/xtdk/rtlfuncs.h +++ b/sdk/xtdk/rtlfuncs.h @@ -54,6 +54,36 @@ RtlCompareMemory(IN PCVOID LeftBuffer, IN PCVOID RightBuffer, IN SIZE_T Length); +XTCDECL +SIZE_T +RtlCompareString(IN CONST PCHAR String1, + IN CONST PCHAR String2, + IN SIZE_T Length); + +XTCDECL +SIZE_T +RtlCompareStringInsensitive(IN CONST PCHAR String1, + IN CONST PCHAR String2, + IN SIZE_T Length); + +XTCDECL +SIZE_T +RtlCompareWideString(IN CONST PWCHAR String1, + IN CONST PWCHAR String2, + IN SIZE_T Length); + +XTCDECL +SIZE_T +RtlCompareWideStringInsensitive(IN CONST PWCHAR String1, + IN CONST PWCHAR String2, + IN SIZE_T Length); + +XTCDECL +PWCHAR +RtlConcatenateWideString(OUT PWCHAR Destination, + IN PWCHAR Source, + IN SIZE_T Count); + XTAPI VOID RtlCopyMemory(OUT PVOID Destination, @@ -86,38 +116,26 @@ RtlSetMemory(OUT PVOID Destination, XTCDECL SIZE_T -RtlStringLength(IN CONST PUCHAR String, +RtlStringLength(IN CONST PCHAR String, IN SIZE_T MaxLength); XTCDECL -INT +SIZE_T RtlStringToWideString(OUT PWCHAR Destination, - IN CONST PUCHAR *Source, + IN CONST PCHAR *Source, IN SIZE_T Length); -XTCDECL -INT -RtlWideStringCompare(IN CONST PWCHAR String1, - IN CONST PWCHAR String2, - IN CONST SIZE_T Length); - XTCDECL PWCHAR -RtlWideStringConcatenate(OUT PWCHAR Destination, - IN PWCHAR Source, - IN SIZE_T Count); +RtlTokenizeWideString(IN PWCHAR String, + IN CONST PWCHAR Delimiter, + IN OUT PWCHAR *SavePtr); XTCDECL SIZE_T RtlWideStringLength(IN CONST PWCHAR String, IN SIZE_T MaxLength); -XTCDECL -PWCHAR -RtlWideStringTokenize(IN PWCHAR String, - IN CONST PWCHAR Delimiter, - IN OUT PWCHAR *SavePtr); - XTAPI VOID RtlWriteRegisterByte(IN VOLATILE PVOID Register, diff --git a/xtldr/efiutil.c b/xtldr/efiutil.c index 7c2201c..39d01a3 100644 --- a/xtldr/efiutil.c +++ b/xtldr/efiutil.c @@ -146,19 +146,19 @@ BlComPortInitialize() CommandLine = (PWCHAR)LoadedImage->LoadOptions; /* Find command in command line */ - Argument = RtlWideStringTokenize(CommandLine, L" ", &LastArg); + Argument = RtlTokenizeWideString(CommandLine, L" ", &LastArg); /* Iterate over all arguments passed to boot loader */ while(Argument != NULL) { /* Check if this is DEBUG parameter */ - if(RtlWideStringCompare(Argument, L"DEBUG=", 6) == 0) + if(RtlCompareWideString(Argument, L"DEBUG=", 6) == 0) { /* Skip to the argument value */ Argument += 6; /* Make sure COM port is being used */ - if(RtlWideStringCompare(Argument, L"COM", 3)) + if(RtlCompareWideString(Argument, L"COM", 3)) { /* Invalid debug port specified */ BlEfiPrint(L"ERROR: Invalid debug port specified, falling back to defaults\n"); @@ -176,7 +176,7 @@ BlComPortInitialize() } /* Check if custom COM port address supplied */ - if(PortNumber == 0 && RtlWideStringCompare(Argument, L":0x", 3) == 0) + if(PortNumber == 0 && RtlCompareWideString(Argument, L":0x", 3) == 0) { /* COM port address provided */ Argument += 3; @@ -221,7 +221,7 @@ BlComPortInitialize() } /* Take next argument */ - Argument = RtlWideStringTokenize(NULL, L" ", &LastArg); + Argument = RtlTokenizeWideString(NULL, L" ", &LastArg); } } } @@ -349,7 +349,7 @@ BlEfiPrint(IN PUINT16 Format, BlStringPrint(BlConsolePutChar, Format, Arguments); /* Print to serial console only if not running under OVMF */ - if(RtlWideStringCompare(EfiSystemTable->FirmwareVendor, L"EDK II", 6) != 0) + if(RtlCompareWideString(EfiSystemTable->FirmwareVendor, L"EDK II", 6) != 0) { /* Check if debugging enabled and if EFI serial port is fully initialized */ if(DEBUG && (EfiSerialPort.Flags & COMPORT_FLAG_INIT)) diff --git a/xtldr/modules/xtos/xtos.c b/xtldr/modules/xtos/xtos.c index 07b963f..c663e6a 100644 --- a/xtldr/modules/xtos/xtos.c +++ b/xtldr/modules/xtos/xtos.c @@ -132,7 +132,7 @@ XtBootSystem(IN PXT_BOOT_PROTOCOL_PARAMETERS Parameters) } /* System path has to point to the boot directory */ - RtlWideStringConcatenate(Parameters->SystemPath, L"\\Boot", 0); + RtlConcatenateWideString(Parameters->SystemPath, L"\\Boot", 0); /* Open XTOS system boot directory */ Status = FsHandle->Open(FsHandle, &BootDir, Parameters->SystemPath, EFI_FILE_MODE_READ, 0); diff --git a/xtldr/xtldr.c b/xtldr/xtldr.c index 09bf22f..dd9abee 100644 --- a/xtldr/xtldr.c +++ b/xtldr/xtldr.c @@ -116,7 +116,7 @@ BlLoadEfiModules() /* Set correct path to the module file */ RtlCopyMemory(ModulePath, ModulesDirPath, sizeof(ModulePath) / sizeof(WCHAR)); - RtlWideStringConcatenate(ModulePath, ModuleName, 0); + RtlConcatenateWideString(ModulePath, ModuleName, 0); /* Find valid device path */ Status = BlFindVolumeDevicePath(DevicePath, ModulePath, &VolumeDevicePath); diff --git a/xtoskrnl/rtl/string.c b/xtoskrnl/rtl/string.c index aef02b2..3716d6b 100644 --- a/xtoskrnl/rtl/string.c +++ b/xtoskrnl/rtl/string.c @@ -9,6 +9,125 @@ #include +/** + * Compares at most specified number of characters of two C strings. + * + * @param String1 + * String to be compared. + * + * @param String2 + * String to be compared. + * + * @param Length + * Maximum number of characters to compare. If no limit set, it compares whole strings. + * + * @return Integral value indicating the relationship between the strings. + * + * @since XT 1.0 + */ +XTCDECL +SIZE_T +RtlCompareString(IN CONST PCHAR String1, + IN CONST PCHAR String2, + IN SIZE_T Length) +{ + SIZE_T Index; + + /* Iterate through the strings */ + for(Index = 0; ; Index++) { + /* Check if length limit reached */ + if(Index != 0 && Index == Length) + { + /* Skip checking next characters */ + break; + } + + /* Check if string characters are equal */ + if(String1[Index] != String2[Index]) + { + /* Different characters found */ + return String1[Index] < String2[Index] ? -1 : 1; + } + + /* Check if end of string reached */ + if(!String1[Index] || !String2[Index]) + { + /* Equal strings until the end of one of them */ + return 0; + } + } + + /* Strings are equal */ + return 0; +} + +/** + * Compares at most specified number of characters of two C strings, while ignoring differences in case. + * + * @param String1 + * String to be compared. + * + * @param String2 + * String to be compared. + * + * @param Length + * Maximum number of characters to compare. If no limit set, it compares whole strings. + * + * @return Integral value indicating the relationship between the strings. + * + * @since XT 1.0 + */ +XTCDECL +SIZE_T +RtlCompareStringInsensitive(IN CONST PCHAR String1, + IN CONST PCHAR String2, + IN SIZE_T Length) +{ + CHAR Character1; + CHAR Character2; + ULONG Index = 0; + + /* Iterate through the strings */ + while(String1[Index] != '\0' && String2[Index] != '\0') + { + /* Check if length limit reached */ + if(Index != 0 && Index == Length) + { + /* Skip checking next characters */ + break; + } + + /* Get the characters */ + Character1 = String1[Index]; + Character2 = String2[Index]; + + /* Lowercase string1 character if needed */ + if(String1[Index] >= 'A' && String1[Index] <= 'Z') + { + Character1 = String1[Index] - 'A' + 'a'; + } + + /* Lowercase string2 character if needed */ + if(String2[Index] >= 'A' && String2[Index] <= 'Z') + { + Character2 = String2[Index] - 'A' + 'a'; + } + + /* Compare the characters */ + if(Character1 != Character2) + { + /* Strings are not equal */ + return Character1 > Character2 ? 1 : -1; + } + + /* Get next character */ + Index++; + } + + /* Strings are equal */ + return 0; +} + /** * Calculates the length of a given string. * @@ -24,7 +143,7 @@ */ XTCDECL SIZE_T -RtlStringLength(IN CONST PUCHAR String, +RtlStringLength(IN CONST PCHAR String, IN SIZE_T MaxLength) { SIZE_T Length; @@ -47,7 +166,7 @@ RtlStringLength(IN CONST PUCHAR String, } } - /* Return wide string length */ + /* Return string length */ return Length; } @@ -68,12 +187,12 @@ RtlStringLength(IN CONST PUCHAR String, * @since XT 1.0 */ XTCDECL -INT +SIZE_T RtlStringToWideString(OUT PWCHAR Destination, - IN CONST PUCHAR *Source, + IN CONST PCHAR *Source, IN SIZE_T Length) { - PUCHAR LocalSource = *Source; + PCHAR LocalSource = *Source; SIZE_T Count = Length; if(Destination == NULL) @@ -83,7 +202,7 @@ RtlStringToWideString(OUT PWCHAR Destination, while(Count) { - if((*Destination = (UCHAR)*LocalSource) == 0) + if((*Destination = *LocalSource) == 0) { LocalSource = NULL; break; diff --git a/xtoskrnl/rtl/widestr.c b/xtoskrnl/rtl/widestr.c index 57e1fe2..6bb77c4 100644 --- a/xtoskrnl/rtl/widestr.c +++ b/xtoskrnl/rtl/widestr.c @@ -19,17 +19,17 @@ * Wide string to be compared. * * @param Length - * Maximum number of characters to compare. If no limit set, it compares whole strings. + * Maximum number of characters to compare. If no limit set, it compares whole wide strings. * * @return Integral value indicating the relationship between the wide strings. * * @since XT 1.0 */ XTCDECL -INT -RtlWideStringCompare(IN CONST PWCHAR String1, +SIZE_T +RtlCompareWideString(IN CONST PWCHAR String1, IN CONST PWCHAR String2, - IN CONST SIZE_T Length) + IN SIZE_T Length) { SIZE_T Index; @@ -42,22 +42,89 @@ RtlWideStringCompare(IN CONST PWCHAR String1, break; } - /* Check if string characters are equal */ + /* Check if wide string characters are equal */ if(String1[Index] != String2[Index]) { /* Different characters found */ return String1[Index] < String2[Index] ? -1 : 1; } - /* Check if end of string reached */ + /* Check if end of wide string reached */ if(!String1[Index] || !String2[Index]) { - /* Equal strings until the end of one of them */ + /* Equal wide strings until the end of one of them */ return 0; } } - /* Strings are equal */ + /* Wide strings are equal */ + return 0; +} + +/** + * Compares at most specified number of characters of two C wide strings, while ignoring differences in case. + * + * @param String1 + * Wide string to be compared. + * + * @param String2 + * Wide string to be compared. + * + * @param Length + * Maximum number of characters to compare. If no limit set, it compares whole wide strings. + * + * @return Integral value indicating the relationship between the wide strings. + * + * @since XT 1.0 + */ +XTCDECL +SIZE_T +RtlCompareWideStringInsensitive(IN CONST PWCHAR String1, + IN CONST PWCHAR String2, + IN SIZE_T Length) +{ + WCHAR Character1; + WCHAR Character2; + ULONG Index = 0; + + /* Iterate through the wide strings */ + while(String1[Index] != '\0' && String2[Index] != '\0') + { + /* Check if length limit reached */ + if(Index != 0 && Index == Length) + { + /* Skip checking next characters */ + break; + } + + /* Get the characters */ + Character1 = String1[Index]; + Character2 = String2[Index]; + + /* Lowercase wide string1 character if needed */ + if(String1[Index] >= 'A' && String1[Index] <= 'Z') + { + Character1 = String1[Index] - 'A' + 'a'; + } + + /* Lowercase wide string2 character if needed */ + if(String2[Index] >= 'A' && String2[Index] <= 'Z') + { + Character2 = String2[Index] - 'A' + 'a'; + } + + /* Compare the characters */ + if(Character1 != Character2) + { + /* Wide strings are not equal */ + return Character1 > Character2 ? 1 : -1; + } + + /* Get next character */ + Index++; + } + + /* Wide strings are equal */ return 0; } @@ -79,7 +146,7 @@ RtlWideStringCompare(IN CONST PWCHAR String1, */ XTCDECL PWCHAR -RtlWideStringConcatenate(OUT PWCHAR Destination, +RtlConcatenateWideString(OUT PWCHAR Destination, IN PWCHAR Source, IN SIZE_T Count) { @@ -120,48 +187,6 @@ RtlWideStringConcatenate(OUT PWCHAR Destination, return DestString; } -/** - * Calculates the length of a given wide string. - * - * @param String - * Pointer to the null-terminated wide string to be examined. - * - * @param MaxLength - * Maximum number of wide characters to examine. If no limit set, it examines whole string. - * - * @return The length of the null-terminated wide string. - * - * @since: XT 1.0 - */ -XTCDECL -SIZE_T -RtlWideStringLength(IN CONST PWCHAR String, - IN SIZE_T MaxLength) -{ - SIZE_T Length; - - /* Check if NULL pointer passed */ - if(String == NULL) - { - return 0; - } - - /* Iterate through the wide string */ - for(Length = 0; ; Length++) - { - - /* Check if NULL found or max length limit reached */ - if((Length != 0 && Length == MaxLength) || !String[Length]) - { - /* Finish examination */ - break; - } - } - - /* Return wide string length */ - return Length; -} - /** * Finds the next token in a null-terminated wide string. * @@ -180,7 +205,7 @@ RtlWideStringLength(IN CONST PWCHAR String, */ XTCDECL PWCHAR -RtlWideStringTokenize(IN PWCHAR String, +RtlTokenizeWideString(IN PWCHAR String, IN CONST PWCHAR Delimiter, IN OUT PWCHAR *SavePtr) { @@ -231,3 +256,45 @@ RtlWideStringTokenize(IN PWCHAR String, while(SpanChar != L'\0'); } } + +/** + * Calculates the length of a given wide string. + * + * @param String + * Pointer to the null-terminated wide string to be examined. + * + * @param MaxLength + * Maximum number of wide characters to examine. If no limit set, it examines whole string. + * + * @return The length of the null-terminated wide string. + * + * @since: XT 1.0 + */ +XTCDECL +SIZE_T +RtlWideStringLength(IN CONST PWCHAR String, + IN SIZE_T MaxLength) +{ + SIZE_T Length; + + /* Check if NULL pointer passed */ + if(String == NULL) + { + return 0; + } + + /* Iterate through the wide string */ + for(Length = 0; ; Length++) + { + + /* Check if NULL found or max length limit reached */ + if((Length != 0 && Length == MaxLength) || !String[Length]) + { + /* Finish examination */ + break; + } + } + + /* Return wide string length */ + return Length; +} diff --git a/xtoskrnl/xtoskrnl.spec b/xtoskrnl/xtoskrnl.spec index 9a79a41..0864d76 100644 --- a/xtoskrnl/xtoskrnl.spec +++ b/xtoskrnl/xtoskrnl.spec @@ -32,12 +32,15 @@ @ stdcall RtlReadRegisterByte(ptr) @ stdcall RtlReadRegisterLong(ptr) @ stdcall RtlReadRegisterShort(ptr) +@ cdecl RtlCompareString(str str long) +@ cdecl RtlCompareStringInsensitive(str str long) @ cdecl RtlStringLength(str long) @ cdecl RtlStringToWideString(wstr str long) -@ cdecl RtlWideStringCompare(wstr wstr long) -@ cdecl RtlWideStringConcatenate(wstr wstr long) +@ cdecl RtlCompareWideString(wstr wstr long) +@ cdecl RtlCompareWideStringInsensitive(wstr wstr long) +@ cdecl RtlConcatenateWideString(wstr wstr long) +@ cdecl RtlTokenizeWideString(wstr wstr wstr) @ cdecl RtlWideStringLength(wstr long) -@ cdecl RtlWideStringTokenize(wstr wstr wstr) @ stdcall RtlWriteRegisterByte(ptr long) @ stdcall RtlWriteRegisterLong(ptr long) @ stdcall RtlWriteRegisterShort(ptr long)