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.

1812 lines
44 KiB

  1. //
  2. // compdata.cpp : Implementation of ComponentData
  3. //
  4. // This COM object is primarily concerned with
  5. // the scope 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(compdata.cpp)")
  13. #include "dataobj.h"
  14. #include "compdata.h"
  15. #include "cookie.h"
  16. #include "snapmgr.h"
  17. #include "schmutil.h"
  18. #include "cache.h"
  19. #include "relation.h"
  20. #include "attrpage.h"
  21. #include "advui.h"
  22. #include "aclpage.h"
  23. #include "select.h"
  24. #include "classgen.hpp"
  25. #include "newclass.hpp"
  26. #include "newattr.hpp"
  27. //
  28. // CComponentData implementation.
  29. //
  30. #include "stdcdata.cpp"
  31. //
  32. // ComponentData
  33. //
  34. ComponentData::ComponentData()
  35. :
  36. m_pRootCookie( NULL ),
  37. m_pPathname( NULL ),
  38. m_hItem( NULL )
  39. {
  40. //
  41. // We must refcount the root cookie, since a dataobject for it
  42. // might outlive the IComponentData. JonN 9/2/97
  43. //
  44. m_pRootCookie = new Cookie( SCHMMGMT_SCHMMGMT );
  45. ASSERT(NULL != m_pRootCookie);
  46. m_pRootCookie->AddRef();
  47. g_SchemaCache.SetScopeControl( this );
  48. SetHtmlHelpFileName (L"schmmgmt.chm");
  49. SetCanChangeOperationsMaster( );
  50. SetCanCreateClass( );
  51. SetCanCreateAttribute( );
  52. }
  53. ComponentData::~ComponentData()
  54. {
  55. SAFE_RELEASE(m_pRootCookie);
  56. SAFE_RELEASE(m_pPathname);
  57. }
  58. DEFINE_FORWARDS_MACHINE_NAME( ComponentData, m_pRootCookie )
  59. CCookie&
  60. ComponentData::QueryBaseRootCookie()
  61. {
  62. ASSERT(NULL != m_pRootCookie);
  63. return (CCookie&)*m_pRootCookie;
  64. }
  65. STDMETHODIMP
  66. ComponentData::Initialize( LPUNKNOWN pUnknown )
  67. {
  68. HRESULT hr = CComponentData::Initialize( pUnknown );
  69. if( SUCCEEDED(hr) )
  70. {
  71. ASSERT( !m_pPathname );
  72. // create Pathname Object
  73. if( FAILED( CoCreateInstance(CLSID_Pathname,
  74. NULL,
  75. CLSCTX_INPROC_SERVER,
  76. IID_IADsPathname,
  77. (void**)&m_pPathname) ) )
  78. {
  79. // in case of an error, ignore and later provide no escaping.
  80. ASSERT( FALSE );
  81. SAFE_RELEASE( m_pPathname );
  82. }
  83. }
  84. return hr;
  85. }
  86. STDMETHODIMP
  87. ComponentData::CreateComponent( LPCOMPONENT* ppComponent )
  88. {
  89. MFC_TRY;
  90. ASSERT(ppComponent != NULL);
  91. CComObject<Component>* pObject;
  92. CComObject<Component>::CreateInstance(&pObject);
  93. ASSERT(pObject != NULL);
  94. pObject->SetComponentDataPtr( (ComponentData*)this );
  95. return pObject->QueryInterface( IID_IComponent,
  96. reinterpret_cast<void**>(ppComponent) );
  97. MFC_CATCH;
  98. }
  99. HRESULT
  100. ComponentData::LoadIcons(
  101. LPIMAGELIST pImageList,
  102. BOOL
  103. )
  104. /***
  105. This routine loads the icon resources that MMC will use.
  106. We use the image list member ImageListSetIcon to make these
  107. resources available to MMC.
  108. ***/
  109. {
  110. HICON hIcon;
  111. HRESULT hr = S_OK;
  112. if( !IsErrorSet() )
  113. {
  114. //
  115. // Set the generic and the last icon in case they are used.
  116. //
  117. hIcon = LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_GENERIC));
  118. ASSERT(hIcon != NULL);
  119. hr = pImageList->ImageListSetIcon((PLONG_PTR)hIcon,iIconGeneric);
  120. ASSERT(SUCCEEDED(hr));
  121. hr = pImageList->ImageListSetIcon((PLONG_PTR)hIcon,iIconLast);
  122. ASSERT(SUCCEEDED(hr));
  123. //
  124. // Set the closed folder icon.
  125. //
  126. hIcon = LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_FOLDER_CLOSED));
  127. ASSERT(hIcon != NULL);
  128. hr = pImageList->ImageListSetIcon((PLONG_PTR)hIcon,iIconFolder);
  129. ASSERT(SUCCEEDED(hr));
  130. //
  131. // Set the class, attribute, and display specifier icon.
  132. //
  133. hIcon = LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_CLASS));
  134. ASSERT(hIcon != NULL);
  135. hr = pImageList->ImageListSetIcon((PLONG_PTR)hIcon,iIconClass);
  136. ASSERT(SUCCEEDED(hr));
  137. hIcon = LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_ATTRIBUTE));
  138. ASSERT(hIcon != NULL);
  139. hr = pImageList->ImageListSetIcon((PLONG_PTR)hIcon,iIconAttribute);
  140. ASSERT(SUCCEEDED(hr));
  141. }
  142. return S_OK;
  143. }
  144. HRESULT
  145. ComponentData::OnNotifyExpand(
  146. LPDATAOBJECT lpDataObject,
  147. BOOL bExpanding,
  148. HSCOPEITEM hParent
  149. )
  150. /***
  151. This routine is called in response to IComponentData:Notify with
  152. the MMCN_EXPAND notification. The argument bExpanding tells us
  153. whether the node is expanding or contracting.
  154. ***/
  155. {
  156. ASSERT( NULL != lpDataObject &&
  157. NULL != hParent &&
  158. NULL != m_pConsoleNameSpace );
  159. //
  160. // Do nothing on a contraction - we will get notifications to
  161. // destroy the disappearing nodes.
  162. //
  163. if ( !bExpanding )
  164. return S_OK;
  165. //
  166. // This code will not work if SchmMgmt becomes an extension
  167. // since the RawCookie format will not be available.
  168. //
  169. CCookie* pBaseParentCookie = NULL;
  170. HRESULT hr = ExtractData( lpDataObject,
  171. CSchmMgmtDataObject::m_CFRawCookie,
  172. reinterpret_cast<PBYTE>(&pBaseParentCookie),
  173. sizeof(pBaseParentCookie) );
  174. ASSERT( SUCCEEDED(hr) );
  175. Cookie* pParentCookie = ActiveCookie(pBaseParentCookie);
  176. ASSERT( NULL != pParentCookie );
  177. //
  178. // If this node already has children then this expansion is a
  179. // re-expansion. We should complain, but not do anything.
  180. //
  181. if ( !((pParentCookie->m_listScopeCookieBlocks).IsEmpty()) ) {
  182. ASSERT(FALSE);
  183. return S_OK;
  184. }
  185. switch ( pParentCookie->m_objecttype ) {
  186. case SCHMMGMT_SCHMMGMT:
  187. // expanding the root, need to bind
  188. hr = _InitBasePaths();
  189. if( SUCCEEDED(hr) )
  190. {
  191. CheckSchemaPermissions( ); // ignoring errors
  192. }
  193. else
  194. {
  195. SetError( IDS_ERR_ERROR, IDS_ERR_NO_SCHEMA_PATH );
  196. SetDelayedRefreshOnShow( hParent );
  197. return S_OK;
  198. }
  199. InitializeRootTree( hParent, pParentCookie );
  200. break;
  201. case SCHMMGMT_CLASSES:
  202. return FastInsertClassScopeCookies(
  203. pParentCookie,
  204. hParent );
  205. break;
  206. //
  207. // These node types have no scope children.
  208. //
  209. case SCHMMGMT_CLASS:
  210. case SCHMMGMT_ATTRIBUTE:
  211. case SCHMMGMT_ATTRIBUTES:
  212. return S_OK;
  213. //
  214. // We received an unknown node type.
  215. //
  216. default:
  217. TRACE( "ComponentData::EnumerateScopeChildren bad parent type.\n" );
  218. ASSERT( FALSE );
  219. return S_OK;
  220. }
  221. return S_OK;
  222. }
  223. HRESULT
  224. ComponentData::OnNotifyRelease(
  225. LPDATAOBJECT,
  226. HSCOPEITEM
  227. ) {
  228. //
  229. // Since we are not a valid extension snap in,
  230. // we don't need to do anything here.
  231. //
  232. return S_OK;
  233. }
  234. HRESULT
  235. ComponentData::OnNotifyDelete(
  236. LPDATAOBJECT lpDataObject)
  237. {
  238. CCookie* pBaseParentCookie = NULL;
  239. HRESULT hr = ExtractData( lpDataObject,
  240. CSchmMgmtDataObject::m_CFRawCookie,
  241. reinterpret_cast<PBYTE>(&pBaseParentCookie),
  242. sizeof(pBaseParentCookie) );
  243. ASSERT( SUCCEEDED(hr) );
  244. Cookie* pParentCookie = ActiveCookie(pBaseParentCookie);
  245. ASSERT( NULL != pParentCookie );
  246. UINT promptID = 0;
  247. LPARAM updateType = SCHMMGMT_CLASS;
  248. if (pParentCookie->m_objecttype == SCHMMGMT_CLASS)
  249. {
  250. promptID = IDS_DELETE_CLASS_PROMPT;
  251. updateType = SCHMMGMT_CLASS;
  252. }
  253. else if (pParentCookie->m_objecttype == SCHMMGMT_ATTRIBUTE)
  254. {
  255. promptID = IDS_DELETE_ATTR_PROMPT;
  256. updateType = SCHMMGMT_ATTRIBUTES;
  257. }
  258. else
  259. {
  260. // We should never get called to delete anything but
  261. // class and attribute nodes
  262. ASSERT(FALSE);
  263. return E_FAIL;
  264. }
  265. if( IDYES == AfxMessageBox( promptID, MB_YESNO | MB_ICONWARNING ))
  266. {
  267. hr = DeleteClass( pParentCookie );
  268. if ( SUCCEEDED(hr) )
  269. {
  270. // Remove the node from the UI
  271. m_pConsoleNameSpace->DeleteItem( pParentCookie->m_hScopeItem, TRUE );
  272. // Remove the node from the list
  273. bool result = g_ClassCookieList.DeleteCookie(pParentCookie);
  274. ASSERT(result);
  275. }
  276. else
  277. {
  278. CString szDeleteError;
  279. szDeleteError.Format(IDS_ERRMSG_DELETE_FAILED_CLASS, GetErrorMessage(hr, TRUE));
  280. DoErrMsgBox( ::GetActiveWindow(), TRUE, szDeleteError );
  281. }
  282. }
  283. return hr;
  284. }
  285. HRESULT
  286. ComponentData::DeleteClass(
  287. Cookie* pcookie
  288. )
  289. /***
  290. This deletes an attribute from the schema
  291. ***/
  292. {
  293. HRESULT hr = S_OK;
  294. do
  295. {
  296. if ( !pcookie )
  297. {
  298. hr = E_INVALIDARG;
  299. break;
  300. }
  301. SchemaObject* pObject = g_SchemaCache.LookupSchemaObjectByCN(
  302. pcookie->strSchemaObject,
  303. SCHMMGMT_CLASS );
  304. if ( !pObject )
  305. {
  306. hr = E_FAIL;
  307. break;
  308. }
  309. CString szAdsPath;
  310. GetSchemaObjectPath( pObject->commonName, szAdsPath );
  311. hr = DeleteObject( szAdsPath, pcookie, g_ClassFilter );
  312. } while (false);
  313. return hr;
  314. }
  315. //
  316. // This is where we store the string handed back to GetDisplayInfo().
  317. //
  318. CString g_strResultColumnText;
  319. BSTR
  320. ComponentData::QueryResultColumnText(
  321. CCookie& basecookieref,
  322. int nCol
  323. ) {
  324. #ifndef UNICODE
  325. #error not ANSI-enabled
  326. #endif
  327. BSTR strDisplayText = NULL;
  328. Cookie& cookieref = (Cookie&)basecookieref;
  329. SchemaObject *pSchemaObject = NULL;
  330. SchemaObject *pSrcSchemaObject = NULL;
  331. switch ( cookieref.m_objecttype ) {
  332. //
  333. // These only have first column textual data.
  334. //
  335. case SCHMMGMT_SCHMMGMT:
  336. if ( COLNUM_SCHEMA_NAME == nCol )
  337. strDisplayText = const_cast<BSTR>(((LPCTSTR)g_strSchmMgmt));
  338. break;
  339. case SCHMMGMT_CLASSES:
  340. if ( COLNUM_SCHEMA_NAME == nCol )
  341. strDisplayText = const_cast<BSTR>(((LPCTSTR)g_strClasses));
  342. break;
  343. case SCHMMGMT_ATTRIBUTES:
  344. if ( COLNUM_SCHEMA_NAME == nCol )
  345. strDisplayText = const_cast<BSTR>(((LPCTSTR)g_strAttributes));
  346. break;
  347. case SCHMMGMT_CLASS:
  348. //
  349. // These display names come out of the schema cache objects.
  350. //
  351. pSchemaObject = g_SchemaCache.LookupSchemaObjectByCN(
  352. cookieref.strSchemaObject,
  353. SCHMMGMT_CLASS );
  354. //
  355. // If there is no cache object, we just have to return UNKNOWN.
  356. //
  357. if ( !pSchemaObject ) {
  358. ASSERT(FALSE);
  359. strDisplayText = const_cast<BSTR>( (LPCTSTR)g_Unknown );
  360. break;
  361. }
  362. //
  363. // Otherwise, return the appropriate text for the column.
  364. //
  365. if ( COLNUM_CLASS_NAME == nCol ) {
  366. strDisplayText = const_cast<BSTR>((LPCTSTR)pSchemaObject->ldapDisplayName);
  367. } else if ( COLNUM_CLASS_TYPE == nCol ) {
  368. switch ( pSchemaObject->dwClassType ) {
  369. case 0:
  370. strDisplayText = const_cast<BSTR>(((LPCTSTR)g_88Class));
  371. break;
  372. case 1:
  373. strDisplayText = const_cast<BSTR>(((LPCTSTR)g_StructuralClass));
  374. break;
  375. case 2:
  376. strDisplayText = const_cast<BSTR>(((LPCTSTR)g_AbstractClass));
  377. break;
  378. case 3:
  379. strDisplayText = const_cast<BSTR>(((LPCTSTR)g_AuxClass));
  380. break;
  381. default:
  382. strDisplayText = const_cast<BSTR>(((LPCTSTR)g_Unknown));
  383. break;
  384. }
  385. } else if ( COLNUM_CLASS_STATUS == nCol ) {
  386. if ( pSchemaObject->isDefunct ) {
  387. strDisplayText = const_cast<BSTR>( (LPCTSTR)g_Defunct );
  388. } else {
  389. strDisplayText = const_cast<BSTR>( (LPCTSTR)g_Active );
  390. }
  391. } else if ( COLNUM_CLASS_DESCRIPTION == nCol ) {
  392. strDisplayText = const_cast<BSTR>((LPCTSTR)pSchemaObject->description);
  393. }
  394. break;
  395. case SCHMMGMT_ATTRIBUTE:
  396. pSchemaObject = g_SchemaCache.LookupSchemaObjectByCN(
  397. cookieref.strSchemaObject,
  398. SCHMMGMT_ATTRIBUTE );
  399. //
  400. // If there is no cache object, we just have to return UNKNOWN.
  401. //
  402. if ( !pSchemaObject ) {
  403. ASSERT(FALSE);
  404. strDisplayText = const_cast<BSTR>( (LPCTSTR)g_Unknown );
  405. break;
  406. }
  407. //
  408. // Otherwise, return the appropriate text for the column.
  409. //
  410. if ( COLNUM_ATTRIBUTE_NAME == nCol ) {
  411. strDisplayText = const_cast<BSTR>((LPCTSTR)pSchemaObject->ldapDisplayName);
  412. } else if ( COLNUM_ATTRIBUTE_TYPE == nCol ) {
  413. //
  414. // If the parent cookie is the attributes folder, then
  415. // this column is the syntax. Otherwise, this column
  416. // is the optional/mandatory status of the attribute.
  417. //
  418. if ( (cookieref.pParentCookie)->m_objecttype == SCHMMGMT_ATTRIBUTES ) {
  419. strDisplayText = const_cast<BSTR>(
  420. (LPCTSTR)g_Syntax[pSchemaObject->SyntaxOrdinal].m_strSyntaxName
  421. );
  422. } else {
  423. if ( cookieref.Mandatory ) {
  424. strDisplayText = const_cast<BSTR>(((LPCTSTR)g_MandatoryAttribute));
  425. } else {
  426. strDisplayText = const_cast<BSTR>(((LPCTSTR)g_OptionalAttribute));
  427. }
  428. }
  429. } else if ( COLNUM_ATTRIBUTE_STATUS == nCol) {
  430. if ( pSchemaObject->isDefunct ) {
  431. strDisplayText = const_cast<BSTR>( (LPCTSTR)g_Defunct );
  432. } else {
  433. strDisplayText = const_cast<BSTR>( (LPCTSTR)g_Active );
  434. }
  435. } else if ( COLNUM_ATTRIBUTE_SYSTEM == nCol ) {
  436. //
  437. // If the parent is the attributes folder, this is the description.
  438. // Otherwise, it's the system status.
  439. //
  440. if ( (cookieref.pParentCookie)->m_objecttype == SCHMMGMT_ATTRIBUTES ) {
  441. strDisplayText = const_cast<BSTR>((LPCTSTR)pSchemaObject->description);
  442. } else {
  443. if ( cookieref.System ) {
  444. strDisplayText = const_cast<BSTR>(((LPCTSTR)g_Yes));
  445. } else {
  446. strDisplayText = const_cast<BSTR>(((LPCTSTR)g_No));
  447. }
  448. }
  449. } else if ( COLNUM_ATTRIBUTE_DESCRIPTION == nCol ) {
  450. strDisplayText = const_cast<BSTR>((LPCTSTR)pSchemaObject->description);
  451. } else if ( COLNUM_ATTRIBUTE_PARENT == nCol ) {
  452. pSrcSchemaObject = g_SchemaCache.LookupSchemaObjectByCN(
  453. cookieref.strSrcSchemaObject,
  454. SCHMMGMT_CLASS );
  455. //
  456. // If there is no cache object, we just have to return UNKNOWN.
  457. //
  458. if ( !pSchemaObject ) {
  459. ASSERT(FALSE);
  460. strDisplayText = const_cast<BSTR>( (LPCTSTR)g_Unknown );
  461. break;
  462. }
  463. //
  464. // Otherwise, return the appropriate text for the column.
  465. //
  466. strDisplayText = const_cast<BSTR>((LPCTSTR)pSrcSchemaObject->ldapDisplayName);
  467. }
  468. break;
  469. default:
  470. TRACE( "ComponentData::QueryResultColumnText bad cookie.\n" );
  471. ASSERT( FALSE );
  472. break;
  473. }
  474. //
  475. // Release the schema cache references.
  476. //
  477. if ( pSchemaObject ) {
  478. g_SchemaCache.ReleaseRef( pSchemaObject );
  479. }
  480. if ( pSrcSchemaObject ) {
  481. g_SchemaCache.ReleaseRef( pSrcSchemaObject );
  482. }
  483. //
  484. // Return the appropriate display string.
  485. //
  486. if ( strDisplayText ) {
  487. return strDisplayText;
  488. }
  489. return L"";
  490. }
  491. //
  492. // Given a cookie, this returns the icon to display for that cookie.
  493. //
  494. int
  495. ComponentData::QueryImage(
  496. CCookie& basecookieref,
  497. BOOL )
  498. {
  499. Cookie& cookieref = (Cookie&)basecookieref;
  500. switch ( cookieref.m_objecttype ) {
  501. case SCHMMGMT_SCHMMGMT:
  502. case SCHMMGMT_CLASSES:
  503. case SCHMMGMT_ATTRIBUTES:
  504. return iIconFolder;
  505. break;
  506. case SCHMMGMT_CLASS:
  507. return iIconClass;
  508. break;
  509. case SCHMMGMT_ATTRIBUTE:
  510. return iIconAttribute;
  511. break;
  512. default:
  513. TRACE( "ComponentData::QueryImage bad parent type.\n" );
  514. ASSERT( FALSE );
  515. break;
  516. }
  517. return iIconGeneric;
  518. }
  519. //
  520. // This routines tells MMC whether or not there are
  521. // property pages and menus for this item.
  522. //
  523. HRESULT
  524. _InsertMenuHelper(
  525. LPCONTEXTMENUCALLBACK piCallback,
  526. long lInsertionPointID,
  527. int index,
  528. BOOL fEnabled = TRUE );
  529. HRESULT
  530. _InsertMenuHelper(
  531. LPCONTEXTMENUCALLBACK piCallback,
  532. long lInsertionPointID,
  533. int index,
  534. BOOL fEnabled /* = TRUE */ )
  535. {
  536. CONTEXTMENUITEM MenuItem;
  537. MenuItem.lInsertionPointID = lInsertionPointID;
  538. MenuItem.fFlags = fEnabled ? 0 : MF_GRAYED ;
  539. MenuItem.fSpecialFlags = 0;
  540. MenuItem.strName = const_cast<BSTR>(
  541. (LPCTSTR)g_MenuStrings[index] );
  542. MenuItem.strStatusBarText = const_cast<BSTR>(
  543. (LPCTSTR)g_StatusStrings[index] );
  544. MenuItem.lCommandID = index;
  545. return piCallback->AddItem( &MenuItem );
  546. }
  547. STDMETHODIMP
  548. ComponentData::AddMenuItems(
  549. LPDATAOBJECT piDataObject,
  550. LPCONTEXTMENUCALLBACK piCallback,
  551. long* )
  552. {
  553. CCookie* pBaseParentCookie = NULL;
  554. HRESULT hr = ExtractData( piDataObject,
  555. CSchmMgmtDataObject::m_CFRawCookie,
  556. reinterpret_cast<PBYTE>(&pBaseParentCookie),
  557. sizeof(pBaseParentCookie) );
  558. ASSERT( SUCCEEDED(hr) );
  559. Cookie* pParentCookie = ActiveCookie(pBaseParentCookie);
  560. ASSERT( NULL != pParentCookie );
  561. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  562. LoadGlobalCookieStrings();
  563. switch (pParentCookie->m_objecttype)
  564. {
  565. case SCHMMGMT_SCHMMGMT: // Root Folder
  566. {
  567. VERIFY(
  568. SUCCEEDED(
  569. _InsertMenuHelper(
  570. piCallback,
  571. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  572. SCHEMA_RETARGET)));
  573. VERIFY(
  574. SUCCEEDED(
  575. _InsertMenuHelper(
  576. piCallback,
  577. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  578. SCHEMA_EDIT_FSMO,
  579. !IsErrorSet() && IsSchemaLoaded())));
  580. VERIFY(
  581. SUCCEEDED(
  582. _InsertMenuHelper(
  583. piCallback,
  584. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  585. SCHEMA_SECURITY,
  586. !IsErrorSet() && IsSchemaLoaded())));
  587. VERIFY(
  588. SUCCEEDED(
  589. _InsertMenuHelper(
  590. piCallback,
  591. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  592. SCHEMA_REFRESH,
  593. !IsErrorSet() && IsSchemaLoaded())));
  594. break;
  595. }
  596. case SCHMMGMT_CLASSES: // classes folder
  597. {
  598. // 285448, 293449
  599. VERIFY(
  600. SUCCEEDED(
  601. _InsertMenuHelper(
  602. piCallback,
  603. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  604. NEW_CLASS,
  605. !IsErrorSet() && CanCreateClass())));
  606. if( !IsErrorSet() && CanCreateClass() ) // add only if enabsed
  607. VERIFY(
  608. SUCCEEDED(
  609. _InsertMenuHelper(
  610. piCallback,
  611. CCM_INSERTIONPOINTID_PRIMARY_NEW,
  612. CLASSES_CREATE_CLASS)));
  613. break;
  614. }
  615. case SCHMMGMT_ATTRIBUTES: // attributes folder
  616. {
  617. VERIFY(
  618. SUCCEEDED(
  619. _InsertMenuHelper(
  620. piCallback,
  621. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  622. NEW_ATTRIBUTE,
  623. !IsErrorSet() && CanCreateAttribute())));
  624. if( !IsErrorSet() && CanCreateAttribute() ) // add only if enabsed
  625. VERIFY(
  626. SUCCEEDED(
  627. _InsertMenuHelper(
  628. piCallback,
  629. CCM_INSERTIONPOINTID_PRIMARY_NEW,
  630. ATTRIBUTES_CREATE_ATTRIBUTE)));
  631. break;
  632. }
  633. default:
  634. {
  635. // could be class or attribute item
  636. }
  637. } // switch
  638. return S_OK;
  639. }
  640. STDMETHODIMP
  641. ComponentData::Command(long lCommandID, LPDATAOBJECT piDataObject)
  642. {
  643. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  644. switch ( lCommandID )
  645. {
  646. case NEW_ATTRIBUTE:
  647. case ATTRIBUTES_CREATE_ATTRIBUTE:
  648. {
  649. CDialog warn(IDD_CREATE_WARN);
  650. if (IDOK == warn.DoModal())
  651. {
  652. CreateAttributeDialog(this, piDataObject).DoModal();
  653. }
  654. break;
  655. }
  656. case NEW_CLASS:
  657. case CLASSES_CREATE_CLASS:
  658. {
  659. CDialog warn(IDD_CREATE_WARN);
  660. if (IDOK == warn.DoModal())
  661. {
  662. DoNewClassDialog(*this);
  663. }
  664. break;
  665. }
  666. case SCHEMA_RETARGET:
  667. _OnRetarget(piDataObject);
  668. break;
  669. case SCHEMA_EDIT_FSMO:
  670. _OnEditFSMO();
  671. break;
  672. case SCHEMA_REFRESH:
  673. if( FAILED(_OnRefresh(piDataObject)) )
  674. DoErrMsgBox(::GetActiveWindow(), TRUE, IDS_ERR_NO_UPDATE);
  675. break;
  676. case SCHEMA_SECURITY:
  677. _OnSecurity();
  678. break;
  679. default:
  680. break;
  681. }
  682. return S_OK;
  683. }
  684. STDMETHODIMP
  685. ComponentData::QueryPagesFor(
  686. LPDATAOBJECT pDataObject )
  687. {
  688. MFC_TRY;
  689. if ( NULL == pDataObject ) {
  690. ASSERT(FALSE);
  691. return E_POINTER;
  692. }
  693. HRESULT hr;
  694. CCookie* pBaseParentCookie = NULL;
  695. hr = ExtractData( pDataObject,
  696. CSchmMgmtDataObject::m_CFRawCookie,
  697. reinterpret_cast<PBYTE>(&pBaseParentCookie),
  698. sizeof(pBaseParentCookie) );
  699. ASSERT( SUCCEEDED(hr) );
  700. Cookie* pParentCookie = ActiveCookie(pBaseParentCookie);
  701. ASSERT( NULL != pParentCookie );
  702. if ( pParentCookie->m_objecttype == SCHMMGMT_CLASS ) {
  703. return S_OK;
  704. }
  705. return S_FALSE;
  706. MFC_CATCH;
  707. }
  708. //
  709. // This adds pages to the property sheet if appropriate.
  710. // The handle parameter must be saved in the property page
  711. // object to notify the parent when modified.
  712. //
  713. STDMETHODIMP
  714. ComponentData::CreatePropertyPages(
  715. LPPROPERTYSHEETCALLBACK pCallBack,
  716. LONG_PTR,
  717. LPDATAOBJECT pDataObject )
  718. {
  719. MFC_TRY;
  720. CWaitCursor wait;
  721. //
  722. // Validate the parameters.
  723. //
  724. if ( ( NULL == pCallBack ) ||
  725. ( NULL == pDataObject ) ) {
  726. ASSERT(FALSE);
  727. return E_POINTER;
  728. }
  729. //
  730. // Make sure this is a class object that we are calling up.
  731. //
  732. CCookie* pBaseParentCookie = NULL;
  733. HRESULT hr = ExtractData( pDataObject,
  734. CSchmMgmtDataObject::m_CFRawCookie,
  735. reinterpret_cast<PBYTE>(&pBaseParentCookie),
  736. sizeof(pBaseParentCookie) );
  737. ASSERT( SUCCEEDED(hr) );
  738. hr = S_OK;
  739. Cookie* pParentCookie = ActiveCookie(pBaseParentCookie);
  740. ASSERT( NULL != pParentCookie );
  741. ASSERT( pParentCookie->m_objecttype == SCHMMGMT_CLASS );
  742. //
  743. // Create the page.
  744. //
  745. HPROPSHEETPAGE hPage;
  746. ClassGeneralPage *pGeneralPage = new ClassGeneralPage( this );
  747. ClassRelationshipPage *pRelationshipPage =
  748. new ClassRelationshipPage( this, pDataObject );
  749. ClassAttributePage *pAttributesPage =
  750. new ClassAttributePage( this, pDataObject );
  751. if ( pGeneralPage ) {
  752. pGeneralPage->Load( *pParentCookie );
  753. MMCPropPageCallback( &pGeneralPage->m_psp );
  754. hPage = CreatePropertySheetPage( &pGeneralPage->m_psp );
  755. pCallBack->AddPage(hPage);
  756. }
  757. if ( pRelationshipPage ) {
  758. pRelationshipPage->Load( *pParentCookie );
  759. MMCPropPageCallback( &pRelationshipPage->m_psp );
  760. hPage = CreatePropertySheetPage( &pRelationshipPage->m_psp );
  761. pCallBack->AddPage(hPage);
  762. }
  763. if ( pAttributesPage ) {
  764. pAttributesPage->Load( *pParentCookie );
  765. MMCPropPageCallback( &pAttributesPage->m_psp );
  766. hPage = CreatePropertySheetPage( &pAttributesPage->m_psp );
  767. pCallBack->AddPage(hPage);
  768. }
  769. //
  770. // Add the ACL editor page.
  771. //
  772. SchemaObject * pObject = NULL;
  773. CAclEditorPage * pAclPage = NULL;
  774. CString szAdsPath;
  775. pObject = g_SchemaCache.LookupSchemaObjectByCN(
  776. pParentCookie->strSchemaObject,
  777. SCHMMGMT_CLASS );
  778. if ( pObject ) {
  779. GetSchemaObjectPath( pObject->commonName, szAdsPath );
  780. if ( !szAdsPath.IsEmpty() ) {
  781. hr = CAclEditorPage::CreateInstance( &pAclPage, szAdsPath,
  782. pParentCookie->strSchemaObject );
  783. if ( SUCCEEDED(hr) )
  784. {
  785. ASSERT( pAclPage );
  786. pCallBack->AddPage( pAclPage->CreatePage() );
  787. }
  788. else
  789. {
  790. DoErrMsgBox( ::GetActiveWindow(), TRUE, GetErrorMessage(hr) );
  791. hr = S_FALSE; // tell mmc to cancel "show prop pages"
  792. }
  793. }
  794. }
  795. return hr;
  796. MFC_CATCH;
  797. }
  798. HRESULT
  799. ComponentData::FastInsertClassScopeCookies(
  800. Cookie* pParentCookie,
  801. HSCOPEITEM hParentScopeItem
  802. )
  803. /***
  804. On an expand for the "Classes" node, this inserts the
  805. class scope items from the cache.
  806. pParentCookie is the cookie for the parent object.
  807. hParentScopeItem is the HSCOPEITEM for the parent.
  808. ****/
  809. {
  810. HRESULT hr;
  811. SCOPEDATAITEM ScopeItem;
  812. Cookie* pNewCookie;
  813. LPCWSTR lpcszMachineName = pParentCookie->QueryNonNULLMachineName();
  814. SchemaObject *pObject, *pHead;
  815. //
  816. // Initialize the scope item.
  817. //
  818. ::ZeroMemory( &ScopeItem, sizeof(ScopeItem) );
  819. ScopeItem.mask =
  820. SDI_STR
  821. | SDI_IMAGE
  822. | SDI_OPENIMAGE
  823. | SDI_STATE
  824. | SDI_PARAM
  825. | SDI_PARENT
  826. | SDI_CHILDREN;
  827. ScopeItem.displayname = MMC_CALLBACK;
  828. ScopeItem.relativeID = hParentScopeItem;
  829. ScopeItem.nState = TVIS_EXPANDED;
  830. ScopeItem.cChildren = 0;
  831. //
  832. // Remember the parent cookie and scope item; we
  833. // may need to insert later as a refresh.
  834. //
  835. g_ClassCookieList.pParentCookie = pParentCookie;
  836. g_ClassCookieList.hParentScopeItem = hParentScopeItem;
  837. //
  838. // Rather than having a clean class interface to the cache, we
  839. // walk the cache data structures ourselves. This isn't super
  840. // clean, but it's simple.
  841. //
  842. // Since we do this, we have to make sure that the cache is loaded.
  843. //
  844. // This is just like in
  845. // Component::FastInsertAttributeResultCookies
  846. //
  847. g_SchemaCache.LoadCache();
  848. pObject = g_SchemaCache.pSortedClasses;
  849. //
  850. // If there's no sorted list, we can't insert anything!!!!
  851. // We must return an error or else the console will never
  852. // ask us again for scope items.
  853. //
  854. if ( !pObject ) {
  855. ASSERT( FALSE );
  856. // @@ spb: bad message, this could occur if the schema
  857. // queries were empty...
  858. DoErrMsgBox( ::GetActiveWindow(), TRUE, IDS_ERR_NO_SCHEMA_PATH );
  859. return E_FAIL;
  860. }
  861. //
  862. // Do the insert.
  863. //
  864. pHead = pObject;
  865. do {
  866. //
  867. // Insert this result.
  868. //
  869. pNewCookie= new Cookie( SCHMMGMT_CLASS,
  870. lpcszMachineName );
  871. if ( pNewCookie ) {
  872. pNewCookie->pParentCookie = pParentCookie;
  873. pNewCookie->strSchemaObject = pObject->commonName;
  874. pParentCookie->m_listScopeCookieBlocks.AddHead(
  875. (CBaseCookieBlock*)pNewCookie
  876. );
  877. ScopeItem.lParam = reinterpret_cast<LPARAM>((CCookie*)pNewCookie);
  878. ScopeItem.nImage = QueryImage( *pNewCookie, FALSE );
  879. ScopeItem.nOpenImage = QueryImage( *pNewCookie, TRUE );
  880. hr = m_pConsoleNameSpace->InsertItem(&ScopeItem);
  881. if ( SUCCEEDED(hr) ) {
  882. pNewCookie->m_hScopeItem = ScopeItem.ID;
  883. g_ClassCookieList.AddCookie( pNewCookie, ScopeItem.ID );
  884. } else {
  885. delete pNewCookie;
  886. }
  887. }
  888. pObject = pObject->pSortedListFlink;
  889. } while ( pObject != pHead );
  890. return S_OK;
  891. }
  892. //
  893. // Refreshing the scope pane view.
  894. //
  895. VOID
  896. ComponentData::RefreshScopeView(
  897. VOID
  898. )
  899. /***
  900. When we reload the schema cache and the "Classes"
  901. folder has been opened, this routine deletes all
  902. the scope items from view and re-inserts them.
  903. This makes new classes visible to the user.
  904. ***/
  905. {
  906. HRESULT hr;
  907. CCookieListEntry *pHead = g_ClassCookieList.pHead;
  908. CCookieListEntry *pCurrent;
  909. if ( pHead != NULL ) {
  910. //
  911. // Remove all the scope pane items.
  912. //
  913. pCurrent = pHead;
  914. while ( pCurrent->pNext != pHead ) {
  915. hr = m_pConsoleNameSpace->DeleteItem( pCurrent->pNext->hScopeItem, TRUE );
  916. ASSERT( SUCCEEDED( hr ));
  917. //
  918. // This should cause the cookie to be deleted.
  919. //
  920. pCurrent->pNext->pCookie->Release();
  921. pCurrent = pCurrent->pNext;
  922. }
  923. //
  924. // Remove the head of the list.
  925. //
  926. hr = m_pConsoleNameSpace->DeleteItem( pHead->hScopeItem, TRUE );
  927. ASSERT( SUCCEEDED( hr ));
  928. pHead->pCookie->Release();
  929. //
  930. // Delete the class cookie list.
  931. //
  932. g_ClassCookieList.DeleteAll();
  933. }
  934. //
  935. // Re-insert them from the cache if this node has
  936. // been expanded at some point. We have to do this
  937. // because the console doesn't ever seem to ask
  938. // again.
  939. //
  940. if ( g_ClassCookieList.pParentCookie ) {
  941. FastInsertClassScopeCookies(
  942. g_ClassCookieList.pParentCookie,
  943. g_ClassCookieList.hParentScopeItem
  944. );
  945. }
  946. return;
  947. }
  948. void ComponentData::_OnRetarget(LPDATAOBJECT lpDataObject)
  949. {
  950. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  951. MyBasePathsInfo oldBasePathsInfo;
  952. MyBasePathsInfo newBasePathsInfo;
  953. HRESULT hr = S_OK;
  954. HWND hWndParent = NULL;
  955. BOOL fWasErrorSet = IsErrorSet();
  956. m_pConsole->GetMainWindow(&hWndParent);
  957. CChangeDCDialog dlg(GetBasePathsInfo(), hWndParent);
  958. do
  959. {
  960. if (IDOK != dlg.DoModal())
  961. break;
  962. CWaitCursor wait;
  963. // save the old path just in case
  964. oldBasePathsInfo.InitFromInfo( GetBasePathsInfo() );
  965. // attempt to bind
  966. hr = newBasePathsInfo.InitFromName(dlg.GetNewDCName());
  967. BREAK_ON_FAILED_HRESULT(hr);
  968. // switch focus
  969. GetBasePathsInfo()->InitFromInfo(&newBasePathsInfo);
  970. // invalidate the whole tree
  971. hr = _OnRefresh(lpDataObject);
  972. BREAK_ON_FAILED_HRESULT(hr);
  973. SetError( 0, 0 );
  974. // Reset the ResultViewType
  975. if( IsErrorSet() != fWasErrorSet )
  976. {
  977. ASSERT( SCHMMGMT_SCHMMGMT == QueryRootCookie().m_objecttype );
  978. hr = m_pConsole->SelectScopeItem( QueryRootCookie().m_hScopeItem );
  979. ASSERT_BREAK_ON_FAILED_HRESULT(hr);
  980. //
  981. // Add children nodes if needed
  982. //
  983. if ( (QueryRootCookie().m_listScopeCookieBlocks).IsEmpty() )
  984. {
  985. InitializeRootTree( QueryRootCookie().m_hScopeItem, &QueryRootCookie() );
  986. }
  987. }
  988. // Update the root display name
  989. if (GetBasePathsInfo()->GetServerName())
  990. {
  991. CString strDisplayName;
  992. strDisplayName.LoadString(IDS_SCOPE_SCHMMGMT);
  993. strDisplayName += L" [";
  994. strDisplayName += GetBasePathsInfo()->GetServerName();
  995. strDisplayName += L"]";
  996. SCOPEDATAITEM RootItem;
  997. ::ZeroMemory( &RootItem, sizeof(RootItem));
  998. RootItem.mask = SDI_STR | SDI_PARAM;
  999. RootItem.displayname = const_cast<PWSTR>((PCWSTR)strDisplayName);
  1000. RootItem.ID = QueryRootCookie().m_hScopeItem;
  1001. hr = m_pConsoleNameSpace->SetItem(&RootItem);
  1002. ASSERT(SUCCEEDED(hr));
  1003. }
  1004. } while( FALSE );
  1005. if( FAILED(hr) )
  1006. {
  1007. DoErrMsgBox(::GetActiveWindow(), TRUE, IDS_ERR_CANT_RETARGET);
  1008. // restoring...
  1009. GetBasePathsInfo()->InitFromInfo(&oldBasePathsInfo);
  1010. }
  1011. }
  1012. void ComponentData::_OnEditFSMO()
  1013. {
  1014. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1015. HWND hWndParent;
  1016. // Enable hourglass
  1017. CWaitCursor wait;
  1018. m_pConsole->GetMainWindow(&hWndParent);
  1019. CComPtr<IDisplayHelp> spIDisplayHelp;
  1020. m_pConsole->QueryInterface (IID_IDisplayHelp, (void **)&spIDisplayHelp);
  1021. ASSERT(spIDisplayHelp != NULL);
  1022. CEditFsmoDialog dlg(GetBasePathsInfo(), hWndParent, spIDisplayHelp, CanChangeOperationsMaster() );
  1023. dlg.DoModal();
  1024. }
  1025. HRESULT ComponentData::_OnRefresh(LPDATAOBJECT lpDataObject)
  1026. {
  1027. CWaitCursor wait;
  1028. HRESULT hr = S_OK;
  1029. do
  1030. {
  1031. //
  1032. // Force the ds to update the schema cache.
  1033. //
  1034. hr = ForceDsSchemaCacheUpdate();
  1035. // error here means Schema is read-only, cannot force refresh. Ignoring...
  1036. hr = S_OK;
  1037. // nothing shuld fail after this point
  1038. g_SchemaCache.FreeAll();
  1039. g_SchemaCache.LoadCache();
  1040. RefreshScopeView();
  1041. m_pConsole->UpdateAllViews(
  1042. lpDataObject,
  1043. SCHMMGMT_SCHMMGMT,
  1044. SCHMMGMT_UPDATEVIEW_REFRESH);
  1045. } while( FALSE );
  1046. return hr;
  1047. }
  1048. void ComponentData::_OnSecurity()
  1049. {
  1050. HRESULT hr = S_OK;
  1051. HWND hWndParent = NULL;
  1052. CString szSchemaPath;
  1053. do
  1054. {
  1055. // Enable hourglass
  1056. CWaitCursor wait;
  1057. CComPtr<IADs> spSchemaContainer;
  1058. GetBasePathsInfo()->GetSchemaPath(szSchemaPath);
  1059. hr = ADsGetObject( (LPWSTR)(LPCWSTR)szSchemaPath,
  1060. IID_IADs,
  1061. (void**) &spSchemaContainer);
  1062. BREAK_ON_FAILED_HRESULT(hr);
  1063. CComBSTR path;
  1064. hr = spSchemaContainer->get_ADsPath(&path);
  1065. BREAK_ON_FAILED_HRESULT(hr);
  1066. CComBSTR classname;
  1067. hr = spSchemaContainer->get_Class(&classname);
  1068. BREAK_ON_FAILED_HRESULT(hr);
  1069. m_pConsole->GetMainWindow(&hWndParent);
  1070. // Determine if the registry is accessible & schema modifications are allowed
  1071. PWSTR pszFsmoOwnerServerName = 0;
  1072. MyBasePathsInfo fsmoOwnerInfo;
  1073. HRESULT hr = FindFsmoOwner(GetBasePathsInfo(), SCHEMA_FSMO, &fsmoOwnerInfo, &pszFsmoOwnerServerName);
  1074. // If we have the server name, try to read the registry
  1075. BOOL fMarkReadOnly = ( FAILED(hr) || pszFsmoOwnerServerName == 0 || pszFsmoOwnerServerName[0] == 0);
  1076. // Ignore hr code.
  1077. hr =
  1078. DSEditSecurity(
  1079. hWndParent,
  1080. path,
  1081. classname,
  1082. fMarkReadOnly ? DSSI_READ_ONLY : 0,
  1083. NULL,
  1084. NULL,
  1085. NULL,
  1086. 0);
  1087. }
  1088. while (0);
  1089. if (FAILED(hr))
  1090. {
  1091. m_pConsole->GetMainWindow(&hWndParent);
  1092. if( szSchemaPath.IsEmpty() )
  1093. DoErrMsgBox( hWndParent, TRUE, IDS_ERR_NO_SCHEMA_PATH );
  1094. else
  1095. DoErrMsgBox( hWndParent, TRUE, GetErrorMessage(hr,TRUE) );
  1096. }
  1097. }
  1098. HRESULT ComponentData::_InitBasePaths()
  1099. {
  1100. CWaitCursor wait;
  1101. // try to get a bind to a generic DC
  1102. HRESULT hr = GetBasePathsInfo()->InitFromName(NULL);
  1103. if (FAILED(hr))
  1104. return hr; // ADSI failed, cannot get any server
  1105. // from the current server, try to bind to the schema FSMO owner
  1106. MyBasePathsInfo fsmoBasePathsInfo;
  1107. PWSTR pszFsmoOwnerServerName = 0;
  1108. hr = FindFsmoOwner(GetBasePathsInfo(), SCHEMA_FSMO, &fsmoBasePathsInfo,
  1109. &pszFsmoOwnerServerName);
  1110. delete[] pszFsmoOwnerServerName;
  1111. pszFsmoOwnerServerName = 0;
  1112. if (FAILED(hr))
  1113. return S_OK; // still good keep what we have (even though not the FSMO owner)
  1114. // got it, we switch focus
  1115. return GetBasePathsInfo()->InitFromInfo(&fsmoBasePathsInfo);
  1116. }
  1117. STDMETHODIMP ComponentData::GetLinkedTopics(LPOLESTR* lpCompiledHelpFile)
  1118. {
  1119. if (lpCompiledHelpFile == NULL)
  1120. return E_INVALIDARG;
  1121. CString szHelpFilePath;
  1122. LPTSTR lpszBuffer = szHelpFilePath.GetBuffer(2*MAX_PATH);
  1123. UINT nLen = ::GetSystemWindowsDirectory(lpszBuffer, 2*MAX_PATH);
  1124. if (nLen == 0)
  1125. return E_FAIL;
  1126. szHelpFilePath.ReleaseBuffer();
  1127. szHelpFilePath += L"\\help\\ADconcepts.chm";
  1128. UINT nBytes = (szHelpFilePath.GetLength()+1) * sizeof(WCHAR);
  1129. *lpCompiledHelpFile = (LPOLESTR)::CoTaskMemAlloc(nBytes);
  1130. if (*lpCompiledHelpFile != NULL)
  1131. {
  1132. memcpy(*lpCompiledHelpFile, (LPCWSTR)szHelpFilePath, nBytes);
  1133. }
  1134. return S_OK;
  1135. }
  1136. const WCHAR CN_EQUALS[] = L"CN=";
  1137. HRESULT ComponentData::GetSchemaObjectPath( const CString & strCN,
  1138. CString & strPath,
  1139. ADS_FORMAT_ENUM formatType /* = ADS_FORMAT_X500 */ )
  1140. {
  1141. HRESULT hr = E_FAIL;
  1142. do
  1143. {
  1144. if( !m_pPathname )
  1145. break;
  1146. CComBSTR bstr;
  1147. // Escape it
  1148. hr = m_pPathname->GetEscapedElement( 0,
  1149. CComBSTR( CString(CN_EQUALS) + strCN ),
  1150. &bstr );
  1151. BREAK_ON_FAILED_HRESULT(hr);
  1152. // set the dn without the leaf node.
  1153. hr = m_pPathname->Set(
  1154. CComBSTR(
  1155. CString( GetBasePathsInfo()->GetProviderAndServerName())
  1156. + GetBasePathsInfo()->GetSchemaNamingContext() ),
  1157. ADS_SETTYPE_FULL );
  1158. BREAK_ON_FAILED_HRESULT(hr);
  1159. // add new leaf element
  1160. hr = m_pPathname->AddLeafElement( bstr );
  1161. BREAK_ON_FAILED_HRESULT(hr);
  1162. // the result should be property escaped
  1163. hr = m_pPathname->put_EscapedMode( ADS_ESCAPEDMODE_DEFAULT );
  1164. BREAK_ON_FAILED_HRESULT(hr);
  1165. // the full thing is needed
  1166. hr = m_pPathname->SetDisplayType( ADS_DISPLAY_FULL );
  1167. BREAK_ON_FAILED_HRESULT(hr);
  1168. // get the final result.
  1169. hr = m_pPathname->Retrieve( formatType, &bstr );
  1170. BREAK_ON_FAILED_HRESULT(hr);
  1171. strPath = bstr;
  1172. } while( FALSE );
  1173. ASSERT( SUCCEEDED(hr) );
  1174. return hr;
  1175. }
  1176. HRESULT ComponentData::GetLeafObjectFromDN( const BSTR bstrDN,
  1177. CString & strCN )
  1178. {
  1179. HRESULT hr = E_FAIL;
  1180. do
  1181. {
  1182. if( !m_pPathname )
  1183. break;
  1184. // set the full DN.
  1185. hr = m_pPathname->Set( bstrDN, ADS_SETTYPE_DN );
  1186. BREAK_ON_FAILED_HRESULT(hr);
  1187. // the result should not be escaped
  1188. hr = m_pPathname->put_EscapedMode( ADS_ESCAPEDMODE_OFF_EX );
  1189. BREAK_ON_FAILED_HRESULT(hr);
  1190. // just the value please
  1191. hr = m_pPathname->SetDisplayType( ADS_DISPLAY_VALUE_ONLY );
  1192. BREAK_ON_FAILED_HRESULT(hr);
  1193. CComBSTR bstrCN;
  1194. // extract the leaf node
  1195. hr = m_pPathname->Retrieve( ADS_FORMAT_LEAF, &bstrCN );
  1196. BREAK_ON_FAILED_HRESULT(hr);
  1197. strCN = bstrCN;
  1198. } while( FALSE );
  1199. ASSERT( SUCCEEDED(hr) ); // this function should never fail (in theory)
  1200. return hr;
  1201. }
  1202. //
  1203. // Determine what operations are allowed. Optionally returns IADs * to Schema Container
  1204. // if the path is not present, the returned value is E_FAIL
  1205. //
  1206. HRESULT ComponentData::CheckSchemaPermissions( IADs ** ppADs /* = NULL */ )
  1207. {
  1208. HRESULT hr = S_OK;
  1209. CComPtr<IADs> ipADs;
  1210. CString szSchemaContainerPath;
  1211. CStringList strlist;
  1212. ASSERT( !ppADs || !(*ppADs) ); // if present, must point to NULL
  1213. do
  1214. {
  1215. //
  1216. // Disable new attrib/class menu items
  1217. //
  1218. SetCanCreateClass( FALSE );
  1219. SetCanCreateAttribute( FALSE );
  1220. SetCanChangeOperationsMaster( FALSE );
  1221. //
  1222. // Get the schema container path.
  1223. //
  1224. GetBasePathsInfo()->GetSchemaPath( szSchemaContainerPath );
  1225. if( szSchemaContainerPath.IsEmpty() )
  1226. {
  1227. hr = E_FAIL;
  1228. break;
  1229. }
  1230. //
  1231. // Open the schema container.
  1232. //
  1233. hr = ADsGetObject( (LPWSTR)(LPCWSTR)szSchemaContainerPath,
  1234. IID_IADs,
  1235. (void **)&ipADs );
  1236. BREAK_ON_FAILED_HRESULT(hr);
  1237. // extract the list of allowed attributes
  1238. hr = GetStringListElement( ipADs, &g_allowedAttributesEffective, strlist );
  1239. if( SUCCEEDED(hr) )
  1240. {
  1241. // search for needed attributes
  1242. for( POSITION pos = strlist.GetHeadPosition(); pos != NULL; )
  1243. {
  1244. CString * pstr = &strlist.GetNext( pos );
  1245. if( !pstr->CompareNoCase( g_fsmoRoleOwner ) )
  1246. {
  1247. SetCanChangeOperationsMaster( TRUE );
  1248. break;
  1249. }
  1250. }
  1251. }
  1252. // extract the list of allowed classes
  1253. hr = GetStringListElement( ipADs, &g_allowedChildClassesEffective, strlist );
  1254. if( SUCCEEDED(hr) )
  1255. {
  1256. // search for needed attributes
  1257. for( POSITION pos = strlist.GetHeadPosition(); pos != NULL; )
  1258. {
  1259. CString * pstr = &strlist.GetNext( pos );
  1260. if( !pstr->CompareNoCase( g_AttributeFilter ) )
  1261. {
  1262. SetCanCreateAttribute( TRUE );
  1263. if( CanCreateClass() )
  1264. break;
  1265. }
  1266. else if( !pstr->CompareNoCase( g_ClassFilter ) )
  1267. {
  1268. SetCanCreateClass( TRUE );
  1269. if( CanCreateAttribute() )
  1270. break;
  1271. }
  1272. }
  1273. }
  1274. } while( FALSE );
  1275. if( ppADs )
  1276. {
  1277. *ppADs = ipADs;
  1278. if( *ppADs )
  1279. (*ppADs)->AddRef();
  1280. }
  1281. return hr;
  1282. }
  1283. ////////////////////////////////////////////////////////////////////
  1284. //
  1285. // Error handling
  1286. //
  1287. // Set's error title & body text. Call it with 0, 0 to remove
  1288. void ComponentData::SetError( UINT idsErrorTitle, UINT idsErrorText )
  1289. {
  1290. if( idsErrorTitle )
  1291. m_sErrorTitle.LoadString( idsErrorTitle );
  1292. else
  1293. m_sErrorTitle.Empty();
  1294. if( idsErrorText )
  1295. m_sErrorText.LoadString( idsErrorText );
  1296. else
  1297. m_sErrorText.Empty();
  1298. }
  1299. VOID ComponentData::InitializeRootTree( HSCOPEITEM hParent, Cookie * pParentCookie )
  1300. {
  1301. //
  1302. // This node has the two static nodes
  1303. // for Classes and Attributes.
  1304. //
  1305. HRESULT hr = S_OK;
  1306. LPCWSTR lpcszMachineName = pParentCookie->QueryNonNULLMachineName();
  1307. // Update the name of the root to contain the servername we are bound to
  1308. if (GetBasePathsInfo()->GetServerName())
  1309. {
  1310. CString strDisplayName;
  1311. strDisplayName.LoadString(IDS_SCOPE_SCHMMGMT);
  1312. strDisplayName += L" [";
  1313. strDisplayName += GetBasePathsInfo()->GetServerName();
  1314. strDisplayName += L"]";
  1315. SCOPEDATAITEM RootItem;
  1316. ::ZeroMemory( &RootItem, sizeof(RootItem));
  1317. RootItem.mask = SDI_STR | SDI_PARAM;
  1318. RootItem.displayname = const_cast<PWSTR>((PCWSTR)strDisplayName);
  1319. RootItem.ID = hParent;
  1320. hr = m_pConsoleNameSpace->SetItem(&RootItem);
  1321. ASSERT(SUCCEEDED(hr));
  1322. }
  1323. SCOPEDATAITEM ScopeItem;
  1324. ::ZeroMemory( &ScopeItem, sizeof(ScopeItem) );
  1325. ScopeItem.mask = SDI_STR | SDI_IMAGE | SDI_OPENIMAGE | SDI_STATE | SDI_PARAM | SDI_PARENT;
  1326. ScopeItem.displayname = MMC_CALLBACK;
  1327. ScopeItem.relativeID = hParent;
  1328. ScopeItem.nState = 0;
  1329. LoadGlobalCookieStrings();
  1330. //
  1331. // Create new cookies for the static scope items.
  1332. // We're doing something funky with the cookie cast.
  1333. //
  1334. Cookie* pNewCookie;
  1335. pNewCookie= new Cookie( SCHMMGMT_CLASSES,
  1336. lpcszMachineName );
  1337. pParentCookie->m_listScopeCookieBlocks.AddHead(
  1338. (CBaseCookieBlock*)pNewCookie );
  1339. ScopeItem.lParam = reinterpret_cast<LPARAM>((CCookie*)pNewCookie);
  1340. ScopeItem.nImage = QueryImage( *pNewCookie, FALSE );
  1341. ScopeItem.nOpenImage = QueryImage( *pNewCookie, TRUE );
  1342. hr = m_pConsoleNameSpace->InsertItem(&ScopeItem);
  1343. ASSERT(SUCCEEDED(hr));
  1344. pNewCookie->m_hScopeItem = ScopeItem.ID;
  1345. pNewCookie = new Cookie( SCHMMGMT_ATTRIBUTES,
  1346. lpcszMachineName );
  1347. pParentCookie->m_listScopeCookieBlocks.AddHead(
  1348. (CBaseCookieBlock*)pNewCookie );
  1349. ScopeItem.lParam = reinterpret_cast<LPARAM>((CCookie*)pNewCookie);
  1350. ScopeItem.nImage = QueryImage( *pNewCookie, FALSE );
  1351. ScopeItem.nOpenImage = QueryImage( *pNewCookie, TRUE );
  1352. // turn of the + on the Attributes node
  1353. ScopeItem.mask |= SDI_CHILDREN;
  1354. ScopeItem.cChildren = 0;
  1355. hr = m_pConsoleNameSpace->InsertItem(&ScopeItem);
  1356. ASSERT(SUCCEEDED(hr));
  1357. pNewCookie->m_hScopeItem = ScopeItem.ID;
  1358. //
  1359. // Force Cache load (if not done already)
  1360. //
  1361. g_SchemaCache.LoadCache();
  1362. }