4.1.10.5.2 GetReplChanges

 procedure GetReplChanges(
   hDrs: DRS_HANDLE,
   searchFilter: LDAPString,
   dirSyncFlags: ULONG,
   msgIn: DRS_MSG_GETCHGREQ_V10,
   var msgOut: DRS_MSG_GETCHGREPLY_NATIVE): ULONG

Informative summary of behavior: The GetReplChanges procedure processes an LDAP Search request with LDAP_SERVER_DIRSYNC_OID control or a normal replication request; that is, an IDL_DRSGetNCChanges request that is not a FSMO role request. It adds changed objects and link values to the response, subject to the scope (msgIn.pNC^, msgIn.ulFlags), filter criteria (msgIn.pUpToDateVecDest, msgIn.ulFlags, msgIn.pPartialAttrSet, msgIn.pPartialAttrSetEx, searchFilter, dirSyncFlags), response limits (msgIn.cMaxObjects, msgIn.cMaxBytes), and the previous server cookie (msgIn.usnvecFrom) in the request. It returns 0 if successful, otherwise a Windows error code.

 err: ULONG 
 ncRoot: DSName
 pUtd: ADDRESS OF UPTODATE_VECTOR_V1_EXT
 scope: set of DSName
 attribute: ATTRTYP
 partialAttrs: set of ATTRTYP
 partialAttrsEx: set of ATTRTYP
 changedObjs: set of ObjAtts
 changedLinks: set of ObjAttVal
 responseObjs: set of ObjAtts
 responseLinks: set of ObjAttVal
 anc: ObjAtts
 clientDSA : DSName
 updRefs: DRS_MSG_UPDREFS_V1 /* See IDL_DRSUpdateRefs structures. */
 tgt: DSName
  
 if AmIRODC() then
   return ERROR_DS_DRA_SOURCE_DISABLED
 endif
  
 /* check whether outbound replication is disabled */
 /* NTDSDSA_OPT_DISABLE_OUTBOUND_REPL defined in
  * [MS-ADTS] section 6.1.1.2.2.1.2.1.1, "nTDSDSA Object" */
  
 if NTDSDSA_OPT_DISABLE_OUTBOUND_REPL in DSAObj()!options and
    not DRS_SYNC_FORCED in msgIn.ulFlags and
    not dirSyncFlags then
   return ERROR_DS_DRA_SOURCE_DISABLED
 endif
 ncRoot := GetObjectNC(msgIn.pNC^)
  
 /* Determine stamp filter to apply to the response. */
 if DRS_FULL_SYNC_PACKET in msgIn.ulFlags then
   pUtd := null
 else
   pUtd := msgIn.pUpToDateVecDest
 endif
  
 /* Determine attribute filters to apply to the response. */
 if msgIn.pPartialAttrSet = null
   partialAttrs := null
 else
   partialAttrs := {}
   foreach id in msgIn.pPartialAttrSet
     attribute := LocalAttidFromRemoteAttid(msgIn.PrefixTableDest, id)
     if (not IT_WRITE in ncRoot!instanceType) and
        (not attribute in ncRoot!partialAttributeSet) then
       return ERROR_DS_DRA_INCOMPATIBLE_PARTIAL_SET
     endif
     partialAttrs := partialAttrs + { attribute }
   endfor
 endif
 if msgIn.pPartialAttrSetEx = null
   partialAttrsEx := null
 else
   partialAttrsEx := {}
   foreach id in msgIn.pPartialAttrSetEx
     attribute := LocalAttidFromRemoteAttid(msgIn.PrefixTableDest, id)
     if (not IT_WRITE in ncRoot!instanceType) and
        (not attribute in ncRoot!partialAttributeSet) then
       return ERROR_DS_DRA_INCOMPATIBLE_PARTIAL_SET
     endif
     partialAttrsEx:= partialAttrsEx + { attribute }
   endfor
 endif
  
 /* Get nTDSDSA of the client */
 clientDSA := select one o from ConfigNC() where
              o!objectGUID = msgIn.uuidDsaObjDest
  
 /* Get the set of all objects that are in scope. */
 scope := GetReplScope(msgIn, searchFilter)
  
 /* Get object and link value changes in scope. */
 GetChangesInScope(scope, pUtd, msgIn.ulExtendedOp, partialAttrs,
     partialAttrsEx, dirSyncFlags, changedObjs, changedLinks)
  
 /* Choose subsets of changedObjs and changedLinks to include in this
  * response. Set usnvecTo and fMoreData in out to indicate the
  * subset to return in the next response, if any. */
 GetResponseSubset(msgIn, changedObjs, changedLinks, msgOut,
     responseObjs, responseLinks)
  
 /* Add responseObjs to response. */
 foreach o in responseObjs
   if DRS_GET_ANC in msgIn.ulFlags then
     /* Ancestors predicate: insert any changes to parent before any
      * changes to child. */
     foreach n in Ancestors of o.obj, most distant ancestor first
       anc := select one a from changedObjs where a.obj = n
       if anc ≠ null then
         err := AddObjToResponse(
           hDrs, anc, ncRoot, msgIn.ulFlags, 0, clientDSA, msgOut)
         if err ≠ 0 then
           return err
         endif
       endif
     endfor
   endif
   err := AddObjToResponse(
     hDrs, o, ncRoot, msgIn.ulFlags, 0, clientDSA, msgOut)
   if err ≠ 0 then 
     return err
   endif
 endfor
  
 /* Add responseLinks to response. */
 foreach v in responseLinks
   if DRS_GET_ANC in msgIn.ulFlags then
     /* Ancestors predicate: insert any changes to object before any
      * changes to its link values. */
     anc := select one a from changedObjs where a.obj = v.obj
     if anc ≠ null then
       err := AddObjToResponse(hDrs, anc, ncRoot,
                        msgIn.ulFlags, 0, clientDSA, msgOut)
       if err ≠ 0 then
         return err
       endif
     endif
   endif
   if DRS_GET_TGT in msgIn.ulMoreFlags then
     /* Target predicate: insert any changes to the target object 
      * before any changes to the link value. */
     tgt := GetDSNameFromAttrVal(v.att, v.val)
     if DRS_GET_ANC in msgIn.ulFlags then
        /* Ancestors predicate: insert any changes to the ancestors of 
         * the target before any changes to the target. */
        foreach n in Ancestors of tgt, most distant ancestor first
          anc := select one a from changedObjs where a.obj = n
          if anc ≠ null then
            err := AddObjToResponse(hDrs, anc, ncRoot,
                             msgIn.ulFlags, 0, clientDSA, msgOut)
            if err ≠ 0 then
              return err
            endif
          endif
        endfor
     endif
     err := AddObjToResponse(hDrs, tgt, ncRoot,
                      msgIn.ulFlags, 0, clientDSA, msgOut)
     if err ≠ 0 then 
       return err
     endif
   endif
   AddLinkToResponse(v, msgIn, msgOut)
 endfor
  
 if not msgOut.fMoreData
   msgOut.pUpToDateVecSrc := The cycle goal, as specified in
       section 4.1.10.1.2.
 endif
  
 if DRS_GET_NC_SIZE in msgIn.ulFlags then
   msgOut.cNumNcSizeObjects := Approximate number of objects in
       NC replica msgIn.pNC^
   msgOut.cNumNcSizeValues := Approximate number of link values
       with stamps in NC replica msgIn.pNC^
 endif
  
 if (DRS_ADD_REF in msgIn.ulFlags and msgIn.uuidDsaObjDest ≠ NULLGUID) then
   /* Client has requested the server to add a repsTo entry. */
   updRefs.uuidDsaDes := msgIn.uuidDsaObjDest
   updRefs.pNC := msgIn.pNC^
   updRefs.pszDsaDest := NetworkAddress of DC corresponding to 
                         msgIn.uuidDsaObjDest
   updRefs.ulOptions := {DRS_ADD_REF, DRS_ASYNC_OP, 
                         DRS_GETCHG_CHECK} +
                        { msgIn.ulFlags ∩ {DRS_WRIT_REP, DRS_REF_GCSPN}}
  
   /* Using updRefs, perform repsTo add to the specified NC replica, 
    * the result value is a Windows error code or 0.
   err := UpdateRefs(updRefs^.V1) 
   if(err ≠ 0) then
      return err
   endif
 endif
  
 return 0