ntdll: Don't modify LockCount in RtlLeaveCriticalSection if section is not acquired.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Sebastian Lackner <sebastian@fds-team.de>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2017-03-06 12:51:22 +01:00 committed by Alexandre Julliard
parent 533d800d42
commit 14206495e3
2 changed files with 65 additions and 1 deletions

View file

@ -665,7 +665,11 @@ BOOL WINAPI RtlIsCriticalSectionLockedByThread( RTL_CRITICAL_SECTION *crit )
*/
NTSTATUS WINAPI RtlLeaveCriticalSection( RTL_CRITICAL_SECTION *crit )
{
if (--crit->RecursionCount) interlocked_dec( &crit->LockCount );
if (--crit->RecursionCount)
{
if (crit->RecursionCount > 0) interlocked_dec( &crit->LockCount );
else ERR( "section %p is not acquired\n", crit );
}
else
{
crit->OwningThread = 0;

View file

@ -2094,6 +2094,65 @@ static void test_RtlInitializeCriticalSectionEx(void)
RtlDeleteCriticalSection(&cs);
}
static void test_RtlLeaveCriticalSection(void)
{
RTL_CRITICAL_SECTION cs;
NTSTATUS status;
if (!pRtlInitializeCriticalSectionEx)
return; /* Skip winxp */
status = RtlInitializeCriticalSection(&cs);
ok(!status, "RtlInitializeCriticalSection failed: %x\n", status);
status = RtlEnterCriticalSection(&cs);
ok(!status, "RtlEnterCriticalSection failed: %x\n", status);
todo_wine
ok(cs.LockCount == -2, "expected LockCount == -2, got %d\n", cs.LockCount);
ok(cs.RecursionCount == 1, "expected RecursionCount == 1, got %d\n", cs.RecursionCount);
ok(cs.OwningThread == ULongToHandle(GetCurrentThreadId()), "unexpected OwningThread\n");
status = RtlLeaveCriticalSection(&cs);
ok(!status, "RtlLeaveCriticalSection failed: %x\n", status);
ok(cs.LockCount == -1, "expected LockCount == -1, got %d\n", cs.LockCount);
ok(cs.RecursionCount == 0, "expected RecursionCount == 0, got %d\n", cs.RecursionCount);
ok(!cs.OwningThread, "unexpected OwningThread %p\n", cs.OwningThread);
/*
* Trying to leave a section that wasn't acquired modifies RecusionCount to an invalid value,
* but doesn't modify LockCount so that an attempt to enter the section later will work.
*/
status = RtlLeaveCriticalSection(&cs);
ok(!status, "RtlLeaveCriticalSection failed: %x\n", status);
ok(cs.LockCount == -1, "expected LockCount == -1, got %d\n", cs.LockCount);
ok(cs.RecursionCount == -1, "expected RecursionCount == -1, got %d\n", cs.RecursionCount);
ok(!cs.OwningThread, "unexpected OwningThread %p\n", cs.OwningThread);
/* and again */
status = RtlLeaveCriticalSection(&cs);
ok(!status, "RtlLeaveCriticalSection failed: %x\n", status);
ok(cs.LockCount == -1, "expected LockCount == -1, got %d\n", cs.LockCount);
ok(cs.RecursionCount == -2, "expected RecursionCount == -2, got %d\n", cs.RecursionCount);
ok(!cs.OwningThread, "unexpected OwningThread %p\n", cs.OwningThread);
/* entering section fixes RecursionCount */
status = RtlEnterCriticalSection(&cs);
ok(!status, "RtlEnterCriticalSection failed: %x\n", status);
todo_wine
ok(cs.LockCount == -2, "expected LockCount == -2, got %d\n", cs.LockCount);
ok(cs.RecursionCount == 1, "expected RecursionCount == 1, got %d\n", cs.RecursionCount);
ok(cs.OwningThread == ULongToHandle(GetCurrentThreadId()), "unexpected OwningThread\n");
status = RtlLeaveCriticalSection(&cs);
ok(!status, "RtlLeaveCriticalSection failed: %x\n", status);
ok(cs.LockCount == -1, "expected LockCount == -1, got %d\n", cs.LockCount);
ok(cs.RecursionCount == 0, "expected RecursionCount == 0, got %d\n", cs.RecursionCount);
ok(!cs.OwningThread, "unexpected OwningThread %p\n", cs.OwningThread);
status = RtlDeleteCriticalSection(&cs);
ok(!status, "RtlDeleteCriticalSection failed: %x\n", status);
}
START_TEST(rtl)
{
InitFunctionPtrs();
@ -2125,4 +2184,5 @@ START_TEST(rtl)
test_RtlDecompressBuffer();
test_RtlIsCriticalSectionLocked();
test_RtlInitializeCriticalSectionEx();
test_RtlLeaveCriticalSection();
}