mirror of
https://github.com/reactos/reactos.git
synced 2025-04-19 20:19:26 +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
|
* PURPOSE: Configuration Manager - Internal Registry APIs
|
||||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||||
* Eric Kohl
|
* Eric Kohl
|
||||||
|
* Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES ******************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
@ -2120,3 +2121,227 @@ CmCountOpenSubKeys(IN PCM_KEY_CONTROL_BLOCK RootKcb,
|
||||||
|
|
||||||
return SubKeys;
|
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;
|
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
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
CmpOpenHiveFiles(IN PCUNICODE_STRING BaseName,
|
CmpOpenHiveFiles(IN PCUNICODE_STRING BaseName,
|
||||||
|
|
|
@ -361,3 +361,62 @@ CmpRemoveValueFromList(IN PHHIVE Hive,
|
||||||
ChildList->Count = Count;
|
ChildList->Count = Count;
|
||||||
return STATUS_SUCCESS;
|
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,
|
NtSaveKey(IN HANDLE KeyHandle,
|
||||||
IN HANDLE FileHandle)
|
IN HANDLE FileHandle)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
/* Call the extended API */
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
return NtSaveKeyEx(KeyHandle, FileHandle, REG_STANDARD_FORMAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -1158,8 +1158,43 @@ NtSaveKeyEx(IN HANDLE KeyHandle,
|
||||||
IN HANDLE FileHandle,
|
IN HANDLE FileHandle,
|
||||||
IN ULONG Flags)
|
IN ULONG Flags)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
NTSTATUS Status;
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
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
|
NTSTATUS
|
||||||
|
|
|
@ -786,6 +786,12 @@ CmpInitializeHive(
|
||||||
IN ULONG CheckFlags
|
IN ULONG CheckFlags
|
||||||
);
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
CmpDestroyHive(
|
||||||
|
IN PCMHIVE CmHive
|
||||||
|
);
|
||||||
|
|
||||||
PSECURITY_DESCRIPTOR
|
PSECURITY_DESCRIPTOR
|
||||||
NTAPI
|
NTAPI
|
||||||
CmpHiveRootSecurityDescriptor(
|
CmpHiveRootSecurityDescriptor(
|
||||||
|
@ -1322,6 +1328,16 @@ CmpGetValueData(
|
||||||
OUT PHCELL_INDEX CellToRelease
|
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
|
// Boot Routines
|
||||||
//
|
//
|
||||||
|
@ -1527,6 +1543,33 @@ CmCountOpenSubKeys(
|
||||||
IN BOOLEAN RemoveEmptyCacheEntries
|
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
|
// Startup and Shutdown
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in a new issue