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.

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