[Kernel] add object type stub functions, export object types
This commit is contained in:
parent
6a08208dc8
commit
9b3601c6fa
|
@ -22,7 +22,9 @@
|
|||
#include "xenia/kernel/user_module.h"
|
||||
#include "xenia/kernel/util/shim_utils.h"
|
||||
#include "xenia/kernel/xam/xam_module.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_memory.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_module.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_ob.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_threading.h"
|
||||
#include "xenia/kernel/xevent.h"
|
||||
#include "xenia/kernel/xmodule.h"
|
||||
|
@ -48,7 +50,10 @@ KernelState::KernelState(Emulator* emulator)
|
|||
: emulator_(emulator),
|
||||
memory_(emulator->memory()),
|
||||
dispatch_thread_running_(false),
|
||||
dpc_list_(emulator->memory()) {
|
||||
dpc_list_(emulator->memory()),
|
||||
kernel_trampoline_group_(emulator->processor()->backend()) {
|
||||
assert_null(shared_kernel_state_);
|
||||
shared_kernel_state_ = this;
|
||||
processor_ = emulator->processor();
|
||||
file_system_ = emulator->file_system();
|
||||
|
||||
|
@ -64,9 +69,6 @@ KernelState::KernelState(Emulator* emulator)
|
|||
}
|
||||
content_manager_ = std::make_unique<xam::ContentManager>(this, content_root);
|
||||
|
||||
assert_null(shared_kernel_state_);
|
||||
shared_kernel_state_ = this;
|
||||
|
||||
// Hardcoded maximum of 2048 TLS slots.
|
||||
tls_bitmap_.Resize(2048);
|
||||
|
||||
|
@ -1148,6 +1150,64 @@ void KernelState::SetProcessTLSVars(X_KPROCESS* process, int num_slots,
|
|||
if (((num_slots + 3) & 0x1C) != 0)
|
||||
process->bitmap[count_div32] = -1 << (32 - ((num_slots + 3) & 0x1C));
|
||||
}
|
||||
void AllocateThread(PPCContext* context) {
|
||||
uint32_t thread_mem_size = static_cast<uint32_t>(context->r[3]);
|
||||
uint32_t a2 = static_cast<uint32_t>(context->r[4]);
|
||||
uint32_t a3 = static_cast<uint32_t>(context->r[5]);
|
||||
if (thread_mem_size <= 0xFD8) thread_mem_size += 8;
|
||||
uint32_t result =
|
||||
xboxkrnl::xeAllocatePoolTypeWithTag(context, thread_mem_size, a2, a3);
|
||||
if (((unsigned short)result & 0xFFF) != 0) {
|
||||
result += 2;
|
||||
}
|
||||
|
||||
context->r[3] = static_cast<uint64_t>(result);
|
||||
}
|
||||
void FreeThread(PPCContext* context) {
|
||||
uint32_t thread_memory = static_cast<uint32_t>(context->r[3]);
|
||||
if ((thread_memory & 0xFFF) != 0) {
|
||||
thread_memory -= 8;
|
||||
}
|
||||
xboxkrnl::xeFreePool(context, thread_memory);
|
||||
}
|
||||
|
||||
void SimpleForwardAllocatePoolTypeWithTag(PPCContext* context) {
|
||||
uint32_t a1 = static_cast<uint32_t>(context->r[3]);
|
||||
uint32_t a2 = static_cast<uint32_t>(context->r[4]);
|
||||
uint32_t a3 = static_cast<uint32_t>(context->r[5]);
|
||||
context->r[3] = static_cast<uint64_t>(
|
||||
xboxkrnl::xeAllocatePoolTypeWithTag(context, a1, a2, a3));
|
||||
}
|
||||
void SimpleForwardFreePool(PPCContext* context) {
|
||||
xboxkrnl::xeFreePool(context, static_cast<uint32_t>(context->r[3]));
|
||||
}
|
||||
|
||||
void DeleteMutant(PPCContext* context) {
|
||||
// todo: this should call kereleasemutant with some specific args
|
||||
|
||||
xe::FatalError("DeleteMutant - need KeReleaseMutant(mutant, 1, 1, 0) ");
|
||||
}
|
||||
void DeleteTimer(PPCContext* context) {
|
||||
// todo: this should call KeCancelTimer
|
||||
xe::FatalError("DeleteTimer - need KeCancelTimer(mutant, 1, 1, 0) ");
|
||||
}
|
||||
|
||||
void DeleteIoCompletion(PPCContext* context) {}
|
||||
|
||||
void UnknownProcIoDevice(PPCContext* context) {}
|
||||
|
||||
void CloseFileProc(PPCContext* context) {}
|
||||
|
||||
void DeleteFileProc(PPCContext* context) {}
|
||||
|
||||
void UnknownFileProc(PPCContext* context) {}
|
||||
|
||||
void DeleteSymlink(PPCContext* context) {
|
||||
X_KSYMLINK* lnk = context->TranslateVirtualGPR<X_KSYMLINK*>(context->r[3]);
|
||||
|
||||
context->r[3] = lnk->refed_object_maybe;
|
||||
xboxkrnl::xeObDereferenceObject(context, lnk->refed_object_maybe);
|
||||
}
|
||||
void KernelState::InitializeKernelGuestGlobals() {
|
||||
kernel_guest_globals_ = memory_->SystemHeapAlloc(sizeof(KernelGuestGlobals));
|
||||
|
||||
|
@ -1162,6 +1222,120 @@ void KernelState::InitializeKernelGuestGlobals() {
|
|||
memory()->TranslateVirtual<X_KPROCESS*>(GetSystemProcess());
|
||||
InitializeProcess(system_process, X_PROCTYPE_SYSTEM, 2, 5, 9);
|
||||
SetProcessTLSVars(system_process, 32, 0, 0);
|
||||
|
||||
uint32_t oddobject_offset =
|
||||
kernel_guest_globals_ + offsetof(KernelGuestGlobals, OddObj);
|
||||
|
||||
// init unknown object
|
||||
|
||||
block->OddObj.field0 = 0x1000000;
|
||||
block->OddObj.field4 = 1;
|
||||
block->OddObj.points_to_self =
|
||||
oddobject_offset + offsetof(X_UNKNOWN_TYPE_REFED, points_to_self);
|
||||
block->OddObj.points_to_prior = block->OddObj.points_to_self;
|
||||
|
||||
// init thread object
|
||||
block->ExThreadObjectType.pool_tag = 0x65726854;
|
||||
block->ExThreadObjectType.allocate_proc =
|
||||
kernel_trampoline_group_.NewLongtermTrampoline(AllocateThread);
|
||||
|
||||
block->ExThreadObjectType.free_proc =
|
||||
kernel_trampoline_group_.NewLongtermTrampoline(FreeThread);
|
||||
|
||||
// several object types just call freepool/allocatepool
|
||||
uint32_t trampoline_allocatepool =
|
||||
kernel_trampoline_group_.NewLongtermTrampoline(
|
||||
SimpleForwardAllocatePoolTypeWithTag);
|
||||
uint32_t trampoline_freepool =
|
||||
kernel_trampoline_group_.NewLongtermTrampoline(SimpleForwardFreePool);
|
||||
|
||||
// init event object
|
||||
block->ExEventObjectType.pool_tag = 0x76657645;
|
||||
block->ExEventObjectType.allocate_proc = trampoline_allocatepool;
|
||||
block->ExEventObjectType.free_proc = trampoline_freepool;
|
||||
|
||||
// init mutant object
|
||||
block->ExMutantObjectType.pool_tag = 0x6174754D;
|
||||
block->ExMutantObjectType.allocate_proc = trampoline_allocatepool;
|
||||
block->ExMutantObjectType.free_proc = trampoline_freepool;
|
||||
|
||||
block->ExMutantObjectType.delete_proc =
|
||||
kernel_trampoline_group_.NewLongtermTrampoline(DeleteMutant);
|
||||
// init semaphore obj
|
||||
block->ExSemaphoreObjectType.pool_tag = 0x616D6553;
|
||||
block->ExSemaphoreObjectType.allocate_proc = trampoline_allocatepool;
|
||||
block->ExSemaphoreObjectType.free_proc = trampoline_freepool;
|
||||
// init timer obj
|
||||
block->ExTimerObjectType.pool_tag = 0x656D6954;
|
||||
block->ExTimerObjectType.allocate_proc = trampoline_allocatepool;
|
||||
block->ExTimerObjectType.free_proc = trampoline_freepool;
|
||||
block->ExTimerObjectType.delete_proc =
|
||||
kernel_trampoline_group_.NewLongtermTrampoline(DeleteTimer);
|
||||
// iocompletion object
|
||||
block->IoCompletionObjectType.pool_tag = 0x706D6F43;
|
||||
block->IoCompletionObjectType.allocate_proc = trampoline_allocatepool;
|
||||
block->IoCompletionObjectType.free_proc = trampoline_freepool;
|
||||
block->IoCompletionObjectType.delete_proc =
|
||||
kernel_trampoline_group_.NewLongtermTrampoline(DeleteIoCompletion);
|
||||
block->IoCompletionObjectType.unknown_size_or_object_ = oddobject_offset;
|
||||
|
||||
// iodevice object
|
||||
block->IoDeviceObjectType.pool_tag = 0x69766544;
|
||||
block->IoDeviceObjectType.allocate_proc = trampoline_allocatepool;
|
||||
block->IoDeviceObjectType.free_proc = trampoline_freepool;
|
||||
block->IoDeviceObjectType.unknown_size_or_object_ = oddobject_offset;
|
||||
block->IoDeviceObjectType.unknown_proc =
|
||||
kernel_trampoline_group_.NewLongtermTrampoline(UnknownProcIoDevice);
|
||||
|
||||
// file object
|
||||
block->IoFileObjectType.pool_tag = 0x656C6946;
|
||||
block->IoFileObjectType.allocate_proc = trampoline_allocatepool;
|
||||
block->IoFileObjectType.free_proc = trampoline_freepool;
|
||||
block->IoFileObjectType.unknown_size_or_object_ =
|
||||
0x38; // sizeof fileobject, i believe
|
||||
block->IoFileObjectType.close_proc =
|
||||
kernel_trampoline_group_.NewLongtermTrampoline(CloseFileProc);
|
||||
block->IoFileObjectType.delete_proc =
|
||||
kernel_trampoline_group_.NewLongtermTrampoline(DeleteFileProc);
|
||||
block->IoFileObjectType.unknown_proc =
|
||||
kernel_trampoline_group_.NewLongtermTrampoline(UnknownFileProc);
|
||||
|
||||
// directory object
|
||||
block->ObDirectoryObjectType.pool_tag = 0x65726944;
|
||||
block->ObDirectoryObjectType.allocate_proc = trampoline_allocatepool;
|
||||
block->ObDirectoryObjectType.free_proc = trampoline_freepool;
|
||||
block->ObDirectoryObjectType.unknown_size_or_object_ = oddobject_offset;
|
||||
|
||||
// symlink object
|
||||
block->ObSymbolicLinkObjectType.pool_tag = 0x626D7953;
|
||||
block->ObSymbolicLinkObjectType.allocate_proc = trampoline_allocatepool;
|
||||
block->ObSymbolicLinkObjectType.free_proc = trampoline_freepool;
|
||||
block->ObSymbolicLinkObjectType.unknown_size_or_object_ = oddobject_offset;
|
||||
block->ObSymbolicLinkObjectType.delete_proc =
|
||||
kernel_trampoline_group_.NewLongtermTrampoline(DeleteSymlink);
|
||||
|
||||
#define offsetof32(s, m) static_cast<uint32_t>( offsetof(s, m) )
|
||||
|
||||
host_object_type_enum_to_guest_object_type_ptr_ = {
|
||||
{XObject::Type::Event,
|
||||
kernel_guest_globals_ +
|
||||
offsetof32(KernelGuestGlobals, ExEventObjectType)},
|
||||
{XObject::Type::Semaphore,
|
||||
kernel_guest_globals_ +
|
||||
offsetof32(KernelGuestGlobals, ExSemaphoreObjectType)},
|
||||
{XObject::Type::Thread,
|
||||
kernel_guest_globals_ +
|
||||
offsetof32(KernelGuestGlobals, ExThreadObjectType)},
|
||||
{XObject::Type::File,
|
||||
kernel_guest_globals_ +
|
||||
offsetof32(KernelGuestGlobals, IoFileObjectType)},
|
||||
{XObject::Type::Mutant,
|
||||
kernel_guest_globals_ +
|
||||
offsetof32(KernelGuestGlobals, ExMutantObjectType)},
|
||||
{XObject::Type::Device,
|
||||
kernel_guest_globals_ +
|
||||
offsetof32(KernelGuestGlobals, IoDeviceObjectType)}};
|
||||
xboxkrnl::xeKeSetEvent(&block->UsbdBootEnumerationDoneEvent, 1, 0);
|
||||
}
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "xenia/base/bit_map.h"
|
||||
#include "xenia/base/cvar.h"
|
||||
#include "xenia/base/mutex.h"
|
||||
#include "xenia/cpu/backend/backend.h"
|
||||
#include "xenia/cpu/export_resolver.h"
|
||||
#include "xenia/kernel/util/kernel_fwd.h"
|
||||
#include "xenia/kernel/util/native_list.h"
|
||||
|
@ -29,6 +30,7 @@
|
|||
#include "xenia/kernel/xam/app_manager.h"
|
||||
#include "xenia/kernel/xam/content_manager.h"
|
||||
#include "xenia/kernel/xam/user_profile.h"
|
||||
#include "xenia/kernel/xevent.h"
|
||||
#include "xenia/memory.h"
|
||||
#include "xenia/vfs/virtual_file_system.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
@ -83,7 +85,6 @@ struct X_KPROCESS {
|
|||
};
|
||||
static_assert_size(X_KPROCESS, 0x60);
|
||||
|
||||
|
||||
struct TerminateNotification {
|
||||
uint32_t guest_routine;
|
||||
uint32_t priority;
|
||||
|
@ -99,13 +100,46 @@ struct X_TIME_STAMP_BUNDLE {
|
|||
uint32_t tick_count;
|
||||
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 {
|
||||
X_KPROCESS idle_process; // X_PROCTYPE_IDLE. runs in interrupt contexts. is also the context the kernel starts in?
|
||||
X_OBJECT_TYPE ExThreadObjectType;
|
||||
X_OBJECT_TYPE ExEventObjectType;
|
||||
X_OBJECT_TYPE ExMutantObjectType;
|
||||
X_OBJECT_TYPE ExSemaphoreObjectType;
|
||||
X_OBJECT_TYPE ExTimerObjectType;
|
||||
X_OBJECT_TYPE IoCompletionObjectType;
|
||||
X_OBJECT_TYPE IoDeviceObjectType;
|
||||
X_OBJECT_TYPE IoFileObjectType;
|
||||
X_OBJECT_TYPE ObDirectoryObjectType;
|
||||
X_OBJECT_TYPE ObSymbolicLinkObjectType;
|
||||
// a constant buffer that some object types' "unknown_size_or_object" field
|
||||
// points to
|
||||
X_UNKNOWN_TYPE_REFED OddObj;
|
||||
X_KPROCESS idle_process; // X_PROCTYPE_IDLE. runs in interrupt contexts. is
|
||||
// also the context the kernel starts in?
|
||||
X_KPROCESS title_process; // X_PROCTYPE_TITLE
|
||||
X_KPROCESS system_process; // X_PROCTYPE_SYSTEM. no idea when this runs. can
|
||||
// create threads in this process with
|
||||
// ExCreateThread and the thread flag 0x2
|
||||
|
||||
// locks.
|
||||
X_KSPINLOCK dispatcher_lock; // called the "dispatcher lock" in nt 3.5 ppc
|
||||
// .dbg file. Used basically everywhere that
|
||||
// DISPATCHER_HEADER'd objects appear
|
||||
// this lock is only used in some Ob functions. It's odd that it is used at
|
||||
// all, as each table already has its own spinlock.
|
||||
X_KSPINLOCK ob_lock;
|
||||
|
||||
// if LLE emulating Xam, this is needed or you get an immediate freeze
|
||||
X_KEVENT UsbdBootEnumerationDoneEvent;
|
||||
};
|
||||
struct DPCImpersonationScope {
|
||||
uint8_t previous_irql_;
|
||||
|
@ -318,13 +352,17 @@ class KernelState {
|
|||
BitMap tls_bitmap_;
|
||||
uint32_t ke_timestamp_bundle_ptr_ = 0;
|
||||
std::unique_ptr<xe::threading::HighResolutionTimer> timestamp_timer_;
|
||||
cpu::backend::GuestTrampolineGroup kernel_trampoline_group_;
|
||||
//fixed address referenced by dashboards. Data is currently unknown
|
||||
uint32_t strange_hardcoded_page_ = 0x8E038634 & (~0xFFFF);
|
||||
uint32_t strange_hardcoded_location_ = 0x8E038634;
|
||||
|
||||
friend class XObject;
|
||||
public:
|
||||
public:
|
||||
uint32_t dash_context_ = 0;
|
||||
std::unordered_map<XObject::Type, uint32_t>
|
||||
host_object_type_enum_to_guest_object_type_ptr_;
|
||||
uint32_t GetKernelGuestGlobals() const { return kernel_guest_globals_; }
|
||||
};
|
||||
|
||||
} // namespace kernel
|
||||
|
|
|
@ -218,6 +218,23 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state)
|
|||
export_resolver_->SetVariableMapping("xboxkrnl.exe",
|
||||
ordinals::KeTimeStampBundle,
|
||||
kernel_state->GetKeTimestampBundle());
|
||||
#define EXPORT_KVAR(typ) \
|
||||
export_resolver_->SetVariableMapping("xboxkrnl.exe", ordinals::typ, \
|
||||
kernel_state->GetKernelGuestGlobals() + \
|
||||
offsetof(KernelGuestGlobals, typ))
|
||||
|
||||
EXPORT_KVAR(ExThreadObjectType);
|
||||
EXPORT_KVAR(ExEventObjectType);
|
||||
EXPORT_KVAR(ExMutantObjectType);
|
||||
EXPORT_KVAR(ExSemaphoreObjectType);
|
||||
EXPORT_KVAR(ExTimerObjectType);
|
||||
EXPORT_KVAR(IoCompletionObjectType);
|
||||
EXPORT_KVAR(IoDeviceObjectType);
|
||||
EXPORT_KVAR(IoFileObjectType);
|
||||
EXPORT_KVAR(ObDirectoryObjectType);
|
||||
EXPORT_KVAR(ObSymbolicLinkObjectType);
|
||||
EXPORT_KVAR(UsbdBootEnumerationDoneEvent);
|
||||
#undef EXPORT_KVAR
|
||||
}
|
||||
|
||||
static auto& get_xboxkrnl_exports() {
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "xenia/kernel/kernel_state.h"
|
||||
#include "xenia/kernel/util/shim_utils.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_ob.h"
|
||||
#include "xenia/kernel/xobject.h"
|
||||
#include "xenia/kernel/xsemaphore.h"
|
||||
#include "xenia/kernel/xthread.h"
|
||||
|
@ -90,24 +91,6 @@ dword_result_t ObLookupAnyThreadByThreadId_entry(dword_t thread_id,
|
|||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(ObLookupAnyThreadByThreadId, kNone, kImplemented);
|
||||
|
||||
template <uint32_t ordinal>
|
||||
static constexpr uint32_t object_type_id_for_ordinal_v =
|
||||
0xD000BEEF | (ordinal << 16);
|
||||
// These values come from how Xenia handles uninitialized kernel data exports.
|
||||
// D###BEEF where ### is the ordinal.
|
||||
const static std::unordered_map<XObject::Type, uint32_t> object_types = {
|
||||
{XObject::Type::Event,
|
||||
object_type_id_for_ordinal_v<ordinals::ExEventObjectType>},
|
||||
{XObject::Type::Semaphore,
|
||||
object_type_id_for_ordinal_v<ordinals::ExSemaphoreObjectType>},
|
||||
{XObject::Type::Thread,
|
||||
object_type_id_for_ordinal_v<ordinals::ExThreadObjectType>},
|
||||
{XObject::Type::File,
|
||||
object_type_id_for_ordinal_v<ordinals::IoFileObjectType>},
|
||||
{XObject::Type::Mutant,
|
||||
object_type_id_for_ordinal_v<ordinals::ExMutantObjectType>},
|
||||
{XObject::Type::Device,
|
||||
object_type_id_for_ordinal_v<ordinals::IoDeviceObjectType>}};
|
||||
dword_result_t ObReferenceObjectByHandle_entry(dword_t handle,
|
||||
dword_t object_type_ptr,
|
||||
lpdword_t out_object_ptr) {
|
||||
|
@ -120,6 +103,8 @@ dword_result_t ObReferenceObjectByHandle_entry(dword_t handle,
|
|||
}
|
||||
|
||||
uint32_t native_ptr = object->guest_object();
|
||||
auto& object_types =
|
||||
kernel_state()->host_object_type_enum_to_guest_object_type_ptr_;
|
||||
auto object_type = object_types.find(object->type());
|
||||
if (object_type != object_types.end()) {
|
||||
if (object_type_ptr && object_type_ptr != object_type->second) {
|
||||
|
@ -161,7 +146,7 @@ dword_result_t ObReferenceObjectByName_entry(pointer_t<X_ANSI_STRING> name,
|
|||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(ObReferenceObjectByName, kNone, kImplemented);
|
||||
|
||||
void ObDereferenceObject_entry(dword_t native_ptr, const ppc_context_t& ctx) {
|
||||
void xeObDereferenceObject(PPCContext* context, uint32_t native_ptr) {
|
||||
// Check if a dummy value from ObReferenceObjectByHandle.
|
||||
if (native_ptr == 0xDEADF00D) {
|
||||
return;
|
||||
|
@ -179,11 +164,16 @@ void ObDereferenceObject_entry(dword_t native_ptr, const ppc_context_t& ctx) {
|
|||
} else {
|
||||
if (native_ptr) {
|
||||
XELOGW("Unregistered guest object provided to ObDereferenceObject {:08X}",
|
||||
native_ptr.value());
|
||||
native_ptr);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void ObDereferenceObject_entry(dword_t native_ptr, const ppc_context_t& ctx) {
|
||||
xeObDereferenceObject(ctx, native_ptr);
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(ObDereferenceObject, kNone, kImplemented);
|
||||
|
||||
void ObReferenceObject_entry(dword_t native_ptr) {
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2023 Xenia Canary. All rights reserved. * Released under the BSD
|
||||
*license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_XBOXKRNL_OB_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_XBOXKRNL_OB_H_
|
||||
|
||||
#include "xenia/kernel/util/shim_utils.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
void xeObDereferenceObject(PPCContext* context, uint32_t native_ptr);
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_XBOXKRNL_OB_H_
|
|
@ -368,6 +368,12 @@ struct X_OBJECT_TYPE {
|
|||
xe::be<uint32_t> pool_tag; // 0x18
|
||||
};
|
||||
static_assert_size(X_OBJECT_TYPE, 0x1C);
|
||||
|
||||
struct X_KSYMLINK {
|
||||
xe::be<uint32_t> refed_object_maybe;
|
||||
X_ANSI_STRING refed_object_name_maybe;
|
||||
};
|
||||
static_assert_size(X_KSYMLINK, 0xC);
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa363082.aspx
|
||||
typedef struct {
|
||||
// Renamed due to a collision with exception_code from Windows excpt.h.
|
||||
|
|
Loading…
Reference in New Issue