[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);
@ -542,6 +546,135 @@ RtlInitializeCriticalSection(PRTL_CRITICAL_SECTION CriticalSection)
return RtlInitializeCriticalSectionAndSpinCount(CriticalSection, 0);
}
/*++
* RtlInitializeCriticalSectionEx
* @implemented NT6.0
*
* Initialises a new critical section.
*
* Params:
* CriticalSection - Critical section to initialise
*
* SpinCount - Spin count for the critical section.
*
* Flags - Flags for initialization.
*
* Returns:
* STATUS_SUCCESS.
*
* Remarks:
* SpinCount is ignored on single-processor systems.
*
*--*/
NTSTATUS
NTAPI
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);
CriticalSection->LockCount = -1;
CriticalSection->RecursionCount = 0;
CriticalSection->OwningThread = 0;
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",
CritcalSectionDebugData,
NtCurrentTeb()->ClientId.UniqueProcess);
if (!CritcalSectionDebugData)
{
/* This is bad! */
DPRINT1("Couldn't allocate Debug Data for: %p\n", CriticalSection);
return STATUS_NO_MEMORY;
}
/* Set it up */
CritcalSectionDebugData->Type = RTL_CRITSECT_TYPE;
CritcalSectionDebugData->ContentionCount = 0;
CritcalSectionDebugData->EntryCount = 0;
CritcalSectionDebugData->CriticalSection = CriticalSection;
CritcalSectionDebugData->Flags = 0;
CriticalSection->DebugInfo = CritcalSectionDebugData;
/*
* 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);
/* Protect List */
RtlEnterCriticalSection(&RtlCriticalSectionLock);
/* 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);
}
}
return STATUS_SUCCESS;
}
/*++
* RtlInitializeCriticalSectionAndSpinCount
* @implemented NT4
@ -562,73 +695,12 @@ RtlInitializeCriticalSection(PRTL_CRITICAL_SECTION CriticalSection)
*--*/
NTSTATUS
NTAPI
RtlInitializeCriticalSectionAndSpinCount(PRTL_CRITICAL_SECTION CriticalSection,
ULONG SpinCount)
RtlInitializeCriticalSectionAndSpinCount(
_Out_ PRTL_CRITICAL_SECTION CriticalSection,
_In_ ULONG SpinCount)
{
PRTL_CRITICAL_SECTION_DEBUG CritcalSectionDebugData;
/* First things first, set up the Object */
DPRINT("Initializing Critical Section: %p\n", CriticalSection);
CriticalSection->LockCount = -1;
CriticalSection->RecursionCount = 0;
CriticalSection->OwningThread = 0;
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)
{
/* This is bad! */
DPRINT1("Couldn't allocate Debug Data for: %p\n", CriticalSection);
return STATUS_NO_MEMORY;
}
/* Set it up */
CritcalSectionDebugData->Type = RTL_CRITSECT_TYPE;
CritcalSectionDebugData->ContentionCount = 0;
CritcalSectionDebugData->EntryCount = 0;
CritcalSectionDebugData->CriticalSection = CriticalSection;
CritcalSectionDebugData->Flags = 0;
CriticalSection->DebugInfo = CritcalSectionDebugData;
/*
* 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);
/* Protect List */
RtlEnterCriticalSection(&RtlCriticalSectionLock);
/* 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);
}
return STATUS_SUCCESS;
SpinCount &= ~RTL_CRITICAL_SECTION_ALL_FLAG_BITS;
return RtlInitializeCriticalSectionEx(CriticalSection, SpinCount, 0);
}
/*++