ATLSNAP.H

#ifndef __ATL_SNAPIN_H__ 
#define __ATL_SNAPIN_H__

#include <mmc.h>
#include <commctrl.h>

#ifdef _DEBUG
void __cdecl operator delete(void* p);
void* __cdecl operator new(size_t nSize, LPCSTR lpszFileName, int nLine);
#undef new
#define new new(__FILE__, __LINE__)

#endif

#ifdef __cplusplus
extern "C"{
#endif

void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t);
void __RPC_USER MIDL_user_free( void __RPC_FAR * );

#ifndef __ISnapInDataInterface_INTERFACE_DEFINED__
#define __ISnapInDataInterface_INTERFACE_DEFINED__

EXTERN_C const IID IID_ISnapInDataInterface;

#if defined(__cplusplus) && !defined(CINTERFACE)

interface DECLSPEC_UUID("1FABD781-ECDA-11D0-AACE-00AA00C00189")
ISnapInDataInterface : public IUnknown
{
public:
virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Notify(
MMC_NOTIFY_TYPE event,
long arg,
long param,
BOOL bComponentData,
IConsole __RPC_FAR *pConsole,
IHeaderCtrl __RPC_FAR *pHeader,
IToolbar __RPC_FAR *pToolbar) = 0;

virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetDispInfo(
SCOPEDATAITEM __RPC_FAR *pScopeDataItem) = 0;

virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetResultViewType(
LPOLESTR __RPC_FAR *ppVIewType,
long __RPC_FAR *pViewOptions) = 0;

virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetDisplayInfo(
RESULTDATAITEM __RPC_FAR *pResultDataItem) = 0;

virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddMenuItems(
LPCONTEXTMENUCALLBACK piCallback,
long __RPC_FAR *pInsertionAllowed) = 0;

virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Command(
long lCommandID) = 0;

virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreatePropertyPages(
LPPROPERTYSHEETCALLBACK lpProvider,
long handle,
IUnknown* pUnk) = 0;

virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE QueryPagesFor( void) = 0;

virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetControlbar(
IControlbar __RPC_FAR *pControlbar,
IExtendControlbar __RPC_FAR *pExtendControlbar) = 0;

virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ControlbarNotify(
IControlbar __RPC_FAR *pControlbar,
IExtendControlbar __RPC_FAR *pExtendControlbar,
MMC_NOTIFY_TYPE event,
long arg,
long param) = 0;

virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetScopeData(
SCOPEDATAITEM __RPC_FAR *__RPC_FAR *pScopeDataItem) = 0;

virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetResultData(
RESULTDATAITEM __RPC_FAR *__RPC_FAR *pResultDataItem) = 0;

};

#else /* C style interface */

typedef struct ISnapInDataInterfaceVtbl
{
BEGIN_INTERFACE

HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )(
ISnapInDataInterface __RPC_FAR * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);

ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )(
ISnapInDataInterface __RPC_FAR * This);

ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )(
ISnapInDataInterface __RPC_FAR * This);

/* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Notify )(
ISnapInDataInterface __RPC_FAR * This,
MMC_NOTIFY_TYPE event,
long arg,
long param,
BOOL bComponentData,
IConsole __RPC_FAR *pConsole,
IHeaderCtrl __RPC_FAR *pHeader,
IToolbar __RPC_FAR *pToolbar);

/* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetDispInfo )(
ISnapInDataInterface __RPC_FAR * This,
SCOPEDATAITEM __RPC_FAR *pScopeDataItem);

/* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetResultViewType )(
ISnapInDataInterface __RPC_FAR * This,
LPOLESTR __RPC_FAR *ppVIewType,
long __RPC_FAR *pViewOptions);

/* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetDisplayInfo )(
ISnapInDataInterface __RPC_FAR * This,
RESULTDATAITEM __RPC_FAR *pResultDataItem);

/* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *AddMenuItems )(
ISnapInDataInterface __RPC_FAR * This,
LPCONTEXTMENUCALLBACK piCallback,
long __RPC_FAR *pInsertionAllowed);

/* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Command )(
ISnapInDataInterface __RPC_FAR * This,
long lCommandID);

/* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *CreatePropertyPages )(
ISnapInDataInterface __RPC_FAR * This,
LPPROPERTYSHEETCALLBACK lpProvider,
long handle,
IUnknown* pUnk);

/* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryPagesFor )(
ISnapInDataInterface __RPC_FAR * This);

/* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetControlbar )(
ISnapInDataInterface __RPC_FAR * This,
IControlbar __RPC_FAR *pControlbar,
IExtendControlbar __RPC_FAR *pExtendControlbar);

/* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *ControlbarNotify )(
ISnapInDataInterface __RPC_FAR * This,
IControlbar __RPC_FAR *pControlbar,
IExtendControlbar __RPC_FAR *pExtendControlbar,
MMC_NOTIFY_TYPE event,
long arg,
long param);

/* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetScopeData )(
ISnapInDataInterface __RPC_FAR * This,
SCOPEDATAITEM __RPC_FAR *__RPC_FAR *pScopeDataItem);

/* [helpstring] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetResultData )(
ISnapInDataInterface __RPC_FAR * This,
RESULTDATAITEM __RPC_FAR *__RPC_FAR *pResultDataItem);

END_INTERFACE
} ISnapInDataInterfaceVtbl;

interface ISnapInDataInterface
{
CONST_VTBL struct ISnapInDataInterfaceVtbl __RPC_FAR *lpVtbl;
};



#ifdef COBJMACROS


#define ISnapInDataInterface_QueryInterface(This,riid,ppvObject)\
(This)->lpVtbl -> QueryInterface(This,riid,ppvObject)

#define ISnapInDataInterface_AddRef(This)\
(This)->lpVtbl -> AddRef(This)

#define ISnapInDataInterface_Release(This)\
(This)->lpVtbl -> Release(This)


#define ISnapInDataInterface_Notify(This,event,arg,param,bComponentData,pConsole,pHeader,pToolbar)\
(This)->lpVtbl -> Notify(This,event,arg,param,bComponentData,pConsole,pHeader,pToolbar)

#define ISnapInDataInterface_GetDispInfo(This,pScopeDataItem)\
(This)->lpVtbl -> GetDispInfo(This,pScopeDataItem)

#define ISnapInDataInterface_GetResultViewType(This,ppVIewType,pViewOptions)\
(This)->lpVtbl -> GetResultViewType(This,ppVIewType,pViewOptions)

#define ISnapInDataInterface_GetDisplayInfo(This,pResultDataItem)\
(This)->lpVtbl -> GetDisplayInfo(This,pResultDataItem)

#define ISnapInDataInterface_AddMenuItems(This,piCallback,pInsertionAllowed)\
(This)->lpVtbl -> AddMenuItems(This,piCallback,pInsertionAllowed)

#define ISnapInDataInterface_Command(This,lCommandID)\
(This)->lpVtbl -> Command(This,lCommandID)

#define ISnapInDataInterface_CreatePropertyPages(This,lpProvider,handle, pUnk)\
(This)->lpVtbl -> CreatePropertyPages(This,lpProvider,handle, pUnk)

#define ISnapInDataInterface_QueryPagesFor(This)\
(This)->lpVtbl -> QueryPagesFor(This)

#define ISnapInDataInterface_SetControlbar(This,pControlbar,pExtendControlbar)\
(This)->lpVtbl -> SetControlbar(This,pControlbar,pExtendControlbar)

#define ISnapInDataInterface_ControlbarNotify(This,pControlbar,pExtendControlbar,event,arg,param)\
(This)->lpVtbl -> ControlbarNotify(This,pControlbar,pExtendControlbar,event,arg,param)

#define ISnapInDataInterface_GetScopeData(This,pScopeDataItem)\
(This)->lpVtbl -> GetScopeData(This,pScopeDataItem)

#define ISnapInDataInterface_GetResultData(This,pResultDataItem)\
(This)->lpVtbl -> GetResultData(This,pResultDataItem)

#endif /* COBJMACROS */


