Preserve original IO status block and context for ApcRoutine
Fixes cases where guest's APC routine/completion callback does not receive the original IO status block variable, but it assumed it did (it's allowed as per WinAPI docs). Fixes Project Gotham Racing deadlocking after intro movies
This commit is contained in:
parent
8415397067
commit
0411f27c65
|
@ -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<LPOVERLAPPED_COMPLETION_ROUTINE>(ApcContext);
|
||||
LPOVERLAPPED lpOverlapped = reinterpret_cast<LPOVERLAPPED>(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,
|
||||
|
|
|
@ -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<CxbxIoDispatcherContext*>(ApcContext);
|
||||
std::get<xbox::PIO_APC_ROUTINE>(*cxbxContext)(
|
||||
std::get<LPVOID>(*cxbxContext),std::get<xbox::PIO_STATUS_BLOCK>(*cxbxContext), Reserved);
|
||||
delete cxbxContext;
|
||||
}
|
||||
|
||||
const std::string MediaBoardRomFile = "Chihiro\\fpr21042_m29w160et.bin";
|
||||
const std::string DrivePrefix = "\\??\\";
|
||||
const std::string DriveSerial = DrivePrefix + "serial:";
|
||||
|
|
|
@ -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<xbox::PIO_STATUS_BLOCK, xbox::PIO_APC_ROUTINE, PVOID>;
|
||||
|
||||
void NTAPI CxbxIoApcDispatcher
|
||||
(
|
||||
PVOID ApcContext,
|
||||
xbox::PIO_STATUS_BLOCK IoStatusBlock,
|
||||
xbox::ulong_xt Reserved
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue