Export (0) Print
Expand All

4.1.5.2 Server Behavior of the IDL_DRSDomainControllerInfo Method

Informative summary of behavior: The IDL_DRSDomainControllerInfo method supports four information levels. For levels 1, 2, and 3, the server returns information for the DCs in the domain of the server. For level 0xffffffff, the server returns information about the LDAP connections on the server that are currently open.

Regular read access checks apply to the information that is returned to the caller. Therefore, if the caller does not have read permission on data that needs to be returned, this data is not included in the response. See [MS-ADTS] section 3.1.1.4.3 for more information about access check behavior in read operations.

For information about the Windows versions in which information levels were introduced and supported, see the following behavior note.<13>

Note  The server behavior of the IDL_DRSDomainControllerInfo method uses the CrackNames procedure defined in section 4.1.4.2.9.

ULONG
IDL_DRSDomainControllerInfo(
  [in, ref] DRS_HANDLE hDrs,
  [in] DWORD dwInVersion,
  [in, ref, switch_is(dwInVersion)] DRS_MSG_DCINFOREQ *pmsgIn,
  [out, ref] DWORD *pdwOutVersion,
  [out, ref, switch_is(*pdwOutVersion)] DRS_MSG_DCINFOREPLY *pmsgOut)

msgIn: DRS_MSG_DCINFOREQ_V1
infoLevel, i: integer
domainName: unicodestring
dcSet: set of DSName
serversContainer, crObj, dcObj, dsaObj, svrObj, siteObj, obj, v: DSName
lc: DS_DOMAIN_CONTROLLER_INFO_FFFFFFFFW
rI1: ADDRESS OF DS_DOMAIN_CONTROLLER_INFO_1W
rI2: ADDRESS OF DS_DOMAIN_CONTROLLER_INFO_2W
rI3: ADDRESS OF DS_DOMAIN_CONTROLLER_INFO_3W
found: boolean
crackMsgIn: DRS_MSG_CRACKREQ_V1
crackOut: DS_NAME_RESULTW
outV: DWORD
userAccountControl: set of integer

ValidateDRSInput(hDrs, 16)

msgIn := pmsgIn^.V1
infoLevel := msgIn.InfoLevel
domainName := msgIn.Domain

pdwOutVersion^ := infoLevel

if infoLevel = 1 then
  pmsgOut^.V1.cItems := 0
  pmsgOut^.V1.rItems := null
else if infoLevel = 2 then
  pmsgOut^.V2.cItems := 0
  pmsgOut^.V2.rItems := null
else if infoLevel = 3 then
  pmsgOut^.V3.cItems := 0
  pmsgOut^.V3.rItems := null
else if infoLevel = 0xFFFFFFFF then
  pmsgOut^.VFFFFFFFF.cItems := 0
  pmsgOut^.VFFFFFFFF.rItems := null
endif

if dwInVersion ≠ 1 then
  return ERROR_INVALID_PARAMETER
endif

if not (infoLevel in {1,2,3,0xFFFFFFFF}) then
  return ERROR_INVALID_PARAMETER
endif


if infoLevel = 0xFFFFFFFF then
  /* Enumerate the LDAP connections. */
  if not IsMemberOfBuiltinAdminGroup() then
    return ERROR_ACCESS_DENIED
  endif

  pmsgOut^.VFFFFFFFF.cItems := number(dc.ldapConnections)

  i := 0
  foreach lc in dc.ldapConnections
    pmsgOut^.VFFFFFFFF.rItems[i].IPAddress := lc.iPAddress
    pmsgOut^.VFFFFFFFF.rItems[i].NotificationCount := 
        lc.notificationCount
    pmsgOut^.VFFFFFFFF.rItems[i].secTimeConnected := 
        lc.secTimeConnected
    pmsgOut^.VFFFFFFFF.rItems[i].Flags := lc.flags
    pmsgOut^.VFFFFFFFF.rItems[i].TotalRequests := lc.totalRequests
    pmsgOut^.VFFFFFFFF.rItems[i].UserName := lc.userName
    pmsgOut^.VFFFFFFFF.rItems[i].Reserved1 := 0

    i := i + 1
  endfor

  return 0
