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.

1901 lines
63 KiB

  1. /*
  2. * Component.cxx
  3. *
  4. *
  5. * Copyright (c) 1998-1999 Microsoft Corporation
  6. *
  7. * PURPOSE: Defines the CComponent class.
  8. *
  9. *
  10. * OWNER: ptousig
  11. */
  12. #include "headers.hxx"
  13. // -----------------------------------------------------------------------------
  14. CComponent::CComponent(void)
  15. {
  16. m_pComponentData = NULL;
  17. m_pitemScopeSelected = NULL;
  18. m_pMultiSelectSnapinItem = NULL; // initially not involved in a multi select
  19. }
  20. // -----------------------------------------------------------------------------
  21. // Destructor doesn't do anything, but it's useful to have one for debugging
  22. // purposes.
  23. //
  24. CComponent::~CComponent(void)
  25. {
  26. }
  27. // -----------------------------------------------------------------------------
  28. // This version of Pitem() is a shortcut, it forwards the call to the
  29. // CBaseSnapin with the correct CComponentData and CComponent parameters.
  30. //
  31. CBaseSnapinItem *CComponent::Pitem(
  32. LPDATAOBJECT lpDataObject,
  33. HSCOPEITEM hscopeitem,
  34. long cookie)
  35. {
  36. return Psnapin()->Pitem(PComponentData(), this, lpDataObject, hscopeitem, cookie);
  37. }
  38. // -----------------------------------------------------------------------------
  39. // Tells this component who the data is. Called shortly after the construction
  40. // of the object. Why isn't this a parameter of the constructor ? Because ATL
  41. // will always use the default constructor when creating a COM object.
  42. //
  43. void CComponent::SetComponentData(CComponentData *pComponentData)
  44. {
  45. m_pComponentData = pComponentData;
  46. }
  47. /*+-------------------------------------------------------------------------*
  48. *
  49. * CComponent::QueryIComponent2
  50. *
  51. * PURPOSE: Determines whether or not to expose the IComponent2 interface on
  52. * the object. This is because snapins that implement IComponent2
  53. * will not be able to test IComponent::GetResultViewType and the MMCN_RESTORE_VIEW
  54. * notification.
  55. *
  56. * PARAMETERS:
  57. * void* pv :
  58. * REFIID riid :
  59. * LPVOID* ppv : pointer to the "this" object.
  60. * DWORD dw :
  61. *
  62. * RETURNS:
  63. * HRESULT WINAPI
  64. *
  65. *+-------------------------------------------------------------------------*/
  66. HRESULT WINAPI
  67. CComponent::QueryIComponent2(void* pv, REFIID riid, LPVOID* ppv, DWORD dw)
  68. {
  69. DECLARE_SC(sc, TEXT("CComponent::QueryIComponent2"));
  70. sc = ScCheckPointers(ppv);
  71. if (sc)
  72. return sc.ToHr();
  73. *ppv = NULL;
  74. CComponent *pComponent = reinterpret_cast<CComponent *>(pv);
  75. if(!pComponent)
  76. return E_NOINTERFACE;
  77. sc = ScCheckPointers(pComponent->Psnapin());
  78. if(sc)
  79. return E_NOINTERFACE;
  80. if(pComponent->Psnapin()->FSupportsIComponent2())
  81. {
  82. // Cant use QueryInterface as it will cause infinite recursion.
  83. (*ppv) = (LPVOID)reinterpret_cast<IComponent2*>(pv);
  84. if (*ppv)
  85. {
  86. ((IUnknown*)(*ppv))->AddRef();
  87. return S_OK;
  88. }
  89. }
  90. return E_NOINTERFACE;
  91. }
  92. // -----------------------------------------------------------------------------
  93. // Is called by the MMC to initialize the object. We QueryInterface
  94. // for pointers to various interfaces, which we cache in
  95. // member variables. This is called only once, when the user clicks on
  96. // the snapin.
  97. //
  98. // $REVIEW (ptousig) I am not sure which of interfaces we are allowed to QI
  99. // for from the parameter. The MMC docs are no help (as usual),
  100. //
  101. SC CComponent::ScInitialize(LPCONSOLE lpConsole)
  102. {
  103. DECLARE_SC(sc, _T("CComponent::ScInitialize"));
  104. ASSERT(lpConsole != NULL);
  105. ASSERT(m_ipConsole == NULL);
  106. // These are CComQIPtr so they will call QueryInterface.
  107. m_ipConsole = lpConsole;
  108. m_ipHeaderCtrl = lpConsole;
  109. m_ipColumnDataPtr = lpConsole;
  110. m_ipResultData = lpConsole;
  111. m_ipPropertySheetProvider = lpConsole;
  112. ASSERT( (m_ipConsole != NULL) || (m_ipHeaderCtrl != NULL) || (m_ipResultData!=NULL) || (m_ipPropertySheetProvider!=NULL) );
  113. // Short circuit the header control pointer back to the MMC
  114. sc = m_ipConsole->SetHeader(m_ipHeaderCtrl);
  115. if (sc)
  116. goto Error;
  117. // Get the IConsoleVerb interface.
  118. sc = m_ipConsole->QueryConsoleVerb(&m_ipConsoleVerb);
  119. if (sc)
  120. goto Error;
  121. // Get a pointer to the result pane's IImageList.
  122. sc = m_ipConsole->QueryResultImageList(&m_ipImageList);
  123. if (sc)
  124. goto Error;
  125. Cleanup:
  126. return sc;
  127. Error:
  128. TraceError(_T("CComponent::ScInitialize"), sc);
  129. goto Cleanup;
  130. }
  131. // -----------------------------------------------------------------------------
  132. // Handles component event notification.
  133. // See MMC docs for the meaning of 'arg' and 'param'.
  134. //
  135. SC CComponent::ScNotify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, long arg, long param)
  136. {
  137. SC sc = S_OK;
  138. switch (event)
  139. {
  140. case MMCN_ACTIVATE:
  141. sc = ScOnActivate(lpDataObject, arg != FALSE);
  142. break;
  143. case MMCN_ADD_IMAGES:
  144. sc = ScOnAddImages(lpDataObject, reinterpret_cast<IImageList *>(arg), param);
  145. break;
  146. case MMCN_BTN_CLICK:
  147. sc = ScOnButtonClick(lpDataObject, (MMC_CONSOLE_VERB) param);
  148. break;
  149. case MMCN_CONTEXTHELP:
  150. sc = ScOnContextHelp(lpDataObject);
  151. break;
  152. case MMCN_DBLCLICK:
  153. sc = ScOnDoubleClick(lpDataObject);
  154. break;
  155. case MMCN_DELETE:
  156. sc = ScOnDelete(lpDataObject);
  157. break;
  158. case MMCN_CUTORMOVE:
  159. sc = Psnapin()->ScOnCutOrMove(reinterpret_cast<LPDATAOBJECT>(arg), IpConsoleNameSpace(), IpConsole());
  160. break;
  161. case MMCN_QUERY_PASTE:
  162. sc = Psnapin()->ScOnQueryPaste(lpDataObject, reinterpret_cast<LPDATAOBJECT>(arg), reinterpret_cast<LPDWORD>(param));
  163. break;
  164. case MMCN_CANPASTE_OUTOFPROC:
  165. sc = Psnapin()->ScOnCanPasteOutOfProcDataObject(reinterpret_cast<LPBOOL>(param));
  166. break;
  167. case MMCN_PASTE:
  168. sc = Psnapin()->ScOnPaste(lpDataObject, reinterpret_cast<LPDATAOBJECT>(arg), reinterpret_cast<LPDATAOBJECT *>(param), IpConsole());
  169. break;
  170. case MMCN_RENAME:
  171. sc = Psnapin()->ScOnRename(lpDataObject, reinterpret_cast<LPCTSTR>(param), IpConsole());
  172. break;
  173. case MMCN_LISTPAD:
  174. sc = ScOnListPad(lpDataObject, arg != FALSE);
  175. break;
  176. case MMCN_PROPERTY_CHANGE:
  177. sc = Psnapin()->ScOnPropertyChange(arg != FALSE, param, IpConsoleNameSpace(), IpConsole());
  178. break;
  179. case MMCN_REFRESH:
  180. //
  181. // Undocumented: arg is the HSCOPEITEM
  182. //
  183. sc = ScOnRefresh(lpDataObject, arg);
  184. break;
  185. case MMCN_SELECT:
  186. sc = ScOnSelect(lpDataObject, LOWORD(arg) != FALSE, HIWORD(arg) != FALSE);
  187. break;
  188. case MMCN_SHOW:
  189. sc = ScOnShow(lpDataObject, arg != FALSE, param);
  190. break;
  191. case MMCN_VIEW_CHANGE:
  192. sc = ScOnViewChange(lpDataObject, arg, param);
  193. break;
  194. case MMCN_INITOCX:
  195. sc = ScOnInitOCX(lpDataObject, reinterpret_cast<IUnknown*>(param));
  196. break;
  197. default:
  198. sc = S_FALSE;
  199. ASSERT(_T("CComponent::ScNotify: unimplemented event"));
  200. break;
  201. }
  202. if (sc)
  203. goto Error;
  204. Cleanup:
  205. return sc;
  206. Error:
  207. TraceError(_T("CComponent::ScNotify"), sc);
  208. goto Cleanup;
  209. }
  210. // -----------------------------------------------------------------------------
  211. // Releases all interfaces.
  212. //
  213. SC CComponent::ScDestroy(void)
  214. {
  215. if (m_ipConsole)
  216. // Release the interfaces that we QI'ed
  217. m_ipConsole->SetHeader(NULL);
  218. m_ipConsole.Release();
  219. m_ipHeaderCtrl.Release();
  220. m_ipColumnDataPtr.Release();
  221. m_ipResultData.Release();
  222. m_ipConsoleVerb.Release();
  223. m_ipImageList.Release();
  224. m_ipPropertySheetProvider.Release();
  225. return S_OK;
  226. }
  227. // -----------------------------------------------------------------------------
  228. // MMC wants to know what to display for a given result item.
  229. // Warning: This is called very very often (on WM_PAINT) so it is important
  230. // we don't take any high latency actions (ie Network or Disk access).
  231. //
  232. SC CComponent::ScGetDisplayInfo(LPRESULTDATAITEM pResultItem)
  233. {
  234. SC sc = S_OK;
  235. CBaseSnapinItem *pitem = NULL;
  236. // We need to figure out which snapin item to route the getdisplayinfo
  237. if (FVirtualResultsPane())
  238. {
  239. // We are displaying virtual items in the results pane. So
  240. // we will ask the controlling scope item to get the display
  241. // info because no "real" item exists in the results pane.
  242. ASSERT(PitemScopeSelected());
  243. sc = PitemScopeSelected()->ScGetVirtualDisplayInfo(pResultItem, IpResultData());
  244. if (sc)
  245. goto Error;
  246. }
  247. else
  248. {
  249. // The lParam member of RESULTDATAITEM contains the cookie.
  250. pitem = Pitem(NULL, 0, pResultItem->lParam);
  251. ASSERT(pitem);
  252. sc = pitem->ScGetDisplayInfo(pResultItem);
  253. if (sc)
  254. goto Error;
  255. }
  256. Cleanup:
  257. return sc;
  258. Error:
  259. TraceError(_T("CComponent::ScGetDisplayInfo"), sc);
  260. goto Cleanup;
  261. }
  262. /*+-------------------------------------------------------------------------*
  263. *
  264. * CComponent::ScQueryDispatch
  265. *
  266. * PURPOSE: Returns a dispatch interface for the specified data object.
  267. *
  268. * PARAMETERS:
  269. * MMC_COOKIE cookie :
  270. * DATA_OBJECT_TYPES type :
  271. * LPDISPATCH* ppDispatch :
  272. *
  273. * RETURNS:
  274. * SC
  275. *
  276. *+-------------------------------------------------------------------------*/
  277. SC
  278. CComponent::ScQueryDispatch(MMC_COOKIE cookie, DATA_OBJECT_TYPES type, LPDISPATCH* ppDispatch)
  279. {
  280. DECLARE_SC(sc, TEXT("CComponent::ScQueryDispatch"));
  281. CBaseSnapinItem * pitem = NULL;
  282. // Determine if we have a special cookie for multiselect
  283. if (IS_SPECIAL_COOKIE(cookie) && (MMC_MULTI_SELECT_COOKIE == cookie))
  284. {
  285. // Make sure we are queried for a multiselect
  286. ASSERT(CCT_UNINITIALIZED == type);
  287. // We need to create a special multiselect data object
  288. ASSERT(Psnapin());
  289. //NOTE: need to implement multi select dispatch obect
  290. sc = S_FALSE; //Psnapin()->ScCreateMultiSelectionDataObject(ppDataObject, this);
  291. if (sc)
  292. return sc;
  293. }
  294. else
  295. {
  296. // We are a component, we should only receive result pane cookies.
  297. ASSERT(type==CCT_RESULT);
  298. if (FVirtualResultsPane())
  299. {
  300. ASSERT(PitemScopeSelected());
  301. // This function is being asked for a data object for a row in a virtual
  302. // results pane. By definition there is no snapin item there. So we ask
  303. // the controlling scope item to provide us with a "temporary" data object.
  304. sc = S_FALSE; //PitemScopeSelected()->ScVirtualQueryDataObject(cookie, type, ppDataObject);
  305. if (sc)
  306. return sc;
  307. }
  308. else
  309. {
  310. // If the cookie does not correspond to a known object, return E_UNEXPECTED.
  311. // This is correct and is also a workaround for a MMC bug. See bug X5:74405.
  312. if (cookie && (Psnapin()->Pcookielist()->find(cookie) == Psnapin()->Pcookielist()->end() ) )
  313. {
  314. return(sc = E_UNEXPECTED);
  315. }
  316. pitem = Pitem(NULL, 0, cookie);
  317. ASSERT(pitem);
  318. sc = pitem->ScQueryDispatch(cookie, type, ppDispatch);
  319. if (sc)
  320. return sc;
  321. }
  322. }
  323. return sc;
  324. }
  325. SC
  326. CComponent::ScGetResultViewType2(MMC_COOKIE cookie, PRESULT_VIEW_TYPE_INFO pResultViewType)
  327. {
  328. DECLARE_SC(sc, _T("CComponent::ScGetResultViewType2"));
  329. CBaseSnapinItem *pitem = NULL;
  330. ASSERT(pResultViewType);
  331. pitem = Pitem(NULL, 0, cookie);
  332. ASSERT(pitem);
  333. sc = pitem->ScGetResultViewType2(m_ipConsole, pResultViewType);
  334. if (sc)
  335. return sc;
  336. return sc;
  337. }
  338. SC
  339. CComponent::ScRestoreResultView(MMC_COOKIE cookie, RESULT_VIEW_TYPE_INFO* pResultViewType)
  340. {
  341. DECLARE_SC(sc, _T("CComponent::ScRestoreResultView"));
  342. CBaseSnapinItem *pitem = NULL;
  343. ASSERT(pResultViewType);
  344. pitem = Pitem(NULL, 0, cookie);
  345. ASSERT(pitem);
  346. sc = pitem->ScRestoreResultView(pResultViewType);
  347. if (sc)
  348. return sc;
  349. return sc;
  350. }
  351. // -----------------------------------------------------------------------------
  352. // Handles the MMCN_SELECT notification sent to IComponent::Notify. Enables the Properties
  353. // and Refresh verbs. Sets Properties as the default verb.
  354. //
  355. SC CComponent::ScOnSelect(LPDATAOBJECT lpDataObject, BOOL fScope, BOOL fSelect)
  356. {
  357. // Declarations
  358. SC sc = S_OK;
  359. DWORD dwVerbs = 0;
  360. MMC_CONSOLE_VERB mmcverbDefault = MMC_VERB_NONE;
  361. INT i = 0;
  362. CBaseSnapinItem * pitem = NULL;
  363. CBaseMultiSelectSnapinItem *pBaseMultiSelectSnapinItem = NULL;
  364. // Data validation
  365. ASSERT(lpDataObject);
  366. // Determine if this is a multiselect data object
  367. sc = CBaseMultiSelectSnapinItem::ScGetMultiSelectDataObject(lpDataObject, &pBaseMultiSelectSnapinItem);
  368. if (sc)
  369. goto Error;
  370. // If we received a multiselect snapin item
  371. if (pBaseMultiSelectSnapinItem)
  372. {
  373. // Call ScOnSelect for the multiselect object for dispatch
  374. sc = pBaseMultiSelectSnapinItem->ScOnSelect(this, lpDataObject, fScope, fSelect);
  375. if (sc)
  376. goto Error;
  377. }
  378. else
  379. {
  380. // Handle the normal case - PItem() does more work than a simple cast to verify that the snapin item belongs to the snapin etc.
  381. pitem = Pitem(lpDataObject);
  382. ASSERT(pitem);
  383. if (pitem->FIsContainer())
  384. {
  385. // Enable the Open property // $REVIEW (dominicp) Why 2 separate calls?
  386. sc = IpConsoleVerb()->SetVerbState(MMC_VERB_OPEN, ENABLED, TRUE);
  387. if (sc)
  388. goto Error;
  389. // Need to hide it but keep it enabled.
  390. sc = IpConsoleVerb()->SetVerbState(MMC_VERB_OPEN, HIDDEN, TRUE);
  391. if (sc)
  392. goto Error;
  393. }
  394. if (fSelect)
  395. {
  396. // Get all the required verbs, bitwise-ORed together.
  397. sc = Psnapin()->ScGetVerbs(lpDataObject, &dwVerbs);
  398. if (sc)
  399. goto Error;
  400. // Loop through the list of verbs, turning on the needed ones.
  401. for (i=0; i<Psnapin()->Cverbmap(); i++)
  402. {
  403. ASSERT(Psnapin()->Pverbmap(i));
  404. if (dwVerbs & Psnapin()->Pverbmap(i)->verbmask)
  405. {
  406. sc = IpConsoleVerb()->SetVerbState(Psnapin()->Pverbmap(i)->mmcverb, ENABLED, TRUE);
  407. if (sc)
  408. goto Error;
  409. }
  410. }
  411. #ifdef _DEBUG
  412. if (tagBaseSnapinDebugCopy.FAny())
  413. {
  414. sc = IpConsoleVerb()->SetVerbState(MMC_VERB_COPY, ENABLED, TRUE);
  415. if (sc)
  416. goto Error;
  417. }
  418. #endif
  419. // Get the default verb.
  420. mmcverbDefault = Psnapin()->MmcverbDefault(lpDataObject);
  421. // Set the default verb, which is invoked by double clicking.
  422. if (mmcverbDefault != MMC_VERB_NONE)
  423. {
  424. sc = IpConsoleVerb()->SetDefaultVerb(mmcverbDefault);
  425. if (sc)
  426. goto Error;
  427. }
  428. }
  429. // To call DisplayStatusText for example, we need to get to the IComponent's IConsole2
  430. // IComponentData's IConsole2 is no good, so we pass 'this'
  431. sc = pitem->ScOnSelect(this, lpDataObject, fScope, fSelect);
  432. if (sc)
  433. goto Error;
  434. }
  435. Cleanup:
  436. return sc;
  437. Error:
  438. TraceError(_T("CComponent::ScOnSelect"), sc);
  439. goto Cleanup;
  440. }
  441. // -----------------------------------------------------------------------------
  442. // Loads per-view information. We don't have any.
  443. //
  444. SC CComponent::ScLoad(IStream *pstream)
  445. {
  446. return S_OK;
  447. }
  448. // -----------------------------------------------------------------------------
  449. // If one of the commands added to the context menu is
  450. // subsequently selected, MMC calls Command.
  451. //
  452. // Even though this method "looks" like the one in CComponentData,
  453. // the use of the Pitem() shortcut makes them different. The CComponentData
  454. // version does not pass a component to the real Pitem().
  455. //
  456. SC CComponent::ScCommand(long nCommandID, LPDATAOBJECT lpDataObject)
  457. {
  458. // Declarations
  459. SC sc = S_OK;
  460. CBaseSnapinItem * pitem = NULL;
  461. CBaseMultiSelectSnapinItem * pBaseMultiSelectSnapinItem = NULL;
  462. // Data validation
  463. ASSERT(lpDataObject);
  464. // See if we can extract the multi select data object from the composite data object
  465. sc = CBaseMultiSelectSnapinItem::ScExtractMultiSelectDataObject(Psnapin(), lpDataObject, &pBaseMultiSelectSnapinItem);
  466. if (sc)
  467. goto Error;
  468. // If we actually had a composite data object and we were able to find our multiselect snapin item
  469. if (pBaseMultiSelectSnapinItem)
  470. {
  471. // Call ScCommand for the multiselect object for dispatch
  472. sc = pBaseMultiSelectSnapinItem->ScCommand(this, nCommandID, lpDataObject);
  473. if (sc)
  474. goto Error;
  475. }
  476. else
  477. {
  478. // Handle the normal case - PItem() does more work than a simple cast to verify that the snapin item belongs to the snapin etc.
  479. pitem = Pitem(lpDataObject);
  480. ASSERT(pitem);
  481. sc = pitem->ScCommand(nCommandID, this);
  482. if (sc)
  483. goto Error;
  484. }
  485. Cleanup:
  486. return sc;
  487. Error:
  488. TraceError(_T("CComponent::ScCommand"), sc);
  489. goto Cleanup;
  490. }
  491. // -----------------------------------------------------------------------------
  492. // MMC wants to know the kind of result pane we want.
  493. //
  494. SC CComponent::ScGetResultViewType(long cookie, LPOLESTR *ppViewType, long *pViewOptions)
  495. {
  496. SC sc = S_OK;
  497. CBaseSnapinItem *pitem = NULL;
  498. ASSERT(ppViewType);
  499. ASSERT(pViewOptions);
  500. pitem = Pitem(NULL, 0, cookie);
  501. ASSERT(pitem);
  502. sc = pitem->ScGetResultViewType(ppViewType, pViewOptions);
  503. if (sc)
  504. goto Error;
  505. Cleanup:
  506. return sc;
  507. Error:
  508. TraceError(_T("CComponent::ScGetResultViewType"), sc);
  509. goto Cleanup;
  510. }
  511. // -----------------------------------------------------------------------------
  512. // IResultOwnerData method used to tell a snapin item which rows in
  513. // the result pane it will be asking for soon so they can be cached.
  514. //
  515. SC CComponent::ScCacheHint(INT nStartIndex, INT nEndIndex)
  516. {
  517. SC sc = S_OK;
  518. ASSERT(FVirtualResultsPane());
  519. ASSERT(PitemScopeSelected());
  520. sc = PitemScopeSelected()->ScCacheHint(nStartIndex, nEndIndex);
  521. if (sc)
  522. goto Error;
  523. Cleanup:
  524. return sc;
  525. Error:
  526. TraceError(_T("CComponent::ScCacheHint"), sc);
  527. goto Cleanup;
  528. }
  529. // -----------------------------------------------------------------------------
  530. // IResultOwnerData method used to ask a snapin item sort a virtual list.
  531. //
  532. SC CComponent::ScSortItems(INT nColumn, DWORD dwSortOptions, long lUserParam)
  533. {
  534. SC sc = S_OK;
  535. ASSERT(FVirtualResultsPane());
  536. ASSERT(PitemScopeSelected());
  537. sc = PitemScopeSelected()->ScSortItems(nColumn, dwSortOptions, lUserParam);
  538. if (sc)
  539. goto Error;
  540. Cleanup:
  541. return sc;
  542. Error:
  543. TraceError(_T("CComponent::ScSortItems"), sc);
  544. goto Cleanup;
  545. }
  546. // -----------------------------------------------------------------------------
  547. // Are we currently displaying a virtual list in the result pane ?
  548. //
  549. BOOL CComponent::FVirtualResultsPane(void)
  550. {
  551. // TRUE if an item is currently selected in the scope pane and it says it is virtual.
  552. return m_pitemScopeSelected && m_pitemScopeSelected->FVirtualResultsPane();
  553. }
  554. // -----------------------------------------------------------------------------
  555. // Determines whether any settings have changed since the last time the file
  556. // was saved.
  557. //
  558. SC CComponent::ScIsDirty(void)
  559. {
  560. SC sc = S_OK;
  561. BOOL fIsDirty = FALSE;
  562. INT i = 0;
  563. sc = Pitem()->ScIsDirty();
  564. if (sc == S_FALSE)
  565. sc = S_OK;
  566. else if (sc)
  567. fIsDirty = TRUE;
  568. else
  569. goto Error;
  570. Cleanup:
  571. sc = fIsDirty ? S_OK : S_FALSE;
  572. return sc;
  573. Error:
  574. TraceError(_T("CComponent::ScIsDirty"), sc);
  575. fIsDirty = FALSE;
  576. goto Cleanup;
  577. }
  578. // -----------------------------------------------------------------------------
  579. HRESULT CComponent::Initialize(LPCONSOLE lpConsole)
  580. {
  581. DECLARE_SC(sc, _T("CComponent::Initialize"));
  582. Trace(tagBaseSnapinIComponent, _T("--> %s::IComponent::Initialize(lpConsole=0x%08X)"), StrSnapinClassName(), lpConsole);
  583. ADMIN_TRY;
  584. sc = ScInitialize(lpConsole);
  585. ADMIN_CATCH_HR
  586. Trace(tagBaseSnapinIComponent, _T("<-- %s::IComponent::Initialize is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  587. return sc.ToHr();
  588. }
  589. // -----------------------------------------------------------------------------
  590. HRESULT CComponent::Notify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, long arg, long param)
  591. {
  592. DECLARE_SC(sc, _T("CComponent::Notify"));
  593. Trace(tagBaseSnapinIComponent, _T("--> %s::IComponent::Notify(lpDataObject=0x%08X, event=%s, arg=0x%08X, param=0x%08X)"), StrSnapinClassName(), lpDataObject, SzGetDebugNameOfMMC_NOTIFY_TYPE(event), arg, param);
  594. ADMIN_TRY;
  595. sc=ScNotify(lpDataObject, event, arg, param);
  596. ADMIN_CATCH_HR
  597. Trace(tagBaseSnapinIComponent, _T("<-- %s::IComponent::Notify is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  598. return sc.ToHr();
  599. }
  600. // -----------------------------------------------------------------------------
  601. HRESULT CComponent::Destroy(long cookie)
  602. {
  603. DECLARE_SC(sc, _T("CComponent::Destroy"));
  604. Trace(tagBaseSnapinIComponent, _T("--> %s::IComponent::Destroy"), StrSnapinClassName());
  605. ADMIN_TRY;
  606. sc=ScDestroy();
  607. ADMIN_CATCH_HR
  608. Trace(tagBaseSnapinIComponent, _T("<-- %s::IComponent::Destroy is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  609. return sc.ToHr();
  610. }
  611. // -----------------------------------------------------------------------------
  612. HRESULT CComponent::GetResultViewType(long cookie, LPOLESTR *ppViewType, long *pViewOptions)
  613. {
  614. DECLARE_SC(sc, _T("CComponent::GetResultViewType"));
  615. Trace(tagBaseSnapinIComponent, _T("--> %s::IComponent::GetResultViewType(cookie=0x%08X)"), StrSnapinClassName(), cookie);
  616. ADMIN_TRY;
  617. sc=ScGetResultViewType(cookie, ppViewType, pViewOptions);
  618. ADMIN_CATCH_HR
  619. Trace(tagBaseSnapinIComponent, _T("<-- %s::IComponent::GetResultViewType is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  620. return sc.ToHr();
  621. }
  622. // -----------------------------------------------------------------------------
  623. HRESULT CComponent::QueryDataObject(long cookie, DATA_OBJECT_TYPES type, LPDATAOBJECT *ppDataObject)
  624. {
  625. DECLARE_SC(sc, _T("CComponent::QueryDataObject"));
  626. Trace(tagBaseSnapinIComponentQueryDataObject, _T("--> %s::IComponent::QueryDataObject(cookie=0x%08X, type=%s)"), StrSnapinClassName(), cookie, SzGetDebugNameOfDATA_OBJECT_TYPES(type));
  627. ADMIN_TRY;
  628. //
  629. // If we receive E_UNEXPECTED we don't want to call MMCHrFromSc because
  630. // that will bring up an error message. We don't want an error message
  631. // in this case because of a known MMC bug (see bug X5:74405).
  632. // The bug says that we might receive QueryDataObject on items that
  633. // we were told no longer exists (by MMCN_REMOVE_CHILDREN).
  634. //
  635. sc = ScQueryDataObject(cookie, type, ppDataObject);
  636. if (sc)
  637. return sc.ToHr();
  638. ADMIN_CATCH_HR
  639. Trace(tagBaseSnapinIComponentQueryDataObject, _T("<-- %s::IComponent::QueryDataObject is returning hr=%s, *ppDataObject=0x%08X"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()), *ppDataObject);
  640. return sc.ToHr();
  641. }
  642. // -----------------------------------------------------------------------------
  643. HRESULT CComponent::GetDisplayInfo(RESULTDATAITEM *pResultDataItem)
  644. {
  645. DECLARE_SC(sc, _T("CComponent::GetDisplayInfo"));
  646. Trace(tagBaseSnapinIComponentGetDisplayInfo, _T("--> %s::IComponent::GetDisplayInfo(cookie=0x%08X)"), StrSnapinClassName(), pResultDataItem->lParam);
  647. ADMIN_TRY;
  648. sc=ScGetDisplayInfo(pResultDataItem);
  649. ADMIN_CATCH_HR
  650. Trace(tagBaseSnapinIComponentGetDisplayInfo, _T("<-- %s::IComponent::GetDisplayInfo is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  651. return sc.ToHr();
  652. }
  653. // -----------------------------------------------------------------------------
  654. HRESULT CComponent::CompareObjects(LPDATAOBJECT lpDataObjectA, LPDATAOBJECT lpDataObjectB)
  655. {
  656. DECLARE_SC(sc, _T("CComponent::CompareObjects"));
  657. Trace(tagBaseSnapinIComponent, _T("--> %s::IComponent::CompareObjects(lpDataObjectA=0x%08X, lpDataObjectB=0x%08X)"), StrSnapinClassName(), lpDataObjectA, lpDataObjectB);
  658. ADMIN_TRY;
  659. sc=Psnapin()->ScCompareObjects(lpDataObjectA, lpDataObjectB);
  660. ADMIN_CATCH_HR
  661. Trace(tagBaseSnapinIComponent, _T("<-- %s::IComponent::CompareObjects is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  662. return sc.ToHr();
  663. }
  664. // -----------------------------------------------------------------------------
  665. HRESULT CComponent::QueryDispatch(MMC_COOKIE cookie, DATA_OBJECT_TYPES type, LPDISPATCH* ppDispatch)
  666. {
  667. DECLARE_SC(sc, _T("CComponent::QueryDispatch"));
  668. ADMIN_TRY;
  669. sc = ScQueryDispatch(cookie, type, ppDispatch);
  670. ADMIN_CATCH_HR;
  671. Trace(tagBaseSnapinIComponent, _T("<-- %s::IComponent::QueryDispatch is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  672. return sc.ToHr();
  673. }
  674. // -----------------------------------------------------------------------------
  675. HRESULT CComponent::GetResultViewType2(MMC_COOKIE cookie, PRESULT_VIEW_TYPE_INFO pResultViewType)
  676. {
  677. DECLARE_SC(sc, _T("CComponent::GetResultViewType2"));
  678. ADMIN_TRY;
  679. sc = ScGetResultViewType2(cookie, pResultViewType);
  680. ADMIN_CATCH_HR;
  681. Trace(tagBaseSnapinIComponent, _T("<-- %s::IComponent::GetResultViewType2 is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  682. return sc.ToHr();
  683. }
  684. // -----------------------------------------------------------------------------
  685. HRESULT CComponent::RestoreResultView(MMC_COOKIE cookie, RESULT_VIEW_TYPE_INFO* pResultViewType)
  686. {
  687. DECLARE_SC(sc, _T("CComponent::RestoreResultView"));
  688. ADMIN_TRY;
  689. sc = ScRestoreResultView(cookie, pResultViewType);
  690. ADMIN_CATCH_HR;
  691. Trace(tagBaseSnapinIComponent, _T("<-- %s::IComponent::RestoreResultView is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  692. return sc.ToHr();
  693. }
  694. // -----------------------------------------------------------------------------
  695. HRESULT CComponent::AddMenuItems(LPDATAOBJECT pDataObject, LPCONTEXTMENUCALLBACK ipContextMenuCallback, long *pInsertionAllowed)
  696. {
  697. DECLARE_SC(sc, _T("CComponent::AddMenuItems"));
  698. Trace(tagBaseSnapinIExtendContextMenu, _T("--> %s::IExtendContextMenu::AddMenuItems(pDataObject=0x%08X)"), StrSnapinClassName(), pDataObject);
  699. ADMIN_TRY;
  700. sc=Psnapin()->ScAddMenuItems(pDataObject, ipContextMenuCallback, pInsertionAllowed);
  701. ADMIN_CATCH_HR
  702. Trace(tagBaseSnapinIExtendContextMenu, _T("<-- %s::IExtendContextMenu::AddMenuItems is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  703. return sc.ToHr();
  704. }
  705. // -----------------------------------------------------------------------------
  706. HRESULT CComponent::Command(long nCommandID, LPDATAOBJECT pDataObject)
  707. {
  708. DECLARE_SC(sc, _T("CComponent::Command"));
  709. Trace(tagBaseSnapinIExtendContextMenu, _T("--> %s::IExtendContextMenu::Command(nCommandID=%ld, pDataObject=0x%08X)"), StrSnapinClassName(), nCommandID, pDataObject);
  710. ADMIN_TRY;
  711. sc=ScCommand(nCommandID, pDataObject);
  712. ADMIN_CATCH_HR
  713. Trace(tagBaseSnapinIExtendContextMenu, _T("<-- %s::IExtendContextMenu::Command is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  714. return sc.ToHr();
  715. }
  716. // -----------------------------------------------------------------------------
  717. HRESULT CComponent::CreatePropertyPages(LPPROPERTYSHEETCALLBACK lpProvider, long handle, LPDATAOBJECT lpDataObject)
  718. {
  719. DECLARE_SC(sc, _T("CComponent::CreatePropertyPages"));
  720. Trace(tagBaseSnapinIExtendPropertySheet, _T("--> %s::IExtendPropertySheet::CreatePropertyPages(lpDataObject=0x%08X)"), StrSnapinClassName(), lpDataObject);
  721. ADMIN_TRY;
  722. sc = ScCreatePropertyPages(lpProvider, handle, lpDataObject);
  723. if (sc)
  724. sc=sc.ToHr();
  725. ADMIN_CATCH_HR
  726. Trace(tagBaseSnapinIExtendPropertySheet, _T("<-- %s::IExtendPropertySheet::CreatePropertyPages is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  727. return sc.ToHr();
  728. }
  729. // -----------------------------------------------------------------------------
  730. HRESULT CComponent::QueryPagesFor(LPDATAOBJECT lpDataObject)
  731. {
  732. DECLARE_SC(sc, _T("CComponent::QueryPagesFor"));
  733. Trace(tagBaseSnapinIExtendPropertySheet, _T("--> %s::IExtendPropertySheet::QueryPagesFor(lpDataObject=0x%08X)"), StrSnapinClassName(), lpDataObject);
  734. ADMIN_TRY;
  735. sc=ScQueryPagesFor(lpDataObject);
  736. ADMIN_CATCH_HR
  737. Trace(tagBaseSnapinIExtendPropertySheet, _T("<-- %s::IExtendPropertySheet::QueryPagesFor is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  738. return sc.ToHr();
  739. }
  740. // -----------------------------------------------------------------------------
  741. HRESULT CComponent::GetSizeMax(ULARGE_INTEGER *pcbSize)
  742. {
  743. DECLARE_SC(sc, _T("CComponent::GetSizeMax"));
  744. Trace(tagBaseSnapinIPersistStreamInit, _T("--> %s::IPersistStreamInit::GetSizeMax"), StrSnapinClassName());
  745. ADMIN_TRY;
  746. ASSERT(pcbSize);
  747. pcbSize->LowPart = cMaxStreamSizeLow;
  748. pcbSize->HighPart = cMaxStreamSizeHigh;
  749. ADMIN_CATCH_HR
  750. Trace(tagBaseSnapinIPersistStreamInit, _T("<-- %s::IPersistStreamInit::GetSizeMax is returning hr=%s, (*pcbSize).LowPart=%d"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()), (*pcbSize).LowPart);
  751. return sc.ToHr();
  752. }
  753. // -----------------------------------------------------------------------------
  754. HRESULT CComponent::IsDirty(void)
  755. {
  756. DECLARE_SC(sc, _T("CComponent::IsDirty"));
  757. Trace(tagBaseSnapinIPersistStreamInit, _T("--> %s::IPersistStreamInit::IsDirty"), StrSnapinClassName());
  758. ADMIN_TRY;
  759. sc=ScIsDirty();
  760. ADMIN_CATCH_HR
  761. Trace(tagBaseSnapinIPersistStreamInit, _T("<-- %s::IPersistStreamInit::IsDirty is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  762. return sc.ToHr();
  763. }
  764. // -----------------------------------------------------------------------------
  765. HRESULT CComponent::Load(IStream *pstream)
  766. {
  767. DECLARE_SC(sc, _T("CComponent::Load"));
  768. Trace(tagBaseSnapinIPersistStreamInit, _T("--> %s::IPersistStreamInit::Load"), StrSnapinClassName());
  769. ADMIN_TRY;
  770. sc=ScLoad(pstream);
  771. ADMIN_CATCH_HR
  772. Trace(tagBaseSnapinIPersistStreamInit, _T("<-- %s::IPersistStreamInit::Load is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  773. return sc.ToHr();
  774. }
  775. // -----------------------------------------------------------------------------
  776. HRESULT CComponent::Save(IStream *pstream, BOOL fClearDirty)
  777. {
  778. DECLARE_SC(sc, _T("CComponent::Save"));
  779. Trace(tagBaseSnapinIPersistStreamInit, _T("--> %s::IPersistStreamInit::Save(fClearDirty=%S)"), StrSnapinClassName(), fClearDirty ? "TRUE" : "FALSE");
  780. ADMIN_TRY;
  781. sc=ScSave(pstream, fClearDirty);
  782. ADMIN_CATCH_HR
  783. Trace(tagBaseSnapinIPersistStreamInit, _T("<-- %s::IPersistStreamInit::Save is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  784. return sc.ToHr();
  785. }
  786. // -----------------------------------------------------------------------------
  787. HRESULT CComponent::InitNew(void)
  788. {
  789. DECLARE_SC(sc, _T("CComponent::InitNew"));
  790. // We don't have anything to do, but we still want to log the call.
  791. Trace(tagBaseSnapinIPersistStreamInit, _T("--> %s::IPersistStreamInit::InitNew"), StrSnapinClassName());
  792. Trace(tagBaseSnapinIPersistStreamInit, _T("<-- %s::IPersistStreamInit::InitNew is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  793. return sc.ToHr();
  794. }
  795. // -----------------------------------------------------------------------------
  796. HRESULT CComponent::GetClassID(CLSID *pclsid)
  797. {
  798. DECLARE_SC(sc, _T("CComponent::GetClassID"));
  799. Trace(tagBaseSnapinIPersistStreamInit, _T("--> %s::IPersistStreamInit::GetClassID"), StrSnapinClassName());
  800. ADMIN_TRY;
  801. ASSERT(pclsid);
  802. *pclsid = *(Psnapin()->PclsidSnapin());
  803. ADMIN_CATCH_HR
  804. Trace(tagBaseSnapinIPersistStreamInit, _T("<-- %s::IPersistStreamInit::GetClassID is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  805. return sc.ToHr();
  806. }
  807. // -----------------------------------------------------------------------------
  808. HRESULT CComponent::CacheHint(int nStartIndex, int nEndIndex)
  809. {
  810. DECLARE_SC(sc,_T("CComponent::CacheHint"));
  811. Trace(tagBaseSnapinIResultOwnerData, _T("--> %s::IResultOwnerData::CacheHint(nStartIndex=%d, nEndIndex=%d)"), StrSnapinClassName(), nStartIndex, nEndIndex);
  812. ADMIN_TRY;
  813. sc=ScCacheHint(nStartIndex, nEndIndex);
  814. ADMIN_CATCH_HR
  815. Trace(tagBaseSnapinIResultOwnerData, _T("<-- %s::IResultOwnerData::CacheHint is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  816. return sc.ToHr();
  817. }
  818. // -----------------------------------------------------------------------------
  819. HRESULT CComponent::SortItems(int nColumn, DWORD dwSortOptions, long lUserParam)
  820. {
  821. DECLARE_SC(sc,_T("CComponent::SortItems"));
  822. Trace(tagBaseSnapinIResultOwnerData, _T("--> %s::IResultOwnerData::SortItems"), StrSnapinClassName());
  823. ADMIN_TRY;
  824. sc=ScSortItems(nColumn, dwSortOptions, lUserParam);
  825. ADMIN_CATCH_HR
  826. Trace(tagBaseSnapinIResultOwnerData, _T("<-- %s::IResultOwnerData::SortItems is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  827. return sc.ToHr();
  828. }
  829. // -----------------------------------------------------------------------------
  830. HRESULT CComponent::FindItem(LPRESULTFINDINFO pFindinfo, int *pnFoundIndex)
  831. {
  832. DECLARE_SC(sc,_T("CComponent::FindItem"));
  833. Trace(tagBaseSnapinIResultOwnerData, _T("--> %s::IResultOwnerData::FindItem"), StrSnapinClassName());
  834. ADMIN_TRY;
  835. ASSERT(pnFoundIndex);
  836. sc = ScFindItem(pFindinfo, pnFoundIndex);
  837. if (! sc)
  838. // if no error occured -- convert the found item index into the mmc expected return codes
  839. sc=(*pnFoundIndex != -1) ? S_OK : S_FALSE;
  840. ADMIN_CATCH_HR
  841. Trace(tagBaseSnapinIResultOwnerData, _T("<-- %s::IResultOwnerData::FindItem is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  842. return sc.ToHr();
  843. }
  844. // -----------------------------------------------------------------------------
  845. HRESULT CComponent::Compare(RDCOMPARE * prdc, int * pnResult)
  846. {
  847. DECLARE_SC(sc,_T("CComponent::Compare"));
  848. Trace(tagBaseSnapinIResultDataCompare, _T("--> %s::IResultDataCompare::Compare(cookieA=0x%08X, cookieB=0x%08X)"), StrSnapinClassName(), prdc->prdch1->cookie, prdc->prdch2->cookie);
  849. ADMIN_TRY;
  850. ASSERT(pnResult);
  851. ASSERT(prdc);
  852. ASSERT(prdc->prdch1);
  853. ASSERT(prdc->prdch2);
  854. sc=Psnapin()->ScCompare(prdc->prdch1->cookie, prdc->prdch2->cookie, prdc->nColumn, pnResult);
  855. ADMIN_CATCH_HR
  856. Trace(tagBaseSnapinIResultDataCompare, _T("<-- %s::IResultDataCompare::Compare is returning hr=%s, *pnResult=%d"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()), *pnResult);
  857. return sc.ToHr();
  858. }
  859. // -----------------------------------------------------------------------------
  860. // IResultOwnerData method used to ask a snapin item to do a find
  861. // in a virtual list.
  862. //
  863. SC CComponent::ScFindItem(LPRESULTFINDINFO pFindinfo, INT *pnFoundIndex)
  864. {
  865. SC sc = S_OK;
  866. ASSERT(FVirtualResultsPane());
  867. ASSERT(PitemScopeSelected());
  868. sc = PitemScopeSelected()->ScFindItem(pFindinfo, pnFoundIndex);
  869. if (sc)
  870. goto Error;
  871. Cleanup:
  872. return sc;
  873. Error:
  874. TraceError(_T("CComponent::ScFindItem"), sc);
  875. goto Cleanup;
  876. }
  877. // -----------------------------------------------------------------------------
  878. // Handles the MMCN_DBLCLICK notification sent to IComponent::Notify.
  879. //
  880. SC CComponent::ScOnDoubleClick(LPDATAOBJECT lpDataObject)
  881. {
  882. // $REVIEW (ptousig) What does S_FALSE mean ?
  883. return S_FALSE;
  884. }
  885. // -----------------------------------------------------------------------------
  886. // Creates a data object of the appropriate type, and returns the
  887. // IDataObject interface on it.
  888. //
  889. SC CComponent::ScQueryDataObject(long cookie, DATA_OBJECT_TYPES type, LPDATAOBJECT * ppDataObject)
  890. {
  891. // Declarations
  892. SC sc = S_OK;
  893. CBaseSnapinItem * pitem = NULL;
  894. // Determine if we have a special cookie for multiselect
  895. if (IS_SPECIAL_COOKIE(cookie) && (MMC_MULTI_SELECT_COOKIE == cookie))
  896. {
  897. // Make sure we are queried for a multiselect
  898. ASSERT(CCT_UNINITIALIZED == type);
  899. // We need to create a special multiselect data object
  900. ASSERT(Psnapin());
  901. sc = Psnapin()->ScCreateMultiSelectionDataObject(ppDataObject, this);
  902. if (sc)
  903. goto Error;
  904. }
  905. else
  906. {
  907. // We are a component, we should only receive result pane cookies.
  908. ASSERT(type==CCT_RESULT);
  909. if (FVirtualResultsPane())
  910. {
  911. ASSERT(PitemScopeSelected());
  912. // This function is being asked for a data object for a row in a virtual
  913. // results pane. By definition there is no snapin item there. So we ask
  914. // the controlling scope item to provide us with a "temporary" data object.
  915. sc = PitemScopeSelected()->ScVirtualQueryDataObject(cookie, type, ppDataObject);
  916. if (sc)
  917. goto Error;
  918. }
  919. else
  920. {
  921. // If the cookie does not correspond to a known object, return E_UNEXPECTED.
  922. // This is correct and is also a workaround for a MMC bug. See bug X5:74405.
  923. if (cookie && (Psnapin()->Pcookielist()->find(cookie) == Psnapin()->Pcookielist()->end() ) )
  924. {
  925. sc = E_UNEXPECTED;
  926. goto Cleanup;
  927. }
  928. pitem = Pitem(NULL, 0, cookie);
  929. ASSERT(pitem);
  930. sc = pitem->ScQueryDataObject(cookie, type, ppDataObject);
  931. if (sc)
  932. goto Error;
  933. }
  934. }
  935. Cleanup:
  936. return sc;
  937. Error:
  938. TraceError(_T("CComponent::ScQueryDataObject"), sc);
  939. goto Cleanup;
  940. }
  941. // -----------------------------------------------------------------------------
  942. // Handles the MMCN_SHOW notification sent to IComponent::Notify. Initializes the
  943. // default list view's headers.
  944. //
  945. SC CComponent::ScOnShow(LPDATAOBJECT lpDataObject, BOOL fSelect, HSCOPEITEM hscopeitem)
  946. {
  947. SC sc = S_OK;
  948. BOOL fIsOwned = TRUE;
  949. CBaseSnapinItem *pitem = NULL;
  950. pitem = Pitem(lpDataObject, hscopeitem);
  951. ASSERT(pitem);
  952. // Since we are selecting/deselecting a scope item we
  953. // need to update who the selected scope item is. Note:
  954. // we dont do this in MMCN_SELECT. MMCN_SELECT gets called
  955. // when a results node is being selected. We aren't tracking
  956. // the selected RESULTS node but selected SCOPE node.
  957. SetItemScopeSelected(fSelect ? pitem : NULL);
  958. // Use this opportunity to correlate the CSnapinItem and the HSCOPEITEM.
  959. // $REVIEW (ptousig) Should be done inside Pitem().
  960. pitem->SetHscopeitem(hscopeitem);
  961. // Set up the list view.
  962. sc = pitem->ScOnShow(this, fSelect);
  963. if (sc)
  964. goto Error;
  965. // $REVIEW (ptousig) Couldn't we just call ScOnViewChangeUpdateResultItems either way ?
  966. if (fSelect)
  967. {
  968. // Note: this is not a call to UpdateAllViews
  969. sc = ScOnViewChangeUpdateResultItems(pitem, fSelect);
  970. if (sc)
  971. goto Error;
  972. }
  973. else
  974. {
  975. // This call doesn't do anything.
  976. sc = pitem->ScRemoveResultItems(IpResultData());
  977. if (sc)
  978. goto Error;
  979. }
  980. Cleanup:
  981. return sc;
  982. Error:
  983. TraceError(_T("CComponent::ScOnShow"), sc);
  984. goto Cleanup;
  985. }
  986. // -----------------------------------------------------------------------------
  987. // Used to update the description bar
  988. //
  989. SC CComponent::ScOnViewChangeUpdateDescriptionBar(CBaseSnapinItem *pitem)
  990. {
  991. SC sc = S_OK;
  992. if (PitemScopeSelected() != pitem)
  993. goto Cleanup;
  994. if (pitem->PstrDescriptionBar())
  995. {
  996. ASSERT(IpResultData());
  997. sc = IpResultData()->SetDescBarText((LPTSTR)pitem->PstrDescriptionBar()->data());
  998. if (sc)
  999. goto Error;
  1000. }
  1001. Cleanup:
  1002. return sc;
  1003. Error:
  1004. TraceError(_T("CComponent::ScOnViewChangeUpdateDescriptionBar"), sc);
  1005. goto Cleanup;
  1006. }
  1007. // -----------------------------------------------------------------------------
  1008. // Used to update an item's result-item children.
  1009. //
  1010. SC CComponent::ScOnViewChangeUpdateResultItems(CBaseSnapinItem *pitem, BOOL fSelect)
  1011. {
  1012. SC sc = S_OK;
  1013. CViewItemList viewitemlist;
  1014. CViewItemListBase::iterator viewitemiter;
  1015. if (PitemScopeSelected() != pitem)
  1016. goto Cleanup;
  1017. if (!pitem->FUsesResultList())
  1018. goto Cleanup;
  1019. if (fSelect)
  1020. {
  1021. // Create a result view.
  1022. viewitemlist.Initialize(pitem, pitem->DatPresort(), pitem->DatSort());
  1023. // Update description text
  1024. if (pitem->PstrDescriptionBar())
  1025. {
  1026. sc = IpResultData()->SetDescBarText((LPTSTR)pitem->PstrDescriptionBar()->data());
  1027. if (sc)
  1028. goto Error;
  1029. }
  1030. // remove all result items because are going to re add them
  1031. // all here.
  1032. sc = IpResultData()->DeleteAllRsltItems();
  1033. if (sc)
  1034. goto Error;
  1035. // if we are selecting and updating the result pane then we
  1036. // are inserting all the result items. We need to make sure that
  1037. // we are in vlb mode and that the number of vlb items is set
  1038. // by initializing the result view.
  1039. sc = pitem->ScInitializeResultView(this);
  1040. if (sc)
  1041. goto Error;
  1042. // Insert all leaf nodes into the list view.
  1043. for (viewitemiter = viewitemlist.begin(); viewitemiter < viewitemlist.end(); viewitemiter++)
  1044. {
  1045. // Only add non-container, ie leaf, nodes.
  1046. if ((*viewitemiter)->FIsContainer() == FALSE)
  1047. {
  1048. sc = (*viewitemiter)->ScInsertResultItem(this);
  1049. if (sc)
  1050. goto Error;
  1051. }
  1052. }
  1053. }
  1054. else
  1055. {
  1056. // $REVIEW (ptousig) This could be done from inside "pitem->ScRemoveResultItems".
  1057. sc = IpResultData()->DeleteAllRsltItems();
  1058. if (sc)
  1059. goto Error;
  1060. sc = pitem->ScRemoveResultItems(IpResultData());
  1061. if (sc)
  1062. goto Error;
  1063. }
  1064. Cleanup:
  1065. return sc;
  1066. Error:
  1067. TraceError(_T("CComponent::ScOnViewChangeUpdateResultItems"), sc);
  1068. goto Cleanup;
  1069. }
  1070. // -----------------------------------------------------------------------------
  1071. // Called by the MMC upon a call to IConsole->UpdateAllViews().
  1072. //
  1073. SC CComponent::ScOnViewChange(LPDATAOBJECT lpDataObject, long data, long hint)
  1074. {
  1075. SC sc = S_OK;
  1076. CBaseSnapinItem * pitem = NULL;
  1077. pitem = Pitem(lpDataObject);
  1078. switch (hint)
  1079. {
  1080. case ONVIEWCHANGE_DELETEITEMS:
  1081. // Are we being called to delete all items?
  1082. sc = ScOnViewChangeDeleteItems(pitem);
  1083. break;
  1084. case ONVIEWCHANGE_DELETESINGLEITEM:
  1085. sc = ScOnViewChangeDeleteSingleItem(pitem);
  1086. break;
  1087. case ONVIEWCHANGE_INSERTNEWITEM:
  1088. sc = ScOnViewChangeInsertItem(pitem);
  1089. break;
  1090. case ONVIEWCHANGE_UPDATERESULTITEM:
  1091. sc = ScOnViewChangeUpdateItem(pitem);
  1092. break;
  1093. case ONVIEWCHANGE_REFRESHCHILDREN:
  1094. sc = ScOnRefresh(pitem->Pdataobject(), data);
  1095. break;
  1096. case ONVIEWCHANGE_DELETERESULTITEMS:
  1097. sc = ScOnViewChangeUpdateResultItems(pitem, FALSE);
  1098. break;
  1099. case ONVIEWCHANGE_UPDATEDESCRIPTIONBAR:
  1100. sc = ScOnViewChangeUpdateDescriptionBar(pitem);
  1101. break;
  1102. case ONVIEWCHANGE_INSERTRESULTITEMS:
  1103. sc = ScOnViewChangeUpdateResultItems(pitem, TRUE);
  1104. break;
  1105. default:
  1106. sc = ScOnViewChangeHint(pitem, hint);
  1107. break;
  1108. }
  1109. if (sc)
  1110. goto Error;
  1111. Cleanup:
  1112. return sc;
  1113. Error:
  1114. TraceError(_T("CComponent::ScOnViewChange"), sc);
  1115. goto Cleanup;
  1116. }
  1117. // -----------------------------------------------------------------------------
  1118. // Deletes all the items underneath the root. This is typically used to regenerate the tree.
  1119. //
  1120. SC CComponent::ScOnViewChangeDeleteItems(CBaseSnapinItem *pitem)
  1121. {
  1122. SC sc = S_OK;
  1123. CBaseSnapinItem *pitemRoot = NULL;
  1124. pitemRoot = Pitem();
  1125. // First check that the root item's HSCOPEITEM is non-null.
  1126. // If it is NULL the item was never Expand'ed or Show'ed so OK to ignore.
  1127. if (pitemRoot->Hscopeitem() == 0)
  1128. goto Cleanup;
  1129. // Select the root scope item first.
  1130. ASSERT(pitemRoot->Hscopeitem());
  1131. sc = IpConsole()->SelectScopeItem(pitemRoot->Hscopeitem());
  1132. if (sc)
  1133. goto Error;
  1134. // Delete all items below the root node, not counting the root node itself.
  1135. sc = IpConsoleNameSpace()->DeleteItem(pitemRoot->Hscopeitem(), FALSE);
  1136. if (sc)
  1137. goto Error;
  1138. Cleanup:
  1139. return sc;
  1140. Error:
  1141. TraceError(_T("CComponent::ScOnViewChangeDeleteItems"), sc);
  1142. goto Cleanup;
  1143. }
  1144. // -----------------------------------------------------------------------------
  1145. // Used to delete a single item. If the item is a container, it is deleted from the namespace [NYI]. If it
  1146. // is a leaf, it is deleted from the result view.
  1147. //
  1148. SC CComponent::ScOnViewChangeDeleteSingleItem(CBaseSnapinItem *pitem)
  1149. {
  1150. SC sc = S_OK;
  1151. HRESULTITEM itemID = NULL;
  1152. // Find out the item ID of the data object.
  1153. sc = IpResultData()->FindItemByLParam((LPARAM) pitem, &itemID);
  1154. if (sc)
  1155. {
  1156. // $REVIEW (ptousig) Why are we ignoring errors ?
  1157. sc = S_OK;
  1158. goto Cleanup;
  1159. }
  1160. // Delete it from the result view.
  1161. sc = IpResultData()->DeleteItem(itemID, 0);
  1162. if (sc)
  1163. goto Error;
  1164. Cleanup:
  1165. return sc;
  1166. Error:
  1167. TraceError(_T("CComponent::ScOnViewChangeDeleteSingleItem"), sc);
  1168. goto Cleanup;
  1169. }
  1170. // -----------------------------------------------------------------------------
  1171. // Pass a view change notification (that we don't have a predefined handler for)
  1172. // to the snapin item.
  1173. //
  1174. SC CComponent::ScOnViewChangeHint(CBaseSnapinItem *pitem, long hint)
  1175. {
  1176. SC sc = S_OK;
  1177. ASSERT(pitem);
  1178. sc = pitem->ScOnViewChangeHint(hint, this);
  1179. if (sc)
  1180. goto Error;
  1181. Cleanup:
  1182. return sc;
  1183. Error:
  1184. TraceError(_T("CComponent::ScOnViewChangeHint"), sc);
  1185. goto Cleanup;
  1186. }
  1187. // -----------------------------------------------------------------------------
  1188. // Inserts a new item into the namespace/result view. Called when the property sheet for a new item is
  1189. // dismissed with OK being pressed.
  1190. // The PitemParent() of the node being inserted should already be set.
  1191. //
  1192. SC CComponent::ScOnViewChangeInsertItem(CBaseSnapinItem *pitem)
  1193. {
  1194. SC sc = S_OK;
  1195. // $REVIEW (ptousig) Why is the view inserting the item in the document ?
  1196. // Wouldn't that end up getting executed multiple times ?
  1197. sc = PComponentData()->ScOnDocumentChangeInsertItem(pitem);
  1198. if (sc)
  1199. goto Error;
  1200. if (pitem->FIsContainer() == FALSE) // leaf items need to be added to every view.
  1201. {
  1202. //
  1203. // If the parent of the new item is the currently selected scope item,
  1204. // then add the new item to the result pane.
  1205. //
  1206. ASSERT(pitem->PitemParent());
  1207. if (PitemScopeSelected() == pitem->PitemParent())
  1208. // $REVIEW (ptousig) Why are we ignoring errors ?
  1209. pitem->ScInsertResultItem(this);
  1210. }
  1211. Cleanup:
  1212. return sc;
  1213. Error:
  1214. TraceError(_T("CComponent::ScOnViewChangeInsertItem"), sc);
  1215. goto Cleanup;
  1216. }
  1217. // -----------------------------------------------------------------------------
  1218. // Used to update an item when properties on it change.
  1219. //
  1220. SC CComponent::ScOnViewChangeUpdateItem(CBaseSnapinItem *pitem)
  1221. {
  1222. SC sc = S_OK;
  1223. // This works as follows. RESULTDATAITEMS are automatically inserted by the MMC for all scope nodes that
  1224. // are in the result pane (ie container nodes.) RESULTDATAITEMS are inserted by the snapin for leaf nodes.
  1225. // So calling ScUpdateResultItem works correctly for all items that are in the result pane, because it first
  1226. // calls IResultData->FindItemByLParam(), and if that succeeded, calls IResultData->UpdateItem().
  1227. sc = pitem->ScUpdateResultItem(IpResultData());
  1228. if (sc == E_FAIL)
  1229. // the item was not updated because it is not in the list anymore
  1230. sc = S_FALSE;
  1231. else if (sc)
  1232. goto Error;
  1233. Cleanup:
  1234. return sc;
  1235. Error:
  1236. TraceError(_T("CComponent::ScOnViewChangeUpdateItem"), sc);
  1237. goto Cleanup;
  1238. }
  1239. // -----------------------------------------------------------------------------
  1240. // Handles the MMCN_REFRESH notification.
  1241. //
  1242. SC CComponent::ScOnRefresh(LPDATAOBJECT lpDataObject, HSCOPEITEM hscopeitem)
  1243. {
  1244. SC sc = S_OK;
  1245. BOOL fIsOwned = FALSE;
  1246. CNodeType *pnodetype = NULL;
  1247. CBaseSnapinItem *pitem = NULL;
  1248. CBaseSnapinItem *pCurrent = NULL;
  1249. BOOL fWasExpanded = FALSE;
  1250. // Find out which item was asked to refresh
  1251. pitem = Pitem(lpDataObject, hscopeitem);
  1252. // Is this the notification for the owner of the node or for
  1253. // the extension of a node ?
  1254. sc = Psnapin()->ScIsOwnedDataObject(lpDataObject, &fIsOwned, &pnodetype);
  1255. if (sc)
  1256. goto Error;
  1257. if (fIsOwned)
  1258. {
  1259. // If we have never been expanded before, refresh would be pointless.
  1260. sc = PComponentData()->ScWasExpandedOnce(pitem, &fWasExpanded);
  1261. if (sc)
  1262. goto Error;
  1263. if (fWasExpanded == FALSE)
  1264. goto Cleanup;
  1265. // Remove all visible result items before we delete the pitems behind them
  1266. sc = IpConsole()->UpdateAllViews(lpDataObject, 0, ONVIEWCHANGE_DELETERESULTITEMS);
  1267. if (sc)
  1268. goto Error;
  1269. // Delete children pitems
  1270. sc = pitem->ScDeleteSubTree(FALSE);
  1271. if (sc)
  1272. goto Error;
  1273. // Ask the node that was refreshed to update its data
  1274. sc = pitem->ScOnRefresh();
  1275. if (sc)
  1276. goto Error;
  1277. // Most of our snapins reload data on ScOnPropertyChange
  1278. sc = pitem->ScOnPropertyChange();
  1279. if (sc)
  1280. goto Error;
  1281. // Recreate children with fresh data
  1282. sc = PComponentData()->ScOnExpand(pitem->Pdataobject(), TRUE, pitem->Hscopeitem());
  1283. if (sc)
  1284. goto Error;
  1285. // Add result items back to all instances of the refreshed node that are selected
  1286. sc = IpConsole()->UpdateAllViews(lpDataObject, 0, ONVIEWCHANGE_INSERTRESULTITEMS);
  1287. if (sc)
  1288. goto Error;
  1289. }
  1290. else
  1291. {
  1292. // Delete children
  1293. sc = pitem->ScDeleteSubTree(FALSE);
  1294. if (sc)
  1295. goto Error;
  1296. // Update refreshed items data
  1297. sc = pitem->ScOnRefresh();
  1298. if (sc)
  1299. goto Error;
  1300. // Most of our snapins reload data on ScOnPropertyChange
  1301. sc = pitem->ScOnPropertyChange();
  1302. if (sc)
  1303. goto Error;
  1304. // Recreate children with fresh data
  1305. sc = PComponentData()->ScOnExpand(pitem->Pdataobject(), TRUE, pitem->Hscopeitem());
  1306. if (sc)
  1307. goto Error;
  1308. }
  1309. Cleanup:
  1310. return sc;
  1311. Error:
  1312. TraceError(_T("CComponent::ScOnRefresh"), sc);
  1313. goto Cleanup;
  1314. }
  1315. // -----------------------------------------------------------------------------
  1316. // $REVIEW (ptousig) I don't know when this is called.
  1317. //
  1318. SC CComponent::ScOnListPad(LPDATAOBJECT lpDataObject, BOOL fAttach)
  1319. {
  1320. SC sc = S_OK;
  1321. CBaseSnapinItem *pitem = NULL;
  1322. pitem = Pitem(lpDataObject);
  1323. ASSERT(pitem);
  1324. sc = pitem->ScOnAddImages(IpImageList());
  1325. if (sc)
  1326. goto Error;
  1327. sc = ScOnShow(lpDataObject, fAttach, pitem->Hscopeitem());
  1328. if (sc)
  1329. goto Error;
  1330. Cleanup:
  1331. return sc;
  1332. Error:
  1333. TraceError(_T("CComponent::ScOnExpand"), sc);
  1334. goto Cleanup;
  1335. }
  1336. // -----------------------------------------------------------------------------
  1337. // The user has asked to delete this node.
  1338. //
  1339. SC CComponent::ScOnDelete(LPDATAOBJECT lpDataObject)
  1340. {
  1341. // Declarations
  1342. SC sc = S_OK;
  1343. CBaseSnapinItem * pitem = NULL;
  1344. BOOL fDeleted = FALSE;
  1345. BOOL fPagesUp = FALSE;
  1346. tstring strMsg;
  1347. CBaseMultiSelectSnapinItem * pBaseMultiSelectSnapinItem = NULL;
  1348. // Data validation
  1349. ASSERT(lpDataObject);
  1350. // Determine if this is a multiselect data object
  1351. sc = CBaseMultiSelectSnapinItem::ScGetMultiSelectDataObject(lpDataObject, &pBaseMultiSelectSnapinItem);
  1352. if (sc)
  1353. goto Error;
  1354. // If we received a multiselect snapin item
  1355. if (pBaseMultiSelectSnapinItem)
  1356. {
  1357. // Call ScOnDelete for the multiselect object
  1358. sc = pBaseMultiSelectSnapinItem->ScOnDelete(this, lpDataObject);
  1359. if (sc)
  1360. goto Error;
  1361. }
  1362. else
  1363. {
  1364. // Handle the normal case - PItem() does more work than a simple cast to verify that the snapin item belongs to the snapin etc.
  1365. pitem = Pitem(lpDataObject);
  1366. ASSERT(pitem);
  1367. // The Component should only receive notifications for result pane items
  1368. ASSERT(pitem->FIsContainer() == FALSE);
  1369. // Check if property pages are open for the object
  1370. // $REVIEW (dominicp) What if another Administrator has property pages open anyways? Not much point in doing this.
  1371. sc = pitem->ScIsPropertySheetOpen(&fPagesUp, dynamic_cast<IComponent *>(this));
  1372. if (sc)
  1373. goto Error;
  1374. if (fPagesUp)
  1375. {
  1376. ASSERT(FALSE && "Add below resource string");
  1377. //strMsg.LoadString(_Module.GetResourceInstance(), idsPropsUpNoDelete);
  1378. strMsg += (*pitem->PstrDisplayName());
  1379. MMCErrorBox(strMsg.data());
  1380. goto Cleanup;
  1381. }
  1382. // Ask the item to delete the underlying object.
  1383. sc = pitem->ScOnDelete(&fDeleted);
  1384. if (sc)
  1385. goto Error;
  1386. if (fDeleted == FALSE)
  1387. // The item did not want to be deleted.
  1388. goto Cleanup;
  1389. // Leaf items need to be deleted from the views.
  1390. sc = IpConsole()->UpdateAllViews(lpDataObject, 0, ONVIEWCHANGE_DELETESINGLEITEM);
  1391. if (sc)
  1392. goto Error;
  1393. // At this point, the item exists only in the tree, if at all.
  1394. // Remove it from the tree.
  1395. pitem->Unlink();
  1396. // Get rid of it for good from the tree of items.
  1397. pitem->Pdataobject()->Release();
  1398. }
  1399. Cleanup:
  1400. return sc;
  1401. Error:
  1402. TraceError(_T("CComponent::ScOnDelete"), sc);
  1403. goto Cleanup;
  1404. }
  1405. // -----------------------------------------------------------------------------
  1406. // The user wants context-sensitive help on the given node.
  1407. //
  1408. SC CComponent::ScOnContextHelp(LPDATAOBJECT lpDataObject)
  1409. {
  1410. SC sc = S_OK;
  1411. tstring strHelpTopic;
  1412. CComQIPtr<IDisplayHelp, &IID_IDisplayHelp> ipDisplayHelp;
  1413. LPOLESTR lpolestr = NULL;
  1414. CBaseSnapinItem *pitem = NULL;
  1415. USES_CONVERSION;
  1416. pitem = Pitem(lpDataObject);
  1417. ASSERT(pitem);
  1418. // Get the name of the compiled help file.
  1419. sc = Psnapin()->ScGetHelpTopic(strHelpTopic);
  1420. if (sc)
  1421. goto Error;
  1422. // Ask the item if it wants to handle this.
  1423. sc = pitem->ScOnContextHelp(strHelpTopic);
  1424. if (sc == S_FALSE)
  1425. {
  1426. // The item refused to handle the request. Default behavior
  1427. // is to append the name of the TOC
  1428. strHelpTopic += szHelpFileTOC;
  1429. sc = S_OK;
  1430. }
  1431. if (sc)
  1432. goto Error;
  1433. // Get an interface pointer to IDisplayHelp
  1434. ipDisplayHelp = IpConsole();
  1435. ASSERT(ipDisplayHelp);
  1436. // Allocate an LPOLESTR
  1437. lpolestr = T2OLE((LPTSTR)strHelpTopic.data());
  1438. // Call ShowTopic to bring up MMC help system.
  1439. // MMC will release the LPOLESTR.
  1440. // $REVIEW (ptousig) If MMC fails we don't know if it released the string or not.
  1441. // For now, I assume that they always do because I prefer to leak
  1442. // memory then to cause a GPF.
  1443. sc = ipDisplayHelp->ShowTopic(lpolestr);
  1444. if (sc)
  1445. goto Error;
  1446. Cleanup:
  1447. return sc;
  1448. Error:
  1449. TraceError(_T("CComponent::ScOnContextHelp"), sc);
  1450. goto Cleanup;
  1451. }
  1452. // -----------------------------------------------------------------------------
  1453. // Toolbar button clicked.
  1454. //
  1455. SC CComponent::ScOnButtonClick(LPDATAOBJECT lpDataObject, MMC_CONSOLE_VERB mcvVerb)
  1456. {
  1457. return S_OK;
  1458. }
  1459. // -----------------------------------------------------------------------------
  1460. // Adds the result view images to the imagelist.
  1461. //
  1462. SC CComponent::ScOnAddImages(LPDATAOBJECT lpDataObject, IImageList *ipImageList, HSCOPEITEM hscopeitem)
  1463. {
  1464. SC sc = S_OK;
  1465. CBaseSnapinItem *pitem = NULL;
  1466. pitem = Pitem(lpDataObject, hscopeitem);
  1467. ASSERT(pitem);
  1468. sc = pitem->ScOnAddImages(ipImageList);
  1469. if (sc)
  1470. goto Error;
  1471. Cleanup:
  1472. return sc;
  1473. Error:
  1474. TraceError(_T("CComponent::ScOnAddImages"), sc);
  1475. goto Cleanup;
  1476. }
  1477. // -----------------------------------------------------------------------------
  1478. // Called when the window of this view is activated. We don't care.
  1479. //
  1480. SC CComponent::ScOnActivate(LPDATAOBJECT lpDataObject, BOOL fActivate)
  1481. {
  1482. return S_OK;
  1483. }
  1484. // -----------------------------------------------------------------------------
  1485. // Adds property pages for the given data object, taking into account the context and also
  1486. // whether the data object is for a new object that is being created.
  1487. //
  1488. SC CComponent::ScCreatePropertyPages(LPPROPERTYSHEETCALLBACK ipPropertySheetCallback, long handle, LPDATAOBJECT lpDataObject)
  1489. {
  1490. // Declarations
  1491. SC sc = S_OK;
  1492. CBaseSnapinItem * pitem = NULL;
  1493. CBaseMultiSelectSnapinItem * pBaseMultiSelectSnapinItem = NULL;
  1494. // Data validation
  1495. ASSERT(lpDataObject);
  1496. ASSERT(ipPropertySheetCallback);
  1497. // Determine if this is a multiselect data object
  1498. sc = CBaseMultiSelectSnapinItem::ScGetMultiSelectDataObject(lpDataObject, &pBaseMultiSelectSnapinItem);
  1499. if (sc)
  1500. goto Error;
  1501. // If we received a multiselect snapin item
  1502. if (pBaseMultiSelectSnapinItem)
  1503. {
  1504. // Call ScCreatePropertyPages for the multiselect object
  1505. sc = pBaseMultiSelectSnapinItem->ScCreatePropertyPages(this, ipPropertySheetCallback, handle, lpDataObject);
  1506. if (sc)
  1507. goto Error;
  1508. }
  1509. else
  1510. {
  1511. // Handle the normal case - PItem() does more work than a simple cast to verify that the snapin item belongs to the snapin etc.
  1512. pitem = Pitem(lpDataObject); // get the correct CSnapinItem object.
  1513. ASSERT(pitem);
  1514. ASSERT(pitem->FIsSnapinManager() == FALSE);
  1515. // Simple version
  1516. sc = pitem->ScCreatePropertyPages(ipPropertySheetCallback);
  1517. if (sc)
  1518. goto Error;
  1519. // Complete version - for snapins that need all information (like Recipients)
  1520. sc = pitem->ScCreatePropertyPages(ipPropertySheetCallback, handle);
  1521. if (sc)
  1522. goto Error;
  1523. }
  1524. Cleanup:
  1525. return sc;
  1526. Error:
  1527. TraceError(_T("CComponent::ScCreatePropertyPages"), sc);
  1528. goto Cleanup;
  1529. }
  1530. // -----------------------------------------------------------------------------
  1531. // Saves per-view information. We don't have any.
  1532. //
  1533. SC CComponent::ScSave(IStream *pstream, BOOL fClearDirty)
  1534. {
  1535. return S_OK;
  1536. }
  1537. // -----------------------------------------------------------------------------
  1538. // Given a dataobject, determines whether or not pages exist.
  1539. // Actually, need to return S_OK here in both cases. If no pages exist
  1540. // it is CreatePropertyPages that should return S_FALSE. Sad but true.
  1541. //
  1542. SC CComponent::ScQueryPagesFor(LPDATAOBJECT lpDataObject)
  1543. {
  1544. // Declarations
  1545. SC sc = S_OK;
  1546. CBaseSnapinItem * pitem = NULL;
  1547. CBaseMultiSelectSnapinItem * pBaseMultiSelectSnapinItem = NULL;
  1548. // Data validation
  1549. ASSERT(lpDataObject);
  1550. // Determine if this is a multiselect data object
  1551. sc = CBaseMultiSelectSnapinItem::ScGetMultiSelectDataObject(lpDataObject, &pBaseMultiSelectSnapinItem);
  1552. if (sc)
  1553. goto Error;
  1554. // If we received a multiselect snapin item
  1555. if (pBaseMultiSelectSnapinItem)
  1556. {
  1557. // Call ScQueryPagesFor for the multiselect object
  1558. sc = pBaseMultiSelectSnapinItem->ScQueryPagesFor(this, lpDataObject);
  1559. if (sc)
  1560. goto Error;
  1561. }
  1562. else
  1563. {
  1564. // Handle the normal case - PItem() does more work than a simple cast to verify that the snapin item belongs to the snapin etc.
  1565. pitem = Pitem(lpDataObject);
  1566. ASSERT(pitem);
  1567. sc = pitem->ScQueryPagesFor();
  1568. if (sc)
  1569. goto Error;
  1570. }
  1571. Cleanup:
  1572. return sc;
  1573. Error:
  1574. TraceError(_T("CComponent::ScQueryPagesFor"), sc);
  1575. goto Cleanup;
  1576. }
  1577. //+-------------------------------------------------------------------
  1578. //
  1579. // Member: CComponent::ScOnInitOCX
  1580. //
  1581. // Synopsis: MMCN_INITOCX handler
  1582. //
  1583. // Arguments:
  1584. //
  1585. // Returns: SC
  1586. //
  1587. //--------------------------------------------------------------------
  1588. SC CComponent::ScOnInitOCX (LPDATAOBJECT lpDataObject, LPUNKNOWN lpOCXUnknown)
  1589. {
  1590. DECLARE_SC(sc, _T("CComponent::ScOnInitOCX"));
  1591. CBaseSnapinItem * pitem = NULL;
  1592. CBaseMultiSelectSnapinItem * pBaseMultiSelectSnapinItem = NULL;
  1593. sc = ScCheckPointers(Psnapin());
  1594. if(sc)
  1595. return E_NOINTERFACE;
  1596. // If snapin has IComponent2 then it created OCX and returned the IUnknown for
  1597. // the OCX using IComponent2::GetResultViewType2. Since it created, it also
  1598. // should initialize the OCX in which case MMC should not send MMCN_INITOCX.
  1599. // The below statement is just in case if MMC sends the notification.
  1600. if(Psnapin()->FSupportsIComponent2())
  1601. return sc;
  1602. // Data validation
  1603. ASSERT(lpDataObject);
  1604. // Determine if this is a multiselect data object
  1605. sc = CBaseMultiSelectSnapinItem::ScGetMultiSelectDataObject(lpDataObject, &pBaseMultiSelectSnapinItem);
  1606. if (sc)
  1607. return sc;
  1608. // If we received a multiselect snapin item
  1609. if (pBaseMultiSelectSnapinItem)
  1610. {
  1611. return (sc = E_UNEXPECTED);
  1612. }
  1613. else
  1614. {
  1615. // Handle the normal case - PItem() does more work than a simple cast to verify that the snapin item belongs to the snapin etc.
  1616. pitem = Pitem(lpDataObject);
  1617. ASSERT(pitem);
  1618. sc = pitem->ScInitOCX(lpOCXUnknown, IpConsole());
  1619. if (sc)
  1620. return sc;
  1621. }
  1622. return (sc);
  1623. }