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.

1029 lines
30 KiB

  1. /*++
  2. Copyright (c) 1994-2000, Microsoft Corporation All rights reserved.
  3. Module Name:
  4. intl.c
  5. Abstract:
  6. This module contains the main routines for the Regional Options applet.
  7. Revision History:
  8. --*/
  9. //
  10. // Include Files.
  11. //
  12. #include "intl.h"
  13. #include <cpl.h>
  14. #include <tchar.h>
  15. //
  16. // Constant Declarations.
  17. //
  18. #define MAX_PAGES 3 // limit on the number of pages on the first level
  19. #define LANGUAGE_PACK_KEY TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\LanguagePack")
  20. #define LANGUAGE_PACK_VALUE TEXT("COMPLEXSCRIPTS")
  21. #define LANGUAGE_PACK_DLL TEXT("lpk.dll")
  22. static const TCHAR c_szLanguages[] =
  23. TEXT("System\\CurrentControlSet\\Control\\Nls\\Language");
  24. static const TCHAR c_szControlPanelIntl[] =
  25. TEXT("Control Panel\\International");
  26. //
  27. // Global Variables.
  28. //
  29. HANDLE g_hMutex = NULL;
  30. TCHAR szMutexName[] = TEXT("RegionalSettings_InputLocaleMutex");
  31. HANDLE g_hEvent = NULL;
  32. TCHAR szEventName[] = TEXT("RegionalSettings_InputLocaleEvent");
  33. TCHAR aInt_Str[cInt_Str][3] = { TEXT("0"),
  34. TEXT("1"),
  35. TEXT("2"),
  36. TEXT("3"),
  37. TEXT("4"),
  38. TEXT("5"),
  39. TEXT("6"),
  40. TEXT("7"),
  41. TEXT("8"),
  42. TEXT("9")
  43. };
  44. BOOL g_bAdmin_Privileges = FALSE;
  45. DWORD g_dwLastSorting;
  46. DWORD g_dwCurSorting;
  47. BOOL g_bCustomize = FALSE;
  48. BOOL g_bDefaultUser = FALSE;
  49. DWORD g_dwCustChange = 0L;
  50. BOOL g_bShowSortingTab = FALSE;
  51. BOOL g_bInstallComplex = FALSE;
  52. BOOL g_bInstallCJK = FALSE;
  53. TCHAR szSample_Number[] = TEXT("123456789.00");
  54. TCHAR szNegSample_Number[] = TEXT("-123456789.00");
  55. TCHAR szTimeChars[] = TEXT(" Hhmst,-./:;\\ ");
  56. TCHAR szTCaseSwap[] = TEXT(" MST");
  57. TCHAR szTLetters[] = TEXT("Hhmst");
  58. TCHAR szSDateChars[] = TEXT(" dgMy,-./:;\\ ");
  59. TCHAR szSDCaseSwap[] = TEXT(" DGmY");
  60. TCHAR szSDLetters[] = TEXT("dgMy");
  61. TCHAR szLDateChars[] = TEXT(" dgMy,-./:;\\");
  62. TCHAR szLDCaseSwap[] = TEXT(" DGmY");
  63. TCHAR szLDLetters[] = TEXT("dgHhMmsty");
  64. TCHAR szStyleH[3];
  65. TCHAR szStyleh[3];
  66. TCHAR szStyleM[3];
  67. TCHAR szStylem[3];
  68. TCHAR szStyles[3];
  69. TCHAR szStylet[3];
  70. TCHAR szStyled[3];
  71. TCHAR szStyley[3];
  72. TCHAR szLocaleGetError[SIZE_128];
  73. TCHAR szIntl[] = TEXT("intl");
  74. TCHAR szInvalidSDate[] = TEXT("Mdyg'");
  75. TCHAR szInvalidSTime[] = TEXT("Hhmst'");
  76. HINSTANCE hInstance;
  77. int Verified_Regional_Chg = 0;
  78. int RegionalChgState = 0;
  79. BOOL Styles_Localized;
  80. LCID UserLocaleID;
  81. LCID SysLocaleID;
  82. LCID RegUserLocaleID;
  83. LCID RegSysLocaleID;
  84. BOOL bShowArabic;
  85. BOOL bShowRtL;
  86. BOOL bHebrewUI;
  87. BOOL bLPKInstalled;
  88. TCHAR szSetupSourcePath[MAX_PATH];
  89. TCHAR szSetupSourcePathWithArchitecture[MAX_PATH];
  90. LPTSTR pSetupSourcePath = NULL;
  91. LPTSTR pSetupSourcePathWithArchitecture = NULL;
  92. BOOL g_bCDROM = FALSE;
  93. BOOL g_bSetupCase = FALSE;
  94. BOOL g_bLog = FALSE;
  95. BOOL g_bProgressBarDisplay = FALSE;
  96. BOOL g_bSettingsChanged = FALSE;
  97. BOOL g_bUnttendMode = FALSE;
  98. BOOL g_bMatchUIFont = FALSE;
  99. const TCHAR c_szInstalledLocales[] = TEXT("System\\CurrentControlSet\\Control\\Nls\\Locale");
  100. const TCHAR c_szLanguageGroups[] = TEXT("System\\CurrentControlSet\\Control\\Nls\\Language Groups");
  101. const TCHAR c_szMUILanguages[] = TEXT("System\\CurrentControlSet\\Control\\Nls\\MUILanguages");
  102. const TCHAR c_szLIPInstalled[] = TEXT("Software\\Microsoft\\Windows Interface Pack\\LIPInstalled");
  103. const TCHAR c_szFontSubstitute[] = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes");
  104. const TCHAR c_szSetupKey[] = TEXT("System\\Setup");
  105. const TCHAR c_szCPanelIntl[] = TEXT("Control Panel\\International");
  106. const TCHAR c_szCPanelIntl_DefUser[] = TEXT(".DEFAULT\\Control Panel\\International");
  107. const TCHAR c_szCtfmon[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Run");
  108. const TCHAR c_szCtfmon_DefUser[] = TEXT(".DEFAULT\\Software\\Microsoft\\Windows\\CurrentVersion\\Run");
  109. const TCHAR c_szCPanelDesktop[] = TEXT("Control Panel\\Desktop");
  110. const TCHAR c_szCPanelDesktop_DefUser[] = TEXT(".DEFAULT\\Control Panel\\Desktop");
  111. const TCHAR c_szKbdLayouts[] = TEXT("Keyboard Layout");
  112. const TCHAR c_szKbdLayouts_DefUser[] = TEXT(".DEFAULT\\Keyboard Layout");
  113. const TCHAR c_szInputMethod[] = TEXT("Control Panel\\Input Method");
  114. const TCHAR c_szInputMethod_DefUser[] = TEXT(".DEFAULT\\Control Panel\\Input Method");
  115. const TCHAR c_szInputTips[] = TEXT("Software\\Microsoft\\CTF");
  116. const TCHAR c_szInputTips_DefUser[] = TEXT(".DEFAULT\\Software\\Microsoft\\CTF");
  117. const TCHAR c_szMUIPolicyKeyPath[] = TEXT("Software\\Policies\\Microsoft\\Control Panel\\Desktop");
  118. const TCHAR c_szMUIValue[] = TEXT("MultiUILanguageId");
  119. const TCHAR c_szIntlRun[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\IntlRun");
  120. const TCHAR c_szSysocmgr[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\IntlRun.OC");
  121. TCHAR szIntlInf[] = TEXT("intl.inf");
  122. TCHAR szHelpFile[] = TEXT("windows.hlp");
  123. TCHAR szFontSubstitute[] = TEXT("FontSubstitute");
  124. TCHAR szLocaleListPrefix[] = TEXT("LOCALE_LIST_");
  125. TCHAR szLGBasicInstall[] = TEXT("LANGUAGE_COLLECTION.BASIC.INSTALL");
  126. TCHAR szLGComplexInstall[] = TEXT("LANGUAGE_COLLECTION.COMPLEX.INSTALL");
  127. TCHAR szLGComplexRemove[] = TEXT("LANGUAGE_COLLECTION.COMPLEX.REMOVE");
  128. TCHAR szLGExtInstall[] = TEXT("LANGUAGE_COLLECTION.EXTENDED.INSTALL");
  129. TCHAR szLGExtRemove[] = TEXT("LANGUAGE_COLLECTION.EXTENDED.REMOVE");
  130. TCHAR szCPInstallPrefix[] = TEXT("CODEPAGE_INSTALL_");
  131. TCHAR szCPRemovePrefix[] = TEXT("CODEPAGE_REMOVE_");
  132. TCHAR szKbdLayoutIds[] = TEXT("KbdLayoutIds");
  133. TCHAR szInputLibrary[] = TEXT("input.dll");
  134. TCHAR szUIFontSubstitute[] = TEXT("UIFontSubstitute");
  135. TCHAR szSetupInProgress[] = TEXT("SystemSetupInProgress");
  136. TCHAR szSetupUpgrade[] = TEXT("UpgradeInProgress");
  137. TCHAR szMUILangPending[] = TEXT("MUILanguagePending");
  138. TCHAR szCtfmonValue[] = TEXT("ctfmon.exe");
  139. TCHAR szRegionalSettings[] = TEXT("RegionalSettings");
  140. TCHAR szLanguageGroup[] = TEXT("LanguageGroup");
  141. TCHAR szLanguage[] = TEXT("Language");
  142. TCHAR szSystemLocale[] = TEXT("SystemLocale");
  143. TCHAR szUserLocale[] = TEXT("UserLocale");
  144. TCHAR szInputLocale[] = TEXT("InputLocale");
  145. TCHAR szMUILanguage[] = TEXT("MUILanguage");
  146. TCHAR szUserLocale_DefUser[] = TEXT("UserLocale_DefaultUser");
  147. TCHAR szInputLocale_DefUser[] = TEXT("InputLocale_DefaultUser");
  148. TCHAR szMUILanguage_DefUSer[] = TEXT("MUILanguage_DefaultUser");
  149. HINF g_hIntlInf = NULL;
  150. LPLANGUAGEGROUP pLanguageGroups = NULL;
  151. LPCODEPAGE pCodePages = NULL;
  152. int g_NumAltSorts = 0;
  153. HANDLE hAltSorts = NULL;
  154. LPDWORD pAltSorts = NULL;
  155. HINSTANCE hInputDLL = NULL;
  156. BOOL (*pfnInstallInputLayout)(LCID, DWORD, BOOL, HKL, BOOL, BOOL) = NULL;
  157. BOOL (*pfnUninstallInputLayout)(LCID, DWORD, BOOL) = NULL;
  158. UILANGUAGEGROUP UILangGroup;
  159. //
  160. // Function Prototypes.
  161. //
  162. void
  163. DoProperties(
  164. HWND hwnd,
  165. LPCTSTR pCmdLine);
  166. ////////////////////////////////////////////////////////////////////////////
  167. //
  168. // LibMain
  169. //
  170. // This routine is called from LibInit to perform any initialization that
  171. // is required.
  172. //
  173. ////////////////////////////////////////////////////////////////////////////
  174. BOOL APIENTRY LibMain(
  175. HANDLE hDll,
  176. DWORD dwReason,
  177. LPVOID lpReserved)
  178. {
  179. switch (dwReason)
  180. {
  181. case ( DLL_PROCESS_ATTACH ) :
  182. {
  183. hInstance = hDll;
  184. //
  185. // Create the mutex used for the Input Locale property page.
  186. //
  187. g_hMutex = CreateMutex(NULL, FALSE, szMutexName);
  188. g_hEvent = CreateEvent(NULL, TRUE, TRUE, szEventName);
  189. DisableThreadLibraryCalls(hDll);
  190. break;
  191. }
  192. case ( DLL_PROCESS_DETACH ) :
  193. {
  194. if (g_hMutex)
  195. {
  196. CloseHandle(g_hMutex);
  197. }
  198. if (g_hEvent)
  199. {
  200. CloseHandle(g_hEvent);
  201. }
  202. break;
  203. }
  204. case ( DLL_THREAD_DETACH ) :
  205. {
  206. break;
  207. }
  208. case ( DLL_THREAD_ATTACH ) :
  209. default :
  210. {
  211. break;
  212. }
  213. }
  214. return (TRUE);
  215. }
  216. ////////////////////////////////////////////////////////////////////////////
  217. //
  218. // CreateGlobals
  219. //
  220. ////////////////////////////////////////////////////////////////////////////
  221. BOOL CreateGlobals()
  222. {
  223. HKEY hKey;
  224. TCHAR szData[MAX_PATH];
  225. DWORD cbData;
  226. //
  227. // Get the localized strings.
  228. //
  229. LoadString(hInstance, IDS_LOCALE_GET_ERROR, szLocaleGetError, SIZE_128);
  230. LoadString(hInstance, IDS_STYLEUH, szStyleH, 3);
  231. LoadString(hInstance, IDS_STYLELH, szStyleh, 3);
  232. LoadString(hInstance, IDS_STYLEUM, szStyleM, 3);
  233. LoadString(hInstance, IDS_STYLELM, szStylem, 3);
  234. LoadString(hInstance, IDS_STYLELS, szStyles, 3);
  235. LoadString(hInstance, IDS_STYLELT, szStylet, 3);
  236. LoadString(hInstance, IDS_STYLELD, szStyled, 3);
  237. LoadString(hInstance, IDS_STYLELY, szStyley, 3);
  238. Styles_Localized = (szStyleH[0] != TEXT('H') || szStyleh[0] != TEXT('h') ||
  239. szStyleM[0] != TEXT('M') || szStylem[0] != TEXT('m') ||
  240. szStyles[0] != TEXT('s') || szStylet[0] != TEXT('t') ||
  241. szStyled[0] != TEXT('d') || szStyley[0] != TEXT('y'));
  242. //
  243. // Get the user and system default locale ids.
  244. //
  245. UserLocaleID = GetUserDefaultLCID();
  246. SysLocaleID = GetSystemDefaultLCID();
  247. //
  248. // Get the system locale id from the registry. This may be
  249. // different from the current system default locale id if the user
  250. // changed the system locale and chose not to reboot.
  251. //
  252. if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  253. c_szLanguages,
  254. 0L,
  255. KEY_READ,
  256. &hKey ) == ERROR_SUCCESS)
  257. {
  258. //
  259. // Query the default locale id.
  260. //
  261. szData[0] = 0;
  262. cbData = sizeof(szData);
  263. RegQueryValueEx(hKey, TEXT("Default"), NULL, NULL, (LPBYTE)szData, &cbData);
  264. RegCloseKey(hKey);
  265. if ((RegSysLocaleID = TransNum(szData)) == 0)
  266. {
  267. RegSysLocaleID = SysLocaleID;
  268. }
  269. }
  270. else
  271. {
  272. RegSysLocaleID = SysLocaleID;
  273. }
  274. //
  275. // Get the user locale id from the registry.
  276. //
  277. if (RegOpenKeyEx( HKEY_CURRENT_USER,
  278. c_szControlPanelIntl,
  279. 0L,
  280. KEY_READ,
  281. &hKey ) == ERROR_SUCCESS)
  282. {
  283. //
  284. // Query the locale id.
  285. //
  286. szData[0] = 0;
  287. cbData = sizeof(szData);
  288. RegQueryValueEx(hKey, TEXT("Locale"), NULL, NULL, (LPBYTE)szData, &cbData);
  289. RegCloseKey(hKey);
  290. if ((RegUserLocaleID = TransNum(szData)) == 0)
  291. {
  292. RegUserLocaleID = UserLocaleID;
  293. }
  294. }
  295. else
  296. {
  297. RegUserLocaleID = UserLocaleID;
  298. }
  299. //
  300. // See if the user locale id is Arabic or/and right to left.
  301. //
  302. bShowRtL = IsRtLLocale(UserLocaleID);
  303. bShowArabic = (bShowRtL &&
  304. (PRIMARYLANGID(LANGIDFROMLCID(UserLocaleID)) != LANG_HEBREW));
  305. bHebrewUI = (PRIMARYLANGID(UserLocaleID) == LANG_HEBREW);
  306. //
  307. // See if there is an LPK installed.
  308. //
  309. if (GetModuleHandle(LANGUAGE_PACK_DLL))
  310. {
  311. bLPKInstalled = TRUE;
  312. }
  313. else
  314. {
  315. bLPKInstalled = FALSE;
  316. }
  317. //
  318. // Return success.
  319. //
  320. return (TRUE);
  321. }
  322. ////////////////////////////////////////////////////////////////////////////
  323. //
  324. // DestroyGlobals
  325. //
  326. ////////////////////////////////////////////////////////////////////////////
  327. void DestroyGlobals()
  328. {
  329. }
  330. ////////////////////////////////////////////////////////////////////////////
  331. //
  332. // CPlApplet
  333. //
  334. ////////////////////////////////////////////////////////////////////////////
  335. LONG CALLBACK CPlApplet(
  336. HWND hwnd,
  337. UINT Msg,
  338. LPARAM lParam1,
  339. LPARAM lParam2)
  340. {
  341. switch (Msg)
  342. {
  343. case ( CPL_INIT ) :
  344. {
  345. //
  346. // First message to CPlApplet(), sent once only.
  347. // Perform all control panel applet initialization and return
  348. // true for further processing.
  349. //
  350. InitCommonControls();
  351. return (CreateGlobals());
  352. }
  353. case ( CPL_GETCOUNT ) :
  354. {
  355. //
  356. // Second message to CPlApplet(), sent once only.
  357. // Return the number of control applets to be displayed in the
  358. // control panel window. For this applet, return 1.
  359. //
  360. return (1);
  361. }
  362. case ( CPL_INQUIRE ) :
  363. {
  364. //
  365. // Third message to CPlApplet().
  366. // It is sent as many times as the number of applets returned by
  367. // CPL_GETCOUNT message. Each applet must register by filling
  368. // in the CPLINFO structure referenced by lParam2 with the
  369. // applet's icon, name, and information string. Since there is
  370. // only one applet, simply set the information for this
  371. // singular case.
  372. //
  373. LPCPLINFO lpCPlInfo = (LPCPLINFO)lParam2;
  374. lpCPlInfo->idIcon = IDI_ICON;
  375. lpCPlInfo->idName = IDS_NAME;
  376. lpCPlInfo->idInfo = IDS_INFO;
  377. lpCPlInfo->lData = 0;
  378. break;
  379. }
  380. case ( CPL_NEWINQUIRE ) :
  381. {
  382. //
  383. // Third message to CPlApplet().
  384. // It is sent as many times as the number of applets returned by
  385. // CPL_GETCOUNT message. Each applet must register by filling
  386. // in the NEWCPLINFO structure referenced by lParam2 with the
  387. // applet's icon, name, and information string. Since there is
  388. // only one applet, simply set the information for this
  389. // singular case.
  390. //
  391. LPNEWCPLINFO lpNewCPlInfo = (LPNEWCPLINFO)lParam2;
  392. lpNewCPlInfo->dwSize = sizeof(NEWCPLINFO);
  393. lpNewCPlInfo->dwFlags = 0;
  394. lpNewCPlInfo->dwHelpContext = 0UL;
  395. lpNewCPlInfo->lData = 0;
  396. lpNewCPlInfo->hIcon = LoadIcon( hInstance,
  397. (LPCTSTR)MAKEINTRESOURCE(IDI_ICON) );
  398. LoadString(hInstance, IDS_NAME, lpNewCPlInfo->szName, 32);
  399. LoadString(hInstance, IDS_INFO, lpNewCPlInfo->szInfo, 64);
  400. lpNewCPlInfo->szHelpFile[0] = CHAR_NULL;
  401. break;
  402. }
  403. case ( CPL_SELECT ) :
  404. {
  405. //
  406. // Applet has been selected, do nothing.
  407. //
  408. break;
  409. }
  410. case ( CPL_DBLCLK ) :
  411. {
  412. //
  413. // Applet icon double clicked -- invoke property sheet with
  414. // the first property sheet page on top.
  415. //
  416. DoProperties(hwnd, (LPCTSTR)NULL);
  417. break;
  418. }
  419. case ( CPL_STARTWPARMS ) :
  420. {
  421. //
  422. // Same as CPL_DBLCLK, but lParam2 is a long pointer to
  423. // a string of extra directions that are to be supplied to
  424. // the property sheet that is to be initiated.
  425. //
  426. DoProperties(hwnd, (LPCTSTR)lParam2);
  427. break;
  428. }
  429. case ( CPL_STOP ) :
  430. {
  431. //
  432. // Sent once for each applet prior to the CPL_EXIT msg.
  433. // Perform applet specific cleanup.
  434. //
  435. break;
  436. }
  437. case ( CPL_EXIT ) :
  438. {
  439. //
  440. // Last message, sent once only, before MMCPL.EXE calls
  441. // FreeLibrary() on this DLL. Do non-applet specific cleanup.
  442. //
  443. DestroyGlobals();
  444. break;
  445. }
  446. default :
  447. {
  448. return (FALSE);
  449. }
  450. }
  451. //
  452. // Return success.
  453. //
  454. return (TRUE);
  455. }
  456. ////////////////////////////////////////////////////////////////////////////
  457. //
  458. // DoProperties
  459. //
  460. ////////////////////////////////////////////////////////////////////////////
  461. void DoProperties(
  462. HWND hwnd,
  463. LPCTSTR pCmdLine)
  464. {
  465. HPROPSHEETPAGE rPages[MAX_PAGES];
  466. PROPSHEETHEADER psh;
  467. LPARAM lParam = SETUP_SWITCH_NONE;
  468. LPTSTR pStartPage;
  469. LPTSTR pSrc;
  470. LPTSTR pSrcDrv;
  471. BOOL bShortDate = FALSE;
  472. BOOL bNoUI = FALSE;
  473. BOOL bUnattended = FALSE;
  474. TCHAR szUnattendFile[MAX_PATH * 2];
  475. HKEY hKey;
  476. TCHAR szSetupSourceDrive[MAX_PATH];
  477. //
  478. // Log if the command line is not null.
  479. //
  480. if (pCmdLine != NULL)
  481. {
  482. g_bLog = TRUE;
  483. }
  484. //
  485. // Begin Log and log command line parameters.
  486. //
  487. Intl_LogSimpleMessage(IDS_LOG_HEAD, NULL);
  488. Intl_LogMessage(pCmdLine);
  489. Intl_LogMessage(TEXT("")); // add a carriage return and newline
  490. //
  491. // Load the library used for Text Services.
  492. //
  493. if (!hInputDLL)
  494. {
  495. hInputDLL = LoadLibrary(szInputLibrary);
  496. }
  497. //
  498. // Initialize the Install/Remove function from the Input applet.
  499. //
  500. if (hInputDLL)
  501. {
  502. //
  503. // Initialize Install function.
  504. //
  505. pfnInstallInputLayout = (BOOL (*)(LCID, DWORD, BOOL, HKL, BOOL, BOOL))
  506. GetProcAddress(hInputDLL, MAKEINTRESOURCEA(ORD_INPUT_INST_LAYOUT));
  507. //
  508. // Initialize Uninstall function.
  509. //
  510. pfnUninstallInputLayout = (BOOL (*)(LCID, DWORD, BOOL))
  511. GetProcAddress(hInputDLL, MAKEINTRESOURCEA(ORD_INPUT_UNINST_LAYOUT));
  512. }
  513. //
  514. // See if there is a command line switch from Setup.
  515. //
  516. psh.nStartPage = (UINT)-1;
  517. while (pCmdLine && *pCmdLine)
  518. {
  519. if (*pCmdLine == TEXT('/'))
  520. {
  521. //
  522. // Legend:
  523. // gG: allow progress bar to show when setup is copying files
  524. // iI: bring up the Input Locale page only
  525. // rR: bring up the General page on top
  526. // sS: setup source string passed on command line
  527. // [example: /s:"c:\winnt"]
  528. //
  529. // NO UI IS SHOWN IF THE FOLLOWING OPTIONS ARE SPECIFIED:
  530. // fF: unattend mode file - no UI is shown
  531. // [example: /f:"c:\unattend.txt"]
  532. // uU: update short date format to 4-digit year - no UI is shown
  533. // (registry only updated if current setting is the
  534. // same as the default setting except for the
  535. // "yy" vs. "yyyy")
  536. // tT: Match system UI font with the default UI language
  537. //
  538. switch (*++pCmdLine)
  539. {
  540. case ( TEXT('g') ) :
  541. case ( TEXT('G') ) :
  542. {
  543. //
  544. // Log switch.
  545. //
  546. Intl_LogSimpleMessage(IDS_LOG_SWITCH_G, NULL);
  547. //
  548. // Do switch related processing.
  549. //
  550. g_bProgressBarDisplay = TRUE;
  551. pCmdLine++;
  552. break;
  553. }
  554. case ( TEXT('i') ) :
  555. case ( TEXT('I') ) :
  556. {
  557. //
  558. // Log switch.
  559. //
  560. Intl_LogSimpleMessage(IDS_LOG_SWITCH_I, NULL);
  561. //
  562. // Do switch related processing
  563. //
  564. lParam |= SETUP_SWITCH_I;
  565. psh.nStartPage = 0;
  566. pCmdLine++;
  567. break;
  568. }
  569. case ( TEXT('r') ) :
  570. case ( TEXT('R') ) :
  571. {
  572. //
  573. // Log switch.
  574. //
  575. Intl_LogSimpleMessage(IDS_LOG_SWITCH_R, NULL);
  576. //
  577. // Do switch related processing
  578. //
  579. lParam |= SETUP_SWITCH_R;
  580. psh.nStartPage = 0;
  581. pCmdLine++;
  582. break;
  583. }
  584. case ( TEXT('s') ) :
  585. case ( TEXT('S') ) :
  586. {
  587. //
  588. // Log switch.
  589. //
  590. Intl_LogSimpleMessage(IDS_LOG_SWITCH_S, NULL);
  591. //
  592. // Get the name of the setup source path.
  593. //
  594. lParam |= SETUP_SWITCH_S;
  595. if ((*++pCmdLine == TEXT(':')) && (*++pCmdLine == TEXT('"')))
  596. {
  597. pCmdLine++;
  598. pSrc = szSetupSourcePath;
  599. pSrcDrv = szSetupSourceDrive;
  600. while (*pCmdLine && (*pCmdLine != TEXT('"')))
  601. {
  602. *pSrc = *pCmdLine;
  603. pSrc++;
  604. *pSrcDrv = *pCmdLine;
  605. pSrcDrv++;
  606. pCmdLine++;
  607. }
  608. *pSrc = 0;
  609. *pSrcDrv = 0;
  610. wcscpy(szSetupSourcePathWithArchitecture, szSetupSourcePath);
  611. pSetupSourcePathWithArchitecture = szSetupSourcePathWithArchitecture;
  612. //
  613. // Remove the architecture-specific portion of
  614. // the source path (that gui-mode setup sent us).
  615. //
  616. pSrc = wcsrchr(szSetupSourcePath, TEXT('\\'));
  617. if (pSrc)
  618. {
  619. *pSrc = TEXT('\0');
  620. }
  621. pSetupSourcePath = szSetupSourcePath;
  622. }
  623. if (*pCmdLine == TEXT('"'))
  624. {
  625. pCmdLine++;
  626. }
  627. pSrcDrv = szSetupSourceDrive;
  628. while (*pSrcDrv)
  629. {
  630. if (*pSrcDrv == TEXT('\\'))
  631. {
  632. pSrcDrv[1] = 0;
  633. }
  634. pSrcDrv++;
  635. }
  636. g_bCDROM = (GetDriveType(szSetupSourceDrive) == DRIVE_CDROM);
  637. break;
  638. }
  639. case ( TEXT('f') ) :
  640. case ( TEXT('F') ) :
  641. {
  642. //
  643. // Log switch.
  644. //
  645. Intl_LogSimpleMessage(IDS_LOG_SWITCH_F, NULL);
  646. //
  647. // Get the name of the unattend file.
  648. //
  649. g_bUnttendMode = TRUE;
  650. bNoUI = TRUE;
  651. szUnattendFile[0] = 0;
  652. if ((*++pCmdLine == TEXT(':')) && (*++pCmdLine == TEXT('"')))
  653. {
  654. pCmdLine++;
  655. pSrc = szUnattendFile;
  656. while (*pCmdLine && (*pCmdLine != TEXT('"')))
  657. {
  658. *pSrc = *pCmdLine;
  659. pSrc++;
  660. pCmdLine++;
  661. }
  662. *pSrc = 0;
  663. }
  664. if (*pCmdLine == TEXT('"'))
  665. {
  666. pCmdLine++;
  667. }
  668. break;
  669. }
  670. case ( TEXT('u') ) :
  671. case ( TEXT('U') ) :
  672. {
  673. //
  674. // Log switch.
  675. //
  676. Intl_LogSimpleMessage(IDS_LOG_SWITCH_U, NULL);
  677. //
  678. // Do switch related processing.
  679. //
  680. bShortDate = TRUE;
  681. bNoUI = TRUE;
  682. break;
  683. }
  684. case ( TEXT('t') ) :
  685. case ( TEXT('T') ) :
  686. {
  687. g_bMatchUIFont = TRUE;
  688. }
  689. default :
  690. {
  691. //
  692. // Log switch.
  693. //
  694. Intl_LogSimpleMessage(IDS_LOG_SWITCH_DEFAULT, pCmdLine);
  695. //
  696. // Fall out, maybe it's a number...
  697. //
  698. break;
  699. }
  700. }
  701. }
  702. else if (*pCmdLine == TEXT(' '))
  703. {
  704. pCmdLine++;
  705. }
  706. else
  707. {
  708. break;
  709. }
  710. }
  711. //
  712. // See if we are in setup mode.
  713. //
  714. g_bSetupCase = Intl_IsSetupMode();
  715. //
  716. // See if the user has Administrative privileges by checking for
  717. // write permission to the registry key.
  718. //
  719. if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  720. c_szInstalledLocales,
  721. 0UL,
  722. KEY_WRITE,
  723. &hKey ) == ERROR_SUCCESS)
  724. {
  725. //
  726. // See if the user can write into the registry. Due to a registry
  727. // modification, we can open a registry key with write access and
  728. // be unable to write to the key... thanks to terminal server.
  729. //
  730. if (RegSetValueEx( hKey,
  731. TEXT("Test"),
  732. 0UL,
  733. REG_SZ,
  734. (LPBYTE)TEXT("Test"),
  735. (DWORD)(lstrlen(TEXT("Test")) + 1) * sizeof(TCHAR) ) == ERROR_SUCCESS)
  736. {
  737. //
  738. // Delete the value created
  739. //
  740. RegDeleteValue(hKey, TEXT("Test"));
  741. //
  742. // We can write to the HKEY_LOCAL_MACHINE key, so the user
  743. // has Admin privileges.
  744. //
  745. g_bAdmin_Privileges = TRUE;
  746. }
  747. else
  748. {
  749. //
  750. // The user does not have admin privileges.
  751. //
  752. g_bAdmin_Privileges = FALSE;
  753. }
  754. RegCloseKey(hKey);
  755. }
  756. //
  757. // See if we are in setup mode.
  758. //
  759. if (g_bSetupCase)
  760. {
  761. //
  762. // We need to remove the hard coded LPK registry key.
  763. //
  764. if (RegOpenKey( HKEY_LOCAL_MACHINE,
  765. LANGUAGE_PACK_KEY,
  766. &hKey ) == ERROR_SUCCESS)
  767. {
  768. RegDeleteValue(hKey, LANGUAGE_PACK_VALUE);
  769. RegCloseKey(hKey);
  770. }
  771. }
  772. //
  773. // See if the unattend mode file switch was used.
  774. //
  775. if (g_bUnttendMode)
  776. {
  777. //
  778. // Use the unattend mode file to carry out the appropriate commands.
  779. //
  780. Region_DoUnattendModeSetup(szUnattendFile);
  781. if (Intl_IsWinntUpgrade())
  782. {
  783. //
  784. // Remove MUI files.
  785. //
  786. Intl_RemoveMUIFile();
  787. }
  788. }
  789. //
  790. // If the update to 4-digit year switch was used and the user's short
  791. // date setting is still set to the default for the chosen locale, then
  792. // update the current user's short date setting to the new 4-digit year
  793. // default.
  794. //
  795. if (bShortDate)
  796. {
  797. Region_UpdateShortDate();
  798. }
  799. //
  800. // If we're not to show any UI, then return.
  801. //
  802. if (bNoUI)
  803. {
  804. return;
  805. }
  806. //
  807. // Make sure we have a start page.
  808. //
  809. if (psh.nStartPage == (UINT)-1)
  810. {
  811. psh.nStartPage = 0;
  812. if (pCmdLine && *pCmdLine)
  813. {
  814. //
  815. // Get the start page from the command line.
  816. //
  817. pStartPage = (LPTSTR)pCmdLine;
  818. while ((*pStartPage >= TEXT('0')) && (*pStartPage <= TEXT('9')))
  819. {
  820. psh.nStartPage *= 10;
  821. psh.nStartPage += *pStartPage++ - CHAR_ZERO;
  822. }
  823. //
  824. // Make sure that the requested starting page is less than
  825. // the max page for the selected applet.
  826. //
  827. if (psh.nStartPage >= MAX_PAGES)
  828. {
  829. psh.nStartPage = 0;
  830. }
  831. }
  832. }
  833. //
  834. // Set up the property sheet information.
  835. //
  836. psh.dwSize = sizeof(psh);
  837. psh.dwFlags = 0;
  838. psh.hwndParent = hwnd;
  839. psh.hInstance = hInstance;
  840. psh.nPages = 0;
  841. psh.phpage = rPages;
  842. //
  843. // Add the appropriate property pages.
  844. //
  845. if (lParam &= SETUP_SWITCH_I)
  846. {
  847. psh.pszCaption = MAKEINTRESOURCE(IDS_TEXT_INPUT_METHODS);
  848. Intl_AddExternalPage( &psh,
  849. DLG_INPUT_LOCALES,
  850. hInputDLL,
  851. MAKEINTRESOURCEA(ORD_INPUT_DLG_PROC),
  852. MAX_PAGES ); // One page
  853. }
  854. else
  855. {
  856. psh.pszCaption = MAKEINTRESOURCE(IDS_NAME);
  857. Intl_AddPage(&psh, DLG_GENERAL, GeneralDlgProc, lParam, MAX_PAGES);
  858. Intl_AddPage(&psh, DLG_LANGUAGES, LanguageDlgProc, lParam, MAX_PAGES);
  859. if (g_bAdmin_Privileges == TRUE)
  860. {
  861. Intl_AddPage(&psh, DLG_ADVANCED, AdvancedDlgProc, lParam, MAX_PAGES);
  862. }
  863. }
  864. //
  865. // Make the property sheet.
  866. //
  867. PropertySheet(&psh);
  868. //
  869. // Free the Text Services Library.
  870. //
  871. if (hInputDLL)
  872. {
  873. FreeLibrary(hInputDLL);
  874. pfnInstallInputLayout = NULL;
  875. pfnUninstallInputLayout = NULL;
  876. }
  877. }
  878. ////////////////////////////////////////////////////////////////////////////
  879. //
  880. // IsRtLLocale
  881. //
  882. ////////////////////////////////////////////////////////////////////////////
  883. #define MAX_FONTSIGNATURE 16 // length of font signature string
  884. BOOL IsRtLLocale(
  885. LCID iLCID)
  886. {
  887. WORD wLCIDFontSignature[MAX_FONTSIGNATURE];
  888. BOOL bRet = FALSE;
  889. //
  890. // Verify that this is an RTL (BiDi) locale. Call GetLocaleInfo with
  891. // LOCALE_FONTSIGNATURE which always gives back 16 WORDs.
  892. //
  893. if (GetLocaleInfo( iLCID,
  894. LOCALE_FONTSIGNATURE,
  895. (LPTSTR) &wLCIDFontSignature,
  896. (sizeof(wLCIDFontSignature) / sizeof(TCHAR)) ))
  897. {
  898. //
  899. // Verify the bits show a BiDi UI locale.
  900. //
  901. if (wLCIDFontSignature[7] & 0x0800)
  902. {
  903. bRet = TRUE;
  904. }
  905. }
  906. //
  907. // Return the result.
  908. //
  909. return (bRet);
  910. }