|
|
/*++
Copyright (C) Microsoft Corporation
Module Name:
compdata.cpp
Abstract:
This module implemets CComponentData class
Author:
William Hsieh (williamh) created
Revision History:
--*/
#include "devmgr.h"
#include "factory.h"
#include "genpage.h"
const WCHAR* const DM_COMPDATA_SIGNATURE = L"Device Manager";
CComponentData::CComponentData() { m_pScope = NULL; m_pConsole = NULL; m_pCookieRoot = NULL; m_pScopeItemRoot = NULL; //
// Static scope item default to device manager
//
m_ctRoot = COOKIE_TYPE_SCOPEITEM_DEVMGR; m_hwndMain = NULL; m_pMachine = NULL; m_IsDirty = FALSE; //
// Increment object count (used by CanUnloadNow)
//
::InterlockedIncrement(&CClassFactory::s_Objects); m_Ref = 1; }
CComponentData::~CComponentData() { //
// All QIed interfaces should be released during
// Destroy method
//
ASSERT(NULL == m_pScope); ASSERT(NULL == m_pConsole); ASSERT(NULL == m_pCookieRoot); //
// decrement object count(used by CanUnloadNow)
//
ASSERT( 0 != CClassFactory::s_Objects ); ::InterlockedDecrement(&CClassFactory::s_Objects); }
//
// IUnknown interface
//
ULONG CComponentData::AddRef() { return ::InterlockedIncrement(&m_Ref); }
ULONG CComponentData::Release() { ASSERT( 0 != m_Ref ); ULONG cRef = ::InterlockedDecrement(&m_Ref); if ( 0 == cRef ) { delete this; } return cRef; }
STDMETHODIMP CComponentData::QueryInterface( REFIID riid, void** ppv ) { if (!ppv) { return E_INVALIDARG; }
HRESULT hr = S_OK;
if (IsEqualIID(riid, IID_IUnknown)) { *ppv = (IUnknown*)(IComponentData*)this; } else if (IsEqualIID(riid, IID_IComponentData)) { *ppv = (IComponentData*)this; } else if (IsEqualIID(riid, IID_IExtendContextMenu)) { *ppv = (IExtendContextMenu*)this; } else if (IsEqualIID(riid, IID_IExtendPropertySheet)) { *ppv = (IExtendPropertySheet*)this; } else if (IsEqualIID(riid, IID_IPersistStream)) { *ppv = (IPersistStream*)this; } else if (IsEqualIID(riid, IID_ISnapinHelp)) { *ppv = (ISnapinHelp*)this; } else { *ppv = NULL; hr = E_NOINTERFACE; } if (SUCCEEDED(hr)) { AddRef(); }
return hr; }
/////////////////////////////////////////////////////////////////////////////
// IComponentData implementation
///
STDMETHODIMP CComponentData::Initialize( LPUNKNOWN pUnknown ) { if (!pUnknown) { return E_INVALIDARG; }
HRESULT hr; try { //
// This function should be called only once.
//
ASSERT(NULL == m_pScope); //
// Get the IConsoleNameSpace interface
//
hr = pUnknown->QueryInterface(IID_IConsoleNameSpace, (void**)&m_pScope); if (SUCCEEDED(hr)) { hr = pUnknown->QueryInterface(IID_IConsole, (void**)&m_pConsole); if (SUCCEEDED(hr)) { //
// Retreive the console main window. It will be used
// as the parent window of property sheets and
// parent handle for setupapi calls
//
m_pConsole->GetMainWindow(&m_hwndMain); LoadScopeIconsForScopePane(); } else { //
// Unable to get the IConsole Interface
//
m_pScope->Release(); } } } catch (CMemoryException* e) { e->Delete(); MsgBoxParam(m_hwndMain, 0, 0, 0); hr = E_OUTOFMEMORY; } return hr; }
// This function creates a new CComponent
// A Component will be created when a new "window" is being created.
//
STDMETHODIMP CComponentData::CreateComponent( LPCOMPONENT* ppComponent ) { HRESULT hr;
if (!ppComponent) { return E_INVALIDARG; }
try { CComponent* pComponent = new CComponent(this); //
// Return the IComponent interface
//
hr = pComponent->QueryInterface(IID_IComponent, (void**)ppComponent); pComponent->Release(); if (SUCCEEDED(hr)) { hr = CreateScopeItems(); if (SUCCEEDED(hr)) { hr = pComponent->CreateFolderList(m_pCookieRoot); } else { pComponent->Release(); *ppComponent = NULL; } } } catch (CMemoryException* e) { e->Delete(); MsgBoxParam(m_hwndMain, 0, 0, 0); hr = E_OUTOFMEMORY; } return hr; }
STDMETHODIMP CComponentData::Notify( LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param ) { HRESULT hr;
try { //
// On MMCN_PROPERTY_CHANGE event, lpDataObject is invalid
// Donot touch it.
//
if (MMCN_PROPERTY_CHANGE == event) { PPROPERTY_CHANGE_INFO pPCI = (PPROPERTY_CHANGE_INFO) param; if (pPCI && PCT_STARTUP_INFODATA == pPCI->Type) { PSTARTUP_INFODATA pSI = (PSTARTUP_INFODATA)&pPCI->InfoData; ASSERT(pSI->Size == sizeof(STARTUP_INFODATA)); if (pSI->MachineName[0] != _T('\0')) { m_strMachineName = pSI->MachineName; } m_ctRoot = pSI->ct; SetDirty(); }
return S_OK; }
else if (MMCN_EXPAND == event) { return OnExpand(lpDataObject, arg, param); } else if (MMCN_REMOVE_CHILDREN == event) { //
// This is basically a hack!!!!
// When the target computer is switched in Computer Management
// snapin (we are an extention to it), we basically get
// a MMCN_REMOVE_CHILDREN followed by MMCN_EXPAND.
// The right thing for MMC to do is to create a new IComponent
// for each new machine so that each IComponent can maintain
// its own states (thus, its own folders).
// Well, it is not a perfect world and we are forced to use
// the old IComponent. So here we notify each scope node
// which in turns will notify all the CFolders.
//
// After reset, each folder does not attach to any CMachine object
// (thus, its m_pMachine will be NULL). Each folder will attach
// to the new machine object when its OnShow method is called
// the very "first" time.
//
if (!IsPrimarySnapin() && m_pScopeItemRoot) { m_pMachine->DestroyNotifyWindow(); ResetScopeItem(m_pScopeItemRoot); }
return S_OK; } ASSERT(m_pScope); INTERNAL_DATA tID; hr = ExtractData(lpDataObject, CDataObject::m_cfSnapinInternal, (PBYTE)&tID, sizeof(tID)); if (SUCCEEDED(hr)) { switch (event) { case MMCN_DELETE: hr = OnDelete(tID.cookie, arg, param); break; case MMCN_RENAME: hr = OnRename(tID.cookie, arg, param); break; case MMCN_CONTEXTMENU: hr = OnContextMenu(tID.cookie, arg, param); break; case MMCN_BTN_CLICK: hr = OnBtnClick(tID.cookie, arg, param); break; default: hr = S_OK; break; } } } catch(CMemoryException* e) { e->Delete(); hr = E_OUTOFMEMORY; }
return hr; }
STDMETHODIMP CComponentData::GetDisplayInfo( SCOPEDATAITEM* pScopeDataItem ) { if (!pScopeDataItem) { return E_INVALIDARG; }
try { //
// IComponentData::GetDisplayInfo only deals with scope pane items.
// Snapin's IComponent::GetDisplayInfo will deal with result pane items
//
CCookie* pCookie = (CCookie*) pScopeDataItem->lParam; ASSERT(pCookie); return pCookie->GetScopeItem()->GetDisplayInfo(pScopeDataItem); } catch (CMemoryException* e) { e->Delete(); MsgBoxParam(m_hwndMain, 0, 0, 0); return E_OUTOFMEMORY; } }
STDMETHODIMP CComponentData::Destroy() { if (m_pCookieRoot) { delete m_pCookieRoot; m_pCookieRoot = NULL; }
if (m_pScopeItemRoot) { delete m_pScopeItemRoot; }
if (m_pScope) { m_pScope->Release(); m_pScope = NULL; } if (m_pConsole) { m_pConsole->Release(); m_pConsole = NULL; }
return S_OK; }
STDMETHODIMP CComponentData::QueryDataObject( MMC_COOKIE cookie, DATA_OBJECT_TYPES type, LPDATAOBJECT* ppDataObject ) { CDataObject* pDataObject; COOKIE_TYPE ct; CCookie* pCookie;
try { pCookie = GetActiveCookie(cookie); if (NULL == pCookie) { ct = m_ctRoot; } else { ct = pCookie->GetType(); } pDataObject = new CDataObject; pDataObject->Initialize(type, ct, pCookie, m_strMachineName); pDataObject->AddRef(); *ppDataObject = pDataObject; } catch (CMemoryException* e) { e->Delete(); MsgBoxParam(m_hwndMain, 0, 0, 0); return E_OUTOFMEMORY; } return S_OK; }
STDMETHODIMP CComponentData::CompareObjects( LPDATAOBJECT lpDataObjectA, LPDATAOBJECT lpDataObjectB ) { HRESULT hr; try { INTERNAL_DATA tID_A, tID_B; hr = ExtractData(lpDataObjectA, CDataObject::m_cfSnapinInternal, (PBYTE)&tID_A, sizeof(tID_A)); if (SUCCEEDED(hr)) { hr = ExtractData(lpDataObjectB, CDataObject::m_cfSnapinInternal, (PBYTE)&tID_B, sizeof(tID_B)); if (SUCCEEDED(hr)) { hr = (tID_A.ct == tID_B.ct && tID_A.cookie == tID_B.cookie && tID_A.dot == tID_B.dot) ? S_OK : S_FALSE; } } } catch(CMemoryException* e) { e->Delete(); MsgBoxParam(m_hwndMain, 0, 0, 0); hr = E_OUTOFMEMORY; } return hr; }
///////////////////////////////////////////////////////////////////
//// IExtendPropertySheet implementation
////
STDMETHODIMP CComponentData::QueryPagesFor( LPDATAOBJECT lpDataObject ) { HRESULT hr;
if (!lpDataObject) { return E_INVALIDARG; }
try { INTERNAL_DATA tID; hr = ExtractData(lpDataObject, CDataObject::m_cfSnapinInternal, (PBYTE)&tID, sizeof(tID)); if (SUCCEEDED(hr)) { CScopeItem* pScopeItem; pScopeItem = FindScopeItem(tID.cookie); if (CCT_SNAPIN_MANAGER == tID.dot && COOKIE_TYPE_SCOPEITEM_DEVMGR == tID.ct) { hr = S_OK; }
else if (pScopeItem) { hr = pScopeItem->QueryPagesFor(); } else { hr = S_FALSE; } } }
catch (CMemoryException* e) { e->Delete(); MsgBoxParam(m_hwndMain, 0, 0, 0); hr = E_OUTOFMEMORY; } return hr; }
STDMETHODIMP CComponentData::CreatePropertyPages( LPPROPERTYSHEETCALLBACK lpProvider, LONG_PTR handle, LPDATAOBJECT lpDataObject ) { if (!lpProvider || !lpDataObject) { return E_INVALIDARG; }
HRESULT hr;
try { INTERNAL_DATA tID; hr = ExtractData(lpDataObject, CDataObject::m_cfSnapinInternal, reinterpret_cast<BYTE*>(&tID), sizeof(tID) ); if (SUCCEEDED(hr)) { CScopeItem* pScopeItem = FindScopeItem(tID.cookie); if (CCT_SNAPIN_MANAGER == tID.dot && COOKIE_TYPE_SCOPEITEM_DEVMGR == tID.ct) { hr = DoStartupProperties(lpProvider, handle, lpDataObject); } else if (pScopeItem) { hr = pScopeItem->CreatePropertyPages(lpProvider, handle); }
else { hr = S_OK; } } } catch(CMemoryException* e) { e->Delete(); MsgBoxParam(m_hwndMain, 0, 0, 0); hr = E_OUTOFMEMORY; } return hr; }
////////////////////////////////////////////////////////////
//// IExtendContextMenu implemantation
////
STDMETHODIMP CComponentData::AddMenuItems( LPDATAOBJECT lpDataObject, LPCONTEXTMENUCALLBACK pCallbackUnknown, long *pInsertionAllowed ) { if (!lpDataObject || !pCallbackUnknown || !pInsertionAllowed) { return E_INVALIDARG; }
return S_OK; }
STDMETHODIMP CComponentData::Command( long nCommandID, LPDATAOBJECT lpDataObject ) { UNREFERENCED_PARAMETER(nCommandID);
if (!lpDataObject) { return E_INVALIDARG; }
return S_OK; }
HRESULT CComponentData::CreateCookieSubtree( CScopeItem* pScopeItem, CCookie* pCookieParent ) { ASSERT(pScopeItem);
CScopeItem* pChild; CCookie* pCookieSibling; pCookieSibling = NULL; int Index = 0;
while (pScopeItem->EnumerateChildren(Index, &pChild)) { CCookie* pCookie; pCookie = new CCookie(pChild->GetType()); if (pCookie) { pCookie->SetScopeItem(pChild); if (!pCookieSibling) { pCookieParent->SetChild(pCookie); } else { pCookieSibling->SetSibling(pCookie); } pCookie->SetParent(pCookieParent); if (pChild->GetChildCount()) { CreateCookieSubtree(pChild, pCookie); } pCookieSibling = pCookie; }
Index++; }
return S_OK; } ////////////////////////////////////////////////////////////
/// IPersistStream implementation
///
STDMETHODIMP CComponentData::GetClassID( CLSID* pClassID ) { if(!pClassID) { return E_INVALIDARG; }
*pClassID = GetCoClassID(); return S_OK; }
STDMETHODIMP CComponentData::IsDirty() { return m_IsDirty ? S_OK : S_FALSE; }
STDMETHODIMP CComponentData::Load( IStream* pStm ) { HRESULT hr; SafeInterfacePtr<IStream> StmPtr(pStm);
//
// Fix up the MachineName that we got from the command line if there was one.
// We need to prepend "\\" to the MachineName if it does not start with two
// backslashes, and then we will verify the machine name by calling CM_Connect_Machine
// to verify that this user has access to that machine. If they do not then we
// will set the MachineName to NULL.
//
if (!g_strStartupMachineName.IsEmpty()) { if (_T('\\') != g_strStartupMachineName[0]) { g_strStartupMachineName = TEXT("\\\\") + g_strStartupMachineName; } }
COMPDATA_PERSISTINFO Info; ULONG BytesRead;
ASSERT(pStm); //
// Read the persist data and verify that we have the right data
//
hr = pStm->Read(&Info, sizeof(Info), &BytesRead);
if (SUCCEEDED(hr) && (BytesRead >= sizeof(Info)) && (Info.Size >= sizeof(Info)) && (!wcscmp(Info.Signature, DM_COMPDATA_SIGNATURE))) { try { m_ctRoot = Info.RootCookie; m_strMachineName.Empty();
if (UNICODE_NULL != Info.ComputerFullName[0]) { m_strMachineName = Info.ComputerFullName; } if (COOKIE_TYPE_SCOPEITEM_DEVMGR == m_ctRoot) { //
// Parameters from command line has the priority
//
if (!g_strStartupMachineName.IsEmpty()) { m_strMachineName = g_strStartupMachineName; } m_strStartupDeviceId = g_strStartupDeviceId; m_strStartupCommand = g_strStartupCommand; } hr = CreateScopeItems(); if (SUCCEEDED(hr)) { if (!m_pMachine) { if (!g_MachineList.CreateMachine(m_strMachineName, &m_pMachine)) { hr = HRESULT_FROM_WIN32(GetLastError()); } } } }
catch(CMemoryException* e) { e->Delete(); MsgBoxParam(m_hwndMain, 0, 0, 0); hr = E_OUTOFMEMORY; } } else { //
// No persistant data, so use the command line parameters.
//
m_strMachineName = g_strStartupMachineName; m_strStartupDeviceId = g_strStartupDeviceId; m_strStartupCommand = g_strStartupCommand; }
m_IsDirty = FALSE;
return hr; }
STDMETHODIMP CComponentData::Save( IStream* pStm, BOOL fClearDirty ) { SafeInterfacePtr<IStream> StmPtr(pStm);
HRESULT hr;
try { COMPDATA_PERSISTINFO Info; Info.Size = sizeof(Info); Info.RootCookie = m_ctRoot; StringCchCopy(Info.Signature, ARRAYLEN(Info.Signature), DM_COMPDATA_SIGNATURE); //
// Assuming it is on local machine. The machine name is saved
// in UNICODE
//
Info.ComputerFullName[0] = UNICODE_NULL; if (m_strMachineName.GetLength()) StringCchCopy(Info.ComputerFullName, ARRAYLEN(Info.ComputerFullName), m_strMachineName); hr = pStm->Write(&Info, sizeof(Info), NULL); }
catch (CMemoryException* e) { e->Delete(); MsgBoxParam(m_hwndMain, 0, 0, 0); hr = E_OUTOFMEMORY; }
if (fClearDirty) { m_IsDirty = FALSE; } return hr; }
STDMETHODIMP CComponentData::GetSizeMax( ULARGE_INTEGER* pcbSize ) { if (!pcbSize) { return E_INVALIDARG; }
int len; len = sizeof(m_ctRoot) + sizeof(len) + (m_strMachineName.GetLength() + 1) * sizeof(TCHAR); ULISet32(*pcbSize, len); return S_OK; }
//
// Method to support html help.
//
//
STDMETHODIMP CComponentData::GetHelpTopic( LPOLESTR* lpCompileHelpFile ) { if (!lpCompileHelpFile) { return E_INVALIDARG; }
*lpCompileHelpFile = NULL; String strHelpFile; if (strHelpFile.GetSystemWindowsDirectory()) { strHelpFile += (LPCTSTR)DEVMGR_HTML_HELP_FILE_NAME; *lpCompileHelpFile = AllocOleTaskString((LPCTSTR)strHelpFile); }
return S_OK; }
CScopeItem* CComponentData::FindScopeItem( MMC_COOKIE cookie ) { CCookie* pCookie = GetActiveCookie(cookie); if (pCookie) { return pCookie->GetScopeItem(); }
return NULL; }
//
// This function loads icons for the scope items
//
HRESULT CComponentData::LoadScopeIconsForScopePane() { ASSERT(m_pScope); ASSERT(m_pConsole);
LPIMAGELIST lpScopeImage; HRESULT hr; hr = m_pConsole->QueryScopeImageList(&lpScopeImage); if (SUCCEEDED(hr)) { HICON hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_DEVMGR)); if (hIcon) { hr = lpScopeImage->ImageListSetIcon((PLONG_PTR)hIcon, IMAGE_INDEX_DEVMGR); DestroyIcon(hIcon); } hr = lpScopeImage->Release(); }
return hr; }
//
// This function create the startup wizard property sheet
//
// INPUT:
// lpProvider -- Interface for us to add pages
// handle -- notify console handle
// lpDataObject -- the data object
//
// OUTPUT:
// standard OLE HRESULT
HRESULT CComponentData::DoStartupProperties( LPPROPERTYSHEETCALLBACK lpProvider, LONG_PTR handle, LPDATAOBJECT lpDataObject ) { CGeneralPage* pGenPage; HPROPSHEETPAGE hPage;
UNREFERENCED_PARAMETER(lpDataObject);
pGenPage = new CGeneralPage();
if (pGenPage) { hPage = pGenPage->Create(handle); if (hPage) { lpProvider->AddPage(hPage); //
// If no console handle is provided, we have to use
// our call back function
//
if(!handle) { pGenPage->SetOutputBuffer(&m_strMachineName, &m_ctRoot); } return S_OK; } else { throw &g_MemoryException; } }
else { throw &g_MemoryException; } }
//
// This function creates all the necessary classes represent
// our scope items
//
HRESULT CComponentData::CreateScopeItems() { HRESULT hr = S_OK;
//
// All classes are linked by cookie with m_pCookieRoot
// points to the "root" scope item
//
if (!m_pScopeItemRoot) { switch (m_ctRoot) { case COOKIE_TYPE_SCOPEITEM_DEVMGR: m_pScopeItemRoot = new CScopeItem(COOKIE_TYPE_SCOPEITEM_DEVMGR, IMAGE_INDEX_DEVMGR, OPEN_IMAGE_INDEX_DEVMGR, IDS_NAME_DEVMGR, IDS_DESC_DEVMGR, IDS_DISPLAYNAME_SCOPE_DEVMGR); break; default: ASSERT(FALSE); break; } if (m_pScopeItemRoot->Create()) { //
// Bind scope items and cookies together.
// Cookies know its scopeitem.
// Scopeitems do not know cookies.
//
m_pCookieRoot = new CCookie(m_ctRoot); if (m_pCookieRoot) {
ASSERT(m_pScopeItemRoot->GetType() == m_ctRoot); m_pCookieRoot->SetScopeItem(m_pScopeItemRoot); CreateCookieSubtree(m_pScopeItemRoot, m_pCookieRoot); } else {
hr = E_OUTOFMEMORY; } } } return hr; }
//
// This function resets the given scopeitem.
//
HRESULT CComponentData::ResetScopeItem( CScopeItem* pScopeItem ) { HRESULT hr = S_OK; if (pScopeItem) { CScopeItem* pChild; int Index; Index = 0; while (SUCCEEDED(hr) && pScopeItem->EnumerateChildren(Index, &pChild)) { hr = ResetScopeItem(pChild); Index++; } if (SUCCEEDED(hr)) { return pScopeItem->Reset(); } }
return hr; }
|