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