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.

1507 lines
38 KiB

  1. /*++
  2. 1998 Seagate Software, Inc. All rights reserved.
  3. Module Name:
  4. CSakSnap.cpp
  5. Abstract:
  6. This component implements the IComponent interface for
  7. the snapin. Primarily it is responsible for handling the
  8. result view panes.
  9. Author:
  10. Rohde Wakefield [rohde] 04-Mar-1997
  11. Revision History:
  12. --*/
  13. #include "stdafx.h"
  14. #include "CSakSnap.h"
  15. #include "CSakData.h"
  16. #include "MsDatObj.h"
  17. UINT CSakSnap::m_nImageArray[RS_RESULT_IMAGE_ARRAY_MAX];
  18. INT CSakSnap::m_nImageCount = 0;
  19. STDMETHODIMP
  20. CSakSnap::GetResultViewType(
  21. IN MMC_COOKIE Cookie,
  22. OUT BSTR* ppViewType,
  23. OUT long* pViewOptions
  24. )
  25. /*++
  26. Routine Description:
  27. Determine what the type of the result view will be:
  28. Arguments:
  29. pUnk - Base IUnknown of console
  30. Return Value:
  31. S_OK : either an OCX CLSID string or a URL path.
  32. S_FALSE : default list view will be used.
  33. --*/
  34. {
  35. WsbTraceIn( L"CSakSnap::GetResultViewType", L"Cookie = <0x%p>, ppViewType = <0x%p>, pViewOptions = <0x%p>", Cookie, ppViewType, pViewOptions );
  36. HRESULT hr = S_FALSE;
  37. try {
  38. CComPtr<ISakNode> pSakNode;
  39. WsbAffirmHr( m_pSakData->GetBaseHsmFromCookie( Cookie, &pSakNode ) );
  40. //
  41. // Use default view
  42. //
  43. *ppViewType = 0;
  44. *pViewOptions = MMC_VIEW_OPTIONS_MULTISELECT;
  45. hr = S_FALSE;
  46. } WsbCatch( hr );
  47. WsbTraceOut( L"CSakSnap::GetResultViewType", L"hr = <%ls>, *ppViewType = <%ls>, *pViewOptions = <%ls>", WsbHrAsString( hr ), WsbPtrToStringAsString( ppViewType ), WsbPtrToPtrAsString( (void**)pViewOptions ) );
  48. return( hr );
  49. }
  50. STDMETHODIMP
  51. CSakSnap::Initialize(
  52. IN IConsole * lpConsole
  53. )
  54. /*++
  55. Routine Description:
  56. Called when the user first clicks on node to show result pane.
  57. Arguments:
  58. pUnk - Base IUnknown of console
  59. Return Value:
  60. S_OK - Correctly initialized.
  61. E_xxxxxxxxxxx - Unable to initialize.
  62. --*/
  63. {
  64. WsbTraceIn( L"CSakSnap::Initialize", L"lpConsole = <0x%p>", lpConsole );
  65. HRESULT hr = S_OK;
  66. try {
  67. //
  68. // validity check on parameters
  69. //
  70. WsbAffirmPointer( lpConsole );
  71. //
  72. // Save the IConsole pointer
  73. //
  74. m_pConsole = lpConsole;
  75. //
  76. // Save the result image list
  77. // MS seems to QI for this instead of call
  78. // 'QueryResultImageList'
  79. //
  80. WsbAffirmHr( m_pConsole->QueryInterface( IID_IImageList, (void**)&m_pImageResult ) );
  81. // WsbAffirmHr( m_pConsole->QueryResultImageList( &m_pImageResult ) );
  82. //
  83. // Save the result data pointer
  84. //
  85. WsbAffirmHr( m_pConsole->QueryInterface( IID_IResultData, (void**)&m_pResultData ) );
  86. // Save the ConsolveVerb pointer
  87. // WsbAffirmHr( m_pConsole->QueryInterface( IID_IConsoleVerb, (void **)&m_pConsoleVerb ) );
  88. WsbAffirmHr (m_pConsole->QueryConsoleVerb(&m_pConsoleVerb));
  89. //
  90. // Get the header interface
  91. //
  92. WsbAffirmHr( m_pConsole->QueryInterface( IID_IHeaderCtrl, (void**)&m_pHeader ) );
  93. //
  94. // Give the console the header control interface pointer
  95. //
  96. WsbAffirmHr( m_pConsole->SetHeader( m_pHeader ) );
  97. } WsbCatch( hr);
  98. WsbTraceOut( L"CSakSnap::Initialize", L"hr = <%ls>", WsbHrAsString( hr ) );
  99. return( hr );
  100. }
  101. STDMETHODIMP
  102. CSakSnap::Notify(
  103. IN IDataObject* pDataObject,
  104. IN MMC_NOTIFY_TYPE event,
  105. IN LPARAM arg,
  106. IN LPARAM param
  107. )
  108. /*++
  109. Routine Description:
  110. Handle user clicks on nodes in the result view, along with other
  111. MMC notices.
  112. Arguments:
  113. pDataObject - Data Object for which event occured
  114. event - The event type
  115. arg, param - Info for event (depend on type)
  116. Return Value:
  117. S_OK - Notification handled without error.
  118. E_xxxxxxxxxxx - Unable to register server.
  119. --*/
  120. {
  121. WsbTraceIn( L"CSakSnap::Notify", L"pDataObject = <0x%p>, event = <%ls>, arg = <%ld><0x%p>, param = <%ld><0x%p>", pDataObject, RsNotifyEventAsString( event ), arg, arg, param, param );
  122. CComPtr <IDataObject> pTempDataObject;
  123. HRESULT hr = S_OK;
  124. try {
  125. CComPtr<ISakNode> pBaseHsm;
  126. CComPtr <ISakSnapAsk> pSakSnapAsk;
  127. switch( event ) {
  128. case MMCN_PROPERTY_CHANGE:
  129. WsbAffirmHr( m_pSakData->GetDataObjectFromCookie( param, &pTempDataObject ) );
  130. WsbAffirmHr( OnChange( pTempDataObject, arg, 0L ) );
  131. break;
  132. // This node was expanded or contracted in the scope pane (the user
  133. // clicked on the actual node
  134. case MMCN_SHOW:
  135. WsbAffirmHr( OnShow(pDataObject, arg, param) );
  136. break;
  137. // Not implemented
  138. case MMCN_SELECT:
  139. WsbAffirmHr( OnSelect(pDataObject, arg, param) );
  140. break;
  141. // Not implemented
  142. case MMCN_MINIMIZED:
  143. WsbAffirmHr( OnMinimize(pDataObject, arg, param) );
  144. break;
  145. case MMCN_ADD_IMAGES:
  146. WsbAffirmHr( OnAddImages() );
  147. break;
  148. case MMCN_VIEW_CHANGE:
  149. WsbAffirmHr ( OnChange(pDataObject, arg, param) );
  150. break;
  151. case MMCN_CLICK:
  152. break;
  153. case MMCN_DBLCLICK:
  154. //
  155. // return S_FALSE so that auto-expansion takes place
  156. //
  157. hr = S_FALSE;
  158. break;
  159. case MMCN_DELETE:
  160. WsbAffirmHr( OnDelete(pDataObject, arg, param) );
  161. break;
  162. case MMCN_REFRESH:
  163. WsbAffirmHr( OnRefresh(pDataObject, arg, param) );
  164. break;
  165. case MMCN_CONTEXTHELP:
  166. WsbAffirmHr( m_pSakData->OnContextHelp( pDataObject, arg, param ) );
  167. break;
  168. // Note - Future expansion of notify types possible
  169. default:
  170. // WsbThrow( S_FALSE ); // Handle new messages
  171. break;
  172. }
  173. } WsbCatch( hr );
  174. WsbTraceOut( L"CSakSnap::Notify", L"hr = <%ls>", WsbHrAsString( hr ) );
  175. return( hr );
  176. }
  177. STDMETHODIMP
  178. CSakSnap::Destroy(
  179. MMC_COOKIE Cookie
  180. )
  181. /*++
  182. Routine Description:
  183. Called to force the release of any owned objects and
  184. to clear all views.
  185. Arguments:
  186. cookie - Not used.
  187. Return Value:
  188. S_OK - Correctly tore down.
  189. E_xxxxxxxxxxx - Failure occurred (not meaningful).
  190. --*/
  191. {
  192. WsbTraceIn( L"CSakSnap::Destroy", L"Cookie = <0x%p>", Cookie );
  193. HRESULT hr = S_OK;
  194. try {
  195. // This is a straight C++ pointer, so null it out
  196. m_pSakData = 0;
  197. // Release the interfaces that we QI'ed
  198. if( m_pToolbar && m_pControlbar ) {
  199. m_pControlbar->Detach( m_pToolbar );
  200. }
  201. if( m_pConsole ) {
  202. m_pConsole->SetHeader( 0 );
  203. }
  204. m_pToolbar.Release();
  205. m_pControlbar.Release();
  206. m_pHeader.Release();
  207. m_pResultData.Release();
  208. m_pImageResult.Release();
  209. m_pConsoleVerb.Release();
  210. m_pConsole.Release( );
  211. } WsbCatch( hr );
  212. WsbTraceOut( L"CSakSnap::Destroy", L"hr = <%ls>", WsbHrAsString( hr ) );
  213. return( hr );
  214. }
  215. STDMETHODIMP
  216. CSakSnap::QueryDataObject(
  217. IN MMC_COOKIE cookie,
  218. IN DATA_OBJECT_TYPES type,
  219. OUT IDataObject** ppDataObject
  220. )
  221. /*++
  222. Routine Description:
  223. Called by the console when it needs data for a particular node.
  224. Since each node is a data object, its IDataObject interface is
  225. simply returned. The console will later pass in this dataobject to
  226. SakSnap help it establish the context under which it is being called.
  227. Arguments:
  228. cookie - Node which is being queried.
  229. type - The context under which a dataobject is being requested.
  230. ppDataObject - returned data object.
  231. Return Value:
  232. S_OK - Data Object found and returned.
  233. E_xxxxxxxxxxx - Failure occurred.
  234. --*/
  235. {
  236. WsbTraceIn( L"CSakSnap::QueryDataObject", L"cookie = <0x%p>, type = <%d>, ppDataObject = <0x%p>", cookie, type, ppDataObject );
  237. HRESULT hr = S_OK;
  238. try {
  239. //
  240. // If multi select, we create and return a special data object
  241. //
  242. if( ( MMC_MULTI_SELECT_COOKIE == cookie ) ) {
  243. HRESULT hrInternal = S_OK;
  244. RESULTDATAITEM item;
  245. item.mask = RDI_STATE;
  246. item.nState = LVIS_SELECTED;
  247. item.nIndex = -1;
  248. // Create a Com object
  249. CComObject <CMsDataObject> * pMsDataObject = new CComObject <CMsDataObject>;
  250. pMsDataObject->FinalConstruct();
  251. pMsDataObject->AddRef(); // zzzzz
  252. // Get the IDataObject pointer to pass back to the caller
  253. WsbAffirmHr (pMsDataObject->QueryInterface (IID_IDataObject, (void **) ppDataObject));
  254. // Go through the selected nodes in the result pane and add their node pointers
  255. // and GUIDs to the Data object.
  256. while (hrInternal == S_OK) {
  257. hrInternal = m_pResultData->GetNextItem (&item);
  258. if (hrInternal == S_OK) {
  259. CComPtr<ISakNode> pSakNode;
  260. WsbAffirmHr( m_pSakData->GetBaseHsmFromCookie( item.lParam, &pSakNode ) );
  261. WsbAffirmPointer( pSakNode );
  262. WsbAffirmHr( pMsDataObject->AddNode( pSakNode ) );
  263. }
  264. } // while
  265. } else {
  266. //
  267. // Delegate to SakData
  268. //
  269. WsbAffirmHr (m_pSakData->QueryDataObject( cookie, type, ppDataObject ));
  270. }
  271. } WsbCatch (hr);
  272. WsbTraceOut( L"CSakSnap::QueryDataObject", L"hr = <%ls>, *ppDataObject = <%ls>", WsbHrAsString( hr ), WsbPtrToPtrAsString( (void**)ppDataObject ) );
  273. return( hr );
  274. }
  275. void
  276. CSakSnap::FinalRelease(
  277. void
  278. )
  279. /*++
  280. Routine Description:
  281. Called on final release in order to clean up all members.
  282. Arguments:
  283. none.
  284. Return Value:
  285. none.
  286. --*/
  287. {
  288. WsbTraceIn( L"CSakSnap::FinalRelease", L"" );
  289. WsbTraceOut( L"CSakSnap::FinalRelease", L"" );
  290. }
  291. HRESULT
  292. CSakSnap::FinalConstruct(
  293. void
  294. )
  295. /*++
  296. Routine Description:
  297. Called during initial CSakSnap construction to initialize members.
  298. Arguments:
  299. none.
  300. Return Value:
  301. S_OK - Initialized correctly.
  302. E_xxxxxxxxxxx - Failure occurred.
  303. --*/
  304. {
  305. WsbTraceIn( L"CSakSnap::FinalConstruct", L"" );
  306. HRESULT hr = CComObjectRoot::FinalConstruct( );
  307. m_ActiveNodeCookie = 0;
  308. m_pEnumeratedNode = NULL;
  309. //
  310. // Initialize column widths to 0
  311. //
  312. for( INT i = 0; i < BHSM_MAX_NODE_TYPES; i++ ) {
  313. m_ChildPropWidths[ i ].nodeTypeId = GUID_NULL;
  314. m_ChildPropWidths[ i ].colCount = 0;
  315. for ( INT j = 0; j < BHSM_MAX_CHILD_PROPS; j++ ) {
  316. m_ChildPropWidths[ i ].columnWidths[ j ] = 0;
  317. }
  318. }
  319. m_cChildPropWidths = 0;
  320. WsbTraceOut( L"CSakSnap::FinalConstruct", L"hr = <%ls>", WsbHrAsString( hr ) );
  321. return( hr );
  322. }
  323. HRESULT
  324. CSakSnap::InitResultPaneHeaders(
  325. ISakNode* pNode
  326. )
  327. /*++
  328. Routine Description:
  329. This functions sets up the result view header titles and widths.
  330. It should be called immediately prior to populating the result view.
  331. Arguments:
  332. pNode - Node whose contents will be shown.
  333. Return Value:
  334. S_OK - Initialized correctly.
  335. E_xxxxxxxxxxx - Failure occurred.
  336. --*/
  337. {
  338. WsbTraceIn( L"CSakSnap::InitResultPaneHeaders", L"pNode = <0x%p>", pNode );
  339. HRESULT hr = S_OK;
  340. HRESULT hrInternal = S_OK;
  341. BOOL bGotSavedWidths = FALSE;
  342. CComPtr<IEnumString> pEnumStr;
  343. try {
  344. WsbAffirmPointer( m_pHeader );
  345. WsbAffirmPointer( pNode );
  346. // Clean out any old columns in the result pane
  347. hrInternal = S_OK;
  348. while ( hrInternal == S_OK ) {
  349. hrInternal = m_pHeader->DeleteColumn( 0 );
  350. }
  351. // Get saved column widths (from CSakSnap) (they may not exist).
  352. INT columnWidths [ BHSM_MAX_CHILD_PROPS ];
  353. INT colCount;
  354. hrInternal = GetSavedColumnWidths( pNode, &colCount, columnWidths );
  355. if( hrInternal == S_OK ) {
  356. bGotSavedWidths = TRUE;
  357. }
  358. // Enumerate child display property column widths and create the columns with the correct
  359. // widths (but wrong titles).
  360. WsbAffirmHr( pNode->EnumChildDisplayPropWidths( &pEnumStr ) );
  361. if( pEnumStr ) {
  362. OLECHAR* str;
  363. // loop over the columns of display properties to get their widths.
  364. INT nCol = 0;
  365. while( pEnumStr->Next( 1, &str, NULL ) == S_OK ) {
  366. // Set the the next column width. Sometimes we may display more columns
  367. // than were saved - if so use the resource string for those columns. We
  368. // don't throw errors because this function can get called when (I think)
  369. // when the scope pane is displaying the nodes in the result pane and the
  370. // header functions will fail.
  371. if( bGotSavedWidths && ( nCol < colCount ) ) {
  372. hrInternal = m_pHeader->InsertColumn( nCol, str, LVCFMT_LEFT, columnWidths[ nCol ] );
  373. } else {
  374. hrInternal = m_pHeader->InsertColumn( nCol, str, LVCFMT_LEFT, MMCLV_AUTO );
  375. }
  376. nCol++;
  377. CoTaskMemFree( str );
  378. str = 0;
  379. }
  380. } else {
  381. hr = S_FALSE;
  382. }
  383. // Enumerate child display titles and use as correct column titles.
  384. pEnumStr = NULL;
  385. pNode->EnumChildDisplayTitles( &pEnumStr );
  386. if( pEnumStr ) {
  387. OLECHAR* str;
  388. // loop over the columns of display properties to get their titles.
  389. INT nCol = 0;
  390. while( pEnumStr->Next( 1, &str, NULL ) == S_OK ) {
  391. // Reset the strings in the titles of the headers. For some reason, it is NOW
  392. // acting as if 0 based.
  393. WsbAffirmHr( m_pHeader->SetColumnText( nCol, str ) );
  394. nCol++;
  395. CoTaskMemFree( str );
  396. str = 0;
  397. }
  398. } else {
  399. hr = S_FALSE;
  400. }
  401. } WsbCatch( hr );
  402. WsbTraceOut( L"CSakSnap::InitResultPaneHeaders", L"hr = <%ls>", WsbHrAsString( hr ) );
  403. return hr;
  404. }
  405. STDMETHODIMP
  406. CSakSnap::GetDisplayInfo(
  407. IN OUT RESULTDATAITEM * pResult
  408. )
  409. /*++
  410. Routine Description:
  411. When MMC is told to call back concerning resultview items,
  412. we receive a call here to fill in missing information (once per "cell"
  413. in the columns and rows of a "listview" style of result view).
  414. Note that the snapin manager automatically calls this method for the items
  415. appearing in the scope pane to render them in the result pane, and then it is
  416. called again for the items that appear only in the result pane as a result of
  417. our establishing the callback in EnumResultView.
  418. Arguments:
  419. pResult - RESULTDATAITEM structure representing state of the node
  420. in the result listview.
  421. Return Value:
  422. S_OK - Struct filled in.
  423. E_xxxxxxxxxxx - Failure occurred.
  424. --*/
  425. {
  426. static CWsbStringPtr tmpString;
  427. WsbTraceIn( L"CSakSnap::GetDisplayInfo", L"cookie = <0x%p>, pScopeItem->mask = <0x%p>, pResult->nCol = <%d>", pResult->lParam, pResult->mask, pResult->nCol );
  428. HRESULT hr = S_OK;
  429. try {
  430. WsbAffirmPointer( pResult );
  431. CComPtr<ISakNode> pNode; // basehsm interface for the node whose properties are being displayed.
  432. WsbAffirmHr( m_pSakData->GetBaseHsmFromCookie( pResult->lParam, &pNode ) );
  433. if( pResult->mask & RDI_IMAGE ) {
  434. WsbAffirmHr( pNode->GetResultIcon( m_pSakData->m_State, &pResult->nImage ) );
  435. }
  436. //
  437. // If the RESULTDATAITEM indicates that it needs a string...
  438. //
  439. if( pResult->mask & RDI_STR ) {
  440. //
  441. // Use the basehsm pointer to get the correct data to populate the listview.
  442. //
  443. DISPID dispid;
  444. CComPtr<IDispatch> pDisp; // dispatch interface
  445. CComPtr<ISakNode> pParentNode; // basehsm interface for the node's parent
  446. CWsbVariant varRet;
  447. CWsbStringPtr pPropString;
  448. //
  449. // Prepare an enumerator to look at each child property
  450. // (i.e. - column of info). Need to get the list of child properties from
  451. // the parent of this child.
  452. //
  453. CComPtr<IEnumString> pEnum;
  454. WsbAffirmHr( pNode->GetParent( &pParentNode ));
  455. //
  456. // If parentNode == 0, we are displaying our root node in the result pane
  457. // ( we are extending someone else ). Since the parent has determined the
  458. // columns to be name, type and description, we show that.
  459. //
  460. if( ! pParentNode ) {
  461. WsbAffirmHr( EnumRootDisplayProps( &pEnum ) );
  462. } else {
  463. WsbAffirmHr( pParentNode->EnumChildDisplayProps( &pEnum ) );
  464. }
  465. if( pEnum ) {
  466. //
  467. // Skip the correct number of columns to access
  468. // the exact column that we need.
  469. //
  470. if( pResult->nCol > 0 ) {
  471. WsbAffirmHr( pEnum->Skip( pResult->nCol ) );
  472. }
  473. WsbAffirmHr( pEnum->Next( 1, &pPropString, NULL ) );
  474. //
  475. // get the dispatch interface for this node
  476. //
  477. WsbAffirmHr( pNode->QueryInterface( IID_IDispatch, (void**)&pDisp ) );
  478. DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
  479. //
  480. // convert the property name to a dispatch id that can be invoked.
  481. // Invoke the interfaces to get the value of the cell.
  482. //
  483. WsbAffirmHr( pDisp->GetIDsOfNames( IID_NULL, &(pPropString), 1, LOCALE_USER_DEFAULT, &dispid ));
  484. WsbAffirmHr( pDisp->Invoke( dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
  485. &dispparamsNoArgs, &varRet, NULL, NULL) );
  486. tmpString = (OLECHAR*)varRet;
  487. }
  488. pResult->str = tmpString;
  489. }
  490. } WsbCatch( hr );
  491. WsbTraceOut( L"CSakSnap::GetDisplayInfo", L"hr = <%ls>, pResult->str = <%ls>, pResult->nImage = <%ls>", WsbHrAsString( hr ), (RDI_STR & pResult->mask) ? pResult->str : L"N/A", (RDI_IMAGE & pResult->mask) ? WsbLongAsString( pResult->nImage ) : L"N/A" );
  492. return( hr );
  493. }
  494. HRESULT CSakSnap::EnumRootDisplayProps( IEnumString ** ppEnum )
  495. {
  496. WsbTraceIn( L"CSakSnap::EnumRootDisplayProps", L"ppEnum = <0x%p>", ppEnum );
  497. HRESULT hr = S_OK;
  498. CEnumString * pEnum = 0;
  499. BSTR rgszRootPropIds[] = {L"DisplayName", L"Type", L"Description"};
  500. INT cRootPropsShow = 3;
  501. try {
  502. WsbAffirmPointer( ppEnum );
  503. WsbAffirm( cRootPropsShow > 0, S_FALSE );
  504. *ppEnum = 0;
  505. //
  506. // New an ATL enumerator
  507. //
  508. pEnum = new CEnumString;
  509. WsbAffirm( pEnum, E_OUTOFMEMORY );
  510. WsbAffirmHr( pEnum->FinalConstruct( ) );
  511. WsbAffirmHr( pEnum->Init( &rgszRootPropIds[0], &rgszRootPropIds[cRootPropsShow], NULL, AtlFlagCopy ) );
  512. WsbAffirmHr( pEnum->QueryInterface( IID_IEnumString, (void**)ppEnum ) );
  513. } WsbCatchAndDo( hr,
  514. if( pEnum ) delete pEnum;
  515. );
  516. WsbTraceOut( L"CSakSnap::EnumRootDisplayProps", L"hr = <%ls>, *ppEnum = <%ls>", WsbHrAsString( hr ), WsbPtrToPtrAsString( (void**)ppEnum ) );
  517. return( hr );
  518. }
  519. /////////////////////////////////////////////////////////////////////////////////////////
  520. //
  521. // IExtendPropertySheet Implementation.
  522. //
  523. STDMETHODIMP
  524. CSakSnap::CreatePropertyPages(
  525. IPropertySheetCallback* pPropSheetCallback,
  526. RS_NOTIFY_HANDLE handle,
  527. IDataObject* pDataObject
  528. )
  529. /*++
  530. Routine Description:
  531. Console calls this when it is building a property sheet to
  532. show for a node. It is also called for the data object given
  533. to represent the snapin to the snapin manager, and should
  534. show the initial selection page at that point.
  535. Arguments:
  536. pPropSheetCallback - MMC interface to use to add page.
  537. handle - Handle to MMC to use to add the page.
  538. pDataObject - Data object refering to node.
  539. Return Value:
  540. S_OK - Pages added.
  541. E_xxxxxxxxxxx - Failure occurred.
  542. --*/
  543. {
  544. WsbTraceIn( L"CSakSnap::CreatePropertyPages", L"pPropSheetCallback = <0x%p>, handle = <0x%p>, pDataObject = <0x%p>", pPropSheetCallback, handle, pDataObject );
  545. //
  546. // Delegate to CSakData
  547. //
  548. HRESULT hr = m_pSakData->CreatePropertyPages( pPropSheetCallback, handle, pDataObject );
  549. WsbTraceOut( L"CSakSnap::CreatePropertyPages", L"hr = <%ls>", WsbHrAsString( hr ) );
  550. return( hr );
  551. }
  552. STDMETHODIMP
  553. CSakSnap::QueryPagesFor(
  554. IDataObject* pDataObject
  555. )
  556. /*++
  557. Routine Description:
  558. This method is called by MMC when it wants to find out if this node
  559. supports property pages. The answer is yes if:
  560. 1) The MMC context is either for the scope pane or result pane, AND
  561. 2) The node actually DOES have property pages.
  562. OR
  563. 1) The Data Object is acquired by the snapin manager.
  564. Return S_OK if it DOES have pages, and S_FALSE if it does NOT have pages.
  565. Arguments:
  566. pDataObject - Data object refering to node.
  567. Return Value:
  568. S_OK - Pages exist.
  569. S_FALSE - No property pages.
  570. E_xxxxxxxxxxx - Failure occurred.
  571. --*/
  572. {
  573. WsbTraceIn( L"CSakSnap::QueryPagesFor", L"pDataObject = <0x%p>", pDataObject );
  574. HRESULT hr = m_pSakData->QueryPagesFor( pDataObject );
  575. WsbTraceOut( L"CSakSnap::QueryPagesFor", L"hr = <%ls>", WsbHrAsString( hr ) );
  576. return ( hr );
  577. }
  578. STDMETHODIMP
  579. CSakSnap::CompareObjects(
  580. IN IDataObject* pDataObjectA,
  581. IN IDataObject* pDataObjectB
  582. )
  583. /*++
  584. Routine Description:
  585. Compare data objects for MMC
  586. Arguments:
  587. pDataObjectA, - Data object refering to node.
  588. pDataObjectB
  589. Return Value:
  590. S_OK - Objects represent the same node.
  591. S_FALSE - Objects do not represent the same node.
  592. E_xxxxxxxxxxx - Failure occurred.
  593. --*/
  594. {
  595. HRESULT hr = S_OK;
  596. WsbTraceIn( L"CSakSnap::CompareObjects", L"pDataObjectA = <0x%p>, pDataObjectB = <0x%p>", pDataObjectA, pDataObjectB );
  597. hr = m_pSakData->CompareObjects( pDataObjectA, pDataObjectB );
  598. WsbTraceOut( L"CSakSnap::CompareObjects", L"hr = <%ls>", WsbHrAsString( hr ) );
  599. return ( hr );
  600. }
  601. /////////////////////////////////////////////////////////////////////////////////////////
  602. //
  603. // IPersistStream implementation
  604. //
  605. HRESULT
  606. CSakSnap::Save(
  607. IStream *pStm,
  608. BOOL fClearDirty
  609. )
  610. /*++
  611. Routine Description:
  612. Save the information we need to reconstruct the root node in the
  613. supplied stream.
  614. Arguments:
  615. pStm I: Console-supplied stream
  616. fClearDirty I: The console tells us to clear our dirty flag
  617. Return Value:
  618. S_OK - Saved successfully.
  619. E_* - Some error occurred.
  620. --*/
  621. {
  622. WsbTraceIn( L"CSakSnap::Save", L"pStm = <0x%p>, fClearDirty", pStm, WsbBoolAsString( fClearDirty ) );
  623. HRESULT hr = S_OK;
  624. INT index;
  625. INT jindex;
  626. try {
  627. ULONG version = HSMADMIN_CURRENT_VERSION;
  628. WsbAffirmHr( WsbSaveToStream( pStm, version ) );
  629. // Get the settings from the currently opened view
  630. if ( m_pEnumeratedNode ) {
  631. SaveColumnWidths( m_pEnumeratedNode );
  632. }
  633. // Save the number of different nodes
  634. WsbAffirmHr( WsbSaveToStream ( pStm, m_cChildPropWidths ) );
  635. // For each different node...
  636. for ( index = 0; index < m_cChildPropWidths; index++ ) {
  637. // Save the nodetype and column count
  638. WsbAffirmHr( WsbSaveToStream ( pStm, m_ChildPropWidths[ index ].nodeTypeId ) );
  639. WsbAffirmHr( WsbSaveToStream ( pStm, m_ChildPropWidths[ index ].colCount ) );
  640. // Save the column widths
  641. for ( jindex = 0; jindex < m_ChildPropWidths[ index ].colCount; jindex++ ) {
  642. WsbAffirmHr( WsbSaveToStream ( pStm, m_ChildPropWidths[ index ].columnWidths[ jindex ] ) );
  643. }
  644. }
  645. } WsbCatch ( hr );
  646. WsbTraceOut( L"CSakSnap::Save", L"hr = <%ls>", WsbHrAsString( hr ) );
  647. return( hr );
  648. }
  649. HRESULT
  650. CSakSnap::Load(
  651. IStream *pStm
  652. )
  653. /*++
  654. Routine Description:
  655. Load the information we need to reconstruct the root node from the
  656. supplied stream.
  657. Arguments:
  658. pStm IConsole-supplied stream
  659. Return Value:
  660. S_OK - Saved successfully.
  661. E_* - Some error occurred.
  662. --*/
  663. {
  664. WsbTraceIn( L"CSakSnap::Load", L"pStm = <0x%p>", pStm );
  665. HRESULT hr = S_OK;
  666. HRESULT hrInternal = S_OK;
  667. USHORT nodeCount;
  668. INT index;
  669. INT jindex;
  670. try {
  671. ULONG version = 0;
  672. WsbAffirmHr( WsbLoadFromStream( pStm, &version ) );
  673. WsbAssert( ( version == 1 ), E_FAIL );
  674. // Set to zero in case we fail part way through
  675. m_cChildPropWidths = 0;
  676. // If this fails, it probably means that nothing has been saved yet
  677. hrInternal = WsbLoadFromStream (pStm, &nodeCount);
  678. if ( hrInternal == S_OK ) {
  679. for ( index = 0; index < nodeCount; index++ ) {
  680. // Retrieve the nodetype and column count
  681. WsbAffirmHr( WsbLoadFromStream ( pStm, &( m_ChildPropWidths[ index ].nodeTypeId ) ) );
  682. WsbAffirmHr( WsbLoadFromStream ( pStm, &( m_ChildPropWidths[ index ].colCount ) ) );
  683. // Retrieve the column widths
  684. for ( jindex = 0; jindex < m_ChildPropWidths[ index ].colCount; jindex++ ) {
  685. WsbAffirmHr( WsbLoadFromStream ( pStm, &( m_ChildPropWidths[ index ].columnWidths[ jindex ] ) ) );
  686. }
  687. }
  688. m_cChildPropWidths = nodeCount;
  689. }
  690. WsbTraceOut( L"CSakSnap::Load", L"hr = <%ls>", WsbHrAsString( hr ) );
  691. } WsbCatch (hr);
  692. return( hr );
  693. }
  694. HRESULT
  695. CSakSnap::IsDirty(
  696. void
  697. )
  698. /*++
  699. Routine Description:
  700. The console asks us if we are dirty.
  701. Arguments:
  702. None
  703. Return Value:
  704. S_OK - Dirty.
  705. S_FALSE - Not Dirty.
  706. --*/
  707. {
  708. WsbTraceIn( L"CSakSnap::IsDirty", L"" );
  709. HRESULT hr = S_OK;
  710. WsbTraceOut( L"CSakSnap::IsDirty", L"hr = <%ls>", WsbHrAsString( hr ) );
  711. return( hr );
  712. }
  713. HRESULT
  714. CSakSnap::GetSizeMax(
  715. ULARGE_INTEGER *pcbSize
  716. )
  717. /*++
  718. Routine Description:
  719. Not currently used by the console
  720. Arguments:
  721. pcbSize
  722. Return Value:
  723. S_OK
  724. --*/
  725. {
  726. WsbTraceIn( L"CSakSnap::GetSizeMax", L"" );
  727. pcbSize->QuadPart = 256;
  728. HRESULT hr = S_OK;
  729. WsbTraceOut( L"CSakSnap::GetSizeMax", L"hr = <%ls>", WsbHrAsString( hr ) );
  730. return( hr );
  731. }
  732. HRESULT
  733. CSakSnap::GetClassID(
  734. CLSID *pClassID
  735. )
  736. /*++
  737. Routine Description:
  738. Not currently used by the console
  739. Arguments:
  740. pClassID - The class ID for the snapin
  741. Return Value:
  742. S_OK
  743. --*/
  744. {
  745. WsbTraceIn( L"CSakSnap::GetClassID", L"pClassID = <0x%p>", pClassID );
  746. HRESULT hr = S_OK;
  747. *pClassID = CLSID_HsmAdmin;
  748. WsbTraceOut( L"CSakSnap::GetClassID", L"hr = <%ls>, *pClassID = <%ls>", WsbHrAsString( hr ), WsbPtrToGuidAsString( pClassID ) );
  749. return( hr );
  750. }
  751. //////////////////////////////////////////////////////////////////////////////////
  752. //
  753. // Description: Add the supplied resource ID to the list of resource IDs for
  754. // the scope pane. Returns the index into the array.
  755. //
  756. INT CSakSnap::AddImage( UINT rId )
  757. {
  758. INT nIndex = 1;
  759. if (CSakSnap::m_nImageCount < RS_RESULT_IMAGE_ARRAY_MAX) {
  760. CSakSnap::m_nImageArray[CSakSnap::m_nImageCount] = rId;
  761. nIndex = CSakSnap::m_nImageCount;
  762. CSakSnap::m_nImageCount++;
  763. }
  764. return nIndex;
  765. }
  766. /////////////////////////////////////////////////////////////////////////////
  767. //
  768. // Adds images to the consoles image list from the static array
  769. //
  770. HRESULT CSakSnap::OnAddImages()
  771. {
  772. HRESULT hr = S_OK;
  773. HICON hIcon;
  774. AFX_MANAGE_STATE( AfxGetStaticModuleState( ) );
  775. try {
  776. //
  777. // References to the image list are now invalid
  778. //
  779. // Put the images from the static array into the image list
  780. // for the result pane
  781. for( INT i = 0; i < m_nImageCount; i++) {
  782. // Load the icon using the resource Id stored in the
  783. // static array and get the handle.
  784. hIcon = LoadIcon( _Module.m_hInst,
  785. MAKEINTRESOURCE( m_nImageArray [i] ) );
  786. // Add to the Console's Image list
  787. WsbAffirmHr( m_pImageResult->ImageListSetIcon( (RS_WIN32_HANDLE*)hIcon, i) );
  788. }
  789. } WsbCatch (hr);
  790. return hr;
  791. }
  792. HRESULT CSakSnap::SaveColumnWidths( ISakNode *pNode )
  793. {
  794. WsbTraceIn( L"CSakSnap::SaveColumnWidths", L"pNode = <0x%p>", pNode );
  795. HRESULT hr = S_OK;
  796. HRESULT hrInternal;
  797. INT columnWidth;
  798. GUID nodeTypeGuid;
  799. BOOL exists = FALSE;
  800. INT updateIndex = -1;
  801. INT col;
  802. try {
  803. WsbAssertPointer( pNode );
  804. // Get the type of the supplied node
  805. WsbAffirmHr( pNode->GetNodeType ( &nodeTypeGuid ) );
  806. // Search to see if the GUID already has an entry
  807. for ( INT index = 0; index < m_cChildPropWidths; index++ ) {
  808. if ( m_ChildPropWidths[ index ].nodeTypeId == nodeTypeGuid ) {
  809. updateIndex = index;
  810. exists = TRUE;
  811. }
  812. }
  813. if ( !exists ) {
  814. // Create a new entry
  815. WsbAssert( m_cChildPropWidths < BHSM_MAX_NODE_TYPES - 1, E_FAIL );
  816. updateIndex = m_cChildPropWidths;
  817. m_ChildPropWidths[ updateIndex ].nodeTypeId = nodeTypeGuid;
  818. m_cChildPropWidths++;
  819. }
  820. // Now set the column widths
  821. col = 0;
  822. hrInternal = S_OK;
  823. while ( hrInternal == S_OK ) {
  824. hrInternal = m_pHeader->GetColumnWidth( col, &columnWidth );
  825. if (hrInternal == S_OK) {
  826. m_ChildPropWidths[ updateIndex ].columnWidths[ col ] = (USHORT)columnWidth;
  827. col++;
  828. }
  829. }
  830. // if we failed totally to get column widths, don't wipe out the previous value
  831. if ( col > 0 ) {
  832. m_ChildPropWidths[ updateIndex ].colCount = (USHORT)col;
  833. }
  834. } WsbCatch (hr);
  835. WsbTraceOut( L"CSakSnap::SaveColumnWidths", L"hr = <%ls>", WsbHrAsString( hr ) );
  836. return hr;
  837. }
  838. HRESULT CSakSnap::GetSavedColumnWidths( ISakNode *pNode, INT *pColCount, INT *pColumnWidths )
  839. {
  840. WsbTraceIn( L"CSakSnap::SaveColumnWidths", L"pNode = <0x%p>", pNode );
  841. HRESULT hr = S_OK;
  842. GUID nodeTypeGuid;
  843. BOOL exists = FALSE;
  844. INT col;
  845. try {
  846. WsbAssertPointer( pNode );
  847. // Get the type of the supplied node
  848. WsbAffirmHr( pNode->GetNodeType ( &nodeTypeGuid ) );
  849. // Search to see if the GUID already has an entry
  850. for( INT index = 0; index < m_cChildPropWidths; index++ ) {
  851. if ( m_ChildPropWidths[ index ].nodeTypeId == nodeTypeGuid ) {
  852. for ( col = 0; col < m_ChildPropWidths[ index ].colCount; col++) {
  853. // Return the column widths
  854. pColumnWidths[ col ] = m_ChildPropWidths[ index ].columnWidths[ col ];
  855. }
  856. *pColCount = m_ChildPropWidths[ index ].colCount;
  857. exists = TRUE;
  858. }
  859. }
  860. if ( !exists ) {
  861. return WSB_E_NOTFOUND;
  862. }
  863. } WsbCatch (hr);
  864. WsbTraceOut( L"CSakSnap::SaveColumnWidths", L"hr = <%ls>", WsbHrAsString( hr ) );
  865. return hr;
  866. }
  867. ///////////////////////////////////////////////////////////////////////////////
  868. // IExtendControlbar implementation
  869. //
  870. STDMETHODIMP CSakSnap::SetControlbar(LPCONTROLBAR pControlbar)
  871. {
  872. WsbTraceIn( L"CSakSnap::SetControlbar", L"pControlbar = <0x%p>", pControlbar );
  873. HRESULT hr = S_OK;
  874. try {
  875. //
  876. // Clear out old controlbar
  877. //
  878. if( m_pControlbar && m_pToolbar ) {
  879. m_pControlbar->Detach( m_pToolbar );
  880. }
  881. m_pToolbar.Release( );
  882. m_pControlbar.Release( );
  883. //
  884. // Hold on to the controlbar interface.
  885. //
  886. m_pControlbar = pControlbar;
  887. } WsbCatch( hr );
  888. WsbTraceOut( L"CSakSnap::SetControlbar", L"hr = <%ls>", WsbHrAsString( hr ) );
  889. return( hr );
  890. }
  891. STDMETHODIMP CSakSnap::ControlbarNotify( MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param )
  892. {
  893. WsbTraceIn( L"CSakSnap::ControlbarNotify", L"" );
  894. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  895. HRESULT hr = S_FALSE;
  896. switch( event ) {
  897. case MMCN_BTN_CLICK:
  898. hr = OnToolbarButtonClick( arg, param );
  899. break;
  900. case MMCN_DESELECT_ALL:
  901. break;
  902. case MMCN_SELECT:
  903. OnSelectToolbars( arg, param );
  904. break;
  905. case MMCN_MENU_BTNCLICK:
  906. // HandleExtMenus(arg, param);
  907. break;
  908. default:
  909. break;
  910. }
  911. WsbTraceOut( L"CSakSnap::ControlbarNotify", L"hr = <%ls>", WsbHrAsString( hr ) );
  912. return( hr );
  913. }
  914. HRESULT CSakSnap::OnToolbarButtonClick( LPARAM arg, LPARAM cmdId )
  915. {
  916. WsbTraceIn( L"CSakSnap::OnToolbarButtonClick", L"arg = <0x%p>, cmdId = <%ld>" );
  917. HRESULT hr = S_OK;
  918. try {
  919. IDataObject* pDataObject = (IDataObject*)arg;
  920. WsbAffirmPointer( pDataObject );
  921. CComPtr<ISakNode> pNode;
  922. WsbAffirmHr( m_pSakData->GetBaseHsmFromDataObject( pDataObject, &pNode ) );
  923. // Delegate to the node
  924. WsbAffirmHr( pNode->OnToolbarButtonClick( pDataObject, (LONG)cmdId ) );
  925. } WsbCatch( hr );
  926. WsbTraceOut( L"CSakSnap::OnToolbarButtonClick", L"hr = <%ls>", WsbHrAsString( hr ) );
  927. return( hr );
  928. }
  929. void CSakSnap::OnSelectToolbars(LPARAM arg, LPARAM param)
  930. {
  931. HRESULT hr = S_OK;
  932. try {
  933. BOOL bScope = (BOOL) LOWORD( arg );
  934. BOOL bSelect = (BOOL) HIWORD( arg );
  935. IDataObject* pDataObject = (IDataObject*)param;
  936. WsbAffirmPointer( pDataObject );
  937. CComPtr<ISakNode> pNode;
  938. WsbAffirmHr( m_pSakData->GetBaseHsmFromDataObject( pDataObject, &pNode ) );
  939. if( bSelect ) {
  940. //
  941. // ATL detaches any existing toolbar before attaching new ones.
  942. // This appears to fix issues of us adding toolbar upon toolbar
  943. //
  944. if( m_pToolbar ) {
  945. m_pControlbar->Detach( m_pToolbar );
  946. m_pToolbar.Release( );
  947. }
  948. //
  949. // Does the node have a toolbar?
  950. //
  951. if( pNode->HasToolbar() == S_OK ) {
  952. //
  953. // Create the toolbar for the indicated node
  954. //
  955. WsbAffirmHr( m_pControlbar->Create( TOOLBAR, this, reinterpret_cast<LPUNKNOWN*>(&m_pToolbar) ) );
  956. //
  957. // Returns S_FALSE if there is no toolbar for the node
  958. //
  959. if( pNode->SetupToolbar( m_pToolbar ) == S_OK ) {
  960. //
  961. // Attach the toolbar
  962. //
  963. WsbAffirmHr( m_pControlbar->Attach( TOOLBAR, (IUnknown*) m_pToolbar ) );
  964. }
  965. }
  966. } else {
  967. //
  968. // Destroy the toolbar
  969. // NOTE: Not done in ATL snapin classes
  970. //
  971. if( m_pToolbar ) {
  972. m_pControlbar->Detach( m_pToolbar );
  973. }
  974. m_pToolbar.Release();
  975. }
  976. } WsbCatch( hr );
  977. }
  978. STDMETHODIMP
  979. CSakSnap::Compare(
  980. IN LPARAM /*lUserParam*/,
  981. IN MMC_COOKIE CookieA,
  982. IN MMC_COOKIE CookieB,
  983. IN OUT int* pnResult
  984. )
  985. {
  986. HRESULT hr = S_OK;
  987. try {
  988. //
  989. // Store column and set result to 'equal' ASAP
  990. //
  991. WsbAffirmPointer( pnResult );
  992. int col = *pnResult;
  993. *pnResult = 0;
  994. //
  995. // And make sure we have a node we know we're showing
  996. //
  997. WsbAffirmPointer( m_pEnumeratedNode );
  998. CComPtr<ISakNode> pNodeA, pNodeB;
  999. CComPtr<IDispatch> pDispA, pDispB;
  1000. WsbAffirmHr( m_pSakData->GetBaseHsmFromCookie( CookieA, &pNodeA ) );
  1001. WsbAffirmHr( m_pSakData->GetBaseHsmFromCookie( CookieB, &pNodeB ) );
  1002. WsbAffirmHr( pNodeA.QueryInterface( &pDispA ) );
  1003. WsbAffirmHr( pNodeB.QueryInterface( &pDispB ) );
  1004. CComPtr<IEnumString> pEnum;
  1005. WsbAffirmHrOk( m_pEnumeratedNode->EnumChildDisplayProps( &pEnum ) );
  1006. //
  1007. // Skip the correct number of columns to access
  1008. // the exact column that we need.
  1009. //
  1010. if( col > 0 ) {
  1011. WsbAffirmHr( pEnum->Skip( col ) );
  1012. }
  1013. CWsbVariant varRetA, varRetB;
  1014. CWsbStringPtr pPropString;
  1015. WsbAffirmHrOk( pEnum->Next( 1, &pPropString, NULL ) );
  1016. WsbAffirmHr( pPropString.Append( L"_SortKey" ) );
  1017. //
  1018. // convert the property name to a dispatch id that can be invoked.
  1019. // Invoke the interfaces to get the value of the cell.
  1020. //
  1021. DISPID dispid;
  1022. DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
  1023. WsbAffirmHr( pDispA->GetIDsOfNames( IID_NULL, &(pPropString), 1, LOCALE_USER_DEFAULT, &dispid ));
  1024. WsbAffirmHr(
  1025. pDispA->Invoke(
  1026. dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
  1027. &dispparamsNoArgs, &varRetA, NULL, NULL ) );
  1028. WsbAffirmHr(
  1029. pDispB->Invoke(
  1030. dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
  1031. &dispparamsNoArgs, &varRetB, NULL, NULL ) );
  1032. WsbAffirmPointer( (WCHAR*)varRetA );
  1033. WsbAffirmPointer( (WCHAR*)varRetB );
  1034. *pnResult = _wcsicmp( (WCHAR*)varRetA, (WCHAR*)varRetB );
  1035. //
  1036. // If results are that they are the same (and not first column)
  1037. // than compare the first column (the Name)
  1038. //
  1039. if( ( 0 == *pnResult ) && ( col > 0 ) ) {
  1040. *pnResult = 0; // Compare first Column if same
  1041. WsbAffirmHr( Compare( 0, CookieA, CookieB, pnResult ) );
  1042. }
  1043. WsbTrace( L"CSakSnap::Compare: *pnResult = <%ls>, SortKeyA = <%ls>, SortKeyB = <%ls>\n", WsbPtrToLongAsString( (LONG*)pnResult ), (WCHAR*)varRetA, (WCHAR*)varRetB );
  1044. } WsbCatch( hr );
  1045. return( hr );
  1046. }