From eaef76f041d529b5fb8cfe98b68c36baeab453cb Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Tue, 12 Nov 2013 10:04:51 +0100 Subject: [PATCH] netapi32: Add support for remote computers in NetServerGetInfo. --- configure | 68 +++++++++++++++ configure.ac | 7 ++ dlls/netapi32/netapi32.c | 184 +++++++++++++++++++++++++++++++++++---- include/config.h.in | 3 + 4 files changed, 247 insertions(+), 15 deletions(-) diff --git a/configure b/configure index 663de64c620..3942d45dd66 100755 --- a/configure +++ b/configure @@ -827,6 +827,7 @@ with_hal with_jpeg with_ldap with_mpg123 +with_netapi with_openal with_opencl with_opengl @@ -2038,6 +2039,7 @@ Optional Packages: --without-jpeg do not use JPEG --without-ldap do not use LDAP --without-mpg123 do not use the mpg123 library + --without-netapi do not use the Samba NetAPI library --without-openal do not use OpenAL --without-opencl do not use OpenCL --without-opengl do not use OpenGL @@ -3232,6 +3234,12 @@ if test "${with_mpg123+set}" = set; then : fi +# Check whether --with-netapi was given. +if test "${with_netapi+set}" = set; then : + withval=$with_netapi; +fi + + # Check whether --with-openal was given. if test "${with_openal+set}" = set; then : withval=$with_openal; if test "x$withval" = "xno"; then ac_cv_header_AL_al_h=no; ac_cv_header_OpenAL_al_h=no; fi @@ -12987,6 +12995,66 @@ _ACEOF fi +if test "x$with_netapi" != "xno" +then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -lnetapi" >&5 +$as_echo_n "checking for -lnetapi... " >&6; } +if ${ac_cv_lib_soname_netapi+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_soname_save_LIBS=$LIBS +LIBS="-lnetapi $LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char libnetapi_init (); +int +main () +{ +return libnetapi_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + case "$LIBEXT" in + dll) ac_cv_lib_soname_netapi=`$ac_cv_path_LDD conftest.exe | grep "netapi" | sed -e "s/dll.*/dll/"';2,$d'` ;; + dylib) ac_cv_lib_soname_netapi=`otool -L conftest$ac_exeext | grep "libnetapi\\.[0-9A-Za-z.]*dylib" | sed -e "s/^.*\/\(libnetapi\.[0-9A-Za-z.]*dylib\).*$/\1/"';2,$d'` ;; + *) ac_cv_lib_soname_netapi=`$READELF -d conftest$ac_exeext | grep "NEEDED.*libnetapi\\.$LIBEXT" | sed -e "s/^.*\\[\\(libnetapi\\.$LIBEXT[^ ]*\\)\\].*$/\1/"';2,$d'` + if test "x$ac_cv_lib_soname_netapi" = x; then : + ac_cv_lib_soname_netapi=`$LDD conftest$ac_exeext | grep "libnetapi\\.$LIBEXT" | sed -e "s/^.*\(libnetapi\.$LIBEXT[^ ]*\).*$/\1/"';2,$d'` +fi ;; + esac +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS=$ac_check_soname_save_LIBS +fi +if test "x$ac_cv_lib_soname_netapi" = "x"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 +$as_echo "not found" >&6; } + cat >>confdefs.h <<_ACEOF +#define SONAME_LIBNETAPI "libnetapi.$LIBEXT" +_ACEOF + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_soname_netapi" >&5 +$as_echo "$ac_cv_lib_soname_netapi" >&6; } + +cat >>confdefs.h <<_ACEOF +#define SONAME_LIBNETAPI "$ac_cv_lib_soname_netapi" +_ACEOF + + +fi +fi + test -n "$ALSALIBS" || enable_winealsa_drv=${enable_winealsa_drv:-no} test -n "$COREAUDIO" || enable_winecoreaudio_drv=${enable_winecoreaudio_drv:-no} test "x$ac_cv_member_oss_sysinfo_numaudioengines" = xyes || enable_wineoss_drv=${enable_wineoss_drv:-no} diff --git a/configure.ac b/configure.ac index 98220b237c7..106377ea161 100644 --- a/configure.ac +++ b/configure.ac @@ -57,6 +57,7 @@ AC_ARG_WITH(jpeg, AS_HELP_STRING([--without-jpeg],[do not use JPEG])) AC_ARG_WITH(ldap, AS_HELP_STRING([--without-ldap],[do not use LDAP]), [if test "x$withval" = "xno"; then ac_cv_header_ldap_h=no; ac_cv_header_lber_h=no; fi]) AC_ARG_WITH(mpg123, AS_HELP_STRING([--without-mpg123],[do not use the mpg123 library])) +AC_ARG_WITH(netapi, AS_HELP_STRING([--without-netapi],[do not use the Samba NetAPI library])) AC_ARG_WITH(openal, AS_HELP_STRING([--without-openal],[do not use OpenAL]), [if test "x$withval" = "xno"; then ac_cv_header_AL_al_h=no; ac_cv_header_OpenAL_al_h=no; fi]) AC_ARG_WITH(opencl, AS_HELP_STRING([--without-opencl],[do not use OpenCL]), @@ -1756,6 +1757,12 @@ fi dnl **** Check for libodbc **** WINE_CHECK_SONAME(odbc,SQLConnect,,[AC_DEFINE_UNQUOTED(SONAME_LIBODBC,["libodbc.$LIBEXT"])]) +dnl **** Check for libnetapi **** +if test "x$with_netapi" != "xno" +then + WINE_CHECK_SONAME(netapi,libnetapi_init,,[AC_DEFINE_UNQUOTED(SONAME_LIBNETAPI,["libnetapi.$LIBEXT"])]) +fi + dnl **** Disable unsupported winmm drivers **** test -n "$ALSALIBS" || enable_winealsa_drv=${enable_winealsa_drv:-no} test -n "$COREAUDIO" || enable_winecoreaudio_drv=${enable_winecoreaudio_drv:-no} diff --git a/dlls/netapi32/netapi32.c b/dlls/netapi32/netapi32.c index 313d1accaf6..e09c6cee61a 100644 --- a/dlls/netapi32/netapi32.c +++ b/dlls/netapi32/netapi32.c @@ -3,6 +3,7 @@ * Copyright 2003 Juan Lang * Copyright 2005,2006 Paul Vriens * Copyright 2006 Robert Reif + * Copyright 2013 Hans Leidekker for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,6 +21,8 @@ */ #include "config.h" +#include "wine/port.h" + #include #include #include @@ -49,11 +52,171 @@ #include "dsrole.h" #include "dsgetdc.h" #include "wine/debug.h" +#include "wine/library.h" #include "wine/list.h" #include "wine/unicode.h" WINE_DEFAULT_DEBUG_CHANNEL(netapi32); +static char *strdup_unixcp( const WCHAR *str ) +{ + char *ret; + int len = WideCharToMultiByte( CP_UNIXCP, 0, str, -1, NULL, 0, NULL, NULL ); + if ((ret = HeapAlloc( GetProcessHeap(), 0, len ))) + WideCharToMultiByte( CP_UNIXCP, 0, str, -1, ret, len, NULL, NULL ); + return ret; +} + +#ifdef SONAME_LIBNETAPI + +static void *libnetapi_handle; +static void *libnetapi_ctx; + +static DWORD (*plibnetapi_init)(void **); +static DWORD (*plibnetapi_free)(void *); +static DWORD (*plibnetapi_set_debuglevel)(void *, const char *); + +static NET_API_STATUS (*pNetApiBufferAllocate)(unsigned int, void **); +static NET_API_STATUS (*pNetApiBufferFree)(void *); +static NET_API_STATUS (*pNetServerGetInfo)(const char *, unsigned int, unsigned char **); + +static BOOL libnetapi_init(void) +{ + char buf[200]; + DWORD status; + + if (libnetapi_handle) return TRUE; + if (!(libnetapi_handle = wine_dlopen( SONAME_LIBNETAPI, RTLD_NOW, buf, sizeof(buf) ))) + { + WARN( "Failed to load libnetapi: %s\n", buf ); + return FALSE; + } + +#define LOAD_FUNCPTR(f) \ + if (!(p##f = wine_dlsym( libnetapi_handle, #f, buf, sizeof(buf) ))) \ + { \ + ERR( "Failed to load %s: %s\n", #f, buf ); \ + goto error; \ + } + + LOAD_FUNCPTR(libnetapi_init) + LOAD_FUNCPTR(libnetapi_free) + LOAD_FUNCPTR(libnetapi_set_debuglevel) + + LOAD_FUNCPTR(NetApiBufferAllocate) + LOAD_FUNCPTR(NetApiBufferFree) + LOAD_FUNCPTR(NetServerGetInfo) +#undef LOAD_FUNCPTR + + if ((status = plibnetapi_init( &libnetapi_ctx ))) + { + ERR( "Failed to initialize context %u\n", status ); + goto error; + } + if (TRACE_ON( netapi32 ) && (status = plibnetapi_set_debuglevel( libnetapi_ctx, "10" ))) + { + ERR( "Failed to set debug level %u\n", status ); + goto error; + } + return TRUE; + +error: + if (libnetapi_ctx) + { + plibnetapi_free( libnetapi_ctx ); + libnetapi_ctx = NULL; + } + wine_dlclose( libnetapi_handle, NULL, 0 ); + libnetapi_handle = NULL; + return FALSE; +} + +struct server_info_101 +{ + unsigned int sv101_platform_id; + const char *sv101_name; + unsigned int sv101_version_major; + unsigned int sv101_version_minor; + unsigned int sv101_type; + const char *sv101_comment; +}; + +static NET_API_STATUS server_info_101_from_samba( const unsigned char *buf, BYTE **bufptr ) +{ + SERVER_INFO_101 *ret; + struct server_info_101 *info = (struct server_info_101 *)buf; + DWORD len = 0; + WCHAR *ptr; + + if (info->sv101_name) len += MultiByteToWideChar( CP_UNIXCP, 0, info->sv101_name, -1, NULL, 0 ); + if (info->sv101_comment) len += MultiByteToWideChar( CP_UNIXCP, 0, info->sv101_comment, -1, NULL, 0 ); + if (!(ret = HeapAlloc( GetProcessHeap(), 0, sizeof(*ret) + (len * sizeof(WCHAR) )))) + return ERROR_OUTOFMEMORY; + + ptr = (WCHAR *)(ret + 1); + ret->sv101_platform_id = info->sv101_platform_id; + if (!info->sv101_name) ret->sv101_name = NULL; + else + { + ret->sv101_name = ptr; + ptr += MultiByteToWideChar( CP_UNIXCP, 0, info->sv101_name, -1, ptr, len ); + } + ret->sv101_version_major = info->sv101_version_major; + ret->sv101_version_minor = info->sv101_version_minor; + ret->sv101_type = info->sv101_type; + if (!info->sv101_comment) ret->sv101_comment = NULL; + else + { + ret->sv101_comment = ptr; + MultiByteToWideChar( CP_UNIXCP, 0, info->sv101_comment, -1, ptr, len ); + } + *bufptr = (BYTE *)ret; + return NERR_Success; +} + +static NET_API_STATUS server_info_from_samba( DWORD level, const unsigned char *buf, BYTE **bufptr ) +{ + switch (level) + { + case 101: return server_info_101_from_samba( buf, bufptr ); + default: + FIXME( "level %u not supported\n", level ); + return ERROR_NOT_SUPPORTED; + } +} + +static NET_API_STATUS server_getinfo( LMSTR servername, DWORD level, LPBYTE *bufptr ) +{ + NET_API_STATUS status; + char *server = NULL; + unsigned char *buf = NULL; + + if (servername && !(server = strdup_unixcp( servername ))) return ERROR_OUTOFMEMORY; + status = pNetServerGetInfo( server, level, &buf ); + HeapFree( GetProcessHeap(), 0, server ); + if (!status) + { + status = server_info_from_samba( level, buf, bufptr ); + pNetApiBufferFree( buf ); + } + return status; +} + +#else + +static BOOL libnetapi_init(void) +{ + return FALSE; +} + +static NET_API_STATUS server_getinfo( LMSTR servername, DWORD level, LPBYTE *bufptr ) +{ + ERR( "\n" ); + return ERROR_NOT_SUPPORTED; +} + +#endif /* SONAME_LIBNETAPI */ + /************************************************************ * NETAPI_IsLocalComputer * @@ -158,15 +321,15 @@ NET_API_STATUS WINAPI NetServerDiskEnum( NET_API_STATUS WINAPI NetServerGetInfo(LMSTR servername, DWORD level, LPBYTE* bufptr) { NET_API_STATUS ret; + BOOL local = NETAPI_IsLocalComputer( servername ); TRACE("%s %d %p\n", debugstr_w( servername ), level, bufptr ); - if (servername) + + if (!local) { - if (!NETAPI_IsLocalComputer(servername)) - { - FIXME("remote computers not supported\n"); - return ERROR_INVALID_LEVEL; - } + if (libnetapi_init()) return server_getinfo( servername, level, bufptr ); + FIXME( "remote computers not supported\n" ); + return ERROR_INVALID_LEVEL; } if (!bufptr) return ERROR_INVALID_PARAMETER; @@ -1809,15 +1972,6 @@ NET_API_STATUS WINAPI NetUserModalsGet( return NERR_Success; } -static char *strdup_unixcp( const WCHAR *str ) -{ - char *ret; - int len = WideCharToMultiByte( CP_UNIXCP, 0, str, -1, NULL, 0, NULL, NULL ); - if ((ret = HeapAlloc( GetProcessHeap(), 0, len ))) - WideCharToMultiByte( CP_UNIXCP, 0, str, -1, ret, len, NULL, NULL ); - return ret; -} - static NET_API_STATUS change_password_smb( LPCWSTR domainname, LPCWSTR username, LPCWSTR oldpassword, LPCWSTR newpassword ) { diff --git a/include/config.h.in b/include/config.h.in index 6422b5a1266..54dcebacaa6 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -1311,6 +1311,9 @@ /* Define to the soname of the libncurses library. */ #undef SONAME_LIBNCURSES +/* Define to the soname of the libnetapi library. */ +#undef SONAME_LIBNETAPI + /* Define to the soname of the libodbc library. */ #undef SONAME_LIBODBC