Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2103 lines
58 KiB

// This is a part of the Active Template Library.
// Copyright (C) Microsoft Corporation, 1996 - 1999
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Active Template Library Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Active Template Library product.
#ifndef __ATL_SNAPIN_H__
#define __ATL_SNAPIN_H__
#include <mmc.h>
#include <commctrl.h>
#pragma comment(lib, "mmc.lib")
#pragma comment(lib, "comctl32.lib")
// MAM things which haven't made it into real atlsnap.h yet.
#define TASKPAD_SUPPORT
#define FIX_PROBLEM_WITH_PROPERTY_CHANGE_NOTIFICATION_HANDLES
#define FIX_PROBLEM_WITH_DYNAMIC_CAST_ON_CSNAPINOBJECTROOT_NOT_WORKING
#define FIX_PROBLEM_WITH_GET_RESULT_VIEW_TYPE_NULL_COOKIE
template <class T, bool bAutoDelete = TRUE>
class ATL_NO_VTABLE CSnapInPropertyPageImpl : public CDialogImplBase
{
public:
PROPSHEETPAGE m_psp;
#ifdef FIX_PROBLEM_WITH_PROPERTY_CHANGE_NOTIFICATION_HANDLES
LONG_PTR m_hNotificationHandle;
BOOL m_bOwnsNotificationHandle;
#endif FIX_PROBLEM_WITH_PROPERTY_CHANGE_NOTIFICATION_HANDLES
operator PROPSHEETPAGE*() { return &m_psp; }
// Construction
#ifdef FIX_PROBLEM_WITH_PROPERTY_CHANGE_NOTIFICATION_HANDLES
CSnapInPropertyPageImpl(LONG_PTR hNotificationHandle, LPCTSTR lpszTitle = NULL, BOOL bOwnsNotificationHandle = FALSE)
#else
CSnapInPropertyPageImpl(LPCTSTR lpszTitle = NULL)
#endif // FIX_PROBLEM_WITH_PROPERTY_CHANGE_NOTIFICATION_HANDLES
{
// initialize PROPSHEETPAGE struct
memset(&m_psp, 0, sizeof(PROPSHEETPAGE));
m_psp.dwSize = sizeof(PROPSHEETPAGE);
m_psp.dwFlags = PSP_USECALLBACK;
m_psp.hInstance = _Module.GetResourceInstance();
m_psp.pszTemplate = MAKEINTRESOURCE(T::IDD);
m_psp.pfnDlgProc = T::StartDialogProc;
m_psp.pfnCallback = T::PropPageCallback;
m_psp.lParam = (LPARAM)this;
if(lpszTitle != NULL)
{
m_psp.pszTitle = lpszTitle;
m_psp.dwFlags |= PSP_USETITLE;
}
#ifdef FIX_PROBLEM_WITH_PROPERTY_CHANGE_NOTIFICATION_HANDLES
m_hNotificationHandle = hNotificationHandle;
m_bOwnsNotificationHandle = bOwnsNotificationHandle;
#endif //FIX_PROBLEM_WITH_PROPERTY_CHANGE_NOTIFICATION_HANDLES
}
void SetTitles(LPCWSTR szTitle, LPCWSTR szSubtitle)
{
m_psp.dwFlags |= PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
m_psp.pszHeaderTitle = szTitle;
m_psp.pszHeaderSubTitle = szSubtitle;
};
#ifdef FIX_PROBLEM_WITH_PROPERTY_CHANGE_NOTIFICATION_HANDLES
~CSnapInPropertyPageImpl()
{
if( m_bOwnsNotificationHandle )
{
// The MMC docs specify that this handle should only be freed once.
// For this reason, we have the bOwnsNotificationHandle flag which
// should only be set for one property page.
// We only free the handle in the destructor of the page
// that has been designated as the "owner".
MMCFreeNotifyHandle( m_hNotificationHandle );
}
}
HRESULT PropertyChangeNotify( LPARAM param )
{
return MMCPropertyChangeNotify( m_hNotificationHandle, param );
}
#endif //FIX_PROBLEM_WITH_PROPERTY_CHANGE_NOTIFICATION_HANDLES
static UINT CALLBACK PropPageCallback(HWND hWnd, UINT uMsg, LPPROPSHEETPAGE ppsp)
{
ATLASSERT(hWnd == NULL);
if(uMsg == PSPCB_CREATE)
{
CDialogImplBase* pPage = (CDialogImplBase*)ppsp->lParam;
_Module.AddCreateWndData(&pPage->m_thunk.cd, pPage);
}
if (bAutoDelete && uMsg == PSPCB_RELEASE)
{
T* pPage = (T*)ppsp->lParam;
delete pPage;
}
return 1;
}
HPROPSHEETPAGE Create()
{
return ::CreatePropertySheetPage(&m_psp);
}
BOOL EndDialog(int)
{
// do nothing here, calling ::EndDialog will close the whole sheet
ATLASSERT(FALSE);
return FALSE;
}
// Operations
void CancelToClose()
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(GetParent() != NULL);
::SendMessage(GetParent(), PSM_CANCELTOCLOSE, 0, 0L);
}
void SetModified(BOOL bChanged = TRUE)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(GetParent() != NULL);
if(bChanged)
::SendMessage(GetParent(), PSM_CHANGED, (WPARAM)m_hWnd, 0L);
else
::SendMessage(GetParent(), PSM_UNCHANGED, (WPARAM)m_hWnd, 0L);
}
LRESULT QuerySiblings(WPARAM wParam, LPARAM lParam)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(GetParent() != NULL);
return ::SendMessage(GetParent(), PSM_QUERYSIBLINGS, wParam, lParam);
}
BEGIN_MSG_MAP(CSnapInPropertyPageImpl< T >)
MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
END_MSG_MAP()
// Message handler
LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
ATLASSERT(::IsWindow(m_hWnd));
NMHDR* pNMHDR = (NMHDR*)lParam;
// don't handle messages not from the page/sheet itself
if(pNMHDR->hwndFrom != m_hWnd && pNMHDR->hwndFrom != ::GetParent(m_hWnd))
{
bHandled = FALSE;
return 1;
}
T* pT = (T*)this;
LRESULT lResult = 0;
// handle default
switch(pNMHDR->code)
{
case PSN_SETACTIVE:
lResult = pT->OnSetActive() ? 0 : -1;
break;
case PSN_KILLACTIVE:
lResult = !pT->OnKillActive();
break;
case PSN_APPLY:
lResult = pT->OnApply() ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE;
break;
case PSN_RESET:
pT->OnReset();
break;
case PSN_QUERYCANCEL:
lResult = !pT->OnQueryCancel();
break;
case PSN_WIZNEXT:
// changed, since the orginal one doesn't work when jump to a different page
{
LRESULT l = pT->OnWizardNext();
switch(l)
{
case TRUE:
lResult = 0;
break;
case FALSE:
lResult = -1;
break;
default:
lResult = l;
break;
}
}
break;
case PSN_WIZBACK:
// changed, since the orginal one doesn't work when jump to a different page
{
LRESULT l = pT->OnWizardBack();
switch(l)
{
case TRUE:
lResult = 0;
break;
case FALSE:
lResult = -1;
break;
default:
lResult = l;
break;
}
}
break;
case PSN_WIZFINISH:
lResult = !pT->OnWizardFinish();
break;
case PSN_HELP:
lResult = pT->OnHelp();
break;
default:
bHandled = FALSE; // not handled
}
return lResult;
}
// Overridables
BOOL OnSetActive()
{
return TRUE;
}
BOOL OnKillActive()
{
return TRUE;
}
BOOL OnApply()
{
return TRUE;
}
void OnReset()
{
}
BOOL OnQueryCancel()
{
return TRUE; // ok to cancel
}
BOOL OnWizardBack()
{
return TRUE;
}
BOOL OnWizardNext()
{
return TRUE;
}
BOOL OnWizardFinish()
{
return TRUE;
}
BOOL OnHelp()
{
return TRUE;
}
};
#if _ATL_VER < 0x0300
// intended for small number of simple types or pointers
template <class TKey, class TVal>
class CSimpleMap
{
public:
TKey* m_aKey;
TVal* m_aVal;
int m_nSize;
// Construction/destruction
CSimpleMap() : m_aKey(NULL), m_aVal(NULL), m_nSize(0)
{ }
~CSimpleMap()
{
RemoveAll();
}
// Operations
int GetSize() const
{
return m_nSize;
}
BOOL Add(TKey key, TVal val)
{
TKey* pKey;
pKey = (TKey*)realloc(m_aKey, (m_nSize + 1) * sizeof(TKey));
if(pKey == NULL)
return FALSE;
m_aKey = pKey;
TVal* pVal;
pVal = (TVal*)realloc(m_aVal, (m_nSize + 1) * sizeof(TVal));
if(pVal == NULL)
return FALSE;
m_aVal = pVal;
m_nSize++;
SetAtIndex(m_nSize - 1, key, val);
return TRUE;
}
BOOL Remove(TKey key)
{
int nIndex = FindKey(key);
if(nIndex == -1)
return FALSE;
if(nIndex != (m_nSize - 1))
{
memmove((void*)&m_aKey[nIndex], (void*)&m_aKey[nIndex + 1], (m_nSize - (nIndex + 1)) * sizeof(TKey));
memmove((void*)&m_aVal[nIndex], (void*)&m_aVal[nIndex + 1], (m_nSize - (nIndex + 1)) * sizeof(TVal));
}
TKey* pKey;
pKey = (TKey*)realloc(m_aKey, (m_nSize - 1) * sizeof(TKey));
if(pKey != NULL || m_nSize == 1)
m_aKey = pKey;
TVal* pVal;
pVal = (TVal*)realloc(m_aVal, (m_nSize - 1) * sizeof(TVal));
if(pVal != NULL || m_nSize == 1)
m_aVal = pVal;
m_nSize--;
return TRUE;
}
void RemoveAll()
{
if(m_nSize > 0)
{
free(m_aKey);
free(m_aVal);
m_aKey = NULL;
m_aVal = NULL;
m_nSize = 0;
}
}
BOOL SetAt(TKey key, TVal val)
{
int nIndex = FindKey(key);
if(nIndex == -1)
return FALSE;
SetAtIndex(nIndex, key, val);
return TRUE;
}
TVal Lookup(TKey key) const
{
int nIndex = FindKey(key);
if(nIndex == -1)
return NULL; // must be able to convert
return GetValueAt(nIndex);
}
TKey ReverseLookup(TVal val) const
{
int nIndex = FindVal(val);
if(nIndex == -1)
return NULL; // must be able to convert
return GetKeyAt(nIndex);
}
TKey& GetKeyAt(int nIndex) const
{
ATLASSERT(nIndex >= 0 && nIndex < m_nSize);
return m_aKey[nIndex];
}
TVal& GetValueAt(int nIndex) const
{
ATLASSERT(nIndex >= 0 && nIndex < m_nSize);
return m_aVal[nIndex];
}
// Implementation
void SetAtIndex(int nIndex, TKey& key, TVal& val)
{
ATLASSERT(nIndex >= 0 && nIndex < m_nSize);
m_aKey[nIndex] = key;
m_aVal[nIndex] = val;
}
int FindKey(TKey& key) const
{
for(int i = 0; i < m_nSize; i++)
{
if(m_aKey[i] == key)
return i;
}
return -1; // not found
}
int FindVal(TVal& val) const
{
for(int i = 0; i < m_nSize; i++)
{
if(m_aVal[i] == val)
return i;
}
return -1; // not found
}
};
#endif
class CSnapInItem;
class CSnapInObjectRootBase;
class CObjectData
{
public:
CSnapInItem* m_pItem;
DATA_OBJECT_TYPES m_type;
};
class ATL_NO_VTABLE CSnapInItem
{
public:
CSnapInItem(unsigned int helpIndex = 0)
:m_helpIndex(helpIndex)
{
}
virtual ~CSnapInItem()
{
}
STDMETHOD(Notify)(MMC_NOTIFY_TYPE event,
LPARAM arg,
LPARAM param,
IComponentData* pComponentData,
IComponent* pComponent,
DATA_OBJECT_TYPES type) = 0;
STDMETHOD(GetScopePaneInfo)(SCOPEDATAITEM *pScopeDataItem) = 0;
STDMETHOD(GetResultViewType)(LPOLESTR *ppViewType,
long *pViewOptions) = 0;
STDMETHOD(GetResultPaneInfo)(RESULTDATAITEM *pResultDataItem) = 0;
STDMETHOD(AddMenuItems)(LPCONTEXTMENUCALLBACK piCallback,
long *pInsertionAllowed,
DATA_OBJECT_TYPES type) = 0;
STDMETHOD(Command)(long lCommandID,
CSnapInObjectRootBase* pObj,
DATA_OBJECT_TYPES type) = 0;
STDMETHOD(CreatePropertyPages)(LPPROPERTYSHEETCALLBACK lpProvider,
LONG_PTR handle,
IUnknown* pUnk,
DATA_OBJECT_TYPES type) = 0;
STDMETHOD(QueryPagesFor)(DATA_OBJECT_TYPES type) = 0;
STDMETHOD(SetControlbar)(IControlbar *pControlbar,
IExtendControlbar *pExtendControlbar,
CSimpleMap<UINT, IUnknown*>* pToolbarMap) = 0;
STDMETHOD(ControlbarNotify)(IControlbar *pControlbar,
IExtendControlbar *pExtendControlbar,
CSimpleMap<UINT, IUnknown*>* pToolbarMap,
MMC_NOTIFY_TYPE event,
LPARAM arg,
LPARAM param,
CSnapInObjectRootBase* pObj,
DATA_OBJECT_TYPES type) = 0;
STDMETHOD(GetScopeData)(SCOPEDATAITEM * *pScopeDataItem) = 0;
STDMETHOD(GetResultData)(RESULTDATAITEM * *pResultDataItem) = 0;
STDMETHOD(FillData)(CLIPFORMAT cf,
LPSTREAM pStream) = 0;
virtual void InitDataClass(IDataObject* pDataObject, CSnapInItem* pDefault)
{
_ASSERTE(0 && "Override this function in derived class");
}
static HRESULT GetDataClass(IDataObject* pDataObj, CSnapInItem** ppItem, DATA_OBJECT_TYPES* pType)
{
if (ppItem == NULL)
return E_POINTER;
if (pType == NULL)
return E_POINTER;
if (IS_SPECIAL_DATAOBJECT(pDataObj))
return E_NOTIMPL;
*ppItem = NULL;
*pType = CCT_UNINITIALIZED;
STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL };
FORMATETC formatetc = { m_CCF_SNAPIN_GETOBJECTDATA,
NULL,
DVASPECT_CONTENT,
-1,
TYMED_HGLOBAL
};
stgmedium.hGlobal = GlobalAlloc(0, sizeof(CObjectData));
if (stgmedium.hGlobal == NULL)
return E_OUTOFMEMORY;
HRESULT hr = pDataObj->GetDataHere(&formatetc, &stgmedium);
if (SUCCEEDED(hr))
{
CObjectData* pData = (CObjectData*)stgmedium.hGlobal;
*ppItem = pData->m_pItem;
*pType = pData->m_type;
}
GlobalFree(stgmedium.hGlobal);
return hr;
}
#ifdef TASKPAD_SUPPORT
STDMETHOD(TaskNotify)(
IDataObject * pDataObject
, VARIANT * pvarg
, VARIANT * pvparam
) = 0;
STDMETHOD(EnumTasks)(
IDataObject * pDataObject
, BSTR szTaskGroup
, IEnumTASK** ppEnumTASK
) = 0;
#endif // TASKPAD_SUPPORT
virtual HRESULT STDMETHODCALLTYPE GetDataObject(IDataObject** pDataObj, DATA_OBJECT_TYPES type) = 0;
static void Init()
{
m_CCF_NODETYPE = (CLIPFORMAT) RegisterClipboardFormat(_T("CCF_NODETYPE"));
m_CCF_SZNODETYPE = (CLIPFORMAT) RegisterClipboardFormat(_T("CCF_SZNODETYPE"));
m_CCF_DISPLAY_NAME = (CLIPFORMAT) RegisterClipboardFormat(_T("CCF_DISPLAY_NAME"));
m_CCF_SNAPIN_CLASSID = (CLIPFORMAT) RegisterClipboardFormat(_T("CCF_SNAPIN_CLASSID"));
m_CCF_SNAPIN_GETOBJECTDATA = (CLIPFORMAT) RegisterClipboardFormat(_T("CCF_GETOBJECTDATA"));
m_CCF_MMC_MULTISELECT_DATAOBJECT = (CLIPFORMAT) RegisterClipboardFormat(_T("CCF_MMC_MULTISELECT_DATAOBJECT"));
}
public:
static CLIPFORMAT m_CCF_NODETYPE;
static CLIPFORMAT m_CCF_SZNODETYPE;
static CLIPFORMAT m_CCF_DISPLAY_NAME;
static CLIPFORMAT m_CCF_SNAPIN_CLASSID;
static CLIPFORMAT m_CCF_SNAPIN_GETOBJECTDATA;
static CLIPFORMAT m_CCF_MMC_MULTISELECT_DATAOBJECT;
// IAS: Added to store some information about which help file to use
unsigned int m_helpIndex;
};
class CSnapInObjectRootBase
{
public:
CComPtr <IControlbar> m_spControlbar;
CSimpleMap <UINT, IUnknown*> m_toolbarMap;
const int m_ntype;
CSnapInObjectRootBase(int n = 0) : m_ntype(n)
{
}
HRESULT GetDataClass(IDataObject* pDataObject, CSnapInItem** ppItem, DATA_OBJECT_TYPES* pType)
{
return CSnapInItem::GetDataClass(pDataObject, ppItem, pType);
}
#ifdef FIX_PROBLEM_WITH_DYNAMIC_CAST_ON_CSNAPINOBJECTROOT_NOT_WORKING
// Need at least one virtual method, or compiler does not generate a vtable
virtual ~CSnapInObjectRootBase()
{
}
#endif FIX_PROBLEM_WITH_DYNAMIC_CAST_ON_CSNAPINOBJECTROOT_NOT_WORKING
};
template <int n, class ComponentData>
class CSnapInObjectRoot : public CSnapInObjectRootBase
{
public :
CSnapInObjectRoot() : CSnapInObjectRootBase(n)
{
m_pComponentData = NULL;
}
ComponentData* m_pComponentData;
};
#define EXTENSION_SNAPIN_DATACLASS(dataClass) dataClass m_##dataClass;
#define BEGIN_EXTENSION_SNAPIN_NODEINFO_MAP(classname) \
HRESULT GetDataClass(IDataObject* pDataObject, CSnapInItem** ppItem, DATA_OBJECT_TYPES* pType) \
{ \
if (ppItem == NULL) \
return E_POINTER; \
if (pType == NULL) \
return E_POINTER; \
if (IS_SPECIAL_DATAOBJECT(pDataObject)) \
return E_NOTIMPL; \
\
*ppItem = NULL; \
\
*pType = CCT_UNINITIALIZED; \
\
STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL }; \
FORMATETC formatetc = { CSnapInItem::m_CCF_NODETYPE, \
NULL, \
DVASPECT_CONTENT, \
-1, \
TYMED_HGLOBAL \
}; \
\
stgmedium.hGlobal = GlobalAlloc(0, sizeof(GUID)); \
if (stgmedium.hGlobal == NULL) \
return E_OUTOFMEMORY; \
\
HRESULT hr = pDataObject->GetDataHere(&formatetc, &stgmedium); \
if (FAILED(hr)) \
{ \
GlobalFree(stgmedium.hGlobal); \
return hr; \
} \
\
GUID guid; \
memcpy(&guid, stgmedium.hGlobal, sizeof(GUID)); \
\
GlobalFree(stgmedium.hGlobal); \
hr = S_OK;
#define EXTENSION_SNAPIN_NODEINFO_ENTRY(dataClass) \
if (IsEqualGUID(guid, *(GUID*)m_##dataClass.GetNodeType())) \
{ \
*ppItem = m_##dataClass.GetExtNodeObject(pDataObject, &m_##dataClass); \
_ASSERTE(*ppItem != NULL); \
(*ppItem)->InitDataClass(pDataObject, &m_##dataClass); \
return hr; \
}
#define END_EXTENSION_SNAPIN_NODEINFO_MAP() \
return CSnapInItem::GetDataClass(pDataObject, ppItem, pType); \
};
class ATL_NO_VTABLE CSnapInDataObjectImpl : public IDataObject,
public CComObjectRoot
{
public:
BEGIN_COM_MAP(CSnapInDataObjectImpl)
COM_INTERFACE_ENTRY(IDataObject)
END_COM_MAP()
STDMETHOD(GetData)(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
{
ATLTRACENOTIMPL(_T("SnapInDataObjectImpl::GetData\n"));
}
STDMETHOD(GetDataHere)(FORMATETC* pformatetc, STGMEDIUM* pmedium)
{
ATLTRACE(_T("SnapInDataObjectImpl::GetDataHere\n"));
if (pmedium == NULL)
return E_POINTER;
HRESULT hr = DV_E_TYMED;
// Make sure the type medium is HGLOBAL
if (pmedium->tymed == TYMED_HGLOBAL)
{
// Create the stream on the hGlobal passed in
CComPtr<IStream> spStream;
hr = CreateStreamOnHGlobal(pmedium->hGlobal, FALSE, &spStream);
if (SUCCEEDED(hr))
if (pformatetc->cfFormat == CSnapInItem::m_CCF_SNAPIN_GETOBJECTDATA)
{
hr = DV_E_CLIPFORMAT;
ULONG uWritten;
hr = spStream->Write(&m_objectData, sizeof(CObjectData), &uWritten);
}
else
hr = m_objectData.m_pItem->FillData(pformatetc->cfFormat, spStream);
}
return hr;
}
STDMETHOD(QueryGetData)(FORMATETC* /* pformatetc */)
{
ATLTRACENOTIMPL(_T("SnapInDataObjectImpl::QueryGetData\n"));
}
STDMETHOD(GetCanonicalFormatEtc)(FORMATETC* /* pformatectIn */,FORMATETC* /* pformatetcOut */)
{
ATLTRACENOTIMPL(_T("SnapInDataObjectImpl::GetCanonicalFormatEtc\n"));
}
STDMETHOD(SetData)(FORMATETC* /* pformatetc */, STGMEDIUM* /* pmedium */, BOOL /* fRelease */)
{
ATLTRACENOTIMPL(_T("SnapInDataObjectImpl::SetData\n"));
}
STDMETHOD(EnumFormatEtc)(DWORD /* dwDirection */, IEnumFORMATETC** /* ppenumFormatEtc */)
{
ATLTRACENOTIMPL(_T("SnapInDataObjectImpl::EnumFormatEtc\n"));
}
STDMETHOD(DAdvise)(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink,
DWORD *pdwConnection)
{
ATLTRACENOTIMPL(_T("SnapInDataObjectImpl::SetData\n"));
}
STDMETHOD(DUnadvise)(DWORD dwConnection)
{
ATLTRACENOTIMPL(_T("SnapInDataObjectImpl::SetDatan\n"));
}
STDMETHOD(EnumDAdvise)(IEnumSTATDATA **ppenumAdvise)
{
ATLTRACENOTIMPL(_T("SnapInDataObjectImpl::SetData\n"));
}
CObjectData m_objectData;
};
template <class T, class Component>
class ATL_NO_VTABLE IComponentDataImpl : public IComponentData
{
public :
IComponentDataImpl()
{
m_pNode = NULL;
}
STDMETHOD(Initialize)(LPUNKNOWN pUnknown)
{
ATLTRACE(_T("IComponentDataImpl::Initialize\n"));
HRESULT hr = E_POINTER;
ATLASSERT(pUnknown != NULL);
if (pUnknown == NULL)
ATLTRACE(_T("IComponentData::Initialize called with pUnknown == NULL\n"));
else
{
hr = pUnknown->QueryInterface(IID_IConsole, (void**)&m_spConsole);
if (FAILED(hr))
ATLTRACE(_T("QI for IConsole failed\n"));
}
return hr;
}
STDMETHOD(CreateComponent)(LPCOMPONENT *ppComponent)
{
ATLTRACE(_T("IComponentDataImpl::CreateComponent\n"));
HRESULT hr = E_POINTER;
ATLASSERT(ppComponent != NULL);
if (ppComponent == NULL)
ATLTRACE(_T("IComponentData::CreateComponent called with ppComponent == NULL\n"));
else
{
*ppComponent = NULL;
CComObject< Component >* pComponent;
hr = CComObject< Component >::CreateInstance(&pComponent);
ATLASSERT(SUCCEEDED(hr));
if (FAILED(hr))
ATLTRACE(_T("IComponentData::CreateComponent : Could not create IComponent object\n"));
else
{
pComponent->m_pComponentData = static_cast<T*>(this);
hr = pComponent->QueryInterface(IID_IComponent, (void**)ppComponent);
}
}
return hr;
}
STDMETHOD(Notify)(
LPDATAOBJECT lpDataObject,
MMC_NOTIFY_TYPE event,
LPARAM arg,
LPARAM param)
{
ATLTRACE(_T("IComponentDataImpl::Notify\n"));
HRESULT hr = E_POINTER;
ATLASSERT(lpDataObject != NULL);
if (lpDataObject == NULL)
ATLTRACE(_T("IComponentData::Notify called with lpDataObject == NULL\n"));
else
{
T* pT = static_cast<T*>(this);
CSnapInItem* pItem;
DATA_OBJECT_TYPES type;
hr = pT->m_pComponentData->GetDataClass(lpDataObject, &pItem, &type);
ATLASSERT(SUCCEEDED(hr));
if (SUCCEEDED(hr))
hr = pItem->Notify(event, arg, param, pT, NULL, type);
}
return hr;
}
STDMETHOD(Destroy)(void)
{
ATLTRACE(_T("IComponentDataImpl::Destroy\n"));
T* pT = static_cast<T*>(this);
if (pT->m_spControlbar != NULL)
{
int n = pT->m_toolbarMap.GetSize();
for (int i = 0; i < n; i++)
{
IToolbar* pToolbar = (IToolbar*)pT->m_toolbarMap.GetValueAt(i);
if (pToolbar != NULL)
{
pT->m_spControlbar->Detach(pToolbar);
pToolbar->Release();
}
}
}
pT->m_toolbarMap.RemoveAll();
m_spConsole.Release();
return S_OK;
}
STDMETHOD(QueryDataObject)(MMC_COOKIE cookie,
DATA_OBJECT_TYPES type,
LPDATAOBJECT *ppDataObject)
{
ATLTRACE(_T("IComponentDataImpl::QueryDataObject\n"));
HRESULT hr = E_POINTER;
ATLASSERT(ppDataObject != NULL);
if (ppDataObject == NULL)
ATLTRACE(_T("IComponentData::QueryDataObject called with ppDataObject == NULL\n"));
else
{
*ppDataObject = NULL;
CSnapInItem* pItem = (CSnapInItem*) cookie;
if (cookie == NULL)
pItem = m_pNode;
hr = pItem->GetDataObject(ppDataObject, type);
}
return hr;
}
STDMETHOD(GetDisplayInfo)(SCOPEDATAITEM *pScopeDataItem)
{
ATLTRACE(_T("IComponentDataImpl::GetDisplayInfo\n"));
HRESULT hr = E_POINTER;
ATLASSERT(pScopeDataItem != NULL);
if (pScopeDataItem == NULL)
ATLTRACE(_T("IComponentData::GetDisplayInfo called with pScopeDataItem == NULL\n"));
else
{
CSnapInItem* pItem= (CSnapInItem*) pScopeDataItem->lParam;
if (pItem == NULL)
pItem = m_pNode;
hr = E_UNEXPECTED;
if (pItem != NULL)
hr = pItem->GetScopePaneInfo(pScopeDataItem);
}
return hr;
}
STDMETHOD(CompareObjects)(LPDATAOBJECT lpDataObjectA,
LPDATAOBJECT lpDataObjectB)
{
ATLTRACENOTIMPL(_T("IComponentDataImpl::CompareObjects\n"));
}
CComPtr<IConsole> m_spConsole;
CSnapInItem* m_pNode;
};
template <class T>
class ATL_NO_VTABLE IComponentImpl : public IComponent
{
public:
STDMETHOD(Initialize)(LPCONSOLE lpConsole)
{
ATLTRACE(_T("IComponentImpl::Initialize\n"));
HRESULT hr = E_POINTER;
ATLASSERT(lpConsole != NULL);
if (lpConsole == NULL)
ATLTRACE(_T("lpConsole is NULL\n"));
else
{
m_spConsole = lpConsole;
CComPtr<IHeaderCtrl> spHeaderCtrl;
hr = m_spConsole->QueryInterface(IID_IHeaderCtrl, (void**)&spHeaderCtrl);
if (FAILED(hr))
ATLTRACE(_T("QI for IHeaderCtrl failed\n"));
else
{
hr = m_spConsole->SetHeader(spHeaderCtrl);
if (FAILED(hr))
ATLTRACE(_T("IConsole::SetHeader failed (HRESULT = %x)\n"), hr);
}
}
return hr;
}
STDMETHOD(Notify)(LPDATAOBJECT lpDataObject,
MMC_NOTIFY_TYPE event,
LPARAM arg,
LPARAM param);
STDMETHOD(Destroy)(MMC_COOKIE cookie)
{
ATLTRACE(_T("IComponentImpl::Destroy\n"));
T* pT = static_cast<T*>(this);
if (pT->m_spControlbar != NULL)
{
int n = pT->m_toolbarMap.GetSize();
for (int i = 0; i < n; i++)
{
IToolbar* pToolbar = (IToolbar*)pT->m_toolbarMap.GetValueAt(i);
if (pToolbar != NULL)
{
pT->m_spControlbar->Detach(pToolbar);
pToolbar->Release();
}
}
}
pT->m_toolbarMap.RemoveAll();
m_spConsole->SetHeader(NULL);
m_spConsole.Release();
return S_OK;
}
STDMETHOD(QueryDataObject)(MMC_COOKIE cookie,
DATA_OBJECT_TYPES type,
LPDATAOBJECT *ppDataObject)
{
ATLTRACE(_T("IComponentImpl::QueryDataObject\n"));
ATLASSERT(ppDataObject != NULL);
if (ppDataObject == NULL)
{
ATLTRACE(_T("IComponent::QueryDataObject called with ppDataObject==NULL \n"));
return E_POINTER;
}
if (cookie == NULL)
{
ATLTRACE(_T("IComponent::QueryDataObject called with cookie==NULL \n"));
return E_UNEXPECTED;
}
*ppDataObject = NULL;
if (cookie == MMC_MULTI_SELECT_COOKIE)
{
ATLTRACE(_T("Override QueryDataObject to handle multiselect\n"));
return E_UNEXPECTED;
}
CSnapInItem* pItem = (CSnapInItem*) cookie;
return pItem->GetDataObject(ppDataObject, type);
}
STDMETHOD(GetResultViewType)(MMC_COOKIE cookie,
LPOLESTR *ppViewType,
long *pViewOptions)
{
ATLTRACE(_T("IComponentImpl::GetResultViewType\n"));
if (cookie == NULL)
{
#ifdef FIX_PROBLEM_WITH_GET_RESULT_VIEW_TYPE_NULL_COOKIE
T* pT = static_cast<T*>(this);
// We are being asked about our root node.
_ASSERTE( pT->m_pComponentData!= NULL );
_ASSERTE( pT->m_pComponentData->m_pNode != NULL );
return pT->m_pComponentData->m_pNode->GetResultViewType(ppViewType, pViewOptions);
#else // FIX_PROBLEM_WITH_GET_RESULT_VIEW_TYPE_NULL_COOKIE
*ppViewType = NULL;
*pViewOptions = MMC_VIEW_OPTIONS_NONE;
return S_FALSE;
#endif //FIX_PROBLEM_WITH_GET_RESULT_VIEW_TYPE_NULL_COOKIE
}
CSnapInItem* pItem = (CSnapInItem*)cookie;
return pItem->GetResultViewType(ppViewType, pViewOptions);
}
STDMETHOD(GetDisplayInfo)(RESULTDATAITEM *pResultDataItem)
{
ATLTRACE(_T("IComponentImpl::GetDisplayInfo\n"));
ATLASSERT(pResultDataItem != NULL);
if (pResultDataItem == NULL)
{
ATLTRACE(_T("IComponent::GetDisplayInfo called with pResultDataItem==NULL\n"));
return E_POINTER;
}
CSnapInItem* pItem = (CSnapInItem*) pResultDataItem->lParam;
if (pItem == NULL)
{
ATLTRACE(_T("Invalid Item\n"));
return E_UNEXPECTED;
}
return pItem->GetResultPaneInfo(pResultDataItem);
}
STDMETHOD(CompareObjects)( LPDATAOBJECT lpDataObjectA,
LPDATAOBJECT lpDataObjectB)
{
ATLTRACENOTIMPL(_T("IComponentImpl::CompareObjects\n"));
}
CComPtr<IConsole> m_spConsole;
};
template <class T>
HRESULT IComponentImpl<T>::Notify(LPDATAOBJECT lpDataObject,
MMC_NOTIFY_TYPE event,
LPARAM arg,
LPARAM param)
{
ATLTRACE(_T("IComponentImpl::Notify\n"));
HRESULT hr = E_POINTER;
ATLASSERT(lpDataObject != NULL);
if (lpDataObject == NULL)
ATLTRACE(_T("IComponent::Notify called with lpDataObject==NULL \n"));
else
{
T* pT = static_cast<T*>(this);
CSnapInItem* pItem;
DATA_OBJECT_TYPES type;
// Make sure that the object is derived from CSnapInObjectRoot
hr = pT->m_pComponentData->GetDataClass(lpDataObject, &pItem, &type);
if (SUCCEEDED(hr))
hr = pItem->Notify(event, arg, param, NULL, pT, type);
}
return hr;
}
template <class T, class D>
class ATL_NO_VTABLE IResultDataCompareImpl : public IResultDataCompare
{
public:
STDMETHOD(Compare)(LPARAM lUserParam,
MMC_COOKIE cookieA,
MMC_COOKIE cookieB,
int *pnResult)
{
ATLTRACENOTIMPL(_T("IResultDataCompareImpl::Compare"));
}
};
template <class T>
class ATL_NO_VTABLE IExtendContextMenuImpl : public IExtendContextMenu
{
public:
STDMETHOD(AddMenuItems)(LPDATAOBJECT pDataObject,
LPCONTEXTMENUCALLBACK piCallback,
long *pInsertionAllowed);
STDMETHOD(Command)(long lCommandID,
LPDATAOBJECT pDataObject);
};
template <class T>
inline HRESULT IExtendContextMenuImpl<T>::AddMenuItems(LPDATAOBJECT pDataObject,
LPCONTEXTMENUCALLBACK piCallback,
long *pInsertionAllowed)
{
ATLTRACE(_T("IExtendContextMenuImpl::AddMenuItems\n"));
HRESULT hr = E_POINTER;
ATLASSERT(pDataObject != NULL);
if (pDataObject == NULL)
ATLTRACE(_T("IExtendContextMenu::AddMenuItems called with pDataObject==NULL\n"));
else
{
T* pT = static_cast<T*>(this);
CSnapInItem* pItem;
DATA_OBJECT_TYPES type;
hr = pT->m_pComponentData->GetDataClass(pDataObject, &pItem, &type);
if (SUCCEEDED(hr))
hr = pItem->AddMenuItems(piCallback, pInsertionAllowed, type);
}
return hr;
}
template <class T>
inline HRESULT IExtendContextMenuImpl<T>::Command(long lCommandID,
LPDATAOBJECT pDataObject)
{
ATLTRACE(_T("IExtendContextMenuImpl::Command\n"));
HRESULT hr = E_POINTER;
ATLASSERT(pDataObject != NULL);
if (pDataObject == NULL)
ATLTRACE(_T("IExtendContextMenu::Command called with pDataObject==NULL\n"));
else
{
T* pT = static_cast<T*>(this);
CSnapInItem* pItem;
DATA_OBJECT_TYPES type;
hr = pT->m_pComponentData->GetDataClass(pDataObject, &pItem, &type);
if (SUCCEEDED(hr))
hr = pItem->Command(lCommandID, (CSnapInObjectRootBase*)pT, type);
}
return hr;
}
template<class T>
class ATL_NO_VTABLE IExtendPropertySheetImpl : public IExtendPropertySheet2
{
public:
STDMETHOD(CreatePropertyPages)(LPPROPERTYSHEETCALLBACK lpProvider,
LONG_PTR handle,
LPDATAOBJECT pDataObject);
STDMETHOD(QueryPagesFor)(LPDATAOBJECT pDataObject);
STDMETHOD(GetWatermarks)(
LPDATAOBJECT lpIDataObject,
HBITMAP *lphWatermark,
HBITMAP *lphHeader,
HPALETTE *lphPalette,
BOOL *bStretch);
};
template<class T>
inline HRESULT IExtendPropertySheetImpl<T>::GetWatermarks(
LPDATAOBJECT lpIDataObject,
HBITMAP *lphWatermark,
HBITMAP *lphHeader,
HPALETTE *lphPalette,
BOOL *bStretch)
{
ATLTRACE(_T("IExtendPropertySheetImpl::GetWatermarks\n"));
return E_NOTIMPL;
}
template<class T>
inline HRESULT IExtendPropertySheetImpl<T>::CreatePropertyPages(LPPROPERTYSHEETCALLBACK lpProvider,
LONG_PTR handle,
LPDATAOBJECT pDataObject)
{
ATLTRACE(_T("IExtendPropertySheetImpl::CreatePropertyPages\n"));
HRESULT hr = E_POINTER;
ATLASSERT(pDataObject != NULL);
if (pDataObject == NULL)
ATLTRACE(_T("IExtendPropertySheetImpl::CreatePropertyPages called with pDataObject==NULL\n"));
else
{
T* pT = static_cast<T*>(this);
CSnapInItem* pItem;
DATA_OBJECT_TYPES type;
hr = pT->m_pComponentData->GetDataClass(pDataObject, &pItem, &type);
if (SUCCEEDED(hr))
hr = pItem->CreatePropertyPages(lpProvider, handle, this, type);
}
return hr;
}
template <class T>
inline HRESULT IExtendPropertySheetImpl<T>::QueryPagesFor(LPDATAOBJECT pDataObject)
{
ATLTRACE(_T("IExtendPropertySheetImpl::QueryPagesFor\n"));
HRESULT hr = E_POINTER;
ATLASSERT(pDataObject != NULL);
if (pDataObject == NULL)
ATLTRACE(_T("IExtendPropertySheetImpl::QueryPagesFor called with pDataObject==NULL\n"));
else
{
T* pT = static_cast<T*>(this);
CSnapInItem* pItem;
DATA_OBJECT_TYPES type;
hr = pT->m_pComponentData->GetDataClass(pDataObject, &pItem, &type);
if (SUCCEEDED(hr))
hr = pItem->QueryPagesFor(type);
}
return hr;
}
template <class T>
class ATL_NO_VTABLE IExtendControlbarImpl : public IExtendControlbar
{
public:
STDMETHOD(SetControlbar)(LPCONTROLBAR pControlbar)
{
ATLTRACE(_T("IExtendControlbarImpl::SetControlbar\n"));
T* pT = static_cast<T*>(this);
if (pT->m_spControlbar != NULL)
{
int n = pT->m_toolbarMap.GetSize();
for (int i = 0; i < n; i++)
{
IToolbar* pToolbar = (IToolbar*)pT->m_toolbarMap.GetValueAt(i);
if (pToolbar != NULL)
{
pT->m_spControlbar->Detach(pToolbar);
pToolbar->Release();
}
}
}
pT->m_toolbarMap.RemoveAll();
pT->m_spControlbar = pControlbar;
return S_OK;
}
STDMETHOD(ControlbarNotify)(MMC_NOTIFY_TYPE event,
LPARAM arg,
LPARAM param);
};
template <class T>
inline HRESULT IExtendControlbarImpl<T>::ControlbarNotify(MMC_NOTIFY_TYPE event,
LPARAM arg,
LPARAM param)
{
ATLTRACE(_T("IExtendControlbarImpl::ControlbarNotify\n"));
CSnapInItem* pItem = NULL;
DATA_OBJECT_TYPES type;
HRESULT hr = S_OK;
T* pT = static_cast<T*>(this);
if (event == MMCN_BTN_CLICK)
hr = pT->m_pComponentData->GetDataClass((IDataObject*) arg, &pItem, &type);
else if (event == MMCN_SELECT)
{
hr = pT->m_pComponentData->GetDataClass((IDataObject*) param, &pItem, &type);
BOOL bSelect = (BOOL) HIWORD (arg);
BOOL bScope = (BOOL) LOWORD(arg);
if (bSelect)
{
int n = pT->m_toolbarMap.GetSize();
for (int i = 0; i < n; i++)
{
IToolbar* pToolbar = (IToolbar*)pT->m_toolbarMap.GetValueAt(i);
if (pToolbar != NULL)
pT->m_spControlbar->Detach(pToolbar);
}
}
}
if (SUCCEEDED(hr))
hr = pItem->ControlbarNotify(pT->m_spControlbar, this, &(pT->m_toolbarMap), event, arg, param, (CSnapInObjectRootBase*) pT, type);
return hr;
}
#ifdef TASKPAD_SUPPORT
template <class T>
class ATL_NO_VTABLE IExtendTaskPadImpl : public IExtendTaskPad
{
public:
STDMETHOD(TaskNotify)(
/* [in] */ IDataObject __RPC_FAR *lpDataObject,
/* [in] */ VARIANT __RPC_FAR *pvarg,
/* [in] */ VARIANT __RPC_FAR *pvparam)
{
ATLTRACE(_T("IExtendTaskPadImpl::TaskNotify\n"));
HRESULT hr = E_POINTER;
ATLASSERT(lpDataObject != NULL);
if (lpDataObject == NULL)
ATLTRACE(_T("IExtendTaskPadImpl::TaskNotify called with lpDataObject==NULL \n"));
else
{
T* pT = static_cast<T*>(this);
CSnapInItem* pItem;
DATA_OBJECT_TYPES type;
ATLASSERT(pT->m_pComponentData != NULL);
hr = pT->m_pComponentData->GetDataClass(lpDataObject, &pItem, &type);
if (SUCCEEDED(hr))
hr = pItem->TaskNotify(
lpDataObject
, pvarg
, pvparam
);
}
return hr;
}
STDMETHOD(EnumTasks)(
/* [in] */ IDataObject __RPC_FAR *lpDataObject,
/* [in] */ LPOLESTR szTaskGroup,
/* [out] */ IEnumTASK __RPC_FAR *__RPC_FAR *ppEnumTASK)
{
ATLTRACE(_T("IExtendTaskPadImpl::EnumTasks\n"));
HRESULT hr = E_POINTER;
ATLASSERT(lpDataObject != NULL);
if (lpDataObject == NULL)
ATLTRACE(_T("IExtendTaskPadImpl::EnumTasks called with lpDataObject==NULL \n"));
else
{
T* pT = static_cast<T*>(this);
CSnapInItem* pItem;
DATA_OBJECT_TYPES type;
ATLASSERT(pT->m_pComponentData != NULL);
hr = pT->m_pComponentData->GetDataClass(lpDataObject, &pItem, &type);
if (SUCCEEDED(hr))
hr = pItem->EnumTasks(
lpDataObject
, szTaskGroup
, ppEnumTASK
);
}
return hr;
}
STDMETHOD(GetTitle)(
/* [in,string] */ LPOLESTR szGroup,
/* [out,string] */ LPOLESTR *pszTitle)
{
ATLTRACENOTIMPL(_T("IExtendTaskPadImpl::GetTitle\n"));
}
STDMETHOD(GetDescriptiveText)(
/* [in,string] */ LPOLESTR pszGroup,
/* [out,string] */ LPOLESTR *pszDescriptiveText)
{
ATLTRACENOTIMPL(_T("IExtendTaskPadImpl::GetDescriptiveText\n"));
}
STDMETHOD(GetBackground)(
/* [in,string] */ LPOLESTR pszGroup,
/* [out] */ MMC_TASK_DISPLAY_OBJECT *pTDO )
{
ATLTRACENOTIMPL(_T("IExtendTaskPadImpl::GetBackground\n"));
}
STDMETHOD(GetListPadInfo)(
/* [string][in] */ LPOLESTR pszGroup,
/* [out] */ MMC_LISTPAD_INFO __RPC_FAR *lpListPadInfo)
{
ATLTRACENOTIMPL(_T("IExtendTaskPadImpl::GetListPadInfo\n"));
}
};
#endif // TASKPAD_SUPPORT
#define SNAPINMENUID(id) \
public: \
static const UINT GetMenuID() \
{ \
static const UINT IDMENU = id; \
return id; \
}
#define EXT_SNAPINMENUID(id) \
public: \
static const UINT GetMenuID() \
{ \
static const UINT IDMENU = id; \
return id; \
}
#define BEGIN_SNAPINCOMMAND_MAP(theClass, bIsExtension) \
HRESULT ProcessCommand(UINT nID, \
bool& bHandled, \
CSnapInObjectRootBase* pObj, \
DATA_OBJECT_TYPES type) \
{ \
bHandled = true; \
HRESULT hr = S_OK;
#define SNAPINCOMMAND_ENTRY(id, func) \
if (id == nID) \
{ \
hr = func(bHandled, pObj); \
if (bHandled) \
return hr; \
}
#define SNAPINCOMMAND_RANGE_ENTRY(id1, id2, func) \
if (id1 >= nID && nID <= id2) \
{ \
hr = func(nID, bHandled, pObj); \
if (bHandled) \
return hr; \
}
#define CHAIN_SNAPINCOMMAND_MAP(theChainClass) \
{ \
hr = theChainClass::ProcessCommand(nID, bHandled, pObj, type); \
if (bHandled) \
return hr; \
}
#define END_SNAPINCOMMAND_MAP() \
return hr; \
}
struct CSnapInToolBarData
{
WORD wVersion;
WORD wWidth;
WORD wHeight;
WORD wItemCount;
//WORD aItems[wItemCount]
WORD* items()
{ return (WORD*)(this+1); }
};
#define RT_TOOLBAR MAKEINTRESOURCE(241)
class CSnapInToolbarInfo
{
public:
~CSnapInToolbarInfo()
{
CleanUp();
}
HRESULT CleanUp()
{
if (m_pStrToolTip)
{
for (UINT i = 0; i < m_nButtonCount; i++)
{
delete m_pStrToolTip[i];
m_pStrToolTip[i] = NULL;
}
delete [] m_pStrToolTip;
m_pStrToolTip = NULL;
}
if (m_pStrButtonText)
{
for (UINT i = 0; i < m_nButtonCount; i++)
{
delete m_pStrButtonText[i];
m_pStrButtonText[i] = NULL;
}
delete [] m_pStrButtonText;
m_pStrButtonText = NULL;
}
if (m_pnButtonID)
{
delete m_pnButtonID;
m_pnButtonID = NULL;
}
m_nButtonCount = 0;
return S_OK;
}
OLECHAR** m_pStrToolTip;
OLECHAR** m_pStrButtonText;
UINT* m_pnButtonID;
UINT m_idToolbar;
UINT m_nButtonCount;
};
#define BEGIN_SNAPINTOOLBARID_MAP(theClass) \
public: \
static CSnapInToolbarInfo* GetToolbarInfo() \
{ \
static CSnapInToolbarInfo m_toolbarInfo[] = \
{
#define SNAPINTOOLBARID_ENTRY(id) \
{ NULL, NULL, NULL, id, 0},
#define END_SNAPINTOOLBARID_MAP() \
{ NULL, NULL, NULL, 0, 0} \
}; \
return m_toolbarInfo; \
}
class GdiObjectSentry
{
public:
GdiObjectSentry(HGDIOBJ object) throw ()
: obj(object)
{
}
~GdiObjectSentry() throw ()
{
DeleteObject(obj);
}
private:
HGDIOBJ obj;
// Not implemented.
GdiObjectSentry(const GdiObjectSentry&);
GdiObjectSentry& operator=(const GdiObjectSentry&);
};
template <class T, BOOL bIsExtension = FALSE>
class ATL_NO_VTABLE CSnapInItemImpl : public CSnapInItem
{
public:
CSnapInItemImpl(unsigned int helpIndex = 0)
:CSnapInItem(helpIndex)
{
}
virtual ~CSnapInItemImpl()
{
}
public:
STDMETHOD(Notify)( MMC_NOTIFY_TYPE event,
LPARAM arg,
LPARAM param,
IComponentData* pComponentData,
IComponent* pComponent,
DATA_OBJECT_TYPES type)
{
ATLASSERT("Override Function in Derived Class");
ATLTRACENOTIMPL(_T("CSnapInItemImpl::Notify"));
}
STDMETHOD(GetScopePaneInfo)(SCOPEDATAITEM *pScopeDataItem)
{
ATLTRACENOTIMPL(_T("CSnapInItemImpl::GetScopePaneInfo"));
}
STDMETHOD(GetResultViewType)(LPOLESTR *ppViewType,
long *pViewOptions)
{
ATLTRACE(_T("CSnapInItemImpl::GetResultViewType\n"));
*ppViewType = NULL;
*pViewOptions = MMC_VIEW_OPTIONS_NONE;
return S_FALSE;
}
STDMETHOD(GetResultPaneInfo)(RESULTDATAITEM *pResultDataItem)
{
ATLTRACENOTIMPL(_T("CSnapInItemImpl::GetResultPaneInfo"));
}
STDMETHOD(AddMenuItems)(LPCONTEXTMENUCALLBACK piCallback,
long *pInsertionAllowed,
DATA_OBJECT_TYPES type)
{
ATLTRACE(_T("CSnapInItemImpl::AddMenuItems\n"));
T* pT = static_cast<T*>(this);
if (!bIsExtension)
pT->SetMenuInsertionFlags(true, pInsertionAllowed);
UINT menuID = pT->GetMenuID();
if (menuID == 0)
return S_OK;
HMENU hMenu = LoadMenu(_Module.GetResourceInstance(), MAKEINTRESOURCE(menuID));
long insertionID;
if (hMenu)
{
for (int i = 0; 1; i++)
{
HMENU hSubMenu = GetSubMenu(hMenu, i);
if (hSubMenu == NULL)
break;
MENUITEMINFO menuItemInfo;
memset(&menuItemInfo, 0, sizeof(menuItemInfo));
menuItemInfo.cbSize = sizeof(menuItemInfo);
switch (i)
{
case 0:
if (! (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP) )
continue;
insertionID = CCM_INSERTIONPOINTID_PRIMARY_TOP;
break;
case 1:
if (! (*pInsertionAllowed & CCM_INSERTIONALLOWED_NEW) )
continue;
if (bIsExtension)
insertionID = CCM_INSERTIONPOINTID_3RDPARTY_NEW;
else
insertionID = CCM_INSERTIONPOINTID_PRIMARY_NEW;
break;
case 2:;
if (! (*pInsertionAllowed & CCM_INSERTIONALLOWED_TASK) )
continue;
if (bIsExtension)
insertionID = CCM_INSERTIONPOINTID_3RDPARTY_TASK;
else
insertionID = CCM_INSERTIONPOINTID_PRIMARY_TASK;
break;
case 3:;
if (! (*pInsertionAllowed & CCM_INSERTIONALLOWED_VIEW) )
continue;
insertionID = CCM_INSERTIONPOINTID_PRIMARY_VIEW;
break;
default:
{
insertionID = 0;
continue;
}
break;
}
menuItemInfo.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID;
menuItemInfo.fType = MFT_STRING;
TCHAR szMenuText[128];
for (int j = 0; 1; j++)
{
menuItemInfo.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID;
menuItemInfo.fType = MFT_STRING;
menuItemInfo.cch = 128;
menuItemInfo.dwTypeData = szMenuText;
TCHAR szStatusBar[256];
if (!GetMenuItemInfo(hSubMenu, j, TRUE, &menuItemInfo))
break;
if (menuItemInfo.fType != MFT_STRING)
continue;
pT->UpdateMenuState(menuItemInfo.wID, szMenuText, &menuItemInfo.fState);
LoadString(_Module.GetResourceInstance(), menuItemInfo.wID, szStatusBar, 256);
OLECHAR wszStatusBar[256];
OLECHAR wszMenuText[128];
USES_CONVERSION;
ocscpy(wszMenuText, T2OLE(szMenuText));
ocscpy(wszStatusBar, T2OLE(szStatusBar));
CONTEXTMENUITEM contextMenuItem;
contextMenuItem.strName = wszMenuText;
contextMenuItem.strStatusBarText = wszStatusBar;
contextMenuItem.lCommandID = menuItemInfo.wID;
contextMenuItem.lInsertionPointID = insertionID;
contextMenuItem.fFlags = menuItemInfo.fState;
contextMenuItem.fSpecialFlags = 0;
HRESULT hr = piCallback->AddItem(&contextMenuItem);
ATLASSERT(SUCCEEDED(hr));
}
}
DestroyMenu(hMenu);
}
if (!bIsExtension)
pT->SetMenuInsertionFlags(true, pInsertionAllowed);
return S_OK;
}
STDMETHOD(Command)(long lCommandID,
CSnapInObjectRootBase* pObj,
DATA_OBJECT_TYPES type)
{
ATLTRACE(_T("CSnapInItemImpl::Command\n"));
bool bHandled;
T* pT = static_cast<T*>(this);
return pT->ProcessCommand(lCommandID, bHandled, pObj, type);
}
STDMETHOD(CreatePropertyPages)(LPPROPERTYSHEETCALLBACK lpProvider,
LONG_PTR handle,
IUnknown* pUnk,
DATA_OBJECT_TYPES type)
{
ATLASSERT("Override Function in Derived Class");
ATLTRACENOTIMPL(_T("CSnapInItemImpl::CreatePropertyPages"));
}
STDMETHOD(QueryPagesFor)(DATA_OBJECT_TYPES type)
{
ATLASSERT("Override Function in Derived Class");
ATLTRACENOTIMPL(_T("CSnapInItemImpl::QueryPagesFor"));
}
STDMETHOD(SetControlbar)(IControlbar *pControlbar,
IExtendControlbar* pExtendControlBar,
CSimpleMap<UINT, IUnknown*>* pToolbarMap)
{
ATLTRACE(_T("CSnapInItemImpl::SetControlbar\n"));
T* pT = static_cast<T*>(this);
CSnapInToolbarInfo* pInfo = pT->GetToolbarInfo();
if (pInfo == NULL)
return S_OK;
for( ; pInfo->m_idToolbar; pInfo++)
{
IToolbar* p = (IToolbar*) pToolbarMap->Lookup(pInfo->m_idToolbar);
if (p != NULL)
continue;
HBITMAP hBitmap = LoadBitmap(_Module.GetResourceInstance(), MAKEINTRESOURCE(pInfo->m_idToolbar));
if (hBitmap == NULL)
return S_OK;
GdiObjectSentry sentry(hBitmap);
HRSRC hRsrc = ::FindResource(_Module.GetResourceInstance(), MAKEINTRESOURCE(pInfo->m_idToolbar), RT_TOOLBAR);
if (hRsrc == NULL)
return S_OK;
HGLOBAL hGlobal = LoadResource(_Module.GetResourceInstance(), hRsrc);
if (hGlobal == NULL)
return S_OK;
CSnapInToolBarData* pData = (CSnapInToolBarData*)LockResource(hGlobal);
if (pData == NULL)
return S_OK;
ATLASSERT(pData->wVersion == 1);
ATLASSERT(pData->wWidth == 16);
ATLASSERT(pData->wHeight == 16);
pInfo->m_nButtonCount = pData->wItemCount;
if (pInfo->m_pnButtonID == NULL)
pInfo->m_pnButtonID = new UINT[pInfo->m_nButtonCount];
if (pInfo->m_pnButtonID == NULL)
continue;
MMCBUTTON *pButtons = new MMCBUTTON[pData->wItemCount];
if (pButtons == NULL)
{
delete []pInfo->m_pnButtonID;
continue;
}
if (pInfo->m_pStrToolTip == NULL)
{
pInfo->m_pStrToolTip = new OLECHAR* [pData->wItemCount];
if (pInfo->m_pStrToolTip)
memset(pInfo->m_pStrToolTip, 0, sizeof(OLECHAR*) * pData->wItemCount);
}
if (pInfo->m_pStrToolTip == NULL)
{
delete []pInfo->m_pnButtonID;
delete []pButtons;
continue;
}
for (int i = 0, j = 0; i < pData->wItemCount; i++)
{
pInfo->m_pnButtonID[i] = pButtons[i].idCommand = pData->items()[i];
if (pButtons[i].idCommand)
{
pButtons[i].nBitmap = j++;
// get the statusbar string and allow modification of the button state
TCHAR szStatusBar[512];
LoadString(_Module.GetResourceInstance(), pButtons[i].idCommand, szStatusBar, 512);
if (pInfo->m_pStrToolTip[i] == NULL)
pInfo->m_pStrToolTip[i] = new OLECHAR[lstrlen(szStatusBar) + 1];
if (pInfo->m_pStrToolTip[i] == NULL)
continue;
USES_CONVERSION;
ocscpy(pInfo->m_pStrToolTip[i], T2OLE(szStatusBar));
pButtons[i].lpTooltipText = pInfo->m_pStrToolTip[i];
pButtons[i].lpButtonText = OLESTR("");
pButtons[i].fsState = TBSTATE_ENABLED;
pButtons[i].fsType = TBSTYLE_BUTTON;
pT->SetToolbarButtonInfo(pButtons[i].idCommand, &pButtons[i].fsState, &pButtons[i].fsType);
}
else
{
pButtons[i].lpTooltipText = OLESTR("");
pButtons[i].lpButtonText = OLESTR("");
pButtons[i].fsType = TBSTYLE_SEP;
pButtons[i].fsState = 0;
}
}
IToolbar* pToolbar;
HRESULT hr = pControlbar->Create(TOOLBAR, pExtendControlBar, reinterpret_cast<LPUNKNOWN*>(&pToolbar));
if (SUCCEEDED(hr))
{
hr = pToolbar->AddBitmap(pData->wItemCount, hBitmap, pData->wWidth, pData->wHeight, RGB(255, 0, 255));
if (SUCCEEDED(hr))
{
hr = pToolbar->AddButtons(pData->wItemCount, pButtons);
if (SUCCEEDED(hr))
{
pToolbar->AddRef();
pToolbarMap->Add(pInfo->m_idToolbar, (IUnknown*)pToolbar);
}
}
}
pToolbar->Release();
delete [] pButtons;
}
return S_OK;
}
STDMETHOD(ControlbarNotify)(IControlbar *pControlbar,
IExtendControlbar *pExtendControlbar,
CSimpleMap<UINT, IUnknown*>* pToolbarMap,
MMC_NOTIFY_TYPE event,
LPARAM arg,
LPARAM param,
CSnapInObjectRootBase* pObj,
DATA_OBJECT_TYPES type)
{
ATLTRACE(_T("CSnapInItemImpl::ControlbarNotify\n"));
T* pT = static_cast<T*>(this);
SetControlbar(pControlbar, pExtendControlbar, pToolbarMap);
if(event == MMCN_SELECT)
{
if (pControlbar == NULL)
return S_OK;
BOOL bSelect = (BOOL) HIWORD (arg);
BOOL bScope = (BOOL) LOWORD(arg);
CSnapInToolbarInfo* pInfo = pT->GetToolbarInfo();
if (pInfo == NULL)
return S_OK;
for(; pInfo->m_idToolbar; pInfo++)
{
IToolbar* pToolbar = (IToolbar*)pToolbarMap->Lookup(pInfo->m_idToolbar);
if (pToolbar == NULL)
continue;
if (!bSelect && bScope)
pControlbar->Detach(pToolbar);
else
{
pControlbar->Attach(TOOLBAR, pToolbar);
for (UINT i = 0; i < pInfo->m_nButtonCount; i++)
{
if (pInfo->m_pnButtonID[i])
{
pToolbar->SetButtonState(pInfo->m_pnButtonID[i],
ENABLED,
pT->UpdateToolbarButton(pInfo->m_pnButtonID[i],
ENABLED));
pToolbar->SetButtonState(pInfo->m_pnButtonID[i],
CHECKED,
pT->UpdateToolbarButton(pInfo->m_pnButtonID[i],
CHECKED));
pToolbar->SetButtonState(pInfo->m_pnButtonID[i],
HIDDEN,
pT->UpdateToolbarButton(pInfo->m_pnButtonID[i],
HIDDEN));
pToolbar->SetButtonState(pInfo->m_pnButtonID[i],
INDETERMINATE,
pT->UpdateToolbarButton(pInfo->m_pnButtonID[i],
INDETERMINATE));
pToolbar->SetButtonState(pInfo->m_pnButtonID[i],
BUTTONPRESSED,
pT->UpdateToolbarButton(pInfo->m_pnButtonID[i],
BUTTONPRESSED));
}
}
}
}
return S_OK;
}
else if (event == MMCN_BTN_CLICK)
{
bool bHandled;
return pT->ProcessCommand((UINT) param, bHandled, pObj, type);
}
return E_UNEXPECTED;
}
STDMETHOD(GetScopeData)(SCOPEDATAITEM **pScopeDataItem)
{
if (pScopeDataItem == NULL)
return E_FAIL;
*pScopeDataItem = &m_scopeDataItem;
return S_OK;
}
STDMETHOD(GetResultData)(RESULTDATAITEM **pResultDataItem)
{
if (pResultDataItem == NULL)
return E_FAIL;
*pResultDataItem = &m_resultDataItem;
return S_OK;
}
STDMETHOD(GetDataObject)(IDataObject** pDataObj, DATA_OBJECT_TYPES type)
{
CComObject<CSnapInDataObjectImpl>* pData;
HRESULT hr = CComObject<CSnapInDataObjectImpl>::CreateInstance(&pData);
if (FAILED(hr))
return hr;
T* pT = static_cast<T*> (this);
pData->m_objectData.m_pItem = pT;
pData->m_objectData.m_type = type;
hr = pData->QueryInterface(IID_IDataObject, (void**)(pDataObj));
return hr;
}
void UpdateMenuState(UINT id, LPTSTR pBuf, UINT *flags)
{
return;
}
void SetToolbarButtonInfo(UINT id, BYTE *pfsState, BYTE *pfsType)
{
*pfsState = TBSTATE_ENABLED;
*pfsType = TBSTYLE_BUTTON;
}
BOOL UpdateToolbarButton(UINT id, BYTE fsState)
{
if (fsState == ENABLED)
return TRUE;
return FALSE;
}
HRESULT ProcessCommand(UINT nID,
bool& bHandled,
CSnapInObjectRootBase* pObj,
DATA_OBJECT_TYPES type)
{
ATLTRACE(_T("No handler for item with ID %d\n"), nID);
return S_OK;
}
STDMETHOD (FillData)(CLIPFORMAT cf, LPSTREAM pStream)
{
HRESULT hr = DV_E_CLIPFORMAT;
ULONG uWritten;
T* pT = static_cast<T*> (this);
if (cf == m_CCF_NODETYPE)
{
hr = pStream->Write(pT->GetNodeType(), sizeof(GUID), &uWritten);
return hr;
}
if (cf == m_CCF_SZNODETYPE)
{
hr = pStream->Write(pT->GetSZNodeType(), (ocslen((OLECHAR*)pT->GetSZNodeType()) + 1 )* sizeof(OLECHAR), &uWritten);
return hr;
}
if (cf == m_CCF_DISPLAY_NAME)
{
hr = pStream->Write(pT->GetDisplayName(), (ocslen((OLECHAR*)pT->GetDisplayName()) + 1) * sizeof(OLECHAR), &uWritten);
return hr;
}
if (cf == m_CCF_SNAPIN_CLASSID)
{
hr = pStream->Write(pT->GetSnapInCLSID(), sizeof(GUID), &uWritten);
return hr;
}
return hr;
}
static CSnapInToolbarInfo* GetToolbarInfo()
{
return NULL;
}
static const UINT GetMenuID()
{
return 0;
}
void SetMenuInsertionFlags(bool bBeforeInsertion, long* pInsertionAllowed)
{
}
void* GetNodeType()
{
return (void*)T::m_NODETYPE;
}
void* GetSZNodeType()
{
return (void*)T::m_SZNODETYPE;
}
void* GetDisplayName()
{
return (void*)T::m_SZDISPLAY_NAME;
}
void* GetSnapInCLSID()
{
return (void*)T::m_SNAPIN_CLASSID;
}
CComBSTR m_bstrDisplayName;
SCOPEDATAITEM m_scopeDataItem;
RESULTDATAITEM m_resultDataItem;
#ifdef TASKPAD_SUPPORT
STDMETHOD(TaskNotify)(
IDataObject * pDataObject
, VARIANT * pvarg
, VARIANT * pvparam
)
{
ATLTRACENOTIMPL(_T("CSnapInItemImpl::TaskNotify"));
}
STDMETHOD(EnumTasks)(
IDataObject * pDataObject
, BSTR szTaskGroup
, IEnumTASK** ppEnumTASK
)
{
ATLTRACENOTIMPL(_T("CSnapInItemImpl::EnumTasks"));
}
#endif // TASKPAD_SUPPORT
};
_declspec( selectany ) CLIPFORMAT CSnapInItem::m_CCF_NODETYPE = 0;
_declspec( selectany ) CLIPFORMAT CSnapInItem::m_CCF_SZNODETYPE = 0;
_declspec( selectany ) CLIPFORMAT CSnapInItem::m_CCF_DISPLAY_NAME = 0;
_declspec( selectany ) CLIPFORMAT CSnapInItem::m_CCF_SNAPIN_CLASSID = 0;
_declspec( selectany ) CLIPFORMAT CSnapInItem::m_CCF_SNAPIN_GETOBJECTDATA = 0;
_declspec( selectany ) CLIPFORMAT CSnapInItem::m_CCF_MMC_MULTISELECT_DATAOBJECT = 0;
#endif //__ATL_SNAPIN_H__