// 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; 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(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(pbasecookie); hr = m_pResultData->InsertItem(&tRDItem); if ( FAILED(hr) ) { ASSERT(FALSE); break; } } } return hr; } STDMETHODIMP CComponent::GetResultViewType(MMC_COOKIE /*cookie*/, BSTR* ppViewType, long* pViewOptions) { // ISSUE-2002/03/28-JonN check for NULL *ppViewType = NULL; *pViewOptions = MMC_VIEW_OPTIONS_NONE; return S_FALSE; } STDMETHODIMP CComponent::GetDisplayInfo(RESULTDATAITEM* pResultDataItem) { MFC_TRY; CCookie* pcookie = ActiveBaseCookie( reinterpret_cast(pResultDataItem->lParam)); // ISSUE-2002/03/28-JonN handle NULL parameter 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; // ISSUE-2002/03/28-JonN check objecttype parameter // ISSUE-2002/03/28-JonN should invoke AFX_MANAGE_STATE 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((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 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; }