From 3627418e0ee7b4720dca7194534a206dc626869e Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Tue, 9 Jun 2015 18:58:02 -0500 Subject: [PATCH 1/4] Object table handle duplication --- src/xenia/kernel/object_table.cc | 15 +++++++++++++++ src/xenia/kernel/object_table.h | 1 + 2 files changed, 16 insertions(+) diff --git a/src/xenia/kernel/object_table.cc b/src/xenia/kernel/object_table.cc index 8defb54c5..50cb6720c 100644 --- a/src/xenia/kernel/object_table.cc +++ b/src/xenia/kernel/object_table.cc @@ -112,6 +112,21 @@ X_STATUS ObjectTable::AddHandle(XObject* object, X_HANDLE* out_handle) { return result; } +X_STATUS ObjectTable::DuplicateHandle(X_HANDLE handle, X_HANDLE* out_handle) { + X_STATUS result = X_STATUS_SUCCESS; + handle = TranslateHandle(handle); + + XObject* object = LookupObject(handle, false); + if (object) { + result = AddHandle(object, out_handle); + object->Release(); // Release the ref that LookupObject took + } else { + result = X_STATUS_INVALID_HANDLE; + } + + return result; +} + X_STATUS ObjectTable::RemoveHandle(X_HANDLE handle) { X_STATUS result = X_STATUS_SUCCESS; diff --git a/src/xenia/kernel/object_table.h b/src/xenia/kernel/object_table.h index e5ba8061e..340a01b9a 100644 --- a/src/xenia/kernel/object_table.h +++ b/src/xenia/kernel/object_table.h @@ -27,6 +27,7 @@ class ObjectTable { ~ObjectTable(); X_STATUS AddHandle(XObject* object, X_HANDLE* out_handle); + X_STATUS DuplicateHandle(X_HANDLE orig, X_HANDLE* out_handle); X_STATUS RemoveHandle(X_HANDLE handle); template object_ref LookupObject(X_HANDLE handle) { From 72a641efac8a6579ddc344b08c0d3d12fd2dce91 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Tue, 9 Jun 2015 18:58:21 -0500 Subject: [PATCH 2/4] Fix up NtDuplicateObject --- src/xenia/kernel/xboxkrnl_ob.cc | 56 +++++++++------------------------ 1 file changed, 15 insertions(+), 41 deletions(-) diff --git a/src/xenia/kernel/xboxkrnl_ob.cc b/src/xenia/kernel/xboxkrnl_ob.cc index e5a131819..8714a4f53 100644 --- a/src/xenia/kernel/xboxkrnl_ob.cc +++ b/src/xenia/kernel/xboxkrnl_ob.cc @@ -133,55 +133,31 @@ SHIM_CALL ObDereferenceObject_shim(PPCContext* ppc_context, SHIM_SET_RETURN_32(0); } -SHIM_CALL NtDuplicateObject_shim(PPCContext* ppc_context, - KernelState* kernel_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); - +dword_result_t NtDuplicateObject(dword_t handle, lpdword_t new_handle_ptr, + dword_t 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. + // This function actually just creates a new handle to the same object. + // Most games use it to get real handles to the current thread or whatever. - X_STATUS result = X_STATUS_SUCCESS; + X_HANDLE new_handle = X_INVALID_HANDLE_VALUE; + X_STATUS result = + kernel_state()->object_table()->DuplicateHandle(handle, &new_handle); - auto object = kernel_state->object_table()->LookupObject(handle); - if (object) { - object->Retain(); - object->RetainHandle(); - uint32_t new_handle = object->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. - kernel_state->object_table()->RemoveHandle(handle); - } - } else { - result = X_STATUS_INVALID_HANDLE; + if (options == 1 /* DUPLICATE_CLOSE_SOURCE */) { + // Always close the source object. + kernel_state()->object_table()->RemoveHandle(handle); } - SHIM_SET_RETURN_32(result); + return result; } +DECLARE_XBOXKRNL_EXPORT(NtDuplicateObject, ExportTag::kImplemented); -SHIM_CALL NtClose_shim(PPCContext* ppc_context, KernelState* kernel_state) { - uint32_t handle = SHIM_GET_ARG_32(0); - - XELOGD("NtClose(%.8X)", handle); - - X_STATUS result = X_STATUS_INVALID_HANDLE; - - result = kernel_state->object_table()->RemoveHandle(handle); - - SHIM_SET_RETURN_32(result); +dword_result_t NtClose(dword_t handle) { + return kernel_state()->object_table()->RemoveHandle(handle); } +DECLARE_XBOXKRNL_EXPORT(NtClose, ExportTag::kImplemented); } // namespace kernel } // namespace xe @@ -191,6 +167,4 @@ void xe::kernel::xboxkrnl::RegisterObExports( SHIM_SET_MAPPING("xboxkrnl.exe", ObOpenObjectByName, 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); } From 41f102354903df2112f2c5906f639f0c26cca000 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Tue, 9 Jun 2015 18:58:45 -0500 Subject: [PATCH 3/4] Minor fix in XThread - checking the wrong address for NULL --- src/xenia/kernel/objects/xthread.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xenia/kernel/objects/xthread.cc b/src/xenia/kernel/objects/xthread.cc index 89db7072f..0222443e1 100644 --- a/src/xenia/kernel/objects/xthread.cc +++ b/src/xenia/kernel/objects/xthread.cc @@ -157,7 +157,7 @@ X_STATUS XThread::Create() { // structure. pcr_address_ = memory()->SystemHeapAlloc(0x2D8 + 0xAB0); thread_state_address_ = pcr_address_ + 0x2D8; - if (!thread_state_address_) { + if (!pcr_address_) { XELOGW("Unable to allocate thread state block"); return X_STATUS_NO_MEMORY; } From 60cf80d85c8bb450bc742ed369bc13b517c4d2f7 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Tue, 9 Jun 2015 19:04:41 -0500 Subject: [PATCH 4/4] Actually give the game the new handle --- src/xenia/kernel/xboxkrnl_ob.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/xenia/kernel/xboxkrnl_ob.cc b/src/xenia/kernel/xboxkrnl_ob.cc index 8714a4f53..a3f154865 100644 --- a/src/xenia/kernel/xboxkrnl_ob.cc +++ b/src/xenia/kernel/xboxkrnl_ob.cc @@ -145,6 +145,10 @@ dword_result_t NtDuplicateObject(dword_t handle, lpdword_t new_handle_ptr, X_STATUS result = kernel_state()->object_table()->DuplicateHandle(handle, &new_handle); + if (new_handle_ptr) { + *new_handle_ptr = new_handle; + } + if (options == 1 /* DUPLICATE_CLOSE_SOURCE */) { // Always close the source object. kernel_state()->object_table()->RemoveHandle(handle);