#endif /* C style interface */



/* [helpstring] */ HRESULT STDMETHODCALLTYPE ISnapInDataInterface_Notify_Proxy(
ISnapInDataInterface __RPC_FAR * This,
MMC_NOTIFY_TYPE event,
long arg,
long param,
BOOL bComponentData,
IConsole __RPC_FAR *pConsole,
IHeaderCtrl __RPC_FAR *pHeader,
IToolbar __RPC_FAR *pToolbar);


void __RPC_STUB ISnapInDataInterface_Notify_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);


/* [helpstring] */ HRESULT STDMETHODCALLTYPE ISnapInDataInterface_GetDispInfo_Proxy(
ISnapInDataInterface __RPC_FAR * This,
SCOPEDATAITEM __RPC_FAR *pScopeDataItem);


void __RPC_STUB ISnapInDataInterface_GetDispInfo_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);


/* [helpstring] */ HRESULT STDMETHODCALLTYPE ISnapInDataInterface_GetResultViewType_Proxy(
ISnapInDataInterface __RPC_FAR * This,
LPOLESTR __RPC_FAR *ppVIewType,
long __RPC_FAR *pViewOptions);


void __RPC_STUB ISnapInDataInterface_GetResultViewType_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);


/* [helpstring] */ HRESULT STDMETHODCALLTYPE ISnapInDataInterface_GetDisplayInfo_Proxy(
ISnapInDataInterface __RPC_FAR * This,
RESULTDATAITEM __RPC_FAR *pResultDataItem);


void __RPC_STUB ISnapInDataInterface_GetDisplayInfo_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);


/* [helpstring] */ HRESULT STDMETHODCALLTYPE ISnapInDataInterface_AddMenuItems_Proxy(
ISnapInDataInterface __RPC_FAR * This,
LPCONTEXTMENUCALLBACK piCallback,
long __RPC_FAR *pInsertionAllowed);


void __RPC_STUB ISnapInDataInterface_AddMenuItems_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);


/* [helpstring] */ HRESULT STDMETHODCALLTYPE ISnapInDataInterface_Command_Proxy(
ISnapInDataInterface __RPC_FAR * This,
long lCommandID);


void __RPC_STUB ISnapInDataInterface_Command_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);


/* [helpstring] */ HRESULT STDMETHODCALLTYPE ISnapInDataInterface_CreatePropertyPages_Proxy(
ISnapInDataInterface __RPC_FAR * This,
LPPROPERTYSHEETCALLBACK lpProvider,
long handle,
IUnknown* pUnk);


void __RPC_STUB ISnapInDataInterface_CreatePropertyPages_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);


/* [helpstring] */ HRESULT STDMETHODCALLTYPE ISnapInDataInterface_QueryPagesFor_Proxy(
ISnapInDataInterface __RPC_FAR * This);


void __RPC_STUB ISnapInDataInterface_QueryPagesFor_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);


/* [helpstring] */ HRESULT STDMETHODCALLTYPE ISnapInDataInterface_SetControlbar_Proxy(
ISnapInDataInterface __RPC_FAR * This,
IControlbar __RPC_FAR *pControlbar,
IExtendControlbar __RPC_FAR *pExtendControlbar);


void __RPC_STUB ISnapInDataInterface_SetControlbar_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);


/* [helpstring] */ HRESULT STDMETHODCALLTYPE ISnapInDataInterface_ControlbarNotify_Proxy(
ISnapInDataInterface __RPC_FAR * This,
IControlbar __RPC_FAR *pControlbar,
IExtendControlbar __RPC_FAR *pExtendControlbar,
MMC_NOTIFY_TYPE event,
long arg,
long param);


void __RPC_STUB ISnapInDataInterface_ControlbarNotify_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);


/* [helpstring] */ HRESULT STDMETHODCALLTYPE ISnapInDataInterface_GetScopeData_Proxy(
ISnapInDataInterface __RPC_FAR * This,
SCOPEDATAITEM __RPC_FAR *__RPC_FAR *pScopeDataItem);


void __RPC_STUB ISnapInDataInterface_GetScopeData_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);


/* [helpstring] */ HRESULT STDMETHODCALLTYPE ISnapInDataInterface_GetResultData_Proxy(
ISnapInDataInterface __RPC_FAR * This,
RESULTDATAITEM __RPC_FAR *__RPC_FAR *pResultDataItem);


void __RPC_STUB ISnapInDataInterface_GetResultData_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);



#endif /* __ISnapInDataInterface_INTERFACE_DEFINED__ */

#ifdef __cplusplus
}
#endif

#pragma comment(lib, "mmc.lib")

#ifndef CPropertyPageImpl
#pragma comment(lib, "comctl32.lib")

