diff --git a/src/common/platform/kernel_mapped.hpp b/src/common/platform/kernel_mapped.hpp index 221545fb..f0677a3f 100644 --- a/src/common/platform/kernel_mapped.hpp +++ b/src/common/platform/kernel_mapped.hpp @@ -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 StandardName; + SYSTEMTIME StandardDate; + LONG StandardBias; + ARRAY_CONTAINER DaylightName; + SYSTEMTIME DaylightDate; + LONG DaylightBias; +} SYSTEM_TIMEZONE_INFORMATION, *PSYSTEM_TIMEZONE_INFORMATION; + +typedef struct _SYSTEM_DYNAMIC_TIMEZONE_INFORMATION +{ + LONG Bias; + ARRAY_CONTAINER StandardName; + SYSTEMTIME StandardDate; + LONG StandardBias; + ARRAY_CONTAINER DaylightName; + SYSTEMTIME DaylightDate; + LONG DaylightBias; + ARRAY_CONTAINER TimeZoneKeyName; + BOOLEAN DynamicDaylightTimeDisabled; +} SYSTEM_DYNAMIC_TIMEZONE_INFORMATION, *PSYSTEM_DYNAMIC_TIMEZONE_INFORMATION; + typedef struct _PROCESS_BASIC_INFORMATION64 { NTSTATUS ExitStatus; diff --git a/src/windows-emulator/process_context.hpp b/src/windows-emulator/process_context.hpp index 7fe34f27..b6aa8e30 100644 --- a/src/windows-emulator/process_context.hpp +++ b/src/windows-emulator/process_context.hpp @@ -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 exception_rip{}; std::optional exit_status{}; diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index a03e525f..358128c3 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -118,11 +118,14 @@ namespace syscalls emulator_object /*default_casing_table_size*/); NTSTATUS handle_NtQueryDefaultLocale(const syscall_context&, BOOLEAN /*user_profile*/, emulator_object 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 section_pointer, + emulator_object section_size); NTSTATUS handle_NtGetMUIRegistryInfo(); NTSTATUS handle_NtIsUILanguageComitted(); NTSTATUS handle_NtUserGetKeyboardLayout(); - NTSTATUS handle_NtQueryInstallUILanguage(); + NTSTATUS handle_NtQueryDefaultUILanguage(const syscall_context&, emulator_object language_id); + NTSTATUS handle_NtQueryInstallUILanguage(const syscall_context&, emulator_object 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 /*server_shared_memory*/, emulator_object /*maximum_message_length*/, emulator_pointer connection_info, emulator_object connection_info_length); + NTSTATUS handle_NtSecureConnectPort(const syscall_context& c, emulator_object client_port_handle, + emulator_object>> server_port_name, + emulator_object security_qos, + emulator_object client_shared_memory, + emulator_object /*server_sid*/, + emulator_object server_shared_memory, + emulator_object maximum_message_length, emulator_pointer connection_info, + emulator_object connection_info_length); NTSTATUS handle_NtAlpcSendWaitReceivePort(const syscall_context& c, handle port_handle, ULONG /*flags*/, emulator_object /*send_message*/, emulator_object @@ -732,6 +743,7 @@ void syscall_dispatcher::add_handlers(std::map& 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& ha add_handler(NtOpenEvent); add_handler(NtGetMUIRegistryInfo); add_handler(NtIsUILanguageComitted); + add_handler(NtQueryDefaultUILanguage); add_handler(NtQueryInstallUILanguage); add_handler(NtUpdateWnfStateData); add_handler(NtRaiseException); diff --git a/src/windows-emulator/syscalls/locale.cpp b/src/windows-emulator/syscalls/locale.cpp index c1768148..cb4fac79 100644 --- a/src/windows-emulator/syscalls/locale.cpp +++ b/src/windows-emulator/syscalls/locale.cpp @@ -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 section_pointer, + emulator_object 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(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(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 language_id) { - return STATUS_NOT_SUPPORTED; + language_id.write(0x407); + return STATUS_SUCCESS; + } + + NTSTATUS handle_NtQueryInstallUILanguage(const syscall_context&, emulator_object language_id) + { + language_id.write(0x407); + return STATUS_SUCCESS; } } diff --git a/src/windows-emulator/syscalls/port.cpp b/src/windows-emulator/syscalls/port.cpp index bfade094..a2a765d2 100644 --- a/src/windows-emulator/syscalls/port.cpp +++ b/src/windows-emulator/syscalls/port.cpp @@ -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 client_port_handle, const emulator_object>> server_port_name, const emulator_object /*security_qos*/, @@ -21,9 +33,34 @@ namespace syscalls if (connection_info) { - std::vector 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 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 client_port_handle, + emulator_object>> server_port_name, + emulator_object security_qos, + emulator_object client_shared_memory, + emulator_object /*server_sid*/, + emulator_object server_shared_memory, + emulator_object maximum_message_length, emulator_pointer connection_info, + emulator_object 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 /*send_message*/, const emulator_object diff --git a/src/windows-emulator/syscalls/section.cpp b/src/windows-emulator/syscalls/section.cpp index bb0aa437..586de935 100644 --- a/src/windows-emulator/syscalls/section.cpp +++ b/src/windows-emulator/syscalls/section.cpp @@ -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; } diff --git a/src/windows-emulator/syscalls/system.cpp b/src/windows-emulator/syscalls/system.cpp index 2d443891..37ead1ef 100644 --- a/src/windows-emulator/syscalls/system.cpp +++ b/src/windows-emulator/syscalls/system.cpp @@ -115,10 +115,87 @@ namespace syscalls return handle_query(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( + 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( + 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(c.emu, system_information, system_information_length, return_length,