//+--------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation, 1994-1995 // // File: unicwrap.cpp // // Contents: Wrappers for all Unicode functions used in MSHTML. // Any Unicode parameters/structure fields/buffers are converted // to ANSI, and then the corresponding ANSI version of the function // is called. // //---------------------------------------------------------------------------- #include "ctlspriv.h" #ifdef UNICODE #ifndef WINNT #include "unicwrap.h" #undef TextOutW #undef ExtTextOutW int MbcsFromUnicode(LPSTR pstr, int cch, LPCWSTR pwstr, int cwch = -1); int UnicodeFromMbcs(LPWSTR pwstr, int cwch, LPCSTR pstr, int cch = -1); //+--------------------------------------------------------------------------- // // Member: CConvertStr::Free // // Synopsis: Frees string if alloc'd and initializes to NULL. // //---------------------------------------------------------------------------- void CConvertStr::Free() { if (_pstr != _ach && HIWORD64(_pstr) != 0) { delete [] _pstr; } _pstr = NULL; } //+--------------------------------------------------------------------------- // // Member: CConvertStrW::Free // // Synopsis: Frees string if alloc'd and initializes to NULL. // //---------------------------------------------------------------------------- void CConvertStrW::Free() { if (_pwstr != _awch && HIWORD64(_pwstr) != 0) { delete [] _pwstr; } _pwstr = NULL; } //+--------------------------------------------------------------------------- // // Member: CStrInW::Init // // Synopsis: Converts a LPSTR function argument to a LPWSTR. // // Arguments: [pstr] -- The function argument. May be NULL or an atom // (HIWORD(pwstr) == 0). // // [cch] -- The number of characters in the string to // convert. If -1, the string is assumed to be // NULL terminated and its length is calculated. // // Modifies: [this] // //---------------------------------------------------------------------------- void CStrInW::Init(LPCSTR pstr, int cch) { int cchBufReq; _cwchLen = 0; // Check if string is NULL or an atom. if (HIWORD64(pstr) == 0) { _pwstr = (LPWSTR) pstr; return; } ASSERT(cch == -1 || cch > 0); // // Convert string to preallocated buffer, and return if successful. // _cwchLen = MultiByteToWideChar( CP_ACP, 0, pstr, cch, _awch, ARRAYSIZE(_awch)); if (_cwchLen > 0) { if(_awch[_cwchLen-1] == 0) _cwchLen--; // account for terminator _pwstr = _awch; return; } // // Alloc space on heap for buffer. // cchBufReq = MultiByteToWideChar( CP_ACP, 0, pstr, cch, NULL, 0 ); ASSERT(cchBufReq > 0); _pwstr = new WCHAR[cchBufReq]; if (!_pwstr) { // On failure, the argument will point to the empty string. _awch[0] = 0; _pwstr = _awch; return; } ASSERT(HIWORD64(_pwstr)); _cwchLen = -1 + MultiByteToWideChar( CP_ACP, 0, pstr, cch, _pwstr, cchBufReq ); ASSERT(_cwchLen >= 0); } //+--------------------------------------------------------------------------- // // Member: CStrIn::CStrIn // // Synopsis: Inits the class. // // NOTE: Don't inline this function or you'll increase code size // by pushing -1 on the stack for each call. // //---------------------------------------------------------------------------- CStrIn::CStrIn(LPCWSTR pwstr) : CConvertStr(CP_ACP) { Init(pwstr, -1); } CStrIn::CStrIn(UINT uCP, LPCWSTR pwstr) : CConvertStr(uCP) { Init(pwstr, -1); } //+--------------------------------------------------------------------------- // // Member: CStrIn::Init // // Synopsis: Converts a LPWSTR function argument to a LPSTR. // // Arguments: [pwstr] -- The function argument. May be NULL or an atom // (HIWORD(pwstr) == 0). // // [cwch] -- The number of characters in the string to // convert. If -1, the string is assumed to be // NULL terminated and its length is calculated. // // Modifies: [this] // //---------------------------------------------------------------------------- void CStrIn::Init(LPCWSTR pwstr, int cwch) { int cchBufReq; #if DBG == 1 /* { */ int errcode; #endif /* } */ _cchLen = 0; // Check if string is NULL or an atom. if (HIWORD64(pwstr) == 0) { _pstr = (LPSTR) pwstr; return; } if ( cwch == 0 ) { *_ach = '\0'; _pstr = _ach; return; } ASSERT(cwch == -1 || cwch > 0); // // Convert string to preallocated buffer, and return if successful. // _cchLen = WideCharToMultiByte( _uCP, 0, pwstr, cwch, _ach, ARRAYSIZE(_ach), NULL, NULL); if (_cchLen > 0) { if (_ach[_cchLen-1]==0) _cchLen--; // account for terminator _pstr = _ach; return; } cchBufReq = WideCharToMultiByte( CP_ACP, 0, pwstr, cwch, NULL, 0, NULL, NULL); ASSERT(cchBufReq > 0); _pstr = new char[cchBufReq]; if (!_pstr) { // On failure, the argument will point to the empty string. _ach[0] = 0; _pstr = _ach; return; } ASSERT(HIWORD64(_pstr)); _cchLen = -1 + WideCharToMultiByte( _uCP, 0, pwstr, cwch, _pstr, cchBufReq, NULL, NULL); #if DBG == 1 /* { */ if (_cchLen < 0) { errcode = GetLastError(); ASSERT(0 && "WideCharToMultiByte failed in unicode wrapper."); } #endif /* } */ } //+--------------------------------------------------------------------------- // // Member: CStrInMulti::CStrInMulti // // Synopsis: Converts mulitple LPWSTRs to a multiple LPSTRs. // // Arguments: [pwstr] -- The strings to convert. // // Modifies: [this] // //---------------------------------------------------------------------------- CStrInMulti::CStrInMulti(LPCWSTR pwstr) { LPCWSTR pwstrT; // We don't handle atoms because we don't need to. ASSERT(HIWORD64(pwstr)); // // Count number of characters to convert. // pwstrT = pwstr; if (pwstr) { do { while (*pwstrT++) ; } while (*pwstrT++); } Init(pwstr, (int)(pwstrT - pwstr)); } //+--------------------------------------------------------------------------- // // Member: CStrOut::CStrOut // // Synopsis: Allocates enough space for an out buffer. // // Arguments: [pwstr] -- The Unicode buffer to convert to when destroyed. // May be NULL. // // [cwchBuf] -- The size of the buffer in characters. // // Modifies: [this]. // //---------------------------------------------------------------------------- CStrOut::CStrOut(LPWSTR pwstr, int cwchBuf) : CConvertStr(CP_ACP) { ASSERT(cwchBuf >= 0); if (!cwchBuf) pwstr = NULL; _pwstr = pwstr; _cwchBuf = cwchBuf; if (!pwstr) { ASSERT(cwchBuf == 0); _pstr = NULL; return; } ASSERT(HIWORD64(pwstr)); // Initialize buffer in case Windows API returns an error. _ach[0] = 0; // Use preallocated buffer if big enough. if (cwchBuf * 2 <= ARRAYSIZE(_ach)) { _pstr = _ach; return; } // Allocate buffer. _pstr = new char[cwchBuf * 2]; if (!_pstr) { // // On failure, the argument will point to a zero-sized buffer initialized // to the empty string. This should cause the Windows API to fail. // ASSERT(cwchBuf > 0); _pwstr[0] = 0; _cwchBuf = 0; _pstr = _ach; return; } ASSERT(HIWORD64(_pstr)); _pstr[0] = 0; } //+--------------------------------------------------------------------------- // // Member: CStrOut::ConvertIncludingNul // // Synopsis: Converts the buffer from MBCS to Unicode // // Return: Character count INCLUDING the trailing '\0' // //---------------------------------------------------------------------------- int CStrOut::ConvertIncludingNul() { int cwch; if (!_pstr) return 0; ASSERT(_cwchBuf); // Preinit to null string in case of horrible catastrophe _pwstr[0] = TEXT('\0'); cwch = MultiByteToWideChar(_uCP, 0, _pstr, -1, _pwstr, _cwchBuf); if (!cwch) { // Output buffer was short. Must double-buffer (yuck) int cwchNeeded = MultiByteToWideChar(_uCP, 0, _pstr, -1, NULL, 0); if (cwchNeeded) { LPWSTR pwsz = (LPWSTR)LocalAlloc(LMEM_FIXED, cwchNeeded * SIZEOF(WCHAR)); if (pwsz) { cwch = MultiByteToWideChar(_uCP, 0, _pstr, -1, pwsz, cwchNeeded); if (cwch) { StrCpyNW(_pwstr, pwsz, _cwchBuf); cwch = _cwchBuf; } LocalFree(pwsz); } } else { #if DBG == 1 /* { */ DWORD errcode = GetLastError(); ASSERT(0 && "MultiByteToWideChar failed in unicode wrapper."); #endif /* } */ } } Free(); return cwch; } //+--------------------------------------------------------------------------- // // Member: CStrOut::ConvertExcludingNul // // Synopsis: Converts the buffer from MBCS to Unicode // // Return: Character count EXCLUDING the trailing '\0' // //---------------------------------------------------------------------------- int CStrOut::ConvertExcludingNul() { int ret = ConvertIncludingNul(); if (ret) { ret -= 1; } return ret; } //+--------------------------------------------------------------------------- // // Member: CStrOut::~CStrOut // // Synopsis: Converts the buffer from MBCS to Unicode. // // Note: Don't inline this function, or you'll increase code size as // both ConvertIncludingNul() and CConvertStr::~CConvertStr will be // called inline. // //---------------------------------------------------------------------------- CStrOut::~CStrOut() { ConvertIncludingNul(); } //+--------------------------------------------------------------------------- // // Function: MbcsFromUnicode // // Synopsis: Converts a string to MBCS from Unicode. // // Arguments: [pstr] -- The buffer for the MBCS string. // [cch] -- The size of the MBCS buffer, including space for // NULL terminator. // // [pwstr] -- The Unicode string to convert. // [cwch] -- The number of characters in the Unicode string to // convert, including NULL terminator. If this // number is -1, the string is assumed to be // NULL terminated. -1 is supplied as a // default argument. // // Returns: If [pstr] is NULL or [cch] is 0, 0 is returned. Otherwise, // the number of characters converted, including the terminating // NULL, is returned (note that converting the empty string will // return 1). If the conversion fails, 0 is returned. // // Modifies: [pstr]. // //---------------------------------------------------------------------------- int MbcsFromUnicode(LPSTR pstr, int cch, LPCWSTR pwstr, int cwch) { int ret; #if DBG == 1 /* { */ int errcode; #endif /* } */ ASSERT(cch >= 0); if (!pstr || cch == 0) return 0; ASSERT(pwstr); ASSERT(cwch == -1 || cwch > 0); ret = WideCharToMultiByte(CP_ACP, 0, pwstr, cwch, pstr, cch, NULL, NULL); #if DBG == 1 /* { */ if (ret <= 0) { errcode = GetLastError(); ASSERT(0 && "WideCharToMultiByte failed in unicode wrapper."); } #endif /* } */ return ret; } //+--------------------------------------------------------------------------- // // Function: UnicodeFromMbcs // // Synopsis: Converts a string to Unicode from MBCS. // // Arguments: [pwstr] -- The buffer for the Unicode string. // [cwch] -- The size of the Unicode buffer, including space for // NULL terminator. // // [pstr] -- The MBCS string to convert. // [cch] -- The number of characters in the MBCS string to // convert, including NULL terminator. If this // number is -1, the string is assumed to be // NULL terminated. -1 is supplied as a // default argument. // // Returns: If [pwstr] is NULL or [cwch] is 0, 0 is returned. Otherwise, // the number of characters converted, including the terminating // NULL, is returned (note that converting the empty string will // return 1). If the conversion fails, 0 is returned. // // Modifies: [pwstr]. // //---------------------------------------------------------------------------- int UnicodeFromMbcs(LPWSTR pwstr, int cwch, LPCSTR pstr, int cch) { int ret; #if DBG == 1 /* { */ int errcode; #endif /* } */ ASSERT(cwch >= 0); if (!pwstr || cwch == 0) return 0; ASSERT(pstr); ASSERT(cch == -1 || cch > 0); ret = MultiByteToWideChar(CP_ACP, 0, pstr, cch, pwstr, cwch); #if DBG == 1 /* { */ if (ret <= 0) { errcode = GetLastError(); ASSERT(0 && "MultiByteToWideChar failed in unicode wrapper."); } #endif /* } */ return ret; } //+------------------------------------------------------------------------ // // Contents: widechar character type function (CT_CTYPE1) and (CT_CTYPE3) // // Synopsis: We do not have wide char support for IsChar functions // under Win95. The Unicode-Wrapper functions we have // in core\wrappers all convert to CP_ACP and then call // the A version, which means we will have invalid results // for any characters which aren't in CP_ACP. // // The solution is to roll our own, which result in these // unfortunately large tables. Here's how it works: // // bits: fedc ba98 7654 3210 // pppp pppp iiib bbbb // // The 'b' bits form a 32-bit bit mask into our data. The data // entrys boolean, and are thus 4-bytes long. Of the 2^32 // possible combinations, we in fact have only 218 distinct // values of data. These are stored in adwData. // // The 'p' bits represent a page. Each page has eight // possible entries, represent by 'i'. In most pages, the // bitfields and data are both uniform. // // adwData[abIndex[abType[page]][index]] represents the data // // 1 << bits represents the bitmask. // //------------------------------------------------------------------------- #define __BIT_SHIFT 0 #define __INDEX_SHIFT 5 #define __PAGE_SHIFT 8 #define __BIT_MASK 31 #define __INDEX_MASK 7 // straight lookup functions are inlined. #define ISCHARFUNC(type, wch) \ (adwData[abIndex[abType1##type[wch>>__PAGE_SHIFT]] \ [(wch>>__INDEX_SHIFT)&__INDEX_MASK]] \ >> (wch&__BIT_MASK)) & 1 // // To avoid header file conflicts with IsCharAlphaW, IsCharAlphaNumericW, ... defined in // winuser.h, the functions names end in "Wrap". SHLWAPI.DEF exports these functions with // the correct name. // STDAPI_(BOOL) IsCharAlphaWrap(WCHAR wch); STDAPI_(BOOL) IsCharAlphaNumericWrap(WCHAR wch); STDAPI_(BOOL) IsCharUpperWrap(WCHAR wch); STDAPI_(BOOL) IsCharLowerWrap(WCHAR wch); const DWORD adwData[218] = { 0x00000000, 0x07fffffe, 0xff7fffff, 0xffffffff, // 0x00-0x03 0xfc3fffff, 0x00ffffff, 0xffff0000, 0x000001ff, // 0x04-0x07 0xffffd740, 0xfffffffb, 0x547f7fff, 0x000ffffd, // 0x08-0x0b 0xffffdffe, 0xdffeffff, 0xffff0003, 0xffff199f, // 0x0c-0x0f 0x033fcfff, 0xfffe0000, 0x007fffff, 0xfffffffe, // 0x10-0x13 0x000000ff, 0x000707ff, 0x000007fe, 0x7cffffff, // 0x14-0x17 0x002f7fff, 0xffffffe0, 0x03ffffff, 0xff000000, // 0x18-0x1b 0x00000003, 0xfff99fe0, 0x03c5fdff, 0xb0000000, // 0x1c-0x1f 0x00030003, 0xfff987e0, 0x036dfdff, 0x5e000000, // 0x20-0x23 0xfffbafe0, 0x03edfdff, 0x00000001, 0x03cdfdff, // 0x24-0x27 0xd63dc7e0, 0x03bfc718, 0xfffddfe0, 0x03effdff, // 0x28-0x2b 0x40000000, 0x03fffdff, 0x000d7fff, 0x0000003f, // 0x2c-0x2f 0xfef02596, 0x00006cae, 0x30000000, 0xffff003f, // 0x30-0x33 0x83ffffff, 0xffffff07, 0x07ffffff, 0x3f3fffff, // 0x34-0x37 0xaaff3f3f, 0x3fffffff, 0x1fdfffff, 0x0fcf1fdc, // 0x38-0x3b 0x1fdc1fff, 0xf0000000, 0x000003ff, 0x00000020, // 0x3c-0x3f 0x781fffff, 0x77ffffff, 0xfffe1fff, 0x00007fff, // 0x40-0x43 0x0000000f, 0x00003fff, 0x80f8007f, 0x5f7fffff, // 0x44-0x47 0xffffffdb, 0x0003ffff, 0xfff80000, 0xfffffdff, // 0x48-0x4b 0xfffffffd, 0xfffcffff, 0x0fff0000, 0x1fffffff, // 0x4c-0x4f 0xffffffc0, 0x7ffffffe, 0x1cfcfcfc, 0x00003e00, // 0x50-0x53 0x00000fff, 0x80000000, 0xfc00fffe, 0xf8000001, // 0x54-0x57 0x78000001, 0x00800000, 0x00040000, 0x7fffffff, // 0x58-0x5b 0x44300003, 0x000000b0, 0x0000007c, 0xfe000000, // 0x5c-0x5f 0x00000200, 0x00180000, 0x88001000, 0x0007f801, // 0x60-0x63 0x00013c00, 0xffd00000, 0x0000000e, 0x001f3fff, // 0x64-0x67 0x0001003c, 0xd0000000, 0x0080399f, 0x07fc000c, // 0x68-0x6b 0x00000004, 0x00003987, 0x001f0000, 0x00013bbf, // 0x6c-0x6f 0x00c0398f, 0x00010000, 0x0000000c, 0xc0000000, // 0x70-0x73 0x00803dc7, 0x00603ddf, 0x00803dcf, 0x87f28000, // 0x74-0x77 0x0c00ffc0, 0x3bff8000, 0x00003f5f, 0x08000000, // 0x78-0x7b 0xe0000000, 0xe000e003, 0x6000e000, 0xffff7fff, // 0x7c-0x7f 0x0000007f, 0xfc00fc00, 0x00007c00, 0x01ffffff, // 0x80-0x83 0xffff0007, 0x000007ff, 0x0000001f, 0x003fffff, // 0x84-0x87 0xffffdfff, 0x0000ffff, 0xfc0fffff, 0xfffff3de, // 0x88-0x8b 0xfffffeff, 0x7f47afff, 0xffc000fe, 0xff1fffff, // 0x8c-0x8f 0x7ffeffff, 0x80ffffff, 0x7e000000, 0x78000000, // 0x90-0x93 0x8fffffff, 0x0001ffff, 0xffff0fff, 0xf87fffff, // 0x94-0x97 0xffff000f, 0xfff7fe1f, 0xffd70f7f, 0x0001003e, // 0x98-0x9b 0x00007f7f, 0x03ff0000, 0x020c0000, 0x0000ffc0, // 0x9c-0x9f 0x0007ff80, 0x03f10000, 0x0000007e, 0x7f7fffff, // 0xa0-0xa3 0x55555555, 0xaa555555, 0x555554aa, 0x2b555555, // 0xa4-0xa7 0xb1dbced6, 0x11aed295, 0x4aaaadb0, 0x54165555, // 0xa8-0xab 0x00555555, 0xfffed740, 0x00000ffb, 0x541c0000, // 0xac-0xaf 0x00005555, 0x55550001, 0x5555088a, 0x01154555, // 0xb0-0xb3 0x00155555, 0x01555555, 0x3f00ff00, 0xff00ff00, // 0xb4-0xb7 0xaa003f00, 0x0000ff00, 0x1f00ff00, 0x0f001f00, // 0xb8-0xbb 0x1f001f00, 0xffc00000, 0xaaaaaaaa, 0x55aaaaaa, // 0xbc-0xbf 0xaaaaab55, 0xd4aaaaaa, 0x4e243129, 0x2651292a, // 0xc0-0xc3 0xb5555b60, 0xa82daaaa, 0x00aaaaaa, 0xffaffbfb, // 0xc4-0xc7 0x640f7ffc, 0x000001f9, 0xfffff000, 0x00637fff, // 0xc8-0xcb 0x000faaa8, 0xaaaa0002, 0xaaaa1114, 0x022a8aaa, // 0xcc-0xcf 0x07eaaaaa, 0x02aaaaaa, 0x003f00ff, 0x00ff00ff, // 0xd0-0xd3 0x00ff003f, 0x3fff00ff, 0x00df00ff, 0x00cf00dc, // 0xd4-0xd7 0x00dc00ff, 0x00f8007f }; const BYTE abIndex[98][8] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x00 { 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02 }, // 0x01 { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04 }, // 0x02 { 0x05, 0x00, 0x06, 0x03, 0x03, 0x07, 0x00, 0x00 }, // 0x03 { 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x0a, 0x0b }, // 0x04 { 0x0c, 0x03, 0x0d, 0x03, 0x0e, 0x03, 0x0f, 0x10 }, // 0x05 { 0x00, 0x11, 0x12, 0x13, 0x14, 0x00, 0x06, 0x15 }, // 0x06 { 0x00, 0x01, 0x16, 0x11, 0x03, 0x17, 0x18, 0x00 }, // 0x07 { 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20 }, // 0x08 { 0x21, 0x22, 0x23, 0x00, 0x24, 0x25, 0x00, 0x26 }, // 0x09 { 0x1d, 0x27, 0x1f, 0x1c, 0x28, 0x29, 0x00, 0x00 }, // 0x0a { 0x2a, 0x2b, 0x00, 0x1c, 0x2a, 0x2b, 0x2c, 0x1c }, // 0x0b { 0x2a, 0x2d, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00 }, // 0x0c { 0x13, 0x2e, 0x2f, 0x00, 0x30, 0x31, 0x32, 0x00 }, // 0x0d { 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x33, 0x12 }, // 0x0e { 0x03, 0x03, 0x34, 0x03, 0x03, 0x35, 0x03, 0x1a }, // 0x0f { 0x03, 0x03, 0x03, 0x03, 0x36, 0x03, 0x03, 0x1a }, // 0x10 { 0x37, 0x03, 0x38, 0x39, 0x03, 0x3a, 0x3b, 0x3c }, // 0x11 { 0x00, 0x00, 0x00, 0x00, 0x3d, 0x03, 0x03, 0x3e }, // 0x12 { 0x3f, 0x00, 0x13, 0x03, 0x40, 0x13, 0x03, 0x41 }, // 0x13 { 0x19, 0x42, 0x03, 0x03, 0x43, 0x00, 0x00, 0x00 }, // 0x14 { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 }, // 0x15 { 0x03, 0x03, 0x03, 0x03, 0x03, 0x2f, 0x00, 0x00 }, // 0x16 { 0x03, 0x03, 0x03, 0x03, 0x03, 0x44, 0x00, 0x00 }, // 0x17 { 0x03, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x18 { 0x46, 0x47, 0x48, 0x03, 0x03, 0x49, 0x4a, 0x4b }, // 0x19 { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x4c }, // 0x1a { 0x03, 0x39, 0x06, 0x03, 0x4d, 0x03, 0x14, 0x4e }, // 0x1b { 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x4f }, // 0x1c { 0x00, 0x01, 0x01, 0x50, 0x03, 0x51, 0x52, 0x00 }, // 0x1d { 0x53, 0x26, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00 }, // 0x1e { 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x1f { 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x20 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55 }, // 0x21 { 0x00, 0x56, 0x57, 0x58, 0x00, 0x13, 0x59, 0x59 }, // 0x22 { 0x00, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00 }, // 0x23 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x5b, 0x3e }, // 0x24 { 0x03, 0x03, 0x2f, 0x5c, 0x5d, 0x00, 0x00, 0x00 }, // 0x25 { 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00 }, // 0x26 { 0x00, 0x00, 0x5f, 0x00, 0x60, 0x06, 0x44, 0x61 }, // 0x27 { 0x62, 0x00, 0x63, 0x64, 0x00, 0x00, 0x65, 0x45 }, // 0x28 { 0x66, 0x3d, 0x67, 0x68, 0x66, 0x69, 0x6a, 0x6b }, // 0x29 { 0x6c, 0x69, 0x6d, 0x6e, 0x66, 0x3d, 0x6f, 0x00 }, // 0x2a { 0x66, 0x3d, 0x70, 0x71, 0x72, 0x73, 0x74, 0x00 }, // 0x2b { 0x66, 0x73, 0x75, 0x00, 0x72, 0x73, 0x75, 0x00 }, // 0x2c { 0x72, 0x73, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2d { 0x00, 0x77, 0x78, 0x00, 0x00, 0x79, 0x7a, 0x00 }, // 0x2e { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b }, // 0x2f { 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7d, 0x7e }, // 0x30 { 0x03, 0x7f, 0x80, 0x81, 0x82, 0x54, 0x06, 0x1c }, // 0x31 { 0x03, 0x83, 0x4a, 0x03, 0x84, 0x03, 0x03, 0x85 }, // 0x32 { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x49 }, // 0x33 { 0x4c, 0x03, 0x03, 0x36, 0x00, 0x00, 0x00, 0x00 }, // 0x34 { 0x03, 0x86, 0x85, 0x03, 0x03, 0x03, 0x03, 0x85 }, // 0x35 { 0x03, 0x03, 0x03, 0x03, 0x87, 0x88, 0x03, 0x89 }, // 0x36 { 0x8a, 0x03, 0x03, 0x89, 0x00, 0x00, 0x00, 0x00 }, // 0x37 { 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x00, 0x00 }, // 0x38 { 0x13, 0x91, 0x00, 0x00, 0x92, 0x00, 0x00, 0x93 }, // 0x39 { 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00 }, // 0x3a { 0x4f, 0x03, 0x44, 0x94, 0x03, 0x95, 0x96, 0x5b }, // 0x3b { 0x03, 0x03, 0x03, 0x97, 0x03, 0x03, 0x39, 0x5b }, // 0x3c { 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3d { 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3e { 0x00, 0x98, 0x99, 0x9a, 0x03, 0x03, 0x03, 0x4f }, // 0x3f { 0x56, 0x57, 0x58, 0x9b, 0x73, 0x26, 0x00, 0x9c }, // 0x40 { 0x00, 0x9d, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00 }, // 0x41 { 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x9d }, // 0x42 { 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x9f }, // 0x43 { 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0xa0 }, // 0x44 { 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x00 }, // 0x45 { 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x9d, 0x00 }, // 0x46 { 0x00, 0x00, 0x00, 0xa1, 0x3e, 0x00, 0x00, 0x00 }, // 0x47 { 0x9d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x48 { 0x00, 0x9d, 0xa2, 0xa2, 0x00, 0x00, 0x00, 0x00 }, // 0x49 { 0x9d, 0xa2, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4a { 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xa3, 0x00 }, // 0x4b { 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab }, // 0x4c { 0xac, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4d { 0x00, 0x00, 0x00, 0x00, 0xad, 0xae, 0xaf, 0xb0 }, // 0x4e { 0x0c, 0x89, 0x00, 0xa4, 0xb1, 0xa4, 0xb2, 0xb3 }, // 0x4f { 0x00, 0x11, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x50 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x2f, 0x00 }, // 0x51 { 0xa4, 0xa4, 0xa4, 0xa4, 0xb4, 0xa4, 0xa4, 0xb5 }, // 0x52 { 0xb6, 0xb7, 0xb8, 0xb9, 0xb7, 0xba, 0xbb, 0xbc }, // 0x53 { 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0x89, 0x00 }, // 0x54 { 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x55 { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x55, 0x02 }, // 0x56 { 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5 }, // 0x57 { 0xc6, 0x00, 0x06, 0xc7, 0xc8, 0xc9, 0x00, 0x00 }, // 0x58 { 0x00, 0x00, 0x00, 0x00, 0x71, 0xca, 0xcb, 0xcc }, // 0x59 { 0x00, 0x06, 0x0d, 0xbe, 0xcd, 0xbe, 0xce, 0xcf }, // 0x5a { 0x00, 0x00, 0x00, 0x13, 0x14, 0x00, 0x00, 0x00 }, // 0x5b { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x12 }, // 0x5c { 0xbe, 0xbe, 0xbe, 0xbe, 0xd0, 0xbe, 0xbe, 0xd1 }, // 0x5d { 0xd2, 0xd3, 0xd4, 0xd5, 0xd3, 0xd6, 0xd7, 0xd8 }, // 0x5e { 0x00, 0x00, 0x00, 0x00, 0x3d, 0x87, 0x06, 0x3e }, // 0x5f { 0xd9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x60 { 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 } // 0x61 }; const BYTE abType1Alpha[256] = // 154 { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x00, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x00, 0x0e, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d }; BOOL IsCharSpaceW(WCHAR wch) { int nType; switch(wch>>8) { case 0x00: nType = 0x1e; break; case 0x20: nType = 0x1f; break; case 0x30: nType = 0x20; break; case 0xfe: nType = 0x21; break; default: nType = 0x00; break; } return (adwData[abIndex[nType][(wch>>__INDEX_SHIFT)&__INDEX_MASK]] >>(wch&__BIT_MASK)) & 1; } const BYTE abType1Punct[256] = // 32 { 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x00, 0x00, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x3a, 0x3b, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x3e, 0x3f, 0x40 }; const BYTE abType1Digit[256] = // 11 { 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x43, 0x43, 0x44, 0x43, 0x45, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48 }; BOOL IsCharDigitW(WCHAR wch) { return ISCHARFUNC(Digit, wch); } BOOL IsCharXDigitW(WCHAR wch) { int nType; switch(wch>>8) { case 0x00: nType = 0x49; break; case 0xff: nType = 0x4a; break; default: nType = 0x00; break; } return (adwData[abIndex[nType][(wch>>__INDEX_SHIFT)&__INDEX_MASK]] >> (wch&__BIT_MASK)) & 1; } const BYTE abType1Upper[256] = // 12 { 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x53, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55 }; const BYTE abType1Lower[256] = // 13 { 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x61 }; BOOL IsCharPunctW(WCHAR wch) { return ISCHARFUNC(Punct, wch); } BOOL IsCharCntrlW(WCHAR wch) { return (unsigned)(wch - 0x0000) <= (0x001f - 0x0000) || (unsigned)(wch - 0x007f) <= (0x009f - 0x007f); } // NB (cthrash) WCH_NBSP is considered blank, for compatibility. BOOL IsCharBlankW(WCHAR wch) { return wch == 0x0009 || wch == 0x0020 || wch == 0x00a0 || wch == 0x3000 || wch == 0xfeff; } BOOL IsCharAlphaWrap(WCHAR wch) { return ISCHARFUNC(Alpha, wch); } BOOL IsCharUpperWrap(WCHAR wch) { return ISCHARFUNC(Upper, wch); } BOOL IsCharLowerWrap(WCHAR wch) { return ISCHARFUNC(Lower, wch); } BOOL IsCharAlphaNumericWrap(WCHAR wch) { return ISCHARFUNC(Alpha, wch) || ISCHARFUNC(Digit, wch); } static const BYTE abType3PageSub[256] = { 0x00, 0x80, 0x81, 0x82, 0x00, 0x83, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x00, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x8f, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x92, 0x00, 0x00, 0x93, 0x94, 0x00 }; static const BYTE abType3Page0[256] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x09, 0x09, 0x01, 0x09, 0x09, 0x01, 0x01, 0x01, 0x00, 0x01, 0x09, 0x01, 0x01, 0x09, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const BYTE abType3Page32[256] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x11, 0x11, 0x01, 0x01, 0x11, 0x11, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x09, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const BYTE abType3Page48[256] = { 0x11, 0x11, 0x11, 0x00, 0x00, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x11, 0x11, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x16, 0x16, 0x04, 0x04, 0x00, 0x00, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x02, 0x12, 0x02, 0x12, 0x02, 0x12, 0x02, 0x12, 0x02, 0x12, 0x02, 0x12, 0x02, 0x12, 0x02, 0x12, 0x02, 0x12, 0x02, 0x12, 0x02, 0x12, 0x02, 0x12, 0x12, 0x02, 0x12, 0x02, 0x12, 0x02, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x02, 0x02, 0x12, 0x02, 0x02, 0x12, 0x02, 0x02, 0x12, 0x02, 0x02, 0x12, 0x02, 0x02, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x02, 0x12, 0x02, 0x02, 0x12, 0x12, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x13, 0x06, 0x02, 0x02, 0x00 }; static const BYTE abType3Page255[256] = { 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x11, 0x11, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; struct tagType3DualValue { DWORD adwBitfield[8]; DWORD adwValue[2]; } const aType3DualValue[21] = { { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // Page1 0x00000000, 0x0000000f, 0x00000000, 0x00000000, 0x00000001 }, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // Page2 0x00000000, 0x3f000000, 0x00000000, 0x00000000, 0x00000001 }, { 0x00000000, 0x00000000, 0x00000000, 0x04000000, 0x000000b0, // Page3 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001 }, { 0x00000000, 0x00000000, 0xf8000000, 0x00000000, 0x00000200, // Page5 0x40000000, 0x00000009, 0x00180000, 0x00000000, 0x00000001 }, { 0x88001000, 0x00000000, 0x00000000, 0x00003c00, 0x00000000, // Page6 0x00000000, 0x00100000, 0x00000200, 0x00000000, 0x00000001 }, { 0x00000000, 0x80008000, 0x0c008040, 0x00000000, 0x00000000, // Page14 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001 }, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // Page31 0xe0000000, 0xe000e003, 0x6000e000, 0x00000000, 0x00000001 }, { 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0xffff0000, // Page33 0xffffffff, 0xffffffff, 0x000007ff, 0x00000000, 0x00000001 }, { 0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // Page34 0x00000000, 0x00000000, 0xfffc0000, 0x00000001, 0x00000000 }, { 0x00000002, 0x00000000, 0x00000000, 0xf8000000, 0xffffffff, // Page35 0xffffffff, 0xffffffff, 0xffffffff, 0x00000001, 0x00000000 }, { 0x00000000, 0xffffffe0, 0xfffff800, 0xffffffff, 0xffffffff, // Page36 0xffffffff, 0xffffffff, 0xffffffff, 0x00000001, 0x00000000 }, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffc00000, // Page37 0x00002000, 0x00000000, 0xffff8000, 0x00000001, 0x00000000 }, { 0x03f00000, 0x00000000, 0x00000000, 0xffff0000, 0xffffffff, // Page38 0xffffffff, 0xffffffff, 0xffffffff, 0x00000001, 0x00000000 }, { 0xfffff3de, 0xfffffeff, 0x7f47afff, 0x000000fe, 0xff100000, // Page39 0x7ffeffff, 0x00000000, 0x00000000, 0x00000000, 0x00000001 }, { 0x00000000, 0xfffe0000, 0xffffffff, 0x0000001f, 0x00000000, // Page49 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000010 }, { 0x00000000, 0x00000000, 0x00000000, 0x80000000, 0x00000000, // Page50 0x00000000, 0x00000fff, 0x00000000, 0x00000000, 0x00000001 }, { 0x00000000, 0x00000000, 0xff000000, 0x0001ffff, 0x00000000, // Page51 0x00000000, 0x00000000, 0x7fffffff, 0x00000000, 0x00000001 }, { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // Page159 0xffffffc0, 0xffffffff, 0xffffffff, 0x00000020, 0x00000000 }, { 0x00000000, 0xffffc000, 0xffffffff, 0xffffffff, 0xffffffff, // Page250 0xffffffff, 0xffffffff, 0xffffffff, 0x00000020, 0x00000000 }, { 0x00000000, 0xc0000000, 0x00000000, 0x00000000, 0x00000000, // Page253 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001 }, { 0x00000000, 0xfff90000, 0xfef7fe1f, 0x00000f77, 0x00000000, // Page254 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001 } }; // // CType 3 Flag Bits. // // In the interest of reducing our table complexity, we've here a reduced // bitfield. Only those bits currently used by IE4 are returned by // GetStringType3Ex(). // // These are the flags are they are defined in winnls.h // // C3_NONSPACING 0x0001 // C3_DIACRITIC 0x0002 // C3_VOWELMARK 0x0004 // C3_SYMBOL 0x0008 // C3_KATAKANA 0x0010 // C3_HIRAGANA 0x0020 // C3_HALFWIDTH 0x0040 // C3_FULLWIDTH 0x0080 // C3_IDEOGRAPH 0x0100 // C3_KASHIDA 0x0200 // C3_LEXICAL 0x0400 // C3_ALPHA 0x8000 // The supported flags are encoded by shifting them to the right 3 bits. // C3_SYMBOL 0x0001 // C3_KATAKANA 0x0002 // C3_HIRAGANA 0x0004 // C3_HALFWIDTH 0x0008 // C3_FULLWIDTH 0x0010 // C3_IDEOGRAPH 0x0020 // GetStringType3Ex returns the correct Win32 flags NOT the compressed flags. BOOL GetStringType3ExW( LPCWSTR lpSrcStr, // string arg int cchSrc, // length (or -1) LPWORD lpCharType ) // output buffer { LPCWSTR lpStop = lpSrcStr + ((cchSrc == -1) ? MAXLONG : cchSrc); while (lpSrcStr < lpStop) { WCHAR wch = *lpSrcStr++; WORD wCharType; BYTE bPageSub; if (!wch && cchSrc == -1) break; switch (wch & (unsigned int)0xff00) { case 0x0000: wCharType = abType3Page0[wch]; // Page0: 4 values break; case 0x2000: wCharType = abType3Page32[wch & 0xff]; // Page32: 4 values break; case 0x3000: wCharType = abType3Page48[wch & 0xff]; // Page48: 10 values break; case 0xff00: wCharType = abType3Page255[wch & 0xff]; // Page255: 7 values break; default: bPageSub = abType3PageSub[wch>>8]; if (bPageSub & 0x80) // 21 pages have 2 values { const struct tagType3DualValue *p = aType3DualValue + (bPageSub & 0x7f); wCharType = (BYTE) p->adwValue[(p->adwBitfield[(wch>>5)&7] >> (wch & 0x1f)) & 1]; } else // 231 pages have 1 value { wCharType = bPageSub; } break; } *lpCharType++ = wCharType << 3; } return TRUE; } // // Str Functions from SHLWAPI // int StrCmpW( IN LPCWSTR pwsz1, IN LPCWSTR pwsz2) { int iRet = -1; // arbitrary on failure ASSERT(IS_VALID_STRING_PTRW(pwsz1, -1)); ASSERT(IS_VALID_STRING_PTRW(pwsz2, -1)); if (pwsz1 && pwsz2) { CStrIn psz1(pwsz1); CStrIn psz2(pwsz2); iRet = lstrcmpA(psz1, psz2); } return iRet; } int StrCmpIW( IN LPCWSTR pwsz1, IN LPCWSTR pwsz2) { int iRet = -1; // arbitrary on failure ASSERT(IS_VALID_STRING_PTRW(pwsz1, -1)); ASSERT(IS_VALID_STRING_PTRW(pwsz2, -1)); if (pwsz1 && pwsz2) { CStrIn psz1(pwsz1); CStrIn psz2(pwsz2); iRet = lstrcmpiA(psz1, psz2); } return iRet; } #if 0 // BUGBUG: We have another StrCpyW in strings.c LPWSTR StrCpyW(LPWSTR psz1, LPCWSTR psz2) { LPWSTR psz = psz1; ASSERT(psz1); ASSERT(psz2); while (*psz1++ = *psz2++) ; return psz; } #endif LPWSTR StrCatW(LPWSTR psz1, LPCWSTR psz2) { LPWSTR psz = psz1; ASSERT(psz1); ASSERT(psz2); while (0 != *psz1) psz1++; while (*psz1++ = *psz2++) ; return psz; } //+------------------------------------------------------------------------ // // Implementation of the wrapped functions // //------------------------------------------------------------------------- BOOL AppendMenuWrap( HMENU hMenu, UINT uFlags, UINT uIDnewItem, LPCWSTR lpnewItem) { ASSERT(!(uFlags & MF_BITMAP) && !(uFlags & MF_OWNERDRAW)); CStrIn str(lpnewItem); return AppendMenuA(hMenu, uFlags, uIDnewItem, str); } BOOL CallMsgFilterWrap(LPMSG lpMsg, int nCode) { return CallMsgFilterA(lpMsg, nCode); } LRESULT CallWindowProcWrap( WNDPROC lpPrevWndFunc, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { return CallWindowProcA(lpPrevWndFunc, hWnd, Msg, wParam, lParam); } //---------------------------------------------------------------------- // // function: CharLowerWrap( LPWSTR pch ) // // purpose: Converts character to lowercase. Takes either a pointer // to a string, or a character masquerading as a pointer. // In the later case, the HIWORD must be zero. This is // as spec'd for Win32. // // returns: Lowercased character or string. In the string case, // the lowercasing is done inplace. // //---------------------------------------------------------------------- LPWSTR CharLowerWrap( LPWSTR pch ) { if (!HIWORD64(pch)) { WCHAR ch = (WCHAR)(LONG_PTR)pch; CharLowerBuffWrap( &ch, 1 ); pch = (LPWSTR)MAKEINTATOM(ch); } else { CharLowerBuffWrap( pch, lstrlenW(pch) ); } return pch; } //---------------------------------------------------------------------- // // function: CharLowerBuffWrap( LPWSTR pch, DWORD cch ) // // purpose: Converts a string to lowercase. String must be cch // characters in length. // // returns: Character count (cch). The lowercasing is done inplace. // //---------------------------------------------------------------------- DWORD CharLowerBuffWrap( LPWSTR pch, DWORD cchLength ) { DWORD cch; for ( cch = cchLength; cch-- ; pch++ ) { WCHAR ch = *pch; if (IsCharUpperWrap(ch)) { if (ch < 0x0100) { *pch += 32; // Get Latin-1 out of the way first } else if (ch < 0x0531) { if (ch < 0x0391) { if (ch < 0x01cd) { if (ch <= 0x178) { if (ch < 0x0178) { *pch += (ch == 0x0130) ? 0 : 1; } else { *pch -= 121; } } else { static const BYTE abLookup[] = { // 0/8 1/9 2/a 3/b 4/c 5/d 6/e 7/f /* 0x0179-0x17f */ 1, 0, 1, 0, 1, 0, 0, /* 0x0180-0x187 */ 0, 210, 1, 0, 1, 0, 206, 1, /* 0x0188-0x18f */ 0, 205, 205, 1, 0, 0, 79, 202, /* 0x0190-0x197 */ 203, 1, 0, 205, 207, 0, 211, 209, /* 0x0198-0x19f */ 1, 0, 0, 0, 211, 213, 0, 214, /* 0x01a0-0x1a7 */ 1, 0, 1, 0, 1, 0, 0, 1, /* 0x01a8-0x1af */ 0, 218, 0, 0, 1, 0, 218, 1, /* 0x01b0-0x1b7 */ 0, 217, 217, 1, 0, 1, 0, 219, /* 0x01b8-0x1bf */ 1, 0, 0, 0, 1, 0, 0, 0, /* 0x01c0-0x1c7 */ 0, 0, 0, 0, 2, 0, 0, 2, /* 0x01c8-0x1cb */ 0, 0, 2, 0 }; *pch += abLookup[ch-0x0179]; } } else if (ch < 0x0386) { switch (ch) { case 0x01f1: *pch += 2; break; case 0x01f2: break; default: *pch += 1; } } else { static const BYTE abLookup[] = { 38, 0, 37, 37, 37, 0, 64, 0, 63, 63 }; *pch += abLookup[ch-0x0386]; } } else { if (ch < 0x0410) { if (ch < 0x0401) { if (ch < 0x03e2) { if (!InRange(ch, 0x03d2, 0x03d4) && !(InRange(ch, 0x3da, 0x03e0) & !(ch & 1))) { *pch += 32; } } else { *pch += 1; } } else { *pch += 80; } } else { if (ch < 0x0460) { *pch += 32; } else { *pch += 1; } } } } else { if (ch < 0x2160) { if (ch < 0x1fba) { if (ch < 0x1f08) { if (ch < 0x1e00) { *pch += 48; } else { *pch += 1; } } else if (!(InRange(ch, 0x1f88, 0x1faf) && (ch & 15)>7)) { *pch -= 8; } } else { static const BYTE abLookup[] = { // 8 9 a b c d e f 0, 0, 74, 74, 0, 0, 0, 0, 86, 86, 86, 86, 0, 0, 0, 0, 8, 8, 100, 100, 0, 0, 0, 0, 8, 8, 112, 112, 7, 0, 0, 0, 128, 128, 126, 126, 0, 0, 0, 0 }; int i = (ch-0x1fb0); *pch -= (int)abLookup[((i>>1) & ~7) | (i & 7)]; } } else { if (ch < 0xff21) { if (ch < 0x24b6) { *pch += 16; } else { *pch += 26; } } else { *pch += 32; } } } } else { // These are Unicode Number Forms. They have lowercase counter- // parts, but are not considered uppercase. Why, I don't know. if (InRange(ch, 0x2160, 0x216f)) { *pch += 16; } } } return cchLength; } // // BUGBUG - Do CharNextWrap and CharPrevWrap need to call the // CharNextW, CharPrevW on WinNT? Couldn't these be MACROS? LPWSTR CharNextWrap(LPCWSTR lpszCurrent) { if (*lpszCurrent) { return (LPWSTR) lpszCurrent + 1; } else { return (LPWSTR) lpszCurrent; } } LPWSTR CharPrevWrap(LPCWSTR lpszStart, LPCWSTR lpszCurrent) { if (lpszCurrent == lpszStart) { return (LPWSTR) lpszStart; } else { return (LPWSTR) lpszCurrent - 1; } } BOOL CharToOemWrap(LPCWSTR lpszSrc, LPSTR lpszDst) { CStrIn str(lpszSrc); return CharToOemA(str, lpszDst); } //---------------------------------------------------------------------- // // function: CharUpperWrap( LPWSTR pch ) // // purpose: Converts character to uppercase. Takes either a pointer // to a string, or a character masquerading as a pointer. // In the later case, the HIWORD must be zero. This is // as spec'd for Win32. // // returns: Uppercased character or string. In the string case, // the uppercasing is done inplace. // //---------------------------------------------------------------------- LPWSTR CharUpperWrap( LPWSTR pch ) { if (!HIWORD64(pch)) { WCHAR ch = (WCHAR)(LONG_PTR)pch; CharUpperBuffWrap( &ch, 1 ); pch = (LPWSTR)MAKEINTATOM(ch); } else { CharUpperBuffWrap( pch, lstrlenW(pch) ); } return pch; } //---------------------------------------------------------------------- // // function: CharUpperBuffWrap( LPWSTR pch, DWORD cch ) // // purpose: Converts a string to uppercase. String must be cch // characters in length. Note that this function is // is messier that CharLowerBuffWrap, and the reason for // this is many Unicode characters are considered uppercase, // even when they don't have an uppercase counterpart. // // returns: Character count (cch). The uppercasing is done inplace. // //---------------------------------------------------------------------- DWORD CharUpperBuffWrap( LPWSTR pch, DWORD cchLength ) { DWORD cch; for ( cch = cchLength; cch-- ; pch++ ) { WCHAR ch = *pch; if (IsCharLowerWrap(ch)) { if (ch < 0x00ff) { *pch -= ((ch != 0xdf) << 5); } else if (ch < 0x03b1) { if (ch < 0x01f5) { if (ch < 0x01ce) { if (ch < 0x017f) { if (ch < 0x0101) { *pch += 121; } else { *pch -= (ch != 0x0131 && ch != 0x0138 && ch != 0x0149); } } else if (ch < 0x01c9) { static const BYTE abMask[] = { // 6543210f edcba987 0xfc, 0xbf, // 11111100 10111111 0xbf, 0x67, // 10111111 01100111 0xff, 0xef, // 11111111 11101111 0xff, 0xf7, // 11111111 11110111 0xbf, 0xfd // 10111111 11111101 }; int i = ch - 0x017f; *pch -= ((abMask[i>>3] >> (i&7)) & 1) + (ch == 0x01c6); } else { *pch -= ((ch != 0x01cb)<<1); } } else { if (ch < 0x01df) { if (ch < 0x01dd) { *pch -= 1; } else { *pch -= 79; } } else { *pch -= 1 + (ch == 0x01f3) - InRange(ch,0x01f0,0x01f2); } } } else if (ch < 0x0253) { *pch -= (ch < 0x0250); } else if (ch < 0x03ac) { static const BYTE abLookup[] = {// 0/8 1/9 2/a 3/b 4/c 5/d 6/e 7/f /* 0x0253-0x0257 */ 210, 206, 0, 205, 205, /* 0x0258-0x025f */ 0, 202, 0, 203, 0, 0, 0, 0, /* 0x0260-0x0267 */ 205, 0, 0, 207, 0, 0, 0, 0, /* 0x0268-0x026f */ 209, 211, 0, 0, 0, 0, 0, 211, /* 0x0270-0x0277 */ 0, 0, 213, 0, 0, 214, 0, 0, /* 0x0278-0x027f */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x0280-0x0287 */ 0, 0, 0, 218, 0, 0, 0, 0, /* 0x0288-0x028f */ 218, 0, 217, 217, 0, 0, 0, 0, /* 0x0290-0x0297 */ 0, 0, 219 }; if (ch <= 0x0292) { *pch -= abLookup[ch - 0x0253]; } } else { *pch -= (ch == 0x03b0) ? 0 : (37 + (ch == 0x03ac)); } } else { if (ch < 0x0561) { if (ch < 0x0451) { if (ch < 0x03e3) { if (ch < 0x03cc) { *pch -= (ch != 0x03c2)<<5; } else { int i = (ch < 0x03d0); *pch -= (i<<6) - i + (ch == 0x03cc); } } else if (ch < 0x0430) { *pch -= (ch < 0x03f0); } else { *pch -= 32; } } else if (ch < 0x0461) { *pch -= 80; } else { *pch -= 1; } } else { if (ch < 0x1fb0) { if (ch < 0x1f70) { if (ch < 0x1e01) { int i = ch != 0x0587 && ch != 0x10f6; *pch -= ((i<<5)+(i<<4)); /* 48 */ } else if (ch < 0x1f00) { *pch -= !InRange(ch, 0x1e96, 0x1e9a); } else { int i = !InRange(ch, 0x1f50, 0x1f56)||(ch & 1); *pch += (i<<3); } } else { static const BYTE abLookup[] = { 74, 86, 86, 100, 128, 112, 126 }; if ( ch <= 0x1f7d ) { *pch += abLookup[(ch-0x1f70)>>1]; } } } else { if (ch < 0x24d0) { if (ch < 0x1fe5) { *pch += (0x0023 & (1<<(ch&15))) ? 8 : 0; } else if (ch < 0x2170) { *pch += (0x0023 & (1<<(ch&15))) ? 7 : 0; } else { *pch -= ((ch > 0x24b5)<<4); } } else if (ch < 0xff41) { int i = !InRange(ch, 0xfb00, 0xfb17); *pch -= (i<<4)+(i<<3)+(i<<1); /* 26 */ } else { *pch -= 32; } } } } } else { int i = InRange(ch, 0x2170, 0x217f); *pch -= (i<<4); } } return cchLength; } int CopyAcceleratorTableWrap( HACCEL hAccelSrc, LPACCEL lpAccelDst, int cAccelEntries) { return CopyAcceleratorTableA(hAccelSrc, lpAccelDst, cAccelEntries); } HACCEL CreateAcceleratorTableWrap(LPACCEL lpAccel, int cEntries) { return CreateAcceleratorTableA(lpAccel, cEntries); } typedef HDC (*FnCreateHDCA)(LPCSTR, LPCSTR, LPCSTR, CONST DEVMODEA *); HDC CreateHDCWrap( LPCWSTR lpszDriver, LPCWSTR lpszDevice, LPCWSTR lpszOutput, CONST DEVMODEW * lpInitData, FnCreateHDCA pfn) { DEVMODEA * pdevmode = NULL; CStrIn strDriver(lpszDriver); CStrIn strDevice(lpszDevice); CStrIn strOutput(lpszOutput); HDC hdcReturn = 0; if (lpInitData) { pdevmode = (DEVMODEA *) LocalAlloc( LPTR, lpInitData->dmSize + lpInitData->dmDriverExtra ); if (pdevmode) { MbcsFromUnicode((CHAR *)pdevmode->dmDeviceName, CCHDEVICENAME, lpInitData->dmDeviceName); memcpy(&pdevmode->dmSpecVersion, &lpInitData->dmSpecVersion, FIELD_OFFSET(DEVMODEW,dmFormName) - FIELD_OFFSET(DEVMODEW,dmSpecVersion)); MbcsFromUnicode((CHAR *)pdevmode->dmFormName, CCHFORMNAME, lpInitData->dmFormName); memcpy(&pdevmode->dmLogPixels, &lpInitData->dmLogPixels, lpInitData->dmDriverExtra + lpInitData->dmSize - FIELD_OFFSET(DEVMODEW, dmLogPixels)); pdevmode->dmSize -= (sizeof(BCHAR) - sizeof(char)) * (CCHDEVICENAME + CCHFORMNAME); } } hdcReturn = (*pfn)(strDriver, strDevice, strOutput, pdevmode); if (pdevmode) { LocalFree(pdevmode); } return hdcReturn; } HDC CreateDCWrap( LPCWSTR lpszDriver, LPCWSTR lpszDevice, LPCWSTR lpszOutput, CONST DEVMODEW * lpInitData) { return CreateHDCWrap(lpszDriver, lpszDevice, lpszOutput, lpInitData, CreateDCA); } HDC CreateICWrap( LPCWSTR lpszDriver, LPCWSTR lpszDevice, LPCWSTR lpszOutput, CONST DEVMODEW * lpInitData) { return CreateHDCWrap(lpszDriver, lpszDevice, lpszOutput, lpInitData, CreateICA); } BOOL CreateDirectoryWrap( LPCWSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes) { CStrIn str(lpPathName); ASSERT(!lpSecurityAttributes); return CreateDirectoryA(str, lpSecurityAttributes); } HANDLE CreateEventWrap( LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCWSTR lpName) { return CreateEventA(lpEventAttributes, bManualReset, bInitialState, (LPCSTR) lpName); } HANDLE CreateFileWrap( LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) { CStrIn str(lpFileName); return CreateFileA( str, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); } HANDLE CreateFileMappingWrap( HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect, DWORD dwMaxSizeHigh, DWORD dwMaxSizeLow, LPCWSTR lpName) { CStrIn str(lpName); return CreateFileMappingA( hFile, lpFileMappingAttributes, flProtect, dwMaxSizeHigh, dwMaxSizeLow, str); } HFONT CreateFontWrap( int nHeight, int nWidth, int nEscapement, int nOrientation, int fnWeight, DWORD fdwItalic, DWORD fdwUnderline, DWORD fdwStrikeOut, DWORD fdwCharSet, DWORD fdwOutputPrecision, DWORD fdwClipPrecision, DWORD fdwQuality, DWORD fdwPitchAndFamily, LPCWSTR lpszFace) { CStrIn str(lpszFace); return CreateFontA( nHeight, nWidth, nEscapement, nOrientation, fnWeight, fdwItalic, fdwUnderline, fdwStrikeOut, fdwCharSet, fdwOutputPrecision, fdwClipPrecision, fdwQuality, fdwPitchAndFamily, str); } HFONT CreateFontIndirectWrap(CONST LOGFONTW * plfw) { LOGFONTA lfa; HFONT hFont; memcpy(&lfa, plfw, FIELD_OFFSET(LOGFONTA, lfFaceName)); MbcsFromUnicode(lfa.lfFaceName, ARRAYSIZE(lfa.lfFaceName), plfw->lfFaceName); hFont = CreateFontIndirectA(&lfa); return hFont; } HWND CreateWindowExWrap( DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam) { CStrIn strClass(lpClassName); CStrIn strWindow(lpWindowName); return CreateWindowExA( dwExStyle, strClass, strWindow, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); } LRESULT DefWindowProcWrap(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { return DefWindowProcA(hWnd, msg, wParam, lParam); } BOOL DeleteFileWrap(LPCWSTR pwsz) { CStrIn str(pwsz); return DeleteFileA(str); } LRESULT DispatchMessageWrap(CONST MSG * lpMsg) { return DispatchMessageA(lpMsg); } #ifndef FONT_LINK int DrawTextWrap( HDC hDC, LPCWSTR lpString, int nCount, LPRECT lpRect, UINT uFormat) { CStrIn str(lpString, nCount); return DrawTextA(hDC, str, str.strlen(), lpRect, uFormat); } // shlwapi also have this. int DrawTextExPrivWrap( HDC hDC, LPWSTR lpString, int nCount, LPRECT lpRect, UINT uFormat, LPDRAWTEXTPARAMS lpDTParams) { CStrIn str(lpString, nCount); return DrawTextExA(hDC, str, str.strlen(), lpRect, uFormat, lpDTParams); } #endif struct EFFSTAT { LPARAM lParam; FONTENUMPROC lpEnumFontProc; BOOL fFamilySpecified; }; int CALLBACK EnumFontFamiliesCallbackWrap( ENUMLOGFONTA * lpelf, NEWTEXTMETRIC * lpntm, DWORD FontType, LPARAM lParam) { ENUMLOGFONTW elf; // Convert strings from ANSI to Unicode if (((EFFSTAT *)lParam)->fFamilySpecified && (FontType & TRUETYPE_FONTTYPE) ) { UnicodeFromMbcs( elf.elfFullName, ARRAYSIZE(elf.elfFullName), (LPCSTR) lpelf->elfFullName); UnicodeFromMbcs( elf.elfStyle, ARRAYSIZE(elf.elfStyle), (LPCSTR) lpelf->elfStyle); } else { elf.elfStyle[0] = L'\0'; elf.elfFullName[0] = L'\0'; } UnicodeFromMbcs( elf.elfLogFont.lfFaceName, ARRAYSIZE(elf.elfLogFont.lfFaceName), (LPCSTR) lpelf->elfLogFont.lfFaceName); // Copy the non-string data memcpy( &elf.elfLogFont, &lpelf->elfLogFont, FIELD_OFFSET(LOGFONTA, lfFaceName)); // Chain to the original callback function return (*((EFFSTAT *) lParam)->lpEnumFontProc)( (const LOGFONTW *) &elf, (const TEXTMETRICW *) lpntm, FontType, ((EFFSTAT *) lParam)->lParam); } int EnumFontFamiliesWrap( HDC hdc, LPCWSTR lpszFamily, FONTENUMPROC lpEnumFontProc, LPARAM lParam) { CStrIn str(lpszFamily); EFFSTAT effstat; effstat.lParam = lParam; effstat.lpEnumFontProc = lpEnumFontProc; effstat.fFamilySpecified = lpszFamily != NULL; return EnumFontFamiliesA( hdc, str, (FONTENUMPROCA) EnumFontFamiliesCallbackWrap, (LPARAM) &effstat); } int EnumFontFamiliesExWrap( HDC hdc, LPLOGFONTW lplfw, FONTENUMPROC lpEnumFontProc, LPARAM lParam, DWORD dwFlags ) { LOGFONTA lfa; CStrIn str(lplfw->lfFaceName); EFFSTAT effstat; ASSERT( FIELD_OFFSET(LOGFONTW, lfFaceName) == FIELD_OFFSET(LOGFONTA, lfFaceName) ); memcpy( &lfa, lplfw, sizeof(LOGFONTA) - FIELD_OFFSET(LOGFONTA, lfFaceName) ); memcpy( lfa.lfFaceName, str, LF_FACESIZE ); effstat.lParam = lParam; effstat.lpEnumFontProc = lpEnumFontProc; effstat.fFamilySpecified = lplfw->lfFaceName != NULL; return EnumFontFamiliesExA( hdc, &lfa, (FONTENUMPROCA) EnumFontFamiliesCallbackWrap, (LPARAM) &effstat, dwFlags ); } BOOL EnumResourceNamesWrap( HINSTANCE hModule, LPCWSTR lpType, ENUMRESNAMEPROCW lpEnumFunc, LONG lParam) { ASSERT(HIWORD64(lpType) == 0); return EnumResourceNamesA(hModule, (LPCSTR) lpType, (ENUMRESNAMEPROCA)lpEnumFunc, lParam); } #ifndef FONT_LINK // // There's an app that patches Win95 GDI and their ExtTextOutW handler // is broken. It always dereferences the lpStr parameter, even if // cb is zero. Consequently, any time we are about to pass NULL as // the lpStr, we have to change our mind and pass a null UNICODE string // instead. // // The name of this app: Lotus SmartSuite ScreenCam 97. // BOOL ExtTextOutWrap(HDC hdc, int x, int y, UINT fuOptions, CONST RECT *lprc, LPCWSTR lpStr, UINT cch, CONST INT *lpDx) { // Force a thunk to ANSI if running Win95 + ME if (g_fMEEnabled && !g_bRunOnMemphis) { CStrIn str(lpStr, cch); return ExtTextOutA(hdc, x, y, fuOptions, lprc, str, str.strlen(), lpDx); } else { if (lpStr == NULL) // workaround lpStr = TEXT(""); // for ScreenCam 97 return ExtTextOutW(hdc, x, y, fuOptions, lprc, lpStr, cch, lpDx); } } #endif HANDLE FindFirstFileWrap( LPCWSTR lpFileName, LPWIN32_FIND_DATAW pwszFd) { CStrIn str(lpFileName); WIN32_FIND_DATAA fd; HANDLE ret; memcpy(&fd, pwszFd, sizeof(FILETIME)*3+sizeof(DWORD)*5); ret = FindFirstFileA(str, &fd); memcpy(pwszFd, &fd, sizeof(FILETIME)*3+sizeof(DWORD)*5); UnicodeFromMbcs(pwszFd->cFileName, ARRAYSIZE(pwszFd->cFileName), fd.cFileName); UnicodeFromMbcs(pwszFd->cAlternateFileName, ARRAYSIZE(pwszFd->cAlternateFileName), fd.cAlternateFileName); return ret; } // // Although Win95 implements FindResource[Ex]W, its implementation is buggy // if you pass a string parameter, so we must thunk to the ANSI side. // // The bug is that FindResource[Ex]W will accidentally // call LocalFree(lpName) and LocalFree(lpType), so if lpName and lpType // point to heap memory, Kernel32 secretly freed your memory and you fault // five minutes later. // HRSRC FindResourceExWrap(HINSTANCE hModule, LPCWSTR lpType, LPCWSTR lpName, WORD wLang) { CStrIn strType(lpType); // rlefile.cpp passes TEXT("AVI") CStrIn strName(lpName); return FindResourceExA(hModule, strType, strName, wLang); } HWND FindWindowWrap(LPCWSTR lpClassName, LPCWSTR lpWindowName) { CStrIn strClass(lpClassName); CStrIn strWindow(lpWindowName); return FindWindowA(strClass, strWindow); } DWORD FormatMessageWrap( DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPWSTR lpBuffer, DWORD nSize, va_list * Arguments) { //This assert is only valid on Windows 95. ASSERT(!(dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER)); CStrOut str(lpBuffer, nSize); FormatMessageA( dwFlags, lpSource, dwMessageId, dwLanguageId, str, str.BufSize(), Arguments); return str.ConvertExcludingNul(); } BOOL GetClassInfoWrap(HINSTANCE hModule, LPCWSTR lpClassName, LPWNDCLASSW lpWndClassW) { BOOL ret; CStrIn strClassName(lpClassName); ASSERT(sizeof(WNDCLASSA) == sizeof(WNDCLASSW)); ret = GetClassInfoA(hModule, strClassName, (LPWNDCLASSA) lpWndClassW); lpWndClassW->lpszMenuName = NULL; lpWndClassW->lpszClassName = NULL; return ret; } DWORD GetClassLongWrap(HWND hWnd, int nIndex) { return GetClassLongA(hWnd, nIndex); } int GetClassNameWrap(HWND hWnd, LPWSTR lpClassName, int nMaxCount) { CStrOut strClassName(lpClassName, nMaxCount); GetClassNameA(hWnd, strClassName, strClassName.BufSize()); return strClassName.ConvertIncludingNul(); } int GetClipboardFormatNameWrap(UINT format, LPWSTR lpFormatName, int cchFormatName) { CStrOut strFormatName(lpFormatName, cchFormatName); GetClipboardFormatNameA(format, strFormatName, strFormatName.BufSize()); return strFormatName.ConvertIncludingNul(); } DWORD GetCurrentDirectoryWrap(DWORD nBufferLength, LPWSTR lpBuffer) { CStrOut str(lpBuffer, nBufferLength); GetCurrentDirectoryA(str.BufSize(), str); return str.ConvertExcludingNul(); } int GetDateFormatWrap( LCID Locale, DWORD dwFlags, CONST SYSTEMTIME *lpDate, LPCWSTR lpFormat, LPWSTR lpDateStr, int cchDate) { CStrIn strFormat(lpFormat); CStrOut str(lpDateStr, cchDate); ASSERT(cchDate != 0 || lpDateStr == NULL); int iRc = GetDateFormatA(Locale, dwFlags, lpDate, strFormat, str, str.BufSize()); // If app was merely querying, then return size and stop if (!str) return iRc; return str.ConvertIncludingNul(); } UINT GetDlgItemTextWrap( HWND hWndDlg, int idControl, LPWSTR lpsz, int cchMax) { CStrOut str(lpsz, cchMax); GetDlgItemTextA(hWndDlg, idControl, str, str.BufSize()); return str.ConvertExcludingNul(); } DWORD GetFileAttributesWrap(LPCWSTR lpFileName) { CStrIn str(lpFileName); return GetFileAttributesA(str); } int GetKeyNameTextWrap(LONG lParam, LPWSTR lpsz, int nSize) { CStrOut str(lpsz, nSize); GetKeyNameTextA(lParam, str, str.BufSize()); return str.ConvertExcludingNul(); } int GetLocaleInfoWrap(LCID Locale, LCTYPE LCType, LPWSTR lpsz, int cchData) { CStrOut str(lpsz, cchData); GetLocaleInfoA(Locale, LCType, str, str.BufSize()); return str.ConvertIncludingNul(); } BOOL GetMenuItemInfoWrap( HMENU hMenu, UINT uItem, BOOL fByPosition, LPMENUITEMINFOW lpmiiW) { BOOL fRet; ASSERT( sizeof(MENUITEMINFOW) == sizeof(MENUITEMINFOA) && FIELD_OFFSET(MENUITEMINFOW, dwTypeData) == FIELD_OFFSET(MENUITEMINFOA, dwTypeData) ); if ( (MIIM_TYPE & lpmiiW->fMask) && 0 == (lpmiiW->fType & (MFT_BITMAP | MFT_SEPARATOR))) { MENUITEMINFOA miiA; CStrOut str(lpmiiW->dwTypeData, lpmiiW->cch); memcpy( &miiA, lpmiiW, sizeof(MENUITEMINFOA) ); miiA.dwTypeData = str; miiA.cch = str.BufSize(); fRet = GetMenuItemInfoA( hMenu, uItem, fByPosition, &miiA ); memcpy(lpmiiW, &miiA, FIELD_OFFSET(MENUITEMINFOW, dwTypeData)); } else { fRet = GetMenuItemInfoA( hMenu, uItem, fByPosition, (LPMENUITEMINFOA)lpmiiW ); } return fRet; } int GetMenuStringWrap( HMENU hMenu, UINT uIDItem, LPWSTR lpString, int nMaxCount, UINT uFlag) { CStrOut str(lpString, nMaxCount); GetMenuStringA(hMenu, uIDItem, str, str.BufSize(), uFlag); return str.ConvertExcludingNul(); } BOOL GetMessageWrap( LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax) { return GetMessageA(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); } DWORD GetModuleFileNameWrap(HINSTANCE hModule, LPWSTR pwszFilename, DWORD nSize) { CStrOut str(pwszFilename, nSize); GetModuleFileNameA(hModule, str, str.BufSize()); return str.ConvertIncludingNul(); } int GetNumberFormatWrap( LCID Locale, DWORD dwFlags, LPCWSTR lpValue, CONST NUMBERFMTW *lpFormat, LPWSTR lpNumberStr, int cchNumber) { CStrIn strValue(lpValue); CStrOut str(lpNumberStr, cchNumber); ASSERT(cchNumber != 0); NUMBERFMTA nfA; CopyMemory(&nfA, lpFormat, sizeof(nfA)); CStrIn strDec(lpFormat->lpDecimalSep); nfA.lpDecimalSep = strDec; CStrIn strThou(lpFormat->lpThousandSep); nfA.lpThousandSep = strThou; GetNumberFormatA(Locale, dwFlags, strValue, &nfA, str, str.BufSize()); return str.ConvertIncludingNul(); } UINT GetSystemDirectoryWrap(LPWSTR lpBuffer, UINT uSize) { CStrOut str(lpBuffer, uSize); GetSystemDirectoryA(str, str.BufSize()); return str.ConvertExcludingNul(); } DWORD SearchPathWrap( LPCWSTR lpPathName, LPCWSTR lpFileName, LPCWSTR lpExtension, DWORD cchReturnBuffer, LPWSTR lpReturnBuffer, LPWSTR * plpfilePart) { CStrIn strPath(lpPathName); CStrIn strFile(lpFileName); CStrIn strExtension(lpExtension); CStrOut strReturnBuffer(lpReturnBuffer, cchReturnBuffer); DWORD dwLen = SearchPathA( strPath, strFile, strExtension, strReturnBuffer.BufSize(), strReturnBuffer, (LPSTR *)plpfilePart); // // Getting the correct value for plpfilePart requires // a strrchr on the converted string. If this value // is needed, just add the code to do it here. // *plpfilePart = NULL; if (cchReturnBuffer == 0) dwLen = 2*dwLen; else dwLen = strReturnBuffer.ConvertExcludingNul(); return dwLen; } HMODULE GetModuleHandleWrap(LPCWSTR lpModuleName) { CStrIn str(lpModuleName); return GetModuleHandleA(str); } int GetObjectWrap(HGDIOBJ hgdiObj, int cbBuffer, LPVOID lpvObj) { int nRet; if(cbBuffer != sizeof(LOGFONTW)) { nRet = GetObjectA(hgdiObj, cbBuffer, lpvObj); } else { LOGFONTA lfa; nRet = GetObjectA(hgdiObj, sizeof(lfa), &lfa); if (nRet > 0) { memcpy(lpvObj, &lfa, FIELD_OFFSET(LOGFONTW, lfFaceName)); UnicodeFromMbcs(((LOGFONTW*)lpvObj)->lfFaceName, ARRAYSIZE(((LOGFONTW*)lpvObj)->lfFaceName), lfa.lfFaceName, -1); nRet = sizeof(LOGFONTW); } } return nRet; } //-------------------------------------------------------------- // GetFullPathNameWrap //-------------------------------------------------------------- DWORD GetFullPathNameWrap( LPCWSTR lpFileName, DWORD nBufferLength, LPWSTR lpBuffer, LPWSTR *lpFilePart) { CStrIn strIn(lpFileName); CStrOut strOut(lpBuffer,nBufferLength); LPSTR pFile; DWORD dwRet; dwRet = GetFullPathNameA(strIn, nBufferLength, strOut, &pFile); strOut.ConvertIncludingNul(); *lpFilePart = lpBuffer + (pFile - strOut); return dwRet; } BOOL GetStringTypeExWrap(LCID lcid, DWORD dwInfoType, LPCTSTR lpSrcStr, int cchSrc, LPWORD lpCharType) { CStrIn str(lpSrcStr, cchSrc); return GetStringTypeExA(lcid, dwInfoType, str, str.strlen(), lpCharType); } UINT GetPrivateProfileIntWrap( LPCWSTR lpAppName, LPCWSTR lpKeyName, INT nDefault, LPCWSTR lpFileName) { CStrIn strApp(lpAppName); CStrIn strKey(lpKeyName); CStrIn strFile(lpFileName); return GetPrivateProfileIntA(strApp, strKey, nDefault, strFile); } UINT GetProfileIntWrap( LPCWSTR lpAppName, LPCWSTR lpKeyName, INT nDefault) { CStrIn strApp(lpAppName); CStrIn strKey(lpKeyName); return GetProfileIntA(strApp, strKey, nDefault); } DWORD GetProfileStringWrap( LPCWSTR lpAppName, LPCWSTR lpKeyName, LPCWSTR lpDefault, LPWSTR lpBuffer, DWORD dwBuffersize) { CStrIn strApp(lpAppName); CStrIn strKey(lpKeyName); CStrIn strDefault(lpDefault); CStrOut strBuffer(lpBuffer, dwBuffersize); GetProfileStringA(strApp, strKey, strDefault, strBuffer, dwBuffersize); return strBuffer.ConvertIncludingNul(); } HANDLE GetPropWrap(HWND hWnd, LPCWSTR lpString) { CStrIn str(lpString); return GetPropA(hWnd, str); } UINT GetTempFileNameWrap( LPCWSTR lpPathName, LPCWSTR lpPrefixString, UINT uUnique, LPWSTR lpTempFileName) { CStrIn strPath(lpPathName); CStrIn strPrefix(lpPrefixString); CStrOut strFileName(lpTempFileName, MAX_PATH); return GetTempFileNameA(strPath, strPrefix, uUnique, strFileName); } DWORD GetTempPathWrap(DWORD nBufferLength, LPWSTR lpBuffer) { CStrOut str(lpBuffer, nBufferLength); GetTempPathA(str.BufSize(), str); return str.ConvertExcludingNul(); } #ifndef FONT_LINK BOOL GetTextExtentPointWrap( HDC hdc, LPCWSTR pwsz, int cb, LPSIZE pSize) { CStrIn str(pwsz,cb); return GetTextExtentPointA(hdc, str, str.strlen(), pSize); } BOOL GetTextExtentPoint32Wrap( HDC hdc, LPCWSTR pwsz, int cb, LPSIZE pSize) { CStrIn str(pwsz,cb); return GetTextExtentPoint32A(hdc, str, str.strlen(), pSize); } #endif int GetTextFaceWrap( HDC hdc, int cch, LPWSTR lpFaceName) { CStrOut str(lpFaceName, cch); GetTextFaceA(hdc, str.BufSize(), str); return str.ConvertIncludingNul(); } BOOL GetTextMetricsWrap(HDC hdc, LPTEXTMETRICW lptm) { BOOL ret; TEXTMETRICA tm; ret = GetTextMetricsA(hdc, &tm); if (ret) { lptm->tmHeight = tm.tmHeight; lptm->tmAscent = tm.tmAscent; lptm->tmDescent = tm.tmDescent; lptm->tmInternalLeading = tm.tmInternalLeading; lptm->tmExternalLeading = tm.tmExternalLeading; lptm->tmAveCharWidth = tm.tmAveCharWidth; lptm->tmMaxCharWidth = tm.tmMaxCharWidth; lptm->tmWeight = tm.tmWeight; lptm->tmOverhang = tm.tmOverhang; lptm->tmDigitizedAspectX = tm.tmDigitizedAspectX; lptm->tmDigitizedAspectY = tm.tmDigitizedAspectY; lptm->tmItalic = tm.tmItalic; lptm->tmUnderlined = tm.tmUnderlined; lptm->tmStruckOut = tm.tmStruckOut; lptm->tmPitchAndFamily = tm.tmPitchAndFamily; lptm->tmCharSet = tm.tmCharSet; UnicodeFromMbcs(&lptm->tmFirstChar, 1, (LPSTR) &tm.tmFirstChar, 1); UnicodeFromMbcs(&lptm->tmLastChar, 1, (LPSTR) &tm.tmLastChar, 1); UnicodeFromMbcs(&lptm->tmDefaultChar, 1, (LPSTR) &tm.tmDefaultChar, 1); UnicodeFromMbcs(&lptm->tmBreakChar, 1, (LPSTR) &tm.tmBreakChar, 1); } return ret; } int GetTimeFormatWrap( LCID Locale, DWORD dwFlags, CONST SYSTEMTIME *lpTime, LPCWSTR lpFormat, LPWSTR lpTimeStr, int cchTime) { CStrIn strFormat(lpFormat); CStrOut str(lpTimeStr, cchTime); ASSERT(cchTime != 0); GetTimeFormatA(Locale, dwFlags, lpTime, strFormat, str, str.BufSize()); return str.ConvertIncludingNul(); } LONG GetWindowLongWrap(HWND hWnd, int nIndex) { return GetWindowLongA(hWnd, nIndex); } int GetWindowTextWrap(HWND hWnd, LPWSTR lpString, int nMaxCount) { CStrOut str(lpString, nMaxCount); GetWindowTextA(hWnd, str, str.BufSize()); return str.ConvertExcludingNul(); } int GetWindowTextLengthWrap(HWND hWnd) { WCHAR wstr[MAX_PATH]; return GetWindowTextWrap(hWnd, wstr, ARRAYSIZE(wstr)); } UINT GetWindowsDirectoryWrap(LPWSTR lpWinPath, UINT cch) { CStrOut str(lpWinPath, cch); GetWindowsDirectoryA(str, str.BufSize()); return str.ConvertExcludingNul(); } ATOM GlobalAddAtomWrap(LPCWSTR lpString) { CStrIn str(lpString); return GlobalAddAtomA(str); } BOOL GrayStringWrap( HDC hDC, HBRUSH hBrush, GRAYSTRINGPROC lpOutputFunc, LPARAM lpData, int nCount, int x, int y, int nWidth, int nHeight) { CStrIn str((LPWSTR)lpData); return GrayStringA(hDC, hBrush, lpOutputFunc, (LPARAM)(LPCSTR)str, str.strlen(), x, y, nWidth, nHeight); } LONG ImmGetCompositionStringWrap(HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen) { int cb = 0; if ((dwIndex & GCS_COMPSTR) || (dwIndex & GCS_RESULTSTR)) { if (dwBufLen) { CStrOut str((LPWSTR)lpBuf, dwBufLen/sizeof(WCHAR) + 1); cb = ImmGetCompositionStringA(hIMC, dwIndex, str, str.BufSize()); *(WCHAR*)((LPSTR)str + cb) = L'\0'; return str.ConvertExcludingNul() * sizeof(WCHAR); } else { LPWSTR lpStr; cb = ImmGetCompositionStringA(hIMC, dwIndex, lpBuf, dwBufLen); lpStr = (LPWSTR)LocalAlloc(LPTR, (cb + 1) * sizeof(WCHAR)); if (lpStr) { CStrOut str(lpStr, cb + 1); cb = ImmGetCompositionStringA(hIMC, dwIndex, str, str.BufSize()); *(WCHAR*)((LPSTR)str + cb) = L'\0'; cb = str.ConvertExcludingNul() * sizeof(WCHAR); LocalFree(lpStr); return cb; } } } else if (dwIndex & GCS_COMPATTR) { if (dwBufLen) { LPSTR lpStr, lpAttr; UINT i = 0; lpStr = (LPSTR)LocalAlloc(LPTR, dwBufLen); if (lpStr) { lpAttr = (LPSTR)LocalAlloc(LPTR, dwBufLen); if (lpAttr) { LPSTR lpNext = lpStr; cb = ImmGetCompositionStringA(hIMC, GCS_COMPSTR, lpStr, dwBufLen); ImmGetCompositionStringA(hIMC, GCS_COMPATTR, lpAttr, dwBufLen); for (i = 0; (lpNext - lpStr < cb) && (i < dwBufLen); i++) { ((LPSTR)lpBuf)[i] = lpAttr[lpNext - lpStr]; lpNext = CharNextA(lpNext); } LocalFree(lpAttr); } LocalFree(lpStr); } return i; } } return ImmGetCompositionStringA(hIMC, dwIndex, lpBuf, dwBufLen); } LONG ImmSetCompositionStringWrap(HIMC hIMC, DWORD dwIndex, LPVOID lpComp, DWORD dwCompLen, LPVOID lpRead, DWORD dwReadLen) { if (dwIndex & SCS_SETSTR) { CStrIn str((LPWSTR)lpComp); ASSERT(!lpRead); return ImmSetCompositionStringA(hIMC, dwIndex, str, str.strlen(), lpRead, dwReadLen); } return ImmSetCompositionStringA(hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen); } BOOL InsertMenuWrap( HMENU hMenu, UINT uPosition, UINT uFlags, UINT uIDNewItem, LPCWSTR lpNewItem) { CStrIn str(lpNewItem); return InsertMenuA(hMenu, uPosition, uFlags, uIDNewItem, str); } BOOL IsDialogMessageWrap(HWND hWndDlg, LPMSG lpMsg) { return IsDialogMessageA(hWndDlg, lpMsg); } HACCEL LoadAcceleratorsWrap(HINSTANCE hInstance, LPCWSTR lpTableName) { CStrIn str(lpTableName); return LoadAcceleratorsA(hInstance, (LPCSTR) str); } HBITMAP LoadBitmapWrap(HINSTANCE hInstance, LPCWSTR lpBitmapName) { CStrIn str(lpBitmapName); return LoadBitmapA(hInstance, str); } HCURSOR LoadCursorWrap(HINSTANCE hInstance, LPCWSTR lpCursorName) { CStrIn str(lpCursorName); return LoadCursorA(hInstance, (LPCSTR) str); } HICON LoadIconWrap(HINSTANCE hInstance, LPCWSTR lpIconName) { CStrIn str(lpIconName); return LoadIconA(hInstance, str); } HANDLE LoadImageWrap( HINSTANCE hInstance, LPCWSTR lpName, UINT uType, int cxDesired, int cyDesired, UINT fuLoad) { CStrIn str(lpName); return LoadImageA( hInstance, str, uType, cxDesired, cyDesired, fuLoad); } HINSTANCE LoadLibraryWrap(LPCWSTR lpLibFileName) { CStrIn str(lpLibFileName); return LoadLibraryA(str); } HINSTANCE LoadLibraryExWrap( LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) { CStrIn str(lpLibFileName); return LoadLibraryExA(str, hFile, dwFlags); } HMENU LoadMenuWrap(HINSTANCE hInstance, LPCWSTR lpMenuName) { ASSERT(HIWORD64(lpMenuName) == 0); return LoadMenuA(hInstance, (LPCSTR) lpMenuName); } int LoadStringWrap(HINSTANCE hInstance, UINT uID, LPWSTR lpBuffer, int nBufferMax) { // // Do it manually. The old code used to call LoadStringA and then // convert it up to unicode, which is bad since resources are // physically already Unicode! Just copy it out directly. // if (nBufferMax <= 0) return 0; // sanity check PWCHAR pwch; /* * String tables are broken up into "bundles" of 16 strings each. */ HRSRC hrsrc; int cwch = 0; hrsrc = FindResourceA(hInstance, (LPSTR)(LONG_PTR)(1 + uID / 16), (LPSTR)RT_STRING); if (hrsrc) { pwch = (PWCHAR)LoadResource(hInstance, hrsrc); if (pwch) { /* * Now skip over the strings in the resource until we * hit the one we want. Each entry is a counted string, * just like Pascal. */ for (uID %= 16; uID; uID--) { pwch += *pwch + 1; } cwch = min(*pwch, nBufferMax - 1); memcpy(lpBuffer, pwch+1, cwch * sizeof(WCHAR)); /* Copy the goo */ } } lpBuffer[cwch] = L'\0'; /* Terminate the string */ return cwch; } UINT MapVirtualKeyWrap(UINT uCode, UINT uMapType) { return MapVirtualKeyA(uCode, uMapType); } //---------------------------------------------------------------------- // // function: TransformCharNoOp1( WCHAR **ppch ) // // purpose: Stand-in for TransformCharWidth. Used by the function // CompareStringString. // // returns: Character at *ppch. The value *ppch is incremented. // //---------------------------------------------------------------------- static WCHAR TransformCharNoOp1( LPCWSTR *ppch, int ) { WCHAR ch = **ppch; (*ppch)++; return ch; } //---------------------------------------------------------------------- // // function: TransformCharWidth( WCHAR **ppch, cchRemaining ) // // purpose: Converts halfwidth characters to fullwidth characters. // Also combines voiced (dakuon) and semi-voiced (handakuon) // characters. *pch is advanced by one, unless there is a // (semi)voiced character, in which case it is advanced by // two characters. // // Note that unlike the full widechar version, we do not // combine other characters, notably the combining Hiragana // characters (U+3099 and U+309A.) This is to keep the // tables from getting unnecessarily large. // // cchRemaining is passed so as to not include the voiced // marks if it's passed the end of the specified buffer. // // returns: Full width character. *pch is incremented. // //---------------------------------------------------------------------- static WCHAR TransformCharWidth( LPCWSTR *ppch, int cchRemaining ) { WCHAR ch = **ppch; (*ppch)++; if (ch == 0x0020) { ch = 0x3000; } else if (ch == 0x005c) { // REVERSE SOLIDUS (aka BACKSLASH) maps to itself } else if (InRange(ch, 0x0021, 0x07e)) { ch += 65248; } else if (InRange(ch, 0x00a2, 0x00af)) { static const WCHAR achFull[] = { 0xffe0, 0xffe1, 0x00a4, 0xffe5, 0xffe4, 0x00a7, 0x00a8, // 0xa2-0xa8 0x00a9, 0x00aa, 0x00ab, 0xffe2, 0x00ad, 0x00ae, 0xffe3 // 0xa9-0xaf }; ch = achFull[ch - 0x00a2]; } else if (ch == 0x20a9) // WON SIGN { ch = 0xffe6; } else if (InRange(ch, 0xff61, 0xffdc)) { WCHAR chNext = (cchRemaining > 1) ? **ppch : 0; if (chNext == 0xff9e && InRange(ch, 0xff73, 0xff8e)) { if (cchRemaining != 1) { static const WCHAR achFull[] = { /* 0xff73-0xff79 */ 0xb0f4, 0x30a8, 0x30aa, 0xb0ac, 0xb0ae, 0xb0b0, 0xb0b2, /* 0xff7a-0xff80 */ 0xb0b4, 0xb0b6, 0xb0b8, 0xb0ba, 0xb0bc, 0xb0be, 0xb0c0, /* 0xff81-0xff87 */ 0xb0c2, 0xb0c5, 0xb0c7, 0xb0c9, 0x30ca, 0x30cb, 0x30cc, /* 0xff88-0xff8e */ 0x30cd, 0x30ce, 0xb0d0, 0xb0d3, 0xb0d6, 0xb0d9, 0xb0dc }; // HALFWIDTH KATAKANA VOICED SOUND MARK WCHAR chTemp = achFull[ch - 0xff73]; // Some in the range absorb the sound mark. // These are indicated by the set high-bit. ch = chTemp & 0x7fff; if (chTemp & 0x8000) { (*ppch)++; } } } else if (chNext == 0xff9f && InRange(ch, 0xff8a, 0xff8e)) { // HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK ch = 0x30d1 + (ch - 0xff8a) * 3; (*ppch)++; } else { static const WCHAR achMapFullFFxx[] = { 0x3002, 0x300c, 0x300d, 0x3001, 0x30fb, 0x30f2, 0x30a1, // 0xff61-0xff67 0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30e3, 0x30e5, 0x30e7, // 0xff68-0xff6e 0x30c3, 0x30fc, 0x30a2, 0x30a4, 0x30a6, 0x30a8, 0x30aa, // 0xff6f-0xff75 0x30ab, 0x30ad, 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7, // 0xff76-0xff7c 0x30b9, 0x30bb, 0x30bd, 0x30bf, 0x30c1, 0x30c4, 0x30c6, // 0xff7d-0xff83 0x30c8, 0x30ca, 0x30cb, 0x30cc, 0x30cd, 0x30ce, 0x30cf, // 0xff84-0xff8a 0x30d2, 0x30d5, 0x30d8, 0x30db, 0x30de, 0x30df, 0x30e0, // 0xff8b-0xff91 0x30e1, 0x30e2, 0x30e4, 0x30e6, 0x30e8, 0x30e9, 0x30ea, // 0xff92-0xff98 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f3, 0x309b, 0x309c, // 0xff99-0xff9f 0x3164, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, // 0xffa0-0xffa6 0x3137, 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, // 0xffa7-0xffad 0x313e, 0x313f, 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, // 0xffae-0xffb4 0x3145, 0x3146, 0x3147, 0x3148, 0x3149, 0x314a, 0x314b, // 0xffb5-0xffbb 0x314c, 0x314d, 0x314e, 0xffbf, 0xffc0, 0xffc1, 0x314f, // 0xffbc-0xffc2 0x3150, 0x3151, 0x3152, 0x3153, 0x3154, 0xffc8, 0xffc9, // 0xffc3-0xffc9 0x3155, 0x3156, 0x3157, 0x3158, 0x3159, 0x315a, 0xffd0, // 0xffca-0xffd0 0xffd1, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, 0x3160, // 0xffd1-0xffd7 0xffd8, 0xffd9, 0x3161, 0x3162, 0x3163 // 0xffd8-0xffac }; ch = achMapFullFFxx[ch - 0xff61]; } } return ch; } //---------------------------------------------------------------------- // // function: TransformaCharNoOp2( WCHAR ch ) // // purpose: Stand-in for CharLowerBuffWrap. Used by the function // CompareStringString. // // returns: Original character // //---------------------------------------------------------------------- static WCHAR TransformCharNoOp2( WCHAR ch ) { return ch; } //---------------------------------------------------------------------- // // function: TransformaCharKana( WCHAR ch ) // // purpose: Converts Hiragana characters to Katakana characters // // returns: Original character if not Hiragana, // Katanaka character if Hiragana // //---------------------------------------------------------------------- static WCHAR TransformCharKana( WCHAR ch ) { if (((ch & 0xff00) == 0x3000) && (InRange(ch, 0x3041, 0x3094) || InRange(ch, 0x309d, 0x309e))) { ch += 0x060; } return ch; } //---------------------------------------------------------------------- // // function: TransformCharNoOp3( LPWSTR pch, DWORD cch ) // // purpose: Stand-in for CharLowerBuffWrap. Used by the function // CompareStringString. // // returns: Character count (cch). // //---------------------------------------------------------------------- static DWORD TransformCharNoOp3( LPWSTR, DWORD cch ) { return cch; } //---------------------------------------------------------------------- // // function: TransformaCharFinal( WCHAR ch ) // // purpose: Converts "final" forms to regular forms // // returns: Original character if not Hiragana, // Katanaka character if Hiragana // //---------------------------------------------------------------------- // BUGBUG (cthrash) We do not fold Presentation Forms (Alphabetic or Arabic) static WCHAR TransformCharFinal( WCHAR ch ) { WCHAR chRet = ch; if (ch >= 0x3c2) // short-circuit ASCII + { switch (ch) { case 0x03c2: // GREEK SMALL LETTER FINAL SIGMA case 0x05da: // HEBREW LETTER FINAL KAF case 0x05dd: // HEBREW LETTER FINAL MEM case 0x05df: // HEBREW LETTER FINAL NUN case 0x05e3: // HEBREW LETTER FINAL PE case 0x05e5: // HEBREW LETTER FINAL TSADI case 0xfb26: // HEBREW LETTER WIDE FINAL MEM case 0xfb3a: // HEBREW LETTER FINAL KAF WITH DAGESH case 0xfb43: // HEBREW LETTER FINAL PE WITH DAGESH chRet++; break; } } return ch; } //---------------------------------------------------------------------- // // function: CompareStringString( ... ) // // purpose: Helper for CompareStringWrap. // // We handle the string comparsion for CompareStringWrap. // We can convert each character to (1) fullwidth, // (2) Katakana, and (3) lowercase, as necessary. // // returns: 1 - string A is less in lexical value as string B // 2 - string B is equal in lexical value as string B // 3 - string B is greater in lexical value as string B // //---------------------------------------------------------------------- static int CompareStringString( DWORD dwFlags, LPCWSTR lpA, int cchA, LPCWSTR lpB, int cchB ) { int nRet = 0; WCHAR wchIgnoreNulA = cchA == -1 ? 0 : -1; WCHAR wchIgnoreNulB = cchB == -1 ? 0 : -1; WCHAR (*pfnTransformWidth)(LPCWSTR *, int); WCHAR (*pfnTransformKana)(WCHAR); DWORD (*pfnTransformLower)(LPWSTR, DWORD); WCHAR (*pfnTransformFinal)(WCHAR); pfnTransformWidth = (dwFlags & NORM_IGNOREWIDTH) ? TransformCharWidth : TransformCharNoOp1; pfnTransformKana = (dwFlags & NORM_IGNOREKANATYPE) ? TransformCharKana : TransformCharNoOp2; pfnTransformLower = (dwFlags & NORM_IGNORECASE) ? CharLowerBuffWrap : TransformCharNoOp3; pfnTransformFinal = (dwFlags & NORM_IGNORECASE) ? TransformCharFinal : TransformCharNoOp2; while ( !nRet && cchA && cchB && (*lpA | wchIgnoreNulA) && (*lpB | wchIgnoreNulB) ) { WCHAR chA, chB; LPCWSTR lpAOld = lpA; LPCWSTR lpBOld = lpB; chA = (*pfnTransformWidth)(&lpA, cchA); chA = (*pfnTransformKana)(chA); (*pfnTransformLower)(&chA, 1); chA = (*pfnTransformFinal)(chA); chB = (*pfnTransformWidth)(&lpB, cchB); chB = (*pfnTransformKana)(chB); (*pfnTransformLower)(&chB, 1); chB = (*pfnTransformFinal)(chB); nRet = (int)chA - (int)chB; cchA -= (int) (lpA-lpAOld); cchB -= (int) (lpB-lpBOld); } if (!nRet) { nRet = cchA - cchB; } if (nRet) { nRet = nRet > 0 ? 1 : -1; } return nRet + 2; } //---------------------------------------------------------------------- // // function: CompareStringWord( ... ) // // purpose: Helper for CompareStringWrap. // // We handle the word comparsion for CompareStringWrap. // // returns: 1 - string A is less in lexical value as string B // 2 - string B is equal in lexical value as string B // 3 - string B is greater in lexical value as string B // //---------------------------------------------------------------------- static int CompareStringWord( LCID lcid, DWORD dwFlags, LPCWSTR lpA, int cchA, LPCWSTR lpB, int cchB ) { // BUGBUG (cthrash) We won't properly support word compare for the // time being. Do the same old CP_ACP trick, which should cover // enough cases. // fail if either string is NULL, as it causes assert on debug windows if (!lpA || !lpB) return 0; CStrIn strA(lpA, cchA); CStrIn strB(lpB, cchB); cchA = strA.strlen(); cchB = strB.strlen(); return CompareStringA(lcid, dwFlags, strA, cchA, strB, cchB); } //---------------------------------------------------------------------- // // function: CompareStringWrap( ... ) // // purpose: Unicode wrapper of CompareString for Win95. // // Note not all bits in dwFlags are honored; specifically, // since we don't do a true widechar word compare, we // won't properly handle NORM_IGNORENONSPACE or // NORM_IGNORESYMBOLS for arbitrary widechar strings. // // returns: 1 - string A is less in lexical value as string B // 2 - string B is equal in lexical value as string B // 3 - string B is greater in lexical value as string B // //---------------------------------------------------------------------- LWSTDAPI_(int) CompareStringAltW( LCID lcid, DWORD dwFlags, LPCWSTR lpA, int cchA, LPCWSTR lpB, int cchB ) { int nRet; if (dwFlags & SORT_STRINGSORT) { nRet = CompareStringString(dwFlags, lpA, cchA, lpB, cchB); } else { nRet = CompareStringWord(lcid, dwFlags, lpA, cchA, lpB, cchB); } return nRet; } int CompareStringWrap( LCID Locale, DWORD dwCmpFlags, LPCWSTR lpString1, int cchCount1, LPCWSTR lpString2, int cchCount2) { // fail if either string is NULL, as it causes assert on debug windows if (!lpString1 || !lpString2) return 0; CStrIn strString1(lpString1, cchCount1); CStrIn strString2(lpString2, cchCount2); cchCount1 = strString1.strlen(); cchCount2 = strString2.strlen(); return CompareStringA(Locale, dwCmpFlags, strString1,cchCount1, strString2,cchCount2); } BOOL MessageBoxIndirectWrap(MSGBOXPARAMS *pmbp) { CStrIn strText(pmbp->lpszText); CStrIn strCaption(pmbp->lpszCaption); MSGBOXPARAMSA mbp; memcpy(&mbp, pmbp, sizeof(mbp)); mbp.lpszText = strText; mbp.lpszCaption = strCaption; ASSERT(HIWORD64(mbp.lpszIcon) == 0); return MessageBoxIndirectA(&mbp); } DWORD GetCharacterPlacementWrap( HDC hdc, // handle to device context LPCTSTR lpString, // pointer to string int nCount, // number of characters in string int nMaxExtent, // maximum extent for displayed string LPGCP_RESULTS lpResults, // pointer to buffer for placement result DWORD dwFlags // placement flags ) { CStrIn strText(lpString); DWORD dwRet; // Leave for someone else. ASSERT (lpResults->lpOutString == NULL); ASSERT (lpResults->lpClass == NULL); dwRet = GetCharacterPlacementA (hdc, strText, nCount, nMaxExtent, (LPGCP_RESULTSA)lpResults, dwFlags); return dwRet; } #ifndef FONT_LINK BOOL GetCharWidthWrap ( HDC hdc, UINT iFirstChar, UINT iLastChar, LPINT lpBuffer) { // Note that we expect to do only one character at a time for anything but // ISO Latin 1. if (iFirstChar > 255) { UINT mbChar=0; WCHAR ch; // Convert string ch = (WCHAR)iFirstChar; WideCharToMultiByte(CP_ACP, 0, &ch, 1, (char *)&mbChar, 2, NULL, NULL); } return (GetCharWidthA (hdc, iFirstChar, iLastChar, lpBuffer)); } #endif BOOL ModifyMenuWrap( HMENU hMenu, UINT uPosition, UINT uFlags, UINT uIDNewItem, LPCWSTR lpNewItem) { ASSERT(!(uFlags & MF_BITMAP) && !(uFlags & MF_OWNERDRAW)); CStrIn str(lpNewItem); return ModifyMenuA(hMenu, uPosition, uFlags, uIDNewItem, str); } BOOL CopyFileWrap(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, BOOL bFailIfExists) { CStrIn strOld(lpExistingFileName); CStrIn strNew(lpNewFileName); return CopyFileA(strOld, strNew, bFailIfExists); } BOOL MoveFileWrap(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName) { CStrIn strOld(lpExistingFileName); CStrIn strNew(lpNewFileName); return MoveFileA(strOld, strNew); } BOOL OemToCharWrap(LPCSTR lpszSrc, LPWSTR lpszDst) { CStrOut strDst(lpszDst, lstrlenA(lpszSrc)); return OemToCharA(lpszSrc, strDst); } VOID OutputDebugStringWrap(LPCWSTR lpOutputString) { CStrIn str(lpOutputString); OutputDebugStringA(str); } BOOL PeekMessageWrap( LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg) { return PeekMessageA(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); } BOOL PostMessageWrap( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { return PostMessageA(hWnd, Msg, wParam, lParam); } BOOL PostThreadMessageWrap( DWORD idThread, UINT Msg, WPARAM wParam, LPARAM lParam) { return PostThreadMessageA(idThread, Msg, wParam, lParam); } LONG RegCreateKeyWrap(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult) { CStrIn str(lpSubKey); return RegCreateKeyA(hKey, str, phkResult); } LONG RegCreateKeyExWrap(HKEY hKey, LPCTSTR lpSubKey, DWORD Reserved, LPTSTR lpClass, DWORD dwOptions, REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition) { CStrIn strSubKey(lpSubKey); CStrIn strClass(lpClass); return RegCreateKeyExA(hKey, strSubKey, Reserved, strClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition); } LONG RegDeleteKeyWrap(HKEY hKey, LPCWSTR pwszSubKey) { CStrIn str(pwszSubKey); return RegDeleteKeyA(hKey, str); } LONG RegEnumKeyWrap( HKEY hKey, DWORD dwIndex, LPWSTR lpName, DWORD cbName) { CStrOut str(lpName, cbName); return RegEnumKeyA(hKey, dwIndex, str, str.BufSize()); } LONG RegEnumKeyExWrap( HKEY hKey, DWORD dwIndex, LPWSTR lpName, LPDWORD lpcbName, LPDWORD lpReserved, LPWSTR lpClass, LPDWORD lpcbClass, PFILETIME lpftLastWriteTime) { long ret; DWORD dwClass = 0; if (!lpcbClass) { lpcbClass = &dwClass; } CStrOut strName(lpName, *lpcbName); CStrOut strClass(lpClass, *lpcbClass); ret = RegEnumKeyExA( hKey, dwIndex, strName, lpcbName, lpReserved, strClass, lpcbClass, lpftLastWriteTime); *lpcbName = strName.ConvertExcludingNul(); *lpcbClass = strClass.ConvertExcludingNul(); return ret; } LONG RegOpenKeyWrap(HKEY hKey, LPCWSTR pwszSubKey, PHKEY phkResult) { CStrIn str(pwszSubKey); return RegOpenKeyA(hKey, str, phkResult); } LONG RegOpenKeyExWrap( HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult) { CStrIn str(lpSubKey); return RegOpenKeyExA(hKey, str, ulOptions, samDesired, phkResult); } LONG RegQueryInfoKeyWrap( HKEY hKey, LPWSTR lpClass, LPDWORD lpcbClass, LPDWORD lpReserved, LPDWORD lpcSubKeys, LPDWORD lpcbMaxSubKeyLen, LPDWORD lpcbMaxClassLen, LPDWORD lpcValues, LPDWORD lpcbMaxValueNameLen, LPDWORD lpcbMaxValueLen, LPDWORD lpcbSecurityDescriptor, PFILETIME lpftLastWriteTime) { CStrIn str(lpClass); return RegQueryInfoKeyA( hKey, str, lpcbClass, lpReserved, lpcSubKeys, lpcbMaxSubKeyLen, lpcbMaxClassLen, lpcValues, lpcbMaxValueNameLen, lpcbMaxValueLen, lpcbSecurityDescriptor, lpftLastWriteTime); } LONG RegQueryValueWrap( HKEY hKey, LPCWSTR pwszSubKey, LPWSTR pwszValue, PLONG lpcbValue) { long ret; long cb; CStrIn strKey(pwszSubKey); CStrOut strValue(pwszValue, (*lpcbValue) / sizeof(WCHAR)); cb = strValue.BufSize(); ret = RegQueryValueA(hKey, strKey, strValue, &cb); if (ret != ERROR_SUCCESS) goto Cleanup; if (strValue) { cb = strValue.ConvertIncludingNul(); } *lpcbValue = cb * sizeof(WCHAR); Cleanup: return ret; } LONG RegQueryValueExWrap( HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData) { LONG ret; CStrIn strValueName(lpValueName); DWORD dwTempType; DWORD cb; // // Determine the type of buffer needed // ret = RegQueryValueExA(hKey, strValueName, lpReserved, &dwTempType, NULL, &cb); if (ret != ERROR_SUCCESS) goto Cleanup; ASSERT(dwTempType != REG_MULTI_SZ); switch (dwTempType) { case REG_EXPAND_SZ: case REG_SZ: { CStrOut strData((LPWSTR) lpData, (*lpcbData) / sizeof(WCHAR)); cb = strData.BufSize(); ret = RegQueryValueExA(hKey, strValueName, lpReserved, lpType, (LPBYTE)(LPSTR)strData, &cb); if (ret != ERROR_SUCCESS) break; if (strData) { cb = strData.ConvertIncludingNul(); } *lpcbData = cb * sizeof(WCHAR); break; } default: { ret = RegQueryValueExA( hKey, strValueName, lpReserved, lpType, lpData, lpcbData); break; } } Cleanup: return ret; } LONG RegSetValueWrap( HKEY hKey, LPCWSTR lpSubKey, DWORD dwType, LPCWSTR lpData, DWORD cbData) { CStrIn strKey(lpSubKey); CStrIn strValue(lpData); return RegSetValueA(hKey, strKey, dwType, strValue, cbData); } LONG RegSetValueExWrap( HKEY hKey, LPCWSTR lpValueName, DWORD Reserved, DWORD dwType, CONST BYTE* lpData, DWORD cbData) { ASSERT(dwType != REG_MULTI_SZ); CStrIn strKey(lpValueName); CStrIn strSZ((dwType == REG_SZ || dwType == REG_EXPAND_SZ) ? (LPCWSTR) lpData : NULL); if (strSZ) { lpData = (LPBYTE) (LPSTR) strSZ; cbData = strSZ.strlen() + 1; } return RegSetValueExA( hKey, strKey, Reserved, dwType, lpData, cbData); } ATOM RegisterClassWrap(CONST WNDCLASSW * lpWndClass) { WNDCLASSA wc; CStrIn strMenuName(lpWndClass->lpszMenuName); CStrIn strClassName(lpWndClass->lpszClassName); ASSERT(sizeof(wc) == sizeof(*lpWndClass)); memcpy(&wc, lpWndClass, sizeof(wc)); wc.lpszMenuName = strMenuName; wc.lpszClassName = strClassName; return RegisterClassA(&wc); } UINT RegisterClipboardFormatWrap(LPCWSTR lpString) { CStrIn str(lpString); return RegisterClipboardFormatA(str); } UINT RegisterWindowMessageWrap(LPCWSTR lpString) { CStrIn str(lpString); return RegisterWindowMessageA(str); } HANDLE RemovePropWrap( HWND hWnd, LPCWSTR lpString) { CStrIn str(lpString); return RemovePropA(hWnd, str); } // NOTE (SumitC) Instead of calling SendDlgItemMessageA below, I'm forwarding to // SendMessageWrap so as not to have to re-do the special-case processing. LRESULT SendDlgItemMessageWrap( HWND hDlg, int nIDDlgItem, UINT Msg, WPARAM wParam, LPARAM lParam) { HWND hWnd; hWnd = GetDlgItem(hDlg, nIDDlgItem); return SendMessageWrap(hWnd, Msg, wParam, lParam); } // AdjustECPosition // // Convert mulitbyte position to unicode number of character position in EDIT control // // iType: ADJUST_TO_WCHAR_POS or ADJUST_TO_CHAR_POS // #define ADJUST_TO_WCHAR_POS 0 #define ADJUST_TO_CHAR_POS 1 int AdjustECPosition(char *psz, int iPos, int iType) { char *pstr = psz; int iNewPos = iPos; if (ADJUST_TO_WCHAR_POS == iType) { iNewPos = 0; while (*pstr && (pstr - psz != iPos)) { pstr = CharNextA(pstr); iNewPos++; } } else if (ADJUST_TO_CHAR_POS == iType) { while (*pstr && iPos--) pstr = CharNextA(pstr); iNewPos = (int) (pstr-psz); } return iNewPos; } // // Edit controls can get really huge, so the MAX_PATH buffer in // SendMessageWrap just doesn't cut it when push comes to shove. // // Try to use the small buffer, and switch to an allocated buffer // only if the small buffer doesn't work. // // Use the handy CConvertStr class as our basis. // class CStrA : public CConvertStr { public: CStrA(int cch); inline int bufsize() { return _cchLen; } protected: int _cchLen; }; CStrA::CStrA(int cch) : CConvertStr(CP_ACP) { _cchLen = cch; if (cch <= ARRAYSIZE(_ach)) { // It fits in our small buffer _pstr = _ach; } else { // Need to allocate a big buffer _pstr = new char[cch]; if (!_pstr) { // On failure, use the small buffer after all. _pstr = _ach; _cchLen = ARRAYSIZE(_ach); } } } LRESULT SendEditMessageWrap( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { WORD wStart, wEnd; DWORD dwPos; // // EM_SETSEL is special - We can often handle it without having to // get the client text, which is good since some clients // return bad data. // // If the start and end positions are both either 0 or -1, then we // don't need to do adjustment since 0 is always 0 and -1 is always -1. // if (Msg == EM_SETSEL) { if ((wParam == 0 || (DWORD)wParam == 0xFFFFFFFF) && (lParam == 0 || (DWORD)lParam == 0xFFFFFFFF)) return SendMessageA(hWnd, Msg, wParam, lParam); } // Get the current window text, since we will be studying it CStrA sz(GetWindowTextLengthA(hWnd) + 1); GetWindowTextA(hWnd, sz, sz.bufsize()); switch (Msg) { case EM_GETSEL: { DWORD_PTR dwPos; dwPos = SendMessageA(hWnd, Msg, wParam, lParam); wStart = (WORD)AdjustECPosition(sz, GET_X_LPARAM(dwPos), ADJUST_TO_WCHAR_POS); wEnd = (WORD)AdjustECPosition(sz, GET_Y_LPARAM(dwPos), ADJUST_TO_WCHAR_POS); return MAKELONG(wStart, wEnd); } case EM_SETSEL: wStart = (WORD)AdjustECPosition(sz, wParam, ADJUST_TO_CHAR_POS); wEnd = (WORD)AdjustECPosition(sz, lParam, ADJUST_TO_CHAR_POS); return SendMessageA(hWnd, Msg, wStart, wEnd); case EM_LINEINDEX: dwPos = SendMessageA(hWnd, Msg, wParam, lParam); return AdjustECPosition(sz, dwPos, ADJUST_TO_WCHAR_POS); case EM_LINELENGTH: wStart = (WORD)AdjustECPosition(sz, wParam, ADJUST_TO_CHAR_POS); dwPos = SendMessageA(hWnd, Msg, wStart, lParam); return AdjustECPosition(sz + wStart, dwPos, ADJUST_TO_WCHAR_POS); case EM_LINEFROMCHAR: case EM_POSFROMCHAR: wStart = (WORD)AdjustECPosition(sz, wParam, ADJUST_TO_CHAR_POS); return SendMessageA(hWnd, Msg, wStart, lParam); default: AssertMsg(FALSE, TEXT("error: unknown message leaked into SendEditMessageWrap")); return SendMessageA(hWnd, Msg, wParam, lParam); } } #ifndef UNIX #define SHLWAPI_SENDMESSAGEWRAPW_ORD 136 #else #define SHLWAPI_SENDMESSAGEWRAPW_ORD "SendMessageWrapW" #endif typedef LRESULT (* PFNSENDMESSAGEWRAPW)(HWND, UINT, WPARAM, LPARAM); LRESULT SendMessageWrap( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { // For XCP PlugUI: // 1)If shlwapi is in memory, ask it to do the work, otherwise let it // fall through to original comctl32 wrap implementation. // 2)This implementation only apply to LB for fixing #67837 switch (Msg) { case LB_ADDSTRING: case LB_FINDSTRING: case LB_FINDSTRINGEXACT: case LB_INSERTSTRING: case LB_GETTEXT: case LB_GETTEXTLEN: case LB_SELECTSTRING: { extern HMODULE GetShlwapiHModule(); PFNSENDMESSAGEWRAPW pfnSndMsgWrapW = NULL; HMODULE hShlwapi; hShlwapi = GetShlwapiHModule(); if (hShlwapi) pfnSndMsgWrapW = (PFNSENDMESSAGEWRAPW)GetProcAddress(hShlwapi, (LPCSTR)SHLWAPI_SENDMESSAGEWRAPW_ORD); if (pfnSndMsgWrapW) return pfnSndMsgWrapW(hWnd, Msg, wParam, lParam); else break; // fall through the regular comctl32's wrap } } // original comctl32's wrap implementation CHAR sz[MAX_PATH]; // BUGBUG: It's big enough current comctl32 usage until now ... switch (Msg) { case WM_GETTEXT: { CStrOut str((LPWSTR)lParam, (int) wParam); SendMessageA(hWnd, Msg, (WPARAM) str.BufSize(), (LPARAM) (LPSTR) str); return str.ConvertExcludingNul(); } // The sz[] buffer is not large enough for these guys, so use a // separate helper function. case EM_GETSEL: case EM_SETSEL: case EM_LINEINDEX: case EM_LINELENGTH: case EM_LINEFROMCHAR: case EM_POSFROMCHAR: return SendEditMessageWrap(hWnd, Msg, wParam, lParam); // BUGBUG raymondc - This is wrong. EM_GETLIMITTEXT returns the number // of characters, not bytes. But the only place we use it is in our // IME composition code, and maybe they really meant to divide by two... case EM_GETLIMITTEXT: return SendMessageA(hWnd, Msg, wParam, lParam) / sizeof(WCHAR); case EM_GETLINE: { LRESULT nLen; CStrOut str((LPWSTR) lParam, (* (SHORT *) lParam) + 1); * (SHORT *) (LPSTR) str = * (SHORT *) lParam; nLen = SendMessageA(hWnd, Msg, (WPARAM) wParam, (LPARAM) (LPSTR) str); if(nLen > 0) ((LPSTR) str)[nLen] = '\0'; return nLen; } // BUGBUG: Always assume lParam points structure, not string buffer case CB_INSERTSTRING: { return SendMessageA(hWnd, Msg, wParam, (LPARAM) lParam); } case WM_SETTEXT: case LB_ADDSTRING: case CB_ADDSTRING: case EM_REPLACESEL: ASSERT(wParam == 0 && "wParam should be 0 for these messages"); // fall through case CB_SELECTSTRING: case CB_FINDSTRINGEXACT: case CB_FINDSTRING: case LB_INSERTSTRING: case LB_FINDSTRINGEXACT: { CStrIn str((LPWSTR) lParam); return SendMessageA(hWnd, Msg, wParam, (LPARAM) (LPSTR) str); } case LB_GETTEXTLEN: case CB_GETLBTEXTLEN: ASSERT((LB_GETTEXTLEN - LB_GETTEXT) == (CB_GETLBTEXTLEN - CB_GETLBTEXT)); lParam = (LPARAM)sz; // use temp buffer Msg -= (LB_GETTEXTLEN - LB_GETTEXT); // fall through ... case LB_GETTEXT: case CB_GETLBTEXT: { CStrOut str((LPWSTR)lParam, 255); SendMessageA(hWnd, Msg, wParam, (LPARAM) (LPSTR) str); return str.ConvertExcludingNul(); } case EM_SETPASSWORDCHAR: { WPARAM wp; ASSERT(HIWORD64(wParam) == 0); MbcsFromUnicode((LPSTR) &wp, sizeof(wp), (LPWSTR) &wParam); ASSERT(HIWORD64(wp) == 0); return SendMessageA(hWnd, Msg, wp, lParam); } default: return SendMessageA(hWnd, Msg, wParam, lParam); } } BOOL SendNotifyMessageWrap(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { // BUGBUG: Should we use SendMessageWarp like SendDlgItemMessageWrap above? return SendNotifyMessageA(hWnd, Msg, wParam, lParam); } BOOL SetCurrentDirectoryWrap(LPCWSTR lpszCurDir) { CStrIn str(lpszCurDir); return SetCurrentDirectoryA(str); } BOOL SetDlgItemTextWrap(HWND hDlg, int nIDDlgItem, LPCWSTR lpString) { CStrIn str(lpString); return SetDlgItemTextA(hDlg, nIDDlgItem, str); } BOOL SetMenuItemInfoWrap( HMENU hMenu, UINT uItem, BOOL fByPosition, LPCMENUITEMINFOW lpmiiW) { BOOL fRet; ASSERT( sizeof(MENUITEMINFOW) == sizeof(MENUITEMINFOA) && FIELD_OFFSET(MENUITEMINFOW, dwTypeData) == FIELD_OFFSET(MENUITEMINFOA, dwTypeData) ); if ( (MIIM_TYPE & lpmiiW->fMask) && 0 == (lpmiiW->fType & (MFT_BITMAP | MFT_SEPARATOR))) { MENUITEMINFOA miiA; CStrIn str(lpmiiW->dwTypeData, lpmiiW->cch); memcpy( &miiA, lpmiiW, sizeof(MENUITEMINFOA) ); miiA.dwTypeData = str; miiA.cch = str.strlen(); fRet = SetMenuItemInfoA( hMenu, uItem, fByPosition, &miiA ); } else { fRet = SetMenuItemInfoA( hMenu, uItem, fByPosition, (LPCMENUITEMINFOA)lpmiiW ); } return fRet; } BOOL SetPropWrap( HWND hWnd, LPCWSTR lpString, HANDLE hData) { CStrIn str(lpString); return SetPropA(hWnd, str, hData); } LONG SetWindowLongWrap(HWND hWnd, int nIndex, LONG dwNewLong) { return SetWindowLongA(hWnd, nIndex, dwNewLong); } HHOOK SetWindowsHookExWrap( int idHook, HOOKPROC lpfn, HINSTANCE hmod, DWORD dwThreadId) { return SetWindowsHookExA(idHook, lpfn, hmod, dwThreadId); } BOOL SetWindowTextWrap(HWND hWnd, LPCWSTR lpString) { CStrIn str(lpString); return SetWindowTextA(hWnd, str); } BOOL SystemParametersInfoWrap( UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni) { BOOL ret; char ach[LF_FACESIZE]; if (uiAction == SPI_SETDESKWALLPAPER) { CStrIn str((LPCWSTR) pvParam); ret = SystemParametersInfoA( uiAction, uiParam, str, fWinIni); } else if (uiAction == SPI_GETNONCLIENTMETRICS) { NONCLIENTMETRICSA ncmA; NONCLIENTMETRICS *pncm = (NONCLIENTMETRICS *)pvParam; ASSERT(uiParam == sizeof(NONCLIENTMETRICS) && pncm->cbSize == sizeof(NONCLIENTMETRICS)); ncmA.cbSize = sizeof(ncmA); ret = SystemParametersInfoA( uiAction, sizeof(ncmA), &ncmA, fWinIni); pncm->iBorderWidth = ncmA.iBorderWidth; pncm->iScrollWidth = ncmA.iScrollWidth; pncm->iScrollHeight = ncmA.iScrollHeight; pncm->iCaptionWidth = ncmA.iCaptionWidth; pncm->iCaptionHeight = ncmA.iCaptionHeight; pncm->iSmCaptionWidth = ncmA.iSmCaptionWidth; pncm->iSmCaptionHeight = ncmA.iSmCaptionHeight; pncm->iMenuWidth = ncmA.iMenuWidth; pncm->iMenuHeight = ncmA.iMenuHeight; memcpy(&pncm->lfCaptionFont, &ncmA.lfCaptionFont, FIELD_OFFSET(LOGFONTW, lfFaceName)); UnicodeFromMbcs(pncm->lfCaptionFont.lfFaceName, ARRAYSIZE(pncm->lfCaptionFont.lfFaceName), ncmA.lfCaptionFont.lfFaceName); memcpy(&pncm->lfSmCaptionFont, &ncmA.lfSmCaptionFont, FIELD_OFFSET(LOGFONTW, lfFaceName)); UnicodeFromMbcs(pncm->lfSmCaptionFont.lfFaceName, ARRAYSIZE(pncm->lfSmCaptionFont.lfFaceName), ncmA.lfSmCaptionFont.lfFaceName); memcpy(&pncm->lfMenuFont, &ncmA.lfMenuFont, FIELD_OFFSET(LOGFONTW, lfFaceName)); UnicodeFromMbcs(pncm->lfMenuFont.lfFaceName, ARRAYSIZE(pncm->lfMenuFont.lfFaceName), ncmA.lfMenuFont.lfFaceName); memcpy(&pncm->lfStatusFont, &ncmA.lfStatusFont, FIELD_OFFSET(LOGFONTW, lfFaceName)); UnicodeFromMbcs(pncm->lfStatusFont.lfFaceName, ARRAYSIZE(pncm->lfStatusFont.lfFaceName), ncmA.lfStatusFont.lfFaceName); memcpy(&pncm->lfMessageFont, &ncmA.lfMessageFont, FIELD_OFFSET(LOGFONTW, lfFaceName)); UnicodeFromMbcs(pncm->lfMessageFont.lfFaceName, ARRAYSIZE(pncm->lfMessageFont.lfFaceName), ncmA.lfMessageFont.lfFaceName); } else ret = SystemParametersInfoA( uiAction, uiParam, pvParam, fWinIni); if ((uiAction == SPI_GETICONTITLELOGFONT) && ret) { strcpy(ach, ((LPLOGFONTA)pvParam)->lfFaceName); UnicodeFromMbcs( ((LPLOGFONTW)pvParam)->lfFaceName, ARRAYSIZE(((LPLOGFONTW)pvParam)->lfFaceName), ach); } return ret; } #ifndef FONT_LINK BOOL TextOutWrap(HDC hdc, int x, int y, LPCWSTR lpStr, int cb) { if (g_fMEEnabled && !g_bRunOnMemphis) { CStrIn str(lpStr); return TextOutA(hdc, x, y, str, str.strlen()); } else return TextOutW(hdc, x, y, lpStr, cb); } #endif int TranslateAcceleratorWrap(HWND hWnd, HACCEL hAccTable, LPMSG lpMsg) { return TranslateAcceleratorA(hWnd, hAccTable, lpMsg); } BOOL UnregisterClassWrap(LPCWSTR lpClassName, HINSTANCE hInstance) { CStrIn str(lpClassName); return UnregisterClassA(str, hInstance); } SHORT VkKeyScanWrap(WCHAR ch) { CStrIn str(&ch, 1); return VkKeyScanA(*(char *)str); } BOOL WinHelpWrap(HWND hwnd, LPCWSTR szFile, UINT uCmd, DWORD dwData) { CStrIn str(szFile); return WinHelpA(hwnd, str, uCmd, dwData); } #define DBCS_CHARSIZE (2) // N versions of wsprintf and wvsprintf which take an output buffer size to prevent overflow // bugs. Taken from the NT wsprintf source code. // _MBToWCS and _WCSToMB are actually macros which call ntrtl functions in the NT version. int _MBToWCS(LPCSTR pszIn, int cchIn, LPWSTR *ppwszOut) { int cch = 0; int cbAlloc; if ((0 != cchIn) && (NULL != ppwszOut)) { cchIn++; cbAlloc = cchIn * sizeof(WCHAR); *ppwszOut = (LPWSTR)LocalAlloc(LMEM_FIXED, cbAlloc); if (NULL != *ppwszOut) { cch = MultiByteToWideChar(CP_ACP, 0, pszIn, cchIn, *ppwszOut, cchIn); if (!cch) { LocalFree(*ppwszOut); *ppwszOut = NULL; } else { cch--; // Just return the number of characters } } } return cch; } /****************************** Module Header ******************************\ * Module Name: wsprintf.c * * Copyright (c) 1985-91, Microsoft Corporation * sprintf.c * * Implements Windows friendly versions of sprintf and vsprintf * * History: * 2-15-89 craigc Initial * 11-12-90 MikeHar Ported from windows 3 \***************************************************************************/ /* Max number of characters. Doesn't include termination character */ #define out(c) if (cchLimit) {*lpOut++=(c); cchLimit--;} else goto errorout /***************************************************************************\ * SP_GetFmtValueW * * reads a width or precision value from the format string * * History: * 11-12-90 MikeHar Ported from windows 3 * 07-27-92 GregoryW Created Unicode version (copied from SP_GetFmtValue) \***************************************************************************/ LPCWSTR SP_GetFmtValueW( LPCWSTR lpch, int *lpw) { int ii = 0; /* It might not work for some locales or digit sets */ while (*lpch >= L'0' && *lpch <= L'9') { ii *= 10; ii += (int)(*lpch - L'0'); lpch++; } *lpw = ii; /* * return the address of the first non-digit character */ return lpch; } /***************************************************************************\ * SP_PutNumberW * * Takes an unsigned long integer and places it into a buffer, respecting * a buffer limit, a radix, and a case select (upper or lower, for hex). * * * History: * 11-12-90 MikeHar Ported from windows 3 asm --> C * 12-11-90 GregoryW need to increment lpstr after assignment of mod * 02-11-92 GregoryW temporary version until we have C runtime support \***************************************************************************/ int SP_PutNumberW( LPWSTR lpstr, DWORD n, int limit, DWORD radix, int uppercase) { DWORD mod; int count = 0; /* It might not work for some locales or digit sets */ if(uppercase) uppercase = 'A'-'0'-10; else uppercase = 'a'-'0'-10; if (count < limit) { do { mod = n % radix; n /= radix; mod += '0'; if (mod > '9') mod += uppercase; *lpstr++ = (WCHAR)mod; count++; } while((count < limit) && n); } return count; } /***************************************************************************\ * SP_ReverseW * * reverses a string in place * * History: * 11-12-90 MikeHar Ported from windows 3 asm --> C * 12-11-90 GregoryW fixed boundary conditions; removed count * 02-11-92 GregoryW temporary version until we have C runtime support \***************************************************************************/ void SP_ReverseW( LPWSTR lpFirst, LPWSTR lpLast) { WCHAR ch; while(lpLast > lpFirst){ ch = *lpFirst; *lpFirst++ = *lpLast; *lpLast-- = ch; } } /***************************************************************************\ * wvsprintfW (API) * * wsprintfW() calls this function. * * History: * 11-Feb-1992 GregoryW copied xwvsprintf * Temporary hack until we have C runtime support * 1-22-97 tnoonan Converted to wvnsprintfW \***************************************************************************/ int wvnsprintfW( LPWSTR lpOut, int cchLimitIn, LPCWSTR lpFmt, va_list arglist) { BOOL fAllocateMem = FALSE; WCHAR prefix, fillch; int left, width, prec, size, sign, radix, upper, hprefix; int cchLimit = --cchLimitIn, cch; LPWSTR lpT, lpTWC; LPCSTR psz; va_list varglist = arglist; union { long l; unsigned long ul; char sz[2]; WCHAR wsz[2]; } val; if (cchLimit < 0) return 0; while (*lpFmt != 0) { if (*lpFmt == L'%') { /* * read the flags. These can be in any order */ left = 0; prefix = 0; while (*++lpFmt) { if (*lpFmt == L'-') left++; else if (*lpFmt == L'#') prefix++; else break; } /* * find fill character */ if (*lpFmt == L'0') { fillch = L'0'; lpFmt++; } else fillch = L' '; /* * read the width specification */ lpFmt = SP_GetFmtValueW(lpFmt, &cch); width = cch; /* * read the precision */ if (*lpFmt == L'.') { lpFmt = SP_GetFmtValueW(++lpFmt, &cch); prec = cch; } else prec = -1; /* * get the operand size * default size: size == 0 * long number: size == 1 * wide chars: size == 2 * It may be a good idea to check the value of size when it * is tested for non-zero below (IanJa) */ hprefix = 0; if ((*lpFmt == L'w') || (*lpFmt == L't')) { size = 2; lpFmt++; } else if (*lpFmt == L'l') { size = 1; lpFmt++; } else { size = 0; if (*lpFmt == L'h') { lpFmt++; hprefix = 1; } } upper = 0; sign = 0; radix = 10; switch (*lpFmt) { case 0: goto errorout; case L'i': case L'd': size=1; sign++; /*** FALL THROUGH to case 'u' ***/ case L'u': /* turn off prefix if decimal */ prefix = 0; donumeric: /* special cases to act like MSC v5.10 */ if (left || prec >= 0) fillch = L' '; /* * if size == 1, "%lu" was specified (good) * if size == 2, "%wu" was specified (bad) */ if (size) { val.l = va_arg(varglist, LONG); } else if (sign) { val.l = va_arg(varglist, SHORT); } else { val.ul = va_arg(varglist, unsigned); } if (sign && val.l < 0L) val.l = -val.l; else sign = 0; lpT = lpOut; /* * blast the number backwards into the user buffer */ cch = SP_PutNumberW(lpOut, val.l, cchLimit, radix, upper); if (!(cchLimit -= cch)) goto errorout; lpOut += cch; width -= cch; prec -= cch; if (prec > 0) width -= prec; /* * fill to the field precision */ while (prec-- > 0) out(L'0'); if (width > 0 && !left) { /* * if we're filling with spaces, put sign first */ if (fillch != L'0') { if (sign) { sign = 0; out(L'-'); width--; } if (prefix) { out(prefix); out(L'0'); prefix = 0; } } if (sign) width--; /* * fill to the field width */ while (width-- > 0) out(fillch); /* * still have a sign? */ if (sign) out(L'-'); if (prefix) { out(prefix); out(L'0'); } /* * now reverse the string in place */ SP_ReverseW(lpT, lpOut - 1); } else { /* * add the sign character */ if (sign) { out(L'-'); width--; } if (prefix) { out(prefix); out(L'0'); } /* * reverse the string in place */ SP_ReverseW(lpT, lpOut - 1); /* * pad to the right of the string in case left aligned */ while (width-- > 0) out(fillch); } break; case L'X': upper++; /*** FALL THROUGH to case 'x' ***/ case L'x': radix = 16; if (prefix) if (upper) prefix = L'X'; else prefix = L'x'; goto donumeric; case L'c': case L'C': if (!size && !hprefix) { size = 1; // force WCHAR } /*** FALL THROUGH to case 'C' ***/ /* * if size == 0, "%C" or "%hc" was specified (CHAR) * if size == 1, "%c" or "%lc" was specified (WCHAR) * if size == 2, "%wc" or "%tc" was specified (WCHAR) */ cch = 1; /* One character must be copied to the output buffer */ if (size) { val.wsz[0] = va_arg(varglist, WCHAR); val.wsz[1] = 0; lpT = val.wsz; goto putwstring; } else { val.sz[0] = va_arg(varglist, CHAR); val.sz[1] = 0; psz = val.sz; goto putstring; } case L's': case L'S': if (!size && !hprefix) { size = 1; // force LPWSTR } /*** FALL THROUGH to case 'S' ***/ /* * if size == 0, "%S" or "%hs" was specified (LPSTR) * if size == 1, "%s" or "%ls" was specified (LPWSTR) * if size == 2, "%ws" or "%ts" was specified (LPWSTR) */ if (size) { lpT = va_arg(varglist, LPWSTR); cch = lstrlenW(lpT); // Win95 supports lstrlenW! } else { psz = va_arg(varglist, LPSTR); cch = lstrlenA(psz); putstring: cch = _MBToWCS(psz, cch, &lpTWC); fAllocateMem = (BOOL) cch; lpT = lpTWC; } putwstring: if (prec >= 0 && cch > prec) cch = prec; width -= cch; if (left) { while (cch--) out(*lpT++); while (width-- > 0) out(fillch); } else { while (width-- > 0) out(fillch); while (cch--) out(*lpT++); } if (fAllocateMem) { LocalFree(lpTWC); fAllocateMem = FALSE; } break; default: normalch: out((WCHAR)*lpFmt); break; } /* END OF SWITCH(*lpFmt) */ } /* END OF IF(%) */ else goto normalch; /* character not a '%', just do it */ /* * advance to next format string character */ lpFmt++; } /* END OF OUTER WHILE LOOP */ errorout: *lpOut = 0; if (fAllocateMem) { LocalFree(lpTWC); } return cchLimitIn - cchLimit; } LWSTDAPIV_(int) wnsprintfW( LPWSTR lpOut, int cchLimitIn, LPCWSTR lpFmt, ...) { va_list arglist; int ret; va_start(arglist, lpFmt); ret = wvnsprintfW(lpOut, cchLimitIn, lpFmt, arglist); va_end(arglist); return ret; } LWSTDAPIV_(int) wsprintfW( LPWSTR lpOut, LPCWSTR lpFmt, ...) { // unsafe printf. arbitrary max of 0x10000 length va_list arglist; int ret; va_start(arglist, lpFmt); ret = wvnsprintfW(lpOut, 0x10000, lpFmt, arglist); va_end(arglist); return ret; } //+--------------------------------------------------------------------------- // StartDoc //---------------------------------------------------------------------------- int StartDocWrap( HDC hDC, const DOCINFO * lpdi ) { CStrIn strDocName( lpdi->lpszDocName ); CStrIn strOutput( lpdi->lpszOutput ); CStrIn strDatatype( lpdi->lpszDatatype ); DOCINFOA dia; dia.cbSize = sizeof(DOCINFO); dia.lpszDocName = strDocName; dia.lpszOutput = strOutput; dia.lpszDatatype = strDatatype; dia.fwType = lpdi->fwType; return StartDocA( hDC, &dia ); } #endif // !WINNT //////////////////////////////////////////////////////////////////// // // Plug UI support with SHLWAPI // typedef HRESULT (*PFNDLLGETVERSION)(DLLVERSIONINFO * pinfo); HMODULE GetShlwapiHModule() { HMODULE hShlwapi = GetModuleHandle(TEXT("SHLWAPI")); if (hShlwapi) { PFNDLLGETVERSION pfnDllGetVersion = (PFNDLLGETVERSION)GetProcAddress(hShlwapi, "DllGetVersion"); if (pfnDllGetVersion) { DLLVERSIONINFO dllinfo; dllinfo.cbSize = sizeof(DLLVERSIONINFO); if (pfnDllGetVersion(&dllinfo) == NOERROR) { if (dllinfo.dwMajorVersion < 5) { // This guy doesn't support ML functions hShlwapi = NULL; } } } } return hShlwapi; } // First, we need access to some helper functions: // #ifndef UNIX #define SHLWAPIMLISMLHINSTANCE_ORD 429 #else #define SHLWAPIMLISMLHINSTANCE_ORD "MLIsMLHInstance" #endif typedef BOOL (* PFNMLISMLHINSTANCE)(HINSTANCE); BOOL MLIsMLHInstanceWrap(HINSTANCE hInst) { HMODULE hShlwapi = GetShlwapiHModule(); if (hShlwapi) { PFNMLISMLHINSTANCE pfn; pfn = (PFNMLISMLHINSTANCE)GetProcAddress(hShlwapi, (LPCSTR)SHLWAPIMLISMLHINSTANCE_ORD); if (pfn) return pfn(hInst); } // BUGBUG: What if an app told comctl32 to be PlugUI and we picked // a resource that cannot be displayed on Win9x without // shlwapi's font linking? Seems like we need to foricbly // load shlwapi in that case... // // No shlwapi? then this can't be an ML hinstance. return FALSE; } #ifndef UNIX #define SHLWAPIMLSETMLHINSTANCE_ORD 430 #else #define SHLWAPIMLSETMLHINSTANCE_ORD "MLSetMLHInstance" #endif typedef HRESULT (* PFNMLSETMLHINSTANCE)(HINSTANCE, LANGID); HRESULT MLSetMLHInstanceWrap(HINSTANCE hInst, LANGID lidUI) { HMODULE hShlwapi; PFNMLSETMLHINSTANCE pfnMLSet = NULL; hShlwapi = GetShlwapiHModule(); if (hShlwapi) { pfnMLSet = (PFNMLSETMLHINSTANCE)GetProcAddress(hShlwapi, (LPCSTR)SHLWAPIMLSETMLHINSTANCE_ORD); if (pfnMLSet) return pfnMLSet(hInst, lidUI); } return E_FAIL; } #ifndef UNIX #define SHLWAPIMLCLEARMLHINSTANCE_ORD 431 #else #define SHLWAPIMLCLEARMLHINSTANCE_ORD "MLClearMLHInstance" #endif typedef HRESULT (* PFNMLCLEARMLHINSTANCE)(HINSTANCE); HRESULT MLClearMLHinstanceWrap(HINSTANCE hInst) { HMODULE hShlwapi; PFNMLCLEARMLHINSTANCE pfnMLClear = NULL; hShlwapi = GetShlwapiHModule(); if (hShlwapi) { pfnMLClear = (PFNMLCLEARMLHINSTANCE)GetProcAddress(hShlwapi, (LPCSTR)SHLWAPIMLCLEARMLHINSTANCE_ORD); if (pfnMLClear) return pfnMLClear(hInst); } return E_FAIL; } // // And now, when shlwapi is around we delegate to it's ML-enabled implementations: // // // Make sure we get the real USER32 versions. // #undef CreateDialogIndirectParamW #ifndef UNIX #define SHLWAPICREATEDIALOGINDIRECTPARAM_ORD 393 #else #define SHLWAPICREATEDIALOGINDIRECTPARAM_ORD "CreateDialogIndirectParamWrapW" #endif typedef HWND (* PFNCREATEDIALOGINDIRECTPARAM)(HINSTANCE, LPCDLGTEMPLATE, HWND, DLGPROC, LPARAM); HWND CreateDialogIndirectParamWrap( HINSTANCE hInstance, LPCDLGTEMPLATE lpTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam) { HMODULE hShlwapi; PFNCREATEDIALOGINDIRECTPARAM pfnCDIP = NULL; HWND hwndRet; // If shlwapi is in memory, ask it to create the dialog, // as then we get ML dialogs on downlevel platforms (if // the hInstance is from MLLoadLibrary -- otherwise it // thunks to the real A/W api for us). // hShlwapi = GetShlwapiHModule(); if (hShlwapi) { pfnCDIP = (PFNCREATEDIALOGINDIRECTPARAM)GetProcAddress(hShlwapi, (LPCSTR)SHLWAPICREATEDIALOGINDIRECTPARAM_ORD); } if (!pfnCDIP) { if (g_bRunOnNT) pfnCDIP = CreateDialogIndirectParamW; else pfnCDIP = CreateDialogIndirectParamA; } // If this is from comctl32, assume it was loaded via the MUI-Language if (HINST_THISDLL == hInstance) MLSetMLHInstanceWrap(hInstance, GetMUILanguage()); hwndRet = pfnCDIP(hInstance, lpTemplate, hWndParent, lpDialogFunc, dwInitParam); if (HINST_THISDLL == hInstance) MLClearMLHinstanceWrap(hInstance); return(hwndRet); } // // Make sure we get the real USER32 versions. // #undef DialogBoxIndirectParamW #ifndef UNIX #define SHLWAPIDIALOGBOXINDIRECTPARAM_ORD 58 #else #define SHLWAPIDIALOGBOXINDIRECTPARAM_ORD "DialogBoxIndirectParamWrapW" #endif typedef INT_PTR (* PFNDIALOGBOXINDIRECTPARAM)(HINSTANCE, LPCDLGTEMPLATE, HWND, DLGPROC, LPARAM); INT_PTR DialogBoxIndirectParamWrap( HINSTANCE hInstance, LPCDLGTEMPLATEW hDialogTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam) { HMODULE hShlwapi; INT_PTR iRet; PFNDIALOGBOXINDIRECTPARAM pfnDBIP = NULL; // If shlwapi is in memory, ask it to create the dialog, // as then we get ML dialogs on downlevel platforms (if // the hInstance is from MLLoadLibrary -- otherwise it // thunks to the real A/W api for us). // hShlwapi = GetShlwapiHModule(); if (hShlwapi) pfnDBIP = (PFNDIALOGBOXINDIRECTPARAM)GetProcAddress(hShlwapi, (LPCSTR)SHLWAPIDIALOGBOXINDIRECTPARAM_ORD); if (!pfnDBIP) { if (g_bRunOnNT) pfnDBIP = DialogBoxIndirectParamW; else pfnDBIP = DialogBoxIndirectParamA; } // If this is from comctl32, assume it was loaded via the MUI-Language if (HINST_THISDLL == hInstance) MLSetMLHInstanceWrap(hInstance, GetMUILanguage()); iRet = pfnDBIP(hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam); if (HINST_THISDLL == hInstance) MLClearMLHinstanceWrap(hInstance); return iRet; } #endif // UNICODE