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.

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