3.1.1.5.1.8 Updates Performed Only on FSMOs
Certain originating update operations in Active Directory must be performed on a single master. For example, all schema updates must happen on the schema master FSMODC; creation and deletion of crossRefobjects representing naming contexts must happen on the domain naming FSMO DC. If the operation is attempted on a DC that does not hold the FSMO role, then it issues a referral to the current FSMO role owner. The following section describes how such updates are handled. The processing is not performed when applying replicated updates.
The following types and functions are used in specifying the FSMOrelated processing of originating update.
The function IsEffectiveRoleOwner(roleObject:object) verifies that the current DC is the valid owner of the given FSMO role. The FSMO ownership is considered valid if a successful replication of the corresponding NC occurred with some replication partner. This function is defined later in this section.
For a given FSMO role, the function RoleUpdateScope(roleObject:Object) returns the set of objects and their attributes that can only be updated on the FSMO role owner DC. For example, for Schema Master FSMO Role (section 6.1.5.1), the set contains all objects residing within schema NC, with all of their attributes. The function is defined later in this section.
Define variable timeLastReboot equal to the time when the server last rebooted.
Define function IsEffectiveRoleOwner(roleObject: object), which returns a Boolean as follows:

Let S be the nTDSDSA object of the server.

If S ≠ roleObject!fSMORoleOwner, then return false.

Let N be the NC containing roleObject.

If there exists at least one entry E in N!repsFrom such that E.timeLastSuccess > timeLastReboot, then return true.

Otherwise return false.
Let RoleType be the enumeration (SchemaMasterRole, DomainNamingMasterRole, InfrastructureMasterRole, RidAllocationMasterRole, PdcEmulationMasterRole).
Define function RoleObject(n: NC, roleType: RoleType), which returns an object as follows:

If roleType = SchemaMasterRole,

if n = Schema NC, return n, otherwise return null.


If roleType = DomainNamingMasterRole,

if n = Config NC, return Partition container of n, otherwise return null.


If roleType = InfrastructureMasterRole,

if n = Default NC (AD DS), return Infrastructure container of n, otherwise return null.


If roleType = RidAllocationMasterRole,

if n = Default NC (AD DS), return RID Manager container of n, otherwise return null.


If roleType = PdcEmulationMasterRole,

if n = Default NC (AD DS), return n, otherwise return null.


Otherwise return null.
Define function RoleUpdateScope(roleObject: object), which returns the set S as follows. S is a set such that each element is an object and a list of attributes associated with the object.

Let n be the NC containing roleObject.

Let roleType be the role corresponding to the roleObject; that is, RoleObject(n, roleType) = roleObject.

If roleType = SchemaMasterRole, the union of:

The set of all objects and all attributes in the roleObject's NC.

The RoleObject(Config NC, DomainNamingMasterRoll) with the msDSBehaviorVersion attribute.


If roleType = DomainNamingMasterRole, the union of

roleObject and all attributes except msDSBehaviorVersion.

The objects that are children of roleObject and all attributes.


If roleType = InfrastructureMasterRole, the union of

roleObject and all attributes.

The Updates container u of roleObject's NC and all attributes.

The objects that are children u and all attributes.


If roleType = RidAllocationMasterRole, the union of

roleObject and all attributes.

Let I = GetWellKnownObject(n, GUID_INFRASTRUCTURE_CONTAINER).

All children C of I and all attributes, such that C!objectClass contains infrastructureUpdate and C!proxiedObjectName is present.

If C is the computer object for the DC requesting the FSMO operation, C and all attributes.

The DC's rIDSet object.


If roleType = PdcEmulationMasterRole,

roleObject and all attributes.

n with attributes wellKnownObjects and msDSBehaviorVersion.


Otherwise return NULL.
Given those preliminaries, the following processing is performed on each object O on which an originating update is being made.
Let O.A be the attribute that is being updated.
Let N be the NC containing O.
For each RoleType T do the following:

Let R = RoleObject(N, T)

If R exists, then

Let S = RoleUpdateScope(R).

If O is not an element of {S} or O.A is not an element of {S}, then proceed with the originating update operation.

If R!fSMORoleOwner ≠ distinguished name of the nTDSDSA object of the server, then let K = (R!fSMORoleOwner)!parent. Return the error referral / <unrestricted> to K!dNSHostName.

If IsEffectiveRoleOwner(R) = true, proceed with the originating update operation.

Otherwise, return the error busy / <unrestricted>.
