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.

1299 lines
39 KiB

  1. #include "stdafx.h"
  2. #include "compdata.h"
  3. #include "cmponent.h"
  4. #include "attrgen.hpp"
  5. #include "resource.h"
  6. #include "dataobj.h"
  7. const TCHAR szUserClass[] = USER_CLASS_NAME ;
  8. // disable User Copy for the following list of attributes
  9. const TCHAR * rgszExclClass[] = { _T("cn"), _T("displayName"),
  10. _T("sAMAccountName"), _T("userAccountControl"),
  11. _T("userParameters"), _T("userPrincipalName"),
  12. NULL };
  13. //
  14. // The following table is copied from dirsync\ldifds\ldifldap\samrestrict.h
  15. //
  16. // CLASS_USER, SampUserObjectType (ldapdisplayname: user)
  17. //
  18. PCWSTR rgszExclClass2[] = { // user[] = {
  19. L"memberOf", // SAMP_USER_GROUPS, ATT_MEMBER
  20. L"dBCSPwd", // SAMP_USER_DBCS_PWD, ATT_DBCS_PWD
  21. L"ntPwdHistory", // SAMP_USER_NT_PWD_HISTORY, ATT_NT_PWD_HISTORY
  22. L"lmPwdHistory", // SAMP_USER_LM_PWD_HISTORY, ATT_LM_PWD_HISTORY
  23. L"lastLogon", // SAMP_FIXED_USER_LAST_LOGON, ATT_LAST_LOGON
  24. L"lastLogoff", // SAMP_FIXED_USER_LAST_LOGOFF, ATT_LAST_LOGOFF
  25. L"badPasswordTime", // SAMP_FIXED_USER_LAST_BAD_PASSWORD_TIME,
  26. // ATT_BAD_PASSWORD_TIME
  27. L"rid", // SAMP_FIXED_USER_USERID, ATT_RID
  28. L"badPwdCount", // SAMP_FIXED_USER_BAD_PWD_COUNT,
  29. // ATT_BAD_PWD_COUNT
  30. L"logonCount", // SAMP_FIXED_USER_LOGON_COUNT, ATT_LOGON_COUNT
  31. L"sAMAccountType", // SAMP_USER_ACCOUNT_TYPE, ATT_SAM_ACCOUNT_TYPE
  32. L"supplementalCredentials", // SAMP_FIXED_USER_SUPPLEMENTAL_CREDENTIALS,
  33. // ATT_SUPPLEMENTAL_CREDENTIALS
  34. L"objectSid", // not in mappings.c, but still required!,
  35. // ATT_OBJECT_SID
  36. L"pwdLastSet",
  37. NULL
  38. };
  39. const TCHAR szTopClass[] = _T("Top");
  40. const CDialogControlsInfo ctrls[] =
  41. {
  42. { IDC_ATTRIB_GENERAL_DESCRIPTION_EDIT, g_Description, TRUE },
  43. { IDC_ATTRIB_GENERAL_MIN_EDIT, g_RangeLower, TRUE },
  44. { IDC_ATTRIB_GENERAL_MAX_EDIT, g_RangeUpper, TRUE },
  45. { IDC_ATTRIB_GENERAL_DISPLAYABLE_CHECK, g_ShowInAdvViewOnly, FALSE },
  46. { IDC_ATTRIB_GENERAL_DEACTIVATE, g_isDefunct, FALSE },
  47. { IDC_ATTRIB_GENERAL_INDEX_CHECK, g_IndexFlag, FALSE },
  48. { IDC_ATTRIB_GENERAL_REPLICATED, g_GCReplicated, FALSE },
  49. { IDC_ATTRIB_GENERAL_CPYATTR_CHECK, g_IndexFlag, FALSE },
  50. { IDC_ATTRIB_GENERAL_ANR_CHECK, g_IndexFlag, FALSE },
  51. { IDC_ATTRIB_GENERAL_CONTAINERIZED_INDEX_CHECK, g_IndexFlag, FALSE},
  52. } ;
  53. const DWORD AttributeGeneralPage::help_map[] =
  54. {
  55. IDI_ATTRIBUTE, NO_HELP,
  56. IDC_ATTRIB_GENERAL_NAME_STATIC, NO_HELP,
  57. IDC_ATTRIB_GENERAL_DESCRIPTION_EDIT, IDH_ATTRIB_GENERAL_DESCRIPTION_EDIT,
  58. IDC_ATTRIB_GENERAL_LDN, IDH_ATTRIB_GENERAL_LDN,
  59. IDC_ATTRIB_GENERAL_OID_EDIT, IDH_ATTRIB_GENERAL_OID_EDIT,
  60. IDC_ATTRIB_GENERAL_VALUE_STATIC, NO_HELP,
  61. IDC_ATTRIB_GENERAL_SYNTAX_EDIT, IDH_ATTRIB_GENERAL_SYNTAX_EDIT,
  62. IDC_ATTRIB_GENERAL_MIN_EDIT, IDH_ATTRIB_GENERAL_MIN_EDIT,
  63. IDC_ATTRIB_GENERAL_MAX_EDIT, IDH_ATTRIB_GENERAL_MAX_EDIT,
  64. IDC_ATTRIB_GENERAL_DISPLAYABLE_CHECK, IDH_ATTRIB_GENERAL_DISPLAYABLE_CHECK,
  65. IDC_ATTRIB_GENERAL_DEACTIVATE, IDH_ATTRIB_DEACTIVATE,
  66. IDC_ATTRIB_GENERAL_INDEX_CHECK, IDH_ATTRIB_GENERAL_INDEX_CHECK,
  67. IDC_ATTRIB_GENERAL_CONTAINERIZED_INDEX_CHECK, IDH_ATTRIB_GENERAL_CONTAINERIZED_INDEX_CHECK,
  68. IDC_ATTRIB_GENERAL_ANR_CHECK, IDH_ATTRIB_GENERAL_ANR_CHECK,
  69. IDC_ATTRIB_GENERAL_REPLICATED, IDH_REPLICATED,
  70. IDC_ATTRIB_GENERAL_CPYATTR_CHECK, IDH_ATTRIB_GENERAL_CPYATTR_CHECK,
  71. IDC_ATTRIB_GENERAL_SYSCLASS_STATIC, NO_HELP,
  72. 0, 0
  73. };
  74. // returns state of bit n
  75. inline
  76. bool
  77. getbit(const DWORD& bits, int n)
  78. {
  79. return (bits & (1 << n)) ? true : false;
  80. }
  81. // sets bit n to 1
  82. inline
  83. void
  84. setbit(DWORD& bits, int n)
  85. {
  86. bits |= (1 << n);
  87. }
  88. // sets bit n to 0
  89. inline
  90. void
  91. clearbit(DWORD& bits, int n)
  92. {
  93. bits &= ~(1 << n);
  94. }
  95. //
  96. // Attribute property sheet routines.
  97. //
  98. BEGIN_MESSAGE_MAP( AttributeGeneralPage, CDialog )
  99. ON_MESSAGE(WM_HELP, OnHelp)
  100. ON_MESSAGE(WM_CONTEXTMENU, OnContextHelp)
  101. ON_BN_CLICKED(IDC_ATTRIB_GENERAL_INDEX_CHECK, OnIndexClick)
  102. ON_BN_CLICKED(IDC_ATTRIB_GENERAL_DEACTIVATE, OnDeactivateClick)
  103. END_MESSAGE_MAP()
  104. AttributeGeneralPage::AttributeGeneralPage(
  105. Component* pResultControl,
  106. LPDATAOBJECT lpDataObject)
  107. :
  108. CPropertyPageAutoDelete( IDD_ATTRIB_GENERAL ),
  109. pCookie( NULL ),
  110. pIADsObject( NULL ),
  111. pObject( NULL),
  112. lpResultDataObject( lpDataObject ),
  113. pComponent( pResultControl ),
  114. fDataLoaded( FALSE ),
  115. Displayable( TRUE ),
  116. DDXDisplayable( TRUE ),
  117. search_flags(0),
  118. DDXIndexed( FALSE ),
  119. DDXANR( FALSE ),
  120. DDXCopyOnDuplicate( FALSE ),
  121. Defunct( FALSE ),
  122. DDXDefunct( FALSE ),
  123. ReplicatedToGC( FALSE ),
  124. DDXReplicatedToGC( FALSE ),
  125. DDXContainerIndexed( FALSE ),
  126. m_editLowerRange( CParsedEdit::EDIT_TYPE_UINT32 ),
  127. m_editUpperRange( CParsedEdit::EDIT_TYPE_UINT32 )
  128. {
  129. }
  130. BOOL
  131. AttributeGeneralPage::OnSetActive()
  132. {
  133. // If pIADsObject is NULL, close dialog box
  134. if( CPropertyPage::OnSetActive() )
  135. {
  136. if ( !pIADsObject )
  137. {
  138. return FALSE;
  139. }
  140. else
  141. {
  142. // always enable the Apply button
  143. SetModified(TRUE);
  144. return TRUE;
  145. }
  146. }
  147. else
  148. return FALSE;
  149. }
  150. AttributeGeneralPage::~AttributeGeneralPage(
  151. )
  152. {
  153. ComponentData& Scope = pComponent->QueryComponentDataRef();
  154. //
  155. // Always make sure we free the IADs object.
  156. //
  157. if ( pIADsObject ) {
  158. pIADsObject->Release();
  159. pIADsObject = NULL;
  160. }
  161. //
  162. // And release the cache.
  163. //
  164. if ( pObject ) {
  165. Scope.g_SchemaCache.ReleaseRef( pObject );
  166. }
  167. }
  168. BOOL
  169. AttributeGeneralPage::OnInitDialog()
  170. {
  171. CPropertyPage::OnInitDialog();
  172. ASSERT( GetDlgItem(IDC_ATTRIB_GENERAL_DESCRIPTION_EDIT) );
  173. ( static_cast<CEdit *>( GetDlgItem(IDC_ATTRIB_GENERAL_DESCRIPTION_EDIT) ) )
  174. -> LimitText( 1024 ) ;
  175. m_editLowerRange.SubclassEdit(IDC_ATTRIB_GENERAL_MIN_EDIT, this, cchMinMaxRange);
  176. m_editUpperRange.SubclassEdit(IDC_ATTRIB_GENERAL_MAX_EDIT, this, cchMinMaxRange);
  177. // NTRAID#NTBUG9-460503,460511-2001/09/10-lucios
  178. // Replaced SysClass Computation by Making the window visible in OnInitDialog
  179. if(pIADsObject != NULL)
  180. { // DoDataExchange has gotten a good pIADsObject or the dialog
  181. // will be closed in OnSetActive
  182. VARIANT AdsResult;
  183. VariantInit( &AdsResult );
  184. // NTRAID#NTBUG9-540866-2002/02/13-dantra-Schema Manager: passing WCHAR * instead of BSTR to method requiring a BSTR
  185. HRESULT hr = pIADsObject->Get( const_cast<BSTR>((LPCTSTR)g_SystemOnly),
  186. &AdsResult );
  187. if ( SUCCEEDED( hr ) ) {
  188. ASSERT( AdsResult.vt == VT_BOOL );
  189. if ( AdsResult.boolVal ) {
  190. ASSERT(GetDlgItem( IDC_ATTRIB_GENERAL_SYSCLASS_STATIC ) != NULL);
  191. GetDlgItem( IDC_ATTRIB_GENERAL_SYSCLASS_STATIC )->ShowWindow( SW_SHOW );
  192. }
  193. VariantClear( &AdsResult );
  194. }
  195. }
  196. return TRUE;
  197. }
  198. void
  199. AttributeGeneralPage::Load(
  200. Cookie& CookieRef
  201. ) {
  202. //
  203. // Store the cookie object pointer. Everything
  204. // else gets loaded when the page is displayed.
  205. //
  206. pCookie = &CookieRef;
  207. return;
  208. }
  209. BOOL
  210. AttributeGeneralPage::OnApply(
  211. VOID
  212. ) {
  213. HRESULT hr;
  214. VARIANT AdsValue;
  215. BOOL fChangesMade = FALSE;
  216. BOOL fRangeChange = FALSE;
  217. BOOL fApplyAbort = FALSE; // stop later saves
  218. BOOL fApplyFailed = FALSE; // should not close the box
  219. DWORD dwRange;
  220. // Enable hourglass
  221. CWaitCursor wait;
  222. //
  223. // We have to flush the IADS property cache if we
  224. // have a failure so later operations won't fail because
  225. // of a bad cached attribute.
  226. //
  227. IADsPropertyList *pPropertyList;
  228. hr = pIADsObject->QueryInterface( IID_IADsPropertyList,
  229. reinterpret_cast<void**>(&pPropertyList) );
  230. if ( FAILED( hr ) ) {
  231. pPropertyList = NULL;
  232. fApplyAbort = TRUE;
  233. }
  234. //
  235. // Check to see if something we cared about changed.
  236. // We care about Description, Min, Max, Indexed,
  237. // Defunct, ReplicatedToGC, and Displayable.
  238. //
  239. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  240. VariantInit( &AdsValue );
  241. //
  242. // Defunct -- in case it was deactivated, activate the object first
  243. //
  244. // NTRAID#NTBUG9-477290-2001/10/10-lucios
  245. // && !DDXDefunct was taken out and fChangesMade=TRUE added
  246. if( !fApplyAbort && DDXDefunct != Defunct )
  247. {
  248. hr = ChangeDefunctState( DDXDefunct, Defunct, pPropertyList, fApplyAbort, fApplyFailed );
  249. if (FAILED(hr)) fApplyAbort = TRUE;
  250. else fChangesMade = TRUE;
  251. }
  252. //
  253. // Description
  254. //
  255. if ( !fApplyAbort && DDXDescription != Description ) {
  256. V_VT(&AdsValue) = VT_BSTR;
  257. // NTRAID#NTBUG9-540866-2002/02/13-dantra-Schema Manager: passing WCHAR * instead of BSTR to method requiring a BSTR
  258. V_BSTR(&AdsValue) = const_cast<BSTR>((LPCTSTR)DDXDescription);
  259. if ( DDXDescription.IsEmpty() ) {
  260. hr = pIADsObject->PutEx( ADS_PROPERTY_CLEAR,
  261. // NTRAID#NTBUG9-540866-2002/02/13-dantra-Schema Manager: passing WCHAR * instead of BSTR to method requiring a BSTR
  262. const_cast<BSTR>((LPCTSTR)g_Description),
  263. AdsValue );
  264. } else {
  265. // NTRAID#NTBUG9-540866-2002/02/13-dantra-Schema Manager: passing WCHAR * instead of BSTR to method requiring a BSTR
  266. hr = pIADsObject->Put( const_cast<BSTR>((LPCTSTR)g_Description),
  267. AdsValue );
  268. }
  269. // NTRAID#NTBUG9-542354-2002/02/14-dantra-Errors returned by IADs::Put and PutEx are being masked.
  270. if ( SUCCEEDED( hr ) ) hr = pIADsObject->SetInfo();
  271. if ( SUCCEEDED( hr ) ) {
  272. pObject->description = DDXDescription;
  273. fChangesMade = TRUE;
  274. Description = DDXDescription;
  275. } else {
  276. pPropertyList->PurgePropertyList();
  277. if( ERROR_DS_UNWILLING_TO_PERFORM == HRESULT_CODE(hr) )
  278. {
  279. fApplyFailed = TRUE;
  280. DoErrMsgBox( ::GetActiveWindow(), TRUE, IDS_ERR_EDIT_DESC );
  281. }
  282. else
  283. {
  284. fApplyAbort = TRUE;
  285. DoErrMsgBox( ::GetActiveWindow(), TRUE, GetErrorMessage(hr,TRUE) );
  286. }
  287. }
  288. VariantInit( &AdsValue );
  289. }
  290. //
  291. // Displayable
  292. //
  293. if ( !fApplyAbort && DDXDisplayable != Displayable ) {
  294. V_VT(&AdsValue) = VT_BOOL;
  295. if ( DDXDisplayable ) {
  296. V_BOOL(&AdsValue) = 0;
  297. } else {
  298. V_BOOL(&AdsValue) = -1;
  299. }
  300. hr = pIADsObject->Put( CComBSTR(g_ShowInAdvViewOnly), AdsValue);
  301. // NTRAID#NTBUG9-542354-2002/02/14-dantra-Errors returned by IADs::Put and PutEx are being masked.
  302. if ( SUCCEEDED( hr ) ) hr = pIADsObject->SetInfo();
  303. if ( FAILED( hr ) ) {
  304. pPropertyList->PurgePropertyList();
  305. if( ERROR_DS_UNWILLING_TO_PERFORM == HRESULT_CODE(hr) )
  306. {
  307. fApplyFailed = TRUE;
  308. DoErrMsgBox( ::GetActiveWindow(), TRUE, IDS_ERR_EDIT_DISPLAYABLE );
  309. }
  310. else
  311. {
  312. fApplyAbort = TRUE;
  313. DoErrMsgBox( ::GetActiveWindow(), TRUE, GetErrorMessage(hr,TRUE) );
  314. }
  315. }
  316. else
  317. {
  318. Displayable = DDXDisplayable;
  319. }
  320. VariantInit( &AdsValue );
  321. }
  322. //
  323. // ReplicatedToGC
  324. //
  325. if ( !fApplyAbort && DDXReplicatedToGC != ReplicatedToGC ) {
  326. V_VT(&AdsValue) = VT_BOOL;
  327. if ( DDXReplicatedToGC ) {
  328. V_BOOL(&AdsValue) = -1;
  329. } else {
  330. V_BOOL(&AdsValue) = 0;
  331. }
  332. // NTRAID#NTBUG9-540866-2002/02/13-dantra-Schema Manager: passing WCHAR * instead of BSTR to method requiring a BSTR
  333. hr = pIADsObject->Put( const_cast<BSTR>((LPCTSTR)g_GCReplicated),
  334. AdsValue );
  335. // NTRAID#NTBUG9-542354-2002/02/14-dantra-Errors returned by IADs::Put and PutEx are being masked.
  336. if ( SUCCEEDED( hr ) ) hr = pIADsObject->SetInfo();
  337. if ( FAILED( hr ) ) {
  338. pPropertyList->PurgePropertyList();
  339. if( ERROR_DS_UNWILLING_TO_PERFORM == HRESULT_CODE(hr) )
  340. {
  341. fApplyFailed = TRUE;
  342. DoErrMsgBox( ::GetActiveWindow(), TRUE, IDS_ERR_EDIT_GC );
  343. }
  344. else
  345. {
  346. fApplyAbort = TRUE;
  347. DoErrMsgBox( ::GetActiveWindow(), TRUE, GetErrorMessage(hr,TRUE) );
  348. }
  349. }
  350. else
  351. {
  352. ReplicatedToGC = DDXReplicatedToGC;
  353. }
  354. VariantInit( &AdsValue );
  355. }
  356. //
  357. // Indexed
  358. //
  359. // make sure ANR is not set when Indexed is unchecked
  360. if( !DDXIndexed )
  361. DDXANR = FALSE;
  362. if( !fApplyAbort &&
  363. (getbit(search_flags, INDEX_BIT_ATTINDEX) != (DDXIndexed ? 1 : 0)
  364. || getbit(search_flags, INDEX_BIT_ANR) != (DDXANR ? 1 : 0)
  365. || getbit(search_flags, INDEX_BIT_COPYONDUPLICATE) != (DDXCopyOnDuplicate ? 1 : 0)
  366. || getbit(search_flags, INDEX_BIT_PDNTATTINDEX) != (DDXContainerIndexed ? 1 : 0)) )
  367. {
  368. DWORD DDXsearch_flags = search_flags;
  369. V_VT(&AdsValue) = VT_I4;
  370. if (DDXIndexed)
  371. setbit(DDXsearch_flags, INDEX_BIT_ATTINDEX);
  372. else
  373. clearbit(DDXsearch_flags, INDEX_BIT_ATTINDEX);
  374. ASSERT( DDXIndexed || !DDXANR );
  375. if (DDXANR)
  376. setbit(DDXsearch_flags, INDEX_BIT_ANR);
  377. else
  378. clearbit(DDXsearch_flags, INDEX_BIT_ANR);
  379. if (DDXCopyOnDuplicate)
  380. setbit(DDXsearch_flags, INDEX_BIT_COPYONDUPLICATE);
  381. else
  382. clearbit(DDXsearch_flags, INDEX_BIT_COPYONDUPLICATE);
  383. if (DDXContainerIndexed)
  384. setbit(DDXsearch_flags, INDEX_BIT_PDNTATTINDEX);
  385. else
  386. clearbit(DDXsearch_flags, INDEX_BIT_PDNTATTINDEX);
  387. V_I4(&AdsValue) = DDXsearch_flags;
  388. // NTRAID#NTBUG9-540866-2002/02/13-dantra-Schema Manager: passing WCHAR * instead of BSTR to method requiring a BSTR
  389. hr = pIADsObject->Put( const_cast<BSTR>((LPCTSTR)g_IndexFlag),
  390. AdsValue );
  391. // NTRAID#NTBUG9-542354-2002/02/14-dantra-Errors returned by IADs::Put and PutEx are being masked.
  392. if ( SUCCEEDED( hr ) ) hr = pIADsObject->SetInfo();
  393. if ( FAILED( hr ) ) {
  394. pPropertyList->PurgePropertyList();
  395. if( ERROR_DS_UNWILLING_TO_PERFORM == HRESULT_CODE(hr) )
  396. {
  397. fApplyFailed = TRUE;
  398. DoErrMsgBox( ::GetActiveWindow(), TRUE, IDS_ERR_EDIT_INDEXED );
  399. }
  400. else
  401. {
  402. fApplyAbort = TRUE;
  403. DoErrMsgBox( ::GetActiveWindow(), TRUE, GetErrorMessage(hr,TRUE) );
  404. }
  405. }
  406. else
  407. {
  408. search_flags = DDXsearch_flags;
  409. }
  410. VariantInit( &AdsValue );
  411. }
  412. //
  413. // RangeUpper and RangeLower
  414. // These have to be set together so the server
  415. // range validation works correctly.
  416. //
  417. if ( !fApplyAbort && RangeUpper != DDXRangeUpper ) {
  418. if ( DDXRangeUpper.IsEmpty() ) {
  419. //
  420. // Clear the value.
  421. //
  422. hr = pIADsObject->PutEx( ADS_PROPERTY_CLEAR,
  423. // NTRAID#NTBUG9-540866-2002/02/13-dantra-Schema Manager: passing WCHAR * instead of BSTR to method requiring a BSTR
  424. const_cast<BSTR>((LPCTSTR)g_RangeUpper),
  425. AdsValue );
  426. } else {
  427. //
  428. // Store the new value.
  429. //
  430. ASSERT(pObject);
  431. hr = GetSafeSignedDWORDFromString( this, dwRange, DDXRangeUpper,
  432. g_Syntax[ pObject->SyntaxOrdinal ].m_fIsSigned );
  433. ASSERT( S_OK == hr ); // validation should have taken care of min/max stuff
  434. V_VT( &AdsValue ) = VT_I4;
  435. V_I4( &AdsValue ) = dwRange;
  436. // NTRAID#NTBUG9-540866-2002/02/13-dantra-Schema Manager: passing WCHAR * instead of BSTR to method requiring a BSTR
  437. hr = pIADsObject->Put( const_cast<BSTR>((LPCTSTR)g_RangeUpper),
  438. AdsValue );
  439. }
  440. fRangeChange = TRUE;
  441. VariantInit( &AdsValue );
  442. }
  443. if ( !fApplyAbort && RangeLower != DDXRangeLower ) {
  444. if ( DDXRangeLower.IsEmpty() ) {
  445. //
  446. // Clear the value.
  447. //
  448. hr = pIADsObject->PutEx( ADS_PROPERTY_CLEAR,
  449. // NTRAID#NTBUG9-540866-2002/02/13-dantra-Schema Manager: passing WCHAR * instead of BSTR to method requiring a BSTR
  450. const_cast<BSTR>((LPCTSTR)g_RangeLower),
  451. AdsValue );
  452. } else {
  453. //
  454. // Store the new value.
  455. //
  456. ASSERT(pObject);
  457. hr = GetSafeSignedDWORDFromString( this, dwRange, DDXRangeLower,
  458. g_Syntax[ pObject->SyntaxOrdinal ].m_fIsSigned );
  459. ASSERT( S_OK == hr ); // validation should have taken care of min/max stuff
  460. V_VT( &AdsValue ) = VT_I4;
  461. V_I4( &AdsValue ) = dwRange;
  462. // NTRAID#NTBUG9-540866-2002/02/13-dantra-Schema Manager: passing WCHAR * instead of BSTR to method requiring a BSTR
  463. hr = pIADsObject->Put( const_cast<BSTR>((LPCTSTR)g_RangeLower),
  464. AdsValue );
  465. }
  466. fRangeChange = TRUE;
  467. VariantInit( &AdsValue );
  468. }
  469. //
  470. // Actually commit the changes.
  471. //
  472. if ( !fApplyAbort && fRangeChange ) {
  473. // NTRAID#NTBUG9-542354-2002/02/14-dantra-Errors returned by IADs::Put and PutEx are being masked.
  474. if( SUCCEEDED( hr ) ) hr = pIADsObject->SetInfo();
  475. if ( FAILED( hr ) ) {
  476. pPropertyList->PurgePropertyList();
  477. if( ERROR_DS_UNWILLING_TO_PERFORM == HRESULT_CODE(hr) )
  478. {
  479. fApplyFailed = TRUE;
  480. DoErrMsgBox( ::GetActiveWindow(), TRUE, IDS_ERR_CREATE_MINMAX );
  481. }
  482. else
  483. {
  484. fApplyAbort = TRUE;
  485. DoErrMsgBox( ::GetActiveWindow(), TRUE, GetErrorMessage(hr,TRUE) );
  486. }
  487. }
  488. else
  489. {
  490. RangeLower = DDXRangeLower;
  491. RangeUpper = DDXRangeUpper;
  492. }
  493. }
  494. //
  495. // Defunct -- in case it was active, deactivate the object after we are done update
  496. //
  497. if( !fApplyAbort && DDXDefunct && DDXDefunct != Defunct )
  498. {
  499. hr = ChangeDefunctState( DDXDefunct, Defunct, pPropertyList, fApplyAbort, fApplyFailed );
  500. }
  501. //
  502. // If there are visible changes, update the views.
  503. //
  504. if ( ( fChangesMade ) &&
  505. ( pComponent ) &&
  506. ( lpResultDataObject ) ) {
  507. CCookie* pBaseCookie;
  508. Cookie* pCookie;
  509. hr = ExtractData( lpResultDataObject,
  510. CSchmMgmtDataObject::m_CFRawCookie,
  511. OUT reinterpret_cast<PBYTE>(&pBaseCookie),
  512. sizeof(pBaseCookie) );
  513. ASSERT( SUCCEEDED(hr) );
  514. pCookie = pComponent->ActiveCookie(pBaseCookie);
  515. ASSERT( NULL != pCookie );
  516. hr = pComponent->m_pResultData->UpdateItem( pCookie->hResultId );
  517. ASSERT( SUCCEEDED(hr) );
  518. }
  519. if ( pPropertyList ) {
  520. pPropertyList->Release();
  521. }
  522. return !fApplyAbort && !fApplyFailed ; // return TRUE if nothing happened
  523. }
  524. void
  525. AttributeGeneralPage::DoDataExchange(
  526. CDataExchange *pDX
  527. ) {
  528. HRESULT hr;
  529. CString szAdsPath;
  530. VARIANT AdsResult;
  531. UINT SyntaxOrdinal = SCHEMA_SYNTAX_UNKNOWN;
  532. ComponentData& Scope = pComponent->QueryComponentDataRef();
  533. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  534. CThemeContextActivator activator;
  535. // Enable hourglass
  536. CWaitCursor wait;
  537. CPropertyPage::DoDataExchange( pDX );
  538. VariantInit( &AdsResult );
  539. // We still want to do the DDX exchange at the bottom
  540. // even if the data is already loaded so make it part
  541. // of this if statement instead of short circuiting
  542. // from within
  543. if ( !pDX->m_bSaveAndValidate &&
  544. !fDataLoaded) {
  545. //
  546. // Get the schema cache object and the actual ADS object.
  547. // Keep the ADS object around while the page is loaded.
  548. //
  549. ASSERT( !pObject ); // Must be NULL initially
  550. pObject = Scope.g_SchemaCache.LookupSchemaObjectByCN(
  551. pCookie->strSchemaObject,
  552. SCHMMGMT_ATTRIBUTE );
  553. if ( pObject ) {
  554. Scope.GetSchemaObjectPath( pObject->commonName, szAdsPath );
  555. if ( !szAdsPath.IsEmpty() ) {
  556. hr = SchemaOpenObject( (LPWSTR)(LPCWSTR)szAdsPath,
  557. IID_IADs,
  558. (void **)&pIADsObject );
  559. if( SUCCEEDED(hr) )
  560. {
  561. BOOL fIsConstructed = FALSE;
  562. // Igrnore error code
  563. IsConstructedObject( pIADsObject, fIsConstructed );
  564. // Enable check box if ths attribute is not in the excluded
  565. // list and available for the User Class
  566. GetDlgItem(IDC_ATTRIB_GENERAL_CPYATTR_CHECK)->EnableWindow(
  567. !fIsConstructed &&
  568. !IsInList( rgszExclClass, pObject->ldapDisplayName ) &&
  569. !IsInList( rgszExclClass2, pObject->ldapDisplayName ) &&
  570. IsAttributeInUserClass( pObject->ldapDisplayName ) );
  571. }
  572. }
  573. }
  574. //
  575. // If we have no ADS object, we should error out!
  576. //
  577. if ( !pIADsObject )
  578. {
  579. DoErrMsgBox( ::GetActiveWindow(), TRUE, IDS_ERR_NO_SCHEMA_OBJECT );
  580. // Because there is no pIADsObject, OnSetActive() will close dialog box
  581. return;
  582. }
  583. //
  584. // ObjectName - Use the ldapDisplayName to be consistent
  585. // with the other admin components.
  586. //
  587. // NTRAID#NTBUG9-540866-2002/02/13-dantra-Schema Manager: passing WCHAR * instead of BSTR to method requiring a BSTR
  588. hr = pIADsObject->Get( const_cast<BSTR>((LPCTSTR)g_DisplayName),
  589. &AdsResult );
  590. if ( SUCCEEDED( hr ) ) {
  591. ASSERT( AdsResult.vt == VT_BSTR );
  592. ObjectName = AdsResult.bstrVal;
  593. VariantClear( &AdsResult );
  594. }
  595. //
  596. // Description
  597. //
  598. // NTRAID#NTBUG9-540866-2002/02/13-dantra-Schema Manager: passing WCHAR * instead of BSTR to method requiring a BSTR
  599. hr = pIADsObject->Get( const_cast<BSTR>((LPCTSTR)g_Description),
  600. &AdsResult );
  601. if ( SUCCEEDED( hr ) ) {
  602. ASSERT( AdsResult.vt == VT_BSTR );
  603. Description = AdsResult.bstrVal;
  604. DDXDescription = AdsResult.bstrVal;
  605. VariantClear( &AdsResult );
  606. }
  607. //
  608. // CommonName
  609. //
  610. // NTRAID#NTBUG9-540866-2002/02/13-dantra-Schema Manager: passing WCHAR * instead of BSTR to method requiring a BSTR
  611. hr = pIADsObject->Get( const_cast<BSTR>((LPCTSTR)g_CN),
  612. &AdsResult );
  613. if ( SUCCEEDED( hr ) ) {
  614. ASSERT( AdsResult.vt == VT_BSTR );
  615. DisplayName = AdsResult.bstrVal;
  616. VariantClear( &AdsResult );
  617. }
  618. // NTRAID#NTBUG9-460503,460511-2001/09/10-lucios
  619. // Replaced SysClass Computation by Making the window visible in OnInitDialog
  620. //
  621. // Syntax
  622. //
  623. // No need to reload from schema -- syntax never changes
  624. //
  625. ASSERT(pObject);
  626. if( pObject )
  627. SyntaxOrdinal = pObject->SyntaxOrdinal;
  628. SyntaxString = g_Syntax[ SyntaxOrdinal ].m_strSyntaxName;
  629. //
  630. // Syntax min and max values.
  631. //
  632. // NTRAID#NTBUG9-540866-2002/02/13-dantra-Schema Manager: passing WCHAR * instead of BSTR to method requiring a BSTR
  633. hr = pIADsObject->Get( const_cast<BSTR>((LPCTSTR)g_RangeLower),
  634. &AdsResult );
  635. if ( SUCCEEDED( hr ) ) {
  636. ASSERT( V_VT( &AdsResult ) == VT_I4 );
  637. RangeLower.Format( g_Syntax[ SyntaxOrdinal ].m_fIsSigned ?
  638. g_INT32_FORMAT : g_UINT32_FORMAT,
  639. V_I4( &AdsResult ) );
  640. ASSERT( RangeLower.GetLength() <= cchMinMaxRange );
  641. DDXRangeLower = RangeLower;
  642. VariantClear( &AdsResult );
  643. }
  644. // NTRAID#NTBUG9-540866-2002/02/13-dantra-Schema Manager: passing WCHAR * instead of BSTR to method requiring a BSTR
  645. hr = pIADsObject->Get( const_cast<BSTR>((LPCTSTR)g_RangeUpper),
  646. &AdsResult );
  647. if ( SUCCEEDED( hr ) ) {
  648. ASSERT( V_VT( &AdsResult ) == VT_I4 );
  649. RangeUpper.Format( g_Syntax[ SyntaxOrdinal ].m_fIsSigned ?
  650. g_INT32_FORMAT : g_UINT32_FORMAT,
  651. V_I4( &AdsResult ) );
  652. ASSERT( RangeUpper.GetLength() <= cchMinMaxRange );
  653. DDXRangeUpper = RangeUpper;
  654. VariantClear( &AdsResult );
  655. }
  656. //
  657. // Multi-Valued
  658. //
  659. MultiValued.LoadString( IDS_ATTRIBUTE_MULTI );
  660. // NTRAID#NTBUG9-540866-2002/02/13-dantra-Schema Manager: passing WCHAR * instead of BSTR to method requiring a BSTR
  661. hr = pIADsObject->Get( const_cast<BSTR>((LPCTSTR)g_IsSingleValued),
  662. &AdsResult );
  663. if ( SUCCEEDED( hr ) ) {
  664. ASSERT( AdsResult.vt == VT_BOOL );
  665. if ( AdsResult.boolVal == -1 ) {
  666. MultiValued.Empty();
  667. MultiValued.LoadString( IDS_ATTRIBUTE_SINGLE );
  668. }
  669. VariantClear( &AdsResult );
  670. }
  671. //
  672. // Displayable
  673. //
  674. // NTRAID#NTBUG9-540866-2002/02/13-dantra-Schema Manager: passing WCHAR * instead of BSTR to method requiring a BSTR
  675. hr = pIADsObject->Get( CComBSTR(g_ShowInAdvViewOnly), &AdsResult);
  676. if ( SUCCEEDED( hr ) ) {
  677. ASSERT( AdsResult.vt == VT_BOOL );
  678. if ( AdsResult.boolVal == -1 ) {
  679. Displayable = FALSE;
  680. DDXDisplayable = FALSE;
  681. }
  682. VariantClear( &AdsResult );
  683. }
  684. //
  685. // Defunct
  686. //
  687. // NTRAID#NTBUG9-540866-2002/02/13-dantra-Schema Manager: passing WCHAR * instead of BSTR to method requiring a BSTR
  688. hr = pIADsObject->Get( const_cast<BSTR>((LPCTSTR)g_isDefunct),
  689. &AdsResult );
  690. if ( SUCCEEDED( hr ) ) {
  691. ASSERT( AdsResult.vt == VT_BOOL );
  692. if ( AdsResult.boolVal == -1 ) {
  693. Defunct = TRUE;
  694. DDXDefunct = TRUE;
  695. }
  696. VariantClear( &AdsResult );
  697. }
  698. //
  699. // ReplicatedToGC
  700. //
  701. // NTRAID#NTBUG9-540866-2002/02/13-dantra-Schema Manager: passing WCHAR * instead of BSTR to method requiring a BSTR
  702. hr = pIADsObject->Get( const_cast<BSTR>((LPCTSTR)g_GCReplicated),
  703. &AdsResult );
  704. if ( SUCCEEDED( hr ) ) {
  705. ASSERT( AdsResult.vt == VT_BOOL );
  706. if ( AdsResult.boolVal == -1 ) {
  707. ReplicatedToGC = TRUE;
  708. DDXReplicatedToGC = TRUE;
  709. }
  710. VariantClear( &AdsResult );
  711. }
  712. //
  713. // OID
  714. //
  715. // NTRAID#NTBUG9-540866-2002/02/13-dantra-Schema Manager: passing WCHAR * instead of BSTR to method requiring a BSTR
  716. hr = pIADsObject->Get( const_cast<BSTR>((LPCTSTR)g_GlobalAttributeID),
  717. &AdsResult );
  718. if ( SUCCEEDED( hr ) ) {
  719. ASSERT( AdsResult.vt == VT_BSTR );
  720. OidString = AdsResult.bstrVal;
  721. VariantClear( &AdsResult );
  722. }
  723. //
  724. // Indexed, ANR, & Copy on duplicate
  725. //
  726. // NTRAID#NTBUG9-540866-2002/02/13-dantra-Schema Manager: passing WCHAR * instead of BSTR to method requiring a BSTR
  727. hr = pIADsObject->Get( const_cast<BSTR>((LPCTSTR)g_IndexFlag),
  728. &AdsResult );
  729. if (SUCCEEDED(hr))
  730. {
  731. ASSERT(AdsResult.vt == VT_I4);
  732. search_flags = V_I4(&AdsResult);
  733. // Index this attribute in the Active Directory
  734. DDXIndexed = getbit( search_flags, INDEX_BIT_ATTINDEX );
  735. // Ambiguous Name Resolution (ANR)
  736. // checkbox must exist
  737. ASSERT( GetDlgItem(IDC_ATTRIB_GENERAL_ANR_CHECK) );
  738. // if not indexed, or not allowed, disable the checkbox
  739. GetDlgItem(IDC_ATTRIB_GENERAL_ANR_CHECK)->EnableWindow(
  740. g_Syntax[ SyntaxOrdinal ].m_fIsANRCapable ? DDXIndexed : FALSE );
  741. if( DDXIndexed )
  742. DDXANR = getbit( search_flags, INDEX_BIT_ANR );
  743. else
  744. {
  745. DDXANR = FALSE;
  746. // if not indexed, ANR in DS should not be set
  747. ASSERT( !getbit( search_flags, INDEX_BIT_ANR ) );
  748. }
  749. // Attribute is copied when duplicating a user
  750. DDXCopyOnDuplicate = getbit( search_flags, INDEX_BIT_COPYONDUPLICATE );
  751. VariantClear( &AdsResult );
  752. }
  753. // Containerized index
  754. DDXContainerIndexed = getbit( search_flags, INDEX_BIT_PDNTATTINDEX );
  755. // Determine if this is a category 1 object & disable read-only fields
  756. BOOL fIsSystemObject = FALSE;
  757. hr = IsCategory1Object( pIADsObject, fIsSystemObject );
  758. if( SUCCEEDED(hr) && fIsSystemObject )
  759. {
  760. ASSERT( GetDlgItem(IDC_ATTRIB_GENERAL_MIN_EDIT) );
  761. ASSERT( GetDlgItem(IDC_ATTRIB_GENERAL_MAX_EDIT) );
  762. ASSERT( GetDlgItem(IDC_ATTRIB_GENERAL_DEACTIVATE) );
  763. reinterpret_cast<CEdit *>( GetDlgItem(IDC_ATTRIB_GENERAL_MIN_EDIT) )->SetReadOnly();
  764. reinterpret_cast<CEdit *>( GetDlgItem(IDC_ATTRIB_GENERAL_MAX_EDIT) )->SetReadOnly();
  765. GetDlgItem(IDC_ATTRIB_GENERAL_DEACTIVATE)->EnableWindow( FALSE );
  766. }
  767. hr = DissableReadOnlyAttributes( this, pIADsObject, ctrls, sizeof(ctrls)/sizeof(ctrls[0]) );
  768. hr = S_OK;
  769. // NTRAID#NTBUG9-503619-2002/05/15-lucios
  770. // We are deliberatelly ignoring the error here. This function is called to make extra attributes
  771. // read only or disabled if they don't belong to allollklk
  772. // If it fails for any reason, we are not making those attributes read only, but writing them
  773. // will fail and will return an appropriate error message.
  774. // warn the user if this is a read/write defunct object
  775. ASSERT( GetDlgItem(IDC_ATTRIB_GENERAL_DEACTIVATE) );
  776. if( DDXDefunct &&
  777. GetDlgItem(IDC_ATTRIB_GENERAL_DEACTIVATE)->IsWindowEnabled() )
  778. {
  779. AfxMessageBox( IDS_WARNING_DEFUNCT, MB_OK | MB_ICONINFORMATION );
  780. }
  781. //
  782. // Remember that the data is loaded.
  783. //
  784. fDataLoaded = TRUE;
  785. m_editLowerRange.SetSigned( g_Syntax[ SyntaxOrdinal ].m_fIsSigned );
  786. m_editUpperRange.SetSigned( g_Syntax[ SyntaxOrdinal ].m_fIsSigned );
  787. }
  788. //
  789. // Set up the dialog data exchange.
  790. //
  791. DDX_Text( pDX, IDC_ATTRIB_GENERAL_NAME_STATIC, ObjectName );
  792. DDX_Text( pDX, IDC_ATTRIB_GENERAL_SYNTAX_EDIT, SyntaxString );
  793. DDX_Text( pDX, IDC_ATTRIB_GENERAL_OID_EDIT, OidString );
  794. DDX_Text( pDX, IDC_ATTRIB_GENERAL_VALUE_STATIC, MultiValued );
  795. DDX_Text( pDX, IDC_ATTRIB_GENERAL_LDN, DisplayName );
  796. DDX_Text( pDX, IDC_ATTRIB_GENERAL_DESCRIPTION_EDIT, DDXDescription );
  797. DDXV_VerifyAttribRange( pDX, g_Syntax[ pObject->SyntaxOrdinal ].m_fIsSigned,
  798. IDC_ATTRIB_GENERAL_MIN_EDIT, DDXRangeLower,
  799. IDC_ATTRIB_GENERAL_MAX_EDIT, DDXRangeUpper );
  800. DDX_Check( pDX, IDC_ATTRIB_GENERAL_DISPLAYABLE_CHECK, DDXDisplayable );
  801. DDX_Check( pDX, IDC_ATTRIB_GENERAL_INDEX_CHECK, DDXIndexed );
  802. DDX_Check( pDX, IDC_ATTRIB_GENERAL_ANR_CHECK, DDXANR );
  803. DDX_Check( pDX, IDC_ATTRIB_GENERAL_CPYATTR_CHECK, DDXCopyOnDuplicate );
  804. DDX_Check( pDX, IDC_ATTRIB_GENERAL_REPLICATED, DDXReplicatedToGC );
  805. DDX_Check( pDX, IDC_ATTRIB_GENERAL_CONTAINERIZED_INDEX_CHECK, DDXContainerIndexed );
  806. // Since we want the checkbox label to be positive
  807. // the value is actually the opposite of defunct
  808. int checkValue = !Defunct;
  809. DDX_Check( pDX, IDC_ATTRIB_GENERAL_DEACTIVATE, checkValue );
  810. DDXDefunct = !checkValue;
  811. return;
  812. }
  813. void
  814. AttributeGeneralPage::OnIndexClick()
  815. {
  816. ASSERT( pObject );
  817. if( pObject && g_Syntax[ pObject->SyntaxOrdinal ].m_fIsANRCapable )
  818. {
  819. GetDlgItem(IDC_ATTRIB_GENERAL_ANR_CHECK)->
  820. EnableWindow( IsDlgButtonChecked(IDC_ATTRIB_GENERAL_INDEX_CHECK) );
  821. }
  822. }
  823. void
  824. AttributeGeneralPage::OnDeactivateClick()
  825. {
  826. CThemeContextActivator activator;
  827. if( !IsDlgButtonChecked(IDC_ATTRIB_GENERAL_DEACTIVATE) )
  828. {
  829. if(IDYES != AfxMessageBox
  830. (
  831. IDS_WARNING_DEFUNCT_SET,
  832. MB_YESNO | MB_DEFBUTTON2 | MB_ICONWARNING
  833. )
  834. )
  835. {
  836. CheckDlgButton( IDC_ATTRIB_GENERAL_DEACTIVATE, BST_CHECKED );
  837. }
  838. }
  839. }
  840. // Search User class & aux classes for the specified attribute
  841. BOOL
  842. AttributeGeneralPage::IsAttributeInUserClass( const CString & strAttribDN )
  843. {
  844. BOOL fFound = FALSE;
  845. ComponentData & Scope = pComponent->QueryComponentDataRef();
  846. SchemaObject * pObject = Scope.g_SchemaCache.LookupSchemaObject(
  847. CString( szUserClass ),
  848. SCHMMGMT_CLASS );
  849. //
  850. // Call the attribute check routine. This routine
  851. // will call itself recursively to search the
  852. // inheritance structure of the class User.
  853. //
  854. if ( pObject ) {
  855. fFound = RecursiveIsAttributeInUserClass( strAttribDN, pObject );
  856. Scope.g_SchemaCache.ReleaseRef( pObject );
  857. }
  858. return fFound ;
  859. }
  860. // Search the user class & subclasses
  861. BOOL
  862. AttributeGeneralPage::RecursiveIsAttributeInUserClass(
  863. const CString & strAttribDN,
  864. SchemaObject * pObject )
  865. {
  866. BOOL fFound = FALSE;
  867. //
  868. // Don't process "top" here since everyone inherits from it.
  869. //
  870. // i don't think we ever get "top" here?
  871. ASSERT( pObject->ldapDisplayName.CompareNoCase( szTopClass ) );
  872. if ( !pObject->ldapDisplayName.CompareNoCase(szTopClass) )
  873. return fFound;
  874. DebugTrace( L"RecursiveIsAttributeInUserClass: %ls\n",
  875. const_cast<LPWSTR>((LPCTSTR)pObject->ldapDisplayName) );
  876. // Check every list
  877. if( !SearchResultList( strAttribDN, pObject->systemMayContain) &&
  878. !SearchResultList( strAttribDN, pObject->mayContain) &&
  879. !SearchResultList( strAttribDN, pObject->systemMustContain) &&
  880. !SearchResultList( strAttribDN, pObject->mustContain) )
  881. {
  882. //
  883. // The attribute was not found in the given class, diging deeper...
  884. // Check each auxiliary class...
  885. //
  886. fFound = TraverseAuxiliaryClassList( strAttribDN,
  887. pObject->systemAuxiliaryClass );
  888. if( !fFound )
  889. {
  890. fFound = TraverseAuxiliaryClassList( strAttribDN,
  891. pObject->auxiliaryClass );
  892. }
  893. }
  894. else
  895. {
  896. fFound = TRUE;
  897. }
  898. return fFound ;
  899. }
  900. // Linear search of the linked list for the string strAttribDN
  901. BOOL
  902. AttributeGeneralPage::SearchResultList(
  903. const CString & strAttribDN,
  904. ListEntry * pList )
  905. {
  906. // Traverse the list
  907. while ( pList )
  908. {
  909. // Searching for the existance of the attribute
  910. if( !pList->Attribute.CompareNoCase( strAttribDN ) )
  911. return TRUE;
  912. pList = pList->pNext;
  913. }
  914. return FALSE;
  915. }
  916. // Traverse each auxiliary class by recursivly
  917. // calling RecursiveIsAttributeInUserClass()
  918. BOOL
  919. AttributeGeneralPage::TraverseAuxiliaryClassList(
  920. const CString & strAttribDN,
  921. ListEntry * pList )
  922. {
  923. SchemaObject * pInheritFrom = NULL;
  924. ComponentData & Scope = pComponent->QueryComponentDataRef();
  925. BOOL fFound = FALSE;
  926. while ( !fFound && pList ) {
  927. pInheritFrom = Scope.g_SchemaCache.LookupSchemaObject( pList->Attribute,
  928. SCHMMGMT_CLASS );
  929. if ( pInheritFrom )
  930. {
  931. // recursive call
  932. fFound = RecursiveIsAttributeInUserClass( strAttribDN, pInheritFrom );
  933. Scope.g_SchemaCache.ReleaseRef( pInheritFrom );
  934. }
  935. pList = pList->pNext;
  936. }
  937. return fFound ;
  938. }
  939. HRESULT
  940. AttributeGeneralPage::ChangeDefunctState( BOOL DDXDefunct,
  941. BOOL & Defunct,
  942. IADsPropertyList * pPropertyList,
  943. BOOL & fApplyAbort,
  944. BOOL & fApplyFailed )
  945. {
  946. ASSERT( !fApplyAbort && DDXDefunct != Defunct );
  947. VARIANT AdsValue;
  948. HRESULT hr = S_OK;
  949. VariantInit( &AdsValue );
  950. V_VT(&AdsValue) = VT_BOOL;
  951. if ( DDXDefunct ) {
  952. V_BOOL(&AdsValue) = -1;
  953. } else {
  954. V_BOOL(&AdsValue) = 0;
  955. }
  956. // NTRAID#NTBUG9-540866-2002/02/13-dantra-Schema Manager: passing WCHAR * instead of BSTR to method requiring a BSTR
  957. hr = pIADsObject->Put( const_cast<BSTR>((LPCTSTR)g_isDefunct),
  958. AdsValue );
  959. // NTRAID#NTBUG9-542354-2002/02/14-dantra-Errors returned by IADs::Put and PutEx are being masked.
  960. if( SUCCEEDED( hr ) ) hr = pIADsObject->SetInfo();
  961. if ( FAILED( hr ) ) {
  962. pPropertyList->PurgePropertyList();
  963. if( ERROR_DS_UNWILLING_TO_PERFORM == HRESULT_CODE(hr) )
  964. {
  965. fApplyFailed = TRUE;
  966. DoErrMsgBox( ::GetActiveWindow(),
  967. TRUE,
  968. DDXDefunct ? IDS_ERR_EDIT_DEFUNCT_SET : IDS_ERR_EDIT_DEFUNCT_REMOVE );
  969. }
  970. else
  971. {
  972. fApplyAbort = TRUE;
  973. DoErrMsgBox( ::GetActiveWindow(), TRUE, GetErrorMessage(hr,TRUE) );
  974. }
  975. } else {
  976. pObject->isDefunct = DDXDefunct;
  977. Defunct = DDXDefunct;
  978. }
  979. return hr;
  980. }