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

2596 lines
73 KiB

  1. /*++
  2. Copyright (c) 1991-2000, Microsoft Corporation All rights reserved.
  3. Module Name:
  4. ansi.c
  5. Abstract:
  6. This file contains the ANSI versions of the NLS API functions.
  7. APIs found in this file:
  8. CompareStringA
  9. LCMapStringA
  10. GetLocaleInfoA
  11. SetLocaleInfoA
  12. GetCalendarInfoA
  13. SetCalendarInfoA
  14. GetTimeFormatA
  15. GetDateFormatA
  16. GetNumberFormatA
  17. GetCurrencyFormatA
  18. EnumCalendarInfoA
  19. EnumCalendarInfoExA
  20. EnumTimeFormatsA
  21. EnumDateFormatsA
  22. EnumDateFormatsExA
  23. GetStringTypeExA
  24. GetStringTypeA
  25. FoldStringA
  26. EnumSystemLanguageGroupsA
  27. EnumLanguageGroupLocalesA
  28. EnumUILanguagesA
  29. EnumSystemLocalesA
  30. EnumSystemCodePagesA
  31. GetCPInfoExA
  32. GetGeoInfoA
  33. Revision History:
  34. 11-10-93 JulieB Created.
  35. 07-03-00 lguindon Began GEO API port
  36. --*/
  37. //
  38. // Include Files.
  39. //
  40. #include "nls.h"
  41. //
  42. // Forward Declarations.
  43. //
  44. PCP_HASH
  45. NlsGetACPFromLocale(
  46. LCID Locale,
  47. DWORD dwFlags);
  48. BOOL
  49. NlsAnsiToUnicode(
  50. PCP_HASH pHashN,
  51. DWORD dwFlags,
  52. LPCSTR pAnsiBuffer,
  53. int AnsiLength,
  54. LPWSTR *ppUnicodeBuffer,
  55. int *pUnicodeLength);
  56. int
  57. NlsUnicodeToAnsi(
  58. PCP_HASH pHashN,
  59. LPCWSTR pUnicodeBuffer,
  60. int UnicodeLength,
  61. LPSTR pAnsiBuffer,
  62. int AnsiLength);
  63. BOOL
  64. NlsEnumUnicodeToAnsi(
  65. PCP_HASH pHashN,
  66. LPCWSTR pUnicodeBuffer,
  67. LPSTR *ppAnsiBuffer);
  68. //-------------------------------------------------------------------------//
  69. // API ROUTINES //
  70. //-------------------------------------------------------------------------//
  71. ////////////////////////////////////////////////////////////////////////////
  72. //
  73. // CompareStringA
  74. //
  75. // Compares two wide character strings of the same locale according to the
  76. // supplied locale handle.
  77. //
  78. // 11-10-93 JulieB Created.
  79. ////////////////////////////////////////////////////////////////////////////
  80. int WINAPI CompareStringA(
  81. LCID Locale,
  82. DWORD dwCmpFlags,
  83. LPCSTR lpString1,
  84. int cchCount1,
  85. LPCSTR lpString2,
  86. int cchCount2)
  87. {
  88. PCP_HASH pHashN; // ptr to CP hash node
  89. WCHAR pSTmp1[MAX_STRING_LEN]; // tmp Unicode buffer (string 1)
  90. WCHAR pSTmp2[MAX_STRING_LEN]; // tmp Unicode buffer (string 2)
  91. LPWSTR pUnicode1; // ptr to unicode string 1
  92. LPWSTR pUnicode2; // ptr to unicode string 2
  93. int UnicodeLength1; // length of Unicode string 1
  94. int UnicodeLength2; // length of Unicode string 2
  95. int ResultLen; // result length
  96. BOOL fUseNegCounts = (cchCount1 < 0 && cchCount2 < 0); // flag to use negative counts
  97. //
  98. // Invalid Parameter Check:
  99. // - Get the code page hash node for the given locale.
  100. // - either string is null
  101. //
  102. pHashN = NlsGetACPFromLocale(Locale, dwCmpFlags);
  103. if ((pHashN == NULL) ||
  104. (lpString1 == NULL) || (lpString2 == NULL))
  105. {
  106. SetLastError(ERROR_INVALID_PARAMETER);
  107. return (0);
  108. }
  109. //
  110. // Invalid Flags Check:
  111. // - invalid flags
  112. //
  113. if (dwCmpFlags & CS_INVALID_FLAG)
  114. {
  115. SetLastError(ERROR_INVALID_FLAGS);
  116. return (0);
  117. }
  118. //
  119. // Convert Ansi string 1 to Unicode.
  120. //
  121. pUnicode1 = pSTmp1;
  122. if (!NlsAnsiToUnicode( pHashN,
  123. 0,
  124. lpString1,
  125. cchCount1,
  126. &pUnicode1,
  127. &UnicodeLength1 ))
  128. {
  129. return (0);
  130. }
  131. //
  132. // Convert Ansi string 2 to Unicode.
  133. //
  134. pUnicode2 = pSTmp2;
  135. if (!NlsAnsiToUnicode( pHashN,
  136. 0,
  137. lpString2,
  138. cchCount2,
  139. &pUnicode2,
  140. &UnicodeLength2 ))
  141. {
  142. NLS_FREE_TMP_BUFFER(pUnicode1, pSTmp1);
  143. return (0);
  144. }
  145. //
  146. // Call the W version of the API.
  147. //
  148. ResultLen = CompareStringW( Locale,
  149. dwCmpFlags,
  150. pUnicode1,
  151. (fUseNegCounts) ? -1 : UnicodeLength1,
  152. pUnicode2,
  153. (fUseNegCounts) ? -1 : UnicodeLength2 );
  154. //
  155. // Free the allocated source buffers (if they were allocated).
  156. //
  157. NLS_FREE_TMP_BUFFER(pUnicode1, pSTmp1);
  158. NLS_FREE_TMP_BUFFER(pUnicode2, pSTmp2);
  159. //
  160. // Return the result of the call to CompareStringW.
  161. //
  162. return (ResultLen);
  163. }
  164. ////////////////////////////////////////////////////////////////////////////
  165. //
  166. // LCMapStringA
  167. //
  168. // Maps one wide character string to another performing the specified
  169. // translation. This mapping routine only takes flags that are locale
  170. // dependent.
  171. //
  172. // 11-10-93 JulieB Created.
  173. ////////////////////////////////////////////////////////////////////////////
  174. int WINAPI LCMapStringA(
  175. LCID Locale,
  176. DWORD dwMapFlags,
  177. LPCSTR lpSrcStr,
  178. int cchSrc,
  179. LPSTR lpDestStr,
  180. int cchDest)
  181. {
  182. PCP_HASH pHashN; // ptr to CP hash node
  183. LPWSTR pUnicode; // ptr to unicode string
  184. int UnicodeLength; // length of Unicode string
  185. WCHAR pSTmp[MAX_STRING_LEN]; // tmp Unicode buffer (source)
  186. WCHAR pDTmp[MAX_STRING_LEN]; // tmp Unicode buffer (destination)
  187. LPWSTR pBuf; // ptr to destination buffer
  188. int ResultLen; // result length
  189. //
  190. // Get the code page hash node for the given locale.
  191. //
  192. pHashN = NlsGetACPFromLocale(Locale, dwMapFlags);
  193. //
  194. // Invalid Parameter Check:
  195. // - valid code page
  196. // - destination buffer size is negative
  197. // - length of dest string is NOT zero AND dest string is NULL
  198. // - same buffer - src = destination
  199. // if not UPPER or LOWER or
  200. // UPPER or LOWER used with Japanese flags
  201. //
  202. if ((pHashN == NULL) ||
  203. (cchDest < 0) ||
  204. ((cchDest != 0) && (lpDestStr == NULL)) ||
  205. ((lpSrcStr == lpDestStr) &&
  206. ((!(dwMapFlags & (LCMAP_UPPERCASE | LCMAP_LOWERCASE))) ||
  207. (dwMapFlags & (LCMAP_HIRAGANA | LCMAP_KATAKANA |
  208. LCMAP_HALFWIDTH | LCMAP_FULLWIDTH)))))
  209. {
  210. SetLastError(ERROR_INVALID_PARAMETER);
  211. return (0);
  212. }
  213. //
  214. // Convert Ansi string to Unicode.
  215. //
  216. pUnicode = pSTmp;
  217. if (!NlsAnsiToUnicode( pHashN,
  218. 0,
  219. lpSrcStr,
  220. cchSrc,
  221. &pUnicode,
  222. &UnicodeLength ))
  223. {
  224. return (0);
  225. }
  226. //
  227. // Special case the sortkey flag, since the Unicode buffer does
  228. // NOT need to be converted back to Ansi.
  229. //
  230. if (dwMapFlags & LCMAP_SORTKEY)
  231. {
  232. //
  233. // Call the W version of the API.
  234. //
  235. ResultLen = LCMapStringW( Locale,
  236. dwMapFlags,
  237. pUnicode,
  238. UnicodeLength,
  239. (LPWSTR)lpDestStr,
  240. cchDest );
  241. //
  242. // Free the allocated source buffer (if one was allocated).
  243. //
  244. NLS_FREE_TMP_BUFFER(pUnicode, pSTmp);
  245. //
  246. // Return the result of LCMapStringW.
  247. //
  248. return (ResultLen);
  249. }
  250. //
  251. // Call the W version of the API.
  252. //
  253. pBuf = pDTmp;
  254. ResultLen = MAX_STRING_LEN;
  255. while (1)
  256. {
  257. ResultLen = LCMapStringW( Locale,
  258. dwMapFlags,
  259. pUnicode,
  260. UnicodeLength,
  261. pBuf,
  262. ResultLen );
  263. //
  264. // Make sure the static buffer was large enough.
  265. //
  266. if ((ResultLen != 0) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
  267. {
  268. break;
  269. }
  270. //
  271. // Get the size of the buffer needed for the mapping.
  272. //
  273. if (ResultLen = LCMapStringW( Locale,
  274. dwMapFlags,
  275. pUnicode,
  276. UnicodeLength,
  277. NULL,
  278. 0 ))
  279. {
  280. //
  281. // Allocate a buffer of the appropriate size.
  282. //
  283. if ((pBuf = (LPWSTR)NLS_ALLOC_MEM(ResultLen * sizeof(WCHAR))) == NULL)
  284. {
  285. NLS_FREE_TMP_BUFFER(pUnicode, pSTmp);
  286. SetLastError(ERROR_OUTOFMEMORY);
  287. return (0);
  288. }
  289. }
  290. }
  291. //
  292. // Free the allocated source buffer (if one was allocated).
  293. //
  294. NLS_FREE_TMP_BUFFER(pUnicode, pSTmp);
  295. //
  296. // Convert the destination Unicode buffer to the given Ansi buffer.
  297. //
  298. if (ResultLen > 0)
  299. {
  300. ResultLen = NlsUnicodeToAnsi( pHashN,
  301. pBuf,
  302. ResultLen,
  303. lpDestStr,
  304. cchDest );
  305. }
  306. //
  307. // Free the allocated destination buffer (if one was allocated).
  308. //
  309. NLS_FREE_TMP_BUFFER(pBuf, pDTmp);
  310. //
  311. // Return the result of the call to LCMapStringW.
  312. //
  313. return (ResultLen);
  314. }
  315. ////////////////////////////////////////////////////////////////////////////
  316. //
  317. // GetLocaleInfoA
  318. //
  319. // Returns one of the various pieces of information about a particular
  320. // locale by querying the configuration registry. This call also indicates
  321. // how much memory is necessary to contain the desired information.
  322. //
  323. // 11-10-93 JulieB Created.
  324. ////////////////////////////////////////////////////////////////////////////
  325. int WINAPI GetLocaleInfoA(
  326. LCID Locale,
  327. LCTYPE LCType,
  328. LPSTR lpLCData,
  329. int cchData)
  330. {
  331. PCP_HASH pHashN; // ptr to CP hash node
  332. WCHAR pDTmp[MAX_STRING_LEN]; // tmp Unicode buffer (destination)
  333. LPWSTR pBuf; // ptr to destination buffer
  334. int ResultLen; // result length
  335. //
  336. // Invalid Parameter Check:
  337. // - count is negative
  338. // - NULL data pointer AND count is not zero
  339. //
  340. if ((cchData < 0) ||
  341. (lpLCData == NULL) && (cchData != 0))
  342. {
  343. SetLastError(ERROR_INVALID_PARAMETER);
  344. return (0);
  345. }
  346. //
  347. // Call the W version of the API.
  348. //
  349. pBuf = pDTmp;
  350. ResultLen = MAX_STRING_LEN;
  351. while (1)
  352. {
  353. ResultLen = GetLocaleInfoW( Locale,
  354. LCType,
  355. pBuf,
  356. ResultLen );
  357. //
  358. // Make sure the static buffer was large enough.
  359. //
  360. if ((ResultLen != 0) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
  361. {
  362. break;
  363. }
  364. //
  365. // Get the size of the buffer needed for the mapping.
  366. //
  367. if (ResultLen = GetLocaleInfoW( Locale,
  368. LCType,
  369. NULL,
  370. 0 ))
  371. {
  372. //
  373. // Allocate a buffer of the appropriate size.
  374. //
  375. if ((pBuf = (LPWSTR)NLS_ALLOC_MEM(ResultLen * sizeof(WCHAR))) == NULL)
  376. {
  377. SetLastError(ERROR_OUTOFMEMORY);
  378. return (0);
  379. }
  380. }
  381. }
  382. //
  383. // Convert the destination Unicode buffer to the given Ansi buffer.
  384. //
  385. if (ResultLen > 0)
  386. {
  387. if ((LCType & LOCALE_RETURN_NUMBER) ||
  388. (NLS_GET_LCTYPE_VALUE(LCType) == LOCALE_FONTSIGNATURE))
  389. {
  390. //
  391. // For the font signature and number value, the result length
  392. // will actually be twice the amount of the wide char version.
  393. //
  394. ResultLen *= 2;
  395. //
  396. // Make sure we can use the buffer.
  397. //
  398. if (cchData)
  399. {
  400. //
  401. // Make sure the buffer is large enough.
  402. //
  403. if (cchData < ResultLen)
  404. {
  405. //
  406. // The buffer is too small.
  407. //
  408. NLS_FREE_TMP_BUFFER(pBuf, pDTmp);
  409. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  410. return (0);
  411. }
  412. //
  413. // Convert the font signature or number value to its byte
  414. // form. Since it's already byte reversed, just do a move
  415. // memory.
  416. //
  417. RtlMoveMemory(lpLCData, pBuf, ResultLen);
  418. }
  419. }
  420. else
  421. {
  422. //
  423. // If this is LCTYPE == LOCALE_SLANGUAGE, then use the
  424. // CP_ACP of the system. This is what Win9x has done,
  425. // and we need to be compatible with this.
  426. //
  427. if (NLS_GET_LCTYPE_VALUE(LCType) == LOCALE_SLANGUAGE)
  428. {
  429. LCType |= LOCALE_USE_CP_ACP;
  430. }
  431. //
  432. // Get the code page hash node for the given locale.
  433. //
  434. pHashN = NlsGetACPFromLocale(Locale, LCType);
  435. if (pHashN == NULL)
  436. {
  437. ResultLen = 0;
  438. }
  439. else
  440. {
  441. //
  442. // Convert to Ansi.
  443. //
  444. ResultLen = NlsUnicodeToAnsi( pHashN,
  445. pBuf,
  446. ResultLen,
  447. lpLCData,
  448. cchData );
  449. }
  450. }
  451. }
  452. //
  453. // Free the allocated destination buffer (if one was allocated).
  454. //
  455. NLS_FREE_TMP_BUFFER(pBuf, pDTmp);
  456. //
  457. // Return the result of the call to GetLocaleInfoW.
  458. //
  459. return (ResultLen);
  460. }
  461. ////////////////////////////////////////////////////////////////////////////
  462. //
  463. // SetLocaleInfoA
  464. //
  465. // Sets one of the various pieces of information about a particular
  466. // locale by making an entry in the user's portion of the configuration
  467. // registry. This will only affect the user override portion of the locale
  468. // settings. The system defaults will never be reset.
  469. //
  470. // 11-10-93 JulieB Created.
  471. ////////////////////////////////////////////////////////////////////////////
  472. BOOL WINAPI SetLocaleInfoA(
  473. LCID Locale,
  474. LCTYPE LCType,
  475. LPCSTR lpLCData)
  476. {
  477. PCP_HASH pHashN; // ptr to CP hash node
  478. LPWSTR pUnicode; // ptr to unicode string
  479. int UnicodeLength; // length of Unicode string
  480. WCHAR pSTmp[MAX_STRING_LEN]; // tmp Unicode buffer (source)
  481. BOOL Result; // result
  482. //
  483. // Get the code page hash node for the given locale.
  484. //
  485. pHashN = NlsGetACPFromLocale(Locale, LCType);
  486. if (pHashN == NULL)
  487. {
  488. return (0);
  489. }
  490. //
  491. // Convert Ansi string to Unicode.
  492. //
  493. pUnicode = pSTmp;
  494. if (!NlsAnsiToUnicode( pHashN,
  495. 0,
  496. lpLCData,
  497. -1,
  498. &pUnicode,
  499. &UnicodeLength ))
  500. {
  501. return (FALSE);
  502. }
  503. //
  504. // Call the W version of the API.
  505. //
  506. Result = SetLocaleInfoW( Locale,
  507. LCType,
  508. pUnicode );
  509. //
  510. // Free the allocated source buffer (if one was allocated).
  511. //
  512. NLS_FREE_TMP_BUFFER(pUnicode, pSTmp);
  513. //
  514. // Return the result of the call to SetLocaleInfoW.
  515. //
  516. return (Result);
  517. }
  518. ////////////////////////////////////////////////////////////////////////////
  519. //
  520. // GetCalendarInfoA
  521. //
  522. // Returns one of the various pieces of information about a particular
  523. // calendar by querying the configuration registry. This call also indicates
  524. // how much memory is necessary to contain the desired information.
  525. //
  526. // 12-17-97 JulieB Created.
  527. ////////////////////////////////////////////////////////////////////////////
  528. int WINAPI GetCalendarInfoA(
  529. LCID Locale,
  530. CALID Calendar,
  531. CALTYPE CalType,
  532. LPSTR lpCalData,
  533. int cchData,
  534. LPDWORD lpValue)
  535. {
  536. PCP_HASH pHashN; // ptr to CP hash node
  537. WCHAR pDTmp[MAX_STRING_LEN]; // tmp Unicode buffer (destination)
  538. LPWSTR pBuf; // ptr to destination buffer
  539. int ResultLen; // result length
  540. //
  541. // Invalid Parameter Check:
  542. // - count is negative
  543. // - NULL data pointer AND count is not zero
  544. //
  545. if ((cchData < 0) ||
  546. ((lpCalData == NULL) && (cchData != 0)))
  547. {
  548. SetLastError(ERROR_INVALID_PARAMETER);
  549. return (0);
  550. }
  551. //
  552. // Need to check the parameters based on the CAL_RETURN_NUMBER
  553. // CalType.
  554. //
  555. if (CalType & CAL_RETURN_NUMBER)
  556. {
  557. if ((lpCalData != NULL) || (cchData != 0) || (lpValue == NULL))
  558. {
  559. SetLastError(ERROR_INVALID_PARAMETER);
  560. return (0);
  561. }
  562. }
  563. else
  564. {
  565. if ((lpValue != NULL) ||
  566. (cchData < 0) ||
  567. ((lpCalData == NULL) && (cchData != 0)))
  568. {
  569. SetLastError(ERROR_INVALID_PARAMETER);
  570. return (0);
  571. }
  572. }
  573. //
  574. // Call the W version of the API.
  575. //
  576. pBuf = pDTmp;
  577. ResultLen = MAX_STRING_LEN;
  578. while (1)
  579. {
  580. ResultLen = GetCalendarInfoW( Locale,
  581. Calendar,
  582. CalType,
  583. lpCalData ? pBuf : NULL,
  584. lpCalData ? ResultLen : 0,
  585. lpValue );
  586. //
  587. // Make sure the static buffer was large enough.
  588. //
  589. if ((ResultLen != 0) ||
  590. (lpValue != NULL) ||
  591. (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
  592. {
  593. break;
  594. }
  595. //
  596. // Get the size of the buffer needed for the mapping.
  597. //
  598. if (ResultLen = GetCalendarInfoW( Locale,
  599. Calendar,
  600. CalType,
  601. NULL,
  602. 0,
  603. NULL ))
  604. {
  605. //
  606. // Allocate a buffer of the appropriate size.
  607. //
  608. if ((pBuf = (LPWSTR)NLS_ALLOC_MEM(ResultLen * sizeof(WCHAR))) == NULL)
  609. {
  610. SetLastError(ERROR_OUTOFMEMORY);
  611. return (0);
  612. }
  613. }
  614. }
  615. //
  616. // Convert the destination Unicode buffer to the given Ansi buffer.
  617. //
  618. if (ResultLen > 0)
  619. {
  620. if (CalType & CAL_RETURN_NUMBER)
  621. {
  622. //
  623. // For the number value, the result length will actually be
  624. // twice the amount of the wide char version.
  625. //
  626. ResultLen *= 2;
  627. //
  628. // There is nothing else to do in this case, since the value
  629. // has already been stored in lpValue.
  630. //
  631. }
  632. else
  633. {
  634. //
  635. // Get the code page hash node for the given locale.
  636. //
  637. pHashN = NlsGetACPFromLocale(Locale, CalType);
  638. if (pHashN == NULL)
  639. {
  640. ResultLen = 0;
  641. }
  642. else
  643. {
  644. //
  645. // Convert to Ansi.
  646. //
  647. ResultLen = NlsUnicodeToAnsi( pHashN,
  648. pBuf,
  649. ResultLen,
  650. lpCalData,
  651. cchData );
  652. }
  653. }
  654. }
  655. //
  656. // Free the allocated destination buffer (if one was allocated).
  657. //
  658. NLS_FREE_TMP_BUFFER(pBuf, pDTmp);
  659. //
  660. // Return the result of the call to GetCalendarInfoW.
  661. //
  662. return (ResultLen);
  663. }
  664. ////////////////////////////////////////////////////////////////////////////
  665. //
  666. // SetCalendarInfoA
  667. //
  668. // Sets one of the various pieces of information about a particular
  669. // calendar by making an entry in the user's portion of the configuration
  670. // registry. This will only affect the user override portion of the
  671. // calendar settings. The system defaults will never be reset.
  672. //
  673. // 12-17-97 JulieB Created.
  674. ////////////////////////////////////////////////////////////////////////////
  675. BOOL WINAPI SetCalendarInfoA(
  676. LCID Locale,
  677. CALID Calendar,
  678. CALTYPE CalType,
  679. LPCSTR lpCalData)
  680. {
  681. PCP_HASH pHashN; // ptr to CP hash node
  682. LPWSTR pUnicode; // ptr to unicode string
  683. int UnicodeLength; // length of Unicode string
  684. WCHAR pSTmp[MAX_STRING_LEN]; // tmp Unicode buffer (source)
  685. BOOL Result; // result
  686. //
  687. // Get the code page hash node for the given locale.
  688. //
  689. pHashN = NlsGetACPFromLocale(Locale, CalType);
  690. if (pHashN == NULL)
  691. {
  692. return (0);
  693. }
  694. //
  695. // Convert Ansi string to Unicode.
  696. //
  697. pUnicode = pSTmp;
  698. if (!NlsAnsiToUnicode( pHashN,
  699. 0,
  700. lpCalData,
  701. -1,
  702. &pUnicode,
  703. &UnicodeLength ))
  704. {
  705. return (FALSE);
  706. }
  707. //
  708. // Call the W version of the API.
  709. //
  710. Result = SetCalendarInfoW( Locale,
  711. Calendar,
  712. CalType,
  713. pUnicode );
  714. //
  715. // Free the allocated source buffer (if one was allocated).
  716. //
  717. NLS_FREE_TMP_BUFFER(pUnicode, pSTmp);
  718. //
  719. // Return the result of the call to SetCalendarInfoW.
  720. //
  721. return (Result);
  722. }
  723. ////////////////////////////////////////////////////////////////////////////
  724. //
  725. // GetTimeFormatA
  726. //
  727. // Returns a properly formatted time string for the given locale. It uses
  728. // either the system time or the specified time. This call also indicates
  729. // how much memory is necessary to contain the desired information.
  730. //
  731. // 11-10-93 JulieB Created.
  732. ////////////////////////////////////////////////////////////////////////////
  733. int WINAPI GetTimeFormatA(
  734. LCID Locale,
  735. DWORD dwFlags,
  736. CONST SYSTEMTIME *lpTime,
  737. LPCSTR lpFormat,
  738. LPSTR lpTimeStr,
  739. int cchTime)
  740. {
  741. PCP_HASH pHashN; // ptr to CP hash node
  742. LPWSTR pUnicode; // ptr to unicode string
  743. int UnicodeLength; // length of Unicode string
  744. WCHAR pSTmp[MAX_STRING_LEN]; // tmp Unicode buffer (source)
  745. WCHAR pDTmp[MAX_STRING_LEN]; // tmp Unicode buffer (destination)
  746. LPWSTR pBuf; // ptr to destination buffer
  747. int ResultLen; // result length
  748. //
  749. // Get the code page hash node for the given locale.
  750. //
  751. pHashN = NlsGetACPFromLocale(Locale, dwFlags);
  752. //
  753. // Invalid Parameter Check:
  754. // - valid code page
  755. // - count is negative
  756. // - NULL data pointer AND count is not zero
  757. //
  758. if ((pHashN == NULL) ||
  759. (cchTime < 0) ||
  760. ((lpTimeStr == NULL) && (cchTime != 0)))
  761. {
  762. SetLastError(ERROR_INVALID_PARAMETER);
  763. return (0);
  764. }
  765. //
  766. // Convert Ansi string to Unicode.
  767. //
  768. pUnicode = pSTmp;
  769. if (!NlsAnsiToUnicode( pHashN,
  770. 0,
  771. lpFormat,
  772. -1,
  773. &pUnicode,
  774. &UnicodeLength ))
  775. {
  776. return (0);
  777. }
  778. //
  779. // Call the W version of the API.
  780. //
  781. pBuf = pDTmp;
  782. ResultLen = MAX_STRING_LEN;
  783. while (1)
  784. {
  785. ResultLen = GetTimeFormatW( Locale,
  786. dwFlags,
  787. lpTime,
  788. pUnicode,
  789. pBuf,
  790. ResultLen );
  791. //
  792. // Make sure the static buffer was large enough.
  793. //
  794. if ((ResultLen != 0) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
  795. {
  796. break;
  797. }
  798. //
  799. // Get the size of the buffer needed for the mapping.
  800. //
  801. if (ResultLen = GetTimeFormatW( Locale,
  802. dwFlags,
  803. lpTime,
  804. pUnicode,
  805. NULL,
  806. 0 ))
  807. {
  808. //
  809. // Allocate a buffer of the appropriate size.
  810. //
  811. if ((pBuf = (LPWSTR)NLS_ALLOC_MEM(ResultLen * sizeof(WCHAR))) == NULL)
  812. {
  813. NLS_FREE_TMP_BUFFER(pUnicode, pSTmp);
  814. SetLastError(ERROR_OUTOFMEMORY);
  815. return (0);
  816. }
  817. }
  818. }
  819. //
  820. // Free the allocated source buffer (if one was allocated).
  821. //
  822. NLS_FREE_TMP_BUFFER(pUnicode, pSTmp);
  823. //
  824. // Convert the destination Unicode buffer to the given Ansi buffer.
  825. //
  826. if (ResultLen > 0)
  827. {
  828. ResultLen = NlsUnicodeToAnsi( pHashN,
  829. pBuf,
  830. ResultLen,
  831. lpTimeStr,
  832. cchTime );
  833. }
  834. //
  835. // Free the allocated destination buffer (if one was allocated).
  836. //
  837. NLS_FREE_TMP_BUFFER(pBuf, pDTmp);
  838. //
  839. // Return the result of the call to GetTimeFormatW.
  840. //
  841. return (ResultLen);
  842. }
  843. ////////////////////////////////////////////////////////////////////////////
  844. //
  845. // GetDateFormatA
  846. //
  847. // Returns a properly formatted date string for the given locale. It uses
  848. // either the system date or the specified date. The user may specify
  849. // the short date format, the long date format, or the year/month format.
  850. // This call also indicates how much memory is necessary to contain the
  851. // desired information.
  852. //
  853. // 11-10-93 JulieB Created.
  854. ////////////////////////////////////////////////////////////////////////////
  855. int WINAPI GetDateFormatA(
  856. LCID Locale,
  857. DWORD dwFlags,
  858. CONST SYSTEMTIME *lpDate,
  859. LPCSTR lpFormat,
  860. LPSTR lpDateStr,
  861. int cchDate)
  862. {
  863. PCP_HASH pHashN; // ptr to CP hash node
  864. LPWSTR pUnicode; // ptr to unicode string
  865. int UnicodeLength; // length of Unicode string
  866. WCHAR pSTmp[MAX_STRING_LEN]; // tmp Unicode buffer (source)
  867. WCHAR pDTmp[MAX_STRING_LEN]; // tmp Unicode buffer (destination)
  868. LPWSTR pBuf; // ptr to destination buffer
  869. int ResultLen; // result length
  870. //
  871. // Get the code page hash node for the given locale.
  872. //
  873. pHashN = NlsGetACPFromLocale(Locale, dwFlags);
  874. //
  875. // Invalid Parameter Check:
  876. // - valid code page
  877. // - count is negative
  878. // - NULL data pointer AND count is not zero
  879. //
  880. if ((pHashN == NULL) ||
  881. (cchDate < 0) ||
  882. ((lpDateStr == NULL) && (cchDate != 0)))
  883. {
  884. SetLastError(ERROR_INVALID_PARAMETER);
  885. return (0);
  886. }
  887. //
  888. // Invalid Flags Check:
  889. // - flags other than valid ones
  890. // - more than one of either ltr reading or rtl reading
  891. // - using LTR or RTL flag and not using cp 1255 or 1256
  892. //
  893. if ((dwFlags & GDF_INVALID_FLAG) ||
  894. (MORE_THAN_ONE(dwFlags, GDF_SINGLE_FLAG)) ||
  895. ((dwFlags & (DATE_LTRREADING | DATE_RTLREADING)) &&
  896. (pHashN->CodePage != 1255) && (pHashN->CodePage != 1256)))
  897. {
  898. SetLastError(ERROR_INVALID_FLAGS);
  899. return (0);
  900. }
  901. //
  902. // Convert Ansi string to Unicode.
  903. //
  904. pUnicode = pSTmp;
  905. if (!NlsAnsiToUnicode( pHashN,
  906. 0,
  907. lpFormat,
  908. -1,
  909. &pUnicode,
  910. &UnicodeLength ))
  911. {
  912. return (0);
  913. }
  914. //
  915. // Call the W version of the API.
  916. //
  917. pBuf = pDTmp;
  918. ResultLen = MAX_STRING_LEN;
  919. while (1)
  920. {
  921. ResultLen = GetDateFormatW( Locale,
  922. dwFlags,
  923. lpDate,
  924. pUnicode,
  925. pBuf,
  926. ResultLen );
  927. //
  928. // Make sure the static buffer was large enough.
  929. //
  930. if ((ResultLen != 0) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
  931. {
  932. break;
  933. }
  934. //
  935. // Get the size of the buffer needed for the mapping.
  936. //
  937. if (ResultLen = GetDateFormatW( Locale,
  938. dwFlags,
  939. lpDate,
  940. pUnicode,
  941. NULL,
  942. 0 ))
  943. {
  944. //
  945. // Allocate a buffer of the appropriate size.
  946. //
  947. if ((pBuf = (LPWSTR)NLS_ALLOC_MEM(ResultLen * sizeof(WCHAR))) == NULL)
  948. {
  949. NLS_FREE_TMP_BUFFER(pUnicode, pSTmp);
  950. SetLastError(ERROR_OUTOFMEMORY);
  951. return (0);
  952. }
  953. }
  954. }
  955. //
  956. // Free the allocated source buffer (if one was allocated).
  957. //
  958. NLS_FREE_TMP_BUFFER(pUnicode, pSTmp);
  959. //
  960. // Convert the destination Unicode buffer to the given Ansi buffer.
  961. //
  962. if (ResultLen > 0)
  963. {
  964. ResultLen = NlsUnicodeToAnsi( pHashN,
  965. pBuf,
  966. ResultLen,
  967. lpDateStr,
  968. cchDate );
  969. }
  970. //
  971. // Free the allocated destination buffer (if one was allocated).
  972. //
  973. NLS_FREE_TMP_BUFFER(pBuf, pDTmp);
  974. //
  975. // Return the result of the call to GetDateFormatW.
  976. //
  977. return (ResultLen);
  978. }
  979. ////////////////////////////////////////////////////////////////////////////
  980. //
  981. // GetNumberFormatA
  982. //
  983. // Returns a properly formatted number string for the given locale.
  984. // This call also indicates how much memory is necessary to contain
  985. // the desired information.
  986. //
  987. // 11-10-93 JulieB Created.
  988. ////////////////////////////////////////////////////////////////////////////
  989. int WINAPI GetNumberFormatA(
  990. LCID Locale,
  991. DWORD dwFlags,
  992. LPCSTR lpValue,
  993. CONST NUMBERFMTA *lpFormat,
  994. LPSTR lpNumberStr,
  995. int cchNumber)
  996. {
  997. PCP_HASH pHashN; // ptr to CP hash node
  998. LPWSTR pValueU; // ptr to unicode string
  999. int UnicodeLength; // length of Unicode string
  1000. WCHAR pSTmp[MAX_STRING_LEN]; // tmp Unicode buffer (source)
  1001. WCHAR pDTmp[MAX_STRING_LEN]; // tmp Unicode buffer (destination)
  1002. LPWSTR pBuf; // ptr to destination buffer
  1003. int ResultLen; // result length
  1004. NUMBERFMTW FormatU; // Unicode number format
  1005. LPNUMBERFMTW pFormatU = NULL; // ptr to Unicode number format
  1006. //
  1007. // Get the code page hash node for the given locale.
  1008. //
  1009. pHashN = NlsGetACPFromLocale(Locale, dwFlags);
  1010. //
  1011. // Invalid Parameter Check:
  1012. // - valid code page
  1013. // - count is negative
  1014. // - NULL data pointer AND count is not zero
  1015. // - ptrs to string buffers same
  1016. //
  1017. if ((pHashN == NULL) ||
  1018. (cchNumber < 0) ||
  1019. ((lpNumberStr == NULL) && (cchNumber != 0)) ||
  1020. (lpValue == lpNumberStr))
  1021. {
  1022. SetLastError(ERROR_INVALID_PARAMETER);
  1023. return (0);
  1024. }
  1025. //
  1026. // Convert Ansi string to Unicode.
  1027. //
  1028. pValueU = pSTmp;
  1029. if (!NlsAnsiToUnicode( pHashN,
  1030. 0,
  1031. lpValue,
  1032. -1,
  1033. &pValueU,
  1034. &UnicodeLength ))
  1035. {
  1036. return (0);
  1037. }
  1038. //
  1039. // If the format structure exists, convert the strings
  1040. // in the structure.
  1041. //
  1042. if (lpFormat)
  1043. {
  1044. //
  1045. // Copy Ansi structure to Unicode structure.
  1046. //
  1047. FormatU = *(NUMBERFMTW *)lpFormat;
  1048. FormatU.lpDecimalSep = NULL;
  1049. FormatU.lpThousandSep = NULL;
  1050. //
  1051. // Convert Ansi strings in structure to Unicode strings.
  1052. //
  1053. if (!NlsAnsiToUnicode( pHashN,
  1054. 0,
  1055. lpFormat->lpDecimalSep,
  1056. -1,
  1057. &(FormatU.lpDecimalSep),
  1058. &UnicodeLength ) ||
  1059. !NlsAnsiToUnicode( pHashN,
  1060. 0,
  1061. lpFormat->lpThousandSep,
  1062. -1,
  1063. &(FormatU.lpThousandSep),
  1064. &UnicodeLength ))
  1065. {
  1066. NLS_FREE_TMP_BUFFER(pValueU, pSTmp);
  1067. NLS_FREE_MEM(FormatU.lpDecimalSep);
  1068. return (0);
  1069. }
  1070. pFormatU = &FormatU;
  1071. }
  1072. //
  1073. // Call the W version of the API.
  1074. //
  1075. pBuf = pDTmp;
  1076. ResultLen = MAX_STRING_LEN;
  1077. while (1)
  1078. {
  1079. ResultLen = GetNumberFormatW( Locale,
  1080. dwFlags,
  1081. pValueU,
  1082. pFormatU,
  1083. pBuf,
  1084. ResultLen );
  1085. //
  1086. // Make sure the static buffer was large enough.
  1087. //
  1088. if ((ResultLen != 0) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
  1089. {
  1090. break;
  1091. }
  1092. //
  1093. // Get the size of the buffer needed for the mapping.
  1094. //
  1095. if (ResultLen = GetNumberFormatW( Locale,
  1096. dwFlags,
  1097. pValueU,
  1098. pFormatU,
  1099. NULL,
  1100. 0 ))
  1101. {
  1102. //
  1103. // Allocate a buffer of the appropriate size.
  1104. //
  1105. if ((pBuf = (LPWSTR)NLS_ALLOC_MEM(ResultLen * sizeof(WCHAR))) == NULL)
  1106. {
  1107. SetLastError(ERROR_OUTOFMEMORY);
  1108. ResultLen = 0;
  1109. break;
  1110. }
  1111. }
  1112. }
  1113. //
  1114. // Free the allocated source buffer (if one was allocated).
  1115. //
  1116. NLS_FREE_TMP_BUFFER(pValueU, pSTmp);
  1117. if (lpFormat)
  1118. {
  1119. NLS_FREE_MEM(FormatU.lpDecimalSep);
  1120. NLS_FREE_MEM(FormatU.lpThousandSep);
  1121. }
  1122. //
  1123. // Convert the destination Unicode buffer to the given Ansi buffer.
  1124. //
  1125. if (ResultLen > 0)
  1126. {
  1127. ResultLen = NlsUnicodeToAnsi( pHashN,
  1128. pBuf,
  1129. ResultLen,
  1130. lpNumberStr,
  1131. cchNumber );
  1132. }
  1133. //
  1134. // Free the allocated destination buffer (if one was allocated).
  1135. //
  1136. NLS_FREE_TMP_BUFFER(pBuf, pDTmp);
  1137. //
  1138. // Return the result of the call to GetNumberFormatW.
  1139. //
  1140. return (ResultLen);
  1141. }
  1142. ////////////////////////////////////////////////////////////////////////////
  1143. //
  1144. // GetCurrencyFormatA
  1145. //
  1146. // Returns a properly formatted currency string for the given locale.
  1147. // This call also indicates how much memory is necessary to contain
  1148. // the desired information.
  1149. //
  1150. // 11-10-93 JulieB Created.
  1151. ////////////////////////////////////////////////////////////////////////////
  1152. int WINAPI GetCurrencyFormatA(
  1153. LCID Locale,
  1154. DWORD dwFlags,
  1155. LPCSTR lpValue,
  1156. CONST CURRENCYFMTA *lpFormat,
  1157. LPSTR lpCurrencyStr,
  1158. int cchCurrency)
  1159. {
  1160. PCP_HASH pHashN; // ptr to CP hash node
  1161. LPWSTR pValueU; // ptr to unicode string
  1162. int UnicodeLength; // length of Unicode string
  1163. WCHAR pSTmp[MAX_STRING_LEN]; // tmp Unicode buffer (source)
  1164. WCHAR pDTmp[MAX_STRING_LEN]; // tmp Unicode buffer (destination)
  1165. LPWSTR pBuf; // ptr to destination buffer
  1166. int ResultLen; // result length
  1167. CURRENCYFMTW FormatU; // Unicode currency format
  1168. LPCURRENCYFMTW pFormatU = NULL; // ptr to Unicode currency format
  1169. //
  1170. // Get the code page hash node for the given locale.
  1171. //
  1172. pHashN = NlsGetACPFromLocale(Locale, dwFlags);
  1173. //
  1174. // Invalid Parameter Check:
  1175. // - count is negative
  1176. // - NULL data pointer AND count is not zero
  1177. // - ptrs to string buffers same
  1178. //
  1179. if ((pHashN == NULL) ||
  1180. (cchCurrency < 0) ||
  1181. ((lpCurrencyStr == NULL) && (cchCurrency != 0)) ||
  1182. (lpValue == lpCurrencyStr))
  1183. {
  1184. SetLastError(ERROR_INVALID_PARAMETER);
  1185. return (0);
  1186. }
  1187. //
  1188. // Convert Ansi string to Unicode.
  1189. //
  1190. pValueU = pSTmp;
  1191. if (!NlsAnsiToUnicode( pHashN,
  1192. 0,
  1193. lpValue,
  1194. -1,
  1195. &pValueU,
  1196. &UnicodeLength ))
  1197. {
  1198. return (0);
  1199. }
  1200. //
  1201. // If the format structure exists, convert the strings
  1202. // in the structure.
  1203. //
  1204. if (lpFormat)
  1205. {
  1206. //
  1207. // Copy Ansi structure to Unicode structure.
  1208. //
  1209. FormatU = *(CURRENCYFMTW *)lpFormat;
  1210. FormatU.lpDecimalSep = NULL;
  1211. FormatU.lpThousandSep = NULL;
  1212. FormatU.lpCurrencySymbol = NULL;
  1213. //
  1214. // Convert Ansi strings in structure to Unicode strings.
  1215. //
  1216. if (!NlsAnsiToUnicode( pHashN,
  1217. 0,
  1218. lpFormat->lpDecimalSep,
  1219. -1,
  1220. &(FormatU.lpDecimalSep),
  1221. &UnicodeLength ) ||
  1222. !NlsAnsiToUnicode( pHashN,
  1223. 0,
  1224. lpFormat->lpThousandSep,
  1225. -1,
  1226. &(FormatU.lpThousandSep),
  1227. &UnicodeLength ) ||
  1228. !NlsAnsiToUnicode( pHashN,
  1229. 0,
  1230. lpFormat->lpCurrencySymbol,
  1231. -1,
  1232. &(FormatU.lpCurrencySymbol),
  1233. &UnicodeLength ))
  1234. {
  1235. NLS_FREE_TMP_BUFFER(pValueU, pSTmp);
  1236. NLS_FREE_MEM(FormatU.lpDecimalSep);
  1237. NLS_FREE_MEM(FormatU.lpThousandSep);
  1238. return (0);
  1239. }
  1240. pFormatU = &FormatU;
  1241. }
  1242. //
  1243. // Call the W version of the API.
  1244. //
  1245. pBuf = pDTmp;
  1246. ResultLen = MAX_STRING_LEN;
  1247. while (1)
  1248. {
  1249. ResultLen = GetCurrencyFormatW( Locale,
  1250. dwFlags,
  1251. pValueU,
  1252. pFormatU,
  1253. pBuf,
  1254. ResultLen );
  1255. //
  1256. // Make sure the static buffer was large enough.
  1257. //
  1258. if ((ResultLen != 0) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
  1259. {
  1260. break;
  1261. }
  1262. //
  1263. // Get the size of the buffer needed for the mapping.
  1264. //
  1265. if (ResultLen = GetCurrencyFormatW( Locale,
  1266. dwFlags,
  1267. pValueU,
  1268. pFormatU,
  1269. NULL,
  1270. 0 ))
  1271. {
  1272. //
  1273. // Allocate a buffer of the appropriate size.
  1274. //
  1275. if ((pBuf = (LPWSTR)NLS_ALLOC_MEM(ResultLen * sizeof(WCHAR))) == NULL)
  1276. {
  1277. SetLastError(ERROR_OUTOFMEMORY);
  1278. ResultLen = 0;
  1279. break;
  1280. }
  1281. }
  1282. }
  1283. //
  1284. // Free the allocated source buffer (if one was allocated).
  1285. //
  1286. NLS_FREE_TMP_BUFFER(pValueU, pSTmp);
  1287. if (lpFormat)
  1288. {
  1289. NLS_FREE_MEM(FormatU.lpDecimalSep);
  1290. NLS_FREE_MEM(FormatU.lpThousandSep);
  1291. NLS_FREE_MEM(FormatU.lpCurrencySymbol);
  1292. }
  1293. //
  1294. // Convert the destination Unicode buffer to the given Ansi buffer.
  1295. //
  1296. if (ResultLen > 0)
  1297. {
  1298. ResultLen = NlsUnicodeToAnsi( pHashN,
  1299. pBuf,
  1300. ResultLen,
  1301. lpCurrencyStr,
  1302. cchCurrency );
  1303. }
  1304. //
  1305. // Free the allocated destination buffer (if one was allocated).
  1306. //
  1307. NLS_FREE_TMP_BUFFER(pBuf, pDTmp);
  1308. //
  1309. // Return the result of the call to GetCurrencyFormatW.
  1310. //
  1311. return (ResultLen);
  1312. }
  1313. ////////////////////////////////////////////////////////////////////////////
  1314. //
  1315. // EnumCalendarInfoA
  1316. //
  1317. // Enumerates the specified calendar information that is available for the
  1318. // specified locale, based on the CalType parameter. It does so by
  1319. // passing the pointer to the string buffer containing the calendar info
  1320. // to an application-defined callback function. It continues until the
  1321. // last calendar info is found or the callback function returns FALSE.
  1322. //
  1323. // 11-10-93 JulieB Created.
  1324. ////////////////////////////////////////////////////////////////////////////
  1325. BOOL WINAPI EnumCalendarInfoA(
  1326. CALINFO_ENUMPROCA lpCalInfoEnumProc,
  1327. LCID Locale,
  1328. CALID Calendar,
  1329. CALTYPE CalType)
  1330. {
  1331. return (Internal_EnumCalendarInfo( (NLS_ENUMPROC)lpCalInfoEnumProc,
  1332. Locale,
  1333. Calendar,
  1334. CalType,
  1335. FALSE,
  1336. FALSE ));
  1337. }
  1338. ////////////////////////////////////////////////////////////////////////////
  1339. //
  1340. // EnumCalendarInfoExA
  1341. //
  1342. // Enumerates the specified calendar information that is available for the
  1343. // specified locale, based on the CalType parameter. It does so by
  1344. // passing the pointer to the string buffer containing the calendar info
  1345. // and the calendar id to an application-defined callback function. It
  1346. // continues until the last calendar info is found or the callback function
  1347. // returns FALSE.
  1348. //
  1349. // 10-14-96 JulieB Created.
  1350. ////////////////////////////////////////////////////////////////////////////
  1351. BOOL WINAPI EnumCalendarInfoExA(
  1352. CALINFO_ENUMPROCEXA lpCalInfoEnumProcEx,
  1353. LCID Locale,
  1354. CALID Calendar,
  1355. CALTYPE CalType)
  1356. {
  1357. return (Internal_EnumCalendarInfo( (NLS_ENUMPROC)lpCalInfoEnumProcEx,
  1358. Locale,
  1359. Calendar,
  1360. CalType,
  1361. FALSE,
  1362. TRUE ));
  1363. }
  1364. ////////////////////////////////////////////////////////////////////////////
  1365. //
  1366. // EnumTimeFormatsA
  1367. //
  1368. // Enumerates the time formats that are available for the
  1369. // specified locale, based on the dwFlags parameter. It does so by
  1370. // passing the pointer to the string buffer containing the time format
  1371. // to an application-defined callback function. It continues until the
  1372. // last time format is found or the callback function returns FALSE.
  1373. //
  1374. // 11-10-93 JulieB Created.
  1375. ////////////////////////////////////////////////////////////////////////////
  1376. BOOL WINAPI EnumTimeFormatsA(
  1377. TIMEFMT_ENUMPROCA lpTimeFmtEnumProc,
  1378. LCID Locale,
  1379. DWORD dwFlags)
  1380. {
  1381. return (Internal_EnumTimeFormats( (NLS_ENUMPROC)lpTimeFmtEnumProc,
  1382. Locale,
  1383. dwFlags,
  1384. FALSE ));
  1385. }
  1386. ////////////////////////////////////////////////////////////////////////////
  1387. //
  1388. // EnumDateFormatsA
  1389. //
  1390. // Enumerates the short date, long date, or year/month formats that are
  1391. // available for the specified locale, based on the dwFlags parameter.
  1392. // It does so by passing the pointer to the string buffer containing the
  1393. // date format to an application-defined callback function. It continues
  1394. // until the last date format is found or the callback function returns
  1395. // FALSE.
  1396. //
  1397. // 11-10-93 JulieB Created.
  1398. ////////////////////////////////////////////////////////////////////////////
  1399. BOOL WINAPI EnumDateFormatsA(
  1400. DATEFMT_ENUMPROCA lpDateFmtEnumProc,
  1401. LCID Locale,
  1402. DWORD dwFlags)
  1403. {
  1404. return (Internal_EnumDateFormats( (NLS_ENUMPROC)lpDateFmtEnumProc,
  1405. Locale,
  1406. dwFlags,
  1407. FALSE,
  1408. FALSE ));
  1409. }
  1410. ////////////////////////////////////////////////////////////////////////////
  1411. //
  1412. // EnumDateFormatsExA
  1413. //
  1414. // Enumerates the short date, long date, or year/month formats that are
  1415. // available for the specified locale, based on the dwFlags parameter.
  1416. // It does so by passing the pointer to the string buffer containing the
  1417. // date format and the calendar id to an application-defined callback
  1418. // function. It continues until the last date format is found or the
  1419. // callback function returns FALSE.
  1420. //
  1421. // 10-14-96 JulieB Created.
  1422. ////////////////////////////////////////////////////////////////////////////
  1423. BOOL WINAPI EnumDateFormatsExA(
  1424. DATEFMT_ENUMPROCEXA lpDateFmtEnumProcEx,
  1425. LCID Locale,
  1426. DWORD dwFlags)
  1427. {
  1428. return (Internal_EnumDateFormats( (NLS_ENUMPROC)lpDateFmtEnumProcEx,
  1429. Locale,
  1430. dwFlags,
  1431. FALSE,
  1432. TRUE ));
  1433. }
  1434. ////////////////////////////////////////////////////////////////////////////
  1435. //
  1436. // GetStringTypeExA
  1437. //
  1438. // Returns character type information about a particular Ansi string.
  1439. //
  1440. // 01-18-94 JulieB Created.
  1441. ////////////////////////////////////////////////////////////////////////////
  1442. BOOL WINAPI GetStringTypeExA(
  1443. LCID Locale,
  1444. DWORD dwInfoType,
  1445. LPCSTR lpSrcStr,
  1446. int cchSrc,
  1447. LPWORD lpCharType)
  1448. {
  1449. return (GetStringTypeA( Locale,
  1450. dwInfoType,
  1451. lpSrcStr,
  1452. cchSrc,
  1453. lpCharType));
  1454. }
  1455. ////////////////////////////////////////////////////////////////////////////
  1456. //
  1457. // GetStringTypeA
  1458. //
  1459. // Returns character type information about a particular Ansi string.
  1460. //
  1461. // NOTE: The number of parameters is different from GetStringTypeW.
  1462. // The 16-bit OLE product shipped this routine with the wrong
  1463. // parameters (ported from Chicago) and now we must support it.
  1464. //
  1465. // Use GetStringTypeEx to get the same set of parameters between
  1466. // the A and W version.
  1467. //
  1468. // 11-10-93 JulieB Created.
  1469. ////////////////////////////////////////////////////////////////////////////
  1470. BOOL WINAPI GetStringTypeA(
  1471. LCID Locale,
  1472. DWORD dwInfoType,
  1473. LPCSTR lpSrcStr,
  1474. int cchSrc,
  1475. LPWORD lpCharType)
  1476. {
  1477. PCP_HASH pHashCP; // ptr to CP hash node
  1478. LPWSTR pUnicode; // ptr to unicode string
  1479. int UnicodeLength; // length of Unicode string
  1480. WCHAR pSTmp[MAX_STRING_LEN]; // tmp Unicode buffer (source)
  1481. BOOL Result; // result
  1482. //
  1483. // Get the code page hash node for the given locale.
  1484. // This will also return an error if the locale id is invalid,
  1485. // so there is no need to check the locale id separately.
  1486. //
  1487. pHashCP = NlsGetACPFromLocale(Locale, 0);
  1488. //
  1489. // Invalid Parameter Check:
  1490. // - Validate LCID
  1491. // - valid code page
  1492. // - same buffer - src and destination
  1493. //
  1494. if ((pHashCP == NULL) ||
  1495. (lpSrcStr == (LPSTR)lpCharType))
  1496. {
  1497. SetLastError(ERROR_INVALID_PARAMETER);
  1498. return (0);
  1499. }
  1500. //
  1501. // Convert Ansi string to Unicode.
  1502. //
  1503. pUnicode = pSTmp;
  1504. if (!NlsAnsiToUnicode( pHashCP,
  1505. MB_INVALID_CHAR_CHECK,
  1506. lpSrcStr,
  1507. cchSrc,
  1508. &pUnicode,
  1509. &UnicodeLength ))
  1510. {
  1511. return (0);
  1512. }
  1513. //
  1514. // Call the W version of the API.
  1515. //
  1516. Result = GetStringTypeW( dwInfoType,
  1517. pUnicode,
  1518. UnicodeLength,
  1519. lpCharType );
  1520. //
  1521. // Free the allocated source buffer (if one was allocated).
  1522. //
  1523. NLS_FREE_TMP_BUFFER(pUnicode, pSTmp);
  1524. //
  1525. // Return the result of the call to GetStringTypeW.
  1526. //
  1527. return (Result);
  1528. }
  1529. ////////////////////////////////////////////////////////////////////////////
  1530. //
  1531. // FoldStringA
  1532. //
  1533. // Maps one wide character string to another performing the specified
  1534. // translation. This mapping routine only takes flags that are locale
  1535. // independent.
  1536. //
  1537. // 11-10-93 JulieB Created.
  1538. ////////////////////////////////////////////////////////////////////////////
  1539. int WINAPI FoldStringA(
  1540. DWORD dwMapFlags,
  1541. LPCSTR lpSrcStr,
  1542. int cchSrc,
  1543. LPSTR lpDestStr,
  1544. int cchDest)
  1545. {
  1546. LPWSTR pUnicode; // ptr to unicode string
  1547. int UnicodeLength; // length of Unicode string
  1548. WCHAR pSTmp[MAX_STRING_LEN]; // tmp Unicode buffer (source)
  1549. WCHAR pDTmp[MAX_STRING_LEN]; // tmp Unicode buffer (destination)
  1550. LPWSTR pBuf; // ptr to destination buffer
  1551. int ResultLen; // result length
  1552. //
  1553. // Invalid Parameter Check:
  1554. // - dest buffer size is negative
  1555. // - length of dest string is NOT zero AND dest string is NULL
  1556. // - same buffer - src = destination
  1557. //
  1558. if ((cchDest < 0) ||
  1559. ((cchDest != 0) && (lpDestStr == NULL)) ||
  1560. (lpSrcStr == lpDestStr))
  1561. {
  1562. SetLastError(ERROR_INVALID_PARAMETER);
  1563. return (0);
  1564. }
  1565. //
  1566. // Convert Ansi string to Unicode.
  1567. //
  1568. RtlZeroMemory(pSTmp, sizeof(pSTmp));
  1569. pUnicode = pSTmp;
  1570. if (!NlsAnsiToUnicode( gpACPHashN,
  1571. 0,
  1572. lpSrcStr,
  1573. cchSrc,
  1574. &pUnicode,
  1575. &UnicodeLength ))
  1576. {
  1577. return (0);
  1578. }
  1579. //
  1580. // Call the W version of the API.
  1581. //
  1582. pBuf = pDTmp;
  1583. ResultLen = MAX_STRING_LEN;
  1584. while (1)
  1585. {
  1586. ResultLen = FoldStringW( dwMapFlags,
  1587. pUnicode,
  1588. UnicodeLength,
  1589. pBuf,
  1590. ResultLen );
  1591. //
  1592. // Make sure the static buffer was large enough.
  1593. //
  1594. if ((ResultLen != 0) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
  1595. {
  1596. break;
  1597. }
  1598. //
  1599. // Get the size of the buffer needed for the mapping.
  1600. //
  1601. if (ResultLen = FoldStringW( dwMapFlags,
  1602. pUnicode,
  1603. UnicodeLength,
  1604. NULL,
  1605. 0 ))
  1606. {
  1607. //
  1608. // Allocate a buffer of the appropriate size.
  1609. //
  1610. if ((pBuf = (LPWSTR)NLS_ALLOC_MEM(ResultLen * sizeof(WCHAR))) == NULL)
  1611. {
  1612. NLS_FREE_TMP_BUFFER(pUnicode, pSTmp);
  1613. SetLastError(ERROR_OUTOFMEMORY);
  1614. return (0);
  1615. }
  1616. }
  1617. }
  1618. //
  1619. // Free the allocated source buffer (if one was allocated).
  1620. //
  1621. NLS_FREE_TMP_BUFFER(pUnicode, pSTmp);
  1622. //
  1623. // Convert the destination Unicode buffer to the given Ansi buffer.
  1624. //
  1625. if (ResultLen > 0)
  1626. {
  1627. ResultLen = NlsUnicodeToAnsi( gpACPHashN,
  1628. pBuf,
  1629. ResultLen,
  1630. lpDestStr,
  1631. cchDest );
  1632. }
  1633. //
  1634. // Free the allocated destination buffer (if one was allocated).
  1635. //
  1636. NLS_FREE_TMP_BUFFER(pBuf, pDTmp);
  1637. //
  1638. // Return the result of the call to FoldStringW.
  1639. //
  1640. return (ResultLen);
  1641. }
  1642. ////////////////////////////////////////////////////////////////////////////
  1643. //
  1644. // EnumSystemLanguageGroupsA
  1645. //
  1646. // Enumerates the system language groups that are installed or supported,
  1647. // based on the dwFlags parameter. It does so by passing the pointer to
  1648. // the string buffer containing the language group id to an
  1649. // application-defined callback function. It continues until the last
  1650. // language group id is found or the callback function returns FALSE.
  1651. //
  1652. // 03-10-98 JulieB Created.
  1653. ////////////////////////////////////////////////////////////////////////////
  1654. BOOL WINAPI EnumSystemLanguageGroupsA(
  1655. LANGUAGEGROUP_ENUMPROCA lpLanguageGroupEnumProc,
  1656. DWORD dwFlags,
  1657. LONG_PTR lParam)
  1658. {
  1659. return (Internal_EnumSystemLanguageGroups(
  1660. (NLS_ENUMPROC)lpLanguageGroupEnumProc,
  1661. dwFlags,
  1662. lParam,
  1663. FALSE ));
  1664. }
  1665. ////////////////////////////////////////////////////////////////////////////
  1666. //
  1667. // EnumLanguageGroupLocalesA
  1668. //
  1669. // Enumerates the locales in a given language group. It does so by
  1670. // passing the appropriate information to an application-defined
  1671. // callback function. It continues until the last locale in the language
  1672. // group is found or the callback function returns FALSE.
  1673. //
  1674. // 03-10-98 JulieB Created.
  1675. ////////////////////////////////////////////////////////////////////////////
  1676. BOOL WINAPI EnumLanguageGroupLocalesA(
  1677. LANGGROUPLOCALE_ENUMPROCA lpLangGroupLocaleEnumProc,
  1678. LGRPID LanguageGroup,
  1679. DWORD dwFlags,
  1680. LONG_PTR lParam)
  1681. {
  1682. return (Internal_EnumLanguageGroupLocales(
  1683. (NLS_ENUMPROC)lpLangGroupLocaleEnumProc,
  1684. LanguageGroup,
  1685. dwFlags,
  1686. lParam,
  1687. FALSE ));
  1688. }
  1689. ////////////////////////////////////////////////////////////////////////////
  1690. //
  1691. // EnumUILanguagesA
  1692. //
  1693. // Enumerates the system UI languages that are installed. It does so by
  1694. // passing the pointer to the string buffer containing the UI language id
  1695. // to an application-defined callback function. It continues until the
  1696. // last UI language id is found or the callback function returns FALSE.
  1697. //
  1698. // 03-10-98 JulieB Created.
  1699. ////////////////////////////////////////////////////////////////////////////
  1700. BOOL WINAPI EnumUILanguagesA(
  1701. UILANGUAGE_ENUMPROCA lpUILanguageEnumProc,
  1702. DWORD dwFlags,
  1703. LONG_PTR lParam)
  1704. {
  1705. return (Internal_EnumUILanguages( (NLS_ENUMPROC)lpUILanguageEnumProc,
  1706. dwFlags,
  1707. lParam,
  1708. FALSE ));
  1709. }
  1710. ////////////////////////////////////////////////////////////////////////////
  1711. //
  1712. // EnumSystemLocalesA
  1713. //
  1714. // Enumerates the system locales that are installed or supported, based on
  1715. // the dwFlags parameter. It does so by passing the pointer to the string
  1716. // buffer containing the locale id to an application-defined callback
  1717. // function. It continues until the last locale id is found or the
  1718. // callback function returns FALSE.
  1719. //
  1720. // 11-10-93 JulieB Created.
  1721. ////////////////////////////////////////////////////////////////////////////
  1722. BOOL WINAPI EnumSystemLocalesA(
  1723. LOCALE_ENUMPROCA lpLocaleEnumProc,
  1724. DWORD dwFlags)
  1725. {
  1726. return (Internal_EnumSystemLocales( (NLS_ENUMPROC)lpLocaleEnumProc,
  1727. dwFlags,
  1728. FALSE ));
  1729. }
  1730. ////////////////////////////////////////////////////////////////////////////
  1731. //
  1732. // EnumSystemCodePagesA
  1733. //
  1734. // Enumerates the system code pages that are installed or supported, based on
  1735. // the dwFlags parameter. It does so by passing the pointer to the string
  1736. // buffer containing the code page id to an application-defined callback
  1737. // function. It continues until the last code page is found or the
  1738. // callback function returns FALSE.
  1739. //
  1740. // 11-10-93 JulieB Created.
  1741. ////////////////////////////////////////////////////////////////////////////
  1742. BOOL WINAPI EnumSystemCodePagesA(
  1743. CODEPAGE_ENUMPROCA lpCodePageEnumProc,
  1744. DWORD dwFlags)
  1745. {
  1746. return (Internal_EnumSystemCodePages( (NLS_ENUMPROC)lpCodePageEnumProc,
  1747. dwFlags,
  1748. FALSE ));
  1749. }
  1750. ////////////////////////////////////////////////////////////////////////////
  1751. //
  1752. // GetCPInfoExA
  1753. //
  1754. // Returns information about a given code page.
  1755. //
  1756. // 11-15-96 JulieB Created.
  1757. ////////////////////////////////////////////////////////////////////////////
  1758. BOOL WINAPI GetCPInfoExA(
  1759. UINT CodePage,
  1760. DWORD dwFlags,
  1761. LPCPINFOEXA lpCPInfoEx)
  1762. {
  1763. CPINFOEXW lpCPInfoExW;
  1764. BOOL rc;
  1765. //
  1766. // Invalid Parameter Check:
  1767. // - lpCPInfoEx is NULL
  1768. //
  1769. if (lpCPInfoEx == NULL)
  1770. {
  1771. SetLastError(ERROR_INVALID_PARAMETER);
  1772. return (FALSE);
  1773. }
  1774. //
  1775. // Call the W version of the API.
  1776. //
  1777. rc = GetCPInfoExW(CodePage, dwFlags, &lpCPInfoExW);
  1778. //
  1779. // Convert the code page name from Unicode to Ansi.
  1780. //
  1781. if (rc == TRUE)
  1782. {
  1783. if (!NlsUnicodeToAnsi( gpACPHashN,
  1784. lpCPInfoExW.CodePageName,
  1785. -1,
  1786. lpCPInfoEx->CodePageName,
  1787. MAX_PATH ))
  1788. {
  1789. return (FALSE);
  1790. }
  1791. }
  1792. //
  1793. // Copy the rest of the information from the Unicode buffer to the
  1794. // Ansi buffer.
  1795. //
  1796. RtlMoveMemory( lpCPInfoEx,
  1797. &lpCPInfoExW,
  1798. FIELD_OFFSET(CPINFOEXW, CodePageName) );
  1799. //
  1800. // Return the result.
  1801. //
  1802. return (rc);
  1803. }
  1804. ////////////////////////////////////////////////////////////////////////////
  1805. //
  1806. // GetGeoInfoA
  1807. //
  1808. // Wrapper funtion of GetGeoInfoW for ANSI. This function return information
  1809. // about a geographical region.
  1810. //
  1811. // 11-20-99 WeiWu Created
  1812. // 07-03-00 lguindon Began GEO API port
  1813. ////////////////////////////////////////////////////////////////////////////
  1814. int WINAPI GetGeoInfoA(
  1815. GEOID GeoId,
  1816. DWORD GeoType,
  1817. LPSTR lpGeoData,
  1818. int cchData,
  1819. LANGID LangId)
  1820. {
  1821. int iRet = 0;
  1822. //
  1823. // Create buffer initialized to zero.
  1824. //
  1825. WCHAR wszBuffer[MAX_REG_VAL_SIZE] = {0};
  1826. //
  1827. // Sanity check.
  1828. //
  1829. if ((lpGeoData == NULL) && (cchData > 0))
  1830. {
  1831. SetLastError(ERROR_INVALID_PARAMETER);
  1832. return (iRet);
  1833. }
  1834. //
  1835. // Call the unicode version.
  1836. //
  1837. iRet = GetGeoInfoW( GeoId,
  1838. GeoType,
  1839. wszBuffer,
  1840. sizeof(wszBuffer) / sizeof(WCHAR),
  1841. LangId );
  1842. //
  1843. // Convert to ANSI if we get something.
  1844. //
  1845. if (iRet)
  1846. {
  1847. iRet = WideCharToMultiByte( CP_ACP,
  1848. 0,
  1849. wszBuffer,
  1850. iRet,
  1851. lpGeoData,
  1852. cchData,
  1853. NULL,
  1854. NULL );
  1855. }
  1856. return (iRet);
  1857. }
  1858. //-------------------------------------------------------------------------//
  1859. // INTERNAL ROUTINES //
  1860. //-------------------------------------------------------------------------//
  1861. ////////////////////////////////////////////////////////////////////////////
  1862. //
  1863. // NlsGetACPFromLocale
  1864. //
  1865. // Gets the CP hash node for the default ACP of the given locale. If
  1866. // either the locale or the code page are invalid, then NULL is returned.
  1867. //
  1868. // 01-19-94 JulieB Created.
  1869. ////////////////////////////////////////////////////////////////////////////
  1870. PCP_HASH NlsGetACPFromLocale(
  1871. LCID Locale,
  1872. DWORD dwFlags)
  1873. {
  1874. PLOC_HASH pHashN; // ptr to LOC hash node
  1875. PCP_HASH pHashCP; // ptr to CP hash node
  1876. UNICODE_STRING ObUnicodeStr; // value string
  1877. UINT CodePage; // code page value
  1878. //
  1879. // See if the system ACP should be used.
  1880. //
  1881. if (dwFlags & (LOCALE_USE_CP_ACP | LOCALE_RETURN_NUMBER))
  1882. {
  1883. return (gpACPHashN);
  1884. }
  1885. //
  1886. // Get the locale hash node.
  1887. //
  1888. VALIDATE_LOCALE(Locale, pHashN, FALSE);
  1889. if (pHashN == NULL)
  1890. {
  1891. SetLastError(ERROR_INVALID_PARAMETER);
  1892. return (NULL);
  1893. }
  1894. //
  1895. // Get the ACP code page. If it's equal to CP_ACP (0), then return
  1896. // the system ACP hash node.
  1897. //
  1898. CodePage = pHashN->pLocaleFixed->DefaultACP;
  1899. if (CodePage == CP_ACP)
  1900. {
  1901. return (gpACPHashN);
  1902. }
  1903. //
  1904. // Get the CP hash node for the code page.
  1905. //
  1906. pHashCP = GetCPHashNode(CodePage);
  1907. if (pHashCP == NULL)
  1908. {
  1909. SetLastError(ERROR_INVALID_PARAMETER);
  1910. }
  1911. //
  1912. // Return the code page hash node.
  1913. //
  1914. return (pHashCP);
  1915. }
  1916. ////////////////////////////////////////////////////////////////////////////
  1917. //
  1918. // NlsAnsiToUnicode
  1919. //
  1920. // Converts an Ansi string to a Unicode string.
  1921. //
  1922. // NOTE: The Unicode buffer is allocated if the routine succeeds, so the
  1923. // caller will need to free the buffer when it is no longer needed.
  1924. //
  1925. // 11-10-93 JulieB Created.
  1926. ////////////////////////////////////////////////////////////////////////////
  1927. BOOL NlsAnsiToUnicode(
  1928. PCP_HASH pHashN,
  1929. DWORD dwFlags,
  1930. LPCSTR pAnsiBuffer,
  1931. int AnsiLength,
  1932. LPWSTR *ppUnicodeBuffer,
  1933. int *pUnicodeLength)
  1934. {
  1935. LPWSTR pUnicode; // ptr to Unicode buffer
  1936. ULONG UnicodeLength; // length of the Unicode string
  1937. int ResultLength; // result length of Unicode string
  1938. //
  1939. // Make sure the pointer passed in is not null.
  1940. //
  1941. if (pAnsiBuffer == NULL)
  1942. {
  1943. *ppUnicodeBuffer = NULL;
  1944. *pUnicodeLength = 0;
  1945. return (TRUE);
  1946. }
  1947. //
  1948. // Make sure the Ansi length is set properly (in bytes).
  1949. //
  1950. if (AnsiLength < 0)
  1951. {
  1952. AnsiLength = strlen(pAnsiBuffer) + 1;
  1953. }
  1954. //
  1955. // See if the static buffer is big enough.
  1956. //
  1957. if ((*ppUnicodeBuffer == NULL) || (AnsiLength > (MAX_STRING_LEN - 1)))
  1958. {
  1959. //
  1960. // Get the size of the Unicode string, including the
  1961. // null terminator.
  1962. //
  1963. UnicodeLength = AnsiLength;
  1964. //
  1965. // Allocate the Unicode buffer.
  1966. //
  1967. if ((pUnicode = (LPWSTR)NLS_ALLOC_MEM(
  1968. (UnicodeLength + 1) * sizeof(WCHAR) )) == NULL)
  1969. {
  1970. SetLastError(ERROR_OUTOFMEMORY);
  1971. return (FALSE);
  1972. }
  1973. }
  1974. else
  1975. {
  1976. UnicodeLength = MAX_STRING_LEN - 1;
  1977. pUnicode = *ppUnicodeBuffer;
  1978. }
  1979. //
  1980. // Make sure the length of the Ansi string is not zero.
  1981. //
  1982. if (AnsiLength == 0)
  1983. {
  1984. pUnicode[0] = 0;
  1985. *ppUnicodeBuffer = pUnicode;
  1986. *pUnicodeLength = 0;
  1987. return (TRUE);
  1988. }
  1989. //
  1990. // Convert the Ansi string to a Unicode string.
  1991. //
  1992. ResultLength = SpecialMBToWC( pHashN,
  1993. dwFlags,
  1994. pAnsiBuffer,
  1995. AnsiLength,
  1996. pUnicode,
  1997. UnicodeLength );
  1998. if (ResultLength == 0)
  1999. {
  2000. //
  2001. // Free the allocated Unicode buffer (if one was allocated).
  2002. //
  2003. NLS_FREE_TMP_BUFFER(pUnicode, *ppUnicodeBuffer);
  2004. //
  2005. // See if the failure was due to insufficient buffer size.
  2006. //
  2007. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  2008. {
  2009. //
  2010. // Get the size of the buffer needed to hold the
  2011. // Unicode string.
  2012. //
  2013. UnicodeLength = SpecialMBToWC( pHashN,
  2014. dwFlags,
  2015. pAnsiBuffer,
  2016. AnsiLength,
  2017. NULL,
  2018. 0 );
  2019. //
  2020. // Allocate the Unicode buffer.
  2021. //
  2022. if ((pUnicode = (LPWSTR)NLS_ALLOC_MEM(
  2023. (UnicodeLength + 1) * sizeof(WCHAR) )) == NULL)
  2024. {
  2025. SetLastError(ERROR_OUTOFMEMORY);
  2026. return (FALSE);
  2027. }
  2028. //
  2029. // Try the translation again.
  2030. //
  2031. ResultLength = SpecialMBToWC( pHashN,
  2032. dwFlags,
  2033. pAnsiBuffer,
  2034. AnsiLength,
  2035. pUnicode,
  2036. UnicodeLength );
  2037. }
  2038. //
  2039. // If there was still an error, return failure.
  2040. //
  2041. if (ResultLength == 0)
  2042. {
  2043. SetLastError(ERROR_INVALID_PARAMETER);
  2044. return (FALSE);
  2045. }
  2046. }
  2047. //
  2048. // Make sure there is room in the buffer for the null terminator.
  2049. //
  2050. ASSERT(ResultLength <= (int)UnicodeLength);
  2051. //
  2052. // Null terminate the string.
  2053. //
  2054. pUnicode[ResultLength] = UNICODE_NULL;
  2055. //
  2056. // Return the Unicode buffer and success.
  2057. //
  2058. *ppUnicodeBuffer = pUnicode;
  2059. *pUnicodeLength = ResultLength;
  2060. return (TRUE);
  2061. }
  2062. ////////////////////////////////////////////////////////////////////////////
  2063. //
  2064. // NlsUnicodeToAnsi
  2065. //
  2066. // Converts a Unicode string to an Ansi string.
  2067. //
  2068. // This routine does NOT allocate the Ansi buffer. Instead, it uses the
  2069. // Ansi buffer passed in (unless AnsiLength is 0) and checks for buffer
  2070. // overflow.
  2071. //
  2072. // 11-10-93 JulieB Created.
  2073. ////////////////////////////////////////////////////////////////////////////
  2074. int NlsUnicodeToAnsi(
  2075. PCP_HASH pHashN,
  2076. LPCWSTR pUnicodeBuffer,
  2077. int UnicodeLength,
  2078. LPSTR pAnsiBuffer,
  2079. int AnsiLength)
  2080. {
  2081. //
  2082. // Convert the Unicode string to an Ansi string and return the
  2083. // result. The last error will be set appropriately by
  2084. // WideCharToMultiByte.
  2085. //
  2086. return (WideCharToMultiByte( pHashN->CodePage,
  2087. 0,
  2088. pUnicodeBuffer,
  2089. UnicodeLength,
  2090. pAnsiBuffer,
  2091. AnsiLength,
  2092. NULL,
  2093. NULL ));
  2094. }
  2095. ////////////////////////////////////////////////////////////////////////////
  2096. //
  2097. // NlsEnumUnicodeToAnsi
  2098. //
  2099. // Converts a Unicode string to an Ansi string.
  2100. //
  2101. // NOTE: The Ansi buffer is allocated if the routine succeeds, so the
  2102. // caller will need to free the buffer when it is no longer needed.
  2103. //
  2104. // 11-10-93 JulieB Created.
  2105. ////////////////////////////////////////////////////////////////////////////
  2106. BOOL NlsEnumUnicodeToAnsi(
  2107. PCP_HASH pHashN,
  2108. LPCWSTR pUnicodeBuffer,
  2109. LPSTR *ppAnsiBuffer)
  2110. {
  2111. LPSTR pAnsi; // ptr to Ansi buffer
  2112. ULONG AnsiLength; // length of the Ansi string
  2113. ULONG UnicodeLength; // length of the Unicode string
  2114. ULONG ResultLength; // result length of Ansi string
  2115. //
  2116. // Get the length of the Unicode string (in bytes), including the
  2117. // null terminator.
  2118. //
  2119. UnicodeLength = NlsStrLenW(pUnicodeBuffer) + 1;
  2120. //
  2121. // Get the size of the Ansi string (in bytes), including the
  2122. // null terminator.
  2123. //
  2124. AnsiLength = UnicodeLength * sizeof(WCHAR);
  2125. //
  2126. // Allocate the Ansi buffer.
  2127. //
  2128. if ((pAnsi = (LPSTR)NLS_ALLOC_MEM(AnsiLength)) == NULL)
  2129. {
  2130. SetLastError(ERROR_OUTOFMEMORY);
  2131. return (FALSE);
  2132. }
  2133. //
  2134. // Convert the Unicode string to an Ansi string.
  2135. // It will already be null terminated.
  2136. //
  2137. ResultLength = WideCharToMultiByte( pHashN->CodePage,
  2138. 0,
  2139. pUnicodeBuffer,
  2140. UnicodeLength,
  2141. pAnsi,
  2142. AnsiLength,
  2143. NULL,
  2144. NULL );
  2145. if (ResultLength == 0)
  2146. {
  2147. //
  2148. // Free the allocated Ansi buffer.
  2149. //
  2150. NLS_FREE_MEM(pAnsi);
  2151. //
  2152. // See if the failure was due to insufficient buffer size.
  2153. //
  2154. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  2155. {
  2156. //
  2157. // Get the size of the buffer needed to hold the
  2158. // ansi string.
  2159. //
  2160. AnsiLength = WideCharToMultiByte( pHashN->CodePage,
  2161. 0,
  2162. pUnicodeBuffer,
  2163. UnicodeLength,
  2164. 0,
  2165. 0,
  2166. NULL,
  2167. NULL );
  2168. //
  2169. // Allocate the Ansi buffer.
  2170. //
  2171. if ((pAnsi = (LPSTR)NLS_ALLOC_MEM(AnsiLength)) == NULL)
  2172. {
  2173. SetLastError(ERROR_OUTOFMEMORY);
  2174. return (FALSE);
  2175. }
  2176. //
  2177. // Try the translation again.
  2178. //
  2179. ResultLength = WideCharToMultiByte( pHashN->CodePage,
  2180. 0,
  2181. pUnicodeBuffer,
  2182. UnicodeLength,
  2183. pAnsi,
  2184. AnsiLength,
  2185. NULL,
  2186. NULL );
  2187. }
  2188. //
  2189. // If there was still an error, return failure.
  2190. //
  2191. if (ResultLength == 0)
  2192. {
  2193. SetLastError(ERROR_INVALID_PARAMETER);
  2194. return (FALSE);
  2195. }
  2196. }
  2197. //
  2198. // Return the Ansi buffer and success.
  2199. //
  2200. *ppAnsiBuffer = pAnsi;
  2201. return (TRUE);
  2202. }
  2203. ////////////////////////////////////////////////////////////////////////////
  2204. //
  2205. // NlsDispatchAnsiEnumProc
  2206. //
  2207. // Converts a Unicode string to an Ansi string.
  2208. //
  2209. // 11-10-93 JulieB Created.
  2210. ////////////////////////////////////////////////////////////////////////////
  2211. BOOL NlsDispatchAnsiEnumProc(
  2212. LCID Locale,
  2213. NLS_ENUMPROC pNlsEnumProc,
  2214. DWORD dwFlags,
  2215. LPWSTR pUnicodeBuffer1,
  2216. LPWSTR pUnicodeBuffer2,
  2217. DWORD dwValue1,
  2218. DWORD dwValue2,
  2219. LONG_PTR lParam,
  2220. BOOL fVersion)
  2221. {
  2222. PCP_HASH pHashN; // ptr to CP hash node
  2223. LPSTR pAnsiBuffer1 = NULL; // ptr to ansi buffer
  2224. LPSTR pAnsiBuffer2 = NULL; // ptr to ansi buffer
  2225. BOOL rc = FALSE; // return code
  2226. //
  2227. // Get the code page hash node for the given locale.
  2228. //
  2229. pHashN = NlsGetACPFromLocale(Locale, dwFlags);
  2230. if (pHashN == NULL)
  2231. {
  2232. return (0);
  2233. }
  2234. //
  2235. // Convert the null-terminated Unicode string to a
  2236. // null-terminated Ansi string.
  2237. //
  2238. if (!NlsEnumUnicodeToAnsi( pHashN,
  2239. pUnicodeBuffer1,
  2240. &pAnsiBuffer1 ))
  2241. {
  2242. return (FALSE);
  2243. }
  2244. if ((pUnicodeBuffer2 != NULL) &&
  2245. (!NlsEnumUnicodeToAnsi( pHashN,
  2246. pUnicodeBuffer2,
  2247. &pAnsiBuffer2 )))
  2248. {
  2249. NLS_FREE_MEM(pAnsiBuffer1);
  2250. return (FALSE);
  2251. }
  2252. //
  2253. // Call the callback function.
  2254. //
  2255. switch (fVersion)
  2256. {
  2257. case ( 0 ) :
  2258. {
  2259. rc = (*pNlsEnumProc)(pAnsiBuffer1);
  2260. break;
  2261. }
  2262. case ( 1 ) :
  2263. {
  2264. rc = (*((NLS_ENUMPROCEX)pNlsEnumProc))(pAnsiBuffer1, dwValue1);
  2265. break;
  2266. }
  2267. case ( 2 ) :
  2268. {
  2269. rc = (*((NLS_ENUMPROC2)pNlsEnumProc))( dwValue1,
  2270. dwValue2,
  2271. pAnsiBuffer1,
  2272. lParam );
  2273. break;
  2274. }
  2275. case ( 3 ) :
  2276. {
  2277. rc = (*((NLS_ENUMPROC3)pNlsEnumProc))( dwValue1,
  2278. pAnsiBuffer1,
  2279. pAnsiBuffer2,
  2280. dwValue2,
  2281. lParam );
  2282. break;
  2283. }
  2284. case ( 4 ) :
  2285. {
  2286. rc = (*((NLS_ENUMPROC4)pNlsEnumProc))( pAnsiBuffer1,
  2287. lParam );
  2288. break;
  2289. }
  2290. }
  2291. //
  2292. // Free any allocated memory.
  2293. //
  2294. NLS_FREE_MEM(pAnsiBuffer1);
  2295. if (pAnsiBuffer2)
  2296. {
  2297. NLS_FREE_MEM(pAnsiBuffer2);
  2298. }
  2299. //
  2300. // Return the result.
  2301. //
  2302. return (rc);
  2303. }