From 58ba3f5db02aca7b90a3593a1c249862b2fbc150 Mon Sep 17 00:00:00 2001 From: Dibyamartanda Samanta Date: Thu, 25 Sep 2025 14:57:10 +0200 Subject: [PATCH] Nuke Old Mutex Implementation To many changes to make , so i just updated with my recent iteration. Signed-off-by: CodingWorkshop Signing Team --- NTOSKRNL/KE/mutex.cpp | 544 ++++++++++++++++++++++++++++++------------ 1 file changed, 385 insertions(+), 159 deletions(-) diff --git a/NTOSKRNL/KE/mutex.cpp b/NTOSKRNL/KE/mutex.cpp index effd47f..49075d1 100644 --- a/NTOSKRNL/KE/mutex.cpp +++ b/NTOSKRNL/KE/mutex.cpp @@ -3,20 +3,20 @@ * LICENSE: BSD Clause 3 * PURPOSE: Mutexes * NT KERNEL: 5.11.9360 - * COPYRIGHT: 2023-2029 Dibymartanda Samanta <> + * COPYRIGHT: 2023-2029 Dibymartanda Samanta */ - #include #define NTDEBUG extern "C" -/*Mutex Count : -0 => Can Be aquired, -1 => Is Aquired by a Thread -In Negative Indigates, Number of Threads waiting*/ -constexpr ULONG MUTEX_READY_TO_BE_AQUIRED = 0; +/*Mutex Count : +0 => Can Be acquired, +1 => Is Acquired by a Thread +In Negative Indicates, Number of Threads waiting*/ + +constexpr ULONG MUTEX_READY_TO_BE_ACQUIRED = 0; /*Internal Function*/ @@ -37,95 +37,78 @@ typedef struct _FAST_MUTEX { typedef PFAST_MUTEX PKGUARDED_MUTEX; -/*Internal Functio*/ +/*Internal Function*/ VOID FASTCALL KiAcquireFastMutex( _Inout_ PFAST_MUTEX Mutex ) { - LONG AcquireMarker = {0}; - LONG AcquireBit = {0}; - LONG OldCount = {0}; + LONG OldCount; + LONG NewCount; PAGED_CODE(); /* Increment contention count */ InterlockedIncrement(&Mutex->Contention); - /* Initialize loop variables */ - AcquireMarker = 4; - AcquireBit = 1; - - while(true) + while (TRUE) { /* Read current count */ OldCount = ReadForWriteAccess(&Mutex->Count); - /* Check if mutex is free */ - if ((OldCount & 1) == 0) + /* Check if mutex is free (count == 0) */ + if (OldCount == 0) { - /* Attempt to acquire by incrementing count */ - if (InterlockedCompareExchange(&Mutex->Count, OldCount + AcquireMarker,OldCount) == OldCount) - { - /* Wait for the mutex event */ - KeWaitForSingleObject(&Mutex->Event,WrFastMutex,KernelMode,false,0); - - AcquireMarker = 2; - AcquireBit = 3; - continue; - } - } - else - { - /* Attempt to mark mutex as owned */ - if (InterlockedCompareExchange(&Mutex->Count, AcquireBit ^ OldCount,OldCount) == OldCount) + /* Attempt to acquire by setting count to 1 */ + if (InterlockedCompareExchange(&Mutex->Count, 1, 0) == 0) { /* Mutex acquired successfully */ break; } } + else + { + /* Mutex is owned, increment waiter count (make it more negative) */ + NewCount = OldCount - 1; + if (InterlockedCompareExchange(&Mutex->Count, NewCount, OldCount) == OldCount) + { + /* Wait for the mutex event */ + KeWaitForSingleObject(&Mutex->Event, WrFastMutex, KernelMode, FALSE, NULL); + /* Continue loop to try acquiring again */ + } + } } } +VOID FASTCALL KeReleaseFastMutexContended( IN PFAST_MUTEX FastMutex, IN LONG OldValue) { - BOOLEAN WakeWaiter = false; - LONG NewValue = {0}; - PKTHREAD WokenThread = nullptr; - KPRIORITY HandoffPriority = {0}; + LONG NewValue; - /* Loop until we successfully update the mutex state */ - for (;;) + /* If there are waiters (negative count), wake one up */ + if (OldValue < 0) { - WakeWaiter = false; - NewValue = OldValue + FM_LOCK_BIT; - - if (!(OldValue & FM_LOCK_WAITER_WOKEN)) + /* Increment count (reduce number of waiters) but keep it owned */ + NewValue = OldValue + 1; + if (NewValue == 0) { - NewValue = OldValue - FM_LOCK_BIT; - WakeWaiter = true; + /* No more waiters, mutex becomes free */ + NewValue = 0; + } + + if (InterlockedCompareExchange(&FastMutex->Count, NewValue, OldValue) == OldValue) + { + /* Wake up a waiter */ + KeSetEvent(&FastMutex->Event, IO_NO_INCREMENT, FALSE); } - - LONG PreviousValue = InterlockedCompareExchange(&FastMutex->Lock, NewValue, OldValue); - if (PreviousValue == OldValue) - break; - - OldValue = PreviousValue; - } - - if (WakeWaiter) - { - /* Wake up a waiter */ - KeSetEventBoostPriority(&FastMutex->Event); } } - -/* Exported Function */ +/* Exported Function */ VOID NTAPI @@ -133,14 +116,14 @@ KeInitializeFastMutex( _Out_ PFAST_MUTEX Mutex ) { - /* Initialize the mutex structure */ RtlZeroMemory(Mutex, sizeof(FAST_MUTEX)); - /* Set initial values */ - Mutex->Owner = nullptr; + /* Set initial values - 0 means free/available */ + Mutex->Owner = NULL; Mutex->Contention = 0; - Mutex->Count = 1; + Mutex->Count = 0; // 0 = free + Mutex->RecursionDepth = 0; /* Initialize the Mutex Gate */ KeInitializeEvent(&Mutex->Event, SynchronizationEvent, FALSE); @@ -151,23 +134,25 @@ VECTORCALL KeTryToAcquireFastMutex( _Inout_ PFAST_MUTEX Mutex) { - KIRQL CurrentIrql = KeGetCurrentIrql(); - BOOLEAN Result = false; - if(_InterlockedBitTestAndReset(&FastMutex->Count, MUTEX_READY_TO_BE_AQUIRED)) + KIRQL OldIrql; + + /* Raise IRQL to APC_LEVEL */ + OldIrql = KeRaiseIrqlToSynchLevel(); + + /* Try to acquire the mutex atomically */ + if (InterlockedCompareExchange(&Mutex->Count, 1, 0) == 0) { - FastMutex->Owner = (PVOID)KeGetCurrentThread(); - Mutex->OldIrql = KeRaiseIrql(APC_LEVEL); - Result = TRUE; + /* Successfully acquired */ + Mutex->Owner = (PVOID)KeGetCurrentThread(); + Mutex->OldIrql = OldIrql; + return TRUE; } else { /* Failed to acquire the mutex */ - KeLowerIrql(CurrentIrql); - KeYieldProcessor(); - Result = FALSE; + KeLowerIrql(OldIrql); + return FALSE; } - -return Result; } VOID @@ -175,24 +160,21 @@ NTAPI KeEnterCriticalRegionAndAcquireFastMutexUnsafe( _In_ PFAST_MUTEX FastMutex) { - PKTHREAD OwnerThread = nullptr; - KeEnterCriticalRegion(); + PKTHREAD OwnerThread; - /* Get the current thread again (following the pseudocode) */ + KeEnterCriticalRegion(); + + /* Get the current thread */ OwnerThread = KeGetCurrentThread(); /* Try to acquire the FastMutex */ - if (_InterlockedBitTestAndReset(&FastMutex->Lock, 0)) - { - /* FastMutex was free, we acquired it */ - FastMutex->Owner = OwnerThread; - } - else + if (InterlockedCompareExchange(&FastMutex->Count, 1, 0) != 0) { /* FastMutex was locked, we need to wait */ KiAcquireFastMutex(FastMutex); - FastMutex->Owner = OwnerThread; } + + FastMutex->Owner = OwnerThread; } VOID @@ -200,38 +182,36 @@ FASTCALL KeReleaseFastMutexUnsafeAndLeaveCriticalRegion( _In_ PFAST_MUTEX FastMutex) { - LONG OldValue = {0}; - PKTHREAD CurrentThread = nullptr ; - SHORT NewValue ={0}; + LONG OldValue; /* Clear the owner */ - FastMutex->Owner = nullptr; + FastMutex->Owner = NULL; - /* Try to release the FastMutex */ - OldValue = InterlockedCompareExchange(&FastMutex->Lock, 1, 0); - if (OldValue != 0) + /* Release the FastMutex */ + OldValue = InterlockedExchange(&FastMutex->Count, 0); + + if (OldValue < 0) { - /* Contended case, call the contended release function */ + /* There were waiters, call the contended release function */ KeReleaseFastMutexContended(FastMutex, OldValue); } - /* leave critical region*/ + /* Leave critical region */ KeLeaveCriticalRegion(); } - VOID NTAPI KeAcquireFastMutex( _In_ PFAST_MUTEX FastMutex) { - KIRQL OldIrql = {0}; + KIRQL OldIrql; /* Raise IRQL to APC_LEVEL */ OldIrql = KeRaiseIrqlToSynchLevel(); /* Try to acquire the FastMutex */ - if (InterlockedBitTestAndReset(&FastMutex->Lock, 0) == 0) + if (InterlockedCompareExchange(&FastMutex->Count, 1, 0) != 0) { /* We didn't acquire it, we'll have to wait */ KiAcquireFastMutex(FastMutex); @@ -247,13 +227,13 @@ NTAPI KeAcquireFastMutexUnsafe( _In_ PFAST_MUTEX FastMutex) { - PKTHREAD CurrentThread = nullptr; + PKTHREAD CurrentThread; /* Get the current thread */ CurrentThread = KeGetCurrentThread(); /* Try to acquire the FastMutex */ - if (!InterlockedBitTestAndReset(&FastMutex->Lock, 0)) + if (InterlockedCompareExchange(&FastMutex->Count, 1, 0) != 0) { /* FastMutex was locked, we need to wait */ KiAcquireFastMutex(FastMutex); @@ -269,21 +249,24 @@ KeReleaseFastMutex( _Inout_ PFAST_MUTEX FastMutex ) { - KIRQL OldIrql ={0}; - LONG OldCount ={0}; + KIRQL OldIrql; + LONG OldCount; - FastMutex->Owner = nullptr; + /* Clear owner and get saved IRQL */ + FastMutex->Owner = NULL; OldIrql = FastMutex->OldIrql; - OldCount = InterlockedExchangeAdd(&FastMutex->Count, 1); + /* Release the mutex */ + OldCount = InterlockedExchange(&FastMutex->Count, 0); - if (OldCount != 0 && - (OldCount & 2) == 0 && - InterlockedCompareExchange(&FastMutex->Count, OldCount - 1, OldCount + 1) == OldCount + 1) + /* Check if there were waiters */ + if (OldCount < 0) { + /* Wake up waiters */ KeSetEvent(&FastMutex->Event, IO_NO_INCREMENT, FALSE); } + /* Restore IRQL */ KeLowerIrql(OldIrql); } @@ -292,55 +275,56 @@ NTAPI KeReleaseFastMutexUnsafe( _In_ PFAST_MUTEX FastMutex) { - LONG OldValue = {0}; + LONG OldValue; /* Clear the owner */ - FastMutex->Owner = nullptr; + FastMutex->Owner = NULL; /* Release the lock and get the old value */ - OldValue = InterlockedExchangeAdd(&FastMutex->Lock, 1); + OldValue = InterlockedExchange(&FastMutex->Count, 0); /* Check if there were waiters */ - if (OldValue != 0) + if (OldValue < 0) { - /* Check if no waiter has been woken up yet */ - if ((OldValue & FM_LOCK_WAITER_WOKEN) == 0) - { - /* Try to wake up a waiter */ - if (OldValue + 1 == InterlockedCompareExchange(&FastMutex->Lock, - OldValue - 1, - OldValue + 1)) - { - /* Wake up one waiter */ - KeSetEvent(&FastMutex->Event, IO_NO_INCREMENT, FALSE); - } - } + /* Wake up waiters */ + KeSetEvent(&FastMutex->Event, IO_NO_INCREMENT, FALSE); } } -/*Guarded Mutexes in Modern NT behave just like Fast Mutexes with bit of protection */ +/*Guarded Mutexes in Modern NT behave just like Fast Mutexes with bit of protection */ VOID NTAPI KeInitializeGuardedMutex(_Out_ PKGUARDED_MUTEX GuardedMutex) { - /* Initialize the GuardedMutex*/ - GuardedMutex->Count = 1; - GuardedMutex->Owner = nullptr; + /* Initialize the GuardedMutex */ + GuardedMutex->Count = 0; // 0 = free + GuardedMutex->Owner = NULL; GuardedMutex->Contention = 0; - /* Initialize the Mutex Gate */ - KeInitializeEvent(&Mutex->Event, SynchronizationEvent, FALSE); + GuardedMutex->RecursionDepth = 0; + + /* Initialize the Mutex Gate */ + KeInitializeEvent(&GuardedMutex->Event, SynchronizationEvent, FALSE); } VOID NTAPI KeAcquireGuardedMutex(_Inout_ PKGUARDED_MUTEX Mutex) { - PKTHREAD OwnerThread = KeGetCurrentThread(); - KeEnterGuardedRegion(); - if (!_Interlockedbittestandreset(&Mutex->Count, 0) ) - KiAcquireFastMutex(Mutex); - Mutex->Owner = OwnerThread; + PKTHREAD OwnerThread = KeGetCurrentThread(); + KIRQL OldIrql; + + /* Raise IRQL and enter guarded region */ + OldIrql = KeRaiseIrqlToSynchLevel(); + KeEnterGuardedRegion(); + + if (InterlockedCompareExchange(&Mutex->Count, 1, 0) != 0) + { + KiAcquireFastMutex(Mutex); + } + + Mutex->Owner = OwnerThread; + Mutex->OldIrql = OldIrql; } VOID @@ -349,11 +333,12 @@ KeAcquireGuardedMutexUnsafe( _Inout_ PKGUARDED_MUTEX FastMutex ) { - PKTHREAD CurrentThread = nullptr; + PKTHREAD CurrentThread; + KeEnterGuardedRegion(); CurrentThread = KeGetCurrentThread(); - if (!_InterlockedBitTestAndReset(&FastMutex->Count, 0)) + if (InterlockedCompareExchange(&FastMutex->Count, 1, 0) != 0) { KiAcquireFastMutex(FastMutex); } @@ -367,18 +352,17 @@ KeReleaseGuardedMutexUnsafe( _Inout_ PKGUARDED_MUTEX FastMutex ) { - LONG OldCount ={0}; + LONG OldCount; - FastMutex->Owner = nullptr; + FastMutex->Owner = NULL; - OldCount = _InterlockedExchangeAdd(&FastMutex->Count, 1); + OldCount = InterlockedExchange(&FastMutex->Count, 0); - if (OldCount != 0 && - (OldCount & FM_LOCK_WAITER_WOKEN) == 0 && - OldCount + 1 == InterlockedCompareExchange(&FastMutex->Count, OldCount - 1, OldCount + 1)) + if (OldCount < 0) { KeSetEvent(&FastMutex->Event, IO_NO_INCREMENT, FALSE); } + KeLeaveGuardedRegion(); } @@ -387,57 +371,299 @@ NTAPI KeReleaseGuardedMutex( _In_ PKGUARDED_MUTEX FastMutex) { - KIRQL OldIrql ={0}; - LONG OldValue ={0}; + KIRQL OldIrql; + LONG OldValue; /* Save the old IRQL and clear the owner */ OldIrql = FastMutex->OldIrql; - FastMutex->Owner = nullptr; + FastMutex->Owner = NULL; /* Try to release the FastMutex */ - OldValue = _InterlockedExchangeAdd(&Mutex->Count, 1); - if (OldCount != 0 && - (OldCount & FM_LOCK_WAITER_WOKEN) == 0 && - OldCount + 1 == InterlockedCompareExchange(&FastMutex->Count, OldCount - 1, OldCount + 1)) + OldValue = InterlockedExchange(&FastMutex->Count, 0); + + if (OldValue < 0) { KeSetEvent(&FastMutex->Event, IO_NO_INCREMENT, FALSE); } - /* Lower IRQL */ + /* Lower IRQL and leave guarded region */ KeLowerIrql(OldIrql); KeLeaveGuardedRegion(); } /* Specific to Alcyone, Not found in Windows NT */ -VOID NTAPI KeInitializeRecursiveFastMutex(_Out_ PFAST_MUTEX Mutex) { +VOID +NTAPI +KeInitializeRecursiveFastMutex(_Out_ PFAST_MUTEX Mutex) +{ KeInitializeFastMutex(Mutex); - Mutex->Count |= FM_RECURSIVE_BIT; + /* Mark as recursive by setting the recursive bit in a separate field */ + Mutex->RecursionDepth = -1; // Use -1 to indicate recursive capability } -NTSTATUS NTAPI KeAcquireFastMutexTimeout(_Inout_ PFAST_MUTEX Mutex, _In_ PLARGE_INTEGER Timeout) { - if (KeTryToAcquireFastMutex(Mutex)) { +NTSTATUS +NTAPI +KeAcquireFastMutexTimeout(_Inout_ PFAST_MUTEX Mutex, _In_ PLARGE_INTEGER Timeout) +{ + KIRQL OldIrql; + NTSTATUS Status; + + /* Raise IRQL */ + OldIrql = KeRaiseIrqlToSynchLevel(); + + /* Try to acquire immediately */ + if (InterlockedCompareExchange(&Mutex->Count, 1, 0) == 0) + { + Mutex->Owner = KeGetCurrentThread(); + Mutex->OldIrql = OldIrql; return STATUS_SUCCESS; } - NTSTATUS Status = KeWaitForSingleObject(&Mutex->Event, WrFastMutex, KernelMode, FALSE, Timeout); - if (Status == STATUS_SUCCESS) { - KiAcquireFastMutex(Mutex); + + /* Increment waiter count */ + InterlockedDecrement(&Mutex->Count); + + /* Wait with timeout */ + Status = KeWaitForSingleObject(&Mutex->Event, WrFastMutex, KernelMode, FALSE, Timeout); + + if (Status == STATUS_SUCCESS) + { + /* Try to acquire after being woken up */ + if (InterlockedCompareExchange(&Mutex->Count, 1, 0) == 0) + { + Mutex->Owner = KeGetCurrentThread(); + Mutex->OldIrql = OldIrql; + } + else + { + /* Someone else got it, this shouldn't happen normally */ + KeLowerIrql(OldIrql); + Status = STATUS_TIMEOUT; + } } + else + { + /* Timeout or other error - remove ourselves from waiter count */ + InterlockedIncrement(&Mutex->Count); + KeLowerIrql(OldIrql); + } + return Status; } -BOOLEAN NTAPI KeIsMutexOwned(_In_ PFAST_MUTEX Mutex) { +BOOLEAN +NTAPI +KeIsMutexOwned(_In_ PFAST_MUTEX Mutex) +{ return (Mutex->Owner == KeGetCurrentThread()); } -NTSTATUS NTAPI KeAcquireGuardedMutexTimeout(_Inout_ PKGUARDED_MUTEX Mutex, _In_ PLARGE_INTEGER Timeout) { +NTSTATUS +NTAPI +KeAcquireGuardedMutexTimeout(_Inout_ PKGUARDED_MUTEX Mutex, _In_ PLARGE_INTEGER Timeout) +{ + KIRQL OldIrql; + NTSTATUS Status; + + /* Raise IRQL and enter guarded region */ + OldIrql = KeRaiseIrqlToSynchLevel(); KeEnterGuardedRegion(); - NTSTATUS Status = KeAcquireFastMutexTimeout(Mutex, Timeout); - if (Status != STATUS_SUCCESS) { + + /* Try to acquire immediately */ + if (InterlockedCompareExchange(&Mutex->Count, 1, 0) == 0) + { + Mutex->Owner = KeGetCurrentThread(); + Mutex->OldIrql = OldIrql; + return STATUS_SUCCESS; + } + + /* Increment waiter count */ + InterlockedDecrement(&Mutex->Count); + + /* Wait with timeout */ + Status = KeWaitForSingleObject(&Mutex->Event, WrGuardedMutex, KernelMode, FALSE, Timeout); + + if (Status == STATUS_SUCCESS) + { + /* Try to acquire after being woken up */ + if (InterlockedCompareExchange(&Mutex->Count, 1, 0) == 0) + { + Mutex->Owner = KeGetCurrentThread(); + Mutex->OldIrql = OldIrql; + } + else + { + /* Someone else got it, this shouldn't happen normally */ + KeLowerIrql(OldIrql); + KeLeaveGuardedRegion(); + Status = STATUS_TIMEOUT; + } + } + else + { + /* Timeout or other error - remove ourselves from waiter count */ + InterlockedIncrement(&Mutex->Count); + KeLowerIrql(OldIrql); KeLeaveGuardedRegion(); } + return Status; } +/* Additional Alcyone-specific recursive mutex functions */ +VOID +NTAPI +KeAcquireRecursiveFastMutex(_Inout_ PFAST_MUTEX Mutex) +{ + PKTHREAD CurrentThread = KeGetCurrentThread(); + KIRQL OldIrql; + + /* Check if this is a recursive mutex */ + if (Mutex->RecursionDepth == -1) + { + /* Check if current thread already owns it */ + if (Mutex->Owner == CurrentThread) + { + /* Increment recursion depth */ + InterlockedIncrement(&Mutex->RecursionDepth); + return; + } + } + + /* Not recursive or not owned by current thread - acquire normally */ + OldIrql = KeRaiseIrqlToSynchLevel(); + + if (InterlockedCompareExchange(&Mutex->Count, 1, 0) != 0) + { + KiAcquireFastMutex(Mutex); + } + + Mutex->Owner = CurrentThread; + Mutex->OldIrql = OldIrql; + + /* Set recursion depth to 1 for recursive mutexes */ + if (Mutex->RecursionDepth == -1) + { + Mutex->RecursionDepth = 1; + } +} +VOID +NTAPI +KeReleaseRecursiveFastMutex(_Inout_ PFAST_MUTEX Mutex) +{ + PKTHREAD CurrentThread = KeGetCurrentThread(); + KIRQL OldIrql; + LONG OldCount; + + /* Verify ownership */ + if (Mutex->Owner != CurrentThread) + { + KeBugCheckEx(MUTEX_LEVEL_NUMBER_VIOLATION, + (ULONG_PTR)Mutex, + (ULONG_PTR)CurrentThread, + (ULONG_PTR)Mutex->Owner, + 0); + return; + } + + /* Handle recursive case */ + if (Mutex->RecursionDepth > 1) + { + InterlockedDecrement(&Mutex->RecursionDepth); + return; + } + + /* Clear owner and get saved IRQL */ + Mutex->Owner = NULL; + OldIrql = Mutex->OldIrql; + + /* Reset recursion depth for recursive mutexes */ + if (Mutex->RecursionDepth != 0) + { + Mutex->RecursionDepth = -1; // Mark as recursive but not owned + } + + /* Release the mutex */ + OldCount = InterlockedExchange(&Mutex->Count, 0); + + /* Check if there were waiters */ + if (OldCount < 0) + { + KeSetEvent(&Mutex->Event, IO_NO_INCREMENT, FALSE); + } + + /* Restore IRQL */ + KeLowerIrql(OldIrql); +} + +/* Utility functions for debugging and monitoring */ + +ULONG +NTAPI +KeGetMutexContentionCount(_In_ PFAST_MUTEX Mutex) +{ + return Mutex->Contention; +} + +PKTHREAD +NTAPI +KeGetMutexOwner(_In_ PFAST_MUTEX Mutex) +{ + return (PKTHREAD)Mutex->Owner; +} + +LONG +NTAPI +KeGetMutexRecursionDepth(_In_ PFAST_MUTEX Mutex) +{ + return Mutex->RecursionDepth; +} + +BOOLEAN +NTAPI +KeIsMutexRecursive(_In_ PFAST_MUTEX Mutex) +{ + return (Mutex->RecursionDepth == -1 || Mutex->RecursionDepth > 0); +} + +/* Enhanced try-acquire with recursion support */ + +BOOLEAN +NTAPI +KeTryToAcquireRecursiveFastMutex(_Inout_ PFAST_MUTEX Mutex) +{ + PKTHREAD CurrentThread = KeGetCurrentThread(); + KIRQL OldIrql; + + /* Check if this is a recursive mutex and current thread owns it */ + if (Mutex->RecursionDepth != 0 && Mutex->Owner == CurrentThread) + { + /* Increment recursion depth */ + InterlockedIncrement(&Mutex->RecursionDepth); + return TRUE; + } + + /* Try normal acquisition */ + OldIrql = KeRaiseIrqlToSynchLevel(); + + if (InterlockedCompareExchange(&Mutex->Count, 1, 0) == 0) + { + Mutex->Owner = CurrentThread; + Mutex->OldIrql = OldIrql; + + /* Set recursion depth to 1 for recursive mutexes */ + if (Mutex->RecursionDepth == -1) + { + Mutex->RecursionDepth = 1; + } + + return TRUE; + } + else + { + KeLowerIrql(OldIrql); + return FALSE; + } +} \ No newline at end of file