ComputerName

Martin Wilck Martin.Wilck at Fujitsu-Siemens.com
Wed Nov 6 09:27:02 CST 2002


Patch: ComputerName.diff

Added files:
        dlls/kernel:    computername.c
Removed files:
        win32:          init.c
Modified files:
        dlls/kernel:    Makefile.in
                        kernel32.spec
        include:        winbase.h
        misc:           registry.c
        win32:          newfns.c

Log message: Martin Wilck <Martin.Wilck at Fujitsu-Siemens.com>:
        - Implement SetComputerName(), SetComputerNameEx(), GetComputerNameEx()
        - Allow setting NetBIOS ComputerName through registry.
        - Keep old behavior as default, using new config option to change.

License: X11.

Comment:

Alexandre said it's important not to break wine on machines that change
host name frequently (laptops, I guess). I found it impossible to realize this
without an additional config option. Of course if every app would do the right
thing, i.e. query ...Control\ActiveComputerName rather than ...\Control\ComputerName,
we'd have no problem - we could simply live without the ComputerName Registry entry
in the "use Unix name" case.

In any case, ComputerName is in the Registry after Wine's first run on a machine.
CVS wine simply ignores that setting on subsequent starts (questionable IMO).
With my patch, the setting is still ignored unless the "UseDnsComputerName" 
config option is explicitly set to "N".

