[Kernel] - Change OddObj to X_DISPATCH_HEADER
- Change OddObj to X_DISPATCH_HEADER - Add unknown X_KWAIT_REASON flag - Fixed InitializeGuestObject mistake - Replaces unknowns in kthread using nukernel as reference
This commit is contained in:
committed by
Radosław Gliński
parent
c2674b19d2
commit
dc4db67f9c
@@ -1527,15 +1527,17 @@ void KernelState::InitializeKernelGuestGlobals() {
|
|||||||
SetProcessTLSVars(system_process, 32, 0, 0);
|
SetProcessTLSVars(system_process, 32, 0, 0);
|
||||||
|
|
||||||
uint32_t oddobject_offset =
|
uint32_t oddobject_offset =
|
||||||
kernel_guest_globals_ + offsetof(KernelGuestGlobals, OddObj);
|
kernel_guest_globals_ +
|
||||||
|
offsetof(KernelGuestGlobals, XboxKernelDefaultObject);
|
||||||
|
|
||||||
// init unknown object
|
// init unknown object
|
||||||
|
|
||||||
block->OddObj.field0 = 0x1000000;
|
block->XboxKernelDefaultObject.type = DISPATCHER_AUTO_RESET_EVENT;
|
||||||
block->OddObj.field4 = 1;
|
block->XboxKernelDefaultObject.signal_state = 1;
|
||||||
block->OddObj.points_to_self =
|
block->XboxKernelDefaultObject.wait_list.flink_ptr =
|
||||||
oddobject_offset + offsetof(X_UNKNOWN_TYPE_REFED, points_to_self);
|
oddobject_offset + offsetof(X_DISPATCH_HEADER, wait_list.flink_ptr);
|
||||||
block->OddObj.points_to_prior = block->OddObj.points_to_self;
|
block->XboxKernelDefaultObject.wait_list.blink_ptr =
|
||||||
|
block->XboxKernelDefaultObject.wait_list.flink_ptr;
|
||||||
|
|
||||||
// init thread object
|
// init thread object
|
||||||
block->ExThreadObjectType.pool_tag = 0x65726854;
|
block->ExThreadObjectType.pool_tag = 0x65726854;
|
||||||
|
|||||||
@@ -96,21 +96,13 @@ struct TerminateNotification {
|
|||||||
// a bit like the timers on KUSER_SHARED on normal win32
|
// a bit like the timers on KUSER_SHARED on normal win32
|
||||||
// https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/ntexapi_x/kuser_shared_data/index.htm
|
// https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/ntexapi_x/kuser_shared_data/index.htm
|
||||||
struct X_TIME_STAMP_BUNDLE {
|
struct X_TIME_STAMP_BUNDLE {
|
||||||
|
// according to Nukernl these are BE
|
||||||
uint64_t interrupt_time;
|
uint64_t interrupt_time;
|
||||||
// i assume system_time is in 100 ns intervals like on win32
|
// i assume system_time is in 100 ns intervals like on win32
|
||||||
uint64_t system_time;
|
uint64_t system_time;
|
||||||
uint32_t tick_count;
|
uint32_t tick_count;
|
||||||
uint32_t padding;
|
uint32_t padding;
|
||||||
};
|
};
|
||||||
struct X_UNKNOWN_TYPE_REFED {
|
|
||||||
xe::be<uint32_t> field0;
|
|
||||||
xe::be<uint32_t> field4;
|
|
||||||
// this is definitely a LIST_ENTRY?
|
|
||||||
xe::be<uint32_t> points_to_self; // this field points to itself
|
|
||||||
xe::be<uint32_t>
|
|
||||||
points_to_prior; // points to the previous field, which points to itself
|
|
||||||
};
|
|
||||||
static_assert_size(X_UNKNOWN_TYPE_REFED, 16);
|
|
||||||
|
|
||||||
struct KernelGuestGlobals {
|
struct KernelGuestGlobals {
|
||||||
X_OBJECT_TYPE ExThreadObjectType;
|
X_OBJECT_TYPE ExThreadObjectType;
|
||||||
@@ -125,7 +117,7 @@ struct KernelGuestGlobals {
|
|||||||
X_OBJECT_TYPE ObSymbolicLinkObjectType;
|
X_OBJECT_TYPE ObSymbolicLinkObjectType;
|
||||||
// a constant buffer that some object types' "unknown_size_or_object" field
|
// a constant buffer that some object types' "unknown_size_or_object" field
|
||||||
// points to
|
// points to
|
||||||
X_UNKNOWN_TYPE_REFED OddObj;
|
X_DISPATCH_HEADER XboxKernelDefaultObject;
|
||||||
X_KPROCESS idle_process; // X_PROCTYPE_IDLE. runs in interrupt contexts. is
|
X_KPROCESS idle_process; // X_PROCTYPE_IDLE. runs in interrupt contexts. is
|
||||||
// also the context the kernel starts in?
|
// also the context the kernel starts in?
|
||||||
X_KPROCESS title_process; // X_PROCTYPE_TITLE
|
X_KPROCESS title_process; // X_PROCTYPE_TITLE
|
||||||
|
|||||||
@@ -676,7 +676,7 @@ struct X_POOL_ALLOC_HEADER {
|
|||||||
};
|
};
|
||||||
|
|
||||||
uint32_t xeAllocatePoolTypeWithTag(PPCContext* context, uint32_t size,
|
uint32_t xeAllocatePoolTypeWithTag(PPCContext* context, uint32_t size,
|
||||||
uint32_t tag, uint32_t zero) {
|
uint32_t tag, uint32_t pool_selector) {
|
||||||
if (size <= 0xFD8) {
|
if (size <= 0xFD8) {
|
||||||
uint32_t adjusted_size = size + sizeof(X_POOL_ALLOC_HEADER);
|
uint32_t adjusted_size = size + sizeof(X_POOL_ALLOC_HEADER);
|
||||||
|
|
||||||
@@ -694,9 +694,9 @@ uint32_t xeAllocatePoolTypeWithTag(PPCContext* context, uint32_t size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
dword_result_t ExAllocatePoolTypeWithTag_entry(dword_t size, dword_t tag,
|
dword_result_t ExAllocatePoolTypeWithTag_entry(dword_t size, dword_t tag,
|
||||||
dword_t zero,
|
dword_t pool_selector,
|
||||||
const ppc_context_t& context) {
|
const ppc_context_t& context) {
|
||||||
return xeAllocatePoolTypeWithTag(context, size, tag, zero);
|
return xeAllocatePoolTypeWithTag(context, size, tag, pool_selector);
|
||||||
}
|
}
|
||||||
DECLARE_XBOXKRNL_EXPORT1(ExAllocatePoolTypeWithTag, kMemory, kImplemented);
|
DECLARE_XBOXKRNL_EXPORT1(ExAllocatePoolTypeWithTag, kMemory, kImplemented);
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ uint32_t xeMmAllocatePhysicalMemoryEx(uint32_t flags, uint32_t region_size,
|
|||||||
dword_result_t xeMmQueryStatistics(
|
dword_result_t xeMmQueryStatistics(
|
||||||
pointer_t<X_MM_QUERY_STATISTICS_RESULT> stats_ptr);
|
pointer_t<X_MM_QUERY_STATISTICS_RESULT> stats_ptr);
|
||||||
uint32_t xeAllocatePoolTypeWithTag(PPCContext* context, uint32_t size,
|
uint32_t xeAllocatePoolTypeWithTag(PPCContext* context, uint32_t size,
|
||||||
uint32_t tag, uint32_t zero);
|
uint32_t tag, uint32_t pool_selector);
|
||||||
|
|
||||||
void xeFreePool(PPCContext* context, uint32_t base_address);
|
void xeFreePool(PPCContext* context, uint32_t base_address);
|
||||||
|
|
||||||
|
|||||||
@@ -544,7 +544,7 @@ static_assert_size(X_RTL_CRITICAL_SECTION, 28);
|
|||||||
|
|
||||||
void xeRtlInitializeCriticalSection(X_RTL_CRITICAL_SECTION* cs,
|
void xeRtlInitializeCriticalSection(X_RTL_CRITICAL_SECTION* cs,
|
||||||
uint32_t cs_ptr) {
|
uint32_t cs_ptr) {
|
||||||
cs->header.type = 1; // EventSynchronizationObject (auto reset)
|
cs->header.type = X_DISPATCHER_FLAGS::DISPATCHER_AUTO_RESET_EVENT;
|
||||||
cs->header.absolute = 0; // spin count div 256
|
cs->header.absolute = 0; // spin count div 256
|
||||||
cs->header.signal_state = 0;
|
cs->header.signal_state = 0;
|
||||||
cs->lock_count = -1;
|
cs->lock_count = -1;
|
||||||
@@ -567,7 +567,7 @@ X_STATUS xeRtlInitializeCriticalSectionAndSpinCount(X_RTL_CRITICAL_SECTION* cs,
|
|||||||
spin_count_div_256 = 255;
|
spin_count_div_256 = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
cs->header.type = 1; // EventSynchronizationObject (auto reset)
|
cs->header.type = X_DISPATCHER_FLAGS::DISPATCHER_AUTO_RESET_EVENT;
|
||||||
cs->header.absolute = spin_count_div_256;
|
cs->header.absolute = spin_count_div_256;
|
||||||
cs->header.signal_state = 0;
|
cs->header.signal_state = 0;
|
||||||
cs->lock_count = -1;
|
cs->lock_count = -1;
|
||||||
|
|||||||
@@ -692,12 +692,12 @@ DECLARE_XBOXKRNL_EXPORT2(NtClearEvent, kThreading, kImplemented,
|
|||||||
// https://msdn.microsoft.com/en-us/library/windows/hardware/ff552150(v=vs.85).aspx
|
// https://msdn.microsoft.com/en-us/library/windows/hardware/ff552150(v=vs.85).aspx
|
||||||
void KeInitializeSemaphore_entry(pointer_t<X_KSEMAPHORE> semaphore_ptr,
|
void KeInitializeSemaphore_entry(pointer_t<X_KSEMAPHORE> semaphore_ptr,
|
||||||
dword_t count, dword_t limit) {
|
dword_t count, dword_t limit) {
|
||||||
semaphore_ptr->header.type = 5; // SemaphoreObject
|
semaphore_ptr->header.type = X_DISPATCHER_FLAGS::DISPATCHER_SEMAPHORE;
|
||||||
semaphore_ptr->header.signal_state = (uint32_t)count;
|
semaphore_ptr->header.signal_state = (uint32_t)count;
|
||||||
semaphore_ptr->limit = (uint32_t)limit;
|
semaphore_ptr->limit = (uint32_t)limit;
|
||||||
|
|
||||||
auto sem = XObject::GetNativeObject<XSemaphore>(kernel_state(), semaphore_ptr,
|
auto sem = XObject::GetNativeObject<XSemaphore>(
|
||||||
5 /* SemaphoreObject */);
|
kernel_state(), semaphore_ptr, X_DISPATCHER_FLAGS::DISPATCHER_SEMAPHORE);
|
||||||
if (!sem) {
|
if (!sem) {
|
||||||
assert_always();
|
assert_always();
|
||||||
return;
|
return;
|
||||||
@@ -1014,7 +1014,7 @@ dword_result_t KeWaitForMultipleObjects_entry(
|
|||||||
dword_t count, lpdword_t objects_ptr, dword_t wait_type,
|
dword_t count, lpdword_t objects_ptr, dword_t wait_type,
|
||||||
dword_t wait_reason, dword_t processor_mode, dword_t alertable,
|
dword_t wait_reason, dword_t processor_mode, dword_t alertable,
|
||||||
lpqword_t timeout_ptr, lpvoid_t wait_block_array_ptr) {
|
lpqword_t timeout_ptr, lpvoid_t wait_block_array_ptr) {
|
||||||
assert_true(wait_type <= 1);
|
assert_true(wait_type <= X_KWAIT_REASON::WaitAny);
|
||||||
|
|
||||||
assert_true(count <= 64);
|
assert_true(count <= 64);
|
||||||
object_ref<XObject> objects[64];
|
object_ref<XObject> objects[64];
|
||||||
@@ -1049,7 +1049,7 @@ uint32_t xeNtWaitForMultipleObjectsEx(uint32_t count, xe::be<uint32_t>* handles,
|
|||||||
uint32_t wait_type, uint32_t wait_mode,
|
uint32_t wait_type, uint32_t wait_mode,
|
||||||
uint32_t alertable,
|
uint32_t alertable,
|
||||||
uint64_t* timeout_ptr) {
|
uint64_t* timeout_ptr) {
|
||||||
assert_true(wait_type <= 1);
|
assert_true(wait_type <= X_KWAIT_REASON::WaitAny);
|
||||||
|
|
||||||
assert_true(count <= 64);
|
assert_true(count <= 64);
|
||||||
object_ref<XObject> objects[64];
|
object_ref<XObject> objects[64];
|
||||||
@@ -1091,7 +1091,8 @@ dword_result_t NtWaitForMultipleObjectsEx_entry(
|
|||||||
dword_t count, lpdword_t handles, dword_t wait_type, dword_t wait_mode,
|
dword_t count, lpdword_t handles, dword_t wait_type, dword_t wait_mode,
|
||||||
dword_t alertable, lpqword_t timeout_ptr) {
|
dword_t alertable, lpqword_t timeout_ptr) {
|
||||||
uint64_t timeout = timeout_ptr ? static_cast<uint64_t>(*timeout_ptr) : 0u;
|
uint64_t timeout = timeout_ptr ? static_cast<uint64_t>(*timeout_ptr) : 0u;
|
||||||
if (!count || count > 64 || (wait_type != 1 && wait_type)) {
|
if (!count || count > 64 ||
|
||||||
|
(wait_type != X_KWAIT_REASON::WaitAny && wait_type)) {
|
||||||
return X_STATUS_INVALID_PARAMETER;
|
return X_STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
return xeNtWaitForMultipleObjectsEx(count, handles, wait_type, wait_mode,
|
return xeNtWaitForMultipleObjectsEx(count, handles, wait_type, wait_mode,
|
||||||
@@ -1871,7 +1872,7 @@ dword_result_t KeSetPriorityThread_entry(pointer_t<X_KTHREAD> thread_ptr,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thread_ptr->header.type != 6) {
|
if (thread_ptr->header.type != X_DISPATCHER_FLAGS::DISPATCHER_THREAD) {
|
||||||
XELOGW("{}: Invalid object type: {}", __func__, thread_ptr->header.type);
|
XELOGW("{}: Invalid object type: {}", __func__, thread_ptr->header.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,10 +34,21 @@ class KernelState;
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
class object_ref;
|
class object_ref;
|
||||||
|
|
||||||
|
enum X_DISPATCHER_FLAGS : uint8_t {
|
||||||
|
DISPATCHER_MANUAL_RESET_EVENT = 0,
|
||||||
|
DISPATCHER_AUTO_RESET_EVENT = 1, // EventSynchronizationObject
|
||||||
|
DISPATCHER_MUTANT = 2,
|
||||||
|
DISPATCHER_QUEUE = 4,
|
||||||
|
DISPATCHER_SEMAPHORE = 5, // SemaphoreObject
|
||||||
|
DISPATCHER_THREAD = 6,
|
||||||
|
DISPATCHER_MANUAL_RESET_TIMER = 8,
|
||||||
|
DISPATCHER_AUTO_RESET_TIMER = 9,
|
||||||
|
};
|
||||||
|
|
||||||
// https://www.nirsoft.net/kernel_struct/vista/DISPATCHER_HEADER.html
|
// https://www.nirsoft.net/kernel_struct/vista/DISPATCHER_HEADER.html
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct {
|
struct {
|
||||||
uint8_t type;
|
uint8_t type; // X_DISPATCHER_FLAGS
|
||||||
|
|
||||||
union {
|
union {
|
||||||
uint8_t abandoned;
|
uint8_t abandoned;
|
||||||
|
|||||||
@@ -180,21 +180,25 @@ static uint8_t GetFakeCpuNumber(uint8_t proc_mask) {
|
|||||||
void XThread::InitializeGuestObject() {
|
void XThread::InitializeGuestObject() {
|
||||||
auto guest_thread = guest_object<X_KTHREAD>();
|
auto guest_thread = guest_object<X_KTHREAD>();
|
||||||
auto thread_guest_ptr = guest_object();
|
auto thread_guest_ptr = guest_object();
|
||||||
guest_thread->header.type = 6;
|
guest_thread->header.type = X_DISPATCHER_FLAGS::DISPATCHER_THREAD;
|
||||||
guest_thread->suspend_count =
|
guest_thread->suspend_count =
|
||||||
(creation_params_.creation_flags & X_CREATE_SUSPENDED) ? 1 : 0;
|
(creation_params_.creation_flags & X_CREATE_SUSPENDED) ? 1 : 0;
|
||||||
|
|
||||||
guest_thread->unk_10 = (thread_guest_ptr + 0x10);
|
guest_thread->mutants_list.flink_ptr = (thread_guest_ptr + 0x10);
|
||||||
guest_thread->unk_14 = (thread_guest_ptr + 0x10);
|
guest_thread->mutants_list.blink_ptr = (thread_guest_ptr + 0x10);
|
||||||
|
|
||||||
|
auto timer_wait_header_list_entry = memory()->HostToGuestVirtual(
|
||||||
|
&guest_thread->wait_timeout_timer.header.wait_list);
|
||||||
guest_thread->wait_timeout_block.wait_list_entry.flink_ptr =
|
guest_thread->wait_timeout_block.wait_list_entry.flink_ptr =
|
||||||
thread_guest_ptr + 0x20;
|
timer_wait_header_list_entry;
|
||||||
guest_thread->wait_timeout_block.wait_list_entry.blink_ptr =
|
guest_thread->wait_timeout_block.wait_list_entry.blink_ptr =
|
||||||
thread_guest_ptr + 0x20;
|
timer_wait_header_list_entry;
|
||||||
guest_thread->wait_timeout_block.thread = thread_guest_ptr;
|
guest_thread->wait_timeout_block.thread = thread_guest_ptr;
|
||||||
uint32_t v6 = thread_guest_ptr + 0x18;
|
guest_thread->wait_timeout_block.object =
|
||||||
guest_thread->wait_timeout_block.wait_result_xstatus = 0x0100;
|
memory()->HostToGuestVirtual(&guest_thread->wait_timeout_timer);
|
||||||
guest_thread->wait_timeout_block.wait_type = 0x0201;
|
guest_thread->wait_timeout_block.wait_result_xstatus = X_STATUS_TIMEOUT;
|
||||||
guest_thread->wait_timeout_block.object = v6;
|
guest_thread->wait_timeout_block.wait_type = X_KWAIT_REASON::WaitAny;
|
||||||
|
|
||||||
guest_thread->stack_base = (this->stack_base_);
|
guest_thread->stack_base = (this->stack_base_);
|
||||||
guest_thread->stack_limit = (this->stack_limit_);
|
guest_thread->stack_limit = (this->stack_limit_);
|
||||||
guest_thread->stack_kernel = (this->stack_base_ - 240);
|
guest_thread->stack_kernel = (this->stack_base_ - 240);
|
||||||
|
|||||||
@@ -48,17 +48,6 @@ enum IRQL_FLAGS : uint8_t {
|
|||||||
IRQL_HIGHEST = 124
|
IRQL_HIGHEST = 124
|
||||||
};
|
};
|
||||||
|
|
||||||
enum X_DISPATCHER_FLAGS {
|
|
||||||
DISPATCHER_MANUAL_RESET_EVENT = 0,
|
|
||||||
DISPATCHER_AUTO_RESET_EVENT = 1,
|
|
||||||
DISPATCHER_MUTANT = 2,
|
|
||||||
DISPATCHER_QUEUE = 4,
|
|
||||||
DISPATCHER_SEMAPHORE = 5,
|
|
||||||
DISPATCHER_THREAD = 6,
|
|
||||||
DISPATCHER_MANUAL_RESET_TIMER = 8,
|
|
||||||
DISPATCHER_AUTO_RESET_TIMER = 9,
|
|
||||||
};
|
|
||||||
|
|
||||||
// https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/ntos/ke/kthread_state.htm
|
// https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/ntos/ke/kthread_state.htm
|
||||||
enum X_KTHREAD_STATE_FLAGS : uint8_t {
|
enum X_KTHREAD_STATE_FLAGS : uint8_t {
|
||||||
KTHREAD_STATE_INITIALIZED = 0,
|
KTHREAD_STATE_INITIALIZED = 0,
|
||||||
@@ -222,12 +211,22 @@ struct X_KPCR {
|
|||||||
uint8_t unk_2AC[0x2C]; // 0x2AC
|
uint8_t unk_2AC[0x2C]; // 0x2AC
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef WAIT_ANY
|
struct X_KMUTANT {
|
||||||
#undef WAIT_ANY
|
X_DISPATCH_HEADER header; // 0x0
|
||||||
#endif
|
X_LIST_ENTRY unk_list; // 0x10
|
||||||
enum : uint16_t {
|
TypedGuestPointer<X_KTHREAD> owner; // 0x18
|
||||||
WAIT_ALL = 0,
|
bool abandoned; // 0x1C
|
||||||
WAIT_ANY = 1,
|
// these might just be padding
|
||||||
|
uint8_t unk_1D; // 0x1D
|
||||||
|
uint8_t unk_1E; // 0x1E
|
||||||
|
uint8_t unk_1F; // 0x1F
|
||||||
|
};
|
||||||
|
static_assert_size(X_KMUTANT, 0x20);
|
||||||
|
|
||||||
|
enum X_KWAIT_REASON : uint16_t {
|
||||||
|
WaitAll = 0,
|
||||||
|
WaitAny = 1,
|
||||||
|
WaitUnk3 = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
// https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/ntos/ke_x/kwait_block.htm
|
// https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/ntos/ke_x/kwait_block.htm
|
||||||
@@ -243,7 +242,7 @@ struct X_KWAIT_BLOCK {
|
|||||||
// is satisfied
|
// is satisfied
|
||||||
xe::be<uint16_t> wait_result_xstatus;
|
xe::be<uint16_t> wait_result_xstatus;
|
||||||
// WAIT_ALL or WAIT_ANY
|
// WAIT_ALL or WAIT_ANY
|
||||||
xe::be<uint16_t> wait_type;
|
xe::be<X_KWAIT_REASON> wait_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert_size(X_KWAIT_BLOCK, 0x18);
|
static_assert_size(X_KWAIT_BLOCK, 0x18);
|
||||||
@@ -258,9 +257,9 @@ struct X_KTIMER {
|
|||||||
static_assert_size(X_KTIMER, 0x28);
|
static_assert_size(X_KTIMER, 0x28);
|
||||||
|
|
||||||
struct X_KTHREAD {
|
struct X_KTHREAD {
|
||||||
X_DISPATCH_HEADER header; // 0x0
|
X_DISPATCH_HEADER header; // 0x0
|
||||||
xe::be<uint32_t> unk_10; // 0x10
|
util::X_TYPED_LIST<X_KMUTANT, offsetof(X_KMUTANT, unk_list)>
|
||||||
xe::be<uint32_t> unk_14; // 0x14
|
mutants_list; // 0x10
|
||||||
X_KTIMER wait_timeout_timer; // 0x18
|
X_KTIMER wait_timeout_timer; // 0x18
|
||||||
X_KWAIT_BLOCK wait_timeout_block; // 0x40
|
X_KWAIT_BLOCK wait_timeout_block; // 0x40
|
||||||
uint8_t unk_58[0x4]; // 0x58
|
uint8_t unk_58[0x4]; // 0x58
|
||||||
@@ -295,7 +294,11 @@ struct X_KTHREAD {
|
|||||||
xe::be<uint32_t> msr_mask; // 0x9C
|
xe::be<uint32_t> msr_mask; // 0x9C
|
||||||
xe::be<X_STATUS> wait_result; // 0xA0
|
xe::be<X_STATUS> wait_result; // 0xA0
|
||||||
uint8_t wait_irql; // 0xA4
|
uint8_t wait_irql; // 0xA4
|
||||||
uint8_t unk_A5[0xB]; // 0xA5
|
uint8_t processor_mode; // 0xA5
|
||||||
|
uint8_t wait_next; // 0xA6
|
||||||
|
uint8_t wait_reason; // 0xA7
|
||||||
|
TypedGuestPointer<X_KWAIT_BLOCK> wait_blocks; // 0xA8
|
||||||
|
uint8_t unk_AC[4]; // 0xAC
|
||||||
int32_t apc_disable_count; // 0xB0
|
int32_t apc_disable_count; // 0xB0
|
||||||
xe::be<int32_t> quantum; // 0xB4
|
xe::be<int32_t> quantum; // 0xB4
|
||||||
uint8_t saturation_increment; // 0xB8
|
uint8_t saturation_increment; // 0xB8
|
||||||
|
|||||||
Reference in New Issue
Block a user