template <class T>
class ATL_NO_VTABLE CPropertyPageImpl : public CDialogImplBase
{
public:
PROPSHEETPAGE m_psp;

operator PROPSHEETPAGE*() { return &m_psp; }

// Construction
CPropertyPageImpl(LPCTSTR lpszTitle = NULL)
{
// 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 = (DLGPROC)T::StartDialogProc;
m_psp.pfnCallback = T::PropPageCallback;
m_psp.lParam = (LPARAM)this;

if(lpszTitle != NULL)
{
m_psp.pszTitle = lpszTitle;
m_psp.dwFlags |= PSP_USETITLE;
}
}

static UINT CALLBACK PropPageCallback(HWND hWnd, UINT uMsg, LPPROPSHEETPAGE ppsp)
{
if(uMsg == PSPCB_CREATE)
{
_ASSERTE(hWnd == NULL);
CDialogImplBase* pPage = (CDialogImplBase*)ppsp->lParam;
_Module.AddCreateWndData(&pPage->m_thunk.cd, pPage);
}

return 1;
}

HPROPSHEETPAGE Create()
{
return ::CreatePropertySheetPage(&m_psp);
}

BOOL EndDialog(int)
{
// do nothing here, calling ::EndDialog will close the whole sheet
_ASSERTE(FALSE);
return FALSE;
}

// Operations
void CancelToClose()
{
_ASSERTE(::IsWindow(m_hWnd));
_ASSERTE(GetParent() != NULL);

::SendMessage(GetParent(), PSM_CANCELTOCLOSE, 0, 0L);
}
void SetModified(BOOL bChanged = TRUE)
{
_ASSERTE(::IsWindow(m_hWnd));
_ASSERTE(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)
{
_ASSERTE(::IsWindow(m_hWnd));
_ASSERTE(GetParent() != NULL);

return ::SendMessage(GetParent(), PSM_QUERYSIBLINGS, wParam, lParam);
}

BEGIN_MSG_MAP(CPropertyPageImpl< T >)
MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
END_MSG_MAP()

// Message handler
LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
_ASSERTE(::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:
//? other values
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:
//? other values
lResult = !pT->OnWizardNext();
break;
case PSN_WIZBACK:
lResult = !pT->OnWizardBack();
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;
}
};
#endif


template <class T>
class ATL_NO_VTABLE CSnapInDataObjectImpl : public IDataObject
{
public:
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
LPSTREAM pStream;
hr = CreateStreamOnHGlobal(pmedium->hGlobal, FALSE, &pStream);
if (SUCCEEDED(hr))
{
T* pT = static_cast<T*>(this);
hr = pT->FillData(pformatetc->cfFormat, pStream);
pStream->Release();
}
}

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"));
}
};


template <class T, class C>
class ATL_NO_VTABLE IComponentDataImpl : public IComponentData
{
public :
CComQIPtr<IConsoleNameSpace, &IID_IConsoleNameSpace> m_spConsoleNameSpace;
CComQIPtr<IConsole, &IID_IConsole> m_spConsole;

STDMETHOD(Initialize)(LPUNKNOWN pUnknown)
{
ATLTRACE(_T("IComponentDataImpl::Initialize\n"));

if (pUnknown == NULL)
{
ATLTRACE(_T("IComponentData::Initialize called with pUnknown == NULL\n"));
return E_UNEXPECTED;
}

m_spConsoleNameSpace = pUnknown;
if (m_spConsoleNameSpace == NULL)
{
ATLTRACE(_T("QI for IConsoleNameSpace failed\n"));
return E_UNEXPECTED;
}

m_spConsole = pUnknown;
if (m_spConsole == NULL)
{
ATLTRACE(_T("QI for IConsole failed\n"));
return E_UNEXPECTED;
}

return S_OK;
}

STDMETHOD(CreateComponent)(LPCOMPONENT *ppComponent)
{
ATLTRACE(_T("IComponentDataImpl::CreateComponent\n"));
if (ppComponent == NULL)
{
ATLTRACE(_T("IComponentData::CreateComponent called with ppComponent == NULL\n"));
return E_UNEXPECTED;
}

*ppComponent = NULL;

CComObject< C >* pComponent;
HRESULT hr = CComObject< C >::CreateInstance(&pComponent);
if (FAILED(hr))
{
ATLTRACE(_T("IComponentData::CreateComponent : Could not create IComponent object\n"));
return hr;
}

return pComponent->QueryInterface(IID_IComponent, (void**)ppComponent);
}


STDMETHOD(Notify)(
LPDATAOBJECT lpDataObject,
MMC_NOTIFY_TYPE event,
long arg,
long param)
{
ATLTRACE(_T("IComponentDataImpl::Notify\n"));
if (lpDataObject == NULL)
{
ATLTRACE(_T("IComponentData::Notify called with lpDataObject == NULL\n"));
return E_UNEXPECTED;
}

CComQIPtr<ISnapInDataInterface, &IID_ISnapInDataInterface> spData(lpDataObject);
if (spData == NULL)
{
ATLTRACE(_T("QI for ISnapInDataInterface failed\n"));
return E_UNEXPECTED;
}
return spData->Notify(event, arg, param, TRUE, m_spConsole, NULL, NULL);
}

STDMETHOD(Destroy)(void)
{
ATLTRACE(_T("IComponentDataImpl::Destroy\n"));

m_spNode.Release();
m_spConsole.Release();
m_spConsoleNameSpace.Release();
return S_OK;
}

STDMETHOD(QueryDataObject)(long cookie,
DATA_OBJECT_TYPES type,
LPDATAOBJECT *ppDataObject)
{
ATLTRACE(_T("IComponentDataImpl::QueryDataObject\n"));
_ASSERTE(m_spNode != NULL);

if (ppDataObject == NULL)
{
ATLTRACE(_T("IComponentData::QueryDataObject called with ppDataObject == NULL\n"));
return E_UNEXPECTED;
}

*ppDataObject = NULL;

if (cookie == NULL)
return m_spNode->QueryInterface(IID_IDataObject, (void**)(ppDataObject));

IUnknown* pUnk = (IUnknown*) cookie;
return pUnk->QueryInterface(IID_IDataObject, (void**)(ppDataObject));
}

STDMETHOD(GetDisplayInfo)(SCOPEDATAITEM *pScopeDataItem)
{
ATLTRACE(_T("IComponentDataImpl::GetDisplayInfo\n"));

if (pScopeDataItem == NULL)
{
ATLTRACE(_T("IComponentData::GetDisplayInfo called with pScopeDataItem == NULL\n"));
return E_UNEXPECTED;
}

IUnknown* pUnk = (IUnknown*) pScopeDataItem->lParam;
if (pUnk == NULL)
pUnk = m_spNode;

CComQIPtr<ISnapInDataInterface, &IID_ISnapInDataInterface> spData(pUnk);
if (spData == NULL)
{
ATLTRACE(_T("QI for ISnapInDataInterface failed\n"));
return E_UNEXPECTED;
}
return spData->GetDispInfo(pScopeDataItem);
}

STDMETHOD(CompareObjects)(LPDATAOBJECT lpDataObjectA,
LPDATAOBJECT lpDataObjectB)
{
ATLTRACENOTIMPL(_T("IComponentDataImpl::CompareObjects\n"));
return S_FALSE;
}

protected:
CComPtr<IUnknown> m_spNode;
};

