[NTOSKRNL]
[reactos.git] / reactos / ntoskrnl / config / cmsysini.c
index f6b3142..dc03e96 100644 (file)
@@ -121,6 +121,7 @@ CmpQueryKeyName(IN PVOID ObjectBody,
                 IN KPROCESSOR_MODE PreviousMode)
 {
     PUNICODE_STRING KeyName;
+    ULONG BytesToCopy;
     NTSTATUS Status = STATUS_SUCCESS;
     PCM_KEY_BODY KeyBody = (PCM_KEY_BODY)ObjectBody;
     PCM_KEY_CONTROL_BLOCK Kcb = KeyBody->KeyControlBlock;
@@ -155,17 +156,33 @@ CmpQueryKeyName(IN PVOID ObjectBody,
     /* Set the returned length */
     *ReturnLength = KeyName->Length + sizeof(OBJECT_NAME_INFORMATION) + sizeof(WCHAR);
 
-    /* Check if it fits into the provided buffer */
-    if ((Length < sizeof(OBJECT_NAME_INFORMATION)) ||
-        (Length < (*ReturnLength - sizeof(OBJECT_NAME_INFORMATION))))
+    /* Calculate amount of bytes to copy into the buffer */
+    BytesToCopy = KeyName->Length + sizeof(WCHAR);
+
+    /* Check if the provided buffer is too small to fit even anything */
+    if ((Length <= sizeof(OBJECT_NAME_INFORMATION)) ||
+        ((Length < (*ReturnLength)) && (BytesToCopy < sizeof(WCHAR))))
     {
         /* Free the buffer allocated by CmpConstructName */
         ExFreePool(KeyName);
 
-        /* Return buffer length failure */
+        /* Return buffer length failure without writing anything there because nothing fits */
         return STATUS_INFO_LENGTH_MISMATCH;
     }
 
+    /* Check if the provided buffer can be partially written */
+    if (Length < (*ReturnLength))
+    {
+        /* Yes, indicate so in the return status */
+        Status = STATUS_INFO_LENGTH_MISMATCH;
+
+        /* Calculate amount of bytes which the provided buffer could handle */
+        BytesToCopy = Length - sizeof(OBJECT_NAME_INFORMATION);
+    }
+
+    /* Remove the null termination character from the size */
+    BytesToCopy -= sizeof(WCHAR);
+
     /* Fill in the result */
     _SEH2_TRY
     {
@@ -177,7 +194,10 @@ CmpQueryKeyName(IN PVOID ObjectBody,
         /* Copy string content*/
         RtlCopyMemory(ObjectNameInfo->Name.Buffer,
                       KeyName->Buffer,
-                      *ReturnLength);
+                      BytesToCopy);
+
+        /* Null terminate it */
+        ObjectNameInfo->Name.Buffer[BytesToCopy / sizeof(WCHAR)] = 0;
     }
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
@@ -313,7 +333,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);
 
@@ -339,9 +359,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,
@@ -354,7 +374,7 @@ Quickie:
     RtlFreeUnicodeString(&ValueName);
 
     /* Close the key and return */
-    NtClose(KeyHandle);
+    if (KeyHandle) NtClose(KeyHandle);
 
     /* Return the status */
     return (ExpInTextModeSetup ? STATUS_SUCCESS : Status);
@@ -846,6 +866,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);
@@ -1078,10 +1099,12 @@ CmpLoadHiveThread(IN PVOID StartContext)
 {
     WCHAR FileBuffer[MAX_PATH], RegBuffer[MAX_PATH], ConfigPath[MAX_PATH];
     UNICODE_STRING TempName, FileName, RegName;
-    ULONG FileStart, RegStart, 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();
@@ -1106,10 +1129,9 @@ CmpLoadHiveThread(IN PVOID StartContext)
     /* And build the registry root path */
     RtlInitUnicodeString(&TempName, L"\\REGISTRY\\");
     RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName);
-    RegStart = RegName.Length;
+    //RegStart = RegName.Length;
 
     /* Build the base name */
-    RegName.Length = RegStart;
     RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].BaseName);
     RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName);
 
@@ -1239,7 +1261,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();
 
@@ -1358,7 +1381,8 @@ 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);
         }
     }
 
@@ -1546,7 +1570,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);
@@ -1591,25 +1616,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)
         {
@@ -1617,7 +1642,7 @@ CmpFreeDriverList(IN PHHIVE Hive,
             CmpFree(DriverNode->ListEntry.RegistryPath.Buffer,
                     DriverNode->ListEntry.RegistryPath.MaximumLength);
         }
-        
+
         /* Was there a file path? */
         if (DriverNode->ListEntry.FilePath.Buffer)
         {
@@ -1625,7 +1650,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));
     }
