[PATCH 3/4] mountmgr.sys: Add support for querying DHCP parameters on macOS.

Hans Leidekker hans at codeweavers.com
Tue Nov 19 07:44:59 CST 2019


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 configure.ac                  |   3 +
 dlls/mountmgr.sys/Makefile.in |   2 +-
 dlls/mountmgr.sys/diskarb.c   | 167 ++++++++++++++++++++++++++++++++++
 3 files changed, 171 insertions(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index 64721e9644..22ce5f33a3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -436,6 +436,8 @@ AC_CHECK_HEADERS(\
 	OpenCL/opencl.h \
 	QuickTime/ImageCompression.h \
 	Security/Security.h \
+	SystemConfiguration/SCDynamicStoreCopyDHCPInfo.h \
+	SystemConfiguration/SCNetworkConfiguration.h \
 	alias.h \
 	arpa/inet.h \
 	arpa/nameser.h \
@@ -759,6 +761,7 @@ case $host_os in
     AC_SUBST(APPLICATIONSERVICES_LIBS,"-framework ApplicationServices")
     AC_SUBST(CORESERVICES_LIBS,"-framework CoreServices")
     AC_SUBST(APPKIT_LIBS,"-framework AppKit")
+    AC_SUBST(SYSTEMCONFIGURATION_LIBS,"-framework SystemConfiguration")
 
     WINELOADER_LDFLAGS="-Wl,-pie,-pagezero_size,0x1000,-sectcreate,__TEXT,__info_plist,wine_info.plist"
 
diff --git a/dlls/mountmgr.sys/Makefile.in b/dlls/mountmgr.sys/Makefile.in
index 738f071390..e229164280 100644
--- a/dlls/mountmgr.sys/Makefile.in
+++ b/dlls/mountmgr.sys/Makefile.in
@@ -3,7 +3,7 @@ IMPORTS   = uuid advapi32 ntoskrnl
 DELAYIMPORTS = user32 iphlpapi
 EXTRADLLFLAGS = -Wl,--subsystem,native
 EXTRAINCL = $(DBUS_CFLAGS) $(HAL_CFLAGS)
-EXTRALIBS = $(DISKARBITRATION_LIBS)
+EXTRALIBS = $(DISKARBITRATION_LIBS) $(SYSTEMCONFIGURATION_LIBS) $(CORESERVICES_LIBS)
 
 C_SRCS = \
 	dbus.c \
diff --git a/dlls/mountmgr.sys/diskarb.c b/dlls/mountmgr.sys/diskarb.c
index 9a7616ecc6..66c121e114 100644
--- a/dlls/mountmgr.sys/diskarb.c
+++ b/dlls/mountmgr.sys/diskarb.c
@@ -29,8 +29,18 @@
 #ifdef HAVE_DISKARBITRATION_DISKARBITRATION_H
 #include <DiskArbitration/DiskArbitration.h>
 #endif
+#if defined(HAVE_SYSTEMCONFIGURATION_SCDYNAMICSTORECOPYDHCPINFO_H) && defined(HAVE_SYSTEMCONFIGURATION_SCNETWORKCONFIGURATION_H)
+#include <SystemConfiguration/SCDynamicStoreCopyDHCPInfo.h>
+#include <SystemConfiguration/SCNetworkConfiguration.h>
+#endif
 
 #include "mountmgr.h"
+#define USE_WS_PREFIX
+#include "winsock2.h"
+#include "ws2ipdef.h"
+#include "nldef.h"
+#include "netioapi.h"
+#include "dhcpcsdk.h"
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(mountmgr);
@@ -152,3 +162,160 @@ void initialize_diskarbitration(void)
 }
 
 #endif  /* HAVE_DISKARBITRATION_DISKARBITRATION_H */
+
+#if defined(HAVE_SYSTEMCONFIGURATION_SCDYNAMICSTORECOPYDHCPINFO_H) && defined(HAVE_SYSTEMCONFIGURATION_SCNETWORKCONFIGURATION_H)
+
+static UInt8 map_option( ULONG option )
+{
+    switch (option)
+    {
+    case OPTION_SUBNET_MASK:         return 1;
+    case OPTION_ROUTER_ADDRESS:      return 3;
+    case OPTION_HOST_NAME:           return 12;
+    case OPTION_DOMAIN_NAME:         return 15;
+    case OPTION_BROADCAST_ADDRESS:   return 28;
+    case OPTION_MSFT_IE_PROXY:       return 252;
+    default:
+        FIXME( "unhandled option %u\n", option );
+        return 0;
+    }
+}
+
+#define IF_NAMESIZE 16
+static BOOL map_adapter_name( const WCHAR *name, WCHAR *unix_name, DWORD len )
+{
+    WCHAR buf[IF_NAMESIZE];
+    UNICODE_STRING str;
+    GUID guid;
+
+    RtlInitUnicodeString( &str, name );
+    if (!RtlGUIDFromString( &str, &guid ))
+    {
+        NET_LUID luid;
+        if (ConvertInterfaceGuidToLuid( &guid, &luid ) ||
+            ConvertInterfaceLuidToNameW( &luid, buf, ARRAY_SIZE(buf) )) return FALSE;
+
+        name = buf;
+    }
+    if (lstrlenW( name ) >= len) return FALSE;
+    lstrcpyW( unix_name, name );
+    return TRUE;
+}
+
+static CFStringRef find_service_id( const WCHAR *adapter )
+{
+    SCPreferencesRef prefs;
+    SCNetworkSetRef set = NULL;
+    CFArrayRef services = NULL;
+    CFStringRef id, ret = NULL;
+    WCHAR unix_name[IF_NAMESIZE];
+    CFIndex i;
+
+    if (!map_adapter_name( adapter, unix_name, ARRAY_SIZE(unix_name) )) return NULL;
+    if (!(prefs = SCPreferencesCreate( NULL, CFSTR("mountmgr.sys"), NULL ))) return NULL;
+    if (!(set = SCNetworkSetCopyCurrent( prefs ))) goto done;
+    if (!(services = SCNetworkSetCopyServices( set ))) goto done;
+
+    for (i = 0; i < CFArrayGetCount( services ); i++)
+    {
+        SCNetworkServiceRef service;
+        UniChar buf[IF_NAMESIZE] = {0};
+        CFStringRef name;
+
+        service = CFArrayGetValueAtIndex( services, i );
+        name = SCNetworkInterfaceGetBSDName( SCNetworkServiceGetInterface(service) );
+        if (CFStringGetLength( name ) < ARRAY_SIZE( buf ))
+        {
+            CFStringGetCharacters( name, CFRangeMake(0, CFStringGetLength(name)), buf );
+            if (!lstrcmpW( buf, unix_name ) && (id = SCNetworkServiceGetServiceID( service )))
+            {
+                ret = CFStringCreateCopy( NULL, id );
+                break;
+            }
+        }
+    }
+
+done:
+    if (services) CFRelease( services );
+    if (set) CFRelease( set );
+    CFRelease( prefs );
+    return ret;
+}
+
+ULONG get_dhcp_request_param( const WCHAR *adapter, struct mountmgr_dhcp_request_param *param, char *buf, ULONG offset,
+                              ULONG size )
+{
+    CFStringRef service_id = find_service_id( adapter );
+    CFDictionaryRef dict;
+    CFDataRef value;
+    DWORD ret = 0;
+    CFIndex len;
+
+    param->offset = 0;
+    param->size   = 0;
+
+    if (!service_id) return 0;
+    if (!(dict = SCDynamicStoreCopyDHCPInfo( NULL, service_id )))
+    {
+        CFRelease( service_id );
+        return 0;
+    }
+    CFRelease( service_id );
+    if (!(value = DHCPInfoGetOptionData( dict, map_option(param->id) )))
+    {
+        CFRelease( dict );
+        return 0;
+    }
+    len = CFDataGetLength( value );
+
+    switch (param->id)
+    {
+    case OPTION_SUBNET_MASK:
+    case OPTION_ROUTER_ADDRESS:
+    case OPTION_BROADCAST_ADDRESS:
+    {
+        DWORD *ptr = (DWORD *)(buf + offset);
+        if (len == sizeof(*ptr) && size >= sizeof(*ptr))
+        {
+            CFDataGetBytes( value, CFRangeMake(0, len), (UInt8 *)ptr );
+            param->offset = offset;
+            param->size   = sizeof(*ptr);
+            TRACE( "returning %08x\n", *ptr );
+        }
+        ret = sizeof(*ptr);
+        break;
+    }
+    case OPTION_HOST_NAME:
+    case OPTION_DOMAIN_NAME:
+    case OPTION_MSFT_IE_PROXY:
+    {
+        char *ptr = buf + offset;
+        if (size >= len)
+        {
+            CFDataGetBytes( value, CFRangeMake(0, len), (UInt8 *)ptr );
+            param->offset = offset;
+            param->size   = len;
+            TRACE( "returning %s\n", debugstr_an(ptr, len) );
+        }
+        ret = len;
+        break;
+    }
+    default:
+        FIXME( "option %u not supported\n", param->id );
+        break;
+    }
+
+    CFRelease( dict );
+    return ret;
+}
+
+#elif !defined(SONAME_LIBDBUS_1)
+
+ULONG get_dhcp_request_param( const WCHAR *adapter, struct mountmgr_dhcp_request_param *param, char *buf, ULONG offset,
+                              ULONG size )
+{
+    FIXME( "support not compiled in\n" );
+    return 0;
+}
+
+#endif
-- 
2.20.1




More information about the wine-devel mailing list