From 0f95864b8dc8a528b814bbdea09a24c26be551d8 Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Sun, 5 Jan 2014 15:56:37 -0800 Subject: [PATCH] NtDuplicateObject. --- src/xenia/kernel/object_table.cc | 27 +++++++++++---- src/xenia/kernel/object_table.h | 1 + src/xenia/kernel/xboxkrnl_nt.cc | 18 ---------- src/xenia/kernel/xboxkrnl_ob.cc | 58 ++++++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 24 deletions(-) diff --git a/src/xenia/kernel/object_table.cc b/src/xenia/kernel/object_table.cc index 495656410..8f5eb772a 100644 --- a/src/xenia/kernel/object_table.cc +++ b/src/xenia/kernel/object_table.cc @@ -120,6 +120,11 @@ X_STATUS ObjectTable::AddHandle(XObject* object, X_HANDLE* out_handle) { X_STATUS ObjectTable::RemoveHandle(X_HANDLE handle) { X_STATUS result = X_STATUS_SUCCESS; + handle = TranslateHandle(handle); + if (!handle) { + return X_STATUS_INVALID_HANDLE; + } + xe_mutex_lock(table_mutex_); // Lower 2 bits are ignored. @@ -155,12 +160,9 @@ X_STATUS ObjectTable::GetObject(X_HANDLE handle, XObject** out_object) { X_STATUS result = X_STATUS_SUCCESS; - if (handle == 0xFFFFFFFF) { - // CurrentProcess - XEASSERTALWAYS(); - } else if (handle == 0xFFFFFFFE) { - // CurrentThread - handle = XThread::GetCurrentThreadHandle(); + handle = TranslateHandle(handle); + if (!handle) { + return X_STATUS_INVALID_HANDLE; } xe_mutex_lock(table_mutex_); @@ -191,3 +193,16 @@ X_STATUS ObjectTable::GetObject(X_HANDLE handle, XObject** out_object) { *out_object = object; return result; } + +X_HANDLE ObjectTable::TranslateHandle(X_HANDLE handle) { + if (handle == 0xFFFFFFFF) { + // CurrentProcess + XEASSERTALWAYS(); + return 0; + } else if (handle == 0xFFFFFFFE) { + // CurrentThread + return XThread::GetCurrentThreadHandle(); + } else { + return handle; + } +} diff --git a/src/xenia/kernel/object_table.h b/src/xenia/kernel/object_table.h index c62f7f02f..ddd0dc4cc 100644 --- a/src/xenia/kernel/object_table.h +++ b/src/xenia/kernel/object_table.h @@ -33,6 +33,7 @@ public: X_STATUS GetObject(X_HANDLE handle, XObject** out_object); private: + X_HANDLE TranslateHandle(X_HANDLE handle); X_STATUS FindFreeSlot(uint32_t* out_slot); typedef struct { diff --git a/src/xenia/kernel/xboxkrnl_nt.cc b/src/xenia/kernel/xboxkrnl_nt.cc index 5da0cfa5b..c0ab764a1 100644 --- a/src/xenia/kernel/xboxkrnl_nt.cc +++ b/src/xenia/kernel/xboxkrnl_nt.cc @@ -11,7 +11,6 @@ #include #include -#include #include @@ -24,27 +23,10 @@ namespace xe { namespace kernel { -SHIM_CALL NtClose_shim( - PPCContext* ppc_state, KernelState* state) { - uint32_t handle = SHIM_GET_ARG_32(0); - - XELOGD( - "NtClose(%.8X)", - handle); - - X_STATUS result = X_STATUS_INVALID_HANDLE; - - result = state->object_table()->RemoveHandle(handle); - - SHIM_SET_RETURN(result); -} - - } // namespace kernel } // namespace xe void xe::kernel::xboxkrnl::RegisterNtExports( ExportResolver* export_resolver, KernelState* state) { - SHIM_SET_MAPPING("xboxkrnl.exe", NtClose, state); } diff --git a/src/xenia/kernel/xboxkrnl_ob.cc b/src/xenia/kernel/xboxkrnl_ob.cc index 9062bc4d6..aacbfb8fc 100644 --- a/src/xenia/kernel/xboxkrnl_ob.cc +++ b/src/xenia/kernel/xboxkrnl_ob.cc @@ -88,6 +88,62 @@ SHIM_CALL ObDereferenceObject_shim( } +SHIM_CALL NtDuplicateObject_shim( + PPCContext* ppc_state, KernelState* state) { + uint32_t handle = SHIM_GET_ARG_32(0); + uint32_t new_handle_ptr = SHIM_GET_ARG_32(1); + uint32_t options = SHIM_GET_ARG_32(2); + + XELOGD( + "NtDuplicateObject(%.8X, %.8X, %.8X)", + handle, new_handle_ptr, options); + + // NOTE: new_handle_ptr can be zero to just close a handle. + // NOTE: this function seems to be used to get the current thread handle + // (passed handle=-2). + // Because this function is not like the NT version (with cross process + // mumble), my guess is that it's just use for getting real handles. + // So we just fake it and properly reference count but not actually make + // different handles. + + X_STATUS result = X_STATUS_INVALID_HANDLE; + + XObject* obj = 0; + result = state->object_table()->GetObject(handle, &obj); + if (XSUCCEEDED(result)) { + obj->RetainHandle(); + uint32_t new_handle = obj->handle(); + if (new_handle_ptr) { + SHIM_SET_MEM_32(new_handle_ptr, new_handle); + } + + if (options == 1 /* DUPLICATE_CLOSE_SOURCE */) { + // Always close the source object. + state->object_table()->RemoveHandle(handle); + } + obj->Release(); + } + + SHIM_SET_RETURN(result); +} + + +SHIM_CALL NtClose_shim( + PPCContext* ppc_state, KernelState* state) { + uint32_t handle = SHIM_GET_ARG_32(0); + + XELOGD( + "NtClose(%.8X)", + handle); + + X_STATUS result = X_STATUS_INVALID_HANDLE; + + result = state->object_table()->RemoveHandle(handle); + + SHIM_SET_RETURN(result); +} + + } // namespace kernel } // namespace xe @@ -96,4 +152,6 @@ void xe::kernel::xboxkrnl::RegisterObExports( ExportResolver* export_resolver, KernelState* state) { SHIM_SET_MAPPING("xboxkrnl.exe", ObReferenceObjectByHandle, state); SHIM_SET_MAPPING("xboxkrnl.exe", ObDereferenceObject, state); + SHIM_SET_MAPPING("xboxkrnl.exe", NtDuplicateObject, state); + SHIM_SET_MAPPING("xboxkrnl.exe", NtClose, state); }