test: nlsxlat.c Source File

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

# nlsxlat.c

Go to the documentation of this file.

    00001 /****************************** Module Header ******************************\
    00002 * Module Name: nlsxlat.c
    00003 *
    00004 * Copyright (c) 1985-91, Microsoft Corporation
    00005 *
    00006 * This modules contains the private routines for character translation:
    00007 * 8-bit <=> Unicode.
    00008 *
    00009 * History:
    00010 * 03-Jan-1992    gregoryw
    00011 * 16-Feb-1993    JulieB      Added Upcase Routines & Macros.
    00012 * 17-Feb-1993    JulieB      Fixed Tables; Fixed DBCS Code.
    00013 * 08-Mar-1993    JulieB      Moved Upcase Macro to ntrtlp.h.
    00014 \***************************************************************************/
    00015
    00016 #include "ntrtlp.h"
    00017
    00018
    00019 NTSTATUS
    00020 RtlConsoleMultiByteToUnicodeN(
    00021     OUT PWCH UnicodeString,
    00022     IN ULONG MaxBytesInUnicodeString,
    00023     OUT PULONG BytesInUnicodeString OPTIONAL,
    00024     IN PCH MultiByteString,
    00025     IN ULONG BytesInMultiByteString,
    00026     OUT PULONG pdwSpecialChar );
    00027
    00028 VOID
    00029 RtlpInitUpcaseTable(
    00030     IN PUSHORT TableBase,
    00031     OUT PNLSTABLEINFO CodePageTable
    00032     );
    00033
    00034 #if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
    00035 #pragma alloc_text(PAGE,RtlConsoleMultiByteToUnicodeN)
    00036 #pragma alloc_text(PAGE,RtlMultiByteToUnicodeN)
    00037 #pragma alloc_text(PAGE,RtlOemToUnicodeN)
    00038 #pragma alloc_text(PAGE,RtlUnicodeToMultiByteN)
    00039 #pragma alloc_text(PAGE,RtlUpcaseUnicodeToMultiByteN)
    00040 #pragma alloc_text(PAGE,RtlUnicodeToOemN)
    00041 #pragma alloc_text(PAGE,RtlUpcaseUnicodeToOemN)
    00042 #pragma alloc_text(PAGE,RtlpDidUnicodeToOemWork)
    00043 #pragma alloc_text(PAGE,RtlCustomCPToUnicodeN)
    00044 #pragma alloc_text(PAGE,RtlUnicodeToCustomCPN)
    00045 #pragma alloc_text(PAGE,RtlUpcaseUnicodeToCustomCPN)
    00046 #pragma alloc_text(PAGE,RtlInitCodePageTable)
    00047 #pragma alloc_text(PAGE,RtlpInitUpcaseTable)
    00048 #pragma alloc_text(PAGE,RtlInitNlsTables)
    00049 #pragma alloc_text(PAGE,RtlResetRtlTranslations)
    00050 #pragma alloc_text(PAGE,RtlMultiByteToUnicodeSize)
    00051 #pragma alloc_text(PAGE,RtlUnicodeToMultiByteSize)
    00052 #pragma alloc_text(PAGE,RtlGetDefaultCodePage)
    00053 #endif
    00054
    00055
    00056
    00057 //
    00058 // Various defines and convenient macros for data access
    00059 //
    00060
    00061 #define DBCS_TABLE_SIZE 256
    00062
    00063
    00064 /*
    00065  * Global data used by the translation routines.
    00066  *
    00067  */
    00068
    00069 //
    00070 // Upcase and Lowercase data
    00071 //
    00072 PUSHORT Nls844UnicodeUpcaseTable;
    00073 PUSHORT Nls844UnicodeLowercaseTable;
    00074
    00075 //
    00076 // ACP related data
    00077 //
    00078 USHORT   NlsLeadByteInfoTable[DBCS_TABLE_SIZE]; // Lead byte info. for ACP
    00079 USHORT   NlsAnsiCodePage;                  // Default ANSI code page
    00080 USHORT   NlsOemCodePage;                   // Default OEM code page
    00081 PUSHORT  NlsLeadByteInfo = NlsLeadByteInfoTable;
    00082 PUSHORT  NlsMbAnsiCodePageTables;          // Multibyte to Unicode translation tables
    00083 PUSHORT  NlsAnsiToUnicodeData;             // Ansi CP to Unicode translation table
    00084 PCH      NlsUnicodeToAnsiData;             // Unicode to Ansi CP translation table
    00085 PUSHORT  NlsUnicodeToMbAnsiData;           // Unicode to Multibyte Ansi CP translation table
    00086 BOOLEAN  NlsMbCodePageTag = FALSE;         // TRUE -> Multibyte ACP, FALSE -> Singlebyte ACP
    00087
    00088 //
    00089 // OEM related data
    00090 //
    00091 USHORT   NlsOemLeadByteInfoTable[DBCS_TABLE_SIZE]; // Lead byte info. for 0CP
    00092 PUSHORT  NlsOemLeadByteInfo = NlsOemLeadByteInfoTable;
    00093 PUSHORT  NlsMbOemCodePageTables;              // OEM Multibyte to Unicode translation tables
    00094 PUSHORT  NlsOemToUnicodeData;                 // Oem CP to Unicode translation table
    00095 PCH      NlsUnicodeToOemData;                 // Unicode to Oem CP translation table
    00096 PUSHORT  NlsUnicodeToMbOemData;               // Unicode to Multibyte Oem CP translation table
    00097 BOOLEAN  NlsMbOemCodePageTag = FALSE;         // TRUE -> Multibyte OCP, FALSE -> Singlebyte OCP
    00098
    00099 //
    00100 // Default info taken from data files
    00101 //
    00102 USHORT   UnicodeDefaultChar;
    00103
    00104 USHORT   OemDefaultChar;
    00105 USHORT   OemTransUniDefaultChar;
    00106
    00107 //
    00108 // Default info NOT taken from data files
    00109 //
    00110 USHORT   UnicodeNull  = 0x0000;
    00111
    00112
    00113
    00114 NTSTATUS
    00115 RtlConsoleMultiByteToUnicodeN(
    00116     OUT PWCH UnicodeString,
    00117     IN ULONG MaxBytesInUnicodeString,
    00118     OUT PULONG BytesInUnicodeString OPTIONAL,
    00119     IN PCH MultiByteString,
    00120     IN ULONG BytesInMultiByteString,
    00121     OUT PULONG pdwSpecialChar )
    00122
    00123 /*++
    00124
    00125 Routine Description:
    00126
    00127     This function is a superset of MultiByteToUnicode for the
    00128     console.  It works just like the other, except it will detect
    00129     if any characters were under 0x20.
    00130
    00131     This functions converts the specified ansi source string into a
    00132     Unicode string. The translation is done with respect to the
    00133     ANSI Code Page (ACP) installed at boot time.  Single byte characters
    00134     in the range 0x00 - 0x7f are simply zero extended as a performance
    00135     enhancement.  In some far eastern code pages 0x5c is defined as the
    00136     Yen sign.  For system translation we always want to consider 0x5c
    00137     to be the backslash character.  We get this for free by zero extending.
    00138
    00139     NOTE: This routine only supports precomposed Unicode characters.
    00140
    00141 Arguments:
    00142
    00143     UnicodeString - Returns a unicode string that is equivalent to
    00144         the ansi source string.
    00145
    00146     MaxBytesInUnicodeString - Supplies the maximum number of bytes to be
    00147         written to UnicodeString.  If this causes UnicodeString to be a
    00148         truncated equivalent of MultiByteString, no error condition results.
    00149
    00150     BytesInUnicodeString - Returns the number of bytes in the returned
    00151         unicode string pointed to by UnicodeString.
    00152
    00153     MultiByteString - Supplies the ansi source string that is to be
    00154         converted to unicode.
    00155
    00156     BytesInMultiByteString - The number of bytes in the string pointed to
    00157         by MultiByteString.
    00158
    00159     pdwSpecialChar - will be zero if non detected, else it will contain the
    00160        approximate index (can be off by 32).
    00161
    00162 Return Value:
    00163
    00164     SUCCESS - The conversion was successful.
    00165
    00166
    00167 --*/
    00168
    00169 {
    00170     ULONG LoopCount;
    00171     PUSHORT TranslateTable;
    00172     ULONG MaxCharsInUnicodeString;
    00173
    00174     RTL_PAGED_CODE();
    00175
    00176     *pdwSpecialChar = 0;
    00177
    00178     if (!NlsMbCodePageTag) {
    00179         MaxCharsInUnicodeString = MaxBytesInUnicodeString / sizeof(WCHAR);
    00180
    00181         LoopCount = (MaxCharsInUnicodeString < BytesInMultiByteString) ?
    00182                      MaxCharsInUnicodeString : BytesInMultiByteString;
    00183
    00184         if (ARGUMENT_PRESENT(BytesInUnicodeString))
    00185             *BytesInUnicodeString = LoopCount * sizeof(WCHAR);
    00186
    00187         TranslateTable = NlsAnsiToUnicodeData;  // used to help the mips compiler
    00188
    00189         quick_copy:
    00190             switch( LoopCount ) {
    00191             default:
    00192                 if ((UCHAR)MultiByteString[0x1F] < 0x20)    goto  bad_case;
    00193                 UnicodeString[0x1F] = TranslateTable[(UCHAR)MultiByteString[0x1F]];
    00194             case 0x1F:
    00195                 if ((UCHAR)MultiByteString[0x1E] < 0x20)    goto  bad_case;
    00196                 UnicodeString[0x1E] = TranslateTable[(UCHAR)MultiByteString[0x1E]];
    00197             case 0x1E:
    00198                 if ((UCHAR)MultiByteString[0x1D] < 0x20)    goto  bad_case;
    00199                 UnicodeString[0x1D] = TranslateTable[(UCHAR)MultiByteString[0x1D]];
    00200             case 0x1D:
    00201                 if ((UCHAR)MultiByteString[0x1C] < 0x20)    goto  bad_case;
    00202                 UnicodeString[0x1C] = TranslateTable[(UCHAR)MultiByteString[0x1C]];
    00203             case 0x1C:
    00204                 if ((UCHAR)MultiByteString[0x1B] < 0x20)    goto  bad_case;
    00205                 UnicodeString[0x1B] = TranslateTable[(UCHAR)MultiByteString[0x1B]];
    00206             case 0x1B:
    00207                 if ((UCHAR)MultiByteString[0x1A] < 0x20)    goto  bad_case;
    00208                 UnicodeString[0x1A] = TranslateTable[(UCHAR)MultiByteString[0x1A]];
    00209             case 0x1A:
    00210                 if ((UCHAR)MultiByteString[0x19] < 0x20)    goto  bad_case;
    00211                 UnicodeString[0x19] = TranslateTable[(UCHAR)MultiByteString[0x19]];
    00212             case 0x19:
    00213                 if ((UCHAR)MultiByteString[0x18] < 0x20)    goto  bad_case;
    00214                 UnicodeString[0x18] = TranslateTable[(UCHAR)MultiByteString[0x18]];
    00215             case 0x18:
    00216                 if ((UCHAR)MultiByteString[0x17] < 0x20)    goto  bad_case;
    00217                 UnicodeString[0x17] = TranslateTable[(UCHAR)MultiByteString[0x17]];
    00218             case 0x17:
    00219                 if ((UCHAR)MultiByteString[0x16] < 0x20)    goto  bad_case;
    00220                 UnicodeString[0x16] = TranslateTable[(UCHAR)MultiByteString[0x16]];
    00221             case 0x16:
    00222                 if ((UCHAR)MultiByteString[0x15] < 0x20)    goto  bad_case;
    00223                 UnicodeString[0x15] = TranslateTable[(UCHAR)MultiByteString[0x15]];
    00224             case 0x15:
    00225                 if ((UCHAR)MultiByteString[0x14] < 0x20)    goto  bad_case;
    00226                 UnicodeString[0x14] = TranslateTable[(UCHAR)MultiByteString[0x14]];
    00227             case 0x14:
    00228                 if ((UCHAR)MultiByteString[0x13] < 0x20)    goto  bad_case;
    00229                 UnicodeString[0x13] = TranslateTable[(UCHAR)MultiByteString[0x13]];
    00230             case 0x13:
    00231                 if ((UCHAR)MultiByteString[0x12] < 0x20)    goto  bad_case;
    00232                 UnicodeString[0x12] = TranslateTable[(UCHAR)MultiByteString[0x12]];
    00233             case 0x12:
    00234                 if ((UCHAR)MultiByteString[0x11] < 0x20)    goto  bad_case;
    00235                 UnicodeString[0x11] = TranslateTable[(UCHAR)MultiByteString[0x11]];
    00236             case 0x11:
    00237                 if ((UCHAR)MultiByteString[0x10] < 0x20)    goto  bad_case;
    00238                 UnicodeString[0x10] = TranslateTable[(UCHAR)MultiByteString[0x10]];
    00239             case 0x10:
    00240                 if ((UCHAR)MultiByteString[0x0F] < 0x20)    goto  bad_case;
    00241                 UnicodeString[0x0F] = TranslateTable[(UCHAR)MultiByteString[0x0F]];
    00242             case 0x0F:
    00243                 if ((UCHAR)MultiByteString[0x0E] < 0x20)    goto  bad_case;
    00244                 UnicodeString[0x0E] = TranslateTable[(UCHAR)MultiByteString[0x0E]];
    00245             case 0x0E:
    00246                 if ((UCHAR)MultiByteString[0x0D] < 0x20)    goto  bad_case;
    00247                 UnicodeString[0x0D] = TranslateTable[(UCHAR)MultiByteString[0x0D]];
    00248             case 0x0D:
    00249                 if ((UCHAR)MultiByteString[0x0C] < 0x20)    goto  bad_case;
    00250                 UnicodeString[0x0C] = TranslateTable[(UCHAR)MultiByteString[0x0C]];
    00251             case 0x0C:
    00252                 if ((UCHAR)MultiByteString[0x0B] < 0x20)    goto  bad_case;
    00253                 UnicodeString[0x0B] = TranslateTable[(UCHAR)MultiByteString[0x0B]];
    00254             case 0x0B:
    00255                 if ((UCHAR)MultiByteString[0x0A] < 0x20)    goto  bad_case;
    00256                 UnicodeString[0x0A] = TranslateTable[(UCHAR)MultiByteString[0x0A]];
    00257             case 0x0A:
    00258                 if ((UCHAR)MultiByteString[0x09] < 0x20)    goto  bad_case;
    00259                 UnicodeString[0x09] = TranslateTable[(UCHAR)MultiByteString[0x09]];
    00260             case 0x09:
    00261                 if ((UCHAR)MultiByteString[0x08] < 0x20)    goto  bad_case;
    00262                 UnicodeString[0x08] = TranslateTable[(UCHAR)MultiByteString[0x08]];
    00263             case 0x08:
    00264                 if ((UCHAR)MultiByteString[0x07] < 0x20)    goto  bad_case;
    00265                 UnicodeString[0x07] = TranslateTable[(UCHAR)MultiByteString[0x07]];
    00266             case 0x07:
    00267                 if ((UCHAR)MultiByteString[0x06] < 0x20)    goto  bad_case;
    00268                 UnicodeString[0x06] = TranslateTable[(UCHAR)MultiByteString[0x06]];
    00269             case 0x06:
    00270                 if ((UCHAR)MultiByteString[0x05] < 0x20)    goto  bad_case;
    00271                 UnicodeString[0x05] = TranslateTable[(UCHAR)MultiByteString[0x05]];
    00272             case 0x05:
    00273                 if ((UCHAR)MultiByteString[0x04] < 0x20)    goto  bad_case;
    00274                 UnicodeString[0x04] = TranslateTable[(UCHAR)MultiByteString[0x04]];
    00275             case 0x04:
    00276                 if ((UCHAR)MultiByteString[0x03] < 0x20)    goto  bad_case;
    00277                 UnicodeString[0x03] = TranslateTable[(UCHAR)MultiByteString[0x03]];
    00278             case 0x03:
    00279                 if ((UCHAR)MultiByteString[0x02] < 0x20)    goto  bad_case;
    00280                 UnicodeString[0x02] = TranslateTable[(UCHAR)MultiByteString[0x02]];
    00281             case 0x02:
    00282                 if ((UCHAR)MultiByteString[0x01] < 0x20)    goto  bad_case;
    00283                 UnicodeString[0x01] = TranslateTable[(UCHAR)MultiByteString[0x01]];
    00284             case 0x01:
    00285                 if ((UCHAR)MultiByteString[0x00] < 0x20)    goto  bad_case;
    00286                 UnicodeString[0x00] = TranslateTable[(UCHAR)MultiByteString[0x00]];
    00287             case 0x00:
    00288                 ;
    00289             }
    00290
    00291             if ( LoopCount > 0x20 ) {
    00292                 LoopCount -= 0x20;
    00293                 UnicodeString += 0x20;
    00294                 MultiByteString += 0x20;
    00295
    00296                 goto  quick_copy;
    00297             }
    00298         /* end of copy... */
    00299     } else {
    00300         register USHORT Entry;
    00301
    00302         PWCH UnicodeStringAnchor = UnicodeString;
    00303         TranslateTable = (PUSHORT)NlsMbAnsiCodePageTables;
    00304
    00305         // yea, this line is duplicated, but the compiler can handle opt
    00306         // better by moving it around
    00307         MaxCharsInUnicodeString = MaxBytesInUnicodeString / sizeof(WCHAR);
    00308
    00309         //
    00310         // The ACP is a multibyte code page.  Check each character
    00311         // to see if it is a lead byte before doing the translation.
    00312         //
    00313         while (MaxCharsInUnicodeString && BytesInMultiByteString) {
    00314             MaxCharsInUnicodeString--;
    00315             BytesInMultiByteString--;
    00316             if (NlsLeadByteInfo[*(PUCHAR)MultiByteString]) {
    00317                 //
    00318                 // Lead byte - Make sure there is a trail byte.  If not,
    00319                 // pass back a space rather than an error.  Some 3.x
    00320                 // applications pass incorrect strings and don't expect
    00321                 // to get an error.
    00322                 //
    00323                 if (BytesInMultiByteString == 0)
    00324                 {
    00325                     *UnicodeString++ = UnicodeNull;
    00326                     break;
    00327                 }
    00328
    00329                 //
    00330                 // Get the unicode character.
    00331                 //
    00332                 Entry = NlsLeadByteInfo[*(PUCHAR)MultiByteString++];
    00333                 *UnicodeString = (WCHAR)TranslateTable[ Entry + *(PUCHAR)MultiByteString++ ];
    00334                 UnicodeString++;
    00335
    00336                 //
    00337                 // Decrement count of bytes in multibyte string to account
    00338                 // for the double byte character.
    00339                 //
    00340                 BytesInMultiByteString--;
    00341             } else {
    00342                 //
    00343                 // Single byte character.
    00344                 //
    00345                 if ((UCHAR)MultiByteString[0x00] < 0x20)
    00346                     *pdwSpecialChar = 1;
    00347                 *UnicodeString++ = NlsAnsiToUnicodeData[*(PUCHAR)MultiByteString++];
    00348             }
    00349         }
    00350
    00351         if (ARGUMENT_PRESENT(BytesInUnicodeString))
    00352             *BytesInUnicodeString = (ULONG)((PCH)UnicodeString - (PCH)UnicodeStringAnchor);
    00353     }
    00354
    00355     return STATUS_SUCCESS;
    00356
    00357     bad_case:
    00358         //
    00359         // this is a low probability case, so we optimized the loop.  If have a
    00360         // special char, finish trans and notify caller.
    00361         //
    00362         *pdwSpecialChar = 1;
    00363         return RtlMultiByteToUnicodeN(UnicodeString, MaxBytesInUnicodeString,
    00364                 NULL, MultiByteString, LoopCount);
    00365 }
    00366
    00367
    00368 NTSTATUS
    00369 RtlMultiByteToUnicodeN(
    00370     OUT PWCH UnicodeString,
    00371     IN ULONG MaxBytesInUnicodeString,
    00372     OUT PULONG BytesInUnicodeString OPTIONAL,
    00373     IN PCH MultiByteString,
    00374     IN ULONG BytesInMultiByteString)
    00375
    00376 /*++
    00377
    00378 Routine Description:
    00379
    00380     This functions converts the specified ansi source string into a
    00381     Unicode string. The translation is done with respect to the
    00382     ANSI Code Page (ACP) installed at boot time.  Single byte characters
    00383     in the range 0x00 - 0x7f are simply zero extended as a performance
    00384     enhancement.  In some far eastern code pages 0x5c is defined as the
    00385     Yen sign.  For system translation we always want to consider 0x5c
    00386     to be the backslash character.  We get this for free by zero extending.
    00387
    00388     NOTE: This routine only supports precomposed Unicode characters.
    00389
    00390 Arguments:
    00391
    00392     UnicodeString - Returns a unicode string that is equivalent to
    00393         the ansi source string.
    00394
    00395     MaxBytesInUnicodeString - Supplies the maximum number of bytes to be
    00396         written to UnicodeString.  If this causes UnicodeString to be a
    00397         truncated equivalent of MultiByteString, no error condition results.
    00398
    00399     BytesInUnicodeString - Returns the number of bytes in the returned
    00400         unicode string pointed to by UnicodeString.
    00401
    00402     MultiByteString - Supplies the ansi source string that is to be
    00403         converted to unicode.  For single-byte character sets, this address
    00404         CAN be the same as UnicodeString.
    00405
    00406     BytesInMultiByteString - The number of bytes in the string pointed to
    00407         by MultiByteString.
    00408
    00409 Return Value:
    00410
    00411     SUCCESS - The conversion was successful.
    00412
    00413
    00414 --*/
    00415
    00416 {
    00417     ULONG LoopCount;
    00418     ULONG TmpCount;
    00419     PUSHORT TranslateTable;
    00420     ULONG MaxCharsInUnicodeString;
    00421
    00422     RTL_PAGED_CODE();
    00423
    00424     if (!NlsMbCodePageTag) {
    00425         MaxCharsInUnicodeString = MaxBytesInUnicodeString / sizeof(WCHAR);
    00426
    00427         LoopCount = (MaxCharsInUnicodeString < BytesInMultiByteString) ?
    00428                      MaxCharsInUnicodeString : BytesInMultiByteString;
    00429
    00430         if (ARGUMENT_PRESENT(BytesInUnicodeString))
    00431             *BytesInUnicodeString = LoopCount * sizeof(WCHAR);
    00432
    00433         TranslateTable = NlsAnsiToUnicodeData;  // used to help the mips compiler
    00434
    00435         TmpCount = LoopCount & 0x1F;
    00436         UnicodeString += (LoopCount - TmpCount);
    00437         MultiByteString += (LoopCount - TmpCount);
    00438         quick_copy:
    00439             switch( TmpCount ) {
    00440             default:
    00441                 UnicodeString[0x1F] = TranslateTable[(UCHAR)MultiByteString[0x1F]];
    00442             case 0x1F:
    00443                 UnicodeString[0x1E] = TranslateTable[(UCHAR)MultiByteString[0x1E]];
    00444             case 0x1E:
    00445                 UnicodeString[0x1D] = TranslateTable[(UCHAR)MultiByteString[0x1D]];
    00446             case 0x1D:
    00447                 UnicodeString[0x1C] = TranslateTable[(UCHAR)MultiByteString[0x1C]];
    00448             case 0x1C:
    00449                 UnicodeString[0x1B] = TranslateTable[(UCHAR)MultiByteString[0x1B]];
    00450             case 0x1B:
    00451                 UnicodeString[0x1A] = TranslateTable[(UCHAR)MultiByteString[0x1A]];
    00452             case 0x1A:
    00453                 UnicodeString[0x19] = TranslateTable[(UCHAR)MultiByteString[0x19]];
    00454             case 0x19:
    00455                 UnicodeString[0x18] = TranslateTable[(UCHAR)MultiByteString[0x18]];
    00456             case 0x18:
    00457                 UnicodeString[0x17] = TranslateTable[(UCHAR)MultiByteString[0x17]];
    00458             case 0x17:
    00459                 UnicodeString[0x16] = TranslateTable[(UCHAR)MultiByteString[0x16]];
    00460             case 0x16:
    00461                 UnicodeString[0x15] = TranslateTable[(UCHAR)MultiByteString[0x15]];
    00462             case 0x15:
    00463                 UnicodeString[0x14] = TranslateTable[(UCHAR)MultiByteString[0x14]];
    00464             case 0x14:
    00465                 UnicodeString[0x13] = TranslateTable[(UCHAR)MultiByteString[0x13]];
    00466             case 0x13:
    00467                 UnicodeString[0x12] = TranslateTable[(UCHAR)MultiByteString[0x12]];
    00468             case 0x12:
    00469                 UnicodeString[0x11] = TranslateTable[(UCHAR)MultiByteString[0x11]];
    00470             case 0x11:
    00471                 UnicodeString[0x10] = TranslateTable[(UCHAR)MultiByteString[0x10]];
    00472             case 0x10:
    00473                 UnicodeString[0x0F] = TranslateTable[(UCHAR)MultiByteString[0x0F]];
    00474             case 0x0F:
    00475                 UnicodeString[0x0E] = TranslateTable[(UCHAR)MultiByteString[0x0E]];
    00476             case 0x0E:
    00477                 UnicodeString[0x0D] = TranslateTable[(UCHAR)MultiByteString[0x0D]];
    00478             case 0x0D:
    00479                 UnicodeString[0x0C] = TranslateTable[(UCHAR)MultiByteString[0x0C]];
    00480             case 0x0C:
    00481                 UnicodeString[0x0B] = TranslateTable[(UCHAR)MultiByteString[0x0B]];
    00482             case 0x0B:
    00483                 UnicodeString[0x0A] = TranslateTable[(UCHAR)MultiByteString[0x0A]];
    00484             case 0x0A:
    00485                 UnicodeString[0x09] = TranslateTable[(UCHAR)MultiByteString[0x09]];
    00486             case 0x09:
    00487                 UnicodeString[0x08] = TranslateTable[(UCHAR)MultiByteString[0x08]];
    00488             case 0x08:
    00489                 UnicodeString[0x07] = TranslateTable[(UCHAR)MultiByteString[0x07]];
    00490             case 0x07:
    00491                 UnicodeString[0x06] = TranslateTable[(UCHAR)MultiByteString[0x06]];
    00492             case 0x06:
    00493                 UnicodeString[0x05] = TranslateTable[(UCHAR)MultiByteString[0x05]];
    00494             case 0x05:
    00495                 UnicodeString[0x04] = TranslateTable[(UCHAR)MultiByteString[0x04]];
    00496             case 0x04:
    00497                 UnicodeString[0x03] = TranslateTable[(UCHAR)MultiByteString[0x03]];
    00498             case 0x03:
    00499                 UnicodeString[0x02] = TranslateTable[(UCHAR)MultiByteString[0x02]];
    00500             case 0x02:
    00501                 UnicodeString[0x01] = TranslateTable[(UCHAR)MultiByteString[0x01]];
    00502             case 0x01:
    00503                 UnicodeString[0x00] = TranslateTable[(UCHAR)MultiByteString[0x00]];
    00504             case 0x00:
    00505                 ;
    00506             }
    00507
    00508             if ( LoopCount >= 0x20 ) {
    00509                 TmpCount = 0x20;
    00510                 LoopCount -= 0x20;
    00511                 UnicodeString -= 0x20;
    00512                 MultiByteString -= 0x20;
    00513
    00514                 goto  quick_copy;
    00515             }
    00516         /* end of copy... */
    00517     } else {
    00518         register USHORT Entry;
    00519         PWCH UnicodeStringAnchor = UnicodeString;
    00520         TranslateTable = (PUSHORT)NlsMbAnsiCodePageTables;
    00521
    00522         // yea, this line is duplicated, but the compiler can handle opt
    00523         // better buy moving it around
    00524         MaxCharsInUnicodeString = MaxBytesInUnicodeString / sizeof(WCHAR);
    00525
    00526         //
    00527         // The ACP is a multibyte code page.  Check each character
    00528         // to see if it is a lead byte before doing the translation.
    00529         //
    00530         while (MaxCharsInUnicodeString && BytesInMultiByteString) {
    00531             MaxCharsInUnicodeString--;
    00532             BytesInMultiByteString--;
    00533             if (NlsLeadByteInfo[*(PUCHAR)MultiByteString]) {
    00534                 //
    00535                 // Lead byte - Make sure there is a trail byte.  If not,
    00536                 // pass back a space rather than an error.  Some 3.x
    00537                 // applications pass incorrect strings and don't expect
    00538                 // to get an error.
    00539                 //
    00540                 if (BytesInMultiByteString == 0)
    00541                 {
    00542                     *UnicodeString++ = UnicodeNull;
    00543                     break;
    00544                 }
    00545
    00546                 //
    00547                 // Get the unicode character.
    00548                 //
    00549                 Entry = NlsLeadByteInfo[*(PUCHAR)MultiByteString++];
    00550                 *UnicodeString = (WCHAR)TranslateTable[ Entry + *(PUCHAR)MultiByteString++ ];
    00551                 UnicodeString++;
    00552
    00553                 //
    00554                 // Decrement count of bytes in multibyte string to account
    00555                 // for the double byte character.
    00556                 //
    00557                 BytesInMultiByteString--;
    00558             } else {
    00559                 //
    00560                 // Single byte character.
    00561                 //
    00562                 *UnicodeString++ = NlsAnsiToUnicodeData[*(PUCHAR)MultiByteString++];
    00563             }
    00564         }
    00565
    00566         if (ARGUMENT_PRESENT(BytesInUnicodeString))
    00567             *BytesInUnicodeString = (ULONG)((PCH)UnicodeString - (PCH)UnicodeStringAnchor);
    00568     }
    00569
    00570     return STATUS_SUCCESS;
    00571
    00572 }
    00573
    00574
    00575 NTSTATUS
    00576 RtlOemToUnicodeN(
    00577     OUT PWCH UnicodeString,
    00578     IN ULONG MaxBytesInUnicodeString,
    00579     OUT PULONG BytesInUnicodeString OPTIONAL,
    00580     IN PCH OemString,
    00581     IN ULONG BytesInOemString)
    00582
    00583 /*++
    00584
    00585 Routine Description:
    00586
    00587     This functions converts the specified oem source string into a
    00588     Unicode string. The translation is done with respect to the
    00589     OEM Code Page (OCP) installed at boot time.  Single byte characters
    00590     in the range 0x00 - 0x7f are simply zero extended as a performance
    00591     enhancement.  In some far eastern code pages 0x5c is defined as the
    00592     Yen sign.  For system translation we always want to consider 0x5c
    00593     to be the backslash character.  We get this for free by zero extending.
    00594
    00595     NOTE: This routine only supports precomposed Unicode characters.
    00596
    00597 Arguments:
    00598
    00599     UnicodeString - Returns a unicode string that is equivalent to
    00600         the oem source string.
    00601
    00602     MaxBytesInUnicodeString - Supplies the maximum number of bytes to be
    00603         written to UnicodeString.  If this causes UnicodeString to be a
    00604         truncated equivalent of OemString, no error condition results.
    00605
    00606     BytesInUnicodeString - Returns the number of bytes in the returned
    00607         unicode string pointed to by UnicodeString.
    00608
    00609     OemString - Supplies the oem source string that is to be
    00610         converted to unicode.
    00611
    00612     BytesInOemString - The number of bytes in the string pointed to
    00613         by OemString.
    00614
    00615 Return Value:
    00616
    00617     SUCCESS - The conversion was successful
    00618
    00619     STATUS_ILLEGAL_CHARACTER - The final Oem character was illegal
    00620
    00621     STATUS_BUFFER_OVERFLOW - MaxBytesInUnicodeString was not enough to hold
    00622         the whole Oem string.  It was converted correct to the point though.
    00623
    00624 --*/
    00625
    00626 {
    00627     ULONG LoopCount;
    00628     PUSHORT TranslateTable;
    00629     ULONG MaxCharsInUnicodeString;
    00630
    00631     RTL_PAGED_CODE();
    00632
    00633     if (!NlsMbOemCodePageTag) {
    00634         //
    00635         // The OCP is a single byte code page.
    00636         //
    00637         MaxCharsInUnicodeString = MaxBytesInUnicodeString / sizeof(WCHAR);
    00638
    00639         LoopCount = (MaxCharsInUnicodeString < BytesInOemString) ?
    00640                      MaxCharsInUnicodeString : BytesInOemString;
    00641
    00642         if (ARGUMENT_PRESENT(BytesInUnicodeString))
    00643             *BytesInUnicodeString = LoopCount * sizeof(WCHAR);
    00644
    00645
    00646         TranslateTable = NlsOemToUnicodeData;  // used to help the mips compiler
    00647
    00648         quick_copy:
    00649             switch( LoopCount ) {
    00650             default:
    00651                 UnicodeString[0x0F] = TranslateTable[(UCHAR)OemString[0x0F]];
    00652             case 0x0F:
    00653                 UnicodeString[0x0E] = TranslateTable[(UCHAR)OemString[0x0E]];
    00654             case 0x0E:
    00655                 UnicodeString[0x0D] = TranslateTable[(UCHAR)OemString[0x0D]];
    00656             case 0x0D:
    00657                 UnicodeString[0x0C] = TranslateTable[(UCHAR)OemString[0x0C]];
    00658             case 0x0C:
    00659                 UnicodeString[0x0B] = TranslateTable[(UCHAR)OemString[0x0B]];
    00660             case 0x0B:
    00661                 UnicodeString[0x0A] = TranslateTable[(UCHAR)OemString[0x0A]];
    00662             case 0x0A:
    00663                 UnicodeString[0x09] = TranslateTable[(UCHAR)OemString[0x09]];
    00664             case 0x09:
    00665                 UnicodeString[0x08] = TranslateTable[(UCHAR)OemString[0x08]];
    00666             case 0x08:
    00667                 UnicodeString[0x07] = TranslateTable[(UCHAR)OemString[0x07]];
    00668             case 0x07:
    00669                 UnicodeString[0x06] = TranslateTable[(UCHAR)OemString[0x06]];
    00670             case 0x06:
    00671                 UnicodeString[0x05] = TranslateTable[(UCHAR)OemString[0x05]];
    00672             case 0x05:
    00673                 UnicodeString[0x04] = TranslateTable[(UCHAR)OemString[0x04]];
    00674             case 0x04:
    00675                 UnicodeString[0x03] = TranslateTable[(UCHAR)OemString[0x03]];
    00676             case 0x03:
    00677                 UnicodeString[0x02] = TranslateTable[(UCHAR)OemString[0x02]];
    00678             case 0x02:
    00679                 UnicodeString[0x01] = TranslateTable[(UCHAR)OemString[0x01]];
    00680             case 0x01:
    00681                 UnicodeString[0x00] = TranslateTable[(UCHAR)OemString[0x00]];
    00682             case 0x00:
    00683                 ;
    00684             }
    00685
    00686             if ( LoopCount > 0x10 ) {
    00687                 LoopCount -= 0x10;
    00688                 OemString += 0x10;
    00689                 UnicodeString += 0x10;
    00690
    00691                 goto  quick_copy;
    00692             }
    00693         /* end of copy... */
    00694     } else {
    00695         register USHORT Entry;
    00696         PWCH UnicodeStringAnchor = UnicodeString;
    00697
    00698         //
    00699         // The OCP is a multibyte code page.  Check each character
    00700         // to see if it is a lead byte before doing the translation.
    00701         //
    00702         MaxCharsInUnicodeString = MaxBytesInUnicodeString / sizeof(WCHAR);
    00703         TranslateTable = (PUSHORT)NlsMbOemCodePageTables;
    00704
    00705         while (MaxCharsInUnicodeString && BytesInOemString) {
    00706             MaxCharsInUnicodeString--;
    00707             BytesInOemString--;
    00708             if (NlsOemLeadByteInfo[*(PUCHAR)OemString]) {
    00709                 //
    00710                 // Lead byte - Make sure there is a trail byte.  If not,
    00711                 // pass back a space rather than an error.  Some 3.x
    00712                 // applications pass incorrect strings and don't expect
    00713                 // to get an error.
    00714                 //
    00715                 if (BytesInOemString == 0)
    00716                 {
    00717                     *UnicodeString++ = UnicodeNull;
    00718                     break;
    00719                 }
    00720
    00721                 //
    00722                 // Get the unicode character.
    00723                 //
    00724                 Entry = NlsOemLeadByteInfo[*(PUCHAR)OemString++];
    00725                 *UnicodeString = TranslateTable[ Entry + *(PUCHAR)OemString++ ];
    00726                 UnicodeString++;
    00727
    00728                 //
    00729                 // Decrement count of bytes in oem string to account
    00730                 // for the double byte character.
    00731                 //
    00732                 BytesInOemString--;
    00733             } else {
    00734                 //
    00735                 // Single byte character.
    00736                 //
    00737                 *UnicodeString++ = NlsOemToUnicodeData[*(PUCHAR)OemString++];
    00738             }
    00739         }
    00740
    00741         if (ARGUMENT_PRESENT(BytesInUnicodeString))
    00742             *BytesInUnicodeString = (ULONG)((PCH)UnicodeString - (PCH)UnicodeStringAnchor);
    00743     }
    00744
    00745     //
    00746     //  Check if we were able to use all of the source Oem String
    00747     //
    00748     return (BytesInOemString <= MaxCharsInUnicodeString) ?
    00749            STATUS_SUCCESS :
    00750            STATUS_BUFFER_OVERFLOW;
    00751 }
    00752
    00753
    00754 NTSTATUS
    00755 RtlMultiByteToUnicodeSize(
    00756     OUT PULONG BytesInUnicodeString,
    00757     IN PCH MultiByteString,
    00758     IN ULONG BytesInMultiByteString)
    00759
    00760 /*++
    00761
    00762 Routine Description:
    00763
    00764     This functions determines how many bytes would be needed to represent
    00765     the specified ANSI source string in Unicode string (not counting the
    00766     null terminator)
    00767     The translation is done with respect to the ANSI Code Page (ACP) installed
    00768     at boot time.  Single byte characters in the range 0x00 - 0x7f are simply
    00769     zero extended as a performance enhancement.  In some far eastern code pages
    00770     0x5c is defined as the Yen sign.  For system translation we always want to
    00771     consider 0x5c to be the backslash character.  We get this for free by zero
    00772     extending.
    00773
    00774     NOTE: This routine only supports precomposed Unicode characters.
    00775
    00776 Arguments:
    00777
    00778     BytesInUnicodeString - Returns the number of bytes a Unicode translation
    00779         of the ANSI string pointed to by MultiByteString would contain.
    00780
    00781     MultiByteString - Supplies the ansi source string whose Unicode length
    00782         is to be calculated.
    00783
    00784     BytesInMultiByteString - The number of bytes in the string pointed to
    00785         by MultiByteString.
    00786
    00787 Return Value:
    00788
    00789     SUCCESS - The conversion was successful
    00790
    00791
    00792 --*/
    00793
    00794 {
    00795     ULONG cbUnicode = 0;
    00796
    00797     RTL_PAGED_CODE();
    00798
    00799     if (NlsMbCodePageTag) {
    00800         //
    00801         // The ACP is a multibyte code page.  Check each character
    00802         // to see if it is a lead byte before doing the translation.
    00803         //
    00804         while (BytesInMultiByteString--) {
    00805             if (NlsLeadByteInfo[*(PUCHAR)MultiByteString++]) {
    00806                 //
    00807                 // Lead byte - translate the trail byte using the table
    00808                 // that corresponds to this lead byte.  NOTE: make sure
    00809                 // we have a trail byte to convert.
    00810                 //
    00811                 if (BytesInMultiByteString == 0) {
    00812                     //
    00813                     // RtlMultibyteToUnicodeN() uses the unicode
    00814                     // default character if the last multibyte
    00815                     // character is a lead byte.
    00816                     //
    00817                     cbUnicode += sizeof(WCHAR);
    00818                     break;
    00819                 } else {
    00820                     BytesInMultiByteString--;
    00821                     MultiByteString++;
    00822                 }
    00823             }
    00824             cbUnicode += sizeof(WCHAR);
    00825         }
    00826         *BytesInUnicodeString = cbUnicode;
    00827     } else {
    00828         //
    00829         // The ACP is a single byte code page.
    00830         //
    00831         *BytesInUnicodeString = BytesInMultiByteString * sizeof(WCHAR);
    00832     }
    00833
    00834     return STATUS_SUCCESS;
    00835 }
    00836
    00837
    00838 NTSTATUS
    00839 RtlUnicodeToMultiByteSize(
    00840     OUT PULONG BytesInMultiByteString,
    00841     IN PWCH UnicodeString,
    00842     IN ULONG BytesInUnicodeString)
    00843
    00844 /*++
    00845
    00846 Routine Description:
    00847
    00848     This functions determines how many bytes would be needed to represent
    00849     the specified Unicode source string as an ANSI string (not counting the
    00850     null terminator)
    00851
    00852 Arguments:
    00853
    00854     BytesInMultiByteString - Returns the number of bytes an ANSI translation
    00855         of the Unicode string pointed to by UnicodeString would contain.
    00856
    00857     UnicodeString - Supplies the unicode source string whose ANSI length
    00858         is to be calculated.
    00859
    00860     BytesInUnicodeString - The number of bytes in the the string pointed to by
    00861         UnicodeString.
    00862
    00863 Return Value:
    00864
    00865     SUCCESS - The conversion was successful
    00866
    00867     !SUCCESS - The conversion failed.  A unicode character was encountered
    00868         that has no translation for the current ANSI Code Page (ACP).
    00869
    00870 --*/
    00871
    00872 {
    00873     ULONG cbMultiByte = 0;
    00874     ULONG CharsInUnicodeString;
    00875
    00876     RTL_PAGED_CODE();
    00877
    00878     /*
    00879      * convert from bytes to chars for easier loop handling.
    00880      */
    00881     CharsInUnicodeString = BytesInUnicodeString / sizeof(WCHAR);
    00882
    00883     if (NlsMbCodePageTag) {
    00884         USHORT MbChar;
    00885
    00886         while (CharsInUnicodeString--) {
    00887             MbChar = NlsUnicodeToMbAnsiData[ *UnicodeString++ ];
    00888             if (HIBYTE(MbChar) == 0) {
    00889                 cbMultiByte++ ;
    00890             } else {
    00891                 cbMultiByte += 2;
    00892             }
    00893         }
    00894         *BytesInMultiByteString = cbMultiByte;
    00895     }
    00896     else {
    00897         *BytesInMultiByteString = CharsInUnicodeString;
    00898     }
    00899
    00900     return STATUS_SUCCESS;
    00901 }
    00902
    00903
    00904 NTSTATUS
    00905 RtlUnicodeToMultiByteN(
    00906     OUT PCH MultiByteString,
    00907     IN ULONG MaxBytesInMultiByteString,
    00908     OUT PULONG BytesInMultiByteString OPTIONAL,
    00909     IN PWCH UnicodeString,
    00910     IN ULONG BytesInUnicodeString)
    00911
    00912 /*++
    00913
    00914 Routine Description:
    00915
    00916     This functions converts the specified unicode source string into an
    00917     ansi string. The translation is done with respect to the
    00918     ANSI Code Page (ACP) loaded at boot time.
    00919
    00920 Arguments:
    00921
    00922     MultiByteString - Returns an ansi string that is equivalent to the
    00923         unicode source string.  If the translation can not be done,
    00924         an error is returned.
    00925
    00926     MaxBytesInMultiByteString - Supplies the maximum number of bytes to be
    00927         written to MultiByteString.  If this causes MultiByteString to be a
    00928         truncated equivalent of UnicodeString, no error condition results.
    00929
    00930     BytesInMultiByteString - Returns the number of bytes in the returned
    00931         ansi string pointed to by MultiByteString.
    00932
    00933     UnicodeString - Supplies the unicode source string that is to be
    00934         converted to ansi.
    00935
    00936     BytesInUnicodeString - The number of bytes in the the string pointed to by
    00937         UnicodeString.
    00938
    00939 Return Value:
    00940
    00941     SUCCESS - The conversion was successful
    00942
    00943 --*/
    00944
    00945 {
    00946     ULONG TmpCount;
    00947     ULONG LoopCount;
    00948     PCH TranslateTable;
    00949     ULONG CharsInUnicodeString;
    00950
    00951     RTL_PAGED_CODE();
    00952
    00953     //
    00954     // Convert Unicode byte count to character count. Byte count of
    00955     // multibyte string is equivalent to character count.
    00956     //
    00957     if (!NlsMbCodePageTag) {
    00958         CharsInUnicodeString = BytesInUnicodeString / sizeof(WCHAR);
    00959
    00960         LoopCount = (CharsInUnicodeString < MaxBytesInMultiByteString) ?
    00961                      CharsInUnicodeString : MaxBytesInMultiByteString;
    00962
    00963         if (ARGUMENT_PRESENT(BytesInMultiByteString))
    00964             *BytesInMultiByteString = LoopCount;
    00965
    00966         TranslateTable = NlsUnicodeToAnsiData;  // used to help the mips compiler
    00967
    00968         TmpCount = LoopCount & 0x0F;
    00969         UnicodeString += TmpCount;
    00970         MultiByteString += TmpCount;
    00971
    00972         do
    00973         {
    00974             switch( TmpCount ) {
    00975             default:
    00976                 UnicodeString += 0x10;
    00977                 MultiByteString += 0x10;
    00978
    00979                 MultiByteString[-0x10] = TranslateTable[UnicodeString[-0x10]];
    00980             case 0x0F:
    00981                 MultiByteString[-0x0F] = TranslateTable[UnicodeString[-0x0F]];
    00982             case 0x0E:
    00983                 MultiByteString[-0x0E] = TranslateTable[UnicodeString[-0x0E]];
    00984             case 0x0D:
    00985                 MultiByteString[-0x0D] = TranslateTable[UnicodeString[-0x0D]];
    00986             case 0x0C:
    00987                 MultiByteString[-0x0C] = TranslateTable[UnicodeString[-0x0C]];
    00988             case 0x0B:
    00989                 MultiByteString[-0x0B] = TranslateTable[UnicodeString[-0x0B]];
    00990             case 0x0A:
    00991                 MultiByteString[-0x0A] = TranslateTable[UnicodeString[-0x0A]];
    00992             case 0x09:
    00993                 MultiByteString[-0x09] = TranslateTable[UnicodeString[-0x09]];
    00994             case 0x08:
    00995                 MultiByteString[-0x08] = TranslateTable[UnicodeString[-0x08]];
    00996             case 0x07:
    00997                 MultiByteString[-0x07] = TranslateTable[UnicodeString[-0x07]];
    00998             case 0x06:
    00999                 MultiByteString[-0x06] = TranslateTable[UnicodeString[-0x06]];
    01000             case 0x05:
    01001                 MultiByteString[-0x05] = TranslateTable[UnicodeString[-0x05]];
    01002             case 0x04:
    01003                 MultiByteString[-0x04] = TranslateTable[UnicodeString[-0x04]];
    01004             case 0x03:
    01005                 MultiByteString[-0x03] = TranslateTable[UnicodeString[-0x03]];
    01006             case 0x02:
    01007                 MultiByteString[-0x02] = TranslateTable[UnicodeString[-0x02]];
    01008             case 0x01:
    01009                 MultiByteString[-0x01] = TranslateTable[UnicodeString[-0x01]];
    01010             case 0x00:
    01011                 ;
    01012             }
    01013
    01014             LoopCount -= TmpCount;
    01015             TmpCount = 0x10;
    01016         } while ( LoopCount > 0 );
    01017
    01018         /* end of copy... */
    01019     } else {
    01020         USHORT MbChar;
    01021         PCH MultiByteStringAnchor = MultiByteString;
    01022
    01023         CharsInUnicodeString = BytesInUnicodeString / sizeof(WCHAR);
    01024
    01025         while ( CharsInUnicodeString && MaxBytesInMultiByteString ) {
    01026
    01027             MbChar = NlsUnicodeToMbAnsiData[ *UnicodeString++ ];
    01028             if (HIBYTE(MbChar) != 0) {
    01029                 //
    01030                 // Need at least 2 bytes to copy a double byte char.
    01031                 // Don't want to truncate in the middle of a DBCS char.
    01032                 //
    01033                 if (MaxBytesInMultiByteString-- < 2) {
    01034                     break;
    01035                 }
    01036                 *MultiByteString++ = HIBYTE(MbChar);  // lead byte
    01037             }
    01038             *MultiByteString++ = LOBYTE(MbChar);
    01039             MaxBytesInMultiByteString--;
    01040
    01041             CharsInUnicodeString--;
    01042         }
    01043
    01044         if (ARGUMENT_PRESENT(BytesInMultiByteString))
    01045             *BytesInMultiByteString = (ULONG)(MultiByteString - MultiByteStringAnchor);
    01046     }
    01047
    01048     return STATUS_SUCCESS;
    01049 }
    01050
    01051
    01052 NTSTATUS
    01053 RtlUpcaseUnicodeToMultiByteN(
    01054     OUT PCH MultiByteString,
    01055     IN ULONG MaxBytesInMultiByteString,
    01056     OUT PULONG BytesInMultiByteString OPTIONAL,
    01057     IN PWCH UnicodeString,
    01058     IN ULONG BytesInUnicodeString)
    01059
    01060 /*++
    01061
    01062 Routine Description:
    01063
    01064     This functions upper cases the specified unicode source string and
    01065     converts it into an ansi string. The translation is done with respect
    01066     to the ANSI Code Page (ACP) loaded at boot time.
    01067
    01068 Arguments:
    01069
    01070     MultiByteString - Returns an ansi string that is equivalent to the
    01071         upper case of the unicode source string.  If the translation can
    01072         not be done, an error is returned.
    01073
    01074     MaxBytesInMultiByteString - Supplies the maximum number of bytes to be
    01075         written to MultiByteString.  If this causes MultiByteString to be a
    01076         truncated equivalent of UnicodeString, no error condition results.
    01077
    01078     BytesInMultiByteString - Returns the number of bytes in the returned
    01079         ansi string pointed to by MultiByteString.
    01080
    01081     UnicodeString - Supplies the unicode source string that is to be
    01082         converted to ansi.
    01083
    01084     BytesInUnicodeString - The number of bytes in the the string pointed to by
    01085         UnicodeString.
    01086
    01087 Return Value:
    01088
    01089     SUCCESS - The conversion was successful
    01090
    01091 --*/
    01092
    01093 {
    01094     ULONG TmpCount;
    01095     ULONG LoopCount;
    01096     PCH TranslateTable;
    01097     ULONG CharsInUnicodeString;
    01098     UCHAR SbChar;
    01099     WCHAR UnicodeChar;
    01100
    01101     RTL_PAGED_CODE();
    01102
    01103     //
    01104     // Convert Unicode byte count to character count. Byte count of
    01105     // multibyte string is equivalent to character count.
    01106     //
    01107     if (!NlsMbCodePageTag) {
    01108         CharsInUnicodeString = BytesInUnicodeString / sizeof(WCHAR);
    01109
    01110         LoopCount = (CharsInUnicodeString < MaxBytesInMultiByteString) ?
    01111                      CharsInUnicodeString : MaxBytesInMultiByteString;
    01112
    01113         if (ARGUMENT_PRESENT(BytesInMultiByteString))
    01114             *BytesInMultiByteString = LoopCount;
    01115
    01116         TranslateTable = NlsUnicodeToAnsiData;  // used to help the mips compiler
    01117
    01118         TmpCount = LoopCount & 0x0F;
    01119         UnicodeString += TmpCount;
    01120         MultiByteString += TmpCount;
    01121
    01122         do
    01123         {
    01124             //
    01125             // Convert to ANSI and back to Unicode before upper casing
    01126             // to ensure the visual best fits are converted and
    01127             // upper cased properly.
    01128             //
    01129             switch( TmpCount ) {
    01130             default:
    01131                 UnicodeString += 0x10;
    01132                 MultiByteString += 0x10;
    01133
    01134                 SbChar = TranslateTable[UnicodeString[-0x10]];
    01135                 UnicodeChar = NlsAnsiToUnicodeData[SbChar];
    01136                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01137                 MultiByteString[-0x10] = TranslateTable[UnicodeChar];
    01138             case 0x0F:
    01139                 SbChar = TranslateTable[UnicodeString[-0x0F]];
    01140                 UnicodeChar = NlsAnsiToUnicodeData[SbChar];
    01141                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01142                 MultiByteString[-0x0F] = TranslateTable[UnicodeChar];
    01143             case 0x0E:
    01144                 SbChar = TranslateTable[UnicodeString[-0x0E]];
    01145                 UnicodeChar = NlsAnsiToUnicodeData[SbChar];
    01146                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01147                 MultiByteString[-0x0E] = TranslateTable[UnicodeChar];
    01148             case 0x0D:
    01149                 SbChar = TranslateTable[UnicodeString[-0x0D]];
    01150                 UnicodeChar = NlsAnsiToUnicodeData[SbChar];
    01151                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01152                 MultiByteString[-0x0D] = TranslateTable[UnicodeChar];
    01153             case 0x0C:
    01154                 SbChar = TranslateTable[UnicodeString[-0x0C]];
    01155                 UnicodeChar = NlsAnsiToUnicodeData[SbChar];
    01156                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01157                 MultiByteString[-0x0C] = TranslateTable[UnicodeChar];
    01158             case 0x0B:
    01159                 SbChar = TranslateTable[UnicodeString[-0x0B]];
    01160                 UnicodeChar = NlsAnsiToUnicodeData[SbChar];
    01161                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01162                 MultiByteString[-0x0B] = TranslateTable[UnicodeChar];
    01163             case 0x0A:
    01164                 SbChar = TranslateTable[UnicodeString[-0x0A]];
    01165                 UnicodeChar = NlsAnsiToUnicodeData[SbChar];
    01166                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01167                 MultiByteString[-0x0A] = TranslateTable[UnicodeChar];
    01168             case 0x09:
    01169                 SbChar = TranslateTable[UnicodeString[-0x09]];
    01170                 UnicodeChar = NlsAnsiToUnicodeData[SbChar];
    01171                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01172                 MultiByteString[-0x09] = TranslateTable[UnicodeChar];
    01173             case 0x08:
    01174                 SbChar = TranslateTable[UnicodeString[-0x08]];
    01175                 UnicodeChar = NlsAnsiToUnicodeData[SbChar];
    01176                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01177                 MultiByteString[-0x08] = TranslateTable[UnicodeChar];
    01178             case 0x07:
    01179                 SbChar = TranslateTable[UnicodeString[-0x07]];
    01180                 UnicodeChar = NlsAnsiToUnicodeData[SbChar];
    01181                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01182                 MultiByteString[-0x07] = TranslateTable[UnicodeChar];
    01183             case 0x06:
    01184                 SbChar = TranslateTable[UnicodeString[-0x06]];
    01185                 UnicodeChar = NlsAnsiToUnicodeData[SbChar];
    01186                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01187                 MultiByteString[-0x06] = TranslateTable[UnicodeChar];
    01188             case 0x05:
    01189                 SbChar = TranslateTable[UnicodeString[-0x05]];
    01190                 UnicodeChar = NlsAnsiToUnicodeData[SbChar];
    01191                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01192                 MultiByteString[-0x05] = TranslateTable[UnicodeChar];
    01193             case 0x04:
    01194                 SbChar = TranslateTable[UnicodeString[-0x04]];
    01195                 UnicodeChar = NlsAnsiToUnicodeData[SbChar];
    01196                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01197                 MultiByteString[-0x04] = TranslateTable[UnicodeChar];
    01198             case 0x03:
    01199                 SbChar = TranslateTable[UnicodeString[-0x03]];
    01200                 UnicodeChar = NlsAnsiToUnicodeData[SbChar];
    01201                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01202                 MultiByteString[-0x03] = TranslateTable[UnicodeChar];
    01203             case 0x02:
    01204                 SbChar = TranslateTable[UnicodeString[-0x02]];
    01205                 UnicodeChar = NlsAnsiToUnicodeData[SbChar];
    01206                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01207                 MultiByteString[-0x02] = TranslateTable[UnicodeChar];
    01208             case 0x01:
    01209                 SbChar = TranslateTable[UnicodeString[-0x01]];
    01210                 UnicodeChar = NlsAnsiToUnicodeData[SbChar];
    01211                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01212                 MultiByteString[-0x01] = TranslateTable[UnicodeChar];
    01213             case 0x00:
    01214                 ;
    01215             }
    01216
    01217             LoopCount -= TmpCount;
    01218             TmpCount = 0x10;
    01219         } while ( LoopCount > 0 );
    01220
    01221         /* end of copy... */
    01222     } else {
    01223         USHORT MbChar;
    01224         register USHORT Entry;
    01225         PCH MultiByteStringAnchor = MultiByteString;
    01226
    01227         CharsInUnicodeString = BytesInUnicodeString / sizeof(WCHAR);
    01228
    01229         while ( CharsInUnicodeString && MaxBytesInMultiByteString ) {
    01230             //
    01231             // Convert to ANSI and back to Unicode before upper casing
    01232             // to ensure the visual best fits are converted and
    01233             // upper cased properly.
    01234             //
    01235             MbChar = NlsUnicodeToMbAnsiData[ *UnicodeString++ ];
    01236             if ( NlsLeadByteInfo[HIBYTE(MbChar)] ) {
    01237                 //
    01238                 // Lead byte - translate the trail byte using the table
    01239                 // that corresponds to this lead byte.
    01240                 //
    01241                 Entry = NlsLeadByteInfo[HIBYTE(MbChar)];
    01242                 UnicodeChar = (WCHAR)NlsMbAnsiCodePageTables[ Entry + LOBYTE(MbChar) ];
    01243             } else {
    01244                 //
    01245                 // Single byte character.
    01246                 //
    01247                 UnicodeChar = NlsAnsiToUnicodeData[LOBYTE(MbChar)];
    01248             }
    01249             UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01250             MbChar = NlsUnicodeToMbAnsiData[UnicodeChar];
    01251
    01252             if (HIBYTE(MbChar) != 0) {
    01253                 //
    01254                 // Need at least 2 bytes to copy a double byte char.
    01255                 // Don't want to truncate in the middle of a DBCS char.
    01256                 //
    01257                 if (MaxBytesInMultiByteString-- < 2) {
    01258                     break;
    01259                 }
    01260                 *MultiByteString++ = HIBYTE(MbChar);  // lead byte
    01261             }
    01262             *MultiByteString++ = LOBYTE(MbChar);
    01263             MaxBytesInMultiByteString--;
    01264
    01265             CharsInUnicodeString--;
    01266         }
    01267
    01268         if (ARGUMENT_PRESENT(BytesInMultiByteString))
    01269             *BytesInMultiByteString = (ULONG)(MultiByteString - MultiByteStringAnchor);
    01270     }
    01271
    01272     return STATUS_SUCCESS;
    01273 }
    01274
    01275
    01276 NTSTATUS
    01277 RtlUnicodeToOemN(
    01278     OUT PCH OemString,
    01279     IN ULONG MaxBytesInOemString,
    01280     OUT PULONG BytesInOemString OPTIONAL,
    01281     IN PWCH UnicodeString,
    01282     IN ULONG BytesInUnicodeString)
    01283
    01284 /*++
    01285
    01286 Routine Description:
    01287
    01288     This functions converts the specified unicode source string into an
    01289     oem string. The translation is done with respect to the OEM Code
    01290     Page (OCP) loaded at boot time.
    01291
    01292 Arguments:
    01293
    01294     OemString - Returns an oem string that is equivalent to the
    01295         unicode source string.  If the translation can not be done,
    01296         an error is returned.
    01297
    01298     MaxBytesInOemString - Supplies the maximum number of bytes to be
    01299         written to OemString.  If this causes OemString to be a
    01300         truncated equivalent of UnicodeString, no error condition results.
    01301
    01302     BytesInOemString - Returns the number of bytes in the returned
    01303         oem string pointed to by OemString.
    01304
    01305     UnicodeString - Supplies the unicode source string that is to be
    01306         converted to oem.
    01307
    01308     BytesInUnicodeString - The number of bytes in the the string pointed to by
    01309         UnicodeString.
    01310
    01311 Return Value:
    01312
    01313     SUCCESS - The conversion was successful
    01314
    01315     STATUS_BUFFER_OVERFLOW - MaxBytesInUnicodeString was not enough to hold
    01316         the whole Oem string.  It was converted correct to the point though.
    01317
    01318 --*/
    01319
    01320 {
    01321     ULONG TmpCount;
    01322     ULONG LoopCount;
    01323     PCH TranslateTable;
    01324     ULONG CharsInUnicodeString;
    01325
    01326     RTL_PAGED_CODE();
    01327
    01328     //
    01329     // Convert Unicode byte count to character count. Byte count of
    01330     // multibyte string is equivalent to character count.
    01331     //
    01332     if (!NlsMbOemCodePageTag) {
    01333         CharsInUnicodeString = BytesInUnicodeString / sizeof(WCHAR);
    01334
    01335         LoopCount = (CharsInUnicodeString < MaxBytesInOemString) ?
    01336                      CharsInUnicodeString : MaxBytesInOemString;
    01337
    01338         if (ARGUMENT_PRESENT(BytesInOemString))
    01339             *BytesInOemString = LoopCount;
    01340
    01341         TranslateTable = NlsUnicodeToOemData;  // used to help the mips compiler
    01342
    01343         TmpCount = LoopCount & 0x0F;
    01344         UnicodeString += TmpCount;
    01345         OemString += TmpCount;
    01346
    01347         do
    01348         {
    01349             switch( TmpCount ) {
    01350             default:
    01351                 UnicodeString += 0x10;
    01352                 OemString += 0x10;
    01353
    01354                 OemString[-0x10] = TranslateTable[UnicodeString[-0x10]];
    01355             case 0x0F:
    01356                 OemString[-0x0F] = TranslateTable[UnicodeString[-0x0F]];
    01357             case 0x0E:
    01358                 OemString[-0x0E] = TranslateTable[UnicodeString[-0x0E]];
    01359             case 0x0D:
    01360                 OemString[-0x0D] = TranslateTable[UnicodeString[-0x0D]];
    01361             case 0x0C:
    01362                 OemString[-0x0C] = TranslateTable[UnicodeString[-0x0C]];
    01363             case 0x0B:
    01364                 OemString[-0x0B] = TranslateTable[UnicodeString[-0x0B]];
    01365             case 0x0A:
    01366                 OemString[-0x0A] = TranslateTable[UnicodeString[-0x0A]];
    01367             case 0x09:
    01368                 OemString[-0x09] = TranslateTable[UnicodeString[-0x09]];
    01369             case 0x08:
    01370                 OemString[-0x08] = TranslateTable[UnicodeString[-0x08]];
    01371             case 0x07:
    01372                 OemString[-0x07] = TranslateTable[UnicodeString[-0x07]];
    01373             case 0x06:
    01374                 OemString[-0x06] = TranslateTable[UnicodeString[-0x06]];
    01375             case 0x05:
    01376                 OemString[-0x05] = TranslateTable[UnicodeString[-0x05]];
    01377             case 0x04:
    01378                 OemString[-0x04] = TranslateTable[UnicodeString[-0x04]];
    01379             case 0x03:
    01380                 OemString[-0x03] = TranslateTable[UnicodeString[-0x03]];
    01381             case 0x02:
    01382                 OemString[-0x02] = TranslateTable[UnicodeString[-0x02]];
    01383             case 0x01:
    01384                 OemString[-0x01] = TranslateTable[UnicodeString[-0x01]];
    01385             case 0x00:
    01386                 ;
    01387             }
    01388
    01389             LoopCount -= TmpCount;
    01390             TmpCount = 0x10;
    01391         } while ( LoopCount > 0 );
    01392
    01393         /* end of copy... */
    01394     } else {
    01395         register USHORT MbChar;
    01396         PCH OemStringAnchor = OemString;
    01397
    01398         CharsInUnicodeString = BytesInUnicodeString / sizeof(WCHAR);
    01399
    01400         while ( CharsInUnicodeString && MaxBytesInOemString ) {
    01401
    01402             MbChar = NlsUnicodeToMbOemData[ *UnicodeString++ ];
    01403             if (HIBYTE(MbChar) != 0) {
    01404                 //
    01405                 // Need at least 2 bytes to copy a double byte char.
    01406                 // Don't want to truncate in the middle of a DBCS char.
    01407                 //
    01408                 if (MaxBytesInOemString-- < 2) {
    01409                     break;
    01410                 }
    01411                 *OemString++ = HIBYTE(MbChar);  // lead byte
    01412             }
    01413             *OemString++ = LOBYTE(MbChar);
    01414             MaxBytesInOemString--;
    01415
    01416             CharsInUnicodeString--;
    01417         }
    01418
    01419         if (ARGUMENT_PRESENT(BytesInOemString))
    01420             *BytesInOemString = (ULONG)(OemString - OemStringAnchor);
    01421     }
    01422
    01423     //
    01424     //  Check if we were able to use all of the source Unicode String
    01425     //
    01426     return ( CharsInUnicodeString <= MaxBytesInOemString ) ?
    01427            STATUS_SUCCESS :
    01428            STATUS_BUFFER_OVERFLOW;
    01429 }
    01430
    01431
    01432 NTSTATUS
    01433 RtlUpcaseUnicodeToOemN(
    01434     OUT PCH OemString,
    01435     IN ULONG MaxBytesInOemString,
    01436     OUT PULONG BytesInOemString OPTIONAL,
    01437     IN PWCH UnicodeString,
    01438     IN ULONG BytesInUnicodeString)
    01439
    01440 /*++
    01441
    01442 Routine Description:
    01443
    01444     This functions upper cases the specified unicode source string and
    01445     converts it into an oem string. The translation is done with respect
    01446     to the OEM Code Page (OCP) loaded at boot time.
    01447
    01448 Arguments:
    01449
    01450     OemString - Returns an oem string that is equivalent to the upper
    01451         case of the unicode source string.  If the translation can not
    01452         be done, an error is returned.
    01453
    01454     MaxBytesInOemString - Supplies the maximum number of bytes to be
    01455         written to OemString.  If this causes OemString to be a
    01456         truncated equivalent of UnicodeString, no error condition results.
    01457
    01458     BytesInOemString - Returns the number of bytes in the returned
    01459         oem string pointed to by OemString.
    01460
    01461     UnicodeString - Supplies the unicode source string that is to be
    01462         converted to oem.
    01463
    01464     BytesInUnicodeString - The number of bytes in the the string pointed
    01465         to by UnicodeString.
    01466
    01467 Return Value:
    01468
    01469     SUCCESS - The conversion was successful
    01470
    01471     STATUS_BUFFER_OVERFLOW - MaxBytesInUnicodeString was not enough to
    01472         hold the whole Oem string.  It was converted correctly to that
    01473         point, though.
    01474
    01475 --*/
    01476
    01477 {
    01478     ULONG TmpCount;
    01479     ULONG LoopCount;
    01480     PCH TranslateTable;
    01481     ULONG CharsInUnicodeString;
    01482     UCHAR SbChar;
    01483     WCHAR UnicodeChar;
    01484
    01485     RTL_PAGED_CODE();
    01486
    01487     //
    01488     // Convert Unicode byte count to character count. Byte count of
    01489     // multibyte string is equivalent to character count.
    01490     //
    01491     if (!NlsMbOemCodePageTag) {
    01492         CharsInUnicodeString = BytesInUnicodeString / sizeof(WCHAR);
    01493
    01494         LoopCount = (CharsInUnicodeString < MaxBytesInOemString) ?
    01495                      CharsInUnicodeString : MaxBytesInOemString;
    01496
    01497         if (ARGUMENT_PRESENT(BytesInOemString))
    01498             *BytesInOemString = LoopCount;
    01499
    01500         TranslateTable = NlsUnicodeToOemData;  // used to help the mips compiler
    01501
    01502         TmpCount = LoopCount & 0x0F;
    01503         UnicodeString += TmpCount;
    01504         OemString += TmpCount;
    01505
    01506         do
    01507         {
    01508             //
    01509             // Convert to OEM and back to Unicode before upper casing
    01510             // to ensure the visual best fits are converted and
    01511             // upper cased properly.
    01512             //
    01513             switch( TmpCount ) {
    01514             default:
    01515                 UnicodeString += 0x10;
    01516                 OemString += 0x10;
    01517
    01518                 SbChar = TranslateTable[UnicodeString[-0x10]];
    01519                 UnicodeChar = NlsOemToUnicodeData[SbChar];
    01520                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01521                 OemString[-0x10] = TranslateTable[UnicodeChar];
    01522             case 0x0F:
    01523                 SbChar = TranslateTable[UnicodeString[-0x0F]];
    01524                 UnicodeChar = NlsOemToUnicodeData[SbChar];
    01525                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01526                 OemString[-0x0F] = TranslateTable[UnicodeChar];
    01527             case 0x0E:
    01528                 SbChar = TranslateTable[UnicodeString[-0x0E]];
    01529                 UnicodeChar = NlsOemToUnicodeData[SbChar];
    01530                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01531                 OemString[-0x0E] = TranslateTable[UnicodeChar];
    01532             case 0x0D:
    01533                 SbChar = TranslateTable[UnicodeString[-0x0D]];
    01534                 UnicodeChar = NlsOemToUnicodeData[SbChar];
    01535                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01536                 OemString[-0x0D] = TranslateTable[UnicodeChar];
    01537             case 0x0C:
    01538                 SbChar = TranslateTable[UnicodeString[-0x0C]];
    01539                 UnicodeChar = NlsOemToUnicodeData[SbChar];
    01540                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01541                 OemString[-0x0C] = TranslateTable[UnicodeChar];
    01542             case 0x0B:
    01543                 SbChar = TranslateTable[UnicodeString[-0x0B]];
    01544                 UnicodeChar = NlsOemToUnicodeData[SbChar];
    01545                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01546                 OemString[-0x0B] = TranslateTable[UnicodeChar];
    01547             case 0x0A:
    01548                 SbChar = TranslateTable[UnicodeString[-0x0A]];
    01549                 UnicodeChar = NlsOemToUnicodeData[SbChar];
    01550                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01551                 OemString[-0x0A] = TranslateTable[UnicodeChar];
    01552             case 0x09:
    01553                 SbChar = TranslateTable[UnicodeString[-0x09]];
    01554                 UnicodeChar = NlsOemToUnicodeData[SbChar];
    01555                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01556                 OemString[-0x09] = TranslateTable[UnicodeChar];
    01557             case 0x08:
    01558                 SbChar = TranslateTable[UnicodeString[-0x08]];
    01559                 UnicodeChar = NlsOemToUnicodeData[SbChar];
    01560                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01561                 OemString[-0x08] = TranslateTable[UnicodeChar];
    01562             case 0x07:
    01563                 SbChar = TranslateTable[UnicodeString[-0x07]];
    01564                 UnicodeChar = NlsOemToUnicodeData[SbChar];
    01565                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01566                 OemString[-0x07] = TranslateTable[UnicodeChar];
    01567             case 0x06:
    01568                 SbChar = TranslateTable[UnicodeString[-0x06]];
    01569                 UnicodeChar = NlsOemToUnicodeData[SbChar];
    01570                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01571                 OemString[-0x06] = TranslateTable[UnicodeChar];
    01572             case 0x05:
    01573                 SbChar = TranslateTable[UnicodeString[-0x05]];
    01574                 UnicodeChar = NlsOemToUnicodeData[SbChar];
    01575                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01576                 OemString[-0x05] = TranslateTable[UnicodeChar];
    01577             case 0x04:
    01578                 SbChar = TranslateTable[UnicodeString[-0x04]];
    01579                 UnicodeChar = NlsOemToUnicodeData[SbChar];
    01580                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01581                 OemString[-0x04] = TranslateTable[UnicodeChar];
    01582             case 0x03:
    01583                 SbChar = TranslateTable[UnicodeString[-0x03]];
    01584                 UnicodeChar = NlsOemToUnicodeData[SbChar];
    01585                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01586                 OemString[-0x03] = TranslateTable[UnicodeChar];
    01587             case 0x02:
    01588                 SbChar = TranslateTable[UnicodeString[-0x02]];
    01589                 UnicodeChar = NlsOemToUnicodeData[SbChar];
    01590                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01591                 OemString[-0x02] = TranslateTable[UnicodeChar];
    01592             case 0x01:
    01593                 SbChar = TranslateTable[UnicodeString[-0x01]];
    01594                 UnicodeChar = NlsOemToUnicodeData[SbChar];
    01595                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01596                 OemString[-0x01] = TranslateTable[UnicodeChar];
    01597             case 0x00:
    01598                 ;
    01599             }
    01600
    01601             LoopCount -= TmpCount;
    01602             TmpCount = 0x10;
    01603         } while ( LoopCount > 0 );
    01604
    01605         /* end of copy... */
    01606     } else {
    01607         USHORT MbChar;
    01608         register USHORT Entry;
    01609         PCH OemStringAnchor = OemString;
    01610
    01611         CharsInUnicodeString = BytesInUnicodeString / sizeof(WCHAR);
    01612
    01613         while ( CharsInUnicodeString && MaxBytesInOemString ) {
    01614             //
    01615             // Convert to OEM and back to Unicode before upper casing
    01616             // to ensure the visual best fits are converted and
    01617             // upper cased properly.
    01618             //
    01619             MbChar = NlsUnicodeToMbOemData[ *UnicodeString++ ];
    01620             if (NlsOemLeadByteInfo[HIBYTE(MbChar)]) {
    01621                 //
    01622                 // Lead byte - translate the trail byte using the table
    01623                 // that corresponds to this lead byte.
    01624                 //
    01625                 Entry = NlsOemLeadByteInfo[HIBYTE(MbChar)];
    01626                 UnicodeChar = (WCHAR)NlsMbOemCodePageTables[ Entry + LOBYTE(MbChar) ];
    01627             } else {
    01628                 //
    01629                 // Single byte character.
    01630                 //
    01631                 UnicodeChar = NlsOemToUnicodeData[LOBYTE(MbChar)];
    01632             }
    01633             UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    01634             MbChar = NlsUnicodeToMbOemData[UnicodeChar];
    01635
    01636             if (HIBYTE(MbChar) != 0) {
    01637                 //
    01638                 // Need at least 2 bytes to copy a double byte char.
    01639                 // Don't want to truncate in the middle of a DBCS char.
    01640                 //
    01641                 if (MaxBytesInOemString-- < 2) {
    01642                     break;
    01643                 }
    01644                 *OemString++ = HIBYTE(MbChar);  // lead byte
    01645             }
    01646             *OemString++ = LOBYTE(MbChar);
    01647             MaxBytesInOemString--;
    01648
    01649             CharsInUnicodeString--;
    01650         }
    01651
    01652         if (ARGUMENT_PRESENT(BytesInOemString))
    01653             *BytesInOemString = (ULONG)(OemString - OemStringAnchor);
    01654     }
    01655
    01656     //
    01657     //  Check if we were able to use all of the source Unicode String
    01658     //
    01659     return ( CharsInUnicodeString <= MaxBytesInOemString ) ?
    01660            STATUS_SUCCESS :
    01661            STATUS_BUFFER_OVERFLOW;
    01662 }
    01663
    01664 BOOLEAN
    01665 RtlpDidUnicodeToOemWork(
    01666     IN POEM_STRING OemString,
    01667     IN PUNICODE_STRING UnicodeString
    01668     )
    01669
    01670 /*++
    01671
    01672 Routine Description:
    01673
    01674     This function looks for the default character in the Oem string, making
    01675     sure it was not a correct translation from the Unicode source string.
    01676
    01677     This allows us to test whether or not a translation was really successful.
    01678
    01679 Arguments:
    01680
    01681     OemString - The result of conversion from the unicode string.
    01682
    01683     UnicodeString - The source of the Oem string.
    01684
    01685 Return Value:
    01686
    01687     TRUE if the Unicode to Oem translation caused no default characters to be
    01688         inserted.  FALSE otherwise.
    01689
    01690 --*/
    01691
    01692 {
    01693     ULONG OemOffset;
    01694     BOOLEAN Result = TRUE;
    01695
    01696     RTL_PAGED_CODE();
    01697
    01698     if (!NlsMbOemCodePageTag) {
    01699
    01700         for (OemOffset = 0;
    01701              OemOffset < OemString->Length;
    01702              OemOffset += 1) {
    01703
    01704             if ((OemString->Buffer[OemOffset] == (UCHAR)OemDefaultChar) &&
    01705                 (UnicodeString->Buffer[OemOffset] != OemTransUniDefaultChar)) {
    01706
    01707                 Result = FALSE;
    01708                 break;
    01709             }
    01710         }
    01711
    01712     } else {
    01713
    01714         ULONG UnicodeOffset;
    01715
    01716         for (OemOffset = 0, UnicodeOffset = 0;
    01717              OemOffset < OemString->Length;
    01718              OemOffset += 1, UnicodeOffset += 1) {
    01719
    01720             //
    01721             //  If we landed on a DBCS character handle it accordingly
    01722             //
    01723
    01724             if (NlsOemLeadByteInfo[(UCHAR)OemString->Buffer[OemOffset]]) {
    01725
    01726                 USHORT DbcsChar;
    01727
    01728                 ASSERT( OemOffset + 1 < OemString->Length );
    01729
    01730                 DbcsChar = (OemString->Buffer[OemOffset] << 8) + (UCHAR)OemString->Buffer[OemOffset+1];
    01731                 OemOffset++;
    01732
    01733                 if ((DbcsChar == OemDefaultChar) &&
    01734                     (UnicodeString->Buffer[UnicodeOffset] != OemTransUniDefaultChar)) {
    01735
    01736                     Result = FALSE;
    01737                     break;
    01738                 }
    01739
    01740                 continue;
    01741             }
    01742
    01743             if ((OemString->Buffer[OemOffset] == (UCHAR)OemDefaultChar) &&
    01744                 (UnicodeString->Buffer[UnicodeOffset] != OemTransUniDefaultChar)) {
    01745
    01746                 Result = FALSE;
    01747                 break;
    01748             }
    01749         }
    01750     }
    01751
    01752     return Result;
    01753 }
    01754
    01755
    01756 NTSTATUS
    01757 RtlCustomCPToUnicodeN(
    01758     IN PCPTABLEINFO CustomCP,
    01759     OUT PWCH UnicodeString,
    01760     IN ULONG MaxBytesInUnicodeString,
    01761     OUT PULONG BytesInUnicodeString OPTIONAL,
    01762     IN PCH CustomCPString,
    01763     IN ULONG BytesInCustomCPString)
    01764
    01765 /*++
    01766
    01767 Routine Description:
    01768
    01769     This functions converts the specified CustomCP source string into a
    01770     Unicode string. The translation is done with respect to the
    01771     CustomCP Code Page specified.  Single byte characters
    01772     in the range 0x00 - 0x7f are simply zero extended as a performance
    01773     enhancement.  In some far eastern code pages 0x5c is defined as the
    01774     Yen sign.  For system translation we always want to consider 0x5c
    01775     to be the backslash character.  We get this for free by zero extending.
    01776
    01777     NOTE: This routine only supports precomposed Unicode characters.
    01778
    01779 Arguments:
    01780
    01781     CustomCP - Supplies the address of the code page that translations
    01782         are done relative to
    01783
    01784     UnicodeString - Returns a unicode string that is equivalent to
    01785         the CustomCP source string.
    01786
    01787     MaxBytesInUnicodeString - Supplies the maximum number of bytes to be
    01788         written to UnicodeString.  If this causes UnicodeString to be a
    01789         truncated equivalent of CustomCPString, no error condition results.
    01790
    01791     BytesInUnicodeString - Returns the number of bytes in the returned
    01792         unicode string pointed to by UnicodeString.
    01793
    01794     CustomCPString - Supplies the CustomCP source string that is to be
    01795         converted to unicode.
    01796
    01797     BytesInCustomCPString - The number of bytes in the string pointed to
    01798         by CustomCPString.
    01799
    01800 Return Value:
    01801
    01802     SUCCESS - The conversion was successful
    01803
    01804     STATUS_ILLEGAL_CHARACTER - The final CustomCP character was illegal
    01805
    01806     STATUS_BUFFER_OVERFLOW - MaxBytesInUnicodeString was not enough to hold
    01807         the whole CustomCP string.  It was converted correct to the point though.
    01808
    01809 --*/
    01810
    01811 {
    01812     ULONG LoopCount;
    01813     PUSHORT TranslateTable;
    01814     ULONG MaxCharsInUnicodeString;
    01815
    01816     RTL_PAGED_CODE();
    01817
    01818     if (!(CustomCP->DBCSCodePage)) {
    01819         //
    01820         // The Custom CP is a single byte code page.
    01821         //
    01822         MaxCharsInUnicodeString = MaxBytesInUnicodeString / sizeof(WCHAR);
    01823
    01824         LoopCount = (MaxCharsInUnicodeString < BytesInCustomCPString) ?
    01825                      MaxCharsInUnicodeString : BytesInCustomCPString;
    01826
    01827         if (ARGUMENT_PRESENT(BytesInUnicodeString))
    01828             *BytesInUnicodeString = LoopCount * sizeof(WCHAR);
    01829
    01830
    01831         TranslateTable = CustomCP->MultiByteTable;
    01832
    01833         quick_copy:
    01834             switch( LoopCount ) {
    01835             default:
    01836                 UnicodeString[0x0F] = TranslateTable[(UCHAR)CustomCPString[0x0F]];
    01837             case 0x0F:
    01838                 UnicodeString[0x0E] = TranslateTable[(UCHAR)CustomCPString[0x0E]];
    01839             case 0x0E:
    01840                 UnicodeString[0x0D] = TranslateTable[(UCHAR)CustomCPString[0x0D]];
    01841             case 0x0D:
    01842                 UnicodeString[0x0C] = TranslateTable[(UCHAR)CustomCPString[0x0C]];
    01843             case 0x0C:
    01844                 UnicodeString[0x0B] = TranslateTable[(UCHAR)CustomCPString[0x0B]];
    01845             case 0x0B:
    01846                 UnicodeString[0x0A] = TranslateTable[(UCHAR)CustomCPString[0x0A]];
    01847             case 0x0A:
    01848                 UnicodeString[0x09] = TranslateTable[(UCHAR)CustomCPString[0x09]];
    01849             case 0x09:
    01850                 UnicodeString[0x08] = TranslateTable[(UCHAR)CustomCPString[0x08]];
    01851             case 0x08:
    01852                 UnicodeString[0x07] = TranslateTable[(UCHAR)CustomCPString[0x07]];
    01853             case 0x07:
    01854                 UnicodeString[0x06] = TranslateTable[(UCHAR)CustomCPString[0x06]];
    01855             case 0x06:
    01856                 UnicodeString[0x05] = TranslateTable[(UCHAR)CustomCPString[0x05]];
    01857             case 0x05:
    01858                 UnicodeString[0x04] = TranslateTable[(UCHAR)CustomCPString[0x04]];
    01859             case 0x04:
    01860                 UnicodeString[0x03] = TranslateTable[(UCHAR)CustomCPString[0x03]];
    01861             case 0x03:
    01862                 UnicodeString[0x02] = TranslateTable[(UCHAR)CustomCPString[0x02]];
    01863             case 0x02:
    01864                 UnicodeString[0x01] = TranslateTable[(UCHAR)CustomCPString[0x01]];
    01865             case 0x01:
    01866                 UnicodeString[0x00] = TranslateTable[(UCHAR)CustomCPString[0x00]];
    01867             case 0x00:
    01868                 ;
    01869             }
    01870
    01871             if ( LoopCount > 0x10 ) {
    01872                 LoopCount -= 0x10;
    01873                 CustomCPString += 0x10;
    01874                 UnicodeString += 0x10;
    01875
    01876                 goto  quick_copy;
    01877             }
    01878         /* end of copy... */
    01879     } else {
    01880         register USHORT Entry;
    01881         PWCH UnicodeStringAnchor = UnicodeString;
    01882         PUSHORT NlsCustomLeadByteInfo = CustomCP->DBCSOffsets;
    01883
    01884         //
    01885         // The CP is a multibyte code page.  Check each character
    01886         // to see if it is a lead byte before doing the translation.
    01887         //
    01888         MaxCharsInUnicodeString = MaxBytesInUnicodeString / sizeof(WCHAR);
    01889         TranslateTable = (PUSHORT)(CustomCP->DBCSOffsets);
    01890
    01891         while (MaxCharsInUnicodeString && BytesInCustomCPString) {
    01892             MaxCharsInUnicodeString--;
    01893             BytesInCustomCPString--;
    01894             if (NlsCustomLeadByteInfo[*(PUCHAR)CustomCPString]) {
    01895                 //
    01896                 // Lead byte - Make sure there is a trail byte.  If not,
    01897                 // pass back a space rather than an error.  Some 3.x
    01898                 // applications pass incorrect strings and don't expect
    01899                 // to get an error.
    01900                 //
    01901                 if (BytesInCustomCPString == 0)
    01902                 {
    01903                     *UnicodeString++ = UnicodeNull;
    01904                     break;
    01905                 }
    01906
    01907                 //
    01908                 // Get the unicode character.
    01909                 //
    01910                 Entry = NlsCustomLeadByteInfo[*(PUCHAR)CustomCPString++];
    01911                 *UnicodeString = TranslateTable[ Entry + *(PUCHAR)CustomCPString++ ];
    01912                 UnicodeString++;
    01913
    01914                 //
    01915                 // Decrement count of bytes in multibyte string to account
    01916                 // for the double byte character.
    01917                 //
    01918                 BytesInCustomCPString--;
    01919             } else {
    01920                 //
    01921                 // Single byte character.
    01922                 //
    01923                 *UnicodeString++ = (CustomCP->MultiByteTable)[*(PUCHAR)CustomCPString++];
    01924             }
    01925         }
    01926
    01927         if (ARGUMENT_PRESENT(BytesInUnicodeString))
    01928             *BytesInUnicodeString = (ULONG)((PCH)UnicodeString - (PCH)UnicodeStringAnchor);
    01929     }
    01930
    01931     //
    01932     //  Check if we were able to use all of the source CustomCP String
    01933     //
    01934     return ( BytesInCustomCPString <= MaxCharsInUnicodeString ) ?
    01935            STATUS_SUCCESS :
    01936            STATUS_BUFFER_OVERFLOW;
    01937 }
    01938
    01939
    01940 NTSTATUS
    01941 RtlUnicodeToCustomCPN(
    01942     IN PCPTABLEINFO CustomCP,
    01943     OUT PCH CustomCPString,
    01944     IN ULONG MaxBytesInCustomCPString,
    01945     OUT PULONG BytesInCustomCPString OPTIONAL,
    01946     IN PWCH UnicodeString,
    01947     IN ULONG BytesInUnicodeString)
    01948
    01949 /*++
    01950
    01951 Routine Description:
    01952
    01953     This functions converts the specified unicode source string into an
    01954     CustomCP string.  The translation is done with respect to the
    01955     CustomCP Code Page specified by CustomCp.
    01956
    01957 Arguments:
    01958
    01959     CustomCP - Supplies the address of the code page that translations
    01960         are done relative to
    01961
    01962     CustomCPString - Returns an CustomCP string that is equivalent to the
    01963         unicode source string.  If the translation can not be done,
    01964         an error is returned.
    01965
    01966     MaxBytesInCustomCPString - Supplies the maximum number of bytes to be
    01967         written to CustomCPString.  If this causes CustomCPString to be a
    01968         truncated equivalent of UnicodeString, no error condition results.
    01969
    01970     BytesInCustomCPString - Returns the number of bytes in the returned
    01971         CustomCP string pointed to by CustomCPString.
    01972
    01973     UnicodeString - Supplies the unicode source string that is to be
    01974         converted to CustomCP.
    01975
    01976     BytesInUnicodeString - The number of bytes in the the string pointed to by
    01977         UnicodeString.
    01978
    01979 Return Value:
    01980
    01981     SUCCESS - The conversion was successful
    01982
    01983     STATUS_BUFFER_OVERFLOW - MaxBytesInUnicodeString was not enough to hold
    01984         the whole CustomCP string.  It was converted correct to the point though.
    01985
    01986 --*/
    01987
    01988 {
    01989     ULONG TmpCount;
    01990     ULONG LoopCount;
    01991     PCH TranslateTable;
    01992     PUSHORT WideTranslateTable;
    01993     ULONG CharsInUnicodeString;
    01994
    01995     RTL_PAGED_CODE();
    01996
    01997     //
    01998     // Convert Unicode byte count to character count. Byte count of
    01999     // multibyte string is equivalent to character count.
    02000     //
    02001     if (!(CustomCP->DBCSCodePage)) {
    02002         CharsInUnicodeString = BytesInUnicodeString / sizeof(WCHAR);
    02003
    02004         LoopCount = (CharsInUnicodeString < MaxBytesInCustomCPString) ?
    02005                      CharsInUnicodeString : MaxBytesInCustomCPString;
    02006
    02007         if (ARGUMENT_PRESENT(BytesInCustomCPString))
    02008             *BytesInCustomCPString = LoopCount;
    02009
    02010         TranslateTable = CustomCP->WideCharTable;
    02011
    02012         TmpCount = LoopCount & 0x0F;
    02013         UnicodeString += TmpCount;
    02014         CustomCPString += TmpCount;
    02015
    02016         do
    02017         {
    02018             switch( TmpCount ) {
    02019             default:
    02020                 UnicodeString += 0x10;
    02021                 CustomCPString += 0x10;
    02022
    02023                 CustomCPString[-0x10] = TranslateTable[UnicodeString[-0x10]];
    02024             case 0x0F:
    02025                 CustomCPString[-0x0F] = TranslateTable[UnicodeString[-0x0F]];
    02026             case 0x0E:
    02027                 CustomCPString[-0x0E] = TranslateTable[UnicodeString[-0x0E]];
    02028             case 0x0D:
    02029                 CustomCPString[-0x0D] = TranslateTable[UnicodeString[-0x0D]];
    02030             case 0x0C:
    02031                 CustomCPString[-0x0C] = TranslateTable[UnicodeString[-0x0C]];
    02032             case 0x0B:
    02033                 CustomCPString[-0x0B] = TranslateTable[UnicodeString[-0x0B]];
    02034             case 0x0A:
    02035                 CustomCPString[-0x0A] = TranslateTable[UnicodeString[-0x0A]];
    02036             case 0x09:
    02037                 CustomCPString[-0x09] = TranslateTable[UnicodeString[-0x09]];
    02038             case 0x08:
    02039                 CustomCPString[-0x08] = TranslateTable[UnicodeString[-0x08]];
    02040             case 0x07:
    02041                 CustomCPString[-0x07] = TranslateTable[UnicodeString[-0x07]];
    02042             case 0x06:
    02043                 CustomCPString[-0x06] = TranslateTable[UnicodeString[-0x06]];
    02044             case 0x05:
    02045                 CustomCPString[-0x05] = TranslateTable[UnicodeString[-0x05]];
    02046             case 0x04:
    02047                 CustomCPString[-0x04] = TranslateTable[UnicodeString[-0x04]];
    02048             case 0x03:
    02049                 CustomCPString[-0x03] = TranslateTable[UnicodeString[-0x03]];
    02050             case 0x02:
    02051                 CustomCPString[-0x02] = TranslateTable[UnicodeString[-0x02]];
    02052             case 0x01:
    02053                 CustomCPString[-0x01] = TranslateTable[UnicodeString[-0x01]];
    02054             case 0x00:
    02055                 ;
    02056             }
    02057
    02058             LoopCount -= TmpCount;
    02059             TmpCount = 0x10;
    02060         } while ( LoopCount > 0 );
    02061
    02062         /* end of copy... */
    02063     } else {
    02064         USHORT MbChar;
    02065         PCH CustomCPStringAnchor = CustomCPString;
    02066
    02067         WideTranslateTable = CustomCP->WideCharTable;
    02068
    02069         CharsInUnicodeString = BytesInUnicodeString / sizeof(WCHAR);
    02070
    02071         while (CharsInUnicodeString && MaxBytesInCustomCPString) {
    02072
    02073             MbChar = WideTranslateTable[ *UnicodeString++ ];
    02074             if (HIBYTE(MbChar) != 0) {
    02075                 //
    02076                 // Need at least 2 bytes to copy a double byte char.
    02077                 // Don't want to truncate in the middle of a DBCS char.
    02078                 //
    02079                 if (MaxBytesInCustomCPString-- < 2) {
    02080                     break;
    02081                 }
    02082                 *CustomCPString++ = HIBYTE(MbChar);  // lead byte
    02083             }
    02084             *CustomCPString++ = LOBYTE(MbChar);
    02085             MaxBytesInCustomCPString--;
    02086
    02087             CharsInUnicodeString--;
    02088         }
    02089
    02090         if (ARGUMENT_PRESENT(BytesInCustomCPString))
    02091             *BytesInCustomCPString = (ULONG)(CustomCPString - CustomCPStringAnchor);
    02092     }
    02093
    02094     //
    02095     //  Check if we were able to use all of the source Unicode String
    02096     //
    02097     return ( CharsInUnicodeString <= MaxBytesInCustomCPString ) ?
    02098            STATUS_SUCCESS :
    02099            STATUS_BUFFER_OVERFLOW;
    02100 }
    02101
    02102
    02103 NTSTATUS
    02104 RtlUpcaseUnicodeToCustomCPN(
    02105     IN PCPTABLEINFO CustomCP,
    02106     OUT PCH CustomCPString,
    02107     IN ULONG MaxBytesInCustomCPString,
    02108     OUT PULONG BytesInCustomCPString OPTIONAL,
    02109     IN PWCH UnicodeString,
    02110     IN ULONG BytesInUnicodeString)
    02111
    02112 /*++
    02113
    02114 Routine Description:
    02115
    02116     This functions upper cases the specified unicode source string and
    02117     converts it into a CustomCP string.  The translation is done with
    02118     respect to the CustomCP Code Page specified by CustomCp.
    02119
    02120 Arguments:
    02121
    02122     CustomCP - Supplies the address of the code page that translations
    02123         are done relative to
    02124
    02125     CustomCPString - Returns an CustomCP string that is equivalent to the
    02126         unicode source string.  If the translation can not be done,
    02127         an error is returned.
    02128
    02129     MaxBytesInCustomCPString - Supplies the maximum number of bytes to be
    02130         written to CustomCPString.  If this causes CustomCPString to be a
    02131         truncated equivalent of UnicodeString, no error condition results.
    02132
    02133     BytesInCustomCPString - Returns the number of bytes in the returned
    02134         CustomCP string pointed to by CustomCPString.
    02135
    02136     UnicodeString - Supplies the unicode source string that is to be
    02137         converted to CustomCP.
    02138
    02139     BytesInUnicodeString - The number of bytes in the the string pointed
    02140         to by UnicodeString.
    02141
    02142 Return Value:
    02143
    02144     SUCCESS - The conversion was successful
    02145
    02146     STATUS_BUFFER_OVERFLOW - MaxBytesInUnicodeString was not enough to
    02147         hold the whole CustomCP string.  It was converted correctly to
    02148         that point, though.
    02149
    02150 --*/
    02151
    02152 {
    02153     ULONG TmpCount;
    02154     ULONG LoopCount;
    02155     PCH TranslateTable;
    02156     PUSHORT WideTranslateTable;
    02157     ULONG CharsInUnicodeString;
    02158     UCHAR SbChar;
    02159     WCHAR UnicodeChar;
    02160
    02161     RTL_PAGED_CODE();
    02162
    02163     //
    02164     // Convert Unicode byte count to character count. Byte count of
    02165     // multibyte string is equivalent to character count.
    02166     //
    02167     if (!(CustomCP->DBCSCodePage)) {
    02168         CharsInUnicodeString = BytesInUnicodeString / sizeof(WCHAR);
    02169
    02170         LoopCount = (CharsInUnicodeString < MaxBytesInCustomCPString) ?
    02171                      CharsInUnicodeString : MaxBytesInCustomCPString;
    02172
    02173         if (ARGUMENT_PRESENT(BytesInCustomCPString))
    02174             *BytesInCustomCPString = LoopCount;
    02175
    02176         TranslateTable = CustomCP->WideCharTable;
    02177
    02178         TmpCount = LoopCount & 0x0F;
    02179         UnicodeString += TmpCount;
    02180         CustomCPString += TmpCount;
    02181
    02182         do
    02183         {
    02184             //
    02185             // Convert to Single Byte and back to Unicode before upper
    02186             // casing to ensure the visual best fits are converted and
    02187             // upper cased properly.
    02188             //
    02189             switch( TmpCount ) {
    02190             default:
    02191                 UnicodeString += 0x10;
    02192                 CustomCPString += 0x10;
    02193
    02194                 SbChar = TranslateTable[UnicodeString[-0x10]];
    02195                 UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
    02196                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    02197                 CustomCPString[-0x10] = TranslateTable[UnicodeChar];
    02198             case 0x0F:
    02199                 SbChar = TranslateTable[UnicodeString[-0x0F]];
    02200                 UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
    02201                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    02202                 CustomCPString[-0x0F] = TranslateTable[UnicodeChar];
    02203             case 0x0E:
    02204                 SbChar = TranslateTable[UnicodeString[-0x0E]];
    02205                 UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
    02206                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    02207                 CustomCPString[-0x0E] = TranslateTable[UnicodeChar];
    02208             case 0x0D:
    02209                 SbChar = TranslateTable[UnicodeString[-0x0D]];
    02210                 UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
    02211                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    02212                 CustomCPString[-0x0D] = TranslateTable[UnicodeChar];
    02213             case 0x0C:
    02214                 SbChar = TranslateTable[UnicodeString[-0x0C]];
    02215                 UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
    02216                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    02217                 CustomCPString[-0x0C] = TranslateTable[UnicodeChar];
    02218             case 0x0B:
    02219                 SbChar = TranslateTable[UnicodeString[-0x0B]];
    02220                 UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
    02221                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    02222                 CustomCPString[-0x0B] = TranslateTable[UnicodeChar];
    02223             case 0x0A:
    02224                 SbChar = TranslateTable[UnicodeString[-0x0A]];
    02225                 UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
    02226                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    02227                 CustomCPString[-0x0A] = TranslateTable[UnicodeChar];
    02228             case 0x09:
    02229                 SbChar = TranslateTable[UnicodeString[-0x09]];
    02230                 UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
    02231                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    02232                 CustomCPString[-0x09] = TranslateTable[UnicodeChar];
    02233             case 0x08:
    02234                 SbChar = TranslateTable[UnicodeString[-0x08]];
    02235                 UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
    02236                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    02237                 CustomCPString[-0x08] = TranslateTable[UnicodeChar];
    02238             case 0x07:
    02239                 SbChar = TranslateTable[UnicodeString[-0x07]];
    02240                 UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
    02241                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    02242                 CustomCPString[-0x07] = TranslateTable[UnicodeChar];
    02243             case 0x06:
    02244                 SbChar = TranslateTable[UnicodeString[-0x06]];
    02245                 UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
    02246                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    02247                 CustomCPString[-0x06] = TranslateTable[UnicodeChar];
    02248             case 0x05:
    02249                 SbChar = TranslateTable[UnicodeString[-0x05]];
    02250                 UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
    02251                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    02252                 CustomCPString[-0x05] = TranslateTable[UnicodeChar];
    02253             case 0x04:
    02254                 SbChar = TranslateTable[UnicodeString[-0x04]];
    02255                 UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
    02256                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    02257                 CustomCPString[-0x04] = TranslateTable[UnicodeChar];
    02258             case 0x03:
    02259                 SbChar = TranslateTable[UnicodeString[-0x03]];
    02260                 UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
    02261                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    02262                 CustomCPString[-0x03] = TranslateTable[UnicodeChar];
    02263             case 0x02:
    02264                 SbChar = TranslateTable[UnicodeString[-0x02]];
    02265                 UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
    02266                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    02267                 CustomCPString[-0x02] = TranslateTable[UnicodeChar];
    02268             case 0x01:
    02269                 SbChar = TranslateTable[UnicodeString[-0x01]];
    02270                 UnicodeChar = (CustomCP->MultiByteTable)[SbChar];
    02271                 UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    02272                 CustomCPString[-0x01] = TranslateTable[UnicodeChar];
    02273             case 0x00:
    02274                 ;
    02275             }
    02276
    02277             LoopCount -= TmpCount;
    02278             TmpCount = 0x10;
    02279         } while ( LoopCount > 0 );
    02280
    02281         /* end of copy... */
    02282     } else {
    02283         USHORT MbChar;
    02284         register USHORT Entry;
    02285         PCH CustomCPStringAnchor = CustomCPString;
    02286         PUSHORT NlsCustomLeadByteInfo = CustomCP->DBCSOffsets;
    02287
    02288         WideTranslateTable = CustomCP->WideCharTable;
    02289
    02290         CharsInUnicodeString = BytesInUnicodeString / sizeof(WCHAR);
    02291
    02292         while ( CharsInUnicodeString && MaxBytesInCustomCPString ) {
    02293             //
    02294             // Convert to Single Byte and back to Unicode before upper
    02295             // casing to ensure the visual best fits are converted and
    02296             // upper cased properly.
    02297             //
    02298             MbChar = WideTranslateTable[ *UnicodeString++ ];
    02299             if (NlsCustomLeadByteInfo[HIBYTE(MbChar)]) {
    02300                 //
    02301                 // Lead byte - translate the trail byte using the table
    02302                 // that corresponds to this lead byte.
    02303                 //
    02304                 Entry = NlsCustomLeadByteInfo[HIBYTE(MbChar)];
    02305                 UnicodeChar = NlsCustomLeadByteInfo[ Entry + LOBYTE(MbChar) ];
    02306             } else {
    02307                 //
    02308                 // Single byte character.
    02309                 //
    02310                 UnicodeChar = (CustomCP->MultiByteTable)[LOBYTE(MbChar)];
    02311             }
    02312             UnicodeChar = (WCHAR)NLS_UPCASE(UnicodeChar);
    02313             MbChar = WideTranslateTable[UnicodeChar];
    02314
    02315             if (HIBYTE(MbChar) != 0) {
    02316                 //
    02317                 // Need at least 2 bytes to copy a double byte char.
    02318                 // Don't want to truncate in the middle of a DBCS char.
    02319                 //
    02320                 if (MaxBytesInCustomCPString-- < 2) {
    02321                     break;
    02322                 }
    02323                 *CustomCPString++ = HIBYTE(MbChar);  // lead byte
    02324             }
    02325             *CustomCPString++ = LOBYTE(MbChar);
    02326             MaxBytesInCustomCPString--;
    02327
    02328             CharsInUnicodeString--;
    02329         }
    02330
    02331         if (ARGUMENT_PRESENT(BytesInCustomCPString))
    02332             *BytesInCustomCPString = (ULONG)(CustomCPString - CustomCPStringAnchor);
    02333     }
    02334
    02335     //
    02336     //  Check if we were able to use all of the source Unicode String
    02337     //
    02338     return ( CharsInUnicodeString <= MaxBytesInCustomCPString ) ?
    02339            STATUS_SUCCESS :
    02340            STATUS_BUFFER_OVERFLOW;
    02341 }
    02342
    02343 #define MB_TBL_SIZE      256             /* size of MB tables */
    02344 #define GLYPH_TBL_SIZE   MB_TBL_SIZE     /* size of GLYPH tables */
    02345 #define DBCS_TBL_SIZE    256             /* size of DBCS tables */
    02346 #define GLYPH_HEADER     1               /* size of GLYPH table header */
    02347 #define DBCS_HEADER      1               /* size of DBCS table header */
    02348 #define LANG_HEADER      1               /* size of LANGUAGE file header */
    02349 #define UP_HEADER        1               /* size of UPPERCASE table header */
    02350 #define LO_HEADER        1               /* size of LOWERCASE table header */
    02351
    02352 VOID
    02353 RtlInitCodePageTable(
    02354     IN PUSHORT TableBase,
    02355     OUT PCPTABLEINFO CodePageTable
    02356     )
    02357 {
    02358     USHORT offMB;
    02359     USHORT offWC;
    02360     PUSHORT pGlyph;
    02361     PUSHORT pRange;
    02362
    02363     RTL_PAGED_CODE();
    02364
    02365     //
    02366     // Get the offsets.
    02367     //
    02368
    02369     offMB = TableBase[0];
    02370     offWC = offMB + TableBase[offMB];
    02371
    02372
    02373     //
    02374     // Attach Code Page Info to CP hash node.
    02375     //
    02376
    02377     CodePageTable->CodePage = TableBase[1];
    02378     CodePageTable->MaximumCharacterSize = TableBase[2];
    02379     CodePageTable->DefaultChar = TableBase[3];           // default character (MB)
    02380     CodePageTable->UniDefaultChar = TableBase[4];        // default character (Unicode)
    02381     CodePageTable->TransDefaultChar = TableBase[5];      // trans of default char (Unicode)
    02382     CodePageTable->TransUniDefaultChar = TableBase[6];   // trans of Uni default char (MB)
    02383     RtlMoveMemory(
    02384         &CodePageTable->LeadByte,
    02385         &TableBase[7],
    02386         MAXIMUM_LEADBYTES
    02387         );
    02388     CodePageTable->MultiByteTable = (TableBase + offMB + 1);
    02389
    02390     pGlyph = CodePageTable->MultiByteTable + MB_TBL_SIZE;
    02391
    02392     if (pGlyph[0] != 0) {
    02393         pRange = CodePageTable->DBCSRanges = pGlyph + GLYPH_HEADER + GLYPH_TBL_SIZE;
    02394         }
    02395     else {
    02396         pRange = CodePageTable->DBCSRanges = pGlyph + GLYPH_HEADER;
    02397         }
    02398
    02399     //
    02400     //  Attach DBCS information to CP hash node.
    02401     //
    02402
    02403     if (pRange[0] > 0) {
    02404         CodePageTable->DBCSOffsets = pRange + DBCS_HEADER;
    02405         CodePageTable->DBCSCodePage = 1;
    02406         }
    02407     else {
    02408         CodePageTable->DBCSCodePage = 0;
    02409         CodePageTable->DBCSOffsets = NULL;
    02410         }
    02411
    02412     CodePageTable->WideCharTable = (TableBase + offWC + 1);
    02413 }
    02414
    02415
    02416 VOID
    02417 RtlpInitUpcaseTable(
    02418     IN PUSHORT TableBase,
    02419     OUT PNLSTABLEINFO CodePageTable
    02420     )
    02421 {
    02422     USHORT offUP;
    02423     USHORT offLO;
    02424
    02425     //
    02426     // Get the offsets.
    02427     //
    02428
    02429     offUP = LANG_HEADER;
    02430     offLO = offUP + TableBase[offUP];
    02431
    02432     CodePageTable->UpperCaseTable = TableBase + offUP + UP_HEADER;
    02433     CodePageTable->LowerCaseTable = TableBase + offLO + LO_HEADER;
    02434 }
    02435
    02436
    02437 VOID
    02438 RtlInitNlsTables(
    02439     IN PUSHORT AnsiNlsBase,
    02440     IN PUSHORT OemNlsBase,
    02441     IN PUSHORT LanguageNlsBase,
    02442     OUT PNLSTABLEINFO TableInfo
    02443     )
    02444 {
    02445     RTL_PAGED_CODE();
    02446
    02447     RtlInitCodePageTable(AnsiNlsBase,&TableInfo->AnsiTableInfo);
    02448     RtlInitCodePageTable(OemNlsBase,&TableInfo->OemTableInfo);
    02449     RtlpInitUpcaseTable(LanguageNlsBase,TableInfo);
    02450 }
    02451
    02452
    02453 VOID
    02454 RtlResetRtlTranslations(
    02455     PNLSTABLEINFO TableInfo
    02456     )
    02457 {
    02458     RTL_PAGED_CODE();
    02459
    02460     if ( TableInfo->AnsiTableInfo.DBCSCodePage ) {
    02461         RtlMoveMemory(NlsLeadByteInfo,TableInfo->AnsiTableInfo.DBCSOffsets,DBCS_TBL_SIZE*sizeof(USHORT));
    02462         }
    02463     else {
    02464         RtlZeroMemory(NlsLeadByteInfo,DBCS_TBL_SIZE*sizeof(USHORT));
    02465         }
    02466
    02467     NlsMbAnsiCodePageTables = (PUSHORT)TableInfo->AnsiTableInfo.DBCSOffsets;
    02468
    02469     NlsAnsiToUnicodeData = TableInfo->AnsiTableInfo.MultiByteTable;
    02470     NlsUnicodeToAnsiData = (PCH)TableInfo->AnsiTableInfo.WideCharTable;
    02471     NlsUnicodeToMbAnsiData = (PUSHORT)TableInfo->AnsiTableInfo.WideCharTable;
    02472     NlsMbCodePageTag = TableInfo->AnsiTableInfo.DBCSCodePage ? TRUE : FALSE;
    02473     NlsAnsiCodePage = TableInfo->AnsiTableInfo.CodePage;
    02474
    02475     if ( TableInfo->OemTableInfo.DBCSCodePage ) {
    02476         RtlMoveMemory(NlsOemLeadByteInfo,TableInfo->OemTableInfo.DBCSOffsets,DBCS_TBL_SIZE*sizeof(USHORT));
    02477         }
    02478     else {
    02479         RtlZeroMemory(NlsOemLeadByteInfo,DBCS_TBL_SIZE*sizeof(USHORT));
    02480         }
    02481
    02482     NlsMbOemCodePageTables = (PUSHORT)TableInfo->OemTableInfo.DBCSOffsets;
    02483
    02484     NlsOemToUnicodeData = TableInfo->OemTableInfo.MultiByteTable;
    02485     NlsUnicodeToOemData = (PCH)TableInfo->OemTableInfo.WideCharTable;
    02486     NlsUnicodeToMbOemData = (PUSHORT)TableInfo->OemTableInfo.WideCharTable;
    02487     NlsMbOemCodePageTag = TableInfo->OemTableInfo.DBCSCodePage ? TRUE : FALSE;
    02488     NlsOemCodePage = TableInfo->OemTableInfo.CodePage;
    02489     OemDefaultChar = TableInfo->OemTableInfo.DefaultChar;
    02490     OemTransUniDefaultChar = TableInfo->OemTableInfo.TransDefaultChar;
    02491
    02492     Nls844UnicodeUpcaseTable = TableInfo->UpperCaseTable;
    02493     Nls844UnicodeLowercaseTable = TableInfo->LowerCaseTable;
    02494     UnicodeDefaultChar = TableInfo->AnsiTableInfo.UniDefaultChar;
    02495 }
    02496
    02497 void
    02498 RtlGetDefaultCodePage(
    02499     OUT PUSHORT AnsiCodePage,
    02500     OUT PUSHORT OemCodePage
    02501     )
    02502 {
    02503     RTL_PAGED_CODE();
    02504     *AnsiCodePage = NlsAnsiCodePage;
    02505     *OemCodePage = NlsOemCodePage;
    02506 }
    02507
    02508
    02509
    02510
    02511