C#: How to check if the current user is an Administrator (even if UAC is on)

How to check if the current user is an Administrator (even if UAC is on)

There may be a scenario where you want to determine from code if the current user is an Administrator.

One example of this which I have had to deal with is checking for software updates.

Say your application contacts a service to see if there is a newer version of the application available; if so, you can download and run the installer.

Imagine that the installer requires admin privileges; you don’t want to run the installer if the current user does not have administrative privileges.

So how can we check if the user is an admin or not?

In VB6, C++ etc

There is a Windows API function you can use very easily to see if the current user is an admin: IsUserAnAdmin.

Visual Basic 6 Declaration

Private Declare Function IsUserAnAdmin Lib “Shell32″ Alias “#680″ () As Integer

While you can still use this, it is actually deprecated, and the documentation recommends you call the CheckTokenMembership function instead (which IsUserAnAdmin is a wrapper for).



using System;

using System.Security.Principal;

var identity = WindowsIdentity.GetCurrent();

if (identity == null) throw new InvalidOperationException("Couldn’t get the current user identity");

var principal = new WindowsPrincipal(identity);

return principal.IsInRole(WindowsBuiltInRole.Administrator);

User Account Control (UAC)

A problem arises when you use any of the above code on a machine that has UAC enabled, and the process is not elevated.

While the user may be an administrator, when the process is not elevated yet, the user has a split token – which doesn’t have the administrator privileges.

A way around this is to use the GetTokenInformation API call to inspect the token to see if it’s a split token. In most cases this will mean that UAC is on and the current user is an administrator.

This is not 100% reliable (see References) but it’s probably the best we can do for now.


This code is slightly easier in .NET, as there’s already a fair amount of code we don’t have to write to get the current process’s token.

First, we’ll need some code to support the GetTokenInformation API call:

[DllImport("advapi32.dll", SetLastError = true)]

static extern bool GetTokenInformation(IntPtr tokenHandle, TokenInformationClass tokenInformationClass, IntPtr tokenInformation, int tokenInformationLength, out int returnLength);

/// <summary>

/// Passed to <see cref="GetTokenInformation"/> to specify what

/// information about the token to return.

/// </summary>

enum TokenInformationClass


TokenUser = 1,






























/// <summary>

/// The elevation type for a user token.

/// </summary>

enum TokenElevationType


TokenElevationTypeDefault = 1,




Then, the actual code to detect if the user is an Administrator (returning true if they are, otherwise false).

var identity = WindowsIdentity.GetCurrent();

if (identity == null) throw new InvalidOperationException("Couldn’t get the current user identity");

var principal = new WindowsPrincipal(identity);

// Check if this user has the Administrator role. If they do, return immediately.

// If UAC is on, and the process is not elevated, then this will actually return false.

if (principal.IsInRole(WindowsBuiltInRole.Administrator)) return true;

// If we’re not running in Vista onwards, we don’t have to worry about checking for UAC.

if (Environment.OSVersion.Platform != PlatformID.Win32NT || Environment.OSVersion.Version.Major < 6)


// Operating system does not support UAC; skipping elevation check.

return false;


int tokenInfLength = Marshal.SizeOf(typeof(int));

IntPtr tokenInformation = Marshal.AllocHGlobal(tokenInfLength);



var token = identity.Token;

var result = GetTokenInformation(token, TokenInformationClass.TokenElevationType, tokenInformation, tokenInfLength, out tokenInfLength);

if (!result)


var exception = Marshal.GetExceptionForHR( Marshal.GetHRForLastWin32Error() );

throw new InvalidOperationException("Couldn’t get token information", exception);


var elevationType = (TokenElevationType)Marshal.ReadInt32(tokenInformation);

switch (elevationType)


case TokenElevationType.TokenElevationTypeDefault:

// TokenElevationTypeDefault – User is not using a split token, so they cannot elevate.

return false;

case TokenElevationType.TokenElevationTypeFull:

// TokenElevationTypeFull – User has a split token, and the process is running elevated. Assuming they’re an administrator.

return true;

case TokenElevationType.TokenElevationTypeLimited:

// TokenElevationTypeLimited – User has a split token, but the process is not running elevated. Assuming they’re an administrator.

return true;


// Unknown token elevation type.

return false;





if (tokenInformation != IntPtr.Zero) Marshal.FreeHGlobal(tokenInformation);




User Account Control (UAC) Step-by-Step Guide

User Account Control Step-by-Step Guide

Updated: April 20, 2011

Applies To: Windows 7, Windows Server 2008, Windows Server 2008 R2, Windows Storage Server 2008 R2, Windows Vista

User Account Control (UAC) is a security component that allows an administrator to enter credentials during a non-administrator’s user session to perform occasional administrative tasks. This step-by-step guide provides the instructions that are necessary for using UAC in a test environment. You can use this guide to test how your line-of-business (LOB) applications run in Windows 7 and Windows Vista.

In this guide



C#: How to elevate privileges only when required?

How to elevate privileges only when required?

This question applies to Windows Vista!

I have an application which normally works without administrative privileges. There is one activity which does need administrative privilege but I don’t want to start the application itself with higher privileges when I know most of time user wont even be using that feature.

I am thinking about certain method by which I can elevate the privileges of application on some event (such as press of a button). Example:

If user clicks this button then he is prompted with UAC dialog or consent. How can I do this?


Solution 1:

Process.StartInfo.UseShellExecute = true;

Process.StartInfo.Verb = "runas";

will run the process as admin to do whatever you need with the registry, but return to your app with the normal privileges.

Solution 2:

ted I don’t believe that it is possible to elevate the currently running process. It is built into Windows Vista that administrator privileges are given to a process upon startup, as I understand. If you look at various programs that utilise UAC, you should see that they actually launch a separate process each time an administrative action needs to be performed (Task Manager is one, Paint.NET is another, the latter being a .NET application in fact).

The typical solution to this problem is to specify command line arguments when launching an elevated process (abatishchev’s suggestion is one way to do this), so that the launched process knows only to display a certain dialog box, and then quit after this action has been completed. Thus it should hardly be noticeable to the user that a new process has been launched and then exited, and would rather appear as if a new dialog box within the same app has been opened (especially if you some hackery to make the main window of the elevated process a child of the parent process). If you don’t need UI for the elevated access, even better.

