Make WINE_GET_SONAME work on NetBSD.
[wine/wine64.git] / dlls / kernel / computername.c
blob74a66cd77508893e1d08e44d50dfba97e95b6e01
1 /*
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
23 #include "config.h"
25 #include <string.h>
26 #ifdef HAVE_UNISTD_H
27 # include <unistd.h>
28 #endif
29 #include <stdlib.h>
30 #include <errno.h>
31 #ifdef HAVE_NETDB_H
32 #include <netdb.h>
33 #endif
35 #include "winbase.h"
36 #include "winerror.h"
37 #include "winnls.h"
38 #include "winternl.h"
39 #include "wine/unicode.h"
40 #include "wine/exception.h"
41 #include "excpt.h"
42 #include "wine/debug.h"
43 #include "file.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)
73 * From hostname(1):
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;
82 char *extrabuf;
83 int ebufsize = 1024;
84 struct hostent hostentry;
85 int locerr = ENOBUFS, res = ENOMEM;
87 extrabuf = HeapAlloc( GetProcessHeap(), 0, ebufsize ) ;
89 while( extrabuf )
91 res = gethostbyname_r ( name, &hostentry, extrabuf, ebufsize, &host, &locerr );
92 if( res != ERANGE ) break;
93 ebufsize *= 2;
94 extrabuf = HeapReAlloc( GetProcessHeap(), 0, extrabuf, ebufsize ) ;
97 if ( res )
98 WARN ("Error in gethostbyname_r %d (%d)\n", res, locerr);
99 else
101 size_t len = strlen ( host->h_name );
102 if ( len < *size )
104 strcpy ( name, host->h_name );
105 *size = len;
107 else
109 memcpy ( name, host->h_name, *size );
110 name[*size] = 0;
111 SetLastError ( ERROR_MORE_DATA );
112 res = 1;
116 HeapFree( GetProcessHeap(), 0, extrabuf );
117 return !res;
119 #else
120 # define dns_gethostbyname(name,size) 0
121 #endif
123 /***********************************************************************
124 * dns_fqdn (INTERNAL)
126 static BOOL dns_fqdn ( char *name, int *size )
128 if ( gethostname ( name, *size + 1 ) )
130 switch( errno )
132 case ENAMETOOLONG:
133 SetLastError ( ERROR_MORE_DATA );
134 default:
135 SetLastError ( ERROR_INVALID_PARAMETER );
137 return FALSE;
140 if ( !dns_gethostbyname ( name, size ) )
141 *size = strlen ( name );
143 return TRUE;
146 /***********************************************************************
147 * dns_hostname (INTERNAL)
149 static BOOL dns_hostname ( char *name, int *size )
151 char *c;
152 if ( ! dns_fqdn ( name, size ) ) return FALSE;
153 c = strchr ( name, '.' );
154 if (c)
156 *c = 0;
157 *size = (c - name);
159 return TRUE;
162 /***********************************************************************
163 * dns_domainname (INTERNAL)
165 static BOOL dns_domainname ( char *name, int *size )
167 char *c;
168 if ( ! dns_fqdn ( name, size ) ) return FALSE;
169 c = strchr ( name, '.' );
170 if (c)
172 c += 1;
173 *size -= (c - name);
174 memmove ( name, c, *size + 1 );
176 return TRUE;
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;
205 TRACE("(void)\n");
206 _init_attr ( &attr, &nameW );
208 RtlInitUnicodeString( &nameW, ComputerW );
209 if ( ( st = NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ) ) != STATUS_SUCCESS )
210 goto out;
212 attr.RootDirectory = hkey;
213 RtlInitUnicodeString( &nameW, ComputerNameW );
214 if ( (st = NtCreateKey( &hsubkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ) ) != STATUS_SUCCESS )
215 goto out;
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 ) ) )
222 char hbuf[256];
223 int hlen = sizeof (hbuf);
224 char *dot;
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, '.' );
233 if ( dot ) *dot = 0;
234 hlen = strlen ( hbuf );
235 len = MultiByteToWideChar( CP_ACP, 0, hbuf, hlen + 1, computer_name, MAX_COMPUTERNAME_LENGTH + 1 )
236 * sizeof( WCHAR );
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" );
245 else goto out;
247 NtClose( hsubkey );
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 ) )
252 != STATUS_SUCCESS )
253 goto out;
255 RtlInitUnicodeString( &nameW, ComputerNameW );
256 st = NtSetValueKey( hsubkey, &nameW, 0, REG_SZ, computer_name, len );
258 out:
259 NtClose( hsubkey );
260 NtClose( hkey );
262 if ( st == STATUS_SUCCESS )
263 TRACE( "success\n" );
264 else
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 )
290 goto out;
292 attr.RootDirectory = hkey;
293 RtlInitUnicodeString( &nameW, ActiveComputerNameW );
294 if ( ( st = NtOpenKey( &hsubkey, KEY_ALL_ACCESS, &attr ) ) != STATUS_SUCCESS )
295 goto out;
297 RtlInitUnicodeString( &nameW, ComputerNameW );
298 if ( ( st = NtQueryValueKey( hsubkey, &nameW, KeyValuePartialInformation, buf, len, &len ) )
299 != STATUS_SUCCESS )
300 goto out;
302 len = (len -offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data )) / sizeof (WCHAR) - 1;
303 TRACE ("ComputerName is %s (length %lu)\n", debugstr_w ( theName ), len);
305 __TRY
307 if ( *size < len )
309 memcpy ( name, theName, *size * sizeof (WCHAR) );
310 name[*size] = 0;
311 *size = len;
312 st = STATUS_MORE_ENTRIES;
314 else
316 memcpy ( name, theName, len * sizeof (WCHAR) );
317 name[len] = 0;
318 *size = len;
319 st = STATUS_SUCCESS;
322 __EXCEPT(page_fault)
324 st = STATUS_INVALID_PARAMETER;
326 __ENDTRY
328 out:
329 NtClose ( hsubkey );
330 NtClose ( hkey );
332 if ( st == STATUS_SUCCESS )
333 return TRUE;
334 else
336 SetLastError ( RtlNtStatusToDosError ( st ) );
337 WARN ( "Status %lu reading computer name from registry\n", st );
338 return FALSE;
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;
349 int len;
350 BOOL ret;
352 if ( !GetComputerNameW (nameW, &sizeW) ) return FALSE;
354 len = WideCharToMultiByte ( CP_ACP, 0, nameW, sizeW, NULL, 0, NULL, 0 );
355 __TRY
357 if ( *size < len )
359 WideCharToMultiByte ( CP_ACP, 0, nameW, sizeW, name, *size, NULL, 0 );
360 name[*size] = 0;
361 *size = len;
362 SetLastError( ERROR_MORE_DATA );
363 ret = FALSE;
365 else
367 WideCharToMultiByte ( CP_ACP, 0, nameW, sizeW, name, len, NULL, 0 );
368 name[len] = 0;
369 *size = len;
370 ret = TRUE;
373 __EXCEPT(page_fault)
375 SetLastError( ERROR_INVALID_PARAMETER );
376 ret = FALSE;
378 __ENDTRY
380 return ret;
383 /***********************************************************************
384 * GetComputerNameExA (KERNEL32.@)
386 BOOL WINAPI GetComputerNameExA(COMPUTER_NAME_FORMAT type, LPSTR name, LPDWORD size)
388 char buf[256];
389 int len = sizeof (buf), ret;
390 TRACE("%d, %p, %p\n", type, name, size);
391 switch( type )
393 case ComputerNameNetBIOS:
394 case ComputerNamePhysicalNetBIOS:
395 return GetComputerNameA (name, size);
396 case ComputerNameDnsHostname:
397 case ComputerNamePhysicalDnsHostname:
398 ret = dns_hostname (buf, &len);
399 break;
400 case ComputerNameDnsDomain:
401 case ComputerNamePhysicalDnsDomain:
402 ret = dns_domainname (buf, &len);
403 break;
404 case ComputerNameDnsFullyQualified:
405 case ComputerNamePhysicalDnsFullyQualified:
406 ret = dns_fqdn (buf, &len);
407 break;
408 default:
409 SetLastError (ERROR_INVALID_PARAMETER);
410 return FALSE;
413 if ( ret )
415 TRACE ("-> %s (%d)\n", debugstr_a (buf), len);
416 __TRY
418 if ( *size < len )
420 memcpy( name, buf, *size );
421 name[*size] = 0;
422 *size = len;
423 SetLastError( ERROR_MORE_DATA );
424 ret = FALSE;
426 else
428 memcpy( name, buf, len );
429 name[len] = 0;
430 *size = len;
431 ret = TRUE;
434 __EXCEPT(page_fault)
436 SetLastError( ERROR_INVALID_PARAMETER );
437 return FALSE;
439 __ENDTRY
442 return ret;
446 /***********************************************************************
447 * GetComputerNameExW (KERNEL32.@)
449 BOOL WINAPI GetComputerNameExW( COMPUTER_NAME_FORMAT type, LPWSTR name, LPDWORD size )
451 char buf[256];
452 int len = sizeof (buf), ret;
454 TRACE("%d, %p, %p\n", type, name, size);
455 switch( type )
457 case ComputerNameNetBIOS:
458 case ComputerNamePhysicalNetBIOS:
459 return GetComputerNameW (name, size);
460 case ComputerNameDnsHostname:
461 case ComputerNamePhysicalDnsHostname:
462 ret = dns_hostname (buf, &len);
463 break;
464 case ComputerNameDnsDomain:
465 case ComputerNamePhysicalDnsDomain:
466 ret = dns_domainname (buf, &len);
467 break;
468 case ComputerNameDnsFullyQualified:
469 case ComputerNamePhysicalDnsFullyQualified:
470 ret = dns_fqdn (buf, &len);
471 break;
472 default:
473 SetLastError (ERROR_INVALID_PARAMETER);
474 return FALSE;
477 if ( ret )
479 TRACE ("-> %s (%d)\n", debugstr_a (buf), len);
480 __TRY
482 int lenW = MultiByteToWideChar( CP_ACP, 0, buf, len, NULL, 0 );
483 if ( *size < lenW )
485 MultiByteToWideChar( CP_ACP, 0, buf, len, name, *size );
486 name[*size] = 0;
487 *size = lenW;
488 SetLastError( ERROR_MORE_DATA );
489 ret = FALSE;
491 else
493 MultiByteToWideChar( CP_ACP, 0, buf, len, name, lenW );
494 name[lenW] = 0;
495 *size = lenW;
496 ret = TRUE;
499 __EXCEPT(page_fault)
501 SetLastError( ERROR_INVALID_PARAMETER );
502 return FALSE;
504 __ENDTRY
507 return ret;
510 /******************************************************************************
511 * netbios_char (INTERNAL)
513 static WCHAR netbios_char ( WCHAR wc )
515 static const WCHAR special[] = {'!','@','#','$','%','^','&','\'',')','(','-','_','{','}','~'};
516 static const WCHAR deflt = '_';
517 int i;
519 if ( isalnumW ( wc ) ) return wc;
520 for ( i = 0; i < sizeof (special) / sizeof (WCHAR); i++ )
521 if ( wc == special[i] ) return wc;
522 return deflt;
525 /******************************************************************************
526 * SetComputerNameW [KERNEL32.@]
528 * PARAMS
529 * lpComputerName [I] Address of new computer name
531 * RETURNS STD
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 );
539 int i;
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 );
548 return FALSE;
551 TRACE( "%s\n", debugstr_w (lpComputerName) );
553 /* Check parameter */
554 if ( plen > MAX_COMPUTERNAME_LENGTH )
555 goto out;
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 ) )
562 goto out;
565 _init_attr ( &attr, &nameW );
567 RtlInitUnicodeString (&nameW, ComputerW);
568 if ( ( st = NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr ) ) != STATUS_SUCCESS )
569 goto out;
570 attr.RootDirectory = hkey;
571 RtlInitUnicodeString( &nameW, ComputerNameW );
572 if ( ( st = NtOpenKey( &hsubkey, KEY_ALL_ACCESS, &attr ) ) != STATUS_SUCCESS )
573 goto out;
574 if ( ( st = NtSetValueKey( hsubkey, &nameW, 0, REG_SZ, lpComputerName, ( plen + 1) * sizeof(WCHAR) ) )
575 != STATUS_SUCCESS )
576 goto out;
578 out:
579 NtClose( hsubkey );
580 NtClose( hkey );
582 if ( st == STATUS_SUCCESS )
584 TRACE( "ComputerName changed\n" );
585 return TRUE;
588 else
590 SetLastError ( RtlNtStatusToDosError ( st ) );
591 WARN ( "status %lu\n", st );
592 return FALSE;
596 /******************************************************************************
597 * SetComputerNameA [KERNEL32.@]
599 BOOL WINAPI SetComputerNameA( LPCSTR lpComputerName )
601 BOOL ret;
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 );
608 return ret;
611 /******************************************************************************
612 * SetComputerNameExW [KERNEL32.@]
615 BOOL WINAPI SetComputerNameExW( COMPUTER_NAME_FORMAT type, LPCWSTR lpComputerName )
617 TRACE("%d, %s\n", type, debugstr_w (lpComputerName));
618 switch( type )
620 case ComputerNameNetBIOS:
621 case ComputerNamePhysicalNetBIOS:
622 return SetComputerNameW( lpComputerName );
623 default:
624 SetLastError( ERROR_ACCESS_DENIED );
625 return FALSE;
629 /******************************************************************************
630 * SetComputerNameExA [KERNEL32.@]
633 BOOL WINAPI SetComputerNameExA( COMPUTER_NAME_FORMAT type, LPCSTR lpComputerName )
635 TRACE( "%d, %s\n", type, debugstr_a (lpComputerName) );
636 switch( type )
638 case ComputerNameNetBIOS:
639 case ComputerNamePhysicalNetBIOS:
640 return SetComputerNameA( lpComputerName );
641 default:
642 SetLastError( ERROR_ACCESS_DENIED );
643 return FALSE;
647 /***********************************************************************
648 * DnsHostnameToComputerNameA (KERNEL32.@)
650 BOOL WINAPI DnsHostnameToComputerNameA(LPCSTR Hostname, LPSTR ComputerName,
651 LPDWORD nSize)
653 FIXME("(%s, %s, %08lx): stub\n", debugstr_a(Hostname),
654 debugstr_a(ComputerName), *nSize);
655 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
656 return FALSE;
659 /***********************************************************************
660 * DnsHostnameToComputerNameW (KERNEL32.@)
662 BOOL WINAPI DnsHostnameToComputerNameW(LPCWSTR Hostname, LPWSTR ComputerName,
663 LPDWORD nSize)
665 FIXME("(%s, %s, %08lx): stub\n", debugstr_w(Hostname),
666 debugstr_w(ComputerName), *nSize);
667 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
668 return FALSE;