Active Directory Service Interfaces
Recently, I needed to modify an application I'd written that provides Web-based delegated administration for Windows NT. I needed to make the application work with Active Directory (AD). I set a short time line for the project because functions that work with the NT SAM usually differ from those that work against AD only by their binding string. Although that assumption proved generally true, I became frustrated trying to convert one particular function.
The troublesome function reset an account lockout condition for NT accounts. The function simply binds to the User object, calls IADsUser::IsAccountLocked property, and returns a Boolean value that represents the result. As I had with every other function in the class module, I changed the binding string from WinNT: to an appropriate LDAP: binding string and assumed it would work as all the others had before it. When it didn't, I searched the Microsoft Developer Network (MSDN) and found the Microsoft article "Programmatically Changing the Lockout Flag in Windows 2000" (http://support.microsoft.com/default.aspx?scid=kb;en-us;q250873), which explains that the Active Directory Service Interfaces (ADSI) LDAP: provider doesn't properly report the account-locked condition for AD accounts. Instead, the article offers, "To read or reset the lockout bit, use the WinNT: provider to gain access to Active Directory." The workaround is easy, but how could I convert from the Lightweight Directory Access Protocol (LDAP) type of distinguished name (DN) that the ADsPath key provides to a name that the WinNT: provider could use in the most generic, reusable way?
I found my answer in the Windows 2000 Support Tools. Among the tools, I found the IADsTools (iadstool.dll) object in the support.cab file. This COM object lets you convert from an LDAP-type DN (e.g., cn=Thomas Eck, ou=Americas,ou=Users,dc=Fiction, dc=com) to an NT-type DN of the form domain\username.
But that's not all the IADsTools object can do. I discovered that this relatively unadvertised DLL provides several capabilities, such as
- general functions for working with ADSI and AD and, to a lesser extent, native LDAP namespaces
- management and monitoring of AD replication
- management of Group Policy links
Here, I explain some general functions in the IADsTools DCFunctions class that you can use as the foundation for projects that involve AD and Group Policy. In an upcoming article, I'll talk about some of the DLL's other capabilities.
Getting Started
To obtain the Win2K Support Tools, navigate to support\tools on the Win2K CD-ROM. Execute setup.exe to install the tools. Then, you access the Microsoft WordPad document iadstools.doc and the COM object iadstools.dll. If you have either Microsoft Visual Basic (VB) or the VB Macro Editor that comes with most of the Microsoft Office suite tools, you can simply set a reference to IADsTools and use VB's Object Browser to look at the object model.
Instantiation and General Network Functions
You can use Windows Script Host (WSH) to run from the command line all the sample code that I discuss. The code that Listing 1 shows creates an instance of the DCFunctions class. You should include this code in all other listings.
To begin working with IADsTools, let's start with a simple example. In the same way that you use the Net Send command from the command line to send an instant message to a user, you can use the IADsTools NetSendMessage() function to send an instant message natively (i.e., without using the Shell method) from within VB and VBScript functions. After you instantiate the DCFunctions class, you call the NetSendMessage() function and specify the target machine for the message, the message originator, and the message body, as Listing 2 shows.
To query IP configuration, you can use IADsTools and Win2K Server. Simply call the GetIPConfiguration() function and specify the target server's IP address as the first argument. Listing 3 shows an example. The 0 value I specified for the second parameter tells GetIPConfiguration() to use the credentials of the currently logged-on user.
Name Conversion: NT and DNs
In working with ADSI, you might (as I discovered) occasionally need to translate between naming formats used to bind objects in AD. Typically, you need to bind a User object by using the object's LDAP DN; however, in some cases you might need to use the WinNT: provider to perform the binding or you might need to provide the downlevel DN to complete a function.
To bind the User object that Figure 1 shows, you can use one of two LDAP DNs to perform the binding. To bind using the little endian form (which ADSI uses by default), you'd use
cn=Thomas Eck,ou=Americas,
ou=Users,dc=Fiction,dc=com
To bind using the big endian form, you'd use
dc=com/dc=Fiction/ou=Users/
ou=Americas/cn=Thomas Eck
You can also use the WinNT: provider and the syntax
WinNT://Domain/sAMAccountName
to bind to any object in the directory. For example, you could bind the user object in Figure 1 as Fiction\teck. The object might be in an organizational unit (OU) dozens of levels below the domain's root, yet you can still use this simple syntax because domain\username will always be globally unique in the domain.