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