2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/cm/ntfunc.c
5 * PURPOSE: Ntxxx function for registry access
9 /* INCLUDES *****************************************************************/
11 #define NTOS_MODE_KERNEL
15 #include <internal/ob.h>
16 #include <internal/se.h>
19 #include <internal/debug.h>
24 /* GLOBALS ******************************************************************/
26 extern POBJECT_TYPE CmiKeyType
;
27 extern PREGISTRY_HIVE CmiVolatileHive
;
29 static BOOLEAN CmiRegistryInitialized
= FALSE
;
32 /* FUNCTIONS ****************************************************************/
35 NtCreateKey(OUT PHANDLE KeyHandle
,
36 IN ACCESS_MASK DesiredAccess
,
37 IN POBJECT_ATTRIBUTES ObjectAttributes
,
39 IN PUNICODE_STRING Class
,
40 IN ULONG CreateOptions
,
41 OUT PULONG Disposition
)
43 UNICODE_STRING RemainingPath
;
44 PKEY_OBJECT KeyObject
;
50 DPRINT("NtCreateKey (Name %wZ KeyHandle %x Root %x)\n",
51 ObjectAttributes
->ObjectName
,
53 ObjectAttributes
->RootDirectory
);
55 Status
= ObFindObject(ObjectAttributes
,
59 if (!NT_SUCCESS(Status
))
64 DPRINT("RemainingPath %wZ\n", &RemainingPath
);
66 if ((RemainingPath
.Buffer
== NULL
) || (RemainingPath
.Buffer
[0] == 0))
68 /* Fail if the key has been deleted */
69 if (((PKEY_OBJECT
) Object
)->Flags
& KO_MARKED_FOR_DELETE
)
71 ObDereferenceObject(Object
);
72 RtlFreeUnicodeString(&RemainingPath
);
73 return(STATUS_UNSUCCESSFUL
);
77 *Disposition
= REG_OPENED_EXISTING_KEY
;
79 Status
= ObCreateHandle(PsGetCurrentProcess(),
85 DPRINT("Status %x\n", Status
);
86 ObDereferenceObject(Object
);
87 RtlFreeUnicodeString(&RemainingPath
);
91 /* If RemainingPath contains \ we must return error
92 because NtCreateKey don't create trees */
93 Start
= RemainingPath
.Buffer
;
97 End
= wcschr(Start
, L
'\\');
100 ObDereferenceObject(Object
);
101 RtlFreeUnicodeString(&RemainingPath
);
102 return STATUS_OBJECT_NAME_NOT_FOUND
;
105 DPRINT("RemainingPath %S ParentObject %x\n", RemainingPath
.Buffer
, Object
);
107 Status
= ObCreateObject(ExGetPreviousMode(),
116 if (!NT_SUCCESS(Status
))
121 Status
= ObInsertObject((PVOID
)KeyObject
,
127 if (!NT_SUCCESS(Status
))
129 ObDereferenceObject(KeyObject
);
130 RtlFreeUnicodeString(&RemainingPath
);
134 KeyObject
->ParentKey
= Object
;
136 if (CreateOptions
& REG_OPTION_VOLATILE
)
137 KeyObject
->RegistryHive
= CmiVolatileHive
;
139 KeyObject
->RegistryHive
= KeyObject
->ParentKey
->RegistryHive
;
141 KeyObject
->Flags
= 0;
142 KeyObject
->NumberOfSubKeys
= 0;
143 KeyObject
->SizeOfSubKeys
= 0;
144 KeyObject
->SubKeys
= NULL
;
146 /* Acquire hive lock */
147 KeEnterCriticalRegion();
148 ExAcquireResourceExclusiveLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
150 /* add key to subkeys of parent if needed */
151 Status
= CmiAddSubKey(KeyObject
->RegistryHive
,
152 KeyObject
->ParentKey
,
158 if (!NT_SUCCESS(Status
))
160 DPRINT("CmiAddSubKey() failed (Status %lx)\n", Status
);
161 /* Release hive lock */
162 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
163 KeLeaveCriticalRegion();
164 ObDereferenceObject(KeyObject
);
165 ObDereferenceObject(Object
);
166 RtlFreeUnicodeString(&RemainingPath
);
167 return STATUS_UNSUCCESSFUL
;
170 if (Start
== RemainingPath
.Buffer
)
172 KeyObject
->Name
= RemainingPath
;
176 RtlCreateUnicodeString(&KeyObject
->Name
,
178 RtlFreeUnicodeString(&RemainingPath
);
181 if (KeyObject
->RegistryHive
== KeyObject
->ParentKey
->RegistryHive
)
183 KeyObject
->KeyCell
->ParentKeyOffset
= KeyObject
->ParentKey
->KeyCellOffset
;
184 KeyObject
->KeyCell
->SecurityKeyOffset
= KeyObject
->ParentKey
->KeyCell
->SecurityKeyOffset
;
188 KeyObject
->KeyCell
->ParentKeyOffset
= -1;
189 KeyObject
->KeyCell
->SecurityKeyOffset
= -1;
190 /* This key must remain in memory unless it is deleted
191 or file is unloaded */
192 ObReferenceObjectByPointer(KeyObject
,
193 STANDARD_RIGHTS_REQUIRED
,
198 CmiAddKeyToList(KeyObject
->ParentKey
, KeyObject
);
200 VERIFY_KEY_OBJECT(KeyObject
);
202 /* Release hive lock */
203 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
204 KeLeaveCriticalRegion();
206 ObDereferenceObject(KeyObject
);
207 ObDereferenceObject(Object
);
210 *Disposition
= REG_CREATED_NEW_KEY
;
219 NtDeleteKey(IN HANDLE KeyHandle
)
221 PKEY_OBJECT KeyObject
;
224 DPRINT("KeyHandle %x\n", KeyHandle
);
226 /* Verify that the handle is valid and is a registry key */
227 Status
= ObReferenceObjectByHandle(KeyHandle
,
233 if (!NT_SUCCESS(Status
))
238 /* Acquire hive lock */
239 KeEnterCriticalRegion();
240 ExAcquireResourceExclusiveLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
242 VERIFY_KEY_OBJECT(KeyObject
);
244 /* Check for subkeys */
245 if (KeyObject
->NumberOfSubKeys
!= 0)
247 Status
= STATUS_CANNOT_DELETE
;
251 /* Set the marked for delete bit in the key object */
252 KeyObject
->Flags
|= KO_MARKED_FOR_DELETE
;
253 Status
= STATUS_SUCCESS
;
256 /* Release hive lock */
257 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
258 KeLeaveCriticalRegion();
260 DPRINT("PointerCount %lu\n", ObGetObjectPointerCount((PVOID
)KeyObject
));
262 /* Dereference the object */
263 ObDereferenceObject(KeyObject
);
264 if(KeyObject
->RegistryHive
!= KeyObject
->ParentKey
->RegistryHive
)
265 ObDereferenceObject(KeyObject
);
267 DPRINT("PointerCount %lu\n", ObGetObjectPointerCount((PVOID
)KeyObject
));
271 * Hive-Synchronization will not be triggered here. This is done in
272 * CmiObjectDelete() (in regobj.c) after all key-related structures
273 * have been released.
281 NtEnumerateKey(IN HANDLE KeyHandle
,
283 IN KEY_INFORMATION_CLASS KeyInformationClass
,
284 OUT PVOID KeyInformation
,
286 OUT PULONG ResultLength
)
288 PKEY_OBJECT KeyObject
;
289 PKEY_OBJECT SubKeyObject
;
290 PREGISTRY_HIVE RegistryHive
;
291 PKEY_CELL KeyCell
, SubKeyCell
;
292 PHASH_TABLE_CELL HashTableBlock
;
293 PKEY_BASIC_INFORMATION BasicInformation
;
294 PKEY_NODE_INFORMATION NodeInformation
;
295 PKEY_FULL_INFORMATION FullInformation
;
296 PDATA_CELL ClassCell
;
300 DPRINT("KH %x I %d KIC %x KI %x L %d RL %x\n",
308 /* Verify that the handle is valid and is a registry key */
309 Status
= ObReferenceObjectByHandle(KeyHandle
,
310 KEY_ENUMERATE_SUB_KEYS
,
313 (PVOID
*) &KeyObject
,
315 if (!NT_SUCCESS(Status
))
317 DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status
);
321 /* Acquire hive lock */
322 KeEnterCriticalRegion();
323 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
325 VERIFY_KEY_OBJECT(KeyObject
);
327 /* Get pointer to KeyCell */
328 KeyCell
= KeyObject
->KeyCell
;
329 RegistryHive
= KeyObject
->RegistryHive
;
333 /* Check for hightest possible sub key index */
334 if (Index
>= KeyCell
->NumberOfSubKeys
+ KeyObject
->NumberOfSubKeys
)
336 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
337 KeLeaveCriticalRegion();
338 ObDereferenceObject(KeyObject
);
339 DPRINT("No more volatile entries\n");
340 return STATUS_NO_MORE_ENTRIES
;
343 /* Get pointer to SubKey */
344 if (Index
>= KeyCell
->NumberOfSubKeys
)
346 PKEY_OBJECT CurKey
= NULL
;
350 /* Search for volatile or 'foreign' keys */
351 j
= KeyCell
->NumberOfSubKeys
;
352 for (i
= 0; i
< KeyObject
->NumberOfSubKeys
; i
++)
354 CurKey
= KeyObject
->SubKeys
[i
];
355 if (CurKey
->RegistryHive
== CmiVolatileHive
||
356 CurKey
->RegistryHive
!= RegistryHive
)
364 if (i
>= KeyObject
->NumberOfSubKeys
)
366 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
367 KeLeaveCriticalRegion();
368 ObDereferenceObject(KeyObject
);
369 DPRINT("No more non-volatile entries\n");
370 return STATUS_NO_MORE_ENTRIES
;
373 SubKeyObject
= CurKey
;
374 SubKeyCell
= CurKey
->KeyCell
;
378 if (KeyCell
->HashTableOffset
== (BLOCK_OFFSET
)-1)
380 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
381 KeLeaveCriticalRegion();
382 ObDereferenceObject(KeyObject
);
383 return STATUS_NO_MORE_ENTRIES
;
386 HashTableBlock
= CmiGetCell (RegistryHive
, KeyCell
->HashTableOffset
, NULL
);
387 if (HashTableBlock
== NULL
)
389 DPRINT("CmiGetBlock() failed\n");
390 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
391 KeLeaveCriticalRegion();
392 ObDereferenceObject(KeyObject
);
393 return STATUS_UNSUCCESSFUL
;
396 SubKeyCell
= CmiGetKeyFromHashByIndex(RegistryHive
,
401 if (SubKeyCell
== NULL
)
403 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
404 KeLeaveCriticalRegion();
405 ObDereferenceObject(KeyObject
);
406 DPRINT("No more entries\n");
407 return(STATUS_NO_MORE_ENTRIES
);
410 Status
= STATUS_SUCCESS
;
411 switch (KeyInformationClass
)
413 case KeyBasicInformation
:
414 /* Check size of buffer */
415 NameSize
= SubKeyCell
->NameSize
;
416 if (SubKeyCell
->Flags
& REG_KEY_NAME_PACKED
)
418 NameSize
*= sizeof(WCHAR
);
420 *ResultLength
= sizeof(KEY_BASIC_INFORMATION
) + NameSize
;
422 if (Length
< *ResultLength
)
424 Status
= STATUS_BUFFER_OVERFLOW
;
428 /* Fill buffer with requested info */
429 BasicInformation
= (PKEY_BASIC_INFORMATION
) KeyInformation
;
430 BasicInformation
->LastWriteTime
.u
.LowPart
= SubKeyCell
->LastWriteTime
.u
.LowPart
;
431 BasicInformation
->LastWriteTime
.u
.HighPart
= SubKeyCell
->LastWriteTime
.u
.HighPart
;
432 BasicInformation
->TitleIndex
= Index
;
433 BasicInformation
->NameLength
= NameSize
;
435 if (SubKeyObject
!= NULL
)
437 BasicInformation
->NameLength
= SubKeyObject
->Name
.Length
;
438 RtlCopyMemory(BasicInformation
->Name
,
439 SubKeyObject
->Name
.Buffer
,
440 SubKeyObject
->Name
.Length
);
444 BasicInformation
->NameLength
= NameSize
;
445 if (SubKeyCell
->Flags
& REG_KEY_NAME_PACKED
)
447 CmiCopyPackedName(BasicInformation
->Name
,
449 SubKeyCell
->NameSize
);
453 RtlCopyMemory(BasicInformation
->Name
,
455 SubKeyCell
->NameSize
);
461 case KeyNodeInformation
:
462 /* Check size of buffer */
463 if (SubKeyCell
->Flags
& REG_KEY_NAME_PACKED
)
465 NameSize
= SubKeyCell
->NameSize
* sizeof(WCHAR
);
469 NameSize
= SubKeyCell
->NameSize
;
471 *ResultLength
= sizeof(KEY_NODE_INFORMATION
) +
472 NameSize
+ SubKeyCell
->ClassSize
;
474 if (Length
< *ResultLength
)
476 Status
= STATUS_BUFFER_OVERFLOW
;
480 /* Fill buffer with requested info */
481 NodeInformation
= (PKEY_NODE_INFORMATION
) KeyInformation
;
482 NodeInformation
->LastWriteTime
.u
.LowPart
= SubKeyCell
->LastWriteTime
.u
.LowPart
;
483 NodeInformation
->LastWriteTime
.u
.HighPart
= SubKeyCell
->LastWriteTime
.u
.HighPart
;
484 NodeInformation
->TitleIndex
= Index
;
485 NodeInformation
->ClassOffset
= sizeof(KEY_NODE_INFORMATION
) + NameSize
;
486 NodeInformation
->ClassLength
= SubKeyCell
->ClassSize
;
488 if (SubKeyObject
!= NULL
)
490 NodeInformation
->NameLength
= SubKeyObject
->Name
.Length
;
491 RtlCopyMemory(NodeInformation
->Name
,
492 SubKeyObject
->Name
.Buffer
,
493 SubKeyObject
->Name
.Length
);
497 NodeInformation
->NameLength
= NameSize
;
498 if (SubKeyCell
->Flags
& REG_KEY_NAME_PACKED
)
500 CmiCopyPackedName(NodeInformation
->Name
,
502 SubKeyCell
->NameSize
);
506 RtlCopyMemory(NodeInformation
->Name
,
508 SubKeyCell
->NameSize
);
512 if (SubKeyCell
->ClassSize
!= 0)
514 ClassCell
= CmiGetCell (KeyObject
->RegistryHive
,
515 SubKeyCell
->ClassNameOffset
,
517 RtlCopyMemory (NodeInformation
->Name
+ SubKeyCell
->NameSize
,
519 SubKeyCell
->ClassSize
);
524 case KeyFullInformation
:
525 /* Check size of buffer */
526 *ResultLength
= sizeof(KEY_FULL_INFORMATION
) +
527 SubKeyCell
->ClassSize
;
529 if (Length
< *ResultLength
)
531 Status
= STATUS_BUFFER_OVERFLOW
;
535 /* Fill buffer with requested info */
536 FullInformation
= (PKEY_FULL_INFORMATION
) KeyInformation
;
537 FullInformation
->LastWriteTime
.u
.LowPart
= SubKeyCell
->LastWriteTime
.u
.LowPart
;
538 FullInformation
->LastWriteTime
.u
.HighPart
= SubKeyCell
->LastWriteTime
.u
.HighPart
;
539 FullInformation
->TitleIndex
= Index
;
540 FullInformation
->ClassOffset
= sizeof(KEY_FULL_INFORMATION
) -
542 FullInformation
->ClassLength
= SubKeyCell
->ClassSize
;
543 FullInformation
->SubKeys
= CmiGetNumberOfSubKeys(KeyObject
); //SubKeyCell->NumberOfSubKeys;
544 FullInformation
->MaxNameLen
= CmiGetMaxNameLength(KeyObject
);
545 FullInformation
->MaxClassLen
= CmiGetMaxClassLength(KeyObject
);
546 FullInformation
->Values
= SubKeyCell
->NumberOfValues
;
547 FullInformation
->MaxValueNameLen
=
548 CmiGetMaxValueNameLength(RegistryHive
, SubKeyCell
);
549 FullInformation
->MaxValueDataLen
=
550 CmiGetMaxValueDataLength(RegistryHive
, SubKeyCell
);
551 if (SubKeyCell
->ClassSize
!= 0)
553 ClassCell
= CmiGetCell (KeyObject
->RegistryHive
,
554 SubKeyCell
->ClassNameOffset
,
556 RtlCopyMemory (FullInformation
->Class
,
558 SubKeyCell
->ClassSize
);
564 DPRINT1("Not handling 0x%x\n", KeyInformationClass
);
568 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
569 KeLeaveCriticalRegion();
570 ObDereferenceObject(KeyObject
);
572 DPRINT("Returning status %x\n", Status
);
579 NtEnumerateValueKey(IN HANDLE KeyHandle
,
581 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
,
582 OUT PVOID KeyValueInformation
,
584 OUT PULONG ResultLength
)
587 PKEY_OBJECT KeyObject
;
588 PREGISTRY_HIVE RegistryHive
;
590 PVALUE_CELL ValueCell
;
593 PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation
;
594 PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation
;
595 PKEY_VALUE_FULL_INFORMATION ValueFullInformation
;
597 DPRINT("KH %x I %d KVIC %x KVI %x L %d RL %x\n",
600 KeyValueInformationClass
,
605 /* Verify that the handle is valid and is a registry key */
606 Status
= ObReferenceObjectByHandle(KeyHandle
,
610 (PVOID
*) &KeyObject
,
613 if (!NT_SUCCESS(Status
))
618 /* Acquire hive lock */
619 KeEnterCriticalRegion();
620 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
622 VERIFY_KEY_OBJECT(KeyObject
);
624 /* Get pointer to KeyCell */
625 KeyCell
= KeyObject
->KeyCell
;
626 RegistryHive
= KeyObject
->RegistryHive
;
628 /* Get Value block of interest */
629 Status
= CmiGetValueFromKeyByIndex(RegistryHive
,
634 if (!NT_SUCCESS(Status
))
636 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
637 KeLeaveCriticalRegion();
638 ObDereferenceObject(KeyObject
);
642 if (ValueCell
!= NULL
)
644 switch (KeyValueInformationClass
)
646 case KeyValueBasicInformation
:
647 NameSize
= ValueCell
->NameSize
;
648 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
650 NameSize
*= sizeof(WCHAR
);
652 *ResultLength
= sizeof(KEY_VALUE_BASIC_INFORMATION
) + NameSize
;
653 if (Length
< *ResultLength
)
655 Status
= STATUS_BUFFER_OVERFLOW
;
659 ValueBasicInformation
= (PKEY_VALUE_BASIC_INFORMATION
)
661 ValueBasicInformation
->TitleIndex
= 0;
662 ValueBasicInformation
->Type
= ValueCell
->DataType
;
663 ValueBasicInformation
->NameLength
= NameSize
;
664 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
666 CmiCopyPackedName(ValueBasicInformation
->Name
,
668 ValueCell
->NameSize
);
672 RtlCopyMemory(ValueBasicInformation
->Name
,
679 case KeyValuePartialInformation
:
680 *ResultLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) +
681 (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
682 if (Length
< *ResultLength
)
684 Status
= STATUS_BUFFER_OVERFLOW
;
688 ValuePartialInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)
690 ValuePartialInformation
->TitleIndex
= 0;
691 ValuePartialInformation
->Type
= ValueCell
->DataType
;
692 ValuePartialInformation
->DataLength
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
693 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
))
695 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
696 RtlCopyMemory(ValuePartialInformation
->Data
,
698 ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
702 RtlCopyMemory(ValuePartialInformation
->Data
,
703 &ValueCell
->DataOffset
,
704 ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
709 case KeyValueFullInformation
:
710 NameSize
= ValueCell
->NameSize
;
711 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
713 NameSize
*= sizeof(WCHAR
);
715 *ResultLength
= sizeof(KEY_VALUE_FULL_INFORMATION
) +
716 NameSize
+ (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
717 if (Length
< *ResultLength
)
719 Status
= STATUS_BUFFER_OVERFLOW
;
723 ValueFullInformation
= (PKEY_VALUE_FULL_INFORMATION
)
725 ValueFullInformation
->TitleIndex
= 0;
726 ValueFullInformation
->Type
= ValueCell
->DataType
;
727 ValueFullInformation
->NameLength
= NameSize
;
728 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
730 CmiCopyPackedName(ValueFullInformation
->Name
,
732 ValueCell
->NameSize
);
736 RtlCopyMemory(ValueFullInformation
->Name
,
738 ValueCell
->NameSize
);
740 ValueFullInformation
->DataOffset
=
741 (ULONG
)ValueFullInformation
->Name
- (ULONG
)ValueFullInformation
+
742 ValueFullInformation
->NameLength
;
743 ValueFullInformation
->DataOffset
=
744 ROUND_UP(ValueFullInformation
->DataOffset
, sizeof(PVOID
));
745 ValueFullInformation
->DataLength
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
746 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
))
748 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
749 RtlCopyMemory((PCHAR
) ValueFullInformation
750 + ValueFullInformation
->DataOffset
,
752 ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
756 RtlCopyMemory((PCHAR
) ValueFullInformation
757 + ValueFullInformation
->DataOffset
,
758 &ValueCell
->DataOffset
,
759 ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
765 DPRINT1("Not handling 0x%x\n", KeyValueInformationClass
);
771 Status
= STATUS_UNSUCCESSFUL
;
774 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
775 KeLeaveCriticalRegion();
776 ObDereferenceObject(KeyObject
);
783 NtFlushKey(IN HANDLE KeyHandle
)
786 PKEY_OBJECT KeyObject
;
787 PREGISTRY_HIVE RegistryHive
;
789 DPRINT("NtFlushKey (KeyHandle %lx) called\n", KeyHandle
);
791 /* Verify that the handle is valid and is a registry key */
792 Status
= ObReferenceObjectByHandle(KeyHandle
,
798 if (!NT_SUCCESS(Status
))
803 VERIFY_KEY_OBJECT(KeyObject
);
805 RegistryHive
= KeyObject
->RegistryHive
;
807 /* Acquire hive lock */
808 KeEnterCriticalRegion();
809 ExAcquireResourceExclusiveLite(&RegistryHive
->HiveResource
,
812 if (IsNoFileHive(RegistryHive
))
814 Status
= STATUS_SUCCESS
;
818 /* Flush non-volatile hive */
819 Status
= CmiFlushRegistryHive(RegistryHive
);
822 ExReleaseResourceLite(&RegistryHive
->HiveResource
);
823 KeLeaveCriticalRegion();
825 ObDereferenceObject(KeyObject
);
827 return STATUS_SUCCESS
;
832 NtOpenKey(OUT PHANDLE KeyHandle
,
833 IN ACCESS_MASK DesiredAccess
,
834 IN POBJECT_ATTRIBUTES ObjectAttributes
)
836 UNICODE_STRING RemainingPath
;
840 DPRINT("NtOpenKey(KH %x DA %x OA %x OA->ON '%wZ'\n",
844 ObjectAttributes
? ObjectAttributes
->ObjectName
: NULL
);
846 RemainingPath
.Buffer
= NULL
;
847 Status
= ObFindObject(ObjectAttributes
,
851 if (!NT_SUCCESS(Status
))
856 VERIFY_KEY_OBJECT((PKEY_OBJECT
) Object
);
858 DPRINT("RemainingPath '%wZ'\n", &RemainingPath
);
860 if ((RemainingPath
.Buffer
!= NULL
) && (RemainingPath
.Buffer
[0] != 0))
862 ObDereferenceObject(Object
);
863 RtlFreeUnicodeString(&RemainingPath
);
864 return STATUS_OBJECT_NAME_NOT_FOUND
;
867 RtlFreeUnicodeString(&RemainingPath
);
869 /* Fail if the key has been deleted */
870 if (((PKEY_OBJECT
)Object
)->Flags
& KO_MARKED_FOR_DELETE
)
872 ObDereferenceObject(Object
);
873 return(STATUS_UNSUCCESSFUL
);
876 Status
= ObCreateHandle(PsGetCurrentProcess(),
881 ObDereferenceObject(Object
);
883 if (!NT_SUCCESS(Status
))
888 return(STATUS_SUCCESS
);
893 NtQueryKey(IN HANDLE KeyHandle
,
894 IN KEY_INFORMATION_CLASS KeyInformationClass
,
895 OUT PVOID KeyInformation
,
897 OUT PULONG ResultLength
)
899 PKEY_BASIC_INFORMATION BasicInformation
;
900 PKEY_NODE_INFORMATION NodeInformation
;
901 PKEY_FULL_INFORMATION FullInformation
;
902 PREGISTRY_HIVE RegistryHive
;
903 PDATA_CELL ClassCell
;
904 PKEY_OBJECT KeyObject
;
908 DPRINT("NtQueryKey(KH %x KIC %x KI %x L %d RL %x)\n",
915 /* Verify that the handle is valid and is a registry key */
916 Status
= ObReferenceObjectByHandle(KeyHandle
,
920 (PVOID
*) &KeyObject
,
922 if (!NT_SUCCESS(Status
))
927 /* Acquire hive lock */
928 KeEnterCriticalRegion();
929 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
931 VERIFY_KEY_OBJECT(KeyObject
);
933 /* Get pointer to KeyCell */
934 KeyCell
= KeyObject
->KeyCell
;
935 RegistryHive
= KeyObject
->RegistryHive
;
937 Status
= STATUS_SUCCESS
;
938 switch (KeyInformationClass
)
940 case KeyBasicInformation
:
941 /* Check size of buffer */
942 *ResultLength
= sizeof(KEY_BASIC_INFORMATION
) +
943 KeyObject
->Name
.Length
;
945 if (Length
< *ResultLength
)
947 Status
= STATUS_BUFFER_OVERFLOW
;
951 /* Fill buffer with requested info */
952 BasicInformation
= (PKEY_BASIC_INFORMATION
) KeyInformation
;
953 BasicInformation
->LastWriteTime
.u
.LowPart
= KeyCell
->LastWriteTime
.u
.LowPart
;
954 BasicInformation
->LastWriteTime
.u
.HighPart
= KeyCell
->LastWriteTime
.u
.HighPart
;
955 BasicInformation
->TitleIndex
= 0;
956 BasicInformation
->NameLength
= KeyObject
->Name
.Length
;
958 RtlCopyMemory(BasicInformation
->Name
,
959 KeyObject
->Name
.Buffer
,
960 KeyObject
->Name
.Length
);
964 case KeyNodeInformation
:
965 /* Check size of buffer */
966 *ResultLength
= sizeof(KEY_NODE_INFORMATION
) +
967 KeyObject
->Name
.Length
+ KeyCell
->ClassSize
;
969 if (Length
< *ResultLength
)
971 Status
= STATUS_BUFFER_OVERFLOW
;
975 /* Fill buffer with requested info */
976 NodeInformation
= (PKEY_NODE_INFORMATION
) KeyInformation
;
977 NodeInformation
->LastWriteTime
.u
.LowPart
= KeyCell
->LastWriteTime
.u
.LowPart
;
978 NodeInformation
->LastWriteTime
.u
.HighPart
= KeyCell
->LastWriteTime
.u
.HighPart
;
979 NodeInformation
->TitleIndex
= 0;
980 NodeInformation
->ClassOffset
= sizeof(KEY_NODE_INFORMATION
) +
981 KeyObject
->Name
.Length
;
982 NodeInformation
->ClassLength
= KeyCell
->ClassSize
;
983 NodeInformation
->NameLength
= KeyObject
->Name
.Length
;
985 RtlCopyMemory(NodeInformation
->Name
,
986 KeyObject
->Name
.Buffer
,
987 KeyObject
->Name
.Length
);
989 if (KeyCell
->ClassSize
!= 0)
991 ClassCell
= CmiGetCell (KeyObject
->RegistryHive
,
992 KeyCell
->ClassNameOffset
,
994 RtlCopyMemory (NodeInformation
->Name
+ KeyObject
->Name
.Length
,
1001 case KeyFullInformation
:
1002 /* Check size of buffer */
1003 *ResultLength
= sizeof(KEY_FULL_INFORMATION
) +
1006 if (Length
< *ResultLength
)
1008 Status
= STATUS_BUFFER_OVERFLOW
;
1012 /* Fill buffer with requested info */
1013 FullInformation
= (PKEY_FULL_INFORMATION
) KeyInformation
;
1014 FullInformation
->LastWriteTime
.u
.LowPart
= KeyCell
->LastWriteTime
.u
.LowPart
;
1015 FullInformation
->LastWriteTime
.u
.HighPart
= KeyCell
->LastWriteTime
.u
.HighPart
;
1016 FullInformation
->TitleIndex
= 0;
1017 FullInformation
->ClassOffset
= sizeof(KEY_FULL_INFORMATION
) - sizeof(WCHAR
);
1018 FullInformation
->ClassLength
= KeyCell
->ClassSize
;
1019 FullInformation
->SubKeys
= CmiGetNumberOfSubKeys(KeyObject
); //KeyCell->NumberOfSubKeys;
1020 FullInformation
->MaxNameLen
= CmiGetMaxNameLength(KeyObject
);
1021 FullInformation
->MaxClassLen
= CmiGetMaxClassLength(KeyObject
);
1022 FullInformation
->Values
= KeyCell
->NumberOfValues
;
1023 FullInformation
->MaxValueNameLen
=
1024 CmiGetMaxValueNameLength(RegistryHive
, KeyCell
);
1025 FullInformation
->MaxValueDataLen
=
1026 CmiGetMaxValueDataLength(RegistryHive
, KeyCell
);
1027 if (KeyCell
->ClassSize
!= 0)
1029 ClassCell
= CmiGetCell (KeyObject
->RegistryHive
,
1030 KeyCell
->ClassNameOffset
,
1032 RtlCopyMemory (FullInformation
->Class
,
1034 KeyCell
->ClassSize
);
1040 DPRINT1("Not handling 0x%x\n", KeyInformationClass
);
1041 Status
= STATUS_INVALID_INFO_CLASS
;
1045 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1046 KeLeaveCriticalRegion();
1047 ObDereferenceObject(KeyObject
);
1054 NtQueryValueKey(IN HANDLE KeyHandle
,
1055 IN PUNICODE_STRING ValueName
,
1056 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
,
1057 OUT PVOID KeyValueInformation
,
1059 OUT PULONG ResultLength
)
1063 PKEY_OBJECT KeyObject
;
1064 PREGISTRY_HIVE RegistryHive
;
1066 PVALUE_CELL ValueCell
;
1067 PDATA_CELL DataCell
;
1068 PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation
;
1069 PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation
;
1070 PKEY_VALUE_FULL_INFORMATION ValueFullInformation
;
1072 DPRINT("NtQueryValueKey(KeyHandle %x ValueName %S Length %x)\n",
1073 KeyHandle
, ValueName
->Buffer
, Length
);
1075 /* Verify that the handle is valid and is a registry key */
1076 Status
= ObReferenceObjectByHandle(KeyHandle
,
1080 (PVOID
*)&KeyObject
,
1083 if (!NT_SUCCESS(Status
))
1085 DPRINT1("ObReferenceObjectByHandle() failed with status %x\n", Status
);
1089 /* Acquire hive lock */
1090 KeEnterCriticalRegion();
1091 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1093 VERIFY_KEY_OBJECT(KeyObject
);
1095 /* Get pointer to KeyCell */
1096 KeyCell
= KeyObject
->KeyCell
;
1097 RegistryHive
= KeyObject
->RegistryHive
;
1099 /* Get value cell by name */
1100 Status
= CmiScanKeyForValue(RegistryHive
,
1105 if (!NT_SUCCESS(Status
))
1107 DPRINT("CmiScanKeyForValue() failed with status %x\n", Status
);
1111 Status
= STATUS_SUCCESS
;
1112 switch (KeyValueInformationClass
)
1114 case KeyValueBasicInformation
:
1115 NameSize
= ValueCell
->NameSize
;
1116 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1118 NameSize
*= sizeof(WCHAR
);
1120 *ResultLength
= sizeof(KEY_VALUE_BASIC_INFORMATION
) + NameSize
;
1121 if (Length
< *ResultLength
)
1123 Status
= STATUS_BUFFER_TOO_SMALL
;
1127 ValueBasicInformation
= (PKEY_VALUE_BASIC_INFORMATION
)
1128 KeyValueInformation
;
1129 ValueBasicInformation
->TitleIndex
= 0;
1130 ValueBasicInformation
->Type
= ValueCell
->DataType
;
1131 ValueBasicInformation
->NameLength
= NameSize
;
1132 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1134 CmiCopyPackedName(ValueBasicInformation
->Name
,
1136 ValueCell
->NameSize
);
1140 RtlCopyMemory(ValueBasicInformation
->Name
,
1142 ValueCell
->NameSize
* sizeof(WCHAR
));
1147 case KeyValuePartialInformation
:
1148 *ResultLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
)
1149 + (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
1150 if (Length
< *ResultLength
)
1152 Status
= STATUS_BUFFER_TOO_SMALL
;
1156 ValuePartialInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)
1157 KeyValueInformation
;
1158 ValuePartialInformation
->TitleIndex
= 0;
1159 ValuePartialInformation
->Type
= ValueCell
->DataType
;
1160 ValuePartialInformation
->DataLength
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
1161 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
))
1163 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
1164 RtlCopyMemory(ValuePartialInformation
->Data
,
1166 ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
1170 RtlCopyMemory(ValuePartialInformation
->Data
,
1171 &ValueCell
->DataOffset
,
1172 ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
1177 case KeyValueFullInformation
:
1178 NameSize
= ValueCell
->NameSize
;
1179 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1181 NameSize
*= sizeof(WCHAR
);
1183 *ResultLength
= sizeof(KEY_VALUE_FULL_INFORMATION
) +
1184 NameSize
+ (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
1185 if (Length
< *ResultLength
)
1187 Status
= STATUS_BUFFER_TOO_SMALL
;
1191 ValueFullInformation
= (PKEY_VALUE_FULL_INFORMATION
)
1192 KeyValueInformation
;
1193 ValueFullInformation
->TitleIndex
= 0;
1194 ValueFullInformation
->Type
= ValueCell
->DataType
;
1195 ValueFullInformation
->NameLength
= NameSize
;
1196 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1198 CmiCopyPackedName(ValueFullInformation
->Name
,
1200 ValueCell
->NameSize
);
1204 RtlCopyMemory(ValueFullInformation
->Name
,
1206 ValueCell
->NameSize
);
1208 ValueFullInformation
->DataOffset
=
1209 (ULONG
)ValueFullInformation
->Name
- (ULONG
)ValueFullInformation
+
1210 ValueFullInformation
->NameLength
;
1211 ValueFullInformation
->DataOffset
=
1212 ROUND_UP(ValueFullInformation
->DataOffset
, sizeof(PVOID
));
1213 ValueFullInformation
->DataLength
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
1214 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
))
1216 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
1217 RtlCopyMemory((PCHAR
) ValueFullInformation
1218 + ValueFullInformation
->DataOffset
,
1220 ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
1224 RtlCopyMemory((PCHAR
) ValueFullInformation
1225 + ValueFullInformation
->DataOffset
,
1226 &ValueCell
->DataOffset
,
1227 ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
1233 DPRINT1("Not handling 0x%x\n", KeyValueInformationClass
);
1234 Status
= STATUS_INVALID_INFO_CLASS
;
1239 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1240 KeLeaveCriticalRegion();
1241 ObDereferenceObject(KeyObject
);
1248 NtSetValueKey(IN HANDLE KeyHandle
,
1249 IN PUNICODE_STRING ValueName
,
1250 IN ULONG TitleIndex
,
1256 PKEY_OBJECT KeyObject
;
1257 PREGISTRY_HIVE RegistryHive
;
1259 PVALUE_CELL ValueCell
;
1260 BLOCK_OFFSET ValueCellOffset
;
1261 PDATA_CELL DataCell
;
1262 PDATA_CELL NewDataCell
;
1264 ULONG DesiredAccess
;
1266 DPRINT("NtSetValueKey(KeyHandle %x ValueName '%wZ' Type %d)\n",
1267 KeyHandle
, ValueName
, Type
);
1269 DesiredAccess
= KEY_SET_VALUE
;
1270 if (Type
== REG_LINK
)
1271 DesiredAccess
|= KEY_CREATE_LINK
;
1273 /* Verify that the handle is valid and is a registry key */
1274 Status
= ObReferenceObjectByHandle(KeyHandle
,
1278 (PVOID
*)&KeyObject
,
1280 if (!NT_SUCCESS(Status
))
1283 /* Acquire hive lock exclucively */
1284 KeEnterCriticalRegion();
1285 ExAcquireResourceExclusiveLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1287 VERIFY_KEY_OBJECT(KeyObject
);
1289 /* Get pointer to key cell */
1290 KeyCell
= KeyObject
->KeyCell
;
1291 RegistryHive
= KeyObject
->RegistryHive
;
1292 Status
= CmiScanKeyForValue(RegistryHive
,
1297 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1299 DPRINT("Allocate new value cell\n");
1300 Status
= CmiAddValueToKey(RegistryHive
,
1302 KeyObject
->KeyCellOffset
,
1308 if (!NT_SUCCESS(Status
))
1310 DPRINT("Cannot add value. Status 0x%X\n", Status
);
1312 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1313 KeLeaveCriticalRegion();
1314 ObDereferenceObject(KeyObject
);
1318 DPRINT("DataSize %lu\n", DataSize
);
1319 DPRINT("ValueCell %p\n", ValueCell
);
1320 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
1322 if (DataSize
<= sizeof(BLOCK_OFFSET
))
1324 /* If data size <= sizeof(BLOCK_OFFSET) then store data in the data offset */
1325 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
1326 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
) &&
1327 (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
) != 0)
1329 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
1330 CmiDestroyCell(RegistryHive
, DataCell
, ValueCell
->DataOffset
);
1333 RtlCopyMemory(&ValueCell
->DataOffset
, Data
, DataSize
);
1334 ValueCell
->DataSize
= DataSize
| REG_DATA_IN_OFFSET
;
1335 ValueCell
->DataType
= Type
;
1336 RtlMoveMemory(&ValueCell
->DataOffset
, Data
, DataSize
);
1337 CmiMarkBlockDirty(RegistryHive
, ValueCellOffset
);
1339 else if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
) &&
1340 (DataSize
<= (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
)))
1342 /* If new data size is <= current then overwrite current data */
1343 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
,&pBin
);
1344 RtlZeroMemory(DataCell
->Data
, ValueCell
->DataSize
);
1345 RtlCopyMemory(DataCell
->Data
, Data
, DataSize
);
1346 ValueCell
->DataSize
= DataSize
;
1347 ValueCell
->DataType
= Type
;
1352 * New data size is larger than the current, destroy current
1353 * data block and allocate a new one.
1355 BLOCK_OFFSET NewOffset
;
1357 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
1359 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
) &&
1360 (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
) != 0)
1362 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
1363 CmiDestroyCell(RegistryHive
, DataCell
, ValueCell
->DataOffset
);
1364 ValueCell
->DataSize
= 0;
1365 ValueCell
->DataType
= 0;
1366 ValueCell
->DataOffset
= (BLOCK_OFFSET
)-1;
1369 Status
= CmiAllocateCell (RegistryHive
,
1370 sizeof(CELL_HEADER
) + DataSize
,
1371 (PVOID
*)&NewDataCell
,
1373 if (!NT_SUCCESS(Status
))
1375 DPRINT("CmiAllocateBlock() failed (Status %lx)\n", Status
);
1377 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1378 KeLeaveCriticalRegion();
1379 ObDereferenceObject(KeyObject
);
1384 RtlCopyMemory(&NewDataCell
->Data
[0], Data
, DataSize
);
1385 ValueCell
->DataSize
= DataSize
& REG_DATA_SIZE_MASK
;
1386 ValueCell
->DataType
= Type
;
1387 ValueCell
->DataOffset
= NewOffset
;
1388 CmiMarkBlockDirty(RegistryHive
, ValueCell
->DataOffset
);
1389 CmiMarkBlockDirty(RegistryHive
, ValueCellOffset
);
1393 if ((Type
== REG_LINK
) &&
1394 (_wcsicmp(ValueName
->Buffer
, L
"SymbolicLinkValue") == 0))
1396 KeyCell
->Flags
|= REG_KEY_LINK_CELL
;
1399 NtQuerySystemTime (&KeyCell
->LastWriteTime
);
1400 CmiMarkBlockDirty (RegistryHive
, KeyObject
->KeyCellOffset
);
1402 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1403 KeLeaveCriticalRegion();
1404 ObDereferenceObject(KeyObject
);
1408 DPRINT("Return Status 0x%X\n", Status
);
1415 NtDeleteValueKey (IN HANDLE KeyHandle
,
1416 IN PUNICODE_STRING ValueName
)
1418 PKEY_OBJECT KeyObject
;
1421 /* Verify that the handle is valid and is a registry key */
1422 Status
= ObReferenceObjectByHandle(KeyHandle
,
1426 (PVOID
*)&KeyObject
,
1428 if (!NT_SUCCESS(Status
))
1433 /* Acquire hive lock */
1434 KeEnterCriticalRegion();
1435 ExAcquireResourceExclusiveLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1437 VERIFY_KEY_OBJECT(KeyObject
);
1439 Status
= CmiDeleteValueFromKey(KeyObject
->RegistryHive
,
1441 KeyObject
->KeyCellOffset
,
1444 NtQuerySystemTime (&KeyObject
->KeyCell
->LastWriteTime
);
1445 CmiMarkBlockDirty (KeyObject
->RegistryHive
, KeyObject
->KeyCellOffset
);
1447 /* Release hive lock */
1448 ExReleaseResourceLite (&KeyObject
->RegistryHive
->HiveResource
);
1449 KeLeaveCriticalRegion();
1451 ObDereferenceObject (KeyObject
);
1461 * KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
1462 * KeyObjectAttributes->Name specifies the name of the key to load.
1465 NtLoadKey (IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
1466 IN POBJECT_ATTRIBUTES FileObjectAttributes
)
1468 return NtLoadKey2 (KeyObjectAttributes
,
1469 FileObjectAttributes
,
1476 * KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
1477 * KeyObjectAttributes->Name specifies the name of the key to load.
1478 * Flags can be 0 or REG_NO_LAZY_FLUSH.
1481 NtLoadKey2 (IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
1482 IN POBJECT_ATTRIBUTES FileObjectAttributes
,
1485 POBJECT_NAME_INFORMATION NameInfo
;
1486 PUNICODE_STRING NamePointer
;
1492 DPRINT ("NtLoadKey2() called\n");
1495 if (!SeSinglePrivilegeCheck (SeRestorePrivilege
, KeGetPreviousMode ()))
1496 return STATUS_PRIVILEGE_NOT_HELD
;
1499 if (FileObjectAttributes
->RootDirectory
!= NULL
)
1502 sizeof(OBJECT_NAME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
);
1503 Buffer
= ExAllocatePool (NonPagedPool
,
1506 return STATUS_INSUFFICIENT_RESOURCES
;
1508 Status
= NtQueryObject (FileObjectAttributes
->RootDirectory
,
1509 ObjectNameInformation
,
1513 if (!NT_SUCCESS(Status
))
1515 DPRINT1 ("NtQueryObject() failed (Status %lx)\n", Status
);
1516 ExFreePool (Buffer
);
1520 NameInfo
= (POBJECT_NAME_INFORMATION
)Buffer
;
1521 DPRINT ("ObjectPath: '%wZ' Length %hu\n",
1522 &NameInfo
->Name
, NameInfo
->Name
.Length
);
1524 NameInfo
->Name
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
1525 if (FileObjectAttributes
->ObjectName
->Buffer
[0] != L
'\\')
1527 RtlAppendUnicodeToString (&NameInfo
->Name
,
1529 DPRINT ("ObjectPath: '%wZ' Length %hu\n",
1530 &NameInfo
->Name
, NameInfo
->Name
.Length
);
1532 RtlAppendUnicodeStringToString (&NameInfo
->Name
,
1533 FileObjectAttributes
->ObjectName
);
1535 DPRINT ("ObjectPath: '%wZ' Length %hu\n",
1536 &NameInfo
->Name
, NameInfo
->Name
.Length
);
1537 NamePointer
= &NameInfo
->Name
;
1541 if (FileObjectAttributes
->ObjectName
->Buffer
[0] == L
'\\')
1544 NamePointer
= FileObjectAttributes
->ObjectName
;
1549 sizeof(OBJECT_NAME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
);
1550 Buffer
= ExAllocatePool (NonPagedPool
,
1553 return STATUS_INSUFFICIENT_RESOURCES
;
1555 NameInfo
= (POBJECT_NAME_INFORMATION
)Buffer
;
1556 NameInfo
->Name
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
1557 NameInfo
->Name
.Length
= 0;
1558 NameInfo
->Name
.Buffer
= (PWSTR
)((ULONG_PTR
)Buffer
+ sizeof(OBJECT_NAME_INFORMATION
));
1559 NameInfo
->Name
.Buffer
[0] = 0;
1561 RtlAppendUnicodeToString (&NameInfo
->Name
,
1563 RtlAppendUnicodeStringToString (&NameInfo
->Name
,
1564 FileObjectAttributes
->ObjectName
);
1566 NamePointer
= &NameInfo
->Name
;
1570 DPRINT ("Full name: '%wZ'\n", NamePointer
);
1572 Status
= CmiLoadHive (KeyObjectAttributes
,
1575 if (!NT_SUCCESS (Status
))
1577 DPRINT1 ("CmiLoadHive() failed (Status %lx)\n", Status
);
1581 ExFreePool (Buffer
);
1588 NtNotifyChangeKey (IN HANDLE KeyHandle
,
1590 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1591 IN PVOID ApcContext OPTIONAL
,
1592 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1593 IN ULONG CompletionFilter
,
1594 IN BOOLEAN Asynchroneous
,
1595 OUT PVOID ChangeBuffer
,
1597 IN BOOLEAN WatchSubtree
)
1600 return(STATUS_NOT_IMPLEMENTED
);
1605 NtQueryMultipleValueKey (IN HANDLE KeyHandle
,
1606 IN OUT PKEY_VALUE_ENTRY ValueList
,
1607 IN ULONG NumberOfValues
,
1609 IN OUT PULONG Length
,
1610 OUT PULONG ReturnLength
)
1612 PREGISTRY_HIVE RegistryHive
;
1613 PVALUE_CELL ValueCell
;
1614 PKEY_OBJECT KeyObject
;
1615 PDATA_CELL DataCell
;
1616 ULONG BufferLength
= 0;
1622 /* Verify that the handle is valid and is a registry key */
1623 Status
= ObReferenceObjectByHandle(KeyHandle
,
1627 (PVOID
*) &KeyObject
,
1629 if (!NT_SUCCESS(Status
))
1631 DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status
);
1635 /* Acquire hive lock */
1636 KeEnterCriticalRegion();
1637 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1639 VERIFY_KEY_OBJECT(KeyObject
);
1641 /* Get pointer to KeyCell */
1642 KeyCell
= KeyObject
->KeyCell
;
1643 RegistryHive
= KeyObject
->RegistryHive
;
1645 DataPtr
= (PUCHAR
) Buffer
;
1647 for (i
= 0; i
< NumberOfValues
; i
++)
1649 DPRINT("ValueName: '%wZ'\n", ValueList
[i
].ValueName
);
1651 /* Get Value block of interest */
1652 Status
= CmiScanKeyForValue(RegistryHive
,
1654 ValueList
[i
].ValueName
,
1658 if (!NT_SUCCESS(Status
))
1660 DPRINT("CmiScanKeyForValue() failed with status %x\n", Status
);
1663 else if (ValueCell
== NULL
)
1665 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
1669 BufferLength
= ROUND_UP(BufferLength
, sizeof(PVOID
));
1671 if (BufferLength
+ (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
) <= *Length
)
1673 DataPtr
= (PUCHAR
)ROUND_UP((ULONG
)DataPtr
, sizeof(PVOID
));
1675 ValueList
[i
].Type
= ValueCell
->DataType
;
1676 ValueList
[i
].DataLength
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
1677 ValueList
[i
].DataOffset
= (ULONG
) DataPtr
- (ULONG
) Buffer
;
1679 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
))
1681 DataCell
= CmiGetCell (RegistryHive
,
1682 ValueCell
->DataOffset
,
1684 RtlCopyMemory(DataPtr
,
1686 ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
1690 RtlCopyMemory(DataPtr
,
1691 &ValueCell
->DataOffset
,
1692 ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
1695 DataPtr
+= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
1699 Status
= STATUS_BUFFER_TOO_SMALL
;
1702 BufferLength
+= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
1705 if (NT_SUCCESS(Status
))
1706 *Length
= BufferLength
;
1708 *ReturnLength
= BufferLength
;
1710 /* Release hive lock */
1711 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1712 KeLeaveCriticalRegion();
1714 ObDereferenceObject(KeyObject
);
1716 DPRINT("Return Status 0x%X\n", Status
);
1723 NtReplaceKey (IN POBJECT_ATTRIBUTES ObjectAttributes
,
1725 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes
)
1728 return(STATUS_NOT_IMPLEMENTED
);
1733 NtRestoreKey (IN HANDLE KeyHandle
,
1734 IN HANDLE FileHandle
,
1735 IN ULONG RestoreFlags
)
1738 return(STATUS_NOT_IMPLEMENTED
);
1743 NtSaveKey (IN HANDLE KeyHandle
,
1744 IN HANDLE FileHandle
)
1746 PREGISTRY_HIVE TempHive
;
1747 PKEY_OBJECT KeyObject
;
1750 DPRINT ("NtSaveKey() called\n");
1753 if (!SeSinglePrivilegeCheck (SeBackupPrivilege
, KeGetPreviousMode ()))
1754 return STATUS_PRIVILEGE_NOT_HELD
;
1757 Status
= ObReferenceObjectByHandle (KeyHandle
,
1760 KeGetPreviousMode(),
1761 (PVOID
*)&KeyObject
,
1763 if (!NT_SUCCESS(Status
))
1765 DPRINT1 ("ObReferenceObjectByHandle() failed (Status %lx)\n", Status
);
1769 /* Acquire hive lock exclucively */
1770 KeEnterCriticalRegion();
1771 ExAcquireResourceExclusiveLite (&KeyObject
->RegistryHive
->HiveResource
,
1774 /* Refuse to save a volatile key */
1775 if (KeyObject
->RegistryHive
== CmiVolatileHive
)
1777 DPRINT1 ("Cannot save a volatile key\n");
1778 ExReleaseResourceLite (&KeyObject
->RegistryHive
->HiveResource
);
1779 KeLeaveCriticalRegion();
1780 ObDereferenceObject (KeyObject
);
1781 return STATUS_ACCESS_DENIED
;
1784 Status
= CmiCreateTempHive(&TempHive
);
1785 if (!NT_SUCCESS(Status
))
1787 DPRINT1 ("CmiCreateTempHive() failed (Status %lx)\n", Status
);
1788 ExReleaseResourceLite (&KeyObject
->RegistryHive
->HiveResource
);
1789 KeLeaveCriticalRegion();
1790 ObDereferenceObject (KeyObject
);
1794 Status
= CmiCopyKey (TempHive
,
1796 KeyObject
->RegistryHive
,
1797 KeyObject
->KeyCell
);
1798 if (!NT_SUCCESS(Status
))
1800 DPRINT1 ("CmiCopyKey() failed (Status %lx)\n", Status
);
1801 CmiRemoveRegistryHive (TempHive
);
1802 ExReleaseResourceLite (&KeyObject
->RegistryHive
->HiveResource
);
1803 KeLeaveCriticalRegion();
1804 ObDereferenceObject (KeyObject
);
1808 Status
= CmiSaveTempHive (TempHive
,
1810 if (!NT_SUCCESS(Status
))
1812 DPRINT1 ("CmiSaveTempHive() failed (Status %lx)\n", Status
);
1815 CmiRemoveRegistryHive (TempHive
);
1817 /* Release hive lock */
1818 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1819 KeLeaveCriticalRegion();
1821 ObDereferenceObject (KeyObject
);
1823 DPRINT ("NtSaveKey() done\n");
1825 return STATUS_SUCCESS
;
1830 NtSetInformationKey (IN HANDLE KeyHandle
,
1831 IN KEY_SET_INFORMATION_CLASS KeyInformationClass
,
1832 IN PVOID KeyInformation
,
1833 IN ULONG KeyInformationLength
)
1835 PKEY_OBJECT KeyObject
;
1838 if (KeyInformationClass
!= KeyLastWriteTimeInformation
)
1839 return STATUS_INVALID_INFO_CLASS
;
1841 if (KeyInformationLength
!= sizeof (KEY_LAST_WRITE_TIME_INFORMATION
))
1842 return STATUS_INFO_LENGTH_MISMATCH
;
1844 /* Verify that the handle is valid and is a registry key */
1845 Status
= ObReferenceObjectByHandle (KeyHandle
,
1849 (PVOID
*)&KeyObject
,
1851 if (!NT_SUCCESS (Status
))
1853 DPRINT ("ObReferenceObjectByHandle() failed with status %x\n", Status
);
1857 /* Acquire hive lock */
1858 KeEnterCriticalRegion();
1859 ExAcquireResourceExclusiveLite (&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1861 VERIFY_KEY_OBJECT(KeyObject
);
1863 KeyObject
->KeyCell
->LastWriteTime
.QuadPart
=
1864 ((PKEY_LAST_WRITE_TIME_INFORMATION
)KeyInformation
)->LastWriteTime
.QuadPart
;
1866 CmiMarkBlockDirty (KeyObject
->RegistryHive
,
1867 KeyObject
->KeyCellOffset
);
1869 /* Release hive lock */
1870 ExReleaseResourceLite (&KeyObject
->RegistryHive
->HiveResource
);
1871 KeLeaveCriticalRegion();
1873 ObDereferenceObject (KeyObject
);
1877 DPRINT ("NtSaveKey() done\n");
1879 return STATUS_SUCCESS
;
1885 * KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
1886 * KeyObjectAttributes->Name specifies the name of the key to unload.
1889 NtUnloadKey (IN POBJECT_ATTRIBUTES KeyObjectAttributes
)
1891 PREGISTRY_HIVE RegistryHive
;
1894 DPRINT ("NtUnloadKey() called\n");
1897 if (!SeSinglePrivilegeCheck (SeRestorePrivilege
, KeGetPreviousMode ()))
1898 return STATUS_PRIVILEGE_NOT_HELD
;
1901 Status
= CmiDisconnectHive (KeyObjectAttributes
,
1903 if (!NT_SUCCESS (Status
))
1905 DPRINT1 ("CmiDisconnectHive() failed (Status %lx)\n", Status
);
1909 DPRINT ("RegistryHive %p\n", RegistryHive
);
1911 /* Acquire hive list lock exclusively */
1912 KeEnterCriticalRegion();
1913 ExAcquireResourceExclusiveLite (&CmiHiveListLock
,
1918 if (!IsNoFileHive (RegistryHive
))
1919 CmiFlushRegistryHive (RegistryHive
);
1922 /* Release hive list lock */
1923 ExReleaseResourceLite (&CmiHiveListLock
);
1924 KeLeaveCriticalRegion();
1926 CmiRemoveRegistryHive (RegistryHive
);
1928 DPRINT ("NtUnloadKey() done\n");
1930 return STATUS_SUCCESS
;
1935 NtInitializeRegistry (IN BOOLEAN SetUpBoot
)
1939 if (CmiRegistryInitialized
== TRUE
)
1940 return STATUS_ACCESS_DENIED
;
1942 /* FIXME: save boot log file */
1944 Status
= CmiInitHives (SetUpBoot
);
1946 CmiRegistryInitialized
= TRUE
;