Implement KeReleaseSemaphore based on kernel reverse engineering. Needs KiWaitTest to be implemented to be fully functional.

This commit is contained in:
Fisherman166 2020-06-04 21:20:45 -07:00
parent e5af2b1754
commit db1429a4b9
4 changed files with 33 additions and 6 deletions

View File

@ -321,7 +321,7 @@ XBSYSAPI EXPORTNUM(132) LONG NTAPI KeReleaseSemaphore
(
IN PRKSEMAPHORE Semaphore,
IN KPRIORITY Increment,
IN BOOLEAN Adjustment,
IN LONG Adjustment,
IN BOOLEAN Wait
);

View File

@ -152,6 +152,7 @@ typedef long NTSTATUS;
#define STATUS_USER_APC ((DWORD )0x000000C0L)
// The SCSI input buffer was too large (not necessarily an error!)
#define STATUS_DATA_OVERRUN ((DWORD )0xC000003CL)
#define STATUS_SEMAPHORE_LIMIT_EXCEEDED ((DWORD )0xC0000047L)
#define STATUS_INVALID_IMAGE_FORMAT ((DWORD )0xC000007BL)
#define STATUS_INSUFFICIENT_RESOURCES ((DWORD )0xC000009AL)
#define STATUS_TOO_MANY_SECRETS ((DWORD )0xC0000156L)

View File

@ -600,11 +600,11 @@ XBSYSAPI EXPORTNUM(28) xboxkrnl::VOID NTAPI xboxkrnl::ExReleaseReadWriteLock
if (ReadWriteLock->ReadersEntryCount == 0) {
if (ReadWriteLock->ReadersWaitingCount != 0) {
ULONG temp_readers_waiting = ReadWriteLock->ReadersWaitingCount;
ULONG orig_readers_waiting = ReadWriteLock->ReadersWaitingCount;
ReadWriteLock->ReadersEntryCount = ReadWriteLock->ReadersWaitingCount;
ReadWriteLock->ReadersWaitingCount = 0;
RestoreInterruptMode(interrupt_mode);
KeReleaseSemaphore(&ReadWriteLock->ReaderSemaphore, 1, (BOOLEAN)temp_readers_waiting, 0);
KeReleaseSemaphore(&ReadWriteLock->ReaderSemaphore, 1, (LONG)orig_readers_waiting, 0);
return;
}
}

View File

@ -1314,7 +1314,7 @@ XBSYSAPI EXPORTNUM(132) xboxkrnl::LONG NTAPI xboxkrnl::KeReleaseSemaphore
(
IN PRKSEMAPHORE Semaphore,
IN KPRIORITY Increment,
IN BOOLEAN Adjustment,
IN LONG Adjustment,
IN BOOLEAN Wait
)
{
@ -1325,9 +1325,35 @@ XBSYSAPI EXPORTNUM(132) xboxkrnl::LONG NTAPI xboxkrnl::KeReleaseSemaphore
LOG_FUNC_ARG(Wait)
LOG_FUNC_END;
LOG_UNIMPLEMENTED();
UCHAR orig_irql = KeRaiseIrqlToDpcLevel();
LONG initial_state = Semaphore->Header.SignalState;
LONG adjusted_signalstate = Semaphore->Header.SignalState + Adjustment;
BOOL limit_reached = adjusted_signalstate > Semaphore->Limit;
BOOL signalstate_overflow = adjusted_signalstate < initial_state;
if (limit_reached || signalstate_overflow) {
KiUnlockDispatcherDatabase(orig_irql);
ExRaiseStatus(STATUS_SEMAPHORE_LIMIT_EXCEEDED);
}
Semaphore->Header.SignalState = adjusted_signalstate;
//TODO: Implement KiWaitTest
#if 0
if ((initial_state == 0) && (IsListEmpty(&Semaphore->Header.WaitListHead) == FALSE)) {
KiWaitTest(&Semaphore->Header, Increment);
}
#endif
if (Wait) {
PKTHREAD current_thread = KeGetCurrentThread();
current_thread->WaitNext = TRUE;
current_thread->WaitIrql = orig_irql;
}
else {
KiUnlockDispatcherDatabase(orig_irql);
}
RETURN(0);
RETURN(initial_state);
}
XBSYSAPI EXPORTNUM(133) xboxkrnl::PKDEVICE_QUEUE_ENTRY NTAPI xboxkrnl::KeRemoveByKeyDeviceQueue