[NTOS:CM]
[reactos.git] / reactos / ntoskrnl / config / cmsysini.c
index 93ab54b..f41d27b 100644 (file)
@@ -36,6 +36,71 @@ extern BOOLEAN CmFirstTime;
 
 /* FUNCTIONS ******************************************************************/
 
+BOOLEAN
+NTAPI
+CmpLinkKeyToHive(
+    _In_z_ PWSTR LinkKeyName,
+    _In_z_ PWSTR TargetKeyName)
+{
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    UNICODE_STRING LinkKeyName_U;
+    HANDLE TargetKeyHandle;
+    ULONG Disposition;
+    NTSTATUS Status;
+    PAGED_CODE();
+
+    /* Initialize the object attributes */
+    RtlInitUnicodeString(&LinkKeyName_U, LinkKeyName);
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &LinkKeyName_U,
+                               OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+                               NULL,
+                               NULL);
+
+    /* Create the link key */
+    Status = ZwCreateKey(&TargetKeyHandle,
+                         KEY_CREATE_LINK,
+                         &ObjectAttributes,
+                         0,
+                         NULL,
+                         REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK,
+                         &Disposition);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CM: CmpLinkKeyToHive: couldn't create %S Status = 0x%lx\n",
+                LinkKeyName, Status);
+        return FALSE;
+    }
+
+    /* Check if the new key was actually created */
+    if (Disposition != REG_CREATED_NEW_KEY)
+    {
+        DPRINT1("CM: CmpLinkKeyToHive: %S already exists!\n", LinkKeyName);
+        ZwClose(TargetKeyHandle);
+        return FALSE;
+    }
+
+    /* Set the target key name as link target */
+    Status = ZwSetValueKey(TargetKeyHandle,
+                           &CmSymbolicLinkValueName,
+                           0,
+                           REG_LINK,
+                           TargetKeyName,
+                           wcslen(TargetKeyName) * sizeof(WCHAR));
+
+    /* Close the link key handle */
+    ObCloseHandle(TargetKeyHandle, KernelMode);
+
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CM: CmpLinkKeyToHive: couldn't create symbolic link for %S\n",
+                TargetKeyName);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
 VOID
 NTAPI
 CmpDeleteKeyObject(PVOID DeletedObject)
@@ -64,7 +129,7 @@ CmpDeleteKeyObject(PVOID DeletedObject)
     CmpLockRegistry();
 
     /* Make sure this is a valid key body */
