Author: aandrejevic
Date: Thu May 29 19:44:36 2014
New Revision: 63495
URL:
http://svn.reactos.org/svn/reactos?rev=63495&view=rev
Log:
[NTOSKRNL]
Implement NtSaveKey/NtSaveKeyEx and its backend CmSaveKey.
CORE-8259 #resolve #comment Committed in revision r63495.
Modified:
trunk/reactos/ntoskrnl/config/cmapi.c
trunk/reactos/ntoskrnl/config/cminit.c
trunk/reactos/ntoskrnl/config/cmvalue.c
trunk/reactos/ntoskrnl/config/ntapi.c
trunk/reactos/ntoskrnl/include/internal/cm.h
Modified: trunk/reactos/ntoskrnl/config/cmapi.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmapi.c?re…
==============================================================================
--- trunk/reactos/ntoskrnl/config/cmapi.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/config/cmapi.c [iso-8859-1] Thu May 29 19:44:36 2014
@@ -5,6 +5,7 @@
* PURPOSE: Configuration Manager - Internal Registry APIs
* PROGRAMMERS: Alex Ionescu (alex.ionescu(a)reactos.org)
* Eric Kohl
+ * Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*/
/* INCLUDES ******************************************************************/
@@ -2120,3 +2121,227 @@
return SubKeys;
}
+
+HCELL_INDEX
+NTAPI
+CmpCopyCell(IN PHHIVE SourceHive,
+ IN HCELL_INDEX SourceCell,
+ IN PHHIVE DestinationHive,
+ IN HSTORAGE_TYPE StorageType)
+{
+ PCELL_DATA SourceData;
+ PCELL_DATA DestinationData = NULL;
+ HCELL_INDEX DestinationCell = HCELL_NIL;
+ LONG DataSize;
+ PAGED_CODE();
+
+ /* Get the data and the size of the source cell */
+ SourceData = HvGetCell(SourceHive, SourceCell);
+ DataSize = HvGetCellSize(SourceHive, SourceData);
+
+ /* Allocate a new cell in the destination hive */
+ DestinationCell = HvAllocateCell(DestinationHive,
+ DataSize,
+ StorageType,
+ HCELL_NIL);
+ if (DestinationCell == HCELL_NIL) goto Cleanup;
+
+ /* Get the data of the destination cell */
+ DestinationData = HvGetCell(DestinationHive, DestinationCell);
+
+ /* Copy the data from the source cell to the destination cell */
+ RtlMoveMemory(DestinationData, SourceData, DataSize);
+
+Cleanup:
+
+ /* Release the cells */
+ if (SourceData) HvReleaseCell(SourceHive, SourceCell);
+ if (DestinationData) HvReleaseCell(DestinationHive, DestinationCell);
+
+ /* Return the destination cell index */
+ return DestinationCell;
+}
+
+static
+NTSTATUS
+NTAPI
+CmpDeepCopyKeyInternal(IN PHHIVE SourceHive,
+ IN HCELL_INDEX SrcKeyCell,
+ IN PHHIVE DestinationHive,
+ IN HCELL_INDEX Parent,
+ IN HSTORAGE_TYPE StorageType,
+ OUT PHCELL_INDEX DestKeyCell OPTIONAL)
+{
+ NTSTATUS Status;
+ PCM_KEY_NODE SrcNode, DestNode;
+ HCELL_INDEX NewKeyCell, SubKey, NewSubKey;
+ ULONG Index, SubKeyCount;
+ PAGED_CODE();
+
+ DPRINT("CmpDeepCopyKeyInternal(0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X,
0x%08X)\n",
+ SourceHive,
+ SrcKeyCell,
+ DestinationHive,
+ Parent,
+ StorageType,
+ DestKeyCell);
+
+ /* Get the source cell node */
+ SrcNode = HvGetCell(SourceHive, SrcKeyCell);
+
+ /* Sanity check */
+ ASSERT(SrcNode->Signature == CM_KEY_NODE_SIGNATURE);
+
+ /* Create a simple copy of the source key */
+ NewKeyCell = CmpCopyCell(SourceHive,
+ SrcKeyCell,
+ DestinationHive,
+ StorageType);
+ if (NewKeyCell == HCELL_NIL)
+ {
+ /* Not enough storage space */
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto Cleanup;
+ }
+
+ /* Get the destination cell node */
+ DestNode = HvGetCell(DestinationHive, NewKeyCell);
+
+ /* Set the parent */
+ DestNode->Parent = Parent;
+
+ // TODO: These should also be copied!
+ DestNode->Security = DestNode->Class = HCELL_NIL;
+
+ /* Copy the value list */
+ Status = CmpCopyKeyValueList(SourceHive,
+ &SrcNode->ValueList,
+ DestinationHive,
+ &DestNode->ValueList,
+ StorageType);
+ if (!NT_SUCCESS(Status)) goto Cleanup;
+
+ /* Clear the invalid subkey index */
+ DestNode->SubKeyCounts[Stable] = DestNode->SubKeyCounts[Volatile] = 0;
+ DestNode->SubKeyLists[Stable] = DestNode->SubKeyLists[Volatile] = HCELL_NIL;
+
+ /* Calculate the total number of subkeys */
+ SubKeyCount = SrcNode->SubKeyCounts[Stable] + SrcNode->SubKeyCounts[Volatile];
+
+ /* Loop through all the subkeys */
+ for (Index = 0; Index < SubKeyCount; Index++)
+ {
+ /* Get the subkey */
+ SubKey = CmpFindSubKeyByNumber(SourceHive, SrcNode, Index);
+ ASSERT(SubKey != HCELL_NIL);
+
+ /* Call the function recursively for the subkey */
+ Status = CmpDeepCopyKeyInternal(SourceHive,
+ SubKey,
+ DestinationHive,
+ NewKeyCell,
+ StorageType,
+ &NewSubKey);
+ if (!NT_SUCCESS(Status)) goto Cleanup;
+
+ /* Add the copy of the subkey to the new key */
+ if (!CmpAddSubKey(DestinationHive,
+ NewKeyCell,
+ NewSubKey))
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto Cleanup;
+ }
+ }
+
+ /* Set the cell index if requested and return success */
+ if (DestKeyCell) *DestKeyCell = NewKeyCell;
+ Status = STATUS_SUCCESS;
+
+Cleanup:
+
+ /* Release the cells */
+ if (SrcNode) HvReleaseCell(SourceHive, SrcKeyCell);
+ if (DestNode) HvReleaseCell(DestinationHive, NewKeyCell);
+
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+CmpDeepCopyKey(IN PHHIVE SourceHive,
+ IN HCELL_INDEX SrcKeyCell,
+ IN PHHIVE DestinationHive,
+ IN HSTORAGE_TYPE StorageType,
+ OUT PHCELL_INDEX DestKeyCell OPTIONAL)
+{
+ /* Call the internal function */
+ return CmpDeepCopyKeyInternal(SourceHive,
+ SrcKeyCell,
+ DestinationHive,
+ HCELL_NIL,
+ StorageType,
+ DestKeyCell);
+}
+
+NTSTATUS
+NTAPI
+CmSaveKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
+ IN HANDLE FileHandle,
+ IN ULONG Flags)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ PCMHIVE KeyHive = NULL;
+ PAGED_CODE();
+
+ DPRINT("CmSaveKey(0x%08X, 0x%08X, %lu)\n", Kcb, FileHandle, Flags);
+
+ /* Lock the registry and KCB */
+ CmpLockRegistry();
+ CmpAcquireKcbLockShared(Kcb);
+
+ if (Kcb->Delete)
+ {
+ /* The source key has been deleted, do nothing */
+ Status = STATUS_KEY_DELETED;
+ goto Cleanup;
+ }
+
+ /* Create a new hive that will hold the key */
+ Status = CmpInitializeHive(&KeyHive,
+ HINIT_CREATE,
+ HIVE_VOLATILE,
+ HFILE_TYPE_PRIMARY,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(Status)) goto Cleanup;
+
+ /* Copy the key recursively into the new hive */
+ Status = CmpDeepCopyKey(Kcb->KeyHive,
+ Kcb->KeyCell,
+ &KeyHive->Hive,
+ Stable,
+ &KeyHive->Hive.BaseBlock->RootCell);
+ if (!NT_SUCCESS(Status)) goto Cleanup;
+
+ /* Set the primary handle of the hive */
+ KeyHive->FileHandles[HFILE_TYPE_PRIMARY] = FileHandle;
+
+ /* Dump the hive into the file */
+ HvWriteHive(&KeyHive->Hive);
+
+Cleanup:
+
+ /* Free the hive */
+ if (KeyHive) CmpDestroyHive(KeyHive);
+
+ /* Release the locks */
+ CmpReleaseKcbLock(Kcb);
+ CmpUnlockRegistry();
+
+ return Status;
+}
Modified: trunk/reactos/ntoskrnl/config/cminit.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cminit.c?r…
==============================================================================
--- trunk/reactos/ntoskrnl/config/cminit.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/config/cminit.c [iso-8859-1] Thu May 29 19:44:36 2014
@@ -235,6 +235,28 @@
/* Return the hive and success */
*RegistryHive = (PCMHIVE)Hive;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+CmpDestroyHive(IN PCMHIVE CmHive)
+{
+ /* Remove the hive from the list */
+ ExAcquirePushLockExclusive(&CmpHiveListHeadLock);
+ RemoveEntryList(&CmHive->HiveList);
+ ExReleasePushLock(&CmpHiveListHeadLock);
+
+ /* Delete the flusher lock */
+ ExDeleteResourceLite(CmHive->FlusherLock);
+ ExFreePoolWithTag(CmHive->FlusherLock, TAG_CM);
+
+ /* Delete the view lock */
+ ExFreePoolWithTag(CmHive->ViewLock, TAG_CM);
+
+ /* Free the hive */
+ HvFree(&CmHive->Hive);
+
return STATUS_SUCCESS;
}
Modified: trunk/reactos/ntoskrnl/config/cmvalue.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmvalue.c?…
==============================================================================
--- trunk/reactos/ntoskrnl/config/cmvalue.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/config/cmvalue.c [iso-8859-1] Thu May 29 19:44:36 2014
@@ -361,3 +361,62 @@
ChildList->Count = Count;
return STATUS_SUCCESS;
}
+
+NTSTATUS
+NTAPI
+CmpCopyKeyValueList(IN PHHIVE SourceHive,
+ IN PCHILD_LIST SrcValueList,
+ IN PHHIVE DestinationHive,
+ IN OUT PCHILD_LIST DestValueList,
+ IN HSTORAGE_TYPE StorageType)
+
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ HCELL_INDEX CellIndex = HCELL_NIL;
+ ULONG Index;
+ PCELL_DATA SrcListData = NULL;
+ PCELL_DATA DestListData = NULL;
+
+ PAGED_CODE();
+
+ /* Set the count */
+ DestValueList->Count = SrcValueList->Count;
+
+ /* Check if the list is empty */
+ if (!DestValueList->Count)
+ {
+ DestValueList->List = HCELL_NIL;
+ return STATUS_SUCCESS;
+ }
+
+ /* Create a simple copy of the list */
+ CellIndex = CmpCopyCell(SourceHive,
+ SrcValueList->List,
+ DestinationHive,
+ StorageType);
+ if (CellIndex == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Get the source and the destination value list */
+ SrcListData = HvGetCell(SourceHive, SrcValueList->List);
+ DestListData = HvGetCell(DestinationHive, CellIndex);
+
+ /* Copy the actual values */
+ for (Index = 0; Index < SrcValueList->Count; Index++)
+ {
+ DestListData->u.KeyList[Index] = CmpCopyCell(SourceHive,
+ SrcListData->u.KeyList[Index],
+ DestinationHive,
+ StorageType);
+ if (DestListData->u.KeyList[Index] == HCELL_NIL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+ }
+
+ /* Release the cells */
+ if (SrcListData) HvReleaseCell(SourceHive, SrcValueList->List);
+ if (DestListData) HvReleaseCell(DestinationHive, CellIndex);
+
+ return Status;
+}
Modified: trunk/reactos/ntoskrnl/config/ntapi.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/ntapi.c?re…
==============================================================================
--- trunk/reactos/ntoskrnl/config/ntapi.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/config/ntapi.c [iso-8859-1] Thu May 29 19:44:36 2014
@@ -1148,8 +1148,8 @@
NtSaveKey(IN HANDLE KeyHandle,
IN HANDLE FileHandle)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ /* Call the extended API */
+ return NtSaveKeyEx(KeyHandle, FileHandle, REG_STANDARD_FORMAT);
}
NTSTATUS
@@ -1158,8 +1158,43 @@
IN HANDLE FileHandle,
IN ULONG Flags)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ NTSTATUS Status;
+ PCM_KEY_BODY KeyObject;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+
+ PAGED_CODE();
+
+ DPRINT("NtSaveKeyEx(0x%08X, 0x%08X, %lu)\n", KeyHandle, FileHandle,
Flags);
+
+ /* Verify the flags */
+ if ((Flags != REG_STANDARD_FORMAT)
+ && (Flags != REG_LATEST_FORMAT)
+ && (Flags != REG_NO_COMPRESSION))
+ {
+ /* Only one of these values can be specified */
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Check for the SeBackupPrivilege */
+ if (!SeSinglePrivilegeCheck(SeBackupPrivilege, PreviousMode))
+ {
+ return STATUS_PRIVILEGE_NOT_HELD;
+ }
+
+ /* Verify that the handle is valid and is a registry key */
+ Status = ObReferenceObjectByHandle(KeyHandle,
+ KEY_READ,
+ CmpKeyObjectType,
+ PreviousMode,
+ (PVOID*)&KeyObject,
+ NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Call the internal API */
+ Status = CmSaveKey(KeyObject->KeyControlBlock, FileHandle, Flags);
+
+ ObDereferenceObject(KeyObject);
+ return Status;
}
NTSTATUS
Modified: trunk/reactos/ntoskrnl/include/internal/cm.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/cm.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/cm.h [iso-8859-1] Thu May 29 19:44:36 2014
@@ -786,6 +786,12 @@
IN ULONG CheckFlags
);
+NTSTATUS
+NTAPI
+CmpDestroyHive(
+ IN PCMHIVE CmHive
+);
+
PSECURITY_DESCRIPTOR
NTAPI
CmpHiveRootSecurityDescriptor(
@@ -1322,6 +1328,16 @@
OUT PHCELL_INDEX CellToRelease
);
+NTSTATUS
+NTAPI
+CmpCopyKeyValueList(
+ IN PHHIVE SourceHive,
+ IN PCHILD_LIST SrcValueList,
+ IN PHHIVE DestinationHive,
+ IN OUT PCHILD_LIST DestValueList,
+ IN HSTORAGE_TYPE StorageType
+);
+
//
// Boot Routines
//
@@ -1525,6 +1541,33 @@
CmCountOpenSubKeys(
IN PCM_KEY_CONTROL_BLOCK RootKcb,
IN BOOLEAN RemoveEmptyCacheEntries
+);
+
+HCELL_INDEX
+NTAPI
+CmpCopyCell(
+ IN PHHIVE SourceHive,
+ IN HCELL_INDEX SourceCell,
+ IN PHHIVE DestinationHive,
+ IN HSTORAGE_TYPE StorageType
+);
+
+NTSTATUS
+NTAPI
+CmpDeepCopyKey(
+ IN PHHIVE SourceHive,
+ IN HCELL_INDEX SrcKeyCell,
+ IN PHHIVE DestinationHive,
+ IN HSTORAGE_TYPE StorageType,
+ OUT PHCELL_INDEX DestKeyCell OPTIONAL
+);
+
+NTSTATUS
+NTAPI
+CmSaveKey(
+ IN PCM_KEY_CONTROL_BLOCK Kcb,
+ IN HANDLE FileHandle,
+ IN ULONG Flags
);
//