home *** CD-ROM | disk | FTP | other *** search
/ Team Palmtops 7 / Palmtops_numero07.iso / WinCE / SDKWindowsCE / HandHeldPCPro30 / sdk.exe / Jupiter SDK / data1.cab / ATL / include / Atlsnap.h < prev    next >
Encoding:
C/C++ Source or Header  |  1999-02-19  |  39.4 KB  |  1,588 lines

  1. // This is a part of the Active Template Library.
  2. // Copyright (C) 1996-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Active Template Library Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Active Template Library product.
  10.  
  11. #ifndef __ATL_SNAPIN_H__
  12. #define __ATL_SNAPIN_H__
  13.  
  14. #ifndef UNICODE
  15. #error "Only Unicode builds supported"
  16. #endif
  17.  
  18. #include <mmc.h>
  19. #include <commctrl.h>
  20.  
  21. #pragma comment(lib, "mmc.lib")
  22. #pragma comment(lib, "comctl32.lib")
  23.  
  24. template <class T>
  25. class ATL_NO_VTABLE CSnapInPropertyPageImpl : public CDialogImplBase
  26. {
  27. public:
  28.     PROPSHEETPAGE m_psp;
  29.  
  30.     operator PROPSHEETPAGE*() { return &m_psp; }
  31.  
  32. // Construction
  33.     CSnapInPropertyPageImpl(LPCTSTR lpszTitle = NULL)
  34.     {
  35.         // initialize PROPSHEETPAGE struct
  36.         memset(&m_psp, 0, sizeof(PROPSHEETPAGE));
  37.         m_psp.dwSize = sizeof(PROPSHEETPAGE);
  38.         m_psp.dwFlags = PSP_USECALLBACK;
  39.         m_psp.hInstance = _Module.GetResourceInstance();
  40.         m_psp.pszTemplate = MAKEINTRESOURCE(T::IDD);
  41.         m_psp.pfnDlgProc = (DLGPROC)T::StartDialogProc;
  42.         m_psp.pfnCallback = T::PropPageCallback;
  43.         m_psp.lParam = (LPARAM)this;
  44.  
  45.         if(lpszTitle != NULL)
  46.         {
  47.             m_psp.pszTitle = lpszTitle;
  48.             m_psp.dwFlags |= PSP_USETITLE;
  49.         }
  50.     }
  51.  
  52.     static UINT CALLBACK PropPageCallback(HWND hWnd, UINT uMsg, LPPROPSHEETPAGE ppsp)
  53.     {
  54.         if(uMsg == PSPCB_CREATE)
  55.         {
  56.             ATLASSERT(hWnd == NULL);
  57.             CDialogImplBase* pPage = (CDialogImplBase*)ppsp->lParam;
  58.             _Module.AddCreateWndData(&pPage->m_thunk.cd, pPage);
  59.         }
  60.  
  61.         return 1;
  62.     }
  63.  
  64.     HPROPSHEETPAGE Create()
  65.     {
  66.         return ::CreatePropertySheetPage(&m_psp);
  67.     }
  68.  
  69.     BOOL EndDialog(int)
  70.     {
  71.         // do nothing here, calling ::EndDialog will close the whole sheet
  72.         ATLASSERT(FALSE);
  73.         return FALSE;
  74.     }
  75.  
  76. // Operations
  77.     void CancelToClose()
  78.     {
  79.         ATLASSERT(::IsWindow(m_hWnd));
  80.         ATLASSERT(GetParent() != NULL);
  81.  
  82.         ::SendMessage(GetParent(), PSM_CANCELTOCLOSE, 0, 0L);
  83.     }
  84.     void SetModified(BOOL bChanged = TRUE)
  85.     {
  86.         ATLASSERT(::IsWindow(m_hWnd));
  87.         ATLASSERT(GetParent() != NULL);
  88.  
  89.         if(bChanged)
  90.             ::SendMessage(GetParent(), PSM_CHANGED, (WPARAM)m_hWnd, 0L);
  91.         else
  92.             ::SendMessage(GetParent(), PSM_UNCHANGED, (WPARAM)m_hWnd, 0L);
  93.     }
  94.     LRESULT QuerySiblings(WPARAM wParam, LPARAM lParam)
  95.     {
  96.         ATLASSERT(::IsWindow(m_hWnd));
  97.         ATLASSERT(GetParent() != NULL);
  98.  
  99.         return ::SendMessage(GetParent(), PSM_QUERYSIBLINGS, wParam, lParam);
  100.     }
  101.  
  102.     BEGIN_MSG_MAP(CSnapInPropertyPageImpl< T >)
  103.         MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
  104.     END_MSG_MAP()
  105.  
  106. // Message handler
  107.     LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  108.     {
  109.         ATLASSERT(::IsWindow(m_hWnd));
  110.         NMHDR* pNMHDR = (NMHDR*)lParam;
  111.  
  112.         // don't handle messages not from the page/sheet itself
  113.         if(pNMHDR->hwndFrom != m_hWnd && pNMHDR->hwndFrom != ::GetParent(m_hWnd))
  114.         {
  115.             bHandled = FALSE;
  116.             return 1;
  117.         }
  118.  
  119.         T* pT = (T*)this;
  120.         LRESULT lResult = 0;
  121.         // handle default
  122.         switch(pNMHDR->code)
  123.         {
  124.         case PSN_SETACTIVE:
  125.             lResult = pT->OnSetActive() ? 0 : -1;
  126.             break;
  127.         case PSN_KILLACTIVE:
  128.             lResult = !pT->OnKillActive();
  129.             break;
  130.         case PSN_APPLY:
  131.             lResult = pT->OnApply() ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE;
  132.             break;
  133.         case PSN_RESET:
  134.             pT->OnReset();
  135.             break;
  136.         case PSN_QUERYCANCEL:
  137.             lResult = !pT->OnQueryCancel();
  138.             break;
  139.         case PSN_WIZNEXT:
  140.             lResult = !pT->OnWizardNext();
  141.             break;
  142.         case PSN_WIZBACK:
  143.             lResult = !pT->OnWizardBack();
  144.             break;
  145.         case PSN_WIZFINISH:
  146.             lResult = !pT->OnWizardFinish();
  147.             break;
  148.         case PSN_HELP:
  149.             lResult = pT->OnHelp();
  150.             break;
  151.         default:
  152.             bHandled = FALSE;    // not handled
  153.         }
  154.  
  155.         return lResult;
  156.     }
  157.  
  158. // Overridables
  159.     BOOL OnSetActive()
  160.     {
  161.         return TRUE;
  162.     }
  163.     BOOL OnKillActive()
  164.     {
  165.         return TRUE;
  166.     }
  167.     BOOL OnApply()
  168.     {
  169.         return TRUE;
  170.     }
  171.     void OnReset()
  172.     {
  173.     }
  174.     BOOL OnQueryCancel()
  175.     {
  176.         return TRUE;    // ok to cancel
  177.     }
  178.     BOOL OnWizardBack()
  179.     {
  180.         return TRUE;
  181.     }
  182.     BOOL OnWizardNext()
  183.     {
  184.         return TRUE;
  185.     }
  186.     BOOL OnWizardFinish()
  187.     {
  188.         return TRUE;
  189.     }
  190.     BOOL OnHelp()
  191.     {
  192.         return TRUE;
  193.     }
  194. };
  195.  
  196. class CSnapInItem;
  197.  
  198. class CObjectData
  199. {
  200. public:
  201.     CSnapInItem* m_pItem;
  202.     DATA_OBJECT_TYPES m_type;
  203. };
  204.  
  205. class ATL_NO_VTABLE CSnapInItem 
  206. {
  207. public:
  208.     virtual ~CSnapInItem()
  209.     {
  210.     }
  211.     STDMETHOD(Notify)(MMC_NOTIFY_TYPE event,
  212.         long arg,
  213.         long param,
  214.         IComponentData* pComponentData,
  215.         IComponent* pComponent,
  216.         DATA_OBJECT_TYPES type) = 0;
  217.     
  218.     STDMETHOD(GetScopePaneInfo)(SCOPEDATAITEM  *pScopeDataItem) = 0;
  219.     
  220.     STDMETHOD(GetResultViewType)(LPOLESTR  *ppViewType,
  221.         long  *pViewOptions) = 0;
  222.     
  223.     STDMETHOD(GetResultPaneInfo)(RESULTDATAITEM  *pResultDataItem) = 0;
  224.     
  225.     STDMETHOD(AddMenuItems)(LPCONTEXTMENUCALLBACK piCallback,
  226.         long  *pInsertionAllowed,
  227.         DATA_OBJECT_TYPES type) = 0;
  228.     
  229.     STDMETHOD(Command)(long lCommandID,        
  230.         DATA_OBJECT_TYPES type) = 0;
  231.     
  232.     STDMETHOD(CreatePropertyPages)(LPPROPERTYSHEETCALLBACK lpProvider,
  233.         long handle,
  234.         IUnknown* pUnk,
  235.         DATA_OBJECT_TYPES type) = 0;
  236.     
  237.     STDMETHOD(QueryPagesFor)(DATA_OBJECT_TYPES type) = 0;
  238.     
  239.     STDMETHOD(SetControlbar)(IControlbar  *pControlbar,
  240.         IExtendControlbar  *pExtendControlbar,
  241.         CSimpleMap<UINT, IUnknown*>* pToolbarMap) = 0;
  242.     
  243.     STDMETHOD(ControlbarNotify)(IControlbar  *pControlbar,
  244.         IExtendControlbar  *pExtendControlbar,
  245.         CSimpleMap<UINT, IUnknown*>* pToolbarMap,
  246.         MMC_NOTIFY_TYPE event,
  247.         long arg,
  248.         long param,
  249.         DATA_OBJECT_TYPES type) = 0;
  250.     
  251.     STDMETHOD(GetScopeData)(SCOPEDATAITEM  * *pScopeDataItem) = 0;
  252.     
  253.     STDMETHOD(GetResultData)(RESULTDATAITEM  * *pResultDataItem) = 0;
  254.  
  255.     STDMETHOD(FillData)(CLIPFORMAT cf, 
  256.         LPSTREAM pStream) = 0;
  257.  
  258.     virtual void InitDataClass(IDataObject* pDataObject, CSnapInItem* pDefault)
  259.     {
  260.         _ASSERTE(0 && "Override this function in derived class");
  261.     }
  262.  
  263.     static HRESULT GetDataClass(IDataObject* pDataObj, CSnapInItem** ppItem, DATA_OBJECT_TYPES* pType)
  264.     {
  265.         if (ppItem == NULL)
  266.             return E_POINTER;
  267.         if (pType == NULL)
  268.             return E_POINTER;
  269.  
  270.         *ppItem = NULL;
  271.         *pType = CCT_UNINITIALIZED;
  272.  
  273.         STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL };
  274.         FORMATETC formatetc = { m_CCF_SNAPIN_GETOBJECTDATA, 
  275.             NULL, 
  276.             DVASPECT_CONTENT, 
  277.             -1, 
  278.             TYMED_HGLOBAL 
  279.         };
  280.  
  281.         stgmedium.hGlobal = GlobalAlloc(0, sizeof(CObjectData));
  282.         if (stgmedium.hGlobal == NULL)
  283.             return E_OUTOFMEMORY;
  284.  
  285.         HRESULT hr = pDataObj->GetDataHere(&formatetc, &stgmedium);
  286.         if (SUCCEEDED(hr))
  287.         {
  288.             CObjectData* pData = (CObjectData*)stgmedium.hGlobal;
  289.              *ppItem = pData->m_pItem;
  290.              *pType = pData->m_type;
  291.         }
  292.         
  293.         GlobalFree(stgmedium.hGlobal);
  294.         
  295.         return hr;
  296.     }
  297.  
  298.  
  299.     virtual HRESULT STDMETHODCALLTYPE GetDataObject(IDataObject** pDataObj, DATA_OBJECT_TYPES type) = 0;
  300.  
  301.     static void Init()
  302.     {
  303.         m_CCF_NODETYPE            = (CLIPFORMAT) RegisterClipboardFormat(_T("CCF_NODETYPE"));
  304.         m_CCF_SZNODETYPE        = (CLIPFORMAT) RegisterClipboardFormat(_T("CCF_SZNODETYPE"));  
  305.         m_CCF_DISPLAY_NAME        = (CLIPFORMAT) RegisterClipboardFormat(_T("CCF_DISPLAY_NAME")); 
  306.         m_CCF_SNAPIN_CLASSID    = (CLIPFORMAT) RegisterClipboardFormat(_T("CCF_SNAPIN_CLASSID"));
  307.         m_CCF_SNAPIN_GETOBJECTDATA    = (CLIPFORMAT) RegisterClipboardFormat(_T("CCF_GETOBJECTDATA"));
  308.     }
  309. public:
  310.     static CLIPFORMAT m_CCF_NODETYPE;
  311.     static CLIPFORMAT m_CCF_SZNODETYPE;
  312.     static CLIPFORMAT m_CCF_DISPLAY_NAME;
  313.     static CLIPFORMAT m_CCF_SNAPIN_CLASSID;
  314.     static CLIPFORMAT m_CCF_SNAPIN_GETOBJECTDATA;
  315. };
  316.  
  317. class CSnapInObjectRoot
  318. {
  319. public:
  320.     CComPtr <IControlbar> m_spControlbar;
  321.     CSimpleMap <UINT, IUnknown*> m_toolbarMap;
  322.  
  323.     HRESULT GetDataClass(IDataObject* pDataObject, CSnapInItem** ppItem, DATA_OBJECT_TYPES* pType)
  324.     {
  325.         return CSnapInItem::GetDataClass(pDataObject, ppItem, pType);
  326.     }
  327. };
  328.  
  329. #define EXTENSION_SNAPIN_DATACLASS(dataClass) dataClass m_##dataClass;
  330.  
  331. #define BEGIN_EXTENSION_SNAPIN_NODEINFO_MAP(classname) \
  332.     HRESULT GetDataClass(IDataObject* pDataObject, CSnapInItem** ppItem, DATA_OBJECT_TYPES* pType) \
  333.     { \
  334.         if (ppItem == NULL) \
  335.             return E_POINTER; \
  336.         if (pType == NULL) \
  337.             return E_POINTER; \
  338. \
  339.         *ppItem = NULL; \
  340. \
  341.         *pType = CCT_UNINITIALIZED; \
  342. \
  343.         STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL }; \
  344.         FORMATETC formatetc = { CSnapInItem::m_CCF_NODETYPE, \
  345.             NULL, \
  346.             DVASPECT_CONTENT, \
  347.             -1, \
  348.             TYMED_HGLOBAL \
  349.         }; \
  350. \
  351.         stgmedium.hGlobal = GlobalAlloc(0, sizeof(GUID)); \
  352.         if (stgmedium.hGlobal == NULL) \
  353.             return E_OUTOFMEMORY; \
  354. \
  355.         HRESULT hr = pDataObject->GetDataHere(&formatetc, &stgmedium); \
  356.         if (FAILED(hr)) \
  357.         { \
  358.             GlobalFree(stgmedium.hGlobal); \
  359.             return hr; \
  360.         } \
  361. \
  362.         GUID guid; \
  363.         memcpy(&guid, stgmedium.hGlobal, sizeof(GUID)); \
  364. \
  365.         GlobalFree(stgmedium.hGlobal); \
  366.         hr = S_OK;
  367.  
  368. #define EXTENSION_SNAPIN_NODEINFO_ENTRY(dataClass) \
  369.         if (IsEqualGUID(guid, *(GUID*)m_##dataClass.GetNodeType())) \
  370.         { \
  371.             *ppItem = m_##dataClass.GetExtNodeObject(pDataObject, &m_##dataClass); \
  372.             _ASSERTE(*ppItem != NULL); \
  373.             (*ppItem)->InitDataClass(pDataObject, &m_##dataClass); \
  374.             return hr; \
  375.         }
  376.  
  377. #define END_EXTENSION_SNAPIN_NODEINFO_MAP() \
  378.             return CSnapInItem::GetDataClass(pDataObject, ppItem, pType); \
  379.     };
  380.  
  381. class ATL_NO_VTABLE CSnapInDataObjectImpl : public IDataObject,
  382.     public CComObjectRoot
  383. {
  384. public:
  385.     BEGIN_COM_MAP(CSnapInDataObjectImpl)
  386.         COM_INTERFACE_ENTRY(IDataObject)
  387.     END_COM_MAP()
  388.     STDMETHOD(GetData)(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
  389.     {
  390.         ATLTRACENOTIMPL(_T("SnapInDataObjectImpl::GetData\n"));
  391.     }
  392.  
  393.     STDMETHOD(GetDataHere)(FORMATETC* pformatetc, STGMEDIUM* pmedium)
  394.     {
  395.         ATLTRACE2(atlTraceSnapin, 0, _T("SnapInDataObjectImpl::GetDataHere\n"));
  396.         if (pmedium == NULL)
  397.             return E_POINTER;
  398.  
  399.         HRESULT hr = DV_E_TYMED;
  400.         // Make sure the type medium is HGLOBAL
  401.         if (pmedium->tymed == TYMED_HGLOBAL)
  402.         {
  403.             // Create the stream on the hGlobal passed in
  404.             CComPtr<IStream> spStream;
  405.             hr = CreateStreamOnHGlobal(pmedium->hGlobal, FALSE, &spStream);
  406.             if (SUCCEEDED(hr))
  407.                 if (pformatetc->cfFormat == CSnapInItem::m_CCF_SNAPIN_GETOBJECTDATA)
  408.                 {
  409.                     hr = DV_E_CLIPFORMAT;
  410.                     ULONG uWritten;
  411.                     hr = spStream->Write(&m_objectData, sizeof(CObjectData), &uWritten);
  412.                 }
  413.                 else
  414.                     hr = m_objectData.m_pItem->FillData(pformatetc->cfFormat, spStream);
  415.         }
  416.         return hr;
  417.     }
  418.  
  419.     STDMETHOD(QueryGetData)(FORMATETC* /* pformatetc */)
  420.     {
  421.         ATLTRACENOTIMPL(_T("SnapInDataObjectImpl::QueryGetData\n"));
  422.     }
  423.     STDMETHOD(GetCanonicalFormatEtc)(FORMATETC* /* pformatectIn */,FORMATETC* /* pformatetcOut */)
  424.     {
  425.         ATLTRACENOTIMPL(_T("SnapInDataObjectImpl::GetCanonicalFormatEtc\n"));
  426.     }
  427.     STDMETHOD(SetData)(FORMATETC* /* pformatetc */, STGMEDIUM* /* pmedium */, BOOL /* fRelease */)
  428.     {
  429.         ATLTRACENOTIMPL(_T("SnapInDataObjectImpl::SetData\n"));
  430.     }
  431.     STDMETHOD(EnumFormatEtc)(DWORD /* dwDirection */, IEnumFORMATETC** /* ppenumFormatEtc */)
  432.     {
  433.         ATLTRACENOTIMPL(_T("SnapInDataObjectImpl::EnumFormatEtc\n"));
  434.     }
  435.     STDMETHOD(DAdvise)(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink,
  436.         DWORD *pdwConnection)
  437.     {
  438.         ATLTRACENOTIMPL(_T("SnapInDataObjectImpl::SetData\n"));
  439.     }
  440.     STDMETHOD(DUnadvise)(DWORD dwConnection)
  441.     {
  442.         ATLTRACENOTIMPL(_T("SnapInDataObjectImpl::SetDatan\n"));
  443.     }
  444.     STDMETHOD(EnumDAdvise)(IEnumSTATDATA **ppenumAdvise)
  445.     {
  446.         ATLTRACENOTIMPL(_T("SnapInDataObjectImpl::SetData\n"));
  447.     }
  448.  
  449.     CObjectData m_objectData;
  450. };
  451.  
  452.  
  453. template <class T, class Component>
  454. class ATL_NO_VTABLE IComponentDataImpl : public IComponentData 
  455. {
  456. public :
  457.     IComponentDataImpl()
  458.     {
  459.         m_pNode = NULL;
  460.     }
  461.  
  462.     STDMETHOD(Initialize)(LPUNKNOWN pUnknown)
  463.     {
  464.         ATLTRACE2(atlTraceSnapin, 0, _T("IComponentDataImpl::Initialize\n"));
  465.  
  466.         HRESULT hr = E_POINTER;
  467.  
  468.         ATLASSERT(pUnknown != NULL);
  469.         if (pUnknown == NULL)
  470.             ATLTRACE2(atlTraceSnapin, 0, _T("IComponentData::Initialize called with pUnknown == NULL\n"));
  471.         else
  472.         {
  473.             hr = pUnknown->QueryInterface(&m_spConsole);
  474.             if (FAILED(hr))
  475.             {
  476.                 ATLTRACE2(atlTraceSnapin, 0, _T("QI for IConsole failed\n"));
  477.                 hr = E_UNEXPECTED;
  478.             }
  479.         }
  480.  
  481.         return hr;
  482.     }
  483.  
  484.     STDMETHOD(CreateComponent)(LPCOMPONENT *ppComponent)
  485.     {
  486.         ATLTRACE2(atlTraceSnapin, 0, _T("IComponentDataImpl::CreateComponent\n"));
  487.  
  488.         HRESULT hr = E_POINTER;
  489.  
  490.         ATLASSERT(ppComponent != NULL);
  491.         if (ppComponent == NULL)
  492.             ATLTRACE2(atlTraceSnapin, 0, _T("IComponentData::CreateComponent called with ppComponent == NULL\n"));
  493.         else
  494.         {
  495.             *ppComponent = NULL;
  496.             
  497.             CComObject< Component >* pComponent;
  498.             hr = CComObject< Component >::CreateInstance(&pComponent);
  499.             ATLASSERT(SUCCEEDED(hr));
  500.             if (FAILED(hr))
  501.                 ATLTRACE2(atlTraceSnapin, 0, _T("IComponentData::CreateComponent : Could not create IComponent object\n"));
  502.             else            
  503.                 hr = pComponent->QueryInterface(IID_IComponent, (void**)ppComponent);
  504.         }
  505.         return hr;
  506.     }
  507.  
  508.     
  509.     STDMETHOD(Notify)( 
  510.         LPDATAOBJECT lpDataObject,
  511.         MMC_NOTIFY_TYPE event,
  512.         long arg,
  513.         long param)
  514.     {
  515.         ATLTRACE2(atlTraceSnapin, 0, _T("IComponentDataImpl::Notify\n"));
  516.  
  517.         HRESULT hr = E_POINTER;
  518.  
  519.         ATLASSERT(lpDataObject != NULL);
  520.         if (lpDataObject == NULL)
  521.             ATLTRACE2(atlTraceSnapin, 0, _T("IComponentData::Notify called with lpDataObject == NULL\n"));
  522.         else
  523.         {
  524.             T* pT = static_cast<T*>(this);
  525.             CSnapInItem* pItem;
  526.             DATA_OBJECT_TYPES type;
  527.             hr = pT->GetDataClass(lpDataObject, &pItem, &type);
  528.             ATLASSERT(SUCCEEDED(hr));
  529.             if (SUCCEEDED(hr))
  530.                 hr = pItem->Notify(event, arg, param, pT, NULL, type);
  531.         }
  532.         return hr;
  533.     }
  534.  
  535.     STDMETHOD(Destroy)(void)
  536.     {
  537.         ATLTRACE2(atlTraceSnapin, 0, _T("IComponentDataImpl::Destroy\n"));
  538.  
  539.         T* pT = static_cast<T*>(this);
  540.         if (pT->m_spControlbar != NULL)
  541.         {
  542.             int n = pT->m_toolbarMap.GetSize();
  543.             for (int i = 0; i < n; i++)
  544.             {
  545.                 IToolbar* pToolbar = (IToolbar*)pT->m_toolbarMap.GetValueAt(i);
  546.                  if (pToolbar != NULL)
  547.                  {
  548.                     pT->m_spControlbar->Detach(pToolbar);
  549.                     pToolbar->Release();
  550.                  }
  551.             }
  552.         }
  553.         pT->m_toolbarMap.RemoveAll();
  554.  
  555.         m_spConsole.Release();
  556.         return S_OK;
  557.     }
  558.  
  559.     STDMETHOD(QueryDataObject)(long cookie,
  560.         DATA_OBJECT_TYPES type,
  561.         LPDATAOBJECT  *ppDataObject)
  562.     {
  563.         ATLTRACE2(atlTraceSnapin, 0, _T("IComponentDataImpl::QueryDataObject\n"));
  564.         ATLASSERT(m_pNode != NULL);
  565.  
  566.  
  567.         HRESULT hr = E_POINTER;
  568.         
  569.         ATLASSERT(ppDataObject != NULL);
  570.         if (ppDataObject == NULL)
  571.             ATLTRACE2(atlTraceSnapin, 0, _T("IComponentData::QueryDataObject called with ppDataObject == NULL\n"));
  572.         else
  573.         {
  574.             *ppDataObject = NULL;
  575.             
  576.             CSnapInItem* pItem = (CSnapInItem*) cookie;
  577.             if (cookie == NULL)
  578.                 pItem = m_pNode;
  579.  
  580.             hr = pItem->GetDataObject(ppDataObject, type);
  581.         }
  582.         return hr;
  583.     }
  584.     
  585.     STDMETHOD(GetDisplayInfo)(SCOPEDATAITEM *pScopeDataItem)
  586.     {
  587.         ATLTRACE2(atlTraceSnapin, 0, _T("IComponentDataImpl::GetDisplayInfo\n"));
  588.  
  589.  
  590.         HRESULT hr = E_POINTER;
  591.         
  592.         ATLASSERT(pScopeDataItem != NULL);
  593.         if (pScopeDataItem == NULL)
  594.             ATLTRACE2(atlTraceSnapin, 0, _T("IComponentData::GetDisplayInfo called with pScopeDataItem == NULL\n"));
  595.         else
  596.         {
  597.             CSnapInItem* pItem= (CSnapInItem*) pScopeDataItem->lParam;
  598.             if (pItem == NULL)
  599.                 pItem = m_pNode;
  600.  
  601.             hr = E_UNEXPECTED;
  602.             if (pItem != NULL)
  603.                 hr = pItem->GetScopePaneInfo(pScopeDataItem);
  604.         }
  605.         return hr;
  606.     }
  607.     
  608.     STDMETHOD(CompareObjects)(LPDATAOBJECT lpDataObjectA,
  609.         LPDATAOBJECT lpDataObjectB)
  610.     {
  611.         ATLTRACENOTIMPL(_T("IComponentDataImpl::CompareObjects\n"));
  612.     }
  613.  
  614.     CComPtr<IConsole> m_spConsole;
  615.  
  616.     protected:
  617.         CSnapInItem* m_pNode;
  618. };
  619.  
  620.  
  621. template <class T>
  622. class ATL_NO_VTABLE IComponentImpl : public IComponent
  623. {
  624. public:
  625.     STDMETHOD(Initialize)(LPCONSOLE lpConsole)
  626.     {
  627.         ATLTRACE2(atlTraceSnapin, 0, _T("IComponentImpl::Initialize\n"));
  628.  
  629.         HRESULT hr = E_POINTER;
  630.  
  631.         ATLASSERT(lpConsole != NULL);
  632.         if (lpConsole == NULL)
  633.             ATLTRACE2(atlTraceSnapin, 0, _T("lpConsole is NULL\n"));
  634.         else
  635.         {
  636.             m_spConsole = lpConsole;
  637.     
  638.             CComPtr<IHeaderCtrl> spHeaderCtrl;
  639.             hr = m_spConsole.QueryInterface(&spHeaderCtrl);
  640.             if (FAILED(hr))
  641.                 ATLTRACE2(atlTraceSnapin, 0, _T("QI for IHeaderCtrl failed\n"));
  642.             else
  643.             {
  644.                 hr = m_spConsole->SetHeader(spHeaderCtrl);
  645.                 if (FAILED(hr))
  646.                     ATLTRACE2(atlTraceSnapin, 0, _T("IConsole::SetHeader failed (HRESULT = %x)\n"), hr);
  647.             }
  648.         }
  649.         return hr;
  650.     }
  651.     
  652.     STDMETHOD(Notify)(LPDATAOBJECT lpDataObject,
  653.         MMC_NOTIFY_TYPE event,
  654.         long arg,
  655.         long param)
  656.     {
  657.         ATLTRACE2(atlTraceSnapin, 0, _T("IComponentImpl::Notify\n"));
  658.  
  659.  
  660.         HRESULT hr = E_POINTER;
  661.         
  662.         ATLASSERT(lpDataObject != NULL);
  663.         if (lpDataObject == NULL)
  664.             ATLTRACE2(atlTraceSnapin, 0, _T("IComponent::Notify called with lpDataObject==NULL \n"));
  665.         else
  666.         {
  667.             T* pT = static_cast<T*>(this);
  668.             CSnapInItem* pItem;
  669.             DATA_OBJECT_TYPES type;
  670.             hr = pT->GetDataClass(lpDataObject, &pItem, &type);
  671.             if (SUCCEEDED(hr))
  672.                 hr = pItem->Notify(event, arg, param, NULL, pT, type);
  673.         }
  674.         return hr;
  675.     }
  676.     
  677.     STDMETHOD(Destroy)(long cookie)
  678.     {
  679.         ATLTRACE2(atlTraceSnapin, 0, _T("IComponentImpl::Destroy\n"));
  680.  
  681.         T* pT = static_cast<T*>(this);
  682.  
  683.         if (pT->m_spControlbar != NULL)
  684.         {
  685.             int n = pT->m_toolbarMap.GetSize();
  686.             for (int i = 0; i < n; i++)
  687.             {
  688.                 IToolbar* pToolbar = (IToolbar*)pT->m_toolbarMap.GetValueAt(i);
  689.                  if (pToolbar != NULL)
  690.                  {
  691.                     pT->m_spControlbar->Detach(pToolbar);
  692.                     pToolbar->Release();
  693.                  }
  694.             }
  695.         }
  696.         pT->m_toolbarMap.RemoveAll();
  697.  
  698.         m_spConsole->SetHeader(NULL);
  699.         m_spConsole.Release();
  700.         return S_OK;
  701.     }
  702.     
  703.     STDMETHOD(QueryDataObject)(long cookie,
  704.         DATA_OBJECT_TYPES type,
  705.         LPDATAOBJECT  *ppDataObject)
  706.     {
  707.         ATLTRACE2(atlTraceSnapin, 0, _T("IComponentImpl::QueryDataObject\n"));
  708.  
  709.         ATLASSERT(ppDataObject != NULL);
  710.         if (ppDataObject == NULL)
  711.         {
  712.             ATLTRACE2(atlTraceSnapin, 0, _T("IComponent::QueryDataObject called with ppDataObject==NULL \n"));
  713.             return E_POINTER;
  714.         }
  715.         
  716.         if (cookie == NULL)
  717.         {
  718.             ATLTRACE2(atlTraceSnapin, 0, _T("IComponent::QueryDataObject called with cookie==NULL \n"));
  719.             return E_UNEXPECTED;
  720.         }
  721.  
  722.         *ppDataObject = NULL;
  723.  
  724.         CSnapInItem* pItem = (CSnapInItem*) cookie;
  725.         return pItem->GetDataObject(ppDataObject, type);
  726.     }
  727.     
  728.     STDMETHOD(GetResultViewType)(long cookie,
  729.         LPOLESTR  *ppViewType,
  730.         long  *pViewOptions)
  731.     {
  732.         ATLTRACE2(atlTraceSnapin, 0, _T("IComponentImpl::GetResultViewType\n"));
  733.  
  734.         if (cookie == NULL)
  735.         {
  736.             *ppViewType = NULL;
  737.             *pViewOptions = MMC_VIEW_OPTIONS_NONE;
  738.             return S_FALSE;
  739.         }
  740.         
  741.         CSnapInItem* pItem = (CSnapInItem*)cookie;
  742.         return pItem->GetResultViewType(ppViewType, pViewOptions);
  743.     }
  744.     
  745.     STDMETHOD(GetDisplayInfo)(RESULTDATAITEM *pResultDataItem)
  746.     {
  747.         ATLTRACE2(atlTraceSnapin, 0, _T("IComponentImpl::GetDisplayInfo\n"));
  748.  
  749.         ATLASSERT(pResultDataItem != NULL);
  750.         if (pResultDataItem == NULL)
  751.         {
  752.             ATLTRACE2(atlTraceSnapin, 0, _T("IComponent::GetDisplayInfo called with pResultDataItem==NULL\n"));
  753.             return E_POINTER;
  754.         }
  755.  
  756.         CSnapInItem* pItem = (CSnapInItem*) pResultDataItem->lParam;
  757.  
  758.         if (pItem == NULL)
  759.         {
  760.             ATLTRACE2(atlTraceSnapin, 0, _T("Invalid Item\n"));
  761.             return E_UNEXPECTED;
  762.         }
  763.         return pItem->GetResultPaneInfo(pResultDataItem);
  764.     }
  765.     
  766.     STDMETHOD(CompareObjects)( LPDATAOBJECT lpDataObjectA,
  767.         LPDATAOBJECT lpDataObjectB)
  768.     {
  769.         ATLTRACENOTIMPL(_T("IComponentImpl::CompareObjects\n"));
  770.     }
  771.  
  772.     CComPtr<IConsole> m_spConsole;
  773. };
  774.  
  775. template <class T, class D>        
  776. class ATL_NO_VTABLE IResultDataCompareImpl : public IResultDataCompare
  777. {
  778. public:
  779.     STDMETHOD(Compare)(long lUserParam,
  780.         long cookieA,
  781.         long cookieB,
  782.         int *pnResult)
  783.     {
  784.         ATLTRACENOTIMPL(_T("IResultDataCompareImpl::Compare"));
  785.     }
  786. };
  787.  
  788.  
  789. template <class T>
  790. class ATL_NO_VTABLE IExtendContextMenuImpl : public IExtendContextMenu
  791. {
  792. public:
  793.     STDMETHOD(AddMenuItems)(LPDATAOBJECT pDataObject,
  794.         LPCONTEXTMENUCALLBACK piCallback,
  795.         long *pInsertionAllowed)
  796.     {
  797.         ATLTRACE2(atlTraceSnapin, 0, _T("IExtendContextMenuImpl::AddMenuItems\n"));
  798.  
  799.         HRESULT hr = E_POINTER;
  800.  
  801.         ATLASSERT(pDataObject != NULL);
  802.         if (pDataObject == NULL)
  803.             ATLTRACE2(atlTraceSnapin, 0, _T("IExtendContextMenu::AddMenuItems called with pDataObject==NULL\n"));
  804.         else
  805.         {
  806.             T* pT = static_cast<T*>(this);
  807.             CSnapInItem* pItem;
  808.             DATA_OBJECT_TYPES type;
  809.             hr = pT->GetDataClass(pDataObject, &pItem, &type);
  810.  
  811.             if (SUCCEEDED(hr))
  812.                 hr = pItem->AddMenuItems(piCallback, pInsertionAllowed, type);
  813.         }
  814.         return hr;
  815.     }
  816.     
  817.     STDMETHOD(Command)(long lCommandID,
  818.         LPDATAOBJECT pDataObject)
  819.     {
  820.         ATLTRACE2(atlTraceSnapin, 0, _T("IExtendContextMenuImpl::Command\n"));
  821.  
  822.         HRESULT hr = E_POINTER;
  823.  
  824.         ATLASSERT(pDataObject != NULL);
  825.         if (pDataObject == NULL)
  826.             ATLTRACE2(atlTraceSnapin, 0, _T("IExtendContextMenu::Command called with pDataObject==NULL\n"));
  827.         else
  828.         {
  829.             T* pT = static_cast<T*>(this);
  830.             CSnapInItem* pItem;
  831.             DATA_OBJECT_TYPES type;
  832.             hr = pT->GetDataClass(pDataObject, &pItem, &type);
  833.             
  834.             if (SUCCEEDED(hr))
  835.                 hr = pItem->Command(lCommandID, type);
  836.         }
  837.         return hr;
  838.     }
  839. };
  840.  
  841. template<class T>
  842. class ATL_NO_VTABLE IExtendPropertySheetImpl : public IExtendPropertySheet
  843. {
  844. public:
  845.     STDMETHOD(CreatePropertyPages)(LPPROPERTYSHEETCALLBACK lpProvider,
  846.         long handle,
  847.         LPDATAOBJECT pDataObject)
  848.     {
  849.         ATLTRACE2(atlTraceSnapin, 0, _T("IExtendPropertySheetImpl::CreatePropertyPages\n"));
  850.  
  851.         HRESULT hr = E_POINTER;
  852.  
  853.         ATLASSERT(pDataObject != NULL);
  854.         if (pDataObject == NULL)
  855.             ATLTRACE2(atlTraceSnapin, 0, _T("IExtendPropertySheetImpl::CreatePropertyPages called with pDataObject==NULL\n"));
  856.         else
  857.         {
  858.             T* pT = static_cast<T*>(this);
  859.             CSnapInItem* pItem;
  860.             DATA_OBJECT_TYPES type;
  861.             hr = pT->GetDataClass(pDataObject, &pItem, &type);
  862.  
  863.             if (SUCCEEDED(hr))
  864.                 hr = pItem->CreatePropertyPages(lpProvider, handle, this, type);
  865.         }
  866.  
  867.         return hr;
  868.     }
  869.     
  870.     STDMETHOD(QueryPagesFor)(LPDATAOBJECT pDataObject)
  871.     {
  872.         ATLTRACE2(atlTraceSnapin, 0, _T("IExtendPropertySheetImpl::QueryPagesFor\n"));
  873.         
  874.  
  875.         HRESULT hr = E_POINTER;
  876.         
  877.         ATLASSERT(pDataObject != NULL);
  878.         if (pDataObject == NULL)
  879.             ATLTRACE2(atlTraceSnapin, 0, _T("IExtendPropertySheetImpl::QueryPagesFor called with pDataObject==NULL\n"));
  880.         else
  881.         {
  882.             T* pT = static_cast<T*>(this);
  883.             CSnapInItem* pItem;
  884.             DATA_OBJECT_TYPES type;
  885.             hr = pT->GetDataClass(pDataObject, &pItem, &type);
  886.  
  887.             if (SUCCEEDED(hr))
  888.                 hr = pItem->QueryPagesFor(type);
  889.         }
  890.         return hr;
  891.     }
  892. };
  893.  
  894. template <class T>
  895. class ATL_NO_VTABLE IExtendControlbarImpl : public IExtendControlbar
  896. {
  897. public:
  898.     STDMETHOD(SetControlbar)(LPCONTROLBAR pControlbar)
  899.     {
  900.         ATLTRACE2(atlTraceSnapin, 0, _T("IExtendControlbarImpl::SetControlbar\n"));
  901.         T* pT = static_cast<T*>(this);
  902.  
  903.         if (pT->m_spControlbar != NULL)
  904.         {
  905.             int n = pT->m_toolbarMap.GetSize();
  906.             for (int i = 0; i < n; i++)
  907.             {
  908.                 IToolbar* pToolbar = (IToolbar*)pT->m_toolbarMap.GetValueAt(i);
  909.                  if (pToolbar != NULL)
  910.                  {
  911.                     pT->m_spControlbar->Detach(pToolbar);
  912.                     pToolbar->Release();
  913.                  }
  914.             }
  915.         }
  916.         pT->m_toolbarMap.RemoveAll();
  917.  
  918.         pT->m_spControlbar = pControlbar;
  919.         return S_OK;
  920.     }
  921.     
  922.     STDMETHOD(ControlbarNotify)(MMC_NOTIFY_TYPE event,
  923.         long arg,
  924.         long param)
  925.     {
  926.         ATLTRACE2(atlTraceSnapin, 0, _T("IExtendControlbarImpl::ControlbarNotify\n"));
  927.  
  928.         CSnapInItem* pItem = NULL;
  929.         DATA_OBJECT_TYPES type;
  930.         HRESULT hr = S_OK;
  931.         T* pT = static_cast<T*>(this);
  932.  
  933.         if (event == MMCN_BTN_CLICK)
  934.             hr = pT->GetDataClass((IDataObject*) arg, &pItem, &type);
  935.         else if (event == MMCN_SELECT)
  936.             hr = pT->GetDataClass((IDataObject*) param, &pItem, &type);
  937.  
  938.         if (SUCCEEDED(hr))
  939.         {
  940.             hr = pItem->ControlbarNotify(pT->m_spControlbar, this, &(pT->m_toolbarMap), event, arg, param, type);
  941.         }
  942.  
  943.         return hr;
  944.     }
  945. };
  946.  
  947. #define SNAPINMENUID(id) \
  948. public: \
  949.     static const UINT GetMenuID() \
  950.     { \
  951.         static const UINT IDMENU = id; \
  952.         return id; \
  953.     }
  954.  
  955. #define EXT_SNAPINMENUID(id) \
  956. public: \
  957.     static const UINT GetMenuID() \
  958.     { \
  959.         static const UINT IDMENU = id; \
  960.         return id; \
  961.     }
  962.  
  963. #define BEGIN_SNAPINCOMMAND_MAP(theClass, bIsExtension) \
  964.     HRESULT ProcessCommand(UINT nID, \
  965.         bool& bHandled, \
  966.         CSnapInObjectRoot* pObj, \
  967.         DATA_OBJECT_TYPES type) \
  968.     { \
  969.             bHandled = true; \
  970.             HRESULT hr = S_OK;
  971.  
  972. #define SNAPINCOMMAND_ENTRY(id, func) \
  973.         if (id == nID) \
  974.         { \
  975.             hr = func(bHandled, pObj); \
  976.             if (bHandled) \
  977.                 return hr; \
  978.         }
  979.  
  980. #define SNAPINCOMMAND_RANGE_ENTRY(id1, id2, func) \
  981.         if (id1 >= nID && nID <= id2) \
  982.         { \
  983.             hr = func(nID, bHandled, pObj); \
  984.             if (bHandled) \
  985.                 return hr; \
  986.         }
  987.  
  988. #define CHAIN_SNAPINCOMMAND_MAP(theChainClass) \
  989.     { \
  990.         hr = theChainClass.ProcessCommand(nID, bHandled, pObj, type); \
  991.         if (bHandled) \
  992.             return hr; \
  993.     }
  994.  
  995. #define END_SNAPINCOMMAND_MAP() \
  996.             return hr; \
  997.     }
  998.  
  999. struct CSnapInToolBarData
  1000. {
  1001.     WORD wVersion;
  1002.     WORD wWidth;
  1003.     WORD wHeight;
  1004.     WORD wItemCount;
  1005.     //WORD aItems[wItemCount]
  1006.  
  1007.     WORD* items()
  1008.         { return (WORD*)(this+1); }
  1009. };
  1010.  
  1011. #define RT_TOOLBAR  MAKEINTRESOURCE(241)
  1012.     
  1013. class CSnapInToolbarInfo
  1014. {
  1015. public:
  1016.     ~CSnapInToolbarInfo()
  1017.     {
  1018.         CleanUp();
  1019.     }
  1020.  
  1021.     HRESULT CleanUp()
  1022.     {
  1023.         if (m_pStrToolTip)
  1024.         {
  1025.             for (UINT i = 0; i < m_nButtonCount; i++)
  1026.             {
  1027.                 delete m_pStrToolTip[i];
  1028.                 m_pStrToolTip[i] = NULL;
  1029.             }
  1030.             delete [] m_pStrToolTip;
  1031.             m_pStrToolTip = NULL;
  1032.         }
  1033.  
  1034.         if (m_pStrButtonText)
  1035.         {
  1036.             for (UINT i = 0; i < m_nButtonCount; i++)
  1037.             {
  1038.                 delete m_pStrButtonText[i];
  1039.                 m_pStrButtonText[i] = NULL;
  1040.             }
  1041.  
  1042.             delete [] m_pStrButtonText;
  1043.             m_pStrButtonText = NULL;
  1044.         }
  1045.         if (m_pnButtonID)
  1046.         {
  1047.             delete m_pnButtonID;
  1048.             m_pnButtonID = NULL;
  1049.         }
  1050.  
  1051.         m_nButtonCount = 0;
  1052.         return S_OK;
  1053.     }
  1054.  
  1055.     TCHAR** m_pStrToolTip;
  1056.     TCHAR** m_pStrButtonText;
  1057.     UINT* m_pnButtonID;
  1058.     UINT m_idToolbar;
  1059.     UINT m_nButtonCount;
  1060. };
  1061.  
  1062. #define BEGIN_SNAPINTOOLBARID_MAP(theClass) \
  1063. public: \
  1064.     static CSnapInToolbarInfo* GetToolbarInfo() \
  1065.     { \
  1066.         static CSnapInToolbarInfo m_toolbarInfo[] = \
  1067.         {
  1068.  
  1069. #define SNAPINTOOLBARID_ENTRY(id) \
  1070.             { NULL, NULL, NULL, id, 0},
  1071.  
  1072. #define END_SNAPINTOOLBARID_MAP() \
  1073.             { NULL, NULL, NULL, 0, 0} \
  1074.         }; \
  1075.         return m_toolbarInfo; \
  1076.     }    
  1077.  
  1078. template <class T, BOOL bIsExtension = FALSE>
  1079. class ATL_NO_VTABLE CSnapInItemImpl : public CSnapInItem
  1080. {
  1081. public:
  1082.     CSnapInItemImpl()
  1083.     {
  1084.     }
  1085.  
  1086.     virtual ~CSnapInItemImpl()
  1087.     {
  1088.     }    
  1089.  
  1090. public:
  1091.  
  1092.     STDMETHOD(Notify)( MMC_NOTIFY_TYPE event,
  1093.         long arg,
  1094.         long param,
  1095.         IComponentData* pComponentData,
  1096.         IComponent* pComponent,
  1097.         DATA_OBJECT_TYPES type)
  1098.     {
  1099.         ATLASSERT("Override Function in Derived Class");
  1100.         ATLTRACENOTIMPL(_T("CSnapInItemImpl::Notify"));
  1101.     }
  1102.     
  1103.     STDMETHOD(GetScopePaneInfo)(SCOPEDATAITEM *pScopeDataItem)
  1104.     {
  1105.         ATLTRACENOTIMPL(_T("CSnapInItemImpl::GetScopePaneInfo"));
  1106.     }
  1107.     
  1108.     STDMETHOD(GetResultViewType)(LPOLESTR *ppViewType,
  1109.         long *pViewOptions)
  1110.     {
  1111.         ATLTRACE2(atlTraceSnapin, 0, _T("CSnapInItemImpl::GetResultViewType\n"));
  1112.         *ppViewType = NULL;
  1113.         *pViewOptions = MMC_VIEW_OPTIONS_NONE;
  1114.         return S_FALSE;
  1115.     }
  1116.     
  1117.     STDMETHOD(GetResultPaneInfo)(RESULTDATAITEM *pResultDataItem)
  1118.     {
  1119.         ATLTRACENOTIMPL(_T("CSnapInItemImpl::GetResultPaneInfo"));
  1120.     }
  1121.     
  1122.     STDMETHOD(AddMenuItems)(LPCONTEXTMENUCALLBACK piCallback,
  1123.         long *pInsertionAllowed,
  1124.         DATA_OBJECT_TYPES type)
  1125.     {
  1126.         ATLTRACE2(atlTraceSnapin, 0, _T("CSnapInItemImpl::AddMenuItems\n"));
  1127.         T* pT = static_cast<T*>(this);
  1128.  
  1129.         if (!bIsExtension)
  1130.             pT->SetMenuInsertionFlags(true, pInsertionAllowed);
  1131.  
  1132.         UINT menuID = pT->GetMenuID();
  1133.         if (menuID == 0)
  1134.             return S_OK;
  1135.  
  1136.         HMENU hMenu = LoadMenu(_Module.GetResourceInstance(), MAKEINTRESOURCE(menuID));
  1137.         long insertionID;
  1138.         if (hMenu)
  1139.         {
  1140.             for (int i = 0; 1; i++)
  1141.             {
  1142.                 HMENU hSubMenu = GetSubMenu(hMenu, i);
  1143.                 if (hSubMenu == NULL)
  1144.                     break;
  1145.                 
  1146.                 MENUITEMINFO menuItemInfo;
  1147.                 memset(&menuItemInfo, 0, sizeof(menuItemInfo));
  1148.                 menuItemInfo.cbSize = sizeof(menuItemInfo);
  1149.  
  1150.                 switch (i)
  1151.                 {
  1152.                 case 0:
  1153.                     if (! (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP) )
  1154.                         continue;
  1155.                     insertionID = CCM_INSERTIONPOINTID_PRIMARY_TOP;
  1156.                     break;
  1157.  
  1158.                 case 1:
  1159.                     if (! (*pInsertionAllowed & CCM_INSERTIONALLOWED_NEW) )
  1160.                         continue;
  1161.                     if (bIsExtension)
  1162.                         insertionID = CCM_INSERTIONPOINTID_3RDPARTY_NEW;
  1163.                     else
  1164.                         insertionID = CCM_INSERTIONPOINTID_PRIMARY_NEW;
  1165.                     break;
  1166.  
  1167.                 case 2:;
  1168.                     if (! (*pInsertionAllowed & CCM_INSERTIONALLOWED_TASK) )
  1169.                         continue;
  1170.                     if (bIsExtension)
  1171.                         insertionID = CCM_INSERTIONPOINTID_3RDPARTY_TASK;
  1172.                     else
  1173.                         insertionID = CCM_INSERTIONPOINTID_PRIMARY_TASK;
  1174.                     break;
  1175.                 case 3:;
  1176.                     if (! (*pInsertionAllowed & CCM_INSERTIONALLOWED_VIEW) )
  1177.                         continue;
  1178.                     insertionID = CCM_INSERTIONPOINTID_PRIMARY_VIEW;
  1179.                     break;
  1180.                 default:
  1181.                     {
  1182.                         insertionID = 0;
  1183.                         continue;
  1184.                     }
  1185.                     break;
  1186.                 }
  1187.  
  1188.                 menuItemInfo.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID;
  1189.                 menuItemInfo.fType = MFT_STRING;
  1190.                 TCHAR buf[128];
  1191.  
  1192.                 for (int j = 0; 1; j++)
  1193.                 {
  1194.                     menuItemInfo.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID;
  1195.                     menuItemInfo.fType = MFT_STRING;
  1196.                     menuItemInfo.cch = 128;
  1197.                     menuItemInfo.dwTypeData = buf;
  1198.                     TCHAR strStatusBar[256];
  1199.  
  1200.                     if (!GetMenuItemInfo(hSubMenu, j, TRUE, &menuItemInfo))
  1201.                         break;
  1202.                     if (menuItemInfo.fType != MFT_STRING)
  1203.                         continue;
  1204.  
  1205.                     pT->UpdateMenuState(menuItemInfo.wID, buf, &menuItemInfo.fState);
  1206.                     LoadString(_Module.GetResourceInstance(), menuItemInfo.wID, strStatusBar, 256);
  1207.  
  1208.                     CONTEXTMENUITEM contextMenuItem;
  1209.                     memset(&contextMenuItem, 0, sizeof(contextMenuItem));
  1210.                     contextMenuItem.strName = buf;
  1211.                     contextMenuItem.strStatusBarText = strStatusBar;
  1212.                     contextMenuItem.lCommandID = menuItemInfo.wID;
  1213.                     contextMenuItem.lInsertionPointID = insertionID;
  1214.                     contextMenuItem.fFlags = menuItemInfo.fState;
  1215.                     
  1216.                     HRESULT hr = piCallback->AddItem(&contextMenuItem);
  1217.                     ATLASSERT(SUCCEEDED(hr));
  1218.                 }
  1219.             }
  1220.             DestroyMenu(hMenu);
  1221.         }
  1222.  
  1223.         if (!bIsExtension)
  1224.             pT->SetMenuInsertionFlags(true, pInsertionAllowed);
  1225.  
  1226.         return S_OK;
  1227.     }
  1228.     
  1229.     STDMETHOD(Command)(long lCommandID,        
  1230.         DATA_OBJECT_TYPES type)
  1231.     {
  1232.         ATLTRACE2(atlTraceSnapin, 0, _T("CSnapInItemImpl::Command\n"));
  1233.         bool bHandled;
  1234.         T* pT = static_cast<T*>(this);
  1235.         return pT->ProcessCommand(lCommandID, bHandled, (CSnapInObjectRoot*) this, type);
  1236.     }
  1237.     
  1238.     STDMETHOD(CreatePropertyPages)(LPPROPERTYSHEETCALLBACK lpProvider,
  1239.         long handle, 
  1240.         IUnknown* pUnk,
  1241.         DATA_OBJECT_TYPES type)
  1242.     {
  1243.         ATLASSERT("Override Function in Derived Class");
  1244.         ATLTRACENOTIMPL(_T("CSnapInItemImpl::CreatePropertyPages"));
  1245.     }
  1246.     
  1247.     STDMETHOD(QueryPagesFor)(DATA_OBJECT_TYPES type)
  1248.     {
  1249.         ATLASSERT("Override Function in Derived Class");
  1250.         ATLTRACENOTIMPL(_T("CSnapInItemImpl::QueryPagesFor"));
  1251.     }
  1252.  
  1253.     STDMETHOD(SetControlbar)(IControlbar *pControlbar, 
  1254.         IExtendControlbar* pExtendControlBar,
  1255.         CSimpleMap<UINT, IUnknown*>* pToolbarMap)
  1256.     {
  1257.         ATLTRACE2(atlTraceSnapin, 0, _T("CSnapInItemImpl::SetControlbar\n"));
  1258.         T* pT = static_cast<T*>(this);
  1259.  
  1260.         CSnapInToolbarInfo* pInfo = pT->GetToolbarInfo();
  1261.         if (pInfo == NULL)
  1262.             return S_OK;
  1263.  
  1264.         for( ; pInfo->m_idToolbar; pInfo++)
  1265.         {
  1266.             IToolbar* p = (IToolbar*) pToolbarMap->Lookup(pInfo->m_idToolbar);
  1267.             if (p != NULL)
  1268.                 continue;
  1269.  
  1270.             HBITMAP hBitmap = LoadBitmap(_Module.GetResourceInstance(), MAKEINTRESOURCE(pInfo->m_idToolbar));
  1271.             if (hBitmap == NULL)
  1272.                 return S_OK;
  1273.  
  1274.             HRSRC hRsrc = ::FindResource(_Module.GetResourceInstance(), MAKEINTRESOURCE(pInfo->m_idToolbar), RT_TOOLBAR);
  1275.             if (hRsrc == NULL)
  1276.                 return S_OK;
  1277.  
  1278.             HGLOBAL hGlobal = LoadResource(_Module.GetResourceInstance(), hRsrc);
  1279.             if (hGlobal == NULL)
  1280.                 return S_OK;
  1281.  
  1282.             CSnapInToolBarData* pData = (CSnapInToolBarData*)LockResource(hGlobal);
  1283.             if (pData == NULL)
  1284.                 return S_OK;
  1285.             ATLASSERT(pData->wVersion == 1);
  1286.             ATLASSERT(pData->wWidth == 16);
  1287.             ATLASSERT(pData->wHeight == 16);
  1288.  
  1289.             pInfo->m_nButtonCount = pData->wItemCount;
  1290.             if (pInfo->m_pnButtonID == NULL)
  1291.                 pInfo->m_pnButtonID = new UINT[pInfo->m_nButtonCount];
  1292.  
  1293.             if (pInfo->m_pnButtonID == NULL)
  1294.                 continue;
  1295.  
  1296.             MMCBUTTON *pButtons = new MMCBUTTON[pData->wItemCount];
  1297.             if (pButtons == NULL)
  1298.             {
  1299.                 delete []pInfo->m_pnButtonID;
  1300.                 continue;
  1301.             }
  1302.             
  1303.             if (pInfo->m_pStrToolTip == NULL)
  1304.             {
  1305.                 pInfo->m_pStrToolTip = new TCHAR* [pData->wItemCount];
  1306.                 if (pInfo->m_pStrToolTip)
  1307.                     memset(pInfo->m_pStrToolTip, 0, sizeof(TCHAR*) * pData->wItemCount);
  1308.             }
  1309.  
  1310.             if (pInfo->m_pStrToolTip == NULL)
  1311.             {
  1312.                 delete []pInfo->m_pnButtonID;
  1313.                 delete []pButtons;
  1314.                 continue;
  1315.             }
  1316.  
  1317.  
  1318.             for (int i = 0, j = 0; i < pData->wItemCount; i++)
  1319.             {
  1320. //                pInfo->m_pStrToolTip[i] = NULL;
  1321.                 memset(&pButtons[i], 0, sizeof(MMCBUTTON));
  1322.                 pInfo->m_pnButtonID[i] = pButtons[i].idCommand = pData->items()[i];
  1323.                 if (pButtons[i].idCommand)
  1324.                 {
  1325.                     pButtons[i].nBitmap = j++;
  1326.                     // get the statusbar string and allow modification of the button state
  1327.                     TCHAR strStatusBar[512];
  1328.                     LoadString(_Module.GetResourceInstance(), pButtons[i].idCommand, strStatusBar, 512);
  1329.  
  1330.                     if (pInfo->m_pStrToolTip[i] == NULL)
  1331.                         pInfo->m_pStrToolTip[i] = new TCHAR[lstrlen(strStatusBar) + 1];
  1332.                     if (pInfo->m_pStrToolTip[i] == NULL)
  1333.                         continue;
  1334.                     lstrcpy(pInfo->m_pStrToolTip[i], strStatusBar);
  1335.                     pButtons[i].lpTooltipText = pInfo->m_pStrToolTip[i];
  1336.                     pButtons[i].lpButtonText = _T("");
  1337.                     pT->SetToolbarButtonInfo(pButtons[i].idCommand, &pButtons[i].fsState, &pButtons[i].fsType);
  1338.                 }
  1339.                 else
  1340.                 {
  1341.                     pButtons[i].lpTooltipText = _T("");
  1342.                     pButtons[i].lpButtonText = _T("");
  1343.                     pButtons[i].fsType = TBSTYLE_SEP;
  1344.                 }
  1345.             }
  1346.  
  1347.             IToolbar* pToolbar;
  1348.             HRESULT hr = pControlbar->Create(TOOLBAR, pExtendControlBar, reinterpret_cast<LPUNKNOWN*>(&pToolbar));
  1349.             if (SUCCEEDED(hr))
  1350.             {
  1351.  
  1352.                 hr = pToolbar->AddBitmap(pData->wItemCount, hBitmap, pData->wWidth, pData->wHeight, RGB(192, 192, 192));
  1353.                 if (SUCCEEDED(hr))
  1354.                 {
  1355.                     hr = pToolbar->AddButtons(pData->wItemCount, pButtons);
  1356.                     if (SUCCEEDED(hr))
  1357.                     {
  1358.                         pToolbar->AddRef();
  1359.                         pToolbarMap->Add(pInfo->m_idToolbar, (IUnknown*)pToolbar);
  1360.                     }
  1361.                 }
  1362.             }
  1363.             pToolbar->Release();
  1364.             delete [] pButtons;
  1365.         }
  1366.         return S_OK;
  1367.     }
  1368.     
  1369.     STDMETHOD(ControlbarNotify)(IControlbar *pControlbar,
  1370.         IExtendControlbar *pExtendControlbar,
  1371.         CSimpleMap<UINT, IUnknown*>* pToolbarMap,
  1372.         MMC_NOTIFY_TYPE event,
  1373.         long arg, 
  1374.         long param,
  1375.         DATA_OBJECT_TYPES type)
  1376.     {
  1377.         ATLTRACE2(atlTraceSnapin, 0, _T("CSnapInItemImpl::ControlbarNotify\n"));
  1378.         T* pT = static_cast<T*>(this);
  1379.  
  1380.         SetControlbar(pControlbar, pExtendControlbar, pToolbarMap);
  1381.  
  1382.         CComPtr<IUnknown> spUnknown;
  1383.         HRESULT hr = pControlbar->QueryInterface(IID_IUnknown, (void**)&spUnknown);
  1384.         if (FAILED(hr))
  1385.             return hr;
  1386.  
  1387.         if(event == MMCN_SELECT)
  1388.         {
  1389.             if (pControlbar == NULL)
  1390.                 return S_OK;
  1391.  
  1392.             BOOL bSelect = (BOOL) HIWORD (arg);
  1393.             BOOL bScope = (BOOL) LOWORD(arg); 
  1394.  
  1395.             CSnapInToolbarInfo* pInfo = pT->GetToolbarInfo();
  1396.             if (pInfo == NULL)
  1397.                 return S_OK;
  1398.  
  1399.             for(; pInfo->m_idToolbar; pInfo++)
  1400.             {
  1401.                 IToolbar* pToolbar = (IToolbar*)pToolbarMap->Lookup(pInfo->m_idToolbar);
  1402.                 if (pToolbar == NULL)
  1403.                     continue;
  1404.  
  1405.                 if (!bSelect)
  1406.                     pControlbar->Detach(pToolbar);
  1407.                 else
  1408.                 {
  1409.                     pControlbar->Attach(TOOLBAR, pToolbar);
  1410.                     for (UINT i = 0; i < pInfo->m_nButtonCount; i++)
  1411.                     {
  1412.                         if (pInfo->m_pnButtonID[i])
  1413.                         {
  1414.                             pToolbar->SetButtonState(pInfo->m_pnButtonID[i], 
  1415.                                 ENABLED,
  1416.                                 pT->UpdateToolbarButton(pInfo->m_pnButtonID[i], 
  1417.                                     ENABLED));
  1418.                             pToolbar->SetButtonState(pInfo->m_pnButtonID[i], 
  1419.                                 CHECKED,
  1420.                                 pT->UpdateToolbarButton(pInfo->m_pnButtonID[i], 
  1421.                                     CHECKED));
  1422.                             pToolbar->SetButtonState(pInfo->m_pnButtonID[i], 
  1423.                                 HIDDEN,
  1424.                                 pT->UpdateToolbarButton(pInfo->m_pnButtonID[i], 
  1425.                                     HIDDEN));
  1426.                             pToolbar->SetButtonState(pInfo->m_pnButtonID[i], 
  1427.                                 INDETERMINATE,
  1428.                                 pT->UpdateToolbarButton(pInfo->m_pnButtonID[i], 
  1429.                                     INDETERMINATE));
  1430.                             pToolbar->SetButtonState(pInfo->m_pnButtonID[i], 
  1431.                                 BUTTONPRESSED,
  1432.                                 pT->UpdateToolbarButton(pInfo->m_pnButtonID[i], 
  1433.                                     BUTTONPRESSED));
  1434.                         }
  1435.                     }
  1436.                 }
  1437.             }
  1438.             return S_OK;
  1439.         }
  1440.         else if (event == MMCN_BTN_CLICK)
  1441.         {
  1442.             bool bHandled;
  1443.             return pT->ProcessCommand((UINT) param, bHandled, (CSnapInObjectRoot*) this, type);
  1444.         }
  1445.  
  1446.         return E_UNEXPECTED;
  1447.     }
  1448.  
  1449.     STDMETHOD(GetScopeData)(SCOPEDATAITEM **pScopeDataItem)
  1450.     {
  1451.         if (pScopeDataItem == NULL)
  1452.             return E_FAIL;
  1453.  
  1454.         *pScopeDataItem = &m_scopeDataItem;
  1455.         return S_OK;
  1456.     }
  1457.         
  1458.     STDMETHOD(GetResultData)(RESULTDATAITEM **pResultDataItem)
  1459.     {
  1460.         if (pResultDataItem == NULL)
  1461.             return E_FAIL;
  1462.  
  1463.         *pResultDataItem = &m_resultDataItem;
  1464.         return S_OK;
  1465.     }
  1466.  
  1467.     STDMETHOD(GetDataObject)(IDataObject** pDataObj, DATA_OBJECT_TYPES type)
  1468.     {
  1469.         CComObject<CSnapInDataObjectImpl>* pData;
  1470.         HRESULT hr = CComObject<CSnapInDataObjectImpl>::CreateInstance(&pData);
  1471.         if (FAILED(hr))
  1472.             return hr;
  1473.  
  1474.         T* pT = static_cast<T*> (this);
  1475.         pData->m_objectData.m_pItem = pT;
  1476.         pData->m_objectData.m_type = type;
  1477.  
  1478.         hr = pData->QueryInterface(IID_IDataObject, (void**)(pDataObj));
  1479.         return hr;
  1480.     }
  1481.  
  1482.     void UpdateMenuState(UINT id, LPTSTR pBuf, UINT *flags)
  1483.     {
  1484.         return;
  1485.     }
  1486.  
  1487.     void SetToolbarButtonInfo(UINT id, BYTE *fsState, BYTE *fsType)
  1488.     {
  1489.         *fsState = TBSTATE_ENABLED;
  1490.         *fsType = TBSTYLE_BUTTON;
  1491.     }
  1492.  
  1493.     BOOL UpdateToolbarButton(UINT id, BYTE fsState)
  1494.     {
  1495.         if (fsState == ENABLED)
  1496.             return TRUE;
  1497.         return FALSE;
  1498.     }
  1499.  
  1500.     HRESULT ProcessCommand(UINT nID, 
  1501.         bool& bHandled,
  1502.         CSnapInObjectRoot* pObj,
  1503.         DATA_OBJECT_TYPES type)
  1504.     {
  1505.         ATLTRACE2(atlTraceSnapin, 0, _T("No handler for item with ID %d\n"), nID);
  1506.         return S_OK;
  1507.     }
  1508.  
  1509.     STDMETHOD (FillData)(CLIPFORMAT cf, LPSTREAM pStream)
  1510.     {
  1511.         HRESULT hr = DV_E_CLIPFORMAT;
  1512.         ULONG uWritten;
  1513.  
  1514.         T* pT = static_cast<T*> (this);
  1515.  
  1516.         if (cf == m_CCF_NODETYPE)
  1517.         {
  1518.             hr = pStream->Write(pT->GetNodeType(), sizeof(GUID), &uWritten);
  1519.             return hr;
  1520.         }
  1521.  
  1522.         if (cf == m_CCF_SZNODETYPE)
  1523.         {
  1524.             hr = pStream->Write(pT->GetSZNodeType(), (lstrlen((LPCTSTR)pT->GetSZNodeType()) + 1 )* sizeof(TCHAR), &uWritten);
  1525.             return hr;
  1526.         }
  1527.  
  1528.         if (cf == m_CCF_DISPLAY_NAME)
  1529.         {
  1530.             hr = pStream->Write(pT->GetDisplayName(), (lstrlen((LPCTSTR)pT->GetDisplayName()) + 1) * sizeof(TCHAR), &uWritten);
  1531.             return hr;
  1532.         }
  1533.  
  1534.         if (cf == m_CCF_SNAPIN_CLASSID)
  1535.         {
  1536.             hr = pStream->Write(pT->GetSnapInCLSID(), sizeof(GUID), &uWritten);
  1537.             return hr;
  1538.         }
  1539.  
  1540.         return hr;
  1541.     }
  1542.  
  1543.     static CSnapInToolbarInfo* GetToolbarInfo()
  1544.     {
  1545.         return NULL;
  1546.     }
  1547.  
  1548.     static const UINT GetMenuID() 
  1549.     {
  1550.         return 0;
  1551.     }
  1552.  
  1553.     void SetMenuInsertionFlags(bool bBeforeInsertion, long* pInsertionAllowed)
  1554.     {
  1555.     }
  1556.  
  1557.     void* GetNodeType()
  1558.     {
  1559.         return (void*)T::m_NODETYPE;
  1560.     }
  1561.     void* GetSZNodeType()
  1562.     {
  1563.         return (void*)T::m_SZNODETYPE;
  1564.     }
  1565.  
  1566.     void* GetDisplayName()
  1567.     {
  1568.         return (void*)T::m_SZDISPLAY_NAME;
  1569.     }
  1570.  
  1571.     void* GetSnapInCLSID()
  1572.     {
  1573.         return (void*)T::m_SNAPIN_CLASSID;
  1574.     }
  1575.  
  1576.     CComBSTR m_bstrDisplayName;
  1577.     SCOPEDATAITEM m_scopeDataItem;
  1578.     RESULTDATAITEM m_resultDataItem;
  1579. };
  1580.  
  1581.  
  1582. _declspec( selectany ) CLIPFORMAT CSnapInItem::m_CCF_NODETYPE = 0;
  1583. _declspec( selectany ) CLIPFORMAT CSnapInItem::m_CCF_SZNODETYPE = 0;
  1584. _declspec( selectany ) CLIPFORMAT CSnapInItem::m_CCF_DISPLAY_NAME = 0;
  1585. _declspec( selectany ) CLIPFORMAT CSnapInItem::m_CCF_SNAPIN_CLASSID = 0;
  1586. _declspec( selectany ) CLIPFORMAT CSnapInItem::m_CCF_SNAPIN_GETOBJECTDATA = 0;
  1587.  
  1588. #endif //__ATL_SNAPIN_H__