1.3.2 Sequencing Issues
The sequencing issues in this RPC protocol are as follows:
For server and client initialization, see section 3.6.
The drsuapi RPC interface is a "context handle"–based RPC interface; [C706] specifies what this means. A client obtains a DRS_HANDLE for a particular DC by calling IDL_DRSBind, then calls any other drsuapi method on that DC, passing the DRS_HANDLE as the first parameter. The client's DRS_HANDLE remains valid for making method calls until the client calls IDL_DRSUnbind, or until the server unilaterally invalidates the DRS_HANDLE (for example, by crashing).
The only state associated with a DRS_HANDLE is the state established by IDL_DRSBind. This state is immutable for as long as the DRS_HANDLE remains valid. Therefore, if a client creates two binding handles to the same DC by using the same parameters to IDL_DRSBind, the server behavior of a drsuapi method is not affected by the client's choice of binding handle passed to the method.
Because the state associated with a DRS_HANDLE is immutable so long as the DRS_HANDLE remains valid, there are no special considerations involved in making concurrent method calls using the same DRS_HANDLE; the client is free to make concurrent method calls.
Two methods use the "cookie" design pattern. In this pattern, the client sends an initial request containing a designated null value for a certain parameter. The server response contains a value that is opaque to the client or contains the designated null value. If the value is not null, and the response indicates that another client request is required to complete some higher-level operation, the client sends the opaque value returned by the server in the next request rather than sending the designated null value. The exchange of requests and responses continues until some response indicates that the higher-level operation is complete.
The two methods that follow this pattern are:
IDL_DRSGetNCChanges: In this instance of the "cookie" pattern, the server returns a "cookie" in the response that completes the higher-level operation. The client can use this cookie at the start of the next higher-level operation. The higher-level operation is a complete replication cycle that improves the client's up-to-date vector. See section 4.1.10.1 for an explanation of replication cycles.
IDL_DRSGetNT4ChangeLog: In this instance of the "cookie" pattern, the server returns a "cookie" in the response that completes the higher-level operation. The client does not use this cookie at the start of the next higher-level operation. The client supplies the designated null value at the start of the next higher-level operation. The higher-level operation is the retrieval of a complete Windows NT 4.0 operating system change log. See the informative summary of this method in section 4.1.11.3.
Successfully processing an IDL_DSAPrepareScript request generates a password and stores that password locally on the server. The server returns this password in the IDL_DSAPrepareScript response. When a server is in this state (that is, when it holds the password created by IDL_DSAPrepareScript), it processes an IDL_DSAExecuteScript request that includes this password; otherwise it rejects the request.
IDL_DRSInitDemotion is called before the other demotion methods: IDL_DRSReplicaDemotion and IDL_DRSFinishDemotion.
Otherwise, all method requests are independent, apart from their dependencies on the state of the directory. The potential dependencies are varied, and understanding them requires understanding the state model specified in [MS-ADTS] section 3.1.1. Here are some examples:
Successfully processing an IDL_DRSAddEntry request can create a crossRef object. When the directory is in this state (that is, when it holds the crossRef object), an IDL_DRSRemoveDsDomain request can successfully remove that crossRef object (subject to other conditions specified with IDL_DRSRemoveDsDomain).
Successfully processing an IDL_DRSAddEntry request can create an nTDSDSA object. When the directory is in this state (that is, when it holds the nTDSDSA object), an IDL_DRSRemoveDsServer request can successfully remove that nTDSDSA object.
Successfully processing an IDL_DRSReplicaAdd request creates a repsFrom value on a server. When a server is in this state (that is, when it holds the repsFrom value), it has the information needed to make an IDL_DRSGetNCChanges request on the DC that is specified in IDL_DRSReplicaAdd.
Successfully processing an IDL_DRSUpdateRefs request creates a repsTo value on a server. When a server is in this state (that is, when it holds the repsTo value), it has the information needed to make an IDL_DRSReplicaSync request on the DC that is specified in IDL_DRSUpdateRefs.
Successfully processing an IDL_DRSRemoveDsDomain request first requires the removal of the metadata for all DCs hosting the domain NC for the domain that is to be removed. This precondition is achieved by the client calling IDL_DRSRemoveDsServer for each such DC.
State-based sequencing issues also exist between methods specified in this document and LDAP, because LDAP provides another way to change the state of the directory.
One method, IDL_DRSGetReplInfo, has a parameter of both input and output, dwEnumerationContext. This parameter is defined for the following:
dwInVersion=2, and
InfoType=DS_REPL_INFO_METADATA_FOR_ATTR_VALUE, or DS_REPL_INFO_METADATA_2_FOR_ATTR_VALUE, or DS_REPL_INFO_CURSORS_2_FOR_NC, or DS_REPL_INFO_CURSORS_3_FOR_NC.
For the first call to this method for a specific InfoType, the client sets dwEnumerationContext in pmsgIn to zero. The server returns an implementation-specific value for dwEnumerationContext in pmsgOut. On subsequent calls to this method with the same InfoType, the client sets the input dwEnumerationContext in pmsgIn to the last value of that field returned from the server. The purpose of this field is to allow the client to gather all the requested information, but in more than one server call. The final call is identified when the method returns ERROR_NO_MORE_ITEMS. See the server implementation section for IDL_DRSGetReplInfo (4.1.13.3) for exact details.
Figure 1: Using dwEnumerationContext