* PROJECT: ReactOS hive maker
* FILE: tools/mkhive/registry.c
* PURPOSE: Registry code
- * PROGRAMMER: Hervé Poussineau
+ * PROGRAMMERS: Hervé Poussineau
+ * Hermès Bélusca-Maïto
*/
/*
* - 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 */
+
+static CMHIVE SystemHive; /* \Registry\Machine\SYSTEM */
+static CMHIVE SoftwareHive; /* \Registry\Machine\SOFTWARE */
+static CMHIVE DefaultHive; /* \Registry\User\.DEFAULT */
+static CMHIVE SamHive; /* \Registry\Machine\SAM */
+static CMHIVE SecurityHive; /* \Registry\Machine\SECURITY */
+static CMHIVE BcdHive; /* \Registry\Machine\BCD00000000 */
//
// TODO: Write these values in a more human-readable form.
// A cross-check was subsequently done with the system hives to verify that
// the security descriptors were the same.
//
-UCHAR BcdSecurity[] =
+static UCHAR BcdSecurity[] =
{
// SECURITY_DESCRIPTOR_RELATIVE
0x01, // Revision
0x01, 0x02, 0x00, 0x00
};
-UCHAR SoftwareSecurity[] =
+static UCHAR SoftwareSecurity[] =
{
// SECURITY_DESCRIPTOR_RELATIVE
0x01, // Revision
};
// Same security for SYSTEM, SAM and .DEFAULT
-UCHAR SystemSecurity[] =
+static UCHAR SystemSecurity[] =
{
// SECURITY_DESCRIPTOR_RELATIVE
0x01, // Revision
0x01, 0x02, 0x00, 0x00
};
+
+HIVE_LIST_ENTRY RegistryHives[/*MAX_NUMBER_OF_REGISTRY_HIVES*/] =
+{
+ /* Special Setup system registry hive */
+ // WARNING: Please *keep* it in first position!
+ { "SETUPREG", L"Registry\\Machine\\SYSTEM" , &SystemHive , SystemSecurity , sizeof(SystemSecurity) },
+
+ /* Regular registry hives */
+ { "SYSTEM" , L"Registry\\Machine\\SYSTEM" , &SystemHive , SystemSecurity , sizeof(SystemSecurity) },
+ { "SOFTWARE", L"Registry\\Machine\\SOFTWARE" , &SoftwareHive, SoftwareSecurity, sizeof(SoftwareSecurity) },
+ { "DEFAULT" , L"Registry\\User\\.DEFAULT" , &DefaultHive , SystemSecurity , sizeof(SystemSecurity) },
+ { "SAM" , L"Registry\\Machine\\SAM" , &SamHive , SystemSecurity , sizeof(SystemSecurity) },
+ { "SECURITY", L"Registry\\Machine\\SECURITY" , &SecurityHive, NULL , 0 },
+ { "BCD" , L"Registry\\Machine\\BCD00000000", &BcdHive , BcdSecurity , sizeof(BcdSecurity) },
+};
+C_ASSERT(_countof(RegistryHives) == MAX_NUMBER_OF_REGISTRY_HIVES);
+
+
static PMEMKEY
CreateInMemoryStructure(
IN PCMHIVE RegistryHive,
return Key;
}
+LIST_ENTRY CmiHiveListHead;
LIST_ENTRY CmiReparsePointsHead;
static LONG
-RegpOpenOrCreateKey(
+RegpCreateOrOpenKey(
IN HKEY hParentKey,
IN PCWSTR KeyName,
IN BOOL AllowCreation,
PCM_KEY_NODE SubKeyCell;
HCELL_INDEX BlockOffset;
- DPRINT("RegpCreateOpenKey('%S')\n", KeyName);
+ DPRINT("RegpCreateOrOpenKey('%S')\n", KeyName);
if (*KeyName == OBJ_NAME_PATH_SEPARATOR)
{
Volatile,
&BlockOffset);
}
+ else // if (BlockOffset == HCELL_NIL)
+ {
+ Status = STATUS_OBJECT_NAME_NOT_FOUND; // ERROR_PATH_NOT_FOUND;
+ }
HvReleaseCell(&ParentRegistryHive->Hive, ParentCellOffset);
if (!NT_SUCCESS(Status))
+ {
+ DPRINT("RegpCreateOrOpenKey('%S'): Could not create or open subkey '%wZ'\n", KeyName, &KeyString);
return ERROR_UNSUCCESSFUL;
+ }
ParentCellOffset = BlockOffset;
if (End)
}
LONG WINAPI
-RegCreateKeyW(
- IN HKEY hKey,
- IN LPCWSTR lpSubKey,
- OUT PHKEY phkResult)
+RegCloseKey(
+ IN HKEY hKey)
{
- return RegpOpenOrCreateKey(hKey, lpSubKey, TRUE, FALSE, phkResult);
-}
+ PMEMKEY Key = HKEY_TO_MEMKEY(hKey); // ParentKey
+
+ /* Free the object */
+ free(Key);
-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(
+RegCreateKeyW(
IN HKEY hKey,
IN LPCWSTR lpSubKey,
OUT PHKEY phkResult)
{
- return RegpOpenOrCreateKey(hKey, lpSubKey, FALSE, FALSE, phkResult);
+ return RegpCreateOrOpenKey(hKey, lpSubKey, TRUE, FALSE, phkResult);
}
LONG WINAPI
OUT PHKEY phkResult,
OUT LPDWORD lpdwDisposition OPTIONAL)
{
- return RegpOpenOrCreateKey(hKey,
+ return RegpCreateOrOpenKey(hKey,
lpSubKey,
TRUE,
(dwOptions & REG_OPTION_VOLATILE) != 0,
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 RegpCreateOrOpenKey(hKey, lpSubKey, FALSE, FALSE, phkResult);
+}
+
LONG WINAPI
RegSetValueExW(
IN HKEY hKey,
PHHIVE Hive;
PCM_KEY_NODE KeyNode; // ParentNode
PCM_KEY_VALUE ValueCell;
+ ULONG ChildIndex;
HCELL_INDEX CellIndex;
UNICODE_STRING ValueNameString;
/* Initialize value name string */
RtlInitUnicodeString(&ValueNameString, lpValueName);
- CellIndex = CmpFindValueByName(Hive, KeyNode, &ValueNameString);
+ if (!CmpFindNameInList(Hive,
+ &KeyNode->ValueList,
+ &ValueNameString,
+ &ChildIndex,
+ &CellIndex))
+ {
+ /* Sanity check */
+ ASSERT(CellIndex == HCELL_NIL);
+ /* Fail */
+ // Status = STATUS_INSUFFICIENT_RESOURCES;
+ return ERROR_UNSUCCESSFUL;
+ }
if (CellIndex == HCELL_NIL)
{
/* The value doesn't exist, create a new one */
Status = CmiAddValueKey(Key->RegistryHive,
KeyNode,
+ ChildIndex,
&ValueNameString,
&ValueCell,
&CellIndex);
/* 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);/**/
NewOffset = HvAllocateCell(Hive, cbData, Stable, HCELL_NIL);
if (NewOffset == HCELL_NIL)
{
- DPRINT("HvAllocateCell() failed with status 0x%08x\n", Status);
+ DPRINT("HvAllocateCell() has failed!\n");
return ERROR_UNSUCCESSFUL;
}
/* Save the write time */
KeQuerySystemTime(&KeyNode->LastWriteTime);
- DPRINT("Return status 0x%08x\n", Status);
- return Status;
+ return ERROR_SUCCESS;
}
-// Synced with freeldr/windows/registry.c
+// Synced with freeldr/ntldr/registry.c
static
VOID
RepGetValueData(
IN PHHIVE Hive,
IN PCM_KEY_VALUE ValueCell,
- OUT ULONG* Type OPTIONAL,
+ OUT PULONG Type OPTIONAL,
OUT PUCHAR Data OPTIONAL,
- IN OUT ULONG* DataSize OPTIONAL)
+ IN OUT PULONG DataSize OPTIONAL)
{
ULONG DataLength;
PVOID DataCell;
}
}
-// Similar to RegQueryValue in freeldr/windows/registry.c
+// Similar to RegQueryValue in freeldr/ntldr/registry.c
LONG WINAPI
RegQueryValueExW(
IN HKEY hKey,
ConnectRegistry(
IN HKEY RootKey,
IN PCMHIVE HiveToConnect,
- IN PUCHAR Descriptor,
- IN ULONG DescriptorLength,
- IN LPCWSTR Path)
+ IN PUCHAR SecurityDescriptor,
+ IN ULONG SecurityDescriptorLength,
+ IN PCWSTR Path)
{
NTSTATUS Status;
+ LONG rc;
PREPARSE_POINT ReparsePoint;
PMEMKEY NewKey;
- LONG rc;
- ReparsePoint = (PREPARSE_POINT)malloc(sizeof(REPARSE_POINT));
+ ReparsePoint = (PREPARSE_POINT)malloc(sizeof(*ReparsePoint));
if (!ReparsePoint)
return FALSE;
*/
Status = CmiCreateSecurityKey(&HiveToConnect->Hive,
HiveToConnect->Hive.BaseBlock->RootCell,
- Descriptor, DescriptorLength);
+ SecurityDescriptor, SecurityDescriptorLength);
if (!NT_SUCCESS(Status))
DPRINT1("Failed to add security for root key '%S'\n", Path);
- /* Create key */
+ /* Create the key */
rc = RegCreateKeyExW(RootKey,
Path,
0,
ReparsePoint->DestinationHive = NewKey->RegistryHive;
ReparsePoint->DestinationKeyCellOffset = NewKey->KeyCellOffset;
InsertTailList(&CmiReparsePointsHead, &ReparsePoint->ListEntry);
+
return TRUE;
}
-LIST_ENTRY CmiHiveListHead;
+static BOOL
+CreateSymLink(
+ IN PCWSTR LinkKeyPath OPTIONAL,
+ IN OUT PHKEY LinkKeyHandle OPTIONAL,
+ // IN PCWSTR TargetKeyPath OPTIONAL,
+ IN HKEY TargetKeyHandle)
+{
+ LONG rc;
+ PMEMKEY LinkKey, TargetKey;
+ PREPARSE_POINT ReparsePoint;
+
+ ReparsePoint = (PREPARSE_POINT)malloc(sizeof(*ReparsePoint));
+ if (!ReparsePoint)
+ return FALSE;
+
+ if (LinkKeyPath && !(LinkKeyHandle && *LinkKeyHandle))
+ {
+ /* Create the link key */
+ rc = RegCreateKeyExW(NULL,
+ LinkKeyPath,
+ 0,
+ NULL,
+ REG_OPTION_VOLATILE,
+ 0,
+ NULL,
+ (PHKEY)&LinkKey,
+ NULL);
+ if (rc != ERROR_SUCCESS)
+ {
+ free(ReparsePoint);
+ return FALSE;
+ }
+ }
+ else if (LinkKeyHandle)
+ {
+ /* Use the user-provided link key handle */
+ LinkKey = HKEY_TO_MEMKEY(*LinkKeyHandle);
+ }
+
+ if (LinkKeyHandle)
+ *LinkKeyHandle = MEMKEY_TO_HKEY(LinkKey);
+
+ TargetKey = HKEY_TO_MEMKEY(TargetKeyHandle);
+
+ ReparsePoint->SourceHive = LinkKey->RegistryHive;
+ ReparsePoint->SourceKeyCellOffset = LinkKey->KeyCellOffset;
+ ReparsePoint->DestinationHive = TargetKey->RegistryHive;
+ ReparsePoint->DestinationKeyCellOffset = TargetKey->KeyCellOffset;
+ InsertTailList(&CmiReparsePointsHead, &ReparsePoint->ListEntry);
+
+ return TRUE;
+}
VOID
-RegInitializeRegistry(VOID)
+RegInitializeRegistry(
+ IN PCSTR HiveList)
{
- UNICODE_STRING RootKeyName = RTL_CONSTANT_STRING(L"\\");
NTSTATUS Status;
- PMEMKEY ControlSetKey, CurrentControlSetKey;
- PREPARSE_POINT ReparsePoint;
+ UINT i;
+ HKEY ControlSetKey;
InitializeListHead(&CmiHiveListHead);
InitializeListHead(&CmiReparsePointsHead);
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 */
+ for (i = 0; i < _countof(RegistryHives); ++i)
+ {
+ /* Skip this registry hive if it's not in the list */
+ if (!strstr(HiveList, RegistryHives[i].HiveName))
+ continue;
+
+ /* Create the registry key */
+ ConnectRegistry(NULL,
+ RegistryHives[i].CmHive,
+ RegistryHives[i].SecurityDescriptor,
+ RegistryHives[i].SecurityDescriptorLength,
+ RegistryHives[i].HiveRegistryPath);
+
+ /* If we happen to deal with the special setup registry hive, stop there */
+ // if (strcmp(RegistryHives[i].HiveName, "SETUPREG") == 0)
+ if (i == 0)
+ break;
+ }
+
+ /* Create the '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);
+ &ControlSetKey);
+
+ /* Create the 'CurrentControlSet' key as a symlink to 'ControlSet001' */
+ CreateSymLink(L"Registry\\Machine\\SYSTEM\\CurrentControlSet",
+ NULL, ControlSetKey);
+
+ RegCloseKey(ControlSetKey);
+
+#if 0
+ /* Link SECURITY to SAM */
+ CmpLinkKeyToHive(L"\\Registry\\Machine\\Security\\SAM", L"\\Registry\\Machine\\SAM\\SAM");
+ /* Link S-1-5-18 to .Default */
+ CmpLinkKeyToHive(L"\\Registry\\User\\S-1-5-18", L"\\Registry\\User\\.Default");
+#endif
}
VOID
RegShutdownRegistry(VOID)
{
+ PLIST_ENTRY Entry;
+ PREPARSE_POINT ReparsePoint;
+
+ /* Clean up the reparse points list */
+ while (!IsListEmpty(&CmiReparsePointsHead))
+ {
+ Entry = RemoveHeadList(&CmiReparsePointsHead);
+ ReparsePoint = CONTAINING_RECORD(Entry, REPARSE_POINT, ListEntry);
+ free(ReparsePoint);
+ }
+
/* FIXME: clean up the complete hive */
free(RootKey);