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.

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