|
|
/* CompData.cpp : Implementation of the ComponentData (namespace items) for
* the MSInfo Snapin. * * Copyright (c) 1998-1999 Microsoft Corporation * * History: a-jsari 8/27/97 Initial version */
#include "StdAfx.h"
#include <Commdlg.h>
#include <iostream.h>
#include <atlbase.h>
#include <htmlhelp.h>
#ifndef IDB_16x16
#include "Resource.h"
#endif // IDB_16x16
#include "resrc1.h"
#include "DataObj.h"
#include "CompData.h"
#include "DataSrc.h"
#include "SysInfo.h"
#include "ViewObj.h"
#include "Dialogs.h"
#include "chooser.h"
static LPCTSTR cszViewKey = _T("Software\\Microsoft\\MSInfo"); static LPCTSTR cszViewValue = _T("View"); static LPCTSTR cszBasicValue = _T("basic"); static LPCTSTR cszAdvancedValue = _T("advanced");
/*
* CSystemInfoScope - Trivial constructor. Make sure all of our * essential pointers start NULL. * * History: a-jsari 8/27/97 Initial version */ CSystemInfoScope::CSystemInfoScope() :m_pScope(NULL), m_pConsole(NULL), m_pSource(NULL), m_bIsDirty(FALSE), m_bInitializedCD(FALSE), m_fViewUninitialized(FALSE), m_prdSave(NULL), m_prdOpen(NULL), m_prdReport(NULL), m_pthdFind(NULL), m_BasicFlags(0L), m_AdvancedFlags(MF_CHECKED), m_pwConsole(NULL), m_pmapCategories(NULL), m_pstrMachineName(new CString), m_pstrOverrideName(new CString), m_pstrCategory(NULL), m_RootCookie(0), m_fSelectCategory(FALSE), m_pSetSourceSource(NULL), m_fSetSourcePreLaunch(FALSE), m_pViewCABTool(NULL), m_pSaveUnknown(NULL), m_fInternalDelete(FALSE), m_pLastSystemInfo(NULL) { #ifdef _DEBUG
m_bDestroyedCD = true; #endif // _DEBUG
}
/*
* ~CSystemInfoScope - Never called. Don't use. * * History: a-jsari 8/27/97 Initial version */ CSystemInfoScope::~CSystemInfoScope() { #ifdef _DEBUG
if (m_bInitializedCD) ASSERT(m_pScope == NULL); ASSERT(m_pConsole == NULL); ASSERT(m_bDestroyedCD); #endif
}
/*
* InitializeDialogs - Pre-create our Dialog pointers to speed their loading when * they are needed. * * History: a-jsari 11/28/97 Moved from Initialize */ inline HRESULT CSystemInfoScope::InitializeDialogs() { HWND hWindow;
ASSERT(m_pConsole != NULL); HRESULT hr = m_pConsole->GetMainWindow(&hWindow); ASSERT(hr == S_OK); if (FAILED(hr)) return hr;
ASSERT(m_prdReport == NULL); m_prdReport = new CMSInfoReportDialog(hWindow); ASSERT(m_prdReport != NULL); if (m_prdReport == NULL) ::AfxThrowMemoryException();
m_prdSave = new CMSInfoSaveDialog(hWindow); ASSERT(m_prdSave != NULL); if (m_prdSave == NULL) ::AfxThrowMemoryException();
m_prdOpen = new CMSInfoOpenDialog(hWindow); ASSERT(m_prdOpen != NULL); if (m_prdOpen == NULL) ::AfxThrowMemoryException();
return hr; }
/*
* FindWindowProc - The window proc for the hidden window that will allow us to * call find from the Find Dialog Thread. * * History: a-jsari 2/6/98 Initial version */ static LRESULT CALLBACK FindWindowProc(HWND, UINT uMsg, WPARAM wParam, LPARAM lParam) { // ASSERT(uMsg == CFindDialog::WM_MSINFO_FIND);
// Only process our specific message.
if (uMsg == CFindDialog::WM_MSINFO_FIND) reinterpret_cast<CSystemInfoScope *>(wParam)->ExecuteFind((long)lParam); return 1; }
/*
* InitializeInternal - Because MMC never calls our destructor, we are leaking * memory in our member classes. To fix this, allocate them on the heap * and delete them in our Destroy method. * * History: a-jsari 12/30/97 Initial version */ inline HRESULT CSystemInfoScope::InitializeInternal() { AFX_MANAGE_STATE(::AfxGetStaticModuleState());
m_pmapCategories = new CScopeItemMap; ASSERT(m_pmapCategories != NULL); if (m_pmapCategories == NULL) ::AfxThrowMemoryException();
CString strClassName; CString strWindowName; HWND hwndParent; CREATESTRUCT csFind;
VERIFY(strClassName.LoadString(IDS_FINDCLASS)); VERIFY(strWindowName.LoadString(IDS_FINDWINDOWNAME));
WNDCLASSEX wceFind; ::memset(&wceFind, 0, sizeof(wceFind)); wceFind.cbSize = sizeof(wceFind); wceFind.style = CS_CLASSDC; wceFind.lpfnWndProc = FindWindowProc; wceFind.hInstance = ::AfxGetInstanceHandle(); wceFind.lpszClassName = (LPCTSTR)strClassName;
::RegisterClassEx(&wceFind); pConsole()->GetMainWindow(&hwndParent); m_hwndFind = ::CreateWindow(strClassName, strWindowName, WS_CHILD, 0, 0, 0, 0, hwndParent, NULL, wceFind.hInstance, &csFind); ASSERT(m_hwndFind != NULL); return S_OK; }
/*
* SkipSpaces - Advance the pointer passed in beyond all spaces. * * History: a-jsari 11/28/97 Initial version */ inline void SkipSpaces(LPTSTR &pszString) { while (_istspace(*pszString)) ++pszString; }
/*
* GetValue - Save the value (of the form '= Value' out of pszString into * szValue. * * History: a-jsari 11/28/97 Initial version */ static inline BOOL GetValue(LPTSTR &pszString, LPTSTR szValue) { SkipSpaces(pszString); //if (*pszString++ != (TCHAR)'=')
// return FALSE;
if (*pszString == (TCHAR)'=') pszString++;
SkipSpaces(pszString); if (*pszString == (TCHAR)'"') {
++pszString; do { *szValue = *pszString; if (*szValue++ == 0) return FALSE; } while ((*pszString++ != '"'));
*--szValue = (TCHAR)0; } else { do { *szValue++ = *pszString; if (*pszString == 0) return TRUE; } while (!::_istspace(*pszString++)); *--szValue = (TCHAR)0; } return TRUE; }
/*
* DisplayHelp - Show the help information for MSInfo * * History: a-jsari 11/28/97 Initial version */ static inline void DisplayHelp(LPTSTR /* szHelp */) { AFX_MANAGE_STATE(::AfxGetStaticModuleState());
CString strHelpFile; VERIFY(strHelpFile.LoadString(IDS_HELPFILE)); ::HtmlHelp(/* HWND */ NULL, strHelpFile, HH_DISPLAY_TOPIC, 0); }
/*
* ProcessCommandLine - Grab all of the essential values out of our command * line. * * History: a-jsari 11/28/97 Initial version */ HRESULT CSystemInfoScope::ProcessCommandLine() { const int VALUE_SIZE = 256; LPTSTR szCommands = ::GetCommandLine(); LPTSTR pszCurrent = szCommands; TCHAR szValueBuffer[VALUE_SIZE]; int iFirst;
if (pszCurrent == NULL) return E_FAIL; while (TRUE) { iFirst = _tcscspn(pszCurrent, _T(" \t"));
// If our match is \0, we have reached the end of the string.
if (pszCurrent[iFirst] == (TCHAR)'\0') break;
pszCurrent += iFirst; ++pszCurrent; SkipSpaces(pszCurrent);
// Not a command line switch, check the next parameter.
if (!(*pszCurrent == (TCHAR)'/' || *pszCurrent == (TCHAR)'-')) continue; else ++pszCurrent;
// We are processing the computer flag.
if (_tcsnicmp(pszCurrent, _T("computer"), 8) == 0) { pszCurrent += 8; if (GetValue(pszCurrent, szValueBuffer) == TRUE) m_strDeferredMachine = szValueBuffer; }
// After this point, all flags are msinfo specific.
if (_tcsnicmp(pszCurrent, _T("msinfo"), 6) != 0) continue; pszCurrent += 6; // pszCurrent += strlen("msinfo");
if (*pszCurrent == (TCHAR)'?' || _tcsnicmp(pszCurrent, _T("_help"), 5) == 0) { LPTSTR pszValue; if (GetValue(pszCurrent, szValueBuffer) == TRUE) { pszValue = szValueBuffer; } else { // No value for help switch, back up to the previous space, unless we're
// at the end of the string.
if (*pszCurrent != 0) do --pszCurrent; while (!::_istspace(*pszCurrent)); pszValue = NULL; } DisplayHelp(pszValue); continue; }
if (_tcsnicmp(pszCurrent, _T("_category"), 9) == 0) { pszCurrent += 9; if (GetValue(pszCurrent, szValueBuffer) == TRUE) { // -1 parameter means select no result pane item.
m_pstrCategory = new CString(szValueBuffer); // SelectItem(szValueBuffer, -1);
} continue; }
if (_tcsnicmp(pszCurrent, _T("_file"), 5) == 0) { pszCurrent += 5; if (GetValue(pszCurrent, szValueBuffer) == TRUE) m_strDeferredLoad = szValueBuffer; continue; }
if (_tcsnicmp(pszCurrent, _T("_showcategories"), 15) == 0) { pszCurrent += 15; if (GetValue(pszCurrent, szValueBuffer) == TRUE) m_strDeferredCategories = szValueBuffer; continue; } }
return S_OK; }
/*
* Initialize - Called from MMC; we Initialize all of our relevant pointers * using QueryInterface and set the IConsole ImageList. * * History: a-jsari 8/27/97 Initial version */
STDMETHODIMP CSystemInfoScope::Initialize(LPUNKNOWN pUnknown) { ASSERT(pUnknown != NULL); TRACE(_T("CSystemInfoScope::Initialize\n"));
HRESULT hr;
do { AFX_MANAGE_STATE(AfxGetStaticModuleState());
// MMC should only call ::Initialize once!
ASSERT(m_pScope == NULL);
hr = pUnknown->QueryInterface(IID_IConsoleNameSpace, reinterpret_cast<void **>(&m_pScope));
ASSERT(hr == S_OK); if (FAILED(hr)) break;
ASSERT(m_pConsole == NULL); hr = pUnknown->QueryInterface(IID_IConsole, reinterpret_cast<void **>(&m_pConsole)); ASSERT(hr == S_OK); if (FAILED(hr)) break;
if (m_pSaveUnknown == NULL) // check this out, reversed
{ // We are reinitializing, so don't do the image list code again.
::CBitmap bmp16x16; ::CBitmap bmp32x32; LPIMAGELIST lpScopeImage;
hr = m_pConsole->QueryScopeImageList(&lpScopeImage); ASSERT(hr == S_OK); if (FAILED(hr)) break;
VERIFY(bmp16x16.LoadBitmap(IDB_16x16)); VERIFY(bmp32x32.LoadBitmap(IDB_32x32));
hr = lpScopeImage->ImageListSetStrip( reinterpret_cast<LONG_PTR *>(static_cast<HBITMAP>(bmp16x16)), reinterpret_cast<LONG_PTR *>(static_cast<HBITMAP>(bmp32x32)), 0, RGB(255,0,255));
(void)lpScopeImage->Release();
ASSERT(hr == S_OK); if (FAILED(hr)) break;
// This is also a fine place to add the log entry for starting MSInfo,
// so it won't be repeated when we reinitialize.
if (msiLog.IsLogging()) msiLog.WriteLog(CMSInfoLog::BASIC, _T("START MSInfo\r\n")); }
hr = InitializeDialogs(); if (FAILED(hr)) break;
hr = InitializeInternal(); if (FAILED(hr)) break;
hr = ProcessCommandLine();
} while (FALSE);
if (FAILED(hr)) { SAFE_RELEASE(m_pScope); SAFE_RELEASE(m_pConsole); } else { m_bInitializedCD = true; }
#ifdef _DEBUG
m_bDestroyedCD = false; #endif
// Note that MMC does not permit us to fail return from Initialize,
// so we always return S_OK, whether or not our Initialization is
// successful.
return S_OK; }
/*
* InitializeView - Read the current user's view information from the registry * * History: a-jsari 12/3/97 Initial version. */ HRESULT CSystemInfoScope::InitializeView() { CRegKey crkView; long lResult; TCHAR szBuffer[1024]; DWORD dwSize;
lResult = crkView.Open(HKEY_CURRENT_USER, cszViewKey); if (lResult == ERROR_SUCCESS) { dwSize = sizeof(szBuffer); lResult = crkView.QueryValue(szBuffer, cszViewValue, &dwSize); } if (lResult != ERROR_SUCCESS) // Default to basic view.
SetView(BASIC, TRUE); else { if (::_tcscmp(szBuffer, cszBasicValue) == 0) SetView(BASIC, FALSE); else if (::_tcscmp(szBuffer, cszAdvancedValue) == 0) SetView(ADVANCED, FALSE); else { ASSERT(FALSE); return E_FAIL; } } return S_OK; }
HRESULT CSystemInfoScope::MessageBox( CString strText) { CString strTitle; strTitle.LoadString( IDS_DESCRIPTION); int nRC;
return pConsole()->MessageBox( strText, strTitle, MB_OK, &nRC); }
/*
* InitializeSource - Perform any initialization which may fail. * * History: a-jsari 12/3/97 Initial version. */ HRESULT CSystemInfoScope::InitializeSource() { AFX_MANAGE_STATE(::AfxGetStaticModuleState()); CWaitCursor DoWaitCursor;
try { // m_pSource will exist if we were loaded from a stream.
if (m_pSource == NULL) { m_bInitializedCD = true; // Initialize WBEM with the machine name.
// Deleted in either SetView or Destroy
m_pSource = new CWBEMDataSource(MachineName()); } } catch (CUserException *) { CString strLocalConnect;
VERIFY(strLocalConnect.LoadString(IDS_LOCAL_CONNECT)); MessageBox((LPCTSTR)strLocalConnect);
try { (*m_pstrMachineName) = _T(""); m_pSource = new CWBEMDataSource(NULL); } catch (CUserException *) { m_bInitializedCD = false; return E_FAIL; } } m_fViewUninitialized = TRUE; InitializeView(); return S_OK; }
/*
* DestroyInternal - Delete all of our internal pointers. This method of dealing * with pointers is required because MMC never calls our object's destructor. * * History: a-jsari 12/30/97 Initial version */ void CSystemInfoScope::DestroyInternal() { // AFX_MANAGE_STATE(::AfxGetStaticModuleState());
if (pSource() && pSource()->GetType() == CDataSource::GATHERER) { CWBEMDataSource * pWBEMSource = reinterpret_cast<CWBEMDataSource *>(pSource()); if (pWBEMSource && pWBEMSource->m_pThreadRefresh) pWBEMSource->m_pThreadRefresh->CancelRefresh(FALSE); }
// If there is a find thread, it will take care of getting rid of the window.
// Otherwise, we must destroy it here. Fixes bug 395091.
if (m_pthdFind) dynamic_cast<CFindThread *>(m_pthdFind)->RemoteQuit(); else ::DestroyWindow(m_hwndFind);
if (m_pSource) { delete m_pSource; m_pSource = NULL; } if (m_prdSave) { delete m_prdSave; m_prdSave = NULL; } if (m_prdOpen) { delete m_prdOpen; m_prdOpen = NULL; } if (m_prdReport) { delete m_prdReport; m_prdReport = NULL; } if (m_pstrMachineName) { delete m_pstrMachineName; m_pstrMachineName = NULL; } if (m_pstrOverrideName) { delete m_pstrOverrideName; m_pstrOverrideName = NULL; } if (m_pmapCategories) { delete m_pmapCategories; m_pmapCategories = NULL; } if (m_pViewCABTool) { delete m_pViewCABTool; m_pViewCABTool = NULL; } }
/*
* CreateComponent - Create the IComponent interface object (the CSystemInfo * object in this framework) and attach myself (the IComponentData * interface object) to it. Return the QueryInterfaced IComponent * pointer in ppComponent. * * History: a-jsari 8/27/97 Initial version */ STDMETHODIMP CSystemInfoScope::CreateComponent(LPCOMPONENT *ppComponent) { ASSERT(ppComponent != NULL); TRACE(_T("CSystemInfoScope::CreateComponent\n"));
#if 0
if (m_bInitializedCD == false) { *ppComponent = NULL; return S_OK; } #endif
CComObject<CSystemInfo> *pObject;
CComObject<CSystemInfo>::CreateInstance(&pObject); ASSERT(pObject != NULL);
if(NULL == pObject) return E_OUTOFMEMORY;
m_pLastSystemInfo = pObject;
//Store IComponentData
HRESULT hr; hr = pObject->SetIComponentData(this); ASSERT(hr == S_OK); if (FAILED(hr)) { return hr; }
return pObject->QueryInterface(IID_IComponent, reinterpret_cast<void **>(ppComponent)); }
/*
* PreUIInit - Make any changes required just before the UI initializes. * * History: a-jsari 3/6/98 Initial version */ HRESULT CSystemInfoScope::PreUIInit() { HRESULT hr = S_OK;
if (m_pSource == NULL) { hr = InitializeSource(); } else { hr = InitializeView(); } return hr; }
/*
* PostUIInit - Do all initialization which can only occur after the result * pane UI * * History: a-jsari 3/6/98 Initial version */ void CSystemInfoScope::PostUIInit() { if (!m_strDeferredLoad.IsEmpty() || !m_strDeferredMachine.IsEmpty()) { // Instead of doing a "SetSource(m_pSource, FALSE)", which deletes the
// tree, all we need to do here is rename the root node to match the
// opened file. A non-empty m_strDeferredLoad indicates this is necessary.
// (Or a non empty deferred machine change.)
m_strDeferredLoad.Empty(); m_strDeferredMachine.Empty();
SCOPEDATAITEM sdiRoot; CString strNodeName; HSCOPEITEM hsiRoot; HRESULT hr;
if (m_pmapCategories->ScopeFromView(NULL, hsiRoot)) { ::memset(&sdiRoot, 0, sizeof(sdiRoot)); sdiRoot.ID = hsiRoot; sdiRoot.mask = SDI_STR; hr = pScope()->GetItem(&sdiRoot); ASSERT(SUCCEEDED(hr));
if (SUCCEEDED(hr)) { m_pSource->GetNodeName(strNodeName); sdiRoot.displayname = T2OLE(const_cast<LPTSTR>((LPCTSTR)strNodeName)); hr = pScope()->SetItem(&sdiRoot); ASSERT(SUCCEEDED(hr)); } } }
// This is the first point at which we can set UI values.
if (m_fViewUninitialized && m_fSelectCategory) { m_fViewUninitialized = FALSE;
SetSource(m_pSource, FALSE); } if (m_pstrCategory != NULL && m_fSelectCategory) { // Before the SelectItem call to prevent recursion.
m_fSelectCategory = FALSE; SelectItem(*m_pstrCategory); delete m_pstrCategory; m_pstrCategory = NULL; } }
/*
* Notify - Handle any MSInfo namespace node events posted by MMC. * * History: a-jsari 8/27/97 Initial version */
STDMETHODIMP CSystemInfoScope::Notify(LPDATAOBJECT pDataObject, MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param) { TRACE(_T("CSystemInfoScope::Notify (DataObject, %lx, %p, %p)\n"), event, arg, param); HRESULT hr;
if (m_bInitializedCD == false) return S_OK;
switch(event) { case MMCN_EXPAND: if (m_pSaveUnknown) { m_pstrMachineName = new CString; m_pstrOverrideName = new CString; Initialize(m_pSaveUnknown); m_pSaveUnknown = NULL; }
hr = PreUIInit(); if (FAILED(hr)) break; hr = OnExpand(pDataObject, arg, param); PostUIInit(); break;
case MMCN_REMOVE_CHILDREN: // Sometimes we make an internal call which causes this notification to be
// sent, but we don't want to process it the same way.
if (!m_fInternalDelete) { m_pSaveUnknown = m_pScope;
DestroyInternal(); SAFE_RELEASE(m_pScope); SAFE_RELEASE(m_pConsole); m_pScope = NULL; m_pConsole = NULL; m_pSource = NULL; m_prdSave = NULL; m_prdOpen = NULL; m_prdReport = NULL; m_pstrMachineName = NULL; m_pstrOverrideName = NULL; m_pmapCategories = NULL; }
hr = S_OK; break;
case MMCN_PROPERTY_CHANGE: hr = OnProperties(param); break;
case MMCN_EXPANDSYNC: break;
default: ASSERT(FALSE); break; }
return hr; }
/*
* Destroy - Release all of our Initialized pointers. * * History: a-jsari 8/27/97 Initial version */ STDMETHODIMP CSystemInfoScope::Destroy() { TRACE(L"CSystemInfoScope::Destroy\n");
if (m_pwConsole != NULL) { m_pwConsole->Detach(); delete m_pwConsole; }
#if FALSE
#ifdef _DEBUG
m_bDestroyedCD = true; #endif
#if 0
if (m_bInitializedCD == FALSE) return S_OK; #endif
DestroyInternal(); SAFE_RELEASE(m_pScope); SAFE_RELEASE(m_pConsole); #endif
return S_OK; }
/*
* QueryDataObject - Return the DataObject referred to by the cookie * and type. * * History: a-jsari 8/27/97 Initial version */ STDMETHODIMP CSystemInfoScope::QueryDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type, LPDATAOBJECT *ppDataObject) { TRACE(_T("CSystemInfoScope::QueryDataObject (%lx, %x, DataObject)\n"), cookie, type);
return CDataObject::CreateDataObject(cookie, type, this, ppDataObject); }
/*
* CompareObjects - Compare two objects to see if they are equivalent. * * History: a-jsari 8/27/97 Initial version */ STDMETHODIMP CSystemInfoScope::CompareObjects(LPDATAOBJECT lpDataObjectA, LPDATAOBJECT lpDataObjectB) { TRACE(_T("CSystemInfoScope::CompareObjects\n")); return CDataObject::CompareObjects(lpDataObjectA, lpDataObjectB); }
/*
* GetDisplayInfo - Returns display information for this node in the scope pane. * * History: a-jsari 8/27/97 Initial version */ STDMETHODIMP CSystemInfoScope::GetDisplayInfo(SCOPEDATAITEM *pScopeDataItem) { USES_CONVERSION;
#if 0
TRACE(_T("CSystemInfoScope::GetDisplayInfo\n")); #endif
ASSERT(pScopeDataItem != NULL); if (pScopeDataItem == NULL) return E_POINTER;
ASSERT(pScopeDataItem->mask & SDI_STR); if (pScopeDataItem->mask & SDI_STR) { CViewObject *pDataCategory = reinterpret_cast<CViewObject *>(pScopeDataItem->lParam); pScopeDataItem->displayname = T2OLE(const_cast<LPTSTR>(pDataCategory->GetTextItem())); }
return S_OK; }
/*
* AddToMenu - Add an item to a menu. This method assumes that the calling * function has called AFX_MANAGE_STATE(AfxGetStaticModuleState()) prior * to calling this function. * * History: a-jsari 9/15/97 Initial version */ HRESULT CSystemInfoScope::AddToMenu(LPCONTEXTMENUCALLBACK lpCallback, long lNameResource, long lStatusResource, long lCommandID, long lInsertionPoint, long fFlags) { USES_CONVERSION;
CONTEXTMENUITEM cmiMenuItem = { NULL, NULL, lCommandID, lInsertionPoint, fFlags, 0L}; CString szResourceName; CString szResourceStatus;
// FIX: Make these resources load only once.
VERIFY(szResourceName.LoadString(lNameResource)); VERIFY(szResourceStatus.LoadString(lStatusResource)); cmiMenuItem.strName = WSTR_FROM_CSTRING(szResourceName); cmiMenuItem.strStatusBarText = WSTR_FROM_CSTRING(szResourceStatus); HRESULT hr = lpCallback->AddItem(&cmiMenuItem); ASSERT(hr == S_OK); return hr; }
/*
* AddMenuItems - Add the "Save Report" and "Save System Information" items to * the context menu. * * History: a-jsari 9/15/97 Initial version */ extern BOOL fCABOpened;
STDMETHODIMP CSystemInfoScope::AddMenuItems(LPDATAOBJECT lpDataObject, LPCONTEXTMENUCALLBACK lpCallback, long *pInsertionAllowed) { TRACE(_T("CSystemInfoScope::AddMenuItems\n")); ASSERT(lpDataObject != NULL); ASSERT(lpCallback != NULL); ASSERT(pInsertionAllowed != NULL); if (lpDataObject == NULL || lpCallback == NULL || pInsertionAllowed == NULL) return E_POINTER;
HRESULT hr = S_OK;
// Note - snap-ins need to look at the data object and determine in what
// context menu items need to be added. They must also observe the
// insertion allowed flags to see what items can be added.
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// CHECK: Will this ever work differently for multiselect?
do { // Save Report and Save File are both task items and context items.
if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP) { hr = AddToTopMenu(lpCallback, IDS_SAVEREPORTMENUNAME, IDS_SAVEREPORTSTATUS, IDM_SAVEREPORT); if (FAILED(hr)) break; hr = AddToTopMenu(lpCallback, IDS_SAVEFILEMENUNAME, IDS_SAVEFILESTATUS, IDM_SAVEFILE); if (FAILED(hr)) break; hr = AddToTopMenu(lpCallback, IDS_FINDMENUNAME, IDS_FINDSTATUS, IDM_FIND); if (FAILED(hr)) break; }
if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TASK) {
hr = AddToTaskMenu(lpCallback, IDS_FINDMENUNAME, IDS_FINDSTATUS, IDM_TASK_FIND); if (FAILED(hr)) break;
// Don't add the Open File menu item for Extension snap-ins.
if (IsPrimaryImpl()) { hr = AddToTaskMenu(lpCallback, IDS_OPENFILEMENUNAME, IDS_OPENFILESTATUS, IDM_TASK_OPENFILE); if (FAILED(hr)) break;
CDataSource * pCurrentSource = pSource(); if (pCurrentSource && pCurrentSource->GetType() != CDataSource::GATHERER) hr = AddToTaskMenu(lpCallback, IDS_CLOSEFILEMENUNAME, IDS_CLOSEFILEMENUSTATUS, IDM_TASK_CLOSE); else hr = AddToMenu(lpCallback, IDS_CLOSEFILEMENUNAME, IDS_CLOSEFILEMENUSTATUS, IDM_TASK_CLOSE, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_GRAYED);
if (FAILED(hr)) break; }
hr = AddToTaskMenu(lpCallback, IDS_SAVEFILEMENUNAME, IDS_SAVEFILESTATUS, IDM_TASK_SAVEFILE); if (FAILED(hr)) break; hr = AddToTaskMenu(lpCallback, IDS_SAVEREPORTMENUNAME, IDS_SAVEREPORTSTATUS, IDM_TASK_SAVEREPORT); if (FAILED(hr)) break;
// If a CAB file has been opened, add the view CAB contents menu item. Also
// take this opportunity to create the tool to view the CAB contents, if it
// has not already been created.
if (fCABOpened) { if (m_pViewCABTool == NULL) m_pViewCABTool = new CCabTool(this);
if (m_pViewCABTool != NULL) { hr = AddToTaskMenu(lpCallback, IDS_CAB_NAME, IDS_CAB_DESCRIPTION, IDM_TASK_VIEWCAB); if (FAILED(hr)) break; } } }
if (*pInsertionAllowed & CCM_INSERTIONALLOWED_VIEW) { hr = AddToViewMenu(lpCallback, IDS_ADVANCEDVIEWNAME, IDS_ADVANCEDSTATUS, IDM_VIEW_ADVANCED, m_AdvancedFlags); if (FAILED(hr)) break; hr = AddToViewMenu(lpCallback, IDS_BASICVIEWNAME, IDS_BASICSTATUS, IDM_VIEW_BASIC, m_BasicFlags); if (FAILED(hr)) break; }
} while (FALSE); return hr; }
/*
* DisplayFileError - Show a message box with an error message taken from * the exception thrown. * * History: a-jsari 2/13/98 Initial version */ static inline void DisplayError(HRESULT hr, const CString &strFileName) { AFX_MANAGE_STATE(::AfxGetStaticModuleState());
USES_CONVERSION; CString strFileError, strTitle; switch (hr) { case STG_E_PATHNOTFOUND: strFileError.Format(IDS_BAD_PATH, (LPCTSTR)strFileName); break; case STG_E_TOOMANYOPENFILES: VERIFY(strFileError.LoadString(IDS_TOOMANYOPENFILES)); break; case STG_E_ACCESSDENIED: strFileError.Format(IDS_ACCESS_DENIED, (LPCTSTR)strFileName); break; case STG_E_SHAREVIOLATION: strFileError.Format(IDS_SHARING_VIOLATION, (LPCTSTR)strFileName); break; case STG_E_WRITEFAULT: VERIFY(strFileError.LoadString(IDS_HARDIO)); break; case STG_E_MEDIUMFULL: strFileError.Format(IDS_DISK_FULL, (LPCTSTR)strFileName); break; default: VERIFY(strFileError.LoadString(IDS_UNKNOWN_FILE)); break; } strTitle.LoadString(IDS_DESCRIPTION); ::MessageBox( ::AfxGetMainWnd()->GetSafeHwnd(), strFileError, strTitle, MB_OK); }
/*
* SaveReport - Create the save report save file dialog and save the selected file. * * History: a-jsari 12/8/97 Initial version */ void CSystemInfoScope::SaveReport() { if (m_prdReport->DoModal() == IDOK) { CWaitCursor DoWaitCursor;
if (m_pLastSystemInfo) m_pLastSystemInfo->SetStatusText(IDS_REFRESHING_MSG);
HRESULT hr = pSource()->ReportWrite(m_prdReport->GetPathName(), m_pfLast);
if (m_pLastSystemInfo) m_pLastSystemInfo->SetStatusText(_T(""));
if (FAILED(hr)) { ::DisplayError(hr, m_prdReport->GetPathName()); } } }
/*
* SaveFile - Create the save file dialog and save the selected file. * * History: a-jsari 12/8/97 Initial version */ void CSystemInfoScope::SaveFile() { if (m_prdSave->DoModal() == IDOK) { CWaitCursor DoWaitCursor;
if (m_pLastSystemInfo) m_pLastSystemInfo->SetStatusText(IDS_REFRESHING_MSG);
HRESULT hr = pSource()->SaveFile(m_prdSave->GetPathName());
if (m_pLastSystemInfo) m_pLastSystemInfo->SetStatusText(_T(""));
if (FAILED(hr)) ::DisplayError(hr, m_prdSave->GetPathName()); } }
/*
* PrintReport - Create the print dialog and do the print. * * History: a-jsari 12/8/97 Initial version */ void CSystemInfoScope::PrintReport() { HWND hWindow;
ASSERT(m_pConsole != NULL); HRESULT hr = m_pConsole->GetMainWindow(&hWindow); ASSERT(hr == S_OK); if (FAILED(hr)) return;
CMSInfoPrintDialog * prdPrint = new CMSInfoPrintDialog(hWindow); ASSERT(prdPrint != NULL); if (prdPrint == NULL) ::AfxThrowMemoryException();
prdPrint->m_pd.nToPage = prdPrint->m_pd.nFromPage = prdPrint->m_pd.nMinPage = 1; prdPrint->m_pd.nMaxPage = 1000;
if (prdPrint->DoModal() == IDOK) { CWaitCursor DoWaitCursor;
pSource()->RefreshPrintData(prdPrint, m_pfLast); pSource()->PrintReport(prdPrint, m_pfLast); }
delete prdPrint; }
/*
* DoFind - Display the Find dialog * * History: a-jsari 12/8/97 Initial version. */ void CSystemInfoScope::DoFind() { const UINT STACK_SIZE_PARENT = 0; // const DWORD FLAGS_IMMEDIATE_START = 0;
const LPSECURITY_ATTRIBUTES NO_ATTRIBUTES = NULL;
if (m_pthdFind == NULL) { m_pthdFind = dynamic_cast<CFindThread *>(::AfxBeginThread(RUNTIME_CLASS(CFindThread), THREAD_PRIORITY_NORMAL, STACK_SIZE_PARENT, CREATE_SUSPENDED, NO_ATTRIBUTES)); m_pthdFind->SetScope(this);
HWND hwndMMC; if (pConsole() == NULL || FAILED(pConsole()->GetMainWindow(&hwndMMC))) hwndMMC = NULL;
m_pthdFind->SetParent(m_hwndFind, hwndMMC); m_pthdFind->ResumeThread(); } else m_pthdFind->Activate(); }
/*
* ExecuteFind - This function is actually called via a hook into * MMC's main window's WindowProc, by a message posted by * CFindThread's Find button function.. * * The Refresh and Find functions may be interrupted by the Find * window's UI thread, and m_pthdFind may be deleted while this * function is executing. * * Instead of taking parameters, this function calls back to our * existing find thread to get its search string and last * search string. This simplifies the PostMessage call, but * would need to change if we ever decide to have multiple * find windows per IComponentData...unlikely. * * History: a-jsari 1/22/98 Initial version. */ void CSystemInfoScope::ExecuteFind(long lFindState) { AFX_MANAGE_STATE(::AfxGetStaticModuleState());
CWaitCursor DoWaitCursor; // Display the hourglass
CString strFindData; // Our current search string.
// The restricted context within which our search occurs.
static CFolder *pfContext;
// Check m_pthdFind since there's a remote possibility of thread pointer
// invalidation (by the user closing the Find dialog while the
// find is running).
if (m_pthdFind == NULL) return; strFindData = m_pthdFind->FindString();
CDataSource *pdsSearch = pSource(); do { if ((lFindState & CDataSource::FIND_OPTION_REPEAT_SEARCH) == 0) { // Only refresh the first time we search for a given string.
// Also, only refresh if we are searching more than category names.
BOOL fRefreshResult = TRUE; if ((lFindState & CDataSource::FIND_OPTION_CATEGORY_ONLY) == 0) { // If we are only searching in one category, only refresh that
// category.
if ((lFindState & CDataSource::FIND_OPTION_ONE_CATEGORY) != 0) { if (pdsSearch->GetType() == CDataSource::GATHERER) { CWBEMDataSource * pWBEMSource = reinterpret_cast<CWBEMDataSource *>(pSource()); if (pWBEMSource && pWBEMSource->m_pThreadRefresh) pWBEMSource->m_pThreadRefresh->RefreshFolder(m_pfLast, TRUE, FALSE); } } else fRefreshResult = pdsSearch->Refresh(TRUE); }
if (!fRefreshResult) { if (m_pthdFind != NULL) m_pthdFind->ResetSearch(); break; }
// Set our context the first time we start a restricted search.
if ((lFindState & CDataSource::FIND_OPTION_ONE_CATEGORY) != 0) pfContext = m_pfLast; else pfContext = NULL; } else if ((lFindState & CDataSource::FIND_OPTION_ONE_CATEGORY) != 0) { // If we set a restricted search inside an already started search
// restrict our context.
// CHECK: iDepth???
if (pfContext == NULL) pfContext = m_pfLast; } if (pdsSearch->Find(strFindData, lFindState) == FALSE) { // Failed find means no match or halted execution.
// If the user stoppped the find, no message necessary.
if (!pdsSearch->FindStopped()) {
CString strError; // Error display
CString strTitle; // Error title.
int nReturn;
// Test the thread because the find window might vanish in the middle
// of our find operation.
if (m_pthdFind != NULL) m_pthdFind->FindComplete(); if (m_pthdFind != NULL) m_pthdFind->ResetSearch();
// If we're repeating a search, no more matches otherwise, not found.
if ((lFindState & CDataSource::FIND_OPTION_REPEAT_SEARCH) == 0) { strError.Format(IDS_DATANOTFOUND, (LPCTSTR)strFindData); } else strError.Format(IDS_NOMOREMATCHES, (LPCTSTR)strFindData); VERIFY(strTitle.LoadString(IDS_FIND_TITLE)); pConsole()->MessageBox((LPCTSTR)strError, (LPCTSTR)strTitle, MB_TOPMOST|MB_SETFOREGROUND, &nReturn);
// If we are restricting our search, reset the selected folder to the
// beginning of our restricted search.
if ((lFindState & CDataSource::FIND_OPTION_ONE_CATEGORY) != 0) SetSelectedFolder(pfContext); // We've already completed the find, don't drop out.
return; } } else { SelectItem(pdsSearch->m_strPath, pdsSearch->m_iLine); } } while (FALSE); // The find window might vanish in the middle of our find operation.
if (m_pthdFind != NULL) m_pthdFind->FindComplete(); }
/*
* MainThreadStopFind - Stops a find operation running in an alternate thread. * * History: a-jsari 1/22/98 Initial version. */ void CSystemInfoScope::StopFind() { // This will be called by an alternate UI thread.
pSource()->StopSearch(); }
/*
* Refresh - Refresh the data, and redraw the current node if applicable. * * History: a-jsari 2/25/98 Initial version */ void CSystemInfoScope::Refresh(CFolder * pfSelected, CSystemInfo * pSystemInfo) { CWaitCursor DoWaitCursor;
if (pfSelected && pSource() && pSource()->GetType() == CDataSource::GATHERER) { CWBEMDataSource * pWBEMSource = reinterpret_cast<CWBEMDataSource *>(pSource()); if (pWBEMSource && pWBEMSource->m_pThreadRefresh) { if (pSystemInfo) pWBEMSource->m_pThreadRefresh->RefreshFolderAsync(pfSelected, pSystemInfo, TRUE, FALSE); else pWBEMSource->m_pThreadRefresh->RefreshFolder(pfSelected, TRUE, FALSE); } } else pSource()->Refresh();
if (pfSelected != NULL) { CString strName; int nLine = 0; pfSelected->InternalName(strName); SelectItem(strName, nLine); } }
/*
* CloseFindWindow - Function to be called when the find window closes. * * History: a-jsari 1/22/97 Initial version. */ void CSystemInfoScope::CloseFindWindow() { // Don't delete m_pthdFind; it will delete itself.
m_pthdFind = NULL; }
/*
* OpenFile - Create the open file file dialog and open the resultant file * * History: a-jsari 12/8/97 Initial version */ void CSystemInfoScope::OpenFile() { const long DONT_USE_LAST_FOLDER = 1;
if (m_prdOpen->DoModal() == IDOK) { CWaitCursor DoWaitCursor; CDataSource *pSource = NULL;
try { pSource = CBufferDataSource::CreateDataSourceFromFile(m_prdOpen->GetPathName()); } catch (...) { delete pSource; pSource = NULL; } if (pSource != NULL) { SetSource(pSource); InitializeView(); }
pConsole()->UpdateAllViews(0, DONT_USE_LAST_FOLDER, 0L);
// Reset the selected folder (it's no longer valid with the new tree).
SetSelectedFolder(NULL);
HSCOPEITEM hsiNode = NULL; if (m_pmapCategories && m_pmapCategories->ScopeFromView(NULL, hsiNode)) pConsole()->SelectScopeItem(hsiNode); } }
//-----------------------------------------------------------------------------
// Close the currently opened file.
//-----------------------------------------------------------------------------
void CSystemInfoScope::CloseFile() { CDataSource * pDataSource = pSource(); if (pDataSource && pDataSource->GetType() == CDataSource::GATHERER) return;
try { (*m_pstrMachineName) = _T(""); pDataSource = new CWBEMDataSource(NULL); } catch (CUserException *) { m_bInitializedCD = false; return; }
if (pDataSource != NULL) { SetSource(pDataSource); InitializeView(); }
const long DONT_USE_LAST_FOLDER = 1; pConsole()->UpdateAllViews(0, DONT_USE_LAST_FOLDER, 0L);
// Reset the selected folder (it's no longer valid with the new tree).
SetSelectedFolder(NULL); }
/*
* Command - Call the function represented by nCommandID. * * History: a-jsari 9/15/97 Initial version * * Note: This function currently takes no notice of the context represented * by pdoContext. */ STDMETHODIMP CSystemInfoScope::Command(long nCommandID, LPDATAOBJECT) { HRESULT hr = S_OK;
TRACE(_T("CSystemInfoScope::Command(%lx)\n"), nCommandID); AFX_MANAGE_STATE(::AfxGetStaticModuleState());
// For any of these commands, we want to cancel an async category refresh
// is there is one in progress.
if (pSource() && pSource()->GetType() == CDataSource::GATHERER) { CWBEMDataSource * pWBEMSource = reinterpret_cast<CWBEMDataSource *>(pSource()); if (pWBEMSource && pWBEMSource->m_pThreadRefresh) { CWaitCursor waitcursor; pWBEMSource->m_pThreadRefresh->WaitForRefresh(); } }
try { switch (nCommandID) { case IDM_SAVEREPORT: case IDM_TASK_SAVEREPORT: if (msiLog.IsLogging()) msiLog.WriteLog(CMSInfoLog::MENU, _T("MENU \"Save As Text\"\r\n")); SaveReport(); break;
case IDM_SAVEFILE: case IDM_TASK_SAVEFILE: if (msiLog.IsLogging()) msiLog.WriteLog(CMSInfoLog::MENU, _T("MENU \"Save NFO\"\r\n")); SaveFile(); break;
case IDM_TASK_FIND: case IDM_FIND: if (msiLog.IsLogging()) msiLog.WriteLog(CMSInfoLog::MENU, _T("MENU \"Find\"\r\n")); DoFind(); break;
case IDM_TASK_OPENFILE: if (msiLog.IsLogging()) msiLog.WriteLog(CMSInfoLog::MENU, _T("MENU \"Open NFO\"\r\n")); OpenFile(); break;
case IDM_TASK_VIEWCAB: if (msiLog.IsLogging()) msiLog.WriteLog(CMSInfoLog::MENU, _T("MENU \"View CAB\"\r\n")); if (m_pViewCABTool) m_pViewCABTool->RunTool(); break;
case IDM_VIEW_ADVANCED: if (msiLog.IsLogging()) msiLog.WriteLog(CMSInfoLog::MENU, _T("MENU \"Set View ADVANCED\"\r\n")); SetView(ADVANCED, TRUE); break;
case IDM_VIEW_BASIC: if (msiLog.IsLogging()) msiLog.WriteLog(CMSInfoLog::MENU, _T("MENU \"Set View BASIC\"\r\n")); SetView(BASIC, TRUE); break;
case IDM_TASK_CLOSE: if (msiLog.IsLogging()) msiLog.WriteLog(CMSInfoLog::MENU, _T("MENU \"Close NFO\"\r\n")); CloseFile(); break;
case ~0: // We get this result when we back arrow on the taskpad.
break;
default: ASSERT(FALSE); break; } } catch (...) { ASSERT(FALSE); hr = HRESULT_FROM_WIN32(::GetLastError()); } return hr; }
/*
* CreatePropertyPages - Create an instance of our property pages and attach them * to MMC's property sheet. * * History: a-jsari 9/17/97 Initial version */ STDMETHODIMP CSystemInfoScope::CreatePropertyPages(LPPROPERTYSHEETCALLBACK pProvider, LONG_PTR handle, LPDATAOBJECT pDataObject) { ASSERT(pProvider != NULL); ASSERT(pDataObject != NULL);
TRACE(_T("CSystemInfoScope::CreatePropertyPages\n")); if (pProvider == NULL || pDataObject == NULL) return E_INVALIDARG;
// Special code goes here if we're used as an extension.
HRESULT hResult;
do { CChooseMachinePropPage *pPropChoose; HPROPSHEETPAGE hGeneralPage; BOOL fOverride;
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
// Deleted automatically.
pPropChoose = new CChooseMachinePropPage(IDD_CHOOSER_CHOOSE_MACHINE);
if (pPropChoose == NULL) { ::MMCFreeNotifyHandle(handle); ::AfxThrowMemoryException(); }
// Save the current machine name, in case the one selected in the property
// page is not any good.
m_strLastMachineName = *m_pstrMachineName;
pPropChoose->SetHandle(handle); pPropChoose->SetOutputBuffers(m_pstrMachineName, &fOverride, m_pstrOverrideName);
hGeneralPage = ::CreatePropertySheetPage(&pPropChoose->m_psp); if (!hGeneralPage) { hResult = E_FAIL; break; }
hResult = pProvider->AddPage(hGeneralPage); ASSERT(SUCCEEDED(hResult));
} while (FALSE);
if (FAILED(hResult)) return hResult; return S_OK; }
/*
* QueryPagesFor - Return S_OK, informing MMC that we have property sheets available. * * History: a-jsari 9/17/97 Initial version */ STDMETHODIMP CSystemInfoScope::QueryPagesFor(LPDATAOBJECT pDataObject) { TRACE(_T("CSystemInfoScope::QueryPagesFor\n")); ASSERT(pDataObject != NULL);
if (pDataObject == NULL) return E_POINTER;
// If we are being loaded as an extension, don't display property pages.
// We do this because the base snap-in is responsible for the connected
// machine, not us.
if (!IsPrimaryImpl()) return S_FALSE;
#if 0
// Not sure why I did this.
// If the machine name is already set, don't display the property page.
if (m_pstrMachineName && m_pstrMachineName->GetLength() > 0) return S_FALSE; #endif
return S_OK; }
/*
* Load - Load our state from the stream provided. * * History: a-jsari 11/5/97 Initial version */ STDMETHODIMP CSystemInfoScope::Load(IStream *pStm) { CDataSource *pSource;
AFX_MANAGE_STATE(AfxGetStaticModuleState());
TRACE(_T("CSystemInfoScope::Load\n")); ASSERT(pStm != NULL); if (pStm == NULL) return E_POINTER; ClearDirty(); // If our command-line parameters have specified a source, don't replace it.
if (!m_fViewUninitialized) { if (m_strDeferredLoad.IsEmpty()) pSource = CDataSource::CreateFromIStream(pStm); else { pSource = CBufferDataSource::CreateDataSourceFromFile(m_strDeferredLoad); if (pSource) { const long DONT_USE_LAST_FOLDER = 1; SetSource(pSource, TRUE); pConsole()->UpdateAllViews(0, DONT_USE_LAST_FOLDER, 0L); SetSelectedFolder(NULL); return S_OK; } else m_strDeferredLoad.Empty(); }
if (pSource == NULL) InitializeSource(); else { if (!m_strDeferredCategories.IsEmpty()) pSource->SetCategories(m_strDeferredCategories);
SetSource(pSource, TRUE);
if (!m_strDeferredMachine.IsEmpty()) SetMachine(m_strDeferredMachine); } } return S_OK; }
/*
* Save - Save our state to the stream provided. * * History: a-jsari 11/5/97 Initial version */ STDMETHODIMP CSystemInfoScope::Save(IStream *pStm, BOOL fClearDirty) { TRACE(_T("CSystemInfoScope::Save\n")); ASSERT(pStm != NULL); if (pStm == NULL) return E_POINTER;
if (fClearDirty) ClearDirty();
HRESULT hResult = S_OK;
// If there is a source, let it save its state to the stream. Otherwise,
// save the state for the default source (GATHERER with no machine name).
if (m_pSource) hResult = m_pSource->Save(pStm); else { unsigned wValue; ULONG cWrite;
wValue = CDataSource::GATHERER; hResult = pStm->Write(&wValue, sizeof(wValue), &cWrite); if (SUCCEEDED(hResult)) { wValue = 0; hResult = pStm->Write(&wValue, sizeof(wValue), &cWrite); } }
return hResult; }
/*
* IsDirty - Return our Dirty status, to see if a save would be beneficial. * * History: a-jsari 11/5/97 Initial version */ STDMETHODIMP CSystemInfoScope::IsDirty() { TRACE(_T("CSystemInfoScope::IsDirty\n")); return ObjectIsDirty() ? S_OK : S_FALSE; }
/*
* GetClassID - Return our Component Object Class ID. * * History: a-jsari 11/5/97 Initial version */ STDMETHODIMP CSystemInfoScope::GetClassID(CLSID *pClassID) { TRACE(_T("CSystemInfoScope::GetClassID\n")); ASSERT(pClassID != NULL); if (pClassID == NULL) return E_POINTER; *pClassID = GetCoClassID(); return S_OK; }
/*
* GetSizeMax - Return the maximum size consumed in a stream by our * persistance. * * History: a-jsari 11/5/97 Initial version */ STDMETHODIMP CSystemInfoScope::GetSizeMax(ULARGE_INTEGER *pcbSize) { TRACE(_T("CSystemInfoScope::GetSizeMax\n")); ASSERT(pcbSize != NULL); if (pcbSize == NULL) return E_POINTER; pcbSize->LowPart = 2 * sizeof(unsigned) + MAX_PATH; pcbSize->HighPart = 0; return E_NOTIMPL; }
//-----------------------------------------------------------------------------
// Implementation of GetHelpTopic, which supplies the location of our help
// file to MMC for merging into the combined help. Adapted from example in
// the MMC help file.
//-----------------------------------------------------------------------------
STDMETHODIMP CSystemInfoScope::GetHelpTopic(LPOLESTR* lpCompiledHelpFile) { if (lpCompiledHelpFile == NULL) return E_POINTER;
// Get the name of our help file, and prepend the help directory.
// Actually, although the MMC documentation said that a full path is
// required, we can just put the file name, since it is being stored in
// the system help directory (HTMLHelp will find it there).
AFX_MANAGE_STATE(AfxGetStaticModuleState()); CString strHelp; strHelp.LoadString(IDS_MSINFO_HELP_FILE);
// NOTE: It looks like HTMLHelp has been changed, and will not locate
// the help file in the standard help directory. So we'll need to get
// the full path to the help file. (JCM, 7/1/98)
TCHAR szFilePath[MAX_PATH]; DWORD dwCnt = ExpandEnvironmentStrings(CString(_T("%WINDIR%\\help\\")) + strHelp, szFilePath, MAX_PATH); ASSERT(dwCnt != 0); if (dwCnt != 0) strHelp = szFilePath; // Allocate the string to hold the help file path. MMC will be responsible
// for deallocating this buffer later.
*lpCompiledHelpFile = reinterpret_cast<LPOLESTR>(CoTaskMemAlloc((strHelp.GetLength() + 1)* sizeof(wchar_t))); if (*lpCompiledHelpFile == NULL) return E_OUTOFMEMORY;
// Copy from the path string to the buffer and return success.
USES_CONVERSION; wcscpy(*lpCompiledHelpFile, T2OLE((LPTSTR)(LPCTSTR)strHelp)); return S_OK; }
/*
* SetMachine - Set our internal machine name. * * History: a-jsari 1/16/98 Initial version. */ BOOL CSystemInfoScope::SetMachine(const CString &strMachine) { BOOL fReturn = FALSE;
*m_pstrMachineName = strMachine; ASSERT(pSource() != NULL); if (pSource() && pSource()->GetType() == CDataSource::GATHERER) { // Changing the machine name is only meaningful if we are connected to a WBEM
// data source.
CWBEMDataSource * pWBEMSource = reinterpret_cast<CWBEMDataSource *>(pSource());
fReturn = pWBEMSource->SetMachineName(*m_pstrMachineName); if (fReturn) { // If we succeeded, reset the root node text. Also, there's a hack in place
// to keep SetSource from running twice during initialization. Which requires
// another hack here to make it run - change the flag it uses to keep track
// of the last call so that this call is different. I hate this.
m_fSetSourcePreLaunch = TRUE; SetSource(pSource(), FALSE); } else { } } return fReturn; }
/*
* SetView - Set the view on the data. * * History: a-jsari 12/3/97 Initial version. */ void CSystemInfoScope::SetView(enum DataComplexity Complexity, BOOL fViewInitialized) { CDataSource *pDataSource = pSource(); switch (Complexity) { case BASIC: m_BasicFlags = MF_CHECKED; m_AdvancedFlags = 0L; break; case ADVANCED: m_BasicFlags = 0L; m_AdvancedFlags = MF_CHECKED; break; } if (pDataSource != NULL) VERIFY(pDataSource->SetDataComplexity(Complexity)); if (fViewInitialized) { CRegKey crkView; long lResult;
pConsole()->UpdateAllViews(NULL, 0, 0); lResult = crkView.Create(HKEY_CURRENT_USER, cszViewKey); if (lResult != ERROR_SUCCESS) return; switch (Complexity) { case ADVANCED: lResult = crkView.SetValue(cszAdvancedValue, cszViewValue); break; case BASIC: lResult = crkView.SetValue(cszBasicValue, cszViewValue); break; } } }
/*
* SetSource - Remove the old data source, and replace it with a new one. * * History: a-jsari 9/25/97 Initial version. */
void CSystemInfoScope::SetSource(CDataSource *pNewSource, BOOL fPreLaunch) { HSCOPEITEM hsiRoot; HRESULT hr; BOOL fUIOK = FALSE;
// We have some variables in this class to make sure that SetSource
// isn't called twice during initialization with the same parameters.
if (m_pSetSourceSource == pNewSource && m_fSetSourcePreLaunch == fPreLaunch) return; m_pSetSourceSource = pNewSource; m_fSetSourcePreLaunch = fPreLaunch;
// If fPreLaunch is TRUE, we have not yet created our UI items.
if (fPreLaunch == FALSE) { if (m_pmapCategories == NULL) m_pmapCategories = new CScopeItemMap;
// Select the root node so we can remove all its children.
if (m_pmapCategories && !m_pmapCategories->ScopeFromView(NULL, hsiRoot)) return; hr = pConsole()->SelectScopeItem(hsiRoot); ASSERT(SUCCEEDED(hr)); if (FAILED(hr)) return;
// Before we delete the item, we want to make sure that it's actually
// been added. Try a call to GetItem to make sure it's there.
SCOPEDATAITEM item; item.mask = SDI_CHILDREN; item.ID = hsiRoot; fUIOK = SUCCEEDED(pScope()->GetItem(&item));
if (fUIOK) { m_fInternalDelete = TRUE; hr = pScope()->DeleteItem(hsiRoot, FALSE); m_fInternalDelete = FALSE;
if (pSource() && pSource()->GetType() == CDataSource::GATHERER) ((CWBEMDataSource *) pSource())->ResetCategoryRefresh();
ASSERT(SUCCEEDED(hr)); if (FAILED(hr)) return;
if (m_pSaveUnknown) { m_pstrMachineName = new CString; m_pstrOverrideName = new CString; Initialize(m_pSaveUnknown); m_pSaveUnknown = NULL; } }
// Remove our memory of data items.
m_pmapCategories->Clear(); } // Don't delete our pointer if we are resetting the same pointer.
if (m_pSource != pNewSource) { if (!m_pSource) m_pSource = pNewSource; else { DataComplexity Complexity; Complexity = m_pSource->m_Complexity;
delete m_pSource; m_pSource = pNewSource; m_pSource->SetDataComplexity(Complexity); } } if (fPreLaunch == FALSE) { CFolder *pFolder; SCOPEDATAITEM sdiRoot; CString strNodeName;
USES_CONVERSION; ::memset(&sdiRoot, 0, sizeof(sdiRoot)); // Identify the node.
sdiRoot.ID = hsiRoot; sdiRoot.mask = SDI_STR; m_pSource->GetNodeName(strNodeName); sdiRoot.displayname = T2OLE(const_cast<LPTSTR>((LPCTSTR)strNodeName)); hr = pScope()->SetItem(&sdiRoot); ASSERT(SUCCEEDED(hr)); hr = AddRoot(hsiRoot, &pFolder); ASSERT(SUCCEEDED(hr)); if (FAILED(hr)) return;
if (fUIOK) { hr = ScopeEnumerate(hsiRoot, pFolder); ASSERT(SUCCEEDED(hr)); if (FAILED(hr)) return; } } }
/*
* AddRoot - Insert a CCategoryObject of the root folder into our Category map. * * History: a-jsari 11/20/97 Initial version */ HRESULT CSystemInfoScope::AddRoot(HSCOPEITEM hsiRoot, CFolder **ppFolder) { ASSERT(ppFolder != NULL); (*ppFolder) = pRootCategory(); ASSERT(*ppFolder != NULL); if (*ppFolder == NULL) return E_FAIL; // This object gets deleted in the mapCategories destructor
CViewObject *pvoData = new CCategoryObject(*ppFolder); if (pvoData == NULL) ::AfxThrowMemoryException(); m_pmapCategories->InsertRoot(pvoData, hsiRoot); return S_OK; }
/*
* GetNamedChildFolder - Update strCategory to add the next backslash- * delimited path element from strPath. * * History: a-jsari 12/17/97 Initial version */ static inline void GetNamedChildFolder( CString &strCategory, const CString &strPath) { int iString; CString strSubCategory; CString strName;
// Remove the Category prefix from the path
iString = strPath.Find(strCategory); ASSERT(iString == 0); strSubCategory = strPath.Mid(iString + strCategory.GetLength() + 1);
// Remove the trailing categories
// (We'll deal with your rebel friends soon enough).
iString = strSubCategory.Find((TCHAR) '\\'); if (iString != -1) strSubCategory = strSubCategory.Left(iString);
// Update the category to add the current category
strCategory += _T("\\"); strCategory += strSubCategory;
#if 0
// Turned out not to need this code.
// Find the Sub-folder with the name of the Sub-category.
pfNext = pfNext->GetChildNode(); do { pfNext->GetName(szName); if (szName == szSubCategory) break; pfNext = pfNext->GetNextNode(); } while (pfNext != NULL); ASSERT(pfNext != NULL); #endif
}
//-----------------------------------------------------------------------------
// If were are currently refreshing, hang here until it's done.
//-----------------------------------------------------------------------------
void CSystemInfoScope::WaitForRefresh() { if (pSource() && pSource()->GetType() == CDataSource::GATHERER) { CWBEMDataSource * pWBEMSource = reinterpret_cast<CWBEMDataSource *>(pSource()); if (pWBEMSource && pWBEMSource->m_pThreadRefresh) pWBEMSource->m_pThreadRefresh->WaitForRefresh(); } }
//-----------------------------------------------------------------------------
// Is an asynchronous refresh currently in progress?
//-----------------------------------------------------------------------------
BOOL CSystemInfoScope::InRefresh() { if (pSource() && pSource()->GetType() == CDataSource::GATHERER) { CWBEMDataSource * pWBEMSource = reinterpret_cast<CWBEMDataSource *>(pSource()); if (pWBEMSource && pWBEMSource->m_pThreadRefresh) return pWBEMSource->m_pThreadRefresh->IsRefreshing(); }
return FALSE; }
/*
* SelectItem - Select the item pointed to by szPath * * History: a-jsari 12/11/97 Initial version */ BOOL CSystemInfoScope::SelectItem(const CString &strPath, int iLine) { HSCOPEITEM hsiNode; HRESULT hr;
// Get the named node from our internal list.
if (m_pmapCategories->ScopeFromName(strPath, hsiNode)) { CFolder *pFolder = m_pmapCategories->CategoryFromScope(hsiNode); pFolder->SetSelectedItem(iLine); hr = pConsole()->SelectScopeItem(hsiNode); ASSERT(hr == S_OK);
if (m_pLastSystemInfo) m_pLastSystemInfo->SelectLine(iLine);
if (FAILED(hr)) return FALSE; } else {
CString strCategory = strPath; int iEnumerations = 0; int iString;
// If the category isn't in our list, we need to enumerate all nodes
// leading up to it.
while (!m_pmapCategories->ScopeFromName(strCategory, hsiNode)) { ++iEnumerations; // Strip the last Category off the Path.
iString = strCategory.ReverseFind((TCHAR) '\\'); if (iString == -1) { // If this fails, no nodes have been yet enumerated.
if (!m_pmapCategories->ScopeFromName(_T(""), hsiNode)) { // --iEnumerations;
break; } } else { strCategory = strCategory.Left(iString); } }
HRESULT hr; // Enumerate all unenumerated nodes.
#if 0
// Commented out because InsertItem in ScopeEnumerate fails inexplicably.
CFolder *pfCurrent = pmapCategories->CategoryFromScope(hsiNode); #endif
while (iEnumerations--) { #if 0
hr = ScopeEnumerate(hsiNode, pfCurrent); #else
hr = pConsole()->SelectScopeItem(hsiNode); #endif
ASSERT(hr == S_OK); if (FAILED(hr)) return FALSE; GetNamedChildFolder(strCategory, strPath); if (!m_pmapCategories->ScopeFromName(strCategory, hsiNode)) // The scope item we are searching for cannot be enumerated (The
// attempt to do so in SelectScopeItem has failed.) This can happen
// when we are connected to a remote computer which can't be accessed.
return FALSE; } CFolder *pFolder = m_pmapCategories->CategoryFromScope(hsiNode); // Using this method of selecting a line because MMC won't
// just allow me to call GetItem.
pFolder->SetSelectedItem(iLine); hr = pConsole()->SelectScopeItem(hsiNode);
if (m_pLastSystemInfo) m_pLastSystemInfo->SelectLine(iLine);
ASSERT(hr == S_OK); if (FAILED(hr)) return FALSE; } return TRUE; }
/*
* ScopeEnumerate - Insert all categories of the given pFolder as namespace children * of hsiNode. * * History: a-jsari 11/20/97 Initial version */
HRESULT CSystemInfoScope::ScopeEnumerate(HSCOPEITEM hsiNode, CFolder *pFolder) { HRESULT hr = S_OK;
ASSERT(pFolder); if (pFolder == NULL) return hr;
SCOPEDATAITEM sdiNode; sdiNode.mask = SDI_STR | SDI_PARAM | SDI_PARENT; sdiNode.displayname = MMC_CALLBACK; sdiNode.relativeID = hsiNode;
// If GetChildNode returned a NULL pointer, and this is the root node,
// then some sort of error must have occurred.
CFolder * pfolIterator = pFolder->GetChildNode(); if (pfolIterator == NULL && pFolder->GetParentNode() == NULL) { AFX_MANAGE_STATE(::AfxGetStaticModuleState());
if (m_pSource && m_pSource->GetType() == CDataSource::GATHERER) if (((CWBEMDataSource *)m_pSource)->m_pGatherer) { DWORD dwError = ((CWBEMDataSource *)m_pSource)->m_pGatherer->GetLastError(); if (dwError) DisplayGatherError(dwError, (LPCTSTR)((CWBEMDataSource *)m_pSource)->m_strMachineName); } }
while (pfolIterator) { // This object gets deleted inthe mapCategories destructor.
CViewObject * pCategory = new CCategoryObject(pfolIterator); ASSERT(pCategory != NULL); if (pCategory == NULL) return E_OUTOFMEMORY;
// If there are no children, modify the node we're inserting so
// we don't get a '+' sign next to the folder.
if (pfolIterator->GetChildNode() == NULL) { sdiNode.cChildren = 0; sdiNode.mask |= SDI_CHILDREN; } else { sdiNode.cChildren = 1; sdiNode.mask &= ~SDI_CHILDREN; }
sdiNode.lParam = reinterpret_cast<LPARAM>(pCategory); hr = pScope()->InsertItem(&sdiNode); ASSERT(hr == S_OK); if (FAILED(hr)) { delete pCategory; break; }
pfolIterator->m_hsi = sdiNode.ID; m_pmapCategories->Insert(pCategory, sdiNode.ID); pfolIterator = pfolIterator->GetNextNode(); }
return hr; }
/*
* AddExtensionRoot - If the snapin is loaded as an extension, create the root node. * * History: a-jsari 1/6/97 Initial version */ HRESULT CSystemInfoScope::AddExtensionRoot(HSCOPEITEM &hsiNode, CFolder **pFolder) { SCOPEDATAITEM sdiNode; HRESULT hrReturn; CViewObject *pView;
::memset(&sdiNode, 0, sizeof(sdiNode)); sdiNode.mask = SDI_STR | SDI_PARAM | SDI_PARENT | SDI_IMAGE | SDI_OPENIMAGE; sdiNode.nImage = 0; sdiNode.nOpenImage = 0; sdiNode.displayname = MMC_CALLBACK; sdiNode.relativeID = hsiNode;
pView = new CExtensionRootObject(pRootCategory()); ASSERT(pView != NULL); if (pView == NULL) ::AfxThrowMemoryException(); m_RootCookie = sdiNode.lParam = reinterpret_cast<LPARAM>(pView); hrReturn = pScope()->InsertItem(&sdiNode); hsiNode = sdiNode.ID; m_pmapCategories->InsertRoot(pView, hsiNode); *pFolder = pRootCategory(); return hrReturn; }
/*
* OnExpand - If fExpand is TRUE, expand the item pointed to by pDataObject, * otherwise contract it. If expanding, enumerate children. * * History: a-jsari 9/25/97 Initial version */
HRESULT CSystemInfoScope::OnExpand(LPDATAOBJECT pDataObject, LPARAM fExpand, HSCOPEITEM hsiNode) { CFolder *pfolSelection; HRESULT hr;
// Log the expand event, so we know that the user clicked on a node.
if (msiLog.IsLogging(CMSInfoLog::CATEGORY)) { CFolder * pFolder = m_pmapCategories->CategoryFromScope(hsiNode); if (pFolder) { CString strName; if (pFolder->GetName(strName)) msiLog.WriteLog(CMSInfoLog::CATEGORY, _T("CATEGORY \"%s\"\r\n"), strName); } }
// We have nothing to do if we are contracting a node.
// This never happens.
if (fExpand == 0) return S_OK;
// If our initialization failed, exit.
if (!m_bInitializedCD) return S_OK; // Look up the CViewObject in our internal table based on our hsiNode value,
// and
// CHECK: Consider the memory leak potential in this map.
if ((pfolSelection = m_pmapCategories->CategoryFromScope(hsiNode)) == NULL) { // If the expanded node isn't in our internal hash table, we should
// be looking at the root node, so get it.
if (IsPrimaryImpl() == FALSE) { // If we are an extension . . .
FORMATETC fmtMachine = { (CLIPFORMAT) CDataObject::m_cfMachineName, NULL, DVASPECT_CONTENT, TYMED_HGLOBAL }; STGMEDIUM stgMachine;
stgMachine.tymed = TYMED_HGLOBAL; stgMachine.hGlobal = ::GlobalAlloc(GMEM_MOVEABLE, (MAX_PATH + 1)* sizeof(WCHAR)); stgMachine.pUnkForRelease = NULL;
// Only look externally for the machine when we are an extension.
hr = pDataObject->GetDataHere(&fmtMachine, &stgMachine); if (hr == S_OK) { USES_CONVERSION; CString strMachine = W2T((LPWSTR)::GlobalLock(stgMachine.hGlobal)); ::GlobalUnlock(stgMachine.hGlobal); HGLOBAL hGlobal = ::GlobalFree(stgMachine.hGlobal); ASSERT(hGlobal == NULL); SetMachine(strMachine); } else ASSERT(hr == DV_E_FORMATETC); hr = AddExtensionRoot(hsiNode, &pfolSelection); ASSERT(SUCCEEDED(hr)); return hr; } else { hr = AddRoot(hsiNode, &pfolSelection); ASSERT(SUCCEEDED(hr)); if (FAILED(hr)) return hr; } } return ScopeEnumerate(hsiNode, pfolSelection); }
/*
* OnProperties - Called when a property value changes. * * History: a-jsari 9/25/97 Initial version. */ HRESULT CSystemInfoScope::OnProperties(LPARAM) { DWORD dwError = 0;
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
if (m_pSource && m_pSource->GetType() == CDataSource::GATHERER) { CWBEMDataSource * pWBEMSource = reinterpret_cast<CWBEMDataSource *>(pSource()); if (pWBEMSource && pWBEMSource->m_pThreadRefresh) pWBEMSource->m_pThreadRefresh->CancelRefresh();
if (m_strLastMachineName.CompareNoCase((LPCTSTR) *m_pstrMachineName) != 0) { // Try to connect to the new machine. If the connection fails, display
// an appropriate error message and restore the machine name to the
// original string.
if (((CWBEMDataSource *)m_pSource)->m_pGatherer->SetConnect(*m_pstrMachineName)) { if (NULL == ((CWBEMDataSource *)m_pSource)->m_pGatherer->GetProvider()) dwError = ((CWBEMDataSource *)m_pSource)->m_pGatherer->GetLastError(); } else dwError = ((CWBEMDataSource *)m_pSource)->m_pGatherer->GetLastError();
if (dwError) { // Display the error, and reset the machine name and the data source
// to the previous known good name.
DisplayGatherError(dwError, (LPCTSTR) *m_pstrMachineName); *m_pstrMachineName = m_strLastMachineName; ((CWBEMDataSource *)m_pSource)->m_pGatherer->SetConnect(*m_pstrMachineName); ((CWBEMDataSource *)m_pSource)->m_pGatherer->GetProvider(); RefreshAsync(m_pfLast, m_pLastSystemInfo, FALSE); } else { if (pSource() != NULL) SetMachine(*m_pstrMachineName); } }
// This doesn't really seem necessary...
// if (m_pfLast && pConsole())
// pConsole()->SelectScopeItem(m_pfLast->m_hsi);
}
return S_OK; }
//-----------------------------------------------------------------------------
// DisplayGatherError
//
// There are multiple places we need to display a connection error to the user,
// so the functionality is gathered here.
//-----------------------------------------------------------------------------
void CSystemInfoScope::DisplayGatherError(DWORD dwError, LPCTSTR szMachineName) { CString strMachine, strErrorMessage;
if (!dwError) return;
if (szMachineName) strMachine = CString(szMachineName);
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
if (strMachine.IsEmpty()) strMachine.LoadString(IDS_LOCALCOMPLABEL);
switch (dwError) { case GATH_ERR_ALLOCATIONFAILED: case GATH_ERR_NOWBEMOUTOFMEM: strErrorMessage.LoadString(IDS_OUTOFMEMERROR); break; case GATH_ERR_NOWBEMLOCATOR: strErrorMessage.LoadString(IDS_NOLOCATOR); break; case GATH_ERR_NOWBEMCONNECT: strErrorMessage.Format(IDS_NOGATHERER, strMachine); break; case GATH_ERR_NOWBEMACCESSDENIED: strErrorMessage.Format(IDS_GATHERACCESS, strMachine); break; case GATH_ERR_NOWBEMBADSERVER: strErrorMessage.Format(IDS_BADSERVER, strMachine); break; case GATH_ERR_NOWBEMNETWORKFAILURE: strErrorMessage.Format(IDS_NETWORKERROR, strMachine); break; case GATH_ERR_BADCATEGORYID: strErrorMessage.LoadString(IDS_UNEXPECTED); break; default: ASSERT(FALSE); strErrorMessage.LoadString(IDS_UNEXPECTED); break; }
MessageBox(strErrorMessage); }
/*
* MachineName - Return the current connected machine as a LPCSTR. * * History: a-jsari 11/12/97 Initial version. */ LPCTSTR CSystemInfoScope::MachineName() const { if (m_pstrMachineName == NULL || m_pstrMachineName->GetLength() == 0) return NULL; return (LPCTSTR)(*m_pstrMachineName)+2; // +2 to skip over the initial "\\"
}
/*
* SetSelectedFolder - Remember the last selected folder for context- * sensitive operations (i.e. Print, Report, Find) * * History: a-jsari 2/12/98 Initial version */ void CSystemInfoScope::SetSelectedFolder(CFolder *pFolder) { m_pfLast = pFolder; if (pSource() != NULL) pSource()->SetLastFolder(pFolder); }
//-----------------------------------------------------------------------------
// Start an async refresh of the specified folder.
//-----------------------------------------------------------------------------
void CSystemInfoScope::RefreshAsync(CFolder * pFolder, CSystemInfo * pSystemInfo, BOOL fSoftRefresh) { if (pSource() && pSource()->GetType() == CDataSource::GATHERER) { CWBEMDataSource * pWBEMSource = reinterpret_cast<CWBEMDataSource *>(pSource()); if (pWBEMSource && pWBEMSource->m_pThreadRefresh) pWBEMSource->m_pThreadRefresh->RefreshFolderAsync(pFolder, pSystemInfo, FALSE, fSoftRefresh); } }
|