kernel32: Add a bit of slack to the mailslot timeout test.
[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 static inline 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 + 1;
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 )
385         {
386             *size = len;
387             SetLastError( ERROR_MORE_DATA );
388             ret = FALSE;
389         }
390         else
391         {
392             WideCharToMultiByte ( CP_ACP, 0, nameW, -1, name, len, NULL, 0 );
393             *size = len - 1;
394             ret = TRUE;
395         }
396     }
397     __EXCEPT_PAGE_FAULT
398     {
399         SetLastError( ERROR_INVALID_PARAMETER );
400         ret = FALSE;
401     }
402     __ENDTRY
403
404     return ret;
405 }
406
407 /***********************************************************************
408  *              GetComputerNameExA         (KERNEL32.@)
409  */
410 BOOL WINAPI GetComputerNameExA(COMPUTER_NAME_FORMAT type, LPSTR name, LPDWORD size)
411 {
412     char buf[256];
413     int len = sizeof(buf) - 1, ret;
414     TRACE("%d, %p, %p\n", type, name, size);
415     switch( type )
416     {
417     case ComputerNameNetBIOS:
418     case ComputerNamePhysicalNetBIOS:
419         return GetComputerNameA (name, size);
420     case ComputerNameDnsHostname:
421     case ComputerNamePhysicalDnsHostname:
422         ret = dns_hostname (buf, &len);
423         break;
424     case ComputerNameDnsDomain:
425     case ComputerNamePhysicalDnsDomain:
426         ret = dns_domainname (buf, &len);
427         break;
428     case ComputerNameDnsFullyQualified:
429     case ComputerNamePhysicalDnsFullyQualified:
430         ret = dns_fqdn (buf, &len);
431         break;
432     default:
433         SetLastError (ERROR_INVALID_PARAMETER);
434         return FALSE;
435     }
436
437     if ( ret )
438     {
439         TRACE ("-> %s (%d)\n", debugstr_a (buf), len);
440         if ( *size < len + 1 )
441         {
442             *size = len + 1;
443             SetLastError( ERROR_MORE_DATA );
444             ret = FALSE;
445         }
446         else
447         {
448             memcpy( name, buf, len );
449             name[len] = 0;
450             *size = len;
451             ret = TRUE;
452         }
453     }
454
455     return ret;
456 }
457
458
459 /***********************************************************************
460  *              GetComputerNameExW         (KERNEL32.@)
461  */
462 BOOL WINAPI GetComputerNameExW( COMPUTER_NAME_FORMAT type, LPWSTR name, LPDWORD size )
463 {
464     char buf[256];
465     int len = sizeof(buf) - 1, ret;
466
467     TRACE("%d, %p, %p\n", type, name, size);
468     switch( type )
469     {
470     case ComputerNameNetBIOS:
471     case ComputerNamePhysicalNetBIOS:
472         return GetComputerNameW (name, size);
473     case ComputerNameDnsHostname:
474     case ComputerNamePhysicalDnsHostname:
475         ret = dns_hostname (buf, &len);
476         break;
477     case ComputerNameDnsDomain:
478     case ComputerNamePhysicalDnsDomain:
479         ret = dns_domainname (buf, &len);
480         break;
481     case ComputerNameDnsFullyQualified:
482     case ComputerNamePhysicalDnsFullyQualified:
483         ret = dns_fqdn (buf, &len);
484         break;
485     default:
486         SetLastError (ERROR_INVALID_PARAMETER);
487         return FALSE;
488     }
489
490     if ( ret )
491     {
492         unsigned int lenW;
493
494         TRACE ("-> %s (%d)\n", debugstr_a (buf), len);
495
496         lenW = MultiByteToWideChar( CP_ACP, 0, buf, len, NULL, 0 );
497         if ( *size < lenW + 1 )
498         {
499             *size = lenW + 1;
500             SetLastError( ERROR_MORE_DATA );
501             ret = FALSE;
502         }
503         else
504         {
505             MultiByteToWideChar( CP_ACP, 0, buf, len, name, lenW );
506             name[lenW] = 0;
507             *size = lenW;
508             ret = TRUE;
509         }
510     }
511
512     return ret;
513 }
514
515 /******************************************************************************
516  * netbios_char (INTERNAL)
517  */
518 static WCHAR netbios_char ( WCHAR wc )
519 {
520     static const WCHAR special[] = {'!','@','#','$','%','^','&','\'',')','(','-','_','{','}','~'};
521     static const WCHAR deflt = '_';
522     unsigned int i;
523     
524     if ( isalnumW ( wc ) ) return wc;
525     for ( i = 0; i < sizeof (special) / sizeof (WCHAR); i++ )
526         if ( wc == special[i] ) return wc;
527     return deflt;
528 }
529
530 /******************************************************************************
531  * SetComputerNameW [KERNEL32.@]
532  *
533  * Set a new NetBIOS name for the local computer.
534  *
535  * PARAMS
536  *    lpComputerName [I] Address of new computer name
537  *
538  * RETURNS
539  *    Success: TRUE
540  *    Failure: FALSE
541  */
542 BOOL WINAPI SetComputerNameW( LPCWSTR lpComputerName )
543 {
544     UNICODE_STRING nameW;
545     OBJECT_ATTRIBUTES attr;
546     HANDLE hkey = INVALID_HANDLE_VALUE, hsubkey = INVALID_HANDLE_VALUE;
547     int plen = strlenW ( lpComputerName );
548     int i;
549     NTSTATUS st = STATUS_INTERNAL_ERROR;
550
551     if (get_use_dns_option())
552     {
553         /* This check isn't necessary, but may help debugging problems. */
554         WARN( "Disabled by Wine Configuration.\n" );
555         WARN( "Set \"UseDnsComputerName\" = \"N\" in category [Network] to enable.\n" );
556         SetLastError ( ERROR_ACCESS_DENIED );
557         return FALSE;
558     }
559
560     TRACE( "%s\n", debugstr_w (lpComputerName) );
561
562     /* Check parameter */
563     if ( plen > MAX_COMPUTERNAME_LENGTH ) 
564         goto out;
565
566     /* This is NT behaviour. Win 95/98 would coerce characters. */
567     for ( i = 0; i < plen; i++ )
568     {
569         WCHAR wc = lpComputerName[i];
570         if ( wc != netbios_char( wc ) )
571             goto out;
572     }
573     
574     _init_attr ( &attr, &nameW );
575     
576     RtlInitUnicodeString (&nameW, ComputerW);
577     if ( ( st = NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr ) ) != STATUS_SUCCESS )
578         goto out;
579     attr.RootDirectory = hkey;
580     RtlInitUnicodeString( &nameW, ComputerNameW );
581     if ( ( st = NtOpenKey( &hsubkey, KEY_ALL_ACCESS, &attr ) ) != STATUS_SUCCESS )
582         goto out;
583     if ( ( st = NtSetValueKey( hsubkey, &nameW, 0, REG_SZ, lpComputerName, ( plen + 1) * sizeof(WCHAR) ) )
584          != STATUS_SUCCESS )
585         goto out;
586
587 out:
588     NtClose( hsubkey );
589     NtClose( hkey );
590     
591     if ( st == STATUS_SUCCESS )
592     {
593         TRACE( "ComputerName changed\n" );
594         return TRUE;
595     }
596
597     else
598     {
599         SetLastError ( RtlNtStatusToDosError ( st ) );
600         WARN ( "status %u\n", st );
601         return FALSE;
602     }
603 }
604
605 /******************************************************************************
606  * SetComputerNameA [KERNEL32.@]
607  *
608  * See SetComputerNameW.
609  */
610 BOOL WINAPI SetComputerNameA( LPCSTR lpComputerName )
611 {
612     BOOL ret;
613     DWORD len = MultiByteToWideChar( CP_ACP, 0, lpComputerName, -1, NULL, 0 );
614     LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
615
616     MultiByteToWideChar( CP_ACP, 0, lpComputerName, -1, nameW, len );
617     ret = SetComputerNameW( nameW );
618     HeapFree( GetProcessHeap(), 0, nameW );
619     return ret;
620 }
621
622 /******************************************************************************
623  * SetComputerNameExW [KERNEL32.@]
624  *
625  */
626 BOOL WINAPI SetComputerNameExW( COMPUTER_NAME_FORMAT type, LPCWSTR lpComputerName )
627 {
628     TRACE("%d, %s\n", type, debugstr_w (lpComputerName));
629     switch( type )
630     {
631     case ComputerNameNetBIOS:
632     case ComputerNamePhysicalNetBIOS:
633         return SetComputerNameW( lpComputerName );
634     default:
635         SetLastError( ERROR_ACCESS_DENIED );
636         return FALSE;
637     }
638 }
639
640 /******************************************************************************
641  * SetComputerNameExA [KERNEL32.@]
642  *
643  */
644 BOOL WINAPI SetComputerNameExA( COMPUTER_NAME_FORMAT type, LPCSTR lpComputerName )
645 {
646     TRACE( "%d, %s\n", type, debugstr_a (lpComputerName) );
647     switch( type )
648     {
649     case ComputerNameNetBIOS:
650     case ComputerNamePhysicalNetBIOS:
651         return SetComputerNameA( lpComputerName );
652     default:
653         SetLastError( ERROR_ACCESS_DENIED );
654         return FALSE;
655     }
656 }
657
658 /***********************************************************************
659  *              DnsHostnameToComputerNameA         (KERNEL32.@)
660  */
661 BOOL WINAPI DnsHostnameToComputerNameA(LPCSTR hostname,
662     LPSTR computername, LPDWORD size)
663 {
664     DWORD len;
665
666     FIXME("(%s, %p, %p): stub\n", debugstr_a(hostname), computername, size);
667
668     if (!hostname || !size) return FALSE;
669     len = lstrlenA(hostname);
670
671     if (len > MAX_COMPUTERNAME_LENGTH)
672         len = MAX_COMPUTERNAME_LENGTH;
673
674     if (*size < len)
675     {
676         *size = len;
677         return FALSE;
678     }
679     if (!computername) return FALSE;
680
681     memcpy( computername, hostname, len );
682     computername[len + 1] = 0;
683     return TRUE;
684 }
685
686 /***********************************************************************
687  *              DnsHostnameToComputerNameW         (KERNEL32.@)
688  */
689 BOOL WINAPI DnsHostnameToComputerNameW(LPCWSTR hostname,
690     LPWSTR computername, LPDWORD size)
691 {
692     DWORD len;
693
694     FIXME("(%s, %p, %p): stub\n", debugstr_w(hostname), computername, size);
695
696     if (!hostname || !size) return FALSE;
697     len = lstrlenW(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 * sizeof(WCHAR) );
710     computername[len + 1] = 0;
711     return TRUE;
712 }