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
24 #include "wine/port.h"
44 #include "wine/unicode.h"
45 #include "wine/exception.h"
47 #include "wine/debug.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(computername
);
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 #define IS_OPTION_TRUE(ch) ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
64 /* filter for page-fault exceptions */
65 static WINE_EXCEPTION_FILTER(page_fault
)
67 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION
)
68 return EXCEPTION_EXECUTE_HANDLER
;
69 return EXCEPTION_CONTINUE_SEARCH
;
72 /***********************************************************************
73 * dns_gethostbyname (INTERNAL)
76 * "The FQDN is the name gethostbyname(2) returns for the host name returned by gethostname(2)."
78 * Wine can use this technique only if the thread-safe gethostbyname_r is available.
80 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
81 static BOOL
dns_gethostbyname ( char *name
, int *size
)
83 struct hostent
* host
= NULL
;
86 struct hostent hostentry
;
87 int locerr
= ENOBUFS
, res
= ENOMEM
;
89 extrabuf
= HeapAlloc( GetProcessHeap(), 0, ebufsize
) ;
93 res
= gethostbyname_r ( name
, &hostentry
, extrabuf
, ebufsize
, &host
, &locerr
);
94 if( res
!= ERANGE
) break;
96 extrabuf
= HeapReAlloc( GetProcessHeap(), 0, extrabuf
, ebufsize
) ;
100 WARN ("Error in gethostbyname_r %d (%d)\n", res
, locerr
);
103 int len
= strlen ( host
->h_name
);
106 strcpy ( name
, host
->h_name
);
111 memcpy ( name
, host
->h_name
, *size
);
113 SetLastError ( ERROR_MORE_DATA
);
118 HeapFree( GetProcessHeap(), 0, extrabuf
);
122 # define dns_gethostbyname(name,size) 0
125 /***********************************************************************
126 * dns_fqdn (INTERNAL)
128 static BOOL
dns_fqdn ( char *name
, int *size
)
130 if ( gethostname ( name
, *size
+ 1 ) )
135 SetLastError ( ERROR_MORE_DATA
);
137 SetLastError ( ERROR_INVALID_PARAMETER
);
142 if ( !dns_gethostbyname ( name
, size
) )
143 *size
= strlen ( name
);
148 /***********************************************************************
149 * dns_hostname (INTERNAL)
151 static BOOL
dns_hostname ( char *name
, int *size
)
154 if ( ! dns_fqdn ( name
, size
) ) return FALSE
;
155 c
= strchr ( name
, '.' );
164 /***********************************************************************
165 * dns_domainname (INTERNAL)
167 static BOOL
dns_domainname ( char *name
, int *size
)
170 if ( ! dns_fqdn ( name
, size
) ) return FALSE
;
171 c
= strchr ( name
, '.' );
176 memmove ( name
, c
, *size
+ 1 );
181 /***********************************************************************
182 * _init_attr (INTERNAL)
184 inline static void _init_attr ( OBJECT_ATTRIBUTES
*attr
, UNICODE_STRING
*name
)
186 attr
->Length
= sizeof (OBJECT_ATTRIBUTES
);
187 attr
->RootDirectory
= 0;
188 attr
->ObjectName
= name
;
189 attr
->Attributes
= 0;
190 attr
->SecurityDescriptor
= NULL
;
191 attr
->SecurityQualityOfService
= NULL
;
194 /***********************************************************************
197 static BOOL
get_use_dns_option(void)
199 static const WCHAR NetworkW
[] = {'M','a','c','h','i','n','e','\\',
200 'S','o','f','t','w','a','r','e','\\',
201 'W','i','n','e','\\','W','i','n','e','\\',
202 'C','o','n','f','i','g','\\','N','e','t','w','o','r','k',0};
203 static const WCHAR UseDNSW
[] = {'U','s','e','D','n','s','C','o','m','p','u','t','e','r','N','a','m','e',0};
208 OBJECT_ATTRIBUTES attr
;
209 UNICODE_STRING nameW
;
212 _init_attr( &attr
, &nameW
);
213 RtlInitUnicodeString( &nameW
, NetworkW
);
215 if (!NtOpenKey( &hkey
, KEY_ALL_ACCESS
, &attr
))
217 RtlInitUnicodeString( &nameW
, UseDNSW
);
218 if (!NtQueryValueKey( hkey
, &nameW
, KeyValuePartialInformation
, tmp
, sizeof(tmp
), &dummy
))
220 WCHAR
*str
= (WCHAR
*)((KEY_VALUE_PARTIAL_INFORMATION
*)tmp
)->Data
;
221 ret
= IS_OPTION_TRUE( str
[0] );
229 /***********************************************************************
230 * COMPUTERNAME_Init (INTERNAL)
232 void COMPUTERNAME_Init (void)
234 HKEY hkey
= INVALID_HANDLE_VALUE
, hsubkey
= INVALID_HANDLE_VALUE
;
235 OBJECT_ATTRIBUTES attr
;
236 UNICODE_STRING nameW
;
237 char buf
[offsetof( KEY_VALUE_PARTIAL_INFORMATION
, Data
) + (MAX_COMPUTERNAME_LENGTH
+ 1) * sizeof( WCHAR
)];
238 DWORD len
= sizeof( buf
);
239 LPWSTR computer_name
= (LPWSTR
) (buf
+ offsetof( KEY_VALUE_PARTIAL_INFORMATION
, Data
));
240 NTSTATUS st
= STATUS_INTERNAL_ERROR
;
243 _init_attr ( &attr
, &nameW
);
245 RtlInitUnicodeString( &nameW
, ComputerW
);
246 if ( ( st
= NtCreateKey( &hkey
, KEY_ALL_ACCESS
, &attr
, 0, NULL
, 0, NULL
) ) != STATUS_SUCCESS
)
249 attr
.RootDirectory
= hkey
;
250 RtlInitUnicodeString( &nameW
, ComputerNameW
);
251 if ( (st
= NtCreateKey( &hsubkey
, KEY_ALL_ACCESS
, &attr
, 0, NULL
, 0, NULL
) ) != STATUS_SUCCESS
)
254 st
= NtQueryValueKey( hsubkey
, &nameW
, KeyValuePartialInformation
, buf
, len
, &len
);
256 if ( st
!= STATUS_SUCCESS
|| get_use_dns_option() )
259 int hlen
= sizeof (hbuf
);
261 TRACE( "retrieving Unix host name\n" );
262 if ( gethostname ( hbuf
, hlen
) )
264 strcpy ( hbuf
, default_ComputerName
);
265 WARN( "gethostname() error: %d, using host name %s\n", errno
, hbuf
);
267 hbuf
[MAX_COMPUTERNAME_LENGTH
] = 0;
268 dot
= strchr ( hbuf
, '.' );
270 hlen
= strlen ( hbuf
);
271 len
= MultiByteToWideChar( CP_ACP
, 0, hbuf
, hlen
+ 1, computer_name
, MAX_COMPUTERNAME_LENGTH
+ 1 )
273 if ( NtSetValueKey( hsubkey
, &nameW
, 0, REG_SZ
, computer_name
, len
) != STATUS_SUCCESS
)
274 WARN ( "failed to set ComputerName\n" );
276 else if ( st
== STATUS_SUCCESS
)
278 len
= (len
- offsetof( KEY_VALUE_PARTIAL_INFORMATION
, Data
));
279 TRACE( "found in registry\n" );
284 TRACE(" ComputerName: %s (%lu)\n", debugstr_w ( computer_name
), len
/ sizeof(WCHAR
));
286 RtlInitUnicodeString( &nameW
, ActiveComputerNameW
);
287 if ( ( st
= NtCreateKey( &hsubkey
, KEY_ALL_ACCESS
, &attr
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
) )
291 RtlInitUnicodeString( &nameW
, ComputerNameW
);
292 st
= NtSetValueKey( hsubkey
, &nameW
, 0, REG_SZ
, computer_name
, len
);
298 if ( st
== STATUS_SUCCESS
)
299 TRACE( "success\n" );
302 WARN( "status trying to set ComputerName: %lx\n", st
);
303 SetLastError ( RtlNtStatusToDosError ( st
) );
308 /***********************************************************************
309 * GetComputerNameW (KERNEL32.@)
311 BOOL WINAPI
GetComputerNameW(LPWSTR name
,LPDWORD size
)
313 UNICODE_STRING nameW
;
314 OBJECT_ATTRIBUTES attr
;
315 HKEY hkey
= INVALID_HANDLE_VALUE
, hsubkey
= INVALID_HANDLE_VALUE
;
316 char buf
[offsetof( KEY_VALUE_PARTIAL_INFORMATION
, Data
) + (MAX_COMPUTERNAME_LENGTH
+ 1) * sizeof( WCHAR
)];
317 DWORD len
= sizeof( buf
);
318 LPWSTR theName
= (LPWSTR
) (buf
+ offsetof( KEY_VALUE_PARTIAL_INFORMATION
, Data
));
319 NTSTATUS st
= STATUS_INVALID_PARAMETER
;
321 TRACE ("%p %p\n", name
, size
);
323 _init_attr ( &attr
, &nameW
);
324 RtlInitUnicodeString( &nameW
, ComputerW
);
325 if ( ( st
= NtOpenKey( &hkey
, KEY_ALL_ACCESS
, &attr
) ) != STATUS_SUCCESS
)
328 attr
.RootDirectory
= hkey
;
329 RtlInitUnicodeString( &nameW
, ActiveComputerNameW
);
330 if ( ( st
= NtOpenKey( &hsubkey
, KEY_ALL_ACCESS
, &attr
) ) != STATUS_SUCCESS
)
333 RtlInitUnicodeString( &nameW
, ComputerNameW
);
334 if ( ( st
= NtQueryValueKey( hsubkey
, &nameW
, KeyValuePartialInformation
, buf
, len
, &len
) )
338 len
= (len
-offsetof( KEY_VALUE_PARTIAL_INFORMATION
, Data
)) / sizeof (WCHAR
) - 1;
339 TRACE ("ComputerName is %s (length %lu)\n", debugstr_w ( theName
), len
);
345 memcpy ( name
, theName
, *size
* sizeof (WCHAR
) );
348 st
= STATUS_MORE_ENTRIES
;
352 memcpy ( name
, theName
, len
* sizeof (WCHAR
) );
360 st
= STATUS_INVALID_PARAMETER
;
368 if ( st
== STATUS_SUCCESS
)
372 SetLastError ( RtlNtStatusToDosError ( st
) );
373 WARN ( "Status %lu reading computer name from registry\n", st
);
378 /***********************************************************************
379 * GetComputerNameA (KERNEL32.@)
381 BOOL WINAPI
GetComputerNameA(LPSTR name
, LPDWORD size
)
383 WCHAR nameW
[ MAX_COMPUTERNAME_LENGTH
+ 1 ];
384 DWORD sizeW
= MAX_COMPUTERNAME_LENGTH
;
388 if ( !GetComputerNameW (nameW
, &sizeW
) ) return FALSE
;
390 len
= WideCharToMultiByte ( CP_ACP
, 0, nameW
, sizeW
, NULL
, 0, NULL
, 0 );
395 WideCharToMultiByte ( CP_ACP
, 0, nameW
, sizeW
, name
, *size
, NULL
, 0 );
398 SetLastError( ERROR_MORE_DATA
);
403 WideCharToMultiByte ( CP_ACP
, 0, nameW
, sizeW
, name
, len
, NULL
, 0 );
411 SetLastError( ERROR_INVALID_PARAMETER
);
419 /***********************************************************************
420 * GetComputerNameExA (KERNEL32.@)
422 BOOL WINAPI
GetComputerNameExA(COMPUTER_NAME_FORMAT type
, LPSTR name
, LPDWORD size
)
425 int len
= sizeof (buf
), ret
;
426 TRACE("%d, %p, %p\n", type
, name
, size
);
429 case ComputerNameNetBIOS
:
430 case ComputerNamePhysicalNetBIOS
:
431 return GetComputerNameA (name
, size
);
432 case ComputerNameDnsHostname
:
433 case ComputerNamePhysicalDnsHostname
:
434 ret
= dns_hostname (buf
, &len
);
436 case ComputerNameDnsDomain
:
437 case ComputerNamePhysicalDnsDomain
:
438 ret
= dns_domainname (buf
, &len
);
440 case ComputerNameDnsFullyQualified
:
441 case ComputerNamePhysicalDnsFullyQualified
:
442 ret
= dns_fqdn (buf
, &len
);
445 SetLastError (ERROR_INVALID_PARAMETER
);
451 TRACE ("-> %s (%d)\n", debugstr_a (buf
), len
);
456 memcpy( name
, buf
, *size
);
459 SetLastError( ERROR_MORE_DATA
);
464 memcpy( name
, buf
, len
);
472 SetLastError( ERROR_INVALID_PARAMETER
);
482 /***********************************************************************
483 * GetComputerNameExW (KERNEL32.@)
485 BOOL WINAPI
GetComputerNameExW( COMPUTER_NAME_FORMAT type
, LPWSTR name
, LPDWORD size
)
488 int len
= sizeof (buf
), ret
;
490 TRACE("%d, %p, %p\n", type
, name
, size
);
493 case ComputerNameNetBIOS
:
494 case ComputerNamePhysicalNetBIOS
:
495 return GetComputerNameW (name
, size
);
496 case ComputerNameDnsHostname
:
497 case ComputerNamePhysicalDnsHostname
:
498 ret
= dns_hostname (buf
, &len
);
500 case ComputerNameDnsDomain
:
501 case ComputerNamePhysicalDnsDomain
:
502 ret
= dns_domainname (buf
, &len
);
504 case ComputerNameDnsFullyQualified
:
505 case ComputerNamePhysicalDnsFullyQualified
:
506 ret
= dns_fqdn (buf
, &len
);
509 SetLastError (ERROR_INVALID_PARAMETER
);
515 TRACE ("-> %s (%d)\n", debugstr_a (buf
), len
);
518 unsigned int lenW
= MultiByteToWideChar( CP_ACP
, 0, buf
, len
, NULL
, 0 );
521 MultiByteToWideChar( CP_ACP
, 0, buf
, len
, name
, *size
);
524 SetLastError( ERROR_MORE_DATA
);
529 MultiByteToWideChar( CP_ACP
, 0, buf
, len
, name
, lenW
);
537 SetLastError( ERROR_INVALID_PARAMETER
);
546 /******************************************************************************
547 * netbios_char (INTERNAL)
549 static WCHAR
netbios_char ( WCHAR wc
)
551 static const WCHAR special
[] = {'!','@','#','$','%','^','&','\'',')','(','-','_','{','}','~'};
552 static const WCHAR deflt
= '_';
555 if ( isalnumW ( wc
) ) return wc
;
556 for ( i
= 0; i
< sizeof (special
) / sizeof (WCHAR
); i
++ )
557 if ( wc
== special
[i
] ) return wc
;
561 /******************************************************************************
562 * SetComputerNameW [KERNEL32.@]
565 * lpComputerName [I] Address of new computer name
569 BOOL WINAPI
SetComputerNameW( LPCWSTR lpComputerName
)
571 UNICODE_STRING nameW
;
572 OBJECT_ATTRIBUTES attr
;
573 HKEY hkey
= INVALID_HANDLE_VALUE
, hsubkey
= INVALID_HANDLE_VALUE
;
574 int plen
= strlenW ( lpComputerName
);
576 NTSTATUS st
= STATUS_INTERNAL_ERROR
;
578 if (get_use_dns_option())
580 /* This check isn't necessary, but may help debugging problems. */
581 WARN( "Disabled by Wine Configuration.\n" );
582 WARN( "Set \"UseDnsComputerName\" = \"N\" in category [Network] to enable.\n" );
583 SetLastError ( ERROR_ACCESS_DENIED
);
587 TRACE( "%s\n", debugstr_w (lpComputerName
) );
589 /* Check parameter */
590 if ( plen
> MAX_COMPUTERNAME_LENGTH
)
593 /* This is NT behaviour. Win 95/98 would coerce characters. */
594 for ( i
= 0; i
< plen
; i
++ )
596 WCHAR wc
= lpComputerName
[i
];
597 if ( wc
!= netbios_char( wc
) )
601 _init_attr ( &attr
, &nameW
);
603 RtlInitUnicodeString (&nameW
, ComputerW
);
604 if ( ( st
= NtOpenKey( &hkey
, KEY_ALL_ACCESS
, &attr
) ) != STATUS_SUCCESS
)
606 attr
.RootDirectory
= hkey
;
607 RtlInitUnicodeString( &nameW
, ComputerNameW
);
608 if ( ( st
= NtOpenKey( &hsubkey
, KEY_ALL_ACCESS
, &attr
) ) != STATUS_SUCCESS
)
610 if ( ( st
= NtSetValueKey( hsubkey
, &nameW
, 0, REG_SZ
, lpComputerName
, ( plen
+ 1) * sizeof(WCHAR
) ) )
618 if ( st
== STATUS_SUCCESS
)
620 TRACE( "ComputerName changed\n" );
626 SetLastError ( RtlNtStatusToDosError ( st
) );
627 WARN ( "status %lu\n", st
);
632 /******************************************************************************
633 * SetComputerNameA [KERNEL32.@]
635 BOOL WINAPI
SetComputerNameA( LPCSTR lpComputerName
)
638 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, lpComputerName
, -1, NULL
, 0 );
639 LPWSTR nameW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
641 MultiByteToWideChar( CP_ACP
, 0, lpComputerName
, -1, nameW
, len
);
642 ret
= SetComputerNameW( nameW
);
643 HeapFree( GetProcessHeap(), 0, nameW
);
647 /******************************************************************************
648 * SetComputerNameExW [KERNEL32.@]
651 BOOL WINAPI
SetComputerNameExW( COMPUTER_NAME_FORMAT type
, LPCWSTR lpComputerName
)
653 TRACE("%d, %s\n", type
, debugstr_w (lpComputerName
));
656 case ComputerNameNetBIOS
:
657 case ComputerNamePhysicalNetBIOS
:
658 return SetComputerNameW( lpComputerName
);
660 SetLastError( ERROR_ACCESS_DENIED
);
665 /******************************************************************************
666 * SetComputerNameExA [KERNEL32.@]
669 BOOL WINAPI
SetComputerNameExA( COMPUTER_NAME_FORMAT type
, LPCSTR lpComputerName
)
671 TRACE( "%d, %s\n", type
, debugstr_a (lpComputerName
) );
674 case ComputerNameNetBIOS
:
675 case ComputerNamePhysicalNetBIOS
:
676 return SetComputerNameA( lpComputerName
);
678 SetLastError( ERROR_ACCESS_DENIED
);
683 /***********************************************************************
684 * DnsHostnameToComputerNameA (KERNEL32.@)
686 BOOL WINAPI
DnsHostnameToComputerNameA(LPCSTR hostname
,
687 LPSTR computername
, LPDWORD size
)
691 FIXME("(%s, %p, %p): stub\n", debugstr_a(hostname
), computername
, size
);
693 if (!hostname
|| !size
) return FALSE
;
694 len
= lstrlenA(hostname
);
696 if (len
> MAX_COMPUTERNAME_LENGTH
)
697 len
= MAX_COMPUTERNAME_LENGTH
;
704 if (!computername
) return FALSE
;
706 memcpy( computername
, hostname
, len
);
707 computername
[len
+ 1] = 0;
711 /***********************************************************************
712 * DnsHostnameToComputerNameW (KERNEL32.@)
714 BOOL WINAPI
DnsHostnameToComputerNameW(LPCWSTR hostname
,
715 LPWSTR computername
, LPDWORD size
)
719 FIXME("(%s, %p, %p): stub\n", debugstr_w(hostname
), computername
, size
);
721 if (!hostname
|| !size
) return FALSE
;
722 len
= lstrlenW(hostname
);
724 if (len
> MAX_COMPUTERNAME_LENGTH
)
725 len
= MAX_COMPUTERNAME_LENGTH
;
732 if (!computername
) return FALSE
;
734 memcpy( computername
, hostname
, len
* sizeof(WCHAR
) );
735 computername
[len
+ 1] = 0;