Implemented registry links (REG_LINK).
authorEric Kohl <eric.kohl@reactos.org>
Wed, 19 Jun 2002 22:32:47 +0000 (22:32 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Wed, 19 Jun 2002 22:32:47 +0000 (22:32 +0000)
Create the 'CurrentControlSet' link after the registry has been initialized.

svn path=/trunk/; revision=3130

reactos/include/ddk/cmtypes.h
reactos/include/ntos/registry.h
reactos/ntoskrnl/cm/cm.h
reactos/ntoskrnl/cm/ntfunc.c
reactos/ntoskrnl/cm/regfile.c
reactos/ntoskrnl/cm/registry.c
reactos/ntoskrnl/cm/regobj.c
reactos/system.hiv

index b44d83d..a9af321 100644 (file)
@@ -87,9 +87,6 @@ typedef struct _KEY_VALUE_PARTIAL_INFORMATION
   UCHAR  Data[1];
 } KEY_VALUE_PARTIAL_INFORMATION, *PKEY_VALUE_PARTIAL_INFORMATION;
 
-#define  REG_OPTION_CREATE_LINK     0x00000002
-#define  REG_OPTION_BACKUP_RESTORE  0x00000004
-
 
 /* used by [Nt/Zw]QueryMultipleValueKey */
 
index 6282cc3..d2cf2f4 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: registry.h,v 1.2 2001/05/30 19:58:48 ekohl Exp $
+/* $Id: registry.h,v 1.3 2002/06/19 22:30:29 ekohl Exp $
  *
  * COPYRIGHT:    See COPYING in the top level directory
  * PROJECT:      ReactOS kernel
 #define __INCLUDE_NTOS_REGISTRY_H
 
 /* Key access rights */
-#define KEY_QUERY_VALUE        (1)
-#define KEY_SET_VALUE  (2)
-#define KEY_CREATE_SUB_KEY     (4)
-#define KEY_ENUMERATE_SUB_KEYS (8)
-#define KEY_NOTIFY     (16)
-#define KEY_CREATE_LINK        (32)
-
-#define KEY_READ       (0x20019L)
-#define KEY_WRITE      (0x20006L)
-#define KEY_EXECUTE    (0x20019L)
-#define KEY_ALL_ACCESS (0xf003fL)
-
-
-/* RegCreateKeyEx */
-#define REG_OPTION_VOLATILE    (0x1L)
-#define REG_OPTION_NON_VOLATILE        (0L)
-#define REG_CREATED_NEW_KEY    (0x1L)
-#define REG_OPENED_EXISTING_KEY        (0x2L)
-
-
-/* RegEnumValue */
+#define KEY_QUERY_VALUE                        (1)
+#define KEY_SET_VALUE                  (2)
+#define KEY_CREATE_SUB_KEY             (4)
+#define KEY_ENUMERATE_SUB_KEYS         (8)
+#define KEY_NOTIFY                     (16)
+#define KEY_CREATE_LINK                        (32)
+
+#define KEY_READ                       (0x20019L)
+#define KEY_WRITE                      (0x20006L)
+#define KEY_EXECUTE                    (0x20019L)
+#define KEY_ALL_ACCESS                 (0xf003fL)
+
+/* Key create options */
+#define REG_OPTION_NON_VOLATILE                (0x0L)
+#define REG_OPTION_VOLATILE            (0x1L)
+#define REG_OPTION_CREATE_LINK         (0x2L)
+#define REG_OPTION_BACKUP_RESTORE      (0x8L)
+#define REG_OPTION_OPEN_LINK           (0x8L)
+
+/* Key create/open disposition */
+#define REG_CREATED_NEW_KEY            (0x1L)
+#define REG_OPENED_EXISTING_KEY                (0x2L)
+
+/* Value types */
 #define REG_NONE                       (0)
 #define REG_SZ                         (1)
 #define REG_EXPAND_SZ                  (2)
index 6d9a2f2..0c208e6 100644 (file)
 #define  SAM_REG_FILE                  L"\\SystemRoot\\System32\\Config\\SAM"
 #define  SEC_REG_FILE                  L"\\SystemRoot\\System32\\Config\\SECURITY"
 
+#define  REG_BLOCK_SIZE                4096
+#define  REG_HBIN_DATA_OFFSET          32
+#define  REG_BIN_ID                    0x6e696268
+#define  REG_INIT_BLOCK_LIST_SIZE      32
+#define  REG_INIT_HASH_TABLE_SIZE      3
+#define  REG_EXTEND_HASH_TABLE_SIZE    4
+#define  REG_VALUE_LIST_CELL_MULTIPLE  4
+#define  REG_KEY_CELL_ID               0x6b6e
+#define  REG_HASH_TABLE_BLOCK_ID       0x666c
+#define  REG_VALUE_CELL_ID             0x6b76
+#define  REG_LINK_KEY_CELL_TYPE        0x10
+#define  REG_KEY_CELL_TYPE             0x20
+#define  REG_ROOT_KEY_CELL_TYPE        0x2c
+#define  REG_HIVE_ID                   0x66676572
+
 #define  REGISTRY_FILE_MAGIC    "REGEDIT4"
 
 #define  REG_MACHINE_STD_HANDLE_NAME  "HKEY_LOCAL_MACHINE"
@@ -247,6 +262,7 @@ typedef struct _REGISTRY_HIVE
    atempts to access the key must not succeed */
 #define KO_MARKED_FOR_DELETE              0x00000001
 