diff -uN /dev/null dlls/kernel/computername.c
--- /dev/null	Thu Apr 11 16:25:15 2002
+++ dlls/kernel/computername.c	Tue Nov  5 20:25:11 2002
@@ -0,0 +1,555 @@
+/*
+ * Win32 kernel functions
+ *
+ * Copyright 1995 Martin von Loewis and Cameron Heide
+ * Copyright 1999 Peter Ganten
+ * Copyright 2002 Martin Wilck
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#include <stdlib.h>
+#include <errno.h>
+#include <netdb.h>
+
+#include "winbase.h"
+#include "winerror.h"
+#include "winnls.h" 
+#include "winternl.h"
+#include "wine/unicode.h"
+#include "wine/exception.h"
+#include "msvcrt/excpt.h"
+#include "wine/debug.h"
+
+
+WINE_DEFAULT_DEBUG_CHANNEL(computername);
+
+/* filter for page-fault exceptions */
+static WINE_EXCEPTION_FILTER(page_fault)
+{
+    if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
+        return EXCEPTION_EXECUTE_HANDLER;
+    return EXCEPTION_CONTINUE_SEARCH;
+}
+
+/*********************************************************************** 
+ *                    dns_gethostbyname (INTERNAL)
+ *
+ *  From hostname(1):
+ *  "The FQDN is the name gethostbyname(2) returns for the host name returned by gethostname(2)."
+ *
+ *  Wine can use this technique only if the thread-safe gethostbyname_r is available.
+ */
+#ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
+static BOOL dns_gethostbyname ( char *name, int *size )
+{
+    struct hostent* host = NULL;
+    char *extrabuf;
+    int ebufsize = 1024;
+    struct hostent hostentry;
+    int locerr = ENOBUFS, res = ENOMEM;
+
+    extrabuf = HeapAlloc( GetProcessHeap(), 0, ebufsize ) ;
+
+    while( extrabuf ) 
+    {
+        res = gethostbyname_r ( name, &hostentry, extrabuf, ebufsize, &host, &locerr );
+        if( res != ERANGE ) break;
+        ebufsize *= 2;
+        extrabuf = HeapReAlloc( GetProcessHeap(), 0, extrabuf, ebufsize ) ;
+    }
+    
+    if ( res )
+        WARN ("Error in gethostbyname_r %d (%d)\n", res, locerr);
+    else
+    {
+        size_t len = strlen ( host->h_name );
+        if ( len < *size )
+        {
+            strcpy ( name, host->h_name );
+            *size = len;
+        }
+        else
+        {
+            memcpy ( name, host->h_name, *size );
+            name[*size] = 0;
+            SetLastError ( ERROR_MORE_DATA );
+            res = 1;
+        }
+    }
+
+    HeapFree( GetProcessHeap(), 0, extrabuf );
+    return !res;
+}
+#else
+#  define dns_gethostbyname(name,size) 0
+#endif
+
+/*********************************************************************** 
+ *                     dns_fqdn (INTERNAL)
+ */
+static BOOL dns_fqdn ( char *name, int *size )
+{
+    if ( gethostname ( name, *size + 1 ) ) 
+    {
+        switch( errno )
+        {
+        case ENAMETOOLONG:
+            SetLastError ( ERROR_MORE_DATA );
+        default:
+            SetLastError ( ERROR_INVALID_PARAMETER );
+        }
+        return FALSE;
+    }
+
+    if ( !dns_gethostbyname ( name, size ) )
+        *size = strlen ( name );
+
+    return TRUE;
+}
+
+/*********************************************************************** 
+ *                     dns_hostname (INTERNAL)
+ */
+static BOOL dns_hostname ( char *name, int *size )
+{
+    char *c;
+    if ( ! dns_fqdn ( name, size ) ) return FALSE;
+    c = strchr ( name, '.' );
+    if (c)
+    {
+        *c = 0;
+        *size = (c - name);
+    }
+    return TRUE;
+}
+
+/*********************************************************************** 
+ *                     dns_domainname (INTERNAL)
+ */
+static BOOL dns_domainname ( char *name, int *size )
+{
+    char *c;
+    if ( !dns_fqdn ( name, size ) ) return FALSE;
+    c = strchr ( name, '.' );
+    if (c)
+    {
+        c += 1;
+        *size -= (c - name);
+        memmove ( name, c, *size + 1 );
+    }
+    return TRUE;
+}
+
+/***********************************************************************
+ *              GetComputerNameW         (KERNEL32.@)
+ */
+BOOL WINAPI GetComputerNameW(LPWSTR name,LPDWORD size)
+{
+    static const WCHAR ComputerW[] = {'M','a','c','h','i','n','e','\\',
+                                      'S','y','s','t','e','m','\\',
+                                      'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
+                                      'C','o','n','t','r','o','l','\\',
+                                      'C','o','m','p','u','t','e','r','N','a','m','e','\\',
+                                      'A','c','t','i','v','e','C','o','m','p','u','t','e','r','N','a','m','e',0};
+    static const WCHAR ComputerNameW[] = {'C','o','m','p','u','t','e','r','N','a','m','e',0};
+    UNICODE_STRING nameW, valueW;
+    OBJECT_ATTRIBUTES attr;
+    HKEY hkey;
+    NTSTATUS st;
+    char buf[offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data ) 
+             + (MAX_COMPUTERNAME_LENGTH + 1) * sizeof( WCHAR )];
+    DWORD len = sizeof( buf );
+    LPWSTR theName = (LPWSTR) (buf + offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data ));
+    BOOL ret;
+
+    TRACE ("%p %p\n", name, size);
+
+    attr.Length = sizeof(attr);
+    attr.RootDirectory = 0;
+    attr.ObjectName = &nameW;
+    attr.Attributes = 0;
+    attr.SecurityDescriptor = NULL;
+    attr.SecurityQualityOfService = NULL;
+    
+    RtlInitUnicodeString( &nameW, ComputerW );
+    st = NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr );
+    if ( st != STATUS_SUCCESS )
+    {
+        SetLastError ( RtlNtStatusToDosError ( st ) );
+        goto error;
+    }
+
+    RtlInitUnicodeString( &valueW, ComputerNameW );
+    st = NtQueryValueKey( hkey, &valueW, KeyValuePartialInformation, buf, len, &len );
+    if ( st != STATUS_SUCCESS)
+    {
+        SetLastError ( RtlNtStatusToDosError ( st ) );
+        goto close;
+    }
+    NtClose ( hkey );
+
+    len = (len -offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data )) / sizeof (WCHAR) - 1;
+    TRACE ("ComputerName is %s (length %lu)\n", debugstr_w ( theName ), len);
+
+    __TRY
+    {
+        if ( *size < len )
+        {
+            memcpy ( name, theName, *size * sizeof (WCHAR) );
+            name[*size] = 0;
+            *size = len;
+            SetLastError ( ERROR_MORE_DATA );
+            ret = FALSE;
+        }
+        else
+        {
+            memcpy ( name, theName, len * sizeof (WCHAR) );
+            name[len] = 0;
+            *size = len;
+            ret = TRUE;
+        }
+    }
+    __EXCEPT(page_fault)
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        ret =  FALSE;
+    }
+    __ENDTRY
+
+    return ret;
+
+close:
+    NtClose ( hkey );
+error:
+    WARN ( "Error %lu reading computer name from registry\n", GetLastError() );
+    return FALSE;
+
+}
+
+/***********************************************************************
+ *              GetComputerNameA         (KERNEL32.@)
+ */
+BOOL WINAPI GetComputerNameA(LPSTR name, LPDWORD size)
+{
+    WCHAR nameW[ MAX_COMPUTERNAME_LENGTH + 1 ];
+    DWORD sizeW = MAX_COMPUTERNAME_LENGTH;
+    int len;
+    BOOL ret;
+
+    if ( !GetComputerNameW (nameW, &sizeW) ) return FALSE;
+
+    len = WideCharToMultiByte ( CP_ACP, 0, nameW, sizeW, NULL, 0, NULL, 0 );
+    __TRY
+    {
+        if ( *size < len )
+        {
+            WideCharToMultiByte ( CP_ACP, 0, nameW, sizeW, name, *size, NULL, 0 );
+            name[*size] = 0;
+            *size = len;
+            SetLastError( ERROR_MORE_DATA );
+            ret = FALSE;
+        }
+        else 
+        {
+            WideCharToMultiByte ( CP_ACP, 0, nameW, sizeW, name, len, NULL, 0 );
+            name[len] = 0;
+            *size = len;
+            ret = TRUE;
+        }
+    }
+    __EXCEPT(page_fault)
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        ret = FALSE;
+    }
+    __ENDTRY
+
+    return ret;
+}
+
+/***********************************************************************
+ *              GetComputerNameExA         (KERNEL32.@)
+ */
+BOOL WINAPI GetComputerNameExA(COMPUTER_NAME_FORMAT type, LPSTR name, LPDWORD size)
+{
+    char buf[256];
+    int len = sizeof (buf), ret;
+    TRACE("%d, %p, %p\n", type, name, size);
+    switch( type )
+    {
+    case ComputerNameNetBIOS:
+    case ComputerNamePhysicalNetBIOS:
+        return GetComputerNameA (name, size);
+    case ComputerNameDnsHostname:
+    case ComputerNamePhysicalDnsHostname:
+        ret = dns_hostname (buf, &len);
+        break;
+    case ComputerNameDnsDomain:
+    case ComputerNamePhysicalDnsDomain:
+        ret = dns_domainname (buf, &len);
+        break;
+    case ComputerNameDnsFullyQualified:
+    case ComputerNamePhysicalDnsFullyQualified:
+        ret = dns_fqdn (buf, &len);
+        break;
+    default:
+        SetLastError (ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    if ( ret )
+    {
+        TRACE ("-> %s (%d)\n", debugstr_a (buf), len);
+        __TRY
+        {
+            if ( *size < len )
+            {
+                memcpy( name, buf, *size );
+                name[*size] = 0;
+                *size = len;
+                SetLastError( ERROR_MORE_DATA );
+                ret = FALSE;
+            }
+            else
+            {
+                memcpy( name, buf, len );
+                name[len] = 0;
+                *size = len;
+            }
+        }
+        __EXCEPT(page_fault)
+        {
+            SetLastError( ERROR_INVALID_PARAMETER );
+            ret = FALSE;
+        }
+        __ENDTRY
+    }
+
+    return ret;
+}
+
+
+/***********************************************************************
+ *              GetComputerNameExW         (KERNEL32.@)
+ */
+BOOL WINAPI GetComputerNameExW( COMPUTER_NAME_FORMAT type, LPWSTR name, LPDWORD size )
+{
+    char buf[256];
+    int len = sizeof (buf), ret;
+
+    TRACE("%d, %p, %p\n", type, name, size);
+    switch( type )
+    {
+    case ComputerNameNetBIOS:
+    case ComputerNamePhysicalNetBIOS:
+        return GetComputerNameW (name, size);
+    case ComputerNameDnsHostname:
+    case ComputerNamePhysicalDnsHostname:
+        ret = dns_hostname (buf, &len);
+        break;
+    case ComputerNameDnsDomain:
+    case ComputerNamePhysicalDnsDomain:
+        ret = dns_domainname (buf, &len);
+        break;
+    case ComputerNameDnsFullyQualified:
+    case ComputerNamePhysicalDnsFullyQualified:
+        ret = dns_fqdn (buf, &len);
+        break;
+    default:
+        SetLastError (ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    if ( ret )
+    {
+        TRACE ("-> %s (%d)\n", debugstr_a (buf), len);
+        __TRY
+        {
+            int len = MultiByteToWideChar( CP_ACP, 0, buf, len, NULL, 0 );
+            if ( *size < len )
+            {
+                MultiByteToWideChar( CP_ACP, 0, buf, len, name, *size );
+                name[*size] = 0;
+                *size = len;
+                SetLastError( ERROR_MORE_DATA );
+                ret = FALSE;
+            }
+            else
+            {
+                MultiByteToWideChar( CP_ACP, 0, buf, len, name, len );
+                name[len] = 0;
+                *size = len;
+            }
+        }
+        __EXCEPT(page_fault)
+        {
+            SetLastError( ERROR_INVALID_PARAMETER );
+            ret = FALSE;
+        }
+        __ENDTRY
+    }
+
+    return ret;
+}
+
+/******************************************************************************
+ * netbios_char (INTERNAL)
+ */
+static WCHAR netbios_char ( WCHAR wc )
+{
+    static const WCHAR special[] = {'!','@','#','$','%','^','&','\'',')','(','-','_','{','}','~'};
+    static const WCHAR deflt = '_';
+    int i;
+    
+    if ( isalnumW ( wc ) ) return wc;
+    for ( i = 0; i < sizeof (special); i++ )
+        if ( wc == special[i] ) return wc;
+    return deflt;
+}
+
+/******************************************************************************
+ * SetComputerNameW [KERNEL32.@]
+ *
+ * PARAMS
+ *    lpComputerName [I] Address of new computer name
+ *
+ * RETURNS STD
+ */
+BOOL WINAPI SetComputerNameW( LPCWSTR lpComputerName )
+{
+    static const WCHAR ComputerW[] = {'M','a','c','h','i','n','e','\\',
+                                      'S','y','s','t','e','m','\\',
+                                      'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
+                                      'C','o','n','t','r','o','l','\\',
+                                      'C','o','m','p','u','t','e','r','N','a','m','e','\\',
+                                      'C','o','m','p','u','t','e','r','N','a','m','e',0};
+    static const WCHAR ComputerNameW[] = {'C','o','m','p','u','t','e','r','N','a','m','e',0};
+    UNICODE_STRING nameW, valueW;
+    OBJECT_ATTRIBUTES attr;
+    HKEY hkey;
+    NTSTATUS st;
+    int plen = strlenW ( lpComputerName );
+    int i;
+
+    TRACE( "%s\n", debugstr_w (lpComputerName) );
+
+    /* Check parameter */
+    if ( plen > MAX_COMPUTERNAME_LENGTH ) 
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        goto error;
+    }
+    /* This is NT behaviour. Win 95/98 would coerce characters. */
+    for ( i = 0; i < plen; i++ )
+    {
+        WCHAR wc = lpComputerName[i];
+        if ( wc != netbios_char( wc ) )
+        {
+            SetLastError( ERROR_INVALID_PARAMETER );
+            goto error;
+        }
+    }
+
+    attr.Length = sizeof(attr);
+    attr.RootDirectory = 0;
+    attr.ObjectName = &nameW;
+    attr.Attributes = 0;
+    attr.SecurityDescriptor = NULL;
+    attr.SecurityQualityOfService = NULL;
+
+    RtlInitUnicodeString (&nameW, ComputerW);
+    st = NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr );
+    if ( st != STATUS_SUCCESS )
+    {
+        SetLastError( RtlNtStatusToDosError( st ) );
+        goto error;
+    }
+    RtlInitUnicodeString( &valueW, ComputerNameW );
+    st = NtSetValueKey( hkey, &valueW, 0, REG_SZ, lpComputerName, ( plen + 1) * sizeof(WCHAR) );
+    if ( st != STATUS_SUCCESS )
+    {
+        SetLastError( RtlNtStatusToDosError( st ) );
+        goto close;
+    }
+
+    NtClose( hkey );
+    TRACE( "ComputerName changed\n" );
+    return TRUE;
+
+close:
+    NtClose( hkey );
+    
+error:
+    TRACE( "error %lu\n", GetLastError() );
+    return FALSE;
+}
+
+/******************************************************************************
+ * SetComputerNameA [KERNEL32.@]
+ */
+BOOL WINAPI SetComputerNameA( LPCSTR lpComputerName )
+{
+    BOOL ret;
+    DWORD len = MultiByteToWideChar( CP_ACP, 0, lpComputerName, -1, NULL, 0 );
+    LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
+
+    MultiByteToWideChar( CP_ACP, 0, lpComputerName, -1, nameW, len );
+    ret = SetComputerNameW( nameW );
+    HeapFree( GetProcessHeap(), 0, nameW );
+    return ret;
+}
+
+/******************************************************************************
+ * SetComputerNameExW [KERNEL32.@]
+ *
+ */
+BOOL WINAPI SetComputerNameExW( COMPUTER_NAME_FORMAT type, LPCWSTR lpComputerName )
+{
+    TRACE("%d, %s\n", type, debugstr_w (lpComputerName));
+    switch( type )
+    {
+    case ComputerNameNetBIOS:
+    case ComputerNamePhysicalNetBIOS:
+        return SetComputerNameW( lpComputerName );
+    default:
+        SetLastError( ERROR_ACCESS_DENIED );
+        return FALSE;
+    }
+}
+
+/******************************************************************************
+ * SetComputerNameExA [KERNEL32.@]
+ *
+ */
+BOOL WINAPI SetComputerNameExA( COMPUTER_NAME_FORMAT type, LPCSTR lpComputerName )
+{
+    TRACE( "%d, %s\n", type, debugstr_a (lpComputerName) );
+    switch( type )
+    {
+    case ComputerNameNetBIOS:
+    case ComputerNamePhysicalNetBIOS:
+        return SetComputerNameA( lpComputerName );
+    default:
+        SetLastError( ERROR_ACCESS_DENIED );
+        return FALSE;
+    }
+}
Index: dlls/kernel/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/kernel/Makefile.in,v
retrieving revision 1.48
diff -u -r1.48 Makefile.in
--- dlls/kernel/Makefile.in	29 Oct 2002 21:26:42 -0000	1.48
+++ dlls/kernel/Makefile.in	5 Nov 2002 21:50:01 -0000
@@ -11,6 +11,7 @@
 C_SRCS = \
 	$(TOPOBJDIR)/ole/ole2nls.c \
 	comm.c \
+	computername.c \
 	console.c \
 	debugger.c \
 	editline.c \
Index: dlls/kernel/kernel32.spec
===================================================================
RCS file: /home/wine/wine/dlls/kernel/kernel32.spec,v
retrieving revision 1.67
diff -u -r1.67 kernel32.spec
--- dlls/kernel/kernel32.spec	29 Oct 2002 23:09:30 -0000	1.67
+++ dlls/kernel/kernel32.spec	5 Nov 2002 21:50:01 -0000
@@ -665,6 +665,8 @@
 @ stdcall SetCommTimeouts(long ptr) SetCommTimeouts
 @ stdcall SetComputerNameA(str) SetComputerNameA
 @ stdcall SetComputerNameW(wstr) SetComputerNameW
+@ stdcall SetComputerNameExA(long str) SetComputerNameExA
+@ stdcall SetComputerNameExW(long wstr) SetComputerNameExW
 @ stdcall SetConsoleActiveScreenBuffer(long) SetConsoleActiveScreenBuffer
 @ stdcall SetConsoleCP(long) SetConsoleCP
 @ stdcall SetConsoleCtrlHandler(ptr long) SetConsoleCtrlHandler
Index: include/winbase.h
===================================================================
RCS file: /home/wine/wine/include/winbase.h,v
retrieving revision 1.163
diff -u -r1.163 winbase.h
--- include/winbase.h	4 Nov 2002 22:43:24 -0000	1.163
+++ include/winbase.h	5 Nov 2002 21:50:02 -0000
@@ -1456,6 +1456,9 @@
 BOOL      WINAPI SetComputerNameA(LPCSTR);
 BOOL      WINAPI SetComputerNameW(LPCWSTR);
 #define     SetComputerName WINELIB_NAME_AW(SetComputerName)
+BOOL      WINAPI SetComputerNameExA(COMPUTER_NAME_FORMAT,LPCSTR);
+BOOL      WINAPI SetComputerNameExW(COMPUTER_NAME_FORMAT,LPCWSTR);
+#define     SetComputerNameEx WINELIB_NAME_AW(SetComputerNameEx)
 BOOL        WINAPI SetDefaultCommConfigA(LPCSTR,LPCOMMCONFIG,DWORD);
 BOOL        WINAPI SetDefaultCommConfigW(LPCWSTR,LPCOMMCONFIG,DWORD);
 #define     SetDefaultCommConfig WINELIB_NAME_AW(SetDefaultCommConfig)
Index: misc/registry.c
===================================================================
RCS file: /home/wine/wine/misc/registry.c,v
retrieving revision 1.118
diff -u -r1.118 registry.c
--- misc/registry.c	24 Sep 2002 03:07:17 -0000	1.118
+++ misc/registry.c	5 Nov 2002 21:50:02 -0000
@@ -1119,11 +1119,9 @@
  */
 static void _allocate_default_keys(void)
 {
-    HKEY hkey;
+    HKEY hkey, hkey1;
     OBJECT_ATTRIBUTES attr;
     UNICODE_STRING nameW, valueW;
-    WCHAR computer_name[200];
-    DWORD size = sizeof(computer_name)/sizeof(WCHAR);
 
     static const WCHAR StatDataW[] = {'D','y','n','D','a','t','a','\\',
                                       'P','e','r','f','S','t','a','t','s','\\',
@@ -1132,9 +1130,14 @@
                                       'S','y','s','t','e','m','\\',
                                       'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
                                       'C','o','n','t','r','o','l','\\',
-                                      'C','o','m','p','u','t','e','r','N','a','m','e','\\',
                                       'C','o','m','p','u','t','e','r','N','a','m','e',0};
+    static const WCHAR ActiveW[] =   {'A','c','t','i','v','e','C','o','m','p','u','t','e','r','N','a','m','e',0};
     static const WCHAR ComputerNameW[] = {'C','o','m','p','u','t','e','r','N','a','m','e',0};
+    static const char defaultname[] = "WINE";
+    char buf[offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data ) + (MAX_COMPUTERNAME_LENGTH + 1) * sizeof( WCHAR )];
+    DWORD len = sizeof( buf );
+    LPWSTR computer_name = (LPWSTR) (buf + offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data ));
+    NTSTATUS st;
 
     TRACE("(void)\n");
 
@@ -1161,17 +1164,83 @@
      * 					string	SysLocation
      * 						SysServices
      */
-    if (GetComputerNameW( computer_name, &size ))
+
+    /*
+     * In HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\ComputerName:
+     *
+     * Try to read Computername\ComputerName.
+     * If this fails, call gethostname() and use hostname part.
+     * If this also fails, use default.
+     * Then set both Computername\ComputerName and ActiveComputername\ComputerName.
+     *
+     * Compare this to GetComputerName()/SetComputerName() in dlls/kernel. 
+     */
+
+    RtlInitUnicodeString( &nameW, ComputerW );
+    st = NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL );
+    if ( st != STATUS_SUCCESS )
+        goto error;
+
+    attr.RootDirectory = hkey;
+    RtlInitUnicodeString( &nameW, ComputerNameW );
+    RtlInitUnicodeString( &valueW, ComputerNameW );
+
+    st = NtCreateKey( &hkey1, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL );
+    if ( st != STATUS_SUCCESS )
+        goto error;
+    
+    st = NtQueryValueKey( hkey1, &valueW, KeyValuePartialInformation, buf, len, &len );
+    switch( st )
+    {
+    case STATUS_SUCCESS:
+        len = (len - offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data ));
+        TRACE( "found in registry\n" );
+        break;
+    case STATUS_OBJECT_NAME_NOT_FOUND:
     {
-        RtlInitUnicodeString( &nameW, ComputerW );
-        if (!NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ))
+        char hbuf[256];
+        int hlen = sizeof (hbuf);
+        char *dot;
+        TRACE( "retrieving Unix host name\n" );
+        if ( gethostname ( hbuf, hlen ) )
         {
-            RtlInitUnicodeString( &valueW, ComputerNameW );
-            NtSetValueKey( hkey, &valueW, 0, REG_SZ, computer_name,
-                           (strlenW(computer_name) + 1) * sizeof(WCHAR) );
-            NtClose(hkey);
+            strcpy ( hbuf, defaultname );
+            WARN( "gethostname() error: %d, using host name %s\n", errno, hbuf );
         }
