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

3073 lines
87 KiB

  1. // This is a part of the Microsoft Management Console.
  2. // Copyright 1995 - 1997 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Management Console and related
  7. // electronic documentation provided with the interfaces.
  8. #include "stdafx.h"
  9. #include "Service.h"
  10. #include "CSnapin.h"
  11. #include "DataObj.h"
  12. #include "afxdlgs.h"
  13. #include "resource.h"
  14. #include "genpage.h" // Step 3
  15. #include <atlimpl.cpp>
  16. #ifdef _DEBUG
  17. #define new DEBUG_NEW
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21. // All data is static for the sample
  22. FOLDER_DATA FolderData[NUM_FOLDERS] =
  23. {
  24. {L"User Data", L"1111", L"Info about users", USER},
  25. {L"Company Data", L"2222", L"Info about Companies", COMPANY},
  26. {L"Virtual Data", L"3333", L"Info about virtual items", VIRTUAL},
  27. {L"", L"", L"",STATIC}
  28. };
  29. FOLDER_DATA ExtFolderData[NUM_FOLDERS] =
  30. {
  31. {L"1:", L"1111", L"Info about users", EXT_USER},
  32. {L"2:", L"2222", L"Info about Companies", EXT_COMPANY},
  33. {L"3:", L"3333", L"Infor about virtual items", EXT_VIRTUAL},
  34. {L"", L"", L"",STATIC}
  35. };
  36. static MMCBUTTON SnapinButtons[] =
  37. {
  38. { 0, 1, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"Folder", L"New Folder" },
  39. { 1, 2, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"Inbox", L"Mail Inbox"},
  40. { 2, 3, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"Outbox", L"Mail Outbox" },
  41. { 3, 4, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"Send", L"Send Message" },
  42. { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, L" ", L"" },
  43. { 4, 5, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"Trash", L"Trash" },
  44. { 5, 6, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"Open", L"Open Folder"},
  45. { 6, 7, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"News", L"Today's News" },
  46. { 7, 8, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"INews", L"Internet News" },
  47. };
  48. static MMCBUTTON SnapinButtons2[] =
  49. {
  50. { 0, 10, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"Compose", L"Compose Message" },
  51. { 1, 20, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"Print", L"Print Message" },
  52. { 2, 30, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"Find", L"Find Message" },
  53. { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, L" ", L"" },
  54. { 3, 40, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"Inbox", L"Inbox" },
  55. { 4, 50, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"Smile", L"Smile :-)" },
  56. { 5, 60, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"Reply", L"Reply" },
  57. { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP , L" ", L"" },
  58. { 6, 70, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"Reply All", L"Reply All" },
  59. };
  60. enum
  61. {
  62. // Identifiers for each of the commands/views to be inserted into the context menu.
  63. IDM_COMMAND1,
  64. IDM_COMMAND2,
  65. IDM_DEFAULT_MESSAGE_VIEW,
  66. IDM_SAMPLE_OCX_VIEW,
  67. IDM_SAMPLE_WEB_VIEW
  68. };
  69. static int n_count = 0;
  70. #define ODS OutputDebugString
  71. #ifdef DBX
  72. void DbxPrint(LPTSTR pszFmt, ...)
  73. {
  74. va_list va;
  75. va_start (va, pszFmt);
  76. TCHAR buf[250];
  77. wsprintf(buf, pszFmt, va);
  78. OutputDebugString(buf);
  79. va_end(va);
  80. }
  81. //#define DBX_PRINT DbxPrint
  82. inline void __DummyTrace(LPTSTR, ...) { }
  83. #define DBX_PRINT 1 ? (void)0 : ::__DummyTrace
  84. #else
  85. inline void __DummyTrace(LPTSTR, ...) { }
  86. #define DBX_PRINT 1 ? (void)0 : ::__DummyTrace
  87. #endif
  88. //
  89. // The sample snap-in only has 1 property type and it's the workstation name
  90. //
  91. //
  92. // Extracts the coclass guid format from the data object
  93. //
  94. template <class TYPE>
  95. TYPE* Extract(LPDATAOBJECT lpDataObject, unsigned int ucf)
  96. {
  97. ASSERT(lpDataObject != NULL);
  98. TYPE* p = NULL;
  99. CLIPFORMAT cf = (CLIPFORMAT)ucf;
  100. STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL };
  101. FORMATETC formatetc = { cf, NULL,
  102. DVASPECT_CONTENT, -1, TYMED_HGLOBAL
  103. };
  104. // Allocate memory for the stream
  105. int len = (cf == CDataObject::m_cfWorkstation) ?
  106. ((MAX_COMPUTERNAME_LENGTH+1) * sizeof(TYPE)) : sizeof(TYPE);
  107. stgmedium.hGlobal = GlobalAlloc(GMEM_SHARE, len);
  108. // Get the workstation name from the data object
  109. do
  110. {
  111. if (stgmedium.hGlobal == NULL)
  112. break;
  113. if (FAILED(lpDataObject->GetDataHere(&formatetc, &stgmedium)))
  114. break;
  115. p = reinterpret_cast<TYPE*>(stgmedium.hGlobal);
  116. if (p == NULL)
  117. break;
  118. } while (FALSE);
  119. return p;
  120. }
  121. template<class T>
  122. void ReleaseExtracted (T* t)
  123. {
  124. GlobalFree (reinterpret_cast<HGLOBAL>(t));
  125. }
  126. BOOL IsMMCMultiSelectDataObject(IDataObject* pDataObject)
  127. {
  128. if (pDataObject == NULL)
  129. return FALSE;
  130. static CLIPFORMAT s_cf = 0;
  131. if (s_cf == 0)
  132. {
  133. USES_CONVERSION;
  134. s_cf = (CLIPFORMAT)RegisterClipboardFormat(W2T(CCF_MMC_MULTISELECT_DATAOBJECT));
  135. }
  136. FORMATETC fmt = {s_cf, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  137. return (pDataObject->QueryGetData(&fmt) == S_OK);
  138. }
  139. BOOL IsMyMultiSelectDataObject(IDataObject* pIDataObject)
  140. {
  141. if (pIDataObject == NULL)
  142. return FALSE;
  143. CDataObject* pCDataObject = dynamic_cast<CDataObject*>(pIDataObject);
  144. if (pCDataObject == NULL)
  145. return FALSE;
  146. return pCDataObject->IsMultiSelDobj();
  147. }
  148. // Data object extraction helpers
  149. CLSID* ExtractClassID(LPDATAOBJECT lpDataObject)
  150. {
  151. return Extract<CLSID>(lpDataObject, CDataObject::m_cfCoClass);
  152. }
  153. GUID* ExtractNodeType(LPDATAOBJECT lpDataObject)
  154. {
  155. return Extract<GUID>(lpDataObject, CDataObject::m_cfNodeType);
  156. }
  157. wchar_t* ExtractWorkstation(LPDATAOBJECT lpDataObject)
  158. {
  159. return Extract<wchar_t>(lpDataObject, CDataObject::m_cfWorkstation);
  160. }
  161. INTERNAL* ExtractInternalFormat(LPDATAOBJECT lpDataObject)
  162. {
  163. return Extract<INTERNAL>(lpDataObject, CDataObject::m_cfInternal);
  164. }
  165. void ReleaseClassID (CLSID* pclsid)
  166. {
  167. ReleaseExtracted<CLSID>(pclsid);
  168. }
  169. void ReleaseNodeType (GUID* pguid)
  170. {
  171. ReleaseExtracted<GUID>(pguid);
  172. }
  173. void ReleaseWorkstation (wchar_t* p)
  174. {
  175. ReleaseExtracted<wchar_t>(p);
  176. }
  177. void ReleaseInternalFormat (INTERNAL* pInternal)
  178. {
  179. ReleaseExtracted<INTERNAL>(pInternal);
  180. }
  181. HRESULT _QueryDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type,
  182. CComponentDataImpl* pImpl, LPDATAOBJECT* ppDataObject)
  183. {
  184. ASSERT(ppDataObject != NULL);
  185. ASSERT(pImpl != NULL);
  186. CComObject<CDataObject>* pObject;
  187. CComObject<CDataObject>::CreateInstance(&pObject);
  188. ASSERT(pObject != NULL);
  189. // Save cookie and type for delayed rendering
  190. pObject->SetType(type);
  191. pObject->SetCookie(cookie);
  192. #ifdef _DEBUG
  193. pObject->SetComponentData(pImpl);
  194. #endif
  195. // Store the coclass with the data object
  196. pObject->SetClsid(pImpl->GetCoClassID());
  197. return pObject->QueryInterface(IID_IDataObject,
  198. reinterpret_cast<void**>(ppDataObject));
  199. }
  200. DWORD GetItemType(MMC_COOKIE cookie)
  201. {
  202. // folder = CFoder* is cookie
  203. // result = RESULT_DATA* is the cookie
  204. return (*reinterpret_cast<DWORD*>(cookie));
  205. }
  206. /////////////////////////////////////////////////////////////////////////////
  207. // Return TRUE if we are enumerating our main folder
  208. BOOL CSnapin::IsEnumerating(LPDATAOBJECT lpDataObject)
  209. {
  210. BOOL bResult = FALSE;
  211. ASSERT(lpDataObject);
  212. GUID* nodeType = ExtractNodeType(lpDataObject);
  213. // Is this my main node (static folder node type)
  214. if (::IsEqualGUID(*nodeType, cNodeTypeStatic) == TRUE)
  215. bResult = TRUE;
  216. // Free resources
  217. ::GlobalFree(reinterpret_cast<HANDLE>(nodeType));
  218. return bResult;
  219. }
  220. /////////////////////////////////////////////////////////////////////////////
  221. // CSnapin's IComponent implementation
  222. // guid for custom view
  223. static WCHAR* szCalendarGUID = L"{8E27C92B-1264-101C-8A2F-040224009C02}";
  224. static WCHAR* szMicrosoftURL = L"www.microsoft.com";
  225. STDMETHODIMP CSnapin::GetResultViewType(MMC_COOKIE cookie, LPOLESTR* ppViewType, long* pViewOptions)
  226. {
  227. *pViewOptions = MMC_VIEW_OPTIONS_MULTISELECT;
  228. // if list view
  229. if (m_CustomViewID == VIEW_DEFAULT_LV)
  230. {
  231. m_bVirtualView = FALSE;
  232. // if static folder not selected
  233. if (cookie != NULL)
  234. {
  235. // See if virtual data folder is selected
  236. CFolder* pFolder = reinterpret_cast<CFolder*>(cookie);
  237. ASSERT(pFolder->itemType == SCOPE_ITEM);
  238. FOLDER_TYPES ftype = pFolder->GetType();
  239. m_bVirtualView = (ftype == VIRTUAL || ftype == EXT_VIRTUAL);
  240. if (m_bVirtualView)
  241. *pViewOptions |= MMC_VIEW_OPTIONS_OWNERDATALIST;
  242. }
  243. return S_FALSE;
  244. }
  245. WCHAR szMessageViewGUID[40];
  246. WCHAR* pszView;
  247. switch (m_CustomViewID)
  248. {
  249. case VIEW_CALENDAR_OCX:
  250. pszView = szCalendarGUID;
  251. break;
  252. case VIEW_MICROSOFT_URL:
  253. pszView = szMicrosoftURL;
  254. break;
  255. case VIEW_DEFAULT_MESSAGE_VIEW:
  256. StringFromGUID2 (CLSID_MessageView, szMessageViewGUID, ARRAYLEN(szMessageViewGUID));
  257. pszView = szMessageViewGUID;
  258. break;
  259. default:
  260. ASSERT (false && "CSnapin::GetResultViewType: Unknown view ID");
  261. return (S_FALSE);
  262. break;
  263. }
  264. UINT uiByteLen = (wcslen(pszView) + 1) * sizeof(WCHAR);
  265. LPOLESTR psz = (LPOLESTR)::CoTaskMemAlloc(uiByteLen);
  266. USES_CONVERSION;
  267. if (psz != NULL)
  268. {
  269. wcscpy(psz, pszView);
  270. *ppViewType = psz;
  271. return S_OK;
  272. }
  273. return S_FALSE;
  274. }
  275. STDMETHODIMP CSnapin::Initialize(LPCONSOLE lpConsole)
  276. {
  277. DBX_PRINT(_T(" ---------- CSnapin::Initialize<0x08x>\n"), this);
  278. ASSERT(lpConsole != NULL);
  279. m_bInitializedC = true;
  280. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  281. // Save the IConsole pointer
  282. m_pConsole = lpConsole;
  283. m_pConsole->AddRef();
  284. // Load resource strings
  285. LoadResources();
  286. // QI for a IHeaderCtrl
  287. HRESULT hr = m_pConsole->QueryInterface(IID_IHeaderCtrl,
  288. reinterpret_cast<void**>(&m_pHeader));
  289. // Give the console the header control interface pointer
  290. if (SUCCEEDED(hr))
  291. m_pConsole->SetHeader(m_pHeader);
  292. m_pConsole->QueryInterface(IID_IResultData,
  293. reinterpret_cast<void**>(&m_pResult));
  294. hr = m_pConsole->QueryResultImageList(&m_pImageResult);
  295. ASSERT(hr == S_OK);
  296. hr = m_pConsole->QueryConsoleVerb(&m_pConsoleVerb);
  297. ASSERT(hr == S_OK);
  298. return S_OK;
  299. }
  300. STDMETHODIMP CSnapin::Notify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param)
  301. {
  302. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  303. if (IS_SPECIAL_DATAOBJECT(lpDataObject))
  304. {
  305. if (event == MMCN_BTN_CLICK)
  306. {
  307. if (m_CustomViewID != VIEW_DEFAULT_LV)
  308. {
  309. switch (param)
  310. {
  311. case MMC_VERB_REFRESH:
  312. ::AfxMessageBox(_T("MMCN_BTN_CLICK::MMC_VERB_REFRESH"));
  313. _OnRefresh(lpDataObject);
  314. break;
  315. case MMC_VERB_PROPERTIES:
  316. ::AfxMessageBox(_T("MMCN_BTN_CLICK::MMC_VERB_PROPERTIES"));
  317. break;
  318. default:
  319. ::AfxMessageBox(_T("MMCN_BTN_CLICK::param unknown"));
  320. break;
  321. }
  322. }
  323. }
  324. else
  325. {
  326. switch (event)
  327. {
  328. case MMCN_REFRESH:
  329. ::AfxMessageBox(_T("MMCN_BTN_CLICK::MMCN_REFRESH"));
  330. _OnRefresh(lpDataObject);
  331. break;
  332. }
  333. }
  334. return S_OK;
  335. }
  336. HRESULT hr = S_OK;
  337. MMC_COOKIE cookie;
  338. if (event == MMCN_PROPERTY_CHANGE)
  339. {
  340. hr = OnPropertyChange(lpDataObject);
  341. }
  342. else if (event == MMCN_VIEW_CHANGE)
  343. {
  344. hr = OnUpdateView(lpDataObject);
  345. }
  346. else if (event == MMCN_DESELECT_ALL)
  347. {
  348. DBX_PRINT(_T("CSnapin::Notify -> MMCN_DESELECT_ALL \n"));
  349. }
  350. else if (event == MMCN_COLUMN_CLICK)
  351. {
  352. DBX_PRINT(_T("CSnapin::Notify -> MMCN_COLUMN_CLICK \n"));
  353. }
  354. else if (event == MMCN_SNAPINHELP)
  355. {
  356. AfxMessageBox(_T("CSnapin::Notify ->MMCN_SNAPINHELP"));
  357. }
  358. else
  359. {
  360. INTERNAL* pInternal = NULL;
  361. if (IsMMCMultiSelectDataObject(lpDataObject) == FALSE)
  362. {
  363. pInternal = ExtractInternalFormat(lpDataObject);
  364. if (pInternal == NULL)
  365. {
  366. ASSERT(FALSE);
  367. return S_OK;
  368. }
  369. if (pInternal)
  370. cookie = pInternal->m_cookie;
  371. }
  372. switch(event)
  373. {
  374. case MMCN_ACTIVATE:
  375. break;
  376. case MMCN_CLICK:
  377. hr = OnResultItemClk(pInternal->m_type, cookie);
  378. break;
  379. case MMCN_DBLCLICK:
  380. if (pInternal->m_type == CCT_RESULT)
  381. Command(IDM_COMMAND1, lpDataObject);
  382. else
  383. hr = S_FALSE;
  384. break;
  385. case MMCN_ADD_IMAGES:
  386. OnAddImages(cookie, arg, param);
  387. break;
  388. case MMCN_SHOW:
  389. hr = OnShow(cookie, arg, param);
  390. break;
  391. case MMCN_MINIMIZED:
  392. hr = OnMinimize(cookie, arg, param);
  393. break;
  394. case MMCN_INITOCX:
  395. // ::MessageBox(NULL, _T("MMCN_INITOCX"), _T("TRACE"), MB_OK);
  396. ASSERT(param != 0);
  397. break;
  398. case MMCN_DESELECT_ALL:
  399. case MMCN_SELECT:
  400. HandleStandardVerbs((event == MMCN_DESELECT_ALL),
  401. arg, lpDataObject);
  402. break;
  403. case MMCN_PASTE:
  404. AfxMessageBox(_T("CSnapin::MMCN_PASTE"));
  405. break;
  406. case MMCN_DELETE:
  407. AfxMessageBox(_T("CSnapin::MMCN_DELETE"));
  408. break;
  409. case MMCN_CONTEXTHELP:
  410. hr = OnContextHelp(lpDataObject);
  411. break;
  412. case MMCN_REFRESH:
  413. AfxMessageBox(_T("CSnapin::MMCN_REFRESH"));
  414. _OnRefresh(lpDataObject);
  415. break;
  416. case MMCN_PRINT:
  417. AfxMessageBox(_T("CSnapin::MMCN_PRINT"));
  418. break;
  419. case MMCN_RENAME:
  420. // ODS(_T("\n\n\t\tCSnapin::MMCN_RENAME\n\n"));
  421. break;
  422. case MMCN_RESTORE_VIEW:
  423. { // user selected Back or Forward buttons:
  424. // we get the same info back that we gave
  425. // MMC during the GetResultViewType call.
  426. MMC_RESTORE_VIEW* pmrv = (MMC_RESTORE_VIEW*)arg;
  427. BOOL * b = (BOOL*)param;
  428. *b = TRUE; // we're handling it
  429. // first, setup m_bVirtualMode
  430. m_bVirtualView = FALSE;
  431. CFolder* pFolder = reinterpret_cast<CFolder*>(pmrv->cookie);
  432. if (pFolder != NULL)
  433. if (pFolder->GetType() == VIRTUAL)
  434. m_bVirtualView = TRUE;
  435. WCHAR szMessageViewGUID[40];
  436. StringFromGUID2 (CLSID_MessageView, szMessageViewGUID, ARRAYLEN(szMessageViewGUID));
  437. // also, maintain m_CustomViewID
  438. if (pmrv->pViewType == NULL)
  439. m_CustomViewID = VIEW_DEFAULT_LV;
  440. else if (!wcscmp (pmrv->pViewType, szCalendarGUID))
  441. m_CustomViewID = VIEW_CALENDAR_OCX;
  442. else if (!wcscmp (pmrv->pViewType, szMicrosoftURL))
  443. m_CustomViewID = VIEW_MICROSOFT_URL;
  444. else if (!wcscmp (pmrv->pViewType, szMessageViewGUID))
  445. m_CustomViewID = VIEW_DEFAULT_MESSAGE_VIEW;
  446. else
  447. // doesn't look like one of mine, but it is:
  448. // if the URL leads to another URL. This is
  449. // sent to you can still maintain your checks
  450. // in the view menu.
  451. m_CustomViewID = VIEW_MICROSOFT_URL;
  452. // also, you could be re-directed via script or asp.
  453. // also, you may have neglected
  454. }
  455. break;
  456. // Note - Future expansion of notify types possible
  457. default:
  458. hr = E_UNEXPECTED;
  459. break;
  460. }
  461. if (pInternal != NULL)
  462. {
  463. ::GlobalFree(reinterpret_cast<HANDLE>(pInternal));
  464. }
  465. }
  466. if (m_pResult)
  467. m_pResult->SetDescBarText(L"hello world");
  468. return hr;
  469. }
  470. void CSnapin::_OnRefresh(LPDATAOBJECT pDataObject)
  471. {
  472. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  473. INTERNAL* pInternal = ExtractInternalFormat(pDataObject);
  474. if (pInternal == NULL)
  475. return;
  476. USES_CONVERSION;
  477. if (pInternal->m_type == CCT_SCOPE)
  478. {
  479. CComponentDataImpl* pData = dynamic_cast<CComponentDataImpl*>(m_pComponentData);
  480. if (pData->IsPrimaryImpl())
  481. {
  482. CFolder* pFolder = pData->FindObject(pInternal->m_cookie);
  483. ::AfxMessageBox(pInternal->m_cookie ? OLE2T(pFolder->m_pszName) : _T("Files"));
  484. pData->DeleteAndReinsertAll();
  485. }
  486. }
  487. else
  488. {
  489. RESULT_DATA* pData = reinterpret_cast<RESULT_DATA*>(pInternal->m_cookie);
  490. ::AfxMessageBox(OLE2T(pData->szName));
  491. }
  492. }
  493. HRESULT CSnapin::OnContextHelp(LPDATAOBJECT pdtobj)
  494. {
  495. TCHAR name[128];
  496. GetItemName(pdtobj, name);
  497. TCHAR buf[200];
  498. wsprintf(buf, _T("Context help requested for item: %s"), name);
  499. ::MessageBox(NULL, buf, _T("TRACE"), MB_OK);
  500. return S_OK;
  501. }
  502. STDMETHODIMP CSnapin::Destroy(MMC_COOKIE cookie)
  503. {
  504. DBX_PRINT(_T(" ---------- CSnapin::Destroy<0x08x>\n"), this);
  505. ASSERT(m_bInitializedC);
  506. m_bDestroyedC = true;
  507. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  508. // Release the interfaces that we QI'ed
  509. if (m_pConsole != NULL)
  510. {
  511. // Tell the console to release the header control interface
  512. m_pConsole->SetHeader(NULL);
  513. SAFE_RELEASE(m_pHeader);
  514. SAFE_RELEASE(m_pResult);
  515. SAFE_RELEASE(m_pImageResult);
  516. // Release the IConsole interface last
  517. SAFE_RELEASE(m_pConsole);
  518. SAFE_RELEASE(m_pComponentData); // QI'ed in IComponentDataImpl::CreateComponent
  519. SAFE_RELEASE(m_pConsoleVerb);
  520. }
  521. return S_OK;
  522. }
  523. typedef CArray<GUID, const GUID&> CGUIDArray;
  524. void GuidArray_Add(CGUIDArray& rgGuids, const GUID& guid)
  525. {
  526. for (int i=rgGuids.GetUpperBound(); i >= 0; --i)
  527. {
  528. if (rgGuids[i] == guid)
  529. break;
  530. }
  531. if (i < 0)
  532. rgGuids.Add(guid);
  533. }
  534. HRESULT CSnapin::QueryMultiSelectDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type,
  535. LPDATAOBJECT* ppDataObject)
  536. {
  537. ASSERT(ppDataObject != NULL);
  538. if (ppDataObject == NULL)
  539. return E_POINTER;
  540. CGUIDArray rgGuids;
  541. if (m_bVirtualView == TRUE)
  542. {
  543. GuidArray_Add(rgGuids, cNodeTypeCompany);
  544. }
  545. else
  546. {
  547. // Determine the items selected
  548. ASSERT(m_pResult != NULL);
  549. RESULTDATAITEM rdi;
  550. ZeroMemory(&rdi, sizeof(rdi));
  551. rdi.mask = RDI_STATE;
  552. rdi.nIndex = -1;
  553. rdi.nState = TVIS_SELECTED;
  554. while (m_pResult->GetNextItem(&rdi) == S_OK)
  555. {
  556. FOLDER_TYPES fType;
  557. DWORD* pdw = reinterpret_cast<DWORD*>(rdi.lParam);
  558. if (*pdw == SCOPE_ITEM)
  559. {
  560. CFolder* pFolder = reinterpret_cast<CFolder*>(rdi.lParam);
  561. fType = pFolder->m_type;
  562. }
  563. else
  564. {
  565. ASSERT(*pdw == RESULT_ITEM);
  566. RESULT_DATA* pData = reinterpret_cast<RESULT_DATA*>(rdi.lParam);
  567. fType = pData->parentType;
  568. }
  569. const GUID* pguid;
  570. switch (fType)
  571. {
  572. case STATIC:
  573. pguid = &cNodeTypeStatic;
  574. break;
  575. case COMPANY:
  576. pguid = &cNodeTypeCompany;
  577. break;
  578. case USER:
  579. pguid = &cNodeTypeUser;
  580. break;
  581. case EXT_COMPANY:
  582. pguid = &cNodeTypeExtCompany;
  583. break;
  584. case EXT_USER:
  585. pguid = &cNodeTypeExtUser;
  586. break;
  587. case VIRTUAL:
  588. case EXT_VIRTUAL:
  589. pguid = &cNodeTypeVirtual;
  590. break;
  591. default:
  592. return E_FAIL;
  593. }
  594. GuidArray_Add(rgGuids, *pguid);
  595. }
  596. }
  597. CComObject<CDataObject>* pObject;
  598. CComObject<CDataObject>::CreateInstance(&pObject);
  599. ASSERT(pObject != NULL);
  600. // Save cookie and type for delayed rendering
  601. pObject->SetType(type);
  602. pObject->SetCookie(cookie);
  603. pObject->SetMultiSelDobj();
  604. CComponentDataImpl* pImpl = dynamic_cast<CComponentDataImpl*>(m_pComponentData);
  605. #ifdef _DEBUG
  606. pObject->SetComponentData(pImpl);
  607. #endif
  608. // Store the coclass with the data object
  609. pObject->SetClsid(pImpl->GetCoClassID());
  610. UINT cb = rgGuids.GetSize() * sizeof(GUID);
  611. GUID* pGuid = new GUID[rgGuids.GetSize()];
  612. CopyMemory(pGuid, rgGuids.GetData(), cb);
  613. pObject->SetMultiSelData((BYTE*)pGuid, cb);
  614. return pObject->QueryInterface(IID_IDataObject,
  615. reinterpret_cast<void**>(ppDataObject));
  616. return S_OK;
  617. }
  618. STDMETHODIMP CSnapin::QueryDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type,
  619. LPDATAOBJECT* ppDataObject)
  620. {
  621. if (cookie == MMC_MULTI_SELECT_COOKIE)
  622. return QueryMultiSelectDataObject(cookie, type, ppDataObject);
  623. ASSERT(type == CCT_RESULT);
  624. #ifdef _DEBUG
  625. if (cookie != MMC_MULTI_SELECT_COOKIE &&
  626. m_bVirtualView == FALSE)
  627. {
  628. DWORD dwItemType = GetItemType(cookie);
  629. ASSERT(dwItemType == RESULT_ITEM);
  630. }
  631. #endif
  632. // Delegate it to the IComponentData
  633. ASSERT(m_pComponentData != NULL);
  634. CComponentDataImpl* pImpl = dynamic_cast<CComponentDataImpl*>(m_pComponentData);
  635. ASSERT(pImpl != NULL);
  636. return _QueryDataObject(cookie, type, pImpl, ppDataObject);
  637. }
  638. /////////////////////////////////////////////////////////////////////////////
  639. // CSnapin's implementation specific members
  640. DEBUG_DECLARE_INSTANCE_COUNTER(CSnapin);
  641. CSnapin::CSnapin()
  642. : m_bIsDirty(TRUE), m_bInitializedC(false), m_bDestroyedC(false)
  643. {
  644. DEBUG_INCREMENT_INSTANCE_COUNTER(CSnapin);
  645. Construct();
  646. }
  647. CSnapin::~CSnapin()
  648. {
  649. #if DBG==1
  650. ASSERT(dbg_cRef == 0);
  651. #endif
  652. DEBUG_DECREMENT_INSTANCE_COUNTER(CSnapin);
  653. SAFE_RELEASE(m_pToolbar1);
  654. SAFE_RELEASE(m_pToolbar2);
  655. SAFE_RELEASE(m_pMenuButton1);
  656. SAFE_RELEASE(m_pControlbar);
  657. // Make sure the interfaces have been released
  658. ASSERT(m_pConsole == NULL);
  659. ASSERT(m_pHeader == NULL);
  660. ASSERT(m_pToolbar1 == NULL);
  661. ASSERT(m_pToolbar2 == NULL);
  662. delete m_pbmpToolbar1;
  663. delete m_pbmpToolbar2;
  664. ASSERT(!m_bInitializedC || m_bDestroyedC);
  665. Construct();
  666. }
  667. void CSnapin::Construct()
  668. {
  669. #if DBG==1
  670. dbg_cRef = 0;
  671. #endif
  672. m_pConsole = NULL;
  673. m_pHeader = NULL;
  674. m_pResult = NULL;
  675. m_pImageResult = NULL;
  676. m_pComponentData = NULL;
  677. m_pToolbar1 = NULL;
  678. m_pToolbar2 = NULL;
  679. m_pControlbar = NULL;
  680. m_pMenuButton1 = NULL;
  681. m_pbmpToolbar1 = NULL;
  682. m_pbmpToolbar2 = NULL;
  683. m_pConsoleVerb = NULL;
  684. m_CustomViewID = VIEW_DEFAULT_LV;
  685. // m_CustomViewID = VIEW_MICROSOFT_URL;
  686. // m_CustomViewID = VIEW_CALENDAR_OCX;
  687. // m_CustomViewID = VIEW_DEFAULT_MESSAGE_VIEW;
  688. m_bVirtualView = FALSE;
  689. m_dwVirtualSortOptions = 0;
  690. }
  691. void CSnapin::LoadResources()
  692. {
  693. // Load strings from resources
  694. m_column1.LoadString(IDS_NAME);
  695. m_column2.LoadString(IDS_SIZE);
  696. m_column3.LoadString(IDS_TYPE);
  697. }
  698. HRESULT CSnapin::InitializeHeaders(MMC_COOKIE cookie)
  699. {
  700. HRESULT hr = S_OK;
  701. ASSERT(m_pHeader);
  702. USES_CONVERSION;
  703. // Put the correct headers depending on the cookie
  704. // Note - cookie ignored for this sample
  705. m_pHeader->InsertColumn(0, T2COLE(m_column1), LVCFMT_LEFT, 180); // Name
  706. m_pHeader->InsertColumn(1, T2COLE(m_column2), LVCFMT_RIGHT, 90); // Size
  707. m_pHeader->InsertColumn(2, T2COLE(m_column3), LVCFMT_LEFT, 160); // Type
  708. return hr;
  709. }
  710. HRESULT CSnapin::InitializeBitmaps(MMC_COOKIE cookie)
  711. {
  712. ASSERT(m_pImageResult != NULL);
  713. ::CBitmap bmp16x16;
  714. ::CBitmap bmp32x32;
  715. // Load the bitmaps from the dll
  716. bmp16x16.LoadBitmap(IDB_16x16);
  717. bmp32x32.LoadBitmap(IDB_32x32);
  718. // Set the images
  719. m_pImageResult->ImageListSetStrip(
  720. reinterpret_cast<PLONG_PTR>(static_cast<HBITMAP>(bmp16x16)),
  721. reinterpret_cast<PLONG_PTR>(static_cast<HBITMAP>(bmp32x32)),
  722. 0, RGB(255, 0, 255));
  723. return S_OK;
  724. }
  725. WCHAR* StringFromFolderType(FOLDER_TYPES type)
  726. {
  727. static WCHAR* s_szStatic = L"Static";
  728. static WCHAR* s_szCompany = L"Company";
  729. static WCHAR* s_szUser = L"User";
  730. static WCHAR* s_szVirtual = L"Virtual";
  731. static WCHAR* s_szUnknown = L"Unknown";
  732. switch (type)
  733. {
  734. case STATIC: return s_szStatic;
  735. case COMPANY: return s_szCompany;
  736. case USER: return s_szUser;
  737. case VIRTUAL: return s_szVirtual;
  738. default: return s_szUnknown;
  739. }
  740. }
  741. STDMETHODIMP CSnapin::GetDisplayInfo(LPRESULTDATAITEM pResult)
  742. {
  743. static WCHAR* s_szSize = L"200";
  744. ASSERT(pResult != NULL);
  745. if (pResult)
  746. {
  747. if (pResult->bScopeItem == TRUE)
  748. {
  749. CFolder* pFolder = reinterpret_cast<CFolder*>(pResult->lParam);
  750. if (pResult->mask & RDI_STR)
  751. {
  752. if (pResult->nCol == 0)
  753. pResult->str = pFolder->m_pszName;
  754. else if (pResult->nCol == 1)
  755. pResult->str = (LPOLESTR)s_szSize;
  756. else
  757. pResult->str = (LPOLESTR)StringFromFolderType(pFolder->m_type);
  758. ASSERT(pResult->str != NULL);
  759. if (pResult->str == NULL)
  760. pResult->str = (LPOLESTR)L"";
  761. }
  762. if (pResult->mask & RDI_IMAGE)
  763. {
  764. switch(pFolder->GetType())
  765. {
  766. case USER:
  767. case EXT_USER:
  768. pResult->nImage = USER_IMAGE;
  769. break;
  770. case COMPANY:
  771. case EXT_COMPANY:
  772. pResult->nImage = COMPANY_IMAGE;
  773. break;
  774. case VIRTUAL:
  775. pResult->nImage = VIRTUAL_IMAGE;
  776. break;
  777. }
  778. }
  779. }
  780. else
  781. {
  782. RESULT_DATA* pData;
  783. // if virtual, derive result item from index
  784. // else lParam is the item pointer
  785. if (m_bVirtualView)
  786. pData = GetVirtualResultItem(pResult->nIndex);
  787. else
  788. pData= reinterpret_cast<RESULT_DATA*>(pResult->lParam);
  789. if (pResult->mask & RDI_STR)
  790. {
  791. if (pResult->nCol == 0)
  792. pResult->str = (LPOLESTR)pData->szName;
  793. else if(pResult->nCol == 1)
  794. pResult->str = (LPOLESTR)pData->szSize;
  795. else
  796. pResult->str = (LPOLESTR)pData->szType;
  797. ASSERT(pResult->str != NULL);
  798. if (pResult->str == NULL)
  799. pResult->str = (LPOLESTR)L"";
  800. }
  801. // MMC can request image and indent for virtual data
  802. if (pResult->mask & RDI_IMAGE)
  803. pResult->nImage = 4;
  804. }
  805. }
  806. return S_OK;
  807. }
  808. /////////////////////////////////////////////////////////////////////////////
  809. // IExtendContextMenu Implementation
  810. // Array of menu item commands to be inserted into the contest menu.
  811. // Note - the first item is the menu text, // CCM_SPECIAL_DEFAULT_ITEM
  812. // the second item is the status string
  813. static CONTEXTMENUITEM menuItems[] =
  814. {
  815. {
  816. L"Command 1", L"Sample extension menu added by snapin (Command 1)",
  817. IDM_COMMAND1, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, 0
  818. },
  819. {
  820. L"Command 2", L"Sample extension menu added by snapin (Command 2)",
  821. IDM_COMMAND2, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, 0
  822. },
  823. { NULL, NULL, 0, 0, 0 }
  824. };
  825. // Array of view items to be inserted into the context menu.
  826. static CONTEXTMENUITEM viewItems[] =
  827. {
  828. {
  829. L"Message View", L"Default message view",
  830. IDM_DEFAULT_MESSAGE_VIEW, CCM_INSERTIONPOINTID_PRIMARY_VIEW, 0, 0
  831. },
  832. {
  833. L"Calendar", L"Sample OCX custom view",
  834. IDM_SAMPLE_OCX_VIEW, CCM_INSERTIONPOINTID_PRIMARY_VIEW, 0, 0
  835. },
  836. {
  837. szMicrosoftURL, L"Sample WEB custom view",
  838. IDM_SAMPLE_WEB_VIEW, CCM_INSERTIONPOINTID_PRIMARY_VIEW, 0, 0
  839. },
  840. { NULL, NULL, 0, 0, 0 },
  841. };
  842. // guid for custom view
  843. static GUID CLSID_SmGraphControl =
  844. {0xC4D2D8E0L,0xD1DD,0x11CE,0x94,0x0F,0x00,0x80,0x29,0x00,0x43,0x47};
  845. STDMETHODIMP CSnapin::AddMenuItems(LPDATAOBJECT pDataObject,
  846. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  847. long *pInsertionAllowed)
  848. {
  849. #if 1 //testing
  850. ASSERT(pDataObject != NULL);
  851. if (pDataObject && IsMMCMultiSelectDataObject(pDataObject))
  852. {
  853. static CLIPFORMAT s_cf = 0;
  854. if (s_cf == 0)
  855. {
  856. USES_CONVERSION;
  857. s_cf = (CLIPFORMAT)RegisterClipboardFormat(W2T(CCF_MULTI_SELECT_SNAPINS));
  858. }
  859. FORMATETC fmt = {s_cf, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  860. STGMEDIUM stgm = { TYMED_HGLOBAL, NULL };
  861. HRESULT hr = pDataObject->GetData(&fmt, &stgm);
  862. SMMCDataObjects* pData = (SMMCDataObjects*)stgm.hGlobal;
  863. int count = pData->count;
  864. IDataObject* pDO = NULL;
  865. hr = pData->lpDataObject[0]->QueryInterface(IID_IDataObject, (void**)&pDO);
  866. pDO->Release();
  867. }
  868. #endif
  869. viewItems[0].fFlags = (m_CustomViewID == VIEW_DEFAULT_MESSAGE_VIEW) ? MF_CHECKED : 0;
  870. viewItems[1].fFlags = (m_CustomViewID == VIEW_CALENDAR_OCX) ? MF_CHECKED : 0;
  871. viewItems[2].fFlags = (m_CustomViewID == VIEW_MICROSOFT_URL) ? MF_CHECKED : 0;
  872. CComponentDataImpl* pCCD = dynamic_cast<CComponentDataImpl*>(m_pComponentData);
  873. HRESULT hr = pCCD->AddMenuItems(pDataObject, pContextMenuCallback, pInsertionAllowed);
  874. #if 0
  875. /*
  876. * add do-nothing commands on odd numbered items in the virtual list view
  877. */
  878. if (SUCCEEDED (hr) && (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP) && m_bVirtualView)
  879. {
  880. INTERNAL* pInternal = pDataObject ? ExtractInternalFormat(pDataObject) : NULL;
  881. if (pInternal && (pInternal->m_cookie % 2))
  882. {
  883. CONTEXTMENUITEM cmi;
  884. cmi.strName = L"Another command (odd, virtual-only)";
  885. cmi.strStatusBarText = NULL;
  886. cmi.lCommandID = 0xDDDD;
  887. cmi.lInsertionPointID = CCM_INSERTIONPOINTID_PRIMARY_TOP;
  888. cmi.fFlags = 0;
  889. cmi.fSpecialFlags = 0;
  890. pContextMenuCallback->AddItem (&cmi);
  891. ReleaseInternalFormat (pInternal);
  892. }
  893. }
  894. #endif
  895. return (hr);
  896. }
  897. STDMETHODIMP CSnapin::Command(long nCommandID, LPDATAOBJECT pDataObject)
  898. {
  899. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  900. INTERNAL* pInternal = ExtractInternalFormat(pDataObject);
  901. if (pInternal == NULL)
  902. return E_FAIL;
  903. if (pInternal->m_type == CCT_SCOPE)
  904. {
  905. // Handle view specific commands here
  906. switch (nCommandID)
  907. {
  908. case IDM_SAMPLE_WEB_VIEW:
  909. case IDM_SAMPLE_OCX_VIEW:
  910. case IDM_DEFAULT_MESSAGE_VIEW:
  911. m_CustomViewID =
  912. (nCommandID == IDM_SAMPLE_OCX_VIEW) ? VIEW_CALENDAR_OCX :
  913. (nCommandID == IDM_SAMPLE_WEB_VIEW) ? VIEW_MICROSOFT_URL :
  914. VIEW_DEFAULT_MESSAGE_VIEW;
  915. // Ask console to reslelect the node to force a new view
  916. if (pInternal->m_cookie == 0)
  917. {
  918. CComponentDataImpl* pCCDI =
  919. dynamic_cast<CComponentDataImpl*>(m_pComponentData);
  920. ASSERT(pCCDI != NULL);
  921. m_pConsole->SelectScopeItem(pCCDI->m_pStaticRoot);
  922. }
  923. else
  924. {
  925. CFolder* pFolder = reinterpret_cast<CFolder*>(pInternal->m_cookie);
  926. m_pConsole->SelectScopeItem(pFolder->m_pScopeItem->ID);
  927. }
  928. break;
  929. case MMCC_STANDARD_VIEW_SELECT:
  930. m_CustomViewID = VIEW_DEFAULT_LV;
  931. break;
  932. default:
  933. // Pass non-view specific commands to ComponentData
  934. return dynamic_cast<CComponentDataImpl*>(m_pComponentData)->
  935. Command(nCommandID, pDataObject);
  936. }
  937. }
  938. else if (pInternal->m_type == CCT_RESULT)
  939. {
  940. // Handle each of the commands.
  941. switch (nCommandID)
  942. {
  943. case IDM_COMMAND1:
  944. case IDM_COMMAND2:
  945. {
  946. m_pResult->ModifyViewStyle(MMC_SINGLESEL, (MMC_RESULT_VIEW_STYLE)0);
  947. RESULTDATAITEM rdi;
  948. ZeroMemory(&rdi, sizeof(rdi));
  949. rdi.mask = RDI_STATE;
  950. rdi.nState = LVIS_SELECTED;
  951. rdi.nIndex = -1;
  952. m_pResult->GetNextItem(&rdi);
  953. int iSel = rdi.nIndex;
  954. int nImage = rdi.nImage;
  955. HRESULTITEM hri = 0;
  956. RESULT_DATA* pData;
  957. // if virtual view, derive result item from the index
  958. if (m_bVirtualView)
  959. {
  960. pData = GetVirtualResultItem(iSel);
  961. }
  962. // else get the cookie (which is result item ptr)
  963. else
  964. {
  965. ZeroMemory(&rdi, sizeof(rdi));
  966. rdi.mask = RDI_PARAM | RDI_IMAGE;
  967. rdi.nIndex = iSel;
  968. HRESULT hr = m_pResult->GetItem(&rdi);
  969. nImage = rdi.nImage;
  970. ASSERT(SUCCEEDED(hr));
  971. ASSERT(rdi.lParam != 0);
  972. m_pResult->FindItemByLParam (rdi.lParam, &hri);
  973. pData = reinterpret_cast<RESULT_DATA*>(rdi.lParam);
  974. }
  975. #if 0
  976. static int nIconIndex = 12;
  977. nIconIndex = (nIconIndex == 12) ? 13 : 12;
  978. HICON hIcon = ExtractIcon (AfxGetInstanceHandle(),
  979. _T("%SystemRoot%\\system32\\shell32.dll"),
  980. nIconIndex);
  981. IImageList* pil;
  982. m_pConsole->QueryResultImageList(&pil);
  983. _asm int 3;
  984. pil->ImageListSetIcon((LONG_PTR*) hIcon, nImage);
  985. pil->ImageListSetIcon((LONG_PTR*) hIcon, ILSI_SMALL_ICON (nImage));
  986. pil->ImageListSetIcon((LONG_PTR*) hIcon, ILSI_LARGE_ICON (nImage));
  987. pil->Release();
  988. m_pResult->UpdateItem (hri);
  989. #else
  990. CString strBuf = (nCommandID == IDM_COMMAND1) ?
  991. _T("\t Command 1 executed.\n\n") : _T("\t Command 2 executed.\n\n");
  992. strBuf += pData->szName;
  993. strBuf += _T(" is the currently selected item.");
  994. AfxMessageBox(strBuf);
  995. // change image in list
  996. if (!m_bVirtualView)
  997. {
  998. ZeroMemory(&rdi, sizeof(rdi));
  999. rdi.mask = RDI_IMAGE;
  1000. rdi.nIndex = iSel;
  1001. rdi.nImage = 3;
  1002. HRESULT hr = m_pResult->SetItem(&rdi);
  1003. ASSERT(SUCCEEDED(hr));
  1004. }
  1005. #endif
  1006. }
  1007. break;
  1008. default:
  1009. ASSERT(FALSE); // Unknown command!
  1010. break;
  1011. }
  1012. }
  1013. else
  1014. {
  1015. ASSERT(0);
  1016. }
  1017. ::GlobalFree(reinterpret_cast<HANDLE>(pInternal));
  1018. return S_OK;
  1019. }
  1020. STDMETHODIMP CSnapin::GetClassID(CLSID *pClassID)
  1021. {
  1022. ASSERT(pClassID != NULL);
  1023. // Copy the CLSID for this snapin
  1024. *pClassID = CLSID_Snapin;
  1025. return E_NOTIMPL;
  1026. }
  1027. STDMETHODIMP CSnapin::IsDirty()
  1028. {
  1029. // Always save / Always dirty.
  1030. return ThisIsDirty() ? S_OK : S_FALSE;
  1031. }
  1032. STDMETHODIMP CSnapin::Load(IStream *pStm)
  1033. {
  1034. DBX_PRINT(_T(" ---------- CSnapin::Load<0x08x>\n"), this);
  1035. ASSERT(m_bInitializedC);
  1036. ASSERT(pStm);
  1037. // Read the string
  1038. char psz[10];
  1039. ULONG nBytesRead;
  1040. HRESULT hr = pStm->Read(psz, 10, &nBytesRead);
  1041. // Verify that the read succeeded
  1042. ASSERT(SUCCEEDED(hr) && nBytesRead == 10);
  1043. // check to see if the string is the correct string
  1044. ASSERT(strcmp("987654321", psz) == 0);
  1045. ClearDirty();
  1046. return SUCCEEDED(hr) ? S_OK : E_FAIL;
  1047. }
  1048. STDMETHODIMP CSnapin::Save(IStream *pStm, BOOL fClearDirty)
  1049. {
  1050. DBX_PRINT(_T(" ---------- CSnapin::Save<0x08x>\n"), this);
  1051. ASSERT(m_bInitializedC);
  1052. ASSERT(pStm);
  1053. // Write the string
  1054. ULONG nBytesWritten;
  1055. HRESULT hr = pStm->Write("987654321", 10, &nBytesWritten);
  1056. // Verify that the write operation succeeded
  1057. ASSERT(SUCCEEDED(hr) && nBytesWritten == 10);
  1058. if (FAILED(hr))
  1059. return STG_E_CANTSAVE;
  1060. if (fClearDirty)
  1061. ClearDirty();
  1062. return S_OK;
  1063. }
  1064. STDMETHODIMP CSnapin::GetSizeMax(ULARGE_INTEGER *pcbSize)
  1065. {
  1066. ASSERT(pcbSize);
  1067. // Set the size of the string to be saved
  1068. ULISet32(*pcbSize, 10);
  1069. return S_OK;
  1070. }
  1071. ///////////////////////////////////////////////////////////////////////////////
  1072. // IComponentData implementation
  1073. DEBUG_DECLARE_INSTANCE_COUNTER(CComponentDataImpl);
  1074. CComponentDataImpl::CComponentDataImpl()
  1075. : m_bIsDirty(TRUE), m_pScope(NULL), m_pConsole(NULL),
  1076. m_bInitializedCD(false), m_bDestroyedCD(false)
  1077. {
  1078. DEBUG_INCREMENT_INSTANCE_COUNTER(CComponentDataImpl);
  1079. #ifdef _DEBUG
  1080. m_cDataObjects = 0;
  1081. #endif
  1082. }
  1083. CComponentDataImpl::~CComponentDataImpl()
  1084. {
  1085. DEBUG_DECREMENT_INSTANCE_COUNTER(CComponentDataImpl);
  1086. ASSERT(m_pScope == NULL);
  1087. ASSERT(!m_bInitializedCD || m_bDestroyedCD);
  1088. // Some snap-in is hanging on to data objects.
  1089. // If they access, it will crash!!!
  1090. ASSERT(m_cDataObjects <= 1);
  1091. }
  1092. STDMETHODIMP CComponentDataImpl::Initialize(LPUNKNOWN pUnknown)
  1093. {
  1094. DBX_PRINT(_T(" ---------- CComponentDataImpl::Initialize<0x08x>\n"), this);
  1095. m_bInitializedCD = true;
  1096. ASSERT(pUnknown != NULL);
  1097. HRESULT hr;
  1098. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1099. // MMC should only call ::Initialize once!
  1100. ASSERT(m_pScope == NULL);
  1101. pUnknown->QueryInterface(IID_IConsoleNameSpace,
  1102. reinterpret_cast<void**>(&m_pScope));
  1103. // add the images for the scope tree
  1104. ::CBitmap bmp16x16;
  1105. LPIMAGELIST lpScopeImage;
  1106. hr = pUnknown->QueryInterface(IID_IConsole, reinterpret_cast<void**>(&m_pConsole));
  1107. ASSERT(hr == S_OK);
  1108. hr = m_pConsole->QueryScopeImageList(&lpScopeImage);
  1109. ASSERT(hr == S_OK);
  1110. // Load the bitmaps from the dll
  1111. bmp16x16.LoadBitmap(IDB_16x16);
  1112. // Set the images
  1113. lpScopeImage->ImageListSetStrip(
  1114. reinterpret_cast<PLONG_PTR>(static_cast<HBITMAP>(bmp16x16)),
  1115. reinterpret_cast<PLONG_PTR>(static_cast<HBITMAP>(bmp16x16)),
  1116. 0, RGB(255, 0, 255));
  1117. lpScopeImage->Release();
  1118. return S_OK;
  1119. }
  1120. STDMETHODIMP CComponentDataImpl::CreateComponent(LPCOMPONENT* ppComponent)
  1121. {
  1122. ASSERT(ppComponent != NULL);
  1123. CComObject<CSnapin>* pObject;
  1124. CComObject<CSnapin>::CreateInstance(&pObject);
  1125. ASSERT(pObject != NULL);
  1126. // Store IComponentData
  1127. pObject->SetIComponentData(this);
  1128. return pObject->QueryInterface(IID_IComponent,
  1129. reinterpret_cast<void**>(ppComponent));
  1130. }
  1131. STDMETHODIMP CComponentDataImpl::Notify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param)
  1132. {
  1133. AFX_MANAGE_STATE (AfxGetStaticModuleState());
  1134. ASSERT(m_pScope != NULL);
  1135. HRESULT hr;
  1136. // Since it's my folder it has an internal format.
  1137. // Design Note: for extension. I can use the fact, that the data object doesn't have
  1138. // my internal format and I should look at the node type and see how to extend it.
  1139. if (event == MMCN_PROPERTY_CHANGE)
  1140. {
  1141. hr = OnProperties(param);
  1142. }
  1143. else
  1144. {
  1145. INTERNAL* pInternal = ExtractInternalFormat(lpDataObject);
  1146. if (pInternal == NULL)
  1147. {
  1148. return S_OK;
  1149. }
  1150. MMC_COOKIE cookie = pInternal->m_cookie;
  1151. ::GlobalFree(reinterpret_cast<HANDLE>(pInternal));
  1152. switch(event)
  1153. {
  1154. case MMCN_PASTE:
  1155. AfxMessageBox(_T("CSnapin::MMCN_PASTE"));
  1156. break;
  1157. case MMCN_DELETE:
  1158. AfxMessageBox(_T("CD::MMCN_DELETE"));
  1159. //hr = OnDelete(cookie);
  1160. break;
  1161. case MMCN_REMOVE_CHILDREN:
  1162. hr = OnRemoveChildren(arg);
  1163. break;
  1164. case MMCN_RENAME:
  1165. hr = OnRename(cookie, arg, param);
  1166. break;
  1167. case MMCN_EXPAND:
  1168. hr = OnExpand(lpDataObject, arg, param);
  1169. break;
  1170. default:
  1171. break;
  1172. }
  1173. }
  1174. return hr;
  1175. }
  1176. STDMETHODIMP CComponentDataImpl::Destroy()
  1177. {
  1178. DBX_PRINT(_T(" ---------- CComponentDataImpl::Destroy<0x08x>\n"), this);
  1179. ASSERT(m_bInitializedCD);
  1180. m_bDestroyedCD = true;
  1181. // Delete enumerated scope items
  1182. DeleteList();
  1183. SAFE_RELEASE(m_pScope);
  1184. SAFE_RELEASE(m_pConsole);
  1185. return S_OK;
  1186. }
  1187. STDMETHODIMP CComponentDataImpl::QueryDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type, LPDATAOBJECT* ppDataObject)
  1188. {
  1189. #ifdef _DEBUG
  1190. if (cookie == 0)
  1191. {
  1192. ASSERT(type != CCT_RESULT);
  1193. }
  1194. else
  1195. {
  1196. ASSERT(type == CCT_SCOPE);
  1197. DWORD dwItemType = GetItemType(cookie);
  1198. ASSERT(dwItemType == SCOPE_ITEM);
  1199. }
  1200. #endif
  1201. return _QueryDataObject(cookie, type, this, ppDataObject);
  1202. }
  1203. ///////////////////////////////////////////////////////////////////////////////
  1204. //// IPersistStream interface members
  1205. STDMETHODIMP CComponentDataImpl::GetClassID(CLSID *pClassID)
  1206. {
  1207. ASSERT(pClassID != NULL);
  1208. // Copy the CLSID for this snapin
  1209. *pClassID = CLSID_Snapin;
  1210. return E_NOTIMPL;
  1211. }
  1212. STDMETHODIMP CComponentDataImpl::IsDirty()
  1213. {
  1214. // Always save / Always dirty.
  1215. return ThisIsDirty() ? S_OK : S_FALSE;
  1216. }
  1217. STDMETHODIMP CComponentDataImpl::Load(IStream *pStm)
  1218. {
  1219. DBX_PRINT(_T(" ---------- CComponentDataImpl::Load<0x08x>\n"), this);
  1220. ASSERT(pStm);
  1221. ASSERT(m_bInitializedCD);
  1222. // Read the string
  1223. char psz[10];
  1224. ULONG nBytesRead;
  1225. HRESULT hr = pStm->Read(psz, 10, &nBytesRead);
  1226. // Verify that the read succeeded
  1227. ASSERT(SUCCEEDED(hr) && nBytesRead == 10);
  1228. // check to see if the string is the correct string
  1229. ASSERT(strcmp("123456789", psz) == 0);
  1230. ClearDirty();
  1231. return SUCCEEDED(hr) ? S_OK : E_FAIL;
  1232. }
  1233. STDMETHODIMP CComponentDataImpl::Save(IStream *pStm, BOOL fClearDirty)
  1234. {
  1235. DBX_PRINT(_T(" ---------- CComponentDataImpl::Save<0x08x>\n"), this);
  1236. ASSERT(pStm);
  1237. ASSERT(m_bInitializedCD);
  1238. // Write the string
  1239. ULONG nBytesWritten;
  1240. HRESULT hr = pStm->Write("123456789", 10, &nBytesWritten);
  1241. // Verify that the write operation succeeded
  1242. ASSERT(SUCCEEDED(hr) && nBytesWritten == 10);
  1243. if (FAILED(hr))
  1244. return STG_E_CANTSAVE;
  1245. if (fClearDirty)
  1246. ClearDirty();
  1247. return S_OK;
  1248. }
  1249. STDMETHODIMP CComponentDataImpl::GetSizeMax(ULARGE_INTEGER *pcbSize)
  1250. {
  1251. ASSERT(pcbSize);
  1252. // Set the size of the string to be saved
  1253. ULISet32(*pcbSize, 10);
  1254. return S_OK;
  1255. }
  1256. ///////////////////////////////////////////////////////////////////////////////
  1257. //// Notify handlers for IComponentData
  1258. HRESULT CComponentDataImpl::OnDelete(MMC_COOKIE cookie)
  1259. {
  1260. return S_OK;
  1261. }
  1262. HRESULT CComponentDataImpl::OnRemoveChildren(LPARAM arg)
  1263. {
  1264. return S_OK;
  1265. }
  1266. HRESULT CComponentDataImpl::OnRename(MMC_COOKIE cookie, LPARAM arg, LPARAM param)
  1267. {
  1268. if (arg == 0)
  1269. return S_OK;
  1270. LPOLESTR pszNewName = reinterpret_cast<LPOLESTR>(param);
  1271. if (pszNewName == NULL)
  1272. return E_INVALIDARG;
  1273. CFolder* pFolder = reinterpret_cast<CFolder*>(cookie);
  1274. ASSERT(pFolder != NULL);
  1275. if (pFolder == NULL)
  1276. return E_INVALIDARG;
  1277. pFolder->SetName(pszNewName);
  1278. return S_OK;
  1279. }
  1280. HRESULT CComponentDataImpl::OnExpand(LPDATAOBJECT lpDataObject, LPARAM arg, LPARAM param)
  1281. {
  1282. if (arg == TRUE)
  1283. {
  1284. // Did Initialize get called?
  1285. ASSERT(m_pScope != NULL);
  1286. EnumerateScopePane(lpDataObject, param);
  1287. }
  1288. return S_OK;
  1289. }
  1290. HRESULT CComponentDataImpl::OnSelect(MMC_COOKIE cookie, LPARAM arg, LPARAM param)
  1291. {
  1292. return E_UNEXPECTED;
  1293. }
  1294. HRESULT CComponentDataImpl::OnProperties(LPARAM param)
  1295. {
  1296. if (param == NULL)
  1297. {
  1298. return S_OK;
  1299. }
  1300. ASSERT(param != NULL);
  1301. CFolder* pFolder = new CFolder();
  1302. // Create a new folder object
  1303. pFolder->Create( reinterpret_cast<LPOLESTR>(param), 0, 0, STATIC, FALSE);
  1304. // The static folder in the last item in the list
  1305. POSITION pos = m_scopeItemList.GetTailPosition();
  1306. if (pos == 0)
  1307. {
  1308. // CreateFolderList();
  1309. pos = m_scopeItemList.GetTailPosition();
  1310. }
  1311. ASSERT(pos);
  1312. // Add it to the internal list
  1313. if (pos)
  1314. {
  1315. CFolder* pItem = m_scopeItemList.GetAt(pos);
  1316. m_scopeItemList.InsertBefore(pos, pFolder);
  1317. pFolder->m_pScopeItem->relativeID = pItem->m_pScopeItem->relativeID;
  1318. // Set the folder as the cookie
  1319. pFolder->m_pScopeItem->mask |= SDI_PARAM;
  1320. pFolder->m_pScopeItem->lParam = reinterpret_cast<LPARAM>(pFolder);
  1321. pFolder->SetCookie(reinterpret_cast<MMC_COOKIE>(pFolder));
  1322. m_pScope->InsertItem(pFolder->m_pScopeItem);
  1323. }
  1324. ::GlobalFree(reinterpret_cast<void*>(param));
  1325. return S_OK;
  1326. }
  1327. void CComponentDataImpl::CreateFolderList(LPDATAOBJECT lpDataObject)
  1328. {
  1329. CFolder* pFolder;
  1330. ASSERT(lpDataObject != NULL);
  1331. wchar_t* pWkStation = ExtractWorkstation(lpDataObject);
  1332. ASSERT(pWkStation != NULL);
  1333. CLSID* pCoClassID = ExtractClassID(lpDataObject);
  1334. ASSERT(pCoClassID != NULL);
  1335. // Determine which folder set to use based on context information
  1336. FOLDER_DATA* pFolderSet = FolderData;
  1337. BOOL bExtend = FALSE;
  1338. if (!IsEqualCLSID(*pCoClassID, GetCoClassID()))
  1339. {
  1340. pFolderSet = ExtFolderData;
  1341. bExtend = TRUE;
  1342. // TRACE(_T("Using Extension Data\n"));
  1343. }
  1344. ASSERT(m_scopeItemList.GetCount() == 0);
  1345. wchar_t buf[100];
  1346. for (int i=0; i < NUM_FOLDERS; i++)
  1347. {
  1348. pFolder = new CFolder();
  1349. buf[0] = NULL;
  1350. USES_CONVERSION;
  1351. wcscpy(buf, pFolderSet[i].szName);
  1352. // Add context info to the folder name
  1353. if (bExtend)
  1354. wcscat(buf, pWkStation);
  1355. int nImage = 0;
  1356. switch(pFolderSet[i].type)
  1357. {
  1358. case USER:
  1359. case EXT_USER:
  1360. nImage = USER_IMAGE;
  1361. break;
  1362. case COMPANY:
  1363. case EXT_COMPANY:
  1364. nImage = COMPANY_IMAGE;
  1365. break;
  1366. case VIRTUAL:
  1367. nImage = VIRTUAL_IMAGE;
  1368. break;
  1369. }
  1370. // Create the folder objects with static data
  1371. pFolder->Create(buf, nImage/*FOLDER_IMAGE_IDX*/, OPEN_FOLDER_IMAGE_IDX,
  1372. pFolderSet[i].type, FALSE);
  1373. m_scopeItemList.AddTail(pFolder);
  1374. }
  1375. // mark cookie for last item
  1376. pFolder->SetCookie(NULL);
  1377. // Free memory from data object extraction
  1378. ::GlobalFree(reinterpret_cast<HGLOBAL>(pWkStation));
  1379. ::GlobalFree(reinterpret_cast<HGLOBAL>(pCoClassID));
  1380. }
  1381. void CComponentDataImpl::EnumerateScopePane(LPDATAOBJECT lpDataObject, HSCOPEITEM pParent)
  1382. {
  1383. int i;
  1384. ASSERT(m_pScope != NULL); // make sure we QI'ed for the interface
  1385. ASSERT(lpDataObject != NULL);
  1386. INTERNAL* pInternal = ExtractInternalFormat(lpDataObject);
  1387. if (pInternal == NULL)
  1388. return ;
  1389. MMC_COOKIE cookie = pInternal->m_cookie;
  1390. #ifndef RECURSIVE_NODE_EXPANSION
  1391. // Only the static node has enumerated children
  1392. if (cookie != NULL)
  1393. return ;
  1394. #endif
  1395. ::GlobalFree(reinterpret_cast<HANDLE>(pInternal));
  1396. // Initialize folder list if empty
  1397. if (m_scopeItemList.GetCount() == 0)
  1398. CreateFolderList(lpDataObject);
  1399. // Enumerate the scope pane
  1400. // return the folder object that represents the cookie
  1401. // Note - for large list, use dictionary
  1402. CFolder* pStatic = FindObject(cookie);
  1403. #ifndef RECURSIVE_NODE_EXPANSION
  1404. ASSERT(!pStatic->IsEnumerated());
  1405. // Note - Each cookie in the scope pane represents a folder.
  1406. // A released product may have more then one level of children.
  1407. // This sample assumes the parent node is one level deep.
  1408. #endif
  1409. ASSERT(pParent != NULL);
  1410. // Cache the HSCOPEITEM of the static root.
  1411. if (cookie == NULL)
  1412. m_pStaticRoot = pParent;
  1413. POSITION pos = m_scopeItemList.GetHeadPosition();
  1414. CFolder* pFolder;
  1415. for (i=0; (i < (NUM_FOLDERS - 1)) && (pos != NULL); i++)
  1416. {
  1417. pFolder = m_scopeItemList.GetNext(pos);
  1418. ASSERT(pFolder);
  1419. // Set the parent
  1420. pFolder->m_pScopeItem->relativeID = pParent;
  1421. // Set the folder as the cookie
  1422. pFolder->m_pScopeItem->mask |= SDI_PARAM;
  1423. pFolder->m_pScopeItem->lParam = reinterpret_cast<LPARAM>(pFolder);
  1424. pFolder->SetCookie(reinterpret_cast<MMC_COOKIE>(pFolder));
  1425. m_pScope->InsertItem(pFolder->m_pScopeItem);
  1426. // Note - On return, the ID member of 'm_pScopeItem'
  1427. // contains the handle to the newly inserted item!
  1428. ASSERT(pFolder->m_pScopeItem->ID != NULL);
  1429. }
  1430. // Last folder added is the static folder
  1431. pStatic->Set(TRUE); // folder has been enumerated
  1432. pStatic->m_pScopeItem->relativeID = pParent;
  1433. }
  1434. void CComponentDataImpl::DeleteAndReinsertAll()
  1435. {
  1436. ASSERT(m_pScope != NULL); // make sure we QI'ed for the interface
  1437. ASSERT (m_scopeItemList.GetCount() > 0);
  1438. //m_pStaticRoot
  1439. HRESULT hr = m_pScope->DeleteItem(m_pStaticRoot, FALSE);
  1440. ASSERT(SUCCEEDED(hr));
  1441. POSITION pos = m_scopeItemList.GetHeadPosition();
  1442. CFolder* pFolder;
  1443. for (UINT i=0; (i < (NUM_FOLDERS - 1)) && (pos != NULL); i++)
  1444. {
  1445. pFolder = m_scopeItemList.GetNext(pos);
  1446. ASSERT(pFolder);
  1447. // clear old ID
  1448. pFolder->m_pScopeItem->ID = NULL;
  1449. // Set the parent
  1450. pFolder->m_pScopeItem->relativeID = m_pStaticRoot;
  1451. // Set the folder as the cookie
  1452. pFolder->m_pScopeItem->mask |= SDI_PARAM;
  1453. pFolder->m_pScopeItem->lParam = reinterpret_cast<LPARAM>(pFolder);
  1454. pFolder->SetCookie(reinterpret_cast<MMC_COOKIE>(pFolder));
  1455. m_pScope->InsertItem(pFolder->m_pScopeItem);
  1456. // Note - On return, the ID member of 'm_pScopeItem'
  1457. // contains the handle to the newly inserted item!
  1458. ASSERT(pFolder->m_pScopeItem->ID != NULL);
  1459. }
  1460. }
  1461. void CComponentDataImpl::DeleteList()
  1462. {
  1463. POSITION pos = m_scopeItemList.GetHeadPosition();
  1464. while (pos)
  1465. delete m_scopeItemList.GetNext(pos);
  1466. }
  1467. CFolder* CComponentDataImpl::FindObject(MMC_COOKIE cookie)
  1468. {
  1469. POSITION pos = m_scopeItemList.GetHeadPosition();
  1470. CFolder* pFolder = NULL;
  1471. while(pos)
  1472. {
  1473. pFolder = m_scopeItemList.GetNext(pos);
  1474. if (*pFolder == cookie)
  1475. return pFolder;
  1476. }
  1477. return NULL;
  1478. }
  1479. STDMETHODIMP CComponentDataImpl::GetDisplayInfo(SCOPEDATAITEM* pScopeDataItem)
  1480. {
  1481. ASSERT(pScopeDataItem != NULL);
  1482. if (pScopeDataItem == NULL)
  1483. return E_POINTER;
  1484. CFolder* pFolder = reinterpret_cast<CFolder*>(pScopeDataItem->lParam);
  1485. ASSERT(pScopeDataItem->mask & SDI_STR);
  1486. pScopeDataItem->displayname = pFolder ? pFolder->m_pszName : L"Snapin Data";
  1487. //ASSERT(pScopeDataItem->displayname != NULL);
  1488. return S_OK;
  1489. }
  1490. STDMETHODIMP CComponentDataImpl::CompareObjects(LPDATAOBJECT lpDataObjectA, LPDATAOBJECT lpDataObjectB)
  1491. {
  1492. if (lpDataObjectA == NULL || lpDataObjectB == NULL)
  1493. return E_POINTER;
  1494. // Make sure both data object are mine
  1495. INTERNAL* pA;
  1496. INTERNAL* pB;
  1497. HRESULT hr = S_FALSE;
  1498. pA = ExtractInternalFormat(lpDataObjectA);
  1499. pB = ExtractInternalFormat(lpDataObjectA);
  1500. if (pA != NULL && pB != NULL)
  1501. hr = (*pA == *pB) ? S_OK : S_FALSE;
  1502. ::GlobalFree(reinterpret_cast<HANDLE>(pA));
  1503. ::GlobalFree(reinterpret_cast<HANDLE>(pB));
  1504. return hr;
  1505. }
  1506. /////////////////////////////////////////////////////////////////////////////
  1507. // IExtendPropertySheet2 Implementation
  1508. HRESULT CComponentDataImpl::DoInsertWizard(LPPROPERTYSHEETCALLBACK lpProvider)
  1509. {
  1510. CStartUpWizard* pWizard = new CStartUpWizard;
  1511. CStartupWizard1* pWizard1 = new CStartupWizard1;
  1512. MMCPropPageCallback(&pWizard->m_psp97);
  1513. MMCPropPageCallback(&pWizard1->m_psp97);
  1514. HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pWizard->m_psp97);
  1515. if (hPage == NULL)
  1516. return E_UNEXPECTED;
  1517. lpProvider->AddPage(hPage);
  1518. hPage = CreatePropertySheetPage(&pWizard1->m_psp97);
  1519. if (hPage == NULL)
  1520. return E_UNEXPECTED;
  1521. lpProvider->AddPage(hPage);
  1522. return S_OK;
  1523. }
  1524. STDMETHODIMP
  1525. CComponentDataImpl::GetWatermarks(
  1526. LPDATAOBJECT lpIDataObject,
  1527. HBITMAP* lphWatermark,
  1528. HBITMAP* lphHeader,
  1529. HPALETTE* lphPalette,
  1530. BOOL* pbStretch)
  1531. {
  1532. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1533. *lphHeader = ::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BANNER));
  1534. *lphWatermark = ::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_WATERMARK));
  1535. *pbStretch = TRUE; // force the watermark bitmap to stretch
  1536. return S_OK;
  1537. }
  1538. STDMETHODIMP CComponentDataImpl::CreatePropertyPages(LPPROPERTYSHEETCALLBACK lpProvider,
  1539. LONG_PTR handle,
  1540. LPDATAOBJECT lpIDataObject)
  1541. {
  1542. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1543. // Look at the data object and determine if this an extension or a primary
  1544. ASSERT(lpIDataObject != NULL);
  1545. // Look at the data object and see if the snap-in manager is asking for pages
  1546. INTERNAL* pInternal= ExtractInternalFormat(lpIDataObject);
  1547. if (pInternal != NULL)
  1548. {
  1549. DATA_OBJECT_TYPES type = pInternal->m_type;
  1550. FREE_DATA(pInternal);
  1551. if (type == CCT_SNAPIN_MANAGER)
  1552. {
  1553. HRESULT hr = DoInsertWizard(lpProvider);
  1554. return hr;
  1555. }
  1556. }
  1557. CLSID* pCoClassID = ExtractClassID(lpIDataObject);
  1558. if(pCoClassID == NULL)
  1559. {
  1560. ASSERT(FALSE);
  1561. return E_UNEXPECTED;
  1562. }
  1563. CPropertyPage* pBasePage;
  1564. // Determine which
  1565. // Note: Should check the node type, but the sample only has 1
  1566. if (IsEqualCLSID(*pCoClassID, GetCoClassID()))
  1567. {
  1568. // Create the primary property page
  1569. CGeneralPage* pPage = new CGeneralPage();
  1570. pPage->m_hConsoleHandle = handle;
  1571. pBasePage = pPage;
  1572. }
  1573. else
  1574. {
  1575. // Create the extension property page
  1576. CExtensionPage* pPage = new CExtensionPage();
  1577. pBasePage = pPage;
  1578. wchar_t* pWkStation = ExtractWorkstation(lpIDataObject);
  1579. if (pWkStation == NULL)
  1580. {
  1581. ASSERT(FALSE);
  1582. return E_FAIL;
  1583. }
  1584. // Save the workstation name
  1585. pPage->m_szText = pWkStation;
  1586. FREE_DATA(pWkStation);
  1587. }
  1588. FREE_DATA(pCoClassID);
  1589. // Object gets deleted when the page is destroyed
  1590. ASSERT(lpProvider != NULL);
  1591. HRESULT hr = MMCPropPageCallback(&pBasePage->m_psp);
  1592. if (SUCCEEDED(hr))
  1593. {
  1594. HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pBasePage->m_psp);
  1595. if (hPage == NULL)
  1596. return E_UNEXPECTED;
  1597. lpProvider->AddPage(hPage);
  1598. }
  1599. return hr;
  1600. }
  1601. STDMETHODIMP CComponentDataImpl::QueryPagesFor(LPDATAOBJECT lpDataObject)
  1602. {
  1603. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1604. // Get the node type and see if it's one of mine
  1605. // if (nodetype == one of mine)
  1606. // do this
  1607. // else
  1608. // see which node type it is and answer the question
  1609. return S_OK;
  1610. }
  1611. BOOL CComponentDataImpl::IsScopePaneNode(LPDATAOBJECT lpDataObject)
  1612. {
  1613. BOOL bResult = FALSE;
  1614. INTERNAL* pInternal = ExtractInternalFormat(lpDataObject);
  1615. if (pInternal->m_cookie == NULL &&
  1616. (pInternal->m_type == CCT_SCOPE || pInternal->m_type == CCT_RESULT))
  1617. bResult = TRUE;
  1618. FREE_DATA(pInternal);
  1619. return bResult;
  1620. }
  1621. ///////////////////////////////////////////////////////////////////////////////
  1622. // IExtendContextMenu implementation
  1623. //
  1624. STDMETHODIMP CComponentDataImpl::AddMenuItems(LPDATAOBJECT pDataObject,
  1625. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  1626. long *pInsertionAllowed)
  1627. {
  1628. HRESULT hr = S_OK;
  1629. // Note - snap-ins need to look at the data object and determine
  1630. // in what context, menu items need to be added. They must also
  1631. // observe the insertion allowed flags to see what items can be
  1632. // added.
  1633. if (IsMMCMultiSelectDataObject(pDataObject) == TRUE)
  1634. return S_FALSE;
  1635. INTERNAL* pInternal = ExtractInternalFormat(pDataObject);
  1636. BOOL bCmd1IsDefault = (pInternal->m_type == CCT_RESULT);
  1637. if (bCmd1IsDefault)
  1638. menuItems[0].fSpecialFlags = CCM_SPECIAL_DEFAULT_ITEM;
  1639. else
  1640. menuItems[0].fSpecialFlags = 0;
  1641. // Loop through and add each of the menu items
  1642. if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP)
  1643. {
  1644. for (LPCONTEXTMENUITEM m = menuItems; m->strName; m++)
  1645. {
  1646. hr = pContextMenuCallback->AddItem(m);
  1647. if (FAILED(hr))
  1648. break;
  1649. }
  1650. }
  1651. // Loop through and add each of the view items
  1652. if (*pInsertionAllowed & CCM_INSERTIONALLOWED_VIEW)
  1653. {
  1654. for (LPCONTEXTMENUITEM m = viewItems; m->strName; m++)
  1655. {
  1656. hr = pContextMenuCallback->AddItem(m);
  1657. if (FAILED(hr))
  1658. break;
  1659. }
  1660. }
  1661. return hr;
  1662. }
  1663. STDMETHODIMP CComponentDataImpl::Command(long nCommandID, LPDATAOBJECT pDataObject)
  1664. {
  1665. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1666. #ifdef DOBJ_NOCONSOLE
  1667. if (pDataObject == DOBJ_NOCONSOLE)
  1668. {
  1669. TCHAR szMsg[256];
  1670. wsprintf (szMsg, _T("CComponentDataImpl::Command invoked from outside the context of MMC (nCommandID = %d)."), nCommandID);
  1671. AfxMessageBox (szMsg);
  1672. return (S_OK);
  1673. }
  1674. #endif // DOBJ_NOCONSOLE
  1675. // Note - snap-ins need to look at the data object and determine
  1676. // in what context the command is being called.
  1677. // Handle each of the commands.
  1678. switch (nCommandID)
  1679. {
  1680. case IDM_COMMAND1:
  1681. {
  1682. ASSERT(m_pConsole);
  1683. m_pConsole->MessageBox(L"Snapin Menu Comand Selected",
  1684. menuItems[nCommandID].strName, MB_OK, NULL);
  1685. if (1)
  1686. {
  1687. IConsole2* pc2 = NULL;
  1688. m_pConsole->QueryInterface(IID_IConsole2, (void**)&pc2);
  1689. ASSERT(pc2 != NULL);
  1690. pc2->IsTaskpadViewPreferred();
  1691. pc2->Release();
  1692. break;
  1693. }
  1694. INTERNAL* pi = ExtractInternalFormat(pDataObject);
  1695. ASSERT(pi);
  1696. ASSERT(pi->m_type != CCT_RESULT);
  1697. CFolder* pFolder = reinterpret_cast<CFolder*>(pi->m_cookie);
  1698. if (pFolder)
  1699. {
  1700. m_pConsole->SelectScopeItem(pFolder->m_pScopeItem->ID);
  1701. }
  1702. else
  1703. {
  1704. SCOPEDATAITEM si;
  1705. ZeroMemory(&si, sizeof(si));
  1706. si.ID = m_pStaticRoot;
  1707. si.mask = SDI_STR;
  1708. si.displayname = MMC_TEXTCALLBACK; // _T("Sample snapin's static folder");
  1709. m_pScope->SetItem(&si);
  1710. }
  1711. break;
  1712. }
  1713. case IDM_COMMAND2:
  1714. ASSERT(m_pConsole);
  1715. m_pConsole->MessageBox(L"Snapin Menu Comand Selected",
  1716. menuItems[nCommandID].strName, MB_OK, NULL);
  1717. break;
  1718. default:
  1719. ASSERT(FALSE); // Unknown command!
  1720. break;
  1721. }
  1722. return S_OK;
  1723. }
  1724. ///////////////////////////////////////////////////////////////////////////////
  1725. // IExtendControlbar implementation
  1726. //
  1727. STDMETHODIMP CSnapin::SetControlbar(LPCONTROLBAR pControlbar)
  1728. {
  1729. // TRACE(_T("CSnapin::SetControlbar(%ld)\n"),pControlbar);
  1730. // Please don't delete this. Required to make sure we pick up the bitmap
  1731. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1732. if (pControlbar != NULL)
  1733. {
  1734. // Hold on to the controlbar interface.
  1735. if (m_pControlbar)
  1736. {
  1737. m_pControlbar->Release();
  1738. }
  1739. m_pControlbar = pControlbar;
  1740. m_pControlbar->AddRef();
  1741. HRESULT hr=S_FALSE;
  1742. if (!m_pMenuButton1)
  1743. {
  1744. hr = m_pControlbar->Create(MENUBUTTON, this,
  1745. reinterpret_cast<LPUNKNOWN*>(&m_pMenuButton1));
  1746. ASSERT(SUCCEEDED(hr));
  1747. }
  1748. if (m_pMenuButton1)
  1749. {
  1750. // Unlike toolbar buttons, menu buttons need to be added every time.
  1751. hr = m_pMenuButton1->AddButton(FOLDEREX_MENU, L"FolderEx", L"Extended Folder Menu");
  1752. ASSERT(SUCCEEDED(hr));
  1753. hr = m_pMenuButton1->AddButton(FILEEX_MENU, L"FileEx", L"Extended File Menu");
  1754. ASSERT(SUCCEEDED(hr));
  1755. }
  1756. // Create the Toolbar 1
  1757. if (!m_pToolbar1)
  1758. {
  1759. hr = m_pControlbar->Create(TOOLBAR, this, reinterpret_cast<LPUNKNOWN*>(&m_pToolbar1));
  1760. ASSERT(SUCCEEDED(hr));
  1761. // Add the bitmap
  1762. m_pbmpToolbar1 = new ::CBitmap;
  1763. m_pbmpToolbar1->LoadBitmap(IDB_TOOLBAR1);
  1764. hr = m_pToolbar1->AddBitmap(11, *m_pbmpToolbar1, 16, 16, RGB(255, 0, 255));
  1765. ASSERT(SUCCEEDED(hr));
  1766. // Add the buttons to the toolbar
  1767. hr = m_pToolbar1->AddButtons(ARRAYLEN(SnapinButtons), SnapinButtons);
  1768. ASSERT(SUCCEEDED(hr));
  1769. }
  1770. // TOOLBAR 2
  1771. // Create the Toolbar 2
  1772. if (!m_pToolbar2)
  1773. {
  1774. hr = m_pControlbar->Create(TOOLBAR, this, reinterpret_cast<LPUNKNOWN*>(&m_pToolbar2));
  1775. ASSERT(SUCCEEDED(hr));
  1776. // Add the bitmap
  1777. m_pbmpToolbar2 = new ::CBitmap;
  1778. m_pbmpToolbar2->LoadBitmap(IDB_TOOLBAR2);
  1779. hr = m_pToolbar2->AddBitmap(36, *m_pbmpToolbar2, 16, 16, RGB(192,192,192));
  1780. ASSERT(SUCCEEDED(hr));
  1781. // Add the buttons to the toolbar
  1782. hr = m_pToolbar2->AddButtons(ARRAYLEN(SnapinButtons2), SnapinButtons2);
  1783. ASSERT(SUCCEEDED(hr));
  1784. }
  1785. }
  1786. else
  1787. {
  1788. SAFE_RELEASE(m_pControlbar);
  1789. }
  1790. return S_OK;
  1791. }
  1792. void CSnapin::OnButtonClick(LPDATAOBJECT pdtobj, LONG_PTR idBtn)
  1793. {
  1794. TCHAR name[128];
  1795. GetItemName(pdtobj, name);
  1796. TCHAR buf[200];
  1797. wsprintf(buf, _T("Toolbar button<%d> was clicked. \nThe currently selected result item is <%s>"), idBtn, name);
  1798. ::MessageBox(NULL, buf, _T("TRACE"), MB_OK);
  1799. }
  1800. STDMETHODIMP CSnapin::ControlbarNotify(MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param)
  1801. {
  1802. HRESULT hr=S_FALSE;
  1803. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1804. switch (event)
  1805. {
  1806. case MMCN_BTN_CLICK:
  1807. //TCHAR szMessage[MAX_PATH];
  1808. //wsprintf(szMessage, _T("CommandID %ld"),param);
  1809. //AfxMessageBox(szMessage);
  1810. OnButtonClick(reinterpret_cast<LPDATAOBJECT>(arg), param);
  1811. break;
  1812. case MMCN_DESELECT_ALL:
  1813. case MMCN_SELECT:
  1814. HandleExtToolbars((event == MMCN_DESELECT_ALL), arg, param);
  1815. break;
  1816. case MMCN_MENU_BTNCLICK:
  1817. HandleExtMenus(arg, param);
  1818. break;
  1819. default:
  1820. break;
  1821. }
  1822. return S_OK;
  1823. }
  1824. // This compares two data objects to see if they are the same object.
  1825. // return
  1826. // S_OK if equal otherwise S_FALSE
  1827. //
  1828. // Note: check to make sure both objects belong to the snap-in.
  1829. //
  1830. STDMETHODIMP CSnapin::CompareObjects(LPDATAOBJECT lpDataObjectA, LPDATAOBJECT lpDataObjectB)
  1831. {
  1832. return S_FALSE;
  1833. }
  1834. // This compare is used to sort the item's in the listview
  1835. //
  1836. // Parameters:
  1837. //
  1838. // lUserParam - user param passed in when IResultData::Sort() was called
  1839. // cookieA - first item to compare
  1840. // cookieB - second item to compare
  1841. // pnResult [in, out]- contains the col on entry,
  1842. // -1, 0, 1 based on comparison for return value.
  1843. //
  1844. // Note: Assum sort is ascending when comparing.
  1845. STDMETHODIMP CSnapin::Compare(LPARAM lUserParam, MMC_COOKIE cookieA, MMC_COOKIE cookieB, int* pnResult)
  1846. {
  1847. if (pnResult == NULL)
  1848. {
  1849. ASSERT(FALSE);
  1850. return E_POINTER;
  1851. }
  1852. // check col range
  1853. int nCol = *pnResult;
  1854. ASSERT(nCol >=0 && nCol< 3);
  1855. *pnResult = 0;
  1856. USES_CONVERSION;
  1857. LPTSTR szStringA;
  1858. LPTSTR szStringB;
  1859. RESULT_DATA* pDataA = reinterpret_cast<RESULT_DATA*>(cookieA);
  1860. RESULT_DATA* pDataB = reinterpret_cast<RESULT_DATA*>(cookieB);
  1861. ASSERT(pDataA != NULL && pDataB != NULL);
  1862. if (nCol == 0)
  1863. {
  1864. szStringA = OLE2T(pDataA->szName);
  1865. szStringB = OLE2T(pDataB->szName);
  1866. }
  1867. else if(nCol == 1)
  1868. {
  1869. szStringA = OLE2T(pDataA->szSize);
  1870. szStringB = OLE2T(pDataB->szSize);
  1871. }
  1872. else
  1873. {
  1874. szStringA = OLE2T(pDataA->szType);
  1875. szStringB = OLE2T(pDataB->szType) ;
  1876. }
  1877. ASSERT(szStringA != NULL);
  1878. ASSERT(szStringB != NULL);
  1879. *pnResult = _tcscmp(szStringA, szStringB);
  1880. return S_OK;
  1881. }
  1882. ///////////////////////////////////////////////////////////////////////////////
  1883. // IResultOwnerData implementation
  1884. //
  1885. STDMETHODIMP CSnapin::FindItem (LPRESULTFINDINFO pFindInfo, int* pnFoundIndex)
  1886. {
  1887. // find next item that matches the string (exact or partial)
  1888. // if matched found, set FoundIndex and return S_OK
  1889. // For the sample all items are named by their index number
  1890. // so we don't do a real string search. Also, to simplify the code
  1891. // the routine assumes a partial match search with wrap, which is what
  1892. // keyboard navigation calls use.
  1893. ASSERT((pFindInfo->dwOptions & (RFI_PARTIAL | RFI_WRAP)) == (RFI_PARTIAL | RFI_WRAP));
  1894. USES_CONVERSION;
  1895. TCHAR* lpszFind = OLE2T(pFindInfo->psz);
  1896. // TRACE(_T("CSnapin::FindItem(\"%s\")"), lpszFind);
  1897. // convert search string to number
  1898. int nMatchVal = 0;
  1899. TCHAR* pch = lpszFind;
  1900. while (*pch >= _T('0') && *pch <= _T('9') && nMatchVal < NUM_VIRTUAL_ITEMS)
  1901. nMatchVal = nMatchVal * 10 + (*pch++ - _T('0'));
  1902. // if string has a non-decimal char or is too large, it won't match anything
  1903. if (*pch != 0 || nMatchVal >= NUM_VIRTUAL_ITEMS)
  1904. return S_FALSE;
  1905. // if ascending sequence
  1906. if (!(m_dwVirtualSortOptions & RSI_DESCENDING))
  1907. {
  1908. int nStartVal = pFindInfo->nStart;
  1909. // if match is less than start (but not zero), locate first value above start that matches
  1910. // otherwise the match number itself it the answer
  1911. if (nMatchVal < nStartVal && nMatchVal != 0)
  1912. {
  1913. // find scale factor to reach value >= start value
  1914. int nScale = 1;
  1915. while (nMatchVal * nScale < nStartVal)
  1916. nScale *= 10;
  1917. // check special case of start value beginning with the match digits
  1918. int nTestVal = (nStartVal * 10 - nMatchVal * nScale) < nScale ? nStartVal : nMatchVal * nScale;
  1919. // if not too big it's the match, else the match value is the match
  1920. if (nTestVal < NUM_VIRTUAL_ITEMS)
  1921. nMatchVal = nTestVal;
  1922. }
  1923. }
  1924. else // descending sequence
  1925. {
  1926. // convert start index to start value
  1927. int nStartVal = (NUM_VIRTUAL_ITEMS - 1) - pFindInfo->nStart;
  1928. if (nMatchVal != 0)
  1929. {
  1930. // if match number > start, we will have to wrap to find a match
  1931. // so use max index as our target
  1932. int nTargetVal = (nMatchVal > nStartVal) ? NUM_VIRTUAL_ITEMS - 1 : nStartVal;
  1933. // find scale factor that gets closest without going over target
  1934. int nScale = 1;
  1935. while (nMatchVal * nScale * 10 < nTargetVal)
  1936. nScale *= 10;
  1937. // check special case of target value beginning with the match digits
  1938. nMatchVal = (nTargetVal - nMatchVal * nScale) < nScale ? nTargetVal : (nMatchVal + 1) * nScale - 1;
  1939. }
  1940. // convert match value back to an item index
  1941. nMatchVal = (NUM_VIRTUAL_ITEMS - 1) - nMatchVal;
  1942. }
  1943. *pnFoundIndex = nMatchVal;
  1944. return S_OK;
  1945. }
  1946. STDMETHODIMP CSnapin::CacheHint (int nStartIndex, int nEndIndex)
  1947. {
  1948. // If advantageous, use this hint to pre-fetch the result item info that
  1949. // is about to be requested.
  1950. // TRACE(_T("CSnapin::CacheHint(%d,%d)\n"), nStartIndex, nEndIndex);
  1951. return S_OK;
  1952. }
  1953. STDMETHODIMP CSnapin::SortItems (int nColumn, DWORD dwSortOptions, LPARAM lUserParam)
  1954. {
  1955. // sort request for user owned result items
  1956. // if item order changed return S_OK, else S_FALSE
  1957. // Sample only sorts on the first column (item name)
  1958. if ((nColumn == 0) && (m_dwVirtualSortOptions != dwSortOptions))
  1959. {
  1960. m_dwVirtualSortOptions = dwSortOptions;
  1961. return S_OK;
  1962. }
  1963. return S_FALSE;
  1964. }
  1965. void CSnapin::HandleStandardVerbs(bool bDeselectAll, LPARAM arg,
  1966. LPDATAOBJECT lpDataObject)
  1967. {
  1968. WORD bScope = LOWORD(arg);
  1969. WORD bSelect = HIWORD(arg);
  1970. #if 0
  1971. // trace
  1972. {
  1973. TCHAR buf[250];
  1974. static UINT s_count1 = 0;
  1975. wsprintf(buf, _T("<%4d> %s - %s\n"), ++s_count1, bScope ? _T("Scope") : _T("Result"),
  1976. bSelect ? _T("selected") : _T("de-selected"));
  1977. OutputDebugString(buf);
  1978. }
  1979. #endif
  1980. if (!bScope)
  1981. {
  1982. if (m_CustomViewID == VIEW_MICROSOFT_URL)
  1983. {
  1984. m_pConsoleVerb->SetVerbState(MMC_VERB_REFRESH, HIDDEN, FALSE);
  1985. m_pConsoleVerb->SetVerbState(MMC_VERB_REFRESH, ENABLED, TRUE);
  1986. return;
  1987. }
  1988. else if (m_CustomViewID == VIEW_CALENDAR_OCX)
  1989. {
  1990. m_pConsoleVerb->SetVerbState(MMC_VERB_REFRESH, HIDDEN, FALSE);
  1991. m_pConsoleVerb->SetVerbState(MMC_VERB_REFRESH, ENABLED, TRUE);
  1992. m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, HIDDEN, FALSE);
  1993. m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, TRUE);
  1994. return;
  1995. }
  1996. }
  1997. if (!bDeselectAll && lpDataObject == NULL)
  1998. return;
  1999. // You should crack the data object and enable/disable/hide standard
  2000. // commands appropriately. The standard commands are reset everytime you get
  2001. // called. So you must reset them back.
  2002. #if 0
  2003. TCHAR buf[40];
  2004. wsprintf(buf, _T(" %4d - CSnapin::OnSelect<%d, %d>\n"), ++n_count, bScope, bSelect);
  2005. ODS(buf);
  2006. #else
  2007. DBX_PRINT(_T(" %4d - CSnapin::OnSelect<%d, %d>\n"), ++n_count, bScope, bSelect);
  2008. #endif
  2009. if (!bDeselectAll && IsMyMultiSelectDataObject(lpDataObject) == TRUE)
  2010. {
  2011. m_pConsoleVerb->SetVerbState(MMC_VERB_DELETE, HIDDEN, FALSE);
  2012. m_pConsoleVerb->SetVerbState(MMC_VERB_DELETE, ENABLED, TRUE);
  2013. m_pConsoleVerb->SetVerbState(MMC_VERB_COPY, HIDDEN, FALSE);
  2014. m_pConsoleVerb->SetVerbState(MMC_VERB_COPY, ENABLED, TRUE);
  2015. m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, HIDDEN, FALSE);
  2016. m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, TRUE);
  2017. return;
  2018. }
  2019. INTERNAL* pInternal = lpDataObject ? ExtractInternalFormat(lpDataObject) : NULL;
  2020. if (bSelect && (pInternal != NULL) && (pInternal->m_type == CCT_SCOPE))
  2021. {
  2022. IConsole2* pConsole2;
  2023. m_pConsole->QueryInterface (IID_IConsole2, (void**)&pConsole2);
  2024. CFolder* pFolder = reinterpret_cast<CFolder*>(pInternal->m_cookie);
  2025. if (pFolder != NULL)
  2026. {
  2027. switch (pFolder->GetType())
  2028. {
  2029. case USER:
  2030. pConsole2->SetStatusText (L"User node selected||third pane");
  2031. break;
  2032. case COMPANY:
  2033. pConsole2->SetStatusText (L"Company node selected|%25|third pane");
  2034. break;
  2035. case VIRTUAL:
  2036. pConsole2->SetStatusText (L" Virtual node selected | %50 | third pane ");
  2037. break;
  2038. }
  2039. }
  2040. else
  2041. pConsole2->SetStatusText (L"Static root node selected||third pane");
  2042. pConsole2->Release ();
  2043. }
  2044. if (bDeselectAll || !bSelect)
  2045. {
  2046. if (bScope)
  2047. {
  2048. m_pConsoleVerb->SetVerbState(MMC_VERB_OPEN, ENABLED, FALSE);
  2049. m_pConsoleVerb->SetVerbState(MMC_VERB_COPY, ENABLED, FALSE);
  2050. m_pConsoleVerb->SetVerbState(MMC_VERB_PASTE, ENABLED, FALSE);
  2051. m_pConsoleVerb->SetVerbState(MMC_VERB_DELETE, ENABLED, FALSE);
  2052. m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, FALSE);
  2053. m_pConsoleVerb->SetVerbState(MMC_VERB_RENAME, ENABLED, FALSE);
  2054. }
  2055. else
  2056. {
  2057. // Result pane background
  2058. m_pConsoleVerb->SetVerbState(MMC_VERB_PASTE, HIDDEN, FALSE);
  2059. m_pConsoleVerb->SetVerbState(MMC_VERB_PASTE, ENABLED, TRUE);
  2060. if (pInternal && pInternal->m_cookie == 0)
  2061. {
  2062. m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, HIDDEN, FALSE);
  2063. m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, TRUE);
  2064. }
  2065. m_pConsoleVerb->SetVerbState(MMC_VERB_REFRESH, HIDDEN, FALSE);
  2066. m_pConsoleVerb->SetVerbState(MMC_VERB_REFRESH, ENABLED, TRUE);
  2067. }
  2068. return;
  2069. }
  2070. if (m_pConsoleVerb && pInternal)
  2071. {
  2072. if (pInternal->m_type == CCT_SCOPE)
  2073. {
  2074. // Standard funcitonality support by scope items
  2075. m_pConsoleVerb->SetVerbState(MMC_VERB_OPEN, HIDDEN, FALSE);
  2076. m_pConsoleVerb->SetVerbState(MMC_VERB_OPEN, ENABLED, TRUE);
  2077. m_pConsoleVerb->SetVerbState(MMC_VERB_REFRESH, HIDDEN, FALSE);
  2078. m_pConsoleVerb->SetVerbState(MMC_VERB_REFRESH, ENABLED, TRUE);
  2079. // Enable properties for static node only.
  2080. if (pInternal->m_cookie == 0)
  2081. {
  2082. m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, HIDDEN, FALSE);
  2083. m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, TRUE);
  2084. //m_pConsoleVerb->SetDefaultVerb(MMC_VERB_PROPERTIES);
  2085. m_pConsoleVerb->SetDefaultVerb(MMC_VERB_OPEN);
  2086. }
  2087. else
  2088. {
  2089. m_pConsoleVerb->SetVerbState(MMC_VERB_PRINT, HIDDEN, FALSE);
  2090. m_pConsoleVerb->SetVerbState(MMC_VERB_PRINT, ENABLED, TRUE);
  2091. m_pConsoleVerb->SetDefaultVerb(MMC_VERB_OPEN);
  2092. }
  2093. // Standard funcitonality NOT support by scope items
  2094. m_pConsoleVerb->SetVerbState(MMC_VERB_COPY, ENABLED, TRUE);
  2095. m_pConsoleVerb->SetVerbState(MMC_VERB_DELETE, ENABLED, TRUE);
  2096. m_pConsoleVerb->SetVerbState(MMC_VERB_CUT, HIDDEN, FALSE);
  2097. m_pConsoleVerb->SetVerbState(MMC_VERB_CUT, ENABLED, FALSE);
  2098. //m_pConsoleVerb->SetVerbState(MMC_VERB_CUT, ENABLED, TRUE);
  2099. }
  2100. else
  2101. {
  2102. // Standard funcitonality support by result items
  2103. m_pConsoleVerb->SetVerbState(MMC_VERB_REFRESH, HIDDEN, FALSE);
  2104. m_pConsoleVerb->SetVerbState(MMC_VERB_REFRESH, ENABLED, TRUE);
  2105. m_pConsoleVerb->SetVerbState(MMC_VERB_DELETE, HIDDEN, FALSE);
  2106. m_pConsoleVerb->SetVerbState(MMC_VERB_DELETE, ENABLED, TRUE);
  2107. m_pConsoleVerb->SetDefaultVerb(MMC_VERB_NONE);
  2108. // Standard funcitonality NOT support by result items
  2109. }
  2110. m_pConsoleVerb->SetVerbState(MMC_VERB_RENAME, ENABLED, TRUE);
  2111. // Standard funcitonality NOT support by all items
  2112. //m_pConsoleVerb->SetVerbState(MMC_VERB_COPY, HIDDEN, TRUE);
  2113. //m_pConsoleVerb->SetVerbState(MMC_VERB_PASTE, HIDDEN, TRUE);
  2114. }
  2115. }
  2116. void EnableToolbar(LPTOOLBAR pToolbar, MMCBUTTON rgSnapinButtons[], int nRgSize,
  2117. BOOL bEnable)
  2118. {
  2119. for (int i=0; i < nRgSize; ++i)
  2120. {
  2121. if (rgSnapinButtons[i].idCommand != 0)
  2122. pToolbar->SetButtonState(rgSnapinButtons[i].idCommand, ENABLED,
  2123. bEnable);
  2124. }
  2125. }
  2126. void EnableMenuBtns(LPMENUBUTTON pMenuBtn, MMCBUTTON rgSnapinButtons[], int nRgSize,
  2127. BOOL bEnable)
  2128. {
  2129. for (int i=0; i < nRgSize; ++i)
  2130. {
  2131. if (rgSnapinButtons[i].idCommand != 0)
  2132. pMenuBtn->SetButtonState(rgSnapinButtons[i].idCommand, ENABLED,
  2133. bEnable);
  2134. }
  2135. }
  2136. void CSnapin::HandleExtToolbars(bool bDeselectAll, LPARAM arg, LPARAM param)
  2137. {
  2138. INTERNAL* pInternal = NULL;
  2139. HRESULT hr;
  2140. BOOL bScope = (BOOL) LOWORD(arg);
  2141. BOOL bSelect = (BOOL) HIWORD(arg);
  2142. #if 0
  2143. #if 1
  2144. {
  2145. if (param)
  2146. {
  2147. LPDATAOBJECT pDataObject = reinterpret_cast<LPDATAOBJECT>(param);
  2148. pInternal = ExtractInternalFormat(pDataObject);
  2149. }
  2150. TCHAR buf[200];
  2151. wsprintf(buf, _T(" %4d - CExtendControlbar::OnSelect<%d, %d> = %d\n"),
  2152. ++n_count, bScope, bSelect, pInternal ? pInternal->m_cookie : 0);
  2153. ODS(buf);
  2154. }
  2155. #else
  2156. DBX_PRINT(_T(" %4d - CExtendControlbar::OnSelect<%d, %d>\n"), ++n_count, bScope, bSelect);
  2157. #endif
  2158. #endif
  2159. if (bDeselectAll || bSelect == FALSE)
  2160. {
  2161. ASSERT(m_pToolbar1);
  2162. EnableToolbar(m_pToolbar1, SnapinButtons,
  2163. ARRAYLEN(SnapinButtons), FALSE);
  2164. ASSERT(m_pToolbar2);
  2165. EnableToolbar(m_pToolbar2, SnapinButtons2,
  2166. ARRAYLEN(SnapinButtons2), FALSE);
  2167. ASSERT(m_pMenuButton1 != NULL);
  2168. m_pMenuButton1->SetButtonState(FOLDEREX_MENU, ENABLED, FALSE);
  2169. m_pMenuButton1->SetButtonState(FILEEX_MENU, ENABLED, FALSE);
  2170. return;
  2171. }
  2172. ASSERT(bSelect == TRUE);
  2173. bool bFileExBtn = false;
  2174. if (bScope == TRUE)
  2175. {
  2176. LPDATAOBJECT pDataObject = reinterpret_cast<LPDATAOBJECT>(param);
  2177. pInternal = ExtractInternalFormat(pDataObject);
  2178. if (pInternal == NULL)
  2179. return;
  2180. CFolder* pFolder = reinterpret_cast<CFolder*>(pInternal->m_cookie);
  2181. if (pInternal->m_cookie == 0)
  2182. {
  2183. if (IsPrimaryImpl() == TRUE)
  2184. {
  2185. // Attach the toolbars to the window
  2186. hr = m_pControlbar->Attach(TOOLBAR, (LPUNKNOWN) m_pToolbar1);
  2187. ASSERT(SUCCEEDED(hr));
  2188. hr = m_pControlbar->Attach(TOOLBAR, (LPUNKNOWN) m_pToolbar2);
  2189. ASSERT(SUCCEEDED(hr));
  2190. }
  2191. }
  2192. else if ((IsPrimaryImpl() == TRUE && pFolder->GetType() == COMPANY) ||
  2193. (IsPrimaryImpl() == FALSE && pFolder->GetType() == EXT_COMPANY))
  2194. {
  2195. // Detach the toolbar2 from the window
  2196. hr = m_pControlbar->Detach((LPUNKNOWN)m_pToolbar2);
  2197. ASSERT(SUCCEEDED(hr));
  2198. // Attach the toolbar1 to the window
  2199. hr = m_pControlbar->Attach(TOOLBAR, (LPUNKNOWN) m_pToolbar1);
  2200. ASSERT(SUCCEEDED(hr));
  2201. }
  2202. else if ((IsPrimaryImpl() == TRUE && pFolder->GetType() == USER) ||
  2203. (IsPrimaryImpl() == FALSE && pFolder->GetType() == EXT_USER))
  2204. {
  2205. // Detach the toolbar1 from the window
  2206. hr = m_pControlbar->Detach((LPUNKNOWN)m_pToolbar1);
  2207. ASSERT(SUCCEEDED(hr));
  2208. // Attach the toolbar2 to the window
  2209. hr = m_pControlbar->Attach(TOOLBAR, (LPUNKNOWN) m_pToolbar2);
  2210. ASSERT(SUCCEEDED(hr));
  2211. }
  2212. else
  2213. {
  2214. // Detach the toolbars from the window
  2215. hr = m_pControlbar->Detach((LPUNKNOWN)m_pToolbar1);
  2216. ASSERT(SUCCEEDED(hr));
  2217. hr = m_pControlbar->Detach((LPUNKNOWN)m_pToolbar2);
  2218. ASSERT(SUCCEEDED(hr));
  2219. }
  2220. FREE_DATA(pInternal);
  2221. EnableToolbar(m_pToolbar1, SnapinButtons,
  2222. ARRAYLEN(SnapinButtons), FALSE);
  2223. EnableToolbar(m_pToolbar2, SnapinButtons2,
  2224. ARRAYLEN(SnapinButtons2), FALSE);
  2225. }
  2226. else // result item selected.
  2227. {
  2228. LPDATAOBJECT pDataObject = reinterpret_cast<LPDATAOBJECT>(param);
  2229. if (pDataObject != NULL)
  2230. pInternal = ExtractInternalFormat(pDataObject);
  2231. if (pInternal == NULL)
  2232. return;
  2233. if (pInternal->m_type == CCT_RESULT)
  2234. {
  2235. bFileExBtn = true;
  2236. ASSERT(m_pToolbar1);
  2237. EnableToolbar(m_pToolbar1, SnapinButtons,
  2238. ARRAYLEN(SnapinButtons), TRUE);
  2239. m_pToolbar1->SetButtonState(1, ENABLED, FALSE);
  2240. m_pToolbar1->SetButtonState(2, CHECKED, TRUE);
  2241. m_pToolbar1->SetButtonState(3, HIDDEN, TRUE);
  2242. m_pToolbar1->SetButtonState(4, INDETERMINATE, TRUE);
  2243. m_pToolbar1->SetButtonState(5, BUTTONPRESSED, TRUE);
  2244. // Above is the correct way
  2245. ASSERT(m_pToolbar2);
  2246. m_pToolbar2->SetButtonState(20, CHECKED, TRUE);
  2247. m_pToolbar2->SetButtonState(30, HIDDEN, TRUE);
  2248. m_pToolbar2->SetButtonState(40, INDETERMINATE, TRUE);
  2249. m_pToolbar2->SetButtonState(50, BUTTONPRESSED, TRUE);
  2250. EnableToolbar(m_pToolbar2, SnapinButtons2,
  2251. ARRAYLEN(SnapinButtons2), TRUE);
  2252. }
  2253. else // sub folder slected
  2254. {
  2255. CFolder* pFolder = reinterpret_cast<CFolder*>(pInternal->m_cookie);
  2256. ASSERT(m_pControlbar);
  2257. if (pInternal->m_cookie == 0)
  2258. {
  2259. if (IsPrimaryImpl() == TRUE)
  2260. {
  2261. // Attach the toolbars to the window
  2262. hr = m_pControlbar->Attach(TOOLBAR, (LPUNKNOWN) m_pToolbar1);
  2263. ASSERT(SUCCEEDED(hr));
  2264. hr = m_pControlbar->Attach(TOOLBAR, (LPUNKNOWN) m_pToolbar2);
  2265. ASSERT(SUCCEEDED(hr));
  2266. }
  2267. }
  2268. else if ((IsPrimaryImpl() == TRUE && pFolder->GetType() == COMPANY) ||
  2269. (IsPrimaryImpl() == FALSE && pFolder->GetType() == EXT_COMPANY))
  2270. {
  2271. // Detach the toolbar2 from the window
  2272. hr = m_pControlbar->Detach((LPUNKNOWN)m_pToolbar2);
  2273. ASSERT(SUCCEEDED(hr));
  2274. // Attach the toolbar1 to the window
  2275. hr = m_pControlbar->Attach(TOOLBAR, (LPUNKNOWN) m_pToolbar1);
  2276. ASSERT(SUCCEEDED(hr));
  2277. }
  2278. else if ((IsPrimaryImpl() == TRUE && pFolder->GetType() == USER) ||
  2279. (IsPrimaryImpl() == FALSE && pFolder->GetType() == EXT_USER))
  2280. {
  2281. // Detach the toolbar1 from the window
  2282. hr = m_pControlbar->Detach((LPUNKNOWN)m_pToolbar1);
  2283. ASSERT(SUCCEEDED(hr));
  2284. // Attach the toolbar2 to the window
  2285. hr = m_pControlbar->Attach(TOOLBAR, (LPUNKNOWN) m_pToolbar2);
  2286. ASSERT(SUCCEEDED(hr));
  2287. }
  2288. else
  2289. {
  2290. // Detach the toolbars from the window
  2291. hr = m_pControlbar->Detach((LPUNKNOWN)m_pToolbar1);
  2292. ASSERT(SUCCEEDED(hr));
  2293. hr = m_pControlbar->Detach((LPUNKNOWN)m_pToolbar2);
  2294. ASSERT(SUCCEEDED(hr));
  2295. }
  2296. ASSERT(m_pToolbar1);
  2297. EnableToolbar(m_pToolbar1, SnapinButtons,
  2298. ARRAYLEN(SnapinButtons), TRUE);
  2299. m_pToolbar1->SetButtonState(1, ENABLED, FALSE);
  2300. m_pToolbar1->SetButtonState(2, CHECKED, TRUE);
  2301. m_pToolbar1->SetButtonState(3, ENABLED, TRUE);
  2302. m_pToolbar1->SetButtonState(4, INDETERMINATE, TRUE);
  2303. m_pToolbar1->SetButtonState(5, BUTTONPRESSED, TRUE);
  2304. ASSERT(m_pToolbar2);
  2305. EnableToolbar(m_pToolbar2, SnapinButtons2,
  2306. ARRAYLEN(SnapinButtons2), TRUE);
  2307. // Above is the correct way
  2308. m_pToolbar2->SetButtonState(20, CHECKED, FALSE);
  2309. m_pToolbar2->SetButtonState(30, ENABLED, TRUE);
  2310. m_pToolbar2->SetButtonState(40, INDETERMINATE, FALSE);
  2311. m_pToolbar2->SetButtonState(50, BUTTONPRESSED, TRUE);
  2312. }
  2313. }
  2314. if (m_pMenuButton1)
  2315. {
  2316. // Always make sure the menuButton is attached
  2317. m_pControlbar->Attach(MENUBUTTON, m_pMenuButton1);
  2318. if (bFileExBtn)
  2319. {
  2320. m_pMenuButton1->SetButtonState(FILEEX_MENU, HIDDEN, FALSE);
  2321. m_pMenuButton1->SetButtonState(FOLDEREX_MENU, HIDDEN, TRUE);
  2322. m_pMenuButton1->SetButtonState(FILEEX_MENU, ENABLED, TRUE);
  2323. }
  2324. else
  2325. {
  2326. m_pMenuButton1->SetButtonState(FOLDEREX_MENU, HIDDEN, FALSE);
  2327. m_pMenuButton1->SetButtonState(FILEEX_MENU, HIDDEN, TRUE);
  2328. m_pMenuButton1->SetButtonState(FOLDEREX_MENU, ENABLED, TRUE);
  2329. }
  2330. }
  2331. }
  2332. void CSnapin::HandleExtMenus(LPARAM arg, LPARAM param)
  2333. {
  2334. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  2335. LPDATAOBJECT* ppDataObject = reinterpret_cast<LPDATAOBJECT*>(arg);
  2336. LPMENUBUTTONDATA pMenuData = reinterpret_cast<LPMENUBUTTONDATA>(param);
  2337. if (ppDataObject == NULL || pMenuData == NULL)
  2338. {
  2339. ASSERT(FALSE);
  2340. return;
  2341. }
  2342. ::CMenu menu;
  2343. ::CMenu* pMenu = NULL;
  2344. switch (pMenuData->idCommand)
  2345. {
  2346. case FOLDEREX_MENU:
  2347. menu.LoadMenu(FOLDEREX_MENU);
  2348. pMenu = menu.GetSubMenu(0);
  2349. break;
  2350. case FILEEX_MENU:
  2351. menu.LoadMenu(FILEEX_MENU);
  2352. pMenu = menu.GetSubMenu(0);
  2353. break;
  2354. default:
  2355. ASSERT(FALSE);
  2356. }
  2357. if (pMenu == NULL)
  2358. return;
  2359. pMenu->TrackPopupMenu(TPM_RETURNCMD | TPM_NONOTIFY, pMenuData->x, pMenuData->y, AfxGetMainWnd());
  2360. }
  2361. void CSnapin::GetItemName(LPDATAOBJECT pdtobj, LPTSTR pszName)
  2362. {
  2363. ASSERT(pszName != NULL);
  2364. pszName[0] = 0;
  2365. INTERNAL* pInternal = ExtractInternalFormat(pdtobj);
  2366. ASSERT(pInternal != NULL);
  2367. if (pInternal == NULL)
  2368. return;
  2369. OLECHAR *pszTemp;
  2370. USES_CONVERSION;
  2371. if (pInternal->m_type == CCT_RESULT)
  2372. {
  2373. RESULT_DATA* pData;
  2374. // if virtual, derive result item from index
  2375. // else cookie is the item pointer
  2376. if (m_bVirtualView)
  2377. pData = GetVirtualResultItem(pInternal->m_cookie);
  2378. else
  2379. pData = reinterpret_cast<RESULT_DATA*>(pInternal->m_cookie);
  2380. ASSERT(pData != NULL);
  2381. pszTemp = pData->szName;
  2382. }
  2383. else
  2384. {
  2385. CFolder* pFolder = reinterpret_cast<CFolder*>(pInternal->m_cookie);
  2386. if (pFolder == 0)
  2387. pszTemp = L"Static folder";
  2388. else
  2389. pszTemp = pFolder->m_pszName;
  2390. }
  2391. lstrcpy(pszName, OLE2T(pszTemp));
  2392. }
  2393. /* end of file */