mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 07:22:58 +00:00
501 lines
11 KiB
C
501 lines
11 KiB
C
/* $Id: locale.c,v 1.13 2004/11/15 14:38:37 ekohl Exp $
|
|
*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS kernel
|
|
* FILE: ntoskrnl/ps/locale.c
|
|
* PURPOSE: Locale support
|
|
* PROGRAMMER: David Welch (welch@cwcom.net)
|
|
* UPDATE HISTORY:
|
|
* Created 22/05/98
|
|
*/
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
#include <ntoskrnl.h>
|
|
|
|
#define NDEBUG
|
|
#include <internal/debug.h>
|
|
|
|
|
|
/* GLOBALS *******************************************************************/
|
|
|
|
/*
|
|
* Default setting: LANG_NEUTRAL, SUBLANG_NEUTRAL, SORT_DEFAULT
|
|
*/
|
|
LCID PsDefaultThreadLocaleId = 0;
|
|
LCID PsDefaultSystemLocaleId = 0;
|
|
BOOL PsDefaultThreadLocaleInitialized = FALSE;
|
|
|
|
static LANGID PsInstallUILanguageId = 0;
|
|
|
|
#define VALUE_BUFFER_SIZE 256
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
/*
|
|
* FUNCTION:
|
|
* Initializes the default locale.
|
|
* Reads default locale from registry, if available
|
|
* ARGUMENTS:
|
|
* None.
|
|
* Returns:
|
|
* None.
|
|
*/
|
|
VOID INIT_FUNCTION
|
|
PiInitDefaultLocale(VOID)
|
|
{
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING KeyName;
|
|
UNICODE_STRING ValueName;
|
|
HANDLE KeyHandle;
|
|
ULONG ValueLength;
|
|
UCHAR ValueBuffer[VALUE_BUFFER_SIZE];
|
|
PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
|
|
UNICODE_STRING ValueString;
|
|
ULONG Value;
|
|
NTSTATUS Status;
|
|
|
|
ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer;
|
|
|
|
RtlRosInitUnicodeStringFromLiteral(&KeyName,
|
|
L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Nls\\Language");
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&KeyName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
Status = NtOpenKey(&KeyHandle,
|
|
KEY_QUERY_VALUE,
|
|
&ObjectAttributes);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
/* Read system locale */
|
|
RtlRosInitUnicodeStringFromLiteral(&ValueName,
|
|
L"Default");
|
|
Status = NtQueryValueKey(KeyHandle,
|
|
&ValueName,
|
|
KeyValuePartialInformation,
|
|
ValueBuffer,
|
|
VALUE_BUFFER_SIZE,
|
|
&ValueLength);
|
|
if ((NT_SUCCESS(Status)) && (ValueInfo->Type == REG_SZ))
|
|
{
|
|
ValueString.Length = ValueInfo->DataLength;
|
|
ValueString.MaximumLength = ValueInfo->DataLength;
|
|
ValueString.Buffer = (PWSTR)ValueInfo->Data;
|
|
|
|
Status = RtlUnicodeStringToInteger(&ValueString,
|
|
16,
|
|
&Value);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
DPRINT("System locale: %08lx\n", Value);
|
|
PsDefaultSystemLocaleId = (LCID)Value;
|
|
}
|
|
}
|
|
|
|
/* Read install language id */
|
|
RtlRosInitUnicodeStringFromLiteral(&ValueName,
|
|
L"InstallLanguage");
|
|
Status = NtQueryValueKey(KeyHandle,
|
|
&ValueName,
|
|
KeyValuePartialInformation,
|
|
ValueBuffer,
|
|
VALUE_BUFFER_SIZE,
|
|
&ValueLength);
|
|
if ((NT_SUCCESS(Status)) && (ValueInfo->Type == REG_SZ))
|
|
{
|
|
ValueString.Length = ValueInfo->DataLength;
|
|
ValueString.MaximumLength = ValueInfo->DataLength;
|
|
ValueString.Buffer = (PWSTR)ValueInfo->Data;
|
|
|
|
Status = RtlUnicodeStringToInteger(&ValueString,
|
|
16,
|
|
&Value);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
DPRINT("Install language id: %04lx\n", Value);
|
|
PsInstallUILanguageId = (LANGID)Value;
|
|
}
|
|
}
|
|
|
|
NtClose(KeyHandle);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* FUNCTION:
|
|
* Initializes the default thread locale.
|
|
* Reads default locale from registry, if available
|
|
* ARGUMENTS:
|
|
* None.
|
|
* Returns:
|
|
* None.
|
|
*/
|
|
VOID STDCALL
|
|
PiInitThreadLocale(VOID)
|
|
{
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING KeyName;
|
|
UNICODE_STRING ValueName;
|
|
HANDLE KeyHandle;
|
|
ULONG ValueLength;
|
|
UCHAR ValueBuffer[VALUE_BUFFER_SIZE];
|
|
PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
|
|
UNICODE_STRING ValueString;
|
|
ULONG LocaleValue;
|
|
NTSTATUS Status;
|
|
|
|
ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer;
|
|
|
|
/* read default thread locale */
|
|
RtlRosInitUnicodeStringFromLiteral(&KeyName,
|
|
L"\\Registry\\User\\.Default\\Control Panel\\International");
|
|
RtlRosInitUnicodeStringFromLiteral(&ValueName,
|
|
L"Locale");
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&KeyName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
Status = NtOpenKey(&KeyHandle,
|
|
KEY_QUERY_VALUE,
|
|
&ObjectAttributes);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
Status = NtQueryValueKey(KeyHandle,
|
|
&ValueName,
|
|
KeyValuePartialInformation,
|
|
ValueBuffer,
|
|
VALUE_BUFFER_SIZE,
|
|
&ValueLength);
|
|
if ((NT_SUCCESS(Status)) && (ValueInfo->Type == REG_SZ))
|
|
{
|
|
ValueString.Length = ValueInfo->DataLength;
|
|
ValueString.MaximumLength = ValueInfo->DataLength;
|
|
ValueString.Buffer = (PWSTR)ValueInfo->Data;
|
|
|
|
Status = RtlUnicodeStringToInteger(&ValueString,
|
|
16,
|
|
&LocaleValue);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
DPRINT("Thread locale: %08lu\n", LocaleValue);
|
|
PsDefaultThreadLocaleId = (LCID)LocaleValue;
|
|
}
|
|
}
|
|
NtClose(KeyHandle);
|
|
}
|
|
|
|
PsDefaultThreadLocaleInitialized = TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
* FUNCTION:
|
|
* Returns the default locale.
|
|
* ARGUMENTS:
|
|
* UserProfile = If TRUE then the locale for this thread is returned,
|
|
* otherwise the locale for the system is returned.
|
|
* DefaultLocaleId = Points to a variable that receives the locale id.
|
|
* Returns:
|
|
* Status.
|
|
*/
|
|
NTSTATUS STDCALL
|
|
NtQueryDefaultLocale(IN BOOLEAN UserProfile,
|
|
OUT PLCID DefaultLocaleId)
|
|
{
|
|
if (DefaultLocaleId == NULL)
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
if (UserProfile)
|
|
{
|
|
if (!PsDefaultThreadLocaleInitialized)
|
|
{
|
|
PiInitThreadLocale();
|
|
}
|
|
|
|
/* set thread locale */
|
|
*DefaultLocaleId = PsDefaultThreadLocaleId;
|
|
}
|
|
else
|
|
{
|
|
/* set system locale */
|
|
*DefaultLocaleId = PsDefaultSystemLocaleId;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
* FUNCTION:
|
|
* Sets the default locale.
|
|
* ARGUMENTS:
|
|
* ThreadOrSystem = If TRUE then the locale for this thread is set,
|
|
* otherwise the locale for the system is set.
|
|
* DefaultLocaleId = The locale id to be set.
|
|
* Returns:
|
|
* Status.
|
|
*/
|
|
NTSTATUS STDCALL
|
|
NtSetDefaultLocale(IN BOOLEAN UserProfile,
|
|
IN LCID DefaultLocaleId)
|
|
{
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING KeyName;
|
|
UNICODE_STRING ValueName;
|
|
HANDLE KeyHandle;
|
|
ULONG ValueLength;
|
|
WCHAR ValueBuffer[20];
|
|
HANDLE UserKey = NULL;
|
|
NTSTATUS Status;
|
|
|
|
if (UserProfile)
|
|
{
|
|
/* thread locale */
|
|
Status = RtlOpenCurrentUser(KEY_WRITE,
|
|
&UserKey);
|
|
if (!NT_SUCCESS(Status))
|
|
return(Status);
|
|
RtlRosInitUnicodeStringFromLiteral(&KeyName,
|
|
L"Control Panel\\International");
|
|
RtlRosInitUnicodeStringFromLiteral(&ValueName,
|
|
L"Locale");
|
|
}
|
|
else
|
|
{
|
|
/* system locale */
|
|
RtlRosInitUnicodeStringFromLiteral(&KeyName,
|
|
L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Nls\\Language");
|
|
RtlRosInitUnicodeStringFromLiteral(&ValueName,
|
|
L"Default");
|
|
}
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&KeyName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
UserKey,
|
|
NULL);
|
|
Status = NtOpenKey(&KeyHandle,
|
|
KEY_SET_VALUE,
|
|
&ObjectAttributes);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
if (UserKey != NULL)
|
|
{
|
|
NtClose(UserKey);
|
|
}
|
|
return(Status);
|
|
}
|
|
|
|
if (UserProfile)
|
|
{
|
|
ValueLength = swprintf(ValueBuffer,
|
|
L"%08lx",
|
|
(ULONG)DefaultLocaleId);
|
|
}
|
|
else
|
|
{
|
|
ValueLength = swprintf(ValueBuffer,
|
|
L"%04lx",
|
|
(ULONG)DefaultLocaleId & 0xFFFF);
|
|
}
|
|
ValueLength = (ValueLength + 1) * sizeof(WCHAR);
|
|
|
|
Status = NtSetValueKey(KeyHandle,
|
|
&ValueName,
|
|
0,
|
|
REG_SZ,
|
|
ValueBuffer,
|
|
ValueLength);
|
|
|
|
NtClose(KeyHandle);
|
|
if (UserKey != NULL)
|
|
{
|
|
NtClose(UserKey);
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return(Status);
|
|
}
|
|
|
|
if (UserProfile)
|
|
{
|
|
/* set thread locale */
|
|
DPRINT("Thread locale: %08lu\n", DefaultLocaleId);
|
|
PsDefaultThreadLocaleId = DefaultLocaleId;
|
|
PsDefaultThreadLocaleInitialized = TRUE;
|
|
}
|
|
else
|
|
{
|
|
/* set system locale */
|
|
DPRINT("System locale: %08lu\n", DefaultLocaleId);
|
|
PsDefaultSystemLocaleId = DefaultLocaleId;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
NTSTATUS STDCALL
|
|
NtQueryDefaultUILanguage(OUT PLANGID LanguageId)
|
|
{
|
|
UCHAR ValueBuffer[VALUE_BUFFER_SIZE];
|
|
PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING KeyName;
|
|
UNICODE_STRING ValueName;
|
|
UNICODE_STRING ValueString;
|
|
ULONG ValueLength;
|
|
ULONG Value;
|
|
HANDLE UserKey;
|
|
HANDLE KeyHandle;
|
|
NTSTATUS Status;
|
|
|
|
Status = RtlOpenCurrentUser(KEY_READ,
|
|
&UserKey);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
*LanguageId = PsInstallUILanguageId;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
RtlRosInitUnicodeStringFromLiteral(&KeyName,
|
|
L"Control Panel\\International");
|
|
RtlRosInitUnicodeStringFromLiteral(&ValueName,
|
|
L"MultiUILanguageId");
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&KeyName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
UserKey,
|
|
NULL);
|
|
Status = NtOpenKey(&KeyHandle,
|
|
KEY_QUERY_VALUE,
|
|
&ObjectAttributes);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
*LanguageId = PsInstallUILanguageId;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer;
|
|
|
|
Status = NtQueryValueKey(KeyHandle,
|
|
&ValueName,
|
|
KeyValuePartialInformation,
|
|
ValueBuffer,
|
|
VALUE_BUFFER_SIZE,
|
|
&ValueLength);
|
|
|
|
NtClose(KeyHandle);
|
|
NtClose(UserKey);
|
|
|
|
if (!NT_SUCCESS(Status) || ValueInfo->Type != REG_SZ)
|
|
{
|
|
*LanguageId = PsInstallUILanguageId;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
ValueString.Length = ValueInfo->DataLength;
|
|
ValueString.MaximumLength = ValueInfo->DataLength;
|
|
ValueString.Buffer = (PWSTR)ValueInfo->Data;
|
|
|
|
Status = RtlUnicodeStringToInteger(&ValueString,
|
|
16,
|
|
&Value);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
*LanguageId = PsInstallUILanguageId;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
DPRINT("Default language id: %04lx\n", Value);
|
|
|
|
*LanguageId = Value;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
NTSTATUS STDCALL
|
|
NtQueryInstallUILanguage(OUT PLANGID LanguageId)
|
|
{
|
|
*LanguageId = PsInstallUILanguageId;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
NTSTATUS STDCALL
|
|
NtSetDefaultUILanguage(IN LANGID LanguageId)
|
|
{
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING KeyName;
|
|
UNICODE_STRING ValueName;
|
|
WCHAR ValueBuffer[8];
|
|
ULONG ValueLength;
|
|
HANDLE UserHandle;
|
|
HANDLE KeyHandle;
|
|
NTSTATUS Status;
|
|
|
|
Status = RtlOpenCurrentUser(KEY_WRITE,
|
|
&UserHandle);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
RtlRosInitUnicodeStringFromLiteral(&KeyName,
|
|
L"Control Panel\\Desktop");
|
|
RtlRosInitUnicodeStringFromLiteral(&ValueName,
|
|
L"MultiUILanguageId");
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&KeyName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
UserHandle,
|
|
NULL);
|
|
|
|
Status = NtOpenKey(&KeyHandle,
|
|
KEY_SET_VALUE,
|
|
&ObjectAttributes);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
NtClose(UserHandle);
|
|
return Status;
|
|
}
|
|
|
|
ValueLength = swprintf(ValueBuffer,
|
|
L"%04lX",
|
|
(ULONG)LanguageId);
|
|
ValueLength = (ValueLength + 1) * sizeof(WCHAR);
|
|
|
|
Status = NtSetValueKey(KeyHandle,
|
|
&ValueName,
|
|
0,
|
|
REG_SZ,
|
|
ValueBuffer,
|
|
ValueLength);
|
|
|
|
NtClose(KeyHandle);
|
|
NtClose(UserHandle);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/* EOF */
|