https://git.reactos.org/?p=reactos.git;a=commitdiff;h=8f6aaa8af64ab752960f9…
commit 8f6aaa8af64ab752960f9404a8b5dfeadaf57b1e
Author: Timo Kreuzer <timo.kreuzer(a)reactos.org>
AuthorDate: Sun Aug 13 14:03:48 2023 +0300
Commit: Timo Kreuzer <timo.kreuzer(a)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