#include "stdafx.h" #include "DfrgSnap.h" #include "DfrgSnapin.h" #include "resource.h" #include "GetDfrgRes.h" #include "Message.h" #include "ErrMacro.h" #include "vString.hpp" ///////////////////////////////////////////////////////////////////////////// // CDfrgSnapinComponentData //static const GUID CDfrgSnapinGUID_NODETYPE = //{ 0xcd83a794, 0x6f75, 0x11d2, { 0xa3, 0x85, 0x0, 0x60, 0x97, 0x72, 0x64, 0x2e } }; static const GUID CDfrgSnapinGUID_NODETYPE = { 0x43668e22, 0x2636, 0x11d1, { 0xa1, 0xce, 0x0, 0x80, 0xc8, 0x85, 0x93, 0xa5 } }; const GUID* CDfrgSnapinData::m_NODETYPE = &CDfrgSnapinGUID_NODETYPE; // original const OLECHAR* CDfrgSnapinData::m_SZNODETYPE = OLESTR("CD83A794-6F75-11D2-A385-00609772642E"); const OLECHAR* CDfrgSnapinData::m_SZNODETYPE = OLESTR("43668E22-2636-11D1-A1CE-0080C88593A5"); const OLECHAR* CDfrgSnapinData::m_SZDISPLAY_NAME = OLESTR("Disk Defragmenter"); const CLSID* CDfrgSnapinData::m_SNAPIN_CLASSID = &CLSID_DfrgSnapin; ////////////////////////////////////// // New Extension code static const GUID CDfrgSnapinExtGUID_NODETYPE = { 0x476e644a, 0xaaff, 0x11d0, { 0xb9, 0x44, 0x0, 0xc0, 0x4f, 0xd8, 0xd5, 0xb0 } }; const GUID* CDfrgSnapinExtData::m_NODETYPE = &CDfrgSnapinExtGUID_NODETYPE; const OLECHAR* CDfrgSnapinExtData::m_SZNODETYPE = OLESTR("476e644a-aaff-11d0-b944-00c04fd8d5b0"); //sks bug # 94863, storing text "disk Defragmenter" in the registry. took out the words //disk defragmenter, because it is loaded from the resources in the override method. const OLECHAR* CDfrgSnapinExtData::m_SZDISPLAY_NAME = OLESTR(""); const CLSID* CDfrgSnapinExtData::m_SNAPIN_CLASSID = &CLSID_DfrgSnapin; // New Extension code end ////////////////////////////////////// HRESULT CDfrgSnapinData::GetScopePaneInfo(SCOPEDATAITEM *pScopeDataItem) { //TCHAR szBuf[ 256 ]; //wsprintf( szBuf, _T( "Mask is %d\n" ), pScopeDataItem->mask ); //OutputDebugString( szBuf ); if (pScopeDataItem->mask & SDI_STR) pScopeDataItem->displayname = m_bstrDisplayName; if (pScopeDataItem->mask & SDI_IMAGE) pScopeDataItem->nImage = m_scopeDataItem.nImage; if (pScopeDataItem->mask & SDI_OPENIMAGE) pScopeDataItem->nOpenImage = m_scopeDataItem.nOpenImage; if (pScopeDataItem->mask & SDI_PARAM) pScopeDataItem->lParam = m_scopeDataItem.lParam; if (pScopeDataItem->mask & SDI_STATE ) pScopeDataItem->nState = m_scopeDataItem.nState; // TODO : Add code for SDI_CHILDREN return S_OK; } HRESULT CDfrgSnapinData::GetResultPaneInfo(RESULTDATAITEM *pResultDataItem) { //TCHAR szBuf[ 256 ]; //wsprintf( szBuf, _T( "Mask is %d\n" ), pResultDataItem->mask ); //OutputDebugString( szBuf ); if (pResultDataItem->bScopeItem) { if (pResultDataItem->mask & RDI_STR) { pResultDataItem->str = GetResultPaneColInfo(pResultDataItem->nCol); } if (pResultDataItem->mask & RDI_IMAGE) { pResultDataItem->nImage = m_scopeDataItem.nImage; } if (pResultDataItem->mask & RDI_PARAM) { pResultDataItem->lParam = m_scopeDataItem.lParam; } return S_OK; } if (pResultDataItem->mask & RDI_STR) { pResultDataItem->str = GetResultPaneColInfo(pResultDataItem->nCol); } if (pResultDataItem->mask & RDI_IMAGE) { pResultDataItem->nImage = m_resultDataItem.nImage; } if (pResultDataItem->mask & RDI_PARAM) { pResultDataItem->lParam = m_resultDataItem.lParam; } if (pResultDataItem->mask & RDI_INDEX) { pResultDataItem->nIndex = m_resultDataItem.nIndex; } return S_OK; } HRESULT CDfrgSnapinData::Notify( MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param, IComponentData* pComponentData, IComponent* pComponent, DATA_OBJECT_TYPES type) { // Add code to handle the different notifications. // Handle MMCN_SHOW and MMCN_EXPAND to enumerate children items. // In response to MMCN_SHOW you have to enumerate both the scope // and result pane items. // For MMCN_EXPAND you only need to enumerate the scope items // Use IConsoleNameSpace::InsertItem to insert scope pane items // Use IResultData::InsertItem to insert result pane item. HRESULT hr = E_NOTIMPL; _ASSERTE(pComponentData != NULL || pComponent != NULL); CComPtr spConsole; CComQIPtr spHeader; if (pComponentData != NULL) spConsole = ((CDfrgSnapin*)pComponentData)->m_spConsole; else { spConsole = ((CDfrgSnapinComponent*)pComponent)->m_spConsole; spHeader = spConsole; } switch (event) { case MMCN_SELECT: { // // Always track the last valid component. // if ( HIWORD( arg ) == TRUE && pComponent ) m_pComponent = (CDfrgSnapinComponent*) pComponent; // // Always track whether or not we're a scope item. // m_fScopeItem = LOWORD( arg ); hr = S_OK; } break; case MMCN_RESTORE_VIEW: { // // Determines whether or not the remoted or OCX is displayed. // *( (BOOL*)param ) = TRUE; hr = S_OK; } break; case MMCN_CONTEXTHELP: { CComQIPtr spHelp = spConsole; spHelp->ShowTopic( CoTaskDupString( OLESTR( "defrag.chm::/defrag_overview.htm" ) ) ); hr = S_OK; } break; case MMCN_DBLCLICK: { hr = S_FALSE; } break; case MMCN_INITOCX: { hr = S_OK; break; } case MMCN_SHOW: { CComQIPtr spResultData(spConsole); if(arg == 0) { SetActiveControl(FALSE, pComponent ); } else { SetActiveControl(TRUE, pComponent ); } hr = OnShow( arg, spResultData ); break; } case MMCN_EXPAND: { CComQIPtr spConsoleNameSpace(spConsole); // TODO : Enumerate scope pane items hr = S_OK; break; } case MMCN_ADD_IMAGES: { // Add Images IImageList* pImageList = (IImageList*)arg; hr = E_FAIL; // Load bitmaps associated with the scope pane // and add them to the image list // Loads the default bitmaps generated by the wizard // Change as required HBITMAP hBitmap16 = (HBITMAP) LoadImage( GetDfrgResHandle(), // handle of the instance that contains the image MAKEINTRESOURCE(IDB_DEFRAGSNAPIN_16), // name or identifier of image IMAGE_BITMAP, // type of image 0, // desired width 0, // desired height LR_DEFAULTCOLOR // load flags ); if (hBitmap16 != NULL) { HBITMAP hBitmap32 = (HBITMAP ) LoadImage( GetDfrgResHandle(), MAKEINTRESOURCE(IDB_DEFRAGSNAPIN_32), // name or identifier of image IMAGE_BITMAP, // type of image 0, // desired width 0, // desired height LR_DEFAULTCOLOR // load flags ); if (hBitmap32 != NULL) { hr = pImageList->ImageListSetStrip((LONG_PTR *)hBitmap16, (LONG_PTR *)hBitmap32, 0, RGB(255, 255, 255)); if (FAILED(hr)) ATLTRACE(_T("IImageList::ImageListSetStrip failed\n")); ::DeleteObject(hBitmap32); hBitmap32 = NULL; } ::DeleteObject(hBitmap16); hBitmap16 = NULL; } break; } } return hr; } LPOLESTR CDfrgSnapinData::GetResultPaneColInfo(int nCol) { // // 12/13/99 This method is prototyped to return a pointer to an OLESTR which is // an OLECHAR array. Since this is a COM interface we should be using // CoTaskMemAlloc to allocate space for a copy and then copy it in. // The caller is then expected to free it. However per the MMC PM they are not // freeing it and probably cannot now or they would break too many snap-ins. // // So until they change which will probably be never, I will temporarily just // copy into a static and return a pointer to it. That way no one gets a // pointer internal to our snap-in object, and we don't leak either. // LPOLESTR pStr = NULL; static OLECHAR ColumnName[50 + 1]; static OLECHAR ColumnType[50 + 1]; static OLECHAR ColumnDesc[100 + 1]; switch (nCol) { case 0: wcsncpy(ColumnName, m_wstrColumnName, 50); ColumnName[50] = 0; pStr = ColumnName; break; case 1: wcsncpy(ColumnType, m_wstrColumnType, 50); ColumnType[50] = 0; pStr = ColumnType; break; case 2: wcsncpy(ColumnDesc, m_wstrColumnDesc, 100); ColumnDesc[100] = 0; pStr = ColumnDesc; break; } return(pStr); } HRESULT CDfrgSnapin::Initialize(LPUNKNOWN pUnknown) { HRESULT hr = IComponentDataImpl::Initialize(pUnknown); if (FAILED(hr)) return hr; CComPtr spImageList; if (m_spConsole->QueryScopeImageList(&spImageList) != S_OK) { ATLTRACE(_T("IConsole::QueryScopeImageList failed\n")); return E_UNEXPECTED; } // Load bitmaps associated with the scope pane // and add them to the image list // Loads the default bitmaps generated by the wizard // Change as required m_hBitmap16 = LoadBitmap( GetDfrgResHandle(), MAKEINTRESOURCE(IDB_DEFRAGSNAPIN_16)); if (m_hBitmap16 == NULL) return S_OK; m_hBitmap32 = LoadBitmap( GetDfrgResHandle(), MAKEINTRESOURCE(IDB_DEFRAGSNAPIN_32)); if (m_hBitmap32 == NULL) { ::DeleteObject(m_hBitmap16); m_hBitmap16 = NULL; return S_OK; } if (spImageList->ImageListSetStrip( (LONG_PTR *)m_hBitmap16, (LONG_PTR *)m_hBitmap32, 0, RGB(255, 255, 255)) != S_OK) { ATLTRACE(_T("IImageList::ImageListSetStrip failed\n")); ::DeleteObject(m_hBitmap16); m_hBitmap16 = NULL; ::DeleteObject(m_hBitmap32); m_hBitmap32 = NULL; return E_UNEXPECTED; } ::DeleteObject(m_hBitmap16); m_hBitmap16 = NULL; ::DeleteObject(m_hBitmap32); m_hBitmap32 = NULL; return S_OK; } /////////////////////////////////////////////////////////////////////////////////////////////////// // ESI Code Start /////////////////////////////////// // IExtendContextMenu::AddMenuItems() STDMETHODIMP CDfrgSnapinData::AddMenuItems( LPCONTEXTMENUCALLBACK pContextMenuCallback, long *pInsertionAllowed, DATA_OBJECT_TYPES type) { Message(TEXT("CDfrgSnapinData::AddMenuItems"), -1, NULL); HRESULT hr = S_OK; // Note - snap-ins need to look at the data object and determine // in what context, menu items need to be added. They must also // observe the insertion allowed flags to see what items can be // added. /* handy comment: typedef struct _CONTEXTMENUITEM { LPWSTR strName; LPWSTR strStatusBarText; LONG lCommandID; LONG lInsertionPointID; LONG fFlags; LONG fSpecialFlags; } CONTEXTMENUITEM; */ HINSTANCE hDfrgRes = GetDfrgResHandle(); CONTEXTMENUITEM singleMenuItem; TCHAR menuText[200]; TCHAR statusBarText[300]; // // Retrieve the control from the current component. // assert( m_pComponent != NULL ); CComPtr spDispCtl = m_pComponent->GetControl(); singleMenuItem.strName = menuText; singleMenuItem.strStatusBarText = statusBarText; singleMenuItem.fFlags = 0; singleMenuItem.fSpecialFlags = 0; // Add each of the items to the Action menu if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP) { // setting for the Action menu singleMenuItem.lInsertionPointID = CCM_INSERTIONPOINTID_PRIMARY_TOP; // get the state of the current engine BOOL isOkToRun = GetSessionState( spDispCtl, IS_OK_TO_RUN); if (isOkToRun && m_fScopeItem){ BOOL isEnginePaused = GetSessionState(spDispCtl, IS_ENGINE_PAUSED); BOOL isEngineRunning = GetSessionState(spDispCtl, IS_ENGINE_RUNNING); BOOL isVolListLocked = GetSessionState(spDispCtl, IS_VOLLIST_LOCKED); BOOL isDefragInProcess = GetSessionState(spDispCtl, IS_DEFRAG_IN_PROCESS); BOOL isReportAvailable = GetSessionState(spDispCtl, IS_REPORT_AVAILABLE); // get the proper button states LONG analyzeFlags=0; LONG defragFlags=0; LONG pauseFlags=0; LONG stopFlags=0; LONG seeReportFlags=0; if (isVolListLocked){ // turn off all buttons if this volume is locked analyzeFlags = defragFlags = pauseFlags = stopFlags = seeReportFlags = MF_DISABLED|MF_GRAYED; } else if (isEngineRunning){ analyzeFlags = defragFlags = seeReportFlags = MF_DISABLED|MF_GRAYED; pauseFlags = stopFlags = MF_ENABLED; } else{ // neither defrag nor analyze are not running on any volumes analyzeFlags = defragFlags = MF_ENABLED; pauseFlags = stopFlags = MF_DISABLED|MF_GRAYED; // is the report available for the currently selected volume? seeReportFlags = isReportAvailable ? MF_ENABLED : MF_DISABLED|MF_GRAYED; } // analyze singleMenuItem.lCommandID = IDM_ANALYZE; singleMenuItem.fFlags = analyzeFlags; LoadString(hDfrgRes, IDS_ANALYZE, menuText, sizeof(menuText) / sizeof(TCHAR)); LoadString(hDfrgRes, IDS_ANALYZE_STATUS_BAR, statusBarText, sizeof(statusBarText) / sizeof(TCHAR)); hr = pContextMenuCallback->AddItem(&singleMenuItem); if (FAILED(hr)) { Message(TEXT("CComponentDataImpl::AddMenuItems - pContextMenuCallback->AddItem"), hr, NULL); return hr; } // defrag singleMenuItem.lCommandID = IDM_DEFRAG; singleMenuItem.fFlags = defragFlags; LoadString(hDfrgRes, IDS_DEFRAGMENT, menuText, sizeof(menuText) / sizeof(TCHAR)); LoadString(hDfrgRes, IDS_DEFRAG_STATUS_BAR, statusBarText, sizeof(statusBarText) / sizeof(TCHAR)); hr = pContextMenuCallback->AddItem(&singleMenuItem); if (FAILED(hr)) { Message(TEXT("CComponentDataImpl::AddMenuItems - pContextMenuCallback->AddItem"), hr, NULL); return hr; } // pause and resume button singleMenuItem.fFlags = pauseFlags; if (isEnginePaused) // resume { singleMenuItem.lCommandID = IDM_CONTINUE; LoadString(hDfrgRes, IDS_RESUME, menuText, sizeof(menuText) / sizeof(TCHAR)); LoadString(hDfrgRes, IDS_RESUME_STATUS_BAR, statusBarText, sizeof(statusBarText) / sizeof(TCHAR)); } else{ // pause button singleMenuItem.lCommandID = IDM_PAUSE; LoadString(hDfrgRes, IDS_PAUSE, menuText, sizeof(menuText) / sizeof(TCHAR)); LoadString(hDfrgRes, IDS_PAUSE_STATUS_BAR, statusBarText, sizeof(statusBarText) / sizeof(TCHAR)); } // add the pause/resume button hr = pContextMenuCallback->AddItem(&singleMenuItem); if (FAILED(hr)) { Message(TEXT("CComponentDataImpl::AddMenuItems - pContextMenuCallback->AddItem"), hr, NULL); return hr; } // stop singleMenuItem.lCommandID = IDM_STOP; singleMenuItem.fFlags = stopFlags; LoadString(hDfrgRes, IDS_STOP, menuText, sizeof(menuText) / sizeof(TCHAR)); LoadString(hDfrgRes, IDS_STOP_STATUS_BAR, statusBarText, sizeof(statusBarText) / sizeof(TCHAR)); hr = pContextMenuCallback->AddItem(&singleMenuItem); if (FAILED(hr)) { Message(TEXT("CComponentDataImpl::AddMenuItems - pContextMenuCallback->AddItem"), hr, NULL); return hr; } // See Report singleMenuItem.lCommandID = IDM_REPORT; singleMenuItem.fFlags = seeReportFlags; LoadString(hDfrgRes, IDS_REPORT, menuText, sizeof(menuText) / sizeof(TCHAR)); LoadString(hDfrgRes, IDS_REPORT_STATUS_BAR, statusBarText, sizeof(statusBarText) / sizeof(TCHAR)); hr = pContextMenuCallback->AddItem(&singleMenuItem); if (FAILED(hr)) { Message(TEXT("CComponentDataImpl::AddMenuItems - pContextMenuCallback->AddItem"), hr, NULL); return hr; } // spacer singleMenuItem.fFlags = MF_SEPARATOR; hr = pContextMenuCallback->AddItem(&singleMenuItem); if (FAILED(hr)) { Message(TEXT("CComponentDataImpl::AddMenuItems - pContextMenuCallback->AddItem"), hr, NULL); return hr; } // Refresh the list view singleMenuItem.lCommandID = IDM_REFRESH; singleMenuItem.fFlags = MF_ENABLED; LoadString(hDfrgRes, IDS_REFRESH, menuText, sizeof(menuText) / sizeof(TCHAR)); LoadString(hDfrgRes, IDS_REFRESH_STATUS_BAR, statusBarText, sizeof(statusBarText) / sizeof(TCHAR)); hr = pContextMenuCallback->AddItem(&singleMenuItem); if (FAILED(hr)) { Message(TEXT("CComponentDataImpl::AddMenuItems - pContextMenuCallback->AddItem"), hr, NULL); return hr; } }// end of IsOkToRun } // add the view items if (*pInsertionAllowed & CCM_INSERTIONALLOWED_VIEW) { } return hr; } /////////////////////////////////// // IExtendContextMenu::Command() STDMETHODIMP CDfrgSnapinData::Command(long lCommandID, CSnapInObjectRootBase* pObj, DATA_OBJECT_TYPES type) { Message(TEXT("CDfrgSnapinData::Command"), -1, NULL); // Handle each of the commands. switch (lCommandID) { case IDM_ANALYZE: SendCommand(ID_ANALYZE); break; case IDM_DEFRAG: SendCommand(ID_DEFRAG); break; case IDM_CONTINUE: SendCommand(ID_CONTINUE); break; case IDM_PAUSE: SendCommand(ID_PAUSE); break; case IDM_STOP: SendCommand(ID_STOP); break; case IDM_REPORT: SendCommand(ID_REPORT); break; case IDM_REFRESH: SendCommand(ID_REFRESH); break; default: break; } return S_OK; } // contructor added by ESI CDfrgSnapinComponent::CDfrgSnapinComponent() { Message(TEXT("CSnapinApp::InitInstance"), -1, NULL); /* Message(TEXT("CDefragSnapinComponent::CDefragSnapinComponent"), -1, NULL); m_pHeader = NULL; m_pComponentData = NULL; //m_pToolbar1 = NULL; //m_pControlbar = NULL; //m_pbmpToolbar1 = NULL; m_pConsoleVerb = NULL; //m_pDfrgCtl = NULL; */ m_dwAdvise = 0; } CDfrgSnapinComponent::~CDfrgSnapinComponent() { Message(TEXT("CSnapinApp::ExitInstance"), -1, NULL); } /* /////////////////////////////////////////////////////////////////////////////////////////////////// // Implementation of IComponent::Notify() STDMETHODIMP CDfrgSnapinComponent::Notify( LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, long arg, long param) { long cookie = 0; HRESULT hr = S_OK; TCHAR cString[64]; switch(event) { case MMCN_PROPERTY_CHANGE: Message(TEXT("CDefragSnapinComponent::Notify - MMCN_PROPERTY_CHANGE"), -1, NULL); break; case MMCN_VIEW_CHANGE: Message(TEXT("CDefragSnapinComponent::Notify - MMCN_VIEW_CHANGE"), -1, NULL); break; case MMCN_ACTIVATE: Message(TEXT("CDefragSnapinComponent::Notify - MMCN_ACTIVATE"), -1, NULL); //hr = OnActivate(cookie, arg, param); break; case MMCN_CLICK: Message(TEXT("CDefragSnapinComponent::Notify - MMCN_CLICK"), -1, NULL); break; case MMCN_DBLCLICK: Message(TEXT("CDefragSnapinComponent::Notify - MMCN_DBLCLICK"), -1, NULL); hr = S_FALSE; // false indicates that this is not implemented break; case MMCN_ADD_IMAGES: Message(TEXT("CDefragSnapinComponent::Notify - MMCN_ADD_IMAGES"), -1, NULL); break; case MMCN_SHOW: hr = OnShow(arg); break; case MMCN_MINIMIZED: //hr = OnMinimize(cookie, arg, param); break; case MMCN_SELECT: Message(TEXT("CDefragSnapinComponent::Notify - MMCN_SELECT"), -1, NULL); // todo HandleStandardVerbs(arg, lpDataObject); break; case MMCN_BTN_CLICK: Message(TEXT("CDefragSnapinComponent::Notify - MMCN_BTN_CLICK"), -1, NULL); //AfxMessageBox(_T("CDefragSnapinComponent::MMCN_BTN_CLICK")); break; case MMCN_INITOCX: Message(TEXT("CDefragSnapinComponent::Notify - MMCN_INITOCX"), -1, NULL); break; // Note - Future expansion of notify types possible default: wsprintf(cString, TEXT("event = 0x%x"), event); Message(TEXT("CDefragSnapinComponent::Notify"), E_UNEXPECTED, cString); hr = E_UNEXPECTED; break; } return hr; } */ ///////////////////////////////////////////////////// // // Dispatch interface to the OCX (DfrgCtl) to send commands // ///////////////////////////////////////////////////// BOOL CDfrgSnapinData::SendCommand(LPARAM lparamCommand) { HRESULT hr; // Ensure that we have a pointer to the Defrag OCX if ( m_iDfrgCtlDispatch == NULL ){ Message(TEXT("SendCommand - m_iDfrgCtlDispatch is NULL!"), -1, NULL); return( FALSE ); } // get the defragger OCX dispatch interface CComPtr pDfrgCtlDispatch = m_iDfrgCtlDispatch; // get the ID of the "Command" interface OLECHAR FAR* szMember = TEXT("Command"); // maps this to "put_Command()" DISPID dispid; hr = pDfrgCtlDispatch->GetIDsOfNames( IID_NULL, // Reserved for future use. Must be IID_NULL. &szMember, // Passed-in array of names to be mapped. 1, // Count of the names to be mapped. LOCALE_USER_DEFAULT,// The locale context in which to interpret the names. &dispid); // Caller-allocated array (see help for details) if (!SUCCEEDED(hr)) { Message(TEXT("SendCommand - pDfrgCtlDispatch->GetIDsOfNames"), hr, NULL); return FALSE; } DISPID mydispid = DISPID_PROPERTYPUT; VARIANTARG* pvars = new VARIANTARG; EF(pvars); VariantInit(&pvars[0]); pvars[0].vt = VT_I2; pvars[0].iVal = (short)lparamCommand; DISPPARAMS disp = { pvars, &mydispid, 1, 1 }; hr = pDfrgCtlDispatch->Invoke( dispid, // unique number identifying the method to invoke IID_NULL, // Reserved. Must be IID_NULL LOCALE_USER_DEFAULT, // A locale ID DISPATCH_PROPERTYPUT, // flag indicating the context of the method to invoke &disp, // A structure with the parameters to pass to the method NULL, // The result from the calling method NULL, // returned exception information NULL); // index indicating the first argument that is in error delete pvars; if (!SUCCEEDED(hr)) { Message(TEXT("SendCommand - pDfrgCtlDispatch->Invoke"), hr, NULL); return FALSE; } return TRUE; } /////////////////////////////////////////////////////////////////////////////////////////////////// // gets one of the states of the OCX // see CSnapin.h for definition /////////////////////////////////////////////////////////////////////////////////////////////////// BOOL CDfrgSnapinData::GetSessionState(LPDISPATCH pdispControl, UINT sessionState) { DISPID dispid; HRESULT hr; // Ensure that we have a pointer to the Defrag OCX if ( pdispControl == NULL) return FALSE; // get the defragger OCX dispatch interface CComPtr pDfrgCtlDispatch = pdispControl; // array of the interface names OLECHAR FAR* szMember[DFRG_INTERFACE_COUNT] = { OLESTR("IsEnginePaused"), OLESTR("IsEngineRunning"), OLESTR("IsDefragInProcess"), OLESTR("IsVolListLocked"), OLESTR("ReportStatus"), OLESTR("IsOkToRun")}; hr = pDfrgCtlDispatch->GetIDsOfNames( IID_NULL, // Reserved for future use. Must be IID_NULL. &szMember[sessionState], // Passed-in array of names to be mapped. 1/*DFRG_INTERFACE_COUNT*/, // Count of the names to be mapped. LOCALE_USER_DEFAULT,// The locale context in which to interpret the names. &dispid); // Caller-allocated array (see help for details) if (!SUCCEEDED(hr)) { Message(TEXT("GetSessionState - pDfrgCtlDispatch->GetIDsOfNames"), hr, NULL); return FALSE; } VARIANT varResult; VariantInit(&varResult); V_VT(&varResult) = VT_I2; DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0}; hr = pDfrgCtlDispatch->Invoke( dispid, // unique number identifying the method to invoke IID_NULL, // Reserved. Must be IID_NULL LOCALE_USER_DEFAULT, // A locale ID DISPATCH_PROPERTYGET, // flag indicating the context of the method to invoke &dispparamsNoArgs, // A structure with the parameters to pass to the method &varResult, // The result from the calling method NULL, // returned exception information NULL); // index indicating the first argument that is in error if (!SUCCEEDED(hr)) { Message(TEXT("IsReportAvailable - pDfrgCtlDispatch->Invoke"), hr, NULL); return FALSE; } return V_BOOL(&varResult); } /////////////////////////////////////////////////////////////////////////////////////////////////// // gets the current engine state from the OCX /////////////////////////////////////////////////////////////////////////////////////////////////// short CDfrgSnapinData::GetEngineState(void) { // Ensure that we have a pointer to the Defrag OCX if( m_iDfrgCtlDispatch == NULL ) return FALSE; // get the defragger OCX dispatch interface CComPtr pDfrgCtlDispatch = m_iDfrgCtlDispatch; // get the ID of the "Command" interface OLECHAR FAR* szMember = TEXT("EngineState"); // maps this to "get_EngineState()" DISPID dispid; HRESULT hr = pDfrgCtlDispatch->GetIDsOfNames( IID_NULL, // Reserved for future use. Must be IID_NULL. &szMember, // Passed-in array of names to be mapped. 1, // Count of the names to be mapped. LOCALE_USER_DEFAULT,// The locale context in which to interpret the names. &dispid); // Caller-allocated array (see help for details) if (!SUCCEEDED(hr)) { Message(TEXT("GetEngineState - pDfrgCtlDispatch->GetIDsOfNames"), hr, NULL); return 0; } VARIANT varResult; VariantInit(&varResult); V_VT(&varResult) = VT_I2; DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0}; hr = pDfrgCtlDispatch->Invoke( dispid, // unique number identifying the method to invoke IID_NULL, // Reserved. Must be IID_NULL LOCALE_USER_DEFAULT, // A locale ID DISPATCH_PROPERTYGET, // flag indicating the context of the method to invoke &dispparamsNoArgs, // A structure with the parameters to pass to the method &varResult, // The result from the calling method NULL, // returned exception information NULL); // index indicating the first argument that is in error if (!SUCCEEDED(hr)) { Message(TEXT("GetEngineState - pDfrgCtlDispatch->Invoke"), hr, NULL); return 0; } return V_I2(&varResult); } // // Determines if the enumeration is for a remoted machine or not. // #ifndef DNS_MAX_NAME_LENGTH #define DNS_MAX_NAME_LENGTH 255 #endif bool CDfrgSnapin::IsDataObjectRemoted( IDataObject* pDataObject ) { bool fRemoted = false; TCHAR szComputerName[ DNS_MAX_NAME_LENGTH + 1 ]; DWORD dwNameLength = (DNS_MAX_NAME_LENGTH + 1); TCHAR szDataMachineName[ DNS_MAX_NAME_LENGTH + 1 ]; // // Get local computer name. // GetComputerName(szComputerName, &dwNameLength); // // Get the machine name from the given data object. // if ( ExtractString( pDataObject, m_ccfRemotedFormat, szDataMachineName, DNS_MAX_NAME_LENGTH + 1 ) ) { _toupper( szDataMachineName ); // // Find the start of the server name. // LPTSTR pStr = szDataMachineName; while ( pStr && *pStr == L'\\' ) pStr++; // // Compare the server name. // if ( pStr && *pStr && wcscmp( pStr, szComputerName ) != 0 ) fRemoted = true; } return( fRemoted ); } // // Retrieves the value of a given clipboard format from a given data object. // bool CDfrgSnapin::ExtractString( IDataObject* pDataObject, unsigned int cfClipFormat, LPTSTR pBuf, DWORD dwMaxLength) { USES_CONVERSION; bool fFound = false; FORMATETC formatetc = { (CLIPFORMAT) cfClipFormat, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL }; stgmedium.hGlobal = ::GlobalAlloc( GMEM_SHARE, dwMaxLength * sizeof(TCHAR)); HRESULT hr; do { // // This is a memory error condition! // if ( NULL == stgmedium.hGlobal ) break; hr = pDataObject->GetDataHere( &formatetc, &stgmedium ); if ( FAILED(hr) ) break; LPWSTR pszNewData = reinterpret_cast( ::GlobalLock( stgmedium.hGlobal ) ); if ( NULL == pszNewData ) break; pszNewData[ dwMaxLength - 1 ] = L'\0'; _tcscpy( pBuf, OLE2T( pszNewData ) ); fFound = true; } while( false ); if ( NULL != stgmedium.hGlobal ) { GlobalUnlock( stgmedium.hGlobal ); GlobalFree( stgmedium.hGlobal ); } return( fFound ); } HRESULT CDfrgSnapinExtData::Notify( MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param, IComponentData* pComponentData, IComponent* pComponent, DATA_OBJECT_TYPES type) { // Add code to handle the different notifications. // Handle MMCN_SHOW and MMCN_EXPAND to enumerate children items. // In response to MMCN_SHOW you have to enumerate both the scope // and result pane items. // For MMCN_EXPAND you only need to enumerate the scope items // Use IConsoleNameSpace::InsertItem to insert scope pane items // Use IResultData::InsertItem to insert result pane item. HRESULT hr = E_NOTIMPL; bool fRemoted = false; _ASSERTE( pComponentData != NULL || pComponent != NULL ); CComPtr spConsole; if ( pComponentData != NULL ) { CDfrgSnapin* pExt = (CDfrgSnapin*) pComponentData; spConsole = pExt->m_spConsole; // // Determine if we're remoted. // fRemoted = pExt->IsRemoted(); } else { spConsole = ( (CDfrgSnapinComponent*) pComponent )->m_spConsole; } switch ( event ) { case MMCN_SHOW: arg = arg; hr = S_OK; break; case MMCN_EXPAND: { if ( arg == TRUE ) { CComQIPtr spConsoleNameSpace(spConsole); SCOPEDATAITEM* pScopeData; // // Create the node based on whether we're remoted or // not. // m_pNode = new CDfrgSnapinData( fRemoted ); EE(m_pNode); m_pNode->GetScopeData( &pScopeData ); pScopeData->relativeID = param; spConsoleNameSpace->InsertItem( pScopeData ); if ( pComponentData ) ( (CDfrgSnapin*) pComponentData )->m_pNode = m_pNode; } hr = S_OK; break; } case MMCN_REMOVE_CHILDREN: { // // We are not deleting this node since this same pointer is // stashed in the pComponentData in response to the MMCN_EXPAND // notification. The destructor of pComponentData deletes the pointer // to this node. // //delete m_pNode; m_pNode = NULL; hr = S_OK; break; } case MMCN_ADD_IMAGES: { // Add Images IImageList* pImageList = (IImageList*)arg; hr = E_FAIL; // Load bitmaps associated with the scope pane // and add them to the image list // Loads the default bitmaps generated by the wizard // Change as required HBITMAP hBitmap16 = (HBITMAP) LoadImage( GetDfrgResHandle(), // handle of the instance that contains the image MAKEINTRESOURCE(IDB_DEFRAGSNAPIN_16), // name or identifier of image IMAGE_BITMAP, // type of image 0, // desired width 0, // desired height LR_DEFAULTCOLOR // load flags ); if (hBitmap16 != NULL) { BITMAP bm; GetObject( hBitmap16, sizeof( bm ), &bm ); HBITMAP hBitmap32 = (HBITMAP ) LoadImage( GetDfrgResHandle(), MAKEINTRESOURCE(IDB_DEFRAGSNAPIN_32), // name or identifier of image IMAGE_BITMAP, // type of image 0, // desired width 0, // desired height LR_DEFAULTCOLOR // load flags ); if (hBitmap32 != NULL) { GetObject( hBitmap32, sizeof( bm ), &bm ); hr = pImageList->ImageListSetStrip((LONG_PTR *)hBitmap16, (LONG_PTR *)hBitmap32, 0, RGB(255, 255, 255)); if (FAILED(hr)) ATLTRACE(_T("IImageList::ImageListSetStrip failed\n")); ::DeleteObject(hBitmap32); hBitmap32 = NULL; } ::DeleteObject(hBitmap16); hBitmap16 = NULL; } break; } } return hr; } ///////////////////////////////////////////////////////////////////////////////////////////// // // ESI function called when the snapin changes show state // HRESULT CDfrgSnapinData::OnShow(LPARAM isShowing, IResultData* pResults ) { return S_OK; } ///////////////////////////////////////////////////////////////////////////////////////////// // // instantiates the OCX // // implementation of IComponent::GetResultViewType() STDMETHODIMP CDfrgSnapinData::GetResultViewType( LPOLESTR* ppViewType, long* pViewOptions) { TCHAR szPath[ _MAX_PATH + 30 ]; Message(TEXT("IComponent::GetResultViewType"), -1, NULL); *pViewOptions = MMC_VIEW_OPTIONS_NOLISTVIEWS; // Make sure that we are displaying the OCX? if ( m_CustomViewID != VIEW_DEFRAG_OCX ) { return S_FALSE; } // // TLP: Return back a web page if we're remoted. // if ( m_fRemoted ) { TCHAR szModulePath[ _MAX_PATH + 1 ]; // // Get the HTML embedded in the res file. // GetModuleFileName( GetDfrgResHandle(), szModulePath, _MAX_PATH ); // // Append the necessary decorations for correct access. // _tcscpy( szPath, _T( "res://" ) ); _tcscat( szPath, szModulePath ); _tcscat( szPath, _T( "/REMOTED.HTM" ) ); } else { // // Display the normal OCX. // _tcscpy( szPath, szDefragGUID ); } UINT uiByteLen = (lstrlen(szPath) + 1) * sizeof(OLECHAR); LPOLESTR psz = (LPOLESTR)::CoTaskMemAlloc(uiByteLen); if (psz == NULL) { return S_FALSE; } lstrcpy(psz, szPath); *ppViewType = psz; return S_OK; } void CDfrgSnapinComponent::Advise() { if ( m_dwAdvise == 0 ) { HRESULT hr = AtlAdvise( m_spDisp, this->GetUnknown(), IID_IDfrgEvents, &m_dwAdvise ); _ASSERTE( SUCCEEDED( hr ) ); } } void CDfrgSnapinComponent::Unadvise() { if ( m_dwAdvise != 0 ) { HRESULT hr = AtlUnadvise( m_spDisp, IID_IDfrgEvents, m_dwAdvise ); _ASSERTE( SUCCEEDED( hr ) ); m_dwAdvise = 0; } } // // Overrides the Filldata // STDMETHODIMP CDfrgSnapinData::FillData( CLIPFORMAT cf, LPSTREAM pStream ) { HRESULT hr = DV_E_CLIPFORMAT; ULONG uWritten; // // We need to write out our own member since GetDisplayName() does // not give us an opportunity override its static implementation by // ATL. // if (cf == m_CCF_NODETYPE) // wants the guid for the node { hr = pStream->Write( GetNodeType(), sizeof(GUID), &uWritten); return hr; } if (cf == m_CCF_SZNODETYPE) // string that describes the node (not displayed, used for lookup of the node) { hr = pStream->Write( GetSZNodeType(), (lstrlen((LPCTSTR) GetSZNodeType()) + 1 )* sizeof(TCHAR), &uWritten); return hr; } if (cf == m_CCF_DISPLAY_NAME) // displayed in the scope pane to id the node (root only) { USES_CONVERSION; VString vDisplayName(IDS_PRODUCT_NAME, GetDfrgResHandle()); hr = pStream->Write(vDisplayName.GetBuffer(), vDisplayName.GetLength() * sizeof( WCHAR ), &uWritten); return hr; } if (cf == m_CCF_SNAPIN_CLASSID) // guid of the snapin (CLSID) { hr = pStream->Write( GetSnapInCLSID(), sizeof(GUID), &uWritten); return hr; } return hr; } /* STDMETHODIMP_(ULONG) CDfrgSnapinData::Release(void) { if (InterlockedDecrement(&m_cRef) == 0) { delete this; return 0; } return m_cRef; } STDMETHODIMP CDfrgSnapinData::QueryInterface(REFIID riid, void** ppv) { if (ppv == NULL) return E_INVALIDARG; // Make sure we are being asked for a DataObject interface. if ( riid == IID_IUnknown || riid == IID_IDfrgEvents ) { // If so return a pointer to this interface. *ppv = (IUnknown *) this; AddRef(); return S_OK; } // No interface. *ppv = NULL; return E_NOINTERFACE; } */ // // Called from the OCX when the status has changed. // STDMETHODIMP CDfrgSnapinComponent::StatusChanged( BSTR bszStatus ) { if (m_spConsole){ CComQIPtr pConsole = m_spConsole; pConsole->SetStatusText( bszStatus ); } return( S_OK ); } // // Called from the OCX when the OK to run property has changed. // STDMETHODIMP CDfrgSnapinComponent::IsOKToRun( BOOL bOK ) { ( (CDfrgSnapinData*) m_pComponentData->m_pNode )->SetActiveControl( TRUE, this ); return( S_OK ); } void CDfrgSnapinData::SetActiveControl( BOOL bActive, IComponent* pComponent ) { CComPtr spConsole; spConsole = ((CDfrgSnapinComponent*)pComponent)->m_spConsole; // // Always get the ctl dispatch pointer. // CComPtr pUnk; spConsole->QueryResultView( &pUnk ); CComQIPtr pCtl = pUnk; // // If this is the first one, then check if we're // valid. If we are, then assign this conrol to // if ( GetSessionState( pCtl, IS_OK_TO_RUN ) == TRUE ) m_iDfrgCtlDispatch = pCtl; // // Always attach the control to the component. // ( (CDfrgSnapinComponent*) pComponent )->SetControl( bActive == TRUE ? (LPDISPATCH) pCtl : (LPDISPATCH) NULL ); } STDMETHODIMP CDfrgSnapinComponent::AddMenuItems(LPDATAOBJECT pDataObject, LPCONTEXTMENUCALLBACK piCallback,long *pInsertionAllowed) { HRESULT hr; if ( IS_SPECIAL_DATAOBJECT( pDataObject ) ) { hr = m_pComponentData->m_pNode->AddMenuItems( piCallback, pInsertionAllowed, CCT_RESULT ); } else { hr = IExtendContextMenuImpl::AddMenuItems( pDataObject, piCallback, pInsertionAllowed ); } return( hr ); } STDMETHODIMP CDfrgSnapinComponent::Command(long lCommandID, LPDATAOBJECT pDataObject) { HRESULT hr; if ( IS_SPECIAL_DATAOBJECT( pDataObject ) ) { hr = m_pComponentData->m_pNode->Command( lCommandID, this, CCT_RESULT ); } else { hr = IExtendContextMenuImpl::Command( lCommandID, pDataObject ); } return( hr ); }