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
23 #include <ndk/obfuncs.h>
31 _In_ HANDLE SourceKeyHandle
,
32 _In_ HANDLE DestKeyHandle
)
35 PKEY_BASIC_INFORMATION KeyInformation
;
36 PKEY_VALUE_FULL_INFORMATION KeyValueInformation
;
37 OBJECT_ATTRIBUTES ObjectAttributes
;
38 ULONG Index
, InformationLength
, RequiredLength
;
39 UNICODE_STRING NameString
;
41 HANDLE SourceSubKeyHandle
, DestSubKeyHandle
;
43 /* Start with no buffer, set initial size */
45 InformationLength
= 256;
47 /* Start looping with key index 0 */
51 /* Check if we have no buffer */
52 if (InfoBuffer
== NULL
)
54 /* Allocate a new buffer */
55 InfoBuffer
= ExAllocatePoolWithTag(PagedPool
,
57 TAG_VIDEO_PORT_BUFFER
);
58 if (InfoBuffer
== NULL
)
60 ERR_(VIDEOPRT
, "Could not allocate buffer for key info\n");
61 return STATUS_INSUFFICIENT_RESOURCES
;
65 /* Enumerate the next sub-key */
66 KeyInformation
= InfoBuffer
;
67 Status
= ZwEnumerateKey(SourceKeyHandle
,
73 if ((Status
== STATUS_BUFFER_OVERFLOW
) ||
74 (Status
== STATUS_BUFFER_TOO_SMALL
))
76 /* Free the buffer and remember the required size */
77 ExFreePoolWithTag(InfoBuffer
, TAG_VIDEO_PORT_BUFFER
);
79 InformationLength
= RequiredLength
;
84 else if (Status
== STATUS_NO_MORE_ENTRIES
)
86 /* We are done with the sub-keys */
89 else if (!NT_SUCCESS(Status
))
91 ERR_(VIDEOPRT
, "ZwEnumerateKey failed, status 0x%lx\n", Status
);
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
;
100 /* Initialize object attributes and open the source sub-key */
101 InitializeObjectAttributes(&ObjectAttributes
,
103 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
106 Status
= ZwOpenKey(&SourceSubKeyHandle
, KEY_READ
, &ObjectAttributes
);
107 if (!NT_SUCCESS(Status
))
109 ERR_(VIDEOPRT
, "failed to open the source key.\n");
113 /* Initialize object attributes and create the dest sub-key */
114 InitializeObjectAttributes(&ObjectAttributes
,
116 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
119 Status
= ZwCreateKey(&DestSubKeyHandle
,
124 REG_OPTION_NON_VOLATILE
,
126 if (!NT_SUCCESS(Status
))
128 ERR_(VIDEOPRT
, "failed to create the destination key.\n");
129 ObCloseHandle(SourceSubKeyHandle
, KernelMode
);
133 /* Recursively copy the sub-key */
134 Status
= IntCopyRegistryKey(SourceSubKeyHandle
, DestSubKeyHandle
);
135 if (!NT_SUCCESS(Status
))
137 /* Just warn, but continue with the remaining sub-keys */
138 WARN_(VIDEOPRT
, "failed to copy subkey '%wZ'.\n", &NameString
);
141 /* Close the sub-key handles */
142 ObCloseHandle(SourceSubKeyHandle
, KernelMode
);
143 ObCloseHandle(DestSubKeyHandle
, KernelMode
);
149 /* Start looping with value index 0 */
153 /* Check if we have no buffer */
154 if (InfoBuffer
== NULL
)
156 /* Allocate a new buffer */
157 InfoBuffer
= ExAllocatePoolWithTag(PagedPool
,
159 TAG_VIDEO_PORT_BUFFER
);
160 if (InfoBuffer
== NULL
)
162 ERR_(VIDEOPRT
, "Could not allocate buffer for key values\n");
167 /* Enumerate the next value */
168 KeyValueInformation
= InfoBuffer
;
169 Status
= ZwEnumerateValueKey(SourceKeyHandle
,
171 KeyValueFullInformation
,
175 if ((Status
== STATUS_BUFFER_OVERFLOW
) ||
176 (Status
== STATUS_BUFFER_TOO_SMALL
))
178 /* Free the buffer and remember the required size */
179 ExFreePoolWithTag(InfoBuffer
, TAG_VIDEO_PORT_BUFFER
);
181 InformationLength
= RequiredLength
;
186 else if (Status
== STATUS_NO_MORE_ENTRIES
)
188 /* We are done with the values */
189 Status
= STATUS_SUCCESS
;
192 else if (!NT_SUCCESS(Status
))
194 ERR_(VIDEOPRT
, "ZwEnumerateValueKey failed, status 0x%lx\n", Status
);
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
;
203 /* Create the key value in the destination key */
204 Status
= ZwSetValueKey(DestKeyHandle
,
206 KeyValueInformation
->TitleIndex
,
207 KeyValueInformation
->Type
,
208 (PUCHAR
)KeyValueInformation
+ KeyValueInformation
->DataOffset
,
209 KeyValueInformation
->DataLength
);
210 if (!NT_SUCCESS(Status
))
212 /* Just warn, but continue with the remaining sub-keys */
213 WARN_(VIDEOPRT
, "failed to set value '%wZ'.\n", &NameString
);
221 /* Free the buffer and return the failure code */
222 if (InfoBuffer
!= NULL
)
223 ExFreePoolWithTag(InfoBuffer
, TAG_VIDEO_PORT_BUFFER
);
229 IntCopyRegistryValue(
230 HANDLE SourceKeyHandle
,
231 HANDLE DestKeyHandle
,
234 PKEY_VALUE_PARTIAL_INFORMATION ValueInformation
;
235 UNICODE_STRING ValueNameString
;
239 RtlInitUnicodeString(&ValueNameString
, ValueName
);
241 /* Query the value length */
242 Status
= ZwQueryValueKey(SourceKeyHandle
,
244 KeyValuePartialInformation
,
248 if ((Status
!= STATUS_BUFFER_OVERFLOW
) &&
249 (Status
!= STATUS_BUFFER_TOO_SMALL
))
251 /* The key seems not present */
252 NT_ASSERT(!NT_SUCCESS(Status
));
256 /* Allocate a buffer */
257 ValueInformation
= ExAllocatePoolWithTag(PagedPool
, Length
, TAG_VIDEO_PORT_BUFFER
);
258 if (ValueInformation
== NULL
)
263 /* Query the value */
264 Status
= ZwQueryValueKey(SourceKeyHandle
,
266 KeyValuePartialInformation
,
270 if (!NT_SUCCESS(Status
))
272 ExFreePoolWithTag(ValueInformation
, TAG_VIDEO_PORT_BUFFER
);
276 /* Write the registry value */
277 Status
= ZwSetValueKey(DestKeyHandle
,
279 ValueInformation
->TitleIndex
,
280 ValueInformation
->Type
,
281 ValueInformation
->Data
,
282 ValueInformation
->DataLength
);
284 ExFreePoolWithTag(ValueInformation
, TAG_VIDEO_PORT_BUFFER
);
286 if (!NT_SUCCESS(Status
))
288 ERR_(VIDEOPRT
, "ZwSetValueKey failed: status 0x%lx\n", Status
);
296 IntSetupDeviceSettingsKey(
297 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
)
299 static UNICODE_STRING SettingsKeyName
= RTL_CONSTANT_STRING(L
"Settings");
300 HANDLE DevInstRegKey
, SourceKeyHandle
, DestKeyHandle
;
301 OBJECT_ATTRIBUTES ObjectAttributes
;
304 /* Open the software key: HKLM\System\CurrentControlSet\Control\Class\<ClassGUID>\<n> */
305 Status
= IoOpenDeviceRegistryKey(DeviceExtension
->PhysicalDeviceObject
,
306 PLUGPLAY_REGKEY_DRIVER
,
309 if (Status
!= STATUS_SUCCESS
)
311 ERR_(VIDEOPRT
, "Failed to open device software key. Status 0x%lx\n", Status
);
315 /* Open the 'Settings' sub-key */
316 InitializeObjectAttributes(&ObjectAttributes
,
318 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
321 Status
= ZwOpenKey(&DestKeyHandle
, KEY_WRITE
, &ObjectAttributes
);
323 /* Close the device software key */
324 ObCloseHandle(DevInstRegKey
, KernelMode
);
326 if (Status
!= STATUS_SUCCESS
)
328 ERR_(VIDEOPRT
, "Failed to open settings key. Status 0x%lx\n", Status
);
332 /* Open the device profile key */
333 InitializeObjectAttributes(&ObjectAttributes
,
334 &DeviceExtension
->RegistryPath
,
335 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
338 Status
= ZwOpenKey(&SourceKeyHandle
, KEY_WRITE
, &ObjectAttributes
);
339 if (Status
!= STATUS_SUCCESS
)
341 ERR_(VIDEOPRT
, "ZwOpenKey failed for settings key: status 0x%lx\n", Status
);
342 ObCloseHandle(DestKeyHandle
, KernelMode
);
346 IntCopyRegistryValue(SourceKeyHandle
, DestKeyHandle
, L
"InstalledDisplayDrivers");
347 IntCopyRegistryValue(SourceKeyHandle
, DestKeyHandle
, L
"Attach.ToDesktop");
349 ObCloseHandle(SourceKeyHandle
, KernelMode
);
350 ObCloseHandle(DestKeyHandle
, KernelMode
);
352 return STATUS_SUCCESS
;
357 IntCreateNewRegistryPath(
358 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
)
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
;
367 PKEY_VALUE_PARTIAL_INFORMATION ValueInformation
;
371 OBJECT_ATTRIBUTES ObjectAttributes
;
373 /* Open the hardware key: HKLM\System\CurrentControlSet\Enum\... */
374 Status
= IoOpenDeviceRegistryKey(DeviceExtension
->PhysicalDeviceObject
,
375 PLUGPLAY_REGKEY_DEVICE
,
378 if (Status
!= STATUS_SUCCESS
)
380 ERR_(VIDEOPRT
, "IoOpenDeviceRegistryKey failed: status 0x%lx\n", Status
);
384 /* Query the VideoId value */
385 ValueInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)VideoIdBuffer
;
386 Status
= ZwQueryValueKey(DevInstRegKey
,
388 KeyValuePartialInformation
,
390 sizeof(VideoIdBuffer
),
392 if (!NT_SUCCESS(Status
))
394 /* Create a new video Id */
395 Status
= ExUuidCreate(&VideoId
);
396 if (!NT_SUCCESS(Status
))
398 ERR_(VIDEOPRT
, "ExUuidCreate failed: status 0x%lx\n", Status
);
399 ObCloseHandle(DevInstRegKey
, KernelMode
);
403 /* Convert the GUID into a string */
404 Status
= RtlStringFromGUID(&VideoId
, &VideoIdString
);
405 if (!NT_SUCCESS(Status
))
407 ERR_(VIDEOPRT
, "RtlStringFromGUID failed: status 0x%lx\n", Status
);
408 ObCloseHandle(DevInstRegKey
, KernelMode
);
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
);
418 /* Free the GUID string */
419 RtlFreeUnicodeString(&VideoIdString
);
421 /* Write the VideoId registry value */
422 Status
= ZwSetValueKey(DevInstRegKey
,
426 ValueInformation
->Data
,
427 ValueInformation
->DataLength
);
428 if (!NT_SUCCESS(Status
))
430 ERR_(VIDEOPRT
, "ZwSetValueKey failed: status 0x%lx\n", Status
);
431 ObCloseHandle(DevInstRegKey
, KernelMode
);
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
;
441 /* Close the hardware key */
442 ObCloseHandle(DevInstRegKey
, KernelMode
);
444 /* Calculate the size needed for the new registry path name */
445 KeyMaxLength
= ControlVideoPathName
.Length
+
446 VideoIdString
.Length
+
449 /* Allocate the path name buffer */
450 DeviceExtension
->NewRegistryPath
.Length
= 0;
451 DeviceExtension
->NewRegistryPath
.MaximumLength
= KeyMaxLength
;
452 DeviceExtension
->NewRegistryPath
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
455 if (DeviceExtension
->NewRegistryPath
.Buffer
== NULL
)
457 ERR_(VIDEOPRT
, "Failed to allocate key name buffer.\n");
458 return STATUS_INSUFFICIENT_RESOURCES
;
461 /* Copy the root key name and append the VideoId string */
462 RtlCopyUnicodeString(&DeviceExtension
->NewRegistryPath
,
463 &ControlVideoPathName
);
464 RtlAppendUnicodeStringToString(&DeviceExtension
->NewRegistryPath
,
467 /* Check if we have the key already */
468 Status
= RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE
,
469 DeviceExtension
->NewRegistryPath
.Buffer
);
470 if (Status
!= STATUS_SUCCESS
)
472 /* Try to create the new key */
473 Status
= RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE
,
474 DeviceExtension
->NewRegistryPath
.Buffer
);
477 /* Append a the instance path */ /// \todo HACK
478 RtlAppendUnicodeToString(&DeviceExtension
->NewRegistryPath
, L
"\\");
479 RtlAppendUnicodeToString(&DeviceExtension
->NewRegistryPath
, L
"0000");
481 /* Check this key again */
482 Status
= RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE
,
483 DeviceExtension
->NewRegistryPath
.Buffer
);
484 if (Status
!= STATUS_SUCCESS
)
486 /* Try to create the new key */
487 Status
= RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE
,
488 DeviceExtension
->NewRegistryPath
.Buffer
);
489 if (!NT_SUCCESS(Status
))
491 ERR_(VIDEOPRT
, "Failed create key '%wZ'\n", &DeviceExtension
->NewRegistryPath
);
495 /* Open the new key */
496 InitializeObjectAttributes(&ObjectAttributes
,
497 &DeviceExtension
->NewRegistryPath
,
498 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
501 Status
= ZwOpenKey(&NewKey
, KEY_READ
, &ObjectAttributes
);
502 if (!NT_SUCCESS(Status
))
504 ERR_(VIDEOPRT
, "Failed to open settings key. Status 0x%lx\n", Status
);
508 /* Open the device profile key */
509 InitializeObjectAttributes(&ObjectAttributes
,
510 &DeviceExtension
->RegistryPath
,
511 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
514 Status
= ZwOpenKey(&SettingsKey
, KEY_READ
, &ObjectAttributes
);
515 if (!NT_SUCCESS(Status
))
517 ERR_(VIDEOPRT
, "Failed to open settings key. Status 0x%lx\n", Status
);
518 ObCloseHandle(NewKey
, KernelMode
);
522 /* Copy the registry data from the legacy key */
523 Status
= IntCopyRegistryKey(SettingsKey
, NewKey
);
532 IntCreateRegistryPath(
533 IN PCUNICODE_STRING DriverRegistryPath
,
534 OUT PUNICODE_STRING DeviceRegistryPath
)
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";
542 UNICODE_STRING AfterControlSet
;
544 AfterControlSet
= *DriverRegistryPath
;
546 /* Check if path begins with \\REGISTRY\\MACHINE\\SYSTEM\\ */
547 Valid
= (DriverRegistryPath
->Length
> sizeof(RegistryMachineSystem
) &&
548 0 == _wcsnicmp(DriverRegistryPath
->Buffer
, RegistryMachineSystem
,
549 wcslen(RegistryMachineSystem
)));
552 AfterControlSet
.Buffer
+= wcslen(RegistryMachineSystem
);
553 AfterControlSet
.Length
-= sizeof(RegistryMachineSystem
) - sizeof(UNICODE_NULL
);
555 /* Check if path contains CURRENTCONTROLSET */
556 if (AfterControlSet
.Length
> sizeof(CurrentControlSet
) &&
557 0 == _wcsnicmp(AfterControlSet
.Buffer
, CurrentControlSet
, wcslen(CurrentControlSet
)))
559 AfterControlSet
.Buffer
+= wcslen(CurrentControlSet
);
560 AfterControlSet
.Length
-= sizeof(CurrentControlSet
) - sizeof(UNICODE_NULL
);
562 /* Check if path contains CONTROLSETnum */
563 else if (AfterControlSet
.Length
> sizeof(ControlSet
) &&
564 0 == _wcsnicmp(AfterControlSet
.Buffer
, ControlSet
, wcslen(ControlSet
)))
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')
572 AfterControlSet
.Buffer
++;
573 AfterControlSet
.Length
-= sizeof(WCHAR
);
576 Valid
= (AfterControlSet
.Length
> 0 && L
'\\' == *AfterControlSet
.Buffer
);
577 AfterControlSet
.Buffer
++;
578 AfterControlSet
.Length
-= sizeof(WCHAR
);
579 AfterControlSet
.MaximumLength
= AfterControlSet
.Length
;
589 DeviceRegistryPath
->MaximumLength
= DriverRegistryPath
->Length
+ sizeof(Insert1
) + sizeof(Insert2
);
590 DeviceRegistryPath
->Buffer
= ExAllocatePoolWithTag(PagedPool
,
591 DeviceRegistryPath
->MaximumLength
,
593 if (DeviceRegistryPath
->Buffer
!= NULL
)
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
);
604 /* Check if registry key exists */
605 Valid
= NT_SUCCESS(RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE
, DeviceRegistryPath
->Buffer
));
608 ExFreePoolWithTag(DeviceRegistryPath
->Buffer
, TAG_VIDEO_PORT
);
617 WARN_(VIDEOPRT
, "Unparsable registry path %wZ\n", DriverRegistryPath
);
620 /* If path doesn't point to *ControlSet*, use DriverRegistryPath directly */
623 DeviceRegistryPath
->MaximumLength
= DriverRegistryPath
->Length
+ sizeof(Insert2
);
624 DeviceRegistryPath
->Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
625 DeviceRegistryPath
->MaximumLength
,
628 if (!DeviceRegistryPath
->Buffer
)
629 return STATUS_NO_MEMORY
;
631 RtlCopyUnicodeString(DeviceRegistryPath
, DriverRegistryPath
);
632 RtlAppendUnicodeToString(DeviceRegistryPath
, Insert2
);
635 DPRINT("Formatted registry key '%wZ' -> '%wZ'\n",
636 DriverRegistryPath
, DeviceRegistryPath
);
638 return STATUS_SUCCESS
;