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