endif

/* Verify that the given domain name matches the default domain NC.
 * First check if it is the nETBiosName or dNSHostName of the default
 * domain NC by searching for the crossRef object. If this doesn't 
 * find a match, call IDL_DRSCrackNames to check if the given 
 * domain name is a name for the default domain NC. */

crObj := select one v from children
    DescendantObject(ConfigNC(), "CN=Partitions,")
    where
      (v!dnsRoot = domainName or v!nETBiosName = domainName)
      and 
      v!nCName = DefaultNC()

found := (crObj ≠ null)

if not found then
  /* Not found; use IDL_DRSCrackNames to resolve the name. */
  crackMsgIn.dwFlags := 0
  crackMsgIn.formatOffered := DS_UNKNOWN_NAME
  crackMsgIn.formatDesired := DS_FQDN_1779_NAME
  crackMsgIn.cNames := 3
  crackMsgIn.rpNames[0] := domainName
  crackMsgIn.rpNames[1] := domainName + "\"
  crackMsgIn.rpNames[2] := domainName + "/"

  /* Call IDL_DRSCrackNames as a local procedure. */
  CrackNames(crackMsgIn, ADR(crackOut))
  
  i := 0
  while i < 3 and not found
    if crackOut.rItems[i].status = DS_NAME_NO_ERROR 
        then 
      if crackOut.rItems[i].pName = DefaultNC().dn 
          then
        found := true
      else 
        return ERROR_INVALID_PARAMETER
      endif
    endif
    i := i + 1
  endwhile
endif

if not found then 
  return ERROR_DS_OBJ_NOT_FOUND
endif

/* Enumerate the DCs in the domain. */
if infoLevel = 3 then
  /* client requests to return RODCs too */
  userAccountControl :=
      {ADS_UF_SERVER_TRUST_ACCOUNT, ADS_UF_PARTIAL_SECRETS_ACCOUNT}
else
  userAccountControl := {ADS_UF_SERVER_TRUST_ACCOUNT}
endif

dcSet := select all v from subtree DefaultNC() where 
     v!objectCategory = GetDefaultObjectCategory(computer) 
       and (userAccountControl ∩ v!userAccountControl ≠ null)

if infoLevel = 1 then
  pmsgOut^.V1.cItems := number(dcSet)

  i := 0
  foreach dcObj in dcSet
    rI1 := ADR(pmsgOut^.V1.rItems[i])

    rI1^.DnsHostName := dcObj!dNSHostName
    rI1^.ComputerObjectName := dcObj.dn
    /* sAMAccountName excluding the "$" at the end. */
    rI1^.NetbiosName := SubString(dcObj!sAMAccountName, 0,
        dcObj!samAccountName.length-1) 
    rI1^.fDsEnabled := true

    /* select a server object from the serverReferenceBL, it is 
       preferred that the server object has a child object with
       CN "NTDS Settings" */    
    svrObj := 
        select one v from all where v.dn in dcObj!serverReferenceBL 
              and DescendantObject(v, "CN=NTDS Settings") ≠ null
    if svrObj = null then
        svrObj := 
            select one v from all where v.dn in dcObj!serverReferenceBL
    endif
    if svrObj ≠ null then
      rI1^.ServerObjectName := svrObj.dn
      serversContainer :=
          select one o from all where o!objectGUID = svrObj!parent
      siteObj := serversContainer!parent
      rI1^.SiteObjectName := siteObj.dn
      dsaObj := DescendantObject(v, "CN=NTDS Settings,")
      rI1^.fIsPdc := (dsaObj = GetFSMORoleOwner(FSMO_PDC))
    endif
    i := i + 1
  endfor 
