/******************************Module*Header*******************************\ * Module Name: nlsconv.c * * * * NLS conversion routines. * * * * Created: 08-Sep-1991 15:56:30 * * Author: Bodin Dresevic [BodinD] * * * * Copyright (c) 1991-1999 Microsoft Corporation * \**************************************************************************/ #include "precomp.h" #pragma hdrstop /******************************Public*Routine******************************\ * bGetANSISetMap * * * * Tries to get a simple translation table from ANSI to UNICODE. Returns * * TRUE on success. Sets the gbDBCSCodePage flag if it thinks the char set * * MIGHT be DBCS. * * * * * * Mon 11-Jan-1993 14:13:34 -by- Charles Whitmer [chuckwh] * * Wrote it. I'm clearly assuming that by the time this is called, the * * char set is well defined, and will not change. * \**************************************************************************/ WCHAR *gpwcANSICharSet = NULL; WCHAR *gpwcDBCSCharSet = NULL; BOOL bGetANSISetMap() { CHAR ch[256]; ULONG *pul; ULONG ii,jj; NTSTATUS st; ULONG cjResult; WCHAR *pwc; WCHAR *pwcSBC; // See if we know the answers already. (The client should not have called!) if (gpwcANSICharSet != (WCHAR *) NULL) return(TRUE); // Create a mapping. // Make an ANSI source char set. This funny way of initialization takes // about 180 instructions to execute rather than over 1000. pul = (ULONG *) ch; for (ii=0x03020100L,jj=0; jj<64; jj+=4) { pul[jj+0] = ii; ii += 0x04040404L; pul[jj+1] = ii; ii += 0x04040404L; pul[jj+2] = ii; ii += 0x04040404L; pul[jj+3] = ii; ii += 0x04040404L; } // Allocate the UNICODE buffer but don't write the pointer in until the // table is valid, in case we're racing another thread. pwc = LOCALALLOC(512 * sizeof(WCHAR)); pwcSBC = &pwc[256]; if (pwc == (WCHAR *) NULL) return(FALSE); // Convert the characters. pwc[0] = 0; st = RtlMultiByteToUnicodeN ( &pwc[1], // OUT PWCH UnicodeString 255 * sizeof(WCHAR), // IN ULONG MaxBytesInUnicodeString &cjResult, // OUT PULONG BytesInUnicodeString &ch[1], // IN PCH MultiByteString 255 // IN ULONG BytesInMultiByteString ); if( !NT_SUCCESS(st) ) { // Clean up and forget about accelerations. WARNING("GDI32: RtlMultiByteToUnicodeN error."); LOCALFREE(pwc); return(FALSE); } if( cjResult != 255 * sizeof(WCHAR) ) { // There must be a DBCS code page so gpwcANSIMap takes on new meaning. // It is used for fonts with ANSI,OEM, and SYMBOL charsets. Also, // another table, gpwcDBCS is constructed that is used to map the SBCS // of SHIFT-JIS fonts. WARNING("GDI32:Assuming DBCS code page.\n"); st = MultiByteToWideChar ( 1252, // code page to use 0, // flags &ch[1], // characters to translate 255, // number of multibyte characters &pwc[1], // unicode values of characters 255 // number of wide characters ); if( !NT_SUCCESS(st) ) { // Clean up and forget about accelerations. WARNING("GDI32: MultiByteToWideChar error."); LOCALFREE(pwc); return(FALSE); } // Okay now make a table for SBC bytes. Mark DBCS lead bytes // with 0xFFFF. for( jj = 0; jj < 256; jj++ ) { if( IsDBCSLeadByte( (UCHAR)jj )) { pwcSBC[jj] = (WCHAR) 0xFFFF; } else { st = RtlMultiByteToUnicodeN ( &pwcSBC[jj], sizeof(WCHAR), &cjResult, &ch[jj], 1 ); if( !NT_SUCCESS(st) ) { WARNING("GDI32: RtlMultByteToUnicodeN error."); LOCALFREE(pwc); return(FALSE); } } } } // The table is good, jam it in. Watch out for another thread running this // routine simultaneously. ENTERCRITICALSECTION(&semLocal); { if (gpwcANSICharSet == (WCHAR *) NULL) { gpwcANSICharSet = pwc; gpwcDBCSCharSet = pwcSBC; pwc = (WCHAR *) NULL; } } LEAVECRITICALSECTION(&semLocal); // If we collided with another thread, clean up our extra space. if (pwc != (WCHAR *) NULL) LOCALFREE(pwc); // At this point we have a valid mapping. return(TRUE); }