- Implemented fast loading of bounded images.

- Implemented handling of tls sections.
- Fixed referencing of loaded dlls.

svn path=/trunk/; revision=7498
This commit is contained in:
Hartmut Birr 2004-01-07 10:09:03 +00:00
parent d3fbd8e582
commit 446ec6d27b
4 changed files with 1533 additions and 743 deletions

View file

@ -13,6 +13,15 @@ typedef BOOL STDCALL_FUNC
ULONG ul_reason_for_call, ULONG ul_reason_for_call,
LPVOID lpReserved); LPVOID lpReserved);
/* Module flags */
#define IMAGE_DLL 0x00000004
#define LOAD_IN_PROGRESS 0x00001000
#define UNLOAD_IN_PROGRESS 0x00002000
#define ENTRY_PROCESSED 0x00004000
#define DONT_CALL_FOR_THREAD 0x00040000
#define PROCESS_ATTACH_CALLED 0x00080000
#define IMAGE_NOT_AT_BASE 0x00200000
typedef struct _LDR_MODULE typedef struct _LDR_MODULE
{ {
LIST_ENTRY InLoadOrderModuleList; LIST_ENTRY InLoadOrderModuleList;
@ -67,7 +76,7 @@ typedef struct _MODULE_INFORMATION
MODULE_ENTRY ModuleEntry[1]; MODULE_ENTRY ModuleEntry[1];
} MODULE_INFORMATION, *PMODULE_INFORMATION; } MODULE_INFORMATION, *PMODULE_INFORMATION;
#if defined(KDBG) || defined(DBG) #ifdef KDBG
VOID VOID
LdrpLoadUserModuleSymbols(PLDR_MODULE LdrModule); LdrpLoadUserModuleSymbols(PLDR_MODULE LdrModule);
@ -90,7 +99,7 @@ NTSTATUS STDCALL
LdrDisableThreadCalloutsForDll(IN PVOID BaseAddress); LdrDisableThreadCalloutsForDll(IN PVOID BaseAddress);
NTSTATUS STDCALL NTSTATUS STDCALL
LdrGetDllHandle(IN ULONG Unknown1, LdrGetDllHandle(IN PWCHAR Path OPTIONAL,
IN ULONG Unknown2, IN ULONG Unknown2,
IN PUNICODE_STRING DllName, IN PUNICODE_STRING DllName,
OUT PVOID *BaseAddress); OUT PVOID *BaseAddress);

View file

@ -15,12 +15,14 @@
#ifdef NDEBUG #ifdef NDEBUG
#if defined(__GNUC__) #if defined(__GNUC__)
#define TRACE_LDR(args...) if (NtGlobalFlag & FLG_SHOW_LDR_SNAPS) { DbgPrint("(LDR:%s:%d) ",__FILE__,__LINE__); DbgPrint(args); }
#define DPRINT(args...) #define DPRINT(args...)
#else #else
#define DPRINT #define DPRINT
#endif /* __GNUC__ */ #endif /* __GNUC__ */
#define CHECKPOINT #define CHECKPOINT
#else #else
#define TRACE_LDR(args...) do { DbgPrint("(LDR:%s:%d) ",__FILE__,__LINE__); DbgPrint(args); } while(0)
#define DPRINT(args...) do { DbgPrint("(NTDLL:%s:%d) ",__FILE__,__LINE__); DbgPrint(args); } while(0) #define DPRINT(args...) do { DbgPrint("(NTDLL:%s:%d) ",__FILE__,__LINE__); DbgPrint(args); } while(0)
#define CHECKPOINT do { DbgPrint("(NTDLL:%s:%d) Checkpoint\n",__FILE__,__LINE__); } while(0) #define CHECKPOINT do { DbgPrint("(NTDLL:%s:%d) Checkpoint\n",__FILE__,__LINE__); } while(0)
#endif #endif

View file

