diff --git a/src/xenia/kernel/util/shim_utils.h b/src/xenia/kernel/util/shim_utils.h index 9443d3908..1ac2e1b58 100644 --- a/src/xenia/kernel/util/shim_utils.h +++ b/src/xenia/kernel/util/shim_utils.h @@ -280,6 +280,7 @@ class Result { } Result() = delete; Result& operator=(const Result&) = delete; + operator T() const { return value_; } private: T value_; diff --git a/src/xenia/kernel/xam_net.cc b/src/xenia/kernel/xam_net.cc index b55e1cddd..916dc4880 100644 --- a/src/xenia/kernel/xam_net.cc +++ b/src/xenia/kernel/xam_net.cc @@ -13,6 +13,7 @@ #include "xenia/base/logging.h" #include "xenia/kernel/kernel_state.h" #include "xenia/kernel/objects/xevent.h" +#include "xenia/kernel/objects/xthread.h" #include "xenia/kernel/util/shim_utils.h" #include "xenia/kernel/xam_private.h" #include "xenia/xbox.h" @@ -252,6 +253,56 @@ dword_result_t NetDll_WSARecvFrom(dword_t caller, dword_t socket, DECLARE_XAM_EXPORT(NetDll_WSARecvFrom, ExportTag::kNetworking | ExportTag::kStub); +dword_result_t NtWaitForMultipleObjectsEx( + dword_t count, pointer_t> handles, dword_t wait_type, + dword_t wait_mode, dword_t alertable, + pointer_t> timeout_ptr); +dword_result_t RtlNtStatusToDosError(dword_t source_status); + +dword_result_t NetDll_WSAWaitForMultipleEvents( + dword_t num_events, pointer_t> events, dword_t wait_all, + dword_t timeout, dword_t alertable) { + if (num_events > 64) { + XThread::GetCurrentThread()->set_last_error(87); // ERROR_INVALID_PARAMETER + return -1; + } + + xe::be timeout_wait = (uint64_t)timeout; + + X_STATUS result = 0; + do { + result = + NtWaitForMultipleObjectsEx(num_events, events, wait_all, 1, alertable, + timeout != -1 ? &timeout_wait : nullptr); + } while (result == X_STATUS_ALERTED); + + if (XFAILED(result)) { + uint32_t error = RtlNtStatusToDosError(result); + XThread::GetCurrentThread()->set_last_error(error); + return -1; + } + + return 0; +} +DECLARE_XAM_EXPORT(NetDll_WSAWaitForMultipleEvents, + ExportTag::kNetworking | ExportTag::kStub); + +dword_result_t NtClearEvent(dword_t handle); + +dword_result_t NetDll_WSAResetEvent(dword_t event_handle) { + X_STATUS result = NtClearEvent(event_handle); + + if (XFAILED(result)) { + uint32_t error = RtlNtStatusToDosError(result); + XThread::GetCurrentThread()->set_last_error(error); + return 0; + } + + return 1; +} +DECLARE_XAM_EXPORT(NetDll_WSAResetEvent, + ExportTag::kNetworking | ExportTag::kStub); + struct XnAddrStatus { // Address acquisition is not yet complete const static uint32_t XNET_GET_XNADDR_PENDING = 0x00000000; diff --git a/src/xenia/kernel/xboxkrnl_threading.cc b/src/xenia/kernel/xboxkrnl_threading.cc index 4769b8df3..2442b9483 100644 --- a/src/xenia/kernel/xboxkrnl_threading.cc +++ b/src/xenia/kernel/xboxkrnl_threading.cc @@ -598,23 +598,20 @@ SHIM_CALL KeResetEvent_shim(PPCContext* ppc_context, SHIM_SET_RETURN_32(result); } -SHIM_CALL NtClearEvent_shim(PPCContext* ppc_context, - KernelState* kernel_state) { - uint32_t event_handle = SHIM_GET_ARG_32(0); - - XELOGD("NtClearEvent(%.8X)", event_handle); - +dword_result_t NtClearEvent(dword_t handle) { X_STATUS result = X_STATUS_SUCCESS; - auto ev = kernel_state->object_table()->LookupObject(event_handle); + auto ev = kernel_state()->object_table()->LookupObject(handle); if (ev) { ev->Reset(); } else { result = X_STATUS_INVALID_HANDLE; } - SHIM_SET_RETURN_32(result); + return result; } +DECLARE_XBOXKRNL_EXPORT(NtClearEvent, + ExportTag::kImplemented | ExportTag::kThreading); SHIM_CALL NtCreateSemaphore_shim(PPCContext* ppc_context, KernelState* kernel_state) { @@ -964,41 +961,33 @@ SHIM_CALL KeWaitForMultipleObjects_shim(PPCContext* ppc_context, SHIM_SET_RETURN_32(result); } -SHIM_CALL NtWaitForMultipleObjectsEx_shim(PPCContext* ppc_context, - KernelState* kernel_state) { - uint32_t count = SHIM_GET_ARG_32(0); - uint32_t handles_ptr = SHIM_GET_ARG_32(1); - uint32_t wait_type = SHIM_GET_ARG_32(2); - uint8_t wait_mode = SHIM_GET_ARG_8(3); - uint32_t alertable = SHIM_GET_ARG_32(4); - uint32_t timeout_ptr = SHIM_GET_ARG_32(5); - - XELOGD("NtWaitForMultipleObjectsEx(%d, %.8X, %.8X, %.8X, %.8X, %.8X)", count, - handles_ptr, wait_type, wait_mode, alertable, timeout_ptr); - +dword_result_t NtWaitForMultipleObjectsEx( + dword_t count, pointer_t> handles, dword_t wait_type, + dword_t wait_mode, dword_t alertable, + pointer_t> timeout_ptr) { assert_true(wait_type >= 0 && wait_type <= 1); - X_STATUS result = X_STATUS_SUCCESS; std::vector> objects(count); for (uint32_t n = 0; n < count; n++) { - uint32_t object_handle = SHIM_MEM_32(handles_ptr + n * 4); + uint32_t object_handle = handles[n]; auto object = - kernel_state->object_table()->LookupObject(object_handle); + kernel_state()->object_table()->LookupObject(object_handle); if (!object) { - SHIM_SET_RETURN_32(X_STATUS_INVALID_PARAMETER); - return; + return X_STATUS_INVALID_PARAMETER; } objects[n] = std::move(object); } - uint64_t timeout = timeout_ptr ? SHIM_MEM_64(timeout_ptr) : 0; + uint64_t timeout = timeout_ptr ? *timeout_ptr : 0; result = XObject::WaitMultiple( count, reinterpret_cast(objects.data()), wait_type, 6, wait_mode, alertable, timeout_ptr ? &timeout : nullptr); - SHIM_SET_RETURN_32(result); + return result; } +DECLARE_XBOXKRNL_EXPORT(NtWaitForMultipleObjectsEx, + ExportTag::kImplemented | ExportTag::kThreading); SHIM_CALL NtSignalAndWaitForSingleObjectEx_shim(PPCContext* ppc_context, KernelState* kernel_state) { @@ -1413,7 +1402,6 @@ void xe::kernel::xboxkrnl::RegisterThreadingExports( SHIM_SET_MAPPING("xboxkrnl.exe", KePulseEvent, state); SHIM_SET_MAPPING("xboxkrnl.exe", NtPulseEvent, state); SHIM_SET_MAPPING("xboxkrnl.exe", KeResetEvent, state); - SHIM_SET_MAPPING("xboxkrnl.exe", NtClearEvent, state); SHIM_SET_MAPPING("xboxkrnl.exe", NtCreateSemaphore, state); SHIM_SET_MAPPING("xboxkrnl.exe", KeInitializeSemaphore, state); @@ -1430,7 +1418,6 @@ void xe::kernel::xboxkrnl::RegisterThreadingExports( SHIM_SET_MAPPING("xboxkrnl.exe", KeWaitForSingleObject, state); SHIM_SET_MAPPING("xboxkrnl.exe", NtWaitForSingleObjectEx, state); SHIM_SET_MAPPING("xboxkrnl.exe", KeWaitForMultipleObjects, state); - SHIM_SET_MAPPING("xboxkrnl.exe", NtWaitForMultipleObjectsEx, state); SHIM_SET_MAPPING("xboxkrnl.exe", NtSignalAndWaitForSingleObjectEx, state); SHIM_SET_MAPPING("xboxkrnl.exe", KfAcquireSpinLock, state);