Sync with trunk r63270.
[reactos.git] / base / setup / usetup / settings.c
index 90fd263..0346167 100644 (file)
 #define NDEBUG
 #include <debug.h>
 
+/* GLOBALS ******************************************************************/
+
+ULONG DefaultLanguageIndex = 0;
+
 /* FUNCTIONS ****************************************************************/
 
-static BOOLEAN
-GetComputerIdentifier(PWSTR Identifier,
-                      ULONG IdentifierLength)
+static
+BOOLEAN
+IsAcpiComputer(VOID)
+{
+    UNICODE_STRING MultiKeyPathU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
+    UNICODE_STRING IdentifierU = RTL_CONSTANT_STRING(L"Identifier");
+    UNICODE_STRING AcpiBiosIdentifier = RTL_CONSTANT_STRING(L"ACPI BIOS");
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    PKEY_BASIC_INFORMATION pDeviceInformation = NULL;
+    ULONG DeviceInfoLength = sizeof(KEY_BASIC_INFORMATION) + 50 * sizeof(WCHAR);
+    PKEY_VALUE_PARTIAL_INFORMATION pValueInformation = NULL;
+    ULONG ValueInfoLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 50 * sizeof(WCHAR);
+    ULONG RequiredSize;
+    ULONG IndexDevice = 0;
+    UNICODE_STRING DeviceName, ValueName;
+    HANDLE hDevicesKey = NULL;
+    HANDLE hDeviceKey = NULL;
+    NTSTATUS Status;
+    BOOLEAN ret = FALSE;
+
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &MultiKeyPathU,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+    Status = NtOpenKey(&hDevicesKey,
+                       KEY_ENUMERATE_SUB_KEYS,
+                       &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT("NtOpenKey() failed with status 0x%08lx\n", Status);
+        goto cleanup;
+    }
+
+   pDeviceInformation = RtlAllocateHeap(RtlGetProcessHeap(), 0, DeviceInfoLength);
+   if (!pDeviceInformation)
+   {
+      DPRINT("RtlAllocateHeap() failed\n");
+      Status = STATUS_NO_MEMORY;
+      goto cleanup;
+   }
+
+   pValueInformation = RtlAllocateHeap(RtlGetProcessHeap(), 0, ValueInfoLength);
+   if (!pDeviceInformation)
+   {
+      DPRINT("RtlAllocateHeap() failed\n");
+      Status = STATUS_NO_MEMORY;
+      goto cleanup;
+   }
+
+   while (TRUE)
+   {
+      Status = NtEnumerateKey(hDevicesKey, IndexDevice, KeyBasicInformation, pDeviceInformation, DeviceInfoLength, &RequiredSize);
+      if (Status == STATUS_NO_MORE_ENTRIES)
+         break;
+      else if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
+      {
+         RtlFreeHeap(RtlGetProcessHeap(), 0, pDeviceInformation);
+         DeviceInfoLength = RequiredSize;
+         pDeviceInformation = RtlAllocateHeap(RtlGetProcessHeap(), 0, DeviceInfoLength);
+         if (!pDeviceInformation)
+         {
+            DPRINT("RtlAllocateHeap() failed\n");
+            Status = STATUS_NO_MEMORY;
+            goto cleanup;
+         }
+         Status = NtEnumerateKey(hDevicesKey, IndexDevice, KeyBasicInformation, pDeviceInformation, DeviceInfoLength, &RequiredSize);
+      }
+      if (!NT_SUCCESS(Status))
+      {
+         DPRINT("NtEnumerateKey() failed with status 0x%08lx\n", Status);
+         goto cleanup;
+      }
+      IndexDevice++;
+
+      /* Open device key */
+      DeviceName.Length = DeviceName.MaximumLength = pDeviceInformation->NameLength;
+      DeviceName.Buffer = pDeviceInformation->Name;
+      InitializeObjectAttributes(&ObjectAttributes, &DeviceName, OBJ_CASE_INSENSITIVE, hDevicesKey, NULL);
+      Status = NtOpenKey(
+         &hDeviceKey,
+         KEY_QUERY_VALUE,
+         &ObjectAttributes);
+      if (!NT_SUCCESS(Status))
+      {
+         DPRINT("NtOpenKey() failed with status 0x%08lx\n", Status);
+         goto cleanup;
+      }
+
+      /* Read identifier */
+      Status = NtQueryValueKey(hDeviceKey, &IdentifierU, KeyValuePartialInformation, pValueInformation, ValueInfoLength, &RequiredSize);
+      if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
+      {
+         RtlFreeHeap(RtlGetProcessHeap(), 0, pValueInformation);
+         ValueInfoLength = RequiredSize;
+         pValueInformation = RtlAllocateHeap(RtlGetProcessHeap(), 0, ValueInfoLength);
+         if (!pValueInformation)
+         {
+            DPRINT("RtlAllocateHeap() failed\n");
+            Status = STATUS_NO_MEMORY;
+            goto cleanup;
+         }
+         Status = NtQueryValueKey(hDeviceKey, &IdentifierU, KeyValuePartialInformation, pValueInformation, ValueInfoLength, &RequiredSize);
+      }
+      if (!NT_SUCCESS(Status))
+      {
+         DPRINT("NtQueryValueKey() failed with status 0x%08lx\n", Status);
+         goto nextdevice;
+      }
+      else if (pValueInformation->Type != REG_SZ)
+      {
+         DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation->Type, REG_SZ);
+         goto nextdevice;
+      }
+
+      ValueName.Length = ValueName.MaximumLength = pValueInformation->DataLength;
+      ValueName.Buffer = (PWCHAR)pValueInformation->Data;
+      if (ValueName.Length >= sizeof(WCHAR) && ValueName.Buffer[ValueName.Length / sizeof(WCHAR) - 1] == UNICODE_NULL)
+         ValueName.Length -= sizeof(WCHAR);
+      if (RtlCompareUnicodeString(&ValueName, &AcpiBiosIdentifier, FALSE) == 0)
+      {
+         DPRINT("Found ACPI BIOS\n");
+         ret = TRUE;
+         goto cleanup;
+      }
+
+nextdevice:
+      NtClose(hDeviceKey);
+      hDeviceKey = NULL;
+   }
+
+cleanup:
+   if (pDeviceInformation)
+      RtlFreeHeap(RtlGetProcessHeap(), 0, pDeviceInformation);
+   if (pValueInformation)
+      RtlFreeHeap(RtlGetProcessHeap(), 0, pValueInformation);
+   if (hDevicesKey)
+      NtClose(hDevicesKey);
+   if (hDeviceKey)
+      NtClose(hDeviceKey);
+   return ret;
+}
+
+
+static
+BOOLEAN
+GetComputerIdentifier(
+    PWSTR Identifier,
+    ULONG IdentifierLength)
 {
     OBJECT_ATTRIBUTES ObjectAttributes;
     UNICODE_STRING KeyName;
@@ -75,14 +225,12 @@ GetComputerIdentifier(PWSTR Identifier,
     }
 
     /* Get number of subkeys */
-    Status = NtQueryKey(
-        ProcessorsKey,
-        KeyFullInformation,
-        pFullInfo,
-        Size,
-        &Size);
+    Status = NtQueryKey(ProcessorsKey,
+                        KeyFullInformation,
+                        pFullInfo,
+                        Size,
+                        &Size);
     NtClose(ProcessorsKey);
-
     if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
     {
         DPRINT("NtQueryKey() failed (Status 0x%lx)\n", Status);
@@ -98,15 +246,31 @@ GetComputerIdentifier(PWSTR Identifier,
         return FALSE;
     }
 
-    if (pFullInfo->SubKeys == 1)
+    if (IsAcpiComputer())
     {
-        /* Computer is mono-CPU */
-        ComputerIdentifier = L"PC UP";
+        if (pFullInfo->SubKeys == 1)
+        {
+            /* Computer is mono-CPU */
+            ComputerIdentifier = L"ACPI UP";
+        }
+        else
+        {
+            /* Computer is multi-CPUs */
+            ComputerIdentifier = L"ACPI MP";
+        }
     }
     else
     {
-        /* Computer is multi-CPUs */
-        ComputerIdentifier = L"PC MP";
+        if (pFullInfo->SubKeys == 1)
+        {
+            /* Computer is mono-CPU */
+            ComputerIdentifier = L"PC UP";
+        }
+        else
+        {
+            /* Computer is multi-CPUs */
+            ComputerIdentifier = L"PC MP";
+        }
     }
 
     RtlFreeHeap(RtlGetProcessHeap(), 0, pFullInfo);
@@ -123,7 +287,8 @@ GetComputerIdentifier(PWSTR Identifier,
 
 
 PGENERIC_LIST
-CreateComputerTypeList(HINF InfFile)
+CreateComputerTypeList(
+    HINF InfFile)
 {
     CHAR Buffer[128];
     PGENERIC_LIST List;
@@ -211,8 +376,10 @@ CreateComputerTypeList(HINF InfFile)
 }
 
 
-static BOOLEAN
-GetDisplayIdentifier(PWSTR Identifier,
+static
+BOOLEAN
+GetDisplayIdentifier(
+    PWSTR Identifier,
     ULONG IdentifierLength)
 {
     OBJECT_ATTRIBUTES ObjectAttributes;
@@ -377,7 +544,8 @@ GetDisplayIdentifier(PWSTR Identifier,
 
 
 PGENERIC_LIST
-CreateDisplayDriverList(HINF InfFile)
+CreateDisplayDriverList(
+    HINF InfFile)
 {
     CHAR Buffer[128];
     PGENERIC_LIST List;
@@ -477,8 +645,12 @@ CreateDisplayDriverList(HINF InfFile)
     return List;
 }
 
+
 BOOLEAN
-ProcessComputerFiles(HINF InfFile, PGENERIC_LIST List, PWCHAR* AdditionalSectionName)
+ProcessComputerFiles(
+    HINF InfFile,
+    PGENERIC_LIST List,
+    PWCHAR *AdditionalSectionName)
 {
     PGENERIC_LIST_ENTRY Entry;
     static WCHAR SectionName[128];
@@ -501,7 +673,9 @@ ProcessComputerFiles(HINF InfFile, PGENERIC_LIST List, PWCHAR* AdditionalSection
 
 
 BOOLEAN
-ProcessDisplayRegistry(HINF InfFile, PGENERIC_LIST List)
+ProcessDisplayRegistry(
+    HINF InfFile,
+    PGENERIC_LIST List)
 {
     PGENERIC_LIST_ENTRY Entry;
     INFCONTEXT Context;
@@ -539,12 +713,11 @@ ProcessDisplayRegistry(HINF InfFile, PGENERIC_LIST List)
 
     StartValue = 1;
     Status = RtlWriteRegistryValue(RTL_REGISTRY_SERVICES,
-        ServiceName,
-        L"Start",
-        REG_DWORD,
-        &StartValue,
-        sizeof(ULONG));
-
+                                   ServiceName,
+                                   L"Start",
+                                   REG_DWORD,
+                                   &StartValue,
+                                   sizeof(ULONG));
     if (!NT_SUCCESS(Status))
     {
         DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status);
@@ -562,11 +735,11 @@ ProcessDisplayRegistry(HINF InfFile, PGENERIC_LIST List)
 
     Width = wcstoul(Buffer, NULL, 10);
     Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
-        RegPath,
-        L"DefaultSettings.XResolution",
-        REG_DWORD,
-        &Width,
-        sizeof(ULONG));
+                                   RegPath,
+                                   L"DefaultSettings.XResolution",
+                                   REG_DWORD,
+                                   &Width,
+                                   sizeof(ULONG));
     if (!NT_SUCCESS(Status))
     {
         DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status);
@@ -581,11 +754,11 @@ ProcessDisplayRegistry(HINF InfFile, PGENERIC_LIST List)
 
     Height = wcstoul(Buffer, 0, 0);
     Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
-        RegPath,
-        L"DefaultSettings.YResolution",
-        REG_DWORD,
-        &Height,
-        sizeof(ULONG));
+                                   RegPath,
+                                   L"DefaultSettings.YResolution",
+                                   REG_DWORD,
+                                   &Height,
+                                   sizeof(ULONG));
     if (!NT_SUCCESS(Status))
     {
         DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status);
@@ -600,11 +773,11 @@ ProcessDisplayRegistry(HINF InfFile, PGENERIC_LIST List)
 
     Bpp = wcstoul(Buffer, 0, 0);
     Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
-        RegPath,
-        L"DefaultSettings.BitsPerPel",
-        REG_DWORD,
-        &Bpp,
-        sizeof(ULONG));
+                                   RegPath,
+                                   L"DefaultSettings.BitsPerPel",
+                                   REG_DWORD,
+                                   &Bpp,
+                                   sizeof(ULONG));
     if (!NT_SUCCESS(Status))
     {
         DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status);
@@ -618,7 +791,8 @@ ProcessDisplayRegistry(HINF InfFile, PGENERIC_LIST List)
 
 
 BOOLEAN
-ProcessLocaleRegistry(PGENERIC_LIST List)
+ProcessLocaleRegistry(
+    PGENERIC_LIST List)
 {
     PGENERIC_LIST_ENTRY Entry;
     PWCHAR LanguageId;
@@ -654,7 +828,6 @@ ProcessLocaleRegistry(PGENERIC_LIST List)
     Status =  NtOpenKey(&KeyHandle,
                         KEY_SET_VALUE,
                         &ObjectAttributes);
-
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
@@ -698,7 +871,8 @@ ProcessLocaleRegistry(PGENERIC_LIST List)
 
 
 PGENERIC_LIST
-CreateKeyboardDriverList(HINF InfFile)
+CreateKeyboardDriverList(
+    HINF InfFile)
 {
     CHAR Buffer[128];
     PGENERIC_LIST List;
@@ -726,9 +900,9 @@ CreateKeyboardDriverList(HINF InfFile)
             break;
         }
 
-        UserData = (WCHAR*) RtlAllocateHeap(ProcessHeap,
-                                            0,
-                                            (wcslen(KeyName) + 1) * sizeof(WCHAR));
+        UserData = (WCHAR*)RtlAllocateHeap(ProcessHeap,
+                                           0,
+                                           (wcslen(KeyName) + 1) * sizeof(WCHAR));
         if (UserData == NULL)
         {
             /* FIXME: Handle error! */
@@ -743,7 +917,6 @@ CreateKeyboardDriverList(HINF InfFile)
     return List;
 }
 
-ULONG DefaultLanguageIndex = 0;
 
 ULONG
 GetDefaultLanguageIndex(VOID)
@@ -751,15 +924,18 @@ GetDefaultLanguageIndex(VOID)
     return DefaultLanguageIndex;
 }
 
+
 PGENERIC_LIST
-CreateLanguageList(HINF InfFile, WCHAR * DefaultLanguage) 
+CreateLanguageList(
+    HINF InfFile,
+    WCHAR *DefaultLanguage) 
 {
     CHAR Buffer[128];
     PGENERIC_LIST List;
     INFCONTEXT Context;
     PWCHAR KeyName;
     PWCHAR KeyValue;
-    PWCHAR UserData;
+    PWCHAR UserData = NULL;
     ULONG uIndex = 0;
 
     /* Get default language id */
@@ -792,31 +968,46 @@ CreateLanguageList(HINF InfFile, WCHAR * DefaultLanguage)
             break;
         }
 
-        UserData = (WCHAR*) RtlAllocateHeap(ProcessHeap,
-                                            0,
-                                            (wcslen(KeyName) + 1) * sizeof(WCHAR));
-        if (UserData == NULL)
+        if (IsLanguageAvailable(KeyName))
         {
-            /* FIXME: Handle error! */
-        }
 
-        wcscpy(UserData, KeyName);
+            UserData = (WCHAR*) RtlAllocateHeap(ProcessHeap,
+                                                0,
+                                                (wcslen(KeyName) + 1) * sizeof(WCHAR));
+            if (UserData == NULL)
+            {
+                /* FIXME: Handle error! */
+            }
 
-        if (!_wcsicmp(KeyName, DefaultLanguage)) DefaultLanguageIndex = uIndex;
+            wcscpy(UserData, KeyName);
 
-        sprintf(Buffer, "%S", KeyValue);
-        AppendGenericListEntry(List,
-                               Buffer,
-                               UserData,
-                               FALSE);
-        uIndex++;
+            if (!_wcsicmp(KeyName, DefaultLanguage))
+                DefaultLanguageIndex = uIndex;
+
+            sprintf(Buffer, "%S", KeyValue);
+            AppendGenericListEntry(List,
+                                   Buffer,
+                                   UserData,
+                                   FALSE);
+            uIndex++;
+        }
     } while (SetupFindNextLine(&Context, &Context));
 
