[VIDEOPRT][WIN32K] Use a Windows-compatible way of communicating the 'BaseVideo'...
[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 #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 }