* Create a branch for USB experiments.

svn path=/branches/usb-experiments/; revision=72629
This commit is contained in:
Amine Khaldi 2016-09-09 15:11:19 +00:00
parent 28d8ba0d3e
commit 0ee830d7a4
23049 changed files with 0 additions and 1313991 deletions

View 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)

View 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 */

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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 */

View 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
View 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;
}