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.

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