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.

672 lines
24 KiB

  1. // Created 07-Jan-1993 11:20am by Jeff Parsons
  2. #include "shellprv.h"
  3. #pragma hdrstop
  4. #include <setupapi.h>
  5. #ifdef _X86_
  6. const TCHAR szRegKeyMSDOSApps[] = REGSTR_PATH_NEWDOSBOX;
  7. const TCHAR szParams[] = KEY_PARAMS;
  8. const TCHAR szBatchFile[] = KEY_BATCHFILE;
  9. const TCHAR szLowMem[] = KEY_LOWMEM;
  10. const TCHAR szEmsMem[] = KEY_EMSMEM;
  11. const TCHAR szXmsMem[] = KEY_XMSMEM;
  12. const TCHAR szDpmiMem[] = KEY_DPMIMEM;
  13. const TCHAR szEnable[] = KEY_ENABLE;
  14. const TCHAR szDisable[] = KEY_DISABLE;
  15. const TCHAR szWindowed[] = KEYVAL_WINDOWED;
  16. const TCHAR szBackground[] = KEYVAL_BACKGROUND;
  17. const TCHAR szExclusive[] = KEYVAL_EXCLUSIVE;
  18. const TCHAR szDetectIdle[] = KEYVAL_DETECTIDLE;
  19. const TCHAR szLowLocked[] = KEYVAL_LOWLOCKED;
  20. const TCHAR szEMSLocked[] = KEYVAL_EMSLOCKED;
  21. const TCHAR szXMSLocked[] = KEYVAL_XMSLOCKED;
  22. const TCHAR szUseHMA[] = KEYVAL_USEHMA;
  23. const TCHAR szEmulateROM[] = KEYVAL_EMULATEROM;
  24. const TCHAR szRetainVRAM[] = KEYVAL_RETAINVRAM;
  25. const TCHAR szFastPaste[] = KEYVAL_FASTPASTE;
  26. const TCHAR szALTTAB[] = KEYVAL_ALTTAB;
  27. const TCHAR szALTESC[] = KEYVAL_ALTESC;
  28. const TCHAR szCTRLESC[] = KEYVAL_CTRLESC;
  29. const TCHAR szPRTSCRN[] = KEYVAL_PRTSCRN;
  30. const TCHAR szALTPRTSCRN[] = KEYVAL_ALTPRTSCRN;
  31. const TCHAR szALTSPACE[] = KEYVAL_ALTSPACE;
  32. const TCHAR szALTENTER[] = KEYVAL_ALTENTER;
  33. const TCHAR szWinLie[] = KEYVAL_WINLIE;
  34. const TCHAR szGlobalMem[] = KEYVAL_GLOBALMEM;
  35. const TCHAR szRealMode[] = KEYVAL_REALMODE;
  36. const TCHAR szMouse[] = KEYVAL_MOUSE;
  37. const TCHAR szEMS[] = KEYVAL_EMS;
  38. const TCHAR szCDROM[] = KEYVAL_CDROM;
  39. const TCHAR szNetwork[] = KEYVAL_NETWORK;
  40. const TCHAR szDiskLock[] = KEYVAL_DISKLOCK;
  41. const TCHAR szPrivateCFG[] = KEYVAL_PRIVATECFG;
  42. const TCHAR szCloseOnExit[] = KEYVAL_CLOSEONEXIT;
  43. const TCHAR szAllowSSaver[] = KEYVAL_ALLOWSSAVER;
  44. const TCHAR szUniqueSettings[] = KEYVAL_UNIQUESETTINGS;
  45. const LPCTSTR apszKey[] = {
  46. szParams,
  47. szBatchFile,
  48. szLowMem,
  49. szEmsMem,
  50. szXmsMem,
  51. szDpmiMem,
  52. szEnable,
  53. szDisable,
  54. };
  55. const LPCTSTR apszKeyVal[] = {
  56. szWindowed, // abKeyValIDBits[0]
  57. szBackground, // abKeyValIDBits[1]
  58. szExclusive, // abKeyValIDBits[2]
  59. szDetectIdle, // abKeyValIDBits[3]
  60. szLowLocked, // abKeyValIDBits[4]
  61. szEMSLocked, // abKeyValIDBits[5]
  62. szXMSLocked, // abKeyValIDBits[6]
  63. szUseHMA, // abKeyValIDBits[7]
  64. szEmulateROM, // abKeyValIDBits[8]
  65. szRetainVRAM, // abKeyValIDBits[9]
  66. szFastPaste, // abKeyValIDBits[10]
  67. szALTTAB, // abKeyValIDBits[11]
  68. szALTESC, // abKeyValIDBits[12]
  69. szCTRLESC, // abKeyValIDBits[13]
  70. szPRTSCRN, // abKeyValIDBits[14]
  71. szALTPRTSCRN, // abKeyValIDBits[15]
  72. szALTSPACE, // abKeyValIDBits[16]
  73. szALTENTER, // abKeyValIDBits[17]
  74. szWinLie, // abKeyValIDBits[18]
  75. szGlobalMem, // abKeyValIDBits[19]
  76. szRealMode, // abKeyValIDBits[20]
  77. szMouse, // abRMKeyValIDBits[0]
  78. szEMS, // abRMKeyValIDBits[1]
  79. szCDROM, // abRMKeyValIDBits[2]
  80. szNetwork, // abRMKeyValIDBits[3]
  81. szDiskLock, // abRMKeyValIDBits[4]
  82. szPrivateCFG, // abRMKeyValIDBits[5]
  83. szCloseOnExit, // special case 0 (see "special case 0" below)
  84. szAllowSSaver, // special case 1 (see "special case 1" below)
  85. szUniqueSettings, // Never transferred to PIF - Used to populate registry
  86. };
  87. // Array of bit numbers that must be kept in sync with KEYVALIDs
  88. //
  89. // 0x80 means bit must be inverted
  90. // 0x40 means bit must be set in PfW386Flags2 instead of PfW386Flags
  91. const BYTE abKeyValIDBits[] = {
  92. BITNUM(fFullScreen) | 0x80,
  93. BITNUM(fBackground),
  94. BITNUM(fExclusive),
  95. BITNUM(fPollingDetect),
  96. BITNUM(fVMLocked),
  97. BITNUM(fEMSLocked),
  98. BITNUM(fXMSLocked),
  99. BITNUM(fNoHMA) | 0x80,
  100. BITNUM(fVidTxtEmulate) | 0x40,
  101. BITNUM(fVidRetainAllo) | 0x40,
  102. BITNUM(fINT16Paste),
  103. BITNUM(fALTTABdis) | 0x80,
  104. BITNUM(fALTESCdis) | 0x80,
  105. BITNUM(fCTRLESCdis) | 0x80,
  106. BITNUM(fPRTSCdis) | 0x80,
  107. BITNUM(fALTPRTSCdis) | 0x80,
  108. BITNUM(fALTSPACEdis) | 0x80,
  109. BITNUM(fALTENTERdis) | 0x80,
  110. BITNUM(fWinLie),
  111. BITNUM(fGlobalProtect),
  112. BITNUM(fRealMode),
  113. };
  114. const BYTE abRMKeyValIDBits[] = {
  115. BITNUM(RMOPT_MOUSE),
  116. BITNUM(RMOPT_EMS),
  117. BITNUM(RMOPT_CDROM),
  118. BITNUM(RMOPT_NETWORK),
  119. BITNUM(RMOPT_DISKLOCK),
  120. BITNUM(RMOPT_PRIVATECFG),
  121. BITNUM(RMOPT_VESA),
  122. };
  123. // FEATURE: other bits to be supported (maybe):
  124. // WIN_TOOLBAR,
  125. // WIN_SAVESETTINGS,
  126. // MSE_WINDOWENABLE | 0x80,
  127. // MSE_EXCLUSIVE,
  128. // TSK_NOWARNTERMINATE | 0x80,
  129. void InitWorkDir(PPROPLINK ppl, LPPROPPRG lpPrg, LPPROPNT40 lpnt40)
  130. {
  131. int i;
  132. if (lpnt40)
  133. {
  134. lstrcpyn((LPTSTR)lpnt40->awchWorkDir,
  135. ppl->szPathName,
  136. min(ARRAYSIZE(lpnt40->awchWorkDir),ppl->iFileName+1));
  137. // Working directories like C:\ are ok, but C:\FOO\ are not,
  138. // so remove trailing '\' in that case
  139. i = lstrlen((LPTSTR)lpnt40->awchWorkDir)-1;
  140. if (i > 2 && lpnt40->awchWorkDir[i] == TEXT('\\'))
  141. lpnt40->awchWorkDir[i] = TEXT('\0');
  142. WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lpnt40->awchWorkDir, -1, lpPrg->achWorkDir, ARRAYSIZE(lpPrg->achWorkDir), NULL, NULL );
  143. }
  144. else
  145. {
  146. WideCharToMultiByte( CP_ACP, 0,
  147. ppl->szPathName,
  148. min(ARRAYSIZE(lpPrg->achWorkDir),ppl->iFileName+1),
  149. (LPSTR)lpPrg->achWorkDir,
  150. ARRAYSIZE(lpPrg->achWorkDir),
  151. NULL,
  152. NULL
  153. );
  154. // Working directories like C:\ are ok, but C:\FOO\ are not,
  155. // so remove trailing '\' in that case
  156. i = lstrlenA(lpPrg->achWorkDir)-1;
  157. if (i > 2 && lpPrg->achWorkDir[i] == '\\')
  158. lpPrg->achWorkDir[i] = '\0';
  159. }
  160. }
  161. BOOL FAR GetAppsInfData(PPROPLINK ppl, LPPROPPRG lpPrg, LPPROPNT40 lpnt40, HINF hInf, LPCTSTR lpszApp, BOOL fNotAmbiguous, int flOpt)
  162. {
  163. HINF hinfApps;
  164. int id, i;
  165. TCHAR szTmp[MAX_PATH];
  166. TCHAR szPIFSection[MAX_KEY_SIZE];
  167. BOOL fSuccess = FALSE;
  168. INFCONTEXT InfContext;
  169. DWORD dwSize;
  170. FunctionName(GetAppsInfData);
  171. //
  172. // Although not strictly part of INF processing, it's most
  173. // convenient here to search for any ICO file that might exist
  174. // in the same directory as the app, and select it for our default icon.
  175. //
  176. lstrcpyn(szTmp, ppl->szPathName, ppl->iFileExt+1);
  177. lstrcpy(szTmp + ppl->iFileExt, TEXT(".ICO"));
  178. if ((int)GetFileAttributes(szTmp) != -1) {
  179. StringCchCopy((LPTSTR)lpnt40->awchIconFile, ARRAYSIZE(lpnt40->awchIconFile), szTmp);
  180. WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lpnt40->awchIconFile, -1, lpPrg->achIconFile, ARRAYSIZE(lpPrg->achIconFile), NULL, NULL );
  181. lpPrg->wIconIndex = 0;
  182. PifMgr_SetProperties(ppl, MAKELP(0,GROUP_PRG),
  183. lpPrg, SIZEOF(*lpPrg), SETPROPS_CACHE);
  184. PifMgr_SetProperties(ppl, MAKELP(0,GROUP_NT40),
  185. lpnt40, SIZEOF(*lpnt40), SETPROPS_CACHE);
  186. }
  187. if (hInf)
  188. hinfApps = hInf;
  189. else
  190. hinfApps = SetupOpenInfFileW(LoadStringSafe(NULL,
  191. IDS_APPSINF,
  192. szTmp,
  193. ARRAYSIZE(szTmp)),
  194. 0, INF_STYLE_WIN4, NULL );
  195. if (hinfApps==INVALID_HANDLE_VALUE) {
  196. id = IDS_CANTOPENAPPSINF;
  197. if (GetLastError()==ERROR_FILE_NOT_FOUND)
  198. id = IDS_NOAPPSINF;
  199. Warning((HWND)ppl, (WORD)id, MB_ICONEXCLAMATION | MB_OK | MB_NOFOCUS);
  200. goto CloseDLL;
  201. }
  202. // OK, now we have APPS.INF open, so let's bounce around the [pif95]
  203. // section and try to find the app of interest.
  204. if (!SetupFindFirstLine(hinfApps, TEXT("pif95"), NULL, &InfContext)) {
  205. Warning((HWND)ppl, IDS_APPSINFERROR, MB_ICONEXCLAMATION | MB_OK | MB_NOFOCUS);
  206. goto CloseInf;
  207. }
  208. // OK, we've found the [pif95] section, so let's go to it
  209. do {
  210. if (!SetupGetStringFieldW(&InfContext, APPSINF_FILENAME, szTmp, ARRAYSIZE(szTmp), &dwSize))
  211. continue;
  212. // We need to read the rest of the fields now, before we do any
  213. // more processing, because otherwise we lose our place in the file
  214. if (lstrcmpi(szTmp, ppl->szPathName+ppl->iFileName) == 0) {
  215. // See if Other File was specified, and then make sure it
  216. // exists. If it doesn't, then we need to continue the search.
  217. // Initialize szTmp with only the path portion of the app's
  218. // fully-qualified name. Giving lstrcpyn a length of iFileName+1
  219. // insures that szTmp[ppl->iFileName] will be NULL.
  220. lstrcpyn(szTmp, ppl->szPathName, ppl->iFileName+1);
  221. SetupGetStringFieldW(&InfContext, APPSINF_OTHERFILE,
  222. &szTmp[ppl->iFileName], ARRAYSIZE(lpPrg->achOtherFile), &dwSize);
  223. // If szTmp[ppl->iFileName] is no longer NULL, then
  224. // GetStringField filled it in. See if the file exists.
  225. if (szTmp[ppl->iFileName]) {
  226. if ((int)GetFileAttributes(szTmp) == -1)
  227. continue; // Other File didn't exist, continue search
  228. }
  229. // If the PIF data we have is ambiguous, and it has already
  230. // been initialized with data from this APPS.INF entry, then just
  231. // leave the PIF data alone and LEAVE.
  232. if (lpPrg->flPrgInit & PRGINIT_AMBIGUOUSPIF) {
  233. if (lstrcmpi((LPWSTR)lpnt40->awchOtherFile, szTmp+ppl->iFileName) == 0) {
  234. if (!szTmp[ppl->iFileName]) {
  235. // The comparison was inconclusive; both filenames
  236. // are blank. See if the filename contained in
  237. // lpPrg->achCmdLine matches lpszApp; if not, again
  238. // we should fail the search.
  239. //
  240. // It's ok to whack lpPrg->achCmdLine with a null;
  241. // OpenProperties (our only caller) doesn't depend on
  242. // that data in lpPrg.
  243. lpnt40->awchCmdLine[lstrskipfnameA(lpPrg->achCmdLine)] = L'\0';
  244. if (lstrcmpi((LPWSTR)lpnt40->awchCmdLine, lpszApp) != 0)
  245. goto CloseInf; // unsuccessful search
  246. }
  247. fSuccess++; // successful search
  248. }
  249. // Otherwise, this APPS.INF entry isn't a match, implying
  250. // some of the PIF's settings don't really apply. We need
  251. // to fail this search, get back to OpenProperties, look ONLY
  252. // for _DEFAULT.PIF, and let it try to call GetAppsInfData
  253. // one more time.
  254. goto CloseInf;
  255. }
  256. // Otherwise, update Other File. THIS is the APPS.INF entry
  257. // we're going to use!
  258. StringCchCopy((LPWSTR)lpnt40->awchOtherFile, ARRAYSIZE(lpnt40->awchOtherFile), szTmp + ppl->iFileName);
  259. WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lpnt40->awchOtherFile, -1, lpPrg->achOtherFile, ARRAYSIZE( lpPrg->achOtherFile ), NULL, NULL );
  260. SetupGetStringFieldW(&InfContext, APPSINF_TITLE, (LPWSTR)lpnt40->awchTitle, ARRAYSIZE(lpnt40->awchTitle), &dwSize);
  261. WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lpnt40->awchTitle, -1, lpPrg->achTitle, ARRAYSIZE( lpPrg->achTitle ), NULL, NULL );
  262. StringCchCopy((LPWSTR)lpnt40->awchCmdLine, ARRAYSIZE(lpnt40->awchCmdLine), lpszApp);
  263. WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lpnt40->awchCmdLine, -1, lpPrg->achCmdLine, ARRAYSIZE( lpPrg->achCmdLine ), NULL, NULL );
  264. i = 0;
  265. SetupGetIntField(&InfContext, APPSINF_NOWORKDIR, &i);
  266. // Only set the working directory if "NoWorkDir" in the INF
  267. // is FALSE and no working directory was supplied by the caller.
  268. if (i == 0 && !lpnt40->awchWorkDir[0]) {
  269. // No hard-coded working directory, so let's provide one
  270. InitWorkDir(ppl, lpPrg, lpnt40);
  271. }
  272. szTmp[0] = 0;
  273. SetupGetStringFieldW(&InfContext, APPSINF_ICONFILE, szTmp, ARRAYSIZE(szTmp), &dwSize);
  274. if (!szTmp[0])
  275. StringCchCopy(szTmp, ARRAYSIZE(szTmp), TEXT("SHELL32.DLL"));
  276. i = 0;
  277. SetupGetIntField(&InfContext, APPSINF_ICONINDEX, &i);
  278. // Update the icon info now, if it's valid
  279. if (i != 0) {
  280. StringCchCopy((LPWSTR)lpnt40->awchIconFile, ARRAYSIZE(lpnt40->awchIconFile), szTmp);
  281. WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lpnt40->awchIconFile, -1, lpPrg->achIconFile, ARRAYSIZE( lpPrg->achIconFile ), NULL, NULL );
  282. lpPrg->wIconIndex = (WORD) i;
  283. }
  284. SetupGetStringFieldW(&InfContext, APPSINF_SECTIONID,
  285. szPIFSection, ARRAYSIZE(szPIFSection), &dwSize);
  286. szTmp[0] = TEXT('\0');
  287. SetupGetStringFieldW(&InfContext, APPSINF_NOPIF,
  288. szTmp, ARRAYSIZE(szTmp), &dwSize);
  289. // This code used to set INHBITPIF if the app was NOT on a
  290. // fixed disk, knowing that we would otherwise try to create
  291. // a PIF in the PIF directory instead of the app's directory;
  292. // in other words, NOPIF really meant "no PIF in the PIF
  293. // directory please, because this app is ambiguously named".
  294. // Now, we want to always allow PIF creation, so the user
  295. // always has a place to save properties for an app. But we
  296. // also need to propagate the old NOPIF flag to AMBIGUOUSPIF,
  297. // so that we'll always check to see if the PIF should be
  298. // regenerated (based on the presence of a NEW Other File).
  299. lpPrg->flPrgInit &= ~PRGINIT_AMBIGUOUSPIF;
  300. if (!fNotAmbiguous && szTmp[0] == TEXT('1'))
  301. lpPrg->flPrgInit |= PRGINIT_AMBIGUOUSPIF;
  302. if (flOpt & OPENPROPS_FORCEREALMODE)
  303. lpPrg->flPrgInit |= PRGINIT_REALMODE;
  304. // Time to dirty those properties!
  305. PifMgr_SetProperties(ppl, MAKELP(0,GROUP_PRG),
  306. lpPrg, SIZEOF(*lpPrg), SETPROPS_CACHE);
  307. PifMgr_SetProperties(ppl, MAKELP(0,GROUP_NT40),
  308. lpnt40, SIZEOF(*lpnt40), SETPROPS_CACHE);
  309. GetAppsInfSectionData(&InfContext, APPSINF_DEFAULT_SECTION, ppl);
  310. if (*szPIFSection)
  311. GetAppsInfSectionData(&InfContext, szPIFSection, ppl);
  312. // Make a note that we found INF settings (appwiz cares)
  313. ppl->flProp |= PROP_INFSETTINGS;
  314. // GetAppsInfSectionData affects program props, so get fresh copy
  315. PifMgr_GetProperties(ppl, MAKELP(0,GROUP_PRG),
  316. lpPrg, SIZEOF(*lpPrg), GETPROPS_NONE);
  317. // Now call appwiz in "silent configuration mode", to create the
  318. // per-app config and autoexec images, if app runs in real mode;
  319. // BUT don't do this if the caller (NOT the INF) specified no PIF,
  320. // to avoid unwanted dialog boxes popping up from appwiz. Yes, I'm
  321. // telling appwiz to be quiet, but sometimes he just can't contain
  322. // himself (ie, silent configuration may not be possible given the
  323. // the real-mode configuration required).
  324. if (!(ppl->flProp & PROP_INHIBITPIF)) {
  325. if (lpPrg->flPrgInit & PRGINIT_REALMODE)
  326. AppWizard(NULL, ppl, WIZACTION_SILENTCONFIGPROP);
  327. }
  328. FlushPIFData(ppl, FALSE);
  329. fSuccess++; // successful search
  330. goto CloseInf;
  331. }
  332. } while (SetupFindNextLine(&InfContext, &InfContext));
  333. CloseInf:
  334. if (!hInf)
  335. SetupCloseInfFile(hinfApps);
  336. CloseDLL:
  337. return fSuccess;
  338. }
  339. void GetAppsInfSectionData(PINFCONTEXT pInfContext, LPCTSTR lpszSection, PPROPLINK ppl)
  340. {
  341. int i, j, idKey;
  342. LPSTDPIF lpstd;
  343. LPW386PIF30 lp386;
  344. LPWENHPIF40 lpenh;
  345. TCHAR szVal[MAX_KEYVAL_SIZE];
  346. TCHAR szVal2[MAX_KEYVAL_SIZE];
  347. FunctionName(GetAppsInfSectionData);
  348. if (!SetupFindFirstLineW(pInfContext, lpszSection, NULL, NULL))
  349. return;
  350. ppl->cLocks++;
  351. lpstd = (LPSTDPIF)ppl->lpPIFData;
  352. // lp386 may or may not exist, but we'll create if not
  353. lp386 = GetGroupData(ppl, szW386HDRSIG30, NULL, NULL);
  354. if (!lp386) {
  355. if (AddGroupData(ppl, szW386HDRSIG30, NULL, SIZEOF(W386PIF30))) {
  356. lp386 = GetGroupData(ppl, szW386HDRSIG30, NULL, NULL);
  357. if (!lp386)
  358. goto UnlockPIF;
  359. }
  360. }
  361. // lpenh may or may not exist, but we'll create if not
  362. lpenh = GetGroupData(ppl, szWENHHDRSIG40, NULL, NULL);
  363. if (!lpenh) {
  364. if (AddGroupData(ppl, szWENHHDRSIG40, NULL, SIZEOF(WENHPIF40))) {
  365. lpenh = GetGroupData(ppl, szWENHHDRSIG40, NULL, NULL);
  366. if (!lpenh)
  367. goto UnlockPIF;
  368. }
  369. }
  370. do {
  371. BYTE bInvert;
  372. DWORD dwSize;
  373. idKey = GetKeyID(pInfContext);
  374. if (!SetupGetStringFieldW(pInfContext, APPSINF_KEYVAL, szVal, ARRAYSIZE(szVal), &dwSize))
  375. continue;
  376. szVal2[0] = TEXT('\0');
  377. if (idKey >= KEYID_LOWMEM && idKey <= KEYID_DPMIMEM)
  378. SetupGetStringFieldW(pInfContext, APPSINF_KEYVAL2, szVal2, ARRAYSIZE(szVal2), &dwSize);
  379. bInvert = 0;
  380. switch (idKey)
  381. {
  382. case KEYID_UNKNOWN:
  383. ASSERTFAIL();
  384. break;
  385. case KEYID_NONE:
  386. break;
  387. case KEYID_PARAMS:
  388. {
  389. WCHAR szTmp[ ARRAYSIZE(lp386->PfW386params) ];
  390. MultiByteToWideChar( CP_ACP, 0, (LPSTR)lp386->PfW386params, -1, szTmp, ARRAYSIZE(szTmp) );
  391. SetupGetStringFieldW(pInfContext, APPSINF_KEYVAL, szTmp, SIZEOF(lp386->PfW386params), &dwSize);
  392. }
  393. break;
  394. case KEYID_BATCHFILE:
  395. break;
  396. case KEYID_LOWMEM:
  397. if (!lstrcmpi(szVal, g_szAuto))
  398. lp386->PfW386minmem = 0xFFFF;
  399. else
  400. lp386->PfW386minmem = (WORD) StrToInt(szVal);
  401. if (!szVal2[0])
  402. lp386->PfW386maxmem = 0xFFFF;
  403. else
  404. lp386->PfW386maxmem = (WORD) StrToInt(szVal2);
  405. break;
  406. case KEYID_EMSMEM:
  407. if (!lstrcmpi(szVal, g_szNone)) {
  408. lp386->PfMaxEMMK = lp386->PfMinEMMK = 0;
  409. }
  410. if (!lstrcmpi(szVal, g_szAuto)) {
  411. lp386->PfMinEMMK = 0;
  412. lp386->PfMaxEMMK = 0xFFFF;
  413. }
  414. else
  415. lp386->PfMaxEMMK = lp386->PfMinEMMK = (WORD) StrToInt(szVal);
  416. if (szVal2[0])
  417. lp386->PfMaxEMMK = (WORD) StrToInt(szVal2);
  418. break;
  419. case KEYID_XMSMEM:
  420. if (!lstrcmpi(szVal, g_szNone)) {
  421. lp386->PfMaxXmsK = lp386->PfMinXmsK = 0;
  422. }
  423. if (!lstrcmpi(szVal, g_szAuto)) {
  424. lp386->PfMinXmsK = 0;
  425. lp386->PfMaxXmsK = 0xFFFF;
  426. }
  427. else
  428. lp386->PfMaxXmsK = lp386->PfMinXmsK = (WORD) StrToInt(szVal);
  429. if (szVal2[0])
  430. lp386->PfMaxXmsK = (WORD) StrToInt(szVal2);
  431. break;
  432. case KEYID_DPMIMEM:
  433. if (!lstrcmpi(szVal, g_szAuto))
  434. lpenh->envProp.wMaxDPMI = 0;
  435. else
  436. lpenh->envProp.wMaxDPMI = (WORD) StrToInt(szVal);
  437. break;
  438. case KEYID_DISABLE:
  439. bInvert = 0x80;
  440. // fall into KEYID_ENABLE...
  441. case KEYID_ENABLE:
  442. for (i=1; 0 != (j = GetKeyValID(pInfContext, i)); i++)
  443. {
  444. int s;
  445. BYTE b;
  446. if (j == KEYVAL_ID_UNKNOWN) {
  447. ASSERTFAIL();
  448. continue;
  449. }
  450. if (j == KEYVAL_ID_UNIQUESETTINGS) {
  451. continue;
  452. }
  453. j--;
  454. if (j < ARRAYSIZE(abKeyValIDBits)) {
  455. b = abKeyValIDBits[j];
  456. s = b & 0x3F;
  457. b ^= bInvert;
  458. if (!(b & 0x80)) {
  459. if (!(b & 0x40)) {
  460. lp386->PfW386Flags |= 1L << s;
  461. }
  462. else
  463. lp386->PfW386Flags2 |= 1L << s;
  464. }
  465. else {
  466. if (!(b & 0x40))
  467. lp386->PfW386Flags &= ~(1L << s);
  468. else
  469. lp386->PfW386Flags2 &= ~(1L << s);
  470. }
  471. }
  472. else {
  473. j -= ARRAYSIZE(abKeyValIDBits);
  474. if (j < ARRAYSIZE(abRMKeyValIDBits)) {
  475. b = abRMKeyValIDBits[j];
  476. s = b & 0x3F;
  477. b ^= bInvert;
  478. if (!(b & 0x80))
  479. lpenh->dwRealModeFlagsProp |= 1L << s;
  480. else
  481. lpenh->dwRealModeFlagsProp &= ~(1L << s);
  482. }
  483. else {
  484. j -= ARRAYSIZE(abRMKeyValIDBits);
  485. switch(j) {
  486. case 0: // special case 0
  487. if (!bInvert)
  488. lpstd->MSflags |= EXITMASK;
  489. else
  490. lpstd->MSflags &= ~EXITMASK;
  491. break;
  492. case 1: // special case 1
  493. if (bInvert)
  494. lpenh->tskProp.flTsk |= TSK_NOSCREENSAVER;
  495. else
  496. lpenh->tskProp.flTsk &= ~TSK_NOSCREENSAVER;
  497. break;
  498. default:
  499. ASSERTFAIL();
  500. break;
  501. }
  502. }
  503. }
  504. }
  505. break;
  506. }
  507. } while (SetupFindNextLine(pInfContext, pInfContext));
  508. UnlockPIF:
  509. ppl->cLocks--;
  510. }
  511. int GetKeyID(PINFCONTEXT pInfContext)
  512. {
  513. int i;
  514. TCHAR szCurKey[MAX_KEY_SIZE];
  515. DWORD dwSize;
  516. FunctionName(GetKeyID);
  517. if (SetupGetStringFieldW(pInfContext, APPSINF_KEY, szCurKey, ARRAYSIZE(szCurKey), &dwSize)) {
  518. for (i=0; i<ARRAYSIZE(apszKey); i++) {
  519. if (!lstrcmpi(szCurKey, apszKey[i]))
  520. return i+1;
  521. }
  522. return KEYID_UNKNOWN;
  523. }
  524. return KEYID_NONE;
  525. }
  526. int GetKeyValID(PINFCONTEXT pInfContext, int i)
  527. {
  528. TCHAR szCurKeyVal[MAX_KEYVAL_SIZE];
  529. DWORD dwSize;
  530. FunctionName(GetKeyValID);
  531. if (SetupGetStringFieldW(pInfContext, i, szCurKeyVal, ARRAYSIZE(szCurKeyVal), &dwSize)) {
  532. for (i=0; i<ARRAYSIZE(apszKeyVal); i++) {
  533. if (!lstrcmpi(szCurKeyVal, apszKeyVal[i]))
  534. return i+1;
  535. }
  536. return KEYVAL_ID_UNKNOWN;
  537. }
  538. return KEYVAL_ID_NONE;
  539. }
  540. #endif