Implement KeEvent Api's for non-windows event structures.

This commit is contained in:
Luke Usher 2017-09-21 20:49:35 +01:00
parent 7067db44dc
commit 18a64386cd
1 changed files with 65 additions and 9 deletions

View File

@ -60,6 +60,8 @@ namespace NtDll
#include <chrono> #include <chrono>
#include <thread> #include <thread>
#include <windows.h>
#include <map>
// Copied over from Dxbx. // Copied over from Dxbx.
// TODO : Move towards thread-simulation based Dpc emulation // TODO : Move towards thread-simulation based Dpc emulation
@ -73,6 +75,8 @@ typedef struct _DpcData {
DpcData g_DpcData = { 0 }; // Note : g_DpcData is initialized in InitDpcAndTimerThread() DpcData g_DpcData = { 0 }; // Note : g_DpcData is initialized in InitDpcAndTimerThread()
std::map<xboxkrnl::PRKEVENT, HANDLE> g_KeEventHandles;
xboxkrnl::ULONGLONG LARGE_INTEGER2ULONGLONG(xboxkrnl::LARGE_INTEGER value) xboxkrnl::ULONGLONG LARGE_INTEGER2ULONGLONG(xboxkrnl::LARGE_INTEGER value)
{ {
// Weird construction because there doesn't seem to exist an implicit // Weird construction because there doesn't seem to exist an implicit
@ -666,10 +670,19 @@ XBSYSAPI EXPORTNUM(108) xboxkrnl::VOID NTAPI xboxkrnl::KeInitializeEvent
LOG_FUNC_ARG(SignalState) LOG_FUNC_ARG(SignalState)
LOG_FUNC_END; LOG_FUNC_END;
// Setup the Xbox event struct
Event->Header.Type = Type; Event->Header.Type = Type;
Event->Header.Size = sizeof(KEVENT) / sizeof(LONG); Event->Header.Size = sizeof(KEVENT) / sizeof(LONG);
Event->Header.SignalState = SignalState; Event->Header.SignalState = SignalState;
InitializeListHead(&(Event->Header.WaitListHead)); InitializeListHead(&(Event->Header.WaitListHead));
// Create a Windows event, to be used in KeWaitForObject
// 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);
g_KeEventHandles[Event] = hostEvent;
} }
// ****************************************************************** // ******************************************************************
@ -997,6 +1010,14 @@ XBSYSAPI EXPORTNUM(123) xboxkrnl::LONG NTAPI xboxkrnl::KePulseEvent
LOG_FUNC_ARG(Wait) LOG_FUNC_ARG(Wait)
LOG_FUNC_END; LOG_FUNC_END;
// Fetch the host event and signal it, if present
if (g_KeEventHandles.find(Event) == g_KeEventHandles.end()) {
EmuWarning("KePulseEvent called on a non-existant event!");
}
else {
PulseEvent(g_KeEventHandles[Event]);
}
LOG_UNIMPLEMENTED(); LOG_UNIMPLEMENTED();
RETURN(0); RETURN(0);
@ -1295,6 +1316,15 @@ XBSYSAPI EXPORTNUM(138) xboxkrnl::LONG NTAPI xboxkrnl::KeResetEvent
LONG ret = Event->Header.SignalState; LONG ret = Event->Header.SignalState;
Event->Header.SignalState = 0; Event->Header.SignalState = 0;
// Fetch the host event and signal it, if present
if (g_KeEventHandles.find(Event) == g_KeEventHandles.end()) {
EmuWarning("KeResetEvent called on a non-existant event!");
}
else {
ResetEvent(g_KeEventHandles[Event]);
}
return ret; return ret;
} }
@ -1422,6 +1452,15 @@ XBSYSAPI EXPORTNUM(145) xboxkrnl::LONG NTAPI xboxkrnl::KeSetEvent
LONG ret = Event->Header.SignalState; LONG ret = Event->Header.SignalState;
Event->Header.SignalState = TRUE; Event->Header.SignalState = TRUE;
// Fetch the host event and signal it, if present
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);
} else {
SetEvent(g_KeEventHandles[Event]);
}
RETURN(ret); RETURN(ret);
} }
@ -1683,24 +1722,41 @@ XBSYSAPI EXPORTNUM(158) xboxkrnl::NTSTATUS NTAPI xboxkrnl::KeWaitForMultipleObje
NTSTATUS ret = STATUS_SUCCESS; NTSTATUS ret = STATUS_SUCCESS;
// Take the input and build two arrays: One of handles created by our kernel and one for not
// Handles created by our kernel need to be forwarded to WaitForMultipleObjects while handles
// created by Windows need to be forwarded to NtDll::KeWaitForMultipleObjects
std::vector<HANDLE> nativeObjects;
std::vector<HANDLE> ntdllObjects;
for (uint i = 0; i < Count; i++) { for (uint i = 0; i < Count; i++) {
DbgPrintf("Object: 0x%08X\n", Object[i]); DbgPrintf("Object: 0x%08X\n", Object[i]);
if (IsEmuHandle(Object[i])) { if (g_KeEventHandles.find((PKEVENT)Object[i]) == g_KeEventHandles.end()) {
ret = WAIT_FAILED; ntdllObjects.push_back(Object[i]);
EmuWarning("WaitFor EmuHandle not supported!"); } else {
break; nativeObjects.push_back(g_KeEventHandles[(PRKEVENT)Object[i]]);
} }
} }
if (ret == STATUS_SUCCESS) if (ntdllObjects.size() > 0) {
{
// TODO : What should we do with the (currently ignored) // TODO : What should we do with the (currently ignored)
// WaitReason, WaitMode, WaitBlockArray? // WaitReason, WaitMode, WaitBlockArray?
// Unused arguments : WaitReason, WaitMode, WaitBlockArray // Unused arguments : WaitReason, WaitMode, WaitBlockArray
ret = NtDll::NtWaitForMultipleObjects( ret = NtDll::NtWaitForMultipleObjects(
Count, ntdllObjects.size(),
Object, &ntdllObjects[0],
(NtDll::OBJECT_WAIT_TYPE)WaitType,
Alertable,
(NtDll::PLARGE_INTEGER)Timeout);
if (FAILED(ret))
EmuWarning("KeWaitForMultipleObjects failed! (%s)", NtStatusToString(ret));
}
if (nativeObjects.size() > 0) {
ret = NtDll::NtWaitForMultipleObjects(
nativeObjects.size(),
&nativeObjects[0],
(NtDll::OBJECT_WAIT_TYPE)WaitType, (NtDll::OBJECT_WAIT_TYPE)WaitType,
Alertable, Alertable,
(NtDll::PLARGE_INTEGER)Timeout); (NtDll::PLARGE_INTEGER)Timeout);