See https://gitlab.winehq.org/wine/wine/-/merge_requests/5379 , this is an alternative way which doesn't remove MakeCriticalSectionGlobal() functionality.
From: Paul Gofman pgofman@codeweavers.com
--- dlls/kernel32/sync.c | 2 +- dlls/ntdll/sync.c | 37 +++++++++++-------------------------- 2 files changed, 12 insertions(+), 27 deletions(-)
diff --git a/dlls/kernel32/sync.c b/dlls/kernel32/sync.c index 53419cd4618..f1d3a6ef561 100644 --- a/dlls/kernel32/sync.c +++ b/dlls/kernel32/sync.c @@ -128,7 +128,7 @@ void WINAPI MakeCriticalSectionGlobal( CRITICAL_SECTION *crit ) { /* let's assume that only one thread at a time will try to do this */ HANDLE sem = crit->LockSemaphore; - if (!sem) NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 ); + if (!sem || ((ULONG_PTR)sem & 3)) NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 ); crit->LockSemaphore = ConvertToGlobalHandle( sem ); if (crit->DebugInfo != (void *)(ULONG_PTR)-1) RtlFreeHeap( GetProcessHeap(), 0, crit->DebugInfo ); diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c index 00ab614803f..2c950d2bb91 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c @@ -163,29 +163,17 @@ static const char *crit_section_get_name( const RTL_CRITICAL_SECTION *crit )
static inline HANDLE get_semaphore( RTL_CRITICAL_SECTION *crit ) { - HANDLE ret = crit->LockSemaphore; - if (!ret) - { - HANDLE sem; - if (NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 )) return 0; - if (!(ret = InterlockedCompareExchangePointer( &crit->LockSemaphore, sem, 0 ))) - ret = sem; - else - NtClose(sem); /* somebody beat us to it */ - } - return ret; + if (crit->LockSemaphore && !((ULONG_PTR)crit->LockSemaphore & 3)) return crit->LockSemaphore; + return NULL; }
static inline NTSTATUS wait_semaphore( RTL_CRITICAL_SECTION *crit, int timeout ) { LARGE_INTEGER time = {.QuadPart = timeout * (LONGLONG)-10000000}; + HANDLE sem;
/* debug info is cleared by MakeCriticalSectionGlobal */ - if (!crit_section_has_debuginfo( crit )) - { - HANDLE sem = get_semaphore( crit ); - return NtWaitForSingleObject( sem, FALSE, &time ); - } + if ((sem = get_semaphore( crit ))) return NtWaitForSingleObject( sem, FALSE, &time ); else { LONG *lock = (LONG *)&crit->LockSemaphore; @@ -276,6 +264,8 @@ ULONG WINAPI RtlSetCriticalSectionSpinCount( RTL_CRITICAL_SECTION *crit, ULONG s */ NTSTATUS WINAPI RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit ) { + HANDLE sem; + crit->LockCount = -1; crit->RecursionCount = 0; crit->OwningThread = 0; @@ -288,11 +278,9 @@ NTSTATUS WINAPI RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit ) crit->DebugInfo = NULL; } } - else - { - NtClose( crit->LockSemaphore ); - crit->DebugInfo = NULL; - } + else crit->DebugInfo = NULL; + + if ((sem = get_semaphore( crit ))) NtClose( sem ); crit->LockSemaphore = 0; return STATUS_SUCCESS; } @@ -335,13 +323,10 @@ NTSTATUS WINAPI RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit ) NTSTATUS WINAPI RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit ) { NTSTATUS ret; + HANDLE sem;
/* debug info is cleared by MakeCriticalSectionGlobal */ - if (!crit_section_has_debuginfo( crit )) - { - HANDLE sem = get_semaphore( crit ); - ret = NtReleaseSemaphore( sem, 1, NULL ); - } + if ((sem = get_semaphore( crit ))) ret = NtReleaseSemaphore( sem, 1, NULL ); else { LONG *lock = (LONG *)&crit->LockSemaphore;