The P&M feature provides a set of COM/Automation-compliant classes that fall into two broad categories: front-end COM objects and administrative COM objects. The front-end COM objects are normally used in Active Server Pages (ASP) scripts, but can be used in many places outside ASP, and in any language that supports the COM. The administrative COM objects can be used by non-administrators to fetch nonsensitive configuration information, and by administrators to configure the various P&M services. They can also be used from any language that supports the COM. Each COM object's requirements are listed in the corresponding reference section. There are a number of examples demonstrating the use of these objects in various programming languages showing a wide variety of standard tasks.
The following topics describe these objects and what they are used to do.
Any discussion of programming with P&M would not be complete without some discussion of the ADSI interfaces and standard ADSI implementations. A complete ADSI SDK exists in the Microsoft® Platform SDK under "Networking and Distributed Systems"; it covers ADSI in detail, particularly the LDAP and WinNT namespaces. It goes into great detail about the general architecture ADSI provides for such things as property caching, access control lists, and using OLE DB to perform queries. Most of these topics will not be covered here.
Active Directory Services Interfaces specify a stock set of COM dual interfaces that provide a natural and simple set of related methods and properties for dealing with directory service information. Additionally, there are numerous pure COM interfaces and low-level "helper" functions that make things a bit easier for languages such as C++. We will briefly cover the most important of these in the discussion that follows.
When contrasting directory service databases of information with relational databases, the most important distinction is that the directory service emphasizes hierarchy over relation. The expression of this hierarchy abstracts to the notion of a container object and a leaf object. Container objects are nodes in the hierarchy that have descendents, or children. A leaf object is a node in the hierarchy with no descendents. The ADSI object model centers around this approach to data structure and accessibility.
Each node in the hierarchy, whether it be a container or a leaf, has its "blueprint" defined by another object, labeled a schema object, that is accessible in the hierarchy as well. You can think of the schema as the "DNA" that defines the object, and each subsequently created object that inherits from this schema has its structure defined by the schema. The schema object itself is made up of other objects that define attribute types and the syntax each type supports. One example of such an object from the LDAP service is the "UnicodeString" syntax object. An example of a schema object is one that describes the schema of a User or a Computer on the network, or a type of content. In the Membership Directory Service, the object that defines a user is called the member schema object. As with many other technologies that present information and functionality in terms of "objects," these names are referred to as classes.
To create and bind COM objects that contain directory data, the ADSI system relies on what is arguably the most important technology provided by the COM system, the notion of moniker objects, and the display names they "understand." A display name is just a string that when passed to a moniker object, is parsed, examined, and used to unambiguously create and/or bind an interface on a given COM object, which is then returned to the caller. In ADSI parlance, these strings are called Active Directory Service paths, or ADs paths for short. An example of an ADs path, using the LDAP namespace, is LDAP://servername:1002/o=CompanyA
. As with most display names, the structure is quite simple. The first part of the string before the colon (:) is a programmatic identifier, in this case, LDAP. This identifies the moniker object that will interpret the rest of the string and bind the COM object. So the COM object identified by "LDAP" receives the string "//server:1002/o=CompanyA" to parse, interpret and service by creating or binding the specified COM object. For example, in VBScript, this is done in the following way:
Set oOrg = GetObject("LDAP://servername:1003/o=CompanyA")
This is equivalent to the more direct approach that most should find familiar:
Set oNamespace = CreateObject("LDAPNamespace")
Set oOrg = oNamespace.GetObject("//servername:1003/o=CompanyA")
In the latter case the creatable "LDAPNamespace" COM object is bound directly, and then passed a display name to service. Of course, the former construction requires less typing and is completely equivalent, so it is always used. The nice thing about using ADSI is that not only can you present simple display name strings to identify the desired object, but all the low-level details such as networking and encryption are hidden from the user as part of the object's implementation.
After we have received an interface on an ADSI COM object, we can begin to use it. The most fundamental ADSI COM interface that all ADSI COM objects must implement is the IADs interface. This dual interface provides a set of properties that define the object in the hierarchy, and a set of methods that can be used to fetch and place the data contained in the object itself, as defined by its schema object.
The main IADs properties are:
ADsPath
The unique display name for the object.
GUID
A globally unique identifier for the object.
Class
The schema class of the object as named in the directory service namespace.
Schema
The display name, or ADs path that uniquely identifies the schema object on which this object is based.
The IADs data assessor methods are:
GetInfo
Loads the persisted data from the directory database into the object.
Get
Retrieves a property specified by name from the object.
GetEx
Retrieves a property specified by name from the object. In some cases, this method handles multivalued properties.
Put
Puts a property value into the object.
PutEx
Puts a property value into the object. In some cases, this method handles putting multivalued properties.
SetInfo
Sets the data currently in the object into the directory database.
A complete reference for this interface can be found in the ADSI 2.0 SDK.
In general, this interface is easy to use. As an example, consider the following VBScript code that interacts with a hypothetical Membership Directory Service to fetch information about the user "Joe."
Set oUser = GetObject("LDAP://server:1002/o=CompanyA/ou=Members/cn=Joe")
‘ display information about the ADSI object
WScript.Echo oUser.ADsPath
WScript.Echo oUser.Class
WScript.Echo oUser.Schema
WScript.Echo oUser.GUID
‘ Get the information about “Joe”
oUser.Getinfo
WScript.Echo oUser.Get("givenName")
WScript.Echo oUser.Get("GUID")
WScript.ECho oUser.Get(“password”)
‘ Set or update information about Joe
oUser.Set "givenName", "Joe"
oUser.Set “password”, “thePassword”
oUser.SetInfo
The output would be something like
LDAP://server:1002/cn=Joe,ou=Members,o=Company
member
LDAP://server:1002/cn=member,cn=schema,ou=admin,o=CompanyA
{ef323…}
Joseph
{13fgdf…}
(Notice that the ADSI object has a GUID property, and the schema for the LDAP class member defines a property called GUID as well. These are not the same!)
If the object is a container node in the hierarchy, then it must expose the next fundamental ADSI COM interface called IADsContainer as well. This interface exposes the normal set of "collection" properties such as _NewEnum and Count. The most important method exposed on this interface is GetObject, which is used to further resolve display names to fetch objects lower in the hierarchy, especially the direct descendants. For example,
Set oContainer = GetObject("LDAP://server/o=CompanyA/ou=Members")
WScript.Echo "There are " & oContainer.Count & " descendants in this container"
For Each obj in oContainer
WScript.Echo obj.Name
WScript.Echo obj.ADsPath
Next
Set oUser = oContainer.GetObject("cn=Joe")
…
The IADsContainer interface also declares some methods for the management of descendants, and they are:
Create
Create an object of some allowed class in the container.
Delete
Remove an object of some allowed class from the container.
MoveHere
Move an object of some allowed class into the container.
CopyHere
Copy an object of some allowed class into the container.
A VBScript example is:
Set Obj = GetObject("LDAP://someserver:1003/o=Realm/ou=members")
Set UserObj = Obj.Create "member", "cn=NewUser"
UserObj.Put "GUID", guid
UserObj.SetInfo
Modifying the schema for these ADSI objects is covered in the Platform SDK ADSI documentation.
The UserObjects Class (Membership.UserObjects.1)
This class is at the heart of the Active User Objects (AUO) system. Programmers and script writers can use instances of this class to automatically and easily access directory service information for users in an ASP or other environment.
The SchemaObjects Class (Membership.SchemaObjects.1)
This class is part of the Active User Objects (AUO) system. Programmers and script writers can use objects of this class to view and/or modify the directory service schema definitions for users.
The AuoConfig Class (MemAdmin.AuoConfig.1)
This class is the administrative tool used to configure the Active User Objects (AUO) system. Administrators can use objects of this class to set up the AUO system so instances of the UserObjects and SchemaObjects coclasses can function. Non-administrators can use instances to examine the AUO provider configuration at run time.
The VerifUsr Class (Membership.Verifusr.1)
This class can be used for a variety of tasks in an ASP environment. It can be used to issue the appropriate HTTP cookies to users that are required by Membership Server instances, as well as provide authentication services for Web sites that are using Forms Authentication.
The GuidGen Class (Membership.GuidGen.1)
This class provides access to the low-level COM library CoCreateGuid function. This class allows script writers to generate GUID values in scripts at run time.
The BrokServers Class (MemAdmin.BrokServers.1)
Objects of this class can be used to configure Membership Authentication service instances.
The BrokConfig Class (MemAdmin.BrokConfig.1)
Objects of this class can be used to configure specific instances of the Membership Authentication service.
The LdapCfg Class (MemAdmin.LdapConfig.1)
Objects of this class can be used to configure instances of the Lightweight Directory Access Protocol (LDAP) service.
The TMAdmin Class (MemAdmin.DMailConfig.1)
Objects of this class can be used to configure various instances of the Direct Mail service.
The SetupStore Class (MemAdmin.DSConfig.1)
Objects of this class can be used to set up back-end database information used by LDAP service instances to persist directory information.