[Kernel] Added usage of X_DISPATCHER_FLAGS

This commit is contained in:
Adrian
2026-07-28 21:35:07 +01:00
committed by Radosław Gliński
parent 2ddc5ef737
commit 1807da06db
10 changed files with 102 additions and 83 deletions

View File

@@ -700,8 +700,8 @@ dword_result_t XamSwapDisc_entry(
auto kevent = xboxkrnl::xeKeSetEvent(completion_handle, 1, 0); auto kevent = xboxkrnl::xeKeSetEvent(completion_handle, 1, 0);
// Release the completion handle // Release the completion handle
auto object = auto object = XObject::GetNativeObject<XEvent>(
XObject::GetNativeObject<XObject>(kernel_state(), completion_handle); kernel_state(), completion_handle, completion_handle->header.type);
if (object) { if (object) {
object->Retain(); object->Retain();
} }

View File

@@ -250,7 +250,8 @@ DECLARE_XBOXKRNL_EXPORT1(NtResumeThread, kThreading, kImplemented);
dword_result_t KeResumeThread_entry(pointer_t<X_KTHREAD> 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,
DISPATCHER_THREAD);
if (thread) { if (thread) {
result = thread->Resume(); result = thread->Resume();
} else { } else {
@@ -314,8 +315,8 @@ DECLARE_XBOXKRNL_EXPORT1(NtSuspendThread, kThreading, kImplemented);
dword_result_t KeSuspendThread_entry(pointer_t<X_KTHREAD> kthread, dword_result_t KeSuspendThread_entry(pointer_t<X_KTHREAD> kthread,
const ppc_context_t& context) { const ppc_context_t& context) {
auto thread = auto thread = XObject::GetNativeObject<XThread>(context->kernel_state,
XObject::GetNativeObject<XThread>(context->kernel_state, kthread); kthread, DISPATCHER_THREAD);
uint32_t suspend_count_out = 0; uint32_t suspend_count_out = 0;
if (thread) { if (thread) {
@@ -356,7 +357,8 @@ void KeSetCurrentStackPointers_entry(lpvoid_t stack_ptr,
DECLARE_XBOXKRNL_EXPORT2(KeSetCurrentStackPointers, kThreading, kImplemented, DECLARE_XBOXKRNL_EXPORT2(KeSetCurrentStackPointers, kThreading, kImplemented,
kHighFrequency); kHighFrequency);
dword_result_t KeSetAffinityThread_entry(lpvoid_t thread_ptr, dword_t affinity, dword_result_t KeSetAffinityThread_entry(pointer_t<X_KTHREAD> thread_ptr,
dword_t affinity,
lpdword_t previous_affinity_ptr) { lpdword_t previous_affinity_ptr) {
// The Xbox 360, according to disassembly of KeSetAffinityThread, unlike // The Xbox 360, according to disassembly of KeSetAffinityThread, unlike
// Windows NT, stores the previous affinity via the pointer provided as an // Windows NT, stores the previous affinity via the pointer provided as an
@@ -365,7 +367,8 @@ dword_result_t KeSetAffinityThread_entry(lpvoid_t thread_ptr, dword_t affinity,
if (!affinity) { if (!affinity) {
return X_STATUS_INVALID_PARAMETER; return X_STATUS_INVALID_PARAMETER;
} }
auto thread = XObject::GetNativeObject<XThread>(kernel_state(), thread_ptr); auto thread = XObject::GetNativeObject<XThread>(kernel_state(), thread_ptr,
DISPATCHER_THREAD);
if (!thread) { if (!thread) {
XELOGW( XELOGW(
"KeSetAffinityThread: guest thread pointer {:08X} did not resolve to " "KeSetAffinityThread: guest thread pointer {:08X} did not resolve to "
@@ -381,10 +384,12 @@ dword_result_t KeSetAffinityThread_entry(lpvoid_t thread_ptr, dword_t affinity,
} }
DECLARE_XBOXKRNL_EXPORT1(KeSetAffinityThread, kThreading, kImplemented); DECLARE_XBOXKRNL_EXPORT1(KeSetAffinityThread, kThreading, kImplemented);
dword_result_t KeQueryBasePriorityThread_entry(lpvoid_t thread_ptr) { dword_result_t KeQueryBasePriorityThread_entry(
pointer_t<X_KTHREAD> thread_ptr) {
int32_t priority = 0; int32_t priority = 0;
auto thread = XObject::GetNativeObject<XThread>(kernel_state(), thread_ptr); auto thread = XObject::GetNativeObject<XThread>(kernel_state(), thread_ptr,
DISPATCHER_THREAD);
if (thread) { if (thread) {
priority = thread->QueryPriority(); priority = thread->QueryPriority();
} }
@@ -393,10 +398,11 @@ dword_result_t KeQueryBasePriorityThread_entry(lpvoid_t thread_ptr) {
} }
DECLARE_XBOXKRNL_EXPORT1(KeQueryBasePriorityThread, kThreading, kImplemented); DECLARE_XBOXKRNL_EXPORT1(KeQueryBasePriorityThread, kThreading, kImplemented);
dword_result_t KeSetBasePriorityThread_entry(lpvoid_t thread_ptr, dword_result_t KeSetBasePriorityThread_entry(pointer_t<X_KTHREAD> thread_ptr,
dword_t increment) { dword_t increment) {
int32_t prev_priority = 0; int32_t prev_priority = 0;
auto thread = XObject::GetNativeObject<XThread>(kernel_state(), thread_ptr); auto thread = XObject::GetNativeObject<XThread>(kernel_state(), thread_ptr,
DISPATCHER_THREAD);
if (thread) { if (thread) {
prev_priority = thread->QueryPriority(); prev_priority = thread->QueryPriority();
@@ -559,10 +565,10 @@ DECLARE_XBOXKRNL_EXPORT1(KeTlsSetValue, kThreading, kImplemented);
void KeInitializeEvent_entry(pointer_t<X_KEVENT> event_ptr, dword_t event_type, void KeInitializeEvent_entry(pointer_t<X_KEVENT> event_ptr, dword_t event_type,
dword_t initial_state) { dword_t initial_state) {
event_ptr.Zero(); event_ptr.Zero();
event_ptr->header.type = event_type; event_ptr->header.type = static_cast<X_DISPATCHER_FLAGS>(event_type.value());
event_ptr->header.signal_state = (uint32_t)initial_state; event_ptr->header.signal_state = initial_state.value();
auto ev = auto ev = XObject::GetNativeObject<XEvent>(kernel_state(), event_ptr,
XObject::GetNativeObject<XEvent>(kernel_state(), event_ptr, event_type); event_ptr->header.type);
if (!ev) { if (!ev) {
assert_always(); assert_always();
return; return;
@@ -571,7 +577,8 @@ void KeInitializeEvent_entry(pointer_t<X_KEVENT> event_ptr, dword_t event_type,
DECLARE_XBOXKRNL_EXPORT1(KeInitializeEvent, kThreading, kImplemented); DECLARE_XBOXKRNL_EXPORT1(KeInitializeEvent, kThreading, kImplemented);
uint32_t xeKeSetEvent(X_KEVENT* event_ptr, uint32_t increment, uint32_t wait) { uint32_t xeKeSetEvent(X_KEVENT* event_ptr, uint32_t increment, uint32_t wait) {
auto ev = XObject::GetNativeObject<XEvent>(kernel_state(), event_ptr); auto ev = XObject::GetNativeObject<XEvent>(kernel_state(), event_ptr,
event_ptr->header.type);
if (!ev) { if (!ev) {
assert_always(); assert_always();
return 0; return 0;
@@ -588,7 +595,8 @@ DECLARE_XBOXKRNL_EXPORT2(KeSetEvent, kThreading, kImplemented, kHighFrequency);
dword_result_t KePulseEvent_entry(pointer_t<X_KEVENT> event_ptr, dword_result_t KePulseEvent_entry(pointer_t<X_KEVENT> event_ptr,
dword_t increment, dword_t wait) { dword_t increment, dword_t wait) {
auto ev = XObject::GetNativeObject<XEvent>(kernel_state(), event_ptr); auto ev = XObject::GetNativeObject<XEvent>(kernel_state(), event_ptr,
event_ptr->header.type);
if (!ev) { if (!ev) {
assert_always(); assert_always();
return 0; return 0;
@@ -600,7 +608,8 @@ DECLARE_XBOXKRNL_EXPORT2(KePulseEvent, kThreading, kImplemented,
kHighFrequency); kHighFrequency);
dword_result_t KeResetEvent_entry(pointer_t<X_KEVENT> event_ptr) { dword_result_t KeResetEvent_entry(pointer_t<X_KEVENT> event_ptr) {
auto ev = XObject::GetNativeObject<XEvent>(kernel_state(), event_ptr); auto ev = XObject::GetNativeObject<XEvent>(kernel_state(), event_ptr,
event_ptr->header.type);
if (!ev) { if (!ev) {
assert_always(); assert_always();
return 0; return 0;
@@ -727,12 +736,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 = X_DISPATCHER_FLAGS::DISPATCHER_SEMAPHORE; semaphore_ptr->header.type = 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>( auto sem = XObject::GetNativeObject<XSemaphore>(kernel_state(), semaphore_ptr,
kernel_state(), semaphore_ptr, X_DISPATCHER_FLAGS::DISPATCHER_SEMAPHORE); DISPATCHER_SEMAPHORE);
if (!sem) { if (!sem) {
assert_always(); assert_always();
return; return;
@@ -742,8 +751,8 @@ DECLARE_XBOXKRNL_EXPORT1(KeInitializeSemaphore, kThreading, kImplemented);
uint32_t xeKeReleaseSemaphore(X_KSEMAPHORE* semaphore_ptr, uint32_t increment, uint32_t xeKeReleaseSemaphore(X_KSEMAPHORE* semaphore_ptr, uint32_t increment,
uint32_t adjustment, uint32_t wait) { uint32_t adjustment, uint32_t wait) {
auto sem = auto sem = XObject::GetNativeObject<XSemaphore>(kernel_state(), semaphore_ptr,
XObject::GetNativeObject<XSemaphore>(kernel_state(), semaphore_ptr); DISPATCHER_SEMAPHORE);
if (!sem) { if (!sem) {
assert_always(); assert_always();
return 0; return 0;
@@ -1057,8 +1066,8 @@ dword_result_t KeWaitForMultipleObjects_entry(
auto crit = global_critical_region::AcquireDirect(); auto crit = global_critical_region::AcquireDirect();
for (uint32_t n = 0; n < count; n++) { for (uint32_t n = 0; n < count; n++) {
auto object_ptr = kernel_memory()->TranslateVirtual(objects_ptr[n]); auto object_ptr = kernel_memory()->TranslateVirtual(objects_ptr[n]);
auto object_ref = XObject::GetNativeObject<XObject>(kernel_state(), auto object_ref = XObject::GetNativeObject<XObject>(
object_ptr, -1, true); kernel_state(), object_ptr, DISPATCHER_UNDEFINED, true);
if (!object_ref) { if (!object_ref) {
return X_STATUS_INVALID_PARAMETER; return X_STATUS_INVALID_PARAMETER;
} }
@@ -1907,19 +1916,21 @@ dword_result_t KeSetPriorityThread_entry(pointer_t<X_KTHREAD> thread_ptr,
return 0; return 0;
} }
if (thread_ptr->header.type != X_DISPATCHER_FLAGS::DISPATCHER_THREAD) { if (thread_ptr->header.type != DISPATCHER_THREAD) {
XELOGW("{}: Invalid object type: {}", __func__, thread_ptr->header.type); XELOGW("{}: Invalid object type: {}", __func__,
static_cast<uint8_t>(thread_ptr->header.type));
} }
X_KPRCB* prcb = context->TranslateVirtual(thread_ptr->a_prcb_ptr); X_KPRCB* prcb = context->TranslateVirtual(thread_ptr->a_prcb_ptr);
const uint32_t old_irql = xeKeKfAcquireSpinLock(context, &prcb->spin_lock); const uint32_t old_irql = xeKeKfAcquireSpinLock(context, &prcb->spin_lock);
const uint8_t old_priority = thread_ptr->priority; const uint8_t old_priority = thread_ptr->priority;
auto thread_ref = auto thread_ref = XObject::GetNativeObject<XThread>(
XObject::GetNativeObject<XThread>(kernel_state(), thread_ptr); kernel_state(), thread_ptr, DISPATCHER_THREAD);
if (!thread_ref) { if (!thread_ref) {
XELOGW("{}: Missing native thread: {}", __func__, thread_ptr->header.type); XELOGW("{}: Missing native thread: {}", __func__,
static_cast<uint8_t>(thread_ptr->header.type));
} else { } else {
thread_ref->SetPriority(new_priority); thread_ref->SetPriority(new_priority);
} }
@@ -1937,7 +1948,8 @@ void xeKeInitializeTimerEx(X_KTIMER* timer, uint32_t type, uint32_t proctype,
// initialize // initialize
timer->header.process_type = proctype; timer->header.process_type = proctype;
timer->header.inserted = 0; timer->header.inserted = 0;
timer->header.type = type + 8; timer->header.type =
type ? DISPATCHER_AUTO_RESET_TIMER : DISPATCHER_MANUAL_RESET_TIMER;
timer->header.signal_state = 0; timer->header.signal_state = 0;
util::XeInitializeListHead(&timer->header.wait_list, context); util::XeInitializeListHead(&timer->header.wait_list, context);
timer->due_time = 0; timer->due_time = 0;

View File

@@ -23,7 +23,7 @@ XEvent::~XEvent() = default;
void XEvent::Initialize(bool manual_reset, bool initial_state) { void XEvent::Initialize(bool manual_reset, bool initial_state) {
assert_false(event_); assert_false(event_);
this->CreateNative<X_KEVENT>(); CreateNative<X_KEVENT>();
if (manual_reset) { if (manual_reset) {
event_ = xe::threading::Event::CreateManualResetEvent(initial_state); event_ = xe::threading::Event::CreateManualResetEvent(initial_state);
@@ -33,14 +33,15 @@ void XEvent::Initialize(bool manual_reset, bool initial_state) {
assert_not_null(event_); assert_not_null(event_);
} }
void XEvent::InitializeNative(void* native_ptr, X_DISPATCH_HEADER* header) { void XEvent::InitializeNative(void* native_ptr,
const X_DISPATCH_HEADER* header) {
assert_false(event_); assert_false(event_);
switch (header->type) { switch (header->type) {
case 0x00: // EventNotificationObject (manual reset) case X_DISPATCHER_FLAGS::DISPATCHER_MANUAL_RESET_EVENT:
manual_reset_ = true; manual_reset_ = true;
break; break;
case 0x01: // EventSynchronizationObject (auto reset) case X_DISPATCHER_FLAGS::DISPATCHER_AUTO_RESET_EVENT:
manual_reset_ = false; manual_reset_ = false;
break; break;
default: default:

View File

@@ -31,7 +31,7 @@ class XEvent : public XObject {
~XEvent() override; ~XEvent() override;
void Initialize(bool manual_reset, bool initial_state); void Initialize(bool manual_reset, bool initial_state);
void InitializeNative(void* native_ptr, X_DISPATCH_HEADER* header); void InitializeNative(void* native_ptr, const X_DISPATCH_HEADER* header);
int32_t Set(uint32_t priority_increment, bool wait); int32_t Set(uint32_t priority_increment, bool wait);
int32_t Pulse(uint32_t priority_increment, bool wait); int32_t Pulse(uint32_t priority_increment, bool wait);

View File

@@ -31,7 +31,8 @@ void XMutant::Initialize(bool initial_owner) {
assert_not_null(mutant_); assert_not_null(mutant_);
} }
void XMutant::InitializeNative(void* native_ptr, X_DISPATCH_HEADER* header) { void XMutant::InitializeNative(void* native_ptr,
const X_DISPATCH_HEADER* header) {
assert_false(mutant_); assert_false(mutant_);
// Haven't seen this yet, but it's possible. // Haven't seen this yet, but it's possible.

View File

@@ -28,7 +28,7 @@ class XMutant : public XObject {
~XMutant() override; ~XMutant() override;
void Initialize(bool initial_owner); void Initialize(bool initial_owner);
void InitializeNative(void* native_ptr, X_DISPATCH_HEADER* header); void InitializeNative(void* native_ptr, const X_DISPATCH_HEADER* header);
X_STATUS ReleaseMutant(uint32_t priority_increment, bool abandon, bool wait); X_STATUS ReleaseMutant(uint32_t priority_increment, bool abandon, bool wait);

View File

@@ -395,7 +395,8 @@ void XObject::SetNativePointer(uint32_t native_ptr, bool uninitialized) {
} }
object_ref<XObject> XObject::GetNativeObject(KernelState* kernel_state, object_ref<XObject> XObject::GetNativeObject(KernelState* kernel_state,
void* native_ptr, int32_t as_type, void* native_ptr,
X_DISPATCHER_FLAGS as_type,
bool already_locked) { bool already_locked) {
assert_not_null(native_ptr); assert_not_null(native_ptr);
@@ -411,11 +412,13 @@ object_ref<XObject> XObject::GetNativeObject(KernelState* kernel_state,
global_critical_region::mutex().lock(); global_critical_region::mutex().lock();
} }
XObject* result; XObject* result = nullptr;
auto header = reinterpret_cast<X_DISPATCH_HEADER*>(native_ptr); auto header = reinterpret_cast<X_DISPATCH_HEADER*>(native_ptr);
if (as_type == -1) { X_DISPATCHER_FLAGS type = X_DISPATCHER_FLAGS::DISPATCHER_UNDEFINED;
as_type = header->type;
if (as_type == X_DISPATCHER_FLAGS::DISPATCHER_UNDEFINED) {
type = header->type;
} }
if (header->wait_list.flink_ptr == kXObjSignature) { if (header->wait_list.flink_ptr == kXObjSignature) {
@@ -428,28 +431,24 @@ object_ref<XObject> XObject::GetNativeObject(KernelState* kernel_state,
} else { } else {
// First use, create new. // First use, create new.
// https://www.nirsoft.net/kernel_struct/vista/KOBJECTS.html // https://www.nirsoft.net/kernel_struct/vista/KOBJECTS.html
XObject* object = nullptr; switch (type) {
switch (as_type) { case X_DISPATCHER_FLAGS::DISPATCHER_MANUAL_RESET_EVENT:
case 0: // EventNotificationObject case X_DISPATCHER_FLAGS::DISPATCHER_AUTO_RESET_EVENT: {
case 1: // EventSynchronizationObject
{
auto ev = new XEvent(kernel_state); auto ev = new XEvent(kernel_state);
ev->InitializeNative(native_ptr, header); ev->InitializeNative(native_ptr, header);
object = ev; result = ev;
} break; } break;
case 2: // MutantObject case X_DISPATCHER_FLAGS::DISPATCHER_MUTANT: {
{
auto mutant = new XMutant(kernel_state); auto mutant = new XMutant(kernel_state);
mutant->InitializeNative(native_ptr, header); mutant->InitializeNative(native_ptr, header);
object = mutant; result = mutant;
} break; } break;
case 5: // SemaphoreObject case X_DISPATCHER_FLAGS::DISPATCHER_SEMAPHORE: {
{
auto sem = new XSemaphore(kernel_state); auto sem = new XSemaphore(kernel_state);
auto success = sem->InitializeNative(native_ptr, header); auto success = sem->InitializeNative(native_ptr, header);
// Can't report failure to the guest at late initialization: // Can't report failure to the guest at late initialization:
assert_true(success); assert_true(success);
object = sem; result = sem;
} break; } break;
case 3: // ProcessObject case 3: // ProcessObject
case 4: // QueueObject case 4: // QueueObject
@@ -470,10 +469,9 @@ object_ref<XObject> XObject::GetNativeObject(KernelState* kernel_state,
} }
// Stash pointer in struct. // Stash pointer in struct.
// FIXME: This assumes the object contains a dispatch header (some don't!) // FIXME: This assumes the object contains a dispatch header (some don't!)
if (object) { if (result) {
StashHandle(header, object->handle()); StashHandle(header, result->handle());
} }
result = object;
} }
if (!already_locked) { if (!already_locked) {

View File

@@ -35,20 +35,21 @@ template <typename T>
class object_ref; class object_ref;
enum X_DISPATCHER_FLAGS : uint8_t { enum X_DISPATCHER_FLAGS : uint8_t {
DISPATCHER_MANUAL_RESET_EVENT = 0, DISPATCHER_MANUAL_RESET_EVENT = 0, // EventNotificationObject
DISPATCHER_AUTO_RESET_EVENT = 1, // EventSynchronizationObject DISPATCHER_AUTO_RESET_EVENT = 1, // EventSynchronizationObject
DISPATCHER_MUTANT = 2, DISPATCHER_MUTANT = 2, // MutantObject
DISPATCHER_QUEUE = 4, DISPATCHER_QUEUE = 4,
DISPATCHER_SEMAPHORE = 5, // SemaphoreObject DISPATCHER_SEMAPHORE = 5, // SemaphoreObject
DISPATCHER_THREAD = 6, DISPATCHER_THREAD = 6,
DISPATCHER_MANUAL_RESET_TIMER = 8, DISPATCHER_MANUAL_RESET_TIMER = 8,
DISPATCHER_AUTO_RESET_TIMER = 9, DISPATCHER_AUTO_RESET_TIMER = 9,
DISPATCHER_UNDEFINED = 0xFF,
}; };
// 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; // X_DISPATCHER_FLAGS X_DISPATCHER_FLAGS type;
union { union {
uint8_t abandoned; uint8_t abandoned;
@@ -149,27 +150,30 @@ class XObject {
default: default:
return false; return false;
} }
return false;
} }
static Type MapGuestTypeToHost(uint16_t type) { static Type MapGuestTypeToHost(X_DISPATCHER_FLAGS flag) {
// todo: this is not fully filled in // TODO: This is not fully filled in.
switch (type) { switch (flag) {
case 0: case X_DISPATCHER_FLAGS::DISPATCHER_MANUAL_RESET_EVENT:
case 1: case X_DISPATCHER_FLAGS::DISPATCHER_AUTO_RESET_EVENT:
return Type::Event; return Type::Event;
case 2:
return Type::Mutant; return Type::Mutant;
case 5: case X_DISPATCHER_FLAGS::DISPATCHER_MUTANT:
return Type::Mutant;
case X_DISPATCHER_FLAGS::DISPATCHER_SEMAPHORE:
return Type::Semaphore; return Type::Semaphore;
case 6: case X_DISPATCHER_FLAGS::DISPATCHER_THREAD:
return Type::Thread; return Type::Thread;
case 8: case X_DISPATCHER_FLAGS::DISPATCHER_MANUAL_RESET_TIMER:
case 9: case X_DISPATCHER_FLAGS::DISPATCHER_AUTO_RESET_TIMER:
return Type::Timer; return Type::Timer;
default:
return Type::Undefined;
// assert_always();
} }
return Type::Undefined;
} }
XObject(Type type); XObject(Type type);
XObject(KernelState* kernel_state, Type type, bool host_object = false); XObject(KernelState* kernel_state, Type type, bool host_object = false);
virtual ~XObject(); virtual ~XObject();
@@ -228,14 +232,15 @@ class XObject {
uint32_t processor_mode, uint32_t alertable, uint32_t processor_mode, uint32_t alertable,
uint64_t* opt_timeout); uint64_t* opt_timeout);
static object_ref<XObject> GetNativeObject(KernelState* kernel_state, static object_ref<XObject> GetNativeObject(
void* native_ptr, KernelState* kernel_state, void* native_ptr,
int32_t as_type = -1, X_DISPATCHER_FLAGS as_type = DISPATCHER_UNDEFINED,
bool already_locked = false); bool already_locked = false);
template <typename T> template <typename T>
static object_ref<T> GetNativeObject(KernelState* kernel_state, static object_ref<T> GetNativeObject(
void* native_ptr, int32_t as_type = -1, KernelState* kernel_state, void* native_ptr,
bool already_locked = false); X_DISPATCHER_FLAGS as_type = DISPATCHER_UNDEFINED,
bool already_locked = false);
// Priority increment stored by the most recent signal operation // Priority increment stored by the most recent signal operation
// (KeSetEvent, KeReleaseSemaphore, etc.). Read by the waiter on wake // (KeSetEvent, KeReleaseSemaphore, etc.). Read by the waiter on wake
@@ -418,7 +423,8 @@ object_ref<T> retain_object(T* ptr) {
template <typename T> template <typename T>
object_ref<T> XObject::GetNativeObject(KernelState* kernel_state, object_ref<T> XObject::GetNativeObject(KernelState* kernel_state,
void* native_ptr, int32_t as_type, void* native_ptr,
X_DISPATCHER_FLAGS as_type,
bool already_locked) { bool already_locked) {
return object_ref<T>(reinterpret_cast<T*>( return object_ref<T>(reinterpret_cast<T*>(
GetNativeObject(kernel_state, native_ptr, as_type, already_locked) GetNativeObject(kernel_state, native_ptr, as_type, already_locked)

View File

@@ -30,7 +30,8 @@ bool XSemaphore::Initialize(int32_t initial_count, int32_t maximum_count) {
return !!semaphore_; return !!semaphore_;
} }
bool XSemaphore::InitializeNative(void* native_ptr, X_DISPATCH_HEADER* header) { bool XSemaphore::InitializeNative(void* native_ptr,
const X_DISPATCH_HEADER* header) {
assert_false(semaphore_); assert_false(semaphore_);
auto semaphore = reinterpret_cast<X_KSEMAPHORE*>(native_ptr); auto semaphore = reinterpret_cast<X_KSEMAPHORE*>(native_ptr);

View File

@@ -27,7 +27,7 @@ class XSemaphore : public XObject {
[[nodiscard]] bool Initialize(int32_t initial_count, int32_t maximum_count); [[nodiscard]] bool Initialize(int32_t initial_count, int32_t maximum_count);
[[nodiscard]] bool InitializeNative(void* native_ptr, [[nodiscard]] bool InitializeNative(void* native_ptr,
X_DISPATCH_HEADER* header); const X_DISPATCH_HEADER* header);
[[nodiscard]] bool ReleaseSemaphore(int32_t release_count, [[nodiscard]] bool ReleaseSemaphore(int32_t release_count,
int32_t* out_previous_count); int32_t* out_previous_count);