mirror of
https://github.com/reactos/reactos.git
synced 2025-07-31 10:01:43 +00:00
* Create a branch for USB experiments.
svn path=/branches/usb-experiments/; revision=72629
This commit is contained in:
parent
28d8ba0d3e
commit
0ee830d7a4
23049 changed files with 0 additions and 1313991 deletions
18
sdk/tools/mkhive/CMakeLists.txt
Normal file
18
sdk/tools/mkhive/CMakeLists.txt
Normal file
|
@ -0,0 +1,18 @@
|
|||
|
||||
add_definitions(-DMKHIVE_HOST)
|
||||
|
||||
include_directories(
|
||||
${REACTOS_SOURCE_DIR}/sdk/lib/inflib
|
||||
${REACTOS_SOURCE_DIR}/sdk/lib/cmlib
|
||||
${REACTOS_SOURCE_DIR}/sdk/lib/rtl)
|
||||
|
||||
list(APPEND SOURCE
|
||||
binhive.c
|
||||
cmi.c
|
||||
mkhive.c
|
||||
reginf.c
|
||||
registry.c
|
||||
rtl.c)
|
||||
|
||||
add_host_tool(mkhive ${SOURCE})
|
||||
target_link_libraries(mkhive unicode cmlibhost inflibhost)
|
59
sdk/tools/mkhive/binhive.c
Normal file
59
sdk/tools/mkhive/binhive.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* ReactOS kernel
|
||||
* Copyright (C) 2006 ReactOS Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* 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
|
||||
* PROJECT: ReactOS hive maker
|
||||
* FILE: tools/mkhive/binhive.c
|
||||
* PURPOSE: Binary hive export code
|
||||
* PROGRAMMER: Hervé Poussineau
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "mkhive.h"
|
||||
|
||||
BOOL
|
||||
ExportBinaryHive(
|
||||
IN PCSTR FileName,
|
||||
IN PCMHIVE Hive)
|
||||
{
|
||||
FILE *File;
|
||||
BOOL ret;
|
||||
|
||||
printf (" Creating binary hive: %s\n", FileName);
|
||||
|
||||
/* Create new hive file */
|
||||
File = fopen (FileName, "w+b");
|
||||
if (File == NULL)
|
||||
{
|
||||
printf(" Error creating/opening file\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fseek (File, 0, SEEK_SET);
|
||||
|
||||
Hive->FileHandles[HFILE_TYPE_PRIMARY] = (HANDLE)File;
|
||||
ret = HvWriteHive(&Hive->Hive);
|
||||
fclose (File);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* EOF */
|
34
sdk/tools/mkhive/binhive.h
Normal file
34
sdk/tools/mkhive/binhive.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* ReactOS kernel
|
||||
* Copyright (C) 2006 ReactOS Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* 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
|
||||
* PROJECT: ReactOS hive maker
|
||||
* FILE: tools/mkhive/binhive.h
|
||||
* PURPOSE: Binary hive export code
|
||||
* PROGRAMMER: Hervé Poussineau
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
BOOL
|
||||
ExportBinaryHive(
|
||||
IN PCSTR FileName,
|
||||
IN PCMHIVE Hive);
|
||||
|
||||
/* EOF */
|
448
sdk/tools/mkhive/cmi.c
Normal file
448
sdk/tools/mkhive/cmi.c
Normal file
|
@ -0,0 +1,448 @@
|
|||
/*
|
||||
* ReactOS kernel
|
||||
* Copyright (C) 2006 ReactOS Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* 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
|
||||
* PROJECT: ReactOS hive maker
|
||||
* FILE: tools/mkhive/cmi.c
|
||||
* PURPOSE: Registry file manipulation routines
|
||||
* PROGRAMMER: Hervé Poussineau
|
||||
*/
|
||||
|
||||
#define NDEBUG
|
||||
#include "mkhive.h"
|
||||
|
||||
PVOID
|
||||
NTAPI
|
||||
CmpAllocate(
|
||||
IN SIZE_T Size,
|
||||
IN BOOLEAN Paged,
|
||||
IN ULONG Tag)
|
||||
{
|
||||
return (PVOID)malloc((size_t)Size);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CmpFree(
|
||||
IN PVOID Ptr,
|
||||
IN ULONG Quota)
|
||||
{
|
||||
free(Ptr);
|
||||
}
|
||||
|
||||
static BOOLEAN
|
||||
NTAPI
|
||||
CmpFileRead(
|
||||
IN PHHIVE RegistryHive,
|
||||
IN ULONG FileType,
|
||||
IN PULONG FileOffset,
|
||||
OUT PVOID Buffer,
|
||||
IN SIZE_T BufferLength)
|
||||
{
|
||||
DPRINT1("CmpFileRead() unimplemented\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOLEAN
|
||||
NTAPI
|
||||
CmpFileWrite(
|
||||
IN PHHIVE RegistryHive,
|
||||
IN ULONG FileType,
|
||||
IN PULONG FileOffset,
|
||||
IN PVOID Buffer,
|
||||
IN SIZE_T BufferLength)
|
||||
{
|
||||
PCMHIVE CmHive = (PCMHIVE)RegistryHive;
|
||||
FILE *File = CmHive->FileHandles[HFILE_TYPE_PRIMARY];
|
||||
if (fseek(File, *FileOffset, SEEK_SET) != 0)
|
||||
return FALSE;
|
||||
|
||||
return (fwrite(Buffer, 1, BufferLength, File) == BufferLength);
|
||||
}
|
||||
|
||||
static BOOLEAN
|
||||
NTAPI
|
||||
CmpFileSetSize(
|
||||
IN PHHIVE RegistryHive,
|
||||
IN ULONG FileType,
|
||||
IN ULONG FileSize,
|
||||
IN ULONG OldFileSize)
|
||||
{
|
||||
DPRINT1("CmpFileSetSize() unimplemented\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOLEAN
|
||||
NTAPI
|
||||
CmpFileFlush(
|
||||
IN PHHIVE RegistryHive,
|
||||
IN ULONG FileType,
|
||||
PLARGE_INTEGER FileOffset,
|
||||
ULONG Length)
|
||||
{
|
||||
PCMHIVE CmHive = (PCMHIVE)RegistryHive;
|
||||
FILE *File = CmHive->FileHandles[HFILE_TYPE_PRIMARY];
|
||||
return (fflush(File) == 0);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
CmiInitializeHive(
|
||||
IN OUT PCMHIVE Hive,
|
||||
IN PCWSTR Name)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
RtlZeroMemory(Hive, sizeof(*Hive));
|
||||
|
||||
DPRINT("Hive 0x%p\n", Hive);
|
||||
|
||||
Status = HvInitialize(&Hive->Hive,
|
||||
HINIT_CREATE,
|
||||
HIVE_NOLAZYFLUSH,
|
||||
HFILE_TYPE_PRIMARY,
|
||||
0,
|
||||
CmpAllocate,
|
||||
CmpFree,
|
||||
CmpFileSetSize,
|
||||
CmpFileWrite,
|
||||
CmpFileRead,
|
||||
CmpFileFlush,
|
||||
1,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
// HACK: See the HACK from r31253
|
||||
if (!CmCreateRootNode(&Hive->Hive, Name))
|
||||
{
|
||||
HvFree(&Hive->Hive);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* Add the new hive to the hive list */
|
||||
InsertTailList(&CmiHiveListHead,
|
||||
&Hive->HiveList);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
CmiCreateSecurityKey(
|
||||
IN PHHIVE Hive,
|
||||
IN HCELL_INDEX Cell,
|
||||
IN PUCHAR Descriptor,
|
||||
IN ULONG DescriptorLength)
|
||||
{
|
||||
HCELL_INDEX SecurityCell;
|
||||
PCM_KEY_NODE Node;
|
||||
PCM_KEY_SECURITY Security;
|
||||
|
||||
Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
|
||||
SecurityCell = HvAllocateCell(Hive,
|
||||
FIELD_OFFSET(CM_KEY_SECURITY, Descriptor) +
|
||||
DescriptorLength,
|
||||
Stable,
|
||||
HCELL_NIL);
|
||||
if (SecurityCell == HCELL_NIL)
|
||||
{
|
||||
HvReleaseCell(Hive, Cell);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
Node->Security = SecurityCell;
|
||||
Security = (PCM_KEY_SECURITY)HvGetCell(Hive, SecurityCell);
|
||||
Security->Signature = CM_KEY_SECURITY_SIGNATURE;
|
||||
Security->ReferenceCount = 1;
|
||||
Security->DescriptorLength = DescriptorLength;
|
||||
|
||||
RtlMoveMemory(&Security->Descriptor,
|
||||
Descriptor,
|
||||
DescriptorLength);
|
||||
|
||||
Security->Flink = Security->Blink = SecurityCell;
|
||||
|
||||
HvReleaseCell(Hive, SecurityCell);
|
||||
HvReleaseCell(Hive, Cell);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS
|
||||
CmiCreateSubKey(
|
||||
IN PCMHIVE RegistryHive,
|
||||
IN HCELL_INDEX ParentKeyCellOffset,
|
||||
IN PCUNICODE_STRING SubKeyName,
|
||||
IN BOOLEAN VolatileKey,
|
||||
OUT HCELL_INDEX* pNKBOffset)
|
||||
{
|
||||
HCELL_INDEX NKBOffset;
|
||||
PCM_KEY_NODE NewKeyCell;
|
||||
UNICODE_STRING KeyName;
|
||||
HSTORAGE_TYPE Storage;
|
||||
|
||||
/* Skip leading path separator if present */
|
||||
if (SubKeyName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
|
||||
{
|
||||
KeyName.Buffer = &SubKeyName->Buffer[1];
|
||||
KeyName.Length = KeyName.MaximumLength = SubKeyName->Length - sizeof(WCHAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
KeyName = *SubKeyName;
|
||||
}
|
||||
|
||||
Storage = (VolatileKey ? Volatile : Stable);
|
||||
|
||||
NKBOffset = HvAllocateCell(&RegistryHive->Hive,
|
||||
FIELD_OFFSET(CM_KEY_NODE, Name) +
|
||||
CmpNameSize(&RegistryHive->Hive, &KeyName),
|
||||
Storage,
|
||||
HCELL_NIL);
|
||||
if (NKBOffset == HCELL_NIL)
|
||||
{
|
||||
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
|
||||
{
|
||||
/* Get the parent node */
|
||||
PCM_KEY_NODE ParentKeyCell;
|
||||
ParentKeyCell = (PCM_KEY_NODE)HvGetCell(&RegistryHive->Hive, ParentKeyCellOffset);
|
||||
|
||||
if (ParentKeyCell)
|
||||
{
|
||||
/* Inherit the security block of the parent */
|
||||
NewKeyCell->Security = ParentKeyCell->Security;
|
||||
if (NewKeyCell->Security != HCELL_NIL)
|
||||
{
|
||||
PCM_KEY_SECURITY Security;
|
||||
Security = (PCM_KEY_SECURITY)HvGetCell(&RegistryHive->Hive, NewKeyCell->Security);
|
||||
++Security->ReferenceCount;
|
||||
HvReleaseCell(&RegistryHive->Hive, NewKeyCell->Security);
|
||||
}
|
||||
|
||||
HvReleaseCell(&RegistryHive->Hive, ParentKeyCellOffset);
|
||||
}
|
||||
}
|
||||
|
||||
HvReleaseCell(&RegistryHive->Hive, NKBOffset);
|
||||
|
||||
*pNKBOffset = NKBOffset;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
CmiAddSubKey(
|
||||
IN PCMHIVE RegistryHive,
|
||||
IN HCELL_INDEX ParentKeyCellOffset,
|
||||
IN PCUNICODE_STRING SubKeyName,
|
||||
IN BOOLEAN VolatileKey,
|
||||
OUT HCELL_INDEX *pBlockOffset)
|
||||
{
|
||||
PCM_KEY_NODE ParentKeyCell;
|
||||
HCELL_INDEX NKBOffset;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Create the new key */
|
||||
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);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
CmiAddValueKey(
|
||||
IN PCMHIVE RegistryHive,
|
||||
IN PCM_KEY_NODE Parent,
|
||||
IN PCUNICODE_STRING ValueName,
|
||||
OUT PCM_KEY_VALUE *pValueCell,
|
||||
OUT HCELL_INDEX *pValueCellOffset)
|
||||
{
|
||||
PCELL_DATA ValueListCell;
|
||||
PCM_KEY_VALUE NewValueCell;
|
||||
HCELL_INDEX ValueListCellOffset;
|
||||
HCELL_INDEX NewValueCellOffset;
|
||||
ULONG CellSize;
|
||||
HSTORAGE_TYPE Storage;
|
||||
|
||||
#ifndef FIELD_SIZE
|
||||
#define FIELD_SIZE(type, field) (sizeof(((type *)0)->field))
|
||||
#endif
|
||||
|
||||
Storage = (Parent->Flags & KEY_IS_VOLATILE) ? Volatile : Stable;
|
||||
if (Parent->ValueList.List == HCELL_NIL)
|
||||
{
|
||||
/* Allocate some room for the value list */
|
||||
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 = (PCELL_DATA)HvGetCell(&RegistryHive->Hive, ValueListCellOffset);
|
||||
if (!ValueListCell)
|
||||
{
|
||||
HvFreeCell(&RegistryHive->Hive, ValueListCellOffset);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
Parent->ValueList.List = ValueListCellOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
ValueListCell = (PCELL_DATA)HvGetCell(&RegistryHive->Hive, Parent->ValueList.List);
|
||||
if (!ValueListCell)
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
|
||||
CellSize = ABS_VALUE(HvGetCellSize(&RegistryHive->Hive, ValueListCell));
|
||||
|
||||
if (Parent->ValueList.Count >= CellSize / sizeof(HCELL_INDEX))
|
||||
{
|
||||
CellSize *= 2;
|
||||
ValueListCellOffset = HvReallocateCell(&RegistryHive->Hive, Parent->ValueList.List, CellSize);
|
||||
if (ValueListCellOffset == HCELL_NIL)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
ValueListCell = (PCELL_DATA)HvGetCell(&RegistryHive->Hive, ValueListCellOffset);
|
||||
if (!ValueListCell)
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
|
||||
Parent->ValueList.List = ValueListCellOffset;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NewValueCellOffset = HvAllocateCell(&RegistryHive->Hive,
|
||||
FIELD_OFFSET(CM_KEY_VALUE, Name) +
|
||||
CmpNameSize(&RegistryHive->Hive, (PUNICODE_STRING)ValueName),
|
||||
Storage,
|
||||
HCELL_NIL);
|
||||
if (NewValueCellOffset == HCELL_NIL)
|
||||
{
|
||||
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
|
||||
{
|
||||
/* No flags to set */
|
||||
NewValueCell->Flags = 0;
|
||||
}
|
||||
|
||||
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;
|
||||
*pValueCellOffset = NewValueCellOffset;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
55
sdk/tools/mkhive/cmi.h
Normal file
55
sdk/tools/mkhive/cmi.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* ReactOS kernel
|
||||
* Copyright (C) 2006 ReactOS Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* 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
|
||||
* PROJECT: ReactOS hive maker
|
||||
* FILE: tools/mkhive/cmi.h
|
||||
* PURPOSE: Registry file manipulation routines
|
||||
* PROGRAMMER: Hervé Poussineau
|
||||
*/
|
||||
|
||||
#define VERIFY_KEY_CELL(key)
|
||||
|
||||
NTSTATUS
|
||||
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 BOOLEAN VolatileKey,
|
||||
OUT HCELL_INDEX *pBlockOffset);
|
||||
|
||||
NTSTATUS
|
||||
CmiAddValueKey(
|
||||
IN PCMHIVE RegistryHive,
|
||||
IN PCM_KEY_NODE Parent,
|
||||
IN PCUNICODE_STRING ValueName,
|
||||
OUT PCM_KEY_VALUE *pValueCell,
|
||||
OUT HCELL_INDEX *pValueCellOffset);
|
162
sdk/tools/mkhive/mkhive.c
Normal file
162
sdk/tools/mkhive/mkhive.c
Normal file
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* ReactOS kernel
|
||||
* Copyright (C) 2003, 2006 ReactOS Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* 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
|
||||
* PROJECT: ReactOS hive maker
|
||||
* FILE: tools/mkhive/mkhive.c
|
||||
* PURPOSE: Hive maker
|
||||
* PROGRAMMER: Eric Kohl
|
||||
* Hervé Poussineau
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "mkhive.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <stdlib.h>
|
||||
#define PATH_MAX _MAX_PATH
|
||||
#endif // _MSC_VER
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX 260
|
||||
#endif
|
||||
#define DIR_SEPARATOR_CHAR '/'
|
||||
#define DIR_SEPARATOR_STRING "/"
|
||||
#else
|
||||
#define DIR_SEPARATOR_CHAR '\\'
|
||||
#define DIR_SEPARATOR_STRING "\\"
|
||||
#endif
|
||||
|
||||
|
||||
void usage (void)
|
||||
{
|
||||
printf ("Usage: mkhive <dstdir> <inffiles>\n\n");
|
||||
printf (" dstdir - binary hive files are created in this directory\n");
|
||||
printf (" inffiles - inf files with full path\n");
|
||||
}
|
||||
|
||||
void convert_path(char *dst, char *src)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
while (src[i] != 0)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (src[i] == '/')
|
||||
{
|
||||
dst[i] = '\\';
|
||||
}
|
||||
#else
|
||||
if (src[i] == '\\')
|
||||
{
|
||||
dst[i] = '/';
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
dst[i] = src[i];
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
dst[i] = 0;
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
char FileName[PATH_MAX];
|
||||
int i;
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
usage ();
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf ("Binary hive maker\n");
|
||||
|
||||
RegInitializeRegistry ();
|
||||
|
||||
for (i = 2; i < argc; i++)
|
||||
{
|
||||
convert_path (FileName, argv[i]);
|
||||
ImportRegistryFile (FileName);
|
||||
}
|
||||
|
||||
convert_path (FileName, argv[1]);
|
||||
strcat (FileName, DIR_SEPARATOR_STRING);
|
||||
strcat (FileName, "default");
|
||||
if (!ExportBinaryHive (FileName, &DefaultHive))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
convert_path (FileName, argv[1]);
|
||||
strcat (FileName, DIR_SEPARATOR_STRING);
|
||||
strcat (FileName, "sam");
|
||||
if (!ExportBinaryHive (FileName, &SamHive))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
convert_path (FileName, argv[1]);
|
||||
strcat (FileName, DIR_SEPARATOR_STRING);
|
||||
strcat (FileName, "security");
|
||||
if (!ExportBinaryHive (FileName, &SecurityHive))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
convert_path (FileName, argv[1]);
|
||||
strcat (FileName, DIR_SEPARATOR_STRING);
|
||||
strcat (FileName, "software");
|
||||
if (!ExportBinaryHive (FileName, &SoftwareHive))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
convert_path (FileName, argv[1]);
|
||||
strcat (FileName, DIR_SEPARATOR_STRING);
|
||||
strcat (FileName, "system");
|
||||
if (!ExportBinaryHive (FileName, &SystemHive))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
convert_path (FileName, argv[1]);
|
||||
strcat (FileName, DIR_SEPARATOR_STRING);
|
||||
strcat (FileName, "BCD");
|
||||
if (!ExportBinaryHive (FileName, &BcdHive))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
RegShutdownRegistry ();
|
||||
|
||||
printf (" Done.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* EOF */
|
122
sdk/tools/mkhive/mkhive.h
Normal file
122
sdk/tools/mkhive/mkhive.h
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* ReactOS kernel
|
||||
* Copyright (C) 2003, 2006 ReactOS Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* 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
|
||||
* PROJECT: ReactOS hive maker
|
||||
* FILE: tools/mkhive/mkhive.h
|
||||
* PURPOSE: Hive maker
|
||||
* PROGRAMMER: Eric Kohl
|
||||
* Hervé Poussineau
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <typedefs.h>
|
||||
|
||||
// Definitions copied from <ntstatus.h>
|
||||
// We only want to include host headers, so we define them manually
|
||||
#define STATUS_SUCCESS ((NTSTATUS)0x00000000)
|
||||
#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001)
|
||||
#define STATUS_NOT_IMPLEMENTED ((NTSTATUS)0xC0000002)
|
||||
#define STATUS_INVALID_PARAMETER ((NTSTATUS)0xC000000D)
|
||||
#define STATUS_NO_MEMORY ((NTSTATUS)0xC0000017)
|
||||
#define STATUS_INSUFFICIENT_RESOURCES ((NTSTATUS)0xC000009A)
|
||||
#define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS)0xC0000034)
|
||||
#define STATUS_INVALID_PARAMETER_2 ((NTSTATUS)0xC00000F0)
|
||||
#define STATUS_BUFFER_OVERFLOW ((NTSTATUS)0x80000005)
|
||||
|
||||
unsigned char BitScanForward(ULONG * Index, unsigned long Mask);
|
||||
unsigned char BitScanReverse(ULONG * const Index, unsigned long Mask);
|
||||
#define RtlFillMemoryUlong(dst, len, val) memset(dst, val, len)
|
||||
|
||||
#ifdef _M_AMD64
|
||||
#define BitScanForward64 _BitScanForward64
|
||||
#define BitScanReverse64 _BitScanReverse64
|
||||
#endif
|
||||
|
||||
typedef DWORD REGSAM;
|
||||
typedef LPVOID LPSECURITY_ATTRIBUTES;
|
||||
typedef HANDLE HKEY, *PHKEY;
|
||||
|
||||
VOID NTAPI
|
||||
RtlInitUnicodeString(
|
||||
IN OUT PUNICODE_STRING DestinationString,
|
||||
IN PCWSTR SourceString);
|
||||
WCHAR NTAPI
|
||||
RtlUpcaseUnicodeChar(
|
||||
IN WCHAR Source);
|
||||
|
||||
LONG WINAPI
|
||||
RegQueryValueExW(
|
||||
IN HKEY hKey,
|
||||
IN LPCWSTR lpValueName,
|
||||
IN PULONG lpReserved,
|
||||
OUT PULONG lpType OPTIONAL,
|
||||
OUT PUCHAR lpData OPTIONAL,
|
||||
IN OUT PULONG lpcbData OPTIONAL);
|
||||
|
||||
LONG WINAPI
|
||||
RegSetValueExW(
|
||||
IN HKEY hKey,
|
||||
IN LPCWSTR lpValueName OPTIONAL,
|
||||
IN ULONG Reserved,
|
||||
IN ULONG dwType,
|
||||
IN const UCHAR* lpData,
|
||||
IN ULONG cbData);
|
||||
|
||||
LONG WINAPI
|
||||
RegDeleteKeyW(
|
||||
IN HKEY hKey,
|
||||
IN LPCWSTR lpSubKey);
|
||||
|
||||
LONG WINAPI
|
||||
RegDeleteValueW(
|
||||
IN HKEY hKey,
|
||||
IN LPCWSTR lpValueName OPTIONAL);
|
||||
|
||||
LONG WINAPI
|
||||
RegCreateKeyW(
|
||||
IN HKEY hKey,
|
||||
IN LPCWSTR lpSubKey,
|
||||
OUT PHKEY phkResult);
|
||||
|
||||
LONG WINAPI
|
||||
RegOpenKeyW(
|
||||
IN HKEY hKey,
|
||||
IN LPCWSTR lpSubKey,
|
||||
OUT PHKEY phkResult);
|
||||
|
||||
#define CMLIB_HOST
|
||||
#include <cmlib.h>
|
||||
#include <infhost.h>
|
||||
#include "reginf.h"
|
||||
#include "cmi.h"
|
||||
#include "registry.h"
|
||||
#include "binhive.h"
|
||||
|
||||
#define OBJ_NAME_PATH_SEPARATOR ((WCHAR)L'\\')
|
||||
|
||||
extern LIST_ENTRY CmiHiveListHead;
|
||||
#define ABS_VALUE(V) (((V) < 0) ? -(V) : (V))
|
||||
#define PAGED_CODE()
|
||||
|
||||
/* EOF */
|
516
sdk/tools/mkhive/reginf.c
Normal file
516
sdk/tools/mkhive/reginf.c
Normal file
|
@ -0,0 +1,516 @@
|
|||
/*
|
||||
* ReactOS kernel
|
||||
* Copyright (C) 2003, 2006 ReactOS Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* 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
|
||||
* PROJECT: ReactOS hive maker
|
||||
* FILE: tools/mkhive/reginf.c
|
||||
* PURPOSE: Inf file import code
|
||||
* PROGRAMMER: Eric Kohl
|
||||
* Hervé Poussineau
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include "mkhive.h"
|
||||
|
||||
#define FLG_ADDREG_BINVALUETYPE 0x00000001
|
||||
#define FLG_ADDREG_NOCLOBBER 0x00000002
|
||||
#define FLG_ADDREG_DELVAL 0x00000004
|
||||
#define FLG_ADDREG_APPEND 0x00000008
|
||||
#define FLG_ADDREG_KEYONLY 0x00000010
|
||||
#define FLG_ADDREG_OVERWRITEONLY 0x00000020
|
||||
#define FLG_ADDREG_TYPE_SZ 0x00000000
|
||||
#define FLG_ADDREG_TYPE_MULTI_SZ 0x00010000
|
||||
#define FLG_ADDREG_TYPE_EXPAND_SZ 0x00020000
|
||||
#define FLG_ADDREG_TYPE_BINARY (0x00000000 | FLG_ADDREG_BINVALUETYPE)
|
||||
#define FLG_ADDREG_TYPE_DWORD (0x00010000 | FLG_ADDREG_BINVALUETYPE)
|
||||
#define FLG_ADDREG_TYPE_NONE (0x00020000 | FLG_ADDREG_BINVALUETYPE)
|
||||
#define FLG_ADDREG_TYPE_MASK (0xFFFF0000 | FLG_ADDREG_BINVALUETYPE)
|
||||
|
||||
|
||||
static const WCHAR HKCR[] = {'H','K','C','R',0};
|
||||
static const WCHAR HKCU[] = {'H','K','C','U',0};
|
||||
static const WCHAR HKLM[] = {'H','K','L','M',0};
|
||||
static const WCHAR HKU[] = {'H','K','U',0};
|
||||
static const WCHAR HKR[] = {'H','K','R',0};
|
||||
static const WCHAR BCD[] = {'B','C','D',0};
|
||||
|
||||
static const WCHAR HKCRPath[] = {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\','S','O','F','T','W','A','R','E','\\','C','l','a','s','s','e','s','\\',0};
|
||||
static const WCHAR HKCUPath[] = {'\\','R','e','g','i','s','t','r','y','\\','U','s','e','r','\\','.','D','E','F','A','U','L','T','\\',0};
|
||||
static const WCHAR HKLMPath[] = {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\',0};
|
||||
static const WCHAR HKUPath[] = {'\\','R','e','g','i','s','t','r','y','\\','U','s','e','r','\\',0};
|
||||
static const WCHAR BCDPath[] = {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\',0};
|
||||
|
||||
static const WCHAR AddReg[] = {'A','d','d','R','e','g',0};
|
||||
static const WCHAR DelReg[] = {'D','e','l','R','e','g',0};
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
static BOOL
|
||||
GetRootKey (PWCHAR Name)
|
||||
{
|
||||
if (!strcmpiW (Name, HKCR))
|
||||
{
|
||||
strcpyW (Name, HKCRPath);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!strcmpiW (Name, HKCU))
|
||||
{
|
||||
strcpyW (Name, HKCUPath);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!strcmpiW (Name, HKLM))
|
||||
{
|
||||
strcpyW (Name, HKLMPath);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!strcmpiW (Name, HKU))
|
||||
{
|
||||
strcpyW (Name, HKUPath);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!strcmpiW (Name, BCD))
|
||||
{
|
||||
strcpyW (Name, BCDPath);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (!strcmpiW (Name, HKR))
|
||||
return FALSE;
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* AppendMultiSzValue
|
||||
*
|
||||
* Append a multisz string to a multisz registry value.
|
||||
*/
|
||||
static VOID
|
||||
AppendMultiSzValue (
|
||||
IN HKEY KeyHandle,
|
||||
IN PWCHAR ValueName,
|
||||
IN PWCHAR Strings,
|
||||
IN ULONG StringSize)
|
||||
{
|
||||
ULONG Size;
|
||||
ULONG Type;
|
||||
ULONG Total;
|
||||
PWCHAR Buffer;
|
||||
PWCHAR p;
|
||||
size_t len;
|
||||
LONG Error;
|
||||
|
||||
Error = RegQueryValueExW (
|
||||
KeyHandle,
|
||||
ValueName,
|
||||
NULL,
|
||||
&Type,
|
||||
NULL,
|
||||
&Size);
|
||||
if ((Error != ERROR_SUCCESS) ||
|
||||
(Type != REG_MULTI_SZ))
|
||||
return;
|
||||
|
||||
Buffer = malloc ((Size + StringSize) * sizeof(WCHAR));
|
||||
if (Buffer == NULL)
|
||||
return;
|
||||
|
||||
Error = RegQueryValueExW (
|
||||
KeyHandle,
|
||||
ValueName,
|
||||
NULL,
|
||||
NULL,
|
||||
(PUCHAR)Buffer,
|
||||
&Size);
|
||||
if (Error != ERROR_SUCCESS)
|
||||
goto done;
|
||||
|
||||
/* compare each string against all the existing ones */
|
||||
Total = Size;
|
||||
while (*Strings != 0)
|
||||
{
|
||||
len = strlenW(Strings) + 1;
|
||||
|
||||
for (p = Buffer; *p != 0; p += strlenW(p) + 1)
|
||||
if (!strcmpiW(p, Strings))
|
||||
break;
|
||||
|
||||
if (*p == 0) /* not found, need to append it */
|
||||
{
|
||||
memcpy (p, Strings, len);
|
||||
p[len] = 0;
|
||||
Total += len;
|
||||
}
|
||||
Strings += len;
|
||||
}
|
||||
|
||||
if (Total != Size)
|
||||
{
|
||||
DPRINT ("setting value %S to %S\n", ValueName, Buffer);
|
||||
RegSetValueExW (
|
||||
KeyHandle,
|
||||
ValueName,
|
||||
0,
|
||||
REG_MULTI_SZ,
|
||||
(PUCHAR)Buffer,
|
||||
Total * sizeof(WCHAR));
|
||||
}
|
||||
|
||||
done:
|
||||
free (Buffer);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* do_reg_operation
|
||||
*
|
||||
* Perform an add/delete registry operation depending on the flags.
|
||||
*/
|
||||
static BOOL
|
||||
do_reg_operation(
|
||||
IN HKEY KeyHandle,
|
||||
IN PWCHAR ValueName,
|
||||
IN PINFCONTEXT Context,
|
||||
IN ULONG Flags)
|
||||
{
|
||||
WCHAR EmptyStr = (CHAR)0;
|
||||
ULONG Type;
|
||||
ULONG Size;
|
||||
LONG Error;
|
||||
|
||||
if (Flags & FLG_ADDREG_DELVAL) /* deletion */
|
||||
{
|
||||
if (ValueName)
|
||||
{
|
||||
RegDeleteValueW (KeyHandle, ValueName);
|
||||
}
|
||||
else
|
||||
{
|
||||
RegDeleteKeyW (KeyHandle, NULL);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (Flags & FLG_ADDREG_KEYONLY)
|
||||
return TRUE;
|
||||
|
||||
if (Flags & (FLG_ADDREG_NOCLOBBER | FLG_ADDREG_OVERWRITEONLY))
|
||||
{
|
||||
Error = RegQueryValueExW (
|
||||
KeyHandle,
|
||||
ValueName,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
if ((Error == ERROR_SUCCESS) &&
|
||||
(Flags & FLG_ADDREG_NOCLOBBER))
|
||||
return TRUE;
|
||||
|
||||
if ((Error != ERROR_SUCCESS) &&
|
||||
(Flags & FLG_ADDREG_OVERWRITEONLY))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
switch (Flags & FLG_ADDREG_TYPE_MASK)
|
||||
{
|
||||
case FLG_ADDREG_TYPE_SZ:
|
||||
Type = REG_SZ;
|
||||
break;
|
||||
|
||||
case FLG_ADDREG_TYPE_MULTI_SZ:
|
||||
Type = REG_MULTI_SZ;
|
||||
break;
|
||||
|
||||
case FLG_ADDREG_TYPE_EXPAND_SZ:
|
||||
Type = REG_EXPAND_SZ;
|
||||
break;
|
||||
|
||||
case FLG_ADDREG_TYPE_BINARY:
|
||||
Type = REG_BINARY;
|
||||
break;
|
||||
|
||||
case FLG_ADDREG_TYPE_DWORD:
|
||||
Type = REG_DWORD;
|
||||
break;
|
||||
|
||||
case FLG_ADDREG_TYPE_NONE:
|
||||
Type = REG_NONE;
|
||||
break;
|
||||
|
||||
default:
|
||||
Type = Flags >> 16;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(Flags & FLG_ADDREG_BINVALUETYPE) ||
|
||||
(Type == REG_DWORD && InfHostGetFieldCount (Context) == 5))
|
||||
{
|
||||
PWCHAR Str = NULL;
|
||||
|
||||
if (Type == REG_MULTI_SZ)
|
||||
{
|
||||
if (InfHostGetMultiSzField (Context, 5, NULL, 0, &Size) != 0)
|
||||
Size = 0;
|
||||
|
||||
if (Size)
|
||||
{
|
||||
Str = malloc (Size * sizeof(WCHAR));
|
||||
if (Str == NULL)
|
||||
return FALSE;
|
||||
|
||||
InfHostGetMultiSzField (Context, 5, Str, Size, NULL);
|
||||
}
|
||||
|
||||
if (Flags & FLG_ADDREG_APPEND)
|
||||
{
|
||||
if (Str == NULL)
|
||||
return TRUE;
|
||||
|
||||
AppendMultiSzValue (
|
||||
KeyHandle,
|
||||
ValueName,
|
||||
Str,
|
||||
Size);
|
||||
|
||||
free (Str);
|
||||
return TRUE;
|
||||
}
|
||||
/* else fall through to normal string handling */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (InfHostGetStringField (Context, 5, NULL, 0, &Size) != 0)
|
||||
Size = 0;
|
||||
|
||||
if (Size)
|
||||
{
|
||||
Str = malloc (Size * sizeof(WCHAR));
|
||||
if (Str == NULL)
|
||||
return FALSE;
|
||||
|
||||
InfHostGetStringField (Context, 5, Str, Size, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (Type == REG_DWORD)
|
||||
{
|
||||
ULONG dw = Str ? strtoulW (Str, NULL, 0) : 0;
|
||||
|
||||
DPRINT("setting dword %S to %x\n", ValueName, dw);
|
||||
|
||||
RegSetValueExW (
|
||||
KeyHandle,
|
||||
ValueName,
|
||||
0,
|
||||
Type,
|
||||
(const PUCHAR)&dw,
|
||||
sizeof(ULONG));
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("setting value %S to %S\n", ValueName, Str);
|
||||
|
||||
if (Str)
|
||||
{
|
||||
RegSetValueExW (
|
||||
KeyHandle,
|
||||
ValueName,
|
||||
0,
|
||||
Type,
|
||||
(PVOID)Str,
|
||||
Size * sizeof(WCHAR));
|
||||
}
|
||||
else
|
||||
{
|
||||
RegSetValueExW (
|
||||
KeyHandle,
|
||||
ValueName,
|
||||
0,
|
||||
Type,
|
||||
(PVOID)&EmptyStr,
|
||||
sizeof(WCHAR));
|
||||
}
|
||||
}
|
||||
free (Str);
|
||||
}
|
||||
else /* get the binary data */
|
||||
{
|
||||
PUCHAR Data = NULL;
|
||||
|
||||
if (InfHostGetBinaryField (Context, 5, NULL, 0, &Size) != 0)
|
||||
Size = 0;
|
||||
|
||||
if (Size)
|
||||
{
|
||||
Data = malloc (Size);
|
||||
if (Data == NULL)
|
||||
return FALSE;
|
||||
|
||||
DPRINT("setting binary data %S len %d\n", ValueName, Size);
|
||||
InfHostGetBinaryField (Context, 5, Data, Size, NULL);
|
||||
}
|
||||
|
||||
RegSetValueExW (
|
||||
KeyHandle,
|
||||
ValueName,
|
||||
0,
|
||||
Type,
|
||||
(PVOID)Data,
|
||||
Size);
|
||||
|
||||
free (Data);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* registry_callback
|
||||
*
|
||||
* Called once for each AddReg and DelReg entry in a given section.
|
||||
*/
|
||||
static BOOL
|
||||
registry_callback (HINF hInf, PWCHAR Section, BOOL Delete)
|
||||
{
|
||||
WCHAR Buffer[MAX_INF_STRING_LENGTH];
|
||||
PWCHAR ValuePtr;
|
||||
ULONG Flags;
|
||||
size_t Length;
|
||||
|
||||
PINFCONTEXT Context = NULL;
|
||||
HKEY KeyHandle;
|
||||
BOOL Ok;
|
||||
|
||||
|
||||
Ok = InfHostFindFirstLine (hInf, Section, NULL, &Context) == 0;
|
||||
if (!Ok)
|
||||
return TRUE; /* Don't fail if the section isn't present */
|
||||
|
||||
for (;Ok; Ok = (InfHostFindNextLine (Context, Context) == 0))
|
||||
{
|
||||
/* get root */
|
||||
if (InfHostGetStringField (Context, 1, Buffer, MAX_INF_STRING_LENGTH, NULL) != 0)
|
||||
continue;
|
||||
if (!GetRootKey (Buffer))
|
||||
continue;
|
||||
|
||||
/* get key */
|
||||
Length = strlenW (Buffer);
|
||||
if (InfHostGetStringField (Context, 2, Buffer + Length, MAX_INF_STRING_LENGTH - (ULONG)Length, NULL) != 0)
|
||||
*Buffer = 0;
|
||||
|
||||
DPRINT("KeyName: <%S>\n", Buffer);
|
||||
|
||||
if (Delete)
|
||||
{
|
||||
Flags = FLG_ADDREG_DELVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* get flags */
|
||||
if (InfHostGetIntField (Context, 4, (INT *)&Flags) != 0)
|
||||
Flags = 0;
|
||||
}
|
||||
|
||||
DPRINT("Flags: 0x%x\n", Flags);
|
||||
|
||||
if (Delete || (Flags & FLG_ADDREG_OVERWRITEONLY))
|
||||
{
|
||||
if (RegOpenKeyW (NULL, Buffer, &KeyHandle) != ERROR_SUCCESS)
|
||||
{
|
||||
DPRINT("RegOpenKey(%S) failed\n", Buffer);
|
||||
continue; /* ignore if it doesn't exist */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (RegCreateKeyW (NULL, Buffer, &KeyHandle) != ERROR_SUCCESS)
|
||||
{
|
||||
DPRINT("RegCreateKey(%S) failed\n", Buffer);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* get value name */
|
||||
if (InfHostGetStringField (Context, 3, Buffer, MAX_INF_STRING_LENGTH, NULL) == 0)
|
||||
{
|
||||
ValuePtr = Buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
ValuePtr = NULL;
|
||||
}
|
||||
|
||||
/* and now do it */
|
||||
if (!do_reg_operation (KeyHandle, ValuePtr, Context, Flags))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
InfHostFreeContext(Context);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
BOOL
|
||||
ImportRegistryFile(PCHAR FileName)
|
||||
{
|
||||
HINF hInf;
|
||||
ULONG ErrorLine;
|
||||
|
||||
/* Load inf file from install media. */
|
||||
if (InfHostOpenFile(&hInf, FileName, 0, &ErrorLine) != 0)
|
||||
{
|
||||
DPRINT1 ("InfHostOpenFile(%s) failed\n", FileName);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!registry_callback (hInf, (PWCHAR)DelReg, TRUE))
|
||||
{
|
||||
DPRINT1 ("registry_callback() for DelReg failed\n");
|
||||
}
|
||||
|
||||
if (!registry_callback (hInf, (PWCHAR)AddReg, FALSE))
|
||||
{
|
||||
DPRINT1 ("registry_callback() for AddReg failed\n");
|
||||
}
|
||||
|
||||
InfHostCloseFile (hInf);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* EOF */
|
32
sdk/tools/mkhive/reginf.h
Normal file
32
sdk/tools/mkhive/reginf.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* ReactOS kernel
|
||||
* Copyright (C) 2006 ReactOS Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* 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
|
||||
* PROJECT: ReactOS hive maker
|
||||
* FILE: tools/mkhive/reginf.h
|
||||
* PURPOSE: Inf file import code
|
||||
* PROGRAMMER: Hervé Poussineau
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
BOOL
|
||||
ImportRegistryFile(PCHAR Filename);
|
||||
|
||||
/* EOF */
|
919
sdk/tools/mkhive/registry.c
Normal file
919
sdk/tools/mkhive/registry.c
Normal file
|
@ -0,0 +1,919 @@
|
|||
/*
|
||||
* ReactOS kernel
|
||||
* Copyright (C) 2006 ReactOS Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* 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
|
||||
* PROJECT: ReactOS hive maker
|
||||
* FILE: tools/mkhive/registry.c
|
||||
* PURPOSE: Registry code
|
||||
* PROGRAMMER: Hervé Poussineau
|
||||
*/
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* - Implement RegDeleteKeyW() and RegDeleteValueW()
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include "mkhive.h"
|
||||
|
||||
static CMHIVE RootHive;
|
||||
static PMEMKEY RootKey;
|
||||
CMHIVE DefaultHive; /* \Registry\User\.DEFAULT */
|
||||
CMHIVE SamHive; /* \Registry\Machine\SAM */
|
||||
CMHIVE SecurityHive; /* \Registry\Machine\SECURITY */
|
||||
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,
|
||||
IN HCELL_INDEX KeyCellOffset)
|
||||
{
|
||||
PMEMKEY Key;
|
||||
|
||||
Key = (PMEMKEY)malloc(sizeof(MEMKEY));
|
||||
if (!Key)
|
||||
return NULL;
|
||||
|
||||
Key->RegistryHive = RegistryHive;
|
||||
Key->KeyCellOffset = KeyCellOffset;
|
||||
return Key;
|
||||
}
|
||||
|
||||
LIST_ENTRY CmiReparsePointsHead;
|
||||
|
||||
static LONG
|
||||
RegpOpenOrCreateKey(
|
||||
IN HKEY hParentKey,
|
||||
IN PCWSTR KeyName,
|
||||
IN BOOL AllowCreation,
|
||||
IN BOOL Volatile,
|
||||
OUT PHKEY Key)
|
||||
{
|
||||
PWSTR LocalKeyName;
|
||||
PWSTR End;
|
||||
UNICODE_STRING KeyString;
|
||||
NTSTATUS Status;
|
||||
PREPARSE_POINT CurrentReparsePoint;
|
||||
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 == OBJ_NAME_PATH_SEPARATOR)
|
||||
{
|
||||
KeyName++;
|
||||
ParentRegistryHive = RootKey->RegistryHive;
|
||||
ParentCellOffset = RootKey->KeyCellOffset;
|
||||
}
|
||||
else if (hParentKey == NULL)
|
||||
{
|
||||
ParentRegistryHive = RootKey->RegistryHive;
|
||||
ParentCellOffset = RootKey->KeyCellOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
ParentRegistryHive = HKEY_TO_MEMKEY(hParentKey)->RegistryHive;
|
||||
ParentCellOffset = HKEY_TO_MEMKEY(hParentKey)->KeyCellOffset;
|
||||
}
|
||||
|
||||
LocalKeyName = (PWSTR)KeyName;
|
||||
for (;;)
|
||||
{
|
||||
End = (PWSTR)strchrW(LocalKeyName, OBJ_NAME_PATH_SEPARATOR);
|
||||
if (End)
|
||||
{
|
||||
KeyString.Buffer = LocalKeyName;
|
||||
KeyString.Length = KeyString.MaximumLength =
|
||||
(USHORT)((ULONG_PTR)End - (ULONG_PTR)LocalKeyName);
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlInitUnicodeString(&KeyString, LocalKeyName);
|
||||
if (KeyString.Length == 0)
|
||||
{
|
||||
/* Trailing path separator: we're done */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
CurrentReparsePoint = CONTAINING_RECORD(Ptr, REPARSE_POINT, ListEntry);
|
||||
if (CurrentReparsePoint->SourceHive == ParentRegistryHive &&
|
||||
CurrentReparsePoint->SourceKeyCellOffset == BlockOffset)
|
||||
{
|
||||
ParentRegistryHive = CurrentReparsePoint->DestinationHive;
|
||||
BlockOffset = CurrentReparsePoint->DestinationKeyCellOffset;
|
||||
break;
|
||||
}
|
||||
Ptr = Ptr->Flink;
|
||||
}
|
||||
}
|
||||
else if (AllowCreation) // && (BlockOffset == HCELL_NIL)
|
||||
{
|
||||
Status = CmiAddSubKey(ParentRegistryHive,
|
||||
ParentCellOffset,
|
||||
&KeyString,
|
||||
Volatile,
|
||||
&BlockOffset);
|
||||
}
|
||||
|
||||
HvReleaseCell(&ParentRegistryHive->Hive, ParentCellOffset);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
return ERROR_UNSUCCESSFUL;
|
||||
|
||||
ParentCellOffset = BlockOffset;
|
||||
if (End)
|
||||
LocalKeyName = End + 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
CurrentKey = CreateInMemoryStructure(ParentRegistryHive, ParentCellOffset);
|
||||
if (!CurrentKey)
|
||||
return ERROR_OUTOFMEMORY;
|
||||
|
||||
*Key = MEMKEY_TO_HKEY(CurrentKey);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
LONG WINAPI
|
||||
RegCreateKeyW(
|
||||
IN HKEY hKey,
|
||||
IN LPCWSTR lpSubKey,
|
||||
OUT PHKEY phkResult)
|
||||
{
|
||||
return RegpOpenOrCreateKey(hKey, lpSubKey, TRUE, FALSE, phkResult);
|
||||
}
|
||||
|
||||
LONG WINAPI
|
||||
RegDeleteKeyW(
|
||||
IN HKEY hKey,
|
||||
IN LPCWSTR lpSubKey)
|
||||
{
|
||||
DPRINT1("RegDeleteKeyW(0x%p, '%S') is UNIMPLEMENTED!\n",
|
||||
hKey, (lpSubKey ? lpSubKey : L""));
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
LONG WINAPI
|
||||
RegOpenKeyW(
|
||||
IN HKEY hKey,
|
||||
IN LPCWSTR lpSubKey,
|
||||
OUT PHKEY phkResult)
|
||||
{
|
||||
return RegpOpenOrCreateKey(hKey, lpSubKey, FALSE, FALSE, phkResult);
|
||||
}
|
||||
|
||||
LONG WINAPI
|
||||
RegCreateKeyExW(
|
||||
IN HKEY hKey,
|
||||
IN LPCWSTR lpSubKey,
|
||||
IN DWORD Reserved,
|
||||
IN LPWSTR lpClass OPTIONAL,
|
||||
IN DWORD dwOptions,
|
||||
IN REGSAM samDesired,
|
||||
IN LPSECURITY_ATTRIBUTES lpSecurityAttributes OPTIONAL,
|
||||
OUT PHKEY phkResult,
|
||||
OUT LPDWORD lpdwDisposition OPTIONAL)
|
||||
{
|
||||
return RegpOpenOrCreateKey(hKey,
|
||||
lpSubKey,
|
||||
TRUE,
|
||||
(dwOptions & REG_OPTION_VOLATILE) != 0,
|
||||
phkResult);
|
||||
}
|
||||
|
||||
LONG WINAPI
|
||||
RegSetValueExW(
|
||||
IN HKEY hKey,
|
||||
IN LPCWSTR lpValueName OPTIONAL,
|
||||
IN ULONG Reserved,
|
||||
IN ULONG dwType,
|
||||
IN const UCHAR* lpData,
|
||||
IN ULONG cbData)
|
||||
{
|
||||
PMEMKEY Key = HKEY_TO_MEMKEY(hKey); // ParentKey
|
||||
PHHIVE Hive;
|
||||
PCM_KEY_NODE KeyNode; // ParentNode
|
||||
PCM_KEY_VALUE ValueCell;
|
||||
HCELL_INDEX CellIndex;
|
||||
UNICODE_STRING ValueNameString;
|
||||
|
||||
PVOID DataCell;
|
||||
ULONG DataCellSize;
|
||||
NTSTATUS Status;
|
||||
|
||||
if (dwType == REG_LINK)
|
||||
{
|
||||
PMEMKEY DestKey;
|
||||
|
||||
/* Special handling of registry links */
|
||||
if (cbData != sizeof(PVOID))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
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 & ~CM_KEY_VALUE_SPECIAL_SIZE) != cbData)
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
|
||||
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);
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// /**/HvReleaseCell(Hive, CellIndex);/**/
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
return ERROR_UNSUCCESSFUL;
|
||||
|
||||
/* 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(Hive, ValueCell->Data);
|
||||
if (!DataCell)
|
||||
return ERROR_UNSUCCESSFUL;
|
||||
|
||||
DataCellSize = (ULONG)(-HvGetCellSize(Hive, DataCell));
|
||||
}
|
||||
else
|
||||
{
|
||||
DataCell = NULL;
|
||||
DataCellSize = 0;
|
||||
}
|
||||
|
||||
if (cbData <= sizeof(HCELL_INDEX))
|
||||
{
|
||||
/* If data size <= sizeof(HCELL_INDEX) then store data in the data offset */
|
||||
DPRINT("ValueCell->DataLength %u\n", ValueCell->DataLength);
|
||||
if (DataCell)
|
||||
HvFreeCell(Hive, ValueCell->Data);
|
||||
|
||||
RtlCopyMemory(&ValueCell->Data, lpData, cbData);
|
||||
ValueCell->DataLength = (cbData | CM_KEY_VALUE_SPECIAL_SIZE);
|
||||
ValueCell->Type = dwType;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cbData > DataCellSize)
|
||||
{
|
||||
/* New data size is larger than the current, destroy current
|
||||
* data block and allocate a new one. */
|
||||
HCELL_INDEX NewOffset;
|
||||
|
||||
DPRINT("ValueCell->DataLength %u\n", ValueCell->DataLength);
|
||||
|
||||
NewOffset = HvAllocateCell(Hive, cbData, Stable, HCELL_NIL);
|
||||
if (NewOffset == HCELL_NIL)
|
||||
{
|
||||
DPRINT("HvAllocateCell() has failed!\n");
|
||||
return ERROR_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
if (DataCell)
|
||||
HvFreeCell(Hive, ValueCell->Data);
|
||||
|
||||
ValueCell->Data = NewOffset;
|
||||
DataCell = (PVOID)HvGetCell(Hive, NewOffset);
|
||||
}
|
||||
|
||||
/* Copy new contents to cell */
|
||||
RtlCopyMemory(DataCell, lpData, cbData);
|
||||
ValueCell->DataLength = (cbData & ~CM_KEY_VALUE_SPECIAL_SIZE);
|
||||
ValueCell->Type = dwType;
|
||||
HvMarkCellDirty(Hive, ValueCell->Data, 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);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
// 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 OPTIONAL,
|
||||
OUT PUCHAR lpData OPTIONAL,
|
||||
IN OUT PULONG lpcbData OPTIONAL)
|
||||
{
|
||||
PMEMKEY ParentKey = HKEY_TO_MEMKEY(hKey);
|
||||
PHHIVE Hive = &ParentKey->RegistryHive->Hive;
|
||||
PCM_KEY_NODE KeyNode;
|
||||
PCM_KEY_VALUE ValueCell;
|
||||
HCELL_INDEX CellIndex;
|
||||
UNICODE_STRING ValueNameString;
|
||||
|
||||
KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, ParentKey->KeyCellOffset);
|
||||
if (!KeyNode)
|
||||
return ERROR_UNSUCCESSFUL;
|
||||
|
||||
ASSERT(KeyNode->Signature == CM_KEY_NODE_SIGNATURE);
|
||||
|
||||
/* 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
|
||||
RegDeleteValueW(
|
||||
IN HKEY hKey,
|
||||
IN LPCWSTR lpValueName OPTIONAL)
|
||||
{
|
||||
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;
|
||||
PREPARSE_POINT ReparsePoint;
|
||||
PMEMKEY NewKey;
|
||||
LONG rc;
|
||||
|
||||
ReparsePoint = (PREPARSE_POINT)malloc(sizeof(REPARSE_POINT));
|
||||
if (!ReparsePoint)
|
||||
return FALSE;
|
||||
|
||||
/*
|
||||
* 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("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,
|
||||
0,
|
||||
NULL,
|
||||
REG_OPTION_VOLATILE,
|
||||
0,
|
||||
NULL,
|
||||
(PHKEY)&NewKey,
|
||||
NULL);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
{
|
||||
free(ReparsePoint);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ReparsePoint->SourceHive = NewKey->RegistryHive;
|
||||
ReparsePoint->SourceKeyCellOffset = NewKey->KeyCellOffset;
|
||||
NewKey->RegistryHive = HiveToConnect;
|
||||
NewKey->KeyCellOffset = HiveToConnect->Hive.BaseBlock->RootCell;
|
||||
ReparsePoint->DestinationHive = NewKey->RegistryHive;
|
||||
ReparsePoint->DestinationKeyCellOffset = NewKey->KeyCellOffset;
|
||||
InsertTailList(&CmiReparsePointsHead, &ReparsePoint->ListEntry);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LIST_ENTRY CmiHiveListHead;
|
||||
|
||||
VOID
|
||||
RegInitializeRegistry(VOID)
|
||||
{
|
||||
UNICODE_STRING RootKeyName = RTL_CONSTANT_STRING(L"\\");
|
||||
NTSTATUS Status;
|
||||
PMEMKEY ControlSetKey, CurrentControlSetKey;
|
||||
PREPARSE_POINT ReparsePoint;
|
||||
|
||||
InitializeListHead(&CmiHiveListHead);
|
||||
InitializeListHead(&CmiReparsePointsHead);
|
||||
|
||||
Status = CmiInitializeHive(&RootHive, L"");
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("CmiInitializeHive() failed with status 0x%08x\n", Status);
|
||||
return;
|
||||
}
|
||||
|
||||
RootKey = CreateInMemoryStructure(&RootHive,
|
||||
RootHive.Hive.BaseBlock->RootCell);
|
||||
|
||||
/* 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 */
|
||||
RegCreateKeyW(NULL,
|
||||
L"Registry\\Machine\\SYSTEM\\ControlSet001",
|
||||
(HKEY*)&ControlSetKey);
|
||||
|
||||
/* Create 'CurrentControlSet' key */
|
||||
RegCreateKeyExW(NULL,
|
||||
L"Registry\\Machine\\SYSTEM\\CurrentControlSet",
|
||||
0,
|
||||
NULL,
|
||||
REG_OPTION_VOLATILE,
|
||||
0,
|
||||
NULL,
|
||||
(HKEY*)&CurrentControlSetKey,
|
||||
NULL);
|
||||
|
||||
/* Connect 'CurrentControlSet' to 'ControlSet001' */
|
||||
ReparsePoint = (PREPARSE_POINT)malloc(sizeof(REPARSE_POINT));
|
||||
ReparsePoint->SourceHive = CurrentControlSetKey->RegistryHive;
|
||||
ReparsePoint->SourceKeyCellOffset = CurrentControlSetKey->KeyCellOffset;
|
||||
ReparsePoint->DestinationHive = ControlSetKey->RegistryHive;
|
||||
ReparsePoint->DestinationKeyCellOffset = ControlSetKey->KeyCellOffset;
|
||||
InsertTailList(&CmiReparsePointsHead, &ReparsePoint->ListEntry);
|
||||
}
|
||||
|
||||
VOID
|
||||
RegShutdownRegistry(VOID)
|
||||
{
|
||||
/* FIXME: clean up the complete hive */
|
||||
|
||||
free(RootKey);
|
||||
}
|
||||
|
||||
/* EOF */
|
65
sdk/tools/mkhive/registry.h
Normal file
65
sdk/tools/mkhive/registry.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS hive maker
|
||||
* FILE: tools/mkhive/registry.h
|
||||
* PURPOSE: Registry code
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef struct _REPARSE_POINT
|
||||
{
|
||||
LIST_ENTRY ListEntry;
|
||||
PCMHIVE SourceHive;
|
||||
HCELL_INDEX SourceKeyCellOffset;
|
||||
PCMHIVE DestinationHive;
|
||||
HCELL_INDEX DestinationKeyCellOffset;
|
||||
} REPARSE_POINT, *PREPARSE_POINT;
|
||||
|
||||
typedef struct _MEMKEY
|
||||
{
|
||||
/* Information on hard disk structure */
|
||||
HCELL_INDEX KeyCellOffset;
|
||||
PCMHIVE RegistryHive;
|
||||
} MEMKEY, *PMEMKEY;
|
||||
|
||||
#define HKEY_TO_MEMKEY(hKey) ((PMEMKEY)(hKey))
|
||||
#define MEMKEY_TO_HKEY(memKey) ((HKEY)(memKey))
|
||||
|
||||
extern CMHIVE DefaultHive; /* \Registry\User\.DEFAULT */
|
||||
extern CMHIVE SamHive; /* \Registry\Machine\SAM */
|
||||
extern CMHIVE SecurityHive; /* \Registry\Machine\SECURITY */
|
||||
extern CMHIVE SoftwareHive; /* \Registry\Machine\SOFTWARE */
|
||||
extern CMHIVE SystemHive; /* \Registry\Machine\SYSTEM */
|
||||
extern CMHIVE BcdHive; /* \Registry\Machine\BCD00000000 */
|
||||
|
||||
#define ERROR_SUCCESS 0L
|
||||
#define ERROR_UNSUCCESSFUL 1L
|
||||
#define ERROR_FILE_NOT_FOUND 2L
|
||||
#define ERROR_OUTOFMEMORY 14L
|
||||
#define ERROR_INVALID_PARAMETER 87L
|
||||
#define ERROR_MORE_DATA 234L
|
||||
#define ERROR_NO_MORE_ITEMS 259L
|
||||
|
||||
#define REG_NONE 0
|
||||
#define REG_SZ 1
|
||||
#define REG_EXPAND_SZ 2
|
||||
#define REG_BINARY 3
|
||||
#define REG_DWORD 4
|
||||
#define REG_DWORD_LITTLE_ENDIAN 4
|
||||
#define REG_DWORD_BIG_ENDIAN 5
|
||||
#define REG_LINK 6
|
||||
#define REG_MULTI_SZ 7
|
||||
#define REG_RESOURCE_LIST 8
|
||||
#define REG_FULL_RESOURCE_DESCRIPTOR 9
|
||||
#define REG_RESOURCE_REQUIREMENTS_LIST 10
|
||||
#define REG_QWORD 11
|
||||
#define REG_QWORD_LITTLE_ENDIAN 11
|
||||
|
||||
VOID
|
||||
RegInitializeRegistry(VOID);
|
||||
|
||||
VOID
|
||||
RegShutdownRegistry(VOID);
|
||||
|
||||
/* EOF */
|
195
sdk/tools/mkhive/rtl.c
Normal file
195
sdk/tools/mkhive/rtl.c
Normal file
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS hive maker
|
||||
* FILE: tools/mkhive/rtl.c
|
||||
* PURPOSE: Runtime Library
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/* gcc defaults to cdecl */
|
||||
#if defined(__GNUC__)
|
||||
#undef __cdecl
|
||||
#define __cdecl
|
||||
#endif
|
||||
|
||||
#include "mkhive.h"
|
||||
#include <bitmap.c>
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*
|
||||
* NOTES
|
||||
* If source is NULL the length of source is assumed to be 0.
|
||||
*/
|
||||
VOID NTAPI
|
||||
RtlInitUnicodeString(
|
||||
IN OUT PUNICODE_STRING DestinationString,
|
||||
IN PCWSTR SourceString)
|
||||
{
|
||||
SIZE_T DestSize;
|
||||
|
||||
if(SourceString)
|
||||
{
|
||||
DestSize = strlenW(SourceString) * sizeof(WCHAR);
|
||||
DestinationString->Length = (USHORT)DestSize;
|
||||
DestinationString->MaximumLength = (USHORT)DestSize + sizeof(WCHAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
DestinationString->Length = 0;
|
||||
DestinationString->MaximumLength = 0;
|
||||
}
|
||||
|
||||
DestinationString->Buffer = (PWCHAR)SourceString;
|
||||
}
|
||||
|
||||
LONG NTAPI
|
||||
RtlCompareUnicodeString(
|
||||
IN PCUNICODE_STRING String1,
|
||||
IN PCUNICODE_STRING String2,
|
||||
IN BOOLEAN CaseInSensitive)
|
||||
{
|
||||
USHORT i;
|
||||
WCHAR c1, c2;
|
||||
|
||||
for (i = 0; i <= String1->Length / sizeof(WCHAR) && i <= String2->Length / sizeof(WCHAR); i++)
|
||||
{
|
||||
if (CaseInSensitive)
|
||||
{
|
||||
c1 = RtlUpcaseUnicodeChar(String1->Buffer[i]);
|
||||
c2 = RtlUpcaseUnicodeChar(String2->Buffer[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
c1 = String1->Buffer[i];
|
||||
c2 = String2->Buffer[i];
|
||||
}
|
||||
|
||||
if (c1 < c2)
|
||||
return -1;
|
||||
else if (c1 > c2)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
WCHAR NTAPI
|
||||
RtlUpcaseUnicodeChar(
|
||||
IN WCHAR Source)
|
||||
{
|
||||
USHORT Offset;
|
||||
|
||||
if (Source < 'a')
|
||||
return Source;
|
||||
|
||||
if (Source <= 'z')
|
||||
return (Source - ('a' - 'A'));
|
||||
|
||||
Offset = 0;
|
||||
|
||||
return Source + (SHORT)Offset;
|
||||
}
|
||||
|
||||
VOID NTAPI
|
||||
KeQuerySystemTime(
|
||||
OUT PLARGE_INTEGER CurrentTime)
|
||||
{
|
||||
CurrentTime->QuadPart = 0;
|
||||
}
|
||||
|
||||
PVOID NTAPI
|
||||
ExAllocatePool(
|
||||
IN POOL_TYPE PoolType,
|
||||
IN SIZE_T NumberOfBytes)
|
||||
{
|
||||
return (PVOID) malloc(NumberOfBytes);
|
||||
}
|
||||
|
||||
VOID NTAPI
|
||||
ExFreePool(
|
||||
IN PVOID p)
|
||||
{
|
||||
free(p);
|
||||
}
|
||||
|
||||
ULONG
|
||||
__cdecl
|
||||
DbgPrint(
|
||||
IN CHAR *Format,
|
||||
IN ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, Format);
|
||||
vprintf(Format, ap);
|
||||
va_end(ap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
RtlAssert(PVOID FailedAssertion,
|
||||
PVOID FileName,
|
||||
ULONG LineNumber,
|
||||
PCHAR Message)
|
||||
{
|
||||
if (NULL != Message)
|
||||
{
|
||||
DbgPrint("Assertion \'%s\' failed at %s line %d: %s\n",
|
||||
(PCHAR)FailedAssertion,
|
||||
(PCHAR)FileName,
|
||||
LineNumber,
|
||||
Message);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgPrint("Assertion \'%s\' failed at %s line %d\n",
|
||||
(PCHAR)FailedAssertion,
|
||||
(PCHAR)FileName,
|
||||
LineNumber);
|
||||
}
|
||||
|
||||
//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%08X (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;
|
||||
while (Mask && ((Mask & 1) == 0))
|
||||
{
|
||||
Mask >>= 1;
|
||||
++(*Index);
|
||||
}
|
||||
return Mask ? 1 : 0;
|
||||
}
|
||||
|
||||
unsigned char BitScanReverse(ULONG * const Index, unsigned long Mask)
|
||||
{
|
||||
*Index = 0;
|
||||
while (Mask && ((Mask & (1 << 31)) == 0))
|
||||
{
|
||||
Mask <<= 1;
|
||||
++(*Index);
|
||||
}
|
||||
return Mask ? 1 : 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue