Fix some CriticalSection bugs

The main issue was that the corresponding Event to the CriticalSection
wasn't created when the CriticalSection was and the return value of
KeWaitForSingleObject wasn't checked, so the STATUS_INVALID_HANDLE
was quitely ignored.

This actually gets Harry Potter and the Sorcerer's Stone to intro.
This commit is contained in:
Jan Gocník 2018-05-18 23:50:39 +02:00
parent 99b8b7f3d2
commit 9771f989d0
2 changed files with 27 additions and 3 deletions

View File

@ -637,7 +637,15 @@ XBSYSAPI EXPORTNUM(108) xboxkrnl::VOID NTAPI xboxkrnl::KeInitializeEvent
// TODO: This doesn't check for events that are already initialized
// This shouldn't happen, except on shoddily coded titles so we
// ignore it for now
HANDLE hostEvent = CreateEvent(NULL, FALSE, SignalState, NULL);
HANDLE hostEvent;
if (Type == NotificationEvent)
{
hostEvent = CreateEvent(NULL, TRUE, SignalState, NULL);
}
else {
hostEvent = CreateEvent(NULL, FALSE, SignalState, NULL);
}
g_KeEventHandles[Event] = hostEvent;
}
@ -1509,7 +1517,16 @@ XBSYSAPI EXPORTNUM(145) xboxkrnl::LONG NTAPI xboxkrnl::KeSetEvent
if (g_KeEventHandles.find(Event) == g_KeEventHandles.end()) {
EmuWarning("KeSetEvent called on a non-existant event. Creating it!");
// TODO: Find out why some XDKs do not call KeInitializeEvent first
KeInitializeEvent(Event, NotificationEvent, TRUE);
//We can check the event type from the internal structure, see https://www.geoffchappell.com/studies/windows/km/ntoskrnl/structs/kobjects.htm?tx=111
if (Event->Header.Type & 0x7F == 0x01)
{
KeInitializeEvent(Event, NotificationEvent, TRUE);
}
else {
KeInitializeEvent(Event, SynchronizationEvent, TRUE);
}
} else {
SetEvent(g_KeEventHandles[Event]);
}

View File

@ -101,6 +101,8 @@ static void InitHostCriticalSection(xboxkrnl::PRTL_CRITICAL_SECTION xbox_crit_se
CRITICAL_SECTION host_crit_section;
InitializeCriticalSection(&host_crit_section);
add_critical_section(xbox_crit_section, host_crit_section);
//Initalize the host event for the critical section
KeInitializeEvent((xboxkrnl::PRKEVENT)xbox_crit_section, (xboxkrnl::EVENT_TYPE)xboxkrnl::NotificationEvent, FALSE);
}
static void EnterHostCriticalSection(xboxkrnl::PRTL_CRITICAL_SECTION xbox_crit_section)
@ -730,13 +732,18 @@ XBSYSAPI EXPORTNUM(277) xboxkrnl::VOID NTAPI xboxkrnl::RtlEnterCriticalSection
}
else {
if(CriticalSection->OwningThread != thread) {
KeWaitForSingleObject(
NTSTATUS result;
result = KeWaitForSingleObject(
(PVOID)CriticalSection,
(KWAIT_REASON)0,
(KPROCESSOR_MODE)0,
(BOOLEAN)0,
(PLARGE_INTEGER)0
);
if(!NT_SUCCESS(result))
{
CxbxKrnlCleanup("Waiting for event of a critical section returned %lx.", result);
};
CriticalSection->OwningThread = thread;
CriticalSection->RecursionCount = 1;
}