4 * Copyright (C) 2002-2004, 2007 ReactOS Team
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.
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.
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
24 #include <ndk/obfuncs.h>
32 _In_ HANDLE SourceKeyHandle
,
33 _In_ HANDLE DestKeyHandle
)
36 PKEY_BASIC_INFORMATION KeyInformation
;
37 PKEY_VALUE_FULL_INFORMATION KeyValueInformation
;
38 OBJECT_ATTRIBUTES ObjectAttributes
;
39 ULONG Index
, InformationLength
, RequiredLength
;
40 UNICODE_STRING NameString
;
42 HANDLE SourceSubKeyHandle
, DestSubKeyHandle
;
44 /* Start with no buffer, set initial size */
46 InformationLength
= 256;
48 /* Start looping with key index 0 */
52 /* Check if we have no buffer */
53 if (InfoBuffer
== NULL
)
55 /* Allocate a new buffer */
56 InfoBuffer
= ExAllocatePoolWithTag(PagedPool
,
58 TAG_VIDEO_PORT_BUFFER
);
59 if (InfoBuffer
== NULL
)
61 ERR_(VIDEOPRT
, "Could not allocate buffer for key info\n");
66 /* Enumerate the next sub-key */
67 KeyInformation
= InfoBuffer
;
68 Status
= ZwEnumerateKey(SourceKeyHandle
,
74 if ((Status
== STATUS_BUFFER_OVERFLOW
) ||
75 (Status
== STATUS_BUFFER_TOO_SMALL
))
77 /* Free the buffer and remember the required size */
78 ExFreePoolWithTag(InfoBuffer
, TAG_VIDEO_PORT_BUFFER
);
80 InformationLength
= RequiredLength
;
85 else if (Status
== STATUS_NO_MORE_ENTRIES
)
87 /* We are done with the sub-keys */
90 else if (!NT_SUCCESS(Status
))
92 ERR_(VIDEOPRT
, "ZwEnumerateKey failed, status 0x%lx\n", Status
);
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
;
101 /* Initialize object attributes and open the source sub-key */
102 InitializeObjectAttributes(&ObjectAttributes
,
104 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
107 Status
= ZwOpenKey(&SourceSubKeyHandle
, KEY_READ
, &ObjectAttributes
);
108 if (!NT_SUCCESS(Status
))
110 ERR_(VIDEOPRT
, "failed to open the source key.\n");
114 /* Initialize object attributes and create the dest sub-key */
115 InitializeObjectAttributes(&ObjectAttributes
,
117 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
120 Status
= ZwCreateKey(&DestSubKeyHandle
,
127 if (!NT_SUCCESS(Status
))
129 ERR_(VIDEOPRT
, "failed to create the destination key.\n");
130 ObCloseHandle(SourceSubKeyHandle
, KernelMode
);
134 /* Recursively copy the sub-key */
135 Status
= IntCopyRegistryKey(SourceSubKeyHandle
, DestSubKeyHandle
);
136 if (!NT_SUCCESS(Status
))
138 /* Just warn, but continue with the remaining sub-keys */
139 WARN_(VIDEOPRT
, "failed to copy subkey '%wZ'.\n", &NameString
);
142 /* Close the sub-key handles */
143 ObCloseHandle(SourceSubKeyHandle
, KernelMode
);
144 ObCloseHandle(DestSubKeyHandle
, KernelMode
);
150 /* Start looping with value index 0 */
154 /* Check if we have no buffer */
155 if (InfoBuffer
== NULL
)
157 /* Allocate a new buffer */
158 InfoBuffer
= ExAllocatePoolWithTag(PagedPool
,
160 TAG_VIDEO_PORT_BUFFER
);
161 if (InfoBuffer
== NULL
)
163 ERR_(VIDEOPRT
, "Could not allocate buffer for key values\n");
168 /* Enumerate the next value */
169 KeyValueInformation
= InfoBuffer
;
170 Status
= ZwEnumerateValueKey(SourceKeyHandle
,
172 KeyValueFullInformation
,
176 if ((Status
== STATUS_BUFFER_OVERFLOW
) ||
177 (Status
== STATUS_BUFFER_TOO_SMALL
))
179 /* Free the buffer and remember the required size */
180 ExFreePoolWithTag(InfoBuffer
, TAG_VIDEO_PORT_BUFFER
);
182 InformationLength
= RequiredLength
;
187 else if (Status
== STATUS_NO_MORE_ENTRIES
)
189 /* We are done with the values */
190 Status
= STATUS_SUCCESS
;
193 else if (!NT_SUCCESS(Status
))
195 ERR_(VIDEOPRT
, "ZwEnumerateValueKey failed, status 0x%lx\n", Status
);
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
;
204 /* Create the key value in the destination key */
205 Status
= ZwSetValueKey(DestKeyHandle
,
207 KeyValueInformation
->TitleIndex
,
208 KeyValueInformation
->Type
,
209 (PUCHAR
)KeyValueInformation
+ KeyValueInformation
->DataOffset
,
210 KeyValueInformation
->DataLength
);
211 if (!NT_SUCCESS(Status
))
213 /* Just warn, but continue with the remaining sub-keys */
214 WARN_(VIDEOPRT
, "failed to set value '%wZ'.\n", NameString
);
222 /* Free the buffer and return the failure code */
223 if (InfoBuffer
!= NULL
)
224 ExFreePoolWithTag(InfoBuffer
, TAG_VIDEO_PORT_BUFFER
);
230 IntCopyRegistryValue(
231 HANDLE SourceKeyHandle
,
232 HANDLE DestKeyHandle
,
235 PKEY_VALUE_PARTIAL_INFORMATION ValueInformation
;
236 UNICODE_STRING ValueNameString
;
240 RtlInitUnicodeString(&ValueNameString
, ValueName
);
242 /* Query the value length */
243 Status
= ZwQueryValueKey(SourceKeyHandle
,
245 KeyValuePartialInformation
,
249 if ((Status
!= STATUS_BUFFER_OVERFLOW
) &&
250 (Status
!= STATUS_BUFFER_TOO_SMALL
))
252 /* The key seems not present */
253 NT_ASSERT(!NT_SUCCESS(Status
));
257 /* Allocate a buffer */
258 ValueInformation
= ExAllocatePoolWithTag(PagedPool
, Length
, TAG_VIDEO_PORT_BUFFER
);
259 if (ValueInformation
== NULL
)
264 /* Query the value */
265 Status
= ZwQueryValueKey(SourceKeyHandle
,
267 KeyValuePartialInformation
,
271 if (!NT_SUCCESS(Status
))
273 ExFreePoolWithTag(ValueInformation
, TAG_VIDEO_PORT_BUFFER
);
277 /* Write the registry value */
278 Status
= ZwSetValueKey(DestKeyHandle
,
280 ValueInformation
->TitleIndex
,
281 ValueInformation
->Type
,
282 ValueInformation
->Data
,
283 ValueInformation
->DataLength
);
285 ExFreePoolWithTag(ValueInformation
, TAG_VIDEO_PORT_BUFFER
);
287 if (!NT_SUCCESS(Status
))
289 ERR_(VIDEOPRT
, "ZwSetValueKey failed: status 0x%lx\n", Status
);
297 IntSetupDeviceSettingsKey(
298 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
)
300 static UNICODE_STRING SettingsKeyName
= RTL_CONSTANT_STRING(L
"Settings");
301 HANDLE DevInstRegKey
, SourceKeyHandle
, DestKeyHandle
;
302 OBJECT_ATTRIBUTES ObjectAttributes
;
305 /* Open the software key: HKLM\System\CurrentControlSet\Control\Class\<ClassGUID>\<n> */
306 Status
= IoOpenDeviceRegistryKey(DeviceExtension
->PhysicalDeviceObject
,
307 PLUGPLAY_REGKEY_DRIVER
,
310 if (Status
!= STATUS_SUCCESS
)
312 ERR_(VIDEOPRT
, "Failed to open device software key. Status 0x%lx\n", Status
);
316 /* Open the 'Settings' sub-key */
317 InitializeObjectAttributes(&ObjectAttributes
,
319 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
322 Status
= ZwOpenKey(&DestKeyHandle
, KEY_WRITE
, &ObjectAttributes
);
324 /* Close the device software key */
325 ObCloseHandle(DevInstRegKey
, KernelMode
);
327 if (Status
!= STATUS_SUCCESS
)
329 ERR_(VIDEOPRT
, "Failed to open settings key. Status 0x%lx\n", Status
);
333 /* Open the device profile key */
334 InitializeObjectAttributes(&ObjectAttributes
,
335 &DeviceExtension
->RegistryPath
,
336 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
339 Status
= ZwOpenKey(&SourceKeyHandle
, KEY_WRITE
, &ObjectAttributes
);
340 if (Status
!= STATUS_SUCCESS
)
342 ERR_(VIDEOPRT
, "ZwOpenKey failed for settings key: status 0x%lx\n", Status
);
343 ObCloseHandle(DestKeyHandle
, KernelMode
);
347 IntCopyRegistryValue(SourceKeyHandle
, DestKeyHandle
, L
"InstalledDisplayDrivers");
348 IntCopyRegistryValue(SourceKeyHandle
, DestKeyHandle
, L
"Attach.ToDesktop");
350 ObCloseHandle(SourceKeyHandle
, KernelMode
);
351 ObCloseHandle(DestKeyHandle
, KernelMode
);
353 return STATUS_SUCCESS
;
358 IntCreateNewRegistryPath(
359 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
)
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
;
368 PKEY_VALUE_PARTIAL_INFORMATION ValueInformation
;
372 OBJECT_ATTRIBUTES ObjectAttributes
;
374 /* Open the hardware key: HKLM\System\CurrentControlSet\Enum\... */
375 Status
= IoOpenDeviceRegistryKey(DeviceExtension
->PhysicalDeviceObject
,
376 PLUGPLAY_REGKEY_DEVICE
,
379 if (Status
!= STATUS_SUCCESS
)
381 ERR_(VIDEOPRT
, "IoOpenDeviceRegistryKey failed: status 0x%lx\n", Status
);
385 /* Query the VideoId value */
386 ValueInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)VideoIdBuffer
;
387 Status
= ZwQueryValueKey(DevInstRegKey
,
389 KeyValuePartialInformation
,
391 sizeof(VideoIdBuffer
),
393 if (!NT_SUCCESS(Status
))
395 /* Create a new video Id */
396 Status
= ExUuidCreate(&VideoId
);
397 if (!NT_SUCCESS(Status
))
399 ERR_(VIDEOPRT
, "ExUuidCreate failed: status 0x%lx\n", Status
);
400 ObCloseHandle(DevInstRegKey
, KernelMode
);
404 /* Convert the GUID into a string */
405 Status
= RtlStringFromGUID(&VideoId
, &VideoIdString
);
406 if (!NT_SUCCESS(Status
))
408 ERR_(VIDEOPRT
, "RtlStringFromGUID failed: status 0x%lx\n", Status
);
409 ObCloseHandle(DevInstRegKey
, KernelMode
);
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
);
419 /* Free the GUID string */
420 RtlFreeUnicodeString(&VideoIdString
);
422 /* Write the VideoId registry value */
423 Status
= ZwSetValueKey(DevInstRegKey
,
427 ValueInformation
->Data
,
428 ValueInformation
->DataLength
);
429 if (!NT_SUCCESS(Status
))
431 ERR_(VIDEOPRT
, "ZwSetValueKey failed: status 0x%lx\n", Status
);
432 ObCloseHandle(DevInstRegKey
, KernelMode
);
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
;
442 /* Close the hardware key */
443 ObCloseHandle(DevInstRegKey
, KernelMode
);
445 /* Calculate the size needed for the new registry path name */
446 KeyMaxLength
= ControlVideoPathName
.Length
+
447 VideoIdString
.Length
+
450 /* Allocate the path name buffer */
451 DeviceExtension
->NewRegistryPath
.Length
= 0;
452 DeviceExtension
->NewRegistryPath
.MaximumLength
= KeyMaxLength
;
453 DeviceExtension
->NewRegistryPath
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
456 if (DeviceExtension
->NewRegistryPath
.Buffer
== NULL
)
458 ERR_(VIDEOPRT
, "Failed to allocate key name buffer.\n");
459 return STATUS_INSUFFICIENT_RESOURCES
;
462 /* Copy the root key name and append the VideoId string */
463 RtlCopyUnicodeString(&DeviceExtension
->NewRegistryPath
,
464 &ControlVideoPathName
);
465 RtlAppendUnicodeStringToString(&DeviceExtension
->NewRegistryPath
,
468 /* Check if we have the key already */
469 Status
= RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE
,
470 DeviceExtension
->NewRegistryPath
.Buffer
);
471 if (Status
!= STATUS_SUCCESS
)
473 /* Try to create the new key */
474 Status
= RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE
,
475 DeviceExtension
->NewRegistryPath
.Buffer
);
478 /* Append a the instance path */ /// \todo HACK
479 RtlAppendUnicodeToString(&DeviceExtension
->NewRegistryPath
, L
"\\");
480 RtlAppendUnicodeToString(&DeviceExtension
->NewRegistryPath
, L
"0000");
482 /* Check this key again */
483 Status
= RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE
,
484 DeviceExtension
->NewRegistryPath
.Buffer
);
485 if (Status
!= STATUS_SUCCESS
)
487 /* Try to create the new key */
488 Status
= RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE
,
489 DeviceExtension
->NewRegistryPath
.Buffer
);
490 if (!NT_SUCCESS(Status
))
492 ERR_(VIDEOPRT
, "Failed create key '%wZ'\n", &DeviceExtension
->NewRegistryPath
);
496 /* Open the new key */
497 InitializeObjectAttributes(&ObjectAttributes
,
498 &DeviceExtension
->NewRegistryPath
,
499 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
502 Status
= ZwOpenKey(&NewKey
, KEY_READ
, &ObjectAttributes
);
503 if (!NT_SUCCESS(Status
))
505 ERR_(VIDEOPRT
, "Failed to open settings key. Status 0x%lx\n", Status
);
509 /* Open the device profile key */
510 InitializeObjectAttributes(&ObjectAttributes
,
511 &DeviceExtension
->RegistryPath
,
512 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
515 Status
= ZwOpenKey(&SettingsKey
, KEY_READ
, &ObjectAttributes
);
516 if (!NT_SUCCESS(Status
))
518 ERR_(VIDEOPRT
, "Failed to open settings key. Status 0x%lx\n", Status
);
519 ObCloseHandle(NewKey
, KernelMode
);
523 /* Copy the registry data from the legacy key */
524 Status
= IntCopyRegistryKey(SettingsKey
, NewKey
);
533 IntCreateRegistryPath(
534 IN PCUNICODE_STRING DriverRegistryPath
,
535 OUT PUNICODE_STRING DeviceRegistryPath
)
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";
543 UNICODE_STRING AfterControlSet
;
545 AfterControlSet
= *DriverRegistryPath
;
547 /* Check if path begins with \\REGISTRY\\MACHINE\\SYSTEM\\ */
548 Valid
= (DriverRegistryPath
->Length
> sizeof(RegistryMachineSystem
) &&
549 0 == _wcsnicmp(DriverRegistryPath
->Buffer
, RegistryMachineSystem
,
550 wcslen(RegistryMachineSystem
)));
553 AfterControlSet
.Buffer
+= wcslen(RegistryMachineSystem
);
554 AfterControlSet
.Length
-= sizeof(RegistryMachineSystem
) - sizeof(UNICODE_NULL
);
556 /* Check if path contains CURRENTCONTROLSET */
557 if (AfterControlSet
.Length
> sizeof(CurrentControlSet
) &&
558 0 == _wcsnicmp(AfterControlSet
.Buffer
, CurrentControlSet
, wcslen(CurrentControlSet
)))
560 AfterControlSet
.Buffer
+= wcslen(CurrentControlSet
);
561 AfterControlSet
.Length
-= sizeof(CurrentControlSet
) - sizeof(UNICODE_NULL
);
563 /* Check if path contains CONTROLSETnum */
564 else if (AfterControlSet
.Length
> sizeof(ControlSet
) &&
565 0 == _wcsnicmp(AfterControlSet
.Buffer
, ControlSet
, wcslen(ControlSet
)))
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')
573 AfterControlSet
.Buffer
++;
574 AfterControlSet
.Length
-= sizeof(WCHAR
);
577 Valid
= (AfterControlSet
.Length
> 0 && L
'\\' == *AfterControlSet
.Buffer
);
578 AfterControlSet
.Buffer
++;
579 AfterControlSet
.Length
-= sizeof(WCHAR
);
580 AfterControlSet
.MaximumLength
= AfterControlSet
.Length
;
590 DeviceRegistryPath
->MaximumLength
= DriverRegistryPath
->Length
+ sizeof(Insert1
) + sizeof(Insert2
);
591 DeviceRegistryPath
->Buffer
= ExAllocatePoolWithTag(PagedPool
,
592 DeviceRegistryPath
->MaximumLength
,
594 if (DeviceRegistryPath
->Buffer
!= NULL
)
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
);
605 /* Check if registry key exists */
606 Valid
= NT_SUCCESS(RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE
, DeviceRegistryPath
->Buffer
));
609 ExFreePoolWithTag(DeviceRegistryPath
->Buffer
, TAG_VIDEO_PORT
);
618 WARN_(VIDEOPRT
, "Unparsable registry path %wZ\n", DriverRegistryPath
);
621 /* If path doesn't point to *ControlSet*, use DriverRegistryPath directly */
624 DeviceRegistryPath
->MaximumLength
= DriverRegistryPath
->Length
+ sizeof(Insert2
);
625 DeviceRegistryPath
->Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
626 DeviceRegistryPath
->MaximumLength
,
629 if (!DeviceRegistryPath
->Buffer
)
630 return STATUS_NO_MEMORY
;
632 RtlCopyUnicodeString(DeviceRegistryPath
, DriverRegistryPath
);
633 RtlAppendUnicodeToString(DeviceRegistryPath
, Insert2
);
636 DbgPrint("Formatted registry key '%wZ' -> '%wZ'\n",
637 DriverRegistryPath
, DeviceRegistryPath
);
639 return STATUS_SUCCESS
;