/*
* ReactOS kernel
- * Copyright (C) 2003 ReactOS Team
+ * 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
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * 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.
*/
-/* $Id$
- * COPYRIGHT: See COPYING in the top level directory
+/* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS hive maker
* FILE: tools/mkhive/registry.c
* PURPOSE: Registry code
- * PROGRAMMER: Eric Kohl
+ * PROGRAMMER: Hervé Poussineau
*/
/*
* TODO:
- * - Implement RegDeleteKey().
- * - Fix RegEnumValue().
+ * - Implement RegDeleteKeyW()
+ * - Implement RegEnumValue()
+ * - Implement RegQueryValueExW()
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
+#define NDEBUG
#include "mkhive.h"
-#include "registry.h"
-
-static HKEY RootKey;
-
-
-VOID
-RegInitializeRegistry(VOID)
+#define REG_DATA_SIZE_MASK 0x7FFFFFFF
+#define REG_DATA_IN_OFFSET 0x80000000
+
+static CMHIVE RootHive;
+static MEMKEY 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 */
+
+static MEMKEY
+CreateInMemoryStructure(
+ IN PCMHIVE RegistryHive,
+ IN HCELL_INDEX KeyCellOffset,
+ IN PCUNICODE_STRING KeyName)
{
- HKEY ControlSetKey;
- HKEY LinkKey;
-
- /* Create root key */
- RootKey = (HKEY)malloc(sizeof(KEY));
-
- InitializeListHead(&RootKey->SubKeyList);
- InitializeListHead(&RootKey->ValueList);
- InitializeListHead(&RootKey->KeyList);
-
- RootKey->SubKeyCount = 0;
- RootKey->ValueCount = 0;
-
- RootKey->NameSize = 2;
- RootKey->Name = (PCHAR)malloc(2);
- strcpy(RootKey->Name, "\\");
-
- RootKey->DataType = 0;
- RootKey->DataSize = 0;
- RootKey->Data = NULL;
-
- /* Create SYSTEM key */
- RegCreateKey(RootKey,
- "Registry\\Machine\\SYSTEM",
- NULL);
-
- /* Create link 'CurrentControlSet' --> 'ControlSet001' */
- RegCreateKey(RootKey,
- "Registry\\Machine\\SYSTEM\\ControlSet001",
- &ControlSetKey);
-
- RegCreateKey(RootKey,
- "Registry\\Machine\\SYSTEM\\CurrentControlSet",
- &LinkKey);
-
- RegSetValue(LinkKey,
- NULL,
- REG_LINK,
- (PCHAR)&ControlSetKey,
- sizeof(PVOID));
-
- /* Create HARDWARE key */
- RegCreateKey(RootKey,
- "Registry\\Machine\\HARDWARE",
- NULL);
-
- /* Create SAM key */
- RegCreateKey(RootKey,
- "Registry\\Machine\\SAM",
- NULL);
-
- /* Create SECURITY key */
- RegCreateKey(RootKey,
- "Registry\\Machine\\SECURITY",
- NULL);
-
- /* Create SOFTWARE key */
- RegCreateKey(RootKey,
- "Registry\\Machine\\SOFTWARE",
- NULL);
-
- /* Create DEFAULT key */
- RegCreateKey(RootKey,
- "Registry\\User\\.DEFAULT",
- NULL);
+ MEMKEY Key;
+
+ Key = (MEMKEY) malloc (sizeof(KEY));
+ if (!Key)
+ return NULL;
+
+ InitializeListHead (&Key->SubKeyList);
+ InitializeListHead (&Key->ValueList);
+ InitializeListHead (&Key->KeyList);
+
+ Key->SubKeyCount = 0;
+ Key->ValueCount = 0;
+
+ Key->NameSize = KeyName->Length;
+ /* FIXME: It's not enough to allocate this way, because later
+ this memory gets overwritten with bigger names */
+ Key->Name = malloc (Key->NameSize);
+ if (!Key->Name)
+ return NULL;
+ memcpy(Key->Name, KeyName->Buffer, KeyName->Length);
+
+ Key->DataType = 0;
+ Key->DataSize = 0;
+ Key->Data = NULL;
+
+ Key->RegistryHive = RegistryHive;
+ Key->KeyCellOffset = KeyCellOffset;
+ Key->KeyCell = (PCM_KEY_NODE)HvGetCell (&RegistryHive->Hive, Key->KeyCellOffset);
+ if (!Key->KeyCell)
+ {
+ free(Key);
+ return NULL;
+ }
+ Key->LinkedKey = NULL;
+ return Key;
}
-
-LONG
-RegCreateKey(HKEY ParentKey,
- PCHAR KeyName,
- PHKEY Key)
+static LONG
+RegpOpenOrCreateKey(
+ IN HKEY hParentKey,
+ IN PCWSTR KeyName,
+ IN BOOL AllowCreation,
+ OUT PHKEY Key)
{
- PLIST_ENTRY Ptr;
- HKEY SearchKey = INVALID_HANDLE_VALUE;
- HKEY CurrentKey;
- HKEY NewKey;
- PCHAR p;
- PCHAR name;
- int subkeyLength;
- int stringLength;
-
- DPRINT ("RegCreateKey('%s')\n", KeyName);
-
- if (*KeyName == '\\')
- {
- KeyName++;
- CurrentKey = RootKey;
- }
- else if (ParentKey == NULL)
- {
- CurrentKey = RootKey;
- }
- else
- {
- CurrentKey = ParentKey;
- }
-
- /* Check whether current key is a link */
- if (CurrentKey->DataType == REG_LINK)
- {
- CurrentKey = (HKEY)CurrentKey->Data;
- }
-
- while (*KeyName != 0)
- {
- DPRINT ("KeyName '%s'\n", KeyName);
-
- if (*KeyName == '\\')
- KeyName++;
- p = strchr (KeyName, '\\');
- if ((p != NULL) && (p != KeyName))
+ PWSTR LocalKeyName;
+ PWSTR End;
+ UNICODE_STRING KeyString;
+ NTSTATUS Status;
+ MEMKEY ParentKey;
+ MEMKEY CurrentKey;
+ PLIST_ENTRY Ptr;
+ PCM_KEY_NODE SubKeyCell;
+ HCELL_INDEX BlockOffset;
+
+ DPRINT("RegpCreateOpenKey('%S')\n", KeyName);
+
+ if (*KeyName == L'\\')
{
- subkeyLength = p - KeyName;
- stringLength = subkeyLength + 1;
- name = KeyName;
+ KeyName++;
+ ParentKey = RootKey;
}
- else
+ else if (hParentKey == NULL)
{
- subkeyLength = strlen (KeyName);
- stringLength = subkeyLength;
- name = KeyName;
+ ParentKey = RootKey;
}
-
- Ptr = CurrentKey->SubKeyList.Flink;
- while (Ptr != &CurrentKey->SubKeyList)
+ else
{
- DPRINT ("Ptr 0x%p\n", Ptr);
-
- SearchKey = CONTAINING_RECORD(Ptr,
- KEY,
- KeyList);
- DPRINT ("SearchKey 0x%p\n", SearchKey);
- DPRINT ("Searching '%s'\n", SearchKey->Name);
- if (strncasecmp (SearchKey->Name, name, subkeyLength) == 0)
- break;
-
- Ptr = Ptr->Flink;
+ ParentKey = HKEY_TO_MEMKEY(RootKey);
}
- if (Ptr == &CurrentKey->SubKeyList)
- {
- /* no key found -> create new subkey */
- NewKey = (HKEY)malloc (sizeof(KEY));
- if (NewKey == NULL)
- return ERROR_OUTOFMEMORY;
-
- InitializeListHead (&NewKey->SubKeyList);
- InitializeListHead (&NewKey->ValueList);
-
- NewKey->SubKeyCount = 0;
- NewKey->ValueCount = 0;
-
- NewKey->DataType = 0;
- NewKey->DataSize = 0;
- NewKey->Data = NULL;
-
- InsertTailList (&CurrentKey->SubKeyList, &NewKey->KeyList);
- CurrentKey->SubKeyCount++;
-
- NewKey->NameSize = subkeyLength + 1;
- NewKey->Name = (PCHAR)malloc (NewKey->NameSize);
- if (NewKey->Name == NULL)
- return(ERROR_OUTOFMEMORY);
- memcpy(NewKey->Name, name, subkeyLength);
- NewKey->Name[subkeyLength] = 0;
-
- DPRINT ("NewKey 0x%p\n", NewKey);
- DPRINT ("NewKey '%s' Length %ld\n", NewKey->Name, NewKey->NameSize);
-
- CurrentKey = NewKey;
- }
- else
+ LocalKeyName = (PWSTR)KeyName;
+ for (;;)
{
- CurrentKey = SearchKey;
-
- /* Check whether current key is a link */
- if (CurrentKey->DataType == REG_LINK)
- {
- CurrentKey = (HKEY)CurrentKey->Data;
- }
+ End = (PWSTR) utf16_wcschr(LocalKeyName, '\\');
+ if (End)
+ {
+ KeyString.Buffer = LocalKeyName;
+ KeyString.Length = KeyString.MaximumLength =
+ (USHORT)((ULONG_PTR)End - (ULONG_PTR)LocalKeyName);
+ }
+ else
+ RtlInitUnicodeString(&KeyString, LocalKeyName);
+
+ /* Redirect from 'CurrentControlSet' to 'ControlSet001' */
+ if (!utf16_wcsncmp(LocalKeyName, L"CurrentControlSet", 17) &&
+ ParentKey->NameSize == 12 &&
+ !memcmp(ParentKey->Name, L"SYSTEM", 12))
+ RtlInitUnicodeString(&KeyString, L"ControlSet001");
+
+ /* Check subkey in memory structure */
+ Ptr = ParentKey->SubKeyList.Flink;
+ while (Ptr != &ParentKey->SubKeyList)
+ {
+ CurrentKey = CONTAINING_RECORD(Ptr, KEY, KeyList);
+ if (CurrentKey->NameSize == KeyString.Length
+ && memcmp(CurrentKey->Name, KeyString.Buffer, KeyString.Length) == 0)
+ {
+ goto nextsubkey;
+ }
+
+ Ptr = Ptr->Flink;
+ }
+
+ Status = CmiScanForSubKey(
+ ParentKey->RegistryHive,
+ ParentKey->KeyCell,
+ &KeyString,
+ OBJ_CASE_INSENSITIVE,
+ &SubKeyCell,
+ &BlockOffset);
+ if (AllowCreation && Status == STATUS_OBJECT_NAME_NOT_FOUND)
+ {
+ Status = CmiAddSubKey(
+ ParentKey->RegistryHive,
+ ParentKey->KeyCell,
+ ParentKey->KeyCellOffset,
+ &KeyString,
+ 0,
+ &SubKeyCell,
+ &BlockOffset);
+ }
+ if (!NT_SUCCESS(Status))
+ return ERROR_UNSUCCESSFUL;
+
+ /* Now, SubKeyCell/BlockOffset are valid */
+ CurrentKey = CreateInMemoryStructure(
+ ParentKey->RegistryHive,
+ BlockOffset,
+ &KeyString);
+ if (!CurrentKey)
+ return ERROR_OUTOFMEMORY;
+
+ /* Add CurrentKey in ParentKey */
+ InsertTailList(&ParentKey->SubKeyList, &CurrentKey->KeyList);
+ ParentKey->SubKeyCount++;
+
+nextsubkey:
+ ParentKey = CurrentKey;
+ if (End)
+ LocalKeyName = End + 1;
+ else
+ break;
}
- KeyName = KeyName + stringLength;
- }
+ *Key = MEMKEY_TO_HKEY(ParentKey);
- if (Key != NULL)
- *Key = CurrentKey;
-
- return ERROR_SUCCESS;
+ return ERROR_SUCCESS;
}
-
-LONG
-RegDeleteKey(HKEY Key,
- PCHAR Name)
+LONG WINAPI
+RegCreateKeyW(
+ IN HKEY hKey,
+ IN LPCWSTR lpSubKey,
+ OUT PHKEY phkResult)
{
- if (Name != NULL && strchr(Name, '\\') != NULL)
- return(ERROR_INVALID_PARAMETER);
-
- DPRINT1("FIXME!\n");
-
- return(ERROR_SUCCESS);
+ return RegpOpenOrCreateKey(hKey, lpSubKey, TRUE, phkResult);
}
-
-LONG
-RegEnumKey(HKEY Key,
- ULONG Index,
- PCHAR Name,
- PULONG NameSize)
+static PWSTR
+MultiByteToWideChar(
+ IN PCSTR MultiByteString)
{
- PLIST_ENTRY Ptr;
- HKEY SearchKey;
- ULONG Count = 0;
- ULONG Size;
-
- Ptr = Key->SubKeyList.Flink;
- while (Ptr != &Key->SubKeyList)
- {
- if (Index == Count)
- break;
-
- Count++;
- Ptr = Ptr->Flink;
- }
-
- if (Ptr == &Key->SubKeyList)
- return(ERROR_NO_MORE_ITEMS);
-
- SearchKey = CONTAINING_RECORD(Ptr,
- KEY,
- KeyList);
-
- DPRINT ("Name '%s' Length %ld\n", SearchKey->Name, SearchKey->NameSize);
-
- Size = min(SearchKey->NameSize, *NameSize);
- *NameSize = Size;
- memcpy(Name, SearchKey->Name, Size);
-
- return(ERROR_SUCCESS);
+ ANSI_STRING Source;
+ UNICODE_STRING Destination;
+ NTSTATUS Status;
+
+ RtlInitAnsiString(&Source, MultiByteString);
+ Status = RtlAnsiStringToUnicodeString(&Destination, &Source, TRUE);
+ if (!NT_SUCCESS(Status))
+ return NULL;
+ return Destination.Buffer;
}
-
-LONG
-RegOpenKey(HKEY ParentKey,
- PCHAR KeyName,
- PHKEY Key)
+LONG WINAPI
+RegCreateKeyA(
+ IN HKEY hKey,
+ IN LPCSTR lpSubKey,
+ OUT PHKEY phkResult)
{
- PLIST_ENTRY Ptr;
- HKEY SearchKey = INVALID_HANDLE_VALUE;
- HKEY CurrentKey;
- PCHAR p;
- PCHAR name;
- int subkeyLength;
- int stringLength;
-
- DPRINT("KeyName '%s'\n", KeyName);
-
- *Key = NULL;
-
- if (*KeyName == '\\')
- {
- KeyName++;
- CurrentKey = RootKey;
- }
- else if (ParentKey == NULL)
- {
- CurrentKey = RootKey;
- }
- else
- {
- CurrentKey = ParentKey;
- }
-
- /* Check whether current key is a link */
- if (CurrentKey->DataType == REG_LINK)
- {
- CurrentKey = (HKEY)CurrentKey->Data;
- }
-
- while (*KeyName != 0)
- {
- DPRINT ("KeyName '%s'\n", KeyName);
-
- if (*KeyName == '\\')
- KeyName++;
- p = strchr(KeyName, '\\');
- if ((p != NULL) && (p != KeyName))
- {
- subkeyLength = p - KeyName;
- stringLength = subkeyLength + 1;
- name = KeyName;
- }
- else
- {
- subkeyLength = strlen(KeyName);
- stringLength = subkeyLength;
- name = KeyName;
- }
+ PWSTR lpSubKeyW;
+ LONG rc;
- Ptr = CurrentKey->SubKeyList.Flink;
- while (Ptr != &CurrentKey->SubKeyList)
- {
- DPRINT ("Ptr 0x%p\n", Ptr);
+ lpSubKeyW = MultiByteToWideChar(lpSubKey);
+ if (!lpSubKeyW)
+ return ERROR_OUTOFMEMORY;
- SearchKey = CONTAINING_RECORD(Ptr,
- KEY,
- KeyList);
+ rc = RegCreateKeyW(hKey, lpSubKeyW, phkResult);
+ free(lpSubKeyW);
+ return rc;
+}
- DPRINT ("SearchKey 0x%p\n", SearchKey);
- DPRINT ("Searching '%s'\n", SearchKey->Name);
+LONG WINAPI
+RegDeleteKeyW(
+ IN HKEY hKey,
+ IN LPCWSTR lpSubKey)
+{
+ DPRINT1("FIXME!\n");
+ return ERROR_SUCCESS;
+}
- if (strncasecmp(SearchKey->Name, name, subkeyLength) == 0)
- break;
+LONG WINAPI
+RegDeleteKeyA(
+ IN HKEY hKey,
+ IN LPCSTR lpSubKey)
+{
+ PWSTR lpSubKeyW = NULL;
+ LONG rc;
- Ptr = Ptr->Flink;
- }
+ if (lpSubKey != NULL && strchr(lpSubKey, '\\') != NULL)
+ return ERROR_INVALID_PARAMETER;
- if (Ptr == &CurrentKey->SubKeyList)
+ if (lpSubKey)
{
- return(ERROR_PATH_NOT_FOUND);
- }
- else
- {
- CurrentKey = SearchKey;
-
- /* Check whether current key is a link */
- if (CurrentKey->DataType == REG_LINK)
- {
- CurrentKey = (HKEY)CurrentKey->Data;
- }
+ lpSubKeyW = MultiByteToWideChar(lpSubKey);
+ if (!lpSubKeyW)
+ return ERROR_OUTOFMEMORY;
}
- KeyName = KeyName + stringLength;
- }
+ rc = RegDeleteKeyW(hKey, lpSubKeyW);
- if (Key != NULL)
- *Key = CurrentKey;
+ if (lpSubKey)
+ free(lpSubKeyW);
- return(ERROR_SUCCESS);
+ return rc;
}
+LONG WINAPI
+RegOpenKeyW(
+ IN HKEY hKey,
+ IN LPCWSTR lpSubKey,
+ OUT PHKEY phkResult)
+{
+ return RegpOpenOrCreateKey(hKey, lpSubKey, FALSE, phkResult);
+}
-LONG
-RegSetValue(HKEY Key,
- PCHAR ValueName,
- ULONG Type,
- PCHAR Data,
- ULONG DataSize)
+LONG WINAPI
+RegOpenKeyA(
+ IN HKEY hKey,
+ IN LPCSTR lpSubKey,
+ OUT PHKEY phkResult)
{
- PLIST_ENTRY Ptr;
- PVALUE Value = NULL;
+ PWSTR lpSubKeyW;
+ LONG rc;
- DPRINT ("Key 0x%x, ValueName '%s', Type %d, Data 0x%x, DataSize %d\n",
- (int)Key, ValueName, (int)Type, (int)Data, (int)DataSize);
+ lpSubKeyW = MultiByteToWideChar(lpSubKey);
+ if (!lpSubKeyW)
+ return ERROR_OUTOFMEMORY;
- if ((ValueName == NULL) || (*ValueName == 0))
- {
- /* set default value */
- if ((Key->Data != NULL) && (Key->DataSize > sizeof(PCHAR)))
- {
- free(Key->Data);
- }
+ rc = RegOpenKeyW(hKey, lpSubKeyW, phkResult);
+ free(lpSubKeyW);
+ return rc;
+}
- if (DataSize <= sizeof(PCHAR))
+static LONG
+RegpOpenOrCreateValue(
+ IN HKEY hKey,
+ IN LPCWSTR ValueName,
+ IN BOOL AllowCreation,
+ OUT PCM_KEY_VALUE *ValueCell,
+ OUT PHCELL_INDEX ValueCellOffset)
+{
+ MEMKEY ParentKey;
+ UNICODE_STRING ValueString;
+ NTSTATUS Status;
+
+ ParentKey = HKEY_TO_MEMKEY(hKey);
+ RtlInitUnicodeString(&ValueString, ValueName);
+
+ Status = CmiScanForValueKey(
+ ParentKey->RegistryHive,
+ ParentKey->KeyCell,
+ &ValueString,
+ ValueCell,
+ ValueCellOffset);
+ if (AllowCreation && Status == STATUS_OBJECT_NAME_NOT_FOUND)
{
- Key->DataSize = DataSize;
- Key->DataType = Type;
- memcpy(&Key->Data, Data, DataSize);
+ Status = CmiAddValueKey(
+ ParentKey->RegistryHive,
+ ParentKey->KeyCell,
+ ParentKey->KeyCellOffset,
+ &ValueString,
+ ValueCell,
+ ValueCellOffset);
}
- else
+ if (!NT_SUCCESS(Status))
+ return ERROR_UNSUCCESSFUL;
+ return ERROR_SUCCESS;
+}
+
+LONG WINAPI
+RegSetValueExW(
+ IN HKEY hKey,
+ IN LPCWSTR lpValueName OPTIONAL,
+ IN ULONG Reserved,
+ IN ULONG dwType,
+ IN const UCHAR* lpData,
+ IN USHORT cbData)
+{
+ MEMKEY Key, DestKey;
+ PHKEY phKey;
+ PCM_KEY_VALUE ValueCell;
+ HCELL_INDEX ValueCellOffset;
+ PVOID DataCell;
+ LONG DataCellSize;
+ NTSTATUS Status;
+
+ if (dwType == REG_LINK)
{
- Key->Data = (PCHAR)malloc(DataSize);
- Key->DataSize = DataSize;
- Key->DataType = Type;
- memcpy(Key->Data, Data, DataSize);
+ /* Special handling of registry links */
+ if (cbData != sizeof(PVOID))
+ return STATUS_INVALID_PARAMETER;
+ phKey = (PHKEY)lpData;
+ Key = HKEY_TO_MEMKEY(hKey);
+ DestKey = HKEY_TO_MEMKEY(*phKey);
+
+ /* Create the link in memory */
+ Key->DataType = REG_LINK;
+ Key->LinkedKey = 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;
}
- }
- else
- {
- /* set non-default value */
- Ptr = Key->ValueList.Flink;
- while (Ptr != &Key->ValueList)
- {
- Value = CONTAINING_RECORD(Ptr,
- VALUE,
- ValueList);
- DPRINT ("Value->Name '%s'\n", Value->Name);
+ if ((cbData & REG_DATA_SIZE_MASK) != cbData)
+ return STATUS_UNSUCCESSFUL;
- if (strcasecmp(Value->Name, ValueName) == 0)
- break;
+ Key = HKEY_TO_MEMKEY(hKey);
- Ptr = Ptr->Flink;
- }
+ Status = RegpOpenOrCreateValue(hKey, lpValueName, TRUE, &ValueCell, &ValueCellOffset);
+ if (!NT_SUCCESS(Status))
+ return ERROR_UNSUCCESSFUL;
- if (Ptr == &Key->ValueList)
+ /* Get size of the allocated cellule (if any) */
+ if (!(ValueCell->DataLength & REG_DATA_IN_OFFSET) &&
+ (ValueCell->DataLength & REG_DATA_SIZE_MASK) != 0)
{
- /* add new value */
- DPRINT("No value found - adding new value\n");
-
- Value = (PVALUE)malloc(sizeof(VALUE));
- if (Value == NULL)
- return(ERROR_OUTOFMEMORY);
- InsertTailList(&Key->ValueList, &Value->ValueList);
- Key->ValueCount++;
- Value->NameSize = strlen(ValueName)+1;
- Value->Name = (PCHAR)malloc(Value->NameSize);
- if (Value->Name == NULL)
- return(ERROR_OUTOFMEMORY);
- strcpy(Value->Name, ValueName);
- Value->DataType = REG_NONE;
- Value->DataSize = 0;
- Value->Data = NULL;
+ DataCell = HvGetCell(&Key->RegistryHive->Hive, ValueCell->Data);
+ if (!DataCell)
+ return ERROR_UNSUCCESSFUL;
+ DataCellSize = -HvGetCellSize(&Key->RegistryHive->Hive, DataCell);
}
-
- /* set new value */
- if ((Value->Data != NULL) && (Value->DataSize > sizeof(PCHAR)))
+ else
{
- free(Value->Data);
+ DataCell = NULL;
+ DataCellSize = 0;
}
- if (DataSize <= sizeof(PCHAR))
+ if (cbData <= sizeof(HCELL_INDEX))
{
- Value->DataSize = DataSize;
- Value->DataType = Type;
- memcpy(&Value->Data, Data, DataSize);
+ /* If data size <= sizeof(HCELL_INDEX) then store data in the data offset */
+ DPRINT("ValueCell->DataLength %u\n", ValueCell->DataLength);
+ if (DataCell)
+ HvFreeCell(&Key->RegistryHive->Hive, ValueCell->Data);
+
+ RtlCopyMemory(&ValueCell->Data, lpData, cbData);
+ ValueCell->DataLength = (ULONG)(cbData | REG_DATA_IN_OFFSET);
+ ValueCell->Type = dwType;
+ HvMarkCellDirty(&Key->RegistryHive->Hive, ValueCellOffset, FALSE);
}
- else
+ else
{
- Value->Data = (PCHAR)malloc(DataSize);
- if (Value->Data == NULL)
- return(ERROR_OUTOFMEMORY);
- Value->DataType = Type;
- Value->DataSize = DataSize;
- memcpy(Value->Data, Data, DataSize);
+ if (cbData > (SIZE_T)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(&Key->RegistryHive->Hive, cbData, Stable, HCELL_NIL);
+ if (NewOffset == HCELL_NIL)
+ {
+ DPRINT("HvAllocateCell() failed with status 0x%08x\n", Status);
+ return ERROR_UNSUCCESSFUL;
+ }
+
+ if (DataCell)
+ HvFreeCell(&Key->RegistryHive->Hive, ValueCell->Data);
+
+ ValueCell->Data = NewOffset;
+ DataCell = (PVOID)HvGetCell(&Key->RegistryHive->Hive, NewOffset);
+ }
+
+ /* Copy new contents to cellule */
+ RtlCopyMemory(DataCell, lpData, cbData);
+ ValueCell->DataLength = (ULONG)(cbData & REG_DATA_SIZE_MASK);
+ ValueCell->Type = dwType;
+ HvMarkCellDirty(&Key->RegistryHive->Hive, ValueCell->Data, FALSE);
+ HvMarkCellDirty(&Key->RegistryHive->Hive, ValueCellOffset, FALSE);
}
- }
- return(ERROR_SUCCESS);
-}
-
-LONG
-RegQueryValue(HKEY Key,
- PCHAR ValueName,
- PULONG Type,
- PCHAR Data,
- PULONG DataSize)
-{
- ULONG Size;
- PLIST_ENTRY Ptr;
- PVALUE Value = NULL;
-
- if ((ValueName == NULL) || (*ValueName == 0))
- {
- /* query default value */
- if (Key->Data == NULL)
- return(ERROR_INVALID_PARAMETER);
-
- if (Type != NULL)
- *Type = Key->DataType;
- if ((Data != NULL) && (DataSize != NULL))
- {
- if (Key->DataSize <= sizeof(PCHAR))
- {
- Size = min(Key->DataSize, *DataSize);
- memcpy(Data, &Key->Data, Size);
- *DataSize = Size;
- }
- else
- {
- Size = min(Key->DataSize, *DataSize);
- memcpy(Data, Key->Data, Size);
- *DataSize = Size;
- }
- }
- else if ((Data == NULL) && (DataSize != NULL))
- {
- *DataSize = Key->DataSize;
- }
- }
- else
- {
- /* query non-default value */
- Ptr = Key->ValueList.Flink;
- while (Ptr != &Key->ValueList)
- {
- Value = CONTAINING_RECORD(Ptr,
- VALUE,
- ValueList);
+ HvMarkCellDirty(&Key->RegistryHive->Hive, Key->KeyCellOffset, FALSE);
- DPRINT("Searching for '%s'. Value name '%s'\n", ValueName, Value->Name);
+ DPRINT("Return status 0x%08x\n", Status);
+ return Status;
+}
- if (strcasecmp(Value->Name, ValueName) == 0)
- break;
+LONG WINAPI
+RegSetValueExA(
+ IN HKEY hKey,
+ IN LPCSTR lpValueName OPTIONAL,
+ IN ULONG Reserved,
+ IN ULONG dwType,
+ IN const UCHAR* lpData,
+ IN ULONG cbData)
+{
+ LPWSTR lpValueNameW = NULL;
+ const UCHAR* lpDataW;
+ USHORT cbDataW;
+ LONG rc = ERROR_SUCCESS;
- Ptr = Ptr->Flink;
+ DPRINT("RegSetValueA(%s)\n", lpValueName);
+ if (lpValueName)
+ {
+ lpValueNameW = MultiByteToWideChar(lpValueName);
+ if (!lpValueNameW)
+ return ERROR_OUTOFMEMORY;
}
- if (Ptr == &Key->ValueList)
- return(ERROR_INVALID_PARAMETER);
-
- if (Type != NULL)
- *Type = Value->DataType;
- if ((Data != NULL) && (DataSize != NULL))
+ if ((dwType == REG_SZ || dwType == REG_EXPAND_SZ || dwType == REG_MULTI_SZ)
+ && cbData != 0)
{
- if (Value->DataSize <= sizeof(PCHAR))
- {
- Size = min(Value->DataSize, *DataSize);
- memcpy(Data, &Value->Data, Size);
- *DataSize = Size;
- }
- else
- {
- Size = min(Value->DataSize, *DataSize);
- memcpy(Data, Value->Data, Size);
- *DataSize = Size;
- }
+ ANSI_STRING AnsiString;
+ UNICODE_STRING Data;
+
+ if (lpData[cbData - 1] != '\0')
+ cbData++;
+ RtlInitAnsiString(&AnsiString, NULL);
+ AnsiString.Buffer = (PSTR)lpData;
+ AnsiString.Length = (USHORT)cbData - 1;
+ AnsiString.MaximumLength = (USHORT)cbData;
+ RtlAnsiStringToUnicodeString (&Data, &AnsiString, TRUE);
+ lpDataW = (const UCHAR*)Data.Buffer;
+ cbDataW = Data.MaximumLength;
}
- else if ((Data == NULL) && (DataSize != NULL))
+ else
{
- *DataSize = Value->DataSize;
+ lpDataW = lpData;
+ cbDataW = (USHORT)cbData;
}
- }
- return(ERROR_SUCCESS);
+ if (rc == ERROR_SUCCESS)
+ rc = RegSetValueExW(hKey, lpValueNameW, 0, dwType, lpDataW, cbDataW);
+ if (lpValueNameW)
+ free(lpValueNameW);
+ if (lpData != lpDataW)
+ free((PVOID)lpDataW);
+ return rc;
}
+LONG WINAPI
+RegQueryValueExW(
+ IN HKEY hKey,
+ IN LPCWSTR lpValueName,
+ IN PULONG lpReserved,
+ OUT PULONG lpType,
+ OUT PUCHAR lpData,
+ OUT PSIZE_T lpcbData)
+{
+ //ParentKey = HKEY_TO_MEMKEY(RootKey);
+ PCM_KEY_VALUE ValueCell;
+ HCELL_INDEX ValueCellOffset;
+ LONG rc;
+
+ rc = RegpOpenOrCreateValue(
+ hKey,
+ lpValueName,
+ FALSE,
+ &ValueCell,
+ &ValueCellOffset);
+ if (rc != ERROR_SUCCESS)
+ return rc;
+
+ DPRINT1("RegQueryValueExW(%S) not implemented\n", lpValueName);
+ /* ValueCell and ValueCellOffset are valid */
+
+ return ERROR_UNSUCCESSFUL;
+}
-LONG
-RegDeleteValue(HKEY Key,
- PCHAR ValueName)
+LONG WINAPI
+RegQueryValueExA(
+ IN HKEY hKey,
+ IN LPCSTR lpValueName,
+ IN PULONG lpReserved,
+ OUT PULONG lpType,
+ OUT PUCHAR lpData,
+ OUT PSIZE_T lpcbData)
{
- PLIST_ENTRY Ptr;
- PVALUE Value = NULL;
-
- if ((ValueName == NULL) || (*ValueName == 0))
- {
- /* delete default value */
- if (Key->Data != NULL)
- free(Key->Data);
- Key->Data = NULL;
- Key->DataSize = 0;
- Key->DataType = 0;
- }
- else
- {
- /* delete non-default value */
- Ptr = Key->ValueList.Flink;
- while (Ptr != &Key->ValueList)
- {
- Value = CONTAINING_RECORD(Ptr,
- VALUE,
- ValueList);
- if (strcasecmp(Value->Name, ValueName) == 0)
- break;
+ LPWSTR lpValueNameW = NULL;
+ LONG rc;
- Ptr = Ptr->Flink;
+ if (lpValueName)
+ {
+ lpValueNameW = MultiByteToWideChar(lpValueName);
+ if (!lpValueNameW)
+ return ERROR_OUTOFMEMORY;
}
- if (Ptr == &Key->ValueList)
- return(ERROR_INVALID_PARAMETER);
+ rc = RegQueryValueExW(hKey, lpValueNameW, lpReserved, lpType, lpData, lpcbData);
+ if (lpValueNameW)
+ free(lpValueNameW);
+ return ERROR_UNSUCCESSFUL;
+}
+
+LONG WINAPI
+RegDeleteValueW(
+ IN HKEY hKey,
+ IN LPCWSTR lpValueName OPTIONAL)
+{
+ DPRINT1("RegDeleteValueW() unimplemented\n");
+ return ERROR_UNSUCCESSFUL;
+}
- /* delete value */
- Key->ValueCount--;
- if (Value->Name != NULL)
- free(Value->Name);
- Value->Name = NULL;
- Value->NameSize = 0;
+LONG WINAPI
+RegDeleteValueA(
+ IN HKEY hKey,
+ IN LPCSTR lpValueName OPTIONAL)
+{
+ LPWSTR lpValueNameW;
+ LONG rc;
- if (Value->DataSize > sizeof(PCHAR))
+ if (lpValueName)
{
- if (Value->Data != NULL)
- free(Value->Data);
+ lpValueNameW = MultiByteToWideChar(lpValueName);
+ if (!lpValueNameW)
+ return ERROR_OUTOFMEMORY;
+ rc = RegDeleteValueW(hKey, lpValueNameW);
+ free(lpValueNameW);
}
- Value->Data = NULL;
- Value->DataSize = 0;
- Value->DataType = 0;
-
- RemoveEntryList(&Value->ValueList);
- free(Value);
- }
- return(ERROR_SUCCESS);
+ else
+ rc = RegDeleteValueW(hKey, NULL);
+ return rc;
}
-
-LONG
-RegEnumValue(HKEY Key,
- ULONG Index,
- PCHAR ValueName,
- PULONG NameSize,
- PULONG Type,
- PCHAR Data,
- PULONG DataSize)
+static BOOL
+ConnectRegistry(
+ IN HKEY RootKey,
+ IN PCMHIVE HiveToConnect,
+ IN LPCWSTR Path)
{
- PLIST_ENTRY Ptr;
- PVALUE Value;
- ULONG Count = 0;
+ NTSTATUS Status;
+ MEMKEY NewKey;
+ LONG rc;
- if (Key->Data != NULL)
- {
- if (Index > 0)
- {
- Index--;
- }
- else
+ Status = CmiInitializeTempHive(HiveToConnect);
+ if (!NT_SUCCESS(Status))
{
- /* enumerate default value */
- if (ValueName != NULL)
- *ValueName = 0;
- if (Type != NULL)
- *Type = Key->DataType;
- if (DataSize != NULL)
- *DataSize = Key->DataSize;
-
- /* FIXME: return more values */
+ DPRINT1("CmiInitializeTempHive() failed with status 0x%08x\n", Status);
+ return FALSE;
}
- }
- Ptr = Key->ValueList.Flink;
- while (Ptr != &Key->ValueList)
- {
- if (Index == Count)
- break;
-
- Count++;
- Ptr = Ptr->Flink;
- }
-
- if (Ptr == &Key->ValueList)
- return(ERROR_NO_MORE_ITEMS);
-
- Value = CONTAINING_RECORD(Ptr,
- VALUE,
- ValueList);
-
- /* FIXME: return values */
-
- return(ERROR_SUCCESS);
+ /* Create key */
+ rc = RegCreateKeyW(
+ RootKey,
+ Path,
+ (PHKEY)&NewKey);
+ if (rc != ERROR_SUCCESS)
+ return FALSE;
+
+ NewKey->RegistryHive = HiveToConnect;
+ NewKey->KeyCellOffset = HiveToConnect->Hive.BaseBlock->RootCell;
+ NewKey->KeyCell = (PCM_KEY_NODE)HvGetCell (&HiveToConnect->Hive, NewKey->KeyCellOffset);
+ return TRUE;
}
+LIST_ENTRY CmiHiveListHead;
-USHORT
-RegGetSubKeyCount (HKEY Key)
+VOID
+RegInitializeRegistry(VOID)
{
- return Key->SubKeyCount;
-}
+ UNICODE_STRING RootKeyName = RTL_CONSTANT_STRING(L"\\");
+ NTSTATUS Status;
+ HKEY ControlSetKey;
+ InitializeListHead(&CmiHiveListHead);
-ULONG
-RegGetValueCount (HKEY Key)
-{
- if (Key->DataSize != 0)
- return Key->ValueCount + 1;
+ Status = CmiInitializeTempHive(&RootHive);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("CmiInitializeTempHive() failed with status 0x%08x\n", Status);
+ return;
+ }
- return Key->ValueCount;
+ RootKey = CreateInMemoryStructure(
+ &RootHive,
+ RootHive.Hive.BaseBlock->RootCell,
+ &RootKeyName);
+
+ /* Create DEFAULT key */
+ ConnectRegistry(
+ NULL,
+ &DefaultHive,
+ L"Registry\\User\\.DEFAULT");
+
+ /* Create SAM key */
+ ConnectRegistry(
+ NULL,
+ &SamHive,
+ L"Registry\\Machine\\SAM");
+
+ /* Create SECURITY key */
+ ConnectRegistry(
+ NULL,
+ &SecurityHive,
+ L"Registry\\Machine\\SECURITY");
+
+ /* Create SOFTWARE key */
+ ConnectRegistry(
+ NULL,
+ &SoftwareHive,
+ L"Registry\\Machine\\SOFTWARE");
+
+ /* Create SYSTEM key */
+ ConnectRegistry(
+ NULL,
+ &SystemHive,
+ L"Registry\\Machine\\SYSTEM");
+
+ /* Create 'ControlSet001' key */
+ RegCreateKeyW(
+ NULL,
+ L"Registry\\Machine\\SYSTEM\\ControlSet001",
+ &ControlSetKey);
}
/* EOF */