mirror of https://github.com/tongzx/nt5src
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
1258 lines
32 KiB
//
|
|
// ConfOpt.C
|
|
//
|
|
// Copyright (C) Microsoft, 1994,1995 All Rights Reserved.
|
|
//
|
|
// History:
|
|
// ral 5/23/94 - First pass
|
|
// 3/20/95 [stevecat] - NT port & real clean up, unicode, etc.
|
|
//
|
|
//
|
|
#include "priv.h"
|
|
#include "appwiz.h"
|
|
|
|
#define MAX_CFG_FILE_SIZE 20000
|
|
#define MAX_DESC_SIZE 100
|
|
|
|
//
|
|
// Return codes for OptSelected
|
|
//
|
|
#define OPTSEL_YES 0
|
|
#define OPTSEL_NO 1
|
|
#define OPTSEL_NOTSUPP 2
|
|
|
|
//
|
|
// Define checkbox states for listview
|
|
//
|
|
#define LVIS_GCNOCHECK 0x1000
|
|
#define LVIS_GCCHECK 0x2000
|
|
|
|
//
|
|
// Character definitions
|
|
//
|
|
#define CR 13
|
|
#define LF 10
|
|
|
|
|
|
TCHAR const c_szCRLF[] = {CR, LF, 0};
|
|
TCHAR const c_szRegValAutoexec[] = REGSTR_VAL_AUTOEXEC;
|
|
TCHAR const c_szRegValConfigSys[] = REGSTR_VAL_CONFIGSYS;
|
|
TCHAR const c_szRegDosOptFlags[] = REGSTR_VAL_DOSOPTFLAGS;
|
|
TCHAR const c_szRegStandardOpt[] = REGSTR_VAL_STDDOSOPTION;
|
|
TCHAR const c_szRegDosOptTip[] = REGSTR_VAL_DOSOPTTIP;
|
|
TCHAR const c_szRegDosOptsPath[] = REGSTR_PATH_MSDOSOPTS;
|
|
TCHAR const c_szRegGlobalFlags[] = REGSTR_VAL_DOSOPTGLOBALFLAGS;
|
|
TCHAR const c_szRegShutdownKey[] = REGSTR_PATH_SHUTDOWN;
|
|
TCHAR const c_szForceRebootVal[] = REGSTR_VAL_FORCEREBOOT;
|
|
|
|
|
|
|
|
BOOL MustRebootSystem(void)
|
|
{
|
|
HKEY hk;
|
|
BOOL bMustReboot = FALSE;
|
|
|
|
if (RegOpenKey(HKEY_LOCAL_MACHINE, c_szRegShutdownKey, &hk) == ERROR_SUCCESS)
|
|
{
|
|
bMustReboot = (RegQueryValueEx(hk, c_szForceRebootVal, NULL,
|
|
NULL, NULL, NULL) == ERROR_SUCCESS);
|
|
RegCloseKey(hk);
|
|
}
|
|
return(bMustReboot);
|
|
}
|
|
|
|
|
|
DWORD GetMSDOSOptGlobalFlags(LPWIZDATA lpwd)
|
|
{
|
|
if ((lpwd->dwFlags & WDFLAG_READOPTFLAGS) == 0)
|
|
{
|
|
HKEY hk;
|
|
|
|
lpwd->dwFlags |= WDFLAG_READOPTFLAGS;
|
|
|
|
if (RegOpenKey(HKEY_LOCAL_MACHINE, c_szRegDosOptsPath, &hk)
|
|
== ERROR_SUCCESS)
|
|
{
|
|
UINT cb = sizeof(lpwd->dwDosOptGlobalFlags);
|
|
|
|
if (RegQueryValueEx(hk, c_szRegGlobalFlags, NULL, NULL,
|
|
(LPVOID)(&(lpwd->dwDosOptGlobalFlags)), &cb)
|
|
!= ERROR_SUCCESS)
|
|
{
|
|
lpwd->dwDosOptGlobalFlags = 0;
|
|
}
|
|
RegCloseKey(hk);
|
|
}
|
|
|
|
if (MustRebootSystem())
|
|
{
|
|
lpwd->dwDosOptGlobalFlags |= DOSOPTGF_DEFCLEAN;
|
|
}
|
|
}
|
|
return(lpwd->dwDosOptGlobalFlags);
|
|
}
|
|
|
|
|
|
//
|
|
// Structure used to store text for Autoexec.Bat and Config.Sys
|
|
//
|
|
|
|
typedef struct _TEXTDATA {
|
|
UINT cb;
|
|
LPTSTR lpszData;
|
|
} TEXTDATA, FAR * LPTEXTDATA;
|
|
|
|
|
|
//
|
|
// Gets a single value from the specified option index. If no data is
|
|
// found for the specified value name then a 0 DWORD is stored.
|
|
//
|
|
|
|
void GetOptVal(LPWIZDATA lpwd, int i, LPCTSTR lpszValName, LPVOID lpData, UINT cb)
|
|
{
|
|
if (RegQueryValueEx(lpwd->DosOpt[i].hk, lpszValName, NULL, NULL, lpData, &cb) != ERROR_SUCCESS)
|
|
{
|
|
*(LPDWORD)lpData = (DWORD)0;
|
|
}
|
|
}
|
|
|
|
|
|
BOOL FindDriver(int idFiles, int idLoadHigh, HKEY hk, LPCTSTR lpszRegVal,
|
|
LPCTSTR FAR dirs[])
|
|
{
|
|
TCHAR szFiles[MAX_PATH];
|
|
LPTSTR lpszCur, lpszFileName;
|
|
TCHAR szCommand[MAX_PATH+20];
|
|
|
|
LoadAndStrip(idFiles, szFiles, ARRAYSIZE(szFiles));
|
|
LoadString(g_hinst, idLoadHigh, szCommand, ARRAYSIZE(szCommand));
|
|
|
|
lpszFileName = &szCommand[lstrlen(szCommand)];
|
|
lpszCur = szFiles;
|
|
|
|
while (*lpszCur)
|
|
{
|
|
lstrcpy(lpszFileName, lpszCur);
|
|
if (PathResolve(lpszFileName, dirs, PRF_VERIFYEXISTS))
|
|
{
|
|
PathGetShortPath(lpszFileName);
|
|
|
|
RegSetValueEx(hk, lpszRegVal, 0, REG_SZ, (LPBYTE) szCommand,
|
|
(lstrlen(szCommand)+1)*sizeof(TCHAR));
|
|
|
|
return(TRUE);
|
|
}
|
|
lpszCur = SkipStr(lpszCur);
|
|
}
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
BOOL SetUpMouse(LPWIZDATA lpwd, int i)
|
|
{
|
|
#define MOpt lpwd->DosOpt[i]
|
|
TCHAR szMouseEnv[64];
|
|
TCHAR szMouseDir[64];
|
|
LPCTSTR FAR dirs[] = {szMouseDir, NULL};
|
|
BOOL fRetVal;
|
|
|
|
if (!LoadString(g_hinst, IDS_MOUSEENV, szMouseEnv, ARRAYSIZE(szMouseEnv)))
|
|
{
|
|
fRetVal = FALSE;
|
|
}
|
|
else
|
|
{
|
|
lstrcpy(szMouseDir, szMouseEnv);
|
|
|
|
DoEnvironmentSubst(szMouseDir, ARRAYSIZE(szMouseDir));
|
|
|
|
if (lstrcmp(szMouseDir, szMouseEnv) == 0)
|
|
{
|
|
dirs[0] = NULL;
|
|
}
|
|
|
|
if (FindDriver(IDS_MOUSETSRS, IDS_LOADHIGH,MOpt.hk, c_szRegValAutoexec, dirs) ||
|
|
FindDriver(IDS_MOUSEDRVS, IDS_DEVHIGH, MOpt.hk, c_szRegValConfigSys, dirs))
|
|
{
|
|
MOpt.dwFlags |= DOSOPTF_SUPPORTED;
|
|
TraceMsg(TF_ERROR, "%s", "Found real mode mouse driver");
|
|
}
|
|
|
|
MOpt.dwFlags &= ~DOSOPTF_NEEDSETUP;
|
|
RegSetValueEx(MOpt.hk, c_szRegDosOptFlags, 0, REG_DWORD,
|
|
(LPBYTE)&(MOpt.dwFlags), sizeof(MOpt.dwFlags));
|
|
fRetVal = TRUE;
|
|
}
|
|
|
|
return fRetVal;
|
|
#undef MOpt
|
|
}
|
|
|
|
|
|
//
|
|
// The option is not configured. Here's where to add code to set up any
|
|
// standard option. Currently, we only set up the mouse.
|
|
//
|
|
|
|
BOOL SetupOption(LPWIZDATA lpwd, int i)
|
|
{
|
|
BOOL fRetVal;
|
|
|
|
if (RMOPT_MOUSE == lpwd->DosOpt[i].dwStdOpt)
|
|
{
|
|
TraceMsg(TF_ERROR, "%s", "About to search for real mode mouse driver");
|
|
fRetVal = SetUpMouse(lpwd, i);
|
|
}
|
|
else
|
|
{
|
|
fRetVal = TRUE;
|
|
}
|
|
|
|
return fRetVal;
|
|
}
|
|
|
|
|
|
//
|
|
// Closes all open hkeys and frees the memory. NOTE: This function can
|
|
// be called any time, even if ReadRegInfo has not been called previously.
|
|
//
|
|
|
|
void FreeRegInfo(LPWIZDATA lpwd)
|
|
{
|
|
int i;
|
|
|
|
if (!lpwd->DosOpt)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < lpwd->NumOpts; i++)
|
|
{
|
|
RegCloseKey(lpwd->DosOpt[i].hk);
|
|
}
|
|
|
|
LocalFree(lpwd->DosOpt);
|
|
lpwd->DosOpt = NULL;
|
|
lpwd->NumOpts = 0;
|
|
}
|
|
|
|
|
|
//
|
|
// Initializes the option table in the wizard data header.
|
|
//
|
|
|
|
BOOL ReadRegInfo(LPWIZDATA lpwd)
|
|
{
|
|
HKEY hk;
|
|
BOOL bSuccess = FALSE;
|
|
int i;
|
|
|
|
if (lpwd->DosOpt)
|
|
{
|
|
return(TRUE);
|
|
}
|
|
|
|
if (RegOpenKey(HKEY_LOCAL_MACHINE, c_szRegDosOptsPath, &hk) !=
|
|
ERROR_SUCCESS)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RegQueryInfoKey(hk, NULL, NULL, NULL, &(lpwd->NumOpts),
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL) !=
|
|
ERROR_SUCCESS)
|
|
{
|
|
goto ExitCloseKey;
|
|
}
|
|
|
|
lpwd->DosOpt = LocalAlloc(LPTR, lpwd->NumOpts * sizeof(DOSOPT));
|
|
|
|
if (!lpwd->DosOpt)
|
|
{
|
|
goto ExitCloseKey;
|
|
}
|
|
|
|
for (i = 0; i < lpwd->NumOpts; i++)
|
|
{
|
|
UINT cb;
|
|
TCHAR szOptKey[80];
|
|
HKEY hkOpt;
|
|
UINT uOrder = 0;
|
|
int InsPos;
|
|
|
|
cb = ARRAYSIZE(szOptKey);
|
|
|
|
if ((RegEnumKeyEx(hk, i, szOptKey, &cb, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) ||
|
|
(RegOpenKey(hk, szOptKey, &hkOpt) != ERROR_SUCCESS))
|
|
{
|
|
lpwd->NumOpts = i - 1;
|
|
FreeRegInfo(lpwd); // This frees the DosOpt memory
|
|
goto ExitCloseKey;
|
|
}
|
|
|
|
cb = sizeof(uOrder);
|
|
|
|
RegQueryValueEx(hkOpt, REGSTR_VAL_OPTORDER, NULL, NULL, (LPVOID)&uOrder, &cb);
|
|
|
|
for (InsPos = i;
|
|
(InsPos > 0) && (lpwd->DosOpt[InsPos-1].uOrder > uOrder);
|
|
InsPos--);
|
|
|
|
if (InsPos < i)
|
|
{
|
|
MoveMemory(&(lpwd->DosOpt[InsPos+1]), &(lpwd->DosOpt[InsPos]),
|
|
(i - InsPos) * sizeof(DOSOPT));
|
|
}
|
|
|
|
lpwd->DosOpt[InsPos].hk = hkOpt;
|
|
lpwd->DosOpt[InsPos].uOrder = uOrder;
|
|
|
|
GetOptVal(lpwd, InsPos, c_szRegDosOptFlags, &(lpwd->DosOpt[InsPos].dwFlags), sizeof(DWORD));
|
|
GetOptVal(lpwd, InsPos, c_szRegStandardOpt, &(lpwd->DosOpt[InsPos].dwStdOpt), sizeof(DWORD));
|
|
|
|
if (lpwd->DosOpt[InsPos].dwFlags & DOSOPTF_NEEDSETUP)
|
|
{
|
|
if (!SetupOption(lpwd, InsPos))
|
|
{
|
|
goto ExitCloseKey;
|
|
}
|
|
}
|
|
}
|
|
bSuccess = TRUE;
|
|
|
|
ExitCloseKey:
|
|
RegCloseKey(hk);
|
|
Exit:
|
|
return(bSuccess);
|
|
}
|
|
|
|
|
|
//
|
|
// Inserts a single column into the specified ListView.
|
|
//
|
|
|
|
void InitSingleColListView(HWND hLV)
|
|
{
|
|
LV_COLUMN col = {LVCF_FMT | LVCF_WIDTH, LVCFMT_LEFT};
|
|
RECT rc;
|
|
|
|
GetClientRect(hLV, &rc);
|
|
|
|
col.cx = rc.right - GetSystemMetrics(SM_CXVSCROLL)
|
|
- GetSystemMetrics(SM_CXSMICON)
|
|
- 2 * GetSystemMetrics(SM_CXEDGE);
|
|
|
|
ListView_InsertColumn(hLV, 0, &col);
|
|
}
|
|
|
|
|
|
//
|
|
// Initializes the listview with all available options
|
|
//
|
|
|
|
void ConfOptInit(HWND hDlg, LPPROPSHEETPAGE lpp)
|
|
{
|
|
HIMAGELIST himlState;
|
|
HWND hwndOptions = GetDlgItem(hDlg, IDC_OPTIONLIST);
|
|
LPWIZDATA lpwd = InitWizSheet(hDlg, (LPARAM)lpp, 0);
|
|
|
|
InitSingleColListView(hwndOptions);
|
|
|
|
//
|
|
// Lets load our bitmap as an imagelist
|
|
//
|
|
|
|
himlState = ImageList_LoadImage(g_hinst, MAKEINTRESOURCE(IDB_CHECKSTATES), 0, 2,
|
|
CLR_NONE, IMAGE_BITMAP, LR_LOADTRANSPARENT);
|
|
|
|
ListView_SetImageList(hwndOptions, himlState, LVSIL_STATE);
|
|
|
|
//
|
|
// Find all options for MS-DOS configs and set their approropriate state
|
|
// information
|
|
//
|
|
|
|
if (ReadRegInfo(lpwd))
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < lpwd->NumOpts; i++)
|
|
{
|
|
DWORD dwFlags = lpwd->DosOpt[i].dwFlags;
|
|
|
|
if ((dwFlags & DOSOPTF_SUPPORTED) &&
|
|
((dwFlags & DOSOPTF_ALWAYSUSE) == 0) &&
|
|
((dwFlags & DOSOPTF_USESPMODE) == 0 ||
|
|
(lpwd->dwFlags & WDFLAG_REALMODEONLY) == 0) &&
|
|
(lpwd->DosOpt[i].uOrder > 0))
|
|
{
|
|
TCHAR szDesc[MAX_DESC_SIZE];
|
|
LV_ITEM lvi;
|
|
|
|
GetOptVal(lpwd, i, NULL, szDesc, sizeof(szDesc));
|
|
|
|
lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM;
|
|
lvi.iItem = 0x7FFF;
|
|
lvi.iSubItem = 0;
|
|
|
|
//
|
|
///// REARCHITECT If program properties contains real mode flags, use them for defaults!
|
|
//
|
|
|
|
lvi.state = (dwFlags & DOSOPTF_DEFAULT) ? LVIS_GCCHECK : LVIS_GCNOCHECK;
|
|
lvi.stateMask = LVIS_ALL;
|
|
lvi.pszText = szDesc;
|
|
lvi.lParam = (LPARAM)i;
|
|
lvi.cchTextMax = 0;
|
|
|
|
ListView_InsertItem(hwndOptions, &lvi);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Toggles the state of the specified item in the list view.
|
|
//
|
|
|
|
void ToggleState(HWND hwndLV, int i)
|
|
{
|
|
UINT state = ListView_GetItemState(hwndLV, i, LVIS_STATEIMAGEMASK);
|
|
|
|
state = (state == LVIS_GCNOCHECK) ? LVIS_GCCHECK : LVIS_GCNOCHECK;
|
|
|
|
ListView_SetItemState(hwndLV, i, state, LVIS_STATEIMAGEMASK);
|
|
}
|
|
|
|
|
|
//
|
|
// Returns the path to the boot directory. If we can't find it in the
|
|
// registry then this function returns the default (drive that windows
|
|
// directory is on)
|
|
//
|
|
|
|
void GetBootDir(LPTSTR lpszBootDir, int cchBootDir)
|
|
{
|
|
HKEY hkSetup;
|
|
|
|
*lpszBootDir = 0;
|
|
|
|
if (RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_SETUP REGSTR_KEY_SETUP,
|
|
&hkSetup) == ERROR_SUCCESS)
|
|
{
|
|
UINT cb = cchBootDir * SIZEOF(TCHAR);
|
|
|
|
RegQueryValueEx(hkSetup, REGSTR_VAL_BOOTDIR, NULL,
|
|
NULL, (LPBYTE) lpszBootDir, &cb);
|
|
RegCloseKey(hkSetup);
|
|
}
|
|
|
|
if (*lpszBootDir == 0)
|
|
{
|
|
if (0 != GetWindowsDirectory(lpszBootDir, cchBootDir)
|
|
&& lpszBootDir[0] != TEXT('\0')
|
|
&& lpszBootDir[1] == TEXT(':')
|
|
&& lpszBootDir[2] == TEXT('\\'))
|
|
{
|
|
lpszBootDir[3] = TEXT('\0');
|
|
}
|
|
else
|
|
{
|
|
LoadString(g_hinst, IDS_DEFBOOTDIR, lpszBootDir, cchBootDir);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Process the clicks on the listview. do a hittest to see where the user
|
|
// clicked. If on one of the state bitmaps, toggle it.
|
|
//
|
|
|
|
void ConfOptClick(HWND hDlg, LPNMHDR pnmhdr)
|
|
{
|
|
//
|
|
// The user clicked on one the listview see where...
|
|
//
|
|
|
|
DWORD dwpos;
|
|
LV_HITTESTINFO lvhti;
|
|
|
|
dwpos = GetMessagePos();
|
|
lvhti.pt.x = GET_X_LPARAM(dwpos);
|
|
lvhti.pt.y = GET_Y_LPARAM(dwpos);
|
|
|
|
MapWindowPoints(HWND_DESKTOP, pnmhdr->hwndFrom, &lvhti.pt, 1);
|
|
|
|
ListView_HitTest(pnmhdr->hwndFrom, &lvhti);
|
|
|
|
if (lvhti.flags & LVHT_ONITEMSTATEICON)
|
|
{
|
|
ToggleState(pnmhdr->hwndFrom, lvhti.iItem);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// When the user hits the space bar, toggle the state of the selected item.
|
|
//
|
|
BOOL ConfOptKeyDown(HWND hDlg, LV_KEYDOWN *plvkd)
|
|
{
|
|
int iCursor;
|
|
|
|
if (plvkd->wVKey == VK_SPACE && !(GetAsyncKeyState(VK_MENU) < 0))
|
|
{
|
|
//
|
|
// Lets toggle the cursored item.
|
|
//
|
|
|
|
iCursor = ListView_GetNextItem(plvkd->hdr.hwndFrom, -1, LVNI_FOCUSED);
|
|
|
|
if (iCursor != -1)
|
|
{
|
|
ToggleState(plvkd->hdr.hwndFrom, iCursor);
|
|
}
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Item selection changed. Update tip.
|
|
//
|
|
|
|
void ItemChanged(LPWIZDATA lpwd, LPNM_LISTVIEW lpnmlv)
|
|
{
|
|
LV_ITEM lvi;
|
|
TCHAR szTip[200]; ///???
|
|
|
|
if ((lpnmlv->uNewState & LVIS_FOCUSED) &&
|
|
(!(lpnmlv->uOldState & LVIS_FOCUSED)))
|
|
{
|
|
lvi.iItem = lpnmlv->iItem;
|
|
lvi.iSubItem = 0;
|
|
lvi.mask = LVIF_PARAM;
|
|
|
|
ListView_GetItem(lpnmlv->hdr.hwndFrom, &lvi);
|
|
|
|
GetOptVal(lpwd, (int)lvi.lParam, c_szRegDosOptTip, szTip, sizeof(szTip));
|
|
|
|
Static_SetText(GetDlgItem(lpwd->hwnd, IDC_OPTIONTIP), szTip);
|
|
}
|
|
}
|
|
|
|
|
|
void _inline NoSupportMsg(LPWIZDATA lpwd, int iOpt)
|
|
{
|
|
LPTSTR lpszDesc = (LPTSTR)LocalAlloc(LMEM_FIXED, MAX_DESC_SIZE*sizeof(TCHAR));
|
|
|
|
if (lpszDesc)
|
|
{
|
|
LPTSTR lpszMsg = (LPTSTR)LocalAlloc(LMEM_FIXED, 512*sizeof(TCHAR)); // Max 2 resource size
|
|
|
|
if (lpszMsg)
|
|
{
|
|
GetOptVal(lpwd, iOpt, NULL, lpszDesc, MAX_DESC_SIZE*sizeof(TCHAR));
|
|
LoadString(g_hinst, IDS_NOSUPPORT1, lpszMsg, 512);
|
|
LoadString(g_hinst, IDS_NOSUPPORT2, lpszMsg+lstrlen(lpszMsg), 256);
|
|
ShellMessageBox(g_hinst, lpwd->hwnd,
|
|
lpszMsg, 0,
|
|
MB_OK | MB_ICONEXCLAMATION,
|
|
lpszDesc);
|
|
LocalFree(lpszMsg);
|
|
}
|
|
LocalFree(lpszDesc);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Returns OPTSEL_YES if the option indicated by i is selected in the list
|
|
// box, or, if hwndLV is NULL then OPTSEL_YES if option should be added,
|
|
// OPTSEL_NO if should not be added, and OPTSEL_NOTSUPP if the option is
|
|
// required but can't be added.
|
|
//
|
|
|
|
int OptSelected(LPWIZDATA lpwd, int i, HWND hwndLV)
|
|
{
|
|
BOOL bSelected = FALSE;
|
|
|
|
if (lpwd->DosOpt[i].dwFlags & DOSOPTF_ALWAYSUSE)
|
|
{
|
|
bSelected = TRUE;
|
|
}
|
|
else
|
|
{
|
|
if (hwndLV)
|
|
{
|
|
LV_ITEM lvi;
|
|
int NumItems = ListView_GetItemCount(hwndLV);
|
|
|
|
for (lvi.iItem = 0; lvi.iItem < NumItems; lvi.iItem++)
|
|
{
|
|
lvi.iSubItem = 0;
|
|
lvi.mask = LVIF_PARAM | LVIF_STATE;
|
|
lvi.stateMask = LVIS_STATEIMAGEMASK;
|
|
ListView_GetItem(hwndLV, &lvi);
|
|
if ((int)lvi.lParam == i)
|
|
{
|
|
bSelected = ((lvi.state & LVIS_STATEIMAGEMASK) == LVIS_GCCHECK);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
BOOL bSupported = lpwd->DosOpt[i].dwFlags & DOSOPTF_SUPPORTED;
|
|
|
|
if (lpwd->PropPrg.dwRealModeFlags & lpwd->DosOpt[i].dwStdOpt)
|
|
{
|
|
bSelected = TRUE;
|
|
|
|
if (!bSupported)
|
|
{
|
|
NoSupportMsg(lpwd, i);
|
|
return(OPTSEL_NOTSUPP);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bSupported)
|
|
{
|
|
bSelected = (lpwd->PropPrg.dwRealModeFlags & (lpwd->DosOpt[i].dwStdOpt >> 16));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bSelected)
|
|
{
|
|
return(OPTSEL_YES);
|
|
}
|
|
else
|
|
{
|
|
return(OPTSEL_NO);
|
|
}
|
|
}
|
|
|
|
|
|
void AppendStr(LPTEXTDATA lpTD, LPTSTR lpStr)
|
|
{
|
|
int cb = lstrlen(lpStr)*sizeof(TCHAR);
|
|
|
|
if ((lpTD->cb + cb + 2) <= MAX_CFG_FILE_SIZE*sizeof(TCHAR))
|
|
{
|
|
memcpy(lpTD->lpszData+lpTD->cb, lpStr, cb);
|
|
lpTD->cb += cb;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Appends the string+cr/lf to the TextData structure.
|
|
//
|
|
|
|
void AppendLine(LPTEXTDATA lpTD, LPTSTR lpStr)
|
|
{
|
|
AppendStr(lpTD, lpStr);
|
|
AppendStr(lpTD, (LPTSTR)c_szCRLF);
|
|
}
|
|
|
|
|
|
//
|
|
// Returns NULL if none of the strings in szKeys matches the first entry
|
|
// in the specified string.
|
|
//
|
|
|
|
LPTSTR MatchesKey(LPTSTR lpszStr, LPTSTR lpszKeys)
|
|
{
|
|
UINT cch = lstrlen(lpszStr);
|
|
TCHAR szUpLine[20];
|
|
LPTSTR lpszCurKey;
|
|
|
|
if (cch >= ARRAYSIZE(szUpLine))
|
|
{
|
|
cch = ARRAYSIZE(szUpLine)-1;
|
|
}
|
|
|
|
memcpy(szUpLine, lpszStr, cch*sizeof(TCHAR));
|
|
|
|
szUpLine[cch] = 0;
|
|
|
|
CharUpper(szUpLine);
|
|
|
|
for (lpszCurKey = lpszKeys; *lpszCurKey; lpszCurKey = SkipStr(lpszCurKey))
|
|
{
|
|
UINT cchKey = lstrlen(lpszCurKey);
|
|
|
|
if ((cchKey < cch) &&
|
|
((szUpLine[cchKey] == TEXT(' ')) || (szUpLine[cchKey] == TEXT('='))) &&
|
|
(memcmp(lpszCurKey, szUpLine, cchKey*sizeof(TCHAR)) == 0))
|
|
{
|
|
return(lpszCurKey);
|
|
}
|
|
}
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
//
|
|
// Copy the current environment into Autoexec.Bat
|
|
//
|
|
|
|
void CopyEnvironment(LPTEXTDATA lpAE)
|
|
{
|
|
TCHAR szKeys[MAX_PATH]; // SIZE?
|
|
TCHAR szSetCmd[20];
|
|
LPTSTR lpszCur = (LPTSTR)GetEnvironmentStrings();
|
|
|
|
LoadString(g_hinst, IDS_SETCMD, szSetCmd, ARRAYSIZE(szSetCmd));
|
|
LoadAndStrip(IDS_NOCOPYENV, szKeys, ARRAYSIZE(szKeys));
|
|
|
|
while (*lpszCur)
|
|
{
|
|
if (!MatchesKey(lpszCur, szKeys))
|
|
{
|
|
AppendStr(lpAE, szSetCmd);
|
|
AppendLine(lpAE, lpszCur);
|
|
}
|
|
|
|
lpszCur = SkipStr(lpszCur);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Add keyboard type option for JKEYB.SYS
|
|
//
|
|
|
|
void SetJkeybOpt(LPTSTR lpszStr)
|
|
{
|
|
UINT cb, cbKey;
|
|
TCHAR szUpLine[64];
|
|
TCHAR lpszKey[] = TEXT("JKEYB.SYS");
|
|
TCHAR *lpszOpts[] = {TEXT(" /101"), TEXT(" /AX"), TEXT(" /106"), TEXT(" /J31DT"), TEXT(" /J31NB"), TEXT(" /J31LT")};
|
|
int KeybOpt;
|
|
int i;
|
|
|
|
ASSERT(lpszStr);
|
|
|
|
cb = lstrlen(lpszStr);
|
|
cbKey = lstrlen(lpszKey);
|
|
|
|
if (cb >= ARRAYSIZE(szUpLine))
|
|
{
|
|
cb = ARRAYSIZE(szUpLine)-1;
|
|
}
|
|
|
|
memcpy(szUpLine, lpszStr, cb*sizeof(TCHAR));
|
|
|
|
szUpLine[cb] = 0;
|
|
|
|
// AnsiUpper(szUpLine);
|
|
CharUpper(szUpLine);
|
|
|
|
for (i = 0; cbKey <= cb; i++, cb--)
|
|
{
|
|
if (memcmp(lpszKey, &szUpLine[i], cbKey*sizeof(TCHAR)) == 0)
|
|
{
|
|
|
|
// if (GetKeyboardType(0) == 7){
|
|
// switch(GetKeyboardType(1)) {
|
|
|
|
if (GetPrivateProfileInt(TEXT("keyboard"), TEXT("type"), 0, TEXT("SYSTEM.INI")) == 7)
|
|
{
|
|
switch(GetPrivateProfileInt(TEXT("keyboard"), TEXT("subtype"), 0, TEXT("SYSTEM.INI")))
|
|
{
|
|
case 0:
|
|
KeybOpt = 0;
|
|
break;
|
|
case 1:
|
|
KeybOpt = 1;
|
|
break;
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
KeybOpt = 2;
|
|
break;
|
|
case 13:
|
|
KeybOpt = 3;
|
|
break;
|
|
case 14:
|
|
KeybOpt = 4;
|
|
break;
|
|
case 15:
|
|
KeybOpt = 5;
|
|
break;
|
|
default:
|
|
KeybOpt = 0;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
KeybOpt = 0;
|
|
|
|
lstrcat(lpszStr, lpszOpts[KeybOpt]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Adds an option line from the specified value name to the TEXTDATA structure
|
|
//
|
|
|
|
BOOL AddOption(HKEY hk, LPCTSTR lpszValName, LPTEXTDATA lpTD,
|
|
LPTSTR lpszHighCmds, LPTSTR lpszLowCmd, BOOL bCanLoadHigh)
|
|
{
|
|
TCHAR szOptData[256];
|
|
UINT cb = sizeof(szOptData);
|
|
DWORD dwType;
|
|
LCID lcid = GetThreadLocale();
|
|
|
|
if (RegQueryValueEx(hk, lpszValName, NULL,
|
|
&dwType, (LPBYTE) szOptData, &cb) == ERROR_SUCCESS)
|
|
{
|
|
LPTSTR lpszAddData = szOptData;
|
|
|
|
DoEnvironmentSubst(szOptData, ARRAYSIZE(szOptData));
|
|
|
|
//
|
|
// Now remove LH or LoadHigh or DeviceHigh and replace with the
|
|
// appropriate string if EMM386 has not loaded yet.
|
|
//
|
|
|
|
if (!bCanLoadHigh)
|
|
{
|
|
LPTSTR lpszMatch = MatchesKey(szOptData, lpszHighCmds);
|
|
|
|
if (lpszMatch)
|
|
{
|
|
int cbHigh = lstrlen(lpszMatch);
|
|
if (lpszLowCmd)
|
|
{
|
|
int cbLow = lstrlen(lpszLowCmd);
|
|
|
|
lpszAddData += cbHigh - cbLow;
|
|
|
|
memcpy(lpszAddData, lpszLowCmd, cbLow*sizeof(TCHAR));
|
|
|
|
}
|
|
else
|
|
{
|
|
lpszAddData += cbHigh + 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (PRIMARYLANGID(LANGIDFROMLCID(lcid))==LANG_JAPANESE)
|
|
{
|
|
SetJkeybOpt(lpszAddData);
|
|
}
|
|
AppendLine(lpTD, lpszAddData);
|
|
|
|
return(TRUE);
|
|
}
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
//
|
|
// Sets the appropriate configuration options in the PIF proprties
|
|
// If fForceCleanCfg is TRUE then a clean configuration is created. Otherwise
|
|
// the autoexec and config fields are nuked to force the app to use the current
|
|
// configuration.
|
|
//
|
|
|
|
PIFWIZERR SetConfOptions(LPWIZDATA lpwd, HWND hwndOptions, BOOL fForceCleanCfg)
|
|
{
|
|
TEXTDATA AE;
|
|
TEXTDATA CS;
|
|
int i;
|
|
PIFWIZERR err = PIFWIZERR_SUCCESS;
|
|
TCHAR szCSHighCmds[100];
|
|
TCHAR szCSLowCmd[20];
|
|
TCHAR szAEHighCmds[100];
|
|
BOOL bCanLoadHigh = FALSE;
|
|
|
|
//
|
|
// Make sure the real mode flag is set in the program properties.
|
|
//
|
|
|
|
PifMgr_GetProperties(lpwd->hProps, (LPSTR)GROUP_PRG, &(lpwd->PropPrg),
|
|
sizeof(lpwd->PropPrg), GETPROPS_NONE);
|
|
|
|
lpwd->PropPrg.flPrgInit |= PRGINIT_REALMODE;
|
|
|
|
PifMgr_SetProperties(lpwd->hProps, (LPSTR)GROUP_PRG, &(lpwd->PropPrg),
|
|
sizeof(lpwd->PropPrg), SETPROPS_NONE);
|
|
|
|
if (!fForceCleanCfg)
|
|
{
|
|
TCHAR NullStr = 0;
|
|
|
|
PifMgr_SetProperties(lpwd->hProps, AUTOEXECHDRSIG40, &NullStr, 0, SETPROPS_NONE);
|
|
PifMgr_SetProperties(lpwd->hProps, CONFIGHDRSIG40, &NullStr, 0, SETPROPS_NONE);
|
|
return(err);
|
|
}
|
|
|
|
//
|
|
// Load strings used to force drivers to load low if no EMM386.
|
|
//
|
|
|
|
LoadString(g_hinst, IDS_CSLOWSTR, szCSLowCmd, ARRAYSIZE(szCSLowCmd));
|
|
LoadAndStrip(IDS_CSHIGHSTRS, szCSHighCmds, ARRAYSIZE(szCSHighCmds));
|
|
LoadAndStrip(IDS_AEHIGHSTRS, szAEHighCmds, ARRAYSIZE(szAEHighCmds));
|
|
|
|
//
|
|
// Allocate memory for autoexec/config.sys buffers.
|
|
//
|
|
|
|
AE.lpszData = (LPTSTR)LocalAlloc(LPTR, MAX_CFG_FILE_SIZE*sizeof(TCHAR));
|
|
|
|
if (AE.lpszData == NULL)
|
|
{
|
|
return(PIFWIZERR_OUTOFMEM);
|
|
}
|
|
|
|
CS.lpszData = (LPTSTR)LocalAlloc(LPTR, MAX_CFG_FILE_SIZE*sizeof(TCHAR));
|
|
|
|
if (CS.lpszData == NULL)
|
|
{
|
|
LocalFree(AE.lpszData);
|
|
return(PIFWIZERR_OUTOFMEM);
|
|
}
|
|
|
|
AE.cb = CS.cb = 0;
|
|
|
|
//
|
|
// Copy the appropriate goop out of config.sys and autoexec.bat
|
|
//
|
|
|
|
CopyEnvironment(&AE);
|
|
|
|
for (i = 0; i < lpwd->NumOpts; i++)
|
|
{
|
|
int OptSel = OptSelected(lpwd, i, hwndOptions);
|
|
|
|
if (OptSel == OPTSEL_YES)
|
|
{
|
|
bCanLoadHigh |= (lpwd->DosOpt[i].dwFlags & DOSOPTF_PROVIDESUMB);
|
|
|
|
AddOption(lpwd->DosOpt[i].hk, c_szRegValAutoexec, &AE,
|
|
szAEHighCmds, NULL, bCanLoadHigh);
|
|
|
|
AddOption(lpwd->DosOpt[i].hk, c_szRegValConfigSys, &CS,
|
|
szCSHighCmds, szCSLowCmd, bCanLoadHigh);
|
|
|
|
//
|
|
// DOSOPTF_MULTIPLE will load multiple configuration from
|
|
// Config.Sys1 - Config.Sys9 and Autoexec.Bat1 - Autoexec.Bat9
|
|
//
|
|
|
|
if (lpwd->DosOpt[i].dwFlags & DOSOPTF_MULTIPLE)
|
|
{
|
|
BOOL ret;
|
|
TCHAR multicount[2];
|
|
TCHAR multiAutoexec[64];
|
|
TCHAR multiConfig[64];
|
|
|
|
lstrcpy(multicount,TEXT("1"));
|
|
|
|
while (1)
|
|
{
|
|
lstrcpy(multiAutoexec, c_szRegValAutoexec);
|
|
lstrcat(multiAutoexec, multicount);
|
|
lstrcpy(multiConfig, c_szRegValConfigSys);
|
|
lstrcat(multiConfig, multicount);
|
|
|
|
ret = AddOption(lpwd->DosOpt[i].hk, multiAutoexec, &AE,
|
|
szAEHighCmds, NULL, bCanLoadHigh);
|
|
|
|
ret |= AddOption(lpwd->DosOpt[i].hk, multiConfig, &CS,
|
|
szCSHighCmds, szCSLowCmd, bCanLoadHigh);
|
|
|
|
if (!ret)
|
|
break;
|
|
|
|
multicount[0] += 1;
|
|
|
|
if (multicount[0] > TEXT('9'))
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (OptSel == OPTSEL_NOTSUPP)
|
|
{
|
|
err = PIFWIZERR_UNSUPPORTEDOPT;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Set the properties in the PIF file
|
|
//
|
|
|
|
PifMgr_SetProperties(lpwd->hProps, AUTOEXECHDRSIG40, AE.lpszData, AE.cb, SETPROPS_NONE);
|
|
PifMgr_SetProperties(lpwd->hProps, CONFIGHDRSIG40, CS.lpszData, CS.cb, SETPROPS_NONE);
|
|
|
|
//
|
|
// Clean up allocated memory
|
|
//
|
|
|
|
LocalFree(AE.lpszData);
|
|
LocalFree(CS.lpszData);
|
|
|
|
return(err);
|
|
}
|
|
|
|
|
|
//
|
|
// The user hit the finish button. Set the proper configuration.
|
|
//
|
|
|
|
PIFWIZERR ConfigRealModeOptions(LPWIZDATA lpwd, HWND hwndOptList,
|
|
UINT uAction)
|
|
{
|
|
PIFWIZERR err = PIFWIZERR_GENERALFAILURE;
|
|
BOOL fCleanCfg;
|
|
|
|
switch(uAction)
|
|
{
|
|
case CRMOACTION_DEFAULT:
|
|
fCleanCfg = GetMSDOSOptGlobalFlags(lpwd) & DOSOPTGF_DEFCLEAN;
|
|
break;
|
|
|
|
case CRMOACTION_CLEAN:
|
|
fCleanCfg = TRUE;
|
|
break;
|
|
|
|
case CRMOACTION_CURRENT:
|
|
fCleanCfg = FALSE;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// OK to call twice -- Returns true
|
|
//
|
|
|
|
if (ReadRegInfo(lpwd))
|
|
{
|
|
if (lpwd->hProps == 0)
|
|
{
|
|
if (CreateLink(lpwd))
|
|
{
|
|
TCHAR szLinkName[MAX_PATH];
|
|
|
|
GetLinkName(szLinkName, lpwd);
|
|
|
|
lpwd->hProps = PifMgr_OpenProperties(szLinkName, NULL, 0, OPENPROPS_NONE);
|
|
|
|
if (lpwd->hProps)
|
|
{
|
|
err = SetConfOptions(lpwd, hwndOptList, fCleanCfg);
|
|
|
|
PifMgr_CloseProperties(lpwd->hProps, CLOSEPROPS_NONE);
|
|
|
|
lpwd->hProps = 0;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
err = SetConfOptions(lpwd, hwndOptList, fCleanCfg);
|
|
}
|
|
|
|
FreeRegInfo(lpwd);
|
|
}
|
|
return(err);
|
|
}
|
|
|
|
|
|
BOOL_PTR CALLBACK ConfigOptionsDlgProc(HWND hDlg, UINT message , WPARAM wParam, LPARAM lParam)
|
|
{
|
|
LPNMHDR lpnm = NULL;
|
|
LPPROPSHEETPAGE lpp = (LPPROPSHEETPAGE)(GetWindowLongPtr(hDlg, DWLP_USER));
|
|
LPWIZDATA lpwd = lpp ? (LPWIZDATA)lpp->lParam : NULL;
|
|
|
|
switch(message)
|
|
{
|
|
case WM_NOTIFY:
|
|
lpnm = (LPNMHDR)lParam;
|
|
|
|
if(lpnm)
|
|
{
|
|
switch(lpnm->code)
|
|
{
|
|
case LVN_ITEMCHANGED:
|
|
if(lpwd)
|
|
{
|
|
ItemChanged(lpwd, (LPNM_LISTVIEW)lParam);
|
|
}
|
|
break;
|
|
|
|
case NM_CLICK:
|
|
case NM_DBLCLK:
|
|
ConfOptClick(hDlg, lpnm);
|
|
break;
|
|
|
|
case LVN_KEYDOWN:
|
|
SetDlgMsgResult(hDlg, WM_NOTIFY,
|
|
ConfOptKeyDown(hDlg, (LV_KEYDOWN *)lParam));
|
|
break;
|
|
|
|
|
|
case PSN_SETACTIVE:
|
|
if(lpwd)
|
|
{
|
|
lpwd->hwnd = hDlg;
|
|
|
|
if (lpwd->dwFlags & WDFLAG_PIFPROP)
|
|
{
|
|
TCHAR szOK[20];
|
|
|
|
LoadString(g_hinst, IDS_OK, szOK, ARRAYSIZE(szOK));
|
|
PropSheet_SetFinishText(GetParent(hDlg), szOK);
|
|
}
|
|
else
|
|
{
|
|
PropSheet_SetWizButtons(GetParent(hDlg),
|
|
PSWIZB_FINISH | PSWIZB_BACK);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case PSN_WIZFINISH:
|
|
if(lpwd)
|
|
{
|
|
ConfigRealModeOptions(lpwd, GetDlgItem(hDlg, IDC_OPTIONLIST),
|
|
CRMOACTION_CLEAN);
|
|
}
|
|
break;
|
|
|
|
case PSN_RESET:
|
|
if(lpwd)
|
|
{
|
|
CleanUpWizData(lpwd);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
case WM_INITDIALOG:
|
|
ConfOptInit(hDlg, (LPPROPSHEETPAGE)lParam);
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
|
|
} // end of switch on message
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
void WhichConfInit(HWND hDlg, LPPROPSHEETPAGE lpp)
|
|
{
|
|
LPWIZDATA lpwd = InitWizSheet(hDlg, (LPARAM)lpp, 0);
|
|
|
|
CheckRadioButton(hDlg, IDB_CURCFG, IDB_CLEANCFG,
|
|
GetMSDOSOptGlobalFlags(lpwd) & DOSOPTGF_DEFCLEAN ?
|
|
IDB_CLEANCFG : IDB_CURCFG);
|
|
}
|
|
|
|
|
|
void SetChoiceWizBtns(LPWIZDATA lpwd)
|
|
{
|
|
PropSheet_SetWizButtons(GetParent(lpwd->hwnd),
|
|
IsDlgButtonChecked(lpwd->hwnd, IDB_CLEANCFG) ?
|
|
PSWIZB_NEXT | PSWIZB_BACK :
|
|
PSWIZB_FINISH | PSWIZB_BACK);
|
|
}
|
|
|
|
|
|
BOOL_PTR CALLBACK PickConfigDlgProc(HWND hDlg, UINT message , WPARAM wParam, LPARAM lParam)
|
|
{
|
|
LPNMHDR lpnm = NULL;
|
|
LPPROPSHEETPAGE lpp = (LPPROPSHEETPAGE)(GetWindowLongPtr(hDlg, DWLP_USER));
|
|
LPWIZDATA lpwd = lpp ? (LPWIZDATA)lpp->lParam : NULL;
|
|
|
|
switch(message)
|
|
{
|
|
case WM_NOTIFY:
|
|
lpnm = (LPNMHDR)lParam;
|
|
|
|
if(lpnm)
|
|
{
|
|
switch(lpnm->code)
|
|
{
|
|
case PSN_SETACTIVE:
|
|
if(lpwd)
|
|
{
|
|
lpwd->hwnd = hDlg;
|
|
if (MustRebootSystem())
|
|
{
|
|
SetDlgMsgResult(hDlg, WM_NOTIFY, -1);
|
|
}
|
|
else
|
|
{
|
|
SetChoiceWizBtns(lpwd);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case PSN_WIZFINISH:
|
|
if(lpwd)
|
|
{
|
|
ConfigRealModeOptions(lpwd, GetDlgItem(hDlg, IDC_OPTIONLIST),
|
|
CRMOACTION_CURRENT);
|
|
}
|
|
break;
|
|
|
|
case PSN_RESET:
|
|
if(lpwd)
|
|
{
|
|
CleanUpWizData(lpwd);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
|
{
|
|
case IDB_CURCFG:
|
|
case IDB_CLEANCFG:
|
|
if(lpwd)
|
|
{
|
|
SetChoiceWizBtns(lpwd);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_INITDIALOG:
|
|
WhichConfInit(hDlg, (LPPROPSHEETPAGE)lParam);
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
|
|
} // end of switch on message
|
|
|
|
return TRUE;
|
|
}
|