+
 /* Type defining the Object Manager Key Object */
 typedef struct _KEY_OBJECT
 {
@@ -294,6 +310,9 @@ typedef struct _KEY_OBJECT
 
 
 extern BOOLEAN CmiDoVerify;
+extern PREGISTRY_HIVE CmiVolatileHive;
+extern POBJECT_TYPE CmiKeyType;
+extern KSPIN_LOCK CmiKeyListLock;
 
 
 VOID
index d709e77..1a2ba4d 100644 (file)
@@ -32,11 +32,11 @@ NtCreateKey(OUT PHANDLE KeyHandle,
        IN ULONG CreateOptions,
        OUT PULONG Disposition)
 {
-       UNICODE_STRING RemainingPath;
-       PKEY_OBJECT KeyObject;
-       NTSTATUS Status;
-       PVOID Object;
-       PWSTR End;
+  UNICODE_STRING RemainingPath;
+  PKEY_OBJECT KeyObject;
+  NTSTATUS Status;
+  PVOID Object;
+  PWSTR End;
 
   DPRINT("NtCreateKey (Name %wZ  KeyHandle %x  Root %x)\n",
          ObjectAttributes->ObjectName,
@@ -48,34 +48,34 @@ NtCreateKey(OUT PHANDLE KeyHandle,
   Status = ObFindObject(ObjectAttributes, &Object, &RemainingPath, CmiKeyType);
 
   if (!NT_SUCCESS(Status))
-         {
-                 return Status;
+    {
+      return Status;
     }
 
   DPRINT("RemainingPath %wZ\n", &RemainingPath);
 
   if ((RemainingPath.Buffer == NULL) || (RemainingPath.Buffer[0] == 0))
-         {
-           /* Fail if the key has been deleted */
-           if (((PKEY_OBJECT) Object)->Flags & KO_MARKED_FOR_DELETE)
-                   {
-                     ObDereferenceObject(Object);
-                     return STATUS_UNSUCCESSFUL;
-                   }
+    {
+      /* Fail if the key has been deleted */
+      if (((PKEY_OBJECT) Object)->Flags & KO_MARKED_FOR_DELETE)
+       {
+         ObDereferenceObject(Object);
+         return STATUS_UNSUCCESSFUL;
+       }
 
-           if (Disposition)
-             *Disposition = REG_OPENED_EXISTING_KEY;
+      if (Disposition)
+       *Disposition = REG_OPENED_EXISTING_KEY;
 
-           Status = ObCreateHandle(PsGetCurrentProcess(),
-                               Object,
-                               DesiredAccess,
-                               FALSE,
-                               KeyHandle);
+      Status = ObCreateHandle(PsGetCurrentProcess(),
+                             Object,
+                             DesiredAccess,
+                             FALSE,
+                             KeyHandle);
 
-       DPRINT("Status %x\n", Status);
-           ObDereferenceObject(Object);
-           return Status;
-         }
+      DPRINT("Status %x\n", Status);
+      ObDereferenceObject(Object);
+      return Status;
+    }
 
   /* If RemainingPath contains \ we must return error
      because NtCreateKey don't create trees */
@@ -85,21 +85,21 @@ NtCreateKey(OUT PHANDLE KeyHandle,
     End = wcschr(RemainingPath.Buffer, '\\');
 
   if (End != NULL)
-         {
-           ObDereferenceObject(Object);
-           return STATUS_UNSUCCESSFUL;
-         }
+    {
+      ObDereferenceObject(Object);
+      return STATUS_UNSUCCESSFUL;
+    }
 
   DPRINT("RemainingPath %S  ParentObject %x\n", RemainingPath.Buffer, Object);
 
   Status = ObCreateObject(KeyHandle,
-               DesiredAccess,
-               NULL,
-               CmiKeyType,
-               (PVOID*) &KeyObject);
+                         DesiredAccess,
+                         NULL,
+                         CmiKeyType,
+                         (PVOID*)&KeyObject);
 
   if (!NT_SUCCESS(Status))
-       return(Status);
+    return(Status);
 
   KeyObject->ParentKey = Object;
 
@@ -115,13 +115,13 @@ NtCreateKey(OUT PHANDLE KeyHandle,
 //  KeAcquireSpinLock(&Key->RegistryHive->RegLock, &OldIrql);
   /* add key to subkeys of parent if needed */
   Status = CmiAddSubKey(KeyObject->RegistryHive,
-               KeyObject->ParentKey,
-               KeyObject,
-               RemainingPath.Buffer,
-               RemainingPath.Length,
-               TitleIndex,
-               Class,
-               CreateOptions);
+                       KeyObject->ParentKey,
+                       KeyObject,
+                       RemainingPath.Buffer,
+                       RemainingPath.Length,
+                       TitleIndex,
+                       Class,
+                       CreateOptions);
 
   if (!NT_SUCCESS(Status))
     {
@@ -134,21 +134,21 @@ NtCreateKey(OUT PHANDLE KeyHandle,
   KeyObject->NameSize = KeyObject->KeyCell->NameSize;
 
   if (KeyObject->RegistryHive == KeyObject->ParentKey->RegistryHive)
-         {
-           KeyObject->KeyCell->ParentKeyOffset = KeyObject->ParentKey->BlockOffset;
-           KeyObject->KeyCell->SecurityKeyOffset = KeyObject->ParentKey->KeyCell->SecurityKeyOffset;
-         }
+    {
+      KeyObject->KeyCell->ParentKeyOffset = KeyObject->ParentKey->BlockOffset;
+      KeyObject->KeyCell->SecurityKeyOffset = KeyObject->ParentKey->KeyCell->SecurityKeyOffset;
+    }
   else
-               {
-                 KeyObject->KeyCell->ParentKeyOffset = -1;
-                 KeyObject->KeyCell->SecurityKeyOffset = -1;
-                 /* This key must rest in memory unless it is deleted
-                    or file is unloaded */
-                 ObReferenceObjectByPointer(KeyObject,
-                               STANDARD_RIGHTS_REQUIRED,
-                               NULL,
-                               UserMode);
-               }
+    {
+      KeyObject->KeyCell->ParentKeyOffset = -1;
+      KeyObject->KeyCell->SecurityKeyOffset = -1;
+      /* This key must rest in memory unless it is deleted
+        or file is unloaded */
+      ObReferenceObjectByPointer(KeyObject,
+                                STANDARD_RIGHTS_REQUIRED,
+                                NULL,
+                                UserMode);
+    }
 
   CmiAddKeyToList(KeyObject->ParentKey, KeyObject);
 //  KeReleaseSpinLock(&KeyObject->RegistryHive->RegLock, OldIrql);
@@ -807,61 +807,59 @@ END FIXME*/
 
 NTSTATUS STDCALL
 NtOpenKey(OUT PHANDLE KeyHandle,
-       IN ACCESS_MASK DesiredAccess,
-       IN POBJECT_ATTRIBUTES ObjectAttributes)
+         IN ACCESS_MASK DesiredAccess,
+         IN POBJECT_ATTRIBUTES ObjectAttributes)
 {
-       UNICODE_STRING RemainingPath;
-       NTSTATUS Status;
-       PVOID Object;
+  UNICODE_STRING RemainingPath;
+  NTSTATUS Status;
+  PVOID Object;
 
   DPRINT("KH %x  DA %x  OA %x  OA->ON %x\n",
-       KeyHandle,
-    DesiredAccess,
-       ObjectAttributes,
-    ObjectAttributes ? ObjectAttributes->ObjectName : NULL);
-
-       RemainingPath.Buffer = NULL;
-       Status = ObFindObject(ObjectAttributes,
-    &Object,
-    &RemainingPath,
-    CmiKeyType);
-
+        KeyHandle,
+        DesiredAccess,
+        ObjectAttributes,
+        ObjectAttributes ? ObjectAttributes->ObjectName : NULL);
+
+  RemainingPath.Buffer = NULL;
+  Status = ObFindObject(ObjectAttributes,
+                       &Object,
+                       &RemainingPath,
+                       CmiKeyType);
   if (!NT_SUCCESS(Status))
-               {
-      return Status;
-               }
+    {
+      return(Status);
+    }
 
   VERIFY_KEY_OBJECT((PKEY_OBJECT) Object);
 
-       DPRINT("RemainingPath.Buffer %x\n", RemainingPath.Buffer);
-
-       if ((RemainingPath.Buffer != NULL) && (RemainingPath.Buffer[0] != 0))
-               {
-                       ObDereferenceObject(Object);
-                       return STATUS_UNSUCCESSFUL;
-               }
-
-       /* Fail if the key has been deleted */
-       if (((PKEY_OBJECT)Object)->Flags & KO_MARKED_FOR_DELETE)
-               {
-                       ObDereferenceObject(Object);
-                       return STATUS_UNSUCCESSFUL;
-               }
-         
-       Status = ObCreateHandle(
-               PsGetCurrentProcess(),
-               Object,
-               DesiredAccess,
-               FALSE,
-               KeyHandle);
-       ObDereferenceObject(Object);
-
-       if (!NT_SUCCESS(Status))
-               {
-                 return Status;
-               }
-       
-       return STATUS_SUCCESS;
+  DPRINT("RemainingPath.Buffer %x\n", RemainingPath.Buffer);
+
+  if ((RemainingPath.Buffer != NULL) && (RemainingPath.Buffer[0] != 0))
+    {
+      ObDereferenceObject(Object);
+      return(STATUS_UNSUCCESSFUL);
+    }
+
+  /* Fail if the key has been deleted */
+  if (((PKEY_OBJECT)Object)->Flags & KO_MARKED_FOR_DELETE)
+    {
+      ObDereferenceObject(Object);
+      return(STATUS_UNSUCCESSFUL);
+    }
+
+  Status = ObCreateHandle(PsGetCurrentProcess(),
+                         Object,
+                         DesiredAccess,
+                         FALSE,
+                         KeyHandle);
+  ObDereferenceObject(Object);
+
+  if (!NT_SUCCESS(Status))
+    {
+      return(Status);
+    }
+
+  return(STATUS_SUCCESS);
 }
 
 
@@ -1185,13 +1183,12 @@ NtQueryValueKey(IN HANDLE KeyHandle,
 
 
 NTSTATUS STDCALL
-NtSetValueKey(
-       IN      HANDLE                  KeyHandle,
-       IN      PUNICODE_STRING         ValueName,
-       IN      ULONG                   TitleIndex,
-       IN      ULONG                   Type,
-       IN      PVOID                   Data,
-       IN      ULONG                   DataSize)
+NtSetValueKey(IN HANDLE KeyHandle,
+             IN PUNICODE_STRING ValueName,
+             IN ULONG TitleIndex,
+             IN ULONG Type,
+             IN PVOID Data,
+             IN ULONG DataSize)
 {
   NTSTATUS  Status;
   PKEY_OBJECT  KeyObject;
@@ -1203,6 +1200,7 @@ NtSetValueKey(
   PDATA_CELL DataCell;
   PDATA_CELL NewDataCell;
   PHBIN pBin;
+  ULONG DesiredAccess;
 // KIRQL  OldIrql;
 
   DPRINT("KeyHandle %x  ValueName %S  Type %d\n",
@@ -1211,13 +1209,17 @@ NtSetValueKey(
   wcstombs(ValueName2,ValueName->Buffer, ValueName->Length >> 1);
   ValueName2[ValueName->Length>>1] = 0;
 
+  DesiredAccess = KEY_SET_VALUE;
+  if (Type == REG_LINK)
+    DesiredAccess |= KEY_CREATE_LINK;
+
   /* Verify that the handle is valid and is a registry key */
   Status = ObReferenceObjectByHandle(KeyHandle,
-               KEY_SET_VALUE,
-               CmiKeyType,
-               UserMode,
-               (PVOID *) &KeyObject,
-               NULL);
+                                    DesiredAccess,
+                                    CmiKeyType,
+                                    UserMode,
+                                    (PVOID *)&KeyObject,
+                                    NULL);
   if (!NT_SUCCESS(Status))
     return(Status);
 
@@ -1311,6 +1313,11 @@ NtSetValueKey(
          ValueCell->DataOffset = NewOffset;
        }
 
+      if (strcmp(ValueName2, "SymbolicLinkValue") == 0)
+       {
+         KeyCell->Type = REG_LINK_KEY_CELL_TYPE;
+       }
+
       /* Update time of heap */
       if (IsPermanentHive(RegistryHive) && CmiGetBlock(RegistryHive, VBOffset, &pBin))
        {
index ebffb93..865011e 100644 (file)
 #include "cm.h"
 
 
-#define REG_BLOCK_SIZE                4096
-#define REG_HBIN_DATA_OFFSET          32
-#define REG_BIN_ID                    0x6e696268
-#define REG_INIT_BLOCK_LIST_SIZE      32
-#define REG_INIT_HASH_TABLE_SIZE      3
-#define REG_EXTEND_HASH_TABLE_SIZE    4
-#define REG_VALUE_LIST_CELL_MULTIPLE  4
-#define REG_KEY_CELL_ID               0x6b6e
-#define REG_HASH_TABLE_BLOCK_ID       0x666c
-#define REG_VALUE_CELL_ID             0x6b76
-#define REG_KEY_CELL_TYPE             0x20
-#define REG_ROOT_KEY_CELL_TYPE        0x2c
-#define REG_HIVE_ID                   0x66676572
-
-extern PREGISTRY_HIVE  CmiVolatileHive;
 
 BOOLEAN CmiDoVerify = FALSE;
 
@@ -1067,11 +1052,11 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive,
     &NKBOffset);
 
   if (NewKeyCell == NULL)
-         {
-           Status = STATUS_INSUFFICIENT_RESOURCES;
-         }
+    {
+      Status = STATUS_INSUFFICIENT_RESOURCES;
+    }
   else
-         {
+    {
            NewKeyCell->Id = REG_KEY_CELL_ID;
            NewKeyCell->Type = REG_KEY_CELL_TYPE;
            ZwQuerySystemTime((PTIME) &NewKeyCell->LastWriteTime);
@@ -1339,12 +1324,11 @@ CmiAddValueToKey(IN PREGISTRY_HIVE RegistryHive,
 
 NTSTATUS
 CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive,
-       IN PKEY_CELL KeyCell,
-       IN PCHAR ValueName)
+                     IN PKEY_CELL KeyCell,
+                     IN PCHAR ValueName)
 {
   PVALUE_LIST_CELL ValueListCell;
   PVALUE_CELL CurValueCell;
-  PHBIN pBin;
   ULONG  i;
 
   ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL);
@@ -1358,7 +1342,7 @@ CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive,
 
   for (i = 0; i < KeyCell->NumberOfValues; i++)
     {
-      CurValueCell = CmiGetBlock(RegistryHive, ValueListCell->Values[i], &pBin);
+      CurValueCell = CmiGetBlock(RegistryHive, ValueListCell->Values[i], NULL);
       if ((CurValueCell != NULL) &&
           (CurValueCell->NameSize == strlen(ValueName)) &&
           (memcmp(CurValueCell->Name, ValueName, strlen(ValueName)) == 0))
@@ -1376,8 +1360,6 @@ CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive,
 
           KeyCell->NumberOfValues -= 1;
           CmiDestroyValueCell(RegistryHive, CurValueCell, ValueListCell->Values[i]);
-          /* update time of heap */
-          ZwQuerySystemTime((PTIME) &pBin->DateModified);
           break;
         }
       CmiReleaseBlock(RegistryHive, CurValueCell);
@@ -1409,15 +1391,15 @@ CmiAllocateHashTableBlock(IN PREGISTRY_HIVE RegistryHive,
     HBOffset);
 
   if ((NewHashBlock == NULL) || (!NT_SUCCESS(Status)))
-         {
-           Status = STATUS_INSUFFICIENT_RESOURCES;
-         }
+    {
+      Status = STATUS_INSUFFICIENT_RESOURCES;
+    }
   else
-         {
-           NewHashBlock->Id = REG_HASH_TABLE_BLOCK_ID;
-           NewHashBlock->HashTableSize = HashTableSize;
-           *HashBlock = NewHashBlock;
-         }
+    {
+      NewHashBlock->Id = REG_HASH_TABLE_BLOCK_ID;
+      NewHashBlock->HashTableSize = HashTableSize;
+      *HashBlock = NewHashBlock;
+    }
 
   return Status;
 }
@@ -1864,6 +1846,9 @@ CmiGetBlock(PREGISTRY_HIVE RegistryHive,
        BLOCK_OFFSET BlockOffset,
        PHBIN * ppBin)
 {
+  if (ppBin)
+    *ppBin = NULL;
+
   if ((BlockOffset == 0) || (BlockOffset == -1))
     return NULL;
 
index 6df1038..344001f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: registry.c,v 1.72 2002/06/16 11:45:06 ekohl Exp $
+/* $Id: registry.c,v 1.73 2002/06/19 22:31:33 ekohl Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -42,6 +42,10 @@ VOID
 CmiCheckKey(BOOLEAN Verbose,
   HANDLE Key);
 
+static NTSTATUS
+CmiCreateCurrentControlSetLink(VOID);
+
+/* FUNCTIONS ****************************************************************/
 
 VOID
 CmiCheckSubKeys(BOOLEAN Verbose,
@@ -471,7 +475,9 @@ CmInit2(PCHAR CommandLine)
 
   /* FIXME: Store current command line */
 
-  /* FIXME: Create the 'CurrentControlSet' link. */
+  /* Create the 'CurrentControlSet' link. */
+  CmiCreateCurrentControlSetLink();
+
 
   /* Set PICE 'Start' value to 1, if PICE debugging is enabled */
   PiceStart = 4;
@@ -505,6 +511,100 @@ CmInit2(PCHAR CommandLine)
 }
 
 
+static NTSTATUS
+CmiCreateCurrentControlSetLink(VOID)
+{
+  RTL_QUERY_REGISTRY_TABLE QueryTable[5];
+  WCHAR TargetNameBuffer[80];
+  ULONG TargetNameLength;
+  UNICODE_STRING LinkName;
+  UNICODE_STRING LinkValue;
+  ULONG CurrentSet;
+  ULONG DefaultSet;
+  ULONG Failed;
+  ULONG LastKnownGood;
+  NTSTATUS Status;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  HANDLE KeyHandle;
+
+  DPRINT("CmiCreateCurrentControlSetLink() called\n");
+
+  RtlZeroMemory(&QueryTable, sizeof(QueryTable));
+
+  QueryTable[0].Name = L"Current";
+  QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+  QueryTable[0].EntryContext = &CurrentSet;
+
+  QueryTable[1].Name = L"Default";
+  QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
+  QueryTable[1].EntryContext = &DefaultSet;
+
+  QueryTable[2].Name = L"Failed";
+  QueryTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
+  QueryTable[2].EntryContext = &Failed;
+
+  QueryTable[3].Name = L"LastKnownGood";
+  QueryTable[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
+  QueryTable[3].EntryContext = &LastKnownGood;
+
+  Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
+                                 L"\\Registry\\Machine\\SYSTEM\\Select",
+                                 QueryTable,
+                                 NULL,
+                                 NULL);
+  if (!NT_SUCCESS(Status))
+    {
+      return(Status);
+    }
+
+  DPRINT("Current %ld  Default %ld\n", CurrentSet, DefaultSet);
+
+  swprintf(TargetNameBuffer,
+          L"\\Registry\\Machine\\SYSTEM\\ControlSet%03lu",
+          CurrentSet);
+  TargetNameLength = wcslen(TargetNameBuffer) * sizeof(WCHAR);
+
+  DPRINT("Link target '%S'\n", TargetNameBuffer);
+
+  RtlInitUnicodeString(&LinkName,
+                      L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &LinkName,
+                            OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_OPENLINK,
+                            NULL,
+                            NULL);
+  Status = NtCreateKey(&KeyHandle,
+                      KEY_ALL_ACCESS | KEY_CREATE_LINK,
+                      &ObjectAttributes,
+                      0,
+                      NULL,
+                      REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK,
+                      NULL);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT1("NtCreateKey() failed (Status %lx)\n", Status);
+      return(Status);
+    }
+
+  RtlInitUnicodeString(&LinkValue,
+                      L"SymbolicLinkValue");
+  Status=NtSetValueKey(KeyHandle,
+                      &LinkValue,
+                      0,
+                      REG_LINK,
+                      (PVOID)TargetNameBuffer,
+                      TargetNameLength);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
+    }
+
+  NtClose(KeyHandle);
+
+  return(Status);
+}
+
+
 NTSTATUS
 CmiConnectHive(PWSTR FileName,
   PWSTR FullName,
index f1dc5ef..e7b9c30 100644 (file)
 #include <string.h>
 #include <internal/pool.h>
 #include <internal/registry.h>
+#include <ntos/minmax.h>
 
 #define NDEBUG
 #include <internal/debug.h>
 
 #include "cm.h"
 
-extern POBJECT_TYPE  CmiKeyType;
-extern KSPIN_LOCK  CmiKeyListLock;
+
+static NTSTATUS
+CmiGetLinkTarget(PREGISTRY_HIVE RegistryHive,
+                PKEY_CELL KeyCell,
+                PUNICODE_STRING TargetPath);
+
+/* FUNCTONS *****************************************************************/
 
 NTSTATUS STDCALL
 CmiObjectParse(PVOID ParsedObject,
-       PVOID *NextObject,
-       PUNICODE_STRING FullPath,
-       PWSTR *Path,
-       POBJECT_TYPE ObjectType,
-       ULONG Attributes)
+              PVOID *NextObject,
+              PUNICODE_STRING FullPath,
+              PWSTR *Path,
+              POBJECT_TYPE ObjectType,
+              ULONG Attributes)
 {
-       BLOCK_OFFSET BlockOffset;
-       PKEY_OBJECT FoundObject;
-       PKEY_OBJECT ParsedKey;
-       PKEY_CELL SubKeyCell;
-       CHAR cPath[MAX_PATH];
-       NTSTATUS Status;
-       PWSTR end;
-
-       ParsedKey = ParsedObject;
+  BLOCK_OFFSET BlockOffset;
+  PKEY_OBJECT FoundObject;
+  PKEY_OBJECT ParsedKey;
+  PKEY_CELL SubKeyCell;
+  CHAR cPath[MAX_PATH];
+  NTSTATUS Status;
+  PWSTR end;
+  UNICODE_STRING LinkPath;
+  UNICODE_STRING TargetPath;
+
+  ParsedKey = ParsedObject;
 
   VERIFY_KEY_OBJECT(ParsedKey);
 
-       *NextObject = NULL;
+  *NextObject = NULL;
 
-       if ((*Path) == NULL)
-               {
+  if ((*Path) == NULL)
+    {
       DPRINT("*Path is NULL\n");
-                 return STATUS_UNSUCCESSFUL;
-               }
-       
-       if ((*Path[0]) == '\\')
-               {
-                       end = wcschr((*Path) + 1, '\\');
-                       if (end != NULL)
-                         *end = 0;
-                       wcstombs(cPath, (*Path) + 1, wcslen((*Path) + 1));
-                       cPath[wcslen((*Path) + 1)] = 0;
-               }
-       else
-               {
-                       end = wcschr((*Path), '\\');
-                       if (end != NULL)
-                       *end = 0;
-                       wcstombs(cPath, (*Path), wcslen((*Path)));
-                       cPath[wcslen((*Path))] = 0;
-               }
+      return STATUS_UNSUCCESSFUL;
+    }
 
-       FoundObject = CmiScanKeyList(ParsedKey, cPath, Attributes);
-       if (FoundObject == NULL)
-               {
-                 Status = CmiScanForSubKey(ParsedKey->RegistryHive,
-             ParsedKey->KeyCell,
-             &SubKeyCell,
-             &BlockOffset,
-             cPath,
-             0,
-             Attributes);
-
-                       if (!NT_SUCCESS(Status) || (SubKeyCell == NULL))
-                       {
-                               if (end != NULL)
-                                       {
-                                       *end = '\\';
-                                       }
-                               return STATUS_UNSUCCESSFUL;
-                       }
-       
-               /* Create new key object and put into linked list */
-                       DPRINT("CmiObjectParse %s\n", cPath);
-                       Status = ObCreateObject(NULL,
-                               STANDARD_RIGHTS_REQUIRED,
-                               NULL,
-                               CmiKeyType,
-                               (PVOID*) &FoundObject);
-
-                       if (!NT_SUCCESS(Status))
-                               {
-                                 return Status;
-                               }
-
-                       FoundObject->Flags = 0;
-                       FoundObject->Name = SubKeyCell->Name;
-                       FoundObject->NameSize = SubKeyCell->NameSize;
-                       FoundObject->KeyCell = SubKeyCell;
-                       FoundObject->BlockOffset = BlockOffset;
-                       FoundObject->RegistryHive = ParsedKey->RegistryHive;
-                       CmiAddKeyToList(ParsedKey, FoundObject);
-                       DPRINT("Created object 0x%x\n", FoundObject);
-               }
-       else
+  DPRINT("Path '%S'\n", *Path);
+
+  if ((*Path[0]) == '\\')
     {
-                 ObReferenceObjectByPointer(FoundObject,
-                   STANDARD_RIGHTS_REQUIRED,
-                   NULL,
-                   UserMode);
+      end = wcschr((*Path) + 1, '\\');
+      if (end != NULL)
+       *end = 0;
+      wcstombs(cPath, (*Path) + 1, wcslen((*Path) + 1));
+      cPath[wcslen((*Path) + 1)] = 0;
+    }
+  else
+    {
+      end = wcschr((*Path), '\\');
+      if (end != NULL)
+       *end = 0;
+      wcstombs(cPath, (*Path), wcslen((*Path)));
+      cPath[wcslen((*Path))] = 0;
     }
 
-       DPRINT("CmiObjectParse %s\n", FoundObject->Name);
+  FoundObject = CmiScanKeyList(ParsedKey, cPath, Attributes);
+  if (FoundObject == NULL)
+    {
+      Status = CmiScanForSubKey(ParsedKey->RegistryHive,
+                               ParsedKey->KeyCell,
+                               &SubKeyCell,
+                               &BlockOffset,
+                               cPath,
+                               0,
+                               Attributes);
+      if (!NT_SUCCESS(Status) || (SubKeyCell == NULL))
+       {
+         if (end != NULL)
+           {
+             *end = '\\';
+           }
+         return(STATUS_UNSUCCESSFUL);
+       }
+
+      if ((SubKeyCell->Type == REG_LINK_KEY_CELL_TYPE) &&
+         !((Attributes & OBJ_OPENLINK) && (end == NULL)))
+       {
+         RtlInitUnicodeString(&LinkPath, NULL);
+         Status = CmiGetLinkTarget(ParsedKey->RegistryHive,
+                                   SubKeyCell,
+                                   &LinkPath);
+         if (NT_SUCCESS(Status))
+           {
+             DPRINT("LinkPath '%wZ'\n", &LinkPath);
 
-       if (end != NULL)
+             /* build new FullPath for reparsing */
+             TargetPath.MaximumLength = LinkPath.MaximumLength;
+             if (end != NULL)
                {
-                       *end = '\\';
-                 *Path = end;
+                 *end = '\\';
+                 TargetPath.MaximumLength += (wcslen(end) * sizeof(WCHAR));
+               }
+             TargetPath.Length = TargetPath.MaximumLength - sizeof(WCHAR);
+             TargetPath.Buffer = ExAllocatePool(NonPagedPool,
+                                                TargetPath.MaximumLength);
+             wcscpy(TargetPath.Buffer, LinkPath.Buffer);
+             if (end != NULL)
+               {
+                 wcscat(TargetPath.Buffer, end);
                }
+
+             RtlFreeUnicodeString(FullPath);
+             RtlFreeUnicodeString(&LinkPath);
+             FullPath->Length = TargetPath.Length;
+             FullPath->MaximumLength = TargetPath.MaximumLength;
+             FullPath->Buffer = TargetPath.Buffer;
+
+             DPRINT("FullPath '%wZ'\n", FullPath);
+
+             /* reinitialize Path for reparsing */
+             *Path = FullPath->Buffer;
+
+             *NextObject = NULL;
+             return(STATUS_REPARSE);
+           }
+       }
+
+      /* Create new key object and put into linked list */
+      DPRINT("CmiObjectParse %s\n", cPath);
+      Status = ObCreateObject(NULL,
+                             STANDARD_RIGHTS_REQUIRED,
+                             NULL,
+                             CmiKeyType,
+                             (PVOID*)&FoundObject);
+      if (!NT_SUCCESS(Status))
+       {
+         return(Status);
+       }
+
+      FoundObject->Flags = 0;
+      FoundObject->Name = SubKeyCell->Name;
+      FoundObject->NameSize = SubKeyCell->NameSize;
+      FoundObject->KeyCell = SubKeyCell;
+      FoundObject->BlockOffset = BlockOffset;
+      FoundObject->RegistryHive = ParsedKey->RegistryHive;
+      CmiAddKeyToList(ParsedKey, FoundObject);
+      DPRINT("Created object 0x%x\n", FoundObject);
+    }
   else
+    {
+      if ((FoundObject->KeyCell->Type == REG_LINK_KEY_CELL_TYPE) &&
+         !((Attributes & OBJ_OPENLINK) && (end == NULL)))
+       {
+         RtlInitUnicodeString(&LinkPath, NULL);
+         Status = CmiGetLinkTarget(FoundObject->RegistryHive,
+                                   FoundObject->KeyCell,
+                                   &LinkPath);
+         if (NT_SUCCESS(Status))
+           {
+             DPRINT("LinkPath '%wZ'\n", &LinkPath);
+
+             /* build new FullPath for reparsing */
+             TargetPath.MaximumLength = LinkPath.MaximumLength;
+             if (end != NULL)
                {
-                       *Path = NULL;
+                 *end = '\\';
+                 TargetPath.MaximumLength += (wcslen(end) * sizeof(WCHAR));
+               }
+             TargetPath.Length = TargetPath.MaximumLength - sizeof(WCHAR);
+             TargetPath.Buffer = ExAllocatePool(NonPagedPool,
+                                                TargetPath.MaximumLength);
+             wcscpy(TargetPath.Buffer, LinkPath.Buffer);
+             if (end != NULL)
+               {
+                 wcscat(TargetPath.Buffer, end);
                }
 
-VERIFY_KEY_OBJECT(FoundObject);
-       
-       *NextObject = FoundObject;
-       
-       return STATUS_SUCCESS;
+             RtlFreeUnicodeString(FullPath);
+             RtlFreeUnicodeString(&LinkPath);
+             FullPath->Length = TargetPath.Length;
+             FullPath->MaximumLength = TargetPath.MaximumLength;
+             FullPath->Buffer = TargetPath.Buffer;
+
+             DPRINT("FullPath '%wZ'\n", FullPath);
+
+             /* reinitialize Path for reparsing */
+             *Path = FullPath->Buffer;
+
+             *NextObject = NULL;
+             return(STATUS_REPARSE);
+           }
+       }
+
+      ObReferenceObjectByPointer(FoundObject,
+                                STANDARD_RIGHTS_REQUIRED,
+                                NULL,
+                                UserMode);
+    }
+
+  DPRINT("CmiObjectParse %s\n", FoundObject->Name);
+
+  if (end != NULL)
+    {
+      *end = '\\';
+      *Path = end;
+    }
+  else
+    {
+      *Path = NULL;
+    }
+
+  VERIFY_KEY_OBJECT(FoundObject);
+
+  *NextObject = FoundObject;
+
+  return(STATUS_SUCCESS);
 }
 
 
 NTSTATUS STDCALL
 CmiObjectCreate(PVOID ObjectBody,
-       PVOID Parent,
-       PWSTR RemainingPath,
-       struct _OBJECT_ATTRIBUTES* ObjectAttributes)
+               PVOID Parent,
+               PWSTR RemainingPath,
+               struct _OBJECT_ATTRIBUTES* ObjectAttributes)
 {
   PKEY_OBJECT pKey = ObjectBody;
-       pKey->ParentKey = Parent;
-       if (RemainingPath)
-               {
-                       if(RemainingPath[0]== L'\\')
-                               {
-                                       pKey->Name = (PCHAR) (&RemainingPath[1]);
-                                       pKey->NameSize = wcslen(RemainingPath) - 1;
-                               }
-                       else
-                               {
-                                       pKey->Name = (PCHAR) RemainingPath;
-                                       pKey->NameSize = wcslen(RemainingPath);
-                               }
-          }
+
+  pKey->ParentKey = Parent;
+  if (RemainingPath)
+    {
+      if(RemainingPath[0]== L'\\')
+       {
+         pKey->Name = (PCHAR)(&RemainingPath[1]);
+         pKey->NameSize = wcslen(RemainingPath) - 1;
+       }
+      else
+       {
+         pKey->Name = (PCHAR)RemainingPath;
+         pKey->NameSize = wcslen(RemainingPath);
+       }
+    }
    else
     {
       pKey->NameSize = 0;
@@ -177,16 +272,16 @@ CmiObjectDelete(PVOID DeletedObject)
   KeyObject = (PKEY_OBJECT) DeletedObject;
 
   if (!NT_SUCCESS(CmiRemoveKeyFromList(KeyObject)))
-         {
-           DPRINT1("Key not found in parent list ???\n");
-         }
+    {
+      DPRINT1("Key not found in parent list ???\n");
+    }
 
   if (KeyObject->Flags & KO_MARKED_FOR_DELETE)
     {
       DPRINT("delete really key\n");
       CmiDestroyBlock(KeyObject->RegistryHive,
-        KeyObject->KeyCell,
-                         KeyObject->BlockOffset);
+                     KeyObject->KeyCell,
+                     KeyObject->BlockOffset);
     }
   else
     {
@@ -194,40 +289,41 @@ CmiObjectDelete(PVOID DeletedObject)
     }
 }
 
+
 VOID
 CmiAddKeyToList(PKEY_OBJECT ParentKey,
-  PKEY_OBJECT NewKey)
+               PKEY_OBJECT NewKey)
 {
   KIRQL OldIrql;
 
   DPRINT("ParentKey %.08x\n", ParentKey);
-  
+
   KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
 
   if (ParentKey->SizeOfSubKeys <= ParentKey->NumberOfSubKeys)
-         {
-           PKEY_OBJECT *tmpSubKeys = ExAllocatePool(NonPagedPool,
-        (ParentKey->NumberOfSubKeys + 1) * sizeof(DWORD));
+    {
+      PKEY_OBJECT *tmpSubKeys = ExAllocatePool(NonPagedPool,
+       (ParentKey->NumberOfSubKeys + 1) * sizeof(DWORD));
 
-           if (ParentKey->NumberOfSubKeys > 0)
-        {
-               memcpy(tmpSubKeys,
-            ParentKey->SubKeys,
-                             ParentKey->NumberOfSubKeys * sizeof(DWORD));
-        }
+      if (ParentKey->NumberOfSubKeys > 0)
+       {
+         memcpy(tmpSubKeys,
+                ParentKey->SubKeys,
+                ParentKey->NumberOfSubKeys * sizeof(DWORD));
+       }
 
-           if (ParentKey->SubKeys)
-        ExFreePool(ParentKey->SubKeys);
+      if (ParentKey->SubKeys)
+       ExFreePool(ParentKey->SubKeys);
 
-           ParentKey->SubKeys = tmpSubKeys;
-           ParentKey->SizeOfSubKeys = ParentKey->NumberOfSubKeys + 1;
-         }
+      ParentKey->SubKeys = tmpSubKeys;
+      ParentKey->SizeOfSubKeys = ParentKey->NumberOfSubKeys + 1;
+    }
 
   /* FIXME: Please maintain the list in alphabetic order */
   /*      to allow a dichotomic search */
   ParentKey->SubKeys[ParentKey->NumberOfSubKeys++] = NewKey;
 
-DPRINT("Reference parent key: 0x%x\n", ParentKey);
+  DPRINT("Reference parent key: 0x%x\n", ParentKey);
 
   ObReferenceObjectByPointer(ParentKey,
                STANDARD_RIGHTS_REQUIRED,
@@ -249,36 +345,37 @@ CmiRemoveKeyFromList(PKEY_OBJECT KeyToRemove)
   KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
   /* FIXME: If list maintained in alphabetic order, use dichotomic search */
   for (Index = 0; Index < ParentKey->NumberOfSubKeys; Index++)
-         {
-           if (ParentKey->SubKeys[Index] == KeyToRemove)
-           {
-                     if (Index < ParentKey->NumberOfSubKeys-1)
-                       RtlMoveMemory(&ParentKey->SubKeys[Index],
-                                     &ParentKey->SubKeys[Index + 1],
-                                     (ParentKey->NumberOfSubKeys - Index - 1) * sizeof(PKEY_OBJECT));
-                     ParentKey->NumberOfSubKeys--;
-                     KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
-
-DPRINT("Dereference parent key: 0x%x\n", ParentKey);
+    {
+      if (ParentKey->SubKeys[Index] == KeyToRemove)
+       {
+         if (Index < ParentKey->NumberOfSubKeys-1)
+           RtlMoveMemory(&ParentKey->SubKeys[Index],
+                         &ParentKey->SubKeys[Index + 1],
+                         (ParentKey->NumberOfSubKeys - Index - 1) * sizeof(PKEY_OBJECT));
+         ParentKey->NumberOfSubKeys--;
+         KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
+
+         DPRINT("Dereference parent key: 0x%x\n", ParentKey);
        
-                     ObDereferenceObject(ParentKey);
-                     return STATUS_SUCCESS;
-                   }
-         }
+         ObDereferenceObject(ParentKey);
+         return STATUS_SUCCESS;
+       }
+    }
   KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
+
   return STATUS_UNSUCCESSFUL;
 }
 
 
 PKEY_OBJECT
 CmiScanKeyList(PKEY_OBJECT Parent,
-       PCHAR KeyName,
-       ULONG Attributes)
+              PCHAR KeyName,
+              ULONG Attributes)
 {
-       PKEY_OBJECT CurKey;
-       KIRQL OldIrql;
-       WORD NameSize;
-       DWORD Index;
+  PKEY_OBJECT CurKey;
+  KIRQL OldIrql;
+  WORD NameSize;
+  DWORD Index;
 
   DPRINT("Scanning key list for %s (Parent %s)\n",
     KeyName, Parent->Name);
@@ -287,28 +384,88 @@ CmiScanKeyList(PKEY_OBJECT Parent,
   KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
   /* FIXME: if list maintained in alphabetic order, use dichotomic search */
   for (Index=0; Index < Parent->NumberOfSubKeys; Index++)
-         {
-           CurKey = Parent->SubKeys[Index];
-           if (Attributes & OBJ_CASE_INSENSITIVE)
-                   {
-                     if ((NameSize == CurKey->NameSize)
-                 && (_strnicmp(KeyName, CurKey->Name, NameSize) == 0))
-                 {
-                   KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
-                   return CurKey;
-                 }
-                   }
-           else
-                   {
-                     if ((NameSize == CurKey->NameSize)
-                             && (strncmp(KeyName,CurKey->Name,NameSize) == 0))
-                             {
-                                KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
-                                return CurKey;
-                             }
-                   }
-         }
+    {
+      CurKey = Parent->SubKeys[Index];
+      if (Attributes & OBJ_CASE_INSENSITIVE)
+       {
+         if ((NameSize == CurKey->NameSize)
+             && (_strnicmp(KeyName, CurKey->Name, NameSize) == 0))
+           {
+             KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
+             return CurKey;
+           }
+       }
+      else
+       {
+         if ((NameSize == CurKey->NameSize)
+             && (strncmp(KeyName,CurKey->Name,NameSize) == 0))
+           {
+             KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
+             return CurKey;
+           }
+       }
+    }
   KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
   
   return NULL;
 }
+
+
+static NTSTATUS
+CmiGetLinkTarget(PREGISTRY_HIVE RegistryHive,
+                PKEY_CELL KeyCell,
+                PUNICODE_STRING TargetPath)
+{
+  PVALUE_CELL ValueCell;
+  PDATA_CELL DataCell;
+  NTSTATUS Status;
+
+  /* Get Value block of interest */
+  Status = CmiScanKeyForValue(RegistryHive,
+                             KeyCell,
+                             "SymbolicLinkValue",
+                             &ValueCell,
+                             NULL);
+  if (!NT_SUCCESS(Status))
+    {
+      return(Status);
+    }
+
+  if (ValueCell->DataType != REG_LINK)
+    {
+      DPRINT1("Type != REG_LINK\n!");
+      return(STATUS_UNSUCCESSFUL);
+    }
+
+  if (TargetPath->Buffer == NULL && TargetPath->MaximumLength == 0)
+    {
+      TargetPath->Length = 0;
+      TargetPath->MaximumLength = ValueCell->DataSize + sizeof(WCHAR);
+      TargetPath->Buffer = ExAllocatePool(NonPagedPool,
+                                         TargetPath->MaximumLength);
+    }
+
+  TargetPath->Length = min(TargetPath->MaximumLength - sizeof(WCHAR),
+                          ValueCell->DataSize);
+
+  if (ValueCell->DataSize > 0)
+    {
+      DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
+      RtlCopyMemory(TargetPath->Buffer,
+                   DataCell->Data,
+                   TargetPath->Length);
+      TargetPath->Buffer[TargetPath->Length / sizeof(WCHAR)] = 0;
+      CmiReleaseBlock(RegistryHive, DataCell);
+    }
+  else
+    {
+      RtlCopyMemory(TargetPath->Buffer,
+                   &ValueCell->DataOffset,
+                   TargetPath->Length);
+      TargetPath->Buffer[TargetPath->Length / sizeof(WCHAR)] = 0;
+    }
+
+  return(STATUS_SUCCESS);
+}
+
+/* EOF */
index 634bbc7..021c98a 100644 (file)
@@ -2,13 +2,13 @@ REGEDIT4
 
 [\Registry\Machine\SYSTEM]
 
-[\Registry\Machine\SYSTEM\CurrentControlSet]
+[\Registry\Machine\SYSTEM\ControlSet001]
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Control]
+[\Registry\Machine\SYSTEM\ControlSet001\Control]
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Control\NLS]
+[\Registry\Machine\SYSTEM\ControlSet001\Control\NLS]
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Control\NLS\CodePage]
+[\Registry\Machine\SYSTEM\ControlSet001\Control\NLS\CodePage]
 "10000"="c_10000.nls"
 "1252"="c_1252.nls"
 "437"="c_437.nls"
@@ -17,7 +17,7 @@ REGEDIT4
 "OEMCP"="437"
 "MACCP"="10000"
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Control\NLS\Language]
+[\Registry\Machine\SYSTEM\ControlSet001\Control\NLS\Language]
 "0401"="l_intl.nls"
 "0402"="l_intl.nls"
 "0403"="l_intl.nls"
@@ -37,18 +37,18 @@ REGEDIT4
 "Default"="0409"
 "InstallLanguage"="0409"
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Control\ServiceGroupOrder]
+[\Registry\Machine\SYSTEM\ControlSet001\Control\ServiceGroupOrder]
 "List"=multi:"SCSI Port", "SCSI Miniport", "Primary Disk", "SCSI Class Helper", \
              "SCSI Class", "Boot File System", "Base", "Pointer Port", \
              "Keyboard Port", "Pointer Class", "Keyboard Class", "Debug", \
              "Video Init", "Video", "File System", "Event log", "NDIS", \
              "PNP_TDI", "TDI", "Extended Base"
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Control\Session Manager]
+[\Registry\Machine\SYSTEM\ControlSet001\Control\Session Manager]
 "BootExecute"=multi:"autocheck autochk *"
 "ObjectDirectories"=multi:"\Windows", "\RPC Control"
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Control\Session Manager\DOS Devices]
+[\Registry\Machine\SYSTEM\ControlSet001\Control\Session Manager\DOS Devices]
 "AUX"="\DosDevices\COM1"
 "MAILSLOT"="\Device\MailSlot"
 "NUL"="\Device\Null"
