diff --git a/import/OpenXDK/include/xboxkrnl/kernel.h b/import/OpenXDK/include/xboxkrnl/kernel.h index cc1624385..93a8f7e70 100644 --- a/import/OpenXDK/include/xboxkrnl/kernel.h +++ b/import/OpenXDK/include/xboxkrnl/kernel.h @@ -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 ); diff --git a/import/OpenXDK/include/xboxkrnl/xboxkrnl.h b/import/OpenXDK/include/xboxkrnl/xboxkrnl.h index da9c774eb..5f1af9889 100644 --- a/import/OpenXDK/include/xboxkrnl/xboxkrnl.h +++ b/import/OpenXDK/include/xboxkrnl/xboxkrnl.h @@ -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) diff --git a/src/core/kernel/exports/EmuKrnlEx.cpp b/src/core/kernel/exports/EmuKrnlEx.cpp index 6f1185a99..5f185ed5a 100644 --- a/src/core/kernel/exports/EmuKrnlEx.cpp +++ b/src/core/kernel/exports/EmuKrnlEx.cpp @@ -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; } } diff --git a/src/core/kernel/exports/EmuKrnlKe.cpp b/src/core/kernel/exports/EmuKrnlKe.cpp index 2327e471f..3aa40f51c 100644 --- a/src/core/kernel/exports/EmuKrnlKe.cpp +++ b/src/core/kernel/exports/EmuKrnlKe.cpp @@ -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