[RTL][NTDLL] Implement and export RtlInitializeCriticalSectionEx

This commit is contained in:
Timo Kreuzer 2023-08-13 14:03:48 +03:00
parent 1d59cf43af
commit 8f6aaa8af6
2 changed files with 143 additions and 71 deletions

View file

@ -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)

View file

@ -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,6 +612,12 @@ RtlInitializeCriticalSectionAndSpinCount(PRTL_CRITICAL_SECTION CriticalSection,
CriticalSection->SpinCount = (NtCurrentPeb()->NumberOfProcessors > 1) ? SpinCount : 0;
CriticalSection->LockSemaphore = 0;
if (Flags & RTL_CRITICAL_SECTION_FLAG_NO_DEBUG_INFO)
{
CriticalSection->DebugInfo = LongToPtr(-1);
}
else
{
/* Allocate the Debug Data */
CritcalSectionDebugData = RtlpAllocateDebugInfo();
DPRINT("Allocated Debug Data: %p inside Process: %p\n",
@ -627,10 +670,39 @@ RtlInitializeCriticalSectionAndSpinCount(PRTL_CRITICAL_SECTION CriticalSection,
/* 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