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.

1334 lines
33 KiB

  1. //
  2. // cmponent.cpp : Declaration of Component.
  3. //
  4. // This COM object is primarily concerned with
  5. // the result pane items.
  6. //
  7. // Cory West <[email protected]>
  8. // Copyright (c) Microsoft Corporation 1997
  9. //
  10. #include "stdafx.h"
  11. #include "macros.h"
  12. USE_HANDLE_MACROS("SCHMMGMT(cmponent.cpp)")
  13. #include "dataobj.h"
  14. #include "cmponent.h" // Component
  15. #include "compdata.h" // ComponentData
  16. #include "schmutil.h"
  17. #include "attrgen.hpp"
  18. #include "stdcmpnt.cpp" // CComponent
  19. //
  20. // These arrays describe the result pane layout for when
  21. // any particular object is selected.
  22. //
  23. UINT
  24. g_aColumns0[5] = {
  25. IDS_COLUMN_NAME,
  26. IDS_COLUMN_TYPE,
  27. IDS_COLUMN_STATUS,
  28. IDS_COLUMN_DESCRIPTION,
  29. 0
  30. };
  31. UINT
  32. g_aColumns1[5] = {
  33. IDS_COLUMN_NAME,
  34. IDS_COLUMN_SYNTAX,
  35. IDS_COLUMN_STATUS,
  36. IDS_COLUMN_DESCRIPTION,
  37. 0
  38. };
  39. UINT
  40. g_aColumns2[6] = {
  41. IDS_COLUMN_NAME,
  42. IDS_COLUMN_TYPE,
  43. IDS_COLUMN_SYSTEM,
  44. IDS_COLUMN_DESCRIPTION,
  45. IDS_COLUMN_PARENT,
  46. 0
  47. };
  48. UINT
  49. g_aColumns3[2] =
  50. {
  51. IDS_COLUMN_NAME,
  52. 0
  53. };
  54. UINT*
  55. g_Columns[SCHMMGMT_NUMTYPES] = {
  56. g_aColumns3, // SCHMMGMT_SCHMMGMT
  57. g_aColumns0, // SCHMMGMT_CLASSES
  58. g_aColumns1, // SCHMMGMT_ATTRIBUTES
  59. g_aColumns2, // SCHMMGMT_CLASS
  60. g_aColumns0, // SCHMMGMT_ATTRIBUTE // @@ Is this used?
  61. };
  62. UINT** g_aColumns = g_Columns;
  63. //
  64. // These control the column widths, which I will not change.
  65. //
  66. int g_aColumnWidths0[4] = {150,150,75,150};
  67. int g_aColumnWidths1[5] = {150,75,75,150,150};
  68. int g_aColumnWidths2[1] = {150};
  69. int* g_ColumnWidths[SCHMMGMT_NUMTYPES] = {
  70. g_aColumnWidths2, // SCHMMGMT_SCHMMGMT
  71. g_aColumnWidths0, // SCHMMGMT_CLASSES
  72. g_aColumnWidths0, // SCHMMGMT_ATTRIBUTES
  73. g_aColumnWidths1, // SCHMMGMT_CLASS
  74. g_aColumnWidths0, // SCHMMGMT_ATTRIBUTE
  75. };
  76. int** g_aColumnWidths = g_ColumnWidths;
  77. //
  78. // Constructors and destructors.
  79. //
  80. Component::Component()
  81. : m_pSvcMgmtToolbar( NULL ),
  82. m_pSchmMgmtToolbar( NULL ),
  83. m_pControlbar( NULL ),
  84. m_bDirty(false)
  85. {
  86. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  87. m_pViewedCookie = NULL;
  88. }
  89. Component::~Component()
  90. {
  91. TRACE_METHOD(Component,Destructor);
  92. VERIFY( SUCCEEDED(ReleaseAll()) );
  93. }
  94. HRESULT Component::ReleaseAll()
  95. {
  96. MFC_TRY;
  97. TRACE_METHOD(Component,ReleaseAll);
  98. SAFE_RELEASE(m_pSvcMgmtToolbar);
  99. SAFE_RELEASE(m_pSchmMgmtToolbar);
  100. SAFE_RELEASE(m_pControlbar);
  101. return CComponent::ReleaseAll();
  102. MFC_CATCH;
  103. }
  104. //
  105. // Support routines in ISchmMgmtComponent.
  106. //
  107. HRESULT
  108. Component::LoadColumns(
  109. Cookie* pcookie
  110. ) {
  111. TEST_NONNULL_PTR_PARAM(pcookie);
  112. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  113. return LoadColumnsFromArrays( (INT)(pcookie->m_objecttype) );
  114. }
  115. HRESULT
  116. Component::OnViewChange(
  117. LPDATAOBJECT,
  118. LPARAM data,
  119. LPARAM function
  120. )
  121. /***
  122. This is called when IConsole->UpdateAllViews() is called.
  123. The data is a schema object type as follows:
  124. if function == 0 (SCHMMGMT_UPDATEVIEW_REFRESH)
  125. SCHMMGMT_ATTIBUTES - We need to refresh the attributes
  126. folder displays.
  127. SCHMMGMT_CLASS - We need to refresh _ALL_ class attribute
  128. displays. We don't try and trace the inheritance
  129. graphs and do a selective refresh, that's too complicated.
  130. SCHMMGMT_SCHMMGMT - Refresh EVERYTHING because we reloaded
  131. the schema cache.
  132. else if function == 1 (SCHMMGMT_UPDATEVIEW_DELETE_RESULT_ITEM)
  133. data is the Cookie pointer
  134. ***/
  135. {
  136. //
  137. // Refresh this result view.
  138. //
  139. if ( function == SCHMMGMT_UPDATEVIEW_REFRESH )
  140. {
  141. if ( m_pViewedCookie ) {
  142. if ( ( data == m_pViewedCookie->m_objecttype ) ||
  143. ( data == SCHMMGMT_SCHMMGMT ) ) {
  144. m_pResultData->DeleteAllRsltItems();
  145. PopulateListbox( m_pViewedCookie );
  146. }
  147. }
  148. }
  149. else if ( function == SCHMMGMT_UPDATEVIEW_DELETE_RESULT_ITEM )
  150. {
  151. HRESULTITEM item;
  152. // FUTURE-2002-03/94/2002-dantra-Although this is a safe usage of ZeroMemory, suggest changing
  153. // the definition of item to HRESULTITEM item = {0}; and removing the ZeroMemory call.
  154. ZeroMemory( &item, sizeof(HRESULTITEM) );
  155. HRESULT hr = m_pResultData->FindItemByLParam( data, &item );
  156. if ( SUCCEEDED(hr) )
  157. {
  158. hr = m_pResultData->DeleteItem( item, 0 );
  159. ASSERT( SUCCEEDED(hr) );
  160. }
  161. }
  162. return S_OK;
  163. }
  164. HRESULT
  165. Component::OnNotifySelect( LPDATAOBJECT lpDataObject, BOOL )
  166. /***
  167. This called in response to MMCN_SELECT.
  168. This routine will set the default verb and enable the toolbar buttons.
  169. ***/
  170. {
  171. CCookie* pBaseParentCookie = NULL;
  172. HRESULT hr = ExtractData( lpDataObject,
  173. CSchmMgmtDataObject::m_CFRawCookie,
  174. OUT reinterpret_cast<PBYTE>(&pBaseParentCookie),
  175. sizeof(pBaseParentCookie) );
  176. ASSERT( SUCCEEDED(hr) );
  177. Cookie* pParentCookie = ActiveCookie(pBaseParentCookie);
  178. ASSERT( NULL != pParentCookie );
  179. m_pConsoleVerb->SetVerbState(MMC_VERB_REFRESH,ENABLED,TRUE);
  180. switch ( pParentCookie->m_objecttype ) {
  181. case SCHMMGMT_CLASSES:
  182. case SCHMMGMT_ATTRIBUTES:
  183. break;
  184. case SCHMMGMT_CLASS:
  185. {
  186. //
  187. // Set the default verb to display the properties of the selected object.
  188. //
  189. m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, TRUE);
  190. m_pConsoleVerb->SetDefaultVerb(MMC_VERB_PROPERTIES);
  191. // if the schema class is defunct and the forest version is Whistler or higher
  192. // then allow delete
  193. /* Feature was removed for Whistler
  194. ComponentData& Scope = QueryComponentDataRef();
  195. if ( Scope.GetBasePathsInfo()->GetForestBehaviorVersion() >= 2)
  196. {
  197. SchemaObject *pSchemaObject = Scope.g_SchemaCache.LookupSchemaObjectByCN(
  198. pParentCookie->strSchemaObject,
  199. SCHMMGMT_CLASS );
  200. if ( pSchemaObject &&
  201. pSchemaObject->isDefunct )
  202. {
  203. m_pConsoleVerb->SetVerbState(MMC_VERB_DELETE, ENABLED, TRUE);
  204. }
  205. }
  206. */
  207. }
  208. break;
  209. case SCHMMGMT_ATTRIBUTE:
  210. if ( ( pParentCookie->m_objecttype == SCHMMGMT_ATTRIBUTE ) &&
  211. ( pParentCookie->pParentCookie ) &&
  212. ( pParentCookie->pParentCookie->m_objecttype == SCHMMGMT_ATTRIBUTES ) ) {
  213. //
  214. // Set the default verb to display the properties of the selected object.
  215. //
  216. m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, TRUE);
  217. m_pConsoleVerb->SetDefaultVerb(MMC_VERB_PROPERTIES);
  218. // if the schema class is defunct and the forest version is Whistler or higher
  219. // then allow delete
  220. /* Feature was removed for Whistler
  221. ComponentData& Scope = QueryComponentDataRef();
  222. if ( Scope.GetBasePathsInfo()->GetForestBehaviorVersion() >= 2)
  223. {
  224. SchemaObject *pSchemaObject = Scope.g_SchemaCache.LookupSchemaObjectByCN(
  225. pParentCookie->strSchemaObject,
  226. SCHMMGMT_ATTRIBUTE );
  227. if ( pSchemaObject &&
  228. pSchemaObject->isDefunct )
  229. {
  230. m_pConsoleVerb->SetVerbState(MMC_VERB_DELETE, ENABLED, TRUE);
  231. }
  232. }
  233. */
  234. } else {
  235. m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, HIDDEN, TRUE);
  236. }
  237. break;
  238. default:
  239. //
  240. // Otherwise set the default verb to open/expand the folder.
  241. //
  242. m_pConsoleVerb->SetDefaultVerb(MMC_VERB_OPEN);
  243. break;
  244. }
  245. return S_OK;
  246. }
  247. HRESULT
  248. Component::Show(
  249. CCookie* pcookie,
  250. LPARAM arg,
  251. HSCOPEITEM hScopeItem
  252. )
  253. /***
  254. This is called in response to MMCN_SHOW.
  255. ***/
  256. {
  257. TEST_NONNULL_PTR_PARAM(pcookie);
  258. HRESULT hr = S_OK;
  259. do
  260. {
  261. if ( TRUE == arg ) // showing...
  262. {
  263. if( QueryComponentDataRef().IsSetDelayedRefreshOnShow() )
  264. {
  265. HSCOPEITEM hItem = QueryComponentDataRef().GetDelayedRefreshOnShowItem();
  266. ASSERT( hItem == hScopeItem );
  267. QueryComponentDataRef().SetDelayedRefreshOnShow( NULL );
  268. hr = m_pConsole->SelectScopeItem( hItem ); // will call GetResultViewType & Show
  269. ASSERT_BREAK_ON_FAILED_HRESULT(hr);
  270. }
  271. else if( QueryComponentDataRef().IsErrorSet() )
  272. {
  273. CComPtr<IUnknown> pUnknown;
  274. CComPtr<IMessageView> pMessageView;
  275. hr = m_pConsole->QueryResultView(&pUnknown);
  276. ASSERT_BREAK_ON_FAILED_HRESULT(hr);
  277. hr = pUnknown->QueryInterface(IID_IMessageView, (PVOID*)&pMessageView);
  278. ASSERT_BREAK_ON_FAILED_HRESULT(hr);
  279. pMessageView->SetTitleText( CComBSTR( QueryComponentDataRef().GetErrorTitle() ) );
  280. pMessageView->SetBodyText( CComBSTR( QueryComponentDataRef().GetErrorText() ) );
  281. pMessageView->SetIcon(Icon_Error);
  282. }
  283. else
  284. {
  285. m_pViewedCookie = (Cookie*)pcookie;
  286. LoadColumns( m_pViewedCookie );
  287. hr = PopulateListbox( m_pViewedCookie );
  288. }
  289. }
  290. else // hiding...
  291. {
  292. if( !QueryComponentDataRef().IsErrorSet() )
  293. {
  294. if ( NULL == m_pResultData )
  295. {
  296. ASSERT( FALSE );
  297. hr = E_UNEXPECTED;
  298. break;
  299. }
  300. m_pViewedCookie = NULL;
  301. }
  302. }
  303. } while( FALSE );
  304. return hr;
  305. }
  306. HRESULT
  307. Component::OnNotifyAddImages(
  308. LPDATAOBJECT,
  309. LPIMAGELIST lpImageList,
  310. HSCOPEITEM
  311. )
  312. /***
  313. This routine is called in response to MMCN_ADD_IMAGES. Here's
  314. what mmc.idl says about this:
  315. Sent to IComponent to add images for the result pane. The
  316. primary snapin should add images for both folders and leaf items.
  317. arg = ptr to result panes IImageList.
  318. param = HSCOPEITEM of selected/deselected item
  319. ***/
  320. {
  321. return QueryComponentDataRef().LoadIcons(lpImageList,TRUE);
  322. }
  323. HRESULT
  324. Component::OnNotifyDelete(
  325. LPDATAOBJECT lpDataObject)
  326. {
  327. CThemeContextActivator activator;
  328. CCookie* pBaseParentCookie = NULL;
  329. HRESULT hr = ExtractData( lpDataObject,
  330. CSchmMgmtDataObject::m_CFRawCookie,
  331. reinterpret_cast<PBYTE>(&pBaseParentCookie),
  332. sizeof(pBaseParentCookie) );
  333. ASSERT( SUCCEEDED(hr) );
  334. Cookie* pParentCookie = ActiveCookie(pBaseParentCookie);
  335. ASSERT( NULL != pParentCookie );
  336. UINT promptID = 0;
  337. LPARAM updateType = SCHMMGMT_CLASS;
  338. if (pParentCookie->m_objecttype == SCHMMGMT_CLASS)
  339. {
  340. promptID = IDS_DELETE_CLASS_PROMPT;
  341. updateType = SCHMMGMT_CLASS;
  342. }
  343. else if (pParentCookie->m_objecttype == SCHMMGMT_ATTRIBUTE)
  344. {
  345. promptID = IDS_DELETE_ATTR_PROMPT;
  346. updateType = SCHMMGMT_ATTRIBUTES;
  347. }
  348. else
  349. {
  350. // We should never get called to delete anything but
  351. // class and attribute nodes
  352. ASSERT(FALSE);
  353. return E_FAIL;
  354. }
  355. if( IDYES == AfxMessageBox( promptID, MB_YESNO | MB_ICONWARNING ))
  356. {
  357. hr = DeleteAttribute(pParentCookie);
  358. if ( SUCCEEDED(hr) )
  359. {
  360. // Remove the node from the UI
  361. hr = m_pConsole->UpdateAllViews( lpDataObject,
  362. (LPARAM)pParentCookie,
  363. SCHMMGMT_UPDATEVIEW_DELETE_RESULT_ITEM );
  364. ASSERT( SUCCEEDED(hr) );
  365. }
  366. else
  367. {
  368. CString szDeleteError;
  369. szDeleteError.Format(IDS_ERRMSG_DELETE_FAILED_ATTRIBUTE, GetErrorMessage(hr, TRUE));
  370. DoErrMsgBox( ::GetActiveWindow(), TRUE, szDeleteError );
  371. }
  372. }
  373. return hr;
  374. }
  375. HRESULT
  376. Component::DeleteAttribute(
  377. Cookie* pcookie
  378. )
  379. /***
  380. This deletes an attribute from the schema
  381. ***/
  382. {
  383. HRESULT hr = S_OK;
  384. do
  385. {
  386. if ( !pcookie )
  387. {
  388. hr = E_INVALIDARG;
  389. break;
  390. }
  391. ComponentData& Scope = QueryComponentDataRef();
  392. SchemaObject* pObject = Scope.g_SchemaCache.LookupSchemaObjectByCN(
  393. pcookie->strSchemaObject,
  394. SCHMMGMT_ATTRIBUTE );
  395. if ( !pObject )
  396. {
  397. hr = E_FAIL;
  398. break;
  399. }
  400. CString szAdsPath;
  401. Scope.GetSchemaObjectPath( pObject->commonName, szAdsPath );
  402. hr = DeleteObject( szAdsPath, pcookie, g_AttributeFilter );
  403. } while (false);
  404. return hr;
  405. }
  406. HRESULT
  407. Component::PopulateListbox(
  408. Cookie* pcookie
  409. )
  410. /***
  411. This populates the result pane when the result pane
  412. contains data that is not directly derived from the
  413. data in the scope pane.
  414. ***/
  415. {
  416. switch ( pcookie->m_objecttype ) {
  417. case SCHMMGMT_SCHMMGMT:
  418. case SCHMMGMT_CLASSES:
  419. //
  420. // We don't care about these - the result
  421. // pane contains only scope items.
  422. //
  423. break;
  424. case SCHMMGMT_ATTRIBUTES:
  425. //
  426. // List the specified items in the result pane
  427. // with some informational data.
  428. //
  429. return FastInsertAttributeResultCookies(
  430. pcookie );
  431. break;
  432. case SCHMMGMT_CLASS:
  433. //
  434. // This results in the attributes used in this
  435. // class and other class data being displayed.
  436. //
  437. return FastInsertClassAttributesResults( pcookie );
  438. break;
  439. case SCHMMGMT_ATTRIBUTE:
  440. //
  441. // This is not a scope pane item and can have no
  442. // corresponding result pane data!!
  443. //
  444. ASSERT(FALSE);
  445. break;
  446. }
  447. return S_OK;
  448. }
  449. HRESULT
  450. Component::FastInsertAttributeResultCookies(
  451. Cookie* pParentCookie
  452. )
  453. /***
  454. When the "Attributes" folder is selected, this puts
  455. the attributes in the result pane.
  456. pParentCookie is the cookie for the parent object.
  457. This routine is similar to
  458. ComponentData::FastInsertClassScopeCookies.
  459. ****/
  460. {
  461. HRESULT hr;
  462. SchemaObject *pObject, *pHead;
  463. Cookie *pNewCookie;
  464. RESULTDATAITEM ResultItem;
  465. LPCWSTR lpcszMachineName = pParentCookie->QueryNonNULLMachineName();
  466. ComponentData& Scope = QueryComponentDataRef();
  467. //
  468. // Initialize the result item.
  469. //
  470. // FUTURE-2002-03/94/2002-dantra-Although this is a safe usage of ZeroMemory, suggest changing
  471. // the definition RESULTDATAITEM ResultItem = {0} and removing the ZeroMemory call.
  472. ::ZeroMemory( &ResultItem, sizeof( ResultItem ) );
  473. ResultItem.nCol = 0;
  474. ResultItem.mask = RDI_STR | RDI_IMAGE | RDI_PARAM;
  475. ResultItem.str = MMC_CALLBACK;
  476. ResultItem.nImage = iIconAttribute;
  477. //
  478. // Rather than having a clean class interface to the cache, we
  479. // walk the cache data structures ourselves. This isn't super
  480. // clean, but it's simple.
  481. //
  482. // Since we do this, we have to make sure that the cache is loaded.
  483. //
  484. Scope.g_SchemaCache.LoadCache();
  485. pObject = Scope.g_SchemaCache.pSortedAttribs;
  486. //
  487. // If there's no sorted list, we can't insert anything!!!!
  488. //
  489. if ( !pObject ) {
  490. ASSERT( FALSE );
  491. DoErrMsgBox( ::GetActiveWindow(), TRUE, IDS_ERR_NO_SCHEMA_PATH );
  492. return S_OK;
  493. }
  494. //
  495. // Delete whatever was in the view before
  496. // and do the insert.
  497. //
  498. pHead = pObject;
  499. do {
  500. if ( Scope.m_fViewDefunct || !pObject->isDefunct )
  501. {
  502. //
  503. // Insert this result.
  504. //
  505. pNewCookie= new Cookie( SCHMMGMT_ATTRIBUTE,
  506. lpcszMachineName );
  507. if ( pNewCookie ) {
  508. pNewCookie->pParentCookie = pParentCookie;
  509. pNewCookie->strSchemaObject = pObject->commonName;
  510. pParentCookie->m_listScopeCookieBlocks.AddHead(
  511. (CBaseCookieBlock*)pNewCookie
  512. );
  513. ResultItem.lParam = reinterpret_cast<LPARAM>((CCookie*)pNewCookie);
  514. hr = m_pResultData->InsertItem( &ResultItem );
  515. if ( SUCCEEDED(hr) ) {
  516. pNewCookie->SetResultHandle( ResultItem.itemID );
  517. } else {
  518. delete pNewCookie;
  519. }
  520. }
  521. }
  522. pObject = pObject->pSortedListFlink;
  523. } while ( pObject != pHead );
  524. return S_OK;
  525. }
  526. HRESULT
  527. Component::FastInsertClassAttributesResults(
  528. Cookie* pClassCookie
  529. )
  530. /***
  531. This routine displays all the attributes for a class.
  532. ***/
  533. {
  534. HRESULT hr = S_OK;
  535. SchemaObject *pObject, *pTop;
  536. CString top = L"top";
  537. ComponentData& Scope = QueryComponentDataRef();
  538. //
  539. // Call the attribute display routine. This routine
  540. // will call itself recursively to display the
  541. // inheritance structure of the class.
  542. //
  543. pObject = Scope.g_SchemaCache.LookupSchemaObjectByCN(
  544. pClassCookie->strSchemaObject,
  545. SCHMMGMT_CLASS );
  546. if ( pObject ) {
  547. CStringList szProcessedList;
  548. hr = RecursiveDisplayClassAttributesResults(
  549. pClassCookie,
  550. pObject,
  551. szProcessedList);
  552. Scope.g_SchemaCache.ReleaseRef( pObject );
  553. }
  554. //
  555. // Process "top" just once.
  556. //
  557. pTop = Scope.g_SchemaCache.LookupSchemaObject( top, SCHMMGMT_CLASS );
  558. if ( pTop ) {
  559. ProcessResultList( pClassCookie, pTop->systemMayContain, TRUE, TRUE, pTop );
  560. ProcessResultList( pClassCookie, pTop->mayContain, TRUE, FALSE, pTop );
  561. ProcessResultList( pClassCookie, pTop->systemMustContain, FALSE, TRUE, pTop );
  562. ProcessResultList( pClassCookie, pTop->mustContain, FALSE, FALSE, pTop );
  563. Scope.g_SchemaCache.ReleaseRef( pTop );
  564. }
  565. return hr;
  566. }
  567. HRESULT
  568. Component::RecursiveDisplayClassAttributesResults(
  569. Cookie *pParentCookie,
  570. SchemaObject* pObject,
  571. CStringList& szProcessedList
  572. )
  573. /***
  574. Display all the attributes for this class.
  575. ***/
  576. {
  577. ListEntry *pList;
  578. SchemaObject *pInheritFrom;
  579. ComponentData& Scope = QueryComponentDataRef();
  580. //
  581. // Don't process "top" here since everyone inherits from it.
  582. //
  583. if ( pObject->ldapDisplayName == L"top" ) {
  584. return S_OK;
  585. }
  586. DebugTrace( L"RecursiveDisplayClassAttributesResults: %ls\n",
  587. const_cast<LPWSTR>((LPCTSTR)pObject->ldapDisplayName) );
  588. //
  589. // Insert all the attributes for this class.
  590. // The second parameter dictates whether these
  591. // are optional or not. The third parameter
  592. // is the source of the attribute.
  593. //
  594. ProcessResultList( pParentCookie, pObject->systemMayContain, TRUE, TRUE, pObject );
  595. ProcessResultList( pParentCookie, pObject->mayContain, TRUE, FALSE, pObject );
  596. ProcessResultList( pParentCookie, pObject->systemMustContain, FALSE, TRUE, pObject );
  597. ProcessResultList( pParentCookie, pObject->mustContain, FALSE, FALSE, pObject );
  598. //
  599. // For each auxiliary class, insert those attributes.
  600. //
  601. pList = pObject->systemAuxiliaryClass;
  602. while ( pList ) {
  603. pInheritFrom = Scope.g_SchemaCache.LookupSchemaObject( pList->Attribute,
  604. SCHMMGMT_CLASS ,
  605. Scope.m_fViewDefunct);
  606. //
  607. // Don't recursively process the item if we already processed it
  608. //
  609. if ( pInheritFrom && szProcessedList.Find(pList->Attribute) == NULL) {
  610. RecursiveDisplayClassAttributesResults( pParentCookie, pInheritFrom, szProcessedList );
  611. szProcessedList.AddTail(pList->Attribute);
  612. Scope.g_SchemaCache.ReleaseRef( pInheritFrom );
  613. }
  614. pList = pList->pNext;
  615. }
  616. pList = pObject->auxiliaryClass;
  617. while ( pList ) {
  618. pInheritFrom = Scope.g_SchemaCache.LookupSchemaObject( pList->Attribute,
  619. SCHMMGMT_CLASS,
  620. Scope.m_fViewDefunct);
  621. //
  622. // Don't recursively process the item if we already processed it
  623. //
  624. if ( pInheritFrom && szProcessedList.Find(pList->Attribute) == NULL ) {
  625. RecursiveDisplayClassAttributesResults( pParentCookie, pInheritFrom, szProcessedList );
  626. szProcessedList.AddTail(pList->Attribute);
  627. Scope.g_SchemaCache.ReleaseRef( pInheritFrom );
  628. }
  629. pList = pList->pNext;
  630. }
  631. //
  632. // If this is an inherited class, insert those attributes.
  633. //
  634. pInheritFrom = Scope.g_SchemaCache.LookupSchemaObject( pObject->subClassOf,
  635. SCHMMGMT_CLASS,
  636. Scope.m_fViewDefunct);
  637. if ( pInheritFrom ) {
  638. RecursiveDisplayClassAttributesResults( pParentCookie, pInheritFrom, szProcessedList );
  639. Scope.g_SchemaCache.ReleaseRef( pInheritFrom );
  640. }
  641. return S_OK;
  642. }
  643. HRESULT
  644. Component::ProcessResultList(
  645. Cookie *pParentCookie,
  646. ListEntry *pList,
  647. BOOLEAN fOptional,
  648. BOOLEAN fSystem,
  649. SchemaObject* pSrcObject
  650. )
  651. {
  652. HRESULT hr;
  653. Cookie *pNewCookie;
  654. RESULTDATAITEM ResultItem;
  655. LPCWSTR lpcszMachineName = pParentCookie->QueryNonNULLMachineName();
  656. ListEntry *pCurrent = NULL;
  657. SchemaObject *pAttribute=NULL;
  658. ComponentData& Scope = QueryComponentDataRef();
  659. //
  660. // Initialize the result item.
  661. //
  662. // FUTURE-2002-03/94/2002-dantra-Although this is a safe usage of ZeroMemory, suggest changing
  663. // the definition RESULTDATAITEM ResultItem = {0} and removing the ZeroMemory call.
  664. ::ZeroMemory( &ResultItem, sizeof( ResultItem ) );
  665. ResultItem.nCol = 0;
  666. ResultItem.mask = RDI_STR | RDI_IMAGE | RDI_PARAM;
  667. ResultItem.str = MMC_CALLBACK;
  668. ResultItem.nImage = iIconAttribute;
  669. for (pCurrent = pList ; pCurrent != NULL; pCurrent = pCurrent->pNext)
  670. {
  671. //
  672. // Point to the actual attribute.
  673. //
  674. pAttribute = Scope.g_SchemaCache.LookupSchemaObject(
  675. pCurrent->Attribute,
  676. SCHMMGMT_ATTRIBUTE,
  677. Scope.m_fViewDefunct);
  678. if(pAttribute==NULL)
  679. {
  680. ASSERT(pAttribute!=NULL); // All attributes should be in the cache
  681. continue;
  682. }
  683. //
  684. // Make a new cookie.
  685. //
  686. pNewCookie = new Cookie( SCHMMGMT_ATTRIBUTE,
  687. lpcszMachineName );
  688. if ( pNewCookie )
  689. {
  690. //
  691. // Record the optional status and the source.
  692. //
  693. if ( fOptional ) {
  694. pNewCookie->Mandatory = FALSE;
  695. } else {
  696. pNewCookie->Mandatory = TRUE;
  697. }
  698. if ( fSystem ) {
  699. pNewCookie->System = TRUE;
  700. } else {
  701. pNewCookie->System = FALSE;
  702. }
  703. pNewCookie->strSrcSchemaObject = pSrcObject->commonName;
  704. pNewCookie->pParentCookie = pParentCookie;
  705. pNewCookie->strSchemaObject = pAttribute->commonName;
  706. Scope.g_SchemaCache.ReleaseRef( pAttribute );
  707. //
  708. // Insert the result pane item.
  709. //
  710. pParentCookie->m_listScopeCookieBlocks.AddHead(
  711. (CBaseCookieBlock*)pNewCookie
  712. );
  713. ResultItem.lParam = reinterpret_cast<LPARAM>((CCookie*)pNewCookie);
  714. hr = m_pResultData->InsertItem( &ResultItem );
  715. if ( SUCCEEDED(hr) )
  716. {
  717. pNewCookie->SetResultHandle( ResultItem.itemID );
  718. }
  719. else
  720. {
  721. delete pNewCookie;
  722. }
  723. }
  724. }
  725. return S_OK;
  726. }
  727. STDMETHODIMP
  728. Component::AddMenuItems(
  729. LPDATAOBJECT,
  730. LPCONTEXTMENUCALLBACK piCallback,
  731. long* pInsertionsAllowed
  732. )
  733. {
  734. HRESULT hr = S_OK;
  735. if (*pInsertionsAllowed & CCM_INSERTIONALLOWED_VIEW)
  736. {
  737. ComponentData& Scope = QueryComponentDataRef();
  738. hr=_InsertMenuHelper
  739. (
  740. piCallback,
  741. CCM_INSERTIONPOINTID_PRIMARY_VIEW,
  742. VIEW_DEFUNCT_OBJECTS,
  743. TRUE,
  744. Scope.m_fViewDefunct
  745. );
  746. ASSERT(SUCCEEDED(hr));
  747. }
  748. return hr;
  749. }
  750. STDMETHODIMP
  751. Component::Command(
  752. long lCommandID,
  753. LPDATAOBJECT obj
  754. )
  755. {
  756. switch ( lCommandID )
  757. {
  758. case VIEW_DEFUNCT_OBJECTS:
  759. ComponentData& Scope = QueryComponentDataRef();
  760. Scope.m_fViewDefunct=!Scope.m_fViewDefunct;
  761. OnNotifyRefresh(obj);
  762. CCookie* pBaseParentCookie = NULL;
  763. HRESULT hr = ExtractData( obj,
  764. CSchmMgmtDataObject::m_CFRawCookie,
  765. reinterpret_cast<PBYTE>(&pBaseParentCookie),
  766. sizeof(pBaseParentCookie) );
  767. if( SUCCEEDED(hr) && pBaseParentCookie )
  768. {
  769. this->m_pConsole->SelectScopeItem(pBaseParentCookie->m_hScopeItem);
  770. }
  771. // The only real info we save is the menu state
  772. // so let's flag that a save might be required
  773. m_bDirty=true;
  774. break;
  775. }
  776. return S_OK;
  777. }
  778. HRESULT Component::OnNotifyRefresh(LPDATAOBJECT obj)
  779. {
  780. ComponentData& Scope = QueryComponentDataRef();
  781. Scope.RefreshScopeView();
  782. m_pConsole->UpdateAllViews(
  783. obj,
  784. SCHMMGMT_SCHMMGMT,
  785. SCHMMGMT_UPDATEVIEW_REFRESH);
  786. return S_OK;
  787. }
  788. HRESULT Component::OnNotifySnapinHelp (LPDATAOBJECT)
  789. {
  790. // return ShowHelpTopic( L"sag_adschema.htm" );
  791. CComQIPtr<IDisplayHelp,&IID_IDisplayHelp> spDisplayHelp = m_pConsole;
  792. if ( !spDisplayHelp )
  793. {
  794. ASSERT(FALSE);
  795. return E_UNEXPECTED;
  796. }
  797. CString strHelpTopic = L"ADConcepts.chm::/sag_adschema.htm";
  798. HRESULT hr = spDisplayHelp->ShowTopic (T2OLE ((LPWSTR)(LPCWSTR) strHelpTopic));
  799. ASSERT (SUCCEEDED (hr));
  800. return hr;
  801. }
  802. HRESULT Component::OnNotifyContextHelp (LPDATAOBJECT)
  803. {
  804. // return ShowHelpTopic( L"schmmgmt_top.htm" );
  805. CComQIPtr<IDisplayHelp,&IID_IDisplayHelp> spDisplayHelp = m_pConsole;
  806. if ( !spDisplayHelp )
  807. {
  808. ASSERT(FALSE);
  809. return E_UNEXPECTED;
  810. }
  811. CString strHelpTopic = L"ADConcepts.chm::/schmmgmt_top.htm";
  812. HRESULT hr = spDisplayHelp->ShowTopic (T2OLE ((LPWSTR)(LPCWSTR) strHelpTopic));
  813. ASSERT (SUCCEEDED (hr));
  814. return hr;
  815. }
  816. STDMETHODIMP
  817. Component::QueryPagesFor(
  818. LPDATAOBJECT pDataObject )
  819. {
  820. MFC_TRY;
  821. if ( NULL == pDataObject ) {
  822. ASSERT(FALSE);
  823. return E_POINTER;
  824. }
  825. HRESULT hr;
  826. CCookie* pBaseParentCookie = NULL;
  827. hr = ExtractData( pDataObject,
  828. CSchmMgmtDataObject::m_CFRawCookie,
  829. reinterpret_cast<PBYTE>(&pBaseParentCookie),
  830. sizeof(pBaseParentCookie) );
  831. ASSERT( SUCCEEDED(hr) );
  832. Cookie* pParentCookie = ActiveCookie(pBaseParentCookie);
  833. ASSERT( NULL != pParentCookie );
  834. if ( ( pParentCookie->m_objecttype == SCHMMGMT_ATTRIBUTE ) &&
  835. ( pParentCookie->pParentCookie ) &&
  836. ( pParentCookie->pParentCookie->m_objecttype == SCHMMGMT_ATTRIBUTES ) ) {
  837. return S_OK;
  838. }
  839. return S_FALSE;
  840. MFC_CATCH;
  841. }
  842. //
  843. // This adds pages to the property sheet if appropriate.
  844. // The handle parameter must be saved in the property page
  845. // object to notify the parent when modified.
  846. //
  847. STDMETHODIMP
  848. Component::CreatePropertyPages(
  849. LPPROPERTYSHEETCALLBACK pCallBack,
  850. LONG_PTR,
  851. LPDATAOBJECT pDataObject )
  852. {
  853. MFC_TRY;
  854. CWaitCursor wait;
  855. //
  856. // Validate the parameters.
  857. //
  858. if ( ( NULL == pCallBack ) ||
  859. ( NULL == pDataObject ) ) {
  860. ASSERT(FALSE);
  861. return E_POINTER;
  862. }
  863. //
  864. // Make sure this is a class object that we are calling up.
  865. //
  866. CCookie* pBaseParentCookie = NULL;
  867. HRESULT hr = ExtractData( pDataObject,
  868. CSchmMgmtDataObject::m_CFRawCookie,
  869. reinterpret_cast<PBYTE>(&pBaseParentCookie),
  870. sizeof(pBaseParentCookie) );
  871. ASSERT( SUCCEEDED(hr) );
  872. Cookie* pParentCookie = ActiveCookie(pBaseParentCookie);
  873. ASSERT( NULL != pParentCookie );
  874. ASSERT( pParentCookie->m_objecttype == SCHMMGMT_ATTRIBUTE );
  875. //
  876. // Create the page.
  877. //
  878. HPROPSHEETPAGE hPage;
  879. AttributeGeneralPage *pGeneralPage =
  880. new AttributeGeneralPage( this, pDataObject );
  881. if ( pGeneralPage )
  882. {
  883. pGeneralPage->Load( *pParentCookie );
  884. MMCPropPageCallback( &pGeneralPage->m_psp );
  885. hPage= MyCreatePropertySheetPage( &pGeneralPage->m_psp );
  886. hr = pCallBack->AddPage( hPage );
  887. }
  888. return S_OK;
  889. MFC_CATCH;
  890. }
  891. HRESULT __stdcall
  892. Component::Compare(
  893. LPARAM,
  894. MMC_COOKIE cookieA,
  895. MMC_COOKIE cookieB,
  896. int* result)
  897. {
  898. if (!result)
  899. {
  900. return E_INVALIDARG;
  901. }
  902. if (!m_pViewedCookie)
  903. {
  904. ASSERT(false);
  905. *result = 0;
  906. return S_OK;
  907. }
  908. Cookie* c1 =
  909. (Cookie*) ActiveBaseCookie(reinterpret_cast<CCookie*>(cookieA));
  910. Cookie* c2 =
  911. (Cookie*) ActiveBaseCookie(reinterpret_cast<CCookie*>(cookieB));
  912. PWSTR t1 = QueryBaseComponentDataRef().QueryResultColumnText(*c1, *result);
  913. PWSTR t2 = QueryBaseComponentDataRef().QueryResultColumnText(*c2, *result);
  914. // All columns use a case-insensitive comparison, as many columns contain
  915. // display names from the directory (which are case-insensitive). That we
  916. // also use a case insensitive compare for the other columns is harmless.
  917. // another trick: we are inverting the results from the compare. This is
  918. // because we initially insert the items in the list in sorted order. So
  919. // the first sort request from the user really is intended to reverse-sort
  920. // the list.
  921. *result = -(_wcsicmp(t1, t2));
  922. return S_OK;
  923. }
  924. STDMETHODIMP Component::GetResultViewType(MMC_COOKIE cookie,
  925. BSTR* ppViewType,
  926. long* pViewOptions)
  927. {
  928. MFC_TRY;
  929. if( QueryComponentDataRef().IsErrorSet() )
  930. {
  931. *pViewOptions = MMC_VIEW_OPTIONS_NOLISTVIEWS;
  932. LPOLESTR psz = NULL;
  933. StringFromCLSID(CLSID_MessageView, &psz);
  934. USES_CONVERSION;
  935. if (psz != NULL)
  936. {
  937. *ppViewType = psz;
  938. return S_OK;
  939. }
  940. else
  941. {
  942. return S_FALSE;
  943. }
  944. }
  945. else
  946. {
  947. return CComponent::GetResultViewType( cookie, ppViewType, pViewOptions );
  948. }
  949. MFC_CATCH;
  950. }
  951. HRESULT SaveDWordHelper(IStream* pStm, DWORD dw)
  952. {
  953. ULONG nBytesWritten;
  954. HRESULT hr = pStm->Write((void*)&dw, sizeof(DWORD),&nBytesWritten);
  955. if (nBytesWritten < sizeof(DWORD))
  956. hr = STG_E_CANTSAVE;
  957. return hr;
  958. }
  959. HRESULT LoadDWordHelper(IStream* pStm, DWORD* pdw)
  960. {
  961. ULONG nBytesRead;
  962. HRESULT hr = pStm->Read((void*)pdw,sizeof(DWORD), &nBytesRead);
  963. ASSERT(nBytesRead == sizeof(DWORD));
  964. return hr;
  965. }
  966. ///////////////////////////////////////////////////////////////////////////////
  967. //// IPersistStream interface members
  968. STDMETHODIMP Component::GetClassID(CLSID *pClassID)
  969. {
  970. ASSERT(pClassID != NULL);
  971. // Copy the CLSID for this snapin
  972. *pClassID=CLSID_SchmMgmt;
  973. return S_OK;
  974. }
  975. STDMETHODIMP Component::IsDirty()
  976. {
  977. return m_bDirty ? S_OK : S_FALSE;
  978. }
  979. // IMPORTANT NOTICE: this value has to be bumped up EVERY time
  980. // a change is made to the stream format
  981. #define DS_STREAM_VERSION ((DWORD)0x01)
  982. STDMETHODIMP Component::Load(IStream *pStm)
  983. {
  984. ASSERT(pStm);
  985. // read the version ##
  986. DWORD dwVersion;
  987. HRESULT hr = LoadDWordHelper(pStm, &dwVersion);
  988. if ( FAILED(hr) ||(dwVersion != DS_STREAM_VERSION) ) return E_FAIL;
  989. // read m_fViewDefunct
  990. DWORD auxView;
  991. hr = LoadDWordHelper(pStm, &auxView);
  992. if (FAILED(hr)) return hr;
  993. ComponentData& Scope = QueryComponentDataRef();
  994. Scope.m_fViewDefunct = (bool)auxView;
  995. return hr;
  996. }
  997. STDMETHODIMP Component::Save(IStream *pStm, BOOL fClearDirty)
  998. {
  999. ASSERT(pStm);
  1000. // write the version ##
  1001. HRESULT hr = SaveDWordHelper(pStm, DS_STREAM_VERSION);
  1002. if (FAILED(hr)) return hr;
  1003. ComponentData& Scope = QueryComponentDataRef();
  1004. hr = SaveDWordHelper(pStm, Scope.m_fViewDefunct);
  1005. if (FAILED(hr)) return hr;
  1006. if(fClearDirty) m_bDirty=false;
  1007. return hr;
  1008. }
  1009. STDMETHODIMP Component::GetSizeMax(ULARGE_INTEGER *pcbSize)
  1010. {
  1011. ASSERT(pcbSize);
  1012. ASSERT(FALSE);
  1013. //
  1014. // Arbitrary values but I don't think we ever get called
  1015. //
  1016. pcbSize->LowPart = 0xffff;
  1017. pcbSize->HighPart= 0x0;
  1018. return S_OK;
  1019. }