Platform SDK: Active Directory, ADSI, and Directory Services

Early Binding Support

To begin, let's look at a scenario with early binding support in place. Consider the following code snippet:

Dim x as IADsUser
Dim y as IADsExt1
Dim z as IADsExt2
 
Set x = GetObject("LDAP://CN=JSmith, OU=Sales, 
                   DC=Microsoft,DC=COM")
x.SetPassword("newPassword")
 
Set y = x
y.MyNewMethod( "\\srv\public")
y.MyProperty = "Hello World"
 
Set z = y
z.OtherMethod()
z.OtherProperty = 4362
 
Debug.Print x.LastName
 
Set z = GetObject("LDAP://CN=Alice,OU=Engr, 
                   DC=Microsoft,DC=COM")
z.OtherProperty = 5323

In this example, two extension components extend a user object. Each extension publishes its own interface. Each extension is not aware of the other extension's interface, only ADSI is aware of the existence of both extensions. Each extension will delegate its IUnknown to ADSI. ADSI will act as an aggregator for both extensions, and any other future extensions. Querying an interface from any extension, or from ADSI, will yield the same consistent result.

Let's look at the steps required to make an extension.

Step 1: Add Aggregation to Your Component

Follow the COM specification for adding aggregation to your component. In summary, you must honor the pUnknown requests to your component during CreateInstance, and delegate the pUnknown to the aggregator's IUnknown if the component is being aggregated.

Step 2: Register Your Extension

Now you must decide which directory class you want to extend. You will not use the same interfaces to accomplish this that you would use for an ADSI interface (for example, IADsUser, IADsComputer). Directory objects are persisted in the directory, while your extension and ADSI will be running on the client's machine. Directory object examples are user, computer, printQueue, serviceConnectionPoint, and nTDSService. You can add a new class in Active Directory™ and create a new extension for this new class as well.

You will use registry keys to associate a directory class name with the ADSI extension components. The following figure represents the existing registry layout, as a well as new keys.

Note  Extension objects are still required to register standard COM keys.


HKLM
|__Software
    |___Microsoft
            |____ADS

                    |__Providers

                            |__LDAP

<continue from above>

LDAP

  |__Extensions
        |___<ClassNameA>
        |____<CLSID of ExtensionA1>

                            Interfaces(REG_BINARY) {List of interfaces)

                |____<CLSID of ExtensionA2>

                            Interfaces(REG_BINARY) {List #1 of interfaces)


        |____ <ClassNameB>

        |____<CLSID of ExtensionB1>

                            Interfaces(REG_BINARY) {List of interfaces)

                |____<CLSID of ExtensionB2> {List of interfaces}

                            Interfaces(REG_BINARY) {List #1 of interfaces)

Example

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ADs\Providers\LDAP\Extensions\printQueue\{9f37f39c-6f49-11d1-8c18-00c04fd8d503}]
"Interfaces"={466841B0-E531-11d1-8718-00C04FD44407} {466841B1-E531-11d1-8718-00C04FD44407}

The list of interfaces from Extension1 can be different from that of Extension2. The object, when it's alive, will support the interfaces of the aggregator (ADSI) and all the interfaces provided by the aggregate's Extension1 and Extension2. Resolution of conflicting interfaces (the same interface supported by both the aggregator and the aggregates or by multiple aggregates) is determined by priorities of the extensions.

You may also associate your CLSID extension with multiple object class names. For example, your extension can extend both the user and contact objects.

Note  Extension behavior is added per object class, not per object instance.

It is best to register your extensions, as you would any other COM components, with a call to the DllRegisterSvr function. You should also provide a facility to unregister your extension with the DllUnregisterServer function.

Here is an example for how to register an extension:

///////////////////////////////////////////
// Register the class.
///////////////////////////////////////////
hr = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
                 _T("SOFTWARE\\Microsoft\\ADs\\Providers\\LDAP\\Extensions\\User\\{E1E3EDF8-48D1-11D2-B22B-0000F87A6B50}"),
 0,
 NULL,
 REG_OPTION_NON_VOLATILE,
 KEY_WRITE,
 NULL,
 &hKey,
 &dwDisposition );
 
///////////////////////////////////////////
// Register the Interface.
///////////////////////////////////////////
const TCHAR szIf[] = _T("{E1E3EDF7-48D1-11D2-B22B-0000F87A6B50}");
 
hr = RegSetValueEx( hKey, _T("Interfaces"), 0, REG_BINARY, (const BYTE *) szIf, sizeof(szIf) );
 
RegCloseKey(hKey);
return S_OK;
 
}