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.

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