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.

1552 lines
43 KiB

  1. /*++
  2. Copyright (c) 1994-2000, Microsoft Corporation All rights reserved.
  3. Module Name:
  4. langdlg.c
  5. Abstract:
  6. This module implements the languages 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 "intlhlp.h"
  18. #include <windowsx.h>
  19. #include "winnlsp.h"
  20. //
  21. // Context Help Ids.
  22. //
  23. static int aLanguagesHelpIds[] =
  24. {
  25. IDC_GROUPBOX1, IDH_INTL_LANG_CHANGE,
  26. IDC_LANGUAGE_LIST_TEXT, IDH_INTL_LANG_CHANGE,
  27. IDC_LANGUAGE_CHANGE, IDH_INTL_LANG_CHANGE,
  28. IDC_GROUPBOX2, IDH_INTL_LANG_INSTALL,
  29. IDC_LANGUAGE_SUPPL_TEXT, IDH_INTL_LANG_INSTALL,
  30. IDC_LANGUAGE_COMPLEX, IDH_INTL_LANG_INSTALL,
  31. IDC_LANGUAGE_CJK, IDH_INTL_LANG_INSTALL,
  32. IDC_UI_LANGUAGE_TEXT, IDH_INTL_LANG_UI_LANGUAGE,
  33. IDC_UI_LANGUAGE, IDH_INTL_LANG_UI_LANGUAGE,
  34. 0, 0
  35. };
  36. //
  37. // Global Variable.
  38. //
  39. BOOL bComplexInitState;
  40. BOOL bCJKInitState;
  41. //
  42. // Function prototypes.
  43. //
  44. void
  45. Language_SetValues(
  46. HWND hDlg);
  47. ////////////////////////////////////////////////////////////////////////////
  48. //
  49. // Language_InstallLanguageCollectionProc
  50. //
  51. // This is the dialog proc for the Copy status Dlg.
  52. //
  53. ////////////////////////////////////////////////////////////////////////////
  54. INT_PTR CALLBACK Language_InstallLanguageCollectionProc(
  55. HWND hwnd,
  56. UINT uMsg,
  57. WPARAM wParam,
  58. LPARAM lParam)
  59. {
  60. switch (uMsg)
  61. {
  62. case ( WM_INITDIALOG ) :
  63. {
  64. break;
  65. }
  66. case (WM_DESTROY) :
  67. {
  68. EndDialog(hwnd, 0);
  69. break;
  70. }
  71. default :
  72. {
  73. return (FALSE);
  74. }
  75. }
  76. return (TRUE);
  77. }
  78. ////////////////////////////////////////////////////////////////////////////
  79. //
  80. // Language_GetUILanguagePolicy
  81. //
  82. // Checks if a policy is installed for the current user's MUI language.
  83. // The function assumes this is an MUI system.
  84. //
  85. ////////////////////////////////////////////////////////////////////////////
  86. BOOL Language_GetUILanguagePolicy()
  87. {
  88. HKEY hKey;
  89. BYTE buf[MAX_PATH];
  90. DWORD dwType, dwResultLen = sizeof(buf);
  91. BOOL bRet = FALSE;
  92. DWORD Num;
  93. //
  94. // Try to open the MUI Language policy key.
  95. //
  96. if (RegOpenKey(HKEY_CURRENT_USER,
  97. c_szMUIPolicyKeyPath,
  98. &hKey) == ERROR_SUCCESS)
  99. {
  100. if ((RegQueryValueEx(hKey,
  101. c_szMUIValue,
  102. NULL,
  103. &dwType,
  104. &buf[0],
  105. &dwResultLen) == ERROR_SUCCESS) &&
  106. (dwType == REG_SZ) &&
  107. (dwResultLen > 2))
  108. {
  109. bRet = TRUE;
  110. }
  111. RegCloseKey(hKey);
  112. }
  113. return (bRet);
  114. }
  115. ////////////////////////////////////////////////////////////////////////////
  116. //
  117. // Language_UpdateUILanguageCombo
  118. //
  119. ////////////////////////////////////////////////////////////////////////////
  120. void Language_UpdateUILanguageCombo(
  121. HWND hDlg)
  122. {
  123. HWND hUILangText = GetDlgItem(hDlg, IDC_UI_LANGUAGE_TEXT);
  124. HWND hUILang = GetDlgItem(hDlg, IDC_UI_LANGUAGE);
  125. HKEY hKey;
  126. TCHAR szValue[MAX_PATH];
  127. TCHAR szData[MAX_PATH];
  128. DWORD dwIndex, cchValue, cbData;
  129. DWORD UILang;
  130. DWORD dwType;
  131. LANGID DefaultUILang;
  132. LONG rc;
  133. DWORD dwLangIdx = 0;
  134. //
  135. // Reset the contents of the combo box.
  136. //
  137. ComboBox_ResetContent(hUILang);
  138. //
  139. // See if this combo box should be enabled by getting the default
  140. // UI language and opening the
  141. // HKLM\System\CurrentControlSet\Control\Nls\MUILanguages key.
  142. //
  143. if (!(DefaultUILang = GetUserDefaultUILanguage()) ||
  144. (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  145. c_szMUILanguages,
  146. 0,
  147. KEY_READ,
  148. &hKey ) != ERROR_SUCCESS))
  149. {
  150. //
  151. // No MUILanguages. Disable and hide the UI language combo box.
  152. //
  153. EnableWindow(hUILangText, FALSE);
  154. EnableWindow(hUILang, FALSE);
  155. ShowWindow(hUILangText, SW_HIDE);
  156. ShowWindow(hUILang, SW_HIDE);
  157. return;
  158. }
  159. //
  160. // Enumerate the values in the MUILanguages key.
  161. //
  162. dwIndex = 0;
  163. cchValue = sizeof(szValue) / sizeof(TCHAR);
  164. szValue[0] = TEXT('\0');
  165. cbData = sizeof(szData);
  166. szData[0] = TEXT('\0');
  167. rc = RegEnumValue( hKey,
  168. dwIndex,
  169. szValue,
  170. &cchValue,
  171. NULL,
  172. &dwType,
  173. (LPBYTE)szData,
  174. &cbData );
  175. while (rc == ERROR_SUCCESS)
  176. {
  177. //
  178. // If the UI language contains data, then it is installed.
  179. //
  180. if ((szData[0] != 0) &&
  181. (dwType == REG_SZ) &&
  182. (UILang = TransNum(szValue)) &&
  183. (GetLocaleInfo(UILang, LOCALE_SNATIVELANGNAME, szData, MAX_PATH)))
  184. {
  185. //
  186. // Add the new UI Language option to the combo box.
  187. //
  188. dwLangIdx = ComboBox_AddString(hUILang, szData);
  189. ComboBox_SetItemData(hUILang, dwLangIdx, UILang);
  190. //
  191. // Set this as the current selection if it's the default.
  192. //
  193. if (UILang == (DWORD)DefaultUILang)
  194. {
  195. ComboBox_SetCurSel(hUILang, dwLangIdx);
  196. }
  197. }
  198. //
  199. // Get the next enum value.
  200. //
  201. dwIndex++;
  202. cchValue = sizeof(szValue) / sizeof(TCHAR);
  203. szValue[0] = TEXT('\0');
  204. cbData = sizeof(szData);
  205. szData[0] = TEXT('\0');
  206. rc = RegEnumValue( hKey,
  207. dwIndex,
  208. szValue,
  209. &cchValue,
  210. NULL,
  211. &dwType,
  212. (LPBYTE)szData,
  213. &cbData );
  214. }
  215. //
  216. // Close the registry key handle.
  217. //
  218. RegCloseKey(hKey);
  219. //
  220. // Make sure there is at least one entry in the list.
  221. //
  222. if (ComboBox_GetCount(hUILang) < 1)
  223. {
  224. //
  225. // No MUILanguages. Add the default UI language option to the
  226. // combo box.
  227. //
  228. if ((GetLocaleInfo(DefaultUILang, LOCALE_SNATIVELANGNAME, szData, MAX_PATH)) &&
  229. (ComboBox_AddString(hUILang, szData) == 0))
  230. {
  231. ComboBox_SetItemData(hUILang, 0, (DWORD)DefaultUILang);
  232. ComboBox_SetCurSel(hUILang, 0);
  233. }
  234. }
  235. //
  236. // Make sure something is selected.
  237. //
  238. if (ComboBox_GetCurSel(hUILang) == CB_ERR)
  239. {
  240. ComboBox_SetCurSel(hUILang, 0);
  241. }
  242. //
  243. // Enable the combo box if there is more than one entry in the list.
  244. // Otherwise, disable it.
  245. //
  246. if (ComboBox_GetCount(hUILang) > 1)
  247. {
  248. if ((IsWindowEnabled(hUILang) == FALSE) ||
  249. (IsWindowVisible(hUILang) == FALSE))
  250. {
  251. ShowWindow(hUILangText, SW_SHOW);
  252. ShowWindow(hUILang, SW_SHOW);
  253. }
  254. //
  255. // Check if there is a policy enforced on the user, and if
  256. // so, disable the MUI controls.
  257. //
  258. if (Language_GetUILanguagePolicy())
  259. {
  260. EnableWindow(hUILangText, FALSE);
  261. EnableWindow(hUILang, FALSE);
  262. }
  263. else
  264. {
  265. EnableWindow(hUILangText, TRUE);
  266. EnableWindow(hUILang, TRUE);
  267. }
  268. }
  269. else
  270. {
  271. if ((IsWindowEnabled(hUILang) == TRUE) ||
  272. (IsWindowVisible(hUILang) == TRUE))
  273. {
  274. EnableWindow(hUILangText, FALSE);
  275. EnableWindow(hUILang, FALSE);
  276. ShowWindow(hUILangText, SW_HIDE);
  277. ShowWindow(hUILang, SW_HIDE);
  278. }
  279. }
  280. }
  281. ////////////////////////////////////////////////////////////////////////////
  282. //
  283. // Language_GetCollectionStatus
  284. //
  285. ////////////////////////////////////////////////////////////////////////////
  286. BOOL Language_GetCollectionStatus(
  287. DWORD collection,
  288. WORD wStatus)
  289. {
  290. LPLANGUAGEGROUP pLG = pLanguageGroups;
  291. while (pLG)
  292. {
  293. if (pLG->LanguageCollection == collection)
  294. {
  295. if (pLG->wStatus & wStatus)
  296. {
  297. return (TRUE);
  298. }
  299. }
  300. pLG = pLG->pNext;
  301. }
  302. return (FALSE);
  303. }
  304. ////////////////////////////////////////////////////////////////////////////
  305. //
  306. // Language_SetCollectionStatus
  307. //
  308. ////////////////////////////////////////////////////////////////////////////
  309. BOOL Language_SetCollectionStatus(
  310. DWORD collection,
  311. WORD wStatus,
  312. BOOL bOr)
  313. {
  314. LPLANGUAGEGROUP pLG = pLanguageGroups;
  315. while (pLG)
  316. {
  317. if (pLG->LanguageCollection == collection)
  318. {
  319. if( bOr)
  320. {
  321. pLG->wStatus |= wStatus;
  322. }
  323. else
  324. {
  325. pLG->wStatus &= wStatus;
  326. }
  327. }
  328. pLG = pLG->pNext;
  329. }
  330. return (TRUE);
  331. }
  332. ////////////////////////////////////////////////////////////////////////////
  333. //
  334. // Language_InstallCollection
  335. //
  336. ////////////////////////////////////////////////////////////////////////////
  337. BOOL Language_InstallCollection(
  338. BOOL bInstall,
  339. DWORD collection,
  340. HWND hDlg)
  341. {
  342. HINF hIntlInf;
  343. HSPFILEQ FileQueue;
  344. PVOID QueueContext;
  345. INFCONTEXT Context;
  346. HCURSOR hcurSave;
  347. BOOL bActionSuccess = FALSE;
  348. DWORD dwRet;
  349. LPLANGUAGEGROUP pLG = pLanguageGroups;
  350. LCID *pLocale;
  351. BOOL bStopLoop = FALSE;
  352. LPTSTR pszInfSection = NULL;
  353. //
  354. // Put up the hour glass.
  355. //
  356. hcurSave = SetCursor(LoadCursor(NULL, IDC_WAIT));
  357. //
  358. // Check if we remove the Language Collection. This may affect the
  359. // UI Language, User Locale, and/or System Locale setting.
  360. //
  361. if (!bInstall)
  362. {
  363. //
  364. // Check if we can remove the Language group.
  365. //
  366. if (Language_GetCollectionStatus(collection, ML_PERMANENT))
  367. {
  368. return (FALSE);
  369. }
  370. //
  371. // Inform Text Services that we are going to remove the
  372. // complex script language collection.
  373. //
  374. while (pLG)
  375. {
  376. if (pLG->LanguageCollection == collection)
  377. {
  378. //
  379. // Uninstall keyboards of the current user
  380. //
  381. Intl_UninstallAllKeyboardLayout(pLG->LanguageGroup, FALSE);
  382. //
  383. // Uninstall keyboards of the default user
  384. //
  385. Intl_UninstallAllKeyboardLayout(pLG->LanguageGroup, TRUE);
  386. }
  387. pLG = pLG->pNext;
  388. }
  389. //
  390. // If the User Locale is one the Language group asked to be removed. Change
  391. // the user locale to be the system locale.
  392. //
  393. // Walk through all language groups.
  394. //
  395. pLG = pLanguageGroups;
  396. while (pLG && !bStopLoop)
  397. {
  398. if (pLG->LanguageCollection == collection)
  399. {
  400. pLocale = pLG->pLocaleList;
  401. //
  402. // Walk through the locale list, see if the User Locale is
  403. // part of one of these Language Group.
  404. //
  405. while (*pLocale)
  406. {
  407. if(PRIMARYLANGID(UserLocaleID) == PRIMARYLANGID(*pLocale))
  408. {
  409. //
  410. // Save the new locale information.
  411. //
  412. UserLocaleID = SysLocaleID;
  413. bShowRtL = IsRtLLocale(UserLocaleID);
  414. bHebrewUI = (PRIMARYLANGID(UserLocaleID) == LANG_HEBREW);
  415. bShowArabic = (bShowRtL && (PRIMARYLANGID(LANGIDFROMLCID(UserLocaleID)) != LANG_HEBREW));
  416. //
  417. // Install the new locale by adding the appropriate information
  418. // to the registry.
  419. //
  420. Intl_InstallUserLocale(UserLocaleID, FALSE, TRUE);
  421. //
  422. // Update the NLS process cache.
  423. //
  424. NlsResetProcessLocale();
  425. //
  426. // Reset the registry user locale value.
  427. //
  428. RegUserLocaleID = UserLocaleID;
  429. //
  430. // Need to make sure the proper keyboard layout is installed.
  431. //
  432. Intl_InstallKeyboardLayout(hDlg, UserLocaleID, 0, FALSE, FALSE, FALSE);
  433. //
  434. // Force the loop the end.
  435. //
  436. bStopLoop = TRUE;
  437. break;
  438. }
  439. pLocale++;
  440. }
  441. }
  442. pLG = pLG->pNext;
  443. }
  444. }
  445. //
  446. // Initialize Inf stuff.
  447. //
  448. if (!Intl_InitInf(hDlg, &hIntlInf, szIntlInf, &FileQueue, &QueueContext))
  449. {
  450. SetCursor(hcurSave);
  451. return (FALSE);
  452. }
  453. //
  454. // Determine with language collection we are dealing with
  455. //
  456. if( bInstall)
  457. {
  458. if (collection == COMPLEX_COLLECTION)
  459. {
  460. pszInfSection = szLGComplexInstall;
  461. }
  462. else if (collection == CJK_COLLECTION)
  463. {
  464. pszInfSection = szLGExtInstall;
  465. }
  466. else
  467. {
  468. return (FALSE);
  469. }
  470. }
  471. else
  472. {
  473. if (collection == COMPLEX_COLLECTION)
  474. {
  475. pszInfSection = szLGComplexRemove;
  476. }
  477. else if (collection == CJK_COLLECTION)
  478. {
  479. pszInfSection = szLGExtRemove;
  480. }
  481. else
  482. {
  483. return (FALSE);
  484. }
  485. }
  486. //
  487. // Enqueue the complex script language group files so that they may be
  488. // copied. This only handles the CopyFiles entries in the inf file.
  489. //
  490. if (!SetupInstallFilesFromInfSection( hIntlInf,
  491. NULL,
  492. FileQueue,
  493. pszInfSection,
  494. pSetupSourcePath,
  495. SP_COPY_NEWER ))
  496. {
  497. //
  498. // Setup failed to find the complex script language group.
  499. // This shouldn't happen - the inf file is messed up.
  500. //
  501. ShowMsg( hDlg,
  502. IDS_ML_COPY_FAILED,
  503. 0,
  504. MB_OK_OOPS,
  505. TEXT("Supplemental Language Support") );
  506. }
  507. //
  508. // See if we need to install/remove any files.
  509. //
  510. if (SetupScanFileQueue( FileQueue,
  511. SPQ_SCAN_PRUNE_COPY_QUEUE | SPQ_SCAN_FILE_VALIDITY,
  512. GetParent(hDlg),
  513. NULL,
  514. NULL,
  515. &dwRet ))
  516. {
  517. //
  518. // Copy the files in the queue.
  519. //
  520. if (!SetupCommitFileQueue( GetParent(hDlg),
  521. FileQueue,
  522. SetupDefaultQueueCallback,
  523. QueueContext ))
  524. {
  525. //
  526. // This can happen if the user hits Cancel from within
  527. // the setup dialog.
  528. //
  529. bInstall = FALSE;
  530. ShowMsg( hDlg,
  531. IDS_ML_SETUP_FAILED,
  532. 0,
  533. MB_OK_OOPS,
  534. NULL );
  535. }
  536. else
  537. {
  538. //
  539. // Call setup to install other inf info for this
  540. // language group.
  541. //
  542. if (!SetupInstallFromInfSection( GetParent(hDlg),
  543. hIntlInf,
  544. pszInfSection,
  545. SPINST_ALL & ~SPINST_FILES,
  546. NULL,
  547. pSetupSourcePath,
  548. 0,
  549. NULL,
  550. NULL,
  551. NULL,
  552. NULL ))
  553. {
  554. //
  555. // Setup failed.
  556. //
  557. // Already copied the language group file, so no need to
  558. // change the status of the language group info here.
  559. //
  560. // This shouldn't happen - the inf file is messed up.
  561. //
  562. ShowMsg( hDlg,
  563. IDS_ML_INSTALL_FAILED,
  564. 0,
  565. MB_OK_OOPS,
  566. TEXT("Supplemental Language Support") );
  567. }
  568. else
  569. {
  570. //
  571. // Run any necessary apps (for IME installation).
  572. //
  573. if (bInstall)
  574. {
  575. Intl_RunRegApps(c_szIntlRun);
  576. }
  577. bActionSuccess = TRUE;
  578. }
  579. }
  580. }
  581. //
  582. // Update the status of all language groups included in the
  583. // Supplemental Language support.
  584. //
  585. if (bActionSuccess)
  586. {
  587. if (bInstall)
  588. {
  589. //
  590. // Mark as installed.
  591. //
  592. Language_SetCollectionStatus(collection,
  593. ML_INSTALL,
  594. TRUE);
  595. Language_SetCollectionStatus(collection,
  596. ~(ML_DISABLE | ML_REMOVE),
  597. FALSE);
  598. }
  599. else
  600. {
  601. //
  602. // Mark as removed.
  603. //
  604. Language_SetCollectionStatus(collection,
  605. (ML_DISABLE | ML_REMOVE),
  606. TRUE);
  607. Language_SetCollectionStatus(collection,
  608. ~ML_INSTALL,
  609. FALSE);
  610. }
  611. }
  612. //
  613. // Close Inf stuff.
  614. //
  615. Intl_CloseInf(hIntlInf, FileQueue, QueueContext);
  616. //
  617. // Turn off the hour glass.
  618. //
  619. SetCursor(hcurSave);
  620. //
  621. // Return the result.
  622. //
  623. return (bActionSuccess);
  624. }
  625. ////////////////////////////////////////////////////////////////////////////
  626. //
  627. // Language_InstallLanguageCollection
  628. //
  629. ////////////////////////////////////////////////////////////////////////////
  630. BOOL Language_InstallLanguageCollection(
  631. BOOL bInstall,
  632. DWORD collection,
  633. HWND hDlg)
  634. {
  635. //
  636. // Check if we are in setup. If in setup we need to show up a dialog
  637. // instead of using the progress bar of setup.
  638. //
  639. if( g_bSetupCase)
  640. {
  641. HWND hDialog;
  642. BOOL retVal;
  643. //
  644. // Create a dialog.
  645. //
  646. hDialog = CreateDialog( hInstance,
  647. MAKEINTRESOURCE(DLG_SETUP_INFORMATION),
  648. hDlg,
  649. Language_InstallLanguageCollectionProc);
  650. //
  651. // Show dialog
  652. //
  653. ShowWindow(hDialog, SW_SHOW);
  654. //
  655. // proceed with the installation
  656. //
  657. retVal = Language_InstallCollection(bInstall, collection, hDlg);
  658. //
  659. // Close the dialog
  660. //
  661. DestroyWindow(hDialog);
  662. return (retVal);
  663. }
  664. else
  665. {
  666. return Language_InstallCollection(bInstall, collection, hDlg);
  667. }
  668. }
  669. ////////////////////////////////////////////////////////////////////////////
  670. //
  671. // Language_CommandChange
  672. //
  673. ////////////////////////////////////////////////////////////////////////////
  674. BOOL Language_CommandChange(
  675. HWND hDlg)
  676. {
  677. //
  678. // Call Text Services input page
  679. //
  680. Intl_CallTextServices();
  681. //
  682. // Return the result.
  683. //
  684. return (TRUE);
  685. }
  686. ////////////////////////////////////////////////////////////////////////////
  687. //
  688. // Language_ClearValues
  689. //
  690. // Reset each of the list boxes in the advanced property sheet page.
  691. //
  692. ////////////////////////////////////////////////////////////////////////////
  693. void Language_ClearValues(
  694. HWND hDlg)
  695. {
  696. }
  697. ////////////////////////////////////////////////////////////////////////////
  698. //
  699. // Language_SetValues
  700. //
  701. // Initialize all of the controls in the advanced property sheet page.
  702. //
  703. ////////////////////////////////////////////////////////////////////////////
  704. void Language_SetValues(
  705. HWND hDlg)
  706. {
  707. HWND hUILang = GetDlgItem(hDlg, IDC_UI_LANGUAGE);
  708. TCHAR szUILang[SIZE_128];
  709. DWORD dwIndex;
  710. //
  711. // Fill in the current UI Language settings in the list.
  712. //
  713. ComboBox_GetLBText( hUILang, ComboBox_GetCurSel(hUILang), szUILang );
  714. Language_UpdateUILanguageCombo(hDlg);
  715. dwIndex = ComboBox_GetCurSel(hUILang);
  716. if (ComboBox_SetCurSel( hUILang,
  717. ComboBox_FindStringExact( hUILang,
  718. -1,
  719. szUILang ) ) == CB_ERR)
  720. {
  721. ComboBox_SetCurSel(hUILang, dwIndex);
  722. }
  723. //
  724. // Verify if the user has administrative privileges. If not, then
  725. // disable the controls.
  726. //
  727. if (!g_bAdmin_Privileges)
  728. {
  729. //
  730. // Disable the complex scripts install/remove.
  731. //
  732. EnableWindow(GetDlgItem(hDlg, IDC_LANGUAGE_COMPLEX), FALSE);
  733. //
  734. // Disable the CJK install/remove.
  735. //
  736. EnableWindow(GetDlgItem(hDlg, IDC_LANGUAGE_CJK), FALSE);
  737. }
  738. //
  739. // Verify that the collection is not marked as permanent.
  740. //
  741. if (Language_GetCollectionStatus(COMPLEX_COLLECTION, ML_PERMANENT))
  742. {
  743. //
  744. // Disable the complex scripts install/remove.
  745. //
  746. EnableWindow(GetDlgItem(hDlg, IDC_LANGUAGE_COMPLEX), FALSE);
  747. }
  748. if (Language_GetCollectionStatus(CJK_COLLECTION, ML_PERMANENT))
  749. {
  750. //
  751. // Disable the CJK install/remove.
  752. //
  753. EnableWindow(GetDlgItem(hDlg, IDC_LANGUAGE_CJK), FALSE);
  754. }
  755. //
  756. // Check if we can install the CJK Language Groups. This is only
  757. // the case on a Clean install over the Network.
  758. //
  759. if (g_bSetupCase)
  760. {
  761. //
  762. // Check if we have at least one file in the \Lang directory.
  763. //
  764. if (!Intl_LanguageGroupFilesExist())
  765. {
  766. //
  767. // Disable the CJK install/remove.
  768. //
  769. EnableWindow(GetDlgItem(hDlg, IDC_LANGUAGE_CJK), FALSE);
  770. }
  771. }
  772. }
  773. ////////////////////////////////////////////////////////////////////////////
  774. //
  775. // Language_ApplySettings
  776. //
  777. // If anything has changed, update the settings. Notify the parent of
  778. // changes and reset the change flag stored in the property sheet page
  779. // structure appropriately.
  780. //
  781. ////////////////////////////////////////////////////////////////////////////
  782. BOOL Language_ApplySettings(
  783. HWND hDlg)
  784. {
  785. LPPROPSHEETPAGE lpPropSheet = (LPPROPSHEETPAGE)(GetWindowLongPtr(hDlg, DWLP_USER));
  786. LPARAM Changes = lpPropSheet->lParam;
  787. HCURSOR hcurSave;
  788. BOOL bReboot = FALSE;
  789. //
  790. // See if there are any changes.
  791. //
  792. if (Changes <= LG_EverChg)
  793. {
  794. return (TRUE);
  795. }
  796. //
  797. // Put up the hour glass.
  798. //
  799. hcurSave = SetCursor(LoadCursor(NULL, IDC_WAIT));
  800. //
  801. // See if there are any changes to the Complex Srcipts Languages group
  802. // installation.
  803. //
  804. if (Changes & LG_Complex)
  805. {
  806. //
  807. // Install/Remove Complex Scripts Language groups.
  808. //
  809. if (Language_InstallLanguageCollection(g_bInstallComplex, COMPLEX_COLLECTION, hDlg))
  810. {
  811. if (g_bInstallComplex)
  812. {
  813. //
  814. // Check the box.
  815. //
  816. CheckDlgButton(hDlg, IDC_LANGUAGE_COMPLEX, BST_CHECKED);
  817. bComplexInitState = TRUE;
  818. }
  819. else
  820. {
  821. //
  822. // Uncheck the box.
  823. //
  824. CheckDlgButton(hDlg, IDC_LANGUAGE_COMPLEX, BST_UNCHECKED);
  825. bComplexInitState = FALSE;
  826. }
  827. //
  828. // Need to reboot in order for the change to take effect.
  829. //
  830. bReboot = TRUE;
  831. }
  832. else
  833. {
  834. if (g_bInstallComplex)
  835. {
  836. //
  837. // UnCheck the box.
  838. //
  839. CheckDlgButton(hDlg, IDC_LANGUAGE_COMPLEX, BST_UNCHECKED);
  840. }
  841. else
  842. {
  843. //
  844. // Check the box.
  845. //
  846. CheckDlgButton(hDlg, IDC_LANGUAGE_COMPLEX, BST_CHECKED);
  847. }
  848. }
  849. }
  850. //
  851. // See if there are any changes to the CJK Languages group
  852. // installation.
  853. //
  854. if (Changes & LG_CJK)
  855. {
  856. //
  857. // Install/Remove CJK Language groups.
  858. //
  859. if (Language_InstallLanguageCollection(g_bInstallCJK, CJK_COLLECTION, hDlg))
  860. {
  861. if (g_bInstallCJK)
  862. {
  863. //
  864. // Check the box.
  865. //
  866. CheckDlgButton(hDlg, IDC_LANGUAGE_CJK, BST_CHECKED);
  867. bCJKInitState = TRUE;
  868. }
  869. else
  870. {
  871. //
  872. // Uncheck the box.
  873. //
  874. CheckDlgButton(hDlg, IDC_LANGUAGE_CJK, BST_UNCHECKED);
  875. bCJKInitState = FALSE;
  876. }
  877. //
  878. // Need to reboot to the change to take effect
  879. //
  880. bReboot = TRUE;
  881. }
  882. else
  883. {
  884. if (g_bInstallCJK)
  885. {
  886. //
  887. // Uncheck the box.
  888. //
  889. CheckDlgButton(hDlg, IDC_LANGUAGE_CJK, BST_UNCHECKED);
  890. }
  891. else
  892. {
  893. //
  894. // Check the box.
  895. //
  896. CheckDlgButton(hDlg, IDC_LANGUAGE_CJK, BST_CHECKED);
  897. }
  898. }
  899. }
  900. //
  901. // See if there are any changes to the UI Language.
  902. //
  903. if (Changes & LG_UILanguage)
  904. {
  905. DWORD dwUILang;
  906. LANGID UILang;
  907. HWND hUILang = GetDlgItem(hDlg, IDC_UI_LANGUAGE);
  908. //
  909. // Get the current selection.
  910. //
  911. dwUILang = ComboBox_GetCurSel(hUILang);
  912. //
  913. // See if the current selection is different from the original
  914. // selection.
  915. //
  916. if (dwUILang != CB_ERR)
  917. {
  918. //
  919. // Get the UI Language id for the current selection.
  920. //
  921. UILang = (LANGID)ComboBox_GetItemData(hUILang, dwUILang);
  922. //
  923. // Set the UI Language value in the user's registry.
  924. //
  925. if (NT_SUCCESS(NtSetDefaultUILanguage(UILang)))
  926. {
  927. // deleting the key this way makes the key invalid for this process
  928. // this way the new UI doesn't get bogus cached values
  929. SHDeleteKey(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Windows\\ShellNoRoam\\MUICache"));
  930. }
  931. //
  932. // Install keyboard assciated with the UI language
  933. //
  934. Intl_InstallKeyboardLayout(hDlg, MAKELCID(UILang, SORT_DEFAULT), 0, FALSE, FALSE, FALSE);
  935. //
  936. // Alert them that the UI change will take effect next time
  937. // they log on.
  938. //
  939. ShowMsg( hDlg,
  940. IDS_CHANGE_UI_LANG_NOT_ADMIN,
  941. IDS_TITLE_STRING,
  942. MB_OK | MB_ICONINFORMATION,
  943. NULL );
  944. }
  945. }
  946. //
  947. // Reset the property page settings.
  948. //
  949. PropSheet_UnChanged(GetParent(hDlg), hDlg);
  950. Changes = LG_EverChg;
  951. //
  952. // Turn off the hour glass.
  953. //
  954. SetCursor(hcurSave);
  955. //
  956. // See if we need to display the reboot message.
  957. //
  958. if ((!g_bSetupCase) && (bReboot))
  959. {
  960. if ((RegionalChgState & AD_SystemLocale) ||
  961. (RegionalChgState & AD_CodePages))
  962. {
  963. RegionalChgState &= ~Process_Languages;
  964. RegionalChgState |= AD_SystemLocale;
  965. }
  966. else
  967. {
  968. if (ShowMsg( hDlg,
  969. IDS_REBOOT_STRING,
  970. IDS_TITLE_STRING,
  971. MB_YESNO | MB_ICONQUESTION,
  972. NULL ) == IDYES)
  973. {
  974. Intl_RebootTheSystem();
  975. }
  976. }
  977. }
  978. //
  979. // Return success.
  980. //
  981. return (TRUE);
  982. }
  983. ////////////////////////////////////////////////////////////////////////////
  984. //
  985. // Language_ValidatePPS
  986. //
  987. // Validate each of the combo boxes whose values are constrained.
  988. // If any of the input fails, notify the user and then return FALSE
  989. // to indicate validation failure.
  990. //
  991. ////////////////////////////////////////////////////////////////////////////
  992. BOOL Language_ValidatePPS(
  993. HWND hDlg,
  994. LPARAM Changes)
  995. {
  996. //
  997. // If nothing has changed, return TRUE immediately.
  998. //
  999. if (Changes <= LG_EverChg)
  1000. {
  1001. return (TRUE);
  1002. }
  1003. return (TRUE);
  1004. }
  1005. ////////////////////////////////////////////////////////////////////////////
  1006. //
  1007. // Language_InitPropSheet
  1008. //
  1009. // The extra long value for the property sheet page is used as a set of
  1010. // state or change flags for each of the list boxes in the property sheet.
  1011. // Initialize this value to 0. Call Language_SetValues with the property
  1012. // sheet handle to initialize all of the property sheet controls. Limit
  1013. // the length of the text in some of the ComboBoxes.
  1014. //
  1015. ////////////////////////////////////////////////////////////////////////////
  1016. void Language_InitPropSheet(
  1017. HWND hDlg,
  1018. LPARAM lParam)
  1019. {
  1020. DWORD dwColor;
  1021. //
  1022. // The lParam holds a pointer to the property sheet page. Save it
  1023. // for later reference.
  1024. //
  1025. SetWindowLongPtr(hDlg, DWLP_USER, lParam);
  1026. //
  1027. // Set values.
  1028. //
  1029. if (pLanguageGroups == NULL)
  1030. {
  1031. Intl_LoadLanguageGroups(hDlg);
  1032. }
  1033. Language_SetValues(hDlg);
  1034. //
  1035. // Determine if Complex Scripts language support is installed.
  1036. //
  1037. if (Language_GetCollectionStatus(COMPLEX_COLLECTION, ML_INSTALL))
  1038. {
  1039. //
  1040. // Check the box.
  1041. //
  1042. CheckDlgButton(hDlg, IDC_LANGUAGE_COMPLEX, BST_CHECKED);
  1043. bComplexInitState = TRUE;
  1044. }
  1045. else
  1046. {
  1047. //
  1048. // Uncheck the box.
  1049. //
  1050. CheckDlgButton(hDlg, IDC_LANGUAGE_COMPLEX, BST_UNCHECKED);
  1051. bComplexInitState = FALSE;
  1052. }
  1053. //
  1054. // Determine if CJK language support is installed.
  1055. //
  1056. if (Language_GetCollectionStatus(CJK_COLLECTION, ML_INSTALL))
  1057. {
  1058. //
  1059. // Check the box.
  1060. //
  1061. CheckDlgButton(hDlg, IDC_LANGUAGE_CJK, BST_CHECKED);
  1062. bCJKInitState = TRUE;
  1063. }
  1064. else
  1065. {
  1066. //
  1067. // Uncheck the box.
  1068. //
  1069. CheckDlgButton(hDlg, IDC_LANGUAGE_CJK, BST_UNCHECKED);
  1070. bCJKInitState = FALSE;
  1071. }
  1072. }
  1073. ////////////////////////////////////////////////////////////////////////////
  1074. //
  1075. // LanguagesDlgProc
  1076. //
  1077. ////////////////////////////////////////////////////////////////////////////
  1078. INT_PTR CALLBACK LanguageDlgProc(
  1079. HWND hDlg,
  1080. UINT message,
  1081. WPARAM wParam,
  1082. LPARAM lParam)
  1083. {
  1084. LPPROPSHEETPAGE lpPropSheet = (LPPROPSHEETPAGE)(GetWindowLongPtr(hDlg, DWLP_USER));
  1085. switch (message)
  1086. {
  1087. case ( WM_NOTIFY ) :
  1088. {
  1089. LPNMHDR lpnm = (NMHDR *)lParam;
  1090. switch (lpnm->code)
  1091. {
  1092. case ( PSN_SETACTIVE ) :
  1093. {
  1094. //
  1095. // If there has been a change in the regional Locale
  1096. // setting, clear all of the current info in the
  1097. // property sheet, get the new values, and update the
  1098. // appropriate registry values.
  1099. //
  1100. if (Verified_Regional_Chg & Process_Languages)
  1101. {
  1102. Verified_Regional_Chg &= ~Process_Languages;
  1103. Language_ClearValues(hDlg);
  1104. Language_SetValues(hDlg);
  1105. lpPropSheet->lParam = 0;
  1106. }
  1107. break;
  1108. }
  1109. case ( PSN_KILLACTIVE ) :
  1110. {
  1111. //
  1112. // Validate the entries on the property page.
  1113. //
  1114. SetWindowLongPtr( hDlg,
  1115. DWLP_MSGRESULT,
  1116. !Language_ValidatePPS(hDlg, lpPropSheet->lParam) );
  1117. break;
  1118. }
  1119. case ( PSN_APPLY ) :
  1120. {
  1121. //
  1122. // Apply the settings.
  1123. //
  1124. if (Language_ApplySettings(hDlg))
  1125. {
  1126. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
  1127. //
  1128. // Check if we need to do something for the
  1129. // default user.
  1130. //
  1131. if (g_bDefaultUser)
  1132. {
  1133. g_bSettingsChanged = TRUE;
  1134. Intl_SaveDefaultUserSettings();
  1135. }
  1136. //
  1137. // Zero out the LG_EverChg bit.
  1138. //
  1139. lpPropSheet->lParam = 0;
  1140. }
  1141. else
  1142. {
  1143. SetWindowLongPtr( hDlg,
  1144. DWLP_MSGRESULT,
  1145. PSNRET_INVALID_NOCHANGEPAGE );
  1146. }
  1147. break;
  1148. }
  1149. default :
  1150. {
  1151. return (FALSE);
  1152. }
  1153. }
  1154. break;
  1155. }
  1156. case ( WM_INITDIALOG ) :
  1157. {
  1158. //
  1159. // Init property sheet.
  1160. //
  1161. Language_InitPropSheet(hDlg, lParam);
  1162. break;
  1163. }
  1164. case ( WM_HELP ) :
  1165. {
  1166. WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
  1167. szHelpFile,
  1168. HELP_WM_HELP,
  1169. (DWORD_PTR)(LPTSTR)aLanguagesHelpIds );
  1170. break;
  1171. }
  1172. case ( WM_CONTEXTMENU ) : // right mouse click
  1173. {
  1174. WinHelp( (HWND)wParam,
  1175. szHelpFile,
  1176. HELP_CONTEXTMENU,
  1177. (DWORD_PTR)(LPTSTR)aLanguagesHelpIds );
  1178. break;
  1179. }
  1180. case ( WM_COMMAND ) :
  1181. {
  1182. switch (LOWORD(wParam))
  1183. {
  1184. case ( IDC_UI_LANGUAGE ) :
  1185. {
  1186. if (HIWORD(wParam) == CBN_SELCHANGE)
  1187. {
  1188. DWORD dwUILang;
  1189. HWND hUILang = GetDlgItem(hDlg, IDC_UI_LANGUAGE);
  1190. //
  1191. // Get the current selection.
  1192. //
  1193. dwUILang = ComboBox_GetCurSel(hUILang);
  1194. //
  1195. // Check if the user reverted the change back
  1196. //
  1197. if (dwUILang != CB_ERR)
  1198. {
  1199. if ((LANGID)ComboBox_GetItemData(hUILang, dwUILang) == Intl_GetPendingUILanguage())
  1200. {
  1201. //
  1202. // Reset the LG_UILanguage change flag.
  1203. //
  1204. lpPropSheet->lParam &= ~LG_UILanguage;
  1205. }
  1206. else
  1207. {
  1208. //
  1209. // Set the LG_UILanguage change flag.
  1210. //
  1211. lpPropSheet->lParam |= LG_UILanguage;
  1212. }
  1213. }
  1214. }
  1215. break;
  1216. }
  1217. case ( IDC_LANGUAGE_CHANGE ) :
  1218. {
  1219. if (Language_CommandChange(hDlg))
  1220. {
  1221. //
  1222. // Set the LG_Change change flag.
  1223. //
  1224. lpPropSheet->lParam |= LG_Change;
  1225. }
  1226. break;
  1227. }
  1228. case ( IDC_LANGUAGE_CJK ) :
  1229. {
  1230. BOOL curState;
  1231. //
  1232. // Verify the check box state.
  1233. //
  1234. if (IsDlgButtonChecked(hDlg, IDC_LANGUAGE_CJK))
  1235. {
  1236. #ifdef i386
  1237. ShowMsg( hDlg,
  1238. IDS_SUP_LANG_SUP_CJK_INST,
  1239. IDS_SUP_LANG_SUP_INST_TITLE,
  1240. MB_OK_OOPS,
  1241. NULL );
  1242. #endif
  1243. #ifdef IA64
  1244. ShowMsg( hDlg,
  1245. IDS_SUP_LANG_SUP_CJK_INST64,
  1246. IDS_SUP_LANG_SUP_INST_TITLE,
  1247. MB_OK_OOPS,
  1248. NULL );
  1249. #endif
  1250. curState = TRUE;
  1251. }
  1252. else
  1253. {
  1254. ShowMsg( hDlg,
  1255. IDS_SUP_LANG_SUP_CJK_REM,
  1256. IDS_SUP_LANG_SUP_REM_TITLE,
  1257. MB_OK_OOPS,
  1258. NULL );
  1259. curState = FALSE;
  1260. }
  1261. //
  1262. // Set the LG_CJK change flag.
  1263. //
  1264. if (curState != bCJKInitState)
  1265. {
  1266. lpPropSheet->lParam |= LG_CJK;
  1267. g_bInstallCJK = curState;
  1268. RegionalChgState |= Process_Languages;
  1269. }
  1270. else
  1271. {
  1272. lpPropSheet->lParam &= ~LG_CJK;
  1273. RegionalChgState &= ~Process_Languages;
  1274. }
  1275. //
  1276. // Enable/Disable the avability of Collection dependant locale
  1277. //
  1278. if (curState)
  1279. {
  1280. Language_SetCollectionStatus(CJK_COLLECTION,
  1281. ML_INSTALL,
  1282. TRUE);
  1283. Language_SetCollectionStatus(CJK_COLLECTION,
  1284. ~(ML_DISABLE | ML_REMOVE),
  1285. FALSE);
  1286. }
  1287. else
  1288. {
  1289. Language_SetCollectionStatus(CJK_COLLECTION,
  1290. (ML_DISABLE | ML_REMOVE),
  1291. TRUE);
  1292. Language_SetCollectionStatus(CJK_COLLECTION,
  1293. ~ML_INSTALL,
  1294. FALSE);
  1295. }
  1296. //
  1297. // Register that we changed the Complex Script and/or CJK
  1298. // installation. This will affect settings in other pages. All
  1299. // other changes to settings on this page do not affect other pages.
  1300. //
  1301. Verified_Regional_Chg |= (Process_Regional | Process_Advanced);
  1302. break;
  1303. }
  1304. case ( IDC_LANGUAGE_COMPLEX ) :
  1305. {
  1306. BOOL curState;
  1307. //
  1308. // Verify the check box state.
  1309. //
  1310. if (IsDlgButtonChecked(hDlg, IDC_LANGUAGE_COMPLEX))
  1311. {
  1312. #ifdef i386
  1313. ShowMsg( hDlg,
  1314. IDS_SUP_LANG_SUP_COMPLEX_INST,
  1315. IDS_SUP_LANG_SUP_INST_TITLE,
  1316. MB_OK_OOPS,
  1317. NULL );
  1318. #endif
  1319. #ifdef IA64
  1320. ShowMsg( hDlg,
  1321. IDS_SUP_LANG_SUP_COMPLEX_INST64,
  1322. IDS_SUP_LANG_SUP_INST_TITLE,
  1323. MB_OK_OOPS,
  1324. NULL );
  1325. #endif
  1326. curState = TRUE;
  1327. }
  1328. else
  1329. {
  1330. ShowMsg( hDlg,
  1331. IDS_SUP_LANG_SUP_COMPLEX_REM,
  1332. IDS_SUP_LANG_SUP_REM_TITLE,
  1333. MB_OK_OOPS,
  1334. NULL );
  1335. curState = FALSE;
  1336. }
  1337. //
  1338. // Set the LG_Complex change flag.
  1339. //
  1340. if (curState != bComplexInitState)
  1341. {
  1342. lpPropSheet->lParam |= LG_Complex;
  1343. g_bInstallComplex = curState;
  1344. RegionalChgState |= Process_Languages;
  1345. }
  1346. else
  1347. {
  1348. lpPropSheet->lParam &= ~LG_Complex;
  1349. RegionalChgState &= ~Process_Languages;
  1350. }
  1351. //
  1352. // Enable/Disable the avability of Collection dependant locale
  1353. //
  1354. if (curState)
  1355. {
  1356. Language_SetCollectionStatus(COMPLEX_COLLECTION,
  1357. ML_INSTALL,
  1358. TRUE);
  1359. Language_SetCollectionStatus(COMPLEX_COLLECTION,
  1360. ~(ML_DISABLE | ML_REMOVE),
  1361. FALSE);
  1362. }
  1363. else
  1364. {
  1365. Language_SetCollectionStatus(COMPLEX_COLLECTION,
  1366. (ML_DISABLE | ML_REMOVE),
  1367. TRUE);
  1368. Language_SetCollectionStatus(COMPLEX_COLLECTION,
  1369. ~ML_INSTALL,
  1370. FALSE);
  1371. }
  1372. //
  1373. // Register that we changed the Complex Script and/or CJK
  1374. // installation. This will affect settings in other pages. All
  1375. // other changes to settings on this page do not affect other pages.
  1376. //
  1377. Verified_Regional_Chg |= (Process_Regional | Process_Advanced);
  1378. break;
  1379. }
  1380. }
  1381. //
  1382. // Turn on ApplyNow button.
  1383. //
  1384. if (lpPropSheet->lParam > LG_EverChg)
  1385. {
  1386. PropSheet_Changed(GetParent(hDlg), hDlg);
  1387. }
  1388. break;
  1389. }
  1390. default :
  1391. {
  1392. return (FALSE);
  1393. }
  1394. }
  1395. return (TRUE);
  1396. }