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