@@ -56,187 +56,197 @@ REGEDIT4
 "PRN"="\DosDevices\LPT1"
 "UNC"="\Device\Mup"
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Control\Session Manager\Environment]
+[\Registry\Machine\SYSTEM\ControlSet001\Control\Session Manager\Environment]
 "ComSpec"=expand:"%SystemRoot%\system32\shell.exe"
 "OS"=expand:"ReactOS"
 "Path"=expand:"%SystemRoot%\system32;%SystemRoot%"
 "windir"=expand:"%SystemRoot%"
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management]
+[\Registry\Machine\SYSTEM\ControlSet001\Control\Session Manager\Memory Management]
 "PagingFiles"=multi:"C:\reactos\pagefile.sys"
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Services]
+[\Registry\Machine\SYSTEM\ControlSet001\Services]
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Services\Afd]
+[\Registry\Machine\SYSTEM\ControlSet001\Services\Afd]
 "ErrorControl"=dword:00000001
 "Group"="TDI"
-"ImagePath"="system32\drivers\afd.sys"
+"ImagePath"=expand:"system32\drivers\afd.sys"
 "Start"=dword:00000002
 "Type"=dword:00000001
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Services\Atapi]
+[\Registry\Machine\SYSTEM\ControlSet001\Services\Atapi]
 "ErrorControl"=dword:00000000
 "Group"="SCSI Miniport"
