You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1079 lines
24 KiB
1079 lines
24 KiB
/*++
|
|
|
|
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;
|
|
}
|