|
|
//---------------------------------------------------------------------------
//
// 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; }
|