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
14 #include <internal/ob.h>
17 #include <internal/se.h>
18 #include <internal/registry.h>
21 #include <internal/debug.h>
26 /* GLOBALS ******************************************************************/
28 extern POBJECT_TYPE CmiKeyType
;
29 extern PREGISTRY_HIVE CmiVolatileHive
;
31 static BOOLEAN CmiRegistryInitialized
= FALSE
;
34 /* FUNCTIONS ****************************************************************/
37 NtCreateKey(OUT PHANDLE KeyHandle
,
38 IN ACCESS_MASK DesiredAccess
,
39 IN POBJECT_ATTRIBUTES ObjectAttributes
,
41 IN PUNICODE_STRING Class
,
42 IN ULONG CreateOptions
,
43 OUT PULONG Disposition
)
45 UNICODE_STRING RemainingPath
;
46 PKEY_OBJECT KeyObject
;
52 DPRINT("NtCreateKey (Name %wZ KeyHandle %x Root %x)\n",
53 ObjectAttributes
->ObjectName
,
55 ObjectAttributes
->RootDirectory
);
57 Status
= ObFindObject(ObjectAttributes
,
61 if (!NT_SUCCESS(Status
))
66 DPRINT("RemainingPath %wZ\n", &RemainingPath
);
68 if ((RemainingPath
.Buffer
== NULL
) || (RemainingPath
.Buffer
[0] == 0))
70 /* Fail if the key has been deleted */
71 if (((PKEY_OBJECT
) Object
)->Flags
& KO_MARKED_FOR_DELETE
)
73 ObDereferenceObject(Object
);
74 return(STATUS_UNSUCCESSFUL
);
78 *Disposition
= REG_OPENED_EXISTING_KEY
;
80 Status
= ObCreateHandle(PsGetCurrentProcess(),
86 DPRINT("Status %x\n", Status
);
87 ObDereferenceObject(Object
);
91 /* If RemainingPath contains \ we must return error
92 because NtCreateKey don't create trees */
93 Start
= RemainingPath
.Buffer
;
97 End
= wcschr(Start
, L
'\\');
100 ObDereferenceObject(Object
);
101 return STATUS_OBJECT_NAME_NOT_FOUND
;
104 DPRINT("RemainingPath %S ParentObject %x\n", RemainingPath
.Buffer
, Object
);
106 Status
= ObRosCreateObject(KeyHandle
,
111 if (!NT_SUCCESS(Status
))
116 KeyObject
->ParentKey
= Object
;
118 if (CreateOptions
& REG_OPTION_VOLATILE
)
119 KeyObject
->RegistryHive
= CmiVolatileHive
;
121 KeyObject
->RegistryHive
= KeyObject
->ParentKey
->RegistryHive
;
123 KeyObject
->Flags
= 0;
124 KeyObject
->NumberOfSubKeys
= 0;
125 KeyObject
->SizeOfSubKeys
= 0;
126 KeyObject
->SubKeys
= NULL
;
128 /* Acquire hive lock */
129 ExAcquireResourceExclusiveLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
131 /* add key to subkeys of parent if needed */
132 Status
= CmiAddSubKey(KeyObject
->RegistryHive
,
133 KeyObject
->ParentKey
,
139 if (!NT_SUCCESS(Status
))
141 DPRINT("CmiAddSubKey() failed (Status %lx)\n", Status
);
142 /* Release hive lock */
143 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
144 ObDereferenceObject(KeyObject
);
145 ObDereferenceObject(Object
);
146 return STATUS_UNSUCCESSFUL
;
149 RtlCreateUnicodeString(&KeyObject
->Name
,
152 if (KeyObject
->RegistryHive
== KeyObject
->ParentKey
->RegistryHive
)
154 KeyObject
->KeyCell
->ParentKeyOffset
= KeyObject
->ParentKey
->BlockOffset
;
155 KeyObject
->KeyCell
->SecurityKeyOffset
= KeyObject
->ParentKey
->KeyCell
->SecurityKeyOffset
;
159 KeyObject
->KeyCell
->ParentKeyOffset
= -1;
160 KeyObject
->KeyCell
->SecurityKeyOffset
= -1;
161 /* This key must remain in memory unless it is deleted
162 or file is unloaded */
163 ObReferenceObjectByPointer(KeyObject
,
164 STANDARD_RIGHTS_REQUIRED
,
169 CmiAddKeyToList(KeyObject
->ParentKey
, KeyObject
);
171 VERIFY_KEY_OBJECT(KeyObject
);
173 /* Release hive lock */
174 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
176 ObDereferenceObject(KeyObject
);
177 ObDereferenceObject(Object
);
180 *Disposition
= REG_CREATED_NEW_KEY
;
189 NtDeleteKey(IN HANDLE KeyHandle
)
191 PKEY_OBJECT KeyObject
;
194 DPRINT("KeyHandle %x\n", KeyHandle
);
196 /* Verify that the handle is valid and is a registry key */
197 Status
= ObReferenceObjectByHandle(KeyHandle
,
203 if (!NT_SUCCESS(Status
))
208 /* Acquire hive lock */
209 ExAcquireResourceExclusiveLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
211 VERIFY_KEY_OBJECT(KeyObject
);
213 /* Check for subkeys */
214 if (KeyObject
->NumberOfSubKeys
!= 0)
216 Status
= STATUS_CANNOT_DELETE
;
220 /* Set the marked for delete bit in the key object */
221 KeyObject
->Flags
|= KO_MARKED_FOR_DELETE
;
222 Status
= STATUS_SUCCESS
;
225 /* Release hive lock */
226 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
228 DPRINT("PointerCount %lu\n", ObGetObjectPointerCount((PVOID
)KeyObject
));
230 /* Dereference the object */
231 ObDereferenceObject(KeyObject
);
232 if(KeyObject
->RegistryHive
!= KeyObject
->ParentKey
->RegistryHive
)
233 ObDereferenceObject(KeyObject
);
235 DPRINT("PointerCount %lu\n", ObGetObjectPointerCount((PVOID
)KeyObject
));
239 * Hive-Synchronization will not be triggered here. This is done in
240 * CmiObjectDelete() (in regobj.c) after all key-related structures
241 * have been released.
249 NtEnumerateKey(IN HANDLE KeyHandle
,
251 IN KEY_INFORMATION_CLASS KeyInformationClass
,
252 OUT PVOID KeyInformation
,
254 OUT PULONG ResultLength
)
256 PKEY_OBJECT KeyObject
;
257 PREGISTRY_HIVE RegistryHive
;
258 PKEY_CELL KeyCell
, SubKeyCell
;
259 PHASH_TABLE_CELL HashTableBlock
;
260 PKEY_BASIC_INFORMATION BasicInformation
;
261 PKEY_NODE_INFORMATION NodeInformation
;
262 PKEY_FULL_INFORMATION FullInformation
;
263 PDATA_CELL ClassData
;
267 DPRINT("KH %x I %d KIC %x KI %x L %d RL %x\n",
275 /* Verify that the handle is valid and is a registry key */
276 Status
= ObReferenceObjectByHandle(KeyHandle
,
277 KEY_ENUMERATE_SUB_KEYS
,
280 (PVOID
*) &KeyObject
,
282 if (!NT_SUCCESS(Status
))
284 DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status
);
288 /* Acquire hive lock */
289 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
291 VERIFY_KEY_OBJECT(KeyObject
);
293 /* Get pointer to KeyCell */
294 KeyCell
= KeyObject
->KeyCell
;
295 RegistryHive
= KeyObject
->RegistryHive
;
297 /* Get pointer to SubKey */
298 if (Index
>= KeyCell
->NumberOfSubKeys
)
300 if (RegistryHive
== CmiVolatileHive
)
302 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
303 ObDereferenceObject(KeyObject
);
304 DPRINT("No more volatile entries\n");
305 return(STATUS_NO_MORE_ENTRIES
);
310 PKEY_OBJECT CurKey
= NULL
;
312 /* Search volatile keys */
313 for (i
= 0; i
< KeyObject
->NumberOfSubKeys
; i
++)
315 CurKey
= KeyObject
->SubKeys
[i
];
316 if (CurKey
->RegistryHive
== CmiVolatileHive
)
318 if (Index
-- == KeyObject
->NumberOfSubKeys
)
322 if (Index
>= KeyCell
->NumberOfSubKeys
)
324 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
325 ObDereferenceObject(KeyObject
);
326 DPRINT("No more non-volatile entries\n");
327 return(STATUS_NO_MORE_ENTRIES
);
329 SubKeyCell
= CurKey
->KeyCell
;
334 if (KeyCell
->HashTableOffset
== (BLOCK_OFFSET
)-1)
336 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
337 ObDereferenceObject(KeyObject
);
338 return(STATUS_NO_MORE_ENTRIES
);
341 HashTableBlock
= CmiGetBlock(RegistryHive
, KeyCell
->HashTableOffset
, NULL
);
342 if (HashTableBlock
== NULL
)
344 DPRINT("CmiGetBlock() failed\n");
345 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
346 ObDereferenceObject(KeyObject
);
347 return STATUS_UNSUCCESSFUL
;
349 SubKeyCell
= CmiGetKeyFromHashByIndex(RegistryHive
,
354 if (SubKeyCell
== NULL
)
356 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
357 ObDereferenceObject(KeyObject
);
358 DPRINT("No more entries\n");
359 return(STATUS_NO_MORE_ENTRIES
);
362 Status
= STATUS_SUCCESS
;
363 switch (KeyInformationClass
)
365 case KeyBasicInformation
:
366 /* Check size of buffer */
367 NameSize
= SubKeyCell
->NameSize
;
368 if (SubKeyCell
->Flags
& REG_KEY_NAME_PACKED
)
370 NameSize
*= sizeof(WCHAR
);
372 *ResultLength
= sizeof(KEY_BASIC_INFORMATION
) + NameSize
;
374 if (Length
< *ResultLength
)
376 Status
= STATUS_BUFFER_OVERFLOW
;
380 /* Fill buffer with requested info */
381 BasicInformation
= (PKEY_BASIC_INFORMATION
) KeyInformation
;
382 BasicInformation
->LastWriteTime
.u
.LowPart
= SubKeyCell
->LastWriteTime
.u
.LowPart
;
383 BasicInformation
->LastWriteTime
.u
.HighPart
= SubKeyCell
->LastWriteTime
.u
.HighPart
;
384 BasicInformation
->TitleIndex
= Index
;
385 BasicInformation
->NameLength
= NameSize
;
387 if (SubKeyCell
->Flags
& REG_KEY_NAME_PACKED
)
389 CmiCopyPackedName(BasicInformation
->Name
,
391 SubKeyCell
->NameSize
);
395 RtlCopyMemory(BasicInformation
->Name
,
397 SubKeyCell
->NameSize
);
402 case KeyNodeInformation
:
403 /* Check size of buffer */
404 if (SubKeyCell
->Flags
& REG_KEY_NAME_PACKED
)
406 NameSize
= SubKeyCell
->NameSize
* sizeof(WCHAR
);
410 NameSize
= SubKeyCell
->NameSize
;
412 *ResultLength
= sizeof(KEY_NODE_INFORMATION
) +
413 NameSize
+ SubKeyCell
->ClassSize
;
415 if (Length
< *ResultLength
)
417 Status
= STATUS_BUFFER_OVERFLOW
;
421 /* Fill buffer with requested info */
422 NodeInformation
= (PKEY_NODE_INFORMATION
) KeyInformation
;
423 NodeInformation
->LastWriteTime
.u
.LowPart
= SubKeyCell
->LastWriteTime
.u
.LowPart
;
424 NodeInformation
->LastWriteTime
.u
.HighPart
= SubKeyCell
->LastWriteTime
.u
.HighPart
;
425 NodeInformation
->TitleIndex
= Index
;
426 NodeInformation
->ClassOffset
= sizeof(KEY_NODE_INFORMATION
) + NameSize
;
427 NodeInformation
->ClassLength
= SubKeyCell
->ClassSize
;
428 NodeInformation
->NameLength
= NameSize
;
430 if (SubKeyCell
->Flags
& REG_KEY_NAME_PACKED
)
432 CmiCopyPackedName(BasicInformation
->Name
,
434 SubKeyCell
->NameSize
);
438 RtlCopyMemory(BasicInformation
->Name
,
440 SubKeyCell
->NameSize
);
443 if (SubKeyCell
->ClassSize
!= 0)
445 ClassData
=CmiGetBlock(KeyObject
->RegistryHive
,
446 SubKeyCell
->ClassNameOffset
,
448 wcsncpy(NodeInformation
->Name
+ SubKeyCell
->NameSize
,
449 (PWCHAR
)ClassData
->Data
,
450 SubKeyCell
->ClassSize
);
455 case KeyFullInformation
:
456 /* Check size of buffer */
457 *ResultLength
= sizeof(KEY_FULL_INFORMATION
) +
458 SubKeyCell
->ClassSize
;
460 if (Length
< *ResultLength
)
462 Status
= STATUS_BUFFER_OVERFLOW
;
466 /* Fill buffer with requested info */
467 FullInformation
= (PKEY_FULL_INFORMATION
) KeyInformation
;
468 FullInformation
->LastWriteTime
.u
.LowPart
= SubKeyCell
->LastWriteTime
.u
.LowPart
;
469 FullInformation
->LastWriteTime
.u
.HighPart
= SubKeyCell
->LastWriteTime
.u
.HighPart
;
470 FullInformation
->TitleIndex
= Index
;
471 FullInformation
->ClassOffset
= sizeof(KEY_FULL_INFORMATION
) -
473 FullInformation
->ClassLength
= SubKeyCell
->ClassSize
;
474 FullInformation
->SubKeys
= SubKeyCell
->NumberOfSubKeys
;
475 FullInformation
->MaxNameLen
=
476 CmiGetMaxNameLength(RegistryHive
, SubKeyCell
);
477 FullInformation
->MaxClassLen
=
478 CmiGetMaxClassLength(RegistryHive
, SubKeyCell
);
479 FullInformation
->Values
= SubKeyCell
->NumberOfValues
;
480 FullInformation
->MaxValueNameLen
=
481 CmiGetMaxValueNameLength(RegistryHive
, SubKeyCell
);
482 FullInformation
->MaxValueDataLen
=
483 CmiGetMaxValueDataLength(RegistryHive
, SubKeyCell
);
484 if (SubKeyCell
->ClassSize
!= 0)
486 ClassData
= CmiGetBlock(KeyObject
->RegistryHive
,
487 SubKeyCell
->ClassNameOffset
,
489 wcsncpy(FullInformation
->Class
,
490 (PWCHAR
)ClassData
->Data
,
491 SubKeyCell
->ClassSize
);
497 DPRINT1("Not handling 0x%x\n", KeyInformationClass
);
501 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
502 ObDereferenceObject(KeyObject
);
504 DPRINT("Returning status %x\n", Status
);
511 NtEnumerateValueKey(IN HANDLE KeyHandle
,
513 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
,
514 OUT PVOID KeyValueInformation
,
516 OUT PULONG ResultLength
)
519 PKEY_OBJECT KeyObject
;
520 PREGISTRY_HIVE RegistryHive
;
522 PVALUE_CELL ValueCell
;
524 PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation
;
525 PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation
;
526 PKEY_VALUE_FULL_INFORMATION ValueFullInformation
;
528 DPRINT("KH %x I %d KVIC %x KVI %x L %d RL %x\n",
531 KeyValueInformationClass
,
536 /* Verify that the handle is valid and is a registry key */
537 Status
= ObReferenceObjectByHandle(KeyHandle
,
541 (PVOID
*) &KeyObject
,
544 if (!NT_SUCCESS(Status
))
549 /* Acquire hive lock */
550 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
552 VERIFY_KEY_OBJECT(KeyObject
);
554 /* Get pointer to KeyCell */
555 KeyCell
= KeyObject
->KeyCell
;
556 RegistryHive
= KeyObject
->RegistryHive
;
558 /* Get Value block of interest */
559 Status
= CmiGetValueFromKeyByIndex(RegistryHive
,
564 if (!NT_SUCCESS(Status
))
566 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
567 ObDereferenceObject(KeyObject
);
571 if (ValueCell
!= NULL
)
573 switch (KeyValueInformationClass
)
575 case KeyValueBasicInformation
:
576 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
578 *ResultLength
= sizeof(KEY_VALUE_BASIC_INFORMATION
) +
579 (ValueCell
->NameSize
+ 1) * sizeof(WCHAR
);
583 *ResultLength
= sizeof(KEY_VALUE_BASIC_INFORMATION
) +
584 ValueCell
->NameSize
+ sizeof(WCHAR
);
586 if (Length
< *ResultLength
)
588 Status
= STATUS_BUFFER_OVERFLOW
;
592 ValueBasicInformation
= (PKEY_VALUE_BASIC_INFORMATION
)
594 ValueBasicInformation
->TitleIndex
= 0;
595 ValueBasicInformation
->Type
= ValueCell
->DataType
;
596 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
598 ValueBasicInformation
->NameLength
=
599 (ValueCell
->NameSize
+ 1) * sizeof(WCHAR
);
600 CmiCopyPackedName(ValueBasicInformation
->Name
,
602 ValueCell
->NameSize
);
603 ValueBasicInformation
->Name
[ValueCell
->NameSize
] = 0;
607 ValueBasicInformation
->NameLength
=
608 ValueCell
->NameSize
+ sizeof(WCHAR
);
609 RtlCopyMemory(ValueBasicInformation
->Name
,
611 ValueCell
->NameSize
* sizeof(WCHAR
));
612 ValueBasicInformation
->Name
[ValueCell
->NameSize
/ sizeof(WCHAR
)] = 0;
617 case KeyValuePartialInformation
:
618 *ResultLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) +
619 (ValueCell
->DataSize
& LONG_MAX
);
620 if (Length
< *ResultLength
)
622 Status
= STATUS_BUFFER_OVERFLOW
;
626 ValuePartialInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)
628 ValuePartialInformation
->TitleIndex
= 0;
629 ValuePartialInformation
->Type
= ValueCell
->DataType
;
630 ValuePartialInformation
->DataLength
= ValueCell
->DataSize
& LONG_MAX
;
631 if(ValueCell
->DataSize
>0)
633 DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, NULL
);
634 RtlCopyMemory(ValuePartialInformation
->Data
,
636 ValueCell
->DataSize
& LONG_MAX
);
640 RtlCopyMemory(ValuePartialInformation
->Data
,
641 &ValueCell
->DataOffset
,
642 ValueCell
->DataSize
& LONG_MAX
);
644 DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, NULL
);
648 case KeyValueFullInformation
:
649 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
651 *ResultLength
= sizeof(KEY_VALUE_FULL_INFORMATION
) +
652 (ValueCell
->NameSize
+ 1) * sizeof(WCHAR
) +
653 (ValueCell
->DataSize
& LONG_MAX
);
657 *ResultLength
= sizeof(KEY_VALUE_FULL_INFORMATION
) +
658 ValueCell
->NameSize
+ sizeof(WCHAR
) +
659 (ValueCell
->DataSize
& LONG_MAX
);
661 if (Length
< *ResultLength
)
663 Status
= STATUS_BUFFER_OVERFLOW
;
667 ValueFullInformation
= (PKEY_VALUE_FULL_INFORMATION
)
669 ValueFullInformation
->TitleIndex
= 0;
670 ValueFullInformation
->Type
= ValueCell
->DataType
;
671 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
673 ValueFullInformation
->NameLength
=
674 (ValueCell
->NameSize
+ 1) * sizeof(WCHAR
);
676 CmiCopyPackedName(ValueFullInformation
->Name
,
678 ValueCell
->NameSize
);
679 ValueFullInformation
->Name
[ValueCell
->NameSize
] = 0;
683 ValueFullInformation
->NameLength
=
684 ValueCell
->NameSize
+ sizeof(WCHAR
);
685 RtlCopyMemory(ValueFullInformation
->Name
,
687 ValueCell
->NameSize
);
688 ValueFullInformation
->Name
[ValueCell
->NameSize
/ sizeof(WCHAR
)] = 0;
690 ValueFullInformation
->DataOffset
=
691 (ULONG
)ValueFullInformation
->Name
- (ULONG
)ValueFullInformation
+
692 ValueFullInformation
->NameLength
;
693 ValueFullInformation
->DataOffset
=
694 (ValueFullInformation
->DataOffset
+ 3) & 0xfffffffc;
695 ValueFullInformation
->DataLength
= ValueCell
->DataSize
& LONG_MAX
;
696 if (ValueCell
->DataSize
> 0)
698 DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, NULL
);
699 RtlCopyMemory((PCHAR
) ValueFullInformation
700 + ValueFullInformation
->DataOffset
,
702 ValueCell
->DataSize
& LONG_MAX
);
706 RtlCopyMemory((PCHAR
) ValueFullInformation
707 + ValueFullInformation
->DataOffset
,
708 &ValueCell
->DataOffset
,
709 ValueCell
->DataSize
& LONG_MAX
);
715 DPRINT1("Not handling 0x%x\n", KeyValueInformationClass
);
721 Status
= STATUS_UNSUCCESSFUL
;
724 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
725 ObDereferenceObject(KeyObject
);
732 NtFlushKey(IN HANDLE KeyHandle
)
735 PKEY_OBJECT KeyObject
;
736 PREGISTRY_HIVE RegistryHive
;
738 DPRINT("NtFlushKey (KeyHandle %lx) called\n", KeyHandle
);
740 /* Verify that the handle is valid and is a registry key */
741 Status
= ObReferenceObjectByHandle(KeyHandle
,
747 if (!NT_SUCCESS(Status
))
752 VERIFY_KEY_OBJECT(KeyObject
);
754 RegistryHive
= KeyObject
->RegistryHive
;
756 /* Acquire hive lock */
757 ExAcquireResourceExclusiveLite(&RegistryHive
->HiveResource
,
760 if (IsNoFileHive(RegistryHive
))
762 Status
= STATUS_SUCCESS
;
766 /* Flush non-volatile hive */
767 Status
= CmiFlushRegistryHive(RegistryHive
);
770 ExReleaseResourceLite(&RegistryHive
->HiveResource
);
772 ObDereferenceObject(KeyObject
);
774 return STATUS_SUCCESS
;
779 NtOpenKey(OUT PHANDLE KeyHandle
,
780 IN ACCESS_MASK DesiredAccess
,
781 IN POBJECT_ATTRIBUTES ObjectAttributes
)
783 UNICODE_STRING RemainingPath
;
787 DPRINT("NtOpenFile(KH %x DA %x OA %x OA->ON '%wZ'\n",
791 ObjectAttributes
? ObjectAttributes
->ObjectName
: NULL
);
793 RemainingPath
.Buffer
= NULL
;
794 Status
= ObFindObject(ObjectAttributes
,
798 if (!NT_SUCCESS(Status
))
803 VERIFY_KEY_OBJECT((PKEY_OBJECT
) Object
);
805 DPRINT("RemainingPath '%wZ'\n", &RemainingPath
);
807 if ((RemainingPath
.Buffer
!= NULL
) && (RemainingPath
.Buffer
[0] != 0))
809 ObDereferenceObject(Object
);
810 return(STATUS_UNSUCCESSFUL
);
813 /* Fail if the key has been deleted */
814 if (((PKEY_OBJECT
)Object
)->Flags
& KO_MARKED_FOR_DELETE
)
816 ObDereferenceObject(Object
);
817 return(STATUS_UNSUCCESSFUL
);
820 Status
= ObCreateHandle(PsGetCurrentProcess(),
825 ObDereferenceObject(Object
);
827 if (!NT_SUCCESS(Status
))
832 return(STATUS_SUCCESS
);
837 NtQueryKey(IN HANDLE KeyHandle
,
838 IN KEY_INFORMATION_CLASS KeyInformationClass
,
839 OUT PVOID KeyInformation
,
841 OUT PULONG ResultLength
)
843 PKEY_BASIC_INFORMATION BasicInformation
;
844 PKEY_NODE_INFORMATION NodeInformation
;
845 PKEY_FULL_INFORMATION FullInformation
;
846 PREGISTRY_HIVE RegistryHive
;
847 PDATA_CELL ClassData
;
848 PKEY_OBJECT KeyObject
;
852 DPRINT("KH %x KIC %x KI %x L %d RL %x\n",
859 /* Verify that the handle is valid and is a registry key */
860 Status
= ObReferenceObjectByHandle(KeyHandle
,
864 (PVOID
*) &KeyObject
,
866 if (!NT_SUCCESS(Status
))
871 /* Acquire hive lock */
872 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
874 VERIFY_KEY_OBJECT(KeyObject
);
876 /* Get pointer to KeyCell */
877 KeyCell
= KeyObject
->KeyCell
;
878 RegistryHive
= KeyObject
->RegistryHive
;
880 Status
= STATUS_SUCCESS
;
881 switch (KeyInformationClass
)
883 case KeyBasicInformation
:
884 /* Check size of buffer */
885 *ResultLength
= sizeof(KEY_BASIC_INFORMATION
) +
886 KeyObject
->Name
.Length
;
888 if (Length
< *ResultLength
)
890 Status
= STATUS_BUFFER_OVERFLOW
;
894 /* Fill buffer with requested info */
895 BasicInformation
= (PKEY_BASIC_INFORMATION
) KeyInformation
;
896 BasicInformation
->LastWriteTime
.u
.LowPart
= KeyCell
->LastWriteTime
.u
.LowPart
;
897 BasicInformation
->LastWriteTime
.u
.HighPart
= KeyCell
->LastWriteTime
.u
.HighPart
;
898 BasicInformation
->TitleIndex
= 0;
899 BasicInformation
->NameLength
= KeyObject
->Name
.Length
;
900 RtlCopyMemory(BasicInformation
->Name
,
901 KeyObject
->Name
.Buffer
,
902 KeyObject
->Name
.Length
);
906 case KeyNodeInformation
:
907 /* Check size of buffer */
908 *ResultLength
= sizeof(KEY_NODE_INFORMATION
) +
909 KeyObject
->Name
.Length
+ KeyCell
->ClassSize
;
911 if (Length
< *ResultLength
)
913 Status
= STATUS_BUFFER_OVERFLOW
;
917 /* Fill buffer with requested info */
918 NodeInformation
= (PKEY_NODE_INFORMATION
) KeyInformation
;
919 NodeInformation
->LastWriteTime
.u
.LowPart
= KeyCell
->LastWriteTime
.u
.LowPart
;
920 NodeInformation
->LastWriteTime
.u
.HighPart
= KeyCell
->LastWriteTime
.u
.HighPart
;
921 NodeInformation
->TitleIndex
= 0;
922 NodeInformation
->ClassOffset
= sizeof(KEY_NODE_INFORMATION
) +
923 KeyObject
->Name
.Length
;
924 NodeInformation
->ClassLength
= KeyCell
->ClassSize
;
925 NodeInformation
->NameLength
= KeyObject
->Name
.Length
;
926 RtlCopyMemory(NodeInformation
->Name
,
927 KeyObject
->Name
.Buffer
,
928 KeyObject
->Name
.Length
);
930 if (KeyCell
->ClassSize
!= 0)
932 ClassData
= CmiGetBlock(KeyObject
->RegistryHive
,
933 KeyCell
->ClassNameOffset
,
935 wcsncpy(NodeInformation
->Name
+ KeyObject
->Name
.Length
,
936 (PWCHAR
)ClassData
->Data
,
942 case KeyFullInformation
:
943 /* Check size of buffer */
944 *ResultLength
= sizeof(KEY_FULL_INFORMATION
) +
947 if (Length
< *ResultLength
)
949 Status
= STATUS_BUFFER_OVERFLOW
;
953 /* Fill buffer with requested info */
954 FullInformation
= (PKEY_FULL_INFORMATION
) KeyInformation
;
955 FullInformation
->LastWriteTime
.u
.LowPart
= KeyCell
->LastWriteTime
.u
.LowPart
;
956 FullInformation
->LastWriteTime
.u
.HighPart
= KeyCell
->LastWriteTime
.u
.HighPart
;
957 FullInformation
->TitleIndex
= 0;
958 FullInformation
->ClassOffset
= sizeof(KEY_FULL_INFORMATION
) - sizeof(WCHAR
);
959 FullInformation
->ClassLength
= KeyCell
->ClassSize
;
960 FullInformation
->SubKeys
= KeyCell
->NumberOfSubKeys
;
961 FullInformation
->MaxNameLen
=
962 CmiGetMaxNameLength(RegistryHive
, KeyCell
);
963 FullInformation
->MaxClassLen
=
964 CmiGetMaxClassLength(RegistryHive
, KeyCell
);
965 FullInformation
->Values
= KeyCell
->NumberOfValues
;
966 FullInformation
->MaxValueNameLen
=
967 CmiGetMaxValueNameLength(RegistryHive
, KeyCell
);
968 FullInformation
->MaxValueDataLen
=
969 CmiGetMaxValueDataLength(RegistryHive
, KeyCell
);
970 if (KeyCell
->ClassSize
!= 0)
972 ClassData
=CmiGetBlock(KeyObject
->RegistryHive
,
973 KeyCell
->ClassNameOffset
,
975 wcsncpy(FullInformation
->Class
,
976 (PWCHAR
)ClassData
->Data
,
982 DPRINT1("Not handling 0x%x\n", KeyInformationClass
);
986 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
987 ObDereferenceObject(KeyObject
);
994 NtQueryValueKey(IN HANDLE KeyHandle
,
995 IN PUNICODE_STRING ValueName
,
996 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
,
997 OUT PVOID KeyValueInformation
,
999 OUT PULONG ResultLength
)
1002 PKEY_OBJECT KeyObject
;
1003 PREGISTRY_HIVE RegistryHive
;
1005 PVALUE_CELL ValueCell
;
1006 PDATA_CELL DataCell
;
1007 PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation
;
1008 PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation
;
1009 PKEY_VALUE_FULL_INFORMATION ValueFullInformation
;
1011 DPRINT("NtQueryValueKey(KeyHandle %x ValueName %S Length %x)\n",
1012 KeyHandle
, ValueName
->Buffer
, Length
);
1014 /* Verify that the handle is valid and is a registry key */
1015 Status
= ObReferenceObjectByHandle(KeyHandle
,
1019 (PVOID
*)&KeyObject
,
1022 if (!NT_SUCCESS(Status
))
1024 DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status
);
1028 /* Acquire hive lock */
1029 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1031 VERIFY_KEY_OBJECT(KeyObject
);
1033 /* Get pointer to KeyCell */
1034 KeyCell
= KeyObject
->KeyCell
;
1035 RegistryHive
= KeyObject
->RegistryHive
;
1037 /* Get Value block of interest */
1038 Status
= CmiScanKeyForValue(RegistryHive
,
1043 if (!NT_SUCCESS(Status
))
1045 DPRINT("CmiScanKeyForValue() failed with status %x\n", Status
);
1046 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1047 ObDereferenceObject(KeyObject
);
1050 else if (ValueCell
!= NULL
)
1052 switch (KeyValueInformationClass
)
1054 case KeyValueBasicInformation
:
1055 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1057 *ResultLength
= sizeof(KEY_VALUE_BASIC_INFORMATION
) +
1058 (ValueCell
->NameSize
+ 1) * sizeof(WCHAR
);
1062 *ResultLength
= sizeof(KEY_VALUE_BASIC_INFORMATION
) +
1063 ValueCell
->NameSize
+ sizeof(WCHAR
);
1065 if (Length
< *ResultLength
)
1067 Status
= STATUS_BUFFER_TOO_SMALL
;
1071 ValueBasicInformation
= (PKEY_VALUE_BASIC_INFORMATION
)
1072 KeyValueInformation
;
1073 ValueBasicInformation
->TitleIndex
= 0;
1074 ValueBasicInformation
->Type
= ValueCell
->DataType
;
1075 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1077 ValueBasicInformation
->NameLength
=
1078 (ValueCell
->NameSize
+ 1) * sizeof(WCHAR
);
1079 CmiCopyPackedName(ValueBasicInformation
->Name
,
1081 ValueCell
->NameSize
);
1082 ValueBasicInformation
->Name
[ValueCell
->NameSize
] = 0;
1086 ValueBasicInformation
->NameLength
=
1087 ValueCell
->NameSize
+ sizeof(WCHAR
);
1088 RtlCopyMemory(ValueBasicInformation
->Name
,
1090 ValueCell
->NameSize
* sizeof(WCHAR
));
1091 ValueBasicInformation
->Name
[ValueCell
->NameSize
/ sizeof(WCHAR
)] = 0;
1096 case KeyValuePartialInformation
:
1097 *ResultLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
)
1098 + (ValueCell
->DataSize
& LONG_MAX
);
1099 if (Length
< *ResultLength
)
1101 Status
= STATUS_BUFFER_TOO_SMALL
;
1105 ValuePartialInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)
1106 KeyValueInformation
;
1107 ValuePartialInformation
->TitleIndex
= 0;
1108 ValuePartialInformation
->Type
= ValueCell
->DataType
;
1109 ValuePartialInformation
->DataLength
= ValueCell
->DataSize
& LONG_MAX
;
1110 if (ValueCell
->DataSize
> 0)
1112 DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, NULL
);
1113 RtlCopyMemory(ValuePartialInformation
->Data
,
1115 ValueCell
->DataSize
& LONG_MAX
);
1119 RtlCopyMemory(ValuePartialInformation
->Data
,
1120 &ValueCell
->DataOffset
,
1121 ValueCell
->DataSize
& LONG_MAX
);
1126 case KeyValueFullInformation
:
1127 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1129 *ResultLength
= sizeof(KEY_VALUE_FULL_INFORMATION
) +
1130 (ValueCell
->NameSize
+ 1) * sizeof(WCHAR
) +
1131 (ValueCell
->DataSize
& LONG_MAX
);
1135 *ResultLength
= sizeof(KEY_VALUE_FULL_INFORMATION
) +
1136 ValueCell
->NameSize
+ sizeof(WCHAR
) +
1137 (ValueCell
->DataSize
& LONG_MAX
);
1139 if (Length
< *ResultLength
)
1141 Status
= STATUS_BUFFER_TOO_SMALL
;
1145 ValueFullInformation
= (PKEY_VALUE_FULL_INFORMATION
)
1146 KeyValueInformation
;
1147 ValueFullInformation
->TitleIndex
= 0;
1148 ValueFullInformation
->Type
= ValueCell
->DataType
;
1149 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1151 ValueFullInformation
->NameLength
=
1152 (ValueCell
->NameSize
+ 1) * sizeof(WCHAR
);
1153 CmiCopyPackedName(ValueFullInformation
->Name
,
1155 ValueCell
->NameSize
);
1156 ValueFullInformation
->Name
[ValueCell
->NameSize
] = 0;
1160 ValueFullInformation
->NameLength
=
1161 ValueCell
->NameSize
+ sizeof(WCHAR
);
1162 RtlCopyMemory(ValueFullInformation
->Name
,
1164 ValueCell
->NameSize
);
1165 ValueFullInformation
->Name
[ValueCell
->NameSize
/ sizeof(WCHAR
)] = 0;
1167 ValueFullInformation
->DataOffset
=
1168 (ULONG
)ValueFullInformation
->Name
- (ULONG
)ValueFullInformation
+
1169 ValueFullInformation
->NameLength
;
1170 ValueFullInformation
->DataOffset
=
1171 (ValueFullInformation
->DataOffset
+ 3) & 0xfffffffc;
1172 ValueFullInformation
->DataLength
= ValueCell
->DataSize
& LONG_MAX
;
1173 if (ValueCell
->DataSize
> 0)
1175 DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, NULL
);
1176 RtlCopyMemory((PCHAR
) ValueFullInformation
1177 + ValueFullInformation
->DataOffset
,
1179 ValueCell
->DataSize
& LONG_MAX
);
1183 RtlCopyMemory((PCHAR
) ValueFullInformation
1184 + ValueFullInformation
->DataOffset
,
1185 &ValueCell
->DataOffset
,
1186 ValueCell
->DataSize
& LONG_MAX
);
1191 DPRINT1("Not handling 0x%x\n", KeyValueInformationClass
);
1197 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
1200 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1201 ObDereferenceObject(KeyObject
);
1208 NtSetValueKey(IN HANDLE KeyHandle
,
1209 IN PUNICODE_STRING ValueName
,
1210 IN ULONG TitleIndex
,
1216 PKEY_OBJECT KeyObject
;
1217 PREGISTRY_HIVE RegistryHive
;
1219 PVALUE_CELL ValueCell
;
1220 BLOCK_OFFSET VBOffset
;
1221 PDATA_CELL DataCell
;
1222 PDATA_CELL NewDataCell
;
1224 ULONG DesiredAccess
;
1226 DPRINT("NtSetValueKey(KeyHandle %x ValueName '%wZ' Type %d)\n",
1227 KeyHandle
, ValueName
, Type
);
1229 DesiredAccess
= KEY_SET_VALUE
;
1230 if (Type
== REG_LINK
)
1231 DesiredAccess
|= KEY_CREATE_LINK
;
1233 /* Verify that the handle is valid and is a registry key */
1234 Status
= ObReferenceObjectByHandle(KeyHandle
,
1238 (PVOID
*)&KeyObject
,
1240 if (!NT_SUCCESS(Status
))
1243 /* Acquire hive lock exclucively */
1244 ExAcquireResourceExclusiveLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1246 VERIFY_KEY_OBJECT(KeyObject
);
1248 /* Get pointer to key cell */
1249 KeyCell
= KeyObject
->KeyCell
;
1250 RegistryHive
= KeyObject
->RegistryHive
;
1251 Status
= CmiScanKeyForValue(RegistryHive
,
1256 if (!NT_SUCCESS(Status
))
1258 DPRINT("Value not found. Status 0x%X\n", Status
);
1260 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1261 ObDereferenceObject(KeyObject
);
1265 if (ValueCell
== NULL
)
1267 DPRINT("Allocate new value cell\n");
1268 Status
= CmiAddValueToKey(RegistryHive
,
1273 if (NT_SUCCESS(Status
))
1275 CmiMarkBlockDirty(RegistryHive
, VBOffset
);
1279 if (!NT_SUCCESS(Status
))
1281 DPRINT("Cannot add value. Status 0x%X\n", Status
);
1283 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1284 ObDereferenceObject(KeyObject
);
1288 DPRINT("DataSize %lu\n", DataSize
);
1289 DPRINT("ValueCell %p\n", ValueCell
);
1290 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
1294 /* If datasize <= 4 then write in valueblock directly */
1295 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
1296 if ((ValueCell
->DataSize
>= 0) &&
1297 (DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, NULL
)))
1299 CmiDestroyBlock(RegistryHive
, DataCell
, ValueCell
->DataOffset
);
1302 RtlCopyMemory(&ValueCell
->DataOffset
, Data
, DataSize
);
1303 ValueCell
->DataSize
= DataSize
| 0x80000000;
1304 ValueCell
->DataType
= Type
;
1305 RtlMoveMemory(&ValueCell
->DataOffset
, Data
, DataSize
);
1306 CmiMarkBlockDirty(RegistryHive
, VBOffset
);
1308 else if (DataSize
<= (ULONG
) (ValueCell
->DataSize
& 0x7fffffff))
1310 /* If new data size is <= current then overwrite current data */
1311 DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
,&pBin
);
1312 RtlZeroMemory(DataCell
->Data
, ValueCell
->DataSize
);
1313 RtlCopyMemory(DataCell
->Data
, Data
, DataSize
);
1314 ValueCell
->DataSize
= DataSize
;
1315 ValueCell
->DataType
= Type
;
1317 /* Update time of heap */
1318 if (!IsNoFileHive(RegistryHive
))
1320 NtQuerySystemTime(&pBin
->DateModified
);
1322 CmiMarkBlockDirty(RegistryHive
, ValueCell
->DataOffset
);
1327 * New data size is larger than the current, destroy current
1328 * data block and allocate a new one.
1330 BLOCK_OFFSET NewOffset
;
1332 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
1334 if ((ValueCell
->DataSize
>= 0) &&
1335 (DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, NULL
)))
1337 CmiDestroyBlock(RegistryHive
, DataCell
, ValueCell
->DataOffset
);
1338 ValueCell
->DataSize
= 0;
1339 ValueCell
->DataType
= 0;
1340 ValueCell
->DataOffset
= 0xffffffff;
1343 Status
= CmiAllocateBlock(RegistryHive
,
1344 (PVOID
*)&NewDataCell
,
1347 if (!NT_SUCCESS(Status
))
1349 DPRINT("CmiAllocateBlock() failed (Status %lx)\n", Status
);
1351 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1352 ObDereferenceObject(KeyObject
);
1357 RtlCopyMemory(&NewDataCell
->Data
[0], Data
, DataSize
);
1358 ValueCell
->DataSize
= DataSize
;
1359 ValueCell
->DataType
= Type
;
1360 ValueCell
->DataOffset
= NewOffset
;
1361 CmiMarkBlockDirty(RegistryHive
, ValueCell
->DataOffset
);
1365 if ((_wcsicmp(ValueName
->Buffer
, L
"SymbolicLinkValue") == 0) &&
1368 KeyCell
->Flags
|= REG_KEY_LINK_CELL
;
1369 CmiMarkBlockDirty(RegistryHive
, KeyObject
->BlockOffset
);
1372 /* Update time of heap */
1373 if (!IsNoFileHive(RegistryHive
) && CmiGetBlock(RegistryHive
, VBOffset
, &pBin
))
1375 NtQuerySystemTime(&pBin
->DateModified
);
1378 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1379 ObDereferenceObject(KeyObject
);
1383 DPRINT("Return Status 0x%X\n", Status
);
1390 NtDeleteValueKey (IN HANDLE KeyHandle
,
1391 IN PUNICODE_STRING ValueName
)
1393 PKEY_OBJECT KeyObject
;
1396 /* Verify that the handle is valid and is a registry key */
1397 Status
= ObReferenceObjectByHandle(KeyHandle
,
1401 (PVOID
*)&KeyObject
,
1403 if (!NT_SUCCESS(Status
))
1408 /* Acquire hive lock */
1409 ExAcquireResourceExclusiveLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1411 VERIFY_KEY_OBJECT(KeyObject
);
1413 Status
= CmiDeleteValueFromKey(KeyObject
->RegistryHive
,
1415 KeyObject
->BlockOffset
,
1418 /* Release hive lock */
1419 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1421 ObDereferenceObject(KeyObject
);
1431 * KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
1432 * KeyObjectAttributes->Name specifies the name of the key to load.
1435 NtLoadKey (IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
1436 IN POBJECT_ATTRIBUTES FileObjectAttributes
)
1438 return NtLoadKey2 (KeyObjectAttributes
,
1439 FileObjectAttributes
,
1446 * KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
1447 * KeyObjectAttributes->Name specifies the name of the key to load.
1448 * Flags can be 0 or REG_NO_LAZY_FLUSH.
1451 NtLoadKey2 (IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
1452 IN POBJECT_ATTRIBUTES FileObjectAttributes
,
1455 POBJECT_NAME_INFORMATION NameInfo
;
1456 PUNICODE_STRING NamePointer
;
1462 DPRINT ("NtLoadKey2() called\n");
1465 if (!SeSinglePrivilegeCheck (SeRestorePrivilege
, KeGetPreviousMode ()))
1466 return STATUS_PRIVILEGE_NOT_HELD
;
1469 if (FileObjectAttributes
->RootDirectory
!= NULL
)
1472 sizeof(OBJECT_NAME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
);
1473 Buffer
= ExAllocatePool (NonPagedPool
,
1476 return STATUS_INSUFFICIENT_RESOURCES
;
1478 Status
= NtQueryObject (FileObjectAttributes
->RootDirectory
,
1479 ObjectNameInformation
,
1483 if (!NT_SUCCESS(Status
))
1485 DPRINT1 ("NtQueryObject() failed (Status %lx)\n", Status
);
1486 ExFreePool (Buffer
);
1490 NameInfo
= (POBJECT_NAME_INFORMATION
)Buffer
;
1491 DPRINT ("ObjectPath: '%wZ' Length %hu\n",
1492 &NameInfo
->Name
, NameInfo
->Name
.Length
);
1494 NameInfo
->Name
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
1495 if (FileObjectAttributes
->ObjectName
->Buffer
[0] != L
'\\')
1497 RtlAppendUnicodeToString (&NameInfo
->Name
,
1499 DPRINT ("ObjectPath: '%wZ' Length %hu\n",
1500 &NameInfo
->Name
, NameInfo
->Name
.Length
);
1502 RtlAppendUnicodeStringToString (&NameInfo
->Name
,
1503 FileObjectAttributes
->ObjectName
);
1505 DPRINT ("ObjectPath: '%wZ' Length %hu\n",
1506 &NameInfo
->Name
, NameInfo
->Name
.Length
);
1507 NamePointer
= &NameInfo
->Name
;
1511 if (FileObjectAttributes
->ObjectName
->Buffer
[0] == L
'\\')
1514 NamePointer
= FileObjectAttributes
->ObjectName
;
1519 sizeof(OBJECT_NAME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
);
1520 Buffer
= ExAllocatePool (NonPagedPool
,
1523 return STATUS_INSUFFICIENT_RESOURCES
;
1525 NameInfo
= (POBJECT_NAME_INFORMATION
)Buffer
;
1526 NameInfo
->Name
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
1527 NameInfo
->Name
.Length
= 0;
1528 NameInfo
->Name
.Buffer
= (PWSTR
)((ULONG_PTR
)Buffer
+ sizeof(OBJECT_NAME_INFORMATION
));
1529 NameInfo
->Name
.Buffer
[0] = 0;
1531 RtlAppendUnicodeToString (&NameInfo
->Name
,
1533 RtlAppendUnicodeStringToString (&NameInfo
->Name
,
1534 FileObjectAttributes
->ObjectName
);
1536 NamePointer
= &NameInfo
->Name
;
1540 DPRINT ("Full name: '%wZ'\n", NamePointer
);
1542 Status
= CmiLoadHive (KeyObjectAttributes
,
1545 if (!NT_SUCCESS (Status
))
1547 DPRINT1 ("CmiLoadHive() failed (Status %lx)\n", Status
);
1551 ExFreePool (Buffer
);
1558 NtNotifyChangeKey (IN HANDLE KeyHandle
,
1560 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1561 IN PVOID ApcContext OPTIONAL
,
1562 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1563 IN ULONG CompletionFilter
,
1564 IN BOOLEAN Asynchroneous
,
1565 OUT PVOID ChangeBuffer
,
1567 IN BOOLEAN WatchSubtree
)
1570 return(STATUS_NOT_IMPLEMENTED
);
1575 NtQueryMultipleValueKey (IN HANDLE KeyHandle
,
1576 IN OUT PKEY_VALUE_ENTRY ValueList
,
1577 IN ULONG NumberOfValues
,
1579 IN OUT PULONG Length
,
1580 OUT PULONG ReturnLength
)
1582 PREGISTRY_HIVE RegistryHive
;
1583 PVALUE_CELL ValueCell
;
1584 PKEY_OBJECT KeyObject
;
1585 PDATA_CELL DataCell
;
1586 ULONG BufferLength
= 0;
1592 /* Verify that the handle is valid and is a registry key */
1593 Status
= ObReferenceObjectByHandle(KeyHandle
,
1597 (PVOID
*) &KeyObject
,
1599 if (!NT_SUCCESS(Status
))
1601 DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status
);
1605 /* Acquire hive lock */
1606 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1608 VERIFY_KEY_OBJECT(KeyObject
);
1610 /* Get pointer to KeyCell */
1611 KeyCell
= KeyObject
->KeyCell
;
1612 RegistryHive
= KeyObject
->RegistryHive
;
1614 DataPtr
= (PUCHAR
) Buffer
;
1616 for (i
= 0; i
< NumberOfValues
; i
++)
1618 DPRINT("ValueName: '%wZ'\n", ValueList
[i
].ValueName
);
1620 /* Get Value block of interest */
1621 Status
= CmiScanKeyForValue(RegistryHive
,
1623 ValueList
[i
].ValueName
,
1627 if (!NT_SUCCESS(Status
))
1629 DPRINT("CmiScanKeyForValue() failed with status %x\n", Status
);
1632 else if (ValueCell
== NULL
)
1634 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
1638 BufferLength
= (BufferLength
+ 3) & 0xfffffffc;
1640 if (BufferLength
+ (ValueCell
->DataSize
& LONG_MAX
) <= *Length
)
1642 DataPtr
= (PUCHAR
)(((ULONG
)DataPtr
+ 3) & 0xfffffffc);
1644 ValueList
[i
].Type
= ValueCell
->DataType
;
1645 ValueList
[i
].DataLength
= ValueCell
->DataSize
& LONG_MAX
;
1646 ValueList
[i
].DataOffset
= (ULONG
) DataPtr
- (ULONG
) Buffer
;
1648 if (ValueCell
->DataSize
> 0)
1650 DataCell
= CmiGetBlock(RegistryHive
,
1651 ValueCell
->DataOffset
,
1653 RtlCopyMemory(DataPtr
,
1655 ValueCell
->DataSize
& LONG_MAX
);
1659 RtlCopyMemory(DataPtr
,
1660 &ValueCell
->DataOffset
,
1661 ValueCell
->DataSize
& LONG_MAX
);
1664 DataPtr
+= ValueCell
->DataSize
& LONG_MAX
;
1668 Status
= STATUS_BUFFER_TOO_SMALL
;
1671 BufferLength
+= ValueCell
->DataSize
& LONG_MAX
;
1674 if (NT_SUCCESS(Status
))
1675 *Length
= BufferLength
;
1677 *ReturnLength
= BufferLength
;
1679 /* Release hive lock */
1680 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1682 ObDereferenceObject(KeyObject
);
1684 DPRINT("Return Status 0x%X\n", Status
);
1691 NtReplaceKey (IN POBJECT_ATTRIBUTES ObjectAttributes
,
1693 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes
)
1696 return(STATUS_NOT_IMPLEMENTED
);
1701 NtRestoreKey (IN HANDLE KeyHandle
,
1702 IN HANDLE FileHandle
,
1703 IN ULONG RestoreFlags
)
1706 return(STATUS_NOT_IMPLEMENTED
);
1711 NtSaveKey (IN HANDLE KeyHandle
,
1712 IN HANDLE FileHandle
)
1714 PREGISTRY_HIVE TempHive
;
1715 PKEY_OBJECT KeyObject
;
1718 DPRINT ("NtSaveKey() called\n");
1721 if (!SeSinglePrivilegeCheck (SeBackupPrivilege
, KeGetPreviousMode ()))
1722 return STATUS_PRIVILEGE_NOT_HELD
;
1725 Status
= ObReferenceObjectByHandle (KeyHandle
,
1728 KeGetPreviousMode(),
1729 (PVOID
*)&KeyObject
,
1731 if (!NT_SUCCESS(Status
))
1733 DPRINT1 ("ObReferenceObjectByHandle() failed (Status %lx)\n", Status
);
1737 /* Acquire hive lock exclucively */
1738 ExAcquireResourceExclusiveLite (&KeyObject
->RegistryHive
->HiveResource
,
1741 /* Refuse to save a volatile key */
1742 if (KeyObject
->RegistryHive
== CmiVolatileHive
)
1744 DPRINT1 ("Cannot save a volatile key\n");
1745 ExReleaseResourceLite (&KeyObject
->RegistryHive
->HiveResource
);
1746 ObDereferenceObject (KeyObject
);
1747 return STATUS_ACCESS_DENIED
;
1750 Status
= CmiCreateTempHive(&TempHive
);
1751 if (!NT_SUCCESS(Status
))
1753 DPRINT1 ("CmiCreateTempHive() failed (Status %lx)\n", Status
);
1754 ExReleaseResourceLite (&KeyObject
->RegistryHive
->HiveResource
);
1755 ObDereferenceObject (KeyObject
);
1759 Status
= CmiCopyKey (TempHive
,
1761 KeyObject
->RegistryHive
,
1762 KeyObject
->KeyCell
);
1763 if (!NT_SUCCESS(Status
))
1765 DPRINT1 ("CmiCopyKey() failed (Status %lx)\n", Status
);
1766 CmiRemoveRegistryHive (TempHive
);
1767 ExReleaseResourceLite (&KeyObject
->RegistryHive
->HiveResource
);
1768 ObDereferenceObject (KeyObject
);
1772 Status
= CmiSaveTempHive (TempHive
,
1774 if (!NT_SUCCESS(Status
))
1776 DPRINT1 ("CmiSaveTempHive() failed (Status %lx)\n", Status
);
1779 CmiRemoveRegistryHive (TempHive
);
1781 /* Release hive lock */
1782 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1784 ObDereferenceObject (KeyObject
);
1786 DPRINT ("NtSaveKey() done\n");
1788 return STATUS_SUCCESS
;
1793 NtSetInformationKey (IN HANDLE KeyHandle
,
1794 IN CINT KeyInformationClass
,
1795 IN PVOID KeyInformation
,
1796 IN ULONG KeyInformationLength
)
1799 return(STATUS_NOT_IMPLEMENTED
);
1805 * KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
1806 * KeyObjectAttributes->Name specifies the name of the key to unload.
1809 NtUnloadKey (IN POBJECT_ATTRIBUTES KeyObjectAttributes
)
1811 PREGISTRY_HIVE RegistryHive
;
1814 DPRINT ("NtUnloadKey() called\n");
1817 if (!SeSinglePrivilegeCheck (SeRestorePrivilege
, KeGetPreviousMode ()))
1818 return STATUS_PRIVILEGE_NOT_HELD
;
1821 Status
= CmiDisconnectHive (KeyObjectAttributes
,
1823 if (!NT_SUCCESS (Status
))
1825 DPRINT1 ("CmiDisconnectHive() failed (Status %lx)\n", Status
);
1829 DPRINT ("RegistryHive %p\n", RegistryHive
);
1831 /* Acquire hive list lock exclusively */
1832 ExAcquireResourceExclusiveLite (&CmiHiveListLock
,
1837 if (!IsNoFileHive (RegistryHive
))
1838 CmiFlushRegistryHive (RegistryHive
);
1841 /* Release hive list lock */
1842 ExReleaseResourceLite (&CmiHiveListLock
);
1844 CmiRemoveRegistryHive (RegistryHive
);
1846 DPRINT ("NtUnloadKey() done\n");
1848 return STATUS_SUCCESS
;
1853 NtInitializeRegistry (IN BOOLEAN SetUpBoot
)
1857 if (CmiRegistryInitialized
== TRUE
)
1858 return STATUS_ACCESS_DENIED
;
1860 /* FIXME: save boot log file */
1862 Status
= CmiInitHives (SetUpBoot
);
1864 CmiRegistryInitialized
= TRUE
;