2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/cm/ntfunc.c
5 * PURPOSE: Ntxxx function for registry access
9 /* INCLUDES *****************************************************************/
11 #define NTOS_MODE_KERNEL
15 #include <internal/ob.h>
16 #include <internal/se.h>
19 #include <internal/debug.h>
24 /* GLOBALS ******************************************************************/
26 extern POBJECT_TYPE CmiKeyType
;
27 extern PREGISTRY_HIVE CmiVolatileHive
;
29 static BOOLEAN CmiRegistryInitialized
= FALSE
;
32 /* FUNCTIONS ****************************************************************/
35 NtCreateKey(OUT PHANDLE KeyHandle
,
36 IN ACCESS_MASK DesiredAccess
,
37 IN POBJECT_ATTRIBUTES ObjectAttributes
,
39 IN PUNICODE_STRING Class
,
40 IN ULONG CreateOptions
,
41 OUT PULONG Disposition
)
43 UNICODE_STRING RemainingPath
;
44 PKEY_OBJECT KeyObject
;
50 DPRINT("NtCreateKey (Name %wZ KeyHandle %x Root %x)\n",
51 ObjectAttributes
->ObjectName
,
53 ObjectAttributes
->RootDirectory
);
55 Status
= ObFindObject(ObjectAttributes
,
59 if (!NT_SUCCESS(Status
))
64 DPRINT("RemainingPath %wZ\n", &RemainingPath
);
66 if ((RemainingPath
.Buffer
== NULL
) || (RemainingPath
.Buffer
[0] == 0))
68 /* Fail if the key has been deleted */
69 if (((PKEY_OBJECT
) Object
)->Flags
& KO_MARKED_FOR_DELETE
)
71 ObDereferenceObject(Object
);
72 return(STATUS_UNSUCCESSFUL
);
76 *Disposition
= REG_OPENED_EXISTING_KEY
;
78 Status
= ObCreateHandle(PsGetCurrentProcess(),
84 DPRINT("Status %x\n", Status
);
85 ObDereferenceObject(Object
);
89 /* If RemainingPath contains \ we must return error
90 because NtCreateKey don't create trees */
91 Start
= RemainingPath
.Buffer
;
95 End
= wcschr(Start
, L
'\\');
98 ObDereferenceObject(Object
);
99 return STATUS_OBJECT_NAME_NOT_FOUND
;
102 DPRINT("RemainingPath %S ParentObject %x\n", RemainingPath
.Buffer
, Object
);
104 Status
= ObCreateObject(ExGetPreviousMode(),
113 if (!NT_SUCCESS(Status
))
118 Status
= ObInsertObject((PVOID
)KeyObject
,
124 if (!NT_SUCCESS(Status
))
126 ObDereferenceObject(KeyObject
);
130 KeyObject
->ParentKey
= Object
;
132 if (CreateOptions
& REG_OPTION_VOLATILE
)
133 KeyObject
->RegistryHive
= CmiVolatileHive
;
135 KeyObject
->RegistryHive
= KeyObject
->ParentKey
->RegistryHive
;
137 KeyObject
->Flags
= 0;
138 KeyObject
->NumberOfSubKeys
= 0;
139 KeyObject
->SizeOfSubKeys
= 0;
140 KeyObject
->SubKeys
= NULL
;
142 /* Acquire hive lock */
143 KeEnterCriticalRegion();
144 ExAcquireResourceExclusiveLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
146 /* add key to subkeys of parent if needed */
147 Status
= CmiAddSubKey(KeyObject
->RegistryHive
,
148 KeyObject
->ParentKey
,
154 if (!NT_SUCCESS(Status
))
156 DPRINT("CmiAddSubKey() failed (Status %lx)\n", Status
);
157 /* Release hive lock */
158 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
159 KeLeaveCriticalRegion();
160 ObDereferenceObject(KeyObject
);
161 ObDereferenceObject(Object
);
162 return STATUS_UNSUCCESSFUL
;
165 RtlCreateUnicodeString(&KeyObject
->Name
,
168 if (KeyObject
->RegistryHive
== KeyObject
->ParentKey
->RegistryHive
)
170 KeyObject
->KeyCell
->ParentKeyOffset
= KeyObject
->ParentKey
->KeyCellOffset
;
171 KeyObject
->KeyCell
->SecurityKeyOffset
= KeyObject
->ParentKey
->KeyCell
->SecurityKeyOffset
;
175 KeyObject
->KeyCell
->ParentKeyOffset
= -1;
176 KeyObject
->KeyCell
->SecurityKeyOffset
= -1;
177 /* This key must remain in memory unless it is deleted
178 or file is unloaded */
179 ObReferenceObjectByPointer(KeyObject
,
180 STANDARD_RIGHTS_REQUIRED
,
185 CmiAddKeyToList(KeyObject
->ParentKey
, KeyObject
);
187 VERIFY_KEY_OBJECT(KeyObject
);
189 /* Release hive lock */
190 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
191 KeLeaveCriticalRegion();
193 ObDereferenceObject(KeyObject
);
194 ObDereferenceObject(Object
);
197 *Disposition
= REG_CREATED_NEW_KEY
;
206 NtDeleteKey(IN HANDLE KeyHandle
)
208 PKEY_OBJECT KeyObject
;
211 DPRINT("KeyHandle %x\n", KeyHandle
);
213 /* Verify that the handle is valid and is a registry key */
214 Status
= ObReferenceObjectByHandle(KeyHandle
,
220 if (!NT_SUCCESS(Status
))
225 /* Acquire hive lock */
226 KeEnterCriticalRegion();
227 ExAcquireResourceExclusiveLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
229 VERIFY_KEY_OBJECT(KeyObject
);
231 /* Check for subkeys */
232 if (KeyObject
->NumberOfSubKeys
!= 0)
234 Status
= STATUS_CANNOT_DELETE
;
238 /* Set the marked for delete bit in the key object */
239 KeyObject
->Flags
|= KO_MARKED_FOR_DELETE
;
240 Status
= STATUS_SUCCESS
;
243 /* Release hive lock */
244 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
245 KeLeaveCriticalRegion();
247 DPRINT("PointerCount %lu\n", ObGetObjectPointerCount((PVOID
)KeyObject
));
249 /* Dereference the object */
250 ObDereferenceObject(KeyObject
);
251 if(KeyObject
->RegistryHive
!= KeyObject
->ParentKey
->RegistryHive
)
252 ObDereferenceObject(KeyObject
);
254 DPRINT("PointerCount %lu\n", ObGetObjectPointerCount((PVOID
)KeyObject
));
258 * Hive-Synchronization will not be triggered here. This is done in
259 * CmiObjectDelete() (in regobj.c) after all key-related structures
260 * have been released.
268 NtEnumerateKey(IN HANDLE KeyHandle
,
270 IN KEY_INFORMATION_CLASS KeyInformationClass
,
271 OUT PVOID KeyInformation
,
273 OUT PULONG ResultLength
)
275 PKEY_OBJECT KeyObject
;
276 PREGISTRY_HIVE RegistryHive
;
277 PKEY_CELL KeyCell
, SubKeyCell
;
278 PHASH_TABLE_CELL HashTableBlock
;
279 PKEY_BASIC_INFORMATION BasicInformation
;
280 PKEY_NODE_INFORMATION NodeInformation
;
281 PKEY_FULL_INFORMATION FullInformation
;
282 PDATA_CELL ClassCell
;
286 DPRINT("KH %x I %d KIC %x KI %x L %d RL %x\n",
294 /* Verify that the handle is valid and is a registry key */
295 Status
= ObReferenceObjectByHandle(KeyHandle
,
296 KEY_ENUMERATE_SUB_KEYS
,
299 (PVOID
*) &KeyObject
,
301 if (!NT_SUCCESS(Status
))
303 DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status
);
307 /* Acquire hive lock */
308 KeEnterCriticalRegion();
309 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
311 VERIFY_KEY_OBJECT(KeyObject
);
313 /* Get pointer to KeyCell */
314 KeyCell
= KeyObject
->KeyCell
;
315 RegistryHive
= KeyObject
->RegistryHive
;
317 /* Get pointer to SubKey */
318 if (Index
>= KeyCell
->NumberOfSubKeys
)
320 if (RegistryHive
== CmiVolatileHive
)
322 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
323 KeLeaveCriticalRegion();
324 ObDereferenceObject(KeyObject
);
325 DPRINT("No more volatile entries\n");
326 return(STATUS_NO_MORE_ENTRIES
);
331 PKEY_OBJECT CurKey
= NULL
;
333 /* Search volatile keys */
334 for (i
= 0; i
< KeyObject
->NumberOfSubKeys
; i
++)
336 CurKey
= KeyObject
->SubKeys
[i
];
337 if (CurKey
->RegistryHive
== CmiVolatileHive
)
339 if (Index
-- == KeyCell
->NumberOfSubKeys
)
343 if (Index
>= KeyCell
->NumberOfSubKeys
)
345 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
346 KeLeaveCriticalRegion();
347 ObDereferenceObject(KeyObject
);
348 DPRINT("No more non-volatile entries\n");
349 return(STATUS_NO_MORE_ENTRIES
);
351 SubKeyCell
= CurKey
->KeyCell
;
356 if (KeyCell
->HashTableOffset
== (BLOCK_OFFSET
)-1)
358 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
359 KeLeaveCriticalRegion();
360 ObDereferenceObject(KeyObject
);
361 return(STATUS_NO_MORE_ENTRIES
);
364 HashTableBlock
= CmiGetCell (RegistryHive
, KeyCell
->HashTableOffset
, NULL
);
365 if (HashTableBlock
== NULL
)
367 DPRINT("CmiGetBlock() failed\n");
368 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
369 KeLeaveCriticalRegion();
370 ObDereferenceObject(KeyObject
);
371 return STATUS_UNSUCCESSFUL
;
373 SubKeyCell
= CmiGetKeyFromHashByIndex(RegistryHive
,
378 if (SubKeyCell
== NULL
)
380 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
381 KeLeaveCriticalRegion();
382 ObDereferenceObject(KeyObject
);
383 DPRINT("No more entries\n");
384 return(STATUS_NO_MORE_ENTRIES
);
387 Status
= STATUS_SUCCESS
;
388 switch (KeyInformationClass
)
390 case KeyBasicInformation
:
391 /* Check size of buffer */
392 NameSize
= SubKeyCell
->NameSize
;
393 if (SubKeyCell
->Flags
& REG_KEY_NAME_PACKED
)
395 NameSize
*= sizeof(WCHAR
);
397 *ResultLength
= sizeof(KEY_BASIC_INFORMATION
) + NameSize
;
399 if (Length
< *ResultLength
)
401 Status
= STATUS_BUFFER_OVERFLOW
;
405 /* Fill buffer with requested info */
406 BasicInformation
= (PKEY_BASIC_INFORMATION
) KeyInformation
;
407 BasicInformation
->LastWriteTime
.u
.LowPart
= SubKeyCell
->LastWriteTime
.u
.LowPart
;
408 BasicInformation
->LastWriteTime
.u
.HighPart
= SubKeyCell
->LastWriteTime
.u
.HighPart
;
409 BasicInformation
->TitleIndex
= Index
;
410 BasicInformation
->NameLength
= NameSize
;
412 if (SubKeyCell
->Flags
& REG_KEY_NAME_PACKED
)
414 CmiCopyPackedName(BasicInformation
->Name
,
416 SubKeyCell
->NameSize
);
420 RtlCopyMemory(BasicInformation
->Name
,
422 SubKeyCell
->NameSize
);
427 case KeyNodeInformation
:
428 /* Check size of buffer */
429 if (SubKeyCell
->Flags
& REG_KEY_NAME_PACKED
)
431 NameSize
= SubKeyCell
->NameSize
* sizeof(WCHAR
);
435 NameSize
= SubKeyCell
->NameSize
;
437 *ResultLength
= sizeof(KEY_NODE_INFORMATION
) +
438 NameSize
+ SubKeyCell
->ClassSize
;
440 if (Length
< *ResultLength
)
442 Status
= STATUS_BUFFER_OVERFLOW
;
446 /* Fill buffer with requested info */
447 NodeInformation
= (PKEY_NODE_INFORMATION
) KeyInformation
;
448 NodeInformation
->LastWriteTime
.u
.LowPart
= SubKeyCell
->LastWriteTime
.u
.LowPart
;
449 NodeInformation
->LastWriteTime
.u
.HighPart
= SubKeyCell
->LastWriteTime
.u
.HighPart
;
450 NodeInformation
->TitleIndex
= Index
;
451 NodeInformation
->ClassOffset
= sizeof(KEY_NODE_INFORMATION
) + NameSize
;
452 NodeInformation
->ClassLength
= SubKeyCell
->ClassSize
;
453 NodeInformation
->NameLength
= NameSize
;
455 if (SubKeyCell
->Flags
& REG_KEY_NAME_PACKED
)
457 CmiCopyPackedName(NodeInformation
->Name
,
459 SubKeyCell
->NameSize
);
463 RtlCopyMemory(NodeInformation
->Name
,
465 SubKeyCell
->NameSize
);
468 if (SubKeyCell
->ClassSize
!= 0)
470 ClassCell
= CmiGetCell (KeyObject
->RegistryHive
,
471 SubKeyCell
->ClassNameOffset
,
473 RtlCopyMemory (NodeInformation
->Name
+ SubKeyCell
->NameSize
,
475 SubKeyCell
->ClassSize
);
480 case KeyFullInformation
:
481 /* Check size of buffer */
482 *ResultLength
= sizeof(KEY_FULL_INFORMATION
) +
483 SubKeyCell
->ClassSize
;
485 if (Length
< *ResultLength
)
487 Status
= STATUS_BUFFER_OVERFLOW
;
491 /* Fill buffer with requested info */
492 FullInformation
= (PKEY_FULL_INFORMATION
) KeyInformation
;
493 FullInformation
->LastWriteTime
.u
.LowPart
= SubKeyCell
->LastWriteTime
.u
.LowPart
;
494 FullInformation
->LastWriteTime
.u
.HighPart
= SubKeyCell
->LastWriteTime
.u
.HighPart
;
495 FullInformation
->TitleIndex
= Index
;
496 FullInformation
->ClassOffset
= sizeof(KEY_FULL_INFORMATION
) -
498 FullInformation
->ClassLength
= SubKeyCell
->ClassSize
;
499 FullInformation
->SubKeys
= SubKeyCell
->NumberOfSubKeys
;
500 FullInformation
->MaxNameLen
= CmiGetMaxNameLength(KeyObject
);
501 FullInformation
->MaxClassLen
= CmiGetMaxClassLength(KeyObject
);
502 FullInformation
->Values
= SubKeyCell
->NumberOfValues
;
503 FullInformation
->MaxValueNameLen
=
504 CmiGetMaxValueNameLength(RegistryHive
, SubKeyCell
);
505 FullInformation
->MaxValueDataLen
=
506 CmiGetMaxValueDataLength(RegistryHive
, SubKeyCell
);
507 if (SubKeyCell
->ClassSize
!= 0)
509 ClassCell
= CmiGetCell (KeyObject
->RegistryHive
,
510 SubKeyCell
->ClassNameOffset
,
512 RtlCopyMemory (FullInformation
->Class
,
514 SubKeyCell
->ClassSize
);
520 DPRINT1("Not handling 0x%x\n", KeyInformationClass
);
524 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
525 KeLeaveCriticalRegion();
526 ObDereferenceObject(KeyObject
);
528 DPRINT("Returning status %x\n", Status
);
535 NtEnumerateValueKey(IN HANDLE KeyHandle
,
537 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
,
538 OUT PVOID KeyValueInformation
,
540 OUT PULONG ResultLength
)
543 PKEY_OBJECT KeyObject
;
544 PREGISTRY_HIVE RegistryHive
;
546 PVALUE_CELL ValueCell
;
549 PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation
;
550 PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation
;
551 PKEY_VALUE_FULL_INFORMATION ValueFullInformation
;
553 DPRINT("KH %x I %d KVIC %x KVI %x L %d RL %x\n",
556 KeyValueInformationClass
,
561 /* Verify that the handle is valid and is a registry key */
562 Status
= ObReferenceObjectByHandle(KeyHandle
,
566 (PVOID
*) &KeyObject
,
569 if (!NT_SUCCESS(Status
))
574 /* Acquire hive lock */
575 KeEnterCriticalRegion();
576 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
578 VERIFY_KEY_OBJECT(KeyObject
);
580 /* Get pointer to KeyCell */
581 KeyCell
= KeyObject
->KeyCell
;
582 RegistryHive
= KeyObject
->RegistryHive
;
584 /* Get Value block of interest */
585 Status
= CmiGetValueFromKeyByIndex(RegistryHive
,
590 if (!NT_SUCCESS(Status
))
592 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
593 KeLeaveCriticalRegion();
594 ObDereferenceObject(KeyObject
);
598 if (ValueCell
!= NULL
)
600 switch (KeyValueInformationClass
)
602 case KeyValueBasicInformation
:
603 NameSize
= ValueCell
->NameSize
;
604 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
606 NameSize
*= sizeof(WCHAR
);
608 *ResultLength
= sizeof(KEY_VALUE_BASIC_INFORMATION
) + NameSize
;
609 if (Length
< *ResultLength
)
611 Status
= STATUS_BUFFER_OVERFLOW
;
615 ValueBasicInformation
= (PKEY_VALUE_BASIC_INFORMATION
)
617 ValueBasicInformation
->TitleIndex
= 0;
618 ValueBasicInformation
->Type
= ValueCell
->DataType
;
619 ValueBasicInformation
->NameLength
= NameSize
;
620 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
622 CmiCopyPackedName(ValueBasicInformation
->Name
,
624 ValueCell
->NameSize
);
628 RtlCopyMemory(ValueBasicInformation
->Name
,
635 case KeyValuePartialInformation
:
636 *ResultLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) +
637 (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
638 if (Length
< *ResultLength
)
640 Status
= STATUS_BUFFER_OVERFLOW
;
644 ValuePartialInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)
646 ValuePartialInformation
->TitleIndex
= 0;
647 ValuePartialInformation
->Type
= ValueCell
->DataType
;
648 ValuePartialInformation
->DataLength
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
649 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
))
651 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
652 RtlCopyMemory(ValuePartialInformation
->Data
,
654 ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
658 RtlCopyMemory(ValuePartialInformation
->Data
,
659 &ValueCell
->DataOffset
,
660 ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
665 case KeyValueFullInformation
:
666 NameSize
= ValueCell
->NameSize
;
667 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
669 NameSize
*= sizeof(WCHAR
);
671 *ResultLength
= sizeof(KEY_VALUE_FULL_INFORMATION
) +
672 NameSize
+ (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
673 if (Length
< *ResultLength
)
675 Status
= STATUS_BUFFER_OVERFLOW
;
679 ValueFullInformation
= (PKEY_VALUE_FULL_INFORMATION
)
681 ValueFullInformation
->TitleIndex
= 0;
682 ValueFullInformation
->Type
= ValueCell
->DataType
;
683 ValueFullInformation
->NameLength
= NameSize
;
684 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
686 CmiCopyPackedName(ValueFullInformation
->Name
,
688 ValueCell
->NameSize
);
692 RtlCopyMemory(ValueFullInformation
->Name
,
694 ValueCell
->NameSize
);
696 ValueFullInformation
->DataOffset
=
697 (ULONG
)ValueFullInformation
->Name
- (ULONG
)ValueFullInformation
+
698 ValueFullInformation
->NameLength
;
699 ValueFullInformation
->DataOffset
=
700 ROUND_UP(ValueFullInformation
->DataOffset
, sizeof(PVOID
));
701 ValueFullInformation
->DataLength
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
702 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
))
704 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
705 RtlCopyMemory((PCHAR
) ValueFullInformation
706 + ValueFullInformation
->DataOffset
,
708 ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
712 RtlCopyMemory((PCHAR
) ValueFullInformation
713 + ValueFullInformation
->DataOffset
,
714 &ValueCell
->DataOffset
,
715 ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
721 DPRINT1("Not handling 0x%x\n", KeyValueInformationClass
);
727 Status
= STATUS_UNSUCCESSFUL
;
730 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
731 KeLeaveCriticalRegion();
732 ObDereferenceObject(KeyObject
);
739 NtFlushKey(IN HANDLE KeyHandle
)
742 PKEY_OBJECT KeyObject
;
743 PREGISTRY_HIVE RegistryHive
;
745 DPRINT("NtFlushKey (KeyHandle %lx) called\n", KeyHandle
);
747 /* Verify that the handle is valid and is a registry key */
748 Status
= ObReferenceObjectByHandle(KeyHandle
,
754 if (!NT_SUCCESS(Status
))
759 VERIFY_KEY_OBJECT(KeyObject
);
761 RegistryHive
= KeyObject
->RegistryHive
;
763 /* Acquire hive lock */
764 KeEnterCriticalRegion();
765 ExAcquireResourceExclusiveLite(&RegistryHive
->HiveResource
,
768 if (IsNoFileHive(RegistryHive
))
770 Status
= STATUS_SUCCESS
;
774 /* Flush non-volatile hive */
775 Status
= CmiFlushRegistryHive(RegistryHive
);
778 ExReleaseResourceLite(&RegistryHive
->HiveResource
);
779 KeLeaveCriticalRegion();
781 ObDereferenceObject(KeyObject
);
783 return STATUS_SUCCESS
;
788 NtOpenKey(OUT PHANDLE KeyHandle
,
789 IN ACCESS_MASK DesiredAccess
,
790 IN POBJECT_ATTRIBUTES ObjectAttributes
)
792 UNICODE_STRING RemainingPath
;
796 DPRINT("NtOpenKey(KH %x DA %x OA %x OA->ON '%wZ'\n",
800 ObjectAttributes
? ObjectAttributes
->ObjectName
: NULL
);
802 RemainingPath
.Buffer
= NULL
;
803 Status
= ObFindObject(ObjectAttributes
,
807 if (!NT_SUCCESS(Status
))
812 VERIFY_KEY_OBJECT((PKEY_OBJECT
) Object
);
814 DPRINT("RemainingPath '%wZ'\n", &RemainingPath
);
816 if ((RemainingPath
.Buffer
!= NULL
) && (RemainingPath
.Buffer
[0] != 0))
818 ObDereferenceObject(Object
);
819 return(STATUS_UNSUCCESSFUL
);
822 /* Fail if the key has been deleted */
823 if (((PKEY_OBJECT
)Object
)->Flags
& KO_MARKED_FOR_DELETE
)
825 ObDereferenceObject(Object
);
826 return(STATUS_UNSUCCESSFUL
);
829 Status
= ObCreateHandle(PsGetCurrentProcess(),
834 ObDereferenceObject(Object
);
836 if (!NT_SUCCESS(Status
))
841 return(STATUS_SUCCESS
);
846 NtQueryKey(IN HANDLE KeyHandle
,
847 IN KEY_INFORMATION_CLASS KeyInformationClass
,
848 OUT PVOID KeyInformation
,
850 OUT PULONG ResultLength
)
852 PKEY_BASIC_INFORMATION BasicInformation
;
853 PKEY_NODE_INFORMATION NodeInformation
;
854 PKEY_FULL_INFORMATION FullInformation
;
855 PREGISTRY_HIVE RegistryHive
;
856 PDATA_CELL ClassCell
;
857 PKEY_OBJECT KeyObject
;
861 DPRINT("NtQueryKey(KH %x KIC %x KI %x L %d RL %x)\n",
868 /* Verify that the handle is valid and is a registry key */
869 Status
= ObReferenceObjectByHandle(KeyHandle
,
873 (PVOID
*) &KeyObject
,
875 if (!NT_SUCCESS(Status
))
880 /* Acquire hive lock */
881 KeEnterCriticalRegion();
882 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
884 VERIFY_KEY_OBJECT(KeyObject
);
886 /* Get pointer to KeyCell */
887 KeyCell
= KeyObject
->KeyCell
;
888 RegistryHive
= KeyObject
->RegistryHive
;
890 Status
= STATUS_SUCCESS
;
891 switch (KeyInformationClass
)
893 case KeyBasicInformation
:
894 /* Check size of buffer */
895 *ResultLength
= sizeof(KEY_BASIC_INFORMATION
) +
896 KeyObject
->Name
.Length
;
898 if (Length
< *ResultLength
)
900 Status
= STATUS_BUFFER_OVERFLOW
;
904 /* Fill buffer with requested info */
905 BasicInformation
= (PKEY_BASIC_INFORMATION
) KeyInformation
;
906 BasicInformation
->LastWriteTime
.u
.LowPart
= KeyCell
->LastWriteTime
.u
.LowPart
;
907 BasicInformation
->LastWriteTime
.u
.HighPart
= KeyCell
->LastWriteTime
.u
.HighPart
;
908 BasicInformation
->TitleIndex
= 0;
909 BasicInformation
->NameLength
= KeyObject
->Name
.Length
;
911 if (KeyCell
->Flags
& REG_KEY_NAME_PACKED
)
913 CmiCopyPackedName(BasicInformation
->Name
,
919 RtlCopyMemory(BasicInformation
->Name
,
926 case KeyNodeInformation
:
927 /* Check size of buffer */
928 *ResultLength
= sizeof(KEY_NODE_INFORMATION
) +
929 KeyObject
->Name
.Length
+ KeyCell
->ClassSize
;
931 if (Length
< *ResultLength
)
933 Status
= STATUS_BUFFER_OVERFLOW
;
937 /* Fill buffer with requested info */
938 NodeInformation
= (PKEY_NODE_INFORMATION
) KeyInformation
;
939 NodeInformation
->LastWriteTime
.u
.LowPart
= KeyCell
->LastWriteTime
.u
.LowPart
;
940 NodeInformation
->LastWriteTime
.u
.HighPart
= KeyCell
->LastWriteTime
.u
.HighPart
;
941 NodeInformation
->TitleIndex
= 0;
942 NodeInformation
->ClassOffset
= sizeof(KEY_NODE_INFORMATION
) +
943 KeyObject
->Name
.Length
;
944 NodeInformation
->ClassLength
= KeyCell
->ClassSize
;
945 NodeInformation
->NameLength
= KeyObject
->Name
.Length
;
947 if (KeyCell
->Flags
& REG_KEY_NAME_PACKED
)
949 CmiCopyPackedName(NodeInformation
->Name
,
955 RtlCopyMemory(NodeInformation
->Name
,
960 if (KeyCell
->ClassSize
!= 0)
962 ClassCell
= CmiGetCell (KeyObject
->RegistryHive
,
963 KeyCell
->ClassNameOffset
,
965 RtlCopyMemory (NodeInformation
->Name
+ KeyObject
->Name
.Length
,
972 case KeyFullInformation
:
973 /* Check size of buffer */
974 *ResultLength
= sizeof(KEY_FULL_INFORMATION
) +
977 if (Length
< *ResultLength
)
979 Status
= STATUS_BUFFER_OVERFLOW
;
983 /* Fill buffer with requested info */
984 FullInformation
= (PKEY_FULL_INFORMATION
) KeyInformation
;
985 FullInformation
->LastWriteTime
.u
.LowPart
= KeyCell
->LastWriteTime
.u
.LowPart
;
986 FullInformation
->LastWriteTime
.u
.HighPart
= KeyCell
->LastWriteTime
.u
.HighPart
;
987 FullInformation
->TitleIndex
= 0;
988 FullInformation
->ClassOffset
= sizeof(KEY_FULL_INFORMATION
) - sizeof(WCHAR
);
989 FullInformation
->ClassLength
= KeyCell
->ClassSize
;
990 FullInformation
->SubKeys
= KeyCell
->NumberOfSubKeys
;
991 FullInformation
->MaxNameLen
= CmiGetMaxNameLength(KeyObject
);
992 FullInformation
->MaxClassLen
= CmiGetMaxClassLength(KeyObject
);
993 FullInformation
->Values
= KeyCell
->NumberOfValues
;
994 FullInformation
->MaxValueNameLen
=
995 CmiGetMaxValueNameLength(RegistryHive
, KeyCell
);
996 FullInformation
->MaxValueDataLen
=
997 CmiGetMaxValueDataLength(RegistryHive
, KeyCell
);
998 if (KeyCell
->ClassSize
!= 0)
1000 ClassCell
= CmiGetCell (KeyObject
->RegistryHive
,
1001 KeyCell
->ClassNameOffset
,
1003 RtlCopyMemory (FullInformation
->Class
,
1005 KeyCell
->ClassSize
);
1010 DPRINT1("Not handling 0x%x\n", KeyInformationClass
);
1014 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1015 KeLeaveCriticalRegion();
1016 ObDereferenceObject(KeyObject
);
1023 NtQueryValueKey(IN HANDLE KeyHandle
,
1024 IN PUNICODE_STRING ValueName
,
1025 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
,
1026 OUT PVOID KeyValueInformation
,
1028 OUT PULONG ResultLength
)
1032 PKEY_OBJECT KeyObject
;
1033 PREGISTRY_HIVE RegistryHive
;
1035 PVALUE_CELL ValueCell
;
1036 PDATA_CELL DataCell
;
1037 PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation
;
1038 PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation
;
1039 PKEY_VALUE_FULL_INFORMATION ValueFullInformation
;
1041 DPRINT("NtQueryValueKey(KeyHandle %x ValueName %S Length %x)\n",
1042 KeyHandle
, ValueName
->Buffer
, Length
);
1044 /* Verify that the handle is valid and is a registry key */
1045 Status
= ObReferenceObjectByHandle(KeyHandle
,
1049 (PVOID
*)&KeyObject
,
1052 if (!NT_SUCCESS(Status
))
1054 DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status
);
1058 /* Acquire hive lock */
1059 KeEnterCriticalRegion();
1060 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1062 VERIFY_KEY_OBJECT(KeyObject
);
1064 /* Get pointer to KeyCell */
1065 KeyCell
= KeyObject
->KeyCell
;
1066 RegistryHive
= KeyObject
->RegistryHive
;
1068 /* Get Value block of interest */
1069 Status
= CmiScanKeyForValue(RegistryHive
,
1074 if (!NT_SUCCESS(Status
))
1076 DPRINT("CmiScanKeyForValue() failed with status %x\n", Status
);
1077 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1078 KeLeaveCriticalRegion();
1079 ObDereferenceObject(KeyObject
);
1082 else if (ValueCell
!= NULL
)
1084 switch (KeyValueInformationClass
)
1086 case KeyValueBasicInformation
:
1087 NameSize
= ValueCell
->NameSize
;
1088 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1090 NameSize
*= sizeof(WCHAR
);
1092 *ResultLength
= sizeof(KEY_VALUE_BASIC_INFORMATION
) + NameSize
;
1093 if (Length
< *ResultLength
)
1095 Status
= STATUS_BUFFER_TOO_SMALL
;
1099 ValueBasicInformation
= (PKEY_VALUE_BASIC_INFORMATION
)
1100 KeyValueInformation
;
1101 ValueBasicInformation
->TitleIndex
= 0;
1102 ValueBasicInformation
->Type
= ValueCell
->DataType
;
1103 ValueBasicInformation
->NameLength
= NameSize
;
1104 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1106 CmiCopyPackedName(ValueBasicInformation
->Name
,
1108 ValueCell
->NameSize
);
1112 RtlCopyMemory(ValueBasicInformation
->Name
,
1114 ValueCell
->NameSize
* sizeof(WCHAR
));
1119 case KeyValuePartialInformation
:
1120 *ResultLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
)
1121 + (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
1122 if (Length
< *ResultLength
)
1124 Status
= STATUS_BUFFER_TOO_SMALL
;
1128 ValuePartialInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)
1129 KeyValueInformation
;
1130 ValuePartialInformation
->TitleIndex
= 0;
1131 ValuePartialInformation
->Type
= ValueCell
->DataType
;
1132 ValuePartialInformation
->DataLength
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
1133 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
))
1135 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
1136 RtlCopyMemory(ValuePartialInformation
->Data
,
1138 ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
1142 RtlCopyMemory(ValuePartialInformation
->Data
,
1143 &ValueCell
->DataOffset
,
1144 ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
1149 case KeyValueFullInformation
:
1150 NameSize
= ValueCell
->NameSize
;
1151 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1153 NameSize
*= sizeof(WCHAR
);
1155 *ResultLength
= sizeof(KEY_VALUE_FULL_INFORMATION
) +
1156 NameSize
+ (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
1157 if (Length
< *ResultLength
)
1159 Status
= STATUS_BUFFER_TOO_SMALL
;
1163 ValueFullInformation
= (PKEY_VALUE_FULL_INFORMATION
)
1164 KeyValueInformation
;
1165 ValueFullInformation
->TitleIndex
= 0;
1166 ValueFullInformation
->Type
= ValueCell
->DataType
;
1167 ValueFullInformation
->NameLength
= NameSize
;
1168 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1170 CmiCopyPackedName(ValueFullInformation
->Name
,
1172 ValueCell
->NameSize
);
1176 RtlCopyMemory(ValueFullInformation
->Name
,
1178 ValueCell
->NameSize
);
1180 ValueFullInformation
->DataOffset
=
1181 (ULONG
)ValueFullInformation
->Name
- (ULONG
)ValueFullInformation
+
1182 ValueFullInformation
->NameLength
;
1183 ValueFullInformation
->DataOffset
=
1184 ROUND_UP(ValueFullInformation
->DataOffset
, sizeof(PVOID
));
1185 ValueFullInformation
->DataLength
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
1186 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
))
1188 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
1189 RtlCopyMemory((PCHAR
) ValueFullInformation
1190 + ValueFullInformation
->DataOffset
,
1192 ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
1196 RtlCopyMemory((PCHAR
) ValueFullInformation
1197 + ValueFullInformation
->DataOffset
,
1198 &ValueCell
->DataOffset
,
1199 ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
1204 DPRINT1("Not handling 0x%x\n", KeyValueInformationClass
);
1210 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
1213 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1214 KeLeaveCriticalRegion();
1215 ObDereferenceObject(KeyObject
);
1222 NtSetValueKey(IN HANDLE KeyHandle
,
1223 IN PUNICODE_STRING ValueName
,
1224 IN ULONG TitleIndex
,
1230 PKEY_OBJECT KeyObject
;
1231 PREGISTRY_HIVE RegistryHive
;
1233 PVALUE_CELL ValueCell
;
1234 BLOCK_OFFSET ValueCellOffset
;
1235 PDATA_CELL DataCell
;
1236 PDATA_CELL NewDataCell
;
1238 ULONG DesiredAccess
;
1240 DPRINT("NtSetValueKey(KeyHandle %x ValueName '%wZ' Type %d)\n",
1241 KeyHandle
, ValueName
, Type
);
1243 DesiredAccess
= KEY_SET_VALUE
;
1244 if (Type
== REG_LINK
)
1245 DesiredAccess
|= KEY_CREATE_LINK
;
1247 /* Verify that the handle is valid and is a registry key */
1248 Status
= ObReferenceObjectByHandle(KeyHandle
,
1252 (PVOID
*)&KeyObject
,
1254 if (!NT_SUCCESS(Status
))
1257 /* Acquire hive lock exclucively */
1258 KeEnterCriticalRegion();
1259 ExAcquireResourceExclusiveLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1261 VERIFY_KEY_OBJECT(KeyObject
);
1263 /* Get pointer to key cell */
1264 KeyCell
= KeyObject
->KeyCell
;
1265 RegistryHive
= KeyObject
->RegistryHive
;
1266 Status
= CmiScanKeyForValue(RegistryHive
,
1271 if (!NT_SUCCESS(Status
))
1273 DPRINT("Value not found. Status 0x%X\n", Status
);
1275 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1276 KeLeaveCriticalRegion();
1277 ObDereferenceObject(KeyObject
);
1281 if (ValueCell
== NULL
)
1283 DPRINT("Allocate new value cell\n");
1284 Status
= CmiAddValueToKey(RegistryHive
,
1289 if (NT_SUCCESS(Status
))
1291 CmiMarkBlockDirty(RegistryHive
, ValueCellOffset
);
1295 if (!NT_SUCCESS(Status
))
1297 DPRINT("Cannot add value. Status 0x%X\n", Status
);
1299 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1300 KeLeaveCriticalRegion();
1301 ObDereferenceObject(KeyObject
);
1305 DPRINT("DataSize %lu\n", DataSize
);
1306 DPRINT("ValueCell %p\n", ValueCell
);
1307 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
1309 if (DataSize
<= sizeof(BLOCK_OFFSET
))
1311 /* If data size <= sizeof(BLOCK_OFFSET) then store data in the data offset */
1312 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
1313 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
) &&
1314 (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
) != 0)
1316 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
1317 CmiDestroyCell(RegistryHive
, DataCell
, ValueCell
->DataOffset
);
1320 RtlCopyMemory(&ValueCell
->DataOffset
, Data
, DataSize
);
1321 ValueCell
->DataSize
= DataSize
| REG_DATA_IN_OFFSET
;
1322 ValueCell
->DataType
= Type
;
1323 RtlMoveMemory(&ValueCell
->DataOffset
, Data
, DataSize
);
1324 CmiMarkBlockDirty(RegistryHive
, ValueCellOffset
);
1326 else if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
) &&
1327 (DataSize
<= (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
)))
1329 /* If new data size is <= current then overwrite current data */
1330 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
,&pBin
);
1331 RtlZeroMemory(DataCell
->Data
, ValueCell
->DataSize
);
1332 RtlCopyMemory(DataCell
->Data
, Data
, DataSize
);
1333 ValueCell
->DataSize
= DataSize
;
1334 ValueCell
->DataType
= Type
;
1339 * New data size is larger than the current, destroy current
1340 * data block and allocate a new one.
1342 BLOCK_OFFSET NewOffset
;
1344 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
1346 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
) &&
1347 (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
) != 0)
1349 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
1350 CmiDestroyCell(RegistryHive
, DataCell
, ValueCell
->DataOffset
);
1351 ValueCell
->DataSize
= 0;
1352 ValueCell
->DataType
= 0;
1353 ValueCell
->DataOffset
= (BLOCK_OFFSET
)-1;
1356 Status
= CmiAllocateCell (RegistryHive
,
1357 sizeof(CELL_HEADER
) + DataSize
,
1358 (PVOID
*)&NewDataCell
,
1360 if (!NT_SUCCESS(Status
))
1362 DPRINT("CmiAllocateBlock() failed (Status %lx)\n", Status
);
1364 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1365 KeLeaveCriticalRegion();
1366 ObDereferenceObject(KeyObject
);
1371 RtlCopyMemory(&NewDataCell
->Data
[0], Data
, DataSize
);
1372 ValueCell
->DataSize
= DataSize
& REG_DATA_SIZE_MASK
;
1373 ValueCell
->DataType
= Type
;
1374 ValueCell
->DataOffset
= NewOffset
;
1375 CmiMarkBlockDirty(RegistryHive
, ValueCell
->DataOffset
);
1376 CmiMarkBlockDirty(RegistryHive
, ValueCellOffset
);
1380 if ((Type
== REG_LINK
) &&
1381 (_wcsicmp(ValueName
->Buffer
, L
"SymbolicLinkValue") == 0))
1383 KeyCell
->Flags
|= REG_KEY_LINK_CELL
;
1386 NtQuerySystemTime (&KeyCell
->LastWriteTime
);
1387 CmiMarkBlockDirty (RegistryHive
, KeyObject
->KeyCellOffset
);
1389 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1390 KeLeaveCriticalRegion();
1391 ObDereferenceObject(KeyObject
);
1395 DPRINT("Return Status 0x%X\n", Status
);
1402 NtDeleteValueKey (IN HANDLE KeyHandle
,
1403 IN PUNICODE_STRING ValueName
)
1405 PKEY_OBJECT KeyObject
;
1408 /* Verify that the handle is valid and is a registry key */
1409 Status
= ObReferenceObjectByHandle(KeyHandle
,
1413 (PVOID
*)&KeyObject
,
1415 if (!NT_SUCCESS(Status
))
1420 /* Acquire hive lock */
1421 KeEnterCriticalRegion();
1422 ExAcquireResourceExclusiveLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1424 VERIFY_KEY_OBJECT(KeyObject
);
1426 Status
= CmiDeleteValueFromKey(KeyObject
->RegistryHive
,
1428 KeyObject
->KeyCellOffset
,
1431 NtQuerySystemTime (&KeyObject
->KeyCell
->LastWriteTime
);
1432 CmiMarkBlockDirty (KeyObject
->RegistryHive
, KeyObject
->KeyCellOffset
);
1434 /* Release hive lock */
1435 ExReleaseResourceLite (&KeyObject
->RegistryHive
->HiveResource
);
1436 KeLeaveCriticalRegion();
1438 ObDereferenceObject (KeyObject
);
1448 * KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
1449 * KeyObjectAttributes->Name specifies the name of the key to load.
1452 NtLoadKey (IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
1453 IN POBJECT_ATTRIBUTES FileObjectAttributes
)
1455 return NtLoadKey2 (KeyObjectAttributes
,
1456 FileObjectAttributes
,
1463 * KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
1464 * KeyObjectAttributes->Name specifies the name of the key to load.
1465 * Flags can be 0 or REG_NO_LAZY_FLUSH.
1468 NtLoadKey2 (IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
1469 IN POBJECT_ATTRIBUTES FileObjectAttributes
,
1472 POBJECT_NAME_INFORMATION NameInfo
;
1473 PUNICODE_STRING NamePointer
;
1479 DPRINT ("NtLoadKey2() called\n");
1482 if (!SeSinglePrivilegeCheck (SeRestorePrivilege
, KeGetPreviousMode ()))
1483 return STATUS_PRIVILEGE_NOT_HELD
;
1486 if (FileObjectAttributes
->RootDirectory
!= NULL
)
1489 sizeof(OBJECT_NAME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
);
1490 Buffer
= ExAllocatePool (NonPagedPool
,
1493 return STATUS_INSUFFICIENT_RESOURCES
;
1495 Status
= NtQueryObject (FileObjectAttributes
->RootDirectory
,
1496 ObjectNameInformation
,
1500 if (!NT_SUCCESS(Status
))
1502 DPRINT1 ("NtQueryObject() failed (Status %lx)\n", Status
);
1503 ExFreePool (Buffer
);
1507 NameInfo
= (POBJECT_NAME_INFORMATION
)Buffer
;
1508 DPRINT ("ObjectPath: '%wZ' Length %hu\n",
1509 &NameInfo
->Name
, NameInfo
->Name
.Length
);
1511 NameInfo
->Name
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
1512 if (FileObjectAttributes
->ObjectName
->Buffer
[0] != L
'\\')
1514 RtlAppendUnicodeToString (&NameInfo
->Name
,
1516 DPRINT ("ObjectPath: '%wZ' Length %hu\n",
1517 &NameInfo
->Name
, NameInfo
->Name
.Length
);
1519 RtlAppendUnicodeStringToString (&NameInfo
->Name
,
1520 FileObjectAttributes
->ObjectName
);
1522 DPRINT ("ObjectPath: '%wZ' Length %hu\n",
1523 &NameInfo
->Name
, NameInfo
->Name
.Length
);
1524 NamePointer
= &NameInfo
->Name
;
1528 if (FileObjectAttributes
->ObjectName
->Buffer
[0] == L
'\\')
1531 NamePointer
= FileObjectAttributes
->ObjectName
;
1536 sizeof(OBJECT_NAME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
);
1537 Buffer
= ExAllocatePool (NonPagedPool
,
1540 return STATUS_INSUFFICIENT_RESOURCES
;
1542 NameInfo
= (POBJECT_NAME_INFORMATION
)Buffer
;
1543 NameInfo
->Name
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
1544 NameInfo
->Name
.Length
= 0;
1545 NameInfo
->Name
.Buffer
= (PWSTR
)((ULONG_PTR
)Buffer
+ sizeof(OBJECT_NAME_INFORMATION
));
1546 NameInfo
->Name
.Buffer
[0] = 0;
1548 RtlAppendUnicodeToString (&NameInfo
->Name
,
1550 RtlAppendUnicodeStringToString (&NameInfo
->Name
,
1551 FileObjectAttributes
->ObjectName
);
1553 NamePointer
= &NameInfo
->Name
;
1557 DPRINT ("Full name: '%wZ'\n", NamePointer
);
1559 Status
= CmiLoadHive (KeyObjectAttributes
,
1562 if (!NT_SUCCESS (Status
))
1564 DPRINT1 ("CmiLoadHive() failed (Status %lx)\n", Status
);
1568 ExFreePool (Buffer
);
1575 NtNotifyChangeKey (IN HANDLE KeyHandle
,
1577 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1578 IN PVOID ApcContext OPTIONAL
,
1579 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1580 IN ULONG CompletionFilter
,
1581 IN BOOLEAN Asynchroneous
,
1582 OUT PVOID ChangeBuffer
,
1584 IN BOOLEAN WatchSubtree
)
1587 return(STATUS_NOT_IMPLEMENTED
);
1592 NtQueryMultipleValueKey (IN HANDLE KeyHandle
,
1593 IN OUT PKEY_VALUE_ENTRY ValueList
,
1594 IN ULONG NumberOfValues
,
1596 IN OUT PULONG Length
,
1597 OUT PULONG ReturnLength
)
1599 PREGISTRY_HIVE RegistryHive
;
1600 PVALUE_CELL ValueCell
;
1601 PKEY_OBJECT KeyObject
;
1602 PDATA_CELL DataCell
;
1603 ULONG BufferLength
= 0;
1609 /* Verify that the handle is valid and is a registry key */
1610 Status
= ObReferenceObjectByHandle(KeyHandle
,
1614 (PVOID
*) &KeyObject
,
1616 if (!NT_SUCCESS(Status
))
1618 DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status
);
1622 /* Acquire hive lock */
1623 KeEnterCriticalRegion();
1624 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1626 VERIFY_KEY_OBJECT(KeyObject
);
1628 /* Get pointer to KeyCell */
1629 KeyCell
= KeyObject
->KeyCell
;
1630 RegistryHive
= KeyObject
->RegistryHive
;
1632 DataPtr
= (PUCHAR
) Buffer
;
1634 for (i
= 0; i
< NumberOfValues
; i
++)
1636 DPRINT("ValueName: '%wZ'\n", ValueList
[i
].ValueName
);
1638 /* Get Value block of interest */
1639 Status
= CmiScanKeyForValue(RegistryHive
,
1641 ValueList
[i
].ValueName
,
1645 if (!NT_SUCCESS(Status
))
1647 DPRINT("CmiScanKeyForValue() failed with status %x\n", Status
);
1650 else if (ValueCell
== NULL
)
1652 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
1656 BufferLength
= ROUND_UP(BufferLength
, sizeof(PVOID
));
1658 if (BufferLength
+ (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
) <= *Length
)
1660 DataPtr
= (PUCHAR
)ROUND_UP((ULONG
)DataPtr
, sizeof(PVOID
));
1662 ValueList
[i
].Type
= ValueCell
->DataType
;
1663 ValueList
[i
].DataLength
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
1664 ValueList
[i
].DataOffset
= (ULONG
) DataPtr
- (ULONG
) Buffer
;
1666 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
))
1668 DataCell
= CmiGetCell (RegistryHive
,
1669 ValueCell
->DataOffset
,
1671 RtlCopyMemory(DataPtr
,
1673 ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
1677 RtlCopyMemory(DataPtr
,
1678 &ValueCell
->DataOffset
,
1679 ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
1682 DataPtr
+= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
1686 Status
= STATUS_BUFFER_TOO_SMALL
;
1689 BufferLength
+= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
1692 if (NT_SUCCESS(Status
))
1693 *Length
= BufferLength
;
1695 *ReturnLength
= BufferLength
;
1697 /* Release hive lock */
1698 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1699 KeLeaveCriticalRegion();
1701 ObDereferenceObject(KeyObject
);
1703 DPRINT("Return Status 0x%X\n", Status
);
1710 NtReplaceKey (IN POBJECT_ATTRIBUTES ObjectAttributes
,
1712 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes
)
1715 return(STATUS_NOT_IMPLEMENTED
);
1720 NtRestoreKey (IN HANDLE KeyHandle
,
1721 IN HANDLE FileHandle
,
1722 IN ULONG RestoreFlags
)
1725 return(STATUS_NOT_IMPLEMENTED
);
1730 NtSaveKey (IN HANDLE KeyHandle
,
1731 IN HANDLE FileHandle
)
1733 PREGISTRY_HIVE TempHive
;
1734 PKEY_OBJECT KeyObject
;
1737 DPRINT ("NtSaveKey() called\n");
1740 if (!SeSinglePrivilegeCheck (SeBackupPrivilege
, KeGetPreviousMode ()))
1741 return STATUS_PRIVILEGE_NOT_HELD
;
1744 Status
= ObReferenceObjectByHandle (KeyHandle
,
1747 KeGetPreviousMode(),
1748 (PVOID
*)&KeyObject
,
1750 if (!NT_SUCCESS(Status
))
1752 DPRINT1 ("ObReferenceObjectByHandle() failed (Status %lx)\n", Status
);
1756 /* Acquire hive lock exclucively */
1757 KeEnterCriticalRegion();
1758 ExAcquireResourceExclusiveLite (&KeyObject
->RegistryHive
->HiveResource
,
1761 /* Refuse to save a volatile key */
1762 if (KeyObject
->RegistryHive
== CmiVolatileHive
)
1764 DPRINT1 ("Cannot save a volatile key\n");
1765 ExReleaseResourceLite (&KeyObject
->RegistryHive
->HiveResource
);
1766 KeLeaveCriticalRegion();
1767 ObDereferenceObject (KeyObject
);
1768 return STATUS_ACCESS_DENIED
;
1771 Status
= CmiCreateTempHive(&TempHive
);
1772 if (!NT_SUCCESS(Status
))
1774 DPRINT1 ("CmiCreateTempHive() failed (Status %lx)\n", Status
);
1775 ExReleaseResourceLite (&KeyObject
->RegistryHive
->HiveResource
);
1776 KeLeaveCriticalRegion();
1777 ObDereferenceObject (KeyObject
);
1781 Status
= CmiCopyKey (TempHive
,
1783 KeyObject
->RegistryHive
,
1784 KeyObject
->KeyCell
);
1785 if (!NT_SUCCESS(Status
))
1787 DPRINT1 ("CmiCopyKey() failed (Status %lx)\n", Status
);
1788 CmiRemoveRegistryHive (TempHive
);
1789 ExReleaseResourceLite (&KeyObject
->RegistryHive
->HiveResource
);
1790 KeLeaveCriticalRegion();
1791 ObDereferenceObject (KeyObject
);
1795 Status
= CmiSaveTempHive (TempHive
,
1797 if (!NT_SUCCESS(Status
))
1799 DPRINT1 ("CmiSaveTempHive() failed (Status %lx)\n", Status
);
1802 CmiRemoveRegistryHive (TempHive
);
1804 /* Release hive lock */
1805 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1806 KeLeaveCriticalRegion();
1808 ObDereferenceObject (KeyObject
);
1810 DPRINT ("NtSaveKey() done\n");
1812 return STATUS_SUCCESS
;
1817 NtSetInformationKey (IN HANDLE KeyHandle
,
1818 IN KEY_SET_INFORMATION_CLASS KeyInformationClass
,
1819 IN PVOID KeyInformation
,
1820 IN ULONG KeyInformationLength
)
1822 PKEY_OBJECT KeyObject
;
1825 if (KeyInformationClass
!= KeyLastWriteTimeInformation
)
1826 return STATUS_INVALID_INFO_CLASS
;
1828 if (KeyInformationLength
!= sizeof (KEY_LAST_WRITE_TIME_INFORMATION
))
1829 return STATUS_INFO_LENGTH_MISMATCH
;
1831 /* Verify that the handle is valid and is a registry key */
1832 Status
= ObReferenceObjectByHandle (KeyHandle
,
1836 (PVOID
*)&KeyObject
,
1838 if (!NT_SUCCESS (Status
))
1840 DPRINT ("ObReferenceObjectByHandle() failed with status %x\n", Status
);
1844 /* Acquire hive lock */
1845 KeEnterCriticalRegion();
1846 ExAcquireResourceExclusiveLite (&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1848 VERIFY_KEY_OBJECT(KeyObject
);
1850 KeyObject
->KeyCell
->LastWriteTime
.QuadPart
=
1851 ((PKEY_LAST_WRITE_TIME_INFORMATION
)KeyInformation
)->LastWriteTime
.QuadPart
;
1853 CmiMarkBlockDirty (KeyObject
->RegistryHive
,
1854 KeyObject
->KeyCellOffset
);
1856 /* Release hive lock */
1857 ExReleaseResourceLite (&KeyObject
->RegistryHive
->HiveResource
);
1858 KeLeaveCriticalRegion();
1860 ObDereferenceObject (KeyObject
);
1864 DPRINT ("NtSaveKey() done\n");
1866 return STATUS_SUCCESS
;
1872 * KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
1873 * KeyObjectAttributes->Name specifies the name of the key to unload.
1876 NtUnloadKey (IN POBJECT_ATTRIBUTES KeyObjectAttributes
)
1878 PREGISTRY_HIVE RegistryHive
;
1881 DPRINT ("NtUnloadKey() called\n");
1884 if (!SeSinglePrivilegeCheck (SeRestorePrivilege
, KeGetPreviousMode ()))
1885 return STATUS_PRIVILEGE_NOT_HELD
;
1888 Status
= CmiDisconnectHive (KeyObjectAttributes
,
1890 if (!NT_SUCCESS (Status
))
1892 DPRINT1 ("CmiDisconnectHive() failed (Status %lx)\n", Status
);
1896 DPRINT ("RegistryHive %p\n", RegistryHive
);
1898 /* Acquire hive list lock exclusively */
1899 KeEnterCriticalRegion();
1900 ExAcquireResourceExclusiveLite (&CmiHiveListLock
,
1905 if (!IsNoFileHive (RegistryHive
))
1906 CmiFlushRegistryHive (RegistryHive
);
1909 /* Release hive list lock */
1910 ExReleaseResourceLite (&CmiHiveListLock
);
1911 KeLeaveCriticalRegion();
1913 CmiRemoveRegistryHive (RegistryHive
);
1915 DPRINT ("NtUnloadKey() done\n");
1917 return STATUS_SUCCESS
;
1922 NtInitializeRegistry (IN BOOLEAN SetUpBoot
)
1926 if (CmiRegistryInitialized
== TRUE
)
1927 return STATUS_ACCESS_DENIED
;
1929 /* FIXME: save boot log file */
1931 Status
= CmiInitHives (SetUpBoot
);
1933 CmiRegistryInitialized
= TRUE
;