Резюме: Я хочу получить имя контроллера домена, используя только WinAPI, компьютер не находится в сети, что может привести к сбою моего кода с помощью «NERR_DCNotFound»?
Я пытаюсь получить имя контроллера домена, частью которого будет сетевой компьютер.
Компьютер, с которым я экспериментирую, — это просто персональный компьютер, я никогда не настраиваю контроллер домена или что-либо, что может быть затруднить тестирование? На данный момент он находится внутри VirtualBox, выходящий из Интернета.
Когда я запускаю это из командной строки, я получаю следующий вывод, который, по-видимому, содержит доменное имя:
C:\Users\lone>gpresult /Z
Microsoft (R) Windows (R) Operating System Group Policy Result tool v2.0
© 2016 Microsoft Corporation. All rights reserved.
Created on 31/01/2018 at 12:24:12RSOP data for DESKTOP-I53IU6C\lone on DESKTOP-I53IU6C : Logging Mode
---------------------------------------------------------------------
OS Configuration: Standalone Workstation
OS Version: 10.0.10586
Site Name: N/A
Roaming Profile: N/A
Local Profile: C:\Users\lone
Connected over a slow link?: NoUSER SETTINGS
--------------
Last time Group Policy was applied: 31/01/2018 at 10:30:38
Group Policy was applied from: N/A
Group Policy slow link threshold: 500 kbps
Domain Name: DESKTOP-I53IU6C
Domain Type: <Local Computer>
Applied Group Policy Objects
-----------------------------
N/A
The following GPOs were not applied because they were filtered out
-------------------------------------------------------------------
Local Group Policy
Filtering: Not Applied (Empty)
The user is a part of the following security groups
---------------------------------------------------
None
Everyone
Local account and member of Administrators group
HelpLibraryUpdaters
BUILTIN\Administrators
BUILTIN\Users
NT AUTHORITY\INTERACTIVE
CONSOLE LOGON
NT AUTHORITY\Authenticated Users
This Organization
Local account
LOCAL
NTLM Authentication
High Mandatory Level
The user has the following security privileges
----------------------------------------------Resultant Set Of Policies for User
-----------------------------------
Software Installations
----------------------
N/A
Logon Scripts
-------------
N/A
Logoff Scripts
--------------
N/A
Public Key Policies
-------------------
N/A
Administrative Templates
------------------------
N/A
Folder Redirection
------------------
N/A
Internet Explorer Browser User Interface
----------------------------------------
N/A
Internet Explorer Connection
----------------------------
N/A
Internet Explorer URLs
----------------------
N/A
Internet Explorer Security
--------------------------
N/A
Internet Explorer Programs
--------------------------
N/A
Я получаю это из вышеприведенного вывода:
Доменное имя: DESKTOP-I53IU6C
Может быть, я путаю доменное имя с именем контроллера домена?
Я копирую и вставляю код из MSDN руководство:
#ifndef UNICODE
#define UNICODE
#endif
#include <stdio.h>
#include <stdlib.h> // for _wtoi function
#include <assert.h>
#include <windows.h>
#include <lm.h>
// Need to link with netapi32.lib
#pragma comment(lib, "netapi32.lib")
int wmain(int argc, wchar_t * argv[])
{
NET_API_STATUS nStatus;
LPCWSTR lpServer = NULL;
LPCWSTR lpDomain = NULL;
LPCWSTR lpDcName = NULL;
if (argc != 3 ) {
wprintf(L"Usage: %ws <ServerName> <DomainName>\n",
argv[0]);
wprintf(L" %ws Myserver Domain\n", argv[0]);
exit(1);
}
// lpServer = argv[1];
// lpDomain = argv[2];
wprintf(L"Calling NetGetDCName with parameters\n");
wprintf(L" lpServer = %ws\n", lpServer);
wprintf(L" lpDomain = %ws\n", lpDomain);
//
// Call the NetGetDCName function
//
nStatus = NetGetDCName(lpServer, lpDomain, (LPBYTE *) &lpDcName);
//
// If the call succeeds,
//
if (nStatus == NERR_Success) {
wprintf(L"NetGetDCName was successful\n", nStatus);
wprintf(L"DC Name = %ws\n", lpDcName);
// Need to free the returned buffer
nStatus = NetApiBufferFree( (LPVOID) lpDcName);
if (nStatus != NERR_Success)
wprintf(L"NetApiBufferFree failed with error: %lu (0x%lx)\n",
nStatus, nStatus);
} else {
wprintf(L"NetGetDCName failed with error: %lu (0x%lx)\n", nStatus,
nStatus);
wprintf(L" Error = ");
switch (nStatus) {
case ERROR_INVALID_PARAMETER:
wprintf(L"ERROR_INVALID_PARAMETER\n");
break;
case ERROR_NO_SUCH_DOMAIN:
wprintf(L"ERROR_NO_SUCH_DOMAIN\n");
break;
case ERROR_NOT_SUPPORTED:
wprintf(L"ERROR_NOT_SUPPORTED\n");
break;
case ERROR_BAD_NETPATH:
wprintf(L"ERROR_BAD_NETPATH\n");
break;
case ERROR_INVALID_COMPUTERNAME:
wprintf(L"ERROR_INVALID_COMPUTERNAME\n");
break;
case DNS_ERROR_INVALID_NAME_CHAR:
wprintf(L"DNS_ERROR_INVALID_NAME_CHAR\n");
break;
case DNS_ERROR_NON_RFC_NAME:
wprintf(L"DNS_ERROR_NON_RFC_NAME\n");
break;
case ERROR_INVALID_NAME:
wprintf(L"ERROR_INVALID_NAME\n");
break;
case NERR_DCNotFound:
wprintf(L"NERR_DCNotFound\n");
break;
case NERR_WkstaNotStarted:
wprintf(L"NERR_WkstaNotStarted\n");
break;
case RPC_S_SERVER_UNAVAILABLE:
wprintf(L"RPC_S_SERVER_UNAVAILABLE\n");
break;
case RPC_E_REMOTE_DISABLED:
wprintf(L"RPC_E_REMOTE_DISABLED\n");
break;
default:
wprintf(L"Other error, see Winerror.h or lmerr.h)\n");
break;
}
}
return nStatus;
}
Я только закомментировал аргументы командной строки, чтобы они оставались пустыми:
// lpServer = argv[1]; // lpDomain = argv[2];
Указатель на постоянную строку, которая задает имя DNS или NetBIOS
удаленного сервера, на котором должна выполняться функция. Если это
параметр NULL, локальный компьютер используется.Указатель на постоянную строку, которая задает имя домена.
Доменное имя должно быть доменным именем NetBIOS (например,
Microsoft). NetGetDCName не поддерживает имена в стиле DNS (для
Например, microsoft.com). Если этот параметр равен NULL, функция
возвращает имя контроллера домена для основного домена.
Ошибка, которую я получаю:
NERR_DCNotFound
Почему аргумент командной строки дал мне доменное имя, но WinAPI не работает, или это две разные вещи с одинаковым именем?
Спасибо!
Вы можете использовать звонок LsaQueryInformationPolicy
сначала с PolicyDnsDomainInformation
или же PolicyPrimaryDomainInformation
для получения компьютера основной домен.
если Sid член POLICY_DNS_DOMAIN_INFO
или же POLICY_PRIMARY_DOMAIN_INFO
(SID основного домена) равен 0 — это означает, что система не имеет основного домена. в этом случае нам нужен запрос домен аккаунта:
В системе, которая не является частью сети и поэтому не имеет первичной
домен, домен учетной записи используется для размещения всех учетных записей, которые предоставляют
доступ к компьютеру.
для этого нам нужно позвонить LsaQueryInformationPolicy
с PolicyAccountDomainInformation
и получил POLICY_ACCOUNT_DOMAIN_INFO
состав
#include <Ntsecapi.h>
NTSTATUS PrintDomainName()
{
LSA_HANDLE PolicyHandle;
static LSA_OBJECT_ATTRIBUTES oa = { sizeof(oa) };
NTSTATUS status = LsaOpenPolicy(0, &oa, POLICY_VIEW_LOCAL_INFORMATION, &PolicyHandle);
if (LSA_SUCCESS(status))
{
union {
PPOLICY_DNS_DOMAIN_INFO ppddi;
PPOLICY_ACCOUNT_DOMAIN_INFO ppadi;
};
if (LSA_SUCCESS(status = LsaQueryInformationPolicy(PolicyHandle, PolicyDnsDomainInformation, (void**)&ppddi)))
{
if (ppddi->Sid)
{
DbgPrint("DnsDomainName: %wZ\n", &ppddi->DnsDomainName);
}
else
{
DbgPrint("%wZ: not domain controller !!\n", &ppddi->Name);
status = -1;
}
LsaFreeMemory(ppddi);
if (0 > status)
{
if (LSA_SUCCESS(status = LsaQueryInformationPolicy(PolicyHandle, PolicyAccountDomainInformation, (void**)&ppadi)))
{
DbgPrint("DomainName: %wZ\n", &ppadi->DomainName);
LsaFreeMemory(ppadi);
}
}
}
LsaClose(PolicyHandle);
}
return status;
}
я получил следующий вывод:
WORKGROUP: not domain controller !!
DomainName: DESKTOP-2N5ODLB
Других решений пока нет …