windows-nt/Source/XPSP1/NT/admin/snapin/schmmgmt/newattr.cpp
2020-09-26 16:20:57 +08:00

513 lines
14 KiB
C++

#include "stdafx.h"
#include "compdata.h"
#include "newattr.hpp"
// The default syntax for new attributes
const UINT uDefaultSyntax = 0;
//
// The create new attribute dialog box.
//
CreateAttributeDialog::CreateAttributeDialog(
ComponentData *pScope,
LPDATAOBJECT lpDataObject
) :
CDialog(IDD_CREATE_ATTRIBUTE, NULL),
fDialogLoaded( FALSE ),
MultiValued( FALSE ),
pScopeControl( pScope ),
lpScopeDataObj( lpDataObject ),
SyntaxOrdinal( uDefaultSyntax ),
m_editOID( CParsedEdit::EDIT_TYPE_OID ),
m_editLowerRange( CParsedEdit::EDIT_TYPE_UINT32 ),
m_editUpperRange( CParsedEdit::EDIT_TYPE_UINT32 )
{
ASSERT( uDefaultSyntax < SCHEMA_SYNTAX_UNKNOWN );
}
CreateAttributeDialog::~CreateAttributeDialog()
{ ; }
BOOL
CreateAttributeDialog::OnInitDialog()
{
CComboBox * pwndSyntaxCombo = NULL;
CDialog::OnInitDialog();
//
// Set Limits on Range controls
//
ASSERT( GetDlgItem(IDC_CREATE_ATTRIB_MIN) );
ASSERT( GetDlgItem(IDC_CREATE_ATTRIB_MAX) );
m_editOID.SubclassEdit( IDC_CREATE_ATTRIB_OID, this, cchMaxOID );
m_editLowerRange.SubclassEdit(IDC_CREATE_ATTRIB_MIN, this, cchMinMaxRange);
m_editUpperRange.SubclassEdit(IDC_CREATE_ATTRIB_MAX, this, cchMinMaxRange);
//
// Turn off IME support on the min/max edit boxes
//
ImmAssociateContext(m_editLowerRange.GetSafeHwnd(), NULL);
ImmAssociateContext(m_editUpperRange.GetSafeHwnd(), NULL);
//
// Load the syntax combo box.
//
ASSERT( GetDlgItem( IDC_CREATE_ATTRIB_SYNTAX ) );
pwndSyntaxCombo = static_cast<CComboBox *>(GetDlgItem(IDC_CREATE_ATTRIB_SYNTAX));
VERIFY( pwndSyntaxCombo );
pwndSyntaxCombo->ResetContent() ;
for ( UINT iSyntaxOrdinal = 0 ;
iSyntaxOrdinal < SCHEMA_SYNTAX_UNKNOWN ;
iSyntaxOrdinal++ )
{
pwndSyntaxCombo->AddString( g_Syntax[iSyntaxOrdinal].m_strSyntaxName );
}
pwndSyntaxCombo->SetCurSel( SyntaxOrdinal );
OnSelchangeSyntax();
return TRUE;
}
void
CreateAttributeDialog::DoDataExchange(
CDataExchange *pDX
) {
CDialog::DoDataExchange( pDX );
DDX_Text( pDX, IDC_CREATE_ATTRIB_CN, CommonName );
DDV_MaxChars( pDX, CommonName, 64 );
DDX_Text( pDX, IDC_CREATE_ATTRIB_LDN, LdapDisplayName );
DDV_MaxChars( pDX, LdapDisplayName, 256 );
DDX_Text( pDX, IDC_CREATE_ATTRIB_OID, OID );
DDX_Text( pDX, IDC_DESCRIPTION_EDIT, Description );
DDX_Check( pDX, IDC_CREATE_ATTRIB_VALUED, MultiValued );
ASSERT( !pDX->m_bSaveAndValidate || SyntaxOrdinal == (UINT)
static_cast<CComboBox *>(GetDlgItem(IDC_CREATE_ATTRIB_SYNTAX))->GetCurSel() );
DDXV_VerifyAttribRange( pDX, g_Syntax[ SyntaxOrdinal ].m_fIsSigned,
IDC_CREATE_ATTRIB_MIN, Min,
IDC_CREATE_ATTRIB_MAX, Max );
return;
}
inline void RemoveAttributeInfoLine( ADS_ATTR_INFO * attrInfo, DWORD dwLine, DWORD & dwArraySize )
{
dwArraySize--;
for( ; dwLine < dwArraySize; dwLine++ )
attrInfo[ dwLine ] = attrInfo[ dwLine + 1 ];
}
void
CreateAttributeDialog::OnOK(
void
) {
HRESULT hr = S_OK;
SchemaObject * pNewSchemaObject = NULL;
DWORD dwValue = 0;
IDirectoryObject * pDirObject = NULL;
IDispatch * pDisp = NULL;
CString strSchemaPath;
CString strDecoratedName;
ADSVALUE adsvClassValue,
adsvLDAPDisplayName,
adsvDescription,
adsvAttributeID,
adsvAttributeSyntax,
adsvOmSyntax,
adsvOmObjectClass,
adsvIsSingleValued,
adsvLowerRange,
adsvUpperRange;
//
// Update parameters from the Dialog
//
if ( !UpdateData(TRUE) ) {
return;
}
CWaitCursor wait;
//
// Validate the parameters.
//
//
// Check for valid OID
//
int errorTypeStrID = 0;
if (!OIDHasValidFormat(OID, errorTypeStrID))
{
CString errorType;
CString text;
VERIFY (errorType.LoadString(errorTypeStrID));
text.FormatMessage(IDS_OID_FORMAT_INVALID, OID, errorType);
DoErrMsgBox( ::GetActiveWindow(), TRUE, text );
return;
}
if ( ( CommonName.IsEmpty() ) ||
( SyntaxOrdinal >= SCHEMA_SYNTAX_UNKNOWN ) ) {
DoErrMsgBox( ::GetActiveWindow(), TRUE, IDS_ERR_CREATE_INVALID_PARAM );
return;
}
//
// Allocate a new schema cache object for this object.
//
pNewSchemaObject = new SchemaObject();
if ( !pNewSchemaObject ) {
DoErrMsgBox( ::GetActiveWindow(), TRUE, IDS_ERR_NO_MEM );
return;
}
pNewSchemaObject->schemaObjectType = SCHMMGMT_ATTRIBUTE;
pNewSchemaObject->commonName = CommonName;
pNewSchemaObject->description = Description;
//
// Get the schema container.
//
pScopeControl->GetBasePathsInfo()->GetSchemaPath(strSchemaPath);
hr = ADsGetObject(
(LPWSTR)(LPCWSTR)strSchemaPath,
IID_IDirectoryObject,
(void **)&pDirObject );
if ( FAILED(hr) )
{
if ( hr == ADS_EXTENDED_ERROR )
DoExtErrMsgBox();
else
DoErrMsgBox( ::GetActiveWindow(), TRUE, IDS_ERR_NO_SCHEMA_PATH );
}
else
{
// During the attrib creation, some of the lines may need to be skipped. Use RemoveAttributeInfoLine()
// for this. Removal should be done top to bottom of this array, because all the consts are relative to
// the end of the array.
ADS_ATTR_INFO attrInfo[] =
{
{g_ObjectClass, ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, &adsvClassValue, 1},
{g_GlobalAttributeID, ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, &adsvAttributeID, 1},
{g_IsSingleValued, ADS_ATTR_UPDATE, ADSTYPE_BOOLEAN, &adsvIsSingleValued, 1},
{g_AttributeSyntax, ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, &adsvAttributeSyntax, 1},
{g_omSyntax, ADS_ATTR_UPDATE, ADSTYPE_INTEGER, &adsvOmSyntax, 1},
// make sure the following five attribute's indexes match with constants!!!
{g_Description, ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, &adsvDescription, 1},
{g_DisplayName, ADS_ATTR_UPDATE, ADSTYPE_CASE_IGNORE_STRING, &adsvLDAPDisplayName, 1},
{g_omObjectClass, ADS_ATTR_UPDATE, ADSTYPE_OCTET_STRING, &adsvOmObjectClass, 1},
{g_RangeLower, ADS_ATTR_UPDATE, ADSTYPE_INTEGER, &adsvLowerRange, 1},
{g_RangeUpper, ADS_ATTR_UPDATE, ADSTYPE_INTEGER, &adsvUpperRange, 1},
};
DWORD dwAttrs = sizeof(attrInfo) / sizeof(attrInfo[0]);
// relative constants. Describe the location of the attributes relative to the end of the list
const DWORD dwAttrsDescription = 4; // fifth to last in the array
const DWORD dwAttrsLdapName = 3; // fourth to last in the array
const DWORD dwAttrsObjectClass = 2; // third to last in the array
const DWORD dwAttrsRangeLower = 1; // second to last in the array
const DWORD dwAttrsRangeUpper = 0; // last in the array
// Object's Class -- "attributeSchema"
adsvClassValue.dwType = ADSTYPE_CASE_IGNORE_STRING;
adsvClassValue.CaseIgnoreString = const_cast<LPWSTR>( g_AttributeFilter );
// OID
adsvAttributeID.dwType = ADSTYPE_CASE_IGNORE_STRING;
adsvAttributeID.CaseIgnoreString = const_cast<LPWSTR>( (LPCWSTR) OID );
pNewSchemaObject->oid = OID;
// Is this a single valued attribute?
adsvIsSingleValued.dwType = ADSTYPE_BOOLEAN;
adsvIsSingleValued.Boolean = !MultiValued;
// Attribute Syntax (3 parts)
ASSERT( g_Syntax[SyntaxOrdinal].m_pszAttributeSyntax );
adsvAttributeSyntax.dwType = ADSTYPE_CASE_IGNORE_STRING;
adsvAttributeSyntax.CaseIgnoreString = const_cast<LPWSTR>( g_Syntax[SyntaxOrdinal].m_pszAttributeSyntax );
ASSERT( g_Syntax[SyntaxOrdinal].m_nOmSyntax );
adsvOmSyntax.dwType = ADSTYPE_INTEGER;
adsvOmSyntax.Integer = g_Syntax[SyntaxOrdinal].m_nOmSyntax;
//
// Skip the Description if not needed
//
if (Description.IsEmpty())
{
RemoveAttributeInfoLine(attrInfo, dwAttrs - dwAttrsDescription - 1, dwAttrs);
}
else
{
adsvDescription.dwType = ADSTYPE_CASE_IGNORE_STRING;
adsvDescription.CaseIgnoreString = const_cast<LPWSTR>( (LPCWSTR) Description );
}
// skip Ldap Name if not needed
if( LdapDisplayName.IsEmpty() )
{
RemoveAttributeInfoLine( attrInfo, dwAttrs - dwAttrsLdapName - 1, dwAttrs );
}
else
{
adsvLDAPDisplayName.dwType = ADSTYPE_CASE_IGNORE_STRING;
adsvLDAPDisplayName.CaseIgnoreString = const_cast<LPWSTR>( (LPCWSTR) LdapDisplayName );
pNewSchemaObject->ldapDisplayName = LdapDisplayName;
}
// skip OM-Object-Class if not needed
if( 0 == g_Syntax[SyntaxOrdinal].m_octstrOmObjectClass.dwLength )
{
RemoveAttributeInfoLine( attrInfo, dwAttrs - dwAttrsObjectClass - 1, dwAttrs );
}
else
{
adsvOmObjectClass.dwType = ADSTYPE_OCTET_STRING;
adsvOmObjectClass.OctetString = g_Syntax[SyntaxOrdinal].m_octstrOmObjectClass;
}
pNewSchemaObject->SyntaxOrdinal = SyntaxOrdinal;
hr = S_OK;
// Lower Range
if( Min.IsEmpty() )
{
RemoveAttributeInfoLine( attrInfo, dwAttrs - dwAttrsRangeLower - 1, dwAttrs );
}
else
{
// if the function call fails, no attrib creation is performed
hr = GetSafeSignedDWORDFromString( this, dwValue, Min,
g_Syntax[SyntaxOrdinal].m_fIsSigned, GETSAFEINT_ALLOW_CANCEL );
adsvLowerRange.dwType = ADSTYPE_INTEGER;
adsvLowerRange.Integer = dwValue;
}
// Upper Range
if( SUCCEEDED(hr) )
{
if( Max.IsEmpty() )
{
RemoveAttributeInfoLine( attrInfo, dwAttrs - dwAttrsRangeUpper - 1, dwAttrs );
}
else
{
// if function call fails, no attrib creation is performed
hr = GetSafeSignedDWORDFromString( this, dwValue, Max,
g_Syntax[SyntaxOrdinal].m_fIsSigned, GETSAFEINT_ALLOW_CANCEL );
adsvUpperRange.dwType = ADSTYPE_INTEGER;
adsvUpperRange.Integer = dwValue;
}
}
//
// Create the schema object.
//
if( SUCCEEDED(hr) )
{
pScopeControl->GetSchemaObjectPath( CommonName, strDecoratedName, ADS_FORMAT_LEAF );
hr = pDirObject->CreateDSObject( const_cast<LPWSTR>( (LPCWSTR) strDecoratedName ),
attrInfo, dwAttrs, &pDisp );
if ( SUCCEEDED( hr ) )
{
// if there was no ldap name, and it worked, cn was used as ldap name
if( LdapDisplayName.IsEmpty() )
{
ASSERT( pDisp );
CComVariant value;
CComQIPtr<IADs, &IID_IADs> iads(pDisp);
if( !iads )
{
ASSERT( FALSE );
}
else
{
hr = iads->Get(CComBSTR(g_DisplayName), &value);
ASSERT( SUCCEEDED(hr) ); // should be there!!!
if( SUCCEEDED(hr) )
{
ASSERT( value.vt == VT_BSTR );
pNewSchemaObject->ldapDisplayName = value.bstrVal;
}
}
}
//
// Insert this object into the display cache.
//
hr = pScopeControl->g_SchemaCache.InsertSchemaObject( pNewSchemaObject );
ASSERT( SUCCEEDED( hr ) );
hr = pScopeControl->g_SchemaCache.InsertSortedSchemaObject( pNewSchemaObject );
ASSERT( SUCCEEDED( hr ) );
hr = pScopeControl->m_pConsole->UpdateAllViews( lpScopeDataObj,
SCHMMGMT_ATTRIBUTES,
SCHMMGMT_UPDATEVIEW_REFRESH );
ASSERT( SUCCEEDED( hr ) );
EndDialog( IDOK );
}
else // attribute creation failed
{
if ( hr == ADS_EXTENDED_ERROR )
{
DoExtErrMsgBox();
}
else
{
CString error_text;
CString name;
HRESULT last_ads_hr = GetLastADsError(hr, error_text, name);
if (HRESULT_CODE(last_ads_hr) == ERROR_DS_INVALID_LDAP_DISPLAY_NAME)
{
error_text.LoadString(IDS_LDAPDISPLAYNAME_FORMAT_ERROR);
}
else
{
error_text = GetErrorMessage(hr,TRUE);
}
DoErrMsgBox( ::GetActiveWindow(), TRUE, error_text );
}
}
if( pDisp )
pDisp->Release();
}
}
if( pDirObject )
pDirObject->Release();
}
BEGIN_MESSAGE_MAP( CreateAttributeDialog, CDialog )
ON_MESSAGE(WM_HELP, OnHelp)
ON_MESSAGE(WM_CONTEXTMENU, OnContextHelp)
ON_CBN_SELCHANGE(IDC_CREATE_ATTRIB_SYNTAX, OnSelchangeSyntax)
END_MESSAGE_MAP()
const DWORD CreateAttributeDialog::help_map[] =
{
IDI_ATTRIBUTE, NO_HELP,
IDC_CREATE_ATTRIBUTE_PROMPT_STATIC, NO_HELP,
IDC_CREATE_ATTRIB_CN, IDH_CREATE_ATTRIB_CN,
IDC_CREATE_ATTRIB_LDN, IDH_CREATE_ATTRIB_LDN,
IDC_CREATE_ATTRIB_OID, IDH_CREATE_ATTRIB_OID,
IDC_DESCRIPTION_EDIT, IDH_ATTRIB_GENERAL_DESCRIPTION_EDIT,
IDC_CREATE_ATTRIB_SYNTAX, IDH_CREATE_ATTRIB_SYNTAX,
IDC_CREATE_ATTRIB_MIN, IDH_CREATE_ATTRIB_MIN,
IDC_CREATE_ATTRIB_MAX, IDH_CREATE_ATTRIB_MAX,
IDC_CREATE_ATTRIB_VALUED, IDH_CREATE_ATTRIB_VALUED,
0,0
};
void CreateAttributeDialog::OnSelchangeSyntax()
{
DWORD dw = 0; // temporary variable
BOOL fIsSigned = FALSE;
CComboBox * pwndSyntaxCombo = NULL;
UINT nOldSyntax = SyntaxOrdinal;
HRESULT hr = S_OK;
ASSERT( GetDlgItem( IDC_CREATE_ATTRIB_SYNTAX ) );
pwndSyntaxCombo = static_cast<CComboBox *>(GetDlgItem(IDC_CREATE_ATTRIB_SYNTAX));
VERIFY( pwndSyntaxCombo );
ASSERT( CB_ERR != pwndSyntaxCombo->GetCurSel() );
SyntaxOrdinal = (UINT) pwndSyntaxCombo->GetCurSel();
if( SyntaxOrdinal >= SCHEMA_SYNTAX_UNKNOWN )
{
ASSERT( FALSE );
pwndSyntaxCombo->SetCurSel( SyntaxOrdinal = uDefaultSyntax );
}
fIsSigned = g_Syntax[ SyntaxOrdinal ].m_fIsSigned;
if( GetDlgItemText( IDC_CREATE_ATTRIB_MIN, Min ) )
{
hr = GetSafeSignedDWORDFromString( this, dw, Min, fIsSigned, GETSAFEINT_ALLOW_CANCEL ) ;
if( S_VALUE_MODIFIED == hr )
SetDlgItemText( IDC_CREATE_ATTRIB_MIN, Min );
}
if( SUCCEEDED( hr ) && GetDlgItemText( IDC_CREATE_ATTRIB_MAX, Max ) )
{
hr = GetSafeSignedDWORDFromString( this, dw, Max, fIsSigned, GETSAFEINT_ALLOW_CANCEL );
if( S_VALUE_MODIFIED == hr )
SetDlgItemText( IDC_CREATE_ATTRIB_MAX, Max );
}
if( SUCCEEDED( hr ) )
{
m_editLowerRange.SetSigned( fIsSigned );
m_editUpperRange.SetSigned( fIsSigned );
}
else
{
SyntaxOrdinal = nOldSyntax;
pwndSyntaxCombo->SetCurSel( SyntaxOrdinal );
}
}