+    /* Only one language available, make it the default one */
+    if(uIndex == 1 && UserData != NULL)
+    {
+        DefaultLanguageIndex = 0;
+        wcscpy(DefaultLanguage, UserData);
+    }
+
     return List;
 }
 
+
 PGENERIC_LIST
-CreateKeyboardLayoutList(HINF InfFile, WCHAR * DefaultKBLayout)
+CreateKeyboardLayoutList(
+    HINF InfFile,
+    WCHAR *DefaultKBLayout)
 {
     CHAR Buffer[128];
     PGENERIC_LIST List;
@@ -863,10 +1054,9 @@ CreateKeyboardLayoutList(HINF InfFile, WCHAR * DefaultKBLayout)
 
             if (_wcsicmp(LayoutsList[uIndex].LayoutID, KeyName) == 0)
             {
-                UserData = (WCHAR*) RtlAllocateHeap(ProcessHeap,
-                                                0,
-                                                (wcslen(KeyName) + 1) * sizeof(WCHAR));
-
+                UserData = (WCHAR*)RtlAllocateHeap(ProcessHeap,
+                                                   0,
+                                                   (wcslen(KeyName) + 1) * sizeof(WCHAR));
                 if (UserData == NULL)
                 {
                     /* FIXME: Handle error! */
@@ -902,8 +1092,10 @@ CreateKeyboardLayoutList(HINF InfFile, WCHAR * DefaultKBLayout)
     return List;
 }
 
+
 BOOLEAN
-ProcessKeyboardLayoutRegistry(PGENERIC_LIST List)
+ProcessKeyboardLayoutRegistry(
+    PGENERIC_LIST List)
 {
     PGENERIC_LIST_ENTRY Entry;
     PWCHAR LayoutId;
@@ -952,14 +1144,17 @@ ProcessKeyboardLayoutRegistry(PGENERIC_LIST List)
 
 #if 0
 BOOLEAN
-ProcessKeyboardLayoutFiles(PGENERIC_LIST List)
+ProcessKeyboardLayoutFiles(
+    PGENERIC_LIST List)
 {
     return TRUE;
 }
 #endif
 
+
 BOOLEAN
-SetGeoID(PWCHAR Id)
+SetGeoID(
+    PWCHAR Id)
 {
     OBJECT_ATTRIBUTES ObjectAttributes;
     UNICODE_STRING KeyName;
@@ -968,6 +1163,7 @@ SetGeoID(PWCHAR Id)
     WCHAR szKeyName[] = L"\\Registry\\User\\.DEFAULT\\Control Panel\\International\\Geo";
     WCHAR szValueName[] = L"Nation";
     NTSTATUS Status;
+
     RtlInitUnicodeString(&KeyName,
                          szKeyName);
     InitializeObjectAttributes(&ObjectAttributes,
@@ -978,24 +1174,25 @@ SetGeoID(PWCHAR Id)
 
     Status =  NtOpenKey(&KeyHandle,
                         KEY_SET_VALUE,
-                         &ObjectAttributes);
+                        &ObjectAttributes);
     if(!NT_SUCCESS(Status))
     {
         DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
         return FALSE;
     }
+
     RtlInitUnicodeString(&ValueName, szValueName);
     Status = NtSetValueKey(KeyHandle,
-                                   &ValueName,
-                                   0,
-                                   REG_SZ,
-                                   (PVOID)Id,
-                                   (wcslen(Id) + 1) * sizeof(WCHAR));
+                           &ValueName,
+                           0,
+                           REG_SZ,
+                           (PVOID)Id,
+                           (wcslen(Id) + 1) * sizeof(WCHAR));
     NtClose(KeyHandle);
     if (!NT_SUCCESS(Status))
     {
-         DPRINT1("NtSetValueKey() failed (Status = %lx)\n", Status);
-         return FALSE;
+        DPRINT1("NtSetValueKey() failed (Status = %lx)\n", Status);
+        return FALSE;
     }
 
     return TRUE;