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

2842 lines
85 KiB

  1. /*++
  2. Copyright (c) 1994-2000, Microsoft Corporation All rights reserved.
  3. Module Name:
  4. regdlg.c
  5. Abstract:
  6. This module implements the general property sheet for the Regional
  7. Options applet.
  8. Revision History:
  9. --*/
  10. //
  11. // Include Files.
  12. //
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include "intl.h"
  17. #include "winnlsp.h"
  18. #include <windowsx.h>
  19. #include <regstr.h>
  20. #include <tchar.h>
  21. #include <stdlib.h>
  22. #include <setupapi.h>
  23. #include <syssetup.h>
  24. #include <winuserp.h>
  25. #include <userenv.h>
  26. #include "intlhlp.h"
  27. #include "maxvals.h"
  28. #include "util.h"
  29. //
  30. // Constant Declarations.
  31. //
  32. #define MAX_CUSTOM_PAGES 5 // limit on number of second level pages
  33. //
  34. // TEMPO
  35. //
  36. static TCHAR szLayoutFile[] = TEXT("layout file");
  37. //
  38. // Global Variables.
  39. //
  40. DWORD g_savedLocaleId;
  41. //
  42. // Context Help Ids.
  43. //
  44. static int aRegionHelpIds[] =
  45. {
  46. IDC_GROUPBOX1, IDH_COMM_GROUPBOX,
  47. IDC_USER_LOCALE_TEXT, IDH_INTL_GEN_CULTURE,
  48. IDC_USER_LOCALE, IDH_INTL_GEN_CULTURE,
  49. IDC_USER_REGION_TEXT, IDH_INTL_GEN_REGION,
  50. IDC_USER_REGION, IDH_INTL_GEN_REGION,
  51. IDC_CUSTOMIZE, IDH_INTL_GEN_CUSTOMIZE,
  52. IDC_SAMPLE_TEXT, IDH_INTL_GEN_SAMPLE,
  53. IDC_TEXT1, IDH_INTL_GEN_SAMPLE,
  54. IDC_TEXT2, IDH_INTL_GEN_SAMPLE,
  55. IDC_TEXT3, IDH_INTL_GEN_SAMPLE,
  56. IDC_TEXT4, IDH_INTL_GEN_SAMPLE,
  57. IDC_TEXT5, IDH_INTL_GEN_SAMPLE,
  58. IDC_TEXT6, IDH_INTL_GEN_SAMPLE,
  59. IDC_NUMBER_SAMPLE, IDH_INTL_GEN_SAMPLE,
  60. IDC_CURRENCY_SAMPLE, IDH_INTL_GEN_SAMPLE,
  61. IDC_TIME_SAMPLE, IDH_INTL_GEN_SAMPLE,
  62. IDC_SHRTDATE_SAMPLE, IDH_INTL_GEN_SAMPLE,
  63. IDC_LONGDATE_SAMPLE, IDH_INTL_GEN_SAMPLE,
  64. 0, 0
  65. };
  66. //
  67. // Function Prototypes.
  68. //
  69. void
  70. Region_ShowSettings(
  71. HWND hDlg,
  72. LCID lcid);
  73. int
  74. Region_CommandCustomize(
  75. HWND hDlg,
  76. LPREGDLGDATA pDlgData);
  77. ////////////////////////////////////////////////////////////////////////////
  78. //
  79. // Region_EnumAlternateSorts
  80. //
  81. ////////////////////////////////////////////////////////////////////////////
  82. BOOL Region_EnumAlternateSorts()
  83. {
  84. LPLANGUAGEGROUP pLG;
  85. UINT ctr;
  86. //
  87. // Initialize the globals for the alternate sort locales.
  88. //
  89. if (!pAltSorts)
  90. {
  91. if (!(hAltSorts = GlobalAlloc(GHND, MAX_PATH * sizeof(DWORD))))
  92. {
  93. return (FALSE);
  94. }
  95. pAltSorts = GlobalLock(hAltSorts);
  96. }
  97. //
  98. // Reset the global counter so that we don't get duplicates each time
  99. // this gets called. We need to update the list each time in case any
  100. // language groups get added or removed.
  101. //
  102. g_NumAltSorts = 0;
  103. //
  104. // Go through the language groups to see which ones are installed.
  105. // Save the alternate sorts for these language groups.
  106. //
  107. pLG = pLanguageGroups;
  108. while (pLG)
  109. {
  110. //
  111. // If the language group is originally installed and not marked for
  112. // removal OR is marked to be installed, then add the locales for
  113. // this language group to the System and User combo boxes.
  114. //
  115. if (pLG->wStatus & ML_INSTALL)
  116. {
  117. for (ctr = 0; ctr < pLG->NumAltSorts; ctr++)
  118. {
  119. //
  120. // Save the locale id.
  121. //
  122. if (g_NumAltSorts >= MAX_PATH)
  123. {
  124. return (TRUE);
  125. }
  126. pAltSorts[g_NumAltSorts] = (pLG->pAltSortList)[ctr];
  127. g_NumAltSorts++;
  128. }
  129. }
  130. pLG = pLG->pNext;
  131. }
  132. //
  133. // Return success.
  134. //
  135. return (TRUE);
  136. }
  137. ////////////////////////////////////////////////////////////////////////////
  138. //
  139. // Region_EnableSortingPanel
  140. //
  141. ////////////////////////////////////////////////////////////////////////////
  142. void Region_EnableSortingPanel(
  143. HWND hDlg)
  144. {
  145. LCID LocaleID;
  146. LANGID LangID;
  147. int ctr;
  148. int sortCount = 0;
  149. //
  150. // Get the language id from the locale id.
  151. //
  152. LangID = LANGIDFROMLCID( UserLocaleID );
  153. //
  154. // Special case Spanish (Spain) - list International sort first.
  155. //
  156. if ((LangID == LANG_SPANISH_TRADITIONAL) || (LangID == LANG_SPANISH_INTL))
  157. {
  158. g_bShowSortingTab = TRUE;
  159. return;
  160. }
  161. //
  162. // Fill in the drop down if necessary.
  163. //
  164. for (ctr = 0; ctr < g_NumAltSorts; ctr++)
  165. {
  166. LocaleID = pAltSorts[ctr];
  167. if (LANGIDFROMLCID(LocaleID) == LangID)
  168. {
  169. sortCount++;
  170. }
  171. }
  172. //
  173. // Enable the combo box if there is more than one entry in the list.
  174. // Otherwise, disable it.
  175. //
  176. if (sortCount >= 1)
  177. {
  178. g_bShowSortingTab = TRUE;
  179. }
  180. else
  181. {
  182. g_bShowSortingTab = FALSE;
  183. }
  184. }
  185. ////////////////////////////////////////////////////////////////////////////
  186. //
  187. // Region_SetRegionListValues
  188. //
  189. ////////////////////////////////////////////////////////////////////////////
  190. BOOL Region_SetRegionListValues(
  191. GEOID GeoId,
  192. HWND handle)
  193. {
  194. static HWND hUserRegion = NULL;
  195. DWORD dwIndex;
  196. WCHAR szBuf[SIZE_300];
  197. if (!GeoId)
  198. {
  199. hUserRegion = handle;
  200. }
  201. else if (hUserRegion)
  202. {
  203. if (GetGeoInfo(GeoId, GEO_FRIENDLYNAME, szBuf, SIZE_300, 0))
  204. {
  205. dwIndex = ComboBox_AddString(hUserRegion, szBuf);
  206. if (dwIndex != CB_ERR)
  207. {
  208. ComboBox_SetItemData(hUserRegion, dwIndex, GeoId);
  209. }
  210. }
  211. }
  212. else
  213. {
  214. return (FALSE);
  215. }
  216. return (TRUE);
  217. }
  218. ////////////////////////////////////////////////////////////////////////////
  219. //
  220. // Region_EnumProc
  221. //
  222. ////////////////////////////////////////////////////////////////////////////
  223. BOOL Region_EnumProc(
  224. GEOID GeoId)
  225. {
  226. return (Region_SetRegionListValues(GeoId, NULL));
  227. }
  228. ////////////////////////////////////////////////////////////////////////////
  229. //
  230. // Region_EnumRegions
  231. //
  232. ////////////////////////////////////////////////////////////////////////////
  233. void Region_EnumRegions(
  234. HWND hUserRegion)
  235. {
  236. //
  237. // Fill in the UI.
  238. //
  239. Region_SetRegionListValues(0, hUserRegion);
  240. EnumSystemGeoID(GEOCLASS_NATION, 0, Region_EnumProc);
  241. Region_SetRegionListValues(0, NULL);
  242. }
  243. ////////////////////////////////////////////////////////////////////////////
  244. //
  245. // Region_SaveValues
  246. //
  247. // Save values in the case that we need to restore them.
  248. //
  249. ////////////////////////////////////////////////////////////////////////////
  250. void Region_SaveValues()
  251. {
  252. //
  253. // Save locale values.
  254. //
  255. g_savedLocaleId = RegUserLocaleID;
  256. }
  257. ////////////////////////////////////////////////////////////////////////////
  258. //
  259. // Region_ApplyValues
  260. //
  261. ////////////////////////////////////////////////////////////////////////////
  262. BOOL Region_ApplyValues(
  263. HWND hDlg,
  264. LPREGDLGDATA pDlgData)
  265. {
  266. DWORD dwLocale;
  267. LCID NewLocale;
  268. HCURSOR hcurSave;
  269. HWND hUserLocale = GetDlgItem(hDlg, IDC_USER_LOCALE);
  270. //
  271. // See if there are any changes.
  272. //
  273. if (pDlgData->Changes <= RC_EverChg)
  274. {
  275. return (TRUE);
  276. }
  277. //
  278. // Put up the hour glass.
  279. //
  280. hcurSave = SetCursor(LoadCursor(NULL, IDC_WAIT));
  281. //
  282. // See if there are any changes to the user locale.
  283. //
  284. if (pDlgData->Changes & RC_UserLocale)
  285. {
  286. //
  287. // Get the current selections.
  288. //
  289. dwLocale = ComboBox_GetCurSel(hUserLocale);
  290. //
  291. // See if the current selections are different from the original
  292. // selections.
  293. //
  294. if ((dwLocale != CB_ERR) && (dwLocale != pDlgData->dwCurUserLocale))
  295. {
  296. //
  297. // Get the locale id for the current selection.
  298. //
  299. NewLocale = (LCID)ComboBox_GetItemData(hUserLocale, dwLocale);
  300. //
  301. // Set the current locale values in the pDlgData structure.
  302. //
  303. pDlgData->dwCurUserLocale = dwLocale;
  304. //
  305. // Save the new locale information.
  306. //
  307. UserLocaleID = NewLocale;
  308. bShowRtL = IsRtLLocale(UserLocaleID);
  309. bHebrewUI = (PRIMARYLANGID(UserLocaleID) == LANG_HEBREW);
  310. bShowArabic = (bShowRtL && (PRIMARYLANGID(LANGIDFROMLCID(UserLocaleID)) != LANG_HEBREW));
  311. //
  312. // Install the new locale by adding the appropriate information
  313. // to the registry.
  314. //
  315. Intl_InstallUserLocale( NewLocale, FALSE, TRUE);
  316. //
  317. // Update the NLS process cache.
  318. //
  319. NlsResetProcessLocale();
  320. //
  321. // Reset the registry user locale value.
  322. //
  323. RegUserLocaleID = UserLocaleID;
  324. }
  325. }
  326. //
  327. // Turn off the hour glass.
  328. //
  329. SetCursor(hcurSave);
  330. //
  331. // Return success.
  332. //
  333. return (TRUE);
  334. }
  335. ////////////////////////////////////////////////////////////////////////////
  336. //
  337. // Region_RestoreValues
  338. //
  339. ////////////////////////////////////////////////////////////////////////////
  340. void Region_RestoreValues()
  341. {
  342. //
  343. // See if the current selections are different from the original
  344. // selections.
  345. //
  346. if (UserLocaleID != g_savedLocaleId)
  347. {
  348. //
  349. // Install the new locale by adding the appropriate information
  350. // to the registry.
  351. //
  352. Intl_InstallUserLocale(g_savedLocaleId, FALSE, TRUE);
  353. //
  354. // Update the NLS process cache.
  355. //
  356. NlsResetProcessLocale();
  357. //
  358. // Reset the registry user locale value.
  359. //
  360. UserLocaleID = g_savedLocaleId;
  361. RegUserLocaleID = g_savedLocaleId;
  362. //
  363. // Need to make sure the proper keyboard layout is installed.
  364. //
  365. Intl_InstallKeyboardLayout(NULL, g_savedLocaleId, 0, FALSE, FALSE, FALSE);
  366. }
  367. }
  368. ////////////////////////////////////////////////////////////////////////////
  369. //
  370. // Region_ClearValues
  371. //
  372. // Reset each of the list boxes in the region property sheet page.
  373. //
  374. ////////////////////////////////////////////////////////////////////////////
  375. void Region_ClearValues(
  376. HWND hDlg)
  377. {
  378. ComboBox_ResetContent(GetDlgItem(hDlg, IDC_USER_LOCALE));
  379. ComboBox_ResetContent(GetDlgItem(hDlg, IDC_USER_REGION));
  380. }
  381. ////////////////////////////////////////////////////////////////////////////
  382. //
  383. // Region_SetValues
  384. //
  385. // Initialize all of the controls in the region property sheet page.
  386. //
  387. ////////////////////////////////////////////////////////////////////////////
  388. void Region_SetValues(
  389. HWND hDlg,
  390. LPREGDLGDATA pDlgData,
  391. BOOL fInit)
  392. {
  393. TCHAR szUserBuf[SIZE_128];
  394. GEOID geoID = GEOID_NOT_AVAILABLE;
  395. TCHAR szDefaultUserBuf[SIZE_128];
  396. TCHAR szLastUserBuf[SIZE_128];
  397. TCHAR szBuf[SIZE_128];
  398. DWORD dwIndex;
  399. HWND hUserLocale = GetDlgItem(hDlg, IDC_USER_LOCALE);
  400. HWND hUserRegion = GetDlgItem(hDlg, IDC_USER_REGION );
  401. DWORD dwItemCount;
  402. //
  403. // Get the strings to search for in the combo boxes in order to set
  404. // the current selections.
  405. //
  406. if (fInit)
  407. {
  408. //
  409. // It's init time, so get the local user's default settings.
  410. //
  411. if ((UserLocaleID == LCID_SPANISH_TRADITIONAL) ||
  412. (UserLocaleID == LCID_SPANISH_INTL))
  413. {
  414. LoadString(hInstance, IDS_SPANISH_NAME, szUserBuf, SIZE_128);
  415. }
  416. else
  417. {
  418. GetLocaleInfo(UserLocaleID, LOCALE_SLANGUAGE, szUserBuf, SIZE_128);
  419. }
  420. //
  421. // It's init time, so get the region user default settings.
  422. //
  423. geoID = GetUserGeoID(GEOCLASS_NATION);
  424. }
  425. else
  426. {
  427. //
  428. // It's not init time, so get the settings from the combo boxes.
  429. //
  430. ComboBox_GetLBText( hUserLocale,
  431. ComboBox_GetCurSel(hUserLocale),
  432. szUserBuf );
  433. geoID = (GEOID)ComboBox_GetItemData( hUserRegion,
  434. ComboBox_GetCurSel(hUserRegion));
  435. if (pDlgData)
  436. {
  437. ComboBox_GetLBText( hUserLocale,
  438. pDlgData->dwCurUserLocale,
  439. szDefaultUserBuf );
  440. ComboBox_GetLBText( hUserLocale,
  441. pDlgData->dwLastUserLocale,
  442. szLastUserBuf );
  443. }
  444. }
  445. //
  446. // Reset the combo boxes.
  447. //
  448. Region_ClearValues(hDlg);
  449. //
  450. // Get the list of locales and fill in the user locale combo box.
  451. //
  452. Intl_EnumLocales(hDlg, hUserLocale, FALSE);
  453. //
  454. // Select the current user locale id in the list.
  455. // Special case Spanish.
  456. //
  457. dwIndex = ComboBox_FindStringExact(hUserLocale, -1, szUserBuf);
  458. if (dwIndex == CB_ERR)
  459. {
  460. szBuf[0] = 0;
  461. GetLocaleInfo(SysLocaleID, LOCALE_SLANGUAGE, szBuf, SIZE_128);
  462. dwIndex = ComboBox_FindStringExact(hUserLocale, -1, szBuf);
  463. if (dwIndex == CB_ERR)
  464. {
  465. GetLocaleInfo(US_LOCALE, LOCALE_SLANGUAGE, szBuf, SIZE_128);
  466. dwIndex = ComboBox_FindStringExact(hUserLocale, -1, szBuf);
  467. if (dwIndex == CB_ERR)
  468. {
  469. dwIndex = 0;
  470. }
  471. }
  472. if (!fInit && pDlgData)
  473. {
  474. pDlgData->Changes |= RC_UserLocale;
  475. }
  476. }
  477. ComboBox_SetCurSel(hUserLocale, dwIndex);
  478. //
  479. // Get the list of regions and fill in the region combo box.
  480. //
  481. Region_EnumRegions(hUserRegion);
  482. //
  483. // Select the current user region in the list.
  484. //
  485. dwItemCount = (DWORD)ComboBox_GetCount(hUserRegion);
  486. dwIndex = 0;
  487. while(dwIndex < dwItemCount)
  488. {
  489. if (ComboBox_GetItemData(hUserRegion,dwIndex) == geoID)
  490. {
  491. ComboBox_SetCurSel(hUserRegion, dwIndex);
  492. break;
  493. }
  494. dwIndex++;
  495. }
  496. //
  497. // If it's fail, try with User Locale.
  498. //
  499. if(dwIndex >= dwItemCount)
  500. {
  501. //
  502. // Get the GEOID associated with the User Locale.
  503. //
  504. szBuf[0] = 0;
  505. GetLocaleInfo(UserLocaleID, LOCALE_IGEOID | LOCALE_RETURN_NUMBER, szBuf, SIZE_128);
  506. geoID = *((LPDWORD)szBuf);
  507. //
  508. // Search for it...
  509. //
  510. dwIndex = 0;
  511. while(dwIndex < dwItemCount)
  512. {
  513. if (ComboBox_GetItemData(hUserRegion,dwIndex) == geoID)
  514. {
  515. //
  516. // Note:
  517. // Mark this as being changed so that the region will be set
  518. // when the user hits apply. This avoids the problem of having
  519. // the region change every time the user closes and reopens the
  520. // applet after changing the user locale.
  521. //
  522. if (pDlgData)
  523. {
  524. pDlgData->Changes |= RC_UserRegion;
  525. }
  526. ComboBox_SetCurSel(hUserRegion, dwIndex);
  527. break;
  528. }
  529. dwIndex++;
  530. }
  531. }
  532. //
  533. // If it's fail, try with System Locale.
  534. //
  535. if(dwIndex >= dwItemCount)
  536. {
  537. //
  538. // Get the GEOID associated with the User Locale.
  539. //
  540. szBuf[0] = 0;
  541. GetLocaleInfo(SysLocaleID, LOCALE_IGEOID | LOCALE_RETURN_NUMBER, szBuf, SIZE_128);
  542. geoID = *((LPDWORD)szBuf);
  543. //
  544. // Search for it...
  545. //
  546. dwIndex = 0;
  547. while(dwIndex < dwItemCount)
  548. {
  549. if (ComboBox_GetItemData(hUserRegion,dwIndex) == geoID)
  550. {
  551. //
  552. // Note:
  553. // Mark this as being changed so that the region will be set
  554. // when the user hits apply. This avoids the problem of having
  555. // the region change every time the user closes and reopens the
  556. // applet after changing the user locale.
  557. //
  558. if (pDlgData)
  559. {
  560. pDlgData->Changes |= RC_UserRegion;
  561. }
  562. ComboBox_SetCurSel(hUserRegion, dwIndex);
  563. break;
  564. }
  565. dwIndex++;
  566. }
  567. }
  568. //
  569. // If it's fail, try with US Locale.
  570. //
  571. if(dwIndex >= dwItemCount)
  572. {
  573. //
  574. // Get the GEOID associated with the User Locale.
  575. //
  576. szBuf[0] = 0;
  577. GetLocaleInfo(US_LOCALE, LOCALE_IGEOID | LOCALE_RETURN_NUMBER, szBuf, SIZE_128);
  578. geoID = *((LPDWORD)szBuf);
  579. //
  580. // Search for it...
  581. //
  582. dwIndex = 0;
  583. while(dwIndex >= dwItemCount)
  584. {
  585. if (ComboBox_GetItemData(hUserRegion,dwIndex) == geoID)
  586. {
  587. //
  588. // Note:
  589. // Mark this as being changed so that the region will be set
  590. // when the user hits apply. This avoids the problem of having
  591. // the region change every time the user closes and reopens the
  592. // applet after changing the user locale.
  593. //
  594. if (pDlgData)
  595. {
  596. pDlgData->Changes |= RC_UserRegion;
  597. }
  598. ComboBox_SetCurSel(hUserRegion, dwIndex);
  599. break;
  600. }
  601. dwIndex++;
  602. }
  603. }
  604. //
  605. // If it's fail, set to the first item.
  606. //
  607. if(dwIndex >= dwItemCount)
  608. {
  609. //
  610. // Note:
  611. // Mark this as being changed so that the region will be set
  612. // when the user hits apply. This avoids the problem of having
  613. // the region change every time the user closes and reopens the
  614. // applet after changing the user locale.
  615. //
  616. if (pDlgData)
  617. {
  618. pDlgData->Changes |= RC_UserRegion;
  619. }
  620. ComboBox_SetCurSel(hUserRegion, 0);
  621. }
  622. //
  623. // Store the initial locale state in the pDlgData structure.
  624. //
  625. if (pDlgData)
  626. {
  627. //
  628. // Set the current user locale and the last user locale.
  629. //
  630. if (fInit)
  631. {
  632. pDlgData->dwCurUserLocale = ComboBox_GetCurSel(hUserLocale);
  633. pDlgData->dwLastUserLocale = pDlgData->dwCurUserLocale;
  634. }
  635. else
  636. {
  637. pDlgData->dwCurUserLocale = ComboBox_FindStringExact(hUserLocale, -1, szDefaultUserBuf);
  638. pDlgData->dwLastUserLocale = ComboBox_FindStringExact(hUserLocale, -1, szLastUserBuf);
  639. }
  640. //
  641. // Set the current region selection.
  642. //
  643. // Note: The current region is only set if there is actually
  644. // a region set in the registry. Otherwise, if the
  645. // selection is based off of the user locale, then we
  646. // don't set this so that it will get set when the user
  647. // hits Apply. See above note.
  648. //
  649. if (pDlgData->Changes & RC_UserRegion)
  650. {
  651. pDlgData->dwCurUserRegion = CB_ERR;
  652. }
  653. else
  654. {
  655. pDlgData->dwCurUserRegion = ComboBox_GetCurSel(hUserRegion);
  656. }
  657. }
  658. }
  659. ////////////////////////////////////////////////////////////////////////////
  660. //
  661. // Region_RevertChanges
  662. //
  663. // If the user has changed something at the second level, call
  664. // Set_Locale_Values to restore the user locale information.
  665. //
  666. ////////////////////////////////////////////////////////////////////////////
  667. BOOL Region_RevertChanges()
  668. {
  669. HCURSOR hcurSave;
  670. //
  671. // Put up the hour glass.
  672. //
  673. hcurSave = SetCursor( LoadCursor(NULL, IDC_WAIT) );
  674. //
  675. // Revert any changes.
  676. //
  677. if (g_dwCustChange)
  678. {
  679. DWORD dwRecipients;
  680. //
  681. // Revert changes.
  682. //
  683. Date_RestoreValues();
  684. Currency_RestoreValues();
  685. Time_RestoreValues();
  686. Number_RestoreValues();
  687. Sorting_RestoreValues();
  688. }
  689. //
  690. // Turn off the hour glass.
  691. //
  692. SetCursor(hcurSave);
  693. //
  694. // Return success.
  695. //
  696. return (TRUE);
  697. }
  698. ////////////////////////////////////////////////////////////////////////////
  699. //
  700. // Region_ApplySettings
  701. //
  702. // If the Locale has changed, call Set_Locale_Values to update the
  703. // user locale information. Notify the parent of changes and reset the
  704. // change flag stored in the property sheet page structure appropriately.
  705. //
  706. ////////////////////////////////////////////////////////////////////////////
  707. BOOL Region_ApplySettings(
  708. HWND hDlg,
  709. LPREGDLGDATA pDlgData)
  710. {
  711. DWORD dwLocale, dwRegion;
  712. LCID NewLocale;
  713. GEOID CurGeoID;
  714. HCURSOR hcurSave;
  715. HWND hUserLocale = GetDlgItem(hDlg, IDC_USER_LOCALE);
  716. HWND hUserRegion = GetDlgItem(hDlg, IDC_USER_REGION);
  717. DWORD dwRecipients;
  718. LPLANGUAGEGROUP pLG;
  719. BOOL bState, fUserCancel = FALSE;
  720. LVITEM lvItem;
  721. int iIndex=0, cCount=0;
  722. BOOL bBroadcast = FALSE;
  723. //
  724. // See if there are any changes.
  725. //
  726. if ((pDlgData->Changes <= RC_EverChg) && (g_dwCustChange == 0L))
  727. {
  728. return (TRUE);
  729. }
  730. //
  731. // Check if the second level has changed.
  732. //
  733. if (g_dwCustChange)
  734. {
  735. bBroadcast = TRUE;
  736. }
  737. //
  738. // Put up the hour glass.
  739. //
  740. hcurSave = SetCursor(LoadCursor(NULL, IDC_WAIT));
  741. //
  742. // See if there are any changes to the user locale.
  743. //
  744. if (pDlgData->Changes & RC_UserLocale)
  745. {
  746. //
  747. // Need to make sure the proper keyboard layout is installed.
  748. //
  749. Intl_InstallKeyboardLayout(hDlg, UserLocaleID, 0, FALSE, FALSE, FALSE);
  750. //
  751. // We need to broadcast the change
  752. //
  753. bBroadcast = TRUE;
  754. }
  755. //
  756. // See if there are any changes to the user region.
  757. //
  758. if (pDlgData->Changes & RC_UserRegion)
  759. {
  760. //
  761. // Get the current selection.
  762. //
  763. dwRegion = (GEOID)ComboBox_GetCurSel(hUserRegion);
  764. //
  765. // See if the current selection is different from the original
  766. // selection.
  767. //
  768. if ((dwRegion != CB_ERR) && ((dwRegion != pDlgData->dwCurUserRegion)))
  769. {
  770. //
  771. // Get the Region for the current selection.
  772. //
  773. CurGeoID = (GEOID)ComboBox_GetItemData(hUserRegion, dwRegion);
  774. //
  775. // Set the current Region value in the pDlgData structure.
  776. //
  777. pDlgData->dwCurUserRegion = dwRegion;
  778. //
  779. // Set the Region value in the user's registry.
  780. //
  781. SetUserGeoID(CurGeoID);
  782. }
  783. }
  784. //
  785. // Broadcast the message that the international settings in the
  786. // registry have changed.
  787. //
  788. if (bBroadcast)
  789. {
  790. dwRecipients = BSM_APPLICATIONS | BSM_ALLDESKTOPS;
  791. BroadcastSystemMessage( BSF_FORCEIFHUNG | BSF_IGNORECURRENTTASK |
  792. BSF_NOHANG | BSF_NOTIMEOUTIFNOTHUNG,
  793. &dwRecipients,
  794. WM_WININICHANGE,
  795. 0,
  796. (LPARAM)szIntl );
  797. }
  798. //
  799. // Reset the property page settings.
  800. //
  801. PropSheet_UnChanged(GetParent(hDlg), hDlg);
  802. pDlgData->Changes = RC_EverChg;
  803. //
  804. // Turn off the hour glass.
  805. //
  806. SetCursor(hcurSave);
  807. //
  808. // Return success.
  809. //
  810. return (TRUE);
  811. }
  812. ////////////////////////////////////////////////////////////////////////////
  813. //
  814. // Region_ValidatePPS
  815. //
  816. // Validate each of the combo boxes whose values are constrained.
  817. // If any of the input fails, notify the user and then return FALSE
  818. // to indicate validation failure.
  819. //
  820. // Also, if the user locale has changed, then register the change so
  821. // that all other property pages will be updated with the new locale
  822. // settings.
  823. //
  824. ////////////////////////////////////////////////////////////////////////////
  825. BOOL Region_ValidatePPS(
  826. HWND hDlg,
  827. LPREGDLGDATA pDlgData)
  828. {
  829. LPARAM Changes = pDlgData->Changes;
  830. //
  831. // If nothing has changed, return TRUE immediately.
  832. //
  833. if (Changes <= RC_EverChg)
  834. {
  835. return (TRUE);
  836. }
  837. //
  838. // See if the user locale has changed.
  839. //
  840. if (Changes & RC_UserLocale)
  841. {
  842. HWND hUserLocale = GetDlgItem(hDlg, IDC_USER_LOCALE);
  843. DWORD dwLocale = ComboBox_GetCurSel(hUserLocale);
  844. LCID NewLocale;
  845. //
  846. // See if the current selections are different from the original
  847. // selections.
  848. //
  849. if ((dwLocale != CB_ERR) && (dwLocale != pDlgData->dwLastUserLocale))
  850. {
  851. //
  852. // Get the locale id for the current selection.
  853. //
  854. NewLocale = (LCID)ComboBox_GetItemData(hUserLocale, dwLocale);
  855. //
  856. // Set the current locale values in the pDlgData structure.
  857. //
  858. pDlgData->dwLastUserLocale = dwLocale;
  859. //
  860. // Set the UserLocaleID value.
  861. //
  862. UserLocaleID = NewLocale;
  863. bShowRtL = IsRtLLocale(UserLocaleID);
  864. bHebrewUI = (PRIMARYLANGID(UserLocaleID) == LANG_HEBREW);
  865. bShowArabic = (bShowRtL && (PRIMARYLANGID(LANGIDFROMLCID(UserLocaleID)) != LANG_HEBREW));
  866. }
  867. }
  868. //
  869. // Return success.
  870. //
  871. return (TRUE);
  872. }
  873. ////////////////////////////////////////////////////////////////////////////
  874. //
  875. // Region_InitPropSheet
  876. //
  877. ////////////////////////////////////////////////////////////////////////////
  878. BOOL Region_InitPropSheet(
  879. HWND hDlg,
  880. LPPROPSHEETPAGE psp)
  881. {
  882. LPREGDLGDATA pDlgData = (LPREGDLGDATA)LocalAlloc(LPTR, sizeof(REGDLGDATA));
  883. //
  884. // Make sure we have a REGDLGDATA buffer.
  885. //
  886. if (pDlgData == NULL)
  887. {
  888. return (FALSE);
  889. }
  890. //
  891. // See if we're in setup mode.
  892. //
  893. if (g_bSetupCase)
  894. {
  895. //
  896. // Use the registry system locale value for the setup case.
  897. //
  898. SysLocaleID = RegSysLocaleID;
  899. //
  900. // Use the registry user locale value for the setup case.
  901. //
  902. UserLocaleID = RegUserLocaleID;
  903. bShowRtL = IsRtLLocale(UserLocaleID);
  904. bHebrewUI = (PRIMARYLANGID(UserLocaleID) == LANG_HEBREW);
  905. bShowArabic = (bShowRtL && (PRIMARYLANGID(LANGIDFROMLCID(UserLocaleID)) != LANG_HEBREW));
  906. }
  907. //
  908. // Save the data.
  909. //
  910. psp->lParam = (LPARAM)pDlgData;
  911. SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)psp);
  912. //
  913. // Load the information into the dialog.
  914. //
  915. if (pLanguageGroups == NULL)
  916. {
  917. Intl_LoadLanguageGroups(hDlg);
  918. }
  919. Region_SetValues(hDlg, pDlgData, TRUE);
  920. Region_ShowSettings(hDlg, UserLocaleID);
  921. //
  922. // Return success.
  923. //
  924. return (TRUE);
  925. }
  926. ////////////////////////////////////////////////////////////////////////////
  927. //
  928. // Region_FreeGlobalInfo
  929. //
  930. // Processing for a WM_DESTROY message.
  931. //
  932. ////////////////////////////////////////////////////////////////////////////
  933. void Region_FreeGlobalInfo()
  934. {
  935. LPLANGUAGEGROUP pPreLG, pCurLG;
  936. HANDLE hAlloc;
  937. //
  938. // Remove Language Group info.
  939. //
  940. pCurLG = pLanguageGroups;
  941. pLanguageGroups = NULL;
  942. while (pCurLG)
  943. {
  944. pPreLG = pCurLG;
  945. pCurLG = pPreLG->pNext;
  946. hAlloc = pPreLG->hLanguageGroup;
  947. GlobalUnlock(hAlloc);
  948. GlobalFree(hAlloc);
  949. }
  950. //
  951. // Remove Alternate Sorts info.
  952. //
  953. g_NumAltSorts = 0;
  954. pAltSorts = NULL;
  955. GlobalUnlock(hAltSorts);
  956. GlobalFree(hAltSorts);
  957. }
  958. ////////////////////////////////////////////////////////////////////////////
  959. //
  960. // Region_CommandCustomize
  961. //
  962. ////////////////////////////////////////////////////////////////////////////
  963. int Region_CommandCustomize(
  964. HWND hDlg,
  965. LPREGDLGDATA pDlgData)
  966. {
  967. int rc = 0;
  968. HPROPSHEETPAGE rPages[MAX_CUSTOM_PAGES];
  969. PROPSHEETHEADER psh;
  970. LPARAM lParam = 0;
  971. //
  972. // Start at the first page.
  973. //
  974. psh.nStartPage = 0;
  975. //
  976. // Set up the property sheet information.
  977. //
  978. psh.dwSize = sizeof(psh);
  979. psh.dwFlags = 0;
  980. psh.hwndParent = hDlg;
  981. psh.hInstance = hInstance;
  982. psh.pszCaption = MAKEINTRESOURCE(IDS_NAME_CUSTOM);
  983. psh.nPages = 0;
  984. psh.phpage = rPages;
  985. //
  986. // Add the appropriate property pages.
  987. //
  988. Intl_AddPage(&psh, DLG_NUMBER, NumberDlgProc, lParam, MAX_CUSTOM_PAGES);
  989. Intl_AddPage(&psh, DLG_CURRENCY, CurrencyDlgProc, lParam, MAX_CUSTOM_PAGES);
  990. Intl_AddPage(&psh, DLG_TIME, TimeDlgProc, lParam, MAX_CUSTOM_PAGES);
  991. Intl_AddPage(&psh, DLG_DATE, DateDlgProc, lParam, MAX_CUSTOM_PAGES);
  992. if (g_bShowSortingTab)
  993. {
  994. Intl_AddPage(&psh, DLG_SORTING, SortingDlgProc, lParam, MAX_CUSTOM_PAGES);
  995. }
  996. //
  997. // Make the property sheet.
  998. //
  999. PropertySheet(&psh);
  1000. //
  1001. // Return the result.
  1002. //
  1003. return (rc);
  1004. }
  1005. ////////////////////////////////////////////////////////////////////////////
  1006. //
  1007. // Region_ShowSettings
  1008. //
  1009. ////////////////////////////////////////////////////////////////////////////
  1010. void Region_ShowSettings(
  1011. HWND hDlg,
  1012. LCID lcid)
  1013. {
  1014. WCHAR szBuf[MAX_SAMPLE_SIZE];
  1015. //
  1016. // Show Number Sample.
  1017. //
  1018. if (GetNumberFormat(lcid, 0, szSample_Number, NULL, szBuf, MAX_SAMPLE_SIZE))
  1019. {
  1020. SetDlgItemText(hDlg, IDC_NUMBER_SAMPLE, szBuf);
  1021. }
  1022. else
  1023. {
  1024. SetDlgItemText(hDlg, IDC_NUMBER_SAMPLE, L"");
  1025. }
  1026. //
  1027. // Show Currency Sample.
  1028. //
  1029. if (GetCurrencyFormat(lcid, 0, szSample_Number, NULL, szBuf, MAX_SAMPLE_SIZE))
  1030. {
  1031. SetDlgItemText(hDlg, IDC_CURRENCY_SAMPLE, szBuf);
  1032. }
  1033. else
  1034. {
  1035. SetDlgItemText(hDlg, IDC_CURRENCY_SAMPLE, L"");
  1036. }
  1037. //
  1038. // Show Time Sample.
  1039. //
  1040. if (GetTimeFormat(lcid, 0, NULL, NULL, szBuf, MAX_SAMPLE_SIZE))
  1041. {
  1042. SetDlgItemText(hDlg, IDC_TIME_SAMPLE, szBuf);
  1043. }
  1044. else
  1045. {
  1046. SetDlgItemText(hDlg, IDC_TIME_SAMPLE, L"");
  1047. }
  1048. //
  1049. // Show Short Date Sample.
  1050. //
  1051. if (bShowArabic)
  1052. {
  1053. if (GetDateFormat( lcid,
  1054. DATE_RTLREADING | DATE_SHORTDATE,
  1055. NULL,
  1056. NULL,
  1057. szBuf,
  1058. MAX_SAMPLE_SIZE ))
  1059. {
  1060. SetDlgItemText(hDlg, IDC_SHRTDATE_SAMPLE, szBuf);
  1061. }
  1062. else
  1063. {
  1064. SetDlgItemText(hDlg, IDC_SHRTDATE_SAMPLE, L"");
  1065. }
  1066. }
  1067. else
  1068. {
  1069. // If user locale is not Arabic, make sure that the controls for date samples are:
  1070. // * LTR reading orders for non-Hebrew locales
  1071. // * RTL reading orders for Hebrew locales.
  1072. SetControlReadingOrder(bHebrewUI, GetDlgItem(hDlg, IDC_SHRTDATE_SAMPLE));
  1073. if (GetDateFormat( lcid,
  1074. (bShowRtL ? DATE_LTRREADING : 0) | DATE_SHORTDATE,
  1075. NULL,
  1076. NULL,
  1077. szBuf,
  1078. MAX_SAMPLE_SIZE ))
  1079. {
  1080. SetDlgItemText(hDlg, IDC_SHRTDATE_SAMPLE, szBuf);
  1081. }
  1082. else
  1083. {
  1084. SetDlgItemText(hDlg, IDC_SHRTDATE_SAMPLE, L"");
  1085. }
  1086. }
  1087. //
  1088. // Show Long Date Sample.
  1089. //
  1090. if (bShowArabic)
  1091. {
  1092. if (GetDateFormat( lcid,
  1093. DATE_RTLREADING | DATE_LONGDATE,
  1094. NULL,
  1095. NULL,
  1096. szBuf,
  1097. MAX_SAMPLE_SIZE ))
  1098. {
  1099. SetDlgItemText(hDlg, IDC_LONGDATE_SAMPLE, szBuf);
  1100. }
  1101. else
  1102. {
  1103. SetDlgItemText(hDlg, IDC_LONGDATE_SAMPLE, L"");
  1104. }
  1105. }
  1106. else
  1107. {
  1108. // If user locale is not Arabic, make sure that the control for date samples are:
  1109. // * LTR reading orders for non-Hebrew locales
  1110. // * RTL reading orders for Hebrew locales.
  1111. SetControlReadingOrder(bHebrewUI, GetDlgItem(hDlg, IDC_LONGDATE_SAMPLE));
  1112. if (GetDateFormat( lcid,
  1113. (bHebrewUI ? DATE_RTLREADING :
  1114. (bShowRtL ? DATE_LTRREADING : 0)) | DATE_LONGDATE,
  1115. NULL,
  1116. NULL,
  1117. szBuf,
  1118. MAX_SAMPLE_SIZE ))
  1119. {
  1120. SetDlgItemText(hDlg, IDC_LONGDATE_SAMPLE, szBuf);
  1121. }
  1122. else
  1123. {
  1124. SetDlgItemText(hDlg, IDC_LONGDATE_SAMPLE, L"");
  1125. }
  1126. }
  1127. }
  1128. ////////////////////////////////////////////////////////////////////////////
  1129. //
  1130. // GeneralDlgProc
  1131. //
  1132. ////////////////////////////////////////////////////////////////////////////
  1133. INT_PTR CALLBACK GeneralDlgProc(
  1134. HWND hDlg,
  1135. UINT message,
  1136. WPARAM wParam,
  1137. LPARAM lParam)
  1138. {
  1139. LPPROPSHEETPAGE lpPropSheet = (LPPROPSHEETPAGE)(GetWindowLongPtr(hDlg, DWLP_USER));
  1140. LPREGDLGDATA pDlgData = lpPropSheet ? (LPREGDLGDATA)lpPropSheet->lParam : NULL;
  1141. switch (message)
  1142. {
  1143. case ( WM_INITDIALOG ) :
  1144. {
  1145. if (!Region_InitPropSheet( hDlg, (LPPROPSHEETPAGE)lParam))
  1146. {
  1147. PropSheet_PressButton(GetParent(hDlg), PSBTN_CANCEL);
  1148. }
  1149. Region_SaveValues();
  1150. break;
  1151. }
  1152. case ( WM_DESTROY ) :
  1153. {
  1154. Region_FreeGlobalInfo();
  1155. if (pDlgData)
  1156. {
  1157. lpPropSheet->lParam = 0;
  1158. LocalFree((HANDLE)pDlgData);
  1159. }
  1160. break;
  1161. }
  1162. case ( WM_HELP ) :
  1163. {
  1164. WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
  1165. szHelpFile,
  1166. HELP_WM_HELP,
  1167. (DWORD_PTR)(LPTSTR)aRegionHelpIds );
  1168. break;
  1169. }
  1170. case ( WM_CONTEXTMENU ) : // right mouse click
  1171. {
  1172. WinHelp( (HWND)wParam,
  1173. szHelpFile,
  1174. HELP_CONTEXTMENU,
  1175. (DWORD_PTR)(LPTSTR)aRegionHelpIds );
  1176. break;
  1177. }
  1178. case ( WM_NOTIFY ) :
  1179. {
  1180. LPNMHDR psn = (NMHDR *)lParam;
  1181. switch (psn->code)
  1182. {
  1183. case ( PSN_SETACTIVE ) :
  1184. {
  1185. //
  1186. // If there has been a change in the regional Locale
  1187. // setting, clear all of the current info in the
  1188. // property sheet, get the new values, and update the
  1189. // appropriate registry values.
  1190. //
  1191. if (Verified_Regional_Chg & Process_Regional)
  1192. {
  1193. Verified_Regional_Chg &= ~Process_Regional;
  1194. Region_SetValues(hDlg, pDlgData, FALSE);
  1195. Region_ShowSettings(hDlg, UserLocaleID);
  1196. }
  1197. break;
  1198. }
  1199. case ( PSN_RESET ) :
  1200. {
  1201. //
  1202. // Revert any changes made
  1203. //
  1204. if (g_bCustomize)
  1205. {
  1206. Region_RevertChanges();
  1207. g_bCustomize = FALSE;
  1208. }
  1209. Region_RestoreValues();
  1210. break;
  1211. }
  1212. case ( PSN_KILLACTIVE ) :
  1213. {
  1214. //
  1215. // Validate the entries on the property page.
  1216. //
  1217. if (pDlgData)
  1218. {
  1219. SetWindowLongPtr( hDlg,
  1220. DWLP_MSGRESULT,
  1221. !Region_ValidatePPS(hDlg, pDlgData) );
  1222. }
  1223. break;
  1224. }
  1225. case ( PSN_APPLY ) :
  1226. {
  1227. if (pDlgData)
  1228. {
  1229. //
  1230. // Apply the settings.
  1231. //
  1232. if (Region_ApplySettings(hDlg, pDlgData))
  1233. {
  1234. SetWindowLongPtr( hDlg,
  1235. DWLP_MSGRESULT,
  1236. PSNRET_NOERROR );
  1237. //
  1238. // Check if we need to do something for the
  1239. // default user.
  1240. //
  1241. if (g_bDefaultUser)
  1242. {
  1243. g_bSettingsChanged = TRUE;
  1244. Intl_SaveDefaultUserSettings();
  1245. }
  1246. //
  1247. // Zero out the RC_EverChg bit.
  1248. //
  1249. pDlgData->Changes = 0;
  1250. //
  1251. // Save the new user locale.
  1252. //
  1253. Region_SaveValues();
  1254. //
  1255. // Update settings.
  1256. //
  1257. Region_ShowSettings(hDlg, UserLocaleID);
  1258. }
  1259. else
  1260. {
  1261. SetWindowLongPtr( hDlg,
  1262. DWLP_MSGRESULT,
  1263. PSNRET_INVALID_NOCHANGEPAGE );
  1264. }
  1265. }
  1266. break;
  1267. }
  1268. default :
  1269. {
  1270. return (FALSE);
  1271. }
  1272. }
  1273. break;
  1274. }
  1275. case ( WM_COMMAND ) :
  1276. {
  1277. switch (LOWORD(wParam))
  1278. {
  1279. case ( IDC_USER_LOCALE ) :
  1280. {
  1281. if (HIWORD(wParam) == CBN_SELCHANGE)
  1282. {
  1283. if (pDlgData)
  1284. {
  1285. //
  1286. // User locale has changed.
  1287. //
  1288. pDlgData->Changes |= RC_UserLocale;
  1289. //
  1290. // Apply second level changes.
  1291. //
  1292. Region_ApplyValues(hDlg, pDlgData);
  1293. //
  1294. // Update settings.
  1295. //
  1296. Region_ShowSettings(hDlg, UserLocaleID);
  1297. }
  1298. PropSheet_Changed(GetParent(hDlg), hDlg);
  1299. }
  1300. break;
  1301. }
  1302. case ( IDC_USER_REGION ) :
  1303. {
  1304. //
  1305. // See if it's a selection change.
  1306. //
  1307. if (HIWORD(wParam) == CBN_SELCHANGE)
  1308. {
  1309. if (pDlgData)
  1310. {
  1311. pDlgData->Changes |= RC_UserRegion;
  1312. }
  1313. PropSheet_Changed(GetParent(hDlg), hDlg);
  1314. }
  1315. break;
  1316. }
  1317. case ( IDC_CUSTOMIZE ) :
  1318. {
  1319. //
  1320. // Show second level tabs.
  1321. //
  1322. g_bCustomize = TRUE;
  1323. Region_EnumAlternateSorts();
  1324. Region_EnableSortingPanel(hDlg);
  1325. Region_CommandCustomize(hDlg, pDlgData);
  1326. //
  1327. // Update Settings.
  1328. //
  1329. if (g_dwCustChange)
  1330. {
  1331. Region_ShowSettings(hDlg, UserLocaleID);
  1332. PropSheet_Changed(GetParent(hDlg), hDlg);
  1333. }
  1334. break;
  1335. }
  1336. }
  1337. break;
  1338. }
  1339. default :
  1340. {
  1341. return (FALSE);
  1342. }
  1343. }
  1344. //
  1345. // Return success.
  1346. //
  1347. return (TRUE);
  1348. }
  1349. ////////////////////////////////////////////////////////////////////////////
  1350. //
  1351. // Region_InstallSystemLocale
  1352. //
  1353. ////////////////////////////////////////////////////////////////////////////
  1354. BOOL Region_InstallSystemLocale(
  1355. LCID Locale)
  1356. {
  1357. //
  1358. // Make sure the locale is valid and then call setup to install the
  1359. // requested locale.
  1360. //
  1361. if (IsValidLocale(Locale, LCID_INSTALLED))
  1362. {
  1363. if (!SetupChangeLocaleEx( HWND_DESKTOP,
  1364. LOWORD(Locale),
  1365. pSetupSourcePath,
  1366. SP_INSTALL_FILES_QUIETLY,
  1367. NULL,
  1368. 0 ))
  1369. {
  1370. //
  1371. // Check if we need to proceed with the Font Substitution
  1372. //
  1373. if (Intl_IsUIFontSubstitute() &&
  1374. ((LANGID)LANGIDFROMLCID(Locale) == Intl_GetDotDefaultUILanguage()))
  1375. {
  1376. Intl_ApplyFontSubstitute(Locale);
  1377. }
  1378. //
  1379. // Log system locale change.
  1380. //
  1381. Intl_LogSimpleMessage(IDS_LOG_SYS_LOCALE_CHG, NULL);
  1382. //
  1383. // Update current SysLocale, so we can use it later.
  1384. //
  1385. SysLocaleID = LOWORD(Locale);
  1386. //
  1387. // Return success.
  1388. //
  1389. return (TRUE);
  1390. }
  1391. else
  1392. {
  1393. //
  1394. // This can happen if the user hits Cancel from
  1395. // within the setup dialog.
  1396. //
  1397. Intl_LogFormatMessage(IDS_LOG_EXT_LANG_CANCEL);
  1398. }
  1399. }
  1400. else
  1401. {
  1402. //
  1403. // Log invalid locale info.
  1404. //
  1405. Intl_LogSimpleMessage(IDS_LOG_INVALID_LOCALE, NULL);
  1406. }
  1407. //
  1408. // Return failure.
  1409. //
  1410. return (FALSE);
  1411. }
  1412. ////////////////////////////////////////////////////////////////////////////
  1413. //
  1414. // Region_UpdateShortDate
  1415. //
  1416. // Updates the user's short date setting to contain a 4-digit year.
  1417. // The setting is only updated if it is the same as the default setting
  1418. // for the current locale (except for the 2-digit vs. 4-digit year).
  1419. //
  1420. ////////////////////////////////////////////////////////////////////////////
  1421. void Region_UpdateShortDate()
  1422. {
  1423. TCHAR szBufCur[SIZE_64];
  1424. TCHAR szBufDef[SIZE_64];
  1425. LPTSTR pCur, pDef;
  1426. BOOL bChange = FALSE;
  1427. //
  1428. // Get the current short date format setting and the default short date
  1429. // format setting.
  1430. //
  1431. if ((GetLocaleInfo( LOCALE_USER_DEFAULT,
  1432. LOCALE_SSHORTDATE,
  1433. szBufCur,
  1434. SIZE_64 )) &&
  1435. (GetLocaleInfo( LOCALE_USER_DEFAULT,
  1436. LOCALE_SSHORTDATE | LOCALE_NOUSEROVERRIDE,
  1437. szBufDef,
  1438. SIZE_64 )))
  1439. {
  1440. //
  1441. // See if the current setting and the default setting only differ
  1442. // in a 2-digit year ("yy") vs. a 4-digit year ("yyyy").
  1443. //
  1444. // Note: For this, we want an Exact match, so we don't need to
  1445. // use CompareString to compare the formats.
  1446. //
  1447. pCur = szBufCur;
  1448. pDef = szBufDef;
  1449. while ((*pCur) && (*pCur == *pDef))
  1450. {
  1451. //
  1452. // See if it's a 'y'.
  1453. //
  1454. if (*pCur == CHAR_SML_Y)
  1455. {
  1456. if (((*(pCur + 1)) == CHAR_SML_Y) &&
  1457. ((*(pDef + 1)) == CHAR_SML_Y) &&
  1458. ((*(pDef + 2)) == CHAR_SML_Y) &&
  1459. ((*(pDef + 3)) == CHAR_SML_Y))
  1460. {
  1461. bChange = TRUE;
  1462. pCur += 1;
  1463. pDef += 3;
  1464. }
  1465. }
  1466. pCur++;
  1467. pDef++;
  1468. }
  1469. //
  1470. // Set the default short date format as the user's setting.
  1471. //
  1472. if (bChange && (*pCur == *pDef))
  1473. {
  1474. SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SSHORTDATE, szBufDef);
  1475. }
  1476. }
  1477. }
  1478. ////////////////////////////////////////////////////////////////////////////
  1479. //
  1480. // Region_DoUnattendModeSetup
  1481. //
  1482. // NOTE: The unattend mode file contains strings rather than integer
  1483. // values, so we must get the string field and then convert it
  1484. // to the appropriate integer format. The Setup APIs won't just
  1485. // do the right thing, so we have to roll our own.
  1486. //
  1487. ////////////////////////////////////////////////////////////////////////////
  1488. void Region_DoUnattendModeSetup(
  1489. LPCTSTR pUnattendFile)
  1490. {
  1491. HINF hFile, hIntlInf;
  1492. HSPFILEQ FileQueue;
  1493. PVOID QueueContext;
  1494. INFCONTEXT Context;
  1495. DWORD dwNum, dwCtr, dwLocale, dwLayout;
  1496. UINT LanguageGroup, Language, SystemLocale, UserLocale;
  1497. UINT UserLocale_DefUser = 0;
  1498. LANGID MUILanguage, MUILanguage_DefUser;
  1499. TCHAR szBuffer[MAX_PATH];
  1500. DWORD dwLocaleACP = 0UL;
  1501. BOOL bWinntUpgrade;
  1502. BOOL bFound = FALSE;
  1503. BOOL bFound_DefUser = FALSE;
  1504. BOOL bLangGroup = FALSE;
  1505. TCHAR szLCID[25];
  1506. BOOL bInstallBasic = FALSE;
  1507. BOOL bInstallComplex = FALSE;
  1508. BOOL bInstallExt = FALSE;
  1509. //
  1510. // Log the unattended file content.
  1511. //
  1512. if (g_bSetupCase)
  1513. {
  1514. TCHAR szPath[MAX_PATH * 2] = {0};
  1515. //
  1516. // We are in setup mode. No need to log the unattended mode file
  1517. // because the file is located in the system directory and named
  1518. // $winnt$.inf.
  1519. //
  1520. GetSystemDirectory(szPath, MAX_PATH);
  1521. _tcscat(szPath, TEXT("\\$winnt$.inf"));
  1522. Intl_LogSimpleMessage(IDS_LOG_UNAT_LOCATED, szPath);
  1523. }
  1524. else
  1525. {
  1526. Intl_LogUnattendFile(pUnattendFile);
  1527. }
  1528. //
  1529. // Open the unattend mode file.
  1530. //
  1531. hFile = SetupOpenInfFile(pUnattendFile, NULL, INF_STYLE_OLDNT, NULL);
  1532. if (hFile == INVALID_HANDLE_VALUE)
  1533. {
  1534. Intl_LogFormatMessage(IDS_LOG_FILE_ERROR);
  1535. return;
  1536. }
  1537. //
  1538. // Check if we're doing an upgrade or fresh install.
  1539. //
  1540. bWinntUpgrade = Intl_IsWinntUpgrade();
  1541. //
  1542. // Install the Basic Collection upfront when we are in setup.
  1543. //
  1544. if (g_bSetupCase)
  1545. {
  1546. //
  1547. // Open the intl.inf file.
  1548. //
  1549. if (!Intl_InitInf(0, &hIntlInf, szIntlInf, &FileQueue, &QueueContext))
  1550. {
  1551. SetupCloseInfFile(hFile);
  1552. return;
  1553. }
  1554. if (!SetupInstallFilesFromInfSection( hIntlInf,
  1555. NULL,
  1556. FileQueue,
  1557. szLGBasicInstall,
  1558. pSetupSourcePath,
  1559. SP_COPY_NEWER ))
  1560. {
  1561. Intl_LogFormatMessage(IDS_LOG_SETUP_ERROR);
  1562. goto Region_UnattendModeExit;
  1563. }
  1564. else
  1565. {
  1566. //
  1567. // See if we need to install any files.
  1568. //
  1569. if ((SetupScanFileQueue( FileQueue,
  1570. SPQ_SCAN_PRUNE_COPY_QUEUE |
  1571. SPQ_SCAN_FILE_VALIDITY,
  1572. HWND_DESKTOP,
  1573. NULL,
  1574. NULL,
  1575. &dwCtr )) && (dwCtr != 1))
  1576. {
  1577. //
  1578. // Copy the files in the queue.
  1579. //
  1580. if (!SetupCommitFileQueue( NULL,
  1581. FileQueue,
  1582. SetupDefaultQueueCallback,
  1583. QueueContext ))
  1584. {
  1585. //
  1586. // This can happen if the user hits Cancel from
  1587. // within the setup dialog.
  1588. //
  1589. Intl_LogFormatMessage(IDS_LOG_EXT_LANG_CANCEL);
  1590. goto Region_UnattendModeExit;
  1591. }
  1592. }
  1593. //
  1594. // Call setup to install other inf info for the various
  1595. // language groups.
  1596. //
  1597. if (!SetupInstallFromInfSection( NULL,
  1598. hIntlInf,
  1599. szLGBasicInstall,
  1600. SPINST_ALL & ~SPINST_FILES,
  1601. NULL,
  1602. pSetupSourcePath,
  1603. 0,
  1604. NULL,
  1605. NULL,
  1606. NULL,
  1607. NULL ))
  1608. {
  1609. //
  1610. // This can happen if the user hits Cancel from
  1611. // within the setup dialog.
  1612. //
  1613. Intl_LogFormatMessage(IDS_LOG_EXT_LANG_CANCEL);
  1614. goto Region_UnattendModeExit;
  1615. }
  1616. }
  1617. //
  1618. // Close the inf file.
  1619. //
  1620. Intl_CloseInf(hIntlInf, FileQueue, QueueContext);
  1621. }
  1622. //
  1623. // Open the intl.inf file.
  1624. //
  1625. if (!Intl_InitInf(0, &hIntlInf, szIntlInf, &FileQueue, &QueueContext))
  1626. {
  1627. SetupCloseInfFile(hFile);
  1628. return;
  1629. }
  1630. //
  1631. // Install all requested Language Groups.
  1632. //
  1633. if ((SetupFindFirstLine( hFile,
  1634. szRegionalSettings,
  1635. szLanguageGroup,
  1636. &Context )) &&
  1637. (dwNum = SetupGetFieldCount(&Context)))
  1638. {
  1639. bLangGroup = TRUE;
  1640. //
  1641. // Check for admin privilege.
  1642. //
  1643. if (g_bAdmin_Privileges)
  1644. {
  1645. for (dwCtr = 1; dwCtr <= dwNum; dwCtr++)
  1646. {
  1647. if (SetupGetStringField(&Context, dwCtr, szBuffer, MAX_PATH, NULL))
  1648. {
  1649. //
  1650. // Log language group info.
  1651. //
  1652. Intl_LogSimpleMessage(IDS_LOG_LANG_GROUP, szBuffer);
  1653. //
  1654. // Get the Language Group as an integer.
  1655. //
  1656. LanguageGroup = Intl_StrToLong(szBuffer);
  1657. //
  1658. // See which language collections need to be installed.
  1659. //
  1660. if ((LanguageGroup == LGRPID_JAPANESE) ||
  1661. (LanguageGroup == LGRPID_KOREAN) ||
  1662. (LanguageGroup == LGRPID_TRADITIONAL_CHINESE) ||
  1663. (LanguageGroup == LGRPID_SIMPLIFIED_CHINESE))
  1664. {
  1665. bInstallExt = TRUE;
  1666. }
  1667. else if ((LanguageGroup == LGRPID_ARABIC) ||
  1668. (LanguageGroup == LGRPID_ARMENIAN) ||
  1669. (LanguageGroup == LGRPID_GEORGIAN) ||
  1670. (LanguageGroup == LGRPID_HEBREW) ||
  1671. (LanguageGroup == LGRPID_INDIC) ||
  1672. (LanguageGroup == LGRPID_VIETNAMESE) ||
  1673. (LanguageGroup == LGRPID_THAI))
  1674. {
  1675. bInstallComplex = TRUE;
  1676. }
  1677. else
  1678. {
  1679. bInstallBasic = TRUE;
  1680. }
  1681. }
  1682. }
  1683. //
  1684. // Enqueue the appropriate language group files so that they
  1685. // may be copied. This only handles the CopyFiles entries in
  1686. // the inf file.
  1687. //
  1688. //
  1689. // CJK Collection.
  1690. //
  1691. if (bInstallExt)
  1692. {
  1693. if (!SetupInstallFilesFromInfSection( hIntlInf,
  1694. NULL,
  1695. FileQueue,
  1696. szLGExtInstall,
  1697. pSetupSourcePath,
  1698. SP_COPY_NEWER ))
  1699. {
  1700. bInstallExt = FALSE;
  1701. Intl_LogFormatMessage(IDS_LOG_SETUP_ERROR);
  1702. goto Region_UnattendModeExit;
  1703. }
  1704. }
  1705. //
  1706. // Complex Scripts Collection.
  1707. //
  1708. if (bInstallComplex)
  1709. {
  1710. if (!SetupInstallFilesFromInfSection( hIntlInf,
  1711. NULL,
  1712. FileQueue,
  1713. szLGComplexInstall,
  1714. pSetupSourcePath,
  1715. SP_COPY_NEWER ))
  1716. {
  1717. bInstallComplex = FALSE;
  1718. Intl_LogFormatMessage(IDS_LOG_SETUP_ERROR);
  1719. goto Region_UnattendModeExit;
  1720. }
  1721. }
  1722. //
  1723. // Basic Collection.
  1724. //
  1725. // Only install the Basic Collection if we're not in setup
  1726. // mode. If we're in setup mode, this was already done above.
  1727. //
  1728. if (bInstallBasic && (!g_bSetupCase))
  1729. {
  1730. if (!SetupInstallFilesFromInfSection( hIntlInf,
  1731. NULL,
  1732. FileQueue,
  1733. szLGBasicInstall,
  1734. pSetupSourcePath,
  1735. SP_COPY_NEWER ))
  1736. {
  1737. bInstallBasic = FALSE;
  1738. Intl_LogFormatMessage(IDS_LOG_SETUP_ERROR);
  1739. goto Region_UnattendModeExit;
  1740. }
  1741. }
  1742. //
  1743. // See if we need to install any files.
  1744. //
  1745. if ((SetupScanFileQueue( FileQueue,
  1746. SPQ_SCAN_PRUNE_COPY_QUEUE |
  1747. SPQ_SCAN_FILE_VALIDITY,
  1748. HWND_DESKTOP,
  1749. NULL,
  1750. NULL,
  1751. &dwCtr )) && (dwCtr != 1))
  1752. {
  1753. //
  1754. // Copy the files in the queue.
  1755. //
  1756. if (!SetupCommitFileQueue( NULL,
  1757. FileQueue,
  1758. SetupDefaultQueueCallback,
  1759. QueueContext ))
  1760. {
  1761. //
  1762. // This can happen if the user hits Cancel from
  1763. // within the setup dialog.
  1764. //
  1765. Intl_LogFormatMessage(IDS_LOG_EXT_LANG_CANCEL);
  1766. goto Region_UnattendModeExit;
  1767. }
  1768. }
  1769. //
  1770. // Call setup to install other inf info for the various
  1771. // language groups.
  1772. //
  1773. if (bInstallExt)
  1774. {
  1775. if (!SetupInstallFromInfSection( NULL,
  1776. hIntlInf,
  1777. szLGExtInstall,
  1778. SPINST_ALL & ~SPINST_FILES,
  1779. NULL,
  1780. pSetupSourcePath,
  1781. 0,
  1782. NULL,
  1783. NULL,
  1784. NULL,
  1785. NULL ))
  1786. {
  1787. //
  1788. // This can happen if the user hits Cancel from
  1789. // within the setup dialog.
  1790. //
  1791. Intl_LogFormatMessage(IDS_LOG_EXT_LANG_CANCEL);
  1792. goto Region_UnattendModeExit;
  1793. }
  1794. }
  1795. if (bInstallComplex)
  1796. {
  1797. if (!SetupInstallFromInfSection( NULL,
  1798. hIntlInf,
  1799. szLGComplexInstall,
  1800. SPINST_ALL & ~SPINST_FILES,
  1801. NULL,
  1802. pSetupSourcePath,
  1803. 0,
  1804. NULL,
  1805. NULL,
  1806. NULL,
  1807. NULL ))
  1808. {
  1809. //
  1810. // This can happen if the user hits Cancel from
  1811. // within the setup dialog.
  1812. //
  1813. Intl_LogFormatMessage(IDS_LOG_EXT_LANG_CANCEL);
  1814. goto Region_UnattendModeExit;
  1815. }
  1816. }
  1817. if (bInstallBasic && (!g_bSetupCase))
  1818. {
  1819. if (!SetupInstallFromInfSection( NULL,
  1820. hIntlInf,
  1821. szLGBasicInstall,
  1822. SPINST_ALL & ~SPINST_FILES,
  1823. NULL,
  1824. pSetupSourcePath,
  1825. 0,
  1826. NULL,
  1827. NULL,
  1828. NULL,
  1829. NULL ))
  1830. {
  1831. //
  1832. // This can happen if the user hits Cancel from
  1833. // within the setup dialog.
  1834. //
  1835. Intl_LogFormatMessage(IDS_LOG_EXT_LANG_CANCEL);
  1836. goto Region_UnattendModeExit;
  1837. }
  1838. }
  1839. //
  1840. // Run any necessary apps (for IME installation).
  1841. //
  1842. if (bInstallBasic || bInstallComplex || bInstallExt)
  1843. {
  1844. Intl_RunRegApps(c_szIntlRun);
  1845. }
  1846. }
  1847. else
  1848. {
  1849. //
  1850. // Log that the unattend mode setup was blocked since they
  1851. // do not have admin privileges.
  1852. //
  1853. Intl_LogSimpleMessage(IDS_LOG_NO_ADMIN, NULL);
  1854. }
  1855. }
  1856. //
  1857. // Install the requested Language/Region information. If a
  1858. // Language/Region was not specified, then install the requested
  1859. // System Locale, User Locale, and Input Locales.
  1860. //
  1861. if ((SetupFindFirstLine( hFile,
  1862. szRegionalSettings,
  1863. szLanguage,
  1864. &Context )) &&
  1865. (SetupGetStringField(&Context, 1, szBuffer, MAX_PATH, NULL)))
  1866. {
  1867. //
  1868. // Log language info.
  1869. //
  1870. Intl_LogSimpleMessage(IDS_LOG_LANG, szBuffer);
  1871. //
  1872. // Get the Language as an integer.
  1873. //
  1874. Language = TransNum(szBuffer);
  1875. //
  1876. // Block the invariant locale.
  1877. //
  1878. if (Language != LANG_INVARIANT)
  1879. {
  1880. //
  1881. // Check for admin privilege.
  1882. //
  1883. if (g_bAdmin_Privileges)
  1884. {
  1885. //
  1886. // Install the Language as the System Locale and the User Locale,
  1887. // and then install all layouts associated with the Language.
  1888. //
  1889. if (GetLocaleInfo( MAKELCID(Language, SORT_DEFAULT),
  1890. LOCALE_IDEFAULTANSICODEPAGE |
  1891. LOCALE_NOUSEROVERRIDE |
  1892. LOCALE_RETURN_NUMBER,
  1893. (PTSTR) &dwLocaleACP,
  1894. sizeof(dwLocaleACP) / sizeof(TCHAR) ))
  1895. {
  1896. //
  1897. // Don't set the system locale if the locale doesn't have
  1898. // an ACP.
  1899. //
  1900. if (dwLocaleACP)
  1901. {
  1902. if (Region_InstallSystemLocale(MAKELCID(Language, SORT_DEFAULT)))
  1903. {
  1904. bFound = TRUE;
  1905. }
  1906. }
  1907. else
  1908. {
  1909. //
  1910. // Unicode locale blocked.
  1911. //
  1912. Intl_LogSimpleMessage(IDS_LOG_UNI_BLOCK, NULL);
  1913. }
  1914. //
  1915. // If we are in setup, try to set the Current User GEOID.
  1916. //
  1917. if( g_bSetupCase)
  1918. {
  1919. TCHAR szBuffer[MAX_PATH];
  1920. BOOL bSetGeoId = FALSE;
  1921. //
  1922. // If it's a clean install, then always set the GEOID. If
  1923. // it's a upgrade install set the GEOID only if no value
  1924. // already set.
  1925. //
  1926. if (!bWinntUpgrade)
  1927. {
  1928. bSetGeoId = TRUE;
  1929. }
  1930. else if (GetUserGeoID(GEOCLASS_NATION) != GEOID_NOT_AVAILABLE)
  1931. {
  1932. bSetGeoId = TRUE;
  1933. }
  1934. if (bSetGeoId)
  1935. {
  1936. //
  1937. // Retreive the Geo Identifier from the NLS info
  1938. //
  1939. if(GetLocaleInfo(MAKELCID(Language, SORT_DEFAULT),
  1940. LOCALE_IGEOID | LOCALE_RETURN_NUMBER,
  1941. szBuffer,
  1942. MAX_PATH))
  1943. {
  1944. //
  1945. // Set The GeoId
  1946. //
  1947. SetUserGeoID(*((LPDWORD)szBuffer));
  1948. }
  1949. }
  1950. }
  1951. }
  1952. else
  1953. {
  1954. Intl_LogFormatMessage(IDS_LOG_LOCALE_ACP_FAIL);
  1955. }
  1956. }
  1957. else
  1958. {
  1959. //
  1960. // Log that the unattend mode setup was blocked since they
  1961. // do not have admin privileges.
  1962. //
  1963. Intl_LogSimpleMessage(IDS_LOG_NO_ADMIN, NULL);
  1964. }
  1965. //
  1966. // If we're doing an upgrade, then don't touch per-user settings.
  1967. //
  1968. if (!bWinntUpgrade)
  1969. {
  1970. //
  1971. // Install the requested User Locale.
  1972. //
  1973. if (Intl_InstallUserLocale(MAKELCID(Language, SORT_DEFAULT), FALSE, TRUE))
  1974. {
  1975. bFound = TRUE;
  1976. }
  1977. //
  1978. // Install Keyboard layout
  1979. //
  1980. Intl_InstallAllKeyboardLayout((LANGID)Language);
  1981. }
  1982. }
  1983. else
  1984. {
  1985. //
  1986. // Log invariant locale blocked.
  1987. //
  1988. Intl_LogSimpleMessage(IDS_LOG_INV_BLOCK, NULL);
  1989. }
  1990. }
  1991. //
  1992. // Make sure there was a valid Language setting. If not, then look
  1993. // for the individual keywords.
  1994. //
  1995. if (!bFound)
  1996. {
  1997. //
  1998. // Init the locale variables.
  1999. //
  2000. SystemLocale = 0;
  2001. UserLocale = 0;
  2002. //
  2003. // Log : no valid language setting found.
  2004. //
  2005. Intl_LogSimpleMessage(IDS_LOG_NO_VALID_FOUND, NULL);
  2006. //
  2007. // Install the requested System Locale.
  2008. //
  2009. if ((SetupFindFirstLine( hFile,
  2010. szRegionalSettings,
  2011. szSystemLocale,
  2012. &Context )) &&
  2013. (SetupGetStringField(&Context, 1, szBuffer, MAX_PATH, NULL)))
  2014. {
  2015. SystemLocale = TransNum(szBuffer);
  2016. //
  2017. // Check for admin privilege.
  2018. //
  2019. if (g_bAdmin_Privileges)
  2020. {
  2021. //
  2022. // Log system locale info.
  2023. //
  2024. Intl_LogSimpleMessage(IDS_LOG_SYS_LOCALE, szBuffer);
  2025. //
  2026. // Block the invariant locale.
  2027. //
  2028. if (SystemLocale != LOCALE_INVARIANT)
  2029. {
  2030. dwLocaleACP = 0UL;
  2031. if (GetLocaleInfo( SystemLocale,
  2032. LOCALE_IDEFAULTANSICODEPAGE |
  2033. LOCALE_NOUSEROVERRIDE |
  2034. LOCALE_RETURN_NUMBER,
  2035. (PTSTR) &dwLocaleACP,
  2036. sizeof(dwLocaleACP) / sizeof(TCHAR) ))
  2037. {
  2038. //
  2039. // Don't set the system locale if the locale doesn't
  2040. // have an ACP.
  2041. //
  2042. if (dwLocaleACP)
  2043. {
  2044. if (Region_InstallSystemLocale(SystemLocale))
  2045. {
  2046. bFound = TRUE;
  2047. }
  2048. }
  2049. else
  2050. {
  2051. //
  2052. // Unicode locale blocked.
  2053. //
  2054. Intl_LogSimpleMessage(IDS_LOG_UNI_BLOCK, NULL);
  2055. }
  2056. }
  2057. else
  2058. {
  2059. Intl_LogFormatMessage(IDS_LOG_LOCALE_ACP_FAIL);
  2060. }
  2061. }
  2062. else
  2063. {
  2064. //
  2065. // Log invariant locale blocked.
  2066. //
  2067. Intl_LogSimpleMessage(IDS_LOG_INV_BLOCK, NULL);
  2068. }
  2069. }
  2070. else
  2071. {
  2072. //
  2073. // Log that the unattend mode setup was blocked since they
  2074. // do not have admin privileges.
  2075. //
  2076. Intl_LogSimpleMessage(IDS_LOG_NO_ADMIN, NULL);
  2077. }
  2078. }
  2079. //
  2080. // Install the requested User Locale.
  2081. //
  2082. if ((SetupFindFirstLine( hFile,
  2083. szRegionalSettings,
  2084. szUserLocale,
  2085. &Context )) &&
  2086. (SetupGetStringField(&Context, 1, szBuffer, MAX_PATH, NULL)))
  2087. {
  2088. UserLocale = TransNum(szBuffer);
  2089. //
  2090. // Log User locale info.
  2091. //
  2092. Intl_LogSimpleMessage(IDS_LOG_USER_LOCALE, szBuffer);
  2093. //
  2094. // Block the invariant locale.
  2095. //
  2096. if (UserLocale != LOCALE_INVARIANT)
  2097. {
  2098. if ((!bWinntUpgrade) &&
  2099. (Intl_InstallUserLocale(UserLocale, FALSE, TRUE)))
  2100. {
  2101. bFound = TRUE;
  2102. }
  2103. }
  2104. else
  2105. {
  2106. //
  2107. // Log invariant locale blocked.
  2108. //
  2109. Intl_LogSimpleMessage(IDS_LOG_INV_BLOCK, NULL);
  2110. }
  2111. }
  2112. //
  2113. // Install the requested Input Locales.
  2114. //
  2115. if (SetupFindFirstLine( hFile,
  2116. szRegionalSettings,
  2117. szInputLocale,
  2118. &Context ))
  2119. {
  2120. //
  2121. // Log Default User - Input Locale info.
  2122. //
  2123. Intl_LogSimpleMessage(IDS_LOG_INPUT, NULL);
  2124. //
  2125. // Install the keyboard layout list.
  2126. //
  2127. if (Intl_InstallKeyboardLayoutList(&Context, 1, FALSE))
  2128. {
  2129. bFound = TRUE;
  2130. }
  2131. }
  2132. else
  2133. {
  2134. //
  2135. // No input locales are specified, so install the default
  2136. // input locale for the system locale and/or user locale if
  2137. // they were specified.
  2138. //
  2139. if (SystemLocale != 0)
  2140. {
  2141. //
  2142. // Log system locale info.
  2143. //
  2144. Intl_LogSimpleMessage(IDS_LOG_SYS_DEF_LAYOUT, NULL);
  2145. //
  2146. // Install the keyboard layout.
  2147. //
  2148. Intl_InstallKeyboardLayout(NULL, SystemLocale, 0, FALSE, FALSE, TRUE);
  2149. }
  2150. if ((UserLocale != 0) && (UserLocale != SystemLocale))
  2151. {
  2152. //
  2153. // Log user locale info.
  2154. //
  2155. Intl_LogSimpleMessage(IDS_LOG_USER_DEF_LAYOUT, NULL);
  2156. //
  2157. // Install the keyboard layout.
  2158. //
  2159. Intl_InstallKeyboardLayout(NULL, UserLocale, 0, FALSE, FALSE, FALSE);
  2160. }
  2161. }
  2162. //
  2163. // Install the requested MUI Language.
  2164. //
  2165. if ((SetupFindFirstLine( hFile,
  2166. szRegionalSettings,
  2167. szMUILanguage,
  2168. &Context )) &&
  2169. (SetupGetStringField(&Context, 1, szBuffer, MAX_PATH, NULL)))
  2170. {
  2171. MUILanguage = (LANGID)TransNum(szBuffer);
  2172. //
  2173. // Log MUI Language info.
  2174. //
  2175. Intl_LogSimpleMessage(IDS_LOG_MUI_LANG, szBuffer);
  2176. //
  2177. // Check UI language validity.
  2178. //
  2179. if (IsValidUILanguage(MUILanguage))
  2180. {
  2181. //
  2182. // Block the invariant locale.
  2183. //
  2184. if (MUILanguage != LANG_INVARIANT)
  2185. {
  2186. if ((!bWinntUpgrade) &&
  2187. NT_SUCCESS(NtSetDefaultUILanguage(MUILanguage)))
  2188. {
  2189. // deleting the key this way makes the key invalid for this process
  2190. // this way the new UI doesn't get bogus cached values
  2191. SHDeleteKey(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Windows\\ShellNoRoam\\MUICache"));
  2192. //
  2193. // Install the default keyboard.
  2194. //
  2195. if (Intl_InstallKeyboardLayout( NULL,
  2196. MAKELCID(MUILanguage, SORT_DEFAULT),
  2197. 0,
  2198. FALSE,
  2199. FALSE,
  2200. FALSE ))
  2201. {
  2202. bFound = TRUE;
  2203. }
  2204. }
  2205. }
  2206. else
  2207. {
  2208. //
  2209. // Log invariant locale blocked.
  2210. //
  2211. Intl_LogSimpleMessage(IDS_LOG_INV_BLOCK, NULL);
  2212. }
  2213. }
  2214. else
  2215. {
  2216. //
  2217. // Log invalid UI language blocked.
  2218. //
  2219. Intl_LogSimpleMessage(IDS_LOG_UI_BLOCK, NULL);
  2220. }
  2221. }
  2222. }
  2223. //
  2224. // Install the requested User Locale for the Default User.
  2225. //
  2226. if ((SetupFindFirstLine( hFile,
  2227. szRegionalSettings,
  2228. szUserLocale_DefUser,
  2229. &Context )) &&
  2230. (SetupGetStringField(&Context, 1, szBuffer, MAX_PATH, NULL)))
  2231. {
  2232. UserLocale_DefUser = TransNum(szBuffer);
  2233. //
  2234. // Log default user - user locale info.
  2235. //
  2236. Intl_LogSimpleMessage(IDS_LOG_USER_LOCALE_DEF, szBuffer);
  2237. //
  2238. // Block users that do not have administrative privilege.
  2239. //
  2240. if (g_bAdmin_Privileges)
  2241. {
  2242. //
  2243. // Block the invariant locale.
  2244. //
  2245. if (UserLocale_DefUser != LOCALE_INVARIANT)
  2246. {
  2247. if (Intl_InstallUserLocale(UserLocale_DefUser, TRUE, TRUE))
  2248. {
  2249. if (Intl_InstallKeyboardLayout(NULL, UserLocale_DefUser, 0, FALSE, TRUE, FALSE))
  2250. {
  2251. Intl_SaveDefaultUserInputSettings();
  2252. bFound_DefUser = TRUE;
  2253. }
  2254. }
  2255. }
  2256. else
  2257. {
  2258. //
  2259. // Log invariant locale blocked.
  2260. //
  2261. Intl_LogSimpleMessage(IDS_LOG_INV_BLOCK, NULL);
  2262. }
  2263. }
  2264. else
  2265. {
  2266. //
  2267. // Log that the unattend mode setup was blocked since they
  2268. // do not have admin privileges.
  2269. //
  2270. Intl_LogSimpleMessage(IDS_LOG_NO_ADMIN, NULL);
  2271. }
  2272. }
  2273. //
  2274. // Install the requested Input Locales for the Default User.
  2275. //
  2276. if (SetupFindFirstLine( hFile,
  2277. szRegionalSettings,
  2278. szInputLocale_DefUser,
  2279. &Context ))
  2280. {
  2281. //
  2282. // Log Default User - Input Locale info.
  2283. //
  2284. Intl_LogSimpleMessage(IDS_LOG_INPUT_DEF, NULL);
  2285. //
  2286. // Block users that do not have administrative privilege.
  2287. //
  2288. if (g_bAdmin_Privileges)
  2289. {
  2290. if (Intl_InstallKeyboardLayoutList(&Context, 1, TRUE))
  2291. {
  2292. Intl_SaveDefaultUserInputSettings();
  2293. bFound_DefUser = TRUE;
  2294. }
  2295. }
  2296. else
  2297. {
  2298. //
  2299. // Log that the unattend mode setup was blocked since they
  2300. // do not have admin privileges.
  2301. //
  2302. Intl_LogSimpleMessage(IDS_LOG_NO_ADMIN, NULL);
  2303. }
  2304. }
  2305. //
  2306. // Install the requested MUI Language for the Default User.
  2307. //
  2308. if ((SetupFindFirstLine( hFile,
  2309. szRegionalSettings,
  2310. szMUILanguage_DefUSer,
  2311. &Context )) &&
  2312. (SetupGetStringField(&Context, 1, szBuffer, MAX_PATH, NULL)))
  2313. {
  2314. MUILanguage_DefUser = (LANGID)TransNum(szBuffer);
  2315. //
  2316. // Log Default User - MUI Language info.
  2317. //
  2318. Intl_LogSimpleMessage(IDS_LOG_MUI_LANG_DEF, szBuffer);
  2319. //
  2320. // Check UI language validity.
  2321. //
  2322. if (IsValidUILanguage(MUILanguage_DefUser))
  2323. {
  2324. //
  2325. // Block users that do not have administrative privilege.
  2326. //
  2327. if (g_bAdmin_Privileges)
  2328. {
  2329. //
  2330. // Block the invariant locale.
  2331. //
  2332. if (MUILanguage_DefUser != LANG_INVARIANT)
  2333. {
  2334. if (Intl_ChangeUILangForAllUsers(MUILanguage_DefUser))
  2335. {
  2336. Intl_SaveDefaultUserInputSettings();
  2337. bFound_DefUser = TRUE;
  2338. }
  2339. }
  2340. else
  2341. {
  2342. //
  2343. // Log invariant locale blocked.
  2344. //
  2345. Intl_LogSimpleMessage(IDS_LOG_INV_BLOCK, NULL);
  2346. }
  2347. }
  2348. else
  2349. {
  2350. //
  2351. // Log that the unattend mode setup was blocked since they
  2352. // do not have admin privileges.
  2353. //
  2354. Intl_LogSimpleMessage(IDS_LOG_NO_ADMIN, NULL);
  2355. }
  2356. }
  2357. else
  2358. {
  2359. //
  2360. // Log invalid UI language blocked.
  2361. //
  2362. Intl_LogSimpleMessage(IDS_LOG_UI_BLOCK, NULL);
  2363. }
  2364. }
  2365. //
  2366. // If we still didn't find anything, then load the default locale for
  2367. // the installation. It will be the equivalent of:
  2368. // LanguageGroup = "x"
  2369. // Language = "y"
  2370. // where x is the language group for the default locale and y is the
  2371. // default locale.
  2372. //
  2373. if (!bFound && !bLangGroup && !bFound_DefUser)
  2374. {
  2375. //
  2376. // Get the default locale.
  2377. //
  2378. if ((SetupFindFirstLine( hIntlInf,
  2379. L"DefaultValues",
  2380. L"Locale",
  2381. &Context )) &&
  2382. (SetupGetStringField(&Context, 1, szBuffer, MAX_PATH, NULL)))
  2383. {
  2384. //
  2385. // Get the Language as an integer.
  2386. //
  2387. Language = TransNum(szBuffer);
  2388. //
  2389. // Install the Language Group needed for this Language.
  2390. //
  2391. if ((SetupFindFirstLine( hIntlInf,
  2392. L"Locales",
  2393. szBuffer,
  2394. &Context )) &&
  2395. (SetupGetStringField(&Context, 3, szBuffer, MAX_PATH, NULL)))
  2396. {
  2397. //
  2398. // Get the Language Group as an integer.
  2399. //
  2400. bInstallBasic = FALSE;
  2401. bInstallExt = FALSE;
  2402. LanguageGroup = Intl_StrToLong(szBuffer);
  2403. //
  2404. // Enqueue the language group files so that they may be
  2405. // copied. This only handles the CopyFiles entries in the
  2406. // inf file.
  2407. //
  2408. if ((LanguageGroup == LGRPID_JAPANESE) ||
  2409. (LanguageGroup == LGRPID_KOREAN) ||
  2410. (LanguageGroup == LGRPID_TRADITIONAL_CHINESE) ||
  2411. (LanguageGroup == LGRPID_SIMPLIFIED_CHINESE))
  2412. {
  2413. if (SetupInstallFilesFromInfSection( hIntlInf,
  2414. NULL,
  2415. FileQueue,
  2416. szLGExtInstall,
  2417. pSetupSourcePath,
  2418. SP_COPY_NEWER ))
  2419. {
  2420. bInstallExt = TRUE;
  2421. }
  2422. }
  2423. else if ((LanguageGroup == LGRPID_ARABIC) ||
  2424. (LanguageGroup == LGRPID_ARMENIAN) ||
  2425. (LanguageGroup == LGRPID_GEORGIAN) ||
  2426. (LanguageGroup == LGRPID_HEBREW) ||
  2427. (LanguageGroup == LGRPID_INDIC) ||
  2428. (LanguageGroup == LGRPID_VIETNAMESE) ||
  2429. (LanguageGroup == LGRPID_THAI))
  2430. {
  2431. if (SetupInstallFilesFromInfSection( hIntlInf,
  2432. NULL,
  2433. FileQueue,
  2434. szLGComplexInstall,
  2435. pSetupSourcePath,
  2436. SP_COPY_NEWER ))
  2437. {
  2438. bInstallComplex = TRUE;
  2439. }
  2440. }
  2441. else
  2442. {
  2443. if (SetupInstallFilesFromInfSection( hIntlInf,
  2444. NULL,
  2445. FileQueue,
  2446. szLGBasicInstall,
  2447. pSetupSourcePath,
  2448. SP_COPY_NEWER ))
  2449. {
  2450. bInstallBasic = TRUE;
  2451. }
  2452. }
  2453. //
  2454. // See if we need to install any files.
  2455. //
  2456. if ((SetupScanFileQueue( FileQueue,
  2457. SPQ_SCAN_PRUNE_COPY_QUEUE |
  2458. SPQ_SCAN_FILE_VALIDITY,
  2459. HWND_DESKTOP,
  2460. NULL,
  2461. NULL,
  2462. &dwCtr )) && (dwCtr != 1))
  2463. {
  2464. //
  2465. // Copy the files in the queue.
  2466. //
  2467. if (!SetupCommitFileQueue( NULL,
  2468. FileQueue,
  2469. SetupDefaultQueueCallback,
  2470. QueueContext ))
  2471. {
  2472. //
  2473. // This can happen if the user hits Cancel from
  2474. // within the setup dialog.
  2475. //
  2476. goto Region_UnattendModeExit;
  2477. }
  2478. }
  2479. //
  2480. // Call setup to install other inf info for the various
  2481. // language groups.
  2482. //
  2483. if (bInstallExt)
  2484. {
  2485. if (!SetupInstallFromInfSection( NULL,
  2486. hIntlInf,
  2487. szLGExtInstall,
  2488. SPINST_ALL & ~SPINST_FILES,
  2489. NULL,
  2490. pSetupSourcePath,
  2491. 0,
  2492. NULL,
  2493. NULL,
  2494. NULL,
  2495. NULL ))
  2496. {
  2497. //
  2498. // This can happen if the user hits Cancel from
  2499. // within the setup dialog.
  2500. //
  2501. Intl_LogFormatMessage(IDS_LOG_EXT_LANG_CANCEL);
  2502. goto Region_UnattendModeExit;
  2503. }
  2504. }
  2505. else if (bInstallComplex)
  2506. {
  2507. if (!SetupInstallFromInfSection( NULL,
  2508. hIntlInf,
  2509. szLGComplexInstall,
  2510. SPINST_ALL & ~SPINST_FILES,
  2511. NULL,
  2512. pSetupSourcePath,
  2513. 0,
  2514. NULL,
  2515. NULL,
  2516. NULL,
  2517. NULL ))
  2518. {
  2519. //
  2520. // This can happen if the user hits Cancel from
  2521. // within the setup dialog.
  2522. //
  2523. Intl_LogFormatMessage(IDS_LOG_EXT_LANG_CANCEL);
  2524. goto Region_UnattendModeExit;
  2525. }
  2526. }
  2527. else
  2528. {
  2529. if (!SetupInstallFromInfSection( NULL,
  2530. hIntlInf,
  2531. szLGBasicInstall,
  2532. SPINST_ALL & ~SPINST_FILES,
  2533. NULL,
  2534. pSetupSourcePath,
  2535. 0,
  2536. NULL,
  2537. NULL,
  2538. NULL,
  2539. NULL ))
  2540. {
  2541. //
  2542. // This can happen if the user hits Cancel from
  2543. // within the setup dialog.
  2544. //
  2545. Intl_LogFormatMessage(IDS_LOG_EXT_LANG_CANCEL);
  2546. goto Region_UnattendModeExit;
  2547. }
  2548. }
  2549. //
  2550. // Run any necessary apps (for IME installation).
  2551. //
  2552. if (bInstallBasic || bInstallComplex || bInstallExt)
  2553. {
  2554. Intl_RunRegApps(c_szIntlRun);
  2555. } }
  2556. //
  2557. // Install the Language as the System Locale and the User Locale,
  2558. // and then install all layouts associated with the Language.
  2559. //
  2560. Region_InstallSystemLocale(MAKELCID(Language, SORT_DEFAULT));
  2561. //
  2562. // If we're doing an upgrade, then don't touch per-user settings.
  2563. //
  2564. if (!bWinntUpgrade)
  2565. {
  2566. Intl_InstallUserLocale(MAKELCID(Language, SORT_DEFAULT), FALSE, TRUE);
  2567. Intl_InstallAllKeyboardLayout((LANGID)Language);
  2568. }
  2569. }
  2570. }
  2571. //
  2572. // Run any necessary apps (for FSVGA/FSNEC installation).
  2573. //
  2574. Intl_RunRegApps(c_szSysocmgr);
  2575. Region_UnattendModeExit:
  2576. //
  2577. // Close the inf file.
  2578. //
  2579. Intl_CloseInf(hIntlInf, FileQueue, QueueContext);
  2580. //
  2581. // Close the unattend mode file.
  2582. //
  2583. SetupCloseInfFile(hFile);
  2584. }