+        hbuf[MAX_COMPUTERNAME_LENGTH] = 0;
+        dot = strchr ( hbuf, '.' );
+        if ( dot ) *dot = 0;
+        hlen = strlen ( hbuf );
+        len = MultiByteToWideChar( CP_ACP, 0, hbuf, hlen + 1, computer_name, MAX_COMPUTERNAME_LENGTH + 1 )
+            * sizeof( WCHAR );
+        NtSetValueKey( hkey1, &valueW, 0, REG_SZ, computer_name, len );
+        break;
     }
+    default:
+        goto error;
+    }
+    
+    NtClose( hkey1 );
+    TRACE(" ComputerName: %s (%lu)\n", debugstr_w ( computer_name ), len / sizeof(WCHAR));
+
+    RtlInitUnicodeString( &nameW, ActiveW );
+    st = NtCreateKey( &hkey1, KEY_ALL_ACCESS, &attr, 0, NULL, REG_OPTION_VOLATILE, NULL );
+    if ( st != STATUS_SUCCESS )
+        goto error;
+    
+    st = NtSetValueKey( hkey1, &valueW, 0, REG_SZ, computer_name, len );
+    if ( st != STATUS_SUCCESS ) goto error;
+
+    NtClose( hkey1 );
+    NtClose( hkey );
+    TRACE( "success\n" );
+    return;
+
+error:
+    NtClose( hkey1 );
+    NtClose( hkey );
+    WARN( "status trying to set ComputerName: %lx\n", st );
+    SetLastError ( RtlNtStatusToDosError ( st ) );
 }
 
 #define REG_DONTLOAD -1
