/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
- * FILE: ntoskrnl/config/cmapi.c
+ * FILE: ntoskrnl/config/ntapi.c
* PURPOSE: Configuration Manager - Internal Registry APIs
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* Eric Kohl
BOOLEAN CmBootAcceptFirstTime = TRUE;
BOOLEAN CmFirstTime = TRUE;
+extern ULONG InitSafeBootMode;
/* FUNCTIONS *****************************************************************/
ObjectAttributes->ObjectName, ObjectAttributes->RootDirectory,
DesiredAccess, CreateOptions);
+ /* Ignore the WOW64 flag, it's not valid in the kernel */
+ DesiredAccess &= ~KEY_WOW64_RES;
+
/* Check for user-mode caller */
if (PreviousMode != KernelMode)
{
DPRINT("NtOpenKey(Path: %wZ, Root %x, Access: %x)\n",
ObjectAttributes->ObjectName, ObjectAttributes->RootDirectory, DesiredAccess);
+ /* Ignore the WOW64 flag, it's not valid in the kernel */
+ DesiredAccess &= ~KEY_WOW64_RES;
+
/* Check for user-mode caller */
if (PreviousMode != KernelMode)
{
/* Just let the object manager handle this */
Status = ObOpenObjectByName(ObjectAttributes,
CmpKeyObjectType,
- ExGetPreviousMode(),
+ PreviousMode,
NULL,
DesiredAccess,
&ParseContext,
Status = ObReferenceObjectByHandle(KeyHandle,
KEY_ENUMERATE_SUB_KEYS,
CmpKeyObjectType,
- ExGetPreviousMode(),
+ PreviousMode,
(PVOID*)&KeyObject,
NULL);
if (!NT_SUCCESS(Status)) return Status;
Status = ObReferenceObjectByHandle(KeyHandle,
KEY_QUERY_VALUE,
CmpKeyObjectType,
- ExGetPreviousMode(),
+ PreviousMode,
(PVOID*)&KeyObject,
NULL);
if (!NT_SUCCESS(Status)) return Status;
Status = ObReferenceObjectByHandle(KeyHandle,
0,
CmpKeyObjectType,
- ExGetPreviousMode(),
+ PreviousMode,
(PVOID*)&KeyObject,
&HandleInfo);
if (NT_SUCCESS(Status))
Status = ObReferenceObjectByHandle(KeyHandle,
KEY_QUERY_VALUE,
CmpKeyObjectType,
- ExGetPreviousMode(),
+ PreviousMode,
(PVOID*)&KeyObject,
NULL);
}
Status = ObReferenceObjectByHandle(KeyHandle,
KEY_QUERY_VALUE,
CmpKeyObjectType,
- ExGetPreviousMode(),
+ PreviousMode,
(PVOID*)&KeyObject,
NULL);
if (!NT_SUCCESS(Status)) return Status;
Data = NULL;
/* Probe and copy the data */
- if ((PreviousMode != KernelMode) && Data)
+ if ((PreviousMode != KernelMode) && (DataSize != 0))
{
PVOID DataCopy = ExAllocatePoolWithTag(PagedPool, DataSize, TAG_CM);
if (!DataCopy)
- return STATUS_NO_MEMORY;
+ return STATUS_INSUFFICIENT_RESOURCES;
_SEH2_TRY
{
ProbeForRead(Data, DataSize, 1);
Status = ObReferenceObjectByHandle(KeyHandle,
KEY_SET_VALUE,
CmpKeyObjectType,
- ExGetPreviousMode(),
+ PreviousMode,
(PVOID*)&KeyObject,
NULL);
if (!NT_SUCCESS(Status))
KEY_SET_VALUE,
CmpKeyObjectType,
PreviousMode,
- (PVOID *)&KeyObject,
+ (PVOID*)&KeyObject,
NULL);
if (!NT_SUCCESS(Status)) return Status;
/* Validate privilege */
if (!SeSinglePrivilegeCheck(SeRestorePrivilege, PreviousMode))
{
- /* Fail */
DPRINT1("Restore Privilege missing!\n");
return STATUS_PRIVILEGE_NOT_HELD;
}
0,
CmpKeyObjectType,
PreviousMode,
- (PVOID *)&KeyBody,
+ (PVOID*)&KeyBody,
NULL);
}
/* Enough of the system has booted by now */
Ki386PerfEnd();
-
+
/* Validate flag */
if (Flag > CM_BOOT_FLAG_MAX) return STATUS_INVALID_PARAMETER;
return STATUS_NOT_IMPLEMENTED;
}
+// FIXME: different for different windows versions!
+#define PRODUCT_ACTIVATION_VERSION 7749
+
NTSTATUS
NTAPI
NtLockProductActivationKeys(IN PULONG pPrivateVer,
IN PULONG pSafeMode)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ KPROCESSOR_MODE PreviousMode;
+
+ PreviousMode = ExGetPreviousMode();
+ _SEH2_TRY
+ {
+ /* Check if the caller asked for the version */
+ if (pPrivateVer != NULL)
+ {
+ /* For user mode, probe it */
+ if (PreviousMode != KernelMode)
+ {
+ ProbeForRead(pPrivateVer, sizeof(ULONG), sizeof(ULONG));
+ }
+
+ /* Return the expected version */
+ *pPrivateVer = PRODUCT_ACTIVATION_VERSION;
+ }
+
+ /* Check if the caller asked for safe mode mode state */
+ if (pSafeMode != NULL)
+ {
+ /* For user mode, probe it */
+ if (PreviousMode != KernelMode)
+ {
+ ProbeForRead(pSafeMode, sizeof(ULONG), sizeof(ULONG));
+ }
+
+ /* Return the safe boot mode state */
+ *pSafeMode = InitSafeBootMode;
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+
+ return STATUS_SUCCESS;
}
NTSTATUS
IN ULONG Length,
IN BOOLEAN Asynchronous)
{
- UNIMPLEMENTED;
+ UNIMPLEMENTED_ONCE;
return STATUS_NOT_IMPLEMENTED;
}
/* Get the processor mode */
PreviousMode = KeGetPreviousMode();
+ /* Check for user-mode caller */
if (PreviousMode != KernelMode)
{
/* Prepare to probe parameters */
KEY_READ,
CmpKeyObjectType,
PreviousMode,
- (PVOID *)&KeyBody,
+ (PVOID*)&KeyBody,
NULL);
/* Close the handle */
PAGED_CODE();
- DPRINT("NtSaveKeyEx(0x%08X, 0x%08X, %lu)\n", KeyHandle, FileHandle, Flags);
+ DPRINT("NtSaveKeyEx(0x%p, 0x%p, %lu)\n", KeyHandle, FileHandle, Flags);
/* Verify the flags */
if ((Flags != REG_STANDARD_FORMAT)
return STATUS_INVALID_PARAMETER;
}
- /* Check for the SeBackupPrivilege */
+ /* Validate privilege */
if (!SeSinglePrivilegeCheck(SeBackupPrivilege, PreviousMode))
{
return STATUS_PRIVILEGE_NOT_HELD;
IN HANDLE LowPrecedenceKeyHandle,
IN HANDLE FileHandle)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ KPROCESSOR_MODE PreviousMode;
+ PCM_KEY_BODY HighPrecedenceKeyObject = NULL;
+ PCM_KEY_BODY LowPrecedenceKeyObject = NULL;
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ DPRINT("NtSaveMergedKeys(0x%p, 0x%p, 0x%p)\n",
+ HighPrecedenceKeyHandle, LowPrecedenceKeyHandle, FileHandle);
+
+ PreviousMode = ExGetPreviousMode();
+
+ /* Validate privilege */
+ if (!SeSinglePrivilegeCheck(SeBackupPrivilege, PreviousMode))
+ {
+ return STATUS_PRIVILEGE_NOT_HELD;
+ }
+
+ /* Verify that the handles are valid and are registry keys */
+ Status = ObReferenceObjectByHandle(HighPrecedenceKeyHandle,
+ KEY_READ,
+ CmpKeyObjectType,
+ PreviousMode,
+ (PVOID*)&HighPrecedenceKeyObject,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ goto done;
+
+ Status = ObReferenceObjectByHandle(LowPrecedenceKeyHandle,
+ KEY_READ,
+ CmpKeyObjectType,
+ PreviousMode,
+ (PVOID*)&LowPrecedenceKeyObject,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ goto done;
+
+ /* Call the internal API */
+ Status = CmSaveMergedKeys(HighPrecedenceKeyObject->KeyControlBlock,
+ LowPrecedenceKeyObject->KeyControlBlock,
+ FileHandle);
+
+done:
+ if (LowPrecedenceKeyObject)
+ ObDereferenceObject(LowPrecedenceKeyObject);
+
+ if (HighPrecedenceKeyObject)
+ ObDereferenceObject(HighPrecedenceKeyObject);
+
+ return Status;
}
NTSTATUS
NtUnloadKey2(IN POBJECT_ATTRIBUTES TargetKey,
IN ULONG Flags)
{
-#if 0
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING ObjectName;
PCM_KEY_BODY KeyBody = NULL;
ULONG ParentConv = 0, ChildConv = 0;
HANDLE Handle;
+
PAGED_CODE();
/* Validate privilege */
if (!SeSinglePrivilegeCheck(SeRestorePrivilege, PreviousMode))
{
- /* Fail */
DPRINT1("Restore Privilege missing!\n");
return STATUS_PRIVILEGE_NOT_HELD;
}
goto Quickie;
}
- /* Check if it's a readonly key */
+ /* Check if it's a read-only key */
if (KeyBody->KeyControlBlock->ExtFlags & CM_KCB_READ_ONLY_KEY)
{
/* Return appropriate status */
{
if (Flags != REG_FORCE_UNLOAD)
{
+ /* Release the KCB locks */
+ CmpReleaseTwoKcbLockByKey(ChildConv, ParentConv);
+
/* Release the hive loading lock */
ExReleasePushLockExclusive(&CmpLoadHiveLock);
-
- /* Release two KCBs lock */
- CmpReleaseTwoKcbLockByKey(ChildConv, ParentConv);
}
/* Unlock the registry */
/* Return status */
return Status;
-#else
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-#endif
}
NTSTATUS