- Make mkhive tool correctly initialize the Max(Value)[Name|Data]Length members of HHIVE structure. CORE-10794 #resolve
- Add default security hive descriptors to our mkhive-built registry hives. CORE-10795 #resolve
- Make MKHIVE fully using the CMLIB library. CORE-10802
CORE-10793

svn path=/trunk/; revision=70602
This commit is contained in:
Hermès Bélusca-Maïto
2016-01-17 00:50:03 +00:00
parent 5a29ec2659
commit 30da982e36
6 changed files with 715 additions and 612 deletions

View File

@@ -16,7 +16,8 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* COPYRIGHT: See COPYING in the top level directory
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS hive maker
* FILE: tools/mkhive/cmi.c
* PURPOSE: Registry file manipulation routines
@@ -33,7 +34,7 @@ CmpAllocate(
IN BOOLEAN Paged,
IN ULONG Tag)
{
return (PVOID) malloc((size_t)Size);
return (PVOID)malloc((size_t)Size);
}
VOID
@@ -69,9 +70,10 @@ CmpFileWrite(
{
PCMHIVE CmHive = (PCMHIVE)RegistryHive;
FILE *File = CmHive->FileHandles[HFILE_TYPE_PRIMARY];
if (0 != fseek (File, *FileOffset, SEEK_SET))
if (fseek(File, *FileOffset, SEEK_SET) != 0)
return FALSE;
return BufferLength == fwrite (Buffer, 1, BufferLength, File);
return (fwrite(Buffer, 1, BufferLength, File) == BufferLength);
}
static BOOLEAN
@@ -96,25 +98,24 @@ CmpFileFlush(
{
PCMHIVE CmHive = (PCMHIVE)RegistryHive;
FILE *File = CmHive->FileHandles[HFILE_TYPE_PRIMARY];
return 0 == fflush (File);
return (fflush(File) == 0);
}
NTSTATUS
CmiInitializeTempHive(
IN OUT PCMHIVE Hive)
CmiInitializeHive(
IN OUT PCMHIVE Hive,
IN PCWSTR Name)
{
NTSTATUS Status;
RtlZeroMemory (
Hive,
sizeof(CMHIVE));
RtlZeroMemory(Hive, sizeof(*Hive));
DPRINT("Hive 0x%p\n", Hive);
Status = HvInitialize(&Hive->Hive,
HINIT_CREATE,
0,
0,
HIVE_NOLAZYFLUSH,
HFILE_TYPE_PRIMARY,
0,
CmpAllocate,
CmpFree,
@@ -129,200 +130,158 @@ CmiInitializeTempHive(
return Status;
}
if (!CmCreateRootNode (&Hive->Hive, L""))
// HACK: See the HACK from r31253
if (!CmCreateRootNode(&Hive->Hive, Name))
{
HvFree (&Hive->Hive);
HvFree(&Hive->Hive);
return STATUS_INSUFFICIENT_RESOURCES;
}
Hive->Flags = HIVE_NO_FILE;
/* Add the new hive to the hive list */
InsertTailList(&CmiHiveListHead,
&Hive->HiveList);
VERIFY_REGISTRY_HIVE (Hive);
return STATUS_SUCCESS;
}
static NTSTATUS
CmiAddKeyToHashTable(
IN PCMHIVE RegistryHive,
IN OUT PCM_KEY_FAST_INDEX HashCell,
IN HCELL_INDEX HashCellIndex,
IN PCM_KEY_NODE NewKeyCell,
IN HCELL_INDEX NKBOffset)
NTSTATUS
CmiCreateSecurityKey(
IN PHHIVE Hive,
IN HCELL_INDEX Cell,
IN PUCHAR Descriptor,
IN ULONG DescriptorLength)
{
ULONG i;
ULONG HashKey = 0;
HCELL_INDEX SecurityCell;
PCM_KEY_NODE Node;
PCM_KEY_SECURITY Security;
if (NewKeyCell->Flags & KEY_COMP_NAME)
Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
SecurityCell = HvAllocateCell(Hive,
FIELD_OFFSET(CM_KEY_SECURITY, Descriptor) +
DescriptorLength,
Stable,
HCELL_NIL);
if (SecurityCell == HCELL_NIL)
{
RtlCopyMemory(
&HashKey,
NewKeyCell->Name,
min(NewKeyCell->NameLength, sizeof(ULONG)));
HvReleaseCell(Hive, Cell);
return STATUS_INSUFFICIENT_RESOURCES;
}
for (i = 0; i < HashCell->Count; i++)
{
if (HashCell->List[i].HashKey > HashKey)
break;
}
Node->Security = SecurityCell;
Security = (PCM_KEY_SECURITY)HvGetCell(Hive, SecurityCell);
Security->Signature = CM_KEY_SECURITY_SIGNATURE;
Security->ReferenceCount = 1;
Security->DescriptorLength = DescriptorLength;
if (i < HashCell->Count)
{
RtlMoveMemory(HashCell->List + i + 1,
HashCell->List + i,
(HashCell->Count - i) *
sizeof(HashCell->List[0]));
}
RtlMoveMemory(&Security->Descriptor,
Descriptor,
DescriptorLength);
Security->Flink = Security->Blink = SecurityCell;
HvReleaseCell(Hive, SecurityCell);
HvReleaseCell(Hive, Cell);
HashCell->List[i].Cell = NKBOffset;
HashCell->List[i].HashKey = HashKey;
HashCell->Count++;
HvMarkCellDirty(&RegistryHive->Hive, HashCellIndex, FALSE);
return STATUS_SUCCESS;
}
static NTSTATUS
CmiAllocateHashTableCell (
IN PCMHIVE RegistryHive,
OUT PCM_KEY_FAST_INDEX *HashBlock,
OUT HCELL_INDEX *HBOffset,
IN USHORT SubKeyCount,
IN HSTORAGE_TYPE Storage)
{
PCM_KEY_FAST_INDEX NewHashBlock;
ULONG NewHashSize;
NTSTATUS Status;
Status = STATUS_SUCCESS;
*HashBlock = NULL;
NewHashSize = FIELD_OFFSET(CM_KEY_FAST_INDEX, List) +
(SubKeyCount * sizeof(CM_INDEX));
*HBOffset = HvAllocateCell(&RegistryHive->Hive, NewHashSize, Storage, HCELL_NIL);
if (*HBOffset == HCELL_NIL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
}
else
{
NewHashBlock = (PCM_KEY_FAST_INDEX)HvGetCell (&RegistryHive->Hive, *HBOffset);
NewHashBlock->Signature = CM_KEY_FAST_LEAF;
NewHashBlock->Count = 0;
*HashBlock = NewHashBlock;
}
return Status;
}
static NTSTATUS
CmiCreateSubKey(
IN PCMHIVE RegistryHive,
IN HCELL_INDEX ParentKeyCellOffset,
IN PCUNICODE_STRING SubKeyName,
IN ULONG CreateOptions,
IN BOOLEAN VolatileKey,
OUT HCELL_INDEX* pNKBOffset)
{
HCELL_INDEX NKBOffset;
PCM_KEY_NODE NewKeyCell;
ULONG NewBlockSize;
NTSTATUS Status;
USHORT NameLength;
PWSTR NamePtr;
BOOLEAN Packable;
UNICODE_STRING KeyName;
HSTORAGE_TYPE Storage;
ULONG i;
/* Skip leading backslash */
if (SubKeyName->Buffer[0] == L'\\')
/* Skip leading path separator if present */
if (SubKeyName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
{
NamePtr = &SubKeyName->Buffer[1];
NameLength = SubKeyName->Length - sizeof(WCHAR);
KeyName.Buffer = &SubKeyName->Buffer[1];
KeyName.Length = KeyName.MaximumLength = SubKeyName->Length - sizeof(WCHAR);
}
else
{
NamePtr = SubKeyName->Buffer;
NameLength = SubKeyName->Length;
KeyName = *SubKeyName;
}
/* Check whether key name can be packed */
Packable = TRUE;
for (i = 0; i < NameLength / sizeof(WCHAR); i++)
{
if (NamePtr[i] & 0xFF00)
{
Packable = FALSE;
break;
}
}
Storage = (VolatileKey ? Volatile : Stable);
/* Adjust name size */
if (Packable)
{
NameLength = NameLength / sizeof(WCHAR);
}
Status = STATUS_SUCCESS;
Storage = (CreateOptions & REG_OPTION_VOLATILE) ? Volatile : Stable;
NewBlockSize = FIELD_OFFSET(CM_KEY_NODE, Name) + NameLength;
NKBOffset = HvAllocateCell(&RegistryHive->Hive, NewBlockSize, Storage, HCELL_NIL);
NKBOffset = HvAllocateCell(&RegistryHive->Hive,
FIELD_OFFSET(CM_KEY_NODE, Name) +
CmpNameSize(&RegistryHive->Hive, &KeyName),
Storage,
HCELL_NIL);
if (NKBOffset == HCELL_NIL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
return STATUS_INSUFFICIENT_RESOURCES;
}
NewKeyCell = (PCM_KEY_NODE)HvGetCell(&RegistryHive->Hive, NKBOffset);
if (NewKeyCell == NULL)
{
HvFreeCell(&RegistryHive->Hive, NKBOffset);
return STATUS_INSUFFICIENT_RESOURCES;
}
NewKeyCell->Signature = CM_KEY_NODE_SIGNATURE;
NewKeyCell->Flags = (VolatileKey ? KEY_IS_VOLATILE : 0);
KeQuerySystemTime(&NewKeyCell->LastWriteTime);
NewKeyCell->Parent = ParentKeyCellOffset;
NewKeyCell->SubKeyCounts[Stable] = 0;
NewKeyCell->SubKeyCounts[Volatile] = 0;
NewKeyCell->SubKeyLists[Stable] = HCELL_NIL;
NewKeyCell->SubKeyLists[Volatile] = HCELL_NIL;
NewKeyCell->ValueList.Count = 0;
NewKeyCell->ValueList.List = HCELL_NIL;
NewKeyCell->Security = HCELL_NIL;
NewKeyCell->Class = HCELL_NIL;
NewKeyCell->ClassLength = 0;
NewKeyCell->MaxNameLen = 0;
NewKeyCell->MaxClassLen = 0;
NewKeyCell->MaxValueNameLen = 0;
NewKeyCell->MaxValueDataLen = 0;
NewKeyCell->NameLength = CmpCopyName(&RegistryHive->Hive, NewKeyCell->Name, &KeyName);
if (NewKeyCell->NameLength < KeyName.Length) NewKeyCell->Flags |= KEY_COMP_NAME;
/* Inherit the security from the parent */
if (ParentKeyCellOffset == HCELL_NIL)
{
// We are in fact creating a root key.
// This is not handled there, but when we
// call CmCreateRootNode instead.
ASSERT(FALSE);
}
else
{
NewKeyCell = (PCM_KEY_NODE)HvGetCell (&RegistryHive->Hive, NKBOffset);
NewKeyCell->Signature = CM_KEY_NODE_SIGNATURE;
if (CreateOptions & REG_OPTION_VOLATILE)
{
NewKeyCell->Flags = KEY_IS_VOLATILE;
}
else
{
NewKeyCell->Flags = 0;
}
KeQuerySystemTime(&NewKeyCell->LastWriteTime);
NewKeyCell->Parent = ParentKeyCellOffset;
NewKeyCell->SubKeyCounts[Stable] = 0;
NewKeyCell->SubKeyCounts[Volatile] = 0;
NewKeyCell->SubKeyLists[Stable] = HCELL_NIL;
NewKeyCell->SubKeyLists[Volatile] = HCELL_NIL;
NewKeyCell->ValueList.Count = 0;
NewKeyCell->ValueList.List = HCELL_NIL;
NewKeyCell->Security = HCELL_NIL;
NewKeyCell->Class = HCELL_NIL;
/* Get the parent node */
PCM_KEY_NODE ParentKeyCell;
ParentKeyCell = (PCM_KEY_NODE)HvGetCell(&RegistryHive->Hive, ParentKeyCellOffset);
/* Pack the key name */
NewKeyCell->NameLength = NameLength;
if (Packable)
if (ParentKeyCell)
{
NewKeyCell->Flags |= KEY_COMP_NAME;
for (i = 0; i < NameLength; i++)
/* Inherit the security block of the parent */
NewKeyCell->Security = ParentKeyCell->Security;
if (NewKeyCell->Security != HCELL_NIL)
{
((PCHAR)NewKeyCell->Name)[i] = (CHAR)(NamePtr[i] & 0x00FF);
PCM_KEY_SECURITY Security;
Security = (PCM_KEY_SECURITY)HvGetCell(&RegistryHive->Hive, NewKeyCell->Security);
++Security->ReferenceCount;
HvReleaseCell(&RegistryHive->Hive, NewKeyCell->Security);
}
}
else
{
RtlCopyMemory(NewKeyCell->Name,
NamePtr,
NameLength);
}
VERIFY_KEY_CELL(NewKeyCell);
HvReleaseCell(&RegistryHive->Hive, ParentKeyCellOffset);
}
}
if (NT_SUCCESS(Status))
{
*pNKBOffset = NKBOffset;
}
return Status;
HvReleaseCell(&RegistryHive->Hive, NKBOffset);
*pNKBOffset = NKBOffset;
return STATUS_SUCCESS;
}
NTSTATUS
@@ -330,291 +289,156 @@ CmiAddSubKey(
IN PCMHIVE RegistryHive,
IN HCELL_INDEX ParentKeyCellOffset,
IN PCUNICODE_STRING SubKeyName,
IN ULONG CreateOptions,
OUT PCM_KEY_NODE *pSubKeyCell,
IN BOOLEAN VolatileKey,
OUT HCELL_INDEX *pBlockOffset)
{
PCM_KEY_NODE ParentKeyCell;
HCELL_INDEX NKBOffset;
NTSTATUS Status;
ParentKeyCell = (PCM_KEY_NODE)HvGetCell(&RegistryHive->Hive, ParentKeyCellOffset);
if (!ParentKeyCell)
return STATUS_UNSUCCESSFUL;
VERIFY_KEY_CELL(ParentKeyCell);
/* Create the new key */
Status = CmiCreateSubKey(RegistryHive, ParentKeyCellOffset, SubKeyName, CreateOptions, &NKBOffset);
Status = CmiCreateSubKey(RegistryHive, ParentKeyCellOffset, SubKeyName, VolatileKey, &NKBOffset);
if (!NT_SUCCESS(Status))
{
return Status;
}
/* Mark the parent cell as dirty */
HvMarkCellDirty(&RegistryHive->Hive, ParentKeyCellOffset, FALSE);
if (!CmpAddSubKey(&RegistryHive->Hive, ParentKeyCellOffset, NKBOffset))
{
/* FIXME: delete newly created cell */
// CmpFreeKeyByCell(&RegistryHive->Hive, NewCell /*NKBOffset*/, FALSE);
ASSERT(FALSE);
return STATUS_UNSUCCESSFUL;
}
/* Get the parent node */
ParentKeyCell = (PCM_KEY_NODE)HvGetCell(&RegistryHive->Hive, ParentKeyCellOffset);
if (!ParentKeyCell)
{
/* FIXME: delete newly created cell */
return STATUS_UNSUCCESSFUL;
}
VERIFY_KEY_CELL(ParentKeyCell);
/* Update the timestamp */
KeQuerySystemTime(&ParentKeyCell->LastWriteTime);
HvMarkCellDirty(&RegistryHive->Hive, ParentKeyCellOffset, FALSE);
/* Check if we need to update name maximum, update it if so */
if (ParentKeyCell->MaxNameLen < SubKeyName->Length)
ParentKeyCell->MaxNameLen = SubKeyName->Length;
/* Release the cell */
HvReleaseCell(&RegistryHive->Hive, ParentKeyCellOffset);
*pBlockOffset = NKBOffset;
return STATUS_SUCCESS;
}
#if 0 // Those two functions seem to be unused, but keep them just in case we may need to use them in the future...
static BOOLEAN
CmiCompareHash(
IN PCUNICODE_STRING KeyName,
IN PCHAR HashString)
{
CHAR Buffer[4];
Buffer[0] = (KeyName->Length >= 2) ? (CHAR)KeyName->Buffer[0] : 0;
Buffer[1] = (KeyName->Length >= 4) ? (CHAR)KeyName->Buffer[1] : 0;
Buffer[2] = (KeyName->Length >= 6) ? (CHAR)KeyName->Buffer[2] : 0;
Buffer[3] = (KeyName->Length >= 8) ? (CHAR)KeyName->Buffer[3] : 0;
return (strncmp(Buffer, HashString, 4) == 0);
}
static BOOLEAN
CmiCompareHashI(
IN PCUNICODE_STRING KeyName,
IN PCHAR HashString)
{
CHAR Buffer[4];
Buffer[0] = (KeyName->Length >= 2) ? (CHAR)KeyName->Buffer[0] : 0;
Buffer[1] = (KeyName->Length >= 4) ? (CHAR)KeyName->Buffer[1] : 0;
Buffer[2] = (KeyName->Length >= 6) ? (CHAR)KeyName->Buffer[2] : 0;
Buffer[3] = (KeyName->Length >= 8) ? (CHAR)KeyName->Buffer[3] : 0;
return (strncasecmp(Buffer, HashString, 4) == 0);
}
#endif
NTSTATUS
CmiScanForSubKey(
IN PCMHIVE RegistryHive,
IN HCELL_INDEX ParentKeyCellOffset,
IN PCUNICODE_STRING SubKeyName,
IN ULONG Attributes,
OUT PCM_KEY_NODE *pSubKeyCell,
OUT HCELL_INDEX *pBlockOffset)
{
PCM_KEY_NODE KeyCell;
PCM_KEY_FAST_INDEX HashBlock;
PCM_KEY_NODE CurSubKeyCell;
BOOLEAN CaseInsensitive;
ULONG Storage;
ULONG i;
KeyCell = (PCM_KEY_NODE)HvGetCell(&RegistryHive->Hive, ParentKeyCellOffset);
if (!KeyCell)
return STATUS_UNSUCCESSFUL;
VERIFY_KEY_CELL(KeyCell);
ASSERT(RegistryHive);
*pSubKeyCell = NULL;
CaseInsensitive = (Attributes & OBJ_CASE_INSENSITIVE) != 0;
for (Storage = Stable; Storage < HTYPE_COUNT; Storage++)
{
if (KeyCell->SubKeyLists[Storage] == HCELL_NIL)
{
/* The key does not have any subkeys */
continue;
}
/* Get hash table */
HashBlock = (PCM_KEY_FAST_INDEX)HvGetCell (&RegistryHive->Hive, KeyCell->SubKeyLists[Storage]);
if (!HashBlock || HashBlock->Signature != CM_KEY_FAST_LEAF)
return STATUS_UNSUCCESSFUL;
for (i = 0; i < KeyCell->SubKeyCounts[Storage]; i++)
{
if ((HashBlock->List[i].HashKey == 0) ||
(CmCompareHash(SubKeyName, (PCHAR)&HashBlock->List[i].HashKey, CaseInsensitive)))
{
CurSubKeyCell = (PCM_KEY_NODE)HvGetCell(&RegistryHive->Hive,
HashBlock->List[i].Cell);
if (CmCompareKeyName(CurSubKeyCell, SubKeyName, CaseInsensitive))
{
*pSubKeyCell = CurSubKeyCell;
*pBlockOffset = HashBlock->List[i].Cell;
return STATUS_SUCCESS;
}
}
}
}
return STATUS_OBJECT_NAME_NOT_FOUND;
}
static USHORT
CmiGetPackedNameLength(
IN PCUNICODE_STRING Name,
OUT PBOOLEAN pPackable)
{
USHORT i;
*pPackable = TRUE;
for (i = 0; i < Name->Length / sizeof(WCHAR); i++)
{
if (Name->Buffer[i] & 0xFF00)
{
*pPackable = FALSE;
return Name->Length;
}
}
return (Name->Length / sizeof(WCHAR));
}
static NTSTATUS
CmiAllocateValueCell(
IN PCMHIVE RegistryHive,
OUT PCM_KEY_VALUE *ValueCell,
OUT HCELL_INDEX *VBOffset,
IN PCUNICODE_STRING ValueName,
IN HSTORAGE_TYPE Storage)
{
PCM_KEY_VALUE NewValueCell;
BOOLEAN Packable;
USHORT NameLength, i;
NTSTATUS Status;
Status = STATUS_SUCCESS;
NameLength = CmiGetPackedNameLength(ValueName, &Packable);
DPRINT("ValueName->Length %u NameLength %u\n", ValueName->Length, NameLength);
*VBOffset = HvAllocateCell(&RegistryHive->Hive, sizeof(CM_KEY_VALUE) + NameLength, Storage, HCELL_NIL);
if (*VBOffset == HCELL_NIL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
}
else
{
NewValueCell = (PCM_KEY_VALUE)HvGetCell (&RegistryHive->Hive, *VBOffset);
NewValueCell->Signature = CM_KEY_VALUE_SIGNATURE;
NewValueCell->NameLength = (USHORT)NameLength;
if (Packable)
{
/* Pack the value name */
for (i = 0; i < NameLength; i++)
{
((PCHAR)NewValueCell->Name)[i] = (CHAR)ValueName->Buffer[i];
}
NewValueCell->Flags |= VALUE_COMP_NAME;
}
else
{
/* Copy the value name */
RtlCopyMemory(NewValueCell->Name,
ValueName->Buffer,
NameLength);
NewValueCell->Flags = 0;
}
NewValueCell->Type = 0;
NewValueCell->DataLength = 0;
NewValueCell->Data = HCELL_NIL;
*ValueCell = NewValueCell;
}
return Status;
}
NTSTATUS
CmiAddValueKey(
IN PCMHIVE RegistryHive,
IN HCELL_INDEX KeyCellOffset,
IN PCM_KEY_NODE Parent,
IN PCUNICODE_STRING ValueName,
OUT PCM_KEY_VALUE *pValueCell,
OUT HCELL_INDEX *pValueCellOffset)
{
PVALUE_LIST_CELL ValueListCell;
PCM_KEY_NODE KeyCell;
PCELL_DATA ValueListCell;
PCM_KEY_VALUE NewValueCell;
HCELL_INDEX ValueListCellOffset;
HCELL_INDEX NewValueCellOffset;
ULONG CellSize;
HSTORAGE_TYPE Storage;
NTSTATUS Status;
KeyCell = HvGetCell(&RegistryHive->Hive, KeyCellOffset);
if (!KeyCell)
return STATUS_UNSUCCESSFUL;
#ifndef FIELD_SIZE
#define FIELD_SIZE(type, field) (sizeof(((type *)0)->field))
#endif
Storage = (KeyCell->Flags & KEY_IS_VOLATILE) ? Volatile : Stable;
if (KeyCell->ValueList.List == HCELL_NIL)
Storage = (Parent->Flags & KEY_IS_VOLATILE) ? Volatile : Stable;
if (Parent->ValueList.List == HCELL_NIL)
{
/* Allocate some room for the value list */
CellSize = sizeof(VALUE_LIST_CELL) + (3 * sizeof(HCELL_INDEX));
CellSize = FIELD_SIZE(CELL_DATA, u.KeyList) + (3 * sizeof(HCELL_INDEX));
ValueListCellOffset = HvAllocateCell(&RegistryHive->Hive, CellSize, Storage, HCELL_NIL);
if (ValueListCellOffset == HCELL_NIL)
return STATUS_INSUFFICIENT_RESOURCES;
ValueListCell = (PVALUE_LIST_CELL)HvGetCell(&RegistryHive->Hive, ValueListCellOffset);
ValueListCell = (PCELL_DATA)HvGetCell(&RegistryHive->Hive, ValueListCellOffset);
if (!ValueListCell)
{
HvFreeCell(&RegistryHive->Hive, ValueListCellOffset);
return STATUS_UNSUCCESSFUL;
}
KeyCell->ValueList.List = ValueListCellOffset;
HvMarkCellDirty(&RegistryHive->Hive, KeyCellOffset, FALSE);
Parent->ValueList.List = ValueListCellOffset;
}
else
{
ValueListCell = (PVALUE_LIST_CELL)HvGetCell(&RegistryHive->Hive, KeyCell->ValueList.List);
ValueListCell = (PCELL_DATA)HvGetCell(&RegistryHive->Hive, Parent->ValueList.List);
if (!ValueListCell)
return STATUS_UNSUCCESSFUL;
CellSize = ABS_VALUE(HvGetCellSize(&RegistryHive->Hive, ValueListCell));
if (KeyCell->ValueList.Count >= CellSize / sizeof(HCELL_INDEX))
if (Parent->ValueList.Count >= CellSize / sizeof(HCELL_INDEX))
{
CellSize *= 2;
ValueListCellOffset = HvReallocateCell(&RegistryHive->Hive, KeyCell->ValueList.List, CellSize);
ValueListCellOffset = HvReallocateCell(&RegistryHive->Hive, Parent->ValueList.List, CellSize);
if (ValueListCellOffset == HCELL_NIL)
return STATUS_INSUFFICIENT_RESOURCES;
ValueListCell = (PVALUE_LIST_CELL)HvGetCell(&RegistryHive->Hive, ValueListCellOffset);
ValueListCell = (PCELL_DATA)HvGetCell(&RegistryHive->Hive, ValueListCellOffset);
if (!ValueListCell)
return STATUS_UNSUCCESSFUL;
KeyCell->ValueList.List = ValueListCellOffset;
HvMarkCellDirty(&RegistryHive->Hive, KeyCellOffset, FALSE);
Parent->ValueList.List = ValueListCellOffset;
}
}
Status = CmiAllocateValueCell(RegistryHive,
&NewValueCell,
&NewValueCellOffset,
ValueName,
Storage);
if (!NT_SUCCESS(Status))
return Status;
ValueListCell->ValueOffset[KeyCell->ValueList.Count] = NewValueCellOffset;
KeyCell->ValueList.Count++;
if (NewValueCell->Flags & VALUE_COMP_NAME)
NewValueCellOffset = HvAllocateCell(&RegistryHive->Hive,
FIELD_OFFSET(CM_KEY_VALUE, Name) +
CmpNameSize(&RegistryHive->Hive, (PUNICODE_STRING)ValueName),
Storage,
HCELL_NIL);
if (NewValueCellOffset == HCELL_NIL)
{
if (NewValueCell->NameLength*sizeof(WCHAR) > KeyCell->MaxValueNameLen)
KeyCell->MaxValueNameLen = NewValueCell->NameLength*sizeof(WCHAR);
return STATUS_INSUFFICIENT_RESOURCES;
}
NewValueCell = (PCM_KEY_VALUE)HvGetCell(&RegistryHive->Hive, NewValueCellOffset);
if (NewValueCell == NULL)
{
HvFreeCell(&RegistryHive->Hive, NewValueCellOffset);
return STATUS_INSUFFICIENT_RESOURCES;
}
NewValueCell->Signature = CM_KEY_VALUE_SIGNATURE;
NewValueCell->NameLength = CmpCopyName(&RegistryHive->Hive,
NewValueCell->Name,
(PUNICODE_STRING)ValueName);
/* Check for compressed name */
if (NewValueCell->NameLength < ValueName->Length)
{
/* This is a compressed name */
NewValueCell->Flags = VALUE_COMP_NAME;
}
else
{
if (NewValueCell->NameLength > KeyCell->MaxValueNameLen)
KeyCell->MaxValueNameLen = NewValueCell->NameLength;
/* No flags to set */
NewValueCell->Flags = 0;
}
HvMarkCellDirty(&RegistryHive->Hive, KeyCellOffset, FALSE);
HvMarkCellDirty(&RegistryHive->Hive, KeyCell->ValueList.List, FALSE);
NewValueCell->Type = 0;
NewValueCell->DataLength = 0;
NewValueCell->Data = HCELL_NIL;
ValueListCell->u.KeyList[Parent->ValueList.Count] = NewValueCellOffset;
Parent->ValueList.Count++;
HvMarkCellDirty(&RegistryHive->Hive, Parent->ValueList.List, FALSE);
HvMarkCellDirty(&RegistryHive->Hive, NewValueCellOffset, FALSE);
*pValueCell = NewValueCell;
@@ -622,53 +446,3 @@ CmiAddValueKey(
return STATUS_SUCCESS;
}
NTSTATUS
CmiScanForValueKey(
IN PCMHIVE RegistryHive,
IN HCELL_INDEX KeyCellOffset,
IN PCUNICODE_STRING ValueName,
OUT PCM_KEY_VALUE *pValueCell,
OUT HCELL_INDEX *pValueCellOffset)
{
PCM_KEY_NODE KeyCell;
PVALUE_LIST_CELL ValueListCell;
PCM_KEY_VALUE CurValueCell;
ULONG i;
KeyCell = (PCM_KEY_NODE)HvGetCell(&RegistryHive->Hive, KeyCellOffset);
if (!KeyCell)
return STATUS_UNSUCCESSFUL;
*pValueCell = NULL;
*pValueCellOffset = HCELL_NIL;
/* The key does not have any values */
if (KeyCell->ValueList.List == HCELL_NIL)
{
return STATUS_OBJECT_NAME_NOT_FOUND;
}
ValueListCell = (PVALUE_LIST_CELL)HvGetCell(&RegistryHive->Hive, KeyCell->ValueList.List);
VERIFY_VALUE_LIST_CELL(ValueListCell);
for (i = 0; i < KeyCell->ValueList.Count; i++)
{
CurValueCell = (PCM_KEY_VALUE)HvGetCell(&RegistryHive->Hive,
ValueListCell->ValueOffset[i]);
if (CmComparePackedNames(ValueName,
(PUCHAR)CurValueCell->Name,
CurValueCell->NameLength,
(CurValueCell->Flags & VALUE_COMP_NAME) ? TRUE : FALSE,
TRUE))
{
*pValueCell = CurValueCell;
*pValueCellOffset = ValueListCell->ValueOffset[i];
return STATUS_SUCCESS;
}
}
return STATUS_OBJECT_NAME_NOT_FOUND;
}

View File

@@ -16,7 +16,8 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* COPYRIGHT: See COPYING in the top level directory
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS hive maker
* FILE: tools/mkhive/cmi.h
* PURPOSE: Registry file manipulation routines
@@ -24,42 +25,31 @@
*/
#define VERIFY_KEY_CELL(key)
#define VERIFY_VALUE_LIST_CELL(cell)
NTSTATUS
CmiInitializeTempHive(
IN OUT PCMHIVE Hive);
CmiInitializeHive(
IN OUT PCMHIVE Hive,
IN PCWSTR Name);
NTSTATUS
CmiCreateSecurityKey(
IN PHHIVE Hive,
IN HCELL_INDEX Cell,
IN PUCHAR Descriptor,
IN ULONG DescriptorLength);
NTSTATUS
CmiAddSubKey(
IN PCMHIVE RegistryHive,
IN HCELL_INDEX ParentKeyCellOffset,
IN PCUNICODE_STRING SubKeyName,
IN ULONG CreateOptions,
OUT PCM_KEY_NODE *pSubKeyCell,
OUT HCELL_INDEX *pBlockOffset);
NTSTATUS
CmiScanForSubKey(
IN PCMHIVE RegistryHive,
IN HCELL_INDEX ParentKeyCellOffset,
IN PCUNICODE_STRING SubKeyName,
IN ULONG Attributes,
OUT PCM_KEY_NODE *pSubKeyCell,
IN BOOLEAN VolatileKey,
OUT HCELL_INDEX *pBlockOffset);
NTSTATUS
CmiAddValueKey(
IN PCMHIVE RegistryHive,
IN HCELL_INDEX KeyCellOffset,
IN PCUNICODE_STRING ValueName,
OUT PCM_KEY_VALUE *pValueCell,
OUT HCELL_INDEX *pValueCellOffset);
NTSTATUS
CmiScanForValueKey(
IN PCMHIVE RegistryHive,
IN HCELL_INDEX KeyCellOffset,
IN PCM_KEY_NODE Parent,
IN PCUNICODE_STRING ValueName,
OUT PCM_KEY_VALUE *pValueCell,
OUT HCELL_INDEX *pValueCellOffset);

View File

@@ -16,7 +16,8 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* COPYRIGHT: See COPYING in the top level directory
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS hive maker
* FILE: tools/mkhive/mkhive.c
* PURPOSE: Hive maker
@@ -33,7 +34,7 @@
#ifdef _MSC_VER
#include <stdlib.h>
#define PATH_MAX _MAX_PATH
#endif//_MSC_VER
#endif // _MSC_VER
#ifndef _WIN32
#ifndef PATH_MAX

View File

@@ -16,7 +16,8 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* COPYRIGHT: See COPYING in the top level directory
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS hive maker
* FILE: tools/mkhive/mkhive.h
* PURPOSE: Hive maker
@@ -54,6 +55,7 @@ unsigned char BitScanReverse(ULONG * const Index, unsigned long Mask);
typedef DWORD REGSAM;
typedef LPVOID LPSECURITY_ATTRIBUTES;
typedef HANDLE HKEY, *PHKEY;
NTSTATUS NTAPI
RtlAnsiStringToUnicodeString(
@@ -122,8 +124,6 @@ RegOpenKeyW(
#define OBJ_NAME_PATH_SEPARATOR ((WCHAR)L'\\')
#define HIVE_NO_FILE 2
#define VERIFY_REGISTRY_HIVE(hive)
extern LIST_ENTRY CmiHiveListHead;
#define ABS_VALUE(V) (((V) < 0) ? -(V) : (V))
#define PAGED_CODE()

View File

@@ -16,7 +16,8 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* COPYRIGHT: See COPYING in the top level directory
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS hive maker
* FILE: tools/mkhive/registry.c
* PURPOSE: Registry code
@@ -25,9 +26,7 @@
/*
* TODO:
* - Implement RegDeleteKeyW()
* - Implement RegEnumValue()
* - Implement RegQueryValueExW()
* - Implement RegDeleteKeyW() and RegDeleteValueW()
*/
#include <stdlib.h>
@@ -37,9 +36,6 @@
#define NDEBUG
#include "mkhive.h"
#define REG_DATA_SIZE_MASK 0x7FFFFFFF
#define REG_DATA_IN_OFFSET 0x80000000
static CMHIVE RootHive;
static PMEMKEY RootKey;
CMHIVE DefaultHive; /* \Registry\User\.DEFAULT */
@@ -49,6 +45,291 @@ CMHIVE SoftwareHive; /* \Registry\Machine\SOFTWARE */
CMHIVE SystemHive; /* \Registry\Machine\SYSTEM */
CMHIVE BcdHive; /* \Registry\Machine\BCD00000000 */
//
// TODO: Write these values in a more human-readable form.
// See http://amnesia.gtisc.gatech.edu/~moyix/suzibandit.ltd.uk/MSc/Registry%20Structure%20-%20Appendices%20V4.pdf
// Appendix 12 "The Registry NT Security Descriptor" for more information.
//
// Those SECURITY_DESCRIPTORs were obtained by dumping the security block "sk"
// of registry hives created by setting their permissions to be the same as
// the ones of the BCD, SOFTWARE, or SYSTEM, SAM and .DEFAULT system hives.
// A cross-check was subsequently done with the system hives to verify that
// the security descriptors were the same.
//
UCHAR BcdSecurity[] =
{
// SECURITY_DESCRIPTOR_RELATIVE
0x01, // Revision
0x00, // Sbz1
0x04, 0x94, // Control: SE_SELF_RELATIVE (0x8000) |
// SE_DACL_PROTECTED (0x1000) |
// SE_DACL_AUTO_INHERITED (0x0400) |
// SE_DACL_PRESENT (0x0004)
0x48, 0x00, 0x00, 0x00, // Owner
0x58, 0x00, 0x00, 0x00, // Group
0x00, 0x00, 0x00, 0x00, // Sacl (None)
0x14, 0x00, 0x00, 0x00, // Dacl
// DACL
0x02, // AclRevision
0x00, // Sbz1
0x34, 0x00, // AclSize
0x02, 0x00, // AceCount
0x00, 0x00, // Sbz2
// (1st ACE)
0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE
0x02, // AceFlags: CONTAINER_INHERIT_ACE
0x18, 0x00, // AceSize
0x19, 0x00, 0x06, 0x00, // ACCESS_MASK: "Write DAC" (0x00040000) |
// "Read Control" (0x00020000) |
// "Notify" (0x00000010) |
// "Enumerate Subkeys" (0x00000008) |
// "Query Value" (0x00000001)
// (SidStart: S-1-5-32-544 "Administrators")
0x01, 0x02, 0x00, 0x00,
0x00, 0x00, 0x00, 0x05,
0x20, 0x00, 0x00, 0x00,
0x20, 0x02, 0x00, 0x00,
// (2nd ACE)
0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE
0x02, // AceFlags: CONTAINER_INHERIT_ACE
0x14, 0x00, // AceSize
0x3F, 0x00, 0x0F, 0x00, // ACCESS_MASK: "Full Control" (0x000F003F)
// (SidStart: S-1-5-18 "Local System")
0x01, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x05,
0x12, 0x00, 0x00, 0x00,
// Owner SID (S-1-5-32-544 "Administrators")
0x01, 0x02, 0x00, 0x00,
0x00, 0x00, 0x00, 0x05,
0x20, 0x00, 0x00, 0x00,
0x20, 0x02, 0x00, 0x00,
// Group SID (S-1-5-21-domain-513 "Domain Users")
0x01, 0x05, 0x00, 0x00,
0x00, 0x00, 0x00, 0x05,
0x15, 0x00, 0x00, 0x00,
0xAC, 0xD0, 0x49, 0xCB,
0xE6, 0x52, 0x47, 0x9C,
0xE4, 0x31, 0xDB, 0x5C,
0x01, 0x02, 0x00, 0x00
};
UCHAR SoftwareSecurity[] =
{
// SECURITY_DESCRIPTOR_RELATIVE
0x01, // Revision
0x00, // Sbz1
0x04, 0x94, // Control: SE_SELF_RELATIVE (0x8000) |
// SE_DACL_PROTECTED (0x1000) |
// SE_DACL_AUTO_INHERITED (0x0400) |
// SE_DACL_PRESENT (0x0004)
0xA0, 0x00, 0x00, 0x00, // Owner
0xB0, 0x00, 0x00, 0x00, // Group
0x00, 0x00, 0x00, 0x00, // Sacl (None)
0x14, 0x00, 0x00, 0x00, // Dacl
// DACL
0x02, // AclRevision
0x00, // Sbz1
0x8C, 0x00, // AclSize
0x06, 0x00, // AceCount
0x00, 0x00, // Sbz2
// (1st ACE)
0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE
0x02, // AceFlags: CONTAINER_INHERIT_ACE
0x18, 0x00, // AceSize
0x3F, 0x00, 0x0F, 0x00, // ACCESS_MASK: "Full Control" (0x000F003F)
// (SidStart: S-1-5-32-544 "Administrators")
0x01, 0x02, 0x00, 0x00,
0x00, 0x00, 0x00, 0x05,
0x20, 0x00, 0x00, 0x00,
0x20, 0x02, 0x00, 0x00,
// (2nd ACE)
0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE
0x0A, // AceFlags: INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE
0x14, 0x00, // AceSize
0x3F, 0x00, 0x0F, 0x00, // ACCESS_MASK: "Full Control" (0x000F003F)
// (SidStart: S-1-3-0 "Creator Owner")
0x01, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0x00,
// (3rd ACE)
0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE
0x02, // AceFlags: CONTAINER_INHERIT_ACE
0x14, 0x00, // AceSize
0x3F, 0x00, 0x0F, 0x00, // ACCESS_MASK: "Full Control" (0x000F003F)
// (SidStart: S-1-5-18 "Local System")
0x01, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x05,
0x12, 0x00, 0x00, 0x00,
// (4th ACE)
0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE
0x02, // AceFlags: CONTAINER_INHERIT_ACE
0x14, 0x00, // AceSize
0x1F, 0x00, 0x03, 0x00, // ACCESS_MASK: "Read Control" (0x00020000) |
// "Delete" (0x00010000) |
// "Notify" (0x00000010) |
// "Enumerate Subkeys" (0x00000008) |
// "Create Subkey" (0x00000004) |
// "Set Value" (0x00000002) |
// "Query Value" (0x00000001)
// (SidStart: S-1-5-13 "Terminal Server Users")
0x01, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x05,
0x0D, 0x00, 0x00, 0x00,
// (5th ACE)
0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE
0x02, // AceFlags: CONTAINER_INHERIT_ACE
0x18, 0x00, // AceSize
0x19, 0x00, 0x02, 0x00, // ACCESS_MASK: "Read Control" (0x00020000) |
// "Notify" (0x00000010) |
// "Enumerate Subkeys" (0x00000008) |
// "Query Value" (0x00000001)
// (SidStart: S-1-5-32-545 "Users")
0x01, 0x02, 0x00, 0x00,
0x00, 0x00, 0x00, 0x05,
0x20, 0x00, 0x00, 0x00,
0x21, 0x02, 0x00, 0x00,
// (6th ACE)
0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE
0x02, // AceFlags: CONTAINER_INHERIT_ACE
0x18, 0x00, // AceSize
0x1F, 0x00, 0x03, 0x00, // ACCESS_MASK: "Read Control" (0x00020000) |
// "Delete" (0x00010000) |
// "Notify" (0x00000010) |
// "Enumerate Subkeys" (0x00000008) |
// "Create Subkey" (0x00000004) |
// "Set Value" (0x00000002) |
// "Query Value" (0x00000001)
// (SidStart: S-1-5-32-547 "Power Users")
0x01, 0x02, 0x00, 0x00,
0x00, 0x00, 0x00, 0x05,
0x20, 0x00, 0x00, 0x00,
0x23, 0x02, 0x00, 0x00,
// Owner SID (S-1-5-32-544 "Administrators")
0x01, 0x02, 0x00, 0x00,
0x00, 0x00, 0x00, 0x05,
0x20, 0x00, 0x00, 0x00,
0x20, 0x02, 0x00, 0x00,
// Group SID (S-1-5-21-domain-513 "Domain Users")
0x01, 0x05, 0x00, 0x00,
0x00, 0x00, 0x00, 0x05,
0x15, 0x00, 0x00, 0x00,
0xAC, 0xD0, 0x49, 0xCB,
0xE6, 0x52, 0x47, 0x9C,
0xE4, 0x31, 0xDB, 0x5C,
0x01, 0x02, 0x00, 0x00
};
// Same security for SYSTEM, SAM and .DEFAULT
UCHAR SystemSecurity[] =
{
// SECURITY_DESCRIPTOR_RELATIVE
0x01, // Revision
0x00, // Sbz1
0x04, 0x94, // Control: SE_SELF_RELATIVE (0x8000) |
// SE_DACL_PROTECTED (0x1000) |
// SE_DACL_AUTO_INHERITED (0x0400) |
// SE_DACL_PRESENT (0x0004)
0x8C, 0x00, 0x00, 0x00, // Owner
0x9C, 0x00, 0x00, 0x00, // Group
0x00, 0x00, 0x00, 0x00, // Sacl (None)
0x14, 0x00, 0x00, 0x00, // Dacl
// DACL
0x02, // AclRevision
0x00, // Sbz1
0x78, 0x00, // AclSize
0x05, 0x00, // AceCount
0x00, 0x00, // Sbz2
// (1st ACE)
0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE
0x02, // AceFlags: CONTAINER_INHERIT_ACE
0x18, 0x00, // AceSize
0x3F, 0x00, 0x0F, 0x00, // ACCESS_MASK: "Full Control" (0x000F003F)
// (SidStart: S-1-5-32-544 "Administrators")
0x01, 0x02, 0x00, 0x00,
0x00, 0x00, 0x00, 0x05,
0x20, 0x00, 0x00, 0x00,
0x20, 0x02, 0x00, 0x00,
// (2nd ACE)
0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE
0x0A, // AceFlags: INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE
0x14, 0x00, // AceSize
0x3F, 0x00, 0x0F, 0x00, // ACCESS_MASK: "Full Control" (0x000F003F)
// (SidStart: S-1-3-0 "Creator Owner")
0x01, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0x00,
// (3rd ACE)
0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE
0x02, // AceFlags: CONTAINER_INHERIT_ACE
0x14, 0x00, // AceSize
0x3F, 0x00, 0x0F, 0x00, // ACCESS_MASK: "Full Control" (0x000F003F)
// (SidStart: S-1-5-18 "Local System")
0x01, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x05,
0x12, 0x00, 0x00, 0x00,
// (4th ACE)
0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE
0x02, // AceFlags: CONTAINER_INHERIT_ACE
0x18, 0x00, // AceSize
0x19, 0x00, 0x02, 0x00, // ACCESS_MASK: "Read Control" (0x00020000) |
// "Notify" (0x00000010) |
// "Enumerate Subkeys" (0x00000008) |
// "Query Value" (0x00000001)
// (SidStart: S-1-5-32-545 "Users")
0x01, 0x02, 0x00, 0x00,
0x00, 0x00, 0x00, 0x05,
0x20, 0x00, 0x00, 0x00,
0x21, 0x02, 0x00, 0x00,
// (5th ACE)
0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE
0x02, // AceFlags: CONTAINER_INHERIT_ACE
0x18, 0x00, // AceSize
0x19, 0x00, 0x02, 0x00, // ACCESS_MASK: "Read Control" (0x00020000) |
// "Notify" (0x00000010) |
// "Enumerate Subkeys" (0x00000008) |
// "Query Value" (0x00000001)
// (SidStart: S-1-5-32-547 "Power Users")
0x01, 0x02, 0x00, 0x00,
0x00, 0x00, 0x00, 0x05,
0x20, 0x00, 0x00, 0x00,
0x23, 0x02, 0x00, 0x00,
// Owner SID (S-1-5-32-544 "Administrators")
0x01, 0x02, 0x00, 0x00,
0x00, 0x00, 0x00, 0x05,
0x20, 0x00, 0x00, 0x00,
0x20, 0x02, 0x00, 0x00,
// Group SID (S-1-5-21-domain-513 "Domain Users")
0x01, 0x05, 0x00, 0x00,
0x00, 0x00, 0x00, 0x05,
0x15, 0x00, 0x00, 0x00,
0xAC, 0xD0, 0x49, 0xCB,
0xE6, 0x52, 0x47, 0x9C,
0xE4, 0x31, 0xDB, 0x5C,
0x01, 0x02, 0x00, 0x00
};
static PMEMKEY
CreateInMemoryStructure(
IN PCMHIVE RegistryHive,
@@ -56,7 +337,7 @@ CreateInMemoryStructure(
{
PMEMKEY Key;
Key = (PMEMKEY) malloc (sizeof(MEMKEY));
Key = (PMEMKEY)malloc(sizeof(MEMKEY));
if (!Key)
return NULL;
@@ -83,13 +364,14 @@ RegpOpenOrCreateKey(
PMEMKEY CurrentKey;
PCMHIVE ParentRegistryHive;
HCELL_INDEX ParentCellOffset;
PCM_KEY_NODE ParentKeyCell;
PLIST_ENTRY Ptr;
PCM_KEY_NODE SubKeyCell;
HCELL_INDEX BlockOffset;
DPRINT("RegpCreateOpenKey('%S')\n", KeyName);
if (*KeyName == L'\\')
if (*KeyName == OBJ_NAME_PATH_SEPARATOR)
{
KeyName++;
ParentRegistryHive = RootKey->RegistryHive;
@@ -102,14 +384,14 @@ RegpOpenOrCreateKey(
}
else
{
ParentRegistryHive = HKEY_TO_MEMKEY(RootKey)->RegistryHive;
ParentCellOffset = HKEY_TO_MEMKEY(RootKey)->KeyCellOffset;
ParentRegistryHive = HKEY_TO_MEMKEY(hParentKey)->RegistryHive;
ParentCellOffset = HKEY_TO_MEMKEY(hParentKey)->KeyCellOffset;
}
LocalKeyName = (PWSTR)KeyName;
for (;;)
{
End = (PWSTR)strchrW(LocalKeyName, '\\');
End = (PWSTR)strchrW(LocalKeyName, OBJ_NAME_PATH_SEPARATOR);
if (End)
{
KeyString.Buffer = LocalKeyName;
@@ -121,19 +403,22 @@ RegpOpenOrCreateKey(
RtlInitUnicodeString(&KeyString, LocalKeyName);
if (KeyString.Length == 0)
{
/* Trailing backslash char; we're done */
/* Trailing path separator: we're done */
break;
}
}
Status = CmiScanForSubKey(ParentRegistryHive,
ParentCellOffset,
&KeyString,
OBJ_CASE_INSENSITIVE,
&SubKeyCell,
&BlockOffset);
if (NT_SUCCESS(Status))
ParentKeyCell = (PCM_KEY_NODE)HvGetCell(&ParentRegistryHive->Hive, ParentCellOffset);
if (!ParentKeyCell)
return STATUS_UNSUCCESSFUL;
VERIFY_KEY_CELL(ParentKeyCell);
BlockOffset = CmpFindSubKeyByName(&ParentRegistryHive->Hive, ParentKeyCell, &KeyString);
if (BlockOffset != HCELL_NIL)
{
Status = STATUS_SUCCESS;
/* Search for a possible reparse point */
Ptr = CmiReparsePointsHead.Flink;
while (Ptr != &CmiReparsePointsHead)
@@ -149,19 +434,20 @@ RegpOpenOrCreateKey(
Ptr = Ptr->Flink;
}
}
else if (Status == STATUS_OBJECT_NAME_NOT_FOUND && AllowCreation)
else if (AllowCreation) // && (BlockOffset == HCELL_NIL)
{
Status = CmiAddSubKey(ParentRegistryHive,
ParentCellOffset,
&KeyString,
Volatile ? REG_OPTION_VOLATILE : 0,
&SubKeyCell,
Volatile,
&BlockOffset);
}
HvReleaseCell(&ParentRegistryHive->Hive, ParentCellOffset);
if (!NT_SUCCESS(Status))
return ERROR_UNSUCCESSFUL;
nextsubkey:
ParentCellOffset = BlockOffset;
if (End)
LocalKeyName = End + 1;
@@ -172,6 +458,7 @@ nextsubkey:
CurrentKey = CreateInMemoryStructure(ParentRegistryHive, ParentCellOffset);
if (!CurrentKey)
return ERROR_OUTOFMEMORY;
*Key = MEMKEY_TO_HKEY(CurrentKey);
return ERROR_SUCCESS;
@@ -186,56 +473,16 @@ RegCreateKeyW(
return RegpOpenOrCreateKey(hKey, lpSubKey, TRUE, FALSE, phkResult);
}
static PWSTR
MultiByteToWideChar(
IN PCSTR MultiByteString)
{
ANSI_STRING Source;
UNICODE_STRING Destination;
NTSTATUS Status;
RtlInitAnsiString(&Source, MultiByteString);
Status = RtlAnsiStringToUnicodeString(&Destination, &Source, TRUE);
if (!NT_SUCCESS(Status))
return NULL;
return Destination.Buffer;
}
LONG WINAPI
RegDeleteKeyW(
IN HKEY hKey,
IN LPCWSTR lpSubKey)
{
DPRINT1("FIXME: implement RegDeleteKeyW!\n");
DPRINT1("RegDeleteKeyW(0x%p, '%S') is UNIMPLEMENTED!\n",
hKey, (lpSubKey ? lpSubKey : L""));
return ERROR_SUCCESS;
}
LONG WINAPI
RegDeleteKeyA(
IN HKEY hKey,
IN LPCSTR lpSubKey)
{
PWSTR lpSubKeyW = NULL;
LONG rc;
if (lpSubKey != NULL && strchr(lpSubKey, '\\') != NULL)
return ERROR_INVALID_PARAMETER;
if (lpSubKey)
{
lpSubKeyW = MultiByteToWideChar(lpSubKey);
if (!lpSubKeyW)
return ERROR_OUTOFMEMORY;
}
rc = RegDeleteKeyW(hKey, lpSubKeyW);
if (lpSubKey)
free(lpSubKeyW);
return rc;
}
LONG WINAPI
RegOpenKeyW(
IN HKEY hKey,
@@ -264,57 +511,6 @@ RegCreateKeyExW(
phkResult);
}
LONG WINAPI
RegOpenKeyA(
IN HKEY hKey,
IN LPCSTR lpSubKey,
OUT PHKEY phkResult)
{
PWSTR lpSubKeyW;
LONG rc;
lpSubKeyW = MultiByteToWideChar(lpSubKey);
if (!lpSubKeyW)
return ERROR_OUTOFMEMORY;
rc = RegOpenKeyW(hKey, lpSubKeyW, phkResult);
free(lpSubKeyW);
return rc;
}
static LONG
RegpOpenOrCreateValue(
IN HKEY hKey,
IN LPCWSTR ValueName,
IN BOOL AllowCreation,
OUT PCM_KEY_VALUE *ValueCell,
OUT PHCELL_INDEX ValueCellOffset)
{
PMEMKEY ParentKey;
UNICODE_STRING ValueString;
NTSTATUS Status;
ParentKey = HKEY_TO_MEMKEY(hKey);
RtlInitUnicodeString(&ValueString, ValueName);
Status = CmiScanForValueKey(ParentKey->RegistryHive,
ParentKey->KeyCellOffset,
&ValueString,
ValueCell,
ValueCellOffset);
if (AllowCreation && Status == STATUS_OBJECT_NAME_NOT_FOUND)
{
Status = CmiAddValueKey(ParentKey->RegistryHive,
ParentKey->KeyCellOffset,
&ValueString,
ValueCell,
ValueCellOffset);
}
if (!NT_SUCCESS(Status))
return ERROR_UNSUCCESSFUL;
return ERROR_SUCCESS;
}
LONG WINAPI
RegSetValueExW(
IN HKEY hKey,
@@ -324,49 +520,84 @@ RegSetValueExW(
IN const UCHAR* lpData,
IN USHORT cbData)
{
PMEMKEY Key, DestKey;
PHKEY phKey;
PMEMKEY Key = HKEY_TO_MEMKEY(hKey); // ParentKey
PHHIVE Hive;
PCM_KEY_NODE KeyNode; // ParentNode
PCM_KEY_VALUE ValueCell;
HCELL_INDEX ValueCellOffset;
HCELL_INDEX CellIndex;
UNICODE_STRING ValueNameString;
PVOID DataCell;
LONG DataCellSize;
NTSTATUS Status;
if (dwType == REG_LINK)
{
PMEMKEY DestKey;
/* Special handling of registry links */
if (cbData != sizeof(PVOID))
return STATUS_INVALID_PARAMETER;
phKey = (PHKEY)lpData;
Key = HKEY_TO_MEMKEY(hKey);
DestKey = HKEY_TO_MEMKEY(*phKey);
DestKey = HKEY_TO_MEMKEY(*(PHKEY)lpData);
// FIXME: Add additional checks for the validity of DestKey
/* Create the link in registry hive (if applicable) */
if (Key->RegistryHive != DestKey->RegistryHive)
return STATUS_SUCCESS;
DPRINT1("Save link to registry\n");
return STATUS_NOT_IMPLEMENTED;
}
if ((cbData & REG_DATA_SIZE_MASK) != cbData)
if ((cbData & ~CM_KEY_VALUE_SPECIAL_SIZE) != cbData)
return STATUS_UNSUCCESSFUL;
Key = HKEY_TO_MEMKEY(hKey);
Hive = &Key->RegistryHive->Hive;
KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Key->KeyCellOffset);
if (!KeyNode)
return ERROR_UNSUCCESSFUL;
ASSERT(KeyNode->Signature == CM_KEY_NODE_SIGNATURE);
/* Mark the parent as dirty since we are going to create a new value in it */
HvMarkCellDirty(Hive, Key->KeyCellOffset, FALSE);
/* Initialize value name string */
RtlInitUnicodeString(&ValueNameString, lpValueName);
CellIndex = CmpFindValueByName(Hive, KeyNode, &ValueNameString);
if (CellIndex == HCELL_NIL)
{
/* The value doesn't exist, create a new one */
Status = CmiAddValueKey(Key->RegistryHive,
KeyNode,
&ValueNameString,
&ValueCell,
&CellIndex);
}
else
{
/* The value already exists, use it. Get the value cell. */
ValueCell = HvGetCell(&Key->RegistryHive->Hive, CellIndex);
ASSERT(ValueCell != NULL);
}
// /**/HvReleaseCell(Hive, CellIndex);/**/
Status = RegpOpenOrCreateValue(hKey, lpValueName, TRUE, &ValueCell, &ValueCellOffset);
if (!NT_SUCCESS(Status))
return ERROR_UNSUCCESSFUL;
/* Get size of the allocated cellule (if any) */
if (!(ValueCell->DataLength & REG_DATA_IN_OFFSET) &&
(ValueCell->DataLength & REG_DATA_SIZE_MASK) != 0)
/* Get size of the allocated cell (if any) */
if (!(ValueCell->DataLength & CM_KEY_VALUE_SPECIAL_SIZE) &&
(ValueCell->DataLength & ~CM_KEY_VALUE_SPECIAL_SIZE) != 0)
{
DataCell = HvGetCell(&Key->RegistryHive->Hive, ValueCell->Data);
DataCell = HvGetCell(Hive, ValueCell->Data);
if (!DataCell)
return ERROR_UNSUCCESSFUL;
DataCellSize = -HvGetCellSize(&Key->RegistryHive->Hive, DataCell);
DataCellSize = -HvGetCellSize(Hive, DataCell);
}
else
{
@@ -379,12 +610,11 @@ RegSetValueExW(
/* If data size <= sizeof(HCELL_INDEX) then store data in the data offset */
DPRINT("ValueCell->DataLength %u\n", ValueCell->DataLength);
if (DataCell)
HvFreeCell(&Key->RegistryHive->Hive, ValueCell->Data);
HvFreeCell(Hive, ValueCell->Data);
RtlCopyMemory(&ValueCell->Data, lpData, cbData);
ValueCell->DataLength = (ULONG)(cbData | REG_DATA_IN_OFFSET);
ValueCell->DataLength = (ULONG)(cbData | CM_KEY_VALUE_SPECIAL_SIZE);
ValueCell->Type = dwType;
HvMarkCellDirty(&Key->RegistryHive->Hive, ValueCellOffset, FALSE);
}
else
{
@@ -396,7 +626,7 @@ RegSetValueExW(
DPRINT("ValueCell->DataLength %u\n", ValueCell->DataLength);
NewOffset = HvAllocateCell(&Key->RegistryHive->Hive, cbData, Stable, HCELL_NIL);
NewOffset = HvAllocateCell(Hive, cbData, Stable, HCELL_NIL);
if (NewOffset == HCELL_NIL)
{
DPRINT("HvAllocateCell() failed with status 0x%08x\n", Status);
@@ -404,52 +634,114 @@ RegSetValueExW(
}
if (DataCell)
HvFreeCell(&Key->RegistryHive->Hive, ValueCell->Data);
HvFreeCell(Hive, ValueCell->Data);
ValueCell->Data = NewOffset;
DataCell = (PVOID)HvGetCell(&Key->RegistryHive->Hive, NewOffset);
DataCell = (PVOID)HvGetCell(Hive, NewOffset);
}
/* Copy new contents to cellule */
/* Copy new contents to cell */
RtlCopyMemory(DataCell, lpData, cbData);
ValueCell->DataLength = (ULONG)(cbData & REG_DATA_SIZE_MASK);
ValueCell->DataLength = (ULONG)(cbData & ~CM_KEY_VALUE_SPECIAL_SIZE);
ValueCell->Type = dwType;
HvMarkCellDirty(&Key->RegistryHive->Hive, ValueCell->Data, FALSE);
HvMarkCellDirty(&Key->RegistryHive->Hive, ValueCellOffset, FALSE);
HvMarkCellDirty(Hive, ValueCell->Data, FALSE);
}
HvMarkCellDirty(&Key->RegistryHive->Hive, Key->KeyCellOffset, FALSE);
HvMarkCellDirty(Hive, CellIndex, FALSE);
/* Check if the maximum value name length changed, update it if so */
if (KeyNode->MaxValueNameLen < ValueNameString.Length)
KeyNode->MaxValueNameLen = ValueNameString.Length;
/* Check if the maximum data length changed, update it if so */
if (KeyNode->MaxValueDataLen < cbData)
KeyNode->MaxValueDataLen = cbData;
/* Save the write time */
KeQuerySystemTime(&KeyNode->LastWriteTime);
DPRINT("Return status 0x%08x\n", Status);
return Status;
}
// Synced with freeldr/windows/registry.c
static
VOID
RepGetValueData(
IN PHHIVE Hive,
IN PCM_KEY_VALUE ValueCell,
OUT ULONG* Type OPTIONAL,
OUT PUCHAR Data OPTIONAL,
IN OUT ULONG* DataSize OPTIONAL)
{
ULONG DataLength;
PVOID DataCell;
/* Does the caller want the type? */
if (Type != NULL)
*Type = ValueCell->Type;
/* Does the caller provide DataSize? */
if (DataSize != NULL)
{
// NOTE: CmpValueToData doesn't support big data (the function will
// bugcheck if so), FreeLdr is not supposed to read such data.
// If big data is needed, use instead CmpGetValueData.
// CmpGetValueData(Hive, ValueCell, DataSize, &DataCell, ...);
DataCell = CmpValueToData(Hive, ValueCell, &DataLength);
/* Does the caller want the data? */
if ((Data != NULL) && (*DataSize != 0))
{
RtlCopyMemory(Data,
DataCell,
min(*DataSize, DataLength));
}
/* Return the actual data length */
*DataSize = DataLength;
}
}
// Similar to RegQueryValue in freeldr/windows/registry.c
LONG WINAPI
RegQueryValueExW(
IN HKEY hKey,
IN LPCWSTR lpValueName,
IN PULONG lpReserved,
OUT PULONG lpType,
OUT PUCHAR lpData,
OUT PSIZE_T lpcbData)
OUT PULONG lpType OPTIONAL,
OUT PUCHAR lpData OPTIONAL,
IN OUT PSIZE_T lpcbData OPTIONAL)
{
//ParentKey = HKEY_TO_MEMKEY(RootKey);
PMEMKEY ParentKey = HKEY_TO_MEMKEY(hKey);
PHHIVE Hive = &ParentKey->RegistryHive->Hive;
PCM_KEY_NODE KeyNode;
PCM_KEY_VALUE ValueCell;
HCELL_INDEX ValueCellOffset;
LONG rc;
HCELL_INDEX CellIndex;
UNICODE_STRING ValueNameString;
rc = RegpOpenOrCreateValue(hKey,
lpValueName,
FALSE,
&ValueCell,
&ValueCellOffset);
if (rc != ERROR_SUCCESS)
return rc;
KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, ParentKey->KeyCellOffset);
if (!KeyNode)
return ERROR_UNSUCCESSFUL;
DPRINT1("RegQueryValueExW(%S) not implemented\n", lpValueName);
/* ValueCell and ValueCellOffset are valid */
ASSERT(KeyNode->Signature == CM_KEY_NODE_SIGNATURE);
return ERROR_UNSUCCESSFUL;
/* Initialize value name string */
RtlInitUnicodeString(&ValueNameString, lpValueName);
CellIndex = CmpFindValueByName(Hive, KeyNode, &ValueNameString);
if (CellIndex == HCELL_NIL)
return ERROR_FILE_NOT_FOUND;
/* Get the value cell */
ValueCell = HvGetCell(Hive, CellIndex);
ASSERT(ValueCell != NULL);
RepGetValueData(Hive, ValueCell, lpType, lpData, lpcbData);
HvReleaseCell(Hive, CellIndex);
return ERROR_SUCCESS;
}
LONG WINAPI
@@ -457,14 +749,18 @@ RegDeleteValueW(
IN HKEY hKey,
IN LPCWSTR lpValueName OPTIONAL)
{
DPRINT1("RegDeleteValueW() unimplemented\n");
DPRINT1("RegDeleteValueW(0x%p, '%S') is UNIMPLEMENTED!\n",
hKey, (lpValueName ? lpValueName : L""));
return ERROR_UNSUCCESSFUL;
}
static BOOL
ConnectRegistry(
IN HKEY RootKey,
IN PCMHIVE HiveToConnect,
IN PUCHAR Descriptor,
IN ULONG DescriptorLength,
IN LPCWSTR Path)
{
NTSTATUS Status;
@@ -476,14 +772,32 @@ ConnectRegistry(
if (!ReparsePoint)
return FALSE;
Status = CmiInitializeTempHive(HiveToConnect);
/*
* Use a dummy root key name:
* - On 2k/XP/2k3, this is "$$$PROTO.HIV"
* - On Vista+, this is "CMI-CreateHive{guid}"
* See https://github.com/libyal/winreg-kb/blob/master/documentation/Registry%20files.asciidoc
* for more information.
*/
Status = CmiInitializeHive(HiveToConnect, L"$$$PROTO.HIV");
if (!NT_SUCCESS(Status))
{
DPRINT1("CmiInitializeTempHive() failed with status 0x%08x\n", Status);
DPRINT1("CmiInitializeHive() failed with status 0x%08x\n", Status);
free(ReparsePoint);
return FALSE;
}
/*
* Add security to the root key.
* NOTE: One can implement this using the lpSecurityAttributes
* parameter of RegCreateKeyExW.
*/
Status = CmiCreateSecurityKey(&HiveToConnect->Hive,
HiveToConnect->Hive.BaseBlock->RootCell,
Descriptor, DescriptorLength);
if (!NT_SUCCESS(Status))
DPRINT1("Failed to add security for root key '%S'\n", Path);
/* Create key */
rc = RegCreateKeyExW(RootKey,
Path,
@@ -523,10 +837,10 @@ RegInitializeRegistry(VOID)
InitializeListHead(&CmiHiveListHead);
InitializeListHead(&CmiReparsePointsHead);
Status = CmiInitializeTempHive(&RootHive);
Status = CmiInitializeHive(&RootHive, L"");
if (!NT_SUCCESS(Status))
{
DPRINT1("CmiInitializeTempHive() failed with status 0x%08x\n", Status);
DPRINT1("CmiInitializeHive() failed with status 0x%08x\n", Status);
return;
}
@@ -536,31 +850,37 @@ RegInitializeRegistry(VOID)
/* Create DEFAULT key */
ConnectRegistry(NULL,
&DefaultHive,
SystemSecurity, sizeof(SystemSecurity),
L"Registry\\User\\.DEFAULT");
/* Create SAM key */
ConnectRegistry(NULL,
&SamHive,
SystemSecurity, sizeof(SystemSecurity),
L"Registry\\Machine\\SAM");
/* Create SECURITY key */
ConnectRegistry(NULL,
&SecurityHive,
NULL, 0,
L"Registry\\Machine\\SECURITY");
/* Create SOFTWARE key */
ConnectRegistry(NULL,
&SoftwareHive,
SoftwareSecurity, sizeof(SoftwareSecurity),
L"Registry\\Machine\\SOFTWARE");
/* Create BCD key */
ConnectRegistry(NULL,
&BcdHive,
BcdSecurity, sizeof(BcdSecurity),
L"Registry\\Machine\\BCD00000000");
/* Create SYSTEM key */
ConnectRegistry(NULL,
&SystemHive,
SystemSecurity, sizeof(SystemSecurity),
L"Registry\\Machine\\SYSTEM");
/* Create 'ControlSet001' key */

View File

@@ -1,4 +1,5 @@
/* COPYRIGHT: See COPYING in the top level directory
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS hive maker
* FILE: tools/mkhive/rtl.c
* PURPOSE: Runtime Library
@@ -217,6 +218,23 @@ RtlAssert(PVOID FailedAssertion,
//DbgBreakPoint();
}
// DECLSPEC_NORETURN
VOID
NTAPI
KeBugCheckEx(
IN ULONG BugCheckCode,
IN ULONG_PTR BugCheckParameter1,
IN ULONG_PTR BugCheckParameter2,
IN ULONG_PTR BugCheckParameter3,
IN ULONG_PTR BugCheckParameter4)
{
char Buffer[70];
printf("*** STOP: 0x%08lX (0x%08lX, 0x%08lX, 0x%08lX, 0x%08lX)",
BugCheckCode, BugCheckParameter1, BugCheckParameter2,
BugCheckParameter3, BugCheckParameter4);
ASSERT(FALSE);
}
unsigned char BitScanForward(ULONG * Index, unsigned long Mask)
{
*Index = 0;