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.

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