From 2ac2538faa0456e85a7b2f6e57893aeffaac8d9a Mon Sep 17 00:00:00 2001 From: illusion98 <37698908+illusion98@users.noreply.github.com> Date: Sat, 26 Oct 2019 04:47:11 -0500 Subject: [PATCH] Merge remote-tracking branch 'emoose/ntwritefile-apc' Originally merged by @0x8080 Co-Authored-By: 0x8080 <0x8080@users.noreply.github.com> --- src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc | 30 +++++++++++++----------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc index 4352c7be9..9d9a2753d 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc @@ -244,11 +244,7 @@ dword_result_t NtWriteFile(dword_t file_handle, dword_t event_handle, pointer_t io_status_block, lpvoid_t buffer, dword_t buffer_length, lpqword_t byte_offset_ptr) { - // Async not supported yet. - assert_zero(apc_routine); - X_STATUS result = X_STATUS_SUCCESS; - uint32_t info = 0; // Grab event to signal. bool signal_event = false; @@ -273,30 +269,36 @@ dword_result_t NtWriteFile(dword_t file_handle, dword_t event_handle, buffer, buffer_length, byte_offset_ptr ? static_cast(*byte_offset_ptr) : -1, &bytes_written, apc_context); - if (XSUCCEEDED(result)) { - info = (int32_t)bytes_written; + if (io_status_block) { + io_status_block->status = result; + io_status_block->information = static_cast(bytes_written); + } + + // Queue the APC callback. It must be delivered via the APC mechanism even + // though were are completing immediately. + // Low bit probably means do not queue to IO ports. + if ((uint32_t)apc_routine & ~1) { + if (apc_context) { + auto thread = XThread::GetCurrentThread(); + thread->EnqueueApc(static_cast(apc_routine) & ~1u, + apc_context, io_status_block, 0); + } } if (!file->is_synchronous()) { result = X_STATUS_PENDING; } - if (io_status_block) { - io_status_block->status = X_STATUS_SUCCESS; - io_status_block->information = info; - } - // Mark that we should signal the event now. We do this after // we have written the info out. signal_event = true; } else { // X_STATUS_PENDING if not returning immediately. result = X_STATUS_PENDING; - info = 0; if (io_status_block) { - io_status_block->status = X_STATUS_SUCCESS; - io_status_block->information = info; + io_status_block->status = X_STATUS_PENDING; + io_status_block->information = 0; } } }