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

Reply via email to