获取域控制器名称

时间:2018-01-31 12:33:04

标签: c++ c winapi windows-10 domaincontroller

摘要:我想使用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:12


RSOP 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?: No


USER 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 tutorial中的代码:

#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;
}

我只注释掉命令行参数以使它们保持为NULL:

    // lpServer = argv[1];
    // lpDomain = argv[2];
     

指向常量字符串的指针,该字符串指定DNS或NetBIOS名称   要执行该功能的远程服务器的名称。 如果这样   参数为NULL,使用本地计算机。

     

指向常量字符串的指针,该字符串指定域的名称。   域名必须是NetBIOS域名(例如,   微软)。 NetGetDCName不支持DNS样式名称(for   例如,microsoft.com)。 如果此参数为NULL,则为该函数   返回主域的域控制器的名称。

我收到错误:

  

NERR_DCNotFound

为什么命令行参数给我一个域名,但是WinAPI失败了,还是两个名字相似的东西?

谢谢!

1 个答案:

答案 0 :(得分:1)

您可以先使用LsaQueryInformationPolicyPolicyDnsDomainInformation拨打PolicyPrimaryDomainInformation来获取计算机primary domain

如果POLICY_DNS_DOMAIN_INFOPOLICY_PRIMARY_DOMAIN_INFO Sid 成员(主域的SID )为0 - 这意味着系统没有主域名。在这种情况下,我们需要查询account domain

  

在不属于网络且因此没有主要网络的系统上   域,帐户域用于容纳提供的所有帐户   访问计算机。

为此我们需要使用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