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
!= KernelMode
)
40 /* Prepare to probe parameters */
43 /* Check if we have a class */
47 ParseContext
.Class
= ProbeForReadUnicodeString(Class
);
48 ProbeForRead(ParseContext
.Class
.Buffer
,
49 ParseContext
.Class
.Length
,
53 /* Probe the key handle */
54 ProbeForWriteHandle(KeyHandle
);
57 /* Probe object attributes */
58 ProbeForRead(ObjectAttributes
,
59 sizeof(OBJECT_ATTRIBUTES
),
62 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
64 /* Get the error code */
65 Status
= _SEH2_GetExceptionCode();
68 if(!NT_SUCCESS(Status
)) return Status
;
72 /* Save the class directly */
73 if (Class
) ParseContext
.Class
= *Class
;
76 /* Setup the parse context */
77 ParseContext
.CreateOperation
= TRUE
;
78 ParseContext
.CreateOptions
= CreateOptions
;
81 Status
= ObOpenObjectByName(ObjectAttributes
,
91 /* Return data to user */
92 if (NT_SUCCESS(Status
)) *KeyHandle
= Handle
;
93 if (Disposition
) *Disposition
= ParseContext
.Disposition
;
95 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
98 Status
= _SEH2_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
!= KernelMode
)
122 /* Prepare to probe parameters */
125 /* Probe the key handle */
126 ProbeForWriteHandle(KeyHandle
);
129 /* Probe object attributes */
130 ProbeForRead(ObjectAttributes
,
131 sizeof(OBJECT_ATTRIBUTES
),
134 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
137 Status
= _SEH2_GetExceptionCode();
140 if(!NT_SUCCESS(Status
)) return Status
;
143 /* Just let the object manager handle this */
144 Status
= ObOpenObjectByName(ObjectAttributes
,
152 /* Only do this if we succeeded */
153 if (NT_SUCCESS(Status
))
157 /* Return the handle to caller */
160 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
163 Status
= _SEH2_GetExceptionCode();
175 NtDeleteKey(IN HANDLE KeyHandle
)
177 PCM_KEY_BODY KeyObject
;
179 REG_DELETE_KEY_INFORMATION DeleteKeyInfo
;
180 REG_POST_OPERATION_INFORMATION PostOperationInfo
;
182 DPRINT("NtDeleteKey(KH 0x%p)\n", KeyHandle
);
184 /* Verify that the handle is valid and is a registry key */
185 Status
= ObReferenceObjectByHandle(KeyHandle
,
191 if (!NT_SUCCESS(Status
)) return Status
;
193 /* Setup the callback */
194 PostOperationInfo
.Object
= (PVOID
)KeyObject
;
195 DeleteKeyInfo
.Object
= (PVOID
)KeyObject
;
196 Status
= CmiCallRegisteredCallbacks(RegNtPreDeleteKey
, &DeleteKeyInfo
);
197 if (NT_SUCCESS(Status
))
199 /* Check if we are read-only */
200 if ((KeyObject
->KeyControlBlock
->ExtFlags
& CM_KCB_READ_ONLY_KEY
) ||
201 (KeyObject
->KeyControlBlock
->ParentKcb
->ExtFlags
& CM_KCB_READ_ONLY_KEY
))
204 Status
= STATUS_ACCESS_DENIED
;
208 /* Call the internal API */
209 Status
= CmDeleteKey(KeyObject
);
212 /* Do post callback */
213 PostOperationInfo
.Status
= Status
;
214 CmiCallRegisteredCallbacks(RegNtPostDeleteKey
, &PostOperationInfo
);
217 /* Dereference the object */
218 ObDereferenceObject(KeyObject
);
224 NtEnumerateKey(IN HANDLE KeyHandle
,
226 IN KEY_INFORMATION_CLASS KeyInformationClass
,
227 OUT PVOID KeyInformation
,
229 OUT PULONG ResultLength
)
232 PCM_KEY_BODY KeyObject
;
233 REG_ENUMERATE_KEY_INFORMATION EnumerateKeyInfo
;
234 REG_POST_OPERATION_INFORMATION PostOperationInfo
;
236 DPRINT("NtEnumerateKey() KH 0x%x, Index 0x%x, KIC %d, Length %d\n",
237 KeyHandle
, Index
, KeyInformationClass
, Length
);
239 /* Reject classes we don't know about */
240 if ((KeyInformationClass
!= KeyBasicInformation
) &&
241 (KeyInformationClass
!= KeyNodeInformation
) &&
242 (KeyInformationClass
!= KeyFullInformation
))
245 return STATUS_INVALID_PARAMETER
;
248 /* Verify that the handle is valid and is a registry key */
249 Status
= ObReferenceObjectByHandle(KeyHandle
,
250 KEY_ENUMERATE_SUB_KEYS
,
255 if (!NT_SUCCESS(Status
)) return Status
;
257 /* Setup the callback */
258 PostOperationInfo
.Object
= (PVOID
)KeyObject
;
259 EnumerateKeyInfo
.Object
= (PVOID
)KeyObject
;
260 EnumerateKeyInfo
.Index
= Index
;
261 EnumerateKeyInfo
.KeyInformationClass
= KeyInformationClass
;
262 EnumerateKeyInfo
.Length
= Length
;
263 EnumerateKeyInfo
.ResultLength
= ResultLength
;
265 /* Do the callback */
266 Status
= CmiCallRegisteredCallbacks(RegNtPreEnumerateKey
, &EnumerateKeyInfo
);
267 if (NT_SUCCESS(Status
))
269 /* Call the internal API */
270 Status
= CmEnumerateKey(KeyObject
->KeyControlBlock
,
277 /* Do the post callback */
278 PostOperationInfo
.Status
= Status
;
279 CmiCallRegisteredCallbacks(RegNtPostEnumerateKey
, &PostOperationInfo
);
282 /* Dereference and return status */
283 ObDereferenceObject(KeyObject
);
289 NtEnumerateValueKey(IN HANDLE KeyHandle
,
291 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
,
292 OUT PVOID KeyValueInformation
,
294 OUT PULONG ResultLength
)
297 PCM_KEY_BODY KeyObject
;
298 REG_ENUMERATE_VALUE_KEY_INFORMATION EnumerateValueKeyInfo
;
299 REG_POST_OPERATION_INFORMATION PostOperationInfo
;
301 DPRINT("NtEnumerateValueKey() KH 0x%x, Index 0x%x, KVIC %d, Length %d\n",
302 KeyHandle
, Index
, KeyValueInformationClass
, Length
);
304 /* Reject classes we don't know about */
305 if ((KeyValueInformationClass
!= KeyValueBasicInformation
) &&
306 (KeyValueInformationClass
!= KeyValueFullInformation
) &&
307 (KeyValueInformationClass
!= KeyValuePartialInformation
))
310 return STATUS_INVALID_PARAMETER
;
313 /* Verify that the handle is valid and is a registry key */
314 Status
= ObReferenceObjectByHandle(KeyHandle
,
320 if (!NT_SUCCESS(Status
)) return Status
;
322 /* Setup the callback */
323 PostOperationInfo
.Object
= (PVOID
)KeyObject
;
324 EnumerateValueKeyInfo
.Object
= (PVOID
)KeyObject
;
325 EnumerateValueKeyInfo
.Index
= Index
;
326 EnumerateValueKeyInfo
.KeyValueInformationClass
= KeyValueInformationClass
;
327 EnumerateValueKeyInfo
.KeyValueInformation
= KeyValueInformation
;
328 EnumerateValueKeyInfo
.Length
= Length
;
329 EnumerateValueKeyInfo
.ResultLength
= ResultLength
;
331 /* Do the callback */
332 Status
= CmiCallRegisteredCallbacks(RegNtPreEnumerateValueKey
,
333 &EnumerateValueKeyInfo
);
334 if (NT_SUCCESS(Status
))
336 /* Call the internal API */
337 Status
= CmEnumerateValueKey(KeyObject
->KeyControlBlock
,
339 KeyValueInformationClass
,
344 /* Do the post callback */
345 PostOperationInfo
.Status
= Status
;
346 CmiCallRegisteredCallbacks(RegNtPostEnumerateValueKey
, &PostOperationInfo
);
349 ObDereferenceObject(KeyObject
);
355 NtQueryKey(IN HANDLE KeyHandle
,
356 IN KEY_INFORMATION_CLASS KeyInformationClass
,
357 OUT PVOID KeyInformation
,
359 OUT PULONG ResultLength
)
362 PCM_KEY_BODY KeyObject
;
363 REG_QUERY_KEY_INFORMATION QueryKeyInfo
;
364 REG_POST_OPERATION_INFORMATION PostOperationInfo
;
365 OBJECT_HANDLE_INFORMATION HandleInfo
;
367 DPRINT("NtQueryKey() KH 0x%x, KIC %d, Length %d\n",
368 KeyHandle
, KeyInformationClass
, Length
);
370 /* Reject invalid classes */
371 if ((KeyInformationClass
!= KeyBasicInformation
) &&
372 (KeyInformationClass
!= KeyNodeInformation
) &&
373 (KeyInformationClass
!= KeyFullInformation
) &&
374 (KeyInformationClass
!= KeyNameInformation
) &&
375 (KeyInformationClass
!= KeyCachedInformation
) &&
376 (KeyInformationClass
!= KeyFlagsInformation
))
379 return STATUS_INVALID_PARAMETER
;
382 /* Check if just the name is required */
383 if (KeyInformationClass
== KeyNameInformation
)
385 /* Ignore access level */
386 Status
= ObReferenceObjectByHandle(KeyHandle
,
392 if (NT_SUCCESS(Status
))
394 /* At least a single bit of access is required */
395 if (!HandleInfo
.GrantedAccess
)
398 ObDereferenceObject(KeyObject
);
399 Status
= STATUS_ACCESS_DENIED
;
405 /* Get a reference */
406 Status
= ObReferenceObjectByHandle(KeyHandle
,
414 /* Quit on failure */
415 if (!NT_SUCCESS(Status
)) return Status
;
417 /* Setup the callback */
418 PostOperationInfo
.Object
= (PVOID
)KeyObject
;
419 QueryKeyInfo
.Object
= (PVOID
)KeyObject
;
420 QueryKeyInfo
.KeyInformationClass
= KeyInformationClass
;
421 QueryKeyInfo
.KeyInformation
= KeyInformation
;
422 QueryKeyInfo
.Length
= Length
;
423 QueryKeyInfo
.ResultLength
= ResultLength
;
425 /* Do the callback */
426 Status
= CmiCallRegisteredCallbacks(RegNtPreQueryKey
, &QueryKeyInfo
);
427 if (NT_SUCCESS(Status
))
429 /* Call the internal API */
430 Status
= CmQueryKey(KeyObject
->KeyControlBlock
,
436 /* Do the post callback */
437 PostOperationInfo
.Status
= Status
;
438 CmiCallRegisteredCallbacks(RegNtPostQueryKey
, &PostOperationInfo
);
441 /* Dereference and return status */
442 ObDereferenceObject(KeyObject
);
448 NtQueryValueKey(IN HANDLE KeyHandle
,
449 IN PUNICODE_STRING ValueName
,
450 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
,
451 OUT PVOID KeyValueInformation
,
453 OUT PULONG ResultLength
)
456 PCM_KEY_BODY KeyObject
;
457 REG_QUERY_VALUE_KEY_INFORMATION QueryValueKeyInfo
;
458 REG_POST_OPERATION_INFORMATION PostOperationInfo
;
459 UNICODE_STRING ValueNameCopy
= *ValueName
;
461 DPRINT("NtQueryValueKey() KH 0x%x, VN '%wZ', KVIC %d, Length %d\n",
462 KeyHandle
, ValueName
, KeyValueInformationClass
, Length
);
464 /* Verify that the handle is valid and is a registry key */
465 Status
= ObReferenceObjectByHandle(KeyHandle
,
471 if (!NT_SUCCESS(Status
)) return Status
;
473 /* Make sure the name is aligned properly */
474 if ((ValueNameCopy
.Length
& (sizeof(WCHAR
) - 1)))
476 /* It isn't, so we'll fail */
477 ObDereferenceObject(KeyObject
);
478 return STATUS_INVALID_PARAMETER
;
482 /* Ignore any null characters at the end */
483 while ((ValueNameCopy
.Length
) &&
484 !(ValueNameCopy
.Buffer
[ValueNameCopy
.Length
/ sizeof(WCHAR
) - 1]))
487 ValueNameCopy
.Length
-= sizeof(WCHAR
);
491 /* Setup the callback */
492 PostOperationInfo
.Object
= (PVOID
)KeyObject
;
493 QueryValueKeyInfo
.Object
= (PVOID
)KeyObject
;
494 QueryValueKeyInfo
.ValueName
= &ValueNameCopy
;
495 QueryValueKeyInfo
.KeyValueInformationClass
= KeyValueInformationClass
;
496 QueryValueKeyInfo
.Length
= Length
;
497 QueryValueKeyInfo
.ResultLength
= ResultLength
;
499 /* Do the callback */
500 Status
= CmiCallRegisteredCallbacks(RegNtPreQueryValueKey
, &QueryValueKeyInfo
);
501 if (NT_SUCCESS(Status
))
503 /* Call the internal API */
504 Status
= CmQueryValueKey(KeyObject
->KeyControlBlock
,
506 KeyValueInformationClass
,
511 /* Do the post callback */
512 PostOperationInfo
.Status
= Status
;
513 CmiCallRegisteredCallbacks(RegNtPostQueryValueKey
, &PostOperationInfo
);
516 /* Dereference and return status */
517 ObDereferenceObject(KeyObject
);
523 NtSetValueKey(IN HANDLE KeyHandle
,
524 IN PUNICODE_STRING ValueName
,
531 PCM_KEY_BODY KeyObject
;
532 REG_SET_VALUE_KEY_INFORMATION SetValueKeyInfo
;
533 REG_POST_OPERATION_INFORMATION PostOperationInfo
;
534 UNICODE_STRING ValueNameCopy
= *ValueName
;
536 DPRINT("NtSetValueKey() KH 0x%x, VN '%wZ', TI %x, T %d, DS %d\n",
537 KeyHandle
, ValueName
, TitleIndex
, Type
, DataSize
);
539 /* Verify that the handle is valid and is a registry key */
540 Status
= ObReferenceObjectByHandle(KeyHandle
,
546 if (!NT_SUCCESS(Status
)) return Status
;
548 /* Make sure the name is aligned, not too long, and the data under 4GB */
549 if ( (ValueNameCopy
.Length
> 32767) ||
550 ((ValueNameCopy
.Length
& (sizeof(WCHAR
) - 1))) ||
551 (DataSize
> 0x80000000))
554 ObDereferenceObject(KeyObject
);
555 return STATUS_INVALID_PARAMETER
;
558 /* Ignore any null characters at the end */
559 while ((ValueNameCopy
.Length
) &&
560 !(ValueNameCopy
.Buffer
[ValueNameCopy
.Length
/ sizeof(WCHAR
) - 1]))
563 ValueNameCopy
.Length
-= sizeof(WCHAR
);
566 /* Don't touch read-only keys */
567 if (KeyObject
->KeyControlBlock
->ExtFlags
& CM_KCB_READ_ONLY_KEY
)
570 ObDereferenceObject(KeyObject
);
571 return STATUS_ACCESS_DENIED
;
575 PostOperationInfo
.Object
= (PVOID
)KeyObject
;
576 SetValueKeyInfo
.Object
= (PVOID
)KeyObject
;
577 SetValueKeyInfo
.ValueName
= ValueName
;
578 SetValueKeyInfo
.TitleIndex
= TitleIndex
;
579 SetValueKeyInfo
.Type
= Type
;
580 SetValueKeyInfo
.Data
= Data
;
581 SetValueKeyInfo
.DataSize
= DataSize
;
583 /* Do the callback */
584 Status
= CmiCallRegisteredCallbacks(RegNtPreSetValueKey
, &SetValueKeyInfo
);
585 if (NT_SUCCESS(Status
))
587 /* Call the internal API */
588 Status
= CmSetValueKey(KeyObject
->KeyControlBlock
,
595 /* Do the post-callback */
596 PostOperationInfo
.Status
= Status
;
597 CmiCallRegisteredCallbacks(RegNtPostSetValueKey
, &PostOperationInfo
);
599 /* Dereference and return status */
600 ObDereferenceObject(KeyObject
);
606 NtDeleteValueKey(IN HANDLE KeyHandle
,
607 IN PUNICODE_STRING ValueName
)
609 PCM_KEY_BODY KeyObject
;
611 REG_DELETE_VALUE_KEY_INFORMATION DeleteValueKeyInfo
;
612 REG_POST_OPERATION_INFORMATION PostOperationInfo
;
613 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
614 UNICODE_STRING ValueNameCopy
= *ValueName
;
617 /* Verify that the handle is valid and is a registry key */
618 Status
= ObReferenceObjectByHandle(KeyHandle
,
624 if (!NT_SUCCESS(Status
)) return Status
;
626 /* Don't touch read-only keys */
627 if (KeyObject
->KeyControlBlock
->ExtFlags
& CM_KCB_READ_ONLY_KEY
)
630 ObDereferenceObject(KeyObject
);
631 return STATUS_ACCESS_DENIED
;
634 /* Make sure the name is aligned properly */
635 if ((ValueNameCopy
.Length
& (sizeof(WCHAR
) - 1)))
637 /* It isn't, so we'll fail */
638 ObDereferenceObject(KeyObject
);
639 return STATUS_INVALID_PARAMETER
;
642 /* Do the callback */
643 DeleteValueKeyInfo
.Object
= (PVOID
)KeyObject
;
644 DeleteValueKeyInfo
.ValueName
= ValueName
;
645 Status
= CmiCallRegisteredCallbacks(RegNtPreDeleteValueKey
,
646 &DeleteValueKeyInfo
);
647 if (NT_SUCCESS(Status
))
649 /* Call the internal API */
650 Status
= CmDeleteValueKey(KeyObject
->KeyControlBlock
, ValueNameCopy
);
652 /* Do the post callback */
653 PostOperationInfo
.Object
= (PVOID
)KeyObject
;
654 PostOperationInfo
.Status
= Status
;
655 CmiCallRegisteredCallbacks(RegNtPostDeleteValueKey
,
659 /* Dereference the key body */
660 ObDereferenceObject(KeyObject
);
666 NtFlushKey(IN HANDLE KeyHandle
)
669 PCM_KEY_BODY KeyObject
;
672 /* Get the key object */
673 Status
= ObReferenceObjectByHandle(KeyHandle
,
679 if (!NT_SUCCESS(Status
)) return Status
;
681 /* Lock the registry */
685 CmpAcquireKcbLockShared(KeyObject
->KeyControlBlock
);
687 /* Make sure KCB isn't deleted */
688 if (KeyObject
->KeyControlBlock
->Delete
)
691 Status
= STATUS_KEY_DELETED
;
695 /* Call the internal API */
696 Status
= CmFlushKey(KeyObject
->KeyControlBlock
, FALSE
);
699 /* Release the locks */
700 CmpReleaseKcbLock(KeyObject
->KeyControlBlock
);
703 /* Dereference the object and return status */
704 ObDereferenceObject(KeyObject
);
710 NtLoadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
711 IN POBJECT_ATTRIBUTES FileObjectAttributes
)
713 /* Call the newer API */
714 return NtLoadKeyEx(KeyObjectAttributes
, FileObjectAttributes
, 0, NULL
);
719 NtLoadKey2(IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
720 IN POBJECT_ATTRIBUTES FileObjectAttributes
,
723 /* Call the newer API */
724 return NtLoadKeyEx(KeyObjectAttributes
, FileObjectAttributes
, Flags
, NULL
);
729 NtLoadKeyEx(IN POBJECT_ATTRIBUTES TargetKey
,
730 IN POBJECT_ATTRIBUTES SourceFile
,
732 IN HANDLE TrustClassKey
)
735 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
736 PCM_KEY_BODY KeyBody
= NULL
;
740 if (Flags
& ~REG_NO_LAZY_FLUSH
) return STATUS_INVALID_PARAMETER
;
742 /* Validate privilege */
743 if (!SeSinglePrivilegeCheck(SeRestorePrivilege
, PreviousMode
))
746 DPRINT1("Restore Privilege missing!\n");
747 return STATUS_PRIVILEGE_NOT_HELD
;
751 KeEnterCriticalRegion();
753 /* Check if we have a trust class */
757 Status
= ObReferenceObjectByHandle(TrustClassKey
,
765 /* Call the internal API */
766 Status
= CmLoadKey(TargetKey
, SourceFile
, Flags
, KeyBody
);
768 /* Dereference the trust key, if any */
769 if (KeyBody
) ObDereferenceObject(KeyBody
);
771 /* Bring back APCs */
772 KeLeaveCriticalRegion();
780 NtNotifyChangeKey(IN HANDLE KeyHandle
,
782 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
783 IN PVOID ApcContext OPTIONAL
,
784 OUT PIO_STATUS_BLOCK IoStatusBlock
,
785 IN ULONG CompletionFilter
,
786 IN BOOLEAN WatchTree
,
789 IN BOOLEAN Asynchronous
)
791 /* Call the newer API */
792 return NtNotifyChangeMultipleKeys(KeyHandle
,
808 NtInitializeRegistry(IN USHORT Flag
)
811 NTSTATUS Status
= STATUS_SUCCESS
;
814 /* Always do this as kernel mode */
815 if (KeGetPreviousMode() == UserMode
) return ZwInitializeRegistry(Flag
);
818 if (Flag
> CM_BOOT_FLAG_MAX
) return STATUS_INVALID_PARAMETER
;
820 /* Check if boot was accepted */
821 if ((Flag
>= CM_BOOT_FLAG_ACCEPTED
) && (Flag
<= CM_BOOT_FLAG_MAX
))
823 /* Only allow once */
824 if (!CmBootAcceptFirstTime
) return STATUS_ACCESS_DENIED
;
825 CmBootAcceptFirstTime
= FALSE
;
827 /* Get the control set accepted */
828 Flag
-= CM_BOOT_FLAG_ACCEPTED
;
831 /* FIXME: Save the last known good boot */
832 //Status = CmpSaveBootControlSet(Flag);
837 /* Enable lazy flush */
838 CmpHoldLazyFlush
= FALSE
;
843 /* Otherwise, invalid boot */
844 return STATUS_INVALID_PARAMETER
;
847 /* Check if this was a setup boot */
848 SetupBoot
= (Flag
== CM_BOOT_FLAG_SETUP
? TRUE
: FALSE
);
850 /* Make sure we're only called once */
851 if (!CmFirstTime
) return STATUS_ACCESS_DENIED
;
854 /* Acquire registry lock */
855 //CmpLockRegistryExclusive();
857 /* Initialize the hives and lazy flusher */
858 CmpCmdInit(SetupBoot
);
860 /* FIXME: Save version data */
861 //CmpSetVersionData();
863 /* Release the registry lock */
864 //CmpUnlockRegistry();
865 return STATUS_SUCCESS
;
870 NtCompactKeys(IN ULONG Count
,
874 return STATUS_NOT_IMPLEMENTED
;
879 NtCompressKey(IN HANDLE Key
)
882 return STATUS_NOT_IMPLEMENTED
;
887 NtLockProductActivationKeys(IN PULONG pPrivateVer
,
891 return STATUS_NOT_IMPLEMENTED
;
896 NtLockRegistryKey(IN HANDLE KeyHandle
)
899 return STATUS_NOT_IMPLEMENTED
;
904 NtNotifyChangeMultipleKeys(IN HANDLE MasterKeyHandle
,
906 IN POBJECT_ATTRIBUTES SlaveObjects
,
908 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
909 IN PVOID ApcContext OPTIONAL
,
910 OUT PIO_STATUS_BLOCK IoStatusBlock
,
911 IN ULONG CompletionFilter
,
912 IN BOOLEAN WatchTree
,
915 IN BOOLEAN Asynchronous
)
918 return STATUS_NOT_IMPLEMENTED
;
923 NtQueryMultipleValueKey(IN HANDLE KeyHandle
,
924 IN OUT PKEY_VALUE_ENTRY ValueList
,
925 IN ULONG NumberOfValues
,
927 IN OUT PULONG Length
,
928 OUT PULONG ReturnLength
)
931 return STATUS_NOT_IMPLEMENTED
;
936 NtQueryOpenSubKeys(IN POBJECT_ATTRIBUTES TargetKey
,
937 OUT PULONG HandleCount
)
940 return STATUS_NOT_IMPLEMENTED
;
945 NtQueryOpenSubKeysEx(IN POBJECT_ATTRIBUTES TargetKey
,
946 IN ULONG BufferLength
,
948 IN PULONG RequiredSize
)
951 return STATUS_NOT_IMPLEMENTED
;
956 NtRenameKey(IN HANDLE KeyHandle
,
957 IN PUNICODE_STRING ReplacementName
)
960 return STATUS_NOT_IMPLEMENTED
;
965 NtReplaceKey(IN POBJECT_ATTRIBUTES ObjectAttributes
,
967 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes
)
970 return STATUS_NOT_IMPLEMENTED
;
975 NtRestoreKey(IN HANDLE KeyHandle
,
976 IN HANDLE FileHandle
,
977 IN ULONG RestoreFlags
)
980 return STATUS_NOT_IMPLEMENTED
;
985 NtSaveKey(IN HANDLE KeyHandle
,
986 IN HANDLE FileHandle
)
989 return STATUS_NOT_IMPLEMENTED
;
994 NtSaveKeyEx(IN HANDLE KeyHandle
,
995 IN HANDLE FileHandle
,
999 return STATUS_NOT_IMPLEMENTED
;
1004 NtSaveMergedKeys(IN HANDLE HighPrecedenceKeyHandle
,
1005 IN HANDLE LowPrecedenceKeyHandle
,
1006 IN HANDLE FileHandle
)
1009 return STATUS_NOT_IMPLEMENTED
;
1014 NtSetInformationKey(IN HANDLE KeyHandle
,
1015 IN KEY_SET_INFORMATION_CLASS KeyInformationClass
,
1016 IN PVOID KeyInformation
,
1017 IN ULONG KeyInformationLength
)
1020 return STATUS_NOT_IMPLEMENTED
;
1025 NtUnloadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes
)
1028 return STATUS_NOT_IMPLEMENTED
;
1033 NtUnloadKey2(IN POBJECT_ATTRIBUTES TargetKey
,
1037 return STATUS_NOT_IMPLEMENTED
;
1042 NtUnloadKeyEx(IN POBJECT_ATTRIBUTES TargetKey
,
1046 return STATUS_NOT_IMPLEMENTED
;