xref: /reactos/dll/win32/kernel32/client/compname.c (revision 09dde2cf)
1 /*
2  *  ReactOS kernel
3  *  Copyright (C) 2003 ReactOS Team
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 /*
20  * COPYRIGHT:       See COPYING in the top level directory
21  * PROJECT:         ReactOS system libraries
22  * PURPOSE:         Computer name functions
23  * FILE:            dll/win32/kernel32/client/compname.c
24  * PROGRAMERS:      Eric Kohl
25  *                  Katayama Hirofumi MZ
26  */
27 
28 /* INCLUDES ******************************************************************/
29 
30 #include <k32.h>
31 #include <windns.h>
32 
33 #define NDEBUG
34 #include <debug.h>
35 
36 typedef NTSTATUS (WINAPI *FN_DnsValidateName_W)(LPCWSTR, DNS_NAME_FORMAT);
37 
38 /* FUNCTIONS *****************************************************************/
39 
40 static
41 BOOL
42 GetComputerNameFromRegistry(LPWSTR RegistryKey,
43                             LPWSTR ValueNameStr,
44                             LPWSTR lpBuffer,
45                             LPDWORD nSize)
46 {
47     PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
48     OBJECT_ATTRIBUTES ObjectAttributes;
49     UNICODE_STRING KeyName;
50     UNICODE_STRING ValueName;
51     HANDLE KeyHandle;
52     ULONG KeyInfoSize;
53     ULONG ReturnSize;
54     NTSTATUS Status;
55 
56     if (lpBuffer != NULL && *nSize > 0)
57         lpBuffer[0] = 0;
58 
59     RtlInitUnicodeString(&KeyName, RegistryKey);
60     InitializeObjectAttributes(&ObjectAttributes,
61                                &KeyName,
62                                OBJ_CASE_INSENSITIVE,
63                                NULL,
64                                NULL);
65 
66     Status = NtOpenKey(&KeyHandle,
67                        KEY_READ,
68                        &ObjectAttributes);
69     if (!NT_SUCCESS(Status))
70     {
71         BaseSetLastNTError (Status);
72         return FALSE;
73     }
74 
75     KeyInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + *nSize * sizeof(WCHAR);
76     KeyInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, KeyInfoSize);
77     if (KeyInfo == NULL)
78     {
79         NtClose(KeyHandle);
80         SetLastError(ERROR_OUTOFMEMORY);
81         return FALSE;
82     }
83 
84     RtlInitUnicodeString(&ValueName, ValueNameStr);
85 
86     Status = NtQueryValueKey(KeyHandle,
87                              &ValueName,
88                              KeyValuePartialInformation,
89                              KeyInfo,
90                              KeyInfoSize,
91                              &ReturnSize);
92 
93     NtClose(KeyHandle);
94 
95     if (!NT_SUCCESS(Status))
96     {
97         *nSize = (ReturnSize - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data)) / sizeof(WCHAR);
98         goto failed;
99     }
100 
101     if (KeyInfo->Type != REG_SZ)
102     {
103         Status = STATUS_UNSUCCESSFUL;
104         goto failed;
105     }
106 
107     if (!lpBuffer || *nSize < (KeyInfo->DataLength / sizeof(WCHAR)))
108     {
109         *nSize = (ReturnSize - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data)) / sizeof(WCHAR);
110         Status = STATUS_BUFFER_OVERFLOW;
111         goto failed;
112     }
113 
114     *nSize = KeyInfo->DataLength / sizeof(WCHAR) - 1;
115     RtlCopyMemory(lpBuffer, KeyInfo->Data, KeyInfo->DataLength);
116     lpBuffer[*nSize] = 0;
117 
118     RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
119 
120     return TRUE;
121 
122 failed:
123     RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
124     BaseSetLastNTError(Status);
125     return FALSE;
126 }
127 
128 
129 static
130 BOOL
131 SetActiveComputerNameToRegistry(LPCWSTR RegistryKey,
132                                 LPCWSTR SubKey,
133                                 LPCWSTR ValueNameStr,
134                                 LPCWSTR lpBuffer)
135 {
136     OBJECT_ATTRIBUTES ObjectAttributes;
137     UNICODE_STRING KeyName;
138     UNICODE_STRING ValueName;
139     HANDLE KeyHandle, SubKeyHandle;
140     SIZE_T StringLength;
141     ULONG Disposition;
142     NTSTATUS Status;
143 
144     StringLength = wcslen(lpBuffer);
145     if (StringLength > ((MAXULONG / sizeof(WCHAR)) - 1))
146     {
147         return FALSE;
148     }
149 
150     RtlInitUnicodeString(&KeyName, RegistryKey);
151     InitializeObjectAttributes(&ObjectAttributes,
152                                &KeyName,
153                                OBJ_CASE_INSENSITIVE,
154                                NULL,
155                                NULL);
156 
157     Status = NtOpenKey(&KeyHandle,
158                        KEY_WRITE,
159                        &ObjectAttributes);
160     if (!NT_SUCCESS(Status))
161     {
162         BaseSetLastNTError(Status);
163         return FALSE;
164     }
165 
166     RtlInitUnicodeString(&KeyName, SubKey);
167     InitializeObjectAttributes(&ObjectAttributes,
168                                &KeyName,
169                                OBJ_CASE_INSENSITIVE,
170                                KeyHandle,
171                                NULL);
172 
173     Status = NtCreateKey(&SubKeyHandle,
174                          KEY_WRITE,
175                          &ObjectAttributes,
176                          0,
177                          NULL,
178                          REG_OPTION_VOLATILE,
179                          &Disposition);
180     if (!NT_SUCCESS(Status))
181     {
182         NtClose(KeyHandle);
183         BaseSetLastNTError(Status);
184         return FALSE;
185     }
186 
187     RtlInitUnicodeString(&ValueName, ValueNameStr);
188 
189     Status = NtSetValueKey(SubKeyHandle,
190                            &ValueName,
191                            0,
192                            REG_SZ,
193                            (PVOID)lpBuffer,
194                            (StringLength + 1) * sizeof(WCHAR));
195     if (!NT_SUCCESS(Status))
196     {
197         NtClose(SubKeyHandle);
198         NtClose(KeyHandle);
199         BaseSetLastNTError(Status);
200         return FALSE;
201     }
202 
203     NtFlushKey(SubKeyHandle);
204     NtClose(SubKeyHandle);
205     NtClose(KeyHandle);
206 
207     return TRUE;
208 }
209 
210 
211 /*
212  * @implemented
213  */
214 BOOL
215 WINAPI
216 GetComputerNameExW(COMPUTER_NAME_FORMAT NameType,
217                    LPWSTR lpBuffer,
218                    LPDWORD nSize)
219 {
220     UNICODE_STRING ResultString;
221     UNICODE_STRING DomainPart;
222     RTL_QUERY_REGISTRY_TABLE QueryTable[2];
223     NTSTATUS Status;
224     BOOL ret = TRUE;
225     DWORD HostSize;
226 
227     if ((nSize == NULL) ||
228         (lpBuffer == NULL && *nSize > 0))
229     {
230         SetLastError(ERROR_INVALID_PARAMETER);
231         return FALSE;
232     }
233 
234     switch (NameType)
235     {
236         case ComputerNameNetBIOS:
237             ret = GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
238                                                L"\\Control\\ComputerName\\ActiveComputerName",
239                                                L"ComputerName",
240                                                lpBuffer,
241                                                nSize);
242             if ((ret == FALSE) &&
243                 (GetLastError() != ERROR_MORE_DATA))
244             {
245                 ret = GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
246                                                   L"\\Control\\ComputerName\\ComputerName",
247                                                   L"ComputerName",
248                                                   lpBuffer,
249                                                   nSize);
250                 if (ret)
251                 {
252                     ret = SetActiveComputerNameToRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
253                                                           L"\\Control\\ComputerName",
254                                                           L"ActiveComputerName",
255                                                           L"ComputerName",
256                                                           lpBuffer);
257                 }
258             }
259             return ret;
260 
261         case ComputerNameDnsDomain:
262             return GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
263                                                L"\\Services\\Tcpip\\Parameters",
264                                                L"Domain",
265                                                lpBuffer,
266                                                nSize);
267 
268         case ComputerNameDnsFullyQualified:
269             ResultString.Length = 0;
270             ResultString.MaximumLength = (USHORT)*nSize * sizeof(WCHAR);
271             ResultString.Buffer = lpBuffer;
272 
273             RtlZeroMemory(QueryTable, sizeof(QueryTable));
274             RtlInitUnicodeString(&DomainPart, NULL);
275 
276             QueryTable[0].Name = L"HostName";
277             QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
278             QueryTable[0].EntryContext = &DomainPart;
279 
280             Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
281                                             L"\\Registry\\Machine\\System"
282                                             L"\\CurrentControlSet\\Services\\Tcpip"
283                                             L"\\Parameters",
284                                             QueryTable,
285                                             NULL,
286                                             NULL);
287 
288             if (NT_SUCCESS(Status))
289             {
290                 Status = RtlAppendUnicodeStringToString(&ResultString, &DomainPart);
291                 HostSize = DomainPart.Length;
292 
293                 if (!NT_SUCCESS(Status))
294                 {
295                     ret = FALSE;
296                 }
297 
298                 RtlAppendUnicodeToString(&ResultString, L".");
299                 RtlFreeUnicodeString(&DomainPart);
300 
301                 RtlInitUnicodeString(&DomainPart, NULL);
302                 QueryTable[0].Name = L"Domain";
303                 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
304                 QueryTable[0].EntryContext = &DomainPart;
305 
306                 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
307                                                 L"\\Registry\\Machine\\System"
308                                                 L"\\CurrentControlSet\\Services\\Tcpip"
309                                                 L"\\Parameters",
310                                                 QueryTable,
311                                                 NULL,
312                                                 NULL);
313 
314                 if (NT_SUCCESS(Status))
315                 {
316                     Status = RtlAppendUnicodeStringToString(&ResultString, &DomainPart);
317                     if ((!NT_SUCCESS(Status)) || (!ret))
318                     {
319                         *nSize = HostSize + DomainPart.Length;
320                         SetLastError(ERROR_MORE_DATA);
321                         RtlFreeUnicodeString(&DomainPart);
322                         return FALSE;
323                     }
324                     RtlFreeUnicodeString(&DomainPart);
325                     *nSize = ResultString.Length / sizeof(WCHAR) - 1;
326                     return TRUE;
327                 }
328             }
329             return FALSE;
330 
331         case ComputerNameDnsHostname:
332             return GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
333                                                L"\\Services\\Tcpip\\Parameters",
334                                                L"Hostname",
335                                                lpBuffer,
336                                                nSize);
337 
338         case ComputerNamePhysicalDnsDomain:
339             return GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
340                                                L"\\Services\\Tcpip\\Parameters",
341                                                L"NV Domain",
342                                                lpBuffer,
343                                                nSize);
344 
345         /* XXX Redo this */
346         case ComputerNamePhysicalDnsFullyQualified:
347             return GetComputerNameExW(ComputerNameDnsFullyQualified,
348                                       lpBuffer,
349                                       nSize);
350 
351         case ComputerNamePhysicalDnsHostname:
352             return GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
353                                                L"\\Services\\Tcpip\\Parameters",
354                                                L"NV Hostname",
355                                                lpBuffer,
356                                                nSize);
357 
358         /* XXX Redo this */
359         case ComputerNamePhysicalNetBIOS:
360             return GetComputerNameExW(ComputerNameNetBIOS,
361                                       lpBuffer,
362                                       nSize);
363 
364         case ComputerNameMax:
365             return FALSE;
366     }
367 
368     return FALSE;
369 }
370 
371 /*
372  * @implemented
373  */
374 BOOL
375 WINAPI
376 GetComputerNameExA(COMPUTER_NAME_FORMAT NameType,
377                    LPSTR lpBuffer,
378                    LPDWORD nSize)
379 {
380     UNICODE_STRING UnicodeString;
381     ANSI_STRING AnsiString;
382     BOOL Result;
383     PWCHAR TempBuffer = NULL;
384 
385     if ((nSize == NULL) ||
386         (lpBuffer == NULL && *nSize > 0))
387     {
388         SetLastError(ERROR_INVALID_PARAMETER);
389         return FALSE;
390     }
391 
392     if (*nSize > 0)
393     {
394         TempBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, *nSize * sizeof(WCHAR));
395         if (!TempBuffer)
396         {
397             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
398             return FALSE;
399         }
400     }
401 
402     AnsiString.MaximumLength = (USHORT)*nSize;
403     AnsiString.Length = 0;
404     AnsiString.Buffer = lpBuffer;
405 
406     Result = GetComputerNameExW(NameType, TempBuffer, nSize);
407 
408     if (Result)
409     {
410         UnicodeString.MaximumLength = (USHORT)*nSize * sizeof(WCHAR) + sizeof(WCHAR);
411         UnicodeString.Length = (USHORT)*nSize * sizeof(WCHAR);
412         UnicodeString.Buffer = TempBuffer;
413 
414         RtlUnicodeStringToAnsiString(&AnsiString,
415                                      &UnicodeString,
416                                      FALSE);
417     }
418 
419     RtlFreeHeap(RtlGetProcessHeap(), 0, TempBuffer);
420 
421     return Result;
422 }
423 
424 /*
425  * @implemented
426  */
427 BOOL
428 WINAPI
429 GetComputerNameA(LPSTR lpBuffer, LPDWORD lpnSize)
430 {
431     BOOL ret;
432 
433     ret = GetComputerNameExA(ComputerNameNetBIOS, lpBuffer, lpnSize);
434     if (!ret && GetLastError() == ERROR_MORE_DATA)
435         SetLastError(ERROR_BUFFER_OVERFLOW);
436 
437     return ret;
438 }
439 
440 
441 /*
442  * @implemented
443  */
444 BOOL
445 WINAPI
446 GetComputerNameW(LPWSTR lpBuffer, LPDWORD lpnSize)
447 {
448     BOOL ret;
449 
450     ret = GetComputerNameExW(ComputerNameNetBIOS, lpBuffer, lpnSize);
451     if (!ret && GetLastError() == ERROR_MORE_DATA)
452         SetLastError(ERROR_BUFFER_OVERFLOW);
453 
454     return ret;
455 }
456 
457 static
458 BOOL
459 BaseVerifyDnsName(LPCWSTR lpDnsName)
460 {
461     HINSTANCE hDNSAPI;
462     FN_DnsValidateName_W fnValidate;
463     NTSTATUS Status;
464     BOOL ret = FALSE;
465 
466     hDNSAPI = LoadLibraryW(L"dnsapi.dll");
467     if (hDNSAPI == NULL)
468         return FALSE;
469 
470     fnValidate = (FN_DnsValidateName_W)GetProcAddress(hDNSAPI, "DnsValidateName_W");
471     if (fnValidate)
472     {
473         Status = (*fnValidate)(lpDnsName, DnsNameHostnameLabel);
474         if (Status == STATUS_SUCCESS || Status == DNS_ERROR_NON_RFC_NAME)
475             ret = TRUE;
476     }
477 
478     FreeLibrary(hDNSAPI);
479 
480     return ret;
481 }
482 
483 /*
484  * @implemented
485  */
486 static
487 BOOL
488 IsValidComputerName(COMPUTER_NAME_FORMAT NameType,
489                     LPCWSTR lpComputerName)
490 {
491     size_t Length;
492     static const WCHAR s_szInvalidChars[] =
493         L"\"/\\[]:|<>+=;,?"
494         L"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
495         L"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F";
496 
497     if (lpComputerName == NULL)
498         return FALSE;
499 
500 #define MAX_COMPUTER_NAME_EX 64
501     /* Get string length */
502     if (!NT_SUCCESS(RtlStringCchLengthW(lpComputerName, MAX_COMPUTER_NAME_EX + 1, &Length)))
503         return FALSE;
504 #undef MAX_COMPUTER_NAME_EX
505 
506     /* An empty name is invalid, except a DNS name */
507     if (Length == 0 && NameType != ComputerNamePhysicalDnsDomain)
508         return FALSE;
509 
510     /* Leading or trailing spaces are invalid */
511     if (Length > 0 &&
512         (lpComputerName[0] == L' ' || lpComputerName[Length - 1] == L' '))
513     {
514         return FALSE;
515     }
516 
517     /* Check whether the name contains any invalid character */
518     if (wcscspn(lpComputerName, s_szInvalidChars) < Length)
519         return FALSE;
520 
521     switch (NameType)
522     {
523         case ComputerNamePhysicalNetBIOS:
524             if (Length > MAX_COMPUTERNAME_LENGTH)
525                 return FALSE;
526             return TRUE;
527 
528         case ComputerNamePhysicalDnsDomain:
529             /* An empty DNS name is valid */
530             if (Length != 0)
531                 return BaseVerifyDnsName(lpComputerName);
532             return TRUE;
533 
534         case ComputerNamePhysicalDnsHostname:
535             return BaseVerifyDnsName(lpComputerName);
536 
537         default:
538             return FALSE;
539     }
540 }
541 
542 static
543 BOOL
544 SetComputerNameToRegistry(LPCWSTR RegistryKey,
545                           LPCWSTR ValueNameStr,
546                           LPCWSTR lpBuffer)
547 {
548     OBJECT_ATTRIBUTES ObjectAttributes;
549     UNICODE_STRING KeyName;
550     UNICODE_STRING ValueName;
551     HANDLE KeyHandle;
552     SIZE_T StringLength;
553     NTSTATUS Status;
554 
555     StringLength = wcslen(lpBuffer);
556     if (StringLength > ((MAXULONG / sizeof(WCHAR)) - 1))
557     {
558         return FALSE;
559     }
560 
561     RtlInitUnicodeString(&KeyName, RegistryKey);
562     InitializeObjectAttributes(&ObjectAttributes,
563                                &KeyName,
564                                OBJ_CASE_INSENSITIVE,
565                                NULL,
566                                NULL);
567 
568     Status = NtOpenKey(&KeyHandle,
569                        KEY_WRITE,
570                        &ObjectAttributes);
571     if (!NT_SUCCESS(Status))
572     {
573         BaseSetLastNTError(Status);
574         return FALSE;
575     }
576 
577     RtlInitUnicodeString(&ValueName, ValueNameStr);
578 
579     Status = NtSetValueKey(KeyHandle,
580                            &ValueName,
581                            0,
582                            REG_SZ,
583                            (PVOID)lpBuffer,
584                            (StringLength + 1) * sizeof(WCHAR));
585     if (!NT_SUCCESS(Status))
586     {
587         NtClose(KeyHandle);
588         BaseSetLastNTError(Status);
589         return FALSE;
590     }
591 
592     NtFlushKey(KeyHandle);
593     NtClose(KeyHandle);
594 
595     SetLastError(ERROR_SUCCESS);
596     return TRUE;
597 }
598 
599 
600 /*
601  * @implemented
602  */
603 BOOL
604 WINAPI
605 SetComputerNameA(LPCSTR lpComputerName)
606 {
607     return SetComputerNameExA(ComputerNamePhysicalNetBIOS, lpComputerName);
608 }
609 
610 
611 /*
612  * @implemented
613  */
614 BOOL
615 WINAPI
616 SetComputerNameW(LPCWSTR lpComputerName)
617 {
618     return SetComputerNameExW(ComputerNamePhysicalNetBIOS, lpComputerName);
619 }
620 
621 
622 /*
623  * @implemented
624  */
625 BOOL
626 WINAPI
627 SetComputerNameExA(COMPUTER_NAME_FORMAT NameType,
628                    LPCSTR lpBuffer)
629 {
630     UNICODE_STRING Buffer;
631     BOOL bResult;
632 
633     RtlCreateUnicodeStringFromAsciiz(&Buffer, (LPSTR)lpBuffer);
634 
635     bResult = SetComputerNameExW(NameType, Buffer.Buffer);
636 
637     RtlFreeUnicodeString(&Buffer);
638 
639     return bResult;
640 }
641 
642 
643 /*
644  * @implemented
645  */
646 BOOL
647 WINAPI
648 SetComputerNameExW(COMPUTER_NAME_FORMAT NameType,
649                    LPCWSTR lpBuffer)
650 {
651     WCHAR szShortName[MAX_COMPUTERNAME_LENGTH + 1];
652     BOOL ret1, ret2;
653 
654     if (!IsValidComputerName(NameType, lpBuffer))
655     {
656         SetLastError(ERROR_INVALID_PARAMETER);
657         return FALSE;
658     }
659 
660     switch (NameType)
661     {
662         case ComputerNamePhysicalDnsDomain:
663             return SetComputerNameToRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
664                                              L"\\Services\\Tcpip\\Parameters",
665                                              L"NV Domain",
666                                              lpBuffer);
667 
668         case ComputerNamePhysicalDnsHostname:
669             ret1 = SetComputerNameToRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
670                                              L"\\Services\\Tcpip\\Parameters",
671                                              L"NV Hostname",
672                                              lpBuffer);
673 
674             RtlStringCchCopyNW(szShortName, ARRAYSIZE(szShortName), lpBuffer, MAX_COMPUTERNAME_LENGTH);
675             ret2 = SetComputerNameToRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
676                                              L"\\Control\\ComputerName\\ComputerName",
677                                              L"ComputerName",
678                                              szShortName);
679             return (ret1 && ret2);
680 
681         case ComputerNamePhysicalNetBIOS:
682             RtlStringCchCopyNW(szShortName, ARRAYSIZE(szShortName), lpBuffer, MAX_COMPUTERNAME_LENGTH);
683             return SetComputerNameToRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
684                                              L"\\Control\\ComputerName\\ComputerName",
685                                              L"ComputerName",
686                                              szShortName);
687 
688         default:
689             SetLastError(ERROR_INVALID_PARAMETER);
690             return FALSE;
691     }
692 }
693 
694 
695 /*
696  * @implemented
697  */
698 BOOL
699 WINAPI
700 DnsHostnameToComputerNameA(LPCSTR Hostname,
701                            LPSTR ComputerName,
702                            LPDWORD nSize)
703 {
704     DWORD len;
705 
706     DPRINT("(%s, %p, %p)\n", Hostname, ComputerName, nSize);
707 
708     if (!Hostname || !nSize)
709         return FALSE;
710 
711     len = lstrlenA(Hostname);
712 
713     if (len > MAX_COMPUTERNAME_LENGTH)
714         len = MAX_COMPUTERNAME_LENGTH;
715 
716     if (*nSize < len)
717     {
718         *nSize = len;
719         return FALSE;
720     }
721 
722     if (!ComputerName) return FALSE;
723 
724     memcpy(ComputerName, Hostname, len);
725     ComputerName[len + 1] = 0;
726     return TRUE;
727 }
728 
729 
730 /*
731  * @implemented
732  */
733 BOOL
734 WINAPI
735 DnsHostnameToComputerNameW(LPCWSTR hostname,
736                            LPWSTR computername,
737                            LPDWORD size)
738 {
739     DWORD len;
740 
741     DPRINT("(%s, %p, %p): stub\n", hostname, computername, size);
742 
743     if (!hostname || !size) return FALSE;
744     len = lstrlenW(hostname);
745 
746     if (len > MAX_COMPUTERNAME_LENGTH)
747         len = MAX_COMPUTERNAME_LENGTH;
748 
749     if (*size < len)
750     {
751         *size = len;
752         return FALSE;
753     }
754     if (!computername) return FALSE;
755 
756     memcpy(computername, hostname, len * sizeof(WCHAR));
757     computername[len + 1] = 0;
758     return TRUE;
759 }
760 
761 DWORD
762 WINAPI
763 AddLocalAlternateComputerNameA(LPSTR lpName, PNTSTATUS Status)
764 {
765     STUB;
766     return 0;
767 }
768 
769 DWORD
770 WINAPI
771 AddLocalAlternateComputerNameW(LPWSTR lpName, PNTSTATUS Status)
772 {
773     STUB;
774     return 0;
775 }
776 
777 DWORD
778 WINAPI
779 EnumerateLocalComputerNamesA(PVOID pUnknown, DWORD Size, LPSTR lpBuffer, LPDWORD lpnSize)
780 {
781     STUB;
782     return ERROR_CALL_NOT_IMPLEMENTED;
783 }
784 
785 DWORD
786 WINAPI
787 EnumerateLocalComputerNamesW(PVOID pUnknown, DWORD Size, LPWSTR lpBuffer, LPDWORD lpnSize)
788 {
789     STUB;
790     return ERROR_CALL_NOT_IMPLEMENTED;
791 }
792 
793 DWORD
794 WINAPI
795 RemoveLocalAlternateComputerNameA(LPSTR lpName, DWORD Unknown)
796 {
797     STUB;
798     return ERROR_CALL_NOT_IMPLEMENTED;
799 }
800 
801 DWORD
802 WINAPI
803 RemoveLocalAlternateComputerNameW(LPWSTR lpName, DWORD Unknown)
804 {
805     STUB;
806     return ERROR_CALL_NOT_IMPLEMENTED;
807 }
808 
809 /*
810  * @unimplemented
811  */
812 BOOL
813 WINAPI
814 SetLocalPrimaryComputerNameA(IN DWORD Unknown1,
815                              IN DWORD Unknown2)
816 {
817     STUB;
818     return FALSE;
819 }
820 
821 /*
822  * @unimplemented
823  */
824 BOOL
825 WINAPI
826 SetLocalPrimaryComputerNameW(IN DWORD Unknown1,
827                              IN DWORD Unknown2)
828 {
829     STUB;
830     return FALSE;
831 }
832 
833 
834 /* EOF */
835