/*++ Module Name: IComData.cpp Abstract: This module contains the implementation for CDfsSnapinScopeManager. This class implements IComponentData and other related interfaces --*/ #include "stdafx.h" #include "DfsGUI.h" #include "DfsScope.h" #include "MmcDispl.h" #include "DfsReslt.h" #include "Utils.h" #include "DfsNodes.h" STDMETHODIMP CDfsSnapinScopeManager::Initialize( IN LPUNKNOWN i_pUnknown ) /*++ Routine Description: Initialize the IComponentData interface. The variables needed later are QI'ed now Arguments: i_pUnknown - Pointer to the unknown object of IConsole2. --*/ { RETURN_INVALIDARG_IF_NULL(i_pUnknown); HRESULT hr = i_pUnknown->QueryInterface(IID_IConsole2, reinterpret_cast(&m_pConsole)); RETURN_IF_FAILED(hr); hr = m_pMmcDfsAdmin->PutConsolePtr(m_pConsole); RETURN_IF_FAILED(hr); hr = i_pUnknown->QueryInterface(IID_IConsoleNameSpace, reinterpret_cast(&m_pScope)); RETURN_IF_FAILED(hr); // The snap-in should also call IConsole2::QueryScopeImageList // to get the image list for the scope pane and add images // to be displayed on the scope pane side. CComPtr pScopeImageList; hr = m_pConsole->QueryScopeImageList(&pScopeImageList); RETURN_IF_FAILED(hr); HBITMAP pBMapSm = NULL; HBITMAP pBMapLg = NULL; if (!(pBMapSm = LoadBitmap(_Module.GetModuleInstance(), MAKEINTRESOURCE(IDB_SCOPE_IMAGES_16x16))) || !(pBMapLg = LoadBitmap(_Module.GetModuleInstance(), MAKEINTRESOURCE(IDB_SCOPE_IMAGES_32x32)))) { hr = HRESULT_FROM_WIN32(GetLastError()); } else { hr = pScopeImageList->ImageListSetStrip( (LONG_PTR *)pBMapSm, (LONG_PTR *)pBMapLg, 0, RGB(255, 0, 255) ); } if (pBMapSm) DeleteObject(pBMapSm); if (pBMapLg) DeleteObject(pBMapLg); return hr; } STDMETHODIMP CDfsSnapinScopeManager::CreateComponent( OUT LPCOMPONENT* o_ppComponent ) /*++ Routine Description: Creates the IComponent object Arguments: o_ppComponent - Pointer to the object in which the pointer to IComponent object is stored. --*/ { RETURN_INVALIDARG_IF_NULL(o_ppComponent); CComObject* pResultManager; CComObject::CreateInstance(&pResultManager); if (NULL == pResultManager) { return(E_FAIL); } pResultManager->m_pScopeManager = this; HRESULT hr = pResultManager->QueryInterface(IID_IComponent, (void**) o_ppComponent); _ASSERT(NULL != *o_ppComponent); return hr; } STDMETHODIMP CDfsSnapinScopeManager::Notify( IN LPDATAOBJECT i_lpDataObject, IN MMC_NOTIFY_TYPE i_Event, IN LPARAM i_lArg, IN LPARAM i_lParam ) /*++ Routine Description: Handles different events in form of notify Arguments: i_lpDataObject - The data object for the node for which the event occured i_Event - The type of event for which notify has occurred i_lArg - Argument for the event i_lParam - Parameters for the event. --*/ { // The snap-in should return S_FALSE for any notification it does not handle. // MMC then performs a default operation for the notification. HRESULT hr = S_FALSE; switch(i_Event) { case MMCN_EXPAND: { // MMC sends the MMCN_EXPAND notification the first time it needs to display a // scope item's children in either the scope or result pane. The notification // is not sent each time the item is visually expanded or collapsed. // On receipt of this notification the snap-in should enumerate the children // (subcontainers only) of the specified scope item, if any, using // IConsoleNameSpace2 methods. Subsequently, if a new item is added to or deleted // from this scope object through some external means, that item should also be // added to or deleted from the console's namespace using IConsoleNameSpace2 methods. // lpDataObject: [in] Pointer to the data object of the scope item that needs // to be expanded or collapsed. // arg: [in] TRUE if the folder is being expanded; FALSE if the folder is being collapsed. // param: [in] The HSCOPEITEM of the item that needs to be expanded or collapsed. hr = DoNotifyExpand(i_lpDataObject, (BOOL)i_lArg, (HSCOPEITEM)i_lParam); break; } case MMCN_DELETE: { // This message is generated when the user presses the delete key or uses the // mouse to click the toolbar's delete button. // The snap-in should delete the items specified in the data object. // lpDataObject: [in] Pointer to the data object of the currently selected scope // or result item, provided by the snap-in. // arg: Not used. // param: Not used. CMmcDisplay* pCMmcDisplayObj = NULL; hr = GetDisplayObject(i_lpDataObject, &pCMmcDisplayObj); if (SUCCEEDED(hr)) hr = pCMmcDisplayObj->DoDelete(); // Delete the the item. break; } case MMCN_PROPERTY_CHANGE: // Handle the property change { // i_lpDataObject is NULL because a data object is not required. // i_lArg is TRUE if the property change is for a scope item. // i_lParam is the param passed to MMCPropertyChangeNotify, this is the display object. hr = ((CMmcDisplay*)i_lParam)->PropertyChanged(); break; } default: break; } return hr; } STDMETHODIMP CDfsSnapinScopeManager::DoNotifyExpand( IN LPDATAOBJECT i_lpDataObject, IN BOOL i_bExpanding, IN HSCOPEITEM i_hParent ) /*++ Routine Description: Take action on Notify with the event MMCN_EXPAND. Arguments: i_lpDataObject - The IDataObject pointer which is used to get the DisplayObject. i_bExpanding - TRUE, if the node is expanding. FALSE otherwise i_hParent - HSCOPEITEM of the node that received this event --*/ { RETURN_INVALIDARG_IF_NULL(i_lpDataObject); if (!i_bExpanding) return S_OK; CWaitCursor WaitCursor; CMmcDisplay* pCMmcDisplayObj = NULL; HRESULT hr = GetDisplayObject(i_lpDataObject, &pCMmcDisplayObj); if (SUCCEEDED(hr)) hr = pCMmcDisplayObj->EnumerateScopePane(m_pScope, i_hParent); return hr; } STDMETHODIMP CDfsSnapinScopeManager::Destroy() /*++ Routine Description: The IComponentData object is about to be destroyed. Explicitely release all interface pointers, otherwise, MMC may not call the destructor. Arguments: None. --*/ { // The snap-in is in the process of being unloaded. Release all references to the console. m_pScope.Release(); m_pConsole.Release(); return S_OK; } STDMETHODIMP CDfsSnapinScopeManager::QueryDataObject( IN MMC_COOKIE i_lCookie, IN DATA_OBJECT_TYPES i_DataObjectType, OUT LPDATAOBJECT* o_ppDataObject ) /*++ Routine Description: Returns the IDataObject for the specified node. Arguments: i_lCookie - This parameter identifies the node for which IDataObject is being queried. i_DataObjectType - The context in which the IDataObject is being queried. Eg., Result or Scope or Snapin(Node) Manager. o_ppDataObject - The data object will be returned in this pointer. --*/ { RETURN_INVALIDARG_IF_NULL(o_ppDataObject); // We get back the cookie we stored in lparam of the scopeitem. // The cookie is the MmcDisplay pointer. // For the static(root) node, Use m_pMmcDfsAdmin as no lparam is stored. CMmcDisplay* pMmcDisplay = ((0 == i_lCookie)? (CMmcDisplay *)m_pMmcDfsAdmin : (CMmcDisplay *)i_lCookie); pMmcDisplay->put_CoClassCLSID(CLSID_DfsSnapinScopeManager); return pMmcDisplay->QueryInterface(IID_IDataObject, (void **)o_ppDataObject); } STDMETHODIMP CDfsSnapinScopeManager::GetDisplayInfo( IN OUT SCOPEDATAITEM* io_pScopeDataItem ) /*++ Routine Description: Retrieves display information for a scope item. Arguments: io_pScopeDataItem - Contains details about what information is being asked for. The information being asked is returned in this object itself. --*/ { RETURN_INVALIDARG_IF_NULL(io_pScopeDataItem); // This (cookie) is null for static node. // Static node display name is returned through IDataObject Clipboard. if (NULL == io_pScopeDataItem->lParam) return(S_OK); return ((CMmcDisplay*)(io_pScopeDataItem->lParam))->GetScopeDisplayInfo(io_pScopeDataItem); } STDMETHODIMP CDfsSnapinScopeManager::CompareObjects( IN LPDATAOBJECT lpDataObjectA, IN LPDATAOBJECT lpDataObjectB ) /*++ Routine Description: The method enables a snap-in to compare two data objects acquired through QueryDataObject. Return Values: S_OK: The data objects represented by lpDataObjectA and lpDataObjectB are the same. S_FALSE: The data objects represented by lpDataObjectA and lpDataObjectB are not the same. --*/ { if (lpDataObjectA == lpDataObjectB) return S_OK; if (!lpDataObjectA || !lpDataObjectB) return S_FALSE; FORMATETC fmte = {CMmcDisplay::mMMC_CF_Dfs_Snapin_Internal, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; STGMEDIUM medium = {TYMED_HGLOBAL, NULL, NULL}; medium.hGlobal = ::GlobalAlloc(GMEM_SHARE | GMEM_MOVEABLE | GMEM_NODISCARD, (sizeof(ULONG_PTR))); if (medium.hGlobal == NULL) return STG_E_MEDIUMFULL; HRESULT hr = lpDataObjectA->GetDataHere(&fmte, &medium); RETURN_IF_FAILED(hr); ULONG_PTR* pulVal = (ULONG_PTR*)(GlobalLock(medium.hGlobal)); CMmcDisplay* pMmcDisplayA = reinterpret_cast(*pulVal); GlobalUnlock(medium.hGlobal); hr = lpDataObjectB->GetDataHere(&fmte, &medium); RETURN_IF_FAILED(hr); pulVal = (ULONG_PTR*)(GlobalLock(medium.hGlobal)); CMmcDisplay* pMmcDisplayB = reinterpret_cast(*pulVal); GlobalUnlock(medium.hGlobal); GlobalFree(medium.hGlobal); return ((pMmcDisplayA == pMmcDisplayB) ? S_OK : S_FALSE); } STDMETHODIMP CDfsSnapinScopeManager::GetDisplayObject( IN LPDATAOBJECT i_lpDataObject, OUT CMmcDisplay** o_ppMmcDisplay ) /*++ Routine Description: Get the Display Object from the IDataObject. This is a derived object that is used for a lot of purposes Arguments: i_lpDataObject - The IDataObject pointer which is used to get the DisplayObject. o_ppMmcDisplay - The MmcDisplayObject written by us. Used as a callback for Mmc related display operations. --*/ { RETURN_INVALIDARG_IF_NULL(i_lpDataObject); RETURN_INVALIDARG_IF_NULL(o_ppMmcDisplay); FORMATETC fmte = {CMmcDisplay::mMMC_CF_Dfs_Snapin_Internal, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; STGMEDIUM medium = {TYMED_HGLOBAL, NULL, NULL}; medium.hGlobal = ::GlobalAlloc(GMEM_SHARE | GMEM_MOVEABLE | GMEM_NODISCARD, (sizeof(ULONG_PTR))); if (medium.hGlobal == NULL) return STG_E_MEDIUMFULL; HRESULT hr = i_lpDataObject->GetDataHere(&fmte, &medium); if (SUCCEEDED(hr)) { ULONG_PTR* pulVal = (ULONG_PTR*)(GlobalLock(medium.hGlobal)); *o_ppMmcDisplay = reinterpret_cast(*pulVal); GlobalUnlock(medium.hGlobal); } GlobalFree(medium.hGlobal); return hr; }