Don't change the UI level during ExecuteAction.
[wine] / dlls / kernel / computername.c
1 /*
2  * Win32 kernel functions
3  *
4  * Copyright 1995 Martin von Loewis and Cameron Heide
5  * Copyright 1999 Peter Ganten
6  * Copyright 2002 Martin Wilck
7  *
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.
12  *
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.
17  *
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
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <stdarg.h>
27 #include <string.h>
28 #ifdef HAVE_UNISTD_H
29 # include <unistd.h>
30 #endif
31 #include <stdlib.h>
32 #include <errno.h>
33 #ifdef HAVE_NETDB_H
34 #include <netdb.h>
35 #endif
36
37 #include "ntstatus.h"
38 #include "windef.h"
39 #include "winbase.h"
40 #include "winerror.h"
41 #include "winnls.h"
42 #include "winternl.h"
43 #include "wine/unicode.h"
44 #include "wine/exception.h"
45 #include "excpt.h"
46 #include "wine/debug.h"
47
48 #include "kernel_private.h"
49
50 WINE_DEFAULT_DEBUG_CHANNEL(computername);
51
52 /* Registry key and value names */
53 static const WCHAR ComputerW[] = {'M','a','c','h','i','n','e','\\',
54                                   'S','y','s','t','e','m','\\',
55                                   'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
56                                   'C','o','n','t','r','o','l','\\',
57                                   'C','o','m','p','u','t','e','r','N','a','m','e',0};
58 static const WCHAR ActiveComputerNameW[] =   {'A','c','t','i','v','e','C','o','m','p','u','t','e','r','N','a','m','e',0};
59 static const WCHAR ComputerNameW[] = {'C','o','m','p','u','t','e','r','N','a','m','e',0};
60
61 static const char default_ComputerName[] = "WINE";
62
63 #define IS_OPTION_TRUE(ch) ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
64
65 /* filter for page-fault exceptions */
66 static WINE_EXCEPTION_FILTER(page_fault)
67 {
68     if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
69         return EXCEPTION_EXECUTE_HANDLER;
70     return EXCEPTION_CONTINUE_SEARCH;
71 }
72
73 /*********************************************************************** 
74  *                    dns_gethostbyname (INTERNAL)
75  *
76  *  From hostname(1):
77  *  "The FQDN is the name gethostbyname(2) returns for the host name returned by gethostname(2)."
78  *
79  *  Wine can use this technique only if the thread-safe gethostbyname_r is available.
80  */
81 #ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
82 static BOOL dns_gethostbyname ( char *name, int *size )
83 {
84     struct hostent* host = NULL;
85     char *extrabuf;
86     int ebufsize = 1024;
87     struct hostent hostentry;
88     int locerr = ENOBUFS, res = ENOMEM;
89
90     extrabuf = HeapAlloc( GetProcessHeap(), 0, ebufsize ) ;
91
92     while( extrabuf ) 
93     {
94         res = gethostbyname_r ( name, &hostentry, extrabuf, ebufsize, &host, &locerr );
95         if( res != ERANGE ) break;
96         ebufsize *= 2;
97         extrabuf = HeapReAlloc( GetProcessHeap(), 0, extrabuf, ebufsize ) ;
98     }
99     
100     if ( res )
101         WARN ("Error in gethostbyname_r %d (%d)\n", res, locerr);
102     else
103     {
104         int len = strlen ( host->h_name );
105         if ( len < *size )
106         {
107             strcpy ( name, host->h_name );
108             *size = len;
109         }
110         else
111         {
112             memcpy ( name, host->h_name, *size );
113             name[*size] = 0;
114             SetLastError ( ERROR_MORE_DATA );
115             res = 1;
116         }
117     }
118
119     HeapFree( GetProcessHeap(), 0, extrabuf );
120     return !res;
121 }
122 #else
123 #  define dns_gethostbyname(name,size) 0
124 #endif
125
126 /*********************************************************************** 
127  *                     dns_fqdn (INTERNAL)
128  */
129 static BOOL dns_fqdn ( char *name, int *size )
130 {
131     if ( gethostname ( name, *size + 1 ) ) 
132     {
133         switch( errno )
134         {
135         case ENAMETOOLONG:
136             SetLastError ( ERROR_MORE_DATA );
137         default:
138             SetLastError ( ERROR_INVALID_PARAMETER );
139         }
140         return FALSE;
141     }
142
143     if ( !dns_gethostbyname ( name, size ) )
144         *size = strlen ( name );
145
146     return TRUE;
147 }
148
149 /*********************************************************************** 
150  *                     dns_hostname (INTERNAL)
151  */
152 static BOOL dns_hostname ( char *name, int *size )
153 {
154     char *c;
155     if ( ! dns_fqdn ( name, size ) ) return FALSE;
156     c = strchr ( name, '.' );
157     if (c)
158     {
159         *c = 0;
160         *size = (c - name);
161     }
162     return TRUE;
163 }
164
165 /*********************************************************************** 
166  *                     dns_domainname (INTERNAL)
167  */
168 static BOOL dns_domainname ( char *name, int *size )
169 {
170     char *c;
171     if ( ! dns_fqdn ( name, size ) ) return FALSE;
172     c = strchr ( name, '.' );
173     if (c)
174     {
175         c += 1;
176         *size -= (c - name);
177         memmove ( name, c, *size + 1 );
178     }
179     return TRUE;
180 }
181
182 /*********************************************************************** 
183  *                      _init_attr    (INTERNAL)
184  */
185 inline static void _init_attr ( OBJECT_ATTRIBUTES *attr, UNICODE_STRING *name )
186 {
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;
193 }
194
195 /***********************************************************************
196  *           get_use_dns_option
197  */
198 static BOOL get_use_dns_option(void)
199 {
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};
203
204     char tmp[80];
205     HANDLE root, hkey;
206     DWORD dummy;
207     OBJECT_ATTRIBUTES attr;
208     UNICODE_STRING nameW;
209     BOOL ret = TRUE;
210
211     _init_attr( &attr, &nameW );
212     RtlOpenCurrentUser( KEY_ALL_ACCESS, &root );
213     attr.RootDirectory = root;
214     RtlInitUnicodeString( &nameW, NetworkW );
215
216     /* @@ Wine registry key: HKCU\Software\Wine\Network */
217     if (!NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr ))
218     {
219         RtlInitUnicodeString( &nameW, UseDNSW );
220         if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy ))
221         {
222             WCHAR *str = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
223             ret = IS_OPTION_TRUE( str[0] );
224         }
225         NtClose( hkey );
226     }
227     NtClose( root );
228     return ret;
229 }
230
231
232 /*********************************************************************** 
233  *                      COMPUTERNAME_Init    (INTERNAL)
234  */
235 void COMPUTERNAME_Init (void)
236 {
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;
244
245     TRACE("(void)\n");
246     _init_attr ( &attr, &nameW );
247     
248     RtlInitUnicodeString( &nameW, ComputerW );
249     if ( ( st = NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ) ) != STATUS_SUCCESS )
250         goto out;
251     
252     attr.RootDirectory = hkey;
253     RtlInitUnicodeString( &nameW, ComputerNameW );
254     if ( (st = NtCreateKey( &hsubkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ) ) != STATUS_SUCCESS )
255         goto out;
256     
257     st = NtQueryValueKey( hsubkey, &nameW, KeyValuePartialInformation, buf, len, &len );
258
259     if ( st != STATUS_SUCCESS || get_use_dns_option() )
260     {
261         char hbuf[256];
262         int hlen = sizeof (hbuf);
263         char *dot;
264         TRACE( "retrieving Unix host name\n" );
265         if ( gethostname ( hbuf, hlen ) )
266         {
267             strcpy ( hbuf, default_ComputerName );
268             WARN( "gethostname() error: %d, using host name %s\n", errno, hbuf );
269         }
270         hbuf[MAX_COMPUTERNAME_LENGTH] = 0;
271         dot = strchr ( hbuf, '.' );
272         if ( dot ) *dot = 0;
273         hlen = strlen ( hbuf );
274         len = MultiByteToWideChar( CP_ACP, 0, hbuf, hlen + 1, computer_name, MAX_COMPUTERNAME_LENGTH + 1 )
275             * sizeof( WCHAR );
276         if ( NtSetValueKey( hsubkey, &nameW, 0, REG_SZ, computer_name, len ) != STATUS_SUCCESS )
277             WARN ( "failed to set ComputerName\n" );
278     }
279     else if ( st == STATUS_SUCCESS)
280     {
281         len = (len - offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data ));
282         TRACE( "found in registry\n" );
283     }
284     else goto out;
285     
286     NtClose( hsubkey );
287     TRACE(" ComputerName: %s (%lu)\n", debugstr_w ( computer_name ), len / sizeof(WCHAR));
288
289     RtlInitUnicodeString( &nameW, ActiveComputerNameW );
290     if ( ( st = NtCreateKey( &hsubkey, KEY_ALL_ACCESS, &attr, 0, NULL, REG_OPTION_VOLATILE, NULL ) )
291          != STATUS_SUCCESS )
292         goto out;
293     
294     RtlInitUnicodeString( &nameW, ComputerNameW );
295     st = NtSetValueKey( hsubkey, &nameW, 0, REG_SZ, computer_name, len );
296
297 out:
298     NtClose( hsubkey );
299     NtClose( hkey );
300
301     if ( st == STATUS_SUCCESS )
302         TRACE( "success\n" );
303     else
304     {
305         WARN( "status trying to set ComputerName: %lx\n", st );
306         SetLastError ( RtlNtStatusToDosError ( st ) );
307     }
308 }
309
310
311 /***********************************************************************
312  *              GetComputerNameW         (KERNEL32.@)
313  */
314 BOOL WINAPI GetComputerNameW(LPWSTR name,LPDWORD size)
315 {
316     UNICODE_STRING nameW;
317     OBJECT_ATTRIBUTES attr;
318     HANDLE hkey = INVALID_HANDLE_VALUE, hsubkey = INVALID_HANDLE_VALUE;
319     char buf[offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data ) + (MAX_COMPUTERNAME_LENGTH + 1) * sizeof( WCHAR )];
320     DWORD len = sizeof( buf );
321     LPWSTR theName = (LPWSTR) (buf + offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data ));
322     NTSTATUS st = STATUS_INVALID_PARAMETER;
323     
324     TRACE ("%p %p\n", name, size);
325
326     _init_attr ( &attr, &nameW );
327     RtlInitUnicodeString( &nameW, ComputerW );
328     if ( ( st = NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr ) ) != STATUS_SUCCESS )
329         goto out;
330          
331     attr.RootDirectory = hkey;
332     RtlInitUnicodeString( &nameW, ActiveComputerNameW );
333     if ( ( st = NtOpenKey( &hsubkey, KEY_ALL_ACCESS, &attr ) ) != STATUS_SUCCESS )
334         goto out;
335     
336     RtlInitUnicodeString( &nameW, ComputerNameW );
337     if ( ( st = NtQueryValueKey( hsubkey, &nameW, KeyValuePartialInformation, buf, len, &len ) )
338          != STATUS_SUCCESS )
339         goto out;
340
341     len = (len -offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data )) / sizeof (WCHAR) - 1;
342     TRACE ("ComputerName is %s (length %lu)\n", debugstr_w ( theName ), len);
343
344     __TRY
345     {
346         if ( *size < len )
347         {
348             memcpy ( name, theName, *size * sizeof (WCHAR) );
349             name[*size] = 0;
350             *size = len;
351             st = STATUS_MORE_ENTRIES;
352         }
353         else
354         {
355             memcpy ( name, theName, len * sizeof (WCHAR) );
356             name[len] = 0;
357             *size = len;
358             st = STATUS_SUCCESS;
359         }
360     }
361     __EXCEPT(page_fault)
362     {
363         st = STATUS_INVALID_PARAMETER;
364     }
365     __ENDTRY
366
367 out:
368     NtClose ( hsubkey );
369     NtClose ( hkey );
370
371     if ( st == STATUS_SUCCESS )
372         return TRUE;
373     else
374     {
375         SetLastError ( RtlNtStatusToDosError ( st ) );
376         WARN ( "Status %lu reading computer name from registry\n", st );
377         return FALSE;
378     }
379 }
380
381 /***********************************************************************
382  *              GetComputerNameA         (KERNEL32.@)
383  */
384 BOOL WINAPI GetComputerNameA(LPSTR name, LPDWORD size)
385 {
386     WCHAR nameW[ MAX_COMPUTERNAME_LENGTH + 1 ];
387     DWORD sizeW = MAX_COMPUTERNAME_LENGTH;
388     unsigned int len;
389     BOOL ret;
390
391     if ( !GetComputerNameW (nameW, &sizeW) ) return FALSE;
392
393     len = WideCharToMultiByte ( CP_ACP, 0, nameW, sizeW, NULL, 0, NULL, 0 );
394     __TRY
395     {
396         if ( *size < len )
397         {
398             WideCharToMultiByte ( CP_ACP, 0, nameW, sizeW, name, *size, NULL, 0 );
399             name[*size] = 0;
400             *size = len;
401             SetLastError( ERROR_MORE_DATA );
402             ret = FALSE;
403         }
404         else 
405         {
406             WideCharToMultiByte ( CP_ACP, 0, nameW, sizeW, name, len, NULL, 0 );
407             name[len] = 0;
408             *size = len;
409             ret = TRUE;
410         }
411     }
412     __EXCEPT(page_fault)
413     {
414         SetLastError( ERROR_INVALID_PARAMETER );
415         ret = FALSE;
416     }
417     __ENDTRY
418
419     return ret;
420 }
421
422 /***********************************************************************
423  *              GetComputerNameExA         (KERNEL32.@)
424  */
425 BOOL WINAPI GetComputerNameExA(COMPUTER_NAME_FORMAT type, LPSTR name, LPDWORD size)
426 {
427     char buf[256];
428     int len = sizeof (buf), ret;
429     TRACE("%d, %p, %p\n", type, name, size);
430     switch( type )
431     {
432     case ComputerNameNetBIOS:
433     case ComputerNamePhysicalNetBIOS:
434         return GetComputerNameA (name, size);
435     case ComputerNameDnsHostname:
436     case ComputerNamePhysicalDnsHostname:
437         ret = dns_hostname (buf, &len);
438         break;
439     case ComputerNameDnsDomain:
440     case ComputerNamePhysicalDnsDomain:
441         ret = dns_domainname (buf, &len);
442         break;
443     case ComputerNameDnsFullyQualified:
444     case ComputerNamePhysicalDnsFullyQualified:
445         ret = dns_fqdn (buf, &len);
446         break;
447     default:
448         SetLastError (ERROR_INVALID_PARAMETER);
449         return FALSE;
450     }
451
452     if ( ret )
453     {
454         TRACE ("-> %s (%d)\n", debugstr_a (buf), len);
455         __TRY
456         {
457             if ( *size < len )
458             {
459                 memcpy( name, buf, *size );
460                 name[*size] = 0;
461                 *size = len;
462                 SetLastError( ERROR_MORE_DATA );
463                 ret = FALSE;
464             }
465             else
466             {
467                 memcpy( name, buf, len );
468                 name[len] = 0;
469                 *size = len;
470                 ret = TRUE;
471             }
472         }
473         __EXCEPT(page_fault)
474         {
475             SetLastError( ERROR_INVALID_PARAMETER );
476             return FALSE;
477         }
478         __ENDTRY
479     }
480
481     return ret;
482 }
483
484
485 /***********************************************************************
486  *              GetComputerNameExW         (KERNEL32.@)
487  */
488 BOOL WINAPI GetComputerNameExW( COMPUTER_NAME_FORMAT type, LPWSTR name, LPDWORD size )
489 {
490     char buf[256];
491     int len = sizeof (buf), ret;
492
493     TRACE("%d, %p, %p\n", type, name, size);
494     switch( type )
495     {
496     case ComputerNameNetBIOS:
497     case ComputerNamePhysicalNetBIOS:
498         return GetComputerNameW (name, size);
499     case ComputerNameDnsHostname:
500     case ComputerNamePhysicalDnsHostname:
501         ret = dns_hostname (buf, &len);
502         break;
503     case ComputerNameDnsDomain:
504     case ComputerNamePhysicalDnsDomain:
505         ret = dns_domainname (buf, &len);
506         break;
507     case ComputerNameDnsFullyQualified:
508     case ComputerNamePhysicalDnsFullyQualified:
509         ret = dns_fqdn (buf, &len);
510         break;
511     default:
512         SetLastError (ERROR_INVALID_PARAMETER);
513         return FALSE;
514     }
515
516     if ( ret )
517     {
518         TRACE ("-> %s (%d)\n", debugstr_a (buf), len);
519         __TRY
520         {
521             unsigned int lenW = MultiByteToWideChar( CP_ACP, 0, buf, len, NULL, 0 );
522             if ( *size < lenW )
523             {
524                 MultiByteToWideChar( CP_ACP, 0, buf, len, name, *size );
525                 name[*size] = 0;
526                 *size = lenW;
527                 SetLastError( ERROR_MORE_DATA );
528                 ret = FALSE;
529             }
530             else
531             {
532                 MultiByteToWideChar( CP_ACP, 0, buf, len, name, lenW );
533                 name[lenW] = 0;
534                 *size = lenW;
535                 ret = TRUE;
536             }
537         }
538         __EXCEPT(page_fault)
539         {
540             SetLastError( ERROR_INVALID_PARAMETER );
541             return FALSE;
542         }
543         __ENDTRY
544     }
545
546     return ret;
547 }
548
549 /******************************************************************************
550  * netbios_char (INTERNAL)
551  */
552 static WCHAR netbios_char ( WCHAR wc )
553 {
554     static const WCHAR special[] = {'!','@','#','$','%','^','&','\'',')','(','-','_','{','}','~'};
555     static const WCHAR deflt = '_';
556     unsigned int i;
557     
558     if ( isalnumW ( wc ) ) return wc;
559     for ( i = 0; i < sizeof (special) / sizeof (WCHAR); i++ )
560         if ( wc == special[i] ) return wc;
561     return deflt;
562 }
563
564 /******************************************************************************
565  * SetComputerNameW [KERNEL32.@]
566  *
567  * PARAMS
568  *    lpComputerName [I] Address of new computer name
569  *
570  * RETURNS STD
571  */
572 BOOL WINAPI SetComputerNameW( LPCWSTR lpComputerName )
573 {
574     UNICODE_STRING nameW;
575     OBJECT_ATTRIBUTES attr;
576     HANDLE hkey = INVALID_HANDLE_VALUE, hsubkey = INVALID_HANDLE_VALUE;
577     int plen = strlenW ( lpComputerName );
578     int i;
579     NTSTATUS st = STATUS_INTERNAL_ERROR;
580
581     if (get_use_dns_option())
582     {
583         /* This check isn't necessary, but may help debugging problems. */
584         WARN( "Disabled by Wine Configuration.\n" );
585         WARN( "Set \"UseDnsComputerName\" = \"N\" in category [Network] to enable.\n" );
586         SetLastError ( ERROR_ACCESS_DENIED );
587         return FALSE;
588     }
589
590     TRACE( "%s\n", debugstr_w (lpComputerName) );
591
592     /* Check parameter */
593     if ( plen > MAX_COMPUTERNAME_LENGTH ) 
594         goto out;
595
596     /* This is NT behaviour. Win 95/98 would coerce characters. */
597     for ( i = 0; i < plen; i++ )
598     {
599         WCHAR wc = lpComputerName[i];
600         if ( wc != netbios_char( wc ) )
601             goto out;
602     }
603     
604     _init_attr ( &attr, &nameW );
605     
606     RtlInitUnicodeString (&nameW, ComputerW);
607     if ( ( st = NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr ) ) != STATUS_SUCCESS )
608         goto out;
609     attr.RootDirectory = hkey;
610     RtlInitUnicodeString( &nameW, ComputerNameW );
611     if ( ( st = NtOpenKey( &hsubkey, KEY_ALL_ACCESS, &attr ) ) != STATUS_SUCCESS )
612         goto out;
613     if ( ( st = NtSetValueKey( hsubkey, &nameW, 0, REG_SZ, lpComputerName, ( plen + 1) * sizeof(WCHAR) ) )
614          != STATUS_SUCCESS )
615         goto out;
616
617 out:
618     NtClose( hsubkey );
619     NtClose( hkey );
620     
621     if ( st == STATUS_SUCCESS )
622     {
623         TRACE( "ComputerName changed\n" );
624         return TRUE;
625     }
626
627     else
628     {
629         SetLastError ( RtlNtStatusToDosError ( st ) );
630         WARN ( "status %lu\n", st );
631         return FALSE;
632     }
633 }
634
635 /******************************************************************************
636  * SetComputerNameA [KERNEL32.@]
637  */
638 BOOL WINAPI SetComputerNameA( LPCSTR lpComputerName )
639 {
640     BOOL ret;
641     DWORD len = MultiByteToWideChar( CP_ACP, 0, lpComputerName, -1, NULL, 0 );
642     LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
643
644     MultiByteToWideChar( CP_ACP, 0, lpComputerName, -1, nameW, len );
645     ret = SetComputerNameW( nameW );
646     HeapFree( GetProcessHeap(), 0, nameW );
647     return ret;
648 }
649
650 /******************************************************************************
651  * SetComputerNameExW [KERNEL32.@]
652  *
653  */
654 BOOL WINAPI SetComputerNameExW( COMPUTER_NAME_FORMAT type, LPCWSTR lpComputerName )
655 {
656     TRACE("%d, %s\n", type, debugstr_w (lpComputerName));
657     switch( type )
658     {
659     case ComputerNameNetBIOS:
660     case ComputerNamePhysicalNetBIOS:
661         return SetComputerNameW( lpComputerName );
662     default:
663         SetLastError( ERROR_ACCESS_DENIED );
664         return FALSE;
665     }
666 }
667
668 /******************************************************************************
669  * SetComputerNameExA [KERNEL32.@]
670  *
671  */
672 BOOL WINAPI SetComputerNameExA( COMPUTER_NAME_FORMAT type, LPCSTR lpComputerName )
673 {
674     TRACE( "%d, %s\n", type, debugstr_a (lpComputerName) );
675     switch( type )
676     {
677     case ComputerNameNetBIOS:
678     case ComputerNamePhysicalNetBIOS:
679         return SetComputerNameA( lpComputerName );
680     default:
681         SetLastError( ERROR_ACCESS_DENIED );
682         return FALSE;
683     }
684 }
685
686 /***********************************************************************
687  *              DnsHostnameToComputerNameA         (KERNEL32.@)
688  */
689 BOOL WINAPI DnsHostnameToComputerNameA(LPCSTR hostname,
690     LPSTR computername, LPDWORD size)
691 {
692     DWORD len;
693
694     FIXME("(%s, %p, %p): stub\n", debugstr_a(hostname), computername, size);
695
696     if (!hostname || !size) return FALSE;
697     len = lstrlenA(hostname);
698
699     if (len > MAX_COMPUTERNAME_LENGTH)
700         len = MAX_COMPUTERNAME_LENGTH;
701
702     if (*size < len)
703     {
704         *size = len;
705         return FALSE;
706     }
707     if (!computername) return FALSE;
708
709     memcpy( computername, hostname, len );
710     computername[len + 1] = 0;
711     return TRUE;
712 }
713
714 /***********************************************************************
715  *              DnsHostnameToComputerNameW         (KERNEL32.@)
716  */
717 BOOL WINAPI DnsHostnameToComputerNameW(LPCWSTR hostname,
718     LPWSTR computername, LPDWORD size)
719 {
720     DWORD len;
721
722     FIXME("(%s, %p, %p): stub\n", debugstr_w(hostname), computername, size);
723
724     if (!hostname || !size) return FALSE;
725     len = lstrlenW(hostname);
726
727     if (len > MAX_COMPUTERNAME_LENGTH)
728         len = MAX_COMPUTERNAME_LENGTH;
729
730     if (*size < len)
731     {
732         *size = len;
733         return FALSE;
734     }
735     if (!computername) return FALSE;
736
737     memcpy( computername, hostname, len * sizeof(WCHAR) );
738     computername[len + 1] = 0;
739     return TRUE;
740 }