Dmitry Timoshkov : netapi32: Implement DsGetDcNameW.

Alexandre Julliard julliard at winehq.org
Wed Mar 11 17:38:32 CDT 2020


Module: wine
Branch: master
Commit: 510bea7692971aa31a0b2cca6b6aa9550610b3c4
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=510bea7692971aa31a0b2cca6b6aa9550610b3c4

Author: Dmitry Timoshkov <dmitry at baikal.ru>
Date:   Tue Mar 10 15:42:42 2020 +0800

netapi32: Implement DsGetDcNameW.

Signed-off-by: Dmitry Timoshkov <dmitry at baikal.ru>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/netapi32/Makefile.in |   2 +-
 dlls/netapi32/nbt.c       |   3 +
 dlls/netapi32/netapi32.c  | 149 +++++++++++++++++++++++++++++++++++++++++++---
 include/dsgetdc.h         |   7 +++
 4 files changed, 153 insertions(+), 8 deletions(-)

diff --git a/dlls/netapi32/Makefile.in b/dlls/netapi32/Makefile.in
index 23da4838f9..13065578ef 100644
--- a/dlls/netapi32/Makefile.in
+++ b/dlls/netapi32/Makefile.in
@@ -1,7 +1,7 @@
 EXTRADEFS = -D_SVRAPI_
 MODULE    = netapi32.dll
 IMPORTLIB = netapi32
-IMPORTS   = rpcrt4 iphlpapi ws2_32 advapi32
+IMPORTS   = rpcrt4 iphlpapi ws2_32 advapi32 dnsapi
 
 C_SRCS = \
 	nbcmdqueue.c \
