* Sync up to trunk HEAD (r62286).
[reactos.git] / win32ss / drivers / videoprt / registry.c
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
24 #include <ndk/obfuncs.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;
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 0,
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", 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", 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", 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
374 /* Open the hardware key: HKLM\System\CurrentControlSet\Enum\... */
375 Status = IoOpenDeviceRegistryKey(DeviceExtension->PhysicalDeviceObject,
376 PLUGPLAY_REGKEY_DEVICE,
377 KEY_ALL_ACCESS,
378 &DevInstRegKey);
379 if (Status != STATUS_SUCCESS)
380 {
381 ERR_(VIDEOPRT, "IoOpenDeviceRegistryKey failed: status 0x%lx\n", Status);
382 return Status;
383 }
384
385 /* Query the VideoId value */
386 ValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)VideoIdBuffer;
387 Status = ZwQueryValueKey(DevInstRegKey,
388 &VideoIdValueName,
389 KeyValuePartialInformation,
390 ValueInformation,
391 sizeof(VideoIdBuffer),
392 &ResultLength);
393 if (!NT_SUCCESS(Status))
394 {
395 /* Create a new video Id */
396 Status = ExUuidCreate(&VideoId);
397 if (!NT_SUCCESS(Status))
398 {
399 ERR_(VIDEOPRT, "ExUuidCreate failed: status 0x%lx\n", Status);
400 ObCloseHandle(DevInstRegKey, KernelMode);
401 return Status;
402 }
403
404 /* Convert the GUID into a string */
405 Status = RtlStringFromGUID(&VideoId, &VideoIdString);
406 if (!NT_SUCCESS(Status))
407 {
408 ERR_(VIDEOPRT, "RtlStringFromGUID failed: status 0x%lx\n", Status);
409 ObCloseHandle(DevInstRegKey, KernelMode);
410 return Status;
411 }
412
413 /* Copy the GUID String to our buffer */
414 ValueInformation->DataLength = min(VideoIdString.Length, GUID_STRING_LENGTH);
415 RtlCopyMemory(ValueInformation->Data,
416 VideoIdString.Buffer,
417 ValueInformation->DataLength);
418
419 /* Free the GUID string */
420 RtlFreeUnicodeString(&VideoIdString);
421
422 /* Write the VideoId registry value */
423 Status = ZwSetValueKey(DevInstRegKey,
424 &VideoIdValueName,
425 0,
426 REG_SZ,
427 ValueInformation->Data,
428 ValueInformation->DataLength);
429 if (!NT_SUCCESS(Status))
430 {
431 ERR_(VIDEOPRT, "ZwSetValueKey failed: status 0x%lx\n", Status);
432 ObCloseHandle(DevInstRegKey, KernelMode);
433 return Status;
434 }
435 }
436
437 /* Initialize the VideoId string from the registry data */
438 VideoIdString.Buffer = (PWCHAR)ValueInformation->Data;
439 VideoIdString.Length = (USHORT)ValueInformation->DataLength;
440 VideoIdString.MaximumLength = VideoIdString.Length;
441
442 /* Close the hardware key */
443 ObCloseHandle(DevInstRegKey, KernelMode);
444
445 /* Calculate the size needed for the new registry path name */
446 KeyMaxLength = ControlVideoPathName.Length +
447 VideoIdString.Length +
448 sizeof(L"\\0000");
449
450 /* Allocate the path name buffer */
451 DeviceExtension->NewRegistryPath.Length = 0;
452 DeviceExtension->NewRegistryPath.MaximumLength = KeyMaxLength;
453 DeviceExtension->NewRegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool,
454 KeyMaxLength,
455 TAG_VIDEO_PORT);
456 if (DeviceExtension->NewRegistryPath.Buffer == NULL)
457 {
458 ERR_(VIDEOPRT, "Failed to allocate key name buffer.\n");
459 return STATUS_INSUFFICIENT_RESOURCES;
460 }
461
462 /* Copy the root key name and append the VideoId string */
463 RtlCopyUnicodeString(&DeviceExtension->NewRegistryPath,
464 &ControlVideoPathName);
465 RtlAppendUnicodeStringToString(&DeviceExtension->NewRegistryPath,
466 &VideoIdString);
467
468 /* Check if we have the key already */
469 Status = RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE,
470 DeviceExtension->NewRegistryPath.Buffer);
471 if (Status != STATUS_SUCCESS)
472 {
473 /* Try to create the new key */
474 Status = RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE,
475 DeviceExtension->NewRegistryPath.Buffer);
476 }
477
478 /* Append a the instance path */ /// \todo HACK
479 RtlAppendUnicodeToString(&DeviceExtension->NewRegistryPath, L"\\");
480 RtlAppendUnicodeToString(&DeviceExtension->NewRegistryPath, L"0000");
481
482 /* Check this key again */
483 Status = RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE,
484 DeviceExtension->NewRegistryPath.Buffer);
485 if (Status != STATUS_SUCCESS)
486 {
487 /* Try to create the new key */
488 Status = RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE,
489 DeviceExtension->NewRegistryPath.Buffer);
490 if (!NT_SUCCESS(Status))
491 {
492 ERR_(VIDEOPRT, "Failed create key '%wZ'\n", &DeviceExtension->NewRegistryPath);
493 return Status;
494 }
495
496 /* Open the new key */
497 InitializeObjectAttributes(&ObjectAttributes,
498 &DeviceExtension->NewRegistryPath,
499 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
500 NULL,
501 NULL);
502 Status = ZwOpenKey(&NewKey, KEY_READ, &ObjectAttributes);
503 if (!NT_SUCCESS(Status))
504 {
505 ERR_(VIDEOPRT, "Failed to open settings key. Status 0x%lx\n", Status);
506 return Status;
507 }
508
509 /* Open the device profile key */
510 InitializeObjectAttributes(&ObjectAttributes,
511 &DeviceExtension->RegistryPath,
512 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
513 NULL,
514 NULL);
515 Status = ZwOpenKey(&SettingsKey, KEY_READ, &ObjectAttributes);
516 if (!NT_SUCCESS(Status))
517 {
518 ERR_(VIDEOPRT, "Failed to open settings key. Status 0x%lx\n", Status);
519 ObCloseHandle(NewKey, KernelMode);
520 return Status;
521 }
522
523 /* Copy the registry data from the legacy key */
524 Status = IntCopyRegistryKey(SettingsKey, NewKey);
525 }
526
527
528 return Status;
529 }
530
531 NTSTATUS
532 NTAPI
533 IntCreateRegistryPath(
534 IN PCUNICODE_STRING DriverRegistryPath,
535 OUT PUNICODE_STRING DeviceRegistryPath)
536 {
537 static WCHAR RegistryMachineSystem[] = L"\\REGISTRY\\MACHINE\\SYSTEM\\";
538 static WCHAR CurrentControlSet[] = L"CURRENTCONTROLSET\\";
539 static WCHAR ControlSet[] = L"CONTROLSET";
540 static WCHAR Insert1[] = L"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
541 static WCHAR Insert2[] = L"\\Device0";
542 BOOLEAN Valid;
543 UNICODE_STRING AfterControlSet;
544
545 AfterControlSet = *DriverRegistryPath;
546
547 /* Check if path begins with \\REGISTRY\\MACHINE\\SYSTEM\\ */
548 Valid = (DriverRegistryPath->Length > sizeof(RegistryMachineSystem) &&
549 0 == _wcsnicmp(DriverRegistryPath->Buffer, RegistryMachineSystem,
550 wcslen(RegistryMachineSystem)));
551 if (Valid)
552 {
553 AfterControlSet.Buffer += wcslen(RegistryMachineSystem);
554 AfterControlSet.Length -= sizeof(RegistryMachineSystem) - sizeof(UNICODE_NULL);
555
556 /* Check if path contains CURRENTCONTROLSET */
557 if (AfterControlSet.Length > sizeof(CurrentControlSet) &&
558 0 == _wcsnicmp(AfterControlSet.Buffer, CurrentControlSet, wcslen(CurrentControlSet)))
559 {
560 AfterControlSet.Buffer += wcslen(CurrentControlSet);
561 AfterControlSet.Length -= sizeof(CurrentControlSet) - sizeof(UNICODE_NULL);
562 }
563 /* Check if path contains CONTROLSETnum */
564 else if (AfterControlSet.Length > sizeof(ControlSet) &&
565 0 == _wcsnicmp(AfterControlSet.Buffer, ControlSet, wcslen(ControlSet)))
566 {
567 AfterControlSet.Buffer += wcslen(ControlSet);
568 AfterControlSet.Length -= sizeof(ControlSet) - sizeof(UNICODE_NULL);
569 while (AfterControlSet.Length > 0 &&
570 *AfterControlSet.Buffer >= L'0' &&
571 *AfterControlSet.Buffer <= L'9')
572 {
573 AfterControlSet.Buffer++;
574 AfterControlSet.Length -= sizeof(WCHAR);
575 }
576
577 Valid = (AfterControlSet.Length > 0 && L'\\' == *AfterControlSet.Buffer);
578 AfterControlSet.Buffer++;
579 AfterControlSet.Length -= sizeof(WCHAR);
580 AfterControlSet.MaximumLength = AfterControlSet.Length;
581 }
582 else
583 {
584 Valid = FALSE;
585 }
586 }
587
588 if (Valid)
589 {
590 DeviceRegistryPath->MaximumLength = DriverRegistryPath->Length + sizeof(Insert1) + sizeof(Insert2);
591 DeviceRegistryPath->Buffer = ExAllocatePoolWithTag(PagedPool,
592 DeviceRegistryPath->MaximumLength,
593 TAG_VIDEO_PORT);
594 if (DeviceRegistryPath->Buffer != NULL)
595 {
596 /* Build device path */
597 wcsncpy(DeviceRegistryPath->Buffer,
598 DriverRegistryPath->Buffer,
599 AfterControlSet.Buffer - DriverRegistryPath->Buffer);
600 DeviceRegistryPath->Length = (AfterControlSet.Buffer - DriverRegistryPath->Buffer) * sizeof(WCHAR);
601 RtlAppendUnicodeToString(DeviceRegistryPath, Insert1);
602 RtlAppendUnicodeStringToString(DeviceRegistryPath, &AfterControlSet);
603 RtlAppendUnicodeToString(DeviceRegistryPath, Insert2);
604
605 /* Check if registry key exists */
606 Valid = NT_SUCCESS(RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, DeviceRegistryPath->Buffer));
607
608 if (!Valid)
609 ExFreePoolWithTag(DeviceRegistryPath->Buffer, TAG_VIDEO_PORT);
610 }
611 else
612 {
613 Valid = FALSE;
614 }
615 }
616 else
617 {
618 WARN_(VIDEOPRT, "Unparsable registry path %wZ", DriverRegistryPath);
619 }
620
621 /* If path doesn't point to *ControlSet*, use DriverRegistryPath directly */
622 if (!Valid)
623 {
624 DeviceRegistryPath->MaximumLength = DriverRegistryPath->Length + sizeof(Insert2);
625 DeviceRegistryPath->Buffer = ExAllocatePoolWithTag(NonPagedPool,
626 DeviceRegistryPath->MaximumLength,
627 TAG_VIDEO_PORT);
628
629 if (!DeviceRegistryPath->Buffer)
630 return STATUS_NO_MEMORY;
631
632 RtlCopyUnicodeString(DeviceRegistryPath, DriverRegistryPath);
633 RtlAppendUnicodeToString(DeviceRegistryPath, Insert2);
634 }
635
636 DbgPrint("Formatted registry key '%wZ' -> '%wZ'\n",
637 DriverRegistryPath, DeviceRegistryPath);
638
639 return STATUS_SUCCESS;
640 }