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
))
80 DPRINT("ObFindObject failed, Status: 0x%x\n", Status
);
84 DPRINT("RemainingPath %wZ\n", &RemainingPath
);
86 if ((RemainingPath
.Buffer
== NULL
) || (RemainingPath
.Buffer
[0] == 0))
88 /* Fail if the key has been deleted */
89 if (((PKEY_OBJECT
) Object
)->Flags
& KO_MARKED_FOR_DELETE
)
91 ObDereferenceObject(Object
);
92 RtlFreeUnicodeString(&RemainingPath
);
93 DPRINT("Object marked for delete!\n");
94 return(STATUS_UNSUCCESSFUL
);
98 *Disposition
= REG_OPENED_EXISTING_KEY
;
100 Status
= ObCreateHandle(PsGetCurrentProcess(),
106 DPRINT("ObCreateHandle failed Status 0x%x\n", Status
);
107 ObDereferenceObject(Object
);
108 RtlFreeUnicodeString(&RemainingPath
);
112 /* If RemainingPath contains \ we must return error
113 because NtCreateKey don't create trees */
114 Start
= RemainingPath
.Buffer
;
118 End
= wcschr(Start
, L
'\\');
121 ObDereferenceObject(Object
);
122 RtlFreeUnicodeString(&RemainingPath
);
123 DPRINT1("NtCreateKey() can't create trees! (found \'\\\' in remaining path: \"%wZ\"!)\n", &RemainingPath
);
124 return STATUS_OBJECT_NAME_NOT_FOUND
;
127 DPRINT("RemainingPath %S ParentObject %x\n", RemainingPath
.Buffer
, Object
);
129 Status
= ObCreateObject(ExGetPreviousMode(),
138 if (!NT_SUCCESS(Status
))
140 DPRINT1("ObCreateObject() failed!\n");
144 Status
= ObInsertObject((PVOID
)KeyObject
,
150 if (!NT_SUCCESS(Status
))
152 ObDereferenceObject(KeyObject
);
153 RtlFreeUnicodeString(&RemainingPath
);
154 DPRINT1("ObInsertObject() failed!\n");
158 KeyObject
->ParentKey
= Object
;
160 if (CreateOptions
& REG_OPTION_VOLATILE
)
161 KeyObject
->RegistryHive
= CmiVolatileHive
;
163 KeyObject
->RegistryHive
= KeyObject
->ParentKey
->RegistryHive
;
165 KeyObject
->Flags
= 0;
166 KeyObject
->NumberOfSubKeys
= 0;
167 KeyObject
->SizeOfSubKeys
= 0;
168 KeyObject
->SubKeys
= NULL
;
170 /* Acquire hive lock */
171 KeEnterCriticalRegion();
172 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
174 /* add key to subkeys of parent if needed */
175 Status
= CmiAddSubKey(KeyObject
->RegistryHive
,
176 KeyObject
->ParentKey
,
182 if (!NT_SUCCESS(Status
))
184 DPRINT("CmiAddSubKey() failed (Status %lx)\n", Status
);
185 /* Release hive lock */
186 ExReleaseResourceLite(&CmiRegistryLock
);
187 KeLeaveCriticalRegion();
188 ObDereferenceObject(KeyObject
);
189 ObDereferenceObject(Object
);
190 RtlFreeUnicodeString(&RemainingPath
);
191 return STATUS_UNSUCCESSFUL
;
194 if (Start
== RemainingPath
.Buffer
)
196 KeyObject
->Name
= RemainingPath
;
200 RtlCreateUnicodeString(&KeyObject
->Name
,
202 RtlFreeUnicodeString(&RemainingPath
);
205 if (KeyObject
->RegistryHive
== KeyObject
->ParentKey
->RegistryHive
)
207 KeyObject
->KeyCell
->ParentKeyOffset
= KeyObject
->ParentKey
->KeyCellOffset
;
208 KeyObject
->KeyCell
->SecurityKeyOffset
= KeyObject
->ParentKey
->KeyCell
->SecurityKeyOffset
;
212 KeyObject
->KeyCell
->ParentKeyOffset
= -1;
213 KeyObject
->KeyCell
->SecurityKeyOffset
= -1;
214 /* This key must remain in memory unless it is deleted
215 or file is unloaded */
216 ObReferenceObjectByPointer(KeyObject
,
217 STANDARD_RIGHTS_REQUIRED
,
222 CmiAddKeyToList(KeyObject
->ParentKey
, KeyObject
);
224 VERIFY_KEY_OBJECT(KeyObject
);
226 /* Release hive lock */
227 ExReleaseResourceLite(&CmiRegistryLock
);
228 KeLeaveCriticalRegion();
230 ObDereferenceObject(KeyObject
);
231 ObDereferenceObject(Object
);
234 *Disposition
= REG_CREATED_NEW_KEY
;
243 NtDeleteKey(IN HANDLE KeyHandle
)
245 KPROCESSOR_MODE PreviousMode
;
246 PKEY_OBJECT KeyObject
;
249 DPRINT1("NtDeleteKey(KeyHandle %x) called\n", KeyHandle
);
251 PreviousMode
= ExGetPreviousMode();
253 /* Verify that the handle is valid and is a registry key */
254 Status
= ObReferenceObjectByHandle(KeyHandle
,
260 if (!NT_SUCCESS(Status
))
262 DPRINT1("ObReferenceObjectByHandle() failed (Status %lx)\n", Status
);
266 /* Acquire hive lock */
267 KeEnterCriticalRegion();
268 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
270 VERIFY_KEY_OBJECT(KeyObject
);
272 /* Check for subkeys */
273 if (KeyObject
->NumberOfSubKeys
!= 0)
275 Status
= STATUS_CANNOT_DELETE
;
279 /* Set the marked for delete bit in the key object */
280 KeyObject
->Flags
|= KO_MARKED_FOR_DELETE
;
281 Status
= STATUS_SUCCESS
;
284 /* Release hive lock */
285 ExReleaseResourceLite(&CmiRegistryLock
);
286 KeLeaveCriticalRegion();
288 DPRINT1("PointerCount %lu\n", ObGetObjectPointerCount((PVOID
)KeyObject
));
290 /* Dereference the object */
291 ObDereferenceObject(KeyObject
);
292 if (KeyObject
->RegistryHive
!= KeyObject
->ParentKey
->RegistryHive
)
293 ObDereferenceObject(KeyObject
);
295 DPRINT("PointerCount %lu\n", ObGetObjectPointerCount((PVOID
)KeyObject
));
296 DPRINT("HandleCount %lu\n", ObGetObjectHandleCount((PVOID
)KeyObject
));
300 * Hive-Synchronization will not be triggered here. This is done in
301 * CmiObjectDelete() (in regobj.c) after all key-related structures
302 * have been released.
310 NtEnumerateKey(IN HANDLE KeyHandle
,
312 IN KEY_INFORMATION_CLASS KeyInformationClass
,
313 OUT PVOID KeyInformation
,
315 OUT PULONG ResultLength
)
317 PKEY_OBJECT KeyObject
;
318 PKEY_OBJECT SubKeyObject
;
319 PREGISTRY_HIVE RegistryHive
;
320 PKEY_CELL KeyCell
, SubKeyCell
;
321 PHASH_TABLE_CELL HashTableBlock
;
322 PKEY_BASIC_INFORMATION BasicInformation
;
323 PKEY_NODE_INFORMATION NodeInformation
;
324 PKEY_FULL_INFORMATION FullInformation
;
325 PDATA_CELL ClassCell
;
326 ULONG NameSize
, ClassSize
;
329 DPRINT("KH %x I %d KIC %x KI %x L %d RL %x\n",
337 /* Verify that the handle is valid and is a registry key */
338 Status
= ObReferenceObjectByHandle(KeyHandle
,
339 KEY_ENUMERATE_SUB_KEYS
,
342 (PVOID
*) &KeyObject
,
344 if (!NT_SUCCESS(Status
))
346 DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status
);
350 /* Acquire hive lock */
351 KeEnterCriticalRegion();
352 ExAcquireResourceSharedLite(&CmiRegistryLock
, TRUE
);
354 VERIFY_KEY_OBJECT(KeyObject
);
356 /* Get pointer to KeyCell */
357 KeyCell
= KeyObject
->KeyCell
;
358 RegistryHive
= KeyObject
->RegistryHive
;
362 /* Check for hightest possible sub key index */
363 if (Index
>= KeyCell
->NumberOfSubKeys
+ KeyObject
->NumberOfSubKeys
)
365 ExReleaseResourceLite(&CmiRegistryLock
);
366 KeLeaveCriticalRegion();
367 ObDereferenceObject(KeyObject
);
368 DPRINT("No more volatile entries\n");
369 return STATUS_NO_MORE_ENTRIES
;
372 /* Get pointer to SubKey */
373 if (Index
>= KeyCell
->NumberOfSubKeys
)
375 PKEY_OBJECT CurKey
= NULL
;
379 /* Search for volatile or 'foreign' keys */
380 j
= KeyCell
->NumberOfSubKeys
;
381 for (i
= 0; i
< KeyObject
->NumberOfSubKeys
; i
++)
383 CurKey
= KeyObject
->SubKeys
[i
];
384 if (CurKey
->RegistryHive
== CmiVolatileHive
||
385 CurKey
->RegistryHive
!= RegistryHive
)
393 if (i
>= KeyObject
->NumberOfSubKeys
)
395 ExReleaseResourceLite(&CmiRegistryLock
);
396 KeLeaveCriticalRegion();
397 ObDereferenceObject(KeyObject
);
398 DPRINT("No more non-volatile entries\n");
399 return STATUS_NO_MORE_ENTRIES
;
402 SubKeyObject
= CurKey
;
403 SubKeyCell
= CurKey
->KeyCell
;
407 if (KeyCell
->HashTableOffset
== (BLOCK_OFFSET
)-1)
409 ExReleaseResourceLite(&CmiRegistryLock
);
410 KeLeaveCriticalRegion();
411 ObDereferenceObject(KeyObject
);
412 return STATUS_NO_MORE_ENTRIES
;
415 HashTableBlock
= CmiGetCell (RegistryHive
, KeyCell
->HashTableOffset
, NULL
);
416 if (HashTableBlock
== NULL
)
418 DPRINT("CmiGetBlock() failed\n");
419 ExReleaseResourceLite(&CmiRegistryLock
);
420 KeLeaveCriticalRegion();
421 ObDereferenceObject(KeyObject
);
422 return STATUS_UNSUCCESSFUL
;
425 SubKeyCell
= CmiGetKeyFromHashByIndex(RegistryHive
,
430 if (SubKeyCell
== NULL
)
432 ExReleaseResourceLite(&CmiRegistryLock
);
433 KeLeaveCriticalRegion();
434 ObDereferenceObject(KeyObject
);
435 DPRINT("No more entries\n");
436 return STATUS_NO_MORE_ENTRIES
;
439 Status
= STATUS_SUCCESS
;
440 switch (KeyInformationClass
)
442 case KeyBasicInformation
:
443 /* Check size of buffer */
444 if (SubKeyObject
!= NULL
)
446 NameSize
= SubKeyObject
->Name
.Length
;
450 NameSize
= SubKeyCell
->NameSize
;
451 if (SubKeyCell
->Flags
& REG_KEY_NAME_PACKED
)
453 NameSize
*= sizeof(WCHAR
);
457 *ResultLength
= FIELD_OFFSET(KEY_BASIC_INFORMATION
, Name
[0]) + NameSize
;
460 * NOTE: It's perfetly valid to call NtEnumerateKey to get
461 * all the information but name. Actually the NT4 sound
462 * framework does that while querying parameters from registry.
463 * -- Filip Navara, 19/07/2004
465 if (Length
< FIELD_OFFSET(KEY_BASIC_INFORMATION
, Name
[0]))
467 Status
= STATUS_BUFFER_TOO_SMALL
;
471 /* Fill buffer with requested info */
472 BasicInformation
= (PKEY_BASIC_INFORMATION
) KeyInformation
;
473 BasicInformation
->LastWriteTime
.u
.LowPart
= SubKeyCell
->LastWriteTime
.u
.LowPart
;
474 BasicInformation
->LastWriteTime
.u
.HighPart
= SubKeyCell
->LastWriteTime
.u
.HighPart
;
475 BasicInformation
->TitleIndex
= Index
;
476 BasicInformation
->NameLength
= NameSize
;
478 if (Length
- FIELD_OFFSET(KEY_BASIC_INFORMATION
, Name
[0]) < NameSize
)
480 NameSize
= Length
- FIELD_OFFSET(KEY_BASIC_INFORMATION
, Name
[0]);
481 Status
= STATUS_BUFFER_OVERFLOW
;
485 if (SubKeyObject
!= NULL
)
487 RtlCopyMemory(BasicInformation
->Name
,
488 SubKeyObject
->Name
.Buffer
,
493 if (SubKeyCell
->Flags
& REG_KEY_NAME_PACKED
)
495 CmiCopyPackedName(BasicInformation
->Name
,
497 NameSize
/ sizeof(WCHAR
));
501 RtlCopyMemory(BasicInformation
->Name
,
509 case KeyNodeInformation
:
510 /* Check size of buffer */
511 if (SubKeyObject
!= NULL
)
513 NameSize
= SubKeyObject
->Name
.Length
;
517 NameSize
= SubKeyCell
->NameSize
;
518 if (SubKeyCell
->Flags
& REG_KEY_NAME_PACKED
)
520 NameSize
*= sizeof(WCHAR
);
523 ClassSize
= SubKeyCell
->ClassSize
;
525 *ResultLength
= FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]) +
526 NameSize
+ ClassSize
;
528 if (Length
< FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]))
530 Status
= STATUS_BUFFER_TOO_SMALL
;
534 /* Fill buffer with requested info */
535 NodeInformation
= (PKEY_NODE_INFORMATION
) KeyInformation
;
536 NodeInformation
->LastWriteTime
.u
.LowPart
= SubKeyCell
->LastWriteTime
.u
.LowPart
;
537 NodeInformation
->LastWriteTime
.u
.HighPart
= SubKeyCell
->LastWriteTime
.u
.HighPart
;
538 NodeInformation
->TitleIndex
= Index
;
539 NodeInformation
->ClassOffset
= sizeof(KEY_NODE_INFORMATION
) + NameSize
;
540 NodeInformation
->ClassLength
= SubKeyCell
->ClassSize
;
541 NodeInformation
->NameLength
= NameSize
;
543 if (Length
- FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]) < NameSize
)
545 NameSize
= Length
- FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]);
547 Status
= STATUS_BUFFER_OVERFLOW
;
550 else if (Length
- FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]) -
551 NameSize
< ClassSize
)
553 ClassSize
= Length
- FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]) -
555 Status
= STATUS_BUFFER_OVERFLOW
;
559 if (SubKeyObject
!= NULL
)
561 RtlCopyMemory(NodeInformation
->Name
,
562 SubKeyObject
->Name
.Buffer
,
567 if (SubKeyCell
->Flags
& REG_KEY_NAME_PACKED
)
569 CmiCopyPackedName(NodeInformation
->Name
,
571 NameSize
/ sizeof(WCHAR
));
575 RtlCopyMemory(NodeInformation
->Name
,
583 ClassCell
= CmiGetCell (KeyObject
->RegistryHive
,
584 SubKeyCell
->ClassNameOffset
,
586 RtlCopyMemory (NodeInformation
->Name
+ SubKeyCell
->NameSize
,
593 case KeyFullInformation
:
594 ClassSize
= SubKeyCell
->ClassSize
;
596 *ResultLength
= FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
[0]) +
599 /* Check size of buffer */
600 if (Length
< FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
[0]))
602 Status
= STATUS_BUFFER_TOO_SMALL
;
606 /* Fill buffer with requested info */
607 FullInformation
= (PKEY_FULL_INFORMATION
) KeyInformation
;
608 FullInformation
->LastWriteTime
.u
.LowPart
= SubKeyCell
->LastWriteTime
.u
.LowPart
;
609 FullInformation
->LastWriteTime
.u
.HighPart
= SubKeyCell
->LastWriteTime
.u
.HighPart
;
610 FullInformation
->TitleIndex
= Index
;
611 FullInformation
->ClassOffset
= sizeof(KEY_FULL_INFORMATION
) -
613 FullInformation
->ClassLength
= SubKeyCell
->ClassSize
;
614 FullInformation
->SubKeys
= CmiGetNumberOfSubKeys(KeyObject
); //SubKeyCell->NumberOfSubKeys;
615 FullInformation
->MaxNameLen
= CmiGetMaxNameLength(KeyObject
);
616 FullInformation
->MaxClassLen
= CmiGetMaxClassLength(KeyObject
);
617 FullInformation
->Values
= SubKeyCell
->NumberOfValues
;
618 FullInformation
->MaxValueNameLen
=
619 CmiGetMaxValueNameLength(RegistryHive
, SubKeyCell
);
620 FullInformation
->MaxValueDataLen
=
621 CmiGetMaxValueDataLength(RegistryHive
, SubKeyCell
);
623 if (Length
- FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
[0]) < ClassSize
)
625 ClassSize
= Length
- FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
[0]);
626 Status
= STATUS_BUFFER_OVERFLOW
;
632 ClassCell
= CmiGetCell (KeyObject
->RegistryHive
,
633 SubKeyCell
->ClassNameOffset
,
635 RtlCopyMemory (FullInformation
->Class
,
643 DPRINT1("Not handling 0x%x\n", KeyInformationClass
);
647 ExReleaseResourceLite(&CmiRegistryLock
);
648 KeLeaveCriticalRegion();
649 ObDereferenceObject(KeyObject
);
651 DPRINT("Returning status %x\n", Status
);
658 NtEnumerateValueKey(IN HANDLE KeyHandle
,
660 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
,
661 OUT PVOID KeyValueInformation
,
663 OUT PULONG ResultLength
)
666 PKEY_OBJECT KeyObject
;
667 PREGISTRY_HIVE RegistryHive
;
669 PVALUE_CELL ValueCell
;
671 ULONG NameSize
, DataSize
;
672 PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation
;
673 PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation
;
674 PKEY_VALUE_FULL_INFORMATION ValueFullInformation
;
676 DPRINT("KH %x I %d KVIC %x KVI %x L %d RL %x\n",
679 KeyValueInformationClass
,
684 /* Verify that the handle is valid and is a registry key */
685 Status
= ObReferenceObjectByHandle(KeyHandle
,
689 (PVOID
*) &KeyObject
,
692 if (!NT_SUCCESS(Status
))
697 /* Acquire hive lock */
698 KeEnterCriticalRegion();
699 ExAcquireResourceSharedLite(&CmiRegistryLock
, TRUE
);
701 VERIFY_KEY_OBJECT(KeyObject
);
703 /* Get pointer to KeyCell */
704 KeyCell
= KeyObject
->KeyCell
;
705 RegistryHive
= KeyObject
->RegistryHive
;
707 /* Get Value block of interest */
708 Status
= CmiGetValueFromKeyByIndex(RegistryHive
,
713 if (!NT_SUCCESS(Status
))
715 ExReleaseResourceLite(&CmiRegistryLock
);
716 KeLeaveCriticalRegion();
717 ObDereferenceObject(KeyObject
);
721 if (ValueCell
!= NULL
)
723 switch (KeyValueInformationClass
)
725 case KeyValueBasicInformation
:
726 NameSize
= ValueCell
->NameSize
;
727 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
729 NameSize
*= sizeof(WCHAR
);
732 *ResultLength
= FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[0]) + NameSize
;
734 if (Length
< FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[0]))
736 Status
= STATUS_BUFFER_TOO_SMALL
;
740 ValueBasicInformation
= (PKEY_VALUE_BASIC_INFORMATION
)
742 ValueBasicInformation
->TitleIndex
= 0;
743 ValueBasicInformation
->Type
= ValueCell
->DataType
;
744 ValueBasicInformation
->NameLength
= NameSize
;
746 if (Length
- FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[0]) <
749 NameSize
= Length
- FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[0]);
750 Status
= STATUS_BUFFER_OVERFLOW
;
754 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
756 CmiCopyPackedName(ValueBasicInformation
->Name
,
758 NameSize
/ sizeof(WCHAR
));
762 RtlCopyMemory(ValueBasicInformation
->Name
,
769 case KeyValuePartialInformation
:
770 DataSize
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
772 *ResultLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) +
775 if (Length
< FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]))
777 Status
= STATUS_BUFFER_TOO_SMALL
;
781 ValuePartialInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)
783 ValuePartialInformation
->TitleIndex
= 0;
784 ValuePartialInformation
->Type
= ValueCell
->DataType
;
785 ValuePartialInformation
->DataLength
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
787 if (Length
- FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) <
790 DataSize
= Length
- FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]);
791 Status
= STATUS_BUFFER_OVERFLOW
;
795 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
))
797 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
798 RtlCopyMemory(ValuePartialInformation
->Data
,
804 RtlCopyMemory(ValuePartialInformation
->Data
,
805 &ValueCell
->DataOffset
,
811 case KeyValueFullInformation
:
812 NameSize
= ValueCell
->NameSize
;
813 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
815 NameSize
*= sizeof(WCHAR
);
817 DataSize
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
819 *ResultLength
= ROUND_UP(FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
,
820 Name
[0]) + NameSize
, sizeof(PVOID
)) + DataSize
;
822 if (Length
< FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]))
824 Status
= STATUS_BUFFER_TOO_SMALL
;
828 ValueFullInformation
= (PKEY_VALUE_FULL_INFORMATION
)
830 ValueFullInformation
->TitleIndex
= 0;
831 ValueFullInformation
->Type
= ValueCell
->DataType
;
832 ValueFullInformation
->NameLength
= NameSize
;
833 ValueFullInformation
->DataOffset
=
834 (ULONG_PTR
)ValueFullInformation
->Name
-
835 (ULONG_PTR
)ValueFullInformation
+
836 ValueFullInformation
->NameLength
;
837 ValueFullInformation
->DataOffset
=
838 ROUND_UP(ValueFullInformation
->DataOffset
, sizeof(PVOID
));
839 ValueFullInformation
->DataLength
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
841 if (Length
- FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]) <
844 NameSize
= Length
- FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]);
846 Status
= STATUS_BUFFER_OVERFLOW
;
849 else if (ROUND_UP(Length
- FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
,
850 Name
[0]) - NameSize
, sizeof(PVOID
)) < DataSize
)
852 DataSize
= ROUND_UP(Length
- FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]) - NameSize
, sizeof(PVOID
));
853 Status
= STATUS_BUFFER_OVERFLOW
;
857 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
859 CmiCopyPackedName(ValueFullInformation
->Name
,
861 NameSize
/ sizeof(WCHAR
));
865 RtlCopyMemory(ValueFullInformation
->Name
,
870 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
))
872 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
873 RtlCopyMemory((PCHAR
) ValueFullInformation
874 + ValueFullInformation
->DataOffset
,
875 DataCell
->Data
, DataSize
);
879 RtlCopyMemory((PCHAR
) ValueFullInformation
880 + ValueFullInformation
->DataOffset
,
881 &ValueCell
->DataOffset
, DataSize
);
887 DPRINT1("Not handling 0x%x\n", KeyValueInformationClass
);
893 Status
= STATUS_UNSUCCESSFUL
;
896 ExReleaseResourceLite(&CmiRegistryLock
);
897 KeLeaveCriticalRegion();
898 ObDereferenceObject(KeyObject
);
905 NtFlushKey(IN HANDLE KeyHandle
)
908 PKEY_OBJECT KeyObject
;
909 PREGISTRY_HIVE RegistryHive
;
910 KPROCESSOR_MODE PreviousMode
;
912 DPRINT("NtFlushKey (KeyHandle %lx) called\n", KeyHandle
);
914 PreviousMode
= ExGetPreviousMode();
916 /* Verify that the handle is valid and is a registry key */
917 Status
= ObReferenceObjectByHandle(KeyHandle
,
923 if (!NT_SUCCESS(Status
))
928 VERIFY_KEY_OBJECT(KeyObject
);
930 RegistryHive
= KeyObject
->RegistryHive
;
932 /* Acquire hive lock */
933 KeEnterCriticalRegion();
934 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
936 if (IsNoFileHive(RegistryHive
))
938 Status
= STATUS_SUCCESS
;
942 /* Flush non-volatile hive */
943 Status
= CmiFlushRegistryHive(RegistryHive
);
946 ExReleaseResourceLite(&CmiRegistryLock
);
947 KeLeaveCriticalRegion();
949 ObDereferenceObject(KeyObject
);
951 return STATUS_SUCCESS
;
956 NtOpenKey(OUT PHANDLE KeyHandle
,
957 IN ACCESS_MASK DesiredAccess
,
958 IN POBJECT_ATTRIBUTES ObjectAttributes
)
960 UNICODE_STRING RemainingPath
;
961 KPROCESSOR_MODE PreviousMode
;
964 NTSTATUS Status
= STATUS_SUCCESS
;
966 DPRINT("NtOpenKey(KH %x DA %x OA %x OA->ON '%wZ'\n",
970 ObjectAttributes
? ObjectAttributes
->ObjectName
: NULL
);
972 PreviousMode
= ExGetPreviousMode();
974 if(PreviousMode
!= KernelMode
)
978 ProbeForWrite(KeyHandle
,
984 Status
= _SEH_GetExceptionCode();
988 if(!NT_SUCCESS(Status
))
994 RemainingPath
.Buffer
= NULL
;
995 Status
= ObFindObject(ObjectAttributes
,
999 if (!NT_SUCCESS(Status
))
1004 VERIFY_KEY_OBJECT((PKEY_OBJECT
) Object
);
1006 DPRINT("RemainingPath '%wZ'\n", &RemainingPath
);
1008 if ((RemainingPath
.Buffer
!= NULL
) && (RemainingPath
.Buffer
[0] != 0))
1010 ObDereferenceObject(Object
);
1011 RtlFreeUnicodeString(&RemainingPath
);
1012 return STATUS_OBJECT_NAME_NOT_FOUND
;
1015 RtlFreeUnicodeString(&RemainingPath
);
1017 /* Fail if the key has been deleted */
1018 if (((PKEY_OBJECT
)Object
)->Flags
& KO_MARKED_FOR_DELETE
)
1020 ObDereferenceObject(Object
);
1021 return(STATUS_UNSUCCESSFUL
);
1024 Status
= ObCreateHandle(PsGetCurrentProcess(),
1029 ObDereferenceObject(Object
);
1031 if (!NT_SUCCESS(Status
))
1042 Status
= _SEH_GetExceptionCode();
1051 NtQueryKey(IN HANDLE KeyHandle
,
1052 IN KEY_INFORMATION_CLASS KeyInformationClass
,
1053 OUT PVOID KeyInformation
,
1055 OUT PULONG ResultLength
)
1057 PKEY_BASIC_INFORMATION BasicInformation
;
1058 PKEY_NODE_INFORMATION NodeInformation
;
1059 PKEY_FULL_INFORMATION FullInformation
;
1060 PREGISTRY_HIVE RegistryHive
;
1061 PDATA_CELL ClassCell
;
1062 PKEY_OBJECT KeyObject
;
1064 ULONG NameSize
, ClassSize
;
1067 DPRINT("NtQueryKey(KH %x KIC %x KI %x L %d RL %x)\n",
1069 KeyInformationClass
,
1074 /* Verify that the handle is valid and is a registry key */
1075 Status
= ObReferenceObjectByHandle(KeyHandle
,
1079 (PVOID
*) &KeyObject
,
1081 if (!NT_SUCCESS(Status
))
1086 /* Acquire hive lock */
1087 KeEnterCriticalRegion();
1088 ExAcquireResourceSharedLite(&CmiRegistryLock
, TRUE
);
1090 VERIFY_KEY_OBJECT(KeyObject
);
1092 /* Get pointer to KeyCell */
1093 KeyCell
= KeyObject
->KeyCell
;
1094 RegistryHive
= KeyObject
->RegistryHive
;
1096 Status
= STATUS_SUCCESS
;
1097 switch (KeyInformationClass
)
1099 case KeyBasicInformation
:
1100 NameSize
= KeyObject
->Name
.Length
;
1102 *ResultLength
= FIELD_OFFSET(KEY_BASIC_INFORMATION
, Name
[0]);
1104 /* Check size of buffer */
1105 if (Length
< FIELD_OFFSET(KEY_BASIC_INFORMATION
, Name
[0]))
1107 Status
= STATUS_BUFFER_TOO_SMALL
;
1111 /* Fill buffer with requested info */
1112 BasicInformation
= (PKEY_BASIC_INFORMATION
) KeyInformation
;
1113 BasicInformation
->LastWriteTime
.u
.LowPart
= KeyCell
->LastWriteTime
.u
.LowPart
;
1114 BasicInformation
->LastWriteTime
.u
.HighPart
= KeyCell
->LastWriteTime
.u
.HighPart
;
1115 BasicInformation
->TitleIndex
= 0;
1116 BasicInformation
->NameLength
= KeyObject
->Name
.Length
;
1118 if (Length
- FIELD_OFFSET(KEY_BASIC_INFORMATION
, Name
[0]) <
1121 NameSize
= Length
- FIELD_OFFSET(KEY_BASIC_INFORMATION
, Name
[0]);
1122 Status
= STATUS_BUFFER_OVERFLOW
;
1126 RtlCopyMemory(BasicInformation
->Name
,
1127 KeyObject
->Name
.Buffer
,
1132 case KeyNodeInformation
:
1133 NameSize
= KeyObject
->Name
.Length
;
1134 ClassSize
= KeyCell
->ClassSize
;
1136 *ResultLength
= FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]) +
1137 NameSize
+ ClassSize
;
1139 /* Check size of buffer */
1140 if (Length
< *ResultLength
)
1142 Status
= STATUS_BUFFER_TOO_SMALL
;
1146 /* Fill buffer with requested info */
1147 NodeInformation
= (PKEY_NODE_INFORMATION
) KeyInformation
;
1148 NodeInformation
->LastWriteTime
.u
.LowPart
= KeyCell
->LastWriteTime
.u
.LowPart
;
1149 NodeInformation
->LastWriteTime
.u
.HighPart
= KeyCell
->LastWriteTime
.u
.HighPart
;
1150 NodeInformation
->TitleIndex
= 0;
1151 NodeInformation
->ClassOffset
= sizeof(KEY_NODE_INFORMATION
) +
1152 KeyObject
->Name
.Length
;
1153 NodeInformation
->ClassLength
= KeyCell
->ClassSize
;
1154 NodeInformation
->NameLength
= KeyObject
->Name
.Length
;
1156 if (Length
- FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]) < NameSize
)
1158 NameSize
= Length
- FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]);
1160 Status
= STATUS_BUFFER_OVERFLOW
;
1163 else if (Length
- FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]) -
1164 NameSize
< ClassSize
)
1166 ClassSize
= Length
- FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]) -
1168 Status
= STATUS_BUFFER_OVERFLOW
;
1172 RtlCopyMemory(NodeInformation
->Name
,
1173 KeyObject
->Name
.Buffer
,
1178 ClassCell
= CmiGetCell (KeyObject
->RegistryHive
,
1179 KeyCell
->ClassNameOffset
,
1181 RtlCopyMemory (NodeInformation
->Name
+ KeyObject
->Name
.Length
,
1188 case KeyFullInformation
:
1189 ClassSize
= KeyCell
->ClassSize
;
1191 *ResultLength
= FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
) +
1194 /* Check size of buffer */
1195 if (Length
< FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
))
1197 Status
= STATUS_BUFFER_TOO_SMALL
;
1201 /* Fill buffer with requested info */
1202 FullInformation
= (PKEY_FULL_INFORMATION
) KeyInformation
;
1203 FullInformation
->LastWriteTime
.u
.LowPart
= KeyCell
->LastWriteTime
.u
.LowPart
;
1204 FullInformation
->LastWriteTime
.u
.HighPart
= KeyCell
->LastWriteTime
.u
.HighPart
;
1205 FullInformation
->TitleIndex
= 0;
1206 FullInformation
->ClassOffset
= sizeof(KEY_FULL_INFORMATION
) - sizeof(WCHAR
);
1207 FullInformation
->ClassLength
= KeyCell
->ClassSize
;
1208 FullInformation
->SubKeys
= CmiGetNumberOfSubKeys(KeyObject
); //KeyCell->NumberOfSubKeys;
1209 FullInformation
->MaxNameLen
= CmiGetMaxNameLength(KeyObject
);
1210 FullInformation
->MaxClassLen
= CmiGetMaxClassLength(KeyObject
);
1211 FullInformation
->Values
= KeyCell
->NumberOfValues
;
1212 FullInformation
->MaxValueNameLen
=
1213 CmiGetMaxValueNameLength(RegistryHive
, KeyCell
);
1214 FullInformation
->MaxValueDataLen
=
1215 CmiGetMaxValueDataLength(RegistryHive
, KeyCell
);
1217 if (Length
- FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
[0]) < ClassSize
)
1219 ClassSize
= Length
- FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
[0]);
1220 Status
= STATUS_BUFFER_OVERFLOW
;
1226 ClassCell
= CmiGetCell (KeyObject
->RegistryHive
,
1227 KeyCell
->ClassNameOffset
,
1229 RtlCopyMemory (FullInformation
->Class
,
1230 ClassCell
->Data
, ClassSize
);
1236 DPRINT1("Not handling 0x%x\n", KeyInformationClass
);
1237 Status
= STATUS_INVALID_INFO_CLASS
;
1241 ExReleaseResourceLite(&CmiRegistryLock
);
1242 KeLeaveCriticalRegion();
1243 ObDereferenceObject(KeyObject
);
1250 NtQueryValueKey(IN HANDLE KeyHandle
,
1251 IN PUNICODE_STRING ValueName
,
1252 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
,
1253 OUT PVOID KeyValueInformation
,
1255 OUT PULONG ResultLength
)
1258 ULONG NameSize
, DataSize
;
1259 PKEY_OBJECT KeyObject
;
1260 PREGISTRY_HIVE RegistryHive
;
1262 PVALUE_CELL ValueCell
;
1263 PDATA_CELL DataCell
;
1264 PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation
;
1265 PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation
;
1266 PKEY_VALUE_FULL_INFORMATION ValueFullInformation
;
1268 DPRINT("NtQueryValueKey(KeyHandle %x ValueName %S Length %x)\n",
1269 KeyHandle
, ValueName
->Buffer
, Length
);
1271 /* Verify that the handle is valid and is a registry key */
1272 Status
= ObReferenceObjectByHandle(KeyHandle
,
1276 (PVOID
*)&KeyObject
,
1279 if (!NT_SUCCESS(Status
))
1281 DPRINT1("ObReferenceObjectByHandle() failed with status %x\n", Status
);
1285 /* Acquire hive lock */
1286 KeEnterCriticalRegion();
1287 ExAcquireResourceSharedLite(&CmiRegistryLock
, TRUE
);
1289 VERIFY_KEY_OBJECT(KeyObject
);
1291 /* Get pointer to KeyCell */
1292 KeyCell
= KeyObject
->KeyCell
;
1293 RegistryHive
= KeyObject
->RegistryHive
;
1295 /* Get value cell by name */
1296 Status
= CmiScanKeyForValue(RegistryHive
,
1301 if (!NT_SUCCESS(Status
))
1303 DPRINT("CmiScanKeyForValue() failed with status %x\n", Status
);
1307 Status
= STATUS_SUCCESS
;
1308 switch (KeyValueInformationClass
)
1310 case KeyValueBasicInformation
:
1311 NameSize
= ValueCell
->NameSize
;
1312 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1314 NameSize
*= sizeof(WCHAR
);
1317 *ResultLength
= FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[0]) +
1320 if (Length
< FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[0]))
1322 Status
= STATUS_BUFFER_TOO_SMALL
;
1326 ValueBasicInformation
= (PKEY_VALUE_BASIC_INFORMATION
)
1327 KeyValueInformation
;
1328 ValueBasicInformation
->TitleIndex
= 0;
1329 ValueBasicInformation
->Type
= ValueCell
->DataType
;
1330 ValueBasicInformation
->NameLength
= NameSize
;
1332 if (Length
- FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[0]) <
1335 NameSize
= Length
- FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[0]);
1336 Status
= STATUS_BUFFER_OVERFLOW
;
1340 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1342 CmiCopyPackedName(ValueBasicInformation
->Name
,
1344 NameSize
/ sizeof(WCHAR
));
1348 RtlCopyMemory(ValueBasicInformation
->Name
,
1355 case KeyValuePartialInformation
:
1356 DataSize
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
1358 *ResultLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) +
1361 if (Length
< FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]))
1363 Status
= STATUS_BUFFER_TOO_SMALL
;
1367 ValuePartialInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)
1368 KeyValueInformation
;
1369 ValuePartialInformation
->TitleIndex
= 0;
1370 ValuePartialInformation
->Type
= ValueCell
->DataType
;
1371 ValuePartialInformation
->DataLength
= DataSize
;
1373 if (Length
- FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) <
1376 DataSize
= Length
- FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]);
1377 Status
= STATUS_BUFFER_OVERFLOW
;
1381 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
))
1383 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
1384 RtlCopyMemory(ValuePartialInformation
->Data
,
1390 RtlCopyMemory(ValuePartialInformation
->Data
,
1391 &ValueCell
->DataOffset
,
1397 case KeyValueFullInformation
:
1398 NameSize
= ValueCell
->NameSize
;
1399 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1401 NameSize
*= sizeof(WCHAR
);
1403 DataSize
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
1405 *ResultLength
= ROUND_UP(FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
,
1406 Name
[0]) + NameSize
, sizeof(PVOID
)) + DataSize
;
1408 if (Length
< FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]))
1410 Status
= STATUS_BUFFER_TOO_SMALL
;
1414 ValueFullInformation
= (PKEY_VALUE_FULL_INFORMATION
)
1415 KeyValueInformation
;
1416 ValueFullInformation
->TitleIndex
= 0;
1417 ValueFullInformation
->Type
= ValueCell
->DataType
;
1418 ValueFullInformation
->NameLength
= NameSize
;
1419 ValueFullInformation
->DataOffset
=
1420 (ULONG_PTR
)ValueFullInformation
->Name
-
1421 (ULONG_PTR
)ValueFullInformation
+
1422 ValueFullInformation
->NameLength
;
1423 ValueFullInformation
->DataOffset
=
1424 ROUND_UP(ValueFullInformation
->DataOffset
, sizeof(PVOID
));
1425 ValueFullInformation
->DataLength
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
1427 if (Length
- FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]) <
1430 NameSize
= Length
- FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]);
1432 Status
= STATUS_BUFFER_OVERFLOW
;
1435 else if (ROUND_UP(Length
- FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
,
1436 Name
[0]) - NameSize
, sizeof(PVOID
)) < DataSize
)
1438 DataSize
= ROUND_UP(Length
- FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
,
1439 Name
[0]) - NameSize
, sizeof(PVOID
));
1440 Status
= STATUS_BUFFER_OVERFLOW
;
1444 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1446 CmiCopyPackedName(ValueFullInformation
->Name
,
1448 NameSize
/ sizeof(WCHAR
));
1452 RtlCopyMemory(ValueFullInformation
->Name
,
1456 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
))
1458 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
1459 RtlCopyMemory((PCHAR
) ValueFullInformation
1460 + ValueFullInformation
->DataOffset
,
1466 RtlCopyMemory((PCHAR
) ValueFullInformation
1467 + ValueFullInformation
->DataOffset
,
1468 &ValueCell
->DataOffset
,
1475 DPRINT1("Not handling 0x%x\n", KeyValueInformationClass
);
1476 Status
= STATUS_INVALID_INFO_CLASS
;
1481 ExReleaseResourceLite(&CmiRegistryLock
);
1482 KeLeaveCriticalRegion();
1483 ObDereferenceObject(KeyObject
);
1490 NtSetValueKey(IN HANDLE KeyHandle
,
1491 IN PUNICODE_STRING ValueName
,
1492 IN ULONG TitleIndex
,
1498 PKEY_OBJECT KeyObject
;
1499 PREGISTRY_HIVE RegistryHive
;
1501 PVALUE_CELL ValueCell
;
1502 BLOCK_OFFSET ValueCellOffset
;
1503 PDATA_CELL DataCell
;
1504 PDATA_CELL NewDataCell
;
1506 ULONG DesiredAccess
;
1508 DPRINT("NtSetValueKey(KeyHandle %x ValueName '%wZ' Type %d)\n",
1509 KeyHandle
, ValueName
, Type
);
1511 DesiredAccess
= KEY_SET_VALUE
;
1512 if (Type
== REG_LINK
)
1513 DesiredAccess
|= KEY_CREATE_LINK
;
1515 /* Verify that the handle is valid and is a registry key */
1516 Status
= ObReferenceObjectByHandle(KeyHandle
,
1520 (PVOID
*)&KeyObject
,
1522 if (!NT_SUCCESS(Status
))
1525 /* Acquire hive lock exclucively */
1526 KeEnterCriticalRegion();
1527 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
1529 VERIFY_KEY_OBJECT(KeyObject
);
1531 /* Get pointer to key cell */
1532 KeyCell
= KeyObject
->KeyCell
;
1533 RegistryHive
= KeyObject
->RegistryHive
;
1534 Status
= CmiScanKeyForValue(RegistryHive
,
1539 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1541 DPRINT("Allocate new value cell\n");
1542 Status
= CmiAddValueToKey(RegistryHive
,
1544 KeyObject
->KeyCellOffset
,
1550 if (!NT_SUCCESS(Status
))
1552 DPRINT("Cannot add value. Status 0x%X\n", Status
);
1554 ExReleaseResourceLite(&CmiRegistryLock
);
1555 KeLeaveCriticalRegion();
1556 ObDereferenceObject(KeyObject
);
1560 DPRINT("DataSize %lu\n", DataSize
);
1561 DPRINT("ValueCell %p\n", ValueCell
);
1562 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
1564 if (DataSize
<= sizeof(BLOCK_OFFSET
))
1566 /* If data size <= sizeof(BLOCK_OFFSET) then store data in the data offset */
1567 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
1568 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
) &&
1569 (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
) != 0)
1571 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
1572 CmiDestroyCell(RegistryHive
, DataCell
, ValueCell
->DataOffset
);
1575 RtlCopyMemory(&ValueCell
->DataOffset
, Data
, DataSize
);
1576 ValueCell
->DataSize
= DataSize
| REG_DATA_IN_OFFSET
;
1577 ValueCell
->DataType
= Type
;
1578 RtlMoveMemory(&ValueCell
->DataOffset
, Data
, DataSize
);
1579 CmiMarkBlockDirty(RegistryHive
, ValueCellOffset
);
1581 else if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
) &&
1582 (DataSize
<= (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
)))
1584 /* If new data size is <= current then overwrite current data */
1585 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
,&pBin
);
1586 RtlZeroMemory(DataCell
->Data
, ValueCell
->DataSize
);
1587 RtlCopyMemory(DataCell
->Data
, Data
, DataSize
);
1588 ValueCell
->DataSize
= DataSize
;
1589 ValueCell
->DataType
= Type
;
1594 * New data size is larger than the current, destroy current
1595 * data block and allocate a new one.
1597 BLOCK_OFFSET NewOffset
;
1599 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
1601 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
) &&
1602 (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
) != 0)
1604 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
1605 CmiDestroyCell(RegistryHive
, DataCell
, ValueCell
->DataOffset
);
1606 ValueCell
->DataSize
= 0;
1607 ValueCell
->DataType
= 0;
1608 ValueCell
->DataOffset
= (BLOCK_OFFSET
)-1;
1611 Status
= CmiAllocateCell (RegistryHive
,
1612 sizeof(CELL_HEADER
) + DataSize
,
1613 (PVOID
*)&NewDataCell
,
1615 if (!NT_SUCCESS(Status
))
1617 DPRINT("CmiAllocateBlock() failed (Status %lx)\n", Status
);
1619 ExReleaseResourceLite(&CmiRegistryLock
);
1620 KeLeaveCriticalRegion();
1621 ObDereferenceObject(KeyObject
);
1626 RtlCopyMemory(&NewDataCell
->Data
[0], Data
, DataSize
);
1627 ValueCell
->DataSize
= DataSize
& REG_DATA_SIZE_MASK
;
1628 ValueCell
->DataType
= Type
;
1629 ValueCell
->DataOffset
= NewOffset
;
1630 CmiMarkBlockDirty(RegistryHive
, ValueCell
->DataOffset
);
1631 CmiMarkBlockDirty(RegistryHive
, ValueCellOffset
);
1635 if ((Type
== REG_LINK
) &&
1636 (_wcsicmp(ValueName
->Buffer
, L
"SymbolicLinkValue") == 0))
1638 KeyCell
->Flags
|= REG_KEY_LINK_CELL
;
1641 NtQuerySystemTime (&KeyCell
->LastWriteTime
);
1642 CmiMarkBlockDirty (RegistryHive
, KeyObject
->KeyCellOffset
);
1644 ExReleaseResourceLite(&CmiRegistryLock
);
1645 KeLeaveCriticalRegion();
1646 ObDereferenceObject(KeyObject
);
1650 DPRINT("Return Status 0x%X\n", Status
);
1657 NtDeleteValueKey (IN HANDLE KeyHandle
,
1658 IN PUNICODE_STRING ValueName
)
1660 PKEY_OBJECT KeyObject
;
1663 /* Verify that the handle is valid and is a registry key */
1664 Status
= ObReferenceObjectByHandle(KeyHandle
,
1668 (PVOID
*)&KeyObject
,
1670 if (!NT_SUCCESS(Status
))
1675 /* Acquire hive lock */
1676 KeEnterCriticalRegion();
1677 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
1679 VERIFY_KEY_OBJECT(KeyObject
);
1681 Status
= CmiDeleteValueFromKey(KeyObject
->RegistryHive
,
1683 KeyObject
->KeyCellOffset
,
1686 NtQuerySystemTime (&KeyObject
->KeyCell
->LastWriteTime
);
1687 CmiMarkBlockDirty (KeyObject
->RegistryHive
, KeyObject
->KeyCellOffset
);
1689 /* Release hive lock */
1690 ExReleaseResourceLite(&CmiRegistryLock
);
1691 KeLeaveCriticalRegion();
1693 ObDereferenceObject (KeyObject
);
1703 * KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
1704 * KeyObjectAttributes->Name specifies the name of the key to load.
1707 NtLoadKey (IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
1708 IN POBJECT_ATTRIBUTES FileObjectAttributes
)
1710 return NtLoadKey2 (KeyObjectAttributes
,
1711 FileObjectAttributes
,
1718 * KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
1719 * KeyObjectAttributes->Name specifies the name of the key to load.
1720 * Flags can be 0 or REG_NO_LAZY_FLUSH.
1723 NtLoadKey2 (IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
1724 IN POBJECT_ATTRIBUTES FileObjectAttributes
,
1727 POBJECT_NAME_INFORMATION NameInfo
;
1728 PUNICODE_STRING NamePointer
;
1734 DPRINT ("NtLoadKey2() called\n");
1737 if (!SeSinglePrivilegeCheck (SeRestorePrivilege
, KeGetPreviousMode ()))
1738 return STATUS_PRIVILEGE_NOT_HELD
;
1741 if (FileObjectAttributes
->RootDirectory
!= NULL
)
1744 sizeof(OBJECT_NAME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
);
1745 Buffer
= ExAllocatePool (NonPagedPool
,
1748 return STATUS_INSUFFICIENT_RESOURCES
;
1750 Status
= NtQueryObject (FileObjectAttributes
->RootDirectory
,
1751 ObjectNameInformation
,
1755 if (!NT_SUCCESS(Status
))
1757 DPRINT1 ("NtQueryObject() failed (Status %lx)\n", Status
);
1758 ExFreePool (Buffer
);
1762 NameInfo
= (POBJECT_NAME_INFORMATION
)Buffer
;
1763 DPRINT ("ObjectPath: '%wZ' Length %hu\n",
1764 &NameInfo
->Name
, NameInfo
->Name
.Length
);
1766 NameInfo
->Name
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
1767 if (FileObjectAttributes
->ObjectName
->Buffer
[0] != L
'\\')
1769 RtlAppendUnicodeToString (&NameInfo
->Name
,
1771 DPRINT ("ObjectPath: '%wZ' Length %hu\n",
1772 &NameInfo
->Name
, NameInfo
->Name
.Length
);
1774 RtlAppendUnicodeStringToString (&NameInfo
->Name
,
1775 FileObjectAttributes
->ObjectName
);
1777 DPRINT ("ObjectPath: '%wZ' Length %hu\n",
1778 &NameInfo
->Name
, NameInfo
->Name
.Length
);
1779 NamePointer
= &NameInfo
->Name
;
1783 if (FileObjectAttributes
->ObjectName
->Buffer
[0] == L
'\\')
1786 NamePointer
= FileObjectAttributes
->ObjectName
;
1791 sizeof(OBJECT_NAME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
);
1792 Buffer
= ExAllocatePool (NonPagedPool
,
1795 return STATUS_INSUFFICIENT_RESOURCES
;
1797 NameInfo
= (POBJECT_NAME_INFORMATION
)Buffer
;
1798 NameInfo
->Name
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
1799 NameInfo
->Name
.Length
= 0;
1800 NameInfo
->Name
.Buffer
= (PWSTR
)((ULONG_PTR
)Buffer
+ sizeof(OBJECT_NAME_INFORMATION
));
1801 NameInfo
->Name
.Buffer
[0] = 0;
1803 RtlAppendUnicodeToString (&NameInfo
->Name
,
1805 RtlAppendUnicodeStringToString (&NameInfo
->Name
,
1806 FileObjectAttributes
->ObjectName
);
1808 NamePointer
= &NameInfo
->Name
;
1812 DPRINT ("Full name: '%wZ'\n", NamePointer
);
1814 /* Acquire hive lock */
1815 KeEnterCriticalRegion();
1816 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
1818 Status
= CmiLoadHive (KeyObjectAttributes
,
1821 if (!NT_SUCCESS (Status
))
1823 DPRINT1 ("CmiLoadHive() failed (Status %lx)\n", Status
);
1826 /* Release hive lock */
1827 ExReleaseResourceLite(&CmiRegistryLock
);
1828 KeLeaveCriticalRegion();
1831 ExFreePool (Buffer
);
1838 NtNotifyChangeKey (IN HANDLE KeyHandle
,
1840 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1841 IN PVOID ApcContext OPTIONAL
,
1842 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1843 IN ULONG CompletionFilter
,
1844 IN BOOLEAN WatchSubtree
,
1847 IN BOOLEAN Asynchronous
)
1850 return(STATUS_NOT_IMPLEMENTED
);
1855 NtQueryMultipleValueKey (IN HANDLE KeyHandle
,
1856 IN OUT PKEY_VALUE_ENTRY ValueList
,
1857 IN ULONG NumberOfValues
,
1859 IN OUT PULONG Length
,
1860 OUT PULONG ReturnLength
)
1862 PREGISTRY_HIVE RegistryHive
;
1863 PVALUE_CELL ValueCell
;
1864 PKEY_OBJECT KeyObject
;
1865 PDATA_CELL DataCell
;
1866 ULONG BufferLength
= 0;
1872 /* Verify that the handle is valid and is a registry key */
1873 Status
= ObReferenceObjectByHandle(KeyHandle
,
1877 (PVOID
*) &KeyObject
,
1879 if (!NT_SUCCESS(Status
))
1881 DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status
);
1885 /* Acquire hive lock */
1886 KeEnterCriticalRegion();
1887 ExAcquireResourceSharedLite(&CmiRegistryLock
, TRUE
);
1889 VERIFY_KEY_OBJECT(KeyObject
);
1891 /* Get pointer to KeyCell */
1892 KeyCell
= KeyObject
->KeyCell
;
1893 RegistryHive
= KeyObject
->RegistryHive
;
1895 DataPtr
= (PUCHAR
) Buffer
;
1897 for (i
= 0; i
< NumberOfValues
; i
++)
1899 DPRINT("ValueName: '%wZ'\n", ValueList
[i
].ValueName
);
1901 /* Get Value block of interest */
1902 Status
= CmiScanKeyForValue(RegistryHive
,
1904 ValueList
[i
].ValueName
,
1908 if (!NT_SUCCESS(Status
))
1910 DPRINT("CmiScanKeyForValue() failed with status %x\n", Status
);
1913 else if (ValueCell
== NULL
)
1915 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
1919 BufferLength
= ROUND_UP(BufferLength
, sizeof(PVOID
));
1921 if (BufferLength
+ (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
) <= *Length
)
1923 DataPtr
= (PUCHAR
)ROUND_UP((ULONG_PTR
)DataPtr
, sizeof(PVOID
));
1925 ValueList
[i
].Type
= ValueCell
->DataType
;
1926 ValueList
[i
].DataLength
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
1927 ValueList
[i
].DataOffset
= (ULONG_PTR
)DataPtr
- (ULONG_PTR
)Buffer
;
1929 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
))
1931 DataCell
= CmiGetCell (RegistryHive
,
1932 ValueCell
->DataOffset
,
1934 RtlCopyMemory(DataPtr
,
1936 ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
1940 RtlCopyMemory(DataPtr
,
1941 &ValueCell
->DataOffset
,
1942 ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
1945 DataPtr
+= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
1949 Status
= STATUS_BUFFER_TOO_SMALL
;
1952 BufferLength
+= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
1955 if (NT_SUCCESS(Status
))
1956 *Length
= BufferLength
;
1958 *ReturnLength
= BufferLength
;
1960 /* Release hive lock */
1961 ExReleaseResourceLite(&CmiRegistryLock
);
1962 KeLeaveCriticalRegion();
1964 ObDereferenceObject(KeyObject
);
1966 DPRINT("Return Status 0x%X\n", Status
);
1973 NtReplaceKey (IN POBJECT_ATTRIBUTES ObjectAttributes
,
1975 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes
)
1978 return(STATUS_NOT_IMPLEMENTED
);
1983 NtRestoreKey (IN HANDLE KeyHandle
,
1984 IN HANDLE FileHandle
,
1985 IN ULONG RestoreFlags
)
1988 return(STATUS_NOT_IMPLEMENTED
);
1993 NtSaveKey (IN HANDLE KeyHandle
,
1994 IN HANDLE FileHandle
)
1996 PREGISTRY_HIVE TempHive
;
1997 PKEY_OBJECT KeyObject
;
2000 DPRINT ("NtSaveKey() called\n");
2003 if (!SeSinglePrivilegeCheck (SeBackupPrivilege
, KeGetPreviousMode ()))
2004 return STATUS_PRIVILEGE_NOT_HELD
;
2007 Status
= ObReferenceObjectByHandle (KeyHandle
,
2010 KeGetPreviousMode(),
2011 (PVOID
*)&KeyObject
,
2013 if (!NT_SUCCESS(Status
))
2015 DPRINT1 ("ObReferenceObjectByHandle() failed (Status %lx)\n", Status
);
2019 /* Acquire hive lock exclucively */
2020 KeEnterCriticalRegion();
2021 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
2023 /* Refuse to save a volatile key */
2024 if (KeyObject
->RegistryHive
== CmiVolatileHive
)
2026 DPRINT1 ("Cannot save a volatile key\n");
2027 ExReleaseResourceLite(&CmiRegistryLock
);
2028 KeLeaveCriticalRegion();
2029 ObDereferenceObject (KeyObject
);
2030 return STATUS_ACCESS_DENIED
;
2033 Status
= CmiCreateTempHive(&TempHive
);
2034 if (!NT_SUCCESS(Status
))
2036 DPRINT1 ("CmiCreateTempHive() failed (Status %lx)\n", Status
);
2037 ExReleaseResourceLite(&CmiRegistryLock
);
2038 KeLeaveCriticalRegion();
2039 ObDereferenceObject (KeyObject
);
2043 Status
= CmiCopyKey (TempHive
,
2045 KeyObject
->RegistryHive
,
2046 KeyObject
->KeyCell
);
2047 if (!NT_SUCCESS(Status
))
2049 DPRINT1 ("CmiCopyKey() failed (Status %lx)\n", Status
);
2050 CmiRemoveRegistryHive (TempHive
);
2051 ExReleaseResourceLite(&CmiRegistryLock
);
2052 KeLeaveCriticalRegion();
2053 ObDereferenceObject (KeyObject
);
2057 Status
= CmiSaveTempHive (TempHive
,
2059 if (!NT_SUCCESS(Status
))
2061 DPRINT1 ("CmiSaveTempHive() failed (Status %lx)\n", Status
);
2064 CmiRemoveRegistryHive (TempHive
);
2066 /* Release hive lock */
2067 ExReleaseResourceLite(&CmiRegistryLock
);
2068 KeLeaveCriticalRegion();
2070 ObDereferenceObject (KeyObject
);
2072 DPRINT ("NtSaveKey() done\n");
2074 return STATUS_SUCCESS
;
2083 IN HANDLE KeyHandle
,
2084 IN HANDLE FileHandle
,
2085 IN ULONG Flags
// REG_STANDARD_FORMAT, etc..
2089 return STATUS_NOT_IMPLEMENTED
;
2094 NtSetInformationKey (IN HANDLE KeyHandle
,
2095 IN KEY_SET_INFORMATION_CLASS KeyInformationClass
,
2096 IN PVOID KeyInformation
,
2097 IN ULONG KeyInformationLength
)
2099 PKEY_OBJECT KeyObject
;
2102 if (KeyInformationClass
!= KeyWriteTimeInformation
)
2103 return STATUS_INVALID_INFO_CLASS
;
2105 if (KeyInformationLength
!= sizeof (KEY_WRITE_TIME_INFORMATION
))
2106 return STATUS_INFO_LENGTH_MISMATCH
;
2108 /* Verify that the handle is valid and is a registry key */
2109 Status
= ObReferenceObjectByHandle (KeyHandle
,
2113 (PVOID
*)&KeyObject
,
2115 if (!NT_SUCCESS (Status
))
2117 DPRINT ("ObReferenceObjectByHandle() failed with status %x\n", Status
);
2121 /* Acquire hive lock */
2122 KeEnterCriticalRegion();
2123 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
2125 VERIFY_KEY_OBJECT(KeyObject
);
2127 KeyObject
->KeyCell
->LastWriteTime
.QuadPart
=
2128 ((PKEY_WRITE_TIME_INFORMATION
)KeyInformation
)->LastWriteTime
.QuadPart
;
2130 CmiMarkBlockDirty (KeyObject
->RegistryHive
,
2131 KeyObject
->KeyCellOffset
);
2133 /* Release hive lock */
2134 ExReleaseResourceLite(&CmiRegistryLock
);
2135 KeLeaveCriticalRegion();
2137 ObDereferenceObject (KeyObject
);
2141 DPRINT ("NtSaveKey() done\n");
2143 return STATUS_SUCCESS
;
2149 * KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
2150 * KeyObjectAttributes->Name specifies the name of the key to unload.
2153 NtUnloadKey (IN POBJECT_ATTRIBUTES KeyObjectAttributes
)
2155 PREGISTRY_HIVE RegistryHive
;
2158 DPRINT ("NtUnloadKey() called\n");
2161 if (!SeSinglePrivilegeCheck (SeRestorePrivilege
, KeGetPreviousMode ()))
2162 return STATUS_PRIVILEGE_NOT_HELD
;
2165 /* Acquire registry lock exclusively */
2166 KeEnterCriticalRegion();
2167 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
2169 Status
= CmiDisconnectHive (KeyObjectAttributes
,
2171 if (!NT_SUCCESS (Status
))
2173 DPRINT1 ("CmiDisconnectHive() failed (Status %lx)\n", Status
);
2174 ExReleaseResourceLite (&CmiRegistryLock
);
2175 KeLeaveCriticalRegion();
2179 DPRINT ("RegistryHive %p\n", RegistryHive
);
2183 if (!IsNoFileHive (RegistryHive
))
2184 CmiFlushRegistryHive (RegistryHive
);
2187 CmiRemoveRegistryHive (RegistryHive
);
2189 /* Release registry lock */
2190 ExReleaseResourceLite (&CmiRegistryLock
);
2191 KeLeaveCriticalRegion();
2193 DPRINT ("NtUnloadKey() done\n");
2195 return STATUS_SUCCESS
;
2200 NtInitializeRegistry (IN BOOLEAN SetUpBoot
)
2204 if (CmiRegistryInitialized
== TRUE
)
2205 return STATUS_ACCESS_DENIED
;
2207 /* Save boot log file */
2208 IopSaveBootLogToFile();
2210 Status
= CmiInitHives (SetUpBoot
);
2212 CmiRegistryInitialized
= TRUE
;