mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-11 16:46:16 +00:00
Improvements to locale syscalls and fix TimeZone query
This commit is contained in:
@@ -862,6 +862,44 @@ typedef struct _SYSTEM_TIMEOFDAY_INFORMATION64
|
||||
ULONGLONG SleepTimeBias;
|
||||
} SYSTEM_TIMEOFDAY_INFORMATION64, *PSYSTEM_TIMEOFDAY_INFORMATION64;
|
||||
|
||||
#ifndef OS_WINDOWS
|
||||
typedef struct _SYSTEMTIME
|
||||
{
|
||||
WORD wYear;
|
||||
WORD wMonth;
|
||||
WORD wDayOfWeek;
|
||||
WORD wDay;
|
||||
WORD wHour;
|
||||
WORD wMinute;
|
||||
WORD wSecond;
|
||||
WORD wMilliseconds;
|
||||
} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME;
|
||||
#endif
|
||||
|
||||
typedef struct _SYSTEM_TIMEZONE_INFORMATION
|
||||
{
|
||||
LONG Bias;
|
||||
ARRAY_CONTAINER<char16_t, 32> StandardName;
|
||||
SYSTEMTIME StandardDate;
|
||||
LONG StandardBias;
|
||||
ARRAY_CONTAINER<char16_t, 32> DaylightName;
|
||||
SYSTEMTIME DaylightDate;
|
||||
LONG DaylightBias;
|
||||
} SYSTEM_TIMEZONE_INFORMATION, *PSYSTEM_TIMEZONE_INFORMATION;
|
||||
|
||||
typedef struct _SYSTEM_DYNAMIC_TIMEZONE_INFORMATION
|
||||
{
|
||||
LONG Bias;
|
||||
ARRAY_CONTAINER<char16_t, 32> StandardName;
|
||||
SYSTEMTIME StandardDate;
|
||||
LONG StandardBias;
|
||||
ARRAY_CONTAINER<char16_t, 32> DaylightName;
|
||||
SYSTEMTIME DaylightDate;
|
||||
LONG DaylightBias;
|
||||
ARRAY_CONTAINER<char16_t, 128> TimeZoneKeyName;
|
||||
BOOLEAN DynamicDaylightTimeDisabled;
|
||||
} SYSTEM_DYNAMIC_TIMEZONE_INFORMATION, *PSYSTEM_DYNAMIC_TIMEZONE_INFORMATION;
|
||||
|
||||
typedef struct _PROCESS_BASIC_INFORMATION64
|
||||
{
|
||||
NTSTATUS ExitStatus;
|
||||
|
||||
@@ -80,7 +80,10 @@ struct process_context
|
||||
uint64_t current_ip{0};
|
||||
uint64_t previous_ip{0};
|
||||
|
||||
uint64_t shared_section_address{0};
|
||||
uint64_t shared_section_size{0};
|
||||
uint64_t dbwin_buffer{0};
|
||||
uint64_t dbwin_buffer_size{0};
|
||||
|
||||
std::optional<uint64_t> exception_rip{};
|
||||
std::optional<NTSTATUS> exit_status{};
|
||||
|
||||
@@ -118,11 +118,14 @@ namespace syscalls
|
||||
emulator_object<LARGE_INTEGER> /*default_casing_table_size*/);
|
||||
NTSTATUS handle_NtQueryDefaultLocale(const syscall_context&, BOOLEAN /*user_profile*/,
|
||||
emulator_object<LCID> default_locale_id);
|
||||
NTSTATUS handle_NtGetNlsSectionPtr();
|
||||
NTSTATUS handle_NtGetNlsSectionPtr(const syscall_context& c, ULONG section_type, ULONG section_data,
|
||||
emulator_pointer /*context_data*/, emulator_object<uint64_t> section_pointer,
|
||||
emulator_object<ULONG> section_size);
|
||||
NTSTATUS handle_NtGetMUIRegistryInfo();
|
||||
NTSTATUS handle_NtIsUILanguageComitted();
|
||||
NTSTATUS handle_NtUserGetKeyboardLayout();
|
||||
NTSTATUS handle_NtQueryInstallUILanguage();
|
||||
NTSTATUS handle_NtQueryDefaultUILanguage(const syscall_context&, emulator_object<LANGID> language_id);
|
||||
NTSTATUS handle_NtQueryInstallUILanguage(const syscall_context&, emulator_object<LANGID> language_id);
|
||||
|
||||
// syscalls/memory.cpp:
|
||||
NTSTATUS handle_NtQueryVirtualMemory(const syscall_context& c, handle process_handle, uint64_t base_address,
|
||||
@@ -180,6 +183,14 @@ namespace syscalls
|
||||
emulator_object<REMOTE_PORT_VIEW64> /*server_shared_memory*/,
|
||||
emulator_object<ULONG> /*maximum_message_length*/, emulator_pointer connection_info,
|
||||
emulator_object<ULONG> connection_info_length);
|
||||
NTSTATUS handle_NtSecureConnectPort(const syscall_context& c, emulator_object<handle> client_port_handle,
|
||||
emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> server_port_name,
|
||||
emulator_object<SECURITY_QUALITY_OF_SERVICE> security_qos,
|
||||
emulator_object<PORT_VIEW64> client_shared_memory,
|
||||
emulator_object<SID> /*server_sid*/,
|
||||
emulator_object<REMOTE_PORT_VIEW64> server_shared_memory,
|
||||
emulator_object<ULONG> maximum_message_length, emulator_pointer connection_info,
|
||||
emulator_object<ULONG> connection_info_length);
|
||||
NTSTATUS handle_NtAlpcSendWaitReceivePort(const syscall_context& c, handle port_handle, ULONG /*flags*/,
|
||||
emulator_object<PORT_MESSAGE64> /*send_message*/,
|
||||
emulator_object<ALPC_MESSAGE_ATTRIBUTES>
|
||||
@@ -732,6 +743,7 @@ void syscall_dispatcher::add_handlers(std::map<std::string, syscall_handler>& ha
|
||||
add_handler(NtApphelpCacheControl);
|
||||
add_handler(NtCreateSection);
|
||||
add_handler(NtConnectPort);
|
||||
add_handler(NtSecureConnectPort);
|
||||
add_handler(NtCreateFile);
|
||||
add_handler(NtDeviceIoControlFile);
|
||||
add_handler(NtQueryWnfStateData);
|
||||
@@ -769,6 +781,7 @@ void syscall_dispatcher::add_handlers(std::map<std::string, syscall_handler>& ha
|
||||
add_handler(NtOpenEvent);
|
||||
add_handler(NtGetMUIRegistryInfo);
|
||||
add_handler(NtIsUILanguageComitted);
|
||||
add_handler(NtQueryDefaultUILanguage);
|
||||
add_handler(NtQueryInstallUILanguage);
|
||||
add_handler(NtUpdateWnfStateData);
|
||||
add_handler(NtRaiseException);
|
||||
|
||||
@@ -34,8 +34,32 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtGetNlsSectionPtr()
|
||||
NTSTATUS handle_NtGetNlsSectionPtr(const syscall_context& c, ULONG section_type, ULONG section_data,
|
||||
emulator_pointer /*context_data*/, emulator_object<uint64_t> section_pointer,
|
||||
emulator_object<ULONG> section_size)
|
||||
{
|
||||
if (section_type == 11)
|
||||
{
|
||||
c.win_emu.log.print(color::dark_gray, "--> Code Page: %d\n", section_data);
|
||||
|
||||
const auto file_path = std::format(R"(C:\Windows\System32\C_{}.NLS)", section_data);
|
||||
const auto locale_file = utils::io::read_file(c.win_emu.file_sys.translate(file_path));
|
||||
if (locale_file.empty())
|
||||
{
|
||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
const auto size = static_cast<size_t>(page_align_up(locale_file.size()));
|
||||
const auto section_memory = c.win_emu.memory.allocate_memory(size, memory_permission::read);
|
||||
c.emu.write_memory(section_memory, locale_file.data(), locale_file.size());
|
||||
|
||||
section_pointer.write_if_valid(section_memory);
|
||||
section_size.write_if_valid(static_cast<ULONG>(size));
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
c.win_emu.log.print(color::gray, "Unsupported section type: %X\n", section_type);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
@@ -54,8 +78,15 @@ namespace syscalls
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtQueryInstallUILanguage()
|
||||
NTSTATUS handle_NtQueryDefaultUILanguage(const syscall_context&, emulator_object<LANGID> language_id)
|
||||
{
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
language_id.write(0x407);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtQueryInstallUILanguage(const syscall_context&, emulator_object<LANGID> language_id)
|
||||
{
|
||||
language_id.write(0x407);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,18 @@
|
||||
|
||||
namespace syscalls
|
||||
{
|
||||
struct CSR_API_CONNECTINFO
|
||||
{
|
||||
uint64_t SharedSectionBase;
|
||||
uint64_t SharedStaticServerData;
|
||||
uint64_t SharedSectionHeap;
|
||||
ULONG DebugFlags;
|
||||
ULONG SizeOfPebData;
|
||||
ULONG SizeOfTebData;
|
||||
ULONG NumberOfServerDllNames;
|
||||
EMULATOR_CAST(uint64_t, HANDLE) ServerProcessId;
|
||||
};
|
||||
|
||||
NTSTATUS handle_NtConnectPort(const syscall_context& c, const emulator_object<handle> client_port_handle,
|
||||
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> server_port_name,
|
||||
const emulator_object<SECURITY_QUALITY_OF_SERVICE> /*security_qos*/,
|
||||
@@ -21,9 +33,34 @@ namespace syscalls
|
||||
|
||||
if (connection_info)
|
||||
{
|
||||
std::vector<uint8_t> zero_mem{};
|
||||
zero_mem.resize(connection_info_length.read(), 0);
|
||||
c.emu.write_memory(connection_info, zero_mem.data(), zero_mem.size());
|
||||
if (p.name == u"\\Windows\\ApiPort")
|
||||
{
|
||||
CSR_API_CONNECTINFO connect_info{};
|
||||
|
||||
const auto expected_connect_length = connection_info_length.read();
|
||||
if (expected_connect_length < sizeof(CSR_API_CONNECTINFO))
|
||||
{
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
// TODO: Use client_shared_memory to get the section entry and get the address from it?
|
||||
connect_info.SharedSectionBase = c.proc.shared_section_address;
|
||||
c.emu.write_memory(c.proc.shared_section_address + 2504,
|
||||
0xFFFFFFFF); // BaseStaticServerData->TermsrvClientTimeZoneId
|
||||
|
||||
const auto static_server_data =
|
||||
c.win_emu.memory.allocate_memory(0x10000, memory_permission::read_write);
|
||||
connect_info.SharedStaticServerData = static_server_data;
|
||||
c.emu.write_memory(static_server_data + 8, connect_info.SharedSectionBase);
|
||||
|
||||
c.emu.write_memory(connection_info, &connect_info, sizeof(connect_info));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<uint8_t> zero_mem{};
|
||||
zero_mem.resize(connection_info_length.read(), 0);
|
||||
c.emu.write_memory(connection_info, zero_mem.data(), zero_mem.size());
|
||||
}
|
||||
}
|
||||
|
||||
client_shared_memory.access([&](PORT_VIEW64& view) {
|
||||
@@ -39,6 +76,20 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtSecureConnectPort(const syscall_context& c, emulator_object<handle> client_port_handle,
|
||||
emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> server_port_name,
|
||||
emulator_object<SECURITY_QUALITY_OF_SERVICE> security_qos,
|
||||
emulator_object<PORT_VIEW64> client_shared_memory,
|
||||
emulator_object<SID> /*server_sid*/,
|
||||
emulator_object<REMOTE_PORT_VIEW64> server_shared_memory,
|
||||
emulator_object<ULONG> maximum_message_length, emulator_pointer connection_info,
|
||||
emulator_object<ULONG> connection_info_length)
|
||||
{
|
||||
return handle_NtConnectPort(c, client_port_handle, server_port_name, security_qos, client_shared_memory,
|
||||
server_shared_memory, maximum_message_length, connection_info,
|
||||
connection_info_length);
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtAlpcSendWaitReceivePort(const syscall_context& c, const handle port_handle, const ULONG /*flags*/,
|
||||
const emulator_object<PORT_MESSAGE64> /*send_message*/,
|
||||
const emulator_object<ALPC_MESSAGE_ATTRIBUTES>
|
||||
|
||||
@@ -64,12 +64,26 @@ namespace syscalls
|
||||
|
||||
if (filename == u"\\Windows\\SharedSection")
|
||||
{
|
||||
constexpr auto shared_section_size = 0x10000;
|
||||
|
||||
const auto address = c.win_emu.memory.find_free_allocation_base(shared_section_size);
|
||||
c.win_emu.memory.allocate_memory(address, shared_section_size, memory_permission::read_write);
|
||||
c.proc.shared_section_address = address;
|
||||
c.proc.shared_section_size = shared_section_size;
|
||||
|
||||
section_handle.write(SHARED_SECTION);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (filename == u"DBWIN_BUFFER")
|
||||
{
|
||||
constexpr auto dbwin_buffer_section_size = 0x1000;
|
||||
|
||||
const auto address = c.win_emu.memory.find_free_allocation_base(dbwin_buffer_section_size);
|
||||
c.win_emu.memory.allocate_memory(address, dbwin_buffer_section_size, memory_permission::read_write);
|
||||
c.proc.dbwin_buffer = address;
|
||||
c.proc.dbwin_buffer_size = dbwin_buffer_section_size;
|
||||
|
||||
section_handle.write(DBWIN_BUFFER);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
@@ -120,10 +134,8 @@ namespace syscalls
|
||||
|
||||
if (section_handle == SHARED_SECTION)
|
||||
{
|
||||
constexpr auto shared_section_size = 0x10000;
|
||||
|
||||
const auto address = c.win_emu.memory.find_free_allocation_base(shared_section_size);
|
||||
c.win_emu.memory.allocate_memory(address, shared_section_size, memory_permission::read_write);
|
||||
const auto shared_section_size = c.proc.shared_section_size;
|
||||
const auto address = c.proc.shared_section_address;
|
||||
|
||||
const std::u16string_view windows_dir = c.proc.kusd.get().NtSystemRoot.arr;
|
||||
const auto windows_dir_size = windows_dir.size() * 2;
|
||||
@@ -168,11 +180,8 @@ namespace syscalls
|
||||
|
||||
if (section_handle == DBWIN_BUFFER)
|
||||
{
|
||||
constexpr auto dbwin_buffer_section_size = 0x1000;
|
||||
|
||||
const auto address = c.win_emu.memory.find_free_allocation_base(dbwin_buffer_section_size);
|
||||
c.win_emu.memory.allocate_memory(address, dbwin_buffer_section_size, memory_permission::read_write);
|
||||
c.proc.dbwin_buffer = address;
|
||||
const auto dbwin_buffer_section_size = c.proc.dbwin_buffer_size;
|
||||
const auto address = c.proc.dbwin_buffer;
|
||||
|
||||
if (view_size)
|
||||
{
|
||||
@@ -255,10 +264,17 @@ namespace syscalls
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (base_address == c.proc.shared_section_address)
|
||||
{
|
||||
c.proc.shared_section_address = 0;
|
||||
c.win_emu.memory.release_memory(base_address, c.proc.shared_section_size);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (base_address == c.proc.dbwin_buffer)
|
||||
{
|
||||
c.proc.dbwin_buffer = 0;
|
||||
c.win_emu.memory.release_memory(base_address, 0x1000);
|
||||
c.win_emu.memory.release_memory(base_address, c.proc.dbwin_buffer_size);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -115,10 +115,87 @@ namespace syscalls
|
||||
return handle_query<SYSTEM_TIMEOFDAY_INFORMATION64>(c.emu, system_information, system_information_length,
|
||||
return_length,
|
||||
[&](SYSTEM_TIMEOFDAY_INFORMATION64& info) {
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.BootTime.QuadPart = 0;
|
||||
info.TimeZoneId = 0x00000002;
|
||||
// TODO: Fill
|
||||
});
|
||||
|
||||
case SystemTimeZoneInformation:
|
||||
case SystemCurrentTimeZoneInformation:
|
||||
return handle_query<SYSTEM_TIMEZONE_INFORMATION>(
|
||||
c.emu, system_information, system_information_length, return_length, [&](SYSTEM_TIMEZONE_INFORMATION& tzi) {
|
||||
memset(&tzi, 0, sizeof(tzi));
|
||||
|
||||
tzi.Bias = -60;
|
||||
tzi.StandardBias = 0;
|
||||
tzi.DaylightBias = -60;
|
||||
|
||||
constexpr std::u16string_view std_name{u"W. Europe Standard Time"};
|
||||
memcpy(&tzi.StandardName.arr[0], std_name.data(), std_name.size() * sizeof(char16_t));
|
||||
|
||||
constexpr std::u16string_view dlt_name{u"W. Europe Daylight Time"};
|
||||
memcpy(&tzi.DaylightName.arr[0], dlt_name.data(), dlt_name.size() * sizeof(char16_t));
|
||||
|
||||
// Standard Time: Last Sunday in October, 03:00
|
||||
tzi.StandardDate.wMonth = 10;
|
||||
tzi.StandardDate.wDayOfWeek = 0;
|
||||
tzi.StandardDate.wDay = 5;
|
||||
tzi.StandardDate.wHour = 3;
|
||||
tzi.StandardDate.wMinute = 0;
|
||||
tzi.StandardDate.wSecond = 0;
|
||||
tzi.StandardDate.wMilliseconds = 0;
|
||||
|
||||
// Daylight Time: Last Sunday in March, 02:00
|
||||
tzi.DaylightDate.wMonth = 3;
|
||||
tzi.DaylightDate.wDayOfWeek = 0;
|
||||
tzi.DaylightDate.wDay = 5;
|
||||
tzi.DaylightDate.wHour = 2;
|
||||
tzi.DaylightDate.wMinute = 0;
|
||||
tzi.DaylightDate.wSecond = 0;
|
||||
tzi.DaylightDate.wMilliseconds = 0;
|
||||
});
|
||||
|
||||
case SystemDynamicTimeZoneInformation:
|
||||
return handle_query<SYSTEM_DYNAMIC_TIMEZONE_INFORMATION>(
|
||||
c.emu, system_information, system_information_length, return_length,
|
||||
[&](SYSTEM_DYNAMIC_TIMEZONE_INFORMATION& dtzi) {
|
||||
memset(&dtzi, 0, sizeof(dtzi));
|
||||
|
||||
dtzi.Bias = -60;
|
||||
dtzi.StandardBias = 0;
|
||||
dtzi.DaylightBias = -60;
|
||||
|
||||
constexpr std::u16string_view std_name{u"W. Europe Standard Time"};
|
||||
memcpy(&dtzi.StandardName.arr[0], std_name.data(), std_name.size() * sizeof(char16_t));
|
||||
|
||||
constexpr std::u16string_view dlt_name{u"W. Europe Daylight Time"};
|
||||
memcpy(&dtzi.DaylightName.arr[0], dlt_name.data(), dlt_name.size() * sizeof(char16_t));
|
||||
|
||||
constexpr std::u16string_view key_name{u"W. Europe Standard Time"};
|
||||
memcpy(&dtzi.TimeZoneKeyName.arr[0], key_name.data(), key_name.size() * sizeof(char16_t));
|
||||
|
||||
// Standard Time: Last Sunday in October, 03:00
|
||||
dtzi.StandardDate.wMonth = 10;
|
||||
dtzi.StandardDate.wDayOfWeek = 0;
|
||||
dtzi.StandardDate.wDay = 5;
|
||||
dtzi.StandardDate.wHour = 3;
|
||||
dtzi.StandardDate.wMinute = 0;
|
||||
dtzi.StandardDate.wSecond = 0;
|
||||
dtzi.StandardDate.wMilliseconds = 0;
|
||||
|
||||
// Daylight Time: Last Sunday in March, 02:00
|
||||
dtzi.DaylightDate.wMonth = 3;
|
||||
dtzi.DaylightDate.wDayOfWeek = 0;
|
||||
dtzi.DaylightDate.wDay = 5;
|
||||
dtzi.DaylightDate.wHour = 2;
|
||||
dtzi.DaylightDate.wMinute = 0;
|
||||
dtzi.DaylightDate.wSecond = 0;
|
||||
dtzi.DaylightDate.wMilliseconds = 0;
|
||||
|
||||
dtzi.DynamicDaylightTimeDisabled = FALSE;
|
||||
});
|
||||
|
||||
case SystemRangeStartInformation:
|
||||
return handle_query<SYSTEM_RANGE_START_INFORMATION64>(c.emu, system_information, system_information_length,
|
||||
return_length,
|
||||
|
||||
Reference in New Issue
Block a user