- 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:
Aleksey Bragin 2011-03-22 12:41:52 +00:00
parent 4a05e4ef29
commit 64e9e4c196
6 changed files with 1719 additions and 37 deletions

View file

@ -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);

View file

@ -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 */

View file

@ -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

View file

@ -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;
}

View file

@ -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);

View file

@ -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)
{