2 * Win32 kernel functions
4 * Copyright 1995 Martin von Loewis and Cameron Heide
5 * Copyright 1999 Peter Ganten
6 * Copyright 2002 Martin Wilck
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39 #include "wine/unicode.h"
40 #include "wine/exception.h"
42 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(computername);
47 /* Wine config options */
48 static const WCHAR NetworkW[] = {'N','e','t','w','o','r','k',0};
49 static const WCHAR UseDNSW[] = {'U','s','e','D','n','s','C','o','m','p','u','t','e','r','N','a','m','e',0};
51 /* Registry key and value names */
52 static const WCHAR ComputerW[] = {'M','a','c','h','i','n','e','\\',
53 'S','y','s','t','e','m','\\',
54 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
55 'C','o','n','t','r','o','l','\\',
56 'C','o','m','p','u','t','e','r','N','a','m','e',0};
57 static const WCHAR ActiveComputerNameW[] = {'A','c','t','i','v','e','C','o','m','p','u','t','e','r','N','a','m','e',0};
58 static const WCHAR ComputerNameW[] = {'C','o','m','p','u','t','e','r','N','a','m','e',0};
60 static const char default_ComputerName[] = "WINE";
62 /* filter for page-fault exceptions */
63 static WINE_EXCEPTION_FILTER(page_fault)
65 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
66 return EXCEPTION_EXECUTE_HANDLER;
67 return EXCEPTION_CONTINUE_SEARCH;
70 /***********************************************************************
71 * dns_gethostbyname (INTERNAL)
74 * "The FQDN is the name gethostbyname(2) returns for the host name returned by gethostname(2)."
76 * Wine can use this technique only if the thread-safe gethostbyname_r is available.
78 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
79 static BOOL dns_gethostbyname ( char *name, int *size )
81 struct hostent* host = NULL;
84 struct hostent hostentry;
85 int locerr = ENOBUFS, res = ENOMEM;
87 extrabuf = HeapAlloc( GetProcessHeap(), 0, ebufsize ) ;
91 res = gethostbyname_r ( name, &hostentry, extrabuf, ebufsize, &host, &locerr );
92 if( res != ERANGE ) break;
94 extrabuf = HeapReAlloc( GetProcessHeap(), 0, extrabuf, ebufsize ) ;
98 WARN ("Error in gethostbyname_r %d (%d)\n", res, locerr);
101 size_t len = strlen ( host->h_name );
104 strcpy ( name, host->h_name );
109 memcpy ( name, host->h_name, *size );
111 SetLastError ( ERROR_MORE_DATA );
116 HeapFree( GetProcessHeap(), 0, extrabuf );
120 # define dns_gethostbyname(name,size) 0
123 /***********************************************************************
124 * dns_fqdn (INTERNAL)
126 static BOOL dns_fqdn ( char *name, int *size )
128 if ( gethostname ( name, *size + 1 ) )
133 SetLastError ( ERROR_MORE_DATA );
135 SetLastError ( ERROR_INVALID_PARAMETER );
140 if ( !dns_gethostbyname ( name, size ) )
141 *size = strlen ( name );
146 /***********************************************************************
147 * dns_hostname (INTERNAL)
149 static BOOL dns_hostname ( char *name, int *size )
152 if ( ! dns_fqdn ( name, size ) ) return FALSE;
153 c = strchr ( name, '.' );
162 /***********************************************************************
163 * dns_domainname (INTERNAL)
165 static BOOL dns_domainname ( char *name, int *size )
168 if ( ! dns_fqdn ( name, size ) ) return FALSE;
169 c = strchr ( name, '.' );
174 memmove ( name, c, *size + 1 );
179 /***********************************************************************
180 * _init_attr (INTERNAL)
182 inline static void _init_attr ( OBJECT_ATTRIBUTES *attr, UNICODE_STRING *name )
184 attr->Length = sizeof (OBJECT_ATTRIBUTES);
185 attr->RootDirectory = 0;
186 attr->ObjectName = name;
187 attr->Attributes = 0;
188 attr->SecurityDescriptor = NULL;
189 attr->SecurityQualityOfService = NULL;
192 /***********************************************************************
193 * COMPUTERNAME_Init (INTERNAL)
195 void COMPUTERNAME_Init (void)
197 HKEY hkey = INVALID_HANDLE_VALUE, hsubkey = INVALID_HANDLE_VALUE;
198 OBJECT_ATTRIBUTES attr;
199 UNICODE_STRING nameW;
200 char buf[offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data ) + (MAX_COMPUTERNAME_LENGTH + 1) * sizeof( WCHAR )];
201 DWORD len = sizeof( buf );
202 LPWSTR computer_name = (LPWSTR) (buf + offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data ));
203 NTSTATUS st = STATUS_INTERNAL_ERROR;
206 _init_attr ( &attr, &nameW );
208 RtlInitUnicodeString( &nameW, ComputerW );
209 if ( ( st = NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ) ) != STATUS_SUCCESS )
212 attr.RootDirectory = hkey;
213 RtlInitUnicodeString( &nameW, ComputerNameW );
214 if ( (st = NtCreateKey( &hsubkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ) ) != STATUS_SUCCESS )
217 st = NtQueryValueKey( hsubkey, &nameW, KeyValuePartialInformation, buf, len, &len );
219 if ( st == STATUS_OBJECT_NAME_NOT_FOUND ||
220 ( st == STATUS_SUCCESS && PROFILE_GetWineIniBool( NetworkW, UseDNSW, 1 ) ) )
223 int hlen = sizeof (hbuf);
225 TRACE( "retrieving Unix host name\n" );
226 if ( gethostname ( hbuf, hlen ) )
228 strcpy ( hbuf, default_ComputerName );
229 WARN( "gethostname() error: %d, using host name %s\n", errno, hbuf );
231 hbuf[MAX_COMPUTERNAME_LENGTH] = 0;
232 dot = strchr ( hbuf, '.' );
234 hlen = strlen ( hbuf );
235 len = MultiByteToWideChar( CP_ACP, 0, hbuf, hlen + 1, computer_name, MAX_COMPUTERNAME_LENGTH + 1 )
237 if ( NtSetValueKey( hsubkey, &nameW, 0, REG_SZ, computer_name, len ) != STATUS_SUCCESS )
238 WARN ( "failed to set ComputerName" );
240 else if ( st == STATUS_SUCCESS)
242 len = (len - offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data ));
243 TRACE( "found in registry\n" );
248 TRACE(" ComputerName: %s (%lu)\n", debugstr_w ( computer_name ), len / sizeof(WCHAR));
250 RtlInitUnicodeString( &nameW, ActiveComputerNameW );
251 if ( ( st = NtCreateKey( &hsubkey, KEY_ALL_ACCESS, &attr, 0, NULL, REG_OPTION_VOLATILE, NULL ) )
255 RtlInitUnicodeString( &nameW, ComputerNameW );
256 st = NtSetValueKey( hsubkey, &nameW, 0, REG_SZ, computer_name, len );
262 if ( st == STATUS_SUCCESS )
263 TRACE( "success\n" );
266 WARN( "status trying to set ComputerName: %lx\n", st );
267 SetLastError ( RtlNtStatusToDosError ( st ) );
272 /***********************************************************************
273 * GetComputerNameW (KERNEL32.@)
275 BOOL WINAPI GetComputerNameW(LPWSTR name,LPDWORD size)
277 UNICODE_STRING nameW;
278 OBJECT_ATTRIBUTES attr;
279 HKEY hkey = INVALID_HANDLE_VALUE, hsubkey = INVALID_HANDLE_VALUE;
280 char buf[offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data ) + (MAX_COMPUTERNAME_LENGTH + 1) * sizeof( WCHAR )];
281 DWORD len = sizeof( buf );
282 LPWSTR theName = (LPWSTR) (buf + offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data ));
283 NTSTATUS st = STATUS_INVALID_PARAMETER;
285 TRACE ("%p %p\n", name, size);
287 _init_attr ( &attr, &nameW );
288 RtlInitUnicodeString( &nameW, ComputerW );
289 if ( ( st = NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr ) ) != STATUS_SUCCESS )
292 attr.RootDirectory = hkey;
293 RtlInitUnicodeString( &nameW, ActiveComputerNameW );
294 if ( ( st = NtOpenKey( &hsubkey, KEY_ALL_ACCESS, &attr ) ) != STATUS_SUCCESS )
297 RtlInitUnicodeString( &nameW, ComputerNameW );
298 if ( ( st = NtQueryValueKey( hsubkey, &nameW, KeyValuePartialInformation, buf, len, &len ) )
302 len = (len -offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data )) / sizeof (WCHAR) - 1;
303 TRACE ("ComputerName is %s (length %lu)\n", debugstr_w ( theName ), len);
309 memcpy ( name, theName, *size * sizeof (WCHAR) );
312 st = STATUS_MORE_ENTRIES;
316 memcpy ( name, theName, len * sizeof (WCHAR) );
324 st = STATUS_INVALID_PARAMETER;
332 if ( st == STATUS_SUCCESS )
336 SetLastError ( RtlNtStatusToDosError ( st ) );
337 WARN ( "Status %lu reading computer name from registry\n", st );
342 /***********************************************************************
343 * GetComputerNameA (KERNEL32.@)
345 BOOL WINAPI GetComputerNameA(LPSTR name, LPDWORD size)
347 WCHAR nameW[ MAX_COMPUTERNAME_LENGTH + 1 ];
348 DWORD sizeW = MAX_COMPUTERNAME_LENGTH;
352 if ( !GetComputerNameW (nameW, &sizeW) ) return FALSE;
354 len = WideCharToMultiByte ( CP_ACP, 0, nameW, sizeW, NULL, 0, NULL, 0 );
359 WideCharToMultiByte ( CP_ACP, 0, nameW, sizeW, name, *size, NULL, 0 );
362 SetLastError( ERROR_MORE_DATA );
367 WideCharToMultiByte ( CP_ACP, 0, nameW, sizeW, name, len, NULL, 0 );
375 SetLastError( ERROR_INVALID_PARAMETER );
383 /***********************************************************************
384 * GetComputerNameExA (KERNEL32.@)
386 BOOL WINAPI GetComputerNameExA(COMPUTER_NAME_FORMAT type, LPSTR name, LPDWORD size)
389 int len = sizeof (buf), ret;
390 TRACE("%d, %p, %p\n", type, name, size);
393 case ComputerNameNetBIOS:
394 case ComputerNamePhysicalNetBIOS:
395 return GetComputerNameA (name, size);
396 case ComputerNameDnsHostname:
397 case ComputerNamePhysicalDnsHostname:
398 ret = dns_hostname (buf, &len);
400 case ComputerNameDnsDomain:
401 case ComputerNamePhysicalDnsDomain:
402 ret = dns_domainname (buf, &len);
404 case ComputerNameDnsFullyQualified:
405 case ComputerNamePhysicalDnsFullyQualified:
406 ret = dns_fqdn (buf, &len);
409 SetLastError (ERROR_INVALID_PARAMETER);
415 TRACE ("-> %s (%d)\n", debugstr_a (buf), len);
420 memcpy( name, buf, *size );
423 SetLastError( ERROR_MORE_DATA );
428 memcpy( name, buf, len );
436 SetLastError( ERROR_INVALID_PARAMETER );
446 /***********************************************************************
447 * GetComputerNameExW (KERNEL32.@)
449 BOOL WINAPI GetComputerNameExW( COMPUTER_NAME_FORMAT type, LPWSTR name, LPDWORD size )
452 int len = sizeof (buf), ret;
454 TRACE("%d, %p, %p\n", type, name, size);
457 case ComputerNameNetBIOS:
458 case ComputerNamePhysicalNetBIOS:
459 return GetComputerNameW (name, size);
460 case ComputerNameDnsHostname:
461 case ComputerNamePhysicalDnsHostname:
462 ret = dns_hostname (buf, &len);
464 case ComputerNameDnsDomain:
465 case ComputerNamePhysicalDnsDomain:
466 ret = dns_domainname (buf, &len);
468 case ComputerNameDnsFullyQualified:
469 case ComputerNamePhysicalDnsFullyQualified:
470 ret = dns_fqdn (buf, &len);
473 SetLastError (ERROR_INVALID_PARAMETER);
479 TRACE ("-> %s (%d)\n", debugstr_a (buf), len);
482 int lenW = MultiByteToWideChar( CP_ACP, 0, buf, len, NULL, 0 );
485 MultiByteToWideChar( CP_ACP, 0, buf, len, name, *size );
488 SetLastError( ERROR_MORE_DATA );
493 MultiByteToWideChar( CP_ACP, 0, buf, len, name, lenW );
501 SetLastError( ERROR_INVALID_PARAMETER );
510 /******************************************************************************
511 * netbios_char (INTERNAL)
513 static WCHAR netbios_char ( WCHAR wc )
515 static const WCHAR special[] = {'!','@','#','$','%','^','&','\'',')','(','-','_','{','}','~'};
516 static const WCHAR deflt = '_';
519 if ( isalnumW ( wc ) ) return wc;
520 for ( i = 0; i < sizeof (special) / sizeof (WCHAR); i++ )
521 if ( wc == special[i] ) return wc;
525 /******************************************************************************
526 * SetComputerNameW [KERNEL32.@]
529 * lpComputerName [I] Address of new computer name
533 BOOL WINAPI SetComputerNameW( LPCWSTR lpComputerName )
535 UNICODE_STRING nameW;
536 OBJECT_ATTRIBUTES attr;
537 HKEY hkey = INVALID_HANDLE_VALUE, hsubkey = INVALID_HANDLE_VALUE;
538 int plen = strlenW ( lpComputerName );
540 NTSTATUS st = STATUS_INTERNAL_ERROR;
542 if ( PROFILE_GetWineIniBool ( NetworkW, UseDNSW, 1 ) )
544 /* This check isn't necessary, but may help debugging problems. */
545 WARN( "Disabled by Wine Configuration.\n" );
546 WARN( "Set \"UseDnsComputerName\" = \"N\" in category [Network] to enable.\n" );
547 SetLastError ( ERROR_ACCESS_DENIED );
551 TRACE( "%s\n", debugstr_w (lpComputerName) );
553 /* Check parameter */
554 if ( plen > MAX_COMPUTERNAME_LENGTH )
557 /* This is NT behaviour. Win 95/98 would coerce characters. */
558 for ( i = 0; i < plen; i++ )
560 WCHAR wc = lpComputerName[i];
561 if ( wc != netbios_char( wc ) )
565 _init_attr ( &attr, &nameW );
567 RtlInitUnicodeString (&nameW, ComputerW);
568 if ( ( st = NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr ) ) != STATUS_SUCCESS )
570 attr.RootDirectory = hkey;
571 RtlInitUnicodeString( &nameW, ComputerNameW );
572 if ( ( st = NtOpenKey( &hsubkey, KEY_ALL_ACCESS, &attr ) ) != STATUS_SUCCESS )
574 if ( ( st = NtSetValueKey( hsubkey, &nameW, 0, REG_SZ, lpComputerName, ( plen + 1) * sizeof(WCHAR) ) )
582 if ( st == STATUS_SUCCESS )
584 TRACE( "ComputerName changed\n" );
590 SetLastError ( RtlNtStatusToDosError ( st ) );
591 WARN ( "status %lu\n", st );
596 /******************************************************************************
597 * SetComputerNameA [KERNEL32.@]
599 BOOL WINAPI SetComputerNameA( LPCSTR lpComputerName )
602 DWORD len = MultiByteToWideChar( CP_ACP, 0, lpComputerName, -1, NULL, 0 );
603 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
605 MultiByteToWideChar( CP_ACP, 0, lpComputerName, -1, nameW, len );
606 ret = SetComputerNameW( nameW );
607 HeapFree( GetProcessHeap(), 0, nameW );
611 /******************************************************************************
612 * SetComputerNameExW [KERNEL32.@]
615 BOOL WINAPI SetComputerNameExW( COMPUTER_NAME_FORMAT type, LPCWSTR lpComputerName )
617 TRACE("%d, %s\n", type, debugstr_w (lpComputerName));
620 case ComputerNameNetBIOS:
621 case ComputerNamePhysicalNetBIOS:
622 return SetComputerNameW( lpComputerName );
624 SetLastError( ERROR_ACCESS_DENIED );
629 /******************************************************************************
630 * SetComputerNameExA [KERNEL32.@]
633 BOOL WINAPI SetComputerNameExA( COMPUTER_NAME_FORMAT type, LPCSTR lpComputerName )
635 TRACE( "%d, %s\n", type, debugstr_a (lpComputerName) );
638 case ComputerNameNetBIOS:
639 case ComputerNamePhysicalNetBIOS:
640 return SetComputerNameA( lpComputerName );
642 SetLastError( ERROR_ACCESS_DENIED );
647 /***********************************************************************
648 * DnsHostnameToComputerNameA (KERNEL32.@)
650 BOOL WINAPI DnsHostnameToComputerNameA(LPCSTR Hostname, LPSTR ComputerName,
653 FIXME("(%s, %s, %08lx): stub\n", debugstr_a(Hostname),
654 debugstr_a(ComputerName), *nSize);
655 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
659 /***********************************************************************
660 * DnsHostnameToComputerNameW (KERNEL32.@)
662 BOOL WINAPI DnsHostnameToComputerNameW(LPCWSTR Hostname, LPWSTR ComputerName,
665 FIXME("(%s, %s, %08lx): stub\n", debugstr_w(Hostname),
666 debugstr_w(ComputerName), *nSize);
667 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);