Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1911 lines
44 KiB

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