xref: /reactos/dll/win32/kernel32/client/compname.c (revision 23373acb)
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  * PROGRAMER:       Eric Kohl
25  */
26 
27 /* INCLUDES ******************************************************************/
28 
29 #include <k32.h>
30 
31 #define NDEBUG
32 #include <debug.h>
33 
34 
35 /* FUNCTIONS *****************************************************************/
36 
37 static
38 BOOL
39 GetComputerNameFromRegistry(LPWSTR RegistryKey,
40                             LPWSTR ValueNameStr,
41                             LPWSTR lpBuffer,
42                             LPDWORD nSize)
43 {
44     PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
45     OBJECT_ATTRIBUTES ObjectAttributes;
46     UNICODE_STRING KeyName;
47     UNICODE_STRING ValueName;
48     HANDLE KeyHandle;
49     ULONG KeyInfoSize;
50     ULONG ReturnSize;
51     NTSTATUS Status;
52 
53     if (lpBuffer != NULL && *nSize > 0)
54         lpBuffer[0] = 0;
55 
56     RtlInitUnicodeString(&KeyName, RegistryKey);
57     InitializeObjectAttributes(&ObjectAttributes,
58                                &KeyName,
59                                OBJ_CASE_INSENSITIVE,
60                                NULL,
61                                NULL);
62 
63     Status = NtOpenKey(&KeyHandle,
64                        KEY_READ,
65                        &ObjectAttributes);
66     if (!NT_SUCCESS(Status))
67     {
68         BaseSetLastNTError (Status);
69         return FALSE;
70     }
71 
72     KeyInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + *nSize * sizeof(WCHAR);
73     KeyInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, KeyInfoSize);
74     if (KeyInfo == NULL)
75     {
76         NtClose(KeyHandle);
77         SetLastError(ERROR_OUTOFMEMORY);
78         return FALSE;
79     }
80 
81     RtlInitUnicodeString(&ValueName, ValueNameStr);
82 
83     Status = NtQueryValueKey(KeyHandle,
84                              &ValueName,
85                              KeyValuePartialInformation,
86                              KeyInfo,
87                              KeyInfoSize,
88                              &ReturnSize);
89 
90     NtClose(KeyHandle);
91 
92     if (!NT_SUCCESS(Status))
93     {
94         *nSize = (ReturnSize - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data)) / sizeof(WCHAR);
95         goto failed;
96     }
97 
98     if (KeyInfo->Type != REG_SZ)
99     {
100         Status = STATUS_UNSUCCESSFUL;
101         goto failed;
102     }
103 
104     if (!lpBuffer || *nSize < (KeyInfo->DataLength / sizeof(WCHAR)))
105     {
106         *nSize = (ReturnSize - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data)) / sizeof(WCHAR);
107         Status = STATUS_BUFFER_OVERFLOW;
108         goto failed;
109     }
110 
111     *nSize = KeyInfo->DataLength / sizeof(WCHAR) - 1;
112     RtlCopyMemory(lpBuffer, KeyInfo->Data, KeyInfo->DataLength);
113     lpBuffer[*nSize] = 0;
114 
115     RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
116 
117     return TRUE;
118 
119 failed:
120     RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
121     BaseSetLastNTError(Status);
122     return FALSE;
123 }
124 
125 
126 static
127 BOOL
128 SetActiveComputerNameToRegistry(LPCWSTR RegistryKey,
129                                 LPCWSTR SubKey,
130                                 LPCWSTR ValueNameStr,
131                                 LPCWSTR lpBuffer)
132 {
133     OBJECT_ATTRIBUTES ObjectAttributes;
134     UNICODE_STRING KeyName;
135     UNICODE_STRING ValueName;
136     HANDLE KeyHandle, SubKeyHandle;
137     SIZE_T StringLength;
138     ULONG Disposition;
139     NTSTATUS Status;
140 
141     StringLength = wcslen(lpBuffer);
142     if (StringLength > ((MAXULONG / sizeof(WCHAR)) - 1))
143     {
144         return FALSE;
145     }
146 
147     RtlInitUnicodeString(&KeyName, RegistryKey);
148     InitializeObjectAttributes(&ObjectAttributes,
149                                &KeyName,
150                                OBJ_CASE_INSENSITIVE,
151                                NULL,
152                                NULL);
153 
154     Status = NtOpenKey(&KeyHandle,
155                        KEY_WRITE,
156                        &ObjectAttributes);
157     if (!NT_SUCCESS(Status))
158     {
159         BaseSetLastNTError(Status);
160         return FALSE;
161     }
162 
163     RtlInitUnicodeString(&KeyName, SubKey);
164     InitializeObjectAttributes(&ObjectAttributes,
165                                &KeyName,
166                                OBJ_CASE_INSENSITIVE,
167                                KeyHandle,
168                                NULL);
169 
170     Status = NtCreateKey(&SubKeyHandle,
171                          KEY_WRITE,
172                          &ObjectAttributes,
173                          0,
174                          NULL,
175                          REG_OPTION_VOLATILE,
176                          &Disposition);
177     if (!NT_SUCCESS(Status))
178     {
179         NtClose(KeyHandle);
180         BaseSetLastNTError(Status);
181         return FALSE;
182     }
183 
184     RtlInitUnicodeString(&ValueName, ValueNameStr);
185 
186     Status = NtSetValueKey(SubKeyHandle,
187                            &ValueName,
188                            0,
189                            REG_SZ,
190                            (PVOID)lpBuffer,
191                            (StringLength + 1) * sizeof(WCHAR));
192     if (!NT_SUCCESS(Status))
193     {
194         NtClose(SubKeyHandle);
195         NtClose(KeyHandle);
196         BaseSetLastNTError(Status);
197         return FALSE;
198     }
199 
200     NtFlushKey(SubKeyHandle);
201     NtClose(SubKeyHandle);
202     NtClose(KeyHandle);
203 
204     return TRUE;
205 }
206 
207 
208 /*
209  * @implemented
210  */
211 BOOL
212 WINAPI
213 GetComputerNameExW(COMPUTER_NAME_FORMAT NameType,
214                    LPWSTR lpBuffer,
215                    LPDWORD nSize)
216 {
217     UNICODE_STRING ResultString;
218     UNICODE_STRING DomainPart;
219     RTL_QUERY_REGISTRY_TABLE QueryTable[2];
220     NTSTATUS Status;
221     BOOL ret = TRUE;
222     DWORD HostSize;
223 
224     if ((nSize == NULL) ||
225         (lpBuffer == NULL && *nSize > 0))
226     {
227         SetLastError(ERROR_INVALID_PARAMETER);
228         return FALSE;
229     }
230 
231     switch (NameType)
232     {
233         case ComputerNameNetBIOS:
234             ret = GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
235                                                L"\\Control\\ComputerName\\ActiveComputerName",
236                                                L"ComputerName",
237                                                lpBuffer,
238                                                nSize);
239             if ((ret == FALSE) &&
240                 (GetLastError() != ERROR_MORE_DATA))
241             {
242                 ret = GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
243                                                   L"\\Control\\ComputerName\\ComputerName",
244                                                   L"ComputerName",
245                                                   lpBuffer,
246                                                   nSize);
247                 if (ret)
248                 {
249                     ret = SetActiveComputerNameToRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
250                                                           L"\\Control\\ComputerName",
251                                                           L"ActiveComputerName",
252                                                           L"ComputerName",
253                                                           lpBuffer);
254                 }
255             }
256             return ret;
257 
258         case ComputerNameDnsDomain:
259             return GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
260                                                L"\\Services\\Tcpip\\Parameters",
261                                                L"Domain",
262                                                lpBuffer,
263                                                nSize);
264 
265         case ComputerNameDnsFullyQualified:
266             ResultString.Length = 0;
267             ResultString.MaximumLength = (USHORT)*nSize * sizeof(WCHAR);
268             ResultString.Buffer = lpBuffer;
269 
270             RtlZeroMemory(QueryTable, sizeof(QueryTable));
271             RtlInitUnicodeString(&DomainPart, NULL);
272 
273             QueryTable[0].Name = L"HostName";
274             QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
275             QueryTable[0].EntryContext = &DomainPart;
276 
277             Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
278                                             L"\\Registry\\Machine\\System"
279                                             L"\\CurrentControlSet\\Services\\Tcpip"
280                                             L"\\Parameters",
281                                             QueryTable,
282                                             NULL,
283                                             NULL);
284 
285             if (NT_SUCCESS(Status))
286             {
287                 Status = RtlAppendUnicodeStringToString(&ResultString, &DomainPart);
288                 HostSize = DomainPart.Length;
289 
290                 if (!NT_SUCCESS(Status))
291                 {
292                     ret = FALSE;
293                 }
294 
295                 RtlAppendUnicodeToString(&ResultString, L".");
296                 RtlFreeUnicodeString(&DomainPart);
297 
298                 RtlInitUnicodeString(&DomainPart, NULL);
299                 QueryTable[0].Name = L"Domain";
300                 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
301                 QueryTable[0].EntryContext = &DomainPart;
302 
303                 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
304                                                 L"\\Registry\\Machine\\System"
305                                                 L"\\CurrentControlSet\\Services\\Tcpip"
306                                                 L"\\Parameters",
307                                                 QueryTable,
308                                                 NULL,
309                                                 NULL);
310 
311                 if (NT_SUCCESS(Status))
312                 {
313                     Status = RtlAppendUnicodeStringToString(&ResultString, &DomainPart);
314                     if ((!NT_SUCCESS(Status)) || (!ret))
315                     {
316                         *nSize = HostSize + DomainPart.Length;
317                         SetLastError(ERROR_MORE_DATA);
318                         RtlFreeUnicodeString(&DomainPart);
319                         return FALSE;
320                     }
321                     RtlFreeUnicodeString(&DomainPart);
322                     *nSize = ResultString.Length / sizeof(WCHAR) - 1;
323                     return TRUE;
324                 }
325             }
326             return FALSE;
327 
328         case ComputerNameDnsHostname:
329             return GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
330                                                L"\\Services\\Tcpip\\Parameters",
331                                                L"Hostname",
332                                                lpBuffer,
333                                                nSize);
334 
335         case ComputerNamePhysicalDnsDomain:
336             return GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
337                                                L"\\Services\\Tcpip\\Parameters",
338                                                L"Domain",
339                                                lpBuffer,
340                                                nSize);
341 
342         /* XXX Redo these */
343         case ComputerNamePhysicalDnsFullyQualified:
344             return GetComputerNameExW(ComputerNameDnsFullyQualified,
345                                       lpBuffer,
346                                       nSize);
347 
348         case ComputerNamePhysicalDnsHostname:
349             return GetComputerNameExW(ComputerNameDnsHostname,
350                                       lpBuffer,
351                                       nSize);
352 
353         case ComputerNamePhysicalNetBIOS:
354             return GetComputerNameExW(ComputerNameNetBIOS,
355                                       lpBuffer,
356                                       nSize);
357 
358         case ComputerNameMax:
359             return FALSE;
360     }
361 
362     return FALSE;
363 }
364 
365 /*
366  * @implemented
367  */
368 BOOL
369 WINAPI
370 GetComputerNameExA(COMPUTER_NAME_FORMAT NameType,
371                    LPSTR lpBuffer,
372                    LPDWORD nSize)
373 {
374     UNICODE_STRING UnicodeString;
375     ANSI_STRING AnsiString;
376     BOOL Result;
377     PWCHAR TempBuffer = NULL;
378 
379     if ((nSize == NULL) ||
380         (lpBuffer == NULL && *nSize > 0))
381     {
382         SetLastError(ERROR_INVALID_PARAMETER);
383         return FALSE;
384     }
385 
386     if (*nSize > 0)
387     {
388         TempBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, *nSize * sizeof(WCHAR));
389         if (!TempBuffer)
390         {
391             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
392             return FALSE;
393         }
394     }
395 
396     AnsiString.MaximumLength = (USHORT)*nSize;
397     AnsiString.Length = 0;
398     AnsiString.Buffer = lpBuffer;
399 
400     Result = GetComputerNameExW(NameType, TempBuffer, nSize);
401 
402     if (Result)
403     {
404         UnicodeString.MaximumLength = (USHORT)*nSize * sizeof(WCHAR) + sizeof(WCHAR);
405         UnicodeString.Length = (USHORT)*nSize * sizeof(WCHAR);
406         UnicodeString.Buffer = TempBuffer;
407 
408         RtlUnicodeStringToAnsiString(&AnsiString,
409                                      &UnicodeString,
410                                      FALSE);
411     }
412 
413     RtlFreeHeap(RtlGetProcessHeap(), 0, TempBuffer);
414 
415     return Result;
416 }
417 
418 /*
419  * @implemented
420  */
421 BOOL
422 WINAPI
423 GetComputerNameA(LPSTR lpBuffer, LPDWORD lpnSize)
424 {
425     BOOL ret;
426 
427     ret = GetComputerNameExA(ComputerNameNetBIOS, lpBuffer, lpnSize);
428     if (!ret && GetLastError() == ERROR_MORE_DATA)
429         SetLastError(ERROR_BUFFER_OVERFLOW);
430 
431     return ret;
432 }
433 
434 
435 /*
436  * @implemented
437  */
438 BOOL
439 WINAPI
440 GetComputerNameW(LPWSTR lpBuffer, LPDWORD lpnSize)
441 {
442     BOOL ret;
443 
444     ret = GetComputerNameExW(ComputerNameNetBIOS, lpBuffer, lpnSize);
445     if (!ret && GetLastError() == ERROR_MORE_DATA)
446         SetLastError(ERROR_BUFFER_OVERFLOW);
447 
448     return ret;
449 }
450 
451 
452 /*
453  * @implemented
454  */
455 static
456 BOOL
457 IsValidComputerName(COMPUTER_NAME_FORMAT NameType,
458                     LPCWSTR lpComputerName)
459 {
460     PWCHAR p;
461     ULONG Length;
462 
463     /* FIXME: do verification according to NameType */
464 
465     Length = 0;
466     p = (PWCHAR)lpComputerName;
467 
468     while (*p != 0)
469     {
470         if (!(iswctype(*p, _ALPHA | _DIGIT) || *p == L'!' || *p == L'@' || *p == L'#' ||
471             *p == L'$' || *p == L'%' || *p == L'^' || *p == L'&' || *p == L'\'' ||
472             *p == L')' || *p == L'(' || *p == L'.' || *p == L'-' || *p == L'_' ||
473             *p == L'{' || *p == L'}' || *p == L'~'))
474             return FALSE;
475 
476         Length++;
477         p++;
478     }
479 
480     if (Length == 0 || Length > MAX_COMPUTERNAME_LENGTH)
481         return FALSE;
482 
483     return TRUE;
484 }
485 
486 
487 static
488 BOOL
489 SetComputerNameToRegistry(LPCWSTR RegistryKey,
490                           LPCWSTR ValueNameStr,
491                           LPCWSTR lpBuffer)
492 {
493     OBJECT_ATTRIBUTES ObjectAttributes;
494     UNICODE_STRING KeyName;
495     UNICODE_STRING ValueName;
496     HANDLE KeyHandle;
497     SIZE_T StringLength;
498     NTSTATUS Status;
499 
500     StringLength = wcslen(lpBuffer);
501     if (StringLength > ((MAXULONG / sizeof(WCHAR)) - 1))
502     {
503         return FALSE;
504     }
505 
506     RtlInitUnicodeString(&KeyName, RegistryKey);
507     InitializeObjectAttributes(&ObjectAttributes,
508                                &KeyName,
509                                OBJ_CASE_INSENSITIVE,
510                                NULL,
511                                NULL);
512 
513     Status = NtOpenKey(&KeyHandle,
514                        KEY_WRITE,
515                        &ObjectAttributes);
516     if (!NT_SUCCESS(Status))
517     {
518         BaseSetLastNTError(Status);
519         return FALSE;
520     }
521 
522     RtlInitUnicodeString(&ValueName, ValueNameStr);
523 
524     Status = NtSetValueKey(KeyHandle,
525                            &ValueName,
526                            0,
527                            REG_SZ,
528                            (PVOID)lpBuffer,
529                            (StringLength + 1) * sizeof(WCHAR));
530     if (!NT_SUCCESS(Status))
531     {
532         NtClose(KeyHandle);
533         BaseSetLastNTError(Status);
534         return FALSE;
535     }
536 
537     NtFlushKey(KeyHandle);
538     NtClose(KeyHandle);
539 
540     return TRUE;
541 }
542 
543 
544 /*
545  * @implemented
546  */
547 BOOL
548 WINAPI
549 SetComputerNameA(LPCSTR lpComputerName)
550 {
551     return SetComputerNameExA(ComputerNamePhysicalNetBIOS, lpComputerName);
552 }
553 
554 
555 /*
556  * @implemented
557  */
558 BOOL
559 WINAPI
560 SetComputerNameW(LPCWSTR lpComputerName)
561 {
562     return SetComputerNameExW(ComputerNamePhysicalNetBIOS, lpComputerName);
563 }
564 
565 
566 /*
567  * @implemented
568  */
569 BOOL
570 WINAPI
571 SetComputerNameExA(COMPUTER_NAME_FORMAT NameType,
572                    LPCSTR lpBuffer)
573 {
574     UNICODE_STRING Buffer;
575     BOOL bResult;
576 
577     RtlCreateUnicodeStringFromAsciiz(&Buffer, (LPSTR)lpBuffer);
578 
579     bResult = SetComputerNameExW(NameType, Buffer.Buffer);
580 
581     RtlFreeUnicodeString(&Buffer);
582 
583     return bResult;
584 }
585 
586 
587 /*
588  * @implemented
589  */
590 BOOL
591 WINAPI
592 SetComputerNameExW(COMPUTER_NAME_FORMAT NameType,
593                    LPCWSTR lpBuffer)
594 {
595     if (!IsValidComputerName(NameType, lpBuffer))
596     {
597         SetLastError(ERROR_INVALID_PARAMETER);
598         return FALSE;
599     }
600 
601     switch( NameType )
602     {
603         case ComputerNamePhysicalDnsDomain:
604             return SetComputerNameToRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
605                                              L"\\Services\\Tcpip\\Parameters",
606                                              L"Domain",
607                                              lpBuffer);
608 
609         case ComputerNamePhysicalDnsHostname:
610             return SetComputerNameToRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
611                                              L"\\Services\\Tcpip\\Parameters",
612                                              L"Hostname",
613                                              lpBuffer);
614 
615         case ComputerNamePhysicalNetBIOS:
616             return SetComputerNameToRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
617                                              L"\\Control\\ComputerName\\ComputerName",
618                                              L"ComputerName",
619                                              lpBuffer);
620 
621         default:
622             SetLastError (ERROR_INVALID_PARAMETER);
623             return FALSE;
624     }
625 }
626 
627 
628 /*
629  * @implemented
630  */
631 BOOL
632 WINAPI
633 DnsHostnameToComputerNameA(LPCSTR Hostname,
634                            LPSTR ComputerName,
635                            LPDWORD nSize)
636 {
637     DWORD len;
638 
639     DPRINT("(%s, %p, %p)\n", Hostname, ComputerName, nSize);
640 
641     if (!Hostname || !nSize)
642         return FALSE;
643 
644     len = lstrlenA(Hostname);
645 
646     if (len > MAX_COMPUTERNAME_LENGTH)
647         len = MAX_COMPUTERNAME_LENGTH;
648 
649     if (*nSize < len)
650     {
651         *nSize = len;
652         return FALSE;
653     }
654 
655     if (!ComputerName) return FALSE;
656 
657     memcpy(ComputerName, Hostname, len);
658     ComputerName[len + 1] = 0;
659     return TRUE;
660 }
661 
662 
663 /*
664  * @implemented
665  */
666 BOOL
667 WINAPI
668 DnsHostnameToComputerNameW(LPCWSTR hostname,
669                            LPWSTR computername,
670                            LPDWORD size)
671 {
672     DWORD len;
673 
674     DPRINT("(%s, %p, %p): stub\n", hostname, computername, size);
675 
676     if (!hostname || !size) return FALSE;
677     len = lstrlenW(hostname);
678 
679     if (len > MAX_COMPUTERNAME_LENGTH)
680         len = MAX_COMPUTERNAME_LENGTH;
681 
682     if (*size < len)
683     {
684         *size = len;
685         return FALSE;
686     }
687     if (!computername) return FALSE;
688 
689     memcpy(computername, hostname, len * sizeof(WCHAR));
690     computername[len + 1] = 0;
691     return TRUE;
692 }
693 
694 DWORD
695 WINAPI
696 AddLocalAlternateComputerNameA(LPSTR lpName, PNTSTATUS Status)
697 {
698     STUB;
699     return 0;
700 }
701 
702 DWORD
703 WINAPI
704 AddLocalAlternateComputerNameW(LPWSTR lpName, PNTSTATUS Status)
705 {
706     STUB;
707     return 0;
708 }
709 
710 DWORD
711 WINAPI
712 EnumerateLocalComputerNamesA(PVOID pUnknown, DWORD Size, LPSTR lpBuffer, LPDWORD lpnSize)
713 {
714     STUB;
715     return ERROR_CALL_NOT_IMPLEMENTED;
716 }
717 
718 DWORD
719 WINAPI
720 EnumerateLocalComputerNamesW(PVOID pUnknown, DWORD Size, LPWSTR lpBuffer, LPDWORD lpnSize)
721 {
722     STUB;
723     return ERROR_CALL_NOT_IMPLEMENTED;
724 }
725 
726 DWORD
727 WINAPI
728 RemoveLocalAlternateComputerNameA(LPSTR lpName, DWORD Unknown)
729 {
730     STUB;
731     return ERROR_CALL_NOT_IMPLEMENTED;
732 }
733 
734 DWORD
735 WINAPI
736 RemoveLocalAlternateComputerNameW(LPWSTR lpName, DWORD Unknown)
737 {
738     STUB;
739     return ERROR_CALL_NOT_IMPLEMENTED;
740 }
741 
742 /*
743  * @unimplemented
744  */
745 BOOL
746 WINAPI
747 SetLocalPrimaryComputerNameA(IN DWORD Unknown1,
748                              IN DWORD Unknown2)
749 {
750     STUB;
751     return FALSE;
752 }
753 
754 /*
755  * @unimplemented
756  */
757 BOOL
758 WINAPI
759 SetLocalPrimaryComputerNameW(IN DWORD Unknown1,
760                              IN DWORD Unknown2)
761 {
762     STUB;
763     return FALSE;
764 }
765 
766 
767 /* EOF */
768