2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/config/cmapi.c
5 * PURPOSE: Configuration Manager - Internal Registry APIs
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
15 BOOLEAN CmBootAcceptFirstTime
= TRUE
;
16 BOOLEAN CmFirstTime
= TRUE
;
18 /* FUNCTIONS *****************************************************************/
22 NtCreateKey(OUT PHANDLE KeyHandle
,
23 IN ACCESS_MASK DesiredAccess
,
24 IN POBJECT_ATTRIBUTES ObjectAttributes
,
26 IN PUNICODE_STRING Class
,
27 IN ULONG CreateOptions
,
28 OUT PULONG Disposition
)
30 NTSTATUS Status
= STATUS_SUCCESS
;
31 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
32 CM_PARSE_CONTEXT ParseContext
= {0};
35 DPRINT("NtCreateKey(OB name %wZ)\n", ObjectAttributes
->ObjectName
);
37 /* Check for user-mode caller */
38 if (PreviousMode
== UserMode
)
40 /* Prepare to probe parameters */
43 /* Check if we have a class */
47 ProbeForReadUnicodeString(Class
);
48 ProbeForRead(ParseContext
.Class
.Buffer
,
49 ParseContext
.Class
.Length
,
51 ParseContext
.Class
= *Class
;
54 /* Probe the key handle */
55 ProbeForWriteHandle(KeyHandle
);
58 /* Probe object attributes */
59 ProbeForRead(ObjectAttributes
, sizeof(OBJECT_ATTRIBUTES
), 4);
63 /* Get the error code */
64 Status
= _SEH_GetExceptionCode();
67 if(!NT_SUCCESS(Status
)) return Status
;
71 /* Save the class directly */
72 if (Class
) ParseContext
.Class
= *Class
;
75 /* Setup the parse context */
76 ParseContext
.CreateOperation
= TRUE
;
77 ParseContext
.CreateOptions
= CreateOptions
;
80 Status
= ObOpenObjectByName(ObjectAttributes
,
90 if (NT_SUCCESS(Status
)) *KeyHandle
= Handle
;
92 /* Return data to user */
93 if (Disposition
) *Disposition
= ParseContext
.Disposition
;
98 Status
= _SEH_GetExceptionCode();
108 NtOpenKey(OUT PHANDLE KeyHandle
,
109 IN ACCESS_MASK DesiredAccess
,
110 IN POBJECT_ATTRIBUTES ObjectAttributes
)
112 CM_PARSE_CONTEXT ParseContext
= {0};
114 NTSTATUS Status
= STATUS_SUCCESS
;
115 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
117 DPRINT("NtOpenKey(OB 0x%wZ)\n", ObjectAttributes
->ObjectName
);
119 /* Check for user-mode caller */
120 if (PreviousMode
== UserMode
)
122 /* Prepare to probe parameters */
125 /* Probe the key handle */
126 ProbeForWriteHandle(KeyHandle
);
129 /* Probe object attributes */
130 ProbeForRead(ObjectAttributes
, sizeof(OBJECT_ATTRIBUTES
), 4);
135 Status
= _SEH_GetExceptionCode();
138 if(!NT_SUCCESS(Status
)) return Status
;
141 /* Just let the object manager handle this */
142 Status
= ObOpenObjectByName(ObjectAttributes
,
150 if (NT_SUCCESS(Status
))
159 Status
= _SEH_GetExceptionCode();
171 NtDeleteKey(IN HANDLE KeyHandle
)
173 PCM_KEY_BODY KeyObject
;
175 REG_DELETE_KEY_INFORMATION DeleteKeyInfo
;
176 REG_POST_OPERATION_INFORMATION PostOperationInfo
;
178 DPRINT("NtDeleteKey(KH 0x%p)\n", KeyHandle
);
180 /* Verify that the handle is valid and is a registry key */
181 Status
= ObReferenceObjectByHandle(KeyHandle
,
187 if (!NT_SUCCESS(Status
)) return Status
;
189 /* Setup the callback */
190 PostOperationInfo
.Object
= (PVOID
)KeyObject
;
191 DeleteKeyInfo
.Object
= (PVOID
)KeyObject
;
192 Status
= CmiCallRegisteredCallbacks(RegNtPreDeleteKey
, &DeleteKeyInfo
);
193 if (NT_SUCCESS(Status
))
195 /* Check if we are read-only */
196 if ((KeyObject
->KeyControlBlock
->ExtFlags
& CM_KCB_READ_ONLY_KEY
) ||
197 (KeyObject
->KeyControlBlock
->ParentKcb
->ExtFlags
& CM_KCB_READ_ONLY_KEY
))
200 Status
= STATUS_ACCESS_DENIED
;
204 /* Call the internal API */
205 Status
= CmDeleteKey(KeyObject
);
208 /* Do post callback */
209 PostOperationInfo
.Status
= Status
;
210 CmiCallRegisteredCallbacks(RegNtPostDeleteKey
, &PostOperationInfo
);
213 /* Dereference the object */
214 ObDereferenceObject(KeyObject
);
220 NtEnumerateKey(IN HANDLE KeyHandle
,
222 IN KEY_INFORMATION_CLASS KeyInformationClass
,
223 OUT PVOID KeyInformation
,
225 OUT PULONG ResultLength
)
228 PCM_KEY_BODY KeyObject
;
229 REG_ENUMERATE_KEY_INFORMATION EnumerateKeyInfo
;
230 REG_POST_OPERATION_INFORMATION PostOperationInfo
;
232 DPRINT("NtEnumerateKey() KH 0x%x, Index 0x%x, KIC %d, Length %d\n",
233 KeyHandle
, Index
, KeyInformationClass
, Length
);
235 /* Reject classes we don't know about */
236 if ((KeyInformationClass
!= KeyBasicInformation
) &&
237 (KeyInformationClass
!= KeyNodeInformation
) &&
238 (KeyInformationClass
!= KeyFullInformation
))
241 return STATUS_INVALID_PARAMETER
;
244 /* Verify that the handle is valid and is a registry key */
245 Status
= ObReferenceObjectByHandle(KeyHandle
,
246 KEY_ENUMERATE_SUB_KEYS
,
251 if (!NT_SUCCESS(Status
)) return Status
;
253 /* Setup the callback */
254 PostOperationInfo
.Object
= (PVOID
)KeyObject
;
255 EnumerateKeyInfo
.Object
= (PVOID
)KeyObject
;
256 EnumerateKeyInfo
.Index
= Index
;
257 EnumerateKeyInfo
.KeyInformationClass
= KeyInformationClass
;
258 EnumerateKeyInfo
.Length
= Length
;
259 EnumerateKeyInfo
.ResultLength
= ResultLength
;
261 /* Do the callback */
262 Status
= CmiCallRegisteredCallbacks(RegNtPreEnumerateKey
, &EnumerateKeyInfo
);
263 if (NT_SUCCESS(Status
))
265 /* Call the internal API */
266 Status
= CmEnumerateKey(KeyObject
->KeyControlBlock
,
273 /* Do the post callback */
274 PostOperationInfo
.Status
= Status
;
275 CmiCallRegisteredCallbacks(RegNtPostEnumerateKey
, &PostOperationInfo
);
278 /* Dereference and return status */
279 ObDereferenceObject(KeyObject
);
285 NtEnumerateValueKey(IN HANDLE KeyHandle
,
287 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
,
288 OUT PVOID KeyValueInformation
,
290 OUT PULONG ResultLength
)
293 PCM_KEY_BODY KeyObject
;
294 REG_ENUMERATE_VALUE_KEY_INFORMATION EnumerateValueKeyInfo
;
295 REG_POST_OPERATION_INFORMATION PostOperationInfo
;
297 DPRINT("NtEnumerateValueKey() KH 0x%x, Index 0x%x, KVIC %d, Length %d\n",
298 KeyHandle
, Index
, KeyValueInformationClass
, Length
);
300 /* Reject classes we don't know about */
301 if ((KeyValueInformationClass
!= KeyValueBasicInformation
) &&
302 (KeyValueInformationClass
!= KeyValueFullInformation
) &&
303 (KeyValueInformationClass
!= KeyValuePartialInformation
))
306 return STATUS_INVALID_PARAMETER
;
309 /* Verify that the handle is valid and is a registry key */
310 Status
= ObReferenceObjectByHandle(KeyHandle
,
316 if (!NT_SUCCESS(Status
)) return Status
;
318 /* Setup the callback */
319 PostOperationInfo
.Object
= (PVOID
)KeyObject
;
320 EnumerateValueKeyInfo
.Object
= (PVOID
)KeyObject
;
321 EnumerateValueKeyInfo
.Index
= Index
;
322 EnumerateValueKeyInfo
.KeyValueInformationClass
= KeyValueInformationClass
;
323 EnumerateValueKeyInfo
.KeyValueInformation
= KeyValueInformation
;
324 EnumerateValueKeyInfo
.Length
= Length
;
325 EnumerateValueKeyInfo
.ResultLength
= ResultLength
;
327 /* Do the callback */
328 Status
= CmiCallRegisteredCallbacks(RegNtPreEnumerateValueKey
,
329 &EnumerateValueKeyInfo
);
330 if (NT_SUCCESS(Status
))
332 /* Call the internal API */
333 Status
= CmEnumerateValueKey(KeyObject
->KeyControlBlock
,
335 KeyValueInformationClass
,
340 /* Do the post callback */
341 PostOperationInfo
.Status
= Status
;
342 CmiCallRegisteredCallbacks(RegNtPostEnumerateValueKey
, &PostOperationInfo
);
345 ObDereferenceObject(KeyObject
);
351 NtQueryKey(IN HANDLE KeyHandle
,
352 IN KEY_INFORMATION_CLASS KeyInformationClass
,
353 OUT PVOID KeyInformation
,
355 OUT PULONG ResultLength
)
358 PCM_KEY_BODY KeyObject
;
359 REG_QUERY_KEY_INFORMATION QueryKeyInfo
;
360 REG_POST_OPERATION_INFORMATION PostOperationInfo
;
361 OBJECT_HANDLE_INFORMATION HandleInfo
;
363 DPRINT("NtQueryKey() KH 0x%x, KIC %d, Length %d\n",
364 KeyHandle
, KeyInformationClass
, Length
);
366 /* Reject invalid classes */
367 if ((KeyInformationClass
!= KeyBasicInformation
) &&
368 (KeyInformationClass
!= KeyNodeInformation
) &&
369 (KeyInformationClass
!= KeyFullInformation
) &&
370 (KeyInformationClass
!= KeyNameInformation
) &&
371 (KeyInformationClass
!= KeyCachedInformation
) &&
372 (KeyInformationClass
!= KeyFlagsInformation
))
375 return STATUS_INVALID_PARAMETER
;
378 /* Check if just the name is required */
379 if (KeyInformationClass
== KeyNameInformation
)
381 /* Ignore access level */
382 Status
= ObReferenceObjectByHandle(KeyHandle
,
388 if (NT_SUCCESS(Status
))
390 /* At least a single bit of access is required */
391 if (!HandleInfo
.GrantedAccess
)
394 ObDereferenceObject(KeyObject
);
395 Status
= STATUS_ACCESS_DENIED
;
401 /* Get a reference */
402 Status
= ObReferenceObjectByHandle(KeyHandle
,
410 /* Quit on failure */
411 if (!NT_SUCCESS(Status
)) return Status
;
413 /* Setup the callback */
414 PostOperationInfo
.Object
= (PVOID
)KeyObject
;
415 QueryKeyInfo
.Object
= (PVOID
)KeyObject
;
416 QueryKeyInfo
.KeyInformationClass
= KeyInformationClass
;
417 QueryKeyInfo
.KeyInformation
= KeyInformation
;
418 QueryKeyInfo
.Length
= Length
;
419 QueryKeyInfo
.ResultLength
= ResultLength
;
421 /* Do the callback */
422 Status
= CmiCallRegisteredCallbacks(RegNtPreQueryKey
, &QueryKeyInfo
);
423 if (NT_SUCCESS(Status
))
425 /* Call the internal API */
426 Status
= CmQueryKey(KeyObject
->KeyControlBlock
,
432 /* Do the post callback */
433 PostOperationInfo
.Status
= Status
;
434 CmiCallRegisteredCallbacks(RegNtPostQueryKey
, &PostOperationInfo
);
437 /* Dereference and return status */
438 ObDereferenceObject(KeyObject
);
444 NtQueryValueKey(IN HANDLE KeyHandle
,
445 IN PUNICODE_STRING ValueName
,
446 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
,
447 OUT PVOID KeyValueInformation
,
449 OUT PULONG ResultLength
)
452 PCM_KEY_BODY KeyObject
;
453 REG_QUERY_VALUE_KEY_INFORMATION QueryValueKeyInfo
;
454 REG_POST_OPERATION_INFORMATION PostOperationInfo
;
455 UNICODE_STRING ValueNameCopy
= *ValueName
;
457 DPRINT("NtQueryValueKey() KH 0x%x, VN '%wZ', KVIC %d, Length %d\n",
458 KeyHandle
, ValueName
, KeyValueInformationClass
, Length
);
460 /* Verify that the handle is valid and is a registry key */
461 Status
= ObReferenceObjectByHandle(KeyHandle
,
467 if (!NT_SUCCESS(Status
)) return Status
;
469 /* Make sure the name is aligned properly */
470 if ((ValueNameCopy
.Length
& (sizeof(WCHAR
) - 1)))
472 /* It isn't, so we'll fail */
473 ObDereferenceObject(KeyObject
);
474 return STATUS_INVALID_PARAMETER
;
478 /* Ignore any null characters at the end */
479 while ((ValueNameCopy
.Length
) &&
480 !(ValueNameCopy
.Buffer
[ValueNameCopy
.Length
/ sizeof(WCHAR
) - 1]))
483 ValueNameCopy
.Length
-= sizeof(WCHAR
);
487 /* Setup the callback */
488 PostOperationInfo
.Object
= (PVOID
)KeyObject
;
489 QueryValueKeyInfo
.Object
= (PVOID
)KeyObject
;
490 QueryValueKeyInfo
.ValueName
= &ValueNameCopy
;
491 QueryValueKeyInfo
.KeyValueInformationClass
= KeyValueInformationClass
;
492 QueryValueKeyInfo
.Length
= Length
;
493 QueryValueKeyInfo
.ResultLength
= ResultLength
;
495 /* Do the callback */
496 Status
= CmiCallRegisteredCallbacks(RegNtPreQueryValueKey
, &QueryValueKeyInfo
);
497 if (NT_SUCCESS(Status
))
499 /* Call the internal API */
500 Status
= CmQueryValueKey(KeyObject
->KeyControlBlock
,
502 KeyValueInformationClass
,
507 /* Do the post callback */
508 PostOperationInfo
.Status
= Status
;
509 CmiCallRegisteredCallbacks(RegNtPostQueryValueKey
, &PostOperationInfo
);
512 /* Dereference and return status */
513 ObDereferenceObject(KeyObject
);
519 NtSetValueKey(IN HANDLE KeyHandle
,
520 IN PUNICODE_STRING ValueName
,
527 PCM_KEY_BODY KeyObject
;
528 REG_SET_VALUE_KEY_INFORMATION SetValueKeyInfo
;
529 REG_POST_OPERATION_INFORMATION PostOperationInfo
;
530 UNICODE_STRING ValueNameCopy
= *ValueName
;
532 DPRINT("NtSetValueKey() KH 0x%x, VN '%wZ', TI %x, T %d, DS %d\n",
533 KeyHandle
, ValueName
, TitleIndex
, Type
, DataSize
);
535 /* Verify that the handle is valid and is a registry key */
536 Status
= ObReferenceObjectByHandle(KeyHandle
,
542 if (!NT_SUCCESS(Status
)) return Status
;
544 /* Make sure the name is aligned, not too long, and the data under 4GB */
545 if ( (ValueNameCopy
.Length
> 32767) ||
546 ((ValueNameCopy
.Length
& (sizeof(WCHAR
) - 1))) ||
547 (DataSize
> 0x80000000))
550 ObDereferenceObject(KeyObject
);
551 return STATUS_INVALID_PARAMETER
;
554 /* Ignore any null characters at the end */
555 while ((ValueNameCopy
.Length
) &&
556 !(ValueNameCopy
.Buffer
[ValueNameCopy
.Length
/ sizeof(WCHAR
) - 1]))
559 ValueNameCopy
.Length
-= sizeof(WCHAR
);
562 /* Don't touch read-only keys */
563 if (KeyObject
->KeyControlBlock
->ExtFlags
& CM_KCB_READ_ONLY_KEY
)
566 ObDereferenceObject(KeyObject
);
567 return STATUS_ACCESS_DENIED
;
571 PostOperationInfo
.Object
= (PVOID
)KeyObject
;
572 SetValueKeyInfo
.Object
= (PVOID
)KeyObject
;
573 SetValueKeyInfo
.ValueName
= ValueName
;
574 SetValueKeyInfo
.TitleIndex
= TitleIndex
;
575 SetValueKeyInfo
.Type
= Type
;
576 SetValueKeyInfo
.Data
= Data
;
577 SetValueKeyInfo
.DataSize
= DataSize
;
579 /* Do the callback */
580 Status
= CmiCallRegisteredCallbacks(RegNtPreSetValueKey
, &SetValueKeyInfo
);
581 if (NT_SUCCESS(Status
))
583 /* Call the internal API */
584 Status
= CmSetValueKey(KeyObject
->KeyControlBlock
,
591 /* Do the post-callback */
592 PostOperationInfo
.Status
= Status
;
593 CmiCallRegisteredCallbacks(RegNtPostSetValueKey
, &PostOperationInfo
);
595 /* Dereference and return status */
596 ObDereferenceObject(KeyObject
);
602 NtDeleteValueKey(IN HANDLE KeyHandle
,
603 IN PUNICODE_STRING ValueName
)
605 PCM_KEY_BODY KeyObject
;
607 REG_DELETE_VALUE_KEY_INFORMATION DeleteValueKeyInfo
;
608 REG_POST_OPERATION_INFORMATION PostOperationInfo
;
609 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
610 UNICODE_STRING ValueNameCopy
= *ValueName
;
613 /* Verify that the handle is valid and is a registry key */
614 Status
= ObReferenceObjectByHandle(KeyHandle
,
620 if (!NT_SUCCESS(Status
)) return Status
;
622 /* Don't touch read-only keys */
623 if (KeyObject
->KeyControlBlock
->ExtFlags
& CM_KCB_READ_ONLY_KEY
)
626 ObDereferenceObject(KeyObject
);
627 return STATUS_ACCESS_DENIED
;
630 /* Make sure the name is aligned properly */
631 if ((ValueNameCopy
.Length
& (sizeof(WCHAR
) - 1)))
633 /* It isn't, so we'll fail */
634 ObDereferenceObject(KeyObject
);
635 return STATUS_INVALID_PARAMETER
;
638 /* Do the callback */
639 DeleteValueKeyInfo
.Object
= (PVOID
)KeyObject
;
640 DeleteValueKeyInfo
.ValueName
= ValueName
;
641 Status
= CmiCallRegisteredCallbacks(RegNtPreDeleteValueKey
,
642 &DeleteValueKeyInfo
);
643 if (NT_SUCCESS(Status
))
645 /* Call the internal API */
646 Status
= CmDeleteValueKey(KeyObject
->KeyControlBlock
, ValueNameCopy
);
648 /* Do the post callback */
649 PostOperationInfo
.Object
= (PVOID
)KeyObject
;
650 PostOperationInfo
.Status
= Status
;
651 CmiCallRegisteredCallbacks(RegNtPostDeleteValueKey
,
655 /* Dereference the key body */
656 ObDereferenceObject(KeyObject
);
662 NtFlushKey(IN HANDLE KeyHandle
)
665 PCM_KEY_BODY KeyObject
;
668 /* Get the key object */
669 Status
= ObReferenceObjectByHandle(KeyHandle
,
675 if (!NT_SUCCESS(Status
)) return Status
;
677 /* Lock the registry */
681 CmpAcquireKcbLockShared(KeyObject
->KeyControlBlock
);
683 /* Make sure KCB isn't deleted */
684 if (KeyObject
->KeyControlBlock
->Delete
)
687 Status
= STATUS_KEY_DELETED
;
691 /* Call the internal API */
692 Status
= CmFlushKey(KeyObject
->KeyControlBlock
, FALSE
);
695 /* Release the locks */
696 CmpReleaseKcbLock(KeyObject
->KeyControlBlock
);
699 /* Dereference the object and return status */
700 ObDereferenceObject(KeyObject
);
706 NtLoadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
707 IN POBJECT_ATTRIBUTES FileObjectAttributes
)
709 /* Call the newer API */
710 return NtLoadKeyEx(KeyObjectAttributes
, FileObjectAttributes
, 0, NULL
);
715 NtLoadKey2(IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
716 IN POBJECT_ATTRIBUTES FileObjectAttributes
,
719 /* Call the newer API */
720 return NtLoadKeyEx(KeyObjectAttributes
, FileObjectAttributes
, Flags
, NULL
);
725 NtLoadKeyEx(IN POBJECT_ATTRIBUTES TargetKey
,
726 IN POBJECT_ATTRIBUTES SourceFile
,
728 IN HANDLE TrustClassKey
)
731 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
732 PCM_KEY_BODY KeyBody
= NULL
;
736 if (Flags
& ~REG_NO_LAZY_FLUSH
) return STATUS_INVALID_PARAMETER
;
738 /* Validate privilege */
739 if (!SeSinglePrivilegeCheck(SeRestorePrivilege
, PreviousMode
))
742 DPRINT1("Restore Privilege missing!\n");
743 return STATUS_PRIVILEGE_NOT_HELD
;
747 KeEnterCriticalRegion();
749 /* Check if we have a trust class */
753 Status
= ObReferenceObjectByHandle(TrustClassKey
,
761 /* Call the internal API */
762 Status
= CmLoadKey(TargetKey
, SourceFile
, Flags
, KeyBody
);
764 /* Dereference the trust key, if any */
765 if (KeyBody
) ObDereferenceObject(KeyBody
);
767 /* Bring back APCs */
768 KeLeaveCriticalRegion();
776 NtNotifyChangeKey(IN HANDLE KeyHandle
,
778 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
779 IN PVOID ApcContext OPTIONAL
,
780 OUT PIO_STATUS_BLOCK IoStatusBlock
,
781 IN ULONG CompletionFilter
,
782 IN BOOLEAN WatchTree
,
785 IN BOOLEAN Asynchronous
)
787 /* Call the newer API */
788 return NtNotifyChangeMultipleKeys(KeyHandle
,
804 NtInitializeRegistry(IN USHORT Flag
)
807 NTSTATUS Status
= STATUS_SUCCESS
;
810 /* Always do this as kernel mode */
811 if (KeGetPreviousMode() == UserMode
) return ZwInitializeRegistry(Flag
);
814 if (Flag
> CM_BOOT_FLAG_MAX
) return STATUS_INVALID_PARAMETER
;
816 /* Check if boot was accepted */
817 if ((Flag
>= CM_BOOT_FLAG_ACCEPTED
) && (Flag
<= CM_BOOT_FLAG_MAX
))
819 /* Only allow once */
820 if (!CmBootAcceptFirstTime
) return STATUS_ACCESS_DENIED
;
821 CmBootAcceptFirstTime
= FALSE
;
823 /* Get the control set accepted */
824 Flag
-= CM_BOOT_FLAG_ACCEPTED
;
827 /* FIXME: Save the last known good boot */
828 //Status = CmpSaveBootControlSet(Flag);
833 /* Enable lazy flush */
834 CmpHoldLazyFlush
= FALSE
;
839 /* Otherwise, invalid boot */
840 return STATUS_INVALID_PARAMETER
;
843 /* Check if this was a setup boot */
844 SetupBoot
= (Flag
== CM_BOOT_FLAG_SETUP
? TRUE
: FALSE
);
846 /* Make sure we're only called once */
847 if (!CmFirstTime
) return STATUS_ACCESS_DENIED
;
850 /* Acquire registry lock */
851 //CmpLockRegistryExclusive();
853 /* Initialize the hives and lazy flusher */
854 CmpCmdInit(SetupBoot
);
856 /* FIXME: Save version data */
857 //CmpSetVersionData();
859 /* Release the registry lock */
860 //CmpUnlockRegistry();
861 return STATUS_SUCCESS
;
866 NtCompactKeys(IN ULONG Count
,
870 return STATUS_NOT_IMPLEMENTED
;
875 NtCompressKey(IN HANDLE Key
)
878 return STATUS_NOT_IMPLEMENTED
;
883 NtLockProductActivationKeys(IN PULONG pPrivateVer
,
887 return STATUS_NOT_IMPLEMENTED
;
892 NtLockRegistryKey(IN HANDLE KeyHandle
)
895 return STATUS_NOT_IMPLEMENTED
;
900 NtNotifyChangeMultipleKeys(IN HANDLE MasterKeyHandle
,
902 IN POBJECT_ATTRIBUTES SlaveObjects
,
904 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
905 IN PVOID ApcContext OPTIONAL
,
906 OUT PIO_STATUS_BLOCK IoStatusBlock
,
907 IN ULONG CompletionFilter
,
908 IN BOOLEAN WatchTree
,
911 IN BOOLEAN Asynchronous
)
914 return STATUS_NOT_IMPLEMENTED
;
919 NtQueryMultipleValueKey(IN HANDLE KeyHandle
,
920 IN OUT PKEY_VALUE_ENTRY ValueList
,
921 IN ULONG NumberOfValues
,
923 IN OUT PULONG Length
,
924 OUT PULONG ReturnLength
)
927 return STATUS_NOT_IMPLEMENTED
;
932 NtQueryOpenSubKeys(IN POBJECT_ATTRIBUTES TargetKey
,
933 OUT PULONG HandleCount
)
936 return STATUS_NOT_IMPLEMENTED
;
941 NtQueryOpenSubKeysEx(IN POBJECT_ATTRIBUTES TargetKey
,
942 IN ULONG BufferLength
,
944 IN PULONG RequiredSize
)
947 return STATUS_NOT_IMPLEMENTED
;
952 NtRenameKey(IN HANDLE KeyHandle
,
953 IN PUNICODE_STRING ReplacementName
)
956 return STATUS_NOT_IMPLEMENTED
;
961 NtReplaceKey(IN POBJECT_ATTRIBUTES ObjectAttributes
,
963 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes
)
966 return STATUS_NOT_IMPLEMENTED
;
971 NtRestoreKey(IN HANDLE KeyHandle
,
972 IN HANDLE FileHandle
,
973 IN ULONG RestoreFlags
)
976 return STATUS_NOT_IMPLEMENTED
;
981 NtSaveKey(IN HANDLE KeyHandle
,
982 IN HANDLE FileHandle
)
985 return STATUS_NOT_IMPLEMENTED
;
990 NtSaveKeyEx(IN HANDLE KeyHandle
,
991 IN HANDLE FileHandle
,
995 return STATUS_NOT_IMPLEMENTED
;
1000 NtSaveMergedKeys(IN HANDLE HighPrecedenceKeyHandle
,
1001 IN HANDLE LowPrecedenceKeyHandle
,
1002 IN HANDLE FileHandle
)
1005 return STATUS_NOT_IMPLEMENTED
;
1010 NtSetInformationKey(IN HANDLE KeyHandle
,
1011 IN KEY_SET_INFORMATION_CLASS KeyInformationClass
,
1012 IN PVOID KeyInformation
,
1013 IN ULONG KeyInformationLength
)
1016 return STATUS_NOT_IMPLEMENTED
;
1021 NtUnloadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes
)
1024 return STATUS_NOT_IMPLEMENTED
;
1029 NtUnloadKey2(IN POBJECT_ATTRIBUTES TargetKey
,
1033 return STATUS_NOT_IMPLEMENTED
;
1038 NtUnloadKeyEx(IN POBJECT_ATTRIBUTES TargetKey
,
1042 return STATUS_NOT_IMPLEMENTED
;