2008-08-02 12:46:02 +00:00
|
|
|
/*
|
1999-03-19 05:55:55 +00:00
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS kernel
|
2008-12-26 13:50:35 +00:00
|
|
|
* FILE: dll/ntdll/ldr/startup.c
|
1999-03-19 05:55:55 +00:00
|
|
|
* PURPOSE: Process startup for PE executables
|
|
|
|
* PROGRAMMERS: Jean Michault
|
|
|
|
* Rex Jolliff (rex@lvcablemodem.com)
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
2005-06-17 17:22:27 +00:00
|
|
|
#include <ntdll.h>
|
2005-06-19 22:50:59 +00:00
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
2005-06-19 18:34:35 +00:00
|
|
|
#include <win32k/callback.h>
|
1999-03-19 05:55:55 +00:00
|
|
|
|
2008-12-26 13:50:35 +00:00
|
|
|
VOID RtlInitializeHeapManager(VOID);
|
2003-05-12 19:47:53 +00:00
|
|
|
VOID LdrpInitLoader(VOID);
|
2005-10-19 23:08:12 +00:00
|
|
|
VOID NTAPI RtlpInitDeferedCriticalSection(VOID);
|
2008-12-26 13:50:35 +00:00
|
|
|
NTSTATUS LdrpAttachThread(VOID);
|
|
|
|
VOID RtlpInitializeVectoredExceptionHandling(VOID);
|
2009-09-11 07:12:30 +00:00
|
|
|
extern PTEB LdrpTopLevelDllBeingLoadedTeb;
|
2003-05-12 19:47:53 +00:00
|
|
|
|
2002-09-08 10:23:54 +00:00
|
|
|
/* GLOBALS *******************************************************************/
|
|
|
|
|
2008-12-26 13:50:35 +00:00
|
|
|
PLDR_DATA_TABLE_ENTRY ExeModule;
|
2005-06-17 08:00:30 +00:00
|
|
|
static RTL_CRITICAL_SECTION PebLock;
|
|
|
|
static RTL_CRITICAL_SECTION LoaderLock;
|
2000-11-19 15:59:46 +00:00
|
|
|
static RTL_BITMAP TlsBitMap;
|
2008-07-07 09:24:10 +00:00
|
|
|
static RTL_BITMAP TlsExpansionBitMap;
|
2008-12-28 12:32:20 +00:00
|
|
|
static volatile BOOLEAN LdrpInitialized = FALSE;
|
|
|
|
static LONG LdrpInitLock = 0;
|
2004-01-07 10:09:03 +00:00
|
|
|
|
2003-08-21 12:51:01 +00:00
|
|
|
#define VALUE_BUFFER_SIZE 256
|
|
|
|
|
2008-12-26 13:50:35 +00:00
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
|
|
|
|
BOOLEAN
|
|
|
|
FASTCALL
|
|
|
|
ReadCompatibilitySetting(HANDLE Key,
|
|
|
|
LPWSTR Value,
|
|
|
|
PKEY_VALUE_PARTIAL_INFORMATION ValueInfo,
|
|
|
|
DWORD * Buffer)
|
2003-08-21 12:51:01 +00:00
|
|
|
{
|
2008-12-26 13:50:35 +00:00
|
|
|
UNICODE_STRING ValueName;
|
|
|
|
NTSTATUS Status;
|
|
|
|
ULONG Length;
|
|
|
|
|
|
|
|
RtlInitUnicodeString(&ValueName, Value);
|
|
|
|
Status = NtQueryValueKey(Key,
|
|
|
|
&ValueName,
|
|
|
|
KeyValuePartialInformation,
|
|
|
|
ValueInfo,
|
|
|
|
VALUE_BUFFER_SIZE,
|
|
|
|
&Length);
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status) || (ValueInfo->Type != REG_DWORD))
|
|
|
|
{
|
|
|
|
RtlFreeUnicodeString(&ValueName);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlCopyMemory(Buffer, &ValueInfo->Data[0], sizeof(DWORD));
|
|
|
|
RtlFreeUnicodeString(&ValueName);
|
|
|
|
return TRUE;
|
2003-08-21 12:51:01 +00:00
|
|
|
}
|
|
|
|
|
2008-12-26 13:50:35 +00:00
|
|
|
VOID
|
|
|
|
FASTCALL
|
2004-01-07 10:09:03 +00:00
|
|
|
LoadImageFileExecutionOptions(PPEB Peb)
|
|
|
|
{
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
ULONG Value = 0;
|
2005-08-11 19:46:39 +00:00
|
|
|
UNICODE_STRING ImageName;
|
|
|
|
UNICODE_STRING ImagePathName;
|
2004-01-07 10:09:03 +00:00
|
|
|
ULONG ValueSize;
|
2010-10-06 20:34:30 +00:00
|
|
|
extern ULONG RtlpPageHeapGlobalFlags, RtlpPageHeapSizeRangeStart, RtlpPageHeapSizeRangeEnd;
|
|
|
|
extern ULONG RtlpPageHeapDllRangeStart, RtlpPageHeapDllRangeEnd;
|
|
|
|
extern WCHAR RtlpPageHeapTargetDlls[512];
|
|
|
|
extern BOOLEAN RtlpPageHeapEnabled;
|
2004-01-07 10:09:03 +00:00
|
|
|
|
|
|
|
if (Peb->ProcessParameters &&
|
|
|
|
Peb->ProcessParameters->ImagePathName.Length > 0)
|
2008-12-26 13:50:35 +00:00
|
|
|
{
|
2005-08-11 19:46:39 +00:00
|
|
|
DPRINT("%wZ\n", &Peb->ProcessParameters->ImagePathName);
|
|
|
|
|
|
|
|
ImagePathName = Peb->ProcessParameters->ImagePathName;
|
|
|
|
ImageName.Buffer = ImagePathName.Buffer + ImagePathName.Length / sizeof(WCHAR);
|
|
|
|
ImageName.Length = 0;
|
2008-12-26 13:50:35 +00:00
|
|
|
|
2005-08-11 19:46:39 +00:00
|
|
|
while (ImagePathName.Buffer < ImageName.Buffer)
|
|
|
|
{
|
|
|
|
ImageName.Buffer--;
|
|
|
|
if (*ImageName.Buffer == L'\\')
|
|
|
|
{
|
2008-12-26 13:50:35 +00:00
|
|
|
ImageName.Buffer++;
|
|
|
|
break;
|
2005-08-11 19:46:39 +00:00
|
|
|
}
|
|
|
|
}
|
2008-12-26 13:50:35 +00:00
|
|
|
|
|
|
|
ImageName.Length = ImagePathName.Length -
|
|
|
|
(ImageName.Buffer - ImagePathName.Buffer) * sizeof(WCHAR);
|
|
|
|
ImageName.MaximumLength = ImageName.Length +
|
|
|
|
ImagePathName.MaximumLength - ImagePathName.Length;
|
2005-08-11 19:46:39 +00:00
|
|
|
|
|
|
|
DPRINT("%wZ\n", &ImageName);
|
|
|
|
|
2004-01-07 10:09:03 +00:00
|
|
|
/* global flag */
|
2008-12-26 13:50:35 +00:00
|
|
|
Status = LdrQueryImageFileExecutionOptions(&ImageName,
|
|
|
|
L"GlobalFlag",
|
2010-10-06 17:18:22 +00:00
|
|
|
REG_DWORD,
|
|
|
|
(PVOID)&Value,
|
|
|
|
sizeof(Value),
|
2008-12-26 13:50:35 +00:00
|
|
|
&ValueSize);
|
2004-01-07 10:09:03 +00:00
|
|
|
if (NT_SUCCESS(Status))
|
2008-12-26 13:50:35 +00:00
|
|
|
{
|
2010-10-06 17:18:22 +00:00
|
|
|
Peb->NtGlobalFlag = Value;
|
|
|
|
DPRINT("GlobalFlag: Value=0x%lx\n", Value);
|
2008-12-26 13:50:35 +00:00
|
|
|
}
|
2010-10-06 20:34:30 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Add debugging flags if there is no GlobalFlags override */
|
|
|
|
if (Peb->BeingDebugged)
|
|
|
|
{
|
|
|
|
Peb->NtGlobalFlag |= FLG_HEAP_VALIDATE_PARAMETERS |
|
|
|
|
FLG_HEAP_ENABLE_FREE_CHECK |
|
|
|
|
FLG_HEAP_ENABLE_TAIL_CHECK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Handle the case when page heap is enabled */
|
|
|
|
if (Peb->NtGlobalFlag & FLG_HEAP_PAGE_ALLOCS)
|
|
|
|
{
|
|
|
|
/* Disable all heap debugging flags so that no heap call goes via page heap branch */
|
|
|
|
Peb->NtGlobalFlag &= ~(FLG_HEAP_VALIDATE_PARAMETERS |
|
|
|
|
FLG_HEAP_VALIDATE_ALL |
|
|
|
|
FLG_HEAP_ENABLE_FREE_CHECK |
|
|
|
|
FLG_HEAP_ENABLE_TAIL_CHECK |
|
|
|
|
FLG_USER_STACK_TRACE_DB |
|
|
|
|
FLG_HEAP_ENABLE_TAGGING |
|
|
|
|
FLG_HEAP_ENABLE_TAG_BY_DLL);
|
|
|
|
|
2010-10-07 16:51:19 +00:00
|
|
|
/* Get page heap flags without checking return value */
|
|
|
|
LdrQueryImageFileExecutionOptions(&ImageName,
|
|
|
|
L"PageHeapFlags",
|
|
|
|
REG_DWORD,
|
|
|
|
(PVOID)&RtlpPageHeapGlobalFlags,
|
|
|
|
sizeof(RtlpPageHeapGlobalFlags),
|
|
|
|
&ValueSize);
|
|
|
|
|
|
|
|
LdrQueryImageFileExecutionOptions(&ImageName,
|
|
|
|
L"PageHeapSizeRangeStart",
|
|
|
|
REG_DWORD,
|
|
|
|
(PVOID)&RtlpPageHeapSizeRangeStart,
|
|
|
|
sizeof(RtlpPageHeapSizeRangeStart),
|
|
|
|
&ValueSize);
|
|
|
|
|
|
|
|
LdrQueryImageFileExecutionOptions(&ImageName,
|
|
|
|
L"PageHeapSizeRangeEnd",
|
|
|
|
REG_DWORD,
|
|
|
|
(PVOID)&RtlpPageHeapSizeRangeEnd,
|
|
|
|
sizeof(RtlpPageHeapSizeRangeEnd),
|
|
|
|
&ValueSize);
|
|
|
|
|
|
|
|
LdrQueryImageFileExecutionOptions(&ImageName,
|
|
|
|
L"PageHeapDllRangeStart",
|
|
|
|
REG_DWORD,
|
|
|
|
(PVOID)&RtlpPageHeapDllRangeStart,
|
|
|
|
sizeof(RtlpPageHeapDllRangeStart),
|
|
|
|
&ValueSize);
|
|
|
|
|
|
|
|
LdrQueryImageFileExecutionOptions(&ImageName,
|
|
|
|
L"PageHeapDllRangeEnd",
|
|
|
|
REG_DWORD,
|
|
|
|
(PVOID)&RtlpPageHeapDllRangeEnd,
|
|
|
|
sizeof(RtlpPageHeapDllRangeEnd),
|
|
|
|
&ValueSize);
|
|
|
|
|
|
|
|
LdrQueryImageFileExecutionOptions(&ImageName,
|
|
|
|
L"PageHeapTargetDlls",
|
|
|
|
REG_SZ,
|
|
|
|
(PVOID)RtlpPageHeapTargetDlls,
|
|
|
|
sizeof(RtlpPageHeapTargetDlls),
|
|
|
|
&ValueSize);
|
|
|
|
|
|
|
|
/* Now when all parameters are read, enable page heap */
|
|
|
|
RtlpPageHeapEnabled = TRUE;
|
|
|
|
}
|
2008-12-26 13:50:35 +00:00
|
|
|
}
|
2004-01-07 10:09:03 +00:00
|
|
|
}
|
|
|
|
|
2008-12-26 13:50:35 +00:00
|
|
|
BOOLEAN
|
|
|
|
FASTCALL
|
|
|
|
LoadCompatibilitySettings(PPEB Peb)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
HANDLE UserKey = NULL;
|
|
|
|
HANDLE KeyHandle;
|
|
|
|
HANDLE SubKeyHandle;
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
UNICODE_STRING KeyName = RTL_CONSTANT_STRING(
|
|
|
|
L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers");
|
|
|
|
UNICODE_STRING ValueName;
|
|
|
|
UCHAR ValueBuffer[VALUE_BUFFER_SIZE];
|
|
|
|
PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
|
|
|
|
ULONG Length;
|
|
|
|
DWORD MajorVersion, MinorVersion, BuildNumber, PlatformId,
|
|
|
|
SPMajorVersion, SPMinorVersion = 0;
|
|
|
|
|
|
|
|
if (Peb->ProcessParameters &&
|
|
|
|
(Peb->ProcessParameters->ImagePathName.Length > 0))
|
|
|
|
{
|
|
|
|
Status = RtlOpenCurrentUser(KEY_READ, &UserKey);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&KeyName,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
UserKey,
|
|
|
|
NULL);
|
2004-01-07 10:09:03 +00:00
|
|
|
|
2008-12-26 13:50:35 +00:00
|
|
|
Status = NtOpenKey(&KeyHandle, KEY_QUERY_VALUE, &ObjectAttributes);
|
2005-05-09 01:43:25 +00:00
|
|
|
|
2008-12-26 13:50:35 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
if (UserKey)
|
|
|
|
NtClose(UserKey);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2005-05-09 01:43:25 +00:00
|
|
|
|
2008-12-26 13:50:35 +00:00
|
|
|
/* query version name for application */
|
|
|
|
ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION) ValueBuffer;
|
|
|
|
Status = NtQueryValueKey(KeyHandle,
|
|
|
|
&Peb->ProcessParameters->ImagePathName,
|
|
|
|
KeyValuePartialInformation,
|
|
|
|
ValueBuffer,
|
|
|
|
VALUE_BUFFER_SIZE,
|
|
|
|
&Length);
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status) || (ValueInfo->Type != REG_SZ))
|
|
|
|
{
|
|
|
|
NtClose(KeyHandle);
|
|
|
|
if (UserKey)
|
|
|
|
NtClose(UserKey);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ValueName.Length = ValueInfo->DataLength;
|
|
|
|
ValueName.MaximumLength = ValueInfo->DataLength;
|
|
|
|
ValueName.Buffer = (PWSTR) ValueInfo->Data;
|
|
|
|
|
|
|
|
/* load version info */
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&ValueName,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
KeyHandle,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
Status = NtOpenKey(&SubKeyHandle, KEY_QUERY_VALUE, &ObjectAttributes);
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
NtClose(KeyHandle);
|
|
|
|
if (UserKey)
|
|
|
|
NtClose(UserKey);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
DPRINT("Loading version information for: %wZ\n", &ValueName);
|
|
|
|
|
|
|
|
/* read settings from registry */
|
|
|
|
if (!ReadCompatibilitySetting(SubKeyHandle, L"MajorVersion", ValueInfo, &MajorVersion))
|
|
|
|
goto finish;
|
|
|
|
if (!ReadCompatibilitySetting(SubKeyHandle, L"MinorVersion", ValueInfo, &MinorVersion))
|
|
|
|
goto finish;
|
|
|
|
if (!ReadCompatibilitySetting(SubKeyHandle, L"BuildNumber", ValueInfo, &BuildNumber))
|
|
|
|
goto finish;
|
|
|
|
if (!ReadCompatibilitySetting(SubKeyHandle, L"PlatformId", ValueInfo, &PlatformId))
|
|
|
|
goto finish;
|
|
|
|
|
|
|
|
/* now assign the settings */
|
|
|
|
Peb->OSMajorVersion = (ULONG) MajorVersion;
|
|
|
|
Peb->OSMinorVersion = (ULONG) MinorVersion;
|
|
|
|
Peb->OSBuildNumber = (USHORT) BuildNumber;
|
|
|
|
Peb->OSPlatformId = (ULONG) PlatformId;
|
|
|
|
|
|
|
|
/* optional service pack version numbers */
|
|
|
|
if (ReadCompatibilitySetting(SubKeyHandle,
|
|
|
|
L"SPMajorVersion",
|
|
|
|
ValueInfo,
|
|
|
|
&SPMajorVersion) &&
|
|
|
|
ReadCompatibilitySetting(SubKeyHandle,
|
|
|
|
L"SPMinorVersion",
|
|
|
|
ValueInfo,
|
|
|
|
&SPMinorVersion))
|
|
|
|
{
|
|
|
|
Peb->OSCSDVersion = ((SPMajorVersion & 0xFF) << 8) |
|
|
|
|
(SPMinorVersion & 0xFF);
|
|
|
|
}
|
2003-08-21 12:51:01 +00:00
|
|
|
|
|
|
|
finish:
|
2008-12-26 13:50:35 +00:00
|
|
|
/* we're finished */
|
|
|
|
NtClose(SubKeyHandle);
|
|
|
|
NtClose(KeyHandle);
|
|
|
|
if (UserKey)
|
|
|
|
NtClose(UserKey);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
2003-08-21 12:51:01 +00:00
|
|
|
}
|
|
|
|
|
2008-12-28 12:32:20 +00:00
|
|
|
static
|
Major refactoring of the exception handling code + misc fixes:
- Fix/add prototypes for RtlCaptureContext, RtlDispatchException and RtlUnwind
- Fix EXCEPTION_REGISTRATION_RECORD structure and PEXCEPTION_ROUTINE
- Add w32api excpt.h (based on mingw) with PSDK compatibility fixes
- Fix seriously broken User-Mode Ldr thunk and APC Callback prototypes
- Fix KiUserExceptionDispatcher
- Remove useless NTDLL entrypoint
- Implement NTDLL Ki* callbacks in ASM
- Implement RtlCaptureContext
- Fix RtlRaiseException to handle cases when a user-mode debugger is present
- Fix RtlRaiseStatus as above, plus set the exception address and capture context
- Little cleanup of RTL headers
- Implement RtlpGetStackLimits, RtlpGetExceptionList, RtlpSetExceptionList, RtlpGetExceptionAddress in ASM
- Fix RtlDispatchException, add cases for exceptions in the DPC stack and validate the validity of the
exception frames. Add support for exception logging by the global flag. Use TRAP_FRAME/EXCPETION_FRAME instead of
Context.
- Fix RtlUnwind logic, support cases where it's called with custom arguments instead of NULL.
- Reimplement RtlpCaptureContext to work properly, convert exception handler calling functions to INTEL syntax
and fix some bugs (like checking for the right unwind flag, clearing volatile register values, etc. Also use some
optimizations to increase speed.
- Modify some kernel functions (like KeContextToTrapFrame, KiDispatchException, KiInitializeUserApc, etc.) to
support a PKEXCEPTION_FRAME for future PPC compatibility.
- Reimplement RtlCaptureUnicodeString/FreeUnicodeString as inlined probe macros and optimize them.
- Export ExRaiseStatus/Exception as Rtl*
- Reimplement NtContinue to have more platform-independent code, and to protect and validate user-mode context
and parameters with SEH.
- Implement KiRaiseException, add SEH to all user-mode parameters and when copying data to the user-mode stack.
- Fix KiInitializeUserApc to use KeTrapFrameToContext, to save the debug registers, not to deliver APCs during
v86 mode, and to protect user-mode stack operations in SEH and probing. Also make it generate the proper stack for the
user-mode callback.
- Implement KiUnexpectedInterrupt and KiCoprocessorError
- Reimplement NtRaiseException in ASM to take advantage of optimizations due to the trap frame being in the
stack when called through System call interface.
- Fix Ntcontinue to respect AlertThread paramter
- Fix some functiosn to return with KiServiceExit2 instead of KiServiceExit when required/needed
- Fix KiDispatchException's logic, fix hacks when calling KeUserExceptionDispatcher, use correct context
flags,...
- Make NTDLL Ki* callbacks have SEH to protect them and return to kernel-mode with notification of any
exceptions (the kernel-mode code to handle this isn't written yet though)
svn path=/trunk/; revision=17811
2005-09-11 22:32:20 +00:00
|
|
|
VOID
|
2008-12-28 12:32:20 +00:00
|
|
|
LdrpInit2(PCONTEXT Context,
|
|
|
|
PVOID SystemArgument1,
|
|
|
|
PVOID SystemArgument2)
|
1999-03-19 05:55:55 +00:00
|
|
|
{
|
2008-12-26 13:50:35 +00:00
|
|
|
PIMAGE_NT_HEADERS NTHeaders;
|
|
|
|
PEPFUNC EntryPoint;
|
|
|
|
PIMAGE_DOS_HEADER PEDosHeader;
|
|
|
|
PVOID ImageBase;
|
|
|
|
PPEB Peb = NtCurrentPeb();
|
|
|
|
PLDR_DATA_TABLE_ENTRY NtModule; // ntdll
|
|
|
|
NLSTABLEINFO NlsTable;
|
|
|
|
WCHAR FullNtDllPath[MAX_PATH];
|
|
|
|
SYSTEM_BASIC_INFORMATION SystemInformation;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PVOID BaseAddress = SystemArgument1;
|
|
|
|
|
|
|
|
DPRINT("LdrpInit()\n");
|
|
|
|
DPRINT("Peb %p\n", Peb);
|
|
|
|
ImageBase = Peb->ImageBaseAddress;
|
|
|
|
DPRINT("ImageBase %p\n", ImageBase);
|
|
|
|
|
|
|
|
if (ImageBase <= (PVOID) 0x1000)
|
|
|
|
{
|
|
|
|
DPRINT("ImageBase is null\n");
|
|
|
|
ZwTerminateProcess(NtCurrentProcess(), STATUS_INVALID_IMAGE_FORMAT);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If MZ header exists */
|
|
|
|
PEDosHeader = (PIMAGE_DOS_HEADER) ImageBase;
|
|
|
|
DPRINT("PEDosHeader %p\n", PEDosHeader);
|
|
|
|
|
|
|
|
if (PEDosHeader->e_magic != IMAGE_DOS_SIGNATURE ||
|
|
|
|
PEDosHeader->e_lfanew == 0L ||
|
|
|
|
*(PULONG)((PUCHAR)ImageBase + PEDosHeader->e_lfanew) != IMAGE_NT_SIGNATURE)
|
|
|
|
{
|
|
|
|
DPRINT1("Image has bad header\n");
|
|
|
|
ZwTerminateProcess(NtCurrentProcess(), STATUS_INVALID_IMAGE_FORMAT);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* normalize process parameters */
|
|
|
|
RtlNormalizeProcessParams(Peb->ProcessParameters);
|
|
|
|
|
|
|
|
/* Initialize NLS data */
|
|
|
|
RtlInitNlsTables(Peb->AnsiCodePageData,
|
|
|
|
Peb->OemCodePageData,
|
|
|
|
Peb->UnicodeCaseTableData,
|
|
|
|
&NlsTable);
|
|
|
|
RtlResetRtlTranslations(&NlsTable);
|
|
|
|
|
|
|
|
NTHeaders = (PIMAGE_NT_HEADERS)((ULONG_PTR)ImageBase + PEDosHeader->e_lfanew);
|
|
|
|
|
|
|
|
/* Get number of processors */
|
|
|
|
DPRINT("Here\n");
|
|
|
|
Status = ZwQuerySystemInformation(SystemBasicInformation,
|
|
|
|
&SystemInformation,
|
|
|
|
sizeof(SYSTEM_BASIC_INFORMATION),
|
|
|
|
NULL);
|
|
|
|
DPRINT("Here2\n");
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
ZwTerminateProcess(NtCurrentProcess(), Status);
|
|
|
|
}
|
|
|
|
|
|
|
|
Peb->NumberOfProcessors = SystemInformation.NumberOfProcessors;
|
|
|
|
|
|
|
|
/* Initialize Critical Section Data */
|
|
|
|
RtlpInitDeferedCriticalSection();
|
|
|
|
|
2010-10-07 21:12:10 +00:00
|
|
|
/* Load execution options */
|
|
|
|
LoadImageFileExecutionOptions(Peb);
|
|
|
|
|
2008-12-26 13:50:35 +00:00
|
|
|
/* create process heap */
|
|
|
|
RtlInitializeHeapManager();
|
|
|
|
Peb->ProcessHeap = RtlCreateHeap(HEAP_GROWABLE,
|
|
|
|
NULL,
|
|
|
|
NTHeaders->OptionalHeader.SizeOfHeapReserve,
|
|
|
|
NTHeaders->OptionalHeader.SizeOfHeapCommit,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
if (Peb->ProcessHeap == 0)
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to create process heap\n");
|
|
|
|
ZwTerminateProcess(NtCurrentProcess(), STATUS_INSUFFICIENT_RESOURCES);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* initialized vectored exception handling */
|
|
|
|
RtlpInitializeVectoredExceptionHandling();
|
|
|
|
|
|
|
|
/* initalize peb lock support */
|
|
|
|
RtlInitializeCriticalSection(&PebLock);
|
|
|
|
Peb->FastPebLock = &PebLock;
|
|
|
|
|
|
|
|
/* initialize tls bitmaps */
|
|
|
|
RtlInitializeBitMap(&TlsBitMap, Peb->TlsBitmapBits, TLS_MINIMUM_AVAILABLE);
|
|
|
|
RtlInitializeBitMap(&TlsExpansionBitMap, Peb->TlsExpansionBitmapBits, TLS_EXPANSION_SLOTS);
|
|
|
|
|
|
|
|
Peb->TlsBitmap = &TlsBitMap;
|
|
|
|
Peb->TlsExpansionBitmap = &TlsExpansionBitMap;
|
|
|
|
Peb->TlsExpansionCounter = TLS_MINIMUM_AVAILABLE;
|
|
|
|
|
|
|
|
/* Initialize table of callbacks for the kernel. */
|
|
|
|
Peb->KernelCallbackTable = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
|
|
0,
|
|
|
|
sizeof(PVOID) *
|
|
|
|
(USER32_CALLBACK_MAXIMUM + 1));
|
|
|
|
if (Peb->KernelCallbackTable == NULL)
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to create callback table\n");
|
|
|
|
ZwTerminateProcess(NtCurrentProcess(), STATUS_INSUFFICIENT_RESOURCES);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* initalize loader lock */
|
|
|
|
RtlInitializeCriticalSection(&LoaderLock);
|
|
|
|
Peb->LoaderLock = &LoaderLock;
|
|
|
|
|
|
|
|
/* create loader information */
|
|
|
|
Peb->Ldr = (PPEB_LDR_DATA) RtlAllocateHeap(Peb->ProcessHeap,
|
|
|
|
0,
|
|
|
|
sizeof(PEB_LDR_DATA));
|
|
|
|
if (Peb->Ldr == NULL)
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to create loader data\n");
|
|
|
|
ZwTerminateProcess(NtCurrentProcess(), STATUS_INSUFFICIENT_RESOURCES);
|
|
|
|
}
|
|
|
|
|
|
|
|
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 */
|
|
|
|
LoadCompatibilitySettings(Peb);
|
|
|
|
|
|
|
|
/* build full ntdll path */
|
|
|
|
wcscpy(FullNtDllPath, SharedUserData->NtSystemRoot);
|
|
|
|
wcscat(FullNtDllPath, L"\\system32\\ntdll.dll");
|
|
|
|
|
|
|
|
/* add entry for ntdll */
|
|
|
|
NtModule = (PLDR_DATA_TABLE_ENTRY)
|
|
|
|
RtlAllocateHeap(Peb->ProcessHeap,
|
|
|
|
0,
|
|
|
|
sizeof(LDR_DATA_TABLE_ENTRY));
|
|
|
|
if (NtModule == NULL)
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to create loader module entry (NTDLL)\n");
|
|
|
|
ZwTerminateProcess(NtCurrentProcess(), STATUS_INSUFFICIENT_RESOURCES);
|
|
|
|
}
|
|
|
|
memset(NtModule, 0, sizeof(LDR_DATA_TABLE_ENTRY));
|
|
|
|
|
|
|
|
NtModule->DllBase = BaseAddress;
|
|
|
|
NtModule->EntryPoint = 0; /* no entry point */
|
|
|
|
RtlCreateUnicodeString(&NtModule->FullDllName, FullNtDllPath);
|
|
|
|
RtlCreateUnicodeString(&NtModule->BaseDllName, L"ntdll.dll");
|
|
|
|
NtModule->Flags = LDRP_IMAGE_DLL | LDRP_ENTRY_PROCESSED;
|
|
|
|
|
|
|
|
NtModule->LoadCount = -1; /* don't unload */
|
|
|
|
NtModule->TlsIndex = -1;
|
|
|
|
NtModule->SectionPointer = NULL;
|
|
|
|
NtModule->CheckSum = 0;
|
|
|
|
|
|
|
|
NTHeaders = RtlImageNtHeader(NtModule->DllBase);
|
|
|
|
NtModule->SizeOfImage = LdrpGetResidentSize(NTHeaders);
|
|
|
|
NtModule->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp;
|
|
|
|
|
|
|
|
InsertTailList(&Peb->Ldr->InLoadOrderModuleList,
|
|
|
|
&NtModule->InLoadOrderLinks);
|
|
|
|
InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
|
|
|
|
&NtModule->InInitializationOrderModuleList);
|
2000-09-01 17:09:50 +00:00
|
|
|
|
2008-12-26 13:50:35 +00:00
|
|
|
/* add entry for executable (becomes first list entry) */
|
|
|
|
ExeModule = (PLDR_DATA_TABLE_ENTRY)
|
|
|
|
RtlAllocateHeap(Peb->ProcessHeap,
|
2010-10-12 09:03:39 +00:00
|
|
|
HEAP_ZERO_MEMORY,
|
2008-12-26 13:50:35 +00:00
|
|
|
sizeof(LDR_DATA_TABLE_ENTRY));
|
|
|
|
if (ExeModule == NULL)
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to create loader module infomation\n");
|
|
|
|
ZwTerminateProcess(NtCurrentProcess(), STATUS_INSUFFICIENT_RESOURCES);
|
|
|
|
}
|
|
|
|
|
|
|
|
ExeModule->DllBase = Peb->ImageBaseAddress;
|
|
|
|
|
|
|
|
if ((Peb->ProcessParameters == NULL) ||
|
|
|
|
(Peb->ProcessParameters->ImagePathName.Length == 0))
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to access the process parameter block\n");
|
|
|
|
ZwTerminateProcess(NtCurrentProcess(), STATUS_UNSUCCESSFUL);
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlCreateUnicodeString(&ExeModule->FullDllName,
|
|
|
|
Peb->ProcessParameters->ImagePathName.Buffer);
|
|
|
|
RtlCreateUnicodeString(&ExeModule->BaseDllName,
|
|
|
|
wcsrchr(ExeModule->FullDllName.Buffer, L'\\') + 1);
|
|
|
|
|
|
|
|
DPRINT("BaseDllName '%wZ' FullDllName '%wZ'\n", &ExeModule->BaseDllName, &ExeModule->FullDllName);
|
|
|
|
|
|
|
|
ExeModule->Flags = LDRP_ENTRY_PROCESSED;
|
|
|
|
ExeModule->LoadCount = -1; /* don't unload */
|
|
|
|
ExeModule->TlsIndex = -1;
|
|
|
|
ExeModule->SectionPointer = NULL;
|
|
|
|
ExeModule->CheckSum = 0;
|
|
|
|
|
|
|
|
NTHeaders = RtlImageNtHeader(ExeModule->DllBase);
|
|
|
|
ExeModule->SizeOfImage = LdrpGetResidentSize(NTHeaders);
|
|
|
|
ExeModule->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp;
|
|
|
|
|
2009-09-11 07:12:30 +00:00
|
|
|
LdrpTopLevelDllBeingLoadedTeb = NtCurrentTeb();
|
|
|
|
|
2008-12-26 13:50:35 +00:00
|
|
|
InsertHeadList(&Peb->Ldr->InLoadOrderModuleList,
|
|
|
|
&ExeModule->InLoadOrderLinks);
|
|
|
|
|
|
|
|
LdrpInitLoader();
|
2003-05-12 19:47:53 +00:00
|
|
|
|
2008-12-26 13:50:35 +00:00
|
|
|
EntryPoint = LdrPEStartup((PVOID)ImageBase, NULL, NULL, NULL);
|
|
|
|
ExeModule->EntryPoint = EntryPoint;
|
2000-09-01 17:09:50 +00:00
|
|
|
|
2008-12-26 13:50:35 +00:00
|
|
|
/* all required dlls are loaded now */
|
|
|
|
Peb->Ldr->Initialized = TRUE;
|
2000-09-01 17:09:50 +00:00
|
|
|
|
2008-12-26 13:50:35 +00:00
|
|
|
/* Check before returning that we can run the image safely. */
|
|
|
|
if (EntryPoint == NULL)
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to initialize image\n");
|
|
|
|
ZwTerminateProcess(NtCurrentProcess(), STATUS_INVALID_IMAGE_FORMAT);
|
|
|
|
}
|
2008-06-27 09:50:52 +00:00
|
|
|
|
2008-12-26 13:50:35 +00:00
|
|
|
/* Break into debugger */
|
|
|
|
if (Peb->BeingDebugged)
|
|
|
|
DbgBreakPoint();
|
2008-12-28 12:32:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
LdrpInit(PCONTEXT Context,
|
|
|
|
PVOID SystemArgument1,
|
|
|
|
PVOID SystemArgument2)
|
|
|
|
{
|
|
|
|
if (!LdrpInitialized)
|
|
|
|
{
|
|
|
|
if (!_InterlockedExchange(&LdrpInitLock, 1))
|
|
|
|
{
|
|
|
|
LdrpInit2(Context, SystemArgument1, SystemArgument2);
|
|
|
|
LdrpInitialized = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LARGE_INTEGER Interval = {{-200000, -1}};
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
NtDelayExecution(FALSE, &Interval);
|
|
|
|
}
|
|
|
|
while (!LdrpInitialized);
|
|
|
|
}
|
|
|
|
}
|
2008-06-27 09:50:52 +00:00
|
|
|
|
2008-12-26 13:50:35 +00:00
|
|
|
/* attach the thread */
|
|
|
|
RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock);
|
|
|
|
LdrpAttachThread();
|
|
|
|
RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
|
1999-03-19 05:55:55 +00:00
|
|
|
}
|
1999-08-29 06:59:11 +00:00
|
|
|
|
|
|
|
/* EOF */
|