mirror of
https://github.com/reactos/reactos.git
synced 2024-06-30 18:01:07 +00:00
[NTDLL]
- Implement LdrpInitializeProcess(). Currently unused. - Add a whole bunch of supportive PE related code. Used only by the new code, which is not enabled yet in trunk. - Implement LdrpCheckForLoadedDll(). - Move on to usage of various global vars defined in the new code, rename some of them to match. - Almost no changes for the codepath in trunk. svn path=/trunk/; revision=51117
This commit is contained in:
parent
4a05e4ef29
commit
64e9e4c196
|
@ -26,6 +26,7 @@ extern RTL_CRITICAL_SECTION LdrpLoaderLock;
|
|||
extern BOOLEAN LdrpInLdrInit;
|
||||
extern LIST_ENTRY LdrpHashTable[LDR_HASH_TABLE_ENTRIES];
|
||||
extern BOOLEAN ShowSnaps;
|
||||
extern UNICODE_STRING LdrpDefaultPath;
|
||||
|
||||
/* ldrinit.c */
|
||||
NTSTATUS NTAPI LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL);
|
||||
|
|
|
@ -19,31 +19,69 @@ HKEY ImageExecOptionsKey;
|
|||
HKEY Wow64ExecOptionsKey;
|
||||
UNICODE_STRING ImageExecOptionsString = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options");
|
||||
UNICODE_STRING Wow64OptionsString = RTL_CONSTANT_STRING(L"");
|
||||
UNICODE_STRING NtDllString = RTL_CONSTANT_STRING(L"ntdll.dll");
|
||||
|
||||
BOOLEAN LdrpInLdrInit;
|
||||
LONG LdrpProcessInitialized;
|
||||
BOOLEAN LdrpLoaderLockInit;
|
||||
BOOLEAN LdrpLdrDatabaseIsSetup;
|
||||
|
||||
BOOLEAN LdrpDllValidation;
|
||||
|
||||
PLDR_DATA_TABLE_ENTRY LdrpImageEntry;
|
||||
PUNICODE_STRING LdrpTopLevelDllBeingLoaded;
|
||||
extern PTEB LdrpTopLevelDllBeingLoadedTeb; // defined in rtlsupp.c!
|
||||
PLDR_DATA_TABLE_ENTRY LdrpCurrentDllInitializer;
|
||||
PLDR_DATA_TABLE_ENTRY LdrpNtDllDataTableEntry;
|
||||
|
||||
//RTL_BITMAP TlsBitMap;
|
||||
//RTL_BITMAP TlsExpansionBitMap;
|
||||
//RTL_BITMAP FlsBitMap;
|
||||
RTL_BITMAP TlsBitMap;
|
||||
RTL_BITMAP TlsExpansionBitMap;
|
||||
RTL_BITMAP FlsBitMap;
|
||||
BOOLEAN LdrpImageHasTls;
|
||||
LIST_ENTRY LdrpTlsList;
|
||||
ULONG LdrpNumberOfTlsEntries;
|
||||
ULONG LdrpNumberOfProcessors;
|
||||
PVOID NtDllBase;
|
||||
LARGE_INTEGER RtlpTimeout;
|
||||
BOOLEAN RtlpTimeoutDisable;
|
||||
LIST_ENTRY LdrpHashTable[LDR_HASH_TABLE_ENTRIES];
|
||||
LIST_ENTRY LdrpDllNotificationList;
|
||||
HANDLE LdrpKnownDllObjectDirectory;
|
||||
UNICODE_STRING LdrpKnownDllPath;
|
||||
WCHAR LdrpKnownDllPathBuffer[128];
|
||||
UNICODE_STRING LdrpDefaultPath;
|
||||
|
||||
RTL_CRITICAL_SECTION LdrpLoaderLock;
|
||||
PEB_LDR_DATA PebLdr;
|
||||
|
||||
RTL_CRITICAL_SECTION_DEBUG LdrpLoaderLockDebug;
|
||||
RTL_CRITICAL_SECTION LdrpLoaderLock =
|
||||
{
|
||||
&LdrpLoaderLockDebug,
|
||||
-1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
RTL_CRITICAL_SECTION FastPebLock;
|
||||
|
||||
BOOLEAN ShowSnaps;
|
||||
|
||||
ULONG LdrpFatalHardErrorCount;
|
||||
|
||||
//extern LIST_ENTRY RtlCriticalSectionList;
|
||||
|
||||
VOID RtlpInitializeVectoredExceptionHandling(VOID);
|
||||
VOID NTAPI RtlpInitDeferedCriticalSection(VOID);
|
||||
VOID RtlInitializeHeapManager(VOID);
|
||||
extern BOOLEAN RtlpPageHeapEnabled;
|
||||
extern ULONG RtlpDphGlobalFlags;
|
||||
|
||||
NTSTATUS LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders, PVOID ImageBase);
|
||||
NTSTATUS NTAPI
|
||||
LdrpInitializeProcess_(PCONTEXT Context,
|
||||
PVOID SystemArgument1);
|
||||
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
|
@ -455,12 +493,10 @@ LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL)
|
|||
/* Show debug message */
|
||||
if (ShowSnaps)
|
||||
{
|
||||
DPRINT1("[%x,%x] LDR: Real INIT LIST for Process %wZ pid %u %0x%x\n",
|
||||
DPRINT1("[%x,%x] LDR: Real INIT LIST for Process %wZ\n",
|
||||
NtCurrentTeb()->RealClientId.UniqueThread,
|
||||
NtCurrentTeb()->RealClientId.UniqueProcess,
|
||||
Peb->ProcessParameters->ImagePathName,
|
||||
NtCurrentTeb()->RealClientId.UniqueThread,
|
||||
NtCurrentTeb()->RealClientId.UniqueProcess);
|
||||
&Peb->ProcessParameters->ImagePathName);
|
||||
}
|
||||
|
||||
/* Loop in order */
|
||||
|
@ -838,6 +874,644 @@ LdrpFreeTls(VOID)
|
|||
TlsVector);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
LdrpInitializeExecutionOptions(PUNICODE_STRING ImagePathName, PPEB Peb, PULONG Options)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
*Options = 0;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
LdrpValidateImageForMp(IN PLDR_DATA_TABLE_ENTRY LdrDataTableEntry)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
LdrpInitializeProcess(IN PCONTEXT Context,
|
||||
IN PVOID SystemArgument1)
|
||||
{
|
||||
RTL_HEAP_PARAMETERS HeapParameters;
|
||||
ULONG ComSectionSize;
|
||||
//ANSI_STRING FunctionName = RTL_CONSTANT_STRING("BaseQueryModuleData");
|
||||
PVOID OldShimData;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
//UNICODE_STRING LocalFileName, FullImageName;
|
||||
HANDLE SymLinkHandle;
|
||||
//ULONG DebugHeapOnly;
|
||||
UNICODE_STRING CommandLine, NtSystemRoot, ImagePathName, FullPath, ImageFileName, KnownDllString;
|
||||
PPEB Peb = NtCurrentPeb();
|
||||
BOOLEAN IsDotNetImage = FALSE;
|
||||
BOOLEAN FreeCurDir = FALSE;
|
||||
//HKEY CompatKey;
|
||||
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
|
||||
//LPWSTR ImagePathBuffer;
|
||||
ULONG ConfigSize;
|
||||
UNICODE_STRING CurrentDirectory;
|
||||
ULONG ExecuteOptions;
|
||||
ULONG HeapFlags;
|
||||
PIMAGE_NT_HEADERS NtHeader;
|
||||
LPWSTR NtDllName = NULL;
|
||||
NTSTATUS Status;
|
||||
NLSTABLEINFO NlsTable;
|
||||
PIMAGE_LOAD_CONFIG_DIRECTORY LoadConfig;
|
||||
PTEB Teb = NtCurrentTeb();
|
||||
PLIST_ENTRY ListHead;
|
||||
PLIST_ENTRY NextEntry;
|
||||
ULONG i;
|
||||
PWSTR ImagePath;
|
||||
ULONG DebugProcessHeapOnly = 0;
|
||||
WCHAR FullNtDllPath[MAX_PATH];
|
||||
PLDR_DATA_TABLE_ENTRY NtLdrEntry;
|
||||
PWCHAR Current;
|
||||
|
||||
/* Set a NULL SEH Filter */
|
||||
RtlSetUnhandledExceptionFilter(NULL);
|
||||
|
||||
/* Get the image path */
|
||||
ImagePath = Peb->ProcessParameters->ImagePathName.Buffer;
|
||||
|
||||
/* Check if it's normalized */
|
||||
if (Peb->ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_NORMALIZED)
|
||||
{
|
||||
/* Normalize it*/
|
||||
ImagePath = (PWSTR)((ULONG_PTR)ImagePath + (ULONG_PTR)Peb->ProcessParameters);
|
||||
}
|
||||
|
||||
/* Create a unicode string for the Image Path */
|
||||
ImagePathName.Length = Peb->ProcessParameters->ImagePathName.Length;
|
||||
ImagePathName.MaximumLength = ImagePathName.Length + sizeof(WCHAR);
|
||||
ImagePathName.Buffer = ImagePath;
|
||||
|
||||
/* Get the NT Headers */
|
||||
NtHeader = RtlImageNtHeader(Peb->ImageBaseAddress);
|
||||
|
||||
/* Get the execution options */
|
||||
Status = LdrpInitializeExecutionOptions(&ImagePathName, Peb, &ExecuteOptions);
|
||||
|
||||
/* Check if this is a .NET executable */
|
||||
if (RtlImageDirectoryEntryToData(Peb->ImageBaseAddress,
|
||||
TRUE,
|
||||
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR,
|
||||
&ComSectionSize))
|
||||
{
|
||||
/* Remeber this for later */
|
||||
IsDotNetImage = TRUE;
|
||||
}
|
||||
|
||||
/* Save the NTDLL Base address */
|
||||
NtDllBase = SystemArgument1;
|
||||
|
||||
/* If this is a Native Image */
|
||||
if (NtHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_NATIVE)
|
||||
{
|
||||
/* Then do DLL Validation */
|
||||
LdrpDllValidation = TRUE;
|
||||
}
|
||||
|
||||
/* Save the old Shim Data */
|
||||
OldShimData = Peb->pShimData;
|
||||
|
||||
/* Clear it */
|
||||
Peb->pShimData = NULL;
|
||||
|
||||
/* Save the number of processors and CS Timeout */
|
||||
LdrpNumberOfProcessors = Peb->NumberOfProcessors;
|
||||
RtlpTimeout = Peb->CriticalSectionTimeout;
|
||||
|
||||
/* Normalize the parameters */
|
||||
ProcessParameters = RtlNormalizeProcessParams(Peb->ProcessParameters);
|
||||
ProcessParameters = Peb->ProcessParameters;
|
||||
if (ProcessParameters)
|
||||
{
|
||||
/* Save the Image and Command Line Names */
|
||||
ImageFileName = ProcessParameters->ImagePathName;
|
||||
CommandLine = ProcessParameters->CommandLine;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It failed, initialize empty strings */
|
||||
RtlInitUnicodeString(&ImageFileName, NULL);
|
||||
RtlInitUnicodeString(&CommandLine, NULL);
|
||||
}
|
||||
|
||||
/* Initialize NLS data */
|
||||
RtlInitNlsTables(Peb->AnsiCodePageData,
|
||||
Peb->OemCodePageData,
|
||||
Peb->UnicodeCaseTableData,
|
||||
&NlsTable);
|
||||
|
||||
/* Reset NLS Translations */
|
||||
RtlResetRtlTranslations(&NlsTable);
|
||||
|
||||
/* Get the Image Config Directory */
|
||||
LoadConfig = RtlImageDirectoryEntryToData(Peb->ImageBaseAddress,
|
||||
TRUE,
|
||||
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
|
||||
&ConfigSize);
|
||||
|
||||
/* Setup the Heap Parameters */
|
||||
RtlZeroMemory(&HeapParameters, sizeof(RTL_HEAP_PARAMETERS));
|
||||
HeapFlags = HEAP_GROWABLE;
|
||||
HeapParameters.Length = sizeof(RTL_HEAP_PARAMETERS);
|
||||
|
||||
/* Check if we have Configuration Data */
|
||||
if ((LoadConfig) && (ConfigSize == sizeof(IMAGE_LOAD_CONFIG_DIRECTORY)))
|
||||
{
|
||||
/* FIXME: Custom heap settings and misc. */
|
||||
DPRINT1("We don't support LOAD_CONFIG data yet\n");
|
||||
}
|
||||
|
||||
/* Check for custom affinity mask */
|
||||
if (Peb->ImageProcessAffinityMask)
|
||||
{
|
||||
/* Set it */
|
||||
Status = NtSetInformationProcess(NtCurrentProcess(),
|
||||
ProcessAffinityMask,
|
||||
&Peb->ImageProcessAffinityMask,
|
||||
sizeof(Peb->ImageProcessAffinityMask));
|
||||
}
|
||||
|
||||
/* Check if verbose debugging (ShowSnaps) was requested */
|
||||
ShowSnaps = TRUE;//Peb->NtGlobalFlag & FLG_SHOW_LDR_SNAPS;
|
||||
|
||||
/* Start verbose debugging messages right now if they were requested */
|
||||
if (ShowSnaps)
|
||||
{
|
||||
DPRINT1("LDR: PID: 0x%x started - '%wZ'\n",
|
||||
Teb->ClientId.UniqueProcess,
|
||||
&CommandLine);
|
||||
}
|
||||
|
||||
/* If the timeout is too long */
|
||||
if (RtlpTimeout.QuadPart < Int32x32To64(3600, -10000000))
|
||||
{
|
||||
/* Then disable CS Timeout */
|
||||
RtlpTimeoutDisable = TRUE;
|
||||
}
|
||||
|
||||
/* Initialize Critical Section Data */
|
||||
RtlpInitDeferedCriticalSection();
|
||||
|
||||
/* Initialize VEH Call lists */
|
||||
RtlpInitializeVectoredExceptionHandling();
|
||||
|
||||
/* Set TLS/FLS Bitmap data */
|
||||
Peb->FlsBitmap = &FlsBitMap;
|
||||
Peb->TlsBitmap = &TlsBitMap;
|
||||
Peb->TlsExpansionBitmap = &TlsExpansionBitMap;
|
||||
|
||||
/* Initialize FLS Bitmap */
|
||||
RtlInitializeBitMap(&FlsBitMap,
|
||||
Peb->FlsBitmapBits,
|
||||
FLS_MAXIMUM_AVAILABLE);
|
||||
RtlSetBit(&FlsBitMap, 0);
|
||||
|
||||
/* Initialize TLS Bitmap */
|
||||
RtlInitializeBitMap(&TlsBitMap,
|
||||
Peb->TlsBitmapBits,
|
||||
TLS_MINIMUM_AVAILABLE);
|
||||
RtlSetBit(&TlsBitMap, 0);
|
||||
RtlInitializeBitMap(&TlsExpansionBitMap,
|
||||
Peb->TlsExpansionBitmapBits,
|
||||
TLS_EXPANSION_SLOTS);
|
||||
RtlSetBit(&TlsExpansionBitMap, 0);
|
||||
|
||||
/* Initialize the Hash Table */
|
||||
for (i = 0; i < LDR_HASH_TABLE_ENTRIES; i++)
|
||||
{
|
||||
InitializeListHead(&LdrpHashTable[i]);
|
||||
}
|
||||
|
||||
/* Initialize the Loader Lock */
|
||||
//InsertTailList(&RtlCriticalSectionList, &LdrpLoaderLock.DebugInfo->ProcessLocksList);
|
||||
//LdrpLoaderLock.DebugInfo->CriticalSection = &LdrpLoaderLock;
|
||||
UNIMPLEMENTED;
|
||||
LdrpLoaderLockInit = TRUE;
|
||||
|
||||
/* Check if User Stack Trace Database support was requested */
|
||||
if (Peb->NtGlobalFlag & FLG_USER_STACK_TRACE_DB)
|
||||
{
|
||||
DPRINT1("We don't support user stack trace databases yet\n");
|
||||
}
|
||||
|
||||
/* Setup Fast PEB Lock */
|
||||
RtlInitializeCriticalSection(&FastPebLock);
|
||||
Peb->FastPebLock = &FastPebLock;
|
||||
//Peb->FastPebLockRoutine = (PPEBLOCKROUTINE)RtlEnterCriticalSection;
|
||||
//Peb->FastPebUnlockRoutine = (PPEBLOCKROUTINE)RtlLeaveCriticalSection;
|
||||
|
||||
/* Setup Callout Lock and Notification list */
|
||||
//RtlInitializeCriticalSection(&RtlpCalloutEntryLock);
|
||||
InitializeListHead(&LdrpDllNotificationList);
|
||||
|
||||
/* For old executables, use 16-byte aligned heap */
|
||||
if ((NtHeader->OptionalHeader.MajorSubsystemVersion <= 3) &&
|
||||
(NtHeader->OptionalHeader.MinorSubsystemVersion < 51))
|
||||
{
|
||||
HeapFlags |= HEAP_CREATE_ALIGN_16;
|
||||
}
|
||||
|
||||
/* Setup the Heap */
|
||||
RtlInitializeHeapManager();
|
||||
Peb->ProcessHeap = RtlCreateHeap(HeapFlags,
|
||||
NULL,
|
||||
NtHeader->OptionalHeader.SizeOfHeapReserve,
|
||||
NtHeader->OptionalHeader.SizeOfHeapCommit,
|
||||
NULL,
|
||||
&HeapParameters);
|
||||
|
||||
if (!Peb->ProcessHeap)
|
||||
{
|
||||
DPRINT1("Failed to create process heap\n");
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* Allocate an Activation Context Stack */
|
||||
Status = RtlAllocateActivationContextStack((PVOID *)&Teb->ActivationContextStackPointer);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
// FIXME: Loader private heap is missing
|
||||
DPRINT1("Loader private heap is missing\n");
|
||||
|
||||
/* Check for Debug Heap */
|
||||
DPRINT1("Check for a debug heap is missing\n");
|
||||
if (FALSE)
|
||||
{
|
||||
/* Query the setting */
|
||||
Status = LdrQueryImageFileKeyOption(NULL,//hKey
|
||||
L"DebugProcessHeapOnly",
|
||||
REG_DWORD,
|
||||
&DebugProcessHeapOnly,
|
||||
sizeof(ULONG),
|
||||
NULL);
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Reset DPH if requested */
|
||||
if (RtlpPageHeapEnabled && DebugProcessHeapOnly)
|
||||
{
|
||||
RtlpDphGlobalFlags &= ~0x40;
|
||||
RtlpPageHeapEnabled = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Build the NTDLL Path */
|
||||
FullPath.Buffer = FullNtDllPath;
|
||||
FullPath.Length = 0;
|
||||
FullPath.MaximumLength = sizeof(FullNtDllPath);
|
||||
RtlInitUnicodeString(&NtSystemRoot, SharedUserData->NtSystemRoot);
|
||||
RtlAppendUnicodeStringToString(&FullPath, &NtSystemRoot);
|
||||
RtlAppendUnicodeToString(&FullPath, L"\\System32\\");
|
||||
|
||||
/* Open the Known DLLs directory */
|
||||
RtlInitUnicodeString(&KnownDllString, L"\\KnownDlls");
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KnownDllString,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
NULL,
|
||||
NULL);
|
||||
Status = ZwOpenDirectoryObject(&LdrpKnownDllObjectDirectory,
|
||||
DIRECTORY_QUERY | DIRECTORY_TRAVERSE,
|
||||
&ObjectAttributes);
|
||||
|
||||
/* Check if it exists */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* It doesn't, so assume System32 */
|
||||
LdrpKnownDllObjectDirectory = NULL;
|
||||
RtlInitUnicodeString(&LdrpKnownDllPath, FullPath.Buffer);
|
||||
LdrpKnownDllPath.Length -= sizeof(WCHAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Open the Known DLLs Path */
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KnownDllString,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
LdrpKnownDllObjectDirectory,
|
||||
NULL);
|
||||
Status = NtOpenSymbolicLinkObject(&SymLinkHandle,
|
||||
SYMBOLIC_LINK_QUERY,
|
||||
&ObjectAttributes);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Query the path */
|
||||
LdrpKnownDllPath.Length = 0;
|
||||
LdrpKnownDllPath.MaximumLength = sizeof(LdrpKnownDllPathBuffer);
|
||||
LdrpKnownDllPath.Buffer = LdrpKnownDllPathBuffer;
|
||||
Status = ZwQuerySymbolicLinkObject(SymLinkHandle, &LdrpKnownDllPath, NULL);
|
||||
NtClose(SymLinkHandle);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("LDR: %s - failed call to ZwQuerySymbolicLinkObject with status %x\n", "", Status);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we have process parameters, get the default path and current path */
|
||||
if (ProcessParameters)
|
||||
{
|
||||
/* Check if we have a Dll Path */
|
||||
if (ProcessParameters->DllPath.Length)
|
||||
{
|
||||
/* Get the path */
|
||||
LdrpDefaultPath = *(PUNICODE_STRING)&ProcessParameters->DllPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We need a valid path */
|
||||
LdrpInitFailure(STATUS_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
/* Set the current directory */
|
||||
CurrentDirectory = ProcessParameters->CurrentDirectory.DosPath;
|
||||
|
||||
/* Check if it's empty or invalid */
|
||||
if ((!CurrentDirectory.Buffer) ||
|
||||
(CurrentDirectory.Buffer[0] == UNICODE_NULL) ||
|
||||
(!CurrentDirectory.Length))
|
||||
{
|
||||
/* Allocate space for the buffer */
|
||||
CurrentDirectory.Buffer = RtlAllocateHeap(Peb->ProcessHeap,
|
||||
0,
|
||||
3 * sizeof(WCHAR) +
|
||||
sizeof(UNICODE_NULL));
|
||||
|
||||
/* Copy the drive of the system root */
|
||||
RtlMoveMemory(CurrentDirectory.Buffer,
|
||||
SharedUserData->NtSystemRoot,
|
||||
3 * sizeof(WCHAR));
|
||||
CurrentDirectory.Buffer[3] = UNICODE_NULL;
|
||||
CurrentDirectory.Length = 3 * sizeof(WCHAR);
|
||||
CurrentDirectory.MaximumLength = CurrentDirectory.Length + sizeof(WCHAR);
|
||||
|
||||
FreeCurDir = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Use the local buffer */
|
||||
CurrentDirectory.Length = NtSystemRoot.Length;
|
||||
CurrentDirectory.Buffer = NtSystemRoot.Buffer;
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup Loader Data */
|
||||
Peb->Ldr = &PebLdr;
|
||||
InitializeListHead(&PebLdr.InLoadOrderModuleList);
|
||||
InitializeListHead(&PebLdr.InMemoryOrderModuleList);
|
||||
InitializeListHead(&PebLdr.InInitializationOrderModuleList);
|
||||
PebLdr.Length = sizeof(PEB_LDR_DATA);
|
||||
PebLdr.Initialized = TRUE;
|
||||
|
||||
/* Allocate a data entry for the Image */
|
||||
LdrpImageEntry = NtLdrEntry = LdrpAllocateDataTableEntry(Peb->ImageBaseAddress);
|
||||
|
||||
/* Set it up */
|
||||
NtLdrEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(NtLdrEntry->DllBase);
|
||||
NtLdrEntry->LoadCount = -1;
|
||||
NtLdrEntry->EntryPointActivationContext = 0;
|
||||
NtLdrEntry->FullDllName.Length = ImageFileName.Length;
|
||||
NtLdrEntry->FullDllName.Buffer = ImageFileName.Buffer;
|
||||
if (IsDotNetImage)
|
||||
NtLdrEntry->Flags = LDRP_COR_IMAGE;
|
||||
else
|
||||
NtLdrEntry->Flags = 0;
|
||||
|
||||
/* Check if the name is empty */
|
||||
if (!ImageFileName.Buffer[0])
|
||||
{
|
||||
/* Use the same Base name */
|
||||
NtLdrEntry->BaseDllName = NtLdrEntry->BaseDllName;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Find the last slash */
|
||||
Current = ImageFileName.Buffer;
|
||||
while (*Current)
|
||||
{
|
||||
if (*Current++ == '\\')
|
||||
{
|
||||
/* Set this path */
|
||||
NtDllName = Current;
|
||||
}
|
||||
}
|
||||
|
||||
/* Did we find anything? */
|
||||
if (!NtDllName)
|
||||
{
|
||||
/* Use the same Base name */
|
||||
NtLdrEntry->BaseDllName = NtLdrEntry->FullDllName;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Setup the name */
|
||||
NtLdrEntry->BaseDllName.Length = (USHORT)((ULONG_PTR)ImageFileName.Buffer + ImageFileName.Length - (ULONG_PTR)NtDllName);
|
||||
NtLdrEntry->BaseDllName.MaximumLength = NtLdrEntry->BaseDllName.Length + sizeof(WCHAR);
|
||||
NtLdrEntry->BaseDllName.Buffer = (PWSTR)((ULONG_PTR)ImageFileName.Buffer +
|
||||
(ImageFileName.Length - NtLdrEntry->BaseDllName.Length));
|
||||
}
|
||||
}
|
||||
|
||||
/* Processing done, insert it */
|
||||
LdrpInsertMemoryTableEntry(NtLdrEntry);
|
||||
NtLdrEntry->Flags |= LDRP_ENTRY_PROCESSED;
|
||||
|
||||
/* Now add an entry for NTDLL */
|
||||
NtLdrEntry = LdrpAllocateDataTableEntry(SystemArgument1);
|
||||
NtLdrEntry->Flags = LDRP_IMAGE_DLL;
|
||||
NtLdrEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(NtLdrEntry->DllBase);
|
||||
NtLdrEntry->LoadCount = -1;
|
||||
NtLdrEntry->EntryPointActivationContext = 0;
|
||||
//NtLdrEntry->BaseDllName.Length = NtSystemRoot.Length;
|
||||
//RtlAppendUnicodeStringToString(&NtSystemRoot, &NtDllString);
|
||||
NtLdrEntry->BaseDllName.Length = NtDllString.Length;
|
||||
NtLdrEntry->BaseDllName.MaximumLength = NtDllString.MaximumLength;
|
||||
NtLdrEntry->BaseDllName.Buffer = NtDllString.Buffer;
|
||||
|
||||
// FIXME: Full DLL name?!
|
||||
|
||||
/* Processing done, insert it */
|
||||
LdrpNtDllDataTableEntry = NtLdrEntry;
|
||||
LdrpInsertMemoryTableEntry(NtLdrEntry);
|
||||
|
||||
/* Let the world know */
|
||||
if (ShowSnaps)
|
||||
{
|
||||
DPRINT1("LDR: NEW PROCESS\n");
|
||||
DPRINT1(" Image Path: %wZ (%wZ)\n", &LdrpImageEntry->FullDllName, &LdrpImageEntry->BaseDllName);
|
||||
DPRINT1(" Current Directory: %wZ\n", &CurrentDirectory);
|
||||
DPRINT1(" Search Path: %wZ\n", &LdrpDefaultPath);
|
||||
}
|
||||
|
||||
/* Link the Init Order List */
|
||||
InsertHeadList(&Peb->Ldr->InInitializationOrderModuleList,
|
||||
&LdrpNtDllDataTableEntry->InInitializationOrderModuleList);
|
||||
|
||||
/* Set the current directory */
|
||||
Status = RtlSetCurrentDirectory_U(&CurrentDirectory);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* We failed, check if we should free it */
|
||||
if (FreeCurDir) RtlFreeUnicodeString(&CurrentDirectory);
|
||||
|
||||
/* Set it to the NT Root */
|
||||
CurrentDirectory = NtSystemRoot;
|
||||
RtlSetCurrentDirectory_U(&CurrentDirectory);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We're done with it, free it */
|
||||
if (FreeCurDir) RtlFreeUnicodeString(&CurrentDirectory);
|
||||
}
|
||||
|
||||
/* Check if we should look for a .local file */
|
||||
if (ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_LOCAL_DLL_PATH)
|
||||
{
|
||||
/* FIXME */
|
||||
DPRINT1("We don't support .local overrides yet\n");
|
||||
}
|
||||
|
||||
/* Check if the Application Verifier was enabled */
|
||||
if (Peb->NtGlobalFlag & FLG_POOL_ENABLE_TAIL_CHECK)
|
||||
{
|
||||
/* FIXME */
|
||||
DPRINT1("We don't support Application Verifier yet\n");
|
||||
}
|
||||
|
||||
if (IsDotNetImage)
|
||||
{
|
||||
/* FIXME */
|
||||
DPRINT1("We don't support .NET applications yet\n");
|
||||
}
|
||||
|
||||
/* FIXME: Load support for Terminal Services */
|
||||
if (NtHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI)
|
||||
{
|
||||
/* Load kernel32 and call BasePostImportInit... */
|
||||
DPRINT1("Unimplemented codepath!\n");
|
||||
}
|
||||
|
||||
/* Walk the IAT and load all the DLLs */
|
||||
LdrpWalkImportDescriptor(LdrpDefaultPath.Buffer, LdrpImageEntry);
|
||||
|
||||
/* Check if relocation is needed */
|
||||
if (Peb->ImageBaseAddress != (PVOID)NtHeader->OptionalHeader.ImageBase)
|
||||
{
|
||||
DPRINT("LDR: Performing relocations\n");
|
||||
Status = LdrPerformRelocations(NtHeader, Peb->ImageBaseAddress);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("LdrPerformRelocations() failed\n");
|
||||
return STATUS_INVALID_IMAGE_FORMAT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Lock the DLLs */
|
||||
ListHead = &Peb->Ldr->InLoadOrderModuleList;
|
||||
NextEntry = ListHead->Flink;
|
||||
while (ListHead != NextEntry)
|
||||
{
|
||||
NtLdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
|
||||
NtLdrEntry->LoadCount = -1;
|
||||
NextEntry = NextEntry->Flink;
|
||||
}
|
||||
|
||||
/* Phase 0 is done */
|
||||
LdrpLdrDatabaseIsSetup = TRUE;
|
||||
|
||||
/* Initialize TLS */
|
||||
Status = LdrpInitializeTls();
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("LDR: LdrpProcessInitialization failed to initialize TLS slots; status %x\n",
|
||||
Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* FIXME Mark the DLL Ranges for Stack Traces later */
|
||||
|
||||
/* Notify the debugger now */
|
||||
if (Peb->BeingDebugged)
|
||||
{
|
||||
/* Break */
|
||||
DbgBreakPoint();
|
||||
|
||||
/* Update show snaps again */
|
||||
ShowSnaps = Peb->NtGlobalFlag & FLG_SHOW_LDR_SNAPS;
|
||||
}
|
||||
|
||||
/* Validate the Image for MP Usage */
|
||||
if (LdrpNumberOfProcessors > 1) LdrpValidateImageForMp(LdrpImageEntry);
|
||||
|
||||
/* Check NX Options */
|
||||
if (SharedUserData->NXSupportPolicy == 1)
|
||||
{
|
||||
ExecuteOptions = 0xD;
|
||||
}
|
||||
else if (!SharedUserData->NXSupportPolicy)
|
||||
{
|
||||
ExecuteOptions = 0xA;
|
||||
}
|
||||
|
||||
/* Let Mm know */
|
||||
ZwSetInformationProcess(NtCurrentProcess(),
|
||||
ProcessExecuteFlags,
|
||||
&ExecuteOptions,
|
||||
sizeof(ULONG));
|
||||
|
||||
/* Check if we had Shim Data */
|
||||
if (OldShimData)
|
||||
{
|
||||
/* Load the Shim Engine */
|
||||
Peb->AppCompatInfo = NULL;
|
||||
//LdrpLoadShimEngine(OldShimData, ImagePathName, OldShimData);
|
||||
DPRINT1("We do not support shims yet\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check for Application Compatibility Goo */
|
||||
//LdrQueryApplicationCompatibilityGoo(hKey);
|
||||
DPRINT1("Querying app compat hacks is missing!\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: Check for special images, SecuROM, SafeDisc and other NX-
|
||||
* incompatible images.
|
||||
*/
|
||||
|
||||
/* Now call the Init Routines */
|
||||
Status = LdrpRunInitializeRoutines(Context);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("LDR: LdrpProcessInitialization failed running initialization routines; status %x\n",
|
||||
Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* FIXME: Unload the Shim Engine if it was loaded */
|
||||
|
||||
/* Check if we have a user-defined Post Process Routine */
|
||||
if (NT_SUCCESS(Status) && Peb->PostProcessInitRoutine)
|
||||
{
|
||||
DPRINT1("CP\n");
|
||||
/* Call it */
|
||||
Peb->PostProcessInitRoutine();
|
||||
}
|
||||
|
||||
///* Close the key if we have one opened */
|
||||
//if (hKey) NtClose(hKey);
|
||||
DbgBreakPoint();
|
||||
/* Return status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
LdrpInitFailure(NTSTATUS Status)
|
||||
|
@ -915,17 +1589,11 @@ LdrpInit(PCONTEXT Context,
|
|||
/* Let other code know we're initializing */
|
||||
LdrpInLdrInit = TRUE;
|
||||
|
||||
/* Initialize Critical Section Data */
|
||||
RtlpInitDeferedCriticalSection();
|
||||
|
||||
/* Initialize VEH Call lists */
|
||||
RtlpInitializeVectoredExceptionHandling();
|
||||
|
||||
/* Protect with SEH */
|
||||
_SEH2_TRY
|
||||
{
|
||||
/* Initialize the Process */
|
||||
LoaderStatus = LdrpInitializeProcess(Context,
|
||||
LoaderStatus = LdrpInitializeProcess_(Context,
|
||||
SystemArgument1);
|
||||
|
||||
/* Check for success and if MinimumStackCommit was requested */
|
||||
|
|
|
@ -30,6 +30,595 @@ LdrpLoadImportModule(IN PWSTR DllPath OPTIONAL,
|
|||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
LdrpSnapIAT(IN PLDR_DATA_TABLE_ENTRY ExportLdrEntry,
|
||||
IN PLDR_DATA_TABLE_ENTRY ImportLdrEntry,
|
||||
IN PIMAGE_IMPORT_DESCRIPTOR IatEntry,
|
||||
IN BOOLEAN EntriesValid)
|
||||
{
|
||||
PIMAGE_EXPORT_DIRECTORY ExportDirectory;
|
||||
ULONG ExportSize;
|
||||
PVOID Iat;
|
||||
SIZE_T ImportSize;
|
||||
ULONG IatSize;
|
||||
//PPEB Peb = NtCurrentPeb();
|
||||
NTSTATUS Status;
|
||||
PIMAGE_THUNK_DATA Thunk, OriginalThunk, FirstThunk;
|
||||
LPSTR ImportName;
|
||||
ULONG ForwarderChain;
|
||||
PIMAGE_NT_HEADERS NtHeader;
|
||||
PIMAGE_SECTION_HEADER SectionHeader;
|
||||
ULONG i, Rva;
|
||||
ULONG OldProtect;
|
||||
|
||||
/* Get export directory */
|
||||
ExportDirectory = RtlImageDirectoryEntryToData(ExportLdrEntry->DllBase,
|
||||
TRUE,
|
||||
IMAGE_DIRECTORY_ENTRY_EXPORT,
|
||||
&ExportSize);
|
||||
|
||||
/* Make sure it has one */
|
||||
if (!ExportDirectory) return STATUS_INVALID_IMAGE_FORMAT;
|
||||
|
||||
/* Get the IAT */
|
||||
Iat = RtlImageDirectoryEntryToData(ImportLdrEntry->DllBase,
|
||||
TRUE,
|
||||
IMAGE_DIRECTORY_ENTRY_IAT,
|
||||
&IatSize);
|
||||
ImportSize = IatSize;
|
||||
|
||||
/* Check if we don't have one */
|
||||
if (!Iat)
|
||||
{
|
||||
/* Get the NT Header and the first section */
|
||||
NtHeader = RtlImageNtHeader(ImportLdrEntry->DllBase);
|
||||
SectionHeader = IMAGE_FIRST_SECTION(NtHeader);
|
||||
|
||||
/* Get the RVA of the import directory */
|
||||
Rva = NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
|
||||
|
||||
/* Make sure we got one */
|
||||
if (Rva)
|
||||
{
|
||||
/* Loop all the sections */
|
||||
for (i = 0; i < NtHeader->FileHeader.NumberOfSections; i++)
|
||||
{
|
||||
/* Check if we are inside this section */
|
||||
if ((Rva >= SectionHeader->VirtualAddress) &&
|
||||
(Rva < (SectionHeader->VirtualAddress +
|
||||
SectionHeader->SizeOfRawData)))
|
||||
{
|
||||
/* We are, so set the IAT here */
|
||||
Iat = (PVOID)((ULONG_PTR)(ImportLdrEntry->DllBase) +
|
||||
SectionHeader->VirtualAddress);
|
||||
|
||||
/* Set the size */
|
||||
IatSize = SectionHeader->Misc.VirtualSize;
|
||||
|
||||
/* Deal with Watcom and other retarded compilers */
|
||||
if (!IatSize)
|
||||
{
|
||||
IatSize = SectionHeader->SizeOfRawData;
|
||||
}
|
||||
|
||||
/* Found it, get out */
|
||||
break;
|
||||
}
|
||||
|
||||
/* No match, move to the next section */
|
||||
++SectionHeader;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we still don't have an IAT, that's bad */
|
||||
if (!Iat) return STATUS_INVALID_IMAGE_FORMAT;
|
||||
|
||||
/* Set the right size */
|
||||
ImportSize = IatSize;
|
||||
}
|
||||
|
||||
/* Unprotect the IAT */
|
||||
Status = NtProtectVirtualMemory(NtCurrentProcess(),
|
||||
&Iat,
|
||||
&ImportSize,
|
||||
PAGE_READWRITE,
|
||||
&OldProtect);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* Check if the Thunks are already valid */
|
||||
if (EntriesValid)
|
||||
{
|
||||
/* We'll only do forwarders. Get the import name */
|
||||
ImportName = (LPSTR)((ULONG_PTR)ImportLdrEntry->DllBase + IatEntry->Name);
|
||||
|
||||
/* Get the list of forwaders */
|
||||
ForwarderChain = IatEntry->ForwarderChain;
|
||||
|
||||
/* Loop them */
|
||||
while (ForwarderChain != -1)
|
||||
{
|
||||
/* Get the cached thunk VA*/
|
||||
OriginalThunk = (PIMAGE_THUNK_DATA)
|
||||
((ULONG_PTR)ImportLdrEntry->DllBase +
|
||||
IatEntry->OriginalFirstThunk +
|
||||
(ForwarderChain * sizeof(IMAGE_THUNK_DATA)));
|
||||
|
||||
/* Get the first thunk */
|
||||
FirstThunk = (PIMAGE_THUNK_DATA)
|
||||
((ULONG_PTR)ImportLdrEntry->DllBase +
|
||||
IatEntry->FirstThunk +
|
||||
(ForwarderChain * sizeof(IMAGE_THUNK_DATA)));
|
||||
|
||||
/* Get the Forwarder from the thunk */
|
||||
ForwarderChain = (ULONG)FirstThunk->u1.Ordinal;
|
||||
|
||||
/* Snap the thunk */
|
||||
Status = LdrpSnapThunk(ExportLdrEntry->DllBase,
|
||||
ImportLdrEntry->DllBase,
|
||||
OriginalThunk,
|
||||
FirstThunk,
|
||||
ExportDirectory,
|
||||
ExportSize,
|
||||
TRUE,
|
||||
ImportName);
|
||||
|
||||
/* Move to the next thunk */
|
||||
FirstThunk++;
|
||||
|
||||
/* If we messed up, exit */
|
||||
if (!NT_SUCCESS(Status)) break;
|
||||
}
|
||||
}
|
||||
else if (IatEntry->FirstThunk)
|
||||
{
|
||||
/* Full snapping. Get the First thunk */
|
||||
FirstThunk = (PIMAGE_THUNK_DATA)
|
||||
((ULONG_PTR)ImportLdrEntry->DllBase +
|
||||
IatEntry->FirstThunk);
|
||||
|
||||
/* Get the NT Header */
|
||||
NtHeader = RtlImageNtHeader(ImportLdrEntry->DllBase);
|
||||
|
||||
/* Get the Original thunk VA, watch out for weird images */
|
||||
if ((IatEntry->Characteristics < NtHeader->OptionalHeader.SizeOfHeaders) ||
|
||||
(IatEntry->Characteristics >= NtHeader->OptionalHeader.SizeOfImage))
|
||||
{
|
||||
/* Reuse it, this is a strange linked file */
|
||||
OriginalThunk = FirstThunk;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get the address from the field and convert to VA */
|
||||
OriginalThunk = (PIMAGE_THUNK_DATA)
|
||||
((ULONG_PTR)ImportLdrEntry->DllBase +
|
||||
IatEntry->OriginalFirstThunk);
|
||||
}
|
||||
|
||||
/* Get the Import name VA */
|
||||
ImportName = (LPSTR)((ULONG_PTR)ImportLdrEntry->DllBase +
|
||||
IatEntry->Name);
|
||||
|
||||
/* Loop while it's valid */
|
||||
while (OriginalThunk->u1.AddressOfData)
|
||||
{
|
||||
/* Snap the Thunk */
|
||||
Status = LdrpSnapThunk(ExportLdrEntry->DllBase,
|
||||
ImportLdrEntry->DllBase,
|
||||
OriginalThunk,
|
||||
FirstThunk,
|
||||
ExportDirectory,
|
||||
ExportSize,
|
||||
TRUE,
|
||||
ImportName);
|
||||
|
||||
/* Next thunks */
|
||||
OriginalThunk++;
|
||||
Thunk++;
|
||||
|
||||
/* If we failed the snap, break out */
|
||||
if (!NT_SUCCESS(Status)) break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Protect the IAT again */
|
||||
NtProtectVirtualMemory(NtCurrentProcess(),
|
||||
&Iat,
|
||||
&ImportSize,
|
||||
OldProtect,
|
||||
&OldProtect);
|
||||
|
||||
/* Also flush out the cache */
|
||||
NtFlushInstructionCache(NtCurrentProcess(), Iat, IatSize);
|
||||
|
||||
/* Return to Caller */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
|
||||
IN PLDR_DATA_TABLE_ENTRY LdrEntry,
|
||||
IN PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundEntry,
|
||||
IN PIMAGE_BOUND_IMPORT_DESCRIPTOR FirstEntry)
|
||||
{
|
||||
LPSTR ImportName = NULL, BoundImportName, ForwarderName;
|
||||
NTSTATUS Status;
|
||||
BOOLEAN AlreadyLoaded = FALSE, Stale;
|
||||
PIMAGE_IMPORT_DESCRIPTOR ImportEntry;
|
||||
PLDR_DATA_TABLE_ENTRY DllLdrEntry, ForwarderLdrEntry;
|
||||
PIMAGE_BOUND_FORWARDER_REF ForwarderEntry;
|
||||
PPEB Peb = NtCurrentPeb();
|
||||
ULONG i, IatSize;
|
||||
|
||||
/* Get the name's VA */
|
||||
BoundImportName = (LPSTR)(BoundEntry + BoundEntry->OffsetModuleName);
|
||||
|
||||
/* Show debug mesage */
|
||||
if (ShowSnaps)
|
||||
{
|
||||
DPRINT1("LDR: %wZ bound to %s\n", &LdrEntry->BaseDllName, BoundImportName);
|
||||
}
|
||||
|
||||
/* Load the module for this entry */
|
||||
Status = LdrpLoadImportModule(DllPath,
|
||||
BoundImportName,
|
||||
LdrEntry->DllBase,
|
||||
&DllLdrEntry,
|
||||
&AlreadyLoaded);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Show debug message */
|
||||
if (ShowSnaps)
|
||||
{
|
||||
DPRINT1("LDR: %wZ failed to load import module %s; status = %x\n",
|
||||
&LdrEntry->BaseDllName,
|
||||
BoundImportName,
|
||||
Status);
|
||||
}
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* Check if it wasn't already loaded */
|
||||
if (!AlreadyLoaded)
|
||||
{
|
||||
/* Add it to our list */
|
||||
InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
|
||||
&DllLdrEntry->InInitializationOrderModuleList);
|
||||
}
|
||||
|
||||
/* Check if the Bound Entry is now invalid */
|
||||
if ((BoundEntry->TimeDateStamp != DllLdrEntry->TimeDateStamp) ||
|
||||
(DllLdrEntry->Flags & LDRP_IMAGE_NOT_AT_BASE))
|
||||
{
|
||||
/* Show debug message */
|
||||
if (ShowSnaps)
|
||||
{
|
||||
DPRINT1("LDR: %wZ has stale binding to %s\n",
|
||||
&DllLdrEntry->BaseDllName,
|
||||
BoundImportName);
|
||||
}
|
||||
|
||||
/* Remember it's become stale */
|
||||
Stale = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Show debug message */
|
||||
if (ShowSnaps)
|
||||
{
|
||||
DPRINT1("LDR: %wZ has correct binding to %s\n",
|
||||
&DllLdrEntry->BaseDllName,
|
||||
BoundImportName);
|
||||
}
|
||||
|
||||
/* Remember it's valid */
|
||||
Stale = FALSE;
|
||||
}
|
||||
|
||||
/* Get the forwarders */
|
||||
ForwarderEntry = (PIMAGE_BOUND_FORWARDER_REF)(BoundEntry + 1);
|
||||
|
||||
/* Loop them */
|
||||
for (i = 0; i < BoundEntry->NumberOfModuleForwarderRefs; i++)
|
||||
{
|
||||
/* Get the name */
|
||||
ForwarderName = (LPSTR)(FirstEntry + ForwarderEntry->OffsetModuleName);
|
||||
|
||||
/* Show debug message */
|
||||
if (ShowSnaps)
|
||||
{
|
||||
DPRINT1("LDR: %wZ bound to %s via forwarder(s) from %wZ\n",
|
||||
&LdrEntry->BaseDllName,
|
||||
ForwarderName,
|
||||
&DllLdrEntry->BaseDllName);
|
||||
}
|
||||
|
||||
/* Load the module */
|
||||
Status = LdrpLoadImportModule(DllPath,
|
||||
ForwarderName,
|
||||
LdrEntry->DllBase,
|
||||
&ForwarderLdrEntry,
|
||||
&AlreadyLoaded);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Loaded it, was it already loaded? */
|
||||
if (!AlreadyLoaded)
|
||||
{
|
||||
/* Add it to our list */
|
||||
InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
|
||||
&ForwarderLdrEntry->InInitializationOrderModuleList);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if the Bound Entry is now invalid */
|
||||
if (!(NT_SUCCESS(Status)) ||
|
||||
(ForwarderEntry->TimeDateStamp != ForwarderLdrEntry->TimeDateStamp) ||
|
||||
(ForwarderLdrEntry->Flags & LDRP_IMAGE_NOT_AT_BASE))
|
||||
{
|
||||
/* Show debug message */
|
||||
if (ShowSnaps)
|
||||
{
|
||||
DPRINT1("LDR: %wZ has stale binding to %s\n",
|
||||
&ForwarderLdrEntry->BaseDllName,
|
||||
ForwarderName);
|
||||
}
|
||||
|
||||
/* Remember it's become stale */
|
||||
Stale = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Show debug message */
|
||||
if (ShowSnaps)
|
||||
{
|
||||
DPRINT1("LDR: %wZ has correct binding to %s\n",
|
||||
&ForwarderLdrEntry->BaseDllName,
|
||||
ForwarderName);
|
||||
}
|
||||
|
||||
/* Remember it's valid */
|
||||
Stale = FALSE;
|
||||
}
|
||||
|
||||
/* Move to the next one */
|
||||
ForwarderEntry++;
|
||||
}
|
||||
|
||||
/* Set the next bound entry to the forwarder */
|
||||
FirstEntry = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)ForwarderEntry;
|
||||
|
||||
/* Check if the binding was stale */
|
||||
if (Stale)
|
||||
{
|
||||
/* It was, so find the IAT entry for it */
|
||||
ImportEntry = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
|
||||
TRUE,
|
||||
IMAGE_DIRECTORY_ENTRY_IMPORT,
|
||||
&IatSize);
|
||||
|
||||
/* Make sure it has a name */
|
||||
while (ImportEntry->Name)
|
||||
{
|
||||
/* Get the name */
|
||||
ImportName = (LPSTR)((ULONG_PTR)LdrEntry->DllBase + ImportEntry->Name);
|
||||
|
||||
/* Compare it */
|
||||
if (!_stricmp(ImportName, BoundImportName)) break;
|
||||
|
||||
/* Move to next entry */
|
||||
ImportEntry += 1;
|
||||
}
|
||||
|
||||
/* If we didn't find a name, fail */
|
||||
if (!ImportEntry->Name)
|
||||
{
|
||||
/* Show debug message */
|
||||
if (ShowSnaps)
|
||||
{
|
||||
DPRINT1("LDR: LdrpWalkImportTable - failing with"
|
||||
"STATUS_OBJECT_NAME_INVALID due to no import descriptor name\n");
|
||||
}
|
||||
|
||||
/* Return error */
|
||||
Status = STATUS_OBJECT_NAME_INVALID;
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* Show debug message */
|
||||
if (ShowSnaps)
|
||||
{
|
||||
DPRINT1("LDR: Stale Bind %s from %wZ\n",
|
||||
ImportName,
|
||||
&LdrEntry->BaseDllName);
|
||||
}
|
||||
|
||||
/* Snap the IAT Entry*/
|
||||
Status = LdrpSnapIAT(DllLdrEntry,
|
||||
LdrEntry,
|
||||
ImportEntry,
|
||||
FALSE);
|
||||
|
||||
/* Make sure we didn't fail */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Show debug message */
|
||||
if (ShowSnaps)
|
||||
{
|
||||
DPRINT1("LDR: %wZ failed to load import module %s; status = %x\n",
|
||||
&LdrEntry->BaseDllName,
|
||||
BoundImportName,
|
||||
Status);
|
||||
}
|
||||
|
||||
/* Return */
|
||||
goto Quickie;
|
||||
}
|
||||
}
|
||||
|
||||
/* All done */
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
Quickie:
|
||||
/* Write where we are now and return */
|
||||
*BoundEntry = *FirstEntry;
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
LdrpHandleNewFormatImportDescriptors(IN LPWSTR DllPath OPTIONAL,
|
||||
IN PLDR_DATA_TABLE_ENTRY LdrEntry,
|
||||
IN PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundEntry)
|
||||
{
|
||||
PIMAGE_BOUND_IMPORT_DESCRIPTOR FirstEntry = BoundEntry;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Make sure we have a name */
|
||||
while (BoundEntry->OffsetModuleName)
|
||||
{
|
||||
/* Parse this descriptor */
|
||||
Status = LdrpHandleOneNewFormatImportDescriptor(DllPath,
|
||||
LdrEntry,
|
||||
BoundEntry,
|
||||
FirstEntry);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
}
|
||||
|
||||
/* Done */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
LdrpHandleOneOldFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
|
||||
IN PLDR_DATA_TABLE_ENTRY LdrEntry,
|
||||
IN PIMAGE_IMPORT_DESCRIPTOR ImportEntry)
|
||||
{
|
||||
//ULONG IatSize, i;
|
||||
LPSTR ImportName;
|
||||
NTSTATUS Status;
|
||||
BOOLEAN AlreadyLoaded = FALSE, StaticEntriesValid = FALSE, SkipSnap = TRUE;
|
||||
PLDR_DATA_TABLE_ENTRY DllLdrEntry;
|
||||
PIMAGE_THUNK_DATA FirstThunk;
|
||||
PPEB Peb = NtCurrentPeb();
|
||||
|
||||
/* Get the import name's VA */
|
||||
ImportName = (LPSTR)((ULONG_PTR)LdrEntry->DllBase + ImportEntry->Name);
|
||||
|
||||
/* Get the first thunk */
|
||||
FirstThunk = (PIMAGE_THUNK_DATA)((ULONG_PTR)LdrEntry->DllBase +
|
||||
ImportEntry->FirstThunk);
|
||||
|
||||
/* Make sure it's valid */
|
||||
if (!FirstThunk->u1.Function) goto SkipEntry;
|
||||
|
||||
/* Show debug message */
|
||||
if (ShowSnaps)
|
||||
{
|
||||
DPRINT1("LDR: %s used by %wZ\n",
|
||||
ImportName,
|
||||
&LdrEntry->BaseDllName);
|
||||
}
|
||||
|
||||
/* Load the module associated to it */
|
||||
Status = LdrpLoadImportModule(DllPath,
|
||||
ImportName,
|
||||
LdrEntry->DllBase,
|
||||
&DllLdrEntry,
|
||||
&AlreadyLoaded);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* Show debug message */
|
||||
if (ShowSnaps)
|
||||
{
|
||||
DPRINT1("LDR: Snapping imports for %wZ from %s\n",
|
||||
&LdrEntry->BaseDllName,
|
||||
ImportName);
|
||||
}
|
||||
|
||||
/* Check if the image was bound when compiled */
|
||||
if (ImportEntry->OriginalFirstThunk)
|
||||
{
|
||||
/* It was, so check if the static IAT entries are still valid */
|
||||
if ((ImportEntry->TimeDateStamp) &&
|
||||
(ImportEntry->TimeDateStamp == DllLdrEntry->TimeDateStamp) &&
|
||||
(!(DllLdrEntry->Flags & LDRP_IMAGE_NOT_AT_BASE)))
|
||||
{
|
||||
/* Show debug message */
|
||||
if (ShowSnaps)
|
||||
{
|
||||
DPRINT1("LDR: Snap bypass %s from %wZ\n",
|
||||
ImportName,
|
||||
&LdrEntry->BaseDllName);
|
||||
}
|
||||
|
||||
/*
|
||||
* They are still valid, so we can skip snapping them.
|
||||
* Additionally, if we have no forwarders, we are totally
|
||||
* done.
|
||||
*/
|
||||
if (ImportEntry->ForwarderChain == -1)
|
||||
{
|
||||
/* Totally skip LdrpSnapIAT */
|
||||
SkipSnap = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set this so LdrpSnapIAT will only do forwarders */
|
||||
StaticEntriesValid = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if it wasn't already loaded */
|
||||
if (!AlreadyLoaded)
|
||||
{
|
||||
/* Add the DLL to our list */
|
||||
InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
|
||||
&DllLdrEntry->InInitializationOrderModuleList);
|
||||
}
|
||||
|
||||
/* Check if we should snap at all */
|
||||
if (!SkipSnap)
|
||||
{
|
||||
/* Now snap the IAT Entry */
|
||||
Status = LdrpSnapIAT(DllLdrEntry,
|
||||
LdrEntry,
|
||||
ImportEntry,
|
||||
StaticEntriesValid);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
}
|
||||
|
||||
SkipEntry:
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
LdrpHandleOldFormatImportDescriptors(IN LPWSTR DllPath OPTIONAL,
|
||||
IN PLDR_DATA_TABLE_ENTRY LdrEntry,
|
||||
IN PIMAGE_IMPORT_DESCRIPTOR ImportEntry)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Check for Name and Thunk */
|
||||
while (ImportEntry->Name && ImportEntry->FirstThunk)
|
||||
{
|
||||
/* Parse this descriptor */
|
||||
Status = LdrpHandleOneOldFormatImportDescriptor(DllPath,
|
||||
LdrEntry,
|
||||
ImportEntry);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* Move to the next entry */
|
||||
ImportEntry++;
|
||||
}
|
||||
|
||||
/* Done */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
USHORT NTAPI
|
||||
LdrpNameToOrdinal(LPSTR ImportName,
|
||||
ULONG NumberOfNames,
|
||||
|
@ -41,6 +630,169 @@ LdrpNameToOrdinal(LPSTR ImportName,
|
|||
return 0;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
LdrpWalkImportDescriptor(IN LPWSTR DllPath OPTIONAL,
|
||||
IN PLDR_DATA_TABLE_ENTRY LdrEntry)
|
||||
{
|
||||
RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx;
|
||||
PPEB Peb = NtCurrentPeb();
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundEntry = NULL;
|
||||
PIMAGE_IMPORT_DESCRIPTOR ImportEntry;
|
||||
ULONG BoundSize, IatSize;
|
||||
DPRINT1("LdrpWalkImportDescriptor('%S' %x)\n", DllPath, LdrEntry);
|
||||
/* Set up the Act Ctx */
|
||||
ActCtx.Size = sizeof(ActCtx);
|
||||
ActCtx.Frame.Flags = ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID;
|
||||
RtlZeroMemory(&ActCtx, sizeof(ActCtx));
|
||||
|
||||
/* Check if we have a manifest prober routine */
|
||||
if (LdrpManifestProberRoutine)
|
||||
{
|
||||
DPRINT1("We don't support manifests yet, much less prober routines\n");
|
||||
}
|
||||
|
||||
/* Check if we failed above */
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* Get the Active ActCtx */
|
||||
Status = RtlGetActiveActivationContext(&LdrEntry->EntryPointActivationContext);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* Activate the ActCtx */
|
||||
RtlActivateActivationContextUnsafeFast(&ActCtx,
|
||||
LdrEntry->EntryPointActivationContext);
|
||||
|
||||
/* Check if we were directed */
|
||||
if (!(LdrEntry->Flags & LDRP_REDIRECTED))
|
||||
{
|
||||
/* Get the Bound IAT */
|
||||
BoundEntry = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
|
||||
TRUE,
|
||||
IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT,
|
||||
&BoundSize);
|
||||
}
|
||||
|
||||
/* Get the regular IAT, for fallback */
|
||||
ImportEntry = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
|
||||
TRUE,
|
||||
IMAGE_DIRECTORY_ENTRY_IMPORT,
|
||||
&IatSize);
|
||||
|
||||
/* Check if we got at least one */
|
||||
if (BoundEntry || ImportEntry)
|
||||
{
|
||||
/* Do we have a Bound IAT */
|
||||
if (BoundEntry)
|
||||
{
|
||||
/* Handle the descriptor */
|
||||
Status = LdrpHandleNewFormatImportDescriptors(DllPath,
|
||||
LdrEntry,
|
||||
BoundEntry);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Handle the descriptor */
|
||||
Status = LdrpHandleOldFormatImportDescriptors(DllPath,
|
||||
LdrEntry,
|
||||
ImportEntry);
|
||||
}
|
||||
|
||||
/* Check the status of the handlers */
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Check for Per-DLL Heap Tagging */
|
||||
if (Peb->NtGlobalFlag & FLG_HEAP_ENABLE_TAG_BY_DLL)
|
||||
{
|
||||
/* FIXME */
|
||||
DPRINT1("We don't support Per-DLL Heap Tagging yet!\n");
|
||||
}
|
||||
|
||||
/* Check if Page Heap was enabled */
|
||||
if (Peb->NtGlobalFlag & FLG_HEAP_PAGE_ALLOCS)
|
||||
{
|
||||
/* FIXME */
|
||||
DPRINT1("We don't support Page Heaps yet!\n");
|
||||
}
|
||||
|
||||
/* Check if Application Verifier was enabled */
|
||||
if (Peb->NtGlobalFlag & FLG_HEAP_ENABLE_TAIL_CHECK)
|
||||
{
|
||||
/* FIXME */
|
||||
DPRINT1("We don't support Application Verifier yet!\n");
|
||||
}
|
||||
|
||||
/* Just to be safe */
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* Release the activation context */
|
||||
RtlDeactivateActivationContextUnsafeFast(&ActCtx);
|
||||
|
||||
/* Return status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
LdrpLoadImportModule(IN PWSTR DllPath OPTIONAL,
|
||||
IN LPSTR ImportName,
|
||||
IN PVOID DllBase,
|
||||
OUT PLDR_DATA_TABLE_ENTRY *DataTableEntry,
|
||||
OUT PBOOLEAN Existing)
|
||||
{
|
||||
ANSI_STRING AnsiString;
|
||||
PUNICODE_STRING ImpDescName;
|
||||
NTSTATUS Status;
|
||||
PPEB Peb = RtlGetCurrentPeb();
|
||||
PTEB Teb = NtCurrentTeb();
|
||||
DPRINT1("LdrpLoadImportModule('%S' '%s' %p %p %p)\n", DllPath, ImportName, DllBase, DataTableEntry, Existing);
|
||||
/* Convert import descriptor name to unicode string */
|
||||
ImpDescName = &Teb->StaticUnicodeString;
|
||||
RtlInitAnsiString(&AnsiString, ImportName);
|
||||
Status = RtlAnsiStringToUnicodeString(ImpDescName, &AnsiString, FALSE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* Check if it's loaded */
|
||||
if (LdrpCheckForLoadedDll(DllPath,
|
||||
ImpDescName,
|
||||
TRUE,
|
||||
FALSE,
|
||||
DataTableEntry))
|
||||
{
|
||||
/* It's already existing in the list */
|
||||
*Existing = TRUE;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* We're loading it for the first time */
|
||||
*Existing = FALSE;
|
||||
|
||||
/* Map it */
|
||||
Status = LdrpMapDll(DllPath,
|
||||
ImpDescName->Buffer,
|
||||
NULL,
|
||||
NULL,
|
||||
TRUE,
|
||||
FALSE,
|
||||
DataTableEntry);
|
||||
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* Walk its import descriptor table */
|
||||
Status = LdrpWalkImportDescriptor(DllPath,
|
||||
*DataTableEntry);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Add it to the in-init-order list in case of failure */
|
||||
InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
|
||||
&(*DataTableEntry)->InInitializationOrderModuleList);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
/* GLOBALS *******************************************************************/
|
||||
|
||||
PLDR_DATA_TABLE_ENTRY LdrpLoadedDllHandleCache;
|
||||
LIST_ENTRY LdrpHashTable[LDR_HASH_TABLE_ENTRIES];
|
||||
|
||||
#define LDR_GET_HASH_ENTRY(x) (RtlUpcaseUnicodeChar((x)) & (LDR_HASH_TABLE_ENTRIES - 1))
|
||||
|
||||
|
@ -217,7 +216,261 @@ LdrpCheckForLoadedDll(IN PWSTR DllPath,
|
|||
IN BOOLEAN RedirectedDll,
|
||||
OUT PLDR_DATA_TABLE_ENTRY *LdrEntry)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
ULONG HashIndex;
|
||||
PLIST_ENTRY ListHead, ListEntry;
|
||||
PLDR_DATA_TABLE_ENTRY CurEntry;
|
||||
BOOLEAN FullPath = FALSE;
|
||||
PWCHAR wc;
|
||||
WCHAR NameBuf[266];
|
||||
UNICODE_STRING FullDllName, NtPathName;
|
||||
ULONG Length;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
NTSTATUS Status;
|
||||
HANDLE FileHandle, SectionHandle;
|
||||
IO_STATUS_BLOCK Iosb;
|
||||
PVOID ViewBase = NULL;
|
||||
SIZE_T ViewSize = 0;
|
||||
PIMAGE_NT_HEADERS NtHeader, NtHeader2;
|
||||
DPRINT1("LdrpCheckForLoadedDll('%S' '%wZ' %d %d %p)\n", DllPath, DllName, Flag, RedirectedDll, LdrEntry);
|
||||
/* Check if a dll name was provided */
|
||||
if (!DllName->Buffer || !DllName->Buffer[0]) return FALSE;
|
||||
|
||||
/* Look in the hash table if flag was set */
|
||||
lookinhash:
|
||||
if (Flag)
|
||||
{
|
||||
/* Get hash index */
|
||||
HashIndex = LDR_GET_HASH_ENTRY(DllName->Buffer[0]);
|
||||
|
||||
/* Traverse that list */
|
||||
ListHead = &LdrpHashTable[HashIndex];
|
||||
ListEntry = ListHead->Flink;
|
||||
while (ListEntry != ListHead)
|
||||
{
|
||||
/* Get the current entry */
|
||||
CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, HashLinks);
|
||||
|
||||
/* Check base name of that module */
|
||||
if (RtlEqualUnicodeString(DllName, &CurEntry->BaseDllName, TRUE))
|
||||
{
|
||||
/* It matches, return it */
|
||||
*LdrEntry = CurEntry;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Advance to the next entry */
|
||||
ListEntry = ListEntry->Flink;
|
||||
}
|
||||
|
||||
/* Module was not found, return failure */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Check if there is a full path in this DLL */
|
||||
wc = DllName->Buffer;
|
||||
while (*wc)
|
||||
{
|
||||
/* Check for a slash in the current position*/
|
||||
if (*wc == L'\\' || *wc == L'/')
|
||||
{
|
||||
/* Found the slash, so dll name contains path */
|
||||
FullPath = TRUE;
|
||||
|
||||
/* Setup full dll name string */
|
||||
FullDllName.Buffer = NameBuf;
|
||||
|
||||
Length = RtlDosSearchPath_U(DllPath ? DllPath : LdrpDefaultPath.Buffer,
|
||||
DllName->Buffer,
|
||||
NULL,
|
||||
sizeof(NameBuf) - sizeof(UNICODE_NULL),
|
||||
FullDllName.Buffer,
|
||||
NULL);
|
||||
|
||||
/* Check if that was successful */
|
||||
if (!Length || Length > sizeof(NameBuf) - sizeof(UNICODE_NULL))
|
||||
{
|
||||
if (ShowSnaps)
|
||||
{
|
||||
DPRINT1("LDR: LdrpCheckForLoadedDll - Unable To Locate %ws: 0x%08x\n",
|
||||
DllName->Buffer, Length);
|
||||
}
|
||||
|
||||
/* Return failure */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Full dll name is found */
|
||||
FullDllName.Length = Length;
|
||||
FullDllName.MaximumLength = FullDllName.Length + sizeof(UNICODE_NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
wc++;
|
||||
}
|
||||
|
||||
/* Go check the hash table */
|
||||
if (!FullPath)
|
||||
{
|
||||
Flag = TRUE;
|
||||
goto lookinhash;
|
||||
}
|
||||
|
||||
/* Now go through the InLoadOrder module list */
|
||||
ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
|
||||
ListEntry = ListHead->Flink;
|
||||
|
||||
while (ListEntry != ListHead)
|
||||
{
|
||||
/* Get the containing record of the current entry and advance to the next one */
|
||||
CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
|
||||
ListEntry = ListEntry->Flink;
|
||||
|
||||
/* Check if it's already being unloaded */
|
||||
if (!CurEntry->InMemoryOrderModuleList.Flink) continue;
|
||||
|
||||
/* Check if name matches */
|
||||
if (RtlEqualUnicodeString(&FullDllName,
|
||||
&CurEntry->FullDllName,
|
||||
TRUE))
|
||||
{
|
||||
/* Found it */
|
||||
*LdrEntry = CurEntry;
|
||||
|
||||
/* Find activation context */
|
||||
Status = RtlFindActivationContextSectionString(0, NULL, ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, DllName, NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return FALSE;
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* The DLL was not found in the load order modules list. Perform a complex check */
|
||||
|
||||
/* Convert given path to NT path */
|
||||
if (!RtlDosPathNameToNtPathName_U(FullDllName.Buffer,
|
||||
&NtPathName,
|
||||
NULL,
|
||||
NULL))
|
||||
{
|
||||
/* Fail if conversion failed */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Initialize object attributes and open it */
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&NtPathName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
Status = NtOpenFile(&FileHandle,
|
||||
SYNCHRONIZE | FILE_EXECUTE,
|
||||
&ObjectAttributes,
|
||||
&Iosb,
|
||||
FILE_SHARE_READ | FILE_SHARE_DELETE,
|
||||
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
|
||||
|
||||
/* Free NT path name */
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathName.Buffer);
|
||||
|
||||
/* If opening the file failed - return failure */
|
||||
if (!NT_SUCCESS(Status)) return FALSE;
|
||||
|
||||
/* Create a section for this file */
|
||||
Status = NtCreateSection(&SectionHandle,
|
||||
SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_MAP_WRITE,
|
||||
NULL,
|
||||
NULL,
|
||||
PAGE_EXECUTE,
|
||||
SEC_COMMIT,
|
||||
FileHandle);
|
||||
|
||||
/* Close file handle */
|
||||
NtClose(FileHandle);
|
||||
|
||||
/* If creating section failed - return failure */
|
||||
if (!NT_SUCCESS(Status)) return FALSE;
|
||||
|
||||
/* Map view of this section */
|
||||
Status = ZwMapViewOfSection(SectionHandle,
|
||||
NtCurrentProcess(),
|
||||
&ViewBase,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
&ViewSize,
|
||||
ViewShare,
|
||||
0,
|
||||
PAGE_EXECUTE);
|
||||
/* Close section handle */
|
||||
NtClose(SectionHandle);
|
||||
|
||||
/* If section mapping failed - return failure */
|
||||
if (!NT_SUCCESS(Status)) return FALSE;
|
||||
|
||||
/* Get pointer to the NT header of this section */
|
||||
NtHeader = RtlImageNtHeader(ViewBase);
|
||||
if (!NtHeader)
|
||||
{
|
||||
/* Unmap the section and fail */
|
||||
NtUnmapViewOfSection(NtCurrentProcess(), ViewBase);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Go through the list of modules */
|
||||
ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
|
||||
ListEntry = ListHead->Flink;
|
||||
|
||||
while (ListEntry != ListHead)
|
||||
{
|
||||
CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
|
||||
ListEntry = ListEntry->Flink;
|
||||
|
||||
/* Check if it's already being unloaded */
|
||||
if (!CurEntry->InMemoryOrderModuleList.Flink) continue;
|
||||
|
||||
_SEH2_TRY
|
||||
{
|
||||
/* Check if timedate stamp and sizes match */
|
||||
if (CurEntry->TimeDateStamp == NtHeader->FileHeader.TimeDateStamp &&
|
||||
CurEntry->SizeOfImage == NtHeader->OptionalHeader.SizeOfImage)
|
||||
{
|
||||
/* Time, date and size match. Let's compare their headers */
|
||||
NtHeader2 = RtlImageNtHeader(CurEntry->DllBase);
|
||||
|
||||
if (RtlCompareMemory(NtHeader2, NtHeader, sizeof(IMAGE_NT_HEADERS)))
|
||||
{
|
||||
/* Headers match too! Finally ask the kernel to compare mapped files */
|
||||
Status = ZwAreMappedFilesTheSame(CurEntry->DllBase, ViewBase);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
_SEH2_YIELD(continue;)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is our entry! */
|
||||
*LdrEntry = CurEntry;
|
||||
|
||||
/* Unmap the section */
|
||||
NtUnmapViewOfSection(NtCurrentProcess(), ViewBase);
|
||||
|
||||
_SEH2_YIELD(return TRUE;)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
_SEH2_YIELD(break;)
|
||||
}
|
||||
_SEH2_END;
|
||||
}
|
||||
|
||||
/* Unmap the section */
|
||||
NtUnmapViewOfSection(NtCurrentProcess(), ViewBase);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,13 +17,15 @@
|
|||
VOID RtlInitializeHeapManager(VOID);
|
||||
VOID LdrpInitLoader(VOID);
|
||||
extern PTEB LdrpTopLevelDllBeingLoadedTeb;
|
||||
VOID NTAPI RtlpInitDeferedCriticalSection(VOID);
|
||||
VOID RtlpInitializeVectoredExceptionHandling(VOID);
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
extern PLDR_DATA_TABLE_ENTRY LdrpImageEntry;
|
||||
static RTL_CRITICAL_SECTION PebLock;
|
||||
static RTL_BITMAP TlsBitMap;
|
||||
static RTL_BITMAP TlsExpansionBitMap;
|
||||
extern RTL_CRITICAL_SECTION FastPebLock;
|
||||
extern RTL_BITMAP TlsBitMap;
|
||||
extern RTL_BITMAP TlsExpansionBitMap;
|
||||
|
||||
#define VALUE_BUFFER_SIZE 256
|
||||
|
||||
|
@ -309,7 +311,7 @@ finish:
|
|||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
LdrpInitializeProcess(PCONTEXT Context,
|
||||
LdrpInitializeProcess_(PCONTEXT Context,
|
||||
PVOID SystemArgument1)
|
||||
{
|
||||
PIMAGE_NT_HEADERS NTHeaders;
|
||||
|
@ -372,6 +374,9 @@ LdrpInitializeProcess(PCONTEXT Context,
|
|||
|
||||
Peb->NumberOfProcessors = SystemInformation.NumberOfProcessors;
|
||||
|
||||
/* Initialize Critical Section Data */
|
||||
RtlpInitDeferedCriticalSection();
|
||||
|
||||
/* Load execution options */
|
||||
LoadImageFileExecutionOptions(Peb);
|
||||
|
||||
|
@ -430,9 +435,12 @@ LdrpInitializeProcess(PCONTEXT Context,
|
|||
ZwTerminateProcess(NtCurrentProcess(), STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE);
|
||||
}
|
||||
|
||||
/* initialized vectored exception handling */
|
||||
RtlpInitializeVectoredExceptionHandling();
|
||||
|
||||
/* initalize peb lock support */
|
||||
RtlInitializeCriticalSection(&PebLock);
|
||||
Peb->FastPebLock = &PebLock;
|
||||
RtlInitializeCriticalSection(&FastPebLock);
|
||||
Peb->FastPebLock = &FastPebLock;
|
||||
|
||||
/* initialize tls bitmaps */
|
||||
RtlInitializeBitMap(&TlsBitMap, Peb->TlsBitmapBits, TLS_MINIMUM_AVAILABLE);
|
||||
|
|
|
@ -32,8 +32,8 @@
|
|||
#endif
|
||||
|
||||
static BOOLEAN LdrpDllShutdownInProgress = FALSE;
|
||||
static HANDLE LdrpKnownDllsDirHandle = NULL;
|
||||
static UNICODE_STRING LdrpKnownDllPath = {0, 0, NULL};
|
||||
extern HANDLE LdrpKnownDllObjectDirectory;
|
||||
extern UNICODE_STRING LdrpKnownDllPath;
|
||||
static PLDR_DATA_TABLE_ENTRY LdrpLastModule = NULL;
|
||||
extern PLDR_DATA_TABLE_ENTRY LdrpImageEntry;
|
||||
|
||||
|
@ -231,13 +231,13 @@ LdrpInitLoader(VOID)
|
|||
OBJ_CASE_INSENSITIVE,
|
||||
NULL,
|
||||
NULL);
|
||||
Status = NtOpenDirectoryObject(&LdrpKnownDllsDirHandle,
|
||||
Status = NtOpenDirectoryObject(&LdrpKnownDllObjectDirectory,
|
||||
DIRECTORY_QUERY | DIRECTORY_TRAVERSE,
|
||||
&ObjectAttributes);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("NtOpenDirectoryObject() failed (Status %lx)\n", Status);
|
||||
LdrpKnownDllsDirHandle = NULL;
|
||||
LdrpKnownDllObjectDirectory = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -249,8 +249,8 @@ LdrpInitLoader(VOID)
|
|||
MAX_PATH * sizeof(WCHAR));
|
||||
if (LinkTarget.Buffer == NULL)
|
||||
{
|
||||
NtClose(LdrpKnownDllsDirHandle);
|
||||
LdrpKnownDllsDirHandle = NULL;
|
||||
NtClose(LdrpKnownDllObjectDirectory);
|
||||
LdrpKnownDllObjectDirectory = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -259,7 +259,7 @@ LdrpInitLoader(VOID)
|
|||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&Name,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
LdrpKnownDllsDirHandle,
|
||||
LdrpKnownDllObjectDirectory,
|
||||
NULL);
|
||||
Status = NtOpenSymbolicLinkObject(&LinkHandle,
|
||||
SYMBOLIC_LINK_ALL_ACCESS,
|
||||
|
@ -267,8 +267,8 @@ LdrpInitLoader(VOID)
|
|||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
RtlFreeUnicodeString(&LinkTarget);
|
||||
NtClose(LdrpKnownDllsDirHandle);
|
||||
LdrpKnownDllsDirHandle = NULL;
|
||||
NtClose(LdrpKnownDllObjectDirectory);
|
||||
LdrpKnownDllObjectDirectory = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -279,8 +279,8 @@ LdrpInitLoader(VOID)
|
|||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
RtlFreeUnicodeString(&LinkTarget);
|
||||
NtClose(LdrpKnownDllsDirHandle);
|
||||
LdrpKnownDllsDirHandle = NULL;
|
||||
NtClose(LdrpKnownDllObjectDirectory);
|
||||
LdrpKnownDllObjectDirectory = NULL;
|
||||
}
|
||||
|
||||
RtlCreateUnicodeString(&LdrpKnownDllPath,
|
||||
|
@ -431,7 +431,7 @@ LdrpMapKnownDll(IN PUNICODE_STRING DllName,
|
|||
|
||||
DPRINT("LdrpMapKnownDll() called\n");
|
||||
|
||||
if (LdrpKnownDllsDirHandle == NULL)
|
||||
if (LdrpKnownDllObjectDirectory == NULL)
|
||||
{
|
||||
DPRINT("Invalid 'KnownDlls' directory\n");
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
|
@ -442,7 +442,7 @@ LdrpMapKnownDll(IN PUNICODE_STRING DllName,
|
|||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
DllName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
LdrpKnownDllsDirHandle,
|
||||
LdrpKnownDllObjectDirectory,
|
||||
NULL);
|
||||
Status = NtOpenSection(SectionHandle,
|
||||
SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE,
|
||||
|
@ -1189,7 +1189,7 @@ LdrGetExportByName(PVOID BaseAddress,
|
|||
* NOTE
|
||||
*
|
||||
*/
|
||||
static NTSTATUS
|
||||
NTSTATUS
|
||||
LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders,
|
||||
PVOID ImageBase)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue