//---------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 2001. // // File: ccomp.cpp // // Contents: // // // History: TaroonM // 10/30/01 // //---------------------------------------------------------------------------- #include "stdafx.h" #include #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // contruction/descruction DEBUG_DECLARE_INSTANCE_COUNTER(CComponentImpl); CComponentImpl::CComponentImpl() { DEBUG_INCREMENT_INSTANCE_COUNTER(CComponentImpl); Construct(); } CComponentImpl::~CComponentImpl() { #if DBG==1 ASSERT(dbg_cRef == 0); #endif DEBUG_DECREMENT_INSTANCE_COUNTER(CComponentImpl); // Make sure the interfaces have been released ASSERT(m_pConsole == NULL); ASSERT(m_pHeader == NULL); } void CComponentImpl::Construct() { #if DBG==1 dbg_cRef = 0; #endif m_pConsole = NULL; m_pHeader = NULL; m_pResultData = NULL; m_pComponentData = NULL; m_pConsoleVerb = NULL; m_CustomViewID = VIEW_DEFAULT_LV; m_dwSortOrder = 0; // default is 0, else RSI_DESCENDING m_nSortColumn = 0; } ///////////////////////////////////////////////////////////////////////////// // CComponentImpl's IComponent multiple view/instance helper functions STDMETHODIMP CComponentImpl::QueryDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type, LPDATAOBJECT* ppDataObject) { OPT_TRACE( _T("CComponentImpl::QueryDataObject this-%p, cookie-%p\n"), this, cookie ); AFX_MANAGE_STATE(AfxGetStaticModuleState()); if (ppDataObject == NULL) { TRACE(_T("CComponentImpl::QueryDataObject called with ppDataObject==NULL \n")); return E_UNEXPECTED; } if (cookie == NULL) { TRACE(_T("CComponentImpl::QueryDataObject called with cookie==NULL \n")); return E_UNEXPECTED; } *ppDataObject = NULL; IUnknown* pUnk = (IUnknown *) cookie; #ifdef _DEBUG HRESULT hr = pUnk->QueryInterface( IID_IDataObject, (void**)ppDataObject ); OPT_TRACE(_T(" QI on cookie-%p -> pDataObj-%p\n"), cookie, *ppDataObject); return hr; #else return pUnk->QueryInterface( IID_IDataObject, (void**)ppDataObject ); #endif //#ifdef _DEBUG } void CComponentImpl::SetIComponentData(CComponentDataImpl* pData) { ASSERT(pData); ASSERT(m_pComponentData == NULL); LPUNKNOWN pUnk = pData->GetUnknown(); HRESULT hr; // store their IComponentData for later use hr = pUnk->QueryInterface(IID_IComponentData, reinterpret_cast(&m_pComponentData)); // store their CComponentData for later use m_pCComponentData = pData; } STDMETHODIMP CComponentImpl::GetResultViewType(MMC_COOKIE cookie, LPOLESTR* ppViewType, long* pViewOptions) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); ASSERT (m_CustomViewID == VIEW_DEFAULT_LV); return S_FALSE; } STDMETHODIMP CComponentImpl::Initialize(LPCONSOLE lpConsole) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); HRESULT hr = E_UNEXPECTED; ASSERT(lpConsole != NULL); // Save the IConsole pointer m_pConsole = lpConsole; m_pConsole->AddRef(); // QI for IHeaderCtrl hr = m_pConsole->QueryInterface(IID_IHeaderCtrl, reinterpret_cast(&m_pHeader)); ASSERT (hr == S_OK); if (hr != S_OK) { return hr; } // Pass the IHeaderCtrl Interface on to the console m_pConsole->SetHeader(m_pHeader); // QI for IResultData hr = m_pConsole->QueryInterface(IID_IResultData, reinterpret_cast(&m_pResultData)); ASSERT (hr == S_OK); if (hr != S_OK) { return hr; } // m_pCComponentData->SetResultData (m_pResultData); // get the IControlVerb interface to support enable/disable of verbs (ie CUT/PASTE etc) hr = m_pConsole->QueryConsoleVerb(&m_pConsoleVerb); ASSERT(hr == S_OK); return hr; } STDMETHODIMP CComponentImpl::Destroy(MMC_COOKIE cookie) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); // Release the interfaces that we QI'ed if (m_pConsole != NULL) { // Tell the console to release the header control interface m_pConsole->SetHeader(NULL); SAFE_RELEASE(m_pHeader); SAFE_RELEASE(m_pResultData); // Release the IConsole interface last SAFE_RELEASE(m_pConsole); SAFE_RELEASE(m_pComponentData); // QI'ed in IComponentDataImpl::CreateComponent SAFE_RELEASE(m_pConsoleVerb); } return S_OK; } ///////////////////////////////////////////////////////////////////////////// // CComponentImpl's IComponent view/data helper functions STDMETHODIMP CComponentImpl::GetDisplayInfo(LPRESULTDATAITEM pResult) { OPT_TRACE(_T("CComponentImpl::GetDisplayInfo this-%p pUnk-%p\n"), this, pResult->lParam); AFX_MANAGE_STATE(AfxGetStaticModuleState()); ASSERT(pResult != NULL); if (NULL == pResult) // gack! return E_INVALIDARG; ASSERT( NULL != pResult->lParam ); if (NULL == pResult->lParam) { TRACE(_T("CComponentImpl::GetDisplayInfo RESULTDATAITEM.lParam == NULL\n")); ASSERT( FALSE ); return E_UNEXPECTED; } IUnknown* pUnk = (IUnknown*)pResult->lParam; CComQIPtr spData( pUnk ); if (spData == NULL) { TRACE(_T("CComponentImpl::GetDisplayInfo QI for IWirelessSnapInDataObject FAILED\n")); return E_UNEXPECTED; } return spData->GetResultDisplayInfo( pResult ); } ///////////////////////////////////////////////////////////////////////////// // CComponentImpl's I????? misc helper functions // TODO: Some misc functions don't appear to ever be called? STDMETHODIMP CComponentImpl::GetClassID(CLSID *pClassID) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); ASSERT (0); // TODO: CComponentDataImpl::GetClassID and CComponentImpl::GetClassID are identical (?) ASSERT(pClassID != NULL); // Copy the CLSID for this snapin *pClassID = CLSID_Snapin; return E_NOTIMPL; } // This compares two data objects to see if they are the same object. STDMETHODIMP CComponentImpl::CompareObjects(LPDATAOBJECT pDataObjectA, LPDATAOBJECT pDataObjectB) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); if (NULL == pDataObjectA || NULL == pDataObjectB) return E_INVALIDARG; HRESULT res = S_FALSE; // we need to check to make sure both objects belong to us... if (m_pCComponentData) { HRESULT hr; GUID guidA; GUID guidB; // Obtain GUID for A CComQIPtr spDataA(pDataObjectA); if (spDataA == NULL) { TRACE(_T("CComponentImpl::CompareObjects - QI for IWirelessSnapInDataObject[A] FAILED\n")); return E_UNEXPECTED; } hr = spDataA->GetGuidForCompare( &guidA ); ASSERT(hr == S_OK); // Obtain GUID for B CComQIPtr spDataB(pDataObjectB); if (spDataB == NULL) { TRACE(_T("CComponentImpl::CompareObjects - QI for IWirelessSnapInDataObject[B] FAILED\n")); return E_UNEXPECTED; } hr &= spDataB->GetGuidForCompare( &guidB ); ASSERT(hr == S_OK); // Compare GUIDs if (IsEqualGUID( guidA, guidB )) { return S_OK; } } // they were not ours, or they couldn't have been ours... return E_UNEXPECTED; } // This Compare is used to sort the item's in the result pane using the C runtime's // string comparison function. STDMETHODIMP CComponentImpl::Compare(LPARAM lUserParam, MMC_COOKIE cookieA, MMC_COOKIE cookieB, int* pnResult) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); OPT_TRACE(_T("CComponentImpl::Compare cookieA-%p, cookieB-%p, Column-%i, userParam-%i\n"), cookieA, cookieB, *pnResult, lUserParam ); // Get pDataObject for item A CComQIPtr spDataA((LPDATAOBJECT)cookieA); if (spDataA == NULL) { TRACE(_T("CComponentImpl::Compare - QI for IWirelessSnapInDataObject[A] FAILED\n")); return E_UNEXPECTED; } // Get pDataObject for item B CComQIPtr spDataB((LPDATAOBJECT)cookieB); if (spDataB == NULL) { TRACE(_T("CComponentImpl::Compare - QI for IWirelessSnapInDataObject[B] FAILED\n")); return E_UNEXPECTED; } HRESULT hr = S_OK; do { RESULTDATAITEM rdiA; RESULTDATAITEM rdiB; // Obtain item A's sort string rdiA.mask = RDI_STR; rdiA.nCol = *pnResult; // obtain string for this column hr = spDataA->GetResultDisplayInfo( &rdiA ); if (hr != S_OK) { TRACE(_T("CComponentImpl::Compare - IWirelessSnapInDataObject[A].GetResultDisplayInfo FAILED\n")); hr = E_UNEXPECTED; break; } // Obtain item B's sort string rdiB.mask = RDI_STR; rdiB.nCol = *pnResult; // obtain string for this column hr = spDataB->GetResultDisplayInfo( &rdiB ); if (hr != S_OK) { TRACE(_T("CComponentImpl::Compare - IWirelessSnapInDataObject[B].GetResultDisplayInfo FAILED\n")); hr = E_UNEXPECTED; break; } // Compare strings for sort *pnResult = _tcsicmp( rdiA.str, rdiB.str ); } while (0); // simulate try block return hr; } ///////////////////////////////////////////////////////////////////////////// // Event handlers for IFrame::Notify STDMETHODIMP CComponentImpl::Notify(LPDATAOBJECT pDataObject, MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param) { OPT_TRACE(_T("CComponentImpl::Notify pDataObject-%p\n"), pDataObject); if (pDataObject == NULL) { if (MMCN_PROPERTY_CHANGE == event) { if (param) { IWirelessSnapInDataObject * pData = (IWirelessSnapInDataObject *)param; //used IComponentData's IIconsole, fix for bug 464858 //pData->Notify(event, arg, param, FALSE, m_pConsole, m_pHeader ); pData->Notify(event, arg, param, FALSE, m_pCComponentData->m_pConsole, m_pHeader ); } } if (MMCN_COLUMN_CLICK == event) { ASSERT( NULL != m_pCComponentData ); // should always have this // MMCN_COLUMN_CLICK is specified as having a NULL pDataObject. ASSERT( NULL != m_pResultData ); if (NULL != m_pResultData) { // Save sort request details m_nSortColumn = arg; m_dwSortOrder = param; // Sort all result items HRESULT hr = m_pResultData->Sort( arg, param, 0 ); return hr; } return E_UNEXPECTED; } TRACE(_T("CComponentImpl::Notify ERROR(?) called with pDataObject==NULL for event-%i\n"), event); // If this asserts, look at "event" and determine whether it is normal for // pDataObject to be NULL. If so add code above to handle event. ASSERT( FALSE ); return E_UNEXPECTED; } if (MMCN_VIEW_CHANGE == event) { // Pack info for sorting result view into the hint for this event. Its safe // to do this because all calls to IConsole::UpdateAllViews from within this // snap-in do not use the hint. param = MAKELONG( m_nSortColumn, m_dwSortOrder ); } // Pass call to result item. CComQIPtr spData( pDataObject ); if (spData == NULL) { // If we are loaded as an extension snapin, let our static node handle this. if (NULL != m_pCComponentData->GetStaticScopeObject()->GetExtScopeObject()) { CComQIPtr spExtData( m_pCComponentData->GetStaticScopeObject()->GetExtScopeObject() ); if (spExtData != NULL) { HRESULT hr; hr = spExtData->Notify( event, arg, param, FALSE, m_pConsole, m_pHeader ); return hr; } ASSERT( FALSE ); } TRACE(_T("CComponentImpl::Notify - QI for IWirelessSnapInDataObject FAILED\n")); ASSERT( FALSE ); return E_UNEXPECTED; } return spData->Notify( event, arg, param, FALSE, m_pConsole, m_pHeader ); } ///////////////////////////////////////////////////////////////////////////// // IExtendPropertySheet Implementation STDMETHODIMP CComponentImpl::CreatePropertyPages(LPPROPERTYSHEETCALLBACK lpProvider, LONG_PTR handle, LPDATAOBJECT pDataObject) { if (pDataObject == NULL) { TRACE(_T("CComponentImpl::CreatePropertyPages called with pDataObject == NULL\n")); return E_UNEXPECTED; } CComQIPtr spData(pDataObject); if (spData == NULL) { TRACE(_T("CComponentImpl::CreatePropertyPages - QI for IWirelessSnapInDataObject FAILED\n")); ASSERT( FALSE ); return E_UNEXPECTED; } return spData->CreatePropertyPages( lpProvider, handle ); } STDMETHODIMP CComponentImpl::QueryPagesFor(LPDATAOBJECT pDataObject) { if (pDataObject == NULL) { TRACE(_T("CComponentImpl::QueryPagesFor called with pDataObject == NULL\n")); return E_UNEXPECTED; } CComQIPtr spData(pDataObject); if (spData == NULL) { TRACE(_T("CComponentImpl::QueryPagesFor - QI for IWirelessSnapInDataObject FAILED\n")); ASSERT( FALSE ); return E_UNEXPECTED; } return spData->QueryPagesFor(); } ///////////////////////////////////////////////////////////////////////////// // IExtendContextMenus Implementation STDMETHODIMP CComponentImpl::AddMenuItems(LPDATAOBJECT pDataObject, LPCONTEXTMENUCALLBACK pContextMenuCallback, long *pInsertionAllowed) { if (pDataObject == NULL) { TRACE(_T("CComponentImpl::AddMenuItems called with pDataObject == NULL\n")); return E_UNEXPECTED; } CComQIPtr spData(pDataObject); if (spData == NULL) { TRACE(_T("CComponentImpl::AddMenuItems - QI for IWirelessSnapInDataObject FAILED\n")); ASSERT( FALSE ); return E_UNEXPECTED; } return spData->AddMenuItems( pContextMenuCallback, pInsertionAllowed ); } STDMETHODIMP CComponentImpl::Command(long nCommandID, LPDATAOBJECT pDataObject) { if (pDataObject == NULL) { TRACE(_T("CComponentImpl::Command called with pDataObject == NULL\n")); return E_UNEXPECTED; } CComQIPtr spData(pDataObject); if (spData == NULL) { TRACE(_T("CComponentImpl::Command - QI for IWirelessSnapInDataObject FAILED\n")); ASSERT( FALSE ); return E_UNEXPECTED; } return spData->Command( nCommandID, NULL /*IConsoleNameSpace* */ ); } ///////////////////////////////////////////////////////////////////////////// // IExtendControlbar Implementation STDMETHODIMP CComponentImpl::SetControlbar( LPCONTROLBAR pControlbar ) { OPT_TRACE( _T("CComponentImpl::IExtendControlbar::SetControlbar\n") ); // pControlbar was obtained by MMC (MMCNDMGR) from our CComponentImpl by doing // a QI on IExtendControlbar. Save it so we can use it later. // Note: Always assign pControlbar to our smart pointer. pControlbar == NULL // when MMC wants us to release the interface we already have. m_spControlbar = pControlbar; return S_OK; } STDMETHODIMP CComponentImpl::ControlbarNotify( MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param ) { OPT_TRACE( _T("CComponentImpl::IExtendControlbar::ControlbarNotify\n") ); AFX_MANAGE_STATE(AfxGetStaticModuleState()); // Obtain the data obj of the currently selected item. LPDATAOBJECT pDataObject = NULL; if (event == MMCN_BTN_CLICK) { pDataObject = (LPDATAOBJECT)arg; } else if (event == MMCN_SELECT) { pDataObject = (LPDATAOBJECT)param; } if (NULL == pDataObject) { // This can happen on a MMCN_BTN_CLICK if the result pane is clicked, but not // on a result item, then a scope item toolbar button is pressed. In this case // check for one of the known scope item toolbar commands. if (IDM_CREATENEWSECPOL == param ) { pDataObject = m_pCComponentData->GetStaticScopeObject(); } else { TRACE(_T("CComponentImpl::ControlbarNotify - ERROR no IDataObject available\n")); return E_UNEXPECTED; } } // Let selected item handle command CComQIPtr spData( pDataObject ); if (spData == NULL) { TRACE(_T("CComponentImpl::ControlbarNotify - QI for IWirelessSnapInDataObject FAILED\n")); ASSERT( FALSE ); return E_UNEXPECTED; } HRESULT hr = spData->ControlbarNotify( m_spControlbar, (IExtendControlbar*)this, event, arg, param ); // If the command was not handled by the selected item, pass it to our static // scope obj. if (E_NOTIMPL == hr || S_FALSE == hr) { if (m_pCComponentData->GetStaticScopeObject() != pDataObject) { CComQIPtr spScopeData( m_pCComponentData->GetStaticScopeObject() ); if (spScopeData == NULL) { TRACE(_T("CComponentImpl::ControlbarNotify - StaticScopeObj.QI for IWirelessSnapInDataObject FAILED\n")); ASSERT( FALSE ); return E_UNEXPECTED; } hr = spScopeData->ControlbarNotify( m_spControlbar, (IExtendControlbar*)this, event, arg, param ); } } return hr; }