Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

nls.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1990 Microsoft Corporation 00004 00005 Module Name: 00006 00007 nls.c 00008 00009 Abstract: 00010 00011 This module implements NLS support functions for NT. 00012 00013 Author: 00014 00015 Mark Lucovsky (markl) 16-Apr-1991 00016 00017 Environment: 00018 00019 Kernel or user-mode 00020 00021 Revision History: 00022 00023 16-Feb-1993 JulieB Added Upcase Rtl Routines. 00024 08-Mar-1993 JulieB Moved Upcase Macro to ntrtlp.h. 00025 02-Apr-1993 JulieB Fixed RtlAnsiCharToUnicodeChar to use transl. tbls. 00026 02-Apr-1993 JulieB Fixed BUFFER_TOO_SMALL check. 00027 28-May-1993 JulieB Fixed code to properly handle DBCS. 00028 00029 --*/ 00030 00031 #include "ntrtlp.h" 00032 00033 #if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME) 00034 #pragma alloc_text(PAGE,RtlAnsiStringToUnicodeString) 00035 #pragma alloc_text(PAGE,RtlAnsiCharToUnicodeChar) 00036 #pragma alloc_text(PAGE,RtlOemStringToUnicodeString) 00037 #pragma alloc_text(PAGE,RtlUnicodeStringToAnsiString) 00038 #pragma alloc_text(PAGE,RtlUpcaseUnicodeStringToAnsiString) 00039 #pragma alloc_text(PAGE,RtlUnicodeStringToOemString) 00040 #pragma alloc_text(PAGE,RtlUpcaseUnicodeStringToOemString) 00041 #pragma alloc_text(PAGE,RtlOemStringToCountedUnicodeString) 00042 #pragma alloc_text(PAGE,RtlUnicodeStringToCountedOemString) 00043 #pragma alloc_text(PAGE,RtlUpcaseUnicodeStringToCountedOemString) 00044 #pragma alloc_text(PAGE,RtlUpcaseUnicodeString) 00045 #pragma alloc_text(PAGE,RtlDowncaseUnicodeString) 00046 #pragma alloc_text(PAGE,RtlUpcaseUnicodeChar) 00047 #pragma alloc_text(PAGE,RtlFreeUnicodeString) 00048 #pragma alloc_text(PAGE,RtlFreeAnsiString) 00049 #pragma alloc_text(PAGE,RtlFreeOemString) 00050 #pragma alloc_text(PAGE,RtlCreateUnicodeString) 00051 #pragma alloc_text(PAGE,RtlEqualDomainName) 00052 #pragma alloc_text(PAGE,RtlEqualComputerName) 00053 #pragma alloc_text(PAGE,RtlEqualUnicodeString) 00054 #pragma alloc_text(PAGE,RtlxUnicodeStringToOemSize) 00055 #pragma alloc_text(PAGE,RtlxAnsiStringToUnicodeSize) 00056 #pragma alloc_text(PAGE,RtlxUnicodeStringToAnsiSize) 00057 #pragma alloc_text(PAGE,RtlxOemStringToUnicodeSize) 00058 #pragma alloc_text(PAGE,RtlIsTextUnicode) 00059 #endif 00060 00061 00062 00063 00064 // 00065 // Global data used for translations. 00066 // 00067 00068 extern PUSHORT NlsAnsiToUnicodeData; // Ansi CP to Unicode translation table 00069 extern PUSHORT NlsLeadByteInfo; // Lead byte info for ACP 00070 00071 // 00072 // Pulled from lmcons.h: 00073 // 00074 00075 #ifndef NETBIOS_NAME_LEN 00076 #define NETBIOS_NAME_LEN 16 // NetBIOS net name (bytes) 00077 #endif // NETBIOS_NAME_LEN 00078 00079 00080 00081 NTSTATUS 00082 RtlAnsiStringToUnicodeString( 00083 OUT PUNICODE_STRING DestinationString, 00084 IN PANSI_STRING SourceString, 00085 IN BOOLEAN AllocateDestinationString 00086 ) 00087 00088 /*++ 00089 00090 Routine Description: 00091 00092 This functions converts the specified ansi source string into a 00093 Unicode string. The translation is done with respect to the 00094 current system locale information. 00095 00096 Arguments: 00097 00098 DestinationString - Returns a unicode string that is equivalent to 00099 the ansi source string. The maximum length field is only 00100 set if AllocateDestinationString is TRUE. 00101 00102 SourceString - Supplies the ansi source string that is to be 00103 converted to unicode. 00104 00105 AllocateDestinationString - Supplies a flag that controls whether or 00106 not this API allocates the buffer space for the destination 00107 string. If it does, then the buffer must be deallocated using 00108 RtlFreeUnicodeString (note that only storage for 00109 DestinationString->Buffer is allocated by this API). 00110 00111 Return Value: 00112 00113 SUCCESS - The conversion was successful 00114 00115 !SUCCESS - The operation failed. No storage was allocated and no 00116 conversion was done. None. 00117 00118 --*/ 00119 00120 { 00121 ULONG UnicodeLength; 00122 ULONG Index; 00123 NTSTATUS st; 00124 00125 RTL_PAGED_CODE(); 00126 00127 UnicodeLength = RtlAnsiStringToUnicodeSize(SourceString); 00128 if ( UnicodeLength > MAXUSHORT ) { 00129 return STATUS_INVALID_PARAMETER_2; 00130 } 00131 00132 DestinationString->Length = (USHORT)(UnicodeLength - sizeof(UNICODE_NULL)); 00133 if ( AllocateDestinationString ) { 00134 DestinationString->MaximumLength = (USHORT)UnicodeLength; 00135 DestinationString->Buffer = (RtlAllocateStringRoutine)(UnicodeLength); 00136 if ( !DestinationString->Buffer ) { 00137 return STATUS_NO_MEMORY; 00138 } 00139 } 00140 else { 00141 if ( DestinationString->Length >= DestinationString->MaximumLength ) { 00142 return STATUS_BUFFER_OVERFLOW; 00143 } 00144 } 00145 00146 st = RtlMultiByteToUnicodeN( 00147 DestinationString->Buffer, 00148 DestinationString->Length, 00149 &Index, 00150 SourceString->Buffer, 00151 SourceString->Length 00152 ); 00153 00154 if (!NT_SUCCESS(st)) { 00155 if ( AllocateDestinationString ) { 00156 (RtlFreeStringRoutine)(DestinationString->Buffer); 00157 DestinationString->Buffer = NULL; 00158 } 00159 00160 return st; 00161 } 00162 00163 DestinationString->Buffer[Index / sizeof(WCHAR)] = UNICODE_NULL; 00164 00165 return STATUS_SUCCESS; 00166 00167 } 00168 00169 00170 WCHAR 00171 RtlAnsiCharToUnicodeChar( 00172 IN OUT PUCHAR *SourceCharacter 00173 ) 00174 00175 /*++ 00176 00177 Routine Description: 00178 00179 This function translates the specified ansi character to unicode and 00180 returns the unicode value. The purpose for this routine is to allow 00181 for character by character ansi to unicode translation. The 00182 translation is done with respect to the current system locale 00183 information. 00184 00185 00186 Arguments: 00187 00188 SourceCharacter - Supplies a pointer to an ansi character pointer. 00189 Through two levels of indirection, this supplies an ansi 00190 character that is to be translated to unicode. After 00191 translation, the ansi character pointer is modified to point to 00192 the next character to be converted. This is done to allow for 00193 dbcs ansi characters. 00194 00195 Return Value: 00196 00197 Returns the unicode equivalent of the specified ansi character. 00198 00199 --*/ 00200 00201 { 00202 WCHAR UnicodeCharacter; 00203 ULONG cbCharSize; 00204 NTSTATUS st; 00205 00206 00207 RTL_PAGED_CODE(); 00208 00209 00210 #if 0 00211 UnicodeCharacter = NlsAnsiToUnicodeData[(UCHAR)(**SourceCharacter)]; 00212 (*SourceCharacter)++; 00213 return UnicodeCharacter; 00214 #endif 00215 00216 00217 // 00218 // Translate the ansi character to unicode - this handles DBCS. 00219 // 00220 cbCharSize = NlsLeadByteInfo[ **SourceCharacter ] ? 2 : 1; 00221 st = RtlMultiByteToUnicodeN ( &UnicodeCharacter, 00222 sizeof ( WCHAR ), 00223 NULL, 00224 *SourceCharacter, 00225 cbCharSize ); 00226 00227 // 00228 // Check for error - The only time this will happen is if there is 00229 // a leadbyte without a trail byte. 00230 // 00231 if ( ! NT_SUCCESS( st ) ) 00232 { 00233 // Use space as default. 00234 UnicodeCharacter = 0x0020; 00235 } 00236 00237 // 00238 // Advance the source pointer and return the Unicode character. 00239 // 00240 (*SourceCharacter) += cbCharSize; 00241 return UnicodeCharacter; 00242 } 00243 00244 00245 NTSTATUS 00246 RtlUnicodeStringToAnsiString( 00247 OUT PANSI_STRING DestinationString, 00248 IN PUNICODE_STRING SourceString, 00249 IN BOOLEAN AllocateDestinationString 00250 ) 00251 00252 /*++ 00253 00254 Routine Description: 00255 00256 This functions converts the specified unicode source string into an 00257 ansi string. The translation is done with respect to the 00258 current system locale information. 00259 00260 Arguments: 00261 00262 DestinationString - Returns an ansi string that is equivalent to the 00263 unicode source string. If the translation can not be done, 00264 an error is returned. The maximum length field is only set if 00265 AllocateDestinationString is TRUE. 00266 00267 SourceString - Supplies the unicode source string that is to be 00268 converted to ansi. 00269 00270 AllocateDestinationString - Supplies a flag that controls whether or 00271 not this API allocates the buffer space for the destination 00272 string. If it does, then the buffer must be deallocated using 00273 RtlFreeAnsiString (note that only storage for 00274 DestinationString->Buffer is allocated by this API). 00275 00276 Return Value: 00277 00278 SUCCESS - The conversion was successful 00279 00280 !SUCCESS - The operation failed. No storage was allocated and no 00281 conversion was done. None. 00282 00283 --*/ 00284 00285 { 00286 ULONG AnsiLength; 00287 ULONG Index; 00288 NTSTATUS st; 00289 NTSTATUS ReturnStatus = STATUS_SUCCESS; 00290 00291 RTL_PAGED_CODE(); 00292 00293 AnsiLength = RtlUnicodeStringToAnsiSize(SourceString); 00294 if ( AnsiLength > MAXUSHORT ) { 00295 return STATUS_INVALID_PARAMETER_2; 00296 } 00297 00298 DestinationString->Length = (USHORT)(AnsiLength - 1); 00299 if ( AllocateDestinationString ) { 00300 DestinationString->MaximumLength = (USHORT)AnsiLength; 00301 DestinationString->Buffer = (RtlAllocateStringRoutine)(AnsiLength); 00302 if ( !DestinationString->Buffer ) { 00303 return STATUS_NO_MEMORY; 00304 } 00305 } 00306 else { 00307 if ( DestinationString->Length >= DestinationString->MaximumLength ) { 00308 /* 00309 * Return STATUS_BUFFER_OVERFLOW, but translate as much as 00310 * will fit into the buffer first. This is the expected 00311 * behavior for routines such as GetProfileStringA. 00312 * Set the length of the buffer to one less than the maximum 00313 * (so that the trail byte of a double byte char is not 00314 * overwritten by doing DestinationString->Buffer[Index] = '\0'). 00315 * RtlUnicodeToMultiByteN is careful not to truncate a 00316 * multibyte character. 00317 */ 00318 if (!DestinationString->MaximumLength) { 00319 return STATUS_BUFFER_OVERFLOW; 00320 } 00321 ReturnStatus = STATUS_BUFFER_OVERFLOW; 00322 DestinationString->Length = DestinationString->MaximumLength - 1; 00323 } 00324 } 00325 00326 st = RtlUnicodeToMultiByteN( 00327 DestinationString->Buffer, 00328 DestinationString->Length, 00329 &Index, 00330 SourceString->Buffer, 00331 SourceString->Length 00332 ); 00333 00334 if (!NT_SUCCESS(st)) { 00335 if ( AllocateDestinationString ) { 00336 (RtlFreeStringRoutine)(DestinationString->Buffer); 00337 DestinationString->Buffer = NULL; 00338 } 00339 00340 return st; 00341 } 00342 00343 DestinationString->Buffer[Index] = '\0'; 00344 00345 return ReturnStatus; 00346 } 00347 00348 00349 NTSTATUS 00350 RtlUpcaseUnicodeStringToAnsiString( 00351 OUT PANSI_STRING DestinationString, 00352 IN PUNICODE_STRING SourceString, 00353 IN BOOLEAN AllocateDestinationString 00354 ) 00355 00356 /*++ 00357 00358 Routine Description: 00359 00360 This functions upper cases the specified unicode source string and then 00361 converts it into an ansi string. The translation is done with respect 00362 to the current system locale information. 00363 00364 Arguments: 00365 00366 DestinationString - Returns an ansi string that is equivalent to the 00367 unicode source string. If the translation can not be done, 00368 an error is returned. The maximum length field is only set 00369 if AllocateDestinationString is TRUE. 00370 00371 SourceString - Supplies the unicode source string that is to be 00372 converted to upper case ansi. 00373 00374 AllocateDestinationString - Supplies a flag that controls whether or 00375 not this API allocates the buffer space for the destination 00376 string. If it does, then the buffer must be deallocated using 00377 RtlFreeAnsiString (note that only storage for 00378 DestinationString->Buffer is allocated by this API). 00379 00380 Return Value: 00381 00382 SUCCESS - The conversion was successful 00383 00384 !SUCCESS - The operation failed. No storage was allocated and no 00385 conversion was done. None. 00386 00387 --*/ 00388 00389 { 00390 ULONG AnsiLength; 00391 ULONG Index; 00392 NTSTATUS st; 00393 00394 RTL_PAGED_CODE(); 00395 00396 AnsiLength = RtlUnicodeStringToAnsiSize(SourceString); 00397 if ( AnsiLength > MAXUSHORT ) { 00398 return STATUS_INVALID_PARAMETER_2; 00399 } 00400 00401 DestinationString->Length = (USHORT)(AnsiLength - 1); 00402 if ( AllocateDestinationString ) { 00403 DestinationString->MaximumLength = (USHORT)AnsiLength; 00404 DestinationString->Buffer = (RtlAllocateStringRoutine)(AnsiLength); 00405 if ( !DestinationString->Buffer ) { 00406 return STATUS_NO_MEMORY; 00407 } 00408 } 00409 else { 00410 if ( DestinationString->Length >= DestinationString->MaximumLength ) { 00411 return STATUS_BUFFER_OVERFLOW; 00412 } 00413 } 00414 00415 st = RtlUpcaseUnicodeToMultiByteN( 00416 DestinationString->Buffer, 00417 DestinationString->Length, 00418 &Index, 00419 SourceString->Buffer, 00420 SourceString->Length 00421 ); 00422 00423 if (!NT_SUCCESS(st)) { 00424 if ( AllocateDestinationString ) { 00425 (RtlFreeStringRoutine)(DestinationString->Buffer); 00426 DestinationString->Buffer = NULL; 00427 } 00428 00429 return st; 00430 } 00431 00432 DestinationString->Buffer[Index] = '\0'; 00433 00434 return STATUS_SUCCESS; 00435 } 00436 00437 00438 NTSTATUS 00439 RtlOemStringToUnicodeString( 00440 OUT PUNICODE_STRING DestinationString, 00441 IN POEM_STRING SourceString, 00442 IN BOOLEAN AllocateDestinationString 00443 ) 00444 00445 /*++ 00446 00447 Routine Description: 00448 00449 This functions converts the specified oem source string into a 00450 Unicode string. The translation is done with respect to the 00451 installed OEM code page (OCP). 00452 00453 Arguments: 00454 00455 DestinationString - Returns a unicode string that is equivalent to 00456 the oem source string. The maximum length field is only 00457 set if AllocateDestinationString is TRUE. 00458 00459 SourceString - Supplies the oem source string that is to be 00460 converted to unicode. 00461 00462 AllocateDestinationString - Supplies a flag that controls whether or 00463 not this API allocates the buffer space for the destination 00464 string. If it does, then the buffer must be deallocated using 00465 RtlFreeUnicodeString (note that only storage for 00466 DestinationString->Buffer is allocated by this API). 00467 00468 Return Value: 00469 00470 SUCCESS - The conversion was successful 00471 00472 !SUCCESS - The operation failed. No storage was allocated and no 00473 conversion was done. None. 00474 00475 --*/ 00476 00477 { 00478 ULONG UnicodeLength; 00479 ULONG Index; 00480 NTSTATUS st; 00481 00482 RTL_PAGED_CODE(); 00483 00484 UnicodeLength = RtlOemStringToUnicodeSize(SourceString); 00485 if ( UnicodeLength > MAXUSHORT ) { 00486 return STATUS_INVALID_PARAMETER_2; 00487 } 00488 00489 DestinationString->Length = (USHORT)(UnicodeLength - sizeof(UNICODE_NULL)); 00490 if ( AllocateDestinationString ) { 00491 DestinationString->MaximumLength = (USHORT)UnicodeLength; 00492 DestinationString->Buffer = (RtlAllocateStringRoutine)(UnicodeLength); 00493 if ( !DestinationString->Buffer ) { 00494 return STATUS_NO_MEMORY; 00495 } 00496 } 00497 else { 00498 if ( DestinationString->Length >= DestinationString->MaximumLength ) { 00499 return STATUS_BUFFER_OVERFLOW; 00500 } 00501 } 00502 00503 st = RtlOemToUnicodeN( 00504 DestinationString->Buffer, 00505 DestinationString->Length, 00506 &Index, 00507 SourceString->Buffer, 00508 SourceString->Length 00509 ); 00510 00511 if (!NT_SUCCESS(st)) { 00512 if ( AllocateDestinationString ) { 00513 (RtlFreeStringRoutine)(DestinationString->Buffer); 00514 DestinationString->Buffer = NULL; 00515 } 00516 00517 return st; 00518 } 00519 00520 DestinationString->Buffer[Index / sizeof(WCHAR)] = UNICODE_NULL; 00521 00522 return STATUS_SUCCESS; 00523 00524 } 00525 00526 00527 NTSTATUS 00528 RtlUnicodeStringToOemString( 00529 OUT POEM_STRING DestinationString, 00530 IN PUNICODE_STRING SourceString, 00531 IN BOOLEAN AllocateDestinationString 00532 ) 00533 00534 /*++ 00535 00536 Routine Description: 00537 00538 This functions converts the specified unicode source string into an 00539 oem string. The translation is done with respect to the OEM code 00540 page (OCP). 00541 00542 Arguments: 00543 00544 DestinationString - Returns an oem string that is equivalent to the 00545 unicode source string. If the translation can not be done, 00546 an error is returned. The maximum length field is only set if 00547 AllocateDestinationString is TRUE. 00548 00549 SourceString - Supplies the unicode source string that is to be 00550 converted to oem. 00551 00552 AllocateDestinationString - Supplies a flag that controls whether or 00553 not this API allocates the buffer space for the destination 00554 string. If it does, then the buffer must be deallocated using 00555 RtlFreeAnsiString (note that only storage for 00556 DestinationString->Buffer is allocated by this API). 00557 00558 Return Value: 00559 00560 SUCCESS - The conversion was successful 00561 00562 !SUCCESS - The operation failed. No storage was allocated and no 00563 conversion was done. None. 00564 00565 --*/ 00566 00567 { 00568 ULONG OemLength; 00569 ULONG Index; 00570 NTSTATUS st; 00571 00572 RTL_PAGED_CODE(); 00573 00574 OemLength = RtlUnicodeStringToOemSize(SourceString); 00575 if ( OemLength > MAXUSHORT ) { 00576 return STATUS_INVALID_PARAMETER_2; 00577 } 00578 00579 DestinationString->Length = (USHORT)(OemLength - 1); 00580 if ( AllocateDestinationString ) { 00581 DestinationString->MaximumLength = (USHORT)OemLength; 00582 DestinationString->Buffer = (RtlAllocateStringRoutine)(OemLength); 00583 if ( !DestinationString->Buffer ) { 00584 return STATUS_NO_MEMORY; 00585 } 00586 } 00587 else { 00588 if ( DestinationString->Length >= DestinationString->MaximumLength ) { 00589 return STATUS_BUFFER_OVERFLOW; 00590 } 00591 } 00592 00593 st = RtlUnicodeToOemN( 00594 DestinationString->Buffer, 00595 DestinationString->Length, 00596 &Index, 00597 SourceString->Buffer, 00598 SourceString->Length 00599 ); 00600 00601 if (!NT_SUCCESS(st)) { 00602 if ( AllocateDestinationString ) { 00603 (RtlFreeStringRoutine)(DestinationString->Buffer); 00604 DestinationString->Buffer = NULL; 00605 } 00606 00607 return st; 00608 } 00609 00610 DestinationString->Buffer[Index] = '\0'; 00611 00612 return STATUS_SUCCESS; 00613 } 00614 00615 00616 NTSTATUS 00617 RtlUpcaseUnicodeStringToOemString( 00618 OUT POEM_STRING DestinationString, 00619 IN PUNICODE_STRING SourceString, 00620 IN BOOLEAN AllocateDestinationString 00621 ) 00622 00623 /*++ 00624 00625 Routine Description: 00626 00627 This function upper cases the specified unicode source string and then 00628 converts it into an oem string. The translation is done with respect 00629 to the OEM code page (OCP). 00630 00631 Arguments: 00632 00633 DestinationString - Returns an oem string that is equivalent to the 00634 unicode source string. The maximum length field is only set if 00635 AllocateDestinationString is TRUE. 00636 00637 SourceString - Supplies the unicode source string that is to be 00638 converted to oem. 00639 00640 AllocateDestinationString - Supplies a flag that controls whether or 00641 not this API allocates the buffer space for the destination 00642 string. If it does, then the buffer must be deallocated using 00643 RtlFreeAnsiString (note that only storage for 00644 DestinationString->Buffer is allocated by this API). 00645 00646 Return Value: 00647 00648 SUCCESS - The conversion was successful 00649 00650 !SUCCESS - The operation failed. No storage was allocated and no 00651 conversion was done. None. 00652 00653 --*/ 00654 00655 { 00656 ULONG OemLength; 00657 ULONG Index; 00658 NTSTATUS st; 00659 00660 RTL_PAGED_CODE(); 00661 00662 OemLength = RtlUnicodeStringToOemSize(SourceString); 00663 if ( OemLength > MAXUSHORT ) { 00664 return STATUS_INVALID_PARAMETER_2; 00665 } 00666 00667 DestinationString->Length = (USHORT)(OemLength - 1); 00668 if ( AllocateDestinationString ) { 00669 DestinationString->MaximumLength = (USHORT)OemLength; 00670 DestinationString->Buffer = (RtlAllocateStringRoutine)(OemLength); 00671 if ( !DestinationString->Buffer ) { 00672 return STATUS_NO_MEMORY; 00673 } 00674 } 00675 else { 00676 if ( DestinationString->Length >= DestinationString->MaximumLength ) { 00677 return STATUS_BUFFER_OVERFLOW; 00678 } 00679 } 00680 00681 st = RtlUpcaseUnicodeToOemN( 00682 DestinationString->Buffer, 00683 DestinationString->Length, 00684 &Index, 00685 SourceString->Buffer, 00686 SourceString->Length 00687 ); 00688 00689 // 00690 // Now do a check here to see if there was really a mapping for all 00691 // characters converted. 00692 // 00693 00694 if (NT_SUCCESS(st) && 00695 !RtlpDidUnicodeToOemWork( DestinationString, SourceString )) { 00696 00697 st = STATUS_UNMAPPABLE_CHARACTER; 00698 } 00699 00700 if (!NT_SUCCESS(st)) { 00701 if ( AllocateDestinationString ) { 00702 (RtlFreeStringRoutine)(DestinationString->Buffer); 00703 DestinationString->Buffer = NULL; 00704 } 00705 00706 return st; 00707 } 00708 00709 DestinationString->Buffer[Index] = '\0'; 00710 00711 return STATUS_SUCCESS; 00712 } 00713 00714 00715 NTSTATUS 00716 RtlOemStringToCountedUnicodeString( 00717 OUT PUNICODE_STRING DestinationString, 00718 IN POEM_STRING SourceString, 00719 IN BOOLEAN AllocateDestinationString 00720 ) 00721 00722 /*++ 00723 00724 Routine Description: 00725 00726 This functions converts the specified oem source string into a 00727 Unicode string. The translation is done with respect to the 00728 installed OEM code page (OCP). 00729 00730 The destination string is NOT unnaturally null terminated. It is a 00731 counted string as counted strings are meant to be. 00732 00733 Arguments: 00734 00735 DestinationString - Returns a unicode string that is equivalent to 00736 the oem source string. The maximum length field is only 00737 set if AllocateDestinationString is TRUE. 00738 00739 SourceString - Supplies the oem source string that is to be 00740 converted to unicode. 00741 00742 AllocateDestinationString - Supplies a flag that controls whether or 00743 not this API allocates the buffer space for the destination 00744 string. If it does, then the buffer must be deallocated using 00745 RtlFreeUnicodeString (note that only storage for 00746 DestinationString->Buffer is allocated by this API). 00747 00748 Return Value: 00749 00750 SUCCESS - The conversion was successful 00751 00752 !SUCCESS - The operation failed. No storage was allocated and no 00753 conversion was done. None. 00754 00755 --*/ 00756 00757 { 00758 ULONG UnicodeLength; 00759 ULONG Index; 00760 NTSTATUS st; 00761 00762 RTL_PAGED_CODE(); 00763 00764 UnicodeLength = RtlOemStringToCountedUnicodeSize(SourceString); 00765 00766 if ( UnicodeLength == 0 ) { 00767 00768 DestinationString->Length = 0; 00769 DestinationString->MaximumLength = 0; 00770 DestinationString->Buffer = NULL; 00771 00772 return STATUS_SUCCESS; 00773 } 00774 00775 if ( UnicodeLength > MAXUSHORT ) { 00776 return STATUS_INVALID_PARAMETER_2; 00777 } 00778 00779 DestinationString->Length = (USHORT)(UnicodeLength); 00780 if ( AllocateDestinationString ) { 00781 DestinationString->MaximumLength = (USHORT)UnicodeLength; 00782 DestinationString->Buffer = (RtlAllocateStringRoutine)(UnicodeLength); 00783 if ( !DestinationString->Buffer ) { 00784 return STATUS_NO_MEMORY; 00785 } 00786 } 00787 else { 00788 if ( DestinationString->Length > DestinationString->MaximumLength ) { 00789 return STATUS_BUFFER_OVERFLOW; 00790 } 00791 } 00792 00793 st = RtlOemToUnicodeN( 00794 DestinationString->Buffer, 00795 DestinationString->Length, 00796 &Index, 00797 SourceString->Buffer, 00798 SourceString->Length 00799 ); 00800 00801 if (!NT_SUCCESS(st)) { 00802 if ( AllocateDestinationString ) { 00803 (RtlFreeStringRoutine)(DestinationString->Buffer); 00804 DestinationString->Buffer = NULL; 00805 } 00806 00807 return st; 00808 } 00809 00810 return STATUS_SUCCESS; 00811 00812 } 00813 00814 00815 NTSTATUS 00816 RtlUnicodeStringToCountedOemString( 00817 OUT POEM_STRING DestinationString, 00818 IN PUNICODE_STRING SourceString, 00819 IN BOOLEAN AllocateDestinationString 00820 ) 00821 00822 /*++ 00823 00824 Routine Description: 00825 00826 This functions converts the specified unicode source string into an 00827 oem string. The translation is done with respect to the OEM code 00828 page (OCP). 00829 00830 The destination string is NOT unnaturally null terminated. It is a 00831 counted string as counted strings are meant to be. 00832 00833 Arguments: 00834 00835 DestinationString - Returns an oem string that is equivalent to the 00836 unicode source string. If the translation can not be done, 00837 an error is returned. The maximum length field is only set if 00838 AllocateDestinationString is TRUE. 00839 00840 SourceString - Supplies the unicode source string that is to be 00841 converted to oem. 00842 00843 AllocateDestinationString - Supplies a flag that controls whether or 00844 not this API allocates the buffer space for the destination 00845 string. If it does, then the buffer must be deallocated using 00846 RtlFreeAnsiString (note that only storage for 00847 DestinationString->Buffer is allocated by this API). 00848 00849 Return Value: 00850 00851 SUCCESS - The conversion was successful 00852 00853 !SUCCESS - The operation failed. No storage was allocated and no 00854 conversion was done. None. 00855 00856 --*/ 00857 00858 { 00859 ULONG OemLength; 00860 ULONG Index; 00861 NTSTATUS st; 00862 00863 RTL_PAGED_CODE(); 00864 00865 OemLength = RtlUnicodeStringToCountedOemSize(SourceString); 00866 00867 if ( OemLength == 0 ) { 00868 00869 DestinationString->Length = 0; 00870 DestinationString->MaximumLength = 0; 00871 DestinationString->Buffer = NULL; 00872 00873 return STATUS_SUCCESS; 00874 } 00875 00876 if ( OemLength > MAXUSHORT ) { 00877 return STATUS_INVALID_PARAMETER_2; 00878 } 00879 00880 DestinationString->Length = (USHORT)(OemLength); 00881 if ( AllocateDestinationString ) { 00882 DestinationString->MaximumLength = (USHORT)OemLength; 00883 DestinationString->Buffer = (RtlAllocateStringRoutine)(OemLength); 00884 if ( !DestinationString->Buffer ) { 00885 return STATUS_NO_MEMORY; 00886 } 00887 } 00888 else { 00889 if ( DestinationString->Length > DestinationString->MaximumLength ) { 00890 return STATUS_BUFFER_OVERFLOW; 00891 } 00892 } 00893 00894 st = RtlUnicodeToOemN( 00895 DestinationString->Buffer, 00896 DestinationString->Length, 00897 &Index, 00898 SourceString->Buffer, 00899 SourceString->Length 00900 ); 00901 00902 // 00903 // Now do a check here to see if there was really a mapping for all 00904 // characters converted. 00905 // 00906 00907 if (NT_SUCCESS(st) && 00908 !RtlpDidUnicodeToOemWork( DestinationString, SourceString )) { 00909 00910 st = STATUS_UNMAPPABLE_CHARACTER; 00911 } 00912 00913 if (!NT_SUCCESS(st)) { 00914 if ( AllocateDestinationString ) { 00915 (RtlFreeStringRoutine)(DestinationString->Buffer); 00916 DestinationString->Buffer = NULL; 00917 } 00918 00919 return st; 00920 } 00921 00922 return STATUS_SUCCESS; 00923 } 00924 00925 00926 NTSTATUS 00927 RtlUpcaseUnicodeStringToCountedOemString( 00928 OUT POEM_STRING DestinationString, 00929 IN PUNICODE_STRING SourceString, 00930 IN BOOLEAN AllocateDestinationString 00931 ) 00932 00933 /*++ 00934 00935 Routine Description: 00936 00937 This functions upper cases the specified unicode source string and 00938 then converts it into an oem string. The translation is done with 00939 respect to the OEM code page (OCP). 00940 00941 The destination string is NOT unnaturally null terminated. It is a 00942 counted string as counted strings are meant to be. 00943 00944 Arguments: 00945 00946 DestinationString - Returns an oem string that is equivalent to the 00947 unicode source string. If the translation can not be done, 00948 an error is returned. The maximum length field is only set 00949 if AllocateDestinationString is TRUE. 00950 00951 SourceString - Supplies the unicode source string that is to be 00952 converted to oem. 00953 00954 AllocateDestinationString - Supplies a flag that controls whether or 00955 not this API allocates the buffer space for the destination 00956 string. If it does, then the buffer must be deallocated using 00957 RtlFreeAnsiString (note that only storage for 00958 DestinationString->Buffer is allocated by this API). 00959 00960 Return Value: 00961 00962 SUCCESS - The conversion was successful 00963 00964 !SUCCESS - The operation failed. No storage was allocated and no 00965 conversion was done. None. 00966 00967 --*/ 00968 00969 { 00970 ULONG OemLength; 00971 ULONG Index; 00972 NTSTATUS st; 00973 00974 RTL_PAGED_CODE(); 00975 00976 OemLength = RtlUnicodeStringToCountedOemSize(SourceString); 00977 00978 if ( OemLength == 0 ) { 00979 00980 DestinationString->Length = 0; 00981 DestinationString->MaximumLength = 0; 00982 DestinationString->Buffer = NULL; 00983 00984 return STATUS_SUCCESS; 00985 } 00986 00987 if ( OemLength > MAXUSHORT ) { 00988 return STATUS_INVALID_PARAMETER_2; 00989 } 00990 00991 DestinationString->Length = (USHORT)(OemLength); 00992 if ( AllocateDestinationString ) { 00993 DestinationString->MaximumLength = (USHORT)OemLength; 00994 DestinationString->Buffer = (RtlAllocateStringRoutine)(OemLength); 00995 if ( !DestinationString->Buffer ) { 00996 return STATUS_NO_MEMORY; 00997 } 00998 } 00999 else { 01000 if ( DestinationString->Length > DestinationString->MaximumLength ) { 01001 return STATUS_BUFFER_OVERFLOW; 01002 } 01003 } 01004 01005 st = RtlUpcaseUnicodeToOemN( 01006 DestinationString->Buffer, 01007 DestinationString->Length, 01008 &Index, 01009 SourceString->Buffer, 01010 SourceString->Length 01011 ); 01012 01013 // 01014 // Now do a check here to see if there was really a mapping for all 01015 // characters converted. 01016 // 01017 01018 if (NT_SUCCESS(st) && 01019 !RtlpDidUnicodeToOemWork( DestinationString, SourceString )) { 01020 01021 st = STATUS_UNMAPPABLE_CHARACTER; 01022 } 01023 01024 if (!NT_SUCCESS(st)) { 01025 if ( AllocateDestinationString ) { 01026 (RtlFreeStringRoutine)(DestinationString->Buffer); 01027 DestinationString->Buffer = NULL; 01028 } 01029 01030 return st; 01031 } 01032 01033 return STATUS_SUCCESS; 01034 } 01035 01036 01037 NTSTATUS 01038 RtlUpcaseUnicodeString( 01039 OUT PUNICODE_STRING DestinationString, 01040 IN PCUNICODE_STRING SourceString, 01041 IN BOOLEAN AllocateDestinationString 01042 ) 01043 01044 /*++ 01045 01046 Routine Description: 01047 01048 This functions converts the specified unicode source string into an 01049 upcased unicode string. The translation is done with respect to the 01050 current system locale information. 01051 01052 Arguments: 01053 01054 DestinationString - Returns a unicode string that is the upcased equivalent 01055 to the unicode source string. The maximum length field is only set if 01056 AllocateDestinationString is TRUE. 01057 01058 SourceString - Supplies the unicode source string that is to being 01059 upcased. 01060 01061 AllocateDestinationString - Supplies a flag that controls whether or 01062 not this API allocates the buffer space for the destination 01063 string. If it does, then the buffer must be deallocated using 01064 RtlFreeUnicodeString (note that only storage for 01065 DestinationString->Buffer is allocated by this API). 01066 01067 Return Value: 01068 01069 SUCCESS - The conversion was successful 01070 01071 !SUCCESS - The operation failed. No storage was allocated and no 01072 conversion was done. None. 01073 01074 --*/ 01075 01076 { 01077 ULONG Index; 01078 ULONG StopIndex; 01079 01080 RTL_PAGED_CODE(); 01081 01082 if ( AllocateDestinationString ) { 01083 DestinationString->MaximumLength = SourceString->Length; 01084 DestinationString->Buffer = (RtlAllocateStringRoutine)((ULONG)DestinationString->MaximumLength); 01085 if ( !DestinationString->Buffer ) { 01086 return STATUS_NO_MEMORY; 01087 } 01088 } 01089 else { 01090 if ( SourceString->Length > DestinationString->MaximumLength ) { 01091 return STATUS_BUFFER_OVERFLOW; 01092 } 01093 } 01094 01095 StopIndex = ((ULONG)SourceString->Length) / sizeof( WCHAR ); 01096 01097 for (Index = 0; Index < StopIndex; Index++) { 01098 DestinationString->Buffer[Index] = (WCHAR)NLS_UPCASE(SourceString->Buffer[Index]); 01099 } 01100 01101 DestinationString->Length = SourceString->Length; 01102 01103 return STATUS_SUCCESS; 01104 } 01105 01106 01107 NTSTATUS 01108 RtlDowncaseUnicodeString( 01109 OUT PUNICODE_STRING DestinationString, 01110 IN PUNICODE_STRING SourceString, 01111 IN BOOLEAN AllocateDestinationString 01112 ) 01113 01114 /*++ 01115 01116 Routine Description: 01117 01118 This functions converts the specified unicode source string into a 01119 downcased unicode string. The translation is done with respect to the 01120 current system locale information. 01121 01122 Arguments: 01123 01124 DestinationString - Returns a unicode string that is the downcased 01125 equivalent to the unicode source string. The maximum length field 01126 is only set if AllocateDestinationString is TRUE. 01127 01128 SourceString - Supplies the unicode source string that is to being 01129 downcased. 01130 01131 AllocateDestinationString - Supplies a flag that controls whether or 01132 not this API allocates the buffer space for the destination 01133 string. If it does, then the buffer must be deallocated using 01134 RtlFreeUnicodeString (note that only storage for 01135 DestinationString->Buffer is allocated by this API). 01136 01137 Return Value: 01138 01139 SUCCESS - The conversion was successful 01140 01141 !SUCCESS - The operation failed. No storage was allocated and no 01142 conversion was done. None. 01143 01144 --*/ 01145 01146 { 01147 ULONG Index; 01148 ULONG StopIndex; 01149 01150 RTL_PAGED_CODE(); 01151 01152 if ( AllocateDestinationString ) { 01153 DestinationString->MaximumLength = SourceString->Length; 01154 DestinationString->Buffer = (RtlAllocateStringRoutine)((ULONG)DestinationString->MaximumLength); 01155 if ( !DestinationString->Buffer ) { 01156 return STATUS_NO_MEMORY; 01157 } 01158 } 01159 else { 01160 if ( SourceString->Length > DestinationString->MaximumLength ) { 01161 return STATUS_BUFFER_OVERFLOW; 01162 } 01163 } 01164 01165 StopIndex = ((ULONG)SourceString->Length) / sizeof( WCHAR ); 01166 01167 for (Index = 0; Index < StopIndex; Index++) { 01168 DestinationString->Buffer[Index] = (WCHAR)NLS_DOWNCASE(SourceString->Buffer[Index]); 01169 } 01170 01171 DestinationString->Length = SourceString->Length; 01172 01173 return STATUS_SUCCESS; 01174 } 01175 01176 01177 WCHAR 01178 RtlUpcaseUnicodeChar( 01179 IN WCHAR SourceCharacter 01180 ) 01181 01182 /*++ 01183 01184 Routine Description: 01185 01186 This function translates the specified unicode character to its 01187 equivalent upcased unicode chararacter. The purpose for this routine 01188 is to allow for character by character upcase translation. The 01189 translation is done with respect to the current system locale 01190 information. 01191 01192 01193 Arguments: 01194 01195 SourceCharacter - Supplies the unicode character to be upcased. 01196 01197 Return Value: 01198 01199 Returns the upcased unicode equivalent of the specified input character. 01200 01201 --*/ 01202 01203 { 01204 RTL_PAGED_CODE(); 01205 01206 // 01207 // Note that this needs to reference the translation table ! 01208 // 01209 01210 return (WCHAR)NLS_UPCASE(SourceCharacter); 01211 } 01212 01213 01214 VOID 01215 RtlFreeUnicodeString( 01216 IN OUT PUNICODE_STRING UnicodeString 01217 ) 01218 01219 /*++ 01220 01221 Routine Description: 01222 01223 This API is used to free storage allocated by 01224 RtlAnsiStringToUnicodeString. Note that only UnicodeString->Buffer 01225 is free'd by this routine. 01226 01227 Arguments: 01228 01229 UnicodeString - Supplies the address of the unicode string whose 01230 buffer was previously allocated by RtlAnsiStringToUnicodeString. 01231 01232 Return Value: 01233 01234 None. 01235 01236 --*/ 01237 01238 { 01239 RTL_PAGED_CODE(); 01240 01241 if (UnicodeString->Buffer) { 01242 (RtlFreeStringRoutine)(UnicodeString->Buffer); 01243 memset( UnicodeString, 0, sizeof( *UnicodeString ) ); 01244 } 01245 } 01246 01247 01248 VOID 01249 RtlFreeAnsiString( 01250 IN OUT PANSI_STRING AnsiString 01251 ) 01252 01253 /*++ 01254 01255 Routine Description: 01256 01257 This API is used to free storage allocated by 01258 RtlUnicodeStringToAnsiString. Note that only AnsiString->Buffer 01259 is free'd by this routine. 01260 01261 Arguments: 01262 01263 AnsiString - Supplies the address of the ansi string whose buffer 01264 was previously allocated by RtlUnicodeStringToAnsiString. 01265 01266 Return Value: 01267 01268 None. 01269 01270 --*/ 01271 01272 { 01273 RTL_PAGED_CODE(); 01274 01275 if (AnsiString->Buffer) { 01276 (RtlFreeStringRoutine)(AnsiString->Buffer); 01277 memset( AnsiString, 0, sizeof( *AnsiString ) ); 01278 } 01279 } 01280 01281 01282 VOID 01283 RtlFreeOemString( 01284 IN OUT POEM_STRING OemString 01285 ) 01286 01287 /*++ 01288 01289 Routine Description: 01290 01291 This API is used to free storage allocated by 01292 RtlUnicodeStringToOemString. Note that only OemString->Buffer 01293 is free'd by this routine. 01294 01295 Arguments: 01296 01297 OemString - Supplies the address of the oem string whose buffer 01298 was previously allocated by RtlUnicodeStringToOemString. 01299 01300 Return Value: 01301 01302 None. 01303 01304 --*/ 01305 01306 { 01307 RTL_PAGED_CODE(); 01308 01309 if (OemString->Buffer) {(RtlFreeStringRoutine)(OemString->Buffer);} 01310 } 01311 01312 01313 ULONG 01314 RtlxUnicodeStringToAnsiSize( 01315 IN PUNICODE_STRING UnicodeString 01316 ) 01317 01318 /*++ 01319 01320 Routine Description: 01321 01322 This function computes the number of bytes required to store 01323 a NULL terminated ansi string that is equivalent to the specified 01324 unicode string. If an ansi string can not be formed, the return value 01325 is 0. 01326 01327 Arguments: 01328 01329 UnicodeString - Supplies a unicode string whose equivalent size as 01330 an ansi string is to be calculated. 01331 01332 Return Value: 01333 01334 0 - The operation failed, the unicode string can not be translated 01335 into ansi using the current system locale therefore no storage 01336 is needed for the ansi string. 01337 01338 !0 - The operation was successful. The return value specifies the 01339 number of bytes required to hold an NULL terminated ansi string 01340 equivalent to the specified unicode string. 01341 01342 --*/ 01343 01344 { 01345 ULONG cbMultiByteString; 01346 01347 RTL_PAGED_CODE(); 01348 01349 // 01350 // Get the size of the string - this call handles DBCS. 01351 // 01352 RtlUnicodeToMultiByteSize( &cbMultiByteString, 01353 UnicodeString->Buffer, 01354 UnicodeString->Length ); 01355 01356 // 01357 // Return the size in bytes. 01358 // 01359 return (cbMultiByteString + 1); 01360 } 01361 01362 01363 ULONG 01364 RtlxUnicodeStringToOemSize( 01365 IN PUNICODE_STRING UnicodeString 01366 ) 01367 01368 /*++ 01369 01370 Routine Description: 01371 01372 This function computes the number of bytes required to store 01373 a NULL terminated oem string that is equivalent to the specified 01374 unicode string. If an oem string can not be formed, the return value 01375 is 0. 01376 01377 Arguments: 01378 01379 UnicodeString - Supplies a unicode string whose equivalent size as 01380 an oem string is to be calculated. 01381 01382 Return Value: 01383 01384 0 - The operation failed, the unicode string can not be translated 01385 into oem using the OEM code page therefore no storage is 01386 needed for the oem string. 01387 01388 !0 - The operation was successful. The return value specifies the 01389 number of bytes required to hold an NULL terminated oem string 01390 equivalent to the specified unicode string. 01391 01392 --*/ 01393 01394 { 01395 ULONG cbMultiByteString; 01396 01397 RTL_PAGED_CODE(); 01398 01399 // 01400 // LATER: Define an RtlUnicodeToOemSize. 01401 // In the Japanese version, it's safe to call 01402 // RtlUnicodeToMultiByteSize because the Ansi code page 01403 // and the OEM code page are the same. 01404 // 01405 01406 // 01407 // Get the size of the string - this call handles DBCS. 01408 // 01409 RtlUnicodeToMultiByteSize( &cbMultiByteString, 01410 UnicodeString->Buffer, 01411 UnicodeString->Length ); 01412 01413 // 01414 // Return the size in bytes. 01415 // 01416 return (cbMultiByteString + 1); 01417 } 01418 01419 01420 ULONG 01421 RtlxAnsiStringToUnicodeSize( 01422 IN PANSI_STRING AnsiString 01423 ) 01424 01425 /*++ 01426 01427 Routine Description: 01428 01429 This function computes the number of bytes required to store a NULL 01430 terminated unicode string that is equivalent to the specified ansi 01431 string. 01432 01433 Arguments: 01434 01435 AnsiString - Supplies an ansi string whose equivalent size as a 01436 unicode string is to be calculated. The ansi string is 01437 interpreted relative to the current system locale. 01438 01439 Return Value: 01440 01441 The return value specifies the number of bytes required to hold a 01442 NULL terminated unicode string equivalent to the specified ansi 01443 string. 01444 01445 --*/ 01446 01447 { 01448 ULONG cbConverted; 01449 01450 RTL_PAGED_CODE(); 01451 01452 // 01453 // Get the size of the string - this call handles DBCS. 01454 // 01455 RtlMultiByteToUnicodeSize( &cbConverted , 01456 AnsiString->Buffer, 01457 AnsiString->Length ); 01458 01459 // 01460 // Return the size in bytes. 01461 // 01462 return ( cbConverted + sizeof(UNICODE_NULL) ); 01463 } 01464 01465 01466 ULONG 01467 RtlxOemStringToUnicodeSize( 01468 IN POEM_STRING OemString 01469 ) 01470 01471 /*++ 01472 01473 Routine Description: 01474 01475 This function computes the number of bytes required to store a NULL 01476 terminated unicode string that is equivalent to the specified oem 01477 string. 01478 01479 Arguments: 01480 01481 OemString - Supplies an oem string whose equivalent size as a 01482 unicode string is to be calculated. The oem string is 01483 interpreted relative to the current oem code page (OCP). 01484 01485 Return Value: 01486 01487 The return value specifies the number of bytes required to hold a 01488 NULL terminated unicode string equivalent to the specified oem 01489 string. 01490 01491 --*/ 01492 01493 { 01494 ULONG cbConverted; 01495 01496 RTL_PAGED_CODE(); 01497 01498 // 01499 // LATER: Define an RtlOemToUnicodeSize. 01500 // In the Japanese version, it's safe to call 01501 // RtlMultiByteToUnicodeSize because the Ansi code page 01502 // and the OEM code page are the same. 01503 // 01504 01505 // 01506 // Get the size of the string - this call handles DBCS. 01507 // 01508 RtlMultiByteToUnicodeSize( &cbConverted, 01509 OemString->Buffer, 01510 OemString->Length ); 01511 01512 // 01513 // Return the size in bytes. 01514 // 01515 return ( cbConverted + sizeof(UNICODE_NULL) ); 01516 } 01517 01518 01519 LONG 01520 RtlCompareUnicodeString( 01521 IN PUNICODE_STRING String1, 01522 IN PUNICODE_STRING String2, 01523 IN BOOLEAN CaseInSensitive 01524 ) 01525 01526 /*++ 01527 01528 Routine Description: 01529 01530 The RtlCompareUnicodeString function compares two counted strings. The 01531 return value indicates if the strings are equal or String1 is less than 01532 String2 or String1 is greater than String2. 01533 01534 The CaseInSensitive parameter specifies if case is to be ignored when 01535 doing the comparison. 01536 01537 Arguments: 01538 01539 String1 - Pointer to the first string. 01540 01541 String2 - Pointer to the second string. 01542 01543 CaseInsensitive - TRUE if case should be ignored when doing the 01544 comparison. 01545 01546 Return Value: 01547 01548 Signed value that gives the results of the comparison: 01549 01550 Zero - String1 equals String2 01551 01552 < Zero - String1 less than String2 01553 01554 > Zero - String1 greater than String2 01555 01556 01557 --*/ 01558 01559 { 01560 01561 PWCHAR s1, s2, Limit; 01562 LONG n1, n2; 01563 WCHAR c1, c2; 01564 01565 s1 = String1->Buffer; 01566 s2 = String2->Buffer; 01567 n1 = String1->Length; 01568 n2 = String2->Length; 01569 01570 ASSERT((n1 & 1) == 0); 01571 ASSERT((n2 & 1) == 0); 01572 ASSERT(!(((((ULONG_PTR)s1 & 1) != 0) || (((ULONG_PTR)s2 & 1) != 0)) && (n1 != 0) && (n2 != 0))); 01573 01574 Limit = (PWCHAR)((PCHAR)s1 + (n1 <= n2 ? n1 : n2)); 01575 if (CaseInSensitive) { 01576 while (s1 < Limit) { 01577 c1 = *s1++; 01578 c2 = *s2++; 01579 if (c1 != c2) { 01580 01581 // 01582 // Note that this needs to reference the translation table! 01583 // 01584 01585 c1 = NLS_UPCASE(c1); 01586 c2 = NLS_UPCASE(c2); 01587 if (c1 != c2) { 01588 return (LONG)(c1) - (LONG)(c2); 01589 } 01590 } 01591 } 01592 01593 } else { 01594 while (s1 < Limit) { 01595 c1 = *s1++; 01596 c2 = *s2++; 01597 if (c1 != c2) { 01598 return (LONG)(c1) - (LONG)(c2); 01599 } 01600 } 01601 } 01602 01603 return n1 - n2; 01604 } 01605 01606 01607 BOOLEAN 01608 RtlEqualUnicodeString( 01609 IN PCUNICODE_STRING String1, 01610 IN PCUNICODE_STRING String2, 01611 IN BOOLEAN CaseInSensitive 01612 ) 01613 01614 /*++ 01615 01616 Routine Description: 01617 01618 The RtlEqualUnicodeString function compares two counted unicode strings for 01619 equality. 01620 01621 The CaseInSensitive parameter specifies if case is to be ignored when 01622 doing the comparison. 01623 01624 Arguments: 01625 01626 String1 - Pointer to the first string. 01627 01628 String2 - Pointer to the second string. 01629 01630 CaseInsensitive - TRUE if case should be ignored when doing the 01631 comparison. 01632 01633 Return Value: 01634 01635 Boolean value that is TRUE if String1 equals String2 and FALSE otherwise. 01636 01637 --*/ 01638 01639 { 01640 01641 PWCHAR s1, s2, Limit; 01642 LONG n1, n2; 01643 WCHAR c1, c2; 01644 01645 RTL_PAGED_CODE(); 01646 01647 n1 = String1->Length; 01648 n2 = String2->Length; 01649 01650 ASSERT((n1 & 1) == 0); 01651 ASSERT((n2 & 1) == 0); 01652 01653 if (n1 == n2) { 01654 s1 = String1->Buffer; 01655 s2 = String2->Buffer; 01656 01657 ASSERT(!(((((ULONG_PTR)s1 & 1) != 0) || (((ULONG_PTR)s2 & 1) != 0)) && (n1 != 0) && (n2 != 0))); 01658 01659 Limit = (PWCHAR)((PCHAR)s1 + n1); 01660 if (CaseInSensitive) { 01661 while (s1 < Limit) { 01662 c1 = *s1++; 01663 c2 = *s2++; 01664 if ((c1 != c2) && (NLS_UPCASE(c1) != NLS_UPCASE(c2))) { 01665 return FALSE; 01666 } 01667 } 01668 01669 return TRUE; 01670 01671 } else { 01672 while (s1 < Limit) { 01673 c1 = *s1++; 01674 c2 = *s2++; 01675 if (c1 != c2) { 01676 return FALSE; 01677 } 01678 } 01679 01680 return TRUE; 01681 } 01682 01683 } else { 01684 return FALSE; 01685 } 01686 } 01687 01688 01689 BOOLEAN 01690 RtlPrefixUnicodeString( 01691 IN PUNICODE_STRING String1, 01692 IN PUNICODE_STRING String2, 01693 IN BOOLEAN CaseInSensitive 01694 ) 01695 01696 /*++ 01697 01698 Routine Description: 01699 01700 The RtlPrefixUnicodeString function determines if the String1 01701 counted string parameter is a prefix of the String2 counted string 01702 parameter. 01703 01704 The CaseInSensitive parameter specifies if case is to be ignored when 01705 doing the comparison. 01706 01707 Arguments: 01708 01709 String1 - Pointer to the first unicode string. 01710 01711 String2 - Pointer to the second unicode string. 01712 01713 CaseInsensitive - TRUE if case should be ignored when doing the 01714 comparison. 01715 01716 Return Value: 01717 01718 Boolean value that is TRUE if String1 equals a prefix of String2 and 01719 FALSE otherwise. 01720 01721 --*/ 01722 01723 { 01724 PWSTR s1, s2; 01725 ULONG n; 01726 WCHAR c1, c2; 01727 01728 s1 = String1->Buffer; 01729 s2 = String2->Buffer; 01730 n = String1->Length; 01731 if (String2->Length < n) { 01732 return( FALSE ); 01733 } 01734 01735 n = n / sizeof(c1); 01736 if (CaseInSensitive) { 01737 while (n) { 01738 c1 = *s1++; 01739 c2 = *s2++; 01740 01741 if ((c1 != c2) && (NLS_UPCASE(c1) != NLS_UPCASE(c2))) { 01742 return( FALSE ); 01743 } 01744 01745 n--; 01746 } 01747 } 01748 else { 01749 while (n) { 01750 if (*s1++ != *s2++) { 01751 return( FALSE ); 01752 } 01753 01754 n--; 01755 } 01756 } 01757 01758 return TRUE; 01759 } 01760 01761 01762 VOID 01763 RtlCopyUnicodeString( 01764 OUT PUNICODE_STRING DestinationString, 01765 IN PUNICODE_STRING SourceString OPTIONAL 01766 ) 01767 01768 /*++ 01769 01770 Routine Description: 01771 01772 The RtlCopyString function copies the SourceString to the 01773 DestinationString. If SourceString is not specified, then 01774 the Length field of DestinationString is set to zero. The 01775 MaximumLength and Buffer fields of DestinationString are not 01776 modified by this function. 01777 01778 The number of bytes copied from the SourceString is either the 01779 Length of SourceString or the MaximumLength of DestinationString, 01780 whichever is smaller. 01781 01782 Arguments: 01783 01784 DestinationString - Pointer to the destination string. 01785 01786 SourceString - Optional pointer to the source string. 01787 01788 Return Value: 01789 01790 None. 01791 01792 --*/ 01793 01794 { 01795 UNALIGNED WCHAR *src, *dst; 01796 ULONG n; 01797 01798 if (ARGUMENT_PRESENT(SourceString)) { 01799 dst = DestinationString->Buffer; 01800 src = SourceString->Buffer; 01801 n = SourceString->Length; 01802 if ((USHORT)n > DestinationString->MaximumLength) { 01803 n = DestinationString->MaximumLength; 01804 } 01805 01806 DestinationString->Length = (USHORT)n; 01807 RtlCopyMemory(dst, src, n); 01808 if (DestinationString->Length < DestinationString->MaximumLength) { 01809 dst[n / sizeof(WCHAR)] = UNICODE_NULL; 01810 } 01811 01812 } else { 01813 DestinationString->Length = 0; 01814 } 01815 01816 return; 01817 } 01818 01819 01820 NTSTATUS 01821 RtlAppendUnicodeToString ( 01822 IN PUNICODE_STRING Destination, 01823 IN PCWSTR Source OPTIONAL 01824 ) 01825 01826 /*++ 01827 01828 Routine Description: 01829 01830 This routine appends the supplied UNICODE string to an existing 01831 PUNICODE_STRING. 01832 01833 It will copy bytes from the Source PSZ to the destination PSTRING up to 01834 the destinations PUNICODE_STRING->MaximumLength field. 01835 01836 Arguments: 01837 01838 IN PUNICODE_STRING Destination, - Supplies a pointer to the destination 01839 string 01840 IN PWSTR Source - Supplies the string to append to the destination 01841 01842 Return Value: 01843 01844 STATUS_SUCCESS - The source string was successfully appended to the 01845 destination counted string. 01846 01847 STATUS_BUFFER_TOO_SMALL - The destination string length was not big 01848 enough to allow the source string to be appended. The Destination 01849 string length is not updated. 01850 01851 --*/ 01852 01853 { 01854 USHORT n; 01855 UNALIGNED WCHAR *dst; 01856 01857 if (ARGUMENT_PRESENT( Source )) { 01858 UNICODE_STRING UniSource; 01859 01860 RtlInitUnicodeString(&UniSource, Source); 01861 01862 n = UniSource.Length; 01863 01864 if ((n + Destination->Length) > Destination->MaximumLength) { 01865 return( STATUS_BUFFER_TOO_SMALL ); 01866 } 01867 01868 dst = &Destination->Buffer[ (Destination->Length / sizeof( WCHAR )) ]; 01869 RtlMoveMemory( dst, Source, n ); 01870 01871 Destination->Length += n; 01872 01873 if (Destination->Length < Destination->MaximumLength) { 01874 dst[ n / sizeof( WCHAR ) ] = UNICODE_NULL; 01875 } 01876 } 01877 01878 return( STATUS_SUCCESS ); 01879 } 01880 01881 01882 NTSTATUS 01883 RtlAppendUnicodeStringToString ( 01884 IN PUNICODE_STRING Destination, 01885 IN PUNICODE_STRING Source 01886 ) 01887 01888 /*++ 01889 01890 Routine Description: 01891 01892 This routine will concatinate two PSTRINGs together. It will copy 01893 bytes from the source up to the MaximumLength of the destination. 01894 01895 Arguments: 01896 01897 IN PSTRING Destination, - Supplies the destination string 01898 IN PSTRING Source - Supplies the source for the string copy 01899 01900 Return Value: 01901 01902 STATUS_SUCCESS - The source string was successfully appended to the 01903 destination counted string. 01904 01905 STATUS_BUFFER_TOO_SMALL - The destination string length was not big 01906 enough to allow the source string to be appended. The Destination 01907 string length is not updated. 01908 01909 --*/ 01910 01911 { 01912 USHORT n = Source->Length; 01913 UNALIGNED WCHAR *dst; 01914 01915 if (n) { 01916 if ((n + Destination->Length) > Destination->MaximumLength) { 01917 return( STATUS_BUFFER_TOO_SMALL ); 01918 } 01919 01920 dst = &Destination->Buffer[ (Destination->Length / sizeof( WCHAR )) ]; 01921 RtlMoveMemory( dst, Source->Buffer, n ); 01922 01923 Destination->Length += n; 01924 01925 if (Destination->Length < Destination->MaximumLength) { 01926 dst[ n / sizeof( WCHAR ) ] = UNICODE_NULL; 01927 } 01928 } 01929 01930 return( STATUS_SUCCESS ); 01931 } 01932 01933 01934 BOOLEAN 01935 RtlCreateUnicodeString( 01936 OUT PUNICODE_STRING DestinationString, 01937 IN PCWSTR SourceString 01938 ) 01939 { 01940 ULONG cb; 01941 01942 RTL_PAGED_CODE(); 01943 01944 cb = (wcslen( SourceString ) + 1) * sizeof( WCHAR ); 01945 DestinationString->Buffer = (RtlAllocateStringRoutine)( cb ); 01946 if (DestinationString->Buffer) { 01947 RtlMoveMemory( DestinationString->Buffer, SourceString, cb ); 01948 DestinationString->MaximumLength = (USHORT)cb; 01949 DestinationString->Length = (USHORT)(cb - sizeof( UNICODE_NULL )); 01950 return( TRUE ); 01951 } 01952 else { 01953 return( FALSE ); 01954 } 01955 } 01956 01957 01958 BOOLEAN 01959 RtlEqualDomainName( 01960 IN PUNICODE_STRING String1, 01961 IN PUNICODE_STRING String2 01962 ) 01963 01964 /*++ 01965 01966 Routine Description: 01967 01968 The RtlEqualDomainName function compares two domain names for equality. 01969 01970 The comparison is a case insensitive comparison of the OEM equivalent 01971 strings. 01972 01973 The domain name is not validated for length nor invalid characters. 01974 01975 Arguments: 01976 01977 String1 - Pointer to the first string. 01978 01979 String2 - Pointer to the second string. 01980 01981 Return Value: 01982 01983 Boolean value that is TRUE if String1 equals String2 and FALSE otherwise. 01984 01985 --*/ 01986 01987 { 01988 NTSTATUS Status; 01989 BOOLEAN ReturnValue = FALSE; 01990 OEM_STRING OemString1; 01991 OEM_STRING OemString2; 01992 01993 RTL_PAGED_CODE(); 01994 01995 // 01996 // Upper case and convert the first string to OEM 01997 // 01998 01999 Status = RtlUpcaseUnicodeStringToOemString( &OemString1, 02000 String1, 02001 TRUE ); // Allocate Dest 02002 02003 if ( NT_SUCCESS( Status ) ) { 02004 02005 // 02006 // Upper case and convert the second string to OEM 02007 // 02008 02009 Status = RtlUpcaseUnicodeStringToOemString( &OemString2, 02010 String2, 02011 TRUE ); // Allocate Dest 02012 02013 if ( NT_SUCCESS( Status ) ) { 02014 02015 // 02016 // Do a case insensitive comparison. 02017 // 02018 02019 ReturnValue = RtlEqualString( &OemString1, 02020 &OemString2, 02021 FALSE ); 02022 02023 RtlFreeOemString( &OemString2 ); 02024 } 02025 02026 RtlFreeOemString( &OemString1 ); 02027 } 02028 02029 return ReturnValue; 02030 } 02031 02032 02033 02034 BOOLEAN 02035 RtlEqualComputerName( 02036 IN PUNICODE_STRING String1, 02037 IN PUNICODE_STRING String2 02038 ) 02039 02040 /*++ 02041 02042 Routine Description: 02043 02044 The RtlEqualComputerName function compares two computer names for equality. 02045 02046 The comparison is a case insensitive comparison of the OEM equivalent 02047 strings. 02048 02049 The domain name is not validated for length nor invalid characters. 02050 02051 Arguments: 02052 02053 String1 - Pointer to the first string. 02054 02055 String2 - Pointer to the second string. 02056 02057 Return Value: 02058 02059 Boolean value that is TRUE if String1 equals String2 and FALSE otherwise. 02060 02061 --*/ 02062 02063 { 02064 return RtlEqualDomainName( String1, String2 ); 02065 } 02066 02072 #define UNICODE_FFFF 0xFFFF 02073 #define REVERSE_BYTE_ORDER_MARK 0xFFFE 02074 #define BYTE_ORDER_MARK 0xFEFF 02075 02076 #define PARAGRAPH_SEPARATOR 0x2029 02077 #define LINE_SEPARATOR 0x2028 02078 02079 #define UNICODE_TAB 0x0009 02080 #define UNICODE_LF 0x000A 02081 #define UNICODE_CR 0x000D 02082 #define UNICODE_SPACE 0x0020 02083 #define UNICODE_CJK_SPACE 0x3000 02084 02085 #define UNICODE_R_TAB 0x0900 02086 #define UNICODE_R_LF 0x0A00 02087 #define UNICODE_R_CR 0x0D00 02088 #define UNICODE_R_SPACE 0x2000 02089 #define UNICODE_R_CJK_SPACE 0x0030 /* Ambiguous - same as ASCII '0' */ 02090 02091 #define ASCII_CRLF 0x0A0D 02092 02093 #define __max(a,b) (((a) > (b)) ? (a) : (b)) 02094 #define __min(a,b) (((a) < (b)) ? (a) : (b)) 02095 02096 02097 BOOLEAN 02098 RtlIsTextUnicode( 02099 IN PVOID Buffer, 02100 IN ULONG Size, 02101 IN OUT PULONG Result OPTIONAL 02102 ) 02103 02104 /*++ 02105 02106 Routine Description: 02107 02108 IsTextUnicode performs a series of inexpensive heuristic checks 02109 on a buffer in order to verify that it contains Unicode data. 02110 02111 02112 [[ need to fix this section, see at the end ]] 02113 02114 Found Return Result 02115 02116 BOM TRUE BOM 02117 RBOM FALSE RBOM 02118 FFFF FALSE Binary 02119 NULL FALSE Binary 02120 null TRUE null bytes 02121 ASCII_CRLF FALSE CRLF 02122 UNICODE_TAB etc. TRUE Zero Ext Controls 02123 UNICODE_TAB_R FALSE Reversed Controls 02124 UNICODE_ZW etc. TRUE Unicode specials 02125 02126 1/3 as little variation in hi-byte as in lo byte: TRUE Correl 02127 3/1 or worse " FALSE AntiCorrel 02128 02129 Arguments: 02130 02131 Buffer - pointer to buffer containing text to examine. 02132 02133 Size - size of buffer in bytes. At most 256 characters in this will 02134 be examined. If the size is less than the size of a unicode 02135 character, then this function returns FALSE. 02136 02137 Result - optional pointer to a flag word that contains additional information 02138 about the reason for the return value. If specified, this value on 02139 input is a mask that is used to limit the factors this routine uses 02140 to make it decision. On output, this flag word is set to contain 02141 those flags that were used to make its decision. 02142 02143 Return Value: 02144 02145 Boolean value that is TRUE if Buffer contains unicode characters. 02146 02147 --*/ 02148 { 02149 UNALIGNED WCHAR *lpBuff = Buffer; 02150 PCHAR lpb = Buffer; 02151 ULONG iBOM = 0; 02152 ULONG iCR = 0; 02153 ULONG iLF = 0; 02154 ULONG iTAB = 0; 02155 ULONG iSPACE = 0; 02156 ULONG iCJK_SPACE = 0; 02157 ULONG iFFFF = 0; 02158 ULONG iPS = 0; 02159 ULONG iLS = 0; 02160 02161 ULONG iRBOM = 0; 02162 ULONG iR_CR = 0; 02163 ULONG iR_LF = 0; 02164 ULONG iR_TAB = 0; 02165 ULONG iR_SPACE = 0; 02166 02167 ULONG iNull = 0; 02168 ULONG iUNULL = 0; 02169 ULONG iCRLF = 0; 02170 ULONG iTmp; 02171 ULONG LastLo = 0; 02172 ULONG LastHi = 0; 02173 ULONG iHi, iLo; 02174 ULONG HiDiff = 0; 02175 ULONG LoDiff = 0; 02176 ULONG cLeadByte = 0; 02177 ULONG cWeird = 0; 02178 02179 ULONG iResult = 0; 02180 02181 ULONG iMaxTmp = __min(256, Size / sizeof(WCHAR)); 02182 02183 // 02184 // Special case when the size is less than or equal to 2. 02185 // Make sure we don't have a character followed by a null byte. 02186 // 02187 if ((Size < 2) || 02188 ((Size == 2) && (lpBuff[0] != 0) && (lpb[1] == 0))) 02189 { 02190 if (ARGUMENT_PRESENT(Result)) 02191 { 02192 *Result = IS_TEXT_UNICODE_ASCII16 | IS_TEXT_UNICODE_CONTROLS; 02193 } 02194 02195 return (FALSE); 02196 } 02197 else if ((Size > 2) && ((Size / sizeof(WCHAR)) <= 256)) 02198 { 02199 // 02200 // If the Size passed in is an even number, we don't want to 02201 // use the last WCHAR because it will contain the final null 02202 // byte. 02203 // 02204 if (((Size % sizeof(WCHAR)) == 0) && 02205 ((lpBuff[iMaxTmp - 1] & 0xff00) == 0)) 02206 { 02207 iMaxTmp--; 02208 } 02209 } 02210 02211 // 02212 // Check at most 256 wide characters, collect various statistics. 02213 // 02214 for (iTmp = 0; iTmp < iMaxTmp; iTmp++) 02215 { 02216 switch (lpBuff[iTmp]) 02217 { 02218 case BYTE_ORDER_MARK: 02219 iBOM++; 02220 break; 02221 case PARAGRAPH_SEPARATOR: 02222 iPS++; 02223 break; 02224 case LINE_SEPARATOR: 02225 iLS++; 02226 break; 02227 case UNICODE_LF: 02228 iLF++; 02229 break; 02230 case UNICODE_TAB: 02231 iTAB++; 02232 break; 02233 case UNICODE_SPACE: 02234 iSPACE++; 02235 break; 02236 case UNICODE_CJK_SPACE: 02237 iCJK_SPACE++; 02238 break; 02239 case UNICODE_CR: 02240 iCR++; 02241 break; 02242 02243 // 02244 // The following codes are expected to show up in 02245 // byte reversed files. 02246 // 02247 case REVERSE_BYTE_ORDER_MARK: 02248 iRBOM++; 02249 break; 02250 case UNICODE_R_LF: 02251 iR_LF++; 02252 break; 02253 case UNICODE_R_TAB: 02254 iR_TAB++; 02255 break; 02256 case UNICODE_R_CR: 02257 iR_CR++; 02258 break; 02259 case UNICODE_R_SPACE: 02260 iR_SPACE++; 02261 break; 02262 02263 // 02264 // The following codes are illegal and should never occur. 02265 // 02266 case UNICODE_FFFF: 02267 iFFFF++; 02268 break; 02269 case UNICODE_NULL: 02270 iUNULL++; 02271 break; 02272 02273 // 02274 // The following is not currently a Unicode character 02275 // but is expected to show up accidentally when reading 02276 // in ASCII files which use CRLF on a little endian machine. 02277 // 02278 case ASCII_CRLF: 02279 iCRLF++; 02280 break; /* little endian */ 02281 } 02282 02283 // 02284 // Collect statistics on the fluctuations of high bytes 02285 // versus low bytes. 02286 // 02287 iHi = HIBYTE(lpBuff[iTmp]); 02288 iLo = LOBYTE(lpBuff[iTmp]); 02289 02290 // 02291 // Count cr/lf and lf/cr that cross two words. 02292 // 02293 if ((iLo == '\r' && LastHi == '\n') || 02294 (iLo == '\n' && LastHi == '\r')) 02295 { 02296 cWeird++; 02297 } 02298 02299 iNull += (iHi ? 0 : 1) + (iLo ? 0 : 1); /* count Null bytes */ 02300 02301 HiDiff += __max(iHi, LastHi) - __min(LastHi, iHi); 02302 LoDiff += __max(iLo, LastLo) - __min(LastLo, iLo); 02303 02304 LastLo = iLo; 02305 LastHi = iHi; 02306 } 02307 02308 // 02309 // Count cr/lf and lf/cr that cross two words. 02310 // 02311 if ((iLo == '\r' && LastHi == '\n') || 02312 (iLo == '\n' && LastHi == '\r')) 02313 { 02314 cWeird++; 02315 } 02316 02317 if (iHi == '\0') /* don't count the last null */ 02318 iNull--; 02319 if (iHi == 26) /* count ^Z at end as weird */ 02320 cWeird++; 02321 02322 iMaxTmp = __min(256 * sizeof(WCHAR), Size); 02323 if (NlsMbCodePageTag) 02324 { 02325 for (iTmp = 0; iTmp < iMaxTmp; iTmp++) 02326 { 02327 if (NlsLeadByteInfo[lpb[iTmp]]) 02328 { 02329 cLeadByte++; 02330 iTmp++; /* should check for trailing-byte range */ 02331 } 02332 } 02333 } 02334 02335 // 02336 // Sift through the statistical evidence. 02337 // 02338 if (LoDiff < 127 && HiDiff == 0) 02339 { 02340 iResult |= IS_TEXT_UNICODE_ASCII16; /* likely 16-bit ASCII */ 02341 } 02342 02343 if (HiDiff && LoDiff == 0) 02344 { 02345 iResult |= IS_TEXT_UNICODE_REVERSE_ASCII16; /* reverse 16-bit ASCII */ 02346 } 02347 02348 // 02349 // Use leadbyte info to weight statistics. 02350 // 02351 if (!NlsMbCodePageTag || cLeadByte == 0 || 02352 !ARGUMENT_PRESENT(Result) || !(*Result & IS_TEXT_UNICODE_DBCS_LEADBYTE)) 02353 { 02354 iHi = 3; 02355 } 02356 else 02357 { 02358 // 02359 // A ratio of cLeadByte:cb of 1:2 ==> dbcs 02360 // Very crude - should have a nice eq. 02361 // 02362 iHi = __min(256, Size / sizeof(WCHAR)) / 2; 02363 if (cLeadByte < (iHi - 1) / 3) 02364 { 02365 iHi = 3; 02366 } 02367 else if (cLeadByte < (2 * (iHi - 1)) / 3) 02368 { 02369 iHi = 2; 02370 } 02371 else 02372 { 02373 iHi = 1; 02374 } 02375 iResult |= IS_TEXT_UNICODE_DBCS_LEADBYTE; 02376 } 02377 02378 if (iHi * HiDiff < LoDiff) 02379 { 02380 iResult |= IS_TEXT_UNICODE_STATISTICS; 02381 } 02382 02383 if (iHi * LoDiff < HiDiff) 02384 { 02385 iResult |= IS_TEXT_UNICODE_REVERSE_STATISTICS; 02386 } 02387 02388 // 02389 // Any control codes widened to 16 bits? Any Unicode character 02390 // which contain one byte in the control code range? 02391 // 02392 if (iCR + iLF + iTAB + iSPACE + iCJK_SPACE /*+iPS+iLS*/) 02393 { 02394 iResult |= IS_TEXT_UNICODE_CONTROLS; 02395 } 02396 02397 if (iR_LF + iR_CR + iR_TAB + iR_SPACE) 02398 { 02399 iResult |= IS_TEXT_UNICODE_REVERSE_CONTROLS; 02400 } 02401 02402 // 02403 // Any characters that are illegal for Unicode? 02404 // 02405 if ((iRBOM + iFFFF + iUNULL + iCRLF) != 0 || 02406 (cWeird != 0 && cWeird >= iMaxTmp/40)) 02407 { 02408 iResult |= IS_TEXT_UNICODE_ILLEGAL_CHARS; 02409 } 02410 02411 // 02412 // Odd buffer length cannot be Unicode. 02413 // 02414 if (Size & 1) 02415 { 02416 iResult |= IS_TEXT_UNICODE_ODD_LENGTH; 02417 } 02418 02419 // 02420 // Any NULL bytes? (Illegal in ANSI) 02421 // 02422 if (iNull) 02423 { 02424 iResult |= IS_TEXT_UNICODE_NULL_BYTES; 02425 } 02426 02427 // 02428 // POSITIVE evidence, BOM or RBOM used as signature. 02429 // 02430 if (*lpBuff == BYTE_ORDER_MARK) 02431 { 02432 iResult |= IS_TEXT_UNICODE_SIGNATURE; 02433 } 02434 else if (*lpBuff == REVERSE_BYTE_ORDER_MARK) 02435 { 02436 iResult |= IS_TEXT_UNICODE_REVERSE_SIGNATURE; 02437 } 02438 02439 // 02440 // Limit to desired categories if requested. 02441 // 02442 if (ARGUMENT_PRESENT(Result)) 02443 { 02444 iResult &= *Result; 02445 *Result = iResult; 02446 } 02447 02448 // 02449 // There are four separate conclusions: 02450 // 02451 // 1: The file APPEARS to be Unicode AU 02452 // 2: The file CANNOT be Unicode CU 02453 // 3: The file CANNOT be ANSI CA 02454 // 02455 // 02456 // This gives the following possible results 02457 // 02458 // CU 02459 // + - 02460 // 02461 // AU AU 02462 // + - + - 02463 // -------- -------- 02464 // CA +| 0 0 2 3 02465 // | 02466 // -| 1 1 4 5 02467 // 02468 // 02469 // Note that there are only 6 really different cases, not 8. 02470 // 02471 // 0 - This must be a binary file 02472 // 1 - ANSI file 02473 // 2 - Unicode file (High probability) 02474 // 3 - Unicode file (more than 50% chance) 02475 // 5 - No evidence for Unicode (ANSI is default) 02476 // 02477 // The whole thing is more complicated if we allow the assumption 02478 // of reverse polarity input. At this point we have a simplistic 02479 // model: some of the reverse Unicode evidence is very strong, 02480 // we ignore most weak evidence except statistics. If this kind of 02481 // strong evidence is found together with Unicode evidence, it means 02482 // its likely NOT Text at all. Furthermore if a REVERSE_BYTE_ORDER_MARK 02483 // is found, it precludes normal Unicode. If both byte order marks are 02484 // found it's not Unicode. 02485 // 02486 02487 // 02488 // Unicode signature : uncontested signature outweighs reverse evidence. 02489 // 02490 if ((iResult & IS_TEXT_UNICODE_SIGNATURE) && 02491 !(iResult & (IS_TEXT_UNICODE_NOT_UNICODE_MASK&(~IS_TEXT_UNICODE_DBCS_LEADBYTE)))) 02492 { 02493 return (TRUE); 02494 } 02495 02496 // 02497 // If we have conflicting evidence, it's not Unicode. 02498 // 02499 if (iResult & IS_TEXT_UNICODE_REVERSE_MASK) 02500 { 02501 return (FALSE); 02502 } 02503 02504 // 02505 // Statistical and other results (cases 2 and 3). 02506 // 02507 if (!(iResult & IS_TEXT_UNICODE_NOT_UNICODE_MASK) && 02508 ((iResult & IS_TEXT_UNICODE_NOT_ASCII_MASK) || 02509 (iResult & IS_TEXT_UNICODE_UNICODE_MASK))) 02510 { 02511 return (TRUE); 02512 } 02513 02514 return (FALSE); 02515 } 02516 02517 02518 NTSTATUS 02519 RtlDnsHostNameToComputerName( 02520 OUT PUNICODE_STRING ComputerNameString, 02521 IN PUNICODE_STRING DnsHostNameString, 02522 IN BOOLEAN AllocateComputerNameString 02523 ) 02524 02525 /*++ 02526 02527 Routine Description: 02528 02529 The RtlDnsHostNameToComputerName API converts a DNS-style host name to a 02530 Netbios-style computer name. 02531 02532 This API does a syntactical mapping of the name. As such, it should not 02533 be used to convert a DNS domain name to a Netbios domain name. 02534 There is no syntactical mapping for domain names. 02535 02536 DNS-style names consist of one or more "labels" separated by a period 02537 (e.g., xxx.nt.microsoft.com). Each label can be up to 63 bytes of 02538 UTF-8 characters and must consist only of characters specified 02539 by the DnsValidateDnsName API. Upper and lower case characters are treated 02540 as the same character. DNS names are represented in the UTF-8 character set 02541 or UNICODE. 02542 02543 Netbios computer names consist of up to 15 bytes of OEM characters 02544 including letters, digits, hyphens, periods and various other characters. 02545 Some of these characters are specific to the character set. Netbios names 02546 are typically represented in the OEM character set. The OEM character 02547 set is different depending on the locale of the particular version of the OS 02548 (e.g., the German version has a different character set than the US version). 02549 Some OEM character sets represent certain characters as 2 bytes 02550 (e.g., Japanese). Netbios names, by convention, are represented in 02551 uppercase where the translation algorithm from lowercase to uppercase 02552 is OEM character set dependent. 02553 02554 These characteristics make translating between DNS name and Netbios name 02555 difficult. 02556 02557 RtlDnsHostNameToComputerName enforces a textual convention for 02558 mapping between the two names. This convention limits the names of 02559 computers to be the common subset of the names. Specifically, the leftmost 02560 label of the DNS name is truncated to 15-bytes of OEM characters. 02561 As such, RtlDnsHostNameToComputerName simply interprets the leftmost label 02562 of the DNS name as the Netbios name. If the DNS name doesn't meet the 02563 criteria of a valid translatable name, a distinct error code is returned. 02564 02565 Arguments: 02566 02567 ComputerNameString - Returns a unicode string that is equivalent to 02568 the DNS source string. The maximum length field is only 02569 set if AllocateComputerNameString is TRUE. 02570 02571 DnsHostNameString - Supplies the DNS host name source string that is to be 02572 converted to a netbios computer name. 02573 02574 This routine does NOT attempt to validate that the passed in DnsHostNameString 02575 is a valid DNS host a DNS host name. Rather it assumes that the passed in 02576 name is valid and converts it on a best effort basis. 02577 02578 AllocateComputerNameString - Supplies a flag that controls whether or 02579 not this API allocates the buffer space for the destination 02580 string. If it does, then the buffer must be deallocated using 02581 RtlFreeUnicodeString (note that only storage for 02582 DestinationString->Buffer is allocated by this API). 02583 02584 Return Value: 02585 02586 SUCCESS - The conversion was successful 02587 02588 STATUS_NO_MEMORY - There is not enough memory to allocate the return buffer. 02589 02590 STATUS_INVALID_COMPUTER_NAME - The DnsHostName has no first label or 02591 one or more characters of the DnsHostName could not be converted to 02592 the OEM character set. 02593 02594 --*/ 02595 02596 { 02597 NTSTATUS Status; 02598 02599 02600 UNICODE_STRING LocalDnsHostNameString; 02601 02602 OEM_STRING OemString; 02603 ULONG ActualOemLength; 02604 CHAR OemStringBuffer[16]; 02605 02606 ULONG i; 02607 02608 RTL_PAGED_CODE(); 02609 02610 // 02611 // Truncate the dns name to the first label 02612 // 02613 02614 LocalDnsHostNameString = *DnsHostNameString; 02615 02616 for ( i=0; i<LocalDnsHostNameString.Length/sizeof(WCHAR); i++ ) { 02617 02618 if ( LocalDnsHostNameString.Buffer[i] == L'.' ) { 02619 LocalDnsHostNameString.Length = (USHORT)(i * sizeof(WCHAR)); 02620 break; 02621 } 02622 } 02623 02624 if ( LocalDnsHostNameString.Length < sizeof(WCHAR) ) { 02625 return STATUS_INVALID_COMPUTER_NAME; 02626 } 02627 02628 // 02629 // Convert the DNS name to OEM truncating at 15 OEM bytes. 02630 // 02631 02632 Status = RtlUpcaseUnicodeToOemN( 02633 OemStringBuffer, 02634 NETBIOS_NAME_LEN-1, // truncate to 15 bytes 02635 &ActualOemLength, 02636 LocalDnsHostNameString.Buffer, 02637 LocalDnsHostNameString.Length ); 02638 02639 if ( !NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW ) { 02640 return Status; 02641 } 02642 02643 02644 // 02645 // Check to see if any characters are not valid OEM characters. 02646 // 02647 02648 OemString.Buffer = OemStringBuffer; 02649 OemString.MaximumLength = OemString.Length = (USHORT) ActualOemLength; 02650 02651 if ( !RtlpDidUnicodeToOemWork( &OemString, &LocalDnsHostNameString )) { 02652 return STATUS_INVALID_COMPUTER_NAME; 02653 } 02654 02655 02656 // 02657 // Convert the OEM string back to UNICODE 02658 // 02659 02660 Status = RtlOemStringToUnicodeString( 02661 ComputerNameString, 02662 &OemString, 02663 AllocateComputerNameString ); 02664 02665 if ( !NT_SUCCESS(Status) ) { 02666 return Status; 02667 } 02668 02669 return STATUS_SUCCESS; 02670 }

Generated on Sat May 15 19:40:57 2004 for test by doxygen 1.3.7