454 lines
12 KiB
C++
454 lines
12 KiB
C++
// stdcmpnt.cpp : Implementation of CComponent
|
|
|
|
#include "guidhelp.h" // ExtractData
|
|
|
|
// Note that m_pComponentData is still NULL during construction
|
|
CComponent::CComponent()
|
|
: m_pConsole( NULL ),
|
|
m_pConsoleVerb( NULL ),
|
|
m_pHeader( NULL ),
|
|
m_pResultData( NULL ),
|
|
m_pConsoleNameSpace( NULL ),
|
|
m_pRsltImageList( NULL ),
|
|
m_pComponentData( NULL )
|
|
{
|
|
}
|
|
|
|
CComponent::~CComponent()
|
|
{
|
|
VERIFY( SUCCEEDED(ReleaseAll()) );
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// CComponent::SetComponentDataPtr()
|
|
void CComponent::SetComponentDataPtr(
|
|
CComponentData* pComponentData)
|
|
{
|
|
ASSERT(NULL != pComponentData && NULL == m_pComponentData);
|
|
(void) ((IComponentData*)pComponentData)->AddRef();
|
|
m_pComponentData = pComponentData;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// CComponent::IComponent::QueryDataObject()
|
|
STDMETHODIMP CComponent::QueryDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type, LPDATAOBJECT* ppDataObject)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
MFC_TRY;
|
|
// Delegate it to the IComponentData
|
|
hr = QueryBaseComponentDataRef().QueryDataObject(cookie, type, ppDataObject);
|
|
MFC_CATCH;
|
|
return hr;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// CComponent::IComponent::CompareObjects()
|
|
STDMETHODIMP CComponent::CompareObjects(
|
|
LPDATAOBJECT lpDataObjectA,
|
|
LPDATAOBJECT lpDataObjectB)
|
|
{
|
|
return QueryBaseComponentDataRef().CompareObjects( lpDataObjectA, lpDataObjectB );
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// Virtual function called by CComponent::IComponent::Notify(MMCN_PROPERTY_CHANGE)
|
|
// OnPropertyChange() is generated by MMCPropertyChangeNotify( param )
|
|
HRESULT CComponent::OnPropertyChange( LPARAM /*param*/)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// Virtual function called by CComponent::IComponent::Notify(MMCN_SELECT)
|
|
HRESULT CComponent::OnNotifySelect( LPDATAOBJECT /*lpDataObject*/, BOOL /*fSelected*/ )
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// Virtual function called by CComponent::IComponent::Notify(MMCN_ACTIVATE)
|
|
HRESULT CComponent::OnNotifyActivate( LPDATAOBJECT /*lpDataObject*/, BOOL /*fActivated*/ )
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// Virtual function called by CComponent::IComponent::Notify(MMCN_CLICK)
|
|
HRESULT CComponent::OnNotifyClick( LPDATAOBJECT /*lpDataObject*/ )
|
|
{
|
|
TRACE0("CComponent::OnNotifyClick().\n");
|
|
return S_OK;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// Virtual function called by CComponent::IComponent::Notify(MMCN_DBLCLICK)
|
|
HRESULT CComponent::OnNotifyDblClick( LPDATAOBJECT /*lpDataObject*/ )
|
|
{
|
|
// Returning S_FALSE allows MMC to do the default verb.
|
|
return S_FALSE;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// Virtual function called by CComponent::IComponent::Notify(MMCN_ADD_IMAGES)
|
|
HRESULT CComponent::OnNotifyAddImages( LPDATAOBJECT /*lpDataObject*/,
|
|
LPIMAGELIST /*lpImageList*/,
|
|
HSCOPEITEM /*hSelectedItem*/ )
|
|
{
|
|
ASSERT(FALSE); // this should be redefined by all snapins
|
|
return S_OK;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// Virtual function called by CComponent::IComponent::Notify(MMCN_VIEW_CHANGE)
|
|
// OnViewChange is generated by UpdateAllViews( lpDataObject, data, hint )
|
|
HRESULT CComponent::OnViewChange( LPDATAOBJECT /*lpDataObject*/, LPARAM /*data*/, LPARAM /*hint*/ )
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// Virtual function called by CComponent::IComponent::Notify(MMCN_REFRESH)
|
|
// OnNotifyRefresh is generated by enabling the verb MMC_VERB_REFRESH.
|
|
// Typically this routine will be overriden.
|
|
HRESULT CComponent::OnNotifyRefresh( LPDATAOBJECT /*lpDataObject*/ )
|
|
{
|
|
TRACE0("CComponent::OnNotifyRefresh() - You must implement your own refresh routine.\n");
|
|
return S_OK;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// Virtual function called by CComponent::IComponent::Notify(MMCN_DELETE)
|
|
HRESULT CComponent::OnNotifyDelete( LPDATAOBJECT /*lpDataObject*/ )
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// Virtual function called by CComponent::IComponent::Notify(MMCN_COLUMN_CLICK)
|
|
HRESULT CComponent::OnNotifyColumnClick( LPDATAOBJECT /*lpDataObject*/, LPARAM /*iColumn*/, LPARAM /*uFlags*/ )
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// CComponent::ReleaseAll()
|
|
HRESULT CComponent::ReleaseAll()
|
|
{
|
|
MFC_TRY;
|
|
TRACE_METHOD(CComponent,Destructor);
|
|
|
|
if (NULL != m_pHeader)
|
|
m_pConsole->SetHeader(NULL);
|
|
|
|
SAFE_RELEASE(m_pHeader);
|
|
|
|
SAFE_RELEASE(m_pResultData);
|
|
SAFE_RELEASE(m_pConsoleNameSpace);
|
|
SAFE_RELEASE(m_pRsltImageList);
|
|
SAFE_RELEASE(m_pConsole);
|
|
SAFE_RELEASE(m_pConsoleVerb);
|
|
|
|
if ( NULL != m_pComponentData )
|
|
{
|
|
((IComponentData*)m_pComponentData)->Release();
|
|
m_pComponentData = NULL;
|
|
}
|
|
|
|
MFC_CATCH;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CComponent::IComponent::Initialize()
|
|
STDMETHODIMP CComponent::Initialize(LPCONSOLE lpConsole)
|
|
{
|
|
MFC_TRY;
|
|
TRACE_METHOD(CComponent,Create);
|
|
TEST_NONNULL_PTR_PARAM(lpConsole);
|
|
|
|
if (NULL == lpConsole)
|
|
{
|
|
ASSERT(FALSE);
|
|
return E_POINTER;
|
|
}
|
|
|
|
ASSERT( NULL == m_pConsole );
|
|
SAFE_RELEASE( m_pConsole ); // just in case
|
|
|
|
lpConsole->AddRef();
|
|
m_pConsole = lpConsole;
|
|
|
|
HRESULT hr = m_pConsole->QueryInterface(IID_IHeaderCtrl, (void**)&m_pHeader);
|
|
|
|
ASSERT(hr == S_OK);
|
|
if (FAILED(hr))
|
|
return E_FAIL;
|
|
|
|
m_pConsole->SetHeader(m_pHeader);
|
|
|
|
hr = m_pConsole->QueryConsoleVerb(OUT &m_pConsoleVerb);
|
|
ASSERT(hr == S_OK);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
ASSERT(NULL != m_pConsoleVerb);
|
|
|
|
hr = m_pConsole->QueryInterface(IID_IResultData, (void**)&m_pResultData);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = m_pConsole->QueryInterface(IID_IConsoleNameSpace, (void**)&m_pConsoleNameSpace);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = m_pConsole->QueryInterface(IID_IImageList, (void**)&m_pRsltImageList);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
// Load icons for the scope pane
|
|
LPIMAGELIST pImageList;
|
|
hr = m_pConsole->QueryScopeImageList(&pImageList);
|
|
ASSERT(SUCCEEDED(hr));
|
|
// LoadIconsIntoImageList(pImageList, FALSE);
|
|
pImageList->Release();
|
|
|
|
MFC_CATCH;
|
|
return S_OK;
|
|
} // CComponent::Initialize()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CComponent::IComponent::Notify()
|
|
// Entry point for all the MMCN_ notification messages.
|
|
// The routine will then call virtual functions of the CComponent object.
|
|
STDMETHODIMP CComponent::Notify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
MFC_TRY;
|
|
TRACE_METHOD(CComponent,Notify);
|
|
|
|
|
|
switch (event)
|
|
{
|
|
case MMCN_SHOW:
|
|
// CODEWORK this is hacked together quickly
|
|
{
|
|
CCookie* pcookie = NULL;
|
|
HRESULT hr = ExtractData( lpDataObject,
|
|
CDataObject::m_CFRawCookie,
|
|
(PBYTE)&pcookie,
|
|
sizeof(pcookie) );
|
|
ASSERT( SUCCEEDED(hr) );
|
|
CCookie* pActiveCookie = ActiveBaseCookie (pcookie);
|
|
// Save the scope item handle in the cookie
|
|
pActiveCookie->m_hScopeItem = (HSCOPEITEM) param;
|
|
hr = Show (pActiveCookie, arg, (HSCOPEITEM) param);
|
|
}
|
|
break;
|
|
|
|
case MMCN_MINIMIZED:
|
|
break;
|
|
|
|
case MMCN_SELECT:
|
|
hr = OnNotifySelect( lpDataObject, (BOOL)(HIWORD(arg)) );
|
|
break;
|
|
|
|
case MMCN_ACTIVATE:
|
|
hr = OnNotifyActivate( lpDataObject, (BOOL)arg );
|
|
break;
|
|
|
|
case MMCN_ADD_IMAGES:
|
|
hr = OnNotifyAddImages( lpDataObject,
|
|
reinterpret_cast<IImageList*>(arg),
|
|
(HSCOPEITEM)param );
|
|
break;
|
|
|
|
case MMCN_CLICK:
|
|
hr = OnNotifyClick( lpDataObject );
|
|
break;
|
|
|
|
case MMCN_DBLCLICK:
|
|
hr = OnNotifyDblClick( lpDataObject );
|
|
break;
|
|
|
|
case MMCN_PROPERTY_CHANGE:
|
|
// CODEWORK arg is "fScopePane", should this be passed on?
|
|
hr = OnPropertyChange( param );
|
|
break;
|
|
|
|
case MMCN_VIEW_CHANGE:
|
|
hr = OnViewChange( lpDataObject, arg, param );
|
|
break;
|
|
|
|
case MMCN_REFRESH:
|
|
hr = OnNotifyRefresh( lpDataObject );
|
|
break;
|
|
|
|
case MMCN_DELETE:
|
|
hr = OnNotifyDelete( lpDataObject );
|
|
break;
|
|
|
|
case MMCN_COLUMN_CLICK:
|
|
hr = OnNotifyColumnClick( lpDataObject, arg, param );
|
|
break;
|
|
|
|
case MMCN_CONTEXTHELP:
|
|
hr = OnNotifyContextHelp( lpDataObject );
|
|
break;
|
|
|
|
case MMCN_SNAPINHELP:
|
|
hr = OnNotifySnapinHelp( lpDataObject );
|
|
break;
|
|
|
|
default:
|
|
TRACE1("INFO: CComponent::Notify() - Unknown Event %d.\n", event);
|
|
break;
|
|
}
|
|
|
|
MFC_CATCH;
|
|
return hr;
|
|
} // CComponent::Notify()
|
|
|
|
|
|
// parameter "MMC_COOKIE cookie" is reserved per MSDN
|
|
STDMETHODIMP CComponent::Destroy(MMC_COOKIE /*cookie*/)
|
|
{
|
|
MFC_TRY;
|
|
TRACE_METHOD(CComponent,Destroy);
|
|
|
|
VERIFY( SUCCEEDED( ReleaseAll() ) );
|
|
|
|
MFC_CATCH;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CComponent::InsertResultCookies( CCookie& refparentcookie )
|
|
{
|
|
ASSERT( NULL != m_pResultData );
|
|
|
|
RESULTDATAITEM tRDItem;
|
|
::ZeroMemory( &tRDItem, sizeof(tRDItem) );
|
|
tRDItem.nCol = 0;
|
|
tRDItem.mask = RDI_STR | RDI_IMAGE | RDI_PARAM;
|
|
tRDItem.str = MMC_CALLBACK;
|
|
// CODEWORK should use MMC_ICON_CALLBACK here
|
|
|
|
HRESULT hr = S_OK;
|
|
POSITION pos = refparentcookie.m_listResultCookieBlocks.GetHeadPosition();
|
|
while (NULL != pos)
|
|
{
|
|
CBaseCookieBlock* pblock = refparentcookie.m_listResultCookieBlocks.GetNext( pos );
|
|
ASSERT( NULL != pblock );
|
|
for (INT i = 0; i < pblock->QueryNumCookies(); i++)
|
|
{
|
|
CCookie* pbasecookie = pblock->QueryBaseCookie(i);
|
|
tRDItem.nImage = QueryBaseComponentDataRef().QueryImage( *pbasecookie, FALSE );
|
|
// WARNING cookie cast
|
|
tRDItem.lParam = reinterpret_cast<LPARAM>(pbasecookie);
|
|
hr = m_pResultData->InsertItem(&tRDItem);
|
|
if ( FAILED(hr) )
|
|
{
|
|
ASSERT(FALSE);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CComponent::GetResultViewType(MMC_COOKIE /*cookie*/,
|
|
BSTR* ppViewType,
|
|
long* pViewOptions)
|
|
{
|
|
*ppViewType = NULL;
|
|
*pViewOptions = MMC_VIEW_OPTIONS_NONE;
|
|
return S_FALSE;
|
|
}
|
|
|
|
STDMETHODIMP CComponent::GetDisplayInfo(RESULTDATAITEM* pResultDataItem)
|
|
{
|
|
MFC_TRY;
|
|
CCookie* pcookie = ActiveBaseCookie(
|
|
reinterpret_cast<CCookie*>(pResultDataItem->lParam));
|
|
ASSERT( NULL != pResultDataItem ); // result items never have NULL cookie
|
|
if (RDI_STR & pResultDataItem->mask)
|
|
{
|
|
pResultDataItem->str = QueryBaseComponentDataRef().QueryResultColumnText(
|
|
*pcookie,
|
|
pResultDataItem->nCol );
|
|
if ( NULL == pResultDataItem->str )
|
|
pResultDataItem->str = L""; // just in case
|
|
}
|
|
if ( RDI_IMAGE & pResultDataItem->mask )
|
|
{
|
|
pResultDataItem->nImage = QueryBaseComponentDataRef().QueryImage(
|
|
*pcookie, FALSE );
|
|
}
|
|
MFC_CATCH;
|
|
return S_OK;
|
|
}
|
|
|
|
// CODEWORK These should be parameters rather than globals
|
|
// CODEWORK figure out correct const'ing
|
|
extern UINT** g_aColumns;
|
|
extern int** g_aColumnWidths;
|
|
|
|
HRESULT CComponent::LoadColumnsFromArrays(
|
|
INT objecttype )
|
|
{
|
|
ASSERT( NULL != m_pHeader );
|
|
|
|
CString str;
|
|
const UINT* pColumns = g_aColumns[objecttype];
|
|
const int* pColumnWidths = g_aColumnWidths[objecttype];
|
|
ASSERT( NULL != pColumns && NULL != pColumnWidths );
|
|
for ( INT i = 0; 0 != pColumns[i]; i++)
|
|
{
|
|
VERIFY( str.LoadString( pColumns[i] ) );
|
|
m_pHeader->InsertColumn(i, const_cast<LPTSTR>((LPCTSTR)str), LVCFMT_LEFT,
|
|
pColumnWidths[i]);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CComponent::OnNotifySnapinHelp (LPDATAOBJECT /*pDataObject*/)
|
|
{
|
|
return ShowHelpTopic( NULL ); // snapins should redefine this
|
|
}
|
|
|
|
HRESULT CComponent::OnNotifyContextHelp (LPDATAOBJECT pDataObject)
|
|
{
|
|
return OnNotifySnapinHelp( pDataObject ); // snapins should redefine this
|
|
}
|
|
|
|
HRESULT CComponent::ShowHelpTopic( LPCWSTR lpcwszHelpTopic )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
MFC_TRY;
|
|
CComQIPtr<IDisplayHelp,&IID_IDisplayHelp> spDisplayHelp = m_pConsole;
|
|
if ( !spDisplayHelp )
|
|
{
|
|
ASSERT(FALSE);
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
CString strHelpTopic;
|
|
hr = QueryBaseComponentDataRef().GetHtmlHelpFilePath( strHelpTopic );
|
|
if ( FAILED(hr) )
|
|
return hr;
|
|
if (NULL != lpcwszHelpTopic && L'\0' != *lpcwszHelpTopic)
|
|
{
|
|
strHelpTopic += L"::/";
|
|
strHelpTopic += lpcwszHelpTopic;
|
|
}
|
|
hr = spDisplayHelp->ShowTopic (T2OLE ((LPWSTR)(LPCWSTR) strHelpTopic));
|
|
ASSERT (SUCCEEDED (hr));
|
|
|
|
MFC_CATCH;
|
|
return hr;
|
|
}
|
|
|