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.

223 lines
6.7 KiB

  1. // from base\ntos\rtl\rtlfindcharinunicodestring
  2. // should be gotten from a static .lib
  3. /*++
  4. Copyright (c) Microsoft Corporation
  5. Module Name:
  6. rtlfindcharinunicodestring.c
  7. Abstract:
  8. This module implements NLS support functions for NT.
  9. Author:
  10. Mark Lucovsky (markl) 16-Apr-1991
  11. Environment:
  12. Kernel or user-mode
  13. Revision History:
  14. 16-Feb-1993 JulieB Added Upcase Rtl Routines.
  15. 08-Mar-1993 JulieB Moved Upcase Macro to ntrtlp.h.
  16. 02-Apr-1993 JulieB Fixed RtlAnsiCharToUnicodeChar to use transl. tbls.
  17. 02-Apr-1993 JulieB Fixed BUFFER_TOO_SMALL check.
  18. 28-May-1993 JulieB Fixed code to properly handle DBCS.
  19. November 30, 2001 JayKrell broken out of nls.c for easier reuse
  20. --*/
  21. #include "spprecmp.h"
  22. WCHAR
  23. RtlDowncaseUnicodeChar(
  24. IN WCHAR SourceCharacter
  25. )
  26. {
  27. return SpToLower(SourceCharacter);
  28. }
  29. NTSTATUS
  30. RtlFindCharInUnicodeString(
  31. ULONG Flags,
  32. PCUNICODE_STRING StringToSearch,
  33. PCUNICODE_STRING CharSet,
  34. USHORT *NonInclusivePrefixLength
  35. )
  36. {
  37. NTSTATUS Status;
  38. USHORT PrefixLengthFound = 0;
  39. USHORT CharsToSearch = 0;
  40. int MovementDirection = 0;
  41. PCWSTR Cursor = NULL;
  42. BOOLEAN Found = FALSE;
  43. USHORT CharSetChars = 0;
  44. PCWSTR CharSetBuffer = NULL;
  45. USHORT i;
  46. if (NonInclusivePrefixLength != 0)
  47. *NonInclusivePrefixLength = 0;
  48. if (((Flags & ~(RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END |
  49. RTL_FIND_CHAR_IN_UNICODE_STRING_COMPLEMENT_CHAR_SET |
  50. RTL_FIND_CHAR_IN_UNICODE_STRING_CASE_INSENSITIVE)) != 0) ||
  51. (NonInclusivePrefixLength == NULL)) {
  52. Status = STATUS_INVALID_PARAMETER;
  53. goto Exit;
  54. }
  55. Status = RtlValidateUnicodeString(0, StringToSearch);
  56. if (!NT_SUCCESS(Status))
  57. goto Exit;
  58. Status = RtlValidateUnicodeString(0, CharSet);
  59. if (!NT_SUCCESS(Status))
  60. goto Exit;
  61. CharsToSearch = StringToSearch->Length / sizeof(WCHAR);
  62. CharSetChars = CharSet->Length / sizeof(WCHAR);
  63. CharSetBuffer = CharSet->Buffer;
  64. if (Flags & RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END) {
  65. MovementDirection = -1;
  66. Cursor = StringToSearch->Buffer + CharsToSearch - 1;
  67. } else {
  68. MovementDirection = 1;
  69. Cursor = StringToSearch->Buffer;
  70. }
  71. if (Flags & RTL_FIND_CHAR_IN_UNICODE_STRING_CASE_INSENSITIVE) {
  72. // Unicode standard says to always do case insensitive comparisons in lower case since the case mappings are
  73. // asymmetric.
  74. WCHAR CharSetStackBuffer[32]; // optimized pre-downcased for case insensitive
  75. // Optimization for the case of a relatively small char set to match
  76. if (CharSetChars <= RTL_NUMBER_OF(CharSetStackBuffer)) {
  77. for (i=0; i<CharSetChars; i++)
  78. CharSetStackBuffer[i] = RtlDowncaseUnicodeChar(CharSetBuffer[i]);
  79. while (CharsToSearch != 0) {
  80. const WCHAR wch = RtlDowncaseUnicodeChar(*Cursor);
  81. if (Flags & RTL_FIND_CHAR_IN_UNICODE_STRING_COMPLEMENT_CHAR_SET) {
  82. for (i=0; i<CharSetChars; i++) {
  83. if (wch == CharSetStackBuffer[i])
  84. break;
  85. }
  86. if (i == CharSetChars)
  87. break;
  88. } else {
  89. for (i=0; i<CharSetChars; i++) {
  90. if (wch == CharSetStackBuffer[i])
  91. break;
  92. }
  93. if (i != CharSetChars)
  94. break;
  95. }
  96. CharsToSearch--;
  97. Cursor += MovementDirection;
  98. }
  99. } else {
  100. while (CharsToSearch != 0) {
  101. const WCHAR wch = RtlDowncaseUnicodeChar(*Cursor);
  102. if (Flags & RTL_FIND_CHAR_IN_UNICODE_STRING_COMPLEMENT_CHAR_SET) {
  103. for (i=0; i<CharSetChars; i++) {
  104. if (wch == RtlDowncaseUnicodeChar(CharSetBuffer[i])) {
  105. break;
  106. }
  107. }
  108. if (i == CharSetChars)
  109. break;
  110. } else {
  111. for (i=0; i<CharSetChars; i++) {
  112. if (wch == RtlDowncaseUnicodeChar(CharSetBuffer[i])) {
  113. break;
  114. }
  115. }
  116. if (i != CharSetChars)
  117. break;
  118. }
  119. CharsToSearch--;
  120. Cursor += MovementDirection;
  121. }
  122. }
  123. } else {
  124. if (CharSetChars == 1) {
  125. // Significant optimization for looking for one character.
  126. const WCHAR wchSearchChar = CharSetBuffer[0];
  127. if (Flags & RTL_FIND_CHAR_IN_UNICODE_STRING_COMPLEMENT_CHAR_SET) {
  128. while (CharsToSearch != 0) {
  129. if (*Cursor != wchSearchChar)
  130. break;
  131. CharsToSearch--;
  132. Cursor += MovementDirection;
  133. }
  134. } else {
  135. while (CharsToSearch != 0) {
  136. if (*Cursor == wchSearchChar)
  137. break;
  138. CharsToSearch--;
  139. Cursor += MovementDirection;
  140. }
  141. }
  142. } else {
  143. while (CharsToSearch != 0) {
  144. const WCHAR wch = *Cursor;
  145. if (Flags & RTL_FIND_CHAR_IN_UNICODE_STRING_COMPLEMENT_CHAR_SET) {
  146. for (i=0; i<CharSetChars; i++) {
  147. if (wch == CharSetBuffer[i])
  148. break;
  149. }
  150. if (i == CharSetChars)
  151. break;
  152. } else {
  153. for (i=0; i<CharSetChars; i++) {
  154. if (wch == CharSetBuffer[i])
  155. break;
  156. }
  157. if (i != CharSetChars)
  158. break;
  159. }
  160. CharsToSearch--;
  161. Cursor += MovementDirection;
  162. }
  163. }
  164. }
  165. if (CharsToSearch == 0) {
  166. Status = STATUS_NOT_FOUND;
  167. goto Exit;
  168. }
  169. CharsToSearch--;
  170. if (Flags & RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END)
  171. PrefixLengthFound = (USHORT) (CharsToSearch * sizeof(WCHAR));
  172. else
  173. PrefixLengthFound = (USHORT) (StringToSearch->Length - (CharsToSearch * sizeof(WCHAR)));
  174. *NonInclusivePrefixLength = PrefixLengthFound;
  175. Status = STATUS_SUCCESS;
  176. Exit:
  177. return Status;
  178. }