From: Alex Ionescu Date: Thu, 8 Sep 2005 02:29:30 +0000 (+0000) Subject: - Move more stuff to /rtl X-Git-Tag: ReactOS-0.2.8~683 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=7206207210e08ce6db9ad98d496c82532415a146 - Move more stuff to /rtl - Bring back Ki* callbacks into ntdll. svn path=/trunk/; revision=17732 --- diff --git a/reactos/lib/ntdll/def/ntdll.def b/reactos/lib/ntdll/def/ntdll.def index 6674365ad7d..1fd10bd093f 100644 --- a/reactos/lib/ntdll/def/ntdll.def +++ b/reactos/lib/ntdll/def/ntdll.def @@ -317,7 +317,6 @@ RtlAreAnyAccessesGranted@8 RtlAreBitsClear@12 RtlAreBitsSet@12 RtlAssert@16 -RtlBaseProcessStartRoutine DATA ;RtlCaptureStackBackTrace RtlCharToInteger@12 RtlCheckRegistryKey@8 diff --git a/reactos/lib/ntdll/inc/ntdllp.h b/reactos/lib/ntdll/inc/ntdllp.h index 70a645d664a..7b8dad8d3d8 100644 --- a/reactos/lib/ntdll/inc/ntdllp.h +++ b/reactos/lib/ntdll/inc/ntdllp.h @@ -27,50 +27,11 @@ typedef BOOL (STDCALL *PDLLMAIN_FUNC)(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved); -VOID -STDCALL -RtlpInitDeferedCriticalSection( - VOID -); + #if defined(KDBG) || defined(DBG) VOID LdrpLoadUserModuleSymbols(PLDR_DATA_TABLE_ENTRY LdrModule); #endif extern HANDLE WindowsApiPort; -NTSTATUS -STDCALL -RtlpWaitForCriticalSection( - PRTL_CRITICAL_SECTION CriticalSection -); - -VOID -STDCALL -RtlpUnWaitCriticalSection( - PRTL_CRITICAL_SECTION CriticalSection -); - -VOID -STDCALL -RtlpCreateCriticalSectionSem( - PRTL_CRITICAL_SECTION CriticalSection -); - -VOID -STDCALL -RtlpInitDeferedCriticalSection( - VOID -); - -VOID -STDCALL -RtlpFreeDebugInfo( - PRTL_CRITICAL_SECTION_DEBUG DebugInfo -); - -PRTL_CRITICAL_SECTION_DEBUG -STDCALL -RtlpAllocateDebugInfo( - VOID -); /* EOF */ diff --git a/reactos/lib/ntdll/ldr/startup.c b/reactos/lib/ntdll/ldr/startup.c index f8b275c9870..5ad16c8ce77 100644 --- a/reactos/lib/ntdll/ldr/startup.c +++ b/reactos/lib/ntdll/ldr/startup.c @@ -17,6 +17,7 @@ VOID RtlInitializeHeapManager (VOID); VOID LdrpInitLoader(VOID); +VOID STDCALL RtlpInitDeferedCriticalSection(VOID); /* GLOBALS *******************************************************************/ diff --git a/reactos/lib/ntdll/main/dispatch.c b/reactos/lib/ntdll/main/dispatch.c new file mode 100644 index 00000000000..6b2774dcd4d --- /dev/null +++ b/reactos/lib/ntdll/main/dispatch.c @@ -0,0 +1,121 @@ +/* COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * PURPOSE: User-mode APC support + * FILE: lib/ntdll/main/dispatch.c + * PROGRAMER: David Welch + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include + +typedef NTSTATUS (STDCALL *KERNEL_CALLBACK_FUNCTION)(PVOID Argument, + ULONG ArgumentLength); + +EXCEPTION_DISPOSITION +RtlpExecuteVectoredExceptionHandlers(IN PEXCEPTION_RECORD ExceptionRecord, + IN PCONTEXT Context); + +ULONG +RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord, + IN PCONTEXT Context); +/* FUNCTIONS ****************************************************************/ + +/* + * @implemented + */ +VOID +STDCALL +KiUserApcDispatcher(PIO_APC_ROUTINE ApcRoutine, + PVOID ApcContext, + PIO_STATUS_BLOCK Iosb, + ULONG Reserved, + PCONTEXT Context) +{ + /* + * Call the APC + */ + //DPRINT1("ITS ME\n"); + ApcRoutine(ApcContext, + Iosb, + Reserved); + /* + * Switch back to the interrupted context + */ + //DPRINT1("switch back\n"); + NtContinue(Context, 1); +} + +/* + * @implemented + */ +VOID +STDCALL +KiUserExceptionDispatcher(PEXCEPTION_RECORD ExceptionRecord, + PCONTEXT Context) +{ + EXCEPTION_RECORD NestedExceptionRecord; + NTSTATUS Status; + + if(RtlpExecuteVectoredExceptionHandlers(ExceptionRecord, + Context) != ExceptionContinueExecution) + { + Status = NtContinue(Context, FALSE); + } + else + { + if(RtlpDispatchException(ExceptionRecord, Context) != ExceptionContinueExecution) + { + Status = NtContinue(Context, FALSE); + } + else + { + Status = NtRaiseException(ExceptionRecord, Context, FALSE); + } + } + + NestedExceptionRecord.ExceptionCode = Status; + NestedExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE; + NestedExceptionRecord.ExceptionRecord = ExceptionRecord; + NestedExceptionRecord.NumberParameters = Status; + + RtlRaiseException(&NestedExceptionRecord); +} + +/* + * @implemented + */ +VOID +STDCALL +KiRaiseUserExceptionDispatcher(VOID) +{ + EXCEPTION_RECORD ExceptionRecord; + + ExceptionRecord.ExceptionCode = ((PTEB)NtCurrentTeb())->ExceptionCode; + ExceptionRecord.ExceptionFlags = 0; + ExceptionRecord.ExceptionRecord = NULL; + ExceptionRecord.NumberParameters = 0; + + RtlRaiseException(&ExceptionRecord); +} + +/* + * @implemented + */ +VOID +STDCALL +KiUserCallbackDispatcher(ULONG RoutineIndex, + PVOID Argument, + ULONG ArgumentLength) +{ + PPEB Peb; + NTSTATUS Status; + KERNEL_CALLBACK_FUNCTION Callback; + + Peb = NtCurrentPeb(); + Callback = (KERNEL_CALLBACK_FUNCTION)Peb->KernelCallbackTable[RoutineIndex]; + Status = Callback(Argument, ArgumentLength); + ZwCallbackReturn(NULL, 0, Status); +} diff --git a/reactos/lib/ntdll/ntdll.xml b/reactos/lib/ntdll/ntdll.xml index 4244a5fa295..db6ef03f265 100644 --- a/reactos/lib/ntdll/ntdll.xml +++ b/reactos/lib/ntdll/ntdll.xml @@ -29,13 +29,11 @@ utils.c + dispatch.c dllmain.c - critical.c - exception.c libsupp.c - path.c version.c diff --git a/reactos/lib/ntdll/rtl/libsupp.c b/reactos/lib/ntdll/rtl/libsupp.c index eb67ddad1c6..b92354de2b4 100644 --- a/reactos/lib/ntdll/rtl/libsupp.c +++ b/reactos/lib/ntdll/rtl/libsupp.c @@ -61,6 +61,38 @@ RtlGetNtGlobalFlags(VOID) return pPeb->NtGlobalFlag; } +NTSTATUS +STDCALL +RtlDeleteHeapLock( + PRTL_CRITICAL_SECTION CriticalSection) +{ + return RtlDeleteCriticalSection(CriticalSection); +} + +NTSTATUS +STDCALL +RtlEnterHeapLock( + PRTL_CRITICAL_SECTION CriticalSection) +{ + return RtlEnterCriticalSection(CriticalSection); +} + +NTSTATUS +STDCALL +RtlInitializeHeapLock( + PRTL_CRITICAL_SECTION CriticalSection) +{ + return RtlInitializeCriticalSection(CriticalSection ); +} + +NTSTATUS +STDCALL +RtlLeaveHeapLock( + PRTL_CRITICAL_SECTION CriticalSection) +{ + return RtlLeaveCriticalSection(CriticalSection ); +} + PVOID STDCALL RtlpAllocateMemory(UINT Bytes, diff --git a/reactos/lib/rtl/apc.c b/reactos/lib/rtl/apc.c deleted file mode 100644 index a2ffb28ea0f..00000000000 --- a/reactos/lib/rtl/apc.c +++ /dev/null @@ -1,37 +0,0 @@ -/* COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * PURPOSE: User-mode APC support - * FILE: lib/rtl/apc.c - * PROGRAMER: David Welch - */ - -/* INCLUDES *****************************************************************/ - -#include - -#define NDEBUG -#include - -/* FUNCTIONS ****************************************************************/ - -VOID STDCALL -KiUserApcDispatcher(PIO_APC_ROUTINE ApcRoutine, - PVOID ApcContext, - PIO_STATUS_BLOCK Iosb, - ULONG Reserved, - PCONTEXT Context) -{ - /* - * Call the APC - */ - //DPRINT1("ITS ME\n"); - ApcRoutine(ApcContext, - Iosb, - Reserved); - /* - * Switch back to the interrupted context - */ - //DPRINT1("switch back\n"); - NtContinue(Context, 1); -} - diff --git a/reactos/lib/rtl/callback.c b/reactos/lib/rtl/callback.c deleted file mode 100644 index 5bdeda91456..00000000000 --- a/reactos/lib/rtl/callback.c +++ /dev/null @@ -1,35 +0,0 @@ -/* COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * PURPOSE: User-mode callback support - * FILE: lib/rtl/callback.c - * PROGRAMER: David Welch - */ - -/* INCLUDES *****************************************************************/ - -#include - -#define NDEBUG -#include - -/* FUNCTIONS *****************************************************************/ - -typedef NTSTATUS (STDCALL *KERNEL_CALLBACK_FUNCTION)(PVOID Argument, - ULONG ArgumentLength); - -/* FUNCTIONS *****************************************************************/ - -VOID STDCALL -KiUserCallbackDispatcher(ULONG RoutineIndex, - PVOID Argument, - ULONG ArgumentLength) -{ - PPEB Peb; - NTSTATUS Status; - KERNEL_CALLBACK_FUNCTION Callback; - - Peb = NtCurrentPeb(); - Callback = (KERNEL_CALLBACK_FUNCTION)Peb->KernelCallbackTable[RoutineIndex]; - Status = Callback(Argument, ArgumentLength); - ZwCallbackReturn(NULL, 0, Status); -} diff --git a/reactos/lib/ntdll/rtl/critical.c b/reactos/lib/rtl/critical.c similarity index 90% rename from reactos/lib/ntdll/rtl/critical.c rename to reactos/lib/rtl/critical.c index 60b5de0af20..aa4622ae465 100644 --- a/reactos/lib/ntdll/rtl/critical.c +++ b/reactos/lib/rtl/critical.c @@ -1,693 +1,676 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/ntdll/rtl/critical.c - * PURPOSE: Critical sections - * UPDATE HISTORY: - * Created 30/09/98 - * Rewritten ROS version, based on WINE code plus - * some fixes useful only for ROS right now - 03/01/05 - */ - -/* INCLUDES ******************************************************************/ - -#include -#define NDEBUG -#include - -/* FUNCTIONS *****************************************************************/ - -#define MAX_STATIC_CS_DEBUG_OBJECTS 64 - -static RTL_CRITICAL_SECTION RtlCriticalSectionLock; -static LIST_ENTRY RtlCriticalSectionList; -static BOOLEAN RtlpCritSectInitialized = FALSE; -static RTL_CRITICAL_SECTION_DEBUG RtlpStaticDebugInfo[MAX_STATIC_CS_DEBUG_OBJECTS]; -static BOOLEAN RtlpDebugInfoFreeList[MAX_STATIC_CS_DEBUG_OBJECTS]; - -/*++ - * RtlDeleteCriticalSection - * @implemented NT4 - * - * Deletes a Critical Section - * - * Params: - * CriticalSection - Critical section to delete. - * - * Returns: - * STATUS_SUCCESS, or error value returned by NtClose. - * - * Remarks: - * The critical section members should not be read after this call. - * - *--*/ -NTSTATUS -STDCALL -RtlDeleteCriticalSection( - PRTL_CRITICAL_SECTION CriticalSection) -{ - NTSTATUS Status = STATUS_SUCCESS; - - DPRINT("Deleting Critical Section: %x\n", CriticalSection); - /* Close the Event Object Handle if it exists */ - if (CriticalSection->LockSemaphore) { - - /* In case NtClose fails, return the status */ - Status = NtClose(CriticalSection->LockSemaphore); - - } - - /* Protect List */ - RtlEnterCriticalSection(&RtlCriticalSectionLock); - - /* Remove it from the list */ - RemoveEntryList(&CriticalSection->DebugInfo->ProcessLocksList); - - /* Unprotect */ - RtlLeaveCriticalSection(&RtlCriticalSectionLock); - - /* Free it */ - RtlpFreeDebugInfo(CriticalSection->DebugInfo); - - /* Wipe it out */ - RtlZeroMemory(CriticalSection, sizeof(RTL_CRITICAL_SECTION)); - - /* Return */ - return Status; -} - -/*++ - * RtlSetCriticalSectionSpinCount - * @implemented NT4 - * - * Sets the spin count for a critical section. - * - * Params: - * CriticalSection - Critical section to set the spin count for. - * - * SpinCount - Spin count for the critical section. - * - * Returns: - * STATUS_SUCCESS. - * - * Remarks: - * SpinCount is ignored on single-processor systems. - * - *--*/ -DWORD -STDCALL -RtlSetCriticalSectionSpinCount( - PRTL_CRITICAL_SECTION CriticalSection, - ULONG SpinCount - ) -{ - ULONG OldCount = CriticalSection->SpinCount; - - /* Set to parameter if MP, or to 0 if this is Uniprocessor */ - CriticalSection->SpinCount = (NtCurrentPeb()->NumberOfProcessors > 1) ? SpinCount : 0; - return OldCount; -} - -/*++ - * RtlEnterCriticalSection - * @implemented NT4 - * - * Waits to gain ownership of the critical section. - * - * Params: - * CriticalSection - Critical section to wait for. - * - * Returns: - * STATUS_SUCCESS. - * - * Remarks: - * Uses a fast-path unless contention happens. - * - *--*/ -NTSTATUS -STDCALL -RtlEnterCriticalSection( - PRTL_CRITICAL_SECTION CriticalSection) -{ - HANDLE Thread = (HANDLE)NtCurrentTeb()->Cid.UniqueThread; - - /* Try to Lock it */ - if (InterlockedIncrement(&CriticalSection->LockCount) != 0) { - - /* - * We've failed to lock it! Does this thread - * actually own it? - */ - if (Thread == CriticalSection->OwningThread) { - - /* You own it, so you'll get it when you're done with it! No need to - use the interlocked functions as only the thread who already owns - the lock can modify this data. */ - CriticalSection->RecursionCount++; - return STATUS_SUCCESS; - } - - /* NOTE - CriticalSection->OwningThread can be NULL here because changing - this information is not serialized. This happens when thread a - acquires the lock (LockCount == 0) and thread b tries to - acquire it as well (LockCount == 1) but thread a hasn't had a - chance to set the OwningThread! So it's not an error when - OwningThread is NULL here! */ - - /* We don't own it, so we must wait for it */ - RtlpWaitForCriticalSection(CriticalSection); - } - - /* Lock successful. Changing this information has not to be serialized because - only one thread at a time can actually change it (the one who acquired - the lock)! */ - CriticalSection->OwningThread = Thread; - CriticalSection->RecursionCount = 1; - return STATUS_SUCCESS; -} - -/*++ - * RtlInitializeCriticalSection - * @implemented NT4 - * - * Initialises a new critical section. - * - * Params: - * CriticalSection - Critical section to initialise - * - * Returns: - * STATUS_SUCCESS. - * - * Remarks: - * Simply calls RtlInitializeCriticalSectionAndSpinCount - * - *--*/ -NTSTATUS -STDCALL -RtlInitializeCriticalSection( - PRTL_CRITICAL_SECTION CriticalSection) -{ - /* Call the Main Function */ - return RtlInitializeCriticalSectionAndSpinCount(CriticalSection, 0); -} - -/*++ - * 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 -STDCALL -RtlInitializeCriticalSectionAndSpinCount ( - PRTL_CRITICAL_SECTION CriticalSection, - ULONG SpinCount) -{ - PRTL_CRITICAL_SECTION_DEBUG CritcalSectionDebugData; - - /* First things first, set up the Object */ - DPRINT("Initializing Critical Section: %x\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: %x inside Process: %x\n", - CritcalSectionDebugData, - NtCurrentTeb()->Cid.UniqueProcess); - - if (!CritcalSectionDebugData) { - - /* This is bad! */ - DPRINT1("Couldn't allocate Debug Data for: %x\n", CriticalSection); - return STATUS_NO_MEMORY; - } - - /* Set it up */ - CritcalSectionDebugData->Type = RTL_CRITSECT_TYPE; - CritcalSectionDebugData->ContentionCount = 0; - CritcalSectionDebugData->EntryCount = 0; - CritcalSectionDebugData->CriticalSection = CriticalSection; - 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: %x, %x, %x\n", - &CritcalSectionDebugData->ProcessLocksList, - CriticalSection, - &RtlCriticalSectionList); - - /* Protect List */ - RtlEnterCriticalSection(&RtlCriticalSectionLock); - - /* Add this one */ - InsertTailList(&RtlCriticalSectionList, &CritcalSectionDebugData->ProcessLocksList); - - /* Unprotect */ - RtlLeaveCriticalSection(&RtlCriticalSectionLock); - - } else { - - DPRINT("Inserting into ProcessLocks: %x, %x, %x\n", - &CritcalSectionDebugData->ProcessLocksList, - CriticalSection, - &RtlCriticalSectionList); - - /* Add it directly */ - InsertTailList(&RtlCriticalSectionList, &CritcalSectionDebugData->ProcessLocksList); - } - - return STATUS_SUCCESS; -} - -/*++ - * RtlLeaveCriticalSection - * @implemented NT4 - * - * Releases a critical section and makes if available for new owners. - * - * Params: - * CriticalSection - Critical section to release. - * - * Returns: - * STATUS_SUCCESS. - * - * Remarks: - * If another thread was waiting, the slow path is entered. - * - *--*/ -NTSTATUS -STDCALL -RtlLeaveCriticalSection( - PRTL_CRITICAL_SECTION CriticalSection) -{ -#ifndef NDEBUG - HANDLE Thread = (HANDLE)NtCurrentTeb()->Cid.UniqueThread; - - /* In win this case isn't checked. However it's a valid check so it should only - be performed in debug builds! */ - if (Thread != CriticalSection->OwningThread) - { - DPRINT1("Releasing critical section not owned!\n"); - return STATUS_INVALID_PARAMETER; - } -#endif - - /* Decrease the Recursion Count. No need to do this atomically because only - the thread who holds the lock can call this function (unless the program - is totally screwed... */ - if (--CriticalSection->RecursionCount) { - - /* Someone still owns us, but we are free. This needs to be done atomically. */ - InterlockedDecrement(&CriticalSection->LockCount); - - } else { - - /* Nobody owns us anymore. No need to do this atomically. See comment - above. */ - CriticalSection->OwningThread = 0; - - /* Was someone wanting us? This needs to be done atomically. */ - if (-1 != InterlockedDecrement(&CriticalSection->LockCount)) { - - /* Let him have us */ - RtlpUnWaitCriticalSection(CriticalSection); - } - } - - /* Sucessful! */ - return STATUS_SUCCESS; -} - -/*++ - * RtlTryEnterCriticalSection - * @implemented NT4 - * - * Attemps to gain ownership of the critical section without waiting. - * - * Params: - * CriticalSection - Critical section to attempt acquiring. - * - * Returns: - * TRUE if the critical section has been acquired, FALSE otherwise. - * - * Remarks: - * None - * - *--*/ -BOOLEAN -STDCALL -RtlTryEnterCriticalSection( - PRTL_CRITICAL_SECTION CriticalSection) -{ - /* Try to take control */ - if (InterlockedCompareExchange(&CriticalSection->LockCount, - 0, - -1) == -1) { - - /* It's ours */ - CriticalSection->OwningThread = NtCurrentTeb()->Cid.UniqueThread; - CriticalSection->RecursionCount = 1; - return TRUE; - - } else if (CriticalSection->OwningThread == NtCurrentTeb()->Cid.UniqueThread) { - - /* It's already ours */ - InterlockedIncrement(&CriticalSection->LockCount); - CriticalSection->RecursionCount++; - return TRUE; - } - - /* It's not ours */ - return FALSE; -} - -/*++ - * RtlpWaitForCriticalSection - * - * Slow path of RtlEnterCriticalSection. Waits on an Event Object. - * - * Params: - * CriticalSection - Critical section to acquire. - * - * Returns: - * STATUS_SUCCESS, or raises an exception if a deadlock is occuring. - * - * Remarks: - * None - * - *--*/ -NTSTATUS -STDCALL -RtlpWaitForCriticalSection( - PRTL_CRITICAL_SECTION CriticalSection) -{ - NTSTATUS Status; - EXCEPTION_RECORD ExceptionRecord; - BOOLEAN LastChance = FALSE; - LARGE_INTEGER Timeout; - - /* Wait 2.5 minutes */ - Timeout.QuadPart = 150000L * (ULONGLONG)10000; - Timeout.QuadPart = -Timeout.QuadPart; - /* ^^ HACK HACK HACK. Good way: - Timeout = &NtCurrentPeb()->CriticalSectionTimeout */ - - /* Do we have an Event yet? */ - if (!CriticalSection->LockSemaphore) { - RtlpCreateCriticalSectionSem(CriticalSection); - } - - /* Increase the Debug Entry count */ - DPRINT("Waiting on Critical Section Event: %x %x\n", - CriticalSection, - CriticalSection->LockSemaphore); - CriticalSection->DebugInfo->EntryCount++; - - for (;;) { - - /* Increase the number of times we've had contention */ - CriticalSection->DebugInfo->ContentionCount++; - - /* Wait on the Event */ - Status = NtWaitForSingleObject(CriticalSection->LockSemaphore, - FALSE, - &Timeout); - - /* We have Timed out */ - if (Status == STATUS_TIMEOUT) { - - /* Is this the 2nd time we've timed out? */ - if (LastChance) { - - DPRINT1("Deadlock: %x\n", CriticalSection); - - /* Yes it is, we are raising an exception */ - ExceptionRecord.ExceptionCode = STATUS_POSSIBLE_DEADLOCK; - ExceptionRecord.ExceptionFlags = 0; - ExceptionRecord.ExceptionRecord = NULL; - ExceptionRecord.ExceptionAddress = RtlRaiseException; - ExceptionRecord.NumberParameters = 1; - ExceptionRecord.ExceptionInformation[0] = (ULONG_PTR)CriticalSection; - RtlRaiseException(&ExceptionRecord); - - } - - /* One more try */ - LastChance = TRUE; - - } else { - - /* If we are here, everything went fine */ - return STATUS_SUCCESS; - } - } -} - -/*++ - * RtlpUnWaitCriticalSection - * - * Slow path of RtlLeaveCriticalSection. Fires an Event Object. - * - * Params: - * CriticalSection - Critical section to release. - * - * Returns: - * None. Raises an exception if the system call failed. - * - * Remarks: - * None - * - *--*/ -VOID -STDCALL -RtlpUnWaitCriticalSection( - PRTL_CRITICAL_SECTION CriticalSection) - -{ - NTSTATUS Status; - - /* Do we have an Event yet? */ - if (!CriticalSection->LockSemaphore) { - RtlpCreateCriticalSectionSem(CriticalSection); - } - - /* Signal the Event */ - DPRINT("Signaling Critical Section Event: %x, %x\n", - CriticalSection, - CriticalSection->LockSemaphore); - Status = NtSetEvent(CriticalSection->LockSemaphore, NULL); - - if (!NT_SUCCESS(Status)) { - - /* We've failed */ - DPRINT1("Signaling Failed for: %x, %x, %x\n", - CriticalSection, - CriticalSection->LockSemaphore, - Status); - RtlRaiseStatus(Status); - } -} - -/*++ - * RtlpCreateCriticalSectionSem - * - * Checks if an Event has been created for the critical section. - * - * Params: - * None - * - * Returns: - * None. Raises an exception if the system call failed. - * - * Remarks: - * None - * - *--*/ -VOID -STDCALL -RtlpCreateCriticalSectionSem( - PRTL_CRITICAL_SECTION CriticalSection) -{ - HANDLE hEvent = CriticalSection->LockSemaphore; - HANDLE hNewEvent; - NTSTATUS Status; - - /* Chevk if we have an event */ - if (!hEvent) { - - /* No, so create it */ - if (!NT_SUCCESS(Status = NtCreateEvent(&hNewEvent, - EVENT_ALL_ACCESS, - NULL, - SynchronizationEvent, - FALSE))) { - - /* We failed, this is bad... */ - DPRINT1("Failed to Create Event!\n"); - InterlockedDecrement(&CriticalSection->LockCount); - RtlRaiseStatus(Status); - return; - } - DPRINT("Created Event: %x \n", hNewEvent); - - if ((hEvent = InterlockedCompareExchangePointer((PVOID*)&CriticalSection->LockSemaphore, - (PVOID)hNewEvent, - 0))) { - - /* Some just created an event */ - DPRINT("Closing already created event: %x\n", hNewEvent); - NtClose(hNewEvent); - } - } - - return; -} - -/*++ - * RtlpInitDeferedCriticalSection - * - * Initializes the Critical Section implementation. - * - * Params: - * None - * - * Returns: - * None. - * - * Remarks: - * After this call, the Process Critical Section list is protected. - * - *--*/ -VOID -STDCALL -RtlpInitDeferedCriticalSection( - VOID) -{ - - /* Initialize the Process Critical Section List */ - InitializeListHead(&RtlCriticalSectionList); - - /* Initialize the CS Protecting the List */ - RtlInitializeCriticalSection(&RtlCriticalSectionLock); - - /* It's now safe to enter it */ - RtlpCritSectInitialized = TRUE; -} - -/*++ - * RtlpAllocateDebugInfo - * - * Finds or allocates memory for a Critical Section Debug Object - * - * Params: - * None - * - * Returns: - * A pointer to an empty Critical Section Debug Object. - * - * Remarks: - * For optimization purposes, the first 64 entries can be cached. From - * then on, future Critical Sections will allocate memory from the heap. - * - *--*/ -PRTL_CRITICAL_SECTION_DEBUG -STDCALL -RtlpAllocateDebugInfo( - VOID) -{ - ULONG i; - - /* Try to allocate from our buffer first */ - for (i = 0; i < MAX_STATIC_CS_DEBUG_OBJECTS; i++) { - - /* Check if Entry is free */ - if (!RtlpDebugInfoFreeList[i]) { - - /* Mark entry in use */ - DPRINT("Using entry: %d. Buffer: %x\n", i, &RtlpStaticDebugInfo[i]); - RtlpDebugInfoFreeList[i] = TRUE; - - /* Use free entry found */ - return &RtlpStaticDebugInfo[i]; - } - - } - - /* We are out of static buffer, allocate dynamic */ - return RtlAllocateHeap(NtCurrentPeb()->ProcessHeap, - 0, - sizeof(RTL_CRITICAL_SECTION_DEBUG)); -} - -/*++ - * RtlpFreeDebugInfo - * - * Frees the memory for a Critical Section Debug Object - * - * Params: - * DebugInfo - Pointer to Critical Section Debug Object to free. - * - * Returns: - * None. - * - * Remarks: - * If the pointer is part of the static buffer, then the entry is made - * free again. If not, the object is de-allocated from the heap. - * - *--*/ -VOID -STDCALL -RtlpFreeDebugInfo( - PRTL_CRITICAL_SECTION_DEBUG DebugInfo) -{ - ULONG EntryId; - - /* Is it part of our cached entries? */ - if ((DebugInfo >= RtlpStaticDebugInfo) && - (DebugInfo <= &RtlpStaticDebugInfo[MAX_STATIC_CS_DEBUG_OBJECTS-1])) { - - /* Yes. zero it out */ - RtlZeroMemory(DebugInfo, sizeof(RTL_CRITICAL_SECTION_DEBUG)); - - /* Mark as free */ - EntryId = (DebugInfo - RtlpStaticDebugInfo); - DPRINT("Freeing from Buffer: %x. Entry: %d inside Process: %x\n", - DebugInfo, - EntryId, - NtCurrentTeb()->Cid.UniqueProcess); - RtlpDebugInfoFreeList[EntryId] = FALSE; - - } else { - - /* It's a dynamic one, so free from the heap */ - DPRINT("Freeing from Heap: %x inside Process: %x\n", - DebugInfo, - NtCurrentTeb()->Cid.UniqueProcess); - RtlFreeHeap(NtCurrentPeb()->ProcessHeap, 0, DebugInfo); - - } -} - -/* EOF */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/rtl/critical.c + * PURPOSE: Critical sections + * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) + * Gunnar Dalsnes + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#define MAX_STATIC_CS_DEBUG_OBJECTS 64 + +static RTL_CRITICAL_SECTION RtlCriticalSectionLock; +static LIST_ENTRY RtlCriticalSectionList; +static BOOLEAN RtlpCritSectInitialized = FALSE; +static RTL_CRITICAL_SECTION_DEBUG RtlpStaticDebugInfo[MAX_STATIC_CS_DEBUG_OBJECTS]; +static BOOLEAN RtlpDebugInfoFreeList[MAX_STATIC_CS_DEBUG_OBJECTS]; + +/* FUNCTIONS *****************************************************************/ + +/*++ + * RtlpCreateCriticalSectionSem + * + * Checks if an Event has been created for the critical section. + * + * Params: + * None + * + * Returns: + * None. Raises an exception if the system call failed. + * + * Remarks: + * None + * + *--*/ +VOID +STDCALL +RtlpCreateCriticalSectionSem(PRTL_CRITICAL_SECTION CriticalSection) +{ + HANDLE hEvent = CriticalSection->LockSemaphore; + HANDLE hNewEvent; + NTSTATUS Status; + + /* Chevk if we have an event */ + if (!hEvent) { + + /* No, so create it */ + if (!NT_SUCCESS(Status = NtCreateEvent(&hNewEvent, + EVENT_ALL_ACCESS, + NULL, + SynchronizationEvent, + FALSE))) { + + /* We failed, this is bad... */ + DPRINT1("Failed to Create Event!\n"); + InterlockedDecrement(&CriticalSection->LockCount); + RtlRaiseStatus(Status); + return; + } + DPRINT("Created Event: %x \n", hNewEvent); + + if ((hEvent = InterlockedCompareExchangePointer((PVOID*)&CriticalSection->LockSemaphore, + (PVOID)hNewEvent, + 0))) { + + /* Some just created an event */ + DPRINT("Closing already created event: %x\n", hNewEvent); + NtClose(hNewEvent); + } + } + + return; +} + +/*++ + * RtlpWaitForCriticalSection + * + * Slow path of RtlEnterCriticalSection. Waits on an Event Object. + * + * Params: + * CriticalSection - Critical section to acquire. + * + * Returns: + * STATUS_SUCCESS, or raises an exception if a deadlock is occuring. + * + * Remarks: + * None + * + *--*/ +NTSTATUS +STDCALL +RtlpWaitForCriticalSection(PRTL_CRITICAL_SECTION CriticalSection) +{ + NTSTATUS Status; + EXCEPTION_RECORD ExceptionRecord; + BOOLEAN LastChance = FALSE; + LARGE_INTEGER Timeout; + + /* Wait 2.5 minutes */ + Timeout.QuadPart = 150000L * (ULONGLONG)10000; + Timeout.QuadPart = -Timeout.QuadPart; + /* ^^ HACK HACK HACK. Good way: + Timeout = &NtCurrentPeb()->CriticalSectionTimeout */ + + /* Do we have an Event yet? */ + if (!CriticalSection->LockSemaphore) { + RtlpCreateCriticalSectionSem(CriticalSection); + } + + /* Increase the Debug Entry count */ + DPRINT("Waiting on Critical Section Event: %x %x\n", + CriticalSection, + CriticalSection->LockSemaphore); + CriticalSection->DebugInfo->EntryCount++; + + for (;;) { + + /* Increase the number of times we've had contention */ + CriticalSection->DebugInfo->ContentionCount++; + + /* Wait on the Event */ + Status = NtWaitForSingleObject(CriticalSection->LockSemaphore, + FALSE, + &Timeout); + + /* We have Timed out */ + if (Status == STATUS_TIMEOUT) { + + /* Is this the 2nd time we've timed out? */ + if (LastChance) { + + DPRINT1("Deadlock: %x\n", CriticalSection); + + /* Yes it is, we are raising an exception */ + ExceptionRecord.ExceptionCode = STATUS_POSSIBLE_DEADLOCK; + ExceptionRecord.ExceptionFlags = 0; + ExceptionRecord.ExceptionRecord = NULL; + ExceptionRecord.ExceptionAddress = RtlRaiseException; + ExceptionRecord.NumberParameters = 1; + ExceptionRecord.ExceptionInformation[0] = (ULONG_PTR)CriticalSection; + RtlRaiseException(&ExceptionRecord); + + } + + /* One more try */ + LastChance = TRUE; + + } else { + + /* If we are here, everything went fine */ + return STATUS_SUCCESS; + } + } +} + +/*++ + * RtlpUnWaitCriticalSection + * + * Slow path of RtlLeaveCriticalSection. Fires an Event Object. + * + * Params: + * CriticalSection - Critical section to release. + * + * Returns: + * None. Raises an exception if the system call failed. + * + * Remarks: + * None + * + *--*/ +VOID +STDCALL +RtlpUnWaitCriticalSection(PRTL_CRITICAL_SECTION CriticalSection) +{ + NTSTATUS Status; + + /* Do we have an Event yet? */ + if (!CriticalSection->LockSemaphore) { + RtlpCreateCriticalSectionSem(CriticalSection); + } + + /* Signal the Event */ + DPRINT("Signaling Critical Section Event: %x, %x\n", + CriticalSection, + CriticalSection->LockSemaphore); + Status = NtSetEvent(CriticalSection->LockSemaphore, NULL); + + if (!NT_SUCCESS(Status)) { + + /* We've failed */ + DPRINT1("Signaling Failed for: %x, %x, %x\n", + CriticalSection, + CriticalSection->LockSemaphore, + Status); + RtlRaiseStatus(Status); + } +} + +/*++ + * RtlpInitDeferedCriticalSection + * + * Initializes the Critical Section implementation. + * + * Params: + * None + * + * Returns: + * None. + * + * Remarks: + * After this call, the Process Critical Section list is protected. + * + *--*/ +VOID +STDCALL +RtlpInitDeferedCriticalSection(VOID) +{ + + /* Initialize the Process Critical Section List */ + InitializeListHead(&RtlCriticalSectionList); + + /* Initialize the CS Protecting the List */ + RtlInitializeCriticalSection(&RtlCriticalSectionLock); + + /* It's now safe to enter it */ + RtlpCritSectInitialized = TRUE; +} + +/*++ + * RtlpAllocateDebugInfo + * + * Finds or allocates memory for a Critical Section Debug Object + * + * Params: + * None + * + * Returns: + * A pointer to an empty Critical Section Debug Object. + * + * Remarks: + * For optimization purposes, the first 64 entries can be cached. From + * then on, future Critical Sections will allocate memory from the heap. + * + *--*/ +PRTL_CRITICAL_SECTION_DEBUG +STDCALL +RtlpAllocateDebugInfo(VOID) +{ + ULONG i; + + /* Try to allocate from our buffer first */ + for (i = 0; i < MAX_STATIC_CS_DEBUG_OBJECTS; i++) { + + /* Check if Entry is free */ + if (!RtlpDebugInfoFreeList[i]) { + + /* Mark entry in use */ + DPRINT("Using entry: %d. Buffer: %x\n", i, &RtlpStaticDebugInfo[i]); + RtlpDebugInfoFreeList[i] = TRUE; + + /* Use free entry found */ + return &RtlpStaticDebugInfo[i]; + } + + } + + /* We are out of static buffer, allocate dynamic */ + return RtlAllocateHeap(NtCurrentPeb()->ProcessHeap, + 0, + sizeof(RTL_CRITICAL_SECTION_DEBUG)); +} + +/*++ + * RtlpFreeDebugInfo + * + * Frees the memory for a Critical Section Debug Object + * + * Params: + * DebugInfo - Pointer to Critical Section Debug Object to free. + * + * Returns: + * None. + * + * Remarks: + * If the pointer is part of the static buffer, then the entry is made + * free again. If not, the object is de-allocated from the heap. + * + *--*/ +VOID +STDCALL +RtlpFreeDebugInfo(PRTL_CRITICAL_SECTION_DEBUG DebugInfo) +{ + ULONG EntryId; + + /* Is it part of our cached entries? */ + if ((DebugInfo >= RtlpStaticDebugInfo) && + (DebugInfo <= &RtlpStaticDebugInfo[MAX_STATIC_CS_DEBUG_OBJECTS-1])) { + + /* Yes. zero it out */ + RtlZeroMemory(DebugInfo, sizeof(RTL_CRITICAL_SECTION_DEBUG)); + + /* Mark as free */ + EntryId = (DebugInfo - RtlpStaticDebugInfo); + DPRINT("Freeing from Buffer: %x. Entry: %d inside Process: %x\n", + DebugInfo, + EntryId, + NtCurrentTeb()->Cid.UniqueProcess); + RtlpDebugInfoFreeList[EntryId] = FALSE; + + } else { + + /* It's a dynamic one, so free from the heap */ + DPRINT("Freeing from Heap: %x inside Process: %x\n", + DebugInfo, + NtCurrentTeb()->Cid.UniqueProcess); + RtlFreeHeap(NtCurrentPeb()->ProcessHeap, 0, DebugInfo); + + } +} + +/*++ + * RtlDeleteCriticalSection + * @implemented NT4 + * + * Deletes a Critical Section + * + * Params: + * CriticalSection - Critical section to delete. + * + * Returns: + * STATUS_SUCCESS, or error value returned by NtClose. + * + * Remarks: + * The critical section members should not be read after this call. + * + *--*/ +NTSTATUS +STDCALL +RtlDeleteCriticalSection(PRTL_CRITICAL_SECTION CriticalSection) +{ + NTSTATUS Status = STATUS_SUCCESS; + + DPRINT("Deleting Critical Section: %x\n", CriticalSection); + /* Close the Event Object Handle if it exists */ + if (CriticalSection->LockSemaphore) { + + /* In case NtClose fails, return the status */ + Status = NtClose(CriticalSection->LockSemaphore); + + } + + /* Protect List */ + RtlEnterCriticalSection(&RtlCriticalSectionLock); + + /* Remove it from the list */ + RemoveEntryList(&CriticalSection->DebugInfo->ProcessLocksList); + + /* Unprotect */ + RtlLeaveCriticalSection(&RtlCriticalSectionLock); + + /* Free it */ + RtlpFreeDebugInfo(CriticalSection->DebugInfo); + + /* Wipe it out */ + RtlZeroMemory(CriticalSection, sizeof(RTL_CRITICAL_SECTION)); + + /* Return */ + return Status; +} + +/*++ + * RtlSetCriticalSectionSpinCount + * @implemented NT4 + * + * Sets the spin count for a critical section. + * + * Params: + * CriticalSection - Critical section to set the spin count for. + * + * SpinCount - Spin count for the critical section. + * + * Returns: + * STATUS_SUCCESS. + * + * Remarks: + * SpinCount is ignored on single-processor systems. + * + *--*/ +DWORD +STDCALL +RtlSetCriticalSectionSpinCount(PRTL_CRITICAL_SECTION CriticalSection, + ULONG SpinCount) +{ + ULONG OldCount = CriticalSection->SpinCount; + + /* Set to parameter if MP, or to 0 if this is Uniprocessor */ + CriticalSection->SpinCount = (NtCurrentPeb()->NumberOfProcessors > 1) ? SpinCount : 0; + return OldCount; +} + +/*++ + * RtlEnterCriticalSection + * @implemented NT4 + * + * Waits to gain ownership of the critical section. + * + * Params: + * CriticalSection - Critical section to wait for. + * + * Returns: + * STATUS_SUCCESS. + * + * Remarks: + * Uses a fast-path unless contention happens. + * + *--*/ +NTSTATUS +STDCALL +RtlEnterCriticalSection(PRTL_CRITICAL_SECTION CriticalSection) +{ + HANDLE Thread = (HANDLE)NtCurrentTeb()->Cid.UniqueThread; + + /* Try to Lock it */ + if (InterlockedIncrement(&CriticalSection->LockCount) != 0) { + + /* + * We've failed to lock it! Does this thread + * actually own it? + */ + if (Thread == CriticalSection->OwningThread) { + + /* You own it, so you'll get it when you're done with it! No need to + use the interlocked functions as only the thread who already owns + the lock can modify this data. */ + CriticalSection->RecursionCount++; + return STATUS_SUCCESS; + } + + /* NOTE - CriticalSection->OwningThread can be NULL here because changing + this information is not serialized. This happens when thread a + acquires the lock (LockCount == 0) and thread b tries to + acquire it as well (LockCount == 1) but thread a hasn't had a + chance to set the OwningThread! So it's not an error when + OwningThread is NULL here! */ + + /* We don't own it, so we must wait for it */ + RtlpWaitForCriticalSection(CriticalSection); + } + + /* Lock successful. Changing this information has not to be serialized because + only one thread at a time can actually change it (the one who acquired + the lock)! */ + CriticalSection->OwningThread = Thread; + CriticalSection->RecursionCount = 1; + return STATUS_SUCCESS; +} + +/*++ + * RtlInitializeCriticalSection + * @implemented NT4 + * + * Initialises a new critical section. + * + * Params: + * CriticalSection - Critical section to initialise + * + * Returns: + * STATUS_SUCCESS. + * + * Remarks: + * Simply calls RtlInitializeCriticalSectionAndSpinCount + * + *--*/ +NTSTATUS +STDCALL +RtlInitializeCriticalSection(PRTL_CRITICAL_SECTION CriticalSection) +{ + /* Call the Main Function */ + return RtlInitializeCriticalSectionAndSpinCount(CriticalSection, 0); +} + +/*++ + * 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 +STDCALL +RtlInitializeCriticalSectionAndSpinCount(PRTL_CRITICAL_SECTION CriticalSection, + ULONG SpinCount) +{ + PRTL_CRITICAL_SECTION_DEBUG CritcalSectionDebugData; + + /* First things first, set up the Object */ + DPRINT("Initializing Critical Section: %x\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: %x inside Process: %x\n", + CritcalSectionDebugData, + NtCurrentTeb()->Cid.UniqueProcess); + + if (!CritcalSectionDebugData) { + + /* This is bad! */ + DPRINT1("Couldn't allocate Debug Data for: %x\n", CriticalSection); + return STATUS_NO_MEMORY; + } + + /* Set it up */ + CritcalSectionDebugData->Type = RTL_CRITSECT_TYPE; + CritcalSectionDebugData->ContentionCount = 0; + CritcalSectionDebugData->EntryCount = 0; + CritcalSectionDebugData->CriticalSection = CriticalSection; + 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: %x, %x, %x\n", + &CritcalSectionDebugData->ProcessLocksList, + CriticalSection, + &RtlCriticalSectionList); + + /* Protect List */ + RtlEnterCriticalSection(&RtlCriticalSectionLock); + + /* Add this one */ + InsertTailList(&RtlCriticalSectionList, &CritcalSectionDebugData->ProcessLocksList); + + /* Unprotect */ + RtlLeaveCriticalSection(&RtlCriticalSectionLock); + + } else { + + DPRINT("Inserting into ProcessLocks: %x, %x, %x\n", + &CritcalSectionDebugData->ProcessLocksList, + CriticalSection, + &RtlCriticalSectionList); + + /* Add it directly */ + InsertTailList(&RtlCriticalSectionList, &CritcalSectionDebugData->ProcessLocksList); + } + + return STATUS_SUCCESS; +} + +/*++ + * RtlLeaveCriticalSection + * @implemented NT4 + * + * Releases a critical section and makes if available for new owners. + * + * Params: + * CriticalSection - Critical section to release. + * + * Returns: + * STATUS_SUCCESS. + * + * Remarks: + * If another thread was waiting, the slow path is entered. + * + *--*/ +NTSTATUS +STDCALL +RtlLeaveCriticalSection(PRTL_CRITICAL_SECTION CriticalSection) +{ +#ifndef NDEBUG + HANDLE Thread = (HANDLE)NtCurrentTeb()->Cid.UniqueThread; + + /* In win this case isn't checked. However it's a valid check so it should only + be performed in debug builds! */ + if (Thread != CriticalSection->OwningThread) + { + DPRINT1("Releasing critical section not owned!\n"); + return STATUS_INVALID_PARAMETER; + } +#endif + + /* Decrease the Recursion Count. No need to do this atomically because only + the thread who holds the lock can call this function (unless the program + is totally screwed... */ + if (--CriticalSection->RecursionCount) { + + /* Someone still owns us, but we are free. This needs to be done atomically. */ + InterlockedDecrement(&CriticalSection->LockCount); + + } else { + + /* Nobody owns us anymore. No need to do this atomically. See comment + above. */ + CriticalSection->OwningThread = 0; + + /* Was someone wanting us? This needs to be done atomically. */ + if (-1 != InterlockedDecrement(&CriticalSection->LockCount)) { + + /* Let him have us */ + RtlpUnWaitCriticalSection(CriticalSection); + } + } + + /* Sucessful! */ + return STATUS_SUCCESS; +} + +/*++ + * RtlTryEnterCriticalSection + * @implemented NT4 + * + * Attemps to gain ownership of the critical section without waiting. + * + * Params: + * CriticalSection - Critical section to attempt acquiring. + * + * Returns: + * TRUE if the critical section has been acquired, FALSE otherwise. + * + * Remarks: + * None + * + *--*/ +BOOLEAN +STDCALL +RtlTryEnterCriticalSection(PRTL_CRITICAL_SECTION CriticalSection) +{ + /* Try to take control */ + if (InterlockedCompareExchange(&CriticalSection->LockCount, + 0, + -1) == -1) { + + /* It's ours */ + CriticalSection->OwningThread = NtCurrentTeb()->Cid.UniqueThread; + CriticalSection->RecursionCount = 1; + return TRUE; + + } else if (CriticalSection->OwningThread == NtCurrentTeb()->Cid.UniqueThread) { + + /* It's already ours */ + InterlockedIncrement(&CriticalSection->LockCount); + CriticalSection->RecursionCount++; + return TRUE; + } + + /* It's not ours */ + return FALSE; +} + +/* EOF */ diff --git a/reactos/lib/rtl/heap.c b/reactos/lib/rtl/heap.c index d14e843052a..b8a818cc355 100644 --- a/reactos/lib/rtl/heap.c +++ b/reactos/lib/rtl/heap.c @@ -570,7 +570,7 @@ static BOOLEAN HEAP_InitSubHeap( HEAP *heap, PVOID address, ULONG flags, /* Initialize critical section */ - RtlInitializeCriticalSection( &heap->critSection ); + RtlInitializeHeapLock( &heap->critSection ); } /* Commit memory */ @@ -937,12 +937,12 @@ int HEAP_IsInsideHeap( return 0; flags |= heapPtr->flags; if (!(flags & HEAP_NO_SERIALIZE)) - RtlEnterCriticalSection( &heapPtr->critSection ); + RtlEnterHeapLock( &heapPtr->critSection ); ret = (((subheap = HEAP_FindSubHeap( heapPtr, ptr )) != NULL) && (((char *)ptr >= (char *)subheap + subheap->headerSize + sizeof(ARENA_INUSE)))); if (!(flags & HEAP_NO_SERIALIZE)) - RtlLeaveCriticalSection( &heapPtr->critSection ); + RtlLeaveHeapLock( &heapPtr->critSection ); return ret; } @@ -1002,7 +1002,7 @@ static BOOLEAN HEAP_IsRealArena( flags |= heapPtr->flags; /* calling HeapLock may result in infinite recursion, so do the critsect directly */ if (!(flags & HEAP_NO_SERIALIZE)) - RtlEnterCriticalSection( &heapPtr->critSection ); + RtlEnterHeapLock( &heapPtr->critSection ); if (block) { @@ -1032,7 +1032,7 @@ static BOOLEAN HEAP_IsRealArena( ret = HEAP_ValidateInUseArena( subheap, (ARENA_INUSE *)block - 1, quiet ); if (!(flags & HEAP_NO_SERIALIZE)) - RtlLeaveCriticalSection( &heapPtr->critSection ); + RtlLeaveHeapLock( &heapPtr->critSection ); return ret; } @@ -1065,7 +1065,7 @@ static BOOLEAN HEAP_IsRealArena( } if (!(flags & HEAP_NO_SERIALIZE)) - RtlLeaveCriticalSection( &heapPtr->critSection ); + RtlLeaveHeapLock( &heapPtr->critSection ); return ret; } @@ -1105,14 +1105,14 @@ RtlCreateHeap(ULONG flags, if (RtlpGetMode() == UserMode) { /* link it into the per-process heap list */ - RtlEnterCriticalSection (&RtlpProcessHeapsListLock); + RtlEnterHeapLock (&RtlpProcessHeapsListLock); heapPtr = subheap->heap; heapPtr->next = (HEAP*)NtCurrentPeb()->ProcessHeaps; NtCurrentPeb()->ProcessHeaps = (HANDLE)heapPtr; NtCurrentPeb()->NumberOfHeaps++; - RtlLeaveCriticalSection (&RtlpProcessHeapsListLock); + RtlLeaveHeapLock (&RtlpProcessHeapsListLock); } return (HANDLE)subheap; @@ -1148,17 +1148,17 @@ RtlDestroyHeap(HANDLE heap) /* [in] Handle of heap */ return heap; /* cannot delete the main process heap */ /* remove it from the per-process list */ - RtlEnterCriticalSection (&RtlpProcessHeapsListLock); + RtlEnterHeapLock (&RtlpProcessHeapsListLock); pptr = (HEAP**)&NtCurrentPeb()->ProcessHeaps; while (*pptr && *pptr != heapPtr) pptr = &(*pptr)->next; if (*pptr) *pptr = (*pptr)->next; NtCurrentPeb()->NumberOfHeaps--; - RtlLeaveCriticalSection (&RtlpProcessHeapsListLock); + RtlLeaveHeapLock (&RtlpProcessHeapsListLock); } - RtlDeleteCriticalSection( &heapPtr->critSection ); + RtlDeleteHeapLock( &heapPtr->critSection ); subheap = &heapPtr->subheap; // We must save the flags. The first subheap is located after // the heap structure. If we release the first subheap, @@ -1207,7 +1207,7 @@ RtlAllocateHeap(HANDLE heap, /* [in] Handle of private heap block */ flags &= HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY; flags |= heapPtr->flags; if (!(flags & HEAP_NO_SERIALIZE)) - RtlEnterCriticalSection( &heapPtr->critSection ); + RtlEnterHeapLock( &heapPtr->critSection ); size = (size + 7) & ~7; if (size < HEAP_MIN_BLOCK_SIZE) size = HEAP_MIN_BLOCK_SIZE; @@ -1219,7 +1219,7 @@ RtlAllocateHeap(HANDLE heap, /* [in] Handle of private heap block */ DPRINT("(%08x,%08lx,%08lx): returning NULL\n", heap, flags, size ); if (!(flags & HEAP_NO_SERIALIZE)) - RtlLeaveCriticalSection( &heapPtr->critSection ); + RtlLeaveHeapLock( &heapPtr->critSection ); if (flags & HEAP_GENERATE_EXCEPTIONS) RtlRaiseStatus( STATUS_NO_MEMORY ); return NULL; @@ -1248,7 +1248,7 @@ RtlAllocateHeap(HANDLE heap, /* [in] Handle of private heap block */ memset( pInUse + 1, ARENA_INUSE_FILLER, pInUse->size & ARENA_SIZE_MASK ); if (!(flags & HEAP_NO_SERIALIZE)) - RtlLeaveCriticalSection( &heapPtr->critSection ); + RtlLeaveHeapLock( &heapPtr->critSection ); DPRINT("(%08x,%08lx,%08lx): returning %p\n", heap, flags, size, (PVOID)(pInUse + 1) ); @@ -1288,11 +1288,11 @@ BOOLEAN STDCALL RtlFreeHeap( flags &= HEAP_NO_SERIALIZE; flags |= heapPtr->flags; if (!(flags & HEAP_NO_SERIALIZE)) - RtlEnterCriticalSection( &heapPtr->critSection ); + RtlEnterHeapLock( &heapPtr->critSection ); if (!HEAP_IsRealArena( heap, HEAP_NO_SERIALIZE, ptr, QUIET )) { if (!(flags & HEAP_NO_SERIALIZE)) - RtlLeaveCriticalSection( &heapPtr->critSection ); + RtlLeaveHeapLock( &heapPtr->critSection ); DPRINT("(%08x,%08lx,%p): returning FALSE\n", heap, flags, ptr ); return FALSE; @@ -1305,7 +1305,7 @@ BOOLEAN STDCALL RtlFreeHeap( HEAP_MakeInUseBlockFree( subheap, pInUse, heapPtr->flags ); if (!(flags & HEAP_NO_SERIALIZE)) - RtlLeaveCriticalSection( &heapPtr->critSection ); + RtlLeaveHeapLock( &heapPtr->critSection ); DPRINT("(%08x,%08lx,%p): returning TRUE\n", heap, flags, ptr ); @@ -1354,11 +1354,11 @@ PVOID STDCALL RtlReAllocateHeap( Size = HEAP_MIN_BLOCK_SIZE; if (!(Flags & HEAP_NO_SERIALIZE)) - RtlEnterCriticalSection( &heapPtr->critSection ); + RtlEnterHeapLock( &heapPtr->critSection ); if (!HEAP_IsRealArena( Heap, HEAP_NO_SERIALIZE, Ptr, QUIET )) { if (!(Flags & HEAP_NO_SERIALIZE)) - RtlLeaveCriticalSection( &heapPtr->critSection ); + RtlLeaveHeapLock( &heapPtr->critSection ); DPRINT("(%08x,%08lx,%p,%08lx): returning NULL\n", Heap, Flags, Ptr, Size ); if (Flags & HEAP_GENERATE_EXCEPTIONS) @@ -1390,7 +1390,7 @@ PVOID STDCALL RtlReAllocateHeap( heapPtr->flags)) { if (!(Flags & HEAP_NO_SERIALIZE)) - RtlLeaveCriticalSection( &heapPtr->critSection ); + RtlLeaveHeapLock( &heapPtr->critSection ); if (Flags & HEAP_GENERATE_EXCEPTIONS) RtlRaiseStatus( STATUS_NO_MEMORY ); return NULL; @@ -1407,7 +1407,7 @@ PVOID STDCALL RtlReAllocateHeap( !(pNew = HEAP_FindFreeBlock( heapPtr, Size, &newsubheap ))) { if (!(Flags & HEAP_NO_SERIALIZE)) - RtlLeaveCriticalSection( &heapPtr->critSection ); + RtlLeaveHeapLock( &heapPtr->critSection ); if (Flags & HEAP_GENERATE_EXCEPTIONS) RtlRaiseStatus( STATUS_NO_MEMORY ); return NULL; @@ -1450,7 +1450,7 @@ PVOID STDCALL RtlReAllocateHeap( /* Return the new arena */ if (!(Flags & HEAP_NO_SERIALIZE)) - RtlLeaveCriticalSection( &heapPtr->critSection ); + RtlLeaveHeapLock( &heapPtr->critSection ); DPRINT("(%08x,%08lx,%p,%08lx): returning %p\n", Heap, Flags, Ptr, Size, (PVOID)(pArena + 1) ); @@ -1491,7 +1491,7 @@ RtlLockHeap(IN HANDLE Heap) HEAP *heapPtr = HEAP_GetPtr( Heap ); if (!heapPtr) return FALSE; - RtlEnterCriticalSection( &heapPtr->critSection ); + RtlEnterHeapLock( &heapPtr->critSection ); return TRUE; } @@ -1515,7 +1515,7 @@ RtlUnlockHeap(HANDLE Heap) HEAP *heapPtr = HEAP_GetPtr( Heap ); if (!heapPtr) return FALSE; - RtlLeaveCriticalSection( &heapPtr->critSection ); + RtlLeaveHeapLock( &heapPtr->critSection ); return TRUE; } @@ -1548,7 +1548,7 @@ RtlSizeHeap( Flags &= HEAP_NO_SERIALIZE; Flags |= heapPtr->flags; if (!(Flags & HEAP_NO_SERIALIZE)) - RtlEnterCriticalSection( &heapPtr->critSection ); + RtlEnterHeapLock( &heapPtr->critSection ); if (!HEAP_IsRealArena( Heap, HEAP_NO_SERIALIZE, Ptr, QUIET )) { ret = 0xffffffff; @@ -1559,7 +1559,7 @@ RtlSizeHeap( ret = pArena->size & ARENA_SIZE_MASK; } if (!(Flags & HEAP_NO_SERIALIZE)) - RtlLeaveCriticalSection( &heapPtr->critSection ); + RtlLeaveHeapLock( &heapPtr->critSection ); DPRINT("(%08x,%08lx,%p): returning %08lx\n", Heap, Flags, Ptr, ret ); @@ -1629,7 +1629,7 @@ BOOLEAN STDCALL HeapWalk( } if (!(heapPtr->flags & HEAP_NO_SERIALIZE)) - RtlEnterCriticalSection( &heapPtr->critSection ); + RtlEnterHeapLock( &heapPtr->critSection ); /* set ptr to the next arena to be examined */ @@ -1717,7 +1717,7 @@ BOOLEAN STDCALL HeapWalk( HW_end: if (!(heapPtr->flags & HEAP_NO_SERIALIZE)) - RtlLeaveCriticalSection( &heapPtr->critSection ); + RtlLeaveHeapLock( &heapPtr->critSection ); return ret; } @@ -1735,7 +1735,7 @@ RtlInitializeHeapManager(VOID) Peb->MaximumNumberOfHeaps = -1; /* no limit */ Peb->ProcessHeaps = NULL; - RtlInitializeCriticalSection(&RtlpProcessHeapsListLock); + RtlInitializeHeapLock(&RtlpProcessHeapsListLock); } @@ -1749,7 +1749,7 @@ RtlEnumProcessHeaps(PHEAP_ENUMERATION_ROUTINE HeapEnumerationRoutine, NTSTATUS Status = STATUS_SUCCESS; HEAP** pptr; - RtlEnterCriticalSection(&RtlpProcessHeapsListLock); + RtlEnterHeapLock(&RtlpProcessHeapsListLock); for (pptr = (HEAP**)&NtCurrentPeb()->ProcessHeaps; *pptr; pptr = &(*pptr)->next) { @@ -1758,7 +1758,7 @@ RtlEnumProcessHeaps(PHEAP_ENUMERATION_ROUTINE HeapEnumerationRoutine, break; } - RtlLeaveCriticalSection(&RtlpProcessHeapsListLock); + RtlLeaveHeapLock(&RtlpProcessHeapsListLock); return Status; } @@ -1774,7 +1774,7 @@ RtlGetProcessHeaps(ULONG HeapCount, ULONG Result = 0; HEAP ** pptr; - RtlEnterCriticalSection(&RtlpProcessHeapsListLock); + RtlEnterHeapLock(&RtlpProcessHeapsListLock); Result = NtCurrentPeb()->NumberOfHeaps; @@ -1787,7 +1787,7 @@ RtlGetProcessHeaps(ULONG HeapCount, } } - RtlLeaveCriticalSection (&RtlpProcessHeapsListLock); + RtlLeaveHeapLock (&RtlpProcessHeapsListLock); return Result; } @@ -1802,7 +1802,7 @@ RtlValidateProcessHeaps(VOID) BOOLEAN Result = TRUE; HEAP ** pptr; - RtlEnterCriticalSection(&RtlpProcessHeapsListLock); + RtlEnterHeapLock(&RtlpProcessHeapsListLock); for (pptr = (HEAP**)&NtCurrentPeb()->ProcessHeaps; *pptr; pptr = &(*pptr)->next) { @@ -1813,7 +1813,7 @@ RtlValidateProcessHeaps(VOID) } } - RtlLeaveCriticalSection (&RtlpProcessHeapsListLock); + RtlLeaveHeapLock (&RtlpProcessHeapsListLock); return Result; } diff --git a/reactos/lib/ntdll/rtl/path.c b/reactos/lib/rtl/path.c similarity index 99% rename from reactos/lib/ntdll/rtl/path.c rename to reactos/lib/rtl/path.c index 66b717186be..41b0e0d7812 100644 --- a/reactos/lib/ntdll/rtl/path.c +++ b/reactos/lib/rtl/path.c @@ -1,16 +1,15 @@ -/* $Id$ - * +/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries - * FILE: lib/ntdll/rtl/path.c + * FILE: lib/rtl/path.c * PURPOSE: Path and current directory functions - * UPDATE HISTORY: - * Created 03/02/00 + * PROGRAMMERS: */ -/* INCLUDES ******************************************************************/ +/* INCLUDES *****************************************************************/ + +#include -#include #define NDEBUG #include diff --git a/reactos/lib/rtl/rtl.h b/reactos/lib/rtl/rtl.h index f81062233a3..0c4e4a3ef6f 100644 --- a/reactos/lib/rtl/rtl.h +++ b/reactos/lib/rtl/rtl.h @@ -34,6 +34,10 @@ extern VOID FASTCALL CHECK_PAGED_CODE_RTL(char *file, int line); PVOID STDCALL RtlpAllocateMemory(UINT Bytes, ULONG Tag); VOID STDCALL RtlpFreeMemory(PVOID Mem, ULONG Tag); KPROCESSOR_MODE STDCALL RtlpGetMode(); +NTSTATUS STDCALL RtlDeleteHeapLock(PRTL_CRITICAL_SECTION CriticalSection); +NTSTATUS STDCALL RtlEnterHeapLock(PRTL_CRITICAL_SECTION CriticalSection); +NTSTATUS STDCALL RtlInitializeHeapLock(PRTL_CRITICAL_SECTION CriticalSection); +NTSTATUS STDCALL RtlLeaveHeapLock(PRTL_CRITICAL_SECTION CriticalSection); #define RtlpAllocateStringMemory RtlpAllocateMemory #define RtlpFreeStringMemory RtlpFreeMemory diff --git a/reactos/lib/rtl/rtl.xml b/reactos/lib/rtl/rtl.xml index 5bbb068346d..1be8c54b433 100644 --- a/reactos/lib/rtl/rtl.xml +++ b/reactos/lib/rtl/rtl.xml @@ -15,14 +15,13 @@ access.c acl.c - apc.c atom.c bit.c bitmap.c bootdata.c - callback.c compress.c crc32.c + critical.c dbgbuffer.c dos8dot3.c encode.c @@ -40,6 +39,7 @@ luid.c network.c nls.c + path.c ppb.c process.c propvar.c @@ -58,6 +58,7 @@ timerqueue.c unicode.c unicodeprefix.c + vectoreh.c version.c rtl.h diff --git a/reactos/lib/ntdll/rtl/exception.c b/reactos/lib/rtl/vectoreh.c similarity index 61% rename from reactos/lib/ntdll/rtl/exception.c rename to reactos/lib/rtl/vectoreh.c index 83901e2b5f6..ffab68b8b53 100644 --- a/reactos/lib/ntdll/rtl/exception.c +++ b/reactos/lib/rtl/vectoreh.c @@ -1,221 +1,144 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * PURPOSE: User-mode exception support - * FILE: lib/ntdll/rtl/exception.c - * PROGRAMERS: David Welch - * Skywing - * KJK::Hyperion - * UPDATES: Skywing, 09/11/2003: Implemented RtlRaiseException and - * KiUserRaiseExceptionDispatcher. - * KJK::Hyperion, 22/06/2003: Moved common parts to rtl - */ - -/* INCLUDES *****************************************************************/ - -#include -#define NDEBUG -#include - -static RTL_CRITICAL_SECTION RtlpVectoredExceptionLock; -static LIST_ENTRY RtlpVectoredExceptionHead; - -typedef struct _RTL_VECTORED_EXCEPTION_HANDLER -{ - LIST_ENTRY ListEntry; - PVECTORED_EXCEPTION_HANDLER VectoredHandler; -} RTL_VECTORED_EXCEPTION_HANDLER, *PRTL_VECTORED_EXCEPTION_HANDLER; - -/* FIXME - stupid ld won't resolve RtlDecodePointer! Since their implementation - is the same just use RtlEncodePointer for now! */ -#define RtlDecodePointer RtlEncodePointer - -/* FUNCTIONS ***************************************************************/ - -VOID STDCALL -RtlBaseProcessStart(PTHREAD_START_ROUTINE StartAddress, - PVOID Parameter); - -__declspec(dllexport) -PRTL_BASE_PROCESS_START_ROUTINE RtlBaseProcessStartRoutine = RtlBaseProcessStart; - -ULONG -RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord, - IN PCONTEXT Context); - -EXCEPTION_DISPOSITION -RtlpExecuteVectoredExceptionHandlers(IN PEXCEPTION_RECORD ExceptionRecord, - IN PCONTEXT Context) -{ - PLIST_ENTRY CurrentEntry; - PRTL_VECTORED_EXCEPTION_HANDLER veh; - PVECTORED_EXCEPTION_HANDLER VectoredHandler; - EXCEPTION_POINTERS ExceptionInfo; - - ExceptionInfo.ExceptionRecord = ExceptionRecord; - ExceptionInfo.ContextRecord = Context; - - if(RtlpVectoredExceptionHead.Flink != &RtlpVectoredExceptionHead) - { - RtlEnterCriticalSection(&RtlpVectoredExceptionLock); - for(CurrentEntry = RtlpVectoredExceptionHead.Flink; - CurrentEntry != &RtlpVectoredExceptionHead; - CurrentEntry = CurrentEntry->Flink) - { - veh = CONTAINING_RECORD(CurrentEntry, - RTL_VECTORED_EXCEPTION_HANDLER, - ListEntry); - VectoredHandler = RtlDecodePointer(veh->VectoredHandler); - if(VectoredHandler(&ExceptionInfo) == EXCEPTION_CONTINUE_EXECUTION) - { - RtlLeaveCriticalSection(&RtlpVectoredExceptionLock); - return ExceptionContinueSearch; - } - } - RtlLeaveCriticalSection(&RtlpVectoredExceptionLock); - } - - return ExceptionContinueExecution; -} - -VOID STDCALL -KiUserExceptionDispatcher(PEXCEPTION_RECORD ExceptionRecord, - PCONTEXT Context) -{ - EXCEPTION_RECORD NestedExceptionRecord; - NTSTATUS Status; - - if(RtlpExecuteVectoredExceptionHandlers(ExceptionRecord, - Context) != ExceptionContinueExecution) - { - Status = NtContinue(Context, FALSE); - } - else - { - if(RtlpDispatchException(ExceptionRecord, Context) != ExceptionContinueExecution) - { - Status = NtContinue(Context, FALSE); - } - else - { - Status = NtRaiseException(ExceptionRecord, Context, FALSE); - } - } - - NestedExceptionRecord.ExceptionCode = Status; - NestedExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE; - NestedExceptionRecord.ExceptionRecord = ExceptionRecord; - NestedExceptionRecord.NumberParameters = Status; - - RtlRaiseException(&NestedExceptionRecord); -} - - -/* - * @implemented - */ -VOID STDCALL -KiRaiseUserExceptionDispatcher(VOID) -{ - EXCEPTION_RECORD ExceptionRecord; - - ExceptionRecord.ExceptionCode = ((PTEB)NtCurrentTeb())->ExceptionCode; - ExceptionRecord.ExceptionFlags = 0; - ExceptionRecord.ExceptionRecord = NULL; - ExceptionRecord.NumberParameters = 0; - - RtlRaiseException(&ExceptionRecord); -} - -VOID STDCALL -RtlBaseProcessStart(PTHREAD_START_ROUTINE StartAddress, - PVOID Parameter) -{ - NTSTATUS ExitStatus = STATUS_SUCCESS; - - ExitStatus = (NTSTATUS) (StartAddress)(Parameter); - - NtTerminateProcess(NtCurrentProcess(), ExitStatus); -} - - -VOID -RtlpInitializeVectoredExceptionHandling(VOID) -{ - InitializeListHead(&RtlpVectoredExceptionHead); - RtlInitializeCriticalSection(&RtlpVectoredExceptionLock); -} - - -/* - * @implemented - */ -PVOID STDCALL -RtlAddVectoredExceptionHandler(IN ULONG FirstHandler, - IN PVECTORED_EXCEPTION_HANDLER VectoredHandler) -{ - PRTL_VECTORED_EXCEPTION_HANDLER veh; - - veh = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - sizeof(RTL_VECTORED_EXCEPTION_HANDLER)); - if(veh != NULL) - { - veh->VectoredHandler = RtlEncodePointer(VectoredHandler); - RtlEnterCriticalSection(&RtlpVectoredExceptionLock); - if(FirstHandler != 0) - { - InsertHeadList(&RtlpVectoredExceptionHead, - &veh->ListEntry); - } - else - { - InsertTailList(&RtlpVectoredExceptionHead, - &veh->ListEntry); - } - RtlLeaveCriticalSection(&RtlpVectoredExceptionLock); - } - - return veh; -} - - -/* - * @implemented - */ -ULONG STDCALL -RtlRemoveVectoredExceptionHandler(IN PVOID VectoredHandlerHandle) -{ - PLIST_ENTRY CurrentEntry; - PRTL_VECTORED_EXCEPTION_HANDLER veh = NULL; - ULONG Removed = FALSE; - - RtlEnterCriticalSection(&RtlpVectoredExceptionLock); - for(CurrentEntry = RtlpVectoredExceptionHead.Flink; - CurrentEntry != &RtlpVectoredExceptionHead; - CurrentEntry = CurrentEntry->Flink) - { - veh = CONTAINING_RECORD(CurrentEntry, - RTL_VECTORED_EXCEPTION_HANDLER, - ListEntry); - if(veh == VectoredHandlerHandle) - { - RemoveEntryList(&veh->ListEntry); - Removed = TRUE; - break; - } - } - RtlLeaveCriticalSection(&RtlpVectoredExceptionLock); - - if(Removed) - { - RtlFreeHeap(RtlGetProcessHeap(), - 0, - veh); - } - - return Removed; -} - -/* EOF */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS sysem libraries + * PURPOSE: Vectored Exception Handling + * FILE: lib/rtl/vectoreh.c + * PROGRAMERS: Thomas Weidenmueller + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +static RTL_CRITICAL_SECTION RtlpVectoredExceptionLock; +static LIST_ENTRY RtlpVectoredExceptionHead; + +typedef struct _RTL_VECTORED_EXCEPTION_HANDLER +{ + LIST_ENTRY ListEntry; + PVECTORED_EXCEPTION_HANDLER VectoredHandler; +} RTL_VECTORED_EXCEPTION_HANDLER, *PRTL_VECTORED_EXCEPTION_HANDLER; + +/* FIXME - stupid ld won't resolve RtlDecodePointer! Since their implementation + is the same just use RtlEncodePointer for now! */ +#define RtlDecodePointer RtlEncodePointer + +/* FUNCTIONS ***************************************************************/ + +EXCEPTION_DISPOSITION +RtlpExecuteVectoredExceptionHandlers(IN PEXCEPTION_RECORD ExceptionRecord, + IN PCONTEXT Context) +{ + PLIST_ENTRY CurrentEntry; + PRTL_VECTORED_EXCEPTION_HANDLER veh; + PVECTORED_EXCEPTION_HANDLER VectoredHandler; + EXCEPTION_POINTERS ExceptionInfo; + + ExceptionInfo.ExceptionRecord = ExceptionRecord; + ExceptionInfo.ContextRecord = Context; + + if(RtlpVectoredExceptionHead.Flink != &RtlpVectoredExceptionHead) + { + RtlEnterCriticalSection(&RtlpVectoredExceptionLock); + for(CurrentEntry = RtlpVectoredExceptionHead.Flink; + CurrentEntry != &RtlpVectoredExceptionHead; + CurrentEntry = CurrentEntry->Flink) + { + veh = CONTAINING_RECORD(CurrentEntry, + RTL_VECTORED_EXCEPTION_HANDLER, + ListEntry); + VectoredHandler = RtlDecodePointer(veh->VectoredHandler); + if(VectoredHandler(&ExceptionInfo) == EXCEPTION_CONTINUE_EXECUTION) + { + RtlLeaveCriticalSection(&RtlpVectoredExceptionLock); + return ExceptionContinueSearch; + } + } + RtlLeaveCriticalSection(&RtlpVectoredExceptionLock); + } + + return ExceptionContinueExecution; +} + +VOID +RtlpInitializeVectoredExceptionHandling(VOID) +{ + InitializeListHead(&RtlpVectoredExceptionHead); + RtlInitializeCriticalSection(&RtlpVectoredExceptionLock); +} + + +/* + * @implemented + */ +PVOID STDCALL +RtlAddVectoredExceptionHandler(IN ULONG FirstHandler, + IN PVECTORED_EXCEPTION_HANDLER VectoredHandler) +{ + PRTL_VECTORED_EXCEPTION_HANDLER veh; + + veh = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + sizeof(RTL_VECTORED_EXCEPTION_HANDLER)); + if(veh != NULL) + { + veh->VectoredHandler = RtlEncodePointer(VectoredHandler); + RtlEnterCriticalSection(&RtlpVectoredExceptionLock); + if(FirstHandler != 0) + { + InsertHeadList(&RtlpVectoredExceptionHead, + &veh->ListEntry); + } + else + { + InsertTailList(&RtlpVectoredExceptionHead, + &veh->ListEntry); + } + RtlLeaveCriticalSection(&RtlpVectoredExceptionLock); + } + + return veh; +} + + +/* + * @implemented + */ +ULONG STDCALL +RtlRemoveVectoredExceptionHandler(IN PVOID VectoredHandlerHandle) +{ + PLIST_ENTRY CurrentEntry; + PRTL_VECTORED_EXCEPTION_HANDLER veh = NULL; + ULONG Removed = FALSE; + + RtlEnterCriticalSection(&RtlpVectoredExceptionLock); + for(CurrentEntry = RtlpVectoredExceptionHead.Flink; + CurrentEntry != &RtlpVectoredExceptionHead; + CurrentEntry = CurrentEntry->Flink) + { + veh = CONTAINING_RECORD(CurrentEntry, + RTL_VECTORED_EXCEPTION_HANDLER, + ListEntry); + if(veh == VectoredHandlerHandle) + { + RemoveEntryList(&veh->ListEntry); + Removed = TRUE; + break; + } + } + RtlLeaveCriticalSection(&RtlpVectoredExceptionLock); + + if(Removed) + { + RtlFreeHeap(RtlGetProcessHeap(), + 0, + veh); + } + + return Removed; +} + +/* EOF */ diff --git a/reactos/ntoskrnl/rtl/libsupp.c b/reactos/ntoskrnl/rtl/libsupp.c index d3857a7718b..92d07bbd468 100644 --- a/reactos/ntoskrnl/rtl/libsupp.c +++ b/reactos/ntoskrnl/rtl/libsupp.c @@ -79,25 +79,15 @@ RtlpCurrentPeb(VOID) NTSTATUS STDCALL -RtlDeleteCriticalSection( +RtlDeleteHeapLock( PRTL_CRITICAL_SECTION CriticalSection) { return STATUS_SUCCESS; } -DWORD -STDCALL -RtlSetCriticalSectionSpinCount( - PRTL_CRITICAL_SECTION CriticalSection, - DWORD SpinCount - ) -{ - return 0; -} - NTSTATUS STDCALL -RtlEnterCriticalSection( +RtlEnterHeapLock( PRTL_CRITICAL_SECTION CriticalSection) { ExAcquireFastMutex((PFAST_MUTEX) CriticalSection); @@ -106,7 +96,7 @@ RtlEnterCriticalSection( NTSTATUS STDCALL -RtlInitializeCriticalSection( +RtlInitializeHeapLock( PRTL_CRITICAL_SECTION CriticalSection) { ExInitializeFastMutex((PFAST_MUTEX)CriticalSection ); @@ -115,33 +105,13 @@ RtlInitializeCriticalSection( NTSTATUS STDCALL -RtlLeaveCriticalSection( +RtlLeaveHeapLock( PRTL_CRITICAL_SECTION CriticalSection) { ExReleaseFastMutex((PFAST_MUTEX) CriticalSection ); return STATUS_SUCCESS; } -BOOLEAN -STDCALL -RtlTryEnterCriticalSection( - PRTL_CRITICAL_SECTION CriticalSection) -{ - return ExTryToAcquireFastMutex((PFAST_MUTEX) CriticalSection ); -} - - -NTSTATUS -STDCALL -RtlInitializeCriticalSectionAndSpinCount( - PRTL_CRITICAL_SECTION CriticalSection, - ULONG SpinCount) -{ - ExInitializeFastMutex((PFAST_MUTEX)CriticalSection ); - return STATUS_SUCCESS; -} - - #ifdef DBG VOID FASTCALL CHECK_PAGED_CODE_RTL(char *file, int line)