[MKHIVE]
[reactos.git] / reactos / tools / mkhive / registry.c
index f4863d3..e182596 100644 (file)
@@ -12,9 +12,9 @@
  *  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.
  */
 /* COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS hive maker
@@ -25,9 +25,9 @@
 
 /*
  * TODO:
- *     - Implement RegDeleteKey()
+ *     - Implement RegDeleteKeyW()
  *     - Implement RegEnumValue()
- *     - Implement RegQueryValueExA()
+ *     - Implement RegQueryValueExW()
  */
 
 #include <stdlib.h>
 #define NDEBUG
 #include "mkhive.h"
 
-static EREGISTRY_HIVE RootHive;
+#define REG_DATA_SIZE_MASK                 0x7FFFFFFF
+#define REG_DATA_IN_OFFSET                 0x80000000
+
+static CMHIVE RootHive;
 static MEMKEY RootKey;
-EREGISTRY_HIVE DefaultHive;  /* \Registry\User\.DEFAULT */
-EREGISTRY_HIVE SamHive;      /* \Registry\Machine\SAM */
-EREGISTRY_HIVE SecurityHive; /* \Registry\Machine\SECURITY */
-EREGISTRY_HIVE SoftwareHive; /* \Registry\Machine\SOFTWARE */
-EREGISTRY_HIVE SystemHive;   /* \Registry\Machine\SYSTEM */
+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 PEREGISTRY_HIVE RegistryHive,
+       IN PCMHIVE RegistryHive,
        IN HCELL_INDEX KeyCellOffset,
        IN PCUNICODE_STRING KeyName)
 {
@@ -65,6 +68,8 @@ CreateInMemoryStructure(
        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;
@@ -76,7 +81,7 @@ CreateInMemoryStructure(
 
        Key->RegistryHive = RegistryHive;
        Key->KeyCellOffset = KeyCellOffset;
-       Key->KeyCell = HvGetCell (&RegistryHive->Hive, Key->KeyCellOffset);
+       Key->KeyCell = (PCM_KEY_NODE)HvGetCell (&RegistryHive->Hive, Key->KeyCellOffset);
        if (!Key->KeyCell)
        {
                free(Key);
@@ -122,7 +127,7 @@ RegpOpenOrCreateKey(
        LocalKeyName = (PWSTR)KeyName;
        for (;;)
        {
-               End = wcschr(LocalKeyName, '\\');
+               End = (PWSTR) utf16_wcschr(LocalKeyName, '\\');
                if (End)
                {
                        KeyString.Buffer = LocalKeyName;
@@ -132,6 +137,12 @@ RegpOpenOrCreateKey(
                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)
@@ -150,7 +161,7 @@ RegpOpenOrCreateKey(
                        ParentKey->RegistryHive,
                        ParentKey->KeyCell,
                        &KeyString,
-                       0,
+                       OBJ_CASE_INSENSITIVE,
                        &SubKeyCell,
                        &BlockOffset);
                if (AllowCreation && Status == STATUS_OBJECT_NAME_NOT_FOUND)
@@ -180,9 +191,6 @@ RegpOpenOrCreateKey(
                ParentKey->SubKeyCount++;
 
 nextsubkey:
-               /* Follow registry links */
-               while (CurrentKey->LinkedKey)
-                       CurrentKey = CurrentKey->LinkedKey;
                ParentKey = CurrentKey;
                if (End)
                        LocalKeyName = End + 1;
@@ -238,15 +246,34 @@ RegCreateKeyA(
 }
 
 LONG WINAPI
-RegDeleteKeyA(HKEY Key,
-            LPCSTR Name)
+RegDeleteKeyW(IN HKEY hKey,
+             IN LPCWSTR lpSubKey)
 {
-  if (Name != NULL && strchr(Name, '\\') != NULL)
-    return(ERROR_INVALID_PARAMETER);
+       if (lpSubKey != NULL && wcschr(lpSubKey, L'\\') != NULL)
+               return(ERROR_INVALID_PARAMETER);
+
+       DPRINT1("RegDeleteKeyW: FIXME!\n");
+
+       return(ERROR_SUCCESS);
+}
+
+LONG WINAPI
+RegDeleteKeyA(IN HKEY hKey,
+             IN LPCSTR lpSubKey)
+{
+       PWSTR lpSubKeyW;
+       LONG rc;
+
+       if (lpSubKey != NULL && strchr(lpSubKey, '\\') != NULL)
+               return(ERROR_INVALID_PARAMETER);
 
-  DPRINT1("FIXME!\n");
+       lpSubKeyW = MultiByteToWideChar(lpSubKey);
+       if (!lpSubKeyW)
+               return ERROR_OUTOFMEMORY;
 
-  return(ERROR_SUCCESS);
+       rc = RegDeleteKeyW(hKey, lpSubKeyW);
+       free(lpSubKeyW);
+       return rc;
 }
 
 LONG WINAPI
@@ -276,7 +303,7 @@ RegOpenKeyA(
        return rc;
 }
 
-static NTSTATUS
+static LONG
 RegpOpenOrCreateValue(
        IN HKEY hKey,
        IN LPCWSTR ValueName,
@@ -308,8 +335,8 @@ RegpOpenOrCreateValue(
                        ValueCellOffset);
        }
        if (!NT_SUCCESS(Status))
-               return Status;
-       return STATUS_SUCCESS;
+               return ERROR_UNSUCCESSFUL;
+       return ERROR_SUCCESS;
 }
 
 LONG WINAPI
@@ -318,7 +345,7 @@ RegSetValueExW(
        IN LPCWSTR lpValueName OPTIONAL,
        IN ULONG Reserved,
        IN ULONG dwType,
-       IN const PUCHAR lpData,
+       IN const UCHAR* lpData,
        IN USHORT cbData)
 {
        MEMKEY Key, DestKey;
@@ -339,6 +366,7 @@ RegSetValueExW(
                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) */
@@ -358,10 +386,10 @@ RegSetValueExW(
                return ERROR_UNSUCCESSFUL;
 
        /* Get size of the allocated cellule (if any) */
-       if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET) &&
-               (ValueCell->DataSize & REG_DATA_SIZE_MASK) != 0)
+       if (!(ValueCell->DataLength & REG_DATA_IN_OFFSET) &&
+               (ValueCell->DataLength & REG_DATA_SIZE_MASK) != 0)
        {
-               DataCell = HvGetCell(&Key->RegistryHive->Hive, ValueCell->DataOffset);
+               DataCell = HvGetCell(&Key->RegistryHive->Hive, ValueCell->Data);
                if (!DataCell)
                        return ERROR_UNSUCCESSFUL;
                DataCellSize = -HvGetCellSize(&Key->RegistryHive->Hive, DataCell);
@@ -375,14 +403,14 @@ RegSetValueExW(
        if (cbData <= sizeof(HCELL_INDEX))
        {
                /* If data size <= sizeof(HCELL_INDEX) then store data in the data offset */
-               DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
+               DPRINT("ValueCell->DataLength %u\n", ValueCell->DataLength);
                if (DataCell)
-                       HvFreeCell(&Key->RegistryHive->Hive, ValueCell->DataOffset);
+                       HvFreeCell(&Key->RegistryHive->Hive, ValueCell->Data);
 
-               RtlCopyMemory(&ValueCell->DataOffset, lpData, cbData);
-               ValueCell->DataSize = (ULONG)(cbData | REG_DATA_IN_OFFSET);
-               ValueCell->DataType = dwType;
-               HvMarkCellDirty(&Key->RegistryHive->Hive, ValueCellOffset);
+               RtlCopyMemory(&ValueCell->Data, lpData, cbData);
+               ValueCell->DataLength = (ULONG)(cbData | REG_DATA_IN_OFFSET);
+               ValueCell->Type = dwType;
+               HvMarkCellDirty(&Key->RegistryHive->Hive, ValueCellOffset, FALSE);
        }
        else
        {
@@ -392,33 +420,33 @@ RegSetValueExW(
                         * data block and allocate a new one. */
                        HCELL_INDEX NewOffset;
 
-                       DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
+                       DPRINT("ValueCell->DataLength %u\n", ValueCell->DataLength);
 
-                       NewOffset = HvAllocateCell(&Key->RegistryHive->Hive, cbData, HvStable);
-                       if (NewOffset == HCELL_NULL)
+                       NewOffset = HvAllocateCell(&Key->RegistryHive->Hive, cbData, Stable, HCELL_NIL);
+                       if (NewOffset == HCELL_NIL)
                        {
-                               DPRINT("HvAllocateCell() failed with status 0x%08lx\n", Status);
+                               DPRINT("HvAllocateCell() failed with status 0x%08x\n", Status);
                                return ERROR_UNSUCCESSFUL;
                        }
 
                        if (DataCell)
-                               HvFreeCell(&Key->RegistryHive->Hive, ValueCell->DataOffset);
+                               HvFreeCell(&Key->RegistryHive->Hive, ValueCell->Data);
 
-                       ValueCell->DataOffset = NewOffset;
-                       DataCell = HvGetCell(&Key->RegistryHive->Hive, NewOffset);
+                       ValueCell->Data = NewOffset;
+                       DataCell = (PVOID)HvGetCell(&Key->RegistryHive->Hive, NewOffset);
                }
 
                /* Copy new contents to cellule */
                RtlCopyMemory(DataCell, lpData, cbData);
-               ValueCell->DataSize = (ULONG)(cbData & REG_DATA_SIZE_MASK);
-               ValueCell->DataType = dwType;
-               HvMarkCellDirty(&Key->RegistryHive->Hive, ValueCell->DataOffset);
-               HvMarkCellDirty(&Key->RegistryHive->Hive, ValueCellOffset);
+               ValueCell->DataLength = (ULONG)(cbData & REG_DATA_SIZE_MASK);
+               ValueCell->Type = dwType;
+               HvMarkCellDirty(&Key->RegistryHive->Hive, ValueCell->Data, FALSE);
+               HvMarkCellDirty(&Key->RegistryHive->Hive, ValueCellOffset, FALSE);
        }
 
-       HvMarkCellDirty(&Key->RegistryHive->Hive, Key->KeyCellOffset);
+       HvMarkCellDirty(&Key->RegistryHive->Hive, Key->KeyCellOffset, FALSE);
 
-       DPRINT("Return status 0x%08lx\n", Status);
+       DPRINT("Return status 0x%08x\n", Status);
        return Status;
 }
 
@@ -428,11 +456,11 @@ RegSetValueExA(
        IN LPCSTR lpValueName OPTIONAL,
        IN ULONG Reserved,
        IN ULONG dwType,
-       IN const PUCHAR lpData,
+       IN const UCHAR* lpData,
        IN ULONG cbData)
 {
        LPWSTR lpValueNameW = NULL;
-       PUCHAR lpDataW;
+       const UCHAR* lpDataW;
        USHORT cbDataW;
        LONG rc = ERROR_SUCCESS;
 
@@ -457,7 +485,7 @@ RegSetValueExA(
                AnsiString.Length = (USHORT)cbData - 1;
                AnsiString.MaximumLength = (USHORT)cbData;
                RtlAnsiStringToUnicodeString (&Data, &AnsiString, TRUE);
-               lpDataW = (const PUCHAR)Data.Buffer;
+               lpDataW = (const UCHAR*)Data.Buffer;
                cbDataW = Data.MaximumLength;
        }
        else
@@ -471,7 +499,7 @@ RegSetValueExA(
        if (lpValueNameW)
                free(lpValueNameW);
        if (lpData != lpDataW)
-               free(lpDataW);
+               free((PVOID)lpDataW);
        return rc;
 }
 
@@ -487,17 +515,20 @@ RegQueryValueExW(
        //ParentKey = HKEY_TO_MEMKEY(RootKey);
        PCM_KEY_VALUE ValueCell;
        HCELL_INDEX ValueCellOffset;
-       NTSTATUS Status;
+       LONG rc;
 
-       Status = RegpOpenOrCreateValue(
+       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 */
 
-       //Status = CmiScanForValueKey(
-       //      x
        return ERROR_UNSUCCESSFUL;
 }
 
@@ -513,7 +544,6 @@ RegQueryValueExA(
        LPWSTR lpValueNameW = NULL;
        LONG rc;
 
-       DPRINT1("RegQueryValueExA(%s) not implemented\n", lpValueName);
        if (lpValueName)
        {
                lpValueNameW = MultiByteToWideChar(lpValueName);
@@ -560,7 +590,7 @@ RegDeleteValueA(
 static BOOL
 ConnectRegistry(
        IN HKEY RootKey,
-       IN PEREGISTRY_HIVE HiveToConnect,
+       IN PCMHIVE HiveToConnect,
        IN LPCWSTR Path)
 {
        NTSTATUS Status;
@@ -570,7 +600,7 @@ ConnectRegistry(
        Status = CmiInitializeTempHive(HiveToConnect);
        if (!NT_SUCCESS(Status))
        {
-               DPRINT1("CmiInitializeTempHive() failed with status 0x%08lx\n", Status);
+               DPRINT1("CmiInitializeTempHive() failed with status 0x%08x\n", Status);
                return FALSE;
        }
 
@@ -583,34 +613,11 @@ ConnectRegistry(
                return FALSE;
 
        NewKey->RegistryHive = HiveToConnect;
-       NewKey->KeyCellOffset = HiveToConnect->Hive.HiveHeader->RootCell;
-       NewKey->KeyCell = HvGetCell (&HiveToConnect->Hive, NewKey->KeyCellOffset);
+       NewKey->KeyCellOffset = HiveToConnect->Hive.BaseBlock->RootCell;
+       NewKey->KeyCell = (PCM_KEY_NODE)HvGetCell (&HiveToConnect->Hive, NewKey->KeyCellOffset);
        return TRUE;
 }
 
-static BOOL
-MyExportBinaryHive (PCHAR FileName,
-                 PEREGISTRY_HIVE RootHive)
-{
-       FILE *File;
-       BOOL ret;
-
-       /* 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);
-
-       RootHive->HiveHandle = (HANDLE)File;
-       ret = HvWriteHive(&RootHive->Hive);
-       fclose (File);
-       return ret;
-}
-
 LIST_ENTRY CmiHiveListHead;
 
 VOID
@@ -618,20 +625,20 @@ RegInitializeRegistry(VOID)
 {
        UNICODE_STRING RootKeyName = RTL_CONSTANT_STRING(L"\\");
        NTSTATUS Status;
-       HKEY ControlSetKey, LinkKey;
+       HKEY ControlSetKey;
 
        InitializeListHead(&CmiHiveListHead);
 
        Status = CmiInitializeTempHive(&RootHive);
        if (!NT_SUCCESS(Status))
        {
-               DPRINT1("CmiInitializeTempHive() failed with status 0x%08lx\n", Status);
+               DPRINT1("CmiInitializeTempHive() failed with status 0x%08x\n", Status);
                return;
        }
 
        RootKey = CreateInMemoryStructure(
                &RootHive,
-               RootHive.Hive.HiveHeader->RootCell,
+               RootHive.Hive.BaseBlock->RootCell,
                &RootKeyName);
 
        /* Create DEFAULT key */
@@ -664,17 +671,11 @@ RegInitializeRegistry(VOID)
                &SystemHive,
                L"Registry\\Machine\\SYSTEM");
 
-       /* Create link 'CurrentControlSet' --> 'ControlSet001' */
+       /* Create 'ControlSet001' key */
        RegCreateKeyW(
                NULL,
                L"Registry\\Machine\\SYSTEM\\ControlSet001",
                &ControlSetKey);
-       RegCreateKeyW(
-               NULL,
-               L"Registry\\Machine\\SYSTEM\\CurrentControlSet",
-               &LinkKey);
-       printf("ControlSetKey %p\n", ControlSetKey);
-       RegSetValueExW(LinkKey, NULL, 0, REG_LINK, (PCHAR)&ControlSetKey, sizeof(PVOID));
 }
 
 /* EOF */