@@ -1741,7 +1810,6 @@
     RtlOpenCurrentUser( KEY_ALL_ACCESS, &hkey_current_user );
 
     _set_registry_levels(0,0,0);
-    _allocate_default_keys();
     if (PROFILE_GetWineIniBool(RegistryW, load_win_reg_filesW, 1))
         _load_windows_registry( hkey_local_machine, hkey_current_user, hkey_users_default );
     if (PROFILE_GetWineIniBool(RegistryW, load_global_reg_filesW, 1))
@@ -1749,6 +1817,7 @@
     _set_registry_levels(1,0,0);
     if (PROFILE_GetWineIniBool(RegistryW, load_home_reg_filesW, 1))
         _load_home_registry( hkey_local_machine, hkey_current_user, hkey_users_default );
+    _allocate_default_keys();
     _init_registry_saving( hkey_local_machine, hkey_current_user, hkey_users_default );
     NtClose(hkey_users_default);
     NtClose(hkey_current_user);
Index: win32/init.c
===================================================================
RCS file: /home/wine/wine/win32/init.c,v
retrieving revision 1.23
diff -u -r1.23 init.c
--- win32/init.c	17 Aug 2002 00:43:20 -0000	1.23
+++ win32/init.c	5 Nov 2002 21:50:03 -0000
@@ -1,108 +0,0 @@
-/*
- * Win32 kernel functions
- *
- * Copyright 1995 Martin von Loewis and Cameron Heide
- * 1999 Peter Ganten
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include "config.h"
-
-#include <string.h>
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-#include <stdlib.h>
-#include <errno.h>
-
-#include "winnls.h"
-#include "winbase.h"
-#include "winerror.h"
-#include "wine/exception.h"
-#include "msvcrt/excpt.h"
-#include "wine/debug.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(win32);
-
-/* filter for page-fault exceptions */
-static WINE_EXCEPTION_FILTER(page_fault)
-{
-    if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
-        return EXCEPTION_EXECUTE_HANDLER;
-    return EXCEPTION_CONTINUE_SEARCH;
-}
-
-/***********************************************************************
- *              GetComputerNameA         (KERNEL32.@)
- */
-BOOL WINAPI GetComputerNameA(LPSTR name,LPDWORD size)
-{
-    /* At least Win95OSR2 survives if size is not a pointer (NT crashes though) */
-    BOOL ret;
-    __TRY
-    {
-	char host_name[256];
-	TRACE("*size = %ld\n", *size);
-	ret = (gethostname(host_name, sizeof(host_name)) != -1);
-	if (ret)
-	{
-	    lstrcpynA(name, host_name, *size);
-	    *size = strlen(name);
-	}
-	else
-	    WARN("gethostname: %s\n", strerror(errno));
-    }
-    __EXCEPT(page_fault)
-    {
-      SetLastError( ERROR_INVALID_PARAMETER );
-      return FALSE;
-    }
-    __ENDTRY
-
-    TRACE("returning (%ld) %s\n", *size, debugstr_a(name));
-    return ret;
-}
-
-/***********************************************************************
- *              GetComputerNameW         (KERNEL32.@)
- */
-BOOL WINAPI GetComputerNameW(LPWSTR name,LPDWORD size)
-{
-    LPSTR nameA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, *size);
-    BOOL ret = GetComputerNameA(nameA,size);
-    /* FIXME: should set *size in Unicode chars */
-    if (ret) MultiByteToWideChar( CP_ACP, 0, nameA, -1, name, *size+1 );
-    HeapFree( GetProcessHeap(), 0, nameA );
-    return ret;
-}
-
-/***********************************************************************
- *              GetComputerNameExA         (KERNEL32.@)
- */
-BOOL WINAPI GetComputerNameExA(COMPUTER_NAME_FORMAT type, LPSTR name, LPDWORD size)
-{
-    FIXME("(%d, %p, %p) semi-stub!\n", type, name, size);
-    return GetComputerNameA(name, size);
-}
-
-/***********************************************************************
- *              GetComputerNameExW         (KERNEL32.@)
- */
-BOOL WINAPI GetComputerNameExW(COMPUTER_NAME_FORMAT type, LPWSTR name, LPDWORD size)
-{
-    FIXME("(%d, %p, %p) semi-stub!\n", type, name, size);
-    return GetComputerNameW(name, size);
-}
Index: win32/newfns.c
===================================================================
RCS file: /home/wine/wine/win32/newfns.c,v
retrieving revision 1.41
diff -u -r1.41 newfns.c
--- win32/newfns.c	21 Sep 2002 01:21:01 -0000	1.41
+++ win32/newfns.c	5 Nov 2002 21:50:03 -0000
@@ -287,36 +287,6 @@
 

 /******************************************************************************
- * SetComputerNameA [KERNEL32.@]
- */
-BOOL WINAPI SetComputerNameA( LPCSTR lpComputerName )
-{
-    BOOL ret;
-    DWORD len = MultiByteToWideChar( CP_ACP, 0, lpComputerName, -1, NULL, 0 );
-    LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
-
-    MultiByteToWideChar( CP_ACP, 0, lpComputerName, -1, nameW, len );
-    ret = SetComputerNameW( nameW );
-    HeapFree( GetProcessHeap(), 0, nameW );
-    return ret;
-}
-
-
-/******************************************************************************
- * SetComputerNameW [KERNEL32.@]
- *
- * PARAMS
- *    lpComputerName [I] Address of new computer name
- *
- * RETURNS STD
- */
-BOOL WINAPI SetComputerNameW( LPCWSTR lpComputerName )
-{
-    FIXME("(%s): stub\n", debugstr_w(lpComputerName));
-    return TRUE;
-}
-
-/******************************************************************************
  *		CreateIoCompletionPort (KERNEL32.@)
  */
 HANDLE WINAPI CreateIoCompletionPort(HANDLE hFileHandle,




More information about the wine-patches mailing list