Return to ReStart Setup Program Source Code
// RSsetupDlg.cpp : implementation file
//
// Copyright © 1999 - 2000 - 2005 Richard A. Ellingson
// http://www.createwindow.com
// mailto:CreateWindow.com@comcast.net
#include "stdafx.h"
#include "RSsetup.h"
#include "RSsetupDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CRSsetupDlg dialog
CRSsetupDlg::CRSsetupDlg(CWnd* pParent /*=NULL*/)
: CDialog(CRSsetupDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CRSsetupDlg)
m_csContents = _T("");
m_nShortcut = 0;
m_csURL = _T("");
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CRSsetupDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CRSsetupDlg)
DDX_Control(pDX, IDC_ENABLE, m_ctlEnableBtn);
DDX_Text(pDX, IDC_CONTENTS, m_csContents);
DDX_Radio(pDX, IDC_RESTART, m_nShortcut);
DDX_Text(pDX, IDC_URL, m_csURL);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CRSsetupDlg, CDialog)
//{{AFX_MSG_MAP(CRSsetupDlg)
ON_WM_SYSCOMMAND()
ON_WM_DESTROY()
ON_BN_CLICKED(IDC_ENABLE, OnEnable)
ON_BN_CLICKED(IDC_CREATE, OnCreate)
ON_BN_CLICKED(ID_APP_ABOUT, OnAppAbout)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_TIMER()
ON_BN_CLICKED(ID_HELP, OnHelp)
//}}AFX_MSG_MAP
ON_NOTIFY_EX(TTN_NEEDTEXT, 0, OnToolTipNotify)
ON_MESSAGE(MYMSG_CHECK_DOSSTART, OnCheckDosStart)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CRSsetupDlg message handlers
BOOL CRSsetupDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
// ******* Begin custom code *******
// We have a Minimize box on the dialog, but we don't want
// the Size and Maximize options on the system menu so disable them.
pSysMenu->EnableMenuItem(SC_SIZE, MF_GRAYED);
pSysMenu->EnableMenuItem(SC_MAXIMIZE, MF_GRAYED);
// ******* End custom code *******
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
// ******* Begin custom code *******
// We'll supply tool tips, so enable the feature.
EnableToolTips(TRUE);
// Set the disable text because we'll use it repeatedly.
m_csDisable = "@Exit rem - DosStart.bat is disabled for Restart shortcut." + CString(0x0d) + CString(0x0a);
// Get the text from DosStart.bat.
Read_DosStart();
// Set the Create Window URL
m_csURL = "http://www.createwindow.com";
// Send what we have to the dialog box.
UpdateData(SEND);
// We want to display a message box if we need to modify DosStart.bat right away.
// Post a message so that the message box doesn't appear until after the dialog.
PostMessage(MYMSG_CHECK_DOSSTART, 0, 0);
// ******* End custom code *******
return TRUE; // return TRUE unless you set the focus to a control
}
void CRSsetupDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
void CRSsetupDlg::OnDestroy()
{
WinHelp(0L, HELP_QUIT);
CDialog::OnDestroy();
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CRSsetupDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CRSsetupDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
// Everything above this line is AppWizard generated code
// except for a few lines in OnInitDialog()
// ******* Begin custom code *******
// Handle the Enable/Disable DosStart button
void CRSsetupDlg::OnEnable()
{
// Go get the DosStart text.
Read_DosStart();
// Enable/Disable DosStart.bat depending on the first five characters.
// Reset the Enable/Disable button caption accordingly.
if(m_csContents.Left(5) == ("@Exit"))
{
Enable_DosStart();
m_ctlEnableBtn.SetWindowText("&Disable DosStart.bat");
}
else
{
Disable_DosStart();
m_ctlEnableBtn.SetWindowText("&Enable DosStart.bat");
}
// Make the modification to DosStart.bat.
Write_DosStart();
}
// Handle the Create button
void CRSsetupDlg::OnCreate()
{
// Get the value of m_nShortcut from the dialog.
UpdateData(GET);
// Create the appropriate shortcut
// depending on which radio button is selected.
switch(m_nShortcut)
{
case 0:
Create_ReStart_Shortcut();
break;
case 1:
Create_ReBoot_Shortcut();
break;
case 2:
Create_Shutdown_Shortcut();
}
}
// Get the Windows directory and append the DosStart.bat filename.
CString CRSsetupDlg::Get_DosStart_Path()
{
char lpFilename[MAX_PATH];
GetWindowsDirectory(lpFilename, MAX_PATH);
return CString(lpFilename) + "\\DosStart.bat";
}
// Handler for Close program messages
void CRSsetupDlg::OnCancel()
{
// I like to override this function so the dialog
// doesn't close when the Escape key is pressed.
if(GetKeyState(VK_ESCAPE) & 128)
return;
CDialog::OnCancel();
}
// Remove the disable line from DosStart.bat
void CRSsetupDlg::Enable_DosStart()
{
// Don't bother if DosStart.bat is empty.
if(m_csContents.IsEmpty())
return;
// Create an end on line/return to use repeatedly.
CString eol(CString(0x0d) + CString(0x0a));
// Remove all disable lines, in case there are more than one.
while(m_csContents.Find(m_csDisable) != -1)
m_csContents = m_csContents.Mid(0, m_csContents.Find(m_csDisable)) +
m_csContents.Mid(m_csContents.Find(m_csDisable) + m_csDisable.GetLength());
// Now get rid of any blank lines that might be left over.
while(m_csContents.Find(eol + eol) != -1)
m_csContents = m_csContents.Mid(0, m_csContents.Find(eol + eol)) +
m_csContents.Mid(m_csContents.Find(eol + eol) + 2);
// We might have nothing but a blank line left
// so remove the last one.
if(m_csContents.Left(2) == eol)
m_csContents = m_csContents.Mid(2);
}
void CRSsetupDlg::Disable_DosStart()
{
// If DosStart.bat is empty, just add the disable line.
if(m_csContents.IsEmpty())
m_csContents = m_csDisable;
else
{
// If DosStart.bat isn't empty, check to see if it's already disabled
// or add the disable line as the first line.
if(m_csContents.Left(5) != "@Exit")
m_csContents = m_csDisable + m_csContents;
}
}
void CRSsetupDlg::Write_DosStart()
{
DWORD bytes_written;
HANDLE hFile = {NULL};
// Overwrite DosStart.bat if it already exsits.
hFile = CreateFile(Get_DosStart_Path(), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS,
FILE_FLAG_SEQUENTIAL_SCAN, NULL);
// Inform the user if we failed to open and couldn't write.
if(hFile == INVALID_HANDLE_VALUE)
{
MessageBox("Unable to write to the DosStart.bat file.", "ReStart setup");
return;
}
WriteFile(hFile, m_csContents, m_csContents.GetLength(), &bytes_written, NULL);
// We're done with the file handle so close it.
CloseHandle(hFile);
// The write might have failed, so inform the user.
if(m_csContents.GetLength() != (int)bytes_written)
{
MessageBox("Unable to write to the DosStart.bat file.", "ReStart setup");
return;
}
// If all we did was empty DosStart.bat, then display the empty message in the edit box.
if(m_csContents.IsEmpty())
m_csContents = "DosStart.bat is empty.";
// Send the text to the dialog.
UpdateData(SEND);
}
// Create the ReStart Shortcut.
void CRSsetupDlg::Create_ReStart_Shortcut()
{
HANDLE hFile = {NULL};
// Overwrite the shortcut on the Desktop if it already exists.
hFile = CreateFile(Get_Desktop_Path() + "Restart Windows.pif", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, NULL, NULL);
// Inform the user if we failed to open and couldn't write.
if(hFile == INVALID_HANDLE_VALUE)
{
MessageBox("An error occured while creating the shortcut.", "ReStart setup");
return;
}
DWORD written;
HRSRC hrbpif;
HGLOBAL hgbpif;
// The shortcuts use environment variables and they all work on all machines.
// Therefore, there's no reason to create them programmatically.
// Instead, they're stored as binary templates within the program.
// Get the template and load it into a global buffer.
hrbpif = FindResource(NULL, "#129", "Template");
hgbpif = LoadResource(NULL, hrbpif);
// Write the template into the file.
WriteFile(hFile, (LPCVOID) hgbpif, 967, &written, NULL);
// We're done with the file handle so close it.
// Note that the global buffer is released automatically.
CloseHandle(hFile);
// The write might have failed, so inform the user.
if(written != 967)
{
MessageBox("An error occured while creating the shortcut.", "ReStart setup");
return;
}
}
// Create the ReBoot Shortcut.
void CRSsetupDlg::Create_ReBoot_Shortcut()
{// Same notes as Create_ReStart_Shortcut()
HANDLE hFile = {NULL};
hFile = CreateFile(Get_Desktop_Path() + "ReBoot Windows.lnk", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, NULL, NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
MessageBox("An error occured while creating the shortcut.", "ReStart setup");
return;
}
DWORD written;
HRSRC hrbpif;
HGLOBAL hgbpif;
hrbpif = FindResource(NULL, "#130", "Template");
hgbpif = LoadResource(NULL, hrbpif);
WriteFile(hFile, (LPCVOID) hgbpif, 1188, &written, NULL);
CloseHandle(hFile);
if(written != 1188)
{
MessageBox("An error occured while creating the shortcut.", "ReStart setup");
return;
}
}
// Create the Shutdown Shortcut.
void CRSsetupDlg::Create_Shutdown_Shortcut()
{// Same notes as Create_ReStart_Shortcut()
HANDLE hFile = {NULL};
hFile = CreateFile(Get_Desktop_Path() + "ShutDown Windows.lnk", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, NULL, NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
MessageBox("An error occured while creating the shortcut.", "ReStart setup");
return;
}
DWORD written;
HRSRC hrbpif;
HGLOBAL hgbpif;
hrbpif = FindResource(NULL, "#131", "Template");
hgbpif = LoadResource(NULL, hrbpif);
WriteFile(hFile, (LPCVOID) hgbpif, 1188, &written, NULL);
CloseHandle(hFile);
if(written != 1188)
{
MessageBox("An error occured while creating the shortcut.", "ReStart setup");
return;
}
}
// Get the directory name for the Desktop
CString CRSsetupDlg::Get_Desktop_Path()
{
HKEY myKey;
DWORD data_len;
BOOL success;
CString csFileName;
// The directory name of the Desktop is stored in the registry.
if(RegOpenKeyEx(HKEY_CURRENT_USER,
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
NULL, KEY_QUERY_VALUE, &myKey) != ERROR_SUCCESS)
return ""; // Return nothing if we failed to find it.
// Find the length of the string.
if(success = !RegQueryValueEx(myKey, "Desktop", NULL, NULL, NULL, &data_len))
{
// If successful, retrieve the string itself.
success = !RegQueryValueEx(myKey, "Desktop", NULL, NULL,
(LPBYTE) csFileName.GetBuffer(data_len), &data_len);
// Clean up the CString after direct buffer access.
csFileName.ReleaseBuffer();
}
// Close the registry key
RegCloseKey(myKey);
// Append a backslash and return the path.
csFileName += "\\";
return csFileName;
}
// Handle the About button
void CRSsetupDlg::OnAppAbout()
{
// Display the About box.
CDialog(IDD_ABOUTBOX).DoModal();
}
// Handle tool tips on mouseover
BOOL CRSsetupDlg::OnToolTipNotify(UINT id, NMHDR *pNMHDR, LRESULT *pResult)
{
TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;
UINT nID =pNMHDR->idFrom;
if (pTTT->uFlags & TTF_IDISHWND)
{
// idFrom is actually the HWND of the tool
nID = ::GetDlgCtrlID((HWND)nID);
if(nID)
{
// Get the text from the String Table.
pTTT->lpszText = MAKEINTRESOURCE(nID);
pTTT->hinst = AfxGetResourceHandle();
return TRUE;
}
}
return FALSE;
}
void CRSsetupDlg::Read_DosStart()
{
DWORD bytes_read, dwFileSize;
HANDLE hFile = {NULL};
// Clear our edit box
m_csContents.Empty();
// Open DosStart.bat for reading.
hFile = CreateFile(Get_DosStart_Path(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_ALWAYS,
FILE_FLAG_SEQUENTIAL_SCAN, NULL);
// Inform the user if we failed.
if(hFile == INVALID_HANDLE_VALUE)
{
MessageBox("Unable to read the DosStart.bat file.", "ReStart setup");
return;
}
// Get the file size.
dwFileSize = GetFileSize(hFile, NULL);
// If it isn't empty, read it.
if(dwFileSize)
{
// Make buffer big enough to hold the whole thing
CString buff_data(' ', dwFileSize);
// Read the file into the buffer.
ReadFile(hFile, buff_data.GetBuffer(dwFileSize), dwFileSize, &bytes_read, NULL);
// Put the buffer text in the edit box.
m_csContents = buff_data;
// Always release the buffer after writing to it.
buff_data.ReleaseBuffer();
}
// We're done with the file handle so close it.
CloseHandle(hFile);
// The read might have failed, so inform the user.
if(dwFileSize != bytes_read)
{
MessageBox("Unable to read the DosStart.bat file.", "ReStart setup");
return;
}
}
void CRSsetupDlg::OnCheckDosStart(WPARAM wparam, LPARAM lparam)
{
// Create a temporary string with the edit box contents
// so we can work with it.
CString csTempContents(m_csContents);
// Create an end on line/return to use repeatedly.
CString eol(CString(0x0d) + CString(0x0a));
CString csLine;
CStringList m_cslDosStartList;
// Parse the temporary string, dumping each line into a list.
while(csTempContents.Find(eol) != -1)
{
csLine = csTempContents.Mid(0, csTempContents.Find(eol) +2);
csTempContents = csTempContents.Mid(csTempContents.Find(eol) +2);
m_cslDosStartList.AddTail(csLine);
}
POSITION pos1, pos2;
BOOL trufal(0);
BOOL bWrite(0);
CString csLow_Line;
// Set the Enable/Disable button caption.
m_ctlEnableBtn.SetWindowText("&Disable DosStart.bat");
// Empty the edit box, we'll reconstruct it from the list.
m_csContents.Empty();
// Iterate through the list.
pos1 = m_cslDosStartList.GetHeadPosition();
while(pos1)
{
// Save the current position in case we need to delete it.
pos2 = pos1;
// Get the current line and advance the position.
csLine = m_cslDosStartList.GetNext(pos1);
// Save a lower case copy so it's easier to search.
csLow_Line = csLine;
csLow_Line.MakeLower();
// Get rid of any preceding spaces.
csLow_Line.TrimLeft();
// If it's a blank line, delete it and set our write flag.
if(csLow_Line == eol)
{
bWrite++;
m_cslDosStartList.RemoveAt(pos2);
}
else // Otherwise, if it starts with an exit command...
if((csLow_Line.Left(5) == "@exit") || (csLow_Line.Left(4) == "exit"))
{
// Reset the Enable/Disable button caption.
m_ctlEnableBtn.SetWindowText("&Enable DosStart.bat");
// If it's the first line...
if(pos2 == m_cslDosStartList.GetHeadPosition())
{
// and it's our disable line, save it.
if(csLine == m_csDisable)
m_csContents += csLine;
else // otherwise, delete it.
m_cslDosStartList.RemoveAt(pos2);
}
else // If it's not the first line...
{
// If we haven't informed the user, display a message
// indicating that we'll fix it.
if(!trufal)
MessageBox("DosStart.bat contains an Exit command, but it's not on the first line.\nClick OK to fix this condition.",
"ReStart setup");
// Now remove the line and set the write flag.
m_cslDosStartList.RemoveAt(pos2);
bWrite++;
}
// Set a flag so we don't display the message more than once
// and we know to insert the disable line as the first line.
trufal++;
}
else // If the line doesn't start with an exit command, save it.
m_csContents += m_cslDosStartList.GetAt(pos2);
}
// If we found an exit command and it wasn't our disable line as the first line
// then insert the disable line as the first line.
if(trufal)
{
if(m_cslDosStartList.GetAt(m_cslDosStartList.GetHeadPosition()) != m_csDisable)
{
m_cslDosStartList.AddHead(m_csDisable);
m_csContents = m_csDisable + m_csContents;
// Set the write flag.
bWrite++;
}
}
// If we ended up with an empty DosStart.bat,
// indicate so in the edit box.
if(m_csContents.IsEmpty())
{
m_csContents = "DosStart.bat is empty.";
// Send it to the dialog.
UpdateData(SEND);
}
// If we modified DosStart.bat, rewrite it.
if(bWrite)
Write_DosStart();
}
// Handle the Help button.
void CRSsetupDlg::OnHelp()
{
OnHelpFinder();
}
// ******* End custom code *******