For a full discussion of UAC on Vista, I recommend you see this very through article on the subject (code examples are in C++, but I suspect you’ll need to use the WinAPI and P/Invoke to do most of the things in C# anyway). Hopefully you now at least see the right approach to take, though designing a UAC compliant program is far from trivial…



Active Directory: How Active Directory Searches Work

How Active Directory Searches Work

Applies To: Windows Server 2003, Windows Server 2003 R2, Windows Server 2003 with SP1, Windows Server 2003 with SP2, Windows Server 2008, Windows Server 2008 R2

How Active Directory Searches Work

In this section

In Active Directory, directory clients use Lightweight Directory Access Protocol (LDAP) to perform searches against the directory. LDAP is defined by Request for Comments (RFC) 3377, “Lightweight Directory Access Protocol (v3): Technical Specification.” LDAP is a standards-based protocol that makes it possible for users to query and update information in an LDAP-based directory service, such as Active Directory. To perform Active Directory searches, LDAP-compliant directory clients compose a search query using LDAP syntax and then submit the query to Active Directory for processing.

In Windows 2000 Server and Windows Server 2003, the directory service is named Active Directory. In Windows Server 2008 and Windows Server 2008 R2, the directory service is named Active Directory Domain Services (AD DS). The rest of this topic refers to Active Directory, but the information is also applicable to AD DS.

The ideal environment for Active Directory searches includes network connections between directory clients and Active Directory that are available and working properly, domain controllers that are running and replicating without errors, and directory clients that support LDAP v2 or LDAP v3. This section describes the elements of Active Directory searches, including architecture, protocols, interfaces, LDAP, processes and interactions, and network ports.

Active Directory Searches Architecture

The architecture for Active Directory searches includes both client and server components. On the client side, a directory client application constructs LDAP requests to be sent to Active Directory. These requests can be one of several types, including connect, bind (authentication), modify, and unbind. Depending on how a directory client application is written, one of three different application programming interfaces (APIs) is used to submit requests. The LDAP requests are received and processed by the Directory System Agent (DSA), which is represented by Ntdsa.dll on a domain controller. Ntdsa.dll runs as a part of the local security authority (LSA), which runs as Lsass.exe. The architecture for Active Directory searches is shown in the following figure.

Active Directory Searches Architecture

Active Directory Searches Architecture

The components of the architecture for Active Directory searches are described in the following table.

Active Directory Searches Components

Component Description
Directory client application Any application that is used to send LDAP messages to an LDAP directory service
LDAP APIs Interfaces through which a directory client application can submit an LDAP request. For directory clients running a Windows operating system, one of three LDAP APIs can be used. For more information, see “Active Directory Searches Interfaces” later in this section.
DSA (Ntdsa.dll) The DSA, which runs on each domain controller, accepts LDAP requests through its LDAP protocol head and issues LDAP responses based on those requests.
LDAP protocol head The LDAP interface on the DSA through which LDAP requests are accepted
LDAP request A message that is constructed with LDAP syntax and sent by a directory client application to an LDAP directory service, such as Active Directory
LDAP response A message that is constructed with LDAP syntax and sent by an LDAP directory service, such as Active Directory, to a directory client application

Active Directory Searches Protocols

LDAP is the standards-based protocol that directory client applications use to submit LDAP directory requests (for example, bind, search, modify, and unbind) to Active Directory. Active Directory supports both LDAP v2, which is defined in RFC 1777, “Lightweight Directory Access Protocol,” and LDAP v3, which is defined in RFC 3377. LDAP is designed to be connection oriented, and it uses Transmission Control Protocol (TCP) as its transport layer protocol. LDAP uses Internet Protocol (IP) as its network layer protocol. The Secure Sockets Layer (SSL) protocol can be used for encrypting LDAP communications.

The protocols that are used by Active Directory searches — and their relationship to the International Organization for Standardization (ISO) Open Systems Interconnection (OSI) 7-layered network protocol model — are shown in the following figure.


  • The ISO OSI model is a layered architecture that standardizes levels of service and types of interaction for computers that exchange information through a communications network. The ISO OSI model separates computer-to-computer communications into seven layers, or levels, with each level building on the standards that are contained in the levels below it.

Active Directory Searches Protocols

Active Directory Searches Protocols

The following table describes the protocols that are used in Active Directory searches.

Protocols Used in Active Directory Searches

Component Description
LDAP A standards-based protocol that is used for communication between directory clients and a directory service. LDAP is the primary directory access protocol for Active Directory.
SSL A standards-based protocol for encrypting private communications on the Internet. When a Certificate Services infrastructure is in place (that is, when you have installed a certification authority (CA)), specifying server port 636 in an LDAP bind call results in an attempt to establish an SSL session. The CA serves as the security authority for the secure channel (Schannel) authentication protocol, which includes SSL. For this reason, some form of certificate services must be in place to use LDAP over SSL. For more information about Certificate Services, see “Certificate Services Technical Reference.”
TCP The connection-oriented session protocol on which LDAP runs
IP A routable protocol that is responsible for the addressing, routing, and fragmenting of packets by the sending node. IP is required for Active Directory replication.

Active Directory Searches Interfaces

On computers running a Windows operating system, directory client applications can use one of three different LDAP APIs. As shown in the following figure, all LDAP requests from a directory client application ultimately go through the native LDAP C API, which runs as Wldap32.dll.

Active Directory Searches Interfaces

Active Directory Searches Interfaces

The following table describes the Windows LDAP APIs that are available for Active Directory searches.

Active Directory Searches APIs

API Description

(ADSI for .NET Framework)

A namespace in the Microsoft .NET Framework that provides simple programming access to LDAP directories, such as Active Directory. This API requires the Microsoft .NET Framework to be installed.
Active Directory Service Interfaces (ADSI) (Ads*.dll) A set of Component Object Model (COM) interfaces that abstracts the capabilities of directory services from different network providers (such as LDAP) in a distributed computing environment to present a single set of directory service interfaces for managing network resources.
Native LDAP API (Wldap32.dll) Provides functions that enable directory client applications to search for and retrieve information from an LDAP directory service, as well as functions for modifying directory entries where such modifications are permitted. There are also functions that provide access control for servers by allowing clients to authenticate themselves.

The LDAP Standard

To understand how Active Directory searches work, it is important to understand the LDAP standard. Active Directory structure is based on LDAP v3 requirements, which are defined in a series of Internet Engineering Task Force (IETF) RFCs, as summarized in RFC 3377.

LDAP features and functionality are described in four models:

  • The information model, or schema, which describes the structure of information in a directory information tree
  • The naming model, which describes how information is organized and referenced
  • The functional model, which describes what can be done with the information
  • The security model, which describes how information is protected in the directory information tree

Standardization of LDAP behavior through these models makes LDAP the preferred access protocol for all directory services.

Differences Between LDAP v2 and LDAP v3

Two versions of the LDAP specification exist: LDAP v2 and LDAP v3. LDAP v3 includes the following features that are not supported in LDAP v2:

  • The use of UCS Transformation Format (UTF)-8 for all text string attributes to support extended character sets. Active Directory sends all responses in UTF-8-encoded form.
  • Operational attributes that the directory maintains for its own use, for example, to log the date and time when another attribute is modified.
  • Referrals, which enable a server to direct a client to another server. An LDAP server can return a referral to an LDAP client when the operation that is presented by the client cannot be serviced locally but the LDAP server has information about other LDAP servers that can handle the operation.
  • Schema publishing with the directory, so that a client can discover what object classes and attributes a server supports.
  • Extended search operations that facilitate paging and sorting of results and client-defined searching and sorting controls.
  • Stronger security through the Simple Authentication Security Layer (SASL) authentication mechanism.
  • Extended operations, which provide additional functionality without changing the protocol version.


  • LDAP v3 is backward compatible with LDAP v2. One requirement of an LDAP v3 server is that an LDAP v2 client should be able to connect to the server. Active Directory is compliant with both LDAP v3 and LDAP v2 standards.

LDAP Information Model

The LDAP information model describes the structure of information in a directory. The LDAP information model is based on the entry, which contains information about some object, for example, a person or computer. In Active Directory, an LDAP entry is referred to as an object. Entries are composed of attributes, which have a type and one or more values.

The LDAP information model organizes objects into a hierarchical tree structure. The implementation of the model is called the schema, which is a set of objects that defines the structure and content of every object that can be created in a directory service.

A default (base) schema is installed with Active Directory. The Active Directory schema is stored in the schema directory partition, and the schema is replicated to every domain controller in the Active Directory forest.

For more information about the Active Directory schema, see “Active Directory Schema Technical Reference.”

Classes and Attributes

Classes and attributes are defined in the schema by classSchema objects (object classes) and attributeSchema objects (object attributes), as follows:

  • Object classes are categories of objects that can be created in the directory. For example, users, computers, and printers are classes of objects. Every object in the directory is created as an instance of some class according to the definition that is stored in the classSchema object for the respective class.
  • Object attributes are the characteristics of the object. (These characteristics are also called properties). An attribute can hold a value or values that represent some property of the object. For example, given name, surname, and e-mail address are attributes of every object of the user class, and their values can be created only as character strings. The schema specifies the attributes that are required to have values and the attributes that can have values as an option. In Active Directory, only attributes that have values assigned to them actually use storage space in the database.
  • Each attribute has a syntax that is specified in the schema that determines the kind of values that are allowed in the attribute. Examples of attribute syntaxes are Unicode string, binary, and integer.

New object classes and attributes can be added to the schema, and existing objects can be modified by adding or modifying classSchema and attributeSchema objects.

Child classes inherit attributes from their parent classes. Therefore, each class builds on the attribute set of its parent class. The position in the directory tree of one object relative to another is also defined in the schema.

Categories of Object Classes

Different categories of object classes make it possible to define structure in the directory. The 1993 X.500 specification requires that object classes be assigned to one of three categories:

  • Structural
  • Abstract
  • Auxiliary
Structural classes

Structural classes are the only classes that can have instances in the directory. That is, you can create directory objects whose class is one of the structural classes. A structural class:

  • Can be used in defining the structure of the directory.
  • Is derived from either an abstract class or another structural class.
  • Can include any number of auxiliary classes in its definition.
Abstract classes

Abstract classes are templates that are used to derive new structural classes. Abstract classes cannot be instantiated in the directory. This means that no object can belong only to an abstract class; each object of an abstract class also belongs to some structural subclass of that class. A new abstract class can be derived from an existing abstract class. Abstract classes only provide attributes for subordinate classes, which are called subclasses. A subclass contains all mandatory and optional attributes of the class from which it is derived (its superclass) in addition to those attributes that are specific to the class itself. Likewise, the subclass of that class contains all attributes of both superclasses, and so forth.

Auxiliary classes

Auxiliary classes are like include files; they contain a list of attributes. Adding an auxiliary class to the definition of a structural class or an abstract class adds the auxiliary class’s attributes to the definition of the structural class or the abstract class. An auxiliary class cannot be instantiated in the directory, but new auxiliary classes can be derived from existing auxiliary classes. For example, the securityPrincipal class is an auxiliary class, and it derives its attributes from the parent abstract class called Top. Although you cannot create a security principal object in the directory (because auxiliary classes cannot have instances), you can create an object of the structural class user, which has the securityPrincipal class as an auxiliary class. The attributes of the securityPrincipal class help the system recognize the user object as a security account. Similarly, the group class has securityPrincipal as an auxiliary class.

Windows 2000 Server vs. Windows Server 2003 auxiliary classes

The behavior of auxiliary classes has changed in Windows Server 2003. In Windows 2000 Server, changes that are made to an auxiliary class affect its parent class as well as all instances of the parent object. For example, adding an auxiliary class called pager to the structural class user affects all instances of user, which are all of the user accounts that are created with the user class.

In Windows Server 2003, auxiliary classes can be assigned dynamically to individual instances of classes, rather than being applied automatically to all instances. For example, you can assign the pager auxiliary class to only those users who need it.

Object Identifiers

Object identifiers (also known as OIDs) are hierarchical, dotted-decimal numeric values that uniquely identify entries in a data model. Object identifiers are found in OSI applications, X.500 directories, Simple Network Management Protocol (SNMP), and other applications in which uniqueness is required. Object identifiers are based on a tree structure in which a designated issuing authority (such as the ISO) allocates a branch of the tree to a subauthority, which in turn can allocate subbranches. The Active Directory schema identifies the object identifier for each class, attribute, and syntax.

Schema Versions

The schema directory partition has an attribute called objectVersion that stores the schema version number for a forest. To facilitate upgrading your forest from Windows 2000 Server to Windows Server 2003, Windows Server 2003 includes a tool (Adprep.exe) that automatically upgrades the schema to the version that is required by Windows Server 2003. Before you upgrade the first domain controller, you must use this tool to prepare the domain and the forest so that the schema is upgraded before the operating system is upgraded. Running Adprep.exe prepares the forest and the domain for the Active Directory upgrade by making certain data changes, including an extension of the schema. This schema extension merges existing schema information with new schema information that is supplied by Adprep.exe. This merging of schema information does not affect any schema modifications that you may have already made in your existing environment.

Leaf Objects and Container Objects

Objects in Active Directory are either leaf objects or container objects. A leaf object is an object that has no child objects. The term “container” refers to one of two things:

  • An object of the container structural class
  • An object that has child objects

In the schema, a structural class defines objects that can be created as instances of the class in Active Directory. To have child objects, an object must be an instance of a class that is defined by the schema as being a possible superior of those child objects.


  • A new attribute in the Windows Server 2003 schema, msDsApproxImmedSubordinates, stores the approximate count of immediate children of a container. You can use the ADSI Edit snap-in in Microsoft Management Console (MMC) to view the value of this attribute for any container object. Windows 2000 Server containers do not have this attribute.

Directory Tree

The directory tree represents the hierarchy of Active Directory objects for a given forest. The structure of the hierarchy is derived from the schema, and the directory service implements the hierarchy. The hierarchy provides the basis both for using names for navigation and for defining the scope of search requests.

Every object in Active Directory has exactly one parent, and a reference to the parent object is stored with the object. By virtue of these parent references, the hierarchy of objects that are managed by Active Directory forms a tree structure. The objects that populate the directory create this tree structure according to the rules of the schema. For example, the schema might dictate that a given class of object can be the child of one class but not the child of another class.

The following are architectural restrictions and requirements in the directory tree:

  • Domain objects, which are containers, can be children only of other domain objects. For example, a domain cannot be the child of an organizational unit (OU).
  • The root of the directory tree is a DSA-Specific Entry (DSE) called the rootDSE, or the directory root. The rootDSE is an object that has no hierarchical name or schema class, but it does have a set of attributes that identify the contents of a given domain controller. Therefore, the rootDSE constitutes the root of the directory tree from the perspective of the domain controller to which you are connected.
  • Below the rootDSE, every directory has a root domain, which is the first domain that is created in a forest. This domain always has a child container called the Configuration container, which contains configuration data for the forest.


An LDAP directory service is also referred to as a DSA. In Active Directory, servers that host DSAs are domain controllers.

At the root of an LDAP directory tree is a DSE (the rootDSE), which is not part of any directory partition. TherootDSE represents the top of the logical namespace for one domain controller. The rootDSE attributes contain information about the directory server, including its capabilities and configuration.

There is only one root for a given DSA, but the information that is stored in the root is specific to the domain controller to which you are connected. Among other things, the attributes of the rootDSE identify the following key information:

  • The directory partitions (the domain, schema, and configuration directory partitions) that are specific to one domain controller
  • The forest root domain directory partition

In this way, the rootDSE provides a “table of contents” for a given domain controller. For more information about rootDSE attributes, see “Data Store Technical Reference.”

LDAP Naming Model

The LDAP naming model describes how information is organized and referenced in an LDAP directory. LDAP requires that names of directory objects be formed according to RFC 1779, “A String Representation of Distinguished Names,” and RFC 2247, “Using Domains in LDAP/X.500 Distinguished Names.”

For more information about the LDAP naming model, see RFC 1779 and RFC 2247 in the IETF RFC Database.

Distinguished Name

Every object in Active Directory has a distinguished name (also known as DN). A distinguished name uniquely identifies an object by using the name of the object, plus the names of the container objects and domains that contain the object. Therefore, the distinguished name identifies the object as well as its location in a tree. The distinguished name is unambiguous (that is, it identifies one object only) and unique (that is, no other object in the directory has this name). It contains enough information for an LDAP client to retrieve the object’s information from the directory.

For example, a user named Jeff Smith works in the marketing department of a company as a promotions coordinator. His user account is created in an OU that stores the accounts for marketing department employees who are engaged in promotion activities. The root domain of the company is proseware.com, and the local domain is noam.proseware.com. The distinguished name for this user object is:

cn=Jeff Smith,ou=promotions,ou=marketing,dc=noam,dc=proseware,dc=com

Relative Distinguished Name

The relative distinguished name (also known as the RDN) of an object is the part of the distinguished name that is an attribute of the object itself — the part of the object name that identifies this object as unique within a container. For the example in the previous paragraph, the relative distinguished name of the user object:

cn=Jeff Smith,ou=promotions,ou=marketing,dc=noam,dc=proseware,dc=com

is cn=Jeff Smith.

The following figure illustrates the relative distinguished names that make up the distinguished name of the user object Jeff Smith.

Relative Distinguished Names That Make Up a Distinguished Name

Relative Distinguished Names in Distinguished Name

The maximum length that is allowed for a relative distinguished name is 255 characters, but attributes have specific limits that are imposed by the directory schema. For example, in the case of the common name (cn), which is the attribute type that is often used for naming the relative distinguished name, the maximum number of characters that is allowed is 64.

Active Directory relative distinguished names are unique within a container; that is, Active Directory does not permit two objects with the same relative distinguished name under the same parent container. However, two objects can have identical relative distinguished names but still be unique in the directory because, within their respective parent containers, their distinguished names are not the same. For example, the object cn=Jeff Smith,cn=users,dc=noam,dc=proseware,dc=com is recognized by LDAP as being different from cn=Jeff Smith,ou=marketing,dc=noam,dc=proseware,dc=com.

The relative distinguished name for each object is stored in the Active Directory database. Each object in the directory contains a reference to the parent of the object. An LDAP operation can construct the entire distinguished name by following these references to the root.

Naming Attributes

Each portion of the distinguished name is expressed as attribute_type=value. The attribute type that is used to describe the object’s relative distinguished name (in the Jeff Smith example, cn) is called the naming attribute. In Active Directory, instances of classes have a default mandatory naming attribute that is defined in the schema. For example, part of the definition of the class user is the attribute cn (Common-Name) as the naming attribute. Therefore, the relative distinguished name for user Jeff Smith is expressed as cn=Jeff Smith.

Classes that do not define a naming attribute inherit the naming attribute from their parent class. If you create a new class in the Active Directory schema (that is, if you create a new classSchemaobject), you can use the optional rDNAttID attribute to specify the naming attribute for the class.

The following table shows the naming attributes that are used in Active Directory.

Default Active Directory Naming Attributes

Object Class Naming Attribute Display Name Naming Attribute LDAP Name
user Common-Name cn
organizationalUnit Organizational-Unit-Name ou
domain Domain-Component dc

Other naming attributes that are described in RFC 2253, “Lightweight Directory Access Protocol (v3): UTF-8 String Representation of Distinguished Names,” such as o= for organization name and c= for country/region name, are not used in Active Directory.

The use of distinguished names, relative distinguished names, and naming attributes is required when you are programming for LDAP and using ADSI or other scripting or programming languages. Active Directory tools, such as Active Directory Users and Computers, do not require you to enter such values, nor do they display these values. However, LDAP editors, such as ADSI Edit in Support Tools, require input and display output in the LDAP distinguished name format.

Using different naming attributes for users to avoid naming collisions

To ensure data integrity, Active Directory requires that relative distinguished names be unique in a container. By default, the user class uses Common-Name (cn) as the naming attribute, which ties the test for uniqueness to the user name. The combination of these two restrictions can result in naming collision problems in large deployments. For example, a very large company might want to create user accounts in the same OU where, as a result of the high incidence of certain common names, many user objects have identical first and last names and, therefore, identical relative distinguished names. In this scenario, it is helpful to be able to use a different naming attribute that guarantees uniqueness, such as an employee ID that is created by the human resources department.

The inetOrgPerson object class is a general-purpose object class that holds attributes about people, and it is defined in RFC 2798, Definition of the inetOrgPerson LDAP Object Class. A solution is provided in the Windows Server 2003 schema so that administrators can delete inetOrgPerson (which uses cn as the naming attribute in the default schema) and re-create it using any attribute as the naming attribute. For example, instead of cn, the attribute emplID can be used as the naming attribute. You can choose the attribute and select one that will guarantee that there are no naming collisions.

For more information about inetOrgPerson, see Active Directory Schema Technical Reference.

Object identity

In addition to its distinguished name, every object in Active Directory has an identifier that is unique. This identifier is called the globally unique identifier (GUID). A GUID is a unique 128-bit number that is assigned by the DSA when the object is created. Objects might be moved or renamed within a forest, but their GUID never changes. The GUID is stored in an attribute, objectGUID, which is present on every object. The objectGUID attribute is protected so that it cannot be altered or removed. When you store a reference to an Active Directory object in an external store (for example, in a database, such as Microsoft SQL Server), you should use the objectGUID value to represent the object uniquely.

Active Directory Name Formats

In addition to distinguished names, other formats for providing object names are supported by Active Directory. These formats accommodate the different forms that a name can take, depending on its application of origin.

The LDAP distinguished name in the example earlier in this section can be used to illustrate the other Active Directory name formats. This example distinguished name identifies the account of user Jeff Smith in the OU Promotions, in the OU Marketing, in the domain noam.proseware.com:

cn=Jeff Smith,ou=promotions,ou=marketing,dc=noam,dc=proseware,dc=com

The following formats are supported by Active Directory, and the format examples are based on the LDAP distinguished name of Jeff Smith:

  • LDAP Uniform Resource Locator (URL). Active Directory supports access through the LDAP protocol from any LDAP-enabled client. LDAP URLs are used in scripting. An LDAP URL names the server that holds Active Directory and the attributed name of the object (the distinguished name), for example:

    ldap://server1.proseware.com/cn=Jeff Smith,ou=promotions,ou=marketing,dc=noam,dc=proseware,dc=com

  • Active Directory canonical name. By default, the user interface (UI) for certain Active Directory administrative tools displays object names as canonical names. When you view the properties of objects in Active Directory Users and Computers and Active Directory Sites and Services, the Object tab shows the canonical name of the selected object. The canonical name lists the relative distinguished names from the root downward, without the naming attribute descriptors, and it uses the Domain Name System (DNS) domain name, as follows:

    noam.proseware.com/marketing/promotions/Jeff Smith


  • If the name of a container includes a forward slash character (/), the system requires an escape character in the form of a backslash (\) to distinguish between forward slashes that separate elements of the canonical name and the forward slash that is part of the container name. For example, if the name of an OU is Promotions/Northeast and the name of the domain is proseware.com, the canonical name is displayed as proseware.com/Promotions\/Northeast.

DNS-to-LDAP Distinguished Name Mapping

Although DNS domain names match Active Directory domain names, they are not the same thing. Active Directory names have a different format, which is required by LDAP to identify directory objects. Therefore, DNS domain names are mapped to Active Directory domain names (and back again) as described in RFC 2247.

All access to Active Directory is carried out through LDAP, and every object in Active Directory has an LDAP distinguished name. An algorithm automatically provides an LDAP distinguished name for each DNS domain name.

The algorithm provides a domain component (dc) attribute-type label for each DNS label in the DNS domain name. Each DNS label corresponds to the relative distinguished name of a DNS domain. For example, the DNS domain noam.proseware.com is translated to the LDAP distinguished name that has the form dc=noam,dc=proseware,dc=com.

LDAP Functional Model

The LDAP functional model describes what can be done with directory information. The functional model consists of nine operations in the following three areas:

  • Authentication provides a method for the client to prove its identity to the DSA.
  • Interrogation provides a method for the client to interrogate the directory information tree.
  • Update provides a method for the client to add or modify information in the directory information tree.

The following table shows the nine basic LDAP operations according to their functional areas.

LDAP Functional Model Operations

Functional Area Operations
  1. Bind
  2. Unbind
  3. Abandon
  1. Search
  2. Compare
  1. Add
  2. Modify
  3. Modify RDN
  4. Delete


LDAP authentication consists of the following operations:

  • Bind. Initiates a protocol session to the DSA. After a session is established, a method of authentication is negotiated between the DSA and the client. When the client is authenticated by the DSA, the DSA returns a bind response to the client.
  • Unbind. Terminates an LDAP session between the client and the DSA.
  • Abandon. Issued by the client to stop obtaining the results of a previously initiated operation.


LDAP interrogation consists of the following operations:

  • Search. Used to select entries from a specific region of the directory information tree based on customized criteria called a search filter. The search operation includes several arguments, which are described in “Performing an LDAP Search” later in this section.
  • Compare. Returns a Boolean response based on a comparison of an entry’s attribute value with a user-supplied value.


LDAP update consists of the following operations:

  • Add. Creates an object in the directory information tree based on information that is provided by the client to the DSA. The information that is passed to the DSA must meet the conditions that are imposed on entry creation through the classes that are defined in the schema.
  • Modify. Allows the client to modify an entry’s attributes. Modification of attributes includes creating, modifying, and deleting the attributes.
  • Modify RDN. Provides a mechanism for an entry to be moved in the directory. Modifying the relative distinguished name components of an entry effectively moves the entry to a new container in the directory.
  • Delete. Provides a method for a client to remove an entry from the directory. The success of an entry modification depends on the schema’s constraints and the access permission of the client.

Extended LDAP Controls

Active Directory supports several LDAP controls that extend the functionality of LDAP v3 beyond the standard set of nine LDAP operations. Microsoft has defined these LDAP controls to provide functionality in Active Directory that is not provided by current IETF RFCs. The rootDSE indicates all controls that are in effect for the contacted server through the object identifier values in the supportedControl attribute.

Extended LDAP control functionality is useful to programmers who are using LDAP to perform directory operations. Some of the operations that can be implemented by using extended controls are deleting trees, paging and sorting search results, and showing deleted objects. For more information about these operations, see “Optimizing Searches” later in this section.

LDAP Security Model

The LDAP security model specifies how to access information in the directory in a secure manner. RFC 2251, “Lightweight Directory Access Protocol (v3),” states that SASL mechanisms may be used with LDAP to provide security services. RFC 2222, “Simple Authentication and Security Layer (SASL),” defines SASL.

The rootDSE includes an attribute called supportedSASLMechanisms that lists the supported SASL security features.

RFC 2222 describes a method for providing authentication support in connection-based protocols. To use this specification, protocols have to include a command to identify and authenticate users to a server and, optionally, to negotiate protection of subsequent protocol interactions. If protection is negotiated, a security layer is inserted between the protocol and the connection. RFC 2222 explains how a protocol specifies such a command, and it defines several mechanisms for use by the command, as well as by the protocol, that carry a negotiated security layer over the connection.

Active Directory supports SASL mechanisms, including Kerberos V5 and NTLM. To view the supported SASL mechanisms, you can query the rootDSE. When you perform the query, Active Directory returns the supportedSASLMechanisms attribute and other attributes. The rootDSE attribute value is supportedSASLMechanisms: GSSAPI; GSS-SPNEGO, where GSSAPI = Kerberos and GSS-SPNEGO = NT Negotiate (Kerberos, NTLM, and so on).

The Generic Security Service Application Program Interface (GSS-API), which is defined in RFC 2078, Generic Security Service Application Program Interface, Version 2, provides security services to callers in a generic manner that can be supported with a range of underlying mechanisms and technologies. This enables applications (at the source level) to be ported to different environments. RFC 2078 defines GSS-API services at a level that is independent of the underlying mechanism and programming language environment.

RFC 1510, “The Kerberos Network Authentication Service (V5),” defines an authentication process that provides a method for verifying the identities of principals, such as workstation users and network servers, on an open network. For authentication purposes, clients use Kerberos tickets, which represent the clients’ network credentials. Clients obtain the tickets from the Kerberos Key Distribution Center (KDC), and they present these tickets when a network connection is established. Kerberos represents the identity of a client by using its domain name, user name, and password.

The Active Directory security infrastructure also supports the following primary security protocols:

  • The NTLM authentication protocol is provided to support Windows NT version 4.0 and earlier. NTLM will continue to be supported and used for pass-through network authentication, remote file access, and authenticated Remote Procedure Call (RPC) connections to previous versions of Windows NT.
  • Distributed Password Authentication (DPA) is the authentication protocol that is used by many Internet membership organizations, such as MSN and CompuServe. This authentication protocol is part of Microsoft Commercial Internet System (MCIS) services, and it is designed specifically to enable users to use the same Internet membership password to connect to various Internet sites that are part of the same membership organization. The Internet content servers use MCIS as an authentication service, and users can connect to multiple sites without reentering their passwords.

The following table lists the LDAP authentication methods that are supported by Active Directory.

LDAP Authentication Methods

LDAP Authentication Method Description Credential
SIMPLE Authentication with a simple plaintext password A string containing the user’s password
NTLM An authentication protocol that is used on stand-alone systems and on networks that include systems running the Windows NT 4.0 operating system An array of strings containing the domain name, user name, and encrypted password
DPA Distributed password authentication, which is used by the Microsoft Membership System component of the MCIS Encrypted password
NEGOTIATE (GSS-API) Does not provide any authentication services; instead, it chooses the most appropriate authentication method from a list of available services and passes all authentication information on to that service. To log on as the current user, set the dn and cred parameters to NULL. To log on as another user, pass a pointer to a SEC_WINNT_AUTH_IDENTITY structure with the appropriate user name and password.
SSPI This constant (Security Support Provider Interface (SSPI)) is obsolete, and it is included for backward compatibility only. Using this constant selects GSS-API. Same as NEGOTIATE


  • If a directory client attempts to bind to a directory server without specifying credentials, an anonymous bind is attempted. Active Directory does not accept anonymous binds by default. However, Active Directory can be configured to accept anonymous binds. For more information, see “Anonymous queries” later in this section.

Although the LDAP security model does not include mechanisms for access control, Active Directory provides access control in the form of access control lists (ACLs) on directory objects.

LDAP Encoding

In accordance with RFC 2251, LDAP protocol elements are encoded on the wire using the Basic Encoding Rules (BER) of Abstract Syntax Notation One (ASN.1).

Active Directory Searches Processes and Interactions

Performing an Active Directory search involves several processes, including finding a server, establishing a connection, authenticating, and actually performing the search. In addition, performing an Active Directory search may involve the use of an LDAP referral, which is a reference pointing to a location where data that is searched for might be found. When a search is performed, several features may be used to optimize the search, including indexing, LDAP query policy, the global catalog, query limits, and paging.

Searching Active Directory

Searching is the most common directory activity. To complete an LDAP search, a directory client must complete a series of steps, as follows:

  • Find an LDAP directory server
  • Establish a connection
  • Authenticate against (bind to) the LDAP directory server
  • Perform a search

Windows Server 2003 provides several directory client tools for searching Active Directory, including the following:

  • Active Directory Users and Computers (a Microsoft Management Console (MMC) snap-in that is installed by default on domain controllers)
  • ADSI Edit (an MMC snap-in that is installed with Windows Support Tools)
  • Dsquery (a command-line tool that is installed by default on Windows Server 2003)
  • Ldp (an LDAP graphical user interface (GUI) tool that is installed with Windows Support Tools)
  • Search Companion (which appears on the Start menu as the Search command)

In addition to these tools, many non-Microsoft applications are available for searching Active Directory as well as other LDAP directory servers. The information that you provide the search tool to complete the steps that are described in the following sections depends on the tool that you are using. For example, some directory client tools and applications find an LDAP directory server and establish a connection automatically.

Finding a Server

The first step that a directory client must take in conducting an Active Directory search is to find an LDAP directory server (in other words, a domain controller) to search against. To find a domain controller, directory clients rely on DNS. When a domain controller starts up, it registers service (SRV) records in DNS that indicate that the domain controller provides LDAP directory services. To locate a domain controller, a directory client performs a DNS query for SRV records of hosts that provide LDAP directory services. For more information about how DNS is used to locate domain controllers, see “DNS Support for Active Directory Technical Reference.”

Establishing a Connection

After it finds a directory server, a directory client must next connect to the server. A directory client can connect to an LDAP directory server by opening a session on a TCP port number on which the LDAP directory server is listening. The string that is used to establish the connection includes the fully qualified domain name (FQDN) of the LDAP directory server, along with the TCP port number of the directory server. For standard LDAP searches, directory clients connect to TCP port 389. To search the Active Directory global catalog, directory clients must instead connect to TCP port 3268.

For more information about the global catalog, see “Global Catalog Searches” later in this section. For information about TCP ports that are used by LDAP directory servers and clients, see “Network Ports Used by Active Directory Searches” later in this section.

Authenticating (Binding)

After a directory client establishes a communications path to the domain controller, it must bind to the domain controller to establish the logon and authentication credentials and, if necessary for Windows-based computers, set up a secure channel. (A client can also attempt to bind to a domain controller without first establishing a connection.) The bind operation identifies the connecting person, device, or application to the server by providing a distinguished name and some type of authentication credential, such as a password. The exact credentials depend on the authentication method that is being used.

LDAP v3 enables the client to negotiate with the LDAP server to determine the best available security package. If no security package is available, the bind is a simple bind that uses a plaintext password. The Microsoft implementation of the LDAP API uses the NEGOTIATE flag so that the client can discover the best security package that is available. For example, a SASL mechanism, such as Kerberos V5 or NTLM, might be used. A domain controller can be also be configured to accept anonymous connections.

LDAP bind request

The bind command initiates a protocol session to the domain controller. After a session is established, a method of authentication is negotiated between the domain controller and the client. By default, Kerberos is used, but other methods can also be used. Finally, the domain controller returns a bind response to the client when the client is authenticated.

According to RFC 2251, the LDAP bind request has the following parameters:

  • Version. A version number that indicates the version of the protocol to be used in this protocol session. Note that there is no version negotiation, and the client sets this parameter to the appropriate version.
  • Name. The name of the directory object to which the client wants to bind. This field can take on a null value (a zero-length string) for the purposes of anonymous binds, when authentication has been performed at a lower layer, or when the client is using credentials that are established through a SASL mechanism.
  • Authentication. Information that is used to authenticate the name, if any, that is provided in the bind request.

When a server receives a bind request, it authenticates the requesting client, if necessary. The server then returns a bind response to the client indicating the status of the authentication.

In the following Network Monitor example of an LDAP bind request, the LDAP version is 3, the Name is null, and the authentication type is SASL:

Copy Code

LDAP: ProtocolOp: BindRequest (0) LDAP: MessageID = 11 (0xB) LDAP: ProtocolOp = BindRequest LDAP: Version = 3 (0x3) LDAP: Name = LDAP: Authentication Type = Sasl LDAP: Sasl Mechanism = GSS-SPNEGO LDAP: Sasl Credentials 
LDAP authentication methods

The Windows Server 2003 and Windows 2000 Server implementations of LDAP include support for the authentication methods that are described in “LDAP Security Model” earlier in this section.


  • Authentication within and between Windows Server 2003 and Windows 2000 Server domains is performed by using either the Kerberos V5 authentication protocol (the default method) or NTLM (for Windows NT 40 and earlier). Other methods are available to other clients and external users who connect over the Internet. For more information about authentication, see “Logon and Authentication Technologies.”
LDAP bind response

An LDAP bind response is an indication from the server regarding the status of a request for authentication of the client. If the bind is successful, the result code is “success.” Otherwise, an error is reported in accordance with RFC 2251.

The following is a Network Monitor example of a successful LDAP bind response:

Copy Code

LDAP: ProtocolOp: BindResponse (1) LDAP: MessageID = 18 (0x12) LDAP: ProtocolOp = BindResponse LDAP: Result Code = Success LDAP: Matched DN = LDAP: Error Message = LDAP: Sasl Mechanism = GSSAPI LDAP: Sasl Credentials 

The following is a Network Monitor example of an unsuccessful LDAP bind response:

Copy Code

 LDAP: ProtocolOp: BindResponse (1) LDAP: MessageID = 8 (0x8) LDAP: ProtocolOp = BindResponse  LDAP: Result Code = Invalid Credentials LDAP: Matched DN = LDAP: Error Message = 

The client and server can use simple protected negotiation (SPNEGO) to negotiate either through Kerberos V5 or NTLM, depending on the authentication mechanisms that are available to the particular client and server. With SPNEGO, both the client and server negotiate on a common secure authentication mechanism (Kerberos V5 or NTLM). For more information about SPNEGO, see “Logon and Authentication Technologies.

Concurrent bind for Web site logons

Internet service providers (ISPs) can use LDAP authentication for Active Directory user accounts. In this case, users do not actually have (or need) direct access to Active Directory objects. An application on the Web server uses LDAP to request user name and password verification of credentials that are presented by the site user. The application then passes the user information to Active Directory, which authenticates the user.

Domain controllers running Windows Server 2003 can perform concurrent binds. Unlike normal binds that are serialized on a single connection, concurrent binds enable applications to request multiple binds over a single LDAP connection. Concurrent binds are faster than normal binds, which require construction of a full security token for later use in access checks. In the Web site case, the user has no need for the security token.

Unlike a normal LDAP bind, a concurrent bind does not determine a user’s group association or build a token. The concurrent bind determines only whether the user has a valid user name and password and that the account is enabled. Eliminating the construction of the access token permits the concurrent bind to complete in a fraction of the time that it takes a normal bind to complete.

Determining if concurrent bind exists

To determine if your version of Active Directory supports concurrent binds, view the values in the supportedExtension attribute of the rootDSE. If concurrent binds are supported, the returned attribute includes the value 1.2.840.113556.1.4.1781.

For information about concurrent binding, see “Using Concurrent Binding” in the Microsoft Platform SDK on MSDN.

Anonymous queries

By default, anonymous LDAP operations to Active Directory, other than rootDSE searches and binds, are not permitted in Windows Server 2003. (Active Directory in Windows 2000 Server accepts anonymous requests; a successful result depends on objects having correct user permissions in Active Directory.)

To enable anonymous binding to Active Directory in Windows Server 2003, you must change the seventh character of the dsHeuristics attribute on the following directory object:

CN=Directory Service,CN=Windows NT,CN=Services,CN=Configuration,Root domain in forest

Valid values for the dsHeuristics attribute are 0 and 2. By default, the dsHeuristics attribute does not exist, but its internal default is 0. If you set the seventh character to 2, anonymous clients can perform any operation that is permitted by the access control list (ACL). If the attribute is already set, do not modify any bits in the dsHeuristics string other than the seventh bit. If the value is not set, make sure that you provide the leading zeros up to the seventh bit. You can use Adsiedit.msc to make the change to the dsHeuristics attribute.

After you set the dsHeuristics attribute, if you want anonymous users to be able to query Active Directory, you can enable anonymous access to specific directory objects. Users gain anonymous access to Active Directory objects through Anonymous Logon, which is a special security identifier (SID) that is used to represent anonymous network callers that perform an LDAP bind with NULL credentials.

Performing an LDAP Search

LDAP searches are the most common LDAP operations that are performed against an Active Directory domain controller. An LDAP search retrieves information about all objects within a specific scope that have certain characteristics, for example, the telephone number of every person in a department.

The following parameters are used in LDAP to accomplish an LDAP search:

  • Search base (the distinguished name of the search base object). Defines the location in the directory from which the LDAP search begins.
  • Search scope. Defines how deep to search within the search base:
    • Base (or zero level). Indicates a search of the base object only.
    • One level. Indicates a search of objects immediately subordinate to the base object but not the base object itself.
    • Subtree. Indicates a search of the base object and the entire subtree of which the base-object distinguished name is the topmost object.
  • Filter. Allows certain entries in the subtree and excludes others.
  • Selection. Indicates what attributes to return from objects that match the filter criteria.
  • Optional controls that affect how the search is processed.

The following figure shows the base distinguished name and the possible search scopes of an LDAP search.

LDAP Search Base and Three Search Scopes

LDAP Search Base and Three Search Scopes

The following figure shows the base distinguished name for a container object that is the search base for a search of an OU structure in Active Directory. The entire distinguished name is constructed from the relative distinguished name of an OU named Sales.

Base Distinguished Name for an LDAP Search

Base Distinguished Name for an LDAP Search

Search filters

By using search filters, you can define search criteria to achieve more effective and efficient searches. For example, you might be interested in all the user’s whose surname is Smith, or you might want to find all the team members who report to a manager named Jeff Smith. ADSI supports LDAP search filters as defined in RFC 2254, “The String Representation of LDAP Search Filters.” These search filters are represented by UTF-8 strings. The following table lists some commonly used LDAP search filters.

Common LDAP Search Filters

Filter Description
(objectCategory=*) All objects
(&(objectClass=user)(!(cn=susan))) All user objects except susan
(sn=sm*) All objects with a surname that starts with sm
(&(objectClass=contact)(|(sn=Smith) (sn=Johnson))) All contacts with a surname equal to Smith or Johnson

The search filters in the previous table use one of the following formats:

(attribute operator value)


(operator (filter1) (filter2))

The following table lists some of the most frequently used LDAP search filter operators.

Commonly Used LDAP Search Filter Operators

Operator Description
= Equal to
~= Approximately equal to
<= Lexicographically less than or equal to
>= Lexicographically greater than or equal to
| OR

For more information about LDAP search filter syntax, see “Search Filter Syntax” in the Microsoft Platform SDK on MSDN.

objectClass vs. objectCategory in a search filter

Sometimes, you might want to search Active Directory for objects of a particular type. For example, you might want to search for Active Directory objects that represent users. You can do this by searching for objects of a particular object class, using the objectClass attribute (objectClass=user). Or, you can search for objects of a particular category, using the objectCategory attribute (objectCategory=user). Because of the class inheritance hierarchy in the schema, every object in Active Directory is in fact a member of many classes — four or five, on average. For this reason, searches that use objectClass can be less accurate than searches that use objectCategory.

For example, a search filter of objectClass=user returns both user and computer objects. On the other hand, objectCategory usually refers to the most specific class in the object’s class hierarchy. Every Active Directory object has an objectCategory attribute whose value is a classSchema object. For example, a search filter of objectCategory=user returns only user objects. Although objectClass can have multiple values, the attribute objectCategory has only one value.


  • Every classSchema object has an attribute called defaultObjectCategory, which is the object category of an instance of the class if no object category is specified by the user. For most classes, the defaultObjectCategory value is the class itself. In the search filter, you can specify objectCategory=X, where X is the ldapDisplayName of a class and LDAP automatically expands the filter to objectCategory=defaultObjectCategory of class X. The objectCategory attribute has a syntax of distinguished name, and LDAP automatically converts the value for objectCategory to the distinguished name format. For example, if you use objectCategory=contact in the filter, the filter changes to objectCategory=cn=Person,cn=Schema,cn=Configuration,dc=ForestRootDomain. (Person is the defaultObjectCategory for the class Contact).

For more information about class inheritance, see “Active Directory Schema Technical Reference.”

LDAP Referrals

When a requested object exists in the directory but is not present on the contacted domain controller, resolution of the object name depends on information that is stored on that domain controller about how the directory is partitioned. In a partitioned directory, by definition, the entire directory is not always available on any one domain controller.

In its Configuration container, every domain controller has information about the other domains in the forest. The objects in cn=Partitions,cn=Configuration,dc=ForestRootDomain are cross-reference objects that contain information that Active Directory uses to construct the directory tree hierarchy. When an operation in Active Directory requires action on objects that might exist in the forest but that are not located in the particular domain that is stored on a domain controller, that domain controller must send the client a message that describes where to continue this action — that is, the client is “referred” to a domain controller that is presumed to hold the requested object.

An LDAP referral is a domain controller’s way of indicating to a client application that the domain controller does not have a copy of a requested object (or, more precisely, that the domain controller does not hold the section of the directory tree where that object would be if, in fact, it exists) and of providing the client with a name of a server that is more likely to hold the object. The client uses the name of the server that is provided in the LDAP referral as the basis for a DNS search for a domain controller. Ideally, referrals always reference a domain controller that does indeed hold the object. However, it is possible for the referred-to domain controller to generate yet another referral, although it usually does not take long to discover that the object does not exist and to inform the client that the object does not exist. Active Directory returns referrals in accordance with RFC 2251.

Clients do not have to know the name or location of a child domain to contact a domain controller in that domain. They can query the root domain and reach the appropriate domain controller by being referred there. Two situations generate this type of domain controller response:

  • An external referral, in which the base distinguished name of the requested object is not in this directory, but the domain controller holds information about another LDAP directory where the requested object might be found.
  • A subordinate referral, in which the base distinguished name of the requested object is in this directory, but the directory partition that contains the requested object is not stored locally.

Every domain controller contains information about how the directory is partitioned, and this information can be used in conjunction with DNS to find the Active Directory domain that contains a particular object.

Knowledge References

Active Directory stores information about the existence and location of directory partitions in a forest, including the names of the directory partitions and the names of domain controllers that hold replicas of those directory partitions. Active Directory uses this information (known as knowledge references) to generate referrals to other domain controllers.

Active Directory uses three kinds of knowledge references to generate referrals to other domain controllers:

  • A subordinate reference, which is knowledge of a directory partition (or partitions) directly adjacent in the naming hierarchy to a directory partition that is held by the domain controller.
  • A cross-reference, which is knowledge of one directory partition and which is stored in a cross-reference object in the Partitions container. On a specific domain controller, the combination of all cross-references provides knowledge of all directory partitions in the forest, regardless of the locations of those directory partitions in the directory tree.


    • The state of cross-reference knowledge at any specific time is subject to the effects of directory replication latency.
  • A superior reference, which is knowledge of a specifically designated location that is used whenever the domain controller has no knowledge of the search base that is used in a search.

Knowledge references are the glue that holds the pieces of the distributed directory together. Because Active Directory is logically partitioned and directory partitions are the discrete components of the directory that replicate between domain controllers, either all objects in a directory partition are present on a particular domain controller or no objects in the directory partition are present on the domain controller. References have the effect of linking directory partitions together, which enables operations such as searches to span multiple domain directory partitions.

In Active Directory, referrals are generated when a client requests that the directory locate an object where, based on the position at which the search begins, no copy exists in a local directory partition. When Active Directory can determine definitively from the information it holds that no such object exists in the directory — rather than that it might exist somewhere else, even though no copy exists locally — instead of sending a referral, the directory returns an error message to the client that no such object exists in the forest.

For information about replication of directory partitions, see “Active Directory Replication Model Technical Reference.”

Subordinate References

When a client requests a search, the domain controller searches all objects at or below the search base in the directory partition that the domain controller holds. If a subtree search has a search base that includes child partitions, the domain controller uses information that is provided by subordinate references to return referrals (called subordinate referrals) to these partitions on other domain controllers.

Subordinate referrals are returned as part of the data that is returned from the distinguished name of the directory partition that is named in the search base. The referral contains the distinguished name of the subordinate directory partition and the access point to which queries can be referred. An access point consists of a DNS name and a port number, which is the information that is required to contact a specific LDAP server. Access points are generated from information that is contained in the cross-reference object.


Cross-references are stored as directory objects of the class crossRef that identify the existence and location of all directory partitions, irrespective of their location in the directory tree. Cross-reference objects are used to generate referrals to other directory partitions in the forest and to external directories.

Cross-references enable every domain controller to be aware of all directory partitions in a forest, rather than only the directory partitions that a particular domain controller holds. Because cross-reference objects are stored in the Configuration container, they are replicated to every domain controller in the forest.

Cross-reference objects store the following information:

  • nCName. The distinguished name of the directory partition that the crossRef object references. (“nC” stands for “naming context,” which is a synonym for “directory partition.”) The combination of all of the nCName properties in the forest defines the entire directory tree, including the subordinate and superior relationships between directory partitions.
  • dNSRoot. The DNS name of the domain where servers that store the particular directory partition can be reached. This value can also be a DNS host name.

Cross-reference objects are created in two ways:

  • Internally, by the system, to refer to known locations that are within the forest.
  • Externally, by administrators, to refer to locations that are external to the forest.
Internal cross-references

An internal cross-reference is a cross-reference object that is created by the system. For every directory partition in a forest, there is an internal cross-reference object in the Partitions container (cn=Partitions,cn=Configuration,dc=ForestRootDomain). When you create a new forest, the Active Directory Installation Wizard creates the following three directory partitions:

  • First domain directory partition
  • Configuration directory partition
  • Schema directory partition


  • On a domain controller running Windows Server 2003, one or more application directory partitions might be created in addition to the domain, configuration, and schema directory partitions.

For each of these partitions, a cross-reference object is created automatically. Thereafter, when a new domain or application directory partition is created in the forest, another directory partition is created and the respective cross-reference object is created.


  • Whenever you create a new domain or application directory partition, the appropriate cross-reference objects are created automatically.

Because these cross-reference objects are located in the Configuration container, they are replicated to every domain controller in the forest, and therefore every domain controller has knowledge of the name of every partition in the forest (as well as their superior and subordinate relationships to each other). By virtue of this knowledge, any domain controller can generate referrals to any other domain in the forest, as well as to the schema and configuration directory partitions.

External cross-references

An external cross-reference is a cross-reference object that you create manually to provide the location of an object that is not stored in the forest. If your LDAP clients submit operations for an external LDAP namespace against servers in your forest and you want your forest’s servers to always refer these clients to the correct location, you can create a cross-reference object for that directory in the Partitions container.

There are two ways that external cross-references are used:

  • To reference external directories by their disjoint directory name, that is, a name that is not contiguous with the name of the local directory tree. In this case, when you create the cross-reference, you create a reference to a location that is not a child of any object in the local directory.
  • To reference external directories by a name that is within the Active Directory namespace, that is, a name that is contiguous with the name of this directory tree. In this case, when you create the cross-reference, you create a referenceto a location that is a child of an existing directory object.


  • An external directory that is stored on a domain controller running Windows Server 2003 or Windows 2000 Server does not require an explicit cross-reference object. Because the domain component (dc=) portions of the distinguished names of all Windows Server 2003 domains match their DNS addresses and because DNS is the worldwide namespace, all domain controllers running Windows Server 2003 or Windows 2000 Server can generate external referrals to each other automatically, assuming that the appropriate credentials and trust relationships exist.

Creating External Cross-References

The only time that you have to create a cross-reference object is when you want to extend a search to a directory outside the forest that is a non-Windows LDAP directory service. In this case, you can use an LDAP editor such as ADSI Edit to create objects of the class crossRef (in the Partitions container) that reference external directories.

When you create a cross-reference object, you must provide the values for three attributes:


The name that describes the directory. For example, for the domain noam.proseware.com, your cn value might be noam or something else that describes that domain, such as NorthAmerica. This value is for administrative convenience; it has no impact on the system.


The distinguished name of the domain directory partition to which your cross-reference refers. If the domain name is noam.reskit.com, the value of nCName is dc=noam,dc=proseware,dc=com.


The DNS host name of an LDAP server in the domain that is identified by nCName (for example, server1.noam.proseware.com). The value of dnsRoot can also be the domain name if you do not want to specify a server.


  • You must be able to resolve (use the ping command to test) the name in dnsRoot, which does not necessarily name another system running Windows Server 2003; it might be the DNS address of an LDAP server instead of a domain controller. If the directory partition is a Windows Server 2003 domain in another forest, automatically generated knowledge is usually sufficient and no external cross-reference is required.

ADSI Edit, an MMC snap-in and Active Directory administrative tool, provides a convenient GUI for creating cross-reference objects.

To make use of cross-references, clients must be able to follow (“chase”) referrals that are returned. Windows Address Book chases referrals by default. When you are using ADSI programmatically (for example, by using Active Data Objects (ADO) to search), you must specify whether to chase referrals.


  • When you set the LDAP referral chasing option (LDAP_OPT_REFERRALS) to ON, the LDAP client (Wldap32) ensures that plaintext passwords are not sent over the network and that the same level of security that is required of the originating query server is achievable from the referral server. If the referral server does not support the security package that was used to bind to the query server or if the referral server does not support the same level of integrity or privacy as the query server, Wldap32 does not chase the referral.
  • If no bind is performed on the originating query server, or if a simple (plaintext) bind is performed on the originating server without the use of SSL encryption to protect the passwords, the LDAP client performs an anonymous bind to the referral server. The latter behavior protects passwords from being sent inadvertently over the network in plaintext as the result of chasing a referral.
Creating an external cross-reference for an external location

To create a cross-reference to an external directory by referencing an external location, give the nCName attribute a value that is the name of the actual external directory. For example, an external LDAP directory might use X.500 naming (such as o=Organization Name,c=Country/Region), which can be used for the value of the nCName attribute. Queries for this directory must specify the external object by name in the search base distinguished name. A request for a referral to such a location might come in the form of an LDAP URL that is embedded in an e-mail message or from an application that specifically names the directory distinguished name.

Creating an external cross-reference for an internal location

If you want a subtree search of a portion of your directory to always include an external LDAP directory that is not a Windows Server 2003 or Windows 2000 Server directory service, you can create a cross-reference to the external directory for an internal location. To create an internal location that references an external directory, give the nCName attribute of the cross-reference object a value that is an immediate child object of an existing directory object and that also matches the distinguished name of the external directory. Choose the location according to where you want the external directory to be locatable in Active Directory.

This type of cross-reference is especially useful for integrating dynamic directories smoothly. For example, you might use an instant messaging application such as Microsoft NetMeeting conferencing software to publish a list of current or planned conference calls. LDAP is an effective protocol for querying such a published list. However, short-lived, highly volatile data is inappropriate for Active Directory storage. Therefore, you might use an in-memory, nonreplicated LDAP server (one that can store volatile data) at an arbitrary point in the namespace. This “volatile” directory service can then be configured to inhabit a name inside your organization’s Active Directory namespace, and it can be made available to users through a cross-reference for an internal location in Active Directory. For example, users can use this location to find the list of instant messaging conversations by directory tree navigation.


  • On Windows Server 2003 domain controllers, application directory partitions can be used to provide directory storage for dynamic data. For more information about application directory partitions, see “Data Store Technical Reference.”

Suppose your domain name is proseware.com and you install your messaging application on an LDAP server that does not use Active Directory, which is named vds.it.proseware.com. On that server, you create a directory for your volatile data, such as cn=conversations,dc=proseware,dc=com. Then, on your Active Directory domain controller, you create a cross-reference object and use the following attribute values:

When a user performs a subtree search of dc=proseware,dc=com, the client receives results from the domain controllers running Windows 2000 Server or Windows Server 2003 and also a subordinate referral to the volatile directory service server at vdserver.it.proseware.com, which instructs the client to continue the LDAP search from cn=conversations,dc=proseware,dc=com and below on that server.

Superior References

A superior reference is the fully qualified DNS name of a directory partition that is stored in the superiorDNSRoot attribute on the crossRef object for the forest root domain (the first domain that is created in the forest). A domain controller uses its superior reference to construct a referral only when a search base does not match any directory partition that is defined by the cross-reference objects. A superior reference contains no directory tree information; it consists of only an access point to which otherwise unanswerable queries can be referred.

By default, superiorDNSRoot does not store a value, but the directory uses the dc= components of the search base distinguished name to construct the equivalent of a superior referral. You can use the superiorDNSRoot attribute to define a location to which all queries that cannot be resolved are sent.

Optimizing Searches

Because searches against Active Directory require CPU and memory resources, searches should be performed in ways that minimize their performance impact on domain controllers. You can use several techniques to reduce the impact of directory searches on domain controllers running Windows Server 2003.

Extensions to the base LDAP API, in the form of LDAP v3 controls, make it possible to sort results and set various limits on search operations. You can process search results by paging and by sorting. Paging and sorting are supported in Windows Server 2003 as new LDAP v3 control extensions.

Effects of Indexing on Search Behavior

You can improve search behavior by indexing the attributes that are most likely to be searched. The searchFlags attribute of an attributeSchema object indicates whether the attribute is indexed and the nature of the indexing.

The searchFlags attribute is an integer value whose least significant bits indicate whether the attribute is indexed and in what way. Use the OR operator to combine the bit values to achieve the appropriate indexing behavior.

Values in the searchFlags attribute have the following effects:

  • 1 = Index over attribute only. Bit 0 must be set (0001). You can use the Active Directory Schema MMC snap-in to set this flag.
  • 2 = Index the attribute in each container (this value is used in conjunction with 1). Bit 0 and bit 1 must be set (0011). You can use Active Directory Schema to set this flag.
  • 4 = Add this attribute to the ANR set (this value is used in conjunction with 1). Bit 0 and bit 2 must be set (0101).
  • 8 = Preserve this attribute on logical deletion (that is, make this attribute available on tombstones). Bit 3 must be set (1000).
  • 16 = Copy the value for this attribute when the user object is copied. You can use this value to set up a user object template so that you can create multiple users by making copies of an original and providing values for only those attributes that are unique to each user. Bit 4 must be set (10000). For example, set this flag for attributes, such as company and department, that you want to copy, but do not set attributes that must be unique, such as objectSid and sAMAccountName.
  • 32 = Index this attribute for medial-string search (this value is used in conjunction with 1). Bit 5 and bit 0 must be set (100001). This indexing capability is provided on domain controllers running Windows Server 2003 when the schema has been updated for Windows Server 2003 functionality.
Optimizing container searches

An attribute can be indexed for the attribute only or for both the attribute and the containers that are on the same search level. The value of the searchFlags attribute on the attributeSchema object indicates how the attribute is indexed.

One-level searches are confined to the immediate children of the base object of the search. An index on containers, as well as the attribute, optimizes the search where values are expected to be common across containers. For example, suppose you store phone book data for the United States in Active Directory, organized by state and then by region. If you want to search for a Jeff Dulong in northern Idaho, you go to the Northern Idaho container and do a one-level search for (&(givenName=Jeff)(sn=Dulong)). If the givenName or sn attributes are indexed on the attribute only (flag 1 on the searchFlags attribute), the search must examine all the Dulongs in the United States, all the Jeffs in the United States, or all the people in northern Idaho. With the searchFlags value of 2 set (index the container and the attribute), the search examines only the Dulongs or only the Jeffs in northern Idaho, which results in a substantial improvement in the time that the search takes to complete.


  • Active Directory Schema provides an option to index an attribute for container searches.

Ambiguous name resolution (ANR) is the process of searching for a string value in a set of attributes by using one filter of the form (ANR=string).

ANR attribute set

Attributes are designated as members of the ANR attribute set according to the value of the searchFlags attribute on the attributeSchema object that defines the attribute.

By default, the following attributes are members of the ANR attribute set, and they are evaluated when you enter an ANR search string in an LDAP filter:

  • givenName (first name)
  • sn (surname, or last name)
  • displayName (the name that is given to the object when it is created)
  • RDN (the relative distinguished name of the object)
  • legacyExchangeDN (for enterprises that have upgraded a Microsoft Exchange installation to a later version of Exchange that is synchronized with Active Directory, the distinguished name of the old Exchange mailbox that corresponds to the user in Active Directory)
  • physicalDeliveryOfficeName (for example, Building A, Suite 1234)
  • proxyAddresses (the collection of e-mail addresses over all e-mail address spaces that the Exchange server knows about)

When the (ANR=string) filter is encountered by Active Directory, the filter is expanded to include a search of every attribute in the ANR set. For example, an ANR search is implemented when you use the Check Names option in Microsoft Outlook that searches against a Microsoft Exchange mail server. Because physicalDeliveryOfficeName is in the default ANR attribute set, you can type the building number and room number as it appears in the attribute value into the To line of a mail message, click Check Names, and the Address Book responds with the user name of any account that contains that value in the physicalDeliveryOfficeName attribute of a user object.

In Active Directory Users and Computers, you can use the Filter or Find options on the toolbar and select the Custom and Advanced options to enter an ANR filter. You can also use ADSI Edit to perform filtered LDAP searches.

ANR matching of an embedded space

For the givenName and sn attributes, if a space is embedded in the string that is presented in an ANR filter, the string is split at the first such space, and each piece of the string is evaluated separately. You can use this feature to search for a user object by providing the first few characters of the first name (givenName) and the first few characters of the last name (sn). For example, the filter (ANR=mar ha) finds all objects that have a givenName attribute value that begins with “mar” and an sn attribute value that begins with “ha”. In this example, the filter returns a user who has a givenName attribute of Mark and an sn attribute of Hanson, as well as a user who has a givenName attribute of Mark and an sn attribute of Harrington.

First/last and last/first functionality

For the givenName and sn attributes, if a space is embedded in the string that is presented in an ANR filter, the filter is expanded to find the values in both respective positions. For example, the filter (ANR=c d) finds both the user David Campbell and the user Craig Dewer.

Expanded ANR filter

When an ANR filter is encountered by Active Directory in an LDAP search, the filter is expanded to construct an OR operation on the string for every attribute in the ANR set. For the givenName and sn attributes, the first/last and last/first matching are also applied.

The ANR filter of the form (anr= xxxyyy) is expanded in the following manner:

Copy Code

(| (displayName=xxx yyy*) (givenName=xxx yyy*) (physicalDeliveryOfficeName=xxx yyy*) (proxyAddresses=xxx yyy*)... (sn=xxx yyy*) (& (givenName=xxx*)(sn=yyy*)) (& (givenName=yyy*)(sn=xxx*))) 

The last three lines of the expanded filter are the portion of the filter that evaluates first name and last name.

Suppressing first/last and last/first functionality

You can turn off first/last and last/first functionality if you do not need this type of evaluation and you do not want CPU cycles to be used for it. For example, in the filter (ANR=c d), which finds both the user David Campbell and the user Craig Dewer, you can specify that ANR will always find only Craig Dewer, perhaps because names in your database never occur in any order other than first name/last name and no searches are likely to be looking for anything other than first name/last name. Likewise, if names are always represented in last/first format, you can turn off the first/last functionality. If you do not have values that apply to the first names and last names of people, you can disable both first/last and last/first functionality.

The dsHeuristics attribute on the Directory Service object (cn=Directory Service,cn=Windows NT,cn=Services,cn=Configuration,dc=ForestRootDomain) contains a string value that governs the use of first/last and last/first functionality in the first two character positions. The default value of dsHeuristics is 00, which indicates that both functions are enabled. (For all positions, 0 means “perform the default behavior.”) The first character in the string governs first/last functionality; the second character in the string governs last/first functionality.

You can modify the first two characters of the string to suppress either one or both functionalities as follows:

  • 10 = Suppress first/last functionality. (This value can also be written 1 or 10000 because both mean that only the first character’s behavior must be something other than the default.)
  • 01 = Suppress last/first functionality.
  • 11 = Suppress last/first and first/last functionality.
Adding attributes to the ANR set

You can add attributes to the default ANR set by setting a flag on the attributeSchema object. By using ADSI Edit, connect to the schema, and then open the properties on the attribute that you want to add. Set the searchFlags attribute value to a value that represents a bitwise OR operation of 4 and 1 to the existing value. The value 4 adds the attribute to the ANR set; the value 1 indexes the attribute.


  • Limit the number of attributes that you add to the ANR set as much as possible, because adding an attribute to the ANR set affects the performance of any search that is performed against that attribute on any domain controller.
Searching for deleted objects

When an Active Directory object is deleted, it is stored as a tombstone in the Deleted Objects container of the respective directory partition, with the exception of some objects from the configuration partition, which remain in their original location, even after they are deleted. When an object is marked as a tombstone, the attributes are stripped from the object, with the exception of objectGuid, objectSid, distinguishedName, nTSecurityDescriptor, and usnChanged, and any additional attributes that are marked in the schema as “preserve on delete.” For more information about tombstones, see “Active Directory Replication Model Technical Reference.”

Tombstones are stored for a configurable period of time to allow replication of the deletion to occur. All domain directory partitions, as well as the configuration directory partition, have a hidden Deleted Objects container that stores tombstones until they are permanently removed from the directory by garbage collection. By using the Show Deleted Object control (controlType = 1.2.840.113556.1.4.417) in conjunction with search commands, you can view Active Directory objects that have been deleted but not yet garbage collected.

To retrieve tombstone objects, use Ldp.exe to list the contents of the Deleted Objects container for a directory partition.

Medial-string searches

In Windows 2000 Active Directory, efficient substring searches are supported for query filters with initial strings (for example, cn=abc*). However, medial-string searches (for example, cn=*def*) and final-string searches (for example, cn=*ghi), although supported, are slow as a result of the lack of appropriate indexing. Active Directory in Windows Server 2003 provides support for selectively indexing attributes that have DirectoryString syntax for efficient medial-string and final-string searching. For example, if you index the surname (sn) attribute for medial-string searching, you can find all users named McLaughlin, MacLaughlin, and McLaughlan by using the search string cn=*claughl*. You can use the searchFlags attribute with a value of 33 (1 AND 32) to implement both attribute-level and medial-string indexing.


  • The searchFlags value of 32 makes only medial-string searching efficient. To ensure efficiency for initial-string searches as well, use the value 33.

This new type of indexing, called Tuple indexing, is available only on domain controllers running Windows Server 2003, and it is available at any forest functional level. With Tuple indexing, you can see improved performance of medial-string searches on strings that are at least 3 characters in length. For example, assuming that the attribute cn has been indexed for medial-string search, the performance of searches by filters such as cn=*mic* or cn=*mich* is substantially faster than searches that are run without indexing for medial-string search. However, searches on medial strings that have a shorter length, such as cn=*m* or cn=*mi*, might not see any improvement in performance compared to searches that are not indexed for medial search.

Database indexes are generated separately on each domain controller. Therefore, Tuple indexing only affects domain controllers running Windows Server 2003, and it does not affect any Windows 2000 Server–based domain controllers that are present in the domain or forest. Because searches of the type cn=*def* are possible on Windows 2000 Server–based domain controllers, there are no backward compatibility issues with Tuple indexing and Windows 2000 Server domain controllers. You can perform medial-string searches on both domain controllers running Windows 2000 Server (without the benefit of Tuple indexing) and domain controllers running Windows Server 2003 (with the benefit of Tuple indexing).

Performance considerations

Tuple indexing is a resource-intensive operation for the Active Directory database, which means that updating an attribute that has Tuple indexing applied takes longer than normal. For this reason, by default, no attributes are indexed for this type of search in the Windows Server 2003 schema.


  • Only attributes that are often used to perform medial-string searches should be marked as indexed for medial-string search. Unnecessary indexing, especially of this type, can cause update performance to decrease.
Deleted objects exception to medial-string search

Because Tuple indexes can become quite large, values of Tuple-indexed attributes on deleted objects (called tombstones) are not included in the index. Therefore, if the special LDAP control to show deleted objects is specified in the search operation, the search cannot use Tuple indexes to speed up the search.

Indexing an attribute for medial-string search

You can use ADSI Edit to mark an attribute for Tuple indexing. To use ADSI Edit, you must have Windows Support Tools installed.

The process for marking an attribute for Tuple indexing involves changing the value of the searchFlags attribute on the corresponding attributeSchema object that defines the attribute that you want to index.

Efficient listing of large search results in Windows Server 2003

New LDAP v3 controls are introduced in Windows Server 2003 that improve the ability of applications to display large lists of search results. Two new controls extend the LDAP protocol to provide a scalable solution for managing large directory deployments by improving the paging and sorting of search lists, as follows:

  • Virtual list view (VLV). Allows only the viewed portion of the list to be required in memory.
  • Attribute scoped query (ASQ). Applies VLV functionality to the listing of search results on large, multivalue attributes.

These two controls enable a client to browse large lists of objects without a negative impact to the client. VLV and ASQ lower network traffic and ease the client’s burden of holding a large set of unneeded data in memory.

VLV and ASQ can also be used to extend other applications that retrieve information from Active Directory. For more information about programming applications that implement VLV and ASQ, see “Extended Controls” in the Microsoft Platform SDK on MSDN.


A virtual list is a GUI technique that is employed when ordered lists containing a large number of entries need to be displayed. When the LDAP protocol is extended to use VLV, a window that contains a small number of visible list entries is drawn. The visible portion of the list can be relocated to different points in the list by means of scrolling, slider bars, and cursor keys as well as PAGE UP and PAGE DOWN keys. The user experience is that the full list can be browsed at will, even though it might contain millions of entries. In fact, the complete list contents are never required at any one time. Rather than retrieve the complete list from wherever it is stored (typically, from disk or a remote server), the server retrieves only the information that is required to display the part of the list that is currently in view on the client.

When you have indexed appropriate attributes to use VLV, you can use Ldp (or other VLV-enabled applications) to retrieve large lists from Active Directory without requiring the server to return the entire contents of the results set (improving response speed) and without requiring the search client to store the results set in memory (improving the speed at which results are listed).

Configuring VLV

For the directory service to efficiently browse a container that is sorted on a particular attribute, special indexes have to exist in the directory. These indexes are available in all the languages that are installed on the particular server.

You can define the views that the directory supports by modifying the attributeSchema object for the particular attribute on which you want to search. More specifically, you can modify the searchFlags attribute on the attributeSchema object to set it for VLV indexing.

To index an attribute for VLV, set the searchFlags value as follows:

current value OR 2

For example, if you want to add support for VLV container browsing using the name attribute, modify the attributeSchema object cn=RDN,cn=Schema,cn=Configuration,dc=DomainName.

The default value of searchFlags for this object is 13 (1101); therefore, in this case it becomes 15 (1111). If the attribute has a different value, simply perform an OR operation on that value with 2 (0010).

Active Directory does not implement any specific restrictions on the use of the VLV control. However, if a search operation cannot be processed by the server before the time-out (to build the required table that is specified by the search filter and sort key), the server returns a time-out.


The ASQ LDAP control, which is new in Windows Server 2003, makes it possible to apply the query scope to a linked-value attribute instead of to a container. In this way, ASQ extends the VLV feature to apply to large, multivalue attributes with distinguished name values (the type of attributes that can be linked).

With ASQ, the VLV control can be run on an attribute with distinguished name syntax to:

  • Receive a sorted list of values in a multivalue attribute that has a large number of distinguished name values, such as the member attribute on a group object.
  • Perform a nested query on a multivalue attribute that has a large number of distinguished name values and return the values in a single operation.

For example, if an ASQ search is performed on the member attribute of a group object, ADSI enumerates the distinguished names in the member attribute and searches each of the members of the group for the specified search criteria.

LDAP Query Policy

LDAP v3 supports the definition of client query policy. By default, limits are placed on the server resources that are available to clients requesting LDAP queries, paged result sets, and sorted result sets. These limits constitute the LDAP query policy.

The query policy is stored as a multivalue attribute (lDAPAdminLimits) of the Default Query Policy object in the configuration directory partition (cn=Default Query Policy,cn=Query-Policies,cn=Directory Service,cn=Windows NT,cn=Services,cn=Configuration,dc=Forest RootDomain).


  • LDAP query policy is not related to, and is not a subset of, Group Policy.

Because the workload and resources of a given server can vary, the LDAP query policy is configurable at the server level.

LDAP query policy applies to the following LDAP query–related operations:

  • Search. The basic query operation. An LDAP search might cover a small part of a single domain, or it might span every directory partition in the forest. A search can generate a significant amount of disk activity, take a long time, and return a large volume of data.
  • Search with Paged Results. Because a search can return a large volume of data, the client can ask the server to hold the result set and return it in “pages” of a specified length. The server must hold the result set until the client releases it or unbinds.
  • Search with Sorted Results. A client can request a result set in a particular order. Sorting requires storage and CPU cycles at the server. The resources consumed are directly proportional to the size of the result set.
  • Search with Replication. The administrator can specify the maximum number of attribute values that can be returned per request.
  • Change Notify. A client can request change notification on particular objects in the directory. The mechanism that is used to post a Change Notify request is the asynchronous LDAP query.

In the absence of any other assigned policy, all domain controllers use the default query policy. If a site policy is assigned, the domain controller uses the site policy. If a specific policy has been assigned to a domain controller, this policy takes precedence over any site policy.

Administrative query policies: attribute values

The following table shows the administrative limits for default query policy.

Default Values for LDAP Administrative Limits

LDAP Administrative Limits Default Value Description and Search Behavior
MaxConnIdleTime 900 Maximum Connection Idle Time. The maximum time (in seconds) that the client is allowed to be idle before the connection is closed.
MaxActiveQueries 20 Maximum Active Queries. The maximum number of concurrent search operations allowed on the server. When the stated limit is reached, the LDAP server returns a busy notification.
MaxNotificationPerConn 5 Maximum Notifications per Connection. The maximum number of concurrent notification requests allowed per connection on the server. When the stated limit is reached, the server returns a busy notification.
MaxPageSize 1000 Maximum Page Size. The largest page size allowed by the server (in number of rows). The server returns the number of rows that are specified by MaxPageSize. If paged results are requested, the client can retrieve additional pages until all results are returned.
MaxQueryDuration 120 Maximum Query Duration. The maximum elapsed time (in seconds) that is allowed for a query to complete. If paged results are requested, the client can continue the query if the timer expires before the query completes. When the stated limit is reached, the server returns the timeLimitExceeded error.
MaxReceiveBuffer 10485760 Maximum Receive Buffer. The maximum LDAP request size (in bytes) that the server attempts to process. If the server receives a request that is larger than this value, it closes the connection.
MaxTempTableSize 10000 Maximum Temporary Table Size. The upper limit (in candidate objects) on the temporary table. If the temporary table maximum limit is reached by an “OR” query optimization, the optimization is abandoned and replaced with a direct table scan.
MaxResultSetSize 262144 Maximum Result Set Storage. The maximum storage (in kilobytes (KB)) that the server can hold for all paged result sets. If the stated limit is reached, the oldest result sets are discarded.
MaxPoolThreads 4 Per Processor Asynchronous Thread Queue (ATQ) Threads. The number of threads that are allocated by ATQ per processor. This value is sent as an advisory notification to ATQ. ATQ decides whether to use it or not.

Note If it takes a long time to bind, increase the count to 6 or 8.

MaxDatagramRecv 1024 Maximum Receive Datagram Size. The maximum size of datagrams (in bytes) that can be received by the server. The server preallocates datagram buffers and cannot receive datagrams with a size that is larger than the stated limit.
InitRecvTimeout 120 The maximum time (in seconds) that the server waits for the initial request before the connection is dropped.
MaxConnections 5000 The maximum number of concurrent LDAP connections allowed on the server. User Datagram Protocol (UDP) connections do not count toward this limit. If the limit is reached, the LDAP server sends back an LDAP disconnect notification and closes down the connection.
MaxValRange 1500 Maximum Value Range. Controls the threshold at which the server will start returning the range option for attributes with a large number of values. The minimum value for this policy is 30.

Query Limits

To improve the query response time for searches for Active Directory objects, searches are limited to 1,000 objects by default. However, you may want to increase this limit as your organization grows. You can control the buffer size that is allocated for storing the number of objects that are returned by a query search. To control the buffer size, you can either modify the registry on the search client or use Group Policy to set the buffer size on all computers in a domain, site, or OU.

Modifying the registry to change the maximum query limit

You can increase the number of objects that are returned by an Active Directory search on an individual search client by setting the limit in the registry. The REG_DWORD value named QueryLimit on the registry key HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\Directory controls the maximum query limit on the local computer.

Using Group Policy to change the maximum query limit

You can use Group Policy to increase the maximum query limit on objects that are returned in response to a command to browse or search Active Directory when the command is issued from an operating system in the Windows 2000 Server family or the Windows Server 2003 family. In the User Configuration section of Group Policy, the setting is found in \Administrative Templates\Desktop\Active Directory\Maximum size of Active Directory searches. You can edit this setting with Group Policy Management Console (GPMC).


  • Because this query limit policy is a user-based policy, it is not enforced until the user has logged off the system and then logged on again. Also, the policy only applies to default Active Directory tools, such as Active Directory Users and Computers. Any query limits that are set through Group Policy do not apply to LDAP queries that are performed programmatically.


When an LDAP client is accessing a server across a slow connection or if the result set from a given query may be very large, the client can retrieve a result set in small pieces. The Simple Paged Result extended control provides for this type of retrieval. Options for this control enable the client to set the initial page size and reset the page size with each subsequent request to the server.

The Simple Paged Result control is also used to access all of a large results set when there is a server-side administrative limit to the number of items that are returned from a query. For example, domain controllers running Active Directory have a default server-side limit of 1,000 entries as the maximum number of results that are returned in a single request. If the results of a query exceed this limit, the Paged Results control is used, with a page size equal to or less than the server-side limit, to retrieve all of the results of the query.

For more information about paging, see “Paging Search Results” in the Microsoft Platform SDK on MSDN.

Multivalue Attributes

Attributes can be single value or multivalue. Single-value and multivalue attributes are defined by the singleValued attribute being set to TRUE or FALSE. A multivalue attribute can contain multiple values, all of uniform syntax. Note that multivalue attributes hold a set of values with no particular order. There is no guarantee that multivalue properties are ever going to be returned in the order in which they were stored (or in any other order).

Retrieving the contents of a multivalue attribute, such as a distribution list, can often result in a large number of returned values. LDAP servers often place limits on the maximum number of attribute values that can be retrieved in a single query. If an attribute has more members than can be returned by the server in a single call, the only way to enumerate all of the attribute values is through the use of the range option.

Range retrieval involves requesting a limited number of attribute values in a single query. The number of values that are requested must be less than, or equal to, the maximum number of values that are supported by the server. To reduce the number of times that the query must contact the server, the number of requested values should be as close to this maximum as possible.

Active Directory servers set a limit on the maximum number of attribute values that are returned. The version of the operating system for the server that supplies the requested data determines the maximum number of values that can be retrieved in a single query. The following table lists the operating system version and the maximum number of values that can be retrieved in a single query.

Maximum Query Size for Multivalue Attribute Searches

Operating system version Maximum values returned
Domain controllers running Windows 2000 Server 1,000
Domain controllers running Windows Server 2003 1,500


  • In the Windows Server 2003 family, a server running Windows Server 2003, Web Edition cannot be a domain controller.
Attribute range option

The range option can be specified as part of an LDAP search to retrieve the values of a multivalue attribute incrementally. An LDAP search on an attribute includes an attribute type (for example, member) and a list of options, one of which can be the range option. When it is presented in a searchRequest message, the range option specifies a zero-relative range of elements (for example, 0 through 9) to be retrieved. When the range option is specified, followed by a range specifier, only the number of values in that range is retrieved. For more information about the range option, see “Searching Using Range Retrieval” in the Microsoft Platform SDK on MSDN.


  • You can use the range option in multivalue attribute searches by using Ldp.exe.
Linked-value attributes

Linked-value attributes are a new feature in Windows Server 2003. Linked-value attributes are pairs of attributes in which the system calculates the values of one attribute (the back link) based on the values that are set on the other attribute (the forward link) throughout the forest. A back-link value on any object instance consists of the distinguished names of all the object’s that have the object’s distinguished name set in the corresponding forward link. A back link is always a multivalue attribute. A forward link can be a multivalue attribute or a single-value attribute.

For example, Manager and Reports are a pair of linked-value attributes, where Manager is the forward link and Reports is the back link. For example, suppose that Bill is Joe’s manager. If you store the distinguished name of Bill’s user object in the Manager attribute of Joe’s user object, the distinguished name of Joe’s user object shows up in the Reports attribute of Bill’s user object.

A forward-link/back-link pair is identified by the linkID values of two attributeSchema definitions. The linkID of the forward link is an even, positive, nonzero value, and the linkID of the associated back link is the forward linkID plus one. For example, the linkID for Manager is 42, and the linkID for Reports is 43.

The following is a list of guidelines for defining a new pair of linked-value attributes:

  • The linkID values must be unique among all attributeSchema objects. To avoid conflicts, you can obtain values for linkID attributes from the Link ID Generator on MSDN.
  • A back link must have a corresponding forward link; that is, the forward link must exist before a corresponding back-link attribute can be created.
  • The attributeSchema value of a forward link must be,, or These values correspond to syntaxes that contain a distinguished name, such as the Object(DS-DN) syntax.
  • The attributeSchema value of a back link must be, which is the Object(DS-DN) syntax.
  • By convention, back-link attributes are added to the mayContain value of the top abstract class. This enables the back-link attribute to be read from objects of any class, because they are not actually stored with the object but calculated based on the forward-link values.

For information about the replication of linked-value attributes, see “How the Active Directory Replication Model Works.”

Global Catalog Searches

The global catalog enables searches for Active Directory objects in any domain in the forest, without the need for subordinate referrals. Users can find an object of interest quickly without having to know which domain holds the object.

Global catalog servers

A global catalog server is a domain controller that stores extra information. The database on the global catalog server stores information about every object in the forest, instead of information for the objects in only one domain. The information about objects that occur in directory partitions for domains other than the local domain includes only a subset of attributes for each object. In this way, the global catalog enables forest-wide searches without requiring replication of the entire contents of Active Directory to every domain controller. The Knowledge Consistency Checker (KCC) process creates a replication topology that ensures delivery of the partial contents of every directory partition to every global catalog server in the forest.


  • A global catalog server stores full copies of the schema and configuration directory partitions, which is the same as for any domain controller.

By default, the server on which you install Active Directory to create the first domain in a new forest is a global catalog server. Thereafter, you must designate additional global catalog servers if you need them.

Searching the domain vs. searching the global catalog

The decision whether to search the domain or the global catalog is based on the scope of the search:

  • When the scope of a search is the domain or an OU, the query can be resolved in the domain directory partition by using an LDAP search.
  • When the scope of a search is the forest and the attributes that are being searched against are part of the global catalog, the query can be resolved in any directory partition by using a global catalog search.
Searches that use the global catalog by default

To search the global catalog, instead of the local domain partition, you must specify port 3268 in the search tool that you are using, instead of port 389, the standard LDAP port. Anytime that you specify port 3268, you are searching in the global catalog. In addition, the global catalog is searched by default under the following conditions:

  • During the logon process, when a user principal name (UPN) is presented. The global catalog is searched to find the domain and account name on the basis of the UPN.
  • During the logon process, to expand universal groups. Universal group membership can span domains. It is possible, therefore, that a user has a membership in a universal group that is not in the logon domain. For this reason, the global catalog is contacted to search the membership of universal groups. If a membership is found, the group is attached to the user’s logon credentials.
  • When you select Entire Directory in a search-scope list in an Active Directory tool, such as Active Directory Users and Computers.
  • When you write the distinguished name value for a property, where the distinguished name represents a nonlocal object. For example, if the member that you are adding is from a different domain, the global catalog is used to verify that the user object that is represented by the distinguished name actually exists.
Global catalog search base

For an LDAP search, you must supply a valid search base. For a global catalog search, the search base can be any value, including the value NULL (). A search base of NULL effectively scopes the search on the search computer to the global catalog. If you use a NULL search base with a scope of one level or subtree and specify port 389 (the default LDAP port), the search fails. Therefore, if you submit a NULL search to the global catalog port and then change the port to the LDAP port, you must change the search base for the search to succeed.

Characteristics of a global catalog search

The following additional characteristics differentiate a global catalog search from a standard LDAP search:

  • A global catalog search crosses directory partition boundaries. The extent of an LDAP search is the directory partition.
  • A global catalog search does not return subordinate referrals. If you use port 3268 to request an attribute that is not in the global catalog, you do not receive a referral to it. Subordinate referrals are an LDAP response. When you query a server over port 3268, you receive global catalog responses, which are based solely on the contents of the global catalog. If you query the same server over port 389, you receive referrals for objects that are in the forest but whose attributes are not referenced in the global catalog.


  • An external referral can be returned by the global catalog if a base-level search for an external directory is submitted and if the distinguished name of the external directory uses the domain component (dc=) naming attribute. This referral is returned according to the ability of Active Directory to construct a DNS name from the domain components of the distinguished name, and it is not based on the presence of any cross-reference object. The same referral is returned by using the LDAP port; it is not specific to the global catalog. For more information about constructing a DNS name from the domain components, see “Superior References” earlier in this section.

When a forest consists of a single domain, there is no need for a global catalog because every domain controller has a full, writable copy of every object in the domain and forest. However, it is important to retain the global catalog on at least one domain controller because many applications use port 3268 for searching. For example, if you do not have any global catalog servers, the Search command on the Start menu of Windows 2000 Professional, Windows 2000 Server, Windows XP Professional, and Windows Server 2003 cannot locate objects in Active Directory.

Searching on back links

Some Active Directory attributes cannot be located specifically in the directory database. A back link is an attribute that can be computed only by referencing another attribute, called a forward link. An example of a back-link attribute is the memberOf attribute on a user object, which relies on the group attribute member to derive its values. For example, if you request the groups of which a specific user is a member, the forward link member — an attribute of the group object — is searched to find values that match the user name that you specify.

When you request the value of a back link on a particular object (for example, “What objects are managed by UserB?”), the system searches for all objects whose corresponding forward link names the original object (that is, " What objects have the distinguished name of UserB as the value in their managedBy attribute?"). The results of that search, and therefore the apparent contents of the back-link attribute, depend on the LDAP port to which the client is bound. That is, the results can differ, depending on whether the client binds to the local domain (LDAP port 389) or to the global catalog (LDAP port 3268).

Effect of the global catalog on searches of back links and forward links

Because of the way that groups are enumerated by a global catalog server, the results of a back-link search can vary, depending on whether you search the global catalog (port 3268) or the domain (port 389), the kind of groups that the user belongs to (global groups or domain local groups), and whether the user belongs to universal groups outside the local domain.


  • Universal groups are available only in domains where domain controllers are operating in Windows 2000 native mode (in a Windows 2000 domain), in domains that have a Windows 2000 native domain functional level (in a Windows Server 2003 domain), or in forests that have a Windows Server 2003 forest functional level.

Domain controllers store a full replica of the domain global groups, domain local groups, and any universal groups that are created in that domain. Therefore, if a query occurs over port 389, the global group and domain local group memberships for users in the local domain can be found, as well as memberships in any universal groups that are stored in that domain.

Global catalog servers store a partial replica of every group in the forest. The member attribute of a group is replicated to the global catalog for universal group objects but not for global groups or domain local groups. Therefore, if a query occurs over port 3268 and the global catalog server that is contacted is authoritative for the user’s domain, that user’s domain local memberships and global group memberships can be enumerated because full replicas of those objects exist on the server. Otherwise, only the user’s universal group memberships are available.

Connecting to the global catalog always locates the user’s membership in universal groups. However, connecting to the global catalog does not locate the users membership in global groups or domain local groups, unless the global catalog server happens to be an authoritative domain controller for the user’s domain.

Network Ports Used by Active Directory Searches

The network ports that are used by Active Directory searches are listed in the following table.

Port Assignments for Active Directory Searches

Service Name UDP TCP
LDAP None 389
LDAP SSL None 636
Global Catalog LDAP None 3268
Global Catalog LDAP SSL None 3269

Related Information

The following resources contain additional information that is relevant to this section:



LDAP: How to retrieve 100,000 records from Active directory using LDAP

How to retrieve 100,000 records from Active directory using LDAP


I want to retrieve nearly 100,000 records from Active directory. But currently I am able to retrieve only 1000 records per search. After 1000th record, it gives LDAP error 4 Maximum Limit Exceeded error….. Can any one throw some light on this issue….. with some working codes


The following quote from MSDN. It may give you some help

The SizeLimit and PageSize properties both affect the number of items that are returned by a search. The SizeLimit property sets the maximum number of items that will be returned by a search, but there may be other search result limitations imposed by the underlying directory service. For example, Active Directory limits the maximum number of search results to 1000. In this case, setting the SizeLimit property to a value greater than 1000 has no effect.

The PageSize property sets the maximum number of items in each page of results that will be returned by a search. The page size is also affected by the underlying directory service. With Active Directory, the largest page size is 1000. Any value over 1000 will be ignored. If PageSize is set to its default value (zero), no paging will occur and the maximum number of items returned by the search will be the lesser of SizeLimit and 1000.

To retrieve a set of results that is larger than 1000 items, you must set SizeLimit to its default value (zero) and set PageSize to a value that is less than or equal to 1000. For example, if a search will result in 12,000 items being returned and SizeLimit is set to 500, a total of 500 items will be returned. If, however, SizeLimit is set to zero and PageSize is set to 500, the search will return all 12,000 results in pages of 500 items, with the last page containing only 200 items. The paging occurs transparently to the application and the application does not have to perform any special processing other than setting the PageSize property to the proper value.



C#: Load a COM dll at runtime?


7down voteaccepted When the .NET assembly resolver is unable to find a referenced assembly at runtime (in this case, it cannot find the particular wrapper DLL version the application was linked against), its default behavior is to fail and essentially crash the application. However, this behavior can be overridden by hooking the AppDomain.AssemblyResolve event. This event is fired whenever a referenced assembly cannot be found, and it gives you the opportunity to substitute another assembly in place of the missing one (provided that they are compatible). So, for instance, you could substitute an older version of the wrapper DLL that you load yourself.

The best way I’ve found to do this is to add a static constructor on the main class of the application that hooks the event, e.g.:

using System.Reflection;

static Program()


AppDomain.CurrentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs e)