-    if (KeyBody->Type == '20yk')
+    if (KeyBody->Type == CM_KEY_BODY_TYPE)
     {
         /* Get the KCB */
         Kcb = KeyBody->KeyControlBlock;
@@ -101,7 +166,7 @@ CmpCloseKeyObject(IN PEPROCESS Process OPTIONAL,
     if (SystemHandleCount > 1) return;
 
     /* Make sure we're a valid key body */
-    if (KeyBody->Type == '20yk')
+    if (KeyBody->Type == CM_KEY_BODY_TYPE)
     {
         /* Don't do anything if we don't have a notify block */
         if (!KeyBody->NotifyBlock) return;
@@ -164,7 +229,7 @@ CmpQueryKeyName(IN PVOID ObjectBody,
         ((Length < (*ReturnLength)) && (BytesToCopy < sizeof(WCHAR))))
     {
         /* Free the buffer allocated by CmpConstructName */
-        ExFreePool(KeyName);
+        ExFreePoolWithTag(KeyName, TAG_CM);
 
         /* Return buffer length failure without writing anything there because nothing fits */
         return STATUS_INFO_LENGTH_MISMATCH;
@@ -207,7 +272,7 @@ CmpQueryKeyName(IN PVOID ObjectBody,
     _SEH2_END;
 
     /* Free the buffer allocated by CmpConstructName */
-    ExFreePool(KeyName);
+    ExFreePoolWithTag(KeyName, TAG_CM);
 
     /* Return status */
     return Status;
@@ -293,7 +358,7 @@ CmpInitHiveFromFile(IN PCUNICODE_STRING HiveName,
                                LogHandle,
                                NULL,
                                HiveName,
-                               0);
+                               CheckFlags);
     if (!NT_SUCCESS(Status))
     {
         /* Fail */
@@ -305,7 +370,7 @@ CmpInitHiveFromFile(IN PCUNICODE_STRING HiveName,
     /* Success, return hive */
     *Hive = NewHive;
 
-    /* ROS: Init root key cell and prepare the hive */
+    /* HACK: ROS: Init root key cell and prepare the hive */
     if (Operation == HINIT_CREATE) CmCreateRootNode(&NewHive->Hive, L"");
 
     /* Duplicate the hive name */
@@ -333,7 +398,7 @@ CmpSetSystemValues(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
 {
     OBJECT_ATTRIBUTES ObjectAttributes;
     UNICODE_STRING KeyName, ValueName = { 0, 0, NULL };
-    HANDLE KeyHandle;
+    HANDLE KeyHandle = NULL;
     NTSTATUS Status;
     ASSERT(LoaderBlock != NULL);
 
@@ -359,9 +424,9 @@ CmpSetSystemValues(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
                            CmpLoadOptions.Length);
     if (!NT_SUCCESS(Status)) goto Quickie;
 
-    /* Setup value name for system boot device */
+    /* Setup value name for system boot device in ARC format */
     RtlInitUnicodeString(&KeyName, L"SystemBootDevice");
-    RtlCreateUnicodeStringFromAsciiz(&ValueName, LoaderBlock->NtBootPathName);
+    RtlCreateUnicodeStringFromAsciiz(&ValueName, LoaderBlock->ArcBootDeviceName);
     Status = NtSetValueKey(KeyHandle,
                            &KeyName,
                            0,
@@ -374,7 +439,7 @@ Quickie:
     RtlFreeUnicodeString(&ValueName);
 
     /* Close the key and return */
-    NtClose(KeyHandle);
+    if (KeyHandle) NtClose(KeyHandle);
 
     /* Return the status */
     return (ExpInTextModeSetup ? STATUS_SUCCESS : Status);
@@ -584,7 +649,7 @@ UseSet:
     LoaderExtension = LoaderBlock->Extension;
     if (LoaderExtension)
     {
-        ASSERTMSG("ReactOS doesn't support NTLDR Profiles yet!\n", FALSE);
+        DPRINT("ReactOS doesn't support NTLDR Profiles yet!\n");
     }
 
     /* Create the current hardware profile key */
@@ -751,7 +816,6 @@ CmpInitializeSystemHive(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
     if (HiveBase)
     {
         /* Import it */
-        ((PHBASE_BLOCK)HiveBase)->Length = LoaderBlock->RegistryLength;
         Status = CmpInitializeHive((PCMHIVE*)&SystemHive,
                                    HINIT_MEMORY,
                                    HIVE_NOLAZYFLUSH,
@@ -866,6 +930,7 @@ CmpCreateObjectTypes(VOID)
     ObjectTypeInitializer.QueryNameProcedure = CmpQueryKeyName;
     ObjectTypeInitializer.CloseProcedure = CmpCloseKeyObject;
     ObjectTypeInitializer.SecurityRequired = TRUE;
+    ObjectTypeInitializer.InvalidAttributes = OBJ_EXCLUSIVE | OBJ_PERMANENT;
 
     /* Create it */
     return ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &CmpKeyObjectType);
@@ -987,11 +1052,15 @@ CmpCreateRegistryRoot(VOID)
                                    NULL,
                                    0,
                                    &KeyName);
-    if (!Kcb) return FALSE;
+    if (!Kcb)
+    {
+        ObDereferenceObject(RootKey);
+        return FALSE;
+    }
 
     /* Initialize the object */
     RootKey->KeyControlBlock = Kcb;
-    RootKey->Type = '20yk';
+    RootKey->Type = CM_KEY_BODY_TYPE;
     RootKey->NotifyBlock = NULL;
     RootKey->ProcessID = PsGetCurrentProcessId();
 
@@ -1005,7 +1074,11 @@ CmpCreateRegistryRoot(VOID)
                             0,
                             NULL,
                             &CmpRegistryRootHandle);
-    if (!NT_SUCCESS(Status)) return FALSE;
+    if (!NT_SUCCESS(Status))
+    {
+        ObDereferenceObject(RootKey);
+        return FALSE;
+    }
 
     /* Reference the key again so that we never lose it */
     Status = ObReferenceObjectByHandle(CmpRegistryRootHandle,
@@ -1014,7 +1087,11 @@ CmpCreateRegistryRoot(VOID)
                                        KernelMode,
                                        (PVOID*)&RootKey,
                                        NULL);
-    if (!NT_SUCCESS(Status)) return FALSE;
+    if (!NT_SUCCESS(Status))
+    {
+        ObDereferenceObject(RootKey);
+        return FALSE;
+    }
 
     /* Completely sucessful */
     return TRUE;
@@ -1098,11 +1175,12 @@ CmpLoadHiveThread(IN PVOID StartContext)
 {
     WCHAR FileBuffer[MAX_PATH], RegBuffer[MAX_PATH], ConfigPath[MAX_PATH];
     UNICODE_STRING TempName, FileName, RegName;
-    ULONG FileStart, i, ErrorResponse, WorkerCount, Length;
+    ULONG i, ErrorResponse, WorkerCount, Length;
+    USHORT FileStart;
     //ULONG RegStart;
     ULONG PrimaryDisposition, SecondaryDisposition, ClusterSize;
     PCMHIVE CmHive;
-    HANDLE PrimaryHandle, LogHandle;
+    HANDLE PrimaryHandle = NULL, LogHandle = NULL;
     NTSTATUS Status = STATUS_SUCCESS;
     PVOID ErrorParameters;
     PAGED_CODE();
@@ -1259,7 +1337,8 @@ CmpInitializeHiveList(IN USHORT Flag)
     UNICODE_STRING TempName, FileName, RegName;
     HANDLE Thread;
     NTSTATUS Status;
-    ULONG RegStart, i;
+    ULONG i;
+    USHORT RegStart;
     PSECURITY_DESCRIPTOR SecurityDescriptor;
     PAGED_CODE();
 
@@ -1378,16 +1457,21 @@ CmpInitializeHiveList(IN USHORT Flag)
         /* Check if we created a new hive */
         if (CmpMachineHiveList[i].CmHive2)
         {
-            /* TODO: Add to HiveList key */
+            /* Add to HiveList key */
+            CmpAddToHiveFileList(CmpMachineHiveList[i].CmHive2);
         }
     }
 
     /* Get rid of the SD */
     ExFreePoolWithTag(SecurityDescriptor, TAG_CM);
 
-    /* FIXME: Link SECURITY to SAM */
+    /* Link SECURITY to SAM */
+    CmpLinkKeyToHive(L"\\Registry\\Machine\\Security\\SAM",
+                     L"\\Registry\\Machine\\SAM\\SAM");
 
-    /* FIXME: Link S-1-5-18 to .Default */
+    /* Link S-1-5-18 to .Default */
+    CmpLinkKeyToHive(L"\\Registry\\User\\S-1-5-18",
+                     L"\\Registry\\User\\.Default");
 }
 
 BOOLEAN
@@ -1566,7 +1650,8 @@ CmInitSystem1(VOID)
         KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 1, 12, Status, 0);
     }
 
-    /* FIXME: Add to HiveList key */
+    /* Add to HiveList key */
+    CmpAddToHiveFileList(HardwareHive);
 
     /* Free the security descriptor */
     ExFreePoolWithTag(SecurityDescriptor, TAG_CM);
@@ -1611,25 +1696,25 @@ CmpFreeDriverList(IN PHHIVE Hive,
     PLIST_ENTRY NextEntry, OldEntry;
     PBOOT_DRIVER_NODE DriverNode;
     PAGED_CODE();
-    
+
     /* Parse the current list */
     NextEntry = DriverList->Flink;
     while (NextEntry != DriverList)
     {
         /* Get the driver node */
         DriverNode = CONTAINING_RECORD(NextEntry, BOOT_DRIVER_NODE, ListEntry.Link);
-        
+
         /* Get the next entry now, since we're going to free it later */
         OldEntry = NextEntry;
         NextEntry = NextEntry->Flink;
-        
+
         /* Was there a name? */
         if (DriverNode->Name.Buffer)
         {
             /* Free it */
             CmpFree(DriverNode->Name.Buffer, DriverNode->Name.Length);
         }
-        
+
         /* Was there a registry path? */
         if (DriverNode->ListEntry.RegistryPath.Buffer)
         {
@@ -1637,7 +1722,7 @@ CmpFreeDriverList(IN PHHIVE Hive,
             CmpFree(DriverNode->ListEntry.RegistryPath.Buffer,
                     DriverNode->ListEntry.RegistryPath.MaximumLength);
         }
-        
+
         /* Was there a file path? */
         if (DriverNode->ListEntry.FilePath.Buffer)
         {
@@ -1645,7 +1730,7 @@ CmpFreeDriverList(IN PHHIVE Hive,
             CmpFree(DriverNode->ListEntry.FilePath.Buffer,
                     DriverNode->ListEntry.FilePath.MaximumLength);
         }
-        
+
         /* Now free the node, and move on */
         CmpFree(OldEntry, sizeof(BOOT_DRIVER_NODE));
     }
@@ -1673,7 +1758,7 @@ CmGetSystemDriverList(VOID)
 
     /* Initialize the driver list */
     InitializeListHead(&DriverList);
-    
+
     /* Open the system hive key */
     RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\System");
     InitializeObjectAttributes(&ObjectAttributes,
@@ -1683,7 +1768,7 @@ CmGetSystemDriverList(VOID)
                                NULL);
     Status = NtOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
     if (!NT_SUCCESS(Status)) return NULL;
-    
+
     /* Reference the key object to get the root hive/cell to access directly */
     Status = ObReferenceObjectByHandle(KeyHandle,
                                        KEY_QUERY_VALUE,
@@ -1697,38 +1782,38 @@ CmGetSystemDriverList(VOID)
         NtClose(KeyHandle);
         return NULL;
     }
-    
+
     /* Do all this under the registry lock */
     CmpLockRegistryExclusive();
-    
+
     /* Get the hive and key cell */
     Hive = KeyBody->KeyControlBlock->KeyHive;
     RootCell = KeyBody->KeyControlBlock->KeyCell;
-    
+
     /* Open the current control set key */
     RtlInitUnicodeString(&KeyName, L"Current");
     ControlCell = CmpFindControlSet(Hive, RootCell, &KeyName, &AutoSelect);
     if (ControlCell == HCELL_NIL) goto EndPath;
-    
+
     /* Find all system drivers */
     Success = CmpFindDrivers(Hive, ControlCell, SystemLoad, NULL, &DriverList);
     if (!Success) goto EndPath;
-    
+
     /* Sort by group/tag */
     if (!CmpSortDriverList(Hive, ControlCell, &DriverList)) goto EndPath;
-    
+
     /* Remove circular dependencies (cycles) and sort */
     if (!CmpResolveDriverDependencies(&DriverList)) goto EndPath;
-    
+
     /* Loop the list to count drivers */
     for (i = 0, NextEntry = DriverList.Flink;
          NextEntry != &DriverList;
          i++, NextEntry = NextEntry->Flink);
-    
+
     /* Allocate the array */
     ServicePath = ExAllocatePool(NonPagedPool, (i + 1) * sizeof(PUNICODE_STRING));
     if (!ServicePath) KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 2, 1, 0, 0);
-    
+
     /* Loop the driver list */
     for (i = 0, NextEntry = DriverList.Flink;
          NextEntry != &DriverList;
@@ -1743,17 +1828,17 @@ CmGetSystemDriverList(VOID)
                                   &DriverEntry->RegistryPath,
                                   ServicePath[i]);
     }
-    
+
     /* Terminate the list */
     ServicePath[i] = NULL;
-    
+
 EndPath:
     /* Free the driver list if we had one */
     if (!IsListEmpty(&DriverList)) CmpFreeDriverList(Hive, &DriverList);
-    
+
     /* Unlock the registry */
     CmpUnlockRegistry();
-    
+
     /* Close the key handle and dereference the object, then return the path */
     ObDereferenceObject(KeyBody);
     NtClose(KeyHandle);
@@ -1876,6 +1961,11 @@ CmpUnlockRegistry(VOID)
         CmpDoFlushAll(TRUE);
         CmpFlushOnLockRelease = FALSE;
     }
+    else
+    {
+        /* Lazy flush the registry */
+        CmpLazyFlush();
+    }
 
     /* Release the lock and leave the critical region */
     ExReleaseResourceLite(&CmpRegistryLock);