2004-05-30 14:54:02 +00:00
|
|
|
/*
|
|
|
|
* ReactOS kernel
|
|
|
|
* Copyright (C) 2004 ReactOS Team
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
2009-10-27 10:34:16 +00:00
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
2004-05-30 14:54:02 +00:00
|
|
|
*/
|
2005-09-19 08:11:43 +00:00
|
|
|
/* COPYRIGHT: See COPYING in the top level directory
|
2004-05-30 14:54:02 +00:00
|
|
|
* PROJECT: ReactOS text-mode setup
|
2015-09-13 16:40:36 +00:00
|
|
|
* FILE: base/setup/usetup/settings.c
|
2004-05-30 14:54:02 +00:00
|
|
|
* PURPOSE: Device settings support functions
|
2018-05-27 19:33:07 +00:00
|
|
|
* PROGRAMMERS: Colin Finck
|
2004-05-30 14:54:02 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
2006-08-31 09:13:03 +00:00
|
|
|
#include "usetup.h"
|
2004-05-30 14:54:02 +00:00
|
|
|
|
2010-06-07 21:38:49 +00:00
|
|
|
#define NDEBUG
|
2004-05-30 14:54:02 +00:00
|
|
|
#include <debug.h>
|
|
|
|
|
2014-05-12 16:14:19 +00:00
|
|
|
/* GLOBALS ******************************************************************/
|
|
|
|
|
|
|
|
ULONG DefaultLanguageIndex = 0;
|
|
|
|
|
2004-05-30 14:54:02 +00:00
|
|
|
/* FUNCTIONS ****************************************************************/
|
|
|
|
|
2014-05-12 16:14:19 +00:00
|
|
|
static
|
|
|
|
BOOLEAN
|
2011-08-15 06:27:23 +00:00
|
|
|
IsAcpiComputer(VOID)
|
|
|
|
{
|
2014-05-12 16:14:19 +00:00
|
|
|
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;
|
|
|
|
}
|
2011-08-15 06:27:23 +00:00
|
|
|
|
|
|
|
pDeviceInformation = RtlAllocateHeap(RtlGetProcessHeap(), 0, DeviceInfoLength);
|
|
|
|
if (!pDeviceInformation)
|
|
|
|
{
|
|
|
|
DPRINT("RtlAllocateHeap() failed\n");
|
|
|
|
Status = STATUS_NO_MEMORY;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
pValueInformation = RtlAllocateHeap(RtlGetProcessHeap(), 0, ValueInfoLength);
|
2015-12-04 09:24:52 +00:00
|
|
|
if (!pValueInformation)
|
2011-08-15 06:27:23 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-12 16:14:19 +00:00
|
|
|
static
|
|
|
|
BOOLEAN
|
|
|
|
GetComputerIdentifier(
|
|
|
|
PWSTR Identifier,
|
|
|
|
ULONG IdentifierLength)
|
2005-09-19 08:11:43 +00:00
|
|
|
{
|
2008-01-07 17:22:05 +00:00
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
UNICODE_STRING KeyName;
|
|
|
|
LPCWSTR ComputerIdentifier;
|
|
|
|
HANDLE ProcessorsKey;
|
|
|
|
PKEY_FULL_INFORMATION pFullInfo;
|
|
|
|
ULONG Size, SizeNeeded;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
DPRINT("GetComputerIdentifier() called\n");
|
|
|
|
|
|
|
|
Size = sizeof(KEY_FULL_INFORMATION);
|
|
|
|
pFullInfo = (PKEY_FULL_INFORMATION)RtlAllocateHeap(RtlGetProcessHeap(), 0, Size);
|
|
|
|
if (!pFullInfo)
|
|
|
|
{
|
|
|
|
DPRINT("RtlAllocateHeap() failed\n");
|
|
|
|
return FALSE;
|
2005-09-19 08:11:43 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
/* Open the processors key */
|
|
|
|
RtlInitUnicodeString(&KeyName,
|
|
|
|
L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor");
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&KeyName,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
Status = NtOpenKey(&ProcessorsKey,
|
|
|
|
KEY_QUERY_VALUE ,
|
|
|
|
&ObjectAttributes);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT("NtOpenKey() failed (Status 0x%lx)\n", Status);
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, pFullInfo);
|
|
|
|
return FALSE;
|
2005-09-19 08:11:43 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
/* Get number of subkeys */
|
2014-05-12 16:14:19 +00:00
|
|
|
Status = NtQueryKey(ProcessorsKey,
|
|
|
|
KeyFullInformation,
|
|
|
|
pFullInfo,
|
|
|
|
Size,
|
|
|
|
&Size);
|
2008-01-07 17:22:05 +00:00
|
|
|
NtClose(ProcessorsKey);
|
|
|
|
if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
|
|
|
|
{
|
|
|
|
DPRINT("NtQueryKey() failed (Status 0x%lx)\n", Status);
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, pFullInfo);
|
|
|
|
return FALSE;
|
2005-09-19 08:11:43 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
/* Find computer identifier */
|
|
|
|
if (pFullInfo->SubKeys == 0)
|
2005-09-19 08:11:43 +00:00
|
|
|
{
|
2008-01-07 17:22:05 +00:00
|
|
|
/* Something strange happened. No processor detected */
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, pFullInfo);
|
|
|
|
return FALSE;
|
2005-09-19 08:11:43 +00:00
|
|
|
}
|
|
|
|
|
2011-08-15 06:27:23 +00:00
|
|
|
if (IsAcpiComputer())
|
2005-09-19 08:11:43 +00:00
|
|
|
{
|
2011-08-15 06:27:23 +00:00
|
|
|
if (pFullInfo->SubKeys == 1)
|
|
|
|
{
|
|
|
|
/* Computer is mono-CPU */
|
|
|
|
ComputerIdentifier = L"ACPI UP";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Computer is multi-CPUs */
|
|
|
|
ComputerIdentifier = L"ACPI MP";
|
|
|
|
}
|
2005-09-19 08:11:43 +00:00
|
|
|
}
|
2008-01-07 17:22:05 +00:00
|
|
|
else
|
2005-09-19 08:11:43 +00:00
|
|
|
{
|
2011-08-15 06:27:23 +00:00
|
|
|
if (pFullInfo->SubKeys == 1)
|
|
|
|
{
|
|
|
|
/* Computer is mono-CPU */
|
|
|
|
ComputerIdentifier = L"PC UP";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Computer is multi-CPUs */
|
|
|
|
ComputerIdentifier = L"PC MP";
|
|
|
|
}
|
2005-09-19 08:11:43 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, pFullInfo);
|
|
|
|
|
|
|
|
/* Copy computer identifier to return buffer */
|
|
|
|
SizeNeeded = (wcslen(ComputerIdentifier) + 1) * sizeof(WCHAR);
|
|
|
|
if (SizeNeeded > IdentifierLength)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
RtlCopyMemory(Identifier, ComputerIdentifier, SizeNeeded);
|
|
|
|
|
|
|
|
return TRUE;
|
2005-09-19 08:11:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-05-30 14:54:02 +00:00
|
|
|
PGENERIC_LIST
|
2014-05-12 16:14:19 +00:00
|
|
|
CreateComputerTypeList(
|
|
|
|
HINF InfFile)
|
2004-05-30 14:54:02 +00:00
|
|
|
{
|
2008-01-07 17:22:05 +00:00
|
|
|
CHAR Buffer[128];
|
|
|
|
PGENERIC_LIST List;
|
|
|
|
INFCONTEXT Context;
|
|
|
|
PWCHAR KeyName;
|
|
|
|
PWCHAR KeyValue;
|
|
|
|
PWCHAR UserData;
|
|
|
|
WCHAR ComputerIdentifier[128];
|
|
|
|
WCHAR ComputerKey[32];
|
|
|
|
|
|
|
|
/* Get the computer identification */
|
|
|
|
if (!GetComputerIdentifier(ComputerIdentifier, 128))
|
|
|
|
{
|
|
|
|
ComputerIdentifier[0] = 0;
|
2005-09-19 08:11:43 +00:00
|
|
|
}
|
|
|
|
|
2011-08-15 07:36:58 +00:00
|
|
|
DPRINT("Computer identifier: '%S'\n", ComputerIdentifier);
|
2005-09-19 08:11:43 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
/* Search for matching device identifier */
|
|
|
|
if (!SetupFindFirstLineW(InfFile, L"Map.Computer", NULL, &Context))
|
2005-09-19 08:11:43 +00:00
|
|
|
{
|
2008-01-07 17:22:05 +00:00
|
|
|
/* FIXME: error message */
|
|
|
|
return NULL;
|
2005-09-19 08:11:43 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
do
|
2005-09-19 08:11:43 +00:00
|
|
|
{
|
2008-01-07 17:22:05 +00:00
|
|
|
if (!INF_GetDataField(&Context, 1, &KeyValue))
|
2005-09-19 08:11:43 +00:00
|
|
|
{
|
2008-01-07 17:22:05 +00:00
|
|
|
/* FIXME: Handle error! */
|
|
|
|
DPRINT("INF_GetDataField() failed\n");
|
|
|
|
return NULL;
|
2005-09-19 08:11:43 +00:00
|
|
|
}
|
|
|
|
|
2011-08-15 07:36:58 +00:00
|
|
|
DPRINT("KeyValue: %S\n", KeyValue);
|
2008-01-07 17:22:05 +00:00
|
|
|
if (wcsstr(ComputerIdentifier, KeyValue))
|
2005-09-19 08:11:43 +00:00
|
|
|
{
|
2008-01-07 17:22:05 +00:00
|
|
|
if (!INF_GetDataField(&Context, 0, &KeyName))
|
2005-09-19 08:11:43 +00:00
|
|
|
{
|
2008-01-07 17:22:05 +00:00
|
|
|
/* FIXME: Handle error! */
|
|
|
|
DPRINT("INF_GetDataField() failed\n");
|
|
|
|
return NULL;
|
2005-09-19 08:11:43 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
DPRINT("Computer key: %S\n", KeyName);
|
|
|
|
wcscpy(ComputerKey, KeyName);
|
2005-09-19 08:11:43 +00:00
|
|
|
}
|
2008-01-07 17:22:05 +00:00
|
|
|
} while (SetupFindNextLine(&Context, &Context));
|
2004-05-30 14:54:02 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
List = CreateGenericList();
|
|
|
|
if (List == NULL)
|
|
|
|
return NULL;
|
2004-05-30 14:54:02 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
if (!SetupFindFirstLineW (InfFile, L"Computer", NULL, &Context))
|
2004-05-30 14:54:02 +00:00
|
|
|
{
|
2008-01-07 17:22:05 +00:00
|
|
|
DestroyGenericList(List, FALSE);
|
|
|
|
return NULL;
|
2004-05-30 14:54:02 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
do
|
2004-05-30 14:54:02 +00:00
|
|
|
{
|
2008-01-07 17:22:05 +00:00
|
|
|
if (!INF_GetData (&Context, &KeyName, &KeyValue))
|
|
|
|
{
|
|
|
|
/* FIXME: Handle error! */
|
|
|
|
DPRINT("INF_GetData() failed\n");
|
|
|
|
break;
|
|
|
|
}
|
2004-05-30 14:54:02 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
UserData = (WCHAR*) RtlAllocateHeap(ProcessHeap,
|
|
|
|
0,
|
|
|
|
(wcslen(KeyName) + 1) * sizeof(WCHAR));
|
|
|
|
if (UserData == NULL)
|
|
|
|
{
|
|
|
|
/* FIXME: Handle error! */
|
|
|
|
}
|
2004-05-30 14:54:02 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
wcscpy(UserData, KeyName);
|
2004-05-30 14:54:02 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
sprintf(Buffer, "%S", KeyValue);
|
|
|
|
AppendGenericListEntry(List, Buffer, UserData,
|
|
|
|
_wcsicmp(KeyName, ComputerKey) ? FALSE : TRUE);
|
|
|
|
} while (SetupFindNextLine(&Context, &Context));
|
2004-05-30 14:54:02 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
return List;
|
2004-05-30 14:54:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-12 16:14:19 +00:00
|
|
|
static
|
|
|
|
BOOLEAN
|
|
|
|
GetDisplayIdentifier(
|
|
|
|
PWSTR Identifier,
|
2008-01-07 17:22:05 +00:00
|
|
|
ULONG IdentifierLength)
|
2004-06-20 12:18:08 +00:00
|
|
|
{
|
2008-01-07 17:22:05 +00:00
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
UNICODE_STRING KeyName;
|
|
|
|
WCHAR Buffer[32];
|
|
|
|
HANDLE BusKey;
|
|
|
|
HANDLE BusInstanceKey;
|
|
|
|
HANDLE ControllerKey;
|
|
|
|
HANDLE ControllerInstanceKey;
|
|
|
|
ULONG BusInstance;
|
|
|
|
ULONG ControllerInstance;
|
|
|
|
ULONG BufferLength;
|
|
|
|
ULONG ReturnedLength;
|
|
|
|
PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
DPRINT("GetDisplayIdentifier() called\n");
|
|
|
|
|
|
|
|
/* Open the bus key */
|
|
|
|
RtlInitUnicodeString(&KeyName,
|
|
|
|
L"\\Registry\\Machine\\HARDWARE\\Description\\System\\MultifunctionAdapter");
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&KeyName,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
Status = NtOpenKey(&BusKey,
|
2009-08-23 08:29:23 +00:00
|
|
|
KEY_ENUMERATE_SUB_KEYS,
|
2008-01-07 17:22:05 +00:00
|
|
|
&ObjectAttributes);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT("NtOpenKey() failed (Status %lx)\n", Status);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BusInstance = 0;
|
|
|
|
while (TRUE)
|
|
|
|
{
|
|
|
|
swprintf(Buffer, L"%lu", BusInstance);
|
|
|
|
RtlInitUnicodeString(&KeyName,
|
|
|
|
Buffer);
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&KeyName,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
BusKey,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
Status = NtOpenKey(&BusInstanceKey,
|
2009-08-23 08:29:23 +00:00
|
|
|
KEY_ENUMERATE_SUB_KEYS,
|
2008-01-07 17:22:05 +00:00
|
|
|
&ObjectAttributes);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT("NtOpenKey() failed (Status %lx)\n", Status);
|
|
|
|
NtClose(BusKey);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Open the controller type key */
|
|
|
|
RtlInitUnicodeString(&KeyName,
|
|
|
|
L"DisplayController");
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&KeyName,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
BusInstanceKey,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
Status = NtOpenKey(&ControllerKey,
|
2009-08-23 08:29:23 +00:00
|
|
|
KEY_ENUMERATE_SUB_KEYS,
|
2008-01-07 17:22:05 +00:00
|
|
|
&ObjectAttributes);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
ControllerInstance = 0;
|
2004-06-20 12:18:08 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
while (TRUE)
|
|
|
|
{
|
|
|
|
/* Open the pointer controller instance key */
|
|
|
|
swprintf(Buffer, L"%lu", ControllerInstance);
|
|
|
|
RtlInitUnicodeString(&KeyName,
|
|
|
|
Buffer);
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&KeyName,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
ControllerKey,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
Status = NtOpenKey(&ControllerInstanceKey,
|
2009-08-23 08:29:23 +00:00
|
|
|
KEY_QUERY_VALUE,
|
2008-01-07 17:22:05 +00:00
|
|
|
&ObjectAttributes);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT("NtOpenKey() failed (Status %lx)\n", Status);
|
|
|
|
NtClose(ControllerKey);
|
|
|
|
NtClose(BusInstanceKey);
|
|
|
|
NtClose(BusKey);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get controller identifier */
|
|
|
|
RtlInitUnicodeString(&KeyName,
|
|
|
|
L"Identifier");
|
|
|
|
|
|
|
|
BufferLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
|
|
|
|
256 * sizeof(WCHAR);
|
|
|
|
ValueInfo = (KEY_VALUE_PARTIAL_INFORMATION*) RtlAllocateHeap(RtlGetProcessHeap(),
|
|
|
|
0,
|
|
|
|
BufferLength);
|
|
|
|
if (ValueInfo == NULL)
|
|
|
|
{
|
|
|
|
DPRINT("RtlAllocateHeap() failed\n");
|
|
|
|
NtClose(ControllerInstanceKey);
|
|
|
|
NtClose(ControllerKey);
|
|
|
|
NtClose(BusInstanceKey);
|
|
|
|
NtClose(BusKey);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = NtQueryValueKey(ControllerInstanceKey,
|
|
|
|
&KeyName,
|
|
|
|
KeyValuePartialInformation,
|
|
|
|
ValueInfo,
|
|
|
|
BufferLength,
|
|
|
|
&ReturnedLength);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT("Identifier: %S\n", (PWSTR)ValueInfo->Data);
|
|
|
|
|
|
|
|
BufferLength = min(ValueInfo->DataLength / sizeof(WCHAR), IdentifierLength);
|
|
|
|
RtlCopyMemory (Identifier,
|
|
|
|
ValueInfo->Data,
|
|
|
|
BufferLength * sizeof(WCHAR));
|
|
|
|
Identifier[BufferLength] = 0;
|
|
|
|
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(),
|
|
|
|
0,
|
|
|
|
ValueInfo);
|
|
|
|
|
|
|
|
NtClose(ControllerInstanceKey);
|
|
|
|
NtClose(ControllerKey);
|
|
|
|
NtClose(BusInstanceKey);
|
|
|
|
NtClose(BusKey);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
NtClose(ControllerInstanceKey);
|
|
|
|
|
|
|
|
ControllerInstance++;
|
|
|
|
}
|
|
|
|
|
|
|
|
NtClose(ControllerKey);
|
|
|
|
}
|
|
|
|
|
|
|
|
NtClose(BusInstanceKey);
|
|
|
|
|
|
|
|
BusInstance++;
|
2004-06-20 12:18:08 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
NtClose(BusKey);
|
2004-06-20 12:18:08 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
return FALSE;
|
2004-06-20 12:18:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-05-30 14:54:02 +00:00
|
|
|
PGENERIC_LIST
|
2014-05-12 16:14:19 +00:00
|
|
|
CreateDisplayDriverList(
|
|
|
|
HINF InfFile)
|
2004-05-30 14:54:02 +00:00
|
|
|
{
|
2008-01-07 17:22:05 +00:00
|
|
|
CHAR Buffer[128];
|
|
|
|
PGENERIC_LIST List;
|
|
|
|
INFCONTEXT Context;
|
|
|
|
PWCHAR KeyName;
|
|
|
|
PWCHAR KeyValue;
|
|
|
|
PWCHAR UserData;
|
|
|
|
WCHAR DisplayIdentifier[128];
|
|
|
|
WCHAR DisplayKey[32];
|
|
|
|
|
|
|
|
/* Get the display identification */
|
|
|
|
if (!GetDisplayIdentifier(DisplayIdentifier, 128))
|
|
|
|
{
|
|
|
|
DisplayIdentifier[0] = 0;
|
2004-06-20 12:18:08 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
DPRINT("Display identifier: '%S'\n", DisplayIdentifier);
|
2004-06-20 12:18:08 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
/* Search for matching device identifier */
|
|
|
|
if (!SetupFindFirstLineW(InfFile, L"Map.Display", NULL, &Context))
|
2004-06-20 12:18:08 +00:00
|
|
|
{
|
2008-01-07 17:22:05 +00:00
|
|
|
/* FIXME: error message */
|
|
|
|
return NULL;
|
2004-06-20 12:18:08 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
do
|
|
|
|
{
|
|
|
|
if (!INF_GetDataField(&Context, 1, &KeyValue))
|
|
|
|
{
|
|
|
|
/* FIXME: Handle error! */
|
|
|
|
DPRINT("INF_GetDataField() failed\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
2004-06-20 12:18:08 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
DPRINT("KeyValue: %S\n", KeyValue);
|
|
|
|
if (wcsstr(DisplayIdentifier, KeyValue))
|
|
|
|
{
|
|
|
|
if (!INF_GetDataField(&Context, 0, &KeyName))
|
|
|
|
{
|
|
|
|
/* FIXME: Handle error! */
|
|
|
|
DPRINT("INF_GetDataField() failed\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
DPRINT("Display key: %S\n", KeyName);
|
|
|
|
wcscpy(DisplayKey, KeyName);
|
|
|
|
}
|
|
|
|
} while (SetupFindNextLine(&Context, &Context));
|
2004-05-30 14:54:02 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
List = CreateGenericList();
|
|
|
|
if (List == NULL)
|
|
|
|
return NULL;
|
2004-05-30 14:54:02 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
if (!SetupFindFirstLineW (InfFile, L"Display", NULL, &Context))
|
2004-05-30 14:54:02 +00:00
|
|
|
{
|
2008-01-07 17:22:05 +00:00
|
|
|
DestroyGenericList(List, FALSE);
|
|
|
|
return NULL;
|
2004-05-30 14:54:02 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
do
|
|
|
|
{
|
|
|
|
if (!INF_GetDataField(&Context, 0, &KeyName))
|
|
|
|
{
|
|
|
|
DPRINT1("INF_GetDataField() failed\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!INF_GetDataField(&Context, 1, &KeyValue))
|
|
|
|
{
|
|
|
|
DPRINT1("INF_GetDataField() failed\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
UserData = (WCHAR*) RtlAllocateHeap(ProcessHeap,
|
|
|
|
0,
|
|
|
|
(wcslen(KeyName) + 1) * sizeof(WCHAR));
|
|
|
|
if (UserData == NULL)
|
|
|
|
{
|
|
|
|
DPRINT1("RtlAllocateHeap() failed\n");
|
|
|
|
DestroyGenericList(List, TRUE);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
wcscpy(UserData, KeyName);
|
|
|
|
|
|
|
|
sprintf(Buffer, "%S", KeyValue);
|
|
|
|
AppendGenericListEntry(List,
|
|
|
|
Buffer,
|
|
|
|
UserData,
|
|
|
|
_wcsicmp(KeyName, DisplayKey) ? FALSE : TRUE);
|
|
|
|
} while (SetupFindNextLine(&Context, &Context));
|
2004-05-30 14:54:02 +00:00
|
|
|
|
2004-06-20 12:18:08 +00:00
|
|
|
#if 0
|
2008-01-07 17:22:05 +00:00
|
|
|
AppendGenericListEntry(List, "Other display driver", NULL, TRUE);
|
2004-06-20 12:18:08 +00:00
|
|
|
#endif
|
2004-05-30 14:54:02 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
return List;
|
2004-05-30 14:54:02 +00:00
|
|
|
}
|
|
|
|
|
2014-05-12 16:14:19 +00:00
|
|
|
|
2005-02-20 22:40:30 +00:00
|
|
|
BOOLEAN
|
2014-05-12 16:14:19 +00:00
|
|
|
ProcessComputerFiles(
|
|
|
|
HINF InfFile,
|
|
|
|
PGENERIC_LIST List,
|
|
|
|
PWCHAR *AdditionalSectionName)
|
2005-02-20 22:40:30 +00:00
|
|
|
{
|
2008-01-07 17:22:05 +00:00
|
|
|
PGENERIC_LIST_ENTRY Entry;
|
|
|
|
static WCHAR SectionName[128];
|
2005-05-08 04:07:56 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
DPRINT("ProcessComputerFiles() called\n");
|
2005-05-08 04:07:56 +00:00
|
|
|
|
2008-05-11 21:17:57 +00:00
|
|
|
Entry = GetCurrentListEntry(List);
|
2008-01-07 17:22:05 +00:00
|
|
|
if (Entry == NULL)
|
|
|
|
{
|
2008-05-11 21:17:57 +00:00
|
|
|
DPRINT("GetCurrentListEntry() failed\n");
|
2008-01-07 17:22:05 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2005-05-08 04:07:56 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
wcscpy(SectionName, L"Files.");
|
2008-05-11 21:17:57 +00:00
|
|
|
wcscat(SectionName, (const wchar_t*)GetListEntryUserData(Entry));
|
2008-01-07 17:22:05 +00:00
|
|
|
*AdditionalSectionName = SectionName;
|
2005-05-08 04:07:56 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
return TRUE;
|
2005-02-20 22:40:30 +00:00
|
|
|
}
|
|
|
|
|
2004-05-30 14:54:02 +00:00
|
|
|
|
2004-06-20 12:18:08 +00:00
|
|
|
BOOLEAN
|
2014-05-12 16:14:19 +00:00
|
|
|
ProcessDisplayRegistry(
|
|
|
|
HINF InfFile,
|
|
|
|
PGENERIC_LIST List)
|
2004-06-20 12:18:08 +00:00
|
|
|
{
|
2008-01-07 17:22:05 +00:00
|
|
|
PGENERIC_LIST_ENTRY Entry;
|
|
|
|
INFCONTEXT Context;
|
|
|
|
PWCHAR ServiceName;
|
|
|
|
ULONG StartValue;
|
|
|
|
NTSTATUS Status;
|
|
|
|
WCHAR RegPath [255];
|
|
|
|
PWCHAR Buffer;
|
|
|
|
ULONG Width, Height, Bpp;
|
|
|
|
|
|
|
|
DPRINT("ProcessDisplayRegistry() called\n");
|
|
|
|
|
2008-05-11 21:17:57 +00:00
|
|
|
Entry = GetCurrentListEntry(List);
|
2008-01-07 17:22:05 +00:00
|
|
|
if (Entry == NULL)
|
|
|
|
{
|
2015-03-29 11:29:02 +00:00
|
|
|
DPRINT1("GetCurrentListEntry() failed\n");
|
2008-01-07 17:22:05 +00:00
|
|
|
return FALSE;
|
2004-06-20 12:18:08 +00:00
|
|
|
}
|
|
|
|
|
2008-05-11 21:17:57 +00:00
|
|
|
if (!SetupFindFirstLineW(InfFile, L"Display", (WCHAR*)GetListEntryUserData(Entry), &Context))
|
2004-06-20 12:18:08 +00:00
|
|
|
{
|
2015-03-29 11:29:02 +00:00
|
|
|
DPRINT1("SetupFindFirstLineW() failed\n");
|
2008-01-07 17:22:05 +00:00
|
|
|
return FALSE;
|
2004-06-20 12:18:08 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
/* Enable the right driver */
|
|
|
|
if (!INF_GetDataField(&Context, 3, &ServiceName))
|
2004-06-20 12:18:08 +00:00
|
|
|
{
|
2015-03-29 11:29:02 +00:00
|
|
|
DPRINT1("INF_GetDataField() failed\n");
|
2008-01-07 17:22:05 +00:00
|
|
|
return FALSE;
|
2004-06-20 12:18:08 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
ASSERT(wcslen(ServiceName) < 10);
|
|
|
|
DPRINT("Service name: %S\n", ServiceName);
|
2004-06-20 12:18:08 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
StartValue = 1;
|
|
|
|
Status = RtlWriteRegistryValue(RTL_REGISTRY_SERVICES,
|
2014-05-12 16:14:19 +00:00
|
|
|
ServiceName,
|
|
|
|
L"Start",
|
|
|
|
REG_DWORD,
|
|
|
|
&StartValue,
|
|
|
|
sizeof(ULONG));
|
2008-01-07 17:22:05 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2004-06-20 12:18:08 +00:00
|
|
|
{
|
2015-03-29 11:29:02 +00:00
|
|
|
DPRINT1("RtlWriteRegistryValue() failed (Status %lx)\n", Status);
|
2008-01-07 17:22:05 +00:00
|
|
|
return FALSE;
|
2004-06-20 12:18:08 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
/* Set the resolution */
|
|
|
|
swprintf(RegPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet\\Services\\%s\\Device0", ServiceName);
|
2005-12-23 18:03:12 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
if (!INF_GetDataField(&Context, 4, &Buffer))
|
2005-12-23 18:03:12 +00:00
|
|
|
{
|
2015-03-29 11:29:02 +00:00
|
|
|
DPRINT1("INF_GetDataField() failed\n");
|
2008-01-07 17:22:05 +00:00
|
|
|
return FALSE;
|
2005-12-23 18:03:12 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
Width = wcstoul(Buffer, NULL, 10);
|
|
|
|
Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
|
2014-05-12 16:14:19 +00:00
|
|
|
RegPath,
|
|
|
|
L"DefaultSettings.XResolution",
|
|
|
|
REG_DWORD,
|
|
|
|
&Width,
|
|
|
|
sizeof(ULONG));
|
2008-01-07 17:22:05 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2015-03-29 11:29:02 +00:00
|
|
|
DPRINT1("RtlWriteRegistryValue() failed (Status %lx)\n", Status);
|
2008-01-07 17:22:05 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2007-01-05 20:19:21 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
if (!INF_GetDataField(&Context, 5, &Buffer))
|
2005-12-23 18:03:12 +00:00
|
|
|
{
|
2015-03-29 11:29:02 +00:00
|
|
|
DPRINT1("INF_GetDataField() failed\n");
|
2008-01-07 17:22:05 +00:00
|
|
|
return FALSE;
|
2005-12-23 18:03:12 +00:00
|
|
|
}
|
2008-01-07 17:22:05 +00:00
|
|
|
|
|
|
|
Height = wcstoul(Buffer, 0, 0);
|
|
|
|
Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
|
2014-05-12 16:14:19 +00:00
|
|
|
RegPath,
|
|
|
|
L"DefaultSettings.YResolution",
|
|
|
|
REG_DWORD,
|
|
|
|
&Height,
|
|
|
|
sizeof(ULONG));
|
2008-01-07 17:22:05 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2015-03-29 11:29:02 +00:00
|
|
|
DPRINT1("RtlWriteRegistryValue() failed (Status %lx)\n", Status);
|
2008-01-07 17:22:05 +00:00
|
|
|
return FALSE;
|
2005-12-23 18:03:12 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
if (!INF_GetDataField(&Context, 6, &Buffer))
|
2005-12-23 18:03:12 +00:00
|
|
|
{
|
2015-03-29 11:29:02 +00:00
|
|
|
DPRINT1("INF_GetDataField() failed\n");
|
2008-01-07 17:22:05 +00:00
|
|
|
return FALSE;
|
2005-12-23 18:03:12 +00:00
|
|
|
}
|
2008-01-07 17:22:05 +00:00
|
|
|
|
|
|
|
Bpp = wcstoul(Buffer, 0, 0);
|
|
|
|
Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
|
2014-05-12 16:14:19 +00:00
|
|
|
RegPath,
|
|
|
|
L"DefaultSettings.BitsPerPel",
|
|
|
|
REG_DWORD,
|
|
|
|
&Bpp,
|
|
|
|
sizeof(ULONG));
|
2008-01-07 17:22:05 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2015-03-29 11:29:02 +00:00
|
|
|
DPRINT1("RtlWriteRegistryValue() failed (Status %lx)\n", Status);
|
2008-01-07 17:22:05 +00:00
|
|
|
return FALSE;
|
2005-12-23 18:03:12 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
DPRINT("ProcessDisplayRegistry() done\n");
|
2004-06-20 12:18:08 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
return TRUE;
|
2004-06-20 12:18:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-01-07 21:34:56 +00:00
|
|
|
BOOLEAN
|
2014-05-12 16:14:19 +00:00
|
|
|
ProcessLocaleRegistry(
|
|
|
|
PGENERIC_LIST List)
|
2008-01-07 21:34:56 +00:00
|
|
|
{
|
|
|
|
PGENERIC_LIST_ENTRY Entry;
|
|
|
|
PWCHAR LanguageId;
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
UNICODE_STRING KeyName;
|
|
|
|
UNICODE_STRING ValueName;
|
|
|
|
|
|
|
|
HANDLE KeyHandle;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
2008-05-11 21:17:57 +00:00
|
|
|
Entry = GetCurrentListEntry(List);
|
2008-01-07 21:34:56 +00:00
|
|
|
if (Entry == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
2008-05-11 21:17:57 +00:00
|
|
|
LanguageId = (PWCHAR)GetListEntryUserData(Entry);
|
2008-01-07 21:34:56 +00:00
|
|
|
if (LanguageId == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
2015-12-18 21:36:16 +00:00
|
|
|
DPRINT("LanguageId: %S\n", LanguageId);
|
|
|
|
|
|
|
|
/* Open the default users locale key */
|
|
|
|
RtlInitUnicodeString(&KeyName,
|
|
|
|
L"\\Registry\\User\\.DEFAULT\\Control Panel\\International");
|
|
|
|
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&KeyName,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
Status = NtOpenKey(&KeyHandle,
|
|
|
|
KEY_SET_VALUE,
|
|
|
|
&ObjectAttributes);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set default user locale */
|
|
|
|
RtlInitUnicodeString(&ValueName,
|
|
|
|
L"Locale");
|
|
|
|
Status = NtSetValueKey(KeyHandle,
|
|
|
|
&ValueName,
|
|
|
|
0,
|
|
|
|
REG_SZ,
|
|
|
|
(PVOID)LanguageId,
|
|
|
|
(wcslen(LanguageId) + 1) * sizeof(WCHAR));
|
|
|
|
NtClose(KeyHandle);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
[USETUP]
- Fix a buffer overflow (overread) when adding a locale key to the registry. The history of this bug is funny:
1. Eric wrote the code, which sets a key of REG_SZ type, as 4 widechars plus terminating zero, but passes 8 as the bytesize of the buffer. It's not fully correct (a terminating zero is absent from the bytesize of the buffer, but MSDN doesn't specify if it should be added or not, and hardcoding "8" is not the best idea too) but not dramatic. That was revision 9596, 7 years ago.
2. Lentin notices something is not right in this code, and decides to "fix" it by multiplying that same hardcoded value by.... guess what? sizeof(PWCHAR)! That is, size of a pointer, which on an x86 would be 4 bytes. Massive out of bounds access obviously happens. That was revision 31642, 3 years ago.
3. Very soon Colin reshuffles and improves the code based on patch #2635, however the problem still goes unnoticed (r31655+).
See issue #5810 for more details.
svn path=/trunk/; revision=50968
2011-03-04 18:18:05 +00:00
|
|
|
/* Skip first 4 zeroes */
|
|
|
|
if (wcslen(LanguageId) >= 4)
|
|
|
|
LanguageId += 4;
|
|
|
|
|
2008-01-07 21:34:56 +00:00
|
|
|
/* Open the NLS language key */
|
|
|
|
RtlInitUnicodeString(&KeyName,
|
|
|
|
L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\Language");
|
|
|
|
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&KeyName,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
Status = NtOpenKey(&KeyHandle,
|
2009-08-23 08:29:23 +00:00
|
|
|
KEY_SET_VALUE,
|
2008-01-07 21:34:56 +00:00
|
|
|
&ObjectAttributes);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set default language */
|
|
|
|
RtlInitUnicodeString(&ValueName,
|
|
|
|
L"Default");
|
|
|
|
Status = NtSetValueKey(KeyHandle,
|
|
|
|
&ValueName,
|
|
|
|
0,
|
|
|
|
REG_SZ,
|
[USETUP]
- Fix a buffer overflow (overread) when adding a locale key to the registry. The history of this bug is funny:
1. Eric wrote the code, which sets a key of REG_SZ type, as 4 widechars plus terminating zero, but passes 8 as the bytesize of the buffer. It's not fully correct (a terminating zero is absent from the bytesize of the buffer, but MSDN doesn't specify if it should be added or not, and hardcoding "8" is not the best idea too) but not dramatic. That was revision 9596, 7 years ago.
2. Lentin notices something is not right in this code, and decides to "fix" it by multiplying that same hardcoded value by.... guess what? sizeof(PWCHAR)! That is, size of a pointer, which on an x86 would be 4 bytes. Massive out of bounds access obviously happens. That was revision 31642, 3 years ago.
3. Very soon Colin reshuffles and improves the code based on patch #2635, however the problem still goes unnoticed (r31655+).
See issue #5810 for more details.
svn path=/trunk/; revision=50968
2011-03-04 18:18:05 +00:00
|
|
|
(PVOID)LanguageId,
|
|
|
|
(wcslen(LanguageId) + 1) * sizeof(WCHAR));
|
2008-01-07 21:34:56 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
|
|
|
|
NtClose(KeyHandle);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set install language */
|
|
|
|
RtlInitUnicodeString(&ValueName,
|
|
|
|
L"InstallLanguage");
|
|
|
|
Status = NtSetValueKey (KeyHandle,
|
|
|
|
&ValueName,
|
|
|
|
0,
|
|
|
|
REG_SZ,
|
[USETUP]
- Fix a buffer overflow (overread) when adding a locale key to the registry. The history of this bug is funny:
1. Eric wrote the code, which sets a key of REG_SZ type, as 4 widechars plus terminating zero, but passes 8 as the bytesize of the buffer. It's not fully correct (a terminating zero is absent from the bytesize of the buffer, but MSDN doesn't specify if it should be added or not, and hardcoding "8" is not the best idea too) but not dramatic. That was revision 9596, 7 years ago.
2. Lentin notices something is not right in this code, and decides to "fix" it by multiplying that same hardcoded value by.... guess what? sizeof(PWCHAR)! That is, size of a pointer, which on an x86 would be 4 bytes. Massive out of bounds access obviously happens. That was revision 31642, 3 years ago.
3. Very soon Colin reshuffles and improves the code based on patch #2635, however the problem still goes unnoticed (r31655+).
See issue #5810 for more details.
svn path=/trunk/; revision=50968
2011-03-04 18:18:05 +00:00
|
|
|
(PVOID)LanguageId,
|
|
|
|
(wcslen(LanguageId) + 1) * sizeof(WCHAR));
|
2010-09-25 19:24:03 +00:00
|
|
|
NtClose(KeyHandle);
|
2008-01-07 21:34:56 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-05-30 14:54:02 +00:00
|
|
|
PGENERIC_LIST
|
2014-05-12 16:14:19 +00:00
|
|
|
CreateKeyboardDriverList(
|
|
|
|
HINF InfFile)
|
2004-05-30 14:54:02 +00:00
|
|
|
{
|
2008-01-07 17:22:05 +00:00
|
|
|
CHAR Buffer[128];
|
|
|
|
PGENERIC_LIST List;
|
|
|
|
INFCONTEXT Context;
|
|
|
|
PWCHAR KeyName;
|
|
|
|
PWCHAR KeyValue;
|
|
|
|
PWCHAR UserData;
|
2004-05-30 14:54:02 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
List = CreateGenericList();
|
|
|
|
if (List == NULL)
|
|
|
|
return NULL;
|
2004-05-30 14:54:02 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
if (!SetupFindFirstLineW (InfFile, L"Keyboard", NULL, &Context))
|
2004-05-30 14:54:02 +00:00
|
|
|
{
|
2008-01-07 17:22:05 +00:00
|
|
|
DestroyGenericList(List, FALSE);
|
|
|
|
return NULL;
|
2004-05-30 14:54:02 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
do
|
2004-05-30 14:54:02 +00:00
|
|
|
{
|
2008-01-07 17:22:05 +00:00
|
|
|
if (!INF_GetData (&Context, &KeyName, &KeyValue))
|
|
|
|
{
|
|
|
|
/* FIXME: Handle error! */
|
|
|
|
DPRINT("INF_GetData() failed\n");
|
|
|
|
break;
|
|
|
|
}
|
2004-05-30 14:54:02 +00:00
|
|
|
|
2014-05-12 16:14:19 +00:00
|
|
|
UserData = (WCHAR*)RtlAllocateHeap(ProcessHeap,
|
|
|
|
0,
|
|
|
|
(wcslen(KeyName) + 1) * sizeof(WCHAR));
|
2008-01-07 17:22:05 +00:00
|
|
|
if (UserData == NULL)
|
|
|
|
{
|
|
|
|
/* FIXME: Handle error! */
|
|
|
|
}
|
2004-05-30 14:54:02 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
wcscpy(UserData, KeyName);
|
2004-05-30 14:54:02 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
sprintf(Buffer, "%S", KeyValue);
|
|
|
|
AppendGenericListEntry(List, Buffer, UserData, FALSE);
|
|
|
|
} while (SetupFindNextLine(&Context, &Context));
|
2004-05-30 14:54:02 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
return List;
|
2004-05-30 14:54:02 +00:00
|
|
|
}
|
|
|
|
|
2008-06-02 15:34:57 +00:00
|
|
|
|
|
|
|
ULONG
|
|
|
|
GetDefaultLanguageIndex(VOID)
|
|
|
|
{
|
|
|
|
return DefaultLanguageIndex;
|
|
|
|
}
|
|
|
|
|
2014-05-12 16:14:19 +00:00
|
|
|
|
2008-06-02 15:34:57 +00:00
|
|
|
PGENERIC_LIST
|
2014-05-12 16:14:19 +00:00
|
|
|
CreateLanguageList(
|
|
|
|
HINF InfFile,
|
2015-03-29 11:29:02 +00:00
|
|
|
WCHAR *DefaultLanguage)
|
2008-01-07 17:22:05 +00:00
|
|
|
{
|
|
|
|
CHAR Buffer[128];
|
|
|
|
PGENERIC_LIST List;
|
|
|
|
INFCONTEXT Context;
|
|
|
|
PWCHAR KeyName;
|
|
|
|
PWCHAR KeyValue;
|
2012-02-27 22:46:20 +00:00
|
|
|
PWCHAR UserData = NULL;
|
2008-06-02 15:34:57 +00:00
|
|
|
ULONG uIndex = 0;
|
2008-01-07 17:22:05 +00:00
|
|
|
|
|
|
|
/* Get default language id */
|
|
|
|
if (!SetupFindFirstLineW (InfFile, L"NLS", L"DefaultLanguage", &Context))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!INF_GetData (&Context, NULL, &KeyValue))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
wcscpy(DefaultLanguage, KeyValue);
|
|
|
|
|
2007-12-25 20:24:19 +00:00
|
|
|
SelectedLanguageId = KeyValue;
|
2007-12-23 20:29:52 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
List = CreateGenericList();
|
|
|
|
if (List == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!SetupFindFirstLineW (InfFile, L"Language", NULL, &Context))
|
|
|
|
{
|
2008-06-02 15:34:57 +00:00
|
|
|
DestroyGenericList(List, FALSE);
|
2015-03-29 11:29:02 +00:00
|
|
|
return NULL;
|
2008-01-07 17:22:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (!INF_GetData (&Context, &KeyName, &KeyValue))
|
|
|
|
{
|
|
|
|
/* FIXME: Handle error! */
|
|
|
|
DPRINT("INF_GetData() failed\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-02-27 22:46:20 +00:00
|
|
|
if (IsLanguageAvailable(KeyName))
|
2008-01-07 17:22:05 +00:00
|
|
|
{
|
|
|
|
|
2012-02-27 22:46:20 +00:00
|
|
|
UserData = (WCHAR*) RtlAllocateHeap(ProcessHeap,
|
|
|
|
0,
|
|
|
|
(wcslen(KeyName) + 1) * sizeof(WCHAR));
|
|
|
|
if (UserData == NULL)
|
|
|
|
{
|
|
|
|
/* FIXME: Handle error! */
|
|
|
|
}
|
2008-01-07 17:22:05 +00:00
|
|
|
|
2012-02-27 22:46:20 +00:00
|
|
|
wcscpy(UserData, KeyName);
|
2008-06-02 15:34:57 +00:00
|
|
|
|
2012-02-27 22:46:20 +00:00
|
|
|
if (!_wcsicmp(KeyName, DefaultLanguage))
|
|
|
|
DefaultLanguageIndex = uIndex;
|
|
|
|
|
|
|
|
sprintf(Buffer, "%S", KeyValue);
|
|
|
|
AppendGenericListEntry(List,
|
|
|
|
Buffer,
|
|
|
|
UserData,
|
|
|
|
FALSE);
|
|
|
|
uIndex++;
|
|
|
|
}
|
2008-01-07 17:22:05 +00:00
|
|
|
} while (SetupFindNextLine(&Context, &Context));
|
|
|
|
|
2012-02-27 22:46:20 +00:00
|
|
|
/* Only one language available, make it the default one */
|
|
|
|
if(uIndex == 1 && UserData != NULL)
|
|
|
|
{
|
|
|
|
DefaultLanguageIndex = 0;
|
|
|
|
wcscpy(DefaultLanguage, UserData);
|
|
|
|
}
|
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
return List;
|
2007-12-23 20:29:52 +00:00
|
|
|
}
|
2004-05-30 14:54:02 +00:00
|
|
|
|
2014-05-12 16:14:19 +00:00
|
|
|
|
2004-05-30 14:54:02 +00:00
|
|
|
PGENERIC_LIST
|
2014-05-12 16:14:19 +00:00
|
|
|
CreateKeyboardLayoutList(
|
|
|
|
HINF InfFile,
|
|
|
|
WCHAR *DefaultKBLayout)
|
2004-05-30 14:54:02 +00:00
|
|
|
{
|
2008-01-07 17:22:05 +00:00
|
|
|
CHAR Buffer[128];
|
|
|
|
PGENERIC_LIST List;
|
|
|
|
INFCONTEXT Context;
|
|
|
|
PWCHAR KeyName;
|
|
|
|
PWCHAR KeyValue;
|
|
|
|
PWCHAR UserData;
|
2008-06-01 12:52:18 +00:00
|
|
|
const MUI_LAYOUTS * LayoutsList;
|
|
|
|
ULONG uIndex = 0;
|
2009-04-20 03:16:12 +00:00
|
|
|
BOOL KeyboardLayoutsFound = FALSE;
|
2004-05-30 14:54:02 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
/* Get default layout id */
|
|
|
|
if (!SetupFindFirstLineW (InfFile, L"NLS", L"DefaultLayout", &Context))
|
|
|
|
return NULL;
|
2004-05-30 14:54:02 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
if (!INF_GetData (&Context, NULL, &KeyValue))
|
|
|
|
return NULL;
|
2004-05-30 14:54:02 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
wcscpy(DefaultKBLayout, KeyValue);
|
2004-05-30 14:54:02 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
List = CreateGenericList();
|
|
|
|
if (List == NULL)
|
|
|
|
return NULL;
|
2004-05-30 14:54:02 +00:00
|
|
|
|
2008-06-01 12:52:18 +00:00
|
|
|
LayoutsList = MUIGetLayoutsList();
|
2004-05-30 14:54:02 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
do
|
|
|
|
{
|
2008-06-01 12:52:18 +00:00
|
|
|
if (!SetupFindFirstLineW(InfFile, L"KeyboardLayout", NULL, &Context))
|
2008-01-07 17:22:05 +00:00
|
|
|
{
|
|
|
|
DestroyGenericList(List, FALSE);
|
2008-06-01 12:52:18 +00:00
|
|
|
return NULL;
|
2008-01-07 17:22:05 +00:00
|
|
|
}
|
2004-05-30 14:54:02 +00:00
|
|
|
|
2008-06-01 12:52:18 +00:00
|
|
|
do
|
2008-01-07 17:22:05 +00:00
|
|
|
{
|
2008-06-01 12:52:18 +00:00
|
|
|
if (!INF_GetData (&Context, &KeyName, &KeyValue))
|
|
|
|
{
|
|
|
|
/* FIXME: Handle error! */
|
|
|
|
DPRINT("INF_GetData() failed\n");
|
|
|
|
DestroyGenericList(List, FALSE);
|
2009-04-20 03:16:12 +00:00
|
|
|
return NULL;
|
2008-06-01 12:52:18 +00:00
|
|
|
}
|
2004-06-02 22:18:06 +00:00
|
|
|
|
2008-06-01 12:52:18 +00:00
|
|
|
{
|
2014-05-12 16:14:19 +00:00
|
|
|
UserData = (WCHAR*)RtlAllocateHeap(ProcessHeap,
|
|
|
|
0,
|
|
|
|
(wcslen(KeyName) + 1) * sizeof(WCHAR));
|
2008-06-01 12:52:18 +00:00
|
|
|
if (UserData == NULL)
|
|
|
|
{
|
|
|
|
/* FIXME: Handle error! */
|
2009-04-20 03:16:12 +00:00
|
|
|
DPRINT("RtlAllocateHeap() failed\n");
|
|
|
|
DestroyGenericList(List, FALSE);
|
|
|
|
return NULL;
|
2008-06-01 12:52:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
wcscpy(UserData, KeyName);
|
|
|
|
|
|
|
|
sprintf(Buffer, "%S", KeyValue);
|
|
|
|
AppendGenericListEntry(List,
|
|
|
|
Buffer,
|
|
|
|
UserData,
|
|
|
|
_wcsicmp(KeyName, DefaultKBLayout) ? FALSE : TRUE);
|
2009-04-20 03:16:12 +00:00
|
|
|
KeyboardLayoutsFound = TRUE;
|
2008-06-01 12:52:18 +00:00
|
|
|
}
|
2009-04-20 03:16:12 +00:00
|
|
|
|
2008-06-01 12:52:18 +00:00
|
|
|
} while (SetupFindNextLine(&Context, &Context));
|
|
|
|
|
|
|
|
uIndex++;
|
|
|
|
|
|
|
|
} while (LayoutsList[uIndex].LangID != NULL);
|
2004-06-02 22:18:06 +00:00
|
|
|
|
2009-04-20 03:16:12 +00:00
|
|
|
/* FIXME: Handle this case */
|
|
|
|
if (!KeyboardLayoutsFound)
|
|
|
|
{
|
|
|
|
DPRINT1("No keyboard layouts have been found\n");
|
|
|
|
DestroyGenericList(List, FALSE);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
return List;
|
|
|
|
}
|
2004-06-02 22:18:06 +00:00
|
|
|
|
2014-05-12 16:14:19 +00:00
|
|
|
|
2008-01-07 17:22:05 +00:00
|
|
|
BOOLEAN
|
2014-05-12 16:14:19 +00:00
|
|
|
ProcessKeyboardLayoutRegistry(
|
|
|
|
PGENERIC_LIST List)
|
2008-01-07 17:22:05 +00:00
|
|
|
{
|
|
|
|
PGENERIC_LIST_ENTRY Entry;
|
2008-06-01 12:52:18 +00:00
|
|
|
PWCHAR LayoutId;
|
|
|
|
const MUI_LAYOUTS * LayoutsList;
|
|
|
|
MUI_LAYOUTS NewLayoutsList[20];
|
2008-12-18 12:26:47 +00:00
|
|
|
ULONG uIndex;
|
2008-06-01 12:52:18 +00:00
|
|
|
ULONG uOldPos = 0;
|
2008-01-07 17:22:05 +00:00
|
|
|
|
2008-05-11 21:17:57 +00:00
|
|
|
Entry = GetCurrentListEntry(List);
|
2008-01-07 17:22:05 +00:00
|
|
|
if (Entry == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
2008-06-01 12:52:18 +00:00
|
|
|
LayoutId = (PWCHAR)GetListEntryUserData(Entry);
|
|
|
|
if (LayoutId == NULL)
|
2008-01-07 17:22:05 +00:00
|
|
|
return FALSE;
|
2008-04-28 14:04:22 +00:00
|
|
|
|
2008-06-01 12:52:18 +00:00
|
|
|
LayoutsList = MUIGetLayoutsList();
|
2008-04-28 14:04:22 +00:00
|
|
|
|
2008-06-01 12:52:18 +00:00
|
|
|
if (_wcsicmp(LayoutsList[0].LayoutID, LayoutId) != 0)
|
2008-01-07 17:22:05 +00:00
|
|
|
{
|
2008-12-18 12:26:47 +00:00
|
|
|
for (uIndex = 1; LayoutsList[uIndex].LangID != NULL; uIndex++)
|
2008-04-28 14:04:22 +00:00
|
|
|
{
|
2008-06-01 12:52:18 +00:00
|
|
|
if (_wcsicmp(LayoutsList[uIndex].LayoutID, LayoutId) == 0)
|
|
|
|
{
|
|
|
|
uOldPos = uIndex;
|
2008-12-18 12:26:47 +00:00
|
|
|
continue;
|
2008-06-01 12:52:18 +00:00
|
|
|
}
|
2008-04-28 14:04:22 +00:00
|
|
|
|
2008-12-18 12:26:47 +00:00
|
|
|
NewLayoutsList[uIndex].LangID = LayoutsList[uIndex].LangID;
|
|
|
|
NewLayoutsList[uIndex].LayoutID = LayoutsList[uIndex].LayoutID;
|
|
|
|
}
|
2008-04-28 14:04:22 +00:00
|
|
|
|
2008-06-01 12:52:18 +00:00
|
|
|
NewLayoutsList[uIndex].LangID = NULL;
|
|
|
|
NewLayoutsList[uIndex].LayoutID = NULL;
|
|
|
|
NewLayoutsList[uOldPos].LangID = LayoutsList[0].LangID;
|
|
|
|
NewLayoutsList[uOldPos].LayoutID = LayoutsList[0].LayoutID;
|
|
|
|
NewLayoutsList[0].LangID = LayoutsList[uOldPos].LangID;
|
|
|
|
NewLayoutsList[0].LayoutID = LayoutsList[uOldPos].LayoutID;
|
2008-01-07 17:22:05 +00:00
|
|
|
|
2008-06-01 12:52:18 +00:00
|
|
|
return AddKbLayoutsToRegistry(NewLayoutsList);
|
|
|
|
}
|
2008-01-07 17:22:05 +00:00
|
|
|
|
|
|
|
return TRUE;
|
2004-05-30 14:54:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-06-07 12:24:00 +00:00
|
|
|
#if 0
|
2004-05-30 14:54:02 +00:00
|
|
|
BOOLEAN
|
2014-05-12 16:14:19 +00:00
|
|
|
ProcessKeyboardLayoutFiles(
|
|
|
|
PGENERIC_LIST List)
|
2004-05-30 14:54:02 +00:00
|
|
|
{
|
2008-01-07 17:22:05 +00:00
|
|
|
return TRUE;
|
2004-05-30 14:54:02 +00:00
|
|
|
}
|
2004-06-07 12:24:00 +00:00
|
|
|
#endif
|
|
|
|
|
2014-05-12 16:14:19 +00:00
|
|
|
|
2009-02-05 13:50:49 +00:00
|
|
|
BOOLEAN
|
2014-05-12 16:14:19 +00:00
|
|
|
SetGeoID(
|
|
|
|
PWCHAR Id)
|
2009-02-05 13:50:49 +00:00
|
|
|
{
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
UNICODE_STRING KeyName;
|
|
|
|
UNICODE_STRING ValueName;
|
|
|
|
HANDLE KeyHandle;
|
|
|
|
WCHAR szKeyName[] = L"\\Registry\\User\\.DEFAULT\\Control Panel\\International\\Geo";
|
|
|
|
WCHAR szValueName[] = L"Nation";
|
|
|
|
NTSTATUS Status;
|
2014-05-12 16:14:19 +00:00
|
|
|
|
2009-02-05 13:50:49 +00:00
|
|
|
RtlInitUnicodeString(&KeyName,
|
|
|
|
szKeyName);
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&KeyName,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
Status = NtOpenKey(&KeyHandle,
|
2009-08-23 08:29:23 +00:00
|
|
|
KEY_SET_VALUE,
|
2014-05-12 16:14:19 +00:00
|
|
|
&ObjectAttributes);
|
2009-02-05 13:50:49 +00:00
|
|
|
if(!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2014-05-12 16:14:19 +00:00
|
|
|
|
2009-02-05 13:50:49 +00:00
|
|
|
RtlInitUnicodeString(&ValueName, szValueName);
|
|
|
|
Status = NtSetValueKey(KeyHandle,
|
2014-05-12 16:14:19 +00:00
|
|
|
&ValueName,
|
|
|
|
0,
|
|
|
|
REG_SZ,
|
|
|
|
(PVOID)Id,
|
|
|
|
(wcslen(Id) + 1) * sizeof(WCHAR));
|
2010-09-25 19:24:03 +00:00
|
|
|
NtClose(KeyHandle);
|
2009-02-05 13:50:49 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2014-05-12 16:14:19 +00:00
|
|
|
DPRINT1("NtSetValueKey() failed (Status = %lx)\n", Status);
|
|
|
|
return FALSE;
|
2009-02-05 13:50:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2004-05-30 14:54:02 +00:00
|
|
|
/* EOF */
|