Перечисление контроллеров домена
В более ранних версиях Windows приложение может получить только один контроллер домена в домене, вызвав DsGetDcName. Не было способа предсказать, какой контроллер домена будет извлечен или получить список контроллеров домена. Windows позволяет приложению перечислять контроллеры домена в домене с помощью функций DsGetDcOpen, DsGetDcNext и DsGetDcClose.
Чтобы перечислить контроллер домена, вызовите DsGetDcOpen. Эта функция принимает параметры, определяющие домен для перечисления и других параметров перечисления. DsGetDcOpen предоставляет дескриптор контекста перечисления домена, который используется для идентификации операции перечисления при вызове DsGetDcNext и DsGetDcClose.
Функция DsGetDcNext вызывается с помощью контекста перечисления домена, чтобы получить следующий контроллер домена в перечислении. При первом вызове этой функции извлекается первый контроллер домена в перечислении. Во второй раз, когда эта функция вызывается, извлекается второй контроллер домена в перечислении. Этот процесс повторяется, пока DsGetDcNext не возвращает ERROR_NO_MORE_ITEMS, что указывает конец перечисления.
Функция DsGetDcNext перечисляет контроллеры домена в двух группах. Первая группа содержит контроллеры домена, охватывающие сайт компьютера, где выполняется функция, а вторая группа содержит контроллеры домена, не охватывающие сайт компьютера, где выполняется функция. Если флаг DS_NOTIFY_AFTER_SITE_RECORDS указан в параметре OptionFlags в DsGetDcOpen, функция DsGetDcNext вернет ERROR_FILEMARK_DETECTED после получения всех контроллеров домена, относящихся к сайту. Затем DsGetDcNext начнет перечисление второй группы, которая содержит все контроллеры домена в домене, включая контроллеры домена, относящиеся к сайту, содержащиеся в первой группе.
Контроллеры домена, обрабатывающие сайт компьютера, где выполняется функция, сначала перечисляются контроллерами домена, которые не охватывают сайт компьютера, где выполняется функция. Как сообщается, контроллер домена охватывает сайт, если контроллер домена настроен на расположение этого сайта или если контроллер домена находится на сайте, который ближе всего к сайту с точки зрения настроенной стоимости связи между сайтами. Если в группе контроллеров домена, охватывающих и группу контроллеров домена, не охватывающих сайт компьютера, контроллеры домена возвращаются в группе в порядке их настроенных приоритетов и весов, указанных в DNS. Контроллеры домена, имеющие более низкий числовой приоритет, возвращаются в группе. Если в группе, связанной с сайтом, существует подгруппа нескольких контроллеров домена с одинаковым приоритетом, контроллеры домена возвращаются в взвешенного случайного порядка, где контроллеры домена с более высоким весом имеют большую вероятность возврата. Сайты, приоритеты и весы настраиваются администратором домена для обеспечения эффективной производительности и балансировки нагрузки между несколькими контроллерами домена, доступными в домене. Из-за этого приложения, использующие функции DsGetDcOpen/dsGetDcNext/DsGetDcClose, автоматически используют эти оптимизации.
Когда перечисление завершено или больше не требуется, перечисление должно быть закрыто путем вызова DsGetDcClose с дескриптором контекста перечисления домена.
Чтобы сбросить перечисление, необходимо закрыть текущее перечисление путем вызова DsGetDcClose , а затем повторно открыть перечисление, вызвав DsGetDcOpen еще раз.
Пример
В следующем примере кода показано, как использовать эти функции для перечисления контроллеров домена в локальном домене.
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);
}