windows-nt/Source/XPSP1/NT/base/ntos/config/utils/edithive.c
2020-09-26 16:20:57 +08:00

1060 lines
26 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
edithive.c
Abstract:
Provides functionality for dumping and editing registry hive files from
user-mode.
Author:
John Vert (jvert) 26-Mar-1992
Revision History:
--*/
#include "edithive.h"
#include "nturtl.h"
extern GENERIC_MAPPING CmpKeyMapping;
extern LIST_ENTRY CmpHiveListHead; // List of CMHIVEs
#define SECURITY_CELL_LENGTH(pDescriptor) \
FIELD_OFFSET(CM_KEY_SECURITY,Descriptor) + \
RtlLengthSecurityDescriptor(pDescriptor)
NTSTATUS
EhpAttachSecurity(
IN PHHIVE Hive,
IN HCELL_INDEX Cell
);
PVOID
EhpAllocate(
ULONG Size
);
VOID
EhpFree(
PVOID MemoryBlock
);
BOOLEAN
EhpFileRead (
HANDLE FileHandle,
PULONG FileOffset,
PVOID DataBuffer,
ULONG DataLength
);
BOOLEAN
EhpFileWrite(
HANDLE FileHandle,
PULONG FileOffset,
PVOID DataBuffer,
ULONG DataLength
);
BOOLEAN
EhpFileFlush (
HANDLE FileHandle
);
VOID
CmpGetObjectSecurity(
IN HCELL_INDEX Cell,
IN PHHIVE Hive,
OUT PCM_KEY_SECURITY *Security,
OUT PHCELL_INDEX SecurityCell OPTIONAL
)
/*++
Routine Description:
This routine maps in the security cell of a registry object.
Arguments:
Cell - Supplies the cell index of the object.
Hive - Supplies the hive the object's cell is in.
Security - Returns a pointer to the security cell of the object.
SecurityCell - Returns the index of the security cell
Return Value:
NONE.
--*/
{
HCELL_INDEX CellIndex;
PCM_KEY_NODE Node;
//
// Map the node we need to get the security descriptor for
//
Node = (PCM_KEY_NODE) HvGetCell(Hive, Cell);
CellIndex = Node->u1.s1.Security;
//
// Map in the security descriptor cell
//
*Security = (PCM_KEY_SECURITY) HvGetCell(Hive, CellIndex);
if (ARGUMENT_PRESENT(SecurityCell)) {
*SecurityCell = CellIndex;
}
return;
}
VOID
EhCloseHive(
IN HANDLE HiveHandle
)
/*++
Routine Description:
Closes a hive, including writing all the data out to disk and freeing
the relevant structures.
Arguments:
HiveHandle - Supplies a handle to the hive control structure
Return Value:
None.
--*/
{
HvSyncHive((PHHIVE)HiveHandle);
NtClose(((PCMHIVE)HiveHandle)->FileHandles[HFILE_TYPE_PRIMARY]);
NtClose(((PCMHIVE)HiveHandle)->FileHandles[HFILE_TYPE_ALTERNATE]);
NtClose(((PCMHIVE)HiveHandle)->FileHandles[HFILE_TYPE_LOG]);
CmpFree((PCMHIVE)HiveHandle, sizeof(CMHIVE));
}
HANDLE
EhOpenHive(
IN PUNICODE_STRING FileName,
OUT PHANDLE RootHandle,
IN PUNICODE_STRING RootName,
IN ULONG HiveType
)
/*++
Routine Description:
Opens an existing hive. If the filename does not exist it will be
created.
WARNING: Allocate FileName large enough to acomodate .log or
.alt extension.
Arguments:
FileName - Supplies the NULL-terminated filename to open as a hive.
HiveType - TYPE_SIMPLE = no log or alternate
TYPE_LOG = log
TYPE_ALT = alternate
Return Value:
!= NULL - Handle to the opened hive.
== NULL - Indicates file could not be opened.
--*/
{
NTSTATUS Status;
HANDLE File;
BOOLEAN Allocate;
PCMHIVE Hive;
IO_STATUS_BLOCK IoStatus;
ULONG CreateDisposition;
OBJECT_ATTRIBUTES ObjectAttributes;
PCM_KEY_NODE RootNode;
HANDLE Handle;
HANDLE Primary;
HANDLE Log;
HANDLE Alt;
ULONG FileType;
ULONG Disposition;
ULONG SecondaryDisposition;
ULONG Operation;
Alt = NULL;
Log = NULL;
InitializeListHead(&CmpHiveListHead);
switch (HiveType) {
case TYPE_SIMPLE:
Status = CmpOpenHiveFiles(
FileName,
NULL,
&Primary,
NULL,
&Disposition,
&SecondaryDisposition,
TRUE,
NULL
);
if (!NT_SUCCESS(Status))
{
return NULL;
}
FileType = HFILE_TYPE_PRIMARY;
break;
case TYPE_LOG:
Status = CmpOpenHiveFiles(
FileName,
L".log",
&Primary,
&Log,
&Disposition,
&SecondaryDisposition,
TRUE,
NULL
);
if (!NT_SUCCESS(Status))
{
return NULL;
}
if (Log == NULL) {
return NULL;
}
FileType = HFILE_TYPE_LOG;
break;
case TYPE_ALT:
Status = CmpOpenHiveFiles(
FileName,
L".alt",
&Primary,
&Alt,
&Disposition,
&SecondaryDisposition,
TRUE,
NULL
);
if (!NT_SUCCESS(Status))
{
return NULL;
}
if (Alt == NULL) {
return NULL;
}
FileType = HFILE_TYPE_ALTERNATE;
break;
default:
return NULL;
}
//
// Initialize hive
//
if (Disposition == FILE_CREATED) {
Operation = HINIT_CREATE;
Allocate = TRUE;
} else {
Operation = HINIT_FILE;
Allocate = FALSE;
}
if ( ! CmpInitializeHive(
&Hive,
Operation,
FALSE,
FileType,
NULL,
Primary,
Alt,
Log,
NULL,
NULL
))
{
return NULL;
}
if (!Allocate) {
*RootHandle = (HANDLE)(Hive->Hive.BaseBlock->RootCell);
RootNode = (PCM_KEY_NODE)HvGetCell(
(PHHIVE)Hive, Hive->Hive.BaseBlock->RootCell);
RootName->Length = RootName->MaximumLength = RootNode->NameLength;
RootName->Buffer = RootNode->Name;
} else {
RtlInitUnicodeString(RootName, L"HiveRoot");
*RootHandle = (HANDLE)HCELL_NIL;
HvSyncHive((PHHIVE)Hive);
}
return((HANDLE)Hive);
}
NTSTATUS
EhEnumerateKey(
IN HANDLE HiveHandle,
IN HANDLE CellHandle,
IN ULONG Index,
IN KEY_INFORMATION_CLASS KeyInformationClass,
IN PVOID KeyInformation,
IN ULONG Length,
IN PULONG ResultLength
)
/*++
Routine Description:
Enumerate sub keys, return data on Index'th entry.
CmEnumerateKey returns the name of the Index'th sub key of the open
key specified. The value STATUS_NO_MORE_ENTRIES will be
returned if value of Index is larger than the number of sub keys.
Note that Index is simply a way to select among child keys. Two calls
to CmEnumerateKey with the same Index are NOT guaranteed to return
the same results.
If KeyInformation is not long enough to hold all requested data,
STATUS_BUFFER_OVERFLOW will be returned, and ResultLength will be
set to the number of bytes actually required.
Arguments:
Hive - supplies a pointer to the hive control structure for the hive
Cell - supplies index of node to whose sub keys are to be found
Index - Specifies the (0-based) number of the sub key to be returned.
KeyInformationClass - Specifies the type of information returned in
Buffer. One of the following types:
KeyBasicInformation - return last write time, title index, and name.
(see KEY_BASIC_INFORMATION structure)
KeyNodeInformation - return last write time, title index, name, class.
(see KEY_NODE_INFORMATION structure)
KeyInformation -Supplies pointer to buffer to receive the data.
Length - Length of KeyInformation in bytes.
ResultLength - Number of bytes actually written into KeyInformation.
Return Value:
NTSTATUS - Result code from call, among the following:
<TBS>
--*/
{
CM_KEY_CONTROL_BLOCK kcb;
kcb.Signature = CM_KEY_CONTROL_BLOCK_SIGNATURE;
kcb.Delete = FALSE;
kcb.KeyHive = &((PCMHIVE)HiveHandle)->Hive;
kcb.KeyCell = (HCELL_INDEX)CellHandle;
kcb.RefCount = 1;
return(CmEnumerateKey(&kcb,
Index,
KeyInformationClass,
KeyInformation,
Length,
ResultLength));
}
NTSTATUS
EhEnumerateValueKey(
IN HANDLE HiveHandle,
IN HANDLE CellHandle,
IN ULONG Index,
IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
IN PVOID KeyValueInformation,
IN ULONG Length,
IN PULONG ResultLength
)
/*++
Routine Description:
The value entries of an open key may be enumerated.
CmEnumerateValueKey returns the name of the Index'th value
entry of the open key specified by KeyHandle. The value
STATUS_NO_MORE_ENTRIES will be returned if value of Index is
larger than the number of sub keys.
Note that Index is simply a way to select among value
entries. Two calls to NtEnumerateValueKey with the same Index
are NOT guaranteed to return the same results.
If KeyValueInformation is not long enough to hold all requested data,
STATUS_BUFFER_OVERFLOW will be returned, and ResultLength will be
set to the number of bytes actually required.
Arguments:
Hive - supplies a handle to the hive
Cell - supplies handle to node whose sub keys are to be found
Index - Specifies the (0-based) number of the sub key to be returned.
KeyValueInformationClass - Specifies the type of information returned
in Buffer. One of the following types:
KeyValueBasicInformation - return time of last write,
title index, and name. (See KEY_VALUE_BASIC_INFORMATION)
KeyValueFullInformation - return time of last write,
title index, name, class. (See KEY_VALUE_FULL_INFORMATION)
KeyValueInformation -Supplies pointer to buffer to receive the data.
Length - Length of KeyValueInformation in bytes.
ResultLength - Number of bytes actually written into KeyValueInformation.
Return Value:
NTSTATUS - Result code from call, among the following:
<TBS>
--*/
{
CM_KEY_CONTROL_BLOCK kcb;
kcb.Signature = CM_KEY_CONTROL_BLOCK_SIGNATURE;
kcb.Delete = FALSE;
kcb.KeyHive = (PHHIVE)&(((PCMHIVE)HiveHandle)->Hive);
kcb.KeyCell = (HCELL_INDEX)CellHandle;
kcb.RefCount = 1;
return(CmEnumerateValueKey(&kcb,
Index,
KeyValueInformationClass,
KeyValueInformation,
Length,
ResultLength));
}
NTSTATUS
EhOpenChildByNumber(
IN HANDLE HiveHandle,
IN HANDLE CellHandle,
IN ULONG Index,
IN NODE_TYPE Type,
OUT PHANDLE ChildCell
)
/*++
Routine Description:
Return the cell index of the Nth child cell.
Arguments:
HiveHandle - handle of hive control structure for hive of interest
CellHandle - handle for parent cell
Index - number of desired child
Type - type of the child object
ChildCell - supplies a pointer to a variable to receive the
HCELL_INDEX of the Index'th child.
Return Value:
status
--*/
{
return(CmpFindChildByNumber(&((PCMHIVE)HiveHandle)->Hive,
(HCELL_INDEX)CellHandle,
Index,
Type,
(PHCELL_INDEX)ChildCell));
}
NTSTATUS
EhSetValueKey(
IN HANDLE HiveHandle,
IN HANDLE CellHandle,
IN PUNICODE_STRING ValueName,
IN ULONG TitleIndex OPTIONAL,
IN ULONG Type,
IN PVOID Data,
IN ULONG DataSize
)
/*++
Routine Description:
A value entry may be created or replaced with EhSetValueKey.
If a value entry with a Value ID (i.e. name) matching the
one specified by ValueName exists, it is deleted and replaced
with the one specified. If no such value entry exists, a new
one is created. NULL is a legal Value ID. While Value IDs must
be unique within any given key, the same Value ID may appear
in many different keys.
Arguments:
HiveHandle - handle of hive control structure for hive of interest
CellHandle - handle for parent cell
ValueName - The unique (relative to the containing key) name
of the value entry. May be NULL.
TitleIndex - Supplies the title index for ValueName. The title
index specifies the index of the localized alias for the ValueName.
Type - The integer type number of the value entry.
Data - Pointer to buffer with actual data for the value entry.
DataSize - Size of Data buffer.
Return Value:
NTSTATUS - Result code from call, among the following:
<TBS>
--*/
{
CM_KEY_CONTROL_BLOCK kcb;
kcb.Delete = FALSE;
kcb.Signature = CM_KEY_CONTROL_BLOCK_SIGNATURE;
kcb.KeyHive = (PHHIVE)&(((PCMHIVE)HiveHandle)->Hive);
kcb.KeyCell = (HCELL_INDEX)CellHandle;
kcb.FullName.Length = 0;
kcb.FullName.MaximumLength = 0;
kcb.FullName.Buffer = NULL;
return(CmSetValueKey(&kcb,
*ValueName,
TitleIndex,
Type,
Data,
DataSize));
}
NTSTATUS
EhOpenChildByName(
HANDLE HiveHandle,
HANDLE CellHandle,
PUNICODE_STRING Name,
PHANDLE ChildCell
)
/*++
Routine Description:
Find the child subkey cell specified by Name.
Arguments:
HiveHandle - handle of hive control structure for hive of interest
CellHandle - handle for parent cell
Name - name of child object to find
ChildCell - pointer to variable to receive cell index of child
Return Value:
status
--*/
{
PHCELL_INDEX Index;
return(CmpFindChildByName(&((PCMHIVE)HiveHandle)->Hive,
(HCELL_INDEX)CellHandle,
*Name,
KeyBodyNode,
(PHCELL_INDEX)ChildCell,
&Index));
}
NTSTATUS
EhCreateChild(
IN HANDLE HiveHandle,
IN HANDLE CellHandle,
IN PUNICODE_STRING Name,
OUT PHANDLE ChildCell,
OUT PULONG Disposition OPTIONAL
)
/*++
Routine Description:
Attempts to open the given child subkey specified by name. If the
child does not exist, it is created.
Arguments:
HiveHandle - handle of hive control structure for hive of interest
CellHandle - handle for parent cell
Name - name of child object to create
ChildCell - pointer to variable to receive cell index of child
Disposition - This optional parameter is a pointer to a variable
that will receive a value indicating whether a new Registry
key was created or an existing one opened:
REG_CREATED_NEW_KEY - A new Registry Key was created
REG_OPENED_EXISTING_KEY - An existing Registry Key was opened
Return Value:
status
--*/
{
PHCELL_INDEX Index;
NTSTATUS Status;
PHHIVE Hive;
HCELL_INDEX NewCell;
HCELL_INDEX NewListCell;
HCELL_INDEX OldListCell;
PHCELL_INDEX NewList;
PHCELL_INDEX OldList;
PCM_KEY_NODE Child;
PCM_KEY_NODE Parent;
PCM_KEY_SECURITY Security;
HANDLE Handle;
ULONG oldcount;
Hive = &((PCMHIVE)HiveHandle)->Hive;
if ((HCELL_INDEX)CellHandle == HCELL_NIL) {
if (Hive->BaseBlock->RootCell != HCELL_NIL) {
*ChildCell = (HANDLE)(Hive->BaseBlock->RootCell);
if (ARGUMENT_PRESENT(Disposition)) {
*Disposition = REG_OPENED_EXISTING_KEY;
}
return(STATUS_SUCCESS);
} else {
Status = STATUS_OBJECT_NAME_NOT_FOUND;
}
} else {
Parent = (PCM_KEY_NODE)HvGetCell(Hive, (HCELL_INDEX)CellHandle);
Status = CmpFindChildByName(Hive,
(HCELL_INDEX)CellHandle,
*Name,
KeyBodyNode,
(PHCELL_INDEX)ChildCell,
&Index);
}
if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
NewCell = HvAllocateCell(Hive,
CmpHKeyNodeSize(Hive,Name->Length),
Stable);
if (NewCell != HCELL_NIL) {
*ChildCell = (HANDLE)NewCell;
Child = (PCM_KEY_NODE)HvGetCell(Hive, NewCell);
Child->Signature = CM_KEY_NODE_SIGNATURE;
Child->Flags = 0;
KeQuerySystemTime(&(Child->LastWriteTime));
Child->Spare = 0;
Child->Parent = (HCELL_INDEX)CellHandle;
Child->ValueList.Count = 0;
Child->ValueList.List = HCELL_NIL;
Child->u1.s1.Security = HCELL_NIL;
Child->u1.s1.Class = HCELL_NIL;
Child->NameLength = Name->Length;
Child->ClassLength = 0;
Child->SubKeyCounts[Stable] = 0;
Child->SubKeyCounts[Volatile] = 0;
Child->SubKeyLists[Stable] = HCELL_NIL;
Child->SubKeyLists[Volatile] = HCELL_NIL;
Child->MaxValueDataLen = 0;
Child->MaxNameLen = 0;
Child->MaxValueNameLen = 0;
Child->MaxClassLen = 0;
if((HCELL_INDEX)CellHandle == HCELL_NIL) {
Hive->BaseBlock->RootCell = NewCell;
Status = EhpAttachSecurity(Hive, NewCell);
} else {
Child->u1.s1.Security = Parent->u1.s1.Security;
Security = (PCM_KEY_SECURITY)HvGetCell(Hive, Child->u1.s1.Security);
++Security->ReferenceCount;
}
RtlMoveMemory(
&(Child->Name[0]),
Name->Buffer,
Name->Length
);
Status = STATUS_SUCCESS;
} else {
Status = STATUS_INSUFFICIENT_RESOURCES;
return(Status);
}
if (ARGUMENT_PRESENT(Disposition)) {
*Disposition = REG_CREATED_NEW_KEY;
}
if ((HCELL_INDEX)CellHandle != HCELL_NIL) {
//
// put newly created child into parent's sub key list
//
if (! CmpAddSubKey(Hive, (HCELL_INDEX)CellHandle, NewCell)) {
CmpFreeKeyByCell(Hive, NewCell, FALSE);
return STATUS_INSUFFICIENT_RESOURCES;
}
Parent = (PCM_KEY_NODE)HvGetCell(Hive, (HCELL_INDEX)CellHandle);
if (Parent->MaxNameLen < Name->Length) {
Parent->MaxNameLen = Name->Length;
}
Parent->MaxClassLen = 0;
}
} else {
Status = STATUS_SUCCESS;
if (ARGUMENT_PRESENT(Disposition)) {
*Disposition = REG_OPENED_EXISTING_KEY;
}
}
return(Status);
}
NTSTATUS
EhQueryKey(
IN HANDLE HiveHandle,
IN HANDLE KeyHandle,
IN KEY_INFORMATION_CLASS KeyInformationClass,
IN PVOID KeyInformation,
IN ULONG Length,
IN PULONG ResultLength
)
/*++
Routine Description:
Data about the class of a key, and the numbers and sizes of its
children and value entries may be queried with CmQueryKey.
NOTE: The returned lengths are guaranteed to be at least as
long as the described values, but may be longer in
some circumstances.
Arguments:
Hive - supplies a handle to the hive control structure for the hive
Cell - supplies handle of node to whose sub keys are to be found
KeyInformationClass - Specifies the type of information
returned in Buffer. One of the following types:
KeyBasicInformation - return last write time, title index, and name.
(See KEY_BASIC_INFORMATION)
KeyNodeInformation - return last write time, title index, name, class.
(See KEY_NODE_INFORMATION)
KeyFullInformation - return all data except for name and security.
(See KEY_FULL_INFORMATION)
KeyInformation -Supplies pointer to buffer to receive the data.
Length - Length of KeyInformation in bytes.
ResultLength - Number of bytes actually written into KeyInformation.
Return Value:
NTSTATUS - Result code from call, among the following:
<TBS>
--*/
{
CM_KEY_CONTROL_BLOCK Kcb;
Kcb.Delete = FALSE;
Kcb.Signature = CM_KEY_CONTROL_BLOCK_SIGNATURE;
Kcb.KeyHive = &((PCMHIVE)HiveHandle)->Hive;
Kcb.KeyCell = (HCELL_INDEX)KeyHandle;
Kcb.FullName.Length = 0;
Kcb.FullName.MaximumLength = 0;
Kcb.FullName.Buffer = NULL;
return(CmQueryKey(&Kcb,
KeyInformationClass,
KeyInformation,
Length,
ResultLength));
}
PSECURITY_DESCRIPTOR
EhGetKeySecurity(
IN HANDLE HiveHandle,
IN HANDLE KeyHandle
)
{
PCM_KEY_SECURITY Security;
CmpGetObjectSecurity((HCELL_INDEX)KeyHandle,
&((PCMHIVE)HiveHandle)->Hive,
&Security,
NULL);
return(&Security->Descriptor);
}
NTSTATUS
EhQueryValueKey(
IN HANDLE HiveHandle,
IN HANDLE KeyHandle,
IN PUNICODE_STRING ValueName,
IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
IN PVOID KeyValueInformation,
IN ULONG Length,
IN PULONG ResultLength
)
/*++
Routine Description:
The ValueName, TitleIndex, Type, and Data for any one of a key's
value entries may be queried with CmQueryValueKey.
If KeyValueInformation is not long enough to hold all requested data,
STATUS_BUFFER_OVERFLOW will be returned, and ResultLength will be
set to the number of bytes actually required.
Arguments:
Hive - supplies a pointer to the hive control structure for the hive
Cell - supplies index of node to whose sub keys are to be found
ValueName - The name of the value entry to return data for.
KeyValueInformationClass - Specifies the type of information
returned in KeyValueInformation. One of the following types:
KeyValueBasicInformation - return time of last write, title
index, and name. (See KEY_VALUE_BASIC_INFORMATION)
KeyValueFullInformation - return time of last write, title
index, name, class. (See KEY_VALUE_FULL_INFORMATION)
KeyValueInformation -Supplies pointer to buffer to receive the data.
Length - Length of KeyValueInformation in bytes.
ResultLength - Number of bytes actually written into KeyValueInformation.
Return Value:
NTSTATUS - Result code from call, among the following:
<TBS>
--*/
{
CM_KEY_CONTROL_BLOCK kcb;
kcb.Delete = FALSE;
kcb.Signature = CM_KEY_CONTROL_BLOCK_SIGNATURE;
kcb.KeyHive = &((PCMHIVE)HiveHandle)->Hive;
kcb.KeyCell = (HCELL_INDEX)KeyHandle;
kcb.FullName.Length = 0;
kcb.FullName.MaximumLength = 0;
kcb.FullName.Buffer = NULL;
return(CmQueryValueKey(&kcb,
*ValueName,
KeyValueInformationClass,
KeyValueInformation,
Length,
ResultLength));
}
NTSTATUS
EhDeleteValueKey(
IN HANDLE HiveHandle,
IN HANDLE CellHandle,
IN PUNICODE_STRING ValueName // RAW
)
/*++
Routine Description:
One of the value entries of a registry key may be removed with this call.
The value entry with ValueName matching ValueName is removed from the key.
If no such entry exists, an error is returned.
Arguments:
Hive - Supplies a handle to the hive control structure
Cell - Supplies a handle to the registry key to be operated on
ValueName - The name of the value to be deleted. NULL is a legal name.
Return Value:
NTSTATUS - Result code from call, among the following:
<TBS>
--*/
{
CM_KEY_CONTROL_BLOCK kcb;
kcb.Delete = FALSE;
kcb.Signature = CM_KEY_CONTROL_BLOCK_SIGNATURE;
kcb.KeyHive = &((PCMHIVE)HiveHandle)->Hive;
kcb.KeyCell = (HCELL_INDEX)CellHandle;
kcb.FullName.Length = 0;
kcb.FullName.MaximumLength = 0;
kcb.FullName.Buffer = NULL;
return(CmDeleteValueKey(&kcb, *ValueName));
}
NTSTATUS
EhpAttachSecurity(
IN PHHIVE Hive,
IN HCELL_INDEX Cell
)
/*++
Routine Description:
Creates a security descriptor cell and attaches it to the given
node.
Arguments:
Hive - Supplies a pointer to the hive control structure.
Cell - Supplies the cell index of the node to attach the security
descriptor to.
Return Value:
None.
--*/
{
NTSTATUS Status;
HANDLE Token;
HCELL_INDEX SecurityCell;
PCM_KEY_NODE Node;
PCM_KEY_SECURITY Security;
PSECURITY_DESCRIPTOR Descriptor;
ULONG DescriptorLength;
HANDLE Handle;
Status = NtOpenProcessToken( NtCurrentProcess(),
TOKEN_QUERY,
&Token );
if (!NT_SUCCESS(Status)) {
return(Status);
}
Status = RtlNewSecurityObject( NULL,
NULL,
&Descriptor,
FALSE,
Token,
&CmpKeyMapping );
if (!NT_SUCCESS(Status)) {
return(Status);
}
Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
SecurityCell = HvAllocateCell(Hive,
SECURITY_CELL_LENGTH(Descriptor),
Stable);
if (SecurityCell == HCELL_NIL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
Node->u1.s1.Security = SecurityCell;
Security = (PCM_KEY_SECURITY)HvGetCell(Hive, SecurityCell);
DescriptorLength = RtlLengthSecurityDescriptor(Descriptor);
Security->Signature = CM_KEY_SECURITY_SIGNATURE;
Security->ReferenceCount = 1;
Security->DescriptorLength = DescriptorLength;
RtlMoveMemory( &Security->Descriptor,
Descriptor,
DescriptorLength );
Security->Flink = Security->Blink = SecurityCell;
return(STATUS_SUCCESS);
}