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(NodeInformation
->Name
,
434 SubKeyCell
->NameSize
);
438 RtlCopyMemory(NodeInformation
->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
;
901 if (KeyCell
->Flags
& REG_KEY_NAME_PACKED
)
903 CmiCopyPackedName(BasicInformation
->Name
,
909 RtlCopyMemory(BasicInformation
->Name
,
916 case KeyNodeInformation
:
917 /* Check size of buffer */
918 *ResultLength
= sizeof(KEY_NODE_INFORMATION
) +
919 KeyObject
->Name
.Length
+ KeyCell
->ClassSize
;
921 if (Length
< *ResultLength
)
923 Status
= STATUS_BUFFER_OVERFLOW
;
927 /* Fill buffer with requested info */
928 NodeInformation
= (PKEY_NODE_INFORMATION
) KeyInformation
;
929 NodeInformation
->LastWriteTime
.u
.LowPart
= KeyCell
->LastWriteTime
.u
.LowPart
;
930 NodeInformation
->LastWriteTime
.u
.HighPart
= KeyCell
->LastWriteTime
.u
.HighPart
;
931 NodeInformation
->TitleIndex
= 0;
932 NodeInformation
->ClassOffset
= sizeof(KEY_NODE_INFORMATION
) +
933 KeyObject
->Name
.Length
;
934 NodeInformation
->ClassLength
= KeyCell
->ClassSize
;
935 NodeInformation
->NameLength
= KeyObject
->Name
.Length
;
937 if (KeyCell
->Flags
& REG_KEY_NAME_PACKED
)
939 CmiCopyPackedName(NodeInformation
->Name
,
945 RtlCopyMemory(NodeInformation
->Name
,
950 if (KeyCell
->ClassSize
!= 0)
952 ClassData
= CmiGetBlock(KeyObject
->RegistryHive
,
953 KeyCell
->ClassNameOffset
,
955 wcsncpy(NodeInformation
->Name
+ KeyObject
->Name
.Length
,
956 (PWCHAR
)ClassData
->Data
,
962 case KeyFullInformation
:
963 /* Check size of buffer */
964 *ResultLength
= sizeof(KEY_FULL_INFORMATION
) +
967 if (Length
< *ResultLength
)
969 Status
= STATUS_BUFFER_OVERFLOW
;
973 /* Fill buffer with requested info */
974 FullInformation
= (PKEY_FULL_INFORMATION
) KeyInformation
;
975 FullInformation
->LastWriteTime
.u
.LowPart
= KeyCell
->LastWriteTime
.u
.LowPart
;
976 FullInformation
->LastWriteTime
.u
.HighPart
= KeyCell
->LastWriteTime
.u
.HighPart
;
977 FullInformation
->TitleIndex
= 0;
978 FullInformation
->ClassOffset
= sizeof(KEY_FULL_INFORMATION
) - sizeof(WCHAR
);
979 FullInformation
->ClassLength
= KeyCell
->ClassSize
;
980 FullInformation
->SubKeys
= KeyCell
->NumberOfSubKeys
;
981 FullInformation
->MaxNameLen
=
982 CmiGetMaxNameLength(RegistryHive
, KeyCell
);
983 FullInformation
->MaxClassLen
=
984 CmiGetMaxClassLength(RegistryHive
, KeyCell
);
985 FullInformation
->Values
= KeyCell
->NumberOfValues
;
986 FullInformation
->MaxValueNameLen
=
987 CmiGetMaxValueNameLength(RegistryHive
, KeyCell
);
988 FullInformation
->MaxValueDataLen
=
989 CmiGetMaxValueDataLength(RegistryHive
, KeyCell
);
990 if (KeyCell
->ClassSize
!= 0)
992 ClassData
=CmiGetBlock(KeyObject
->RegistryHive
,
993 KeyCell
->ClassNameOffset
,
995 wcsncpy(FullInformation
->Class
,
996 (PWCHAR
)ClassData
->Data
,
1002 DPRINT1("Not handling 0x%x\n", KeyInformationClass
);
1006 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1007 ObDereferenceObject(KeyObject
);
1014 NtQueryValueKey(IN HANDLE KeyHandle
,
1015 IN PUNICODE_STRING ValueName
,
1016 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
,
1017 OUT PVOID KeyValueInformation
,
1019 OUT PULONG ResultLength
)
1022 PKEY_OBJECT KeyObject
;
1023 PREGISTRY_HIVE RegistryHive
;
1025 PVALUE_CELL ValueCell
;
1026 PDATA_CELL DataCell
;
1027 PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation
;
1028 PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation
;
1029 PKEY_VALUE_FULL_INFORMATION ValueFullInformation
;
1031 DPRINT("NtQueryValueKey(KeyHandle %x ValueName %S Length %x)\n",
1032 KeyHandle
, ValueName
->Buffer
, Length
);
1034 /* Verify that the handle is valid and is a registry key */
1035 Status
= ObReferenceObjectByHandle(KeyHandle
,
1039 (PVOID
*)&KeyObject
,
1042 if (!NT_SUCCESS(Status
))
1044 DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status
);
1048 /* Acquire hive lock */
1049 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1051 VERIFY_KEY_OBJECT(KeyObject
);
1053 /* Get pointer to KeyCell */
1054 KeyCell
= KeyObject
->KeyCell
;
1055 RegistryHive
= KeyObject
->RegistryHive
;
1057 /* Get Value block of interest */
1058 Status
= CmiScanKeyForValue(RegistryHive
,
1063 if (!NT_SUCCESS(Status
))
1065 DPRINT("CmiScanKeyForValue() failed with status %x\n", Status
);
1066 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1067 ObDereferenceObject(KeyObject
);
1070 else if (ValueCell
!= NULL
)
1072 switch (KeyValueInformationClass
)
1074 case KeyValueBasicInformation
:
1075 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1077 *ResultLength
= sizeof(KEY_VALUE_BASIC_INFORMATION
) +
1078 (ValueCell
->NameSize
+ 1) * sizeof(WCHAR
);
1082 *ResultLength
= sizeof(KEY_VALUE_BASIC_INFORMATION
) +
1083 ValueCell
->NameSize
+ sizeof(WCHAR
);
1085 if (Length
< *ResultLength
)
1087 Status
= STATUS_BUFFER_TOO_SMALL
;
1091 ValueBasicInformation
= (PKEY_VALUE_BASIC_INFORMATION
)
1092 KeyValueInformation
;
1093 ValueBasicInformation
->TitleIndex
= 0;
1094 ValueBasicInformation
->Type
= ValueCell
->DataType
;
1095 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1097 ValueBasicInformation
->NameLength
=
1098 (ValueCell
->NameSize
+ 1) * sizeof(WCHAR
);
1099 CmiCopyPackedName(ValueBasicInformation
->Name
,
1101 ValueCell
->NameSize
);
1102 ValueBasicInformation
->Name
[ValueCell
->NameSize
] = 0;
1106 ValueBasicInformation
->NameLength
=
1107 ValueCell
->NameSize
+ sizeof(WCHAR
);
1108 RtlCopyMemory(ValueBasicInformation
->Name
,
1110 ValueCell
->NameSize
* sizeof(WCHAR
));
1111 ValueBasicInformation
->Name
[ValueCell
->NameSize
/ sizeof(WCHAR
)] = 0;
1116 case KeyValuePartialInformation
:
1117 *ResultLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
)
1118 + (ValueCell
->DataSize
& LONG_MAX
);
1119 if (Length
< *ResultLength
)
1121 Status
= STATUS_BUFFER_TOO_SMALL
;
1125 ValuePartialInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)
1126 KeyValueInformation
;
1127 ValuePartialInformation
->TitleIndex
= 0;
1128 ValuePartialInformation
->Type
= ValueCell
->DataType
;
1129 ValuePartialInformation
->DataLength
= ValueCell
->DataSize
& LONG_MAX
;
1130 if (ValueCell
->DataSize
> 0)
1132 DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, NULL
);
1133 RtlCopyMemory(ValuePartialInformation
->Data
,
1135 ValueCell
->DataSize
& LONG_MAX
);
1139 RtlCopyMemory(ValuePartialInformation
->Data
,
1140 &ValueCell
->DataOffset
,
1141 ValueCell
->DataSize
& LONG_MAX
);
1146 case KeyValueFullInformation
:
1147 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1149 *ResultLength
= sizeof(KEY_VALUE_FULL_INFORMATION
) +
1150 (ValueCell
->NameSize
+ 1) * sizeof(WCHAR
) +
1151 (ValueCell
->DataSize
& LONG_MAX
);
1155 *ResultLength
= sizeof(KEY_VALUE_FULL_INFORMATION
) +
1156 ValueCell
->NameSize
+ sizeof(WCHAR
) +
1157 (ValueCell
->DataSize
& LONG_MAX
);
1159 if (Length
< *ResultLength
)
1161 Status
= STATUS_BUFFER_TOO_SMALL
;
1165 ValueFullInformation
= (PKEY_VALUE_FULL_INFORMATION
)
1166 KeyValueInformation
;
1167 ValueFullInformation
->TitleIndex
= 0;
1168 ValueFullInformation
->Type
= ValueCell
->DataType
;
1169 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1171 ValueFullInformation
->NameLength
=
1172 (ValueCell
->NameSize
+ 1) * sizeof(WCHAR
);
1173 CmiCopyPackedName(ValueFullInformation
->Name
,
1175 ValueCell
->NameSize
);
1176 ValueFullInformation
->Name
[ValueCell
->NameSize
] = 0;
1180 ValueFullInformation
->NameLength
=
1181 ValueCell
->NameSize
+ sizeof(WCHAR
);
1182 RtlCopyMemory(ValueFullInformation
->Name
,
1184 ValueCell
->NameSize
);
1185 ValueFullInformation
->Name
[ValueCell
->NameSize
/ sizeof(WCHAR
)] = 0;
1187 ValueFullInformation
->DataOffset
=
1188 (ULONG
)ValueFullInformation
->Name
- (ULONG
)ValueFullInformation
+
1189 ValueFullInformation
->NameLength
;
1190 ValueFullInformation
->DataOffset
=
1191 (ValueFullInformation
->DataOffset
+ 3) & 0xfffffffc;
1192 ValueFullInformation
->DataLength
= ValueCell
->DataSize
& LONG_MAX
;
1193 if (ValueCell
->DataSize
> 0)
1195 DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, NULL
);
1196 RtlCopyMemory((PCHAR
) ValueFullInformation
1197 + ValueFullInformation
->DataOffset
,
1199 ValueCell
->DataSize
& LONG_MAX
);
1203 RtlCopyMemory((PCHAR
) ValueFullInformation
1204 + ValueFullInformation
->DataOffset
,
1205 &ValueCell
->DataOffset
,
1206 ValueCell
->DataSize
& LONG_MAX
);
1211 DPRINT1("Not handling 0x%x\n", KeyValueInformationClass
);
1217 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
1220 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1221 ObDereferenceObject(KeyObject
);
1228 NtSetValueKey(IN HANDLE KeyHandle
,
1229 IN PUNICODE_STRING ValueName
,
1230 IN ULONG TitleIndex
,
1236 PKEY_OBJECT KeyObject
;
1237 PREGISTRY_HIVE RegistryHive
;
1239 PVALUE_CELL ValueCell
;
1240 BLOCK_OFFSET VBOffset
;
1241 PDATA_CELL DataCell
;
1242 PDATA_CELL NewDataCell
;
1244 ULONG DesiredAccess
;
1246 DPRINT("NtSetValueKey(KeyHandle %x ValueName '%wZ' Type %d)\n",
1247 KeyHandle
, ValueName
, Type
);
1249 DesiredAccess
= KEY_SET_VALUE
;
1250 if (Type
== REG_LINK
)
1251 DesiredAccess
|= KEY_CREATE_LINK
;
1253 /* Verify that the handle is valid and is a registry key */
1254 Status
= ObReferenceObjectByHandle(KeyHandle
,
1258 (PVOID
*)&KeyObject
,
1260 if (!NT_SUCCESS(Status
))
1263 /* Acquire hive lock exclucively */
1264 ExAcquireResourceExclusiveLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1266 VERIFY_KEY_OBJECT(KeyObject
);
1268 /* Get pointer to key cell */
1269 KeyCell
= KeyObject
->KeyCell
;
1270 RegistryHive
= KeyObject
->RegistryHive
;
1271 Status
= CmiScanKeyForValue(RegistryHive
,
1276 if (!NT_SUCCESS(Status
))
1278 DPRINT("Value not found. Status 0x%X\n", Status
);
1280 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1281 ObDereferenceObject(KeyObject
);
1285 if (ValueCell
== NULL
)
1287 DPRINT("Allocate new value cell\n");
1288 Status
= CmiAddValueToKey(RegistryHive
,
1293 if (NT_SUCCESS(Status
))
1295 CmiMarkBlockDirty(RegistryHive
, VBOffset
);
1299 if (!NT_SUCCESS(Status
))
1301 DPRINT("Cannot add value. Status 0x%X\n", Status
);
1303 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1304 ObDereferenceObject(KeyObject
);
1308 DPRINT("DataSize %lu\n", DataSize
);
1309 DPRINT("ValueCell %p\n", ValueCell
);
1310 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
1314 /* If datasize <= 4 then write in valueblock directly */
1315 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
1316 if ((ValueCell
->DataSize
>= 0) &&
1317 (DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, NULL
)))
1319 CmiDestroyBlock(RegistryHive
, DataCell
, ValueCell
->DataOffset
);
1322 RtlCopyMemory(&ValueCell
->DataOffset
, Data
, DataSize
);
1323 ValueCell
->DataSize
= DataSize
| 0x80000000;
1324 ValueCell
->DataType
= Type
;
1325 RtlMoveMemory(&ValueCell
->DataOffset
, Data
, DataSize
);
1326 CmiMarkBlockDirty(RegistryHive
, VBOffset
);
1328 else if (DataSize
<= (ULONG
) (ValueCell
->DataSize
& 0x7fffffff))
1330 /* If new data size is <= current then overwrite current data */
1331 DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
,&pBin
);
1332 RtlZeroMemory(DataCell
->Data
, ValueCell
->DataSize
);
1333 RtlCopyMemory(DataCell
->Data
, Data
, DataSize
);
1334 ValueCell
->DataSize
= DataSize
;
1335 ValueCell
->DataType
= Type
;
1337 /* Update time of heap */
1338 if (!IsNoFileHive(RegistryHive
))
1340 NtQuerySystemTime(&pBin
->DateModified
);
1342 CmiMarkBlockDirty(RegistryHive
, ValueCell
->DataOffset
);
1347 * New data size is larger than the current, destroy current
1348 * data block and allocate a new one.
1350 BLOCK_OFFSET NewOffset
;
1352 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
1354 if ((ValueCell
->DataSize
>= 0) &&
1355 (DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, NULL
)))
1357 CmiDestroyBlock(RegistryHive
, DataCell
, ValueCell
->DataOffset
);
1358 ValueCell
->DataSize
= 0;
1359 ValueCell
->DataType
= 0;
1360 ValueCell
->DataOffset
= 0xffffffff;
1363 Status
= CmiAllocateBlock(RegistryHive
,
1364 (PVOID
*)&NewDataCell
,
1367 if (!NT_SUCCESS(Status
))
1369 DPRINT("CmiAllocateBlock() failed (Status %lx)\n", Status
);
1371 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1372 ObDereferenceObject(KeyObject
);
1377 RtlCopyMemory(&NewDataCell
->Data
[0], Data
, DataSize
);
1378 ValueCell
->DataSize
= DataSize
;
1379 ValueCell
->DataType
= Type
;
1380 ValueCell
->DataOffset
= NewOffset
;
1381 CmiMarkBlockDirty(RegistryHive
, ValueCell
->DataOffset
);
1385 if ((_wcsicmp(ValueName
->Buffer
, L
"SymbolicLinkValue") == 0) &&
1388 KeyCell
->Flags
|= REG_KEY_LINK_CELL
;
1389 CmiMarkBlockDirty(RegistryHive
, KeyObject
->BlockOffset
);
1392 /* Update time of heap */
1393 if (!IsNoFileHive(RegistryHive
) && CmiGetBlock(RegistryHive
, VBOffset
, &pBin
))
1395 NtQuerySystemTime(&pBin
->DateModified
);
1398 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1399 ObDereferenceObject(KeyObject
);
1403 DPRINT("Return Status 0x%X\n", Status
);
1410 NtDeleteValueKey (IN HANDLE KeyHandle
,
1411 IN PUNICODE_STRING ValueName
)
1413 PKEY_OBJECT KeyObject
;
1416 /* Verify that the handle is valid and is a registry key */
1417 Status
= ObReferenceObjectByHandle(KeyHandle
,
1421 (PVOID
*)&KeyObject
,
1423 if (!NT_SUCCESS(Status
))
1428 /* Acquire hive lock */
1429 ExAcquireResourceExclusiveLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1431 VERIFY_KEY_OBJECT(KeyObject
);
1433 Status
= CmiDeleteValueFromKey(KeyObject
->RegistryHive
,
1435 KeyObject
->BlockOffset
,
1438 /* Release hive lock */
1439 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1441 ObDereferenceObject(KeyObject
);
1451 * KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
1452 * KeyObjectAttributes->Name specifies the name of the key to load.
1455 NtLoadKey (IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
1456 IN POBJECT_ATTRIBUTES FileObjectAttributes
)
1458 return NtLoadKey2 (KeyObjectAttributes
,
1459 FileObjectAttributes
,
1466 * KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
1467 * KeyObjectAttributes->Name specifies the name of the key to load.
1468 * Flags can be 0 or REG_NO_LAZY_FLUSH.
1471 NtLoadKey2 (IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
1472 IN POBJECT_ATTRIBUTES FileObjectAttributes
,
1475 POBJECT_NAME_INFORMATION NameInfo
;
1476 PUNICODE_STRING NamePointer
;
1482 DPRINT ("NtLoadKey2() called\n");
1485 if (!SeSinglePrivilegeCheck (SeRestorePrivilege
, KeGetPreviousMode ()))
1486 return STATUS_PRIVILEGE_NOT_HELD
;
1489 if (FileObjectAttributes
->RootDirectory
!= NULL
)
1492 sizeof(OBJECT_NAME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
);
1493 Buffer
= ExAllocatePool (NonPagedPool
,
1496 return STATUS_INSUFFICIENT_RESOURCES
;
1498 Status
= NtQueryObject (FileObjectAttributes
->RootDirectory
,
1499 ObjectNameInformation
,
1503 if (!NT_SUCCESS(Status
))
1505 DPRINT1 ("NtQueryObject() failed (Status %lx)\n", Status
);
1506 ExFreePool (Buffer
);
1510 NameInfo
= (POBJECT_NAME_INFORMATION
)Buffer
;
1511 DPRINT ("ObjectPath: '%wZ' Length %hu\n",
1512 &NameInfo
->Name
, NameInfo
->Name
.Length
);
1514 NameInfo
->Name
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
1515 if (FileObjectAttributes
->ObjectName
->Buffer
[0] != L
'\\')
1517 RtlAppendUnicodeToString (&NameInfo
->Name
,
1519 DPRINT ("ObjectPath: '%wZ' Length %hu\n",
1520 &NameInfo
->Name
, NameInfo
->Name
.Length
);
1522 RtlAppendUnicodeStringToString (&NameInfo
->Name
,
1523 FileObjectAttributes
->ObjectName
);
1525 DPRINT ("ObjectPath: '%wZ' Length %hu\n",
1526 &NameInfo
->Name
, NameInfo
->Name
.Length
);
1527 NamePointer
= &NameInfo
->Name
;
1531 if (FileObjectAttributes
->ObjectName
->Buffer
[0] == L
'\\')
1534 NamePointer
= FileObjectAttributes
->ObjectName
;
1539 sizeof(OBJECT_NAME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
);
1540 Buffer
= ExAllocatePool (NonPagedPool
,
1543 return STATUS_INSUFFICIENT_RESOURCES
;
1545 NameInfo
= (POBJECT_NAME_INFORMATION
)Buffer
;
1546 NameInfo
->Name
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
1547 NameInfo
->Name
.Length
= 0;
1548 NameInfo
->Name
.Buffer
= (PWSTR
)((ULONG_PTR
)Buffer
+ sizeof(OBJECT_NAME_INFORMATION
));
1549 NameInfo
->Name
.Buffer
[0] = 0;
1551 RtlAppendUnicodeToString (&NameInfo
->Name
,
1553 RtlAppendUnicodeStringToString (&NameInfo
->Name
,
1554 FileObjectAttributes
->ObjectName
);
1556 NamePointer
= &NameInfo
->Name
;
1560 DPRINT ("Full name: '%wZ'\n", NamePointer
);
1562 Status
= CmiLoadHive (KeyObjectAttributes
,
1565 if (!NT_SUCCESS (Status
))
1567 DPRINT1 ("CmiLoadHive() failed (Status %lx)\n", Status
);
1571 ExFreePool (Buffer
);
1578 NtNotifyChangeKey (IN HANDLE KeyHandle
,
1580 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1581 IN PVOID ApcContext OPTIONAL
,
1582 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1583 IN ULONG CompletionFilter
,
1584 IN BOOLEAN Asynchroneous
,
1585 OUT PVOID ChangeBuffer
,
1587 IN BOOLEAN WatchSubtree
)
1590 return(STATUS_NOT_IMPLEMENTED
);
1595 NtQueryMultipleValueKey (IN HANDLE KeyHandle
,
1596 IN OUT PKEY_VALUE_ENTRY ValueList
,
1597 IN ULONG NumberOfValues
,
1599 IN OUT PULONG Length
,
1600 OUT PULONG ReturnLength
)
1602 PREGISTRY_HIVE RegistryHive
;
1603 PVALUE_CELL ValueCell
;
1604 PKEY_OBJECT KeyObject
;
1605 PDATA_CELL DataCell
;
1606 ULONG BufferLength
= 0;
1612 /* Verify that the handle is valid and is a registry key */
1613 Status
= ObReferenceObjectByHandle(KeyHandle
,
1617 (PVOID
*) &KeyObject
,
1619 if (!NT_SUCCESS(Status
))
1621 DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status
);
1625 /* Acquire hive lock */
1626 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1628 VERIFY_KEY_OBJECT(KeyObject
);
1630 /* Get pointer to KeyCell */
1631 KeyCell
= KeyObject
->KeyCell
;
1632 RegistryHive
= KeyObject
->RegistryHive
;
1634 DataPtr
= (PUCHAR
) Buffer
;
1636 for (i
= 0; i
< NumberOfValues
; i
++)
1638 DPRINT("ValueName: '%wZ'\n", ValueList
[i
].ValueName
);
1640 /* Get Value block of interest */
1641 Status
= CmiScanKeyForValue(RegistryHive
,
1643 ValueList
[i
].ValueName
,
1647 if (!NT_SUCCESS(Status
))
1649 DPRINT("CmiScanKeyForValue() failed with status %x\n", Status
);
1652 else if (ValueCell
== NULL
)
1654 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
1658 BufferLength
= (BufferLength
+ 3) & 0xfffffffc;
1660 if (BufferLength
+ (ValueCell
->DataSize
& LONG_MAX
) <= *Length
)
1662 DataPtr
= (PUCHAR
)(((ULONG
)DataPtr
+ 3) & 0xfffffffc);
1664 ValueList
[i
].Type
= ValueCell
->DataType
;
1665 ValueList
[i
].DataLength
= ValueCell
->DataSize
& LONG_MAX
;
1666 ValueList
[i
].DataOffset
= (ULONG
) DataPtr
- (ULONG
) Buffer
;
1668 if (ValueCell
->DataSize
> 0)
1670 DataCell
= CmiGetBlock(RegistryHive
,
1671 ValueCell
->DataOffset
,
1673 RtlCopyMemory(DataPtr
,
1675 ValueCell
->DataSize
& LONG_MAX
);
1679 RtlCopyMemory(DataPtr
,
1680 &ValueCell
->DataOffset
,
1681 ValueCell
->DataSize
& LONG_MAX
);
1684 DataPtr
+= ValueCell
->DataSize
& LONG_MAX
;
1688 Status
= STATUS_BUFFER_TOO_SMALL
;
1691 BufferLength
+= ValueCell
->DataSize
& LONG_MAX
;
1694 if (NT_SUCCESS(Status
))
1695 *Length
= BufferLength
;
1697 *ReturnLength
= BufferLength
;
1699 /* Release hive lock */
1700 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1702 ObDereferenceObject(KeyObject
);
1704 DPRINT("Return Status 0x%X\n", Status
);
1711 NtReplaceKey (IN POBJECT_ATTRIBUTES ObjectAttributes
,
1713 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes
)
1716 return(STATUS_NOT_IMPLEMENTED
);
1721 NtRestoreKey (IN HANDLE KeyHandle
,
1722 IN HANDLE FileHandle
,
1723 IN ULONG RestoreFlags
)
1726 return(STATUS_NOT_IMPLEMENTED
);
1731 NtSaveKey (IN HANDLE KeyHandle
,
1732 IN HANDLE FileHandle
)
1734 PREGISTRY_HIVE TempHive
;
1735 PKEY_OBJECT KeyObject
;
1738 DPRINT ("NtSaveKey() called\n");
1741 if (!SeSinglePrivilegeCheck (SeBackupPrivilege
, KeGetPreviousMode ()))
1742 return STATUS_PRIVILEGE_NOT_HELD
;
1745 Status
= ObReferenceObjectByHandle (KeyHandle
,
1748 KeGetPreviousMode(),
1749 (PVOID
*)&KeyObject
,
1751 if (!NT_SUCCESS(Status
))
1753 DPRINT1 ("ObReferenceObjectByHandle() failed (Status %lx)\n", Status
);
1757 /* Acquire hive lock exclucively */
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 ObDereferenceObject (KeyObject
);
1767 return STATUS_ACCESS_DENIED
;
1770 Status
= CmiCreateTempHive(&TempHive
);
1771 if (!NT_SUCCESS(Status
))
1773 DPRINT1 ("CmiCreateTempHive() failed (Status %lx)\n", Status
);
1774 ExReleaseResourceLite (&KeyObject
->RegistryHive
->HiveResource
);
1775 ObDereferenceObject (KeyObject
);
1779 Status
= CmiCopyKey (TempHive
,
1781 KeyObject
->RegistryHive
,
1782 KeyObject
->KeyCell
);
1783 if (!NT_SUCCESS(Status
))
1785 DPRINT1 ("CmiCopyKey() failed (Status %lx)\n", Status
);
1786 CmiRemoveRegistryHive (TempHive
);
1787 ExReleaseResourceLite (&KeyObject
->RegistryHive
->HiveResource
);
1788 ObDereferenceObject (KeyObject
);
1792 Status
= CmiSaveTempHive (TempHive
,
1794 if (!NT_SUCCESS(Status
))
1796 DPRINT1 ("CmiSaveTempHive() failed (Status %lx)\n", Status
);
1799 CmiRemoveRegistryHive (TempHive
);
1801 /* Release hive lock */
1802 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1804 ObDereferenceObject (KeyObject
);
1806 DPRINT ("NtSaveKey() done\n");
1808 return STATUS_SUCCESS
;
1813 NtSetInformationKey (IN HANDLE KeyHandle
,
1814 IN CINT KeyInformationClass
,
1815 IN PVOID KeyInformation
,
1816 IN ULONG KeyInformationLength
)
1819 return(STATUS_NOT_IMPLEMENTED
);
1825 * KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
1826 * KeyObjectAttributes->Name specifies the name of the key to unload.
1829 NtUnloadKey (IN POBJECT_ATTRIBUTES KeyObjectAttributes
)
1831 PREGISTRY_HIVE RegistryHive
;
1834 DPRINT ("NtUnloadKey() called\n");
1837 if (!SeSinglePrivilegeCheck (SeRestorePrivilege
, KeGetPreviousMode ()))
1838 return STATUS_PRIVILEGE_NOT_HELD
;
1841 Status
= CmiDisconnectHive (KeyObjectAttributes
,
1843 if (!NT_SUCCESS (Status
))
1845 DPRINT1 ("CmiDisconnectHive() failed (Status %lx)\n", Status
);
1849 DPRINT ("RegistryHive %p\n", RegistryHive
);
1851 /* Acquire hive list lock exclusively */
1852 ExAcquireResourceExclusiveLite (&CmiHiveListLock
,
1857 if (!IsNoFileHive (RegistryHive
))
1858 CmiFlushRegistryHive (RegistryHive
);
1861 /* Release hive list lock */
1862 ExReleaseResourceLite (&CmiHiveListLock
);
1864 CmiRemoveRegistryHive (RegistryHive
);
1866 DPRINT ("NtUnloadKey() done\n");
1868 return STATUS_SUCCESS
;
1873 NtInitializeRegistry (IN BOOLEAN SetUpBoot
)
1877 if (CmiRegistryInitialized
== TRUE
)
1878 return STATUS_ACCESS_DENIED
;
1880 /* FIXME: save boot log file */
1882 Status
= CmiInitHives (SetUpBoot
);
1884 CmiRegistryInitialized
= TRUE
;