xref: /reactos/dll/win32/kernel32/client/compname.c (revision 53221834)
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     BOOL ret1, ret2;
652 
653     if (!IsValidComputerName(NameType, lpBuffer))
654     {
655         SetLastError(ERROR_INVALID_PARAMETER);
656         return FALSE;
657     }
658 
659     switch (NameType)
660     {
661         case ComputerNamePhysicalDnsDomain:
662             return SetComputerNameToRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
663                                              L"\\Services\\Tcpip\\Parameters",
664                                              L"NV Domain",
665                                              lpBuffer);
666 
667         case ComputerNamePhysicalDnsHostname:
668             ret1 = SetComputerNameToRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
669                                              L"\\Services\\Tcpip\\Parameters",
670                                              L"NV Hostname",
671                                              lpBuffer);
672 
673             ret2 = SetComputerNameToRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
674                                              L"\\Control\\ComputerName\\ComputerName",
675                                              L"ComputerName",
676                                              lpBuffer);
677             return (ret1 && ret2);
678 
679         case ComputerNamePhysicalNetBIOS:
680             return SetComputerNameToRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
681                                              L"\\Control\\ComputerName\\ComputerName",
682                                              L"ComputerName",
683                                              lpBuffer);
684 
685         default:
686             SetLastError(ERROR_INVALID_PARAMETER);
687             return FALSE;
688     }
689 }
690 
691 
692 /*
693  * @implemented
694  */
695 BOOL
696 WINAPI
697 DnsHostnameToComputerNameA(LPCSTR Hostname,
698                            LPSTR ComputerName,
699                            LPDWORD nSize)
700 {
701     DWORD len;
702 
703     DPRINT("(%s, %p, %p)\n", Hostname, ComputerName, nSize);
704 
705     if (!Hostname || !nSize)
706         return FALSE;
707 
708     len = lstrlenA(Hostname);
709 
710     if (len > MAX_COMPUTERNAME_LENGTH)
711         len = MAX_COMPUTERNAME_LENGTH;
712 
713     if (*nSize < len)
714     {
715         *nSize = len;
716         return FALSE;
717     }
718 
719     if (!ComputerName) return FALSE;
720 
721     memcpy(ComputerName, Hostname, len);
722     ComputerName[len + 1] = 0;
723     return TRUE;
724 }
725 
726 
727 /*
728  * @implemented
729  */
730 BOOL
731 WINAPI
732 DnsHostnameToComputerNameW(LPCWSTR hostname,
733                            LPWSTR computername,
734                            LPDWORD size)
735 {
736     DWORD len;
737 
738     DPRINT("(%s, %p, %p): stub\n", hostname, computername, size);
739 
740     if (!hostname || !size) return FALSE;
741     len = lstrlenW(hostname);
742 
743     if (len > MAX_COMPUTERNAME_LENGTH)
744         len = MAX_COMPUTERNAME_LENGTH;
745 
746     if (*size < len)
747     {
748         *size = len;
749         return FALSE;
750     }
751     if (!computername) return FALSE;
752 
753     memcpy(computername, hostname, len * sizeof(WCHAR));
754     computername[len + 1] = 0;
755     return TRUE;
756 }
757 
758 DWORD
759 WINAPI
760 AddLocalAlternateComputerNameA(LPSTR lpName, PNTSTATUS Status)
761 {
762     STUB;
763     return 0;
764 }
765 
766 DWORD
767 WINAPI
768 AddLocalAlternateComputerNameW(LPWSTR lpName, PNTSTATUS Status)
769 {
770     STUB;
771     return 0;
772 }
773 
774 DWORD
775 WINAPI
776 EnumerateLocalComputerNamesA(PVOID pUnknown, DWORD Size, LPSTR lpBuffer, LPDWORD lpnSize)
777 {
778     STUB;
779     return ERROR_CALL_NOT_IMPLEMENTED;
780 }
781 
782 DWORD
783 WINAPI
784 EnumerateLocalComputerNamesW(PVOID pUnknown, DWORD Size, LPWSTR lpBuffer, LPDWORD lpnSize)
785 {
786     STUB;
787     return ERROR_CALL_NOT_IMPLEMENTED;
788 }
789 
790 DWORD
791 WINAPI
792 RemoveLocalAlternateComputerNameA(LPSTR lpName, DWORD Unknown)
793 {
794     STUB;
795     return ERROR_CALL_NOT_IMPLEMENTED;
796 }
797 
798 DWORD
799 WINAPI
800 RemoveLocalAlternateComputerNameW(LPWSTR lpName, DWORD Unknown)
801 {
802     STUB;
803     return ERROR_CALL_NOT_IMPLEMENTED;
804 }
805 
806 /*
807  * @unimplemented
808  */
809 BOOL
810 WINAPI
811 SetLocalPrimaryComputerNameA(IN DWORD Unknown1,
812                              IN DWORD Unknown2)
813 {
814     STUB;
815     return FALSE;
816 }
817 
818 /*
819  * @unimplemented
820  */
821 BOOL
822 WINAPI
823 SetLocalPrimaryComputerNameW(IN DWORD Unknown1,
824                              IN DWORD Unknown2)
825 {
826     STUB;
827     return FALSE;
828 }
829 
830 
831 /* EOF */
832