Enumeración de controladores de dominio
En versiones anteriores de Windows, una aplicación solo podía obtener un único controlador de dominio en un dominio llamando a DsGetDcName. No había ninguna manera de predecir qué controlador de dominio se recuperaría o para obtener una lista de los controladores de dominio. Windows permite a una aplicación enumerar los controladores de dominio de un dominio mediante las funciones DsGetDcOpen, DsGetDcNext y DsGetDcClose .
Para enumerar un controlador de dominio, llame a DsGetDcOpen. Esta función toma parámetros que definen el dominio para enumerar y otras opciones de enumeración. DsGetDcOpen proporciona un identificador de contexto de enumeración de dominio que se usa para identificar la operación de enumeración cuando se llama a DsGetDcNext y DsGetDcClose .
Se llama a la función DsGetDcNext con el identificador de contexto de enumeración de dominio para recuperar el siguiente controlador de dominio de la enumeración. La primera vez que se llama a esta función, se recupera el primer controlador de dominio de la enumeración. La segunda vez que se llama a esta función, se recupera el segundo controlador de dominio de la enumeración. Este proceso se repite hasta que DsGetDcNext devuelve ERROR_NO_MORE_ITEMS, que indica el final de la enumeración.
La función DsGetDcNext enumerará los controladores de dominio en dos grupos. El primer grupo contiene los controladores de dominio que cubren el sitio del equipo donde se ejecuta la función y el segundo grupo contiene los controladores de dominio que no cubren el sitio del equipo donde se ejecuta la función. Si se especifica la marca DS_NOTIFY_AFTER_SITE_RECORDS en el parámetro OptionFlags de DsGetDcOpen, la función DsGetDcNext devolverá ERROR_FILEMARK_DETECTED después de recuperar todos los controladores de dominio específicos del sitio. DsGetDcNext comenzará a enumerar el segundo grupo, que contiene todos los controladores de dominio del dominio, incluidos los controladores de dominio específicos del sitio contenidos en el primer grupo.
Los controladores de dominio que controlan el sitio del equipo donde se ejecuta la función se enumeran primero seguidos de los controladores de dominio que no cubren el sitio del equipo donde se ejecuta la función. Se dice que un controlador de dominio cubre un sitio si el controlador de dominio está configurado para residir en ese sitio o si el controlador de dominio reside en un sitio más cercano al sitio en cuestión en términos del costo de vínculo entre sitios configurado. Si hay controladores de dominio en el grupo de controladores de dominio que cubren y el grupo de controladores de dominio que no cubren el sitio del equipo, los controladores de dominio se devuelven dentro del grupo en orden de sus prioridades y pesos configurados que se especifican en DNS. Los controladores de dominio que tienen prioridad numérica más baja se devuelven primero dentro de un grupo. Si dentro de un grupo relacionado con el sitio hay un subgrupo de varios controladores de dominio con la misma prioridad, los controladores de dominio se devuelven en un orden aleatorio ponderado donde los controladores de dominio con mayor peso tienen más probabilidad de devolverse primero. El administrador de dominio configura los sitios, prioridades y pesos para lograr un rendimiento eficaz y equilibrio de carga entre varios controladores de dominio disponibles en el dominio. Por este motivo, las aplicaciones que usan las funciones DsGetDcOpen/DsGetDcNext/DsGetDcClose aprovechan automáticamente estas optimizaciones.
Cuando la enumeración está completa o ya no es necesaria, la enumeración debe cerrarse llamando a DsGetDcClose con el identificador de contexto de enumeración de dominio.
Para restablecer la enumeración, es necesario cerrar la enumeración actual llamando a DsGetDcClose y, a continuación, volver a abrir la enumeración llamando a DsGetDcOpen de nuevo.
Ejemplo
En el ejemplo de código siguiente se muestra cómo usar estas funciones para enumerar los controladores de dominio en el dominio local.
DWORD dwRet;
PDOMAIN_CONTROLLER_INFO pdcInfo;
// Get a domain controller for the domain this computer is on.
dwRet = DsGetDcName(NULL, NULL, NULL, NULL, 0, &pdcInfo);
if(ERROR_SUCCESS == dwRet)
{
HANDLE hGetDc;
// Open the enumeration.
dwRet = DsGetDcOpen( pdcInfo->DomainName,
DS_NOTIFY_AFTER_SITE_RECORDS,
NULL,
NULL,
NULL,
0,
&hGetDc);
if(ERROR_SUCCESS == dwRet)
{
LPTSTR pszDnsHostName;
/*
Enumerate each domain controller and print its name to the
debug window.
*/
while(TRUE)
{
ULONG ulSocketCount;
LPSOCKET_ADDRESS rgSocketAddresses;
dwRet = DsGetDcNext(
hGetDc,
&ulSocketCount,
&rgSocketAddresses,
&pszDnsHostName);
if(ERROR_SUCCESS == dwRet)
{
OutputDebugString(pszDnsHostName);
OutputDebugString(TEXT("\n"));
// Free the allocated string.
NetApiBufferFree(pszDnsHostName);
// Free the socket address array.
LocalFree(rgSocketAddresses);
}
else if(ERROR_NO_MORE_ITEMS == dwRet)
{
// The end of the list has been reached.
break;
}
else if(ERROR_FILEMARK_DETECTED == dwRet)
{
/*
DS_NOTIFY_AFTER_SITE_RECORDS was specified in
DsGetDcOpen and the end of the site-specific
records was reached.
*/
OutputDebugString(
TEXT("End of site-specific domain controllers\n"));
continue;
}
else
{
// Some other error occurred.
break;
}
}
// Close the enumeration.
DsGetDcClose(hGetDc);
}
// Free the DOMAIN_CONTROLLER_INFO structure.
NetApiBufferFree(pdcInfo);
}