@@ -1653,7 +1678,7 @@ CmGetSystemDriverList(VOID)
 
     /* Initialize the driver list */
     InitializeListHead(&DriverList);
-    
+
     /* Open the system hive key */
     RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\System");
     InitializeObjectAttributes(&ObjectAttributes,
@@ -1663,7 +1688,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,
@@ -1677,38 +1702,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;
@@ -1723,17 +1748,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);
@@ -1933,9 +1958,13 @@ VOID
 NTAPI
 CmShutdownSystem(VOID)
 {
-    /* Kill the workers and flush all hives */
+    /* Kill the workers */
     if (!CmFirstTime) CmpShutdownWorkers();
+
+    /* Flush all hives */
+    CmpLockRegistryExclusive();
     CmpDoFlushAll(TRUE);
+    CmpUnlockRegistry();
 }
 
 VOID
@@ -1946,13 +1975,16 @@ CmpSetVersionData(VOID)
     UNICODE_STRING KeyName;
     UNICODE_STRING ValueName;
     UNICODE_STRING ValueData;
-    HANDLE KeyHandle;
+    HANDLE SoftwareKeyHandle = NULL;
+    HANDLE MicrosoftKeyHandle = NULL;
+    HANDLE WindowsNtKeyHandle = NULL;
+    HANDLE CurrentVersionKeyHandle = NULL;
     WCHAR Buffer[128];
     NTSTATUS Status;
 
     /* Open the 'CurrentVersion' key */
     RtlInitUnicodeString(&KeyName,
-                         L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
+                         L"\\REGISTRY\\MACHINE\\SOFTWARE");
 
     InitializeObjectAttributes(&ObjectAttributes,
                                &KeyName,
@@ -1960,7 +1992,7 @@ CmpSetVersionData(VOID)
                                NULL,
                                NULL);
 
-    Status = NtCreateKey(&KeyHandle,
+    Status = NtCreateKey(&SoftwareKeyHandle,
                          KEY_CREATE_SUB_KEY,
                          &ObjectAttributes,
                          0,
@@ -1973,6 +2005,75 @@ CmpSetVersionData(VOID)
         return;
     }
 
+    /* Open the 'CurrentVersion' key */
+    RtlInitUnicodeString(&KeyName,
+                         L"Microsoft");
+
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               SoftwareKeyHandle,
+                               NULL);
+
+    Status = NtCreateKey(&MicrosoftKeyHandle,
+                         KEY_CREATE_SUB_KEY,
+                         &ObjectAttributes,
+                         0,
+                         NULL,
+                         0,
+                         NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to create key %wZ (Status: %08lx)\n", &KeyName, Status);
+        goto done;
+    }
+
+    /* Open the 'CurrentVersion' key */
+    RtlInitUnicodeString(&KeyName,
+                         L"Windows NT");
+
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               MicrosoftKeyHandle,
+                               NULL);
+
+    Status = NtCreateKey(&WindowsNtKeyHandle,
+                         KEY_CREATE_SUB_KEY,
+                         &ObjectAttributes,
+                         0,
+                         NULL,
+                         0,
+                         NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to create key %wZ (Status: %08lx)\n", &KeyName, Status);
+        goto done;
+    }
+
+    /* Open the 'CurrentVersion' key */
+    RtlInitUnicodeString(&KeyName,
+                         L"CurrentVersion");
+
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               WindowsNtKeyHandle,
+                               NULL);
+
+    Status = NtCreateKey(&CurrentVersionKeyHandle,
+                         KEY_CREATE_SUB_KEY | KEY_SET_VALUE,
+                         &ObjectAttributes,
+                         0,
+                         NULL,
+                         0,
+                         NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to create key %wZ (Status: %08lx)\n", &KeyName, Status);
+        goto done;
+    }
+
     /* Set the 'CurrentType' value */
     RtlInitUnicodeString(&ValueName,
                          L"CurrentType");
@@ -1994,15 +2095,26 @@ CmpSetVersionData(VOID)
     RtlInitUnicodeString(&ValueData,
                          Buffer);
 
-    NtSetValueKey(KeyHandle,
+    NtSetValueKey(CurrentVersionKeyHandle,
                   &ValueName,
                   0,
                   REG_SZ,
                   ValueData.Buffer,
                   ValueData.Length + sizeof(WCHAR));
 
-    /* Close the key */
-    NtClose(KeyHandle);
+done:;
+    /* Close the keys */
+    if (CurrentVersionKeyHandle != NULL)
+        NtClose(CurrentVersionKeyHandle);
+
+    if (WindowsNtKeyHandle != NULL)
+        NtClose(WindowsNtKeyHandle);
+
+    if (MicrosoftKeyHandle != NULL)
+        NtClose(MicrosoftKeyHandle);
+
+    if (SoftwareKeyHandle != NULL)
+        NtClose(SoftwareKeyHandle);
 }
 
 /* EOF */