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