template <class T>
class ATL_NO_VTABLE IComponentImpl : public IComponent
{
public:
//Review all of these may not be required
CComPtr<IConsole> m_spConsole;
CComQIPtr<IHeaderCtrl, &IID_IHeaderCtrl> m_spHeaderCtrl;
CComPtr<IImageList> m_spImageList;
CComPtr<IConsoleVerb> m_spConsoleVerb;

STDMETHOD(Initialize)(LPCONSOLE lpConsole)
{
ATLTRACE(_T("IComponentImpl::Initialize\n"));

if (lpConsole == NULL)
{
ATLTRACE(_T("lpConsole is NULL\n"));
return E_UNEXPECTED;
}

m_spConsole = lpConsole;

m_spHeaderCtrl = lpConsole;
if (m_spHeaderCtrl == NULL)
{
ATLTRACE(_T("QI for IHeaderCtrl failed\n"));
return E_UNEXPECTED;
}

HRESULT hr = m_spConsole->SetHeader(m_spHeaderCtrl);
if (FAILED(hr))
{
ATLTRACE(_T("IConsole::SetHeader failed (HRESULT = %x)\n"), hr);
return hr;
}

hr = lpConsole->QueryResultImageList(&m_spImageList);
if (FAILED(hr))
{
ATLTRACE(_T("IConsole::QueryResultImageList failed (HRESULT = %x)\n"), hr);
return hr;
}

lpConsole->QueryConsoleVerb(&m_spConsoleVerb) ;
if (FAILED(hr))
{
ATLTRACE(_T("IConsole::QueryConsoleVerb failed (HRESULT = %x)\n"), hr);
return hr;
}

return S_OK;
}

STDMETHOD(Notify)(LPDATAOBJECT lpDataObject,
MMC_NOTIFY_TYPE event,
long arg,
long param)
{
ATLTRACE(_T("IComponentImpl::Notify\n"));
if (lpDataObject == NULL)
{
ATLTRACE(_T("IComponent::Notify called with lpDataObject==NULL \n"));
return E_UNEXPECTED;
}

CComQIPtr<ISnapInDataInterface, &IID_ISnapInDataInterface> spData(lpDataObject);
if (spData == NULL)
{
ATLTRACE(_T("QI for ISnapInDataInterface failed\n"));
return E_UNEXPECTED;
}
return spData->Notify(event, arg, param, FALSE, m_spConsole, m_spHeaderCtrl, NULL);
}

STDMETHOD(Destroy)(long cookie)
{
ATLTRACE(_T("IComponentImpl::Destroy\n"));

m_spConsoleVerb = NULL;
m_spImageList = NULL;
m_spHeaderCtrl.Release();
m_spConsole.Release();

return S_OK;
}

STDMETHOD(QueryDataObject)(long cookie,
DATA_OBJECT_TYPES type,
LPDATAOBJECT *ppDataObject)
{
ATLTRACE(_T("IComponentImpl::QueryDataObject\n"));

if (ppDataObject == NULL)
{
ATLTRACE(_T("IComponent::QueryDataObject called with ppDataObject==NULL \n"));
return E_UNEXPECTED;
}

if (cookie == NULL)
{
ATLTRACE(_T("IComponent::QueryDataObject called with cookie==NULL \n"));
return E_UNEXPECTED;
}

*ppDataObject = NULL;

IUnknown* pUnk = (IUnknown *) cookie;
return pUnk->QueryInterface(IID_IDataObject, (void**)ppDataObject);
}

STDMETHOD(GetResultViewType)(long cookie,
LPOLESTR *ppViewType,
long *pViewOptions)
{
ATLTRACE(_T("IComponentImpl::GetResultViewType\n"));

if (cookie == NULL)
{
*ppViewType = NULL;
*pViewOptions = MMC_VIEW_OPTIONS_NONE;
return S_OK;
}

CComQIPtr<ISnapInDataInterface, &IID_ISnapInDataInterface> spData((IUnknown*)cookie);
return spData->GetResultViewType(ppViewType, pViewOptions);
}

STDMETHOD(GetDisplayInfo)(RESULTDATAITEM *pResultDataItem)
{
ATLTRACE(_T("IComponentImpl::GetDisplayInfo\n"));
if (pResultDataItem == NULL)
{
ATLTRACE(_T("IComponent::GetDisplayInfo called with pResultDataItem==NULL\n"));
return E_UNEXPECTED;
}

IUnknown* pUnk = (IUnknown*) pResultDataItem->lParam;
if (pUnk == NULL)
return E_UNEXPECTED;

CComQIPtr<ISnapInDataInterface, &IID_ISnapInDataInterface> spData(pUnk);
if (spData == NULL)
{
ATLTRACE(_T("QI for ISnapInDataInterface failed\n"));
return E_UNEXPECTED;
}
return spData->GetDisplayInfo(pResultDataItem);
}

STDMETHOD(CompareObjects)( LPDATAOBJECT lpDataObjectA,
LPDATAOBJECT lpDataObjectB)
{
ATLTRACENOTIMPL(_T("IComponentImpl::CompareObjects\n"));
}
};

template <class T, class D>
class ATL_NO_VTABLE IResultDataCompareImpl : public IResultDataCompare
{
public:
STDMETHOD(Compare)(long lUserParam,
long cookieA,
long cookieB,
int *pnResult)
{
ATLTRACENOTIMPL(_T("IResultDataCompareImpl::Compare"));
}
};


template <class T>
class ATL_NO_VTABLE IExtendContextMenuImpl : public IExtendContextMenu
{
public:
STDMETHOD(AddMenuItems)(LPDATAOBJECT piDataObject,
LPCONTEXTMENUCALLBACK piCallback,
long *pInsertionAllowed)
{
ATLTRACE(_T("IExtendContextMenuImpl::AddMenuItems\n"));
if (piDataObject == NULL)
{
ATLTRACE(_T("IExtendContextMenu::AddMenuItems called with piDataObject==NULL\n"));
return E_UNEXPECTED;
}
CComQIPtr<ISnapInDataInterface, &IID_ISnapInDataInterface> spData(piDataObject);
if (spData == NULL)
{
ATLTRACE(_T("QI for ISnapInDataInterface failed\n"));
return E_UNEXPECTED;
}
return spData->AddMenuItems(piCallback, pInsertionAllowed);
}

STDMETHOD(Command)(long lCommandID,
LPDATAOBJECT piDataObject)
{
ATLTRACE(_T("IExtendContextMenuImpl::Command\n"));
if (piDataObject == NULL)
{
ATLTRACE(_T("IExtendContextMenu::Command called with piDataObject==NULL\n"));
return E_UNEXPECTED;
}
CComQIPtr<ISnapInDataInterface, &IID_ISnapInDataInterface> spData(piDataObject);
if (spData == NULL)
{
ATLTRACE(_T("QI for ISnapInDataInterface failed\n"));
return E_UNEXPECTED;
}
return spData->Command(lCommandID);
}
};

