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.

715 lines
19 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. /*++
  3. Copyright (C) Microsoft Corporation, 1997 - 1999
  4. Module Name:
  5. LogComp.cpp
  6. Abstract:
  7. Implementation file for the CLoggingComponent class.
  8. The CLoggingComponent class implements several interfaces which MMC uses:
  9. The IComponent interface is basically how MMC talks to the snap-in
  10. to get it to implement a right-hand-side "scope" pane. There can be several
  11. objects implementing this interface instantiated at once. These are best
  12. thought of as "views" on the single object implementing the IComponentData
  13. "document" (see ComponentData.cpp).
  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. The IResultDataCompare interface allows us to support a custom
  21. sorting algorithm for result pane items
  22. Note:
  23. Much of the functionality of this class is implemented in atlsnap.h
  24. by IComponentDataImpl. We are mostly overriding here.
  25. Revision History:
  26. mmaguire 11/6/97 - created using MMC snap-in wizard
  27. mmaguire 11/24/97 - hurricaned for better project structure
  28. --*/
  29. //////////////////////////////////////////////////////////////////////////////
  30. //////////////////////////////////////////////////////////////////////////////
  31. // BEGIN INCLUDES
  32. //
  33. // standard includes:
  34. //
  35. #include "Precompiled.h"
  36. //
  37. // where we can find declaration for main class in this file:
  38. //
  39. #include "LogComp.h"
  40. //
  41. // where we can find declarations needed in this file:
  42. //
  43. #include "LogMacNd.h"
  44. #include "LocalfileLoggingNode.h"
  45. #include "LoggingMethodsNode.h"
  46. #include "ChangeNotification.h"
  47. //
  48. // END INCLUDES
  49. //////////////////////////////////////////////////////////////////////////////
  50. //////////////////////////////////////////////////////////////////////////////
  51. /*++
  52. CLoggingComponent::CLoggingComponent
  53. Constructor
  54. --*/
  55. //////////////////////////////////////////////////////////////////////////////
  56. CLoggingComponent::CLoggingComponent()
  57. {
  58. TRACE_FUNCTION("CLoggingComponent::CLoggingComponent");
  59. m_pSelectedNode = NULL;
  60. }
  61. //////////////////////////////////////////////////////////////////////////////
  62. /*++
  63. CLoggingComponent::~CLoggingComponent
  64. Destructor
  65. --*/
  66. //////////////////////////////////////////////////////////////////////////////
  67. CLoggingComponent::~CLoggingComponent()
  68. {
  69. TRACE_FUNCTION("CLoggingComponent::~CLoggingComponent");
  70. }
  71. //+---------------------------------------------------------------------------
  72. //
  73. // Function: Compare
  74. //
  75. // Class: CLoggingComponent (inherited from IResultDataCompare)
  76. //
  77. // Synopsis: customized sorting algorithm
  78. // This method will be called whenever MMC console needs to
  79. // compare two result pane data items, for example, when user
  80. // clicks on the column header
  81. //
  82. // Arguments:
  83. // LPARAM lUserParam, User-provided information
  84. // MMC_COOKIE cookieA, Unique identifier of first object
  85. // MMC_COOKIE cookieB, Unique identifier of second object
  86. // int * pnResult Column being sorted//
  87. //
  88. // Returns: STDMETHODIMP -
  89. //
  90. // History: Created byao 2/5/98 4:19:10 PM
  91. //
  92. //+---------------------------------------------------------------------------
  93. STDMETHODIMP CLoggingComponent::Compare(LPARAM lUserParam,
  94. MMC_COOKIE cookieA,
  95. MMC_COOKIE cookieB,
  96. int *pnResult)
  97. {
  98. TRACE_FUNCTION("CLoggingComponent::Compare");
  99. //
  100. // sort policies node according to their merit value
  101. //
  102. CLocalFileLoggingNode *pA = (CLocalFileLoggingNode*)cookieA;
  103. CLocalFileLoggingNode *pB = (CLocalFileLoggingNode*)cookieB;
  104. ATLASSERT(pA != NULL);
  105. ATLASSERT(pB != NULL);
  106. //*pnResult = pA->GetMerit() > pB->GetMerit();
  107. *pnResult = 0;
  108. return S_OK;
  109. }
  110. //////////////////////////////////////////////////////////////////////////////
  111. /*++
  112. CLoggingComponent::Notify
  113. Notifies the snap-in of actions taken by the user.
  114. HRESULT Notify(
  115. LPDATAOBJECT lpDataObject, // Pointer to a data object
  116. MMC_NOTIFY_TYPE event, // Action taken by a user
  117. LPARAM arg, // Depends on event
  118. LPARAM param // Depends on event
  119. );
  120. Parameters
  121. lpDataObject
  122. [in] Pointer to the data object of the currently selected item.
  123. event
  124. [in] Identifies an action taken by a user. IComponent::Notify can receive the
  125. following notifications:
  126. MMCN_ACTIVATE
  127. MMCN_ADD_IMAGES
  128. MMCN_BTN_CLICK
  129. MMCN_CLICK
  130. MMCN_DBLCLICK
  131. MMCN_DELETE
  132. MMCN_EXPAND
  133. MMCN_MINIMIZED
  134. MMCN_PROPERTY_CHANGE
  135. MMCN_REMOVE_CHILDREN
  136. MMCN_RENAME
  137. MMCN_SELECT
  138. MMCN_SHOW
  139. MMCN_VIEW_CHANGE
  140. All of which are forwarded to each node's Notify method, as well as:
  141. MMCN_COLUMN_CLICK
  142. MMCN_SNAPINHELP
  143. Which are handled here.
  144. arg
  145. Depends on the notification type.
  146. param
  147. Depends on the notification type.
  148. Return Values
  149. S_OK
  150. Depends on the notification type.
  151. E_UNEXPECTED
  152. An unexpected error occurred.
  153. Remarks
  154. We are overiding the ATLsnap.h implementation of IComponentImpl because
  155. it always returns E_UNEXPECTED when lpDataObject == NULL.
  156. Unfortunately, some valid message (e.g. MMCN_SNAPINHELP and MMCN_COLUMN_CLICK)
  157. pass in lpDataObject = NULL by design.
  158. Also, there seems to be some problem with Sridhar's latest
  159. IComponentImpl::Notify method, because it causes MMC to run-time error.
  160. --*/
  161. //////////////////////////////////////////////////////////////////////////////
  162. STDMETHODIMP CLoggingComponent::Notify (
  163. LPDATAOBJECT lpDataObject,
  164. MMC_NOTIFY_TYPE event,
  165. LPARAM arg,
  166. LPARAM param
  167. )
  168. {
  169. TRACE_FUNCTION("CLoggingComponent::Notify");
  170. HRESULT hr;
  171. // deal with help
  172. if(event == MMCN_CONTEXTHELP)
  173. {
  174. return OnResultContextHelp(lpDataObject);
  175. }
  176. // lpDataObject should be a pointer to a node object.
  177. // If it is NULL, then we are being notified of an event
  178. // which doesn't pertain to any specific node.
  179. if ( NULL == lpDataObject )
  180. {
  181. // respond to events which have no associated lpDataObject
  182. switch( event )
  183. {
  184. case MMCN_COLUMN_CLICK:
  185. hr = OnColumnClick( arg, param );
  186. break;
  187. case MMCN_PROPERTY_CHANGE:
  188. hr = OnPropertyChange( arg, param );
  189. break;
  190. case MMCN_VIEW_CHANGE:
  191. hr = OnViewChange( arg, param );
  192. break;
  193. default:
  194. ATLTRACE(_T("+NAPMMC+:# CLoggingComponent::Notify - called with lpDataObject == NULL and no event handler\n"));
  195. hr = E_NOTIMPL;
  196. break;
  197. }
  198. return hr;
  199. }
  200. // Respond to some notifications where the lpDataObject is not NULL
  201. // but we nevertheless have decided that we want to handle them on a
  202. // per-IComponent basis.
  203. switch( event )
  204. {
  205. case MMCN_ADD_IMAGES:
  206. hr = OnAddImages( arg, param );
  207. return hr;
  208. break;
  209. }
  210. // We were passed a LPDATAOBJECT which corresponds to a node.
  211. // We convert this to the ATL ISnapInDataInterface pointer.
  212. // This is done in GetDataClass (a static method of ISnapInDataInterface)
  213. // by asking the dataobject via a supported clipboard format (CCF_GETCOOKIE)
  214. // to write out a pointer to itself on a stream and then
  215. // casting this value to a pointer.
  216. // We then call the Notify method on that object, letting
  217. // the node object deal with the Notify event itself.
  218. CSnapInItem* pData;
  219. DATA_OBJECT_TYPES type;
  220. hr = CSnapInItem::GetDataClass(lpDataObject, &pData, &type);
  221. if (SUCCEEDED(hr))
  222. {
  223. // We need a richer Notify method which has information about the IComponent and IComponentData objects
  224. //hr = pData->Notify(event, arg, param, TRUE, m_spConsole, NULL, NULL);
  225. hr = pData->Notify(event, arg, param, NULL, this, type );
  226. }
  227. return hr;
  228. }
  229. /////////////////////////////////////////////////////////////////////////////
  230. /*++
  231. CLoggingComponent::CompareObjects
  232. Needed so that IPropertySheetProvider::FindPropertySheet will work.
  233. FindPropertySheet is used to bring a pre-existing property sheet to the foreground
  234. so that we don't open multiple copies of Properties on the same node.
  235. It requires CompareObjects to be implemented on both IComponent and IComponentData.
  236. --*/
  237. //////////////////////////////////////////////////////////////////////////////
  238. STDMETHODIMP CLoggingComponent::CompareObjects(
  239. LPDATAOBJECT lpDataObjectA
  240. , LPDATAOBJECT lpDataObjectB
  241. )
  242. {
  243. TRACE_FUNCTION("CLoggingComponent::CompareObjects");
  244. HRESULT hr;
  245. CSnapInItem *pDataA, *pDataB;
  246. DATA_OBJECT_TYPES typeA, typeB;
  247. hr = GetDataClass(lpDataObjectA, &pDataA, &typeA);
  248. if ( FAILED( hr ) )
  249. {
  250. return hr;
  251. }
  252. hr = GetDataClass(lpDataObjectB, &pDataB, &typeB);
  253. if ( FAILED( hr ) )
  254. {
  255. return hr;
  256. }
  257. if( pDataA == pDataB )
  258. {
  259. // They are the same object.
  260. return S_OK;
  261. }
  262. else
  263. {
  264. // They are different.
  265. return S_FALSE;
  266. }
  267. }
  268. /////////////////////////////////////////////////////////////////////////////
  269. /*++
  270. CLoggingComponent::OnColumnClick
  271. HRESULT OnColumnClick(
  272. LPARAM arg
  273. , LPARAM param
  274. )
  275. In our implementation, this method gets called when the MMCN_COLUMN_CLICK
  276. Notify message is sent for our IComponent object.
  277. MMC sends this message when the user clicks on a result-list view column header.
  278. Parameters
  279. arg
  280. Column number.
  281. param
  282. Sort option flags. By default, the sort is in ascending order. To specify descending order, use the RSI_DESCENDING (0x0001) flag.
  283. Return Values
  284. Not used.
  285. --*/
  286. //////////////////////////////////////////////////////////////////////////////
  287. HRESULT CLoggingComponent::OnColumnClick(
  288. LPARAM arg
  289. , LPARAM param
  290. )
  291. {
  292. TRACE_FUNCTION("CLoggingComponent::OnColumnClick -- Not implemented");
  293. return E_NOTIMPL;
  294. }
  295. //////////////////////////////////////////////////////////////////////////////
  296. /*++
  297. CLoggingComponent::OnViewChange
  298. HRESULT OnViewChange(
  299. LPARAM arg
  300. , LPARAM param
  301. )
  302. This is where we respond to an MMCN_VIEW_CHANGE notification which was
  303. set without any reference to a specific node.
  304. In our implementation, this is a signal to refresh the view of the currently
  305. selected node for this IComponent's view.
  306. --*/
  307. //////////////////////////////////////////////////////////////////////////////
  308. HRESULT CLoggingComponent::OnViewChange(
  309. LPARAM arg
  310. , LPARAM param
  311. )
  312. {
  313. ATLTRACE(_T("+NAPMMC+:# CLoggingComponent::OnViewChange\n"));
  314. HRESULT hr = S_FALSE;
  315. CChangeNotification *pChangeNotification = NULL;
  316. try
  317. {
  318. // If arg here is non-NULL, it should be a pointer to a CChangeNotification object.
  319. if( arg != NULL )
  320. {
  321. pChangeNotification = (CChangeNotification *) arg;
  322. // For now, just call update item on the node.
  323. // ISSUE: Later, we should have a switch on m_dwFlags to see what we should do.
  324. // e.g. in the case of a deletion, we should (maybe?) reselect parent node or something.
  325. switch( pChangeNotification->m_dwFlags )
  326. {
  327. case CHANGE_UPDATE_RESULT_NODE:
  328. {
  329. // We need to update a single node.
  330. CComQIPtr< IResultData, &IID_IResultData > spResultData( m_spConsole );
  331. if( ! spResultData )
  332. {
  333. throw hr;
  334. }
  335. if( pChangeNotification->m_pNode )
  336. {
  337. HRESULTITEM item;
  338. hr = spResultData->FindItemByLParam( (LPARAM) pChangeNotification->m_pNode, &item );
  339. // Note: You can't use the itemID stored in CSnapInItem's RESULTDATAITEM structure
  340. // as this itemID is unique to each view -- so when you add the same item in each
  341. // result pane view, you get a different itemID from each call to InsertItem.
  342. // CSnapInItem's RESULTDATAITEM structure only stores the last one stored.
  343. // This is a flaw in the atlsnap.h architecture, which is why we use
  344. // MMC's FindItemByLParam instead to get the appropriate itemID.
  345. hr = spResultData->UpdateItem( item );
  346. }
  347. }
  348. break;
  349. case CHANGE_UPDATE_CHILDREN_OF_SELECTED_NODE:
  350. {
  351. // We basically tell MMC to simulate reselecting the
  352. // currently selected scope-pane node, which causes it to redraw.
  353. // This will cause MMC to send the MMCN_SHOW notification
  354. // to the selected node.
  355. if( m_pSelectedNode )
  356. {
  357. SCOPEDATAITEM *pScopeDataItem;
  358. m_pSelectedNode->GetScopeData( &pScopeDataItem );
  359. hr = m_spConsole->SelectScopeItem( pScopeDataItem->ID );
  360. }
  361. }
  362. break;
  363. case CHANGE_UPDATE_CHILDREN_OF_THIS_NODE:
  364. {
  365. // We basically tell MMC to simulate reselecting the
  366. // currently selected scope-pane node, which causes it to redraw.
  367. // This will cause MMC to send the MMCN_SHOW notification
  368. // to the selected node.
  369. if( pChangeNotification->m_pNode && m_pSelectedNode && pChangeNotification->m_pNode == m_pSelectedNode )
  370. {
  371. SCOPEDATAITEM *pScopeDataItem;
  372. m_pSelectedNode->GetScopeData( &pScopeDataItem );
  373. hr = m_spConsole->SelectScopeItem( pScopeDataItem->ID );
  374. }
  375. }
  376. default:
  377. break;
  378. }
  379. }
  380. }
  381. catch(...)
  382. {
  383. // Do nothing -- just need to catch for proper clean-up below.
  384. }
  385. return hr;
  386. }
  387. //////////////////////////////////////////////////////////////////////////////
  388. /*++
  389. CLoggingComponent::OnAddImages
  390. HRESULT OnAddImages(
  391. LPARAM arg
  392. , LPARAM param
  393. )
  394. This is where we respond to an MMCN_ADD_IMAGES notification to
  395. this IComponent object.
  396. We add images to the image list used to display result pane
  397. items corresponding to this IComponent's view.
  398. MMC sends this message to the snap-in's IComponent implementation
  399. to add images for the result pane.
  400. Parameters
  401. arg
  402. Pointer to the result pane's image list (IImageList).
  403. param
  404. Specifies the HSCOPEITEM of the item that was selected or deselected.
  405. Return Values
  406. Not used.
  407. Remarks
  408. The primary snap-in should add images for both folders and leaf
  409. items. Extension snap-ins should add only folder images.
  410. --*/
  411. //////////////////////////////////////////////////////////////////////////////
  412. HRESULT CLoggingComponent::OnAddImages(
  413. LPARAM arg
  414. , LPARAM param
  415. )
  416. {
  417. ATLTRACE(_T("# CLoggingComponent::OnAddImages\n"));
  418. // Check for preconditions:
  419. _ASSERTE( arg != NULL );
  420. HRESULT hr = S_FALSE;
  421. // ISSUE: sburns in localsec does a trick where he combines
  422. // scope and result pane ImageLists into one
  423. // is this necessary?
  424. CComPtr<IImageList> spImageList = reinterpret_cast<IImageList*>(arg);
  425. _ASSERTE( spImageList != NULL );
  426. HBITMAP hBitmap16 = LoadBitmap( _Module.GetResourceInstance(), MAKEINTRESOURCE( IDB_NAPSNAPIN_16 ) );
  427. HBITMAP hBitmap32 = LoadBitmap( _Module.GetResourceInstance(), MAKEINTRESOURCE( IDB_NAPSNAPIN_32 ) );
  428. if( hBitmap16 != NULL && hBitmap32 != NULL )
  429. {
  430. hr = spImageList->ImageListSetStrip( (LONG_PTR*) hBitmap16, (LONG_PTR*) hBitmap32, 0, RGB(255, 0, 255) );
  431. if( FAILED( hr ) )
  432. {
  433. ATLTRACE(_T("# *** CSnapinNode::OnAddImages -- Failed to add images.\n"));
  434. }
  435. }
  436. if ( hBitmap16 != NULL )
  437. {
  438. DeleteObject(hBitmap16);
  439. }
  440. if ( hBitmap32 != NULL )
  441. {
  442. DeleteObject(hBitmap32);
  443. }
  444. return hr;
  445. }
  446. //////////////////////////////////////////////////////////////////////////////
  447. /*++
  448. CLoggingComponent::OnPropertyChange
  449. HRESULT OnPropertyChange(
  450. LPARAM arg
  451. , LPARAM param
  452. )
  453. This is where we respond to an MMCN_PROPERTY_CHANGE notification.
  454. This notification is sent when we call MMCPropertyChangeNotify.
  455. We call this in our property pages when changes are made to the data
  456. they contain and we may need to update of view of the data.
  457. --*/
  458. //////////////////////////////////////////////////////////////////////////////
  459. HRESULT CLoggingComponent::OnPropertyChange(
  460. LPARAM lArg
  461. , LPARAM lParam
  462. )
  463. {
  464. ATLTRACE(_T("# CNodeWithResultChildrenList::OnPropertyChange\n"));
  465. // Check for preconditions:
  466. _ASSERTE( m_spConsole != NULL );
  467. HRESULT hr = S_FALSE;
  468. if( lParam )
  469. {
  470. // We were passed a pointer to a CChangeNotification in the param argument.
  471. CChangeNotification * pChangeNotification = (CChangeNotification *) lParam;
  472. // We call notify on the node specified, passing it our own custom event type
  473. // so that it knows that it must refresh its data.
  474. // Call notify on this node with the MMCN_PROPERTY_CHANGE notification.
  475. // We had to use this trick because of the fact that we are using template
  476. // classes and so we have no common object among all our nodes
  477. // other than CSnapInItem. But we can't change CSnapInItem
  478. // so instead we use the notify method it already has with a new
  479. // notification.
  480. // Note: We are trying to deal gracefully here with the fact that the
  481. // MMCN_PROPERTY_CHANGE notification doesn't pass us an lpDataObject
  482. // so we have to have our own protocol for picking out which node
  483. // needs to update itself.
  484. hr = pChangeNotification->m_pNode->Notify( MMCN_PROPERTY_CHANGE
  485. , NULL
  486. , NULL
  487. , NULL
  488. , NULL
  489. , (DATA_OBJECT_TYPES) 0
  490. );
  491. // We want to make sure all views with this node select also get updated.
  492. // Pass it the CChangeNotification pointer we were passed in param.
  493. hr = m_pComponentData->m_spConsole->UpdateAllViews( NULL, lParam, 0);
  494. pChangeNotification->Release();
  495. }
  496. return hr;
  497. }
  498. /*!--------------------------------------------------------------------------
  499. CComponent::OnResultContextHelp
  500. Implementation of OnResultContextHelp
  501. Author: EricDav
  502. ---------------------------------------------------------------------------*/
  503. HRESULT CLoggingComponent::OnResultContextHelp(LPDATAOBJECT lpDataObject)
  504. {
  505. // Need to find if the context is running in the Remote Access snap-in
  506. // or in the IAS snapin.
  507. const WCHAR szIASDefaultHelpTopic[] = L"ias_ops.chm::/sag_ias_log_conc.htm";
  508. const WCHAR szRASDefaultHelpTopic[] = L"RRASconcepts.chm::" \
  509. L"/sag_RRAS-Ch1_84.htm";
  510. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  511. bool isRasSnapin = false;
  512. CSnapInItem* pItem;
  513. DATA_OBJECT_TYPES type;
  514. HRESULT hr = GetDataClass(lpDataObject, &pItem, &type);
  515. if ( SUCCEEDED(hr) )
  516. {
  517. isRasSnapin = (pItem->m_helpIndex == RAS_HELP_INDEX);
  518. }
  519. CComPtr<IDisplayHelp> spDisplayHelp;
  520. hr = m_spConsole->QueryInterface(
  521. __uuidof(IDisplayHelp),
  522. (LPVOID*) &spDisplayHelp
  523. );
  524. ASSERT (SUCCEEDED (hr));
  525. if ( SUCCEEDED (hr) )
  526. {
  527. if ( isRasSnapin )
  528. {
  529. hr = spDisplayHelp->ShowTopic(W2OLE ((LPWSTR)szRASDefaultHelpTopic));
  530. }
  531. else
  532. {
  533. hr = spDisplayHelp->ShowTopic(W2OLE ((LPWSTR)szIASDefaultHelpTopic));
  534. }
  535. ASSERT (SUCCEEDED (hr));
  536. }
  537. return hr;
  538. }