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 /* Open the software key: HKLM\System\CurrentControlSet\Control\Class\<ClassGUID>\<n> */ 306 Status = IoOpenDeviceRegistryKey(DeviceExtension->PhysicalDeviceObject, 307 PLUGPLAY_REGKEY_DRIVER, 308 KEY_ALL_ACCESS, 309 &DevInstRegKey); 310 if (Status != STATUS_SUCCESS) 311 { 312 ERR_(VIDEOPRT, "Failed to open device software key. Status 0x%lx\n", Status); 313 return Status; 314 } 315 316 /* Open the 'Settings' sub-key */ 317 InitializeObjectAttributes(&ObjectAttributes, 318 &SettingsKeyName, 319 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, 320 DevInstRegKey, 321 NULL); 322 Status = ZwOpenKey(&DestKeyHandle, KEY_WRITE, &ObjectAttributes); 323 324 /* Close the device software key */ 325 ObCloseHandle(DevInstRegKey, KernelMode); 326 327 if (Status != STATUS_SUCCESS) 328 { 329 ERR_(VIDEOPRT, "Failed to open settings key. Status 0x%lx\n", Status); 330 return Status; 331 } 332 333 /* Open the device profile key */ 334 InitializeObjectAttributes(&ObjectAttributes, 335 &DeviceExtension->RegistryPath, 336 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, 337 NULL, 338 NULL); 339 Status = ZwOpenKey(&SourceKeyHandle, KEY_WRITE, &ObjectAttributes); 340 if (Status != STATUS_SUCCESS) 341 { 342 ERR_(VIDEOPRT, "ZwOpenKey failed for settings key: status 0x%lx\n", Status); 343 ObCloseHandle(DestKeyHandle, KernelMode); 344 return Status; 345 } 346 347 IntCopyRegistryValue(SourceKeyHandle, DestKeyHandle, L"InstalledDisplayDrivers"); 348 IntCopyRegistryValue(SourceKeyHandle, DestKeyHandle, L"Attach.ToDesktop"); 349 350 ObCloseHandle(SourceKeyHandle, KernelMode); 351 ObCloseHandle(DestKeyHandle, KernelMode); 352 353 return STATUS_SUCCESS; 354 } 355 356 NTSTATUS 357 NTAPI 358 IntCreateNewRegistryPath( 359 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension) 360 { 361 static UNICODE_STRING VideoIdValueName = RTL_CONSTANT_STRING(L"VideoId"); 362 static UNICODE_STRING ControlVideoPathName = 363 RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Video\\"); 364 HANDLE DevInstRegKey, SettingsKey, NewKey; 365 UCHAR VideoIdBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + GUID_STRING_LENGTH]; 366 UNICODE_STRING VideoIdString; 367 UUID VideoId; 368 PKEY_VALUE_PARTIAL_INFORMATION ValueInformation ; 369 NTSTATUS Status; 370 ULONG ResultLength; 371 USHORT KeyMaxLength; 372 OBJECT_ATTRIBUTES ObjectAttributes; 373 PWCHAR InstanceIdBuffer; 374 375 /* Open the hardware key: HKLM\System\CurrentControlSet\Enum\... */ 376 Status = IoOpenDeviceRegistryKey(DeviceExtension->PhysicalDeviceObject, 377 PLUGPLAY_REGKEY_DEVICE, 378 KEY_ALL_ACCESS, 379 &DevInstRegKey); 380 if (Status != STATUS_SUCCESS) 381 { 382 ERR_(VIDEOPRT, "IoOpenDeviceRegistryKey failed: status 0x%lx\n", Status); 383 return Status; 384 } 385 386 /* Query the VideoId value */ 387 ValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)VideoIdBuffer; 388 Status = ZwQueryValueKey(DevInstRegKey, 389 &VideoIdValueName, 390 KeyValuePartialInformation, 391 ValueInformation, 392 sizeof(VideoIdBuffer), 393 &ResultLength); 394 if (!NT_SUCCESS(Status)) 395 { 396 /* Create a new video Id */ 397 Status = ExUuidCreate(&VideoId); 398 if (!NT_SUCCESS(Status)) 399 { 400 ERR_(VIDEOPRT, "ExUuidCreate failed: status 0x%lx\n", Status); 401 ObCloseHandle(DevInstRegKey, KernelMode); 402 return Status; 403 } 404 405 /* Convert the GUID into a string */ 406 Status = RtlStringFromGUID(&VideoId, &VideoIdString); 407 if (!NT_SUCCESS(Status)) 408 { 409 ERR_(VIDEOPRT, "RtlStringFromGUID failed: status 0x%lx\n", Status); 410 ObCloseHandle(DevInstRegKey, KernelMode); 411 return Status; 412 } 413 414 /* Copy the GUID String to our buffer */ 415 ValueInformation->DataLength = min(VideoIdString.Length, GUID_STRING_LENGTH); 416 RtlCopyMemory(ValueInformation->Data, 417 VideoIdString.Buffer, 418 ValueInformation->DataLength); 419 420 /* Free the GUID string */ 421 RtlFreeUnicodeString(&VideoIdString); 422 423 /* Write the VideoId registry value */ 424 Status = ZwSetValueKey(DevInstRegKey, 425 &VideoIdValueName, 426 0, 427 REG_SZ, 428 ValueInformation->Data, 429 ValueInformation->DataLength); 430 if (!NT_SUCCESS(Status)) 431 { 432 ERR_(VIDEOPRT, "ZwSetValueKey failed: status 0x%lx\n", Status); 433 ObCloseHandle(DevInstRegKey, KernelMode); 434 return Status; 435 } 436 } 437 438 /* Initialize the VideoId string from the registry data */ 439 VideoIdString.Buffer = (PWCHAR)ValueInformation->Data; 440 VideoIdString.Length = (USHORT)ValueInformation->DataLength; 441 VideoIdString.MaximumLength = VideoIdString.Length; 442 443 /* Close the hardware key */ 444 ObCloseHandle(DevInstRegKey, KernelMode); 445 446 /* Calculate the size needed for the new registry path name */ 447 KeyMaxLength = ControlVideoPathName.Length + 448 VideoIdString.Length + 449 sizeof(L"\\0000"); 450 451 /* Allocate the path name buffer */ 452 DeviceExtension->NewRegistryPath.Length = 0; 453 DeviceExtension->NewRegistryPath.MaximumLength = KeyMaxLength; 454 DeviceExtension->NewRegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool, 455 KeyMaxLength, 456 TAG_VIDEO_PORT); 457 if (DeviceExtension->NewRegistryPath.Buffer == NULL) 458 { 459 ERR_(VIDEOPRT, "Failed to allocate key name buffer.\n"); 460 return STATUS_INSUFFICIENT_RESOURCES; 461 } 462 463 /* Copy the root key name and append the VideoId string */ 464 RtlCopyUnicodeString(&DeviceExtension->NewRegistryPath, 465 &ControlVideoPathName); 466 RtlAppendUnicodeStringToString(&DeviceExtension->NewRegistryPath, 467 &VideoIdString); 468 469 /* Check if we have the key already */ 470 Status = RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, 471 DeviceExtension->NewRegistryPath.Buffer); 472 if (Status != STATUS_SUCCESS) 473 { 474 /* Try to create the new key */ 475 Status = RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE, 476 DeviceExtension->NewRegistryPath.Buffer); 477 } 478 479 /* Append a the instance path */ /// \todo HACK 480 RtlAppendUnicodeToString(&DeviceExtension->NewRegistryPath, L"\\"); 481 InstanceIdBuffer = DeviceExtension->NewRegistryPath.Buffer + 482 DeviceExtension->NewRegistryPath.Length / sizeof(WCHAR); 483 RtlAppendUnicodeToString(&DeviceExtension->NewRegistryPath, L"0000"); 484 485 /* Write instance ID */ 486 swprintf(InstanceIdBuffer, L"%04u", DeviceExtension->DisplayNumber); 487 488 /* Check if the name exists */ 489 Status = RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, 490 DeviceExtension->NewRegistryPath.Buffer); 491 if (Status != STATUS_SUCCESS) 492 { 493 /* Try to create the new key */ 494 Status = RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE, 495 DeviceExtension->NewRegistryPath.Buffer); 496 if (!NT_SUCCESS(Status)) 497 { 498 ERR_(VIDEOPRT, "Failed create key '%wZ'\n", &DeviceExtension->NewRegistryPath); 499 return Status; 500 } 501 } 502 503 /* Open the new key */ 504 InitializeObjectAttributes(&ObjectAttributes, 505 &DeviceExtension->NewRegistryPath, 506 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, 507 NULL, 508 NULL); 509 Status = ZwOpenKey(&NewKey, KEY_READ, &ObjectAttributes); 510 if (!NT_SUCCESS(Status)) 511 { 512 ERR_(VIDEOPRT, "Failed to open settings key. Status 0x%lx\n", Status); 513 return Status; 514 } 515 516 /* Open the device profile key */ 517 InitializeObjectAttributes(&ObjectAttributes, 518 &DeviceExtension->RegistryPath, 519 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, 520 NULL, 521 NULL); 522 Status = ZwOpenKey(&SettingsKey, KEY_READ, &ObjectAttributes); 523 if (!NT_SUCCESS(Status)) 524 { 525 ERR_(VIDEOPRT, "Failed to open settings key. Status 0x%lx\n", Status); 526 ObCloseHandle(NewKey, KernelMode); 527 return Status; 528 } 529 530 /* Copy the registry data from the legacy key */ 531 Status = IntCopyRegistryKey(SettingsKey, NewKey); 532 533 /* Close the key handles */ 534 ObCloseHandle(SettingsKey, KernelMode); 535 ObCloseHandle(NewKey, KernelMode); 536 537 return Status; 538 } 539 540 NTSTATUS 541 NTAPI 542 IntCreateRegistryPath( 543 IN PCUNICODE_STRING DriverRegistryPath, 544 IN ULONG DeviceNumber, 545 OUT PUNICODE_STRING DeviceRegistryPath) 546 { 547 static WCHAR RegistryMachineSystem[] = L"\\REGISTRY\\MACHINE\\SYSTEM\\"; 548 static WCHAR CurrentControlSet[] = L"CURRENTCONTROLSET\\"; 549 static WCHAR ControlSet[] = L"CONTROLSET"; 550 static WCHAR Insert1[] = L"Hardware Profiles\\Current\\System\\CurrentControlSet\\"; 551 static WCHAR Insert2[] = L"\\Device"; 552 UNICODE_STRING DeviceNumberString; 553 WCHAR DeviceNumberBuffer[20]; 554 BOOLEAN Valid; 555 UNICODE_STRING AfterControlSet; 556 NTSTATUS Status; 557 558 AfterControlSet = *DriverRegistryPath; 559 560 /* Convert DeviceNumber to string */ 561 DeviceNumberString.Length = 0; 562 DeviceNumberString.MaximumLength = sizeof(DeviceNumberBuffer); 563 DeviceNumberString.Buffer = DeviceNumberBuffer; 564 Status = RtlIntegerToUnicodeString(DeviceNumber, 10, &DeviceNumberString); 565 if (!NT_SUCCESS(Status)) 566 { 567 ERR_(VIDEOPRT, "RtlIntegerToUnicodeString(%u) returned 0x%08x\n", DeviceNumber, Status); 568 return Status; 569 } 570 571 /* Check if path begins with \\REGISTRY\\MACHINE\\SYSTEM\\ */ 572 Valid = (DriverRegistryPath->Length > sizeof(RegistryMachineSystem) && 573 0 == _wcsnicmp(DriverRegistryPath->Buffer, RegistryMachineSystem, 574 wcslen(RegistryMachineSystem))); 575 if (Valid) 576 { 577 AfterControlSet.Buffer += wcslen(RegistryMachineSystem); 578 AfterControlSet.Length -= sizeof(RegistryMachineSystem) - sizeof(UNICODE_NULL); 579 580 /* Check if path contains CURRENTCONTROLSET */ 581 if (AfterControlSet.Length > sizeof(CurrentControlSet) && 582 0 == _wcsnicmp(AfterControlSet.Buffer, CurrentControlSet, wcslen(CurrentControlSet))) 583 { 584 AfterControlSet.Buffer += wcslen(CurrentControlSet); 585 AfterControlSet.Length -= sizeof(CurrentControlSet) - sizeof(UNICODE_NULL); 586 } 587 /* Check if path contains CONTROLSETnum */ 588 else if (AfterControlSet.Length > sizeof(ControlSet) && 589 0 == _wcsnicmp(AfterControlSet.Buffer, ControlSet, wcslen(ControlSet))) 590 { 591 AfterControlSet.Buffer += wcslen(ControlSet); 592 AfterControlSet.Length -= sizeof(ControlSet) - sizeof(UNICODE_NULL); 593 while (AfterControlSet.Length > 0 && 594 *AfterControlSet.Buffer >= L'0' && 595 *AfterControlSet.Buffer <= L'9') 596 { 597 AfterControlSet.Buffer++; 598 AfterControlSet.Length -= sizeof(WCHAR); 599 } 600 601 Valid = (AfterControlSet.Length > 0 && L'\\' == *AfterControlSet.Buffer); 602 AfterControlSet.Buffer++; 603 AfterControlSet.Length -= sizeof(WCHAR); 604 AfterControlSet.MaximumLength = AfterControlSet.Length; 605 } 606 else 607 { 608 Valid = FALSE; 609 } 610 } 611 612 if (Valid) 613 { 614 DeviceRegistryPath->MaximumLength = DriverRegistryPath->Length + sizeof(Insert1) + sizeof(Insert2) 615 + DeviceNumberString.Length; 616 DeviceRegistryPath->Buffer = ExAllocatePoolWithTag(PagedPool, 617 DeviceRegistryPath->MaximumLength, 618 TAG_VIDEO_PORT); 619 if (DeviceRegistryPath->Buffer != NULL) 620 { 621 /* Build device path */ 622 wcsncpy(DeviceRegistryPath->Buffer, 623 DriverRegistryPath->Buffer, 624 AfterControlSet.Buffer - DriverRegistryPath->Buffer); 625 DeviceRegistryPath->Length = (AfterControlSet.Buffer - DriverRegistryPath->Buffer) * sizeof(WCHAR); 626 RtlAppendUnicodeToString(DeviceRegistryPath, Insert1); 627 RtlAppendUnicodeStringToString(DeviceRegistryPath, &AfterControlSet); 628 RtlAppendUnicodeToString(DeviceRegistryPath, Insert2); 629 RtlAppendUnicodeStringToString(DeviceRegistryPath, &DeviceNumberString); 630 631 /* Check if registry key exists */ 632 Valid = NT_SUCCESS(RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, DeviceRegistryPath->Buffer)); 633 634 if (!Valid) 635 ExFreePoolWithTag(DeviceRegistryPath->Buffer, TAG_VIDEO_PORT); 636 } 637 else 638 { 639 Valid = FALSE; 640 } 641 } 642 else 643 { 644 WARN_(VIDEOPRT, "Unparsable registry path %wZ\n", DriverRegistryPath); 645 } 646 647 /* If path doesn't point to *ControlSet*, use DriverRegistryPath directly */ 648 if (!Valid) 649 { 650 DeviceRegistryPath->MaximumLength = DriverRegistryPath->Length + sizeof(Insert2) + DeviceNumberString.Length; 651 DeviceRegistryPath->Buffer = ExAllocatePoolWithTag(NonPagedPool, 652 DeviceRegistryPath->MaximumLength, 653 TAG_VIDEO_PORT); 654 655 if (!DeviceRegistryPath->Buffer) 656 return STATUS_NO_MEMORY; 657 658 RtlCopyUnicodeString(DeviceRegistryPath, DriverRegistryPath); 659 RtlAppendUnicodeToString(DeviceRegistryPath, Insert2); 660 RtlAppendUnicodeStringToString(DeviceRegistryPath, &DeviceNumberString); 661 } 662 663 DPRINT("Formatted registry key '%wZ' -> '%wZ'\n", 664 DriverRegistryPath, DeviceRegistryPath); 665 666 return STATUS_SUCCESS; 667 } 668