@ -1,4 +1,4 @@
/* $Id: startup.c,v 1.56 2003/11/17 02:32:45 hyperion Exp $ /* $Id: startup.c,v 1.57 2004/01/07 10:09:03 hbirr Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -27,7 +27,6 @@
VOID RtlInitializeHeapManager (VOID); VOID RtlInitializeHeapManager (VOID);
VOID LdrpInitLoader(VOID); VOID LdrpInitLoader(VOID);
/* GLOBALS *******************************************************************/ /* GLOBALS *******************************************************************/
@ -36,9 +35,13 @@ extern unsigned int _image_base__;
static CRITICAL_SECTION PebLock; static CRITICAL_SECTION PebLock;
static CRITICAL_SECTION LoaderLock; static CRITICAL_SECTION LoaderLock;
static RTL_BITMAP TlsBitMap; static RTL_BITMAP TlsBitMap;
PLDR_MODULE ExeModule;
ULONG NtGlobalFlag = 0; ULONG NtGlobalFlag = 0;
NTSTATUS LdrpAttachThread (VOID);
#define VALUE_BUFFER_SIZE 256 #define VALUE_BUFFER_SIZE 256
BOOL FASTCALL BOOL FASTCALL
@ -66,6 +69,45 @@ ReadCompatibilitySetting(HANDLE Key, LPWSTR Value, PKEY_VALUE_PARTIAL_INFORMATIO
return TRUE; return TRUE;
} }
VOID FASTCALL
LoadImageFileExecutionOptions(PPEB Peb)
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG Value = 0;
UNICODE_STRING ValueString;
WCHAR ValueBuffer[64];
ULONG ValueSize;
if (Peb->ProcessParameters &&
Peb->ProcessParameters->ImagePathName.Length > 0)
{
/* global flag */
Status = LdrQueryImageFileExecutionOptions (&Peb->ProcessParameters->ImagePathName,
L"GlobalFlag",
REG_SZ,
(PVOID)ValueBuffer,
sizeof(ValueBuffer),
&ValueSize);
if (NT_SUCCESS(Status))
{
ValueString.Buffer = ValueBuffer + 1;
ValueString.Length = ValueSize - 2 * sizeof(WCHAR);
ValueString.MaximumLength = sizeof(ValueBuffer);
RtlUnicodeStringToInteger(&ValueString, 16, &Value);
Peb->NtGlobalFlag |= Value;
DPRINT("GlobalFlag: Key='%S', Value=%08x\n", ValueBuffer, Value);
}
/*
* FIXME:
* read more options
*/
}
NtGlobalFlag = Peb->NtGlobalFlag;
}
BOOL FASTCALL BOOL FASTCALL
LoadCompatibilitySettings(PPEB Peb) LoadCompatibilitySettings(PPEB Peb)
{ {
@ -198,230 +240,212 @@ __true_LdrInitializeThunk (ULONG Unknown1,
PVOID ImageBase; PVOID ImageBase;
PPEB Peb; PPEB Peb;
PLDR_MODULE NtModule; // ntdll PLDR_MODULE NtModule; // ntdll
PLDR_MODULE ExeModule; // executable
NLSTABLEINFO NlsTable; NLSTABLEINFO NlsTable;
WCHAR FullNtDllPath[MAX_PATH]; WCHAR FullNtDllPath[MAX_PATH];
DPRINT("LdrInitializeThunk()\n"); DPRINT("LdrInitializeThunk()\n");
if (NtCurrentPeb()->Ldr != NULL && NtCurrentPeb()->Ldr->Initialized == TRUE) if (NtCurrentPeb()->Ldr == NULL || NtCurrentPeb()->Ldr->Initialized == FALSE)
{ {
PLIST_ENTRY current_entry; Peb = (PPEB)(PEB_BASE);
PDLLMAIN_FUNC Entrypoint; DPRINT("Peb %x\n", Peb);
PLDR_MODULE current; ImageBase = Peb->ImageBaseAddress;
DPRINT("ImageBase %x\n", ImageBase);
RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock); if (ImageBase <= (PVOID)0x1000)
current_entry =
NtCurrentPeb()->Ldr->InInitializationOrderModuleList.Flink;
while (current_entry !=
&NtCurrentPeb()->Ldr->InInitializationOrderModuleList)
{ {
current = CONTAINING_RECORD(current_entry, LDR_MODULE, DPRINT("ImageBase is null\n");
InInitializationOrderModuleList); ZwTerminateProcess(NtCurrentProcess(), STATUS_UNSUCCESSFUL);
Entrypoint = (PDLLMAIN_FUNC)current->EntryPoint;
if (Entrypoint != NULL &&
current->BaseAddress != NtCurrentPeb()->ImageBaseAddress)
{
(VOID)Entrypoint(current->BaseAddress, DLL_THREAD_ATTACH, NULL);
}
current_entry = current_entry->Flink;
} }
RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
return;
}
Peb = (PPEB)(PEB_BASE); /* If MZ header exists */
DPRINT("Peb %x\n", Peb); PEDosHeader = (PIMAGE_DOS_HEADER) ImageBase;
ImageBase = Peb->ImageBaseAddress; DPRINT("PEDosHeader %x\n", PEDosHeader);
DPRINT("ImageBase %x\n", ImageBase); if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC ||
if (ImageBase <= (PVOID)0x1000) PEDosHeader->e_lfanew == 0L ||
{ *(PULONG)((PUCHAR)ImageBase + PEDosHeader->e_lfanew) != IMAGE_PE_MAGIC)
DPRINT("ImageBase is null\n"); {
ZwTerminateProcess(NtCurrentProcess(), STATUS_UNSUCCESSFUL); DbgPrint("Image has bad header\n");
} ZwTerminateProcess(NtCurrentProcess(), STATUS_UNSUCCESSFUL);
}
NtGlobalFlag = Peb->NtGlobalFlag; /* normalize process parameters */
RtlNormalizeProcessParams (Peb->ProcessParameters);
/* If MZ header exists */ /* Initialize NLS data */
PEDosHeader = (PIMAGE_DOS_HEADER) ImageBase; RtlInitNlsTables (Peb->AnsiCodePageData,
DPRINT("PEDosHeader %x\n", PEDosHeader); Peb->OemCodePageData,
if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC || Peb->UnicodeCaseTableData,
PEDosHeader->e_lfanew == 0L || &NlsTable);
*(PULONG)((PUCHAR)ImageBase + PEDosHeader->e_lfanew) != IMAGE_PE_MAGIC) RtlResetRtlTranslations (&NlsTable);
{
DbgPrint("Image has bad header\n");
ZwTerminateProcess(NtCurrentProcess(), STATUS_UNSUCCESSFUL);
}
/* normalize process parameters */ NTHeaders = (PIMAGE_NT_HEADERS)(ImageBase + PEDosHeader->e_lfanew);
RtlNormalizeProcessParams (Peb->ProcessParameters);
/* Initialize NLS data */ /* create process heap */
RtlInitNlsTables (Peb->AnsiCodePageData, RtlInitializeHeapManager();
Peb->OemCodePageData, Peb->ProcessHeap = RtlCreateHeap(HEAP_GROWABLE,
Peb->UnicodeCaseTableData, (PVOID)HEAP_BASE,
&NlsTable); NTHeaders->OptionalHeader.SizeOfHeapReserve,
RtlResetRtlTranslations (&NlsTable); NTHeaders->OptionalHeader.SizeOfHeapCommit,
NULL,
NULL);
if (Peb->ProcessHeap == 0)
{
DbgPrint("Failed to create process heap\n");
ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
}
NTHeaders = (PIMAGE_NT_HEADERS)(ImageBase + PEDosHeader->e_lfanew); /* initalize peb lock support */
RtlInitializeCriticalSection (&PebLock);
Peb->FastPebLock = &PebLock;
Peb->FastPebLockRoutine = (PPEBLOCKROUTINE)RtlEnterCriticalSection;
Peb->FastPebUnlockRoutine = (PPEBLOCKROUTINE)RtlLeaveCriticalSection;
/* create process heap */ /* initialize tls bitmap */
RtlInitializeHeapManager(); RtlInitializeBitMap (&TlsBitMap,
Peb->ProcessHeap = RtlCreateHeap(HEAP_GROWABLE, Peb->TlsBitmapBits,
(PVOID)HEAP_BASE, TLS_MINIMUM_AVAILABLE);
NTHeaders->OptionalHeader.SizeOfHeapReserve, Peb->TlsBitmap = &TlsBitMap;
NTHeaders->OptionalHeader.SizeOfHeapCommit, Peb->TlsExpansionCounter = TLS_MINIMUM_AVAILABLE;
NULL,
NULL);
if (Peb->ProcessHeap == 0)
{
DbgPrint("Failed to create process heap\n");
ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
}
/* initalize peb lock support */ /* Initialize table of callbacks for the kernel. */
RtlInitializeCriticalSection (&PebLock); Peb->KernelCallbackTable =
Peb->FastPebLock = &PebLock; RtlAllocateHeap(RtlGetProcessHeap(),
Peb->FastPebLockRoutine = (PPEBLOCKROUTINE)RtlEnterCriticalSection; 0,
Peb->FastPebUnlockRoutine = (PPEBLOCKROUTINE)RtlLeaveCriticalSection; sizeof(PVOID) * (USER32_CALLBACK_MAXIMUM + 1));
/* initialize tls bitmap */ /* initalize loader lock */
RtlInitializeBitMap (&TlsBitMap, RtlInitializeCriticalSection (&LoaderLock);
Peb->TlsBitmapBits, Peb->LoaderLock = &LoaderLock;
TLS_MINIMUM_AVAILABLE);
Peb->TlsBitmap = &TlsBitMap;
Peb->TlsExpansionCounter = TLS_MINIMUM_AVAILABLE;
/* Initialize table of callbacks for the kernel. */ /* create loader information */
Peb->KernelCallbackTable = Peb->Ldr = (PPEB_LDR_DATA)RtlAllocateHeap (Peb->ProcessHeap,
RtlAllocateHeap(RtlGetProcessHeap(), 0,
0, sizeof(PEB_LDR_DATA));
sizeof(PVOID) * (USER32_CALLBACK_MAXIMUM + 1)); if (Peb->Ldr == NULL)
{
DbgPrint("Failed to create loader data\n");
ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
}
Peb->Ldr->Length = sizeof(PEB_LDR_DATA);
Peb->Ldr->Initialized = FALSE;
Peb->Ldr->SsHandle = NULL;
InitializeListHead(&Peb->Ldr->InLoadOrderModuleList);
InitializeListHead(&Peb->Ldr->InMemoryOrderModuleList);
InitializeListHead(&Peb->Ldr->InInitializationOrderModuleList);
/* initalize loader lock */ /* Load compatibility settings */
RtlInitializeCriticalSection (&LoaderLock); LoadCompatibilitySettings(Peb);
Peb->LoaderLock = &LoaderLock;
/* create loader information */ /* Load execution options */
Peb->Ldr = (PPEB_LDR_DATA)RtlAllocateHeap (Peb->ProcessHeap, LoadImageFileExecutionOptions(Peb);
0,
sizeof(PEB_LDR_DATA));
if (Peb->Ldr == NULL)
{
DbgPrint("Failed to create loader data\n");
ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
}
Peb->Ldr->Length = sizeof(PEB_LDR_DATA);
Peb->Ldr->Initialized = FALSE;
Peb->Ldr->SsHandle = NULL;
InitializeListHead(&Peb->Ldr->InLoadOrderModuleList);
InitializeListHead(&Peb->Ldr->InMemoryOrderModuleList);
InitializeListHead(&Peb->Ldr->InInitializationOrderModuleList);
/* Load compatibility settings */ /* build full ntdll path */
LoadCompatibilitySettings(Peb); wcscpy (FullNtDllPath, SharedUserData->NtSystemRoot);
wcscat (FullNtDllPath, L"\\system32\\ntdll.dll");
/* build full ntdll path */ /* add entry for ntdll */
wcscpy (FullNtDllPath, SharedUserData->NtSystemRoot); NtModule = (PLDR_MODULE)RtlAllocateHeap (Peb->ProcessHeap,
wcscat (FullNtDllPath, L"\\system32\\ntdll.dll"); 0,
sizeof(LDR_MODULE));
if (NtModule == NULL)
{
DbgPrint("Failed to create loader module entry (NTDLL)\n");
ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
}
memset(NtModule, 0, sizeof(LDR_MODULE));
/* add entry for ntdll */ NtModule->BaseAddress = (PVOID)&_image_base__;
NtModule = (PLDR_MODULE)RtlAllocateHeap (Peb->ProcessHeap, NtModule->EntryPoint = 0; /* no entry point */
0, RtlCreateUnicodeString (&NtModule->FullDllName,
sizeof(LDR_MODULE)); FullNtDllPath);
if (NtModule == NULL) RtlCreateUnicodeString (&NtModule->BaseDllName,
{ L"ntdll.dll");
DbgPrint("Failed to create loader module entry (NTDLL)\n"); NtModule->Flags = IMAGE_DLL|ENTRY_PROCESSED;
ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
}
memset(NtModule, 0, sizeof(LDR_MODULE));
NtModule->BaseAddress = (PVOID)&_image_base__; NtModule->LoadCount = -1; /* don't unload */
NtModule->EntryPoint = 0; /* no entry point */ NtModule->TlsIndex = -1;
RtlCreateUnicodeString (&NtModule->FullDllName, NtModule->SectionHandle = NULL;
FullNtDllPath); NtModule->CheckSum = 0;
RtlCreateUnicodeString (&NtModule->BaseDllName,
L"ntdll.dll");
NtModule->Flags = 0;
NtModule->LoadCount = -1; /* don't unload */
NtModule->TlsIndex = 0;
NtModule->SectionHandle = NULL;
NtModule->CheckSum = 0;
NTHeaders = RtlImageNtHeader (NtModule->BaseAddress); NTHeaders = RtlImageNtHeader (NtModule->BaseAddress);
NtModule->SizeOfImage = NTHeaders->OptionalHeader.SizeOfImage; NtModule->SizeOfImage = NTHeaders->OptionalHeader.SizeOfImage;
NtModule->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp; NtModule->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp;
InsertTailList(&Peb->Ldr->InLoadOrderModuleList, InsertTailList(&Peb->Ldr->InLoadOrderModuleList,
&NtModule->InLoadOrderModuleList); &NtModule->InLoadOrderModuleList);
InsertTailList(&Peb->Ldr->InInitializationOrderModuleList, InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
&NtModule->InInitializationOrderModuleList); &NtModule->InInitializationOrderModuleList);
#ifdef DBG #ifdef KDBG
LdrpLoadUserModuleSymbols(NtModule); LdrpLoadUserModuleSymbols(NtModule);
#endif /* DBG */ #endif /* DBG */
/* add entry for executable (becomes first list entry) */ /* add entry for executable (becomes first list entry) */
ExeModule = (PLDR_MODULE)RtlAllocateHeap (Peb->ProcessHeap, ExeModule = (PLDR_MODULE)RtlAllocateHeap (Peb->ProcessHeap,
0, 0,
sizeof(LDR_MODULE)); sizeof(LDR_MODULE));
if (ExeModule == NULL) if (ExeModule == NULL)
{ {
DbgPrint("Failed to create loader module infomation\n"); DbgPrint("Failed to create loader module infomation\n");
ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL); ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
} }
ExeModule->BaseAddress = Peb->ImageBaseAddress; ExeModule->BaseAddress = Peb->ImageBaseAddress;
if ((Peb->ProcessParameters == NULL) || if ((Peb->ProcessParameters == NULL) ||
(Peb->ProcessParameters->ImagePathName.Length == 0)) (Peb->ProcessParameters->ImagePathName.Length == 0))
{ {
DbgPrint("Failed to access the process parameter block\n"); DbgPrint("Failed to access the process parameter block\n");
ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL); ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
} }
RtlCreateUnicodeString(&ExeModule->FullDllName, RtlCreateUnicodeString(&ExeModule->FullDllName,
Peb->ProcessParameters->ImagePathName.Buffer); Peb->ProcessParameters->ImagePathName.Buffer);
RtlCreateUnicodeString(&ExeModule->BaseDllName, RtlCreateUnicodeString(&ExeModule->BaseDllName,
wcsrchr(ExeModule->FullDllName.Buffer, L'\\') + 1); wcsrchr(ExeModule->FullDllName.Buffer, L'\\') + 1);
DPRINT("BaseDllName '%wZ' FullDllName '%wZ'\n", DPRINT("BaseDllName '%wZ' FullDllName '%wZ'\n",
&ExeModule->BaseDllName, &ExeModule->BaseDllName,
&ExeModule->FullDllName); &ExeModule->FullDllName);
ExeModule->Flags = 0; ExeModule->Flags = ENTRY_PROCESSED;
ExeModule->LoadCount = -1; /* don't unload */ ExeModule->LoadCount = -1; /* don't unload */
ExeModule->TlsIndex = 0; ExeModule->TlsIndex = -1;
ExeModule->SectionHandle = NULL; ExeModule->SectionHandle = NULL;
ExeModule->CheckSum = 0; ExeModule->CheckSum = 0;
NTHeaders = RtlImageNtHeader (ExeModule->BaseAddress); NTHeaders = RtlImageNtHeader (ExeModule->BaseAddress);
ExeModule->SizeOfImage = NTHeaders->OptionalHeader.SizeOfImage; ExeModule->SizeOfImage = NTHeaders->OptionalHeader.SizeOfImage;
ExeModule->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp; ExeModule->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp;
InsertHeadList(&Peb->Ldr->InLoadOrderModuleList, InsertHeadList(&Peb->Ldr->InLoadOrderModuleList,
&ExeModule->InLoadOrderModuleList); &ExeModule->InLoadOrderModuleList);
LdrpInitLoader(); LdrpInitLoader();
#ifdef DBG #ifdef KDBG
LdrpLoadUserModuleSymbols(ExeModule); LdrpLoadUserModuleSymbols(ExeModule);
#endif /* DBG */ #endif /* DBG */
EntryPoint = LdrPEStartup((PVOID)ImageBase, NULL, NULL, NULL); EntryPoint = LdrPEStartup((PVOID)ImageBase, NULL, NULL, NULL);
ExeModule->EntryPoint = (ULONG)EntryPoint; ExeModule->EntryPoint = (ULONG)EntryPoint;
/* all required dlls are loaded now */ /* all required dlls are loaded now */
Peb->Ldr->Initialized = TRUE; Peb->Ldr->Initialized = TRUE;
/* Check before returning that we can run the image safely. */ /* Check before returning that we can run the image safely. */
if (EntryPoint == NULL) if (EntryPoint == NULL)
{ {
DbgPrint("Failed to initialize image\n"); DbgPrint("Failed to initialize image\n");
ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL); ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
}
} }
/* attach the thread */
RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock);
LdrpAttachThread();
RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
} }
/* EOF */ /* EOF */

File diff suppressed because it is too large Load diff