The ADSI Automation Interfaces

This is the point at which I have to issue a terminology ambiguity alert. The things that Active Directory holds information about are called objects. Unfortunately, we're not talking about COM objects or indeed, any other sort of object in the restricted sense that we OO freaks use. When we talk about an Active Directory object, we mean just about anything that can have information about it stored. Examples of such include:

The ambiguity gets worse, alas, because Active Directory also has the concept of a class. Unsurprisingly, these classes have nothing to do with OOP classes. They are simply collections of characteristics that a number of objects have in common with each other.

Let's take a look at some of the attributes that each object in Active Directory must possess. First of all, it must have a name. It may also have a UUID. It must have a class. The class is very important, as this determines the characteristics of the object. One of the neat features of Active Directory, incidentally, is that class definitions are stored as objects (of class "Class"), just like any other.

What sort of characteristics can a class have, then? First of all, a class can either be a container or a leaf. The easiest analogy here is with folders and files. You can embed folders inside folders inside folders, until eventually you come to a file or files at the end. Similarly, containers can contain containers, which can contain containers, and so on, until you get to the leaves inside the final container. If an object belongs to a container class, it is a container; if it does not, it isn't. Where containers differ from folders is that being a container is simply an attribute of the class — so there can be several different types of container.

Classes also have a number of properties, which are attributes that every object belonging to that class can have. Some properties are mandatory and some are optional. All properties are, inevitably, Active Directory objects themselves. The most important characteristic of a property is its syntax. Again, syntax definitions are Active Directory objects as well. The class, property and syntax objects are all leaves in a special container, called the schema.

How does this map onto the ADSI object structure?

The IADs Interface

Every object in the Active Directory hierarchy must support the interface

IADs
. (You'll get used to that Shift-AD-No shift-s combination by the time you've finished with this chapter, believe me.) This interface has the following properties:

Property Type Description
Name
BSTR
Name of object
AdsPath
BSTR
Full directory path to object
Class
BSTR
Class of object
GUID
BSTR
GUID of object
Parent
BSTR
Directory path to parent container
Schema
BSTR
Directory path to schema object; we'll look at the schema a little later on

It also has the following methods:

Method Parameters Description
GetInfo()
Reload object with property values
SetInfo()
Commit changes to property values
Get()
[in] BSTR bstrName, [out,retval] VARIANT *pvProp
Get the value of a named property, invoking
GetInfo()
if none is found
Put()
[in] BSTR bstrName, [in] VARIANT vProp
Set the value of a property
GetEx()
[in] BSTR bstrName, [out,retval] VARIANT *pvProp
Gets values for a named single-valued or multi-valued property, invoking
GetInfoEx()
if none is found
PutEx()
[in] LONG lnControlCode, 
[in] BSTR bstrName, [in] VARIANT vProp
Sets values for a named single- or multi-valued property; also, by setting
lnControlCode
to
ADS_PROPERTY_CLEAR
, you can remove a property altogether
GetInfoEx()
[in] VARIANT vProps, [in] LONG lReserved
This does the same as
GetInfo()
, except that it attempts to cut down on network traffic by specifying which properties are to be loaded, as an array of
BSTR
s.

The IADsContainer Interface

As well as supporting the

IADs
interface, containers must also support the
IADsContainer
interface. This has the following properties:

Property Type Description
Count
long
Count of the number of objects in the container
_NewEnum
LPUNKNOWN
Enumerator for objects in the container
Filter
VARIANT
This is an array of
BSTR
s, each of which is a filter specification, which either consists of a class name or a provider-specific specification
Hints
VARIANT
This is an array of properties that works in the same manner as the property array in
IADs::GetInfoEx()
.

It also has the following methods:

Method Parameters Description
GetObject()
[in] BSTR bstrClass, 
[in] BSTR bstrRelativeName, [out, retval] LPDISPATCH *pNewObject
Get a dispatch pointer to the specified object within this container
Create()
[in] BSTR bstrClass, 
[in] BSTR bstrRelativeName, [out, retval] LPDISPATCH *pNewObject
Create a new object with the specified class within this container (although it isn't written away until
IADs::SetInfo()
is called on the object)
Delete()
[in] BSTR bstrClass, [in] BSTR bstrRelativeName
Delete the specified object from this container
CopyHere()
[in] BSTR bstrSource, [in] BSTR bstrNewName, [out, retval] LPDISPATCH* pNewObject
Make a copy of the object specified by the source path in this container (but not across directory systems)
MoveHere()
[in] BSTR bstrSource, [in] BSTR bstrNewName, [out, retval] LPDISPATCH* pNewObject
Move the object specified by the source path to this container (but not across directory systems)

We'll see these interfaces in action when we use them in a practical example. So, let's take a breather from all these definitions and write some code. We've got a couple more interfaces to tackle yet, but we've got enough to get going.

© 1998 by Wrox Press. All rights reserved.