Was this page helpful?
Your feedback about this content is important. Let us know what you think.
Additional feedback?
1500 characters remaining
4.1.29.3 Server Behavior of the IDL_DRSAddCloneDC Method

4.1.29.3 Server Behavior of the IDL_DRSAddCloneDC Method

Informative summary of behavior: The IDL_DRSAddCloneDC method is used to create a new domain controller (DC) by duplicating the states of the original DC. The states of a DC are composed of computer, server, NTDS settings, FRS, DFSR, and connection objects that are maintained for each DC. When duplicating an object, this RPC method replaces all references to the original DC with corresponding objects of the new DC. The caller must have the control access right DS-Clone-Domain-Controller on the default NC. When called, this RPC method:

  1. Validates that the caller has permission to perform the operation.

  2. Creates new account and other objects for the new domain controller account by copying information from the existing domain controller.

  3. Returns the name, site, and password for the new domain controller to the client.

  4.  ULONG
     IDL_DRSAddCloneDC(
         [in, ref] DRS_HANDLE hDrs,
         [in] DWORD dwInVersion,
         [in, ref, switch_is(dwInVersion)] 
             DRS_MSG_ADDCLONEDCREQ *pmsgIn,
         [out, ref] DWORD *pdwOutVersion,
         [out, ref, switch_is(*pdwOutVersion)] 
             DRS_MSG_ADDCLONEDCREPLY *pmsgOut)
      
     msgIn: DRS_MSG_ADDCLONEDCREQ_V1
     clientCreds: ClientAuthorizationInfo
     tlInfo: TranslationInfo
     callerSid: SID
     isRodc: boolean
      
     computerObj: DSName
     originalDCSrvObj: DSName
     originalDCSiteObj: DSName
     originalDCServersObj: DSName
     originalDSAObj: DSName
      
     newDCComputerObj: DSName
     newDCSiteObj: DSName
     newDCServersObj: DSName
     newDCServerObj: DSName
     newDSAObj: DSName
      
      
     ValidateDRSInput(hDrs, 28)
      
     pdwOutVersion^ := 1
     pmsgOut^.V1.pwszCloneDCName := null
     pmsgOut^.V1.pwszSite := null
     pmsgOut^.V1.cPasswordLength := 0
     pmsgOut^.V1.pwsNewDCAccountPassword := null
     if dwInVersion ≠ 1 then
       return ERROR_DS_DRA_INVALID_PARAMETER
     endif
     msgIn := pmsgIn^.V1
      
     if GetKeyLength(hDrs) < 128 then
         return ERROR_DS_STRONG_AUTH_REQUIRED
     endif
      
     if not AccessCheckCAR(DefaultNC(), DS-Clone-Domain-Controller) then
       return ERROR_DS_DRA_ACCESS_DENIED
     endif
      
     /* Check that the caller (the "source" DC) is actually a DC by
      * checking Enterprise Domain Controllers or Enterprise Read-Only Domain 
      * Controllers SID in its token. */
     clientCreds := GetCallerAuthorizationInfo()
     if not CheckGroupMembership(clientCreds, SidFromStringSid("S-1-5-9")) then
         if not CheckGroupMembership(clientCreds, SidFromStringSid("S-1-5-498"))
           then
             return ERROR_DS_DRA_ACCESS_DENIED
         else
             isRodc := true
         endif
     endif
      
     /* The DC must own the PDC role */
     if GetFSMORoleOwner(FSMO_PDC) ≠ DSAObj() then
       return ERROR_INVALID_DOMAIN_ROLE
     endif
      
     callerSid := GetPrincipalSid(clientCreds)
      
     /* get the original DC computer object */
     computerObj := select one obj from all where
                  (obj!objectSid = callerSid)
      
     tlInfo.OriginalDC.Name := computerObj!sAMAccountName.Remove('$')
      
     /* generate cloned DC name if not specified */
     if (msgIn.pwszCloneDCName = null)
         found : boolean 
         newDCName : string
      
         /* Generate new name by appendling '–CL' and 4 digits to the original
          * DC name */
         found := false
         For suffix = 0000 to 9999 do
            newDCName := tlInfo.OriginalDC.Name[0 .. 8] + '-CL' + suffix 
      
            if not exists(
                select o from all where o!sAMAccountName = (newDCName + '$')
            ) then
                found := true
                break
             endif
         endfor
         if not found then 
             return ERROR_DS_UNWILLING_TO_PERFORM
         endif
         tlInfo.newDC.Name := newDCName
     else
         tlInfo.newDC.Name := msgIn.pwszCloneDCName
     endIf
      
     tlInfo.OriginalDC.Sid := computerObj!objectSid
     tlInfo.OriginalDC.dnsHostName := computerObj!dNSHostName
      
     if isRodc then
         newKrbTgtAcct : DSName
         newKrbTgtAcct := GenerateNewKrbTgtAcct()
         tlInfo.objMap[computerObj!msDS-KrbTgtLink] := newKrbTgtAcct
     endif
      
     /* Duplicate original DC computer object */
     newDCComputerObj := DuplicateObject(computerObj, computerObj!parent,
                             "cn=" + tlInfo.newDC.Name, tlInfo)
     tlInfo.objMap[compuerObj!distinguishedName] :=
       newDCComputerObj!distinguishedName
     tlInfo.NewDC.Sid := newDCComputerObj!objectSid
     tlInfo.NewDC.dnsHostName := newDCComputerObj!dNSHostName
      
     /* Get the original DC server object */
     originalDCSrvObj := select one v from ConfigNC()
       where v.dn in computerObj!serverReferenceBL
     originalDCServersObj := originalDCSrvObj!parent
     originalDCSiteObj := originalDCSrvObj!parent
      
     /* use the specified site for the new DC.
      * use the original DC site if the site is not specified */
     if (msgIn.pwszSite ≠ null) then
         siteContainer: DSName 
         siteContainer := DescendantObject(ConfigNC(), "CN=Sites,")
         newDCSiteObj := select one v from siteContainer!children
             where v!name = msgIn.pwszSite
         if newDCSiteObj = null
             return ERROR_NO_SUCH_SITE
         endIf
     else
         newDCSiteObj := originalDCSiteObj
     endIf
     newDCServersObj := DescendantObject(newDCSiteObj, "CN=Servers")
      
     /* Duplicate the original DC servers object if the servers object is not 
      * present in the new DC site */
     if not exists newDCServersObj then
         newDCServersObj := DuplicateObject(originalDCServersObj, 
                    newDCSiteObj, "CN=Servers", tlInfo)
     endIf
     tlInfo.objMap[originalDCServersObj!distinguishedName] :=
         newDCServersObj!distinguishedName
      
     /* Duplicate the server object */
     newDCServerObj := DescendantObject(newDCServersObj,
         "CN=" + tlInfo.newDC.Name)
      
     if not exists newDCServerObj then
         newDCServerObj := DuplicateObject(originalDCSrvObj, newDCServersObj,
                 "CN=" + tlInfo.newDC.Name, tlInfo)
     endIf
     tlInfo.objMap[originalDCSrvObj!distinguishedName] :=
         newDCServerObj!distinguishedName
      
     /* Duplicate the NTDS settings object */
     originalDSAObj := DescendantObject(originalDCSrvObj,
         "CN=NTDS Settings")
     newDSAObj := DuplicateObject(originalDSAObj, newDCServerObj,
         "CN=NTDS Settings", tlInfo)
     tlInfo.objMap[originalDSAObj!distinguishedName] :=
         newDSAObj!distinguishedName
      
     if isRodc then
         newConnObj: DSName
         topologyObj: DSName
         originalDFSRObj: DSName
         newDFSRObj: DSName
         frsSysvolObj: DSName
         originalFRSObj: DSName
         newfrsObj : DSName
      
         foreach obj in originalDSAObj!children where
           obj!objectClass = "ntdsConnection"
             newConnObj := DuplicateObject(obj, newDSAObj,
                 "CN=" + tlInfo.newDC.Name, tlInfo)
             objMap[obj!distinguishedName] := newConnObj!distinguishedName
         endfor
      
         /* Duplicate DFSR topology object */
         topologyObj := DescendantObject(DefaultNC(),
           "CN=Topology,CN=Domain System Volume,CN=DFSR-GlobalSettings,CN=System")
         originalDFSRObj := DescendantObject(topologyObj,
             "CN=" + tlInfo.OriginalDC.Name)
      
         if originalDFSRObj ≠ null then 
             newDFSRObj = DuplicateObject(originalDFSRObj, topologyObj,
                 "CN="+ tlInfo.newDC.Name, tlInfo)
         endIf
      
         /* Duplicate FRS object */
         frsSysvolObj = DescendantObject(DefaultNC(),
           "CN=Domain System Volume (SYSVOL     share),CN=File Replication Service,CN=System")
         originalFRSObj = DescendantObject(frsSysvolObj,
             "CN=" + tlInfo.OriginalDC.Name)
         if originalFRSObj ≠ null then
             newfrsObj = DuplicateObject(originalFRSObj, frsSysVolObj,
                 "CN=" + tlInfo.newDC.Name, tlInfo)
         endIf
     endif
      
      
     pmsgOut^.V1.pwszCloneDCname := tlInfo.newDC.Name
     pmsgOut^.V1.cPasswordLength := 120
     pmsgOut^.V1.pwsNewDCAccountPassword:= a 120-byte sequence of randomly
       generated characters between ASCII 32 (space) and ASCII 122 ('z')
     pmsgOut^.V1.pwszSite := newDCSiteObj!name
      
     return 0
      
    
Show:
© 2015 Microsoft