mirror of
https://github.com/reactos/reactos.git
synced 2026-06-01 17:00:51 +08:00
[MKHIVE]
- 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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user