mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 08:25:03 +00:00
[NTOSKRNL]
Implement NtSaveKey/NtSaveKeyEx and its backend CmSaveKey. CORE-8259 #resolve #comment Committed in revision r63495. svn path=/trunk/; revision=63495
This commit is contained in:
parent
836f7cd6d3
commit
0d6c552a9d
5 changed files with 388 additions and 4 deletions
|
@ -5,6 +5,7 @@
|
|||
* PURPOSE: Configuration Manager - Internal Registry APIs
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
* Eric Kohl
|
||||
* Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
@ -2120,3 +2121,227 @@ CmCountOpenSubKeys(IN PCM_KEY_CONTROL_BLOCK RootKcb,
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -238,6 +238,28 @@ CmpInitializeHive(OUT PCMHIVE *RegistryHive,
|
|||
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;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CmpOpenHiveFiles(IN PCUNICODE_STRING BaseName,
|
||||
|
|
|
@ -361,3 +361,62 @@ CmpRemoveValueFromList(IN PHHIVE Hive,
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -1148,8 +1148,8 @@ NTAPI
|
|||
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 @@ NtSaveKeyEx(IN HANDLE KeyHandle,
|
|||
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
|
||||
|
|
|
@ -786,6 +786,12 @@ CmpInitializeHive(
|
|||
IN ULONG CheckFlags
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CmpDestroyHive(
|
||||
IN PCMHIVE CmHive
|
||||
);
|
||||
|
||||
PSECURITY_DESCRIPTOR
|
||||
NTAPI
|
||||
CmpHiveRootSecurityDescriptor(
|
||||
|
@ -1322,6 +1328,16 @@ CmpGetValueData(
|
|||
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
|
||||
//
|
||||
|
@ -1527,6 +1543,33 @@ CmCountOpenSubKeys(
|
|||
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
|
||||
);
|
||||
|
||||
//
|
||||
// Startup and Shutdown
|
||||
//
|
||||
|
|
Loading…
Reference in a new issue