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.

1258 lines
32 KiB

  1. //
  2. // ConfOpt.C
  3. //
  4. // Copyright (C) Microsoft, 1994,1995 All Rights Reserved.
  5. //
  6. // History:
  7. // ral 5/23/94 - First pass
  8. // 3/20/95 [stevecat] - NT port & real clean up, unicode, etc.
  9. //
  10. //
  11. #include "priv.h"
  12. #include "appwiz.h"
  13. #define MAX_CFG_FILE_SIZE 20000
  14. #define MAX_DESC_SIZE 100
  15. //
  16. // Return codes for OptSelected
  17. //
  18. #define OPTSEL_YES 0
  19. #define OPTSEL_NO 1
  20. #define OPTSEL_NOTSUPP 2
  21. //
  22. // Define checkbox states for listview
  23. //
  24. #define LVIS_GCNOCHECK 0x1000
  25. #define LVIS_GCCHECK 0x2000
  26. //
  27. // Character definitions
  28. //
  29. #define CR 13
  30. #define LF 10
  31. TCHAR const c_szCRLF[] = {CR, LF, 0};
  32. TCHAR const c_szRegValAutoexec[] = REGSTR_VAL_AUTOEXEC;
  33. TCHAR const c_szRegValConfigSys[] = REGSTR_VAL_CONFIGSYS;
  34. TCHAR const c_szRegDosOptFlags[] = REGSTR_VAL_DOSOPTFLAGS;
  35. TCHAR const c_szRegStandardOpt[] = REGSTR_VAL_STDDOSOPTION;
  36. TCHAR const c_szRegDosOptTip[] = REGSTR_VAL_DOSOPTTIP;
  37. TCHAR const c_szRegDosOptsPath[] = REGSTR_PATH_MSDOSOPTS;
  38. TCHAR const c_szRegGlobalFlags[] = REGSTR_VAL_DOSOPTGLOBALFLAGS;
  39. TCHAR const c_szRegShutdownKey[] = REGSTR_PATH_SHUTDOWN;
  40. TCHAR const c_szForceRebootVal[] = REGSTR_VAL_FORCEREBOOT;
  41. BOOL MustRebootSystem(void)
  42. {
  43. HKEY hk;
  44. BOOL bMustReboot = FALSE;
  45. if (RegOpenKey(HKEY_LOCAL_MACHINE, c_szRegShutdownKey, &hk) == ERROR_SUCCESS)
  46. {
  47. bMustReboot = (RegQueryValueEx(hk, c_szForceRebootVal, NULL,
  48. NULL, NULL, NULL) == ERROR_SUCCESS);
  49. RegCloseKey(hk);
  50. }
  51. return(bMustReboot);
  52. }
  53. DWORD GetMSDOSOptGlobalFlags(LPWIZDATA lpwd)
  54. {
  55. if ((lpwd->dwFlags & WDFLAG_READOPTFLAGS) == 0)
  56. {
  57. HKEY hk;
  58. lpwd->dwFlags |= WDFLAG_READOPTFLAGS;
  59. if (RegOpenKey(HKEY_LOCAL_MACHINE, c_szRegDosOptsPath, &hk)
  60. == ERROR_SUCCESS)
  61. {
  62. UINT cb = sizeof(lpwd->dwDosOptGlobalFlags);
  63. if (RegQueryValueEx(hk, c_szRegGlobalFlags, NULL, NULL,
  64. (LPVOID)(&(lpwd->dwDosOptGlobalFlags)), &cb)
  65. != ERROR_SUCCESS)
  66. {
  67. lpwd->dwDosOptGlobalFlags = 0;
  68. }
  69. RegCloseKey(hk);
  70. }
  71. if (MustRebootSystem())
  72. {
  73. lpwd->dwDosOptGlobalFlags |= DOSOPTGF_DEFCLEAN;
  74. }
  75. }
  76. return(lpwd->dwDosOptGlobalFlags);
  77. }
  78. //
  79. // Structure used to store text for Autoexec.Bat and Config.Sys
  80. //
  81. typedef struct _TEXTDATA {
  82. UINT cb;
  83. LPTSTR lpszData;
  84. } TEXTDATA, FAR * LPTEXTDATA;
  85. //
  86. // Gets a single value from the specified option index. If no data is
  87. // found for the specified value name then a 0 DWORD is stored.
  88. //
  89. void GetOptVal(LPWIZDATA lpwd, int i, LPCTSTR lpszValName, LPVOID lpData, UINT cb)
  90. {
  91. if (RegQueryValueEx(lpwd->DosOpt[i].hk, lpszValName, NULL, NULL, lpData, &cb) != ERROR_SUCCESS)
  92. {
  93. *(LPDWORD)lpData = (DWORD)0;
  94. }
  95. }
  96. BOOL FindDriver(int idFiles, int idLoadHigh, HKEY hk, LPCTSTR lpszRegVal,
  97. LPCTSTR FAR dirs[])
  98. {
  99. TCHAR szFiles[MAX_PATH];
  100. LPTSTR lpszCur, lpszFileName;
  101. TCHAR szCommand[MAX_PATH+20];
  102. LoadAndStrip(idFiles, szFiles, ARRAYSIZE(szFiles));
  103. LoadString(g_hinst, idLoadHigh, szCommand, ARRAYSIZE(szCommand));
  104. lpszFileName = &szCommand[lstrlen(szCommand)];
  105. lpszCur = szFiles;
  106. while (*lpszCur)
  107. {
  108. lstrcpy(lpszFileName, lpszCur);
  109. if (PathResolve(lpszFileName, dirs, PRF_VERIFYEXISTS))
  110. {
  111. PathGetShortPath(lpszFileName);
  112. RegSetValueEx(hk, lpszRegVal, 0, REG_SZ, (LPBYTE) szCommand,
  113. (lstrlen(szCommand)+1)*sizeof(TCHAR));
  114. return(TRUE);
  115. }
  116. lpszCur = SkipStr(lpszCur);
  117. }
  118. return(FALSE);
  119. }
  120. BOOL SetUpMouse(LPWIZDATA lpwd, int i)
  121. {
  122. #define MOpt lpwd->DosOpt[i]
  123. TCHAR szMouseEnv[64];
  124. TCHAR szMouseDir[64];
  125. LPCTSTR FAR dirs[] = {szMouseDir, NULL};
  126. BOOL fRetVal;
  127. if (!LoadString(g_hinst, IDS_MOUSEENV, szMouseEnv, ARRAYSIZE(szMouseEnv)))
  128. {
  129. fRetVal = FALSE;
  130. }
  131. else
  132. {
  133. lstrcpy(szMouseDir, szMouseEnv);
  134. DoEnvironmentSubst(szMouseDir, ARRAYSIZE(szMouseDir));
  135. if (lstrcmp(szMouseDir, szMouseEnv) == 0)
  136. {
  137. dirs[0] = NULL;
  138. }
  139. if (FindDriver(IDS_MOUSETSRS, IDS_LOADHIGH,MOpt.hk, c_szRegValAutoexec, dirs) ||
  140. FindDriver(IDS_MOUSEDRVS, IDS_DEVHIGH, MOpt.hk, c_szRegValConfigSys, dirs))
  141. {
  142. MOpt.dwFlags |= DOSOPTF_SUPPORTED;
  143. TraceMsg(TF_ERROR, "%s", "Found real mode mouse driver");
  144. }
  145. MOpt.dwFlags &= ~DOSOPTF_NEEDSETUP;
  146. RegSetValueEx(MOpt.hk, c_szRegDosOptFlags, 0, REG_DWORD,
  147. (LPBYTE)&(MOpt.dwFlags), sizeof(MOpt.dwFlags));
  148. fRetVal = TRUE;
  149. }
  150. return fRetVal;
  151. #undef MOpt
  152. }
  153. //
  154. // The option is not configured. Here's where to add code to set up any
  155. // standard option. Currently, we only set up the mouse.
  156. //
  157. BOOL SetupOption(LPWIZDATA lpwd, int i)
  158. {
  159. BOOL fRetVal;
  160. if (RMOPT_MOUSE == lpwd->DosOpt[i].dwStdOpt)
  161. {
  162. TraceMsg(TF_ERROR, "%s", "About to search for real mode mouse driver");
  163. fRetVal = SetUpMouse(lpwd, i);
  164. }
  165. else
  166. {
  167. fRetVal = TRUE;
  168. }
  169. return fRetVal;
  170. }
  171. //
  172. // Closes all open hkeys and frees the memory. NOTE: This function can
  173. // be called any time, even if ReadRegInfo has not been called previously.
  174. //
  175. void FreeRegInfo(LPWIZDATA lpwd)
  176. {
  177. int i;
  178. if (!lpwd->DosOpt)
  179. {
  180. return;
  181. }
  182. for (i = 0; i < lpwd->NumOpts; i++)
  183. {
  184. RegCloseKey(lpwd->DosOpt[i].hk);
  185. }
  186. LocalFree(lpwd->DosOpt);
  187. lpwd->DosOpt = NULL;
  188. lpwd->NumOpts = 0;
  189. }
  190. //
  191. // Initializes the option table in the wizard data header.
  192. //
  193. BOOL ReadRegInfo(LPWIZDATA lpwd)
  194. {
  195. HKEY hk;
  196. BOOL bSuccess = FALSE;
  197. int i;
  198. if (lpwd->DosOpt)
  199. {
  200. return(TRUE);
  201. }
  202. if (RegOpenKey(HKEY_LOCAL_MACHINE, c_szRegDosOptsPath, &hk) !=
  203. ERROR_SUCCESS)
  204. {
  205. goto Exit;
  206. }
  207. if (RegQueryInfoKey(hk, NULL, NULL, NULL, &(lpwd->NumOpts),
  208. NULL, NULL, NULL, NULL, NULL, NULL, NULL) !=
  209. ERROR_SUCCESS)
  210. {
  211. goto ExitCloseKey;
  212. }
  213. lpwd->DosOpt = LocalAlloc(LPTR, lpwd->NumOpts * sizeof(DOSOPT));
  214. if (!lpwd->DosOpt)
  215. {
  216. goto ExitCloseKey;
  217. }
  218. for (i = 0; i < lpwd->NumOpts; i++)
  219. {
  220. UINT cb;
  221. TCHAR szOptKey[80];
  222. HKEY hkOpt;
  223. UINT uOrder = 0;
  224. int InsPos;
  225. cb = ARRAYSIZE(szOptKey);
  226. if ((RegEnumKeyEx(hk, i, szOptKey, &cb, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) ||
  227. (RegOpenKey(hk, szOptKey, &hkOpt) != ERROR_SUCCESS))
  228. {
  229. lpwd->NumOpts = i - 1;
  230. FreeRegInfo(lpwd); // This frees the DosOpt memory
  231. goto ExitCloseKey;
  232. }
  233. cb = sizeof(uOrder);
  234. RegQueryValueEx(hkOpt, REGSTR_VAL_OPTORDER, NULL, NULL, (LPVOID)&uOrder, &cb);
  235. for (InsPos = i;
  236. (InsPos > 0) && (lpwd->DosOpt[InsPos-1].uOrder > uOrder);
  237. InsPos--);
  238. if (InsPos < i)
  239. {
  240. MoveMemory(&(lpwd->DosOpt[InsPos+1]), &(lpwd->DosOpt[InsPos]),
  241. (i - InsPos) * sizeof(DOSOPT));
  242. }
  243. lpwd->DosOpt[InsPos].hk = hkOpt;
  244. lpwd->DosOpt[InsPos].uOrder = uOrder;
  245. GetOptVal(lpwd, InsPos, c_szRegDosOptFlags, &(lpwd->DosOpt[InsPos].dwFlags), sizeof(DWORD));
  246. GetOptVal(lpwd, InsPos, c_szRegStandardOpt, &(lpwd->DosOpt[InsPos].dwStdOpt), sizeof(DWORD));
  247. if (lpwd->DosOpt[InsPos].dwFlags & DOSOPTF_NEEDSETUP)
  248. {
  249. if (!SetupOption(lpwd, InsPos))
  250. {
  251. goto ExitCloseKey;
  252. }
  253. }
  254. }
  255. bSuccess = TRUE;
  256. ExitCloseKey:
  257. RegCloseKey(hk);
  258. Exit:
  259. return(bSuccess);
  260. }
  261. //
  262. // Inserts a single column into the specified ListView.
  263. //
  264. void InitSingleColListView(HWND hLV)
  265. {
  266. LV_COLUMN col = {LVCF_FMT | LVCF_WIDTH, LVCFMT_LEFT};
  267. RECT rc;
  268. GetClientRect(hLV, &rc);
  269. col.cx = rc.right - GetSystemMetrics(SM_CXVSCROLL)
  270. - GetSystemMetrics(SM_CXSMICON)
  271. - 2 * GetSystemMetrics(SM_CXEDGE);
  272. ListView_InsertColumn(hLV, 0, &col);
  273. }
  274. //
  275. // Initializes the listview with all available options
  276. //
  277. void ConfOptInit(HWND hDlg, LPPROPSHEETPAGE lpp)
  278. {
  279. HIMAGELIST himlState;
  280. HWND hwndOptions = GetDlgItem(hDlg, IDC_OPTIONLIST);
  281. LPWIZDATA lpwd = InitWizSheet(hDlg, (LPARAM)lpp, 0);
  282. InitSingleColListView(hwndOptions);
  283. //
  284. // Lets load our bitmap as an imagelist
  285. //
  286. himlState = ImageList_LoadImage(g_hinst, MAKEINTRESOURCE(IDB_CHECKSTATES), 0, 2,
  287. CLR_NONE, IMAGE_BITMAP, LR_LOADTRANSPARENT);
  288. ListView_SetImageList(hwndOptions, himlState, LVSIL_STATE);
  289. //
  290. // Find all options for MS-DOS configs and set their approropriate state
  291. // information
  292. //
  293. if (ReadRegInfo(lpwd))
  294. {
  295. int i;
  296. for (i = 0; i < lpwd->NumOpts; i++)
  297. {
  298. DWORD dwFlags = lpwd->DosOpt[i].dwFlags;
  299. if ((dwFlags & DOSOPTF_SUPPORTED) &&
  300. ((dwFlags & DOSOPTF_ALWAYSUSE) == 0) &&
  301. ((dwFlags & DOSOPTF_USESPMODE) == 0 ||
  302. (lpwd->dwFlags & WDFLAG_REALMODEONLY) == 0) &&
  303. (lpwd->DosOpt[i].uOrder > 0))
  304. {
  305. TCHAR szDesc[MAX_DESC_SIZE];
  306. LV_ITEM lvi;
  307. GetOptVal(lpwd, i, NULL, szDesc, sizeof(szDesc));
  308. lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM;
  309. lvi.iItem = 0x7FFF;
  310. lvi.iSubItem = 0;
  311. //
  312. ///// REARCHITECT If program properties contains real mode flags, use them for defaults!
  313. //
  314. lvi.state = (dwFlags & DOSOPTF_DEFAULT) ? LVIS_GCCHECK : LVIS_GCNOCHECK;
  315. lvi.stateMask = LVIS_ALL;
  316. lvi.pszText = szDesc;
  317. lvi.lParam = (LPARAM)i;
  318. lvi.cchTextMax = 0;
  319. ListView_InsertItem(hwndOptions, &lvi);
  320. }
  321. }
  322. }
  323. }
  324. //
  325. // Toggles the state of the specified item in the list view.
  326. //
  327. void ToggleState(HWND hwndLV, int i)
  328. {
  329. UINT state = ListView_GetItemState(hwndLV, i, LVIS_STATEIMAGEMASK);
  330. state = (state == LVIS_GCNOCHECK) ? LVIS_GCCHECK : LVIS_GCNOCHECK;
  331. ListView_SetItemState(hwndLV, i, state, LVIS_STATEIMAGEMASK);
  332. }
  333. //
  334. // Returns the path to the boot directory. If we can't find it in the
  335. // registry then this function returns the default (drive that windows
  336. // directory is on)
  337. //
  338. void GetBootDir(LPTSTR lpszBootDir, int cchBootDir)
  339. {
  340. HKEY hkSetup;
  341. *lpszBootDir = 0;
  342. if (RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_SETUP REGSTR_KEY_SETUP,
  343. &hkSetup) == ERROR_SUCCESS)
  344. {
  345. UINT cb = cchBootDir * SIZEOF(TCHAR);
  346. RegQueryValueEx(hkSetup, REGSTR_VAL_BOOTDIR, NULL,
  347. NULL, (LPBYTE) lpszBootDir, &cb);
  348. RegCloseKey(hkSetup);
  349. }
  350. if (*lpszBootDir == 0)
  351. {
  352. if (0 != GetWindowsDirectory(lpszBootDir, cchBootDir)
  353. && lpszBootDir[0] != TEXT('\0')
  354. && lpszBootDir[1] == TEXT(':')
  355. && lpszBootDir[2] == TEXT('\\'))
  356. {
  357. lpszBootDir[3] = TEXT('\0');
  358. }
  359. else
  360. {
  361. LoadString(g_hinst, IDS_DEFBOOTDIR, lpszBootDir, cchBootDir);
  362. }
  363. }
  364. }
  365. //
  366. // Process the clicks on the listview. do a hittest to see where the user
  367. // clicked. If on one of the state bitmaps, toggle it.
  368. //
  369. void ConfOptClick(HWND hDlg, LPNMHDR pnmhdr)
  370. {
  371. //
  372. // The user clicked on one the listview see where...
  373. //
  374. DWORD dwpos;
  375. LV_HITTESTINFO lvhti;
  376. dwpos = GetMessagePos();
  377. lvhti.pt.x = GET_X_LPARAM(dwpos);
  378. lvhti.pt.y = GET_Y_LPARAM(dwpos);
  379. MapWindowPoints(HWND_DESKTOP, pnmhdr->hwndFrom, &lvhti.pt, 1);
  380. ListView_HitTest(pnmhdr->hwndFrom, &lvhti);
  381. if (lvhti.flags & LVHT_ONITEMSTATEICON)
  382. {
  383. ToggleState(pnmhdr->hwndFrom, lvhti.iItem);
  384. }
  385. }
  386. //
  387. // When the user hits the space bar, toggle the state of the selected item.
  388. //
  389. BOOL ConfOptKeyDown(HWND hDlg, LV_KEYDOWN *plvkd)
  390. {
  391. int iCursor;
  392. if (plvkd->wVKey == VK_SPACE && !(GetAsyncKeyState(VK_MENU) < 0))
  393. {
  394. //
  395. // Lets toggle the cursored item.
  396. //
  397. iCursor = ListView_GetNextItem(plvkd->hdr.hwndFrom, -1, LVNI_FOCUSED);
  398. if (iCursor != -1)
  399. {
  400. ToggleState(plvkd->hdr.hwndFrom, iCursor);
  401. }
  402. return TRUE;
  403. }
  404. return FALSE;
  405. }
  406. //
  407. // Item selection changed. Update tip.
  408. //
  409. void ItemChanged(LPWIZDATA lpwd, LPNM_LISTVIEW lpnmlv)
  410. {
  411. LV_ITEM lvi;
  412. TCHAR szTip[200]; ///???
  413. if ((lpnmlv->uNewState & LVIS_FOCUSED) &&
  414. (!(lpnmlv->uOldState & LVIS_FOCUSED)))
  415. {
  416. lvi.iItem = lpnmlv->iItem;
  417. lvi.iSubItem = 0;
  418. lvi.mask = LVIF_PARAM;
  419. ListView_GetItem(lpnmlv->hdr.hwndFrom, &lvi);
  420. GetOptVal(lpwd, (int)lvi.lParam, c_szRegDosOptTip, szTip, sizeof(szTip));
  421. Static_SetText(GetDlgItem(lpwd->hwnd, IDC_OPTIONTIP), szTip);
  422. }
  423. }
  424. void _inline NoSupportMsg(LPWIZDATA lpwd, int iOpt)
  425. {
  426. LPTSTR lpszDesc = (LPTSTR)LocalAlloc(LMEM_FIXED, MAX_DESC_SIZE*sizeof(TCHAR));
  427. if (lpszDesc)
  428. {
  429. LPTSTR lpszMsg = (LPTSTR)LocalAlloc(LMEM_FIXED, 512*sizeof(TCHAR)); // Max 2 resource size
  430. if (lpszMsg)
  431. {
  432. GetOptVal(lpwd, iOpt, NULL, lpszDesc, MAX_DESC_SIZE*sizeof(TCHAR));
  433. LoadString(g_hinst, IDS_NOSUPPORT1, lpszMsg, 512);
  434. LoadString(g_hinst, IDS_NOSUPPORT2, lpszMsg+lstrlen(lpszMsg), 256);
  435. ShellMessageBox(g_hinst, lpwd->hwnd,
  436. lpszMsg, 0,
  437. MB_OK | MB_ICONEXCLAMATION,
  438. lpszDesc);
  439. LocalFree(lpszMsg);
  440. }
  441. LocalFree(lpszDesc);
  442. }
  443. }
  444. //
  445. // Returns OPTSEL_YES if the option indicated by i is selected in the list
  446. // box, or, if hwndLV is NULL then OPTSEL_YES if option should be added,
  447. // OPTSEL_NO if should not be added, and OPTSEL_NOTSUPP if the option is
  448. // required but can't be added.
  449. //
  450. int OptSelected(LPWIZDATA lpwd, int i, HWND hwndLV)
  451. {
  452. BOOL bSelected = FALSE;
  453. if (lpwd->DosOpt[i].dwFlags & DOSOPTF_ALWAYSUSE)
  454. {
  455. bSelected = TRUE;
  456. }
  457. else
  458. {
  459. if (hwndLV)
  460. {
  461. LV_ITEM lvi;
  462. int NumItems = ListView_GetItemCount(hwndLV);
  463. for (lvi.iItem = 0; lvi.iItem < NumItems; lvi.iItem++)
  464. {
  465. lvi.iSubItem = 0;
  466. lvi.mask = LVIF_PARAM | LVIF_STATE;
  467. lvi.stateMask = LVIS_STATEIMAGEMASK;
  468. ListView_GetItem(hwndLV, &lvi);
  469. if ((int)lvi.lParam == i)
  470. {
  471. bSelected = ((lvi.state & LVIS_STATEIMAGEMASK) == LVIS_GCCHECK);
  472. }
  473. }
  474. }
  475. else
  476. {
  477. BOOL bSupported = lpwd->DosOpt[i].dwFlags & DOSOPTF_SUPPORTED;
  478. if (lpwd->PropPrg.dwRealModeFlags & lpwd->DosOpt[i].dwStdOpt)
  479. {
  480. bSelected = TRUE;
  481. if (!bSupported)
  482. {
  483. NoSupportMsg(lpwd, i);
  484. return(OPTSEL_NOTSUPP);
  485. }
  486. }
  487. else
  488. {
  489. if (bSupported)
  490. {
  491. bSelected = (lpwd->PropPrg.dwRealModeFlags & (lpwd->DosOpt[i].dwStdOpt >> 16));
  492. }
  493. }
  494. }
  495. }
  496. if (bSelected)
  497. {
  498. return(OPTSEL_YES);
  499. }
  500. else
  501. {
  502. return(OPTSEL_NO);
  503. }
  504. }
  505. void AppendStr(LPTEXTDATA lpTD, LPTSTR lpStr)
  506. {
  507. int cb = lstrlen(lpStr)*sizeof(TCHAR);
  508. if ((lpTD->cb + cb + 2) <= MAX_CFG_FILE_SIZE*sizeof(TCHAR))
  509. {
  510. memcpy(lpTD->lpszData+lpTD->cb, lpStr, cb);
  511. lpTD->cb += cb;
  512. }
  513. }
  514. //
  515. // Appends the string+cr/lf to the TextData structure.
  516. //
  517. void AppendLine(LPTEXTDATA lpTD, LPTSTR lpStr)
  518. {
  519. AppendStr(lpTD, lpStr);
  520. AppendStr(lpTD, (LPTSTR)c_szCRLF);
  521. }
  522. //
  523. // Returns NULL if none of the strings in szKeys matches the first entry
  524. // in the specified string.
  525. //
  526. LPTSTR MatchesKey(LPTSTR lpszStr, LPTSTR lpszKeys)
  527. {
  528. UINT cch = lstrlen(lpszStr);
  529. TCHAR szUpLine[20];
  530. LPTSTR lpszCurKey;
  531. if (cch >= ARRAYSIZE(szUpLine))
  532. {
  533. cch = ARRAYSIZE(szUpLine)-1;
  534. }
  535. memcpy(szUpLine, lpszStr, cch*sizeof(TCHAR));
  536. szUpLine[cch] = 0;
  537. CharUpper(szUpLine);
  538. for (lpszCurKey = lpszKeys; *lpszCurKey; lpszCurKey = SkipStr(lpszCurKey))
  539. {
  540. UINT cchKey = lstrlen(lpszCurKey);
  541. if ((cchKey < cch) &&
  542. ((szUpLine[cchKey] == TEXT(' ')) || (szUpLine[cchKey] == TEXT('='))) &&
  543. (memcmp(lpszCurKey, szUpLine, cchKey*sizeof(TCHAR)) == 0))
  544. {
  545. return(lpszCurKey);
  546. }
  547. }
  548. return(NULL);
  549. }
  550. //
  551. // Copy the current environment into Autoexec.Bat
  552. //
  553. void CopyEnvironment(LPTEXTDATA lpAE)
  554. {
  555. TCHAR szKeys[MAX_PATH]; // SIZE?
  556. TCHAR szSetCmd[20];
  557. LPTSTR lpszCur = (LPTSTR)GetEnvironmentStrings();
  558. LoadString(g_hinst, IDS_SETCMD, szSetCmd, ARRAYSIZE(szSetCmd));
  559. LoadAndStrip(IDS_NOCOPYENV, szKeys, ARRAYSIZE(szKeys));
  560. while (*lpszCur)
  561. {
  562. if (!MatchesKey(lpszCur, szKeys))
  563. {
  564. AppendStr(lpAE, szSetCmd);
  565. AppendLine(lpAE, lpszCur);
  566. }
  567. lpszCur = SkipStr(lpszCur);
  568. }
  569. }
  570. //
  571. // Add keyboard type option for JKEYB.SYS
  572. //
  573. void SetJkeybOpt(LPTSTR lpszStr)
  574. {
  575. UINT cb, cbKey;
  576. TCHAR szUpLine[64];
  577. TCHAR lpszKey[] = TEXT("JKEYB.SYS");
  578. TCHAR *lpszOpts[] = {TEXT(" /101"), TEXT(" /AX"), TEXT(" /106"), TEXT(" /J31DT"), TEXT(" /J31NB"), TEXT(" /J31LT")};
  579. int KeybOpt;
  580. int i;
  581. ASSERT(lpszStr);
  582. cb = lstrlen(lpszStr);
  583. cbKey = lstrlen(lpszKey);
  584. if (cb >= ARRAYSIZE(szUpLine))
  585. {
  586. cb = ARRAYSIZE(szUpLine)-1;
  587. }
  588. memcpy(szUpLine, lpszStr, cb*sizeof(TCHAR));
  589. szUpLine[cb] = 0;
  590. // AnsiUpper(szUpLine);
  591. CharUpper(szUpLine);
  592. for (i = 0; cbKey <= cb; i++, cb--)
  593. {
  594. if (memcmp(lpszKey, &szUpLine[i], cbKey*sizeof(TCHAR)) == 0)
  595. {
  596. // if (GetKeyboardType(0) == 7){
  597. // switch(GetKeyboardType(1)) {
  598. if (GetPrivateProfileInt(TEXT("keyboard"), TEXT("type"), 0, TEXT("SYSTEM.INI")) == 7)
  599. {
  600. switch(GetPrivateProfileInt(TEXT("keyboard"), TEXT("subtype"), 0, TEXT("SYSTEM.INI")))
  601. {
  602. case 0:
  603. KeybOpt = 0;
  604. break;
  605. case 1:
  606. KeybOpt = 1;
  607. break;
  608. case 2:
  609. case 3:
  610. case 4:
  611. KeybOpt = 2;
  612. break;
  613. case 13:
  614. KeybOpt = 3;
  615. break;
  616. case 14:
  617. KeybOpt = 4;
  618. break;
  619. case 15:
  620. KeybOpt = 5;
  621. break;
  622. default:
  623. KeybOpt = 0;
  624. break;
  625. }
  626. }
  627. else
  628. KeybOpt = 0;
  629. lstrcat(lpszStr, lpszOpts[KeybOpt]);
  630. break;
  631. }
  632. }
  633. }
  634. //
  635. // Adds an option line from the specified value name to the TEXTDATA structure
  636. //
  637. BOOL AddOption(HKEY hk, LPCTSTR lpszValName, LPTEXTDATA lpTD,
  638. LPTSTR lpszHighCmds, LPTSTR lpszLowCmd, BOOL bCanLoadHigh)
  639. {
  640. TCHAR szOptData[256];
  641. UINT cb = sizeof(szOptData);
  642. DWORD dwType;
  643. LCID lcid = GetThreadLocale();
  644. if (RegQueryValueEx(hk, lpszValName, NULL,
  645. &dwType, (LPBYTE) szOptData, &cb) == ERROR_SUCCESS)
  646. {
  647. LPTSTR lpszAddData = szOptData;
  648. DoEnvironmentSubst(szOptData, ARRAYSIZE(szOptData));
  649. //
  650. // Now remove LH or LoadHigh or DeviceHigh and replace with the
  651. // appropriate string if EMM386 has not loaded yet.
  652. //
  653. if (!bCanLoadHigh)
  654. {
  655. LPTSTR lpszMatch = MatchesKey(szOptData, lpszHighCmds);
  656. if (lpszMatch)
  657. {
  658. int cbHigh = lstrlen(lpszMatch);
  659. if (lpszLowCmd)
  660. {
  661. int cbLow = lstrlen(lpszLowCmd);
  662. lpszAddData += cbHigh - cbLow;
  663. memcpy(lpszAddData, lpszLowCmd, cbLow*sizeof(TCHAR));
  664. }
  665. else
  666. {
  667. lpszAddData += cbHigh + 1;
  668. }
  669. }
  670. }
  671. if (PRIMARYLANGID(LANGIDFROMLCID(lcid))==LANG_JAPANESE)
  672. {
  673. SetJkeybOpt(lpszAddData);
  674. }
  675. AppendLine(lpTD, lpszAddData);
  676. return(TRUE);
  677. }
  678. return(FALSE);
  679. }
  680. //
  681. // Sets the appropriate configuration options in the PIF proprties
  682. // If fForceCleanCfg is TRUE then a clean configuration is created. Otherwise
  683. // the autoexec and config fields are nuked to force the app to use the current
  684. // configuration.
  685. //
  686. PIFWIZERR SetConfOptions(LPWIZDATA lpwd, HWND hwndOptions, BOOL fForceCleanCfg)
  687. {
  688. TEXTDATA AE;
  689. TEXTDATA CS;
  690. int i;
  691. PIFWIZERR err = PIFWIZERR_SUCCESS;
  692. TCHAR szCSHighCmds[100];
  693. TCHAR szCSLowCmd[20];
  694. TCHAR szAEHighCmds[100];
  695. BOOL bCanLoadHigh = FALSE;
  696. //
  697. // Make sure the real mode flag is set in the program properties.
  698. //
  699. PifMgr_GetProperties(lpwd->hProps, (LPSTR)GROUP_PRG, &(lpwd->PropPrg),
  700. sizeof(lpwd->PropPrg), GETPROPS_NONE);
  701. lpwd->PropPrg.flPrgInit |= PRGINIT_REALMODE;
  702. PifMgr_SetProperties(lpwd->hProps, (LPSTR)GROUP_PRG, &(lpwd->PropPrg),
  703. sizeof(lpwd->PropPrg), SETPROPS_NONE);
  704. if (!fForceCleanCfg)
  705. {
  706. TCHAR NullStr = 0;
  707. PifMgr_SetProperties(lpwd->hProps, AUTOEXECHDRSIG40, &NullStr, 0, SETPROPS_NONE);
  708. PifMgr_SetProperties(lpwd->hProps, CONFIGHDRSIG40, &NullStr, 0, SETPROPS_NONE);
  709. return(err);
  710. }
  711. //
  712. // Load strings used to force drivers to load low if no EMM386.
  713. //
  714. LoadString(g_hinst, IDS_CSLOWSTR, szCSLowCmd, ARRAYSIZE(szCSLowCmd));
  715. LoadAndStrip(IDS_CSHIGHSTRS, szCSHighCmds, ARRAYSIZE(szCSHighCmds));
  716. LoadAndStrip(IDS_AEHIGHSTRS, szAEHighCmds, ARRAYSIZE(szAEHighCmds));
  717. //
  718. // Allocate memory for autoexec/config.sys buffers.
  719. //
  720. AE.lpszData = (LPTSTR)LocalAlloc(LPTR, MAX_CFG_FILE_SIZE*sizeof(TCHAR));
  721. if (AE.lpszData == NULL)
  722. {
  723. return(PIFWIZERR_OUTOFMEM);
  724. }
  725. CS.lpszData = (LPTSTR)LocalAlloc(LPTR, MAX_CFG_FILE_SIZE*sizeof(TCHAR));
  726. if (CS.lpszData == NULL)
  727. {
  728. LocalFree(AE.lpszData);
  729. return(PIFWIZERR_OUTOFMEM);
  730. }
  731. AE.cb = CS.cb = 0;
  732. //
  733. // Copy the appropriate goop out of config.sys and autoexec.bat
  734. //
  735. CopyEnvironment(&AE);
  736. for (i = 0; i < lpwd->NumOpts; i++)
  737. {
  738. int OptSel = OptSelected(lpwd, i, hwndOptions);
  739. if (OptSel == OPTSEL_YES)
  740. {
  741. bCanLoadHigh |= (lpwd->DosOpt[i].dwFlags & DOSOPTF_PROVIDESUMB);
  742. AddOption(lpwd->DosOpt[i].hk, c_szRegValAutoexec, &AE,
  743. szAEHighCmds, NULL, bCanLoadHigh);
  744. AddOption(lpwd->DosOpt[i].hk, c_szRegValConfigSys, &CS,
  745. szCSHighCmds, szCSLowCmd, bCanLoadHigh);
  746. //
  747. // DOSOPTF_MULTIPLE will load multiple configuration from
  748. // Config.Sys1 - Config.Sys9 and Autoexec.Bat1 - Autoexec.Bat9
  749. //
  750. if (lpwd->DosOpt[i].dwFlags & DOSOPTF_MULTIPLE)
  751. {
  752. BOOL ret;
  753. TCHAR multicount[2];
  754. TCHAR multiAutoexec[64];
  755. TCHAR multiConfig[64];
  756. lstrcpy(multicount,TEXT("1"));
  757. while (1)
  758. {
  759. lstrcpy(multiAutoexec, c_szRegValAutoexec);
  760. lstrcat(multiAutoexec, multicount);
  761. lstrcpy(multiConfig, c_szRegValConfigSys);
  762. lstrcat(multiConfig, multicount);
  763. ret = AddOption(lpwd->DosOpt[i].hk, multiAutoexec, &AE,
  764. szAEHighCmds, NULL, bCanLoadHigh);
  765. ret |= AddOption(lpwd->DosOpt[i].hk, multiConfig, &CS,
  766. szCSHighCmds, szCSLowCmd, bCanLoadHigh);
  767. if (!ret)
  768. break;
  769. multicount[0] += 1;
  770. if (multicount[0] > TEXT('9'))
  771. break;
  772. }
  773. }
  774. }
  775. else
  776. {
  777. if (OptSel == OPTSEL_NOTSUPP)
  778. {
  779. err = PIFWIZERR_UNSUPPORTEDOPT;
  780. }
  781. }
  782. }
  783. //
  784. // Set the properties in the PIF file
  785. //
  786. PifMgr_SetProperties(lpwd->hProps, AUTOEXECHDRSIG40, AE.lpszData, AE.cb, SETPROPS_NONE);
  787. PifMgr_SetProperties(lpwd->hProps, CONFIGHDRSIG40, CS.lpszData, CS.cb, SETPROPS_NONE);
  788. //
  789. // Clean up allocated memory
  790. //
  791. LocalFree(AE.lpszData);
  792. LocalFree(CS.lpszData);
  793. return(err);
  794. }
  795. //
  796. // The user hit the finish button. Set the proper configuration.
  797. //
  798. PIFWIZERR ConfigRealModeOptions(LPWIZDATA lpwd, HWND hwndOptList,
  799. UINT uAction)
  800. {
  801. PIFWIZERR err = PIFWIZERR_GENERALFAILURE;
  802. BOOL fCleanCfg;
  803. switch(uAction)
  804. {
  805. case CRMOACTION_DEFAULT:
  806. fCleanCfg = GetMSDOSOptGlobalFlags(lpwd) & DOSOPTGF_DEFCLEAN;
  807. break;
  808. case CRMOACTION_CLEAN:
  809. fCleanCfg = TRUE;
  810. break;
  811. case CRMOACTION_CURRENT:
  812. fCleanCfg = FALSE;
  813. break;
  814. }
  815. //
  816. // OK to call twice -- Returns true
  817. //
  818. if (ReadRegInfo(lpwd))
  819. {
  820. if (lpwd->hProps == 0)
  821. {
  822. if (CreateLink(lpwd))
  823. {
  824. TCHAR szLinkName[MAX_PATH];
  825. GetLinkName(szLinkName, lpwd);
  826. lpwd->hProps = PifMgr_OpenProperties(szLinkName, NULL, 0, OPENPROPS_NONE);
  827. if (lpwd->hProps)
  828. {
  829. err = SetConfOptions(lpwd, hwndOptList, fCleanCfg);
  830. PifMgr_CloseProperties(lpwd->hProps, CLOSEPROPS_NONE);
  831. lpwd->hProps = 0;
  832. }
  833. }
  834. }
  835. else
  836. {
  837. err = SetConfOptions(lpwd, hwndOptList, fCleanCfg);
  838. }
  839. FreeRegInfo(lpwd);
  840. }
  841. return(err);
  842. }
  843. BOOL_PTR CALLBACK ConfigOptionsDlgProc(HWND hDlg, UINT message , WPARAM wParam, LPARAM lParam)
  844. {
  845. LPNMHDR lpnm = NULL;
  846. LPPROPSHEETPAGE lpp = (LPPROPSHEETPAGE)(GetWindowLongPtr(hDlg, DWLP_USER));
  847. LPWIZDATA lpwd = lpp ? (LPWIZDATA)lpp->lParam : NULL;
  848. switch(message)
  849. {
  850. case WM_NOTIFY:
  851. lpnm = (LPNMHDR)lParam;
  852. if(lpnm)
  853. {
  854. switch(lpnm->code)
  855. {
  856. case LVN_ITEMCHANGED:
  857. if(lpwd)
  858. {
  859. ItemChanged(lpwd, (LPNM_LISTVIEW)lParam);
  860. }
  861. break;
  862. case NM_CLICK:
  863. case NM_DBLCLK:
  864. ConfOptClick(hDlg, lpnm);
  865. break;
  866. case LVN_KEYDOWN:
  867. SetDlgMsgResult(hDlg, WM_NOTIFY,
  868. ConfOptKeyDown(hDlg, (LV_KEYDOWN *)lParam));
  869. break;
  870. case PSN_SETACTIVE:
  871. if(lpwd)
  872. {
  873. lpwd->hwnd = hDlg;
  874. if (lpwd->dwFlags & WDFLAG_PIFPROP)
  875. {
  876. TCHAR szOK[20];
  877. LoadString(g_hinst, IDS_OK, szOK, ARRAYSIZE(szOK));
  878. PropSheet_SetFinishText(GetParent(hDlg), szOK);
  879. }
  880. else
  881. {
  882. PropSheet_SetWizButtons(GetParent(hDlg),
  883. PSWIZB_FINISH | PSWIZB_BACK);
  884. }
  885. }
  886. break;
  887. case PSN_WIZFINISH:
  888. if(lpwd)
  889. {
  890. ConfigRealModeOptions(lpwd, GetDlgItem(hDlg, IDC_OPTIONLIST),
  891. CRMOACTION_CLEAN);
  892. }
  893. break;
  894. case PSN_RESET:
  895. if(lpwd)
  896. {
  897. CleanUpWizData(lpwd);
  898. }
  899. break;
  900. default:
  901. return FALSE;
  902. }
  903. }
  904. break;
  905. case WM_INITDIALOG:
  906. ConfOptInit(hDlg, (LPPROPSHEETPAGE)lParam);
  907. break;
  908. default:
  909. return FALSE;
  910. } // end of switch on message
  911. return TRUE;
  912. }
  913. ///////////////////////////////////////////////////////////////////////////////
  914. void WhichConfInit(HWND hDlg, LPPROPSHEETPAGE lpp)
  915. {
  916. LPWIZDATA lpwd = InitWizSheet(hDlg, (LPARAM)lpp, 0);
  917. CheckRadioButton(hDlg, IDB_CURCFG, IDB_CLEANCFG,
  918. GetMSDOSOptGlobalFlags(lpwd) & DOSOPTGF_DEFCLEAN ?
  919. IDB_CLEANCFG : IDB_CURCFG);
  920. }
  921. void SetChoiceWizBtns(LPWIZDATA lpwd)
  922. {
  923. PropSheet_SetWizButtons(GetParent(lpwd->hwnd),
  924. IsDlgButtonChecked(lpwd->hwnd, IDB_CLEANCFG) ?
  925. PSWIZB_NEXT | PSWIZB_BACK :
  926. PSWIZB_FINISH | PSWIZB_BACK);
  927. }
  928. BOOL_PTR CALLBACK PickConfigDlgProc(HWND hDlg, UINT message , WPARAM wParam, LPARAM lParam)
  929. {
  930. LPNMHDR lpnm = NULL;
  931. LPPROPSHEETPAGE lpp = (LPPROPSHEETPAGE)(GetWindowLongPtr(hDlg, DWLP_USER));
  932. LPWIZDATA lpwd = lpp ? (LPWIZDATA)lpp->lParam : NULL;
  933. switch(message)
  934. {
  935. case WM_NOTIFY:
  936. lpnm = (LPNMHDR)lParam;
  937. if(lpnm)
  938. {
  939. switch(lpnm->code)
  940. {
  941. case PSN_SETACTIVE:
  942. if(lpwd)
  943. {
  944. lpwd->hwnd = hDlg;
  945. if (MustRebootSystem())
  946. {
  947. SetDlgMsgResult(hDlg, WM_NOTIFY, -1);
  948. }
  949. else
  950. {
  951. SetChoiceWizBtns(lpwd);
  952. }
  953. }
  954. break;
  955. case PSN_WIZFINISH:
  956. if(lpwd)
  957. {
  958. ConfigRealModeOptions(lpwd, GetDlgItem(hDlg, IDC_OPTIONLIST),
  959. CRMOACTION_CURRENT);
  960. }
  961. break;
  962. case PSN_RESET:
  963. if(lpwd)
  964. {
  965. CleanUpWizData(lpwd);
  966. }
  967. break;
  968. default:
  969. return FALSE;
  970. }
  971. }
  972. break;
  973. case WM_COMMAND:
  974. switch (GET_WM_COMMAND_ID(wParam, lParam))
  975. {
  976. case IDB_CURCFG:
  977. case IDB_CLEANCFG:
  978. if(lpwd)
  979. {
  980. SetChoiceWizBtns(lpwd);
  981. }
  982. }
  983. break;
  984. case WM_INITDIALOG:
  985. WhichConfInit(hDlg, (LPPROPSHEETPAGE)lParam);
  986. break;
  987. default:
  988. return FALSE;
  989. } // end of switch on message
  990. return TRUE;
  991. }