4.1.10.5.12 ProcessFsmoRoleRequest
-
procedure ProcessFsmoRoleRequest( hDrs: DRS_HANDLE, msgIn: DRS_MSG_GETCHGREQ_V10, var msgOut: DRS_MSG_GETCHGREPLY_NATIVE)
Informative summary of behavior: The ProcessFsmoRoleRequest procedure performs the requested FSMO role operation indicated by msgIn.ulExtendedOp.
-
fsmoObj: DSName clientDsaObj: DSName serverObj: DSName: DSName rodcObj: DSNAME: DSName clientComputerObj: DSName clientRidSetObj: DSName ownerDsaObj: DSName scope: set of DSName ridAllocLoHi: ULONGLONG ridAllocHi: DWORD ridReqHi: DWORD ridAvailLoHi: ULONGLONG ridAvailLo: DWORD ridAvailHi: DWORD changedObjs: set of ObjAtts changedLinks: set of ObjAttVal /* Specific error check when at DC functional level Win2K3 */ if (DSAObj()!msDS-Behavior-Version = DS_BEHAVIOR_WIN2003) and (not DRS_WRIT_REP in msgIn.ulFlags) then msgOut.ulExtendedRet := EXOP_ERR_PARAM_ERR return endif fsmoObj := msgIn.pNC^ if not ObjExists(fsmoObj) then msgOut.ulExtendedRet := EXOP_ERR_UPDATE_ERR return endif if msgIn.uuidDsaObjDest = null then msgOut.ulExtendedRet := EXOP_ERR_UPDATE_ERR return endif clientDsaObj := select one o from ConfigNC()where o!objectGUID = msgIn.uuidDsaObjDest if clientDsaObj = null then msgOut.ulExtendedRet := EXOP_ERR_UNKNOWN_CALLER return endif scope := {}if msgIn.ulExtendedOp in {EXOP_FSMO_REQ_ROLE, EXOP_FSMO_REQ_PDC, EXOP_FSMO_RID_REQ_ROLE} then /* Change the FSMO role owner from the server to the client. */ if fsmoObj!fSMORoleOwner ≠ DSAObj() then msgOut.ulExtendedRet := EXOP_ERR_FSMO_NOT_OWNER return endif fsmoObj!fSMORoleOwner := clientDsaObj scope := GetRoleScope(fsmoObj) else if msgIn.ulExtendedOp = EXOP_FSMO_ABANDON_ROLE then /* Request a change in the FSMO role owner from the current owner * to the server. The server will refuse to take the FSMO role if * it is not a full replica and cannot own FSMO. */ if AmIRODC() then msgOut.ulExtendedRet := EXOP_ERR_FSMO_REFUSING_ROLES endif if fsmoObj!fSMORoleOwner ≠ DSAObj() then ownerDsaObj := fsmoObj!fSMORoleOwner if not ObjExists(ownerDsaObj) then msgOut.ulExtendedRet := EXOP_ERR_UNKNOWN_CALLER return else if ownerDsaObj!isDeleted = true msgOut.ulExtendedRet := EXOP_ERR_FSMO_OWNER_DELETED return endif Call IDL_DRSGetNCChanges as a client to the server identified by ownerDsaObj to perform a EXOP_FSMO_REQ_ROLE extended operation; see the client request generation and response processing sections if fsmoObj!fSMORoleOwner ≠ DSAObj() then /* Transfer failed. */ msgOut.ulExtendedRet := EXOP_ERR_COULDNT_CONTACT return endif endif else if msgIn.ulExtendedOp = EXOP_FSMO_REQ_RID_ALLOC then /* Allocate a block of RIDs for the client DC. */ if fsmoObj ≠ DefaultNC()!rIDManagerReference then msgOut.ulExtendedRet := EXOP_ERR_MISMATCH return else if fsmoObj!fSMORoleOwner ≠ DSAObj() then msgOut.ulExtendedRet := EXOP_ERR_FSMO_NOT_OWNER return endif /* Locate or create the RID Set object for the client DC. */ serverObj := clientDsaObj!parent clientComputerObj := serverObj!serverReference if clientComputerObj!rIDSetReferences = null then clientRidSetObj := An implementation-defined DSName in the default NC such that not ObjExists(clientRidSetObj) Create object with DSName clientRidSetObj such that rIDSet in clientRidSetObj!objectClass /* Windows Behavior: Windows sets clientRidSetObj to be a child * of clientComputerObj. */ clientComputerObj!rIDSetReferences := clientRidSetObj else clientRidSetObj := clientComputerObj!rIDSetReferences endif /* Get the current RID allocation for the client DC. */ ridAllocLoHi := clientRidSetObj!rIDAllocationPool ridAvailHi := most significant 32 bits of ridAvailLoHi ridReqHi := most significant 32 bits of msgIn.liFsmoInfo if ridAllocLoHi = 0 or ridAvailHi = 0 or ridReqHi ≥ ridAvailHi then /* The client DC has indeed exhausted its current allocation, * according to our records. */ /* Get the range of RIDs that have not yet been allocated to any * DC. */ ridAvailLoHi := fsmoObj!rIDAvailablePool ridAvailLo := least significant 32 bits of ridAvailLoHi ridAvailHi := most significant 32 bits of ridAvailLoHi /* Select a subset of the unallocated RIDs and allocate them to * the client. */ Assign a value to ridAllocHi according to any implementation- defined policy such that ridAvailLo < ridAllocHi < ridAvailHi. /* Windows Behavior: By default, Windows sets ridAllocHi to * ridAvailLo + 500. */ ridAllocLoHi := ridAvailLo as least significant 32 bits and ridAllocHi as most significant 32 bits ridAvailLo := ridAllocHi + 1 ridAvailLoHi := ridAvailLo as least significant 32 bits and ridAvailHi as most significant 32 bits fsmoObj!rIDAvailablePool := ridAvailLoHi clientRidSetObj!rIDAllocationPool := ridAllocLoHi clientRidSetObj!rIDPreviousAllocationPool := 0 clientRidSetObj!rIDNextRID := 0 /* Windows Behavior: rIDUsedPool [MS-ADA3] is not used anywhere, * but Windows always sets it to zero. */ clientRidSetObj!rIDUsedPool := 0 msgOut.liFsmoInfo := ridAllocLoHi endif scope := GetRoleScope(fsmoObj) + {clientComputerObj, clientRidSetObj} else if EXOP_REPL_SECRETS in msgIn.ulExtendedOp and AmILHServer() then /* Request replication of a single object with secret. * Secret replication is allowed only if these three conditions * hold: * 1. Caller is an RODC. An RODC will always be a member of * "Enterprise Read-Only Domain Controllers" (RID 498) * [MS-ADTS] section 6.1.1.6.14. * 2. The object is configured to reveal secrets. * 3. Outbound secret replication is not disabled. */ serverObj := clientDsaObj!parent rodcObj := serverObj!serverReference if CheckGroupMembership( GetCallerAuthorizationInfo(), SidFromStringSid("S-1-5-22")) and RevealSecretsForUserAllowed(rodcObj, fsmoObj) and (not NTDSDSA_OPT_DISABLE_OUTBOUND_REPL in DSAObj()!options or DRS_SYNC_FORCED in msgIn.ulFlags) then scope := {fsmoObj} else scope := {} endif else if EXOP_REPL_OBJ in msgIn.ulExtendedOp if AmILHServer() = true and NTDSDSA_OPT_DISABLE_OUTBOUND_REPL in DSAObj()!options and not DRS_SYNC_FORCED in msgIn.ulFlags then /* replication of single object is disabled */ pmsgOut.dwDRSError := ERROR_DS_DRA_SOURCE_DISABLED return endif /* Operation is invalid if destination is full replica but this server * is not, or if both are partial replicas but this server does not have * all the attributes needed by the destination in its PAS. */ if(not FullReplicaExists(GetObjectNC(msgIn.pNC^)) and not msgIn.pPartialAttrSet = null) msgOut.ulExtendedRet := EXOP_ERR_PARAM_ERR return else if not GetFilteredAttributeSet() ∩ msgIn.pPartialAttrSet = {} then msgOut.ulExtendedRet := EXOP_ERR_PARAM_ERR return endif scope := {fsmoObj} else /* Unrecognized request. */ msgOut.ulExtendedRet := EXOP_ERR_UNKNOWN_OP return endif if scope ≠ {} then /* Add updates in scope to the response. */ GetChangesInScope(scope, msgIn.pUpToDateVecDest, msgIn.ulExtendedOp, msgIn.pPartialAttrSet, msgIn.pPartialAttrSet, 0, changedObjs, changedLinks) foreach o in changedObjs AddObjToResponse( hDrs, o, GetObjectNC(msgIn.pNC^), msgIn.ulFlags, msgIn.ulExtendedOp, msgOut) endfor foreach v in changedLinks AddLinkToResponse(v, msgIn, msgOut) endfor endif msgOut.ulExtendedRet := EXOP_ERR_SUCCESS return