AssemblyName requestedName = new AssemblyName(e.Name);

if (requestedName.Name == "Office11Wrapper")


// Put code here to load whatever version of the assembly you actually have

return Assembly.LoadFile("Office11Wrapper.DLL");




return null;




By putting this in a static constructor of the main application class, it is guaranteed to run before any code attempts to access anything in the wrapper DLL, ensuring that the hook is in place ahead of time.

You can also use policy files to do version redirection, but that tends to be more complex.

Other references


C#: Improving Application Startup Time


One of the ways to improve application startup time is to prevent application connecting to the network several times to download current certificate revocation list and verifying the signed assemblies. To prevent use: “<generatePublisherEvidence enabled="false"/>” in your application config file.

Optimize Authenticode

Authenticode verification adds to the startup time. Authenticode-signed assemblies have to be verified with the certification authority (CA). This verification can be time consuming, because it can require connecting to the network several times to download current certificate revocation lists. It also makes sure that there is a full chain of valid certificates on the path to a trusted root. This can translate to several seconds of delay while the assembly is being loaded.

Consider installing the CA certificate on the client computer, or avoid using Authenticode when it is possible. If you know that your application does not need the publisher evidence, you do not have to pay the cost of signature verification.

Starting in .NET Framework 3.5, there is a configuration option that allows the Authenticode verification to be bypassed. To do this, add the following setting to the app.exe.config file:





<generatePublisherEvidence enabled="false"/>



Other references:

http://msdn.microsoft.com/en-us/library/bb629393.aspx //GeneratePublisherEvidence element.