mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
[NTDLL/LDR]
- Rewrite loader lock APIs. Now they support proper flags, return correct error codes and generate/check a cookie. svn path=/trunk/; revision=51056
This commit is contained in:
parent
62fce851b1
commit
10346cccb2
6 changed files with 256 additions and 76 deletions
|
@ -21,6 +21,8 @@ typedef BOOL
|
|||
ULONG ul_reason_for_call,
|
||||
LPVOID lpReserved);
|
||||
|
||||
/* Global data */
|
||||
extern RTL_CRITICAL_SECTION LdrpLoaderLock;
|
||||
|
||||
/* ldrinit.c */
|
||||
NTSTATUS NTAPI LdrpInitializeTls(VOID);
|
||||
|
|
249
reactos/dll/ntdll/ldr/ldrapi.c
Normal file
249
reactos/dll/ntdll/ldr/ldrapi.c
Normal file
|
@ -0,0 +1,249 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS NT User Mode Library
|
||||
* FILE: dll/ntdll/ldr/ldrapi.c
|
||||
* PURPOSE: PE Loader Public APIs
|
||||
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
|
||||
* Aleksey Bragin (aleksey@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <ntdll.h>
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
#define LDR_LOCK_HELD 0x2
|
||||
#define LDR_LOCK_FREE 0x1
|
||||
|
||||
LONG LdrpLoaderLockAcquisitonCount;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
LdrUnlockLoaderLock(IN ULONG Flags,
|
||||
IN ULONG Cookie OPTIONAL)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
DPRINT("LdrUnlockLoaderLock(%x %x)\n", Flags, Cookie);
|
||||
|
||||
/* Check for valid flags */
|
||||
if (Flags & ~1)
|
||||
{
|
||||
/* Flags are invalid, check how to fail */
|
||||
if (Flags & LDR_LOCK_LOADER_LOCK_FLAG_RAISE_STATUS)
|
||||
{
|
||||
/* The caller wants us to raise status */
|
||||
RtlRaiseStatus(STATUS_INVALID_PARAMETER_1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* A normal failure */
|
||||
return STATUS_INVALID_PARAMETER_1;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we don't have a cookie, just return */
|
||||
if (!Cookie) return STATUS_SUCCESS;
|
||||
|
||||
/* Validate the cookie */
|
||||
if ((Cookie & 0xF0000000) ||
|
||||
((Cookie >> 16) ^ ((ULONG)(NtCurrentTeb()->RealClientId.UniqueThread) & 0xFFF)))
|
||||
{
|
||||
DPRINT1("LdrUnlockLoaderLock() called with an invalid cookie!\n");
|
||||
|
||||
/* Invalid cookie, check how to fail */
|
||||
if (Flags & LDR_LOCK_LOADER_LOCK_FLAG_RAISE_STATUS)
|
||||
{
|
||||
/* The caller wants us to raise status */
|
||||
RtlRaiseStatus(STATUS_INVALID_PARAMETER_2);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* A normal failure */
|
||||
return STATUS_INVALID_PARAMETER_2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ready to release the lock */
|
||||
if (Flags & LDR_LOCK_LOADER_LOCK_FLAG_RAISE_STATUS)
|
||||
{
|
||||
/* Do a direct leave */
|
||||
RtlLeaveCriticalSection(&LdrpLoaderLock);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Wrap this in SEH, since we're not supposed to raise */
|
||||
_SEH2_TRY
|
||||
{
|
||||
/* Leave the lock */
|
||||
RtlLeaveCriticalSection(&LdrpLoaderLock);
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
/* We should use the LDR Filter instead */
|
||||
Status = _SEH2_GetExceptionCode();
|
||||
}
|
||||
_SEH2_END;
|
||||
}
|
||||
|
||||
/* All done */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
LdrLockLoaderLock(IN ULONG Flags,
|
||||
OUT PULONG Result OPTIONAL,
|
||||
OUT PULONG Cookie OPTIONAL)
|
||||
{
|
||||
LONG OldCount;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
BOOLEAN InInit = FALSE; // FIXME
|
||||
//BOOLEAN InInit = LdrpInLdrInit;
|
||||
|
||||
DPRINT("LdrLockLoaderLock(%x %p %p)\n", Flags, Result, Cookie);
|
||||
|
||||
/* Zero out the outputs */
|
||||
if (Result) *Result = 0;
|
||||
if (Cookie) *Cookie = 0;
|
||||
|
||||
/* Validate the flags */
|
||||
if (Flags & ~(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_STATUS |
|
||||
LDR_LOCK_LOADER_LOCK_FLAG_TRY_ONLY))
|
||||
{
|
||||
/* Flags are invalid, check how to fail */
|
||||
if (Flags & LDR_LOCK_LOADER_LOCK_FLAG_RAISE_STATUS)
|
||||
{
|
||||
/* The caller wants us to raise status */
|
||||
RtlRaiseStatus(STATUS_INVALID_PARAMETER_1);
|
||||
}
|
||||
|
||||
/* A normal failure */
|
||||
return STATUS_INVALID_PARAMETER_1;
|
||||
}
|
||||
|
||||
/* Make sure we got a cookie */
|
||||
if (!Cookie)
|
||||
{
|
||||
/* No cookie check how to fail */
|
||||
if (Flags & LDR_LOCK_LOADER_LOCK_FLAG_RAISE_STATUS)
|
||||
{
|
||||
/* The caller wants us to raise status */
|
||||
RtlRaiseStatus(STATUS_INVALID_PARAMETER_3);
|
||||
}
|
||||
|
||||
/* A normal failure */
|
||||
return STATUS_INVALID_PARAMETER_3;
|
||||
}
|
||||
|
||||
/* If the flag is set, make sure we have a valid pointer to use */
|
||||
if ((Flags & LDR_LOCK_LOADER_LOCK_FLAG_TRY_ONLY) && !(Result))
|
||||
{
|
||||
/* No pointer to return the data to */
|
||||
if (Flags & LDR_LOCK_LOADER_LOCK_FLAG_RAISE_STATUS)
|
||||
{
|
||||
/* The caller wants us to raise status */
|
||||
RtlRaiseStatus(STATUS_INVALID_PARAMETER_2);
|
||||
}
|
||||
|
||||
/* Fail */
|
||||
return STATUS_INVALID_PARAMETER_2;
|
||||
}
|
||||
|
||||
/* Return now if we are in the init phase */
|
||||
if (InInit) return STATUS_SUCCESS;
|
||||
|
||||
/* Check what locking semantic to use */
|
||||
if (Flags & LDR_LOCK_LOADER_LOCK_FLAG_RAISE_STATUS)
|
||||
{
|
||||
/* Check if we should enter or simply try */
|
||||
if (Flags & LDR_LOCK_LOADER_LOCK_FLAG_TRY_ONLY)
|
||||
{
|
||||
/* Do a try */
|
||||
if (!RtlTryEnterCriticalSection(&LdrpLoaderLock))
|
||||
{
|
||||
/* It's locked */
|
||||
*Result = LDR_LOCK_HELD;
|
||||
goto Quickie;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It worked */
|
||||
*Result = LDR_LOCK_FREE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Do a enter */
|
||||
RtlEnterCriticalSection(&LdrpLoaderLock);
|
||||
|
||||
/* See if result was requested */
|
||||
if (Result) *Result = LDR_LOCK_FREE;
|
||||
}
|
||||
|
||||
/* Increase the acquisition count */
|
||||
OldCount = _InterlockedIncrement(&LdrpLoaderLockAcquisitonCount);
|
||||
|
||||
/* Generate a cookie */
|
||||
*Cookie = (((ULONG)NtCurrentTeb()->RealClientId.UniqueThread & 0xFFF) << 16) | OldCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Wrap this in SEH, since we're not supposed to raise */
|
||||
_SEH2_TRY
|
||||
{
|
||||
/* Check if we should enter or simply try */
|
||||
if (Flags & LDR_LOCK_LOADER_LOCK_FLAG_TRY_ONLY)
|
||||
{
|
||||
/* Do a try */
|
||||
if (!RtlTryEnterCriticalSection(&LdrpLoaderLock))
|
||||
{
|
||||
/* It's locked */
|
||||
*Result = LDR_LOCK_HELD;
|
||||
_SEH2_YIELD(return STATUS_SUCCESS);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It worked */
|
||||
*Result = LDR_LOCK_FREE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Do an enter */
|
||||
RtlEnterCriticalSection(&LdrpLoaderLock);
|
||||
|
||||
/* See if result was requested */
|
||||
if (Result) *Result = LDR_LOCK_FREE;
|
||||
}
|
||||
|
||||
/* Increase the acquisition count */
|
||||
OldCount = _InterlockedIncrement(&LdrpLoaderLockAcquisitonCount);
|
||||
|
||||
/* Generate a cookie */
|
||||
*Cookie = (((ULONG)NtCurrentTeb()->RealClientId.UniqueThread & 0xFFF) << 16) | OldCount;
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
/* We should use the LDR Filter instead */
|
||||
Status = _SEH2_GetExceptionCode();
|
||||
}
|
||||
_SEH2_END;
|
||||
}
|
||||
|
||||
Quickie:
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* EOF */
|
|
@ -28,6 +28,8 @@ LIST_ENTRY LdrpTlsList;
|
|||
ULONG LdrpNumberOfTlsEntries;
|
||||
ULONG LdrpNumberOfProcessors;
|
||||
|
||||
RTL_CRITICAL_SECTION LdrpLoaderLock;
|
||||
|
||||
BOOLEAN ShowSnaps;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
|
|
@ -25,7 +25,6 @@ extern PTEB LdrpTopLevelDllBeingLoadedTeb;
|
|||
|
||||
PLDR_DATA_TABLE_ENTRY ExeModule;
|
||||
static RTL_CRITICAL_SECTION PebLock;
|
||||
static RTL_CRITICAL_SECTION LoaderLock;
|
||||
static RTL_BITMAP TlsBitMap;
|
||||
static RTL_BITMAP TlsExpansionBitMap;
|
||||
static volatile BOOLEAN LdrpInitialized = FALSE;
|
||||
|
@ -467,8 +466,8 @@ LdrpInit2(PCONTEXT Context,
|
|||
}
|
||||
|
||||
/* initalize loader lock */
|
||||
RtlInitializeCriticalSection(&LoaderLock);
|
||||
Peb->LoaderLock = &LoaderLock;
|
||||
RtlInitializeCriticalSection(&LdrpLoaderLock);
|
||||
Peb->LoaderLock = &LdrpLoaderLock;
|
||||
|
||||
/* create loader information */
|
||||
Peb->Ldr = (PPEB_LDR_DATA) RtlAllocateHeap(Peb->ProcessHeap,
|
||||
|
|
|
@ -3154,79 +3154,6 @@ LdrProcessRelocationBlock(
|
|||
return LdrProcessRelocationBlockLongLong(Address, Count, TypeOffset, Delta);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
LdrLockLoaderLock(IN ULONG Flags,
|
||||
OUT PULONG Disposition OPTIONAL,
|
||||
OUT PULONG Cookie OPTIONAL)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
BOOLEAN Ret;
|
||||
BOOLEAN CookieSet = FALSE;
|
||||
|
||||
if ((Flags != 0x01) && (Flags != 0x02))
|
||||
return STATUS_INVALID_PARAMETER_1;
|
||||
|
||||
if (!Cookie) return STATUS_INVALID_PARAMETER_3;
|
||||
|
||||
/* Set some defaults for failure while verifying params */
|
||||
_SEH2_TRY
|
||||
{
|
||||
*Cookie = 0;
|
||||
CookieSet = TRUE;
|
||||
if (Disposition) *Disposition = 0;
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
if (CookieSet)
|
||||
Status = STATUS_INVALID_PARAMETER_3;
|
||||
else
|
||||
Status = STATUS_INVALID_PARAMETER_2;
|
||||
}
|
||||
_SEH2_END;
|
||||
|
||||
if (Flags == 0x01)
|
||||
{
|
||||
DPRINT1("Warning: Reporting errors with exception not supported yet!\n");
|
||||
RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock);
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Disposition) return STATUS_INVALID_PARAMETER_2;
|
||||
|
||||
Ret = RtlTryEnterCriticalSection(NtCurrentPeb()->LoaderLock);
|
||||
|
||||
if (Ret)
|
||||
*Disposition = 0x01;
|
||||
else
|
||||
*Disposition = 0x02;
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* FIXME: Cookie is based on part of the thread id */
|
||||
*Cookie = (ULONG)NtCurrentTeb()->RealClientId.UniqueThread;
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
LdrUnlockLoaderLock(IN ULONG Flags,
|
||||
IN ULONG Cookie OPTIONAL)
|
||||
{
|
||||
if (Flags != 0x01)
|
||||
return STATUS_INVALID_PARAMETER_1;
|
||||
|
||||
if (Cookie != (ULONG)NtCurrentTeb()->RealClientId.UniqueThread)
|
||||
return STATUS_INVALID_PARAMETER_2;
|
||||
|
||||
RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
LdrUnloadAlternateResourceModule(IN PVOID BaseAddress)
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
<pch>ntdll.h</pch>
|
||||
</directory>
|
||||
<directory name="ldr">
|
||||
<file>ldrapi.c</file>
|
||||
<file>ldrinit.c</file>
|
||||
<file>ldrutils.c</file>
|
||||
<file>startup.c</file>
|
||||
|
|
Loading…
Reference in a new issue