Merge pull request #159 from chrisps/info_stubs_and_misc_kernel
[Kernel] Implement misc functions, bandaids for 415608D8
This commit is contained in:
commit
1319ff6ead
|
@ -152,7 +152,8 @@ void NanoSleep(int64_t ns) {
|
||||||
// nanosleep is done in 100 nanosecond increments
|
// nanosleep is done in 100 nanosecond increments
|
||||||
int64_t in_nt_increments = ns / 100LL;
|
int64_t in_nt_increments = ns / 100LL;
|
||||||
if (in_nt_increments == 0 && ns != 0) {
|
if (in_nt_increments == 0 && ns != 0) {
|
||||||
//if we're explicitly requesting a delay of 0 ns, let it go through, otherwise if it was less than a 100ns increment we round up to 100ns
|
// if we're explicitly requesting a delay of 0 ns, let it go through,
|
||||||
|
// otherwise if it was less than a 100ns increment we round up to 100ns
|
||||||
in_nt_increments = 1;
|
in_nt_increments = 1;
|
||||||
}
|
}
|
||||||
in_nt_increments = -in_nt_increments;
|
in_nt_increments = -in_nt_increments;
|
||||||
|
@ -514,6 +515,10 @@ class Win32Thread : public Win32Handle<Thread> {
|
||||||
~Win32Thread() = default;
|
~Win32Thread() = default;
|
||||||
|
|
||||||
void set_name(std::string name) override {
|
void set_name(std::string name) override {
|
||||||
|
// this can actually happen in some debug builds
|
||||||
|
if (&name == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
xe::threading::set_name(handle_, name);
|
xe::threading::set_name(handle_, name);
|
||||||
Thread::set_name(name);
|
Thread::set_name(name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,16 @@ struct X_FILE_FS_ATTRIBUTE_INFORMATION {
|
||||||
};
|
};
|
||||||
static_assert_size(X_FILE_FS_ATTRIBUTE_INFORMATION, 16);
|
static_assert_size(X_FILE_FS_ATTRIBUTE_INFORMATION, 16);
|
||||||
|
|
||||||
|
enum X_FILE_DEVICE_TYPE : uint32_t {
|
||||||
|
FILE_DEVICE_UNKNOWN = 0x22
|
||||||
|
};
|
||||||
|
|
||||||
|
struct X_FILE_FS_DEVICE_INFORMATION {
|
||||||
|
be<X_FILE_DEVICE_TYPE> device_type;
|
||||||
|
be<uint32_t> characteristics;
|
||||||
|
};
|
||||||
|
static_assert_size(X_FILE_FS_DEVICE_INFORMATION, 8);
|
||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
} // namespace kernel
|
} // namespace kernel
|
||||||
|
|
|
@ -854,10 +854,11 @@ void KernelState::CompleteOverlappedDeferredEx(
|
||||||
XOverlappedSetContext(ptr, XThread::GetCurrentThreadHandle());
|
XOverlappedSetContext(ptr, XThread::GetCurrentThreadHandle());
|
||||||
X_HANDLE event_handle = XOverlappedGetEvent(ptr);
|
X_HANDLE event_handle = XOverlappedGetEvent(ptr);
|
||||||
if (event_handle) {
|
if (event_handle) {
|
||||||
auto ev = object_table()->LookupObject<XEvent>(event_handle);
|
auto ev = object_table()->LookupObject<XObject>(event_handle);
|
||||||
|
|
||||||
assert_not_null(ev);
|
assert_not_null(ev);
|
||||||
if (ev) {
|
if (ev && ev->type() == XObject::Type::Event) {
|
||||||
ev->Reset();
|
ev.get<XEvent>()->Reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto global_lock = global_critical_region_.Acquire();
|
auto global_lock = global_critical_region_.Acquire();
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "xenia/kernel/util/shim_utils.h"
|
#include "xenia/kernel/util/shim_utils.h"
|
||||||
#include "xenia/kernel/xam/xam_module.h"
|
#include "xenia/kernel/xam/xam_module.h"
|
||||||
#include "xenia/kernel/xam/xam_private.h"
|
#include "xenia/kernel/xam/xam_private.h"
|
||||||
|
#include "xenia/kernel/xboxkrnl/xboxkrnl_memory.h"
|
||||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_threading.h"
|
#include "xenia/kernel/xboxkrnl/xboxkrnl_threading.h"
|
||||||
#include "xenia/kernel/xenumerator.h"
|
#include "xenia/kernel/xenumerator.h"
|
||||||
#include "xenia/kernel/xthread.h"
|
#include "xenia/kernel/xthread.h"
|
||||||
|
@ -261,9 +262,7 @@ dword_result_t RtlSleep_entry(dword_t dwMilliseconds, dword_t bAlertable) {
|
||||||
? LLONG_MAX
|
? LLONG_MAX
|
||||||
: static_cast<LONGLONG>(-10000) * dwMilliseconds;
|
: static_cast<LONGLONG>(-10000) * dwMilliseconds;
|
||||||
|
|
||||||
X_STATUS result = xboxkrnl::KeDelayExecutionThread(
|
X_STATUS result = xboxkrnl::KeDelayExecutionThread(MODE::UserMode, bAlertable,
|
||||||
MODE::UserMode,
|
|
||||||
bAlertable,
|
|
||||||
(uint64_t*)&delay);
|
(uint64_t*)&delay);
|
||||||
|
|
||||||
// If the delay was interrupted by an APC, keep delaying the thread
|
// If the delay was interrupted by an APC, keep delaying the thread
|
||||||
|
@ -396,7 +395,8 @@ void XamLoaderTerminateTitle_entry() {
|
||||||
}
|
}
|
||||||
DECLARE_XAM_EXPORT1(XamLoaderTerminateTitle, kNone, kSketchy);
|
DECLARE_XAM_EXPORT1(XamLoaderTerminateTitle, kNone, kSketchy);
|
||||||
|
|
||||||
dword_result_t XamAlloc_entry(dword_t flags, dword_t size, lpdword_t out_ptr) {
|
uint32_t XamAllocImpl(uint32_t flags, uint32_t size,
|
||||||
|
xe::be<uint32_t>* out_ptr) {
|
||||||
if (flags & 0x00100000) { // HEAP_ZERO_memory used unless this flag
|
if (flags & 0x00100000) { // HEAP_ZERO_memory used unless this flag
|
||||||
// do nothing!
|
// do nothing!
|
||||||
// maybe we ought to fill it with nonzero garbage, but otherwise this is a
|
// maybe we ought to fill it with nonzero garbage, but otherwise this is a
|
||||||
|
@ -412,8 +412,44 @@ dword_result_t XamAlloc_entry(dword_t flags, dword_t size, lpdword_t out_ptr) {
|
||||||
|
|
||||||
return X_ERROR_SUCCESS;
|
return X_ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dword_result_t XamAlloc_entry(dword_t flags, dword_t size, lpdword_t out_ptr) {
|
||||||
|
return XamAllocImpl(flags, size, out_ptr);
|
||||||
|
}
|
||||||
DECLARE_XAM_EXPORT1(XamAlloc, kMemory, kImplemented);
|
DECLARE_XAM_EXPORT1(XamAlloc, kMemory, kImplemented);
|
||||||
|
|
||||||
|
static const unsigned short XamPhysicalProtTable[4] = {
|
||||||
|
X_PAGE_READONLY,
|
||||||
|
X_PAGE_READWRITE | X_PAGE_NOCACHE,
|
||||||
|
X_PAGE_READWRITE,
|
||||||
|
X_PAGE_WRITECOMBINE | X_PAGE_READWRITE
|
||||||
|
};
|
||||||
|
|
||||||
|
dword_result_t XamAllocEx_entry(dword_t phys_flags, dword_t flags, dword_t size,
|
||||||
|
lpdword_t out_ptr, const ppc_context_t& ctx) {
|
||||||
|
if ((flags & 0x40000000) == 0) {
|
||||||
|
return XamAllocImpl(flags, size, out_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t flags_remapped = phys_flags;
|
||||||
|
if ((phys_flags & 0xF000000) == 0) {
|
||||||
|
// setting default alignment
|
||||||
|
flags_remapped = 0xC000000 | phys_flags & 0xF0FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t result = xboxkrnl::xeMmAllocatePhysicalMemoryEx(
|
||||||
|
2, size, XamPhysicalProtTable[(flags_remapped >> 28) & 0b11], 0,
|
||||||
|
0xFFFFFFFF, 1 << ((flags_remapped >> 24) & 0xF));
|
||||||
|
|
||||||
|
if (result && (flags_remapped & 0x40000000) != 0) {
|
||||||
|
memset(ctx->TranslateVirtual<uint8_t*>(result), 0, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_ptr = result;
|
||||||
|
return result ? 0 : 0x8007000E;
|
||||||
|
}
|
||||||
|
DECLARE_XAM_EXPORT1(XamAllocEx, kMemory, kImplemented);
|
||||||
|
|
||||||
dword_result_t XamFree_entry(lpdword_t ptr) {
|
dword_result_t XamFree_entry(lpdword_t ptr) {
|
||||||
kernel_state()->memory()->SystemHeapFree(ptr.guest_address());
|
kernel_state()->memory()->SystemHeapFree(ptr.guest_address());
|
||||||
|
|
||||||
|
@ -428,6 +464,11 @@ dword_result_t XamQueryLiveHiveW_entry(lpu16string_t name, lpvoid_t out_buf,
|
||||||
}
|
}
|
||||||
DECLARE_XAM_EXPORT1(XamQueryLiveHiveW, kNone, kStub);
|
DECLARE_XAM_EXPORT1(XamQueryLiveHiveW, kNone, kStub);
|
||||||
|
|
||||||
|
dword_result_t XamIsCurrentTitleDash_entry(const ppc_context_t& ctx) {
|
||||||
|
return ctx->kernel_state->title_id() == 0xFFFE07D1;
|
||||||
|
}
|
||||||
|
DECLARE_XAM_EXPORT1(XamIsCurrentTitleDash, kNone, kImplemented);
|
||||||
|
|
||||||
} // namespace xam
|
} // namespace xam
|
||||||
} // namespace kernel
|
} // namespace kernel
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
|
@ -431,6 +431,26 @@ dword_result_t XamGetLocaleEx_entry(dword_t max_country_id,
|
||||||
static_cast<uint8_t>(max_locale_id));
|
static_cast<uint8_t>(max_locale_id));
|
||||||
}
|
}
|
||||||
DECLARE_XAM_EXPORT1(XamGetLocaleEx, kLocale, kImplemented);
|
DECLARE_XAM_EXPORT1(XamGetLocaleEx, kLocale, kImplemented);
|
||||||
|
//originally a switch table, wrote a script to extract the values for all possible cases
|
||||||
|
|
||||||
|
static constexpr uint8_t XamLocaleDateFmtTable[] = {
|
||||||
|
2, 1, 3, 1, 3, 3, 3, 3, 3, 3, 3, 2, 3, 2, 1, 4, 2, 3, 1, 2, 2, 3,
|
||||||
|
3, 3, 3, 3, 2, 1, 3, 2, 2, 3, 0, 3, 0, 3, 3, 5, 3, 1, 3, 2, 3, 3,
|
||||||
|
3, 2, 3, 3, 5, 3, 3, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
|
2, 3, 3, 0, 2, 1, 3, 3, 3, 3, 3, 5, 3, 2, 3, 3, 3, 2, 3, 5, 0, 3,
|
||||||
|
1, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 5, 1, 1, 1, 1};
|
||||||
|
|
||||||
|
dword_result_t XamGetLocaleDateFormat_entry(dword_t locale) {
|
||||||
|
uint32_t biased_locale = locale - 5;
|
||||||
|
int result = 3;
|
||||||
|
if (biased_locale > 0x68) {
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return XamLocaleDateFmtTable[biased_locale];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_XAM_EXPORT1(XamGetLocaleDateFormat, kLocale, kImplemented);
|
||||||
|
|
||||||
} // namespace xam
|
} // namespace xam
|
||||||
} // namespace kernel
|
} // namespace kernel
|
||||||
|
|
|
@ -92,10 +92,14 @@ dword_result_t NtQueryInformationFile_entry(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case XFileSectorInformation: {
|
case XFileSectorInformation: {
|
||||||
// TODO(benvanik): return sector this file's on.
|
// SW that uses this seems to use the output as a way of uniquely
|
||||||
XELOGE("NtQueryInformationFile(XFileSectorInformation) unimplemented");
|
// identifying a file for sorting/lookup so we can just give it an
|
||||||
status = X_STATUS_INVALID_PARAMETER;
|
// arbitrary 4 byte integer most of the time
|
||||||
out_length = 0;
|
XELOGW("Stub XFileSectorInformation!");
|
||||||
|
auto info = info_ptr.as<uint32_t*>();
|
||||||
|
size_t fname_hash = xe::memory::hash_combine(82589933LL, file->path());
|
||||||
|
*info = static_cast<uint32_t>(fname_hash ^ (fname_hash >> 32));
|
||||||
|
out_length = sizeof(uint32_t);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case XFileXctdCompressionInformation: {
|
case XFileXctdCompressionInformation: {
|
||||||
|
@ -338,9 +342,16 @@ dword_result_t NtQueryVolumeInformationFile_entry(
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case XFileFsDeviceInformation:
|
case XFileFsDeviceInformation: {
|
||||||
|
auto info = info_ptr.as<X_FILE_FS_DEVICE_INFORMATION*>();
|
||||||
|
auto file_device = file->device();
|
||||||
|
XELOGW("Stub XFileFsDeviceInformation!");
|
||||||
|
info->device_type = FILE_DEVICE_UNKNOWN; // 415608D8 checks for 0x46;
|
||||||
|
info->characteristics = 0;
|
||||||
|
out_length = sizeof(X_FILE_FS_DEVICE_INFORMATION);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
// Unsupported, for now.
|
|
||||||
assert_always();
|
assert_always();
|
||||||
out_length = 0;
|
out_length = 0;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
#include "xenia/kernel/util/shim_utils.h"
|
#include "xenia/kernel/util/shim_utils.h"
|
||||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
|
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
|
||||||
#include "xenia/xbox.h"
|
#include "xenia/xbox.h"
|
||||||
|
#include "xenia/kernel/xboxkrnl/xboxkrnl_memory.h"
|
||||||
DEFINE_bool(
|
DEFINE_bool(
|
||||||
ignore_offset_for_ranged_allocations, false,
|
ignore_offset_for_ranged_allocations, false,
|
||||||
"Allows to ignore 4k offset for physical allocations with provided range. "
|
"Allows to ignore 4k offset for physical allocations with provided range. "
|
||||||
|
@ -379,9 +379,11 @@ dword_result_t NtAllocateEncryptedMemory_entry(dword_t unk, dword_t region_size,
|
||||||
}
|
}
|
||||||
DECLARE_XBOXKRNL_EXPORT1(NtAllocateEncryptedMemory, kMemory, kImplemented);
|
DECLARE_XBOXKRNL_EXPORT1(NtAllocateEncryptedMemory, kMemory, kImplemented);
|
||||||
|
|
||||||
dword_result_t MmAllocatePhysicalMemoryEx_entry(
|
uint32_t xeMmAllocatePhysicalMemoryEx(uint32_t flags, uint32_t region_size,
|
||||||
dword_t flags, dword_t region_size, dword_t protect_bits,
|
uint32_t protect_bits,
|
||||||
dword_t min_addr_range, dword_t max_addr_range, dword_t alignment) {
|
uint32_t min_addr_range,
|
||||||
|
uint32_t max_addr_range,
|
||||||
|
uint32_t alignment) {
|
||||||
// Type will usually be 0 (user request?), where 1 and 2 are sometimes made
|
// Type will usually be 0 (user request?), where 1 and 2 are sometimes made
|
||||||
// by D3D/etc.
|
// by D3D/etc.
|
||||||
|
|
||||||
|
@ -430,9 +432,9 @@ dword_result_t MmAllocatePhysicalMemoryEx_entry(
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t heap_min_addr =
|
uint32_t heap_min_addr =
|
||||||
xe::sat_sub(min_addr_range.value(), heap_physical_address_offset);
|
xe::sat_sub(min_addr_range, heap_physical_address_offset);
|
||||||
uint32_t heap_max_addr =
|
uint32_t heap_max_addr =
|
||||||
xe::sat_sub(max_addr_range.value(), heap_physical_address_offset);
|
xe::sat_sub(max_addr_range, heap_physical_address_offset);
|
||||||
uint32_t heap_size = heap->heap_size();
|
uint32_t heap_size = heap->heap_size();
|
||||||
heap_min_addr = heap_base + std::min(heap_min_addr, heap_size - 1);
|
heap_min_addr = heap_base + std::min(heap_min_addr, heap_size - 1);
|
||||||
heap_max_addr = heap_base + std::min(heap_max_addr, heap_size - 1);
|
heap_max_addr = heap_base + std::min(heap_max_addr, heap_size - 1);
|
||||||
|
@ -447,12 +449,20 @@ dword_result_t MmAllocatePhysicalMemoryEx_entry(
|
||||||
|
|
||||||
return base_address;
|
return base_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dword_result_t MmAllocatePhysicalMemoryEx_entry(
|
||||||
|
dword_t flags, dword_t region_size, dword_t protect_bits,
|
||||||
|
dword_t min_addr_range, dword_t max_addr_range, dword_t alignment) {
|
||||||
|
return xeMmAllocatePhysicalMemoryEx(flags, region_size, protect_bits,
|
||||||
|
min_addr_range, max_addr_range,
|
||||||
|
alignment);
|
||||||
|
}
|
||||||
DECLARE_XBOXKRNL_EXPORT1(MmAllocatePhysicalMemoryEx, kMemory, kImplemented);
|
DECLARE_XBOXKRNL_EXPORT1(MmAllocatePhysicalMemoryEx, kMemory, kImplemented);
|
||||||
|
|
||||||
dword_result_t MmAllocatePhysicalMemory_entry(dword_t flags,
|
dword_result_t MmAllocatePhysicalMemory_entry(dword_t flags,
|
||||||
dword_t region_size,
|
dword_t region_size,
|
||||||
dword_t protect_bits) {
|
dword_t protect_bits) {
|
||||||
return MmAllocatePhysicalMemoryEx_entry(flags, region_size, protect_bits, 0,
|
return xeMmAllocatePhysicalMemoryEx(flags, region_size, protect_bits, 0,
|
||||||
0xFFFFFFFFu, 0);
|
0xFFFFFFFFu, 0);
|
||||||
}
|
}
|
||||||
DECLARE_XBOXKRNL_EXPORT1(MmAllocatePhysicalMemory, kMemory, kImplemented);
|
DECLARE_XBOXKRNL_EXPORT1(MmAllocatePhysicalMemory, kMemory, kImplemented);
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2015 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XENIA_KERNEL_XBOXKRNL_XBOXKRNL_MEMORY_H_
|
||||||
|
#define XENIA_KERNEL_XBOXKRNL_XBOXKRNL_MEMORY_H_
|
||||||
|
|
||||||
|
#include "xenia/kernel/util/shim_utils.h"
|
||||||
|
#include "xenia/xbox.h"
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace kernel {
|
||||||
|
|
||||||
|
|
||||||
|
namespace xboxkrnl {
|
||||||
|
|
||||||
|
uint32_t xeMmAllocatePhysicalMemoryEx(uint32_t flags, uint32_t region_size,
|
||||||
|
uint32_t protect_bits,
|
||||||
|
uint32_t min_addr_range,
|
||||||
|
uint32_t max_addr_range,
|
||||||
|
uint32_t alignment);
|
||||||
|
|
||||||
|
} // namespace xboxkrnl
|
||||||
|
} // namespace kernel
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
#endif // XENIA_KERNEL_XBOXKRNL_XBOXKRNL_MEMORY_H_
|
|
@ -12,6 +12,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "third_party/pe/pe_image.h"
|
||||||
#include "xenia/base/atomic.h"
|
#include "xenia/base/atomic.h"
|
||||||
#include "xenia/base/chrono.h"
|
#include "xenia/base/chrono.h"
|
||||||
#include "xenia/base/logging.h"
|
#include "xenia/base/logging.h"
|
||||||
|
@ -24,7 +25,6 @@
|
||||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_threading.h"
|
#include "xenia/kernel/xboxkrnl/xboxkrnl_threading.h"
|
||||||
#include "xenia/kernel/xevent.h"
|
#include "xenia/kernel/xevent.h"
|
||||||
#include "xenia/kernel/xthread.h"
|
#include "xenia/kernel/xthread.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace kernel {
|
namespace kernel {
|
||||||
namespace xboxkrnl {
|
namespace xboxkrnl {
|
||||||
|
@ -402,14 +402,14 @@ DECLARE_XBOXKRNL_EXPORT3(RtlUnicodeToMultiByteN, kNone, kImplemented,
|
||||||
kHighFrequency, kSketchy);
|
kHighFrequency, kSketchy);
|
||||||
|
|
||||||
// https://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Executable%20Images/RtlImageNtHeader.html
|
// https://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Executable%20Images/RtlImageNtHeader.html
|
||||||
pointer_result_t RtlImageNtHeader_entry(lpvoid_t module) {
|
static IMAGE_NT_HEADERS32* ImageNtHeader(uint8_t* module) {
|
||||||
if (!module) {
|
if (!module) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Little-endian! no swapping!
|
// Little-endian! no swapping!
|
||||||
|
|
||||||
auto dos_header = module.as<const uint8_t*>();
|
auto dos_header = module;
|
||||||
auto dos_magic = *reinterpret_cast<const uint16_t*>(&dos_header[0x00]);
|
auto dos_magic = *reinterpret_cast<const uint16_t*>(&dos_header[0x00]);
|
||||||
if (dos_magic != 0x5A4D) { // 'MZ'
|
if (dos_magic != 0x5A4D) { // 'MZ'
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -421,9 +421,82 @@ pointer_result_t RtlImageNtHeader_entry(lpvoid_t module) {
|
||||||
if (nt_magic != 0x4550) { // 'PE'
|
if (nt_magic != 0x4550) { // 'PE'
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return kernel_memory()->HostToGuestVirtual(nt_header);
|
return reinterpret_cast<IMAGE_NT_HEADERS32*>(nt_header);
|
||||||
|
}
|
||||||
|
|
||||||
|
pointer_result_t RtlImageNtHeader_entry(lpvoid_t module) {
|
||||||
|
auto result = ImageNtHeader(module.as<uint8_t*>());
|
||||||
|
if (!result) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return kernel_memory()->HostToGuestVirtual(result);
|
||||||
}
|
}
|
||||||
DECLARE_XBOXKRNL_EXPORT1(RtlImageNtHeader, kNone, kImplemented);
|
DECLARE_XBOXKRNL_EXPORT1(RtlImageNtHeader, kNone, kImplemented);
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/dbghelp/nf-dbghelp-imagedirectoryentrytodata
|
||||||
|
dword_result_t RtlImageDirectoryEntryToData_entry(dword_t Base, dword_t MappedAsImage_,
|
||||||
|
word_t DirectoryEntry, dword_t Size,
|
||||||
|
const ppc_context_t& ctx) {
|
||||||
|
bool MappedAsImage = static_cast<unsigned char>(MappedAsImage_);
|
||||||
|
uint32_t aligned_base = Base;
|
||||||
|
if ((Base & 1) != 0) {
|
||||||
|
aligned_base = Base & 0xFFFFFFFE;
|
||||||
|
MappedAsImage = false;
|
||||||
|
}
|
||||||
|
IMAGE_NT_HEADERS32* nt_header =
|
||||||
|
ImageNtHeader(ctx->TranslateVirtual<uint8_t*>(aligned_base));
|
||||||
|
|
||||||
|
if (!nt_header) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (nt_header->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (DirectoryEntry >= nt_header->OptionalHeader.NumberOfRvaAndSizes) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint32_t Address =
|
||||||
|
nt_header->OptionalHeader.DataDirectory[DirectoryEntry].VirtualAddress;
|
||||||
|
if (!Address) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
xe::store_and_swap<uint32_t>(
|
||||||
|
ctx->TranslateVirtual(Size),
|
||||||
|
nt_header->OptionalHeader.DataDirectory[DirectoryEntry].Size);
|
||||||
|
if (MappedAsImage || Address < nt_header->OptionalHeader.SizeOfHeaders) {
|
||||||
|
return aligned_base + Address;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t n_sections = nt_header->FileHeader.NumberOfSections;
|
||||||
|
IMAGE_SECTION_HEADER* v8 = reinterpret_cast<IMAGE_SECTION_HEADER*>(
|
||||||
|
reinterpret_cast<char*>(&nt_header->OptionalHeader) +
|
||||||
|
nt_header->FileHeader.SizeOfOptionalHeader);
|
||||||
|
if (!n_sections) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t i = 0;
|
||||||
|
while (true) {
|
||||||
|
uint32_t section_virtual_address = v8->VirtualAddress;
|
||||||
|
uint32_t sizeof_section = v8->SizeOfRawData;
|
||||||
|
if (Address >= section_virtual_address &&
|
||||||
|
Address < sizeof_section + section_virtual_address) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
++v8;
|
||||||
|
if (i >= n_sections) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v8) {
|
||||||
|
return aligned_base + Address - v8->VirtualAddress;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_XBOXKRNL_EXPORT1(RtlImageDirectoryEntryToData, kNone, kImplemented);
|
||||||
|
|
||||||
pointer_result_t RtlImageXexHeaderField_entry(pointer_t<xex2_header> xex_header,
|
pointer_result_t RtlImageXexHeaderField_entry(pointer_t<xex2_header> xex_header,
|
||||||
dword_t field_dword) {
|
dword_t field_dword) {
|
||||||
|
|
|
@ -185,7 +185,7 @@ dword_result_t NtResumeThread_entry(dword_t handle,
|
||||||
}
|
}
|
||||||
DECLARE_XBOXKRNL_EXPORT1(NtResumeThread, kThreading, kImplemented);
|
DECLARE_XBOXKRNL_EXPORT1(NtResumeThread, kThreading, kImplemented);
|
||||||
|
|
||||||
dword_result_t KeResumeThread_entry(lpvoid_t thread_ptr) {
|
dword_result_t KeResumeThread_entry(pointer_t<X_KTHREAD> thread_ptr) {
|
||||||
X_STATUS result = X_STATUS_SUCCESS;
|
X_STATUS result = X_STATUS_SUCCESS;
|
||||||
auto thread = XObject::GetNativeObject<XThread>(kernel_state(), thread_ptr);
|
auto thread = XObject::GetNativeObject<XThread>(kernel_state(), thread_ptr);
|
||||||
if (thread) {
|
if (thread) {
|
||||||
|
@ -230,11 +230,27 @@ dword_result_t NtSuspendThread_entry(dword_t handle,
|
||||||
}
|
}
|
||||||
DECLARE_XBOXKRNL_EXPORT1(NtSuspendThread, kThreading, kImplemented);
|
DECLARE_XBOXKRNL_EXPORT1(NtSuspendThread, kThreading, kImplemented);
|
||||||
|
|
||||||
|
dword_result_t KeSuspendThread_entry(pointer_t<X_KTHREAD> kthread,
|
||||||
|
const ppc_context_t& context) {
|
||||||
|
auto thread = XObject::GetNativeObject<XThread>(context->kernel_state, kthread);
|
||||||
|
uint32_t suspend_count_out = 0;
|
||||||
|
|
||||||
|
if (thread) {
|
||||||
|
suspend_count_out = thread->suspend_count();
|
||||||
|
|
||||||
|
uint32_t discarded_new_suspend_count = 0;
|
||||||
|
thread->Suspend(&discarded_new_suspend_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
return suspend_count_out;
|
||||||
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT1(KeSuspendThread, kThreading, kImplemented);
|
||||||
|
|
||||||
void KeSetCurrentStackPointers_entry(lpvoid_t stack_ptr,
|
void KeSetCurrentStackPointers_entry(lpvoid_t stack_ptr,
|
||||||
pointer_t<X_KTHREAD> thread,
|
pointer_t<X_KTHREAD> thread,
|
||||||
lpvoid_t stack_alloc_base,
|
lpvoid_t stack_alloc_base,
|
||||||
lpvoid_t stack_base,
|
lpvoid_t stack_base, lpvoid_t stack_limit,
|
||||||
lpvoid_t stack_limit, const ppc_context_t& context) {
|
const ppc_context_t& context) {
|
||||||
auto current_thread = XThread::GetCurrentThread();
|
auto current_thread = XThread::GetCurrentThread();
|
||||||
|
|
||||||
auto pcr = context->TranslateVirtualGPR<X_KPCR*>(context->r[13]);
|
auto pcr = context->TranslateVirtualGPR<X_KPCR*>(context->r[13]);
|
||||||
|
|
Loading…
Reference in New Issue