Platform SDK: Active Directory, ADSI, and Directory Services

Enumerating Users

Unlike Windows NT® 4.0 domains, Windows® 2000 users can be placed in any container or organizational unit in a domain as well as the root of the domain. This means that users can be in numerous locations in the directory hierarchy. Therefore, you have two choices for enumerating users:

  1. Enumerate the users directly contained in a container, OU, or at the root of the domain.

    Explicitly bind to the container object containing the users you are interested in enumerating, set a filter containing "user" as the class using the IADsContainer::put_Filter method, and use the IADsContainer::get__NewEnum method to enumerate the user objects.

    This technique is useful if you want to enumerate users that are directly contained in a container or OU object. If the container contains other containers that can potentially contain other users, you need to bind to those containers and recursively enumerate the users on those containers. If you do not need to manipulate the user objects and only need to read specific properties, you should use the deep search described in option 2.

    Because enumeration returns pointers to ADSI COM objects representing each user object, you can call QueryInterface to get IADs, IADsUser, and IADsPropertyList interface pointers to the user object. This means you can get interface pointers to each enumerated user object in a container without having to explicitly bind to each user object. If you wanted to perform operations on all the users directly within a container, enumeration saves you from having to bind to each user in order to call IADs or IADsUser methods. If you only want to retrieve specific properties from users, use IDirectorySearch as described in option 2.

  2. Perform a deep search for (&(objectClass=user)(objectCategory=person)) to find all users in a tree.

    First, bind to the container object where you want to begin the search. For example, if you wanted to find all users in a domain, you would bind to root of the domain; if you wanted to find all users in the forest, you would bind to the global catalog and search from the root of the GC.

    Then use IDirectorySearch to query using a search filter containing (&(objectClass=user)(objectCategory=person)) and search preference of ADS_SCOPE_SUBTREE.

    You can perform a search with a search preference of ADS_SCOPE_ONELEVEL to limit the search to the direct contents of the container object that you bound to.

    IDirectorySearch retrieves only the values of specific properties from users. If you only want to retrieve values, use IDirectorySearch. If you want to manipulate the user objects returned from a search (that is, you want to use IADs or IADsUser methods), you must explicitly bind to them (to do this, specify distinguishedName as one of the properties to return from the search and use the returned distinguished names to bind to each user returned in the search).

    Only specific properties are retrieved. You cannot retrieve all attributes without explicitly specifying every possible attribute of the user class.