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 *****************************************************************/
14 #include <ddk/ntddk.h>
16 #include <internal/ob.h>
19 #include <internal/pool.h>
20 #include <internal/registry.h>
23 #include <internal/debug.h>
29 /* GLOBALS ******************************************************************/
31 extern POBJECT_TYPE CmiKeyType
;
32 extern PREGISTRY_HIVE CmiVolatileHive
;
34 static BOOLEAN CmiRegistryInitialized
= FALSE
;
37 /* FUNCTIONS ****************************************************************/
40 NtCreateKey(OUT PHANDLE KeyHandle
,
41 IN ACCESS_MASK DesiredAccess
,
42 IN POBJECT_ATTRIBUTES ObjectAttributes
,
44 IN PUNICODE_STRING Class
,
45 IN ULONG CreateOptions
,
46 OUT PULONG Disposition
)
48 UNICODE_STRING RemainingPath
;
49 PKEY_OBJECT KeyObject
;
54 DPRINT("NtCreateKey (Name %wZ KeyHandle %x Root %x)\n",
55 ObjectAttributes
->ObjectName
,
57 ObjectAttributes
->RootDirectory
);
59 /* FIXME: check for standard handle prefix and adjust objectAttributes accordingly */
61 Status
= ObFindObject(ObjectAttributes
,
65 if (!NT_SUCCESS(Status
))
70 DPRINT("RemainingPath %wZ\n", &RemainingPath
);
72 if ((RemainingPath
.Buffer
== NULL
) || (RemainingPath
.Buffer
[0] == 0))
74 /* Fail if the key has been deleted */
75 if (((PKEY_OBJECT
) Object
)->Flags
& KO_MARKED_FOR_DELETE
)
77 ObDereferenceObject(Object
);
78 return(STATUS_UNSUCCESSFUL
);
82 *Disposition
= REG_OPENED_EXISTING_KEY
;
84 Status
= ObCreateHandle(PsGetCurrentProcess(),
90 DPRINT("Status %x\n", Status
);
91 ObDereferenceObject(Object
);
95 /* If RemainingPath contains \ we must return error
96 because NtCreateKey don't create trees */
97 if (RemainingPath
.Buffer
[0] == '\\')
98 End
= wcschr(RemainingPath
.Buffer
+ 1, '\\');
100 End
= wcschr(RemainingPath
.Buffer
, '\\');
104 ObDereferenceObject(Object
);
105 return STATUS_UNSUCCESSFUL
;
108 DPRINT("RemainingPath %S ParentObject %x\n", RemainingPath
.Buffer
, Object
);
110 Status
= ObCreateObject(KeyHandle
,
115 if (!NT_SUCCESS(Status
))
120 KeyObject
->ParentKey
= Object
;
122 if (CreateOptions
& REG_OPTION_VOLATILE
)
123 KeyObject
->RegistryHive
= CmiVolatileHive
;
125 KeyObject
->RegistryHive
= KeyObject
->ParentKey
->RegistryHive
;
127 KeyObject
->Flags
= 0;
128 KeyObject
->NumberOfSubKeys
= 0;
129 KeyObject
->SizeOfSubKeys
= 0;
130 KeyObject
->SubKeys
= NULL
;
132 /* Acquire hive lock */
133 ExAcquireResourceExclusiveLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
135 /* add key to subkeys of parent if needed */
136 Status
= CmiAddSubKey(KeyObject
->RegistryHive
,
137 KeyObject
->ParentKey
,
139 RemainingPath
.Buffer
,
140 RemainingPath
.Length
,
144 if (!NT_SUCCESS(Status
))
146 /* Release hive lock */
147 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
148 ObDereferenceObject(KeyObject
);
149 ObDereferenceObject(Object
);
150 return STATUS_UNSUCCESSFUL
;
153 KeyObject
->Name
= KeyObject
->KeyCell
->Name
;
154 KeyObject
->NameSize
= KeyObject
->KeyCell
->NameSize
;
156 if (KeyObject
->RegistryHive
== KeyObject
->ParentKey
->RegistryHive
)
158 KeyObject
->KeyCell
->ParentKeyOffset
= KeyObject
->ParentKey
->BlockOffset
;
159 KeyObject
->KeyCell
->SecurityKeyOffset
= KeyObject
->ParentKey
->KeyCell
->SecurityKeyOffset
;
163 KeyObject
->KeyCell
->ParentKeyOffset
= -1;
164 KeyObject
->KeyCell
->SecurityKeyOffset
= -1;
165 /* This key must remain in memory unless it is deleted
166 or file is unloaded */
167 ObReferenceObjectByPointer(KeyObject
,
168 STANDARD_RIGHTS_REQUIRED
,
173 CmiAddKeyToList(KeyObject
->ParentKey
, KeyObject
);
175 VERIFY_KEY_OBJECT(KeyObject
);
177 /* Release hive lock */
178 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
180 ObDereferenceObject(KeyObject
);
181 ObDereferenceObject(Object
);
184 *Disposition
= REG_CREATED_NEW_KEY
;
193 NtDeleteKey(IN HANDLE KeyHandle
)
195 PKEY_OBJECT KeyObject
;
198 DPRINT("KeyHandle %x\n", KeyHandle
);
200 /* Verify that the handle is valid and is a registry key */
201 Status
= ObReferenceObjectByHandle(KeyHandle
,
207 if (!NT_SUCCESS(Status
))
212 /* Acquire hive lock */
213 ExAcquireResourceExclusiveLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
215 VERIFY_KEY_OBJECT(KeyObject
);
217 /* Check for subkeys */
218 if (KeyObject
->NumberOfSubKeys
!= 0)
220 Status
= STATUS_CANNOT_DELETE
;
224 /* Set the marked for delete bit in the key object */
225 KeyObject
->Flags
|= KO_MARKED_FOR_DELETE
;
226 Status
= STATUS_SUCCESS
;
229 /* Release hive lock */
230 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
232 DPRINT1("PointerCount %lu\n", ObGetObjectPointerCount((PVOID
)KeyObject
));
234 /* Dereference the object */
235 ObDereferenceObject(KeyObject
);
236 if(KeyObject
->RegistryHive
!= KeyObject
->ParentKey
->RegistryHive
)
237 ObDereferenceObject(KeyObject
);
239 DPRINT1("PointerCount %lu\n", ObGetObjectPointerCount((PVOID
)KeyObject
));
243 * Hive-Synchronization will not be triggered here. This is done in
244 * CmiObjectDelete() (in regobj.c) after all key-related structures
245 * have been released.
256 IN KEY_INFORMATION_CLASS KeyInformationClass
,
257 OUT PVOID KeyInformation
,
259 OUT PULONG ResultLength
263 PKEY_OBJECT KeyObject
;
264 PREGISTRY_HIVE RegistryHive
;
265 PKEY_CELL KeyCell
, SubKeyCell
;
266 PHASH_TABLE_CELL HashTableBlock
;
267 PKEY_BASIC_INFORMATION BasicInformation
;
268 PKEY_NODE_INFORMATION NodeInformation
;
269 PKEY_FULL_INFORMATION FullInformation
;
270 PDATA_CELL pClassData
;
272 DPRINT("KH %x I %d KIC %x KI %x L %d RL %x\n",
280 /* Verify that the handle is valid and is a registry key */
281 Status
= ObReferenceObjectByHandle(KeyHandle
,
282 KEY_ENUMERATE_SUB_KEYS
,
285 (PVOID
*) &KeyObject
,
287 if (!NT_SUCCESS(Status
))
289 DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status
);
293 /* Acquire hive lock */
294 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
296 VERIFY_KEY_OBJECT(KeyObject
);
298 /* Get pointer to KeyCell */
299 KeyCell
= KeyObject
->KeyCell
;
300 RegistryHive
= KeyObject
->RegistryHive
;
302 /* Get pointer to SubKey */
303 if (Index
>= KeyCell
->NumberOfSubKeys
)
305 if (RegistryHive
== CmiVolatileHive
)
307 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
308 ObDereferenceObject(KeyObject
);
309 DPRINT("No more volatile entries\n");
310 return(STATUS_NO_MORE_ENTRIES
);
315 PKEY_OBJECT CurKey
= NULL
;
317 /* Search volatile keys */
318 for (i
= 0; i
< KeyObject
->NumberOfSubKeys
; i
++)
320 CurKey
= KeyObject
->SubKeys
[i
];
321 if (CurKey
->RegistryHive
== CmiVolatileHive
)
323 if (Index
-- == KeyObject
->NumberOfSubKeys
)
327 if (Index
>= KeyCell
->NumberOfSubKeys
)
329 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
330 ObDereferenceObject(KeyObject
);
331 DPRINT("No more non-volatile entries\n");
332 return(STATUS_NO_MORE_ENTRIES
);
334 SubKeyCell
= CurKey
->KeyCell
;
339 HashTableBlock
= CmiGetBlock(RegistryHive
, KeyCell
->HashTableOffset
, NULL
);
340 SubKeyCell
= CmiGetKeyFromHashByIndex(RegistryHive
,
345 if (SubKeyCell
== NULL
)
347 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
348 ObDereferenceObject(KeyObject
);
349 DPRINT("No more entries\n");
350 return(STATUS_NO_MORE_ENTRIES
);
353 Status
= STATUS_SUCCESS
;
354 switch (KeyInformationClass
)
356 case KeyBasicInformation
:
357 /* Check size of buffer */
358 *ResultLength
= sizeof(KEY_BASIC_INFORMATION
) +
359 (SubKeyCell
->NameSize
) * sizeof(WCHAR
);
360 if (Length
< *ResultLength
)
362 Status
= STATUS_BUFFER_OVERFLOW
;
366 /* Fill buffer with requested info */
367 BasicInformation
= (PKEY_BASIC_INFORMATION
) KeyInformation
;
368 BasicInformation
->LastWriteTime
.u
.LowPart
= SubKeyCell
->LastWriteTime
.dwLowDateTime
;
369 BasicInformation
->LastWriteTime
.u
.HighPart
= SubKeyCell
->LastWriteTime
.dwHighDateTime
;
370 BasicInformation
->TitleIndex
= Index
;
371 BasicInformation
->NameLength
= SubKeyCell
->NameSize
* sizeof(WCHAR
);
372 mbstowcs(BasicInformation
->Name
,
374 SubKeyCell
->NameSize
* 2);
375 // BasicInformation->Name[SubKeyCell->NameSize] = 0;
379 case KeyNodeInformation
:
380 /* Check size of buffer */
381 *ResultLength
= sizeof(KEY_NODE_INFORMATION
) +
382 SubKeyCell
->NameSize
* sizeof(WCHAR
) +
383 SubKeyCell
->ClassSize
;
384 if (Length
< *ResultLength
)
386 Status
= STATUS_BUFFER_OVERFLOW
;
390 /* Fill buffer with requested info */
391 NodeInformation
= (PKEY_NODE_INFORMATION
) KeyInformation
;
392 NodeInformation
->LastWriteTime
.u
.LowPart
= SubKeyCell
->LastWriteTime
.dwLowDateTime
;
393 NodeInformation
->LastWriteTime
.u
.HighPart
= SubKeyCell
->LastWriteTime
.dwHighDateTime
;
394 NodeInformation
->TitleIndex
= Index
;
395 NodeInformation
->ClassOffset
= sizeof(KEY_NODE_INFORMATION
) +
396 SubKeyCell
->NameSize
* sizeof(WCHAR
);
397 NodeInformation
->ClassLength
= SubKeyCell
->ClassSize
;
398 NodeInformation
->NameLength
= SubKeyCell
->NameSize
* sizeof(WCHAR
);
399 mbstowcs(NodeInformation
->Name
,
401 SubKeyCell
->NameSize
* 2);
402 // NodeInformation->Name[SubKeyCell->NameSize] = 0;
403 if (SubKeyCell
->ClassSize
!= 0)
405 pClassData
=CmiGetBlock(KeyObject
->RegistryHive
,
406 SubKeyCell
->ClassNameOffset
,
408 wcsncpy(NodeInformation
->Name
+ SubKeyCell
->NameSize
,
409 (PWCHAR
) pClassData
->Data
,
410 SubKeyCell
->ClassSize
);
411 CmiReleaseBlock(RegistryHive
, pClassData
);
416 case KeyFullInformation
:
417 /* check size of buffer */
418 *ResultLength
= sizeof(KEY_FULL_INFORMATION
) +
419 SubKeyCell
->ClassSize
;
420 if (Length
< *ResultLength
)
422 Status
= STATUS_BUFFER_OVERFLOW
;
426 /* fill buffer with requested info */
427 FullInformation
= (PKEY_FULL_INFORMATION
) KeyInformation
;
428 FullInformation
->LastWriteTime
.u
.LowPart
= SubKeyCell
->LastWriteTime
.dwLowDateTime
;
429 FullInformation
->LastWriteTime
.u
.HighPart
= SubKeyCell
->LastWriteTime
.dwHighDateTime
;
430 FullInformation
->TitleIndex
= Index
;
431 FullInformation
->ClassOffset
= sizeof(KEY_FULL_INFORMATION
) -
433 FullInformation
->ClassLength
= SubKeyCell
->ClassSize
;
434 FullInformation
->SubKeys
= SubKeyCell
->NumberOfSubKeys
;
435 FullInformation
->MaxNameLen
=
436 CmiGetMaxNameLength(RegistryHive
, SubKeyCell
);
437 FullInformation
->MaxClassLen
=
438 CmiGetMaxClassLength(RegistryHive
, SubKeyCell
);
439 FullInformation
->Values
= SubKeyCell
->NumberOfValues
;
440 FullInformation
->MaxValueNameLen
=
441 CmiGetMaxValueNameLength(RegistryHive
, SubKeyCell
);
442 FullInformation
->MaxValueDataLen
=
443 CmiGetMaxValueDataLength(RegistryHive
, SubKeyCell
);
444 if (SubKeyCell
->ClassSize
!= 0)
446 pClassData
= CmiGetBlock(KeyObject
->RegistryHive
,
447 SubKeyCell
->ClassNameOffset
,
449 wcsncpy(FullInformation
->Class
,
450 (PWCHAR
) pClassData
->Data
,
451 SubKeyCell
->ClassSize
);
452 CmiReleaseBlock(RegistryHive
, pClassData
);
457 CmiReleaseBlock(RegistryHive
, SubKeyCell
);
459 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
460 ObDereferenceObject(KeyObject
);
462 DPRINT("Returning status %x\n", Status
);
469 NtEnumerateValueKey(IN HANDLE KeyHandle
,
471 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
,
472 OUT PVOID KeyValueInformation
,
474 OUT PULONG ResultLength
)
477 PKEY_OBJECT KeyObject
;
478 PREGISTRY_HIVE RegistryHive
;
480 PVALUE_CELL ValueCell
;
482 PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation
;
483 PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation
;
484 PKEY_VALUE_FULL_INFORMATION ValueFullInformation
;
486 DPRINT("KH %x I %d KVIC %x KVI %x L %d RL %x\n",
489 KeyValueInformationClass
,
494 /* Verify that the handle is valid and is a registry key */
495 Status
= ObReferenceObjectByHandle(KeyHandle
,
499 (PVOID
*) &KeyObject
,
502 if (!NT_SUCCESS(Status
))
507 /* Acquire hive lock */
508 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
510 VERIFY_KEY_OBJECT(KeyObject
);
512 /* Get pointer to KeyCell */
513 KeyCell
= KeyObject
->KeyCell
;
514 RegistryHive
= KeyObject
->RegistryHive
;
516 /* Get Value block of interest */
517 Status
= CmiGetValueFromKeyByIndex(RegistryHive
,
522 if (!NT_SUCCESS(Status
))
524 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
525 ObDereferenceObject(KeyObject
);
529 if (ValueCell
!= NULL
)
531 switch (KeyValueInformationClass
)
533 case KeyValueBasicInformation
:
534 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
536 *ResultLength
= sizeof(KEY_VALUE_BASIC_INFORMATION
) +
537 (ValueCell
->NameSize
+ 1) * sizeof(WCHAR
);
541 *ResultLength
= sizeof(KEY_VALUE_BASIC_INFORMATION
) +
542 ValueCell
->NameSize
+ sizeof(WCHAR
);
544 if (Length
< *ResultLength
)
546 Status
= STATUS_BUFFER_OVERFLOW
;
550 ValueBasicInformation
= (PKEY_VALUE_BASIC_INFORMATION
)
552 ValueBasicInformation
->TitleIndex
= 0;
553 ValueBasicInformation
->Type
= ValueCell
->DataType
;
554 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
556 ValueBasicInformation
->NameLength
=
557 (ValueCell
->NameSize
+ 1) * sizeof(WCHAR
);
558 CmiCopyPackedName(ValueBasicInformation
->Name
,
560 ValueCell
->NameSize
);
561 ValueBasicInformation
->Name
[ValueCell
->NameSize
] = 0;
565 ValueBasicInformation
->NameLength
=
566 ValueCell
->NameSize
+ sizeof(WCHAR
);
567 RtlCopyMemory(ValueBasicInformation
->Name
,
569 ValueCell
->NameSize
* sizeof(WCHAR
));
570 ValueBasicInformation
->Name
[ValueCell
->NameSize
/ sizeof(WCHAR
)] = 0;
575 case KeyValuePartialInformation
:
576 *ResultLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) +
577 (ValueCell
->DataSize
& LONG_MAX
);
578 if (Length
< *ResultLength
)
580 Status
= STATUS_BUFFER_OVERFLOW
;
584 ValuePartialInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)
586 ValuePartialInformation
->TitleIndex
= 0;
587 ValuePartialInformation
->Type
= ValueCell
->DataType
;
588 ValuePartialInformation
->DataLength
= ValueCell
->DataSize
& LONG_MAX
;
589 if(ValueCell
->DataSize
>0)
591 DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, NULL
);
592 RtlCopyMemory(ValuePartialInformation
->Data
,
594 ValueCell
->DataSize
& LONG_MAX
);
595 CmiReleaseBlock(RegistryHive
, DataCell
);
599 RtlCopyMemory(ValuePartialInformation
->Data
,
600 &ValueCell
->DataOffset
,
601 ValueCell
->DataSize
& LONG_MAX
);
603 DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, NULL
);
607 case KeyValueFullInformation
:
608 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
610 *ResultLength
= sizeof(KEY_VALUE_FULL_INFORMATION
) +
611 (ValueCell
->NameSize
+ 1) * sizeof(WCHAR
) +
612 (ValueCell
->DataSize
& LONG_MAX
);
616 *ResultLength
= sizeof(KEY_VALUE_FULL_INFORMATION
) +
617 ValueCell
->NameSize
+ sizeof(WCHAR
) +
618 (ValueCell
->DataSize
& LONG_MAX
);
620 if (Length
< *ResultLength
)
622 Status
= STATUS_BUFFER_OVERFLOW
;
626 ValueFullInformation
= (PKEY_VALUE_FULL_INFORMATION
)
628 ValueFullInformation
->TitleIndex
= 0;
629 ValueFullInformation
->Type
= ValueCell
->DataType
;
630 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
632 ValueFullInformation
->NameLength
=
633 (ValueCell
->NameSize
+ 1) * sizeof(WCHAR
);
635 CmiCopyPackedName(ValueFullInformation
->Name
,
637 ValueCell
->NameSize
);
638 ValueFullInformation
->Name
[ValueCell
->NameSize
] = 0;
642 ValueFullInformation
->NameLength
=
643 ValueCell
->NameSize
+ sizeof(WCHAR
);
644 RtlCopyMemory(ValueFullInformation
->Name
,
646 ValueCell
->NameSize
);
647 ValueFullInformation
->Name
[ValueCell
->NameSize
/ sizeof(WCHAR
)] = 0;
649 ValueFullInformation
->DataOffset
=
650 (ULONG
)ValueFullInformation
->Name
- (ULONG
)ValueFullInformation
+
651 ValueFullInformation
->NameLength
;
652 ValueFullInformation
->DataOffset
=
653 (ValueFullInformation
->DataOffset
+ 3) & 0xfffffffc;
654 ValueFullInformation
->DataLength
= ValueCell
->DataSize
& LONG_MAX
;
655 if (ValueCell
->DataSize
> 0)
657 DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, NULL
);
658 RtlCopyMemory((PCHAR
) ValueFullInformation
659 + ValueFullInformation
->DataOffset
,
661 ValueCell
->DataSize
& LONG_MAX
);
662 CmiReleaseBlock(RegistryHive
, DataCell
);
666 RtlCopyMemory((PCHAR
) ValueFullInformation
667 + ValueFullInformation
->DataOffset
,
668 &ValueCell
->DataOffset
,
669 ValueCell
->DataSize
& LONG_MAX
);
677 Status
= STATUS_UNSUCCESSFUL
;
680 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
681 ObDereferenceObject(KeyObject
);
688 NtFlushKey(IN HANDLE KeyHandle
)
691 PKEY_OBJECT KeyObject
;
692 PREGISTRY_HIVE RegistryHive
;
694 WCHAR LogName
[MAX_PATH
];
695 UNICODE_STRING TmpFileName
;
697 // HANDLE FileHandleLog;
698 OBJECT_ATTRIBUTES ObjectAttributes
;
699 LARGE_INTEGER fileOffset
;
704 DPRINT("KeyHandle %x\n", KeyHandle
);
706 /* Verify that the handle is valid and is a registry key */
707 Status
= ObReferenceObjectByHandle(KeyHandle
,
713 if (!NT_SUCCESS(Status
))
718 VERIFY_KEY_OBJECT(KeyObject
);
720 RegistryHive
= KeyObject
->RegistryHive
;
722 /* Acquire hive lock */
723 ExAcquireResourceExclusiveLite(&RegistryHive
->HiveResource
,
726 if (IsPermanentHive(RegistryHive
))
728 /* Flush non-volatile hive */
729 Status
= CmiFlushRegistryHive(RegistryHive
);
733 Status
= STATUS_SUCCESS
;
738 /* Then write changed blocks in .log */
739 wcscpy(LogName
,RegistryHive
->Filename
.Buffer
);
740 wcscat(LogName
,L
".log");
741 RtlInitUnicodeString (&TmpFileName
, LogName
);
742 InitializeObjectAttributes(&ObjectAttributes
,
748 /* BEGIN FIXME : actually (26 November 200) vfatfs.sys can't create new files
749 so we can't create log file
750 Status = ZwCreateFile(&FileHandleLog,
755 FILE_ATTRIBUTE_NORMAL,
762 if (!NT_SUCCESS(Status))
764 ObDereferenceObject(KeyObject);
768 Status = ZwWriteFile(FileHandleLog,
773 RegistryHive->HiveHeader,
778 if (!NT_SUCCESS(Status))
780 ZwClose(FileHandleLog);
781 ObDereferenceObject(KeyObject);
785 for (i = 0; i < RegistryHive->BlockListSize ; i++)
787 if ( RegistryHive->BlockList[i]->DateModified.dwHighDateTime
788 > RegistryHive->HiveHeader->DateModified.dwHighDateTime
789 || (RegistryHive->BlockList[i]->DateModified.dwHighDateTime
790 == RegistryHive->HiveHeader->DateModified.dwHighDateTime
791 && RegistryHive->BlockList[i]->DateModified.dwLowDateTime
792 > RegistryHive->HiveHeader->DateModified.dwLowDateTime
796 Status = ZwWriteFile(FileHandleLog,
801 RegistryHive->BlockList[i],
802 RegistryHive->BlockList[i]->BlockSize ,
806 if (!NT_SUCCESS(Status))
808 ZwClose(FileHandleLog);
809 ObDereferenceObject(KeyObject);
813 ZwClose(FileHandleLog);
816 /* Update header of RegistryHive with Version >VersionOld */
817 /* this allow recover if system crash while updating hove file */
818 InitializeObjectAttributes(&ObjectAttributes
,
819 &RegistryHive
->Filename
,
824 Status
= NtOpenFile(&FileHandle
,
829 FILE_SYNCHRONOUS_IO_NONALERT
);
830 if (!NT_SUCCESS(Status
))
832 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
833 ObDereferenceObject(KeyObject
);
837 RegistryHive
->HiveHeader
->Version
++;
839 Status
= ZwWriteFile(FileHandle
,
844 RegistryHive
->HiveHeader
,
848 if (!NT_SUCCESS(Status
))
851 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
852 ObDereferenceObject(KeyObject
);
856 /* Update changed blocks in file */
857 fileOffset
.u
.HighPart
= 0;
858 for (i
= 0; i
< RegistryHive
->BlockListSize
; i
++)
860 if (RegistryHive
->BlockList
[i
]->DateModified
.dwHighDateTime
861 > RegistryHive
->HiveHeader
->DateModified
.dwHighDateTime
862 || (RegistryHive
->BlockList
[i
]->DateModified
.dwHighDateTime
863 == RegistryHive
->HiveHeader
->DateModified
.dwHighDateTime
864 && RegistryHive
->BlockList
[i
]->DateModified
.dwLowDateTime
865 > RegistryHive
->HiveHeader
->DateModified
.dwLowDateTime
))
867 fileOffset
.u
.LowPart
= RegistryHive
->BlockList
[i
]->BlockOffset
+4096;
868 Status
= NtWriteFile(FileHandle
,
873 RegistryHive
->BlockList
[i
],
874 RegistryHive
->BlockList
[i
]->BlockSize
,
877 if (!NT_SUCCESS(Status
))
880 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
881 ObDereferenceObject(KeyObject
);
887 /* Change version in header */
888 RegistryHive
->HiveHeader
->VersionOld
= RegistryHive
->HiveHeader
->Version
;
889 ZwQuerySystemTime((PTIME
) &RegistryHive
->HiveHeader
->DateModified
);
891 /* Calculate checksum */
892 RegistryHive
->HiveHeader
->Checksum
= 0;
893 pEntDword
= (DWORD
*) RegistryHive
->HiveHeader
;
894 for (i
= 0; i
< 127 ; i
++)
896 RegistryHive
->HiveHeader
->Checksum
^= pEntDword
[i
];
899 /* Write new header */
900 fileOffset
.u
.LowPart
= 0;
901 Status
= ZwWriteFile(FileHandle
,
906 RegistryHive
->HiveHeader
,
911 if (!NT_SUCCESS(Status
))
914 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
915 ObDereferenceObject(KeyObject
);
922 ExReleaseResourceLite(&RegistryHive
->HiveResource
);
924 ObDereferenceObject(KeyObject
);
926 return STATUS_SUCCESS
;
931 NtOpenKey(OUT PHANDLE KeyHandle
,
932 IN ACCESS_MASK DesiredAccess
,
933 IN POBJECT_ATTRIBUTES ObjectAttributes
)
935 UNICODE_STRING RemainingPath
;
939 DPRINT("NtOpenFile(KH %x DA %x OA %x OA->ON '%wZ'\n",
943 ObjectAttributes
? ObjectAttributes
->ObjectName
: NULL
);
945 RemainingPath
.Buffer
= NULL
;
946 Status
= ObFindObject(ObjectAttributes
,
950 if (!NT_SUCCESS(Status
))
955 VERIFY_KEY_OBJECT((PKEY_OBJECT
) Object
);
957 DPRINT("RemainingPath '%wZ'\n", &RemainingPath
);
959 if ((RemainingPath
.Buffer
!= NULL
) && (RemainingPath
.Buffer
[0] != 0))
961 ObDereferenceObject(Object
);
962 return(STATUS_UNSUCCESSFUL
);
965 /* Fail if the key has been deleted */
966 if (((PKEY_OBJECT
)Object
)->Flags
& KO_MARKED_FOR_DELETE
)
968 ObDereferenceObject(Object
);
969 return(STATUS_UNSUCCESSFUL
);
972 Status
= ObCreateHandle(PsGetCurrentProcess(),
977 ObDereferenceObject(Object
);
979 if (!NT_SUCCESS(Status
))
984 return(STATUS_SUCCESS
);
989 NtQueryKey(IN HANDLE KeyHandle
,
990 IN KEY_INFORMATION_CLASS KeyInformationClass
,
991 OUT PVOID KeyInformation
,
993 OUT PULONG ResultLength
)
995 PKEY_BASIC_INFORMATION BasicInformation
;
996 PKEY_NODE_INFORMATION NodeInformation
;
997 PKEY_FULL_INFORMATION FullInformation
;
998 PREGISTRY_HIVE RegistryHive
;
999 PDATA_CELL pClassData
;
1000 PKEY_OBJECT KeyObject
;
1004 DPRINT("KH %x KIC %x KI %x L %d RL %x\n",
1006 KeyInformationClass
,
1011 /* Verify that the handle is valid and is a registry key */
1012 Status
= ObReferenceObjectByHandle(KeyHandle
,
1016 (PVOID
*) &KeyObject
,
1018 if (!NT_SUCCESS(Status
))
1025 /* Acquire hive lock */
1026 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1029 VERIFY_KEY_OBJECT(KeyObject
);
1031 /* Get pointer to KeyCell */
1032 KeyCell
= KeyObject
->KeyCell
;
1033 RegistryHive
= KeyObject
->RegistryHive
;
1035 Status
= STATUS_SUCCESS
;
1036 switch (KeyInformationClass
)
1038 case KeyBasicInformation
:
1040 /* Check size of buffer */
1041 if (Length
< sizeof(KEY_BASIC_INFORMATION
) +
1042 KeyObject
->NameSize
* sizeof(WCHAR
))
1044 Status
= STATUS_BUFFER_OVERFLOW
;
1048 /* Fill buffer with requested info */
1049 BasicInformation
= (PKEY_BASIC_INFORMATION
) KeyInformation
;
1050 BasicInformation
->LastWriteTime
.u
.LowPart
= KeyCell
->LastWriteTime
.dwLowDateTime
;
1051 BasicInformation
->LastWriteTime
.u
.HighPart
= KeyCell
->LastWriteTime
.dwHighDateTime
;
1052 BasicInformation
->TitleIndex
= 0;
1053 BasicInformation
->NameLength
= (KeyObject
->NameSize
) * sizeof(WCHAR
);
1054 mbstowcs(BasicInformation
->Name
,
1056 KeyObject
->NameSize
*sizeof(WCHAR
));
1057 *ResultLength
= sizeof(KEY_BASIC_INFORMATION
) +
1058 KeyObject
->NameSize
* sizeof(WCHAR
);
1063 case KeyNodeInformation
:
1064 /* Check size of buffer */
1065 if (Length
< sizeof(KEY_NODE_INFORMATION
)
1066 + KeyObject
->NameSize
* sizeof(WCHAR
)
1067 + KeyCell
->ClassSize
)
1069 Status
= STATUS_BUFFER_OVERFLOW
;
1073 /* Fill buffer with requested info */
1074 NodeInformation
= (PKEY_NODE_INFORMATION
) KeyInformation
;
1075 NodeInformation
->LastWriteTime
.u
.LowPart
= KeyCell
->LastWriteTime
.dwLowDateTime
;
1076 NodeInformation
->LastWriteTime
.u
.HighPart
= KeyCell
->LastWriteTime
.dwHighDateTime
;
1077 NodeInformation
->TitleIndex
= 0;
1078 NodeInformation
->ClassOffset
= sizeof(KEY_NODE_INFORMATION
) +
1079 KeyObject
->NameSize
* sizeof(WCHAR
);
1080 NodeInformation
->ClassLength
= KeyCell
->ClassSize
;
1081 NodeInformation
->NameLength
= KeyObject
->NameSize
* sizeof(WCHAR
);
1082 mbstowcs(NodeInformation
->Name
,
1084 KeyObject
->NameSize
* sizeof(WCHAR
));
1086 if (KeyCell
->ClassSize
!= 0)
1088 pClassData
= CmiGetBlock(KeyObject
->RegistryHive
,
1089 KeyCell
->ClassNameOffset
,
1091 wcsncpy(NodeInformation
->Name
+ KeyObject
->NameSize
* sizeof(WCHAR
),
1092 (PWCHAR
)pClassData
->Data
,
1093 KeyCell
->ClassSize
);
1094 CmiReleaseBlock(RegistryHive
, pClassData
);
1096 *ResultLength
= sizeof(KEY_NODE_INFORMATION
)
1097 + KeyObject
->NameSize
* sizeof(WCHAR
)
1098 + KeyCell
->ClassSize
;
1102 case KeyFullInformation
:
1103 /* Check size of buffer */
1104 if (Length
< sizeof(KEY_FULL_INFORMATION
) + KeyCell
->ClassSize
)
1106 Status
= STATUS_BUFFER_OVERFLOW
;
1110 /* Fill buffer with requested info */
1111 FullInformation
= (PKEY_FULL_INFORMATION
) KeyInformation
;
1112 FullInformation
->LastWriteTime
.u
.LowPart
= KeyCell
->LastWriteTime
.dwLowDateTime
;
1113 FullInformation
->LastWriteTime
.u
.HighPart
= KeyCell
->LastWriteTime
.dwHighDateTime
;
1114 FullInformation
->TitleIndex
= 0;
1115 FullInformation
->ClassOffset
= sizeof(KEY_FULL_INFORMATION
) - sizeof(WCHAR
);
1116 FullInformation
->ClassLength
= KeyCell
->ClassSize
;
1117 FullInformation
->SubKeys
= KeyCell
->NumberOfSubKeys
;
1118 FullInformation
->MaxNameLen
=
1119 CmiGetMaxNameLength(RegistryHive
, KeyCell
);
1120 FullInformation
->MaxClassLen
=
1121 CmiGetMaxClassLength(RegistryHive
, KeyCell
);
1122 FullInformation
->Values
= KeyCell
->NumberOfValues
;
1123 FullInformation
->MaxValueNameLen
=
1124 CmiGetMaxValueNameLength(RegistryHive
, KeyCell
);
1125 FullInformation
->MaxValueDataLen
=
1126 CmiGetMaxValueDataLength(RegistryHive
, KeyCell
);
1127 if (KeyCell
->ClassSize
!= 0)
1129 pClassData
=CmiGetBlock(KeyObject
->RegistryHive
,
1130 KeyCell
->ClassNameOffset
,
1132 wcsncpy(FullInformation
->Class
,
1133 (PWCHAR
)pClassData
->Data
,
1134 KeyCell
->ClassSize
);
1135 CmiReleaseBlock(RegistryHive
, pClassData
);
1137 *ResultLength
= sizeof(KEY_FULL_INFORMATION
) + KeyCell
->ClassSize
;
1143 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1145 ObDereferenceObject(KeyObject
);
1153 NtQueryValueKey(IN HANDLE KeyHandle
,
1154 IN PUNICODE_STRING ValueName
,
1155 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
,
1156 OUT PVOID KeyValueInformation
,
1158 OUT PULONG ResultLength
)
1161 PKEY_OBJECT KeyObject
;
1162 PREGISTRY_HIVE RegistryHive
;
1164 PVALUE_CELL ValueCell
;
1165 PDATA_CELL DataCell
;
1166 PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation
;
1167 PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation
;
1168 PKEY_VALUE_FULL_INFORMATION ValueFullInformation
;
1170 DPRINT("NtQueryValueKey(KeyHandle %x ValueName %S Length %x)\n",
1171 KeyHandle
, ValueName
->Buffer
, Length
);
1173 /* Verify that the handle is valid and is a registry key */
1174 Status
= ObReferenceObjectByHandle(KeyHandle
,
1178 (PVOID
*)&KeyObject
,
1181 if (!NT_SUCCESS(Status
))
1183 DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status
);
1187 /* Acquire hive lock */
1188 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1190 VERIFY_KEY_OBJECT(KeyObject
);
1192 /* Get pointer to KeyCell */
1193 KeyCell
= KeyObject
->KeyCell
;
1194 RegistryHive
= KeyObject
->RegistryHive
;
1196 /* Get Value block of interest */
1197 Status
= CmiScanKeyForValue(RegistryHive
,
1202 if (!NT_SUCCESS(Status
))
1204 DPRINT("CmiScanKeyForValue() failed with status %x\n", Status
);
1205 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1206 ObDereferenceObject(KeyObject
);
1209 else if (ValueCell
!= NULL
)
1211 switch (KeyValueInformationClass
)
1213 case KeyValueBasicInformation
:
1214 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1216 *ResultLength
= sizeof(KEY_VALUE_BASIC_INFORMATION
) +
1217 (ValueCell
->NameSize
+ 1) * sizeof(WCHAR
);
1221 *ResultLength
= sizeof(KEY_VALUE_BASIC_INFORMATION
) +
1222 ValueCell
->NameSize
+ sizeof(WCHAR
);
1224 if (Length
< *ResultLength
)
1226 Status
= STATUS_BUFFER_TOO_SMALL
;
1230 ValueBasicInformation
= (PKEY_VALUE_BASIC_INFORMATION
)
1231 KeyValueInformation
;
1232 ValueBasicInformation
->TitleIndex
= 0;
1233 ValueBasicInformation
->Type
= ValueCell
->DataType
;
1234 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1236 ValueBasicInformation
->NameLength
=
1237 (ValueCell
->NameSize
+ 1) * sizeof(WCHAR
);
1238 CmiCopyPackedName(ValueBasicInformation
->Name
,
1240 ValueCell
->NameSize
);
1241 ValueBasicInformation
->Name
[ValueCell
->NameSize
] = 0;
1245 ValueBasicInformation
->NameLength
=
1246 ValueCell
->NameSize
+ sizeof(WCHAR
);
1247 RtlCopyMemory(ValueBasicInformation
->Name
,
1249 ValueCell
->NameSize
* sizeof(WCHAR
));
1250 ValueBasicInformation
->Name
[ValueCell
->NameSize
/ sizeof(WCHAR
)] = 0;
1255 case KeyValuePartialInformation
:
1256 *ResultLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
)
1257 + (ValueCell
->DataSize
& LONG_MAX
);
1258 if (Length
< *ResultLength
)
1260 Status
= STATUS_BUFFER_TOO_SMALL
;
1264 ValuePartialInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)
1265 KeyValueInformation
;
1266 ValuePartialInformation
->TitleIndex
= 0;
1267 ValuePartialInformation
->Type
= ValueCell
->DataType
;
1268 ValuePartialInformation
->DataLength
= ValueCell
->DataSize
& LONG_MAX
;
1269 if (ValueCell
->DataSize
> 0)
1271 DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, NULL
);
1272 RtlCopyMemory(ValuePartialInformation
->Data
,
1274 ValueCell
->DataSize
& LONG_MAX
);
1275 CmiReleaseBlock(RegistryHive
, DataCell
);
1279 RtlCopyMemory(ValuePartialInformation
->Data
,
1280 &ValueCell
->DataOffset
,
1281 ValueCell
->DataSize
& LONG_MAX
);
1286 case KeyValueFullInformation
:
1287 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1289 *ResultLength
= sizeof(KEY_VALUE_FULL_INFORMATION
) +
1290 (ValueCell
->NameSize
+ 1) * sizeof(WCHAR
) +
1291 (ValueCell
->DataSize
& LONG_MAX
);
1295 *ResultLength
= sizeof(KEY_VALUE_FULL_INFORMATION
) +
1296 ValueCell
->NameSize
+ sizeof(WCHAR
) +
1297 (ValueCell
->DataSize
& LONG_MAX
);
1299 if (Length
< *ResultLength
)
1301 Status
= STATUS_BUFFER_TOO_SMALL
;
1305 ValueFullInformation
= (PKEY_VALUE_FULL_INFORMATION
)
1306 KeyValueInformation
;
1307 ValueFullInformation
->TitleIndex
= 0;
1308 ValueFullInformation
->Type
= ValueCell
->DataType
;
1309 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1311 ValueFullInformation
->NameLength
=
1312 (ValueCell
->NameSize
+ 1) * sizeof(WCHAR
);
1313 CmiCopyPackedName(ValueFullInformation
->Name
,
1315 ValueCell
->NameSize
);
1316 ValueFullInformation
->Name
[ValueCell
->NameSize
] = 0;
1320 ValueFullInformation
->NameLength
=
1321 ValueCell
->NameSize
+ sizeof(WCHAR
);
1322 RtlCopyMemory(ValueFullInformation
->Name
,
1324 ValueCell
->NameSize
);
1325 ValueFullInformation
->Name
[ValueCell
->NameSize
/ sizeof(WCHAR
)] = 0;
1327 ValueFullInformation
->DataOffset
=
1328 (ULONG
)ValueFullInformation
->Name
- (ULONG
)ValueFullInformation
+
1329 ValueFullInformation
->NameLength
;
1330 ValueFullInformation
->DataOffset
=
1331 (ValueFullInformation
->DataOffset
+ 3) & 0xfffffffc;
1332 ValueFullInformation
->DataLength
= ValueCell
->DataSize
& LONG_MAX
;
1333 if (ValueCell
->DataSize
> 0)
1335 DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, NULL
);
1336 RtlCopyMemory((PCHAR
) ValueFullInformation
1337 + ValueFullInformation
->DataOffset
,
1339 ValueCell
->DataSize
& LONG_MAX
);
1340 CmiReleaseBlock(RegistryHive
, DataCell
);
1344 RtlCopyMemory((PCHAR
) ValueFullInformation
1345 + ValueFullInformation
->DataOffset
,
1346 &ValueCell
->DataOffset
,
1347 ValueCell
->DataSize
& LONG_MAX
);
1355 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
1358 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1359 ObDereferenceObject(KeyObject
);
1366 NtSetValueKey(IN HANDLE KeyHandle
,
1367 IN PUNICODE_STRING ValueName
,
1368 IN ULONG TitleIndex
,
1374 PKEY_OBJECT KeyObject
;
1375 PREGISTRY_HIVE RegistryHive
;
1377 PVALUE_CELL ValueCell
;
1378 BLOCK_OFFSET VBOffset
;
1379 PDATA_CELL DataCell
;
1380 PDATA_CELL NewDataCell
;
1382 ULONG DesiredAccess
;
1384 DPRINT("NtSetValueKey(KeyHandle %x ValueName %S Type %d)\n",
1385 KeyHandle
, ValueName
? ValueName
->Buffer
: NULL
, Type
);
1387 DesiredAccess
= KEY_SET_VALUE
;
1388 if (Type
== REG_LINK
)
1389 DesiredAccess
|= KEY_CREATE_LINK
;
1391 /* Verify that the handle is valid and is a registry key */
1392 Status
= ObReferenceObjectByHandle(KeyHandle
,
1396 (PVOID
*)&KeyObject
,
1398 if (!NT_SUCCESS(Status
))
1401 /* Acquire hive lock exclucively */
1402 ExAcquireResourceExclusiveLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1404 VERIFY_KEY_OBJECT(KeyObject
);
1406 /* Get pointer to key cell */
1407 KeyCell
= KeyObject
->KeyCell
;
1408 RegistryHive
= KeyObject
->RegistryHive
;
1409 Status
= CmiScanKeyForValue(RegistryHive
,
1414 if (!NT_SUCCESS(Status
))
1416 DPRINT1("Value not found. Status 0x%X\n", Status
);
1418 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1419 ObDereferenceObject(KeyObject
);
1423 if (ValueCell
== NULL
)
1425 DPRINT("Allocate new value cell\n");
1426 Status
= CmiAddValueToKey(RegistryHive
,
1431 if (NT_SUCCESS(Status
))
1433 CmiMarkBlockDirty(RegistryHive
, VBOffset
);
1437 if (!NT_SUCCESS(Status
))
1439 DPRINT1("Cannot add value. Status 0x%X\n", Status
);
1441 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1442 ObDereferenceObject(KeyObject
);
1446 DPRINT("DataSize %lu\n", DataSize
);
1447 DPRINT("ValueCell %p\n", ValueCell
);
1448 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
1452 /* If datasize <= 4 then write in valueblock directly */
1453 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
1454 if ((ValueCell
->DataSize
>= 0) &&
1455 (DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, NULL
)))
1457 CmiDestroyBlock(RegistryHive
, DataCell
, ValueCell
->DataOffset
);
1460 RtlCopyMemory(&ValueCell
->DataOffset
, Data
, DataSize
);
1461 ValueCell
->DataSize
= DataSize
| 0x80000000;
1462 ValueCell
->DataType
= Type
;
1463 RtlMoveMemory(&ValueCell
->DataOffset
, Data
, DataSize
);
1464 CmiMarkBlockDirty(RegistryHive
, VBOffset
);
1466 else if (DataSize
<= (ULONG
) (ValueCell
->DataSize
& 0x7fffffff))
1468 /* If new data size is <= current then overwrite current data */
1469 DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
,&pBin
);
1470 RtlZeroMemory(DataCell
->Data
, ValueCell
->DataSize
);
1471 RtlCopyMemory(DataCell
->Data
, Data
, DataSize
);
1472 ValueCell
->DataSize
= DataSize
;
1473 ValueCell
->DataType
= Type
;
1474 CmiReleaseBlock(RegistryHive
, DataCell
);
1476 /* Update time of heap */
1477 if (IsPermanentHive(RegistryHive
))
1479 ZwQuerySystemTime((PTIME
) &pBin
->DateModified
);
1481 CmiMarkBlockDirty(RegistryHive
, ValueCell
->DataOffset
);
1486 * New data size is larger than the current, destroy current
1487 * data block and allocate a new one.
1489 BLOCK_OFFSET NewOffset
;
1491 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
1493 if ((ValueCell
->DataSize
>= 0) &&
1494 (DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, NULL
)))
1496 CmiDestroyBlock(RegistryHive
, DataCell
, ValueCell
->DataOffset
);
1497 ValueCell
->DataSize
= 0;
1498 ValueCell
->DataType
= 0;
1499 ValueCell
->DataOffset
= 0xffffffff;
1502 Status
= CmiAllocateBlock(RegistryHive
,
1503 (PVOID
*)&NewDataCell
,
1506 if (!NT_SUCCESS(Status
))
1508 DPRINT("CmiAllocateBlock() failed (Status %lx)\n", Status
);
1510 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1511 ObDereferenceObject(KeyObject
);
1516 RtlCopyMemory(&NewDataCell
->Data
[0], Data
, DataSize
);
1517 ValueCell
->DataSize
= DataSize
;
1518 ValueCell
->DataType
= Type
;
1519 CmiReleaseBlock(RegistryHive
, NewDataCell
);
1520 ValueCell
->DataOffset
= NewOffset
;
1521 CmiMarkBlockDirty(RegistryHive
, ValueCell
->DataOffset
);
1525 if ((_wcsicmp(ValueName
->Buffer
, L
"SymbolicLinkValue") == 0) &&
1528 KeyCell
->Type
= REG_LINK_KEY_CELL_TYPE
;
1529 CmiMarkBlockDirty(RegistryHive
, KeyObject
->BlockOffset
);
1532 /* Update time of heap */
1533 if (IsPermanentHive(RegistryHive
) && CmiGetBlock(RegistryHive
, VBOffset
, &pBin
))
1535 ZwQuerySystemTime((PTIME
) &pBin
->DateModified
);
1538 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1539 ObDereferenceObject(KeyObject
);
1543 DPRINT("Return Status 0x%X\n", Status
);
1550 NtDeleteValueKey(IN HANDLE KeyHandle
,
1551 IN PUNICODE_STRING ValueName
)
1553 PKEY_OBJECT KeyObject
;
1556 /* Verify that the handle is valid and is a registry key */
1557 Status
= ObReferenceObjectByHandle(KeyHandle
,
1561 (PVOID
*)&KeyObject
,
1563 if (!NT_SUCCESS(Status
))
1568 /* Acquire hive lock */
1569 ExAcquireResourceExclusiveLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1571 VERIFY_KEY_OBJECT(KeyObject
);
1573 Status
= CmiDeleteValueFromKey(KeyObject
->RegistryHive
,
1575 KeyObject
->BlockOffset
,
1578 /* Release hive lock */
1579 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1581 ObDereferenceObject(KeyObject
);
1590 NtLoadKey(PHANDLE KeyHandle
,
1591 POBJECT_ATTRIBUTES ObjectAttributes
)
1593 return NtLoadKey2(KeyHandle
, ObjectAttributes
, 0);
1598 NtLoadKey2(IN PHANDLE KeyHandle
,
1599 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1608 IN HANDLE KeyHandle
,
1610 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1611 IN PVOID ApcContext OPTIONAL
,
1612 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1613 IN ULONG CompletionFilter
,
1614 IN BOOLEAN Asynchroneous
,
1615 OUT PVOID ChangeBuffer
,
1617 IN BOOLEAN WatchSubtree
)
1624 NtQueryMultipleValueKey(IN HANDLE KeyHandle
,
1625 IN OUT PKEY_VALUE_ENTRY ValueList
,
1626 IN ULONG NumberOfValues
,
1628 IN OUT PULONG Length
,
1629 OUT PULONG ReturnLength
)
1631 PREGISTRY_HIVE RegistryHive
;
1632 PVALUE_CELL ValueCell
;
1633 PKEY_OBJECT KeyObject
;
1634 PDATA_CELL DataCell
;
1635 ULONG BufferLength
= 0;
1641 /* Verify that the handle is valid and is a registry key */
1642 Status
= ObReferenceObjectByHandle(KeyHandle
,
1646 (PVOID
*) &KeyObject
,
1648 if (!NT_SUCCESS(Status
))
1650 DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status
);
1654 /* Acquire hive lock */
1655 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1657 VERIFY_KEY_OBJECT(KeyObject
);
1659 /* Get pointer to KeyCell */
1660 KeyCell
= KeyObject
->KeyCell
;
1661 RegistryHive
= KeyObject
->RegistryHive
;
1663 DataPtr
= (PUCHAR
) Buffer
;
1665 for (i
= 0; i
< NumberOfValues
; i
++)
1667 DPRINT("ValueName: '%wZ'\n", ValueList
[i
].ValueName
);
1669 /* Get Value block of interest */
1670 Status
= CmiScanKeyForValue(RegistryHive
,
1672 ValueList
[i
].ValueName
,
1676 if (!NT_SUCCESS(Status
))
1678 DPRINT("CmiScanKeyForValue() failed with status %x\n", Status
);
1681 else if (ValueCell
== NULL
)
1683 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
1687 BufferLength
= (BufferLength
+ 3) & 0xfffffffc;
1689 if (BufferLength
+ (ValueCell
->DataSize
& LONG_MAX
) <= *Length
)
1691 DataPtr
= (PUCHAR
)(((ULONG
)DataPtr
+ 3) & 0xfffffffc);
1693 ValueList
[i
].Type
= ValueCell
->DataType
;
1694 ValueList
[i
].DataLength
= ValueCell
->DataSize
& LONG_MAX
;
1695 ValueList
[i
].DataOffset
= (ULONG
) DataPtr
- (ULONG
) Buffer
;
1697 if (ValueCell
->DataSize
> 0)
1699 DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, NULL
);
1700 RtlCopyMemory(DataPtr
, DataCell
->Data
, ValueCell
->DataSize
& LONG_MAX
);
1701 CmiReleaseBlock(RegistryHive
, DataCell
);
1705 RtlCopyMemory(DataPtr
,
1706 &ValueCell
->DataOffset
,
1707 ValueCell
->DataSize
& LONG_MAX
);
1710 DataPtr
+= ValueCell
->DataSize
& LONG_MAX
;
1714 Status
= STATUS_BUFFER_TOO_SMALL
;
1717 BufferLength
+= ValueCell
->DataSize
& LONG_MAX
;
1720 if (NT_SUCCESS(Status
))
1721 *Length
= BufferLength
;
1723 *ReturnLength
= BufferLength
;
1725 /* Release hive lock */
1726 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1728 ObDereferenceObject(KeyObject
);
1730 DPRINT("Return Status 0x%X\n", Status
);
1738 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1740 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes
1749 IN HANDLE KeyHandle
,
1750 IN HANDLE FileHandle
,
1751 IN ULONG RestoreFlags
1760 IN HANDLE KeyHandle
,
1761 IN HANDLE FileHandle
)
1768 NtSetInformationKey(
1769 IN HANDLE KeyHandle
,
1770 IN CINT KeyInformationClass
,
1771 IN PVOID KeyInformation
,
1772 IN ULONG KeyInformationLength
)
1779 NtUnloadKey(IN HANDLE KeyHandle
)
1786 NtInitializeRegistry(IN BOOLEAN SetUpBoot
)
1788 NTSTATUS Status
= STATUS_ACCESS_DENIED
;
1790 if (CmiRegistryInitialized
== FALSE
)
1792 /* FIXME: save boot log file */
1794 Status
= CmiInitHives(SetUpBoot
);
1796 CmiRegistryInitialized
= TRUE
;