https://git.reactos.org/?p=reactos.git;a=commitdiff;h=8f6aaa8af64ab752960f9404a8b5dfeadaf57b1e
commit 8f6aaa8af64ab752960f9404a8b5dfeadaf57b1e Author: Timo Kreuzer <timo.kreu...@reactos.org> AuthorDate: Sun Aug 13 14:03:48 2023 +0300 Commit: Timo Kreuzer <timo.kreu...@reactos.org> CommitDate: Thu Sep 7 08:36:48 2023 +0300 [RTL][NTDLL] Implement and export RtlInitializeCriticalSectionEx --- dll/ntdll/def/ntdll.spec | 2 +- sdk/lib/rtl/critical.c | 174 +++++++++++++++++++++++++++++++++-------------- 2 files changed, 124 insertions(+), 52 deletions(-) diff --git a/dll/ntdll/def/ntdll.spec b/dll/ntdll/def/ntdll.spec index ee2598f8040..b7659f042d5 100644 --- a/dll/ntdll/def/ntdll.spec +++ b/dll/ntdll/def/ntdll.spec @@ -940,7 +940,7 @@ @ stdcall RtlInitializeContext(ptr ptr ptr ptr ptr) @ stdcall RtlInitializeCriticalSection(ptr) @ stdcall RtlInitializeCriticalSectionAndSpinCount(ptr long) -@ stub -version=0x600+ RtlInitializeCriticalSectionEx +@ stdcall -version=0x600+ RtlInitializeCriticalSectionEx(ptr long long) @ stub -version=0x600+ -arch=i386 RtlInitializeExceptionChain @ stdcall RtlInitializeGenericTable(ptr ptr ptr ptr ptr) @ stdcall RtlInitializeGenericTableAvl(ptr ptr ptr ptr ptr) diff --git a/sdk/lib/rtl/critical.c b/sdk/lib/rtl/critical.c index f2e88481417..0d2ca9913ad 100644 --- a/sdk/lib/rtl/critical.c +++ b/sdk/lib/rtl/critical.c @@ -28,6 +28,10 @@ extern HANDLE LdrpShutdownThreadId; /* FUNCTIONS *****************************************************************/ +#define CRITSECT_HAS_DEBUG_INFO(CriticalSection) \ + (((CriticalSection)->DebugInfo != NULL) && \ + ((CriticalSection)->DebugInfo != LongToPtr(-1))) + /*++ * RtlpCreateCriticalSectionSem * @@ -119,7 +123,7 @@ RtlpWaitForCriticalSection(PRTL_CRITICAL_SECTION CriticalSection) CriticalSection, CriticalSection->LockSemaphore); - if (CriticalSection->DebugInfo) + if (CRITSECT_HAS_DEBUG_INFO(CriticalSection)) CriticalSection->DebugInfo->EntryCount++; /* @@ -142,7 +146,7 @@ RtlpWaitForCriticalSection(PRTL_CRITICAL_SECTION CriticalSection) for (;;) { /* Increase the number of times we've had contention */ - if (CriticalSection->DebugInfo) + if (CRITSECT_HAS_DEBUG_INFO(CriticalSection)) CriticalSection->DebugInfo->ContentionCount++; /* Check if allocating the event failed */ @@ -404,7 +408,7 @@ RtlDeleteCriticalSection(PRTL_CRITICAL_SECTION CriticalSection) /* Protect List */ RtlEnterCriticalSection(&RtlCriticalSectionLock); - if (CriticalSection->DebugInfo) + if (CRITSECT_HAS_DEBUG_INFO(CriticalSection)) { /* Remove it from the list */ RemoveEntryList(&CriticalSection->DebugInfo->ProcessLocksList); @@ -417,7 +421,7 @@ RtlDeleteCriticalSection(PRTL_CRITICAL_SECTION CriticalSection) /* Unprotect */ RtlLeaveCriticalSection(&RtlCriticalSectionLock); - if (CriticalSection->DebugInfo) + if (CRITSECT_HAS_DEBUG_INFO(CriticalSection)) { /* Free it */ RtlpFreeDebugInfo(CriticalSection->DebugInfo); @@ -543,8 +547,8 @@ RtlInitializeCriticalSection(PRTL_CRITICAL_SECTION CriticalSection) } /*++ - * RtlInitializeCriticalSectionAndSpinCount - * @implemented NT4 + * RtlInitializeCriticalSectionEx + * @implemented NT6.0 * * Initialises a new critical section. * @@ -553,6 +557,8 @@ RtlInitializeCriticalSection(PRTL_CRITICAL_SECTION CriticalSection) * * SpinCount - Spin count for the critical section. * + * Flags - Flags for initialization. + * * Returns: * STATUS_SUCCESS. * @@ -562,10 +568,41 @@ RtlInitializeCriticalSection(PRTL_CRITICAL_SECTION CriticalSection) *--*/ NTSTATUS NTAPI -RtlInitializeCriticalSectionAndSpinCount(PRTL_CRITICAL_SECTION CriticalSection, - ULONG SpinCount) +RtlInitializeCriticalSectionEx( + _Out_ PRTL_CRITICAL_SECTION CriticalSection, + _In_ ULONG SpinCount, + _In_ ULONG Flags) { PRTL_CRITICAL_SECTION_DEBUG CritcalSectionDebugData; + ULONG AllowedFlags; + ULONG OsVersion; + + /* Remove lower bits from flags */ + Flags &= RTL_CRITICAL_SECTION_ALL_FLAG_BITS; + + /* These flags generally allowed */ + AllowedFlags = RTL_CRITICAL_SECTION_FLAG_NO_DEBUG_INFO | + RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN | + RTL_CRITICAL_SECTION_FLAG_STATIC_INIT; + + /* Flags for Windows 7+ (CHECKME) */ + OsVersion = NtCurrentPeb()->OSMajorVersion << 8 | + NtCurrentPeb()->OSMinorVersion; + if (OsVersion >= _WIN32_WINNT_WIN7) + { + AllowedFlags |= RTL_CRITICAL_SECTION_FLAG_RESOURCE_TYPE | + RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO; + } + + if (Flags & ~AllowedFlags) + { + return STATUS_INVALID_PARAMETER_3; + } + + if (SpinCount & RTL_CRITICAL_SECTION_ALL_FLAG_BITS) + { + return STATUS_INVALID_PARAMETER_2; + } /* First things first, set up the Object */ DPRINT("Initializing Critical Section: %p\n", CriticalSection); @@ -575,62 +612,97 @@ RtlInitializeCriticalSectionAndSpinCount(PRTL_CRITICAL_SECTION CriticalSection, CriticalSection->SpinCount = (NtCurrentPeb()->NumberOfProcessors > 1) ? SpinCount : 0; CriticalSection->LockSemaphore = 0; - /* Allocate the Debug Data */ - CritcalSectionDebugData = RtlpAllocateDebugInfo(); - DPRINT("Allocated Debug Data: %p inside Process: %p\n", - CritcalSectionDebugData, - NtCurrentTeb()->ClientId.UniqueProcess); - - if (!CritcalSectionDebugData) + if (Flags & RTL_CRITICAL_SECTION_FLAG_NO_DEBUG_INFO) { - /* This is bad! */ - DPRINT1("Couldn't allocate Debug Data for: %p\n", CriticalSection); - return STATUS_NO_MEMORY; + CriticalSection->DebugInfo = LongToPtr(-1); } + else + { + /* Allocate the Debug Data */ + CritcalSectionDebugData = RtlpAllocateDebugInfo(); + DPRINT("Allocated Debug Data: %p inside Process: %p\n", + CritcalSectionDebugData, + NtCurrentTeb()->ClientId.UniqueProcess); - /* Set it up */ - CritcalSectionDebugData->Type = RTL_CRITSECT_TYPE; - CritcalSectionDebugData->ContentionCount = 0; - CritcalSectionDebugData->EntryCount = 0; - CritcalSectionDebugData->CriticalSection = CriticalSection; - CritcalSectionDebugData->Flags = 0; - CriticalSection->DebugInfo = CritcalSectionDebugData; + if (!CritcalSectionDebugData) + { + /* This is bad! */ + DPRINT1("Couldn't allocate Debug Data for: %p\n", CriticalSection); + return STATUS_NO_MEMORY; + } - /* - * Add it to the List of Critical Sections owned by the process. - * If we've initialized the Lock, then use it. If not, then probably - * this is the lock initialization itself, so insert it directly. - */ - if ((CriticalSection != &RtlCriticalSectionLock) && (RtlpCritSectInitialized)) - { - DPRINT("Securely Inserting into ProcessLocks: %p, %p, %p\n", - &CritcalSectionDebugData->ProcessLocksList, - CriticalSection, - &RtlCriticalSectionList); + /* Set it up */ + CritcalSectionDebugData->Type = RTL_CRITSECT_TYPE; + CritcalSectionDebugData->ContentionCount = 0; + CritcalSectionDebugData->EntryCount = 0; + CritcalSectionDebugData->CriticalSection = CriticalSection; + CritcalSectionDebugData->Flags = 0; + CriticalSection->DebugInfo = CritcalSectionDebugData; - /* Protect List */ - RtlEnterCriticalSection(&RtlCriticalSectionLock); + /* + * Add it to the List of Critical Sections owned by the process. + * If we've initialized the Lock, then use it. If not, then probably + * this is the lock initialization itself, so insert it directly. + */ + if ((CriticalSection != &RtlCriticalSectionLock) && (RtlpCritSectInitialized)) + { + DPRINT("Securely Inserting into ProcessLocks: %p, %p, %p\n", + &CritcalSectionDebugData->ProcessLocksList, + CriticalSection, + &RtlCriticalSectionList); - /* Add this one */ - InsertTailList(&RtlCriticalSectionList, &CritcalSectionDebugData->ProcessLocksList); + /* Protect List */ + RtlEnterCriticalSection(&RtlCriticalSectionLock); - /* Unprotect */ - RtlLeaveCriticalSection(&RtlCriticalSectionLock); - } - else - { - DPRINT("Inserting into ProcessLocks: %p, %p, %p\n", - &CritcalSectionDebugData->ProcessLocksList, - CriticalSection, - &RtlCriticalSectionList); + /* Add this one */ + InsertTailList(&RtlCriticalSectionList, &CritcalSectionDebugData->ProcessLocksList); + + /* Unprotect */ + RtlLeaveCriticalSection(&RtlCriticalSectionLock); + } + else + { + DPRINT("Inserting into ProcessLocks: %p, %p, %p\n", + &CritcalSectionDebugData->ProcessLocksList, + CriticalSection, + &RtlCriticalSectionList); - /* Add it directly */ - InsertTailList(&RtlCriticalSectionList, &CritcalSectionDebugData->ProcessLocksList); + /* Add it directly */ + InsertTailList(&RtlCriticalSectionList, &CritcalSectionDebugData->ProcessLocksList); + } } return STATUS_SUCCESS; } +/*++ + * RtlInitializeCriticalSectionAndSpinCount + * @implemented NT4 + * + * Initialises a new critical section. + * + * Params: + * CriticalSection - Critical section to initialise + * + * SpinCount - Spin count for the critical section. + * + * Returns: + * STATUS_SUCCESS. + * + * Remarks: + * SpinCount is ignored on single-processor systems. + * + *--*/ +NTSTATUS +NTAPI +RtlInitializeCriticalSectionAndSpinCount( + _Out_ PRTL_CRITICAL_SECTION CriticalSection, + _In_ ULONG SpinCount) +{ + SpinCount &= ~RTL_CRITICAL_SECTION_ALL_FLAG_BITS; + return RtlInitializeCriticalSectionEx(CriticalSection, SpinCount, 0); +} + /*++ * RtlGetCriticalSectionRecursionCount * @implemented NT5.2 SP1