template<class T>
class ATL_NO_VTABLE IExtendPropertySheetImpl : public IExtendPropertySheet
{
public:
STDMETHOD(CreatePropertyPages)(LPPROPERTYSHEETCALLBACK lpProvider,

long handle, 
LPDATAOBJECT lpIDataObject)
{
ATLTRACE(_T("IExtendPropertySheetImpl::CreatePropertyPages\n"));
if (lpIDataObject == NULL)
{
ATLTRACE(_T("IExtendPropertySheetImpl::CreatePropertyPages called with lpIDataObject==NULL\n"));
return E_UNEXPECTED;
}
CComQIPtr<ISnapInDataInterface, &IID_ISnapInDataInterface> spData(lpIDataObject);
if (spData == NULL)
{
ATLTRACE(_T("QI for ISnapInDataInterface failed\n"));
return E_UNEXPECTED;
}
return spData->CreatePropertyPages(lpProvider, handle, this);
}

STDMETHOD(QueryPagesFor)(LPDATAOBJECT lpDataObject)
{
ATLTRACE(_T("IExtendPropertySheetImpl::QueryPagesFor\n"));
if (lpDataObject == NULL)
{
ATLTRACE(_T("IExtendPropertySheetImpl::QueryPagesFor called with lpDataObject==NULL\n"));
return E_UNEXPECTED;
}
CComQIPtr<ISnapInDataInterface, &IID_ISnapInDataInterface> spData(lpDataObject);
if (spData == NULL)
{
ATLTRACE(_T("QI for ISnapInDataInterface failed\n"));
return E_UNEXPECTED;
}
return spData->QueryPagesFor();
}
};

template <class T>
class ATL_NO_VTABLE IExtendControlbarImpl : public IExtendControlbar
{
CComPtr <IControlbar> m_spControlbar;
public:
STDMETHOD(SetControlbar)(LPCONTROLBAR pControlbar)
{
ATLTRACE(_T("IExtendControlbarImpl::SetControlbar\n"));
if (pControlbar == NULL)
{
ATLTRACE(_T("IExtendControlbar::SetControlbar called with pControlbar==NULL\n"));
return E_UNEXPECTED;
}
m_spControlbar = pControlbar;
return S_OK;
}

STDMETHOD(ControlbarNotify)(MMC_NOTIFY_TYPE event,
long arg,
long param)
{
ATLTRACE(_T("IExtendControlbarImpl::ControlbarNotify\n"));
CComQIPtr<ISnapInDataInterface, &IID_ISnapInDataInterface> spData;
if (event == MMCN_BTN_CLICK)
{
spData = ((IDataObject*) arg);
}
else if (event == MMCN_SELECT)
{
BOOL bScope = (BOOL) LOWORD(arg);
if (bScope)
{
LPDATAOBJECT* ppDataobject = (LPDATAOBJECT*) param;
if (ppDataobject[0])
{
spData = ppDataobject[0];
if (spData != NULL)
spData->ControlbarNotify(m_spControlbar, this, event, arg, param);
}

if (ppDataobject[1])
{
spData = ppDataobject[1];
}
}
else
spData = (IDataObject*) param;
}
if (spData == NULL)
{
ATLTRACE(_T("QI for ISnapInDataInterface failed\n"));
return E_UNEXPECTED;
}
return spData->ControlbarNotify(m_spControlbar, this, event, arg, param);
}
};

template <class T>
class ATL_NO_VTABLE ISnapinAboutImpl : public ISnapinAbout
{
public:
STDMETHOD(GetSnapinDescription)(LPOLESTR *lpDescription)
{
ATLTRACENOTIMPL(_T("ISnapinAboutImpl::GetSnapinDescription\n"));
return S_OK;
}

STDMETHOD(GetProvider)(LPOLESTR *lpName)
{
ATLTRACENOTIMPL(_T("ISnapinAboutImpl::GetProvider\n"));
return S_OK;
}

STDMETHOD(GetSnapinVersion)(LPOLESTR *lpVersion)
{
ATLTRACENOTIMPL(_T("ISnapinAboutImpl::GetSnapinVersion\n"));
return S_OK;
}

STDMETHOD(GetSnapinImage)(HICON *hAppIcon)
{
ATLTRACENOTIMPL(_T("ISnapinAboutImpl::GetSnapinImage\n"));
return S_OK;
}

STDMETHOD(GetStaticFolderImage)(HBITMAP *hSmallImage,
HBITMAP *hSmallImageOpen,
HBITMAP *hLargeImage,
COLORREF *cMask)
{
ATLTRACENOTIMPL(_T("ISnapinAboutImpl::GetStaticFolderImage\n"));
return S_OK;
}
};

class CSnapInBaseData
{
public:
static const UINT m_CCF_NODETYPE;
static const UINT m_CCF_SZNODETYPE;
static const UINT m_CCF_DISPLAY_NAME;
static const UINT m_CCF_SNAPIN_CLASSID;
static const UINT m_CCF_SCOPEDATAITEM;
static const UINT m_CCF_RESULTDATAITEM;
CComDynamicUnkArray m_scopeonlyitems;
CComDynamicUnkArray m_resultonlyitems;
CComDynamicUnkArray* m_pParentList;
OLECHAR* m_pszDisplayName;

SCOPEDATAITEM m_scopeDataItem;
RESULTDATAITEM m_resultDataItem;
CSnapInBaseData()
{
m_pszDisplayName = NULL;

memset(&m_scopeDataItem, 0, sizeof(SCOPEDATAITEM));

m_scopeDataItem.mask = SDI_STR | SDI_IMAGE | SDI_OPENIMAGE | SDI_PARAM | SDI_PARENT;
m_scopeDataItem.displayname = MMC_CALLBACK;
m_scopeDataItem.nImage = 0;
m_scopeDataItem.nOpenImage = 1;

memset(&m_resultDataItem, 0, sizeof(RESULTDATAITEM));

m_resultDataItem.mask = RDI_STR | RDI_IMAGE | RDI_PARAM;
m_resultDataItem.str = MMC_CALLBACK;
m_resultDataItem.nImage = 2;

m_pParentList = NULL;
}

~CSnapInBaseData()
{
delete m_pszDisplayName;
m_pszDisplayName = NULL;
for (IUnknown** pp = m_scopeonlyitems.begin(); pp < m_scopeonlyitems.end(); pp++)
{
if (*pp)
{
IUnknown* pUnk = *pp;
m_scopeonlyitems.Remove((DWORD)*pp);
pUnk->Release();
}
}
for (pp = m_resultonlyitems.begin(); pp < m_resultonlyitems.end(); pp++)
{

if (*pp)
{
IUnknown* pUnk = *pp;
m_resultonlyitems.Remove((DWORD)*pp);
pUnk->Release();
}
}
}

void InitParentList(CComDynamicUnkArray* pParent)
{
m_pParentList = pParent;
}

};