-"ImagePath"="system32\drivers\atapi.sys"
+"ImagePath"=expand:"system32\drivers\atapi.sys"
 "Start"=dword:00000000
 "Type"=dword:00000001
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Services\Beep]
+[\Registry\Machine\SYSTEM\ControlSet001\Services\Beep]
 "ErrorControl"=dword:00000000
 "Group"="Base"
-"ImagePath"="system32\drivers\beep.sys"
+"ImagePath"=expand:"system32\drivers\beep.sys"
 "Start"=dword:00000001
 "Type"=dword:00000001
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Services\Blue]
+[\Registry\Machine\SYSTEM\ControlSet001\Services\Blue]
 "ErrorControl"=dword:00000000
 "Group"="Video Init"
-"ImagePath"="system32\drivers\blue.sys"
+"ImagePath"=expand:"system32\drivers\blue.sys"
 "Start"=dword:00000001
 "Type"=dword:00000001
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Services\Cdfs]
+[\Registry\Machine\SYSTEM\ControlSet001\Services\Cdfs]
 "ErrorControl"=dword:00000000
 "Group"="File System"
-"ImagePath"="system32\drivers\cdfs.sys"
+"ImagePath"=expand:"system32\drivers\cdfs.sys"
 "Start"=dword:00000003
 "Type"=dword:00000002
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Services\Cdrom]
+[\Registry\Machine\SYSTEM\ControlSet001\Services\Cdrom]
 "ErrorControl"=dword:00000000
 "Group"="SCSI Class"
