windows-nt/Source/XPSP1/NT/enduser/troubleshoot/msinfo/revents.cpp
2020-09-26 16:20:57 +08:00

643 lines
17 KiB
C++

// REvents.cpp : All result-pane Notify events. These functions are all
// part of the CSystemInfo class.
//
// Copyright (c) 1998-1999 Microsoft Corporation
#include "StdAfx.h"
// This hack is required because we may be building in an environment
// which doesn't have a late enough version of rpcndr.h
#if __RPCNDR_H_VERSION__ < 440
#define __RPCNDR_H_VERSION__ 440
#define MIDL_INTERFACE(x) interface
#endif
#ifndef __mmc_h__
#include <mmc.h> // ..\..\..\public\sdk\inc
#endif
#include <htmlhelp.h> // ..\..\..\public\sdk\inc
#include "DataObj.h"
#include "SysInfo.h"
#include "ViewObj.h"
// This is not necessary; these are enumerated in the scope pane.
#if 0
/*
* EnumerateCategories - Enumerate all sub-categories of pDataObject
* in the result pane.
*
* History: a-jsari 10/2/97 Initial version
*/
HRESULT CSystemInfo::EnumerateCategories(CFolder *pfolSelection)
{
HRESULT hr = S_OK;
RESULTDATAITEM rdiItem;
rdiItem.mask = RDI_STR | RDI_PARAM | RDI_IMAGE;
rdiItem.str = MMC_CALLBACK;
rdiItem.nCol = 0;
rdiItem.nImage = 0;
CFolder *pfolIterator = pfolSelection->GetChildNode();
LPRESULTDATA pResultPane = pResult();
for (rdiItem.nIndex = 0; pfolIterator; ++rdiItem.nIndex,
pfolIterator = pfolIterator->GetNextSibling()) {
// This would leak memory if we used it.
CResultViewObject *proCategory = new CCategoryObject(pfolIterator,
rdiItem.nIndex);
rdiItem.lParam = reinterpret_cast<long>(proCategory);
hr = pResultPane->InsertItem(&rdiItem);
if (FAILED(hr)) break;
}
return hr;
}
#endif
/*
* ClearResultsPane - Clear out all saved state about the results pane,
* in preparation for rebuilding the information.
*
* History: a-jsari 10/7/97 Initial version
*/
HRESULT CSystemInfo::ClearResultsPane()
{
// Delete all items.
HRESULT hres = pResult()->DeleteAllRsltItems();
// Clear our list of ViewObjects.
m_lstView.Clear();
return hres;
}
/*
* EnumerateValues - Enumerate all result pane rows, given the CFolder object
* to be displayed.
*
* We do this by getting the number of rows the folder contains and creating a
* single CDatumObject for each row in the folder, attaching that object
* as the lParam data for the RESULTDATAITEM inserted.
*
* History: a-jsari 10/2/97 Initial version
*/
HRESULT CSystemInfo::EnumerateValues(CFolder *pfolSelection)
{
HRESULT hr = S_OK;
RESULTDATAITEM rdiItem;
// Set the information common to all of our inserted items
// (Modified below for selected items and by specific item data.)
rdiItem.mask = RDI_STR | RDI_PARAM | RDI_IMAGE;
rdiItem.str = MMC_CALLBACK;
rdiItem.nCol = 0;
rdiItem.nImage = 1;
ASSERT(pfolSelection->GetType() != CDataSource::OCX);
int cRows = dynamic_cast<CListViewFolder *>(pfolSelection)->GetRows();
int nSelectionRow = pfolSelection->GetSelectedItem();
LPRESULTDATA pResultPane = pResult();
if (cRows > 0) {
pResultPane->ModifyViewStyle((MMC_RESULT_VIEW_STYLE ) 0x0008 /* = MMC_ENSUREFOCUSVISIBLE */, (MMC_RESULT_VIEW_STYLE ) 0);
for (rdiItem.nIndex = 0 ; rdiItem.nIndex < cRows ; ++rdiItem.nIndex) {
// Create our new CDatumObject so we have strings for GetDisplayInfo.
CViewObject *proValue = new CDatumObject(pfolSelection,
rdiItem.nIndex);
// Attach it in our data.
rdiItem.lParam = reinterpret_cast<LPARAM>(proValue);
// If we are the item selected by a prior find operation, set ourselves
// as focused and selected, otherwise just add as usual.
if (rdiItem.nIndex == nSelectionRow) {
rdiItem.mask |= RDI_STATE;
rdiItem.nState = LVIS_FOCUSED | LVIS_SELECTED;
hr = pResultPane->InsertItem(&rdiItem);
rdiItem.mask &= ~RDI_STATE;
} else
hr = pResultPane->InsertItem(&rdiItem);
if (FAILED(hr)) break;
// Insert our new'd pointer into the list so we may delete them when we
// clear out our result pane data.
m_lstView.Add(proValue);
}
// Set ourselves to the view mode which gives us column data.
pResultPane->SetViewMode(LVS_REPORT);
pResultPane->ModifyViewStyle((MMC_RESULT_VIEW_STYLE ) 0, (MMC_RESULT_VIEW_STYLE ) 0x0008 /* = MMC_ENSUREFOCUSVISIBLE */);
} else {
// No rows means only automatic [folder] result data items, so use
// a list view.
pResultPane->SetViewMode(LVS_LIST);
}
return hr;
}
/*
* HandleStandardVerbs - Set all of the standard verb states, based on
* the context of lpDataObject and the activity state.
*
* History: a-jsari 9/22/97 Initial version
*/
HRESULT CSystemInfo::HandleStandardVerbs(BOOL fScope, LPDATAOBJECT lpDataObject)
{
// CHECK: Candidate for optimization?
SetInitialVerbState(fScope);
CDataObject * pDataObject = GetInternalFromDataObject(lpDataObject);
if (pDataObject)
{
LPCONSOLEVERB pVerbSetting = pConsoleVerb();
if (pVerbSetting)
{
BOOL fIsPrimarySnapin = TRUE;
if (pComponentData())
fIsPrimarySnapin = dynamic_cast<CSystemInfoScope *>(pComponentData())->IsPrimaryImpl();
CDataSource * pSource = pDataObject->pSource();
if (fIsPrimarySnapin && pSource && pSource->GetType() == CDataSource::GATHERER)
pVerbSetting->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, TRUE);
else
pVerbSetting->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, FALSE);
}
}
return S_OK;
}
/*
* SetInitialVerbState - Sets the default state for all of the MMC standard
* verbs.
*
* History: a-jsari 9/22/97 Initial version
*/
void CSystemInfo::SetInitialVerbState(BOOL fScope)
{
HRESULT hr;
LPCONSOLEVERB pVerbSetting = pConsoleVerb();
ASSERT(pVerbSetting != NULL);
#if 1
hr = pVerbSetting->SetVerbState(MMC_VERB_PRINT, HIDDEN, FALSE);
ASSERT(hr == S_OK);
hr = pVerbSetting->SetVerbState(MMC_VERB_PRINT, ENABLED, TRUE);
ASSERT(hr == S_OK);
#endif
// hr = pVerbSetting->SetVerbState(MMC_VERB_PROPERTIES, HIDDEN, !fScope);
// ASSERT(hr == S_OK);
// hr = pVerbSetting->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, fScope);
// ASSERT(hr == S_OK);
hr = pVerbSetting->SetVerbState(MMC_VERB_PROPERTIES, HIDDEN, FALSE);
ASSERT(hr == S_OK);
hr = pVerbSetting->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, TRUE);
ASSERT(hr == S_OK);
// Enable Open verb for result pane folder nodes only.
hr = pVerbSetting->SetVerbState(MMC_VERB_OPEN, HIDDEN, TRUE);
ASSERT(hr == S_OK);
hr = pVerbSetting->SetVerbState(MMC_VERB_OPEN, ENABLED, FALSE);
ASSERT(hr == S_OK);
BOOL fRefreshAvailable = FALSE;
if (((CSystemInfoScope *)pComponentData())->pSource() != NULL
&& ((CSystemInfoScope *)pComponentData())->pSource()->GetType() == CDataSource::GATHERER)
fRefreshAvailable = TRUE;
hr = pVerbSetting->SetVerbState(MMC_VERB_REFRESH, HIDDEN, !fRefreshAvailable);
ASSERT(hr == S_OK);
hr = pVerbSetting->SetVerbState(MMC_VERB_REFRESH, ENABLED, fRefreshAvailable);
ASSERT(hr == S_OK);
hr = pVerbSetting->SetVerbState(MMC_VERB_COPY, HIDDEN, TRUE);
ASSERT(hr == S_OK);
hr = pVerbSetting->SetVerbState(MMC_VERB_COPY, ENABLED, FALSE);
ASSERT(hr == S_OK);
hr = pVerbSetting->SetVerbState(MMC_VERB_PASTE, HIDDEN, TRUE);
ASSERT(hr == S_OK);
hr = pVerbSetting->SetVerbState(MMC_VERB_PASTE, ENABLED, FALSE);
ASSERT(hr == S_OK);
hr = pVerbSetting->SetVerbState(MMC_VERB_DELETE, HIDDEN, TRUE);
ASSERT(hr == S_OK);
hr = pVerbSetting->SetVerbState(MMC_VERB_DELETE, ENABLED, FALSE);
ASSERT(hr == S_OK);
hr = pVerbSetting->SetVerbState(MMC_VERB_RENAME, ENABLED, FALSE);
ASSERT(hr == S_OK);
}
/*
* SetResultHeaderColumns - Sets the header columns used to display
* standard result pane data.
*
* History: a-jsari 10/2/97 Initial version.
*/
HRESULT CSystemInfo::SetResultHeaderColumns(CFolder *pCategory)
{
LPHEADERCTRL pResultHeader;
HRESULT hr;
CListViewFolder *plvfCategory;
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
pResultHeader = pHeaderCtrl();
ASSERT(pResultHeader != NULL);
int cColumns;
ASSERT(pCategory != NULL);
ASSERT(pCategory->GetType() != CDataSource::OCX);
plvfCategory = dynamic_cast<CListViewFolder *>(pCategory);
cColumns = plvfCategory->GetColumns();
do {
hr = pResultHeader->DeleteColumn(0);
} while (hr == S_OK);
for (int i = 0; i < cColumns ; ++i) {
CString szColumnHeading;
DWORD nColumnWidth;
VERIFY(plvfCategory->GetColumnTextAndWidth(i, szColumnHeading, (unsigned &)nColumnWidth));
hr = pResultHeader->InsertColumn(i, (LPCWSTR)szColumnHeading,
LVCFMT_LEFT, nColumnWidth);
if (FAILED(hr)) break;
}
return hr;
}
/*
* OnActivate - Activate event handler
*
* History: a-jsari 10/3/97 Stub version
*/
HRESULT CSystemInfo::OnActivate(LPDATAOBJECT, LPARAM)
{
return S_OK;
}
/*
* OnAddImages - Add the folder and leaf item images for the result pane.
*
* History: a-jsari 9/24/97 Stub version
*/
HRESULT CSystemInfo::OnAddImages(LPDATAOBJECT, LPIMAGELIST pImageList, HSCOPEITEM)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
::CBitmap bmLarge;
bmLarge.LoadBitmap(IDB_LARGE);
::CBitmap bmSmall;
bmSmall.LoadBitmap(IDB_SMALLBMP);
HRESULT hr = pImageList->ImageListSetStrip(reinterpret_cast<LONG_PTR *>((HBITMAP)bmSmall),
reinterpret_cast<LONG_PTR *>((HBITMAP)bmLarge), 0, RGB(255,0,255));
ASSERT(hr == S_OK);
return hr;
}
/*
* OnButtonClick - Handle a toolbar button click.
*
* History: a-jsari 9/24/97 Stub version
*/
HRESULT CSystemInfo::OnButtonClick(LPDATAOBJECT pDataObject, LPARAM idButton)
{
switch (idButton) {
case IDM_TBB_FIND:
pExtendContextMenu()->Command(CSystemInfoScope::IDM_FIND, pDataObject);
break;
case IDM_TBB_OPEN:
pExtendContextMenu()->Command(CSystemInfoScope::IDM_TASK_OPENFILE, pDataObject);
break;
case IDM_TBB_SAVE:
pExtendContextMenu()->Command(CSystemInfoScope::IDM_SAVEFILE, pDataObject);
break;
#if 0
case IDM_TBB_PRINT:
pExtendContextMenu()->Command(CSystemInfoScope::IDM_PRINT, pDataObject);
break;
#endif
case IDM_TBB_REPORT:
pExtendContextMenu()->Command(CSystemInfoScope::IDM_SAVEREPORT, pDataObject);
break;
default:
ASSERT(FALSE);
break;
}
return S_OK;
}
/*
* CustomToolbarHandler - Handle the MSInfo-specific toolbar selection event.
* Note this also handles the toolbar deselect all event.
*
* History: a-jsari 9/24/97 Initial version
*/
HRESULT CSystemInfo::OnControlbarSelect(BOOL fDeselectAll, LPARAM lSelection,
LPDATAOBJECT)
{
#if 0
ASSERT(IsPrimaryImpl());
if (IsPrimaryImpl() == FALSE) return S_OK;
#endif
HRESULT hr;
// Split selection into scope/selection.
BOOL bScope = (BOOL) LOWORD(lSelection);
BOOL bSelect = (BOOL) HIWORD(lSelection);
if (fDeselectAll) bSelect = FALSE;
do {
hr = EnableToolbar(bSelect);
if (FAILED(hr)) break;
hr = EnableSupportTools(bSelect);
} while (0);
return hr;
}
/*
* OnDoubleClick - Handler for Double click event
*
* History: a-jsari 10/3/97 Stub version
*/
HRESULT CSystemInfo::OnDoubleClick(LPDATAOBJECT pDataObject)
{
CDataObject *pdoSelection = GetInternalFromDataObject(pDataObject);
if(NULL == pdoSelection)
return E_FAIL;
// Allow MMC to open the scope node..
if (pdoSelection->Context() == CCT_SCOPE) return S_FALSE;
return S_OK;
}
/*
* OnMenuButtonClick - Handle the SupportTool MENUBUTTON Button click event.
*
* History: a-jsari 9/18/97 Initial version.
*/
HRESULT CSystemInfo::OnMenuButtonClick(LPDATAOBJECT *ppDataObject,
LPMENUBUTTONDATA pMenuData)
{
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
ASSERT(ppDataObject != NULL);
ASSERT(pMenuData != NULL);
if (ppDataObject == NULL || pMenuData == NULL) return E_POINTER;
// Get the pop-up menu we will use to process our commands.
CMenu *pMenu = m_mnuSupport.GetSubMenu(0);
if (pMenu == NULL) return S_FALSE;
unsigned long lCommand = pMenu->TrackPopupMenu(TPM_RETURNCMD | TPM_NONOTIFY,
pMenuData->x, pMenuData->y, ::AfxGetMainWnd());
// We track both the Toolset index and the Tool index with a single long,
// bit-shifting and or'ing them together into lCommand.
//
// The lCommand item is the index of the Toolset left-shifted 8 times
// or'd with the index of the Tool
// lCommand == 0 is the value for items we didn't set.
if (lCommand != 0)
(*m_plistTools)[lCommand >> 8]->RunTool((lCommand & 0xff) - 1);
return S_OK;
}
/*
* OnPrint - Handle the print event.
*
* History: a-jsari 2/26/98 Initial version
*/
HRESULT CSystemInfo::OnPrint()
{
dynamic_cast<CSystemInfoScope *>(pComponentData())->PrintReport();
return S_OK;
}
/*
* OnProperties - Handle the VERB_PROPERTIES event.
*
* History: a-jsari 10/3/97 Stub version.
*/
HRESULT CSystemInfo::OnProperties(LPDATAOBJECT)
{
return S_OK;
}
/*
* OnPropertyChange - Handle the property change event.
*
* History: a-jsari 9/1/97 Stub version
*/
HRESULT CSystemInfo::OnPropertyChange(LPDATAOBJECT lpdo)
{
return dynamic_cast<CSystemInfoScope *>(pComponentData())->OnProperties((LPARAM)lpdo);
}
/*
* OnRefresh - Handle the refresh event.
*
* History: a-jsari 10/3/97 Initial version
*/
HRESULT CSystemInfo::OnRefresh(LPDATAOBJECT)
{
dynamic_cast<CSystemInfoScope *>(pComponentData())->Refresh(m_pfLast, this);
return S_OK;
}
/*
* OnSelect - Called when any node is selected or deselected.
*
* History: a-jsari 9/24/97 Initial version
*/
HRESULT CSystemInfo::OnSelect(LPDATAOBJECT pDataObject, LPARAM lSelection)
{
HRESULT hr = S_OK;
hr = HandleStandardVerbs(LOWORD(lSelection), pDataObject); // LOWORD(lSelection) is scope flag
// It turns out that it's better to handle drawing the contents of a category
// only on the SHOW message (rather than the SELECT message). This avoids showing
// data for a category which wasn't fully selected (i.e. right click, then ESC
// from the context menu).
return hr;
#if FALSE
HRESULT hr = S_OK;
do
{
BOOL fSelect = HIWORD(lSelection);
BOOL fScope = LOWORD(lSelection);
hr = HandleStandardVerbs(fScope, pDataObject);
if (FAILED(hr)) break;
CDataObject * pdoLast = GetInternalFromDataObject(pDataObject);
// If the folder is being deselected, check to see if it is currently
// being refreshed. If it is, change the variable so the threaded
// refresh knows not to update the display.
if (fScope && !fSelect)
{
if (pdoLast->Category() == m_pLastRefreshedFolder)
m_pLastRefreshedFolder = NULL;
}
// We handle it if it's a scope item and is being selected.
if (fScope && fSelect)
{
// Remember the last selection for OnViewChange.
ASSERT(pdoLast != NULL);
ASSERT(pdoLast->Context() == CCT_SCOPE);
// Remember the last selected Folder.
m_pfLast = pdoLast->Category();
m_pLastRefreshedFolder = m_pfLast;
DisplayFolder(m_pfLast);
dynamic_cast<CSystemInfoScope *>(pComponentData())->SetSelectedFolder(m_pfLast);
}
} while (0);
return hr;
#endif
}
/*
* DisplayFolder - Display all result-pane data for the current folder.
*
* History: a-jsari 12/11/97 Initial version
*/
HRESULT CSystemInfo::DisplayFolder(CFolder *pFolder)
{
HRESULT hr;
if (pFolder && pFolder->GetType() == CDataSource::OCX)
{
// If the refresh fails (for instance, if there is no OCX installed to show
// the stream), display a message (unless this is the root node).
COCXFolder * pOCXFolder = reinterpret_cast<COCXFolder *>(pFolder);
LPOLESTR lpCLSID;
if (pOCXFolder && SUCCEEDED(StringFromCLSID(pOCXFolder->m_clsid, &lpCLSID)))
{
CString strCLSID(lpCLSID);
CoTaskMemFree(lpCLSID);
IUnknown * pUnknown = NULL;
m_mapCLSIDToIUnknown.Lookup(strCLSID, (void*&) pUnknown);
if (!pOCXFolder->Refresh(pUnknown) && pFolder->GetParentNode() && pFolder->GetChildNode() == NULL)
SetRefreshing(lparamNoOCXIndicator);
}
return S_OK;
}
CSystemInfoScope * pSysScope = dynamic_cast<CSystemInfoScope *>(pComponentData());
if (pSysScope && pSysScope->InRefresh() && pFolder && pFolder->GetChildNode() == NULL)
{
SetRefreshing(lparamRefreshIndicator);
return S_OK;
}
do {
hr = ClearResultsPane();
ASSERT(hr == S_OK);
if (FAILED(hr)) break;
// Create this folder's header columns
hr = SetResultHeaderColumns(pFolder);
if (FAILED(hr)) break;
// Display all values under those column headers.
hr = EnumerateValues(pFolder);
} while (FALSE);
return hr;
}
/*
* OnShow - Notification when a scope item gets its first selection, or
* when the Snap-in is being unloaded.
*
* History: a-jsari 10/2/97 Initial version
*/
HRESULT CSystemInfo::OnShow(LPDATAOBJECT pDataObject, LPARAM fActive, HSCOPEITEM)
{
HRESULT hr = S_OK;
CDataObject * pdoSelection = GetInternalFromDataObject(pDataObject);
if (!fActive)
{
// If the folder is being deselected, check to see if it is currently
// being refreshed. If it is, change the variable so the threaded
// refresh knows not to update the display.
if (pdoSelection->Category() == m_pLastRefreshedFolder)
m_pLastRefreshedFolder = NULL;
return hr;
}
do
{
ASSERT(pdoSelection != NULL);
ASSERT(pdoSelection->Context() == CCT_SCOPE);
CFolder * pfolSelection = pdoSelection->Category();
m_pLastRefreshedFolder = pfolSelection;
dynamic_cast<CSystemInfoScope *>(pComponentData())->RefreshAsync(pfolSelection, this);
// Remember the last selected Folder.
m_pfLast = pfolSelection;
dynamic_cast<CSystemInfoScope *>(pComponentData())->SetSelectedFolder(m_pfLast);
// Folders may be NULL if Initialize fails.
if (pfolSelection != NULL)
{
hr = DisplayFolder(pfolSelection);
hr = HandleStandardVerbs((BOOL)fActive, pDataObject);
}
} while (0);
return hr;
}
/*
* OnUpdateView - Handle the view update event
*
* History: a-jsari 9/1/97 Stub version
*/
HRESULT CSystemInfo::OnUpdateView(LPARAM arg)
{
HRESULT hr = S_OK;
// arg != 0 is passed by CSystemInfoScope::OpenFile
if (m_pfLast != NULL && arg == 0) {
hr = DisplayFolder(m_pfLast);
}
// Do this so that the refresh verb goes away when we load a file.
SetInitialVerbState(TRUE);
return hr;
}