#define SNAPINMENUID(id) \
public: \
static const UINT GetMenuID() \
{ \
static const UINT IDMENU = id; \
return id; \
}

#define BEGIN_SNAPINCOMMAND_MAP(theClass) \
typedef theClass _theClass; \
HRESULT ProcessCommand(UINT nID, IDataObject* pDataObject) \
{

#define PRIMARY_SNAPINCOMMAND_ENTRY(id, func) \
if (id == nID) \
return func();

#define PRIMARY_SNAPINCOMMAND_RANGE_ENTRY(id1, id2, func) \
if (id1 >= nID && nID <= id2) \
return func(nID);

#define EXTENSION_SNAPINCOMMAND_ENTRY(id, func) \
if (id == nID) \
return func(pDataObject);

#define EXTENSION_SNAPINCOMMAND_RANGE_ENTRY(id1, id2, func) \
if (id1 >= nID && nID <= id2) \
return func(nID, pDataObject);

#define END_SNAPINCOMMAND_MAP() \
return ISnapInDataInterfaceImpl< _theClass >::ProcessCommand(nID, pDataObject); \
}

struct CSnapInToolBarData
{
WORD wVersion;
WORD wWidth;
WORD wHeight;
WORD wItemCount;
//WORD aItems[wItemCount]

WORD* items()
{ return (WORD*)(this+1); }
};

#define RT_TOOLBAR MAKEINTRESOURCE(241)

struct CSnapInToolbarInfo
{
public:
TCHAR** m_pStrToolTip;
TCHAR** m_pStrButtonText;
UINT* m_pnButtonID;
UINT m_idToolbar;
UINT m_nButtonCount;
IToolbar* m_pToolbar;

~CSnapInToolbarInfo()
{
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;
if (m_pToolbar)
m_pToolbar->Release();
m_pToolbar = NULL;
}
};

#define BEGIN_SNAPINTOOLBARID_MAP(theClass) \
public: \
static CSnapInToolbarInfo* GetToolbarInfo() \
{ \
static CSnapInToolbarInfo m_toolbarInfo[] = \
{

#define SNAPINTOOLBARID_ENTRY(id) \
{ NULL, NULL, NULL, id, 0, NULL},

#define END_SNAPINTOOLBARID_MAP() \
{ NULL, NULL, NULL, 0, 0, NULL} \
}; \
return m_toolbarInfo; \
}

template <class T>
class ISnapInDataInterfaceImpl : public ISnapInDataInterface,
public CSnapInBaseData
{
public:
STDMETHOD(Notify)( MMC_NOTIFY_TYPE event,
long arg,
long param,
BOOL bComponentData,
IConsole* pConsole,
IHeaderCtrl* pHeader,
IToolbar* pToolbar)
{
ATLTRACE(_T("ISnapInDataInterfaceImpl::Notify"));
if (event == MMCN_RENAME)
{
T* pT = static_cast<T*>(this);
OLECHAR* pTemp = new OLECHAR[lstrlen((OLECHAR*)param) + 1];
if (pTemp == NULL)
return S_FALSE;
lstrcpy(pTemp, (OLECHAR*)param);
if (!pT->Rename(pTemp))
{
delete []pTemp;
return S_FALSE;
}

delete []m_pszDisplayName;
m_pszDisplayName = pTemp;
return S_OK;
}

if (event == MMCN_ADD_IMAGES)
{
CComPtr<IImageList> spImageList;
spImageList = (IImageList*)arg;

return S_OK;
}

if (event == MMCN_SHOW)
{
int n = 0;
CComQIPtr<IResultData, &IID_IResultData> spResultData(pConsole);
pHeader->InsertColumn(1, _T("File"), LVCFMT_LEFT, MMCLV_AUTO);
return EnumerateResultChildren(spResultData);
}

if (event == MMCN_EXPAND)
{
CComQIPtr<IConsoleNameSpace, &IID_IConsoleNameSpace> spConsoleNameSpace(pConsole);
return EnumerateScopeChildren(param, spConsoleNameSpace);
}

if (event == MMCN_SELECT)
{
CComPtr<IConsoleVerb> spVerb;
pConsole->QueryConsoleVerb(&spVerb) ;

spVerb->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, TRUE);
return S_OK;
}

return E_UNEXPECTED;
}

STDMETHOD(GetDispInfo)(SCOPEDATAITEM *pScopeDataItem)
{
ATLTRACE(_T("ISnapInDataInterfaceImpl::GetDispInfo"));
if (pScopeDataItem->mask & SDI_STR)
pScopeDataItem->displayname = m_pszDisplayName;
if (pScopeDataItem->mask & SDI_IMAGE)
pScopeDataItem->nImage = m_scopeDataItem.nImage;
if (pScopeDataItem->mask & SDI_OPENIMAGE)
pScopeDataItem->nOpenImage = m_scopeDataItem.nOpenImage;
if (pScopeDataItem->mask & SDI_CHILDREN)
pScopeDataItem->cChildren = m_scopeonlyitems.end() - m_scopeonlyitems.begin();
return S_OK;

}

STDMETHOD(GetResultViewType)(LPOLESTR *ppVIewType,
long *pViewOptions)
{
ATLTRACENOTIMPL(_T("ISnapInDataInterfaceImpl::GetResultViewType"));
}

STDMETHOD(GetDisplayInfo)(RESULTDATAITEM *pResultDataItem)
{
ATLTRACE(_T("ISnapInDataInterfaceImpl::GetDisplayInfo"));
T* pT = static_cast<T*> (this);

if (pResultDataItem->bScopeItem)
{
if (pResultDataItem->mask & RDI_STR)
{
pResultDataItem->str = pT->GetResultPaneInfo(pResultDataItem->nCol);
}
if (pResultDataItem->mask & RDI_IMAGE)
{
pResultDataItem->nImage = m_scopeDataItem.nImage;
}

return S_OK;
}
if (pResultDataItem->mask & RDI_STR)
{
pResultDataItem->str = pT->GetResultPaneInfo(pResultDataItem->nCol);
}
if (pResultDataItem->mask & RDI_IMAGE)
{
pResultDataItem->nImage = m_resultDataItem.nImage;
}
return S_OK;
}

