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
,
116 if (!NT_SUCCESS(Status
))
121 KeyObject
->ParentKey
= Object
;
123 if (CreateOptions
& REG_OPTION_VOLATILE
)
124 KeyObject
->RegistryHive
= CmiVolatileHive
;
126 KeyObject
->RegistryHive
= KeyObject
->ParentKey
->RegistryHive
;
128 KeyObject
->Flags
= 0;
129 KeyObject
->NumberOfSubKeys
= 0;
130 KeyObject
->SizeOfSubKeys
= 0;
131 KeyObject
->SubKeys
= NULL
;
133 /* Acquire hive lock */
134 ExAcquireResourceExclusiveLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
136 /* add key to subkeys of parent if needed */
137 Status
= CmiAddSubKey(KeyObject
->RegistryHive
,
138 KeyObject
->ParentKey
,
140 RemainingPath
.Buffer
,
141 RemainingPath
.Length
,
146 if (!NT_SUCCESS(Status
))
148 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
149 ObDereferenceObject(KeyObject
);
150 ObDereferenceObject(Object
);
151 return STATUS_UNSUCCESSFUL
;
154 KeyObject
->Name
= KeyObject
->KeyCell
->Name
;
155 KeyObject
->NameSize
= KeyObject
->KeyCell
->NameSize
;
157 if (KeyObject
->RegistryHive
== KeyObject
->ParentKey
->RegistryHive
)
159 KeyObject
->KeyCell
->ParentKeyOffset
= KeyObject
->ParentKey
->BlockOffset
;
160 KeyObject
->KeyCell
->SecurityKeyOffset
= KeyObject
->ParentKey
->KeyCell
->SecurityKeyOffset
;
164 KeyObject
->KeyCell
->ParentKeyOffset
= -1;
165 KeyObject
->KeyCell
->SecurityKeyOffset
= -1;
166 /* This key must rest in memory unless it is deleted
167 or file is unloaded */
168 ObReferenceObjectByPointer(KeyObject
,
169 STANDARD_RIGHTS_REQUIRED
,
174 CmiAddKeyToList(KeyObject
->ParentKey
, KeyObject
);
176 /* Release hive lock */
177 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
179 ObDereferenceObject(KeyObject
);
180 ObDereferenceObject(Object
);
183 *Disposition
= REG_CREATED_NEW_KEY
;
185 VERIFY_KEY_OBJECT(KeyObject
);
192 NtDeleteKey(IN HANDLE KeyHandle
)
194 PKEY_OBJECT KeyObject
;
197 DPRINT("KeyHandle %x\n", KeyHandle
);
199 /* Verify that the handle is valid and is a registry key */
200 Status
= ObReferenceObjectByHandle(KeyHandle
,
204 (PVOID
*) &KeyObject
,
207 if (!NT_SUCCESS(Status
))
212 /* Acquire hive lock */
213 ExAcquireResourceExclusiveLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
215 VERIFY_KEY_OBJECT(KeyObject
);
217 /* Set the marked for delete bit in the key object */
218 KeyObject
->Flags
|= KO_MARKED_FOR_DELETE
;
220 /* Dereference the object */
221 ObDereferenceObject(KeyObject
);
222 if(KeyObject
->RegistryHive
!= KeyObject
->ParentKey
->RegistryHive
)
223 ObDereferenceObject(KeyObject
);
224 /* Close the handle */
225 ObDeleteHandle(PsGetCurrentProcess(), KeyHandle
);
226 /* FIXME: I think that ObDeleteHandle should dereference the object */
227 ObDereferenceObject(KeyObject
);
229 /* Release hive lock */
230 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
232 return STATUS_SUCCESS
;
240 IN KEY_INFORMATION_CLASS KeyInformationClass
,
241 OUT PVOID KeyInformation
,
243 OUT PULONG ResultLength
247 PKEY_OBJECT KeyObject
;
248 PREGISTRY_HIVE RegistryHive
;
249 PKEY_CELL KeyCell
, SubKeyCell
;
250 PHASH_TABLE_CELL HashTableBlock
;
251 PKEY_BASIC_INFORMATION BasicInformation
;
252 PKEY_NODE_INFORMATION NodeInformation
;
253 PKEY_FULL_INFORMATION FullInformation
;
254 PDATA_CELL pClassData
;
256 DPRINT("KH %x I %d KIC %x KI %x L %d RL %x\n",
264 /* Verify that the handle is valid and is a registry key */
265 Status
= ObReferenceObjectByHandle(KeyHandle
,
266 KEY_ENUMERATE_SUB_KEYS
,
269 (PVOID
*) &KeyObject
,
271 if (!NT_SUCCESS(Status
))
273 DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status
);
277 /* Acquire hive lock */
278 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
280 VERIFY_KEY_OBJECT(KeyObject
);
282 /* Get pointer to KeyCell */
283 KeyCell
= KeyObject
->KeyCell
;
284 RegistryHive
= KeyObject
->RegistryHive
;
286 /* Get pointer to SubKey */
287 if (Index
>= KeyCell
->NumberOfSubKeys
)
289 if (RegistryHive
== CmiVolatileHive
)
291 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
292 ObDereferenceObject(KeyObject
);
293 DPRINT("No more volatile entries\n");
294 return(STATUS_NO_MORE_ENTRIES
);
299 PKEY_OBJECT CurKey
= NULL
;
301 /* Search volatile keys */
302 for (i
= 0; i
< KeyObject
->NumberOfSubKeys
; i
++)
304 CurKey
= KeyObject
->SubKeys
[i
];
305 if (CurKey
->RegistryHive
== CmiVolatileHive
)
307 if (Index
-- == KeyObject
->NumberOfSubKeys
)
311 if (Index
>= KeyCell
->NumberOfSubKeys
)
313 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
314 ObDereferenceObject(KeyObject
);
315 DPRINT("No more non-volatile entries\n");
316 return(STATUS_NO_MORE_ENTRIES
);
318 SubKeyCell
= CurKey
->KeyCell
;
323 HashTableBlock
= CmiGetBlock(RegistryHive
, KeyCell
->HashTableOffset
, NULL
);
324 SubKeyCell
= CmiGetKeyFromHashByIndex(RegistryHive
,
329 if (SubKeyCell
== NULL
)
331 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
332 ObDereferenceObject(KeyObject
);
333 DPRINT("No more entries\n");
334 return(STATUS_NO_MORE_ENTRIES
);
337 Status
= STATUS_SUCCESS
;
338 switch (KeyInformationClass
)
340 case KeyBasicInformation
:
341 /* Check size of buffer */
342 *ResultLength
= sizeof(KEY_BASIC_INFORMATION
) +
343 (SubKeyCell
->NameSize
) * sizeof(WCHAR
);
344 if (Length
< *ResultLength
)
346 Status
= STATUS_BUFFER_OVERFLOW
;
350 /* Fill buffer with requested info */
351 BasicInformation
= (PKEY_BASIC_INFORMATION
) KeyInformation
;
352 BasicInformation
->LastWriteTime
.u
.LowPart
= SubKeyCell
->LastWriteTime
.dwLowDateTime
;
353 BasicInformation
->LastWriteTime
.u
.HighPart
= SubKeyCell
->LastWriteTime
.dwHighDateTime
;
354 BasicInformation
->TitleIndex
= Index
;
355 BasicInformation
->NameLength
= SubKeyCell
->NameSize
* sizeof(WCHAR
);
356 mbstowcs(BasicInformation
->Name
,
358 SubKeyCell
->NameSize
* 2);
359 // BasicInformation->Name[SubKeyCell->NameSize] = 0;
363 case KeyNodeInformation
:
364 /* Check size of buffer */
365 *ResultLength
= sizeof(KEY_NODE_INFORMATION
) +
366 SubKeyCell
->NameSize
* sizeof(WCHAR
) +
367 SubKeyCell
->ClassSize
;
368 if (Length
< *ResultLength
)
370 Status
= STATUS_BUFFER_OVERFLOW
;
374 /* Fill buffer with requested info */
375 NodeInformation
= (PKEY_NODE_INFORMATION
) KeyInformation
;
376 NodeInformation
->LastWriteTime
.u
.LowPart
= SubKeyCell
->LastWriteTime
.dwLowDateTime
;
377 NodeInformation
->LastWriteTime
.u
.HighPart
= SubKeyCell
->LastWriteTime
.dwHighDateTime
;
378 NodeInformation
->TitleIndex
= Index
;
379 NodeInformation
->ClassOffset
= sizeof(KEY_NODE_INFORMATION
) +
380 SubKeyCell
->NameSize
* sizeof(WCHAR
);
381 NodeInformation
->ClassLength
= SubKeyCell
->ClassSize
;
382 NodeInformation
->NameLength
= SubKeyCell
->NameSize
* sizeof(WCHAR
);
383 mbstowcs(NodeInformation
->Name
,
385 SubKeyCell
->NameSize
* 2);
386 // NodeInformation->Name[SubKeyCell->NameSize] = 0;
387 if (SubKeyCell
->ClassSize
!= 0)
389 pClassData
=CmiGetBlock(KeyObject
->RegistryHive
,
390 SubKeyCell
->ClassNameOffset
,
392 wcsncpy(NodeInformation
->Name
+ SubKeyCell
->NameSize
,
393 (PWCHAR
) pClassData
->Data
,
394 SubKeyCell
->ClassSize
);
395 CmiReleaseBlock(RegistryHive
, pClassData
);
400 case KeyFullInformation
:
401 /* check size of buffer */
402 *ResultLength
= sizeof(KEY_FULL_INFORMATION
) +
403 SubKeyCell
->ClassSize
;
404 if (Length
< *ResultLength
)
406 Status
= STATUS_BUFFER_OVERFLOW
;
410 /* fill buffer with requested info */
411 FullInformation
= (PKEY_FULL_INFORMATION
) KeyInformation
;
412 FullInformation
->LastWriteTime
.u
.LowPart
= SubKeyCell
->LastWriteTime
.dwLowDateTime
;
413 FullInformation
->LastWriteTime
.u
.HighPart
= SubKeyCell
->LastWriteTime
.dwHighDateTime
;
414 FullInformation
->TitleIndex
= Index
;
415 FullInformation
->ClassOffset
= sizeof(KEY_FULL_INFORMATION
) -
417 FullInformation
->ClassLength
= SubKeyCell
->ClassSize
;
418 FullInformation
->SubKeys
= SubKeyCell
->NumberOfSubKeys
;
419 FullInformation
->MaxNameLen
=
420 CmiGetMaxNameLength(RegistryHive
, SubKeyCell
);
421 FullInformation
->MaxClassLen
=
422 CmiGetMaxClassLength(RegistryHive
, SubKeyCell
);
423 FullInformation
->Values
= SubKeyCell
->NumberOfValues
;
424 FullInformation
->MaxValueNameLen
=
425 CmiGetMaxValueNameLength(RegistryHive
, SubKeyCell
);
426 FullInformation
->MaxValueDataLen
=
427 CmiGetMaxValueDataLength(RegistryHive
, SubKeyCell
);
428 if (SubKeyCell
->ClassSize
!= 0)
430 pClassData
= CmiGetBlock(KeyObject
->RegistryHive
,
431 SubKeyCell
->ClassNameOffset
,
433 wcsncpy(FullInformation
->Class
,
434 (PWCHAR
) pClassData
->Data
,
435 SubKeyCell
->ClassSize
);
436 CmiReleaseBlock(RegistryHive
, pClassData
);
441 CmiReleaseBlock(RegistryHive
, SubKeyCell
);
443 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
444 ObDereferenceObject(KeyObject
);
446 DPRINT("Returning status %x\n", Status
);
453 NtEnumerateValueKey(IN HANDLE KeyHandle
,
455 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
,
456 OUT PVOID KeyValueInformation
,
458 OUT PULONG ResultLength
)
461 PKEY_OBJECT KeyObject
;
462 PREGISTRY_HIVE RegistryHive
;
464 PVALUE_CELL ValueCell
;
466 PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation
;
467 PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation
;
468 PKEY_VALUE_FULL_INFORMATION ValueFullInformation
;
470 DPRINT("KH %x I %d KVIC %x KVI %x L %d RL %x\n",
473 KeyValueInformationClass
,
478 /* Verify that the handle is valid and is a registry key */
479 Status
= ObReferenceObjectByHandle(KeyHandle
,
483 (PVOID
*) &KeyObject
,
486 if (!NT_SUCCESS(Status
))
491 /* Acquire hive lock */
492 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
494 VERIFY_KEY_OBJECT(KeyObject
);
496 /* Get pointer to KeyCell */
497 KeyCell
= KeyObject
->KeyCell
;
498 RegistryHive
= KeyObject
->RegistryHive
;
500 /* Get Value block of interest */
501 Status
= CmiGetValueFromKeyByIndex(RegistryHive
,
506 if (!NT_SUCCESS(Status
))
508 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
509 ObDereferenceObject(KeyObject
);
513 if (ValueCell
!= NULL
)
515 switch (KeyValueInformationClass
)
517 case KeyValueBasicInformation
:
518 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
520 *ResultLength
= sizeof(KEY_VALUE_BASIC_INFORMATION
) +
521 (ValueCell
->NameSize
+ 1) * sizeof(WCHAR
);
525 *ResultLength
= sizeof(KEY_VALUE_BASIC_INFORMATION
) +
526 ValueCell
->NameSize
+ sizeof(WCHAR
);
528 if (Length
< *ResultLength
)
530 Status
= STATUS_BUFFER_OVERFLOW
;
534 ValueBasicInformation
= (PKEY_VALUE_BASIC_INFORMATION
)
536 ValueBasicInformation
->TitleIndex
= 0;
537 ValueBasicInformation
->Type
= ValueCell
->DataType
;
538 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
540 ValueBasicInformation
->NameLength
=
541 (ValueCell
->NameSize
+ 1) * sizeof(WCHAR
);
542 CmiCopyPackedName(ValueBasicInformation
->Name
,
544 ValueCell
->NameSize
);
545 ValueBasicInformation
->Name
[ValueCell
->NameSize
] = 0;
549 ValueBasicInformation
->NameLength
=
550 ValueCell
->NameSize
+ sizeof(WCHAR
);
551 RtlCopyMemory(ValueBasicInformation
->Name
,
553 ValueCell
->NameSize
* sizeof(WCHAR
));
554 ValueBasicInformation
->Name
[ValueCell
->NameSize
/ sizeof(WCHAR
)] = 0;
559 case KeyValuePartialInformation
:
560 *ResultLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) +
561 (ValueCell
->DataSize
& LONG_MAX
);
562 if (Length
< *ResultLength
)
564 Status
= STATUS_BUFFER_OVERFLOW
;
568 ValuePartialInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)
570 ValuePartialInformation
->TitleIndex
= 0;
571 ValuePartialInformation
->Type
= ValueCell
->DataType
;
572 ValuePartialInformation
->DataLength
= ValueCell
->DataSize
& LONG_MAX
;
573 if(ValueCell
->DataSize
>0)
575 DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, NULL
);
576 RtlCopyMemory(ValuePartialInformation
->Data
,
578 ValueCell
->DataSize
& LONG_MAX
);
579 CmiReleaseBlock(RegistryHive
, DataCell
);
583 RtlCopyMemory(ValuePartialInformation
->Data
,
584 &ValueCell
->DataOffset
,
585 ValueCell
->DataSize
& LONG_MAX
);
587 DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, NULL
);
591 case KeyValueFullInformation
:
592 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
594 *ResultLength
= sizeof(KEY_VALUE_FULL_INFORMATION
) +
595 (ValueCell
->NameSize
+ 1) * sizeof(WCHAR
) +
596 (ValueCell
->DataSize
& LONG_MAX
);
600 *ResultLength
= sizeof(KEY_VALUE_FULL_INFORMATION
) +
601 ValueCell
->NameSize
+ sizeof(WCHAR
) +
602 (ValueCell
->DataSize
& LONG_MAX
);
604 if (Length
< *ResultLength
)
606 Status
= STATUS_BUFFER_OVERFLOW
;
610 ValueFullInformation
= (PKEY_VALUE_FULL_INFORMATION
)
612 ValueFullInformation
->TitleIndex
= 0;
613 ValueFullInformation
->Type
= ValueCell
->DataType
;
614 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
616 ValueFullInformation
->DataOffset
=
617 (DWORD
)ValueFullInformation
->Name
- (DWORD
) ValueFullInformation
618 + (ValueCell
->NameSize
+ 1) * sizeof(WCHAR
);
622 ValueFullInformation
->DataOffset
=
623 (DWORD
)ValueFullInformation
->Name
- (DWORD
) ValueFullInformation
624 + ValueCell
->NameSize
+ sizeof(WCHAR
);
626 ValueFullInformation
->DataOffset
=
627 (ValueFullInformation
->DataOffset
+ 3) & 0xfffffffc;
628 ValueFullInformation
->DataLength
= ValueCell
->DataSize
& LONG_MAX
;
629 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
631 ValueFullInformation
->NameLength
=
632 (ValueCell
->NameSize
+ 1) * sizeof(WCHAR
);
634 CmiCopyPackedName(ValueFullInformation
->Name
,
636 ValueCell
->NameSize
);
637 ValueFullInformation
->Name
[ValueCell
->NameSize
] = 0;
641 ValueFullInformation
->NameLength
=
642 ValueCell
->NameSize
+ sizeof(WCHAR
);
643 RtlCopyMemory(ValueFullInformation
->Name
,
645 ValueCell
->NameSize
);
646 ValueFullInformation
->Name
[ValueCell
->NameSize
/ sizeof(WCHAR
)] = 0;
648 if (ValueCell
->DataSize
> 0)
650 DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, NULL
);
651 RtlCopyMemory((PCHAR
) ValueFullInformation
652 + ValueFullInformation
->DataOffset
,
654 ValueCell
->DataSize
& LONG_MAX
);
655 CmiReleaseBlock(RegistryHive
, DataCell
);
659 RtlCopyMemory((PCHAR
) ValueFullInformation
660 + ValueFullInformation
->DataOffset
,
661 &ValueCell
->DataOffset
,
662 ValueCell
->DataSize
& LONG_MAX
);
670 Status
= STATUS_UNSUCCESSFUL
;
673 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
674 ObDereferenceObject(KeyObject
);
681 NtFlushKey(IN HANDLE KeyHandle
)
684 PKEY_OBJECT KeyObject
;
685 PREGISTRY_HIVE RegistryHive
;
686 WCHAR LogName
[MAX_PATH
];
687 UNICODE_STRING TmpFileName
;
689 // HANDLE FileHandleLog;
690 OBJECT_ATTRIBUTES ObjectAttributes
;
691 LARGE_INTEGER fileOffset
;
695 DPRINT("KeyHandle %x\n", KeyHandle
);
697 /* Verify that the handle is valid and is a registry key */
698 Status
= ObReferenceObjectByHandle(KeyHandle
,
702 (PVOID
*) &KeyObject
,
705 if (!NT_SUCCESS(Status
))
710 /* Acquire hive lock */
711 ExAcquireResourceExclusiveLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
713 VERIFY_KEY_OBJECT(KeyObject
);
715 RegistryHive
= KeyObject
->RegistryHive
;
717 /* Then write changed blocks in .log */
718 wcscpy(LogName
,RegistryHive
->Filename
.Buffer
);
719 wcscat(LogName
,L
".log");
720 RtlInitUnicodeString (&TmpFileName
, LogName
);
721 InitializeObjectAttributes(&ObjectAttributes
,
727 /* BEGIN FIXME : actually (26 November 200) vfatfs.sys can't create new files
728 so we can't create log file
729 Status = ZwCreateFile(&FileHandleLog,
734 FILE_ATTRIBUTE_NORMAL,
741 if (!NT_SUCCESS(Status))
743 ObDereferenceObject(KeyObject);
747 Status = ZwWriteFile(FileHandleLog,
752 RegistryHive->HiveHeader,
757 if (!NT_SUCCESS(Status))
759 ZwClose(FileHandleLog);
760 ObDereferenceObject(KeyObject);
764 for (i = 0; i < RegistryHive->BlockListSize ; i++)
766 if ( RegistryHive->BlockList[i]->DateModified.dwHighDateTime
767 > RegistryHive->HiveHeader->DateModified.dwHighDateTime
768 || (RegistryHive->BlockList[i]->DateModified.dwHighDateTime
769 == RegistryHive->HiveHeader->DateModified.dwHighDateTime
770 && RegistryHive->BlockList[i]->DateModified.dwLowDateTime
771 > RegistryHive->HiveHeader->DateModified.dwLowDateTime
775 Status = ZwWriteFile(FileHandleLog,
780 RegistryHive->BlockList[i],
781 RegistryHive->BlockList[i]->BlockSize ,
785 if (!NT_SUCCESS(Status))
787 ZwClose(FileHandleLog);
788 ObDereferenceObject(KeyObject);
792 ZwClose(FileHandleLog);
795 /* Update header of RegistryHive with Version >VersionOld */
796 /* this allow recover if system crash while updating hove file */
797 InitializeObjectAttributes(&ObjectAttributes
,
798 &RegistryHive
->Filename
,
803 Status
= NtOpenFile(&FileHandle
,
808 FILE_SYNCHRONOUS_IO_NONALERT
);
809 if (!NT_SUCCESS(Status
))
811 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
812 ObDereferenceObject(KeyObject
);
816 RegistryHive
->HiveHeader
->Version
++;
818 Status
= ZwWriteFile(FileHandle
,
823 RegistryHive
->HiveHeader
,
827 if (!NT_SUCCESS(Status
))
830 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
831 ObDereferenceObject(KeyObject
);
835 /* Update changed blocks in file */
836 fileOffset
.u
.HighPart
= 0;
837 for (i
= 0; i
< RegistryHive
->BlockListSize
; i
++)
839 if (RegistryHive
->BlockList
[i
]->DateModified
.dwHighDateTime
840 > RegistryHive
->HiveHeader
->DateModified
.dwHighDateTime
841 || (RegistryHive
->BlockList
[i
]->DateModified
.dwHighDateTime
842 == RegistryHive
->HiveHeader
->DateModified
.dwHighDateTime
843 && RegistryHive
->BlockList
[i
]->DateModified
.dwLowDateTime
844 > RegistryHive
->HiveHeader
->DateModified
.dwLowDateTime
))
846 fileOffset
.u
.LowPart
= RegistryHive
->BlockList
[i
]->BlockOffset
+4096;
847 Status
= NtWriteFile(FileHandle
,
852 RegistryHive
->BlockList
[i
],
853 RegistryHive
->BlockList
[i
]->BlockSize
,
856 if (!NT_SUCCESS(Status
))
859 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
860 ObDereferenceObject(KeyObject
);
866 /* Change version in header */
867 RegistryHive
->HiveHeader
->VersionOld
= RegistryHive
->HiveHeader
->Version
;
868 ZwQuerySystemTime((PTIME
) &RegistryHive
->HiveHeader
->DateModified
);
870 /* Calculate checksum */
871 RegistryHive
->HiveHeader
->Checksum
= 0;
872 pEntDword
= (DWORD
*) RegistryHive
->HiveHeader
;
873 for (i
= 0; i
< 127 ; i
++)
875 RegistryHive
->HiveHeader
->Checksum
^= pEntDword
[i
];
878 /* Write new header */
879 fileOffset
.u
.LowPart
= 0;
880 Status
= ZwWriteFile(FileHandle
,
885 RegistryHive
->HiveHeader
,
890 if (!NT_SUCCESS(Status
))
893 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
894 ObDereferenceObject(KeyObject
);
899 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
900 ObDereferenceObject(KeyObject
);
901 return STATUS_SUCCESS
;
906 NtOpenKey(OUT PHANDLE KeyHandle
,
907 IN ACCESS_MASK DesiredAccess
,
908 IN POBJECT_ATTRIBUTES ObjectAttributes
)
910 UNICODE_STRING RemainingPath
;
914 DPRINT("NtOpenFile(KH %x DA %x OA %x OA->ON '%wZ'\n",
918 ObjectAttributes
? ObjectAttributes
->ObjectName
: NULL
);
920 RemainingPath
.Buffer
= NULL
;
921 Status
= ObFindObject(ObjectAttributes
,
925 if (!NT_SUCCESS(Status
))
930 VERIFY_KEY_OBJECT((PKEY_OBJECT
) Object
);
932 DPRINT("RemainingPath '%wZ'\n", &RemainingPath
);
934 if ((RemainingPath
.Buffer
!= NULL
) && (RemainingPath
.Buffer
[0] != 0))
936 ObDereferenceObject(Object
);
937 return(STATUS_UNSUCCESSFUL
);
940 /* Fail if the key has been deleted */
941 if (((PKEY_OBJECT
)Object
)->Flags
& KO_MARKED_FOR_DELETE
)
943 ObDereferenceObject(Object
);
944 return(STATUS_UNSUCCESSFUL
);
947 Status
= ObCreateHandle(PsGetCurrentProcess(),
952 ObDereferenceObject(Object
);
954 if (!NT_SUCCESS(Status
))
959 return(STATUS_SUCCESS
);
964 NtQueryKey(IN HANDLE KeyHandle
,
965 IN KEY_INFORMATION_CLASS KeyInformationClass
,
966 OUT PVOID KeyInformation
,
968 OUT PULONG ResultLength
)
970 PKEY_BASIC_INFORMATION BasicInformation
;
971 PKEY_NODE_INFORMATION NodeInformation
;
972 PKEY_FULL_INFORMATION FullInformation
;
973 PREGISTRY_HIVE RegistryHive
;
974 PDATA_CELL pClassData
;
975 PKEY_OBJECT KeyObject
;
979 DPRINT("KH %x KIC %x KI %x L %d RL %x\n",
986 /* Verify that the handle is valid and is a registry key */
987 Status
= ObReferenceObjectByHandle(KeyHandle
,
991 (PVOID
*) &KeyObject
,
993 if (!NT_SUCCESS(Status
))
998 /* Acquire hive lock */
999 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1001 VERIFY_KEY_OBJECT(KeyObject
);
1003 /* Get pointer to KeyCell */
1004 KeyCell
= KeyObject
->KeyCell
;
1005 RegistryHive
= KeyObject
->RegistryHive
;
1007 Status
= STATUS_SUCCESS
;
1008 switch (KeyInformationClass
)
1010 case KeyBasicInformation
:
1011 /* Check size of buffer */
1012 if (Length
< sizeof(KEY_BASIC_INFORMATION
) +
1013 KeyObject
->NameSize
* sizeof(WCHAR
))
1015 Status
= STATUS_BUFFER_OVERFLOW
;
1019 /* Fill buffer with requested info */
1020 BasicInformation
= (PKEY_BASIC_INFORMATION
) KeyInformation
;
1021 BasicInformation
->LastWriteTime
.u
.LowPart
= KeyCell
->LastWriteTime
.dwLowDateTime
;
1022 BasicInformation
->LastWriteTime
.u
.HighPart
= KeyCell
->LastWriteTime
.dwHighDateTime
;
1023 BasicInformation
->TitleIndex
= 0;
1024 BasicInformation
->NameLength
= (KeyObject
->NameSize
) * sizeof(WCHAR
);
1025 mbstowcs(BasicInformation
->Name
,
1027 KeyObject
->NameSize
*sizeof(WCHAR
));
1028 *ResultLength
= sizeof(KEY_BASIC_INFORMATION
) +
1029 KeyObject
->NameSize
* sizeof(WCHAR
);
1033 case KeyNodeInformation
:
1034 /* Check size of buffer */
1035 if (Length
< sizeof(KEY_NODE_INFORMATION
)
1036 + KeyObject
->NameSize
* sizeof(WCHAR
)
1037 + KeyCell
->ClassSize
)
1039 Status
= STATUS_BUFFER_OVERFLOW
;
1043 /* Fill buffer with requested info */
1044 NodeInformation
= (PKEY_NODE_INFORMATION
) KeyInformation
;
1045 NodeInformation
->LastWriteTime
.u
.LowPart
= KeyCell
->LastWriteTime
.dwLowDateTime
;
1046 NodeInformation
->LastWriteTime
.u
.HighPart
= KeyCell
->LastWriteTime
.dwHighDateTime
;
1047 NodeInformation
->TitleIndex
= 0;
1048 NodeInformation
->ClassOffset
= sizeof(KEY_NODE_INFORMATION
) +
1049 KeyObject
->NameSize
* sizeof(WCHAR
);
1050 NodeInformation
->ClassLength
= KeyCell
->ClassSize
;
1051 NodeInformation
->NameLength
= KeyObject
->NameSize
* sizeof(WCHAR
);
1052 mbstowcs(NodeInformation
->Name
,
1054 KeyObject
->NameSize
* sizeof(WCHAR
));
1056 if (KeyCell
->ClassSize
!= 0)
1058 pClassData
= CmiGetBlock(KeyObject
->RegistryHive
,
1059 KeyCell
->ClassNameOffset
,
1061 wcsncpy(NodeInformation
->Name
+ KeyObject
->NameSize
* sizeof(WCHAR
),
1062 (PWCHAR
)pClassData
->Data
,
1063 KeyCell
->ClassSize
);
1064 CmiReleaseBlock(RegistryHive
, pClassData
);
1066 *ResultLength
= sizeof(KEY_NODE_INFORMATION
)
1067 + KeyObject
->NameSize
* sizeof(WCHAR
)
1068 + KeyCell
->ClassSize
;
1072 case KeyFullInformation
:
1073 /* Check size of buffer */
1074 if (Length
< sizeof(KEY_FULL_INFORMATION
) + KeyCell
->ClassSize
)
1076 Status
= STATUS_BUFFER_OVERFLOW
;
1080 /* Fill buffer with requested info */
1081 FullInformation
= (PKEY_FULL_INFORMATION
) KeyInformation
;
1082 FullInformation
->LastWriteTime
.u
.LowPart
= KeyCell
->LastWriteTime
.dwLowDateTime
;
1083 FullInformation
->LastWriteTime
.u
.HighPart
= KeyCell
->LastWriteTime
.dwHighDateTime
;
1084 FullInformation
->TitleIndex
= 0;
1085 FullInformation
->ClassOffset
= sizeof(KEY_FULL_INFORMATION
) - sizeof(WCHAR
);
1086 FullInformation
->ClassLength
= KeyCell
->ClassSize
;
1087 FullInformation
->SubKeys
= KeyCell
->NumberOfSubKeys
;
1088 FullInformation
->MaxNameLen
=
1089 CmiGetMaxNameLength(RegistryHive
, KeyCell
);
1090 FullInformation
->MaxClassLen
=
1091 CmiGetMaxClassLength(RegistryHive
, KeyCell
);
1092 FullInformation
->Values
= KeyCell
->NumberOfValues
;
1093 FullInformation
->MaxValueNameLen
=
1094 CmiGetMaxValueNameLength(RegistryHive
, KeyCell
);
1095 FullInformation
->MaxValueDataLen
=
1096 CmiGetMaxValueDataLength(RegistryHive
, KeyCell
);
1097 if (KeyCell
->ClassSize
!= 0)
1099 pClassData
=CmiGetBlock(KeyObject
->RegistryHive
,
1100 KeyCell
->ClassNameOffset
,
1102 wcsncpy(FullInformation
->Class
,
1103 (PWCHAR
)pClassData
->Data
,
1104 KeyCell
->ClassSize
);
1105 CmiReleaseBlock(RegistryHive
, pClassData
);
1107 *ResultLength
= sizeof(KEY_FULL_INFORMATION
) + KeyCell
->ClassSize
;
1112 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1113 ObDereferenceObject(KeyObject
);
1120 NtQueryValueKey(IN HANDLE KeyHandle
,
1121 IN PUNICODE_STRING ValueName
,
1122 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
,
1123 OUT PVOID KeyValueInformation
,
1125 OUT PULONG ResultLength
)
1128 PKEY_OBJECT KeyObject
;
1129 PREGISTRY_HIVE RegistryHive
;
1131 PVALUE_CELL ValueCell
;
1132 PDATA_CELL DataCell
;
1133 PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation
;
1134 PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation
;
1135 PKEY_VALUE_FULL_INFORMATION ValueFullInformation
;
1137 DPRINT("NtQueryValueKey(KeyHandle %x ValueName %S Length %x)\n",
1138 KeyHandle
, ValueName
->Buffer
, Length
);
1140 /* Verify that the handle is valid and is a registry key */
1141 Status
= ObReferenceObjectByHandle(KeyHandle
,
1145 (PVOID
*)&KeyObject
,
1148 if (!NT_SUCCESS(Status
))
1150 DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status
);
1154 /* Acquire hive lock */
1155 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1157 VERIFY_KEY_OBJECT(KeyObject
);
1159 /* Get pointer to KeyCell */
1160 KeyCell
= KeyObject
->KeyCell
;
1161 RegistryHive
= KeyObject
->RegistryHive
;
1163 /* Get Value block of interest */
1164 Status
= CmiScanKeyForValue(RegistryHive
,
1169 if (!NT_SUCCESS(Status
))
1171 DPRINT("CmiScanKeyForValue() failed with status %x\n", Status
);
1172 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1173 ObDereferenceObject(KeyObject
);
1176 else if (ValueCell
!= NULL
)
1178 switch (KeyValueInformationClass
)
1180 case KeyValueBasicInformation
:
1181 *ResultLength
= sizeof(KEY_VALUE_BASIC_INFORMATION
)
1182 + ValueCell
->NameSize
* sizeof(WCHAR
);
1183 if (Length
< *ResultLength
)
1185 Status
= STATUS_BUFFER_TOO_SMALL
;
1189 ValueBasicInformation
= (PKEY_VALUE_BASIC_INFORMATION
)
1190 KeyValueInformation
;
1191 ValueBasicInformation
->TitleIndex
= 0;
1192 ValueBasicInformation
->Type
= ValueCell
->DataType
;
1193 ValueBasicInformation
->NameLength
=
1194 (ValueCell
->NameSize
+ 1) * sizeof(WCHAR
);
1195 mbstowcs(ValueBasicInformation
->Name
,
1196 ValueCell
->Name
,ValueCell
->NameSize
* 2);
1197 ValueBasicInformation
->Name
[ValueCell
->NameSize
] = 0;
1201 case KeyValuePartialInformation
:
1202 *ResultLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
)
1203 + (ValueCell
->DataSize
& LONG_MAX
);
1204 if (Length
< *ResultLength
)
1206 Status
= STATUS_BUFFER_TOO_SMALL
;
1210 ValuePartialInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)
1211 KeyValueInformation
;
1212 ValuePartialInformation
->TitleIndex
= 0;
1213 ValuePartialInformation
->Type
= ValueCell
->DataType
;
1214 ValuePartialInformation
->DataLength
= ValueCell
->DataSize
& LONG_MAX
;
1215 if (ValueCell
->DataSize
> 0)
1217 DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, NULL
);
1218 RtlCopyMemory(ValuePartialInformation
->Data
,
1220 ValueCell
->DataSize
& LONG_MAX
);
1221 CmiReleaseBlock(RegistryHive
, DataCell
);
1225 RtlCopyMemory(ValuePartialInformation
->Data
,
1226 &ValueCell
->DataOffset
,
1227 ValueCell
->DataSize
& LONG_MAX
);
1232 case KeyValueFullInformation
:
1233 *ResultLength
= sizeof(KEY_VALUE_FULL_INFORMATION
)
1234 + (ValueCell
->NameSize
-1) * sizeof(WCHAR
)
1235 + (ValueCell
->DataSize
& LONG_MAX
);
1236 if (Length
< *ResultLength
)
1238 Status
= STATUS_BUFFER_TOO_SMALL
;
1242 ValueFullInformation
= (PKEY_VALUE_FULL_INFORMATION
)
1243 KeyValueInformation
;
1244 ValueFullInformation
->TitleIndex
= 0;
1245 ValueFullInformation
->Type
= ValueCell
->DataType
;
1246 ValueFullInformation
->DataOffset
=
1247 (DWORD
)ValueFullInformation
->Name
- (DWORD
)ValueFullInformation
1248 + (ValueCell
->NameSize
+ 1) * sizeof(WCHAR
);
1249 ValueFullInformation
->DataOffset
=
1250 (ValueFullInformation
->DataOffset
+ 3) &0xfffffffc;
1251 ValueFullInformation
->DataLength
= ValueCell
->DataSize
& LONG_MAX
;
1252 ValueFullInformation
->NameLength
=
1253 (ValueCell
->NameSize
+ 1) * sizeof(WCHAR
);
1254 mbstowcs(ValueFullInformation
->Name
, ValueCell
->Name
,ValueCell
->NameSize
*2);
1255 ValueFullInformation
->Name
[ValueCell
->NameSize
] = 0;
1256 if (ValueCell
->DataSize
> 0)
1258 DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, NULL
);
1259 RtlCopyMemory((PCHAR
) ValueFullInformation
1260 + ValueFullInformation
->DataOffset
,
1262 ValueCell
->DataSize
& LONG_MAX
);
1263 CmiReleaseBlock(RegistryHive
, DataCell
);
1267 RtlCopyMemory((PCHAR
) ValueFullInformation
1268 + ValueFullInformation
->DataOffset
,
1269 &ValueCell
->DataOffset
,
1270 ValueCell
->DataSize
& LONG_MAX
);
1278 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
1281 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1282 ObDereferenceObject(KeyObject
);
1289 NtSetValueKey(IN HANDLE KeyHandle
,
1290 IN PUNICODE_STRING ValueName
,
1291 IN ULONG TitleIndex
,
1297 PKEY_OBJECT KeyObject
;
1298 PREGISTRY_HIVE RegistryHive
;
1300 PVALUE_CELL ValueCell
;
1301 BLOCK_OFFSET VBOffset
;
1302 PDATA_CELL DataCell
;
1303 PDATA_CELL NewDataCell
;
1305 ULONG DesiredAccess
;
1307 DPRINT("NtSetValueKey(KeyHandle %x ValueName %S Type %d)\n",
1308 KeyHandle
, ValueName
? ValueName
->Buffer
: NULL
, Type
);
1310 DesiredAccess
= KEY_SET_VALUE
;
1311 if (Type
== REG_LINK
)
1312 DesiredAccess
|= KEY_CREATE_LINK
;
1314 /* Verify that the handle is valid and is a registry key */
1315 Status
= ObReferenceObjectByHandle(KeyHandle
,
1319 (PVOID
*)&KeyObject
,
1321 if (!NT_SUCCESS(Status
))
1324 /* Acquire hive lock */
1325 ExAcquireResourceExclusiveLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1327 VERIFY_KEY_OBJECT(KeyObject
);
1329 /* Get pointer to key cell */
1330 KeyCell
= KeyObject
->KeyCell
;
1331 RegistryHive
= KeyObject
->RegistryHive
;
1332 Status
= CmiScanKeyForValue(RegistryHive
,
1337 if (!NT_SUCCESS(Status
))
1339 DPRINT1("Value not found. Status 0x%X\n", Status
);
1341 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1342 ObDereferenceObject(KeyObject
);
1346 if (ValueCell
== NULL
)
1348 DPRINT("Allocate new value cell\n");
1349 Status
= CmiAddValueToKey(RegistryHive
,
1356 if (!NT_SUCCESS(Status
))
1358 DPRINT1("Cannot add value. Status 0x%X\n", Status
);
1360 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1361 ObDereferenceObject(KeyObject
);
1365 DPRINT("DataSize %lu\n", DataSize
);
1366 DPRINT("ValueCell %p\n", ValueCell
);
1367 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
1371 /* If datasize <= 4 then write in valueblock directly */
1372 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
1373 if ((ValueCell
->DataSize
>= 0) &&
1374 (DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, NULL
)))
1376 CmiDestroyBlock(RegistryHive
, DataCell
, ValueCell
->DataOffset
);
1379 RtlCopyMemory(&ValueCell
->DataOffset
, Data
, DataSize
);
1380 ValueCell
->DataSize
= DataSize
| 0x80000000;
1381 ValueCell
->DataType
= Type
;
1382 RtlMoveMemory(&ValueCell
->DataOffset
, Data
, DataSize
);
1384 else if (DataSize
<= (ULONG
) (ValueCell
->DataSize
& 0x7fffffff))
1386 /* If new data size is <= current then overwrite current data */
1387 DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
,&pBin
);
1388 RtlCopyMemory(DataCell
->Data
, Data
, DataSize
);
1389 ValueCell
->DataSize
= DataSize
;
1390 ValueCell
->DataType
= Type
;
1391 CmiReleaseBlock(RegistryHive
, DataCell
);
1393 /* Update time of heap */
1394 if (IsPermanentHive(RegistryHive
))
1396 ZwQuerySystemTime((PTIME
) &pBin
->DateModified
);
1402 * New data size is larger than the current, destroy current
1403 * data block and allocate a new one.
1405 BLOCK_OFFSET NewOffset
;
1407 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
1409 if ((ValueCell
->DataSize
>= 0) &&
1410 (DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, NULL
)))
1412 CmiDestroyBlock(RegistryHive
, DataCell
, ValueCell
->DataOffset
);
1413 ValueCell
->DataSize
= 0;
1414 ValueCell
->DataType
= 0;
1415 ValueCell
->DataOffset
= 0xffffffff;
1418 Status
= CmiAllocateBlock(RegistryHive
,
1419 (PVOID
*)&NewDataCell
,
1422 if (!NT_SUCCESS(Status
))
1424 DPRINT("CmiAllocateBlock() failed (Status %lx)\n", Status
);
1426 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1427 ObDereferenceObject(KeyObject
);
1432 RtlCopyMemory(&NewDataCell
->Data
[0], Data
, DataSize
);
1433 ValueCell
->DataSize
= DataSize
;
1434 ValueCell
->DataType
= Type
;
1435 CmiReleaseBlock(RegistryHive
, NewDataCell
);
1436 ValueCell
->DataOffset
= NewOffset
;
1440 if ((_wcsicmp(ValueName
->Buffer
, L
"SymbolicLinkValue") == 0) &&
1443 KeyCell
->Type
= REG_LINK_KEY_CELL_TYPE
;
1446 /* Update time of heap */
1447 if (IsPermanentHive(RegistryHive
) && CmiGetBlock(RegistryHive
, VBOffset
, &pBin
))
1449 ZwQuerySystemTime((PTIME
) &pBin
->DateModified
);
1452 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1453 ObDereferenceObject(KeyObject
);
1455 DPRINT("Return Status 0x%X\n", Status
);
1462 NtDeleteValueKey(IN HANDLE KeyHandle
,
1463 IN PUNICODE_STRING ValueName
)
1465 PKEY_OBJECT KeyObject
;
1468 /* Verify that the handle is valid and is a registry key */
1469 Status
= ObReferenceObjectByHandle(KeyHandle
,
1473 (PVOID
*)&KeyObject
,
1475 if (!NT_SUCCESS(Status
))
1480 /* Acquire hive lock */
1481 ExAcquireResourceExclusiveLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1483 VERIFY_KEY_OBJECT(KeyObject
);
1485 Status
= CmiDeleteValueFromKey(KeyObject
->RegistryHive
,
1489 /* Release hive lock */
1490 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1492 ObDereferenceObject(KeyObject
);
1499 NtLoadKey(PHANDLE KeyHandle
,
1500 POBJECT_ATTRIBUTES ObjectAttributes
)
1502 return NtLoadKey2(KeyHandle
, ObjectAttributes
, 0);
1507 NtLoadKey2(IN PHANDLE KeyHandle
,
1508 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1517 IN HANDLE KeyHandle
,
1519 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1520 IN PVOID ApcContext OPTIONAL
,
1521 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1522 IN ULONG CompletionFilter
,
1523 IN BOOLEAN Asynchroneous
,
1524 OUT PVOID ChangeBuffer
,
1526 IN BOOLEAN WatchSubtree
)
1533 NtQueryMultipleValueKey(IN HANDLE KeyHandle
,
1534 IN OUT PKEY_VALUE_ENTRY ValueList
,
1535 IN ULONG NumberOfValues
,
1537 IN OUT PULONG Length
,
1538 OUT PULONG ReturnLength
)
1540 PREGISTRY_HIVE RegistryHive
;
1541 PVALUE_CELL ValueCell
;
1542 PKEY_OBJECT KeyObject
;
1543 PDATA_CELL DataCell
;
1544 ULONG BufferLength
= 0;
1550 /* Verify that the handle is valid and is a registry key */
1551 Status
= ObReferenceObjectByHandle(KeyHandle
,
1555 (PVOID
*) &KeyObject
,
1557 if (!NT_SUCCESS(Status
))
1559 DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status
);
1563 /* Acquire hive lock */
1564 ExAcquireResourceSharedLite(&KeyObject
->RegistryHive
->HiveResource
, TRUE
);
1566 VERIFY_KEY_OBJECT(KeyObject
);
1568 /* Get pointer to KeyCell */
1569 KeyCell
= KeyObject
->KeyCell
;
1570 RegistryHive
= KeyObject
->RegistryHive
;
1572 DataPtr
= (PUCHAR
) Buffer
;
1574 for (i
= 0; i
< NumberOfValues
; i
++)
1576 DPRINT("ValueName: '%wZ'\n", ValueList
[i
].ValueName
);
1578 /* Get Value block of interest */
1579 Status
= CmiScanKeyForValue(RegistryHive
,
1581 ValueList
[i
].ValueName
,
1585 if (!NT_SUCCESS(Status
))
1587 DPRINT("CmiScanKeyForValue() failed with status %x\n", Status
);
1590 else if (ValueCell
== NULL
)
1592 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
1596 BufferLength
= (BufferLength
+ 3) & 0xfffffffc;
1598 if (BufferLength
+ (ValueCell
->DataSize
& LONG_MAX
) <= *Length
)
1600 DataPtr
= (PUCHAR
)(((ULONG
)DataPtr
+ 3) & 0xfffffffc);
1602 ValueList
[i
].Type
= ValueCell
->DataType
;
1603 ValueList
[i
].DataLength
= ValueCell
->DataSize
& LONG_MAX
;
1604 ValueList
[i
].DataOffset
= (ULONG
) DataPtr
- (ULONG
) Buffer
;
1606 if (ValueCell
->DataSize
> 0)
1608 DataCell
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, NULL
);
1609 RtlCopyMemory(DataPtr
, DataCell
->Data
, ValueCell
->DataSize
& LONG_MAX
);
1610 CmiReleaseBlock(RegistryHive
, DataCell
);
1614 RtlCopyMemory(DataPtr
,
1615 &ValueCell
->DataOffset
,
1616 ValueCell
->DataSize
& LONG_MAX
);
1619 DataPtr
+= ValueCell
->DataSize
& LONG_MAX
;
1623 Status
= STATUS_BUFFER_TOO_SMALL
;
1626 BufferLength
+= ValueCell
->DataSize
& LONG_MAX
;
1629 if (NT_SUCCESS(Status
))
1630 *Length
= BufferLength
;
1632 *ReturnLength
= BufferLength
;
1634 /* Release hive lock */
1635 ExReleaseResourceLite(&KeyObject
->RegistryHive
->HiveResource
);
1637 ObDereferenceObject(KeyObject
);
1639 DPRINT("Return Status 0x%X\n", Status
);
1647 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1649 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes
1658 IN HANDLE KeyHandle
,
1659 IN HANDLE FileHandle
,
1660 IN ULONG RestoreFlags
1669 IN HANDLE KeyHandle
,
1670 IN HANDLE FileHandle
)
1677 NtSetInformationKey(
1678 IN HANDLE KeyHandle
,
1679 IN CINT KeyInformationClass
,
1680 IN PVOID KeyInformation
,
1681 IN ULONG KeyInformationLength
)
1688 NtUnloadKey(IN HANDLE KeyHandle
)
1695 NtInitializeRegistry(IN BOOLEAN SetUpBoot
)
1697 NTSTATUS Status
= STATUS_ACCESS_DENIED
;
1699 if (CmiRegistryInitialized
== FALSE
)
1701 /* FIXME: save boot log file */
1703 Status
= CmiInitHives(SetUpBoot
);
1705 CmiRegistryInitialized
= TRUE
;