Leaked source code of windows server 2003
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.
|
|
/*++
Copyright (c) Microsoft Corporation
Module Name:
rtlfindcharinunicodestring.c
Abstract:
This module implements NLS support functions for NT.
Author:
Mark Lucovsky (markl) 16-Apr-1991
Environment:
Kernel or user-mode
Revision History:
16-Feb-1993 JulieB Added Upcase Rtl Routines. 08-Mar-1993 JulieB Moved Upcase Macro to ntrtlp.h. 02-Apr-1993 JulieB Fixed RtlAnsiCharToUnicodeChar to use transl. tbls. 02-Apr-1993 JulieB Fixed BUFFER_TOO_SMALL check. 28-May-1993 JulieB Fixed code to properly handle DBCS. November 30, 2001 JayKrell broken out of nls.c for easier reuse
--*/
NTSTATUS RtlFindCharInUnicodeString( ULONG Flags, PCUNICODE_STRING StringToSearch, PCUNICODE_STRING CharSet, USHORT *NonInclusivePrefixLength ) { NTSTATUS Status; USHORT PrefixLengthFound = 0; USHORT CharsToSearch = 0; int MovementDirection = 0; PCWSTR Cursor = NULL; BOOLEAN Found = FALSE; USHORT CharSetChars = 0; PCWSTR CharSetBuffer = NULL; USHORT i;
if (NonInclusivePrefixLength != 0) *NonInclusivePrefixLength = 0;
if (((Flags & ~(RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END | RTL_FIND_CHAR_IN_UNICODE_STRING_COMPLEMENT_CHAR_SET | RTL_FIND_CHAR_IN_UNICODE_STRING_CASE_INSENSITIVE)) != 0) || (NonInclusivePrefixLength == NULL)) { Status = STATUS_INVALID_PARAMETER; goto Exit; }
Status = RtlValidateUnicodeString(0, StringToSearch); if (!NT_SUCCESS(Status)) goto Exit;
Status = RtlValidateUnicodeString(0, CharSet); if (!NT_SUCCESS(Status)) goto Exit;
CharsToSearch = StringToSearch->Length / sizeof(WCHAR); CharSetChars = CharSet->Length / sizeof(WCHAR); CharSetBuffer = CharSet->Buffer;
if (Flags & RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END) { MovementDirection = -1; Cursor = StringToSearch->Buffer + CharsToSearch - 1; } else { MovementDirection = 1; Cursor = StringToSearch->Buffer; }
if (Flags & RTL_FIND_CHAR_IN_UNICODE_STRING_CASE_INSENSITIVE) { // Unicode standard says to always do case insensitive comparisons in lower case since the case mappings are
// asymmetric.
WCHAR CharSetStackBuffer[32]; // optimized pre-downcased for case insensitive
// Optimization for the case of a relatively small char set to match
if (CharSetChars <= RTL_NUMBER_OF(CharSetStackBuffer)) {
for (i=0; i<CharSetChars; i++) CharSetStackBuffer[i] = RtlDowncaseUnicodeChar(CharSetBuffer[i]);
while (CharsToSearch != 0) { const WCHAR wch = RtlDowncaseUnicodeChar(*Cursor);
if (Flags & RTL_FIND_CHAR_IN_UNICODE_STRING_COMPLEMENT_CHAR_SET) { for (i=0; i<CharSetChars; i++) { if (wch == CharSetStackBuffer[i]) break; }
if (i == CharSetChars) break; } else { for (i=0; i<CharSetChars; i++) { if (wch == CharSetStackBuffer[i]) break; }
if (i != CharSetChars) break; }
CharsToSearch--; Cursor += MovementDirection; } } else { while (CharsToSearch != 0) { const WCHAR wch = RtlDowncaseUnicodeChar(*Cursor);
if (Flags & RTL_FIND_CHAR_IN_UNICODE_STRING_COMPLEMENT_CHAR_SET) { for (i=0; i<CharSetChars; i++) { if (wch == RtlDowncaseUnicodeChar(CharSetBuffer[i])) { break; } }
if (i == CharSetChars) break; } else { for (i=0; i<CharSetChars; i++) { if (wch == RtlDowncaseUnicodeChar(CharSetBuffer[i])) { break; } }
if (i != CharSetChars) break; }
CharsToSearch--; Cursor += MovementDirection; } } } else { if (CharSetChars == 1) { // Significant optimization for looking for one character.
const WCHAR wchSearchChar = CharSetBuffer[0];
if (Flags & RTL_FIND_CHAR_IN_UNICODE_STRING_COMPLEMENT_CHAR_SET) { while (CharsToSearch != 0) { if (*Cursor != wchSearchChar) break; CharsToSearch--; Cursor += MovementDirection; } } else { while (CharsToSearch != 0) { if (*Cursor == wchSearchChar) break; CharsToSearch--; Cursor += MovementDirection; } } } else { while (CharsToSearch != 0) { const WCHAR wch = *Cursor;
if (Flags & RTL_FIND_CHAR_IN_UNICODE_STRING_COMPLEMENT_CHAR_SET) { for (i=0; i<CharSetChars; i++) { if (wch == CharSetBuffer[i]) break; }
if (i == CharSetChars) break;
} else { for (i=0; i<CharSetChars; i++) { if (wch == CharSetBuffer[i]) break; }
if (i != CharSetChars) break; }
CharsToSearch--; Cursor += MovementDirection; } } }
if (CharsToSearch == 0) { Status = STATUS_NOT_FOUND; goto Exit; }
CharsToSearch--;
if (Flags & RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END) PrefixLengthFound = (USHORT) (CharsToSearch * sizeof(WCHAR)); else PrefixLengthFound = (USHORT) (StringToSearch->Length - (CharsToSearch * sizeof(WCHAR)));
*NonInclusivePrefixLength = PrefixLengthFound;
Status = STATUS_SUCCESS;
Exit: return Status; }
|