You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
279 lines
8.0 KiB
279 lines
8.0 KiB
//---------------------------------------------------------------------------
|
|
//
|
|
// Copyright (c) Microsoft Corporation
|
|
//
|
|
// File: setupenum.cpp
|
|
//
|
|
// The current order of enumeration is whatever order we read from the registry
|
|
//
|
|
// History:
|
|
// 6-11-98 by toddb
|
|
//------------------------------------------------------------------------
|
|
#include "priv.h"
|
|
|
|
#include <shellp.h> // for IsUserAnAdmin
|
|
#include "setupenum.h"
|
|
#include "appwizid.h"
|
|
|
|
#define c_szOCSetupKey TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Setup\\OCManager\\ToDoList")
|
|
|
|
//-----------------------------------------------------------------------
|
|
// OCSetupApp
|
|
//-----------------------------------------------------------------------
|
|
|
|
COCSetupApp::COCSetupApp()
|
|
{
|
|
// This must be heap alloced so everything should be zero'ed out.
|
|
// Make sure this wasn't stack alloced using these asserts:
|
|
ASSERT(0 == _szDisplayName[0]);
|
|
ASSERT(0 == _szApp[0]);
|
|
ASSERT(0 == _szArgs[0]);
|
|
}
|
|
|
|
COCSetupApp::~COCSetupApp()
|
|
{
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// GetAppInfo
|
|
//
|
|
// Fills in the only valid field in our psuedo APPINFODATA structure.
|
|
|
|
BOOL COCSetupApp::GetAppInfo(PAPPINFODATA pai)
|
|
{
|
|
if (pai->cbSize != SIZEOF(APPINFODATA))
|
|
return FALSE;
|
|
|
|
DWORD dwInfoFlags = pai->dwMask;
|
|
pai->dwMask = 0;
|
|
|
|
if (dwInfoFlags & AIM_DISPLAYNAME)
|
|
{
|
|
if (SUCCEEDED(SHStrDup(_szDisplayName, &pai->pszDisplayName)))
|
|
pai->dwMask |= AIM_DISPLAYNAME;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// ReadFromKey
|
|
//
|
|
// This function reads the actual data from the given reg key. It returns
|
|
// TRUE if all required fields contained string data.
|
|
|
|
BOOL COCSetupApp::ReadFromKey( HKEY hkey )
|
|
{
|
|
DWORD dwType;
|
|
DWORD dwSize;
|
|
|
|
dwSize = sizeof(_szDisplayName);
|
|
if ( ERROR_SUCCESS != RegQueryValueEx( hkey, TEXT("Title"), 0, &dwType, (LPBYTE)_szDisplayName, &dwSize ) ||
|
|
dwType != REG_SZ )
|
|
{
|
|
// DisplayName is required
|
|
return FALSE;
|
|
}
|
|
|
|
dwSize = sizeof(_szApp);
|
|
if ( ERROR_SUCCESS == RegQueryValueEx( hkey, TEXT("ConfigCommand"), 0, &dwType, (LPBYTE)_szApp, &dwSize ) &&
|
|
(dwType == REG_SZ || dwType == REG_EXPAND_SZ) )
|
|
{
|
|
if ( dwType == REG_EXPAND_SZ )
|
|
{
|
|
TCHAR szBuf[MAX_PATH];
|
|
ExpandEnvironmentStrings(_szApp, szBuf, ARRAYSIZE(szBuf));
|
|
lstrcpyn(_szApp, szBuf, ARRAYSIZE(_szApp));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// ConfigCommand is required
|
|
return FALSE;
|
|
}
|
|
|
|
dwSize = sizeof(_szArgs);
|
|
if ( ERROR_SUCCESS == RegQueryValueEx( hkey, TEXT("ConfigArgs"), 0, &dwType, (LPBYTE)_szArgs, &dwSize ) &&
|
|
(dwType == REG_SZ || dwType == REG_EXPAND_SZ) )
|
|
{
|
|
if ( dwType == REG_EXPAND_SZ )
|
|
{
|
|
TCHAR szBuf[MAX_PATH];
|
|
ExpandEnvironmentStrings(_szArgs, szBuf, ARRAYSIZE(szBuf));
|
|
lstrcpyn(_szArgs, szBuf, ARRAYSIZE(_szArgs));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// This is optional so we don't fail. Instead simply insure that _szArgs is an empty string.
|
|
_szArgs[0] = 0;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL COCSetupApp::Run()
|
|
{
|
|
// REARCHITECT: (stephstm, 03/17/99) we should probably wait on a job object in case
|
|
// the spawned process spawns some other process(es) and then exits before them.
|
|
|
|
BOOL fRet = FALSE;
|
|
SHELLEXECUTEINFO sei = {0};
|
|
|
|
sei.cbSize = sizeof(SHELLEXECUTEINFO);
|
|
sei.fMask = SEE_MASK_NOCLOSEPROCESS;
|
|
sei.hwnd = GetDesktopWindow();
|
|
sei.lpFile = _szApp;
|
|
sei.lpParameters = _szArgs[0] ? _szArgs : NULL;
|
|
sei.nShow = SW_SHOWDEFAULT;
|
|
|
|
fRet = ShellExecuteEx(&sei);
|
|
|
|
if (fRet)
|
|
{
|
|
DWORD dwRet;
|
|
|
|
do
|
|
{
|
|
MSG msg;
|
|
|
|
// Get and process the messages!
|
|
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
|
|
// MsgWaitForMultipleObjects can fail with -1 being returned!
|
|
dwRet = MsgWaitForMultipleObjects(1, &sei.hProcess, FALSE, INFINITE, QS_ALLINPUT);
|
|
}
|
|
while ((WAIT_OBJECT_0 != dwRet) && (-1 != dwRet));
|
|
|
|
// Did MsgWait... failed?
|
|
if (-1 == dwRet)
|
|
{
|
|
// Yes, kill the process
|
|
TerminateProcess(sei.hProcess, 0);
|
|
|
|
fRet = FALSE;
|
|
}
|
|
|
|
CloseHandle(sei.hProcess);
|
|
}
|
|
else
|
|
{
|
|
ShellMessageBox(HINST_THISDLL, sei.hwnd, MAKEINTRESOURCE( IDS_CONFIGURE_FAILED ),
|
|
MAKEINTRESOURCE( IDS_NAME ),
|
|
MB_OK | MB_ICONEXCLAMATION);
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
// OCSetupEnum
|
|
//-----------------------------------------------------------------------
|
|
|
|
COCSetupEnum::COCSetupEnum()
|
|
{
|
|
_hkeyRoot = 0;
|
|
_iRegEnumIndex = -1;
|
|
}
|
|
|
|
COCSetupEnum::~COCSetupEnum()
|
|
{
|
|
if ( _hkeyRoot )
|
|
{
|
|
RegCloseKey( _hkeyRoot );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// s_OCSetupNeeded
|
|
//
|
|
// This checks for the neccessaary conditions to display the OC Setup portion of the ARP.
|
|
// This section is only shown if the current user is a member of the administrators group
|
|
// AND there are any items listed in the registry that need to be displayed.
|
|
|
|
BOOL COCSetupEnum::s_OCSetupNeeded()
|
|
{
|
|
BOOL fResult = FALSE;
|
|
HKEY hkey;
|
|
// Temporarily open the reg key to see if it exists and has any sub keys
|
|
if ( ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szOCSetupKey, 0, KEY_READ, &hkey ) )
|
|
{
|
|
TCHAR szBuf[MAX_PATH];
|
|
if ( ERROR_SUCCESS == RegEnumKey( hkey, 0, szBuf, ARRAYSIZE(szBuf) ) )
|
|
{
|
|
// Yes, there are OCSetup items, but is the current user an administrator?
|
|
if ( IsUserAnAdmin() )
|
|
{
|
|
fResult = TRUE;
|
|
}
|
|
}
|
|
RegCloseKey( hkey );
|
|
}
|
|
return fResult;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// EnumOCSetupItems
|
|
//
|
|
// This begins the enumeration by opening the required registry key. This does
|
|
// not attempt to read any of the sub items so there is no garentee that the
|
|
// first call to Next() will succeed.
|
|
|
|
BOOL COCSetupEnum::EnumOCSetupItems()
|
|
{
|
|
ASSERT( NULL == _hkeyRoot );
|
|
// Open the reg key, return true if it's open. We leave the key open until
|
|
// our destructor is called since we need this key to do the enumeration.
|
|
if ( ERROR_SUCCESS == RegOpenKeyEx(
|
|
HKEY_LOCAL_MACHINE,
|
|
c_szOCSetupKey,
|
|
0,
|
|
KEY_READ,
|
|
&_hkeyRoot ) )
|
|
{
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Next
|
|
//
|
|
// Reads the data from the next sub key of _hkeyRoot and returns the data in the
|
|
// out pointer. Returns TRUE if the out pointer is a valid COCSetupApp object.
|
|
|
|
BOOL COCSetupEnum::Next(COCSetupApp **ppocsa)
|
|
{
|
|
HKEY hkeySub;
|
|
TCHAR szSubKeyName[MAX_PATH];
|
|
|
|
// We open each subkey of the root key and attempt to read an OCSetup item from the subkey.
|
|
if ( ERROR_SUCCESS == RegEnumKey( _hkeyRoot, ++_iRegEnumIndex, szSubKeyName, ARRAYSIZE(szSubKeyName) ) )
|
|
{
|
|
if ( ERROR_SUCCESS == RegOpenKeyEx( _hkeyRoot, szSubKeyName, 0, KEY_READ, &hkeySub ) )
|
|
{
|
|
*ppocsa = new COCSetupApp();
|
|
if ( *ppocsa )
|
|
{
|
|
if ( (*ppocsa)->ReadFromKey( hkeySub ) )
|
|
{
|
|
RegCloseKey( hkeySub );
|
|
return TRUE;
|
|
}
|
|
|
|
delete *ppocsa;
|
|
}
|
|
RegCloseKey( hkeySub );
|
|
}
|
|
// fall through
|
|
}
|
|
|
|
*ppocsa = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
|