windows-nt/Source/XPSP1/NT/admin/activec/nodemgr/fldrsnap.cpp
2020-09-26 16:20:57 +08:00

1965 lines
53 KiB
C++

/*--------------------------------------------------------------------------*
*
* Microsoft Windows
* Copyright (C) Microsoft Corporation, 1999 - 1999
*
* File: fldrsnap.cpp
*
* Contents: Implementation file for built-in snapins that implement
* the Folder, ActiveX Control, and Web Link nodes.
* These replace earlier code that had special "built-in"
* nodetypes.
*
* History: 23-Jul-98 vivekj Created
*
*--------------------------------------------------------------------------*/
#include "stdafx.h"
#include "tstring.h"
#include "fldrsnap.h"
#include "imageid.h"
#include <comcat.h> // COM Component Categoories Manager
#include "compcat.h"
#include "guids.h"
#include "regutil.h"
#include "newnode.h"
// These must now be the same - CMTNode::ScConvertLegacyNode depends on it.
#define SZ_OCXSTREAM (L"ocx_streamorstorage")
#define SZ_OCXSTORAGE (L"ocx_streamorstorage")
/*+-------------------------------------------------------------------------*
*
* ScLoadAndAllocateString
*
* PURPOSE: Loads the string specified by the string ID and returns a string
* whose storage has been allocated by CoTaskMemAlloc.
*
* PARAMETERS:
* UINT ids :
* LPOLESTR * lpstrOut :
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
ScLoadAndAllocateString(UINT ids, LPOLESTR *lpstrOut)
{
DECLARE_SC(sc, TEXT("ScLoadAndAllocateString"));
sc = ScCheckPointers(lpstrOut);
if(sc)
return sc.ToHr();
USES_CONVERSION;
CStr str;
str.LoadString(GetStringModule(), ids);
*lpstrOut = (LPOLESTR) CoTaskMemAlloc( (str.GetLength() +1) *sizeof(OLECHAR) );
if(*lpstrOut)
wcscpy(*lpstrOut, T2CW(str));
else
sc = E_OUTOFMEMORY;
return sc.ToHr();
}
//############################################################################
//############################################################################
//
// Implementation of class CSnapinDescriptor
//
//############################################################################
//############################################################################
/*+-------------------------------------------------------------------------*
*
* CSnapinDescriptor::CSnapinDescriptor
*
* PURPOSE: Constructor
*
*+-------------------------------------------------------------------------*/
CSnapinDescriptor::CSnapinDescriptor()
: m_idsName(0), m_idsDescription(0), m_idiSnapinImage(0), m_idbSmallImage(0), m_idbSmallImageOpen(0),
m_idbLargeImage(0), m_clsidSnapin(GUID_NULL), m_szClsidSnapin(TEXT("")),
m_guidNodetype(GUID_NULL), m_szGuidNodetype(TEXT("")), m_szClassName(TEXT("")),
m_szProgID(TEXT("")), m_szVersionIndependentProgID(TEXT("")), m_viewOptions(0)
{
}
CSnapinDescriptor::CSnapinDescriptor(UINT idsName, UINT idsDescription, UINT idiSnapinImage,
UINT idbSmallImage,UINT idbSmallImageOpen, UINT idbLargeImage,
const CLSID &clsidSnapin, LPCTSTR szClsidSnapin,
const GUID &guidNodetype, LPCTSTR szGuidNodetype,
LPCTSTR szClassName, LPCTSTR szProgID,
LPCTSTR szVersionIndependentProgID,
long viewOptions)
: m_idsName(idsName), m_idsDescription(idsDescription), m_idiSnapinImage(idiSnapinImage),
m_idbSmallImage(idbSmallImage), m_idbSmallImageOpen(idbSmallImageOpen),
m_idbLargeImage(idbLargeImage), m_clsidSnapin(clsidSnapin), m_szClsidSnapin(szClsidSnapin),
m_guidNodetype(guidNodetype), m_szGuidNodetype(szGuidNodetype), m_szClassName(szClassName),
m_szProgID(szProgID), m_szVersionIndependentProgID(szVersionIndependentProgID),
m_viewOptions(viewOptions)
{
}
/*+-------------------------------------------------------------------------*
* ScFormatIndirectSnapInName
*
* Returns the name of the snap-in in the indirect form supported by
* SHLoadRegUIString:
*
* @<dllname>,-<strId>
*--------------------------------------------------------------------------*/
SC ScFormatIndirectSnapInName (
HINSTANCE hInst, /* I:module containing the resource */
int idNameString, /* I:ID of name's string resource */
CStr& strName) /* O:formatted indirect name string */
{
DECLARE_SC (sc, _T("ScFormatIndirectSnapInName"));
/*
* allocate a buffer for GetModuleFileName
*/
const int cbBuffer = MAX_PATH;
WTL::CString strStringModule;
LPTSTR pBuffer = strStringModule.GetBuffer (cbBuffer);
/*
* if we couldn't allocate a buffer, return an error
*/
if (pBuffer == NULL)
return (sc = E_OUTOFMEMORY);
/*
* get the name of the module that provides strings
*/
const DWORD cbCopied = GetModuleFileName (hInst, pBuffer, cbBuffer);
strStringModule.ReleaseBuffer();
/*
* if GetModuleFileName failed, return its failure code
*/
if (cbCopied == 0)
{
sc.FromLastError();
/*
* just in case GetModuleFileName didn't set the last error, make
* sure the SC contains some kind of failure code
*/
if (!sc.IsError())
sc = E_FAIL;
return (sc);
}
/*
* if a path is present, SHLoadRegUIString won't search for the DLL
* based on the current UI language; remove the path portion of the
* module name so it will
*/
int nLastPathSep = strStringModule.ReverseFind (_T('\\'));
if (nLastPathSep != -1)
strStringModule = strStringModule.Mid (nLastPathSep + 1);
/*
* format the name the way SHLoadRegUIString expects it
*/
strStringModule.MakeLower();
strName.Format (_T("@%s,-%d"), (LPCTSTR) strStringModule, idNameString);
return (sc);
}
/*+-------------------------------------------------------------------------*
* CSnapinDescriptor::GetRegisteredIndirectName
*
* Returns the name of the snap-in in the indirect form supported by
* SHLoadRegUIString:
*
* @<dllname>,-<strId>
*--------------------------------------------------------------------------*/
void
CSnapinDescriptor::GetRegisteredIndirectName(CStr &strIndirectName)
{
DECLARE_SC (sc, _T("CSnapinDescriptor::GetRegisteredIndirectName"));
sc = ScFormatIndirectSnapInName (GetStringModule(), m_idsName, strIndirectName);
if (sc)
sc.TraceAndClear();
}
/*+-------------------------------------------------------------------------*
* CSnapinDescriptor::GetRegisteredDefaultName
*
* Returns the name of the snap-in in the indirect form supported by
* SHLoadRegUIString:
*
* @<dllname>,-<strId>
*--------------------------------------------------------------------------*/
void
CSnapinDescriptor::GetRegisteredDefaultName(CStr &str)
{
str.LoadString (GetStringModule(), m_idsName);
}
/*+-------------------------------------------------------------------------*
* CSnapinDescriptor::GetName
*
* Returns the human-readable name of the snap-in.
*--------------------------------------------------------------------------*/
void
CSnapinDescriptor::GetName(CStr &str)
{
DECLARE_SC (sc, _T("CSnapinDescriptor::GetName"));
/*
* get the name from the registry
*/
sc = ScGetSnapinNameFromRegistry (m_szClsidSnapin, str);
if (sc)
sc.TraceAndClear();
}
HBITMAP
CSnapinDescriptor::GetSmallImage()
{
WTL::CBitmap bmp;
bmp.LoadBitmap(MAKEINTRESOURCE(m_idbSmallImage));
return (bmp.Detach());
}
HBITMAP
CSnapinDescriptor::GetSmallImageOpen()
{
WTL::CBitmap bmp;
bmp.LoadBitmap(MAKEINTRESOURCE(m_idbSmallImageOpen));
return (bmp.Detach());
}
HBITMAP
CSnapinDescriptor::GetLargeImage()
{
WTL::CBitmap bmp;
bmp.LoadBitmap(MAKEINTRESOURCE(m_idbLargeImage));
return (bmp.Detach());
}
HICON
CSnapinDescriptor::GetSnapinImage()
{
return LoadIcon( _Module.GetModuleInstance(), MAKEINTRESOURCE(m_idiSnapinImage));
}
long
CSnapinDescriptor::GetViewOptions()
{
return m_viewOptions;
}
//############################################################################
//############################################################################
//
// Implementation of class CSnapinComponentDataImpl
//
//############################################################################
//############################################################################
/*+-------------------------------------------------------------------------*
*
* CSnapinComponentDataImpl::CSnapinComponentDataImpl
*
* PURPOSE: Constructor
*
*+-------------------------------------------------------------------------*/
CSnapinComponentDataImpl::CSnapinComponentDataImpl()
: m_bDirty(false)
{
}
void
CSnapinComponentDataImpl::SetName(LPCTSTR sz)
{
m_strName = sz;
}
/*+-------------------------------------------------------------------------*
*
* CSnapinComponentDataImpl::SetView
*
* PURPOSE: Sets the view.
*
* PARAMETERS:
* LPCTSTR sz :
*
* RETURNS:
* void
*
*+-------------------------------------------------------------------------*/
void
CSnapinComponentDataImpl::SetView(LPCTSTR sz)
{
m_strView = sz;
}
STDMETHODIMP
CSnapinComponentDataImpl::Initialize(LPUNKNOWN pUnknown)
{
m_spConsole2 = pUnknown;
m_spConsoleNameSpace2 = pUnknown;
return S_OK;
}
/*+-------------------------------------------------------------------------*
*
* CSnapinComponentDataImpl::Notify
*
* PURPOSE: Notification handler for the IComponentData implementation.
*
* PARAMETERS:
* LPDATAOBJECT lpDataObject : As per MMC docs.
* MMC_NOTIFY_TYPE event :
* LPARAM arg :
* LPARAM param :
*
* RETURNS:
* STDMETHODIMP
*
*+-------------------------------------------------------------------------*/
STDMETHODIMP
CSnapinComponentDataImpl::Notify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event,
LPARAM arg, LPARAM param)
{
USES_CONVERSION;
switch(event)
{
case MMCN_RENAME: // the root node is being renamed
m_strName = OLE2T((LPOLESTR)param);
SetDirty();
return S_OK;
case MMCN_PRELOAD:
return OnPreload((HSCOPEITEM) arg);
}
return S_FALSE;
}
/*+-------------------------------------------------------------------------*
*
* CSnapinComponentDataImpl::OnPreload
*
* PURPOSE: sets the icon of the root node (which is the only node.)
*
* PARAMETERS:
* HSCOPEITEM scopeItem :
*
* RETURNS:
* HRESULT
*
*+-------------------------------------------------------------------------*/
HRESULT
CSnapinComponentDataImpl::OnPreload(HSCOPEITEM scopeItem)
{
SCOPEDATAITEM item;
ZeroMemory (&item, sizeof(SCOPEDATAITEM));
item.mask = SDI_CHILDREN;
item.ID = scopeItem;
item.cChildren = 0; // make sure no "+" sign is displayed.
m_spConsoleNameSpace2->SetItem (&item);
return S_OK;
}
/*+-------------------------------------------------------------------------*
*
* CSnapinComponentDataImpl::Destroy
*
* PURPOSE: Gives up all references to MMC.
*
* RETURNS:
* STDMETHODIMP
*
*+-------------------------------------------------------------------------*/
STDMETHODIMP
CSnapinComponentDataImpl::Destroy()
{
m_spConsole2 = NULL;
m_spConsoleNameSpace2 = NULL;
return S_OK;
}
/*+-------------------------------------------------------------------------*
*
* CSnapinComponentDataImpl::QueryDataObject
*
* PURPOSE: Returns a data object for the specified node.
*
* PARAMETERS:
* MMC_COOKIE cookie : NULL for the root node.
* DATA_OBJECT_TYPES type :
* LPDATAOBJECT* ppDataObject :
*
* RETURNS:
* STDMETHODIMP
*
*+-------------------------------------------------------------------------*/
STDMETHODIMP
CSnapinComponentDataImpl::QueryDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type,
LPDATAOBJECT* ppDataObject)
{
ASSERT(cookie == NULL);
if(cookie != NULL)
return E_UNEXPECTED;
CComObject<CSnapinDataObject> * pDataObject;
CComObject<CSnapinDataObject>::CreateInstance(&pDataObject);
if(pDataObject == NULL)
return E_UNEXPECTED;
pDataObject->Initialize(this, type);
return pDataObject->QueryInterface(IID_IDataObject, (void**)ppDataObject);
}
/*+-------------------------------------------------------------------------*
*
* CSnapinComponentDataImpl::GetDisplayInfo
*
* PURPOSE: Gets the display info for the root (the only) node.
*
* PARAMETERS:
* SCOPEDATAITEM* pScopeDataItem : [IN/OUT]: The structure to fill in
* based on the mask value.
*
* RETURNS:
* STDMETHODIMP
*
*+-------------------------------------------------------------------------*/
STDMETHODIMP
CSnapinComponentDataImpl::GetDisplayInfo( SCOPEDATAITEM* pScopeDataItem)
{
SCOPEDATAITEM &sdi = *pScopeDataItem;
DWORD mask = sdi.mask;
if(mask & SDI_STR)
{
sdi.displayname = (LPOLESTR) GetName();
}
if(mask & SDI_IMAGE)
{
sdi.nImage = m_iImage;
}
if(mask & SDI_OPENIMAGE)
{
sdi.nImage = m_iOpenImage;
}
if(mask & SDI_STATE)
{
}
if(mask & SDI_CHILDREN)
{
sdi.cChildren =0;
}
return S_OK;
}
/*+-------------------------------------------------------------------------*
*
* CSnapinComponentDataImpl::CompareObjects
*
* PURPOSE: Determines whether two data objects correspond to the same
* underlying object.
*
* PARAMETERS:
* LPDATAOBJECT lpDataObjectA :
* LPDATAOBJECT lpDataObjectB :
*
* RETURNS:
* STDMETHODIMP : S_OK if they correspond to the same object, else S_FALSE.
*
*+-------------------------------------------------------------------------*/
STDMETHODIMP
CSnapinComponentDataImpl::CompareObjects(LPDATAOBJECT lpDataObjectA, LPDATAOBJECT lpDataObjectB)
{
return (lpDataObjectA == lpDataObjectB) ? S_OK : S_FALSE;
}
// IPersistStream
/*+-------------------------------------------------------------------------*
*
* CSnapinComponentDataImpl::GetClassID
*
* PURPOSE:
*
* PARAMETERS:
* CLSID * pClassID :
*
* RETURNS:
* STDMETHODIMP
*
*+-------------------------------------------------------------------------*/
STDMETHODIMP
CSnapinComponentDataImpl::GetClassID(CLSID *pClassID)
{
return E_NOTIMPL;
}
/*+-------------------------------------------------------------------------*
*
* CSnapinComponentDataImpl::IsDirty
*
* PURPOSE:
*
* PARAMETERS:
* voi d :
*
* RETURNS:
* STDMETHODIMP
*
*+-------------------------------------------------------------------------*/
STDMETHODIMP
CSnapinComponentDataImpl::IsDirty(void)
{
TraceDirtyFlag(TEXT("CSnapinComponentDataImpl (MMC Built-in snapin)"), m_bDirty);
return m_bDirty ? S_OK : S_FALSE;
}
/*+-------------------------------------------------------------------------*
*
* CSnapinComponentDataImpl::Load
*
* PURPOSE:
*
* PARAMETERS:
* LPSTREAM pStm :
*
* RETURNS:
* STDMETHODIMP
*
*+-------------------------------------------------------------------------*/
STDMETHODIMP
CSnapinComponentDataImpl::Load(LPSTREAM pStm)
{
return CSerialObject::Read(*pStm);
}
/*+-------------------------------------------------------------------------*
*
* CSnapinComponentDataImpl::Save
*
* PURPOSE:
*
* PARAMETERS:
* LPSTREAM pStm :
* BOOL fClearDirty :
*
* RETURNS:
* STDMETHODIMP
*
*+-------------------------------------------------------------------------*/
STDMETHODIMP
CSnapinComponentDataImpl::Save(LPSTREAM pStm , BOOL fClearDirty)
{
HRESULT hr = CSerialObjectRW::Write(*pStm);
if (SUCCEEDED(hr) && fClearDirty)
SetDirty(FALSE);
return hr;
}
/*+-------------------------------------------------------------------------*
*
* CSnapinComponentDataImpl::GetSizeMax
*
* PURPOSE:
*
* PARAMETERS:
* ULARGE_INTEGER* pcbSize :
*
* RETURNS:
* STDMETHODIMP
*
*+-------------------------------------------------------------------------*/
STDMETHODIMP
CSnapinComponentDataImpl::GetSizeMax(ULARGE_INTEGER* pcbSize )
{
return E_NOTIMPL;
}
/*+-------------------------------------------------------------------------*
*
* CSnapinComponentDataImpl::GetWatermarks
*
* PURPOSE: Sets the header for the wizard
*
* PARAMETERS:
* LPDATAOBJECT lpIDataObject :
* HBITMAP * lphWatermark :
* HBITMAP * lphHeader :
* HPALETTE * lphPalette :
* BOOL* bStretch :
*
* RETURNS:
* STDMETHODIMP
*
*+-------------------------------------------------------------------------*/
STDMETHODIMP
CSnapinComponentDataImpl::GetWatermarks(LPDATAOBJECT lpIDataObject, HBITMAP * lphWatermark, HBITMAP * lphHeader, HPALETTE * lphPalette, BOOL* bStretch)
{
DECLARE_SC(sc, TEXT("COCXSnapinData::ScGetWatermarks"));
// validate inputs
sc = ScCheckPointers(lpIDataObject, lphWatermark, lphHeader, lphPalette);
if(sc)
return sc.ToHr();
// initialize outputs
*lphWatermark = GetWatermark() ? ::LoadBitmap(_Module.GetResourceInstance(), MAKEINTRESOURCE(GetWatermark()))
: NULL;
// if there is a header, use it.
*lphHeader = GetHeaderBitmap() ? ::LoadBitmap(_Module.GetResourceInstance(), MAKEINTRESOURCE(GetHeaderBitmap()))
: NULL;
*lphPalette = NULL;
return sc.ToHr();
}
/*+-------------------------------------------------------------------------*
*
* CSnapinComponentDataImpl::QueryPagesFor
*
* PURPOSE:
*
* PARAMETERS:
* LPDATAOBJECT lpDataObject :
*
* RETURNS:
* STDMETHODIMP
*
*+-------------------------------------------------------------------------*/
STDMETHODIMP
CSnapinComponentDataImpl::QueryPagesFor(LPDATAOBJECT lpDataObject)
{
CSnapinDataObject *pDataObject = dynamic_cast<CSnapinDataObject *>(lpDataObject);
if(pDataObject == NULL)
return E_UNEXPECTED;
if(pDataObject->GetType() != CCT_SNAPIN_MANAGER)
return S_FALSE;
return S_OK; // properties exist only in the snap-in manager.
}
/*+-------------------------------------------------------------------------*
* CSnapinComponentDataImpl::GetHelpTopic
*
* Default implementation of ISnapinHelp::GetHelpTopic for built-in snap-
* ins (folder, OCX, web page).
*
* We need to implement ISnapinHelp in the built-ins to avoid getting
* "Help for <snap-in>" on the Help menu (bug 453700). They don't really
* have help info, so we simply return S_FALSE so the help engine doesn't
* complain.
*--------------------------------------------------------------------------*/
STDMETHODIMP CSnapinComponentDataImpl::GetHelpTopic (
LPOLESTR* /*ppszCompiledHelpTopic*/)
{
return (S_FALSE); // no help topic
}
// CSerialObject methods
/*+-------------------------------------------------------------------------*
*
* CSnapinComponentDataImpl::ReadSerialObject
*
* PURPOSE:
*
* PARAMETERS:
* IStream & stm :
* UINT nVersion :
*
* RETURNS:
* HRESULT
*
*+-------------------------------------------------------------------------*/
HRESULT
CSnapinComponentDataImpl::ReadSerialObject (IStream &stm, UINT nVersion)
{
if(nVersion==1)
{
stm >> m_strName;
stm >> m_strView;
return S_OK;
}
else
return S_FALSE; //unknown version, skip.
}
/*+-------------------------------------------------------------------------*
*
* CSnapinComponentDataImpl::WriteSerialObject
*
* PURPOSE:
*
* PARAMETERS:
* IStream & stm :
*
* RETURNS:
* HRESULT
*
*+-------------------------------------------------------------------------*/
HRESULT
CSnapinComponentDataImpl::WriteSerialObject(IStream &stm)
{
stm << m_strName;
stm << m_strView;
return S_OK;
}
//############################################################################
//############################################################################
//
// Implementation of class CSnapinComponentImpl
//
//############################################################################
//############################################################################
/*+-------------------------------------------------------------------------*
*
* CSnapinComponentImpl::Init
*
* PURPOSE:
*
* PARAMETERS:
* IComponentData * pComponentData :
*
* RETURNS:
* void
*
*+-------------------------------------------------------------------------*/
void
CSnapinComponentImpl::Init(IComponentData *pComponentData)
{
m_spComponentData = pComponentData;
}
// IComponent
/*+-------------------------------------------------------------------------*
*
* CSnapinComponentImpl::Initialize
*
* PURPOSE:
*
* PARAMETERS:
* LPCONSOLE lpConsole :
*
* RETURNS:
* STDMETHODIMP
*
*+-------------------------------------------------------------------------*/
STDMETHODIMP
CSnapinComponentImpl::Initialize(LPCONSOLE lpConsole)
{
m_spConsole2 = lpConsole;
return S_OK;
}
/*+-------------------------------------------------------------------------*
*
* CSnapinComponentImpl::Notify
*
* PURPOSE:
*
* PARAMETERS:
* LPDATAOBJECT lpDataObject :
* MMC_NOTIFY_TYPE event :
* LPARAM arg :
* LPARAM param :
*
* RETURNS:
* STDMETHODIMP
*
*+-------------------------------------------------------------------------*/
STDMETHODIMP
CSnapinComponentImpl::Notify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event,
LPARAM arg, LPARAM param)
{
switch(event)
{
case MMCN_SELECT:
{
BOOL bScope = (BOOL) LOWORD(arg);
BOOL bSelect = (BOOL) HIWORD(arg);
SC sc = ScOnSelect(bScope, bSelect);
if(sc)
return sc.ToHr();
}
return S_OK;
break;
default:
break;
}
return S_FALSE;
}
/*+-------------------------------------------------------------------------*
*
* CSnapinComponentImpl::ScOnSelect
*
* PURPOSE:
*
* PARAMETERS:
* BOOL bScope :
* BOOL bSelect :
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CSnapinComponentImpl::ScOnSelect(BOOL bScope, BOOL bSelect)
{
DECLARE_SC(sc, TEXT("CSnapinComponentImpl::ScOnSelect"));
IConsoleVerbPtr spConsoleVerb;
sc = m_spConsole2->QueryConsoleVerb(&spConsoleVerb);
if(sc)
return sc;
sc = spConsoleVerb->SetVerbState(MMC_VERB_RENAME, ENABLED, (bSelect && bScope));
if(sc)
return sc;
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CSnapinComponentImpl::Destroy
*
* PURPOSE:
*
* PARAMETERS:
* MMC_COOKIE cookie :
*
* RETURNS:
* STDMETHODIMP
*
*+-------------------------------------------------------------------------*/
STDMETHODIMP
CSnapinComponentImpl::Destroy(MMC_COOKIE cookie)
{
m_spConsole2 = NULL;
m_spComponentData = NULL;
return S_OK;
}
/*+-------------------------------------------------------------------------*
*
* CSnapinComponentImpl::QueryDataObject
*
* PURPOSE:
*
* PARAMETERS:
* MMC_COOKIE cookie :
* DATA_OBJECT_TYPES type :
* LPDATAOBJECT* ppDataObject :
*
* RETURNS:
* STDMETHODIMP
*
*+-------------------------------------------------------------------------*/
STDMETHODIMP
CSnapinComponentImpl::QueryDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type,
LPDATAOBJECT* ppDataObject)
{
return E_NOTIMPL;
}
/*+-------------------------------------------------------------------------*
*
* CSnapinComponentImpl::GetComponentData
*
* PURPOSE:
*
* RETURNS:
* CSnapinComponentDataImpl *
*
*+-------------------------------------------------------------------------*/
CSnapinComponentDataImpl *
CSnapinComponentImpl::GetComponentData()
{
CSnapinComponentDataImpl *pCD = dynamic_cast<CSnapinComponentDataImpl *>(m_spComponentData.GetInterfacePtr());
ASSERT(pCD != NULL);
return pCD;
}
/*+-------------------------------------------------------------------------*
*
* CSnapinComponentImpl::GetResultViewType
*
* PURPOSE:
*
* PARAMETERS:
* MMC_COOKIE cookie :
* LPOLESTR* ppViewType :
* long* pViewOptions : Set to MMC_VIEW_OPTIONS_NOLISTVIEWS for the HTML and OCX snapins,
* 0 for the folder snapin.
*
* RETURNS:
* STDMETHODIMP
*
*+-------------------------------------------------------------------------*/
STDMETHODIMP
CSnapinComponentImpl::GetResultViewType(MMC_COOKIE cookie, LPOLESTR* ppViewType,
long* pViewOptions)
{
// check parameters
if(!ppViewType || !pViewOptions)
return E_UNEXPECTED;
if(!GetComponentData())
return E_UNEXPECTED;
USES_CONVERSION;
*ppViewType = (LPOLESTR)CoTaskMemAlloc( (_tcslen(GetComponentData()->GetView())+1) * sizeof(OLECHAR) );
*pViewOptions = GetComponentData()->GetDescriptor().GetViewOptions();
wcscpy(*ppViewType, T2OLE((LPTSTR)GetComponentData()->GetView()));
return S_OK;
}
/*+-------------------------------------------------------------------------*
*
* CSnapinComponentImpl::GetDisplayInfo
*
* PURPOSE:
*
* PARAMETERS:
* RESULTDATAITEM* pResultDataItem :
*
* RETURNS:
* STDMETHODIMP
*
*+-------------------------------------------------------------------------*/
STDMETHODIMP
CSnapinComponentImpl::GetDisplayInfo( RESULTDATAITEM* pResultDataItem)
{
RESULTDATAITEM &rdi = *pResultDataItem;
DWORD mask = rdi.mask;
if(mask & RDI_STR)
{
rdi.str = (LPOLESTR) GetComponentData()->GetName();
}
if(mask & RDI_IMAGE)
{
rdi.nImage = GetComponentData()->m_iImage;
}
return S_OK;
}
/*+-------------------------------------------------------------------------*
*
* CSnapinComponentImpl::CompareObjects
*
* PURPOSE:
*
* PARAMETERS:
* LPDATAOBJECT lpDataObjectA :
* LPDATAOBJECT lpDataObjectB :
*
* RETURNS:
* STDMETHODIMP
*
*+-------------------------------------------------------------------------*/
STDMETHODIMP
CSnapinComponentImpl::CompareObjects(LPDATAOBJECT lpDataObjectA, LPDATAOBJECT lpDataObjectB)
{
return E_NOTIMPL;
}
//############################################################################
//############################################################################
//
// Implementation of class CSnapinDataObject
//
//############################################################################
//############################################################################
// Clipboard formats that are required by the console
UINT CSnapinDataObject::s_cfNodeType;
UINT CSnapinDataObject::s_cfNodeTypeString;
UINT CSnapinDataObject::s_cfDisplayName;
UINT CSnapinDataObject::s_cfCoClass;
UINT CSnapinDataObject::s_cfSnapinPreloads;
/*+-------------------------------------------------------------------------*
*
* CSnapinDataObject::RegisterClipboardFormats
*
* PURPOSE:
*
* RETURNS:
* void
*
*+-------------------------------------------------------------------------*/
void
CSnapinDataObject::RegisterClipboardFormats()
{
static bool bRegistered = false;
if(!bRegistered)
{
USES_CONVERSION;
CSnapinDataObject::s_cfNodeType = RegisterClipboardFormat(OLE2T(CCF_NODETYPE));
CSnapinDataObject::s_cfNodeTypeString = RegisterClipboardFormat(OLE2T(CCF_SZNODETYPE));
CSnapinDataObject::s_cfDisplayName = RegisterClipboardFormat(OLE2T(CCF_DISPLAY_NAME));
CSnapinDataObject::s_cfCoClass = RegisterClipboardFormat(OLE2T(CCF_SNAPIN_CLASSID));
CSnapinDataObject::s_cfSnapinPreloads = RegisterClipboardFormat(OLE2T(CCF_SNAPIN_PRELOADS));
bRegistered = true;
}
}
CSnapinDataObject::CSnapinDataObject() : m_bInitialized(false)
{
}
/*+-------------------------------------------------------------------------*
*
* CSnapinDataObject::GetDataHere
*
* PURPOSE:
*
* PARAMETERS:
* FORMATETC * pformatetc :
* STGMEDIUM * pmedium :
*
* RETURNS:
* STDMETHODIMP
*
*+-------------------------------------------------------------------------*/
STDMETHODIMP
CSnapinDataObject::GetDataHere(FORMATETC *pformatetc, STGMEDIUM *pmedium)
{
DECLARE_SC(sc, TEXT("CSnapinDataObject::GetDataHere"));
// validate inputs
sc = ScCheckPointers(pformatetc, pmedium);
if(sc)
return sc.ToHr();
USES_CONVERSION;
RegisterClipboardFormats();
// Based on the CLIPFORMAT write data to the stream
const CLIPFORMAT cf = pformatetc->cfFormat;
// ensure the medium is an HGLOBAL
if(pformatetc->tymed != TYMED_HGLOBAL)
return (sc = DV_E_TYMED).ToHr();
IStreamPtr spStream;
HGLOBAL hGlobal = pmedium->hGlobal;
pmedium->pUnkForRelease = NULL; // by OLE spec
sc = CreateStreamOnHGlobal( hGlobal, FALSE, &spStream );
if(sc)
return sc.ToHr();
CSnapinComponentDataImpl *pComponentDataImpl =
dynamic_cast<CSnapinComponentDataImpl *>(m_spComponentData.GetInterfacePtr());
ASSERT(pComponentDataImpl != NULL);
if (cf == s_cfNodeType)
{
spStream<<pComponentDataImpl->GetDescriptor().m_guidNodetype;
}
else if (cf == s_cfCoClass)
{
spStream<<pComponentDataImpl->GetDescriptor().m_clsidSnapin;
}
else if(cf == s_cfNodeTypeString)
{
WriteString(spStream, T2OLE((LPTSTR)pComponentDataImpl->GetDescriptor().m_szGuidNodetype));
}
else if (cf == s_cfDisplayName)
{
WriteString(spStream, T2OLE((LPTSTR)pComponentDataImpl->GetName()));
}
else if (cf == s_cfSnapinPreloads)
{
BOOL bPreload = true;
spStream->Write ((void *)&bPreload, sizeof(BOOL), NULL);
}
else
{
return (sc = DV_E_CLIPFORMAT).ToHr(); // invalid format.
}
return sc.ToHr();
}
/*+-------------------------------------------------------------------------*
*
* CSnapinDataObject::WriteString
*
* PURPOSE:
*
* PARAMETERS:
* IStream * pStream :
* LPCOLESTR sz :
*
* RETURNS:
* HRESULT
*
*+-------------------------------------------------------------------------*/
HRESULT
CSnapinDataObject::WriteString(IStream *pStream, LPCOLESTR sz)
{
HRESULT hr = S_OK;
ASSERT(pStream != NULL);
if(pStream == NULL)
{
//TraceError(TEXT("CSnapinDataObject::WriteString"));
return E_UNEXPECTED;
}
UINT cbToWrite = wcslen(sz)*sizeof(WCHAR);
ULONG cbActuallyWritten=0;
hr = pStream->Write (sz, cbToWrite, &cbActuallyWritten);
ASSERT(cbToWrite==cbActuallyWritten);
return hr;
}
/*+-------------------------------------------------------------------------*
*
* CSnapinDataObject::Initialize
*
* PURPOSE:
*
* PARAMETERS:
* IComponentData * pComponentData :
* DATA_OBJECT_TYPES type :
*
* RETURNS:
* void
*
*+-------------------------------------------------------------------------*/
void
CSnapinDataObject::Initialize(IComponentData *pComponentData, DATA_OBJECT_TYPES type)
{
ASSERT(pComponentData != NULL);
m_spComponentData = pComponentData;
m_type = type;
m_bInitialized = true;
}
//############################################################################
//############################################################################
//
// Implementation of class CFolderSnapinData
//
//############################################################################
//############################################################################
STDMETHODIMP
CFolderSnapinData::CreateComponent(LPCOMPONENT* ppComponent)
{
typedef CComObject<CFolderSnapinComponent> CComponent;
CComponent * pComponent = NULL;
CComObject<CFolderSnapinComponent>::CreateInstance(&pComponent);
ASSERT(pComponent != NULL);
if(pComponent == NULL)
{
//TraceError(TEXT("CFolderSnapinData::CreateComponent"));
return E_UNEXPECTED;
}
pComponent->Init(this);
return pComponent->QueryInterface(IID_IComponent, (void **)ppComponent); // does the Addref.
}
CFolderSnapinData::CFolderSnapinData()
{
m_iImage = eStockImage_Folder;
m_iOpenImage = eStockImage_OpenFolder;
}
const CLSID CLSID_FolderSnapin = {0xC96401CC, 0x0E17,0x11D3, {0x88,0x5B,0x00,0xC0,0x4F,0x72,0xC7,0x17}};
static const GUID GUID_FolderSnapinNodetype = {0xc96401ce, 0xe17, 0x11d3, { 0x88, 0x5b, 0x0, 0xc0, 0x4f, 0x72, 0xc7, 0x17 } };
static LPCTSTR szClsid_FolderSnapin = TEXT("{C96401CC-0E17-11D3-885B-00C04F72C717}");
static LPCTSTR szGuidFolderSnapinNodetype = TEXT("{C96401CE-0E17-11D3-885B-00C04F72C717}");
CSnapinDescriptor &
CFolderSnapinData::GetSnapinDescriptor()
{
static CSnapinDescriptor snapinDescription(IDS_FOLDER,
IDS_FOLDERSNAPIN_DESC, IDI_FOLDER, IDB_FOLDER_16, IDB_FOLDEROPEN_16, IDB_FOLDER_32,
CLSID_FolderSnapin, szClsid_FolderSnapin, GUID_FolderSnapinNodetype,
szGuidFolderSnapinNodetype, TEXT("Folder"), TEXT("Snapins.FolderSnapin"),
TEXT("Snapins.FolderSnapin.1"), 0 /*viewOptions*/ );
return snapinDescription;
}
// IExtendPropertySheet2
STDMETHODIMP
CFolderSnapinData::CreatePropertyPages(LPPROPERTYSHEETCALLBACK lpProvider, LONG_PTR handle, LPDATAOBJECT lpIDataObject)
{
return S_FALSE;
}
//############################################################################
//############################################################################
//
// Implementation of class CHTMLSnapinData
//
//############################################################################
//############################################################################
STDMETHODIMP
CHTMLSnapinData::CreateComponent(LPCOMPONENT* ppComponent)
{
typedef CComObject<CHTMLSnapinComponent> CComponent;
CComponent * pComponent = NULL;
CComObject<CHTMLSnapinComponent>::CreateInstance(&pComponent);
ASSERT(pComponent != NULL);
if(pComponent == NULL)
{
//TraceError(TEXT("CHTMLSnapinData::CreateComponent"));
return E_UNEXPECTED;
}
pComponent->Init(this);
return pComponent->QueryInterface(IID_IComponent, (void **)ppComponent); // does the Addref.
}
CHTMLSnapinData::CHTMLSnapinData()
{
m_pHtmlPage1 = NULL;
m_pHtmlPage2 = NULL;
m_iImage = eStockImage_HTML;
m_iOpenImage = eStockImage_HTML;
}
CHTMLSnapinData::~CHTMLSnapinData()
{
}
STDMETHODIMP
CHTMLSnapinData::Destroy()
{
if(m_pHtmlPage1 != NULL)
{
delete m_pHtmlPage1;
m_pHtmlPage1 = NULL;
}
if(m_pHtmlPage2 != NULL)
{
delete m_pHtmlPage2;
m_pHtmlPage2 = NULL;
}
return BC::Destroy();
}
const CLSID CLSID_HTMLSnapin = {0xC96401D1, 0x0E17,0x11D3, {0x88,0x5B,0x00,0xC0,0x4F,0x72,0xC7,0x17}};
static const GUID GUID_HTMLSnapinNodetype = {0xc96401d2, 0xe17, 0x11d3, { 0x88, 0x5b, 0x0, 0xc0, 0x4f, 0x72, 0xc7, 0x17 } };
static LPCTSTR szClsid_HTMLSnapin = TEXT("{C96401D1-0E17-11D3-885B-00C04F72C717}");
static LPCTSTR szGuidHTMLSnapinNodetype = TEXT("{C96401D2-0E17-11D3-885B-00C04F72C717}");
CSnapinDescriptor &
CHTMLSnapinData::GetSnapinDescriptor()
{
static CSnapinDescriptor snapinDescription(IDS_HTML,
IDS_HTMLSNAPIN_DESC, IDI_HTML, IDB_HTML_16, IDB_HTML_16, IDB_HTML_32,
CLSID_HTMLSnapin, szClsid_HTMLSnapin, GUID_HTMLSnapinNodetype,
szGuidHTMLSnapinNodetype, TEXT("HTML"), TEXT("Snapins.HTMLSnapin"),
TEXT("Snapins.HTMLSnapin.1"), MMC_VIEW_OPTIONS_NOLISTVIEWS /*viewOptions*/ );
return snapinDescription;
}
// IExtendPropertySheet2
/*+-------------------------------------------------------------------------*
*
* CHTMLSnapinData::CreatePropertyPages
*
* PURPOSE:
*
* PARAMETERS:
* LPPROPERTYSHEETCALLBACK lpProvider :
* LONG_PTR handle :
* LPDATAOBJECT lpIDataObject :
*
* RETURNS:
* STDMETHODIMP
*
*+-------------------------------------------------------------------------*/
STDMETHODIMP
CHTMLSnapinData::CreatePropertyPages(LPPROPERTYSHEETCALLBACK lpProvider, LONG_PTR handle, LPDATAOBJECT lpIDataObject)
{
HPROPSHEETPAGE hPage;
ASSERT(lpProvider != NULL);
if(lpProvider == NULL)
{
//TraceError(TEXT("CHTMLSnapinData::CreatePropertyPages"));
return E_UNEXPECTED;
}
ASSERT(m_pHtmlPage1 == NULL);
ASSERT(m_pHtmlPage2 == NULL);
// create property pages
m_pHtmlPage1 = new CHTMLPage1;
m_pHtmlPage2 = new CHTMLPage2;
// pass in pointer to data structure
m_pHtmlPage1->Initialize(this);
m_pHtmlPage2->Initialize(this);
// Add Pages to property sheet
hPage=CreatePropertySheetPage(&m_pHtmlPage1->m_psp);
lpProvider->AddPage(hPage);
hPage=CreatePropertySheetPage(&m_pHtmlPage2->m_psp);
lpProvider->AddPage(hPage);
return S_OK;
}
//############################################################################
//############################################################################
//
// Implementation of class CHTMLSnapinComponent
//
//############################################################################
//############################################################################
/*+-------------------------------------------------------------------------*
*
* CHTMLSnapinComponent::ScOnSelect
*
* PURPOSE: Handles the MMCN_SELECT notification. Enables the Refresh verb,
* which uses the default MMC handler to refresh the page.
*
* PARAMETERS:
* BOOL bScope :
* BOOL bSelect :
*
* RETURNS:
* SC
*
*+-------------------------------------------------------------------------*/
SC
CHTMLSnapinComponent::ScOnSelect(BOOL bScope, BOOL bSelect)
{
DECLARE_SC(sc, TEXT("CHTMLSnapinComponent::ScOnSelect"));
// call the base class method
sc = BC::ScOnSelect(bScope, bSelect);
if(sc)
return sc;
IConsoleVerbPtr spConsoleVerb;
sc = ScCheckPointers(m_spConsole2, E_UNEXPECTED);
if(sc)
return sc;
sc = m_spConsole2->QueryConsoleVerb(&spConsoleVerb);
if(sc)
return sc;
sc = ScCheckPointers(spConsoleVerb, E_UNEXPECTED);
if(sc)
return sc;
// enable the Refresh verb - the default MMC handler is adequate to refresh the page.
sc = spConsoleVerb->SetVerbState(MMC_VERB_REFRESH, ENABLED, (bSelect && bScope));
if(sc)
return sc;
//NOTE: (vivekj): I'm intentionally not setting the HIDDEN state to false here, because
// we have an explicit test in our verb code for MMC1.0 snapins that wrote code like this,
// and this provides a useful compatibility test.
return sc;
}
/*+-------------------------------------------------------------------------*
*
* CHTMLSnapinComponent::GetResultViewType
*
* PURPOSE: Performs parameter substitution on the URL for the environment variables
* %windir% and %systemroot% (only) and returns the expanded URL.
*
* NOTE: We don't expand ALL variables using ExpandEnvironmentString. Doing so could
* break compatibility with URL's that have %var% but DON'T want to be
* expanded.
*
* PARAMETERS:
* MMC_COOKIE cookie :
* LPOLESTR* ppViewType :
* long* pViewOptions :
*
* RETURNS:
* STDMETHODIMP
*
*+-------------------------------------------------------------------------*/
STDMETHODIMP
CHTMLSnapinComponent::GetResultViewType(MMC_COOKIE cookie, LPOLESTR* ppViewType, long* pViewOptions)
{
DECLARE_SC(sc, TEXT("CHTMLSnapinComponent::GetResultViewType"));
// check parameters
if(!ppViewType || !pViewOptions)
return (sc = E_UNEXPECTED).ToHr();
if(!GetComponentData())
return (sc = E_UNEXPECTED).ToHr();
// add support for expanding the environment variables %WINDIR% and %SYSTEMROOT% to maintain compatibility with MMC1.2
CStr strTarget = GetComponentData()->GetView();
CStr strRet = strTarget; // the return value
CStr strTemp = strTarget; // both initialized to the same value.
strTemp.MakeLower(); // NOTE: this lowercase conversion is used only for comparison. The original case is preserved in the output.
// Find out if %windir% or %systemroot% is in the target string
int nWndDir = strTemp.Find(MMC_WINDIR_VARIABLE_PERC);
int nSysDir = strTemp.Find(MMC_SYSTEMROOT_VARIABLE_PERC);
if (nWndDir != -1 || nSysDir != -1)
{
const UINT BUFFERLEN = 4096;
// Get start pos and length of replacement string
int nStpos = (nWndDir != -1) ? nWndDir : nSysDir;
int nLen = (nWndDir != -1) ? _tcslen(MMC_WINDIR_VARIABLE_PERC) : _tcslen(MMC_SYSTEMROOT_VARIABLE_PERC);
// Setup temp variable to hold BUFFERLEN chars
CStr strRoot;
LPTSTR lpsz = strRoot.GetBuffer(BUFFERLEN);
if (lpsz != NULL)
{
int iReturn = -1;
if (nWndDir != -1)
iReturn = GetWindowsDirectory(lpsz, BUFFERLEN);
else
iReturn = GetEnvironmentVariable(MMC_SYSTEMROOT_VARIABLE, lpsz, BUFFERLEN);
// release string buffer
strRoot.ReleaseBuffer();
// Build up new target string based on environemnt variable.
if (iReturn != 0)
{
strRet = strTarget.Left(nStpos);
strRet += strRoot;
strRet += strTarget.Mid(nStpos + nLen, strTarget.GetLength() - (nStpos + nLen));
}
}
}
USES_CONVERSION;
*ppViewType = (LPOLESTR)CoTaskMemAlloc( (_tcslen(strRet)+1) * sizeof(OLECHAR) );
*pViewOptions = GetComponentData()->GetDescriptor().GetViewOptions();
wcscpy(*ppViewType, T2COLE(strRet));
return sc.ToHr();
}
//############################################################################
//############################################################################
//
// Implementation of class COCXSnapinData
//
//############################################################################
//############################################################################
STDMETHODIMP
COCXSnapinData::CreateComponent(LPCOMPONENT* ppComponent)
{
typedef CComObject<COCXSnapinComponent> CComponent;
CComponent * pComponent = NULL;
CComObject<COCXSnapinComponent>::CreateInstance(&pComponent);
ASSERT(pComponent != NULL);
if(pComponent == NULL)
{
//TraceError(TEXT("COCXSnapinData::CreateComponent"));
return E_UNEXPECTED;
}
pComponent->Init(this);
return pComponent->QueryInterface(IID_IComponent, (void **)ppComponent); // does the Addref.
}
COCXSnapinData::COCXSnapinData()
{
m_pActiveXPage0 = NULL;
m_pActiveXPage1 = NULL;
m_pActiveXPage2 = NULL;
m_iImage = eStockImage_OCX;
m_iOpenImage = eStockImage_OCX;
}
COCXSnapinData::~COCXSnapinData()
{
}
STDMETHODIMP
COCXSnapinData::Destroy()
{
if(m_pActiveXPage0 != NULL)
{
delete m_pActiveXPage0;
m_pActiveXPage0 = NULL;
}
if(m_pActiveXPage1 != NULL)
{
delete m_pActiveXPage1;
m_pActiveXPage1 = NULL;
}
if(m_pActiveXPage2 != NULL)
{
delete m_pActiveXPage2;
m_pActiveXPage2 = NULL;
}
return BC::Destroy();
}
const CLSID CLSID_OCXSnapin = {0xC96401CF, 0x0E17,0x11D3, {0x88,0x5B,0x00,0xC0,0x4F,0x72,0xC7,0x17}};
static const GUID GUID_OCXSnapinNodetype = {0xc96401d0, 0xe17, 0x11d3, { 0x88, 0x5b, 0x0, 0xc0, 0x4f, 0x72, 0xc7, 0x17 } };
static LPCTSTR szClsid_OCXSnapin = TEXT("{C96401CF-0E17-11D3-885B-00C04F72C717}");
static LPCTSTR szGuidOCXSnapinNodetype = TEXT("{C96401D0-0E17-11D3-885B-00C04F72C717}");
CSnapinDescriptor &
COCXSnapinData::GetSnapinDescriptor()
{
static CSnapinDescriptor snapinDescription(IDS_ACTIVEXCONTROL,
IDS_OCXSNAPIN_DESC, IDI_OCX, IDB_OCX_16, IDB_OCX_16, IDB_OCX_32,
CLSID_OCXSnapin, szClsid_OCXSnapin, GUID_OCXSnapinNodetype,
szGuidOCXSnapinNodetype, TEXT("OCX"), TEXT("Snapins.OCXSnapin"),
TEXT("Snapins.OCXSnapin.1"), MMC_VIEW_OPTIONS_NOLISTVIEWS /*viewOptions*/ );
return snapinDescription;
}
// IExtendPropertySheet2
STDMETHODIMP
COCXSnapinData::CreatePropertyPages(LPPROPERTYSHEETCALLBACK lpProvider, LONG_PTR handle, LPDATAOBJECT lpIDataObject)
{
HPROPSHEETPAGE hPage;
ASSERT(lpProvider != NULL);
if(lpProvider == NULL)
{
//TraceError(TEXT("CHTMLSnapinData::CreatePropertyPages"));
return E_UNEXPECTED;
}
ASSERT(m_pActiveXPage0 == NULL);
ASSERT(m_pActiveXPage1 == NULL);
ASSERT(m_pActiveXPage2 == NULL);
// create property pages
m_pActiveXPage0 = new CActiveXPage0;
m_pActiveXPage1 = new CActiveXPage1;
m_pActiveXPage2 = new CActiveXPage2;
// pass in pointer to data structure
m_pActiveXPage0->Initialize(this);
m_pActiveXPage1->Initialize(this);
m_pActiveXPage2->Initialize(this);
// Add Pages to property sheet
hPage=CreatePropertySheetPage(&m_pActiveXPage0->m_psp);
lpProvider->AddPage(hPage);
hPage=CreatePropertySheetPage(&m_pActiveXPage1->m_psp);
lpProvider->AddPage(hPage);
hPage=CreatePropertySheetPage(&m_pActiveXPage2->m_psp);
lpProvider->AddPage(hPage);
return S_OK;
}
//############################################################################
//############################################################################
//
// Implementation of class COCXSnapinComponent
//
//############################################################################
//############################################################################
/*+-------------------------------------------------------------------------*
*
* COCXSnapinComponent::Notify
*
* PURPOSE: Implements the CComponent::Notify method
*
* PARAMETERS:
* LPDATAOBJECT lpDataObject :
* MMC_NOTIFY_TYPE event :
* LPARAM arg :
* LPARAM param :
*
* RETURNS:
* HRESULT
*
*+-------------------------------------------------------------------------*/
HRESULT
COCXSnapinComponent::Notify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param)
{
HRESULT hr = S_OK;
switch(event)
{
// Handle just the OCX initialization notify
case MMCN_INITOCX:
return OnInitOCX(lpDataObject, arg, param);
break;
default:
// Pass other notifications on to base class
return CSnapinComponentImpl::Notify(lpDataObject, event, arg, param);
break;
}
return hr;
}
/*+-------------------------------------------------------------------------*
*
* COCXSnapinComponent::OnInitOCX
*
* PURPOSE: Handles the MMCN_INITOCX message.
*
* PARAMETERS:
* LPDATAOBJECT lpDataObject :
* LPARAM arg :
* LPARAM param :
*
* RETURNS:
* HRESULT
*
*+-------------------------------------------------------------------------*/
HRESULT
COCXSnapinComponent::OnInitOCX(LPDATAOBJECT lpDataObject, LPARAM arg, LPARAM param)
{
HRESULT hr = S_OK;
ASSERT(param != NULL);
IUnknown* pUnknown = reinterpret_cast<IUnknown*>(param);
ASSERT(m_bLoaded || m_bInitialized);
// Load or initialze the OCX
if (m_bLoaded || m_bInitialized)
{
IPersistStreamInitPtr spIPStmInit;
// Query for stream support
m_spIPStm = pUnknown;
// if none, try streamInit
if (m_spIPStm == NULL)
{
spIPStmInit = pUnknown;
// if streamInit found, cast to normal stream pointer
// so common methods can be called from single pointer
if (spIPStmInit != NULL)
m_spIPStm = (IPersistStream*)spIPStmInit.GetInterfacePtr();
}
// if either type of stream persistance supported
if (m_spIPStm != NULL)
{
// if load method was called, then ask OCX to load from inner stream
// Note that inner stream will not exist if OCX was never created
if (m_bLoaded)
{
IStreamPtr spStm;
HRESULT hr2 = m_spStg->OpenStream(SZ_OCXSTREAM, NULL, STGM_READ|STGM_SHARE_EXCLUSIVE, NULL, &spStm);
if (SUCCEEDED(hr2))
hr = m_spIPStm->Load(spStm);
else
m_bLoaded = FALSE;
}
// if no load was done and OCX requires an InitNew, give it one now
if (!m_bLoaded && spIPStmInit != NULL)
hr = spIPStmInit->InitNew();
}
else
{
// Query for storage support
m_spIPStg = pUnknown;
// if storage supported, ask OCX to load from inner storage
// Note that inner storage will not exist if OCX was never created
if (m_spIPStg != NULL)
{
if (m_bLoaded)
{
ASSERT(m_spStgInner == NULL);
HRESULT hr2 = m_spStg->OpenStorage(SZ_OCXSTORAGE, NULL, STGM_READWRITE|STGM_SHARE_EXCLUSIVE,
NULL, NULL, &m_spStgInner);
if (SUCCEEDED(hr2))
hr = m_spIPStg->Load(m_spStgInner);
else
m_bLoaded = FALSE;
}
// if no load done, create an inner storage and init from it
if (!m_bLoaded)
{
ASSERT(m_spStgInner == NULL);
hr = m_spStg->CreateStorage(SZ_OCXSTORAGE, STGM_READWRITE|STGM_SHARE_EXCLUSIVE, NULL,
NULL, &m_spStgInner);
if (SUCCEEDED(hr))
hr = m_spIPStg->InitNew(m_spStgInner);
}
}
}
}
return hr;
}
STDMETHODIMP COCXSnapinComponent::InitNew(IStorage* pStg)
{
if (pStg == NULL)
return E_POINTER;
if (m_bInitialized)
return CO_E_ALREADYINITIALIZED;
// Hold onto storage
m_spStg = pStg;
m_bInitialized = TRUE;
return S_OK;
}
HRESULT COCXSnapinComponent::Load(IStorage* pStg)
{
if (pStg == NULL)
return E_POINTER;
if (m_bInitialized)
return CO_E_ALREADYINITIALIZED;
// Hold onto storage
m_spStg = pStg;
m_bLoaded = TRUE;
m_bInitialized = TRUE;
return S_OK;
}
HRESULT COCXSnapinComponent::IsDirty()
{
HRESULT hr = S_FALSE;
if (m_spIPStm != NULL)
{
hr = m_spIPStm->IsDirty();
}
else if (m_spIPStg != NULL)
{
hr = m_spIPStg->IsDirty();
}
return hr;
}
HRESULT COCXSnapinComponent::Save(IStorage* pStg, BOOL fSameAsLoad)
{
DECLARE_SC(sc, TEXT("COCXSnapinComponent::Save"));
// parameter check
sc = ScCheckPointers( pStg );
if (sc)
return sc.ToHr();
// to be able to save we need to be initialized
sc = ScCheckPointers( m_spStg, E_UNEXPECTED );
if (sc)
return sc.ToHr();
// if need to use the new storage - make a copy
if (!fSameAsLoad)
{
sc = m_spStg->CopyTo(0, NULL, NULL, pStg);
if (sc)
return sc.ToHr();
// release cached storage (in case we have it) - it must change
m_spStgInner = NULL;
// hold onto the new storage
m_spStg = pStg;
// assignment uses QI - recheck!
sc = ScCheckPointers( m_spStg, E_UNEXPECTED );
if (sc)
return sc.ToHr();
}
// if storage support, ask OCX to save to inner storage
if (m_spIPStg)
{
bool bSameStorageForSnapin = true;
// if saving to different storage, create new inner storage on it and pass to OCX
if ( m_spStgInner == NULL )
{
sc = pStg->CreateStorage(SZ_OCXSTORAGE, STGM_CREATE|STGM_WRITE|STGM_SHARE_EXCLUSIVE, NULL, NULL, &m_spStgInner);
if (sc)
return sc.ToHr();
bSameStorageForSnapin = false;
}
// recheck the pointer
sc = ScCheckPointers( m_spStgInner, E_UNEXPECTED );
if (sc)
return sc.ToHr();
// save to the storage
sc = m_spIPStg->Save( m_spStgInner, (fSameAsLoad && bSameStorageForSnapin) );
if (sc)
return sc.ToHr();
}
// else if stream support, create/open stream and save to it
else if (m_spIPStm)
{
// if stream support, create internal stream and pass to OCX
IStreamPtr spStm;
sc = m_spStg->CreateStream(SZ_OCXSTREAM, STGM_CREATE|STGM_WRITE|STGM_SHARE_EXCLUSIVE, NULL, NULL, &spStm);
if (sc)
return sc.ToHr();
sc = m_spIPStm->Save(spStm, TRUE);
if (sc)
return sc.ToHr();
}
else
{
// we are here if the OCX was never created (i.e., this component never owned the result pane)
// if node was loaded and has to save to a new file, just copy the current storage to the new one
}
return sc.ToHr();
}
HRESULT COCXSnapinComponent::HandsOffStorage()
{
// Release storage if holding ref
// if ocx is holding storage, forward call to it
if (m_spIPStg != NULL && m_spStgInner != NULL)
m_spIPStg->HandsOffStorage();
// Free our own refs
m_spStgInner = NULL;
m_spStg = NULL;
return S_OK;
}
HRESULT COCXSnapinComponent::SaveCompleted(IStorage* pStgNew)
{
HRESULT hr = S_OK;
if (m_spIPStg != NULL)
{
// if new storage provided
if (pStgNew != NULL && pStgNew != m_spStg)
{
// Create new inner storage and give to OCX
IStoragePtr spStgInner;
hr = pStgNew->CreateStorage(SZ_OCXSTORAGE, STGM_CREATE|STGM_WRITE|STGM_SHARE_EXCLUSIVE, NULL, NULL, &spStgInner);
if (SUCCEEDED(hr))
hr = m_spIPStg->SaveCompleted(spStgInner);
// Free current inner storage and hold onto new one
m_spStgInner = spStgInner;
}
else
{
m_spIPStg->SaveCompleted(NULL);
}
}
if (pStgNew != NULL)
m_spStg = pStgNew;
return hr;
}
HRESULT COCXSnapinComponent::GetClassID(CLSID *pClassID)
{
return E_NOTIMPL;
}