Polling for Changes Using the DirSync Control
The directory synchronization (DirSync) control is an LDAP server extension that enables an application to search an Active Directory™ partition for objects that have changed since a previous state.
Note that the DirSync caller must have the SE_SYNC_AGENT_NAME privilege, which enables the caller to read all objects and attributes in Active Directory, regardless of the access protections on the objects and attributes. By default, this privilege is assigned to the Administrator and LocalSystem accounts on domain controllers. If your application needs to run under an account that does not have this privilege, use the change-tracking technique described in Polling for Changes Using USNChanged. For more information about privileges, see Privileges.
You can use the DirSync control through ADSI by specifying the ADS_SEARCHPREF_DIRSYNC search preference when using IDirectorySearch. For sample code, see Example Code Using ADS_SEARCHPREF_DIRSYNC. You can also perform a DirSync search using the LDAP API. The following discussion describes the ADSI implementation, most of which also applies to using LDAP directly, except as noted at the end of this topic.
When you perform a DirSync search, you pass in a provider-specific blob of data (a cookie) that identifies the directory's state at the time of the previous DirSync search. For the first search, you pass in a NULL cookie, and the search returns all objects that match the filter. The search also returns a valid cookie. Store the cookie in the same storage that you are synchronizing with Active Directory. On subsequent searches, retrieve the cookie from storage and pass it with the search request. The search results now include only the objects and attributes that have changed since the previous state identified by the cookie. The search also returns a new cookie to store for the next search.
The client's search request also specifies the following search parameters:
- Base of the search
- The base of a DirSync search must be the root of a directory partition, which can be a domain partition, the configuration partition, or the schema partition.
- Scope
- The scope of a DirSync search must be ADS_SCOPE_SUBTREE, that is, the entire subtree of the partition. Note that for a search of a domain partition, the subtree includes the heads (but not the contents) of the configuration and schema partitions. To poll for changes in a smaller scope, use the USNChanged technique instead of DirSync.
- Filter
- You can specify any valid search filter. For an initial search with a NULL cookie, the results include all objects that match the filter. For subsequent searches with a valid cookie, the search results include information only for objects that match the filter and have changed since the state indicated by the cookie. For information on search filters, see Creating a Query Filter.
- Attributes
- You can specify a list of attributes to be returned when a change occurs. For each object, the initial results include all the requested attributes that are set on the object. Subsequent search results include only the specified attributes that have changed. Attributes that have not changed are not included in the search results. In the ADSI implementation, the search results automatically include the ADsPath binding string and objectGUID of each object. Also, the specified attributes act as an additional filter; the initial search results include only objects that have at least one of the specified attributes set.
A few additional details:
- For incremental searches, the best practice is to bind to the same domain controller used in the previous search, that is, the DC that generated the cookie. If the same DC is not available, either wait until it is or bind to a new DC and perform a full synchronization. Store the DNS name of the DC in the secondary storage along with the cookie.
You can pass a cookie generated by one DC to a different DC hosting a replica of the same directory partition. There is no chance that a client will miss out on changes by using a cookie from one DC on another DC. However, it is possible that the search results from the new DC may include changes that were already reported by the old DC; and in some cases, the new DC may return all objects and attributes, as with a full synchronization. The client should just make its database consistent with whatever search results are reported on any given DirSync call, that is, treat all incremental results as if they were the latest state. It doesn't matter whether you've seen the change before or are even going back to a previous state because repeated incremental synchronizations will converge on consistency.
- When an object is renamed or moved, its descendants (if any) are NOT included in the search results, even though the distinguished names of the descendants have changed. Similarly, when an inheritable ACE is modified in an object's security-descriptor, the descendants of the object are NOT included in the search results, even though the security-descriptors of the descendants have changed.
- Use the objectGUID attribute to identify the objects being tracked. Each object's objectGUID remains unchanged regardless of where the object is moved within the forest.
- The results of an incremental search automatically include deleted objects. If an object is deleted, the object's isDeleted attribute is set to TRUE. For more information, see Retrieving Deleted Objects.
- Note that the search results of a DirSync search indicate the state of the objects on a replica of the directory partition at the time of the search. This means that changes made on other domain controllers (DC) will not be included if they have not been replicated to the target DC. It also means that an object's attributes may have changed several times since the previous DirSync search, but the search will show only the final state, not the sequence of changes.
- In the ADSI implementation, the application must treat the cookie as opaque and not make any assumptions about its internal organization or value.
- Note that the client stores the cookie, cookie length, and DNS name of the DC in the same storage that contains the synchronized object data. This ensures that the cookie and other parameters remain in sync with the object data if the storage is ever restored from a backup.
LDAP Implementation of the DirSync Control
You can also perform a DirSync search by specifying the LDAP_SERVER_DIRSYNC_OID control with one of the LDAP search functions, such as ldap_search_ext. If you use the LDAP API, be sure to also specify the LDAP_SERVER_EXTENDED_DN_OID and LDAP_SERVER_SHOW_DELETED_OID controls. The EXTENDED_DN control causes an LDAP search to return an extended form of the distinguished name that includes the objectGUID (and objectSID for security principal objects such as users, groups, and computers.) The SHOW_DELETED control causes the search results to include information for deleted objects. Note that these controls are automatically included in the ADSI implementation.