|
|
/*--------------------------------------------------------------------------*
* * 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; }
|