From: Paul Gofman pgofman@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57011 --- dlls/kernel32/tests/sync.c | 33 +++++++++++++++++++++++++++++++++ dlls/ntdll/sync.c | 5 ++++- 2 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c index c06ced47298..b26657b07fa 100644 --- a/dlls/kernel32/tests/sync.c +++ b/dlls/kernel32/tests/sync.c @@ -27,6 +27,7 @@ #include <windef.h> #include <winbase.h> #include <winternl.h> +#include <msvcrt/setjmp.h>
#include "wine/test.h"
@@ -2732,9 +2733,26 @@ static void test_apc_deadlock(void) CloseHandle(pi.hProcess); }
+static jmp_buf bad_cs_jmpbuf; + +static LONG WINAPI bad_cs_handler( EXCEPTION_POINTERS *eptr ) +{ + EXCEPTION_RECORD *rec = eptr->ExceptionRecord; + + ok(!rec->NumberParameters, "got %lu.\n", rec->NumberParameters); + ok(rec->ExceptionFlags == EXCEPTION_NONCONTINUABLE + || rec->ExceptionFlags == (EXCEPTION_NONCONTINUABLE | EXCEPTION_SOFTWARE_ORIGINATE), + "got %#lx.\n", rec->ExceptionFlags); + longjmp(bad_cs_jmpbuf, rec->ExceptionCode); + return EXCEPTION_CONTINUE_SEARCH; +} + static void test_crit_section(void) { + void *vectored_handler; CRITICAL_SECTION cs; + int exc_code; + HANDLE old; BOOL ret;
/* Win8+ does not initialize debug info, one has to use RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO @@ -2798,6 +2816,21 @@ static void test_crit_section(void)
DeleteCriticalSection(&cs); ok(cs.DebugInfo == NULL, "Unexpected debug info pointer %p.\n", cs.DebugInfo); + + ret = pInitializeCriticalSectionEx(&cs, 0, 0); + ok(ret, "got error %lu.\n", GetLastError()); + old = cs.LockSemaphore; + cs.LockSemaphore = (HANDLE)0xdeadbeef; + + cs.LockCount = 0; + vectored_handler = AddVectoredExceptionHandler(TRUE, bad_cs_handler); + if (!(exc_code = setjmp(bad_cs_jmpbuf))) + EnterCriticalSection(&cs); + ok(cs.LockCount, "got %ld.\n", cs.LockCount); + ok(exc_code == STATUS_INVALID_HANDLE, "got %#x.\n", exc_code); + RemoveVectoredExceptionHandler(vectored_handler); + cs.LockSemaphore = old; + DeleteCriticalSection(&cs); }
static DWORD WINAPI thread_proc(LPVOID unused) diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c index 139931a595e..522ce0a2142 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c @@ -313,6 +313,7 @@ NTSTATUS WINAPI RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit ) NTSTATUS status = wait_semaphore( crit, timeout );
if (status == STATUS_WAIT_0) break; + if (status != WAIT_TIMEOUT) return status;
timeout = (TRACE_ON(relay) ? 300 : 60);
@@ -368,6 +369,8 @@ NTSTATUS WINAPI RtlEnterCriticalSection( RTL_CRITICAL_SECTION *crit )
if (InterlockedIncrement( &crit->LockCount )) { + NTSTATUS status; + if (crit->OwningThread == ULongToHandle(GetCurrentThreadId())) { crit->RecursionCount++; @@ -375,7 +378,7 @@ NTSTATUS WINAPI RtlEnterCriticalSection( RTL_CRITICAL_SECTION *crit ) }
/* Now wait for it */ - RtlpWaitForCriticalSection( crit ); + if ((status = RtlpWaitForCriticalSection( crit ))) RtlRaiseStatus( status ); } done: crit->OwningThread = ULongToHandle(GetCurrentThreadId());