[Kernel] Added usage of X_DISPATCHER_FLAGS
This commit is contained in:
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user