Windows NT 4.0 source code leak
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.

1348 lines
46 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1991-1996, Microsoft Corporation All rights reserved.
  3. Module Name:
  4. enum.c
  5. Abstract:
  6. This file contains functions that enumerate the user's portion of the
  7. registry for installed and supported locale ids and code page ids.
  8. APIs found in this file:
  9. EnumSystemLocalesW
  10. EnumSystemCodePagesW
  11. EnumCalendarInfoW
  12. EnumTimeFormatsW
  13. EnumDateFormatsW
  14. Revision History:
  15. 08-02-93 JulieB Created.
  16. --*/
  17. //
  18. // Include Files.
  19. //
  20. #include "nls.h"
  21. //
  22. // Constant Declarations
  23. //
  24. #define ENUM_BUF_SIZE 9 // buffer size (wchar) for lcid or cpid (incl null)
  25. #define ENUM_LANG_SIZE 4 // buffer size (wchar) for lang id in registry
  26. #define ENUM_MAX_CP_SIZE 5 // max size (wchar) for cp id in registry
  27. //
  28. // Forward Declarations.
  29. //
  30. BOOL
  31. EnumDateTime(
  32. NLS_ENUMPROC lpDateTimeFmtEnumProc,
  33. LCID Locale,
  34. DWORD dwFlags,
  35. LPWSTR pValue,
  36. PLOCALE_VAR pLocaleHdr,
  37. LPWSTR pDateTime,
  38. LPWSTR pEndDateTime,
  39. ULONG CalDateOffset,
  40. ULONG EndCalDateOffset,
  41. BOOL fCalendarInfo,
  42. BOOL fUnicodeVer);
  43. //-------------------------------------------------------------------------//
  44. // INTERNAL MACROS //
  45. //-------------------------------------------------------------------------//
  46. ////////////////////////////////////////////////////////////////////////////
  47. //
  48. // NLS_CALL_ENUMPROC_BREAK
  49. //
  50. // Calls the appropriate EnumProc routine. If the fUnicodeVer flag is TRUE,
  51. // then it calls the Unicode version of the callback function. Otherwise,
  52. // it calls the Ansi dispatch routine to translate the string to Ansi and
  53. // then call the Ansi version of the callback function.
  54. //
  55. // This macro will do a break if the enumeration routine returns FALSE.
  56. //
  57. // DEFINED AS A MACRO.
  58. //
  59. // 11-10-93 JulieB Created.
  60. ////////////////////////////////////////////////////////////////////////////
  61. #define NLS_CALL_ENUMPROC_BREAK( Locale, \
  62. lpNlsEnumProc, \
  63. dwFlags, \
  64. pUnicodeBuffer, \
  65. fUnicodeVer ) \
  66. { \
  67. /* \
  68. * Call the appropriate callback function. \
  69. */ \
  70. if (fUnicodeVer) \
  71. { \
  72. /* \
  73. * Call the Unicode callback function. \
  74. */ \
  75. if (((*lpNlsEnumProc)(pUnicodeBuffer)) != TRUE) \
  76. { \
  77. break; \
  78. } \
  79. } \
  80. else \
  81. { \
  82. /* \
  83. * Call the Ansi callback function. \
  84. */ \
  85. if (NlsDispatchAnsiEnumProc( Locale, \
  86. lpNlsEnumProc, \
  87. dwFlags, \
  88. pUnicodeBuffer ) != TRUE) \
  89. { \
  90. break; \
  91. } \
  92. } \
  93. }
  94. ////////////////////////////////////////////////////////////////////////////
  95. //
  96. // NLS_CALL_ENUMPROC_TRUE
  97. //
  98. // Calls the appropriate EnumProc routine. If the fUnicodeVer flag is TRUE,
  99. // then it calls the Unicode version of the callback function. Otherwise,
  100. // it calls the Ansi dispatch routine to translate the string to Ansi and
  101. // then call the Ansi version of the callback function.
  102. //
  103. // This macro will return TRUE if the enumeration routine returns FALSE.
  104. //
  105. // DEFINED AS A MACRO.
  106. //
  107. // 11-10-93 JulieB Created.
  108. ////////////////////////////////////////////////////////////////////////////
  109. #define NLS_CALL_ENUMPROC_TRUE( Locale, \
  110. lpNlsEnumProc, \
  111. dwFlags, \
  112. pUnicodeBuffer, \
  113. fUnicodeVer ) \
  114. { \
  115. /* \
  116. * Call the appropriate callback function. \
  117. */ \
  118. if (fUnicodeVer) \
  119. { \
  120. /* \
  121. * Call the Unicode callback function. \
  122. */ \
  123. if (((*lpNlsEnumProc)(pUnicodeBuffer)) != TRUE) \
  124. { \
  125. return (TRUE); \
  126. } \
  127. } \
  128. else \
  129. { \
  130. /* \
  131. * Call the Ansi callback function. \
  132. */ \
  133. if (NlsDispatchAnsiEnumProc( Locale, \
  134. lpNlsEnumProc, \
  135. dwFlags, \
  136. pUnicodeBuffer ) != TRUE) \
  137. { \
  138. return (TRUE); \
  139. } \
  140. } \
  141. }
  142. //-------------------------------------------------------------------------//
  143. // API ROUTINES //
  144. //-------------------------------------------------------------------------//
  145. ////////////////////////////////////////////////////////////////////////////
  146. //
  147. // EnumSystemLocalesW
  148. //
  149. // Enumerates the system locales that are installed or supported, based on
  150. // the dwFlags parameter. It does so by passing the pointer to the string
  151. // buffer containing the locale id to an application-defined callback
  152. // function. It continues until the last locale id is found or the
  153. // callback function returns FALSE.
  154. //
  155. // 08-02-93 JulieB Created.
  156. ////////////////////////////////////////////////////////////////////////////
  157. BOOL WINAPI EnumSystemLocalesW(
  158. LOCALE_ENUMPROCW lpLocaleEnumProc,
  159. DWORD dwFlags)
  160. {
  161. return (Internal_EnumSystemLocales( (NLS_ENUMPROC)lpLocaleEnumProc,
  162. dwFlags,
  163. TRUE ));
  164. }
  165. ////////////////////////////////////////////////////////////////////////////
  166. //
  167. // EnumSystemCodePagesW
  168. //
  169. // Enumerates the system code pages that are installed or supported, based on
  170. // the dwFlags parameter. It does so by passing the pointer to the string
  171. // buffer containing the code page id to an application-defined callback
  172. // function. It continues until the last code page is found or the
  173. // callback function returns FALSE.
  174. //
  175. // 08-02-93 JulieB Created.
  176. ////////////////////////////////////////////////////////////////////////////
  177. BOOL WINAPI EnumSystemCodePagesW(
  178. CODEPAGE_ENUMPROCW lpCodePageEnumProc,
  179. DWORD dwFlags)
  180. {
  181. return (Internal_EnumSystemCodePages( (NLS_ENUMPROC)lpCodePageEnumProc,
  182. dwFlags,
  183. TRUE ));
  184. }
  185. ////////////////////////////////////////////////////////////////////////////
  186. //
  187. // EnumCalendarInfoW
  188. //
  189. // Enumerates the specified calendar information that is available for the
  190. // specified locale, based on the CalType parameter. It does so by
  191. // passing the pointer to the string buffer containing the calendar info
  192. // to an application-defined callback function. It continues until the
  193. // last calendar info is found or the callback function returns FALSE.
  194. //
  195. // 10-14-93 JulieB Created.
  196. ////////////////////////////////////////////////////////////////////////////
  197. BOOL WINAPI EnumCalendarInfoW(
  198. CALINFO_ENUMPROCW lpCalInfoEnumProc,
  199. LCID Locale,
  200. CALID Calendar,
  201. CALTYPE CalType)
  202. {
  203. return (Internal_EnumCalendarInfo( (NLS_ENUMPROC)lpCalInfoEnumProc,
  204. Locale,
  205. Calendar,
  206. CalType,
  207. TRUE ));
  208. }
  209. ////////////////////////////////////////////////////////////////////////////
  210. //
  211. // EnumTimeFormatsW
  212. //
  213. // Enumerates the time formats that are available for the
  214. // specified locale, based on the dwFlags parameter. It does so by
  215. // passing the pointer to the string buffer containing the time format
  216. // to an application-defined callback function. It continues until the
  217. // last time format is found or the callback function returns FALSE.
  218. //
  219. // 10-14-93 JulieB Created.
  220. ////////////////////////////////////////////////////////////////////////////
  221. BOOL WINAPI EnumTimeFormatsW(
  222. TIMEFMT_ENUMPROCW lpTimeFmtEnumProc,
  223. LCID Locale,
  224. DWORD dwFlags)
  225. {
  226. return (Internal_EnumTimeFormats( (NLS_ENUMPROC)lpTimeFmtEnumProc,
  227. Locale,
  228. dwFlags,
  229. TRUE ));
  230. }
  231. ////////////////////////////////////////////////////////////////////////////
  232. //
  233. // EnumDateFormatsW
  234. //
  235. // Enumerates the long or short date formats that are available for the
  236. // specified locale, based on the dwFlags parameter. It does so by
  237. // passing the pointer to the string buffer containing the date format
  238. // to an application-defined callback function. It continues until the
  239. // last date format is found or the callback function returns FALSE.
  240. //
  241. // 10-14-93 JulieB Created.
  242. ////////////////////////////////////////////////////////////////////////////
  243. BOOL WINAPI EnumDateFormatsW(
  244. DATEFMT_ENUMPROCW lpDateFmtEnumProc,
  245. LCID Locale,
  246. DWORD dwFlags)
  247. {
  248. return (Internal_EnumDateFormats( (NLS_ENUMPROC)lpDateFmtEnumProc,
  249. Locale,
  250. dwFlags,
  251. TRUE ));
  252. }
  253. //-------------------------------------------------------------------------//
  254. // EXTERNAL ROUTINES //
  255. //-------------------------------------------------------------------------//
  256. ////////////////////////////////////////////////////////////////////////////
  257. //
  258. // Internal_EnumSystemLocales
  259. //
  260. // Enumerates the system locales that are installed or supported, based on
  261. // the dwFlags parameter. It does so by passing the pointer to the string
  262. // buffer containing the locale id to an application-defined callback
  263. // function. It continues until the last locale id is found or the
  264. // callback function returns FALSE.
  265. //
  266. // 08-02-93 JulieB Created.
  267. ////////////////////////////////////////////////////////////////////////////
  268. BOOL Internal_EnumSystemLocales(
  269. NLS_ENUMPROC lpLocaleEnumProc,
  270. DWORD dwFlags,
  271. BOOL fUnicodeVer)
  272. {
  273. PKEY_VALUE_FULL_INFORMATION pKeyValueFull = NULL;
  274. BYTE pStatic[MAX_KEY_VALUE_FULLINFO];
  275. BOOL fInstalled; // if installed flag set
  276. ULONG Index = 0; // index for enumeration
  277. ULONG ResultLength; // # bytes written
  278. WCHAR wch; // first char of name
  279. WCHAR pBuffer[ENUM_BUF_SIZE]; // ptr to callback string buffer
  280. LPWSTR pName; // ptr to name string from registry
  281. ULONG rc = 0L; // return code
  282. //
  283. // Invalid Parameter Check:
  284. // - function pointer is null
  285. //
  286. if (lpLocaleEnumProc == NULL)
  287. {
  288. SetLastError(ERROR_INVALID_PARAMETER);
  289. return (FALSE);
  290. }
  291. //
  292. // Invalid Flags Check:
  293. // - flags other than valid ones
  294. // - more than one of either supported or installed
  295. //
  296. if ( (dwFlags & ESL_INVALID_FLAG) ||
  297. (MORE_THAN_ONE(dwFlags, ESL_SINGLE_FLAG)) )
  298. {
  299. SetLastError(ERROR_INVALID_FLAGS);
  300. return (FALSE);
  301. }
  302. //
  303. // Initialize flag option.
  304. //
  305. fInstalled = dwFlags & LCID_INSTALLED;
  306. //
  307. // Loop through the locale ids in the registry, call the function
  308. // pointer for each one that meets the flag criteria.
  309. //
  310. // End loop if either FALSE is returned from the callback function
  311. // or the end of the list is reached.
  312. //
  313. // Always need to ignore the DEFAULT entry.
  314. //
  315. OPEN_LANGUAGE_KEY(FALSE);
  316. pKeyValueFull = (PKEY_VALUE_FULL_INFORMATION)pStatic;
  317. RtlZeroMemory(pKeyValueFull, MAX_KEY_VALUE_FULLINFO);
  318. rc = NtEnumerateValueKey( hLanguageKey,
  319. Index,
  320. KeyValueFullInformation,
  321. pKeyValueFull,
  322. MAX_KEY_VALUE_FULLINFO,
  323. &ResultLength );
  324. while (rc != STATUS_NO_MORE_ENTRIES)
  325. {
  326. if (!NT_SUCCESS(rc))
  327. {
  328. //
  329. // If we get a different error, then the registry
  330. // is corrupt. Just return FALSE.
  331. //
  332. KdPrint(("NLSAPI: LCID Enumeration Error - registry corrupt. - %lx.\n",
  333. rc));
  334. SetLastError(ERROR_BADDB);
  335. return (FALSE);
  336. }
  337. //
  338. // Skip over the Default entry in the registry and any
  339. // entry that does not have data associated with it if the
  340. // LCID_INSTALLED flag is set.
  341. //
  342. pName = pKeyValueFull->Name;
  343. wch = *pName;
  344. if ( (pKeyValueFull->NameLength == (ENUM_LANG_SIZE * sizeof(WCHAR))) &&
  345. ((wch >= NLS_CHAR_ZERO) && (wch <= NLS_CHAR_NINE) ||
  346. ((wch | 0x0020) >= L'a') && ((wch | 0x0020) <= L'f')) &&
  347. (!((fInstalled) && (pKeyValueFull->DataLength < 3))) )
  348. {
  349. //
  350. // Convert the key value name (language id string) to a
  351. // locale id and store it in the callback buffer.
  352. //
  353. *pBuffer = NLS_CHAR_ZERO;
  354. *(pBuffer + 1) = NLS_CHAR_ZERO;
  355. *(pBuffer + 2) = NLS_CHAR_ZERO;
  356. *(pBuffer + 3) = NLS_CHAR_ZERO;
  357. *(pBuffer + 4) = *pName;
  358. *(pBuffer + 5) = *(pName + 1);
  359. *(pBuffer + 6) = *(pName + 2);
  360. *(pBuffer + 7) = *(pName + 3);
  361. *(pBuffer + 8) = 0;
  362. //
  363. // Call the appropriate callback function.
  364. //
  365. NLS_CALL_ENUMPROC_BREAK( gSystemLocale,
  366. lpLocaleEnumProc,
  367. dwFlags,
  368. pBuffer,
  369. fUnicodeVer );
  370. }
  371. //
  372. // Increment enumeration index value and get the next enumeration.
  373. //
  374. Index++;
  375. RtlZeroMemory(pKeyValueFull, MAX_KEY_VALUE_FULLINFO);
  376. rc = NtEnumerateValueKey( hLanguageKey,
  377. Index,
  378. KeyValueFullInformation,
  379. pKeyValueFull,
  380. MAX_KEY_VALUE_FULLINFO,
  381. &ResultLength );
  382. }
  383. //
  384. // Return success.
  385. //
  386. return (TRUE);
  387. }
  388. ////////////////////////////////////////////////////////////////////////////
  389. //
  390. // Internal_EnumSystemCodePages
  391. //
  392. // Enumerates the system code pages that are installed or supported, based on
  393. // the dwFlags parameter. It does so by passing the pointer to the string
  394. // buffer containing the code page id to an application-defined callback
  395. // function. It continues until the last code page is found or the
  396. // callback function returns FALSE.
  397. //
  398. // 08-02-93 JulieB Created.
  399. ////////////////////////////////////////////////////////////////////////////
  400. BOOL Internal_EnumSystemCodePages(
  401. NLS_ENUMPROC lpCodePageEnumProc,
  402. DWORD dwFlags,
  403. BOOL fUnicodeVer)
  404. {
  405. PKEY_VALUE_FULL_INFORMATION pKeyValueFull = NULL;
  406. BYTE pStatic[MAX_KEY_VALUE_FULLINFO];
  407. BOOL fInstalled; // if installed flag set
  408. ULONG Index = 0; // index for enumeration
  409. ULONG ResultLength; // # bytes written
  410. WCHAR wch; // first char of name
  411. LPWSTR pName; // ptr to name string from registry
  412. ULONG NameLen; // length of name string
  413. ULONG rc = 0L; // return code
  414. //
  415. // Invalid Parameter Check:
  416. // - function pointer is null
  417. //
  418. if (lpCodePageEnumProc == NULL)
  419. {
  420. SetLastError(ERROR_INVALID_PARAMETER);
  421. return (FALSE);
  422. }
  423. //
  424. // Invalid Flags Check:
  425. // - flags other than valid ones
  426. // - more than one of either supported or installed
  427. //
  428. if ( (dwFlags & ESCP_INVALID_FLAG) ||
  429. (MORE_THAN_ONE(dwFlags, ESCP_SINGLE_FLAG)) )
  430. {
  431. SetLastError(ERROR_INVALID_FLAGS);
  432. return (FALSE);
  433. }
  434. //
  435. // Initialize flag option.
  436. //
  437. fInstalled = dwFlags & CP_INSTALLED;
  438. //
  439. // Loop through the code page ids in the registry, call the function
  440. // pointer for each one that meets the flag criteria.
  441. //
  442. // End loop if either FALSE is returned from the callback function
  443. // or the end of the list is reached.
  444. //
  445. // Always need to ignore the ACP, OEMCP, MACCP, and OEMHAL entries.
  446. //
  447. OPEN_CODEPAGE_KEY(FALSE);
  448. pKeyValueFull = (PKEY_VALUE_FULL_INFORMATION)pStatic;
  449. RtlZeroMemory(pKeyValueFull, MAX_KEY_VALUE_FULLINFO);
  450. rc = NtEnumerateValueKey( hCodePageKey,
  451. Index,
  452. KeyValueFullInformation,
  453. pKeyValueFull,
  454. MAX_KEY_VALUE_FULLINFO,
  455. &ResultLength );
  456. while (rc != STATUS_NO_MORE_ENTRIES)
  457. {
  458. if (!NT_SUCCESS(rc))
  459. {
  460. //
  461. // If we get a different error, then the registry
  462. // is corrupt. Just return FALSE.
  463. //
  464. KdPrint(("NLSAPI: CP Enumeration Error - registry corrupt. - %lx.\n",
  465. rc));
  466. SetLastError(ERROR_BADDB);
  467. return (FALSE);
  468. }
  469. //
  470. // Skip over the ACP, OEMCP, MACCP, and OEMHAL entries in the
  471. // registry, and any entry that does not have data associated
  472. // with it if the CP_INSTALLED flag is set.
  473. //
  474. pName = pKeyValueFull->Name;
  475. wch = *pName;
  476. NameLen = pKeyValueFull->NameLength / sizeof(WCHAR);
  477. if ( (NameLen <= ENUM_MAX_CP_SIZE) &&
  478. (wch >= NLS_CHAR_ZERO) && (wch <= NLS_CHAR_NINE) &&
  479. (!((fInstalled) && (pKeyValueFull->DataLength < 3))) )
  480. {
  481. //
  482. // Store the code page id string in the callback buffer.
  483. //
  484. pName[NameLen] = 0;
  485. //
  486. // Call the appropriate callback function.
  487. //
  488. NLS_CALL_ENUMPROC_BREAK( gSystemLocale,
  489. lpCodePageEnumProc,
  490. dwFlags,
  491. pName,
  492. fUnicodeVer );
  493. }
  494. //
  495. // Increment enumeration index value and get the next enumeration.
  496. //
  497. Index++;
  498. RtlZeroMemory(pKeyValueFull, MAX_KEY_VALUE_FULLINFO);
  499. rc = NtEnumerateValueKey( hCodePageKey,
  500. Index,
  501. KeyValueFullInformation,
  502. pKeyValueFull,
  503. MAX_KEY_VALUE_FULLINFO,
  504. &ResultLength );
  505. }
  506. //
  507. // Return success.
  508. //
  509. return (TRUE);
  510. }
  511. ////////////////////////////////////////////////////////////////////////////
  512. //
  513. // Internal_EnumCalendarInfo
  514. //
  515. // Enumerates the specified calendar information that is available for the
  516. // specified locale, based on the CalType parameter. It does so by
  517. // passing the pointer to the string buffer containing the calendar info
  518. // to an application-defined callback function. It continues until the
  519. // last calendar info is found or the callback function returns FALSE.
  520. //
  521. // 10-14-93 JulieB Created.
  522. ////////////////////////////////////////////////////////////////////////////
  523. BOOL Internal_EnumCalendarInfo(
  524. NLS_ENUMPROC lpCalInfoEnumProc,
  525. LCID Locale,
  526. CALID Calendar,
  527. CALTYPE CalType,
  528. BOOL fUnicodeVer)
  529. {
  530. PLOC_HASH pHashN; // ptr to LOC hash node
  531. ULONG CalFieldOffset; // field offset in calendar structure
  532. ULONG EndCalFieldOffset; // field offset in calendar structure
  533. ULONG LocFieldOffset; // field offset in locale structure
  534. ULONG EndLocFieldOffset; // field offset in locale structure
  535. LPWSTR pOptCal; // ptr to optional calendar values
  536. LPWSTR pEndOptCal; // ptr to end of optional calendars
  537. PCAL_INFO pCalInfo; // ptr to calendar info
  538. BOOL fIfName = FALSE; // if caltype is a name
  539. UINT fEra = 0; // if era caltype
  540. LPWSTR pString; // ptr to enumeration string
  541. LPWSTR pEndString; // ptr to end of enumeration string
  542. CALID CalNum; // calendar number
  543. DWORD UseCPACP; // original caltype - if use system ACP
  544. //
  545. // Invalid Parameter Check:
  546. // - validate LCID
  547. // - function pointer is null
  548. //
  549. // - CalType will be checked in switch statement below.
  550. //
  551. VALIDATE_LOCALE(Locale, pHashN);
  552. if ((pHashN == NULL) || (lpCalInfoEnumProc == NULL))
  553. {
  554. SetLastError(ERROR_INVALID_PARAMETER);
  555. return (FALSE);
  556. }
  557. //
  558. // Initialize the pointers to the optional calendar data.
  559. //
  560. pOptCal = (LPWORD)(pHashN->pLocaleHdr) + pHashN->pLocaleHdr->IOptionalCal;
  561. pEndOptCal = (LPWORD)(pHashN->pLocaleHdr) + pHashN->pLocaleHdr->SDayName1;
  562. //
  563. // Validate the Calendar parameter and reset the optional calendar
  564. // data pointers if necessary.
  565. //
  566. if (Calendar != ENUM_ALL_CALENDARS)
  567. {
  568. if ((pOptCal = IsValidCalendarType(pHashN, Calendar)) == NULL)
  569. {
  570. SetLastError(ERROR_INVALID_PARAMETER);
  571. return (FALSE);
  572. }
  573. pEndOptCal = pOptCal + ((POPT_CAL)pOptCal)->Offset;
  574. }
  575. //
  576. // Enumerate the information based on CalType.
  577. //
  578. UseCPACP = (DWORD)CalType;
  579. CalType &= (~LOCALE_USE_CP_ACP);
  580. switch (CalType)
  581. {
  582. case ( CAL_ICALINTVALUE ) :
  583. {
  584. //
  585. // Get the integer value for each of the alternate
  586. // calendars (as a string).
  587. //
  588. while (pOptCal < pEndOptCal)
  589. {
  590. if (((POPT_CAL)pOptCal)->CalId != CAL_NO_OPTIONAL)
  591. {
  592. //
  593. // Call the appropriate callback function.
  594. //
  595. NLS_CALL_ENUMPROC_TRUE( Locale,
  596. lpCalInfoEnumProc,
  597. UseCPACP,
  598. ((POPT_CAL)pOptCal)->pCalStr,
  599. fUnicodeVer );
  600. }
  601. //
  602. // Advance ptr to next optional calendar.
  603. //
  604. pOptCal += ((POPT_CAL)pOptCal)->Offset;
  605. }
  606. return (TRUE);
  607. break;
  608. }
  609. case ( CAL_SCALNAME ) :
  610. {
  611. //
  612. // Get the calendar name for each of the alternate
  613. // calendars.
  614. //
  615. while (pOptCal < pEndOptCal)
  616. {
  617. if (((POPT_CAL)pOptCal)->CalId != CAL_NO_OPTIONAL)
  618. {
  619. //
  620. // Call the appropriate callback function.
  621. //
  622. NLS_CALL_ENUMPROC_TRUE(
  623. Locale,
  624. lpCalInfoEnumProc,
  625. UseCPACP,
  626. ((POPT_CAL)pOptCal)->pCalStr +
  627. NlsStrLenW(((POPT_CAL)pOptCal)->pCalStr) + 1,
  628. fUnicodeVer );
  629. }
  630. //
  631. // Advance ptr to next optional calendar.
  632. //
  633. pOptCal += ((POPT_CAL)pOptCal)->Offset;
  634. }
  635. return (TRUE);
  636. break;
  637. }
  638. case ( CAL_IYEAROFFSETRANGE ) :
  639. case ( CAL_SERASTRING ) :
  640. {
  641. fEra = CalType;
  642. CalFieldOffset = FIELD_OFFSET(CALENDAR_VAR, SEraRanges);
  643. EndCalFieldOffset = FIELD_OFFSET(CALENDAR_VAR, SShortDate);
  644. break;
  645. }
  646. case ( CAL_SSHORTDATE ) :
  647. {
  648. CalFieldOffset = FIELD_OFFSET(CALENDAR_VAR, SShortDate);
  649. EndCalFieldOffset = FIELD_OFFSET(CALENDAR_VAR, SLongDate);
  650. LocFieldOffset = FIELD_OFFSET(LOCALE_VAR, SShortDate);
  651. EndLocFieldOffset = FIELD_OFFSET(LOCALE_VAR, SDate);
  652. break;
  653. }
  654. case ( CAL_SLONGDATE ) :
  655. {
  656. CalFieldOffset = FIELD_OFFSET(CALENDAR_VAR, SLongDate);
  657. EndCalFieldOffset = FIELD_OFFSET(CALENDAR_VAR, SDayName1);
  658. LocFieldOffset = FIELD_OFFSET(LOCALE_VAR, SLongDate);
  659. EndLocFieldOffset = FIELD_OFFSET(LOCALE_VAR, IOptionalCal);
  660. break;
  661. }
  662. case ( CAL_SDAYNAME1 ) :
  663. case ( CAL_SDAYNAME2 ) :
  664. case ( CAL_SDAYNAME3 ) :
  665. case ( CAL_SDAYNAME4 ) :
  666. case ( CAL_SDAYNAME5 ) :
  667. case ( CAL_SDAYNAME6 ) :
  668. case ( CAL_SDAYNAME7 ) :
  669. case ( CAL_SABBREVDAYNAME1 ) :
  670. case ( CAL_SABBREVDAYNAME2 ) :
  671. case ( CAL_SABBREVDAYNAME3 ) :
  672. case ( CAL_SABBREVDAYNAME4 ) :
  673. case ( CAL_SABBREVDAYNAME5 ) :
  674. case ( CAL_SABBREVDAYNAME6 ) :
  675. case ( CAL_SABBREVDAYNAME7 ) :
  676. case ( CAL_SMONTHNAME1 ) :
  677. case ( CAL_SMONTHNAME2 ) :
  678. case ( CAL_SMONTHNAME3 ) :
  679. case ( CAL_SMONTHNAME4 ) :
  680. case ( CAL_SMONTHNAME5 ) :
  681. case ( CAL_SMONTHNAME6 ) :
  682. case ( CAL_SMONTHNAME7 ) :
  683. case ( CAL_SMONTHNAME8 ) :
  684. case ( CAL_SMONTHNAME9 ) :
  685. case ( CAL_SMONTHNAME10 ) :
  686. case ( CAL_SMONTHNAME11 ) :
  687. case ( CAL_SMONTHNAME12 ) :
  688. case ( CAL_SMONTHNAME13 ) :
  689. case ( CAL_SABBREVMONTHNAME1 ) :
  690. case ( CAL_SABBREVMONTHNAME2 ) :
  691. case ( CAL_SABBREVMONTHNAME3 ) :
  692. case ( CAL_SABBREVMONTHNAME4 ) :
  693. case ( CAL_SABBREVMONTHNAME5 ) :
  694. case ( CAL_SABBREVMONTHNAME6 ) :
  695. case ( CAL_SABBREVMONTHNAME7 ) :
  696. case ( CAL_SABBREVMONTHNAME8 ) :
  697. case ( CAL_SABBREVMONTHNAME9 ) :
  698. case ( CAL_SABBREVMONTHNAME10 ) :
  699. case ( CAL_SABBREVMONTHNAME11 ) :
  700. case ( CAL_SABBREVMONTHNAME12 ) :
  701. case ( CAL_SABBREVMONTHNAME13 ) :
  702. {
  703. fIfName = TRUE;
  704. CalFieldOffset = FIELD_OFFSET(CALENDAR_VAR, SDayName1) +
  705. ((CalType - CAL_SDAYNAME1) * sizeof(WORD));
  706. EndCalFieldOffset = FIELD_OFFSET(CALENDAR_VAR, SDayName1) +
  707. ((CalType - CAL_SDAYNAME1 + 1) * sizeof(WORD));
  708. LocFieldOffset = FIELD_OFFSET(LOCALE_VAR, SDayName1) +
  709. ((CalType - CAL_SDAYNAME1) * sizeof(WORD));
  710. EndLocFieldOffset = FIELD_OFFSET(LOCALE_VAR, SDayName1) +
  711. ((CalType - CAL_SDAYNAME1 + 1) * sizeof(WORD));
  712. break;
  713. }
  714. default :
  715. {
  716. SetLastError(ERROR_INVALID_FLAGS);
  717. return (FALSE);
  718. }
  719. }
  720. //
  721. // Get the requested information for each of the alternate calendars.
  722. //
  723. // This loop is used for the following CalTypes:
  724. //
  725. // iYearOffsetRange (fEra = TRUE)
  726. // sEraString (fEra = TRUE)
  727. //
  728. // sShortDate
  729. // sLongDate
  730. //
  731. // sDayName1-7 (fIfName = TRUE)
  732. // sAbbrevDayName1-7 (fIfName = TRUE)
  733. // sMonthName1-7 (fIfName = TRUE)
  734. // sAbbrevMonthName1-7 (fIfName = TRUE)
  735. //
  736. while (pOptCal < pEndOptCal)
  737. {
  738. //
  739. // Get the pointer to the appropriate calendar.
  740. //
  741. CalNum = ((POPT_CAL)pOptCal)->CalId;
  742. if (GetCalendar(CalNum, &pCalInfo) == NO_ERROR)
  743. {
  744. //
  745. // Check era information flag.
  746. //
  747. if (fEra)
  748. {
  749. //
  750. // Get the pointer to the appropriate calendar string.
  751. //
  752. pString = (LPWORD)pCalInfo +
  753. *((LPWORD)((LPBYTE)(pCalInfo) + CalFieldOffset));
  754. pEndString = (LPWORD)pCalInfo +
  755. *((LPWORD)((LPBYTE)(pCalInfo) + EndCalFieldOffset));
  756. //
  757. // Make sure the string is NOT empty.
  758. //
  759. if (*pString)
  760. {
  761. //
  762. // See which era information to get.
  763. //
  764. if (fEra == CAL_IYEAROFFSETRANGE)
  765. {
  766. while (pString < pEndString)
  767. {
  768. //
  769. // Call the appropriate callback function.
  770. //
  771. NLS_CALL_ENUMPROC_TRUE(
  772. Locale,
  773. lpCalInfoEnumProc,
  774. UseCPACP,
  775. ((PERA_RANGE)pString)->pYearStr,
  776. fUnicodeVer );
  777. //
  778. // Advance pointer to next era range.
  779. //
  780. pString += ((PERA_RANGE)pString)->Offset;
  781. }
  782. }
  783. else
  784. {
  785. while (pString < pEndString)
  786. {
  787. //
  788. // Call the appropriate callback function.
  789. //
  790. NLS_CALL_ENUMPROC_TRUE(
  791. Locale,
  792. lpCalInfoEnumProc,
  793. UseCPACP,
  794. ((PERA_RANGE)pString)->pYearStr +
  795. NlsStrLenW(((PERA_RANGE)pString)->pYearStr) + 1,
  796. fUnicodeVer );
  797. //
  798. // Advance pointer to next era range.
  799. //
  800. pString += ((PERA_RANGE)pString)->Offset;
  801. }
  802. }
  803. }
  804. }
  805. else if (CalNum == CAL_GREGORIAN)
  806. {
  807. //
  808. // Gregorian calendar, so use the default
  809. // locale string.
  810. //
  811. pString = (LPWORD)(pHashN->pLocaleHdr) +
  812. *((LPWORD)((LPBYTE)(pHashN->pLocaleHdr) +
  813. LocFieldOffset));
  814. pEndString = (LPWORD)(pHashN->pLocaleHdr) +
  815. *((LPWORD)((LPBYTE)(pHashN->pLocaleHdr) +
  816. EndLocFieldOffset));
  817. //
  818. // Go through each of the strings.
  819. //
  820. while (pString < pEndString)
  821. {
  822. //
  823. // Make sure the string is NOT empty.
  824. //
  825. if (*pString)
  826. {
  827. //
  828. // Call the appropriate callback function.
  829. //
  830. NLS_CALL_ENUMPROC_TRUE( Locale,
  831. lpCalInfoEnumProc,
  832. UseCPACP,
  833. pString,
  834. fUnicodeVer );
  835. }
  836. //
  837. // Advance pointer to next string.
  838. //
  839. pString += NlsStrLenW(pString) + 1;
  840. }
  841. }
  842. else if ((!fIfName) ||
  843. (((PCALENDAR_VAR)pCalInfo)->IfNames))
  844. {
  845. //
  846. // Get the pointer to the appropriate calendar string.
  847. //
  848. pString = (LPWORD)pCalInfo +
  849. *((LPWORD)((LPBYTE)(pCalInfo) + CalFieldOffset));
  850. pEndString = (LPWORD)pCalInfo +
  851. *((LPWORD)((LPBYTE)(pCalInfo) + EndCalFieldOffset));
  852. //
  853. // Go through each of the strings.
  854. //
  855. while (pString < pEndString)
  856. {
  857. //
  858. // Make sure the string is NOT empty.
  859. //
  860. if (*pString)
  861. {
  862. //
  863. // Call the appropriate callback function.
  864. //
  865. NLS_CALL_ENUMPROC_TRUE( Locale,
  866. lpCalInfoEnumProc,
  867. UseCPACP,
  868. pString,
  869. fUnicodeVer );
  870. }
  871. //
  872. // Advance pointer to next string.
  873. //
  874. pString += NlsStrLenW(pString) + 1;
  875. }
  876. }
  877. }
  878. //
  879. // Advance ptr to next optional calendar.
  880. //
  881. pOptCal += ((POPT_CAL)pOptCal)->Offset;
  882. }
  883. //
  884. // Return success.
  885. //
  886. return (TRUE);
  887. }
  888. ////////////////////////////////////////////////////////////////////////////
  889. //
  890. // Internal_EnumTimeFormats
  891. //
  892. // Enumerates the time formats that are available for the
  893. // specified locale, based on the dwFlags parameter. It does so by
  894. // passing the pointer to the string buffer containing the time format
  895. // to an application-defined callback function. It continues until the
  896. // last time format is found or the callback function returns FALSE.
  897. //
  898. // 10-14-93 JulieB Created.
  899. ////////////////////////////////////////////////////////////////////////////
  900. BOOL Internal_EnumTimeFormats(
  901. NLS_ENUMPROC lpTimeFmtEnumProc,
  902. LCID Locale,
  903. DWORD dwFlags,
  904. BOOL fUnicodeVer)
  905. {
  906. PLOC_HASH pHashN; // ptr to LOC hash node
  907. //
  908. // Invalid Parameter Check:
  909. // - validate LCID
  910. // - function pointer is null
  911. //
  912. VALIDATE_LOCALE(Locale, pHashN);
  913. if ((pHashN == NULL) || (lpTimeFmtEnumProc == NULL))
  914. {
  915. SetLastError(ERROR_INVALID_PARAMETER);
  916. return (FALSE);
  917. }
  918. //
  919. // Invalid Flags Check:
  920. // - flags other than valid ones
  921. //
  922. if (dwFlags & ETF_INVALID_FLAG)
  923. {
  924. SetLastError(ERROR_INVALID_FLAGS);
  925. return (FALSE);
  926. }
  927. //
  928. // Enumerate the time formats.
  929. //
  930. return ( EnumDateTime( lpTimeFmtEnumProc,
  931. Locale,
  932. dwFlags,
  933. pNlsUserInfo->sTimeFormat,
  934. pHashN->pLocaleHdr,
  935. (LPWORD)(pHashN->pLocaleHdr) +
  936. pHashN->pLocaleHdr->STimeFormat,
  937. (LPWORD)(pHashN->pLocaleHdr) +
  938. pHashN->pLocaleHdr->STime,
  939. (ULONG)0,
  940. (ULONG)0,
  941. FALSE,
  942. fUnicodeVer ) );
  943. }
  944. ////////////////////////////////////////////////////////////////////////////
  945. //
  946. // Internal_EnumDateFormats
  947. //
  948. // Enumerates the long or short date formats that are available for the
  949. // specified locale, based on the dwFlags parameter. It does so by
  950. // passing the pointer to the string buffer containing the date format
  951. // to an application-defined callback function. It continues until the
  952. // last date format is found or the callback function returns FALSE.
  953. //
  954. // 10-14-93 JulieB Created.
  955. ////////////////////////////////////////////////////////////////////////////
  956. BOOL Internal_EnumDateFormats(
  957. NLS_ENUMPROC lpDateFmtEnumProc,
  958. LCID Locale,
  959. DWORD dwFlags,
  960. BOOL fUnicodeVer)
  961. {
  962. PLOC_HASH pHashN; // ptr to LOC hash node
  963. //
  964. // Invalid Parameter Check:
  965. // - validate LCID
  966. // - function pointer is null
  967. //
  968. // - flags will be validated in switch statement below
  969. //
  970. VALIDATE_LOCALE(Locale, pHashN);
  971. if ((pHashN == NULL) || (lpDateFmtEnumProc == NULL))
  972. {
  973. SetLastError(ERROR_INVALID_PARAMETER);
  974. return (FALSE);
  975. }
  976. //
  977. // Enumerate the date pictures based on the flags.
  978. //
  979. switch (dwFlags & (~LOCALE_USE_CP_ACP))
  980. {
  981. case ( 0 ) :
  982. case ( DATE_SHORTDATE ) :
  983. {
  984. //
  985. // Enumerate the short date formats.
  986. //
  987. return ( EnumDateTime( lpDateFmtEnumProc,
  988. Locale,
  989. dwFlags,
  990. pNlsUserInfo->sShortDate,
  991. pHashN->pLocaleHdr,
  992. (LPWORD)(pHashN->pLocaleHdr) +
  993. pHashN->pLocaleHdr->SShortDate,
  994. (LPWORD)(pHashN->pLocaleHdr) +
  995. pHashN->pLocaleHdr->SDate,
  996. (ULONG)FIELD_OFFSET(CALENDAR_VAR, SShortDate),
  997. (ULONG)FIELD_OFFSET(CALENDAR_VAR, SLongDate),
  998. TRUE,
  999. fUnicodeVer ) );
  1000. break;
  1001. }
  1002. case ( DATE_LONGDATE ) :
  1003. {
  1004. //
  1005. // Enumerate the long date formats.
  1006. //
  1007. return ( EnumDateTime( lpDateFmtEnumProc,
  1008. Locale,
  1009. dwFlags,
  1010. pNlsUserInfo->sLongDate,
  1011. pHashN->pLocaleHdr,
  1012. (LPWORD)(pHashN->pLocaleHdr) +
  1013. pHashN->pLocaleHdr->SLongDate,
  1014. (LPWORD)(pHashN->pLocaleHdr) +
  1015. pHashN->pLocaleHdr->IOptionalCal,
  1016. (ULONG)FIELD_OFFSET(CALENDAR_VAR, SLongDate),
  1017. (ULONG)FIELD_OFFSET(CALENDAR_VAR, SDayName1),
  1018. TRUE,
  1019. fUnicodeVer ) );
  1020. break;
  1021. }
  1022. default :
  1023. {
  1024. SetLastError(ERROR_INVALID_FLAGS);
  1025. return (FALSE);
  1026. }
  1027. }
  1028. }
  1029. //-------------------------------------------------------------------------//
  1030. // INTERNAL ROUTINES //
  1031. //-------------------------------------------------------------------------//
  1032. ////////////////////////////////////////////////////////////////////////////
  1033. //
  1034. // EnumDateTime
  1035. //
  1036. // Enumerates the long date, short date, or time formats that are available
  1037. // for the specified locale. This is the worker routine for the
  1038. // EnumTimeFormatsW and EnumDateFormatsW api.
  1039. //
  1040. // 10-14-93 JulieB Created.
  1041. ////////////////////////////////////////////////////////////////////////////
  1042. BOOL EnumDateTime(
  1043. NLS_ENUMPROC lpDateTimeFmtEnumProc,
  1044. LCID Locale,
  1045. DWORD dwFlags,
  1046. LPWSTR pValue,
  1047. PLOCALE_VAR pLocaleHdr,
  1048. LPWSTR pDateTime,
  1049. LPWSTR pEndDateTime,
  1050. ULONG CalDateOffset,
  1051. ULONG EndCalDateOffset,
  1052. BOOL fCalendarInfo,
  1053. BOOL fUnicodeVer)
  1054. {
  1055. LPWSTR pUser = NULL; // ptr to user date/time string
  1056. LPWSTR pOptCal; // ptr to optional calendar values
  1057. LPWSTR pEndOptCal; // ptr to end of optional calendars
  1058. PCAL_INFO pCalInfo; // ptr to calendar info
  1059. CALID CalNum; // calendar number
  1060. WCHAR pTemp[MAX_REG_VAL_SIZE]; // temp buffer
  1061. //
  1062. // Get the user defined string.
  1063. //
  1064. if (GetUserInfo( Locale,
  1065. pValue,
  1066. pTemp,
  1067. TRUE ))
  1068. {
  1069. pUser = pTemp;
  1070. //
  1071. // Call the appropriate callback function.
  1072. //
  1073. NLS_CALL_ENUMPROC_TRUE( Locale,
  1074. lpDateTimeFmtEnumProc,
  1075. dwFlags,
  1076. pUser,
  1077. fUnicodeVer );
  1078. }
  1079. //
  1080. // Get the default strings defined for the Gregorian
  1081. // calendar.
  1082. //
  1083. while (pDateTime < pEndDateTime)
  1084. {
  1085. //
  1086. // Call the callback function if the string is not
  1087. // the same as the user string.
  1088. //
  1089. if ((!pUser) || (!NlsStrEqualW(pUser, pDateTime)))
  1090. {
  1091. //
  1092. // Call the appropriate callback function.
  1093. //
  1094. NLS_CALL_ENUMPROC_TRUE( Locale,
  1095. lpDateTimeFmtEnumProc,
  1096. dwFlags,
  1097. pDateTime,
  1098. fUnicodeVer );
  1099. }
  1100. //
  1101. // Advance pDateTime pointer.
  1102. //
  1103. pDateTime += NlsStrLenW(pDateTime) + 1;
  1104. }
  1105. if (fCalendarInfo)
  1106. {
  1107. //
  1108. // Get any alternate calendar dates.
  1109. //
  1110. pOptCal = (LPWORD)(pLocaleHdr) + pLocaleHdr->IOptionalCal;
  1111. if (((POPT_CAL)pOptCal)->CalId == CAL_NO_OPTIONAL)
  1112. {
  1113. //
  1114. // No optional calendars, so done.
  1115. //
  1116. return (TRUE);
  1117. }
  1118. //
  1119. // Get the requested information for each of the alternate
  1120. // calendars.
  1121. //
  1122. pEndOptCal = (LPWORD)(pLocaleHdr) + pLocaleHdr->SDayName1;
  1123. while (pOptCal < pEndOptCal)
  1124. {
  1125. //
  1126. // Get the pointer to the calendar information.
  1127. //
  1128. CalNum = ((POPT_CAL)pOptCal)->CalId;
  1129. if (GetCalendar(CalNum, &pCalInfo) == NO_ERROR)
  1130. {
  1131. //
  1132. // Get the pointer to the date/time information for the
  1133. // current calendar.
  1134. //
  1135. pDateTime = (LPWORD)pCalInfo +
  1136. *((LPWORD)((LPBYTE)(pCalInfo) + CalDateOffset));
  1137. pEndDateTime = (LPWORD)pCalInfo +
  1138. *((LPWORD)((LPBYTE)(pCalInfo) + EndCalDateOffset));
  1139. //
  1140. // Go through each of the strings.
  1141. //
  1142. while (pDateTime < pEndDateTime)
  1143. {
  1144. //
  1145. // Make sure the string is NOT empty and that it is
  1146. // NOT the same as the user's string.
  1147. //
  1148. if ((*pDateTime) &&
  1149. ((!pUser) || (!NlsStrEqualW(pUser, pDateTime))))
  1150. {
  1151. //
  1152. // Call the appropriate callback function.
  1153. //
  1154. NLS_CALL_ENUMPROC_TRUE( Locale,
  1155. lpDateTimeFmtEnumProc,
  1156. dwFlags,
  1157. pDateTime,
  1158. fUnicodeVer );
  1159. }
  1160. //
  1161. // Advance pointer to next date string.
  1162. //
  1163. pDateTime += NlsStrLenW(pDateTime) + 1;
  1164. }
  1165. }
  1166. //
  1167. // Advance ptr to next optional calendar.
  1168. //
  1169. pOptCal += ((POPT_CAL)pOptCal)->Offset;
  1170. }
  1171. }
  1172. //
  1173. // Return success.
  1174. //
  1175. return (TRUE);
  1176. }