4.1.19.2 Server Behavior of the IDL_DRSReplicaAdd Method

Informative summary of behavior: The server adds a value to the repsFrom of the specified NC replica. If ulOptions contains DRS_ASYNC_OP, the server processes the request asynchronously. The client can be an administrative client or another DC. The client includes DRS_WRIT_REP in ulOptions if the specified NC replica is writable at the server. The client includes DRS_NONGC_RO_REP and DRS_SPECIAL_SECRET_PROCESSING in ulOptions if the specified NC replica is a read-only full replica on a read-only DC. The server adds a value to repsFrom, and the value has replicaFlags derived from ulOptions (see below), serverAddress equal to pszSourceDsaAddress (pszDsaSrc if V1), and schedule equal to rtSchedule. If ulOptions contains DRS_ASYNC_REP but not DRS_MAIL_REP or DRS_NEVER_NOTIFY, the server sends a request to the DC specified by pszSourceDsaAddress to add a value to the repsTo of the specified NC replica by calling IDL_DRSUpdateRefs. Finally, the server begins a replication cycle by sending an IDL_DRSGetNCChanges request.

 ULONG
 IDL_DRSReplicaAdd(
   [in, ref] DRS_HANDLE hDrs,
   [in] DWORD dwVersion,
   [in, ref, switch_is(dwVersion)] DRS_MSG_REPADD *pmsgAdd);
  
 options: DRS_OPTIONS
 nc: DSName
 partitionsObj: DSName
 cr: DSName
 rf: RepsFrom
 msgIn: DRS_MSG_REPADD_V2
 updRefs: DRS_MSG_UPDREFS /* See IDL_DRSUpdateRefs structures. */
 hDrsSrc: DRS_HANDLE
 msgRequest: DRS_MSG_GETCHGREQ
 msgOut: DRS_MSG_GETCHGREPLY
 outVersion: DWORD
 cMaxObjects: ULONG
 cMaxBytes: ULONG
 versionRequestMsg: DWORD
 err: ULONG
  
 ValidateDRSInput(hDrs, 5)
  
 /* Validate the version */
 if dwVersion ≠ 1 and dwVersion ≠ 2 then
   return ERROR_DS_DRA_INVALID_PARAMETER
 endif
 if dwVersion = 1 then
   msgIn := pmsgAdd^.V1
   msgIn.pszSourceDsaAddress = pmsgAdd^.V1.pszDsaSrc
 else
   msgIn := pmsgAdd^.V2
 endif
  
 if msgIn.pNC = null
    or msgIn.pszSourceDsaAddress = null
    or msgIn.pszSourceDsaAddress = "" then
   return ERROR_DS_DRA_INVALID_PARAMETER
 endif
  
 options := msgIn.ulOptions
 nc := msgIn.pNC^
  
 partitionsObj :=
     select one o from children ConfigNC() where o!name = "Partitions"
 cr := select o from children partitionsObj where o!nCName = nc
 if cr = null then
   return ERROR_DS_DRA_BAD_NC
 endif
  
 if options - {DRS_ASYNC_OP, DRS_CRITICAL_ONLY, DRS_ASYNC_REP, 
     DRS_WRIT_REP, DRS_INIT_SYNC,  DRS_PER_SYNC, DRS_MAIL_REP,
     DRS_NONGC_RO_REP, DRS_SPECIAL_SECRET_PROCESSING, DRS_DISABLE_AUTO_SYNC, 
     DRS_DISABLE_PERIODIC_SYNC, DRS_USE_COMPRESSION, DRS_NEVER_NOTIFY,
     DRS_TWOWAY_SYNC} ≠ {} then
   return ERROR_DS_DRA_INVALID_PARAMETER
 endif
  
 if AmIRODC() and DRS_WRIT_REP in options then
   return ERROR_DS_DRA_INVALID_PARAMETER
 endif
  
 if AmIRODC() and DRS_MAIL_REP in options then
   return ERROR_DS_DRA_INVALID_PARAMETER
 endif
  
 if DRS_MAIL_REP in options and not DRS_ASYNC_REP in options then
    return ERROR_DS_DRA_INVALID_PARAMETER
 endif
  
 if ObjExists(nc) then
   if not AccessCheckCAR(nc, DS-Replication-Manage-Topology) then
     return ERROR_DS_DRA_ACCESS_DENIED
   endif
 else
   if not AccessCheckCAR(DefaultNC(), DS-Replication-Manage-Topology)
         then
     return ERROR_DS_DRA_ACCESS_DENIED
   endif
 endif
  
 if DRS_ASYNC_OP in options then
   Asynchronous Processing: Initiate a logical thread of control
    to process the remainder of this request asynchronously
   return 0
 endif
  
 if ObjExists(nc) then
   if (IT_WRITE in nc!instanceType) ≠ (DRS_WRIT_REP in options) then
     return ERROR_DS_DRA_BAD_INSTANCE_TYPE
   endif
   /* Disallow addition if server already replicates from this
    * source */
   if (select one v from nc!repsFrom
         where v.serverAddress = msgIn.pszSourceDsaAddress) ≠ null
         then
     return ERROR_DS_DRA_DN_EXISTS
   endif
 endif
  
 if DRS_ASYNC_REP in options then
   if msgIn.pSourceDsaDN = null
       or not ObjExists(msgIn.pSourceDsaDN^)
     then 
     return ERROR_DS_DRA_INVALID_PARAMETER
   endif
 endif
  
 if DRS_MAIL_REP in options then
   if msgIn.pTransportDN = null
       or not ObjExists(msgIn.pTransportDN^)
     then
     return ERROR_DS_DRA_INVALID_PARAMETER
   endif
 endif
  
 /* Construct RepsFrom value. */
 if msgIn.pSourceDsaDN ≠ null then
   rf.uuidDsa := msgIn.pSourceDsaDN^!objectGUID
 endif
 if msgIn.pTransportDN ≠ null then
   rf.uuidTransportObj := msgIn.pTransportDN^!objectGUID
 endif
 rf.replicaFlags := msgIn.ulOptions ∩ {DRS_DISABLE_AUTO_SYNC,
     DRS_DISABLE_PERIODIC_SYNC, DRS_INIT_SYNC, DRS_MAIL_REP,
     DRS_NEVER_NOTIFY, DRS_PER_SYNC, DRS_TWOWAY_SYNC,
     DRS_USE_COMPRESSION, DRS_WRIT_REP, DRS_NONGC_RO_REP,
     DRS_SPECIAL_SECRET_PROCESSING }
 rf.schedule := msgIn.rtSchedule^
 rf.serverAddress := msgIn.pszSourceDsaAddress^
 rf.timeLastAttempt := current time
  
 nc!repsFrom := nc!repsFrom + {rf}
 if msgIn.ulOptions ∩ {DRS_ASYNC_REP, DRS_NEVER_NOTIFY, DRS_MAIL_REP}
       = {DRS_ASYNC_REP} then
   /* Enable replication notifications by requesting the server DC
    * to add a repsTo for this DC. */
   updRefs.pNC^ := ADR(nc)
   updRefs.pszDsaDest := NetworkAddress of this DC
   updRefs.uuidDsaObjDest := dc.serverGuid
   updRefs.ulOptions := {DRS_ASYNC_OP, DRS_ADD_REF, DRS_DEL_REF}
   if DRS_WRIT_REP in msgIn.ulOptions then
     updRefs.ulOptions := updRefs.ulOptions + {DRS_WRIT_REP}
   endif
  
   hDrsSrc := BindToDSA(msgIn.pSourceDsaDN)
   if hDrsSrc ≠ null then
     ret := IDL_DRSUpdateRefs(hDrsSrc, 1, ADR(updRefs))
     UnbindFromDSA(hDrsSrc)
   endif
  
 endif
  
 /* Perform a replication cycle as a client of IDL_DRSGetNCChanges. */
 versionRequestMsg := The version number of the input message negotiated between the
   client and server (section 4.1.10.4.1).
 cMaxObjects := Implementation-specific value.
 cMaxBytes := Implementation-specific value.
/* Form the first request */
ReplicateNCRequestMsg(
  hDrsSrc,
  versionRequestMsg,
  nc,
  rf,
  options,
  cMaxObjects,
  cMaxBytes,
  ADDR(msgRequest))
 
err := IDL_DRSGetNCChanges(
  hDrsSrc,
  versionRequestMsg,
  msgRequest,
  ADDR(outVersion),
  ADDR(msgOut))
 
if err = 0
    and not DRS_MAIL_REP in msgIn.ulOptions
  then
 
    Wait for the response, process it (section 4.1.10.6), send the next request, etc.
    until the replication cycle is complete.
 
    If there are any failures from this replication attempt, err is assigned an
    appropriate error value.
 
endif
 return err