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