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
|
@ -149,10 +149,11 @@ void MaybeYield() {
|
|||
// MemoryBarrier();
|
||||
}
|
||||
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;
|
||||
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 = -in_nt_increments;
|
||||
|
@ -514,6 +515,10 @@ class Win32Thread : public Win32Handle<Thread> {
|
|||
~Win32Thread() = default;
|
||||
|
||||
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);
|
||||
Thread::set_name(name);
|
||||
}
|
||||
|
|
|
@ -54,6 +54,16 @@ struct X_FILE_FS_ATTRIBUTE_INFORMATION {
|
|||
};
|
||||
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)
|
||||
|
||||
} // namespace kernel
|
||||
|
|
|
@ -854,10 +854,11 @@ void KernelState::CompleteOverlappedDeferredEx(
|
|||
XOverlappedSetContext(ptr, XThread::GetCurrentThreadHandle());
|
||||
X_HANDLE event_handle = XOverlappedGetEvent(ptr);
|
||||
if (event_handle) {
|
||||
auto ev = object_table()->LookupObject<XEvent>(event_handle);
|
||||
auto ev = object_table()->LookupObject<XObject>(event_handle);
|
||||
|
||||
assert_not_null(ev);
|
||||
if (ev) {
|
||||
ev->Reset();
|
||||
if (ev && ev->type() == XObject::Type::Event) {
|
||||
ev.get<XEvent>()->Reset();
|
||||
}
|
||||
}
|
||||
auto global_lock = global_critical_region_.Acquire();
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "xenia/kernel/util/shim_utils.h"
|
||||
#include "xenia/kernel/xam/xam_module.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/xenumerator.h"
|
||||
#include "xenia/kernel/xthread.h"
|
||||
|
@ -261,10 +262,8 @@ dword_result_t RtlSleep_entry(dword_t dwMilliseconds, dword_t bAlertable) {
|
|||
? LLONG_MAX
|
||||
: static_cast<LONGLONG>(-10000) * dwMilliseconds;
|
||||
|
||||
X_STATUS result = xboxkrnl::KeDelayExecutionThread(
|
||||
MODE::UserMode,
|
||||
bAlertable,
|
||||
(uint64_t*)&delay);
|
||||
X_STATUS result = xboxkrnl::KeDelayExecutionThread(MODE::UserMode, bAlertable,
|
||||
(uint64_t*)&delay);
|
||||
|
||||
// If the delay was interrupted by an APC, keep delaying the thread
|
||||
while (bAlertable && result == X_STATUS_ALERTED) {
|
||||
|
@ -396,7 +395,8 @@ void XamLoaderTerminateTitle_entry() {
|
|||
}
|
||||
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
|
||||
// do nothing!
|
||||
// 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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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) {
|
||||
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);
|
||||
|
||||
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 kernel
|
||||
} // namespace xe
|
||||
|
|
|
@ -431,6 +431,26 @@ dword_result_t XamGetLocaleEx_entry(dword_t max_country_id,
|
|||
static_cast<uint8_t>(max_locale_id));
|
||||
}
|
||||
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 kernel
|
||||
|
|
|
@ -92,10 +92,14 @@ dword_result_t NtQueryInformationFile_entry(
|
|||
break;
|
||||
}
|
||||
case XFileSectorInformation: {
|
||||
// TODO(benvanik): return sector this file's on.
|
||||
XELOGE("NtQueryInformationFile(XFileSectorInformation) unimplemented");
|
||||
status = X_STATUS_INVALID_PARAMETER;
|
||||
out_length = 0;
|
||||
// SW that uses this seems to use the output as a way of uniquely
|
||||
// identifying a file for sorting/lookup so we can just give it an
|
||||
// arbitrary 4 byte integer most of the time
|
||||
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;
|
||||
}
|
||||
case XFileXctdCompressionInformation: {
|
||||
|
@ -338,9 +342,16 @@ dword_result_t NtQueryVolumeInformationFile_entry(
|
|||
}
|
||||
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: {
|
||||
// Unsupported, for now.
|
||||
assert_always();
|
||||
out_length = 0;
|
||||
break;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include "xenia/kernel/util/shim_utils.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_memory.h"
|
||||
DEFINE_bool(
|
||||
ignore_offset_for_ranged_allocations, false,
|
||||
"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);
|
||||
|
||||
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) {
|
||||
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) {
|
||||
// Type will usually be 0 (user request?), where 1 and 2 are sometimes made
|
||||
// by D3D/etc.
|
||||
|
||||
|
@ -430,9 +432,9 @@ dword_result_t MmAllocatePhysicalMemoryEx_entry(
|
|||
}
|
||||
|
||||
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 =
|
||||
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();
|
||||
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);
|
||||
|
@ -447,12 +449,20 @@ dword_result_t MmAllocatePhysicalMemoryEx_entry(
|
|||
|
||||
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);
|
||||
|
||||
dword_result_t MmAllocatePhysicalMemory_entry(dword_t flags,
|
||||
dword_t region_size,
|
||||
dword_t protect_bits) {
|
||||
return MmAllocatePhysicalMemoryEx_entry(flags, region_size, protect_bits, 0,
|
||||
return xeMmAllocatePhysicalMemoryEx(flags, region_size, protect_bits, 0,
|
||||
0xFFFFFFFFu, 0);
|
||||
}
|
||||
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 <string>
|
||||
|
||||
#include "third_party/pe/pe_image.h"
|
||||
#include "xenia/base/atomic.h"
|
||||
#include "xenia/base/chrono.h"
|
||||
#include "xenia/base/logging.h"
|
||||
|
@ -24,7 +25,6 @@
|
|||
#include "xenia/kernel/xboxkrnl/xboxkrnl_threading.h"
|
||||
#include "xenia/kernel/xevent.h"
|
||||
#include "xenia/kernel/xthread.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
@ -402,14 +402,14 @@ DECLARE_XBOXKRNL_EXPORT3(RtlUnicodeToMultiByteN, kNone, kImplemented,
|
|||
kHighFrequency, kSketchy);
|
||||
|
||||
// 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) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 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]);
|
||||
if (dos_magic != 0x5A4D) { // 'MZ'
|
||||
return 0;
|
||||
|
@ -421,9 +421,82 @@ pointer_result_t RtlImageNtHeader_entry(lpvoid_t module) {
|
|||
if (nt_magic != 0x4550) { // 'PE'
|
||||
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);
|
||||
// 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,
|
||||
dword_t field_dword) {
|
||||
|
|
|
@ -185,7 +185,7 @@ dword_result_t NtResumeThread_entry(dword_t handle,
|
|||
}
|
||||
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;
|
||||
auto thread = XObject::GetNativeObject<XThread>(kernel_state(), thread_ptr);
|
||||
if (thread) {
|
||||
|
@ -230,11 +230,27 @@ dword_result_t NtSuspendThread_entry(dword_t handle,
|
|||
}
|
||||
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,
|
||||
pointer_t<X_KTHREAD> thread,
|
||||
lpvoid_t stack_alloc_base,
|
||||
lpvoid_t stack_base,
|
||||
lpvoid_t stack_limit, const ppc_context_t& context) {
|
||||
lpvoid_t stack_base, lpvoid_t stack_limit,
|
||||
const ppc_context_t& context) {
|
||||
auto current_thread = XThread::GetCurrentThread();
|
||||
|
||||
auto pcr = context->TranslateVirtualGPR<X_KPCR*>(context->r[13]);
|
||||
|
|
Loading…
Reference in New Issue