windows-nt/Source/XPSP1/NT/admin/pchealth/sysinfo/msconfig/exe/pagestartup.cpp

1655 lines
45 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
#include "stdafx.h"
#include "PageStartup.h"
#include "MSConfigState.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CPageStartup property page
IMPLEMENT_DYNCREATE(CPageStartup, CPropertyPage)
CPageStartup::CPageStartup() : CPropertyPage(CPageStartup::IDD)
{
//{{AFX_DATA_INIT(CPageStartup)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
CPageStartup::~CPageStartup()
{
}
void CPageStartup::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CPageStartup)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CPageStartup, CPropertyPage)
//{{AFX_MSG_MAP(CPageStartup)
ON_WM_DESTROY()
ON_NOTIFY(LVN_ITEMCHANGED, IDC_LISTSTARTUP, OnItemChangedList)
ON_BN_CLICKED(IDC_BUTTONSUDISABLEALL, OnButtonDisableAll)
ON_BN_CLICKED(IDC_BUTTONSUENABLEALL, OnButtonEnableAll)
ON_NOTIFY(NM_SETFOCUS, IDC_LISTSTARTUP, OnSetFocusList)
ON_BN_CLICKED(IDC_BUTTONSURESTORE, OnButtonRestore)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CPageStartup message handlers
//-----------------------------------------------------------------------------
// Load the list of startup items.
//-----------------------------------------------------------------------------
void CPageStartup::LoadStartupList()
{
m_fIgnoreListChanges = TRUE;
EmptyList(FALSE);
m_iNextPosition = 0;
LoadStartupListLiveItems();
LoadStartupListDisabledItems();
m_fIgnoreListChanges = FALSE;
}
//-----------------------------------------------------------------------------
// Load the list of items which are actually being started on this system.
//-----------------------------------------------------------------------------
void CPageStartup::LoadStartupListLiveItems()
{
LoadStartupListLiveItemsRunKey();
LoadStartupListLiveItemsStartup();
LoadStartupListLiveItemsWinIniKey();
}
//-----------------------------------------------------------------------------
// Look under the Run registry key for startup items.
//-----------------------------------------------------------------------------
void CPageStartup::LoadStartupListLiveItemsRunKey()
{
LPCTSTR szRunKey = _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
HKEY ahkey[] = { HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER, NULL };
TCHAR szValueName[MAX_PATH], szValue[MAX_PATH];
DWORD dwSize;
CRegKey regkey;
for (int i = 0; ahkey[i] != NULL; i++)
{
// Try to open the Run registry key.
if (ERROR_SUCCESS != regkey.Open(ahkey[i], szRunKey, KEY_READ))
continue;
// Get the number of keys under the Run key and look at each one.
DWORD dwValueCount;
if (ERROR_SUCCESS != ::RegQueryInfoKey((HKEY)regkey, NULL, NULL, NULL, NULL, NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL))
{
regkey.Close();
continue;
}
for (DWORD dwKey = 0; dwKey < dwValueCount; dwKey++)
{
dwSize = MAX_PATH;
if (ERROR_SUCCESS != ::RegEnumValue((HKEY)regkey, dwKey, szValueName, &dwSize, NULL, NULL, NULL, NULL))
continue;
dwSize = MAX_PATH;
if (ERROR_SUCCESS != regkey.QueryValue(szValue, szValueName, &dwSize))
continue;
// We don't want to show MSConfig in the startup item list.
CString strTemp(szValue);
strTemp.MakeLower();
if (strTemp.Find(_T("msconfig.exe")) != -1)
continue;
// TBD - verify that the file exists?
// To get the name of this startup item, we'll take the command and
// strip off everything but the filename (without the extension).
CString strName(szValue);
GetCommandName(strName);
// Create the startup item and insert it in the list.
CStartupItemRegistry * pItem = new CStartupItemRegistry(ahkey[i], szRunKey, strName, szValueName, szValue);
InsertStartupItem(pItem);
}
regkey.Close();
}
}
//-----------------------------------------------------------------------------
// Look under the registry for the mapped win.ini file and check out its run
// and load items.
//-----------------------------------------------------------------------------
void CPageStartup::LoadStartupListLiveItemsWinIniKey()
{
LPCTSTR aszValueNames[] = { _T("Run"), _T("Load"), NULL };
CRegKey regkey;
TCHAR szValue[MAX_PATH * 4];
DWORD dwSize;
LPCTSTR szKeyName = _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows");
HKEY hkey = HKEY_CURRENT_USER;
if (ERROR_SUCCESS != regkey.Open(hkey, szKeyName, KEY_READ))
return;
for (int i = 0; aszValueNames[i] != NULL; i++)
{
dwSize = MAX_PATH * 4;
if (ERROR_SUCCESS != regkey.QueryValue(szValue, aszValueNames[i], &dwSize))
continue;
// The string we get back is a comma delimited list of programs. We need
// to parse them into individual programs.
CString strLine(szValue);
while (!strLine.IsEmpty())
{
CString strItem = strLine.SpanExcluding(_T(","));
if (!strItem.IsEmpty())
{
// Create the startup item and insert it in the list.
CString strCommandName(strItem);
GetCommandName(strCommandName);
CStartupItemRegistry * pItem = new CStartupItemRegistry(szKeyName, strCommandName, aszValueNames[i], strItem);
InsertStartupItem(pItem);
// Trim the item of the line.
strLine = strLine.Mid(strItem.GetLength());
}
strLine.TrimLeft(_T(" ,"));
}
}
regkey.Close();
}
//-----------------------------------------------------------------------------
// Look in the startup folder for items.
//-----------------------------------------------------------------------------
void CPageStartup::LoadStartupListLiveItemsStartup()
{
LPCTSTR szRunKey = _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders");
HKEY ahkey[] = { HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER, NULL };
LPCTSTR aszRunValue[] = { _T("Common Startup"), _T("Startup"), NULL };
CRegKey regkey;
TCHAR szStartupFolderDir[MAX_PATH];
TCHAR szStartupFileSpec[MAX_PATH];
DWORD dwSize;
for (int i = 0; ahkey[i] != NULL; i++)
{
// Try to open the registry key.
if (ERROR_SUCCESS != regkey.Open(ahkey[i], szRunKey, KEY_READ))
continue;
// Get the path for the startup item folder.
dwSize = MAX_PATH;
if (aszRunValue[i] == NULL || ERROR_SUCCESS != regkey.QueryValue(szStartupFolderDir, aszRunValue[i], &dwSize))
{
regkey.Close();
continue;
}
regkey.Close();
// Append the filespec on the end of the directory.
_tmakepath(szStartupFileSpec, NULL, szStartupFolderDir, _T("*.*"), NULL);
// Examine all of the files in the directory.
WIN32_FIND_DATA fd;
HANDLE hFind = FindFirstFile(szStartupFileSpec, &fd);
if (hFind != INVALID_HANDLE_VALUE)
{
do
{
// We want to ignore the desktop.ini file which might appear in startup.
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) == 0 || _tcsicmp(fd.cFileName, _T("desktop.ini")) != 0)
{
// We only want to examine files which aren't directories.
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
{
CStartupItemFolder * pItem = new CStartupItemFolder;
if (pItem)
{
if (pItem->Create(fd, ahkey[i], szRunKey, aszRunValue[i], szStartupFolderDir))
this->InsertStartupItem(pItem);
else
delete pItem;
}
}
}
} while (FindNextFile(hFind, &fd));
FindClose(hFind);
}
}
}
//-----------------------------------------------------------------------------
// Load the list of items which were being started on this system, but which
// we've disabled. This list is maintained in the registry.
//-----------------------------------------------------------------------------
void CPageStartup::LoadStartupListDisabledItems()
{
CRegKey regkey;
regkey.Attach(GetRegKey(_T("startupreg")));
if ((HKEY)regkey != NULL)
{
DWORD dwKeyCount, dwSize;
TCHAR szKeyName[MAX_PATH];
if (ERROR_SUCCESS == ::RegQueryInfoKey((HKEY)regkey, NULL, NULL, NULL, &dwKeyCount, NULL, NULL, NULL, NULL, NULL, NULL, NULL))
{
for (DWORD dwKey = 0; dwKey < dwKeyCount; dwKey++)
{
dwSize = MAX_PATH;
if (ERROR_SUCCESS != ::RegEnumKeyEx((HKEY)regkey, dwKey, szKeyName, &dwSize, NULL, NULL, NULL, NULL))
continue;
CRegKey regkeyItem;
if (ERROR_SUCCESS == regkeyItem.Open((HKEY)regkey, szKeyName, KEY_READ))
{
CStartupItemRegistry * pItem = new CStartupItemRegistry;
if (pItem->Create(szKeyName, (HKEY)regkeyItem))
InsertStartupItem(pItem);
else
delete pItem;
regkeyItem.Close();
}
}
}
regkey.Close();
}
regkey.Attach(GetRegKey(_T("startupfolder")));
if ((HKEY)regkey != NULL)
{
DWORD dwKeyCount, dwSize;
TCHAR szKeyName[MAX_PATH];
if (ERROR_SUCCESS == ::RegQueryInfoKey((HKEY)regkey, NULL, NULL, NULL, &dwKeyCount, NULL, NULL, NULL, NULL, NULL, NULL, NULL))
{
for (DWORD dwKey = 0; dwKey < dwKeyCount; dwKey++)
{
dwSize = MAX_PATH;
if (ERROR_SUCCESS != ::RegEnumKeyEx((HKEY)regkey, dwKey, szKeyName, &dwSize, NULL, NULL, NULL, NULL))
continue;
CRegKey regkeyItem;
if (ERROR_SUCCESS == regkeyItem.Open((HKEY)regkey, szKeyName, KEY_READ))
{
CStartupItemFolder * pItem = new CStartupItemFolder;
if (pItem->Create(szKeyName, (HKEY)regkeyItem))
InsertStartupItem(pItem);
else
delete pItem;
regkeyItem.Close();
}
}
}
regkey.Close();
}
}
//-----------------------------------------------------------------------------
// Take a command line and strip off everything except the command name.
//-----------------------------------------------------------------------------
void CPageStartup::GetCommandName(CString & strCommand)
{
// Strip off the path information.
int iLastBackslash = strCommand.ReverseFind(_T('\\'));
if (iLastBackslash != -1)
strCommand = strCommand.Mid(iLastBackslash + 1);
// Strip off the extension and any flags.
int iDot = strCommand.Find(_T('.'));
if (iDot != -1)
{
if (iDot != 0)
strCommand = strCommand.Left(iDot);
else
strCommand.Empty();
}
}
//-----------------------------------------------------------------------------
// Insert the specified item in the startup list. The caller is then not
// responsible for deleting the item.
//-----------------------------------------------------------------------------
void CPageStartup::InsertStartupItem(CStartupItem * pItem)
{
ASSERT(pItem);
if (pItem == NULL)
return;
// Get the strings to add to the list view.
CString strItem, strLocation, strCommand;
pItem->GetDisplayInfo(strItem, strLocation, strCommand);
// Insert the item in the list view.
LV_ITEM lvi;
memset(&lvi, 0, sizeof(lvi));
lvi.mask = LVIF_TEXT | LVIF_PARAM;
lvi.iItem = m_iNextPosition;
lvi.pszText = (LPTSTR)(LPCTSTR)strItem;
lvi.iSubItem = 0;
lvi.lParam = (LPARAM)pItem;
m_iNextPosition = ListView_InsertItem(m_list.m_hWnd, &lvi);
ListView_SetItemText(m_list.m_hWnd, m_iNextPosition, 1, (LPTSTR)(LPCTSTR)strCommand);
ListView_SetItemText(m_list.m_hWnd, m_iNextPosition, 2, (LPTSTR)(LPCTSTR)strLocation);
ListView_SetCheckState(m_list.m_hWnd, m_iNextPosition, pItem->IsLive());
m_iNextPosition++;
}
//-----------------------------------------------------------------------------
// Remove all the items from the list view (freeing the objects pointed to
// by the LPARAM).
//-----------------------------------------------------------------------------
void CPageStartup::EmptyList(BOOL fFreeMemoryOnly)
{
LVITEM lvi;
lvi.mask = LVIF_PARAM;
lvi.iSubItem = 0;
for (int i = ListView_GetItemCount(m_list.m_hWnd) - 1; i >= 0; i--)
{
lvi.iItem = i;
if (ListView_GetItem(m_list.m_hWnd, &lvi))
{
CStartupItem * pItem = (CStartupItem *)lvi.lParam;
if (pItem)
delete pItem;
// If we're leaving the list with these items, we better
// not do a double delete.
if (fFreeMemoryOnly)
{
lvi.lParam = 0;
ListView_SetItem(m_list.m_hWnd, &lvi);
}
}
}
if (!fFreeMemoryOnly)
ListView_DeleteAllItems(m_list.m_hWnd);
}
//-----------------------------------------------------------------------------
// Set the state of all of the items in the list.
//-----------------------------------------------------------------------------
void CPageStartup::SetEnableForList(BOOL fEnable)
{
HWND hwndFocus = ::GetFocus();
LVITEM lvi;
lvi.mask = LVIF_PARAM;
lvi.iSubItem = 0;
for (int i = ListView_GetItemCount(m_list.m_hWnd) - 1; i >= 0; i--)
ListView_SetCheckState(m_list.m_hWnd, i, fEnable);
::EnableWindow(GetDlgItemHWND(IDC_BUTTONSUDISABLEALL), fEnable);
if (!fEnable && hwndFocus == GetDlgItemHWND(IDC_BUTTONSUDISABLEALL))
PrevDlgCtrl();
::EnableWindow(GetDlgItemHWND(IDC_BUTTONSUENABLEALL), !fEnable);
if (fEnable && hwndFocus == GetDlgItemHWND(IDC_BUTTONSUENABLEALL))
NextDlgCtrl();
}
//============================================================================
// The CStartupItemRegistry class is used to encapsulate an individual startup
// stored in the registry.
//============================================================================
//----------------------------------------------------------------------------
// Construct this flavor of startup item.
//----------------------------------------------------------------------------
CStartupItemRegistry::CStartupItemRegistry()
{
m_hkey = NULL;
m_fIniMapping = FALSE;
}
CStartupItemRegistry::CStartupItemRegistry(HKEY hkey, LPCTSTR szKey, LPCTSTR szName, LPCTSTR szValueName, LPCTSTR szValue)
{
m_fIniMapping = FALSE;
m_fLive = TRUE;
m_strItem = szName;
m_strLocation = szKey;
m_strCommand = szValue;
// Add the HKEY to the location.
if (hkey == HKEY_LOCAL_MACHINE)
m_strLocation = CString(_T("HKLM\\")) + m_strLocation;
else if (hkey == HKEY_CURRENT_USER)
m_strLocation = CString(_T("HKCU\\")) + m_strLocation;
m_hkey = hkey;
m_strKey = szKey;
m_strValueName = szValueName;
}
//----------------------------------------------------------------------------
// This constructor is specifically for items under the INI file registry
// mapping.
//----------------------------------------------------------------------------
CStartupItemRegistry::CStartupItemRegistry(LPCTSTR szKey, LPCTSTR szName, LPCTSTR szValueName, LPCTSTR szValue)
{
m_fIniMapping = TRUE;
m_fLive = TRUE;
m_strItem = szName;
m_strLocation = szKey;
m_strCommand = szValue;
m_strLocation = CString(_T("HKCU\\")) + m_strLocation + CString(_T(":")) + szValueName;
m_hkey = HKEY_CURRENT_USER;
m_strKey = szKey;
m_strValueName = szValueName;
}
//----------------------------------------------------------------------------
// Enable or disable the startup item in the registry.
//----------------------------------------------------------------------------
BOOL CStartupItemRegistry::SetEnable(BOOL fEnable)
{
if (fEnable == IsLive())
return FALSE;
CRegKey regkey;
if (ERROR_SUCCESS != regkey.Open(m_hkey, m_strKey, KEY_ALL_ACCESS))
return FALSE;
LONG lReturnCode = ERROR_SUCCESS + 1; // need to initialize it to not ERROR_SUCCESS
if (m_fIniMapping == FALSE)
{
// Create or delete the registry key from the data stored in
// this object.
if (fEnable)
lReturnCode = regkey.SetValue(m_strCommand, m_strValueName);
else
lReturnCode = regkey.DeleteValue(m_strValueName);
}
else
{
// This item is an INI file mapping item (which means there
// might be more than one item on this line).
TCHAR szValue[MAX_PATH * 4];
DWORD dwSize = MAX_PATH * 4;
if (ERROR_SUCCESS == regkey.QueryValue(szValue, m_strValueName, &dwSize))
{
CString strValue(szValue);
if (fEnable)
{
if (!strValue.IsEmpty())
strValue += CString(_T(", "));
strValue += m_strCommand;
}
else
{
// The harder case - we need to remove the item, and possibly commas.
int iCommand = strValue.Find(m_strCommand);
if (iCommand != -1)
{
CString strNewValue;
if (iCommand > 0)
{
strNewValue = strValue.Left(iCommand);
strNewValue.TrimRight(_T(", "));
}
if (strValue.GetLength() > (m_strCommand.GetLength() + iCommand))
{
if (!strNewValue.IsEmpty())
strNewValue += CString(_T(", "));
CString strRemainder(strValue.Mid(iCommand + m_strCommand.GetLength()));
strRemainder.TrimLeft(_T(", "));
strNewValue += strRemainder;
}
strValue = strNewValue;
}
}
lReturnCode = regkey.SetValue(strValue, m_strValueName);
}
}
regkey.Close();
if (lReturnCode != ERROR_SUCCESS)
return FALSE;
// Delete or create the registry representation of this item.
// This representation persists the startup item when it has
// been deleted.
regkey.Attach(GetRegKey(_T("startupreg")));
if ((HKEY)regkey != NULL)
{
if (fEnable)
regkey.DeleteSubKey(m_strValueName);
else
{
regkey.SetKeyValue(m_strValueName, m_strKey, _T("key"));
regkey.SetKeyValue(m_strValueName, m_strItem, _T("item"));
if (m_hkey == HKEY_LOCAL_MACHINE)
regkey.SetKeyValue(m_strValueName, _T("HKLM"), _T("hkey"));
else
regkey.SetKeyValue(m_strValueName, _T("HKCU"), _T("hkey"));
regkey.SetKeyValue(m_strValueName, m_strCommand, _T("command"));
regkey.SetKeyValue(m_strValueName, m_fIniMapping ? _T("1") : _T("0"), _T("inimapping"));
}
regkey.Close();
}
m_fLive = fEnable;
return TRUE;
}
//----------------------------------------------------------------------------
// Create the startup item from the registry representation of the item.
//----------------------------------------------------------------------------
BOOL CStartupItemRegistry::Create(LPCTSTR szKeyName, HKEY hkey)
{
if (hkey == NULL)
return FALSE;
CRegKey regkey;
regkey.Attach(hkey);
if ((HKEY)regkey == NULL)
return FALSE;
// Restore all of the values from the registry.
TCHAR szValue[MAX_PATH];
DWORD dwSize;
dwSize = MAX_PATH;
if (ERROR_SUCCESS != regkey.QueryValue(szValue, _T("key"), &dwSize))
{
regkey.Detach();
return FALSE;
}
m_strKey = szValue;
dwSize = MAX_PATH;
if (ERROR_SUCCESS != regkey.QueryValue(szValue, _T("command"), &dwSize))
{
regkey.Detach();
return FALSE;
}
m_strCommand = szValue;
dwSize = MAX_PATH;
if (ERROR_SUCCESS != regkey.QueryValue(szValue, _T("item"), &dwSize))
{
regkey.Detach();
return FALSE;
}
m_strItem = szValue;
dwSize = MAX_PATH;
if (ERROR_SUCCESS != regkey.QueryValue(szValue, _T("hkey"), &dwSize))
{
regkey.Detach();
return FALSE;
}
if (_tcscmp(szValue, _T("HKLM")) == 0)
m_hkey = HKEY_LOCAL_MACHINE;
else
m_hkey = HKEY_CURRENT_USER;
dwSize = MAX_PATH;
if (ERROR_SUCCESS != regkey.QueryValue(szValue, _T("inimapping"), &dwSize))
{
regkey.Detach();
return FALSE;
}
if (_tcscmp(szValue, _T("0")) == 0)
m_fIniMapping = FALSE;
else
m_fIniMapping = TRUE;
regkey.Detach();
m_strLocation = m_strKey;
m_strValueName = szKeyName;
m_fLive = FALSE;
return TRUE;
}
//----------------------------------------------------------------------------
// Remove all the entries persisted in the registry.
//----------------------------------------------------------------------------
void CStartupItemRegistry::RemovePersistedEntries()
{
CRegKey regkey;
regkey.Attach(GetRegKey());
if ((HKEY)regkey != NULL)
regkey.RecurseDeleteKey(_T("startupreg"));
}
//============================================================================
// The CStartupItemFolder class is used to encapsulate an individual startup
// stored in the startup folder.
//============================================================================
CStartupItemFolder::CStartupItemFolder()
{
}
//----------------------------------------------------------------------------
// Enable or disable this startup item. Since the item is an actual file in
// a folder, disabling it will mean copying that file to a backup folder and
// creating a registry entry for it. Enabling will mean copying the file
// back to the appropriate startup folder and deleting the registry entry.
//----------------------------------------------------------------------------
BOOL CStartupItemFolder::SetEnable(BOOL fEnable)
{
if (fEnable == IsLive())
return FALSE;
// Copy the file (from or to the backup directory).
if (fEnable)
{
m_strBackupPath = GetBackupName(m_strFilePath, m_strLocation);
::CopyFile(m_strBackupPath, m_strFilePath, FALSE);
}
else
{
BackupFile(m_strFilePath, m_strLocation, TRUE);
m_strBackupPath = GetBackupName(m_strFilePath, m_strLocation);
}
// Update the registry for the new state. If we are making the file
// disabled, then we need to save both the original path and the
// backed up path (and the standard startup item stuff). Otherwise
// just delete the key.
CRegKey regkey;
regkey.Attach(GetRegKey(_T("startupfolder")));
if ((HKEY)regkey == NULL)
return FALSE;
// The name for the registry key just needs to be unique. And not
// have any backslashes in it.
CString strRegkey(m_strFilePath);
strRegkey.Replace(_T("\\"), _T("^"));
if (fEnable)
{
regkey.DeleteSubKey(strRegkey);
::DeleteFile(m_strBackupPath);
}
else
{
regkey.SetKeyValue(strRegkey, m_strFilePath, _T("path"));
regkey.SetKeyValue(strRegkey, m_strBackupPath, _T("backup"));
regkey.SetKeyValue(strRegkey, m_strLocation, _T("location"));
regkey.SetKeyValue(strRegkey, m_strCommand, _T("command"));
regkey.SetKeyValue(strRegkey, m_strItem, _T("item"));
::DeleteFile(m_strFilePath);
}
m_fLive = fEnable;
return TRUE;
}
//----------------------------------------------------------------------------
// Load the disabled startup item from the registry.
//----------------------------------------------------------------------------
BOOL CStartupItemFolder::Create(LPCTSTR szKeyName, HKEY hkey)
{
if (hkey == NULL)
return FALSE;
CRegKey regkey;
regkey.Attach(hkey);
if ((HKEY)regkey == NULL)
return FALSE;
// Restore all of the values from the registry.
TCHAR szValue[MAX_PATH];
DWORD dwSize;
dwSize = MAX_PATH;
if (ERROR_SUCCESS != regkey.QueryValue(szValue, _T("path"), &dwSize))
{
regkey.Detach();
return FALSE;
}
m_strFilePath = szValue;
dwSize = MAX_PATH;
if (ERROR_SUCCESS != regkey.QueryValue(szValue, _T("backup"), &dwSize))
{
regkey.Detach();
return FALSE;
}
m_strBackupPath = szValue;
dwSize = MAX_PATH;
if (ERROR_SUCCESS != regkey.QueryValue(szValue, _T("location"), &dwSize))
{
regkey.Detach();
return FALSE;
}
m_strLocation = szValue;
dwSize = MAX_PATH;
if (ERROR_SUCCESS != regkey.QueryValue(szValue, _T("command"), &dwSize))
{
regkey.Detach();
return FALSE;
}
m_strCommand = szValue;
dwSize = MAX_PATH;
if (ERROR_SUCCESS != regkey.QueryValue(szValue, _T("item"), &dwSize))
{
regkey.Detach();
return FALSE;
}
m_strItem = szValue;
regkey.Detach();
m_fLive = FALSE;
return TRUE;
}
//----------------------------------------------------------------------------
// Create the startup item from the file found in the folder. If the file
// is a shortcut, get the information about the target.
//----------------------------------------------------------------------------
BOOL CStartupItemFolder::Create(const WIN32_FIND_DATA & fd, HKEY hkey, LPCTSTR szRegPathToFolder, LPCTSTR szFolder, LPCTSTR szDir)
{
// We want to save the path to the file in the startup folder (even if
// it is a shortcut).
m_strFilePath = szDir;
if (m_strFilePath.Right(1) != CString(_T("\\")))
m_strFilePath += CString(_T("\\"));
m_strFilePath += fd.cFileName;
// Look at the file to determine how to handle it.
CString strFile(fd.cFileName);
strFile.MakeLower();
if (strFile.Right(4) == CString(_T(".lnk")))
{
// The file is a shortcut to a different command. Show that command.
CIconInfo info;
_tcscpy(info.szPath, m_strFilePath);
if (SUCCEEDED(GetIconInfo(info)))
{
m_fLive = TRUE;
m_strItem = fd.cFileName;
m_strLocation = szFolder;
m_strCommand.Format(_T("%s %s"), info.szTarget, info.szArgs);
int iDot = m_strItem.ReverseFind(_T('.'));
if (iDot > 0)
m_strItem = m_strItem.Left(iDot);
return TRUE;
}
}
else
{
// A file besides a shortcut. It may be an EXE, or some other file type
// (we'll handle them the same).
m_fLive = TRUE;
m_strItem = fd.cFileName;
m_strLocation = szFolder;
m_strCommand = m_strFilePath;
int iDot = m_strItem.ReverseFind(_T('.'));
if (iDot > 0)
m_strItem = m_strItem.Left(iDot);
return TRUE;
}
return FALSE;
}
//----------------------------------------------------------------------------
// Get the information about a shortcut. Creates a thread to do so, since it
// needs to be done in an apartment model thread.
//
// JJ's code, cleaned up a bit.
//----------------------------------------------------------------------------
DWORD GetIconInfoProc(CStartupItemFolder::CIconInfo * pInfo);
HRESULT CStartupItemFolder::GetIconInfo(CIconInfo & info)
{
DWORD dwID;
HANDLE hThread;
if (hThread = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)GetIconInfoProc, &info, 0, &dwID))
{
info.hResult = S_OK;
::WaitForSingleObject(hThread, INFINITE);
}
else
info.hResult = E_FAIL;
return info.hResult;
}
//----------------------------------------------------------------------------
// Remove all the entries persisted in the registry.
//----------------------------------------------------------------------------
void CStartupItemFolder::RemovePersistedEntries()
{
CRegKey regkey;
regkey.Attach(GetRegKey());
if ((HKEY)regkey != NULL)
regkey.RecurseDeleteKey(_T("startupfolder"));
}
//----------------------------------------------------------------------------
// Procedure (run in its own thread) to get information about a shortcut.
//
// JJ's code, cleaned up a bit.
//----------------------------------------------------------------------------
DWORD GetIconInfoProc(CStartupItemFolder::CIconInfo * pInfo)
{
HRESULT hResult;
IShellLink * psl = NULL;
IPersistFile * ppf = NULL;
try
{
// We have to use COINIT_APARTMENTTHREADED.
if (SUCCEEDED(hResult = CoInitialize(NULL)))
{
// Get a pointer to the IShellLink interface.
if (SUCCEEDED(hResult = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (VOID **) &psl)))
{
// Get a pointer to the IPersistFile interface.
if (SUCCEEDED(hResult = psl->QueryInterface(IID_IPersistFile, (VOID **) &ppf)))
{
BSTR bstrPath;
#ifdef UNICODE
bstrPath = pInfo->szPath;
#else
WCHAR wszTemp[MAX_PATH];
wsprintfW(wszTemp, L"%hs", pInfo->szPath);
bstrPath = wszTemp;
#endif
if (SUCCEEDED(hResult = ppf->Load(bstrPath, STGM_READ)))
{
WIN32_FIND_DATA fd;
hResult = psl->GetPath(pInfo->szTarget, sizeof(pInfo->szTarget), &fd, SLGP_SHORTPATH);
hResult = psl->GetArguments(pInfo->szArgs, sizeof(pInfo->szArgs));
}
}
}
}
pInfo->hResult = hResult;
}
catch(...)
{
if (psl)
psl->Release();
if (ppf)
ppf->Release();
CoUninitialize();
throw;
}
if (psl)
{
psl->Release();
psl = NULL;
}
if (ppf)
{
ppf->Release();
ppf = NULL;
}
CoUninitialize();
return 0;
}
BOOL CPageStartup::OnInitDialog()
{
CPropertyPage::OnInitDialog();
::EnableWindow(GetDlgItemHWND(IDC_LISTSTARTUP), TRUE);
// Attach to the list view and set the styles we need.
m_fIgnoreListChanges = TRUE;
m_list.Attach(GetDlgItemHWND(IDC_LISTSTARTUP));
ListView_SetExtendedListViewStyle(m_list.m_hWnd, LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
// Add all of the necessary columns to the list view's header control.
struct { UINT m_uiStringResource; int m_iPercentOfWidth; } aColumns[] =
{
{ IDS_STARTUP_LOCATION, 50 },
{ IDS_STARTUP_COMMAND, 25 },
{ IDS_STARTUP_ITEM, 25 },
{ 0, 0 }
};
CRect rect;
m_list.GetClientRect(&rect);
int cxWidth = rect.Width();
LVCOLUMN lvc;
lvc.mask = LVCF_TEXT | LVCF_WIDTH;
CString strCaption;
::AfxSetResourceHandle(_Module.GetResourceInstance());
for (int i = 0; aColumns[i].m_uiStringResource; i++)
{
strCaption.LoadString(aColumns[i].m_uiStringResource);
lvc.pszText = (LPTSTR)(LPCTSTR)strCaption;
lvc.cx = aColumns[i].m_iPercentOfWidth * cxWidth / 100;
ListView_InsertColumn(m_list.m_hWnd, 0, &lvc);
}
LoadStartupList();
CPageBase::TabState state = GetCurrentTabState();
::EnableWindow(GetDlgItemHWND(IDC_BUTTONSUDISABLEALL), (state != DIAGNOSTIC));
::EnableWindow(GetDlgItemHWND(IDC_BUTTONSUENABLEALL), (state != NORMAL));
m_stateRequested = GetAppliedTabState();
m_fInitialized = TRUE;
// Show the restore disabled startup item button based on whether or not
// there are items to restore.
::ShowWindow(GetDlgItemHWND(IDC_BUTTONSURESTORE), CRestoreStartup::AreItemsToRestore() ? SW_SHOW : SW_HIDE);
return TRUE; // return TRUE unless you set the focus to a control
}
void CPageStartup::OnDestroy()
{
CPropertyPage::OnDestroy();
EmptyList(TRUE);
}
//-----------------------------------------------------------------------------
// If there's a change to an item in the list, it's probably because the user
// has checked or unchecked a checkbox.
//-----------------------------------------------------------------------------
void CPageStartup::OnItemChangedList(NMHDR * pNMHDR, LRESULT * pResult)
{
NM_LISTVIEW * pNMListView = (NM_LISTVIEW *)pNMHDR;
if (!m_fIgnoreListChanges)
{
LVITEM lvi;
lvi.mask = LVIF_PARAM;
lvi.iSubItem = 0;
lvi.iItem = pNMListView->iItem;
if (ListView_GetItem(m_list.m_hWnd, &lvi))
{
CStartupItem * pItem = (CStartupItem *)lvi.lParam;
if (pItem)
{
BOOL fCurrentCheck = ListView_GetCheckState(m_list.m_hWnd, pNMListView->iItem);
if (fCurrentCheck != pItem->IsLive())
SetModified(TRUE);
CPageBase::TabState state = GetCurrentTabState();
::EnableWindow(GetDlgItemHWND(IDC_BUTTONSUDISABLEALL), (state != DIAGNOSTIC));
::EnableWindow(GetDlgItemHWND(IDC_BUTTONSUENABLEALL), (state != NORMAL));
}
}
}
*pResult = 0;
}
//-----------------------------------------------------------------------------
// Handle the buttons to enable or disable all the items.
//-----------------------------------------------------------------------------
void CPageStartup::OnButtonDisableAll()
{
SetEnableForList(FALSE);
}
void CPageStartup::OnButtonEnableAll()
{
SetEnableForList(TRUE);
}
//-------------------------------------------------------------------------
// Return the current state of the tab (need to look through the list).
//-------------------------------------------------------------------------
CPageBase::TabState CPageStartup::GetCurrentTabState()
{
if (!m_fInitialized)
return GetAppliedTabState();
// If there are no startup items, we can only return the
// state that was last requested.
if (ListView_GetItemCount(m_list.m_hWnd) == 0)
return m_stateRequested;
TabState stateReturn = USER;
BOOL fAllEnabled = TRUE, fAllDisabled = TRUE;
LVITEM lvi;
lvi.mask = LVIF_PARAM;
lvi.iSubItem = 0;
for (int i = ListView_GetItemCount(m_list.m_hWnd) - 1; i >= 0; i--)
{
if (ListView_GetCheckState(m_list.m_hWnd, i))
fAllDisabled = FALSE;
else
fAllEnabled = FALSE;
}
if (fAllEnabled)
stateReturn = NORMAL;
else if (fAllDisabled)
stateReturn = DIAGNOSTIC;
return stateReturn;
}
//-------------------------------------------------------------------------
// Traverse the list looking for items which have check boxes that don't
// match the state of the items. For these items, set the state.
//
// Finally, the base class implementation is called to maintain the
// applied tab state.
//-------------------------------------------------------------------------
BOOL CPageStartup::OnApply()
{
LVITEM lvi;
lvi.mask = LVIF_PARAM;
lvi.iSubItem = 0;
for (int i = ListView_GetItemCount(m_list.m_hWnd) - 1; i >= 0; i--)
{
lvi.iItem = i;
if (ListView_GetItem(m_list.m_hWnd, &lvi))
{
CStartupItem * pItem = (CStartupItem *)lvi.lParam;
if (pItem)
{
BOOL fCurrentCheck = ListView_GetCheckState(m_list.m_hWnd, i);
if (fCurrentCheck != pItem->IsLive())
pItem->SetEnable(fCurrentCheck);
}
}
}
CPageBase::SetAppliedState(GetCurrentTabState());
CancelToClose();
m_fMadeChange = TRUE;
return TRUE;
}
//-------------------------------------------------------------------------
// Apply the changes, remove the persisted registry entries, refill the
// list. Then call the base class implementation.
//-------------------------------------------------------------------------
void CPageStartup::CommitChanges()
{
OnApply();
CStartupItemRegistry::RemovePersistedEntries();
CStartupItemFolder::RemovePersistedEntries();
LoadStartupList();
CPageBase::CommitChanges();
}
//-------------------------------------------------------------------------
// Set the overall state of the tab to normal or diagnostic.
//-------------------------------------------------------------------------
void CPageStartup::SetNormal()
{
SetEnableForList(TRUE);
m_stateRequested = NORMAL;
}
void CPageStartup::SetDiagnostic()
{
SetEnableForList(FALSE);
m_stateRequested = DIAGNOSTIC;
}
//-------------------------------------------------------------------------
// If nothing is selected when the list gets focus, select the first item
// (so the user sees where the focus is).
//-------------------------------------------------------------------------
void CPageStartup::OnSetFocusList(NMHDR * pNMHDR, LRESULT * pResult)
{
if (0 == ListView_GetSelectedCount(m_list.m_hWnd) && 0 < ListView_GetItemCount(m_list.m_hWnd))
ListView_SetItemState(m_list.m_hWnd, 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
*pResult = 0;
}
//-------------------------------------------------------------------------
// Show the dialog which allows the user to restore startup items which
// were disabled during upgrade.
//-------------------------------------------------------------------------
void CPageStartup::OnButtonRestore()
{
CRestoreStartup dlg;
dlg.DoModal();
::EnableWindow(GetDlgItemHWND(IDC_BUTTONSURESTORE), CRestoreStartup::AreItemsToRestore());
}
//=========================================================================
// This code implements the CRestoreStartup dialog, which allows the
// user to restore items disabled by an upgrade.
//=========================================================================
CRestoreStartup::CRestoreStartup(CWnd* pParent /*=NULL*/) : CDialog(CRestoreStartup::IDD, pParent)
{
//{{AFX_DATA_INIT(CRestoreStartup)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
void CRestoreStartup::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CRestoreStartup)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CRestoreStartup, CDialog)
//{{AFX_MSG_MAP(CRestoreStartup)
ON_WM_DESTROY()
ON_NOTIFY(LVN_ITEMCHANGED, IDC_RESTORELIST, OnItemChangedRestoreList)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//-----------------------------------------------------------------------------
// As the dialog initializes, set the format of the list view, add the
// appropriate columns, and populate the list with the disabled startup items.
//-----------------------------------------------------------------------------
BOOL CRestoreStartup::OnInitDialog()
{
CDialog::OnInitDialog();
// Set the list view to have check boxes.
CWnd * pWnd = GetDlgItem(IDC_RESTORELIST);
if (pWnd == NULL)
return FALSE;
m_list.Attach(pWnd->m_hWnd);
ListView_SetExtendedListViewStyle(m_list.m_hWnd, LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
// Add all of the necessary columns to the list view's header control.
struct { UINT m_uiStringResource; int m_iPercentOfWidth; } aColumns[] =
{
{ IDS_STARTUP_ITEM, 65 },
{ IDS_STARTUP_LOCATION, 35 },
{ 0, 0 }
};
CRect rect;
m_list.GetClientRect(&rect);
int cxWidth = rect.Width();
LVCOLUMN lvc;
lvc.mask = LVCF_TEXT | LVCF_WIDTH;
CString strCaption;
::AfxSetResourceHandle(_Module.GetResourceInstance());
for (int i = 0; aColumns[i].m_uiStringResource; i++)
{
strCaption.LoadString(aColumns[i].m_uiStringResource);
lvc.pszText = (LPTSTR)(LPCTSTR)strCaption;
lvc.cx = aColumns[i].m_iPercentOfWidth * cxWidth / 100;
ListView_InsertColumn(m_list.m_hWnd, 0, &lvc);
}
// Load up the list with the disabled items.
LoadDisabledItemList();
SetOKState();
return TRUE;
}
//-----------------------------------------------------------------------------
// Load the items in the list (from the registry and startup directory).
//-----------------------------------------------------------------------------
BOOL CRestoreStartup::LoadDisabledItemList()
{
m_iNextPosition = 0;
BOOL fRegistry = LoadDisabledRegistry();
BOOL fStartup = LoadDisabledStartupGroup();
return (fRegistry && fStartup);
}
//-----------------------------------------------------------------------------
// Read the list of disabled startup items which would be restored to the
// registry. This list is just stored in a different registry location.
//-----------------------------------------------------------------------------
BOOL CRestoreStartup::LoadDisabledRegistry()
{
HKEY ahkeyBases[] = { HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER, NULL };
for (int i = 0; ahkeyBases[i] != NULL; i++)
{
// Open the key containing the disabled items. We open it KEY_WRITE | KEY_READ,
// even though we are just going to read in this function. This is because
// if opening for this access fails, we don't want to list the items because
// the user won't be able to restore the items.
CRegKey regkey;
if (ERROR_SUCCESS != regkey.Open(ahkeyBases[i], DISABLED_KEY, KEY_WRITE | KEY_READ))
return FALSE;
// Get the number of keys under the key and look at each one.
DWORD dwValueCount, dwSize;
if (ERROR_SUCCESS == ::RegQueryInfoKey((HKEY)regkey, NULL, NULL, NULL, NULL, NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL))
{
TCHAR szValueName[MAX_PATH], szValue[MAX_PATH];
for (DWORD dwKey = 0; dwKey < dwValueCount; dwKey++)
{
dwSize = MAX_PATH;
if (ERROR_SUCCESS != ::RegEnumValue((HKEY)regkey, dwKey, szValueName, &dwSize, NULL, NULL, NULL, NULL))
continue;
dwSize = MAX_PATH;
if (ERROR_SUCCESS != regkey.QueryValue(szValue, szValueName, &dwSize))
continue;
// Create the startup item and insert it in the list.
CStartupDisabledRegistry * pItem = new CStartupDisabledRegistry(szValueName, szValue, ENABLED_KEY, ahkeyBases[i]);
InsertDisabledStartupItem(pItem);
}
}
regkey.Close();
}
return TRUE;
}
//-----------------------------------------------------------------------------
// Add the items from the disabled startup group to the list:
//
// GIVEN the path to CSIDL_STARTUP, setup moves disabled items to
// ..\Disabled Startup and makes it hidden; it potentially contains
// the complete content of the original startup folder, which
// can be anything.
//
// Note - we'll also need to look under CSIDL_COMMON_STARTUP.
//-----------------------------------------------------------------------------
BOOL CRestoreStartup::LoadDisabledStartupGroup()
{
int anFolders[] = { CSIDL_STARTUP, CSIDL_COMMON_STARTUP, 0 };
TCHAR szPath[MAX_PATH * 2];
for (int i = 0; anFolders[i] != 0; i++)
{
if (FAILED(::SHGetSpecialFolderPath(NULL, szPath, anFolders[i], FALSE)))
continue;
// We need to trim off the last part of the path and replace it with
// "Disabled Startup".
CString strPath(szPath);
int iLastSlash = strPath.ReverseFind(_T('\\'));
if (iLastSlash == -1)
continue;
strPath = strPath.Left(iLastSlash) + CString(DISABLED_STARTUP);
// Now look for files in the folder.
CString strSearch(strPath);
strSearch += CString(_T("\\*.*"));
WIN32_FIND_DATA fd;
HANDLE hFind = FindFirstFile(strSearch, &fd);
if (hFind != INVALID_HANDLE_VALUE)
{
do
{
// We want to ignore the desktop.ini file which might appear in startup.
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) == 0 || _tcsicmp(fd.cFileName, _T("desktop.ini")) != 0)
{
// We only want to examine files which aren't directories.
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
{
CStartupDisabledStartup * pItem = new CStartupDisabledStartup(fd.cFileName, szPath, strPath);
InsertDisabledStartupItem(pItem);
}
}
} while (FindNextFile(hFind, &fd));
FindClose(hFind);
}
}
return TRUE;
}
//-----------------------------------------------------------------------------
// Insert the disabled item into the list view.
//-----------------------------------------------------------------------------
void CRestoreStartup::InsertDisabledStartupItem(CStartupDisabled * pItem)
{
if (pItem == NULL)
return;
CString strItem, strLocation;
pItem->GetColumnCaptions(strItem, strLocation);
// Insert the item in the list view.
LV_ITEM lvi;
memset(&lvi, 0, sizeof(lvi));
lvi.mask = LVIF_TEXT | LVIF_PARAM;
lvi.iItem = m_iNextPosition;
lvi.pszText = (LPTSTR)(LPCTSTR)strLocation;
lvi.iSubItem = 0;
lvi.lParam = (LPARAM)pItem;
m_iNextPosition = ListView_InsertItem(m_list.m_hWnd, &lvi);
ListView_SetItemText(m_list.m_hWnd, m_iNextPosition, 1, (LPTSTR)(LPCTSTR)strItem);
ListView_SetCheckState(m_list.m_hWnd, m_iNextPosition, TRUE);
m_iNextPosition++;
}
//-----------------------------------------------------------------------------
// Remove all the items from the list view (freeing the objects pointed to
// by the LPARAM).
//-----------------------------------------------------------------------------
void CRestoreStartup::EmptyList()
{
LVITEM lvi;
lvi.mask = LVIF_PARAM;
lvi.iSubItem = 0;
for (int i = ListView_GetItemCount(m_list.m_hWnd) - 1; i >= 0; i--)
{
lvi.iItem = i;
if (ListView_GetItem(m_list.m_hWnd, &lvi))
{
CStartupDisabled * pItem = (CStartupDisabled *)lvi.lParam;
if (pItem)
delete pItem;
}
}
ListView_DeleteAllItems(m_list.m_hWnd);
}
//-----------------------------------------------------------------------------
// When the dialog is being destroyed, be sure to free the memory of the
// object pointers maintained in the list view.
//-----------------------------------------------------------------------------
void CRestoreStartup::OnDestroy()
{
EmptyList();
CDialog::OnDestroy();
}
//-----------------------------------------------------------------------------
// If the user clicks on OK, then we should make sure he or she really wants
// to perform this operation. If so, then look though the list, calling the
// Restore function for each object with the checkbox checked.
//-----------------------------------------------------------------------------
void CRestoreStartup::OnOK()
{
CString strText, strCaption;
strCaption.LoadString(IDS_DIALOGCAPTION);
strText.LoadString(IDS_VERIFYRESTORE);
if (IDYES == ::MessageBox(m_hWnd, strText, strCaption, MB_YESNO))
{
LVITEM lvi;
lvi.mask = LVIF_PARAM;
lvi.iSubItem = 0;
for (int i = ListView_GetItemCount(m_list.m_hWnd) - 1; i >= 0; i--)
if (ListView_GetCheckState(m_list.m_hWnd, i))
{
lvi.iItem = i;
if (ListView_GetItem(m_list.m_hWnd, &lvi))
{
CStartupDisabled * pItem = (CStartupDisabled *)lvi.lParam;
if (pItem != NULL)
pItem->Restore();
}
}
}
CDialog::OnOK();
}
//-----------------------------------------------------------------------------
// Enable or disable the OK button based on the state of the check boxes.
//-----------------------------------------------------------------------------
void CRestoreStartup::SetOKState()
{
CWnd * pWnd = GetDlgItem(IDOK);
if (pWnd == NULL)
return;
BOOL fEnable = FALSE;
for (int i = ListView_GetItemCount(m_list.m_hWnd) - 1; i >= 0; i--)
if (ListView_GetCheckState(m_list.m_hWnd, i))
{
fEnable = TRUE;
break;
}
if (::IsWindowEnabled(pWnd->m_hWnd) != fEnable)
::EnableWindow(pWnd->m_hWnd, fEnable);
}
//-----------------------------------------------------------------------------
// If the user changed something in the list, update the OK button state.
//-----------------------------------------------------------------------------
void CRestoreStartup::OnItemChangedRestoreList(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
SetOKState();
*pResult = 0;
}
//-----------------------------------------------------------------------------
// This static function will be called by the startup tab to determine if the
// button to launch this dialog box should be enabled.
//-----------------------------------------------------------------------------
BOOL CRestoreStartup::AreItemsToRestore()
{
// Look in the registry for disabled items.
HKEY ahkeyBases[] = { HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER, NULL };
for (int j = 0; ahkeyBases[j] != NULL; j++)
{
CRegKey regkey;
if (ERROR_SUCCESS == regkey.Open(ahkeyBases[j], DISABLED_KEY, KEY_READ))
{
DWORD dwValueCount;
if (ERROR_SUCCESS == ::RegQueryInfoKey((HKEY)regkey, NULL, NULL, NULL, NULL, NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL))
if (dwValueCount > 0)
{
regkey.Close();
return TRUE;
}
regkey.Close();
}
}
// Look in the disabled startup items folders.
int anFolders[] = { CSIDL_STARTUP, CSIDL_COMMON_STARTUP, 0 };
TCHAR szPath[MAX_PATH * 2];
BOOL fDisabledItem = FALSE;
for (int i = 0; !fDisabledItem && anFolders[i] != 0; i++)
{
if (FAILED(::SHGetSpecialFolderPath(NULL, szPath, anFolders[i], FALSE)))
continue;
// We need to trim off the last part of the path and replace it with
// "Disabled Startup".
CString strPath(szPath);
int iLastSlash = strPath.ReverseFind(_T('\\'));
if (iLastSlash == -1)
continue;
strPath = strPath.Left(iLastSlash) + CString(DISABLED_STARTUP);
// Now look for files in the folder.
CString strSearch(strPath);
strSearch += CString(_T("\\*.*"));
WIN32_FIND_DATA fd;
HANDLE hFind = FindFirstFile(strSearch, &fd);
if (hFind != INVALID_HANDLE_VALUE)
{
do
{
// We want to ignore the desktop.ini file which might appear in startup.
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) == 0 || _tcsicmp(fd.cFileName, _T("desktop.ini")) != 0)
{
// We only want to examine files which aren't directories.
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
{
fDisabledItem = TRUE;
break;
}
}
} while (FindNextFile(hFind, &fd));
FindClose(hFind);
}
}
return fDisabledItem;
}