STDMETHOD(AddMenuItems)(LPCONTEXTMENUCALLBACK piCallback,
long *pInsertionAllowed)
{
ATLTRACE(_T("ISnapInDataInterfaceImpl::AddMenuItems"));
long insertionID;
T* pT = static_cast<T*> (this);
UINT menuID = pT->GetMenuID();
if (menuID == 0)
return S_OK;
HMENU hMenu = LoadMenu(_Module.GetResourceInstance(), MAKEINTRESOURCE(menuID));
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;
insertionID = CCM_INSERTIONPOINTID_PRIMARY_NEW;
break;

case 2:;
if (! (*pInsertionAllowed & CCM_INSERTIONALLOWED_TASK) )
continue;
insertionID = CCM_INSERTIONPOINTID_PRIMARY_TASK;
break;
case 3:;
if (! (*pInsertionAllowed & CCM_INSERTIONALLOWED_VIEW) )
continue;
insertionID = CCM_INSERTIONPOINTID_PRIMARY_VIEW;
break;
default:
{
insertionID = 0;
continue;
// Review
// Determine what to do here.
menuItemInfo.fMask = MIIM_TYPE ;
menuItemInfo.fType = MFT_STRING;
TCHAR buf[128];
menuItemInfo.dwTypeData = buf;
menuItemInfo.cch = 128;
if (!GetMenuItemInfo(hMenu, i, TRUE, &menuItemInfo))
continue;
//insertionID = _ttol(buf);
}
break;
}

menuItemInfo.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID;
menuItemInfo.fType = MFT_STRING;
TCHAR buf[128];
menuItemInfo.dwTypeData = buf;

for (int j = 0; 1; j++)
{
menuItemInfo.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID;
menuItemInfo.fType = MFT_STRING;
menuItemInfo.cch = 128;
TCHAR strStatusBar[257];

if (!GetMenuItemInfo(hSubMenu, j, TRUE, &menuItemInfo))
break;

pT->UpdateMenuState(menuItemInfo.wID, buf, &menuItemInfo.fState);
LoadString(_Module.GetResourceInstance(), menuItemInfo.wID, strStatusBar, 257);

CONTEXTMENUITEM contextMenuItem;
memset(&contextMenuItem, 0, sizeof(contextMenuItem));
contextMenuItem.strName = buf;
contextMenuItem.strStatusBarText = strStatusBar;
contextMenuItem.lCommandID = menuItemInfo.wID;
contextMenuItem.lInsertionPointID = insertionID;
contextMenuItem.fFlags = menuItemInfo.fState;

piCallback->AddItem(&contextMenuItem);
}
}
DestroyMenu(hMenu);
}

return S_OK;
}

STDMETHOD(Command)(long lCommandID)
{
ATLTRACE(_T("ISnapInDataInterfaceImpl::Command\n"));
T* pT = static_cast<T*>(this);
return pT->ProcessCommand(lCommandID, NULL);
}

STDMETHOD(CreatePropertyPages)(LPPROPERTYSHEETCALLBACK lpProvider,
long handle, IUnknown* pUnk)
{
ATLTRACENOTIMPL(_T("ISnapInDataInterfaceImpl::CreatePropertyPages"));
}

STDMETHOD(QueryPagesFor)(void)
{
ATLTRACENOTIMPL(_T("ISnapInDataInterfaceImpl::QueryPagesFor"));
}

STDMETHOD(SetControlbar)(IControlbar *pControlbar, IExtendControlbar* pExtendControlBar)
{
ATLTRACE(_T("ISnapInDataInterfaceImpl::SetControlbar\n"));
T* pT = static_cast<T*>(this);

CSnapInToolbarInfo* pInfo = pT->GetToolbarInfo();
if (pInfo == NULL)
return S_OK;

for( ; pInfo->m_idToolbar; pInfo++)
{
if (pInfo->m_pToolbar)
continue;

HBITMAP hBitmap = LoadBitmap(_Module.GetResourceInstance(), MAKEINTRESOURCE(pInfo->m_idToolbar));
if (hBitmap == NULL)
return S_OK;

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;
_ASSERTE(pData->wVersion == 1);

pInfo->m_nButtonCount = pData->wItemCount;
pInfo->m_pnButtonID = new UINT[pInfo->m_nButtonCount];
MMCBUTTON *pButtons = new MMCBUTTON[pData->wItemCount];

pInfo->m_pStrToolTip = new TCHAR* [pData->wItemCount];
if (pInfo->m_pStrToolTip == NULL)
continue;

for (int i = 0, j = 0; i < pData->wItemCount; i++)
{
pInfo->m_pStrToolTip[i] = NULL;
memset(&pButtons[i], 0, sizeof(MMCBUTTON));
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 strStatusBar[512];
LoadString(_Module.GetResourceInstance(), pButtons[i].idCommand, strStatusBar, 512);

pInfo->m_pStrToolTip[i] = new TCHAR[lstrlen(strStatusBar) + 1];
if (pInfo->m_pStrToolTip[i] == NULL)
continue;
lstrcpy(pInfo->m_pStrToolTip[i], strStatusBar);
pButtons[i].lpTooltipText = pInfo->m_pStrToolTip[i];
pButtons[i].lpButtonText = _T("");
pT->SetToolbarButtonInfo(pButtons[i].idCommand, &pButtons[i].fsState, &pButtons[i].fsType);
}
else
{
pButtons[i].lpTooltipText = _T("");
pButtons[i].lpButtonText = _T("");
pButtons[i].fsType = TBSTYLE_SEP;
}
}

HRESULT hr = pControlbar->Create(TOOLBAR, pExtendControlBar, reinterpret_cast<LPUNKNOWN*>(&pInfo->m_pToolbar));
if (FAILED(hr))
continue;

hr = pInfo->m_pToolbar->AddBitmap(pData->wItemCount, hBitmap, pData->wWidth, pData->wHeight, RGB(192, 192, 192));
if (FAILED(hr))
{
pInfo->m_pToolbar->Release();
pInfo->m_pToolbar = NULL;
continue;
}

hr = pInfo->m_pToolbar->AddButtons(pData->wItemCount, pButtons);
if (FAILED(hr))
{
pInfo->m_pToolbar->Release();
pInfo->m_pToolbar = NULL;
}

delete [] pButtons;
}
return S_OK;
}

