mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-18 03:13:55 +00:00
Merge remote-tracking branch 'origin/main' into wow64
This commit is contained in:
@@ -319,6 +319,14 @@ typedef struct _FILE_FS_DEVICE_INFORMATION
|
||||
ULONG Characteristics;
|
||||
} FILE_FS_DEVICE_INFORMATION, *PFILE_FS_DEVICE_INFORMATION;
|
||||
|
||||
typedef struct _FILE_FS_ATTRIBUTE_INFORMATION
|
||||
{
|
||||
ULONG FileSystemAttributes;
|
||||
LONG MaximumComponentNameLength;
|
||||
ULONG FileSystemNameLength;
|
||||
char16_t FileSystemName[10];
|
||||
} FILE_FS_ATTRIBUTE_INFORMATION, *PFILE_FS_ATTRIBUTE_INFORMATION;
|
||||
|
||||
typedef struct _FILE_POSITION_INFORMATION
|
||||
{
|
||||
LARGE_INTEGER CurrentByteOffset;
|
||||
@@ -330,6 +338,24 @@ typedef struct _FILE_ATTRIBUTE_TAG_INFORMATION
|
||||
ULONG ReparseTag;
|
||||
} FILE_ATTRIBUTE_TAG_INFORMATION, *PFILE_ATTRIBUTE_TAG_INFORMATION;
|
||||
|
||||
typedef struct _FILE_IS_REMOTE_DEVICE_INFORMATION
|
||||
{
|
||||
BOOLEAN IsRemote;
|
||||
} FILE_IS_REMOTE_DEVICE_INFORMATION, *PFILE_IS_REMOTE_DEVICE_INFORMATION;
|
||||
|
||||
#ifndef OS_WINDOWS
|
||||
typedef struct _FILE_ID_128
|
||||
{
|
||||
BYTE Identifier[16];
|
||||
} FILE_ID_128, *PFILE_ID_128;
|
||||
#endif
|
||||
|
||||
typedef struct _FILE_ID_INFORMATION
|
||||
{
|
||||
ULONGLONG VolumeSerialNumber;
|
||||
FILE_ID_128 FileId;
|
||||
} FILE_ID_INFORMATION, *PFILE_ID_INFORMATION;
|
||||
|
||||
typedef struct _FILE_STANDARD_INFORMATION
|
||||
{
|
||||
LARGE_INTEGER AllocationSize;
|
||||
@@ -423,11 +449,6 @@ typedef struct _FILE_RENAME_INFORMATION
|
||||
} FILE_RENAME_INFORMATION, *PFILE_RENAME_INFORMATION;
|
||||
|
||||
#ifndef OS_WINDOWS
|
||||
typedef struct _FILE_ID_128
|
||||
{
|
||||
BYTE Identifier[16];
|
||||
} FILE_ID_128, *PFILE_ID_128;
|
||||
|
||||
typedef BOOLEAN SECURITY_CONTEXT_TRACKING_MODE, *PSECURITY_CONTEXT_TRACKING_MODE;
|
||||
typedef struct _SECURITY_QUALITY_OF_SERVICE
|
||||
{
|
||||
|
||||
@@ -52,4 +52,63 @@ struct EMU_DISPLAY_DEVICEW
|
||||
char16_t DeviceKey[128];
|
||||
};
|
||||
|
||||
#ifndef ENUM_CURRENT_SETTINGS
|
||||
#define ENUM_CURRENT_SETTINGS ((DWORD) - 1)
|
||||
#endif
|
||||
|
||||
struct EMU_DEVMODEW
|
||||
{
|
||||
char16_t dmDeviceName[32];
|
||||
WORD dmSpecVersion;
|
||||
WORD dmDriverVersion;
|
||||
WORD dmSize;
|
||||
WORD dmDriverExtra;
|
||||
DWORD dmFields;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
int16_t dmOrientation;
|
||||
int16_t dmPaperSize;
|
||||
int16_t dmPaperLength;
|
||||
int16_t dmPaperWidth;
|
||||
int16_t dmScale;
|
||||
int16_t dmCopies;
|
||||
int16_t dmDefaultSource;
|
||||
int16_t dmPrintQuality;
|
||||
} s;
|
||||
POINT dmPosition;
|
||||
struct
|
||||
{
|
||||
POINT dmPosition;
|
||||
DWORD dmDisplayOrientation;
|
||||
DWORD dmDisplayFixedOutput;
|
||||
} s2;
|
||||
} u;
|
||||
int16_t dmColor;
|
||||
int16_t dmDuplex;
|
||||
int16_t dmYResolution;
|
||||
int16_t dmTTOption;
|
||||
int16_t dmCollate;
|
||||
char16_t dmFormName[32];
|
||||
WORD dmLogPixels;
|
||||
DWORD dmBitsPerPel;
|
||||
DWORD dmPelsWidth;
|
||||
DWORD dmPelsHeight;
|
||||
union
|
||||
{
|
||||
DWORD dmDisplayFlags;
|
||||
DWORD dmNup;
|
||||
} u2;
|
||||
DWORD dmDisplayFrequency;
|
||||
DWORD dmICMMethod;
|
||||
DWORD dmICMIntent;
|
||||
DWORD dmMediaType;
|
||||
DWORD dmDitherType;
|
||||
DWORD dmReserved1;
|
||||
DWORD dmReserved2;
|
||||
DWORD dmPanningWidth;
|
||||
DWORD dmPanningHeight;
|
||||
};
|
||||
|
||||
// NOLINTEND(modernize-use-using,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||
|
||||
@@ -19,26 +19,18 @@ namespace utils::string
|
||||
template <typename T, size_t Size>
|
||||
requires(std::is_trivially_copyable_v<T>)
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||
void copy(T (&array)[Size], const std::basic_string_view<T> str)
|
||||
void copy(T (&array)[Size], const T* str)
|
||||
{
|
||||
if constexpr (Size == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto size = std::min(Size, str.size());
|
||||
memcpy(array, str.data(), size * sizeof(T));
|
||||
const auto size = std::min(Size, std::char_traits<T>::length(str));
|
||||
memcpy(array, str, size * sizeof(T));
|
||||
array[std::min(Size - 1, size)] = {};
|
||||
}
|
||||
|
||||
template <typename T, size_t Size>
|
||||
requires(std::is_trivially_copyable_v<T>)
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||
void copy(T (&array)[Size], const T* str)
|
||||
{
|
||||
copy<T, Size>(array, std::basic_string_view<T>(str));
|
||||
}
|
||||
|
||||
inline char char_to_lower(const char val)
|
||||
{
|
||||
return static_cast<char>(std::tolower(static_cast<unsigned char>(val)));
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace
|
||||
{
|
||||
// RNG Microsoft Primitive Provider
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||
std::uint8_t output_data[216] = //
|
||||
std::uint8_t rng_output_data[216] = //
|
||||
{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
@@ -22,6 +22,21 @@ namespace
|
||||
0x70, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6D, 0x00, 0x69, 0x00, 0x74, 0x00, 0x69, 0x00, 0x76, 0x00, 0x65, 0x00, 0x73, 0x00,
|
||||
0x2E, 0x00, 0x64, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
// SHA256 Microsoft Primitive Provider
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||
std::uint8_t sha256_output_data[224] = //
|
||||
{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x32, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x53, 0x00, 0x48, 0x00,
|
||||
0x41, 0x00, 0x32, 0x00, 0x35, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6F,
|
||||
0x00, 0x73, 0x00, 0x6F, 0x00, 0x66, 0x00, 0x74, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6D, 0x00, 0x69, 0x00,
|
||||
0x74, 0x00, 0x69, 0x00, 0x76, 0x00, 0x65, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6F, 0x00, 0x76, 0x00, 0x69, 0x00, 0x64,
|
||||
0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x63, 0x00, 0x72, 0x00, 0x79, 0x00, 0x70, 0x00, 0x74, 0x00, 0x70,
|
||||
0x00, 0x72, 0x00, 0x69, 0x00, 0x6D, 0x00, 0x69, 0x00, 0x74, 0x00, 0x69, 0x00, 0x76, 0x00, 0x65, 0x00, 0x73, 0x00, 0x2E, 0x00,
|
||||
0x64, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
NTSTATUS io_control(windows_emulator& win_emu, const io_device_context& c) override
|
||||
{
|
||||
if (c.io_control_code != 0x390400)
|
||||
@@ -33,13 +48,32 @@ namespace
|
||||
|
||||
if (operation == 2)
|
||||
{
|
||||
win_emu.emu().write_memory(c.output_buffer, output_data);
|
||||
std::array<char16_t, 8> alg_name_buffer{};
|
||||
win_emu.emu().read_memory(c.input_buffer + 0x30, alg_name_buffer.data(), sizeof(alg_name_buffer));
|
||||
|
||||
if (c.io_status_block)
|
||||
const std::u16string algorithm_name(alg_name_buffer.data());
|
||||
|
||||
if (algorithm_name == u"SHA256")
|
||||
{
|
||||
IO_STATUS_BLOCK<EmulatorTraits<Emu64>> block{};
|
||||
block.Information = sizeof(output_data);
|
||||
c.io_status_block.write(block);
|
||||
win_emu.emu().write_memory(c.output_buffer, sha256_output_data);
|
||||
|
||||
if (c.io_status_block)
|
||||
{
|
||||
IO_STATUS_BLOCK<EmulatorTraits<Emu64>> block{};
|
||||
block.Information = sizeof(sha256_output_data);
|
||||
c.io_status_block.write(block);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
win_emu.emu().write_memory(c.output_buffer, rng_output_data);
|
||||
|
||||
if (c.io_status_block)
|
||||
{
|
||||
IO_STATUS_BLOCK<EmulatorTraits<Emu64>> block{};
|
||||
block.Information = sizeof(rng_output_data);
|
||||
c.io_status_block.write(block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -207,7 +207,10 @@ emulator_thread::emulator_thread(memory_manager& memory, const process_context&
|
||||
teb_obj.NtTib.StackBase = wow64_cpureserved_base;
|
||||
teb_obj.NtTib.Self = this->teb64->value();
|
||||
teb_obj.CurrentLocale = 0x409;
|
||||
|
||||
teb_obj.ProcessEnvironmentBlock = context.peb64.value();
|
||||
teb_obj.StaticUnicodeString.MaximumLength = sizeof(teb_obj.StaticUnicodeBuffer);
|
||||
teb_obj.StaticUnicodeString.Buffer = this->teb64->value() + offsetof(TEB64, StaticUnicodeBuffer);
|
||||
|
||||
// Set WowTebOffset to point to 32-bit TEB offset
|
||||
teb_obj.WowTebOffset = static_cast<int32_t>(wow_teb_offset); // 0x2000
|
||||
|
||||
@@ -490,7 +490,7 @@ uint64_t memory_manager::find_free_allocation_base(const size_t size, const uint
|
||||
|
||||
// Since reserved_regions_ is a sorted map, we can iterate through it
|
||||
// and find gaps between regions
|
||||
while (start_address + size <= MAX_ALLOCATION_ADDRESS)
|
||||
while (start_address + size <= MAX_ALLOCATION_END_EXCL)
|
||||
{
|
||||
bool conflict = false;
|
||||
|
||||
@@ -530,7 +530,7 @@ region_info memory_manager::get_region_info(const uint64_t address)
|
||||
{
|
||||
region_info result{};
|
||||
result.start = MIN_ALLOCATION_ADDRESS;
|
||||
result.length = static_cast<size_t>(MAX_ALLOCATION_ADDRESS - result.start);
|
||||
result.length = static_cast<size_t>(MAX_ALLOCATION_END_EXCL - result.start);
|
||||
result.permissions = nt_memory_permission();
|
||||
result.initial_permissions = nt_memory_permission();
|
||||
result.allocation_base = {};
|
||||
@@ -555,7 +555,7 @@ region_info memory_manager::get_region_info(const uint64_t address)
|
||||
if (lower_end <= address)
|
||||
{
|
||||
result.start = lower_end;
|
||||
result.length = static_cast<size_t>(MAX_ALLOCATION_ADDRESS - result.start);
|
||||
result.length = static_cast<size_t>(MAX_ALLOCATION_END_EXCL - result.start);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
constexpr auto ALLOCATION_GRANULARITY = 0x0000000000010000ULL;
|
||||
constexpr auto MIN_ALLOCATION_ADDRESS = 0x0000000000010000ULL;
|
||||
constexpr auto MAX_ALLOCATION_ADDRESS = 0x00007ffffffeffffULL;
|
||||
constexpr auto MAX_ALLOCATION_END_EXCL = MAX_ALLOCATION_ADDRESS + 1ULL;
|
||||
constexpr auto DEFAULT_ALLOCATION_ADDRESS_64BIT = 0x100000000ULL;
|
||||
constexpr auto DEFAULT_ALLOCATION_ADDRESS_32BIT = 0x10000ULL;
|
||||
|
||||
|
||||
@@ -51,8 +51,10 @@ inline std::optional<nt_memory_permission> try_map_nt_to_emulator_protection(uin
|
||||
case PAGE_EXECUTE_READWRITE:
|
||||
common = memory_permission::all;
|
||||
break;
|
||||
case 0:
|
||||
case PAGE_EXECUTE_WRITECOPY:
|
||||
common = memory_permission::all;
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ struct mapped_module
|
||||
|
||||
bool contains(const uint64_t address) const
|
||||
{
|
||||
return address >= this->image_base && address < (this->image_base + this->size_of_image);
|
||||
return (address - this->image_base) < this->size_of_image;
|
||||
}
|
||||
|
||||
uint64_t find_export(const std::string_view export_name) const
|
||||
|
||||
@@ -211,6 +211,7 @@ mapped_module* module_manager::map_module_core(const pe_detection_result& detect
|
||||
|
||||
const auto image_base = mod.image_base;
|
||||
const auto entry = this->modules_.try_emplace(image_base, std::move(mod));
|
||||
this->last_module_cache_ = this->modules_.end();
|
||||
|
||||
// TODO: Patch shell32.dll entry point to prevent TLS storage issues
|
||||
// The shell32.dll module in SysWOW64 has TLS storage that fails, causing crashes
|
||||
@@ -409,6 +410,7 @@ void module_manager::install_wow64_heaven_gate(const logger& logger)
|
||||
module.sections.emplace_back(std::move(section));
|
||||
|
||||
this->modules_.emplace(module.image_base, std::move(module));
|
||||
this->last_module_cache_ = this->modules_.end();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -521,6 +523,7 @@ void module_manager::serialize(utils::buffer_serializer& buffer) const
|
||||
void module_manager::deserialize(utils::buffer_deserializer& buffer)
|
||||
{
|
||||
buffer.read_map(this->modules_);
|
||||
this->last_module_cache_ = this->modules_.end();
|
||||
|
||||
const auto executable_base = buffer.read<uint64_t>();
|
||||
const auto ntdll_base = buffer.read<uint64_t>();
|
||||
@@ -559,6 +562,7 @@ bool module_manager::unmap(const uint64_t address)
|
||||
this->callbacks_->on_module_unload(mod->second);
|
||||
unmap_module(*this->memory_, mod->second);
|
||||
this->modules_.erase(mod);
|
||||
this->last_module_cache_ = this->modules_.end();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -173,6 +173,7 @@ class module_manager
|
||||
callbacks* callbacks_{};
|
||||
|
||||
module_map modules_{};
|
||||
mutable module_map::iterator last_module_cache_{modules_.end()};
|
||||
|
||||
// Strategy pattern components
|
||||
mapping_strategy_factory strategy_factory_;
|
||||
@@ -198,6 +199,11 @@ class module_manager
|
||||
|
||||
module_map::iterator get_module(const uint64_t address)
|
||||
{
|
||||
if (last_module_cache_ != this->modules_.end() && last_module_cache_->second.contains(address))
|
||||
{
|
||||
return last_module_cache_;
|
||||
}
|
||||
|
||||
if (this->modules_.empty())
|
||||
{
|
||||
return this->modules_.end();
|
||||
@@ -213,6 +219,7 @@ class module_manager
|
||||
|
||||
if (upper_bound->second.contains(address))
|
||||
{
|
||||
last_module_cache_ = upper_bound;
|
||||
return upper_bound;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ inline bool is_syscall(const std::string_view name)
|
||||
|
||||
inline bool is_named_pipe_path(const std::u16string_view& filename)
|
||||
{
|
||||
return filename == u"\\Device\\NamedPipe\\" || filename.starts_with(u"\\Device\\NamedPipe\\");
|
||||
return filename == u"\\Device\\NamedPipe\\" || filename.starts_with(u"\\Device\\NamedPipe\\") || filename.starts_with(u"\\??\\pipe\\");
|
||||
}
|
||||
|
||||
inline std::optional<uint32_t> extract_syscall_id(const exported_symbol& symbol, std::span<const std::byte> data)
|
||||
|
||||
@@ -155,6 +155,7 @@ namespace syscalls
|
||||
NTSTATUS handle_NtSetInformationObject();
|
||||
NTSTATUS handle_NtQuerySecurityObject(const syscall_context& c, handle /*h*/, SECURITY_INFORMATION /*security_information*/,
|
||||
emulator_pointer security_descriptor, ULONG length, emulator_object<ULONG> length_needed);
|
||||
NTSTATUS handle_NtSetSecurityObject();
|
||||
|
||||
// syscalls/port.cpp:
|
||||
NTSTATUS handle_NtConnectPort(const syscall_context& c, emulator_object<handle> client_port_handle,
|
||||
@@ -920,32 +921,78 @@ namespace syscalls
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtUserEnumDisplayDevices(const syscall_context& /*c*/,
|
||||
NTSTATUS handle_NtUserEnumDisplayDevices(const syscall_context& c,
|
||||
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> str_device, const DWORD dev_num,
|
||||
const emulator_object<EMU_DISPLAY_DEVICEW> display_device, const DWORD /*flags*/)
|
||||
{
|
||||
if (str_device && dev_num != 0)
|
||||
if (!str_device)
|
||||
{
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
if (dev_num > 0)
|
||||
{
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
if (dev_num > 0)
|
||||
display_device.access([&](EMU_DISPLAY_DEVICEW& dev) {
|
||||
dev.StateFlags = 0x5; // DISPLAY_DEVICE_PRIMARY_DEVICE | DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
|
||||
utils::string::copy(dev.DeviceName, u"\\\\.\\DISPLAY1");
|
||||
utils::string::copy(dev.DeviceString, u"Emulated Virtual Adapter");
|
||||
utils::string::copy(dev.DeviceID, u"PCI\\VEN_10DE&DEV_0000&SUBSYS_00000000&REV_A1");
|
||||
utils::string::copy(dev.DeviceKey, u"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Video\\{00000001-"
|
||||
u"0002-0003-0004-000000000005}\\0000");
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
const auto dev_name = read_unicode_string(c.emu, str_device);
|
||||
|
||||
display_device.access([&](EMU_DISPLAY_DEVICEW& dev) {
|
||||
dev.StateFlags = 0;
|
||||
utils::string::copy(dev.DeviceName, u"\\\\.\\DISPLAY1");
|
||||
utils::string::copy(dev.DeviceID, u"PCI\\VEN_10DE&DEV_0000&SUBSYS_00000000&REV_A1");
|
||||
utils::string::copy(dev.DeviceString, u"Emulator Display");
|
||||
utils::string::copy(dev.DeviceKey, u"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Video\\{00000001-"
|
||||
u"0002-0003-0004-000000000005}\\0001");
|
||||
});
|
||||
if (dev_name != u"\\\\.\\DISPLAY1")
|
||||
{
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
if (dev_num > 0)
|
||||
{
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
display_device.access([&](EMU_DISPLAY_DEVICEW& dev) {
|
||||
dev.StateFlags = 0x1; // DISPLAY_DEVICE_ACTIVE
|
||||
utils::string::copy(dev.DeviceName, u"\\\\.\\DISPLAY1\\Monitor0");
|
||||
utils::string::copy(dev.DeviceString, u"Generic PnP Monitor");
|
||||
utils::string::copy(dev.DeviceID, u"MONITOR\\EMU1234\\{4d36e96e-e325-11ce-bfc1-08002be10318}\\0000");
|
||||
utils::string::copy(dev.DeviceKey, u"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\DISPLAY\\EMU1234\\"
|
||||
u"1&23a45b&0&UID67568640");
|
||||
});
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtUserEnumDisplaySettings(const syscall_context& c,
|
||||
const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> device_name,
|
||||
const DWORD mode_num, const emulator_object<EMU_DEVMODEW> dev_mode, const DWORD /*flags*/)
|
||||
{
|
||||
if (dev_mode && (mode_num == ENUM_CURRENT_SETTINGS || mode_num == 0))
|
||||
{
|
||||
const auto dev_name = read_unicode_string(c.emu, device_name);
|
||||
|
||||
if (dev_name == u"\\\\.\\DISPLAY1")
|
||||
{
|
||||
dev_mode.access([](EMU_DEVMODEW& dm) {
|
||||
dm.dmFields = 0x5C0000; // DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY
|
||||
dm.dmPelsWidth = 1920;
|
||||
dm.dmPelsHeight = 1080;
|
||||
dm.dmBitsPerPel = 32;
|
||||
dm.dmDisplayFrequency = 60;
|
||||
});
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtAssociateWaitCompletionPacket()
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
@@ -1142,6 +1189,7 @@ void syscall_dispatcher::add_handlers(std::map<std::string, syscall_handler>& ha
|
||||
add_handler(NtUserGetRawInputDeviceList);
|
||||
add_handler(NtUserGetKeyboardType);
|
||||
add_handler(NtUserEnumDisplayDevices);
|
||||
add_handler(NtUserEnumDisplaySettings);
|
||||
add_handler(NtUserSetProp);
|
||||
add_handler(NtUserSetProp2);
|
||||
add_handler(NtUserChangeWindowMessageFilterEx);
|
||||
@@ -1165,6 +1213,7 @@ void syscall_dispatcher::add_handlers(std::map<std::string, syscall_handler>& ha
|
||||
add_handler(NtReleaseWorkerFactoryWorker);
|
||||
add_handler(NtAlpcCreateSecurityContext);
|
||||
add_handler(NtAlpcDeleteSecurityContext);
|
||||
add_handler(NtSetSecurityObject);
|
||||
|
||||
#undef add_handler
|
||||
}
|
||||
|
||||
@@ -182,8 +182,18 @@ namespace syscalls
|
||||
return handle_query<FILE_FS_VOLUME_INFORMATION>(c.emu, fs_information, length, io_status_block,
|
||||
[&](FILE_FS_VOLUME_INFORMATION&) {});
|
||||
|
||||
case FileFsAttributeInformation:
|
||||
return handle_query<_FILE_FS_ATTRIBUTE_INFORMATION>(
|
||||
c.emu, fs_information, length, io_status_block, [&](_FILE_FS_ATTRIBUTE_INFORMATION& info) {
|
||||
info.FileSystemAttributes = 0x40006; // FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK | FILE_NAMED_STREAMS
|
||||
info.MaximumComponentNameLength = 255;
|
||||
constexpr auto name = u"NTFS"sv;
|
||||
info.FileSystemNameLength = static_cast<ULONG>(name.size() * sizeof(char16_t));
|
||||
memcpy(info.FileSystemName, name.data(), info.FileSystemNameLength);
|
||||
});
|
||||
|
||||
default:
|
||||
c.win_emu.log.error("Unsupported fs info class: %X\n", fs_information_class);
|
||||
c.win_emu.log.error("Unsupported fs info class: 0x%X\n", fs_information_class);
|
||||
c.emu.stop();
|
||||
return write_io_status(io_status_block, STATUS_NOT_SUPPORTED, true);
|
||||
}
|
||||
@@ -211,7 +221,7 @@ namespace syscalls
|
||||
|
||||
files.emplace_back(file_entry{
|
||||
.file_path = file.path().filename(),
|
||||
.file_size = file.file_size(),
|
||||
.file_size = file.is_directory() ? 0 : file.file_size(),
|
||||
.is_directory = file.is_directory(),
|
||||
});
|
||||
}
|
||||
@@ -232,7 +242,7 @@ namespace syscalls
|
||||
|
||||
files.emplace_back(file_entry{
|
||||
.file_path = filename,
|
||||
.file_size = dir_entry.file_size(),
|
||||
.file_size = dir_entry.is_directory() ? 0 : dir_entry.file_size(),
|
||||
.is_directory = dir_entry.is_directory(),
|
||||
});
|
||||
});
|
||||
@@ -537,12 +547,68 @@ namespace syscalls
|
||||
return ret(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
if (info_class == FileIsRemoteDeviceInformation)
|
||||
{
|
||||
if (!f->handle)
|
||||
{
|
||||
return ret(STATUS_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
block.Information = sizeof(FILE_IS_REMOTE_DEVICE_INFORMATION);
|
||||
|
||||
if (length < block.Information)
|
||||
{
|
||||
return ret(STATUS_BUFFER_OVERFLOW);
|
||||
}
|
||||
|
||||
const emulator_object<FILE_IS_REMOTE_DEVICE_INFORMATION> info{c.emu, file_information};
|
||||
FILE_IS_REMOTE_DEVICE_INFORMATION i{};
|
||||
|
||||
i.IsRemote = FALSE;
|
||||
|
||||
info.write(i);
|
||||
|
||||
return ret(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
if (info_class == FileIdInformation)
|
||||
{
|
||||
if (!f->handle)
|
||||
{
|
||||
return ret(STATUS_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
block.Information = sizeof(FILE_ID_INFORMATION);
|
||||
|
||||
if (length < block.Information)
|
||||
{
|
||||
return ret(STATUS_BUFFER_OVERFLOW);
|
||||
}
|
||||
|
||||
struct _stat64 file_stat{};
|
||||
if (fstat64(f->handle, &file_stat) != 0)
|
||||
{
|
||||
return ret(STATUS_INVALID_HANDLE);
|
||||
}
|
||||
|
||||
const emulator_object<FILE_ID_INFORMATION> info{c.emu, file_information};
|
||||
FILE_ID_INFORMATION i{};
|
||||
|
||||
i.VolumeSerialNumber = file_stat.st_dev;
|
||||
memset(&i.FileId, 0, sizeof(i.FileId));
|
||||
memcpy(&i.FileId.Identifier[0], &file_stat.st_ino, sizeof(file_stat.st_ino));
|
||||
|
||||
info.write(i);
|
||||
|
||||
return ret(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
if (info_class == FileAllInformation)
|
||||
{
|
||||
return ret(STATUS_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
c.win_emu.log.error("Unsupported query file info class: %X\n", info_class);
|
||||
c.win_emu.log.error("Unsupported query file info class: 0x%X\n", info_class);
|
||||
c.emu.stop();
|
||||
|
||||
return ret(STATUS_NOT_SUPPORTED);
|
||||
|
||||
@@ -20,6 +20,15 @@ namespace syscalls
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (base_address < MIN_ALLOCATION_ADDRESS || base_address >= MAX_ALLOCATION_END_EXCL)
|
||||
{
|
||||
if (return_length)
|
||||
{
|
||||
return_length.write(0);
|
||||
}
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (info_class == MemoryBasicInformation)
|
||||
{
|
||||
if (return_length)
|
||||
|
||||
@@ -434,4 +434,9 @@ namespace syscalls
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtSetSecurityObject()
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -448,8 +448,8 @@ void windows_emulator::setup_hooks()
|
||||
this->callbacks.on_rdtscp();
|
||||
|
||||
const auto ticks = this->clock_->timestamp_counter();
|
||||
this->emu().reg(x86_register::rax, ticks & 0xFFFFFFFF);
|
||||
this->emu().reg(x86_register::rdx, (ticks >> 32) & 0xFFFFFFFF);
|
||||
this->emu().reg(x86_register::rax, static_cast<uint32_t>(ticks));
|
||||
this->emu().reg(x86_register::rdx, static_cast<uint32_t>(ticks >> 32));
|
||||
|
||||
// Return the IA32_TSC_AUX value in RCX (low 32 bits)
|
||||
auto tsc_aux = 0; // Need to replace this with proper CPUID later
|
||||
@@ -462,8 +462,8 @@ void windows_emulator::setup_hooks()
|
||||
this->callbacks.on_rdtsc();
|
||||
|
||||
const auto ticks = this->clock_->timestamp_counter();
|
||||
this->emu().reg(x86_register::rax, ticks & 0xFFFFFFFF);
|
||||
this->emu().reg(x86_register::rdx, (ticks >> 32) & 0xFFFFFFFF);
|
||||
this->emu().reg(x86_register::rax, static_cast<uint32_t>(ticks));
|
||||
this->emu().reg(x86_register::rdx, static_cast<uint32_t>(ticks >> 32));
|
||||
|
||||
return instruction_hook_continuation::skip_instruction;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user