1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 using System.Text;
6 using System.Diagnostics;
7 using System.ComponentModel;
8 using System.Runtime.InteropServices;
9 
10 namespace System.DirectoryServices.ActiveDirectory
11 {
12     internal enum SearchFlags : int
13     {
14         None = 0,
15         IsIndexed = 1,
16         IsIndexedOverContainer = 2,
17         IsInAnr = 4,
18         IsOnTombstonedObject = 8,
19         IsTupleIndexed = 32
20     }
21 
22     public class ActiveDirectorySchemaProperty : IDisposable
23     {
24         // private variables
25         private DirectoryEntry _schemaEntry = null;
26         private DirectoryEntry _propertyEntry = null;
27         private DirectoryEntry _abstractPropertyEntry = null;
28         private NativeComInterfaces.IAdsProperty _iadsProperty = null;
29         private DirectoryContext _context = null;
30         internal bool isBound = false;
31         private bool _disposed = false;
32         private ActiveDirectorySchema _schema = null;
33         private bool _propertiesFromSchemaContainerInitialized = false;
34         private bool _isDefunctOnServer = false;
35         private SearchResult _propertyValuesFromServer = null;
36 
37         // private variables for caching properties
38         private string _ldapDisplayName = null;
39         private string _commonName = null;
40         private string _oid = null;
41         private ActiveDirectorySyntax _syntax = (ActiveDirectorySyntax)(-1);
42         private bool _syntaxInitialized = false;
43         private string _description = null;
44         private bool _descriptionInitialized = false;
45         private bool _isSingleValued = false;
46         private bool _isSingleValuedInitialized = false;
47         private bool _isInGlobalCatalog = false;
48         private bool _isInGlobalCatalogInitialized = false;
49         private Nullable<Int32> _rangeLower = null;
50         private bool _rangeLowerInitialized = false;
51         private Nullable<Int32> _rangeUpper = null;
52         private bool _rangeUpperInitialized = false;
53         private bool _isDefunct = false;
54         private SearchFlags _searchFlags = SearchFlags.None;
55         private bool _searchFlagsInitialized = false;
56         private ActiveDirectorySchemaProperty _linkedProperty = null;
57         private bool _linkedPropertyInitialized = false;
58         private Nullable<Int32> _linkId = null;
59         private bool _linkIdInitialized = false;
60         private byte[] _schemaGuidBinaryForm = null;
61 
62         // OMObjectClass values for the syntax
63         //0x2B0C0287731C00854A
64         private static OMObjectClass s_dnOMObjectClass = new OMObjectClass(new byte[] { 0x2B, 0x0C, 0x02, 0x87, 0x73, 0x1C, 0x00, 0x85, 0x4A });
65         //0x2A864886F7140101010C
66         private static OMObjectClass s_dNWithStringOMObjectClass = new OMObjectClass(new byte[] { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x14, 0x01, 0x01, 0x01, 0x0C });
67         //0x2A864886F7140101010B
68         private static OMObjectClass s_dNWithBinaryOMObjectClass = new OMObjectClass(new byte[] { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x14, 0x01, 0x01, 0x01, 0x0B });
69         //0x2A864886F71401010106
70         private static OMObjectClass s_replicaLinkOMObjectClass = new OMObjectClass(new byte[] { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x14, 0x01, 0x01, 0x01, 0x06 });
71         //0x2B0C0287731C00855C
72         private static OMObjectClass s_presentationAddressOMObjectClass = new OMObjectClass(new byte[] { 0x2B, 0x0C, 0x02, 0x87, 0x73, 0x1C, 0x00, 0x85, 0x5C });
73         //0x2B0C0287731C00853E
74         private static OMObjectClass s_accessPointDnOMObjectClass = new OMObjectClass(new byte[] { 0x2B, 0x0C, 0x02, 0x87, 0x73, 0x1C, 0x00, 0x85, 0x3E });
75         //0x56060102050B1D
76         private static OMObjectClass s_oRNameOMObjectClass = new OMObjectClass(new byte[] { 0x56, 0x06, 0x01, 0x02, 0x05, 0x0B, 0x1D });
77 
78         // syntaxes
79         private static int s_syntaxesCount = 23;
80         private static Syntax[] s_syntaxes = {/* CaseExactString */ new Syntax("2.5.5.3", 27, null),
81 											   /* CaseIgnoreString */ new Syntax("2.5.5.4", 20, null),
82 											   /* NumericString */ new Syntax("2.5.5.6", 18, null),
83 											   /* DirectoryString */ new Syntax("2.5.5.12", 64, null),
84 											   /* OctetString */ new Syntax("2.5.5.10", 4, null),
85 											   /* SecurityDescriptor */ new Syntax("2.5.5.15", 66, null),
86 											   /* Int */ new Syntax("2.5.5.9", 2, null),
87 											   /* Int64 */ new Syntax("2.5.5.16", 65, null),
88 											   /* Bool */ new Syntax("2.5.5.8", 1, null),
89 											   /* Oid */ new Syntax("2.5.5.2", 6, null),
90 											   /* GeneralizedTime */ new Syntax("2.5.5.11", 24, null),
91 											   /* UtcTime */ new Syntax("2.5.5.11", 23, null),
92 											   /* DN */ new Syntax("2.5.5.1", 127, s_dnOMObjectClass),
93 											   /* DNWithBinary */ new Syntax("2.5.5.7", 127, s_dNWithBinaryOMObjectClass),
94 											   /* DNWithString */ new Syntax("2.5.5.14", 127, s_dNWithStringOMObjectClass),
95 											   /* Enumeration */ new Syntax("2.5.5.9", 10, null),
96 											   /* IA5String */ new Syntax("2.5.5.5", 22, null),
97 											   /* PrintableString */ new Syntax("2.5.5.5", 19, null),
98 											   /* Sid */ new Syntax("2.5.5.17", 4, null),
99 											   /* AccessPointDN */ new Syntax("2.5.5.14", 127, s_accessPointDnOMObjectClass),
100 											   /* ORName */ new Syntax("2.5.5.7", 127, s_oRNameOMObjectClass),
101 											   /* PresentationAddress */ new Syntax("2.5.5.13", 127, s_presentationAddressOMObjectClass),
102 											   /* ReplicaLink */ new Syntax("2.5.5.10", 127, s_replicaLinkOMObjectClass)};
103 
104         #region constructors
ActiveDirectorySchemaProperty(DirectoryContext context, string ldapDisplayName)105         public ActiveDirectorySchemaProperty(DirectoryContext context, string ldapDisplayName)
106         {
107             if (context == null)
108             {
109                 throw new ArgumentNullException("context");
110             }
111 
112             if ((context.Name == null) && (!context.isRootDomain()))
113             {
114                 throw new ArgumentException(SR.ContextNotAssociatedWithDomain, "context");
115             }
116 
117             if (context.Name != null)
118             {
119                 // the target should be a valid forest name or a server
120                 if (!((context.isRootDomain()) || (context.isADAMConfigSet()) || (context.isServer())))
121                 {
122                     throw new ArgumentException(SR.NotADOrADAM, "context");
123                 }
124             }
125 
126             if (ldapDisplayName == null)
127             {
128                 throw new ArgumentNullException("ldapDisplayName");
129             }
130 
131             if (ldapDisplayName.Length == 0)
132             {
133                 throw new ArgumentException(SR.EmptyStringParameter, "ldapDisplayName");
134             }
135 
136             _context = new DirectoryContext(context);
137 
138             // validate the context
139             _schemaEntry = DirectoryEntryManager.GetDirectoryEntry(context, WellKnownDN.SchemaNamingContext);
140             _schemaEntry.Bind(true);
141 
142             _ldapDisplayName = ldapDisplayName;
143             // common name of the property defaults to the ldap display name
144             _commonName = ldapDisplayName;
145 
146             // set the bind flag
147             this.isBound = false;
148         }
149 
150         // internal constructor
ActiveDirectorySchemaProperty(DirectoryContext context, string ldapDisplayName, DirectoryEntry propertyEntry, DirectoryEntry schemaEntry)151         internal ActiveDirectorySchemaProperty(DirectoryContext context, string ldapDisplayName, DirectoryEntry propertyEntry, DirectoryEntry schemaEntry)
152         {
153             _context = context;
154             _ldapDisplayName = ldapDisplayName;
155 
156             // common name of the property defaults to the ldap display name
157             _propertyEntry = propertyEntry;
158             _isDefunctOnServer = false;
159             _isDefunct = _isDefunctOnServer;
160 
161             try
162             {
163                 // initialize the directory entry for the abstract schema class
164                 _abstractPropertyEntry = DirectoryEntryManager.GetDirectoryEntryInternal(context, "LDAP://" + context.GetServerName() + "/schema/" + ldapDisplayName);
165                 _iadsProperty = (NativeComInterfaces.IAdsProperty)_abstractPropertyEntry.NativeObject;
166             }
167             catch (COMException e)
168             {
169                 if (e.ErrorCode == unchecked((int)0x80005000))
170                 {
171                     throw new ActiveDirectoryObjectNotFoundException(SR.DSNotFound, typeof(ActiveDirectorySchemaProperty), ldapDisplayName);
172                 }
173                 else
174                 {
175                     throw ExceptionHelper.GetExceptionFromCOMException(context, e);
176                 }
177             }
178             catch (InvalidCastException)
179             {
180                 // this means that we found an object but it is not a schema class
181                 throw new ActiveDirectoryObjectNotFoundException(SR.DSNotFound, typeof(ActiveDirectorySchemaProperty), ldapDisplayName);
182             }
183             catch (ActiveDirectoryObjectNotFoundException)
184             {
185                 // this is the case where the context is a config set and we could not find an ADAM instance in that config set
186                 throw new ActiveDirectoryOperationException(SR.Format(SR.ADAMInstanceNotFoundInConfigSet , context.Name));
187             }
188 
189             // set the bind flag
190             this.isBound = true;
191         }
192 
ActiveDirectorySchemaProperty(DirectoryContext context, string commonName, SearchResult propertyValuesFromServer, DirectoryEntry schemaEntry)193         internal ActiveDirectorySchemaProperty(DirectoryContext context, string commonName, SearchResult propertyValuesFromServer, DirectoryEntry schemaEntry)
194         {
195             _context = context;
196             _schemaEntry = schemaEntry;
197 
198             // all relevant properties have already been retrieved from the server
199             _propertyValuesFromServer = propertyValuesFromServer;
200             Debug.Assert(_propertyValuesFromServer != null);
201             _propertiesFromSchemaContainerInitialized = true;
202             _propertyEntry = GetSchemaPropertyDirectoryEntry();
203 
204             // names
205             _commonName = commonName;
206             _ldapDisplayName = (string)GetValueFromCache(PropertyManager.LdapDisplayName, true);
207 
208             // this constructor is only called for defunct classes
209             _isDefunctOnServer = true;
210             _isDefunct = _isDefunctOnServer;
211 
212             // set the bind flag
213             this.isBound = true;
214         }
215 
ActiveDirectorySchemaProperty(DirectoryContext context, string commonName, string ldapDisplayName, DirectoryEntry propertyEntry, DirectoryEntry schemaEntry)216         internal ActiveDirectorySchemaProperty(DirectoryContext context, string commonName, string ldapDisplayName, DirectoryEntry propertyEntry, DirectoryEntry schemaEntry)
217         {
218             _context = context;
219             _schemaEntry = schemaEntry;
220             _propertyEntry = propertyEntry;
221 
222             // names
223             _commonName = commonName;
224             _ldapDisplayName = ldapDisplayName;
225 
226             // this constructor is only called for defunct properties
227             _isDefunctOnServer = true;
228             _isDefunct = _isDefunctOnServer;
229 
230             // set the bind flag
231             this.isBound = true;
232         }
233 
234         #endregion constructors
235 
236         #region IDisposable
237 
Dispose()238         public void Dispose()
239         {
240             Dispose(true);
241         }
242 
243         // private Dispose method
Dispose(bool disposing)244         protected virtual void Dispose(bool disposing)
245         {
246             if (!_disposed)
247             {
248                 // check if this is an explicit Dispose
249                 // only then clean up the directory entries
250                 if (disposing)
251                 {
252                     // dispose schema entry
253                     if (_schemaEntry != null)
254                     {
255                         _schemaEntry.Dispose();
256                         _schemaEntry = null;
257                     }
258                     // dispose property entry
259                     if (_propertyEntry != null)
260                     {
261                         _propertyEntry.Dispose();
262                         _propertyEntry = null;
263                     }
264                     // dispose abstract class entry
265                     if (_abstractPropertyEntry != null)
266                     {
267                         _abstractPropertyEntry.Dispose();
268                         _abstractPropertyEntry = null;
269                     }
270                     // dispose the schema object
271                     if (_schema != null)
272                     {
273                         _schema.Dispose();
274                     }
275                 }
276 
277                 _disposed = true;
278             }
279         }
280         #endregion IDisposable
281 
282         #region public methods
FindByName(DirectoryContext context, string ldapDisplayName)283         public static ActiveDirectorySchemaProperty FindByName(DirectoryContext context, string ldapDisplayName)
284         {
285             ActiveDirectorySchemaProperty schemaProperty = null;
286 
287             if (context == null)
288             {
289                 throw new ArgumentNullException("context");
290             }
291 
292             if ((context.Name == null) && (!context.isRootDomain()))
293             {
294                 throw new ArgumentException(SR.ContextNotAssociatedWithDomain, "context");
295             }
296 
297             if (context.Name != null)
298             {
299                 // the target should be a valid forest name or a server
300                 if (!((context.isRootDomain()) || (context.isADAMConfigSet()) || (context.isServer())))
301                 {
302                     throw new ArgumentException(SR.NotADOrADAM, "context");
303                 }
304             }
305 
306             if (ldapDisplayName == null)
307             {
308                 throw new ArgumentNullException("ldapDisplayName");
309             }
310 
311             if (ldapDisplayName.Length == 0)
312             {
313                 throw new ArgumentException(SR.EmptyStringParameter, "ldapDisplayName");
314             }
315 
316             //  work with copy of the context
317             context = new DirectoryContext(context);
318 
319             // create a schema property
320             schemaProperty = new ActiveDirectorySchemaProperty(context, ldapDisplayName, (DirectoryEntry)null, null);
321 
322             return schemaProperty;
323         }
324 
Save()325         public void Save()
326         {
327             CheckIfDisposed();
328 
329             if (!isBound)
330             {
331                 try
332                 {
333                     // create a new directory entry for this class
334                     if (_schemaEntry == null)
335                     {
336                         _schemaEntry = DirectoryEntryManager.GetDirectoryEntry(_context, WellKnownDN.SchemaNamingContext);
337                     }
338 
339                     // this will create the class and set the CN value
340                     string rdn = "CN=" + _commonName;
341                     rdn = Utils.GetEscapedPath(rdn);
342                     _propertyEntry = _schemaEntry.Children.Add(rdn, "attributeSchema");
343                 }
344                 catch (COMException e)
345                 {
346                     throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
347                 }
348                 catch (ActiveDirectoryObjectNotFoundException)
349                 {
350                     // this is the case where the context is a config set and we could not find an ADAM instance in that config set
351                     throw new ActiveDirectoryOperationException(SR.Format(SR.ADAMInstanceNotFoundInConfigSet , _context.Name));
352                 }
353 
354                 // set the ldap display name property
355                 SetProperty(PropertyManager.LdapDisplayName, _ldapDisplayName);
356 
357                 // set the oid value
358                 SetProperty(PropertyManager.AttributeID, _oid);
359 
360                 // set the syntax
361                 if (_syntax != (ActiveDirectorySyntax)(-1))
362                 {
363                     SetSyntax(_syntax);
364                 }
365 
366                 // set the description
367                 SetProperty(PropertyManager.Description, _description);
368 
369                 // set the isSingleValued attribute
370                 _propertyEntry.Properties[PropertyManager.IsSingleValued].Value = _isSingleValued;
371 
372                 // set the isGlobalCatalogReplicated attribute
373                 _propertyEntry.Properties[PropertyManager.IsMemberOfPartialAttributeSet].Value = _isInGlobalCatalog;
374 
375                 // set the isDefunct attribute
376                 _propertyEntry.Properties[PropertyManager.IsDefunct].Value = _isDefunct;
377 
378                 // set the range lower attribute
379                 if (_rangeLower != null)
380                 {
381                     _propertyEntry.Properties[PropertyManager.RangeLower].Value = (int)_rangeLower.Value;
382                 }
383 
384                 // set the range upper attribute
385                 if (_rangeUpper != null)
386                 {
387                     _propertyEntry.Properties[PropertyManager.RangeUpper].Value = (int)_rangeUpper.Value;
388                 }
389 
390                 // set the searchFlags attribute
391                 if (_searchFlags != SearchFlags.None)
392                 {
393                     _propertyEntry.Properties[PropertyManager.SearchFlags].Value = (int)_searchFlags;
394                 }
395 
396                 // set the link id
397                 if (_linkId != null)
398                 {
399                     _propertyEntry.Properties[PropertyManager.LinkID].Value = (int)_linkId.Value;
400                 }
401 
402                 // set the schemaIDGuid property
403                 if (_schemaGuidBinaryForm != null)
404                 {
405                     SetProperty(PropertyManager.SchemaIDGuid, _schemaGuidBinaryForm);
406                 }
407             }
408 
409             try
410             {
411                 // commit the classEntry to server
412                 _propertyEntry.CommitChanges();
413 
414                 // Refresh the schema cache on the schema role owner
415                 if (_schema == null)
416                 {
417                     ActiveDirectorySchema schemaObject = ActiveDirectorySchema.GetSchema(_context);
418                     bool alreadyUsingSchemaRoleOwnerContext = false;
419                     DirectoryServer schemaRoleOwner = null;
420 
421                     try
422                     {
423                         //
424                         // if we are not already talking to the schema role owner, change the context
425                         //
426                         schemaRoleOwner = schemaObject.SchemaRoleOwner;
427                         if (Utils.Compare(schemaRoleOwner.Name, _context.GetServerName()) != 0)
428                         {
429                             DirectoryContext schemaRoleOwnerContext = Utils.GetNewDirectoryContext(schemaRoleOwner.Name, DirectoryContextType.DirectoryServer, _context);
430                             _schema = ActiveDirectorySchema.GetSchema(schemaRoleOwnerContext);
431                         }
432                         else
433                         {
434                             alreadyUsingSchemaRoleOwnerContext = true;
435                             _schema = schemaObject;
436                         }
437                     }
438                     finally
439                     {
440                         if (schemaRoleOwner != null)
441                         {
442                             schemaRoleOwner.Dispose();
443                         }
444                         if (!alreadyUsingSchemaRoleOwnerContext)
445                         {
446                             schemaObject.Dispose();
447                         }
448                     }
449                 }
450                 _schema.RefreshSchema();
451             }
452             catch (COMException e)
453             {
454                 throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
455             }
456 
457             // now that the changes are committed to the server
458             // update the defunct/non-defunct status of the class on the server
459             _isDefunctOnServer = _isDefunct;
460 
461             // invalidate all properties
462             _commonName = null;
463             _oid = null;
464             _syntaxInitialized = false;
465             _descriptionInitialized = false;
466             _isSingleValuedInitialized = false;
467             _isInGlobalCatalogInitialized = false;
468             _rangeLowerInitialized = false;
469             _rangeUpperInitialized = false;
470             _searchFlagsInitialized = false;
471             _linkedPropertyInitialized = false;
472             _linkIdInitialized = false;
473             _schemaGuidBinaryForm = null;
474             _propertiesFromSchemaContainerInitialized = false;
475 
476             // set bind flag
477             isBound = true;
478         }
479 
ToString()480         public override string ToString() => Name;
481 
GetDirectoryEntry()482         public DirectoryEntry GetDirectoryEntry()
483         {
484             CheckIfDisposed();
485 
486             if (!isBound)
487             {
488                 throw new InvalidOperationException(SR.CannotGetObject);
489             }
490 
491             GetSchemaPropertyDirectoryEntry();
492             Debug.Assert(_propertyEntry != null);
493 
494             return DirectoryEntryManager.GetDirectoryEntryInternal(_context, _propertyEntry.Path);
495         }
496         #endregion public methods
497 
498         #region public properties
499 
500         public string Name
501         {
502             get
503             {
504                 CheckIfDisposed();
505                 return _ldapDisplayName;
506             }
507         }
508 
509         public string CommonName
510         {
511             get
512             {
513                 CheckIfDisposed();
514 
515                 if (isBound)
516                 {
517                     if (_commonName == null)
518                     {
519                         // get the property from the server
520                         _commonName = (string)GetValueFromCache(PropertyManager.Cn, true);
521                     }
522                 }
523                 return _commonName;
524             }
525             set
526             {
527                 CheckIfDisposed();
528 
529                 if (value != null && value.Length == 0)
530                     throw new ArgumentException(SR.EmptyStringParameter, "value");
531 
532                 if (isBound)
533                 {
534                     // set the value on the directory entry
535                     SetProperty(PropertyManager.Cn, value);
536                 }
537                 _commonName = value;
538             }
539         }
540 
541         public string Oid
542         {
543             get
544             {
545                 CheckIfDisposed();
546 
547                 if (isBound)
548                 {
549                     if (_oid == null)
550                     {
551                         // get the property from the abstract schema/ schema container
552                         // (for non-defunt classes this property is available in the abstract schema)
553                         if (!_isDefunctOnServer)
554                         {
555                             try
556                             {
557                                 _oid = _iadsProperty.OID;
558                             }
559                             catch (COMException e)
560                             {
561                                 throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
562                             }
563                         }
564                         else
565                         {
566                             _oid = (string)GetValueFromCache(PropertyManager.AttributeID, true);
567                         }
568                     }
569                 }
570                 return _oid;
571             }
572             set
573             {
574                 CheckIfDisposed();
575 
576                 if (value != null && value.Length == 0)
577                     throw new ArgumentException(SR.EmptyStringParameter, "value");
578 
579                 if (isBound)
580                 {
581                     // set the value on the directory entry
582                     SetProperty(PropertyManager.AttributeID, value);
583                 }
584                 _oid = value;
585             }
586         }
587 
588         public ActiveDirectorySyntax Syntax
589         {
590             get
591             {
592                 CheckIfDisposed();
593 
594                 if (isBound)
595                 {
596                     if (!_syntaxInitialized)
597                     {
598                         byte[] omObjectClassBinaryForm = (byte[])GetValueFromCache(PropertyManager.OMObjectClass, false);
599                         OMObjectClass omObjectClass = (omObjectClassBinaryForm != null) ? new OMObjectClass(omObjectClassBinaryForm) : null;
600 
601                         _syntax = MapSyntax((string)GetValueFromCache(PropertyManager.AttributeSyntax, true),
602                             (int)GetValueFromCache(PropertyManager.OMSyntax, true),
603                             omObjectClass);
604                         _syntaxInitialized = true;
605                     }
606                 }
607                 return _syntax;
608             }
609             set
610             {
611                 CheckIfDisposed();
612 
613                 if (value < ActiveDirectorySyntax.CaseExactString || value > ActiveDirectorySyntax.ReplicaLink)
614                 {
615                     throw new InvalidEnumArgumentException("value", (int)value, typeof(ActiveDirectorySyntax));
616                 }
617 
618                 if (isBound)
619                 {
620                     // set the value on the directory entry
621                     SetSyntax(value);
622                 }
623                 _syntax = value;
624             }
625         }
626 
627         public string Description
628         {
629             get
630             {
631                 CheckIfDisposed();
632 
633                 if (isBound)
634                 {
635                     if (!_descriptionInitialized)
636                     {
637                         // get the property from the server
638                         _description = (string)GetValueFromCache(PropertyManager.Description, false);
639                         _descriptionInitialized = true;
640                     }
641                 }
642                 return _description;
643             }
644             set
645             {
646                 CheckIfDisposed();
647 
648                 if (value != null && value.Length == 0)
649                     throw new ArgumentException(SR.EmptyStringParameter, "value");
650 
651                 if (isBound)
652                 {
653                     // set the value on the directory entry
654                     SetProperty(PropertyManager.Description, value);
655                 }
656                 _description = value;
657             }
658         }
659 
660         public bool IsSingleValued
661         {
662             get
663             {
664                 CheckIfDisposed();
665 
666                 if (isBound)
667                 {
668                     if (!_isSingleValuedInitialized)
669                     {
670                         // get the property from the abstract schema/ schema container
671                         // (for non-defunt classes this property is available in the abstract schema)
672                         if (!_isDefunctOnServer)
673                         {
674                             try
675                             {
676                                 _isSingleValued = !_iadsProperty.MultiValued;
677                             }
678                             catch (COMException e)
679                             {
680                                 throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
681                             }
682                         }
683                         else
684                         {
685                             _isSingleValued = (bool)GetValueFromCache(PropertyManager.IsSingleValued, true);
686                         }
687                         _isSingleValuedInitialized = true;
688                     }
689                 }
690                 return _isSingleValued;
691             }
692             set
693             {
694                 CheckIfDisposed();
695 
696                 if (isBound)
697                 {
698                     // get the distinguished name to construct the directory entry
699                     GetSchemaPropertyDirectoryEntry();
700                     Debug.Assert(_propertyEntry != null);
701 
702                     // set the value on the directory entry
703                     _propertyEntry.Properties[PropertyManager.IsSingleValued].Value = value;
704                 }
705                 _isSingleValued = value;
706             }
707         }
708 
709         public bool IsIndexed
710         {
711             get
712             {
713                 CheckIfDisposed();
714 
715                 return IsSetInSearchFlags(SearchFlags.IsIndexed);
716             }
717             set
718             {
719                 CheckIfDisposed();
720 
721                 if (value)
722                 {
723                     SetBitInSearchFlags(SearchFlags.IsIndexed);
724                 }
725                 else
726                 {
727                     ResetBitInSearchFlags(SearchFlags.IsIndexed);
728                 }
729             }
730         }
731 
732         public bool IsIndexedOverContainer
733         {
734             get
735             {
736                 CheckIfDisposed();
737 
738                 return IsSetInSearchFlags(SearchFlags.IsIndexedOverContainer);
739             }
740             set
741             {
742                 CheckIfDisposed();
743 
744                 if (value)
745                 {
746                     SetBitInSearchFlags(SearchFlags.IsIndexedOverContainer);
747                 }
748                 else
749                 {
750                     ResetBitInSearchFlags(SearchFlags.IsIndexedOverContainer);
751                 }
752             }
753         }
754 
755         public bool IsInAnr
756         {
757             get
758             {
759                 CheckIfDisposed();
760 
761                 return IsSetInSearchFlags(SearchFlags.IsInAnr);
762             }
763             set
764             {
765                 CheckIfDisposed();
766 
767                 if (value)
768                 {
769                     SetBitInSearchFlags(SearchFlags.IsInAnr);
770                 }
771                 else
772                 {
773                     ResetBitInSearchFlags(SearchFlags.IsInAnr);
774                 }
775             }
776         }
777 
778         public bool IsOnTombstonedObject
779         {
780             get
781             {
782                 CheckIfDisposed();
783 
784                 return IsSetInSearchFlags(SearchFlags.IsOnTombstonedObject);
785             }
786             set
787             {
788                 CheckIfDisposed();
789 
790                 if (value)
791                 {
792                     SetBitInSearchFlags(SearchFlags.IsOnTombstonedObject);
793                 }
794                 else
795                 {
796                     ResetBitInSearchFlags(SearchFlags.IsOnTombstonedObject);
797                 }
798             }
799         }
800 
801         public bool IsTupleIndexed
802         {
803             get
804             {
805                 CheckIfDisposed();
806 
807                 return IsSetInSearchFlags(SearchFlags.IsTupleIndexed);
808             }
809             set
810             {
811                 CheckIfDisposed();
812 
813                 if (value)
814                 {
815                     SetBitInSearchFlags(SearchFlags.IsTupleIndexed);
816                 }
817                 else
818                 {
819                     ResetBitInSearchFlags(SearchFlags.IsTupleIndexed);
820                 }
821             }
822         }
823 
824         public bool IsInGlobalCatalog
825         {
826             get
827             {
828                 CheckIfDisposed();
829 
830                 if (isBound)
831                 {
832                     if (!_isInGlobalCatalogInitialized)
833                     {
834                         // get the property from the server
835                         object value = GetValueFromCache(PropertyManager.IsMemberOfPartialAttributeSet, false);
836                         _isInGlobalCatalog = (value != null) ? (bool)value : false;
837                         _isInGlobalCatalogInitialized = true;
838                     }
839                 }
840                 return _isInGlobalCatalog;
841             }
842             set
843             {
844                 CheckIfDisposed();
845 
846                 if (isBound)
847                 {
848                     // get the distinguished name to construct the directory entry
849                     GetSchemaPropertyDirectoryEntry();
850                     Debug.Assert(_propertyEntry != null);
851 
852                     // set the value on the directory entry
853                     _propertyEntry.Properties[PropertyManager.IsMemberOfPartialAttributeSet].Value = value;
854                 }
855                 _isInGlobalCatalog = value;
856             }
857         }
858 
859         public Nullable<Int32> RangeLower
860         {
861             get
862             {
863                 CheckIfDisposed();
864 
865                 if (isBound)
866                 {
867                     if (!_rangeLowerInitialized)
868                     {
869                         // get the property from the server
870                         // if the property is not set then we will return null
871                         object value = GetValueFromCache(PropertyManager.RangeLower, false);
872                         if (value == null)
873                         {
874                             _rangeLower = null;
875                         }
876                         else
877                         {
878                             _rangeLower = (int)value;
879                         }
880                         _rangeLowerInitialized = true;
881                     }
882                 }
883                 return _rangeLower;
884             }
885             set
886             {
887                 CheckIfDisposed();
888 
889                 if (isBound)
890                 {
891                     // get the distinguished name to construct the directory entry
892                     GetSchemaPropertyDirectoryEntry();
893                     Debug.Assert(_propertyEntry != null);
894 
895                     // set the value on the directory entry
896                     if (value == null)
897                     {
898                         if (_propertyEntry.Properties.Contains(PropertyManager.RangeLower))
899                         {
900                             _propertyEntry.Properties[PropertyManager.RangeLower].Clear();
901                         }
902                     }
903                     else
904                     {
905                         _propertyEntry.Properties[PropertyManager.RangeLower].Value = (int)value.Value;
906                     }
907                 }
908                 _rangeLower = value;
909             }
910         }
911 
912         public Nullable<Int32> RangeUpper
913         {
914             get
915             {
916                 CheckIfDisposed();
917 
918                 if (isBound)
919                 {
920                     if (!_rangeUpperInitialized)
921                     {
922                         // get the property from the server
923                         // if the property is not set then we will return null
924                         object value = GetValueFromCache(PropertyManager.RangeUpper, false);
925                         if (value == null)
926                         {
927                             _rangeUpper = null;
928                         }
929                         else
930                         {
931                             _rangeUpper = (int)value;
932                         }
933                         _rangeUpperInitialized = true;
934                     }
935                 }
936                 return _rangeUpper;
937             }
938             set
939             {
940                 CheckIfDisposed();
941 
942                 if (isBound)
943                 {
944                     // get the distinguished name to construct the directory entry
945                     GetSchemaPropertyDirectoryEntry();
946                     Debug.Assert(_propertyEntry != null);
947 
948                     // set the value on the directory entry
949                     if (value == null)
950                     {
951                         if (_propertyEntry.Properties.Contains(PropertyManager.RangeUpper))
952                         {
953                             _propertyEntry.Properties[PropertyManager.RangeUpper].Clear();
954                         }
955                     }
956                     else
957                     {
958                         _propertyEntry.Properties[PropertyManager.RangeUpper].Value = (int)value.Value;
959                     }
960                 }
961                 _rangeUpper = value;
962             }
963         }
964 
965         public bool IsDefunct
966         {
967             get
968             {
969                 CheckIfDisposed();
970                 // this is initialized for bound properties in the constructor
971                 return _isDefunct;
972             }
973             set
974             {
975                 CheckIfDisposed();
976 
977                 if (isBound)
978                 {
979                     // set the value on the directory entry
980                     SetProperty(PropertyManager.IsDefunct, value);
981                 }
982                 _isDefunct = value;
983             }
984         }
985 
986         public ActiveDirectorySchemaProperty Link
987         {
988             get
989             {
990                 CheckIfDisposed();
991 
992                 if (isBound)
993                 {
994                     if (!_linkedPropertyInitialized)
995                     {
996                         object value = GetValueFromCache(PropertyManager.LinkID, false);
997                         int tempLinkId = (value != null) ? (int)value : -1;
998 
999                         if (tempLinkId != -1)
1000                         {
1001                             int linkIdToSearch = tempLinkId - 2 * (tempLinkId % 2) + 1;
1002 
1003                             try
1004                             {
1005                                 if (_schemaEntry == null)
1006                                 {
1007                                     _schemaEntry = DirectoryEntryManager.GetDirectoryEntry(_context, WellKnownDN.SchemaNamingContext);
1008                                 }
1009 
1010                                 string filter = "(&(" + PropertyManager.ObjectCategory + "=attributeSchema)" + "(" + PropertyManager.LinkID + "=" + linkIdToSearch + "))";
1011                                 ReadOnlyActiveDirectorySchemaPropertyCollection linkedProperties = ActiveDirectorySchema.GetAllProperties(_context, _schemaEntry, filter);
1012 
1013                                 if (linkedProperties.Count != 1)
1014                                 {
1015                                     throw new ActiveDirectoryObjectNotFoundException(SR.Format(SR.LinkedPropertyNotFound , linkIdToSearch), typeof(ActiveDirectorySchemaProperty), null);
1016                                 }
1017 
1018                                 _linkedProperty = linkedProperties[0];
1019                             }
1020                             catch (COMException e)
1021                             {
1022                                 throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
1023                             }
1024                         }
1025                         _linkedPropertyInitialized = true;
1026                     }
1027                 }
1028                 return _linkedProperty;
1029             }
1030         }
1031 
1032         public Nullable<Int32> LinkId
1033         {
1034             get
1035             {
1036                 CheckIfDisposed();
1037 
1038                 if (isBound)
1039                 {
1040                     if (!_linkIdInitialized)
1041                     {
1042                         object value = GetValueFromCache(PropertyManager.LinkID, false);
1043                         // if the property was not set we will return null
1044                         if (value == null)
1045                         {
1046                             _linkId = null;
1047                         }
1048                         else
1049                         {
1050                             _linkId = (int)value;
1051                         }
1052                         _linkIdInitialized = true;
1053                     }
1054                 }
1055                 return _linkId;
1056             }
1057             set
1058             {
1059                 CheckIfDisposed();
1060 
1061                 if (isBound)
1062                 {
1063                     // get the distinguished name to construct the directory entry
1064                     GetSchemaPropertyDirectoryEntry();
1065                     Debug.Assert(_propertyEntry != null);
1066 
1067                     // set the value on the directory entry
1068                     if (value == null)
1069                     {
1070                         if (_propertyEntry.Properties.Contains(PropertyManager.LinkID))
1071                         {
1072                             _propertyEntry.Properties[PropertyManager.LinkID].Clear();
1073                         }
1074                     }
1075                     else
1076                     {
1077                         _propertyEntry.Properties[PropertyManager.LinkID].Value = (int)value.Value;
1078                     }
1079                 }
1080                 _linkId = value;
1081             }
1082         }
1083 
1084         public Guid SchemaGuid
1085         {
1086             get
1087             {
1088                 CheckIfDisposed();
1089 
1090                 Guid schemaGuid = Guid.Empty;
1091 
1092                 if (isBound)
1093                 {
1094                     if (_schemaGuidBinaryForm == null)
1095                     {
1096                         // get the property from the server
1097                         _schemaGuidBinaryForm = (byte[])GetValueFromCache(PropertyManager.SchemaIDGuid, true);
1098                     }
1099                 }
1100 
1101                 // we cache the byte array and create a new guid each time
1102                 return new Guid(_schemaGuidBinaryForm);
1103             }
1104             set
1105             {
1106                 CheckIfDisposed();
1107 
1108                 if (isBound)
1109                 {
1110                     // set the value on the directory entry
1111                     SetProperty(PropertyManager.SchemaIDGuid, (value.Equals(Guid.Empty)) ? null : value.ToByteArray());
1112                 }
1113                 _schemaGuidBinaryForm = (value.Equals(Guid.Empty)) ? null : value.ToByteArray();
1114             }
1115         }
1116 
1117         #endregion public properties
1118 
1119         #region private methods
1120 
CheckIfDisposed()1121         private void CheckIfDisposed()
1122         {
1123             if (_disposed)
1124             {
1125                 throw new ObjectDisposedException(GetType().Name);
1126             }
1127         }
1128 
1129         //
1130         // This method retrieves the value of a property (single valued) from the values
1131         // that were retrieved from the server. The "mustExist" parameter controls whether or
1132         // not an exception should be thrown if a value does not exist. If mustExist is true, this
1133         // will throw an exception is value does not exist.
1134         //
GetValueFromCache(string propertyName, bool mustExist)1135         private object GetValueFromCache(string propertyName, bool mustExist)
1136         {
1137             object value = null;
1138 
1139             // retrieve the properties from the server if necessary
1140             InitializePropertiesFromSchemaContainer();
1141 
1142             Debug.Assert(_propertyValuesFromServer != null);
1143 
1144             ResultPropertyValueCollection propertyValues = null;
1145             try
1146             {
1147                 propertyValues = _propertyValuesFromServer.Properties[propertyName];
1148                 if ((propertyValues == null) || (propertyValues.Count < 1))
1149                 {
1150                     if (mustExist)
1151                     {
1152                         throw new ActiveDirectoryOperationException(SR.Format(SR.PropertyNotFound , propertyName));
1153                     }
1154                 }
1155                 else
1156                 {
1157                     value = propertyValues[0];
1158                 }
1159             }
1160             catch (COMException e)
1161             {
1162                 throw ExceptionHelper.GetExceptionFromCOMException(_context, e);
1163             }
1164 
1165             return value;
1166         }
1167 
1168         //
1169         // Just calls the static method GetPropertiesFromSchemaContainer with the correct context
1170         //
InitializePropertiesFromSchemaContainer()1171         private void InitializePropertiesFromSchemaContainer()
1172         {
1173             if (!_propertiesFromSchemaContainerInitialized)
1174             {
1175                 if (_schemaEntry == null)
1176                 {
1177                     _schemaEntry = DirectoryEntryManager.GetDirectoryEntry(_context, WellKnownDN.SchemaNamingContext);
1178                 }
1179 
1180                 _propertyValuesFromServer = GetPropertiesFromSchemaContainer(_context, _schemaEntry, (_isDefunctOnServer) ? _commonName : _ldapDisplayName, _isDefunctOnServer);
1181                 _propertiesFromSchemaContainerInitialized = true;
1182             }
1183         }
1184 
1185         //
1186         // This method retrieves properties for this schema class from the schema container
1187         // on the server. For non-defunct classes only properties that are not available in the abstract
1188         // schema are retrieved.  For defunct classes, all the properties are retrieved.
1189         // The retrieved values are stored in a class variable "propertyValuesFromServer" which is a
1190         // hashtable indexed on the property name.
1191         //
GetPropertiesFromSchemaContainer(DirectoryContext context, DirectoryEntry schemaEntry, string name, bool isDefunctOnServer)1192         internal static SearchResult GetPropertiesFromSchemaContainer(DirectoryContext context, DirectoryEntry schemaEntry, string name, bool isDefunctOnServer)
1193         {
1194             SearchResult propertyValuesFromServer = null;
1195 
1196             //
1197             // The properties that are loaded from the schemaContainer for non-defunct classes:
1198             // DistinguishedName
1199             // CommonName
1200             // Syntax - AttributeSyntax, OMSyntax, OMObjectClass
1201             // Description
1202             // IsIndexed, IsIndexedOverContainer, IsInAnr, IsOnTombstonedObject, IsTupleIndexed - SearchFlags
1203             // IsInGlobalCatalog - IsMemberOfPartialAttributeSet
1204             // LinkId (Link)
1205             // SchemaGuid - SchemaIdGuid
1206             // RangeLower
1207             // RangeUpper
1208 
1209             //
1210             // For defunct class we also load teh remaining properties
1211             // LdapDisplayName
1212             // Oid
1213             // IsSingleValued
1214             //
1215 
1216             // build the filter
1217             StringBuilder str = new StringBuilder(15);
1218             str.Append("(&(");
1219             str.Append(PropertyManager.ObjectCategory);
1220             str.Append("=attributeSchema)");
1221             str.Append("(");
1222             if (!isDefunctOnServer)
1223             {
1224                 str.Append(PropertyManager.LdapDisplayName);
1225             }
1226             else
1227             {
1228                 str.Append(PropertyManager.Cn);
1229             }
1230             str.Append("=");
1231             str.Append(Utils.GetEscapedFilterValue(name));
1232             str.Append(")");
1233             if (!isDefunctOnServer)
1234             {
1235                 str.Append("(!(");
1236             }
1237             else
1238             {
1239                 str.Append("(");
1240             }
1241             str.Append(PropertyManager.IsDefunct);
1242             if (!isDefunctOnServer)
1243             {
1244                 str.Append("=TRUE)))");
1245             }
1246             else
1247             {
1248                 str.Append("=TRUE))");
1249             }
1250 
1251             string[] propertiesToLoad = null;
1252             if (!isDefunctOnServer)
1253             {
1254                 propertiesToLoad = new string[12];
1255 
1256                 propertiesToLoad[0] = PropertyManager.DistinguishedName;
1257                 propertiesToLoad[1] = PropertyManager.Cn;
1258                 propertiesToLoad[2] = PropertyManager.AttributeSyntax;
1259                 propertiesToLoad[3] = PropertyManager.OMSyntax;
1260                 propertiesToLoad[4] = PropertyManager.OMObjectClass;
1261                 propertiesToLoad[5] = PropertyManager.Description;
1262                 propertiesToLoad[6] = PropertyManager.SearchFlags;
1263                 propertiesToLoad[7] = PropertyManager.IsMemberOfPartialAttributeSet;
1264                 propertiesToLoad[8] = PropertyManager.LinkID;
1265                 propertiesToLoad[9] = PropertyManager.SchemaIDGuid;
1266                 propertiesToLoad[10] = PropertyManager.RangeLower;
1267                 propertiesToLoad[11] = PropertyManager.RangeUpper;
1268             }
1269             else
1270             {
1271                 propertiesToLoad = new string[15];
1272 
1273                 propertiesToLoad[0] = PropertyManager.DistinguishedName;
1274                 propertiesToLoad[1] = PropertyManager.Cn;
1275                 propertiesToLoad[2] = PropertyManager.AttributeSyntax;
1276                 propertiesToLoad[3] = PropertyManager.OMSyntax;
1277                 propertiesToLoad[4] = PropertyManager.OMObjectClass;
1278                 propertiesToLoad[5] = PropertyManager.Description;
1279                 propertiesToLoad[6] = PropertyManager.SearchFlags;
1280                 propertiesToLoad[7] = PropertyManager.IsMemberOfPartialAttributeSet;
1281                 propertiesToLoad[8] = PropertyManager.LinkID;
1282                 propertiesToLoad[9] = PropertyManager.SchemaIDGuid;
1283                 propertiesToLoad[10] = PropertyManager.AttributeID;
1284                 propertiesToLoad[11] = PropertyManager.IsSingleValued;
1285                 propertiesToLoad[12] = PropertyManager.RangeLower;
1286                 propertiesToLoad[13] = PropertyManager.RangeUpper;
1287                 propertiesToLoad[14] = PropertyManager.LdapDisplayName;
1288             }
1289 
1290             //
1291             // Get all the values (don't need to use range retrieval as there are no multivalued attributes)
1292             //
1293             ADSearcher searcher = new ADSearcher(schemaEntry, str.ToString(), propertiesToLoad, SearchScope.OneLevel, false /* paged search */, false /* cache results */);
1294 
1295             try
1296             {
1297                 propertyValuesFromServer = searcher.FindOne();
1298             }
1299             catch (COMException e)
1300             {
1301                 if (e.ErrorCode == unchecked((int)0x80072030))
1302                 {
1303                     // object is not found since we cannot even find the container in which to search
1304                     throw new ActiveDirectoryObjectNotFoundException(SR.DSNotFound, typeof(ActiveDirectorySchemaProperty), name);
1305                 }
1306                 else
1307                 {
1308                     throw ExceptionHelper.GetExceptionFromCOMException(context, e);
1309                 }
1310             }
1311 
1312             if (propertyValuesFromServer == null)
1313             {
1314                 throw new ActiveDirectoryObjectNotFoundException(SR.DSNotFound, typeof(ActiveDirectorySchemaProperty), name);
1315             }
1316 
1317             return propertyValuesFromServer;
1318         }
1319 
GetSchemaPropertyDirectoryEntry()1320         internal DirectoryEntry GetSchemaPropertyDirectoryEntry()
1321         {
1322             if (_propertyEntry == null)
1323             {
1324                 InitializePropertiesFromSchemaContainer();
1325                 _propertyEntry = DirectoryEntryManager.GetDirectoryEntry(_context, (string)GetValueFromCache(PropertyManager.DistinguishedName, true));
1326             }
1327 
1328             return _propertyEntry;
1329         }
1330 
1331         ///
1332         /// <summary>
1333         /// Initializes the search flags attribute value i.e. fetches it from
1334         /// the directory, if this object is bound.
1335         /// </summary>
1336         ///
InitializeSearchFlags()1337         private void InitializeSearchFlags()
1338         {
1339             if (isBound)
1340             {
1341                 if (!_searchFlagsInitialized)
1342                 {
1343                     object value = GetValueFromCache(PropertyManager.SearchFlags, false);
1344 
1345                     if (value != null)
1346                     {
1347                         _searchFlags = (SearchFlags)((int)value);
1348                     }
1349                     _searchFlagsInitialized = true;
1350                 }
1351             }
1352         }
1353 
IsSetInSearchFlags(SearchFlags searchFlagBit)1354         private bool IsSetInSearchFlags(SearchFlags searchFlagBit)
1355         {
1356             InitializeSearchFlags();
1357             return (((int)_searchFlags & (int)searchFlagBit) != 0);
1358         }
1359 
SetBitInSearchFlags(SearchFlags searchFlagBit)1360         private void SetBitInSearchFlags(SearchFlags searchFlagBit)
1361         {
1362             InitializeSearchFlags();
1363             _searchFlags = (SearchFlags)((int)_searchFlags | (int)searchFlagBit);
1364 
1365             if (isBound)
1366             {
1367                 // get the distinguished name to construct the directory entry
1368                 GetSchemaPropertyDirectoryEntry();
1369                 Debug.Assert(_propertyEntry != null);
1370 
1371                 // set the value on the directory entry
1372                 _propertyEntry.Properties[PropertyManager.SearchFlags].Value = (int)_searchFlags;
1373             }
1374         }
1375 
ResetBitInSearchFlags(SearchFlags searchFlagBit)1376         private void ResetBitInSearchFlags(SearchFlags searchFlagBit)
1377         {
1378             InitializeSearchFlags();
1379             _searchFlags = (SearchFlags)((int)_searchFlags & ~((int)searchFlagBit));
1380 
1381             if (isBound)
1382             {
1383                 // get the distinguished name to construct the directory entry
1384                 GetSchemaPropertyDirectoryEntry();
1385                 Debug.Assert(_propertyEntry != null);
1386 
1387                 // set the value on the directory entry
1388                 _propertyEntry.Properties[PropertyManager.SearchFlags].Value = (int)_searchFlags;
1389             }
1390         }
1391 
SetProperty(string propertyName, object value)1392         private void SetProperty(string propertyName, object value)
1393         {
1394             // get the distinguished name to construct the directory entry
1395             GetSchemaPropertyDirectoryEntry();
1396             Debug.Assert(_propertyEntry != null);
1397 
1398             if (value == null)
1399             {
1400                 if (_propertyEntry.Properties.Contains(propertyName))
1401                 {
1402                     _propertyEntry.Properties[propertyName].Clear();
1403                 }
1404             }
1405             else
1406             {
1407                 _propertyEntry.Properties[propertyName].Value = value;
1408             }
1409         }
1410 
MapSyntax(string syntaxId, int oMID, OMObjectClass oMObjectClass)1411         private ActiveDirectorySyntax MapSyntax(string syntaxId, int oMID, OMObjectClass oMObjectClass)
1412         {
1413             for (int i = 0; i < s_syntaxesCount; i++)
1414             {
1415                 if (s_syntaxes[i].Equals(new Syntax(syntaxId, oMID, oMObjectClass)))
1416                 {
1417                     return (ActiveDirectorySyntax)i;
1418                 }
1419             }
1420             throw new ActiveDirectoryOperationException(SR.Format(SR.UnknownSyntax , _ldapDisplayName));
1421         }
1422 
SetSyntax(ActiveDirectorySyntax syntax)1423         private void SetSyntax(ActiveDirectorySyntax syntax)
1424         {
1425             if ((((int)syntax) < 0) || (((int)syntax) > (s_syntaxesCount - 1)))
1426             {
1427                 throw new InvalidEnumArgumentException("syntax", (int)syntax, typeof(ActiveDirectorySyntax));
1428             }
1429 
1430             // get the distinguished name to construct the directory entry
1431             GetSchemaPropertyDirectoryEntry();
1432             Debug.Assert(_propertyEntry != null);
1433 
1434             _propertyEntry.Properties[PropertyManager.AttributeSyntax].Value = s_syntaxes[(int)syntax].attributeSyntax;
1435             _propertyEntry.Properties[PropertyManager.OMSyntax].Value = s_syntaxes[(int)syntax].oMSyntax;
1436             OMObjectClass oMObjectClass = s_syntaxes[(int)syntax].oMObjectClass;
1437             if (oMObjectClass != null)
1438             {
1439                 _propertyEntry.Properties[PropertyManager.OMObjectClass].Value = oMObjectClass.Data;
1440             }
1441         }
1442         #endregion private methods
1443     }
1444 }
1445