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.

996 lines
35 KiB

  1. /*
  2. * ComponentData.cxx
  3. *
  4. *
  5. * Copyright (c) 1998-1999 Microsoft Corporation
  6. *
  7. * PURPOSE: Defines the CComponentData class.
  8. *
  9. *
  10. * OWNER: ptousig
  11. */
  12. #include "headers.hxx"
  13. // -----------------------------------------------------------------------------
  14. CComponentData::CComponentData(CBaseSnapin *psnapin)
  15. {
  16. Trace(tagBaseSnapinIComponentData, _T("--> CComponentData::CComponentData(psnapin=0x%08X)"), psnapin);
  17. ASSERT(psnapin);
  18. m_psnapin = psnapin;
  19. m_fIsRealComponentData = FALSE;
  20. m_pitemStandaloneRoot = NULL;
  21. Trace(tagBaseSnapinIComponentData, _T("<-- CComponentData::CComponentData has constructed 0x%08X"), this);
  22. }
  23. // -----------------------------------------------------------------------------
  24. // Destructor doesn't do anything, but it's useful to have one for debugging
  25. // purposes.
  26. //
  27. CComponentData::~CComponentData(void)
  28. {
  29. Trace(tagBaseSnapinIComponentData, _T("--> CComponentData::~CComponentData(), this=0x%08X"), this);
  30. Psnapin()->ScOwnerDying(this);
  31. if (m_pitemStandaloneRoot)
  32. {
  33. Psnapin()->ScReleaseIfRootItem(m_pitemStandaloneRoot);
  34. }
  35. Trace(tagBaseSnapinIComponentData, _T("<-- CComponentData::~CComponentData has destructed 0x%08X"), this);
  36. }
  37. // -----------------------------------------------------------------------------
  38. // This version of Pitem() is a shortcut, it forwards the call to the
  39. // CBaseSnapin with the correct CComponentData parameter.
  40. //
  41. CBaseSnapinItem *CComponentData::Pitem( LPDATAOBJECT lpDataObject,
  42. HSCOPEITEM hscopeitem,
  43. long cookie)
  44. {
  45. return Psnapin()->Pitem(this, NULL, lpDataObject, hscopeitem, cookie);
  46. }
  47. // -----------------------------------------------------------------------------
  48. // The registration routine expects to find this method on the CComponentData
  49. // but the real implementation is on the CBaseSnapin, so we just forward
  50. // the call.
  51. //
  52. SC CComponentData::ScRegister(BOOL fRegister)
  53. {
  54. CBaseSnapin* pSnapin = Psnapin();
  55. return pSnapin->ScRegister(fRegister);
  56. }
  57. // -----------------------------------------------------------------------------
  58. // Is called by the MMC to initialize the object. We QueryInterface
  59. // for pointers to the name space and console, which we cache in
  60. // local variables. This is called only once, when the user clicks on
  61. // the snapin.
  62. //
  63. // $REVIEW (ptousig) I am not sure which of interfaces we are allowed to QI
  64. // for from the parameter. The MMC docs are no help (as usual),
  65. //
  66. SC CComponentData::ScInitialize(LPUNKNOWN pUnknown)
  67. {
  68. SC sc = S_OK;
  69. IImageListPtr ipScopeImageList;
  70. ASSERT(pUnknown != NULL);
  71. ASSERT(m_ipConsoleNameSpace == NULL);
  72. m_fIsRealComponentData = TRUE;
  73. sc = Psnapin()->ScInitBitmaps();
  74. if (sc)
  75. goto Error;
  76. // These are CComQIPtr so they will call QueryInterface.
  77. m_ipConsoleNameSpace = pUnknown;
  78. m_ipConsole = pUnknown;
  79. m_ipResultData = pUnknown;
  80. m_ipPropertySheetProvider = pUnknown;
  81. // Get a pointer to the scope pane's IImageList.
  82. sc = m_ipConsole->QueryScopeImageList(&ipScopeImageList);
  83. if (sc)
  84. goto Error;
  85. // Set the icon strip for the scope pane.
  86. sc = ipScopeImageList->ImageListSetStrip(
  87. reinterpret_cast<long *>(static_cast<HBITMAP>(Psnapin()->BitmapSmall())),
  88. reinterpret_cast<long *>(static_cast<HBITMAP>(Psnapin()->BitmapLarge())),
  89. 0, RGB(255, 0, 255));
  90. if (sc)
  91. goto Error;
  92. Cleanup:
  93. return sc;
  94. Error:
  95. TraceError(_T("CComponentData::ScInitialize"), sc);
  96. goto Cleanup;
  97. }
  98. // -----------------------------------------------------------------------------
  99. // Handles component data event notification.
  100. // See MMC docs for the meaning of 'arg' and 'param'.
  101. //
  102. SC CComponentData::ScNotify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, long arg, long param)
  103. {
  104. SC sc = S_OK;
  105. switch (event)
  106. {
  107. case MMCN_BTN_CLICK:
  108. sc = ScOnButtonClick(lpDataObject, (MMC_CONSOLE_VERB) param);
  109. break;
  110. case MMCN_DELETE:
  111. sc = ScOnDelete(lpDataObject);
  112. break;
  113. case MMCN_RENAME:
  114. sc = Psnapin()->ScOnRename(lpDataObject, reinterpret_cast<LPCTSTR>(param), IpConsole());
  115. break;
  116. case MMCN_EXPAND:
  117. sc = ScOnExpand(lpDataObject, arg != FALSE, param);
  118. break;
  119. case MMCN_EXPANDSYNC:
  120. sc = ScOnExpandSync(lpDataObject, reinterpret_cast<MMC_EXPANDSYNC_STRUCT *>(param));
  121. break;
  122. case MMCN_PROPERTY_CHANGE:
  123. sc = Psnapin()->ScOnPropertyChange(arg != FALSE, param, IpConsoleNameSpace(), IpConsole());
  124. break;
  125. case MMCN_REMOVE_CHILDREN:
  126. sc = ScOnRemoveChildren(lpDataObject, arg);
  127. break;
  128. default:
  129. sc = S_FALSE;
  130. ASSERT(_T("CComponentData::ScNotify: unimplemented event %x"));
  131. break;
  132. }
  133. if (sc)
  134. goto Error;
  135. Cleanup:
  136. return sc;
  137. Error:
  138. TraceError(_T("CComponentData::ScNotify"), sc);
  139. goto Cleanup;
  140. }
  141. // -----------------------------------------------------------------------------
  142. // Releases all interfaces.
  143. //
  144. SC CComponentData::ScDestroy(void)
  145. {
  146. m_ipConsole.Release();
  147. m_ipConsoleNameSpace.Release();
  148. m_ipResultData.Release();
  149. m_ipPropertySheetProvider.Release();
  150. return S_OK;
  151. }
  152. /*+-------------------------------------------------------------------------*
  153. *
  154. * CComponentData::ScQueryDispatch
  155. *
  156. * PURPOSE: Dummy implementation. Does nothing.
  157. *
  158. * PARAMETERS:
  159. * MMC_COOKIE cookie :
  160. * DATA_OBJECT_TYPES type :
  161. * LPDISPATCH* ppDispatch :
  162. *
  163. * RETURNS:
  164. * SC
  165. *
  166. *+-------------------------------------------------------------------------*/
  167. SC
  168. CComponentData::ScQueryDispatch(MMC_COOKIE cookie, DATA_OBJECT_TYPES type, LPDISPATCH* ppDispatch)
  169. {
  170. DECLARE_SC(sc, TEXT("CComponentData::ScQueryDispatch"));
  171. CBaseSnapinItem *pitem = NULL;
  172. // The component data can handle cookie types of CCT_SNAPIN_MANAGER and CCT_SCOPE.
  173. // CCT_RESULT are handled by CComponent.
  174. ASSERT(type==CCT_SCOPE);
  175. //
  176. // If the cookie does not correspond to a known object, return E_UNEXPECTED.
  177. // This is correct and is also a workaround for an MMC bug. See X5:74405.
  178. //
  179. if (cookie && (Psnapin()->Pcookielist()->find(cookie) == Psnapin()->Pcookielist()->end() ) )
  180. {
  181. sc = E_UNEXPECTED;
  182. return sc;
  183. }
  184. pitem = Pitem(NULL, 0, cookie);
  185. ASSERT(pitem);
  186. sc = pitem->ScQueryDispatch(cookie, type, ppDispatch);
  187. if (sc)
  188. return sc;
  189. return sc;
  190. }
  191. // -----------------------------------------------------------------------------
  192. // Load information from the first root item.
  193. //
  194. // $REVIEW (ptousig) Why does the root item implement ScLoad() ?
  195. // If a snapin extends two nodes it has two root items, yet
  196. // only one of which will be saved/loaded.
  197. //
  198. SC CComponentData::ScLoad(IStream *pstream)
  199. {
  200. SC sc = S_OK;
  201. // Load the snapin's serialized information.
  202. sc = Psnapin()->ScLoad(pstream);
  203. if (sc)
  204. goto Error;
  205. // Load the root item's serialized information.
  206. // Only makes sense for standalone snapins.
  207. sc = Pitem()->ScLoad(pstream);
  208. if (sc)
  209. goto Error;
  210. Cleanup:
  211. return sc;
  212. Error:
  213. TraceError(_T("CComponentData::ScLoad"), sc);
  214. goto Cleanup;
  215. }
  216. // -----------------------------------------------------------------------------
  217. // Determines whether any settings have changed since the last time the file
  218. // was saved.
  219. //
  220. // $REVIEW (ptousig) We are never dirty !!! Shouldn't we ask the Pitem() ?
  221. //
  222. SC CComponentData::ScIsDirty(void)
  223. {
  224. return S_FALSE;
  225. }
  226. // -----------------------------------------------------------------------------
  227. // If one of the commands added to the context menu is
  228. // subsequently selected, MMC calls Command.
  229. //
  230. // Even though this method "looks" like the one in CComponent,
  231. // the use of the Pitem() shortcut makes them different. This
  232. // version does not pass a component to the real Pitem().
  233. //
  234. SC CComponentData::ScCommand(long nCommandID, LPDATAOBJECT pDataObject)
  235. {
  236. SC sc = S_OK;
  237. CBaseSnapinItem *pitem = NULL;
  238. pitem = Pitem(pDataObject);
  239. ASSERT(pitem);
  240. sc = pitem->ScCommand(nCommandID);
  241. if (sc)
  242. goto Error;
  243. Cleanup:
  244. return sc;
  245. Error:
  246. TraceError(_T("CComponentData::ScCommand"), sc);
  247. goto Cleanup;
  248. }
  249. // -----------------------------------------------------------------------------
  250. // Gets display information for a scope pane item
  251. // Warning: This is called very very often (on WM_PAINT) so it is important
  252. // we don't take any high latency actions (ie Network or Disk access).
  253. //
  254. SC CComponentData::ScGetDisplayInfo(LPSCOPEDATAITEM pScopeItem)
  255. {
  256. SC sc = S_OK;
  257. CBaseSnapinItem *pitem = NULL;
  258. pitem = Pitem(NULL, 0, pScopeItem->lParam);
  259. ASSERT(pitem);
  260. sc = pitem->ScGetDisplayInfo(pScopeItem);
  261. if (sc)
  262. goto Error;
  263. Cleanup:
  264. return sc;
  265. Error:
  266. TraceError(_T("CComponentData::ScGetDisplayInfo"), sc);
  267. goto Cleanup;
  268. }
  269. // -----------------------------------------------------------------------------
  270. HRESULT CComponentData::CompareObjects(LPDATAOBJECT lpDataObjectA, LPDATAOBJECT lpDataObjectB)
  271. {
  272. DECLARE_SC(sc,_T("CComponentData::CompareObjects"));
  273. Trace(tagBaseSnapinIComponentData, _T("--> %s::IComponentData::CompareObjects(lpDataObjectA=0x%08X, lpDataObjectB=0x%08X), this=0x%08X"), StrSnapinClassName(), lpDataObjectA, lpDataObjectB, this);
  274. ADMIN_TRY;
  275. sc=Psnapin()->ScCompareObjects(lpDataObjectA, lpDataObjectB);
  276. ADMIN_CATCH_HR
  277. Trace(tagBaseSnapinIComponentData, _T("<-- %s::IComponentData::CompareObjects is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  278. return(sc.ToHr());
  279. }
  280. // -----------------------------------------------------------------------------
  281. HRESULT CComponentData::GetDisplayInfo(LPSCOPEDATAITEM pItem)
  282. {
  283. DECLARE_SC(sc,_T("CComponentData::GetDisplayInfo"));
  284. Trace(tagBaseSnapinIComponentDataGetDisplayInfo, _T("--> %s::IComponentData::GetDisplayInfo(cookie=0x%08X), this=0x%08X"), StrSnapinClassName(), pItem->lParam, this);
  285. ADMIN_TRY;
  286. sc=ScGetDisplayInfo(pItem);
  287. ADMIN_CATCH_HR
  288. Trace(tagBaseSnapinIComponentDataGetDisplayInfo, _T("<-- %s::IComponentData::GetDisplayInfo is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  289. return(sc.ToHr());
  290. }
  291. // -----------------------------------------------------------------------------
  292. HRESULT CComponentData::QueryDataObject(long cookie, DATA_OBJECT_TYPES type, LPDATAOBJECT * ppDataObject)
  293. {
  294. DECLARE_SC(sc,_T("CComponentData::QueryDataObject"));
  295. Trace(tagBaseSnapinIComponentDataQueryDataObject, _T("--> %s::IComponentData::QueryDataObject(cookie=0x%08X, type=%s), this=0x%08X"), StrSnapinClassName(), cookie, SzGetDebugNameOfDATA_OBJECT_TYPES(type), this);
  296. ADMIN_TRY;
  297. //
  298. // If we receive E_UNEXPECTED we don't want to call MMCHrFromSc because
  299. // that will bring up an error message. We don't want an error message
  300. // in this case because of a known MMC bug (see bug X5:74405).
  301. // The bug says that we might receive QueryDataObject on items that
  302. // we were told no longer exists (by MMCN_REMOVE_CHILDREN).
  303. //
  304. sc = ScQueryDataObject(cookie, type, ppDataObject);
  305. ADMIN_CATCH_HR
  306. Trace(tagBaseSnapinIComponentDataQueryDataObject, _T("<-- %s::IComponentData::QueryDataObject is returning hr=%s, *ppDataObject=0x%08X"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()), *ppDataObject);
  307. return(sc.ToHr());
  308. }
  309. // -----------------------------------------------------------------------------
  310. HRESULT CComponentData::Notify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, long arg, long param)
  311. {
  312. DECLARE_SC(sc,_T("CComponentData::Notify"));
  313. Trace(tagBaseSnapinIComponentData, _T("--> %s::IComponentData::Notify(lpDataObject=0x%08X, event=%s, arg=0x%08X, param=0x%08X), this=0x%08X"), StrSnapinClassName(), lpDataObject, SzGetDebugNameOfMMC_NOTIFY_TYPE(event), arg, param, this);
  314. ADMIN_TRY;
  315. sc=ScNotify(lpDataObject, event, arg, param);
  316. ADMIN_CATCH_HR
  317. Trace(tagBaseSnapinIComponentData, _T("<-- %s::IComponentData::Notify is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  318. return(sc.ToHr());
  319. }
  320. // -----------------------------------------------------------------------------
  321. HRESULT CComponentData::CreateComponent(LPCOMPONENT * ppComponent)
  322. {
  323. DECLARE_SC(sc,_T("CComponentData::CreateComponent"));
  324. Trace(tagBaseSnapinIComponentData, _T("--> %s::IComponentData::CreateComponent(...), this=0x%08X"), StrSnapinClassName(), this);
  325. ADMIN_TRY;
  326. sc=ScCreateComponent(ppComponent);
  327. ADMIN_CATCH_HR
  328. Trace(tagBaseSnapinIComponentData, _T("<-- %s::IComponentData::CreateComponent is returning hr=%s, *ppComponent=0x%08X"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()), *ppComponent);
  329. return(sc.ToHr());
  330. }
  331. // -----------------------------------------------------------------------------
  332. HRESULT CComponentData::Initialize(LPUNKNOWN pUnknown)
  333. {
  334. DECLARE_SC(sc,_T("CComponentData::Initialize"));
  335. Trace(tagBaseSnapinIComponentData, _T("--> %s::IComponentData::Initialize(pUnknown=0x%08X), this=0x%08X"), StrSnapinClassName(), pUnknown, this);
  336. ADMIN_TRY;
  337. sc=ScInitialize(pUnknown);
  338. ADMIN_CATCH_HR
  339. Trace(tagBaseSnapinIComponentData, _T("<-- %s::IComponentData::Initialize is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  340. return(sc.ToHr());
  341. }
  342. // -----------------------------------------------------------------------------
  343. HRESULT CComponentData::Destroy(void)
  344. {
  345. DECLARE_SC(sc,_T("CComponentData::Destroy"));
  346. Trace(tagBaseSnapinIComponentData, _T("--> %s::IComponentData::Destroy(), , this=0x%08X"), StrSnapinClassName(), this);
  347. ADMIN_TRY;
  348. sc=ScDestroy();
  349. ADMIN_CATCH_HR
  350. Trace(tagBaseSnapinIComponentData, _T("<-- %s::IComponentData::Destroy is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  351. return(sc.ToHr());
  352. }
  353. // -----------------------------------------------------------------------------
  354. HRESULT CComponentData::QueryDispatch(MMC_COOKIE cookie, DATA_OBJECT_TYPES type, LPDISPATCH* ppDispatch)
  355. {
  356. DECLARE_SC(sc,_T("CComponentData::QueryDispatch"));
  357. Trace(tagBaseSnapinIComponentData, _T("--> %s::IComponentData::QueryDispatch(), , this=0x%08X"), StrSnapinClassName(), this);
  358. ADMIN_TRY;
  359. sc=ScQueryDispatch(cookie, type, ppDispatch);
  360. ADMIN_CATCH_HR
  361. Trace(tagBaseSnapinIComponentData, _T("<-- %s::IComponentData::QueryDispatch is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  362. return(sc.ToHr());
  363. }
  364. // -----------------------------------------------------------------------------
  365. HRESULT CComponentData::AddMenuItems(LPDATAOBJECT pDataObject, LPCONTEXTMENUCALLBACK ipContextMenuCallback, long *pInsertionAllowed)
  366. {
  367. DECLARE_SC(sc,_T("CComponentData::AddMenuItems"));
  368. Trace(tagBaseSnapinIExtendContextMenu, _T("--> %s::IExtendContextMenu::AddMenuItems(pDataObject=0x%08X), this=0x%08X"), StrSnapinClassName(), pDataObject, this);
  369. ADMIN_TRY;
  370. // By calling Pitem() at this time, we will force the creation of the ghost
  371. // root node, if necessary.
  372. Pitem(pDataObject);
  373. sc=Psnapin()->ScAddMenuItems(pDataObject, ipContextMenuCallback, pInsertionAllowed);
  374. ADMIN_CATCH_HR
  375. Trace(tagBaseSnapinIExtendContextMenu, _T("<-- %s::IExtendContextMenu::AddMenuItems is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  376. return(sc.ToHr());
  377. }
  378. // -----------------------------------------------------------------------------
  379. HRESULT CComponentData::Command(long nCommandID, LPDATAOBJECT pDataObject)
  380. {
  381. DECLARE_SC(sc,_T("CComponentData::Command"));
  382. Trace(tagBaseSnapinIExtendContextMenu, _T("--> %s::IExtendContextMenu::Command(nCommandID=%ld, pDataObject=0x%08X), this=0x%08X"), StrSnapinClassName(), nCommandID, pDataObject, this);
  383. ADMIN_TRY;
  384. sc=ScCommand(nCommandID, pDataObject);
  385. ADMIN_CATCH_HR
  386. Trace(tagBaseSnapinIExtendContextMenu, _T("<-- %s::IExtendContextMenu::Command is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  387. return(sc.ToHr());
  388. }
  389. // -----------------------------------------------------------------------------
  390. HRESULT CComponentData::CreatePropertyPages(LPPROPERTYSHEETCALLBACK lpProvider, long handle, LPDATAOBJECT lpDataObject)
  391. {
  392. DECLARE_SC(sc,_T("CComponentData::CreatePropertyPages"));
  393. Trace(tagBaseSnapinIExtendPropertySheet, _T("--> %s::IExtendPropertySheet::CreatePropertyPages(lpDataObject=0x%08X), this=0x%08X"), StrSnapinClassName(), lpDataObject, this);
  394. ADMIN_TRY;
  395. // Why are we ignoring E_UNEXPECTED ?
  396. // Because when we are called by the snapin manager, and the user hits cancel we
  397. // need to return E_UNEXPECTED to MMC.
  398. sc = ScCreatePropertyPages(lpProvider, handle, lpDataObject);
  399. ADMIN_CATCH_HR
  400. Trace(tagBaseSnapinIExtendPropertySheet, _T("<-- %s::IExtendPropertySheet::CreatePropertyPages is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  401. return(sc.ToHr());
  402. }
  403. // -----------------------------------------------------------------------------
  404. HRESULT CComponentData::QueryPagesFor(LPDATAOBJECT lpDataObject)
  405. {
  406. DECLARE_SC(sc,_T("CComponentData::QueryPagesFor"));
  407. Trace(tagBaseSnapinIExtendPropertySheet, _T("--> %s::IExtendPropertySheet::QueryPagesFor(lpDataObject=0x%08X), this=0x%08X"), StrSnapinClassName(), lpDataObject, this);
  408. ADMIN_TRY;
  409. sc=ScQueryPagesFor(lpDataObject);
  410. ADMIN_CATCH_HR
  411. Trace(tagBaseSnapinIExtendPropertySheet, _T("<-- %s::IExtendPropertySheet::QueryPagesFor is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  412. return(sc.ToHr());
  413. }
  414. // -----------------------------------------------------------------------------
  415. HRESULT CComponentData::GetSizeMax(ULARGE_INTEGER *pcbSize)
  416. {
  417. DECLARE_SC(sc,_T("CComponentData::GetSizeMax"));
  418. Trace(tagBaseSnapinIPersistStreamInit, _T("--> %s::IPersistStreamInit::GetSizeMax(...), , this=0x%08X"), StrSnapinClassName(), this);
  419. ADMIN_TRY;
  420. pcbSize->LowPart = cMaxStreamSizeLow;
  421. pcbSize->HighPart = cMaxStreamSizeHigh;
  422. ADMIN_CATCH_HR
  423. Trace(tagBaseSnapinIPersistStreamInit, _T("<-- %s::IPersistStreamInit::GetSizeMax is returning hr=%s, (*pcbSize).LowPart=%d"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()), (*pcbSize).LowPart);
  424. return(sc.ToHr());
  425. }
  426. // -----------------------------------------------------------------------------
  427. HRESULT CComponentData::IsDirty(void)
  428. {
  429. DECLARE_SC(sc,_T("CComponentData::IsDirty"));
  430. Trace(tagBaseSnapinIPersistStreamInit, _T("--> %s::IPersistStreamInit::IsDirty(), this=0x%08X"), StrSnapinClassName(), this);
  431. ADMIN_TRY;
  432. sc=ScIsDirty();
  433. ADMIN_CATCH_HR
  434. Trace(tagBaseSnapinIPersistStreamInit, _T("<-- %s::IPersistStreamInit::IsDirty is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  435. return(sc.ToHr());
  436. }
  437. // -----------------------------------------------------------------------------
  438. HRESULT CComponentData::Load(IStream *pstream)
  439. {
  440. DECLARE_SC(sc,_T("CComponentData::Load"));
  441. Trace(tagBaseSnapinIPersistStreamInit, _T("--> %s::IPersistStreamInit::Load(...), this=0x%08X"), StrSnapinClassName(), this);
  442. ADMIN_TRY;
  443. sc=ScLoad(pstream);
  444. ADMIN_CATCH_HR
  445. Trace(tagBaseSnapinIPersistStreamInit, _T("<-- %s::IPersistStreamInit::Load is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  446. return(sc.ToHr());
  447. }
  448. // -----------------------------------------------------------------------------
  449. HRESULT CComponentData::Save(IStream *pstream, BOOL fClearDirty)
  450. {
  451. DECLARE_SC(sc,_T("CComponentData::Save"));
  452. Trace(tagBaseSnapinIPersistStreamInit, _T("--> %s::IPersistStreamInit::Save(fClearDirty=%S), this=0x%08X"), StrSnapinClassName(), fClearDirty ? "TRUE" : "FALSE", this);
  453. ADMIN_TRY;
  454. sc=ScSave(pstream, fClearDirty);
  455. ADMIN_CATCH_HR
  456. Trace(tagBaseSnapinIPersistStreamInit, _T("<-- %s::IPersistStreamInit::Save is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  457. return(sc.ToHr());
  458. }
  459. // -----------------------------------------------------------------------------
  460. HRESULT CComponentData::InitNew(void)
  461. {
  462. DECLARE_SC(sc,_T("CComponentData::InitNew"));
  463. // We don't have anything to do, but we still want to log the call.
  464. Trace(tagBaseSnapinIPersistStreamInit, _T("--> %s::IPersistStreamInit::InitNew(), this=0x%08X"), StrSnapinClassName(), this);
  465. Trace(tagBaseSnapinIPersistStreamInit, _T("<-- %s::IPersistStreamInit::InitNew is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  466. return(sc.ToHr());
  467. }
  468. // -----------------------------------------------------------------------------
  469. HRESULT CComponentData::GetClassID(CLSID *pclsid)
  470. {
  471. DECLARE_SC(sc,_T("CComponentData::GetClassID"));
  472. Trace(tagBaseSnapinIPersistStreamInit, _T("--> %s::IPersistStreamInit::GetClassID(...), this=0x%08X"), StrSnapinClassName(), this);
  473. ADMIN_TRY;
  474. *pclsid = *(Psnapin()->PclsidSnapin());
  475. ADMIN_CATCH_HR
  476. Trace(tagBaseSnapinIPersistStreamInit, _T("<-- %s::IPersistStreamInit::GetClassID is returning hr=%s"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()));
  477. return(sc.ToHr());
  478. }
  479. // -----------------------------------------------------------------------------
  480. HRESULT CComponentData::Compare(RDCOMPARE * prdc, int * pnResult)
  481. {
  482. DECLARE_SC(sc,_T("CComponentData::Compare"));
  483. Trace(tagBaseSnapinIResultDataCompare, _T("--> %s::IResultDataCompare::Compare(cookieA=0x%08X, cookieB=0x%08X), this=0x%08X"), StrSnapinClassName(), prdc->prdch1->cookie, prdc->prdch2->cookie, this);
  484. ADMIN_TRY;
  485. ASSERT(pnResult);
  486. ASSERT(prdc);
  487. ASSERT(prdc->prdch1);
  488. ASSERT(prdc->prdch2);
  489. sc=Psnapin()->ScCompare(prdc->prdch1->cookie, prdc->prdch2->cookie, prdc->nColumn, pnResult);
  490. ADMIN_CATCH_HR
  491. Trace(tagBaseSnapinIResultDataCompare, _T("<-- %s::IResultDataCompare::Compare is returning hr=%s, *pnResult=%d"), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()), *pnResult);
  492. return(sc.ToHr());
  493. }
  494. // -----------------------------------------------------------------------------
  495. // Returns the full path of the compiled file (.chm) for the snapin.
  496. //
  497. HRESULT CComponentData::GetHelpTopic(LPOLESTR *lpCompiledHelpFile)
  498. {
  499. DECLARE_SC(sc,_T("CComponentData::GetHelpTopic"));
  500. tstring strCompiledHelpFile;
  501. USES_CONVERSION;
  502. Trace(tagBaseSnapinISnapinHelp, _T("--> %s::ISnapinHelp::GetHelpTopic(...), this=0x%08X"), StrSnapinClassName(), this);
  503. ADMIN_TRY;
  504. if (lpCompiledHelpFile == NULL)
  505. {
  506. sc = E_POINTER;
  507. goto Error;
  508. }
  509. // Automatically displays an error box.
  510. sc = Psnapin()->ScGetHelpTopic(strCompiledHelpFile);
  511. if (sc)
  512. goto Error;
  513. if (strCompiledHelpFile.empty())
  514. {
  515. sc=S_FALSE;
  516. }
  517. else
  518. {
  519. *lpCompiledHelpFile = reinterpret_cast<LPOLESTR>(CoTaskMemAlloc( (strCompiledHelpFile.length()+1)*sizeof(TCHAR)) );
  520. sc = ScCheckPointers(*lpCompiledHelpFile, E_OUTOFMEMORY);
  521. if (sc)
  522. goto Error;
  523. wcscpy(*lpCompiledHelpFile, T2CW(strCompiledHelpFile.data()) );
  524. }
  525. if (sc)
  526. goto Error; // an exception was caught
  527. Cleanup:
  528. Trace(tagBaseSnapinISnapinHelp, _T("<-- %s::ISnapinHelp::GetHelpTopic is returning hr=%s, lpCompiledHelpFile=\"%s\""), StrSnapinClassName(), SzGetDebugNameOfHr(sc.ToHr()), strCompiledHelpFile.data());
  529. return(sc.ToHr());
  530. Error:
  531. TraceError(_T("CComponentData::GetHelpTopic"), sc);
  532. goto Cleanup;
  533. }
  534. // -----------------------------------------------------------------------------
  535. // Creates a data object of the appropriate type, and returns the IDataObject interface
  536. // on it
  537. //
  538. SC CComponentData::ScQueryDataObject(long cookie, DATA_OBJECT_TYPES type, LPDATAOBJECT* ppDataObject)
  539. {
  540. SC sc = S_OK;
  541. CBaseSnapinItem *pitem = NULL;
  542. // The component data can handle cookie types of CCT_SNAPIN_MANAGER and CCT_SCOPE.
  543. // CCT_RESULT are handled by CComponent.
  544. ASSERT(type==CCT_SNAPIN_MANAGER || type==CCT_SCOPE);
  545. //
  546. // If the cookie does not correspond to a known object, return E_UNEXPECTED.
  547. // This is correct and is also a workaround for an MMC bug. See X5:74405.
  548. //
  549. if (cookie && (Psnapin()->Pcookielist()->find(cookie) == Psnapin()->Pcookielist()->end() ) )
  550. {
  551. sc = E_UNEXPECTED;
  552. goto Cleanup;
  553. }
  554. pitem = Pitem(NULL, 0, cookie);
  555. ASSERT(pitem);
  556. sc = pitem->ScQueryDataObject(cookie, type, ppDataObject);
  557. if (sc)
  558. goto Error;
  559. Cleanup:
  560. return sc;
  561. Error:
  562. TraceError(_T("CComponentData::ScQueryDataObject"), sc);
  563. goto Cleanup;
  564. }
  565. // -----------------------------------------------------------------------------
  566. // Handles the MMCN_EXPAND notification sent to IComponentData::Notify
  567. //
  568. SC CComponentData::ScOnExpand(LPDATAOBJECT lpDataObject, BOOL fExpand, HSCOPEITEM hscopeitem)
  569. {
  570. SC sc = S_OK;
  571. CBaseSnapinItem *pitem = NULL;
  572. if (fExpand == FALSE) // do nothing on a "contract"
  573. goto Cleanup;
  574. pitem = Pitem(lpDataObject, hscopeitem);
  575. ASSERT(pitem);
  576. // Use this opportunity to correlate the CSnapinItem and the HSCOPEITEM.
  577. // $REVIEW (ptousig) Should be done inside Pitem().
  578. pitem->SetHscopeitem(hscopeitem);
  579. pitem->SetComponentData(this);
  580. if (pitem->PitemChild())
  581. {
  582. // We have a list of partial children. We need to remove
  583. // them because we are going to ask the snapin to enumerate
  584. // all of it's children. Do not get rid of this node.
  585. // This can happen if a node creates new children before it is
  586. // expanded.
  587. //
  588. // $REVIEW (ptousig) Creating a child when the parent is not expanded
  589. // should simply not add the child.
  590. //
  591. sc = pitem->ScDeleteSubTree(FALSE);
  592. if (sc)
  593. goto Error;
  594. }
  595. // If we're creating the children, make sure there aren't any around.
  596. ASSERT(pitem->PitemChild() == NULL);
  597. sc = pitem->ScCreateChildren();
  598. if (sc)
  599. goto Error;
  600. if (pitem->PitemChild())
  601. {
  602. // Add or remove children to/from the console.
  603. sc = pitem->PitemChild()->ScInsertScopeItem(this, fExpand, hscopeitem);
  604. if (sc)
  605. goto Error;
  606. }
  607. pitem->SetWasExpanded(TRUE);
  608. Cleanup:
  609. return sc;
  610. Error:
  611. TraceError(_T("CComponentData::ScOnExpand"), sc);
  612. goto Cleanup;
  613. }
  614. // -----------------------------------------------------------------------------
  615. // Called by the MMC to delete the cookies for the entire subtree under a node. This
  616. // is only to clean up allocated objects. Do NOT call IConsoleNameSpace::DeleteItem.
  617. //
  618. SC CComponentData::ScOnRemoveChildren(LPDATAOBJECT lpDataObject, HSCOPEITEM hscopeitem)
  619. {
  620. SC sc = S_OK;
  621. CBaseSnapinItem *pitem = NULL;
  622. pitem = Pitem(lpDataObject, hscopeitem);
  623. ASSERT(pitem);
  624. // Get rid of the children.
  625. sc = pitem->ScDeleteSubTree(FALSE);
  626. if (sc)
  627. goto Error;
  628. // Release the given node if it is one of the root nodes
  629. sc = Psnapin()->ScReleaseIfRootItem(pitem);
  630. if (sc)
  631. goto Error;
  632. Cleanup:
  633. return sc;
  634. Error:
  635. TraceError(_T("CComponentData::ScOnRemoveChildren"), sc);
  636. goto Cleanup;
  637. }
  638. // -----------------------------------------------------------------------------
  639. // Allows a snapin to control whether it will populate the scope pane
  640. // in the background or not.
  641. //
  642. SC CComponentData::ScOnExpandSync(LPDATAOBJECT lpDataObject, MMC_EXPANDSYNC_STRUCT *pmes)
  643. {
  644. // We don't care.
  645. return S_OK;
  646. }
  647. // -----------------------------------------------------------------------------
  648. // The user has asked to delete this node.
  649. //
  650. SC CComponentData::ScOnDelete(LPDATAOBJECT pDataObject)
  651. {
  652. SC sc = S_OK;
  653. CBaseSnapinItem *pitem = NULL;
  654. BOOL fDeleted = FALSE;
  655. BOOL fPagesUp = FALSE;
  656. tstring strMsg;
  657. pitem = Pitem(pDataObject);
  658. ASSERT(pitem);
  659. // The ComponentData should only receive notifications for scope pane items.
  660. ASSERT(pitem->FIsContainer());
  661. sc = pitem->ScIsPropertySheetOpen(&fPagesUp);
  662. if (sc)
  663. goto Error;
  664. if (fPagesUp)
  665. {
  666. ASSERT(FALSE && "Add below resource");
  667. //strMsg.LoadString(_Module.GetResourceInstance(), idsPropsUpNoDelete);
  668. strMsg += (*pitem->PstrDisplayName());
  669. MMCErrorBox(strMsg.data());
  670. goto Cleanup;
  671. }
  672. // Ask the item to delete the underlying object.
  673. sc = pitem->ScOnDelete(&fDeleted);
  674. if (sc)
  675. goto Error;
  676. if (fDeleted == FALSE)
  677. // The item did not want to be deleted.
  678. goto Cleanup;
  679. // Container items need to be deleted from the document
  680. // Delete the item and everything below it.
  681. sc = IpConsoleNameSpace()->DeleteItem(pitem->Hscopeitem(), TRUE);
  682. if (sc)
  683. goto Error;
  684. pitem->SetHscopeitem(0);
  685. // At this point, the item exists only in the tree, if at all.
  686. // Remove it from the tree.
  687. pitem->Unlink();
  688. // Get rid of it for good from the tree of items.
  689. pitem->Pdataobject()->Release();
  690. Cleanup:
  691. return sc;
  692. Error:
  693. TraceError(_T("CComponentData::ScOnDelete"), sc);
  694. goto Cleanup;
  695. }
  696. // -----------------------------------------------------------------------------
  697. // Toolbar button clicked.
  698. //
  699. SC CComponentData::ScOnButtonClick(LPDATAOBJECT lpDataObject, MMC_CONSOLE_VERB mcvVerb)
  700. {
  701. return S_OK;
  702. }
  703. // -----------------------------------------------------------------------------
  704. // Used to insert a new item into the tree of items, and, if the item is a container,
  705. // into the namespace as well. The tree and the namespace are document, not view,
  706. // concept. This insertion is done only once.
  707. //
  708. SC CComponentData::ScOnDocumentChangeInsertItem(CBaseSnapinItem *pitemNew)
  709. {
  710. SC sc = S_OK;
  711. CBaseSnapinItem * pitemParent = NULL;
  712. ASSERT(pitemNew);
  713. // Insert exactly once.
  714. if (pitemNew->FInserted())
  715. goto Cleanup;
  716. // The parent should have already been filled in
  717. pitemParent = pitemNew->PitemParent();
  718. ASSERT(pitemParent);
  719. if (pitemParent->FIncludesChild(pitemNew) == FALSE)
  720. {
  721. sc = pitemParent->ScAddChild(pitemNew);
  722. if (sc)
  723. goto Error;
  724. }
  725. if (pitemNew->FIsContainer())
  726. {
  727. if (pitemParent->FWasExpanded())
  728. {
  729. sc = pitemNew->ScInsertScopeItem(this, TRUE, pitemParent->Hscopeitem());
  730. if (sc)
  731. goto Error;
  732. }
  733. }
  734. // Only insert the item once.
  735. pitemNew->SetInserted(TRUE);
  736. Cleanup:
  737. return sc;
  738. Error:
  739. TraceError(_T("CComponentData::ScOnDocumentChangeInsertItem"), sc);
  740. goto Cleanup;
  741. }
  742. // -----------------------------------------------------------------------------
  743. // Tests whether the given item has already enumerated its children.
  744. //
  745. SC CComponentData::ScWasExpandedOnce(CBaseSnapinItem *pitem, BOOL *pfWasExpanded)
  746. {
  747. SC sc = S_OK;
  748. SCOPEDATAITEM sdi;
  749. if (pitem->Hscopeitem() == 0)
  750. {
  751. //
  752. // If we don't have an HSCOPEITEM then we are not displayed in
  753. // the scope pane, therefore we have never been expanded (and
  754. // probably never will).
  755. //
  756. *pfWasExpanded = FALSE;
  757. goto Cleanup;
  758. }
  759. //
  760. // Ask for the state member of SCOPEDATAITEM
  761. //
  762. ::ZeroMemory(&sdi, sizeof(SCOPEDATAITEM));
  763. sdi.mask = SDI_STATE;
  764. sdi.ID = pitem->Hscopeitem();
  765. sc = IpConsoleNameSpace()->GetItem(&sdi);
  766. if (sc)
  767. goto Error;
  768. //
  769. // If the MMC_SCOPE_ITEM_STATE_EXPANDEDONCE is on it means we have
  770. // been asked to expand ourselves at least once before.
  771. //
  772. *pfWasExpanded = (sdi.nState & MMC_SCOPE_ITEM_STATE_EXPANDEDONCE) != 0;
  773. Cleanup:
  774. return sc;
  775. Error:
  776. TraceError(_T("CComponentData::ScWasExpandedOnce"), sc);
  777. goto Cleanup;
  778. }
  779. // -----------------------------------------------------------------------------
  780. // Adds property pages for the given data object, taking into account the context and also
  781. // whether the data object is for a new object that is being created.
  782. //
  783. SC CComponentData::ScCreatePropertyPages(LPPROPERTYSHEETCALLBACK ipPropertySheetCallback, long handle, LPDATAOBJECT pDataObject)
  784. {
  785. SC sc = S_OK;
  786. CBaseSnapinItem *pitem = NULL;
  787. pitem = Pitem(pDataObject);
  788. ASSERT(pitem);
  789. if (pitem->FIsSnapinManager())
  790. {
  791. sc = pitem->ScCreateSnapinMgrPropertyPages(ipPropertySheetCallback);
  792. if (sc)
  793. goto Error;
  794. }
  795. else
  796. {
  797. // Simple version
  798. sc = pitem->ScCreatePropertyPages(ipPropertySheetCallback);
  799. if (sc)
  800. goto Error;
  801. // Complete version - for snapins that need all information (like Recipients)
  802. sc = pitem->ScCreatePropertyPages(ipPropertySheetCallback, handle);
  803. if (sc)
  804. goto Error;
  805. }
  806. Cleanup:
  807. return sc;
  808. Error:
  809. TraceError(_T("CComponentData::ScCreatePropertyPages"), sc);
  810. goto Cleanup;
  811. }
  812. // -----------------------------------------------------------------------------
  813. // Save information from the first root item.
  814. //
  815. // $REVIEW (ptousig) Why does the root item implement ScSave() ?
  816. // If a snapin extends two nodes it has two root items, yet
  817. // only one of which will be saved/loaded.
  818. //
  819. SC CComponentData::ScSave(IStream *pstream, BOOL fClearDirty)
  820. {
  821. SC sc = S_OK;
  822. // Save the snapin's serialized information.
  823. sc = Psnapin()->ScSave(pstream, fClearDirty);
  824. if (sc)
  825. goto Error;
  826. // Load the root item's serialized information.
  827. // Only makes sense for standalone snapins.
  828. sc = Pitem()->ScSave(pstream, fClearDirty);
  829. if (sc)
  830. goto Error;
  831. Cleanup:
  832. return sc;
  833. Error:
  834. TraceError(_T("CComponentData::ScSave"), sc);
  835. goto Cleanup;
  836. }
  837. // -----------------------------------------------------------------------------
  838. // Given a dataobject, determines whether or not pages exist.
  839. // Actually, need to return S_OK here in both cases. If no pages exist
  840. // it is CreatePropertyPages that should return S_FALSE. Sad but true.
  841. //
  842. SC CComponentData::ScQueryPagesFor(LPDATAOBJECT pDataObject)
  843. {
  844. SC sc = S_OK;
  845. CBaseSnapinItem * pitem = NULL;
  846. pitem = Pitem(pDataObject);
  847. ASSERT(pitem);
  848. sc = pitem->ScQueryPagesFor();
  849. if (sc)
  850. goto Error;
  851. Cleanup:
  852. return sc;
  853. Error:
  854. TraceError(_T("CComponentData::ScQueryPagesFor"), sc);
  855. goto Cleanup;
  856. }