Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1305 lines
42 KiB

#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<IConsole> spConsole;
CComQIPtr<IHeaderCtrl, &IID_IHeaderCtrl> 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<IDisplayHelp,&IID_IDisplayHelp> 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<IResultData, &IID_IResultData> spResultData(spConsole);
if(arg == 0)
{
SetActiveControl(FALSE, pComponent );
} else
{
SetActiveControl(TRUE, pComponent );
}
hr = OnShow( arg, spResultData );
break;
}
case MMCN_EXPAND:
{
CComQIPtr<IConsoleNameSpace, &IID_IConsoleNameSpace> 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<CDfrgSnapin, CDfrgSnapinComponent >::Initialize(pUnknown);
if (FAILED(hr))
return hr;
CComPtr<IImageList> 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<IDispatch> 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<IDispatch> 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<IDispatch> 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<IDispatch> 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<LPWSTR>( ::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<IConsole> 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<IConsoleNameSpace, &IID_IConsoleNameSpace> 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<IConsole2,&IID_IConsole2> 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<IConsole> spConsole;
spConsole = ((CDfrgSnapinComponent*)pComponent)->m_spConsole;
//
// Always get the ctl dispatch pointer.
//
CComPtr<IUnknown> pUnk;
spConsole->QueryResultView( &pUnk );
CComQIPtr<IDispatch,&IID_IDispatch> 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<CDfrgSnapin>::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<CDfrgSnapin>::Command( lCommandID, pDataObject );
}
return( hr );
}