-"ImagePath"="system32\drivers\cdrom.sys"
+"ImagePath"=expand:"system32\drivers\cdrom.sys"
 "Start"=dword:00000001
 "Type"=dword:00000001
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Services\Class2]
+[\Registry\Machine\SYSTEM\ControlSet001\Services\Class2]
 "ErrorControl"=dword:00000000
 "Group"="SCSI Class Helper"
-"ImagePath"="system32\drivers\class2.sys"
+"ImagePath"=expand:"system32\drivers\class2.sys"
 "Start"=dword:00000000
 "Type"=dword:00000001
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Services\Disk]
+[\Registry\Machine\SYSTEM\ControlSet001\Services\Disk]
 "ErrorControl"=dword:00000000
 "Group"="SCSI Class"
-"ImagePath"="system32\drivers\disk.sys"
+"ImagePath"=expand:"system32\drivers\disk.sys"
 "Start"=dword:00000000
 "Type"=dword:00000001
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Services\EventLog]
+[\Registry\Machine\SYSTEM\ControlSet001\Services\EventLog]
 "ErrorControl"=dword:00000000
 "Group"="Event log"
-"ImagePath"="%SystemRoot%\system32\eventlog.exe"
+"ImagePath"=expand:"%SystemRoot%\system32\eventlog.exe"
 "Start"=dword:00000004
