mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 14:56:31 +00:00
[LDR] Guard some sections where we grab a lock.
CORE-14532
This commit is contained in:
parent
86fe412d5c
commit
ad08c6631b
2 changed files with 194 additions and 180 deletions
|
@ -353,73 +353,80 @@ LdrLoadDll(IN PWSTR SearchPath OPTIONAL,
|
||||||
|
|
||||||
/* Check if there's a TLD DLL being loaded */
|
/* Check if there's a TLD DLL being loaded */
|
||||||
OldTldDll = LdrpTopLevelDllBeingLoaded;
|
OldTldDll = LdrpTopLevelDllBeingLoaded;
|
||||||
if (OldTldDll)
|
_SEH2_TRY
|
||||||
{
|
{
|
||||||
/* This is a recursive load, do something about it? */
|
|
||||||
if ((ShowSnaps) || (LdrpShowRecursiveLoads) || (LdrpBreakOnRecursiveDllLoads))
|
|
||||||
{
|
|
||||||
/* Print out debug messages */
|
|
||||||
DPRINT1("[%p, %p] LDR: Recursive DLL Load\n",
|
|
||||||
Teb->RealClientId.UniqueProcess,
|
|
||||||
Teb->RealClientId.UniqueThread);
|
|
||||||
DPRINT1("[%p, %p] Previous DLL being loaded \"%wZ\"\n",
|
|
||||||
Teb->RealClientId.UniqueProcess,
|
|
||||||
Teb->RealClientId.UniqueThread,
|
|
||||||
OldTldDll);
|
|
||||||
DPRINT1("[%p, %p] DLL being requested \"%wZ\"\n",
|
|
||||||
Teb->RealClientId.UniqueProcess,
|
|
||||||
Teb->RealClientId.UniqueThread,
|
|
||||||
DllName);
|
|
||||||
|
|
||||||
/* Was it initializing too? */
|
if (OldTldDll)
|
||||||
if (!LdrpCurrentDllInitializer)
|
{
|
||||||
|
/* This is a recursive load, do something about it? */
|
||||||
|
if ((ShowSnaps) || (LdrpShowRecursiveLoads) || (LdrpBreakOnRecursiveDllLoads))
|
||||||
{
|
{
|
||||||
DPRINT1("[%p, %p] LDR: No DLL Initializer was running\n",
|
/* Print out debug messages */
|
||||||
|
DPRINT1("[%p, %p] LDR: Recursive DLL Load\n",
|
||||||
Teb->RealClientId.UniqueProcess,
|
Teb->RealClientId.UniqueProcess,
|
||||||
Teb->RealClientId.UniqueThread);
|
Teb->RealClientId.UniqueThread);
|
||||||
}
|
DPRINT1("[%p, %p] Previous DLL being loaded \"%wZ\"\n",
|
||||||
else
|
Teb->RealClientId.UniqueProcess,
|
||||||
{
|
Teb->RealClientId.UniqueThread,
|
||||||
DPRINT1("[%p, %p] DLL whose initializer was currently running \"%wZ\"\n",
|
OldTldDll);
|
||||||
Teb->ClientId.UniqueProcess,
|
DPRINT1("[%p, %p] DLL being requested \"%wZ\"\n",
|
||||||
Teb->ClientId.UniqueThread,
|
Teb->RealClientId.UniqueProcess,
|
||||||
&LdrpCurrentDllInitializer->BaseDllName);
|
Teb->RealClientId.UniqueThread,
|
||||||
|
DllName);
|
||||||
|
|
||||||
|
/* Was it initializing too? */
|
||||||
|
if (!LdrpCurrentDllInitializer)
|
||||||
|
{
|
||||||
|
DPRINT1("[%p, %p] LDR: No DLL Initializer was running\n",
|
||||||
|
Teb->RealClientId.UniqueProcess,
|
||||||
|
Teb->RealClientId.UniqueThread);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINT1("[%p, %p] DLL whose initializer was currently running \"%wZ\"\n",
|
||||||
|
Teb->ClientId.UniqueProcess,
|
||||||
|
Teb->ClientId.UniqueThread,
|
||||||
|
&LdrpCurrentDllInitializer->BaseDllName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set this one as the TLD DLL being loaded*/
|
||||||
|
LdrpTopLevelDllBeingLoaded = DllName;
|
||||||
|
|
||||||
|
/* Load the DLL */
|
||||||
|
Status = LdrpLoadDll(RedirectedDll,
|
||||||
|
SearchPath,
|
||||||
|
DllCharacteristics,
|
||||||
|
DllName,
|
||||||
|
BaseAddress,
|
||||||
|
TRUE);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else if ((Status != STATUS_NO_SUCH_FILE) &&
|
||||||
|
(Status != STATUS_DLL_NOT_FOUND) &&
|
||||||
|
(Status != STATUS_OBJECT_NAME_NOT_FOUND) &&
|
||||||
|
(Status != STATUS_DLL_INIT_FAILED))
|
||||||
|
{
|
||||||
|
DbgPrintEx(DPFLTR_LDR_ID,
|
||||||
|
DPFLTR_WARNING_LEVEL,
|
||||||
|
"LDR: %s - failing because LdrpLoadDll(%wZ) returned status %x\n",
|
||||||
|
__FUNCTION__,
|
||||||
|
DllName,
|
||||||
|
Status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
_SEH2_FINALLY
|
||||||
/* Set this one as the TLD DLL being loaded*/
|
|
||||||
LdrpTopLevelDllBeingLoaded = DllName;
|
|
||||||
|
|
||||||
/* Load the DLL */
|
|
||||||
Status = LdrpLoadDll(RedirectedDll,
|
|
||||||
SearchPath,
|
|
||||||
DllCharacteristics,
|
|
||||||
DllName,
|
|
||||||
BaseAddress,
|
|
||||||
TRUE);
|
|
||||||
if (NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
Status = STATUS_SUCCESS;
|
/* Restore the old TLD DLL */
|
||||||
}
|
LdrpTopLevelDllBeingLoaded = OldTldDll;
|
||||||
else if ((Status != STATUS_NO_SUCH_FILE) &&
|
|
||||||
(Status != STATUS_DLL_NOT_FOUND) &&
|
|
||||||
(Status != STATUS_OBJECT_NAME_NOT_FOUND) &&
|
|
||||||
(Status != STATUS_DLL_INIT_FAILED))
|
|
||||||
{
|
|
||||||
DbgPrintEx(DPFLTR_LDR_ID,
|
|
||||||
DPFLTR_WARNING_LEVEL,
|
|
||||||
"LDR: %s - failing because LdrpLoadDll(%wZ) returned status %x\n",
|
|
||||||
__FUNCTION__,
|
|
||||||
DllName,
|
|
||||||
Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Restore the old TLD DLL */
|
/* Release the lock */
|
||||||
LdrpTopLevelDllBeingLoaded = OldTldDll;
|
LdrUnlockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, Cookie);
|
||||||
|
}
|
||||||
/* Release the lock */
|
_SEH2_END;
|
||||||
LdrUnlockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, Cookie);
|
|
||||||
|
|
||||||
/* Do we have a redirect string? */
|
/* Do we have a redirect string? */
|
||||||
if (DllString2.Buffer) RtlFreeUnicodeString(&DllString2);
|
if (DllString2.Buffer) RtlFreeUnicodeString(&DllString2);
|
||||||
|
|
|
@ -2488,146 +2488,153 @@ LdrpLoadDll(IN BOOLEAN Redirected,
|
||||||
/* Check for init flag and acquire lock */
|
/* Check for init flag and acquire lock */
|
||||||
if (!InInit) RtlEnterCriticalSection(&LdrpLoaderLock);
|
if (!InInit) RtlEnterCriticalSection(&LdrpLoaderLock);
|
||||||
|
|
||||||
/* Show debug message */
|
_SEH2_TRY
|
||||||
if (ShowSnaps)
|
|
||||||
{
|
{
|
||||||
DPRINT1("LDR: LdrLoadDll, loading %wZ from %ws\n",
|
/* Show debug message */
|
||||||
&RawDllName,
|
if (ShowSnaps)
|
||||||
DllPath ? DllPath : L"");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if the DLL is already loaded */
|
|
||||||
if (!LdrpCheckForLoadedDll(DllPath,
|
|
||||||
&RawDllName,
|
|
||||||
FALSE,
|
|
||||||
Redirected,
|
|
||||||
&LdrEntry))
|
|
||||||
{
|
|
||||||
/* Map it */
|
|
||||||
Status = LdrpMapDll(DllPath,
|
|
||||||
DllPath,
|
|
||||||
NameBuffer,
|
|
||||||
DllCharacteristics,
|
|
||||||
FALSE,
|
|
||||||
Redirected,
|
|
||||||
&LdrEntry);
|
|
||||||
if (!NT_SUCCESS(Status)) goto Quickie;
|
|
||||||
|
|
||||||
/* FIXME: Need to mark the DLL range for the stack DB */
|
|
||||||
//RtlpStkMarkDllRange(LdrEntry);
|
|
||||||
|
|
||||||
/* Check if IMAGE_FILE_EXECUTABLE_IMAGE was provided */
|
|
||||||
if ((DllCharacteristics) &&
|
|
||||||
(*DllCharacteristics & IMAGE_FILE_EXECUTABLE_IMAGE))
|
|
||||||
{
|
{
|
||||||
/* This is not a DLL, so remove such data */
|
DPRINT1("LDR: LdrLoadDll, loading %wZ from %ws\n",
|
||||||
LdrEntry->EntryPoint = NULL;
|
&RawDllName,
|
||||||
LdrEntry->Flags &= ~LDRP_IMAGE_DLL;
|
DllPath ? DllPath : L"");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure it's a DLL */
|
/* Check if the DLL is already loaded */
|
||||||
if (LdrEntry->Flags & LDRP_IMAGE_DLL)
|
if (!LdrpCheckForLoadedDll(DllPath,
|
||||||
|
&RawDllName,
|
||||||
|
FALSE,
|
||||||
|
Redirected,
|
||||||
|
&LdrEntry))
|
||||||
{
|
{
|
||||||
/* Check if this is a .NET Image */
|
/* Map it */
|
||||||
if (!(LdrEntry->Flags & LDRP_COR_IMAGE))
|
Status = LdrpMapDll(DllPath,
|
||||||
{
|
DllPath,
|
||||||
/* Walk the Import Descriptor */
|
NameBuffer,
|
||||||
Status = LdrpWalkImportDescriptor(DllPath, LdrEntry);
|
DllCharacteristics,
|
||||||
}
|
FALSE,
|
||||||
|
Redirected,
|
||||||
/* Update load count, unless it's locked */
|
&LdrEntry);
|
||||||
if (LdrEntry->LoadCount != 0xFFFF) LdrEntry->LoadCount++;
|
|
||||||
LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_REFCOUNT);
|
|
||||||
|
|
||||||
/* Check if we failed */
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
|
_SEH2_LEAVE;
|
||||||
|
|
||||||
|
/* FIXME: Need to mark the DLL range for the stack DB */
|
||||||
|
//RtlpStkMarkDllRange(LdrEntry);
|
||||||
|
|
||||||
|
/* Check if IMAGE_FILE_EXECUTABLE_IMAGE was provided */
|
||||||
|
if ((DllCharacteristics) &&
|
||||||
|
(*DllCharacteristics & IMAGE_FILE_EXECUTABLE_IMAGE))
|
||||||
{
|
{
|
||||||
/* Clear entrypoint, and insert into list */
|
/* This is not a DLL, so remove such data */
|
||||||
LdrEntry->EntryPoint = NULL;
|
LdrEntry->EntryPoint = NULL;
|
||||||
InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
|
LdrEntry->Flags &= ~LDRP_IMAGE_DLL;
|
||||||
&LdrEntry->InInitializationOrderLinks);
|
}
|
||||||
|
|
||||||
/* Cancel the load */
|
/* Make sure it's a DLL */
|
||||||
|
if (LdrEntry->Flags & LDRP_IMAGE_DLL)
|
||||||
|
{
|
||||||
|
/* Check if this is a .NET Image */
|
||||||
|
if (!(LdrEntry->Flags & LDRP_COR_IMAGE))
|
||||||
|
{
|
||||||
|
/* Walk the Import Descriptor */
|
||||||
|
Status = LdrpWalkImportDescriptor(DllPath, LdrEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update load count, unless it's locked */
|
||||||
|
if (LdrEntry->LoadCount != 0xFFFF) LdrEntry->LoadCount++;
|
||||||
|
LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_REFCOUNT);
|
||||||
|
|
||||||
|
/* Check if we failed */
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Clear entrypoint, and insert into list */
|
||||||
|
LdrEntry->EntryPoint = NULL;
|
||||||
|
InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
|
||||||
|
&LdrEntry->InInitializationOrderLinks);
|
||||||
|
|
||||||
|
/* Cancel the load */
|
||||||
|
LdrpClearLoadInProgress();
|
||||||
|
|
||||||
|
/* Unload the DLL */
|
||||||
|
if (ShowSnaps)
|
||||||
|
{
|
||||||
|
DbgPrint("LDR: Unloading %wZ due to error %x walking "
|
||||||
|
"import descriptors\n",
|
||||||
|
DllName,
|
||||||
|
Status);
|
||||||
|
}
|
||||||
|
LdrUnloadDll(LdrEntry->DllBase);
|
||||||
|
|
||||||
|
/* Return the error */
|
||||||
|
_SEH2_LEAVE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (LdrEntry->LoadCount != 0xFFFF)
|
||||||
|
{
|
||||||
|
/* Increase load count */
|
||||||
|
LdrEntry->LoadCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Insert it into the list */
|
||||||
|
InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
|
||||||
|
&LdrEntry->InInitializationOrderLinks);
|
||||||
|
|
||||||
|
/* If we have to run the entrypoint, make sure the DB is ready */
|
||||||
|
if (CallInit && LdrpLdrDatabaseIsSetup)
|
||||||
|
{
|
||||||
|
/* Notify Shim Engine */
|
||||||
|
if (g_ShimsEnabled)
|
||||||
|
{
|
||||||
|
VOID (NTAPI* SE_DllLoaded)(PLDR_DATA_TABLE_ENTRY) = RtlDecodeSystemPointer(g_pfnSE_DllLoaded);
|
||||||
|
SE_DllLoaded(LdrEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Run the init routine */
|
||||||
|
Status = LdrpRunInitializeRoutines(NULL);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Failed, unload the DLL */
|
||||||
|
if (ShowSnaps)
|
||||||
|
{
|
||||||
|
DbgPrint("LDR: Unloading %wZ because either its init "
|
||||||
|
"routine or one of its static imports failed; "
|
||||||
|
"status = 0x%08lx\n",
|
||||||
|
DllName,
|
||||||
|
Status);
|
||||||
|
}
|
||||||
|
LdrUnloadDll(LdrEntry->DllBase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The DB isn't ready, which means we were loaded because of a forwarder */
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We were already loaded. Are we a DLL? */
|
||||||
|
if ((LdrEntry->Flags & LDRP_IMAGE_DLL) && (LdrEntry->LoadCount != 0xFFFF))
|
||||||
|
{
|
||||||
|
/* Increase load count */
|
||||||
|
LdrEntry->LoadCount++;
|
||||||
|
LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_REFCOUNT);
|
||||||
|
|
||||||
|
/* Clear the load in progress */
|
||||||
LdrpClearLoadInProgress();
|
LdrpClearLoadInProgress();
|
||||||
|
|
||||||
/* Unload the DLL */
|
|
||||||
if (ShowSnaps)
|
|
||||||
{
|
|
||||||
DbgPrint("LDR: Unloading %wZ due to error %x walking "
|
|
||||||
"import descriptors\n",
|
|
||||||
DllName,
|
|
||||||
Status);
|
|
||||||
}
|
|
||||||
LdrUnloadDll(LdrEntry->DllBase);
|
|
||||||
|
|
||||||
/* Return the error */
|
|
||||||
goto Quickie;
|
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
else if (LdrEntry->LoadCount != 0xFFFF)
|
|
||||||
{
|
|
||||||
/* Increase load count */
|
|
||||||
LdrEntry->LoadCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Insert it into the list */
|
|
||||||
InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
|
|
||||||
&LdrEntry->InInitializationOrderLinks);
|
|
||||||
|
|
||||||
/* If we have to run the entrypoint, make sure the DB is ready */
|
|
||||||
if (CallInit && LdrpLdrDatabaseIsSetup)
|
|
||||||
{
|
|
||||||
/* Notify Shim Engine */
|
|
||||||
if (g_ShimsEnabled)
|
|
||||||
{
|
{
|
||||||
VOID (NTAPI* SE_DllLoaded)(PLDR_DATA_TABLE_ENTRY) = RtlDecodeSystemPointer(g_pfnSE_DllLoaded);
|
/* Not a DLL, just increase the load count */
|
||||||
SE_DllLoaded(LdrEntry);
|
if (LdrEntry->LoadCount != 0xFFFF) LdrEntry->LoadCount++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Run the init routine */
|
|
||||||
Status = LdrpRunInitializeRoutines(NULL);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
/* Failed, unload the DLL */
|
|
||||||
if (ShowSnaps)
|
|
||||||
{
|
|
||||||
DbgPrint("LDR: Unloading %wZ because either its init "
|
|
||||||
"routine or one of its static imports failed; "
|
|
||||||
"status = 0x%08lx\n",
|
|
||||||
DllName,
|
|
||||||
Status);
|
|
||||||
}
|
|
||||||
LdrUnloadDll(LdrEntry->DllBase);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* The DB isn't ready, which means we were loaded because of a forwarder */
|
|
||||||
Status = STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
_SEH2_FINALLY
|
||||||
{
|
{
|
||||||
/* We were already loaded. Are we a DLL? */
|
/* Release the lock */
|
||||||
if ((LdrEntry->Flags & LDRP_IMAGE_DLL) && (LdrEntry->LoadCount != 0xFFFF))
|
if (!InInit) RtlLeaveCriticalSection(&LdrpLoaderLock);
|
||||||
{
|
|
||||||
/* Increase load count */
|
|
||||||
LdrEntry->LoadCount++;
|
|
||||||
LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_REFCOUNT);
|
|
||||||
|
|
||||||
/* Clear the load in progress */
|
|
||||||
LdrpClearLoadInProgress();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Not a DLL, just increase the load count */
|
|
||||||
if (LdrEntry->LoadCount != 0xFFFF) LdrEntry->LoadCount++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
_SEH2_END;
|
||||||
Quickie:
|
|
||||||
/* Release the lock */
|
|
||||||
if (!InInit) RtlLeaveCriticalSection(&LdrpLoaderLock);
|
|
||||||
|
|
||||||
/* Check for success */
|
/* Check for success */
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue