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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/port.h"
38 #define WIN32_NO_STATUS
44 #include "wine/unicode.h"
45 #include "wine/exception.h"
46 #include "wine/debug.h"
48 #include "kernel_private.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(computername
);
52 /* Registry key and value names */
53 static const WCHAR ComputerW
[] = {'\\','R','e','g','i','s','t','r','y','\\',
54 'M','a','c','h','i','n','e','\\',
55 'S','y','s','t','e','m','\\',
56 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
57 'C','o','n','t','r','o','l','\\',
58 'C','o','m','p','u','t','e','r','N','a','m','e',0};
59 static const WCHAR ActiveComputerNameW
[] = {'A','c','t','i','v','e','C','o','m','p','u','t','e','r','N','a','m','e',0};
60 static const WCHAR ComputerNameW
[] = {'C','o','m','p','u','t','e','r','N','a','m','e',0};
62 static const char default_ComputerName
[] = "WINE";
64 #define IS_OPTION_TRUE(ch) ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
66 /***********************************************************************
67 * dns_gethostbyname (INTERNAL)
70 * "The FQDN is the name gethostbyname(2) returns for the host name returned by gethostname(2)."
72 * Wine can use this technique only if the thread-safe gethostbyname_r is available.
74 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
75 static BOOL
dns_gethostbyname ( char *name
, int *size
)
77 struct hostent
* host
= NULL
;
80 struct hostent hostentry
;
81 int locerr
= ENOBUFS
, res
= ENOMEM
;
83 extrabuf
= HeapAlloc( GetProcessHeap(), 0, ebufsize
) ;
87 res
= gethostbyname_r ( name
, &hostentry
, extrabuf
, ebufsize
, &host
, &locerr
);
88 if( res
!= ERANGE
) break;
90 extrabuf
= HeapReAlloc( GetProcessHeap(), 0, extrabuf
, ebufsize
) ;
94 WARN ("Error in gethostbyname_r %d (%d)\n", res
, locerr
);
97 WARN ("gethostbyname_r returned NULL host, locerr = %d\n", locerr
);
102 int len
= strlen ( host
->h_name
);
105 strcpy ( name
, host
->h_name
);
110 memcpy ( name
, host
->h_name
, *size
);
112 SetLastError ( ERROR_MORE_DATA
);
117 HeapFree( GetProcessHeap(), 0, extrabuf
);
121 # define dns_gethostbyname(name,size) 0
124 /***********************************************************************
125 * dns_fqdn (INTERNAL)
127 static BOOL
dns_fqdn ( char *name
, int *size
)
129 if ( gethostname ( name
, *size
+ 1 ) )
134 SetLastError ( ERROR_MORE_DATA
);
137 SetLastError ( ERROR_INVALID_PARAMETER
);
143 if ( !dns_gethostbyname ( name
, size
) )
144 *size
= strlen ( name
);
149 /***********************************************************************
150 * dns_hostname (INTERNAL)
152 static BOOL
dns_hostname ( char *name
, int *size
)
155 if ( ! dns_fqdn ( name
, size
) ) return FALSE
;
156 c
= strchr ( name
, '.' );
165 /***********************************************************************
166 * dns_domainname (INTERNAL)
168 static BOOL
dns_domainname ( char *name
, int *size
)
171 if ( ! dns_fqdn ( name
, size
) ) return FALSE
;
172 c
= strchr ( name
, '.' );
177 memmove ( name
, c
, *size
+ 1 );
182 /***********************************************************************
183 * _init_attr (INTERNAL)
185 static inline void _init_attr ( OBJECT_ATTRIBUTES
*attr
, UNICODE_STRING
*name
)
187 attr
->Length
= sizeof (OBJECT_ATTRIBUTES
);
188 attr
->RootDirectory
= 0;
189 attr
->ObjectName
= name
;
190 attr
->Attributes
= 0;
191 attr
->SecurityDescriptor
= NULL
;
192 attr
->SecurityQualityOfService
= NULL
;
195 /***********************************************************************
198 static BOOL
get_use_dns_option(void)
200 static const WCHAR NetworkW
[] = {'S','o','f','t','w','a','r','e','\\',
201 'W','i','n','e','\\','N','e','t','w','o','r','k',0};
202 static const WCHAR UseDNSW
[] = {'U','s','e','D','n','s','C','o','m','p','u','t','e','r','N','a','m','e',0};
207 OBJECT_ATTRIBUTES attr
;
208 UNICODE_STRING nameW
;
211 _init_attr( &attr
, &nameW
);
212 RtlOpenCurrentUser( KEY_READ
, &root
);
213 attr
.RootDirectory
= root
;
214 RtlInitUnicodeString( &nameW
, NetworkW
);
216 /* @@ Wine registry key: HKCU\Software\Wine\Network */
217 if (!NtOpenKey( &hkey
, KEY_READ
, &attr
))
219 RtlInitUnicodeString( &nameW
, UseDNSW
);
220 if (!NtQueryValueKey( hkey
, &nameW
, KeyValuePartialInformation
, tmp
, sizeof(tmp
), &dummy
))
222 WCHAR
*str
= (WCHAR
*)((KEY_VALUE_PARTIAL_INFORMATION
*)tmp
)->Data
;
223 ret
= IS_OPTION_TRUE( str
[0] );
232 /***********************************************************************
233 * COMPUTERNAME_Init (INTERNAL)
235 void COMPUTERNAME_Init (void)
237 HANDLE hkey
= INVALID_HANDLE_VALUE
, hsubkey
= INVALID_HANDLE_VALUE
;
238 OBJECT_ATTRIBUTES attr
;
239 UNICODE_STRING nameW
;
240 char buf
[offsetof( KEY_VALUE_PARTIAL_INFORMATION
, Data
) + (MAX_COMPUTERNAME_LENGTH
+ 1) * sizeof( WCHAR
)];
241 DWORD len
= sizeof( buf
);
242 LPWSTR computer_name
= (LPWSTR
) (buf
+ offsetof( KEY_VALUE_PARTIAL_INFORMATION
, Data
));
243 NTSTATUS st
= STATUS_INTERNAL_ERROR
;
246 _init_attr ( &attr
, &nameW
);
248 RtlInitUnicodeString( &nameW
, ComputerW
);
249 if ( ( st
= NtCreateKey( &hkey
, KEY_ALL_ACCESS
, &attr
, 0, NULL
, 0, NULL
) ) != STATUS_SUCCESS
)
252 attr
.RootDirectory
= hkey
;
253 RtlInitUnicodeString( &nameW
, ComputerNameW
);
254 if ( (st
= NtCreateKey( &hsubkey
, KEY_ALL_ACCESS
, &attr
, 0, NULL
, 0, NULL
) ) != STATUS_SUCCESS
)
257 st
= NtQueryValueKey( hsubkey
, &nameW
, KeyValuePartialInformation
, buf
, len
, &len
);
259 if ( st
!= STATUS_SUCCESS
|| get_use_dns_option() )
262 int hlen
= sizeof (hbuf
);
264 TRACE( "retrieving Unix host name\n" );
265 if ( gethostname ( hbuf
, hlen
) )
267 strcpy ( hbuf
, default_ComputerName
);
268 WARN( "gethostname() error: %d, using host name %s\n", errno
, hbuf
);
270 hbuf
[MAX_COMPUTERNAME_LENGTH
] = 0;
271 dot
= strchr ( hbuf
, '.' );
273 hlen
= strlen ( hbuf
);
274 len
= MultiByteToWideChar( CP_UNIXCP
, 0, hbuf
, hlen
+ 1, computer_name
, MAX_COMPUTERNAME_LENGTH
+ 1 )
276 if ( NtSetValueKey( hsubkey
, &nameW
, 0, REG_SZ
, computer_name
, len
) != STATUS_SUCCESS
)
277 WARN ( "failed to set ComputerName\n" );
281 len
= (len
- offsetof( KEY_VALUE_PARTIAL_INFORMATION
, Data
));
282 TRACE( "found in registry\n" );
286 TRACE(" ComputerName: %s (%u)\n", debugstr_w (computer_name
), len
);
288 RtlInitUnicodeString( &nameW
, ActiveComputerNameW
);
289 if ( ( st
= NtCreateKey( &hsubkey
, KEY_ALL_ACCESS
, &attr
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
) )
293 RtlInitUnicodeString( &nameW
, ComputerNameW
);
294 st
= NtSetValueKey( hsubkey
, &nameW
, 0, REG_SZ
, computer_name
, len
);
300 if ( st
== STATUS_SUCCESS
)
301 TRACE( "success\n" );
304 WARN( "status trying to set ComputerName: %x\n", st
);
305 SetLastError ( RtlNtStatusToDosError ( st
) );
310 /***********************************************************************
311 * GetComputerNameW (KERNEL32.@)
313 BOOL WINAPI
GetComputerNameW(LPWSTR name
,LPDWORD size
)
315 UNICODE_STRING nameW
;
316 OBJECT_ATTRIBUTES attr
;
317 HANDLE hkey
= INVALID_HANDLE_VALUE
, hsubkey
= INVALID_HANDLE_VALUE
;
318 char buf
[offsetof( KEY_VALUE_PARTIAL_INFORMATION
, Data
) + (MAX_COMPUTERNAME_LENGTH
+ 1) * sizeof( WCHAR
)];
319 DWORD len
= sizeof( buf
);
320 LPWSTR theName
= (LPWSTR
) (buf
+ offsetof( KEY_VALUE_PARTIAL_INFORMATION
, Data
));
321 NTSTATUS st
= STATUS_INVALID_PARAMETER
;
322 DWORD err
= ERROR_SUCCESS
;
324 TRACE ("%p %p\n", name
, size
);
326 _init_attr ( &attr
, &nameW
);
327 RtlInitUnicodeString( &nameW
, ComputerW
);
328 if ( ( st
= NtOpenKey( &hkey
, KEY_READ
, &attr
) ) != STATUS_SUCCESS
)
330 err
= RtlNtStatusToDosError ( st
);
334 attr
.RootDirectory
= hkey
;
335 RtlInitUnicodeString( &nameW
, ActiveComputerNameW
);
336 if ( ( st
= NtOpenKey( &hsubkey
, KEY_READ
, &attr
) ) != STATUS_SUCCESS
)
338 err
= RtlNtStatusToDosError ( st
);
342 RtlInitUnicodeString( &nameW
, ComputerNameW
);
343 if ( ( st
= NtQueryValueKey( hsubkey
, &nameW
, KeyValuePartialInformation
, buf
, len
, &len
) )
346 err
= RtlNtStatusToDosError ( st
);
350 len
= (len
-offsetof( KEY_VALUE_PARTIAL_INFORMATION
, Data
)) / sizeof (WCHAR
) - 1;
351 TRACE ("ComputerName is %s (length %u)\n", debugstr_w ( theName
), len
);
353 if ( *size
< len
+ 1 )
356 err
= ERROR_BUFFER_OVERFLOW
;
360 memcpy ( name
, theName
, len
* sizeof (WCHAR
) );
369 if ( err
== ERROR_SUCCESS
)
373 SetLastError ( err
);
374 WARN ( "Status %u reading computer name from registry\n", st
);
379 /***********************************************************************
380 * GetComputerNameA (KERNEL32.@)
382 BOOL WINAPI
GetComputerNameA(LPSTR name
, LPDWORD size
)
384 WCHAR nameW
[ MAX_COMPUTERNAME_LENGTH
+ 1 ];
385 DWORD sizeW
= MAX_COMPUTERNAME_LENGTH
+ 1;
389 if ( !GetComputerNameW (nameW
, &sizeW
) ) return FALSE
;
391 len
= WideCharToMultiByte ( CP_ACP
, 0, nameW
, -1, NULL
, 0, NULL
, 0 );
392 /* for compatibility with Win9x */
398 SetLastError( ERROR_BUFFER_OVERFLOW
);
403 WideCharToMultiByte ( CP_ACP
, 0, nameW
, -1, name
, len
, NULL
, 0 );
410 SetLastError( ERROR_INVALID_PARAMETER
);
418 /***********************************************************************
419 * GetComputerNameExA (KERNEL32.@)
421 BOOL WINAPI
GetComputerNameExA(COMPUTER_NAME_FORMAT type
, LPSTR name
, LPDWORD size
)
424 int len
= sizeof(buf
) - 1, ret
;
425 TRACE("%d, %p, %p\n", type
, name
, size
);
428 case ComputerNameNetBIOS
:
429 case ComputerNamePhysicalNetBIOS
:
430 ret
= GetComputerNameA (name
, size
);
431 if (!ret
&& GetLastError() == ERROR_BUFFER_OVERFLOW
)
432 SetLastError( ERROR_MORE_DATA
);
435 case ComputerNameDnsHostname
:
436 case ComputerNamePhysicalDnsHostname
:
437 ret
= dns_hostname (buf
, &len
);
439 case ComputerNameDnsDomain
:
440 case ComputerNamePhysicalDnsDomain
:
441 ret
= dns_domainname (buf
, &len
);
443 case ComputerNameDnsFullyQualified
:
444 case ComputerNamePhysicalDnsFullyQualified
:
445 ret
= dns_fqdn (buf
, &len
);
448 SetLastError (ERROR_INVALID_PARAMETER
);
454 TRACE ("-> %s (%d)\n", debugstr_a (buf
), len
);
455 if ( *size
< len
+ 1 )
458 SetLastError( ERROR_MORE_DATA
);
463 memcpy( name
, buf
, len
);
474 /***********************************************************************
475 * GetComputerNameExW (KERNEL32.@)
477 BOOL WINAPI
GetComputerNameExW( COMPUTER_NAME_FORMAT type
, LPWSTR name
, LPDWORD size
)
480 int len
= sizeof(buf
) - 1, ret
;
482 TRACE("%d, %p, %p\n", type
, name
, size
);
485 case ComputerNameNetBIOS
:
486 case ComputerNamePhysicalNetBIOS
:
487 ret
= GetComputerNameW (name
, size
);
488 if (!ret
&& GetLastError() == ERROR_BUFFER_OVERFLOW
)
489 SetLastError( ERROR_MORE_DATA
);
491 case ComputerNameDnsHostname
:
492 case ComputerNamePhysicalDnsHostname
:
493 ret
= dns_hostname (buf
, &len
);
495 case ComputerNameDnsDomain
:
496 case ComputerNamePhysicalDnsDomain
:
497 ret
= dns_domainname (buf
, &len
);
499 case ComputerNameDnsFullyQualified
:
500 case ComputerNamePhysicalDnsFullyQualified
:
501 ret
= dns_fqdn (buf
, &len
);
504 SetLastError (ERROR_INVALID_PARAMETER
);
512 TRACE ("-> %s (%d)\n", debugstr_a (buf
), len
);
514 lenW
= MultiByteToWideChar( CP_ACP
, 0, buf
, len
, NULL
, 0 );
515 if ( *size
< lenW
+ 1 )
518 SetLastError( ERROR_MORE_DATA
);
523 MultiByteToWideChar( CP_ACP
, 0, buf
, len
, name
, lenW
);
533 /******************************************************************************
534 * netbios_char (INTERNAL)
536 static WCHAR
netbios_char ( WCHAR wc
)
538 static const WCHAR special
[] = {'!','@','#','$','%','^','&','\'',')','(','-','_','{','}','~'};
539 static const WCHAR deflt
= '_';
542 if ( isalnumW ( wc
) ) return wc
;
543 for ( i
= 0; i
< ARRAY_SIZE( special
); i
++ )
544 if ( wc
== special
[i
] ) return wc
;
548 /******************************************************************************
549 * SetComputerNameW [KERNEL32.@]
551 * Set a new NetBIOS name for the local computer.
554 * lpComputerName [I] Address of new computer name
560 BOOL WINAPI
SetComputerNameW( LPCWSTR lpComputerName
)
562 UNICODE_STRING nameW
;
563 OBJECT_ATTRIBUTES attr
;
564 HANDLE hkey
= INVALID_HANDLE_VALUE
, hsubkey
= INVALID_HANDLE_VALUE
;
565 int plen
= strlenW ( lpComputerName
);
567 NTSTATUS st
= STATUS_INTERNAL_ERROR
;
569 if (get_use_dns_option())
571 /* This check isn't necessary, but may help debugging problems. */
572 WARN( "Disabled by Wine Configuration.\n" );
573 WARN( "Set \"UseDnsComputerName\" = \"N\" in HKCU\\Software\\Wine\\Network to enable.\n" );
574 SetLastError ( ERROR_ACCESS_DENIED
);
578 TRACE( "%s\n", debugstr_w (lpComputerName
) );
580 /* Check parameter */
581 if ( plen
> MAX_COMPUTERNAME_LENGTH
)
584 /* This is NT behaviour. Win 95/98 would coerce characters. */
585 for ( i
= 0; i
< plen
; i
++ )
587 WCHAR wc
= lpComputerName
[i
];
588 if ( wc
!= netbios_char( wc
) )
592 _init_attr ( &attr
, &nameW
);
594 RtlInitUnicodeString (&nameW
, ComputerW
);
595 if ( ( st
= NtOpenKey( &hkey
, KEY_ALL_ACCESS
, &attr
) ) != STATUS_SUCCESS
)
597 attr
.RootDirectory
= hkey
;
598 RtlInitUnicodeString( &nameW
, ComputerNameW
);
599 if ( ( st
= NtOpenKey( &hsubkey
, KEY_ALL_ACCESS
, &attr
) ) != STATUS_SUCCESS
)
601 if ( ( st
= NtSetValueKey( hsubkey
, &nameW
, 0, REG_SZ
, lpComputerName
, ( plen
+ 1) * sizeof(WCHAR
) ) )
609 if ( st
== STATUS_SUCCESS
)
611 TRACE( "ComputerName changed\n" );
617 SetLastError ( RtlNtStatusToDosError ( st
) );
618 WARN ( "status %u\n", st
);
623 /******************************************************************************
624 * SetComputerNameA [KERNEL32.@]
626 * See SetComputerNameW.
628 BOOL WINAPI
SetComputerNameA( LPCSTR lpComputerName
)
631 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, lpComputerName
, -1, NULL
, 0 );
632 LPWSTR nameW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
634 MultiByteToWideChar( CP_ACP
, 0, lpComputerName
, -1, nameW
, len
);
635 ret
= SetComputerNameW( nameW
);
636 HeapFree( GetProcessHeap(), 0, nameW
);
640 /******************************************************************************
641 * SetComputerNameExW [KERNEL32.@]
644 BOOL WINAPI
SetComputerNameExW( COMPUTER_NAME_FORMAT type
, LPCWSTR lpComputerName
)
646 TRACE("%d, %s\n", type
, debugstr_w (lpComputerName
));
649 case ComputerNameNetBIOS
:
650 case ComputerNamePhysicalNetBIOS
:
651 return SetComputerNameW( lpComputerName
);
653 SetLastError( ERROR_ACCESS_DENIED
);
658 /******************************************************************************
659 * SetComputerNameExA [KERNEL32.@]
662 BOOL WINAPI
SetComputerNameExA( COMPUTER_NAME_FORMAT type
, LPCSTR lpComputerName
)
664 TRACE( "%d, %s\n", type
, debugstr_a (lpComputerName
) );
667 case ComputerNameNetBIOS
:
668 case ComputerNamePhysicalNetBIOS
:
669 return SetComputerNameA( lpComputerName
);
671 SetLastError( ERROR_ACCESS_DENIED
);
676 /***********************************************************************
677 * DnsHostnameToComputerNameA (KERNEL32.@)
679 BOOL WINAPI
DnsHostnameToComputerNameA(LPCSTR hostname
,
680 LPSTR computername
, LPDWORD size
)
684 FIXME("(%s, %p, %p): stub\n", debugstr_a(hostname
), computername
, size
);
686 if (!hostname
|| !size
) return FALSE
;
687 len
= lstrlenA(hostname
);
689 if (len
> MAX_COMPUTERNAME_LENGTH
)
690 len
= MAX_COMPUTERNAME_LENGTH
;
697 if (!computername
) return FALSE
;
699 memcpy( computername
, hostname
, len
);
700 computername
[len
] = 0;
704 /***********************************************************************
705 * DnsHostnameToComputerNameW (KERNEL32.@)
707 BOOL WINAPI
DnsHostnameToComputerNameW(LPCWSTR hostname
,
708 LPWSTR computername
, LPDWORD size
)
712 FIXME("(%s, %p, %p): stub\n", debugstr_w(hostname
), computername
, size
);
714 if (!hostname
|| !size
) return FALSE
;
715 len
= lstrlenW(hostname
);
717 if (len
> MAX_COMPUTERNAME_LENGTH
)
718 len
= MAX_COMPUTERNAME_LENGTH
;
725 if (!computername
) return FALSE
;
727 memcpy( computername
, hostname
, len
* sizeof(WCHAR
) );
728 computername
[len
] = 0;