[NTDLL/LDR]

- The long awaited LDR rewrite, a commit for testing the new implementation. In case of serious problems it may be reverted (revert should be approved by me).
- Its features include:
* A proper ...everything. Process, thread initialization codes, DLL loading (including compatible path lookup, and compatible/proper loading order of the dependent DLLs, including their initialization) and mapping and section creation, reference counting, relocations, good and understandable PE code for walking import descriptor, snapping, etc etc. Hacks--; GoodCode++;
* Activation contexts operations are now being performed compatible to how Windows performs them (though the actual actctx implementation is still Wine's, it was modified to be compatible). Previously, actctx stuff was added to the ldr code like a pepper is added to the soup: in different places until it starts to work.
* Partial DLL redirection implementation.
* Possibility to support Shim engine and app compat stuff in future.
* More cool stuff, just browse the code.
- I fixed all regressions I could find but one (hang during shutdown of the 3rd stage). The purpose of this commit is to seek and destroy the regressions I couldn't find (if there are any).
- Some of the old rarely called ldr code still remains in startup.c and utils.c. They are subject to be rewritten/removed soon, and every remaining old function is marked with a respective DPRINT1 to see when it's being called.

svn path=/trunk/; revision=52446
This commit is contained in:
Aleksey Bragin 2011-06-24 21:30:09 +00:00
parent 39b4073643
commit 2d89dd3da3
9 changed files with 2853 additions and 2443 deletions

View file

@ -10,6 +10,11 @@
#define LDR_HASH_TABLE_ENTRIES 32
/* LdrpUpdateLoadCount2 flags */
#define LDRP_UPDATE_REFCOUNT 0x01
#define LDRP_UPDATE_DEREFCOUNT 0x02
#define LDRP_UPDATE_PIN 0x03
typedef struct _LDRP_TLS_DATA
{
LIST_ENTRY TlsLinks;
@ -27,10 +32,21 @@ extern BOOLEAN LdrpInLdrInit;
extern LIST_ENTRY LdrpHashTable[LDR_HASH_TABLE_ENTRIES];
extern BOOLEAN ShowSnaps;
extern UNICODE_STRING LdrpDefaultPath;
extern HANDLE LdrpKnownDllObjectDirectory;
extern ULONG LdrpNumberOfProcessors;
extern ULONG LdrpFatalHardErrorCount;
extern PUNICODE_STRING LdrpTopLevelDllBeingLoaded;
extern PLDR_DATA_TABLE_ENTRY LdrpCurrentDllInitializer;
extern UNICODE_STRING LdrApiDefaultExtension;
extern BOOLEAN LdrpLdrDatabaseIsSetup;
extern ULONG LdrpActiveUnloadCount;
extern BOOLEAN LdrpShutdownInProgress;
extern UNICODE_STRING LdrpKnownDllPath;
extern PLDR_DATA_TABLE_ENTRY LdrpGetModuleHandleCache;
/* ldrinit.c */
NTSTATUS NTAPI LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL);
NTSTATUS NTAPI LdrpInitializeThread(IN PCONTEXT Context);
VOID NTAPI LdrpInitializeThread(IN PCONTEXT Context);
NTSTATUS NTAPI LdrpInitializeTls(VOID);
NTSTATUS NTAPI LdrpAllocateTls(VOID);
VOID NTAPI LdrpFreeTls(VOID);
@ -38,7 +54,7 @@ VOID NTAPI LdrpTlsCallback(PVOID BaseAddress, ULONG Reason);
BOOLEAN NTAPI LdrpCallDllEntry(PDLLMAIN_FUNC EntryPoint, PVOID BaseAddress, ULONG Reason, PVOID Context);
NTSTATUS NTAPI LdrpInitializeProcess(PCONTEXT Context, PVOID SystemArgument1);
VOID NTAPI LdrpInitFailure(NTSTATUS Status);
VOID NTAPI LdrpValidateImageForMp(IN PLDR_DATA_TABLE_ENTRY LdrDataTableEntry);
/* ldrpe.c */
NTSTATUS
@ -79,6 +95,10 @@ LdrpLoadDll(IN BOOLEAN Redirected,
OUT PVOID *BaseAddress,
IN BOOLEAN CallInit);
VOID NTAPI
LdrpUpdateLoadCount2(IN PLDR_DATA_TABLE_ENTRY LdrEntry,
IN ULONG Flags);
ULONG NTAPI
LdrpClearLoadInProgress();
@ -101,6 +121,9 @@ LdrpMapDll(IN PWSTR SearchPath OPTIONAL,
PVOID NTAPI
LdrpFetchAddressOfEntryPoint(PVOID ImageBase);
BOOLEAN NTAPI
LdrpFreeUnicodeString(PUNICODE_STRING String);
/* FIXME: Cleanup this mess */
typedef NTSTATUS (NTAPI *PEPFUNC)(PPEB);
@ -110,13 +133,8 @@ NTSTATUS LdrMapSections(HANDLE ProcessHandle,
PIMAGE_NT_HEADERS NTHeaders);
NTSTATUS LdrMapNTDllForProcess(HANDLE ProcessHandle,
PHANDLE NTDllSectionHandle);
BOOLEAN LdrMappedAsDataFile(PVOID *BaseAddress);
ULONG
LdrpGetResidentSize(PIMAGE_NT_HEADERS NTHeaders);
PEPFUNC LdrPEStartup (PVOID ImageBase,
HANDLE SectionHandle,
PLDR_DATA_TABLE_ENTRY* Module,
PWSTR FullDosName);
extern HANDLE WindowsApiPort;

View file

@ -16,6 +16,8 @@
/* GLOBALS *******************************************************************/
LONG LdrpLoaderLockAcquisitonCount;
BOOLEAN LdrpShowRecursiveLoads;
UNICODE_STRING LdrApiDefaultExtension = RTL_CONSTANT_STRING(L".DLL");
/* FUNCTIONS *****************************************************************/
@ -242,6 +244,483 @@ Quickie:
return Status;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
LdrLoadDll(IN PWSTR SearchPath OPTIONAL,
IN PULONG DllCharacteristics OPTIONAL,
IN PUNICODE_STRING DllName,
OUT PVOID *BaseAddress)
{
WCHAR StringBuffer[MAX_PATH];
UNICODE_STRING DllString1, DllString2;
BOOLEAN RedirectedDll = FALSE;
NTSTATUS Status;
ULONG Cookie;
PUNICODE_STRING OldTldDll;
PTEB Teb = NtCurrentTeb();
/* Initialize the strings */
RtlInitUnicodeString(&DllString2, NULL);
DllString1.Buffer = StringBuffer;
DllString1.Length = 0;
DllString1.MaximumLength = sizeof(StringBuffer);
/* Check if the SxS Assemblies specify another file */
Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
DllName,
&LdrApiDefaultExtension,
&DllString1,
&DllString2,
&DllName,
NULL,
NULL,
NULL);
/* Check success */
if (NT_SUCCESS(Status))
{
/* Let Ldrp know */
RedirectedDll = TRUE;
}
else if (Status != STATUS_SXS_KEY_NOT_FOUND)
{
/* Unrecoverable SxS failure; did we get a string? */
if (DllString2.Buffer)
{
/* Free the string */
RtlFreeUnicodeString(&DllString2);
return Status;
}
}
/* Lock the loader lock */
LdrLockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, NULL, &Cookie);
/* Check if there's a TLD DLL being loaded */
if ((OldTldDll = LdrpTopLevelDllBeingLoaded))
{
/* This is a recursive load, do something about it? */
if (ShowSnaps || LdrpShowRecursiveLoads)
{
/* Print out debug messages */
DPRINT1("[%lx, %lx] LDR: Recursive DLL Load\n",
Teb->RealClientId.UniqueProcess,
Teb->RealClientId.UniqueThread);
DPRINT1("[%lx, %lx] Previous DLL being loaded \"%wZ\"\n",
Teb->RealClientId.UniqueProcess,
Teb->RealClientId.UniqueThread,
OldTldDll);
DPRINT1("[%lx, %lx] DLL being requested \"%wZ\"\n",
Teb->RealClientId.UniqueProcess,
Teb->RealClientId.UniqueThread,
DllName);
/* Was it initializing too? */
if (!LdrpCurrentDllInitializer)
{
DPRINT1("[%lx, %lx] LDR: No DLL Initializer was running\n",
Teb->RealClientId.UniqueProcess,
Teb->RealClientId.UniqueThread);
}
else
{
DPRINT1("[%lx, %lx] DLL whose initializer was currently running \"%wZ\"\n",
Teb->ClientId.UniqueProcess,
Teb->ClientId.UniqueThread,
&LdrpCurrentDllInitializer->BaseDllName);
}
}
}
/* Set this one as the TLD DLL being loaded*/
LdrpTopLevelDllBeingLoaded = DllName;
/* Load the DLL */
Status = LdrpLoadDll(RedirectedDll,
SearchPath,
DllCharacteristics,
DllName,
BaseAddress,
TRUE);
/* Set it to success just to be sure */
Status = STATUS_SUCCESS;
/* Restore the old TLD DLL */
LdrpTopLevelDllBeingLoaded = OldTldDll;
/* Release the lock */
LdrUnlockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, Cookie);
/* Do we have a redirect string? */
if (DllString2.Buffer) RtlFreeUnicodeString(&DllString2);
/* Return */
return Status;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
LdrFindEntryForAddress(PVOID Address,
PLDR_DATA_TABLE_ENTRY *Module)
{
PLIST_ENTRY ListHead, NextEntry;
PLDR_DATA_TABLE_ENTRY LdrEntry;
PIMAGE_NT_HEADERS NtHeader;
PPEB_LDR_DATA Ldr = NtCurrentPeb()->Ldr;
ULONG_PTR DllBase, DllEnd;
DPRINT("LdrFindEntryForAddress(Address %p)\n", Address);
/* Nothing to do */
if (!Ldr) return STATUS_NO_MORE_ENTRIES;
/* Loop the module list */
ListHead = &Ldr->InMemoryOrderModuleList;
NextEntry = ListHead->Flink;
while (NextEntry != ListHead)
{
/* Get the entry and NT Headers */
LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderModuleList);
if ((NtHeader = RtlImageNtHeader(LdrEntry->DllBase)))
{
/* Get the Image Base */
DllBase = (ULONG_PTR)LdrEntry->DllBase;
DllEnd = DllBase + NtHeader->OptionalHeader.SizeOfImage;
/* Check if they match */
if (((ULONG_PTR)Address >= DllBase) &&
((ULONG_PTR)Address < DllEnd))
{
/* Return it */
*Module = LdrEntry;
return STATUS_SUCCESS;
}
/* Next Entry */
NextEntry = NextEntry->Flink;
}
}
/* Nothing found */
return STATUS_NO_MORE_ENTRIES;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
LdrGetDllHandleEx(IN ULONG Flags,
IN PWSTR DllPath OPTIONAL,
IN PULONG DllCharacteristics OPTIONAL,
IN PUNICODE_STRING DllName,
OUT PVOID *DllHandle OPTIONAL)
{
NTSTATUS Status = STATUS_DLL_NOT_FOUND;
PLDR_DATA_TABLE_ENTRY LdrEntry;
UNICODE_STRING RedirectName, DllString1;
UNICODE_STRING RawDllName;
PUNICODE_STRING pRedirectName = &RedirectName;
PUNICODE_STRING CompareName;
PWCHAR p1, p2, p3;
BOOLEAN Locked = FALSE;
BOOLEAN RedirectedDll = FALSE;
ULONG Cookie;
ULONG LoadFlag;
/* Initialize the strings */
RtlInitUnicodeString(&DllString1, NULL);
RtlInitUnicodeString(&RawDllName, NULL);
RedirectName = *DllName;
/* Clear the handle */
if (DllHandle) *DllHandle = NULL;
/* Check for a valid flag */
if ((Flags & ~3) || (!DllHandle && !(Flags & 2)))
{
DPRINT1("Flags are invalid or no DllHandle given\n");
return STATUS_INVALID_PARAMETER;
}
/* If not initializing */
if (!LdrpInLdrInit)
{
/* Acquire the lock */
Status = LdrLockLoaderLock(0, NULL, &Cookie);
Locked = TRUE;
}
/* Check if the SxS Assemblies specify another file */
Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
pRedirectName,
&LdrApiDefaultExtension,
NULL,
&DllString1,
&pRedirectName,
NULL,
NULL,
NULL);
/* Check success */
if (NT_SUCCESS(Status))
{
/* Let Ldrp know */
RedirectedDll = TRUE;
}
else if (Status != STATUS_SXS_KEY_NOT_FOUND)
{
/* Unrecoverable SxS failure; */
goto Quickie;
}
/* Use the cache if we can */
if (LdrpGetModuleHandleCache)
{
/* Check if we were redirected */
if (RedirectedDll)
{
/* Check the flag */
if (LdrpGetModuleHandleCache->Flags & LDRP_REDIRECTED)
{
/* Use the right name */
CompareName = &LdrpGetModuleHandleCache->FullDllName;
}
else
{
goto DontCompare;
}
}
else
{
/* Check the flag */
if (!(LdrpGetModuleHandleCache->Flags & LDRP_REDIRECTED))
{
/* Use the right name */
CompareName = &LdrpGetModuleHandleCache->BaseDllName;
}
else
{
goto DontCompare;
}
}
/* Check if the name matches */
if (RtlEqualUnicodeString(pRedirectName,
CompareName,
TRUE))
{
/* Skip the rest */
LdrEntry = LdrpGetModuleHandleCache;
/* Return success */
Status = STATUS_SUCCESS;
goto FoundEntry;
}
}
DontCompare:
/* Find the name without the extension */
p1 = pRedirectName->Buffer;
p3 = &p1[pRedirectName->Length / sizeof(WCHAR)];
StartLoop:
p2 = NULL;
while (p1 != p3)
{
if (*p1++ == L'.')
{
p2 = p1;
}
else if (*p1 == L'\\')
{
goto StartLoop;
}
}
/* Check if no extension was found or if we got a slash */
if (!p2 || *p2 == L'\\' || *p2 == L'/')
{
/* Check that we have space to add one */
if (pRedirectName->Length + LdrApiDefaultExtension.Length >= MAXLONG)
{
/* No space to add the extension */
return STATUS_NAME_TOO_LONG;
}
/* Setup the string */
RawDllName.MaximumLength = pRedirectName->Length + LdrApiDefaultExtension.Length + sizeof(UNICODE_NULL);
RawDllName.Length = RawDllName.MaximumLength - sizeof(UNICODE_NULL);
RawDllName.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
0,
RawDllName.MaximumLength);
/* Copy the buffer */
RtlMoveMemory(RawDllName.Buffer,
pRedirectName->Buffer,
pRedirectName->Length);
/* Add extension */
RtlMoveMemory((PVOID)((ULONG_PTR)RawDllName.Buffer + pRedirectName->Length),
LdrApiDefaultExtension.Buffer,
LdrApiDefaultExtension.Length);
/* Null terminate */
RawDllName.Buffer[RawDllName.Length / sizeof(WCHAR)] = UNICODE_NULL;
}
else
{
/* Check if there's something in the name */
if (pRedirectName->Length)
{
/* Check and remove trailing period */
if (pRedirectName->Buffer[(pRedirectName->Length - 2) /
sizeof(WCHAR)] == '.')
{
/* Decrease the size */
pRedirectName->Length -= sizeof(WCHAR);
}
}
/* Setup the string */
RawDllName.MaximumLength = pRedirectName->Length + sizeof(WCHAR);
RawDllName.Length = pRedirectName->Length;
RawDllName.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
0,
RawDllName.MaximumLength);
/* Copy the buffer */
RtlMoveMemory(RawDllName.Buffer,
pRedirectName->Buffer,
pRedirectName->Length);
/* Null terminate */
RawDllName.Buffer[RawDllName.Length / sizeof(WCHAR)] = UNICODE_NULL;
}
/* Display debug string */
if (ShowSnaps)
{
DPRINT1("LDR: LdrGetDllHandle, searching for %wZ from %ws\n",
&RawDllName,
DllPath ? ((ULONG_PTR)DllPath == 1 ? L"" : DllPath) : L"");
}
/* Do the lookup */
if (LdrpCheckForLoadedDll(DllPath,
&RawDllName,
((ULONG_PTR)DllPath == 1) ? TRUE : FALSE,
RedirectedDll,
&LdrEntry))
{
/* Update cached entry */
LdrpGetModuleHandleCache = LdrEntry;
/* Return success */
Status = STATUS_SUCCESS;
}
else
{
/* Make sure to NULL this */
LdrEntry = NULL;
}
FoundEntry:
DPRINT("Got LdrEntry->BaseDllName %wZ\n", LdrEntry ? &LdrEntry->BaseDllName : NULL);
/* Check if we got an entry */
if (LdrEntry)
{
/* Check for success */
if (NT_SUCCESS(Status))
{
/* Check if the DLL is locked */
if (LdrEntry->LoadCount != -1)
{
/* Check what flag we got */
if (!(Flags & 1))
{
/* Check what to do with the load count */
if (Flags & 2)
{
/* Pin it */
LdrEntry->LoadCount = -1;
LoadFlag = LDRP_UPDATE_PIN;
}
else
{
/* Increase the load count */
LdrEntry->LoadCount++;
LoadFlag = LDRP_UPDATE_REFCOUNT;
}
/* Update the load count now */
LdrpUpdateLoadCount2(LdrEntry, LoadFlag);
LdrpClearLoadInProgress();
}
}
/* Check if the caller is requesting the handle */
if (DllHandle) *DllHandle = LdrEntry->DllBase;
}
}
Quickie:
/* Free string if needed */
if (DllString1.Buffer) RtlFreeUnicodeString(&DllString1);
/* Free the raw DLL Name if needed */
if (RawDllName.Buffer)
{
/* Free the heap-allocated buffer */
RtlFreeHeap(RtlGetProcessHeap(), 0, RawDllName.Buffer);
RawDllName.Buffer = NULL;
}
/* Release lock */
if (Locked) LdrUnlockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, Cookie);
/* Return */
return Status;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
LdrGetDllHandle(IN PWSTR DllPath OPTIONAL,
IN PULONG DllCharacteristics OPTIONAL,
IN PUNICODE_STRING DllName,
OUT PVOID *DllHandle)
{
/* Call the newer API */
return LdrGetDllHandleEx(TRUE,
DllPath,
DllCharacteristics,
DllName,
DllHandle);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
LdrGetProcedureAddress(IN PVOID BaseAddress,
IN PANSI_STRING Name,
IN ULONG Ordinal,
OUT PVOID *ProcedureAddress)
{
/* Call the internal routine and tell it to execute DllInit */
return LdrpGetProcedureAddress(BaseAddress, Name, Ordinal, ProcedureAddress, TRUE);
}
/*
* @implemented
*/
@ -374,21 +853,6 @@ LdrVerifyImageMatchesChecksum(IN HANDLE FileHandle,
return !Result ? STATUS_IMAGE_CHECKSUM_MISMATCH : Status;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
LdrGetProcedureAddress_(IN PVOID BaseAddress,
IN PANSI_STRING Name,
IN ULONG Ordinal,
OUT PVOID *ProcedureAddress)
{
/* Call the internal routine and tell it to execute DllInit */
return LdrpGetProcedureAddress(BaseAddress, Name, Ordinal, ProcedureAddress, TRUE);
}
NTSTATUS
NTAPI
LdrQueryProcessModuleInformationEx(IN ULONG ProcessId,

View file

@ -10,9 +10,12 @@
/* INCLUDES *****************************************************************/
#include <ntdll.h>
#include <win32k/callback.h>
#define NDEBUG
#include <debug.h>
/* GLOBALS *******************************************************************/
HKEY ImageExecOptionsKey;
@ -25,11 +28,14 @@ BOOLEAN LdrpInLdrInit;
LONG LdrpProcessInitialized;
BOOLEAN LdrpLoaderLockInit;
BOOLEAN LdrpLdrDatabaseIsSetup;
BOOLEAN LdrpShutdownInProgress;
HANDLE LdrpShutdownThreadId;
BOOLEAN LdrpDllValidation;
PLDR_DATA_TABLE_ENTRY LdrpImageEntry;
PUNICODE_STRING LdrpTopLevelDllBeingLoaded;
WCHAR StringBuffer[156];
extern PTEB LdrpTopLevelDllBeingLoadedTeb; // defined in rtlsupp.c!
PLDR_DATA_TABLE_ENTRY LdrpCurrentDllInitializer;
PLDR_DATA_TABLE_ENTRY LdrpNtDllDataTableEntry;
@ -68,6 +74,7 @@ RTL_CRITICAL_SECTION FastPebLock;
BOOLEAN ShowSnaps;
ULONG LdrpFatalHardErrorCount;
ULONG LdrpActiveUnloadCount;
//extern LIST_ENTRY RtlCriticalSectionList;
@ -78,10 +85,12 @@ extern BOOLEAN RtlpPageHeapEnabled;
extern ULONG RtlpDphGlobalFlags;
NTSTATUS LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders, PVOID ImageBase);
NTSTATUS NTAPI
LdrpInitializeProcess_(PCONTEXT Context,
PVOID SystemArgument1);
#ifdef _WIN64
#define DEFAULT_SECURITY_COOKIE 0x00002B992DDFA232ll
#else
#define DEFAULT_SECURITY_COOKIE 0xBB40E64E
#endif
/* FUNCTIONS *****************************************************************/
@ -414,8 +423,7 @@ LdrpFetchAddressOfSecurityCookie(PVOID BaseAddress, ULONG SizeOfImage)
Cookie = (PVOID)ConfigDir->SecurityCookie;
/* Check this cookie */
if (Cookie == NULL ||
(PCHAR)Cookie <= (PCHAR)BaseAddress ||
if ((PCHAR)Cookie <= (PCHAR)BaseAddress ||
(PCHAR)Cookie >= (PCHAR)BaseAddress + SizeOfImage)
{
Cookie = NULL;
@ -429,20 +437,178 @@ PVOID
NTAPI
LdrpInitSecurityCookie(PLDR_DATA_TABLE_ENTRY LdrEntry)
{
PVOID Cookie;
PULONG_PTR Cookie;
LARGE_INTEGER Counter;
//ULONG NewCookie;
/* Fetch address of the cookie */
Cookie = LdrpFetchAddressOfSecurityCookie(LdrEntry->DllBase, LdrEntry->SizeOfImage);
if (Cookie)
{
UNIMPLEMENTED;
Cookie = NULL;
/* Check if it's a default one */
if (*Cookie == DEFAULT_SECURITY_COOKIE ||
*Cookie == 0xBB40)
{
/* We need to initialize it */
NtQueryPerformanceCounter(&Counter, NULL);
#if 0
GetSystemTimeAsFileTime (&systime.ft_struct);
#ifdef _WIN64
cookie = systime.ft_scalar;
#else
cookie = systime.ft_struct.dwLowDateTime;
cookie ^= systime.ft_struct.dwHighDateTime;
#endif
cookie ^= GetCurrentProcessId ();
cookie ^= GetCurrentThreadId ();
cookie ^= GetTickCount ();
QueryPerformanceCounter (&perfctr);
#ifdef _WIN64
cookie ^= perfctr.QuadPart;
#else
cookie ^= perfctr.LowPart;
cookie ^= perfctr.HighPart;
#endif
#ifdef _WIN64
cookie &= 0x0000ffffffffffffll;
#endif
#endif
*Cookie = Counter.LowPart;
//Cookie = NULL;
}
}
return Cookie;
}
VOID
NTAPI
LdrpInitializeThread(IN PCONTEXT Context)
{
PPEB Peb = NtCurrentPeb();
PLDR_DATA_TABLE_ENTRY LdrEntry;
PLIST_ENTRY NextEntry, ListHead;
RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx;
NTSTATUS Status;
PVOID EntryPoint;
DPRINT("LdrpInitializeThread() called for %wZ\n",
&LdrpImageEntry->BaseDllName);
/* Allocate an Activation Context Stack */
/* FIXME: This is a hack for Wine's actctx stuff */
DPRINT("ActivationContextStack %p\n", NtCurrentTeb()->ActivationContextStackPointer);
if (!(NtCurrentTeb()->ActivationContextStackPointer))
{
Status = RtlAllocateActivationContextStack((PVOID*)&NtCurrentTeb()->ActivationContextStackPointer);
if (NT_SUCCESS(Status))
{
DPRINT("ActivationContextStack %p\n", NtCurrentTeb()->ActivationContextStackPointer);
DPRINT("ActiveFrame %p\n", ((PACTIVATION_CONTEXT_STACK)NtCurrentTeb()->ActivationContextStackPointer)->ActiveFrame);
NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NULL;
}
else
DPRINT1("Warning: Unable to allocate ActivationContextStack\n");
}
/* Make sure we are not shutting down */
if (LdrpShutdownInProgress) return;
/* Allocate TLS */
LdrpAllocateTls();
/* Start at the beginning */
ListHead = &Peb->Ldr->InMemoryOrderModuleList;
NextEntry = ListHead->Flink;
while (NextEntry != ListHead)
{
/* Get the current entry */
LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderModuleList);
/* Make sure it's not ourselves */
if (Peb->ImageBaseAddress != LdrEntry->DllBase)
{
/* Check if we should call */
if (!(LdrEntry->Flags & LDRP_DONT_CALL_FOR_THREADS))
{
/* Get the entrypoint */
EntryPoint = LdrEntry->EntryPoint;
/* Check if we are ready to call it */
if ((EntryPoint) &&
(LdrEntry->Flags & LDRP_PROCESS_ATTACH_CALLED) &&
(LdrEntry->Flags & LDRP_IMAGE_DLL))
{
/* Set up the Act Ctx */
ActCtx.Size = sizeof(ActCtx);
ActCtx.Format = 1;
RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
/* Activate the ActCtx */
RtlActivateActivationContextUnsafeFast(&ActCtx,
LdrEntry->EntryPointActivationContext);
/* Check if it has TLS */
if (LdrEntry->TlsIndex)
{
/* Make sure we're not shutting down */
if (!LdrpShutdownInProgress)
{
/* Call TLS */
LdrpTlsCallback(LdrEntry->DllBase, DLL_THREAD_ATTACH);
}
}
/* Make sure we're not shutting down */
if (!LdrpShutdownInProgress)
{
/* Call the Entrypoint */
DPRINT("%wZ - Calling entry point at %x for thread attaching\n",
&LdrEntry->BaseDllName, LdrEntry->EntryPoint);
LdrpCallDllEntry(LdrEntry->EntryPoint,
LdrEntry->DllBase,
DLL_THREAD_ATTACH,
NULL);
}
/* Deactivate the ActCtx */
RtlDeactivateActivationContextUnsafeFast(&ActCtx);
}
}
}
/* Next entry */
NextEntry = NextEntry->Flink;
}
/* Check for TLS */
if (LdrpImageHasTls && !LdrpShutdownInProgress)
{
/* Set up the Act Ctx */
ActCtx.Size = sizeof(ActCtx);
ActCtx.Format = 1;
RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
/* Activate the ActCtx */
RtlActivateActivationContextUnsafeFast(&ActCtx,
LdrpImageEntry->EntryPointActivationContext);
/* Do TLS callbacks */
LdrpTlsCallback(Peb->ImageBaseAddress, DLL_THREAD_ATTACH);
/* Deactivate the ActCtx */
RtlDeactivateActivationContextUnsafeFast(&ActCtx);
}
DPRINT("LdrpInitializeThread() done\n");
}
NTSTATUS
NTAPI
LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL)
@ -715,6 +881,267 @@ Quickie:
return Status;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
LdrShutdownProcess(VOID)
{
PPEB Peb = NtCurrentPeb();
PLDR_DATA_TABLE_ENTRY LdrEntry;
PLIST_ENTRY NextEntry, ListHead;
RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx;
PVOID EntryPoint;
DPRINT("LdrShutdownProcess() called for %wZ\n", &LdrpImageEntry->BaseDllName);
if (LdrpShutdownInProgress) return STATUS_SUCCESS;
/* Tell the Shim Engine */
//if (ShimsEnabled)
//{
/* FIXME */
//}
/* Tell the world */
if (ShowSnaps)
{
DPRINT1("\n");
}
/* Set the shutdown variables */
LdrpShutdownThreadId = NtCurrentTeb()->RealClientId.UniqueThread;
LdrpShutdownInProgress = TRUE;
/* Enter the Loader Lock */
RtlEnterCriticalSection(&LdrpLoaderLock);
/* Cleanup trace logging data (Etw) */
if (SharedUserData->TraceLogging)
{
/* FIXME */
DPRINT1("We don't support Etw yet.\n");
}
/* Start at the end */
ListHead = &Peb->Ldr->InInitializationOrderModuleList;
NextEntry = ListHead->Blink;
while (NextEntry != ListHead)
{
/* Get the current entry */
LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
NextEntry = NextEntry->Blink;
/* Make sure it's not ourselves */
if (Peb->ImageBaseAddress != LdrEntry->DllBase)
{
/* Get the entrypoint */
EntryPoint = LdrEntry->EntryPoint;
/* Check if we are ready to call it */
if (EntryPoint &&
(LdrEntry->Flags & LDRP_PROCESS_ATTACH_CALLED) &&
LdrEntry->Flags)
{
/* Set up the Act Ctx */
ActCtx.Size = sizeof(ActCtx);
ActCtx.Format = 1;
RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
/* Activate the ActCtx */
RtlActivateActivationContextUnsafeFast(&ActCtx,
LdrEntry->EntryPointActivationContext);
/* Check if it has TLS */
if (LdrEntry->TlsIndex)
{
/* Call TLS */
LdrpTlsCallback(LdrEntry->DllBase, DLL_PROCESS_DETACH);
}
/* Call the Entrypoint */
DPRINT("%wZ - Calling entry point at %x for thread detaching\n",
&LdrEntry->BaseDllName, LdrEntry->EntryPoint);
LdrpCallDllEntry(EntryPoint,
LdrEntry->DllBase,
DLL_PROCESS_DETACH,
(PVOID)1);
/* Deactivate the ActCtx */
RtlDeactivateActivationContextUnsafeFast(&ActCtx);
}
}
}
/* Check for TLS */
if (LdrpImageHasTls)
{
/* Set up the Act Ctx */
ActCtx.Size = sizeof(ActCtx);
ActCtx.Format = 1;
RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
/* Activate the ActCtx */
RtlActivateActivationContextUnsafeFast(&ActCtx,
LdrpImageEntry->EntryPointActivationContext);
/* Do TLS callbacks */
LdrpTlsCallback(Peb->ImageBaseAddress, DLL_PROCESS_DETACH);
/* Deactivate the ActCtx */
RtlDeactivateActivationContextUnsafeFast(&ActCtx);
}
/* FIXME: Do Heap detection and Etw final shutdown */
/* Release the lock */
RtlLeaveCriticalSection(&LdrpLoaderLock);
DPRINT("LdrpShutdownProcess() done\n");
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
LdrShutdownThread(VOID)
{
PPEB Peb = NtCurrentPeb();
PTEB Teb = NtCurrentTeb();
PLDR_DATA_TABLE_ENTRY LdrEntry;
PLIST_ENTRY NextEntry, ListHead;
RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx;
PVOID EntryPoint;
DPRINT("LdrShutdownThread() called for %wZ\n",
&LdrpImageEntry->BaseDllName);
/* Cleanup trace logging data (Etw) */
if (SharedUserData->TraceLogging)
{
/* FIXME */
DPRINT1("We don't support Etw yet.\n");
}
/* Get the Ldr Lock */
RtlEnterCriticalSection(&LdrpLoaderLock);
/* Start at the end */
ListHead = &Peb->Ldr->InInitializationOrderModuleList;
NextEntry = ListHead->Blink;
while (NextEntry != ListHead)
{
/* Get the current entry */
LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
NextEntry = NextEntry->Blink;
/* Make sure it's not ourselves */
if (Peb->ImageBaseAddress != LdrEntry->DllBase)
{
/* Check if we should call */
if (!(LdrEntry->Flags & LDRP_DONT_CALL_FOR_THREADS) &&
(LdrEntry->Flags & LDRP_PROCESS_ATTACH_CALLED) &&
(LdrEntry->Flags & LDRP_IMAGE_DLL))
{
/* Get the entrypoint */
EntryPoint = LdrEntry->EntryPoint;
/* Check if we are ready to call it */
if (EntryPoint)
{
/* Set up the Act Ctx */
ActCtx.Size = sizeof(ActCtx);
ActCtx.Format = 1;
RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
/* Activate the ActCtx */
RtlActivateActivationContextUnsafeFast(&ActCtx,
LdrEntry->EntryPointActivationContext);
/* Check if it has TLS */
if (LdrEntry->TlsIndex)
{
/* Make sure we're not shutting down */
if (!LdrpShutdownInProgress)
{
/* Call TLS */
LdrpTlsCallback(LdrEntry->DllBase, DLL_THREAD_DETACH);
}
}
/* Make sure we're not shutting down */
if (!LdrpShutdownInProgress)
{
/* Call the Entrypoint */
DPRINT("%wZ - Calling entry point at %x for thread detaching\n",
&LdrEntry->BaseDllName, LdrEntry->EntryPoint);
LdrpCallDllEntry(EntryPoint,
LdrEntry->DllBase,
DLL_THREAD_DETACH,
NULL);
}
/* Deactivate the ActCtx */
RtlDeactivateActivationContextUnsafeFast(&ActCtx);
}
}
}
}
/* Check for TLS */
if (LdrpImageHasTls)
{
/* Set up the Act Ctx */
ActCtx.Size = sizeof(ActCtx);
ActCtx.Format = 1;
RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
/* Activate the ActCtx */
RtlActivateActivationContextUnsafeFast(&ActCtx,
LdrpImageEntry->EntryPointActivationContext);
/* Do TLS callbacks */
LdrpTlsCallback(Peb->ImageBaseAddress, DLL_THREAD_DETACH);
/* Deactivate the ActCtx */
RtlDeactivateActivationContextUnsafeFast(&ActCtx);
}
/* Free TLS */
LdrpFreeTls();
RtlLeaveCriticalSection(&LdrpLoaderLock);
/* Check for expansion slots */
if (Teb->TlsExpansionSlots)
{
/* Free expansion slots */
RtlFreeHeap(RtlGetProcessHeap(), 0, Teb->TlsExpansionSlots);
}
/* Check for FLS Data */
if (Teb->FlsData)
{
/* FIXME */
DPRINT1("We don't support FLS Data yet\n");
}
/* Check for Fiber data */
if (Teb->HasFiberData)
{
/* Free Fiber data*/
RtlFreeHeap(RtlGetProcessHeap(), 0, Teb->NtTib.FiberData);
Teb->NtTib.FiberData = NULL;
}
/* Free the activation context stack */
RtlFreeThreadActivationContextStack();
DPRINT("LdrShutdownThread() done\n");
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
LdrpInitializeTls(VOID)
@ -879,10 +1306,10 @@ LdrpFreeTls(VOID)
NTSTATUS
NTAPI
LdrpInitializeExecutionOptions(PUNICODE_STRING ImagePathName, PPEB Peb, PULONG Options)
LdrpInitializeExecutionOptions(PUNICODE_STRING ImagePathName, PPEB Peb, PHKEY OptionsKey)
{
UNIMPLEMENTED;
*Options = 0;
*OptionsKey = NULL;
return STATUS_SUCCESS;
}
@ -915,7 +1342,7 @@ LdrpInitializeProcess(IN PCONTEXT Context,
//LPWSTR ImagePathBuffer;
ULONG ConfigSize;
UNICODE_STRING CurrentDirectory;
ULONG ExecuteOptions;
HKEY OptionsKey;
ULONG HeapFlags;
PIMAGE_NT_HEADERS NtHeader;
LPWSTR NtDllName = NULL;
@ -928,9 +1355,9 @@ LdrpInitializeProcess(IN PCONTEXT Context,
ULONG i;
PWSTR ImagePath;
ULONG DebugProcessHeapOnly = 0;
WCHAR FullNtDllPath[MAX_PATH];
PLDR_DATA_TABLE_ENTRY NtLdrEntry;
PWCHAR Current;
ULONG ExecuteOptions = 0;
/* Set a NULL SEH Filter */
RtlSetUnhandledExceptionFilter(NULL);
@ -954,7 +1381,7 @@ LdrpInitializeProcess(IN PCONTEXT Context,
NtHeader = RtlImageNtHeader(Peb->ImageBaseAddress);
/* Get the execution options */
Status = LdrpInitializeExecutionOptions(&ImagePathName, Peb, &ExecuteOptions);
Status = LdrpInitializeExecutionOptions(&ImagePathName, Peb, &OptionsKey);
/* Check if this is a .NET executable */
if (RtlImageDirectoryEntryToData(Peb->ImageBaseAddress,
@ -1040,7 +1467,7 @@ LdrpInitializeProcess(IN PCONTEXT Context,
}
/* Check if verbose debugging (ShowSnaps) was requested */
ShowSnaps = TRUE;//Peb->NtGlobalFlag & FLG_SHOW_LDR_SNAPS;
ShowSnaps = Peb->NtGlobalFlag & FLG_SHOW_LDR_SNAPS;
/* Start verbose debugging messages right now if they were requested */
if (ShowSnaps)
@ -1091,9 +1518,11 @@ LdrpInitializeProcess(IN PCONTEXT Context,
}
/* Initialize the Loader Lock */
// FIXME: What's the point of initing it manually, if two lines lower
// a call to RtlInitializeCriticalSection() is being made anyway?
//InsertTailList(&RtlCriticalSectionList, &LdrpLoaderLock.DebugInfo->ProcessLocksList);
//LdrpLoaderLock.DebugInfo->CriticalSection = &LdrpLoaderLock;
UNIMPLEMENTED;
RtlInitializeCriticalSection(&LdrpLoaderLock);
LdrpLoaderLockInit = TRUE;
/* Check if User Stack Trace Database support was requested */
@ -1134,19 +1563,30 @@ LdrpInitializeProcess(IN PCONTEXT Context,
return STATUS_NO_MEMORY;
}
// FIXME: Is it located properly?
/* Initialize table of callbacks for the kernel. */
Peb->KernelCallbackTable = RtlAllocateHeap(RtlGetProcessHeap(),
0,
sizeof(PVOID) *
(USER32_CALLBACK_MAXIMUM + 1));
if (!Peb->KernelCallbackTable)
{
DPRINT1("Failed to create callback table\n");
ZwTerminateProcess(NtCurrentProcess(), STATUS_INSUFFICIENT_RESOURCES);
}
/* 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");
//DPRINT1("Loader private heap is missing\n");
/* Check for Debug Heap */
DPRINT1("Check for a debug heap is missing\n");
if (FALSE)
if (OptionsKey)
{
/* Query the setting */
Status = LdrQueryImageFileKeyOption(NULL,//hKey
Status = LdrQueryImageFileKeyOption(OptionsKey,
L"DebugProcessHeapOnly",
REG_DWORD,
&DebugProcessHeapOnly,
@ -1165,9 +1605,9 @@ LdrpInitializeProcess(IN PCONTEXT Context,
}
/* Build the NTDLL Path */
FullPath.Buffer = FullNtDllPath;
FullPath.Buffer = StringBuffer;
FullPath.Length = 0;
FullPath.MaximumLength = sizeof(FullNtDllPath);
FullPath.MaximumLength = sizeof(StringBuffer);
RtlInitUnicodeString(&NtSystemRoot, SharedUserData->NtSystemRoot);
RtlAppendUnicodeStringToString(&FullPath, &NtSystemRoot);
RtlAppendUnicodeToString(&FullPath, L"\\System32\\");
@ -1188,7 +1628,7 @@ LdrpInitializeProcess(IN PCONTEXT Context,
{
/* It doesn't, so assume System32 */
LdrpKnownDllObjectDirectory = NULL;
RtlInitUnicodeString(&LdrpKnownDllPath, FullPath.Buffer);
RtlInitUnicodeString(&LdrpKnownDllPath, StringBuffer);
LdrpKnownDllPath.Length -= sizeof(WCHAR);
}
else
@ -1230,6 +1670,7 @@ LdrpInitializeProcess(IN PCONTEXT Context,
else
{
/* We need a valid path */
DPRINT1("No valid DllPath was given!\n");
LdrpInitFailure(STATUS_INVALID_PARAMETER);
}
@ -1246,6 +1687,11 @@ LdrpInitializeProcess(IN PCONTEXT Context,
0,
3 * sizeof(WCHAR) +
sizeof(UNICODE_NULL));
if (!CurrentDirectory.Buffer)
{
DPRINT1("LDR: LdrpInitializeProcess - unable to allocate current working directory buffer\n");
// FIXME: And what?
}
/* Copy the drive of the system root */
RtlMoveMemory(CurrentDirectory.Buffer,
@ -1256,12 +1702,12 @@ LdrpInitializeProcess(IN PCONTEXT Context,
CurrentDirectory.MaximumLength = CurrentDirectory.Length + sizeof(WCHAR);
FreeCurDir = TRUE;
DPRINT("Using dynamically allocd curdir\n");
}
else
{
/* Use the local buffer */
CurrentDirectory.Length = NtSystemRoot.Length;
CurrentDirectory.Buffer = NtSystemRoot.Buffer;
DPRINT("Using local system root\n");
}
}
@ -1280,8 +1726,8 @@ LdrpInitializeProcess(IN PCONTEXT Context,
NtLdrEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(NtLdrEntry->DllBase);
NtLdrEntry->LoadCount = -1;
NtLdrEntry->EntryPointActivationContext = 0;
NtLdrEntry->FullDllName.Length = ImageFileName.Length;
NtLdrEntry->FullDllName.Buffer = ImageFileName.Buffer;
NtLdrEntry->FullDllName = ImageFileName;
if (IsDotNetImage)
NtLdrEntry->Flags = LDRP_COR_IMAGE;
else
@ -1291,7 +1737,7 @@ LdrpInitializeProcess(IN PCONTEXT Context,
if (!ImageFileName.Buffer[0])
{
/* Use the same Base name */
NtLdrEntry->BaseDllName = NtLdrEntry->BaseDllName;
NtLdrEntry->BaseDllName = NtLdrEntry->FullDllName;
}
else
{
@ -1332,14 +1778,16 @@ LdrpInitializeProcess(IN PCONTEXT Context,
NtLdrEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(NtLdrEntry->DllBase);
NtLdrEntry->LoadCount = -1;
NtLdrEntry->EntryPointActivationContext = 0;
//NtLdrEntry->BaseDllName.Length = NtSystemRoot.Length;
//RtlAppendUnicodeStringToString(&NtSystemRoot, &NtDllString);
NtLdrEntry->FullDllName.Length = FullPath.Length;
NtLdrEntry->FullDllName.MaximumLength = FullPath.MaximumLength;
NtLdrEntry->FullDllName.Buffer = StringBuffer;
RtlAppendUnicodeStringToString(&NtLdrEntry->FullDllName, &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);
@ -1510,7 +1958,7 @@ LdrpInitializeProcess(IN PCONTEXT Context,
///* Close the key if we have one opened */
//if (hKey) NtClose(hKey);
DbgBreakPoint();
/* Return status */
return Status;
}
@ -1596,7 +2044,7 @@ LdrpInit(PCONTEXT Context,
_SEH2_TRY
{
/* Initialize the Process */
LoaderStatus = LdrpInitializeProcess_(Context,
LoaderStatus = LdrpInitializeProcess(Context,
SystemArgument1);
/* Check for success and if MinimumStackCommit was requested */

View file

@ -100,9 +100,7 @@ LdrpSnapIAT(IN PLDR_DATA_TABLE_ENTRY ExportLdrEntry,
/* Deal with Watcom and other retarded compilers */
if (!IatSize)
{
IatSize = SectionHeader->SizeOfRawData;
}
/* Found it, get out */
break;
@ -255,7 +253,7 @@ NTSTATUS
NTAPI
LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
IN PLDR_DATA_TABLE_ENTRY LdrEntry,
IN PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundEntry,
IN PIMAGE_BOUND_IMPORT_DESCRIPTOR *BoundEntryPtr,
IN PIMAGE_BOUND_IMPORT_DESCRIPTOR FirstEntry)
{
LPSTR ImportName = NULL, BoundImportName, ForwarderName;
@ -264,11 +262,15 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
PIMAGE_IMPORT_DESCRIPTOR ImportEntry;
PLDR_DATA_TABLE_ENTRY DllLdrEntry, ForwarderLdrEntry;
PIMAGE_BOUND_FORWARDER_REF ForwarderEntry;
PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundEntry;
PPEB Peb = NtCurrentPeb();
ULONG i, IatSize;
/* Get the pointer to the bound entry */
BoundEntry = *BoundEntryPtr;
/* Get the name's VA */
BoundImportName = (LPSTR)(BoundEntry + BoundEntry->OffsetModuleName);
BoundImportName = (LPSTR)FirstEntry + BoundEntry->OffsetModuleName;
/* Show debug mesage */
if (ShowSnaps)
@ -311,7 +313,7 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
if (ShowSnaps)
{
DPRINT1("LDR: %wZ has stale binding to %s\n",
&DllLdrEntry->BaseDllName,
&LdrEntry->BaseDllName,
BoundImportName);
}
@ -324,7 +326,7 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
if (ShowSnaps)
{
DPRINT1("LDR: %wZ has correct binding to %s\n",
&DllLdrEntry->BaseDllName,
&LdrEntry->BaseDllName,
BoundImportName);
}
@ -339,7 +341,7 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
for (i = 0; i < BoundEntry->NumberOfModuleForwarderRefs; i++)
{
/* Get the name */
ForwarderName = (LPSTR)(FirstEntry + ForwarderEntry->OffsetModuleName);
ForwarderName = (LPSTR)FirstEntry + ForwarderEntry->OffsetModuleName;
/* Show debug message */
if (ShowSnaps)
@ -376,7 +378,7 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
if (ShowSnaps)
{
DPRINT1("LDR: %wZ has stale binding to %s\n",
&ForwarderLdrEntry->BaseDllName,
&LdrEntry->BaseDllName,
ForwarderName);
}
@ -389,7 +391,7 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
if (ShowSnaps)
{
DPRINT1("LDR: %wZ has correct binding to %s\n",
&ForwarderLdrEntry->BaseDllName,
&LdrEntry->BaseDllName,
ForwarderName);
}
@ -423,7 +425,7 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
if (!_stricmp(ImportName, BoundImportName)) break;
/* Move to next entry */
ImportEntry += 1;
ImportEntry++;
}
/* If we didn't find a name, fail */
@ -477,7 +479,7 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL,
Quickie:
/* Write where we are now and return */
*BoundEntry = *FirstEntry;
*BoundEntryPtr = FirstEntry;
return Status;
}
@ -496,7 +498,7 @@ LdrpHandleNewFormatImportDescriptors(IN LPWSTR DllPath OPTIONAL,
/* Parse this descriptor */
Status = LdrpHandleOneNewFormatImportDescriptor(DllPath,
LdrEntry,
BoundEntry,
&BoundEntry,
FirstEntry);
if (!NT_SUCCESS(Status)) return Status;
}
@ -642,8 +644,35 @@ LdrpNameToOrdinal(LPSTR ImportName,
PULONG NameTable,
PUSHORT OrdinalTable)
{
UNIMPLEMENTED;
return 0;
ULONG Start, End, Next;
LONG CmpResult;
/* Use classical binary search to find the ordinal */
Start = 0;
End = NumberOfNames - 1;
while (End >= Start)
{
/* Next will be exactly between Start and End */
Next = (Start + End) >> 1;
/* Compare this name with the one we need to find */
CmpResult = strcmp(ImportName, (PCHAR)((ULONG_PTR)ExportBase + NameTable[Next]));
/* We found our entry if result is 0 */
if (!CmpResult) break;
/* We didn't find, update our range then */
if (CmpResult < 0)
End = Next - 1;
else if (CmpResult > 0)
Start = Next + 1;
}
/* If end is before start, then the search failed */
if (End < Start) return -1;
/* Return found name */
return OrdinalTable[Next];
}
NTSTATUS
@ -657,10 +686,12 @@ LdrpWalkImportDescriptor(IN LPWSTR DllPath OPTIONAL,
PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundEntry = NULL;
PIMAGE_IMPORT_DESCRIPTOR ImportEntry;
ULONG BoundSize, IatSize;
DPRINT1("LdrpWalkImportDescriptor('%S' %x)\n", DllPath, LdrEntry);
DPRINT("LdrpWalkImportDescriptor('%S' %x)\n", DllPath, LdrEntry);
/* Set up the Act Ctx */
ActCtx.Size = sizeof(ActCtx);
ActCtx.Frame.Flags = 1;
ActCtx.Format = 1;
RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
/* Check if we have a manifest prober routine */
@ -680,7 +711,7 @@ DPRINT1("LdrpWalkImportDescriptor('%S' %x)\n", DllPath, LdrEntry);
RtlActivateActivationContextUnsafeFast(&ActCtx,
LdrEntry->EntryPointActivationContext);
/* Check if we were directed */
/* Check if we were redirected */
if (!(LdrEntry->Flags & LDRP_REDIRECTED))
{
/* Get the Bound IAT */
@ -764,7 +795,9 @@ LdrpLoadImportModule(IN PWSTR DllPath OPTIONAL,
NTSTATUS Status;
PPEB Peb = RtlGetCurrentPeb();
PTEB Teb = NtCurrentTeb();
DPRINT1("LdrpLoadImportModule('%S' '%s' %p %p %p)\n", DllPath, ImportName, DllBase, DataTableEntry, Existing);
DPRINT("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);
@ -788,8 +821,8 @@ DPRINT1("LdrpLoadImportModule('%S' '%s' %p %p %p)\n", DllPath, ImportName, DllBa
/* Map it */
Status = LdrpMapDll(DllPath,
ImpDescName->Buffer,
NULL,
ImpDescName->Buffer,
NULL,
TRUE,
FALSE,
@ -893,6 +926,12 @@ FailurePath:
/* Is this a static snap? */
if (Static)
{
/* Inform the debug log */
if (IsOrdinal)
DPRINT1("Failed to snap ordinal 0x%x\n", OriginalOrdinal);
else
DPRINT1("Failed to snap %s\n", ImportName);
/* These are critical errors. Setup a string for the DLL name */
RtlInitAnsiString(&TempString, DllName ? DllName : "Unknown");
RtlAnsiStringToUnicodeString(&HardErrorDllName, &TempString, TRUE);
@ -944,6 +983,14 @@ FailurePath:
/* Return ordinal error */
RtlRaiseStatus(STATUS_ORDINAL_NOT_FOUND);
}
else
{
/* Inform the debug log */
if (IsOrdinal)
DPRINT("Non-fatal: Failed to snap ordinal 0x%x\n", OriginalOrdinal);
else
DPRINT("Non-fatal: Failed to snap %s\n", ImportName);
}
/* Set this as a bad DLL */
Thunk->u1.Function = (ULONG_PTR)0xffbadd11;

File diff suppressed because it is too large Load diff

View file

@ -10,12 +10,11 @@
/* INCLUDES *****************************************************************/
#include <ntdll.h>
#define NDEBUG
//#define NDEBUG
#include <debug.h>
#include <win32k/callback.h>
VOID RtlInitializeHeapManager(VOID);
VOID LdrpInitLoader(VOID);
extern PTEB LdrpTopLevelDllBeingLoadedTeb;
VOID NTAPI RtlpInitDeferedCriticalSection(VOID);
VOID RtlpInitializeVectoredExceptionHandling(VOID);
@ -309,280 +308,4 @@ finish:
return FALSE;
}
NTSTATUS
NTAPI
LdrpInitializeProcess_(PCONTEXT Context,
PVOID SystemArgument1)
{
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;
NTHeaders = (PIMAGE_NT_HEADERS)((ULONG_PTR)ImageBase + PEDosHeader->e_lfanew);
DPRINT("PEDosHeader %p\n", PEDosHeader);
if (PEDosHeader->e_magic != IMAGE_DOS_SIGNATURE ||
PEDosHeader->e_lfanew == 0L ||
NTHeaders->Signature != 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);
/* 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();
/* Load execution options */
LoadImageFileExecutionOptions(Peb);
/* 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);
}
/* Check for correct machine type */
if (NTHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_NATIVE)
{
ULONG_PTR HardErrorParameters[1];
UNICODE_STRING ImageNameU;
ANSI_STRING ImageNameA;
WCHAR *Ptr;
ULONG ErrorResponse;
DPRINT1("Image %wZ is for a foreign architecture (0x%x).\n",
&Peb->ProcessParameters->ImagePathName, NTHeaders->FileHeader.Machine);
/* Get the full image path name */
ImageNameU = Peb->ProcessParameters->ImagePathName;
/* Get the file name */
Ptr = Peb->ProcessParameters->ImagePathName.Buffer +
(Peb->ProcessParameters->ImagePathName.Length / sizeof(WCHAR)) -1;
while ((Ptr >= Peb->ProcessParameters->ImagePathName.Buffer) &&
(*Ptr != L'\\')) Ptr--;
ImageNameU.Buffer = Ptr + 1;
ImageNameU.Length = Peb->ProcessParameters->ImagePathName.Length -
(ImageNameU.Buffer - Peb->ProcessParameters->ImagePathName.Buffer) * sizeof(WCHAR);
ImageNameU.MaximumLength = ImageNameU.Length;
/*`Convert to ANSI, harderror message needs that */
RtlUnicodeStringToAnsiString(&ImageNameA, &ImageNameU, TRUE);
/* Raise harderror */
HardErrorParameters[0] = (ULONG_PTR)&ImageNameA;
NtRaiseHardError(STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE,
1,
1,
HardErrorParameters,
OptionOk,
&ErrorResponse);
RtlFreeAnsiString(&ImageNameA);
ZwTerminateProcess(NtCurrentProcess(), STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE);
}
/* initialized vectored exception handling */
RtlpInitializeVectoredExceptionHandling();
/* initalize peb lock support */
RtlInitializeCriticalSection(&FastPebLock);
Peb->FastPebLock = &FastPebLock;
/* 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(&LdrpLoaderLock);
Peb->LoaderLock = &LdrpLoaderLock;
/* 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);
/* add entry for executable (becomes first list entry) */
LdrpImageEntry = (PLDR_DATA_TABLE_ENTRY)
RtlAllocateHeap(Peb->ProcessHeap,
HEAP_ZERO_MEMORY,
sizeof(LDR_DATA_TABLE_ENTRY));
if (LdrpImageEntry == NULL)
{
DPRINT1("Failed to create loader module infomation\n");
ZwTerminateProcess(NtCurrentProcess(), STATUS_INSUFFICIENT_RESOURCES);
}
LdrpImageEntry->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(&LdrpImageEntry->FullDllName,
Peb->ProcessParameters->ImagePathName.Buffer);
RtlCreateUnicodeString(&LdrpImageEntry->BaseDllName,
wcsrchr(LdrpImageEntry->FullDllName.Buffer, L'\\') + 1);
DPRINT("BaseDllName '%wZ' FullDllName '%wZ'\n", &LdrpImageEntry->BaseDllName, &LdrpImageEntry->FullDllName);
LdrpImageEntry->Flags = LDRP_ENTRY_PROCESSED;
LdrpImageEntry->LoadCount = -1; /* don't unload */
LdrpImageEntry->TlsIndex = -1;
LdrpImageEntry->SectionPointer = NULL;
LdrpImageEntry->CheckSum = 0;
NTHeaders = RtlImageNtHeader(LdrpImageEntry->DllBase);
LdrpImageEntry->SizeOfImage = LdrpGetResidentSize(NTHeaders);
LdrpImageEntry->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp;
LdrpTopLevelDllBeingLoadedTeb = NtCurrentTeb();
InsertHeadList(&Peb->Ldr->InLoadOrderModuleList,
&LdrpImageEntry->InLoadOrderLinks);
LdrpInitLoader();
EntryPoint = LdrPEStartup((PVOID)ImageBase, NULL, NULL, NULL);
LdrpImageEntry->EntryPoint = EntryPoint;
/* all required dlls are loaded now */
Peb->Ldr->Initialized = TRUE;
/* 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);
}
/* Break into debugger */
if (Peb->BeingDebugged)
DbgBreakPoint();
return STATUS_SUCCESS;
}
/* EOF */

File diff suppressed because it is too large Load diff

View file

@ -443,20 +443,11 @@ LoadLibraryExW(LPCWSTR lpLibFileName,
}
}
/* HACK!!! FIXME */
if (InWindows)
{
/* Call the API Properly */
Status = LdrLoadDll(SearchPath,
&DllCharacteristics,
&DllName,
(PVOID*)&hInst);
}
else
{
/* Call the ROS API. NOTE: Don't fix this, I have a patch to merge later. */
Status = LdrLoadDll(SearchPath, &dwFlags, &DllName, (PVOID*)&hInst);
}
/* Call the API Properly */
Status = LdrLoadDll(SearchPath,
&DllCharacteristics,
&DllName,
(PVOID*)&hInst);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{

View file

@ -2736,6 +2736,10 @@ NTAPI
RtlAllocateActivationContextStack(IN PVOID *Context)
{
PACTIVATION_CONTEXT_STACK ContextStack;
/* FIXME: Check if it's already allocated */
//if (*Context) return STATUS_SUCCESS;
ContextStack = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof (ACTIVATION_CONTEXT_STACK) );
if (!ContextStack)
{
@ -2798,7 +2802,16 @@ RtlActivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTE
/* Return pointer to the activation frame */
return &Frame->Frame;
#else
return NULL;
RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame = &Frame->Frame;
frame->Previous = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
frame->ActivationContext = Context;
frame->Flags = 0;
NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame;
return STATUS_SUCCESS;
#endif
}
@ -2806,7 +2819,6 @@ PRTL_ACTIVATION_CONTEXT_STACK_FRAME
FASTCALL
RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame)
{
#if NEW_NTDLL_LOADER
RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
/* find the right frame */
@ -2820,9 +2832,6 @@ RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CON
NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame->Previous;
return frame;
#else
return NULL;
#endif
}