Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5211 lines
154 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Copyright (C) Microsoft Corporation, 1994-1995
  4. //
  5. // File: unicwrap.cpp
  6. //
  7. // Contents: Wrappers for all Unicode functions used in MSHTML.
  8. // Any Unicode parameters/structure fields/buffers are converted
  9. // to ANSI, and then the corresponding ANSI version of the function
  10. // is called.
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "ctlspriv.h"
  14. #ifdef UNICODE
  15. #ifndef WINNT
  16. #include "unicwrap.h"
  17. #undef TextOutW
  18. #undef ExtTextOutW
  19. int MbcsFromUnicode(LPSTR pstr, int cch, LPCWSTR pwstr, int cwch = -1);
  20. int UnicodeFromMbcs(LPWSTR pwstr, int cwch, LPCSTR pstr, int cch = -1);
  21. //+---------------------------------------------------------------------------
  22. //
  23. // Member: CConvertStr::Free
  24. //
  25. // Synopsis: Frees string if alloc'd and initializes to NULL.
  26. //
  27. //----------------------------------------------------------------------------
  28. void CConvertStr::Free()
  29. {
  30. if (_pstr != _ach && HIWORD64(_pstr) != 0)
  31. {
  32. delete [] _pstr;
  33. }
  34. _pstr = NULL;
  35. }
  36. //+---------------------------------------------------------------------------
  37. //
  38. // Member: CConvertStrW::Free
  39. //
  40. // Synopsis: Frees string if alloc'd and initializes to NULL.
  41. //
  42. //----------------------------------------------------------------------------
  43. void CConvertStrW::Free()
  44. {
  45. if (_pwstr != _awch && HIWORD64(_pwstr) != 0)
  46. {
  47. delete [] _pwstr;
  48. }
  49. _pwstr = NULL;
  50. }
  51. //+---------------------------------------------------------------------------
  52. //
  53. // Member: CStrInW::Init
  54. //
  55. // Synopsis: Converts a LPSTR function argument to a LPWSTR.
  56. //
  57. // Arguments: [pstr] -- The function argument. May be NULL or an atom
  58. // (HIWORD(pwstr) == 0).
  59. //
  60. // [cch] -- The number of characters in the string to
  61. // convert. If -1, the string is assumed to be
  62. // NULL terminated and its length is calculated.
  63. //
  64. // Modifies: [this]
  65. //
  66. //----------------------------------------------------------------------------
  67. void CStrInW::Init(LPCSTR pstr, int cch)
  68. {
  69. int cchBufReq;
  70. _cwchLen = 0;
  71. // Check if string is NULL or an atom.
  72. if (HIWORD64(pstr) == 0)
  73. {
  74. _pwstr = (LPWSTR) pstr;
  75. return;
  76. }
  77. ASSERT(cch == -1 || cch > 0);
  78. //
  79. // Convert string to preallocated buffer, and return if successful.
  80. //
  81. _cwchLen = MultiByteToWideChar(
  82. CP_ACP, 0, pstr, cch, _awch, ARRAYSIZE(_awch));
  83. if (_cwchLen > 0)
  84. {
  85. if(_awch[_cwchLen-1] == 0)
  86. _cwchLen--; // account for terminator
  87. _pwstr = _awch;
  88. return;
  89. }
  90. //
  91. // Alloc space on heap for buffer.
  92. //
  93. cchBufReq = MultiByteToWideChar( CP_ACP, 0, pstr, cch, NULL, 0 );
  94. ASSERT(cchBufReq > 0);
  95. _pwstr = new WCHAR[cchBufReq];
  96. if (!_pwstr)
  97. {
  98. // On failure, the argument will point to the empty string.
  99. _awch[0] = 0;
  100. _pwstr = _awch;
  101. return;
  102. }
  103. ASSERT(HIWORD64(_pwstr));
  104. _cwchLen = -1 + MultiByteToWideChar(
  105. CP_ACP, 0, pstr, cch, _pwstr, cchBufReq );
  106. ASSERT(_cwchLen >= 0);
  107. }
  108. //+---------------------------------------------------------------------------
  109. //
  110. // Member: CStrIn::CStrIn
  111. //
  112. // Synopsis: Inits the class.
  113. //
  114. // NOTE: Don't inline this function or you'll increase code size
  115. // by pushing -1 on the stack for each call.
  116. //
  117. //----------------------------------------------------------------------------
  118. CStrIn::CStrIn(LPCWSTR pwstr) : CConvertStr(CP_ACP)
  119. {
  120. Init(pwstr, -1);
  121. }
  122. CStrIn::CStrIn(UINT uCP, LPCWSTR pwstr) : CConvertStr(uCP)
  123. {
  124. Init(pwstr, -1);
  125. }
  126. //+---------------------------------------------------------------------------
  127. //
  128. // Member: CStrIn::Init
  129. //
  130. // Synopsis: Converts a LPWSTR function argument to a LPSTR.
  131. //
  132. // Arguments: [pwstr] -- The function argument. May be NULL or an atom
  133. // (HIWORD(pwstr) == 0).
  134. //
  135. // [cwch] -- The number of characters in the string to
  136. // convert. If -1, the string is assumed to be
  137. // NULL terminated and its length is calculated.
  138. //
  139. // Modifies: [this]
  140. //
  141. //----------------------------------------------------------------------------
  142. void CStrIn::Init(LPCWSTR pwstr, int cwch)
  143. {
  144. int cchBufReq;
  145. #if DBG == 1 /* { */
  146. int errcode;
  147. #endif /* } */
  148. _cchLen = 0;
  149. // Check if string is NULL or an atom.
  150. if (HIWORD64(pwstr) == 0)
  151. {
  152. _pstr = (LPSTR) pwstr;
  153. return;
  154. }
  155. if ( cwch == 0 )
  156. {
  157. *_ach = '\0';
  158. _pstr = _ach;
  159. return;
  160. }
  161. ASSERT(cwch == -1 || cwch > 0);
  162. //
  163. // Convert string to preallocated buffer, and return if successful.
  164. //
  165. _cchLen = WideCharToMultiByte(
  166. _uCP, 0, pwstr, cwch, _ach, ARRAYSIZE(_ach), NULL, NULL);
  167. if (_cchLen > 0)
  168. {
  169. if (_ach[_cchLen-1]==0) _cchLen--; // account for terminator
  170. _pstr = _ach;
  171. return;
  172. }
  173. cchBufReq = WideCharToMultiByte(
  174. CP_ACP, 0, pwstr, cwch, NULL, 0, NULL, NULL);
  175. ASSERT(cchBufReq > 0);
  176. _pstr = new char[cchBufReq];
  177. if (!_pstr)
  178. {
  179. // On failure, the argument will point to the empty string.
  180. _ach[0] = 0;
  181. _pstr = _ach;
  182. return;
  183. }
  184. ASSERT(HIWORD64(_pstr));
  185. _cchLen = -1 + WideCharToMultiByte(
  186. _uCP, 0, pwstr, cwch, _pstr, cchBufReq, NULL, NULL);
  187. #if DBG == 1 /* { */
  188. if (_cchLen < 0)
  189. {
  190. errcode = GetLastError();
  191. ASSERT(0 && "WideCharToMultiByte failed in unicode wrapper.");
  192. }
  193. #endif /* } */
  194. }
  195. //+---------------------------------------------------------------------------
  196. //
  197. // Member: CStrInMulti::CStrInMulti
  198. //
  199. // Synopsis: Converts mulitple LPWSTRs to a multiple LPSTRs.
  200. //
  201. // Arguments: [pwstr] -- The strings to convert.
  202. //
  203. // Modifies: [this]
  204. //
  205. //----------------------------------------------------------------------------
  206. CStrInMulti::CStrInMulti(LPCWSTR pwstr)
  207. {
  208. LPCWSTR pwstrT;
  209. // We don't handle atoms because we don't need to.
  210. ASSERT(HIWORD64(pwstr));
  211. //
  212. // Count number of characters to convert.
  213. //
  214. pwstrT = pwstr;
  215. if (pwstr)
  216. {
  217. do {
  218. while (*pwstrT++)
  219. ;
  220. } while (*pwstrT++);
  221. }
  222. Init(pwstr, (int)(pwstrT - pwstr));
  223. }
  224. //+---------------------------------------------------------------------------
  225. //
  226. // Member: CStrOut::CStrOut
  227. //
  228. // Synopsis: Allocates enough space for an out buffer.
  229. //
  230. // Arguments: [pwstr] -- The Unicode buffer to convert to when destroyed.
  231. // May be NULL.
  232. //
  233. // [cwchBuf] -- The size of the buffer in characters.
  234. //
  235. // Modifies: [this].
  236. //
  237. //----------------------------------------------------------------------------
  238. CStrOut::CStrOut(LPWSTR pwstr, int cwchBuf) : CConvertStr(CP_ACP)
  239. {
  240. ASSERT(cwchBuf >= 0);
  241. if (!cwchBuf)
  242. pwstr = NULL;
  243. _pwstr = pwstr;
  244. _cwchBuf = cwchBuf;
  245. if (!pwstr)
  246. {
  247. ASSERT(cwchBuf == 0);
  248. _pstr = NULL;
  249. return;
  250. }
  251. ASSERT(HIWORD64(pwstr));
  252. // Initialize buffer in case Windows API returns an error.
  253. _ach[0] = 0;
  254. // Use preallocated buffer if big enough.
  255. if (cwchBuf * 2 <= ARRAYSIZE(_ach))
  256. {
  257. _pstr = _ach;
  258. return;
  259. }
  260. // Allocate buffer.
  261. _pstr = new char[cwchBuf * 2];
  262. if (!_pstr)
  263. {
  264. //
  265. // On failure, the argument will point to a zero-sized buffer initialized
  266. // to the empty string. This should cause the Windows API to fail.
  267. //
  268. ASSERT(cwchBuf > 0);
  269. _pwstr[0] = 0;
  270. _cwchBuf = 0;
  271. _pstr = _ach;
  272. return;
  273. }
  274. ASSERT(HIWORD64(_pstr));
  275. _pstr[0] = 0;
  276. }
  277. //+---------------------------------------------------------------------------
  278. //
  279. // Member: CStrOut::ConvertIncludingNul
  280. //
  281. // Synopsis: Converts the buffer from MBCS to Unicode
  282. //
  283. // Return: Character count INCLUDING the trailing '\0'
  284. //
  285. //----------------------------------------------------------------------------
  286. int CStrOut::ConvertIncludingNul()
  287. {
  288. int cwch;
  289. if (!_pstr)
  290. return 0;
  291. ASSERT(_cwchBuf);
  292. // Preinit to null string in case of horrible catastrophe
  293. _pwstr[0] = TEXT('\0');
  294. cwch = MultiByteToWideChar(_uCP, 0, _pstr, -1, _pwstr, _cwchBuf);
  295. if (!cwch) {
  296. // Output buffer was short. Must double-buffer (yuck)
  297. int cwchNeeded = MultiByteToWideChar(_uCP, 0, _pstr, -1, NULL, 0);
  298. if (cwchNeeded) {
  299. LPWSTR pwsz = (LPWSTR)LocalAlloc(LMEM_FIXED,
  300. cwchNeeded * SIZEOF(WCHAR));
  301. if (pwsz) {
  302. cwch = MultiByteToWideChar(_uCP, 0, _pstr, -1,
  303. pwsz, cwchNeeded);
  304. if (cwch) {
  305. StrCpyNW(_pwstr, pwsz, _cwchBuf);
  306. cwch = _cwchBuf;
  307. }
  308. LocalFree(pwsz);
  309. }
  310. } else {
  311. #if DBG == 1 /* { */
  312. DWORD errcode = GetLastError();
  313. ASSERT(0 && "MultiByteToWideChar failed in unicode wrapper.");
  314. #endif /* } */
  315. }
  316. }
  317. Free();
  318. return cwch;
  319. }
  320. //+---------------------------------------------------------------------------
  321. //
  322. // Member: CStrOut::ConvertExcludingNul
  323. //
  324. // Synopsis: Converts the buffer from MBCS to Unicode
  325. //
  326. // Return: Character count EXCLUDING the trailing '\0'
  327. //
  328. //----------------------------------------------------------------------------
  329. int CStrOut::ConvertExcludingNul()
  330. {
  331. int ret = ConvertIncludingNul();
  332. if (ret)
  333. {
  334. ret -= 1;
  335. }
  336. return ret;
  337. }
  338. //+---------------------------------------------------------------------------
  339. //
  340. // Member: CStrOut::~CStrOut
  341. //
  342. // Synopsis: Converts the buffer from MBCS to Unicode.
  343. //
  344. // Note: Don't inline this function, or you'll increase code size as
  345. // both ConvertIncludingNul() and CConvertStr::~CConvertStr will be
  346. // called inline.
  347. //
  348. //----------------------------------------------------------------------------
  349. CStrOut::~CStrOut()
  350. {
  351. ConvertIncludingNul();
  352. }
  353. //+---------------------------------------------------------------------------
  354. //
  355. // Function: MbcsFromUnicode
  356. //
  357. // Synopsis: Converts a string to MBCS from Unicode.
  358. //
  359. // Arguments: [pstr] -- The buffer for the MBCS string.
  360. // [cch] -- The size of the MBCS buffer, including space for
  361. // NULL terminator.
  362. //
  363. // [pwstr] -- The Unicode string to convert.
  364. // [cwch] -- The number of characters in the Unicode string to
  365. // convert, including NULL terminator. If this
  366. // number is -1, the string is assumed to be
  367. // NULL terminated. -1 is supplied as a
  368. // default argument.
  369. //
  370. // Returns: If [pstr] is NULL or [cch] is 0, 0 is returned. Otherwise,
  371. // the number of characters converted, including the terminating
  372. // NULL, is returned (note that converting the empty string will
  373. // return 1). If the conversion fails, 0 is returned.
  374. //
  375. // Modifies: [pstr].
  376. //
  377. //----------------------------------------------------------------------------
  378. int MbcsFromUnicode(LPSTR pstr, int cch, LPCWSTR pwstr, int cwch)
  379. {
  380. int ret;
  381. #if DBG == 1 /* { */
  382. int errcode;
  383. #endif /* } */
  384. ASSERT(cch >= 0);
  385. if (!pstr || cch == 0)
  386. return 0;
  387. ASSERT(pwstr);
  388. ASSERT(cwch == -1 || cwch > 0);
  389. ret = WideCharToMultiByte(CP_ACP, 0, pwstr, cwch, pstr, cch, NULL, NULL);
  390. #if DBG == 1 /* { */
  391. if (ret <= 0)
  392. {
  393. errcode = GetLastError();
  394. ASSERT(0 && "WideCharToMultiByte failed in unicode wrapper.");
  395. }
  396. #endif /* } */
  397. return ret;
  398. }
  399. //+---------------------------------------------------------------------------
  400. //
  401. // Function: UnicodeFromMbcs
  402. //
  403. // Synopsis: Converts a string to Unicode from MBCS.
  404. //
  405. // Arguments: [pwstr] -- The buffer for the Unicode string.
  406. // [cwch] -- The size of the Unicode buffer, including space for
  407. // NULL terminator.
  408. //
  409. // [pstr] -- The MBCS string to convert.
  410. // [cch] -- The number of characters in the MBCS string to
  411. // convert, including NULL terminator. If this
  412. // number is -1, the string is assumed to be
  413. // NULL terminated. -1 is supplied as a
  414. // default argument.
  415. //
  416. // Returns: If [pwstr] is NULL or [cwch] is 0, 0 is returned. Otherwise,
  417. // the number of characters converted, including the terminating
  418. // NULL, is returned (note that converting the empty string will
  419. // return 1). If the conversion fails, 0 is returned.
  420. //
  421. // Modifies: [pwstr].
  422. //
  423. //----------------------------------------------------------------------------
  424. int UnicodeFromMbcs(LPWSTR pwstr, int cwch, LPCSTR pstr, int cch)
  425. {
  426. int ret;
  427. #if DBG == 1 /* { */
  428. int errcode;
  429. #endif /* } */
  430. ASSERT(cwch >= 0);
  431. if (!pwstr || cwch == 0)
  432. return 0;
  433. ASSERT(pstr);
  434. ASSERT(cch == -1 || cch > 0);
  435. ret = MultiByteToWideChar(CP_ACP, 0, pstr, cch, pwstr, cwch);
  436. #if DBG == 1 /* { */
  437. if (ret <= 0)
  438. {
  439. errcode = GetLastError();
  440. ASSERT(0 && "MultiByteToWideChar failed in unicode wrapper.");
  441. }
  442. #endif /* } */
  443. return ret;
  444. }
  445. //+------------------------------------------------------------------------
  446. //
  447. // Contents: widechar character type function (CT_CTYPE1) and (CT_CTYPE3)
  448. //
  449. // Synopsis: We do not have wide char support for IsChar functions
  450. // under Win95. The Unicode-Wrapper functions we have
  451. // in core\wrappers all convert to CP_ACP and then call
  452. // the A version, which means we will have invalid results
  453. // for any characters which aren't in CP_ACP.
  454. //
  455. // The solution is to roll our own, which result in these
  456. // unfortunately large tables. Here's how it works:
  457. //
  458. // bits: fedc ba98 7654 3210
  459. // pppp pppp iiib bbbb
  460. //
  461. // The 'b' bits form a 32-bit bit mask into our data. The data
  462. // entrys boolean, and are thus 4-bytes long. Of the 2^32
  463. // possible combinations, we in fact have only 218 distinct
  464. // values of data. These are stored in adwData.
  465. //
  466. // The 'p' bits represent a page. Each page has eight
  467. // possible entries, represent by 'i'. In most pages, the
  468. // bitfields and data are both uniform.
  469. //
  470. // adwData[abIndex[abType[page]][index]] represents the data
  471. //
  472. // 1 << bits represents the bitmask.
  473. //
  474. //-------------------------------------------------------------------------
  475. #define __BIT_SHIFT 0
  476. #define __INDEX_SHIFT 5
  477. #define __PAGE_SHIFT 8
  478. #define __BIT_MASK 31
  479. #define __INDEX_MASK 7
  480. // straight lookup functions are inlined.
  481. #define ISCHARFUNC(type, wch) \
  482. (adwData[abIndex[abType1##type[wch>>__PAGE_SHIFT]] \
  483. [(wch>>__INDEX_SHIFT)&__INDEX_MASK]] \
  484. >> (wch&__BIT_MASK)) & 1
  485. //
  486. // To avoid header file conflicts with IsCharAlphaW, IsCharAlphaNumericW, ... defined in
  487. // winuser.h, the functions names end in "Wrap". SHLWAPI.DEF exports these functions with
  488. // the correct name.
  489. //
  490. STDAPI_(BOOL) IsCharAlphaWrap(WCHAR wch);
  491. STDAPI_(BOOL) IsCharAlphaNumericWrap(WCHAR wch);
  492. STDAPI_(BOOL) IsCharUpperWrap(WCHAR wch);
  493. STDAPI_(BOOL) IsCharLowerWrap(WCHAR wch);
  494. const DWORD adwData[218] =
  495. {
  496. 0x00000000, 0x07fffffe, 0xff7fffff, 0xffffffff, // 0x00-0x03
  497. 0xfc3fffff, 0x00ffffff, 0xffff0000, 0x000001ff, // 0x04-0x07
  498. 0xffffd740, 0xfffffffb, 0x547f7fff, 0x000ffffd, // 0x08-0x0b
  499. 0xffffdffe, 0xdffeffff, 0xffff0003, 0xffff199f, // 0x0c-0x0f
  500. 0x033fcfff, 0xfffe0000, 0x007fffff, 0xfffffffe, // 0x10-0x13
  501. 0x000000ff, 0x000707ff, 0x000007fe, 0x7cffffff, // 0x14-0x17
  502. 0x002f7fff, 0xffffffe0, 0x03ffffff, 0xff000000, // 0x18-0x1b
  503. 0x00000003, 0xfff99fe0, 0x03c5fdff, 0xb0000000, // 0x1c-0x1f
  504. 0x00030003, 0xfff987e0, 0x036dfdff, 0x5e000000, // 0x20-0x23
  505. 0xfffbafe0, 0x03edfdff, 0x00000001, 0x03cdfdff, // 0x24-0x27
  506. 0xd63dc7e0, 0x03bfc718, 0xfffddfe0, 0x03effdff, // 0x28-0x2b
  507. 0x40000000, 0x03fffdff, 0x000d7fff, 0x0000003f, // 0x2c-0x2f
  508. 0xfef02596, 0x00006cae, 0x30000000, 0xffff003f, // 0x30-0x33
  509. 0x83ffffff, 0xffffff07, 0x07ffffff, 0x3f3fffff, // 0x34-0x37
  510. 0xaaff3f3f, 0x3fffffff, 0x1fdfffff, 0x0fcf1fdc, // 0x38-0x3b
  511. 0x1fdc1fff, 0xf0000000, 0x000003ff, 0x00000020, // 0x3c-0x3f
  512. 0x781fffff, 0x77ffffff, 0xfffe1fff, 0x00007fff, // 0x40-0x43
  513. 0x0000000f, 0x00003fff, 0x80f8007f, 0x5f7fffff, // 0x44-0x47
  514. 0xffffffdb, 0x0003ffff, 0xfff80000, 0xfffffdff, // 0x48-0x4b
  515. 0xfffffffd, 0xfffcffff, 0x0fff0000, 0x1fffffff, // 0x4c-0x4f
  516. 0xffffffc0, 0x7ffffffe, 0x1cfcfcfc, 0x00003e00, // 0x50-0x53
  517. 0x00000fff, 0x80000000, 0xfc00fffe, 0xf8000001, // 0x54-0x57
  518. 0x78000001, 0x00800000, 0x00040000, 0x7fffffff, // 0x58-0x5b
  519. 0x44300003, 0x000000b0, 0x0000007c, 0xfe000000, // 0x5c-0x5f
  520. 0x00000200, 0x00180000, 0x88001000, 0x0007f801, // 0x60-0x63
  521. 0x00013c00, 0xffd00000, 0x0000000e, 0x001f3fff, // 0x64-0x67
  522. 0x0001003c, 0xd0000000, 0x0080399f, 0x07fc000c, // 0x68-0x6b
  523. 0x00000004, 0x00003987, 0x001f0000, 0x00013bbf, // 0x6c-0x6f
  524. 0x00c0398f, 0x00010000, 0x0000000c, 0xc0000000, // 0x70-0x73
  525. 0x00803dc7, 0x00603ddf, 0x00803dcf, 0x87f28000, // 0x74-0x77
  526. 0x0c00ffc0, 0x3bff8000, 0x00003f5f, 0x08000000, // 0x78-0x7b
  527. 0xe0000000, 0xe000e003, 0x6000e000, 0xffff7fff, // 0x7c-0x7f
  528. 0x0000007f, 0xfc00fc00, 0x00007c00, 0x01ffffff, // 0x80-0x83
  529. 0xffff0007, 0x000007ff, 0x0000001f, 0x003fffff, // 0x84-0x87
  530. 0xffffdfff, 0x0000ffff, 0xfc0fffff, 0xfffff3de, // 0x88-0x8b
  531. 0xfffffeff, 0x7f47afff, 0xffc000fe, 0xff1fffff, // 0x8c-0x8f
  532. 0x7ffeffff, 0x80ffffff, 0x7e000000, 0x78000000, // 0x90-0x93
  533. 0x8fffffff, 0x0001ffff, 0xffff0fff, 0xf87fffff, // 0x94-0x97
  534. 0xffff000f, 0xfff7fe1f, 0xffd70f7f, 0x0001003e, // 0x98-0x9b
  535. 0x00007f7f, 0x03ff0000, 0x020c0000, 0x0000ffc0, // 0x9c-0x9f
  536. 0x0007ff80, 0x03f10000, 0x0000007e, 0x7f7fffff, // 0xa0-0xa3
  537. 0x55555555, 0xaa555555, 0x555554aa, 0x2b555555, // 0xa4-0xa7
  538. 0xb1dbced6, 0x11aed295, 0x4aaaadb0, 0x54165555, // 0xa8-0xab
  539. 0x00555555, 0xfffed740, 0x00000ffb, 0x541c0000, // 0xac-0xaf
  540. 0x00005555, 0x55550001, 0x5555088a, 0x01154555, // 0xb0-0xb3
  541. 0x00155555, 0x01555555, 0x3f00ff00, 0xff00ff00, // 0xb4-0xb7
  542. 0xaa003f00, 0x0000ff00, 0x1f00ff00, 0x0f001f00, // 0xb8-0xbb
  543. 0x1f001f00, 0xffc00000, 0xaaaaaaaa, 0x55aaaaaa, // 0xbc-0xbf
  544. 0xaaaaab55, 0xd4aaaaaa, 0x4e243129, 0x2651292a, // 0xc0-0xc3
  545. 0xb5555b60, 0xa82daaaa, 0x00aaaaaa, 0xffaffbfb, // 0xc4-0xc7
  546. 0x640f7ffc, 0x000001f9, 0xfffff000, 0x00637fff, // 0xc8-0xcb
  547. 0x000faaa8, 0xaaaa0002, 0xaaaa1114, 0x022a8aaa, // 0xcc-0xcf
  548. 0x07eaaaaa, 0x02aaaaaa, 0x003f00ff, 0x00ff00ff, // 0xd0-0xd3
  549. 0x00ff003f, 0x3fff00ff, 0x00df00ff, 0x00cf00dc, // 0xd4-0xd7
  550. 0x00dc00ff, 0x00f8007f
  551. };
  552. const BYTE abIndex[98][8] =
  553. {
  554. { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x00
  555. { 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02 }, // 0x01
  556. { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04 }, // 0x02
  557. { 0x05, 0x00, 0x06, 0x03, 0x03, 0x07, 0x00, 0x00 }, // 0x03
  558. { 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x0a, 0x0b }, // 0x04
  559. { 0x0c, 0x03, 0x0d, 0x03, 0x0e, 0x03, 0x0f, 0x10 }, // 0x05
  560. { 0x00, 0x11, 0x12, 0x13, 0x14, 0x00, 0x06, 0x15 }, // 0x06
  561. { 0x00, 0x01, 0x16, 0x11, 0x03, 0x17, 0x18, 0x00 }, // 0x07
  562. { 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20 }, // 0x08
  563. { 0x21, 0x22, 0x23, 0x00, 0x24, 0x25, 0x00, 0x26 }, // 0x09
  564. { 0x1d, 0x27, 0x1f, 0x1c, 0x28, 0x29, 0x00, 0x00 }, // 0x0a
  565. { 0x2a, 0x2b, 0x00, 0x1c, 0x2a, 0x2b, 0x2c, 0x1c }, // 0x0b
  566. { 0x2a, 0x2d, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00 }, // 0x0c
  567. { 0x13, 0x2e, 0x2f, 0x00, 0x30, 0x31, 0x32, 0x00 }, // 0x0d
  568. { 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x33, 0x12 }, // 0x0e
  569. { 0x03, 0x03, 0x34, 0x03, 0x03, 0x35, 0x03, 0x1a }, // 0x0f
  570. { 0x03, 0x03, 0x03, 0x03, 0x36, 0x03, 0x03, 0x1a }, // 0x10
  571. { 0x37, 0x03, 0x38, 0x39, 0x03, 0x3a, 0x3b, 0x3c }, // 0x11
  572. { 0x00, 0x00, 0x00, 0x00, 0x3d, 0x03, 0x03, 0x3e }, // 0x12
  573. { 0x3f, 0x00, 0x13, 0x03, 0x40, 0x13, 0x03, 0x41 }, // 0x13
  574. { 0x19, 0x42, 0x03, 0x03, 0x43, 0x00, 0x00, 0x00 }, // 0x14
  575. { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 }, // 0x15
  576. { 0x03, 0x03, 0x03, 0x03, 0x03, 0x2f, 0x00, 0x00 }, // 0x16
  577. { 0x03, 0x03, 0x03, 0x03, 0x03, 0x44, 0x00, 0x00 }, // 0x17
  578. { 0x03, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x18
  579. { 0x46, 0x47, 0x48, 0x03, 0x03, 0x49, 0x4a, 0x4b }, // 0x19
  580. { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x4c }, // 0x1a
  581. { 0x03, 0x39, 0x06, 0x03, 0x4d, 0x03, 0x14, 0x4e }, // 0x1b
  582. { 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x4f }, // 0x1c
  583. { 0x00, 0x01, 0x01, 0x50, 0x03, 0x51, 0x52, 0x00 }, // 0x1d
  584. { 0x53, 0x26, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00 }, // 0x1e
  585. { 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x1f
  586. { 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x20
  587. { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55 }, // 0x21
  588. { 0x00, 0x56, 0x57, 0x58, 0x00, 0x13, 0x59, 0x59 }, // 0x22
  589. { 0x00, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00 }, // 0x23
  590. { 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x5b, 0x3e }, // 0x24
  591. { 0x03, 0x03, 0x2f, 0x5c, 0x5d, 0x00, 0x00, 0x00 }, // 0x25
  592. { 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00 }, // 0x26
  593. { 0x00, 0x00, 0x5f, 0x00, 0x60, 0x06, 0x44, 0x61 }, // 0x27
  594. { 0x62, 0x00, 0x63, 0x64, 0x00, 0x00, 0x65, 0x45 }, // 0x28
  595. { 0x66, 0x3d, 0x67, 0x68, 0x66, 0x69, 0x6a, 0x6b }, // 0x29
  596. { 0x6c, 0x69, 0x6d, 0x6e, 0x66, 0x3d, 0x6f, 0x00 }, // 0x2a
  597. { 0x66, 0x3d, 0x70, 0x71, 0x72, 0x73, 0x74, 0x00 }, // 0x2b
  598. { 0x66, 0x73, 0x75, 0x00, 0x72, 0x73, 0x75, 0x00 }, // 0x2c
  599. { 0x72, 0x73, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2d
  600. { 0x00, 0x77, 0x78, 0x00, 0x00, 0x79, 0x7a, 0x00 }, // 0x2e
  601. { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b }, // 0x2f
  602. { 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7d, 0x7e }, // 0x30
  603. { 0x03, 0x7f, 0x80, 0x81, 0x82, 0x54, 0x06, 0x1c }, // 0x31
  604. { 0x03, 0x83, 0x4a, 0x03, 0x84, 0x03, 0x03, 0x85 }, // 0x32
  605. { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x49 }, // 0x33
  606. { 0x4c, 0x03, 0x03, 0x36, 0x00, 0x00, 0x00, 0x00 }, // 0x34
  607. { 0x03, 0x86, 0x85, 0x03, 0x03, 0x03, 0x03, 0x85 }, // 0x35
  608. { 0x03, 0x03, 0x03, 0x03, 0x87, 0x88, 0x03, 0x89 }, // 0x36
  609. { 0x8a, 0x03, 0x03, 0x89, 0x00, 0x00, 0x00, 0x00 }, // 0x37
  610. { 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x00, 0x00 }, // 0x38
  611. { 0x13, 0x91, 0x00, 0x00, 0x92, 0x00, 0x00, 0x93 }, // 0x39
  612. { 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00 }, // 0x3a
  613. { 0x4f, 0x03, 0x44, 0x94, 0x03, 0x95, 0x96, 0x5b }, // 0x3b
  614. { 0x03, 0x03, 0x03, 0x97, 0x03, 0x03, 0x39, 0x5b }, // 0x3c
  615. { 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3d
  616. { 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3e
  617. { 0x00, 0x98, 0x99, 0x9a, 0x03, 0x03, 0x03, 0x4f }, // 0x3f
  618. { 0x56, 0x57, 0x58, 0x9b, 0x73, 0x26, 0x00, 0x9c }, // 0x40
  619. { 0x00, 0x9d, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00 }, // 0x41
  620. { 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x9d }, // 0x42
  621. { 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x9f }, // 0x43
  622. { 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0xa0 }, // 0x44
  623. { 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x00 }, // 0x45
  624. { 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x9d, 0x00 }, // 0x46
  625. { 0x00, 0x00, 0x00, 0xa1, 0x3e, 0x00, 0x00, 0x00 }, // 0x47
  626. { 0x9d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x48
  627. { 0x00, 0x9d, 0xa2, 0xa2, 0x00, 0x00, 0x00, 0x00 }, // 0x49
  628. { 0x9d, 0xa2, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4a
  629. { 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xa3, 0x00 }, // 0x4b
  630. { 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab }, // 0x4c
  631. { 0xac, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4d
  632. { 0x00, 0x00, 0x00, 0x00, 0xad, 0xae, 0xaf, 0xb0 }, // 0x4e
  633. { 0x0c, 0x89, 0x00, 0xa4, 0xb1, 0xa4, 0xb2, 0xb3 }, // 0x4f
  634. { 0x00, 0x11, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x50
  635. { 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x2f, 0x00 }, // 0x51
  636. { 0xa4, 0xa4, 0xa4, 0xa4, 0xb4, 0xa4, 0xa4, 0xb5 }, // 0x52
  637. { 0xb6, 0xb7, 0xb8, 0xb9, 0xb7, 0xba, 0xbb, 0xbc }, // 0x53
  638. { 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0x89, 0x00 }, // 0x54
  639. { 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x55
  640. { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x55, 0x02 }, // 0x56
  641. { 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5 }, // 0x57
  642. { 0xc6, 0x00, 0x06, 0xc7, 0xc8, 0xc9, 0x00, 0x00 }, // 0x58
  643. { 0x00, 0x00, 0x00, 0x00, 0x71, 0xca, 0xcb, 0xcc }, // 0x59
  644. { 0x00, 0x06, 0x0d, 0xbe, 0xcd, 0xbe, 0xce, 0xcf }, // 0x5a
  645. { 0x00, 0x00, 0x00, 0x13, 0x14, 0x00, 0x00, 0x00 }, // 0x5b
  646. { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x12 }, // 0x5c
  647. { 0xbe, 0xbe, 0xbe, 0xbe, 0xd0, 0xbe, 0xbe, 0xd1 }, // 0x5d
  648. { 0xd2, 0xd3, 0xd4, 0xd5, 0xd3, 0xd6, 0xd7, 0xd8 }, // 0x5e
  649. { 0x00, 0x00, 0x00, 0x00, 0x3d, 0x87, 0x06, 0x3e }, // 0x5f
  650. { 0xd9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x60
  651. { 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 } // 0x61
  652. };
  653. const BYTE abType1Alpha[256] = // 154
  654. {
  655. 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00,
  656. 0x00, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x00,
  657. 0x0e, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  658. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11,
  659. 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
  660. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  661. 0x13, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  662. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  663. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  664. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x15,
  665. 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
  666. 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
  667. 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
  668. 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
  669. 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
  670. 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
  671. 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
  672. 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
  673. 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
  674. 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x16,
  675. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  676. 0x00, 0x00, 0x00, 0x00, 0x15, 0x15, 0x15, 0x15,
  677. 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
  678. 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
  679. 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
  680. 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
  681. 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x17,
  682. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  683. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  684. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  685. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  686. 0x00, 0x15, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d
  687. };
  688. BOOL IsCharSpaceW(WCHAR wch)
  689. {
  690. int nType;
  691. switch(wch>>8)
  692. {
  693. case 0x00: nType = 0x1e; break;
  694. case 0x20: nType = 0x1f; break;
  695. case 0x30: nType = 0x20; break;
  696. case 0xfe: nType = 0x21; break;
  697. default: nType = 0x00; break;
  698. }
  699. return (adwData[abIndex[nType][(wch>>__INDEX_SHIFT)&__INDEX_MASK]]
  700. >>(wch&__BIT_MASK)) & 1;
  701. }
  702. const BYTE abType1Punct[256] = // 32
  703. {
  704. 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x00,
  705. 0x00, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x00,
  706. 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  707. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
  708. 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
  709. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  710. 0x39, 0x3a, 0x3b, 0x3c, 0x00, 0x00, 0x00, 0x00,
  711. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  712. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  713. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  714. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  715. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  716. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  717. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  718. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  719. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  720. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  721. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  722. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  723. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  724. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  725. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  726. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  727. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  728. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  729. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  730. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  731. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  732. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  733. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  734. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  735. 0x00, 0x00, 0x00, 0x3d, 0x00, 0x3e, 0x3f, 0x40
  736. };
  737. const BYTE abType1Digit[256] = // 11
  738. {
  739. 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00,
  740. 0x00, 0x43, 0x43, 0x44, 0x43, 0x45, 0x46, 0x00,
  741. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  742. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  743. 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  744. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  745. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  746. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  747. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  748. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  749. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  750. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  751. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  752. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  753. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  754. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  755. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  756. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  757. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  758. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  759. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  760. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  761. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  762. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  763. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  764. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  765. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  766. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  767. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  768. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  769. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  770. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48
  771. };
  772. BOOL IsCharDigitW(WCHAR wch) { return ISCHARFUNC(Digit, wch); }
  773. BOOL IsCharXDigitW(WCHAR wch)
  774. {
  775. int nType;
  776. switch(wch>>8)
  777. {
  778. case 0x00: nType = 0x49; break;
  779. case 0xff: nType = 0x4a; break;
  780. default: nType = 0x00; break;
  781. }
  782. return (adwData[abIndex[nType][(wch>>__INDEX_SHIFT)&__INDEX_MASK]]
  783. >> (wch&__BIT_MASK)) & 1;
  784. }
  785. const BYTE abType1Upper[256] = // 12
  786. {
  787. 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x00, 0x00,
  788. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  789. 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  790. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x53,
  791. 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
  792. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  793. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  794. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  795. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  796. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  797. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  798. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  799. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  800. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  801. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  802. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  803. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  804. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  805. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  806. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  807. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  808. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  809. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  810. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  811. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  812. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  813. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  814. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  815. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  816. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  817. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  818. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55
  819. };
  820. const BYTE abType1Lower[256] = // 13
  821. {
  822. 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x00, 0x00,
  823. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  824. 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  825. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x5e,
  826. 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00,
  827. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  828. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  829. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  830. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  831. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  832. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  833. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  834. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  835. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  836. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  837. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  838. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  839. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  840. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  841. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  842. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  843. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  844. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  845. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  846. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  847. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  848. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  849. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  850. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  851. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  852. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  853. 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x61
  854. };
  855. BOOL IsCharPunctW(WCHAR wch) { return ISCHARFUNC(Punct, wch); }
  856. BOOL IsCharCntrlW(WCHAR wch)
  857. {
  858. return (unsigned)(wch - 0x0000) <= (0x001f - 0x0000)
  859. || (unsigned)(wch - 0x007f) <= (0x009f - 0x007f);
  860. }
  861. // NB (cthrash) WCH_NBSP is considered blank, for compatibility.
  862. BOOL IsCharBlankW(WCHAR wch)
  863. {
  864. return wch == 0x0009
  865. || wch == 0x0020
  866. || wch == 0x00a0
  867. || wch == 0x3000
  868. || wch == 0xfeff;
  869. }
  870. BOOL IsCharAlphaWrap(WCHAR wch) { return ISCHARFUNC(Alpha, wch); }
  871. BOOL IsCharUpperWrap(WCHAR wch) { return ISCHARFUNC(Upper, wch); }
  872. BOOL IsCharLowerWrap(WCHAR wch) { return ISCHARFUNC(Lower, wch); }
  873. BOOL IsCharAlphaNumericWrap(WCHAR wch)
  874. {
  875. return ISCHARFUNC(Alpha, wch) || ISCHARFUNC(Digit, wch);
  876. }
  877. static const BYTE abType3PageSub[256] =
  878. {
  879. 0x00, 0x80, 0x81, 0x82, 0x00, 0x83, 0x84, 0x00,
  880. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00,
  881. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  882. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86,
  883. 0x00, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d,
  884. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  885. 0x00, 0x8e, 0x8f, 0x90, 0x00, 0x00, 0x00, 0x00,
  886. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  887. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  888. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20,
  889. 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
  890. 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
  891. 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
  892. 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
  893. 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
  894. 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
  895. 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
  896. 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
  897. 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
  898. 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x91,
  899. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  900. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  901. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  902. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  903. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  904. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  905. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  906. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  907. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  908. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  909. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  910. 0x00, 0x20, 0x92, 0x00, 0x00, 0x93, 0x94, 0x00
  911. };
  912. static const BYTE abType3Page0[256] =
  913. {
  914. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  915. 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
  916. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  917. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  918. 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08,
  919. 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x09, 0x09,
  920. 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  921. 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
  922. 0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  923. 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  924. 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  925. 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09,
  926. 0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  927. 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  928. 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  929. 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x00,
  930. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  931. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  932. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  933. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  934. 0x01, 0x01, 0x09, 0x09, 0x01, 0x09, 0x09, 0x01,
  935. 0x01, 0x01, 0x00, 0x01, 0x09, 0x01, 0x01, 0x09,
  936. 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
  937. 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
  938. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  939. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  940. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  941. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  942. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  943. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  944. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  945. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  946. };
  947. static const BYTE abType3Page32[256] =
  948. {
  949. 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  950. 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
  951. 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
  952. 0x11, 0x11, 0x01, 0x01, 0x11, 0x11, 0x01, 0x01,
  953. 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
  954. 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  955. 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  956. 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  957. 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
  958. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  959. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  960. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  961. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  962. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  963. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  964. 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
  965. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  966. 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
  967. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  968. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  969. 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  970. 0x01, 0x09, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
  971. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  972. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  973. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  974. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  975. 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  976. 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  977. 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  978. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  979. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  980. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  981. };
  982. static const BYTE abType3Page48[256] =
  983. {
  984. 0x11, 0x11, 0x11, 0x00, 0x00, 0x20, 0x01, 0x01,
  985. 0x01, 0x01, 0x01, 0x01, 0x11, 0x11, 0x01, 0x01,
  986. 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  987. 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01,
  988. 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  989. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  990. 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x01, 0x01,
  991. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  992. 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  993. 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  994. 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  995. 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  996. 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  997. 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  998. 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  999. 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  1000. 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  1001. 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  1002. 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00,
  1003. 0x00, 0x06, 0x06, 0x16, 0x16, 0x04, 0x04, 0x00,
  1004. 0x00, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,
  1005. 0x12, 0x12, 0x12, 0x12, 0x02, 0x12, 0x02, 0x12,
  1006. 0x02, 0x12, 0x02, 0x12, 0x02, 0x12, 0x02, 0x12,
  1007. 0x02, 0x12, 0x02, 0x12, 0x02, 0x12, 0x02, 0x12,
  1008. 0x02, 0x12, 0x02, 0x12, 0x12, 0x02, 0x12, 0x02,
  1009. 0x12, 0x02, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,
  1010. 0x02, 0x02, 0x12, 0x02, 0x02, 0x12, 0x02, 0x02,
  1011. 0x12, 0x02, 0x02, 0x12, 0x02, 0x02, 0x12, 0x12,
  1012. 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,
  1013. 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x02, 0x12,
  1014. 0x02, 0x02, 0x12, 0x12, 0x02, 0x02, 0x02, 0x02,
  1015. 0x02, 0x02, 0x02, 0x13, 0x06, 0x02, 0x02, 0x00
  1016. };
  1017. static const BYTE abType3Page255[256] =
  1018. {
  1019. 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10,
  1020. 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x11, 0x11,
  1021. 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
  1022. 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
  1023. 0x11, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
  1024. 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
  1025. 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
  1026. 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11,
  1027. 0x11, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
  1028. 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
  1029. 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
  1030. 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x00,
  1031. 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0a, 0x0a,
  1032. 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
  1033. 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
  1034. 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
  1035. 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
  1036. 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
  1037. 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
  1038. 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
  1039. 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  1040. 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  1041. 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  1042. 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00,
  1043. 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  1044. 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  1045. 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  1046. 0x00, 0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
  1047. 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00,
  1048. 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00,
  1049. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1050. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  1051. };
  1052. struct tagType3DualValue
  1053. {
  1054. DWORD adwBitfield[8];
  1055. DWORD adwValue[2];
  1056. }
  1057. const aType3DualValue[21] =
  1058. {
  1059. { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // Page1
  1060. 0x00000000, 0x0000000f, 0x00000000, 0x00000000, 0x00000001 },
  1061. { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // Page2
  1062. 0x00000000, 0x3f000000, 0x00000000, 0x00000000, 0x00000001 },
  1063. { 0x00000000, 0x00000000, 0x00000000, 0x04000000, 0x000000b0, // Page3
  1064. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001 },
  1065. { 0x00000000, 0x00000000, 0xf8000000, 0x00000000, 0x00000200, // Page5
  1066. 0x40000000, 0x00000009, 0x00180000, 0x00000000, 0x00000001 },
  1067. { 0x88001000, 0x00000000, 0x00000000, 0x00003c00, 0x00000000, // Page6
  1068. 0x00000000, 0x00100000, 0x00000200, 0x00000000, 0x00000001 },
  1069. { 0x00000000, 0x80008000, 0x0c008040, 0x00000000, 0x00000000, // Page14
  1070. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001 },
  1071. { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // Page31
  1072. 0xe0000000, 0xe000e003, 0x6000e000, 0x00000000, 0x00000001 },
  1073. { 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0xffff0000, // Page33
  1074. 0xffffffff, 0xffffffff, 0x000007ff, 0x00000000, 0x00000001 },
  1075. { 0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // Page34
  1076. 0x00000000, 0x00000000, 0xfffc0000, 0x00000001, 0x00000000 },
  1077. { 0x00000002, 0x00000000, 0x00000000, 0xf8000000, 0xffffffff, // Page35
  1078. 0xffffffff, 0xffffffff, 0xffffffff, 0x00000001, 0x00000000 },
  1079. { 0x00000000, 0xffffffe0, 0xfffff800, 0xffffffff, 0xffffffff, // Page36
  1080. 0xffffffff, 0xffffffff, 0xffffffff, 0x00000001, 0x00000000 },
  1081. { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffc00000, // Page37
  1082. 0x00002000, 0x00000000, 0xffff8000, 0x00000001, 0x00000000 },
  1083. { 0x03f00000, 0x00000000, 0x00000000, 0xffff0000, 0xffffffff, // Page38
  1084. 0xffffffff, 0xffffffff, 0xffffffff, 0x00000001, 0x00000000 },
  1085. { 0xfffff3de, 0xfffffeff, 0x7f47afff, 0x000000fe, 0xff100000, // Page39
  1086. 0x7ffeffff, 0x00000000, 0x00000000, 0x00000000, 0x00000001 },
  1087. { 0x00000000, 0xfffe0000, 0xffffffff, 0x0000001f, 0x00000000, // Page49
  1088. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000010 },
  1089. { 0x00000000, 0x00000000, 0x00000000, 0x80000000, 0x00000000, // Page50
  1090. 0x00000000, 0x00000fff, 0x00000000, 0x00000000, 0x00000001 },
  1091. { 0x00000000, 0x00000000, 0xff000000, 0x0001ffff, 0x00000000, // Page51
  1092. 0x00000000, 0x00000000, 0x7fffffff, 0x00000000, 0x00000001 },
  1093. { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // Page159
  1094. 0xffffffc0, 0xffffffff, 0xffffffff, 0x00000020, 0x00000000 },
  1095. { 0x00000000, 0xffffc000, 0xffffffff, 0xffffffff, 0xffffffff, // Page250
  1096. 0xffffffff, 0xffffffff, 0xffffffff, 0x00000020, 0x00000000 },
  1097. { 0x00000000, 0xc0000000, 0x00000000, 0x00000000, 0x00000000, // Page253
  1098. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001 },
  1099. { 0x00000000, 0xfff90000, 0xfef7fe1f, 0x00000f77, 0x00000000, // Page254
  1100. 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001 }
  1101. };
  1102. //
  1103. // CType 3 Flag Bits.
  1104. //
  1105. // In the interest of reducing our table complexity, we've here a reduced
  1106. // bitfield. Only those bits currently used by IE4 are returned by
  1107. // GetStringType3Ex().
  1108. //
  1109. // These are the flags are they are defined in winnls.h
  1110. //
  1111. // C3_NONSPACING 0x0001
  1112. // C3_DIACRITIC 0x0002
  1113. // C3_VOWELMARK 0x0004
  1114. // C3_SYMBOL 0x0008
  1115. // C3_KATAKANA 0x0010
  1116. // C3_HIRAGANA 0x0020
  1117. // C3_HALFWIDTH 0x0040
  1118. // C3_FULLWIDTH 0x0080
  1119. // C3_IDEOGRAPH 0x0100
  1120. // C3_KASHIDA 0x0200
  1121. // C3_LEXICAL 0x0400
  1122. // C3_ALPHA 0x8000
  1123. // The supported flags are encoded by shifting them to the right 3 bits.
  1124. // C3_SYMBOL 0x0001
  1125. // C3_KATAKANA 0x0002
  1126. // C3_HIRAGANA 0x0004
  1127. // C3_HALFWIDTH 0x0008
  1128. // C3_FULLWIDTH 0x0010
  1129. // C3_IDEOGRAPH 0x0020
  1130. // GetStringType3Ex returns the correct Win32 flags NOT the compressed flags.
  1131. BOOL GetStringType3ExW(
  1132. LPCWSTR lpSrcStr, // string arg
  1133. int cchSrc, // length (or -1)
  1134. LPWORD lpCharType ) // output buffer
  1135. {
  1136. LPCWSTR lpStop = lpSrcStr + ((cchSrc == -1) ? MAXLONG : cchSrc);
  1137. while (lpSrcStr < lpStop)
  1138. {
  1139. WCHAR wch = *lpSrcStr++;
  1140. WORD wCharType;
  1141. BYTE bPageSub;
  1142. if (!wch && cchSrc == -1)
  1143. break;
  1144. switch (wch & (unsigned int)0xff00)
  1145. {
  1146. case 0x0000:
  1147. wCharType = abType3Page0[wch]; // Page0: 4 values
  1148. break;
  1149. case 0x2000:
  1150. wCharType = abType3Page32[wch & 0xff]; // Page32: 4 values
  1151. break;
  1152. case 0x3000:
  1153. wCharType = abType3Page48[wch & 0xff]; // Page48: 10 values
  1154. break;
  1155. case 0xff00:
  1156. wCharType = abType3Page255[wch & 0xff]; // Page255: 7 values
  1157. break;
  1158. default:
  1159. bPageSub = abType3PageSub[wch>>8];
  1160. if (bPageSub & 0x80) // 21 pages have 2 values
  1161. {
  1162. const struct tagType3DualValue *p = aType3DualValue +
  1163. (bPageSub & 0x7f);
  1164. wCharType = (BYTE) p->adwValue[(p->adwBitfield[(wch>>5)&7]
  1165. >> (wch & 0x1f)) & 1];
  1166. }
  1167. else // 231 pages have 1 value
  1168. {
  1169. wCharType = bPageSub;
  1170. }
  1171. break;
  1172. }
  1173. *lpCharType++ = wCharType << 3;
  1174. }
  1175. return TRUE;
  1176. }
  1177. //
  1178. // Str Functions from SHLWAPI
  1179. //
  1180. int StrCmpW(
  1181. IN LPCWSTR pwsz1,
  1182. IN LPCWSTR pwsz2)
  1183. {
  1184. int iRet = -1; // arbitrary on failure
  1185. ASSERT(IS_VALID_STRING_PTRW(pwsz1, -1));
  1186. ASSERT(IS_VALID_STRING_PTRW(pwsz2, -1));
  1187. if (pwsz1 && pwsz2)
  1188. {
  1189. CStrIn psz1(pwsz1);
  1190. CStrIn psz2(pwsz2);
  1191. iRet = lstrcmpA(psz1, psz2);
  1192. }
  1193. return iRet;
  1194. }
  1195. int StrCmpIW(
  1196. IN LPCWSTR pwsz1,
  1197. IN LPCWSTR pwsz2)
  1198. {
  1199. int iRet = -1; // arbitrary on failure
  1200. ASSERT(IS_VALID_STRING_PTRW(pwsz1, -1));
  1201. ASSERT(IS_VALID_STRING_PTRW(pwsz2, -1));
  1202. if (pwsz1 && pwsz2)
  1203. {
  1204. CStrIn psz1(pwsz1);
  1205. CStrIn psz2(pwsz2);
  1206. iRet = lstrcmpiA(psz1, psz2);
  1207. }
  1208. return iRet;
  1209. }
  1210. #if 0 // BUGBUG: We have another StrCpyW in strings.c
  1211. LPWSTR StrCpyW(LPWSTR psz1, LPCWSTR psz2)
  1212. {
  1213. LPWSTR psz = psz1;
  1214. ASSERT(psz1);
  1215. ASSERT(psz2);
  1216. while (*psz1++ = *psz2++)
  1217. ;
  1218. return psz;
  1219. }
  1220. #endif
  1221. LPWSTR StrCatW(LPWSTR psz1, LPCWSTR psz2)
  1222. {
  1223. LPWSTR psz = psz1;
  1224. ASSERT(psz1);
  1225. ASSERT(psz2);
  1226. while (0 != *psz1)
  1227. psz1++;
  1228. while (*psz1++ = *psz2++)
  1229. ;
  1230. return psz;
  1231. }
  1232. //+------------------------------------------------------------------------
  1233. //
  1234. // Implementation of the wrapped functions
  1235. //
  1236. //-------------------------------------------------------------------------
  1237. BOOL AppendMenuWrap(
  1238. HMENU hMenu,
  1239. UINT uFlags,
  1240. UINT uIDnewItem,
  1241. LPCWSTR lpnewItem)
  1242. {
  1243. ASSERT(!(uFlags & MF_BITMAP) && !(uFlags & MF_OWNERDRAW));
  1244. CStrIn str(lpnewItem);
  1245. return AppendMenuA(hMenu, uFlags, uIDnewItem, str);
  1246. }
  1247. BOOL CallMsgFilterWrap(LPMSG lpMsg, int nCode)
  1248. {
  1249. return CallMsgFilterA(lpMsg, nCode);
  1250. }
  1251. LRESULT CallWindowProcWrap(
  1252. WNDPROC lpPrevWndFunc,
  1253. HWND hWnd,
  1254. UINT Msg,
  1255. WPARAM wParam,
  1256. LPARAM lParam)
  1257. {
  1258. return CallWindowProcA(lpPrevWndFunc, hWnd, Msg, wParam, lParam);
  1259. }
  1260. //----------------------------------------------------------------------
  1261. //
  1262. // function: CharLowerWrap( LPWSTR pch )
  1263. //
  1264. // purpose: Converts character to lowercase. Takes either a pointer
  1265. // to a string, or a character masquerading as a pointer.
  1266. // In the later case, the HIWORD must be zero. This is
  1267. // as spec'd for Win32.
  1268. //
  1269. // returns: Lowercased character or string. In the string case,
  1270. // the lowercasing is done inplace.
  1271. //
  1272. //----------------------------------------------------------------------
  1273. LPWSTR CharLowerWrap( LPWSTR pch )
  1274. {
  1275. if (!HIWORD64(pch))
  1276. {
  1277. WCHAR ch = (WCHAR)(LONG_PTR)pch;
  1278. CharLowerBuffWrap( &ch, 1 );
  1279. pch = (LPWSTR)MAKEINTATOM(ch);
  1280. }
  1281. else
  1282. {
  1283. CharLowerBuffWrap( pch, lstrlenW(pch) );
  1284. }
  1285. return pch;
  1286. }
  1287. //----------------------------------------------------------------------
  1288. //
  1289. // function: CharLowerBuffWrap( LPWSTR pch, DWORD cch )
  1290. //
  1291. // purpose: Converts a string to lowercase. String must be cch
  1292. // characters in length.
  1293. //
  1294. // returns: Character count (cch). The lowercasing is done inplace.
  1295. //
  1296. //----------------------------------------------------------------------
  1297. DWORD CharLowerBuffWrap( LPWSTR pch, DWORD cchLength )
  1298. {
  1299. DWORD cch;
  1300. for ( cch = cchLength; cch-- ; pch++ )
  1301. {
  1302. WCHAR ch = *pch;
  1303. if (IsCharUpperWrap(ch))
  1304. {
  1305. if (ch < 0x0100)
  1306. {
  1307. *pch += 32; // Get Latin-1 out of the way first
  1308. }
  1309. else if (ch < 0x0531)
  1310. {
  1311. if (ch < 0x0391)
  1312. {
  1313. if (ch < 0x01cd)
  1314. {
  1315. if (ch <= 0x178)
  1316. {
  1317. if (ch < 0x0178)
  1318. {
  1319. *pch += (ch == 0x0130) ? 0 : 1;
  1320. }
  1321. else
  1322. {
  1323. *pch -= 121;
  1324. }
  1325. }
  1326. else
  1327. {
  1328. static const BYTE abLookup[] =
  1329. { // 0/8 1/9 2/a 3/b 4/c 5/d 6/e 7/f
  1330. /* 0x0179-0x17f */ 1, 0, 1, 0, 1, 0, 0,
  1331. /* 0x0180-0x187 */ 0, 210, 1, 0, 1, 0, 206, 1,
  1332. /* 0x0188-0x18f */ 0, 205, 205, 1, 0, 0, 79, 202,
  1333. /* 0x0190-0x197 */ 203, 1, 0, 205, 207, 0, 211, 209,
  1334. /* 0x0198-0x19f */ 1, 0, 0, 0, 211, 213, 0, 214,
  1335. /* 0x01a0-0x1a7 */ 1, 0, 1, 0, 1, 0, 0, 1,
  1336. /* 0x01a8-0x1af */ 0, 218, 0, 0, 1, 0, 218, 1,
  1337. /* 0x01b0-0x1b7 */ 0, 217, 217, 1, 0, 1, 0, 219,
  1338. /* 0x01b8-0x1bf */ 1, 0, 0, 0, 1, 0, 0, 0,
  1339. /* 0x01c0-0x1c7 */ 0, 0, 0, 0, 2, 0, 0, 2,
  1340. /* 0x01c8-0x1cb */ 0, 0, 2, 0
  1341. };
  1342. *pch += abLookup[ch-0x0179];
  1343. }
  1344. }
  1345. else if (ch < 0x0386)
  1346. {
  1347. switch (ch)
  1348. {
  1349. case 0x01f1: *pch += 2; break;
  1350. case 0x01f2: break;
  1351. default: *pch += 1;
  1352. }
  1353. }
  1354. else
  1355. {
  1356. static const BYTE abLookup[] =
  1357. { 38, 0, 37, 37, 37, 0, 64, 0, 63, 63 };
  1358. *pch += abLookup[ch-0x0386];
  1359. }
  1360. }
  1361. else
  1362. {
  1363. if (ch < 0x0410)
  1364. {
  1365. if (ch < 0x0401)
  1366. {
  1367. if (ch < 0x03e2)
  1368. {
  1369. if (!InRange(ch, 0x03d2, 0x03d4) &&
  1370. !(InRange(ch, 0x3da, 0x03e0) & !(ch & 1)))
  1371. {
  1372. *pch += 32;
  1373. }
  1374. }
  1375. else
  1376. {
  1377. *pch += 1;
  1378. }
  1379. }
  1380. else
  1381. {
  1382. *pch += 80;
  1383. }
  1384. }
  1385. else
  1386. {
  1387. if (ch < 0x0460)
  1388. {
  1389. *pch += 32;
  1390. }
  1391. else
  1392. {
  1393. *pch += 1;
  1394. }
  1395. }
  1396. }
  1397. }
  1398. else
  1399. {
  1400. if (ch < 0x2160)
  1401. {
  1402. if (ch < 0x1fba)
  1403. {
  1404. if (ch < 0x1f08)
  1405. {
  1406. if (ch < 0x1e00)
  1407. {
  1408. *pch += 48;
  1409. }
  1410. else
  1411. {
  1412. *pch += 1;
  1413. }
  1414. }
  1415. else if (!(InRange(ch, 0x1f88, 0x1faf) && (ch & 15)>7))
  1416. {
  1417. *pch -= 8;
  1418. }
  1419. }
  1420. else
  1421. {
  1422. static const BYTE abLookup[] =
  1423. { // 8 9 a b c d e f
  1424. 0, 0, 74, 74, 0, 0, 0, 0,
  1425. 86, 86, 86, 86, 0, 0, 0, 0,
  1426. 8, 8, 100, 100, 0, 0, 0, 0,
  1427. 8, 8, 112, 112, 7, 0, 0, 0,
  1428. 128, 128, 126, 126, 0, 0, 0, 0
  1429. };
  1430. int i = (ch-0x1fb0);
  1431. *pch -= (int)abLookup[((i>>1) & ~7) | (i & 7)];
  1432. }
  1433. }
  1434. else
  1435. {
  1436. if (ch < 0xff21)
  1437. {
  1438. if (ch < 0x24b6)
  1439. {
  1440. *pch += 16;
  1441. }
  1442. else
  1443. {
  1444. *pch += 26;
  1445. }
  1446. }
  1447. else
  1448. {
  1449. *pch += 32;
  1450. }
  1451. }
  1452. }
  1453. }
  1454. else
  1455. {
  1456. // These are Unicode Number Forms. They have lowercase counter-
  1457. // parts, but are not considered uppercase. Why, I don't know.
  1458. if (InRange(ch, 0x2160, 0x216f))
  1459. {
  1460. *pch += 16;
  1461. }
  1462. }
  1463. }
  1464. return cchLength;
  1465. }
  1466. //
  1467. // BUGBUG - Do CharNextWrap and CharPrevWrap need to call the
  1468. // CharNextW, CharPrevW on WinNT? Couldn't these be MACROS?
  1469. LPWSTR CharNextWrap(LPCWSTR lpszCurrent)
  1470. {
  1471. if (*lpszCurrent)
  1472. {
  1473. return (LPWSTR) lpszCurrent + 1;
  1474. }
  1475. else
  1476. {
  1477. return (LPWSTR) lpszCurrent;
  1478. }
  1479. }
  1480. LPWSTR CharPrevWrap(LPCWSTR lpszStart, LPCWSTR lpszCurrent)
  1481. {
  1482. if (lpszCurrent == lpszStart)
  1483. {
  1484. return (LPWSTR) lpszStart;
  1485. }
  1486. else
  1487. {
  1488. return (LPWSTR) lpszCurrent - 1;
  1489. }
  1490. }
  1491. BOOL CharToOemWrap(LPCWSTR lpszSrc, LPSTR lpszDst)
  1492. {
  1493. CStrIn str(lpszSrc);
  1494. return CharToOemA(str, lpszDst);
  1495. }
  1496. //----------------------------------------------------------------------
  1497. //
  1498. // function: CharUpperWrap( LPWSTR pch )
  1499. //
  1500. // purpose: Converts character to uppercase. Takes either a pointer
  1501. // to a string, or a character masquerading as a pointer.
  1502. // In the later case, the HIWORD must be zero. This is
  1503. // as spec'd for Win32.
  1504. //
  1505. // returns: Uppercased character or string. In the string case,
  1506. // the uppercasing is done inplace.
  1507. //
  1508. //----------------------------------------------------------------------
  1509. LPWSTR CharUpperWrap( LPWSTR pch )
  1510. {
  1511. if (!HIWORD64(pch))
  1512. {
  1513. WCHAR ch = (WCHAR)(LONG_PTR)pch;
  1514. CharUpperBuffWrap( &ch, 1 );
  1515. pch = (LPWSTR)MAKEINTATOM(ch);
  1516. }
  1517. else
  1518. {
  1519. CharUpperBuffWrap( pch, lstrlenW(pch) );
  1520. }
  1521. return pch;
  1522. }
  1523. //----------------------------------------------------------------------
  1524. //
  1525. // function: CharUpperBuffWrap( LPWSTR pch, DWORD cch )
  1526. //
  1527. // purpose: Converts a string to uppercase. String must be cch
  1528. // characters in length. Note that this function is
  1529. // is messier that CharLowerBuffWrap, and the reason for
  1530. // this is many Unicode characters are considered uppercase,
  1531. // even when they don't have an uppercase counterpart.
  1532. //
  1533. // returns: Character count (cch). The uppercasing is done inplace.
  1534. //
  1535. //----------------------------------------------------------------------
  1536. DWORD CharUpperBuffWrap( LPWSTR pch, DWORD cchLength )
  1537. {
  1538. DWORD cch;
  1539. for ( cch = cchLength; cch-- ; pch++ )
  1540. {
  1541. WCHAR ch = *pch;
  1542. if (IsCharLowerWrap(ch))
  1543. {
  1544. if (ch < 0x00ff)
  1545. {
  1546. *pch -= ((ch != 0xdf) << 5);
  1547. }
  1548. else if (ch < 0x03b1)
  1549. {
  1550. if (ch < 0x01f5)
  1551. {
  1552. if (ch < 0x01ce)
  1553. {
  1554. if (ch < 0x017f)
  1555. {
  1556. if (ch < 0x0101)
  1557. {
  1558. *pch += 121;
  1559. }
  1560. else
  1561. {
  1562. *pch -= (ch != 0x0131 &&
  1563. ch != 0x0138 &&
  1564. ch != 0x0149);
  1565. }
  1566. }
  1567. else if (ch < 0x01c9)
  1568. {
  1569. static const BYTE abMask[] =
  1570. { // 6543210f edcba987
  1571. 0xfc, 0xbf, // 11111100 10111111
  1572. 0xbf, 0x67, // 10111111 01100111
  1573. 0xff, 0xef, // 11111111 11101111
  1574. 0xff, 0xf7, // 11111111 11110111
  1575. 0xbf, 0xfd // 10111111 11111101
  1576. };
  1577. int i = ch - 0x017f;
  1578. *pch -= ((abMask[i>>3] >> (i&7)) & 1) +
  1579. (ch == 0x01c6);
  1580. }
  1581. else
  1582. {
  1583. *pch -= ((ch != 0x01cb)<<1);
  1584. }
  1585. }
  1586. else
  1587. {
  1588. if (ch < 0x01df)
  1589. {
  1590. if (ch < 0x01dd)
  1591. {
  1592. *pch -= 1;
  1593. }
  1594. else
  1595. {
  1596. *pch -= 79;
  1597. }
  1598. }
  1599. else
  1600. {
  1601. *pch -= 1 + (ch == 0x01f3) -
  1602. InRange(ch,0x01f0,0x01f2);
  1603. }
  1604. }
  1605. }
  1606. else if (ch < 0x0253)
  1607. {
  1608. *pch -= (ch < 0x0250);
  1609. }
  1610. else if (ch < 0x03ac)
  1611. {
  1612. static const BYTE abLookup[] =
  1613. {// 0/8 1/9 2/a 3/b 4/c 5/d 6/e 7/f
  1614. /* 0x0253-0x0257 */ 210, 206, 0, 205, 205,
  1615. /* 0x0258-0x025f */ 0, 202, 0, 203, 0, 0, 0, 0,
  1616. /* 0x0260-0x0267 */ 205, 0, 0, 207, 0, 0, 0, 0,
  1617. /* 0x0268-0x026f */ 209, 211, 0, 0, 0, 0, 0, 211,
  1618. /* 0x0270-0x0277 */ 0, 0, 213, 0, 0, 214, 0, 0,
  1619. /* 0x0278-0x027f */ 0, 0, 0, 0, 0, 0, 0, 0,
  1620. /* 0x0280-0x0287 */ 0, 0, 0, 218, 0, 0, 0, 0,
  1621. /* 0x0288-0x028f */ 218, 0, 217, 217, 0, 0, 0, 0,
  1622. /* 0x0290-0x0297 */ 0, 0, 219
  1623. };
  1624. if (ch <= 0x0292)
  1625. {
  1626. *pch -= abLookup[ch - 0x0253];
  1627. }
  1628. }
  1629. else
  1630. {
  1631. *pch -= (ch == 0x03b0) ? 0 : (37 + (ch == 0x03ac));
  1632. }
  1633. }
  1634. else
  1635. {
  1636. if (ch < 0x0561)
  1637. {
  1638. if (ch < 0x0451)
  1639. {
  1640. if (ch < 0x03e3)
  1641. {
  1642. if (ch < 0x03cc)
  1643. {
  1644. *pch -= (ch != 0x03c2)<<5;
  1645. }
  1646. else
  1647. {
  1648. int i = (ch < 0x03d0);
  1649. *pch -= (i<<6) - i + (ch == 0x03cc);
  1650. }
  1651. }
  1652. else if (ch < 0x0430)
  1653. {
  1654. *pch -= (ch < 0x03f0);
  1655. }
  1656. else
  1657. {
  1658. *pch -= 32;
  1659. }
  1660. }
  1661. else if (ch < 0x0461)
  1662. {
  1663. *pch -= 80;
  1664. }
  1665. else
  1666. {
  1667. *pch -= 1;
  1668. }
  1669. }
  1670. else
  1671. {
  1672. if (ch < 0x1fb0)
  1673. {
  1674. if (ch < 0x1f70)
  1675. {
  1676. if (ch < 0x1e01)
  1677. {
  1678. int i = ch != 0x0587 && ch != 0x10f6;
  1679. *pch -= ((i<<5)+(i<<4)); /* 48 */
  1680. }
  1681. else if (ch < 0x1f00)
  1682. {
  1683. *pch -= !InRange(ch, 0x1e96, 0x1e9a);
  1684. }
  1685. else
  1686. {
  1687. int i = !InRange(ch, 0x1f50, 0x1f56)||(ch & 1);
  1688. *pch += (i<<3);
  1689. }
  1690. }
  1691. else
  1692. {
  1693. static const BYTE abLookup[] =
  1694. { 74, 86, 86, 100, 128, 112, 126 };
  1695. if ( ch <= 0x1f7d )
  1696. {
  1697. *pch += abLookup[(ch-0x1f70)>>1];
  1698. }
  1699. }
  1700. }
  1701. else
  1702. {
  1703. if (ch < 0x24d0)
  1704. {
  1705. if (ch < 0x1fe5)
  1706. {
  1707. *pch += (0x0023 & (1<<(ch&15))) ? 8 : 0;
  1708. }
  1709. else if (ch < 0x2170)
  1710. {
  1711. *pch += (0x0023 & (1<<(ch&15))) ? 7 : 0;
  1712. }
  1713. else
  1714. {
  1715. *pch -= ((ch > 0x24b5)<<4);
  1716. }
  1717. }
  1718. else if (ch < 0xff41)
  1719. {
  1720. int i = !InRange(ch, 0xfb00, 0xfb17);
  1721. *pch -= (i<<4)+(i<<3)+(i<<1); /* 26 */
  1722. }
  1723. else
  1724. {
  1725. *pch -= 32;
  1726. }
  1727. }
  1728. }
  1729. }
  1730. }
  1731. else
  1732. {
  1733. int i = InRange(ch, 0x2170, 0x217f);
  1734. *pch -= (i<<4);
  1735. }
  1736. }
  1737. return cchLength;
  1738. }
  1739. int CopyAcceleratorTableWrap(
  1740. HACCEL hAccelSrc,
  1741. LPACCEL lpAccelDst,
  1742. int cAccelEntries)
  1743. {
  1744. return CopyAcceleratorTableA(hAccelSrc, lpAccelDst, cAccelEntries);
  1745. }
  1746. HACCEL CreateAcceleratorTableWrap(LPACCEL lpAccel, int cEntries)
  1747. {
  1748. return CreateAcceleratorTableA(lpAccel, cEntries);
  1749. }
  1750. typedef HDC (*FnCreateHDCA)(LPCSTR, LPCSTR, LPCSTR, CONST DEVMODEA *);
  1751. HDC CreateHDCWrap(
  1752. LPCWSTR lpszDriver,
  1753. LPCWSTR lpszDevice,
  1754. LPCWSTR lpszOutput,
  1755. CONST DEVMODEW * lpInitData,
  1756. FnCreateHDCA pfn)
  1757. {
  1758. DEVMODEA * pdevmode = NULL;
  1759. CStrIn strDriver(lpszDriver);
  1760. CStrIn strDevice(lpszDevice);
  1761. CStrIn strOutput(lpszOutput);
  1762. HDC hdcReturn = 0;
  1763. if (lpInitData)
  1764. {
  1765. pdevmode = (DEVMODEA *) LocalAlloc( LPTR, lpInitData->dmSize + lpInitData->dmDriverExtra );
  1766. if (pdevmode)
  1767. {
  1768. MbcsFromUnicode((CHAR *)pdevmode->dmDeviceName, CCHDEVICENAME, lpInitData->dmDeviceName);
  1769. memcpy(&pdevmode->dmSpecVersion,
  1770. &lpInitData->dmSpecVersion,
  1771. FIELD_OFFSET(DEVMODEW,dmFormName) - FIELD_OFFSET(DEVMODEW,dmSpecVersion));
  1772. MbcsFromUnicode((CHAR *)pdevmode->dmFormName, CCHFORMNAME, lpInitData->dmFormName);
  1773. memcpy(&pdevmode->dmLogPixels,
  1774. &lpInitData->dmLogPixels,
  1775. lpInitData->dmDriverExtra + lpInitData->dmSize - FIELD_OFFSET(DEVMODEW, dmLogPixels));
  1776. pdevmode->dmSize -= (sizeof(BCHAR) - sizeof(char)) * (CCHDEVICENAME + CCHFORMNAME);
  1777. }
  1778. }
  1779. hdcReturn = (*pfn)(strDriver, strDevice, strOutput, pdevmode);
  1780. if (pdevmode)
  1781. {
  1782. LocalFree(pdevmode);
  1783. }
  1784. return hdcReturn;
  1785. }
  1786. HDC CreateDCWrap(
  1787. LPCWSTR lpszDriver,
  1788. LPCWSTR lpszDevice,
  1789. LPCWSTR lpszOutput,
  1790. CONST DEVMODEW * lpInitData)
  1791. {
  1792. return CreateHDCWrap(lpszDriver, lpszDevice, lpszOutput, lpInitData, CreateDCA);
  1793. }
  1794. HDC CreateICWrap(
  1795. LPCWSTR lpszDriver,
  1796. LPCWSTR lpszDevice,
  1797. LPCWSTR lpszOutput,
  1798. CONST DEVMODEW * lpInitData)
  1799. {
  1800. return CreateHDCWrap(lpszDriver, lpszDevice, lpszOutput, lpInitData, CreateICA);
  1801. }
  1802. BOOL CreateDirectoryWrap(
  1803. LPCWSTR lpPathName,
  1804. LPSECURITY_ATTRIBUTES lpSecurityAttributes)
  1805. {
  1806. CStrIn str(lpPathName);
  1807. ASSERT(!lpSecurityAttributes);
  1808. return CreateDirectoryA(str, lpSecurityAttributes);
  1809. }
  1810. HANDLE CreateEventWrap(
  1811. LPSECURITY_ATTRIBUTES lpEventAttributes,
  1812. BOOL bManualReset,
  1813. BOOL bInitialState,
  1814. LPCWSTR lpName)
  1815. {
  1816. return CreateEventA(lpEventAttributes, bManualReset, bInitialState, (LPCSTR) lpName);
  1817. }
  1818. HANDLE CreateFileWrap(
  1819. LPCWSTR lpFileName,
  1820. DWORD dwDesiredAccess,
  1821. DWORD dwShareMode,
  1822. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  1823. DWORD dwCreationDisposition,
  1824. DWORD dwFlagsAndAttributes,
  1825. HANDLE hTemplateFile)
  1826. {
  1827. CStrIn str(lpFileName);
  1828. return CreateFileA(
  1829. str,
  1830. dwDesiredAccess,
  1831. dwShareMode,
  1832. lpSecurityAttributes,
  1833. dwCreationDisposition,
  1834. dwFlagsAndAttributes,
  1835. hTemplateFile);
  1836. }
  1837. HANDLE CreateFileMappingWrap(
  1838. HANDLE hFile,
  1839. LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
  1840. DWORD flProtect,
  1841. DWORD dwMaxSizeHigh,
  1842. DWORD dwMaxSizeLow,
  1843. LPCWSTR lpName)
  1844. {
  1845. CStrIn str(lpName);
  1846. return CreateFileMappingA(
  1847. hFile,
  1848. lpFileMappingAttributes,
  1849. flProtect,
  1850. dwMaxSizeHigh,
  1851. dwMaxSizeLow,
  1852. str);
  1853. }
  1854. HFONT CreateFontWrap(
  1855. int nHeight,
  1856. int nWidth,
  1857. int nEscapement,
  1858. int nOrientation,
  1859. int fnWeight,
  1860. DWORD fdwItalic,
  1861. DWORD fdwUnderline,
  1862. DWORD fdwStrikeOut,
  1863. DWORD fdwCharSet,
  1864. DWORD fdwOutputPrecision,
  1865. DWORD fdwClipPrecision,
  1866. DWORD fdwQuality,
  1867. DWORD fdwPitchAndFamily,
  1868. LPCWSTR lpszFace)
  1869. {
  1870. CStrIn str(lpszFace);
  1871. return CreateFontA(
  1872. nHeight,
  1873. nWidth,
  1874. nEscapement,
  1875. nOrientation,
  1876. fnWeight,
  1877. fdwItalic,
  1878. fdwUnderline,
  1879. fdwStrikeOut,
  1880. fdwCharSet,
  1881. fdwOutputPrecision,
  1882. fdwClipPrecision,
  1883. fdwQuality,
  1884. fdwPitchAndFamily,
  1885. str);
  1886. }
  1887. HFONT CreateFontIndirectWrap(CONST LOGFONTW * plfw)
  1888. {
  1889. LOGFONTA lfa;
  1890. HFONT hFont;
  1891. memcpy(&lfa, plfw, FIELD_OFFSET(LOGFONTA, lfFaceName));
  1892. MbcsFromUnicode(lfa.lfFaceName, ARRAYSIZE(lfa.lfFaceName), plfw->lfFaceName);
  1893. hFont = CreateFontIndirectA(&lfa);
  1894. return hFont;
  1895. }
  1896. HWND CreateWindowExWrap(
  1897. DWORD dwExStyle,
  1898. LPCWSTR lpClassName,
  1899. LPCWSTR lpWindowName,
  1900. DWORD dwStyle,
  1901. int X,
  1902. int Y,
  1903. int nWidth,
  1904. int nHeight,
  1905. HWND hWndParent,
  1906. HMENU hMenu,
  1907. HINSTANCE hInstance,
  1908. LPVOID lpParam)
  1909. {
  1910. CStrIn strClass(lpClassName);
  1911. CStrIn strWindow(lpWindowName);
  1912. return CreateWindowExA(
  1913. dwExStyle,
  1914. strClass,
  1915. strWindow,
  1916. dwStyle,
  1917. X,
  1918. Y,
  1919. nWidth,
  1920. nHeight,
  1921. hWndParent,
  1922. hMenu,
  1923. hInstance,
  1924. lpParam);
  1925. }
  1926. LRESULT DefWindowProcWrap(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1927. {
  1928. return DefWindowProcA(hWnd, msg, wParam, lParam);
  1929. }
  1930. BOOL DeleteFileWrap(LPCWSTR pwsz)
  1931. {
  1932. CStrIn str(pwsz);
  1933. return DeleteFileA(str);
  1934. }
  1935. LRESULT DispatchMessageWrap(CONST MSG * lpMsg)
  1936. {
  1937. return DispatchMessageA(lpMsg);
  1938. }
  1939. #ifndef FONT_LINK
  1940. int DrawTextWrap(
  1941. HDC hDC,
  1942. LPCWSTR lpString,
  1943. int nCount,
  1944. LPRECT lpRect,
  1945. UINT uFormat)
  1946. {
  1947. CStrIn str(lpString, nCount);
  1948. return DrawTextA(hDC, str, str.strlen(), lpRect, uFormat);
  1949. }
  1950. // shlwapi also have this.
  1951. int DrawTextExPrivWrap(
  1952. HDC hDC,
  1953. LPWSTR lpString,
  1954. int nCount,
  1955. LPRECT lpRect,
  1956. UINT uFormat,
  1957. LPDRAWTEXTPARAMS lpDTParams)
  1958. {
  1959. CStrIn str(lpString, nCount);
  1960. return DrawTextExA(hDC, str, str.strlen(), lpRect, uFormat, lpDTParams);
  1961. }
  1962. #endif
  1963. struct EFFSTAT
  1964. {
  1965. LPARAM lParam;
  1966. FONTENUMPROC lpEnumFontProc;
  1967. BOOL fFamilySpecified;
  1968. };
  1969. int CALLBACK EnumFontFamiliesCallbackWrap(
  1970. ENUMLOGFONTA * lpelf,
  1971. NEWTEXTMETRIC * lpntm,
  1972. DWORD FontType,
  1973. LPARAM lParam)
  1974. {
  1975. ENUMLOGFONTW elf;
  1976. // Convert strings from ANSI to Unicode
  1977. if (((EFFSTAT *)lParam)->fFamilySpecified && (FontType & TRUETYPE_FONTTYPE) )
  1978. {
  1979. UnicodeFromMbcs(
  1980. elf.elfFullName,
  1981. ARRAYSIZE(elf.elfFullName),
  1982. (LPCSTR) lpelf->elfFullName);
  1983. UnicodeFromMbcs(
  1984. elf.elfStyle,
  1985. ARRAYSIZE(elf.elfStyle),
  1986. (LPCSTR) lpelf->elfStyle);
  1987. }
  1988. else
  1989. {
  1990. elf.elfStyle[0] = L'\0';
  1991. elf.elfFullName[0] = L'\0';
  1992. }
  1993. UnicodeFromMbcs(
  1994. elf.elfLogFont.lfFaceName,
  1995. ARRAYSIZE(elf.elfLogFont.lfFaceName),
  1996. (LPCSTR) lpelf->elfLogFont.lfFaceName);
  1997. // Copy the non-string data
  1998. memcpy(
  1999. &elf.elfLogFont,
  2000. &lpelf->elfLogFont,
  2001. FIELD_OFFSET(LOGFONTA, lfFaceName));
  2002. // Chain to the original callback function
  2003. return (*((EFFSTAT *) lParam)->lpEnumFontProc)(
  2004. (const LOGFONTW *) &elf,
  2005. (const TEXTMETRICW *) lpntm,
  2006. FontType,
  2007. ((EFFSTAT *) lParam)->lParam);
  2008. }
  2009. int EnumFontFamiliesWrap(
  2010. HDC hdc,
  2011. LPCWSTR lpszFamily,
  2012. FONTENUMPROC lpEnumFontProc,
  2013. LPARAM lParam)
  2014. {
  2015. CStrIn str(lpszFamily);
  2016. EFFSTAT effstat;
  2017. effstat.lParam = lParam;
  2018. effstat.lpEnumFontProc = lpEnumFontProc;
  2019. effstat.fFamilySpecified = lpszFamily != NULL;
  2020. return EnumFontFamiliesA(
  2021. hdc,
  2022. str,
  2023. (FONTENUMPROCA) EnumFontFamiliesCallbackWrap,
  2024. (LPARAM) &effstat);
  2025. }
  2026. int EnumFontFamiliesExWrap(
  2027. HDC hdc,
  2028. LPLOGFONTW lplfw,
  2029. FONTENUMPROC lpEnumFontProc,
  2030. LPARAM lParam,
  2031. DWORD dwFlags )
  2032. {
  2033. LOGFONTA lfa;
  2034. CStrIn str(lplfw->lfFaceName);
  2035. EFFSTAT effstat;
  2036. ASSERT( FIELD_OFFSET(LOGFONTW, lfFaceName) == FIELD_OFFSET(LOGFONTA, lfFaceName) );
  2037. memcpy( &lfa, lplfw, sizeof(LOGFONTA) - FIELD_OFFSET(LOGFONTA, lfFaceName) );
  2038. memcpy( lfa.lfFaceName, str, LF_FACESIZE );
  2039. effstat.lParam = lParam;
  2040. effstat.lpEnumFontProc = lpEnumFontProc;
  2041. effstat.fFamilySpecified = lplfw->lfFaceName != NULL;
  2042. return EnumFontFamiliesExA(
  2043. hdc,
  2044. &lfa,
  2045. (FONTENUMPROCA) EnumFontFamiliesCallbackWrap,
  2046. (LPARAM) &effstat,
  2047. dwFlags );
  2048. }
  2049. BOOL EnumResourceNamesWrap(
  2050. HINSTANCE hModule,
  2051. LPCWSTR lpType,
  2052. ENUMRESNAMEPROCW lpEnumFunc,
  2053. LONG lParam)
  2054. {
  2055. ASSERT(HIWORD64(lpType) == 0);
  2056. return EnumResourceNamesA(hModule, (LPCSTR) lpType, (ENUMRESNAMEPROCA)lpEnumFunc, lParam);
  2057. }
  2058. #ifndef FONT_LINK
  2059. //
  2060. // There's an app that patches Win95 GDI and their ExtTextOutW handler
  2061. // is broken. It always dereferences the lpStr parameter, even if
  2062. // cb is zero. Consequently, any time we are about to pass NULL as
  2063. // the lpStr, we have to change our mind and pass a null UNICODE string
  2064. // instead.
  2065. //
  2066. // The name of this app: Lotus SmartSuite ScreenCam 97.
  2067. //
  2068. BOOL ExtTextOutWrap(HDC hdc, int x, int y, UINT fuOptions, CONST RECT *lprc, LPCWSTR lpStr, UINT cch, CONST INT *lpDx)
  2069. {
  2070. // Force a thunk to ANSI if running Win95 + ME
  2071. if (g_fMEEnabled && !g_bRunOnMemphis)
  2072. {
  2073. CStrIn str(lpStr, cch);
  2074. return ExtTextOutA(hdc, x, y, fuOptions, lprc, str, str.strlen(), lpDx);
  2075. }
  2076. else
  2077. {
  2078. if (lpStr == NULL) // workaround
  2079. lpStr = TEXT(""); // for ScreenCam 97
  2080. return ExtTextOutW(hdc, x, y, fuOptions, lprc, lpStr, cch, lpDx);
  2081. }
  2082. }
  2083. #endif
  2084. HANDLE FindFirstFileWrap(
  2085. LPCWSTR lpFileName,
  2086. LPWIN32_FIND_DATAW pwszFd)
  2087. {
  2088. CStrIn str(lpFileName);
  2089. WIN32_FIND_DATAA fd;
  2090. HANDLE ret;
  2091. memcpy(&fd, pwszFd, sizeof(FILETIME)*3+sizeof(DWORD)*5);
  2092. ret = FindFirstFileA(str, &fd);
  2093. memcpy(pwszFd, &fd, sizeof(FILETIME)*3+sizeof(DWORD)*5);
  2094. UnicodeFromMbcs(pwszFd->cFileName, ARRAYSIZE(pwszFd->cFileName), fd.cFileName);
  2095. UnicodeFromMbcs(pwszFd->cAlternateFileName, ARRAYSIZE(pwszFd->cAlternateFileName), fd.cAlternateFileName);
  2096. return ret;
  2097. }
  2098. //
  2099. // Although Win95 implements FindResource[Ex]W, its implementation is buggy
  2100. // if you pass a string parameter, so we must thunk to the ANSI side.
  2101. //
  2102. // The bug is that FindResource[Ex]W will accidentally
  2103. // call LocalFree(lpName) and LocalFree(lpType), so if lpName and lpType
  2104. // point to heap memory, Kernel32 secretly freed your memory and you fault
  2105. // five minutes later.
  2106. //
  2107. HRSRC FindResourceExWrap(HINSTANCE hModule, LPCWSTR lpType, LPCWSTR lpName, WORD wLang)
  2108. {
  2109. CStrIn strType(lpType); // rlefile.cpp passes TEXT("AVI")
  2110. CStrIn strName(lpName);
  2111. return FindResourceExA(hModule, strType, strName, wLang);
  2112. }
  2113. HWND FindWindowWrap(LPCWSTR lpClassName, LPCWSTR lpWindowName)
  2114. {
  2115. CStrIn strClass(lpClassName);
  2116. CStrIn strWindow(lpWindowName);
  2117. return FindWindowA(strClass, strWindow);
  2118. }
  2119. DWORD FormatMessageWrap(
  2120. DWORD dwFlags,
  2121. LPCVOID lpSource,
  2122. DWORD dwMessageId,
  2123. DWORD dwLanguageId,
  2124. LPWSTR lpBuffer,
  2125. DWORD nSize,
  2126. va_list * Arguments)
  2127. {
  2128. //This assert is only valid on Windows 95.
  2129. ASSERT(!(dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER));
  2130. CStrOut str(lpBuffer, nSize);
  2131. FormatMessageA(
  2132. dwFlags,
  2133. lpSource,
  2134. dwMessageId,
  2135. dwLanguageId,
  2136. str,
  2137. str.BufSize(),
  2138. Arguments);
  2139. return str.ConvertExcludingNul();
  2140. }
  2141. BOOL GetClassInfoWrap(HINSTANCE hModule, LPCWSTR lpClassName, LPWNDCLASSW lpWndClassW)
  2142. {
  2143. BOOL ret;
  2144. CStrIn strClassName(lpClassName);
  2145. ASSERT(sizeof(WNDCLASSA) == sizeof(WNDCLASSW));
  2146. ret = GetClassInfoA(hModule, strClassName, (LPWNDCLASSA) lpWndClassW);
  2147. lpWndClassW->lpszMenuName = NULL;
  2148. lpWndClassW->lpszClassName = NULL;
  2149. return ret;
  2150. }
  2151. DWORD GetClassLongWrap(HWND hWnd, int nIndex)
  2152. {
  2153. return GetClassLongA(hWnd, nIndex);
  2154. }
  2155. int GetClassNameWrap(HWND hWnd, LPWSTR lpClassName, int nMaxCount)
  2156. {
  2157. CStrOut strClassName(lpClassName, nMaxCount);
  2158. GetClassNameA(hWnd, strClassName, strClassName.BufSize());
  2159. return strClassName.ConvertIncludingNul();
  2160. }
  2161. int GetClipboardFormatNameWrap(UINT format, LPWSTR lpFormatName, int cchFormatName)
  2162. {
  2163. CStrOut strFormatName(lpFormatName, cchFormatName);
  2164. GetClipboardFormatNameA(format, strFormatName, strFormatName.BufSize());
  2165. return strFormatName.ConvertIncludingNul();
  2166. }
  2167. DWORD GetCurrentDirectoryWrap(DWORD nBufferLength, LPWSTR lpBuffer)
  2168. {
  2169. CStrOut str(lpBuffer, nBufferLength);
  2170. GetCurrentDirectoryA(str.BufSize(), str);
  2171. return str.ConvertExcludingNul();
  2172. }
  2173. int GetDateFormatWrap(
  2174. LCID Locale,
  2175. DWORD dwFlags,
  2176. CONST SYSTEMTIME *lpDate,
  2177. LPCWSTR lpFormat,
  2178. LPWSTR lpDateStr,
  2179. int cchDate)
  2180. {
  2181. CStrIn strFormat(lpFormat);
  2182. CStrOut str(lpDateStr, cchDate);
  2183. ASSERT(cchDate != 0 || lpDateStr == NULL);
  2184. int iRc = GetDateFormatA(Locale, dwFlags, lpDate, strFormat, str, str.BufSize());
  2185. // If app was merely querying, then return size and stop
  2186. if (!str)
  2187. return iRc;
  2188. return str.ConvertIncludingNul();
  2189. }
  2190. UINT GetDlgItemTextWrap(
  2191. HWND hWndDlg,
  2192. int idControl,
  2193. LPWSTR lpsz,
  2194. int cchMax)
  2195. {
  2196. CStrOut str(lpsz, cchMax);
  2197. GetDlgItemTextA(hWndDlg, idControl, str, str.BufSize());
  2198. return str.ConvertExcludingNul();
  2199. }
  2200. DWORD GetFileAttributesWrap(LPCWSTR lpFileName)
  2201. {
  2202. CStrIn str(lpFileName);
  2203. return GetFileAttributesA(str);
  2204. }
  2205. int GetKeyNameTextWrap(LONG lParam, LPWSTR lpsz, int nSize)
  2206. {
  2207. CStrOut str(lpsz, nSize);
  2208. GetKeyNameTextA(lParam, str, str.BufSize());
  2209. return str.ConvertExcludingNul();
  2210. }
  2211. int GetLocaleInfoWrap(LCID Locale, LCTYPE LCType, LPWSTR lpsz, int cchData)
  2212. {
  2213. CStrOut str(lpsz, cchData);
  2214. GetLocaleInfoA(Locale, LCType, str, str.BufSize());
  2215. return str.ConvertIncludingNul();
  2216. }
  2217. BOOL GetMenuItemInfoWrap(
  2218. HMENU hMenu,
  2219. UINT uItem,
  2220. BOOL fByPosition,
  2221. LPMENUITEMINFOW lpmiiW)
  2222. {
  2223. BOOL fRet;
  2224. ASSERT( sizeof(MENUITEMINFOW) == sizeof(MENUITEMINFOA) &&
  2225. FIELD_OFFSET(MENUITEMINFOW, dwTypeData) ==
  2226. FIELD_OFFSET(MENUITEMINFOA, dwTypeData) );
  2227. if ( (MIIM_TYPE & lpmiiW->fMask) &&
  2228. 0 == (lpmiiW->fType & (MFT_BITMAP | MFT_SEPARATOR)))
  2229. {
  2230. MENUITEMINFOA miiA;
  2231. CStrOut str(lpmiiW->dwTypeData, lpmiiW->cch);
  2232. memcpy( &miiA, lpmiiW, sizeof(MENUITEMINFOA) );
  2233. miiA.dwTypeData = str;
  2234. miiA.cch = str.BufSize();
  2235. fRet = GetMenuItemInfoA( hMenu, uItem, fByPosition, &miiA );
  2236. memcpy(lpmiiW, &miiA, FIELD_OFFSET(MENUITEMINFOW, dwTypeData));
  2237. }
  2238. else
  2239. {
  2240. fRet = GetMenuItemInfoA( hMenu, uItem, fByPosition,
  2241. (LPMENUITEMINFOA)lpmiiW );
  2242. }
  2243. return fRet;
  2244. }
  2245. int GetMenuStringWrap(
  2246. HMENU hMenu,
  2247. UINT uIDItem,
  2248. LPWSTR lpString,
  2249. int nMaxCount,
  2250. UINT uFlag)
  2251. {
  2252. CStrOut str(lpString, nMaxCount);
  2253. GetMenuStringA(hMenu, uIDItem, str, str.BufSize(), uFlag);
  2254. return str.ConvertExcludingNul();
  2255. }
  2256. BOOL GetMessageWrap(
  2257. LPMSG lpMsg,
  2258. HWND hWnd,
  2259. UINT wMsgFilterMin,
  2260. UINT wMsgFilterMax)
  2261. {
  2262. return GetMessageA(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
  2263. }
  2264. DWORD GetModuleFileNameWrap(HINSTANCE hModule, LPWSTR pwszFilename, DWORD nSize)
  2265. {
  2266. CStrOut str(pwszFilename, nSize);
  2267. GetModuleFileNameA(hModule, str, str.BufSize());
  2268. return str.ConvertIncludingNul();
  2269. }
  2270. int GetNumberFormatWrap(
  2271. LCID Locale,
  2272. DWORD dwFlags,
  2273. LPCWSTR lpValue,
  2274. CONST NUMBERFMTW *lpFormat,
  2275. LPWSTR lpNumberStr,
  2276. int cchNumber)
  2277. {
  2278. CStrIn strValue(lpValue);
  2279. CStrOut str(lpNumberStr, cchNumber);
  2280. ASSERT(cchNumber != 0);
  2281. NUMBERFMTA nfA;
  2282. CopyMemory(&nfA, lpFormat, sizeof(nfA));
  2283. CStrIn strDec(lpFormat->lpDecimalSep);
  2284. nfA.lpDecimalSep = strDec;
  2285. CStrIn strThou(lpFormat->lpThousandSep);
  2286. nfA.lpThousandSep = strThou;
  2287. GetNumberFormatA(Locale, dwFlags, strValue, &nfA, str, str.BufSize());
  2288. return str.ConvertIncludingNul();
  2289. }
  2290. UINT GetSystemDirectoryWrap(LPWSTR lpBuffer, UINT uSize)
  2291. {
  2292. CStrOut str(lpBuffer, uSize);
  2293. GetSystemDirectoryA(str, str.BufSize());
  2294. return str.ConvertExcludingNul();
  2295. }
  2296. DWORD SearchPathWrap(
  2297. LPCWSTR lpPathName,
  2298. LPCWSTR lpFileName,
  2299. LPCWSTR lpExtension,
  2300. DWORD cchReturnBuffer,
  2301. LPWSTR lpReturnBuffer,
  2302. LPWSTR * plpfilePart)
  2303. {
  2304. CStrIn strPath(lpPathName);
  2305. CStrIn strFile(lpFileName);
  2306. CStrIn strExtension(lpExtension);
  2307. CStrOut strReturnBuffer(lpReturnBuffer, cchReturnBuffer);
  2308. DWORD dwLen = SearchPathA(
  2309. strPath,
  2310. strFile,
  2311. strExtension,
  2312. strReturnBuffer.BufSize(),
  2313. strReturnBuffer,
  2314. (LPSTR *)plpfilePart);
  2315. //
  2316. // Getting the correct value for plpfilePart requires
  2317. // a strrchr on the converted string. If this value
  2318. // is needed, just add the code to do it here.
  2319. //
  2320. *plpfilePart = NULL;
  2321. if (cchReturnBuffer == 0)
  2322. dwLen = 2*dwLen;
  2323. else
  2324. dwLen = strReturnBuffer.ConvertExcludingNul();
  2325. return dwLen;
  2326. }
  2327. HMODULE GetModuleHandleWrap(LPCWSTR lpModuleName)
  2328. {
  2329. CStrIn str(lpModuleName);
  2330. return GetModuleHandleA(str);
  2331. }
  2332. int GetObjectWrap(HGDIOBJ hgdiObj, int cbBuffer, LPVOID lpvObj)
  2333. {
  2334. int nRet;
  2335. if(cbBuffer != sizeof(LOGFONTW))
  2336. {
  2337. nRet = GetObjectA(hgdiObj, cbBuffer, lpvObj);
  2338. }
  2339. else
  2340. {
  2341. LOGFONTA lfa;
  2342. nRet = GetObjectA(hgdiObj, sizeof(lfa), &lfa);
  2343. if (nRet > 0)
  2344. {
  2345. memcpy(lpvObj, &lfa, FIELD_OFFSET(LOGFONTW, lfFaceName));
  2346. UnicodeFromMbcs(((LOGFONTW*)lpvObj)->lfFaceName, ARRAYSIZE(((LOGFONTW*)lpvObj)->lfFaceName),
  2347. lfa.lfFaceName, -1);
  2348. nRet = sizeof(LOGFONTW);
  2349. }
  2350. }
  2351. return nRet;
  2352. }
  2353. //--------------------------------------------------------------
  2354. // GetFullPathNameWrap
  2355. //--------------------------------------------------------------
  2356. DWORD GetFullPathNameWrap( LPCWSTR lpFileName,
  2357. DWORD nBufferLength,
  2358. LPWSTR lpBuffer,
  2359. LPWSTR *lpFilePart)
  2360. {
  2361. CStrIn strIn(lpFileName);
  2362. CStrOut strOut(lpBuffer,nBufferLength);
  2363. LPSTR pFile;
  2364. DWORD dwRet;
  2365. dwRet = GetFullPathNameA(strIn, nBufferLength, strOut, &pFile);
  2366. strOut.ConvertIncludingNul();
  2367. *lpFilePart = lpBuffer + (pFile - strOut);
  2368. return dwRet;
  2369. }
  2370. BOOL GetStringTypeExWrap(LCID lcid, DWORD dwInfoType, LPCTSTR lpSrcStr, int cchSrc, LPWORD lpCharType)
  2371. {
  2372. CStrIn str(lpSrcStr, cchSrc);
  2373. return GetStringTypeExA(lcid, dwInfoType, str, str.strlen(), lpCharType);
  2374. }
  2375. UINT GetPrivateProfileIntWrap(
  2376. LPCWSTR lpAppName,
  2377. LPCWSTR lpKeyName,
  2378. INT nDefault,
  2379. LPCWSTR lpFileName)
  2380. {
  2381. CStrIn strApp(lpAppName);
  2382. CStrIn strKey(lpKeyName);
  2383. CStrIn strFile(lpFileName);
  2384. return GetPrivateProfileIntA(strApp, strKey, nDefault, strFile);
  2385. }
  2386. UINT GetProfileIntWrap(
  2387. LPCWSTR lpAppName,
  2388. LPCWSTR lpKeyName,
  2389. INT nDefault)
  2390. {
  2391. CStrIn strApp(lpAppName);
  2392. CStrIn strKey(lpKeyName);
  2393. return GetProfileIntA(strApp, strKey, nDefault);
  2394. }
  2395. DWORD GetProfileStringWrap(
  2396. LPCWSTR lpAppName,
  2397. LPCWSTR lpKeyName,
  2398. LPCWSTR lpDefault,
  2399. LPWSTR lpBuffer,
  2400. DWORD dwBuffersize)
  2401. {
  2402. CStrIn strApp(lpAppName);
  2403. CStrIn strKey(lpKeyName);
  2404. CStrIn strDefault(lpDefault);
  2405. CStrOut strBuffer(lpBuffer, dwBuffersize);
  2406. GetProfileStringA(strApp, strKey, strDefault, strBuffer, dwBuffersize);
  2407. return strBuffer.ConvertIncludingNul();
  2408. }
  2409. HANDLE GetPropWrap(HWND hWnd, LPCWSTR lpString)
  2410. {
  2411. CStrIn str(lpString);
  2412. return GetPropA(hWnd, str);
  2413. }
  2414. UINT GetTempFileNameWrap(
  2415. LPCWSTR lpPathName,
  2416. LPCWSTR lpPrefixString,
  2417. UINT uUnique,
  2418. LPWSTR lpTempFileName)
  2419. {
  2420. CStrIn strPath(lpPathName);
  2421. CStrIn strPrefix(lpPrefixString);
  2422. CStrOut strFileName(lpTempFileName, MAX_PATH);
  2423. return GetTempFileNameA(strPath, strPrefix, uUnique, strFileName);
  2424. }
  2425. DWORD GetTempPathWrap(DWORD nBufferLength, LPWSTR lpBuffer)
  2426. {
  2427. CStrOut str(lpBuffer, nBufferLength);
  2428. GetTempPathA(str.BufSize(), str);
  2429. return str.ConvertExcludingNul();
  2430. }
  2431. #ifndef FONT_LINK
  2432. BOOL GetTextExtentPointWrap(
  2433. HDC hdc,
  2434. LPCWSTR pwsz,
  2435. int cb,
  2436. LPSIZE pSize)
  2437. {
  2438. CStrIn str(pwsz,cb);
  2439. return GetTextExtentPointA(hdc, str, str.strlen(), pSize);
  2440. }
  2441. BOOL GetTextExtentPoint32Wrap(
  2442. HDC hdc,
  2443. LPCWSTR pwsz,
  2444. int cb,
  2445. LPSIZE pSize)
  2446. {
  2447. CStrIn str(pwsz,cb);
  2448. return GetTextExtentPoint32A(hdc, str, str.strlen(), pSize);
  2449. }
  2450. #endif
  2451. int GetTextFaceWrap(
  2452. HDC hdc,
  2453. int cch,
  2454. LPWSTR lpFaceName)
  2455. {
  2456. CStrOut str(lpFaceName, cch);
  2457. GetTextFaceA(hdc, str.BufSize(), str);
  2458. return str.ConvertIncludingNul();
  2459. }
  2460. BOOL GetTextMetricsWrap(HDC hdc, LPTEXTMETRICW lptm)
  2461. {
  2462. BOOL ret;
  2463. TEXTMETRICA tm;
  2464. ret = GetTextMetricsA(hdc, &tm);
  2465. if (ret)
  2466. {
  2467. lptm->tmHeight = tm.tmHeight;
  2468. lptm->tmAscent = tm.tmAscent;
  2469. lptm->tmDescent = tm.tmDescent;
  2470. lptm->tmInternalLeading = tm.tmInternalLeading;
  2471. lptm->tmExternalLeading = tm.tmExternalLeading;
  2472. lptm->tmAveCharWidth = tm.tmAveCharWidth;
  2473. lptm->tmMaxCharWidth = tm.tmMaxCharWidth;
  2474. lptm->tmWeight = tm.tmWeight;
  2475. lptm->tmOverhang = tm.tmOverhang;
  2476. lptm->tmDigitizedAspectX = tm.tmDigitizedAspectX;
  2477. lptm->tmDigitizedAspectY = tm.tmDigitizedAspectY;
  2478. lptm->tmItalic = tm.tmItalic;
  2479. lptm->tmUnderlined = tm.tmUnderlined;
  2480. lptm->tmStruckOut = tm.tmStruckOut;
  2481. lptm->tmPitchAndFamily = tm.tmPitchAndFamily;
  2482. lptm->tmCharSet = tm.tmCharSet;
  2483. UnicodeFromMbcs(&lptm->tmFirstChar, 1, (LPSTR) &tm.tmFirstChar, 1);
  2484. UnicodeFromMbcs(&lptm->tmLastChar, 1, (LPSTR) &tm.tmLastChar, 1);
  2485. UnicodeFromMbcs(&lptm->tmDefaultChar, 1, (LPSTR) &tm.tmDefaultChar, 1);
  2486. UnicodeFromMbcs(&lptm->tmBreakChar, 1, (LPSTR) &tm.tmBreakChar, 1);
  2487. }
  2488. return ret;
  2489. }
  2490. int GetTimeFormatWrap(
  2491. LCID Locale,
  2492. DWORD dwFlags,
  2493. CONST SYSTEMTIME *lpTime,
  2494. LPCWSTR lpFormat,
  2495. LPWSTR lpTimeStr,
  2496. int cchTime)
  2497. {
  2498. CStrIn strFormat(lpFormat);
  2499. CStrOut str(lpTimeStr, cchTime);
  2500. ASSERT(cchTime != 0);
  2501. GetTimeFormatA(Locale, dwFlags, lpTime, strFormat, str, str.BufSize());
  2502. return str.ConvertIncludingNul();
  2503. }
  2504. LONG GetWindowLongWrap(HWND hWnd, int nIndex)
  2505. {
  2506. return GetWindowLongA(hWnd, nIndex);
  2507. }
  2508. int GetWindowTextWrap(HWND hWnd, LPWSTR lpString, int nMaxCount)
  2509. {
  2510. CStrOut str(lpString, nMaxCount);
  2511. GetWindowTextA(hWnd, str, str.BufSize());
  2512. return str.ConvertExcludingNul();
  2513. }
  2514. int GetWindowTextLengthWrap(HWND hWnd)
  2515. {
  2516. WCHAR wstr[MAX_PATH];
  2517. return GetWindowTextWrap(hWnd, wstr, ARRAYSIZE(wstr));
  2518. }
  2519. UINT GetWindowsDirectoryWrap(LPWSTR lpWinPath, UINT cch)
  2520. {
  2521. CStrOut str(lpWinPath, cch);
  2522. GetWindowsDirectoryA(str, str.BufSize());
  2523. return str.ConvertExcludingNul();
  2524. }
  2525. ATOM GlobalAddAtomWrap(LPCWSTR lpString)
  2526. {
  2527. CStrIn str(lpString);
  2528. return GlobalAddAtomA(str);
  2529. }
  2530. BOOL GrayStringWrap(
  2531. HDC hDC,
  2532. HBRUSH hBrush,
  2533. GRAYSTRINGPROC lpOutputFunc,
  2534. LPARAM lpData,
  2535. int nCount,
  2536. int x,
  2537. int y,
  2538. int nWidth,
  2539. int nHeight)
  2540. {
  2541. CStrIn str((LPWSTR)lpData);
  2542. return GrayStringA(hDC, hBrush, lpOutputFunc, (LPARAM)(LPCSTR)str, str.strlen(), x, y, nWidth, nHeight);
  2543. }
  2544. LONG ImmGetCompositionStringWrap(HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
  2545. {
  2546. int cb = 0;
  2547. if ((dwIndex & GCS_COMPSTR) || (dwIndex & GCS_RESULTSTR))
  2548. {
  2549. if (dwBufLen)
  2550. {
  2551. CStrOut str((LPWSTR)lpBuf, dwBufLen/sizeof(WCHAR) + 1);
  2552. cb = ImmGetCompositionStringA(hIMC, dwIndex, str, str.BufSize());
  2553. *(WCHAR*)((LPSTR)str + cb) = L'\0';
  2554. return str.ConvertExcludingNul() * sizeof(WCHAR);
  2555. }
  2556. else
  2557. {
  2558. LPWSTR lpStr;
  2559. cb = ImmGetCompositionStringA(hIMC, dwIndex, lpBuf, dwBufLen);
  2560. lpStr = (LPWSTR)LocalAlloc(LPTR, (cb + 1) * sizeof(WCHAR));
  2561. if (lpStr)
  2562. {
  2563. CStrOut str(lpStr, cb + 1);
  2564. cb = ImmGetCompositionStringA(hIMC, dwIndex, str, str.BufSize());
  2565. *(WCHAR*)((LPSTR)str + cb) = L'\0';
  2566. cb = str.ConvertExcludingNul() * sizeof(WCHAR);
  2567. LocalFree(lpStr);
  2568. return cb;
  2569. }
  2570. }
  2571. }
  2572. else if (dwIndex & GCS_COMPATTR)
  2573. {
  2574. if (dwBufLen)
  2575. {
  2576. LPSTR lpStr, lpAttr;
  2577. UINT i = 0;
  2578. lpStr = (LPSTR)LocalAlloc(LPTR, dwBufLen);
  2579. if (lpStr)
  2580. {
  2581. lpAttr = (LPSTR)LocalAlloc(LPTR, dwBufLen);
  2582. if (lpAttr)
  2583. {
  2584. LPSTR lpNext = lpStr;
  2585. cb = ImmGetCompositionStringA(hIMC, GCS_COMPSTR, lpStr, dwBufLen);
  2586. ImmGetCompositionStringA(hIMC, GCS_COMPATTR, lpAttr, dwBufLen);
  2587. for (i = 0; (lpNext - lpStr < cb) && (i < dwBufLen); i++)
  2588. {
  2589. ((LPSTR)lpBuf)[i] = lpAttr[lpNext - lpStr];
  2590. lpNext = CharNextA(lpNext);
  2591. }
  2592. LocalFree(lpAttr);
  2593. }
  2594. LocalFree(lpStr);
  2595. }
  2596. return i;
  2597. }
  2598. }
  2599. return ImmGetCompositionStringA(hIMC, dwIndex, lpBuf, dwBufLen);
  2600. }
  2601. LONG ImmSetCompositionStringWrap(HIMC hIMC, DWORD dwIndex, LPVOID lpComp, DWORD dwCompLen, LPVOID lpRead, DWORD dwReadLen)
  2602. {
  2603. if (dwIndex & SCS_SETSTR)
  2604. {
  2605. CStrIn str((LPWSTR)lpComp);
  2606. ASSERT(!lpRead);
  2607. return ImmSetCompositionStringA(hIMC, dwIndex, str, str.strlen(), lpRead, dwReadLen);
  2608. }
  2609. return ImmSetCompositionStringA(hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
  2610. }
  2611. BOOL InsertMenuWrap(
  2612. HMENU hMenu,
  2613. UINT uPosition,
  2614. UINT uFlags,
  2615. UINT uIDNewItem,
  2616. LPCWSTR lpNewItem)
  2617. {
  2618. CStrIn str(lpNewItem);
  2619. return InsertMenuA(hMenu, uPosition, uFlags, uIDNewItem, str);
  2620. }
  2621. BOOL IsDialogMessageWrap(HWND hWndDlg, LPMSG lpMsg)
  2622. {
  2623. return IsDialogMessageA(hWndDlg, lpMsg);
  2624. }
  2625. HACCEL LoadAcceleratorsWrap(HINSTANCE hInstance, LPCWSTR lpTableName)
  2626. {
  2627. CStrIn str(lpTableName);
  2628. return LoadAcceleratorsA(hInstance, (LPCSTR) str);
  2629. }
  2630. HBITMAP LoadBitmapWrap(HINSTANCE hInstance, LPCWSTR lpBitmapName)
  2631. {
  2632. CStrIn str(lpBitmapName);
  2633. return LoadBitmapA(hInstance, str);
  2634. }
  2635. HCURSOR LoadCursorWrap(HINSTANCE hInstance, LPCWSTR lpCursorName)
  2636. {
  2637. CStrIn str(lpCursorName);
  2638. return LoadCursorA(hInstance, (LPCSTR) str);
  2639. }
  2640. HICON LoadIconWrap(HINSTANCE hInstance, LPCWSTR lpIconName)
  2641. {
  2642. CStrIn str(lpIconName);
  2643. return LoadIconA(hInstance, str);
  2644. }
  2645. HANDLE LoadImageWrap(
  2646. HINSTANCE hInstance,
  2647. LPCWSTR lpName,
  2648. UINT uType,
  2649. int cxDesired,
  2650. int cyDesired,
  2651. UINT fuLoad)
  2652. {
  2653. CStrIn str(lpName);
  2654. return LoadImageA(
  2655. hInstance,
  2656. str,
  2657. uType,
  2658. cxDesired,
  2659. cyDesired,
  2660. fuLoad);
  2661. }
  2662. HINSTANCE LoadLibraryWrap(LPCWSTR lpLibFileName)
  2663. {
  2664. CStrIn str(lpLibFileName);
  2665. return LoadLibraryA(str);
  2666. }
  2667. HINSTANCE LoadLibraryExWrap(
  2668. LPCWSTR lpLibFileName,
  2669. HANDLE hFile,
  2670. DWORD dwFlags)
  2671. {
  2672. CStrIn str(lpLibFileName);
  2673. return LoadLibraryExA(str, hFile, dwFlags);
  2674. }
  2675. HMENU LoadMenuWrap(HINSTANCE hInstance, LPCWSTR lpMenuName)
  2676. {
  2677. ASSERT(HIWORD64(lpMenuName) == 0);
  2678. return LoadMenuA(hInstance, (LPCSTR) lpMenuName);
  2679. }
  2680. int LoadStringWrap(HINSTANCE hInstance, UINT uID, LPWSTR lpBuffer, int nBufferMax)
  2681. {
  2682. //
  2683. // Do it manually. The old code used to call LoadStringA and then
  2684. // convert it up to unicode, which is bad since resources are
  2685. // physically already Unicode! Just copy it out directly.
  2686. //
  2687. if (nBufferMax <= 0) return 0; // sanity check
  2688. PWCHAR pwch;
  2689. /*
  2690. * String tables are broken up into "bundles" of 16 strings each.
  2691. */
  2692. HRSRC hrsrc;
  2693. int cwch = 0;
  2694. hrsrc = FindResourceA(hInstance, (LPSTR)(LONG_PTR)(1 + uID / 16), (LPSTR)RT_STRING);
  2695. if (hrsrc) {
  2696. pwch = (PWCHAR)LoadResource(hInstance, hrsrc);
  2697. if (pwch) {
  2698. /*
  2699. * Now skip over the strings in the resource until we
  2700. * hit the one we want. Each entry is a counted string,
  2701. * just like Pascal.
  2702. */
  2703. for (uID %= 16; uID; uID--) {
  2704. pwch += *pwch + 1;
  2705. }
  2706. cwch = min(*pwch, nBufferMax - 1);
  2707. memcpy(lpBuffer, pwch+1, cwch * sizeof(WCHAR)); /* Copy the goo */
  2708. }
  2709. }
  2710. lpBuffer[cwch] = L'\0'; /* Terminate the string */
  2711. return cwch;
  2712. }
  2713. UINT MapVirtualKeyWrap(UINT uCode, UINT uMapType)
  2714. {
  2715. return MapVirtualKeyA(uCode, uMapType);
  2716. }
  2717. //----------------------------------------------------------------------
  2718. //
  2719. // function: TransformCharNoOp1( WCHAR **ppch )
  2720. //
  2721. // purpose: Stand-in for TransformCharWidth. Used by the function
  2722. // CompareStringString.
  2723. //
  2724. // returns: Character at *ppch. The value *ppch is incremented.
  2725. //
  2726. //----------------------------------------------------------------------
  2727. static WCHAR TransformCharNoOp1( LPCWSTR *ppch, int )
  2728. {
  2729. WCHAR ch = **ppch;
  2730. (*ppch)++;
  2731. return ch;
  2732. }
  2733. //----------------------------------------------------------------------
  2734. //
  2735. // function: TransformCharWidth( WCHAR **ppch, cchRemaining )
  2736. //
  2737. // purpose: Converts halfwidth characters to fullwidth characters.
  2738. // Also combines voiced (dakuon) and semi-voiced (handakuon)
  2739. // characters. *pch is advanced by one, unless there is a
  2740. // (semi)voiced character, in which case it is advanced by
  2741. // two characters.
  2742. //
  2743. // Note that unlike the full widechar version, we do not
  2744. // combine other characters, notably the combining Hiragana
  2745. // characters (U+3099 and U+309A.) This is to keep the
  2746. // tables from getting unnecessarily large.
  2747. //
  2748. // cchRemaining is passed so as to not include the voiced
  2749. // marks if it's passed the end of the specified buffer.
  2750. //
  2751. // returns: Full width character. *pch is incremented.
  2752. //
  2753. //----------------------------------------------------------------------
  2754. static WCHAR TransformCharWidth( LPCWSTR *ppch, int cchRemaining )
  2755. {
  2756. WCHAR ch = **ppch;
  2757. (*ppch)++;
  2758. if (ch == 0x0020)
  2759. {
  2760. ch = 0x3000;
  2761. }
  2762. else if (ch == 0x005c)
  2763. {
  2764. // REVERSE SOLIDUS (aka BACKSLASH) maps to itself
  2765. }
  2766. else if (InRange(ch, 0x0021, 0x07e))
  2767. {
  2768. ch += 65248;
  2769. }
  2770. else if (InRange(ch, 0x00a2, 0x00af))
  2771. {
  2772. static const WCHAR achFull[] =
  2773. {
  2774. 0xffe0, 0xffe1, 0x00a4, 0xffe5, 0xffe4, 0x00a7, 0x00a8, // 0xa2-0xa8
  2775. 0x00a9, 0x00aa, 0x00ab, 0xffe2, 0x00ad, 0x00ae, 0xffe3 // 0xa9-0xaf
  2776. };
  2777. ch = achFull[ch - 0x00a2];
  2778. }
  2779. else if (ch == 0x20a9) // WON SIGN
  2780. {
  2781. ch = 0xffe6;
  2782. }
  2783. else if (InRange(ch, 0xff61, 0xffdc))
  2784. {
  2785. WCHAR chNext = (cchRemaining > 1) ? **ppch : 0;
  2786. if (chNext == 0xff9e && InRange(ch, 0xff73, 0xff8e))
  2787. {
  2788. if (cchRemaining != 1)
  2789. {
  2790. static const WCHAR achFull[] =
  2791. {
  2792. /* 0xff73-0xff79 */ 0xb0f4, 0x30a8, 0x30aa, 0xb0ac, 0xb0ae, 0xb0b0, 0xb0b2,
  2793. /* 0xff7a-0xff80 */ 0xb0b4, 0xb0b6, 0xb0b8, 0xb0ba, 0xb0bc, 0xb0be, 0xb0c0,
  2794. /* 0xff81-0xff87 */ 0xb0c2, 0xb0c5, 0xb0c7, 0xb0c9, 0x30ca, 0x30cb, 0x30cc,
  2795. /* 0xff88-0xff8e */ 0x30cd, 0x30ce, 0xb0d0, 0xb0d3, 0xb0d6, 0xb0d9, 0xb0dc
  2796. };
  2797. // HALFWIDTH KATAKANA VOICED SOUND MARK
  2798. WCHAR chTemp = achFull[ch - 0xff73];
  2799. // Some in the range absorb the sound mark.
  2800. // These are indicated by the set high-bit.
  2801. ch = chTemp & 0x7fff;
  2802. if (chTemp & 0x8000)
  2803. {
  2804. (*ppch)++;
  2805. }
  2806. }
  2807. }
  2808. else if (chNext == 0xff9f && InRange(ch, 0xff8a, 0xff8e))
  2809. {
  2810. // HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK
  2811. ch = 0x30d1 + (ch - 0xff8a) * 3;
  2812. (*ppch)++;
  2813. }
  2814. else
  2815. {
  2816. static const WCHAR achMapFullFFxx[] =
  2817. {
  2818. 0x3002, 0x300c, 0x300d, 0x3001, 0x30fb, 0x30f2, 0x30a1, // 0xff61-0xff67
  2819. 0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30e3, 0x30e5, 0x30e7, // 0xff68-0xff6e
  2820. 0x30c3, 0x30fc, 0x30a2, 0x30a4, 0x30a6, 0x30a8, 0x30aa, // 0xff6f-0xff75
  2821. 0x30ab, 0x30ad, 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7, // 0xff76-0xff7c
  2822. 0x30b9, 0x30bb, 0x30bd, 0x30bf, 0x30c1, 0x30c4, 0x30c6, // 0xff7d-0xff83
  2823. 0x30c8, 0x30ca, 0x30cb, 0x30cc, 0x30cd, 0x30ce, 0x30cf, // 0xff84-0xff8a
  2824. 0x30d2, 0x30d5, 0x30d8, 0x30db, 0x30de, 0x30df, 0x30e0, // 0xff8b-0xff91
  2825. 0x30e1, 0x30e2, 0x30e4, 0x30e6, 0x30e8, 0x30e9, 0x30ea, // 0xff92-0xff98
  2826. 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f3, 0x309b, 0x309c, // 0xff99-0xff9f
  2827. 0x3164, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, // 0xffa0-0xffa6
  2828. 0x3137, 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, // 0xffa7-0xffad
  2829. 0x313e, 0x313f, 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, // 0xffae-0xffb4
  2830. 0x3145, 0x3146, 0x3147, 0x3148, 0x3149, 0x314a, 0x314b, // 0xffb5-0xffbb
  2831. 0x314c, 0x314d, 0x314e, 0xffbf, 0xffc0, 0xffc1, 0x314f, // 0xffbc-0xffc2
  2832. 0x3150, 0x3151, 0x3152, 0x3153, 0x3154, 0xffc8, 0xffc9, // 0xffc3-0xffc9
  2833. 0x3155, 0x3156, 0x3157, 0x3158, 0x3159, 0x315a, 0xffd0, // 0xffca-0xffd0
  2834. 0xffd1, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, 0x3160, // 0xffd1-0xffd7
  2835. 0xffd8, 0xffd9, 0x3161, 0x3162, 0x3163 // 0xffd8-0xffac
  2836. };
  2837. ch = achMapFullFFxx[ch - 0xff61];
  2838. }
  2839. }
  2840. return ch;
  2841. }
  2842. //----------------------------------------------------------------------
  2843. //
  2844. // function: TransformaCharNoOp2( WCHAR ch )
  2845. //
  2846. // purpose: Stand-in for CharLowerBuffWrap. Used by the function
  2847. // CompareStringString.
  2848. //
  2849. // returns: Original character
  2850. //
  2851. //----------------------------------------------------------------------
  2852. static WCHAR TransformCharNoOp2( WCHAR ch )
  2853. {
  2854. return ch;
  2855. }
  2856. //----------------------------------------------------------------------
  2857. //
  2858. // function: TransformaCharKana( WCHAR ch )
  2859. //
  2860. // purpose: Converts Hiragana characters to Katakana characters
  2861. //
  2862. // returns: Original character if not Hiragana,
  2863. // Katanaka character if Hiragana
  2864. //
  2865. //----------------------------------------------------------------------
  2866. static WCHAR TransformCharKana( WCHAR ch )
  2867. {
  2868. if (((ch & 0xff00) == 0x3000) &&
  2869. (InRange(ch, 0x3041, 0x3094) || InRange(ch, 0x309d, 0x309e)))
  2870. {
  2871. ch += 0x060;
  2872. }
  2873. return ch;
  2874. }
  2875. //----------------------------------------------------------------------
  2876. //
  2877. // function: TransformCharNoOp3( LPWSTR pch, DWORD cch )
  2878. //
  2879. // purpose: Stand-in for CharLowerBuffWrap. Used by the function
  2880. // CompareStringString.
  2881. //
  2882. // returns: Character count (cch).
  2883. //
  2884. //----------------------------------------------------------------------
  2885. static DWORD TransformCharNoOp3( LPWSTR, DWORD cch )
  2886. {
  2887. return cch;
  2888. }
  2889. //----------------------------------------------------------------------
  2890. //
  2891. // function: TransformaCharFinal( WCHAR ch )
  2892. //
  2893. // purpose: Converts "final" forms to regular forms
  2894. //
  2895. // returns: Original character if not Hiragana,
  2896. // Katanaka character if Hiragana
  2897. //
  2898. //----------------------------------------------------------------------
  2899. // BUGBUG (cthrash) We do not fold Presentation Forms (Alphabetic or Arabic)
  2900. static WCHAR TransformCharFinal( WCHAR ch )
  2901. {
  2902. WCHAR chRet = ch;
  2903. if (ch >= 0x3c2) // short-circuit ASCII +
  2904. {
  2905. switch (ch)
  2906. {
  2907. case 0x03c2: // GREEK SMALL LETTER FINAL SIGMA
  2908. case 0x05da: // HEBREW LETTER FINAL KAF
  2909. case 0x05dd: // HEBREW LETTER FINAL MEM
  2910. case 0x05df: // HEBREW LETTER FINAL NUN
  2911. case 0x05e3: // HEBREW LETTER FINAL PE
  2912. case 0x05e5: // HEBREW LETTER FINAL TSADI
  2913. case 0xfb26: // HEBREW LETTER WIDE FINAL MEM
  2914. case 0xfb3a: // HEBREW LETTER FINAL KAF WITH DAGESH
  2915. case 0xfb43: // HEBREW LETTER FINAL PE WITH DAGESH
  2916. chRet++;
  2917. break;
  2918. }
  2919. }
  2920. return ch;
  2921. }
  2922. //----------------------------------------------------------------------
  2923. //
  2924. // function: CompareStringString( ... )
  2925. //
  2926. // purpose: Helper for CompareStringWrap.
  2927. //
  2928. // We handle the string comparsion for CompareStringWrap.
  2929. // We can convert each character to (1) fullwidth,
  2930. // (2) Katakana, and (3) lowercase, as necessary.
  2931. //
  2932. // returns: 1 - string A is less in lexical value as string B
  2933. // 2 - string B is equal in lexical value as string B
  2934. // 3 - string B is greater in lexical value as string B
  2935. //
  2936. //----------------------------------------------------------------------
  2937. static int CompareStringString(
  2938. DWORD dwFlags,
  2939. LPCWSTR lpA,
  2940. int cchA,
  2941. LPCWSTR lpB,
  2942. int cchB )
  2943. {
  2944. int nRet = 0;
  2945. WCHAR wchIgnoreNulA = cchA == -1 ? 0 : -1;
  2946. WCHAR wchIgnoreNulB = cchB == -1 ? 0 : -1;
  2947. WCHAR (*pfnTransformWidth)(LPCWSTR *, int);
  2948. WCHAR (*pfnTransformKana)(WCHAR);
  2949. DWORD (*pfnTransformLower)(LPWSTR, DWORD);
  2950. WCHAR (*pfnTransformFinal)(WCHAR);
  2951. pfnTransformWidth = (dwFlags & NORM_IGNOREWIDTH)
  2952. ? TransformCharWidth : TransformCharNoOp1;
  2953. pfnTransformKana = (dwFlags & NORM_IGNOREKANATYPE)
  2954. ? TransformCharKana : TransformCharNoOp2;
  2955. pfnTransformLower = (dwFlags & NORM_IGNORECASE)
  2956. ? CharLowerBuffWrap : TransformCharNoOp3;
  2957. pfnTransformFinal = (dwFlags & NORM_IGNORECASE)
  2958. ? TransformCharFinal : TransformCharNoOp2;
  2959. while ( !nRet
  2960. && cchA
  2961. && cchB
  2962. && (*lpA | wchIgnoreNulA)
  2963. && (*lpB | wchIgnoreNulB) )
  2964. {
  2965. WCHAR chA, chB;
  2966. LPCWSTR lpAOld = lpA;
  2967. LPCWSTR lpBOld = lpB;
  2968. chA = (*pfnTransformWidth)(&lpA, cchA);
  2969. chA = (*pfnTransformKana)(chA);
  2970. (*pfnTransformLower)(&chA, 1);
  2971. chA = (*pfnTransformFinal)(chA);
  2972. chB = (*pfnTransformWidth)(&lpB, cchB);
  2973. chB = (*pfnTransformKana)(chB);
  2974. (*pfnTransformLower)(&chB, 1);
  2975. chB = (*pfnTransformFinal)(chB);
  2976. nRet = (int)chA - (int)chB;
  2977. cchA -= (int) (lpA-lpAOld);
  2978. cchB -= (int) (lpB-lpBOld);
  2979. }
  2980. if (!nRet)
  2981. {
  2982. nRet = cchA - cchB;
  2983. }
  2984. if (nRet)
  2985. {
  2986. nRet = nRet > 0 ? 1 : -1;
  2987. }
  2988. return nRet + 2;
  2989. }
  2990. //----------------------------------------------------------------------
  2991. //
  2992. // function: CompareStringWord( ... )
  2993. //
  2994. // purpose: Helper for CompareStringWrap.
  2995. //
  2996. // We handle the word comparsion for CompareStringWrap.
  2997. //
  2998. // returns: 1 - string A is less in lexical value as string B
  2999. // 2 - string B is equal in lexical value as string B
  3000. // 3 - string B is greater in lexical value as string B
  3001. //
  3002. //----------------------------------------------------------------------
  3003. static int CompareStringWord(
  3004. LCID lcid,
  3005. DWORD dwFlags,
  3006. LPCWSTR lpA,
  3007. int cchA,
  3008. LPCWSTR lpB,
  3009. int cchB )
  3010. {
  3011. // BUGBUG (cthrash) We won't properly support word compare for the
  3012. // time being. Do the same old CP_ACP trick, which should cover
  3013. // enough cases.
  3014. // fail if either string is NULL, as it causes assert on debug windows
  3015. if (!lpA || !lpB)
  3016. return 0;
  3017. CStrIn strA(lpA, cchA);
  3018. CStrIn strB(lpB, cchB);
  3019. cchA = strA.strlen();
  3020. cchB = strB.strlen();
  3021. return CompareStringA(lcid, dwFlags, strA, cchA, strB, cchB);
  3022. }
  3023. //----------------------------------------------------------------------
  3024. //
  3025. // function: CompareStringWrap( ... )
  3026. //
  3027. // purpose: Unicode wrapper of CompareString for Win95.
  3028. //
  3029. // Note not all bits in dwFlags are honored; specifically,
  3030. // since we don't do a true widechar word compare, we
  3031. // won't properly handle NORM_IGNORENONSPACE or
  3032. // NORM_IGNORESYMBOLS for arbitrary widechar strings.
  3033. //
  3034. // returns: 1 - string A is less in lexical value as string B
  3035. // 2 - string B is equal in lexical value as string B
  3036. // 3 - string B is greater in lexical value as string B
  3037. //
  3038. //----------------------------------------------------------------------
  3039. LWSTDAPI_(int) CompareStringAltW(
  3040. LCID lcid,
  3041. DWORD dwFlags,
  3042. LPCWSTR lpA,
  3043. int cchA,
  3044. LPCWSTR lpB,
  3045. int cchB )
  3046. {
  3047. int nRet;
  3048. if (dwFlags & SORT_STRINGSORT)
  3049. {
  3050. nRet = CompareStringString(dwFlags, lpA, cchA, lpB, cchB);
  3051. }
  3052. else
  3053. {
  3054. nRet = CompareStringWord(lcid, dwFlags, lpA, cchA, lpB, cchB);
  3055. }
  3056. return nRet;
  3057. }
  3058. int CompareStringWrap(
  3059. LCID Locale,
  3060. DWORD dwCmpFlags,
  3061. LPCWSTR lpString1,
  3062. int cchCount1,
  3063. LPCWSTR lpString2,
  3064. int cchCount2)
  3065. {
  3066. // fail if either string is NULL, as it causes assert on debug windows
  3067. if (!lpString1 || !lpString2)
  3068. return 0;
  3069. CStrIn strString1(lpString1, cchCount1);
  3070. CStrIn strString2(lpString2, cchCount2);
  3071. cchCount1 = strString1.strlen();
  3072. cchCount2 = strString2.strlen();
  3073. return CompareStringA(Locale, dwCmpFlags,
  3074. strString1,cchCount1,
  3075. strString2,cchCount2);
  3076. }
  3077. BOOL MessageBoxIndirectWrap(MSGBOXPARAMS *pmbp)
  3078. {
  3079. CStrIn strText(pmbp->lpszText);
  3080. CStrIn strCaption(pmbp->lpszCaption);
  3081. MSGBOXPARAMSA mbp;
  3082. memcpy(&mbp, pmbp, sizeof(mbp));
  3083. mbp.lpszText = strText;
  3084. mbp.lpszCaption = strCaption;
  3085. ASSERT(HIWORD64(mbp.lpszIcon) == 0);
  3086. return MessageBoxIndirectA(&mbp);
  3087. }
  3088. DWORD GetCharacterPlacementWrap(
  3089. HDC hdc, // handle to device context
  3090. LPCTSTR lpString, // pointer to string
  3091. int nCount, // number of characters in string
  3092. int nMaxExtent, // maximum extent for displayed string
  3093. LPGCP_RESULTS lpResults, // pointer to buffer for placement result
  3094. DWORD dwFlags // placement flags
  3095. )
  3096. {
  3097. CStrIn strText(lpString);
  3098. DWORD dwRet;
  3099. // Leave for someone else.
  3100. ASSERT (lpResults->lpOutString == NULL);
  3101. ASSERT (lpResults->lpClass == NULL);
  3102. dwRet = GetCharacterPlacementA (hdc, strText, nCount, nMaxExtent,
  3103. (LPGCP_RESULTSA)lpResults,
  3104. dwFlags);
  3105. return dwRet;
  3106. }
  3107. #ifndef FONT_LINK
  3108. BOOL GetCharWidthWrap (
  3109. HDC hdc,
  3110. UINT iFirstChar,
  3111. UINT iLastChar,
  3112. LPINT lpBuffer)
  3113. {
  3114. // Note that we expect to do only one character at a time for anything but
  3115. // ISO Latin 1.
  3116. if (iFirstChar > 255)
  3117. {
  3118. UINT mbChar=0;
  3119. WCHAR ch;
  3120. // Convert string
  3121. ch = (WCHAR)iFirstChar;
  3122. WideCharToMultiByte(CP_ACP, 0, &ch, 1,
  3123. (char *)&mbChar, 2, NULL, NULL);
  3124. }
  3125. return (GetCharWidthA (hdc, iFirstChar, iLastChar, lpBuffer));
  3126. }
  3127. #endif
  3128. BOOL ModifyMenuWrap(
  3129. HMENU hMenu,
  3130. UINT uPosition,
  3131. UINT uFlags,
  3132. UINT uIDNewItem,
  3133. LPCWSTR lpNewItem)
  3134. {
  3135. ASSERT(!(uFlags & MF_BITMAP) && !(uFlags & MF_OWNERDRAW));
  3136. CStrIn str(lpNewItem);
  3137. return ModifyMenuA(hMenu, uPosition, uFlags, uIDNewItem, str);
  3138. }
  3139. BOOL CopyFileWrap(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, BOOL bFailIfExists)
  3140. {
  3141. CStrIn strOld(lpExistingFileName);
  3142. CStrIn strNew(lpNewFileName);
  3143. return CopyFileA(strOld, strNew, bFailIfExists);
  3144. }
  3145. BOOL MoveFileWrap(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName)
  3146. {
  3147. CStrIn strOld(lpExistingFileName);
  3148. CStrIn strNew(lpNewFileName);
  3149. return MoveFileA(strOld, strNew);
  3150. }
  3151. BOOL OemToCharWrap(LPCSTR lpszSrc, LPWSTR lpszDst)
  3152. {
  3153. CStrOut strDst(lpszDst, lstrlenA(lpszSrc));
  3154. return OemToCharA(lpszSrc, strDst);
  3155. }
  3156. VOID OutputDebugStringWrap(LPCWSTR lpOutputString)
  3157. {
  3158. CStrIn str(lpOutputString);
  3159. OutputDebugStringA(str);
  3160. }
  3161. BOOL PeekMessageWrap(
  3162. LPMSG lpMsg,
  3163. HWND hWnd,
  3164. UINT wMsgFilterMin,
  3165. UINT wMsgFilterMax,
  3166. UINT wRemoveMsg)
  3167. {
  3168. return PeekMessageA(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
  3169. }
  3170. BOOL PostMessageWrap(
  3171. HWND hWnd,
  3172. UINT Msg,
  3173. WPARAM wParam,
  3174. LPARAM lParam)
  3175. {
  3176. return PostMessageA(hWnd, Msg, wParam, lParam);
  3177. }
  3178. BOOL PostThreadMessageWrap(
  3179. DWORD idThread,
  3180. UINT Msg,
  3181. WPARAM wParam,
  3182. LPARAM lParam)
  3183. {
  3184. return PostThreadMessageA(idThread, Msg, wParam, lParam);
  3185. }
  3186. LONG RegCreateKeyWrap(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult)
  3187. {
  3188. CStrIn str(lpSubKey);
  3189. return RegCreateKeyA(hKey, str, phkResult);
  3190. }
  3191. LONG RegCreateKeyExWrap(HKEY hKey, LPCTSTR lpSubKey, DWORD Reserved, LPTSTR lpClass, DWORD dwOptions, REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition)
  3192. {
  3193. CStrIn strSubKey(lpSubKey);
  3194. CStrIn strClass(lpClass);
  3195. return RegCreateKeyExA(hKey, strSubKey, Reserved, strClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition);
  3196. }
  3197. LONG RegDeleteKeyWrap(HKEY hKey, LPCWSTR pwszSubKey)
  3198. {
  3199. CStrIn str(pwszSubKey);
  3200. return RegDeleteKeyA(hKey, str);
  3201. }
  3202. LONG RegEnumKeyWrap(
  3203. HKEY hKey,
  3204. DWORD dwIndex,
  3205. LPWSTR lpName,
  3206. DWORD cbName)
  3207. {
  3208. CStrOut str(lpName, cbName);
  3209. return RegEnumKeyA(hKey, dwIndex, str, str.BufSize());
  3210. }
  3211. LONG RegEnumKeyExWrap(
  3212. HKEY hKey,
  3213. DWORD dwIndex,
  3214. LPWSTR lpName,
  3215. LPDWORD lpcbName,
  3216. LPDWORD lpReserved,
  3217. LPWSTR lpClass,
  3218. LPDWORD lpcbClass,
  3219. PFILETIME lpftLastWriteTime)
  3220. {
  3221. long ret;
  3222. DWORD dwClass = 0;
  3223. if (!lpcbClass)
  3224. {
  3225. lpcbClass = &dwClass;
  3226. }
  3227. CStrOut strName(lpName, *lpcbName);
  3228. CStrOut strClass(lpClass, *lpcbClass);
  3229. ret = RegEnumKeyExA(
  3230. hKey,
  3231. dwIndex,
  3232. strName,
  3233. lpcbName,
  3234. lpReserved,
  3235. strClass,
  3236. lpcbClass,
  3237. lpftLastWriteTime);
  3238. *lpcbName = strName.ConvertExcludingNul();
  3239. *lpcbClass = strClass.ConvertExcludingNul();
  3240. return ret;
  3241. }
  3242. LONG RegOpenKeyWrap(HKEY hKey, LPCWSTR pwszSubKey, PHKEY phkResult)
  3243. {
  3244. CStrIn str(pwszSubKey);
  3245. return RegOpenKeyA(hKey, str, phkResult);
  3246. }
  3247. LONG RegOpenKeyExWrap(
  3248. HKEY hKey,
  3249. LPCWSTR lpSubKey,
  3250. DWORD ulOptions,
  3251. REGSAM samDesired,
  3252. PHKEY phkResult)
  3253. {
  3254. CStrIn str(lpSubKey);
  3255. return RegOpenKeyExA(hKey, str, ulOptions, samDesired, phkResult);
  3256. }
  3257. LONG RegQueryInfoKeyWrap(
  3258. HKEY hKey,
  3259. LPWSTR lpClass,
  3260. LPDWORD lpcbClass,
  3261. LPDWORD lpReserved,
  3262. LPDWORD lpcSubKeys,
  3263. LPDWORD lpcbMaxSubKeyLen,
  3264. LPDWORD lpcbMaxClassLen,
  3265. LPDWORD lpcValues,
  3266. LPDWORD lpcbMaxValueNameLen,
  3267. LPDWORD lpcbMaxValueLen,
  3268. LPDWORD lpcbSecurityDescriptor,
  3269. PFILETIME lpftLastWriteTime)
  3270. {
  3271. CStrIn str(lpClass);
  3272. return RegQueryInfoKeyA(
  3273. hKey,
  3274. str,
  3275. lpcbClass,
  3276. lpReserved,
  3277. lpcSubKeys,
  3278. lpcbMaxSubKeyLen,
  3279. lpcbMaxClassLen,
  3280. lpcValues,
  3281. lpcbMaxValueNameLen,
  3282. lpcbMaxValueLen,
  3283. lpcbSecurityDescriptor,
  3284. lpftLastWriteTime);
  3285. }
  3286. LONG RegQueryValueWrap(
  3287. HKEY hKey,
  3288. LPCWSTR pwszSubKey,
  3289. LPWSTR pwszValue,
  3290. PLONG lpcbValue)
  3291. {
  3292. long ret;
  3293. long cb;
  3294. CStrIn strKey(pwszSubKey);
  3295. CStrOut strValue(pwszValue, (*lpcbValue) / sizeof(WCHAR));
  3296. cb = strValue.BufSize();
  3297. ret = RegQueryValueA(hKey, strKey, strValue, &cb);
  3298. if (ret != ERROR_SUCCESS)
  3299. goto Cleanup;
  3300. if (strValue)
  3301. {
  3302. cb = strValue.ConvertIncludingNul();
  3303. }
  3304. *lpcbValue = cb * sizeof(WCHAR);
  3305. Cleanup:
  3306. return ret;
  3307. }
  3308. LONG RegQueryValueExWrap(
  3309. HKEY hKey,
  3310. LPCWSTR lpValueName,
  3311. LPDWORD lpReserved,
  3312. LPDWORD lpType,
  3313. LPBYTE lpData,
  3314. LPDWORD lpcbData)
  3315. {
  3316. LONG ret;
  3317. CStrIn strValueName(lpValueName);
  3318. DWORD dwTempType;
  3319. DWORD cb;
  3320. //
  3321. // Determine the type of buffer needed
  3322. //
  3323. ret = RegQueryValueExA(hKey, strValueName, lpReserved, &dwTempType, NULL, &cb);
  3324. if (ret != ERROR_SUCCESS)
  3325. goto Cleanup;
  3326. ASSERT(dwTempType != REG_MULTI_SZ);
  3327. switch (dwTempType)
  3328. {
  3329. case REG_EXPAND_SZ:
  3330. case REG_SZ:
  3331. {
  3332. CStrOut strData((LPWSTR) lpData, (*lpcbData) / sizeof(WCHAR));
  3333. cb = strData.BufSize();
  3334. ret = RegQueryValueExA(hKey, strValueName, lpReserved, lpType, (LPBYTE)(LPSTR)strData, &cb);
  3335. if (ret != ERROR_SUCCESS)
  3336. break;
  3337. if (strData)
  3338. {
  3339. cb = strData.ConvertIncludingNul();
  3340. }
  3341. *lpcbData = cb * sizeof(WCHAR);
  3342. break;
  3343. }
  3344. default:
  3345. {
  3346. ret = RegQueryValueExA(
  3347. hKey,
  3348. strValueName,
  3349. lpReserved,
  3350. lpType,
  3351. lpData,
  3352. lpcbData);
  3353. break;
  3354. }
  3355. }
  3356. Cleanup:
  3357. return ret;
  3358. }
  3359. LONG RegSetValueWrap(
  3360. HKEY hKey,
  3361. LPCWSTR lpSubKey,
  3362. DWORD dwType,
  3363. LPCWSTR lpData,
  3364. DWORD cbData)
  3365. {
  3366. CStrIn strKey(lpSubKey);
  3367. CStrIn strValue(lpData);
  3368. return RegSetValueA(hKey, strKey, dwType, strValue, cbData);
  3369. }
  3370. LONG RegSetValueExWrap(
  3371. HKEY hKey,
  3372. LPCWSTR lpValueName,
  3373. DWORD Reserved,
  3374. DWORD dwType,
  3375. CONST BYTE* lpData,
  3376. DWORD cbData)
  3377. {
  3378. ASSERT(dwType != REG_MULTI_SZ);
  3379. CStrIn strKey(lpValueName);
  3380. CStrIn strSZ((dwType == REG_SZ || dwType == REG_EXPAND_SZ) ? (LPCWSTR) lpData : NULL);
  3381. if (strSZ)
  3382. {
  3383. lpData = (LPBYTE) (LPSTR) strSZ;
  3384. cbData = strSZ.strlen() + 1;
  3385. }
  3386. return RegSetValueExA(
  3387. hKey,
  3388. strKey,
  3389. Reserved,
  3390. dwType,
  3391. lpData,
  3392. cbData);
  3393. }
  3394. ATOM RegisterClassWrap(CONST WNDCLASSW * lpWndClass)
  3395. {
  3396. WNDCLASSA wc;
  3397. CStrIn strMenuName(lpWndClass->lpszMenuName);
  3398. CStrIn strClassName(lpWndClass->lpszClassName);
  3399. ASSERT(sizeof(wc) == sizeof(*lpWndClass));
  3400. memcpy(&wc, lpWndClass, sizeof(wc));
  3401. wc.lpszMenuName = strMenuName;
  3402. wc.lpszClassName = strClassName;
  3403. return RegisterClassA(&wc);
  3404. }
  3405. UINT RegisterClipboardFormatWrap(LPCWSTR lpString)
  3406. {
  3407. CStrIn str(lpString);
  3408. return RegisterClipboardFormatA(str);
  3409. }
  3410. UINT RegisterWindowMessageWrap(LPCWSTR lpString)
  3411. {
  3412. CStrIn str(lpString);
  3413. return RegisterWindowMessageA(str);
  3414. }
  3415. HANDLE RemovePropWrap(
  3416. HWND hWnd,
  3417. LPCWSTR lpString)
  3418. {
  3419. CStrIn str(lpString);
  3420. return RemovePropA(hWnd, str);
  3421. }
  3422. // NOTE (SumitC) Instead of calling SendDlgItemMessageA below, I'm forwarding to
  3423. // SendMessageWrap so as not to have to re-do the special-case processing.
  3424. LRESULT SendDlgItemMessageWrap(
  3425. HWND hDlg,
  3426. int nIDDlgItem,
  3427. UINT Msg,
  3428. WPARAM wParam,
  3429. LPARAM lParam)
  3430. {
  3431. HWND hWnd;
  3432. hWnd = GetDlgItem(hDlg, nIDDlgItem);
  3433. return SendMessageWrap(hWnd, Msg, wParam, lParam);
  3434. }
  3435. // AdjustECPosition
  3436. //
  3437. // Convert mulitbyte position to unicode number of character position in EDIT control
  3438. //
  3439. // iType: ADJUST_TO_WCHAR_POS or ADJUST_TO_CHAR_POS
  3440. //
  3441. #define ADJUST_TO_WCHAR_POS 0
  3442. #define ADJUST_TO_CHAR_POS 1
  3443. int AdjustECPosition(char *psz, int iPos, int iType)
  3444. {
  3445. char *pstr = psz;
  3446. int iNewPos = iPos;
  3447. if (ADJUST_TO_WCHAR_POS == iType)
  3448. {
  3449. iNewPos = 0;
  3450. while (*pstr && (pstr - psz != iPos))
  3451. {
  3452. pstr = CharNextA(pstr);
  3453. iNewPos++;
  3454. }
  3455. }
  3456. else if (ADJUST_TO_CHAR_POS == iType)
  3457. {
  3458. while (*pstr && iPos--)
  3459. pstr = CharNextA(pstr);
  3460. iNewPos = (int) (pstr-psz);
  3461. }
  3462. return iNewPos;
  3463. }
  3464. //
  3465. // Edit controls can get really huge, so the MAX_PATH buffer in
  3466. // SendMessageWrap just doesn't cut it when push comes to shove.
  3467. //
  3468. // Try to use the small buffer, and switch to an allocated buffer
  3469. // only if the small buffer doesn't work.
  3470. //
  3471. // Use the handy CConvertStr class as our basis.
  3472. //
  3473. class CStrA : public CConvertStr
  3474. {
  3475. public:
  3476. CStrA(int cch);
  3477. inline int bufsize() { return _cchLen; }
  3478. protected:
  3479. int _cchLen;
  3480. };
  3481. CStrA::CStrA(int cch) : CConvertStr(CP_ACP)
  3482. {
  3483. _cchLen = cch;
  3484. if (cch <= ARRAYSIZE(_ach))
  3485. {
  3486. // It fits in our small buffer
  3487. _pstr = _ach;
  3488. }
  3489. else
  3490. {
  3491. // Need to allocate a big buffer
  3492. _pstr = new char[cch];
  3493. if (!_pstr)
  3494. {
  3495. // On failure, use the small buffer after all.
  3496. _pstr = _ach;
  3497. _cchLen = ARRAYSIZE(_ach);
  3498. }
  3499. }
  3500. }
  3501. LRESULT SendEditMessageWrap(
  3502. HWND hWnd,
  3503. UINT Msg,
  3504. WPARAM wParam,
  3505. LPARAM lParam)
  3506. {
  3507. WORD wStart, wEnd;
  3508. DWORD dwPos;
  3509. //
  3510. // EM_SETSEL is special - We can often handle it without having to
  3511. // get the client text, which is good since some clients
  3512. // return bad data.
  3513. //
  3514. // If the start and end positions are both either 0 or -1, then we
  3515. // don't need to do adjustment since 0 is always 0 and -1 is always -1.
  3516. //
  3517. if (Msg == EM_SETSEL) {
  3518. if ((wParam == 0 || (DWORD)wParam == 0xFFFFFFFF) &&
  3519. (lParam == 0 || (DWORD)lParam == 0xFFFFFFFF))
  3520. return SendMessageA(hWnd, Msg, wParam, lParam);
  3521. }
  3522. // Get the current window text, since we will be studying it
  3523. CStrA sz(GetWindowTextLengthA(hWnd) + 1);
  3524. GetWindowTextA(hWnd, sz, sz.bufsize());
  3525. switch (Msg)
  3526. {
  3527. case EM_GETSEL:
  3528. {
  3529. DWORD_PTR dwPos;
  3530. dwPos = SendMessageA(hWnd, Msg, wParam, lParam);
  3531. wStart = (WORD)AdjustECPosition(sz, GET_X_LPARAM(dwPos), ADJUST_TO_WCHAR_POS);
  3532. wEnd = (WORD)AdjustECPosition(sz, GET_Y_LPARAM(dwPos), ADJUST_TO_WCHAR_POS);
  3533. return MAKELONG(wStart, wEnd);
  3534. }
  3535. case EM_SETSEL:
  3536. wStart = (WORD)AdjustECPosition(sz, wParam, ADJUST_TO_CHAR_POS);
  3537. wEnd = (WORD)AdjustECPosition(sz, lParam, ADJUST_TO_CHAR_POS);
  3538. return SendMessageA(hWnd, Msg, wStart, wEnd);
  3539. case EM_LINEINDEX:
  3540. dwPos = SendMessageA(hWnd, Msg, wParam, lParam);
  3541. return AdjustECPosition(sz, dwPos, ADJUST_TO_WCHAR_POS);
  3542. case EM_LINELENGTH:
  3543. wStart = (WORD)AdjustECPosition(sz, wParam, ADJUST_TO_CHAR_POS);
  3544. dwPos = SendMessageA(hWnd, Msg, wStart, lParam);
  3545. return AdjustECPosition(sz + wStart, dwPos, ADJUST_TO_WCHAR_POS);
  3546. case EM_LINEFROMCHAR:
  3547. case EM_POSFROMCHAR:
  3548. wStart = (WORD)AdjustECPosition(sz, wParam, ADJUST_TO_CHAR_POS);
  3549. return SendMessageA(hWnd, Msg, wStart, lParam);
  3550. default:
  3551. AssertMsg(FALSE, TEXT("error: unknown message leaked into SendEditMessageWrap"));
  3552. return SendMessageA(hWnd, Msg, wParam, lParam);
  3553. }
  3554. }
  3555. #ifndef UNIX
  3556. #define SHLWAPI_SENDMESSAGEWRAPW_ORD 136
  3557. #else
  3558. #define SHLWAPI_SENDMESSAGEWRAPW_ORD "SendMessageWrapW"
  3559. #endif
  3560. typedef LRESULT (* PFNSENDMESSAGEWRAPW)(HWND, UINT, WPARAM, LPARAM);
  3561. LRESULT SendMessageWrap(
  3562. HWND hWnd,
  3563. UINT Msg,
  3564. WPARAM wParam,
  3565. LPARAM lParam)
  3566. {
  3567. // For XCP PlugUI:
  3568. // 1)If shlwapi is in memory, ask it to do the work, otherwise let it
  3569. // fall through to original comctl32 wrap implementation.
  3570. // 2)This implementation only apply to LB for fixing #67837
  3571. switch (Msg)
  3572. {
  3573. case LB_ADDSTRING:
  3574. case LB_FINDSTRING:
  3575. case LB_FINDSTRINGEXACT:
  3576. case LB_INSERTSTRING:
  3577. case LB_GETTEXT:
  3578. case LB_GETTEXTLEN:
  3579. case LB_SELECTSTRING:
  3580. {
  3581. extern HMODULE GetShlwapiHModule();
  3582. PFNSENDMESSAGEWRAPW pfnSndMsgWrapW = NULL;
  3583. HMODULE hShlwapi;
  3584. hShlwapi = GetShlwapiHModule();
  3585. if (hShlwapi)
  3586. pfnSndMsgWrapW = (PFNSENDMESSAGEWRAPW)GetProcAddress(hShlwapi, (LPCSTR)SHLWAPI_SENDMESSAGEWRAPW_ORD);
  3587. if (pfnSndMsgWrapW)
  3588. return pfnSndMsgWrapW(hWnd, Msg, wParam, lParam);
  3589. else
  3590. break; // fall through the regular comctl32's wrap
  3591. }
  3592. }
  3593. // original comctl32's wrap implementation
  3594. CHAR sz[MAX_PATH]; // BUGBUG: It's big enough current comctl32 usage until now ...
  3595. switch (Msg)
  3596. {
  3597. case WM_GETTEXT:
  3598. {
  3599. CStrOut str((LPWSTR)lParam, (int) wParam);
  3600. SendMessageA(hWnd, Msg, (WPARAM) str.BufSize(), (LPARAM) (LPSTR) str);
  3601. return str.ConvertExcludingNul();
  3602. }
  3603. // The sz[] buffer is not large enough for these guys, so use a
  3604. // separate helper function.
  3605. case EM_GETSEL:
  3606. case EM_SETSEL:
  3607. case EM_LINEINDEX:
  3608. case EM_LINELENGTH:
  3609. case EM_LINEFROMCHAR:
  3610. case EM_POSFROMCHAR:
  3611. return SendEditMessageWrap(hWnd, Msg, wParam, lParam);
  3612. // BUGBUG raymondc - This is wrong. EM_GETLIMITTEXT returns the number
  3613. // of characters, not bytes. But the only place we use it is in our
  3614. // IME composition code, and maybe they really meant to divide by two...
  3615. case EM_GETLIMITTEXT:
  3616. return SendMessageA(hWnd, Msg, wParam, lParam) / sizeof(WCHAR);
  3617. case EM_GETLINE:
  3618. {
  3619. LRESULT nLen;
  3620. CStrOut str((LPWSTR) lParam, (* (SHORT *) lParam) + 1);
  3621. * (SHORT *) (LPSTR) str = * (SHORT *) lParam;
  3622. nLen = SendMessageA(hWnd, Msg, (WPARAM) wParam, (LPARAM) (LPSTR) str);
  3623. if(nLen > 0)
  3624. ((LPSTR) str)[nLen] = '\0';
  3625. return nLen;
  3626. }
  3627. // BUGBUG: Always assume lParam points structure, not string buffer
  3628. case CB_INSERTSTRING:
  3629. {
  3630. return SendMessageA(hWnd, Msg, wParam, (LPARAM) lParam);
  3631. }
  3632. case WM_SETTEXT:
  3633. case LB_ADDSTRING:
  3634. case CB_ADDSTRING:
  3635. case EM_REPLACESEL:
  3636. ASSERT(wParam == 0 && "wParam should be 0 for these messages");
  3637. // fall through
  3638. case CB_SELECTSTRING:
  3639. case CB_FINDSTRINGEXACT:
  3640. case CB_FINDSTRING:
  3641. case LB_INSERTSTRING:
  3642. case LB_FINDSTRINGEXACT:
  3643. {
  3644. CStrIn str((LPWSTR) lParam);
  3645. return SendMessageA(hWnd, Msg, wParam, (LPARAM) (LPSTR) str);
  3646. }
  3647. case LB_GETTEXTLEN:
  3648. case CB_GETLBTEXTLEN:
  3649. ASSERT((LB_GETTEXTLEN - LB_GETTEXT) == (CB_GETLBTEXTLEN - CB_GETLBTEXT));
  3650. lParam = (LPARAM)sz; // use temp buffer
  3651. Msg -= (LB_GETTEXTLEN - LB_GETTEXT);
  3652. // fall through ...
  3653. case LB_GETTEXT:
  3654. case CB_GETLBTEXT:
  3655. {
  3656. CStrOut str((LPWSTR)lParam, 255);
  3657. SendMessageA(hWnd, Msg, wParam, (LPARAM) (LPSTR) str);
  3658. return str.ConvertExcludingNul();
  3659. }
  3660. case EM_SETPASSWORDCHAR:
  3661. {
  3662. WPARAM wp;
  3663. ASSERT(HIWORD64(wParam) == 0);
  3664. MbcsFromUnicode((LPSTR) &wp, sizeof(wp), (LPWSTR) &wParam);
  3665. ASSERT(HIWORD64(wp) == 0);
  3666. return SendMessageA(hWnd, Msg, wp, lParam);
  3667. }
  3668. default:
  3669. return SendMessageA(hWnd, Msg, wParam, lParam);
  3670. }
  3671. }
  3672. BOOL SendNotifyMessageWrap(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
  3673. {
  3674. // BUGBUG: Should we use SendMessageWarp like SendDlgItemMessageWrap above?
  3675. return SendNotifyMessageA(hWnd, Msg, wParam, lParam);
  3676. }
  3677. BOOL SetCurrentDirectoryWrap(LPCWSTR lpszCurDir)
  3678. {
  3679. CStrIn str(lpszCurDir);
  3680. return SetCurrentDirectoryA(str);
  3681. }
  3682. BOOL SetDlgItemTextWrap(HWND hDlg, int nIDDlgItem, LPCWSTR lpString)
  3683. {
  3684. CStrIn str(lpString);
  3685. return SetDlgItemTextA(hDlg, nIDDlgItem, str);
  3686. }
  3687. BOOL SetMenuItemInfoWrap(
  3688. HMENU hMenu,
  3689. UINT uItem,
  3690. BOOL fByPosition,
  3691. LPCMENUITEMINFOW lpmiiW)
  3692. {
  3693. BOOL fRet;
  3694. ASSERT( sizeof(MENUITEMINFOW) == sizeof(MENUITEMINFOA) &&
  3695. FIELD_OFFSET(MENUITEMINFOW, dwTypeData) ==
  3696. FIELD_OFFSET(MENUITEMINFOA, dwTypeData) );
  3697. if ( (MIIM_TYPE & lpmiiW->fMask) &&
  3698. 0 == (lpmiiW->fType & (MFT_BITMAP | MFT_SEPARATOR)))
  3699. {
  3700. MENUITEMINFOA miiA;
  3701. CStrIn str(lpmiiW->dwTypeData, lpmiiW->cch);
  3702. memcpy( &miiA, lpmiiW, sizeof(MENUITEMINFOA) );
  3703. miiA.dwTypeData = str;
  3704. miiA.cch = str.strlen();
  3705. fRet = SetMenuItemInfoA( hMenu, uItem, fByPosition, &miiA );
  3706. }
  3707. else
  3708. {
  3709. fRet = SetMenuItemInfoA( hMenu, uItem, fByPosition,
  3710. (LPCMENUITEMINFOA)lpmiiW );
  3711. }
  3712. return fRet;
  3713. }
  3714. BOOL SetPropWrap(
  3715. HWND hWnd,
  3716. LPCWSTR lpString,
  3717. HANDLE hData)
  3718. {
  3719. CStrIn str(lpString);
  3720. return SetPropA(hWnd, str, hData);
  3721. }
  3722. LONG SetWindowLongWrap(HWND hWnd, int nIndex, LONG dwNewLong)
  3723. {
  3724. return SetWindowLongA(hWnd, nIndex, dwNewLong);
  3725. }
  3726. HHOOK SetWindowsHookExWrap(
  3727. int idHook,
  3728. HOOKPROC lpfn,
  3729. HINSTANCE hmod,
  3730. DWORD dwThreadId)
  3731. {
  3732. return SetWindowsHookExA(idHook, lpfn, hmod, dwThreadId);
  3733. }
  3734. BOOL SetWindowTextWrap(HWND hWnd, LPCWSTR lpString)
  3735. {
  3736. CStrIn str(lpString);
  3737. return SetWindowTextA(hWnd, str);
  3738. }
  3739. BOOL SystemParametersInfoWrap(
  3740. UINT uiAction,
  3741. UINT uiParam,
  3742. PVOID pvParam,
  3743. UINT fWinIni)
  3744. {
  3745. BOOL ret;
  3746. char ach[LF_FACESIZE];
  3747. if (uiAction == SPI_SETDESKWALLPAPER)
  3748. {
  3749. CStrIn str((LPCWSTR) pvParam);
  3750. ret = SystemParametersInfoA(
  3751. uiAction,
  3752. uiParam,
  3753. str,
  3754. fWinIni);
  3755. }
  3756. else if (uiAction == SPI_GETNONCLIENTMETRICS)
  3757. {
  3758. NONCLIENTMETRICSA ncmA;
  3759. NONCLIENTMETRICS *pncm = (NONCLIENTMETRICS *)pvParam;
  3760. ASSERT(uiParam == sizeof(NONCLIENTMETRICS) && pncm->cbSize == sizeof(NONCLIENTMETRICS));
  3761. ncmA.cbSize = sizeof(ncmA);
  3762. ret = SystemParametersInfoA(
  3763. uiAction,
  3764. sizeof(ncmA),
  3765. &ncmA,
  3766. fWinIni);
  3767. pncm->iBorderWidth = ncmA.iBorderWidth;
  3768. pncm->iScrollWidth = ncmA.iScrollWidth;
  3769. pncm->iScrollHeight = ncmA.iScrollHeight;
  3770. pncm->iCaptionWidth = ncmA.iCaptionWidth;
  3771. pncm->iCaptionHeight = ncmA.iCaptionHeight;
  3772. pncm->iSmCaptionWidth = ncmA.iSmCaptionWidth;
  3773. pncm->iSmCaptionHeight = ncmA.iSmCaptionHeight;
  3774. pncm->iMenuWidth = ncmA.iMenuWidth;
  3775. pncm->iMenuHeight = ncmA.iMenuHeight;
  3776. memcpy(&pncm->lfCaptionFont, &ncmA.lfCaptionFont, FIELD_OFFSET(LOGFONTW, lfFaceName));
  3777. UnicodeFromMbcs(pncm->lfCaptionFont.lfFaceName, ARRAYSIZE(pncm->lfCaptionFont.lfFaceName), ncmA.lfCaptionFont.lfFaceName);
  3778. memcpy(&pncm->lfSmCaptionFont, &ncmA.lfSmCaptionFont, FIELD_OFFSET(LOGFONTW, lfFaceName));
  3779. UnicodeFromMbcs(pncm->lfSmCaptionFont.lfFaceName, ARRAYSIZE(pncm->lfSmCaptionFont.lfFaceName), ncmA.lfSmCaptionFont.lfFaceName);
  3780. memcpy(&pncm->lfMenuFont, &ncmA.lfMenuFont, FIELD_OFFSET(LOGFONTW, lfFaceName));
  3781. UnicodeFromMbcs(pncm->lfMenuFont.lfFaceName, ARRAYSIZE(pncm->lfMenuFont.lfFaceName), ncmA.lfMenuFont.lfFaceName);
  3782. memcpy(&pncm->lfStatusFont, &ncmA.lfStatusFont, FIELD_OFFSET(LOGFONTW, lfFaceName));
  3783. UnicodeFromMbcs(pncm->lfStatusFont.lfFaceName, ARRAYSIZE(pncm->lfStatusFont.lfFaceName), ncmA.lfStatusFont.lfFaceName);
  3784. memcpy(&pncm->lfMessageFont, &ncmA.lfMessageFont, FIELD_OFFSET(LOGFONTW, lfFaceName));
  3785. UnicodeFromMbcs(pncm->lfMessageFont.lfFaceName, ARRAYSIZE(pncm->lfMessageFont.lfFaceName), ncmA.lfMessageFont.lfFaceName);
  3786. }
  3787. else
  3788. ret = SystemParametersInfoA(
  3789. uiAction,
  3790. uiParam,
  3791. pvParam,
  3792. fWinIni);
  3793. if ((uiAction == SPI_GETICONTITLELOGFONT) && ret)
  3794. {
  3795. strcpy(ach, ((LPLOGFONTA)pvParam)->lfFaceName);
  3796. UnicodeFromMbcs(
  3797. ((LPLOGFONTW)pvParam)->lfFaceName,
  3798. ARRAYSIZE(((LPLOGFONTW)pvParam)->lfFaceName),
  3799. ach);
  3800. }
  3801. return ret;
  3802. }
  3803. #ifndef FONT_LINK
  3804. BOOL TextOutWrap(HDC hdc, int x, int y, LPCWSTR lpStr, int cb)
  3805. {
  3806. if (g_fMEEnabled && !g_bRunOnMemphis)
  3807. {
  3808. CStrIn str(lpStr);
  3809. return TextOutA(hdc, x, y, str, str.strlen());
  3810. }
  3811. else
  3812. return TextOutW(hdc, x, y, lpStr, cb);
  3813. }
  3814. #endif
  3815. int TranslateAcceleratorWrap(HWND hWnd, HACCEL hAccTable, LPMSG lpMsg)
  3816. {
  3817. return TranslateAcceleratorA(hWnd, hAccTable, lpMsg);
  3818. }
  3819. BOOL UnregisterClassWrap(LPCWSTR lpClassName, HINSTANCE hInstance)
  3820. {
  3821. CStrIn str(lpClassName);
  3822. return UnregisterClassA(str, hInstance);
  3823. }
  3824. SHORT VkKeyScanWrap(WCHAR ch)
  3825. {
  3826. CStrIn str(&ch, 1);
  3827. return VkKeyScanA(*(char *)str);
  3828. }
  3829. BOOL WinHelpWrap(HWND hwnd, LPCWSTR szFile, UINT uCmd, DWORD dwData)
  3830. {
  3831. CStrIn str(szFile);
  3832. return WinHelpA(hwnd, str, uCmd, dwData);
  3833. }
  3834. #define DBCS_CHARSIZE (2)
  3835. // N versions of wsprintf and wvsprintf which take an output buffer size to prevent overflow
  3836. // bugs. Taken from the NT wsprintf source code.
  3837. // _MBToWCS and _WCSToMB are actually macros which call ntrtl functions in the NT version.
  3838. int _MBToWCS(LPCSTR pszIn, int cchIn, LPWSTR *ppwszOut)
  3839. {
  3840. int cch = 0;
  3841. int cbAlloc;
  3842. if ((0 != cchIn) && (NULL != ppwszOut))
  3843. {
  3844. cchIn++;
  3845. cbAlloc = cchIn * sizeof(WCHAR);
  3846. *ppwszOut = (LPWSTR)LocalAlloc(LMEM_FIXED, cbAlloc);
  3847. if (NULL != *ppwszOut)
  3848. {
  3849. cch = MultiByteToWideChar(CP_ACP, 0, pszIn, cchIn, *ppwszOut, cchIn);
  3850. if (!cch)
  3851. {
  3852. LocalFree(*ppwszOut);
  3853. *ppwszOut = NULL;
  3854. }
  3855. else
  3856. {
  3857. cch--; // Just return the number of characters
  3858. }
  3859. }
  3860. }
  3861. return cch;
  3862. }
  3863. /****************************** Module Header ******************************\
  3864. * Module Name: wsprintf.c
  3865. *
  3866. * Copyright (c) 1985-91, Microsoft Corporation
  3867. * sprintf.c
  3868. *
  3869. * Implements Windows friendly versions of sprintf and vsprintf
  3870. *
  3871. * History:
  3872. * 2-15-89 craigc Initial
  3873. * 11-12-90 MikeHar Ported from windows 3
  3874. \***************************************************************************/
  3875. /* Max number of characters. Doesn't include termination character */
  3876. #define out(c) if (cchLimit) {*lpOut++=(c); cchLimit--;} else goto errorout
  3877. /***************************************************************************\
  3878. * SP_GetFmtValueW
  3879. *
  3880. * reads a width or precision value from the format string
  3881. *
  3882. * History:
  3883. * 11-12-90 MikeHar Ported from windows 3
  3884. * 07-27-92 GregoryW Created Unicode version (copied from SP_GetFmtValue)
  3885. \***************************************************************************/
  3886. LPCWSTR SP_GetFmtValueW(
  3887. LPCWSTR lpch,
  3888. int *lpw)
  3889. {
  3890. int ii = 0;
  3891. /* It might not work for some locales or digit sets */
  3892. while (*lpch >= L'0' && *lpch <= L'9') {
  3893. ii *= 10;
  3894. ii += (int)(*lpch - L'0');
  3895. lpch++;
  3896. }
  3897. *lpw = ii;
  3898. /*
  3899. * return the address of the first non-digit character
  3900. */
  3901. return lpch;
  3902. }
  3903. /***************************************************************************\
  3904. * SP_PutNumberW
  3905. *
  3906. * Takes an unsigned long integer and places it into a buffer, respecting
  3907. * a buffer limit, a radix, and a case select (upper or lower, for hex).
  3908. *
  3909. *
  3910. * History:
  3911. * 11-12-90 MikeHar Ported from windows 3 asm --> C
  3912. * 12-11-90 GregoryW need to increment lpstr after assignment of mod
  3913. * 02-11-92 GregoryW temporary version until we have C runtime support
  3914. \***************************************************************************/
  3915. int SP_PutNumberW(
  3916. LPWSTR lpstr,
  3917. DWORD n,
  3918. int limit,
  3919. DWORD radix,
  3920. int uppercase)
  3921. {
  3922. DWORD mod;
  3923. int count = 0;
  3924. /* It might not work for some locales or digit sets */
  3925. if(uppercase)
  3926. uppercase = 'A'-'0'-10;
  3927. else
  3928. uppercase = 'a'-'0'-10;
  3929. if (count < limit) {
  3930. do {
  3931. mod = n % radix;
  3932. n /= radix;
  3933. mod += '0';
  3934. if (mod > '9')
  3935. mod += uppercase;
  3936. *lpstr++ = (WCHAR)mod;
  3937. count++;
  3938. } while((count < limit) && n);
  3939. }
  3940. return count;
  3941. }
  3942. /***************************************************************************\
  3943. * SP_ReverseW
  3944. *
  3945. * reverses a string in place
  3946. *
  3947. * History:
  3948. * 11-12-90 MikeHar Ported from windows 3 asm --> C
  3949. * 12-11-90 GregoryW fixed boundary conditions; removed count
  3950. * 02-11-92 GregoryW temporary version until we have C runtime support
  3951. \***************************************************************************/
  3952. void SP_ReverseW(
  3953. LPWSTR lpFirst,
  3954. LPWSTR lpLast)
  3955. {
  3956. WCHAR ch;
  3957. while(lpLast > lpFirst){
  3958. ch = *lpFirst;
  3959. *lpFirst++ = *lpLast;
  3960. *lpLast-- = ch;
  3961. }
  3962. }
  3963. /***************************************************************************\
  3964. * wvsprintfW (API)
  3965. *
  3966. * wsprintfW() calls this function.
  3967. *
  3968. * History:
  3969. * 11-Feb-1992 GregoryW copied xwvsprintf
  3970. * Temporary hack until we have C runtime support
  3971. * 1-22-97 tnoonan Converted to wvnsprintfW
  3972. \***************************************************************************/
  3973. int wvnsprintfW(
  3974. LPWSTR lpOut,
  3975. int cchLimitIn,
  3976. LPCWSTR lpFmt,
  3977. va_list arglist)
  3978. {
  3979. BOOL fAllocateMem = FALSE;
  3980. WCHAR prefix, fillch;
  3981. int left, width, prec, size, sign, radix, upper, hprefix;
  3982. int cchLimit = --cchLimitIn, cch;
  3983. LPWSTR lpT, lpTWC;
  3984. LPCSTR psz;
  3985. va_list varglist = arglist;
  3986. union {
  3987. long l;
  3988. unsigned long ul;
  3989. char sz[2];
  3990. WCHAR wsz[2];
  3991. } val;
  3992. if (cchLimit < 0)
  3993. return 0;
  3994. while (*lpFmt != 0) {
  3995. if (*lpFmt == L'%') {
  3996. /*
  3997. * read the flags. These can be in any order
  3998. */
  3999. left = 0;
  4000. prefix = 0;
  4001. while (*++lpFmt) {
  4002. if (*lpFmt == L'-')
  4003. left++;
  4004. else if (*lpFmt == L'#')
  4005. prefix++;
  4006. else
  4007. break;
  4008. }
  4009. /*
  4010. * find fill character
  4011. */
  4012. if (*lpFmt == L'0') {
  4013. fillch = L'0';
  4014. lpFmt++;
  4015. } else
  4016. fillch = L' ';
  4017. /*
  4018. * read the width specification
  4019. */
  4020. lpFmt = SP_GetFmtValueW(lpFmt, &cch);
  4021. width = cch;
  4022. /*
  4023. * read the precision
  4024. */
  4025. if (*lpFmt == L'.') {
  4026. lpFmt = SP_GetFmtValueW(++lpFmt, &cch);
  4027. prec = cch;
  4028. } else
  4029. prec = -1;
  4030. /*
  4031. * get the operand size
  4032. * default size: size == 0
  4033. * long number: size == 1
  4034. * wide chars: size == 2
  4035. * It may be a good idea to check the value of size when it
  4036. * is tested for non-zero below (IanJa)
  4037. */
  4038. hprefix = 0;
  4039. if ((*lpFmt == L'w') || (*lpFmt == L't')) {
  4040. size = 2;
  4041. lpFmt++;
  4042. } else if (*lpFmt == L'l') {
  4043. size = 1;
  4044. lpFmt++;
  4045. } else {
  4046. size = 0;
  4047. if (*lpFmt == L'h') {
  4048. lpFmt++;
  4049. hprefix = 1;
  4050. }
  4051. }
  4052. upper = 0;
  4053. sign = 0;
  4054. radix = 10;
  4055. switch (*lpFmt) {
  4056. case 0:
  4057. goto errorout;
  4058. case L'i':
  4059. case L'd':
  4060. size=1;
  4061. sign++;
  4062. /*** FALL THROUGH to case 'u' ***/
  4063. case L'u':
  4064. /* turn off prefix if decimal */
  4065. prefix = 0;
  4066. donumeric:
  4067. /* special cases to act like MSC v5.10 */
  4068. if (left || prec >= 0)
  4069. fillch = L' ';
  4070. /*
  4071. * if size == 1, "%lu" was specified (good)
  4072. * if size == 2, "%wu" was specified (bad)
  4073. */
  4074. if (size) {
  4075. val.l = va_arg(varglist, LONG);
  4076. } else if (sign) {
  4077. val.l = va_arg(varglist, SHORT);
  4078. } else {
  4079. val.ul = va_arg(varglist, unsigned);
  4080. }
  4081. if (sign && val.l < 0L)
  4082. val.l = -val.l;
  4083. else
  4084. sign = 0;
  4085. lpT = lpOut;
  4086. /*
  4087. * blast the number backwards into the user buffer
  4088. */
  4089. cch = SP_PutNumberW(lpOut, val.l, cchLimit, radix, upper);
  4090. if (!(cchLimit -= cch))
  4091. goto errorout;
  4092. lpOut += cch;
  4093. width -= cch;
  4094. prec -= cch;
  4095. if (prec > 0)
  4096. width -= prec;
  4097. /*
  4098. * fill to the field precision
  4099. */
  4100. while (prec-- > 0)
  4101. out(L'0');
  4102. if (width > 0 && !left) {
  4103. /*
  4104. * if we're filling with spaces, put sign first
  4105. */
  4106. if (fillch != L'0') {
  4107. if (sign) {
  4108. sign = 0;
  4109. out(L'-');
  4110. width--;
  4111. }
  4112. if (prefix) {
  4113. out(prefix);
  4114. out(L'0');
  4115. prefix = 0;
  4116. }
  4117. }
  4118. if (sign)
  4119. width--;
  4120. /*
  4121. * fill to the field width
  4122. */
  4123. while (width-- > 0)
  4124. out(fillch);
  4125. /*
  4126. * still have a sign?
  4127. */
  4128. if (sign)
  4129. out(L'-');
  4130. if (prefix) {
  4131. out(prefix);
  4132. out(L'0');
  4133. }
  4134. /*
  4135. * now reverse the string in place
  4136. */
  4137. SP_ReverseW(lpT, lpOut - 1);
  4138. } else {
  4139. /*
  4140. * add the sign character
  4141. */
  4142. if (sign) {
  4143. out(L'-');
  4144. width--;
  4145. }
  4146. if (prefix) {
  4147. out(prefix);
  4148. out(L'0');
  4149. }
  4150. /*
  4151. * reverse the string in place
  4152. */
  4153. SP_ReverseW(lpT, lpOut - 1);
  4154. /*
  4155. * pad to the right of the string in case left aligned
  4156. */
  4157. while (width-- > 0)
  4158. out(fillch);
  4159. }
  4160. break;
  4161. case L'X':
  4162. upper++;
  4163. /*** FALL THROUGH to case 'x' ***/
  4164. case L'x':
  4165. radix = 16;
  4166. if (prefix)
  4167. if (upper)
  4168. prefix = L'X';
  4169. else
  4170. prefix = L'x';
  4171. goto donumeric;
  4172. case L'c':
  4173. case L'C':
  4174. if (!size && !hprefix) {
  4175. size = 1; // force WCHAR
  4176. }
  4177. /*** FALL THROUGH to case 'C' ***/
  4178. /*
  4179. * if size == 0, "%C" or "%hc" was specified (CHAR)
  4180. * if size == 1, "%c" or "%lc" was specified (WCHAR)
  4181. * if size == 2, "%wc" or "%tc" was specified (WCHAR)
  4182. */
  4183. cch = 1; /* One character must be copied to the output buffer */
  4184. if (size) {
  4185. val.wsz[0] = va_arg(varglist, WCHAR);
  4186. val.wsz[1] = 0;
  4187. lpT = val.wsz;
  4188. goto putwstring;
  4189. } else {
  4190. val.sz[0] = va_arg(varglist, CHAR);
  4191. val.sz[1] = 0;
  4192. psz = val.sz;
  4193. goto putstring;
  4194. }
  4195. case L's':
  4196. case L'S':
  4197. if (!size && !hprefix) {
  4198. size = 1; // force LPWSTR
  4199. }
  4200. /*** FALL THROUGH to case 'S' ***/
  4201. /*
  4202. * if size == 0, "%S" or "%hs" was specified (LPSTR)
  4203. * if size == 1, "%s" or "%ls" was specified (LPWSTR)
  4204. * if size == 2, "%ws" or "%ts" was specified (LPWSTR)
  4205. */
  4206. if (size) {
  4207. lpT = va_arg(varglist, LPWSTR);
  4208. cch = lstrlenW(lpT); // Win95 supports lstrlenW!
  4209. } else {
  4210. psz = va_arg(varglist, LPSTR);
  4211. cch = lstrlenA(psz);
  4212. putstring:
  4213. cch = _MBToWCS(psz, cch, &lpTWC);
  4214. fAllocateMem = (BOOL) cch;
  4215. lpT = lpTWC;
  4216. }
  4217. putwstring:
  4218. if (prec >= 0 && cch > prec)
  4219. cch = prec;
  4220. width -= cch;
  4221. if (left) {
  4222. while (cch--)
  4223. out(*lpT++);
  4224. while (width-- > 0)
  4225. out(fillch);
  4226. } else {
  4227. while (width-- > 0)
  4228. out(fillch);
  4229. while (cch--)
  4230. out(*lpT++);
  4231. }
  4232. if (fAllocateMem) {
  4233. LocalFree(lpTWC);
  4234. fAllocateMem = FALSE;
  4235. }
  4236. break;
  4237. default:
  4238. normalch:
  4239. out((WCHAR)*lpFmt);
  4240. break;
  4241. } /* END OF SWITCH(*lpFmt) */
  4242. } /* END OF IF(%) */ else
  4243. goto normalch; /* character not a '%', just do it */
  4244. /*
  4245. * advance to next format string character
  4246. */
  4247. lpFmt++;
  4248. } /* END OF OUTER WHILE LOOP */
  4249. errorout:
  4250. *lpOut = 0;
  4251. if (fAllocateMem)
  4252. {
  4253. LocalFree(lpTWC);
  4254. }
  4255. return cchLimitIn - cchLimit;
  4256. }
  4257. LWSTDAPIV_(int) wnsprintfW(
  4258. LPWSTR lpOut,
  4259. int cchLimitIn,
  4260. LPCWSTR lpFmt,
  4261. ...)
  4262. {
  4263. va_list arglist;
  4264. int ret;
  4265. va_start(arglist, lpFmt);
  4266. ret = wvnsprintfW(lpOut, cchLimitIn, lpFmt, arglist);
  4267. va_end(arglist);
  4268. return ret;
  4269. }
  4270. LWSTDAPIV_(int) wsprintfW(
  4271. LPWSTR lpOut,
  4272. LPCWSTR lpFmt,
  4273. ...)
  4274. {
  4275. // unsafe printf. arbitrary max of 0x10000 length
  4276. va_list arglist;
  4277. int ret;
  4278. va_start(arglist, lpFmt);
  4279. ret = wvnsprintfW(lpOut, 0x10000, lpFmt, arglist);
  4280. va_end(arglist);
  4281. return ret;
  4282. }
  4283. //+---------------------------------------------------------------------------
  4284. // StartDoc
  4285. //----------------------------------------------------------------------------
  4286. int StartDocWrap( HDC hDC, const DOCINFO * lpdi )
  4287. {
  4288. CStrIn strDocName( lpdi->lpszDocName );
  4289. CStrIn strOutput( lpdi->lpszOutput );
  4290. CStrIn strDatatype( lpdi->lpszDatatype );
  4291. DOCINFOA dia;
  4292. dia.cbSize = sizeof(DOCINFO);
  4293. dia.lpszDocName = strDocName;
  4294. dia.lpszOutput = strOutput;
  4295. dia.lpszDatatype = strDatatype;
  4296. dia.fwType = lpdi->fwType;
  4297. return StartDocA( hDC, &dia );
  4298. }
  4299. #endif // !WINNT
  4300. ////////////////////////////////////////////////////////////////////
  4301. //
  4302. // Plug UI support with SHLWAPI
  4303. //
  4304. typedef HRESULT (*PFNDLLGETVERSION)(DLLVERSIONINFO * pinfo);
  4305. HMODULE GetShlwapiHModule()
  4306. {
  4307. HMODULE hShlwapi = GetModuleHandle(TEXT("SHLWAPI"));
  4308. if (hShlwapi)
  4309. {
  4310. PFNDLLGETVERSION pfnDllGetVersion = (PFNDLLGETVERSION)GetProcAddress(hShlwapi, "DllGetVersion");
  4311. if (pfnDllGetVersion)
  4312. {
  4313. DLLVERSIONINFO dllinfo;
  4314. dllinfo.cbSize = sizeof(DLLVERSIONINFO);
  4315. if (pfnDllGetVersion(&dllinfo) == NOERROR)
  4316. {
  4317. if (dllinfo.dwMajorVersion < 5)
  4318. {
  4319. // This guy doesn't support ML functions
  4320. hShlwapi = NULL;
  4321. }
  4322. }
  4323. }
  4324. }
  4325. return hShlwapi;
  4326. }
  4327. // First, we need access to some helper functions:
  4328. //
  4329. #ifndef UNIX
  4330. #define SHLWAPIMLISMLHINSTANCE_ORD 429
  4331. #else
  4332. #define SHLWAPIMLISMLHINSTANCE_ORD "MLIsMLHInstance"
  4333. #endif
  4334. typedef BOOL (* PFNMLISMLHINSTANCE)(HINSTANCE);
  4335. BOOL MLIsMLHInstanceWrap(HINSTANCE hInst)
  4336. {
  4337. HMODULE hShlwapi = GetShlwapiHModule();
  4338. if (hShlwapi)
  4339. {
  4340. PFNMLISMLHINSTANCE pfn;
  4341. pfn = (PFNMLISMLHINSTANCE)GetProcAddress(hShlwapi, (LPCSTR)SHLWAPIMLISMLHINSTANCE_ORD);
  4342. if (pfn)
  4343. return pfn(hInst);
  4344. }
  4345. // BUGBUG: What if an app told comctl32 to be PlugUI and we picked
  4346. // a resource that cannot be displayed on Win9x without
  4347. // shlwapi's font linking? Seems like we need to foricbly
  4348. // load shlwapi in that case...
  4349. //
  4350. // No shlwapi? then this can't be an ML hinstance.
  4351. return FALSE;
  4352. }
  4353. #ifndef UNIX
  4354. #define SHLWAPIMLSETMLHINSTANCE_ORD 430
  4355. #else
  4356. #define SHLWAPIMLSETMLHINSTANCE_ORD "MLSetMLHInstance"
  4357. #endif
  4358. typedef HRESULT (* PFNMLSETMLHINSTANCE)(HINSTANCE, LANGID);
  4359. HRESULT MLSetMLHInstanceWrap(HINSTANCE hInst, LANGID lidUI)
  4360. {
  4361. HMODULE hShlwapi;
  4362. PFNMLSETMLHINSTANCE pfnMLSet = NULL;
  4363. hShlwapi = GetShlwapiHModule();
  4364. if (hShlwapi)
  4365. {
  4366. pfnMLSet = (PFNMLSETMLHINSTANCE)GetProcAddress(hShlwapi, (LPCSTR)SHLWAPIMLSETMLHINSTANCE_ORD);
  4367. if (pfnMLSet)
  4368. return pfnMLSet(hInst, lidUI);
  4369. }
  4370. return E_FAIL;
  4371. }
  4372. #ifndef UNIX
  4373. #define SHLWAPIMLCLEARMLHINSTANCE_ORD 431
  4374. #else
  4375. #define SHLWAPIMLCLEARMLHINSTANCE_ORD "MLClearMLHInstance"
  4376. #endif
  4377. typedef HRESULT (* PFNMLCLEARMLHINSTANCE)(HINSTANCE);
  4378. HRESULT MLClearMLHinstanceWrap(HINSTANCE hInst)
  4379. {
  4380. HMODULE hShlwapi;
  4381. PFNMLCLEARMLHINSTANCE pfnMLClear = NULL;
  4382. hShlwapi = GetShlwapiHModule();
  4383. if (hShlwapi)
  4384. {
  4385. pfnMLClear = (PFNMLCLEARMLHINSTANCE)GetProcAddress(hShlwapi, (LPCSTR)SHLWAPIMLCLEARMLHINSTANCE_ORD);
  4386. if (pfnMLClear)
  4387. return pfnMLClear(hInst);
  4388. }
  4389. return E_FAIL;
  4390. }
  4391. //
  4392. // And now, when shlwapi is around we delegate to it's ML-enabled implementations:
  4393. //
  4394. //
  4395. // Make sure we get the real USER32 versions.
  4396. //
  4397. #undef CreateDialogIndirectParamW
  4398. #ifndef UNIX
  4399. #define SHLWAPICREATEDIALOGINDIRECTPARAM_ORD 393
  4400. #else
  4401. #define SHLWAPICREATEDIALOGINDIRECTPARAM_ORD "CreateDialogIndirectParamWrapW"
  4402. #endif
  4403. typedef HWND (* PFNCREATEDIALOGINDIRECTPARAM)(HINSTANCE, LPCDLGTEMPLATE, HWND, DLGPROC, LPARAM);
  4404. HWND CreateDialogIndirectParamWrap(
  4405. HINSTANCE hInstance,
  4406. LPCDLGTEMPLATE lpTemplate,
  4407. HWND hWndParent,
  4408. DLGPROC lpDialogFunc,
  4409. LPARAM dwInitParam)
  4410. {
  4411. HMODULE hShlwapi;
  4412. PFNCREATEDIALOGINDIRECTPARAM pfnCDIP = NULL;
  4413. HWND hwndRet;
  4414. // If shlwapi is in memory, ask it to create the dialog,
  4415. // as then we get ML dialogs on downlevel platforms (if
  4416. // the hInstance is from MLLoadLibrary -- otherwise it
  4417. // thunks to the real A/W api for us).
  4418. //
  4419. hShlwapi = GetShlwapiHModule();
  4420. if (hShlwapi)
  4421. {
  4422. pfnCDIP = (PFNCREATEDIALOGINDIRECTPARAM)GetProcAddress(hShlwapi, (LPCSTR)SHLWAPICREATEDIALOGINDIRECTPARAM_ORD);
  4423. }
  4424. if (!pfnCDIP)
  4425. {
  4426. if (g_bRunOnNT)
  4427. pfnCDIP = CreateDialogIndirectParamW;
  4428. else
  4429. pfnCDIP = CreateDialogIndirectParamA;
  4430. }
  4431. // If this is from comctl32, assume it was loaded via the MUI-Language
  4432. if (HINST_THISDLL == hInstance)
  4433. MLSetMLHInstanceWrap(hInstance, GetMUILanguage());
  4434. hwndRet = pfnCDIP(hInstance, lpTemplate, hWndParent, lpDialogFunc, dwInitParam);
  4435. if (HINST_THISDLL == hInstance)
  4436. MLClearMLHinstanceWrap(hInstance);
  4437. return(hwndRet);
  4438. }
  4439. //
  4440. // Make sure we get the real USER32 versions.
  4441. //
  4442. #undef DialogBoxIndirectParamW
  4443. #ifndef UNIX
  4444. #define SHLWAPIDIALOGBOXINDIRECTPARAM_ORD 58
  4445. #else
  4446. #define SHLWAPIDIALOGBOXINDIRECTPARAM_ORD "DialogBoxIndirectParamWrapW"
  4447. #endif
  4448. typedef INT_PTR (* PFNDIALOGBOXINDIRECTPARAM)(HINSTANCE, LPCDLGTEMPLATE, HWND, DLGPROC, LPARAM);
  4449. INT_PTR DialogBoxIndirectParamWrap(
  4450. HINSTANCE hInstance,
  4451. LPCDLGTEMPLATEW hDialogTemplate,
  4452. HWND hWndParent,
  4453. DLGPROC lpDialogFunc,
  4454. LPARAM dwInitParam)
  4455. {
  4456. HMODULE hShlwapi;
  4457. INT_PTR iRet;
  4458. PFNDIALOGBOXINDIRECTPARAM pfnDBIP = NULL;
  4459. // If shlwapi is in memory, ask it to create the dialog,
  4460. // as then we get ML dialogs on downlevel platforms (if
  4461. // the hInstance is from MLLoadLibrary -- otherwise it
  4462. // thunks to the real A/W api for us).
  4463. //
  4464. hShlwapi = GetShlwapiHModule();
  4465. if (hShlwapi)
  4466. pfnDBIP = (PFNDIALOGBOXINDIRECTPARAM)GetProcAddress(hShlwapi, (LPCSTR)SHLWAPIDIALOGBOXINDIRECTPARAM_ORD);
  4467. if (!pfnDBIP)
  4468. {
  4469. if (g_bRunOnNT)
  4470. pfnDBIP = DialogBoxIndirectParamW;
  4471. else
  4472. pfnDBIP = DialogBoxIndirectParamA;
  4473. }
  4474. // If this is from comctl32, assume it was loaded via the MUI-Language
  4475. if (HINST_THISDLL == hInstance)
  4476. MLSetMLHInstanceWrap(hInstance, GetMUILanguage());
  4477. iRet = pfnDBIP(hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam);
  4478. if (HINST_THISDLL == hInstance)
  4479. MLClearMLHinstanceWrap(hInstance);
  4480. return iRet;
  4481. }
  4482. #endif // UNICODE