Source code of Windows XP (NT5)
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.

798 lines
19 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. nlsboot.c
  5. Abstract:
  6. This module contains NLS routines for use by the OS Loader. Before
  7. the NLS tables are loaded, they convert between ANSI and Unicode by
  8. zero-extending.
  9. Author:
  10. John Vert (jvert) 11-Nov-1992
  11. Revision History:
  12. John Vert (jvert) 11-Nov-1992
  13. created - mostly copied from old RTL routines
  14. --*/
  15. #include "bldr.h"
  16. //
  17. // Hack-o-rama string routines to use before tables are loaded
  18. //
  19. #define upcase(C) (WCHAR )(((C) >= 'a' && (C) <= 'z' ? (C) - ('a' - 'A') : (C)))
  20. NTSTATUS
  21. RtlAnsiStringToUnicodeString(
  22. OUT PUNICODE_STRING DestinationString,
  23. IN PCANSI_STRING SourceString,
  24. IN BOOLEAN AllocateDestinationString
  25. )
  26. {
  27. ULONG UnicodeLength;
  28. ULONG Index;
  29. NTSTATUS st;
  30. UnicodeLength = (SourceString->Length << 1) + sizeof(UNICODE_NULL);
  31. if ( UnicodeLength > MAXUSHORT ) {
  32. return STATUS_INVALID_PARAMETER_2;
  33. }
  34. DestinationString->Length = (USHORT)(UnicodeLength - sizeof(UNICODE_NULL));
  35. if ( AllocateDestinationString ) {
  36. return STATUS_NO_MEMORY;
  37. }
  38. else {
  39. if ( DestinationString->Length >= DestinationString->MaximumLength ) {
  40. return STATUS_BUFFER_OVERFLOW;
  41. }
  42. }
  43. Index = 0;
  44. while(Index < SourceString->Length ) {
  45. DestinationString->Buffer[Index] = (WCHAR)SourceString->Buffer[Index];
  46. Index++;
  47. }
  48. DestinationString->Buffer[Index] = UNICODE_NULL;
  49. return STATUS_SUCCESS;
  50. }
  51. NTSTATUS
  52. RtlUnicodeStringToAnsiString(
  53. OUT PANSI_STRING DestinationString,
  54. IN PCUNICODE_STRING SourceString,
  55. IN BOOLEAN AllocateDestinationString
  56. )
  57. {
  58. ULONG AnsiLength;
  59. ULONG Index;
  60. NTSTATUS st;
  61. AnsiLength = SourceString->Length + 1;
  62. if ( AnsiLength > MAXUSHORT ) {
  63. return STATUS_INVALID_PARAMETER_2;
  64. }
  65. DestinationString->Length = (USHORT)(AnsiLength*2);
  66. if ( AllocateDestinationString ) {
  67. return STATUS_NO_MEMORY;
  68. }
  69. else {
  70. if ( DestinationString->Length >= DestinationString->MaximumLength ) {
  71. return STATUS_BUFFER_OVERFLOW;
  72. }
  73. }
  74. Index = 0;
  75. while(Index < SourceString->Length ) {
  76. DestinationString->Buffer[Index] = (CHAR)SourceString->Buffer[Index];
  77. Index++;
  78. }
  79. DestinationString->Buffer[Index] = TEXT('\0');
  80. return STATUS_SUCCESS;
  81. }
  82. LONG
  83. RtlCompareUnicodeString(
  84. IN PCUNICODE_STRING String1,
  85. IN PCUNICODE_STRING String2,
  86. IN BOOLEAN CaseInSensitive
  87. )
  88. /*++
  89. Routine Description:
  90. The RtlCompareUnicodeString function compares two counted strings. The
  91. return value indicates if the strings are equal or String1 is less than
  92. String2 or String1 is greater than String2.
  93. The CaseInSensitive parameter specifies if case is to be ignored when
  94. doing the comparison.
  95. Arguments:
  96. String1 - Pointer to the first string.
  97. String2 - Pointer to the second string.
  98. CaseInsensitive - TRUE if case should be ignored when doing the
  99. comparison.
  100. Return Value:
  101. Signed value that gives the results of the comparison:
  102. Zero - String1 equals String2
  103. < Zero - String1 less than String2
  104. > Zero - String1 greater than String2
  105. --*/
  106. {
  107. UNALIGNED WCHAR *s1, *s2;
  108. USHORT n1, n2;
  109. WCHAR c1, c2;
  110. LONG cDiff;
  111. s1 = String1->Buffer;
  112. s2 = String2->Buffer;
  113. n1 = (USHORT )(String1->Length / sizeof(WCHAR));
  114. n2 = (USHORT )(String2->Length / sizeof(WCHAR));
  115. while (n1 && n2) {
  116. c1 = *s1++;
  117. c2 = *s2++;
  118. if (CaseInSensitive) {
  119. //
  120. // Note that this needs to reference the translation table !
  121. //
  122. c1 = upcase(c1);
  123. c2 = upcase(c2);
  124. }
  125. if ((cDiff = ((LONG)c1 - (LONG)c2)) != 0) {
  126. return( cDiff );
  127. }
  128. n1--;
  129. n2--;
  130. }
  131. return( n1 - n2 );
  132. }
  133. BOOLEAN
  134. RtlEqualUnicodeString(
  135. IN const UNICODE_STRING *String1,
  136. IN const UNICODE_STRING *String2,
  137. IN BOOLEAN CaseInSensitive
  138. )
  139. /*++
  140. Routine Description:
  141. The RtlEqualUnicodeString function compares two counted unicode strings for
  142. equality.
  143. The CaseInSensitive parameter specifies if case is to be ignored when
  144. doing the comparison.
  145. Arguments:
  146. String1 - Pointer to the first string.
  147. String2 - Pointer to the second string.
  148. CaseInsensitive - TRUE if case should be ignored when doing the
  149. comparison.
  150. Return Value:
  151. Boolean value that is TRUE if String1 equals String2 and FALSE otherwise.
  152. --*/
  153. {
  154. UNALIGNED WCHAR *s1, *s2;
  155. USHORT n1, n2;
  156. WCHAR c1, c2;
  157. s1 = String1->Buffer;
  158. s2 = String2->Buffer;
  159. n1 = (USHORT )(String1->Length / sizeof(WCHAR));
  160. n2 = (USHORT )(String2->Length / sizeof(WCHAR));
  161. if ( n1 != n2 ) {
  162. return FALSE;
  163. }
  164. if (CaseInSensitive) {
  165. while ( n1 ) {
  166. if ( *s1++ != *s2++ ) {
  167. c1 = upcase(*(s1-1));
  168. c2 = upcase(*(s2-1));
  169. if (c1 != c2) {
  170. return( FALSE );
  171. }
  172. }
  173. n1--;
  174. }
  175. }
  176. else {
  177. while ( n1 ) {
  178. if (*s1++ != *s2++) {
  179. return( FALSE );
  180. }
  181. n1--;
  182. }
  183. }
  184. return TRUE;
  185. }
  186. VOID
  187. RtlInitString(
  188. OUT PSTRING DestinationString,
  189. IN PCSZ SourceString OPTIONAL
  190. )
  191. /*++
  192. Routine Description:
  193. The RtlInitString function initializes an NT counted string.
  194. The DestinationString is initialized to point to the SourceString
  195. and the Length and MaximumLength fields of DestinationString are
  196. initialized to the length of the SourceString, which is zero if
  197. SourceString is not specified.
  198. Arguments:
  199. DestinationString - Pointer to the counted string to initialize
  200. SourceString - Optional pointer to a null terminated string that
  201. the counted string is to point to.
  202. Return Value:
  203. None.
  204. --*/
  205. {
  206. DestinationString->Length = 0;
  207. DestinationString->Buffer = (PCHAR)SourceString;
  208. if (ARGUMENT_PRESENT( SourceString )) {
  209. while (*SourceString++) {
  210. DestinationString->Length++;
  211. }
  212. DestinationString->MaximumLength = (SHORT)(DestinationString->Length+1);
  213. }
  214. else {
  215. DestinationString->MaximumLength = 0;
  216. }
  217. }
  218. VOID
  219. RtlInitUnicodeString(
  220. OUT PUNICODE_STRING DestinationString,
  221. IN PCWSTR SourceString OPTIONAL
  222. )
  223. /*++
  224. Routine Description:
  225. The RtlInitUnicodeString function initializes an NT counted
  226. unicode string. The DestinationString is initialized to point to
  227. the SourceString and the Length and MaximumLength fields of
  228. DestinationString are initialized to the length of the SourceString,
  229. which is zero if SourceString is not specified.
  230. Arguments:
  231. DestinationString - Pointer to the counted string to initialize
  232. SourceString - Optional pointer to a null terminated unicode string that
  233. the counted string is to point to.
  234. Return Value:
  235. None.
  236. --*/
  237. {
  238. USHORT Length = 0;
  239. DestinationString->Length = 0;
  240. DestinationString->Buffer = (PWSTR)SourceString;
  241. if (ARGUMENT_PRESENT( SourceString )) {
  242. while (*SourceString++) {
  243. Length += sizeof(*SourceString);
  244. }
  245. DestinationString->Length = Length;
  246. DestinationString->MaximumLength = Length+(USHORT)sizeof(UNICODE_NULL);
  247. }
  248. else {
  249. DestinationString->MaximumLength = 0;
  250. }
  251. }
  252. VOID
  253. RtlInitAnsiString(
  254. OUT PANSI_STRING DestinationString,
  255. IN PCSTR SourceString OPTIONAL
  256. )
  257. /*++
  258. Routine Description:
  259. The RtlInitAnsiString function initializes an NT counted
  260. ANSI string. The DestinationString is initialized to point to
  261. the SourceString and the Length and MaximumLength fields of
  262. DestinationString are initialized to the length of the SourceString,
  263. which is zero if SourceString is not specified.
  264. Arguments:
  265. DestinationString - Pointer to the counted string to initialize
  266. SourceString - Optional pointer to a null terminated ANSI string that
  267. the counted string is to point to.
  268. Return Value:
  269. None.
  270. --*/
  271. {
  272. USHORT Length = 0;
  273. DestinationString->Length = 0;
  274. DestinationString->Buffer = (PSTR)SourceString;
  275. if (ARGUMENT_PRESENT( SourceString )) {
  276. while (*SourceString++) {
  277. Length += sizeof(*SourceString);
  278. }
  279. DestinationString->Length = Length;
  280. DestinationString->MaximumLength = Length+1;
  281. }
  282. else {
  283. DestinationString->MaximumLength = 0;
  284. }
  285. }
  286. NTSTATUS
  287. RtlAppendUnicodeStringToString (
  288. IN OUT PUNICODE_STRING Destination,
  289. IN PCUNICODE_STRING Source
  290. )
  291. /*++
  292. Routine Description:
  293. This routine will concatinate two PSTRINGs together. It will copy
  294. bytes from the source up to the MaximumLength of the destination.
  295. Arguments:
  296. IN PSTRING Destination, - Supplies the destination string
  297. IN PSTRING Source - Supplies the source for the string copy
  298. Return Value:
  299. STATUS_SUCCESS - The source string was successfully appended to the
  300. destination counted string.
  301. STATUS_BUFFER_TOO_SMALL - The destination string length was not big
  302. enough to allow the source string to be appended. The Destination
  303. string length is not updated.
  304. --*/
  305. {
  306. USHORT n = Source->Length;
  307. UNALIGNED WCHAR *dst;
  308. if (n) {
  309. if ((n + Destination->Length) > Destination->MaximumLength) {
  310. return( STATUS_BUFFER_TOO_SMALL );
  311. }
  312. dst = &Destination->Buffer[ (Destination->Length / sizeof( WCHAR )) ];
  313. RtlMoveMemory( dst, Source->Buffer, n );
  314. Destination->Length += n;
  315. if (Destination->Length < Destination->MaximumLength) {
  316. dst[ n / sizeof( WCHAR ) ] = UNICODE_NULL;
  317. }
  318. }
  319. return( STATUS_SUCCESS );
  320. }
  321. NTSTATUS
  322. RtlAppendUnicodeToString (
  323. IN PUNICODE_STRING Destination,
  324. IN PCWSTR Source OPTIONAL
  325. )
  326. /*++
  327. Routine Description:
  328. This routine appends the supplied UNICODE string to an existing
  329. PUNICODE_STRING.
  330. It will copy bytes from the Source PSZ to the destination PSTRING up to
  331. the destinations PUNICODE_STRING->MaximumLength field.
  332. Arguments:
  333. IN PUNICODE_STRING Destination, - Supplies a pointer to the destination
  334. string
  335. IN PWSTR Source - Supplies the string to append to the destination
  336. Return Value:
  337. STATUS_SUCCESS - The source string was successfully appended to the
  338. destination counted string.
  339. STATUS_BUFFER_TOO_SMALL - The destination string length was not big
  340. enough to allow the source string to be appended. The Destination
  341. string length is not updated.
  342. --*/
  343. {
  344. USHORT n;
  345. UNALIGNED WCHAR *dst;
  346. if (ARGUMENT_PRESENT( Source )) {
  347. UNICODE_STRING UniSource;
  348. RtlInitUnicodeString(&UniSource, Source);
  349. n = UniSource.Length;
  350. if ((n + Destination->Length) > Destination->MaximumLength) {
  351. return( STATUS_BUFFER_TOO_SMALL );
  352. }
  353. dst = &Destination->Buffer[ (Destination->Length / sizeof( WCHAR )) ];
  354. RtlMoveMemory( dst, Source, n );
  355. Destination->Length += n;
  356. if (Destination->Length < Destination->MaximumLength) {
  357. dst[ n / sizeof( WCHAR ) ] = UNICODE_NULL;
  358. }
  359. }
  360. return( STATUS_SUCCESS );
  361. }
  362. WCHAR
  363. RtlUpcaseUnicodeChar(
  364. IN WCHAR SourceCharacter
  365. )
  366. /*++
  367. Routine Description:
  368. This function translates the specified unicode character to its
  369. equivalent upcased unicode chararacter. The purpose for this routine
  370. is to allow for character by character upcase translation. The
  371. translation is done with respect to the current system locale
  372. information.
  373. Arguments:
  374. SourceCharacter - Supplies the unicode character to be upcased.
  375. Return Value:
  376. Returns the upcased unicode equivalent of the specified input character.
  377. --*/
  378. {
  379. return (upcase(SourceCharacter));
  380. }
  381. WCHAR
  382. RtlAnsiCharToUnicodeChar(
  383. IN OUT PUCHAR *SourceCharacter
  384. )
  385. /*++
  386. Routine Description:
  387. This function translates the specified ansi character to unicode and
  388. returns the unicode value. The purpose for this routine is to allow
  389. for character by character ansi to unicode translation. The
  390. translation is done with respect to the current system locale
  391. information.
  392. Arguments:
  393. SourceCharacter - Supplies a pointer to an ansi character pointer.
  394. Through two levels of indirection, this supplies an ansi
  395. character that is to be translated to unicode. After
  396. translation, the ansi character pointer is modified to point to
  397. the next character to be converted. This is done to allow for
  398. dbcs ansi characters.
  399. Return Value:
  400. Returns the unicode equivalent of the specified ansi character.
  401. --*/
  402. {
  403. WCHAR UnicodeCharacter;
  404. ULONG cbCharSize;
  405. NTSTATUS st;
  406. UnicodeCharacter = (WCHAR)**SourceCharacter;
  407. (*SourceCharacter)++;
  408. return(UnicodeCharacter);
  409. }
  410. NTSTATUS
  411. RtlUpcaseUnicodeToMultiByteN(
  412. OUT PCH MultiByteString,
  413. IN ULONG MaxBytesInMultiByteString,
  414. OUT PULONG BytesInMultiByteString OPTIONAL,
  415. IN PWCH UnicodeString,
  416. IN ULONG BytesInUnicodeString)
  417. /*++
  418. Routine Description:
  419. This functions upper cases the specified unicode source string and
  420. converts it into an ansi string. The translation is done with respect
  421. to the ANSI Code Page (ACP) loaded at boot time.
  422. Arguments:
  423. MultiByteString - Returns an ansi string that is equivalent to the
  424. upper case of the unicode source string. If the translation can
  425. not be done, an error is returned.
  426. MaxBytesInMultiByteString - Supplies the maximum number of bytes to be
  427. written to MultiByteString. If this causes MultiByteString to be a
  428. truncated equivalent of UnicodeString, no error condition results.
  429. BytesInMultiByteString - Returns the number of bytes in the returned
  430. ansi string pointed to by MultiByteString.
  431. UnicodeString - Supplies the unicode source string that is to be
  432. converted to ansi.
  433. BytesInUnicodeString - The number of bytes in the the string pointed to by
  434. UnicodeString.
  435. Return Value:
  436. SUCCESS - The conversion was successful
  437. --*/
  438. {
  439. ULONG TmpCount;
  440. ULONG LoopCount;
  441. ULONG CharsInUnicodeString;
  442. UCHAR SbChar;
  443. WCHAR UnicodeChar;
  444. ULONG i;
  445. //
  446. // Convert Unicode byte count to character count. Byte count of
  447. // multibyte string is equivalent to character count.
  448. //
  449. CharsInUnicodeString = BytesInUnicodeString / sizeof(WCHAR);
  450. LoopCount = (CharsInUnicodeString < MaxBytesInMultiByteString) ?
  451. CharsInUnicodeString : MaxBytesInMultiByteString;
  452. if (ARGUMENT_PRESENT(BytesInMultiByteString))
  453. *BytesInMultiByteString = LoopCount;
  454. for (i=0;i<LoopCount;i++) {
  455. MultiByteString[i] = (UCHAR)RtlUpcaseUnicodeChar((UCHAR)(UnicodeString[i]));
  456. }
  457. return STATUS_SUCCESS;
  458. }
  459. NTSTATUS
  460. RtlMultiByteToUnicodeN(
  461. OUT PWCH UnicodeString,
  462. IN ULONG MaxBytesInUnicodeString,
  463. OUT PULONG BytesInUnicodeString OPTIONAL,
  464. IN PCSTR MultiByteString,
  465. IN ULONG BytesInMultiByteString)
  466. /*++
  467. Routine Description:
  468. This functions converts the specified ansi source string into a
  469. Unicode string. The translation is done with respect to the
  470. ANSI Code Page (ACP) installed at boot time. Single byte characters
  471. in the range 0x00 - 0x7f are simply zero extended as a performance
  472. enhancement. In some far eastern code pages 0x5c is defined as the
  473. Yen sign. For system translation we always want to consider 0x5c
  474. to be the backslash character. We get this for free by zero extending.
  475. NOTE: This routine only supports precomposed Unicode characters.
  476. Arguments:
  477. UnicodeString - Returns a unicode string that is equivalent to
  478. the ansi source string.
  479. MaxBytesInUnicodeString - Supplies the maximum number of bytes to be
  480. written to UnicodeString. If this causes UnicodeString to be a
  481. truncated equivalent of MultiByteString, no error condition results.
  482. BytesInUnicodeString - Returns the number of bytes in the returned
  483. unicode string pointed to by UnicodeString.
  484. MultiByteString - Supplies the ansi source string that is to be
  485. converted to unicode.
  486. BytesInMultiByteString - The number of bytes in the string pointed to
  487. by MultiByteString.
  488. Return Value:
  489. SUCCESS - The conversion was successful.
  490. --*/
  491. {
  492. ULONG LoopCount;
  493. PUSHORT TranslateTable;
  494. ULONG MaxCharsInUnicodeString;
  495. ULONG i;
  496. MaxCharsInUnicodeString = MaxBytesInUnicodeString / sizeof(WCHAR);
  497. LoopCount = (MaxCharsInUnicodeString < BytesInMultiByteString) ?
  498. MaxCharsInUnicodeString : BytesInMultiByteString;
  499. if (ARGUMENT_PRESENT(BytesInUnicodeString))
  500. *BytesInUnicodeString = LoopCount * sizeof(WCHAR);
  501. for (i=0;i<LoopCount;i++) {
  502. UnicodeString[i] = (WCHAR)((UCHAR)(MultiByteString[i]));
  503. }
  504. return(STATUS_SUCCESS);
  505. }
  506. NTSTATUS
  507. RtlUnicodeToMultiByteN(
  508. OUT PCH MultiByteString,
  509. IN ULONG MaxBytesInMultiByteString,
  510. OUT PULONG BytesInMultiByteString OPTIONAL,
  511. IN PWCH UnicodeString,
  512. IN ULONG BytesInUnicodeString)
  513. /*++
  514. Routine Description:
  515. This functions converts the specified unicode source string into an
  516. ansi string. The translation is done with respect to the
  517. ANSI Code Page (ACP) loaded at boot time.
  518. Arguments:
  519. MultiByteString - Returns an ansi string that is equivalent to the
  520. unicode source string. If the translation can not be done,
  521. an error is returned.
  522. MaxBytesInMultiByteString - Supplies the maximum number of bytes to be
  523. written to MultiByteString. If this causes MultiByteString to be a
  524. truncated equivalent of UnicodeString, no error condition results.
  525. BytesInMultiByteString - Returns the number of bytes in the returned
  526. ansi string pointed to by MultiByteString.
  527. UnicodeString - Supplies the unicode source string that is to be
  528. converted to ansi.
  529. BytesInUnicodeString - The number of bytes in the the string pointed to by
  530. UnicodeString.
  531. Return Value:
  532. SUCCESS - The conversion was successful
  533. --*/
  534. {
  535. ULONG TmpCount;
  536. ULONG LoopCount;
  537. ULONG CharsInUnicodeString;
  538. UCHAR SbChar;
  539. WCHAR UnicodeChar;
  540. ULONG i;
  541. //
  542. // Convert Unicode byte count to character count. Byte count of
  543. // multibyte string is equivalent to character count.
  544. //
  545. CharsInUnicodeString = BytesInUnicodeString / sizeof(WCHAR);
  546. LoopCount = (CharsInUnicodeString < MaxBytesInMultiByteString) ?
  547. CharsInUnicodeString : MaxBytesInMultiByteString;
  548. if (ARGUMENT_PRESENT(BytesInMultiByteString))
  549. *BytesInMultiByteString = LoopCount;
  550. for (i=0;i<LoopCount;i++) {
  551. MultiByteString[i] = (CHAR)(UnicodeString[i]);
  552. }
  553. return STATUS_SUCCESS;
  554. }
  555.