else
  if infoLevel = 2 then
    pmsgOut^.V2.cItems := number(dcSet)

    i := 0
    foreach dcObj in dcSet
      rI2 := ADR(pmsgOut^.V2.rItems[i])

      rI2^.DnsHostName := dcObj!dNSHostName
      rI2^.ComputerObjectName := dcObj.dn
      /* sAMAccountName excluding the "$" at the end. */
      rI2^.NetbiosName := SubString(dcObj!samAccountName, 0,
        dcObj!samAccountName.length-1) 
      rI2^.ComputerObjectGUID := dcObj.guid
      rI2^.fDsEnabled := true

      /* select a server object from the serverReferenceBL, it is 
         preferred that the server object has a child object with
         CN "NTDS Settings" */    
      svrObj := 
          select one v from all where v.dn in dcObj!serverReferenceBL 
                and DescendantObject(v, "CN=NTDS Settings") ≠ null
      if svrObj = null then
          svrObj := 
              select one v from all where v.dn in dcObj!serverReferenceBL
      endif
      if svrObj ≠ null then
        rI2^.ServerObjectName := svrObj.dn
        rI2^.ServerObjectGuid := svrObj.guid

      serversContainer :=
          select one o from all where o!objectGUID = svrObj!parent
      siteObj := serversContainer!parent

        rI2^.SiteObjectName := siteObj.dn
        rI2^.SiteObjectGUID := siteObj.guid
        dsaObj := DescendantObject(v, "CN=NTDS Settings,")
        rI2^.NtdsDsaObjectGUID := dsaObj.guid
        rI2^.fIsGc := (NTDSDSA_OPT_IS_GC in dsaObj!options)
        rI2^.fIsPdc := (dsaObj = GetFSMORoleOwner(FSMO_PDC))
      endif
      i := i + 1
    endfor

else
  /* infoLevel = 3 */
    pmsgOut^.V3.cItems := number(dcSet)

    i := 0
    foreach dcObj in dcSet
      rI3 := ADR(pmsgOut^.V3.rItems[i])

      rI3^.DnsHostName := dcObj!dNSHostName
      rI3^.ComputerObjectName := dcObj.dn
      /* sAMAccountName excluding the "$" at the end. */
      rI3^.NetbiosName := SubString(dcObj!samAccountName, 0,
          dcObj!samAccountName.length-1) 
      rI3^.ComputerObjectGUID := dcObj.guid
      rI3^.fDsEnabled := true

      /* select a server object from the serverReferenceBL, it is 
         preferred that the server object has a child object with
         CN "NTDS Settings" */    
      svrObj := 
          select one v from all where v.dn in dcObj!serverReferenceBL 
                and DescendantObject(v, "CN=NTDS Settings") ≠ null
      if svrObj = null then
          svrObj := 
              select one v from all where v.dn in dcObj!serverReferenceBL
      endif
      if svrObj ≠ null then
        rI3^.ServerObjectName := svrObj.dn
        rI3^.ServerObjectGuid := svrObj.guid

      serversContainer :=
          select one o from all where o!objectGUID = svrObj!parent
      siteObj := serversContainer!parent

        rI3^.SiteObjectName := siteObj.dn
        rI3^.SiteObjectGUID := siteObj.guid
        dsaObj := DescendantObject(v, "CN=NTDS Settings,")
        rI3^.NtdsDsaObjectGUID := dsaObj.guid
        rI3^.fIsGC := (NTDSDSA_OPT_IS_GC in dsaObj!options)
        rI3^.fIsPDC := (dsaObj = GetFSMORoleOwner(FSMO_PDC))
        rI3^.fIsRodc := ((ADS_UF_PARTIAL_SECRETS_ACCOUNT ∩
            dcObj!userAccountControl) ≠ null)
      endif
      i := i + 1
    endfor
  endif
endif

return 0
 
Show:
© 2014 Microsoft