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
);