|
|
#include "stdafx.h"
#include "PageBootIni.h"
#include "MSConfigState.h"
#include "BootAdv.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__; #endif
/////////////////////////////////////////////////////////////////////////////
// CPageBootIni property page
IMPLEMENT_DYNCREATE(CPageBootIni, CPropertyPage)
CPageBootIni::CPageBootIni() : CPropertyPage(CPageBootIni::IDD) { //{{AFX_DATA_INIT(CPageBootIni)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
m_fIgnoreEdit = FALSE; m_strFileName = BOOT_INI; m_fModified = FALSE; }
CPageBootIni::~CPageBootIni() { }
void CPageBootIni::DoDataExchange(CDataExchange* pDX) { CPropertyPage::DoDataExchange(pDX); //{{AFX_DATA_MAP(CPageBootIni)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CPageBootIni, CPropertyPage) //{{AFX_MSG_MAP(CPageBootIni)
ON_BN_CLICKED(IDC_BOOTMOVEDOWN, OnBootMoveDown) ON_BN_CLICKED(IDC_BOOTMOVEUP, OnBootMoveUp) ON_LBN_SELCHANGE(IDC_LISTBOOTINI, OnSelChangeList) ON_BN_CLICKED(IDC_BASEVIDEO, OnClickedBase) ON_BN_CLICKED(IDC_BOOTLOG, OnClickedBootLog) ON_BN_CLICKED(IDC_NOGUIBOOT, OnClickedNoGUIBoot) ON_BN_CLICKED(IDC_SOS, OnClickedSOS) ON_BN_CLICKED(IDC_SAFEBOOT, OnClickedSafeBoot) ON_BN_CLICKED(IDC_SBDSREPAIR, OnClickedSBDSRepair) ON_BN_CLICKED(IDC_SBMINIMAL, OnClickedSBMinimal) ON_BN_CLICKED(IDC_SBMINIMALALT, OnClickedSBMinimalAlt) ON_BN_CLICKED(IDC_SBNETWORK, OnClickedSBNetwork) ON_EN_CHANGE(IDC_EDITTIMEOUT, OnChangeEditTimeOut) ON_EN_KILLFOCUS(IDC_EDITTIMEOUT, OnKillFocusEditTimeOut) ON_BN_CLICKED(IDC_BOOTADVANCED, OnClickedBootAdvanced) ON_BN_CLICKED(IDC_SETASDEFAULT, OnClickedSetAsDefault) ON_BN_CLICKED(IDC_CHECKBOOTPATHS, OnClickedCheckBootPaths) ON_WM_DESTROY() //}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CPageBootIni message handlers
//-------------------------------------------------------------------------
// Initialize this page by reading the contents of the boot.ini file.
//-------------------------------------------------------------------------
void CPageBootIni::InitializePage() { if (LoadBootIni() && m_nMinOSIndex != -1) { SyncControlsToIni(); if (m_nMinOSIndex != -1) { ::SendMessage(GetDlgItemHWND(IDC_LISTBOOTINI), LB_SETCURSEL, m_nMinOSIndex, 0); SelectLine(m_nMinOSIndex); } } else { // Failed to load the boot.ini file (or it was empty). Disable all controls.
::EnableWindow(GetDlgItemHWND(IDC_BOOTMOVEUP), FALSE); ::EnableWindow(GetDlgItemHWND(IDC_BOOTMOVEDOWN), FALSE); ::EnableWindow(GetDlgItemHWND(IDC_SAFEBOOT), FALSE); ::EnableWindow(GetDlgItemHWND(IDC_NOGUIBOOT), FALSE); ::EnableWindow(GetDlgItemHWND(IDC_BOOTLOG), FALSE); ::EnableWindow(GetDlgItemHWND(IDC_BASEVIDEO), FALSE); ::EnableWindow(GetDlgItemHWND(IDC_SOS), FALSE); ::EnableWindow(GetDlgItemHWND(IDC_BOOTADVANCED), FALSE); ::EnableWindow(GetDlgItemHWND(IDC_SBNETWORK), FALSE); ::EnableWindow(GetDlgItemHWND(IDC_SBDSREPAIR), FALSE); ::EnableWindow(GetDlgItemHWND(IDC_SBMINIMAL), FALSE); ::EnableWindow(GetDlgItemHWND(IDC_SBMINIMALALT), FALSE); ::EnableWindow(GetDlgItemHWND(IDC_SETASDEFAULT), FALSE); ::EnableWindow(GetDlgItemHWND(IDC_CHECKBOOTPATHS), FALSE); ::EnableWindow(GetDlgItemHWND(IDC_EDITTIMEOUT), FALSE); }
m_stateCurrent = CPageBase::GetAppliedTabState(); }
//-------------------------------------------------------------------------
// Load the contents of the BOOT.INI file into our local structures.
//-------------------------------------------------------------------------
BOOL CPageBootIni::LoadBootIni(CString strFileName) { if (strFileName.IsEmpty()) strFileName = m_strFileName;
// Read the contents of the boot.ini file into a string.
HANDLE h = ::CreateFile(strFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (INVALID_HANDLE_VALUE == h) return FALSE;
CString strContents; DWORD dwNumberBytesRead, dwNumberBytesToRead = ::GetFileSize(h, NULL);
// The BOOT.INI file is ANSI, so we should read it and convert to Unicode.
char * szBuffer = new char[dwNumberBytesToRead + 1]; ::ZeroMemory((PVOID)szBuffer, dwNumberBytesToRead + 1); if (!::ReadFile(h, (LPVOID)szBuffer, dwNumberBytesToRead, &dwNumberBytesRead, NULL)) *szBuffer = _T('\0'); ::CloseHandle(h);
// Do the conversion.
USES_CONVERSION; LPTSTR szConverted = A2T(szBuffer); strContents = szConverted; delete [] szBuffer;
if (dwNumberBytesToRead != dwNumberBytesRead || strContents.IsEmpty()) return FALSE;
// Save the original contents of the file.
m_strOriginalContents = strContents;
// Parse the contents of the string into an array of strings (one for each line
// of the file).
m_arrayIniLines.RemoveAll(); m_arrayIniLines.SetSize(10, 10);
CString strLine; int nIndex = 0;
while (!strContents.IsEmpty()) { strLine = strContents.SpanExcluding(_T("\r\n")); if (!strLine.IsEmpty()) { m_arrayIniLines.SetAtGrow(nIndex, strLine); nIndex += 1; } strContents = strContents.Mid(strLine.GetLength()); strContents.TrimLeft(_T("\r\n")); }
// Look through the lines read from the INI file, searching for particular
// ones we'll want to make a note of.
m_nTimeoutIndex = m_nDefaultIndex = m_nMinOSIndex = m_nMaxOSIndex = -1; for (int i = 0; i <= m_arrayIniLines.GetUpperBound(); i++) { CString strScanLine = m_arrayIniLines[i]; strScanLine.MakeLower(); strScanLine.Replace(_T(" "), _T(""));
if (strScanLine.Find(_T("timeout=")) != -1) m_nTimeoutIndex = i; else if (strScanLine.Find(_T("default=")) != -1) m_nDefaultIndex = i;
if (m_nMinOSIndex != -1 && m_nMaxOSIndex == -1 && (strScanLine.IsEmpty() || strScanLine[0] == _T('['))) m_nMaxOSIndex = i - 1; else if (strScanLine.Find(_T("[operatingsystems]")) != -1) m_nMinOSIndex = i + 1; } if (m_nMinOSIndex != -1 && m_nMaxOSIndex == -1) m_nMaxOSIndex = i - 1;
return TRUE; }
//----------------------------------------------------------------------------
// Update the state of the controls on this tab to match the contents of the
// internal representation of the INI file.
//----------------------------------------------------------------------------
void CPageBootIni::SyncControlsToIni(BOOL fSyncEditField) { // We need to keep track of the extent of the strings in the list box
// (to handle a horizontal scroll bar). Code from MSDN.
DWORD dwExtent, dwMaxExtent = 0; TEXTMETRIC tm;
HDC hDCListBox = ::GetDC(GetDlgItemHWND(IDC_LISTBOOTINI)); HFONT hFontNew = (HFONT)::SendMessage(GetDlgItemHWND(IDC_LISTBOOTINI), WM_GETFONT, NULL, NULL); HFONT hFontOld = (HFONT)::SelectObject(hDCListBox, hFontNew); ::GetTextMetrics(hDCListBox, (LPTEXTMETRIC)&tm);
CDC dc; dc.Attach(hDCListBox); for (int i = 0; i <= m_arrayIniLines.GetUpperBound(); i++) if (!m_arrayIniLines[i].IsEmpty()) { CSize size = dc.GetTextExtent(m_arrayIniLines[i]); dwExtent = size.cx + tm.tmAveCharWidth; if (dwExtent > dwMaxExtent) dwMaxExtent = dwExtent; } dc.Detach();
::SelectObject(hDCListBox, hFontOld); ::ReleaseDC(GetDlgItemHWND(IDC_LISTBOOTINI), hDCListBox);
// Set the extent for the list box.
::SendMessage(GetDlgItemHWND(IDC_LISTBOOTINI), LB_SETHORIZONTALEXTENT, (WPARAM)dwMaxExtent, 0);
// First, add the lines from the boot ini into the list control.
::SendMessage(GetDlgItemHWND(IDC_LISTBOOTINI), LB_RESETCONTENT, 0, 0); for (int j = 0; j <= m_arrayIniLines.GetUpperBound(); j++) if (!m_arrayIniLines[j].IsEmpty()) ::SendMessage(GetDlgItemHWND(IDC_LISTBOOTINI), LB_ADDSTRING, 0, (LPARAM)(LPCTSTR)m_arrayIniLines[j]);
// Set the timeout value based on the boot.ini.
if (m_nTimeoutIndex != -1 && fSyncEditField) { CString strTimeout = m_arrayIniLines[m_nTimeoutIndex]; strTimeout.TrimLeft(_T("timeout= ")); m_fIgnoreEdit = TRUE; SetDlgItemText(IDC_EDITTIMEOUT, strTimeout); m_fIgnoreEdit = FALSE; } }
//----------------------------------------------------------------------------
// Update the controls based on the user's selection of a line.
//----------------------------------------------------------------------------
void CPageBootIni::SelectLine(int index) { if (index < m_nMinOSIndex) { ::SendMessage(GetDlgItemHWND(IDC_LISTBOOTINI), LB_SETCURSEL, m_nMinOSIndex, 0); SelectLine(m_nMinOSIndex); return; }
if (index > m_nMaxOSIndex) { ::SendMessage(GetDlgItemHWND(IDC_LISTBOOTINI), LB_SETCURSEL, m_nMaxOSIndex, 0); SelectLine(m_nMaxOSIndex); return; }
HWND hwndFocus = ::GetFocus();
::EnableWindow(GetDlgItemHWND(IDC_BOOTMOVEUP), (index > m_nMinOSIndex)); ::EnableWindow(GetDlgItemHWND(IDC_BOOTMOVEDOWN), (index < m_nMaxOSIndex));
if ((index <= m_nMinOSIndex) && hwndFocus == GetDlgItemHWND(IDC_BOOTMOVEUP)) NextDlgCtrl();
if ((index >= m_nMaxOSIndex) && hwndFocus == GetDlgItemHWND(IDC_BOOTMOVEDOWN)) PrevDlgCtrl();
CString strOS = m_arrayIniLines[index]; strOS.MakeLower();
CheckDlgButton(IDC_SAFEBOOT, (strOS.Find(_T("/safeboot")) != -1)); CheckDlgButton(IDC_NOGUIBOOT, (strOS.Find(_T("/noguiboot")) != -1)); CheckDlgButton(IDC_BOOTLOG, (strOS.Find(_T("/bootlog")) != -1)); CheckDlgButton(IDC_BASEVIDEO, (strOS.Find(_T("/basevideo")) != -1)); CheckDlgButton(IDC_SOS, (strOS.Find(_T("/sos")) != -1));
// If the line selected isn't for Whistler, then disable the controls.
// If the line is for Whistler or W2K, but it has the string "CMDCONS" in
// it, we shouldn't enable the controls.
BOOL fEnableControls = ((strOS.Find(_T("whistler")) != -1) || (strOS.Find(_T("windows 2000")) != -1)); fEnableControls |= ((strOS.Find(_T("windowsxp")) != -1) || (strOS.Find(_T("windows xp")) != -1)); fEnableControls |= (strOS.Find(_T("windows server 2003")) != -1); fEnableControls = fEnableControls && (strOS.Find(_T("cmdcons")) == -1); ::EnableWindow(GetDlgItemHWND(IDC_SAFEBOOT), fEnableControls); ::EnableWindow(GetDlgItemHWND(IDC_NOGUIBOOT), fEnableControls); ::EnableWindow(GetDlgItemHWND(IDC_BOOTLOG), fEnableControls); ::EnableWindow(GetDlgItemHWND(IDC_BASEVIDEO), fEnableControls); ::EnableWindow(GetDlgItemHWND(IDC_SOS), fEnableControls); ::EnableWindow(GetDlgItemHWND(IDC_BOOTADVANCED), fEnableControls);
BOOL fSafeboot = (strOS.Find(_T("/safeboot")) != -1); ::EnableWindow(GetDlgItemHWND(IDC_SBNETWORK), fSafeboot && fEnableControls); ::EnableWindow(GetDlgItemHWND(IDC_SBDSREPAIR), fSafeboot && fEnableControls); ::EnableWindow(GetDlgItemHWND(IDC_SBMINIMAL), fSafeboot && fEnableControls); ::EnableWindow(GetDlgItemHWND(IDC_SBMINIMALALT), fSafeboot && fEnableControls);
if (fSafeboot) { CheckDlgButton(IDC_SBNETWORK, (strOS.Find(_T("/safeboot:network")) != -1)); CheckDlgButton(IDC_SBDSREPAIR, (strOS.Find(_T("/safeboot:dsrepair")) != -1));
if (strOS.Find(_T("/safeboot:minimal")) != -1) { BOOL fAlternateShell = (strOS.Find(_T("/safeboot:minimal(alternateshell)")) != -1); CheckDlgButton(IDC_SBMINIMAL, !fAlternateShell); CheckDlgButton(IDC_SBMINIMALALT, fAlternateShell); } else { CheckDlgButton(IDC_SBMINIMAL, FALSE); CheckDlgButton(IDC_SBMINIMALALT, FALSE); }
int iSafeboot = strOS.Find(_T("/safeboot")); if (iSafeboot != -1) { m_strSafeBoot = strOS.Mid(iSafeboot + 1); m_strSafeBoot = m_strSafeBoot.SpanExcluding(_T(" /")); m_strSafeBoot = CString(_T("/")) + m_strSafeBoot; } }
// Check to see if the selected operating system is the default.
// Then enable the button accordingly.
BOOL fEnableDefault = FALSE; if (m_nDefaultIndex >= 0) { CString strDefault = m_arrayIniLines[m_nDefaultIndex]; int iEquals = strDefault.Find(_T('=')); if (iEquals != -1) { strDefault = strDefault.Mid(iEquals + 1); strDefault.MakeLower(); CString strCurrent = strOS.SpanExcluding(_T("="));
strDefault.TrimLeft(); strCurrent.TrimRight();
if (strDefault != strCurrent || index > m_nMinOSIndex) fEnableDefault = TRUE; } }
::EnableWindow(GetDlgItemHWND(IDC_SETASDEFAULT), fEnableDefault); if (!fEnableDefault && hwndFocus == GetDlgItemHWND(IDC_SETASDEFAULT)) NextDlgCtrl(); }
//-------------------------------------------------------------------------
// Add or remove the specified flag from the currently selected OS line.
//-------------------------------------------------------------------------
void CPageBootIni::ChangeCurrentOSFlag(BOOL fAdd, LPCTSTR szFlag) { int iSelection = (int)::SendMessage(GetDlgItemHWND(IDC_LISTBOOTINI), LB_GETCURSEL, 0, 0); CString strFlagPlusSpace = CString(_T(" ")) + szFlag; CString strNewLine;
if (iSelection == -1) return;
if (fAdd) { if (m_arrayIniLines[iSelection].Find(szFlag) != -1) { ASSERT(0 && "the flag is already there"); return; } strNewLine = m_arrayIniLines[iSelection] + strFlagPlusSpace; } else { int iIndex = m_arrayIniLines[iSelection].Find(strFlagPlusSpace); if (iIndex == -1) { ASSERT(0 && "there is no flag"); return; } strNewLine = m_arrayIniLines[iSelection].Left(iIndex); strNewLine += m_arrayIniLines[iSelection].Mid(iIndex + strFlagPlusSpace.GetLength()); }
m_arrayIniLines.SetAt(iSelection, strNewLine); UserMadeChange(); SyncControlsToIni(); ::SendMessage(GetDlgItemHWND(IDC_LISTBOOTINI), LB_SETCURSEL, iSelection, 0); }
//-------------------------------------------------------------------------
// Sets the "default=" line in the boot.ini.
//-------------------------------------------------------------------------
void CPageBootIni::SetDefaultOS(int iIndex) { if (m_nDefaultIndex == -1) return;
// Get the current string "default=xxxx". Locate the location of the
// '=' so we can replace the later half of the line.
CString strDefault = m_arrayIniLines[m_nDefaultIndex]; int iEquals = strDefault.Find(_T('=')); if (iEquals == -1) return;
CString strValue = m_arrayIniLines[iIndex].SpanExcluding(_T("=")); strValue.TrimRight();
CString strNewDefault = strDefault.Left(iEquals + 1) + strValue; m_arrayIniLines.SetAt(m_nDefaultIndex, strNewDefault); }
//-------------------------------------------------------------------------
// Write new contents to the BOOT.INI file.
//-------------------------------------------------------------------------
BOOL CPageBootIni::SetBootIniContents(const CString & strNewContents, const CString & strAddedExtension) { // Extra safety code.
if ((LPCTSTR)strNewContents == NULL || *((LPCTSTR)strNewContents) == _T('\0')) return FALSE;
// To write to the BOOT.INI file, we need to set it to have normal
// attributes. Save the attribute settings so we can restore them.
DWORD dwWritten, dwAttribs = ::GetFileAttributes(m_strFileName); ::SetFileAttributes(m_strFileName, FILE_ATTRIBUTE_NORMAL);
HANDLE h = ::CreateFile(m_strFileName, GENERIC_WRITE, 0, NULL, TRUNCATE_EXISTING, 0, NULL); if (INVALID_HANDLE_VALUE == h) { ::SetFileAttributes(m_strFileName, dwAttribs); return FALSE; }
// Convert the internal BOOT.INI representation (Unicode) to ANSI for writing.
USES_CONVERSION; LPSTR szBuffer = T2A((LPTSTR)(LPCTSTR)strNewContents);
// CreateFile with TRUNCATE_EXISTING seems to SOMETIMES not set the file length to
// zero, but to overwrite the existing file with zeroes and leave the pointer at
// the end of the file.
::SetFilePointer(h, 0, NULL, FILE_BEGIN); ::WriteFile(h, (void *)szBuffer, strNewContents.GetLength(), &dwWritten, NULL); ::SetEndOfFile(h); ::CloseHandle(h); ::SetFileAttributes(m_strFileName, dwAttribs);
return TRUE; }
//-------------------------------------------------------------------------
// We need to subclass the edit control to catch the enter key, so we
// can validate the data and not close MSConfig.
//-------------------------------------------------------------------------
CPageBootIni * pBootIniPage = NULL; // pointer to the page, so we can call member functions
WNDPROC pOldBootIniEditProc = NULL; // save old wndproc when we subclass edit control
LRESULT BootIniEditSubclassProc(HWND hwnd, UINT wm, WPARAM wp, LPARAM lp) { switch (wm) { case WM_GETDLGCODE: return DLGC_WANTALLKEYS;
case WM_CHAR: if (wp == VK_ESCAPE || wp == VK_RETURN) { if (pBootIniPage != NULL) { pBootIniPage->NextDlgCtrl(); return 0; } } else if (wp == VK_TAB) { if (pBootIniPage != NULL) { if (::GetAsyncKeyState(VK_SHIFT) == 0) pBootIniPage->NextDlgCtrl(); else pBootIniPage->PrevDlgCtrl(); return 0; } } break; }
if (pOldBootIniEditProc != NULL) // better not be null
return CallWindowProc(pOldBootIniEditProc, hwnd, wm, wp, lp); return 0; }
//-------------------------------------------------------------------------
// Initialize the boot.ini page. Read in the INI file, set up internal
// structures to represent the file, and update the controls to reflect
// the internal structures.
//-------------------------------------------------------------------------
extern BOOL fBasicControls; BOOL CPageBootIni::OnInitDialog() { CPropertyPage::OnInitDialog();
// Check the registry for a testing flag (which would mean we aren't
// operating on the real BOOT.INI file). Removed for release.
//
// CRegKey regkey;
// if (ERROR_SUCCESS == regkey.Open(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Shared Tools\\MSConfig")))
// {
// TCHAR szBoot[MAX_PATH];
// DWORD dwCount = MAX_PATH;
//
// if (ERROR_SUCCESS == regkey.QueryValue(szBoot, _T("boot.ini"), &dwCount))
// m_strFileName = szBoot;
// }
InitializePage();
if (fBasicControls) ::ShowWindow(GetDlgItemHWND(IDC_BOOTADVANCED), SW_HIDE);
// Subclass the edit control (to catch the enter key).
HWND hWndEdit = GetDlgItemHWND(IDC_EDITTIMEOUT); if (hWndEdit) { pOldBootIniEditProc = (WNDPROC)::GetWindowLongPtr(hWndEdit, GWLP_WNDPROC); pBootIniPage = this; ::SetWindowLongPtr(hWndEdit, GWLP_WNDPROC, (ULONG_PTR)(WNDPROC)&BootIniEditSubclassProc); }
m_fInitialized = TRUE; return TRUE; // return TRUE unless you set the focus to a control
}
//-------------------------------------------------------------------------
// Called when the user clicks move up or down.
//-------------------------------------------------------------------------
void CPageBootIni::OnBootMoveDown() { int iSelection = (int)::SendMessage(GetDlgItemHWND(IDC_LISTBOOTINI), LB_GETCURSEL, 0, 0); ASSERT(iSelection >= m_nMinOSIndex && iSelection < m_nMaxOSIndex); if (iSelection >= m_nMinOSIndex && iSelection < m_nMaxOSIndex) { CString strTemp = m_arrayIniLines[iSelection + 1]; m_arrayIniLines.SetAt(iSelection + 1, m_arrayIniLines[iSelection]); m_arrayIniLines.SetAt(iSelection, strTemp); UserMadeChange(); SyncControlsToIni(); ::SendMessage(GetDlgItemHWND(IDC_LISTBOOTINI), LB_SETCURSEL, iSelection + 1, 0); SelectLine(iSelection + 1); } }
void CPageBootIni::OnBootMoveUp() { int iSelection = (int)::SendMessage(GetDlgItemHWND(IDC_LISTBOOTINI), LB_GETCURSEL, 0, 0); ASSERT(iSelection > m_nMinOSIndex && iSelection <= m_nMaxOSIndex); if (iSelection > m_nMinOSIndex && iSelection <= m_nMaxOSIndex) { CString strTemp = m_arrayIniLines[iSelection - 1]; m_arrayIniLines.SetAt(iSelection - 1, m_arrayIniLines[iSelection]); m_arrayIniLines.SetAt(iSelection, strTemp); UserMadeChange(); SyncControlsToIni(); ::SendMessage(GetDlgItemHWND(IDC_LISTBOOTINI), LB_SETCURSEL, iSelection - 1, 0); SelectLine(iSelection - 1); } }
//-------------------------------------------------------------------------
// Called when the user clicks on a line in the list view.
//-------------------------------------------------------------------------
void CPageBootIni::OnSelChangeList() { SelectLine((int)::SendMessage(GetDlgItemHWND(IDC_LISTBOOTINI), LB_GETCURSEL, 0, 0)); }
//-------------------------------------------------------------------------
// The check boxes are handled uniformly - adding or removing a flag from
// the currently selected OS line.
//-------------------------------------------------------------------------
void CPageBootIni::OnClickedBase() { ChangeCurrentOSFlag(IsDlgButtonChecked(IDC_BASEVIDEO), _T("/basevideo")); }
void CPageBootIni::OnClickedBootLog() { ChangeCurrentOSFlag(IsDlgButtonChecked(IDC_BOOTLOG), _T("/bootlog")); }
void CPageBootIni::OnClickedNoGUIBoot() { ChangeCurrentOSFlag(IsDlgButtonChecked(IDC_NOGUIBOOT), _T("/noguiboot")); }
void CPageBootIni::OnClickedSOS() { ChangeCurrentOSFlag(IsDlgButtonChecked(IDC_SOS), _T("/sos")); }
//-------------------------------------------------------------------------
// The safeboot flag is a little more complicated, since it has an extra
// portion (from the radio buttons).
//-------------------------------------------------------------------------
void CPageBootIni::OnClickedSafeBoot() { CString strFlag(_T("/safeboot"));
if (IsDlgButtonChecked(IDC_SBNETWORK)) strFlag += _T(":network"); else if (IsDlgButtonChecked(IDC_SBDSREPAIR)) strFlag += _T(":dsrepair"); else if (IsDlgButtonChecked(IDC_SBMINIMALALT)) strFlag += _T(":minimal(alternateshell)"); else { strFlag += _T(":minimal"); CheckDlgButton(IDC_SBMINIMAL, 1); }
BOOL fSafeBoot = IsDlgButtonChecked(IDC_SAFEBOOT); ChangeCurrentOSFlag(fSafeBoot, strFlag); m_strSafeBoot = strFlag; ::EnableWindow(GetDlgItemHWND(IDC_SBNETWORK), fSafeBoot); ::EnableWindow(GetDlgItemHWND(IDC_SBDSREPAIR), fSafeBoot); ::EnableWindow(GetDlgItemHWND(IDC_SBMINIMAL), fSafeBoot); ::EnableWindow(GetDlgItemHWND(IDC_SBMINIMALALT), fSafeBoot); }
//-------------------------------------------------------------------------
// Clicking on one of the safeboot radio buttons requires a little extra
// processing, to remove the existing flag and add the new one.
//-------------------------------------------------------------------------
void CPageBootIni::OnClickedSBDSRepair() { ChangeCurrentOSFlag(FALSE, m_strSafeBoot); m_strSafeBoot = _T("/safeboot:dsrepair"); ChangeCurrentOSFlag(TRUE, m_strSafeBoot); }
void CPageBootIni::OnClickedSBMinimal() { ChangeCurrentOSFlag(FALSE, m_strSafeBoot); m_strSafeBoot = _T("/safeboot:minimal"); ChangeCurrentOSFlag(TRUE, m_strSafeBoot); }
void CPageBootIni::OnClickedSBMinimalAlt() { ChangeCurrentOSFlag(FALSE, m_strSafeBoot); m_strSafeBoot = _T("/safeboot:minimal(alternateshell)"); ChangeCurrentOSFlag(TRUE, m_strSafeBoot); }
void CPageBootIni::OnClickedSBNetwork() { ChangeCurrentOSFlag(FALSE, m_strSafeBoot); m_strSafeBoot = _T("/safeboot:network"); ChangeCurrentOSFlag(TRUE, m_strSafeBoot); }
//-------------------------------------------------------------------------
// As the user enters text in the timeout field, update the line in the
// ini file list box.
//-------------------------------------------------------------------------
void CPageBootIni::OnChangeEditTimeOut() { if (m_fIgnoreEdit) return;
if (m_nTimeoutIndex == -1) return;
CString strTimeout = m_arrayIniLines[m_nTimeoutIndex]; int iEquals = strTimeout.Find(_T('=')); if (iEquals == -1) return; while (strTimeout[iEquals + 1] == _T(' ') && (iEquals + 1) < strTimeout.GetLength()) iEquals++;
TCHAR szValue[MAX_PATH]; GetDlgItemText(IDC_EDITTIMEOUT, szValue, MAX_PATH); CString strNewTimeout = strTimeout.Left(iEquals + 1) + szValue; m_arrayIniLines.SetAt(m_nTimeoutIndex, strNewTimeout); UserMadeChange(); int iSelection = (int)::SendMessage(GetDlgItemHWND(IDC_LISTBOOTINI), LB_GETCURSEL, 0, 0); SyncControlsToIni(FALSE);
if (iSelection != -1) ::SendMessage(GetDlgItemHWND(IDC_LISTBOOTINI), LB_SETCURSEL, iSelection, 0); }
void CPageBootIni::OnKillFocusEditTimeOut() { TCHAR szValue[MAX_PATH]; GetDlgItemText(IDC_EDITTIMEOUT, szValue, MAX_PATH); CString strNewValue(_T("")); BOOL fGiveUpFocus = FALSE;
int iTimeout = _ttoi(szValue); if (iTimeout < 3 || iTimeout > 999) { CString strMessage, strCaption; strMessage.LoadString(IDS_TIMEOUTVALUE); strCaption.LoadString(IDS_APPCAPTION); MessageBox(strMessage, strCaption);
if (iTimeout < 3) strNewValue = _T("3"); else if (iTimeout > 999) strNewValue = _T("999"); } else if (szValue[0] == _T('0')) { // Remove leading zeros.
strNewValue.Format(_T("%d"), iTimeout); fGiveUpFocus = TRUE; }
if (!strNewValue.IsEmpty() && m_nTimeoutIndex != -1) { CString strTimeout = m_arrayIniLines[m_nTimeoutIndex]; int iEquals = strTimeout.Find(_T('=')); if (iEquals != -1) { while (strTimeout[iEquals + 1] == _T(' ') && (iEquals + 1) < strTimeout.GetLength()) iEquals++;
CString strNewTimeout = strTimeout.Left(iEquals + 1) + strNewValue; m_arrayIniLines.SetAt(m_nTimeoutIndex, strNewTimeout); UserMadeChange(); }
SetDlgItemText(IDC_EDITTIMEOUT, strNewValue); ::SendMessage(GetDlgItemHWND(IDC_EDITTIMEOUT), EM_SETSEL, (WPARAM)0, (LPARAM)-1); if (!fGiveUpFocus) GotoDlgCtrl(GetDlgItem(IDC_EDITTIMEOUT)); } }
//-------------------------------------------------------------------------
// Show the advanced options dialog box.
//-------------------------------------------------------------------------
void CPageBootIni::OnClickedBootAdvanced() { int iSelection = (int)::SendMessage(GetDlgItemHWND(IDC_LISTBOOTINI), LB_GETCURSEL, 0, 0); if (iSelection > 0) { CString strLine(m_arrayIniLines[iSelection]); CBootIniAdvancedDlg dlg;
if (dlg.ShowAdvancedOptions(strLine)) { m_arrayIniLines.SetAt(iSelection, strLine); UserMadeChange(); SyncControlsToIni(); ::SendMessage(GetDlgItemHWND(IDC_LISTBOOTINI), LB_SETCURSEL, iSelection, 0); } } }
//-------------------------------------------------------------------------
// If the user clicks "Set as Default", use the path information from the
// currently selected line to set the new "default=" line.
//-------------------------------------------------------------------------
void CPageBootIni::OnClickedSetAsDefault() { if (m_fIgnoreEdit) return;
// Move the currently selected line to the top of the [operating systems]
// section.
int iSelection = (int)::SendMessage(GetDlgItemHWND(IDC_LISTBOOTINI), LB_GETCURSEL, 0, 0); if (iSelection < m_nMinOSIndex || iSelection > m_nMaxOSIndex) return;
while (iSelection > m_nMinOSIndex) { CString strTemp = m_arrayIniLines[iSelection - 1]; m_arrayIniLines.SetAt(iSelection - 1, m_arrayIniLines[iSelection]); m_arrayIniLines.SetAt(iSelection, strTemp); iSelection -= 1; }
// Get the string from the selected line. Strip off everything after the '='.
SetDefaultOS(iSelection); UserMadeChange(); SyncControlsToIni(FALSE); ::SendMessage(GetDlgItemHWND(IDC_LISTBOOTINI), LB_SETCURSEL, iSelection, 0); SelectLine(iSelection); }
//-------------------------------------------------------------------------
// This attempts to programmatically check if each of the boot paths is
// valid. If an invalid path is found, the user is given the opportunity
// to remove it from the boot.ini file.
//-------------------------------------------------------------------------
void CPageBootIni::OnClickedCheckBootPaths() { BOOL fFoundBadLine = FALSE; BOOL fChangedFile = FALSE; BOOL fWinNTType, fWin9xType;
CString strCaption; strCaption.LoadString(IDS_APPCAPTION);
struct { LPCTSTR m_szSearch; BOOL * m_pType; } aOSType[] = { { _T("windows xp"), &fWinNTType }, { _T("windowsxp"), &fWinNTType }, { _T("windows nt"), &fWinNTType }, { _T("whistler"), &fWinNTType }, { _T("windows 2000"), &fWinNTType }, { _T("windows server 2003"), &fWinNTType }, { _T("microsoft windows"), &fWin9xType }, { NULL, NULL } };
// Scan through each of the operating system lines in the boot.ini file.
for (int i = m_nMinOSIndex; i <= m_nMaxOSIndex; i++) { CString strLine = m_arrayIniLines[i]; strLine.MakeLower();
// Try to figure out the type of the operating system line.
fWinNTType = FALSE; fWin9xType = FALSE;
for (int iType = 0; aOSType[iType].m_szSearch != NULL; iType++) if (strLine.Find(aOSType[iType].m_szSearch) != -1) { (*aOSType[iType].m_pType) = TRUE; break; }
// Strip off the '=' and everything after it in the boot line.
int iEquals = strLine.Find(_T('=')); if (iEquals == -1) continue; strLine = strLine.Left(iEquals); strLine.TrimRight(); if (strLine.IsEmpty()) continue;
// Depending on the type of the OS, we need to verify that it's
// installed differently.
if (fWin9xType) { // Look for the bootsect.dos file to see if this is a good drive.
CString strCheck(strLine); if (strCheck.Right(1) != CString(_T("\\"))) strCheck += CString(_T("\\")); strCheck += CString(_T("bootsect.dos")); if (FileExists(strCheck)) continue; } else if (fWinNTType) { // If this line is for a recovery console (i.e. the line as "bootsect.dat"
// in it), then look for the existence of that file.
if (strLine.Find(_T("bootsect.dat")) != -1) { if (FileExists(strLine)) continue; } else { // Look for the SYSTEM registry hive.
CString strCheck(strLine); if (strCheck.Right(1) != CString(_T("\\"))) strCheck += CString(_T("\\")); strCheck += CString(_T("system32\\config\\SYSTEM")); // Add the prefix to attempt to open an ARC path.
strCheck = CString(_T("\\\\?\\GLOBALROOT\\ArcName\\")) + strCheck;
if (FileExists(strCheck)) continue; } } else // this is not an OS type we can check
continue;
// If execution falls through to here, then the line in question was an OS
// we care about, and it looks like it's invalid. Give the user the opportunity
// to remove it from the BOOT.INI file.
CString strMessage; strMessage.Format(IDS_BADBOOTLINE, m_arrayIniLines[i]);
if (IDYES == MessageBox(strMessage, strCaption, MB_YESNO | MB_ICONQUESTION)) { m_arrayIniLines.RemoveAt(i); m_nMaxOSIndex -= 1;
// Check to see if the line we just removed is the default
// operating system.
CString strDefault = m_arrayIniLines[m_nDefaultIndex]; iEquals = strDefault.Find(_T('=')); if (iEquals != -1) { strDefault = strDefault.Mid(iEquals + 1); strDefault.TrimLeft(); if (strDefault.CompareNoCase(strLine) == 0) SetDefaultOS(m_nMinOSIndex); }
i -= 1; // so we look at the next line when the for loop increments i
fChangedFile = TRUE; }
fFoundBadLine = TRUE; }
if (!fFoundBadLine) Message(IDS_NOBADBOOTLINES); else if (fChangedFile) { UserMadeChange(); SyncControlsToIni(); if (m_nMinOSIndex != -1) { ::SendMessage(GetDlgItemHWND(IDC_LISTBOOTINI), LB_SETCURSEL, m_nMinOSIndex, 0); SelectLine(m_nMinOSIndex); } } }
//-------------------------------------------------------------------------
// Return the current state of the tab.
//-------------------------------------------------------------------------
CPageBase::TabState CPageBootIni::GetCurrentTabState() { if (!m_fInitialized) return GetAppliedTabState();
return m_stateCurrent; }
//-------------------------------------------------------------------------
// Applying the changes for the boot.ini tab means writing out the new
// file contents.
//
// The base class implementation is called to maintain the applied
// tab state.
//-------------------------------------------------------------------------
BOOL CPageBootIni::OnApply() { if (!m_fModified) return TRUE;
// Build up the new contents of the boot.ini file from the
// list. If there is no backup of the boot.ini file, make
// one (so the original can be restored). Then write the
// contents out to the file.
CString strNewContents; for (int i = 0; i <= m_arrayIniLines.GetUpperBound(); i++) if (!m_arrayIniLines[i].IsEmpty()) { if (m_nTimeoutIndex == i) { CString strTimeoutValue(m_arrayIniLines[i]); strTimeoutValue.TrimLeft(_T("TIMEOUTtimeout =")); int iTimeout = _ttoi(strTimeoutValue); if (iTimeout < 3 || iTimeout > 999) { if (iTimeout < 3) strTimeoutValue = _T("3"); else if (iTimeout > 999) strTimeoutValue = _T("999"); int iEquals = m_arrayIniLines[i].Find(_T('=')); if (iEquals != -1) { CString strNewTimeout = m_arrayIniLines[i].Left(iEquals + 1) + strTimeoutValue; m_arrayIniLines.SetAt(i, strNewTimeout); } } }
strNewContents += m_arrayIniLines[i] + _T("\r\n"); }
// If we are currently in a "NORMAL" state, then we want to make a new
// backup file (overwriting an existing one, if necessary). Otherwise,
// only make a backup if there isn't already one. This preserves a good
// backup when the user is making incremental changes.
HRESULT hr = BackupFile(m_strFileName, _T(".backup"), (GetAppliedTabState() == NORMAL)); if (FAILED(hr)) return FALSE;
SetBootIniContents(strNewContents); CPageBase::SetAppliedState(GetCurrentTabState()); m_fMadeChange = TRUE; return TRUE; }
//-------------------------------------------------------------------------
// Committing the changes means applying changes, then saving the current
// values to the registry with the commit flag. Refill the list.
//
// Then call the base class implementation.
//-------------------------------------------------------------------------
void CPageBootIni::CommitChanges() { OnApply(); m_stateCurrent = NORMAL;
::DeleteFile(GetBackupName(m_strFileName, _T(".backup")));
CPageBase::CommitChanges(); }
//-------------------------------------------------------------------------
// Set the overall state of the tab to normal or diagnostic.
//-------------------------------------------------------------------------
void CPageBootIni::SetNormal() { // Setting the BOOT.INI tab state to normal means that the original
// BOOT.INI file contents should be restored to the UI (not actually
// saved until the changes are applied). If a BOOT.INI backup file
// exists, we should reload the contents of it. If it doesn't exists,
// reload the contents of the real BOOT.INI.
//
// Note - if the state is already NORMAL, don't do anything.
if (m_stateCurrent == NORMAL) return;
CString strBackup = GetBackupName(m_strFileName, _T(".backup")); if (FileExists(strBackup)) LoadBootIni(strBackup); else LoadBootIni();
int iSelection = (int)::SendMessage(GetDlgItemHWND(IDC_LISTBOOTINI), LB_GETCURSEL, 0, 0); SyncControlsToIni(); if (iSelection > 0) { SelectLine(iSelection); ::SendMessage(GetDlgItemHWND(IDC_LISTBOOTINI), LB_SETCURSEL, iSelection, 0); }
UserMadeChange(); m_stateCurrent = NORMAL; }
void CPageBootIni::SetDiagnostic() { // Don't do anything.
}
void CPageBootIni::OnDestroy() { // Undo the subclass
pBootIniPage = NULL; HWND hWndEdit = GetDlgItemHWND(IDC_EDITTIMEOUT); if (pOldBootIniEditProc != NULL && hWndEdit) ::SetWindowLongPtr(hWndEdit, GWLP_WNDPROC, (ULONG_PTR)(WNDPROC)pOldBootIniEditProc);
CPropertyPage::OnDestroy(); }
|