-"Type"=dword:00000020
+"Type"=dword:00000010
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Services\Floppy]
+[\Registry\Machine\SYSTEM\ControlSet001\Services\Floppy]
 "ErrorControl"=dword:00000000
 "Group"="Primary Disk"
-"ImagePath"="system32\drivers\floppy.sys"
+"ImagePath"=expand:"system32\drivers\floppy.sys"
 "Start"=dword:00000004
 "Type"=dword:00000001
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Services\Fs_Rec]
+[\Registry\Machine\SYSTEM\ControlSet001\Services\Fs_Rec]
 "ErrorControl"=dword:00000000
 "Group"="Boot file system"
-"ImagePath"="system32\drivers\fs_rec.sys"
+"ImagePath"=expand:"system32\drivers\fs_rec.sys"
 "Start"=dword:00000001
 "Type"=dword:00000008
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Services\Ide]
+[\Registry\Machine\SYSTEM\ControlSet001\Services\Ide]
 "ErrorControl"=dword:00000000
 "Group"="Primary Disk"
-"ImagePath"="system32\drivers\ide.sys"
+"ImagePath"=expand:"system32\drivers\ide.sys"
 "Start"=dword:00000004
 "Type"=dword:00000001
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Services\Keyboard]
+[\Registry\Machine\SYSTEM\ControlSet001\Services\Keyboard]
 "ErrorControl"=dword:00000000
 "Group"="Keyboard Port"
