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.

2129 lines
61 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. DWORD OptionsDlgContextHelp[] = { IDC_MAKELOCALSOURCEFROMCD, IDH_MAKELOCALSOURCEFROMCD,
  4. IDC_USEFLOPPIES , IDH_USEFLOPPIES,
  5. IDC_SYSPARTDRIVE , IDH_SYSPARTDRIVE,
  6. IDT_SYSPARTTEXT , IDH_SYSPARTDRIVE,
  7. IDC_CHOOSE_INSTALLPART , IDH_CHOOSE_INSTALLPART,
  8. IDC_INSTALL_DIR , IDH_INSTALL_DIR,
  9. 0 , 0
  10. };
  11. typedef struct _LOCALE_ENTRY {
  12. LPTSTR Lcid;
  13. LPTSTR Description;
  14. LPTSTR LanguageGroup1;
  15. LPTSTR LanguageGroup2;
  16. } LOCALE_ENTRY, *PLOCALE_ENTRY;
  17. typedef struct _LANGUAGE_GROUP_ENTRY {
  18. LPTSTR Id;
  19. LPTSTR Description;
  20. LPTSTR Directory;
  21. BOOL Selected;
  22. } LANGUAGE_GROUP_ENTRY, *PLANGUAGE_GROUP_ENTRY;
  23. BOOL IntlInfProcessed = FALSE;
  24. DWORD LocaleCount = 0;
  25. PLOCALE_ENTRY LocaleList;
  26. DWORD PrimaryLocale;
  27. DWORD LanguageGroupsCount = 0;
  28. PLANGUAGE_GROUP_ENTRY LanguageGroups;
  29. BOOL NTFSConversionChanged;
  30. //
  31. // Headless settings.
  32. //
  33. TCHAR HeadlessSelection[MAX_PATH];
  34. ULONG HeadlessBaudRate = 0;
  35. #define DEFAULT_HEADLESS_SETTING TEXT("COM1")
  36. BOOL
  37. (*Kernel32IsValidLanguageGroup)(
  38. IN LGRPID LanguageGroup,
  39. IN DWORD dwFlags);
  40. // Only used for amd64/X86 case.
  41. BOOL ForceFloppyless = FALSE;
  42. UINT g_Boot16 = BOOT16_NO;
  43. INT_PTR
  44. OptionsDlgProc(
  45. IN HWND hdlg,
  46. IN UINT msg,
  47. IN WPARAM wParam,
  48. IN LPARAM lParam
  49. )
  50. {
  51. BOOL b;
  52. TCHAR Text[MAX_PATH];
  53. switch(msg) {
  54. case WM_INITDIALOG:
  55. #if defined(REMOTE_BOOT)
  56. if (RemoteBoot) {
  57. //
  58. // For remote boot client upgrade, uncheck and disable the
  59. // "copy files from CD-ROM to hard drive" checkbox.
  60. //
  61. CheckDlgButton(hdlg,IDC_MAKELOCALSOURCEFROMCD,BST_UNCHECKED);
  62. EnableWindow(GetDlgItem(hdlg,IDC_MAKELOCALSOURCEFROMCD),FALSE);
  63. ShowWindow(GetDlgItem(hdlg, IDC_MAKELOCALSOURCEFROMCD), SW_HIDE);
  64. } else
  65. #endif // defined(REMOTE_BOOT)
  66. {
  67. if (!IsArc()) {
  68. //
  69. // Set initial state of "copy files from CD-ROM to hard drive"
  70. // checkbox. Note that that control might be disabled.
  71. //
  72. CheckDlgButton(hdlg,
  73. IDC_MAKELOCALSOURCEFROMCD,
  74. MakeLocalSource ? BST_CHECKED : BST_UNCHECKED);
  75. if(!RunFromCD) {
  76. //
  77. // Not run from CD, disable the control. The box won't be checked.
  78. // But MakeLocalSource is probably TRUE.
  79. //
  80. EnableWindow(GetDlgItem(hdlg,IDC_MAKELOCALSOURCEFROMCD),FALSE);
  81. }
  82. } else {
  83. //
  84. // On ARC machines the files are always copied to the hard drive
  85. //
  86. ShowWindow(GetDlgItem(hdlg, IDC_MAKELOCALSOURCEFROMCD), SW_HIDE);
  87. } // if (!IsArc())
  88. }
  89. //
  90. // Disable system partition controls?
  91. //
  92. #if defined _IA64_
  93. EnableWindow(GetDlgItem(hdlg,IDC_SYSPARTDRIVE),FALSE);
  94. ShowWindow(GetDlgItem(hdlg,IDC_SYSPARTDRIVE),SW_HIDE);
  95. ShowWindow(GetDlgItem(hdlg,IDT_SYSPARTTEXT),SW_HIDE);
  96. #else
  97. if( !IsArc()) {
  98. EnableWindow(GetDlgItem(hdlg,IDC_SYSPARTDRIVE),FALSE);
  99. ShowWindow(GetDlgItem(hdlg,IDC_SYSPARTDRIVE),SW_HIDE);
  100. ShowWindow(GetDlgItem(hdlg,IDT_SYSPARTTEXT),SW_HIDE);
  101. } else {
  102. EnableWindow(GetDlgItem(hdlg,IDC_SYSPARTDRIVE),SystemPartitionDriveLetter != 0);
  103. ShowWindow(GetDlgItem(hdlg,IDC_SYSPARTDRIVE),SystemPartitionDriveLetter ? SW_SHOW : SW_HIDE);
  104. ShowWindow(GetDlgItem(hdlg,IDT_SYSPARTTEXT),SystemPartitionDriveLetter ? SW_SHOW : SW_HIDE);
  105. }
  106. #endif
  107. if (!IsArc()) {
  108. #if defined(_AMD64_) || defined(_X86_)
  109. if (Upgrade && !ISNT()) {
  110. //
  111. // Populate the Boot16 value.
  112. //
  113. SendDlgItemMessage(hdlg,IDC_BOOT16_1,BM_SETCHECK, (g_Boot16 == BOOT16_AUTOMATIC) ? BST_CHECKED : BST_UNCHECKED, 0);
  114. SendDlgItemMessage(hdlg,IDC_BOOT16_2,BM_SETCHECK, (g_Boot16 == BOOT16_YES ) ? BST_CHECKED : BST_UNCHECKED, 0);
  115. SendDlgItemMessage(hdlg,IDC_BOOT16_3,BM_SETCHECK, (g_Boot16 == BOOT16_NO ) ? BST_CHECKED : BST_UNCHECKED, 0);
  116. }
  117. //
  118. // Set floppyless control.
  119. //
  120. #if defined(REMOTE_BOOT)
  121. if (RemoteBoot) {
  122. //
  123. // For remote boot client upgrade, this is always unchecked and disabled.
  124. //
  125. CheckDlgButton(hdlg,IDC_USEFLOPPIES,BST_UNCHECKED);
  126. EnableWindow(GetDlgItem(hdlg,IDC_USEFLOPPIES),FALSE);
  127. ShowWindow(GetDlgItem(hdlg,IDC_USEFLOPPIES),SW_HIDE);
  128. } else
  129. #endif // defined(REMOTE_BOOT)
  130. {
  131. CheckDlgButton(hdlg,IDC_USEFLOPPIES,Floppyless ? BST_UNCHECKED : BST_CHECKED);
  132. if(ForceFloppyless) {
  133. EnableWindow(GetDlgItem(hdlg,IDC_USEFLOPPIES),FALSE);
  134. }
  135. }
  136. #endif // defined(_AMD64_) || defined(_X86_)
  137. } else {
  138. #ifdef UNICODE // Always true for ARC, never true for Win9x upgrade
  139. //
  140. // Get rid of floppy-related controls.
  141. //
  142. EnableWindow(GetDlgItem(hdlg,IDC_USEFLOPPIES),FALSE);
  143. ShowWindow(GetDlgItem(hdlg,IDC_USEFLOPPIES),SW_HIDE);
  144. //
  145. // Populate the system partition combobox.
  146. //
  147. if (SystemPartitionDriveLetter)
  148. {
  149. PWCHAR p;
  150. WCHAR x[3];
  151. x[1] = L':';
  152. x[2] = 0;
  153. for(p=SystemPartitionDriveLetters; *p; p++) {
  154. x[0] = *p;
  155. SendDlgItemMessage(hdlg,IDC_SYSPARTDRIVE,CB_ADDSTRING,0,(LPARAM)x);
  156. }
  157. x[0] = SystemPartitionDriveLetter;
  158. SendDlgItemMessage(hdlg,IDC_SYSPARTDRIVE,CB_SELECTSTRING,(WPARAM)(-1),(LPARAM)x);
  159. }
  160. #endif // UNICODE
  161. } // if (!IsArc())
  162. //
  163. // Set text in edit controls, and configure the control a little.
  164. //
  165. SetDlgItemText(hdlg,IDC_SOURCE,InfName);
  166. SendDlgItemMessage(hdlg,IDC_SOURCE,EM_LIMITTEXT,MAX_PATH,0);
  167. if(SourceCount == 1) {
  168. EnableWindow(GetDlgItem(hdlg,IDC_SOURCE2),TRUE);
  169. SetDlgItemText(hdlg,IDC_SOURCE2,NativeSourcePaths[0]);
  170. } else {
  171. LoadString(hInst,IDS_MULTIPLE,Text,sizeof(Text)/sizeof(TCHAR));
  172. SetDlgItemText(hdlg,IDC_SOURCE2,Text);
  173. EnableWindow(GetDlgItem(hdlg,IDC_SOURCE2),FALSE);
  174. }
  175. SendDlgItemMessage(hdlg,IDC_SOURCE2,EM_LIMITTEXT,MAX_PATH-1,0);
  176. SetDlgItemText(hdlg,IDC_INSTALL_DIR,InstallDir);
  177. //
  178. // limit the path to the same value as textmode setup (50 TCHARS)
  179. //
  180. #define MAX_NT_DIR_LEN 50
  181. SendDlgItemMessage(hdlg,IDC_INSTALL_DIR,EM_LIMITTEXT,MAX_NT_DIR_LEN,0);
  182. CheckDlgButton(hdlg,IDC_CHOOSE_INSTALLPART,ChoosePartition ? BST_CHECKED : BST_UNCHECKED);
  183. if (Upgrade) {
  184. TCHAR Text[MAX_PATH];
  185. //
  186. // Set the installation directory to the current Windows directory,
  187. // then disable the user's ability to edit it.
  188. //
  189. MyGetWindowsDirectory(Text,MAX_PATH);
  190. SetDlgItemText(hdlg,IDC_INSTALL_DIR,Text+3);
  191. SendDlgItemMessage(hdlg,IDC_INSTALL_DIR,EM_LIMITTEXT,MAX_PATH,0);
  192. EnableWindow(GetDlgItem(hdlg,IDC_INSTALL_DIR),FALSE);
  193. EnableWindow(GetDlgItem(hdlg,IDC_CHOOSE_INSTALLPART),FALSE);
  194. }
  195. //
  196. // On server installs, don't all the user to modify the
  197. // install partition selection state
  198. //
  199. if (Server) {
  200. EnableWindow( GetDlgItem(hdlg,IDC_CHOOSE_INSTALLPART), FALSE );
  201. }
  202. //
  203. // Set focus to Cancel button.
  204. //
  205. SetFocus(GetDlgItem(hdlg,IDCANCEL));
  206. b = FALSE;
  207. break;
  208. case WM_COMMAND:
  209. b = FALSE;
  210. switch(LOWORD(wParam)) {
  211. case IDOK:
  212. if(HIWORD(wParam) == BN_CLICKED) {
  213. #if defined(REMOTE_BOOT)
  214. if (RemoteBoot) {
  215. MakeLocalSource = FALSE;
  216. } else
  217. #endif // defined(REMOTE_BOOT)
  218. if(RunFromCD) {
  219. if (!IsArc()) {
  220. #if defined(_AMD64_)
  221. MakeLocalSource = TRUE;
  222. UserSpecifiedMakeLocalSource = TRUE;
  223. #endif // defined(_AMD64_)
  224. #if defined(_X86_)
  225. MakeLocalSource = (IsDlgButtonChecked(hdlg,IDC_MAKELOCALSOURCEFROMCD) == BST_CHECKED);
  226. UserSpecifiedMakeLocalSource = (IsDlgButtonChecked(hdlg,IDC_MAKELOCALSOURCEFROMCD) == BST_CHECKED);
  227. #endif // defined(_X86_)
  228. } else {
  229. #ifdef UNICODE // Always true for ARC, never true for Win9x upgrade
  230. MakeLocalSource = TRUE;
  231. UserSpecifiedMakeLocalSource = TRUE;
  232. #endif // UNICODE
  233. } // if (!IsArc())
  234. }
  235. if (!IsArc()) {
  236. #if defined(_AMD64_) || defined(_X86_)
  237. #if defined(REMOTE_BOOT)
  238. if (RemoteBoot) {
  239. MakeBootMedia = FALSE;
  240. Floppyless = TRUE;
  241. } else
  242. #endif // defined(REMOTE_BOOT)
  243. {
  244. Floppyless = (IsDlgButtonChecked(hdlg,IDC_USEFLOPPIES) == BST_UNCHECKED);
  245. }
  246. #endif // defined(_AMD64_) || defined(_X86_)
  247. } else {
  248. #ifdef UNICODE // Always true for ARC, never true for Win9x upgrade
  249. WCHAR x[3];
  250. GetDlgItemText(hdlg,IDC_SYSPARTDRIVE,x,3);
  251. SystemPartitionDriveLetter = x[0];
  252. LocalBootDirectory[0] = x[0];
  253. #endif // UNICODE
  254. } // if (!IsArc())
  255. GetDlgItemText(hdlg,IDC_SOURCE,InfName,MAX_PATH);
  256. if(SourceCount == 1) {
  257. GetDlgItemText(hdlg,IDC_SOURCE2,NativeSourcePaths[0],MAX_PATH);
  258. }
  259. {
  260. TCHAR tmp[MAX_PATH];
  261. BOOL bSelectedChoosePartition;
  262. bSelectedChoosePartition = (IsDlgButtonChecked(hdlg, IDC_CHOOSE_INSTALLPART) == BST_CHECKED);
  263. GetDlgItemText(hdlg,IDC_INSTALL_DIR,tmp,MAX_PATH);
  264. if (tmp[0] == 0) {
  265. InstallDir[0] = 0;
  266. } else if (tmp[1] == L':' && tmp[2] == L'\\')
  267. {
  268. // User included a drive letter.
  269. // remove it and assume they selected to choose the installation
  270. // partition in textmode.
  271. lstrcpy( InstallDir, &tmp[2] );
  272. bSelectedChoosePartition = TRUE;
  273. } else {
  274. if (tmp[0] == L'\\') {
  275. lstrcpy( InstallDir, tmp );
  276. } else {
  277. InstallDir[0] = L'\\';
  278. lstrcpy( &InstallDir[1], tmp );
  279. }
  280. }
  281. //
  282. // if user selected any of the accessibility options, warn about choosing the partition installation
  283. //
  284. if(bSelectedChoosePartition &&
  285. (AccessibleMagnifier || AccessibleKeyboard || AccessibleVoice || AccessibleReader) &&
  286. IDYES != MessageBoxFromMessage(hdlg, MSG_WARNING_ACCESSIBILITY, FALSE, AppTitleStringId, MB_YESNO | MB_ICONEXCLAMATION)) {
  287. b = TRUE;
  288. break;
  289. }
  290. ChoosePartition = bSelectedChoosePartition;
  291. }
  292. //
  293. // warn the user if their install dir is > 8 characters, since it will be truncated
  294. //
  295. if (!IsValid8Dot3(InstallDir) && IsWindowEnabled(GetDlgItem(hdlg,IDC_INSTALL_DIR ))) {
  296. InstallDir[0] = 0;
  297. MessageBoxFromMessage(
  298. hdlg,
  299. MSG_WRN_TRUNC_WINDIR,
  300. FALSE,
  301. AppTitleStringId,
  302. MB_OK | MB_ICONEXCLAMATION
  303. );
  304. SetFocus(GetDlgItem(hdlg,IDC_INSTALL_DIR));
  305. b = FALSE;
  306. } else {
  307. EndDialog(hdlg,TRUE);
  308. b = TRUE;
  309. }
  310. #ifdef _X86_
  311. {
  312. if ((SendDlgItemMessage (hdlg, IDC_BOOT16_1, BM_GETSTATE, 0, 0) & 0x0003) == BST_CHECKED) {
  313. g_Boot16 = BOOT16_AUTOMATIC;
  314. }
  315. else
  316. if ((SendDlgItemMessage (hdlg, IDC_BOOT16_2, BM_GETSTATE, 0, 0) & 0x0003) == BST_CHECKED) {
  317. g_Boot16 = BOOT16_YES;
  318. }
  319. else
  320. if ((SendDlgItemMessage (hdlg, IDC_BOOT16_3, BM_GETSTATE, 0, 0) & 0x0003) == BST_CHECKED) {
  321. g_Boot16 = BOOT16_NO;
  322. }
  323. else {
  324. g_Boot16 = BOOT16_AUTOMATIC;
  325. }
  326. }
  327. #endif
  328. //
  329. // Now take care of the headless settings.
  330. //
  331. if( IsDlgButtonChecked( hdlg, IDC_ENABLE_HEADLESS) == BST_CHECKED ) {
  332. //
  333. // He wants to run setup, and the resulting installation
  334. // through a headless port. Got figure out which headless
  335. // port he wants to use.
  336. //
  337. GetDlgItemText( hdlg,
  338. IDC_HEADLESS_PORT,
  339. HeadlessSelection,
  340. MAX_PATH );
  341. if( (HeadlessSelection[0] == 0) ||
  342. (lstrcmpi( HeadlessSelection, TEXT("usebiossettings"))) ||
  343. (_tcsnicmp( HeadlessSelection, TEXT("com"), 3)) ) {
  344. //
  345. // He gave us something that's invalid.
  346. //
  347. MessageBoxFromMessage( hdlg,
  348. MSG_INVALID_HEADLESS_SETTING,
  349. FALSE,
  350. AppTitleStringId,
  351. MB_OK | MB_ICONEXCLAMATION );
  352. _tcscpy( HeadlessSelection, DEFAULT_HEADLESS_SETTING );
  353. SetDlgItemText( hdlg,
  354. IDC_HEADLESS_PORT,
  355. HeadlessSelection );
  356. SetFocus(GetDlgItem(hdlg,IDC_HEADLESS_PORT));
  357. b = FALSE;
  358. }
  359. }
  360. }
  361. break;
  362. case IDCANCEL:
  363. if(HIWORD(wParam) == BN_CLICKED) {
  364. EndDialog(hdlg,FALSE);
  365. b = TRUE;
  366. }
  367. break;
  368. case IDC_ENABLE_HEADLESS:
  369. if( HIWORD(wParam) == BN_CLICKED ) {
  370. if( IsDlgButtonChecked(hdlg, IDC_ENABLE_HEADLESS) ) {
  371. //
  372. // Make sure the headless settings box is enabled.
  373. //
  374. EnableWindow( GetDlgItem(hdlg, IDC_HEADLESS_PORT), TRUE );
  375. ShowWindow( GetDlgItem(hdlg, IDC_HEADLESS_PORT), SW_SHOW );
  376. if( HeadlessSelection[0] == TEXT('\0') ) {
  377. //
  378. // This is the first time the user has asked
  379. // us to enable Headless. Suggest the use of
  380. // se the default COM port.
  381. //
  382. _tcscpy( HeadlessSelection, DEFAULT_HEADLESS_SETTING );
  383. }
  384. SetDlgItemText( hdlg,
  385. IDC_HEADLESS_PORT,
  386. HeadlessSelection );
  387. SetFocus(GetDlgItem(hdlg,IDC_HEADLESS_PORT));
  388. } else {
  389. //
  390. // Disable the headless settings box since the
  391. // user has chosen not to use headless.
  392. //
  393. HeadlessSelection[0] = TEXT('\0');
  394. EnableWindow( GetDlgItem(hdlg, IDC_HEADLESS_PORT), FALSE );
  395. ShowWindow( GetDlgItem(hdlg, IDC_HEADLESS_PORT), SW_HIDE );
  396. }
  397. }
  398. break;
  399. case IDC_HEADLESS_PORT:
  400. if( HIWORD(wParam) == EN_CHANGE) {
  401. EnableWindow( GetDlgItem(hdlg, IDOK),
  402. SendDlgItemMessage(hdlg, IDC_HEADLESS_PORT,WM_GETTEXTLENGTH,0,0) ? TRUE : FALSE );
  403. }
  404. break;
  405. case IDC_SOURCE:
  406. if(HIWORD(wParam) == EN_CHANGE) {
  407. EnableWindow(
  408. GetDlgItem(hdlg,IDOK),
  409. SendDlgItemMessage(hdlg,IDC_SOURCE,WM_GETTEXTLENGTH,0,0) ? TRUE : FALSE
  410. );
  411. }
  412. break;
  413. case IDC_SOURCE2:
  414. if(HIWORD(wParam) == EN_CHANGE) {
  415. EnableWindow(
  416. GetDlgItem(hdlg,IDOK),
  417. SendDlgItemMessage(hdlg,IDC_SOURCE2,WM_GETTEXTLENGTH,0,0) ? TRUE : FALSE
  418. );
  419. }
  420. break;
  421. case IDB_BROWSE:
  422. if(HIWORD(wParam) == BN_CLICKED) {
  423. TCHAR InitialPath[MAX_PATH];
  424. TCHAR NewPath[MAX_PATH];
  425. GetDlgItemText(hdlg,IDC_SOURCE2,InitialPath,MAX_PATH);
  426. if(BrowseForDosnetInf(hdlg,InitialPath,NewPath)) {
  427. SetDlgItemText(hdlg,IDC_SOURCE2,NewPath);
  428. }
  429. b = TRUE;
  430. }
  431. break;
  432. #if defined(_AMD64_) || defined(_X86_)
  433. case IDC_USEFLOPPIES:
  434. b = FALSE;
  435. if(HIWORD(wParam) == BN_CLICKED) {
  436. MEDIA_TYPE MediaType;
  437. // switch(MediaType = GetMediaType(TEXT('A'), NULL)) {
  438. switch(MediaType = GetMediaType(FirstFloppyDriveLetter, NULL)) {
  439. case Unknown:
  440. case F5_1Pt2_512:
  441. case F3_720_512:
  442. case F5_360_512:
  443. case F5_320_512:
  444. case F5_320_1024:
  445. case F5_180_512:
  446. case F5_160_512:
  447. case RemovableMedia:
  448. case FixedMedia:
  449. //
  450. // None of these are acceptable.
  451. //
  452. MessageBoxFromMessage(
  453. hdlg,
  454. MSG_EVIL_FLOPPY_DRIVE,
  455. FALSE,
  456. AppTitleStringId,
  457. MB_OK | MB_ICONERROR
  458. );
  459. CheckDlgButton(hdlg,IDC_USEFLOPPIES,BST_UNCHECKED);
  460. EnableWindow(GetDlgItem(hdlg,IDC_USEFLOPPIES),FALSE);
  461. Floppyless = TRUE;
  462. ForceFloppyless = TRUE;
  463. b = TRUE;
  464. break;
  465. case F3_1Pt44_512:
  466. case F3_2Pt88_512:
  467. case F3_20Pt8_512:
  468. case F3_120M_512:
  469. default:
  470. //
  471. // Allow these -- nothing to do here.
  472. // Note that this includes types we don't know about,
  473. // since new types could appear after we ship and we assume
  474. // they'll be big enough.
  475. //
  476. break;
  477. }
  478. // } -to match commented out switch above.
  479. }
  480. break;
  481. #endif
  482. }
  483. break;
  484. case WM_HELP:
  485. MyWinHelp(((HELPINFO *)lParam)->hItemHandle,HELP_WM_HELP,(ULONG_PTR)OptionsDlgContextHelp);
  486. b = TRUE;
  487. break;
  488. case WM_CONTEXTMENU:
  489. MyWinHelp((HWND)wParam,HELP_CONTEXTMENU,(ULONG_PTR)OptionsDlgContextHelp);
  490. b = TRUE;
  491. break;
  492. default:
  493. b = FALSE;
  494. break;
  495. }
  496. return(b);
  497. }
  498. VOID
  499. DoOptions(
  500. IN HWND Parent
  501. )
  502. {
  503. INT_PTR i;
  504. if (Upgrade && !ISNT()) {
  505. i = DialogBox(hInst,MAKEINTRESOURCE(IDD_ADVANCED3),Parent,OptionsDlgProc);
  506. }
  507. else {
  508. i = DialogBox(hInst,MAKEINTRESOURCE(IDD_ADVANCED),Parent,OptionsDlgProc);
  509. }
  510. if(i == -1) {
  511. MessageBoxFromMessage(
  512. Parent,
  513. MSG_OUT_OF_MEMORY,
  514. FALSE,
  515. AppTitleStringId,
  516. MB_OK | MB_ICONERROR
  517. );
  518. }
  519. }
  520. VOID
  521. SaveLanguageDirs(
  522. )
  523. {
  524. DWORD ItemNo;
  525. HMODULE hKernel32 = NULL;
  526. LGRPID LangGroupId;
  527. PTSTR p;
  528. p = NULL;
  529. Kernel32IsValidLanguageGroup = NULL;
  530. //
  531. // Get IsValidLanguageGroup if we can
  532. //
  533. if (Upgrade && ISNT() && (BuildNumber >= NT50B3)) {
  534. hKernel32 = LoadLibrary(TEXT("KERNEL32"));
  535. if (hKernel32) {
  536. (FARPROC)Kernel32IsValidLanguageGroup =
  537. GetProcAddress( hKernel32, "IsValidLanguageGroup" );
  538. }
  539. }
  540. for( ItemNo=0; ItemNo<LanguageGroupsCount; ItemNo++ ) {
  541. //
  542. // When upgrading from NT 5, select any languages which are already
  543. // installed, to make sure they get upgraded.
  544. //
  545. LangGroupId = _tcstoul( LanguageGroups[ItemNo].Id, NULL, 10 );
  546. if (Kernel32IsValidLanguageGroup && LangGroupId &&
  547. Kernel32IsValidLanguageGroup( LangGroupId, LGRPID_INSTALLED )
  548. ) {
  549. LanguageGroups[ItemNo].Selected = TRUE;
  550. }
  551. //
  552. // Install any languages required by the primary locale.
  553. //
  554. if (!lstrcmp( LanguageGroups[ItemNo].Id, LocaleList[PrimaryLocale].LanguageGroup1 ) ||
  555. !lstrcmp( LanguageGroups[ItemNo].Id, LocaleList[PrimaryLocale].LanguageGroup2 )
  556. ) {
  557. LanguageGroups[ItemNo].Selected = TRUE;
  558. }
  559. //
  560. // Make sure the necessary optional directories get copied for all
  561. // selected language groups.
  562. //
  563. if( LanguageGroups[ItemNo].Selected ) {
  564. TCHAR TempString[MAX_PATH];
  565. if( LanguageGroups[ItemNo].Directory &&
  566. LanguageGroups[ItemNo].Directory[0]
  567. ) {
  568. RememberOptionalDir(
  569. LanguageGroups[ItemNo].Directory,
  570. OPTDIR_TEMPONLY | OPTDIR_ADDSRCARCH
  571. );
  572. #if defined(_WIN64)
  573. //Add the i386\lang folder if needed
  574. StringCchCopy( TempString, ARRAYSIZE(TempString), TEXT("\\I386\\"));
  575. StringCchCat( TempString, ARRAYSIZE(TempString), LanguageGroups[ItemNo].Directory );
  576. RememberOptionalDir(
  577. TempString,
  578. OPTDIR_TEMPONLY | OPTDIR_PLATFORM_INDEP
  579. );
  580. #endif
  581. }
  582. }
  583. }
  584. #ifdef _X86_
  585. //
  586. // If this is a win9xupg, we need to get any optional directories they need for installed languages.
  587. //
  588. if (Upgrade && !ISNT()) {
  589. p = UpgradeSupport.OptionalDirsRoutine ();
  590. while (p && *p) {
  591. RememberOptionalDir (p, OPTDIR_TEMPONLY | OPTDIR_ADDSRCARCH);
  592. p = _tcschr (p, 0) + 1;
  593. }
  594. }
  595. #endif
  596. }
  597. BOOL
  598. SaveLanguageParams(
  599. IN LPCTSTR FileName
  600. )
  601. {
  602. BOOL b;
  603. DWORD ItemNo;
  604. LPCTSTR WinntLangSection = WINNT_REGIONALSETTINGS;
  605. PTSTR LanguageString = NULL;
  606. UINT LanguageLength = 0;
  607. LPTSTR p;
  608. if( !IntlInfProcessed ) {
  609. return TRUE;
  610. }
  611. //
  612. // If this is a win9x upgrade, let the upgrade .dll take care
  613. // of writing these parameters.
  614. //
  615. if (Upgrade && !ISNT()) {
  616. return TRUE;
  617. }
  618. b = WritePrivateProfileString(
  619. WinntLangSection,
  620. WINNT_D_LANGUAGE,
  621. LocaleList[PrimaryLocale].Lcid,
  622. FileName
  623. );
  624. for( ItemNo=0; ItemNo<LanguageGroupsCount; ItemNo++ ) {
  625. if( LanguageGroups[ItemNo].Selected ) {
  626. if(LanguageString) {
  627. p = REALLOC(
  628. LanguageString,
  629. (lstrlen( LanguageGroups[ItemNo].Id) + 2 + LanguageLength ) * sizeof(TCHAR)
  630. );
  631. } else {
  632. p = MALLOC((lstrlen(LanguageGroups[ItemNo].Id)+2)*sizeof(TCHAR));
  633. }
  634. if(!p) {
  635. if( LanguageString ) {
  636. FREE( LanguageString );
  637. }
  638. return FALSE;
  639. }
  640. LanguageString = p;
  641. if( LanguageLength ) {
  642. lstrcat( LanguageString, LanguageGroups[ItemNo].Id );
  643. } else {
  644. lstrcpy( LanguageString, LanguageGroups[ItemNo].Id );
  645. }
  646. lstrcat( LanguageString, TEXT(",") );
  647. LanguageLength = lstrlen( LanguageString );
  648. }
  649. }
  650. if( LanguageString ) {
  651. //
  652. // Remove trailing "," if any
  653. //
  654. if( LanguageLength && (LanguageString[LanguageLength-1] == TEXT(','))) {
  655. LanguageString[LanguageLength-1] = 0;
  656. }
  657. b = b && WritePrivateProfileString(
  658. WinntLangSection,
  659. WINNT_D_LANGUAGE_GROUP,
  660. LanguageString,
  661. FileName
  662. );
  663. FREE( LanguageString );
  664. }
  665. return b;
  666. }
  667. VOID
  668. FreeLanguageData(
  669. )
  670. {
  671. DWORD ItemNo;
  672. //
  673. // Free all the data allocated for the language options data
  674. //
  675. for( ItemNo=0; ItemNo<LocaleCount; ItemNo++ ) {
  676. FREE( LocaleList[ItemNo].Lcid );
  677. FREE( LocaleList[ItemNo].Description );
  678. FREE( LocaleList[ItemNo].LanguageGroup1 );
  679. FREE( LocaleList[ItemNo].LanguageGroup2 );
  680. }
  681. LocaleCount = 0;
  682. for( ItemNo=0; ItemNo<LanguageGroupsCount; ItemNo++ ) {
  683. FREE( LanguageGroups[ItemNo].Id );
  684. FREE( LanguageGroups[ItemNo].Description );
  685. FREE( LanguageGroups[ItemNo].Directory );
  686. }
  687. LanguageGroupsCount = 0;
  688. if( LocaleList ) {
  689. FREE( LocaleList );
  690. }
  691. if( LanguageGroups ) {
  692. FREE( LanguageGroups );
  693. }
  694. IntlInfProcessed = FALSE;
  695. }
  696. int
  697. __cdecl
  698. LocaleCompare(
  699. const void *arg1,
  700. const void *arg2
  701. )
  702. {
  703. return lstrcmp(
  704. ((PLOCALE_ENTRY)arg1)->Description,
  705. ((PLOCALE_ENTRY)arg2)->Description
  706. );
  707. }
  708. int
  709. __cdecl
  710. LangGroupCompare(
  711. const void *arg1,
  712. const void *arg2
  713. )
  714. {
  715. return lstrcmp(
  716. ((PLANGUAGE_GROUP_ENTRY)arg1)->Description,
  717. ((PLANGUAGE_GROUP_ENTRY)arg2)->Description
  718. );
  719. }
  720. BOOL
  721. ReadIntlInf(
  722. IN HWND hdlg
  723. )
  724. {
  725. HINF IntlInf;
  726. TCHAR IntlInfName[MAX_PATH];
  727. DWORD LineCount;
  728. DWORD ItemNo, NeededSize = 0;
  729. LPCTSTR SectionName;
  730. INFCONTEXT InfContext;
  731. LPCTSTR Language;
  732. TCHAR CurrentLcid[9] = TEXT("\0");
  733. TCHAR CurrentLcidEx[9] = TEXT("\0"); // for AUTO_LANGPACK
  734. //
  735. // For AUTO_LANGPACK - BEGIN
  736. //
  737. // The pieces that are enclosed with AUTO_LANGPACK are for easy
  738. // installation of other LangPack rather than English.
  739. //
  740. // This is originally for globalization testing. You can erase it by
  741. // deleting lines surrounded or marked by the keyword AUTO_LANGPACK.
  742. //
  743. // Contact: YuhongLi
  744. //
  745. //
  746. // read "Locale" from an extra file INTLEX.INF to install
  747. // the locale rather than English (United States) by default.
  748. //
  749. // Here is a sample of INTLEX.INF which specifies Japanese
  750. // as the default. The file INTLEX.INF should be in Unicode.
  751. //
  752. // --- cut here ---
  753. // [Version]
  754. // Signature = $Chicago$
  755. //
  756. // [DefaultValues]
  757. // Locale = "00000411"
  758. // --- end of cut ---
  759. //
  760. // For German (Germany), Locale will be 00000407.
  761. //
  762. FindPathToInstallationFile( TEXT("intlex.inf"), IntlInfName, MAX_PATH);
  763. IntlInf = SetupapiOpenInfFile( IntlInfName, NULL, INF_STYLE_WIN4, NULL );
  764. if( IntlInf != INVALID_HANDLE_VALUE ) {
  765. if( SetupapiFindFirstLine( IntlInf, TEXT("DefaultValues"), TEXT("Locale"), &InfContext ) ) {
  766. SetupapiGetStringField( &InfContext, 1, CurrentLcidEx, (sizeof(CurrentLcidEx)/sizeof(TCHAR)), NULL );
  767. }
  768. SetupapiCloseInfFile( IntlInf );
  769. }
  770. //
  771. // For AUTO_LANGPACK -- END
  772. //
  773. //
  774. // Open the INF
  775. //
  776. FindPathToInstallationFile( TEXT("intl.inf"), IntlInfName, MAX_PATH);
  777. IntlInf = SetupapiOpenInfFile( IntlInfName, NULL, INF_STYLE_WIN4, NULL );
  778. if(IntlInf == INVALID_HANDLE_VALUE && hdlg) {
  779. MessageBoxFromMessageAndSystemError(
  780. hdlg,
  781. MSG_INTLINF_NOT_FOUND,
  782. GetLastError(),
  783. AppTitleStringId,
  784. MB_OK | MB_ICONERROR | MB_TASKMODAL
  785. );
  786. return FALSE;
  787. }
  788. //
  789. // Figure out what the default locale should be.
  790. //
  791. if( Upgrade ) {
  792. wsprintf( CurrentLcid, TEXT("%08x"), GetSystemDefaultLCID());
  793. } else if ( CurrentLcidEx[0] ) { // for AUTO_LANGPACK
  794. lstrcpy( CurrentLcid, CurrentLcidEx); // for AUTO_LANGPACK
  795. } else if( SetupapiFindFirstLine( IntlInf, TEXT("DefaultValues"), TEXT("Locale"), &InfContext )) {
  796. SetupapiGetStringField( &InfContext, 1, CurrentLcid, (sizeof(CurrentLcid)/sizeof(TCHAR)), NULL );
  797. } else {
  798. if (hdlg) {
  799. MessageBoxFromMessage(
  800. hdlg,
  801. MSG_INTLINF_NOT_FOUND,
  802. FALSE,
  803. AppTitleStringId,
  804. MB_OK | MB_ICONERROR | MB_TASKMODAL
  805. );
  806. }
  807. return FALSE;
  808. }
  809. //
  810. // Read the [Locales] section, sort it, and find the default value in the list.
  811. //
  812. SectionName = TEXT("Locales");
  813. LocaleCount = SetupapiGetLineCount( IntlInf, SectionName );
  814. LocaleList = MALLOC( LocaleCount*sizeof( LOCALE_ENTRY ) );
  815. if(!LocaleList){
  816. SetupapiCloseInfFile( IntlInf );
  817. return FALSE;
  818. }
  819. memset(LocaleList, 0, LocaleCount*sizeof( LOCALE_ENTRY ) );
  820. for( ItemNo=0; ItemNo<LocaleCount; ItemNo++ ) {
  821. if( SetupapiGetLineByIndex( IntlInf, SectionName, ItemNo, &InfContext )) {
  822. if( SetupapiGetStringField( &InfContext, 0, NULL, 0, &NeededSize )){
  823. if( NeededSize && (LocaleList[ItemNo].Lcid = MALLOC( NeededSize*sizeof(TCHAR) ))){
  824. SetupapiGetStringField( &InfContext, 0, LocaleList[ItemNo].Lcid, NeededSize, NULL );
  825. }
  826. }
  827. if( SetupapiGetStringField( &InfContext, 1, NULL, 0, &NeededSize )){
  828. if( NeededSize && (LocaleList[ItemNo].Description = MALLOC( NeededSize*sizeof(TCHAR) ))){
  829. SetupapiGetStringField( &InfContext, 1, LocaleList[ItemNo].Description, NeededSize, NULL );
  830. }
  831. }
  832. if( SetupapiGetStringField( &InfContext, 3, NULL, 0, &NeededSize )){
  833. if( NeededSize && (LocaleList[ItemNo].LanguageGroup1 = MALLOC( NeededSize*sizeof(TCHAR) ))){
  834. SetupapiGetStringField( &InfContext, 3, LocaleList[ItemNo].LanguageGroup1, NeededSize, NULL );
  835. }
  836. }
  837. if( SetupapiGetStringField( &InfContext, 4, NULL, 0, &NeededSize )){
  838. if( NeededSize && (LocaleList[ItemNo].LanguageGroup2 = MALLOC( NeededSize*sizeof(TCHAR) ))){
  839. SetupapiGetStringField( &InfContext, 4, LocaleList[ItemNo].LanguageGroup2, NeededSize, NULL );
  840. }
  841. }
  842. }
  843. else {
  844. SetupapiCloseInfFile( IntlInf );
  845. free( LocaleList );
  846. return FALSE;
  847. }
  848. }
  849. qsort(
  850. LocaleList,
  851. LocaleCount,
  852. sizeof(LOCALE_ENTRY),
  853. LocaleCompare
  854. );
  855. for( ItemNo=0; ItemNo<LocaleCount; ItemNo++ ) {
  856. if( LocaleList[ItemNo].Lcid && !lstrcmpi( CurrentLcid, LocaleList[ItemNo].Lcid)) {
  857. PrimaryLocale = ItemNo;
  858. break;
  859. }
  860. }
  861. //
  862. // Read the [LanguageGroups] section and sort it
  863. //
  864. SectionName = TEXT("LanguageGroups");
  865. LanguageGroupsCount = SetupapiGetLineCount( IntlInf, SectionName );
  866. LanguageGroups = MALLOC( LanguageGroupsCount*sizeof( LANGUAGE_GROUP_ENTRY ) );
  867. if(!LanguageGroups){
  868. SetupapiCloseInfFile( IntlInf );
  869. return FALSE;
  870. }
  871. memset(LanguageGroups, 0, LanguageGroupsCount*sizeof( LANGUAGE_GROUP_ENTRY ) );
  872. for( ItemNo=0; ItemNo<LanguageGroupsCount; ItemNo++ ) {
  873. if( SetupapiGetLineByIndex( IntlInf, SectionName, ItemNo, &InfContext )) {
  874. if( SetupapiGetStringField( &InfContext, 0, NULL, 0, &NeededSize )){
  875. if( NeededSize && (LanguageGroups[ItemNo].Id = MALLOC( NeededSize*sizeof(TCHAR) ))){
  876. SetupapiGetStringField( &InfContext, 0, LanguageGroups[ItemNo].Id, NeededSize, NULL );
  877. }
  878. }
  879. if( SetupapiGetStringField( &InfContext, 1, NULL, 0, &NeededSize )){
  880. if( NeededSize && (LanguageGroups[ItemNo].Description = MALLOC( NeededSize*sizeof(TCHAR) ))){
  881. SetupapiGetStringField( &InfContext, 1, LanguageGroups[ItemNo].Description, NeededSize, NULL );
  882. }
  883. }
  884. if( SetupapiGetStringField( &InfContext, 2, NULL, 0, &NeededSize )){
  885. if( NeededSize && (LanguageGroups[ItemNo].Directory = MALLOC( NeededSize*sizeof(TCHAR) ))){
  886. SetupapiGetStringField( &InfContext, 2, LanguageGroups[ItemNo].Directory, NeededSize, NULL );
  887. }
  888. }
  889. LanguageGroups[ItemNo].Selected = FALSE;
  890. //
  891. // Handle Hong Kong upgrades as a special case: always install Language
  892. // Groups 9 and 10.
  893. //
  894. if( (TargetNativeLangID == 0xc04) && Upgrade &&
  895. (!lstrcmpi( LanguageGroups[ItemNo].Id, TEXT("9")) ||
  896. !lstrcmpi( LanguageGroups[ItemNo].Id, TEXT("10"))) ) {
  897. LanguageGroups[ItemNo].Selected = TRUE;
  898. }
  899. }
  900. else {
  901. SetupapiCloseInfFile( IntlInf );
  902. free( LocaleList );
  903. free( LanguageGroups );
  904. return FALSE;
  905. }
  906. }
  907. qsort(
  908. LanguageGroups,
  909. LanguageGroupsCount,
  910. sizeof(LANGUAGE_GROUP_ENTRY),
  911. LangGroupCompare
  912. );
  913. // If the primary language is a Far East one, don't show the check box.
  914. if (IsFarEastLanguage(PrimaryLocale))
  915. {
  916. ShowWindow(GetDlgItem(hdlg, IDC_FAREAST_LANG), SW_HIDE);
  917. }
  918. //
  919. // Clean up
  920. //
  921. SetupapiCloseInfFile( IntlInf );
  922. IntlInfProcessed = TRUE;
  923. return TRUE;
  924. }
  925. BOOL InitLangControl(HWND hdlg, BOOL bFarEast)
  926. {
  927. DWORD ItemNo;
  928. //
  929. // Init primary language combo box
  930. //
  931. for( ItemNo=0; ItemNo<LocaleCount; ItemNo++ ) {
  932. SendDlgItemMessage( hdlg, IDC_COMBO1, CB_ADDSTRING, 0, (LPARAM)LocaleList[ItemNo].Description );
  933. }
  934. SendDlgItemMessage( hdlg, IDC_COMBO1, CB_SETCURSEL, PrimaryLocale, 0 );
  935. // if the running language or the to be installed language is a FarEast
  936. // language, this check box is not visible, because we install the language folder anyway.
  937. if (IsWindowVisible(GetDlgItem(hdlg,IDC_FAREAST_LANG)))
  938. {
  939. if (bFarEast || IsFarEastLanguage(PrimaryLocale))
  940. {
  941. CheckDlgButton(hdlg,IDC_FAREAST_LANG,BST_CHECKED);
  942. }
  943. else
  944. {
  945. CheckDlgButton(hdlg,IDC_FAREAST_LANG,BST_UNCHECKED);
  946. }
  947. }
  948. return TRUE;
  949. }
  950. INT_PTR
  951. LanguageDlgProc(
  952. IN HWND hdlg,
  953. IN UINT msg,
  954. IN WPARAM wParam,
  955. IN LPARAM lParam
  956. )
  957. {
  958. BOOL b;
  959. DWORD ItemNo;
  960. switch(msg) {
  961. case WM_INITDIALOG:
  962. if( !IntlInfProcessed ) {
  963. EndDialog( hdlg, FALSE );
  964. }
  965. //
  966. // Init locales
  967. //
  968. for( ItemNo=0; ItemNo<LocaleCount; ItemNo++ ) {
  969. SendDlgItemMessage( hdlg, IDC_COMBO1, CB_ADDSTRING, 0, (LPARAM)LocaleList[ItemNo].Description );
  970. }
  971. SendDlgItemMessage( hdlg, IDC_COMBO1, CB_SETCURSEL, PrimaryLocale, 0 );
  972. //
  973. // Init language groups
  974. //
  975. for( ItemNo=0; ItemNo<LanguageGroupsCount; ItemNo++ ) {
  976. SendDlgItemMessage( hdlg, IDC_LIST, LB_ADDSTRING, 0, (LPARAM)LanguageGroups[ItemNo].Description );
  977. SendDlgItemMessage( hdlg, IDC_LIST, LB_SETSEL, LanguageGroups[ItemNo].Selected, ItemNo );
  978. }
  979. for( ItemNo=0; ItemNo<LanguageGroupsCount; ItemNo++ ) {
  980. LanguageGroups[ItemNo].Selected = (int)SendDlgItemMessage( hdlg, IDC_LIST, LB_GETSEL, ItemNo, 0 );
  981. }
  982. //
  983. // Set focus to Cancel button.
  984. //
  985. SetFocus(GetDlgItem(hdlg,IDCANCEL));
  986. b = FALSE;
  987. break;
  988. case WM_COMMAND:
  989. b = FALSE;
  990. switch(LOWORD(wParam)) {
  991. case IDOK:
  992. if(HIWORD(wParam) == BN_CLICKED) {
  993. PrimaryLocale = (DWORD)SendDlgItemMessage( hdlg, IDC_COMBO1, CB_GETCURSEL, 0, 0 );
  994. for( ItemNo=0; ItemNo<LanguageGroupsCount; ItemNo++ ) {
  995. LanguageGroups[ItemNo].Selected = (int)SendDlgItemMessage( hdlg, IDC_LIST, LB_GETSEL, ItemNo, 0 );
  996. }
  997. EndDialog(hdlg,TRUE);
  998. b = TRUE;
  999. }
  1000. break;
  1001. case IDCANCEL:
  1002. if(HIWORD(wParam) == BN_CLICKED) {
  1003. EndDialog(hdlg,FALSE);
  1004. b = TRUE;
  1005. }
  1006. break;
  1007. }
  1008. break;
  1009. default:
  1010. b = FALSE;
  1011. break;
  1012. }
  1013. return(b);
  1014. }
  1015. VOID
  1016. DoLanguage(
  1017. IN HWND Parent
  1018. )
  1019. {
  1020. INT_PTR i;
  1021. i = DialogBox(hInst,MAKEINTRESOURCE(IDD_LANGUAGE),Parent,LanguageDlgProc);
  1022. if(i == -1) {
  1023. MessageBoxFromMessage(
  1024. Parent,
  1025. MSG_OUT_OF_MEMORY,
  1026. FALSE,
  1027. AppTitleStringId,
  1028. MB_OK | MB_ICONERROR
  1029. );
  1030. }
  1031. }
  1032. INT_PTR
  1033. AccessibilityDlgProc(
  1034. IN HWND hdlg,
  1035. IN UINT msg,
  1036. IN WPARAM wParam,
  1037. IN LPARAM lParam
  1038. )
  1039. {
  1040. BOOL b;
  1041. TCHAR VisibleNarrator[2];
  1042. switch(msg) {
  1043. case WM_INITDIALOG:
  1044. //
  1045. // Disable the narrator in locales that don't support it.
  1046. //
  1047. if (!LoadString(hInst,IDS_VISIBLE_NARRATOR_CONTROL,VisibleNarrator,sizeof(VisibleNarrator)/sizeof(TCHAR)) ||
  1048. lstrcmp(VisibleNarrator,TEXT("1"))) {
  1049. EnableWindow(GetDlgItem( hdlg, IDC_READER ), FALSE);
  1050. ShowWindow(GetDlgItem( hdlg, IDC_READER ), SW_HIDE);
  1051. EnableWindow(GetDlgItem( hdlg, IDC_READER_TEXT ), FALSE);
  1052. ShowWindow(GetDlgItem( hdlg, IDC_READER_TEXT ), SW_HIDE);
  1053. }
  1054. //
  1055. // check the target LCID and disable it for non-English locales
  1056. //
  1057. if (SourceNativeLangID) {
  1058. if (!(SourceNativeLangID == 0x0409 || SourceNativeLangID == 0x0809)) {
  1059. EnableWindow(GetDlgItem( hdlg, IDC_READER ), FALSE);
  1060. ShowWindow(GetDlgItem( hdlg, IDC_READER ), SW_HIDE);
  1061. EnableWindow(GetDlgItem( hdlg, IDC_READER_TEXT ), FALSE);
  1062. ShowWindow(GetDlgItem( hdlg, IDC_READER_TEXT ), SW_HIDE);
  1063. }
  1064. }
  1065. //
  1066. // Set the initial state of the check boxes.
  1067. //
  1068. CheckDlgButton(hdlg,IDC_MAGNIFIER,AccessibleMagnifier ?
  1069. BST_CHECKED : BST_UNCHECKED);
  1070. CheckDlgButton(hdlg,IDC_KEYBOARD,AccessibleKeyboard ?
  1071. BST_CHECKED : BST_UNCHECKED);
  1072. CheckDlgButton(hdlg,IDC_VOICE,AccessibleVoice ?
  1073. BST_CHECKED : BST_UNCHECKED);
  1074. CheckDlgButton(hdlg,IDC_READER,AccessibleReader ?
  1075. BST_CHECKED : BST_UNCHECKED);
  1076. //
  1077. // Set focus to Cancel button.
  1078. //
  1079. SetFocus(GetDlgItem(hdlg,IDCANCEL));
  1080. b = FALSE;
  1081. break;
  1082. case WM_COMMAND:
  1083. b = FALSE;
  1084. switch(LOWORD(wParam)) {
  1085. case IDOK:
  1086. if(HIWORD(wParam) == BN_CLICKED) {
  1087. BOOL bSelectedAccessibleMagnifier;
  1088. BOOL bSelectedAccessibleKeyboard;
  1089. BOOL bSelectedAccessibleVoice;
  1090. BOOL bSelectedAccessibleReader;
  1091. b = TRUE;
  1092. bSelectedAccessibleMagnifier = (IsDlgButtonChecked(hdlg,IDC_MAGNIFIER) == BST_CHECKED);
  1093. bSelectedAccessibleKeyboard = (IsDlgButtonChecked(hdlg,IDC_KEYBOARD) == BST_CHECKED);
  1094. bSelectedAccessibleVoice = (IsDlgButtonChecked(hdlg,IDC_VOICE) == BST_CHECKED);
  1095. bSelectedAccessibleReader = (IsDlgButtonChecked(hdlg,IDC_READER) == BST_CHECKED);
  1096. //
  1097. // if user selected any of the accessibility options, warn about choosing the partition installation
  1098. //
  1099. if(ChoosePartition &&
  1100. (bSelectedAccessibleMagnifier || bSelectedAccessibleKeyboard || bSelectedAccessibleVoice || bSelectedAccessibleReader) &&
  1101. IDYES != MessageBoxFromMessage(hdlg, MSG_WARNING_ACCESSIBILITY, FALSE, AppTitleStringId, MB_YESNO | MB_ICONEXCLAMATION)) {
  1102. break;
  1103. }
  1104. AccessibleMagnifier = bSelectedAccessibleMagnifier;
  1105. AccessibleKeyboard = bSelectedAccessibleKeyboard;
  1106. AccessibleVoice = bSelectedAccessibleVoice;
  1107. AccessibleReader = bSelectedAccessibleReader;
  1108. EndDialog(hdlg,TRUE);
  1109. }
  1110. break;
  1111. case IDCANCEL:
  1112. if(HIWORD(wParam) == BN_CLICKED) {
  1113. EndDialog(hdlg,FALSE);
  1114. b = TRUE;
  1115. }
  1116. break;
  1117. }
  1118. break;
  1119. default:
  1120. b = FALSE;
  1121. break;
  1122. }
  1123. return(b);
  1124. }
  1125. VOID
  1126. DoAccessibility(
  1127. IN HWND Parent
  1128. )
  1129. {
  1130. INT_PTR i;
  1131. i = DialogBox(hInst,MAKEINTRESOURCE(IDD_ACCESSIBILITY),Parent,AccessibilityDlgProc);
  1132. if(i == -1) {
  1133. MessageBoxFromMessage(
  1134. Parent,
  1135. MSG_OUT_OF_MEMORY,
  1136. FALSE,
  1137. AppTitleStringId,
  1138. MB_OK | MB_ICONERROR
  1139. );
  1140. }
  1141. }
  1142. VOID
  1143. InitVariousOptions(
  1144. VOID
  1145. )
  1146. /*++
  1147. Routine Description:
  1148. Initialize options for program operation, including
  1149. - determining whether we were run from a CD
  1150. - whether we should create a local source
  1151. If we are being run from CD then there's no need to create
  1152. a local source since we assume we can get to the CD from NT.
  1153. Arguments:
  1154. None.
  1155. Return Value:
  1156. None.
  1157. Global variables RunFromCD, MakeLocalSource filled in.
  1158. --*/
  1159. {
  1160. TCHAR Path[MAX_PATH];
  1161. //
  1162. // Assume not run from CD. In that case we need to create
  1163. // a local source. This is a global, and should be FALSE
  1164. // unless the user has sent us a /#R to force the RunFromCD.
  1165. //
  1166. // RunFromCD = FALSE;
  1167. #if defined(REMOTE_BOOT)
  1168. //
  1169. // If this is a remote boot client, MakeLocalSource is always false.
  1170. //
  1171. if (RemoteBoot) {
  1172. MakeLocalSource = FALSE;
  1173. MakeBootMedia = FALSE;
  1174. Floppyless = TRUE;
  1175. } else
  1176. #endif // defined(REMOTE_BOOT)
  1177. {
  1178. //
  1179. // Determine if we were run from CD.
  1180. //
  1181. if(MyGetModuleFileName(NULL,Path,MAX_PATH)) {
  1182. //
  1183. // For UNC paths this will do something bogus, but certainly
  1184. // won't return DRIVE_CDROM, so we don't care.
  1185. //
  1186. Path[3] = 0;
  1187. if(GetDriveType(Path) == DRIVE_CDROM) {
  1188. RunFromCD = TRUE;
  1189. }
  1190. }
  1191. //
  1192. // Now determine if we should MakeLocalSource.
  1193. //
  1194. if (!IsArc()) {
  1195. #if defined(_AMD64_)
  1196. //
  1197. // on AMD64, always make local source.
  1198. //
  1199. MakeLocalSource = TRUE;
  1200. #endif // defined(_AMD64_)
  1201. #if defined(_X86_)
  1202. //
  1203. // MakeLocalSource is a global, so he
  1204. // will be FALSE by default, unless the
  1205. // user has sent winnt32.exe the /MakeLocalSource flag,
  1206. // in which case, the flag will already be set to true.
  1207. //
  1208. MakeLocalSource = (MakeLocalSource || (!RunFromCD));
  1209. #endif // defined(_X86_)
  1210. } else {
  1211. #ifdef UNICODE // Always true for ARC, never true for Win9x upgrade
  1212. //
  1213. // on ARC, always make local source.
  1214. //
  1215. MakeLocalSource = TRUE;
  1216. #endif // UNICODE
  1217. } // if (!IsArc())
  1218. }
  1219. }
  1220. BOOL
  1221. BrowseForDosnetInf(
  1222. IN HWND hdlg,
  1223. IN LPCTSTR InitialPath,
  1224. OUT TCHAR NewPath[MAX_PATH]
  1225. )
  1226. /*++
  1227. Routine Description:
  1228. This routine invokes the standard win32 find file dialog for
  1229. dosnet.inf or whatever inf is currently selected to substitute for
  1230. dosnet.inf.
  1231. Arguments:
  1232. hdlg - supplies window handle of dialog to use as parent for
  1233. find file common dialog.
  1234. Return Value:
  1235. Boolean value indicating whether the user browsed and successfully
  1236. located dosnet.inf (or substitute).
  1237. --*/
  1238. {
  1239. BOOL b;
  1240. OPENFILENAME Info;
  1241. TCHAR Filter[2*MAX_PATH];
  1242. TCHAR File[MAX_PATH];
  1243. TCHAR Path[MAX_PATH];
  1244. DWORD d;
  1245. TCHAR Title[150];
  1246. PVOID p;
  1247. TCHAR* lastWack;
  1248. ZeroMemory(Filter,sizeof(Filter));
  1249. p = InfName;
  1250. d = FormatMessage(
  1251. FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  1252. hInst,
  1253. MSG_DOSNET_INF_DESC,
  1254. 0,
  1255. Filter,
  1256. MAX_PATH,
  1257. (va_list *)&p
  1258. );
  1259. //
  1260. // This is ok, since Filter is 2*MAX_PATH tchars long.
  1261. //
  1262. lstrcpy(Filter+d+1,InfName);
  1263. //
  1264. // This is ok, since both buffers are of size MAX_PATH
  1265. //
  1266. lstrcpy(File,InfName);
  1267. StringCchCopy(Path, ARRAYSIZE(Path), InitialPath);
  1268. LoadString(hInst,IDS_FIND_NT_FILES,Title,sizeof(Title)/sizeof(TCHAR));
  1269. Info.lStructSize = sizeof(OPENFILENAME);
  1270. Info.hwndOwner = hdlg;
  1271. Info.hInstance = NULL; // unused because not using a template
  1272. Info.lpstrFilter = Filter;
  1273. Info.lpstrCustomFilter = NULL;
  1274. Info.nMaxCustFilter = 0; // unused because lpstrCustomFilter is NULL
  1275. Info.nFilterIndex = 1;
  1276. Info.lpstrFile = File;
  1277. Info.nMaxFile = MAX_PATH;
  1278. Info.lpstrFileTitle = NULL;
  1279. Info.nMaxFileTitle = 0; // unused because lpstrFileTitle is NULL
  1280. Info.lpstrInitialDir = Path;
  1281. Info.lpstrTitle = Title;
  1282. Info.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_NODEREFERENCELINKS | OFN_PATHMUSTEXIST;
  1283. Info.nFileOffset = 0;
  1284. Info.nFileExtension = 0;
  1285. Info.lpstrDefExt = NULL;
  1286. Info.lCustData = 0; // unused because no hook is used
  1287. Info.lpfnHook = NULL; // unused because no hook is used
  1288. Info.lpTemplateName = NULL; // unused because no template is used
  1289. b = GetOpenFileName(&Info);
  1290. if(b) {
  1291. lstrcpy(NewPath,File);
  1292. lastWack = _tcsrchr(NewPath,TEXT('\\'));
  1293. if (lastWack) {
  1294. *lastWack = 0;
  1295. }
  1296. }
  1297. return(b);
  1298. }
  1299. BOOL
  1300. IsValid8Dot3(
  1301. IN LPCTSTR Path
  1302. )
  1303. /*++
  1304. Routine Description:
  1305. Check whether a path is valid 8.3. The path may or may not start with
  1306. a backslash. Only backslashes are recognized as path separators.
  1307. Individual characters are not checked for validity (ie, * would not
  1308. invalidate the path). The path may or may not terminate with a backslash.
  1309. A component may have a dot without characters in the extension
  1310. (ie, a\b.\c is valid).
  1311. \ and "" are explicitly disallowed even though they fit the rules.
  1312. Stolen from textmode\kernel sptarget.c
  1313. Arguments:
  1314. Path - pointer to path to check.
  1315. Return Value:
  1316. TRUE if valid 8.3, FALSE otherwise.
  1317. --*/
  1318. {
  1319. UINT Count;
  1320. BOOLEAN DotSeen,FirstChar;
  1321. static LPCTSTR UsableChars = TEXT("_-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
  1322. if((*Path == 0) || ((Path[0] == TEXT('\\')) && (Path[1] == 0))) {
  1323. return(FALSE);
  1324. }
  1325. DotSeen = FALSE;
  1326. FirstChar = TRUE;
  1327. Count = 0;
  1328. while(*Path) {
  1329. //
  1330. // Path points to start of current component (1 past the slash)
  1331. //
  1332. switch(*Path) {
  1333. case TEXT('.'):
  1334. if(FirstChar) {
  1335. return(FALSE);
  1336. }
  1337. if(DotSeen) {
  1338. return(FALSE);
  1339. }
  1340. Count = 0;
  1341. DotSeen = TRUE;
  1342. break;
  1343. case TEXT('\\'):
  1344. DotSeen = FALSE;
  1345. FirstChar = TRUE;
  1346. Count = 0;
  1347. if(*(++Path) == TEXT('\\')) {
  1348. // 2 slashes in a row
  1349. return(FALSE);
  1350. }
  1351. continue;
  1352. default:
  1353. Count++;
  1354. FirstChar = FALSE;
  1355. if((Count == 4) && DotSeen) {
  1356. return(FALSE);
  1357. }
  1358. if(Count == 9) {
  1359. return(FALSE);
  1360. }
  1361. //
  1362. // Make sure it's a printable, US character.
  1363. //
  1364. if( !_tcschr( UsableChars, *Path ) ) {
  1365. return( FALSE );
  1366. }
  1367. }
  1368. Path++;
  1369. }
  1370. return(TRUE);
  1371. }
  1372. BOOL
  1373. SaveLanguageOptions (
  1374. IN PCTSTR AnswerFile
  1375. )
  1376. {
  1377. UINT u;
  1378. UINT rem;
  1379. PTSTR list;
  1380. TCHAR buf[32];
  1381. LPTSTR p;
  1382. DWORD len;
  1383. DWORD size;
  1384. if (IntlInfProcessed) {
  1385. if (!WritePrivateProfileString (
  1386. WINNT_REGIONALSETTINGS,
  1387. TEXT("LangInf"),
  1388. WINNT_A_YES,
  1389. AnswerFile
  1390. )) {
  1391. return FALSE;
  1392. }
  1393. wsprintf (buf, TEXT("%u"), PrimaryLocale);
  1394. if (!WritePrivateProfileString(
  1395. WINNT_REGIONALSETTINGS,
  1396. TEXT("PrimaryLocaleIndex"),
  1397. buf,
  1398. AnswerFile
  1399. )) {
  1400. return FALSE;
  1401. }
  1402. size = rem = 32;
  1403. list = MALLOC (size);
  1404. if (!list) {
  1405. return FALSE;
  1406. }
  1407. *list = 0;
  1408. for (u = 0; u < LanguageGroupsCount; u++) {
  1409. if (LanguageGroups[u].Selected) {
  1410. len = wsprintf (buf, TEXT("%u"), u);
  1411. while (len + 1 > rem) {
  1412. PTSTR listReallocated = NULL;
  1413. size *= 2;
  1414. listReallocated = REALLOC (list, size);
  1415. if (!listReallocated) {
  1416. FREE(list);
  1417. return FALSE;
  1418. }
  1419. list = listReallocated;
  1420. rem = size;
  1421. }
  1422. if (*list) {
  1423. lstrcat (list, TEXT(","));
  1424. rem--;
  1425. }
  1426. lstrcat (list, buf);
  1427. rem -= len;
  1428. }
  1429. }
  1430. if (*list) {
  1431. if (!WritePrivateProfileString(
  1432. WINNT_REGIONALSETTINGS,
  1433. TEXT("Selected"),
  1434. list,
  1435. AnswerFile
  1436. )) {
  1437. FREE( list );
  1438. return FALSE;
  1439. }
  1440. }
  1441. FREE( list );
  1442. }
  1443. return TRUE;
  1444. }
  1445. BOOL
  1446. LoadLanguageOptions (
  1447. IN PCTSTR AnswerFile
  1448. )
  1449. {
  1450. PTSTR optDirs;
  1451. TCHAR buf[MAX_PATH];
  1452. PTSTR list = NULL;
  1453. PTSTR p, q;
  1454. DWORD size;
  1455. DWORD u;
  1456. if (!IntlInfProcessed) {
  1457. return FALSE;
  1458. }
  1459. GetPrivateProfileString (
  1460. WINNT_REGIONALSETTINGS,
  1461. TEXT("LangInf"),
  1462. WINNT_A_NO,
  1463. buf,
  1464. MAX_PATH,
  1465. AnswerFile
  1466. );
  1467. IntlInfProcessed = !lstrcmpi (buf, WINNT_A_YES);
  1468. if (!IntlInfProcessed) {
  1469. return FALSE;
  1470. }
  1471. if (!GetPrivateProfileString(
  1472. WINNT_REGIONALSETTINGS,
  1473. TEXT("PrimaryLocaleIndex"),
  1474. TEXT(""),
  1475. buf,
  1476. MAX_PATH,
  1477. AnswerFile
  1478. )) {
  1479. return FALSE;
  1480. }
  1481. PrimaryLocale = (DWORD) _ttol (buf);
  1482. size = 16;
  1483. do {
  1484. if (!list) {
  1485. list = MALLOC (size);
  1486. } else {
  1487. PTSTR listReallocated;
  1488. size *= 2;
  1489. listReallocated = REALLOC (list, size);
  1490. if(!listReallocated){
  1491. FREE(list);
  1492. }
  1493. list = listReallocated;
  1494. }
  1495. if (!list) {
  1496. return FALSE;
  1497. }
  1498. if (GetPrivateProfileString (
  1499. WINNT_REGIONALSETTINGS,
  1500. TEXT("Selected"),
  1501. TEXT(""),
  1502. list,
  1503. size / sizeof ( TCHAR ),
  1504. AnswerFile
  1505. ) < size - 1) {
  1506. break;
  1507. }
  1508. } while (TRUE);
  1509. p = list;
  1510. do {
  1511. q = _tcschr (p, TEXT(','));
  1512. if (q) {
  1513. *q = 0;
  1514. }
  1515. u = _ttol (p);
  1516. if (u >= LanguageGroupsCount) {
  1517. FREE (list);
  1518. return FALSE;
  1519. }
  1520. LanguageGroups[u].Selected = TRUE;
  1521. if (q) {
  1522. p = q + 1;
  1523. }
  1524. } while (q);
  1525. FREE (list);
  1526. return TRUE;
  1527. }
  1528. BOOL
  1529. SaveAdvancedOptions (
  1530. IN PCTSTR AnswerFile
  1531. )
  1532. {
  1533. TCHAR buf[32];
  1534. return
  1535. (!MakeLocalSource ||
  1536. WritePrivateProfileString (
  1537. TEXT("AdvancedOptions"),
  1538. TEXT("MakeLS"),
  1539. WINNT_A_YES,
  1540. AnswerFile
  1541. )) &&
  1542. (!UserSpecifiedMakeLocalSource ||
  1543. WritePrivateProfileString (
  1544. TEXT("AdvancedOptions"),
  1545. TEXT("UserMakeLS"),
  1546. WINNT_A_YES,
  1547. AnswerFile
  1548. )) &&
  1549. (!Floppyless ||
  1550. WritePrivateProfileString (
  1551. TEXT("AdvancedOptions"),
  1552. TEXT("Floppyless"),
  1553. WINNT_A_YES,
  1554. AnswerFile
  1555. )) &&
  1556. (!SystemPartitionDriveLetter ||
  1557. WritePrivateProfileString (
  1558. TEXT("AdvancedOptions"),
  1559. TEXT("SysPartDriveLetter"),
  1560. _ltot (SystemPartitionDriveLetter, buf, 10),
  1561. AnswerFile
  1562. )) &&
  1563. (!ChoosePartition ||
  1564. WritePrivateProfileString (
  1565. TEXT("AdvancedOptions"),
  1566. TEXT("ChoosePartition"),
  1567. WINNT_A_YES,
  1568. AnswerFile
  1569. )) &&
  1570. (!InstallDir[0] ||
  1571. WritePrivateProfileString (
  1572. TEXT("AdvancedOptions"),
  1573. TEXT("InstallDir"),
  1574. InstallDir,
  1575. AnswerFile
  1576. ));
  1577. }
  1578. BOOL
  1579. LoadAdvancedOptions (
  1580. IN PCTSTR AnswerFile
  1581. )
  1582. {
  1583. TCHAR buf[MAX_PATH];
  1584. GetPrivateProfileString (
  1585. TEXT("AdvancedOptions"),
  1586. TEXT("MakeLS"),
  1587. WINNT_A_NO,
  1588. buf,
  1589. MAX_PATH,
  1590. AnswerFile
  1591. );
  1592. MakeLocalSource = !lstrcmpi (buf, WINNT_A_YES);
  1593. GetPrivateProfileString (
  1594. TEXT("AdvancedOptions"),
  1595. TEXT("UserMakeLS"),
  1596. WINNT_A_NO,
  1597. buf,
  1598. MAX_PATH,
  1599. AnswerFile
  1600. );
  1601. UserSpecifiedMakeLocalSource = !lstrcmpi (buf, WINNT_A_YES);
  1602. GetPrivateProfileString (
  1603. TEXT("AdvancedOptions"),
  1604. TEXT("Floppyless"),
  1605. WINNT_A_NO,
  1606. buf,
  1607. MAX_PATH,
  1608. AnswerFile
  1609. );
  1610. Floppyless = !lstrcmpi (buf, WINNT_A_YES);
  1611. if (GetPrivateProfileString (
  1612. TEXT("AdvancedOptions"),
  1613. TEXT("SysPartDriveLetter"),
  1614. TEXT(""),
  1615. buf,
  1616. MAX_PATH,
  1617. AnswerFile
  1618. )) {
  1619. SystemPartitionDriveLetter = (TCHAR) _ttol (buf);
  1620. }
  1621. GetPrivateProfileString (
  1622. TEXT("AdvancedOptions"),
  1623. TEXT("ChoosePartition"),
  1624. WINNT_A_NO,
  1625. buf,
  1626. MAX_PATH,
  1627. AnswerFile
  1628. );
  1629. ChoosePartition = !lstrcmpi (buf, WINNT_A_YES);
  1630. GetPrivateProfileString (
  1631. TEXT("AdvancedOptions"),
  1632. TEXT("InstallDir"),
  1633. TEXT(""),
  1634. InstallDir,
  1635. sizeof (InstallDir) / sizeof (TCHAR),
  1636. AnswerFile
  1637. );
  1638. return TRUE;
  1639. }
  1640. BOOL
  1641. SaveAccessibilityOptions (
  1642. IN PCTSTR AnswerFile
  1643. )
  1644. {
  1645. return
  1646. (!AccessibleMagnifier ||
  1647. WritePrivateProfileString (
  1648. TEXT("AccessibilityOptions"),
  1649. TEXT("AccessibleMagnifier"),
  1650. WINNT_A_YES,
  1651. AnswerFile
  1652. )) &&
  1653. (!AccessibleKeyboard ||
  1654. WritePrivateProfileString (
  1655. TEXT("AccessibilityOptions"),
  1656. TEXT("AccessibleKeyboard"),
  1657. WINNT_A_YES,
  1658. AnswerFile
  1659. )) &&
  1660. (!AccessibleVoice ||
  1661. WritePrivateProfileString (
  1662. TEXT("AccessibilityOptions"),
  1663. TEXT("AccessibleVoice"),
  1664. WINNT_A_YES,
  1665. AnswerFile
  1666. )) &&
  1667. (!AccessibleReader ||
  1668. WritePrivateProfileString (
  1669. TEXT("AccessibilityOptions"),
  1670. TEXT("AccessibleReader"),
  1671. WINNT_A_YES,
  1672. AnswerFile
  1673. ));
  1674. }
  1675. BOOL
  1676. LoadAccessibilityOptions (
  1677. IN PCTSTR AnswerFile
  1678. )
  1679. {
  1680. TCHAR buf[MAX_PATH];
  1681. if (!AccessibleMagnifier)
  1682. {
  1683. GetPrivateProfileString (
  1684. TEXT("AccessibilityOptions"),
  1685. TEXT("AccessibleMagnifier"),
  1686. WINNT_A_NO,
  1687. buf,
  1688. MAX_PATH,
  1689. AnswerFile
  1690. );
  1691. AccessibleMagnifier = !lstrcmpi (buf, WINNT_A_YES);
  1692. }
  1693. GetPrivateProfileString (
  1694. TEXT("AccessibilityOptions"),
  1695. TEXT("AccessibleKeyboard"),
  1696. WINNT_A_NO,
  1697. buf,
  1698. MAX_PATH,
  1699. AnswerFile
  1700. );
  1701. AccessibleKeyboard = !lstrcmpi (buf, WINNT_A_YES);
  1702. GetPrivateProfileString (
  1703. TEXT("AccessibilityOptions"),
  1704. TEXT("AccessibleVoice"),
  1705. WINNT_A_NO,
  1706. buf,
  1707. MAX_PATH,
  1708. AnswerFile
  1709. );
  1710. AccessibleVoice = !lstrcmpi (buf, WINNT_A_YES);
  1711. GetPrivateProfileString (
  1712. TEXT("AccessibilityOptions"),
  1713. TEXT("AccessibleReader"),
  1714. WINNT_A_NO,
  1715. buf,
  1716. MAX_PATH,
  1717. AnswerFile
  1718. );
  1719. AccessibleReader = !lstrcmpi (buf, WINNT_A_YES);
  1720. return TRUE;
  1721. }
  1722. BOOL IsFarEastLanguage(DWORD LangIdx)
  1723. {
  1724. BOOL FarEastLang = FALSE;
  1725. DWORD LangGroup;
  1726. LangGroup = (DWORD) _ttol (LocaleList[LangIdx].LanguageGroup1);
  1727. if ((LangGroup >= 7) && (LangGroup <= 10))
  1728. {
  1729. FarEastLang = TRUE;
  1730. }
  1731. else
  1732. {
  1733. if (LocaleList[LangIdx].LanguageGroup2)
  1734. {
  1735. LangGroup = (DWORD) _ttol (LocaleList[LangIdx].LanguageGroup2);
  1736. if ((LangGroup >= 7) && (LangGroup <= 10))
  1737. {
  1738. FarEastLang = TRUE;
  1739. }
  1740. }
  1741. }
  1742. return FarEastLang;
  1743. }
  1744. BOOL SelectFarEastLangGroup (BOOL bSelect)
  1745. {
  1746. DWORD LangIdx;
  1747. for (LangIdx = 0; LangIdx < LanguageGroupsCount; LangIdx++)
  1748. {
  1749. // NOTE: Only FarEast Language should have a directory
  1750. // If this ever changes, this code need to change too.
  1751. if (LanguageGroups[LangIdx].Directory &&
  1752. LanguageGroups[LangIdx].Directory[0] )
  1753. {
  1754. LanguageGroups[LangIdx].Selected = bSelect;
  1755. }
  1756. }
  1757. return TRUE;
  1758. }