STDMETHOD(ControlbarNotify)(IControlbar *pControlbar,
IExtendControlbar *pExtendControlbar,
MMC_NOTIFY_TYPE event,
long arg, long param)
{
ATLTRACE(_T("ISnapInDataInterfaceImpl::ControlbarNotify\n"));
T* pT = static_cast<T*>(this);
CComQIPtr<IDataObject, &IID_IDataObject> spData(this);

SetControlbar(pControlbar, pExtendControlbar);

if(event == MMCN_SELECT)
{
BOOL bScope = (BOOL) LOWORD(arg);
BOOL bSelect = (BOOL) HIWORD (arg);

if (!bScope)
{
CSnapInToolbarInfo* pInfo = pT->GetToolbarInfo();
if (pInfo == NULL)
return S_OK;

if (!bSelect)
return S_OK;

for(; pInfo->m_idToolbar; pInfo++)
{
for (UINT i = 0; i < pInfo->m_nButtonCount; i++)
{
if (pInfo->m_pnButtonID[i])
{
for (int j = ENABLED; j <= BUTTONPRESSED; j++)
{
pInfo->m_pToolbar->SetButtonState(pInfo->m_pnButtonID[i],
(MMC_BUTTON_STATE)j,
pT->UpdateToolbarButton(pInfo->m_pnButtonID[i], (MMC_BUTTON_STATE)j));
}
}
}
}
}
else
{
LPDATAOBJECT* pData = (LPDATAOBJECT*) param;
if (pData[0] == pData[1])
return S_OK;
if (spData == pData[0])
{
CSnapInToolbarInfo* pInfo = pT->GetToolbarInfo();
if (pInfo == NULL)
return S_OK;

for(; pInfo->m_idToolbar; pInfo++)
{
pControlbar->Detach(pInfo->m_pToolbar);
}
return S_OK;
}

CSnapInToolbarInfo* pInfo = pT->GetToolbarInfo();
if (pInfo == NULL)
return S_OK;

for(; pInfo->m_idToolbar; pInfo++)
{
pControlbar->Attach(TOOLBAR, pInfo->m_pToolbar);
for (UINT i = 0; i < pInfo->m_nButtonCount; i++)
{
if (pInfo->m_pnButtonID[i])
{
for (int j = ENABLED; j <= BUTTONPRESSED; j++)
{
pInfo->m_pToolbar->SetButtonState(pInfo->m_pnButtonID[i],
(MMC_BUTTON_STATE)j,
pT->UpdateToolbarButton(pInfo->m_pnButtonID[i], (MMC_BUTTON_STATE)j));
}
}
}
}
return S_OK;
}
}
return pT->ProcessCommand((UINT) param, NULL);
}

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

void UpdateMenuState(UINT id, LPTSTR pBuf, UINT *flags)
{
return;
}

void SetToolbarButtonInfo(UINT id, BYTE *fsState, BYTE *fsType)
{
*fsState = TBSTATE_ENABLED;
*fsType = TBSTYLE_BUTTON;
}

BOOL UpdateToolbarButton(UINT id, BYTE fsState)
{
if (fsState == ENABLED)
return TRUE;
return FALSE;
}

HRESULT ProcessCommand(UINT nID, IDataObject* pDataObject)
{
ATLTRACE(_T("No handler for item with ID %d\n"), nID);
return S_OK;
}

HRESULT 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(), (lstrlen((LPCTSTR)pT->GetSZNodeType()) + 1 )* sizeof(TCHAR), &uWritten);
return hr;
}

if (cf == m_CCF_DISPLAY_NAME)
{
hr = pStream->Write(pT->GetDisplayName(), (lstrlen((LPCTSTR)pT->GetDisplayName()) + 1) * sizeof(TCHAR), &uWritten);
return hr;
}

if (cf == m_CCF_SNAPIN_CLASSID)
{
hr = pStream->Write(pT->GetSnapInCLSID(), sizeof(CLSID), &uWritten);
return hr;
}

if (cf == m_CCF_SCOPEDATAITEM)
{
hr = pStream->Write(&m_scopeDataItem, sizeof(SCOPEDATAITEM), &uWritten);
return hr;
}

if (cf == m_CCF_RESULTDATAITEM)
{
hr = pStream->Write(&m_resultDataItem, sizeof(RESULTDATAITEM), &uWritten);
return hr;
}

return hr;
}
OLECHAR* GetResultPaneInfo(int nCol)
{
if (nCol == 0 && m_pszDisplayName)
return m_pszDisplayName;

return L"Override GetResultPaneInfo in your derived class";
}

void PopulateChildren()
{
return;
}

void AddScopeItem(IUnknown* p)
{
m_scopeonlyitems.Add(p);
}

void AddResultItem(IUnknown* p)
{
m_resultonlyitems.Add(p);
}

void RemoveScopeItem(IUnknown* p)
{
m_scopeonlyitems.Remove((DWORD)p);
}

void RemoveResultItem(IUnknown* p)
{
m_resultonlyitems.Remove((DWORD)p);
}

HRESULT EnumerateScopeChildren(long param, IConsoleNameSpace* pNameSpace)
{
T* pT = static_cast<T*>(this);

pT->PopulateChildren();

for (IUnknown** pp = m_scopeonlyitems.begin(); pp < m_scopeonlyitems.end(); pp++)
{
if (*pp == NULL)
continue;

CComQIPtr<ISnapInDataInterface, &IID_ISnapInDataInterface> pData(*pp);
if (pData == NULL)
continue;

SCOPEDATAITEM* pscopeData;
pData->GetScopeData(&pscopeData);

if (pscopeData == NULL)
continue;

pscopeData->relativeID = param;
HRESULT hr = pNameSpace->InsertItem(pscopeData);
if (FAILED(hr))
return hr;
}

return S_OK;
}

HRESULT EnumerateResultChildren(IResultData* pResultData)
{
T* pT = static_cast<T*>(this);

pT->PopulateChildren();

for (IUnknown** pp = m_resultonlyitems.begin(); pp < m_resultonlyitems.end(); pp++)
{
if (*pp == NULL)
continue;

CComQIPtr<ISnapInDataInterface, &IID_ISnapInDataInterface> pData(*pp);
if (pData == NULL)
continue;

RESULTDATAITEM* pResultDataItem;
pData->GetResultData(&pResultDataItem);

if (pResultDataItem == NULL)
continue;

HRESULT hr = pResultData->InsertItem(pResultDataItem);
if (FAILED(hr))
return hr;
}

return S_OK;
}

static CSnapInToolbarInfo* GetToolbarInfo()
{
return NULL;
}

static const UINT GetMenuID()
{
return 0;
}

ISnapInDataInterfaceImpl()
{
}

BOOL Rename(OLECHAR* pNewName)
{
return TRUE;
}

};


#endif //__ATL_SNAPIN_H__