4.1.1.3 Server Behavior of the IDL_DRSAddEntry Method
Informative summary of behavior: A disabled crossRef object cr is one with cr!Enabled = false. Enabling a disabled crossRef object cr means setting cr!nCName and cr!dnsRoot, and removing cr!Enabled.
This method enables, creates, or modifies one or more objects, as requested by the client, in a single transaction. It enables crossRef objects, creates crossRef objects and nTDSDSA objects, and modifies arbitrary objects. The client uses an ENTINF structure to specify the state of each enabled, created, or modified object:
Enabling a crossRef object: The dnsRoot attribute of a disabled crossRef object contains a set of one or more DNS host names, expressed as Unicode strings. The request to enable a crossRef object succeeds only if the IP address of the client that is making the request matches the IP address of one of the DNS host names in the dnsRoot attribute. When a disabled crossRef object is enabled through this method, the server is not required to be the Domain Naming Master FSMO role owner.
The client has to specify the nCName and dnsRoot attributes. The trustParent and rootTrust attributes are optional.
Creating a crossRef object: If the request creates a crossRef object, it succeeds only if the server owns the forest's Domain Naming Master FSMO role. The access check is the same as when a crossRef object is created through LDAP.
The client specifies the same attributes that are required during an LDAP Add of a crossRef object, namely the new object's DN, plus all must-have attributes of the crossRef class. See [MS-ADTS] section 6.1.1.2.1.1 for the specification of crossRef objects.
Creating an nTDSDSA object: Creating an nTDSDSA object is not possible with LDAP. To create an nTDSDSA object, the hasMasterNCs attribute in the request has to identify the forest's schema NC and config NC, and the DC's default NC; that is, the domain of the DC corresponding to the new nTDSDSA object. If the default NC exists on the server as the nTDSDSA object is being created by IDL_DRSAddEntry, the client has to have the control access right DS-Replication-Manage-Topology on the default NC. Otherwise, the client has to have the right to enable or create the crossRef object that corresponds to the default NC, and has to enable or create this crossRef object in the same IDL_DRSAddEntry request.
The client specifies the new object's DN, plus the hasMasterNCs attribute. To create an nTDSDSA object for a functional DC, the request will contain invocationId, dMDLocation, options, msDS-Behavior-Version, and systemFlags. See [MS-ADTS] section 6.1.1.2.2.1.2.1.1 for the specification of nTDSDSA objects.
If the serverReference attribute is given a value in the request, the computer object to which the serverReference attribute points is updated with a new replication SPN.
Modifying an object: To modify an existing object (other than enabling a crossRef object), the client-supplied ENTINF structure includes ENTINF_REMOTE_MODIFY in the ulFlags field and specifies the modified attributes and their values. The client has to have the same rights as those needed to perform the modification via LDAP. The DC enforces the same schema and other constraints on the modification as if performed via LDAP. Performing the modification by using IDL_DRSAddEntry rather than LDAP allows changes to multiple objects to be made in a single transaction.<8>
ULONG IDL_DRSAddEntry( [in, ref] DRS_HANDLE hDrs, [in] DWORD dwInVersion, [in, ref, switch_is(dwInVersion)] DRS_MSG_ADDENTRYREQ *pmsgIn, [out, ref] DWORD *pdwOutVersion, [out, ref, switch_is(*pdwOutVersion)] DRS_MSG_ADDENTRYREPLY *pmsgOut) ext: DRS_EXTENSIONS_INT pEntInfList: ADDRESS OF ENTINFLIST pClientCreds: ADDRESS OF DRS_SecBufferDesc objCls : ATTRTYP ncNameV: DSName infoList: ADDENTRY_REPLY_INFO cObjects: ULONG res: boolean prefixTable: PrefixTable ValidateDRSInput(hDrs, 17) /* Only attributes and classes in the base schema can be specified.*/ prefixTable := NewPrefixTable() /* Set the default response version */ pdwOutVersion := 2 if dwInVersion = 1 then /* obsolete */ pmsgOut^.V1.Guid := 0 pmsgOut^.V1.Sid := 0 pmsgOut^.V1.errCode := 0 pmsgOut^.V1.dsid := 0 pmsgOut^.V1.extendedErr := 0 pmsgOut^.V1.extendedData := 0 pmsgOut^.V1.problem := 0 else if dwInVersion = 2 then pmsgOut^.V2.pErrorObject:= null pmsgOut^.V2.errCode := 0 pmsgOut^.V2.dsid := 0 pmsgOut^.V2.extendedEr := 0 pmsgOut^.V2.extendedData := 0 pmsgOut^.V2.problem := 0 pmsgOut^.V2.cObjectsAdded := 0 pmsgOut^.V2.infoList := null else if dwInVersion = 3 then pmsgOut^.V3.pdsErrObject := null pmsgOut^.V3.dwErrVer := 0 pmsgOut^.V3. pErrData := null pmsgOut^.V3.ULONG cObjectsAdded := 0 pmsgOut^.V3.infoList := null endif /* Validate parameters. */ if not (dwInVersion in {2,3}) then SetErrorData(SV_PROBLEM_UNAVAILABLE, 0, ERROR_DS_UNAVAILABLE, pmsgOut, 2) return 0 endif /* If the client supports the version 3 response, use version 3. */ ext := ClientExtensions(hDrs) if DRS_EXT_ADDENTRYREPLY_V3 in ext.dwFlags then pdwOutVersion^ := 3 else pdwOutVersion^ := 2 endif cObjects := 0 if dwInVersion = 2 then pEntInfList := pmsgIn^.V2.EntInfList pClientCreds := null else pEntInfList := pmsgIn^.V3.EntInfList pClientCreds := pmsgIn^.V3.pClientCreds endif /* If explicit credentials are given, use them for access checks. */ if pClientCreds ≠ null then err := UseCredsForAccessCheck(pClientCreds^) if err ≠ 0 then return err endif endif /* Walk through each item in the EntInfList and perform the requested * operation. */ e := pEntInfList while e ≠ null if ENTINF_REMOTE_MODIFY in e^.ulFlags then if DSAObj()!msDS-Behavior-Version ≥ DS_BEHAVIOR_WIN2008 then res := PerformModifyEntInf( hDrs, e^.Entinf, ADR(infoList[cObjects])) if not res then return 0 endif else /* Not supported (Win2k3 or older DC). */ SetErrorData(SV_PROBLEM_UNAVAILABLE, 0, ERROR_DS_UNAVAILABLE, pmsgOut, pdwOutVersion^) return 0 endif else objCls := ENTINF_GetValue(e^.Entinf, objectClass, prefixTable) if objCls = crossRef then /* Create or enable a crossRef object. */ res := CreateCrossRef(hDrs, e^.Entinf, psmgOut, pdwOutVersion^, ADR(infoList[cObjects])) if not res then return 0 endif else if objCls = nTDSDSA then /* Create an nTDSDSA object. */ res := CreateNtdsDsa(hDrs, e^.Entinf, pEntInfList, pmsgOut, pdwOutVersion^, ADR(infoList[cObjects])) if not res then return 0 endif else /* Not supported. */ SetErrorData(SV_PROBLEM_BUSY, 0, ERROR_DS_DRA_INVALID_PARAMETER, pmsgOut, pdwOutVersion^) return 0 endif endif e := e^.pNextEntInf cObjects := cObjects + 1 endwhile if pdwOutVersion^ = 2 then pmsgOut^.V2.cObjectsAdded := cObjects pmsgOut^.V2.infoList := infoList else pmsgOut^.V3.cObjectsAdded := cObjects pmsgOut^.V3.infoList := infoList endif return 0