diff --git a/dlls/netapi32/nbt.c b/dlls/netapi32/nbt.c
index 4816630334..9c2a731a94 100644
--- a/dlls/netapi32/nbt.c
+++ b/dlls/netapi32/nbt.c
@@ -1437,12 +1437,15 @@ static const WCHAR Config_NetworkW[] = { 'S','o','f','t','w','a','r','e','\\',
 /* Initializes global variables and registers the NetBT transport */
 void NetBTInit(void)
 {
+    WSADATA wsa_data;
     HKEY hKey;
     NetBIOSTransport transport;
     LONG ret;
 
     TRACE("\n");
 
+    WSAStartup(MAKEWORD(2, 2), &wsa_data);
+
     gEnableDNS = TRUE;
     gBCastQueries = BCAST_QUERIES;
     gBCastQueryTimeout = BCAST_QUERY_TIMEOUT;
diff --git a/dlls/netapi32/netapi32.c b/dlls/netapi32/netapi32.c
index d6554aa676..f86e033c21 100644
--- a/dlls/netapi32/netapi32.c
+++ b/dlls/netapi32/netapi32.c
@@ -4,6 +4,7 @@
  * Copyright 2005,2006 Paul Vriens
  * Copyright 2006 Robert Reif
  * Copyright 2013 Hans Leidekker for CodeWeavers
+ * Copyright 2020 Dmitry Timoshkov
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -37,6 +38,9 @@
 #define WIN32_NO_STATUS
 #include "windef.h"
 #include "winbase.h"
+#include "winsock2.h"
+#include "ws2ipdef.h"
+#include "windns.h"
 #include "lm.h"
 #include "lmaccess.h"
 #include "atsvc.h"
@@ -56,9 +60,12 @@
 #include "wine/library.h"
 #include "wine/list.h"
 #include "wine/unicode.h"
+#include "initguid.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
 
+DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
+
 static char *strdup_unixcp( const WCHAR *str )
 {
     char *ret;
@@ -3033,14 +3040,142 @@ NET_API_STATUS WINAPI I_BrowserQueryEmulatedDomains(
     return ERROR_NOT_SUPPORTED;
 }
 
-DWORD WINAPI DsGetDcNameW(LPCWSTR ComputerName, LPCWSTR AvoidDCName,
- GUID* DomainGuid, LPCWSTR SiteName, ULONG Flags,
- PDOMAIN_CONTROLLER_INFOW *DomainControllerInfo)
+#define NS_MAXDNAME 1025
+
+static DWORD get_dc_info(const WCHAR *domain, WCHAR *dc, WCHAR *ip)
 {
-    FIXME("(%s, %s, %s, %s, %08x, %p): stub\n", debugstr_w(ComputerName),
-     debugstr_w(AvoidDCName), debugstr_guid(DomainGuid),
-     debugstr_w(SiteName), Flags, DomainControllerInfo);
-    return ERROR_CALL_NOT_IMPLEMENTED;
+    static const WCHAR pfx[] = {'_','l','d','a','p','.','_','t','c','p','.','d','c','.','_','m','s','d','c','s','.',0};
+    WCHAR name[NS_MAXDNAME];
+    DWORD ret, size;
+    DNS_RECORDW *rec;
+
+    lstrcpyW(name, pfx);
+    lstrcatW(name, domain);
+
+    ret = DnsQuery_W(name, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &rec, NULL);
+    TRACE("DnsQuery_W(%s) => %d\n", wine_dbgstr_w(domain), ret);
+    if (ret == ERROR_SUCCESS)
+    {
+        TRACE("target %s, port %d\n", wine_dbgstr_w(rec->Data.Srv.pNameTarget), rec->Data.Srv.wPort);
+
+        lstrcpynW(dc, rec->Data.Srv.pNameTarget, NS_MAXDNAME);
+        DnsRecordListFree(rec, DnsFreeRecordList);
+
+        /* IPv4 */
+        ret = DnsQuery_W(dc, DNS_TYPE_A, DNS_QUERY_STANDARD, NULL, &rec, NULL);
+        TRACE("DnsQuery_W(%s) => %d\n", wine_dbgstr_w(dc), ret);
+        if (ret == ERROR_SUCCESS)
+        {
+            SOCKADDR_IN addr;
+
+            addr.sin_family = AF_INET;
+            addr.sin_port = 0;
+            addr.sin_addr.s_addr = rec->Data.A.IpAddress;
+            size = IP6_ADDRESS_STRING_LENGTH;
+            ret = WSAAddressToStringW((SOCKADDR *)&addr, sizeof(addr), NULL, ip, &size);
+            if (!ret)
+                TRACE("WSAAddressToStringW => %d, %s\n", ret, wine_dbgstr_w(ip));
+
+            DnsRecordListFree(rec, DnsFreeRecordList);
+
+            return ret;
+        }
+
+        /* IPv6 */
+        ret = DnsQuery_W(dc, DNS_TYPE_AAAA, DNS_QUERY_STANDARD, NULL, &rec, NULL);
+        TRACE("DnsQuery_W(%s) => %d\n", wine_dbgstr_w(dc), ret);
+        if (ret == ERROR_SUCCESS)
+        {
+            SOCKADDR_IN6 addr;
+
+            addr.sin6_family = AF_INET6;
+            addr.sin6_port = 0;
+            addr.sin6_scope_id = 0;
+            memcpy(addr.sin6_addr.s6_addr, &rec->Data.AAAA.Ip6Address, sizeof(rec->Data.AAAA.Ip6Address));
+            size = IP6_ADDRESS_STRING_LENGTH;
+            ret = WSAAddressToStringW((SOCKADDR *)&addr, sizeof(addr), NULL, ip, &size);
+            if (!ret)
+                TRACE("WSAAddressToStringW => %d, %s\n", ret, wine_dbgstr_w(ip));
+
+            DnsRecordListFree(rec, DnsFreeRecordList);
+        }
+    }
+
+    return ret;
+}
+
+DWORD WINAPI DsGetDcNameW(LPCWSTR computer, LPCWSTR domain, GUID *domain_guid,
+                          LPCWSTR site, ULONG flags, PDOMAIN_CONTROLLER_INFOW *dc_info)
+{
+    static const WCHAR pfxW[] = {'\\','\\'};
+    static const WCHAR default_site_nameW[] = {'D','e','f','a','u','l','t','-','F','i','r','s','t','-','S','i','t','e','-','N','a','m','e',0};
+    NTSTATUS status;
+    POLICY_DNS_DOMAIN_INFO *dns_domain_info = NULL;
+    DOMAIN_CONTROLLER_INFOW *info;
+    WCHAR dc[NS_MAXDNAME], ip[IP6_ADDRESS_STRING_LENGTH];
+    DWORD size;
+
+    FIXME("(%s, %s, %s, %s, %08x, %p): semi-stub\n", debugstr_w(computer),
+        debugstr_w(domain), debugstr_guid(domain_guid), debugstr_w(site), flags, dc_info);
+
+    if (!dc_info) return ERROR_INVALID_PARAMETER;
+
+    if (!domain)
+    {
+        LSA_OBJECT_ATTRIBUTES attrs;
+        LSA_HANDLE lsa;
+
+        memset(&attrs, 0, sizeof(attrs));
+        attrs.Length = sizeof(attrs);
+        status = LsaOpenPolicy(NULL, &attrs, POLICY_VIEW_LOCAL_INFORMATION, &lsa);
+        if (status)
+            return LsaNtStatusToWinError(status);
+
+        status = LsaQueryInformationPolicy(lsa, PolicyDnsDomainInformation, (void **)&dns_domain_info);
+        LsaClose(lsa);
+        if (status)
+            return LsaNtStatusToWinError(status);
+
+        domain = dns_domain_info->DnsDomainName.Buffer;
+    }
+
+    status = get_dc_info(domain, dc, ip);
+    if (status) return status;
+
+    size = sizeof(DOMAIN_CONTROLLER_INFOW) + lstrlenW(domain) * sizeof(WCHAR) +
+            sizeof(pfxW) * 2 + (lstrlenW(dc) + 1 + lstrlenW(ip) + 1) * sizeof(WCHAR) +
+            lstrlenW(domain) * sizeof(WCHAR) /* assume forest == domain */ +
+            sizeof(default_site_nameW) * 2;
+    status = NetApiBufferAllocate(size, (void **)&info);
+    if (status != NERR_Success)
+    {
+        LsaFreeMemory(dns_domain_info);
+        return ERROR_NOT_ENOUGH_MEMORY;
+    }
+
+    info->DomainControllerName = (WCHAR *)(info + 1);
+    memcpy(info->DomainControllerName, pfxW, sizeof(pfxW));
+    lstrcpyW(info->DomainControllerName + 2, dc);
+    info->DomainControllerAddress = (WCHAR *)((char *)info->DomainControllerName + (strlenW(info->DomainControllerName) + 1) * sizeof(WCHAR));
+    memcpy(info->DomainControllerAddress, pfxW, sizeof(pfxW));
+    lstrcpyW(info->DomainControllerAddress + 2, ip);
+    info->DomainControllerAddressType = DS_INET_ADDRESS;
+    info->DomainGuid = dns_domain_info ? dns_domain_info->DomainGuid : GUID_NULL /* FIXME */;
+    info->DomainName = (WCHAR *)((char *)info->DomainControllerAddress + (strlenW(info->DomainControllerAddress) + 1) * sizeof(WCHAR));
+    lstrcpyW(info->DomainName, domain);
+    info->DnsForestName = (WCHAR *)((char *)info->DomainName + (lstrlenW(info->DomainName) + 1) * sizeof(WCHAR));
+    lstrcpyW(info->DnsForestName, domain);
+    info->DcSiteName = (WCHAR *)((char *)info->DnsForestName + (lstrlenW(info->DnsForestName) + 1) * sizeof(WCHAR));
+    lstrcpyW(info->DcSiteName, default_site_nameW);
+    info->ClientSiteName = (WCHAR *)((char *)info->DcSiteName + sizeof(default_site_nameW));
+    lstrcpyW(info->ClientSiteName, default_site_nameW);
+    info->Flags = DS_DNS_DOMAIN_FLAG | DS_DNS_FOREST_FLAG;
+
+    LsaFreeMemory(dns_domain_info);
+
+    *dc_info = info;
+
+    return ERROR_SUCCESS;
 }
 
 DWORD WINAPI DsGetDcNameA(LPCSTR ComputerName, LPCSTR AvoidDCName,
diff --git a/include/dsgetdc.h b/include/dsgetdc.h
index c53fcc299a..856912212f 100644
--- a/include/dsgetdc.h
+++ b/include/dsgetdc.h
@@ -23,6 +23,13 @@
 extern "C" {
 #endif
 
+#define DS_INET_ADDRESS                 1
+#define DS_NETBIOS_ADDRESS              2
+
+#define DS_DNS_CONTROLLER_FLAG          0x20000000
+#define DS_DNS_DOMAIN_FLAG              0x40000000
+#define DS_DNS_FOREST_FLAG              0x80000000
+
 #define DS_FORCE_REDISCOVERY            0x00000001
 #define DS_DIRECTORY_SERVICE_REQUIRED   0x00000010
 #define DS_DIRECTORY_SERVICE_PREFERRED  0x00000020




More information about the wine-cvs mailing list