Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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