1060 lines
26 KiB
C
1060 lines
26 KiB
C
/*++
|
||
|
||
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);
|
||
|
||
}
|
||
|