diff --git a/src/core/kernel/exports/EmuKrnlNt.cpp b/src/core/kernel/exports/EmuKrnlNt.cpp index b188d0a1a..84b796bfe 100644 --- a/src/core/kernel/exports/EmuKrnlNt.cpp +++ b/src/core/kernel/exports/EmuKrnlNt.cpp @@ -1648,10 +1648,17 @@ XBSYSAPI EXPORTNUM(219) xbox::ntstatus_xt NTAPI xbox::NtReadFile CxbxDebugger::ReportFileRead(FileHandle, Length, Offset); } + if (ApcRoutine != nullptr) { + // Pack the original parameters to a wrapped context for a custom APC routine + CxbxIoDispatcherContext* cxbxContext = new CxbxIoDispatcherContext(IoStatusBlock, ApcRoutine, ApcContext); + ApcRoutine = CxbxIoApcDispatcher; + ApcContext = cxbxContext; + } + NTSTATUS ret = NtDll::NtReadFile( FileHandle, Event, - (PVOID)ApcRoutine, + ApcRoutine, ApcContext, IoStatusBlock, Buffer, @@ -2043,8 +2050,8 @@ XBSYSAPI EXPORTNUM(232) xbox::void_xt NTAPI xbox::NtUserIoApcDispatcher dwErrorCode = RtlNtStatusToDosError(IoStatusBlock->Status); } - LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine = (LPOVERLAPPED_COMPLETION_ROUTINE)ApcContext; - LPOVERLAPPED lpOverlapped = (LPOVERLAPPED)CONTAINING_RECORD(IoStatusBlock, OVERLAPPED, Internal); + LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine = reinterpret_cast(ApcContext); + LPOVERLAPPED lpOverlapped = reinterpret_cast(IoStatusBlock); (CompletionRoutine)(dwErrorCode, dwTransferred, lpOverlapped); @@ -2168,10 +2175,17 @@ XBSYSAPI EXPORTNUM(236) xbox::ntstatus_xt NTAPI xbox::NtWriteFile CxbxDebugger::ReportFileWrite(FileHandle, Length, Offset); } + if (ApcRoutine != nullptr) { + // Pack the original parameters to a wrapped context for a custom APC routine + CxbxIoDispatcherContext* cxbxContext = new CxbxIoDispatcherContext(IoStatusBlock, ApcRoutine, ApcContext); + ApcRoutine = CxbxIoApcDispatcher; + ApcContext = cxbxContext; + } + NTSTATUS ret = NtDll::NtWriteFile( FileHandle, Event, - (PVOID)ApcRoutine, + ApcRoutine, ApcContext, IoStatusBlock, Buffer, diff --git a/src/core/kernel/support/EmuFile.cpp b/src/core/kernel/support/EmuFile.cpp index edb76a138..d98f98e9d 100644 --- a/src/core/kernel/support/EmuFile.cpp +++ b/src/core/kernel/support/EmuFile.cpp @@ -191,6 +191,14 @@ void CxbxFormatPartitionByHandle(HANDLE hFile) printf("Formatted EmuDisk Partition%d\n", CxbxGetPartitionNumberFromHandle(hFile)); } +void NTAPI CxbxIoApcDispatcher(PVOID ApcContext, xbox::PIO_STATUS_BLOCK /*IoStatusBlock*/, xbox::ulong_xt Reserved) +{ + CxbxIoDispatcherContext* cxbxContext = reinterpret_cast(ApcContext); + std::get(*cxbxContext)( + std::get(*cxbxContext),std::get(*cxbxContext), Reserved); + delete cxbxContext; +} + const std::string MediaBoardRomFile = "Chihiro\\fpr21042_m29w160et.bin"; const std::string DrivePrefix = "\\??\\"; const std::string DriveSerial = DrivePrefix + "serial:"; diff --git a/src/core/kernel/support/EmuFile.h b/src/core/kernel/support/EmuFile.h index 2f351f399..8690f6970 100644 --- a/src/core/kernel/support/EmuFile.h +++ b/src/core/kernel/support/EmuFile.h @@ -304,4 +304,15 @@ int CxbxGetPartitionNumberFromHandle(HANDLE hFile); std::string CxbxGetPartitionDataPathFromHandle(HANDLE hFile); void CxbxFormatPartitionByHandle(HANDLE hFile); +// Ensures that an original IoStatusBlock gets passed to the completion callback +// Used by NtReadFile and NtWriteFile +using CxbxIoDispatcherContext = std::tuple; + +void NTAPI CxbxIoApcDispatcher +( + PVOID ApcContext, + xbox::PIO_STATUS_BLOCK IoStatusBlock, + xbox::ulong_xt Reserved +); + #endif