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.<14>
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