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.

3988 lines
142 KiB

  1. /*++
  2. Copyright (c) 1991-2000, Microsoft Corporation All rights reserved.
  3. Module Name:
  4. mbcs.c
  5. Abstract:
  6. This file contains functions that convert multibyte character strings
  7. to wide character strings, convert wide character strings to multibyte
  8. character strings, convert a multibyte character string from one code
  9. page to a multibyte character string of another code page, and get the
  10. DBCS leadbyte ranges for a given code page.
  11. APIs found in this file:
  12. IsValidCodePage
  13. GetACP
  14. GetOEMCP
  15. GetCPInfo
  16. GetCPInfoExW
  17. IsDBCSLeadByte
  18. IsDBCSLeadByteEx
  19. MultiByteToWideChar
  20. WideCharToMultiByte
  21. Revision History:
  22. 05-31-91 JulieB Created.
  23. --*/
  24. //
  25. // Include Files.
  26. //
  27. #include "nls.h"
  28. //
  29. // Forward Declarations.
  30. //
  31. int
  32. GetWCCompSB(
  33. PMB_TABLE pMBTbl,
  34. LPBYTE pMBStr,
  35. LPWSTR pWCStr,
  36. LPWSTR pEndWCStr);
  37. int
  38. GetWCCompMB(
  39. PCP_HASH pHashN,
  40. PMB_TABLE pMBTbl,
  41. LPBYTE pMBStr,
  42. LPBYTE pEndMBStr,
  43. LPWSTR pWCStr,
  44. LPWSTR pEndWCStr,
  45. int *pmbIncr);
  46. int
  47. GetWCCompSBErr(
  48. PCP_HASH pHashN,
  49. PMB_TABLE pMBTbl,
  50. LPBYTE pMBStr,
  51. LPWSTR pWCStr,
  52. LPWSTR pEndWCStr);
  53. int
  54. GetWCCompMBErr(
  55. PCP_HASH pHashN,
  56. PMB_TABLE pMBTbl,
  57. LPBYTE pMBStr,
  58. LPBYTE pEndMBStr,
  59. LPWSTR pWCStr,
  60. LPWSTR pEndWCStr,
  61. int *pmbIncr);
  62. int
  63. GetMBNoDefault(
  64. PCP_HASH pHashN,
  65. LPWSTR pWCStr,
  66. LPWSTR pEndWCStr,
  67. LPBYTE pMBStr,
  68. int cbMultiByte,
  69. DWORD dwFlags);
  70. int
  71. GetMBDefault(
  72. PCP_HASH pHashN,
  73. LPWSTR pWCStr,
  74. LPWSTR pEndWCStr,
  75. LPBYTE pMBStr,
  76. int cbMultiByte,
  77. WORD wDefault,
  78. LPBOOL pUsedDef,
  79. DWORD dwFlags);
  80. int
  81. GetMBDefaultComp(
  82. PCP_HASH pHashN,
  83. LPWSTR pWCStr,
  84. LPWSTR pEndWCStr,
  85. LPBYTE pMBStr,
  86. int cbMultiByte,
  87. WORD wDefault,
  88. LPBOOL pUsedDef,
  89. DWORD dwFlags);
  90. int
  91. GetMBCompSB(
  92. PCP_HASH pHashN,
  93. DWORD dwFlags,
  94. LPWSTR pWCStr,
  95. LPBYTE pMBStr,
  96. int mbCount,
  97. WORD wDefault,
  98. LPBOOL pUsedDef);
  99. int
  100. GetMBCompMB(
  101. PCP_HASH pHashN,
  102. DWORD dwFlags,
  103. LPWSTR pWCStr,
  104. LPBYTE pMBStr,
  105. int mbCount,
  106. WORD wDefault,
  107. LPBOOL pUsedDef,
  108. BOOL *fError,
  109. BOOL fOnlyOne);
  110. UINT
  111. GetMacCodePage(void);
  112. //-------------------------------------------------------------------------//
  113. // INTERNAL MACROS //
  114. //-------------------------------------------------------------------------//
  115. ////////////////////////////////////////////////////////////////////////////
  116. //
  117. // CHECK_DBCS_LEAD_BYTE
  118. //
  119. // Returns the offset to the DBCS table for the given leadbyte character.
  120. // If the given character is not a leadbyte, then it returns zero (table
  121. // value).
  122. //
  123. // DEFINED AS A MACRO.
  124. //
  125. // 05-31-91 JulieB Created.
  126. ////////////////////////////////////////////////////////////////////////////
  127. #define CHECK_DBCS_LEAD_BYTE(pDBCSOff, Ch) \
  128. (pDBCSOff ? ((WORD)(pDBCSOff[Ch])) : ((WORD)0))
  129. ////////////////////////////////////////////////////////////////////////////
  130. //
  131. // CHECK_ERROR_WC_SINGLE
  132. //
  133. // Checks to see if the default character was used due to an invalid
  134. // character. Sets last error and returns 0 characters written if an
  135. // invalid character was used.
  136. //
  137. // NOTE: This macro may return if an error is encountered.
  138. //
  139. // DEFINED AS A MACRO.
  140. //
  141. // 05-31-91 JulieB Created.
  142. ////////////////////////////////////////////////////////////////////////////
  143. #define CHECK_ERROR_WC_SINGLE( pHashN, \
  144. wch, \
  145. Ch ) \
  146. { \
  147. if ( ( (wch == pHashN->pCPInfo->wUniDefaultChar) && \
  148. (Ch != pHashN->pCPInfo->wTransUniDefaultChar) ) || \
  149. ( (wch >= PRIVATE_USE_BEGIN) && (wch <= PRIVATE_USE_END) ) ) \
  150. { \
  151. SetLastError(ERROR_NO_UNICODE_TRANSLATION); \
  152. return (0); \
  153. } \
  154. }
  155. ////////////////////////////////////////////////////////////////////////////
  156. //
  157. // CHECK_ERROR_WC_MULTI
  158. //
  159. // Checks to see if the default character was used due to an invalid
  160. // character. Sets last error and returns 0 characters written if an
  161. // invalid character was used.
  162. //
  163. // NOTE: This macro may return if an error is encountered.
  164. //
  165. // DEFINED AS A MACRO.
  166. //
  167. // 05-31-91 JulieB Created.
  168. ////////////////////////////////////////////////////////////////////////////
  169. #define CHECK_ERROR_WC_MULTI( pHashN, \
  170. wch, \
  171. lead, \
  172. trail ) \
  173. { \
  174. if ((wch == pHashN->pCPInfo->wUniDefaultChar) && \
  175. (MAKEWORD(trail, lead) != pHashN->pCPInfo->wTransUniDefaultChar)) \
  176. { \
  177. SetLastError(ERROR_NO_UNICODE_TRANSLATION); \
  178. return (0); \
  179. } \
  180. }
  181. ////////////////////////////////////////////////////////////////////////////
  182. //
  183. // CHECK_ERROR_WC_MULTI_SPECIAL
  184. //
  185. // Checks to see if the default character was used due to an invalid
  186. // character. Sets it to 0xffff if invalid.
  187. //
  188. // DEFINED AS A MACRO.
  189. //
  190. // 08-21-95 JulieB Created.
  191. ////////////////////////////////////////////////////////////////////////////
  192. #define CHECK_ERROR_WC_MULTI_SPECIAL( pHashN, \
  193. pWCStr, \
  194. lead, \
  195. trail ) \
  196. { \
  197. if ((*pWCStr == pHashN->pCPInfo->wUniDefaultChar) && \
  198. (MAKEWORD(trail, lead) != pHashN->pCPInfo->wTransUniDefaultChar)) \
  199. { \
  200. *pWCStr = 0xffff; \
  201. } \
  202. }
  203. ////////////////////////////////////////////////////////////////////////////
  204. //
  205. // GET_WC_SINGLE
  206. //
  207. // Fills in pWCStr with the wide character(s) for the corresponding single
  208. // byte character from the appropriate translation table.
  209. //
  210. // DEFINED AS A MACRO.
  211. //
  212. // 05-31-91 JulieB Created.
  213. ////////////////////////////////////////////////////////////////////////////
  214. #define GET_WC_SINGLE( pMBTbl, \
  215. pMBStr, \
  216. pWCStr ) \
  217. { \
  218. *pWCStr = pMBTbl[*pMBStr]; \
  219. }
  220. ////////////////////////////////////////////////////////////////////////////
  221. //
  222. // GET_WC_SINGLE_SPECIAL
  223. //
  224. // Fills in pWCStr with the wide character(s) for the corresponding single
  225. // byte character from the appropriate translation table. Also checks for
  226. // invalid characters - if invalid, it fills in 0xffff instead.
  227. //
  228. // DEFINED AS A MACRO.
  229. //
  230. // 08-21-95 JulieB Created.
  231. ////////////////////////////////////////////////////////////////////////////
  232. #define GET_WC_SINGLE_SPECIAL( pHashN, \
  233. pMBTbl, \
  234. pMBStr, \
  235. pWCStr ) \
  236. { \
  237. *pWCStr = pMBTbl[*pMBStr]; \
  238. \
  239. if ( ( (*pWCStr == pHashN->pCPInfo->wUniDefaultChar) && \
  240. (*pMBStr != pHashN->pCPInfo->wTransUniDefaultChar) ) || \
  241. ( (*pWCStr >= PRIVATE_USE_BEGIN) && \
  242. (*pWCStr <= PRIVATE_USE_END) ) ) \
  243. { \
  244. *pWCStr = 0xffff; \
  245. } \
  246. }
  247. ////////////////////////////////////////////////////////////////////////////
  248. //
  249. // GET_WC_MULTI
  250. //
  251. // Fills in pWCStr with the wide character(s) for the corresponding multibyte
  252. // character from the appropriate translation table. The number of bytes
  253. // used from the pMBStr buffer (single byte or double byte) is stored in
  254. // the mbIncr parameter.
  255. //
  256. // DEFINED AS A MACRO.
  257. //
  258. // 05-31-91 JulieB Created.
  259. ////////////////////////////////////////////////////////////////////////////
  260. #define GET_WC_MULTI( pHashN, \
  261. pMBTbl, \
  262. pMBStr, \
  263. pEndMBStr, \
  264. pWCStr, \
  265. pEndWCStr, \
  266. mbIncr ) \
  267. { \
  268. WORD Offset; /* offset to DBCS table for range */ \
  269. \
  270. \
  271. if (Offset = CHECK_DBCS_LEAD_BYTE(pHashN->pDBCSOffsets, *pMBStr)) \
  272. { \
  273. /* \
  274. * DBCS Lead Byte. Make sure there is a trail byte with the \
  275. * lead byte. \
  276. */ \
  277. if (pMBStr + 1 == pEndMBStr) \
  278. { \
  279. /* \
  280. * There is no trail byte with the lead byte. The lead byte \
  281. * is the LAST character in the string. Translate to NULL. \
  282. */ \
  283. *pWCStr = (WCHAR)0; \
  284. mbIncr = 1; \
  285. } \
  286. else if (*(pMBStr + 1) == 0) \
  287. { \
  288. /* \
  289. * There is no trail byte with the lead byte. The lead byte \
  290. * is followed by a NULL. Translate to NULL. \
  291. * \
  292. * Increment by 2 so that the null is not counted twice. \
  293. */ \
  294. *pWCStr = (WCHAR)0; \
  295. mbIncr = 2; \
  296. } \
  297. else \
  298. { \
  299. /* \
  300. * Fill in the wide character translation from the double \
  301. * byte character table. \
  302. */ \
  303. *pWCStr = (pHashN->pDBCSOffsets + Offset)[*(pMBStr + 1)]; \
  304. mbIncr = 2; \
  305. } \
  306. } \
  307. else \
  308. { \
  309. /* \
  310. * Not DBCS Lead Byte. Fill in the wide character translation \
  311. * from the single byte character table. \
  312. */ \
  313. *pWCStr = pMBTbl[*pMBStr]; \
  314. mbIncr = 1; \
  315. } \
  316. }
  317. ////////////////////////////////////////////////////////////////////////////
  318. //
  319. // GET_WC_MULTI_ERR
  320. //
  321. // Fills in pWCStr with the wide character(s) for the corresponding multibyte
  322. // character from the appropriate translation table. The number of bytes
  323. // used from the pMBStr buffer (single byte or double byte) is stored in
  324. // the mbIncr parameter.
  325. //
  326. // Once the character has been translated, it checks to be sure the
  327. // character was valid. If not, it sets last error and return 0 characters
  328. // written.
  329. //
  330. // NOTE: This macro may return if an error is encountered.
  331. //
  332. // DEFINED AS A MACRO.
  333. //
  334. // 09-01-93 JulieB Created.
  335. ////////////////////////////////////////////////////////////////////////////
  336. #define GET_WC_MULTI_ERR( pHashN, \
  337. pMBTbl, \
  338. pMBStr, \
  339. pEndMBStr, \
  340. pWCStr, \
  341. pEndWCStr, \
  342. mbIncr ) \
  343. { \
  344. WORD Offset; /* offset to DBCS table for range */ \
  345. \
  346. \
  347. if (Offset = CHECK_DBCS_LEAD_BYTE(pHashN->pDBCSOffsets, *pMBStr)) \
  348. { \
  349. /* \
  350. * DBCS Lead Byte. Make sure there is a trail byte with the \
  351. * lead byte. \
  352. */ \
  353. if ((pMBStr + 1 == pEndMBStr) || (*(pMBStr + 1) == 0)) \
  354. { \
  355. /* \
  356. * There is no trail byte with the lead byte. Return error. \
  357. */ \
  358. SetLastError(ERROR_NO_UNICODE_TRANSLATION); \
  359. return (0); \
  360. } \
  361. \
  362. /* \
  363. * Fill in the wide character translation from the double \
  364. * byte character table. \
  365. */ \
  366. *pWCStr = (pHashN->pDBCSOffsets + Offset)[*(pMBStr + 1)]; \
  367. mbIncr = 2; \
  368. \
  369. /* \
  370. * Make sure an invalid character was not translated to \
  371. * the default char. Return an error if invalid. \
  372. */ \
  373. CHECK_ERROR_WC_MULTI( pHashN, \
  374. *pWCStr, \
  375. *pMBStr, \
  376. *(pMBStr + 1) ); \
  377. } \
  378. else \
  379. { \
  380. /* \
  381. * Not DBCS Lead Byte. Fill in the wide character translation \
  382. * from the single byte character table. \
  383. */ \
  384. *pWCStr = pMBTbl[*pMBStr]; \
  385. mbIncr = 1; \
  386. \
  387. /* \
  388. * Make sure an invalid character was not translated to \
  389. * the default char. Return an error if invalid. \
  390. */ \
  391. CHECK_ERROR_WC_SINGLE( pHashN, \
  392. *pWCStr, \
  393. *pMBStr ); \
  394. } \
  395. }
  396. ////////////////////////////////////////////////////////////////////////////
  397. //
  398. // GET_WC_MULTI_ERR_SPECIAL
  399. //
  400. // Fills in pWCStr with the wide character(s) for the corresponding multibyte
  401. // character from the appropriate translation table. The number of bytes
  402. // used from the pMBStr buffer (single byte or double byte) is stored in
  403. // the mbIncr parameter.
  404. //
  405. // Once the character has been translated, it checks to be sure the
  406. // character was valid. If not, it fills in 0xffff.
  407. //
  408. // DEFINED AS A MACRO.
  409. //
  410. // 08-21-95 JulieB Created.
  411. ////////////////////////////////////////////////////////////////////////////
  412. #define GET_WC_MULTI_ERR_SPECIAL( pHashN, \
  413. pMBTbl, \
  414. pMBStr, \
  415. pEndMBStr, \
  416. pWCStr, \
  417. pEndWCStr, \
  418. mbIncr ) \
  419. { \
  420. WORD Offset; /* offset to DBCS table for range */ \
  421. \
  422. \
  423. if (Offset = CHECK_DBCS_LEAD_BYTE(pHashN->pDBCSOffsets, *pMBStr)) \
  424. { \
  425. /* \
  426. * DBCS Lead Byte. Make sure there is a trail byte with the \
  427. * lead byte. \
  428. */ \
  429. if ((pMBStr + 1 == pEndMBStr) || (*(pMBStr + 1) == 0)) \
  430. { \
  431. /* \
  432. * There is no trail byte with the lead byte. The lead byte \
  433. * is the LAST character in the string. Translate to 0xffff. \
  434. */ \
  435. *pWCStr = (WCHAR)0xffff; \
  436. mbIncr = 1; \
  437. } \
  438. else \
  439. { \
  440. /* \
  441. * Fill in the wide character translation from the double \
  442. * byte character table. \
  443. */ \
  444. *pWCStr = (pHashN->pDBCSOffsets + Offset)[*(pMBStr + 1)]; \
  445. mbIncr = 2; \
  446. \
  447. /* \
  448. * Make sure an invalid character was not translated to \
  449. * the default char. Translate to 0xffff if invalid. \
  450. */ \
  451. CHECK_ERROR_WC_MULTI_SPECIAL( pHashN, \
  452. pWCStr, \
  453. *pMBStr, \
  454. *(pMBStr + 1) ); \
  455. } \
  456. } \
  457. else \
  458. { \
  459. /* \
  460. * Not DBCS Lead Byte. Fill in the wide character translation \
  461. * from the single byte character table. \
  462. * Make sure an invalid character was not translated to \
  463. * the default char. Return an error if invalid. \
  464. */ \
  465. GET_WC_SINGLE_SPECIAL( pHashN, \
  466. pMBTbl, \
  467. pMBStr, \
  468. pWCStr ); \
  469. mbIncr = 1; \
  470. } \
  471. }
  472. ////////////////////////////////////////////////////////////////////////////
  473. //
  474. // COPY_MB_CHAR
  475. //
  476. // Copies a multibyte character to the given string buffer. If the
  477. // high byte of the multibyte word is zero, then it is a single byte
  478. // character and the number of characters written (returned) is 1.
  479. // Otherwise, it is a double byte character and the number of characters
  480. // written (returned) is 2.
  481. //
  482. // NumByte will be 0 if the buffer is too small for the translation.
  483. //
  484. // DEFINED AS A MACRO.
  485. //
  486. // 05-31-91 JulieB Created.
  487. ////////////////////////////////////////////////////////////////////////////
  488. #define COPY_MB_CHAR( mbChar, \
  489. pMBStr, \
  490. NumByte, \
  491. fOnlyOne ) \
  492. { \
  493. if (HIBYTE(mbChar)) \
  494. { \
  495. /* \
  496. * Make sure there is enough room in the buffer for both bytes. \
  497. */ \
  498. if (fOnlyOne) \
  499. { \
  500. NumByte = 0; \
  501. } \
  502. else \
  503. { \
  504. /* \
  505. * High Byte is NOT zero, so it's a DOUBLE byte char. \
  506. * Return 2 characters written. \
  507. */ \
  508. *pMBStr = HIBYTE(mbChar); \
  509. *(pMBStr + 1) = LOBYTE(mbChar); \
  510. NumByte = 2; \
  511. } \
  512. } \
  513. else \
  514. { \
  515. /* \
  516. * High Byte IS zero, so it's a SINGLE byte char. \
  517. * Return 1 character written. \
  518. */ \
  519. *pMBStr = LOBYTE(mbChar); \
  520. NumByte = 1; \
  521. } \
  522. }
  523. ////////////////////////////////////////////////////////////////////////////
  524. //
  525. // GET_SB
  526. //
  527. // Fills in pMBStr with the single byte character for the corresponding
  528. // wide character from the appropriate translation table.
  529. //
  530. // DEFINED AS A MACRO.
  531. //
  532. // 05-31-91 JulieB Created.
  533. ////////////////////////////////////////////////////////////////////////////
  534. #define GET_SB( pWC, \
  535. wChar, \
  536. pMBStr ) \
  537. { \
  538. *pMBStr = ((BYTE *)(pWC))[wChar]; \
  539. }
  540. ////////////////////////////////////////////////////////////////////////////
  541. //
  542. // GET_MB
  543. //
  544. // Fills in pMBStr with the multi byte character for the corresponding
  545. // wide character from the appropriate translation table.
  546. //
  547. // mbCount will be 0 if the buffer is too small for the translation.
  548. //
  549. // Broken Down Version:
  550. // --------------------
  551. // mbChar = ((WORD *)(pHashN->pWC))[wChar];
  552. // COPY_MB_CHAR(mbChar, pMBStr, mbCount);
  553. //
  554. // DEFINED AS A MACRO.
  555. //
  556. // 05-31-91 JulieB Created.
  557. ////////////////////////////////////////////////////////////////////////////
  558. #define GET_MB( pWC, \
  559. wChar, \
  560. pMBStr, \
  561. mbCount, \
  562. fOnlyOne ) \
  563. { \
  564. COPY_MB_CHAR( ((WORD *)(pWC))[wChar], \
  565. pMBStr, \
  566. mbCount, \
  567. fOnlyOne ); \
  568. }
  569. ////////////////////////////////////////////////////////////////////////////
  570. //
  571. // ELIMINATE_BEST_FIT_SB
  572. //
  573. // Checks to see if a single byte Best Fit character was used. If so,
  574. // it replaces it with a single byte default character.
  575. //
  576. // DEFINED AS A MACRO.
  577. //
  578. // 05-31-91 JulieB Created.
  579. ////////////////////////////////////////////////////////////////////////////
  580. #define ELIMINATE_BEST_FIT_SB( pHashN, \
  581. wChar, \
  582. pMBStr ) \
  583. { \
  584. if ((pHashN->pMBTbl)[*pMBStr] != wChar) \
  585. { \
  586. *pMBStr = LOBYTE(pHashN->pCPInfo->wDefaultChar); \
  587. } \
  588. }
  589. ////////////////////////////////////////////////////////////////////////////
  590. //
  591. // ELIMINATE_BEST_FIT_MB
  592. //
  593. // Checks to see if a multi byte Best Fit character was used. If so,
  594. // it replaces it with a multi byte default character.
  595. //
  596. // DEFINED AS A MACRO.
  597. //
  598. // 05-31-91 JulieB Created.
  599. ////////////////////////////////////////////////////////////////////////////
  600. #define ELIMINATE_BEST_FIT_MB( pHashN, \
  601. wChar, \
  602. pMBStr, \
  603. mbCount, \
  604. fOnlyOne ) \
  605. { \
  606. WORD Offset; \
  607. WORD wDefault; \
  608. \
  609. if (((mbCount == 1) && ((pHashN->pMBTbl)[*pMBStr] != wChar)) || \
  610. ((mbCount == 2) && \
  611. (Offset = CHECK_DBCS_LEAD_BYTE(pHashN->pDBCSOffsets, *pMBStr)) && \
  612. (((pHashN->pDBCSOffsets + Offset)[*(pMBStr + 1)]) != wChar))) \
  613. { \
  614. wDefault = pHashN->pCPInfo->wDefaultChar; \
  615. if (HIBYTE(wDefault)) \
  616. { \
  617. if (fOnlyOne) \
  618. { \
  619. mbCount = 0; \
  620. } \
  621. else \
  622. { \
  623. *pMBStr = HIBYTE(wDefault); \
  624. *(pMBStr + 1) = LOBYTE(wDefault); \
  625. mbCount = 2; \
  626. } \
  627. } \
  628. else \
  629. { \
  630. *pMBStr = LOBYTE(wDefault); \
  631. mbCount = 1; \
  632. } \
  633. } \
  634. }
  635. ////////////////////////////////////////////////////////////////////////////
  636. //
  637. // GET_DEFAULT_WORD
  638. //
  639. // Takes a pointer to a character string (either one or two characters),
  640. // and converts it to a WORD value. If the character is not DBCS, then it
  641. // zero extends the high byte.
  642. //
  643. // DEFINED AS A MACRO.
  644. //
  645. // 05-31-91 JulieB Created.
  646. ////////////////////////////////////////////////////////////////////////////
  647. #define GET_DEFAULT_WORD(pOff, pDefault) \
  648. (CHECK_DBCS_LEAD_BYTE(pOff, *pDefault) \
  649. ? MAKEWORD(*(pDefault + 1), *pDefault) \
  650. : MAKEWORD(*pDefault, 0))
  651. ////////////////////////////////////////////////////////////////////////////
  652. //
  653. // DEFAULT_CHAR_CHECK_SB
  654. //
  655. // Checks to see if the default character is used. If it is, it sets
  656. // pUsedDef to TRUE (if non-null). If the user specified a default, then
  657. // the user's default character is used.
  658. //
  659. // DEFINED AS A MACRO.
  660. //
  661. // 05-31-91 JulieB Created.
  662. ////////////////////////////////////////////////////////////////////////////
  663. #define DEFAULT_CHAR_CHECK_SB( pHashN, \
  664. wch, \
  665. pMBStr, \
  666. wDefChar, \
  667. pUsedDef ) \
  668. { \
  669. WORD wSysDefChar = pHashN->pCPInfo->wDefaultChar; \
  670. \
  671. \
  672. /* \
  673. * Check for default character being used. \
  674. */ \
  675. if ((*pMBStr == (BYTE)wSysDefChar) && \
  676. (wch != pHashN->pCPInfo->wTransDefaultChar)) \
  677. { \
  678. /* \
  679. * Default was used. Set the pUsedDef parameter to TRUE. \
  680. */ \
  681. *pUsedDef = TRUE; \
  682. \
  683. /* \
  684. * If the user specified a different default character than \
  685. * the system default, use that character instead. \
  686. */ \
  687. if (wSysDefChar != wDefChar) \
  688. { \
  689. *pMBStr = LOBYTE(wDefChar); \
  690. } \
  691. } \
  692. }
  693. ////////////////////////////////////////////////////////////////////////////
  694. //
  695. // DEFAULT_CHAR_CHECK_MB
  696. //
  697. // Checks to see if the default character is used. If it is, it sets
  698. // pUsedDef to TRUE (if non-null). If the user specified a default, then
  699. // the user's default character is used. The number of bytes written to
  700. // the buffer is returned.
  701. //
  702. // NumByte will be -1 if the buffer is too small for the translation.
  703. //
  704. // DEFINED AS A MACRO.
  705. //
  706. // 05-31-91 JulieB Created.
  707. ////////////////////////////////////////////////////////////////////////////
  708. #define DEFAULT_CHAR_CHECK_MB( pHashN, \
  709. wch, \
  710. pMBStr, \
  711. wDefChar, \
  712. pUsedDef, \
  713. NumByte, \
  714. fOnlyOne ) \
  715. { \
  716. WORD wSysDefChar = pHashN->pCPInfo->wDefaultChar; \
  717. \
  718. \
  719. /* \
  720. * Set NumByte to zero for return (zero bytes written). \
  721. */ \
  722. NumByte = 0; \
  723. \
  724. /* \
  725. * Check for default character being used. \
  726. */ \
  727. if ((*pMBStr == (BYTE)wSysDefChar) && \
  728. (wch != pHashN->pCPInfo->wTransDefaultChar)) \
  729. { \
  730. /* \
  731. * Default was used. Set the pUsedDef parameter to TRUE. \
  732. */ \
  733. *pUsedDef = TRUE; \
  734. \
  735. /* \
  736. * If the user specified a different default character than \
  737. * the system default, use that character instead. \
  738. */ \
  739. if (wSysDefChar != wDefChar) \
  740. { \
  741. COPY_MB_CHAR( wDefChar, \
  742. pMBStr, \
  743. NumByte, \
  744. fOnlyOne ); \
  745. if (NumByte == 0) \
  746. { \
  747. NumByte = -1; \
  748. } \
  749. } \
  750. } \
  751. }
  752. ////////////////////////////////////////////////////////////////////////////
  753. //
  754. // GET_WC_TRANSLATION_SB
  755. //
  756. // Gets the 1:1 translation of a given wide character. It fills in the
  757. // string pointer with the single byte character.
  758. //
  759. // DEFINED AS A MACRO.
  760. //
  761. // 05-31-91 JulieB Created.
  762. ////////////////////////////////////////////////////////////////////////////
  763. #define GET_WC_TRANSLATION_SB( pHashN, \
  764. wch, \
  765. pMBStr, \
  766. wDefault, \
  767. pUsedDef, \
  768. dwFlags ) \
  769. { \
  770. GET_SB( pHashN->pWC, \
  771. wch, \
  772. pMBStr ); \
  773. if (dwFlags & WC_NO_BEST_FIT_CHARS) \
  774. { \
  775. ELIMINATE_BEST_FIT_SB( pHashN, \
  776. wch, \
  777. pMBStr ); \
  778. } \
  779. DEFAULT_CHAR_CHECK_SB( pHashN, \
  780. wch, \
  781. pMBStr, \
  782. wDefault, \
  783. pUsedDef ); \
  784. }
  785. ////////////////////////////////////////////////////////////////////////////
  786. //
  787. // GET_WC_TRANSLATION_MB
  788. //
  789. // Gets the 1:1 translation of a given wide character. It fills in the
  790. // appropriate number of characters for the multibyte character and then
  791. // returns the number of characters written to the multibyte string.
  792. //
  793. // mbCnt will be 0 if the buffer is too small for the translation.
  794. //
  795. // DEFINED AS A MACRO.
  796. //
  797. // 05-31-91 JulieB Created.
  798. ////////////////////////////////////////////////////////////////////////////
  799. #define GET_WC_TRANSLATION_MB( pHashN, \
  800. wch, \
  801. pMBStr, \
  802. wDefault, \
  803. pUsedDef, \
  804. mbCnt, \
  805. fOnlyOne, \
  806. dwFlags ) \
  807. { \
  808. int mbCnt2; /* number of characters written */ \
  809. \
  810. \
  811. GET_MB( pHashN->pWC, \
  812. wch, \
  813. pMBStr, \
  814. mbCnt, \
  815. fOnlyOne ); \
  816. if (dwFlags & WC_NO_BEST_FIT_CHARS) \
  817. { \
  818. ELIMINATE_BEST_FIT_MB( pHashN, \
  819. wch, \
  820. pMBStr, \
  821. mbCnt, \
  822. fOnlyOne ); \
  823. } \
  824. if (mbCnt) \
  825. { \
  826. DEFAULT_CHAR_CHECK_MB( pHashN, \
  827. wch, \
  828. pMBStr, \
  829. wDefault, \
  830. pUsedDef, \
  831. mbCnt2, \
  832. fOnlyOne ); \
  833. if (mbCnt2 == -1) \
  834. { \
  835. mbCnt = 0; \
  836. } \
  837. else if (mbCnt2) \
  838. { \
  839. mbCnt = mbCnt2; \
  840. } \
  841. } \
  842. }
  843. ////////////////////////////////////////////////////////////////////////////
  844. //
  845. // GET_CP_HASH_NODE
  846. //
  847. // Sets the code page value (if a special value is passed in) and the
  848. // hash node pointer. If the code page value is invalid, the pointer
  849. // to the hash node will be set to NULL.
  850. //
  851. // DEFINED AS A MACRO.
  852. //
  853. // 05-31-91 JulieB Created.
  854. ////////////////////////////////////////////////////////////////////////////
  855. #define GET_CP_HASH_NODE( CodePage, \
  856. pHashN ) \
  857. { \
  858. PLOC_HASH pHashLoc; \
  859. \
  860. \
  861. /* \
  862. * Check for the ACP, OEMCP, or MACCP. Fill in the appropriate \
  863. * value for the code page if one of these values is given. \
  864. * Otherwise, just get the hash node for the given code page. \
  865. */ \
  866. if (CodePage == gAnsiCodePage) \
  867. { \
  868. pHashN = gpACPHashN; \
  869. } \
  870. else if (CodePage == gOemCodePage) \
  871. { \
  872. pHashN = gpOEMCPHashN; \
  873. } \
  874. else if (CodePage == CP_ACP) \
  875. { \
  876. CodePage = gAnsiCodePage; \
  877. pHashN = gpACPHashN; \
  878. } \
  879. else if (CodePage == CP_OEMCP) \
  880. { \
  881. CodePage = gOemCodePage; \
  882. pHashN = gpOEMCPHashN; \
  883. } \
  884. else if (CodePage == CP_SYMBOL) \
  885. { \
  886. pHashN = NULL; \
  887. } \
  888. else if (CodePage == CP_MACCP) \
  889. { \
  890. CodePage = GetMacCodePage(); \
  891. pHashN = gpMACCPHashN; \
  892. } \
  893. else if (CodePage == CP_THREAD_ACP) \
  894. { \
  895. VALIDATE_LOCALE(NtCurrentTeb()->CurrentLocale, pHashLoc, FALSE); \
  896. if (pHashLoc != NULL) \
  897. { \
  898. CodePage = pHashLoc->pLocaleFixed->DefaultACP; \
  899. } \
  900. if (CodePage == CP_ACP) \
  901. { \
  902. CodePage = gAnsiCodePage; \
  903. pHashN = gpACPHashN; \
  904. } \
  905. else if (CodePage == CP_OEMCP) \
  906. { \
  907. CodePage = gOemCodePage; \
  908. pHashN = gpOEMCPHashN; \
  909. } \
  910. else if (CodePage == CP_MACCP) \
  911. { \
  912. CodePage = GetMacCodePage(); \
  913. pHashN = gpMACCPHashN; \
  914. } \
  915. else \
  916. { \
  917. pHashN = GetCPHashNode(CodePage); \
  918. } \
  919. } \
  920. else \
  921. { \
  922. pHashN = GetCPHashNode(CodePage); \
  923. } \
  924. }
  925. //-------------------------------------------------------------------------//
  926. // API ROUTINES //
  927. //-------------------------------------------------------------------------//
  928. ////////////////////////////////////////////////////////////////////////////
  929. //
  930. // IsValidCodePage
  931. //
  932. // Checks that the given code page is a valid one. It does so by querying
  933. // the registry. If the code page is found, then TRUE is returned.
  934. // Otherwise, FALSE is returned.
  935. //
  936. // 05-31-1991 JulieB Created.
  937. // 05-31-2002 ShawnSte Make it not force the loading of the code page
  938. ////////////////////////////////////////////////////////////////////////////
  939. BOOL WINAPI IsValidCodePage(
  940. UINT CodePage)
  941. {
  942. //
  943. // Do not allow special code page values to be valid here.
  944. // (CP_ACP, CP_OEMCP, CP_MACCP, CP_THREAD_ACP, CP_SYMBOL are invalid)
  945. //
  946. //
  947. // Do the quick check for the code page value equal to either
  948. // the Ansi code page value or the OEM code page value.
  949. //
  950. if ((CodePage == gAnsiCodePage) || (CodePage == gOemCodePage) ||
  951. (CodePage == CP_UTF7) || (CodePage == CP_UTF8))
  952. {
  953. //
  954. // Return success.
  955. //
  956. return (TRUE);
  957. }
  958. //
  959. // Check for other code page values.
  960. //
  961. // If a node already exists, then we're OK
  962. if (IsCPHashNodeLoaded(CodePage) == TRUE)
  963. {
  964. //
  965. // Return success.
  966. //
  967. return (TRUE);
  968. }
  969. //
  970. // Hash node doesn't exist. Have to look in the registry.
  971. // True if this works, false if it doesn't
  972. //
  973. return GetCPFileNameFromRegistry(CodePage, NULL, 0);
  974. }
  975. ////////////////////////////////////////////////////////////////////////////
  976. //
  977. // GetACP
  978. //
  979. // Returns the ANSI code page for the system. If the registry value is
  980. // not readable, then the chosen default ACP is used (NLS_DEFAULT_ACP).
  981. //
  982. // 05-31-91 JulieB Created.
  983. ////////////////////////////////////////////////////////////////////////////
  984. UINT WINAPI GetACP()
  985. {
  986. //
  987. // Return the ACP stored in the cache.
  988. //
  989. return (gAnsiCodePage);
  990. }
  991. ////////////////////////////////////////////////////////////////////////////
  992. //
  993. // SetCPGlobal
  994. //
  995. // Sets the code page global, used by Setup to force the code page into
  996. // the correct value during GUI mode.
  997. //
  998. // 02-15-99 JimSchm Created.
  999. ////////////////////////////////////////////////////////////////////////////
  1000. UINT
  1001. WINAPI
  1002. SetCPGlobal (
  1003. IN UINT NewAcp
  1004. )
  1005. {
  1006. UINT oldVal;
  1007. oldVal = gAnsiCodePage;
  1008. //
  1009. // Sets the ACP global. This is a private exported routine, not an API.
  1010. //
  1011. gAnsiCodePage = NewAcp;
  1012. return oldVal;
  1013. }
  1014. ////////////////////////////////////////////////////////////////////////////
  1015. //
  1016. // GetOEMCP
  1017. //
  1018. // Returns the OEM code page for the system. If the registry value is
  1019. // not readable, then the chosen default ACP is used (NLS_DEFAULT_OEMCP).
  1020. //
  1021. // 05-31-91 JulieB Created.
  1022. ////////////////////////////////////////////////////////////////////////////
  1023. UINT WINAPI GetOEMCP()
  1024. {
  1025. //
  1026. // Return the OEMCP stored in the cache.
  1027. //
  1028. return (gOemCodePage);
  1029. }
  1030. ////////////////////////////////////////////////////////////////////////////
  1031. //
  1032. // GetCPInfo
  1033. //
  1034. // Returns information about a given code page.
  1035. //
  1036. // 05-31-91 JulieB Created.
  1037. ////////////////////////////////////////////////////////////////////////////
  1038. BOOL WINAPI GetCPInfo(
  1039. UINT CodePage,
  1040. LPCPINFO lpCPInfo)
  1041. {
  1042. PCP_HASH pHashN; // ptr to CP hash node
  1043. PCP_TABLE pInfo; // ptr to CP information in file
  1044. WORD wDefChar; // default character
  1045. BYTE *pLeadBytes; // ptr to lead byte ranges
  1046. UINT Ctr; // loop counter
  1047. //
  1048. // See if it's a special code page value for UTF translations.
  1049. //
  1050. if (CodePage >= NLS_CP_ALGORITHM_RANGE)
  1051. {
  1052. return (UTFCPInfo(CodePage, lpCPInfo, FALSE));
  1053. }
  1054. //
  1055. // Get the code page value and the appropriate hash node.
  1056. //
  1057. GET_CP_HASH_NODE(CodePage, pHashN);
  1058. //
  1059. // Invalid Parameter Check:
  1060. // - validate code page - get hash node containing translation tables
  1061. // - lpCPInfo is NULL
  1062. //
  1063. if ( (pHashN == NULL) ||
  1064. ((pHashN->pCPInfo == NULL) && (pHashN->pfnCPProc == NULL)) ||
  1065. (lpCPInfo == NULL) )
  1066. {
  1067. SetLastError(ERROR_INVALID_PARAMETER);
  1068. return (FALSE);
  1069. }
  1070. //
  1071. // See if the given code page is in the DLL range.
  1072. //
  1073. if (pHashN->pfnCPProc)
  1074. {
  1075. //
  1076. // Call the DLL to get the code page information.
  1077. //
  1078. return ( (*(pHashN->pfnCPProc))( CodePage,
  1079. NLS_CP_CPINFO,
  1080. NULL,
  1081. 0,
  1082. NULL,
  1083. 0,
  1084. lpCPInfo ) );
  1085. }
  1086. //
  1087. // Fill in the CPINFO structure with the appropriate information.
  1088. //
  1089. pInfo = pHashN->pCPInfo;
  1090. //
  1091. // Get the max char size.
  1092. //
  1093. lpCPInfo->MaxCharSize = (UINT)((WORD)pInfo->MaxCharSize);
  1094. //
  1095. // Get the default character.
  1096. //
  1097. wDefChar = pInfo->wDefaultChar;
  1098. if (HIBYTE(wDefChar))
  1099. {
  1100. (lpCPInfo->DefaultChar)[0] = HIBYTE(wDefChar);
  1101. (lpCPInfo->DefaultChar)[1] = LOBYTE(wDefChar);
  1102. }
  1103. else
  1104. {
  1105. (lpCPInfo->DefaultChar)[0] = LOBYTE(wDefChar);
  1106. (lpCPInfo->DefaultChar)[1] = (BYTE)0;
  1107. }
  1108. //
  1109. // Get the leadbytes.
  1110. //
  1111. pLeadBytes = pInfo->LeadByte;
  1112. for (Ctr = 0; Ctr < MAX_LEADBYTES; Ctr++)
  1113. {
  1114. (lpCPInfo->LeadByte)[Ctr] = pLeadBytes[Ctr];
  1115. }
  1116. //
  1117. // Return success.
  1118. //
  1119. return (TRUE);
  1120. }
  1121. ////////////////////////////////////////////////////////////////////////////
  1122. //
  1123. // GetCPInfoExW
  1124. //
  1125. // Returns information about a given code page.
  1126. //
  1127. // 11-15-96 JulieB Created.
  1128. ////////////////////////////////////////////////////////////////////////////
  1129. BOOL WINAPI GetCPInfoExW(
  1130. UINT CodePage,
  1131. DWORD dwFlags,
  1132. LPCPINFOEXW lpCPInfoEx)
  1133. {
  1134. PCP_HASH pHashN; // ptr to CP hash node
  1135. PCP_TABLE pInfo; // ptr to CP information in file
  1136. WORD wDefChar; // default character
  1137. BYTE *pLeadBytes; // ptr to lead byte ranges
  1138. UINT Ctr; // loop counter
  1139. //
  1140. // See if it's a special code page value for UTF translations.
  1141. //
  1142. if (CodePage >= NLS_CP_ALGORITHM_RANGE)
  1143. {
  1144. if (UTFCPInfo(CodePage, (LPCPINFO)lpCPInfoEx, TRUE))
  1145. {
  1146. if (GetStringTableEntry( CodePage,
  1147. 0,
  1148. lpCPInfoEx->CodePageName,
  1149. MAX_PATH,
  1150. RC_CODE_PAGE_NAME ) != 0)
  1151. {
  1152. return (TRUE);
  1153. }
  1154. }
  1155. return (FALSE);
  1156. }
  1157. //
  1158. // Get the code page value and the appropriate hash node.
  1159. //
  1160. GET_CP_HASH_NODE(CodePage, pHashN);
  1161. //
  1162. // Invalid Parameter Check:
  1163. // - validate code page - get hash node containing translation tables
  1164. // - lpCPInfoEx is NULL
  1165. //
  1166. if ( (pHashN == NULL) ||
  1167. ((pHashN->pCPInfo == NULL) && (pHashN->pfnCPProc == NULL)) ||
  1168. (lpCPInfoEx == NULL) )
  1169. {
  1170. SetLastError(ERROR_INVALID_PARAMETER);
  1171. return (FALSE);
  1172. }
  1173. //
  1174. // Invalid Flags Check:
  1175. // - flags not 0
  1176. //
  1177. if (dwFlags != 0)
  1178. {
  1179. SetLastError(ERROR_INVALID_FLAGS);
  1180. return (FALSE);
  1181. }
  1182. //
  1183. // See if the given code page is in the DLL range.
  1184. //
  1185. if (pHashN->pfnCPProc)
  1186. {
  1187. //
  1188. // Call the DLL to get the code page information.
  1189. //
  1190. if (((*(pHashN->pfnCPProc))( CodePage,
  1191. NLS_CP_CPINFOEX,
  1192. NULL,
  1193. 0,
  1194. NULL,
  1195. 0,
  1196. (LPCPINFO)lpCPInfoEx )) == TRUE)
  1197. {
  1198. return (TRUE);
  1199. }
  1200. else
  1201. {
  1202. //
  1203. // See if the CPINFO will succeed. If so, then add the
  1204. // default CPINFOEX info to the structure.
  1205. //
  1206. if (((*(pHashN->pfnCPProc))( CodePage,
  1207. NLS_CP_CPINFO,
  1208. NULL,
  1209. 0,
  1210. NULL,
  1211. 0,
  1212. (LPCPINFO)lpCPInfoEx )) == TRUE)
  1213. {
  1214. //
  1215. // Fill in the Ex version info.
  1216. //
  1217. lpCPInfoEx->UnicodeDefaultChar = L'?';
  1218. lpCPInfoEx->CodePage = CodePage;
  1219. GetStringTableEntry( CodePage,
  1220. 0,
  1221. lpCPInfoEx->CodePageName,
  1222. MAX_PATH,
  1223. RC_CODE_PAGE_NAME );
  1224. SetLastError(NO_ERROR);
  1225. return (TRUE);
  1226. }
  1227. return (FALSE);
  1228. }
  1229. }
  1230. //
  1231. // Fill in the CPINFO structure with the appropriate information.
  1232. //
  1233. pInfo = pHashN->pCPInfo;
  1234. //
  1235. // Get the max char size.
  1236. //
  1237. lpCPInfoEx->MaxCharSize = (UINT)((WORD)pInfo->MaxCharSize);
  1238. //
  1239. // Get the default character.
  1240. //
  1241. wDefChar = pInfo->wDefaultChar;
  1242. if (HIBYTE(wDefChar))
  1243. {
  1244. (lpCPInfoEx->DefaultChar)[0] = HIBYTE(wDefChar);
  1245. (lpCPInfoEx->DefaultChar)[1] = LOBYTE(wDefChar);
  1246. }
  1247. else
  1248. {
  1249. (lpCPInfoEx->DefaultChar)[0] = LOBYTE(wDefChar);
  1250. (lpCPInfoEx->DefaultChar)[1] = (BYTE)0;
  1251. }
  1252. //
  1253. // Get the leadbytes.
  1254. //
  1255. pLeadBytes = pInfo->LeadByte;
  1256. for (Ctr = 0; Ctr < MAX_LEADBYTES; Ctr++)
  1257. {
  1258. (lpCPInfoEx->LeadByte)[Ctr] = pLeadBytes[Ctr];
  1259. }
  1260. //
  1261. // Get the Unicode default character.
  1262. //
  1263. lpCPInfoEx->UnicodeDefaultChar = pInfo->wUniDefaultChar;
  1264. //
  1265. // Get the code page id.
  1266. //
  1267. lpCPInfoEx->CodePage = CodePage;
  1268. //
  1269. // Get the code page name.
  1270. //
  1271. if (GetStringTableEntry( CodePage,
  1272. 0,
  1273. lpCPInfoEx->CodePageName,
  1274. MAX_PATH,
  1275. RC_CODE_PAGE_NAME ) == 0)
  1276. {
  1277. return (FALSE);
  1278. }
  1279. //
  1280. // Return success.
  1281. //
  1282. return (TRUE);
  1283. }
  1284. ////////////////////////////////////////////////////////////////////////////
  1285. //
  1286. // IsDBCSLeadByte
  1287. //
  1288. // Checks to see if a given character is a DBCS lead byte in the ACP.
  1289. // Returns TRUE if it is, FALSE if it is not.
  1290. //
  1291. // 05-31-91 JulieB Created.
  1292. ////////////////////////////////////////////////////////////////////////////
  1293. BOOL WINAPI IsDBCSLeadByte(
  1294. BYTE TestChar)
  1295. {
  1296. //
  1297. // Get the hash node for the ACP.
  1298. //
  1299. if (gpACPHashN == NULL)
  1300. {
  1301. SetLastError(ERROR_FILE_NOT_FOUND);
  1302. return (FALSE);
  1303. }
  1304. //
  1305. // See if the given character is a DBCS lead byte.
  1306. //
  1307. if (CHECK_DBCS_LEAD_BYTE(gpACPHashN->pDBCSOffsets, TestChar))
  1308. {
  1309. //
  1310. // Return success - IS a DBCS lead byte.
  1311. //
  1312. return (TRUE);
  1313. }
  1314. //
  1315. // Return failure - is NOT a DBCS lead byte.
  1316. //
  1317. return (FALSE);
  1318. }
  1319. ////////////////////////////////////////////////////////////////////////////
  1320. //
  1321. // IsDBCSLeadByteEx
  1322. //
  1323. // Checks to see if a given character is a DBCS lead byte in the given
  1324. // code page. Returns TRUE if it is, FALSE if it is not.
  1325. //
  1326. // 05-31-91 JulieB Created.
  1327. ////////////////////////////////////////////////////////////////////////////
  1328. BOOL WINAPI IsDBCSLeadByteEx(
  1329. UINT CodePage,
  1330. BYTE TestChar)
  1331. {
  1332. PCP_HASH pHashN; // ptr to CP hash node
  1333. //
  1334. // See if it's a special code page value for UTF translations.
  1335. //
  1336. if (CodePage >= NLS_CP_ALGORITHM_RANGE)
  1337. {
  1338. //
  1339. // Return that it's not a DBCS leadbyte.
  1340. //
  1341. return (FALSE);
  1342. }
  1343. //
  1344. // Get the code page value and the appropriate hash node.
  1345. //
  1346. GET_CP_HASH_NODE(CodePage, pHashN);
  1347. //
  1348. // Invalid Parameter Check:
  1349. // - validate code page
  1350. //
  1351. if (pHashN == NULL)
  1352. {
  1353. SetLastError(ERROR_INVALID_PARAMETER);
  1354. return (FALSE);
  1355. }
  1356. //
  1357. // See if the given character is a DBCS lead byte.
  1358. //
  1359. if (CHECK_DBCS_LEAD_BYTE(pHashN->pDBCSOffsets, TestChar))
  1360. {
  1361. //
  1362. // Return success - IS a DBCS lead byte.
  1363. //
  1364. return (TRUE);
  1365. }
  1366. //
  1367. // Return failure - is NOT a DBCS lead byte.
  1368. //
  1369. return (FALSE);
  1370. }
  1371. ////////////////////////////////////////////////////////////////////////////
  1372. //
  1373. // MultiByteToWideChar
  1374. //
  1375. // Maps a multibyte character string to its wide character string
  1376. // counterpart.
  1377. //
  1378. // 05-31-91 JulieB Created.
  1379. // 09-01-93 JulieB Add support for MB_ERR_INVALID_CHARS flag.
  1380. ////////////////////////////////////////////////////////////////////////////
  1381. int WINAPI MultiByteToWideChar(
  1382. UINT CodePage,
  1383. DWORD dwFlags,
  1384. LPCSTR lpMultiByteStr,
  1385. int cbMultiByte,
  1386. LPWSTR lpWideCharStr,
  1387. int cchWideChar)
  1388. {
  1389. PCP_HASH pHashN; // ptr to CP hash node
  1390. register LPBYTE pMBStr; // ptr to search through MB string
  1391. register LPWSTR pWCStr; // ptr to search through WC string
  1392. LPBYTE pEndMBStr; // ptr to end of MB search string
  1393. LPWSTR pEndWCStr; // ptr to end of WC string buffer
  1394. int wcIncr; // amount to increment pWCStr
  1395. int mbIncr; // amount to increment pMBStr
  1396. int wcCount = 0; // count of wide chars written
  1397. int CompSet; // if MB_COMPOSITE flag is set
  1398. PMB_TABLE pMBTbl; // ptr to correct MB table (MB or GLYPH)
  1399. int ctr; // loop counter
  1400. //
  1401. // See if it's a special code page value for UTF translations.
  1402. //
  1403. if (CodePage >= NLS_CP_ALGORITHM_RANGE)
  1404. {
  1405. return (UTFToUnicode( CodePage,
  1406. dwFlags,
  1407. lpMultiByteStr,
  1408. cbMultiByte,
  1409. lpWideCharStr,
  1410. cchWideChar ));
  1411. }
  1412. //
  1413. // Get the code page value and the appropriate hash node.
  1414. //
  1415. GET_CP_HASH_NODE(CodePage, pHashN);
  1416. //
  1417. // Invalid Parameter Check:
  1418. // - length of MB string is 0
  1419. // - wide char buffer size is negative
  1420. // - MB string is NULL
  1421. // - length of WC string is NOT zero AND
  1422. // (WC string is NULL OR src and dest pointers equal)
  1423. //
  1424. if ( (cbMultiByte == 0) || (cchWideChar < 0) ||
  1425. (lpMultiByteStr == NULL) ||
  1426. ((cchWideChar != 0) &&
  1427. ((lpWideCharStr == NULL) ||
  1428. (lpMultiByteStr == (LPSTR)lpWideCharStr))) )
  1429. {
  1430. SetLastError(ERROR_INVALID_PARAMETER);
  1431. return (0);
  1432. }
  1433. //
  1434. // If cbMultiByte is -1, then the string is null terminated and we
  1435. // need to get the length of the string. Add one to the length to
  1436. // include the null termination. (This will always be at least 1.)
  1437. //
  1438. if (cbMultiByte <= -1)
  1439. {
  1440. cbMultiByte = strlen(lpMultiByteStr) + 1;
  1441. }
  1442. //
  1443. // Check for valid code page.
  1444. //
  1445. if (pHashN == NULL)
  1446. {
  1447. //
  1448. // Special case the CP_SYMBOL code page.
  1449. //
  1450. if ((CodePage == CP_SYMBOL) && (dwFlags == 0))
  1451. {
  1452. //
  1453. // If the caller just wants the size of the buffer needed
  1454. // to do this translation, return the size of the MB string.
  1455. //
  1456. if (cchWideChar == 0)
  1457. {
  1458. return (cbMultiByte);
  1459. }
  1460. //
  1461. // Make sure the buffer is large enough.
  1462. //
  1463. if (cchWideChar < cbMultiByte)
  1464. {
  1465. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1466. return (0);
  1467. }
  1468. //
  1469. // Translate SB char xx to Unicode f0xx.
  1470. // 0x00->0x1f map to 0x0000->0x001f
  1471. // 0x20->0xff map to 0xf020->0xf0ff
  1472. //
  1473. for (ctr = 0; ctr < cbMultiByte; ctr++)
  1474. {
  1475. lpWideCharStr[ctr] = ((BYTE)(lpMultiByteStr[ctr]) < 0x20)
  1476. ? (WCHAR)lpMultiByteStr[ctr]
  1477. : MAKEWORD(lpMultiByteStr[ctr], 0xf0);
  1478. }
  1479. return (cbMultiByte);
  1480. }
  1481. else
  1482. {
  1483. SetLastError(((CodePage == CP_SYMBOL) && (dwFlags != 0))
  1484. ? ERROR_INVALID_FLAGS
  1485. : ERROR_INVALID_PARAMETER);
  1486. return (0);
  1487. }
  1488. }
  1489. //
  1490. // See if the given code page is in the DLL range.
  1491. //
  1492. if (pHashN->pfnCPProc)
  1493. {
  1494. //
  1495. // Invalid Flags Check:
  1496. // - flags not 0
  1497. //
  1498. if (dwFlags != 0)
  1499. {
  1500. SetLastError(ERROR_INVALID_FLAGS);
  1501. return (0);
  1502. }
  1503. //
  1504. // Call the DLL to do the translation.
  1505. //
  1506. return ( (*(pHashN->pfnCPProc))( CodePage,
  1507. NLS_CP_MBTOWC,
  1508. (LPSTR)lpMultiByteStr,
  1509. cbMultiByte,
  1510. (LPWSTR)lpWideCharStr,
  1511. cchWideChar,
  1512. NULL ) );
  1513. }
  1514. //
  1515. // Invalid Flags Check:
  1516. // - flags other than valid ones
  1517. // - composite and precomposed both set
  1518. //
  1519. if ( (dwFlags & MB_INVALID_FLAG) ||
  1520. ((dwFlags & MB_PRECOMPOSED) && (dwFlags & MB_COMPOSITE)) )
  1521. {
  1522. SetLastError(ERROR_INVALID_FLAGS);
  1523. return (0);
  1524. }
  1525. //
  1526. // Initialize multibyte character loop pointers.
  1527. //
  1528. pMBStr = (LPBYTE)lpMultiByteStr;
  1529. pEndMBStr = pMBStr + cbMultiByte;
  1530. CompSet = dwFlags & MB_COMPOSITE;
  1531. //
  1532. // Get the correct MB table (MB or GLYPH).
  1533. //
  1534. if ((dwFlags & MB_USEGLYPHCHARS) && (pHashN->pGlyphTbl != NULL))
  1535. {
  1536. pMBTbl = pHashN->pGlyphTbl;
  1537. }
  1538. else
  1539. {
  1540. pMBTbl = pHashN->pMBTbl;
  1541. }
  1542. //
  1543. // If cchWideChar is 0, then we can't use lpWideCharStr. In this
  1544. // case, we simply want to count the number of characters that would
  1545. // be written to the buffer.
  1546. //
  1547. if (cchWideChar == 0)
  1548. {
  1549. WCHAR pTempStr[MAX_COMPOSITE]; // tmp buffer - max for composite
  1550. //
  1551. // For each multibyte char, translate it to its corresponding
  1552. // wide char and increment the wide character count.
  1553. //
  1554. pEndWCStr = pTempStr + MAX_COMPOSITE;
  1555. if (IS_SBCS_CP(pHashN))
  1556. {
  1557. //
  1558. // Single Byte Character Code Page.
  1559. //
  1560. if (CompSet)
  1561. {
  1562. //
  1563. // Composite flag is set.
  1564. //
  1565. if (dwFlags & MB_ERR_INVALID_CHARS)
  1566. {
  1567. //
  1568. // Error check flag is set.
  1569. //
  1570. while (pMBStr < pEndMBStr)
  1571. {
  1572. if (!(wcIncr = GetWCCompSBErr( pHashN,
  1573. pMBTbl,
  1574. pMBStr,
  1575. pTempStr,
  1576. pEndWCStr )))
  1577. {
  1578. return (0);
  1579. }
  1580. pMBStr++;
  1581. wcCount += wcIncr;
  1582. }
  1583. }
  1584. else
  1585. {
  1586. //
  1587. // Error check flag is NOT set.
  1588. //
  1589. while (pMBStr < pEndMBStr)
  1590. {
  1591. wcCount += GetWCCompSB( pMBTbl,
  1592. pMBStr,
  1593. pTempStr,
  1594. pEndWCStr );
  1595. pMBStr++;
  1596. }
  1597. }
  1598. }
  1599. else
  1600. {
  1601. //
  1602. // Composite flag is NOT set.
  1603. //
  1604. if (dwFlags & MB_ERR_INVALID_CHARS)
  1605. {
  1606. //
  1607. // Error check flag is set.
  1608. //
  1609. wcCount = (int)(pEndMBStr - pMBStr);
  1610. while (pMBStr < pEndMBStr)
  1611. {
  1612. GET_WC_SINGLE( pMBTbl,
  1613. pMBStr,
  1614. pTempStr );
  1615. CHECK_ERROR_WC_SINGLE( pHashN,
  1616. *pTempStr,
  1617. *pMBStr );
  1618. pMBStr++;
  1619. }
  1620. }
  1621. else
  1622. {
  1623. //
  1624. // Error check flag is NOT set.
  1625. //
  1626. // Just return the size of the MB string, since
  1627. // it's a 1:1 translation.
  1628. //
  1629. wcCount = (int)(pEndMBStr - pMBStr);
  1630. }
  1631. }
  1632. }
  1633. else
  1634. {
  1635. //
  1636. // Multi Byte Character Code Page.
  1637. //
  1638. if (CompSet)
  1639. {
  1640. //
  1641. // Composite flag is set.
  1642. //
  1643. if (dwFlags & MB_ERR_INVALID_CHARS)
  1644. {
  1645. //
  1646. // Error check flag is set.
  1647. //
  1648. while (pMBStr < pEndMBStr)
  1649. {
  1650. if (!(wcIncr = GetWCCompMBErr( pHashN,
  1651. pMBTbl,
  1652. pMBStr,
  1653. pEndMBStr,
  1654. pTempStr,
  1655. pEndWCStr,
  1656. &mbIncr )))
  1657. {
  1658. return (0);
  1659. }
  1660. pMBStr += mbIncr;
  1661. wcCount += wcIncr;
  1662. }
  1663. }
  1664. else
  1665. {
  1666. //
  1667. // Error check flag is NOT set.
  1668. //
  1669. while (pMBStr < pEndMBStr)
  1670. {
  1671. wcCount += GetWCCompMB( pHashN,
  1672. pMBTbl,
  1673. pMBStr,
  1674. pEndMBStr,
  1675. pTempStr,
  1676. pEndWCStr,
  1677. &mbIncr );
  1678. pMBStr += mbIncr;
  1679. }
  1680. }
  1681. }
  1682. else
  1683. {
  1684. //
  1685. // Composite flag is NOT set.
  1686. //
  1687. if (dwFlags & MB_ERR_INVALID_CHARS)
  1688. {
  1689. //
  1690. // Error check flag is set.
  1691. //
  1692. while (pMBStr < pEndMBStr)
  1693. {
  1694. GET_WC_MULTI_ERR( pHashN,
  1695. pMBTbl,
  1696. pMBStr,
  1697. pEndMBStr,
  1698. pTempStr,
  1699. pEndWCStr,
  1700. mbIncr );
  1701. pMBStr += mbIncr;
  1702. wcCount++;
  1703. }
  1704. }
  1705. else
  1706. {
  1707. //
  1708. // Error check flag is NOT set.
  1709. //
  1710. while (pMBStr < pEndMBStr)
  1711. {
  1712. GET_WC_MULTI( pHashN,
  1713. pMBTbl,
  1714. pMBStr,
  1715. pEndMBStr,
  1716. pTempStr,
  1717. pEndWCStr,
  1718. mbIncr );
  1719. pMBStr += mbIncr;
  1720. wcCount++;
  1721. }
  1722. }
  1723. }
  1724. }
  1725. }
  1726. else
  1727. {
  1728. //
  1729. // Initialize wide character loop pointers.
  1730. //
  1731. pWCStr = lpWideCharStr;
  1732. pEndWCStr = pWCStr + cchWideChar;
  1733. //
  1734. // For each multibyte char, translate it to its corresponding
  1735. // wide char, store it in lpWideCharStr, and increment the wide
  1736. // character count.
  1737. //
  1738. if (IS_SBCS_CP(pHashN))
  1739. {
  1740. //
  1741. // Single Byte Character Code Page.
  1742. //
  1743. if (CompSet)
  1744. {
  1745. //
  1746. // Composite flag is set.
  1747. //
  1748. if (dwFlags & MB_ERR_INVALID_CHARS)
  1749. {
  1750. //
  1751. // Error check flag is set.
  1752. //
  1753. while ((pMBStr < pEndMBStr) && (pWCStr < pEndWCStr))
  1754. {
  1755. if (!(wcIncr = GetWCCompSBErr( pHashN,
  1756. pMBTbl,
  1757. pMBStr,
  1758. pWCStr,
  1759. pEndWCStr )))
  1760. {
  1761. return (0);
  1762. }
  1763. pMBStr++;
  1764. pWCStr += wcIncr;
  1765. }
  1766. wcCount = (int)(pWCStr - lpWideCharStr);
  1767. }
  1768. else
  1769. {
  1770. //
  1771. // Error check flag is NOT set.
  1772. //
  1773. while ((pMBStr < pEndMBStr) && (pWCStr < pEndWCStr))
  1774. {
  1775. pWCStr += GetWCCompSB( pMBTbl,
  1776. pMBStr,
  1777. pWCStr,
  1778. pEndWCStr );
  1779. pMBStr++;
  1780. }
  1781. wcCount = (int)(pWCStr - lpWideCharStr);
  1782. }
  1783. }
  1784. else
  1785. {
  1786. //
  1787. // Composite flag is NOT set.
  1788. //
  1789. if (dwFlags & MB_ERR_INVALID_CHARS)
  1790. {
  1791. //
  1792. // Error check flag is set.
  1793. //
  1794. wcCount = (int)(pEndMBStr - pMBStr);
  1795. if ((pEndWCStr - pWCStr) < wcCount)
  1796. {
  1797. wcCount = (int)(pEndWCStr - pWCStr);
  1798. }
  1799. for (ctr = wcCount; ctr > 0; ctr--)
  1800. {
  1801. GET_WC_SINGLE( pMBTbl,
  1802. pMBStr,
  1803. pWCStr );
  1804. CHECK_ERROR_WC_SINGLE( pHashN,
  1805. *pWCStr,
  1806. *pMBStr );
  1807. pMBStr++;
  1808. pWCStr++;
  1809. }
  1810. }
  1811. else
  1812. {
  1813. //
  1814. // Error check flag is NOT set.
  1815. //
  1816. wcCount = (int)(pEndMBStr - pMBStr);
  1817. if ((pEndWCStr - pWCStr) < wcCount)
  1818. {
  1819. wcCount = (int)(pEndWCStr - pWCStr);
  1820. }
  1821. for (ctr = wcCount; ctr > 0; ctr--)
  1822. {
  1823. GET_WC_SINGLE( pMBTbl,
  1824. pMBStr,
  1825. pWCStr );
  1826. pMBStr++;
  1827. pWCStr++;
  1828. }
  1829. }
  1830. }
  1831. }
  1832. else
  1833. {
  1834. //
  1835. // Multi Byte Character Code Page.
  1836. //
  1837. if (CompSet)
  1838. {
  1839. //
  1840. // Composite flag is set.
  1841. //
  1842. if (dwFlags & MB_ERR_INVALID_CHARS)
  1843. {
  1844. //
  1845. // Error check flag is set.
  1846. //
  1847. while ((pMBStr < pEndMBStr) && (pWCStr < pEndWCStr))
  1848. {
  1849. if (!(wcIncr = GetWCCompMBErr( pHashN,
  1850. pMBTbl,
  1851. pMBStr,
  1852. pEndMBStr,
  1853. pWCStr,
  1854. pEndWCStr,
  1855. &mbIncr )))
  1856. {
  1857. return (0);
  1858. }
  1859. pMBStr += mbIncr;
  1860. pWCStr += wcIncr;
  1861. }
  1862. wcCount = (int)(pWCStr - lpWideCharStr);
  1863. }
  1864. else
  1865. {
  1866. //
  1867. // Error check flag is NOT set.
  1868. //
  1869. while ((pMBStr < pEndMBStr) && (pWCStr < pEndWCStr))
  1870. {
  1871. pWCStr += GetWCCompMB( pHashN,
  1872. pMBTbl,
  1873. pMBStr,
  1874. pEndMBStr,
  1875. pWCStr,
  1876. pEndWCStr,
  1877. &mbIncr );
  1878. pMBStr += mbIncr;
  1879. }
  1880. wcCount = (int)(pWCStr - lpWideCharStr);
  1881. }
  1882. }
  1883. else
  1884. {
  1885. //
  1886. // Composite flag is NOT set.
  1887. //
  1888. if (dwFlags & MB_ERR_INVALID_CHARS)
  1889. {
  1890. //
  1891. // Error check flag is set.
  1892. //
  1893. while ((pMBStr < pEndMBStr) && (pWCStr < pEndWCStr))
  1894. {
  1895. GET_WC_MULTI_ERR( pHashN,
  1896. pMBTbl,
  1897. pMBStr,
  1898. pEndMBStr,
  1899. pWCStr,
  1900. pEndWCStr,
  1901. mbIncr );
  1902. pMBStr += mbIncr;
  1903. pWCStr++;
  1904. }
  1905. wcCount = (int)(pWCStr - lpWideCharStr);
  1906. }
  1907. else
  1908. {
  1909. //
  1910. // Error check flag is NOT set.
  1911. //
  1912. while ((pMBStr < pEndMBStr) && (pWCStr < pEndWCStr))
  1913. {
  1914. GET_WC_MULTI( pHashN,
  1915. pMBTbl,
  1916. pMBStr,
  1917. pEndMBStr,
  1918. pWCStr,
  1919. pEndWCStr,
  1920. mbIncr );
  1921. pMBStr += mbIncr;
  1922. pWCStr++;
  1923. }
  1924. wcCount = (int)(pWCStr - lpWideCharStr);
  1925. }
  1926. }
  1927. }
  1928. //
  1929. // Make sure wide character buffer was large enough.
  1930. //
  1931. if (pMBStr < pEndMBStr)
  1932. {
  1933. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1934. return (0);
  1935. }
  1936. }
  1937. //
  1938. // Return the number of characters written (or that would have
  1939. // been written) to the buffer.
  1940. //
  1941. return (wcCount);
  1942. }
  1943. ////////////////////////////////////////////////////////////////////////////
  1944. //
  1945. // WideCharToMultiByte
  1946. //
  1947. // Maps a wide character string to its multibyte character string
  1948. // counterpart.
  1949. //
  1950. // NOTE: Most significant bit of dwFlags parameter is used by this routine
  1951. // to indicate that the caller only wants the count of the number of
  1952. // characters written, not the string (ie. do not back up in buffer).
  1953. //
  1954. // 05-31-91 JulieB Created.
  1955. ////////////////////////////////////////////////////////////////////////////
  1956. int WINAPI WideCharToMultiByte(
  1957. UINT CodePage,
  1958. DWORD dwFlags,
  1959. LPCWSTR lpWideCharStr,
  1960. int cchWideChar,
  1961. LPSTR lpMultiByteStr,
  1962. int cbMultiByte,
  1963. LPCSTR lpDefaultChar,
  1964. LPBOOL lpUsedDefaultChar)
  1965. {
  1966. PCP_HASH pHashN; // ptr to CP hash node
  1967. LPWSTR pWCStr; // ptr to search through WC string
  1968. LPWSTR pEndWCStr; // ptr to end of WC string buffer
  1969. WORD wDefault = 0; // default character as a word
  1970. int IfNoDefault; // if default check is to be made
  1971. int IfCompositeChk; // if check for composite
  1972. BOOL TmpUsed; // temp storage for default used
  1973. int ctr; // loop counter
  1974. //
  1975. // See if it's a special code page value for UTF translations.
  1976. //
  1977. if (CodePage >= NLS_CP_ALGORITHM_RANGE)
  1978. {
  1979. return (UnicodeToUTF( CodePage,
  1980. dwFlags,
  1981. lpWideCharStr,
  1982. cchWideChar,
  1983. lpMultiByteStr,
  1984. cbMultiByte,
  1985. lpDefaultChar,
  1986. lpUsedDefaultChar ));
  1987. }
  1988. //
  1989. // Get the code page value and the appropriate hash node.
  1990. //
  1991. GET_CP_HASH_NODE(CodePage, pHashN);
  1992. //
  1993. // Invalid Parameter Check:
  1994. // - length of WC string is 0
  1995. // - multibyte buffer size is negative
  1996. // - WC string is NULL
  1997. // - length of WC string is NOT zero AND
  1998. // (MB string is NULL OR src and dest pointers equal)
  1999. //
  2000. if ( (cchWideChar == 0) || (cbMultiByte < 0) ||
  2001. (lpWideCharStr == NULL) ||
  2002. ((cbMultiByte != 0) &&
  2003. ((lpMultiByteStr == NULL) ||
  2004. (lpWideCharStr == (LPWSTR)lpMultiByteStr))) )
  2005. {
  2006. SetLastError(ERROR_INVALID_PARAMETER);
  2007. return (0);
  2008. }
  2009. //
  2010. // If cchWideChar is -1, then the string is null terminated and we
  2011. // need to get the length of the string. Add one to the length to
  2012. // include the null termination. (This will always be at least 1.)
  2013. //
  2014. if (cchWideChar <= -1)
  2015. {
  2016. cchWideChar = NlsStrLenW(lpWideCharStr) + 1;
  2017. }
  2018. //
  2019. // Check for valid code page.
  2020. //
  2021. if (pHashN == NULL)
  2022. {
  2023. //
  2024. // Special case the CP_SYMBOL code page.
  2025. //
  2026. if ((CodePage == CP_SYMBOL) && (dwFlags == 0) &&
  2027. (lpDefaultChar == NULL) && (lpUsedDefaultChar == NULL))
  2028. {
  2029. //
  2030. // If the caller just wants the size of the buffer needed
  2031. // to do this translation, return the size of the MB string.
  2032. //
  2033. if (cbMultiByte == 0)
  2034. {
  2035. return (cchWideChar);
  2036. }
  2037. //
  2038. // Make sure the buffer is large enough.
  2039. //
  2040. if (cbMultiByte < cchWideChar)
  2041. {
  2042. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  2043. return (0);
  2044. }
  2045. //
  2046. // Translate Unicode char f0xx to SB xx.
  2047. // 0x0000->0x001f map to 0x00->0x1f
  2048. // 0xf020->0xf0ff map to 0x20->0xff
  2049. //
  2050. for (ctr = 0; ctr < cchWideChar; ctr++)
  2051. {
  2052. if ((lpWideCharStr[ctr] >= 0x0020) &&
  2053. ((lpWideCharStr[ctr] < 0xf020) ||
  2054. (lpWideCharStr[ctr] > 0xf0ff)))
  2055. {
  2056. SetLastError(ERROR_NO_UNICODE_TRANSLATION); \
  2057. return (0);
  2058. }
  2059. lpMultiByteStr[ctr] = (BYTE)lpWideCharStr[ctr];
  2060. }
  2061. return (cchWideChar);
  2062. }
  2063. else
  2064. {
  2065. SetLastError(((CodePage == CP_SYMBOL) && (dwFlags != 0))
  2066. ? ERROR_INVALID_FLAGS
  2067. : ERROR_INVALID_PARAMETER);
  2068. return (0);
  2069. }
  2070. }
  2071. //
  2072. // See if the given code page is in the DLL range.
  2073. //
  2074. if (pHashN->pfnCPProc)
  2075. {
  2076. //
  2077. // Invalid Parameter Check:
  2078. // - lpDefaultChar not NULL
  2079. // - lpUsedDefaultChar not NULL
  2080. //
  2081. if ((lpDefaultChar != NULL) || (lpUsedDefaultChar != NULL))
  2082. {
  2083. SetLastError(ERROR_INVALID_PARAMETER);
  2084. return (0);
  2085. }
  2086. //
  2087. // Invalid Flags Check:
  2088. // - flags not 0
  2089. //
  2090. if (dwFlags != 0)
  2091. {
  2092. SetLastError(ERROR_INVALID_FLAGS);
  2093. return (0);
  2094. }
  2095. //
  2096. // Call the DLL to do the translation.
  2097. //
  2098. return ( (*(pHashN->pfnCPProc))( CodePage,
  2099. NLS_CP_WCTOMB,
  2100. (LPSTR)lpMultiByteStr,
  2101. cbMultiByte,
  2102. (LPWSTR)lpWideCharStr,
  2103. cchWideChar,
  2104. NULL ) );
  2105. }
  2106. //
  2107. // Invalid Flags Check:
  2108. // - compositechk flag is not set AND any of comp flags are set
  2109. // - flags other than valid ones
  2110. //
  2111. if ( ((!(IfCompositeChk = (dwFlags & WC_COMPOSITECHECK))) &&
  2112. (dwFlags & WC_COMPCHK_FLAGS)) ||
  2113. (dwFlags & WC_INVALID_FLAG) )
  2114. {
  2115. SetLastError(ERROR_INVALID_FLAGS);
  2116. return (0);
  2117. }
  2118. //
  2119. // Initialize wide character loop pointers.
  2120. //
  2121. pWCStr = (LPWSTR)lpWideCharStr;
  2122. pEndWCStr = pWCStr + cchWideChar;
  2123. //
  2124. // Set the IfNoDefault parameter to TRUE if both lpDefaultChar and
  2125. // lpUsedDefaultChar are NULL.
  2126. //
  2127. IfNoDefault = ((lpDefaultChar == NULL) && (lpUsedDefaultChar == NULL));
  2128. //
  2129. // If the composite check flag is NOT set AND both of the default
  2130. // parameters (lpDefaultChar and lpUsedDefaultChar) are null, then
  2131. // do the quick translation.
  2132. //
  2133. if (IfNoDefault && !IfCompositeChk)
  2134. {
  2135. //
  2136. // Translate WC string to MB string, ignoring default chars.
  2137. //
  2138. return (GetMBNoDefault( pHashN,
  2139. pWCStr,
  2140. pEndWCStr,
  2141. (LPBYTE)lpMultiByteStr,
  2142. cbMultiByte,
  2143. dwFlags ));
  2144. }
  2145. //
  2146. // Set the system default character.
  2147. //
  2148. wDefault = pHashN->pCPInfo->wDefaultChar;
  2149. //
  2150. // See if the default check is needed.
  2151. //
  2152. if (!IfNoDefault)
  2153. {
  2154. //
  2155. // If lpDefaultChar is NULL, then use the system default.
  2156. // Form a word out of the default character. Single byte
  2157. // characters are zero extended, DBCS characters are as is.
  2158. //
  2159. if (lpDefaultChar != NULL)
  2160. {
  2161. wDefault = GET_DEFAULT_WORD( pHashN->pDBCSOffsets,
  2162. (LPBYTE)lpDefaultChar );
  2163. }
  2164. //
  2165. // If lpUsedDefaultChar is NULL, then it won't be used later
  2166. // on if a default character is detected. Otherwise, we need
  2167. // to initialize it.
  2168. //
  2169. if (lpUsedDefaultChar == NULL)
  2170. {
  2171. lpUsedDefaultChar = &TmpUsed;
  2172. }
  2173. *lpUsedDefaultChar = FALSE;
  2174. //
  2175. // Check for "composite check" flag.
  2176. //
  2177. if (!IfCompositeChk)
  2178. {
  2179. //
  2180. // Translate WC string to MB string, checking for the use of the
  2181. // default character.
  2182. //
  2183. return (GetMBDefault( pHashN,
  2184. pWCStr,
  2185. pEndWCStr,
  2186. (LPBYTE)lpMultiByteStr,
  2187. cbMultiByte,
  2188. wDefault,
  2189. lpUsedDefaultChar,
  2190. dwFlags ));
  2191. }
  2192. else
  2193. {
  2194. //
  2195. // Translate WC string to MB string, checking for the use of the
  2196. // default character.
  2197. //
  2198. return (GetMBDefaultComp( pHashN,
  2199. pWCStr,
  2200. pEndWCStr,
  2201. (LPBYTE)lpMultiByteStr,
  2202. cbMultiByte,
  2203. wDefault,
  2204. lpUsedDefaultChar,
  2205. dwFlags ));
  2206. }
  2207. }
  2208. else
  2209. {
  2210. //
  2211. // The only case left here is that the Composite check
  2212. // flag IS set and the default check flag is NOT set.
  2213. //
  2214. // Translate WC string to MB string, checking for the use of the
  2215. // default character.
  2216. //
  2217. return (GetMBDefaultComp( pHashN,
  2218. pWCStr,
  2219. pEndWCStr,
  2220. (LPBYTE)lpMultiByteStr,
  2221. cbMultiByte,
  2222. wDefault,
  2223. &TmpUsed,
  2224. dwFlags ));
  2225. }
  2226. }
  2227. //-------------------------------------------------------------------------//
  2228. // INTERNAL ROUTINES //
  2229. //-------------------------------------------------------------------------//
  2230. ////////////////////////////////////////////////////////////////////////////
  2231. //
  2232. // GetWCCompSB
  2233. //
  2234. // Fills in pWCStr with the wide character(s) for the corresponding single
  2235. // byte character from the appropriate translation table and returns the
  2236. // number of wide characters written. This routine should only be called
  2237. // when the precomposed forms need to be translated to composite.
  2238. //
  2239. // 05-31-91 JulieB Created.
  2240. ////////////////////////////////////////////////////////////////////////////
  2241. int GetWCCompSB(
  2242. PMB_TABLE pMBTbl,
  2243. LPBYTE pMBStr,
  2244. LPWSTR pWCStr,
  2245. LPWSTR pEndWCStr)
  2246. {
  2247. //
  2248. // Get the single byte to wide character translation.
  2249. //
  2250. GET_WC_SINGLE(pMBTbl, pMBStr, pWCStr);
  2251. //
  2252. // Fill in the composite form of the character (if one exists)
  2253. // and return the number of wide characters written.
  2254. //
  2255. return (InsertCompositeForm(pWCStr, pEndWCStr));
  2256. }
  2257. ////////////////////////////////////////////////////////////////////////////
  2258. //
  2259. // GetWCCompMB
  2260. //
  2261. // Fills in pWCStr with the wide character(s) for the corresponding multibyte
  2262. // character from the appropriate translation table and returns the number
  2263. // of wide characters written. The number of bytes used from the pMBStr
  2264. // buffer (single byte or double byte) is returned in the mbIncr parameter.
  2265. // This routine should only be called when the precomposed forms need to be
  2266. // translated to composite.
  2267. //
  2268. // 05-31-91 JulieB Created.
  2269. ////////////////////////////////////////////////////////////////////////////
  2270. int GetWCCompMB(
  2271. PCP_HASH pHashN,
  2272. PMB_TABLE pMBTbl,
  2273. LPBYTE pMBStr,
  2274. LPBYTE pEndMBStr,
  2275. LPWSTR pWCStr,
  2276. LPWSTR pEndWCStr,
  2277. int *pmbIncr)
  2278. {
  2279. //
  2280. // Get the multibyte to wide char translation.
  2281. //
  2282. GET_WC_MULTI( pHashN,
  2283. pMBTbl,
  2284. pMBStr,
  2285. pEndMBStr,
  2286. pWCStr,
  2287. pEndWCStr,
  2288. *pmbIncr );
  2289. //
  2290. // Fill in the composite form of the character (if one exists)
  2291. // and return the number of wide characters written.
  2292. //
  2293. return (InsertCompositeForm(pWCStr, pEndWCStr));
  2294. }
  2295. ////////////////////////////////////////////////////////////////////////////
  2296. //
  2297. // GetWCCompSBErr
  2298. //
  2299. // Fills in pWCStr with the wide character(s) for the corresponding single
  2300. // byte character from the appropriate translation table and returns the
  2301. // number of wide characters written. This routine should only be called
  2302. // when the precomposed forms need to be translated to composite.
  2303. //
  2304. // Checks to be sure an invalid character is not translated to the default
  2305. // character. If so, it sets last error and returns 0 characters written.
  2306. //
  2307. // 09-01-93 JulieB Created.
  2308. ////////////////////////////////////////////////////////////////////////////
  2309. int GetWCCompSBErr(
  2310. PCP_HASH pHashN,
  2311. PMB_TABLE pMBTbl,
  2312. LPBYTE pMBStr,
  2313. LPWSTR pWCStr,
  2314. LPWSTR pEndWCStr)
  2315. {
  2316. //
  2317. // Get the single byte to wide character translation.
  2318. //
  2319. GET_WC_SINGLE(pMBTbl, pMBStr, pWCStr);
  2320. //
  2321. // Make sure an invalid character was not translated to the
  2322. // default char. If it was, set last error and return 0
  2323. // characters written.
  2324. //
  2325. CHECK_ERROR_WC_SINGLE(pHashN, *pWCStr, *pMBStr);
  2326. //
  2327. // Fill in the composite form of the character (if one exists)
  2328. // and return the number of wide characters written.
  2329. //
  2330. return (InsertCompositeForm(pWCStr, pEndWCStr));
  2331. }
  2332. ////////////////////////////////////////////////////////////////////////////
  2333. //
  2334. // GetWCCompMBErr
  2335. //
  2336. // Fills in pWCStr with the wide character(s) for the corresponding multibyte
  2337. // character from the appropriate translation table and returns the number
  2338. // of wide characters written. The number of bytes used from the pMBStr
  2339. // buffer (single byte or double byte) is returned in the mbIncr parameter.
  2340. // This routine should only be called when the precomposed forms need to be
  2341. // translated to composite.
  2342. //
  2343. // Checks to be sure an invalid character is not translated to the default
  2344. // character. If so, it sets last error and returns 0 characters written.
  2345. //
  2346. // 09-01-93 JulieB Created.
  2347. ////////////////////////////////////////////////////////////////////////////
  2348. int GetWCCompMBErr(
  2349. PCP_HASH pHashN,
  2350. PMB_TABLE pMBTbl,
  2351. LPBYTE pMBStr,
  2352. LPBYTE pEndMBStr,
  2353. LPWSTR pWCStr,
  2354. LPWSTR pEndWCStr,
  2355. int *pmbIncr)
  2356. {
  2357. //
  2358. // Get the multibyte to wide char translation.
  2359. //
  2360. // Make sure an invalid character was not translated to the
  2361. // default char. If it was, set last error and return 0
  2362. // characters written.
  2363. //
  2364. GET_WC_MULTI_ERR( pHashN,
  2365. pMBTbl,
  2366. pMBStr,
  2367. pEndMBStr,
  2368. pWCStr,
  2369. pEndWCStr,
  2370. *pmbIncr );
  2371. //
  2372. // Fill in the composite form of the character (if one exists)
  2373. // and return the number of wide characters written.
  2374. //
  2375. return (InsertCompositeForm(pWCStr, pEndWCStr));
  2376. }
  2377. ////////////////////////////////////////////////////////////////////////////
  2378. //
  2379. // GetMBNoDefault
  2380. //
  2381. // Translates the wide character string to a multibyte string and returns
  2382. // the number of bytes written.
  2383. //
  2384. // 05-31-91 JulieB Created.
  2385. ////////////////////////////////////////////////////////////////////////////
  2386. int GetMBNoDefault(
  2387. PCP_HASH pHashN,
  2388. LPWSTR pWCStr,
  2389. LPWSTR pEndWCStr,
  2390. LPBYTE pMBStr,
  2391. int cbMultiByte,
  2392. DWORD dwFlags)
  2393. {
  2394. int mbIncr; // amount to increment pMBStr
  2395. int mbCount = 0; // count of multibyte chars written
  2396. LPBYTE pEndMBStr; // ptr to end of MB string buffer
  2397. PWC_TABLE pWC = pHashN->pWC; // ptr to WC table
  2398. int ctr; // loop counter
  2399. //
  2400. // If cbMultiByte is 0, then we can't use pMBStr. In this
  2401. // case, we simply want to count the number of characters that
  2402. // would be written to the buffer.
  2403. //
  2404. if (cbMultiByte == 0)
  2405. {
  2406. BYTE pTempStr[2]; // tmp buffer - 2 bytes for DBCS
  2407. //
  2408. // For each wide char, translate it to its corresponding multibyte
  2409. // char and increment the multibyte character count.
  2410. //
  2411. if (IS_SBCS_CP(pHashN))
  2412. {
  2413. //
  2414. // Single Byte Character Code Page.
  2415. //
  2416. // Just return the count of characters - it will be the
  2417. // same number of characters as the source string.
  2418. //
  2419. mbCount = (int)(pEndWCStr - pWCStr);
  2420. }
  2421. else
  2422. {
  2423. //
  2424. // Multi Byte Character Code Page.
  2425. //
  2426. if (dwFlags & WC_NO_BEST_FIT_CHARS)
  2427. {
  2428. while (pWCStr < pEndWCStr)
  2429. {
  2430. GET_MB( pWC,
  2431. *pWCStr,
  2432. pTempStr,
  2433. mbIncr,
  2434. FALSE );
  2435. ELIMINATE_BEST_FIT_MB( pHashN,
  2436. *pWCStr,
  2437. pTempStr,
  2438. mbIncr,
  2439. FALSE );
  2440. pWCStr++;
  2441. mbCount += mbIncr;
  2442. }
  2443. }
  2444. else
  2445. {
  2446. while (pWCStr < pEndWCStr)
  2447. {
  2448. GET_MB( pWC,
  2449. *pWCStr,
  2450. pTempStr,
  2451. mbIncr,
  2452. FALSE );
  2453. pWCStr++;
  2454. mbCount += mbIncr;
  2455. }
  2456. }
  2457. }
  2458. }
  2459. else
  2460. {
  2461. //
  2462. // Initialize multibyte loop pointers.
  2463. //
  2464. pEndMBStr = pMBStr + cbMultiByte;
  2465. //
  2466. // For each wide char, translate it to its corresponding
  2467. // multibyte char, store it in pMBStr, and increment the
  2468. // multibyte character count.
  2469. //
  2470. if (IS_SBCS_CP(pHashN))
  2471. {
  2472. //
  2473. // Single Byte Character Code Page.
  2474. //
  2475. mbCount = (int)(pEndWCStr - pWCStr);
  2476. if ((pEndMBStr - pMBStr) < mbCount)
  2477. {
  2478. mbCount = (int)(pEndMBStr - pMBStr);
  2479. }
  2480. if (dwFlags & WC_NO_BEST_FIT_CHARS)
  2481. {
  2482. for (ctr = mbCount; ctr > 0; ctr--)
  2483. {
  2484. GET_SB( pWC,
  2485. *pWCStr,
  2486. pMBStr );
  2487. ELIMINATE_BEST_FIT_SB( pHashN,
  2488. *pWCStr,
  2489. pMBStr );
  2490. pWCStr++;
  2491. pMBStr++;
  2492. }
  2493. }
  2494. else
  2495. {
  2496. for (ctr = mbCount; ctr > 0; ctr--)
  2497. {
  2498. GET_SB( pWC,
  2499. *pWCStr,
  2500. pMBStr );
  2501. pWCStr++;
  2502. pMBStr++;
  2503. }
  2504. }
  2505. }
  2506. else
  2507. {
  2508. //
  2509. // Multi Byte Character Code Page.
  2510. //
  2511. if (dwFlags & WC_NO_BEST_FIT_CHARS)
  2512. {
  2513. while ((pWCStr < pEndWCStr) && (pMBStr < pEndMBStr))
  2514. {
  2515. GET_MB( pWC,
  2516. *pWCStr,
  2517. pMBStr,
  2518. mbIncr,
  2519. ((pMBStr + 1) < pEndMBStr) ? FALSE : TRUE );
  2520. ELIMINATE_BEST_FIT_MB( pHashN,
  2521. *pWCStr,
  2522. pMBStr,
  2523. mbIncr,
  2524. ((pMBStr + 1) < pEndMBStr) ? FALSE : TRUE );
  2525. if (mbIncr == 0)
  2526. {
  2527. //
  2528. // Not enough space in buffer.
  2529. //
  2530. break;
  2531. }
  2532. pWCStr++;
  2533. mbCount += mbIncr;
  2534. pMBStr += mbIncr;
  2535. }
  2536. }
  2537. else
  2538. {
  2539. while ((pWCStr < pEndWCStr) && (pMBStr < pEndMBStr))
  2540. {
  2541. GET_MB( pWC,
  2542. *pWCStr,
  2543. pMBStr,
  2544. mbIncr,
  2545. ((pMBStr + 1) < pEndMBStr) ? FALSE : TRUE );
  2546. if (mbIncr == 0)
  2547. {
  2548. //
  2549. // Not enough space in buffer.
  2550. //
  2551. break;
  2552. }
  2553. pWCStr++;
  2554. mbCount += mbIncr;
  2555. pMBStr += mbIncr;
  2556. }
  2557. }
  2558. }
  2559. //
  2560. // Make sure multibyte character buffer was large enough.
  2561. //
  2562. if (pWCStr < pEndWCStr)
  2563. {
  2564. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  2565. return (0);
  2566. }
  2567. }
  2568. //
  2569. // Return the number of characters written (or that would have
  2570. // been written) to the buffer.
  2571. //
  2572. return (mbCount);
  2573. }
  2574. ////////////////////////////////////////////////////////////////////////////
  2575. //
  2576. // GetMBDefault
  2577. //
  2578. // Translates the wide character string to a multibyte string and returns
  2579. // the number of bytes written. This also checks for the use of the default
  2580. // character, so the translation is slower.
  2581. //
  2582. // 05-31-91 JulieB Created.
  2583. ////////////////////////////////////////////////////////////////////////////
  2584. int GetMBDefault(
  2585. PCP_HASH pHashN,
  2586. LPWSTR pWCStr,
  2587. LPWSTR pEndWCStr,
  2588. LPBYTE pMBStr,
  2589. int cbMultiByte,
  2590. WORD wDefault,
  2591. LPBOOL pUsedDef,
  2592. DWORD dwFlags)
  2593. {
  2594. int mbIncr; // amount to increment pMBStr
  2595. int mbIncr2; // amount to increment pMBStr
  2596. int mbCount = 0; // count of multibyte chars written
  2597. LPBYTE pEndMBStr; // ptr to end of MB string buffer
  2598. PWC_TABLE pWC = pHashN->pWC; // ptr to WC table
  2599. int ctr; // loop counter
  2600. //
  2601. // If cbMultiByte is 0, then we can't use pMBStr. In this
  2602. // case, we simply want to count the number of characters that
  2603. // would be written to the buffer.
  2604. //
  2605. if (cbMultiByte == 0)
  2606. {
  2607. BYTE pTempStr[2]; // tmp buffer - 2 bytes for DBCS
  2608. //
  2609. // For each wide char, translate it to its corresponding multibyte
  2610. // char and increment the multibyte character count.
  2611. //
  2612. if (IS_SBCS_CP(pHashN))
  2613. {
  2614. //
  2615. // Single Byte Character Code Page.
  2616. //
  2617. mbCount = (int)(pEndWCStr - pWCStr);
  2618. if (dwFlags & WC_NO_BEST_FIT_CHARS)
  2619. {
  2620. while (pWCStr < pEndWCStr)
  2621. {
  2622. GET_SB( pWC,
  2623. *pWCStr,
  2624. pTempStr );
  2625. ELIMINATE_BEST_FIT_SB( pHashN,
  2626. *pWCStr,
  2627. pTempStr );
  2628. DEFAULT_CHAR_CHECK_SB( pHashN,
  2629. *pWCStr,
  2630. pTempStr,
  2631. wDefault,
  2632. pUsedDef );
  2633. pWCStr++;
  2634. }
  2635. }
  2636. else
  2637. {
  2638. while (pWCStr < pEndWCStr)
  2639. {
  2640. GET_SB( pWC,
  2641. *pWCStr,
  2642. pTempStr );
  2643. DEFAULT_CHAR_CHECK_SB( pHashN,
  2644. *pWCStr,
  2645. pTempStr,
  2646. wDefault,
  2647. pUsedDef );
  2648. pWCStr++;
  2649. }
  2650. }
  2651. }
  2652. else
  2653. {
  2654. //
  2655. // Multi Byte Character Code Page.
  2656. //
  2657. if (dwFlags & WC_NO_BEST_FIT_CHARS)
  2658. {
  2659. while (pWCStr < pEndWCStr)
  2660. {
  2661. GET_MB( pWC,
  2662. *pWCStr,
  2663. pTempStr,
  2664. mbIncr,
  2665. FALSE );
  2666. ELIMINATE_BEST_FIT_MB( pHashN,
  2667. *pWCStr,
  2668. pTempStr,
  2669. mbIncr,
  2670. FALSE );
  2671. DEFAULT_CHAR_CHECK_MB( pHashN,
  2672. *pWCStr,
  2673. pTempStr,
  2674. wDefault,
  2675. pUsedDef,
  2676. mbIncr2,
  2677. FALSE );
  2678. mbCount += (mbIncr2) ? (mbIncr2) : (mbIncr);
  2679. pWCStr++;
  2680. }
  2681. }
  2682. else
  2683. {
  2684. while (pWCStr < pEndWCStr)
  2685. {
  2686. GET_MB( pWC,
  2687. *pWCStr,
  2688. pTempStr,
  2689. mbIncr,
  2690. FALSE );
  2691. DEFAULT_CHAR_CHECK_MB( pHashN,
  2692. *pWCStr,
  2693. pTempStr,
  2694. wDefault,
  2695. pUsedDef,
  2696. mbIncr2,
  2697. FALSE );
  2698. mbCount += (mbIncr2) ? (mbIncr2) : (mbIncr);
  2699. pWCStr++;
  2700. }
  2701. }
  2702. }
  2703. }
  2704. else
  2705. {
  2706. //
  2707. // Initialize multibyte loop pointers.
  2708. //
  2709. pEndMBStr = pMBStr + cbMultiByte;
  2710. //
  2711. // For each wide char, translate it to its corresponding
  2712. // multibyte char, store it in pMBStr, and increment the
  2713. // multibyte character count.
  2714. //
  2715. if (IS_SBCS_CP(pHashN))
  2716. {
  2717. //
  2718. // Single Byte Character Code Page.
  2719. //
  2720. mbCount = (int)(pEndWCStr - pWCStr);
  2721. if ((pEndMBStr - pMBStr) < mbCount)
  2722. {
  2723. mbCount = (int)(pEndMBStr - pMBStr);
  2724. }
  2725. if (dwFlags & WC_NO_BEST_FIT_CHARS)
  2726. {
  2727. for (ctr = mbCount; ctr > 0; ctr--)
  2728. {
  2729. GET_SB( pWC,
  2730. *pWCStr,
  2731. pMBStr );
  2732. ELIMINATE_BEST_FIT_SB( pHashN,
  2733. *pWCStr,
  2734. pMBStr );
  2735. DEFAULT_CHAR_CHECK_SB( pHashN,
  2736. *pWCStr,
  2737. pMBStr,
  2738. wDefault,
  2739. pUsedDef );
  2740. pWCStr++;
  2741. pMBStr++;
  2742. }
  2743. }
  2744. else
  2745. {
  2746. for (ctr = mbCount; ctr > 0; ctr--)
  2747. {
  2748. GET_SB( pWC,
  2749. *pWCStr,
  2750. pMBStr );
  2751. DEFAULT_CHAR_CHECK_SB( pHashN,
  2752. *pWCStr,
  2753. pMBStr,
  2754. wDefault,
  2755. pUsedDef );
  2756. pWCStr++;
  2757. pMBStr++;
  2758. }
  2759. }
  2760. }
  2761. else
  2762. {
  2763. //
  2764. // Multi Byte Character Code Page.
  2765. //
  2766. if (dwFlags & WC_NO_BEST_FIT_CHARS)
  2767. {
  2768. while ((pWCStr < pEndWCStr) && (pMBStr < pEndMBStr))
  2769. {
  2770. GET_MB( pWC,
  2771. *pWCStr,
  2772. pMBStr,
  2773. mbIncr,
  2774. ((pMBStr + 1) < pEndMBStr) ? FALSE : TRUE );
  2775. ELIMINATE_BEST_FIT_MB( pHashN,
  2776. *pWCStr,
  2777. pMBStr,
  2778. mbIncr,
  2779. ((pMBStr + 1) < pEndMBStr) ? FALSE : TRUE );
  2780. DEFAULT_CHAR_CHECK_MB( pHashN,
  2781. *pWCStr,
  2782. pMBStr,
  2783. wDefault,
  2784. pUsedDef,
  2785. mbIncr2,
  2786. ((pMBStr + 1) < pEndMBStr) ? FALSE : TRUE );
  2787. if ((mbIncr == 0) || (mbIncr2 == -1))
  2788. {
  2789. //
  2790. // Not enough room in buffer.
  2791. //
  2792. break;
  2793. }
  2794. mbCount += (mbIncr2) ? (mbIncr2) : (mbIncr);
  2795. pWCStr++;
  2796. pMBStr += mbIncr;
  2797. }
  2798. }
  2799. else
  2800. {
  2801. while ((pWCStr < pEndWCStr) && (pMBStr < pEndMBStr))
  2802. {
  2803. GET_MB( pWC,
  2804. *pWCStr,
  2805. pMBStr,
  2806. mbIncr,
  2807. ((pMBStr + 1) < pEndMBStr) ? FALSE : TRUE );
  2808. DEFAULT_CHAR_CHECK_MB( pHashN,
  2809. *pWCStr,
  2810. pMBStr,
  2811. wDefault,
  2812. pUsedDef,
  2813. mbIncr2,
  2814. ((pMBStr + 1) < pEndMBStr) ? FALSE : TRUE );
  2815. if ((mbIncr == 0) || (mbIncr2 == -1))
  2816. {
  2817. //
  2818. // Not enough room in buffer.
  2819. //
  2820. break;
  2821. }
  2822. mbCount += (mbIncr2) ? (mbIncr2) : (mbIncr);
  2823. pWCStr++;
  2824. pMBStr += mbIncr;
  2825. }
  2826. }
  2827. }
  2828. //
  2829. // Make sure multibyte character buffer was large enough.
  2830. //
  2831. if (pWCStr < pEndWCStr)
  2832. {
  2833. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  2834. return (0);
  2835. }
  2836. }
  2837. //
  2838. // Return the number of characters written (or that would have
  2839. // been written) to the buffer.
  2840. //
  2841. return (mbCount);
  2842. }
  2843. ////////////////////////////////////////////////////////////////////////////
  2844. //
  2845. // GetMBDefaultComp
  2846. //
  2847. // Translates the wide character string to a multibyte string and returns
  2848. // the number of bytes written. This also checks for the use of the default
  2849. // character and tries to convert composite forms to precomposed forms, so
  2850. // the translation is a lot slower.
  2851. //
  2852. // 05-31-91 JulieB Created.
  2853. ////////////////////////////////////////////////////////////////////////////
  2854. int GetMBDefaultComp(
  2855. PCP_HASH pHashN,
  2856. LPWSTR pWCStr,
  2857. LPWSTR pEndWCStr,
  2858. LPBYTE pMBStr,
  2859. int cbMultiByte,
  2860. WORD wDefault,
  2861. LPBOOL pUsedDef,
  2862. DWORD dwFlags)
  2863. {
  2864. int mbIncr; // amount to increment pMBStr
  2865. int mbCount = 0; // count of multibyte chars written
  2866. LPBYTE pEndMBStr; // ptr to end of MB string buffer
  2867. BOOL fError; // if error during MB conversion
  2868. //
  2869. // If cbMultiByte is 0, then we can't use pMBStr. In this
  2870. // case, we simply want to count the number of characters that
  2871. // would be written to the buffer.
  2872. //
  2873. if (cbMultiByte == 0)
  2874. {
  2875. BYTE pTempStr[2]; // tmp buffer - 2 bytes for DBCS
  2876. //
  2877. // Set most significant bit of flags to indicate to the
  2878. // GetMBComp routine that it's using a temporary storage
  2879. // area, so don't back up in the buffer.
  2880. //
  2881. SET_MSB(dwFlags);
  2882. //
  2883. // For each wide char, translate it to its corresponding multibyte
  2884. // char and increment the multibyte character count.
  2885. //
  2886. if (IS_SBCS_CP(pHashN))
  2887. {
  2888. //
  2889. // Single Byte Character Code Page.
  2890. //
  2891. while (pWCStr < pEndWCStr)
  2892. {
  2893. //
  2894. // Get the translation.
  2895. //
  2896. mbCount += GetMBCompSB( pHashN,
  2897. dwFlags,
  2898. pWCStr,
  2899. pTempStr,
  2900. mbCount,
  2901. wDefault,
  2902. pUsedDef );
  2903. pWCStr++;
  2904. }
  2905. }
  2906. else
  2907. {
  2908. //
  2909. // Multi Byte Character Code Page.
  2910. //
  2911. while (pWCStr < pEndWCStr)
  2912. {
  2913. //
  2914. // Get the translation.
  2915. //
  2916. mbCount += GetMBCompMB( pHashN,
  2917. dwFlags,
  2918. pWCStr,
  2919. pTempStr,
  2920. mbCount,
  2921. wDefault,
  2922. pUsedDef,
  2923. &fError,
  2924. FALSE );
  2925. pWCStr++;
  2926. }
  2927. }
  2928. }
  2929. else
  2930. {
  2931. //
  2932. // Initialize multibyte loop pointers.
  2933. //
  2934. pEndMBStr = pMBStr + cbMultiByte;
  2935. //
  2936. // For each wide char, translate it to its corresponding
  2937. // multibyte char, store it in pMBStr, and increment the
  2938. // multibyte character count.
  2939. //
  2940. if (IS_SBCS_CP(pHashN))
  2941. {
  2942. //
  2943. // Single Byte Character Code Page.
  2944. //
  2945. while ((pWCStr < pEndWCStr) && (pMBStr < pEndMBStr))
  2946. {
  2947. //
  2948. // Get the translation.
  2949. //
  2950. mbIncr = GetMBCompSB( pHashN,
  2951. dwFlags,
  2952. pWCStr,
  2953. pMBStr,
  2954. mbCount,
  2955. wDefault,
  2956. pUsedDef );
  2957. pWCStr++;
  2958. mbCount += mbIncr;
  2959. pMBStr += mbIncr;
  2960. }
  2961. }
  2962. else
  2963. {
  2964. //
  2965. // Multi Byte Character Code Page.
  2966. //
  2967. while ((pWCStr < pEndWCStr) && (pMBStr < pEndMBStr))
  2968. {
  2969. //
  2970. // Get the translation.
  2971. //
  2972. mbIncr = GetMBCompMB( pHashN,
  2973. dwFlags,
  2974. pWCStr,
  2975. pMBStr,
  2976. mbCount,
  2977. wDefault,
  2978. pUsedDef,
  2979. &fError,
  2980. ((pMBStr + 1) < pEndMBStr) ? FALSE : TRUE );
  2981. if (fError)
  2982. {
  2983. //
  2984. // Not enough room in the buffer.
  2985. //
  2986. break;
  2987. }
  2988. pWCStr++;
  2989. mbCount += mbIncr;
  2990. pMBStr += mbIncr;
  2991. }
  2992. }
  2993. //
  2994. // Make sure multibyte character buffer was large enough.
  2995. //
  2996. if (pWCStr < pEndWCStr)
  2997. {
  2998. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  2999. return (0);
  3000. }
  3001. }
  3002. //
  3003. // Return the number of characters written (or that would have
  3004. // been written) to the buffer.
  3005. //
  3006. return (mbCount);
  3007. }
  3008. ////////////////////////////////////////////////////////////////////////////
  3009. //
  3010. // GetMBCompSB
  3011. //
  3012. // Fills in pMBStr with the byte character(s) for the corresponding wide
  3013. // character from the appropriate translation table and returns the number
  3014. // of byte characters written to pMBStr. This routine is only called if
  3015. // the defaultcheck and compositecheck flags were both set.
  3016. //
  3017. // NOTE: Most significant bit of dwFlags parameter is used by this routine
  3018. // to indicate that the caller only wants the count of the number of
  3019. // characters written, not the string (ie. do not back up in buffer).
  3020. //
  3021. // 05-31-91 JulieB Created.
  3022. ////////////////////////////////////////////////////////////////////////////
  3023. int GetMBCompSB(
  3024. PCP_HASH pHashN,
  3025. DWORD dwFlags,
  3026. LPWSTR pWCStr,
  3027. LPBYTE pMBStr,
  3028. int mbCount,
  3029. WORD wDefault,
  3030. LPBOOL pUsedDef)
  3031. {
  3032. WCHAR PreComp; // precomposed wide character
  3033. if ((pTblPtrs->pDefaultSortkey == NULL) ||
  3034. (!IS_NONSPACE_ONLY(pTblPtrs->pDefaultSortkey, *pWCStr)))
  3035. {
  3036. //
  3037. // Get the 1:1 translation from wide char to single byte.
  3038. //
  3039. GET_WC_TRANSLATION_SB( pHashN,
  3040. *pWCStr,
  3041. pMBStr,
  3042. wDefault,
  3043. pUsedDef,
  3044. dwFlags );
  3045. return (1);
  3046. }
  3047. else
  3048. {
  3049. if (mbCount < 1)
  3050. {
  3051. //
  3052. // Need to handle the nonspace character by itself, since
  3053. // it is the first character in the string.
  3054. //
  3055. if (dwFlags & WC_DISCARDNS)
  3056. {
  3057. //
  3058. // Discard the non-spacing char, so just return with
  3059. // zero chars written.
  3060. //
  3061. return (0);
  3062. }
  3063. else if (dwFlags & WC_DEFAULTCHAR)
  3064. {
  3065. //
  3066. // Need to replace the nonspace character with the default
  3067. // character and return the number of characters written
  3068. // to the multibyte string.
  3069. //
  3070. *pUsedDef = TRUE;
  3071. *pMBStr = LOBYTE(wDefault);
  3072. return (1);
  3073. }
  3074. else // WC_SEPCHARS - default
  3075. {
  3076. //
  3077. // Get the 1:1 translation from wide char to multibyte
  3078. // of the non-spacing char and return the number of
  3079. // characters written to the multibyte string.
  3080. //
  3081. GET_WC_TRANSLATION_SB( pHashN,
  3082. *pWCStr,
  3083. pMBStr,
  3084. wDefault,
  3085. pUsedDef,
  3086. dwFlags );
  3087. return (1);
  3088. }
  3089. }
  3090. else if (PreComp = GetPreComposedChar(*pWCStr, *(pWCStr - 1)))
  3091. {
  3092. //
  3093. // Back up in the single byte string and write the
  3094. // precomposed char.
  3095. //
  3096. if (!IS_MSB(dwFlags))
  3097. {
  3098. pMBStr--;
  3099. }
  3100. GET_WC_TRANSLATION_SB( pHashN,
  3101. PreComp,
  3102. pMBStr,
  3103. wDefault,
  3104. pUsedDef,
  3105. dwFlags );
  3106. return (0);
  3107. }
  3108. else
  3109. {
  3110. if (dwFlags & WC_DISCARDNS)
  3111. {
  3112. //
  3113. // Discard the non-spacing char, so just return with
  3114. // zero chars written.
  3115. //
  3116. return (0);
  3117. }
  3118. else if (dwFlags & WC_DEFAULTCHAR)
  3119. {
  3120. //
  3121. // Need to replace the base character with the default
  3122. // character. Since we've already written the base
  3123. // translation char in the single byte string, we need to
  3124. // back up in the single byte string and write the default
  3125. // char.
  3126. //
  3127. if (!IS_MSB(dwFlags))
  3128. {
  3129. pMBStr--;
  3130. }
  3131. *pUsedDef = TRUE;
  3132. *pMBStr = LOBYTE(wDefault);
  3133. return (0);
  3134. }
  3135. else // WC_SEPCHARS - default
  3136. {
  3137. //
  3138. // Get the 1:1 translation from wide char to multibyte
  3139. // of the non-spacing char and return the number of
  3140. // characters written to the multibyte string.
  3141. //
  3142. GET_WC_TRANSLATION_SB( pHashN,
  3143. *pWCStr,
  3144. pMBStr,
  3145. wDefault,
  3146. pUsedDef,
  3147. dwFlags );
  3148. return (1);
  3149. }
  3150. }
  3151. }
  3152. }
  3153. ////////////////////////////////////////////////////////////////////////////
  3154. //
  3155. // GetMBCompMB
  3156. //
  3157. // Fills in pMBStr with the byte character(s) for the corresponding wide
  3158. // character from the appropriate translation table and returns the number
  3159. // of byte characters written to pMBStr. This routine is only called if
  3160. // the defaultcheck and compositecheck flags were both set.
  3161. //
  3162. // If the buffer was too small, the fError flag will be set to TRUE.
  3163. //
  3164. // NOTE: Most significant bit of dwFlags parameter is used by this routine
  3165. // to indicate that the caller only wants the count of the number of
  3166. // characters written, not the string (ie. do not back up in buffer).
  3167. //
  3168. // 05-31-91 JulieB Created.
  3169. ////////////////////////////////////////////////////////////////////////////
  3170. int GetMBCompMB(
  3171. PCP_HASH pHashN,
  3172. DWORD dwFlags,
  3173. LPWSTR pWCStr,
  3174. LPBYTE pMBStr,
  3175. int mbCount,
  3176. WORD wDefault,
  3177. LPBOOL pUsedDef,
  3178. BOOL *fError,
  3179. BOOL fOnlyOne)
  3180. {
  3181. WCHAR PreComp; // precomposed wide character
  3182. BYTE pTmpSp[2]; // temp space - 2 bytes for DBCS
  3183. int nCnt; // number of characters written
  3184. *fError = FALSE;
  3185. if ((pTblPtrs->pDefaultSortkey == NULL) ||
  3186. (!IS_NONSPACE_ONLY(pTblPtrs->pDefaultSortkey, *pWCStr)))
  3187. {
  3188. //
  3189. // Get the 1:1 translation from wide char to multibyte.
  3190. // This also handles DBCS and returns the number of characters
  3191. // written to the multibyte string.
  3192. //
  3193. GET_WC_TRANSLATION_MB( pHashN,
  3194. *pWCStr,
  3195. pMBStr,
  3196. wDefault,
  3197. pUsedDef,
  3198. nCnt,
  3199. fOnlyOne,
  3200. dwFlags );
  3201. if (nCnt == 0)
  3202. {
  3203. *fError = TRUE;
  3204. }
  3205. return (nCnt);
  3206. }
  3207. else
  3208. {
  3209. if (mbCount < 1)
  3210. {
  3211. //
  3212. // Need to handle the nonspace character by itself, since
  3213. // it is the first character in the string.
  3214. //
  3215. if (dwFlags & WC_DISCARDNS)
  3216. {
  3217. //
  3218. // Discard the non-spacing char, so just return with
  3219. // zero chars written.
  3220. //
  3221. return (0);
  3222. }
  3223. else if (dwFlags & WC_DEFAULTCHAR)
  3224. {
  3225. //
  3226. // Need to replace the nonspace character with the default
  3227. // character and return the number of characters written
  3228. // to the multibyte string.
  3229. //
  3230. *pUsedDef = TRUE;
  3231. COPY_MB_CHAR( wDefault,
  3232. pMBStr,
  3233. nCnt,
  3234. fOnlyOne );
  3235. if (nCnt == 0)
  3236. {
  3237. *fError = TRUE;
  3238. }
  3239. return (nCnt);
  3240. }
  3241. else // WC_SEPCHARS - default
  3242. {
  3243. //
  3244. // Get the 1:1 translation from wide char to multibyte
  3245. // of the non-spacing char and return the number of
  3246. // characters written to the multibyte string.
  3247. //
  3248. GET_WC_TRANSLATION_MB( pHashN,
  3249. *pWCStr,
  3250. pMBStr,
  3251. wDefault,
  3252. pUsedDef,
  3253. nCnt,
  3254. fOnlyOne,
  3255. dwFlags );
  3256. if (nCnt == 0)
  3257. {
  3258. *fError = TRUE;
  3259. }
  3260. return (nCnt);
  3261. }
  3262. }
  3263. else if (PreComp = GetPreComposedChar(*pWCStr, *(pWCStr - 1)))
  3264. {
  3265. //
  3266. // Get the 1:1 translation from wide char to multibyte
  3267. // of the precomposed char, back up in the multibyte string,
  3268. // write the precomposed char, and return the DIFFERENCE of
  3269. // the number of characters written to the the multibyte
  3270. // string.
  3271. //
  3272. GET_WC_TRANSLATION_MB( pHashN,
  3273. *(pWCStr - 1),
  3274. pTmpSp,
  3275. wDefault,
  3276. pUsedDef,
  3277. nCnt,
  3278. fOnlyOne,
  3279. dwFlags );
  3280. if (nCnt == 0)
  3281. {
  3282. *fError = TRUE;
  3283. return (nCnt);
  3284. }
  3285. if (!IS_MSB(dwFlags))
  3286. {
  3287. pMBStr -= nCnt;
  3288. }
  3289. GET_WC_TRANSLATION_MB( pHashN,
  3290. PreComp,
  3291. pMBStr,
  3292. wDefault,
  3293. pUsedDef,
  3294. mbCount,
  3295. fOnlyOne,
  3296. dwFlags );
  3297. if (mbCount == 0)
  3298. {
  3299. *fError = TRUE;
  3300. }
  3301. return (mbCount - nCnt);
  3302. }
  3303. else
  3304. {
  3305. if (dwFlags & WC_DISCARDNS)
  3306. {
  3307. //
  3308. // Discard the non-spacing char, so just return with
  3309. // zero chars written.
  3310. //
  3311. return (0);
  3312. }
  3313. else if (dwFlags & WC_DEFAULTCHAR)
  3314. {
  3315. //
  3316. // Need to replace the base character with the default
  3317. // character. Since we've already written the base
  3318. // translation char in the multibyte string, we need to
  3319. // back up in the multibyte string and return the
  3320. // DIFFERENCE of the number of characters written
  3321. // (could be negative).
  3322. //
  3323. //
  3324. // If the previous character written is the default
  3325. // character, then the base character for this nonspace
  3326. // character has already been replaced. Simply throw
  3327. // this character away and return zero chars written.
  3328. //
  3329. if (!IS_MSB(dwFlags))
  3330. {
  3331. //
  3332. // Not using a temporary buffer, so find out if the
  3333. // previous character translated was the default char.
  3334. //
  3335. if ((MAKEWORD(*(pMBStr - 1), 0) == wDefault) ||
  3336. ((mbCount > 1) &&
  3337. (MAKEWORD(*(pMBStr - 1), *(pMBStr - 2)) == wDefault)))
  3338. {
  3339. return (0);
  3340. }
  3341. }
  3342. else
  3343. {
  3344. //
  3345. // Using a temporary buffer. The temp buffer is 2 bytes
  3346. // in length and contains the previous character written.
  3347. //
  3348. if ((MAKEWORD(*pMBStr, 0) == wDefault) ||
  3349. ((mbCount > 1) &&
  3350. (MAKEWORD(*pMBStr, *(pMBStr + 1)) == wDefault)))
  3351. {
  3352. return (0);
  3353. }
  3354. }
  3355. //
  3356. // Get the 1:1 translation from wide char to multibyte
  3357. // of the base char, back up in the multibyte string,
  3358. // write the default char, and return the DIFFERENCE of
  3359. // the number of characters written to the the multibyte
  3360. // string.
  3361. //
  3362. GET_WC_TRANSLATION_MB( pHashN,
  3363. *(pWCStr - 1),
  3364. pTmpSp,
  3365. wDefault,
  3366. pUsedDef,
  3367. nCnt,
  3368. fOnlyOne,
  3369. dwFlags );
  3370. if (nCnt == 0)
  3371. {
  3372. *fError = TRUE;
  3373. return (nCnt);
  3374. }
  3375. if (!IS_MSB(dwFlags))
  3376. {
  3377. pMBStr -= nCnt;
  3378. }
  3379. *pUsedDef = TRUE;
  3380. COPY_MB_CHAR( wDefault,
  3381. pMBStr,
  3382. mbCount,
  3383. fOnlyOne );
  3384. if (mbCount == 0)
  3385. {
  3386. *fError = TRUE;
  3387. }
  3388. return (mbCount - nCnt);
  3389. }
  3390. else // WC_SEPCHARS - default
  3391. {
  3392. //
  3393. // Get the 1:1 translation from wide char to multibyte
  3394. // of the non-spacing char and return the number of
  3395. // characters written to the multibyte string.
  3396. //
  3397. GET_WC_TRANSLATION_MB( pHashN,
  3398. *pWCStr,
  3399. pMBStr,
  3400. wDefault,
  3401. pUsedDef,
  3402. nCnt,
  3403. fOnlyOne,
  3404. dwFlags );
  3405. if (nCnt == 0)
  3406. {
  3407. *fError = TRUE;
  3408. }
  3409. return (nCnt);
  3410. }
  3411. }
  3412. }
  3413. }
  3414. ////////////////////////////////////////////////////////////////////////////
  3415. //
  3416. // GetMacCodePage
  3417. //
  3418. // Returns the system default Mac code page.
  3419. //
  3420. // 09-22-93 JulieB Created.
  3421. ////////////////////////////////////////////////////////////////////////////
  3422. UINT GetMacCodePage()
  3423. {
  3424. PKEY_VALUE_FULL_INFORMATION pKeyValueFull; // ptr to query information
  3425. BYTE pStatic[MAX_KEY_VALUE_FULLINFO]; // ptr to static buffer
  3426. UNICODE_STRING ObUnicodeStr; // unicode string
  3427. UINT CodePage; // code page value
  3428. PCP_HASH pHashN; // ptr to hash node
  3429. //
  3430. // See if the Mac code page globals have been initialized yet.
  3431. // If they have, return the mac code page value.
  3432. //
  3433. if (gMacCodePage != 0)
  3434. {
  3435. return (gMacCodePage);
  3436. }
  3437. //
  3438. // Make sure code page key is open.
  3439. //
  3440. OPEN_CODEPAGE_KEY(NLS_DEFAULT_MACCP);
  3441. //
  3442. // Query the registry for the Mac CP value.
  3443. //
  3444. CodePage = 0;
  3445. pKeyValueFull = (PKEY_VALUE_FULL_INFORMATION)pStatic;
  3446. if ((QueryRegValue( hCodePageKey,
  3447. NLS_VALUE_MACCP,
  3448. &pKeyValueFull,
  3449. MAX_KEY_VALUE_FULLINFO,
  3450. NULL )) == NO_ERROR)
  3451. {
  3452. //
  3453. // Convert the value to an integer.
  3454. //
  3455. RtlInitUnicodeString(&ObUnicodeStr, GET_VALUE_DATA_PTR(pKeyValueFull));
  3456. if (RtlUnicodeStringToInteger(&ObUnicodeStr, 10, (PULONG)&CodePage))
  3457. {
  3458. CodePage = 0;
  3459. }
  3460. }
  3461. //
  3462. // Make sure the CodePage value was set.
  3463. //
  3464. if (CodePage == 0)
  3465. {
  3466. //
  3467. // Registry value is corrupt, so use default Mac code page.
  3468. //
  3469. CodePage = NLS_DEFAULT_MACCP;
  3470. }
  3471. //
  3472. // Get the hash node for the Mac code page.
  3473. //
  3474. pHashN = GetCPHashNode(CodePage);
  3475. //
  3476. // Make sure the Mac hash node is valid.
  3477. //
  3478. if (pHashN == NULL)
  3479. {
  3480. //
  3481. // Invalid hash node, which means either the registry is
  3482. // corrupt, or setup failed to install a file. Use the
  3483. // Ansi code page values.
  3484. //
  3485. CodePage = gAnsiCodePage;
  3486. pHashN = gpACPHashN;
  3487. }
  3488. //
  3489. // Set the final MAC CP values.
  3490. //
  3491. RtlEnterCriticalSection(&gcsTblPtrs);
  3492. if (gMacCodePage == 0)
  3493. {
  3494. gpMACCPHashN = pHashN;
  3495. gMacCodePage = CodePage;
  3496. }
  3497. RtlLeaveCriticalSection(&gcsTblPtrs);
  3498. //
  3499. // Return the Mac code page value.
  3500. //
  3501. return (gMacCodePage);
  3502. }
  3503. ////////////////////////////////////////////////////////////////////////////
  3504. //
  3505. // SpecialMBToWC
  3506. //
  3507. // Maps a multibyte character string to its wide character string
  3508. // counterpart.
  3509. //
  3510. // 08-21-95 JulieB Created.
  3511. ////////////////////////////////////////////////////////////////////////////
  3512. int SpecialMBToWC(
  3513. PCP_HASH pHashN,
  3514. DWORD dwFlags,
  3515. LPCSTR lpMultiByteStr,
  3516. int cbMultiByte,
  3517. LPWSTR lpWideCharStr,
  3518. int cchWideChar)
  3519. {
  3520. register LPBYTE pMBStr; // ptr to search through MB string
  3521. register LPWSTR pWCStr; // ptr to search through WC string
  3522. LPBYTE pEndMBStr; // ptr to end of MB search string
  3523. LPWSTR pEndWCStr; // ptr to end of WC string buffer
  3524. int mbIncr; // amount to increment pMBStr
  3525. int wcCount = 0; // count of wide chars written
  3526. PMB_TABLE pMBTbl; // ptr to MB table
  3527. int ctr; // loop counter
  3528. //
  3529. // Initialize multibyte character loop pointers.
  3530. //
  3531. pMBStr = (LPBYTE)lpMultiByteStr;
  3532. pEndMBStr = pMBStr + cbMultiByte;
  3533. //
  3534. // Get the MB table.
  3535. //
  3536. pMBTbl = pHashN->pMBTbl;
  3537. //
  3538. // If cchWideChar is 0, then we can't use lpWideCharStr. In this
  3539. // case, we simply want to count the number of characters that would
  3540. // be written to the buffer.
  3541. //
  3542. if (cchWideChar == 0)
  3543. {
  3544. //
  3545. // For each multibyte char, translate it to its corresponding
  3546. // wide char and increment the wide character count.
  3547. //
  3548. if (IS_SBCS_CP(pHashN))
  3549. {
  3550. //
  3551. // Single Byte Character Code Page.
  3552. //
  3553. wcCount = (int)(pEndMBStr - pMBStr);
  3554. }
  3555. else
  3556. {
  3557. //
  3558. // Multi Byte Character Code Page.
  3559. //
  3560. WCHAR pTempStr[MAX_COMPOSITE]; // tmp buffer
  3561. pEndWCStr = pTempStr + MAX_COMPOSITE;
  3562. while (pMBStr < pEndMBStr)
  3563. {
  3564. GET_WC_MULTI( pHashN,
  3565. pMBTbl,
  3566. pMBStr,
  3567. pEndMBStr,
  3568. pTempStr,
  3569. pEndWCStr,
  3570. mbIncr );
  3571. pMBStr += mbIncr;
  3572. wcCount++;
  3573. }
  3574. }
  3575. }
  3576. else
  3577. {
  3578. //
  3579. // Initialize wide character loop pointers.
  3580. //
  3581. pWCStr = lpWideCharStr;
  3582. pEndWCStr = pWCStr + cchWideChar;
  3583. //
  3584. // For each multibyte char, translate it to its corresponding
  3585. // wide char, store it in lpWideCharStr, and increment the wide
  3586. // character count.
  3587. //
  3588. if (IS_SBCS_CP(pHashN))
  3589. {
  3590. //
  3591. // Single Byte Character Code Page.
  3592. //
  3593. wcCount = (int)(pEndMBStr - pMBStr);
  3594. if ((pEndWCStr - pWCStr) < wcCount)
  3595. {
  3596. wcCount = (int)(pEndWCStr - pWCStr);
  3597. }
  3598. if (dwFlags & MB_INVALID_CHAR_CHECK)
  3599. {
  3600. //
  3601. // Error check flag is set.
  3602. //
  3603. for (ctr = wcCount; ctr > 0; ctr--)
  3604. {
  3605. GET_WC_SINGLE_SPECIAL( pHashN,
  3606. pMBTbl,
  3607. pMBStr,
  3608. pWCStr );
  3609. pMBStr++;
  3610. pWCStr++;
  3611. }
  3612. }
  3613. else
  3614. {
  3615. //
  3616. // Error check flag is NOT set.
  3617. //
  3618. for (ctr = wcCount; ctr > 0; ctr--)
  3619. {
  3620. GET_WC_SINGLE( pMBTbl,
  3621. pMBStr,
  3622. pWCStr );
  3623. pMBStr++;
  3624. pWCStr++;
  3625. }
  3626. }
  3627. }
  3628. else
  3629. {
  3630. //
  3631. // Multi Byte Character Code Page.
  3632. //
  3633. if (dwFlags & MB_INVALID_CHAR_CHECK)
  3634. {
  3635. //
  3636. // Error check flag is set.
  3637. //
  3638. while ((pMBStr < pEndMBStr) && (pWCStr < pEndWCStr))
  3639. {
  3640. GET_WC_MULTI_ERR_SPECIAL( pHashN,
  3641. pMBTbl,
  3642. pMBStr,
  3643. pEndMBStr,
  3644. pWCStr,
  3645. pEndWCStr,
  3646. mbIncr );
  3647. pMBStr += mbIncr;
  3648. pWCStr++;
  3649. }
  3650. wcCount = (int)(pWCStr - lpWideCharStr);
  3651. }
  3652. else
  3653. {
  3654. //
  3655. // Error check flag is NOT set.
  3656. //
  3657. while ((pMBStr < pEndMBStr) && (pWCStr < pEndWCStr))
  3658. {
  3659. GET_WC_MULTI( pHashN,
  3660. pMBTbl,
  3661. pMBStr,
  3662. pEndMBStr,
  3663. pWCStr,
  3664. pEndWCStr,
  3665. mbIncr );
  3666. pMBStr += mbIncr;
  3667. pWCStr++;
  3668. }
  3669. wcCount = (int)(pWCStr - lpWideCharStr);
  3670. }
  3671. }
  3672. //
  3673. // Make sure wide character buffer was large enough.
  3674. //
  3675. if (pMBStr < pEndMBStr)
  3676. {
  3677. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  3678. return (0);
  3679. }
  3680. }
  3681. //
  3682. // Return the number of characters written (or that would have
  3683. // been written) to the buffer.
  3684. //
  3685. return (wcCount);
  3686. }