-"ImagePath"="system32\drivers\keyboard.sys"
+"ImagePath"=expand:"system32\drivers\keyboard.sys"
 "Start"=dword:00000001
 "Type"=dword:00000001
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Services\Msfs]
+[\Registry\Machine\SYSTEM\ControlSet001\Services\Msfs]
 "ErrorControl"=dword:00000000
 "Group"="File System"
-"ImagePath"="system32\drivers\msfs.sys"
+"ImagePath"=expand:"system32\drivers\msfs.sys"
 "Start"=dword:00000001
 "Type"=dword:00000002
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Services\Ne2000]
+[\Registry\Machine\SYSTEM\ControlSet001\Services\Ne2000]
 "ErrorControl"=dword:00000001
 "Group"="NDIS"
-"ImagePath"="system32\drivers\ne2000.sys"
+"ImagePath"=expand:"system32\drivers\ne2000.sys"
 "Start"=dword:00000004
 "Type"=dword:00000001
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Services\Ndis]
+[\Registry\Machine\SYSTEM\ControlSet001\Services\Ndis]
 "ErrorControl"=dword:00000001
 "Group"="NDIS"
-"ImagePath"="system32\drivers\ndis.sys"
+"ImagePath"=expand:"system32\drivers\ndis.sys"
 "Start"=dword:00000001
 "Type"=dword:00000001
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Services\Npfs]
+[\Registry\Machine\SYSTEM\ControlSet001\Services\Npfs]
 "ErrorControl"=dword:00000000
 "Group"="File System"
