From 9771f989d057e2203e993bbe0e2f05bf051623a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Gocn=C3=ADk?= Date: Fri, 18 May 2018 23:50:39 +0200 Subject: [PATCH] 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. --- src/CxbxKrnl/EmuKrnlKe.cpp | 21 +++++++++++++++++++-- src/CxbxKrnl/EmuKrnlRtl.cpp | 9 ++++++++- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/CxbxKrnl/EmuKrnlKe.cpp b/src/CxbxKrnl/EmuKrnlKe.cpp index e8e4b4b06..b769f440c 100644 --- a/src/CxbxKrnl/EmuKrnlKe.cpp +++ b/src/CxbxKrnl/EmuKrnlKe.cpp @@ -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]); } diff --git a/src/CxbxKrnl/EmuKrnlRtl.cpp b/src/CxbxKrnl/EmuKrnlRtl.cpp index 0619c2fc8..8948b53e4 100644 --- a/src/CxbxKrnl/EmuKrnlRtl.cpp +++ b/src/CxbxKrnl/EmuKrnlRtl.cpp @@ -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; }