xref: /reactos/dll/win32/kernel32/client/compname.c (revision f2df3bf0)
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  * @implemented
127  */
128 BOOL
129 WINAPI
130 GetComputerNameExW(COMPUTER_NAME_FORMAT NameType,
131                    LPWSTR lpBuffer,
132                    LPDWORD nSize)
133 {
134     UNICODE_STRING ResultString;
135     UNICODE_STRING DomainPart;
136     RTL_QUERY_REGISTRY_TABLE QueryTable[2];
137     NTSTATUS Status;
138     BOOL ret = TRUE;
139     DWORD HostSize;
140 
141     if ((nSize == NULL) ||
142         (lpBuffer == NULL && *nSize > 0))
143     {
144         SetLastError(ERROR_INVALID_PARAMETER);
145         return FALSE;
146     }
147 
148     switch (NameType)
149     {
150         case ComputerNameNetBIOS:
151             return GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
152                                                L"\\Control\\ComputerName\\ComputerName",
153                                                L"ComputerName",
154                                                lpBuffer,
155                                                nSize);
156 
157         case ComputerNameDnsDomain:
158             return GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
159                                                L"\\Services\\Tcpip\\Parameters",
160                                                L"Domain",
161                                                lpBuffer,
162                                                nSize);
163 
164         case ComputerNameDnsFullyQualified:
165             ResultString.Length = 0;
166             ResultString.MaximumLength = (USHORT)*nSize * sizeof(WCHAR);
167             ResultString.Buffer = lpBuffer;
168 
169             RtlZeroMemory(QueryTable, sizeof(QueryTable));
170             RtlInitUnicodeString(&DomainPart, NULL);
171 
172             QueryTable[0].Name = L"HostName";
173             QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
174             QueryTable[0].EntryContext = &DomainPart;
175 
176             Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
177                                             L"\\Registry\\Machine\\System"
178                                             L"\\CurrentControlSet\\Services\\Tcpip"
179                                             L"\\Parameters",
180                                             QueryTable,
181                                             NULL,
182                                             NULL);
183 
184             if (NT_SUCCESS(Status))
185             {
186                 Status = RtlAppendUnicodeStringToString(&ResultString, &DomainPart);
187                 HostSize = DomainPart.Length;
188 
189                 if (!NT_SUCCESS(Status))
190                 {
191                     ret = FALSE;
192                 }
193 
194                 RtlAppendUnicodeToString(&ResultString, L".");
195                 RtlFreeUnicodeString(&DomainPart);
196 
197                 RtlInitUnicodeString(&DomainPart, NULL);
198                 QueryTable[0].Name = L"Domain";
199                 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
200                 QueryTable[0].EntryContext = &DomainPart;
201 
202                 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
203                                                 L"\\Registry\\Machine\\System"
204                                                 L"\\CurrentControlSet\\Services\\Tcpip"
205                                                 L"\\Parameters",
206                                                 QueryTable,
207                                                 NULL,
208                                                 NULL);
209 
210                 if (NT_SUCCESS(Status))
211                 {
212                     Status = RtlAppendUnicodeStringToString(&ResultString, &DomainPart);
213                     if ((!NT_SUCCESS(Status)) || (!ret))
214                     {
215                         *nSize = HostSize + DomainPart.Length;
216                         SetLastError(ERROR_MORE_DATA);
217                         RtlFreeUnicodeString(&DomainPart);
218                         return FALSE;
219                     }
220                     RtlFreeUnicodeString(&DomainPart);
221                     *nSize = ResultString.Length / sizeof(WCHAR) - 1;
222                     return TRUE;
223                 }
224             }
225             return FALSE;
226 
227         case ComputerNameDnsHostname:
228             return GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
229                                                L"\\Services\\Tcpip\\Parameters",
230                                                L"Hostname",
231                                                lpBuffer,
232                                                nSize);
233 
234         case ComputerNamePhysicalDnsDomain:
235             return GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
236                                                L"\\Services\\Tcpip\\Parameters",
237                                                L"Domain",
238                                                lpBuffer,
239                                                nSize);
240 
241         /* XXX Redo these */
242         case ComputerNamePhysicalDnsFullyQualified:
243             return GetComputerNameExW(ComputerNameDnsFullyQualified,
244                                       lpBuffer,
245                                       nSize);
246 
247         case ComputerNamePhysicalDnsHostname:
248             return GetComputerNameExW(ComputerNameDnsHostname,
249                                       lpBuffer,
250                                       nSize);
251 
252         case ComputerNamePhysicalNetBIOS:
253             return GetComputerNameExW(ComputerNameNetBIOS,
254                                       lpBuffer,
255                                       nSize);
256 
257         case ComputerNameMax:
258             return FALSE;
259     }
260 
261     return FALSE;
262 }
263 
264 /*
265  * @implemented
266  */
267 BOOL
268 WINAPI
269 GetComputerNameExA(COMPUTER_NAME_FORMAT NameType,
270                    LPSTR lpBuffer,
271                    LPDWORD nSize)
272 {
273     UNICODE_STRING UnicodeString;
274     ANSI_STRING AnsiString;
275     BOOL Result;
276     PWCHAR TempBuffer = NULL;
277 
278     if ((nSize == NULL) ||
279         (lpBuffer == NULL && *nSize > 0))
280     {
281         SetLastError(ERROR_INVALID_PARAMETER);
282         return FALSE;
283     }
284 
285     if (*nSize > 0)
286     {
287         TempBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, *nSize * sizeof(WCHAR));
288         if (!TempBuffer)
289         {
290             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
291             return FALSE;
292         }
293     }
294 
295     AnsiString.MaximumLength = (USHORT)*nSize;
296     AnsiString.Length = 0;
297     AnsiString.Buffer = lpBuffer;
298 
299     Result = GetComputerNameExW(NameType, TempBuffer, nSize);
300 
301     if (Result)
302     {
303         UnicodeString.MaximumLength = (USHORT)*nSize * sizeof(WCHAR) + sizeof(WCHAR);
304         UnicodeString.Length = (USHORT)*nSize * sizeof(WCHAR);
305         UnicodeString.Buffer = TempBuffer;
306 
307         RtlUnicodeStringToAnsiString(&AnsiString,
308                                      &UnicodeString,
309                                      FALSE);
310     }
311 
312     RtlFreeHeap(RtlGetProcessHeap(), 0, TempBuffer);
313 
314     return Result;
315 }
316 
317 /*
318  * @implemented
319  */
320 BOOL
321 WINAPI
322 GetComputerNameA(LPSTR lpBuffer, LPDWORD lpnSize)
323 {
324     BOOL ret;
325 
326     ret = GetComputerNameExA(ComputerNameNetBIOS, lpBuffer, lpnSize);
327     if (!ret && GetLastError() == ERROR_MORE_DATA)
328         SetLastError(ERROR_BUFFER_OVERFLOW);
329 
330     return ret;
331 }
332 
333 
334 /*
335  * @implemented
336  */
337 BOOL
338 WINAPI
339 GetComputerNameW(LPWSTR lpBuffer, LPDWORD lpnSize)
340 {
341     BOOL ret;
342     ret=GetComputerNameExW(ComputerNameNetBIOS, lpBuffer, lpnSize);
343     if(!ret && GetLastError() == ERROR_MORE_DATA)
344       SetLastError(ERROR_BUFFER_OVERFLOW);
345     return ret;
346 }
347 
348 
349 /*
350  * @implemented
351  */
352 static
353 BOOL
354 IsValidComputerName(COMPUTER_NAME_FORMAT NameType,
355                     LPCWSTR lpComputerName)
356 {
357     PWCHAR p;
358     ULONG Length;
359 
360     /* FIXME: do verification according to NameType */
361 
362     Length = 0;
363     p = (PWCHAR)lpComputerName;
364 
365     while (*p != 0)
366     {
367         if (!(iswctype(*p, _ALPHA | _DIGIT) || *p == L'!' || *p == L'@' || *p == L'#' ||
368             *p == L'$' || *p == L'%' || *p == L'^' || *p == L'&' || *p == L'\'' ||
369             *p == L')' || *p == L'(' || *p == L'.' || *p == L'-' || *p == L'_' ||
370             *p == L'{' || *p == L'}' || *p == L'~'))
371             return FALSE;
372 
373         Length++;
374         p++;
375     }
376 
377     if (Length == 0 || Length > MAX_COMPUTERNAME_LENGTH)
378         return FALSE;
379 
380     return TRUE;
381 }
382 
383 
384 static
385 BOOL
386 SetComputerNameToRegistry(LPCWSTR RegistryKey,
387                           LPCWSTR ValueNameStr,
388                           LPCWSTR lpBuffer)
389 {
390     OBJECT_ATTRIBUTES ObjectAttributes;
391     UNICODE_STRING KeyName;
392     UNICODE_STRING ValueName;
393     HANDLE KeyHandle;
394     SIZE_T StringLength;
395     NTSTATUS Status;
396 
397     StringLength = wcslen(lpBuffer);
398     if (StringLength > ((MAXULONG / sizeof(WCHAR)) - 1))
399     {
400         return FALSE;
401     }
402 
403     RtlInitUnicodeString(&KeyName, RegistryKey);
404     InitializeObjectAttributes(&ObjectAttributes,
405                                &KeyName,
406                                OBJ_CASE_INSENSITIVE,
407                                NULL,
408                                NULL);
409 
410     Status = NtOpenKey(&KeyHandle,
411                        KEY_WRITE,
412                        &ObjectAttributes);
413     if (!NT_SUCCESS(Status))
414     {
415         BaseSetLastNTError(Status);
416         return FALSE;
417     }
418 
419     RtlInitUnicodeString(&ValueName, ValueNameStr);
420 
421     Status = NtSetValueKey(KeyHandle,
422                            &ValueName,
423                            0,
424                            REG_SZ,
425                            (PVOID)lpBuffer,
426                            (StringLength + 1) * sizeof(WCHAR));
427     if (!NT_SUCCESS(Status))
428     {
429         NtClose(KeyHandle);
430         BaseSetLastNTError(Status);
431         return FALSE;
432     }
433 
434     NtFlushKey(KeyHandle);
435     NtClose(KeyHandle);
436 
437     return TRUE;
438 }
439 
440 
441 /*
442  * @implemented
443  */
444 BOOL
445 WINAPI
446 SetComputerNameA(LPCSTR lpComputerName)
447 {
448     return SetComputerNameExA(ComputerNamePhysicalNetBIOS, lpComputerName);
449 }
450 
451 
452 /*
453  * @implemented
454  */
455 BOOL
456 WINAPI
457 SetComputerNameW(LPCWSTR lpComputerName)
458 {
459     return SetComputerNameExW(ComputerNamePhysicalNetBIOS, lpComputerName);
460 }
461 
462 
463 /*
464  * @implemented
465  */
466 BOOL
467 WINAPI
468 SetComputerNameExA(COMPUTER_NAME_FORMAT NameType,
469                    LPCSTR lpBuffer)
470 {
471     UNICODE_STRING Buffer;
472     BOOL bResult;
473 
474     RtlCreateUnicodeStringFromAsciiz(&Buffer, (LPSTR)lpBuffer);
475 
476     bResult = SetComputerNameExW(NameType, Buffer.Buffer);
477 
478     RtlFreeUnicodeString(&Buffer);
479 
480     return bResult;
481 }
482 
483 
484 /*
485  * @implemented
486  */
487 BOOL
488 WINAPI
489 SetComputerNameExW(COMPUTER_NAME_FORMAT NameType,
490                    LPCWSTR lpBuffer)
491 {
492     if (!IsValidComputerName(NameType, lpBuffer))
493     {
494         SetLastError(ERROR_INVALID_PARAMETER);
495         return FALSE;
496     }
497 
498     switch( NameType )
499     {
500         case ComputerNamePhysicalDnsDomain:
501             return SetComputerNameToRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
502                                              L"\\Services\\Tcpip\\Parameters",
503                                              L"Domain",
504                                              lpBuffer);
505 
506         case ComputerNamePhysicalDnsHostname:
507             return SetComputerNameToRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
508                                              L"\\Services\\Tcpip\\Parameters",
509                                              L"Hostname",
510                                              lpBuffer);
511 
512         case ComputerNamePhysicalNetBIOS:
513             return SetComputerNameToRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet"
514                                              L"\\Control\\ComputerName\\ComputerName",
515                                              L"ComputerName",
516                                              lpBuffer);
517 
518         default:
519             SetLastError (ERROR_INVALID_PARAMETER);
520             return FALSE;
521     }
522 }
523 
524 
525 /*
526  * @implemented
527  */
528 BOOL
529 WINAPI
530 DnsHostnameToComputerNameA(LPCSTR Hostname,
531                            LPSTR ComputerName,
532                            LPDWORD nSize)
533 {
534     DWORD len;
535 
536     DPRINT("(%s, %p, %p)\n", Hostname, ComputerName, nSize);
537 
538     if (!Hostname || !nSize)
539         return FALSE;
540 
541     len = lstrlenA(Hostname);
542 
543     if (len > MAX_COMPUTERNAME_LENGTH)
544         len = MAX_COMPUTERNAME_LENGTH;
545 
546     if (*nSize < len)
547     {
548         *nSize = len;
549         return FALSE;
550     }
551 
552     if (!ComputerName) return FALSE;
553 
554     memcpy(ComputerName, Hostname, len);
555     ComputerName[len + 1] = 0;
556     return TRUE;
557 }
558 
559 
560 /*
561  * @implemented
562  */
563 BOOL
564 WINAPI
565 DnsHostnameToComputerNameW(LPCWSTR hostname,
566                            LPWSTR computername,
567                            LPDWORD size)
568 {
569     DWORD len;
570 
571     DPRINT("(%s, %p, %p): stub\n", hostname, computername, size);
572 
573     if (!hostname || !size) return FALSE;
574     len = lstrlenW(hostname);
575 
576     if (len > MAX_COMPUTERNAME_LENGTH)
577         len = MAX_COMPUTERNAME_LENGTH;
578 
579     if (*size < len)
580     {
581         *size = len;
582         return FALSE;
583     }
584     if (!computername) return FALSE;
585 
586     memcpy(computername, hostname, len * sizeof(WCHAR));
587     computername[len + 1] = 0;
588     return TRUE;
589 }
590 
591 DWORD
592 WINAPI
593 AddLocalAlternateComputerNameA(LPSTR lpName, PNTSTATUS Status)
594 {
595     STUB;
596     return 0;
597 }
598 
599 DWORD
600 WINAPI
601 AddLocalAlternateComputerNameW(LPWSTR lpName, PNTSTATUS Status)
602 {
603     STUB;
604     return 0;
605 }
606 
607 DWORD
608 WINAPI
609 EnumerateLocalComputerNamesA(PVOID pUnknown, DWORD Size, LPSTR lpBuffer, LPDWORD lpnSize)
610 {
611     STUB;
612     return ERROR_CALL_NOT_IMPLEMENTED;
613 }
614 
615 DWORD
616 WINAPI
617 EnumerateLocalComputerNamesW(PVOID pUnknown, DWORD Size, LPWSTR lpBuffer, LPDWORD lpnSize)
618 {
619     STUB;
620     return ERROR_CALL_NOT_IMPLEMENTED;
621 }
622 
623 DWORD
624 WINAPI
625 RemoveLocalAlternateComputerNameA(LPSTR lpName, DWORD Unknown)
626 {
627     STUB;
628     return ERROR_CALL_NOT_IMPLEMENTED;
629 }
630 
631 DWORD
632 WINAPI
633 RemoveLocalAlternateComputerNameW(LPWSTR lpName, DWORD Unknown)
634 {
635     STUB;
636     return ERROR_CALL_NOT_IMPLEMENTED;
637 }
638 
639 /*
640  * @unimplemented
641  */
642 BOOL
643 WINAPI
644 SetLocalPrimaryComputerNameA(IN DWORD Unknown1,
645                              IN DWORD Unknown2)
646 {
647     STUB;
648     return FALSE;
649 }
650 
651 /*
652  * @unimplemented
653  */
654 BOOL
655 WINAPI
656 SetLocalPrimaryComputerNameW(IN DWORD Unknown1,
657                              IN DWORD Unknown2)
658 {
659     STUB;
660     return FALSE;
661 }
662 
663 
664 /* EOF */
665