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.

546 lines
16 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. /*++
  3. Copyright (C) Microsoft Corporation, 1997 - 1999
  4. Module Name:
  5. ComponentData.cpp
  6. Abstract:
  7. Implementation file for the CComponentData class.
  8. The CComponentData class implements several interfaces which MMC uses:
  9. The IComponentData interface is basically how MMC talks to the snap-in
  10. to get it to implement the left-hand-side "scope" pane. There is only one
  11. object implementing this interface instantiated -- it is best thought of as
  12. the main "document" on which the objects implementing the IComponent interface
  13. (see Component.cpp) are "views".
  14. The IExtendPropertySheet interface is how the snap-in adds property sheets
  15. for any of the items a user might click on.
  16. The IExtendContextMenu interface what we do to add custom entries
  17. to the menu which appears when a user right-clicks on a node.
  18. The IExtendControlBar interface allows us to support a custom
  19. iconic toolbar.
  20. Note:
  21. Much of the functionality of this class is implemented in atlsnap.h
  22. by IComponentDataImpl. We are mostly overriding here.
  23. Revision History:
  24. mmaguire 11/6/97 - created using MMC snap-in wizard
  25. mmaguire 11/24/97 - hurricaned for better project structure
  26. --*/
  27. //////////////////////////////////////////////////////////////////////////////
  28. //////////////////////////////////////////////////////////////////////////////
  29. // BEGIN INCLUDES
  30. //
  31. // standard includes:
  32. //
  33. #include "Precompiled.h"
  34. //
  35. // where we can find declaration for main class in this file:
  36. //
  37. #include "ComponentData.h"
  38. //
  39. // where we can find declarations needed in this file:
  40. //
  41. #include "MachineNode.h"
  42. #include "PoliciesNode.h"
  43. #include "PolicyNode.h"
  44. #include "Component.h"
  45. #include <stdio.h>
  46. #include "ChangeNotification.h"
  47. //
  48. // END INCLUDES
  49. //////////////////////////////////////////////////////////////////////////////
  50. //////////////////////////////////////////////////////////////////////////////
  51. /*++
  52. CComponentData::CComponentData
  53. --*/
  54. //////////////////////////////////////////////////////////////////////////////
  55. CComponentData::CComponentData()
  56. {
  57. ATLTRACE(_T("+NAPMMC+:# +++ CComponentData::CComponentData\n"));
  58. // We pass our CRootNode a pointer to this CComponentData. This is so that
  59. // it and any of its children nodes have access to our member variables
  60. // and services, and thus we have snapin-global data if we need it
  61. // using the GetComponentData function.
  62. // m_pNode = new CRootNode( this );
  63. // _ASSERTE(m_pNode != NULL);
  64. m_pComponentData = this;
  65. }
  66. //////////////////////////////////////////////////////////////////////////////
  67. /*++
  68. CComponentData::~CComponentData
  69. --*/
  70. //////////////////////////////////////////////////////////////////////////////
  71. CComponentData::~CComponentData()
  72. {
  73. ATLTRACE(_T("+NAPMMC+:# --- CComponentData::~CComponentData\n"));
  74. // delete m_pNode;
  75. // m_pNode = NULL;
  76. }
  77. //////////////////////////////////////////////////////////////////////////////
  78. /*++
  79. CComponentData::Initialize
  80. HRESULT Initialize(
  81. LPUNKNOWN pUnknown // Pointer to console's IUnknown.
  82. );
  83. Called by MMC to initialize the IComponentData object.
  84. Parameters
  85. pUnknown [in] Pointer to the console's IUnknown interface. This interface
  86. pointer can be used to call QueryInterface for IConsole and IConsoleNameSpace.
  87. Return Values
  88. S_OK The component was successfully initialized.
  89. E_UNEXPECTED
  90. An unexpected error occurred.
  91. Remarks
  92. IComponentData::Initialize is called when a snap-in is being created and has
  93. items in the scope pane to enumerate. The pointer to IConsole that is passed
  94. in is used to make QueryInterface calls to the console for interfaces such as
  95. IConsoleNamespace. The snap-in should also call IConsole::QueryScopeImageList
  96. to get the image list for the scope pane and add images to be displayed on
  97. the scope pane side.
  98. --*/
  99. //////////////////////////////////////////////////////////////////////////////
  100. STDMETHODIMP CComponentData::Initialize (LPUNKNOWN pUnknown)
  101. {
  102. ATLTRACE(_T("+NAPMMC+:# CComponentData::Initialize\n"));
  103. // MAM: special for extention snapin:
  104. m_CMachineNode.m_pComponentData = this;
  105. HRESULT hr = IComponentDataImpl<CComponentData, CComponent >::Initialize(pUnknown);
  106. if (FAILED(hr))
  107. {
  108. ATLTRACE(_T("+NAPMMC+:***FAILED***: CComponentData::Initialize -- Base class initialization\n"));
  109. return hr;
  110. }
  111. CComPtr<IImageList> spImageList;
  112. if (m_spConsole->QueryScopeImageList(&spImageList) != S_OK)
  113. {
  114. ATLTRACE(_T("+NAPMMC+:***FAILED***: IConsole::QueryScopeImageList failed\n"));
  115. return E_UNEXPECTED;
  116. }
  117. // Load bitmaps associated with the scope pane
  118. // and add them to the image list
  119. HBITMAP hBitmap16 = LoadBitmap(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDB_NAPSNAPIN_16));
  120. if (hBitmap16 == NULL)
  121. {
  122. ATLTRACE(_T("+NAPMMC+:***FAILED***: CComponentData::Initialize -- LoadBitmap\n"));
  123. //ISSUE: Will MMC still be able to function if this fails?
  124. return S_OK;
  125. }
  126. HBITMAP hBitmap32 = LoadBitmap(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDB_NAPSNAPIN_32));
  127. if (hBitmap32 == NULL)
  128. {
  129. ATLTRACE(_T("+NAPMMC+:***FAILED***: CComponentData::Initialize -- LoadBitmap\n"));
  130. //ISSUE: Will MMC still be able to function if this fails?
  131. //ISSUE: Should DeleteObject previous hBitmap16 since it was successfully loaded.
  132. return S_OK;
  133. }
  134. if (spImageList->ImageListSetStrip((LONG_PTR*)hBitmap16, (LONG_PTR*)hBitmap32, 0, RGB(255, 0, 255)) != S_OK)
  135. {
  136. ATLTRACE(_T("+NAPMMC+:***FAILED***: CComponentData::Initialize -- ImageListSetStrip\n"));
  137. return E_UNEXPECTED;
  138. }
  139. // ISSUE: Do we need to release the HBITMAP objects?
  140. // This wasn't done wizard-generated code -- does MMC make a copy of these or
  141. // does it take care of deleting the ones we passed to it?
  142. // DeleteObject( hBitmap16 );
  143. // DeleteObject( hBitmap32 );
  144. //
  145. // NAP snap-in will need to use ListView common control to display
  146. // attribute types for a particular rule. We need to initialize the common
  147. // controls during initialization. This can ensure COMTRL32.DLL is loaded
  148. //
  149. INITCOMMONCONTROLSEX initCommCtrlsEx;
  150. initCommCtrlsEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
  151. initCommCtrlsEx.dwICC = ICC_WIN95_CLASSES ;
  152. if (!InitCommonControlsEx(&initCommCtrlsEx))
  153. {
  154. ATLTRACE(_T("+NAPMMC+:***FAILED***: CComponentData::Initialize -- InitCommonControlsEx()\n"));
  155. return E_UNEXPECTED;
  156. }
  157. return S_OK;
  158. }
  159. /////////////////////////////////////////////////////////////////////////////
  160. /*++
  161. CComponentData::CompareObjects
  162. Needed so that IPropertySheetProvider::FindPropertySheet will work.
  163. FindPropertySheet is used to bring a pre-existing property sheet to the foreground
  164. so that we don't open multiple copies of Properties on the same node.
  165. It requires CompareObjects to be implemented on both IComponent and IComponentData.
  166. --*/
  167. //////////////////////////////////////////////////////////////////////////////
  168. STDMETHODIMP CComponentData::CompareObjects(
  169. LPDATAOBJECT lpDataObjectA
  170. , LPDATAOBJECT lpDataObjectB
  171. )
  172. {
  173. ATLTRACE(_T("+NAPMMC+:# CComponentData::CompareObjects\n"));
  174. HRESULT hr;
  175. CSnapInItem *pDataA, *pDataB;
  176. DATA_OBJECT_TYPES typeA, typeB;
  177. hr = GetDataClass(lpDataObjectA, &pDataA, &typeA);
  178. if ( FAILED( hr ) )
  179. {
  180. return hr;
  181. }
  182. hr = GetDataClass(lpDataObjectB, &pDataB, &typeB);
  183. if ( FAILED( hr ) )
  184. {
  185. return hr;
  186. }
  187. if( pDataA == pDataB )
  188. {
  189. // They are the same object.
  190. return S_OK;
  191. }
  192. else
  193. {
  194. // They are different.
  195. return S_FALSE;
  196. }
  197. }
  198. /////////////////////////////////////////////////////////////////////////////
  199. /*++
  200. CComponentData::CreateComponent
  201. We override the ATLsnap.h implementation so that we can save away our 'this'
  202. pointer into the CComponent object we create. This way the IComponent object
  203. has knowledge of the CComponentData object to which it belongs.
  204. --*/
  205. //////////////////////////////////////////////////////////////////////////////
  206. STDMETHODIMP CComponentData::CreateComponent(LPCOMPONENT *ppComponent)
  207. {
  208. ATLTRACE(_T("# CComponentData::CreateComponent\n"));
  209. HRESULT hr = E_POINTER;
  210. ATLASSERT(ppComponent != NULL);
  211. if (ppComponent == NULL)
  212. ATLTRACE(_T("# IComponentData::CreateComponent called with ppComponent == NULL\n"));
  213. else
  214. {
  215. *ppComponent = NULL;
  216. CComObject< CComponent >* pComponent;
  217. hr = CComObject< CComponent >::CreateInstance(&pComponent);
  218. ATLASSERT(SUCCEEDED(hr));
  219. if (FAILED(hr))
  220. ATLTRACE(_T("# IComponentData::CreateComponent : Could not create IComponent object\n"));
  221. else
  222. {
  223. hr = pComponent->QueryInterface(IID_IComponent, (void**)ppComponent);
  224. pComponent->m_pComponentData = this;
  225. }
  226. }
  227. return hr;
  228. }
  229. //////////////////////////////////////////////////////////////////////////////
  230. /*++
  231. CComponentData::Notify
  232. Notifies the snap-in of actions taken by the user.
  233. HRESULT Notify(
  234. LPDATAOBJECT lpDataObject, // Pointer to a data object
  235. MMC_NOTIFY_TYPE event, // Action taken by a user
  236. LPARAM arg, // Depends on event
  237. LPARAM param // Depends on event
  238. );
  239. Parameters
  240. lpDataObject
  241. [in] Pointer to the data object of the currently selected item.
  242. event
  243. [in] Identifies an action taken by a user. IComponent::Notify can receive the
  244. following notifications:
  245. MMCN_ACTIVATE
  246. MMCN_ADD_IMAGES
  247. MMCN_BTN_CLICK
  248. MMCN_CLICK
  249. MMCN_DBLCLICK
  250. MMCN_DELETE
  251. MMCN_EXPAND
  252. MMCN_MINIMIZED
  253. MMCN_PROPERTY_CHANGE
  254. MMCN_REMOVE_CHILDREN
  255. MMCN_RENAME
  256. MMCN_SELECT
  257. MMCN_SHOW
  258. MMCN_VIEW_CHANGE
  259. All of which are forwarded to each node's Notify method, as well as:
  260. MMCN_COLUMN_CLICK
  261. MMCN_SNAPINHELP
  262. Which are handled here.
  263. arg
  264. Depends on the notification type.
  265. param
  266. Depends on the notification type.
  267. Return Values
  268. S_OK
  269. Depends on the notification type.
  270. E_UNEXPECTED
  271. An unexpected error occurred.
  272. Remarks
  273. We are overiding the ATLsnap.h implementation of IComponentImpl because
  274. it always returns E_UNEXPECTED when lpDataObject == NULL.
  275. Unfortunately, some valid message (e.g. MMCN_SNAPINHELP and MMCN_COLUMN_CLICK)
  276. pass in lpDataObject = NULL by design.
  277. Also, there seems to be some problem with Sridhar's latest
  278. IComponentImpl::Notify method, because it causes MMC to run-time error.
  279. --*/
  280. //////////////////////////////////////////////////////////////////////////////
  281. STDMETHODIMP CComponentData::Notify (
  282. LPDATAOBJECT lpDataObject,
  283. MMC_NOTIFY_TYPE event,
  284. LPARAM arg,
  285. LPARAM param)
  286. {
  287. ATLTRACE(_T("# CComponentData::Notify\n"));
  288. // Check for preconditions:
  289. // None.
  290. HRESULT hr;
  291. // lpDataObject should be a pointer to a node object.
  292. // If it is NULL, then we are being notified of an event
  293. // which doesn't pertain to any specific node.
  294. if ( NULL == lpDataObject )
  295. {
  296. // respond to events which have no associated lpDataObject
  297. switch( event )
  298. {
  299. case MMCN_PROPERTY_CHANGE:
  300. hr = OnPropertyChange( arg, param );
  301. break;
  302. default:
  303. ATLTRACE(_T("# CComponent::Notify - called with lpDataObject == NULL and no event handler\n"));
  304. hr = E_NOTIMPL;
  305. break;
  306. }
  307. return hr;
  308. }
  309. // We were passed a LPDATAOBJECT which corresponds to a node.
  310. // We convert this to the ATL ISnapInDataInterface pointer.
  311. // This is done in GetDataClass (a static method of ISnapInDataInterface)
  312. // by asking the dataobject via a supported clipboard format (CCF_GETCOOKIE)
  313. // to write out a pointer to itself on a stream and then
  314. // casting this value to a pointer.
  315. // We then call the Notify method on that object, letting
  316. // the node object deal with the Notify event itself.
  317. CSnapInItem* pItem;
  318. DATA_OBJECT_TYPES type;
  319. hr = m_pComponentData->GetDataClass(lpDataObject, &pItem, &type);
  320. ATLASSERT(SUCCEEDED(hr));
  321. if (SUCCEEDED(hr))
  322. {
  323. hr = pItem->Notify( event, arg, param, this, NULL, type );
  324. }
  325. return hr;
  326. }
  327. //////////////////////////////////////////////////////////////////////////////
  328. /*++
  329. CComponentData::OnPropertyChange
  330. HRESULT OnPropertyChange(
  331. LPARAM arg
  332. , LPARAM param
  333. )
  334. This is where we respond to an MMCN_PROPERTY_CHANGE notification.
  335. This notification is sent when we call MMCPropertyChangeNotify.
  336. We call this in our property pages when changes are made to the data
  337. they contain and we may need to update of view of the data.
  338. --*/
  339. //////////////////////////////////////////////////////////////////////////////
  340. HRESULT CComponentData::OnPropertyChange(
  341. LPARAM arg
  342. , LPARAM lParam
  343. )
  344. {
  345. ATLTRACE(_T("# CComponentData::OnPropertyChange\n"));
  346. // Check for preconditions:
  347. _ASSERTE( m_spConsole != NULL );
  348. HRESULT hr = S_FALSE;
  349. if( lParam != NULL )
  350. {
  351. // We were passed a pointer to a CChangeNotification in the param argument.
  352. CChangeNotification * pChangeNotification = (CChangeNotification *) lParam;
  353. // We call notify on the node specified, passing it our own custom event type
  354. // so that it knows that it must refresh its data.
  355. // Call notify on this node with the MMCN_PROPERTY_CHANGE notification.
  356. // We had to use this trick because of the fact that we are using template
  357. // classes and so we have no common object among all our nodes
  358. // other than CSnapInItem. But we can't change CSnapInItem
  359. // so instead we use the notify method it already has with a new
  360. // notification.
  361. // Note: We are trying to deal gracefully here with the fact that the
  362. // MMCN_PROPERTY_CHANGE notification doesn't pass us an lpDataObject
  363. // so we have to have our own protocol for picking out which node
  364. // needs to update itself.
  365. hr = pChangeNotification->m_pNode->Notify( MMCN_PROPERTY_CHANGE
  366. , NULL
  367. , NULL
  368. , NULL
  369. , NULL
  370. , (DATA_OBJECT_TYPES) 0
  371. );
  372. // We want to make sure all views with this node select also get updated.
  373. // Pass it the CChangeNotification pointer we were passed in param.
  374. hr = m_spConsole->UpdateAllViews( NULL, lParam, 0);
  375. pChangeNotification->Release();
  376. }
  377. return hr;
  378. }
  379. //////////////////////////////////////////////////////////////////////////////
  380. /*++
  381. CComponentData::GetWatermarks
  382. --*/
  383. //////////////////////////////////////////////////////////////////////////////
  384. STDMETHODIMP CComponentData::GetWatermarks(
  385. LPDATAOBJECT lpIDataObject,
  386. HBITMAP *lphWatermark,
  387. HBITMAP *lphHeader,
  388. HPALETTE *lphPalette,
  389. BOOL *bStretch
  390. )
  391. {
  392. *lphWatermark = LoadBitmap(
  393. _Module.GetResourceInstance(),
  394. MAKEINTRESOURCE(IDB_RAP_WATERMARK)
  395. );
  396. *lphHeader = LoadBitmap(
  397. _Module.GetResourceInstance(),
  398. MAKEINTRESOURCE(IDB_RAP_HEADER)
  399. );
  400. *lphPalette = NULL;
  401. *bStretch = FALSE;
  402. return S_OK;
  403. };