-"ImagePath"="system32\drivers\npfs.sys"
+"ImagePath"=expand:"system32\drivers\npfs.sys"
 "Start"=dword:00000001
 "Type"=dword:00000002
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Services\Ntfs]
+[\Registry\Machine\SYSTEM\ControlSet001\Services\Ntfs]
 "ErrorControl"=dword:00000000
 "Group"="File System"
-"ImagePath"="system32\drivers\ntfs.sys"
+"ImagePath"=expand:"system32\drivers\ntfs.sys"
 "Start"=dword:00000003
 "Type"=dword:00000002
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Services\Null]
+[\Registry\Machine\SYSTEM\ControlSet001\Services\Null]
 "ErrorControl"=dword:00000000
 "Group"="Base"
-"ImagePath"="system32\drivers\null.sys"
+"ImagePath"=expand:"system32\drivers\null.sys"
 "Start"=dword:00000001
 "Type"=dword:00000001
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Services\Pice]
+[\Registry\Machine\SYSTEM\ControlSet001\Services\Pice]
 "ErrorControl"=dword:00000000
 "Group"="Debug"
-"ImagePath"="system32\drivers\pice.sys"
+"ImagePath"=expand:"system32\drivers\pice.sys"
 "Start"=dword:00000004
 "Type"=dword:00000001
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Services\Scsiport]
+[\Registry\Machine\SYSTEM\ControlSet001\Services\RpcSs]
+"ErrorControl"=dword:00000001
+"ImagePath"=expand:"%SystemRoot%\system32\rpcss.exe"
+"Start"=dword:00000004
+"Type"=dword:00000010
+
+[\Registry\Machine\SYSTEM\ControlSet001\Services\Scsiport]
 "ErrorControl"=dword:00000000
 "Group"="SCSI Port"
-"ImagePath"="system32\drivers\scsiport.sys"
+"ImagePath"=expand:"system32\drivers\scsiport.sys"
 "Start"=dword:00000000
 "Type"=dword:00000001
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Services\Tcpip]
+[\Registry\Machine\SYSTEM\ControlSet001\Services\Tcpip]
 "ErrorControl"=dword:00000001
 "Group"="PNP_TDI"
-"ImagePath"="system32\drivers\tcpip.sys"
+"ImagePath"=expand:"system32\drivers\tcpip.sys"
 "Start"=dword:00000002
 "Type"=dword:00000001
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Services\Vfatfs]
+[\Registry\Machine\SYSTEM\ControlSet001\Services\Vfatfs]
 "ErrorControl"=dword:00000000
 "Group"="Boot File System"
-"ImagePath"="system32\drivers\vfatfs.sys"
+"ImagePath"=expand:"system32\drivers\vfatfs.sys"
 "Start"=dword:00000000
 "Type"=dword:00000002
 
-[\Registry\Machine\SYSTEM\CurrentControlSet\Services\Vga]
+[\Registry\Machine\SYSTEM\ControlSet001\Services\Vga]
 "ErrorControl"=dword:00000000
 "Group"="Video"
-"ImagePath"="system32\drivers\vgamp.sys"
+"ImagePath"=expand:"system32\drivers\vgamp.sys"
 "Start"=dword:00000001
 "Type"=dword:00000001
 
+[\Registry\Machine\SYSTEM\ControlSet002]
+
 [\Registry\Machine\SYSTEM\Select]
 "Current"=dword:00000001
 "Default"=dword:00000001
 "Failed"=dword:00000000
 "LastKnownGood"=dword:00000000
+
+[\Registry\Machine\SYSTEM\Setup]