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