1 /* 2 * VideoPort driver 3 * 4 * Copyright (C) 2002-2004, 2007 ReactOS Team 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 * 20 */ 21 22 #include "videoprt.h" 23 #include <ndk/obfuncs.h> 24 #include <stdio.h> 25 26 #define NDEBUG 27 #include <debug.h> 28 29 NTSTATUS 30 NTAPI 31 IntCopyRegistryKey( 32 _In_ HANDLE SourceKeyHandle, 33 _In_ HANDLE DestKeyHandle) 34 { 35 PVOID InfoBuffer; 36 PKEY_BASIC_INFORMATION KeyInformation; 37 PKEY_VALUE_FULL_INFORMATION KeyValueInformation; 38 OBJECT_ATTRIBUTES ObjectAttributes; 39 ULONG Index, InformationLength, RequiredLength; 40 UNICODE_STRING NameString; 41 NTSTATUS Status; 42 HANDLE SourceSubKeyHandle, DestSubKeyHandle; 43 44 /* Start with no buffer, set initial size */ 45 InfoBuffer = NULL; 46 InformationLength = 256; 47 48 /* Start looping with key index 0 */ 49 Index = 0; 50 while (TRUE) 51 { 52 /* Check if we have no buffer */ 53 if (InfoBuffer == NULL) 54 { 55 /* Allocate a new buffer */ 56 InfoBuffer = ExAllocatePoolWithTag(PagedPool, 57 InformationLength, 58 TAG_VIDEO_PORT_BUFFER); 59 if (InfoBuffer == NULL) 60 { 61 ERR_(VIDEOPRT, "Could not allocate buffer for key info\n"); 62 return STATUS_INSUFFICIENT_RESOURCES; 63 } 64 } 65 66 /* Enumerate the next sub-key */ 67 KeyInformation = InfoBuffer; 68 Status = ZwEnumerateKey(SourceKeyHandle, 69 Index, 70 KeyBasicInformation, 71 KeyInformation, 72 InformationLength, 73 &RequiredLength); 74 if ((Status == STATUS_BUFFER_OVERFLOW) || 75 (Status == STATUS_BUFFER_TOO_SMALL)) 76 { 77 /* Free the buffer and remember the required size */ 78 ExFreePoolWithTag(InfoBuffer, TAG_VIDEO_PORT_BUFFER); 79 InfoBuffer = NULL; 80 InformationLength = RequiredLength; 81 82 /* Try again */ 83 continue; 84 } 85 else if (Status == STATUS_NO_MORE_ENTRIES) 86 { 87 /* We are done with the sub-keys */ 88 break; 89 } 90 else if (!NT_SUCCESS(Status)) 91 { 92 ERR_(VIDEOPRT, "ZwEnumerateKey failed, status 0x%lx\n", Status); 93 goto Cleanup; 94 } 95 96 /* Initialize a unicode string from the key name */ 97 NameString.Buffer = KeyInformation->Name; 98 NameString.Length = (USHORT)KeyInformation->NameLength; 99 NameString.MaximumLength = NameString.Length; 100 101 /* Initialize object attributes and open the source sub-key */ 102 InitializeObjectAttributes(&ObjectAttributes, 103 &NameString, 104 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, 105 SourceKeyHandle, 106 NULL); 107 Status = ZwOpenKey(&SourceSubKeyHandle, KEY_READ, &ObjectAttributes); 108 if (!NT_SUCCESS(Status)) 109 { 110 ERR_(VIDEOPRT, "failed to open the source key.\n"); 111 goto Cleanup; 112 } 113 114 /* Initialize object attributes and create the dest sub-key */ 115 InitializeObjectAttributes(&ObjectAttributes, 116 &NameString, 117 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, 118 DestKeyHandle, 119 NULL); 120 Status = ZwCreateKey(&DestSubKeyHandle, 121 KEY_WRITE, 122 &ObjectAttributes, 123 0, 124 NULL, 125 REG_OPTION_NON_VOLATILE, 126 NULL); 127 if (!NT_SUCCESS(Status)) 128 { 129 ERR_(VIDEOPRT, "failed to create the destination key.\n"); 130 ObCloseHandle(SourceSubKeyHandle, KernelMode); 131 goto Cleanup; 132 } 133 134 /* Recursively copy the sub-key */ 135 Status = IntCopyRegistryKey(SourceSubKeyHandle, DestSubKeyHandle); 136 if (!NT_SUCCESS(Status)) 137 { 138 /* Just warn, but continue with the remaining sub-keys */ 139 WARN_(VIDEOPRT, "failed to copy subkey '%wZ'.\n", &NameString); 140 } 141 142 /* Close the sub-key handles */ 143 ObCloseHandle(SourceSubKeyHandle, KernelMode); 144 ObCloseHandle(DestSubKeyHandle, KernelMode); 145 146 /* Next sub-key */ 147 Index++; 148 } 149 150 /* Start looping with value index 0 */ 151 Index = 0; 152 while (TRUE) 153 { 154 /* Check if we have no buffer */ 155 if (InfoBuffer == NULL) 156 { 157 /* Allocate a new buffer */ 158 InfoBuffer = ExAllocatePoolWithTag(PagedPool, 159 InformationLength, 160 TAG_VIDEO_PORT_BUFFER); 161 if (InfoBuffer == NULL) 162 { 163 ERR_(VIDEOPRT, "Could not allocate buffer for key values\n"); 164 return Status; 165 } 166 } 167 168 /* Enumerate the next value */ 169 KeyValueInformation = InfoBuffer; 170 Status = ZwEnumerateValueKey(SourceKeyHandle, 171 Index, 172 KeyValueFullInformation, 173 KeyValueInformation, 174 InformationLength, 175 &RequiredLength); 176 if ((Status == STATUS_BUFFER_OVERFLOW) || 177 (Status == STATUS_BUFFER_TOO_SMALL)) 178 { 179 /* Free the buffer and remember the required size */ 180 ExFreePoolWithTag(InfoBuffer, TAG_VIDEO_PORT_BUFFER); 181 InfoBuffer = NULL; 182 InformationLength = RequiredLength; 183 184 /* Try again */ 185 continue; 186 } 187 else if (Status == STATUS_NO_MORE_ENTRIES) 188 { 189 /* We are done with the values */ 190 Status = STATUS_SUCCESS; 191 break; 192 } 193 else if (!NT_SUCCESS(Status)) 194 { 195 ERR_(VIDEOPRT, "ZwEnumerateValueKey failed, status 0x%lx\n", Status); 196 goto Cleanup; 197 } 198 199 /* Initialize a unicode string from the value name */ 200 NameString.Buffer = KeyValueInformation->Name; 201 NameString.Length = (USHORT)KeyValueInformation->NameLength; 202 NameString.MaximumLength = NameString.Length; 203 204 /* Create the key value in the destination key */ 205 Status = ZwSetValueKey(DestKeyHandle, 206 &NameString, 207 KeyValueInformation->TitleIndex, 208 KeyValueInformation->Type, 209 (PUCHAR)KeyValueInformation + KeyValueInformation->DataOffset, 210 KeyValueInformation->DataLength); 211 if (!NT_SUCCESS(Status)) 212 { 213 /* Just warn, but continue with the remaining sub-keys */ 214 WARN_(VIDEOPRT, "failed to set value '%wZ'.\n", &NameString); 215 } 216 217 /* Next subkey */ 218 Index++; 219 } 220 221 Cleanup: 222 /* Free the buffer and return the failure code */ 223 if (InfoBuffer != NULL) 224 ExFreePoolWithTag(InfoBuffer, TAG_VIDEO_PORT_BUFFER); 225 return Status; 226 } 227 228 NTSTATUS 229 NTAPI 230 IntCopyRegistryValue( 231 HANDLE SourceKeyHandle, 232 HANDLE DestKeyHandle, 233 PWSTR ValueName) 234 { 235 PKEY_VALUE_PARTIAL_INFORMATION ValueInformation; 236 UNICODE_STRING ValueNameString; 237 ULONG Length; 238 NTSTATUS Status; 239 240 RtlInitUnicodeString(&ValueNameString, ValueName); 241 242 /* Query the value length */ 243 Status = ZwQueryValueKey(SourceKeyHandle, 244 &ValueNameString, 245 KeyValuePartialInformation, 246 NULL, 247 0, 248 &Length); 249 if ((Status != STATUS_BUFFER_OVERFLOW) && 250 (Status != STATUS_BUFFER_TOO_SMALL)) 251 { 252 /* The key seems not present */ 253 NT_ASSERT(!NT_SUCCESS(Status)); 254 return Status; 255 } 256 257 /* Allocate a buffer */ 258 ValueInformation = ExAllocatePoolWithTag(PagedPool, Length, TAG_VIDEO_PORT_BUFFER); 259 if (ValueInformation == NULL) 260 { 261 return Status; 262 } 263 264 /* Query the value */ 265 Status = ZwQueryValueKey(SourceKeyHandle, 266 &ValueNameString, 267 KeyValuePartialInformation, 268 ValueInformation, 269 Length, 270 &Length); 271 if (!NT_SUCCESS(Status)) 272 { 273 ExFreePoolWithTag(ValueInformation, TAG_VIDEO_PORT_BUFFER); 274 return Status; 275 } 276 277 /* Write the registry value */ 278 Status = ZwSetValueKey(DestKeyHandle, 279 &ValueNameString, 280 ValueInformation->TitleIndex, 281 ValueInformation->Type, 282 ValueInformation->Data, 283 ValueInformation->DataLength); 284 285 ExFreePoolWithTag(ValueInformation, TAG_VIDEO_PORT_BUFFER); 286 287 if (!NT_SUCCESS(Status)) 288 { 289 ERR_(VIDEOPRT, "ZwSetValueKey failed: status 0x%lx\n", Status); 290 } 291 292 return Status; 293 } 294 295 NTSTATUS 296 NTAPI 297 IntSetupDeviceSettingsKey( 298 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension) 299 { 300 static UNICODE_STRING SettingsKeyName = RTL_CONSTANT_STRING(L"Settings"); 301 HANDLE DevInstRegKey, SourceKeyHandle, DestKeyHandle; 302 OBJECT_ATTRIBUTES ObjectAttributes; 303 NTSTATUS Status; 304 305 if (!DeviceExtension->PhysicalDeviceObject) 306 return STATUS_SUCCESS; 307 308 /* Open the software key: HKLM\System\CurrentControlSet\Control\Class\<ClassGUID>\<n> */ 309 Status = IoOpenDeviceRegistryKey(DeviceExtension->PhysicalDeviceObject, 310 PLUGPLAY_REGKEY_DRIVER, 311 KEY_ALL_ACCESS, 312 &DevInstRegKey); 313 if (Status != STATUS_SUCCESS) 314 { 315 ERR_(VIDEOPRT, "Failed to open device software key. Status 0x%lx\n", Status); 316 return Status; 317 } 318 319 /* Open the 'Settings' sub-key */ 320 InitializeObjectAttributes(&ObjectAttributes, 321 &SettingsKeyName, 322 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, 323 DevInstRegKey, 324 NULL); 325 Status = ZwOpenKey(&DestKeyHandle, KEY_WRITE, &ObjectAttributes); 326 327 /* Close the device software key */ 328 ObCloseHandle(DevInstRegKey, KernelMode); 329 330 if (Status != STATUS_SUCCESS) 331 { 332 ERR_(VIDEOPRT, "Failed to open settings key. Status 0x%lx\n", Status); 333 return Status; 334 } 335 336 /* Open the device profile key */ 337 InitializeObjectAttributes(&ObjectAttributes, 338 &DeviceExtension->RegistryPath, 339 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, 340 NULL, 341 NULL); 342 Status = ZwOpenKey(&SourceKeyHandle, KEY_READ, &ObjectAttributes); 343 if (Status != STATUS_SUCCESS) 344 { 345 ERR_(VIDEOPRT, "ZwOpenKey failed for settings key: status 0x%lx\n", Status); 346 ObCloseHandle(DestKeyHandle, KernelMode); 347 return Status; 348 } 349 350 IntCopyRegistryValue(SourceKeyHandle, DestKeyHandle, L"InstalledDisplayDrivers"); 351 IntCopyRegistryValue(SourceKeyHandle, DestKeyHandle, L"Attach.ToDesktop"); 352 353 ObCloseHandle(SourceKeyHandle, KernelMode); 354 ObCloseHandle(DestKeyHandle, KernelMode); 355 356 return STATUS_SUCCESS; 357 } 358 359 NTSTATUS 360 IntDuplicateUnicodeString( 361 IN ULONG Flags, 362 IN PCUNICODE_STRING SourceString, 363 OUT PUNICODE_STRING DestinationString) 364 { 365 if (SourceString == NULL || 366 DestinationString == NULL || 367 SourceString->Length > SourceString->MaximumLength || 368 (SourceString->Length == 0 && SourceString->MaximumLength > 0 && SourceString->Buffer == NULL) || 369 Flags == RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING || 370 Flags >= 4) 371 { 372 return STATUS_INVALID_PARAMETER; 373 } 374 375 if ((SourceString->Length == 0) && 376 (Flags != (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE | 377 RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING))) 378 { 379 DestinationString->Length = 0; 380 DestinationString->MaximumLength = 0; 381 DestinationString->Buffer = NULL; 382 } 383 else 384 { 385 USHORT DestMaxLength = SourceString->Length; 386 387 if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE) 388 DestMaxLength += sizeof(UNICODE_NULL); 389 390 DestinationString->Buffer = ExAllocatePoolWithTag(PagedPool, DestMaxLength, TAG_VIDEO_PORT); 391 if (DestinationString->Buffer == NULL) 392 return STATUS_NO_MEMORY; 393 394 RtlCopyMemory(DestinationString->Buffer, SourceString->Buffer, SourceString->Length); 395 DestinationString->Length = SourceString->Length; 396 DestinationString->MaximumLength = DestMaxLength; 397 398 if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE) 399 DestinationString->Buffer[DestinationString->Length / sizeof(WCHAR)] = 0; 400 } 401 402 return STATUS_SUCCESS; 403 } 404 405 NTSTATUS 406 NTAPI 407 IntCreateNewRegistryPath( 408 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension) 409 { 410 static UNICODE_STRING VideoIdValueName = RTL_CONSTANT_STRING(L"VideoId"); 411 static UNICODE_STRING ControlVideoPathName = 412 RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Video\\"); 413 HANDLE DevInstRegKey, SettingsKey, NewKey; 414 UCHAR VideoIdBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + GUID_STRING_LENGTH]; 415 UNICODE_STRING VideoIdString; 416 UUID VideoId; 417 PKEY_VALUE_PARTIAL_INFORMATION ValueInformation ; 418 NTSTATUS Status; 419 ULONG ResultLength; 420 USHORT KeyMaxLength; 421 OBJECT_ATTRIBUTES ObjectAttributes; 422 PWCHAR InstanceIdBuffer; 423 424 if (!DeviceExtension->PhysicalDeviceObject) 425 { 426 Status = IntDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, 427 &DeviceExtension->RegistryPath, 428 &DeviceExtension->NewRegistryPath); 429 if (!NT_SUCCESS(Status)) 430 ERR_(VIDEOPRT, "IntDuplicateUnicodeString() failed with status 0x%lx\n", Status); 431 return Status; 432 } 433 434 /* Open the hardware key: HKLM\System\CurrentControlSet\Enum\... */ 435 Status = IoOpenDeviceRegistryKey(DeviceExtension->PhysicalDeviceObject, 436 PLUGPLAY_REGKEY_DEVICE, 437 KEY_ALL_ACCESS, 438 &DevInstRegKey); 439 if (Status != STATUS_SUCCESS) 440 { 441 ERR_(VIDEOPRT, "IoOpenDeviceRegistryKey failed: status 0x%lx\n", Status); 442 return Status; 443 } 444 445 /* Query the VideoId value */ 446 ValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)VideoIdBuffer; 447 Status = ZwQueryValueKey(DevInstRegKey, 448 &VideoIdValueName, 449 KeyValuePartialInformation, 450 ValueInformation, 451 sizeof(VideoIdBuffer), 452 &ResultLength); 453 if (!NT_SUCCESS(Status)) 454 { 455 /* Create a new video Id */ 456 Status = ExUuidCreate(&VideoId); 457 if (!NT_SUCCESS(Status)) 458 { 459 ERR_(VIDEOPRT, "ExUuidCreate failed: status 0x%lx\n", Status); 460 ObCloseHandle(DevInstRegKey, KernelMode); 461 return Status; 462 } 463 464 /* Convert the GUID into a string */ 465 Status = RtlStringFromGUID(&VideoId, &VideoIdString); 466 if (!NT_SUCCESS(Status)) 467 { 468 ERR_(VIDEOPRT, "RtlStringFromGUID failed: status 0x%lx\n", Status); 469 ObCloseHandle(DevInstRegKey, KernelMode); 470 return Status; 471 } 472 473 /* Copy the GUID String to our buffer */ 474 ValueInformation->DataLength = min(VideoIdString.Length, GUID_STRING_LENGTH); 475 RtlCopyMemory(ValueInformation->Data, 476 VideoIdString.Buffer, 477 ValueInformation->DataLength); 478 479 /* Free the GUID string */ 480 RtlFreeUnicodeString(&VideoIdString); 481 482 /* Write the VideoId registry value */ 483 Status = ZwSetValueKey(DevInstRegKey, 484 &VideoIdValueName, 485 0, 486 REG_SZ, 487 ValueInformation->Data, 488 ValueInformation->DataLength); 489 if (!NT_SUCCESS(Status)) 490 { 491 ERR_(VIDEOPRT, "ZwSetValueKey failed: status 0x%lx\n", Status); 492 ObCloseHandle(DevInstRegKey, KernelMode); 493 return Status; 494 } 495 } 496 497 /* Initialize the VideoId string from the registry data */ 498 VideoIdString.Buffer = (PWCHAR)ValueInformation->Data; 499 VideoIdString.Length = (USHORT)ValueInformation->DataLength; 500 VideoIdString.MaximumLength = VideoIdString.Length; 501 502 /* Close the hardware key */ 503 ObCloseHandle(DevInstRegKey, KernelMode); 504 505 /* Calculate the size needed for the new registry path name */ 506 KeyMaxLength = ControlVideoPathName.Length + 507 VideoIdString.Length + 508 sizeof(L"\\0000"); 509 510 /* Allocate the path name buffer */ 511 DeviceExtension->NewRegistryPath.Length = 0; 512 DeviceExtension->NewRegistryPath.MaximumLength = KeyMaxLength; 513 DeviceExtension->NewRegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool, 514 KeyMaxLength, 515 TAG_VIDEO_PORT); 516 if (DeviceExtension->NewRegistryPath.Buffer == NULL) 517 { 518 ERR_(VIDEOPRT, "Failed to allocate key name buffer.\n"); 519 return STATUS_INSUFFICIENT_RESOURCES; 520 } 521 522 /* Copy the root key name and append the VideoId string */ 523 RtlCopyUnicodeString(&DeviceExtension->NewRegistryPath, 524 &ControlVideoPathName); 525 RtlAppendUnicodeStringToString(&DeviceExtension->NewRegistryPath, 526 &VideoIdString); 527 528 /* Check if we have the key already */ 529 Status = RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, 530 DeviceExtension->NewRegistryPath.Buffer); 531 if (Status != STATUS_SUCCESS) 532 { 533 /* Try to create the new key */ 534 Status = RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE, 535 DeviceExtension->NewRegistryPath.Buffer); 536 } 537 538 /* Append a the instance path */ /// \todo HACK 539 RtlAppendUnicodeToString(&DeviceExtension->NewRegistryPath, L"\\"); 540 InstanceIdBuffer = DeviceExtension->NewRegistryPath.Buffer + 541 DeviceExtension->NewRegistryPath.Length / sizeof(WCHAR); 542 RtlAppendUnicodeToString(&DeviceExtension->NewRegistryPath, L"0000"); 543 544 /* Write instance ID */ 545 swprintf(InstanceIdBuffer, L"%04u", DeviceExtension->DisplayNumber); 546 547 /* Check if the name exists */ 548 Status = RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, 549 DeviceExtension->NewRegistryPath.Buffer); 550 if (Status != STATUS_SUCCESS) 551 { 552 /* Try to create the new key */ 553 Status = RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE, 554 DeviceExtension->NewRegistryPath.Buffer); 555 if (!NT_SUCCESS(Status)) 556 { 557 ERR_(VIDEOPRT, "Failed create key '%wZ'\n", &DeviceExtension->NewRegistryPath); 558 return Status; 559 } 560 561 /* Open the new key */ 562 InitializeObjectAttributes(&ObjectAttributes, 563 &DeviceExtension->NewRegistryPath, 564 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, 565 NULL, 566 NULL); 567 Status = ZwOpenKey(&NewKey, KEY_WRITE, &ObjectAttributes); 568 if (!NT_SUCCESS(Status)) 569 { 570 ERR_(VIDEOPRT, "Failed to open settings key. Status 0x%lx\n", Status); 571 return Status; 572 } 573 574 /* Open the device profile key */ 575 InitializeObjectAttributes(&ObjectAttributes, 576 &DeviceExtension->RegistryPath, 577 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, 578 NULL, 579 NULL); 580 Status = ZwOpenKey(&SettingsKey, KEY_READ, &ObjectAttributes); 581 if (!NT_SUCCESS(Status)) 582 { 583 ERR_(VIDEOPRT, "Failed to open settings key. Status 0x%lx\n", Status); 584 ObCloseHandle(NewKey, KernelMode); 585 return Status; 586 } 587 588 /* Copy the registry data from the legacy key */ 589 Status = IntCopyRegistryKey(SettingsKey, NewKey); 590 591 /* Close the key handles */ 592 ObCloseHandle(SettingsKey, KernelMode); 593 ObCloseHandle(NewKey, KernelMode); 594 } 595 596 return Status; 597 } 598 599 NTSTATUS 600 NTAPI 601 IntCreateRegistryPath( 602 IN PCUNICODE_STRING DriverRegistryPath, 603 IN ULONG DeviceNumber, 604 OUT PUNICODE_STRING DeviceRegistryPath) 605 { 606 static WCHAR RegistryMachineSystem[] = L"\\REGISTRY\\MACHINE\\SYSTEM\\"; 607 static WCHAR CurrentControlSet[] = L"CURRENTCONTROLSET\\"; 608 static WCHAR ControlSet[] = L"CONTROLSET"; 609 static WCHAR Insert1[] = L"Hardware Profiles\\Current\\System\\CurrentControlSet\\"; 610 static WCHAR Insert2[] = L"\\Device"; 611 UNICODE_STRING DeviceNumberString; 612 WCHAR DeviceNumberBuffer[20]; 613 BOOLEAN Valid; 614 UNICODE_STRING AfterControlSet; 615 NTSTATUS Status; 616 617 AfterControlSet = *DriverRegistryPath; 618 619 /* Convert DeviceNumber to string */ 620 DeviceNumberString.Length = 0; 621 DeviceNumberString.MaximumLength = sizeof(DeviceNumberBuffer); 622 DeviceNumberString.Buffer = DeviceNumberBuffer; 623 Status = RtlIntegerToUnicodeString(DeviceNumber, 10, &DeviceNumberString); 624 if (!NT_SUCCESS(Status)) 625 { 626 ERR_(VIDEOPRT, "RtlIntegerToUnicodeString(%u) returned 0x%08x\n", DeviceNumber, Status); 627 return Status; 628 } 629 630 /* Check if path begins with \\REGISTRY\\MACHINE\\SYSTEM\\ */ 631 Valid = (DriverRegistryPath->Length > sizeof(RegistryMachineSystem) && 632 0 == _wcsnicmp(DriverRegistryPath->Buffer, RegistryMachineSystem, 633 wcslen(RegistryMachineSystem))); 634 if (Valid) 635 { 636 AfterControlSet.Buffer += wcslen(RegistryMachineSystem); 637 AfterControlSet.Length -= sizeof(RegistryMachineSystem) - sizeof(UNICODE_NULL); 638 639 /* Check if path contains CURRENTCONTROLSET */ 640 if (AfterControlSet.Length > sizeof(CurrentControlSet) && 641 0 == _wcsnicmp(AfterControlSet.Buffer, CurrentControlSet, wcslen(CurrentControlSet))) 642 { 643 AfterControlSet.Buffer += wcslen(CurrentControlSet); 644 AfterControlSet.Length -= sizeof(CurrentControlSet) - sizeof(UNICODE_NULL); 645 } 646 /* Check if path contains CONTROLSETnum */ 647 else if (AfterControlSet.Length > sizeof(ControlSet) && 648 0 == _wcsnicmp(AfterControlSet.Buffer, ControlSet, wcslen(ControlSet))) 649 { 650 AfterControlSet.Buffer += wcslen(ControlSet); 651 AfterControlSet.Length -= sizeof(ControlSet) - sizeof(UNICODE_NULL); 652 while (AfterControlSet.Length > 0 && 653 *AfterControlSet.Buffer >= L'0' && 654 *AfterControlSet.Buffer <= L'9') 655 { 656 AfterControlSet.Buffer++; 657 AfterControlSet.Length -= sizeof(WCHAR); 658 } 659 660 Valid = (AfterControlSet.Length > 0 && L'\\' == *AfterControlSet.Buffer); 661 AfterControlSet.Buffer++; 662 AfterControlSet.Length -= sizeof(WCHAR); 663 AfterControlSet.MaximumLength = AfterControlSet.Length; 664 } 665 else 666 { 667 Valid = FALSE; 668 } 669 } 670 671 if (!VideoPortUseNewKey) 672 { 673 INFO_(VIDEOPRT, "Using old registry key as 'UseNewKey' is FALSE\n"); 674 Valid = FALSE; 675 } 676 else if (Valid) 677 { 678 DeviceRegistryPath->MaximumLength = DriverRegistryPath->Length + sizeof(Insert1) + sizeof(Insert2) 679 + DeviceNumberString.Length; 680 DeviceRegistryPath->Buffer = ExAllocatePoolWithTag(PagedPool, 681 DeviceRegistryPath->MaximumLength, 682 TAG_VIDEO_PORT); 683 if (DeviceRegistryPath->Buffer != NULL) 684 { 685 /* Build device path */ 686 wcsncpy(DeviceRegistryPath->Buffer, 687 DriverRegistryPath->Buffer, 688 AfterControlSet.Buffer - DriverRegistryPath->Buffer); 689 DeviceRegistryPath->Length = (AfterControlSet.Buffer - DriverRegistryPath->Buffer) * sizeof(WCHAR); 690 RtlAppendUnicodeToString(DeviceRegistryPath, Insert1); 691 RtlAppendUnicodeStringToString(DeviceRegistryPath, &AfterControlSet); 692 RtlAppendUnicodeToString(DeviceRegistryPath, Insert2); 693 RtlAppendUnicodeStringToString(DeviceRegistryPath, &DeviceNumberString); 694 695 /* Check if registry key exists */ 696 Valid = NT_SUCCESS(RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, DeviceRegistryPath->Buffer)); 697 698 if (!Valid) 699 ExFreePoolWithTag(DeviceRegistryPath->Buffer, TAG_VIDEO_PORT); 700 } 701 else 702 { 703 Valid = FALSE; 704 } 705 } 706 else 707 { 708 WARN_(VIDEOPRT, "Unparsable registry path %wZ\n", DriverRegistryPath); 709 } 710 711 /* If path doesn't point to *ControlSet*, use DriverRegistryPath directly */ 712 if (!Valid) 713 { 714 DeviceRegistryPath->MaximumLength = DriverRegistryPath->Length + sizeof(Insert2) + DeviceNumberString.Length; 715 DeviceRegistryPath->Buffer = ExAllocatePoolWithTag(NonPagedPool, 716 DeviceRegistryPath->MaximumLength, 717 TAG_VIDEO_PORT); 718 719 if (!DeviceRegistryPath->Buffer) 720 return STATUS_NO_MEMORY; 721 722 RtlCopyUnicodeString(DeviceRegistryPath, DriverRegistryPath); 723 RtlAppendUnicodeToString(DeviceRegistryPath, Insert2); 724 RtlAppendUnicodeStringToString(DeviceRegistryPath, &DeviceNumberString); 725 } 726 727 DPRINT("Formatted registry key '%wZ' -> '%wZ'\n", 728 DriverRegistryPath, DeviceRegistryPath); 729 730 return STATUS_SUCCESS; 731 } 732