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.
331 lines
9.5 KiB
331 lines
9.5 KiB
#include "stdafx.h"
|
|
#include "Vssui.h"
|
|
#include "snapext.h"
|
|
#include "VSSProp.h"
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CVSSUIComponentData
|
|
|
|
static const GUID CVSSUIExtGUID1_NODETYPE =
|
|
{ 0x4e410f0e, 0xabc1, 0x11d0, { 0xb9, 0x44, 0x0, 0xc0, 0x4f, 0xd8, 0xd5, 0xb0 } };
|
|
const GUID* CVSSUIExtData1::m_NODETYPE = &CVSSUIExtGUID1_NODETYPE;
|
|
const OLECHAR* CVSSUIExtData1::m_SZNODETYPE = OLESTR("4e410f0e-abc1-11d0-b944-00c04fd8d5b0");
|
|
const OLECHAR* CVSSUIExtData1::m_SZDISPLAY_NAME = OLESTR("");
|
|
const CLSID* CVSSUIExtData1::m_SNAPIN_CLASSID = &CLSID_VSSUI;
|
|
|
|
static const GUID CVSSUIExtGUID2_NODETYPE =
|
|
{ 0x312B59C1, 0x4002, 0x11d0, { 0x96, 0xF8, 0x0, 0xA0, 0xC9, 0x19, 0x16, 0x01 } };
|
|
const GUID* CVSSUIExtData2::m_NODETYPE = &CVSSUIExtGUID2_NODETYPE;
|
|
const OLECHAR* CVSSUIExtData2::m_SZNODETYPE = OLESTR("312B59C1-4002-11d0-96F8-00A0C9191601");
|
|
const OLECHAR* CVSSUIExtData2::m_SZDISPLAY_NAME = OLESTR("");
|
|
const CLSID* CVSSUIExtData2::m_SNAPIN_CLASSID = &CLSID_VSSUI;
|
|
|
|
CVSSUI::CVSSUI()
|
|
{
|
|
#ifdef DEBUG
|
|
OutputDebugString(_T("CVSSUI::CVSSUI\n"));
|
|
#endif
|
|
m_pComponentData = this;
|
|
m_pPage = NULL;
|
|
}
|
|
|
|
CVSSUI::~CVSSUI()
|
|
{
|
|
#ifdef DEBUG
|
|
OutputDebugString(_T("CVSSUI::~CVSSUI\n"));
|
|
#endif
|
|
if (m_pPage)
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
delete m_pPage;
|
|
m_pPage = NULL;
|
|
}
|
|
}
|
|
///////////////////////////////
|
|
// Interface IExtendContextMenu
|
|
///////////////////////////////
|
|
|
|
CLIPFORMAT g_cfMachineName = (CLIPFORMAT)RegisterClipboardFormat(_T("MMC_SNAPIN_MACHINE_NAME"));
|
|
|
|
HRESULT CVSSUI::AddMenuItems(
|
|
LPDATAOBJECT piDataObject,
|
|
LPCONTEXTMENUCALLBACK piCallback,
|
|
long *pInsertionAllowed)
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
//
|
|
// we add the context menu item only when targeted machine belongs to postW2K server SKUs
|
|
//
|
|
TCHAR szMachineName[MAX_PATH] = {0};
|
|
HRESULT hr = ExtractData(piDataObject, g_cfMachineName, (PBYTE)szMachineName, MAX_PATH);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
CComPtr<IContextMenuCallback2> spiCallback2;
|
|
hr = piCallback->QueryInterface(IID_IContextMenuCallback2, (void **)&spiCallback2);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
if (IsPostW2KServer(szMachineName))
|
|
{
|
|
CString strMenuName;
|
|
strMenuName.LoadString(IDS_MENU_NAME);
|
|
CString strStatusBarText;
|
|
strStatusBarText.LoadString(IDS_MENU_STATUSBARTEXT);
|
|
|
|
CONTEXTMENUITEM2 ContextMenuItem;
|
|
ZeroMemory(&ContextMenuItem, sizeof(CONTEXTMENUITEM));
|
|
ContextMenuItem.strName = (LPTSTR)(LPCTSTR)strMenuName;
|
|
ContextMenuItem.strStatusBarText = (LPTSTR)(LPCTSTR)strStatusBarText;
|
|
ContextMenuItem.lCommandID = ID_CONFIG_SNAPSHOT;
|
|
ContextMenuItem.lInsertionPointID = CCM_INSERTIONPOINTID_3RDPARTY_TASK;
|
|
ContextMenuItem.strLanguageIndependentName = _T("ConfigVSS");
|
|
|
|
if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TASK)
|
|
hr = spiCallback2->AddItem(&ContextMenuItem);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CVSSUI::Command(
|
|
IN long lCommandID,
|
|
IN LPDATAOBJECT piDataObject)
|
|
{
|
|
switch (lCommandID)
|
|
{
|
|
case ID_CONFIG_SNAPSHOT:
|
|
{
|
|
InvokePropSheet(piDataObject);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT ExtractData(
|
|
IDataObject* piDataObject,
|
|
CLIPFORMAT cfClipFormat,
|
|
BYTE* pbData,
|
|
DWORD cbData )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
FORMATETC formatetc = {cfClipFormat, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
|
|
STGMEDIUM stgmedium = {TYMED_HGLOBAL, NULL, NULL};
|
|
|
|
stgmedium.hGlobal = ::GlobalAlloc(GPTR, cbData);
|
|
do // false loop
|
|
{
|
|
if (NULL == stgmedium.hGlobal)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
|
|
hr = piDataObject->GetDataHere( &formatetc, &stgmedium );
|
|
if ( FAILED(hr) )
|
|
{
|
|
break;
|
|
}
|
|
|
|
BYTE* pbNewData = reinterpret_cast<BYTE*>(stgmedium.hGlobal);
|
|
if (NULL == pbNewData)
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
break;
|
|
}
|
|
|
|
::memcpy( pbData, pbNewData, cbData );
|
|
|
|
} while (FALSE); // false loop
|
|
|
|
if (stgmedium.hGlobal)
|
|
::GlobalFree(stgmedium.hGlobal);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// disable the "Cancel" button on the property sheet
|
|
//
|
|
int CALLBACK SnapinPropSheetProc(
|
|
HWND hwndDlg,
|
|
UINT uMsg,
|
|
LPARAM lParam )
|
|
{
|
|
if (PSCB_INITIALIZED == uMsg)
|
|
{
|
|
HWND hwnd = GetDlgItem(hwndDlg, IDCANCEL);
|
|
if (hwnd)
|
|
EnableWindow(hwnd, FALSE);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// This function invokes a modal property sheet.
|
|
//
|
|
void ReplacePropertyPageCallback(void* vpsp); // implemented in shlext.cpp
|
|
HRESULT CVSSUI::InvokePropSheet(LPDATAOBJECT piDataObject)
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
CWaitCursor wait;
|
|
|
|
TCHAR szMachineName[MAX_PATH] = {0};
|
|
HRESULT hr = ExtractData(piDataObject, g_cfMachineName, (PBYTE)szMachineName, MAX_PATH);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
CString strTitle;
|
|
strTitle.LoadString(IDS_PROJNAME);
|
|
|
|
CVSSProp *pPage = new CVSSProp(szMachineName, NULL);
|
|
if (!pPage)
|
|
return E_OUTOFMEMORY;
|
|
|
|
if (pPage->m_psp.dwFlags & PSP_USECALLBACK)
|
|
{
|
|
//
|
|
// Replace with our own callback function such that we can delete pPage
|
|
// when the property sheet is closed.
|
|
//
|
|
// Note: don't change m_psp.lParam, which has to point to CVSSProp object;
|
|
// otherwise, MFC won't hook up message handler correctly.
|
|
//
|
|
ReplacePropertyPageCallback(&(pPage->m_psp));
|
|
}
|
|
|
|
PROPSHEETHEADER psh;
|
|
ZeroMemory(&psh, sizeof(psh));
|
|
psh.dwSize = sizeof(PROPSHEETHEADER);
|
|
psh.dwFlags = PSH_PROPSHEETPAGE | PSH_NOAPPLYNOW | PSH_USECALLBACK;
|
|
psh.hwndParent = ::GetActiveWindow();
|
|
psh.hInstance = _Module.GetResourceInstance();
|
|
psh.pszCaption = strTitle;
|
|
psh.nPages = 1;
|
|
psh.nStartPage = 0;
|
|
psh.ppsp = (LPCPROPSHEETPAGE)&(pPage->m_psp);
|
|
psh.pfnCallback = SnapinPropSheetProc;
|
|
|
|
PropertySheet(&psh); // this will do a modal proerty sheet
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/*
|
|
//
|
|
// This function invokes a modaless property sheet.
|
|
//
|
|
HRESULT CVSSUI::InvokePropSheet(LPDATAOBJECT piDataObject)
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
CWaitCursor wait;
|
|
|
|
//
|
|
// CoCreate an instance of the MMC Node Manager to obtain
|
|
// an IPropertySheetProvider interface pointer
|
|
//
|
|
|
|
CComPtr<IPropertySheetProvider> spiPropertySheetProvider;
|
|
HRESULT hr = CoCreateInstance(CLSID_NodeManager, NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IPropertySheetProvider,
|
|
(void **)&spiPropertySheetProvider);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
//
|
|
// Create the property sheet
|
|
//
|
|
CString strTitle;
|
|
strTitle.LoadString(IDS_PROJNAME);
|
|
hr = spiPropertySheetProvider->CreatePropertySheet(
|
|
strTitle, // pointer to the property page title
|
|
TRUE, // property sheet
|
|
NULL, // cookie of current object - can be NULL for extension snap-ins
|
|
piDataObject, // data object of selected node
|
|
NULL // specifies flags set by the method call
|
|
);
|
|
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
//
|
|
// Call AddPrimaryPages. MMC will then call the
|
|
// IExtendPropertySheet methods of our property sheet extension object
|
|
//
|
|
hr = spiPropertySheetProvider->AddPrimaryPages(
|
|
reinterpret_cast<IUnknown *>(this), // pointer to our object's IUnknown
|
|
FALSE, // specifies whether to create a notification handle
|
|
NULL, // must be NULL
|
|
TRUE // scope pane; FALSE for result pane
|
|
);
|
|
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
//
|
|
// Allow property page extensions to add
|
|
// their own pages to the property sheet
|
|
//
|
|
hr = spiPropertySheetProvider->AddExtensionPages();
|
|
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
//
|
|
//Display property sheet
|
|
//
|
|
hr = spiPropertySheetProvider->Show((LONG_PTR)::GetActiveWindow(),0);
|
|
// hr = spiPropertySheetProvider->Show(NULL,0); //NULL is allowed for modeless prop sheet
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CVSSUI::CreatePropertyPages(
|
|
LPPROPERTYSHEETCALLBACK lpProvider,
|
|
LONG_PTR handle,
|
|
LPDATAOBJECT piDataObject
|
|
)
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
TCHAR szMachineName[MAX_PATH] = {0};
|
|
HRESULT hr = ExtractData(piDataObject, g_cfMachineName, (PBYTE)szMachineName, MAX_PATH);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
m_pPage = new CVSSProp(szMachineName, NULL);
|
|
if (m_pPage)
|
|
{
|
|
CPropertyPage* pBasePage = m_pPage;
|
|
MMCPropPageCallback(&(pBasePage->m_psp));
|
|
HPROPSHEETPAGE hPage = CreatePropertySheetPage(&(pBasePage->m_psp));
|
|
|
|
if (hPage)
|
|
{
|
|
hr = lpProvider->AddPage(hPage);
|
|
if (FAILED(hr))
|
|
DestroyPropertySheetPage(hPage);
|
|
} else
|
|
hr = E_FAIL;
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
delete m_pPage;
|
|
m_pPage = NULL;
|
|
}
|
|
} else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
*/
|