Leaked source code of windows server 2003
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.

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