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.

512 lines
15 KiB

  1. #include "stdafx.h"
  2. #include "compdata.h"
  3. #include "newattr.hpp"
  4. // The default syntax for new attributes
  5. const UINT uDefaultSyntax = 0;
  6. //
  7. // The create new attribute dialog box.
  8. //
  9. CreateAttributeDialog::CreateAttributeDialog(
  10. ComponentData *pScope,
  11. LPDATAOBJECT lpDataObject
  12. ) :
  13. CDialog(IDD_CREATE_ATTRIBUTE, NULL),
  14. fDialogLoaded( FALSE ),
  15. MultiValued( FALSE ),
  16. pScopeControl( pScope ),
  17. lpScopeDataObj( lpDataObject ),
  18. SyntaxOrdinal( uDefaultSyntax ),
  19. m_editOID( CParsedEdit::EDIT_TYPE_OID ),
  20. m_editLowerRange( CParsedEdit::EDIT_TYPE_UINT32 ),
  21. m_editUpperRange( CParsedEdit::EDIT_TYPE_UINT32 )
  22. {
  23. ASSERT( uDefaultSyntax < SCHEMA_SYNTAX_UNKNOWN );
  24. }
  25. CreateAttributeDialog::~CreateAttributeDialog()
  26. { ; }
  27. BOOL
  28. CreateAttributeDialog::OnInitDialog()
  29. {
  30. CComboBox * pwndSyntaxCombo = NULL;
  31. CDialog::OnInitDialog();
  32. //
  33. // Set Limits on Range controls
  34. //
  35. ASSERT( GetDlgItem(IDC_CREATE_ATTRIB_MIN) );
  36. ASSERT( GetDlgItem(IDC_CREATE_ATTRIB_MAX) );
  37. m_editOID.SubclassEdit( IDC_CREATE_ATTRIB_OID, this, cchMaxOID );
  38. m_editLowerRange.SubclassEdit(IDC_CREATE_ATTRIB_MIN, this, cchMinMaxRange);
  39. m_editUpperRange.SubclassEdit(IDC_CREATE_ATTRIB_MAX, this, cchMinMaxRange);
  40. //
  41. // Turn off IME support on the min/max edit boxes
  42. //
  43. ImmAssociateContext(m_editLowerRange.GetSafeHwnd(), NULL);
  44. ImmAssociateContext(m_editUpperRange.GetSafeHwnd(), NULL);
  45. //
  46. // Load the syntax combo box.
  47. //
  48. ASSERT( GetDlgItem( IDC_CREATE_ATTRIB_SYNTAX ) );
  49. pwndSyntaxCombo = static_cast<CComboBox *>(GetDlgItem(IDC_CREATE_ATTRIB_SYNTAX));
  50. VERIFY( pwndSyntaxCombo );
  51. pwndSyntaxCombo->ResetContent() ;
  52. for ( UINT iSyntaxOrdinal = 0 ;
  53. iSyntaxOrdinal < SCHEMA_SYNTAX_UNKNOWN ;
  54. iSyntaxOrdinal++ )
  55. {
  56. pwndSyntaxCombo->AddString( g_Syntax[iSyntaxOrdinal].m_strSyntaxName );
  57. }
  58. pwndSyntaxCombo->SetCurSel( SyntaxOrdinal );
  59. OnSelchangeSyntax();
  60. return TRUE;
  61. }
  62. void
  63. CreateAttributeDialog::DoDataExchange(
  64. CDataExchange *pDX
  65. ) {
  66. CDialog::DoDataExchange( pDX );
  67. DDX_Text( pDX, IDC_CREATE_ATTRIB_CN, CommonName );
  68. DDV_MaxChars( pDX, CommonName, 64 );
  69. DDX_Text( pDX, IDC_CREATE_ATTRIB_LDN, LdapDisplayName );
  70. DDV_MaxChars( pDX, LdapDisplayName, 256 );
  71. DDX_Text( pDX, IDC_CREATE_ATTRIB_OID, OID );
  72. DDX_Text( pDX, IDC_DESCRIPTION_EDIT, Description );
  73. DDX_Check( pDX, IDC_CREATE_ATTRIB_VALUED, MultiValued );
  74. ASSERT( !pDX->m_bSaveAndValidate || SyntaxOrdinal == (UINT)
  75. static_cast<CComboBox *>(GetDlgItem(IDC_CREATE_ATTRIB_SYNTAX))->GetCurSel() );
  76. DDXV_VerifyAttribRange( pDX, g_Syntax[ SyntaxOrdinal ].m_fIsSigned,
  77. IDC_CREATE_ATTRIB_MIN, Min,
  78. IDC_CREATE_ATTRIB_MAX, Max );
  79. return;
  80. }
  81. inline void RemoveAttributeInfoLine( ADS_ATTR_INFO * attrInfo, DWORD dwLine, DWORD & dwArraySize )
  82. {
  83. dwArraySize--;
  84. for( ; dwLine < dwArraySize; dwLine++ )
  85. attrInfo[ dwLine ] = attrInfo[ dwLine + 1 ];
  86. }
  87. void
  88. CreateAttributeDialog::OnOK(
  89. void
  90. ) {
  91. HRESULT hr = S_OK;
  92. SchemaObject * pNewSchemaObject = NULL;
  93. DWORD dwValue = 0;
  94. IDirectoryObject * pDirObject = NULL;
  95. IDispatch * pDisp = NULL;
  96. CString strSchemaPath;
  97. CString strDecoratedName;
  98. ADSVALUE adsvClassValue,
  99. adsvLDAPDisplayName,
  100. adsvDescription,
  101. adsvAttributeID,
  102. adsvAttributeSyntax,
  103. adsvOmSyntax,
  104. adsvOmObjectClass,
  105. adsvIsSingleValued,
  106. adsvLowerRange,
  107. adsvUpperRange;
  108. //
  109. // Update parameters from the Dialog
  110. //
  111. if ( !UpdateData(TRUE) ) {
  112. return;
  113. }
  114. CWaitCursor wait;
  115. //
  116. // Validate the parameters.
  117. //
  118. //
  119. // Check for valid OID
  120. //
  121. int errorTypeStrID = 0;
  122. if (!OIDHasValidFormat(OID, errorTypeStrID))
  123. {
  124. CString errorType;
  125. CString text;
  126. VERIFY (errorType.LoadString(errorTypeStrID));
  127. text.FormatMessage(IDS_OID_FORMAT_INVALID, OID, errorType);
  128. DoErrMsgBox( ::GetActiveWindow(), TRUE, text );
  129. return;
  130. }
  131. if ( ( CommonName.IsEmpty() ) ||
  132. ( SyntaxOrdinal >= SCHEMA_SYNTAX_UNKNOWN ) ) {
  133. DoErrMsgBox( ::GetActiveWindow(), TRUE, IDS_ERR_CREATE_INVALID_PARAM );
  134. return;
  135. }
  136. //
  137. // Allocate a new schema cache object for this object.
  138. //
  139. pNewSchemaObject = new SchemaObject();
  140. if ( !pNewSchemaObject ) {
  141. DoErrMsgBox( ::GetActiveWindow(), TRUE, IDS_ERR_NO_MEM );
  142. return;
  143. }
  144. pNewSchemaObject->schemaObjectType = SCHMMGMT_ATTRIBUTE;
  145. pNewSchemaObject->commonName = CommonName;
  146. pNewSchemaObject->description = Description;
  147. //
  148. // Get the schema container.
  149. //
  150. pScopeControl->GetBasePathsInfo()->GetSchemaPath(strSchemaPath);
  151. hr = SchemaOpenObject(
  152. (LPWSTR)(LPCWSTR)strSchemaPath,
  153. IID_IDirectoryObject,
  154. (void **)&pDirObject );
  155. if ( FAILED(hr) )
  156. {
  157. if ( hr == ADS_EXTENDED_ERROR )
  158. DoExtErrMsgBox();
  159. else
  160. DoErrMsgBox( ::GetActiveWindow(), TRUE, IDS_ERR_NO_SCHEMA_PATH );
  161. }
  162. else
  163. {
  164. // During the attrib creation, some of the lines may need to be skipped. Use RemoveAttributeInfoLine()
  165. // for this. Removal should be done top to bottom of this array, because all the consts are relative to
  166. // the end of the array.
  167. ADS_ATTR_INFO attrInfo[] =
  168. {
  169. {g_ObjectClass, ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, &adsvClassValue, 1},
  170. {g_GlobalAttributeID, ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, &adsvAttributeID, 1},
  171. {g_IsSingleValued, ADS_ATTR_UPDATE, ADSTYPE_BOOLEAN, &adsvIsSingleValued, 1},
  172. {g_AttributeSyntax, ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, &adsvAttributeSyntax, 1},
  173. {g_omSyntax, ADS_ATTR_UPDATE, ADSTYPE_INTEGER, &adsvOmSyntax, 1},
  174. // make sure the following five attribute's indexes match with constants!!!
  175. {g_Description, ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, &adsvDescription, 1},
  176. {g_DisplayName, ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, &adsvLDAPDisplayName, 1},
  177. {g_omObjectClass, ADS_ATTR_UPDATE, ADSTYPE_OCTET_STRING, &adsvOmObjectClass, 1},
  178. {g_RangeLower, ADS_ATTR_UPDATE, ADSTYPE_INTEGER, &adsvLowerRange, 1},
  179. {g_RangeUpper, ADS_ATTR_UPDATE, ADSTYPE_INTEGER, &adsvUpperRange, 1},
  180. };
  181. DWORD dwAttrs = sizeof(attrInfo) / sizeof(attrInfo[0]);
  182. // relative constants. Describe the location of the attributes relative to the end of the list
  183. const DWORD dwAttrsDescription = 4; // fifth to last in the array
  184. const DWORD dwAttrsLdapName = 3; // fourth to last in the array
  185. const DWORD dwAttrsObjectClass = 2; // third to last in the array
  186. const DWORD dwAttrsRangeLower = 1; // second to last in the array
  187. const DWORD dwAttrsRangeUpper = 0; // last in the array
  188. // Object's Class -- "attributeSchema"
  189. adsvClassValue.dwType = ADSTYPE_CASE_IGNORE_STRING;
  190. adsvClassValue.CaseIgnoreString = const_cast<LPWSTR>( g_AttributeFilter );
  191. // OID
  192. adsvAttributeID.dwType = ADSTYPE_CASE_IGNORE_STRING;
  193. adsvAttributeID.CaseIgnoreString = const_cast<LPWSTR>( (LPCWSTR) OID );
  194. pNewSchemaObject->oid = OID;
  195. // Is this a single valued attribute?
  196. adsvIsSingleValued.dwType = ADSTYPE_BOOLEAN;
  197. adsvIsSingleValued.Boolean = !MultiValued;
  198. // Attribute Syntax (3 parts)
  199. ASSERT( g_Syntax[SyntaxOrdinal].m_pszAttributeSyntax );
  200. adsvAttributeSyntax.dwType = ADSTYPE_CASE_IGNORE_STRING;
  201. adsvAttributeSyntax.CaseIgnoreString = const_cast<LPWSTR>( g_Syntax[SyntaxOrdinal].m_pszAttributeSyntax );
  202. ASSERT( g_Syntax[SyntaxOrdinal].m_nOmSyntax );
  203. adsvOmSyntax.dwType = ADSTYPE_INTEGER;
  204. adsvOmSyntax.Integer = g_Syntax[SyntaxOrdinal].m_nOmSyntax;
  205. //
  206. // Skip the Description if not needed
  207. //
  208. if (Description.IsEmpty())
  209. {
  210. RemoveAttributeInfoLine(attrInfo, dwAttrs - dwAttrsDescription - 1, dwAttrs);
  211. }
  212. else
  213. {
  214. adsvDescription.dwType = ADSTYPE_CASE_IGNORE_STRING;
  215. adsvDescription.CaseIgnoreString = const_cast<LPWSTR>( (LPCWSTR) Description );
  216. }
  217. // skip Ldap Name if not needed
  218. if( LdapDisplayName.IsEmpty() )
  219. {
  220. RemoveAttributeInfoLine( attrInfo, dwAttrs - dwAttrsLdapName - 1, dwAttrs );
  221. }
  222. else
  223. {
  224. adsvLDAPDisplayName.dwType = ADSTYPE_CASE_IGNORE_STRING;
  225. adsvLDAPDisplayName.CaseIgnoreString = const_cast<LPWSTR>( (LPCWSTR) LdapDisplayName );
  226. pNewSchemaObject->ldapDisplayName = LdapDisplayName;
  227. }
  228. // skip OM-Object-Class if not needed
  229. if( 0 == g_Syntax[SyntaxOrdinal].m_octstrOmObjectClass.dwLength )
  230. {
  231. RemoveAttributeInfoLine( attrInfo, dwAttrs - dwAttrsObjectClass - 1, dwAttrs );
  232. }
  233. else
  234. {
  235. adsvOmObjectClass.dwType = ADSTYPE_OCTET_STRING;
  236. adsvOmObjectClass.OctetString = g_Syntax[SyntaxOrdinal].m_octstrOmObjectClass;
  237. }
  238. pNewSchemaObject->SyntaxOrdinal = SyntaxOrdinal;
  239. hr = S_OK;
  240. // Lower Range
  241. if( Min.IsEmpty() )
  242. {
  243. RemoveAttributeInfoLine( attrInfo, dwAttrs - dwAttrsRangeLower - 1, dwAttrs );
  244. }
  245. else
  246. {
  247. // if the function call fails, no attrib creation is performed
  248. hr = GetSafeSignedDWORDFromString( this, dwValue, Min,
  249. g_Syntax[SyntaxOrdinal].m_fIsSigned, GETSAFEINT_ALLOW_CANCEL );
  250. adsvLowerRange.dwType = ADSTYPE_INTEGER;
  251. adsvLowerRange.Integer = dwValue;
  252. }
  253. // Upper Range
  254. if( SUCCEEDED(hr) )
  255. {
  256. if( Max.IsEmpty() )
  257. {
  258. RemoveAttributeInfoLine( attrInfo, dwAttrs - dwAttrsRangeUpper - 1, dwAttrs );
  259. }
  260. else
  261. {
  262. // if function call fails, no attrib creation is performed
  263. hr = GetSafeSignedDWORDFromString( this, dwValue, Max,
  264. g_Syntax[SyntaxOrdinal].m_fIsSigned, GETSAFEINT_ALLOW_CANCEL );
  265. adsvUpperRange.dwType = ADSTYPE_INTEGER;
  266. adsvUpperRange.Integer = dwValue;
  267. }
  268. }
  269. //
  270. // Create the schema object.
  271. //
  272. if( SUCCEEDED(hr) )
  273. {
  274. pScopeControl->GetSchemaObjectPath( CommonName, strDecoratedName, ADS_FORMAT_LEAF );
  275. hr = pDirObject->CreateDSObject( const_cast<LPWSTR>( (LPCWSTR) strDecoratedName ),
  276. attrInfo, dwAttrs, &pDisp );
  277. if ( SUCCEEDED( hr ) )
  278. {
  279. // if there was no ldap name, and it worked, cn was used as ldap name
  280. if( LdapDisplayName.IsEmpty() )
  281. {
  282. ASSERT( pDisp );
  283. CComVariant value;
  284. CComQIPtr<IADs, &IID_IADs> iads(pDisp);
  285. if( !iads )
  286. {
  287. ASSERT( FALSE );
  288. }
  289. else
  290. {
  291. hr = iads->Get(CComBSTR(g_DisplayName), &value);
  292. ASSERT( SUCCEEDED(hr) ); // should be there!!!
  293. if( SUCCEEDED(hr) )
  294. {
  295. ASSERT( value.vt == VT_BSTR );
  296. pNewSchemaObject->ldapDisplayName = value.bstrVal;
  297. }
  298. }
  299. }
  300. //
  301. // Insert this object into the display cache.
  302. //
  303. hr = pScopeControl->g_SchemaCache.InsertSchemaObject( pNewSchemaObject );
  304. ASSERT( SUCCEEDED( hr ) );
  305. hr = pScopeControl->g_SchemaCache.InsertSortedSchemaObject( pNewSchemaObject );
  306. ASSERT( SUCCEEDED( hr ) );
  307. hr = pScopeControl->m_pConsole->UpdateAllViews( lpScopeDataObj,
  308. SCHMMGMT_ATTRIBUTES,
  309. SCHMMGMT_UPDATEVIEW_REFRESH );
  310. ASSERT( SUCCEEDED( hr ) );
  311. EndDialog( IDOK );
  312. }
  313. else // attribute creation failed
  314. {
  315. if ( hr == ADS_EXTENDED_ERROR )
  316. {
  317. DoExtErrMsgBox();
  318. }
  319. else
  320. {
  321. CString error_text;
  322. CString name;
  323. HRESULT last_ads_hr = GetLastADsError(hr, error_text, name);
  324. if (HRESULT_CODE(last_ads_hr) == ERROR_DS_INVALID_LDAP_DISPLAY_NAME)
  325. {
  326. error_text.LoadString(IDS_LDAPDISPLAYNAME_FORMAT_ERROR);
  327. }
  328. else
  329. {
  330. error_text = GetErrorMessage(hr,TRUE);
  331. }
  332. DoErrMsgBox( ::GetActiveWindow(), TRUE, error_text );
  333. }
  334. }
  335. if( pDisp )
  336. pDisp->Release();
  337. }
  338. }
  339. if( pDirObject )
  340. pDirObject->Release();
  341. }
  342. BEGIN_MESSAGE_MAP( CreateAttributeDialog, CDialog )
  343. ON_MESSAGE(WM_HELP, OnHelp)
  344. ON_MESSAGE(WM_CONTEXTMENU, OnContextHelp)
  345. ON_CBN_SELCHANGE(IDC_CREATE_ATTRIB_SYNTAX, OnSelchangeSyntax)
  346. END_MESSAGE_MAP()
  347. const DWORD CreateAttributeDialog::help_map[] =
  348. {
  349. IDI_ATTRIBUTE, NO_HELP,
  350. IDC_CREATE_ATTRIBUTE_PROMPT_STATIC, NO_HELP,
  351. IDC_CREATE_ATTRIB_CN, IDH_CREATE_ATTRIB_CN,
  352. IDC_CREATE_ATTRIB_LDN, IDH_CREATE_ATTRIB_LDN,
  353. IDC_CREATE_ATTRIB_OID, IDH_CREATE_ATTRIB_OID,
  354. IDC_DESCRIPTION_EDIT, IDH_ATTRIB_GENERAL_DESCRIPTION_EDIT,
  355. IDC_CREATE_ATTRIB_SYNTAX, IDH_CREATE_ATTRIB_SYNTAX,
  356. IDC_CREATE_ATTRIB_MIN, IDH_CREATE_ATTRIB_MIN,
  357. IDC_CREATE_ATTRIB_MAX, IDH_CREATE_ATTRIB_MAX,
  358. IDC_CREATE_ATTRIB_VALUED, IDH_CREATE_ATTRIB_VALUED,
  359. 0,0
  360. };
  361. void CreateAttributeDialog::OnSelchangeSyntax()
  362. {
  363. DWORD dw = 0; // temporary variable
  364. BOOL fIsSigned = FALSE;
  365. CComboBox * pwndSyntaxCombo = NULL;
  366. UINT nOldSyntax = SyntaxOrdinal;
  367. HRESULT hr = S_OK;
  368. ASSERT( GetDlgItem( IDC_CREATE_ATTRIB_SYNTAX ) );
  369. pwndSyntaxCombo = static_cast<CComboBox *>(GetDlgItem(IDC_CREATE_ATTRIB_SYNTAX));
  370. VERIFY( pwndSyntaxCombo );
  371. ASSERT( CB_ERR != pwndSyntaxCombo->GetCurSel() );
  372. SyntaxOrdinal = (UINT) pwndSyntaxCombo->GetCurSel();
  373. if( SyntaxOrdinal >= SCHEMA_SYNTAX_UNKNOWN )
  374. {
  375. ASSERT( FALSE );
  376. pwndSyntaxCombo->SetCurSel( SyntaxOrdinal = uDefaultSyntax );
  377. }
  378. fIsSigned = g_Syntax[ SyntaxOrdinal ].m_fIsSigned;
  379. if( GetDlgItemText( IDC_CREATE_ATTRIB_MIN, Min ) )
  380. {
  381. hr = GetSafeSignedDWORDFromString( this, dw, Min, fIsSigned, GETSAFEINT_ALLOW_CANCEL ) ;
  382. if( S_VALUE_MODIFIED == hr )
  383. SetDlgItemText( IDC_CREATE_ATTRIB_MIN, Min );
  384. }
  385. if( SUCCEEDED( hr ) && GetDlgItemText( IDC_CREATE_ATTRIB_MAX, Max ) )
  386. {
  387. hr = GetSafeSignedDWORDFromString( this, dw, Max, fIsSigned, GETSAFEINT_ALLOW_CANCEL );
  388. if( S_VALUE_MODIFIED == hr )
  389. SetDlgItemText( IDC_CREATE_ATTRIB_MAX, Max );
  390. }
  391. if( SUCCEEDED( hr ) )
  392. {
  393. m_editLowerRange.SetSigned( fIsSigned );
  394. m_editUpperRange.SetSigned( fIsSigned );
  395. }
  396. else
  397. {
  398. SyntaxOrdinal = nOldSyntax;
  399. pwndSyntaxCombo->SetCurSel( SyntaxOrdinal );
  400. }
  401. }