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 *****************************************************************/
13 #include <internal/debug.h>
18 /* GLOBALS ******************************************************************/
20 extern POBJECT_TYPE CmiKeyType
;
21 extern PREGISTRY_HIVE CmiVolatileHive
;
23 static BOOLEAN CmiRegistryInitialized
= FALSE
;
26 /* FUNCTIONS ****************************************************************/
32 CmRegisterCallback(IN PEX_CALLBACK_FUNCTION Function
,
34 IN OUT PLARGE_INTEGER Cookie
38 return STATUS_NOT_IMPLEMENTED
;
46 CmUnRegisterCallback(IN LARGE_INTEGER Cookie
)
49 return STATUS_NOT_IMPLEMENTED
;
54 NtCreateKey(OUT PHANDLE KeyHandle
,
55 IN ACCESS_MASK DesiredAccess
,
56 IN POBJECT_ATTRIBUTES ObjectAttributes
,
58 IN PUNICODE_STRING Class
,
59 IN ULONG CreateOptions
,
60 OUT PULONG Disposition
)
62 UNICODE_STRING RemainingPath
;
63 PKEY_OBJECT KeyObject
;
69 DPRINT("NtCreateKey (Name %wZ KeyHandle %x Root %x)\n",
70 ObjectAttributes
->ObjectName
,
72 ObjectAttributes
->RootDirectory
);
74 Status
= ObFindObject(ObjectAttributes
,
78 if (!NT_SUCCESS(Status
))
83 DPRINT("RemainingPath %wZ\n", &RemainingPath
);
85 if ((RemainingPath
.Buffer
== NULL
) || (RemainingPath
.Buffer
[0] == 0))
87 /* Fail if the key has been deleted */
88 if (((PKEY_OBJECT
) Object
)->Flags
& KO_MARKED_FOR_DELETE
)
90 ObDereferenceObject(Object
);
91 RtlFreeUnicodeString(&RemainingPath
);
92 return(STATUS_UNSUCCESSFUL
);
96 *Disposition
= REG_OPENED_EXISTING_KEY
;
98 Status
= ObCreateHandle(PsGetCurrentProcess(),
104 DPRINT("Status %x\n", Status
);
105 ObDereferenceObject(Object
);
106 RtlFreeUnicodeString(&RemainingPath
);
110 /* If RemainingPath contains \ we must return error
111 because NtCreateKey don't create trees */
112 Start
= RemainingPath
.Buffer
;
116 End
= wcschr(Start
, L
'\\');
119 ObDereferenceObject(Object
);
120 RtlFreeUnicodeString(&RemainingPath
);
121 return STATUS_OBJECT_NAME_NOT_FOUND
;
124 DPRINT("RemainingPath %S ParentObject %x\n", RemainingPath
.Buffer
, Object
);
126 Status
= ObCreateObject(ExGetPreviousMode(),
135 if (!NT_SUCCESS(Status
))
140 Status
= ObInsertObject((PVOID
)KeyObject
,
146 if (!NT_SUCCESS(Status
))
148 ObDereferenceObject(KeyObject
);
149 RtlFreeUnicodeString(&RemainingPath
);
153 KeyObject
->ParentKey
= Object
;
155 if (CreateOptions
& REG_OPTION_VOLATILE
)
156 KeyObject
->RegistryHive
= CmiVolatileHive
;
158 KeyObject
->RegistryHive
= KeyObject
->ParentKey
->RegistryHive
;
160 KeyObject
->Flags
= 0;
161 KeyObject
->NumberOfSubKeys
= 0;
162 KeyObject
->SizeOfSubKeys
= 0;
163 KeyObject
->SubKeys
= NULL
;
165 /* Acquire hive lock */
166 KeEnterCriticalRegion();
167 ExAcquireResourceExclusiveLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
169 /* add key to subkeys of parent if needed */
170 Status
= CmiAddSubKey(KeyObject
->RegistryHive
,
171 KeyObject
->ParentKey
,
177 if (!NT_SUCCESS(Status
))
179 DPRINT("CmiAddSubKey() failed (Status %lx)\n", Status
);
180 /* Release hive lock */
181 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
182 KeLeaveCriticalRegion();
183 ObDereferenceObject(KeyObject
);
184 ObDereferenceObject(Object
);
185 RtlFreeUnicodeString(&RemainingPath
);
186 return STATUS_UNSUCCESSFUL
;
189 if (Start
== RemainingPath
.Buffer
)
191 KeyObject
->Name
= RemainingPath
;
195 RtlCreateUnicodeString(&KeyObject
->Name
,
197 RtlFreeUnicodeString(&RemainingPath
);
200 if (KeyObject
->RegistryHive
== KeyObject
->ParentKey
->RegistryHive
)
202 KeyObject
->KeyCell
->ParentKeyOffset
= KeyObject
->ParentKey
->KeyCellOffset
;
203 KeyObject
->KeyCell
->SecurityKeyOffset
= KeyObject
->ParentKey
->KeyCell
->SecurityKeyOffset
;
207 KeyObject
->KeyCell
->ParentKeyOffset
= -1;
208 KeyObject
->KeyCell
->SecurityKeyOffset
= -1;
209 /* This key must remain in memory unless it is deleted
210 or file is unloaded */
211 ObReferenceObjectByPointer(KeyObject
,
212 STANDARD_RIGHTS_REQUIRED
,
217 CmiAddKeyToList(KeyObject
->ParentKey
, KeyObject
);
219 VERIFY_KEY_OBJECT(KeyObject
);
221 /* Release hive lock */
222 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
223 KeLeaveCriticalRegion();
225 ObDereferenceObject(KeyObject
);
226 ObDereferenceObject(Object
);
229 *Disposition
= REG_CREATED_NEW_KEY
;
238 NtDeleteKey(IN HANDLE KeyHandle
)
240 PKEY_OBJECT KeyObject
;
243 DPRINT("KeyHandle %x\n", KeyHandle
);
245 /* Verify that the handle is valid and is a registry key */
246 Status
= ObReferenceObjectByHandle(KeyHandle
,
252 if (!NT_SUCCESS(Status
))
257 /* Acquire hive lock */
258 KeEnterCriticalRegion();
259 ExAcquireResourceExclusiveLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
261 VERIFY_KEY_OBJECT(KeyObject
);
263 /* Check for subkeys */
264 if (KeyObject
->NumberOfSubKeys
!= 0)
266 Status
= STATUS_CANNOT_DELETE
;
270 /* Set the marked for delete bit in the key object */
271 KeyObject
->Flags
|= KO_MARKED_FOR_DELETE
;
272 Status
= STATUS_SUCCESS
;
275 /* Release hive lock */
276 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
277 KeLeaveCriticalRegion();
279 DPRINT("PointerCount %lu\n", ObGetObjectPointerCount((PVOID
)KeyObject
));
281 /* Dereference the object */
282 ObDereferenceObject(KeyObject
);
283 if(KeyObject
->RegistryHive
!= KeyObject
->ParentKey
->RegistryHive
)
284 ObDereferenceObject(KeyObject
);
286 DPRINT("PointerCount %lu\n", ObGetObjectPointerCount((PVOID
)KeyObject
));
290 * Hive-Synchronization will not be triggered here. This is done in
291 * CmiObjectDelete() (in regobj.c) after all key-related structures
292 * have been released.
300 NtEnumerateKey(IN HANDLE KeyHandle
,
302 IN KEY_INFORMATION_CLASS KeyInformationClass
,
303 OUT PVOID KeyInformation
,
305 OUT PULONG ResultLength
)
307 PKEY_OBJECT KeyObject
;
308 PKEY_OBJECT SubKeyObject
;
309 PREGISTRY_HIVE RegistryHive
;
310 PKEY_CELL KeyCell
, SubKeyCell
;
311 PHASH_TABLE_CELL HashTableBlock
;
312 PKEY_BASIC_INFORMATION BasicInformation
;
313 PKEY_NODE_INFORMATION NodeInformation
;
314 PKEY_FULL_INFORMATION FullInformation
;
315 PDATA_CELL ClassCell
;
316 ULONG NameSize
, ClassSize
;
319 DPRINT("KH %x I %d KIC %x KI %x L %d RL %x\n",
327 /* Verify that the handle is valid and is a registry key */
328 Status
= ObReferenceObjectByHandle(KeyHandle
,
329 KEY_ENUMERATE_SUB_KEYS
,
332 (PVOID
*) &KeyObject
,
334 if (!NT_SUCCESS(Status
))
336 DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status
);
340 /* Acquire hive lock */
341 KeEnterCriticalRegion();
342 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
344 VERIFY_KEY_OBJECT(KeyObject
);
346 /* Get pointer to KeyCell */
347 KeyCell
= KeyObject
->KeyCell
;
348 RegistryHive
= KeyObject
->RegistryHive
;
352 /* Check for hightest possible sub key index */
353 if (Index
>= KeyCell
->NumberOfSubKeys
+ KeyObject
->NumberOfSubKeys
)
355 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
356 KeLeaveCriticalRegion();
357 ObDereferenceObject(KeyObject
);
358 DPRINT("No more volatile entries\n");
359 return STATUS_NO_MORE_ENTRIES
;
362 /* Get pointer to SubKey */
363 if (Index
>= KeyCell
->NumberOfSubKeys
)
365 PKEY_OBJECT CurKey
= NULL
;
369 /* Search for volatile or 'foreign' keys */
370 j
= KeyCell
->NumberOfSubKeys
;
371 for (i
= 0; i
< KeyObject
->NumberOfSubKeys
; i
++)
373 CurKey
= KeyObject
->SubKeys
[i
];
374 if (CurKey
->RegistryHive
== CmiVolatileHive
||
375 CurKey
->RegistryHive
!= RegistryHive
)
383 if (i
>= KeyObject
->NumberOfSubKeys
)
385 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
386 KeLeaveCriticalRegion();
387 ObDereferenceObject(KeyObject
);
388 DPRINT("No more non-volatile entries\n");
389 return STATUS_NO_MORE_ENTRIES
;
392 SubKeyObject
= CurKey
;
393 SubKeyCell
= CurKey
->KeyCell
;
397 if (KeyCell
->HashTableOffset
== (BLOCK_OFFSET
)-1)
399 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
400 KeLeaveCriticalRegion();
401 ObDereferenceObject(KeyObject
);
402 return STATUS_NO_MORE_ENTRIES
;
405 HashTableBlock
= CmiGetCell (RegistryHive
, KeyCell
->HashTableOffset
, NULL
);
406 if (HashTableBlock
== NULL
)
408 DPRINT("CmiGetBlock() failed\n");
409 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
410 KeLeaveCriticalRegion();
411 ObDereferenceObject(KeyObject
);
412 return STATUS_UNSUCCESSFUL
;
415 SubKeyCell
= CmiGetKeyFromHashByIndex(RegistryHive
,
420 if (SubKeyCell
== NULL
)
422 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
423 KeLeaveCriticalRegion();
424 ObDereferenceObject(KeyObject
);
425 DPRINT("No more entries\n");
426 return STATUS_NO_MORE_ENTRIES
;
429 Status
= STATUS_SUCCESS
;
430 switch (KeyInformationClass
)
432 case KeyBasicInformation
:
433 /* Check size of buffer */
434 if (SubKeyObject
!= NULL
)
436 NameSize
= SubKeyObject
->Name
.Length
;
440 NameSize
= SubKeyCell
->NameSize
;
441 if (SubKeyCell
->Flags
& REG_KEY_NAME_PACKED
)
443 NameSize
*= sizeof(WCHAR
);
447 *ResultLength
= FIELD_OFFSET(KEY_BASIC_INFORMATION
, Name
[0]) + NameSize
;
450 * NOTE: It's perfetly valid to call NtEnumerateKey to get
451 * all the information but name. Actually the NT4 sound
452 * framework does that while querying parameters from registry.
453 * -- Filip Navara, 19/07/2004
455 if (Length
< FIELD_OFFSET(KEY_BASIC_INFORMATION
, Name
[0]))
457 Status
= STATUS_BUFFER_TOO_SMALL
;
461 /* Fill buffer with requested info */
462 BasicInformation
= (PKEY_BASIC_INFORMATION
) KeyInformation
;
463 BasicInformation
->LastWriteTime
.u
.LowPart
= SubKeyCell
->LastWriteTime
.u
.LowPart
;
464 BasicInformation
->LastWriteTime
.u
.HighPart
= SubKeyCell
->LastWriteTime
.u
.HighPart
;
465 BasicInformation
->TitleIndex
= Index
;
466 BasicInformation
->NameLength
= NameSize
;
468 if (Length
- FIELD_OFFSET(KEY_BASIC_INFORMATION
, Name
[0]) < NameSize
)
470 NameSize
= Length
- FIELD_OFFSET(KEY_BASIC_INFORMATION
, Name
[0]);
471 Status
= STATUS_BUFFER_OVERFLOW
;
475 if (SubKeyObject
!= NULL
)
477 RtlCopyMemory(BasicInformation
->Name
,
478 SubKeyObject
->Name
.Buffer
,
483 if (SubKeyCell
->Flags
& REG_KEY_NAME_PACKED
)
485 CmiCopyPackedName(BasicInformation
->Name
,
487 NameSize
/ sizeof(WCHAR
));
491 RtlCopyMemory(BasicInformation
->Name
,
499 case KeyNodeInformation
:
500 /* Check size of buffer */
501 if (SubKeyObject
!= NULL
)
503 NameSize
= SubKeyObject
->Name
.Length
;
507 NameSize
= SubKeyCell
->NameSize
;
508 if (SubKeyCell
->Flags
& REG_KEY_NAME_PACKED
)
510 NameSize
*= sizeof(WCHAR
);
513 ClassSize
= SubKeyCell
->ClassSize
;
515 *ResultLength
= FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]) +
516 NameSize
+ ClassSize
;
518 if (Length
< FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]))
520 Status
= STATUS_BUFFER_TOO_SMALL
;
524 /* Fill buffer with requested info */
525 NodeInformation
= (PKEY_NODE_INFORMATION
) KeyInformation
;
526 NodeInformation
->LastWriteTime
.u
.LowPart
= SubKeyCell
->LastWriteTime
.u
.LowPart
;
527 NodeInformation
->LastWriteTime
.u
.HighPart
= SubKeyCell
->LastWriteTime
.u
.HighPart
;
528 NodeInformation
->TitleIndex
= Index
;
529 NodeInformation
->ClassOffset
= sizeof(KEY_NODE_INFORMATION
) + NameSize
;
530 NodeInformation
->ClassLength
= SubKeyCell
->ClassSize
;
531 NodeInformation
->NameLength
= NameSize
;
533 if (Length
- FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]) < NameSize
)
535 NameSize
= Length
- FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]);
537 Status
= STATUS_BUFFER_OVERFLOW
;
540 else if (Length
- FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]) -
541 NameSize
< ClassSize
)
543 ClassSize
= Length
- FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]) -
545 Status
= STATUS_BUFFER_OVERFLOW
;
549 if (SubKeyObject
!= NULL
)
551 RtlCopyMemory(NodeInformation
->Name
,
552 SubKeyObject
->Name
.Buffer
,
557 if (SubKeyCell
->Flags
& REG_KEY_NAME_PACKED
)
559 CmiCopyPackedName(NodeInformation
->Name
,
561 NameSize
/ sizeof(WCHAR
));
565 RtlCopyMemory(NodeInformation
->Name
,
573 ClassCell
= CmiGetCell (KeyObject
->RegistryHive
,
574 SubKeyCell
->ClassNameOffset
,
576 RtlCopyMemory (NodeInformation
->Name
+ SubKeyCell
->NameSize
,
583 case KeyFullInformation
:
584 ClassSize
= SubKeyCell
->ClassSize
;
586 *ResultLength
= FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
[0]) +
589 /* Check size of buffer */
590 if (Length
< FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
[0]))
592 Status
= STATUS_BUFFER_TOO_SMALL
;
596 /* Fill buffer with requested info */
597 FullInformation
= (PKEY_FULL_INFORMATION
) KeyInformation
;
598 FullInformation
->LastWriteTime
.u
.LowPart
= SubKeyCell
->LastWriteTime
.u
.LowPart
;
599 FullInformation
->LastWriteTime
.u
.HighPart
= SubKeyCell
->LastWriteTime
.u
.HighPart
;
600 FullInformation
->TitleIndex
= Index
;
601 FullInformation
->ClassOffset
= sizeof(KEY_FULL_INFORMATION
) -
603 FullInformation
->ClassLength
= SubKeyCell
->ClassSize
;
604 FullInformation
->SubKeys
= CmiGetNumberOfSubKeys(KeyObject
); //SubKeyCell->NumberOfSubKeys;
605 FullInformation
->MaxNameLen
= CmiGetMaxNameLength(KeyObject
);
606 FullInformation
->MaxClassLen
= CmiGetMaxClassLength(KeyObject
);
607 FullInformation
->Values
= SubKeyCell
->NumberOfValues
;
608 FullInformation
->MaxValueNameLen
=
609 CmiGetMaxValueNameLength(RegistryHive
, SubKeyCell
);
610 FullInformation
->MaxValueDataLen
=
611 CmiGetMaxValueDataLength(RegistryHive
, SubKeyCell
);
613 if (Length
- FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
[0]) < ClassSize
)
615 ClassSize
= Length
- FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
[0]);
616 Status
= STATUS_BUFFER_OVERFLOW
;
622 ClassCell
= CmiGetCell (KeyObject
->RegistryHive
,
623 SubKeyCell
->ClassNameOffset
,
625 RtlCopyMemory (FullInformation
->Class
,
633 DPRINT1("Not handling 0x%x\n", KeyInformationClass
);
637 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
638 KeLeaveCriticalRegion();
639 ObDereferenceObject(KeyObject
);
641 DPRINT("Returning status %x\n", Status
);
648 NtEnumerateValueKey(IN HANDLE KeyHandle
,
650 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
,
651 OUT PVOID KeyValueInformation
,
653 OUT PULONG ResultLength
)
656 PKEY_OBJECT KeyObject
;
657 PREGISTRY_HIVE RegistryHive
;
659 PVALUE_CELL ValueCell
;
661 ULONG NameSize
, DataSize
;
662 PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation
;
663 PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation
;
664 PKEY_VALUE_FULL_INFORMATION ValueFullInformation
;
666 DPRINT("KH %x I %d KVIC %x KVI %x L %d RL %x\n",
669 KeyValueInformationClass
,
674 /* Verify that the handle is valid and is a registry key */
675 Status
= ObReferenceObjectByHandle(KeyHandle
,
679 (PVOID
*) &KeyObject
,
682 if (!NT_SUCCESS(Status
))
687 /* Acquire hive lock */
688 KeEnterCriticalRegion();
689 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
691 VERIFY_KEY_OBJECT(KeyObject
);
693 /* Get pointer to KeyCell */
694 KeyCell
= KeyObject
->KeyCell
;
695 RegistryHive
= KeyObject
->RegistryHive
;
697 /* Get Value block of interest */
698 Status
= CmiGetValueFromKeyByIndex(RegistryHive
,
703 if (!NT_SUCCESS(Status
))
705 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
706 KeLeaveCriticalRegion();
707 ObDereferenceObject(KeyObject
);
711 if (ValueCell
!= NULL
)
713 switch (KeyValueInformationClass
)
715 case KeyValueBasicInformation
:
716 NameSize
= ValueCell
->NameSize
;
717 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
719 NameSize
*= sizeof(WCHAR
);
722 *ResultLength
= FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[0]) + NameSize
;
724 if (Length
< FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[0]))
726 Status
= STATUS_BUFFER_TOO_SMALL
;
730 ValueBasicInformation
= (PKEY_VALUE_BASIC_INFORMATION
)
732 ValueBasicInformation
->TitleIndex
= 0;
733 ValueBasicInformation
->Type
= ValueCell
->DataType
;
734 ValueBasicInformation
->NameLength
= NameSize
;
736 if (Length
- FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[0]) <
739 NameSize
= Length
- FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[0]);
740 Status
= STATUS_BUFFER_OVERFLOW
;
744 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
746 CmiCopyPackedName(ValueBasicInformation
->Name
,
748 NameSize
/ sizeof(WCHAR
));
752 RtlCopyMemory(ValueBasicInformation
->Name
,
759 case KeyValuePartialInformation
:
760 DataSize
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
762 *ResultLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) +
765 if (Length
< FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]))
767 Status
= STATUS_BUFFER_TOO_SMALL
;
771 ValuePartialInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)
773 ValuePartialInformation
->TitleIndex
= 0;
774 ValuePartialInformation
->Type
= ValueCell
->DataType
;
775 ValuePartialInformation
->DataLength
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
777 if (Length
- FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) <
780 DataSize
= Length
- FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]);
781 Status
= STATUS_BUFFER_OVERFLOW
;
785 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
))
787 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
788 RtlCopyMemory(ValuePartialInformation
->Data
,
794 RtlCopyMemory(ValuePartialInformation
->Data
,
795 &ValueCell
->DataOffset
,
801 case KeyValueFullInformation
:
802 NameSize
= ValueCell
->NameSize
;
803 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
805 NameSize
*= sizeof(WCHAR
);
807 DataSize
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
809 *ResultLength
= ROUND_UP(FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
,
810 Name
[0]) + NameSize
, sizeof(PVOID
)) + DataSize
;
812 if (Length
< FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]))
814 Status
= STATUS_BUFFER_TOO_SMALL
;
818 ValueFullInformation
= (PKEY_VALUE_FULL_INFORMATION
)
820 ValueFullInformation
->TitleIndex
= 0;
821 ValueFullInformation
->Type
= ValueCell
->DataType
;
822 ValueFullInformation
->NameLength
= NameSize
;
823 ValueFullInformation
->DataOffset
=
824 (ULONG_PTR
)ValueFullInformation
->Name
-
825 (ULONG_PTR
)ValueFullInformation
+
826 ValueFullInformation
->NameLength
;
827 ValueFullInformation
->DataOffset
=
828 ROUND_UP(ValueFullInformation
->DataOffset
, sizeof(PVOID
));
829 ValueFullInformation
->DataLength
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
831 if (Length
- FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]) <
834 NameSize
= Length
- FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]);
836 Status
= STATUS_BUFFER_OVERFLOW
;
839 else if (ROUND_UP(Length
- FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
,
840 Name
[0]) - NameSize
, sizeof(PVOID
)) < DataSize
)
842 DataSize
= ROUND_UP(Length
- FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]) - NameSize
, sizeof(PVOID
));
843 Status
= STATUS_BUFFER_OVERFLOW
;
847 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
849 CmiCopyPackedName(ValueFullInformation
->Name
,
851 NameSize
/ sizeof(WCHAR
));
855 RtlCopyMemory(ValueFullInformation
->Name
,
860 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
))
862 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
863 RtlCopyMemory((PCHAR
) ValueFullInformation
864 + ValueFullInformation
->DataOffset
,
865 DataCell
->Data
, DataSize
);
869 RtlCopyMemory((PCHAR
) ValueFullInformation
870 + ValueFullInformation
->DataOffset
,
871 &ValueCell
->DataOffset
, DataSize
);
877 DPRINT1("Not handling 0x%x\n", KeyValueInformationClass
);
883 Status
= STATUS_UNSUCCESSFUL
;
886 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
887 KeLeaveCriticalRegion();
888 ObDereferenceObject(KeyObject
);
895 NtFlushKey(IN HANDLE KeyHandle
)
898 PKEY_OBJECT KeyObject
;
899 PREGISTRY_HIVE RegistryHive
;
901 DPRINT("NtFlushKey (KeyHandle %lx) called\n", KeyHandle
);
903 /* Verify that the handle is valid and is a registry key */
904 Status
= ObReferenceObjectByHandle(KeyHandle
,
910 if (!NT_SUCCESS(Status
))
915 VERIFY_KEY_OBJECT(KeyObject
);
917 RegistryHive
= KeyObject
->RegistryHive
;
919 /* Acquire hive lock */
920 KeEnterCriticalRegion();
921 ExAcquireResourceExclusiveLite(&RegistryHive
->HiveResource
,
924 if (IsNoFileHive(RegistryHive
))
926 Status
= STATUS_SUCCESS
;
930 /* Flush non-volatile hive */
931 Status
= CmiFlushRegistryHive(RegistryHive
);
934 ExReleaseResourceLite(&RegistryHive
->HiveResource
);
935 KeLeaveCriticalRegion();
937 ObDereferenceObject(KeyObject
);
939 return STATUS_SUCCESS
;
944 NtOpenKey(OUT PHANDLE KeyHandle
,
945 IN ACCESS_MASK DesiredAccess
,
946 IN POBJECT_ATTRIBUTES ObjectAttributes
)
948 UNICODE_STRING RemainingPath
;
952 DPRINT("NtOpenKey(KH %x DA %x OA %x OA->ON '%wZ'\n",
956 ObjectAttributes
? ObjectAttributes
->ObjectName
: NULL
);
958 RemainingPath
.Buffer
= NULL
;
959 Status
= ObFindObject(ObjectAttributes
,
963 if (!NT_SUCCESS(Status
))
968 VERIFY_KEY_OBJECT((PKEY_OBJECT
) Object
);
970 DPRINT("RemainingPath '%wZ'\n", &RemainingPath
);
972 if ((RemainingPath
.Buffer
!= NULL
) && (RemainingPath
.Buffer
[0] != 0))
974 ObDereferenceObject(Object
);
975 RtlFreeUnicodeString(&RemainingPath
);
976 return STATUS_OBJECT_NAME_NOT_FOUND
;
979 RtlFreeUnicodeString(&RemainingPath
);
981 /* Fail if the key has been deleted */
982 if (((PKEY_OBJECT
)Object
)->Flags
& KO_MARKED_FOR_DELETE
)
984 ObDereferenceObject(Object
);
985 return(STATUS_UNSUCCESSFUL
);
988 Status
= ObCreateHandle(PsGetCurrentProcess(),
993 ObDereferenceObject(Object
);
995 if (!NT_SUCCESS(Status
))
1000 return(STATUS_SUCCESS
);
1005 NtQueryKey(IN HANDLE KeyHandle
,
1006 IN KEY_INFORMATION_CLASS KeyInformationClass
,
1007 OUT PVOID KeyInformation
,
1009 OUT PULONG ResultLength
)
1011 PKEY_BASIC_INFORMATION BasicInformation
;
1012 PKEY_NODE_INFORMATION NodeInformation
;
1013 PKEY_FULL_INFORMATION FullInformation
;
1014 PREGISTRY_HIVE RegistryHive
;
1015 PDATA_CELL ClassCell
;
1016 PKEY_OBJECT KeyObject
;
1018 ULONG NameSize
, ClassSize
;
1021 DPRINT("NtQueryKey(KH %x KIC %x KI %x L %d RL %x)\n",
1023 KeyInformationClass
,
1028 /* Verify that the handle is valid and is a registry key */
1029 Status
= ObReferenceObjectByHandle(KeyHandle
,
1033 (PVOID
*) &KeyObject
,
1035 if (!NT_SUCCESS(Status
))
1040 /* Acquire hive lock */
1041 KeEnterCriticalRegion();
1042 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1044 VERIFY_KEY_OBJECT(KeyObject
);
1046 /* Get pointer to KeyCell */
1047 KeyCell
= KeyObject
->KeyCell
;
1048 RegistryHive
= KeyObject
->RegistryHive
;
1050 Status
= STATUS_SUCCESS
;
1051 switch (KeyInformationClass
)
1053 case KeyBasicInformation
:
1054 NameSize
= KeyObject
->Name
.Length
;
1056 *ResultLength
= FIELD_OFFSET(KEY_BASIC_INFORMATION
, Name
[0]);
1058 /* Check size of buffer */
1059 if (Length
< FIELD_OFFSET(KEY_BASIC_INFORMATION
, Name
[0]))
1061 Status
= STATUS_BUFFER_TOO_SMALL
;
1065 /* Fill buffer with requested info */
1066 BasicInformation
= (PKEY_BASIC_INFORMATION
) KeyInformation
;
1067 BasicInformation
->LastWriteTime
.u
.LowPart
= KeyCell
->LastWriteTime
.u
.LowPart
;
1068 BasicInformation
->LastWriteTime
.u
.HighPart
= KeyCell
->LastWriteTime
.u
.HighPart
;
1069 BasicInformation
->TitleIndex
= 0;
1070 BasicInformation
->NameLength
= KeyObject
->Name
.Length
;
1072 if (Length
- FIELD_OFFSET(KEY_BASIC_INFORMATION
, Name
[0]) <
1075 NameSize
= Length
- FIELD_OFFSET(KEY_BASIC_INFORMATION
, Name
[0]);
1076 Status
= STATUS_BUFFER_OVERFLOW
;
1080 RtlCopyMemory(BasicInformation
->Name
,
1081 KeyObject
->Name
.Buffer
,
1086 case KeyNodeInformation
:
1087 NameSize
= KeyObject
->Name
.Length
;
1088 ClassSize
= KeyCell
->ClassSize
;
1090 *ResultLength
= FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]) +
1091 NameSize
+ ClassSize
;
1093 /* Check size of buffer */
1094 if (Length
< *ResultLength
)
1096 Status
= STATUS_BUFFER_TOO_SMALL
;
1100 /* Fill buffer with requested info */
1101 NodeInformation
= (PKEY_NODE_INFORMATION
) KeyInformation
;
1102 NodeInformation
->LastWriteTime
.u
.LowPart
= KeyCell
->LastWriteTime
.u
.LowPart
;
1103 NodeInformation
->LastWriteTime
.u
.HighPart
= KeyCell
->LastWriteTime
.u
.HighPart
;
1104 NodeInformation
->TitleIndex
= 0;
1105 NodeInformation
->ClassOffset
= sizeof(KEY_NODE_INFORMATION
) +
1106 KeyObject
->Name
.Length
;
1107 NodeInformation
->ClassLength
= KeyCell
->ClassSize
;
1108 NodeInformation
->NameLength
= KeyObject
->Name
.Length
;
1110 if (Length
- FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]) < NameSize
)
1112 NameSize
= Length
- FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]);
1114 Status
= STATUS_BUFFER_OVERFLOW
;
1117 else if (Length
- FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]) -
1118 NameSize
< ClassSize
)
1120 ClassSize
= Length
- FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]) -
1122 Status
= STATUS_BUFFER_OVERFLOW
;
1126 RtlCopyMemory(NodeInformation
->Name
,
1127 KeyObject
->Name
.Buffer
,
1132 ClassCell
= CmiGetCell (KeyObject
->RegistryHive
,
1133 KeyCell
->ClassNameOffset
,
1135 RtlCopyMemory (NodeInformation
->Name
+ KeyObject
->Name
.Length
,
1142 case KeyFullInformation
:
1143 ClassSize
= KeyCell
->ClassSize
;
1145 *ResultLength
= FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
) +
1148 /* Check size of buffer */
1149 if (Length
< FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
))
1151 Status
= STATUS_BUFFER_TOO_SMALL
;
1155 /* Fill buffer with requested info */
1156 FullInformation
= (PKEY_FULL_INFORMATION
) KeyInformation
;
1157 FullInformation
->LastWriteTime
.u
.LowPart
= KeyCell
->LastWriteTime
.u
.LowPart
;
1158 FullInformation
->LastWriteTime
.u
.HighPart
= KeyCell
->LastWriteTime
.u
.HighPart
;
1159 FullInformation
->TitleIndex
= 0;
1160 FullInformation
->ClassOffset
= sizeof(KEY_FULL_INFORMATION
) - sizeof(WCHAR
);
1161 FullInformation
->ClassLength
= KeyCell
->ClassSize
;
1162 FullInformation
->SubKeys
= CmiGetNumberOfSubKeys(KeyObject
); //KeyCell->NumberOfSubKeys;
1163 FullInformation
->MaxNameLen
= CmiGetMaxNameLength(KeyObject
);
1164 FullInformation
->MaxClassLen
= CmiGetMaxClassLength(KeyObject
);
1165 FullInformation
->Values
= KeyCell
->NumberOfValues
;
1166 FullInformation
->MaxValueNameLen
=
1167 CmiGetMaxValueNameLength(RegistryHive
, KeyCell
);
1168 FullInformation
->MaxValueDataLen
=
1169 CmiGetMaxValueDataLength(RegistryHive
, KeyCell
);
1171 if (Length
- FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
[0]) < ClassSize
)
1173 ClassSize
= Length
- FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
[0]);
1174 Status
= STATUS_BUFFER_OVERFLOW
;
1180 ClassCell
= CmiGetCell (KeyObject
->RegistryHive
,
1181 KeyCell
->ClassNameOffset
,
1183 RtlCopyMemory (FullInformation
->Class
,
1184 ClassCell
->Data
, ClassSize
);
1190 DPRINT1("Not handling 0x%x\n", KeyInformationClass
);
1191 Status
= STATUS_INVALID_INFO_CLASS
;
1195 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1196 KeLeaveCriticalRegion();
1197 ObDereferenceObject(KeyObject
);
1204 NtQueryValueKey(IN HANDLE KeyHandle
,
1205 IN PUNICODE_STRING ValueName
,
1206 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
,
1207 OUT PVOID KeyValueInformation
,
1209 OUT PULONG ResultLength
)
1212 ULONG NameSize
, DataSize
;
1213 PKEY_OBJECT KeyObject
;
1214 PREGISTRY_HIVE RegistryHive
;
1216 PVALUE_CELL ValueCell
;
1217 PDATA_CELL DataCell
;
1218 PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation
;
1219 PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation
;
1220 PKEY_VALUE_FULL_INFORMATION ValueFullInformation
;
1222 DPRINT("NtQueryValueKey(KeyHandle %x ValueName %S Length %x)\n",
1223 KeyHandle
, ValueName
->Buffer
, Length
);
1225 /* Verify that the handle is valid and is a registry key */
1226 Status
= ObReferenceObjectByHandle(KeyHandle
,
1230 (PVOID
*)&KeyObject
,
1233 if (!NT_SUCCESS(Status
))
1235 DPRINT1("ObReferenceObjectByHandle() failed with status %x\n", Status
);
1239 /* Acquire hive lock */
1240 KeEnterCriticalRegion();
1241 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1243 VERIFY_KEY_OBJECT(KeyObject
);
1245 /* Get pointer to KeyCell */
1246 KeyCell
= KeyObject
->KeyCell
;
1247 RegistryHive
= KeyObject
->RegistryHive
;
1249 /* Get value cell by name */
1250 Status
= CmiScanKeyForValue(RegistryHive
,
1255 if (!NT_SUCCESS(Status
))
1257 DPRINT("CmiScanKeyForValue() failed with status %x\n", Status
);
1261 Status
= STATUS_SUCCESS
;
1262 switch (KeyValueInformationClass
)
1264 case KeyValueBasicInformation
:
1265 NameSize
= ValueCell
->NameSize
;
1266 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1268 NameSize
*= sizeof(WCHAR
);
1271 *ResultLength
= FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[0]) +
1274 if (Length
< FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[0]))
1276 Status
= STATUS_BUFFER_TOO_SMALL
;
1280 ValueBasicInformation
= (PKEY_VALUE_BASIC_INFORMATION
)
1281 KeyValueInformation
;
1282 ValueBasicInformation
->TitleIndex
= 0;
1283 ValueBasicInformation
->Type
= ValueCell
->DataType
;
1284 ValueBasicInformation
->NameLength
= NameSize
;
1286 if (Length
- FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[0]) <
1289 NameSize
= Length
- FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[0]);
1290 Status
= STATUS_BUFFER_OVERFLOW
;
1294 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1296 CmiCopyPackedName(ValueBasicInformation
->Name
,
1298 NameSize
/ sizeof(WCHAR
));
1302 RtlCopyMemory(ValueBasicInformation
->Name
,
1309 case KeyValuePartialInformation
:
1310 DataSize
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
1312 *ResultLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) +
1315 if (Length
< FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]))
1317 Status
= STATUS_BUFFER_TOO_SMALL
;
1321 ValuePartialInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)
1322 KeyValueInformation
;
1323 ValuePartialInformation
->TitleIndex
= 0;
1324 ValuePartialInformation
->Type
= ValueCell
->DataType
;
1325 ValuePartialInformation
->DataLength
= DataSize
;
1327 if (Length
- FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) <
1330 DataSize
= Length
- FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]);
1331 Status
= STATUS_BUFFER_OVERFLOW
;
1335 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
))
1337 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
1338 RtlCopyMemory(ValuePartialInformation
->Data
,
1344 RtlCopyMemory(ValuePartialInformation
->Data
,
1345 &ValueCell
->DataOffset
,
1351 case KeyValueFullInformation
:
1352 NameSize
= ValueCell
->NameSize
;
1353 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1355 NameSize
*= sizeof(WCHAR
);
1357 DataSize
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
1359 *ResultLength
= ROUND_UP(FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
,
1360 Name
[0]) + NameSize
, sizeof(PVOID
)) + DataSize
;
1362 if (Length
< FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]))
1364 Status
= STATUS_BUFFER_TOO_SMALL
;
1368 ValueFullInformation
= (PKEY_VALUE_FULL_INFORMATION
)
1369 KeyValueInformation
;
1370 ValueFullInformation
->TitleIndex
= 0;
1371 ValueFullInformation
->Type
= ValueCell
->DataType
;
1372 ValueFullInformation
->NameLength
= NameSize
;
1373 ValueFullInformation
->DataOffset
=
1374 (ULONG_PTR
)ValueFullInformation
->Name
-
1375 (ULONG_PTR
)ValueFullInformation
+
1376 ValueFullInformation
->NameLength
;
1377 ValueFullInformation
->DataOffset
=
1378 ROUND_UP(ValueFullInformation
->DataOffset
, sizeof(PVOID
));
1379 ValueFullInformation
->DataLength
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
1381 if (Length
- FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]) <
1384 NameSize
= Length
- FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]);
1386 Status
= STATUS_BUFFER_OVERFLOW
;
1389 else if (ROUND_UP(Length
- FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
,
1390 Name
[0]) - NameSize
, sizeof(PVOID
)) < DataSize
)
1392 DataSize
= ROUND_UP(Length
- FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
,
1393 Name
[0]) - NameSize
, sizeof(PVOID
));
1394 Status
= STATUS_BUFFER_OVERFLOW
;
1398 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1400 CmiCopyPackedName(ValueFullInformation
->Name
,
1402 NameSize
/ sizeof(WCHAR
));
1406 RtlCopyMemory(ValueFullInformation
->Name
,
1410 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
))
1412 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
1413 RtlCopyMemory((PCHAR
) ValueFullInformation
1414 + ValueFullInformation
->DataOffset
,
1420 RtlCopyMemory((PCHAR
) ValueFullInformation
1421 + ValueFullInformation
->DataOffset
,
1422 &ValueCell
->DataOffset
,
1429 DPRINT1("Not handling 0x%x\n", KeyValueInformationClass
);
1430 Status
= STATUS_INVALID_INFO_CLASS
;
1435 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1436 KeLeaveCriticalRegion();
1437 ObDereferenceObject(KeyObject
);
1444 NtSetValueKey(IN HANDLE KeyHandle
,
1445 IN PUNICODE_STRING ValueName
,
1446 IN ULONG TitleIndex
,
1452 PKEY_OBJECT KeyObject
;
1453 PREGISTRY_HIVE RegistryHive
;
1455 PVALUE_CELL ValueCell
;
1456 BLOCK_OFFSET ValueCellOffset
;
1457 PDATA_CELL DataCell
;
1458 PDATA_CELL NewDataCell
;
1460 ULONG DesiredAccess
;
1462 DPRINT("NtSetValueKey(KeyHandle %x ValueName '%wZ' Type %d)\n",
1463 KeyHandle
, ValueName
, Type
);
1465 DesiredAccess
= KEY_SET_VALUE
;
1466 if (Type
== REG_LINK
)
1467 DesiredAccess
|= KEY_CREATE_LINK
;
1469 /* Verify that the handle is valid and is a registry key */
1470 Status
= ObReferenceObjectByHandle(KeyHandle
,
1474 (PVOID
*)&KeyObject
,
1476 if (!NT_SUCCESS(Status
))
1479 /* Acquire hive lock exclucively */
1480 KeEnterCriticalRegion();
1481 ExAcquireResourceExclusiveLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1483 VERIFY_KEY_OBJECT(KeyObject
);
1485 /* Get pointer to key cell */
1486 KeyCell
= KeyObject
->KeyCell
;
1487 RegistryHive
= KeyObject
->RegistryHive
;
1488 Status
= CmiScanKeyForValue(RegistryHive
,
1493 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1495 DPRINT("Allocate new value cell\n");
1496 Status
= CmiAddValueToKey(RegistryHive
,
1498 KeyObject
->KeyCellOffset
,
1504 if (!NT_SUCCESS(Status
))
1506 DPRINT("Cannot add value. Status 0x%X\n", Status
);
1508 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1509 KeLeaveCriticalRegion();
1510 ObDereferenceObject(KeyObject
);
1514 DPRINT("DataSize %lu\n", DataSize
);
1515 DPRINT("ValueCell %p\n", ValueCell
);
1516 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
1518 if (DataSize
<= sizeof(BLOCK_OFFSET
))
1520 /* If data size <= sizeof(BLOCK_OFFSET) then store data in the data offset */
1521 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
1522 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
) &&
1523 (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
) != 0)
1525 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
1526 CmiDestroyCell(RegistryHive
, DataCell
, ValueCell
->DataOffset
);
1529 RtlCopyMemory(&ValueCell
->DataOffset
, Data
, DataSize
);
1530 ValueCell
->DataSize
= DataSize
| REG_DATA_IN_OFFSET
;
1531 ValueCell
->DataType
= Type
;
1532 RtlMoveMemory(&ValueCell
->DataOffset
, Data
, DataSize
);
1533 CmiMarkBlockDirty(RegistryHive
, ValueCellOffset
);
1535 else if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
) &&
1536 (DataSize
<= (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
)))
1538 /* If new data size is <= current then overwrite current data */
1539 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
,&pBin
);
1540 RtlZeroMemory(DataCell
->Data
, ValueCell
->DataSize
);
1541 RtlCopyMemory(DataCell
->Data
, Data
, DataSize
);
1542 ValueCell
->DataSize
= DataSize
;
1543 ValueCell
->DataType
= Type
;
1548 * New data size is larger than the current, destroy current
1549 * data block and allocate a new one.
1551 BLOCK_OFFSET NewOffset
;
1553 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
1555 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
) &&
1556 (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
) != 0)
1558 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
1559 CmiDestroyCell(RegistryHive
, DataCell
, ValueCell
->DataOffset
);
1560 ValueCell
->DataSize
= 0;
1561 ValueCell
->DataType
= 0;
1562 ValueCell
->DataOffset
= (BLOCK_OFFSET
)-1;
1565 Status
= CmiAllocateCell (RegistryHive
,
1566 sizeof(CELL_HEADER
) + DataSize
,
1567 (PVOID
*)&NewDataCell
,
1569 if (!NT_SUCCESS(Status
))
1571 DPRINT("CmiAllocateBlock() failed (Status %lx)\n", Status
);
1573 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1574 KeLeaveCriticalRegion();
1575 ObDereferenceObject(KeyObject
);
1580 RtlCopyMemory(&NewDataCell
->Data
[0], Data
, DataSize
);
1581 ValueCell
->DataSize
= DataSize
& REG_DATA_SIZE_MASK
;
1582 ValueCell
->DataType
= Type
;
1583 ValueCell
->DataOffset
= NewOffset
;
1584 CmiMarkBlockDirty(RegistryHive
, ValueCell
->DataOffset
);
1585 CmiMarkBlockDirty(RegistryHive
, ValueCellOffset
);
1589 if ((Type
== REG_LINK
) &&
1590 (_wcsicmp(ValueName
->Buffer
, L
"SymbolicLinkValue") == 0))
1592 KeyCell
->Flags
|= REG_KEY_LINK_CELL
;
1595 NtQuerySystemTime (&KeyCell
->LastWriteTime
);
1596 CmiMarkBlockDirty (RegistryHive
, KeyObject
->KeyCellOffset
);
1598 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1599 KeLeaveCriticalRegion();
1600 ObDereferenceObject(KeyObject
);
1604 DPRINT("Return Status 0x%X\n", Status
);
1611 NtDeleteValueKey (IN HANDLE KeyHandle
,
1612 IN PUNICODE_STRING ValueName
)
1614 PKEY_OBJECT KeyObject
;
1617 /* Verify that the handle is valid and is a registry key */
1618 Status
= ObReferenceObjectByHandle(KeyHandle
,
1622 (PVOID
*)&KeyObject
,
1624 if (!NT_SUCCESS(Status
))
1629 /* Acquire hive lock */
1630 KeEnterCriticalRegion();
1631 ExAcquireResourceExclusiveLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1633 VERIFY_KEY_OBJECT(KeyObject
);
1635 Status
= CmiDeleteValueFromKey(KeyObject
->RegistryHive
,
1637 KeyObject
->KeyCellOffset
,
1640 NtQuerySystemTime (&KeyObject
->KeyCell
->LastWriteTime
);
1641 CmiMarkBlockDirty (KeyObject
->RegistryHive
, KeyObject
->KeyCellOffset
);
1643 /* Release hive lock */
1644 ExReleaseResourceLite (&KeyObject
->RegistryHive
->HiveResource
);
1645 KeLeaveCriticalRegion();
1647 ObDereferenceObject (KeyObject
);
1657 * KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
1658 * KeyObjectAttributes->Name specifies the name of the key to load.
1661 NtLoadKey (IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
1662 IN POBJECT_ATTRIBUTES FileObjectAttributes
)
1664 return NtLoadKey2 (KeyObjectAttributes
,
1665 FileObjectAttributes
,
1672 * KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
1673 * KeyObjectAttributes->Name specifies the name of the key to load.
1674 * Flags can be 0 or REG_NO_LAZY_FLUSH.
1677 NtLoadKey2 (IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
1678 IN POBJECT_ATTRIBUTES FileObjectAttributes
,
1681 POBJECT_NAME_INFORMATION NameInfo
;
1682 PUNICODE_STRING NamePointer
;
1688 DPRINT ("NtLoadKey2() called\n");
1691 if (!SeSinglePrivilegeCheck (SeRestorePrivilege
, KeGetPreviousMode ()))
1692 return STATUS_PRIVILEGE_NOT_HELD
;
1695 if (FileObjectAttributes
->RootDirectory
!= NULL
)
1698 sizeof(OBJECT_NAME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
);
1699 Buffer
= ExAllocatePool (NonPagedPool
,
1702 return STATUS_INSUFFICIENT_RESOURCES
;
1704 Status
= NtQueryObject (FileObjectAttributes
->RootDirectory
,
1705 ObjectNameInformation
,
1709 if (!NT_SUCCESS(Status
))
1711 DPRINT1 ("NtQueryObject() failed (Status %lx)\n", Status
);
1712 ExFreePool (Buffer
);
1716 NameInfo
= (POBJECT_NAME_INFORMATION
)Buffer
;
1717 DPRINT ("ObjectPath: '%wZ' Length %hu\n",
1718 &NameInfo
->Name
, NameInfo
->Name
.Length
);
1720 NameInfo
->Name
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
1721 if (FileObjectAttributes
->ObjectName
->Buffer
[0] != L
'\\')
1723 RtlAppendUnicodeToString (&NameInfo
->Name
,
1725 DPRINT ("ObjectPath: '%wZ' Length %hu\n",
1726 &NameInfo
->Name
, NameInfo
->Name
.Length
);
1728 RtlAppendUnicodeStringToString (&NameInfo
->Name
,
1729 FileObjectAttributes
->ObjectName
);
1731 DPRINT ("ObjectPath: '%wZ' Length %hu\n",
1732 &NameInfo
->Name
, NameInfo
->Name
.Length
);
1733 NamePointer
= &NameInfo
->Name
;
1737 if (FileObjectAttributes
->ObjectName
->Buffer
[0] == L
'\\')
1740 NamePointer
= FileObjectAttributes
->ObjectName
;
1745 sizeof(OBJECT_NAME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
);
1746 Buffer
= ExAllocatePool (NonPagedPool
,
1749 return STATUS_INSUFFICIENT_RESOURCES
;
1751 NameInfo
= (POBJECT_NAME_INFORMATION
)Buffer
;
1752 NameInfo
->Name
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
1753 NameInfo
->Name
.Length
= 0;
1754 NameInfo
->Name
.Buffer
= (PWSTR
)((ULONG_PTR
)Buffer
+ sizeof(OBJECT_NAME_INFORMATION
));
1755 NameInfo
->Name
.Buffer
[0] = 0;
1757 RtlAppendUnicodeToString (&NameInfo
->Name
,
1759 RtlAppendUnicodeStringToString (&NameInfo
->Name
,
1760 FileObjectAttributes
->ObjectName
);
1762 NamePointer
= &NameInfo
->Name
;
1766 DPRINT ("Full name: '%wZ'\n", NamePointer
);
1768 Status
= CmiLoadHive (KeyObjectAttributes
,
1771 if (!NT_SUCCESS (Status
))
1773 DPRINT1 ("CmiLoadHive() failed (Status %lx)\n", Status
);
1777 ExFreePool (Buffer
);
1784 NtNotifyChangeKey (IN HANDLE KeyHandle
,
1786 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1787 IN PVOID ApcContext OPTIONAL
,
1788 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1789 IN ULONG CompletionFilter
,
1790 IN BOOLEAN Asynchroneous
,
1791 OUT PVOID ChangeBuffer
,
1793 IN BOOLEAN WatchSubtree
)
1796 return(STATUS_NOT_IMPLEMENTED
);
1801 NtQueryMultipleValueKey (IN HANDLE KeyHandle
,
1802 IN OUT PKEY_VALUE_ENTRY ValueList
,
1803 IN ULONG NumberOfValues
,
1805 IN OUT PULONG Length
,
1806 OUT PULONG ReturnLength
)
1808 PREGISTRY_HIVE RegistryHive
;
1809 PVALUE_CELL ValueCell
;
1810 PKEY_OBJECT KeyObject
;
1811 PDATA_CELL DataCell
;
1812 ULONG BufferLength
= 0;
1818 /* Verify that the handle is valid and is a registry key */
1819 Status
= ObReferenceObjectByHandle(KeyHandle
,
1823 (PVOID
*) &KeyObject
,
1825 if (!NT_SUCCESS(Status
))
1827 DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status
);
1831 /* Acquire hive lock */
1832 KeEnterCriticalRegion();
1833 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1835 VERIFY_KEY_OBJECT(KeyObject
);
1837 /* Get pointer to KeyCell */
1838 KeyCell
= KeyObject
->KeyCell
;
1839 RegistryHive
= KeyObject
->RegistryHive
;
1841 DataPtr
= (PUCHAR
) Buffer
;
1843 for (i
= 0; i
< NumberOfValues
; i
++)
1845 DPRINT("ValueName: '%wZ'\n", ValueList
[i
].ValueName
);
1847 /* Get Value block of interest */
1848 Status
= CmiScanKeyForValue(RegistryHive
,
1850 ValueList
[i
].ValueName
,
1854 if (!NT_SUCCESS(Status
))
1856 DPRINT("CmiScanKeyForValue() failed with status %x\n", Status
);
1859 else if (ValueCell
== NULL
)
1861 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
1865 BufferLength
= ROUND_UP(BufferLength
, sizeof(PVOID
));
1867 if (BufferLength
+ (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
) <= *Length
)
1869 DataPtr
= (PUCHAR
)ROUND_UP((ULONG_PTR
)DataPtr
, sizeof(PVOID
));
1871 ValueList
[i
].Type
= ValueCell
->DataType
;
1872 ValueList
[i
].DataLength
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
1873 ValueList
[i
].DataOffset
= (ULONG_PTR
)DataPtr
- (ULONG_PTR
)Buffer
;
1875 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
))
1877 DataCell
= CmiGetCell (RegistryHive
,
1878 ValueCell
->DataOffset
,
1880 RtlCopyMemory(DataPtr
,
1882 ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
1886 RtlCopyMemory(DataPtr
,
1887 &ValueCell
->DataOffset
,
1888 ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
1891 DataPtr
+= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
1895 Status
= STATUS_BUFFER_TOO_SMALL
;
1898 BufferLength
+= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
1901 if (NT_SUCCESS(Status
))
1902 *Length
= BufferLength
;
1904 *ReturnLength
= BufferLength
;
1906 /* Release hive lock */
1907 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1908 KeLeaveCriticalRegion();
1910 ObDereferenceObject(KeyObject
);
1912 DPRINT("Return Status 0x%X\n", Status
);
1919 NtReplaceKey (IN POBJECT_ATTRIBUTES ObjectAttributes
,
1921 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes
)
1924 return(STATUS_NOT_IMPLEMENTED
);
1929 NtRestoreKey (IN HANDLE KeyHandle
,
1930 IN HANDLE FileHandle
,
1931 IN ULONG RestoreFlags
)
1934 return(STATUS_NOT_IMPLEMENTED
);
1939 NtSaveKey (IN HANDLE KeyHandle
,
1940 IN HANDLE FileHandle
)
1942 PREGISTRY_HIVE TempHive
;
1943 PKEY_OBJECT KeyObject
;
1946 DPRINT ("NtSaveKey() called\n");
1949 if (!SeSinglePrivilegeCheck (SeBackupPrivilege
, KeGetPreviousMode ()))
1950 return STATUS_PRIVILEGE_NOT_HELD
;
1953 Status
= ObReferenceObjectByHandle (KeyHandle
,
1956 KeGetPreviousMode(),
1957 (PVOID
*)&KeyObject
,
1959 if (!NT_SUCCESS(Status
))
1961 DPRINT1 ("ObReferenceObjectByHandle() failed (Status %lx)\n", Status
);
1965 /* Acquire hive lock exclucively */
1966 KeEnterCriticalRegion();
1967 ExAcquireResourceExclusiveLite (&KeyObject
->RegistryHive
->HiveResource
,
1970 /* Refuse to save a volatile key */
1971 if (KeyObject
->RegistryHive
== CmiVolatileHive
)
1973 DPRINT1 ("Cannot save a volatile key\n");
1974 ExReleaseResourceLite (&KeyObject
->RegistryHive
->HiveResource
);
1975 KeLeaveCriticalRegion();
1976 ObDereferenceObject (KeyObject
);
1977 return STATUS_ACCESS_DENIED
;
1980 Status
= CmiCreateTempHive(&TempHive
);
1981 if (!NT_SUCCESS(Status
))
1983 DPRINT1 ("CmiCreateTempHive() failed (Status %lx)\n", Status
);
1984 ExReleaseResourceLite (&KeyObject
->RegistryHive
->HiveResource
);
1985 KeLeaveCriticalRegion();
1986 ObDereferenceObject (KeyObject
);
1990 Status
= CmiCopyKey (TempHive
,
1992 KeyObject
->RegistryHive
,
1993 KeyObject
->KeyCell
);
1994 if (!NT_SUCCESS(Status
))
1996 DPRINT1 ("CmiCopyKey() failed (Status %lx)\n", Status
);
1997 CmiRemoveRegistryHive (TempHive
);
1998 ExReleaseResourceLite (&KeyObject
->RegistryHive
->HiveResource
);
1999 KeLeaveCriticalRegion();
2000 ObDereferenceObject (KeyObject
);
2004 Status
= CmiSaveTempHive (TempHive
,
2006 if (!NT_SUCCESS(Status
))
2008 DPRINT1 ("CmiSaveTempHive() failed (Status %lx)\n", Status
);
2011 CmiRemoveRegistryHive (TempHive
);
2013 /* Release hive lock */
2014 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
2015 KeLeaveCriticalRegion();
2017 ObDereferenceObject (KeyObject
);
2019 DPRINT ("NtSaveKey() done\n");
2021 return STATUS_SUCCESS
;
2030 IN HANDLE KeyHandle
,
2031 IN HANDLE FileHandle
,
2032 IN ULONG Flags
// REG_STANDARD_FORMAT, etc..
2036 return STATUS_NOT_IMPLEMENTED
;
2041 NtSetInformationKey (IN HANDLE KeyHandle
,
2042 IN KEY_SET_INFORMATION_CLASS KeyInformationClass
,
2043 IN PVOID KeyInformation
,
2044 IN ULONG KeyInformationLength
)
2046 PKEY_OBJECT KeyObject
;
2049 if (KeyInformationClass
!= KeyLastWriteTimeInformation
)
2050 return STATUS_INVALID_INFO_CLASS
;
2052 if (KeyInformationLength
!= sizeof (KEY_LAST_WRITE_TIME_INFORMATION
))
2053 return STATUS_INFO_LENGTH_MISMATCH
;
2055 /* Verify that the handle is valid and is a registry key */
2056 Status
= ObReferenceObjectByHandle (KeyHandle
,
2060 (PVOID
*)&KeyObject
,
2062 if (!NT_SUCCESS (Status
))
2064 DPRINT ("ObReferenceObjectByHandle() failed with status %x\n", Status
);
2068 /* Acquire hive lock */
2069 KeEnterCriticalRegion();
2070 ExAcquireResourceExclusiveLite (&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
2072 VERIFY_KEY_OBJECT(KeyObject
);
2074 KeyObject
->KeyCell
->LastWriteTime
.QuadPart
=
2075 ((PKEY_LAST_WRITE_TIME_INFORMATION
)KeyInformation
)->LastWriteTime
.QuadPart
;
2077 CmiMarkBlockDirty (KeyObject
->RegistryHive
,
2078 KeyObject
->KeyCellOffset
);
2080 /* Release hive lock */
2081 ExReleaseResourceLite (&KeyObject
->RegistryHive
->HiveResource
);
2082 KeLeaveCriticalRegion();
2084 ObDereferenceObject (KeyObject
);
2088 DPRINT ("NtSaveKey() done\n");
2090 return STATUS_SUCCESS
;
2096 * KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
2097 * KeyObjectAttributes->Name specifies the name of the key to unload.
2100 NtUnloadKey (IN POBJECT_ATTRIBUTES KeyObjectAttributes
)
2102 PREGISTRY_HIVE RegistryHive
;
2105 DPRINT ("NtUnloadKey() called\n");
2108 if (!SeSinglePrivilegeCheck (SeRestorePrivilege
, KeGetPreviousMode ()))
2109 return STATUS_PRIVILEGE_NOT_HELD
;
2112 Status
= CmiDisconnectHive (KeyObjectAttributes
,
2114 if (!NT_SUCCESS (Status
))
2116 DPRINT1 ("CmiDisconnectHive() failed (Status %lx)\n", Status
);
2120 DPRINT ("RegistryHive %p\n", RegistryHive
);
2122 /* Acquire hive list lock exclusively */
2123 KeEnterCriticalRegion();
2124 ExAcquireResourceExclusiveLite (&CmiHiveListLock
,
2129 if (!IsNoFileHive (RegistryHive
))
2130 CmiFlushRegistryHive (RegistryHive
);
2133 /* Release hive list lock */
2134 ExReleaseResourceLite (&CmiHiveListLock
);
2135 KeLeaveCriticalRegion();
2137 CmiRemoveRegistryHive (RegistryHive
);
2139 DPRINT ("NtUnloadKey() done\n");
2141 return STATUS_SUCCESS
;
2146 NtInitializeRegistry (IN BOOLEAN SetUpBoot
)
2150 if (CmiRegistryInitialized
== TRUE
)
2151 return STATUS_ACCESS_DENIED
;
2153 /* Save boot log file */
2154 IopSaveBootLogToFile();
2156 Status
= CmiInitHives (SetUpBoot
);
2158 CmiRegistryInitialized
= TRUE
;