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.

538 lines
14 KiB

  1. //
  2. // relation.cpp : Implementation of ClassRelationshipPage
  3. //
  4. // Jon Newman <[email protected]>
  5. // Copyright (c) Microsoft Corporation 1997
  6. //
  7. #include "stdafx.h"
  8. #include "macros.h"
  9. USE_HANDLE_MACROS("SCHMMGMT(relation.cpp)")
  10. #include "compdata.h"
  11. #include "schmutil.h"
  12. #include "relation.h"
  13. #include "select.h"
  14. const CDialogControlsInfo ctrls[] =
  15. {
  16. { IDC_CLASS_REL_AUX_CLASSES, g_AuxiliaryClass, FALSE },
  17. { IDC_CLASS_REL_AUX_ADD, g_AuxiliaryClass, FALSE },
  18. { IDC_CLASS_REL_SUPER_CLASSES, g_Superiors, FALSE },
  19. { IDC_CLASS_REL_SUPER_ADD, g_Superiors, FALSE },
  20. } ;
  21. const DWORD ClassRelationshipPage::help_map[] =
  22. {
  23. IDI_CLASS, NO_HELP,
  24. IDC_CLASS_REL_NAME_STATIC, NO_HELP,
  25. IDC_CLASS_REL_PARENT_EDIT, IDH_CLASS_REL_PARENT_EDIT,
  26. IDC_CLASS_REL_AUX_CLASSES, IDH_CLASS_REL_AUX_CLASSES,
  27. IDC_STATIC_SYSTEMONLY_AUXILIARY, NO_HELP,
  28. IDC_CLASS_REL_AUX_ADD, IDH_CLASS_REL_AUX_ADD,
  29. IDC_CLASS_REL_AUX_REMOVE, IDH_CLASS_REL_AUX_REMOVE,
  30. IDC_CLASS_REL_SUPER_CLASSES, IDH_CLASS_REL_SUPER_CLASSES,
  31. IDC_STATIC_SYSTEMONLY_SUPERIOR, NO_HELP,
  32. IDC_CLASS_REL_SUPER_ADD, IDH_CLASS_REL_SUPER_ADD,
  33. IDC_CLASS_REL_SUPER_REMOVE, IDH_CLASS_REL_SUPER_REMOVE,
  34. IDC_CLASS_REL_SYSCLASS_STATIC, NO_HELP,
  35. 0,0
  36. };
  37. ClassRelationshipPage::ClassRelationshipPage(
  38. ComponentData *pScope,
  39. LPDATAOBJECT lpDataObject ) :
  40. CPropertyPage(ClassRelationshipPage::IDD)
  41. , m_pIADsObject( NULL )
  42. , fSystemClass( FALSE )
  43. , m_pSchemaObject( NULL )
  44. , m_pScopeControl( pScope )
  45. , m_lpScopeDataObj( lpDataObject )
  46. {
  47. ASSERT( NULL != m_pScopeControl );
  48. ASSERT( NULL != lpDataObject );
  49. }
  50. ClassRelationshipPage::~ClassRelationshipPage()
  51. {
  52. if (NULL != m_pIADsObject)
  53. m_pIADsObject->Release();
  54. if (NULL != m_pSchemaObject) {
  55. m_pScopeControl->g_SchemaCache.ReleaseRef( m_pSchemaObject );
  56. }
  57. }
  58. void
  59. ClassRelationshipPage::Load(
  60. Cookie& CookieRef
  61. ) {
  62. //
  63. // Store the cookie object pointer.
  64. //
  65. m_pCookie = &CookieRef;
  66. return;
  67. }
  68. BOOL
  69. ClassRelationshipPage::OnInitDialog()
  70. {
  71. HRESULT hr = S_OK;
  72. ASSERT( NULL == m_pIADsObject && m_szAdsPath.IsEmpty() );
  73. //
  74. // Get the schema cache object and the actual ADS object.
  75. //
  76. m_pSchemaObject = m_pScopeControl->g_SchemaCache.LookupSchemaObjectByCN(
  77. m_pCookie->strSchemaObject,
  78. SCHMMGMT_CLASS );
  79. if ( m_pSchemaObject ) {
  80. m_pScopeControl->GetSchemaObjectPath( m_pSchemaObject->commonName, m_szAdsPath );
  81. if ( !m_szAdsPath.IsEmpty() ) {
  82. hr = ADsGetObject( (LPWSTR)(LPCWSTR)m_szAdsPath,
  83. IID_IADs,
  84. (void **)&m_pIADsObject );
  85. ASSERT( SUCCEEDED(hr) );
  86. }
  87. }
  88. //
  89. // If we have no ADS object, we should error out!
  90. //
  91. if ( !m_pIADsObject ) {
  92. DoErrMsgBox( ::GetActiveWindow(), TRUE, IDS_ERR_NO_SCHEMA_OBJECT );
  93. ASSERT(FALSE);
  94. return TRUE;
  95. }
  96. //
  97. // get the current values.
  98. //
  99. VARIANT AdsResult;
  100. VariantInit( &AdsResult );
  101. //
  102. // ObjectName
  103. //
  104. hr = m_pIADsObject->Get( const_cast<BSTR>((LPCTSTR)g_DisplayName),
  105. &AdsResult );
  106. if ( SUCCEEDED( hr ) ) {
  107. ASSERT( AdsResult.vt == VT_BSTR );
  108. ObjectName = AdsResult.bstrVal;
  109. VariantClear( &AdsResult );
  110. }
  111. //
  112. // Parent Class.
  113. //
  114. hr = m_pIADsObject->Get( const_cast<BSTR>((LPCTSTR)g_SubclassOf),
  115. &AdsResult );
  116. if ( SUCCEEDED( hr ) ) {
  117. ASSERT( AdsResult.vt == VT_BSTR );
  118. ParentClass = AdsResult.bstrVal;
  119. VariantClear( &AdsResult );
  120. }
  121. //
  122. // SysClass
  123. //
  124. hr = m_pIADsObject->Get( const_cast<BSTR>((LPCTSTR)g_SystemOnly),
  125. &AdsResult );
  126. if ( SUCCEEDED( hr ) )
  127. {
  128. ASSERT( AdsResult.vt == VT_BOOL );
  129. fSystemClass = AdsResult.boolVal;
  130. if ( fSystemClass )
  131. {
  132. SysClassString = g_SysClassString;
  133. }
  134. else
  135. {
  136. SysClassString = L"";
  137. }
  138. VariantClear( &AdsResult );
  139. }
  140. else
  141. {
  142. SysClassString = L"";
  143. }
  144. //
  145. // Determine the auxiliary classes
  146. //
  147. VARIANT varClasses;
  148. VariantInit( &varClasses );
  149. hr = m_pIADsObject->GetEx( g_AuxiliaryClass, &varClasses );
  150. ASSERT( SUCCEEDED(hr) || E_ADS_PROPERTY_NOT_FOUND == hr );
  151. if( SUCCEEDED(hr) )
  152. {
  153. hr = VariantToStringList( varClasses, strlistAuxiliary );
  154. ASSERT( SUCCEEDED(hr) || E_ADS_PROPERTY_NOT_FOUND == hr );
  155. }
  156. VariantClear( &varClasses );
  157. hr = m_pIADsObject->GetEx( g_SystemAuxiliaryClass, &varClasses );
  158. ASSERT( SUCCEEDED(hr) || E_ADS_PROPERTY_NOT_FOUND == hr );
  159. if( SUCCEEDED(hr) )
  160. {
  161. hr = VariantToStringList( varClasses, strlistSystemAuxiliary );
  162. ASSERT( SUCCEEDED(hr) || E_ADS_PROPERTY_NOT_FOUND == hr );
  163. }
  164. VariantClear( &varClasses );
  165. //
  166. // Determine the superior classes
  167. //
  168. hr = m_pIADsObject->GetEx( g_Superiors, &varClasses );
  169. ASSERT( SUCCEEDED(hr) || E_ADS_PROPERTY_NOT_FOUND == hr );
  170. if( SUCCEEDED(hr) )
  171. {
  172. hr = VariantToStringList( varClasses, strlistSuperior );
  173. ASSERT( SUCCEEDED(hr) || E_ADS_PROPERTY_NOT_FOUND == hr );
  174. }
  175. VariantClear( &varClasses );
  176. hr = m_pIADsObject->GetEx( g_SystemSuperiors, &varClasses );
  177. ASSERT( SUCCEEDED(hr) || E_ADS_PROPERTY_NOT_FOUND == hr );
  178. if( SUCCEEDED(hr) )
  179. {
  180. hr = VariantToStringList( varClasses, strlistSystemSuperior );
  181. ASSERT( SUCCEEDED(hr) || E_ADS_PROPERTY_NOT_FOUND == hr );
  182. }
  183. VariantClear( &varClasses );
  184. hr = DissableReadOnlyAttributes( this, m_pIADsObject, ctrls, sizeof(ctrls)/sizeof(ctrls[0]) );
  185. ASSERT( SUCCEEDED(hr) ); // shouldn't fail, but unimportant, so ignore error
  186. // This calls must be done before DDX binding
  187. m_listboxAuxiliary.InitType( m_pScopeControl,
  188. SELECT_AUX_CLASSES,
  189. IDC_CLASS_REL_AUX_REMOVE,
  190. &strlistSystemAuxiliary,
  191. IDC_STATIC_SYSTEMONLY_AUXILIARY
  192. );
  193. m_listboxSuperior.InitType( m_pScopeControl,
  194. SELECT_CLASSES,
  195. IDC_CLASS_REL_SUPER_REMOVE,
  196. &strlistSystemSuperior,
  197. IDC_STATIC_SYSTEMONLY_SUPERIOR
  198. );
  199. CPropertyPage::OnInitDialog();
  200. return TRUE;
  201. }
  202. BOOL
  203. ClassRelationshipPage::OnSetActive()
  204. {
  205. // always enable the Apply button
  206. SetModified(TRUE);
  207. return TRUE;
  208. }
  209. void
  210. ClassRelationshipPage::DoDataExchange(
  211. CDataExchange *pDX
  212. ) {
  213. HRESULT hr = S_OK;
  214. CPropertyPage::DoDataExchange( pDX );
  215. //{{AFX_DATA_MAP(ClassRelationshipPage)
  216. DDX_Control(pDX, IDC_CLASS_REL_PARENT_EDIT, m_staticParent );
  217. DDX_Control(pDX, IDC_CLASS_REL_AUX_CLASSES, m_listboxAuxiliary);
  218. DDX_Control(pDX, IDC_CLASS_REL_SUPER_CLASSES, m_listboxSuperior);
  219. DDX_Text( pDX, IDC_CLASS_REL_NAME_STATIC, ObjectName );
  220. DDX_Text( pDX, IDC_CLASS_REL_PARENT_EDIT, ParentClass );
  221. DDX_Text( pDX, IDC_CLASS_REL_SYSCLASS_STATIC, SysClassString );
  222. //}}AFX_DATA_MAP
  223. if ( !pDX->m_bSaveAndValidate ) {
  224. //
  225. // Fill the auxiliary classes list box.
  226. //
  227. m_listboxAuxiliary.ResetContent();
  228. hr = InsertEditItems( m_listboxAuxiliary, strlistAuxiliary );
  229. ASSERT( SUCCEEDED(hr) );
  230. hr = InsertEditItems( m_listboxAuxiliary, strlistSystemAuxiliary );
  231. ASSERT( SUCCEEDED(hr) );
  232. //
  233. // Fill the possible superiors list box.
  234. //
  235. m_listboxSuperior.ResetContent();
  236. hr = InsertEditItems( m_listboxSuperior, strlistSuperior );
  237. ASSERT( SUCCEEDED(hr) );
  238. hr = InsertEditItems( m_listboxSuperior, strlistSystemSuperior );
  239. ASSERT( SUCCEEDED(hr) );
  240. m_listboxAuxiliary.OnSelChange();
  241. m_listboxSuperior.OnSelChange();
  242. } else {
  243. //
  244. // All changes that we save are tied to button control routines.
  245. //
  246. strlistAuxiliary.RemoveAll();
  247. hr = RetrieveEditItemsWithExclusions(
  248. m_listboxAuxiliary,
  249. strlistAuxiliary,
  250. &strlistSystemAuxiliary
  251. );
  252. ASSERT( SUCCEEDED(hr) );
  253. strlistSuperior.RemoveAll();
  254. hr = RetrieveEditItemsWithExclusions(
  255. m_listboxSuperior,
  256. strlistSuperior,
  257. &strlistSystemSuperior
  258. );
  259. ASSERT( SUCCEEDED(hr) );
  260. }
  261. }
  262. BEGIN_MESSAGE_MAP(ClassRelationshipPage, CPropertyPage)
  263. ON_BN_CLICKED(IDC_CLASS_REL_AUX_ADD, OnButtonAuxiliaryClassAdd)
  264. ON_BN_CLICKED(IDC_CLASS_REL_AUX_REMOVE, OnButtonAuxiliaryClassRemove)
  265. ON_BN_CLICKED(IDC_CLASS_REL_SUPER_ADD, OnButtonSuperiorClassAdd)
  266. ON_BN_CLICKED(IDC_CLASS_REL_SUPER_REMOVE, OnButtonSuperiorClassRemove)
  267. ON_LBN_SELCHANGE(IDC_CLASS_REL_AUX_CLASSES, OnAuxiliarySelChange)
  268. ON_LBN_SELCHANGE(IDC_CLASS_REL_SUPER_CLASSES, OnSuperiorSelChange)
  269. ON_MESSAGE(WM_HELP, OnHelp)
  270. ON_MESSAGE(WM_CONTEXTMENU, OnContextHelp)
  271. END_MESSAGE_MAP()
  272. BOOL
  273. ClassRelationshipPage::OnApply(
  274. )
  275. //
  276. // Revisions:
  277. // CoryWest - 10/1/97 - Changes new additions to be listed by oid.
  278. // Add cache freshening to improve performance.
  279. //
  280. {
  281. ASSERT( NULL != m_pIADsObject);
  282. HRESULT hr = S_OK;
  283. HRESULT flush_result;
  284. ListEntry *pNewList = NULL;
  285. BOOL fApplyAbort = FALSE; // stop later saves
  286. BOOL fApplyFailed = FALSE; // should not close the box
  287. if ( m_listboxAuxiliary.IsModified() )
  288. {
  289. //
  290. // Update the auxiliary classes
  291. //
  292. VARIANT AdsValue;
  293. VariantInit( &AdsValue );
  294. hr = StringListToVariant( AdsValue, strlistAuxiliary );
  295. ASSERT( SUCCEEDED(hr) );
  296. hr = m_pIADsObject->PutEx( ADS_PROPERTY_UPDATE, g_AuxiliaryClass, AdsValue );
  297. ASSERT( SUCCEEDED(hr) );
  298. VariantClear( &AdsValue );
  299. hr = m_pIADsObject->SetInfo();
  300. if ( SUCCEEDED( hr )) {
  301. //
  302. // Update the aux class list in the cache.
  303. //
  304. hr = StringListToColumnList( m_pScopeControl,
  305. strlistAuxiliary,
  306. &pNewList );
  307. if ( SUCCEEDED( hr )) {
  308. m_pScopeControl->g_SchemaCache.FreeColumnList(
  309. m_pSchemaObject->auxiliaryClass );
  310. m_pSchemaObject->auxiliaryClass = pNewList;
  311. //
  312. // Refresh the display!
  313. //
  314. m_pScopeControl->QueryConsole()->UpdateAllViews(
  315. m_lpScopeDataObj, SCHMMGMT_CLASS, SCHMMGMT_UPDATEVIEW_REFRESH );
  316. }
  317. //
  318. // Continue with the directory operation even if
  319. // we couldn't update the display.
  320. //
  321. hr = S_OK;
  322. } else {
  323. //
  324. // Flush the IADS property cache so future
  325. // operations won't fail because of this one.
  326. //
  327. IADsPropertyList *pPropertyList;
  328. flush_result = m_pIADsObject->QueryInterface(
  329. IID_IADsPropertyList,
  330. reinterpret_cast<void**>(&pPropertyList) );
  331. if ( SUCCEEDED( flush_result ) ) {
  332. pPropertyList->PurgePropertyList();
  333. pPropertyList->Release();
  334. }
  335. }
  336. }
  337. if ( SUCCEEDED(hr) && m_listboxSuperior.IsModified() )
  338. {
  339. //
  340. // Update the superior classes
  341. //
  342. VARIANT AdsValue;
  343. VariantInit( &AdsValue );
  344. hr = StringListToVariant( AdsValue, strlistSuperior );
  345. ASSERT( SUCCEEDED(hr) );
  346. hr = m_pIADsObject->PutEx( ADS_PROPERTY_UPDATE, g_Superiors, AdsValue );
  347. ASSERT( SUCCEEDED(hr) );
  348. VariantClear( &AdsValue );
  349. hr = m_pIADsObject->SetInfo();
  350. }
  351. if ( hr == ADS_EXTENDED_ERROR )
  352. {
  353. DoExtErrMsgBox();
  354. }
  355. else if ( FAILED(hr) )
  356. {
  357. if( ERROR_DS_UNWILLING_TO_PERFORM == HRESULT_CODE(hr) )
  358. {
  359. fApplyFailed = TRUE;
  360. DoErrMsgBox( ::GetActiveWindow(), TRUE, IDS_ERR_CHANGE_REJECT );
  361. }
  362. else
  363. {
  364. fApplyAbort = TRUE;
  365. DoErrMsgBox( ::GetActiveWindow(), TRUE, GetErrorMessage(hr,TRUE) );
  366. }
  367. }
  368. else
  369. {
  370. // page is no longer "dirty"
  371. m_listboxAuxiliary.SetModified( FALSE );
  372. m_listboxSuperior.SetModified( FALSE );
  373. // Update comboBox status
  374. OnAuxiliarySelChange();
  375. OnSuperiorSelChange();
  376. SetModified( FALSE );
  377. }
  378. return !fApplyAbort && !fApplyFailed ; // return TRUE if nothing happened
  379. }
  380. void ClassRelationshipPage::OnAuxiliarySelChange()
  381. {
  382. m_listboxAuxiliary.OnSelChange();
  383. }
  384. void ClassRelationshipPage::OnSuperiorSelChange()
  385. {
  386. m_listboxSuperior.OnSelChange();
  387. }
  388. void ClassRelationshipPage::OnButtonAuxiliaryClassRemove()
  389. {
  390. if( m_listboxAuxiliary.RemoveListBoxItem() )
  391. SetModified( TRUE );
  392. }
  393. void ClassRelationshipPage::OnButtonSuperiorClassRemove()
  394. {
  395. if( m_listboxSuperior.RemoveListBoxItem() )
  396. SetModified( TRUE );
  397. }
  398. void
  399. ClassRelationshipPage::OnButtonAuxiliaryClassAdd()
  400. {
  401. if( m_listboxAuxiliary.AddNewObjectToList() )
  402. SetModified( TRUE );
  403. }
  404. void
  405. ClassRelationshipPage::OnButtonSuperiorClassAdd()
  406. {
  407. if( m_listboxSuperior.AddNewObjectToList() )
  408. SetModified( TRUE );
  409. }