#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;
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);
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
OUT PVOID *BaseAddress,
IN BOOLEAN CallInit);
+VOID NTAPI
+LdrpUpdateLoadCount2(IN PLDR_DATA_TABLE_ENTRY LdrEntry,
+ IN ULONG Flags);
+
ULONG NTAPI
LdrpClearLoadInProgress();
PVOID NTAPI
LdrpFetchAddressOfEntryPoint(PVOID ImageBase);
+BOOLEAN NTAPI
+LdrpFreeUnicodeString(PUNICODE_STRING String);
+
/* FIXME: Cleanup this mess */
typedef NTSTATUS (NTAPI *PEPFUNC)(PPEB);
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;
/* GLOBALS *******************************************************************/
LONG LdrpLoaderLockAcquisitonCount;
+BOOLEAN LdrpShowRecursiveLoads;
+UNICODE_STRING LdrApiDefaultExtension = RTL_CONSTANT_STRING(L".DLL");
/* FUNCTIONS *****************************************************************/
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);
+
+ /* 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
*/
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,
/* INCLUDES *****************************************************************/
#include <ntdll.h>
+#include <win32k/callback.h>
+
#define NDEBUG
#include <debug.h>
+
/* GLOBALS *******************************************************************/
HKEY ImageExecOptionsKey;
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;
BOOLEAN ShowSnaps;
ULONG LdrpFatalHardErrorCount;
+ULONG LdrpActiveUnloadCount;
//extern LIST_ENTRY RtlCriticalSectionList;
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 *****************************************************************/
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;
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)
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)
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;
}
//LPWSTR ImagePathBuffer;
ULONG ConfigSize;
UNICODE_STRING CurrentDirectory;
- ULONG ExecuteOptions;
+ HKEY OptionsKey;
ULONG HeapFlags;
PIMAGE_NT_HEADERS NtHeader;
LPWSTR NtDllName = NULL;
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);
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,
}
/* 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)
}
/* 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 */
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,
}
/* 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\\");
{
/* It doesn't, so assume System32 */
LdrpKnownDllObjectDirectory = NULL;
- RtlInitUnicodeString(&LdrpKnownDllPath, FullPath.Buffer);
+ RtlInitUnicodeString(&LdrpKnownDllPath, StringBuffer);
LdrpKnownDllPath.Length -= sizeof(WCHAR);
}
else
else
{
/* We need a valid path */
+ DPRINT1("No valid DllPath was given!\n");
LdrpInitFailure(STATUS_INVALID_PARAMETER);
}
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,
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");
}
}
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
if (!ImageFileName.Buffer[0])
{
/* Use the same Base name */
- NtLdrEntry->BaseDllName = NtLdrEntry->BaseDllName;
+ NtLdrEntry->BaseDllName = NtLdrEntry->FullDllName;
}
else
{
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);
///* Close the key if we have one opened */
//if (hKey) NtClose(hKey);
-DbgBreakPoint();
+
/* Return status */
return Status;
}
_SEH2_TRY
{
/* Initialize the Process */
- LoaderStatus = LdrpInitializeProcess_(Context,
+ LoaderStatus = LdrpInitializeProcess(Context,
SystemArgument1);
/* Check for success and if MinimumStackCommit was requested */
/* Deal with Watcom and other retarded compilers */
if (!IatSize)
- {
IatSize = SectionHeader->SizeOfRawData;
- }
/* Found it, get out */
break;
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;
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)
if (ShowSnaps)
{
DPRINT1("LDR: %wZ has stale binding to %s\n",
- &DllLdrEntry->BaseDllName,
+ &LdrEntry->BaseDllName,
BoundImportName);
}
if (ShowSnaps)
{
DPRINT1("LDR: %wZ has correct binding to %s\n",
- &DllLdrEntry->BaseDllName,
+ &LdrEntry->BaseDllName,
BoundImportName);
}
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)
if (ShowSnaps)
{
DPRINT1("LDR: %wZ has stale binding to %s\n",
- &ForwarderLdrEntry->BaseDllName,
+ &LdrEntry->BaseDllName,
ForwarderName);
}
if (ShowSnaps)
{
DPRINT1("LDR: %wZ has correct binding to %s\n",
- &ForwarderLdrEntry->BaseDllName,
+ &LdrEntry->BaseDllName,
ForwarderName);
}
if (!_stricmp(ImportName, BoundImportName)) break;
/* Move to next entry */
- ImportEntry += 1;
+ ImportEntry++;
}
/* If we didn't find a name, fail */
Quickie:
/* Write where we are now and return */
- *BoundEntry = *FirstEntry;
+ *BoundEntryPtr = FirstEntry;
return Status;
}
/* Parse this descriptor */
Status = LdrpHandleOneNewFormatImportDescriptor(DllPath,
LdrEntry,
- BoundEntry,
+ &BoundEntry,
FirstEntry);
if (!NT_SUCCESS(Status)) return Status;
}
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
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 */
RtlActivateActivationContextUnsafeFast(&ActCtx,
LdrEntry->EntryPointActivationContext);
- /* Check if we were directed */
+ /* Check if we were redirected */
if (!(LdrEntry->Flags & LDRP_REDIRECTED))
{
/* Get the Bound IAT */
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);
/* Map it */
Status = LdrpMapDll(DllPath,
- ImpDescName->Buffer,
NULL,
+ ImpDescName->Buffer,
NULL,
TRUE,
FALSE,
/* 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);
/* 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;
#include <debug.h>
/* GLOBALS *******************************************************************/
+#define IMAGE_DLLCHARACTERISTICS_WX86_DLL 0x1000
+LIST_ENTRY LdrpUnloadHead;
PLDR_DATA_TABLE_ENTRY LdrpLoadedDllHandleCache;
+PLDR_DATA_TABLE_ENTRY LdrpGetModuleHandleCache;
#define LDR_GET_HASH_ENTRY(x) (RtlUpcaseUnicodeChar((x)) & (LDR_HASH_TABLE_ENTRIES - 1))
return EntryPoint(BaseAddress, Reason, Context);
}
+VOID
+NTAPI
+LdrpUpdateLoadCount3(IN PLDR_DATA_TABLE_ENTRY LdrEntry,
+ IN ULONG Flags,
+ OUT PUNICODE_STRING UpdateString)
+{
+ PIMAGE_BOUND_FORWARDER_REF NewImportForwarder;
+
+
+ PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundEntry;
+ PIMAGE_IMPORT_DESCRIPTOR ImportEntry;
+ PIMAGE_THUNK_DATA FirstThunk;
+ PLDR_DATA_TABLE_ENTRY Entry;
+ PUNICODE_STRING ImportNameUnic;
+ ANSI_STRING ImportNameAnsi;
+ LPSTR ImportName;
+ ULONG ImportSize;
+ NTSTATUS Status;
+ ULONG i;
+
+ /* Check the action we need to perform */
+ if (Flags == LDRP_UPDATE_REFCOUNT)
+ {
+ /* Make sure entry is not being loaded already */
+ if (LdrEntry->Flags & LDRP_LOAD_IN_PROGRESS)
+ return;
+
+ LdrEntry->Flags |= LDRP_LOAD_IN_PROGRESS;
+ }
+ else if (Flags == LDRP_UPDATE_DEREFCOUNT)
+ {
+ /* Make sure the entry is not being unloaded already */
+ if (LdrEntry->Flags & LDRP_UNLOAD_IN_PROGRESS)
+ return;
+
+ LdrEntry->Flags |= LDRP_UNLOAD_IN_PROGRESS;
+ }
+
+ /* Go through all bound DLLs and dereference them */
+ ImportNameUnic = &NtCurrentTeb()->StaticUnicodeString;
+
+ /* Try to get the new import entry */
+ BoundEntry = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData(LdrEntry->DllBase,
+ TRUE,
+ IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT,
+ &ImportSize);
+
+ if (BoundEntry)
+ {
+ /* Set entry flags if refing/derefing */
+ if (Flags == LDRP_UPDATE_REFCOUNT)
+ LdrEntry->Flags |= LDRP_LOAD_IN_PROGRESS;
+ else if (Flags == LDRP_UPDATE_DEREFCOUNT)
+ LdrEntry->Flags |= LDRP_UNLOAD_IN_PROGRESS;
+
+ while (BoundEntry->OffsetModuleName)
+ {
+ /* Get pointer to the current import name */
+ ImportName = (PCHAR)BoundEntry + BoundEntry->OffsetModuleName;
+
+ RtlInitAnsiString(&ImportNameAnsi, ImportName);
+ Status = RtlAnsiStringToUnicodeString(ImportNameUnic, &ImportNameAnsi, FALSE);
+
+ if (NT_SUCCESS(Status))
+ {
+ if (LdrpCheckForLoadedDll(NULL,
+ ImportNameUnic,
+ TRUE,
+ FALSE,
+ &Entry))
+ {
+ if (Entry->LoadCount != -1)
+ {
+ /* Perform the required action */
+ switch (Flags)
+ {
+ case LDRP_UPDATE_REFCOUNT:
+ Entry->LoadCount++;
+ break;
+ case LDRP_UPDATE_DEREFCOUNT:
+ Entry->LoadCount--;
+ break;
+ case LDRP_UPDATE_PIN:
+ Entry->LoadCount = -1;
+ break;
+ }
+
+ /* Show snaps */
+ if (ShowSnaps)
+ {
+ DPRINT1("LDR: Flags %d %wZ (%lx)\n", Flags, ImportNameUnic, Entry->LoadCount);
+ }
+ }
+
+ /* Recurse into this entry */
+ LdrpUpdateLoadCount3(Entry, Flags, UpdateString);
+ }
+ }
+
+ /* Go through forwarders */
+ NewImportForwarder = (PIMAGE_BOUND_FORWARDER_REF)(BoundEntry + 1);
+ for (i=0; i<BoundEntry->NumberOfModuleForwarderRefs; i++)
+ {
+ ImportName = (PCHAR)BoundEntry + NewImportForwarder->OffsetModuleName;
+
+ RtlInitAnsiString(&ImportNameAnsi, ImportName);
+ Status = RtlAnsiStringToUnicodeString(ImportNameUnic, &ImportNameAnsi, FALSE);
+ if (NT_SUCCESS(Status))
+ {
+ if (LdrpCheckForLoadedDll(NULL,
+ ImportNameUnic,
+ TRUE,
+ FALSE,
+ &Entry))
+ {
+ if (Entry->LoadCount != -1)
+ {
+ /* Perform the required action */
+ switch (Flags)
+ {
+ case LDRP_UPDATE_REFCOUNT:
+ Entry->LoadCount++;
+ break;
+ case LDRP_UPDATE_DEREFCOUNT:
+ Entry->LoadCount--;
+ break;
+ case LDRP_UPDATE_PIN:
+ Entry->LoadCount = -1;
+ break;
+ }
+
+ /* Show snaps */
+ if (ShowSnaps)
+ {
+ DPRINT1("LDR: Flags %d %wZ (%lx)\n", Flags, ImportNameUnic, Entry->LoadCount);
+ }
+ }
+
+ /* Recurse into this entry */
+ LdrpUpdateLoadCount3(Entry, Flags, UpdateString);
+ }
+ }
+
+ NewImportForwarder++;
+ }
+
+ BoundEntry = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)NewImportForwarder;
+ }
+
+ /* We're done */
+ return;
+ }
+
+ /* Check oldstyle import descriptor */
+ ImportEntry = (PIMAGE_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData(LdrEntry->DllBase,
+ TRUE,
+ IMAGE_DIRECTORY_ENTRY_IMPORT,
+ &ImportSize);
+ if (ImportEntry)
+ {
+ /* There is old one, so go through its entries */
+ while (ImportEntry->Name && ImportEntry->FirstThunk)
+ {
+ FirstThunk = (PIMAGE_THUNK_DATA)((ULONG_PTR)LdrEntry->DllBase + ImportEntry->FirstThunk);
+
+ /* Skip this entry if needed */
+ if (!FirstThunk->u1.Function)
+ {
+ ImportEntry++;
+ continue;
+ }
+
+ ImportName = (PSZ)((ULONG_PTR)LdrEntry->DllBase + ImportEntry->Name);
+
+ RtlInitAnsiString(&ImportNameAnsi, ImportName);
+ Status = RtlAnsiStringToUnicodeString(ImportNameUnic, &ImportNameAnsi, FALSE);
+ if (NT_SUCCESS(Status))
+ {
+ if (LdrpCheckForLoadedDll(NULL,
+ ImportNameUnic,
+ TRUE,
+ FALSE,
+ &Entry))
+ {
+ if (Entry->LoadCount != -1)
+ {
+ /* Perform the required action */
+ switch (Flags)
+ {
+ case LDRP_UPDATE_REFCOUNT:
+ Entry->LoadCount++;
+ break;
+ case LDRP_UPDATE_DEREFCOUNT:
+ Entry->LoadCount--;
+ break;
+ case LDRP_UPDATE_PIN:
+ Entry->LoadCount = -1;
+ break;
+ }
+
+ /* Show snaps */
+ if (ShowSnaps)
+ {
+ DPRINT1("LDR: Flags %d %wZ (%lx)\n", Flags, ImportNameUnic, Entry->LoadCount);
+ }
+ }
+
+ /* Recurse */
+ LdrpUpdateLoadCount3(Entry, Flags, UpdateString);
+ }
+ }
+
+ /* Go to the next entry */
+ ImportEntry++;
+ }
+ }
+}
+
+VOID
+NTAPI
+LdrpUpdateLoadCount2(IN PLDR_DATA_TABLE_ENTRY LdrEntry,
+ IN ULONG Flags)
+{
+ WCHAR Buffer[MAX_PATH];
+ UNICODE_STRING UpdateString;
+
+ /* Setup the string */
+ UpdateString.Buffer = Buffer;
+ UpdateString.Length = 0;
+ UpdateString.MaximumLength = sizeof(Buffer);
+
+ /* Call the extended API */
+ LdrpUpdateLoadCount3(LdrEntry, Flags, &UpdateString);
+}
+
VOID
NTAPI
LdrpTlsCallback(PVOID BaseAddress, ULONG Reason)
}
}
}
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- /* Do nothing */
- }
- _SEH2_END;
-}
-
-PVOID
-NTAPI
-LdrpFetchAddressOfEntryPoint(PVOID ImageBase)
-{
- PIMAGE_NT_HEADERS NtHeaders;
- ULONG_PTR EntryPoint;
-
- /* Get entry point offset from NT headers */
- NtHeaders = RtlImageNtHeader(ImageBase);
- EntryPoint = NtHeaders->OptionalHeader.AddressOfEntryPoint;
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Do nothing */
+ }
+ _SEH2_END;
+}
+
+NTSTATUS
+NTAPI
+LdrpCodeAuthzCheckDllAllowed(PUNICODE_STRING FullName,
+ HANDLE DllHandle)
+{
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+LdrpCreateDllSection(IN PUNICODE_STRING FullName,
+ IN HANDLE DllHandle,
+ IN PULONG DllCharacteristics OPTIONAL,
+ OUT PHANDLE SectionHandle)
+{
+ HANDLE FileHandle;
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ ULONG_PTR HardErrorParameters[1];
+ ULONG Response;
+ SECTION_IMAGE_INFORMATION SectionImageInfo;
+
+ /* Check if we don't already have a handle */
+ if (!DllHandle)
+ {
+ /* Create the object attributes */
+ InitializeObjectAttributes(&ObjectAttributes,
+ FullName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ /* Open the DLL */
+ Status = NtOpenFile(&FileHandle,
+ SYNCHRONIZE | FILE_EXECUTE | FILE_READ_DATA,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_READ | FILE_SHARE_DELETE,
+ FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
+
+ /* Check if we failed */
+ if (!NT_SUCCESS(Status))
+ {
+ /* Attempt to open for execute only */
+ Status = NtOpenFile(&FileHandle,
+ SYNCHRONIZE | FILE_EXECUTE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_READ | FILE_SHARE_DELETE,
+ FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
+
+ /* Check if this failed too */
+ if (!NT_SUCCESS(Status))
+ {
+ /* Show debug message */
+ if (ShowSnaps)
+ {
+ DPRINT1("LDR: LdrpCreateDllSection - NtOpenFile failed; status = %x\n",
+ Status);
+ }
+
+ /* Make sure to return an expected status code */
+ if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
+ {
+ /* Callers expect this instead */
+ Status = STATUS_DLL_NOT_FOUND;
+ }
+
+ /* Return an empty section handle */
+ *SectionHandle = NULL;
+ return Status;
+ }
+ }
+ }
+ else
+ {
+ /* Use the handle we already have */
+ FileHandle = DllHandle;
+ }
+
+ /* Create a section for the DLL */
+ Status = NtCreateSection(SectionHandle,
+ SECTION_MAP_READ | SECTION_MAP_EXECUTE |
+ SECTION_MAP_WRITE | SECTION_QUERY,
+ NULL,
+ NULL,
+ PAGE_EXECUTE,
+ SEC_IMAGE,
+ FileHandle);
+
+ /* If mapping failed, raise a hard error */
+ if (!NT_SUCCESS(Status))
+ {
+ /* Forget the handle */
+ *SectionHandle = NULL;
+
+ /* Give the DLL name */
+ HardErrorParameters[0] = (ULONG_PTR)FullName;
+
+ /* Raise the error */
+ ZwRaiseHardError(STATUS_INVALID_IMAGE_FORMAT,
+ 1,
+ 1,
+ HardErrorParameters,
+ OptionOk,
+ &Response);
+
+ /* Increment the error count */
+ if (LdrpInLdrInit) LdrpFatalHardErrorCount++;
+ }
+
+ /* Check for Safer restrictions */
+ if (DllCharacteristics &&
+ !(*DllCharacteristics & IMAGE_DLLCHARACTERISTICS_WX86_DLL))
+ {
+ /* Make sure it's executable */
+ Status = ZwQuerySection(*SectionHandle,
+ SectionImageInformation,
+ &SectionImageInfo,
+ sizeof(SECTION_IMAGE_INFORMATION),
+ NULL);
+ if (NT_SUCCESS(Status))
+ {
+ /* Check if it's executable */
+ if (SectionImageInfo.ImageContainsCode)
+ {
+ /* It is, check safer */
+ Status = LdrpCodeAuthzCheckDllAllowed(FullName, DllHandle);
+ if (!NT_SUCCESS(Status) && (Status != STATUS_NOT_FOUND))
+ {
+ /* Show debug message */
+ if (ShowSnaps)
+ {
+ DPRINT1("LDR: Loading of (%wZ) blocked by Winsafer\n",
+ &FullName);
+ }
+ }
+ else
+ {
+ /* We're fine, return normally */
+ goto Quickie;
+ }
+ }
+ }
+
+ /* Failure case, close section handle */
+ NtClose(*SectionHandle);
+ *SectionHandle = NULL;
+ }
+
+Quickie:
+ /* Close the file handle, we don't need it */
+ NtClose(FileHandle);
+
+ /* Return status */
+ return Status;
+}
+
+BOOLEAN
+NTAPI
+LdrpResolveDllName(PWSTR DllPath,
+ PWSTR DllName,
+ PUNICODE_STRING FullDllName,
+ PUNICODE_STRING BaseDllName)
+{
+ PWCHAR NameBuffer, p1, p2 = 0;
+ ULONG Length;
+ ULONG BufSize = 500;
+
+ /* Allocate space for full DLL name */
+ FullDllName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufSize + sizeof(UNICODE_NULL));
+ if (!FullDllName->Buffer) return FALSE;
+
+ Length = RtlDosSearchPath_U(DllPath ? DllPath : LdrpDefaultPath.Buffer,
+ DllName,
+ NULL,
+ BufSize,
+ FullDllName->Buffer,
+ &BaseDllName->Buffer);
+
+ if (!Length || Length > BufSize)
+ {
+ if (ShowSnaps)
+ {
+ DPRINT1("LDR: LdrResolveDllName - Unable to find ");
+ DPRINT1("%ws from %ws\n", DllName, DllPath ? DllPath : LdrpDefaultPath.Buffer);
+ }
+
+ RtlFreeUnicodeString(FullDllName);
+ return FALSE;
+ }
+
+ /* Construct full DLL name */
+ FullDllName->Length = Length;
+ FullDllName->MaximumLength = FullDllName->Length + sizeof(UNICODE_NULL);
+
+ /* Allocate a new buffer */
+ NameBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, FullDllName->MaximumLength);
+ if (!NameBuffer)
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, FullDllName->Buffer);
+ return FALSE;
+ }
+
+ /* Copy over the contents from the previous one and free it */
+ RtlCopyMemory(NameBuffer, FullDllName->Buffer, FullDllName->MaximumLength);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, FullDllName->Buffer);
+ FullDllName->Buffer = NameBuffer;
+
+ /* Find last backslash */
+ p1 = FullDllName->Buffer;
+ while (*p1)
+ {
+ if (*p1++ == L'\\')
+ {
+ p2 = p1;
+ }
+ }
+
+ /* If found, set p1 to it, otherwise p1 points to the beginning of DllName */
+ if (p2)
+ p1 = p2;
+ else
+ p1 = DllName;
+
+ p2 = p1;
+
+ /* Calculate remaining length */
+ while (*p1) ++p1;
+
+ /* Construct base DLL name */
+ BaseDllName->Length = (ULONG_PTR)p1 - (ULONG_PTR)p2;
+ BaseDllName->MaximumLength = BaseDllName->Length + sizeof(UNICODE_NULL);
+ BaseDllName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BaseDllName->MaximumLength);
+
+ if (!BaseDllName->Buffer)
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, NameBuffer);
+ return FALSE;
+ }
+
+ /* Copy base dll name to the new buffer */
+ RtlMoveMemory(BaseDllName->Buffer,
+ p2,
+ BaseDllName->Length);
+
+ /* Null-terminate the string */
+ BaseDllName->Buffer[BaseDllName->Length / sizeof(WCHAR)] = 0;
+
+ return TRUE;
+}
+
+PVOID
+NTAPI
+LdrpFetchAddressOfEntryPoint(PVOID ImageBase)
+{
+ PIMAGE_NT_HEADERS NtHeaders;
+ ULONG_PTR EntryPoint;
+
+ /* Get entry point offset from NT headers */
+ NtHeaders = RtlImageNtHeader(ImageBase);
+ EntryPoint = NtHeaders->OptionalHeader.AddressOfEntryPoint;
+
+ /* If it's 0 - return so */
+ if (!EntryPoint) return NULL;
+
+ /* Add image base */
+ EntryPoint += (ULONG_PTR)ImageBase;
+
+ /* Return calculated pointer */
+ return (PVOID)EntryPoint;
+}
+
+HANDLE
+NTAPI
+LdrpCheckForKnownDll(PWSTR DllName,
+ PUNICODE_STRING FullDllName,
+ PUNICODE_STRING BaseDllName)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE Section = NULL;
+ UNICODE_STRING DllNameUnic;
+ NTSTATUS Status;
+ PCHAR p1;
+ PWCHAR p2;
+
+ /* Upgrade DllName to a unicode string */
+ RtlInitUnicodeString(&DllNameUnic, DllName);
+
+ /* Get the activation context */
+ Status = RtlFindActivationContextSectionString(0,
+ NULL,
+ ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION,
+ &DllNameUnic,
+ NULL);
+
+ /* Check if it's a SxS or not */
+ if (Status == STATUS_SXS_SECTION_NOT_FOUND ||
+ Status == STATUS_SXS_KEY_NOT_FOUND)
+ {
+ /* Set up BaseDllName */
+ BaseDllName->Length = DllNameUnic.Length;
+ BaseDllName->MaximumLength = DllNameUnic.MaximumLength;
+ BaseDllName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
+ 0,
+ DllNameUnic.MaximumLength);
+ if (!BaseDllName->Buffer) return NULL;
+
+ /* Copy the contents there */
+ RtlMoveMemory(BaseDllName->Buffer, DllNameUnic.Buffer, DllNameUnic.MaximumLength);
+
+ /* Set up FullDllName */
+ FullDllName->Length = LdrpKnownDllPath.Length + BaseDllName->Length + sizeof(WCHAR);
+ FullDllName->MaximumLength = FullDllName->Length + sizeof(UNICODE_NULL);
+ FullDllName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, FullDllName->MaximumLength);
+ if (!FullDllName->Buffer)
+ {
+ /* Free base name and fail */
+ RtlFreeHeap(RtlGetProcessHeap(), 0, BaseDllName->Buffer);
+ return NULL;
+ }
+
+ RtlMoveMemory(FullDllName->Buffer, LdrpKnownDllPath.Buffer, LdrpKnownDllPath.Length);
+
+ /* Put a slash there */
+ p1 = (PCHAR)FullDllName->Buffer + LdrpKnownDllPath.Length;
+ p2 = (PWCHAR)p1;
+ *p2++ = (WCHAR)'\\';
+ p1 = (PCHAR)p2;
+
+ /* Set up DllNameUnic for a relative path */
+ DllNameUnic.Buffer = (PWSTR)p1;
+ DllNameUnic.Length = BaseDllName->Length;
+ DllNameUnic.MaximumLength = DllNameUnic.Length + sizeof(UNICODE_NULL);
+
+ /* Copy the contents */
+ RtlMoveMemory(p1, BaseDllName->Buffer, BaseDllName->MaximumLength);
+
+ /* There are all names, init attributes and open the section */
+ InitializeObjectAttributes(&ObjectAttributes,
+ &DllNameUnic,
+ OBJ_CASE_INSENSITIVE,
+ LdrpKnownDllObjectDirectory,
+ NULL);
+
+ Status = NtOpenSection(&Section,
+ SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_MAP_WRITE,
+ &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Opening failed, free resources */
+ Section = NULL;
+ RtlFreeHeap(RtlGetProcessHeap(), 0, BaseDllName->Buffer);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, FullDllName->Buffer);
+ }
+ }
+ else
+ {
+ if (!NT_SUCCESS(Status)) Section = NULL;
+ }
+
+ /* Return section handle */
+ return Section;
+}
+
+NTSTATUS
+NTAPI
+LdrpSetProtection(PVOID ViewBase,
+ BOOLEAN Restore)
+{
+ PIMAGE_NT_HEADERS NtHeaders;
+ PIMAGE_SECTION_HEADER Section;
+ NTSTATUS Status;
+ PVOID SectionBase;
+ SIZE_T SectionSize;
+ ULONG NewProtection, OldProtection, i;
+
+ /* Get the NT headers */
+ NtHeaders = RtlImageNtHeader(ViewBase);
+
+ /* Compute address of the first section header */
+ Section = (PIMAGE_SECTION_HEADER)(
+ (ULONG_PTR)NtHeaders + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
+ NtHeaders->FileHeader.SizeOfOptionalHeader);
+
+ /* Go through all sections */
+ for (i = 0; i < NtHeaders->FileHeader.NumberOfSections; i++)
+ {
+ if (Section->SizeOfRawData &&
+ !(Section->Characteristics & IMAGE_SCN_MEM_WRITE))
+ {
+ /* This section is not writable and has some size, so we need to change
+ its protection */
+ if (Restore)
+ {
+ /* Set it to either EXECUTE or READONLY */
+ if (Section->Characteristics & IMAGE_SCN_MEM_EXECUTE)
+ NewProtection = PAGE_EXECUTE;
+ else
+ NewProtection = PAGE_READONLY;
+
+ /* Add PAGE_NOCACHE if needed */
+ if (Section->Characteristics & IMAGE_SCN_MEM_NOT_CACHED)
+ NewProtection |= PAGE_NOCACHE;
+ }
+ else
+ {
+ /* Enable write access */
+ NewProtection = PAGE_READWRITE;
+ }
+
+ SectionBase = (PVOID)((ULONG_PTR)ViewBase + Section->VirtualAddress);
+ SectionSize = Section->SizeOfRawData;
+
+ if (SectionSize)
+ {
+ /* Set protection */
+ Status = ZwProtectVirtualMemory(NtCurrentProcess(),
+ &SectionBase,
+ &SectionSize,
+ NewProtection,
+ &OldProtection);
+
+ if (!NT_SUCCESS(Status)) return Status;
+ }
+ }
+
+ /* Move to the next section */
+ Section++;
+ }
+
+ /* Flush instruction cache if necessary */
+ if (Restore) ZwFlushInstructionCache(NtCurrentProcess(), NULL, 0);
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+LdrpMapDll(IN PWSTR SearchPath OPTIONAL,
+ IN PWSTR DllPath2,
+ IN PWSTR DllName OPTIONAL,
+ IN PULONG DllCharacteristics,
+ IN BOOLEAN Static,
+ IN BOOLEAN Redirect,
+ OUT PLDR_DATA_TABLE_ENTRY *DataTableEntry)
+{
+ PTEB Teb = NtCurrentTeb();
+ PPEB Peb = NtCurrentPeb();
+ PWCHAR p1 = DllName;
+ WCHAR TempChar;
+ BOOLEAN KnownDll = FALSE;
+ UNICODE_STRING FullDllName, BaseDllName;
+ HANDLE SectionHandle = NULL, DllHandle = 0;
+ UNICODE_STRING NtPathDllName;
+ ULONG_PTR HardErrorParameters[2];
+ UNICODE_STRING HardErrorDllName, HardErrorDllPath;
+ ULONG Response;
+ SIZE_T ViewSize = 0;
+ PVOID ViewBase = NULL;
+ PVOID ArbitraryUserPointer;
+ PIMAGE_NT_HEADERS NtHeaders;
+ NTSTATUS HardErrorStatus, Status;
+ BOOLEAN OverlapDllFound = FALSE;
+ ULONG_PTR ImageBase, ImageEnd;
+ PLIST_ENTRY ListHead, NextEntry;
+ PLDR_DATA_TABLE_ENTRY CandidateEntry, LdrEntry;
+ ULONG_PTR CandidateBase, CandidateEnd;
+ UNICODE_STRING OverlapDll;
+ BOOLEAN RelocatableDll = TRUE;
+ UNICODE_STRING IllegalDll;
+ PVOID RelocData;
+ ULONG RelocDataSize = 0;
+
+ // FIXME: AppCompat stuff is missing
+
+ if (ShowSnaps)
+ {
+ DPRINT1("LDR: LdrpMapDll: Image Name %ws, Search Path %ws\n",
+ DllName,
+ SearchPath ? SearchPath : L"");
+ }
+
+ /* Check if we have a known dll directory */
+ if (LdrpKnownDllObjectDirectory)
+ {
+ /* Check if the path is full */
+ while (*p1)
+ {
+ TempChar = *p1++;
+ if (TempChar == '\\' || TempChar == '/' )
+ {
+ /* Complete path, don't do Known Dll lookup */
+ goto SkipCheck;
+ }
+ }
+
+ /* Try to find a Known DLL */
+ SectionHandle = LdrpCheckForKnownDll(DllName,
+ &FullDllName,
+ &BaseDllName);
+ }
+
+SkipCheck:
+
+ /* Check if the Known DLL Check returned something */
+ if (!SectionHandle)
+ {
+ /* It didn't, so try to resolve the name now */
+ if (LdrpResolveDllName(SearchPath,
+ DllName,
+ &FullDllName,
+ &BaseDllName))
+ {
+ /* Got a name, display a message */
+ if (ShowSnaps)
+ {
+ DPRINT1("LDR: Loading (%s) %wZ\n",
+ Static ? "STATIC" : "DYNAMIC",
+ &FullDllName);
+ }
+
+ /* Convert to NT Name */
+ if (!RtlDosPathNameToNtPathName_U(FullDllName.Buffer,
+ &NtPathDllName,
+ NULL,
+ NULL))
+ {
+ /* Path was invalid */
+ return STATUS_OBJECT_PATH_SYNTAX_BAD;
+ }
+
+ /* Create a section for this dLL */
+ Status = LdrpCreateDllSection(&NtPathDllName,
+ DllHandle,
+ DllCharacteristics,
+ &SectionHandle);
+
+ /* Free the NT Name */
+ RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathDllName.Buffer);
+
+ /* If we failed */
+ if (!NT_SUCCESS(Status))
+ {
+ /* Free the name strings and return */
+ RtlFreeUnicodeString(&FullDllName);
+ RtlFreeUnicodeString(&BaseDllName);
+ return Status;
+ }
+ }
+ else
+ {
+ /* We couldn't resolve the name, is this a static load? */
+ if (Static)
+ {
+ /*
+ * This is BAD! Static loads are CRITICAL. Bugcheck!
+ * Initialize the strings for the error
+ */
+ RtlInitUnicodeString(&HardErrorDllName, DllName);
+ RtlInitUnicodeString(&HardErrorDllPath,
+ DllPath2 ? DllPath2 : LdrpDefaultPath.Buffer);
+
+ /* Set them as error parameters */
+ HardErrorParameters[0] = (ULONG_PTR)&HardErrorDllName;
+ HardErrorParameters[1] = (ULONG_PTR)&HardErrorDllPath;
+
+ /* Raise the hard error */
+ NtRaiseHardError(STATUS_DLL_NOT_FOUND,
+ 2,
+ 0x00000003,
+ HardErrorParameters,
+ OptionOk,
+ &Response);
+
+ /* We're back, where we initializing? */
+ if (LdrpInLdrInit) LdrpFatalHardErrorCount++;
+ }
+
+ /* Return failure */
+ return STATUS_DLL_NOT_FOUND;
+ }
+ }
+ else
+ {
+ /* We have a section handle, so this is a known dll */
+ KnownDll = TRUE;
+ }
+
+ /* Stuff the image name in the TIB, for the debugger */
+ ArbitraryUserPointer = Teb->NtTib.ArbitraryUserPointer;
+ Teb->NtTib.ArbitraryUserPointer = FullDllName.Buffer;
+
+ /* Map the DLL */
+ ViewBase = NULL;
+ ViewSize = 0;
+ Status = NtMapViewOfSection(SectionHandle,
+ NtCurrentProcess(),
+ &ViewBase,
+ 0,
+ 0,
+ NULL,
+ &ViewSize,
+ ViewShare,
+ 0,
+ PAGE_READWRITE);
+
+ /* Restore */
+ Teb->NtTib.ArbitraryUserPointer = ArbitraryUserPointer;
+
+ /* Fail if we couldn't map it */
+ if (!NT_SUCCESS(Status))
+ {
+ /* Close and return */
+ NtClose(SectionHandle);
+ return Status;
+ }
+
+ /* Get the NT Header */
+ if (!(NtHeaders = RtlImageNtHeader(ViewBase)))
+ {
+ /* Invalid image, unmap, close handle and fail */
+ NtUnmapViewOfSection(NtCurrentProcess(), ViewBase);
+ NtClose(SectionHandle);
+ return STATUS_INVALID_IMAGE_FORMAT;
+ }
+
+ // FIXME: .NET support is missing
+
+ /* Allocate an entry */
+ if (!(LdrEntry = LdrpAllocateDataTableEntry(ViewBase)))
+ {
+ /* Invalid image, unmap, close handle and fail */
+ NtUnmapViewOfSection(NtCurrentProcess(), ViewBase);
+ NtClose(SectionHandle);
+ return STATUS_NO_MEMORY;
+ }
+
+ /* Setup the entry */
+ LdrEntry->Flags = Static ? LDRP_STATIC_LINK : 0;
+ if (Redirect) LdrEntry->Flags |= LDRP_REDIRECTED;
+ LdrEntry->LoadCount = 0;
+ LdrEntry->FullDllName = FullDllName;
+ LdrEntry->BaseDllName = BaseDllName;
+ LdrEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(LdrEntry->DllBase);
+
+ /* Show debug message */
+ if (ShowSnaps)
+ {
+ DPRINT1("LDR: LdrpMapDll: Full Name %wZ, Base Name %wZ\n",
+ &FullDllName,
+ &BaseDllName);
+ }
+
+ /* Insert this entry */
+ LdrpInsertMemoryTableEntry(LdrEntry);
+
+ // LdrpSendDllNotifications(LdrEntry, TRUE, Status == STATUS_IMAGE_NOT_AT_BASE)
+
+ /* Check for invalid CPU Image */
+ if (Status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH)
+ {
+ /* Load our header */
+ PIMAGE_NT_HEADERS ImageNtHeader = RtlImageNtHeader(Peb->ImageBaseAddress);
+
+ /* Assume defaults if we don't have to run the Hard Error path */
+ HardErrorStatus = STATUS_SUCCESS;
+ Response = ResponseCancel;
+
+ /* Are we an NT 3.0 image? [Do these still exist? LOL -- IAI] */
+ if (ImageNtHeader->OptionalHeader.MajorSubsystemVersion <= 3)
+ {
+ /* Reset the entrypoint, save our Dll Name */
+ LdrEntry->EntryPoint = 0;
+ HardErrorParameters[0] = (ULONG_PTR)&FullDllName;
+
+ /* Raise the error */
+ HardErrorStatus = ZwRaiseHardError(STATUS_IMAGE_MACHINE_TYPE_MISMATCH,
+ 1,
+ 1,
+ HardErrorParameters,
+ OptionOkCancel,
+ &Response);
+ }
+
+ /* Check if the user pressed cancel */
+ if (NT_SUCCESS(HardErrorStatus) && Response == ResponseCancel)
+ {
+ /* Remove the DLL from the lists */
+ RemoveEntryList(&LdrEntry->InLoadOrderLinks);
+ RemoveEntryList(&LdrEntry->InMemoryOrderModuleList);
+ RemoveEntryList(&LdrEntry->HashLinks);
+
+ /* Remove the LDR Entry */
+ RtlFreeHeap(RtlGetProcessHeap(), 0, LdrEntry );
+
+ /* Unmap and close section */
+ NtUnmapViewOfSection(NtCurrentProcess(), ViewBase);
+ NtClose(SectionHandle);
+
+ /* Did we do a hard error? */
+ if (ImageNtHeader->OptionalHeader.MajorSubsystemVersion <= 3)
+ {
+ /* Yup, so increase fatal error count if we are initializing */
+ if (LdrpInLdrInit) LdrpFatalHardErrorCount++;
+ }
+
+ /* Return failure */
+ return STATUS_INVALID_IMAGE_FORMAT;
+ }
+ }
+ else
+ {
+ /* The image was valid. Is it a DLL? */
+ if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL)
+ {
+ /* Set the DLL Flag */
+ LdrEntry->Flags |= LDRP_IMAGE_DLL;
+ }
+
+ /* If we're not a DLL, clear the entrypoint */
+ if (!(LdrEntry->Flags & LDRP_IMAGE_DLL))
+ {
+ LdrEntry->EntryPoint = 0;
+ }
+ }
+
+ /* Return it for the caller */
+ *DataTableEntry = LdrEntry;
+
+ /* Check if we loaded somewhere else */
+ if (Status == STATUS_IMAGE_NOT_AT_BASE)
+ {
+ /* Write the flag */
+ LdrEntry->Flags |= LDRP_IMAGE_NOT_AT_BASE;
+
+ /* Find our region */
+ ImageBase = (ULONG_PTR)NtHeaders->OptionalHeader.ImageBase;
+ ImageEnd = ImageBase + ViewSize;
+
+ DPRINT1("LDR: LdrpMapDll Relocating Image Name %ws (%p -> %p)\n", DllName, ImageBase, ViewBase);
+
+ /* Scan all the modules */
+ ListHead = &Peb->Ldr->InLoadOrderModuleList;
+ NextEntry = ListHead->Flink;
+ while (NextEntry != ListHead)
+ {
+ /* Get the entry */
+ CandidateEntry = CONTAINING_RECORD(NextEntry,
+ LDR_DATA_TABLE_ENTRY,
+ InLoadOrderLinks);
+ NextEntry = NextEntry->Flink;
+
+ /* Get the entry's bounds */
+ CandidateBase = (ULONG_PTR)CandidateEntry->DllBase;
+ CandidateEnd = CandidateBase + CandidateEntry->SizeOfImage;
+
+ /* Make sure this entry isn't unloading */
+ if (!CandidateEntry->InMemoryOrderModuleList.Flink) continue;
+
+ /* Check if our regions are colliding */
+ if ((ImageBase >= CandidateBase && ImageBase <= CandidateEnd) ||
+ (ImageEnd >= CandidateBase && ImageEnd <= CandidateEnd) ||
+ (CandidateBase >= ImageBase && CandidateBase <= ImageEnd))
+ {
+ /* Found who is overlapping */
+ OverlapDllFound = TRUE;
+ OverlapDll = CandidateEntry->FullDllName;
+ break;
+ }
+ }
+
+ /* Check if we found the DLL overlapping with us */
+ if (!OverlapDllFound)
+ {
+ /* It's not another DLL, it's memory already here */
+ RtlInitUnicodeString(&OverlapDll, L"Dynamically Allocated Memory");
+ }
+
+ DPRINT1("Overlapping DLL: %wZ\n", &OverlapDll);
+
+ /* Are we dealing with a DLL? */
+ if (LdrEntry->Flags & LDRP_IMAGE_DLL)
+ {
+ /* Check if relocs were stripped */
+ if (!(NtHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED))
+ {
+ /* Get the relocation data */
+ RelocData = RtlImageDirectoryEntryToData(ViewBase,
+ TRUE,
+ IMAGE_DIRECTORY_ENTRY_BASERELOC,
+ &RelocDataSize);
+
+ /* Does the DLL not have any? */
+ if (!RelocData && !RelocDataSize)
+ {
+ /* We'll allow this and simply continue */
+ goto NoRelocNeeded;
+ }
+ }
+
+ /* See if this is an Illegal DLL - IE: user32 and kernel32 */
+ RtlInitUnicodeString(&IllegalDll,L"user32.dll");
+ if (RtlEqualUnicodeString(&BaseDllName, &IllegalDll, TRUE))
+ {
+ /* Can't relocate user32 */
+ RelocatableDll = FALSE;
+ }
+ else
+ {
+ RtlInitUnicodeString(&IllegalDll, L"kernel32.dll");
+ if (RtlEqualUnicodeString(&BaseDllName, &IllegalDll, TRUE))
+ {
+ /* Can't relocate kernel32 */
+ RelocatableDll = FALSE;
+ }
+ }
+
+ /* Check if this was a non-relocatable DLL or a known dll */
+ if (!RelocatableDll && KnownDll)
+ {
+ /* Setup for hard error */
+ HardErrorParameters[0] = (ULONG_PTR)&IllegalDll;
+ HardErrorParameters[1] = (ULONG_PTR)&OverlapDll;
+
+ /* Raise the error */
+ ZwRaiseHardError(STATUS_ILLEGAL_DLL_RELOCATION,
+ 2,
+ 3,
+ HardErrorParameters,
+ OptionOk,
+ &Response);
+
+ /* If initializing, increase the error count */
+ if (LdrpInLdrInit) LdrpFatalHardErrorCount++;
+
+ /* Don't do relocation */
+ Status = STATUS_CONFLICTING_ADDRESSES;
+ goto NoRelocNeeded;
+ }
+
+ /* Change the protection to prepare for relocation */
+ Status = LdrpSetProtection(ViewBase, FALSE);
+
+ /* Make sure we changed the protection */
+ if (NT_SUCCESS(Status))
+ {
+ /* Do the relocation */
+ Status = LdrRelocateImageWithBias(ViewBase, 0LL, NULL, STATUS_SUCCESS,
+ STATUS_CONFLICTING_ADDRESSES, STATUS_INVALID_IMAGE_FORMAT);
+
+ if (NT_SUCCESS(Status))
+ {
+ /* Stuff the image name in the TIB, for the debugger */
+ ArbitraryUserPointer = Teb->NtTib.ArbitraryUserPointer;
+ Teb->NtTib.ArbitraryUserPointer = FullDllName.Buffer;
+
+ /* Map the DLL */
+ Status = NtMapViewOfSection(SectionHandle,
+ NtCurrentProcess(),
+ &ViewBase,
+ 0,
+ 0,
+ NULL,
+ &ViewSize,
+ ViewShare,
+ 0,
+ PAGE_READWRITE);
+
+ /* Restore */
+ Teb->NtTib.ArbitraryUserPointer = ArbitraryUserPointer;
+
+ /* Return the protection */
+ Status = LdrpSetProtection(ViewBase, TRUE);
+ }
+ }
+//FailRelocate:
+ /* Handle any kind of failure */
+ if (!NT_SUCCESS(Status))
+ {
+ /* Remove it from the lists */
+ RemoveEntryList(&LdrEntry->InLoadOrderLinks);
+ RemoveEntryList(&LdrEntry->InMemoryOrderModuleList);
+ RemoveEntryList(&LdrEntry->HashLinks);
+
+ /* Unmap it, clear the entry */
+ NtUnmapViewOfSection(NtCurrentProcess(), ViewBase);
+ LdrEntry = NULL;
+ }
+
+ /* Show debug message */
+ if (ShowSnaps)
+ {
+ DPRINT1("LDR: Fixups %successfully re-applied @ %p\n",
+ NT_SUCCESS(Status) ? "s" : "uns", ViewBase);
+ }
+ }
+ else
+ {
+NoRelocNeeded:
+ /* Not a DLL, or no relocation needed */
+ Status = STATUS_SUCCESS;
+
+ /* Stuff the image name in the TIB, for the debugger */
+ ArbitraryUserPointer = Teb->NtTib.ArbitraryUserPointer;
+ Teb->NtTib.ArbitraryUserPointer = FullDllName.Buffer;
+
+ /* Map the DLL */
+ Status = NtMapViewOfSection(SectionHandle,
+ NtCurrentProcess(),
+ &ViewBase,
+ 0,
+ 0,
+ NULL,
+ &ViewSize,
+ ViewShare,
+ 0,
+ PAGE_READWRITE);
+
+ /* Restore */
+ Teb->NtTib.ArbitraryUserPointer = ArbitraryUserPointer;
+
+ /* Show debug message */
+ if (ShowSnaps)
+ {
+ DPRINT1("LDR: Fixups won't be re-applied to non-Dll @ %p\n", ViewBase);
+ }
+ }
+ }
- /* If it's 0 - return so */
- if (!EntryPoint) return NULL;
+ // FIXME: LdrpCheckCorImage() is missing
- /* Add image base */
- EntryPoint += (ULONG_PTR)ImageBase;
+ /* Check if this is an SMP Machine and a DLL */
+ if ((LdrpNumberOfProcessors > 1) &&
+ (LdrEntry && (LdrEntry->Flags & LDRP_IMAGE_DLL)))
+ {
+ /* Validate the image for MP */
+ LdrpValidateImageForMp(LdrEntry);
+ }
- /* Return calculated pointer */
- return (PVOID)EntryPoint;
-}
+ // FIXME: LdrpCorUnloadImage() is missing
-NTSTATUS
-NTAPI
-LdrpMapDll(IN PWSTR SearchPath OPTIONAL,
- IN PWSTR DllPath2,
- IN PWSTR DllName OPTIONAL,
- IN PULONG DllCharacteristics,
- IN BOOLEAN Static,
- IN BOOLEAN Redirect,
- OUT PLDR_DATA_TABLE_ENTRY *DataTableEntry)
-{
- UNIMPLEMENTED;
- return STATUS_SUCCESS;
+ /* Close section and return status */
+ NtClose(SectionHandle);
+ return Status;
}
PLDR_DATA_TABLE_ENTRY
PLDR_DATA_TABLE_ENTRY LdrEntry = NULL;
PIMAGE_NT_HEADERS NtHeader = RtlImageNtHeader(BaseAddress);
+ DPRINT("LdrpAllocateDataTableEntry(%p), NtHeader %p\n", BaseAddress, NtHeader);
+
/* Make sure the header is valid */
if (NtHeader)
{
InsertTailList(&PebData->InMemoryOrderModuleList, &LdrEntry->InMemoryOrderModuleList);
}
+VOID
+NTAPI
+LdrpFinalizeAndDeallocateDataTableEntry(PLDR_DATA_TABLE_ENTRY Entry)
+{
+ ASSERT(Entry != NULL);
+
+ /* Release the activation context if it exists */
+ if (Entry->EntryPointActivationContext)
+ {
+ /* Check if it wasn't already released */
+ if ((HANDLE)Entry->EntryPointActivationContext != INVALID_HANDLE_VALUE)
+ {
+ RtlReleaseActivationContext(Entry->EntryPointActivationContext);
+
+ /* Mark it as invalid */
+ Entry->EntryPointActivationContext = INVALID_HANDLE_VALUE;
+ }
+ }
+
+ /* Release the full dll name string */
+ if (Entry->FullDllName.Buffer)
+ LdrpFreeUnicodeString(&Entry->FullDllName);
+
+ /* Finally free the entry's memory */
+ RtlFreeHeap(RtlGetProcessHeap(), 0, Entry);
+}
+
BOOLEAN
NTAPI
LdrpCheckForLoadedDllHandle(IN PVOID Base,
PVOID ViewBase = NULL;
SIZE_T ViewSize = 0;
PIMAGE_NT_HEADERS NtHeader, NtHeader2;
-DPRINT1("LdrpCheckForLoadedDll('%S' '%wZ' %d %d %p)\n", DllPath, DllName, Flag, RedirectedDll, LdrEntry);
+
+ DPRINT("LdrpCheckForLoadedDll('%S' '%wZ' %d %d %p)\n", DllPath, DllName, Flag, RedirectedDll, LdrEntry);
+
/* Check if a dll name was provided */
if (!DllName->Buffer || !DllName->Buffer[0]) return FALSE;
if (Name)
{
/* Show debug message */
- if (ShowSnaps) DPRINT1("NAME - %s\n", Name->Buffer);
+ if (ShowSnaps) DbgPrint("NAME - %s\n", Name->Buffer);
/* Make sure it's not too long */
if ((Name->Length + sizeof(CHAR) + sizeof(USHORT)) > MAXLONG)
ImportName->Hint = 0;
/* Copy the name and null-terminate it */
- RtlMoveMemory(&ImportName->Name, Name->Buffer, Name->Length);
- ImportName->Name[Name->Length + 1] = 0;
+ RtlMoveMemory(ImportName->Name, Name->Buffer, Name->Length);
+ ImportName->Name[Name->Length] = 0;
/* Clear the high bit */
ImageBase = ImportName;
ImageBase = NULL;
/* Show debug message */
- if (ShowSnaps) DPRINT1("ORDINAL - %lx\n", Ordinal);
+ if (ShowSnaps) DbgPrint("ORDINAL - %lx\n", Ordinal);
if (Ordinal)
{
if (!LdrpCheckForLoadedDllHandle(BaseAddress, &LdrEntry))
{
/* Invalid base */
- DPRINT1("Invalid base address\n");
+ DPRINT1("Invalid base address %p\n", BaseAddress);
Status = STATUS_DLL_NOT_FOUND;
_SEH2_YIELD(goto Quickie;)
}
if (!ExportDir)
{
- DPRINT1("Image has no exports\n");
+ DPRINT1("Image %wZ has no exports, but were trying to get procedure %s. BaseAddress asked %p, got entry BA %p\n", &LdrEntry->BaseDllName, Name ? Name->Buffer : NULL, BaseAddress, LdrEntry->DllBase);
Status = STATUS_PROCEDURE_NOT_FOUND;
_SEH2_YIELD(goto Quickie;)
}
OUT PVOID *BaseAddress,
IN BOOLEAN CallInit)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ PPEB Peb = NtCurrentPeb();
+ NTSTATUS Status = STATUS_SUCCESS;
+ PWCHAR p1, p2;
+ WCHAR NameBuffer[266];
+ LPWSTR RawDllName;
+ UNICODE_STRING RawDllNameString;
+ PLDR_DATA_TABLE_ENTRY LdrEntry;
+ BOOLEAN InInit = LdrpInLdrInit;
+
+ /* Find the name without the extension */
+ p1 = DllName->Buffer;
+StartLoop:
+ p2 = NULL;
+ while (*p1)
+ {
+ if (*p1++ == L'.')
+ {
+ p2 = p1;
+ }
+ else if (*p1 == L'\\')
+ {
+ goto StartLoop;
+ }
+ }
+
+ /* Save the Raw DLL Name */
+ RawDllName = NameBuffer;
+ if (DllName->Length >= sizeof(NameBuffer))
+ {
+ /* The DLL's name is too long */
+ return STATUS_NAME_TOO_LONG;
+ }
+ RtlMoveMemory(RawDllName, DllName->Buffer, DllName->Length);
+
+ /* Check if no extension was found or if we got a slash */
+ if (!p2 || *p2 == '\\')
+ {
+ /* Check that we have space to add one */
+ if (DllName->Length + LdrApiDefaultExtension.Length >= sizeof(NameBuffer))
+ {
+ /* No space to add the extension */
+ return STATUS_NAME_TOO_LONG;
+ }
+
+ /* Add it */
+ RtlMoveMemory((PVOID)((ULONG_PTR)RawDllName + DllName->Length),
+ LdrApiDefaultExtension.Buffer,
+ LdrApiDefaultExtension.Length);
+
+ /* Save the length to a unicode string */
+ RawDllNameString.Length = DllName->Length + LdrApiDefaultExtension.Length;
+
+ /* Null terminate it */
+ RawDllName[RawDllNameString.Length / sizeof(WCHAR)] = 0;
+ }
+ else
+ {
+ /* Null terminate it */
+ RawDllName[DllName->Length / sizeof(WCHAR)] = 0;
+
+ /* Save the length to a unicode string */
+ RawDllNameString.Length = DllName->Length;
+ }
+
+ /* Now create a unicode string for the DLL's name */
+ RawDllNameString.MaximumLength = sizeof(NameBuffer);
+ RawDllNameString.Buffer = NameBuffer;
+
+ /* Check for init flag and acquire lock */
+ if (!InInit) RtlEnterCriticalSection(&LdrpLoaderLock);
+
+ /* Show debug message */
+ if (ShowSnaps)
+ {
+ DPRINT1("LDR: LdrLoadDll, loading %ws from %ws\n",
+ RawDllName,
+ DllPath ? DllPath : L"");
+ }
+
+ /* Check if the DLL is already loaded */
+ if (!LdrpCheckForLoadedDll(DllPath,
+ &RawDllNameString,
+ FALSE,
+ Redirected,
+ &LdrEntry))
+ {
+ /* Map it */
+ Status = LdrpMapDll(DllPath,
+ DllPath,
+ NameBuffer,
+ DllCharacteristics,
+ FALSE,
+ Redirected,
+ &LdrEntry);
+ if (!NT_SUCCESS(Status)) goto Quickie;
+
+ /* Check if IMAGE_FILE_EXECUTABLE_IMAGE was provided */
+ if (DllCharacteristics &&
+ (*DllCharacteristics & IMAGE_FILE_EXECUTABLE_IMAGE))
+ {
+ LdrEntry->EntryPoint = NULL;
+ LdrEntry->Flags &= ~LDRP_IMAGE_DLL;
+ }
+
+ /* FIXME Mark the DLL Ranges for Stack Traces later */
+
+ /* Make sure it's a DLL */
+ if (LdrEntry->Flags & LDRP_IMAGE_DLL)
+ {
+ /* Check if this is a .NET Image */
+ if (!(LdrEntry->Flags & LDRP_COR_IMAGE))
+ {
+ /* Walk the Import Descriptor */
+ Status = LdrpWalkImportDescriptor(DllPath, LdrEntry);
+ }
+
+ /* Update load count, unless it's locked */
+ if (LdrEntry->LoadCount != -1) LdrEntry->LoadCount++;
+ LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_REFCOUNT);
+
+ /* Check if we failed */
+ if (!NT_SUCCESS(Status))
+ {
+ /* Clear entrypoint, and insert into list */
+ LdrEntry->EntryPoint = NULL;
+ InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
+ &LdrEntry->InInitializationOrderModuleList);
+
+ /* Cancel the load and unload the DLL */
+ LdrpClearLoadInProgress();
+ LdrUnloadDll(LdrEntry->DllBase);
+
+ /* Return the error */
+ goto Quickie;
+ }
+ }
+ else if (LdrEntry->LoadCount != -1)
+ {
+ /* Increase load count */
+ LdrEntry->LoadCount++;
+ }
+
+ /* Insert it into the list */
+ InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
+ &LdrEntry->InInitializationOrderModuleList);
+
+ /* If we have to run the entrypoint, make sure the DB is ready */
+ if (CallInit && LdrpLdrDatabaseIsSetup)
+ {
+ /* FIXME: Notify Shim Engine */
+
+ /* Run the init routine */
+ Status = LdrpRunInitializeRoutines(NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Failed, unload the DLL */
+ LdrUnloadDll(LdrEntry->DllBase);
+ }
+ }
+ else
+ {
+ /* The DB isn't ready, which means we were loaded because of a forwarder */
+ Status = STATUS_SUCCESS;
+ }
+ }
+ else
+ {
+ /* We were already loaded. Are we a DLL? */
+ if ((LdrEntry->Flags & LDRP_IMAGE_DLL) && (LdrEntry->LoadCount != -1))
+ {
+ /* Increase load count */
+ LdrEntry->LoadCount++;
+ LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_REFCOUNT);
+
+ /* Clear the load in progress */
+ LdrpClearLoadInProgress();
+ }
+ else
+ {
+ /* Not a DLL, just increase the load count */
+ if (LdrEntry->LoadCount != -1) LdrEntry->LoadCount++;
+ }
+ }
+
+Quickie:
+ /* Release the lock */
+ if (!InInit) RtlLeaveCriticalSection(Peb->LoaderLock);
+
+ /* Check for success */
+ if (NT_SUCCESS(Status))
+ {
+ /* Return the base address */
+ *BaseAddress = LdrEntry->DllBase;
+ }
+ else
+ {
+ /* Nothing found */
+ *BaseAddress = NULL;
+ }
+
+ /* Return status */
+ return Status;
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+LdrUnloadDll(IN PVOID BaseAddress)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ PPEB Peb = NtCurrentPeb();
+ PLDR_DATA_TABLE_ENTRY LdrEntry, CurrentEntry;
+ PVOID EntryPoint;
+ PLIST_ENTRY NextEntry;
+ LIST_ENTRY UnloadList;
+ RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx;
+ PVOID CorImageData;
+ ULONG ComSectionSize;
+
+ /* Get the LDR Lock */
+ if (!LdrpInLdrInit) RtlEnterCriticalSection(Peb->LoaderLock);
+
+ /* Increase the unload count */
+ LdrpActiveUnloadCount++;
+
+ /* Skip unload */
+ if (LdrpShutdownInProgress) goto Quickie;
+
+ /* Make sure the DLL is valid and get its entry */
+ if (!LdrpCheckForLoadedDllHandle(BaseAddress, &LdrEntry))
+ {
+ Status = STATUS_DLL_NOT_FOUND;
+ goto Quickie;
+ }
+
+ /* Check the current Load Count */
+ if (LdrEntry->LoadCount != -1)
+ {
+ /* Decrease it */
+ LdrEntry->LoadCount--;
+
+ /* If it's a dll */
+ if (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);
+
+ /* Update the load count */
+ LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_DEREFCOUNT);
+
+ /* Release the context */
+ RtlDeactivateActivationContextUnsafeFast(&ActCtx);
+ }
+ }
+ else
+ {
+ /* The DLL is locked */
+ goto Quickie;
+ }
+
+ /* Show debug message */
+ if (ShowSnaps) DPRINT1("LDR: UNINIT LIST\n");
+
+ /* Check if this is our only unload */
+ if (LdrpActiveUnloadCount == 1)
+ {
+ /* Initialize the unload list */
+ InitializeListHead(&LdrpUnloadHead);
+ }
+
+ /* Loop the modules to build the list */
+ NextEntry = Peb->Ldr->InInitializationOrderModuleList.Blink;
+ while (NextEntry != &Peb->Ldr->InInitializationOrderModuleList)
+ {
+ /* Get the entry */
+ LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
+ NextEntry = NextEntry->Blink;
+
+ /* Remove flag */
+ LdrEntry->Flags &= ~LDRP_UNLOAD_IN_PROGRESS;
+
+ /* If the load count is now 0 */
+ if (!LdrEntry->LoadCount)
+ {
+ /* Show message */
+ if (ShowSnaps)
+ {
+ DPRINT1("(%d) [%ws] %ws (%lx) deinit %lx\n",
+ LdrpActiveUnloadCount,
+ LdrEntry->BaseDllName.Buffer,
+ LdrEntry->FullDllName.Buffer,
+ (ULONG)LdrEntry->LoadCount,
+ LdrEntry->EntryPoint);
+ }
+
+ /* FIXME: Call Shim Engine and notify */
+
+ /* Unlink it */
+ CurrentEntry = LdrEntry;
+ RemoveEntryList(&CurrentEntry->InInitializationOrderModuleList);
+ RemoveEntryList(&CurrentEntry->InMemoryOrderModuleList);
+ RemoveEntryList(&CurrentEntry->HashLinks);
+
+ /* If there's more then one active unload */
+ if (LdrpActiveUnloadCount > 1)
+ {
+ /* Flush the cached DLL handle and clear the list */
+ LdrpLoadedDllHandleCache = NULL;
+ CurrentEntry->InMemoryOrderModuleList.Flink = NULL;
+ }
+
+ /* Add the entry on the unload list */
+ InsertTailList(&LdrpUnloadHead, &CurrentEntry->HashLinks);
+ }
+ }
+
+ /* Only call the entrypoints once */
+ if (LdrpActiveUnloadCount > 1) goto Quickie;
+
+ /* Now loop the unload list and create our own */
+ InitializeListHead(&UnloadList);
+ CurrentEntry = NULL;
+ NextEntry = LdrpUnloadHead.Flink;
+ while (NextEntry != &LdrpUnloadHead)
+ {
+ /* If we have an active entry */
+ if (CurrentEntry)
+ {
+ /* Remove it */
+ RemoveEntryList(&CurrentEntry->InLoadOrderLinks);
+ CurrentEntry = NULL;
+
+ /* Reset list pointers */
+ NextEntry = LdrpUnloadHead.Flink;
+ if (NextEntry == &LdrpUnloadHead) break;
+ }
+
+ /* Get the current entry */
+ LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, HashLinks);
+
+ /* Log the Unload Event */
+ //LdrpRecordUnloadEvent(LdrEntry);
+
+ /* Set the entry and clear it from the list */
+ CurrentEntry = LdrEntry;
+ LdrpLoadedDllHandleCache = NULL;
+ CurrentEntry->InMemoryOrderModuleList.Flink = NULL;
+
+ /* Move it from the global to the local list */
+ RemoveEntryList(&CurrentEntry->HashLinks);
+ InsertTailList(&UnloadList, &CurrentEntry->HashLinks);
+
+ /* Get the entrypoint */
+ EntryPoint = LdrEntry->EntryPoint;
+
+ /* Check if we should call it */
+ if (EntryPoint && (LdrEntry->Flags & LDRP_PROCESS_ATTACH_CALLED))
+ {
+ /* Show message */
+ if (ShowSnaps)
+ {
+ DPRINT1("LDR: Calling deinit %lx\n", 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);
+
+ /* Call the entrypoint */
+ LdrpCallDllEntry(LdrEntry->EntryPoint,
+ LdrEntry->DllBase,
+ DLL_PROCESS_DETACH,
+ NULL);
+
+ /* Release the context */
+ RtlDeactivateActivationContextUnsafeFast(&ActCtx);
+ }
+
+ /* Remove it from the list */
+ RemoveEntryList(&CurrentEntry->InLoadOrderLinks);
+ CurrentEntry = NULL;
+ NextEntry = LdrpUnloadHead.Flink;
+ }
+
+ /* Now loop our local list */
+ NextEntry = UnloadList.Flink;
+ while (NextEntry != &UnloadList)
+ {
+ /* Get the entry */
+ LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, HashLinks);
+ NextEntry = NextEntry->Flink;
+ CurrentEntry = LdrEntry;
+
+ /* Notify Application Verifier */
+ if (Peb->NtGlobalFlag & FLG_HEAP_ENABLE_TAIL_CHECK)
+ {
+ DPRINT1("We don't support Application Verifier yet\n");
+ }
+
+ /* Show message */
+ if (ShowSnaps)
+ {
+ DPRINT1("LDR: Unmapping [%ws]\n", LdrEntry->BaseDllName.Buffer);
+ }
+
+ /* Check if this is a .NET executable */
+ if ((CorImageData = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
+ TRUE,
+ IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR,
+ &ComSectionSize)))
+ {
+ /* FIXME */
+ DPRINT1(".NET Images are not supported yet\n");
+ }
+
+ /* Check if we should unmap*/
+ if (!(CurrentEntry->Flags & LDR_COR_OWNS_UNMAP))
+ {
+ /* Unmap the DLL */
+ Status = NtUnmapViewOfSection(NtCurrentProcess(),
+ CurrentEntry->DllBase);
+ }
+
+ /* Unload the alternate resource module, if any */
+ LdrUnloadAlternateResourceModule(CurrentEntry->DllBase);
+
+ /* Send shutdown notification */
+ //LdrpSendDllNotifications(CurrentEntry, 2, LdrpShutdownInProgress);
+
+ /* Check if a Hotpatch is active */
+ if (LdrEntry->PatchInformation)
+ {
+ /* FIXME */
+ DPRINT1("We don't support Hotpatching yet\n");
+ }
+
+ /* Deallocate the Entry */
+ LdrpFinalizeAndDeallocateDataTableEntry(CurrentEntry);
+
+ /* If this is the cached entry, invalide it */
+ if (LdrpGetModuleHandleCache == CurrentEntry)
+ {
+ LdrpGetModuleHandleCache = NULL;
+ }
+ }
+
+Quickie:
+ /* Decrease unload count */
+ LdrpActiveUnloadCount--;
+ if (!LdrpInLdrInit) RtlLeaveCriticalSection(Peb->LoaderLock);
+
+ /* FIXME: Rundown the Hotpatch data, if present */
+
+ /* Return to caller */
+ return Status;
}
ULONG
return ModulesCount;
}
+/*
+ * @implemented
+ */
+NTSTATUS NTAPI
+LdrAddRefDll(IN ULONG Flags,
+ IN PVOID BaseAddress)
+{
+ PLDR_DATA_TABLE_ENTRY LdrEntry;
+ NTSTATUS Status = STATUS_SUCCESS;
+ ULONG Cookie;
+ BOOLEAN Locked = FALSE;
+
+ /* Check for invalid flags */
+ if (Flags & ~(LDR_PIN_MODULE))
+ {
+ /* Fail with invalid parameter status if so */
+ Status = STATUS_INVALID_PARAMETER;
+ goto quickie;
+ }
+
+ /* Acquire the loader lock if not in init phase */
+ if (!LdrpInLdrInit)
+ {
+ /* Acquire the lock */
+ Status = LdrLockLoaderLock(0, NULL, &Cookie);
+ if (!NT_SUCCESS(Status)) goto quickie;
+ Locked = TRUE;
+ }
+
+ /* Get this module's data table entry */
+ if (LdrpCheckForLoadedDllHandle(BaseAddress, &LdrEntry))
+ {
+ if (!LdrEntry)
+ {
+ /* Shouldn't happen */
+ Status = STATUS_INTERNAL_ERROR;
+ goto quickie;
+ }
+
+ /* If this is not a pinned module */
+ if (LdrEntry->LoadCount != -1)
+ {
+ /* Update its load count */
+ if (Flags & LDR_PIN_MODULE)
+ {
+ /* Pin it by setting load count to -1 */
+ LdrEntry->LoadCount = -1;
+ LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_PIN);
+ }
+ else
+ {
+ /* Increase its load count by one */
+ LdrEntry->LoadCount++;
+ LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_REFCOUNT);
+ }
+
+ /* Clear load in progress */
+ LdrpClearLoadInProgress();
+ }
+ }
+ else
+ {
+ /* There was an error getting this module's handle, return invalid param status */
+ Status = STATUS_INVALID_PARAMETER;
+ goto quickie;
+ }
+
+quickie:
+ if (!NT_SUCCESS(Status))
+ {
+ if (ShowSnaps ||
+ (Status != STATUS_NO_SUCH_FILE &&
+ Status != STATUS_DLL_NOT_FOUND &&
+ Status != STATUS_OBJECT_NAME_NOT_FOUND))
+ {
+ DPRINT1("LDR: LdrAddRefDll(%p) 0x%08lx\n", BaseAddress);
+ }
+ }
+
+ /* Release the lock if needed */
+ if (Locked) LdrUnlockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, Cookie);
+
+ return Status;
+}
+
+
+BOOLEAN
+NTAPI
+LdrpFreeUnicodeString(PUNICODE_STRING String)
+{
+ BOOLEAN Result = FALSE;
+
+ ASSERT(String != NULL);
+
+ /* If Buffer is not NULL - free it */
+ if (String->Buffer)
+ Result = RtlFreeHeap(RtlGetProcessHeap(), 0, String->Buffer);
+
+ /* Zero it out */
+ String->Length = 0;
+ String->MaximumLength = 0;
+ String->Buffer = NULL;
+
+ return Result;
+}
+
/* EOF */
/* 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);
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 */
static NTSTATUS LdrFindEntryForName(PUNICODE_STRING Name, PLDR_DATA_TABLE_ENTRY *Module, BOOLEAN Ref);
static PVOID LdrFixupForward(PCHAR ForwardName);
static PVOID LdrGetExportByName(PVOID BaseAddress, PUCHAR SymbolName, USHORT Hint);
-static NTSTATUS LdrpLoadModule(IN PWSTR SearchPath OPTIONAL,
- IN ULONG LoadFlags,
- IN PUNICODE_STRING Name,
- OUT PLDR_DATA_TABLE_ENTRY *Module,
- OUT PVOID *BaseAddress OPTIONAL);
-static VOID LdrpDetachProcess(BOOLEAN UnloadAll);
-static NTSTATUS LdrpUnloadModule(PLDR_DATA_TABLE_ENTRY Module, BOOLEAN Unload);
NTSTATUS find_actctx_dll( LPCWSTR libname, WCHAR *fulldosname );
NTSTATUS create_module_activation_context( LDR_DATA_TABLE_ENTRY *module );
/* FUNCTIONS *****************************************************************/
-BOOLEAN
-LdrMappedAsDataFile(PVOID *BaseAddress)
-{
- if (0 != ((DWORD_PTR) *BaseAddress & (PAGE_SIZE - 1)))
- {
- *BaseAddress = (PVOID)((DWORD_PTR)*BaseAddress & ~((DWORD_PTR) PAGE_SIZE - 1));
- return TRUE;
- }
-
- return FALSE;
-}
-
static __inline LONG LdrpDecrementLoadCount(PLDR_DATA_TABLE_ENTRY Module, BOOLEAN Locked)
{
LONG LoadCount;
return LoadCount;
}
-static PWSTR
-LdrpQueryAppPaths(IN PCWSTR ImageName)
-{
- PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
- OBJECT_ATTRIBUTES ObjectAttributes;
- WCHAR SearchPathBuffer[5*MAX_PATH];
- UNICODE_STRING ValueNameString;
- UNICODE_STRING KeyName;
- WCHAR NameBuffer[MAX_PATH];
- ULONG KeyInfoSize;
- ULONG ResultSize;
- PWCHAR Backslash;
- HANDLE KeyHandle;
- NTSTATUS Status;
- PWSTR Path = NULL;
-
- _snwprintf(NameBuffer,
- sizeof(NameBuffer) / sizeof(WCHAR),
- L"\\Registry\\Machine\\Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\%s",
- ImageName);
-
- RtlInitUnicodeString(&KeyName, NameBuffer);
-
- InitializeObjectAttributes(&ObjectAttributes,
- &KeyName,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- Status = NtOpenKey(&KeyHandle,
- KEY_READ,
- &ObjectAttributes);
- if (!NT_SUCCESS(Status))
- {
- DPRINT ("NtOpenKey() failed (Status %lx)\n", Status);
- return NULL;
- }
-
- KeyInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 256 * sizeof(WCHAR);
-
- KeyInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, KeyInfoSize);
- if (KeyInfo == NULL)
- {
- DPRINT("RtlAllocateHeap() failed\n");
- NtClose(KeyHandle);
- return NULL;
- }
-
- RtlInitUnicodeString(&ValueNameString,
- L"Path");
-
- Status = NtQueryValueKey(KeyHandle,
- &ValueNameString,
- KeyValuePartialInformation,
- KeyInfo,
- KeyInfoSize,
- &ResultSize);
-
- if (!NT_SUCCESS(Status))
- {
- NtClose(KeyHandle);
- RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
- return NULL;
- }
-
- RtlCopyMemory(SearchPathBuffer,
- &KeyInfo->Data,
- KeyInfo->DataLength);
-
- /* Free KeyInfo memory, we won't need it anymore */
- RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
-
- /* Close the key handle */
- NtClose(KeyHandle);
-
- /* get application running path */
- wcscat(SearchPathBuffer, L";");
- wcscat(SearchPathBuffer, NtCurrentPeb()->ProcessParameters->ImagePathName.Buffer); // FIXME: Don't rely on it being NULL-terminated!!!
-
- /* Remove trailing backslash */
- Backslash = wcsrchr(SearchPathBuffer, L'\\');
- if (Backslash) Backslash = L'\0';
-
- wcscat(SearchPathBuffer, L";");
-
- wcscat(SearchPathBuffer, SharedUserData->NtSystemRoot);
- wcscat(SearchPathBuffer, L"\\system32;");
- wcscat(SearchPathBuffer, SharedUserData->NtSystemRoot);
- wcscat(SearchPathBuffer, L";.");
-
- /* Copy it to the heap allocd memory */
- Path = RtlAllocateHeap(RtlGetProcessHeap(),
- 0,
- (wcslen(SearchPathBuffer) + 1) * sizeof(WCHAR));
-
- if (!Path)
- {
- DPRINT1("RtlAllocateHeap() failed\n");
- return NULL;
- }
-
- wcscpy(Path, SearchPathBuffer);
-
- return Path;
-}
-
-VOID
-LdrpInitLoader(VOID)
-{
- OBJECT_ATTRIBUTES ObjectAttributes;
- UNICODE_STRING LinkTarget;
- UNICODE_STRING Name;
- HANDLE LinkHandle;
- ULONG Length;
- NTSTATUS Status;
-
- DPRINT("LdrpInitLoader() called for %wZ\n", &LdrpImageEntry->BaseDllName);
-
- /* Get handle to the 'KnownDlls' directory */
- RtlInitUnicodeString(&Name,
- L"\\KnownDlls");
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
- Status = NtOpenDirectoryObject(&LdrpKnownDllObjectDirectory,
- DIRECTORY_QUERY | DIRECTORY_TRAVERSE,
- &ObjectAttributes);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("NtOpenDirectoryObject() failed (Status %lx)\n", Status);
- LdrpKnownDllObjectDirectory = NULL;
- return;
- }
-
- /* Allocate target name string */
- LinkTarget.Length = 0;
- LinkTarget.MaximumLength = MAX_PATH * sizeof(WCHAR);
- LinkTarget.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
- 0,
- MAX_PATH * sizeof(WCHAR));
- if (LinkTarget.Buffer == NULL)
- {
- NtClose(LdrpKnownDllObjectDirectory);
- LdrpKnownDllObjectDirectory = NULL;
- return;
- }
-
- RtlInitUnicodeString(&Name,
- L"KnownDllPath");
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- OBJ_CASE_INSENSITIVE,
- LdrpKnownDllObjectDirectory,
- NULL);
- Status = NtOpenSymbolicLinkObject(&LinkHandle,
- SYMBOLIC_LINK_ALL_ACCESS,
- &ObjectAttributes);
- if (!NT_SUCCESS(Status))
- {
- RtlFreeUnicodeString(&LinkTarget);
- NtClose(LdrpKnownDllObjectDirectory);
- LdrpKnownDllObjectDirectory = NULL;
- return;
- }
-
- Status = NtQuerySymbolicLinkObject(LinkHandle,
- &LinkTarget,
- &Length);
- NtClose(LinkHandle);
- if (!NT_SUCCESS(Status))
- {
- RtlFreeUnicodeString(&LinkTarget);
- NtClose(LdrpKnownDllObjectDirectory);
- LdrpKnownDllObjectDirectory = NULL;
- }
-
- RtlCreateUnicodeString(&LdrpKnownDllPath,
- LinkTarget.Buffer);
-
- RtlFreeUnicodeString(&LinkTarget);
-
- DPRINT("LdrpInitLoader() done\n");
-}
-
-
/***************************************************************************
* NAME LOCAL
* LdrAdjustDllName
PWCHAR Extension;
PWCHAR Pointer;
+ DPRINT1("\n");
+
Length = DllName->Length / sizeof(WCHAR);
if (BaseName)
{
PLDR_DATA_TABLE_ENTRY Module;
+ DPRINT1("\n");
+
Module = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof (LDR_DATA_TABLE_ENTRY));
ASSERT(Module);
memset(Module, 0, sizeof(LDR_DATA_TABLE_ENTRY));
return(Module);
}
-
-static NTSTATUS
-LdrpMapKnownDll(IN PUNICODE_STRING DllName,
- OUT PUNICODE_STRING FullDosName,
- OUT PHANDLE SectionHandle)
-{
- OBJECT_ATTRIBUTES ObjectAttributes;
- NTSTATUS Status;
-
- DPRINT("LdrpMapKnownDll() called\n");
-
- if (LdrpKnownDllObjectDirectory == NULL)
- {
- DPRINT("Invalid 'KnownDlls' directory\n");
- return STATUS_UNSUCCESSFUL;
- }
-
- DPRINT("LdrpKnownDllPath '%wZ'\n", &LdrpKnownDllPath);
-
- InitializeObjectAttributes(&ObjectAttributes,
- DllName,
- OBJ_CASE_INSENSITIVE,
- LdrpKnownDllObjectDirectory,
- NULL);
- Status = NtOpenSection(SectionHandle,
- SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE,
- &ObjectAttributes);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("NtOpenSection() failed for '%wZ' (Status 0x%08lx)\n", DllName, Status);
- return Status;
- }
-
- FullDosName->Length = LdrpKnownDllPath.Length + DllName->Length + sizeof(WCHAR);
- FullDosName->MaximumLength = FullDosName->Length + sizeof(WCHAR);
- FullDosName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
- 0,
- FullDosName->MaximumLength);
- if (FullDosName->Buffer == NULL)
- {
- FullDosName->Length = 0;
- FullDosName->MaximumLength = 0;
- return STATUS_SUCCESS;
- }
-
- wcscpy(FullDosName->Buffer, LdrpKnownDllPath.Buffer);
- wcscat(FullDosName->Buffer, L"\\");
- wcscat(FullDosName->Buffer, DllName->Buffer);
-
- DPRINT("FullDosName '%wZ'\n", FullDosName);
-
- DPRINT("LdrpMapKnownDll() done\n");
-
- return STATUS_SUCCESS;
-}
-
-
-static NTSTATUS
-LdrpMapDllImageFile(IN PWSTR SearchPath OPTIONAL,
- IN PUNICODE_STRING DllName,
- OUT PUNICODE_STRING FullDosName,
- IN BOOLEAN MapAsDataFile,
- OUT PHANDLE SectionHandle)
-{
- WCHAR *SearchPathBuffer = NULL;
- WCHAR *ImagePathNameBufferPtr = NULL;
- WCHAR DosName[MAX_PATH];
- UNICODE_STRING FullNtFileName;
- UNICODE_STRING PathEnvironmentVar_U;
- UNICODE_STRING PathName_U;
- OBJECT_ATTRIBUTES FileObjectAttributes;
- HANDLE FileHandle;
- char BlockBuffer [1024];
- PIMAGE_DOS_HEADER DosHeader;
- PIMAGE_NT_HEADERS NTHeaders;
- IO_STATUS_BLOCK IoStatusBlock;
- NTSTATUS Status;
- ULONG len;
- ULONG ImagePathLen;
-
- DPRINT("LdrpMapDllImageFile() called\n");
-
- if (SearchPath == NULL)
- {
- /* get application running path */
- ImagePathNameBufferPtr = NtCurrentPeb()->ProcessParameters->ImagePathName.Buffer;
-
- /* Length of ImagePathName */
- ImagePathLen = wcslen(ImagePathNameBufferPtr);
-
- /* Subtract application name leaveing only the directory length */
- while (ImagePathLen && ImagePathNameBufferPtr[ImagePathLen - 1] != L'\\')
- ImagePathLen--;
-
- /* Length of directory + semicolon */
- len = ImagePathLen + 1;
-
- /* Length of SystemRoot + "//system32" + semicolon*/
- len += wcslen(SharedUserData->NtSystemRoot) + 10;
- /* Length of SystemRoot + semicolon */
- len += wcslen(SharedUserData->NtSystemRoot) + 1;
-
- RtlInitUnicodeString (&PathName_U, L"PATH");
- PathEnvironmentVar_U.Length = 0;
- PathEnvironmentVar_U.MaximumLength = 0;
- PathEnvironmentVar_U.Buffer = NULL;
-
- /* Get the path environment variable */
- Status = RtlQueryEnvironmentVariable_U(NULL, &PathName_U, &PathEnvironmentVar_U);
-
- /* Check that valid information was returned */
- if ((Status == STATUS_BUFFER_TOO_SMALL) && (PathEnvironmentVar_U.Length > 0))
- {
- /* Allocate memory for the path env var */
- PathEnvironmentVar_U.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, PathEnvironmentVar_U.Length + sizeof(WCHAR));
- if (!PathEnvironmentVar_U.Buffer)
- {
- DPRINT1("Fatal! Out of Memory!!\n");
- return STATUS_NO_MEMORY;
- }
- PathEnvironmentVar_U.MaximumLength = PathEnvironmentVar_U.Length + sizeof(WCHAR);
-
- /* Retry */
- Status = RtlQueryEnvironmentVariable_U(NULL, &PathName_U, &PathEnvironmentVar_U);
-
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Unable to get path environment string!\n");
- ASSERT(FALSE);
- }
- /* Length of path evn var + semicolon */
- len += (PathEnvironmentVar_U.Length / sizeof(WCHAR)) + 1;
- }
-
- /* Allocate the size needed to hold all the above paths + period */
- SearchPathBuffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, (len + 2) * sizeof(WCHAR));
- if (!SearchPathBuffer)
- {
- DPRINT1("Fatal! Out of Memory!!\n");
- return STATUS_NO_MEMORY;
- }
-
- wcsncpy(SearchPathBuffer, ImagePathNameBufferPtr, ImagePathLen);
- wcscat (SearchPathBuffer, L";");
- wcscat (SearchPathBuffer, SharedUserData->NtSystemRoot);
- wcscat (SearchPathBuffer, L"\\system32;");
- wcscat (SearchPathBuffer, SharedUserData->NtSystemRoot);
- wcscat (SearchPathBuffer, L";");
-
- if (PathEnvironmentVar_U.Buffer)
- {
- wcscat (SearchPathBuffer, PathEnvironmentVar_U.Buffer);
- wcscat (SearchPathBuffer, L";");
- RtlFreeHeap(RtlGetProcessHeap(), 0, PathEnvironmentVar_U.Buffer);
- }
- wcscat (SearchPathBuffer, L".");
-
- SearchPath = SearchPathBuffer;
- }
-
- if (RtlDosSearchPath_U (SearchPath,
- DllName->Buffer,
- NULL,
- MAX_PATH,
- DosName,
- NULL) == 0)
- {
- /* try to find active context dll */
- Status = find_actctx_dll(DllName->Buffer, DosName);
- if(Status == STATUS_SUCCESS)
- DPRINT("found %S for %S\n", DosName,DllName->Buffer);
- else
- return STATUS_DLL_NOT_FOUND;
- }
-
- if (!RtlDosPathNameToNtPathName_U (DosName,
- &FullNtFileName,
- NULL,
- NULL))
- {
- DPRINT("Dll %wZ not found!\n", DllName);
- return STATUS_DLL_NOT_FOUND;
- }
-
- DPRINT("FullNtFileName %wZ\n", &FullNtFileName);
-
- InitializeObjectAttributes(&FileObjectAttributes,
- &FullNtFileName,
- 0,
- NULL,
- NULL);
-
- DPRINT("Opening dll \"%wZ\"\n", &FullNtFileName);
-
- Status = NtOpenFile(&FileHandle,
- GENERIC_READ|SYNCHRONIZE,
- &FileObjectAttributes,
- &IoStatusBlock,
- FILE_SHARE_READ,
- FILE_SYNCHRONOUS_IO_NONALERT);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Dll open of %wZ failed: Status = 0x%08lx\n",
- &FullNtFileName, Status);
- RtlFreeHeap (RtlGetProcessHeap (),
- 0,
- FullNtFileName.Buffer);
- return Status;
- }
- RtlFreeHeap (RtlGetProcessHeap (),
- 0,
- FullNtFileName.Buffer);
-
- if (!MapAsDataFile)
- {
-
- Status = NtReadFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- BlockBuffer,
- sizeof(BlockBuffer),
- NULL,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("Dll header read failed: Status = 0x%08lx\n", Status);
- NtClose(FileHandle);
- return Status;
- }
-
- /*
- * Overlay DOS and NT headers structures to the
- * buffer with DLL's header raw data.
- */
- DosHeader = (PIMAGE_DOS_HEADER) BlockBuffer;
- NTHeaders = (PIMAGE_NT_HEADERS) (BlockBuffer + DosHeader->e_lfanew);
- /*
- * Check it is a PE image file.
- */
- if ((DosHeader->e_magic != IMAGE_DOS_SIGNATURE)
- || (DosHeader->e_lfanew == 0L)
- || (*(PULONG)(NTHeaders) != IMAGE_NT_SIGNATURE))
- {
- DPRINT("NTDLL format invalid\n");
- NtClose(FileHandle);
-
- return STATUS_UNSUCCESSFUL;
- }
- }
-
- /*
- * Create a section for dll.
- */
- Status = NtCreateSection(SectionHandle,
- SECTION_ALL_ACCESS,
- NULL,
- NULL,
- PAGE_READONLY,
- MapAsDataFile ? SEC_COMMIT : SEC_IMAGE,
- FileHandle);
- NtClose(FileHandle);
-
- if (!NT_SUCCESS(Status))
- {
- DPRINT("NTDLL create section failed: Status = 0x%08lx\n", Status);
- return Status;
- }
-
- RtlCreateUnicodeString(FullDosName,
- DosName);
-
- return Status;
-}
-
-
-
-/***************************************************************************
- * NAME EXPORTED
- * LdrLoadDll
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * REVISIONS
- *
- * NOTE
- *
- * @implemented
- */
-NTSTATUS NTAPI
-LdrLoadDll (IN PWSTR SearchPath OPTIONAL,
- IN PULONG LoadFlags OPTIONAL,
- IN PUNICODE_STRING Name,
- OUT PVOID *BaseAddress /* also known as HMODULE*, and PHANDLE 'DllHandle' */)
-{
- NTSTATUS Status;
- PLDR_DATA_TABLE_ENTRY Module;
- ULONG_PTR cookie;
- PPEB Peb = NtCurrentPeb();
-
- TRACE_LDR("LdrLoadDll loading %wZ%S%S with flags %d\n",
- Name,
- SearchPath ? L" from " : L"",
- SearchPath ? SearchPath : L"",
- LoadFlags ? *LoadFlags : 0);
-
- Status = LdrpLoadModule(SearchPath, LoadFlags ? *LoadFlags : 0, Name, &Module, BaseAddress);
-
- if (NT_SUCCESS(Status) &&
- (!LoadFlags || 0 == (*LoadFlags & LOAD_LIBRARY_AS_DATAFILE)))
- {
- if (!create_module_activation_context( Module ))
- {
- RtlActivateActivationContext(0, Module->EntryPointActivationContext, &cookie);
- }
-
- if (!(Module->Flags & LDRP_PROCESS_ATTACH_CALLED))
- {
- RtlEnterCriticalSection(Peb->LoaderLock);
- Status = LdrpRunInitializeRoutines(NULL);
- RtlLeaveCriticalSection(Peb->LoaderLock);
- }
- if (Module->EntryPointActivationContext) RtlDeactivateActivationContext(0, cookie);
- }
-
- if ((!Module) && (NT_SUCCESS(Status)))
- return Status;
-
- *BaseAddress = NT_SUCCESS(Status) ? Module->DllBase : NULL;
-
- return Status;
-}
-
-
-/***************************************************************************
- * NAME EXPORTED
- * LdrFindEntryForAddress
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * REVISIONS
- *
- * NOTE
- *
- * @implemented
- */
-NTSTATUS NTAPI
-LdrFindEntryForAddress(PVOID Address,
- PLDR_DATA_TABLE_ENTRY *Module)
-{
- PLIST_ENTRY ModuleListHead;
- PLIST_ENTRY Entry;
- PLDR_DATA_TABLE_ENTRY ModulePtr;
-
- DPRINT("LdrFindEntryForAddress(Address %p)\n", Address);
-
- if (NtCurrentPeb()->Ldr == NULL)
- return(STATUS_NO_MORE_ENTRIES);
-
- RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock);
- ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
- Entry = ModuleListHead->Flink;
- if (Entry == ModuleListHead)
- {
- RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
- return(STATUS_NO_MORE_ENTRIES);
- }
-
- while (Entry != ModuleListHead)
- {
- ModulePtr = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
-
- DPRINT("Scanning %wZ at %p\n", &ModulePtr->BaseDllName, ModulePtr->DllBase);
-
- if ((Address >= ModulePtr->DllBase) &&
- ((ULONG_PTR)Address <= ((ULONG_PTR)ModulePtr->DllBase + ModulePtr->SizeOfImage)))
- {
- *Module = ModulePtr;
- RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
- return(STATUS_SUCCESS);
- }
-
- Entry = Entry->Flink;
- }
-
- DPRINT("Failed to find module entry.\n");
-
- RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
- return(STATUS_NO_MORE_ENTRIES);
-}
-
-
/***************************************************************************
* NAME LOCAL
* LdrFindEntryForName
PLDR_DATA_TABLE_ENTRY Module;
PVOID BaseAddress;
+ DPRINT1("\n");
+
strcpy(NameBuffer, ForwardName);
p = strchr(NameBuffer, '.');
if (p != NULL)
/**********************************************************************
* NAME LOCAL
- * LdrGetExportByOrdinal
+ * LdrGetExportByName
*
* DESCRIPTION
*
* REVISIONS
*
* NOTE
+ * AddressOfNames and AddressOfNameOrdinals are paralell tables,
+ * both with NumberOfNames entries.
*
*/
static PVOID
-LdrGetExportByOrdinal (
- PVOID BaseAddress,
- ULONG Ordinal
-)
-{
- PIMAGE_EXPORT_DIRECTORY ExportDir;
- ULONG ExportDirSize;
- PDWORD * ExFunctions;
- PVOID Function;
-
- ExportDir = (PIMAGE_EXPORT_DIRECTORY)
- RtlImageDirectoryEntryToData (BaseAddress,
- TRUE,
- IMAGE_DIRECTORY_ENTRY_EXPORT,
- &ExportDirSize);
-
-
- ExFunctions = (PDWORD*)RVA(BaseAddress, ExportDir->AddressOfFunctions);
- DPRINT("LdrGetExportByOrdinal(Ordinal %lu) = %p\n",
- Ordinal, RVA(BaseAddress, ExFunctions[Ordinal - ExportDir->Base]));
-
- Function = (0 != ExFunctions[Ordinal - ExportDir->Base]
- ? RVA(BaseAddress, ExFunctions[Ordinal - ExportDir->Base] )
- : NULL);
-
- if (((ULONG)Function >= (ULONG)ExportDir) &&
- ((ULONG)Function < (ULONG)ExportDir + (ULONG)ExportDirSize))
- {
- DPRINT("Forward: %s\n", (PCHAR)Function);
- Function = LdrFixupForward((PCHAR)Function);
- }
-
- return Function;
-}
-
-
-/**********************************************************************
- * NAME LOCAL
- * LdrGetExportByName
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * REVISIONS
- *
- * NOTE
- * AddressOfNames and AddressOfNameOrdinals are paralell tables,
- * both with NumberOfNames entries.
- *
- */
-static PVOID
-LdrGetExportByName(PVOID BaseAddress,
- PUCHAR SymbolName,
- WORD Hint)
+LdrGetExportByName(PVOID BaseAddress,
+ PUCHAR SymbolName,
+ WORD Hint)
{
PIMAGE_EXPORT_DIRECTORY ExportDir;
PDWORD *ExFunctions;
LONG_PTR Delta;
NTSTATUS Status;
+ DPRINT1("\n");
+
if (NTHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
{
return STATUS_SUCCESS;
return STATUS_SUCCESS;
}
-static NTSTATUS
-LdrpGetOrLoadModule(PWCHAR SearchPath,
- PCHAR Name,
- PLDR_DATA_TABLE_ENTRY* Module,
- BOOLEAN Load)
-{
- ANSI_STRING AnsiDllName;
- UNICODE_STRING DllName;
- NTSTATUS Status;
-
- DPRINT("LdrpGetOrLoadModule() called for %s\n", Name);
-
- RtlInitAnsiString(&AnsiDllName, Name);
- Status = RtlAnsiStringToUnicodeString(&DllName, &AnsiDllName, TRUE);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-
- Status = LdrFindEntryForName (&DllName, Module, Load);
- if (Load && !NT_SUCCESS(Status))
- {
- Status = LdrpLoadModule(SearchPath,
- 0,
- &DllName,
- Module,
- NULL);
- if (NT_SUCCESS(Status))
- {
- Status = LdrFindEntryForName (&DllName, Module, FALSE);
- }
- if (!NT_SUCCESS(Status))
- {
- ULONG ErrorResponse;
- ULONG_PTR ErrorParameter = (ULONG_PTR)&AnsiDllName;
-
- DPRINT1("failed to load %wZ\n", &DllName);
-
- NtRaiseHardError(STATUS_DLL_NOT_FOUND,
- 1,
- 1,
- &ErrorParameter,
- OptionOk,
- &ErrorResponse);
- }
- }
- RtlFreeUnicodeString (&DllName);
- return Status;
-}
-
void
RtlpRaiseImportNotFound(CHAR *FuncName, ULONG Ordinal, PUNICODE_STRING DllName)
{
ANSI_STRING DllNameAnsi;
CHAR Buffer[8];
+ DPRINT1("\n");
+
if (!FuncName)
{
_snprintf(Buffer, 8, "# %ld", Ordinal);
RtlFreeAnsiString(&DllNameAnsi);
}
-static NTSTATUS
-LdrpProcessImportDirectoryEntry(PLDR_DATA_TABLE_ENTRY Module,
- PLDR_DATA_TABLE_ENTRY ImportedModule,
- PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory)
+/*
+ * @implemented
+ */
+NTSTATUS NTAPI
+LdrDisableThreadCalloutsForDll(IN PVOID BaseAddress)
{
+ PLIST_ENTRY ModuleListHead;
+ PLIST_ENTRY Entry;
+ PLDR_DATA_TABLE_ENTRY Module;
NTSTATUS Status;
- PVOID* ImportAddressList;
- PULONG FunctionNameList;
- PVOID IATBase;
- ULONG OldProtect;
- ULONG Ordinal;
- ULONG IATSize;
-
- if (ImportModuleDirectory == NULL || ImportModuleDirectory->Name == 0)
- {
- return STATUS_UNSUCCESSFUL;
- }
-
- /* Get the import address list. */
- ImportAddressList = (PVOID *)((ULONG_PTR)Module->DllBase +
- (ULONG_PTR)ImportModuleDirectory->FirstThunk);
-
- /* Get the list of functions to import. */
- if (ImportModuleDirectory->OriginalFirstThunk != 0)
- {
- FunctionNameList = (PULONG)((ULONG_PTR)Module->DllBase +
- (ULONG_PTR)ImportModuleDirectory->OriginalFirstThunk);
- }
- else
- {
- FunctionNameList = (PULONG)((ULONG_PTR)Module->DllBase +
- (ULONG_PTR)ImportModuleDirectory->FirstThunk);
- }
- /* Get the size of IAT. */
- IATSize = 0;
- while (FunctionNameList[IATSize] != 0L)
- {
- IATSize++;
- }
-
- /* No need to fixup anything if IAT is empty */
- if (IATSize == 0) return STATUS_SUCCESS;
-
- /* Unprotect the region we are about to write into. */
- IATBase = (PVOID)ImportAddressList;
- IATSize *= sizeof(PVOID*);
- Status = NtProtectVirtualMemory(NtCurrentProcess(),
- &IATBase,
- &IATSize,
- PAGE_READWRITE,
- &OldProtect);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to unprotect IAT.\n");
- return(Status);
- }
-
- /* Walk through function list and fixup addresses. */
- while (*FunctionNameList != 0L)
- {
- if ((*FunctionNameList) & 0x80000000)
- {
- Ordinal = (*FunctionNameList) & 0x7fffffff;
- *ImportAddressList = LdrGetExportByOrdinal(ImportedModule->DllBase,
- Ordinal);
- if ((*ImportAddressList) == NULL)
- {
- DPRINT1("Failed to import #%ld from %wZ\n",
- Ordinal, &ImportedModule->FullDllName);
- RtlpRaiseImportNotFound(NULL, Ordinal, &ImportedModule->FullDllName);
- return STATUS_ENTRYPOINT_NOT_FOUND;
- }
- }
- else
- {
- IMAGE_IMPORT_BY_NAME *pe_name;
- pe_name = RVA(Module->DllBase, *FunctionNameList);
- *ImportAddressList = LdrGetExportByName(ImportedModule->DllBase,
- pe_name->Name,
- pe_name->Hint);
- if ((*ImportAddressList) == NULL)
- {
- DPRINT1("Failed to import %s from %wZ\n",
- pe_name->Name, &ImportedModule->FullDllName);
- RtlpRaiseImportNotFound((CHAR*)pe_name->Name,
- 0,
- &ImportedModule->FullDllName);
- return STATUS_ENTRYPOINT_NOT_FOUND;
- }
- }
- ImportAddressList++;
- FunctionNameList++;
- }
+ DPRINT("LdrDisableThreadCalloutsForDll (BaseAddress %p)\n", BaseAddress);
- /* Protect the region we are about to write into. */
- Status = NtProtectVirtualMemory(NtCurrentProcess(),
- &IATBase,
- &IATSize,
- OldProtect,
- &OldProtect);
- if (!NT_SUCCESS(Status))
+ Status = STATUS_DLL_NOT_FOUND;
+ RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
+ ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
+ Entry = ModuleListHead->Flink;
+ while (Entry != ModuleListHead)
{
- DPRINT1("Failed to protect IAT.\n");
- return(Status);
- }
-
- return STATUS_SUCCESS;
-}
-
-static NTSTATUS
-LdrpProcessImportDirectory(
- PLDR_DATA_TABLE_ENTRY Module,
- PLDR_DATA_TABLE_ENTRY ImportedModule,
- PCHAR ImportedName)
-{
- NTSTATUS Status;
- PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory;
- PCHAR Name;
- ULONG Size;
-
- DPRINT("LdrpProcessImportDirectory(%p '%wZ', '%s')\n",
- Module, &Module->BaseDllName, ImportedName);
-
+ Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
- ImportModuleDirectory = (PIMAGE_IMPORT_DESCRIPTOR)
- RtlImageDirectoryEntryToData(Module->DllBase,
- TRUE,
- IMAGE_DIRECTORY_ENTRY_IMPORT,
- &Size);
- if (ImportModuleDirectory == NULL)
- {
- return STATUS_UNSUCCESSFUL;
- }
+ DPRINT("BaseDllName %wZ BaseAddress %p\n", &Module->BaseDllName, Module->DllBase);
- while (ImportModuleDirectory->Name)
- {
- Name = (PCHAR)Module->DllBase + ImportModuleDirectory->Name;
- if (0 == _stricmp(Name, ImportedName))
+ if (Module->DllBase == BaseAddress)
{
- Status = LdrpProcessImportDirectoryEntry(Module,
- ImportedModule,
- ImportModuleDirectory);
- if (!NT_SUCCESS(Status))
+ if (Module->TlsIndex == 0xFFFF)
{
- return Status;
+ Module->Flags |= LDRP_DONT_CALL_FOR_THREADS;
+ Status = STATUS_SUCCESS;
}
+ break;
}
- ImportModuleDirectory++;
+ Entry = Entry->Flink;
}
-
-
- return STATUS_SUCCESS;
+ RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
+ return Status;
}
-
-static NTSTATUS
-LdrpAdjustImportDirectory(PLDR_DATA_TABLE_ENTRY Module,
- PLDR_DATA_TABLE_ENTRY ImportedModule,
- PCHAR ImportedName)
+/*
+ * @implemented
+ */
+BOOLEAN NTAPI
+RtlDllShutdownInProgress (VOID)
{
- PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory;
- NTSTATUS Status;
- PVOID* ImportAddressList;
- PVOID Start;
- PVOID End;
- PULONG FunctionNameList;
- PVOID IATBase;
- ULONG OldProtect;
- ULONG Offset;
- ULONG IATSize;
- PIMAGE_NT_HEADERS NTHeaders;
- PCHAR Name;
- ULONG Size;
-
- DPRINT("LdrpAdjustImportDirectory(Module %p '%wZ', %p '%wZ', '%s')\n",
- Module, &Module->BaseDllName, ImportedModule, &ImportedModule->BaseDllName, ImportedName);
-
- ImportModuleDirectory = (PIMAGE_IMPORT_DESCRIPTOR)
- RtlImageDirectoryEntryToData(Module->DllBase,
- TRUE,
- IMAGE_DIRECTORY_ENTRY_IMPORT,
- &Size);
- if (ImportModuleDirectory == NULL)
- {
- return STATUS_UNSUCCESSFUL;
- }
-
- while (ImportModuleDirectory->Name)
- {
- Name = (PCHAR)Module->DllBase + ImportModuleDirectory->Name;
- if (0 == _stricmp(Name, (PCHAR)ImportedName))
- {
-
- /* Get the import address list. */
- ImportAddressList = (PVOID *)((ULONG_PTR)Module->DllBase +
- (ULONG_PTR)ImportModuleDirectory->FirstThunk);
-
- /* Get the list of functions to import. */
- if (ImportModuleDirectory->OriginalFirstThunk != 0)
- {
- FunctionNameList = (PULONG)((ULONG_PTR)Module->DllBase +
- (ULONG_PTR)ImportModuleDirectory->OriginalFirstThunk);
- }
- else
- {
- FunctionNameList = (PULONG)((ULONG_PTR)Module->DllBase +
- (ULONG_PTR)ImportModuleDirectory->FirstThunk);
- }
-
- /* Get the size of IAT. */
- IATSize = 0;
- while (FunctionNameList[IATSize] != 0L)
- {
- IATSize++;
- }
-
- /* Unprotect the region we are about to write into. */
- IATBase = (PVOID)ImportAddressList;
- IATSize *= sizeof(PVOID*);
- Status = NtProtectVirtualMemory(NtCurrentProcess(),
- &IATBase,
- &IATSize,
- PAGE_READWRITE,
- &OldProtect);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to unprotect IAT.\n");
- return(Status);
- }
-
- NTHeaders = RtlImageNtHeader (ImportedModule->DllBase);
- Start = (PVOID)NTHeaders->OptionalHeader.ImageBase;
- End = (PVOID)((ULONG_PTR)Start + ImportedModule->SizeOfImage);
- Offset = (ULONG)((ULONG_PTR)ImportedModule->DllBase - (ULONG_PTR)Start);
-
- /* Walk through function list and fixup addresses. */
- while (*FunctionNameList != 0L)
- {
- if (*ImportAddressList >= Start && *ImportAddressList < End)
- {
- (*ImportAddressList) = (PVOID)((ULONG_PTR)(*ImportAddressList) + Offset);
- }
- ImportAddressList++;
- FunctionNameList++;
- }
-
- /* Protect the region we are about to write into. */
- Status = NtProtectVirtualMemory(NtCurrentProcess(),
- &IATBase,
- &IATSize,
- OldProtect,
- &OldProtect);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to protect IAT.\n");
- return(Status);
- }
- }
- ImportModuleDirectory++;
- }
- return STATUS_SUCCESS;
+ DPRINT1("\n");
+ return LdrpDllShutdownInProgress;
}
-
-/**********************************************************************
- * NAME LOCAL
- * LdrFixupImports
- *
- * DESCRIPTION
- * Compute the entry point for every symbol the DLL imports
- * from other modules.
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * REVISIONS
- *
- * NOTE
- *
+/*
+ * Compute size of an image as it is actually present in virt memory
+ * (i.e. excluding NEVER_LOAD sections)
*/
-static NTSTATUS
-LdrFixupImports(IN PWSTR SearchPath OPTIONAL,
- IN PLDR_DATA_TABLE_ENTRY Module)
+ULONG
+LdrpGetResidentSize(PIMAGE_NT_HEADERS NTHeaders)
{
- PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory;
- PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectoryCurrent;
- PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptor;
- PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent;
- PIMAGE_TLS_DIRECTORY TlsDirectory;
- ULONG TlsSize = 0;
- NTSTATUS Status = STATUS_SUCCESS;
- PLDR_DATA_TABLE_ENTRY ImportedModule;
- PCHAR ImportedName;
- PWSTR ModulePath;
- ULONG Size;
- ULONG_PTR cookie;
-
- DPRINT("LdrFixupImports(SearchPath %S, Module %p)\n", SearchPath, Module);
-
- /* Check for tls data */
- TlsDirectory = (PIMAGE_TLS_DIRECTORY)
- RtlImageDirectoryEntryToData(Module->DllBase,
- TRUE,
- IMAGE_DIRECTORY_ENTRY_TLS,
- &Size);
- if (TlsDirectory)
- {
- TlsSize = TlsDirectory->EndAddressOfRawData
- - TlsDirectory->StartAddressOfRawData
- + TlsDirectory->SizeOfZeroFill;
-
- if (TlsSize > 0 && NtCurrentPeb()->Ldr->Initialized)
- {
- TRACE_LDR("Trying to dynamically load %wZ which contains a TLS directory\n",
- &Module->BaseDllName);
- TlsDirectory = NULL;
- }
- }
-
- if (!create_module_activation_context( Module ))
- {
- if (Module->EntryPointActivationContext == NULL)
- {
- DPRINT("EntryPointActivationContext has not be allocated\n");
- DPRINT("Module->DllBaseName %wZ\n", Module->BaseDllName);
- }
- RtlActivateActivationContext( 0, Module->EntryPointActivationContext, &cookie );
- }
-
- /*
- * Process each import module.
- */
- ImportModuleDirectory = (PIMAGE_IMPORT_DESCRIPTOR)
- RtlImageDirectoryEntryToData(Module->DllBase,
- TRUE,
- IMAGE_DIRECTORY_ENTRY_IMPORT,
- &Size);
-
- BoundImportDescriptor = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)
- RtlImageDirectoryEntryToData(Module->DllBase,
- TRUE,
- IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT,
- &Size);
-
- if (BoundImportDescriptor != NULL && ImportModuleDirectory == NULL)
- {
- DPRINT1("%wZ has only a bound import directory\n", &Module->BaseDllName);
- return STATUS_UNSUCCESSFUL;
- }
- if (BoundImportDescriptor)
- {
- DPRINT("BoundImportDescriptor %p\n", BoundImportDescriptor);
-
- BoundImportDescriptorCurrent = BoundImportDescriptor;
- while (BoundImportDescriptorCurrent->OffsetModuleName)
- {
- ImportedName = (PCHAR)BoundImportDescriptor +
- BoundImportDescriptorCurrent->OffsetModuleName;
- TRACE_LDR("%wZ bound to %s\n", &Module->BaseDllName, ImportedName);
- Status = LdrpGetOrLoadModule(SearchPath, ImportedName, &ImportedModule, TRUE);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("failed to load %s\n", ImportedName);
- return Status;
- }
- if (Module == ImportedModule)
- {
- LdrpDecrementLoadCount(Module, FALSE);
- }
- if (ImportedModule->TimeDateStamp != BoundImportDescriptorCurrent->TimeDateStamp)
- {
- TRACE_LDR("%wZ has stale binding to %wZ\n",
- &Module->BaseDllName, &ImportedModule->BaseDllName);
- Status = LdrpProcessImportDirectory(Module, ImportedModule, ImportedName);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("failed to import %s\n", ImportedName);
- return Status;
- }
- }
- else
- {
- BOOLEAN WrongForwarder;
- WrongForwarder = FALSE;
- if (ImportedModule->Flags & LDRP_IMAGE_NOT_AT_BASE)
- {
- TRACE_LDR("%wZ has stale binding to %s\n",
- &Module->BaseDllName, ImportedName);
- }
- else
- {
- TRACE_LDR("%wZ has correct binding to %wZ\n",
- &Module->BaseDllName, &ImportedModule->BaseDllName);
- }
- if (BoundImportDescriptorCurrent->NumberOfModuleForwarderRefs)
- {
- PIMAGE_BOUND_FORWARDER_REF BoundForwarderRef;
- ULONG i;
- PLDR_DATA_TABLE_ENTRY ForwarderModule;
- PCHAR ForwarderName;
-
- BoundForwarderRef = (PIMAGE_BOUND_FORWARDER_REF)(BoundImportDescriptorCurrent + 1);
- for (i = 0;
- i < BoundImportDescriptorCurrent->NumberOfModuleForwarderRefs;
- i++, BoundForwarderRef++)
- {
- ForwarderName = (PCHAR)BoundImportDescriptor +
- BoundForwarderRef->OffsetModuleName;
- TRACE_LDR("%wZ bound to %s via forwardes from %s\n",
- &Module->BaseDllName, ForwarderName, ImportedName);
- Status = LdrpGetOrLoadModule(SearchPath, ForwarderName, &ForwarderModule, TRUE);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("failed to load %s\n", ForwarderName);
- return Status;
- }
- if (Module == ImportedModule)
- {
- LdrpDecrementLoadCount(Module, FALSE);
- }
- if (ForwarderModule->TimeDateStamp != BoundForwarderRef->TimeDateStamp ||
- ForwarderModule->Flags & LDRP_IMAGE_NOT_AT_BASE)
- {
- TRACE_LDR("%wZ has stale binding to %s\n",
- &Module->BaseDllName, ForwarderName);
- WrongForwarder = TRUE;
- }
- else
- {
- TRACE_LDR("%wZ has correct binding to %s\n",
- &Module->BaseDllName, ForwarderName);
- }
- }
- }
- if (WrongForwarder ||
- ImportedModule->Flags & LDRP_IMAGE_NOT_AT_BASE)
- {
- Status = LdrpProcessImportDirectory(Module, ImportedModule, ImportedName);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("failed to import %s\n", ImportedName);
- return Status;
- }
- }
- else if (ImportedModule->Flags & LDRP_IMAGE_NOT_AT_BASE)
- {
- TRACE_LDR("Adjust imports for %s from %wZ\n",
- ImportedName, &Module->BaseDllName);
- Status = LdrpAdjustImportDirectory(Module, ImportedModule, ImportedName);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("failed to adjust import entries for %s\n", ImportedName);
- return Status;
- }
- }
- else if (WrongForwarder)
- {
- /*
- * FIXME:
- * Update only forwarders
- */
- TRACE_LDR("Stale BIND %s from %wZ\n",
- ImportedName, &Module->BaseDllName);
- Status = LdrpProcessImportDirectory(Module, ImportedModule, ImportedName);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("faild to import %s\n", ImportedName);
- return Status;
- }
- }
- else
- {
- /* nothing to do */
- }
- }
- BoundImportDescriptorCurrent += BoundImportDescriptorCurrent->NumberOfModuleForwarderRefs + 1;
- }
- }
- else if (ImportModuleDirectory)
- {
- DPRINT("ImportModuleDirectory %p\n", ImportModuleDirectory);
-
- ImportModuleDirectoryCurrent = ImportModuleDirectory;
- while (ImportModuleDirectoryCurrent->Name)
- {
- ImportedName = (PCHAR)Module->DllBase + ImportModuleDirectoryCurrent->Name;
- TRACE_LDR("%wZ imports functions from %s\n", &Module->BaseDllName, ImportedName);
-
- if (SearchPath == NULL)
- {
- ModulePath = LdrpQueryAppPaths(Module->BaseDllName.Buffer);
-
- Status = LdrpGetOrLoadModule(ModulePath, ImportedName, &ImportedModule, TRUE);
- if (ModulePath != NULL) RtlFreeHeap(RtlGetProcessHeap(), 0, ModulePath);
- if (NT_SUCCESS(Status)) goto Success;
- }
-
- Status = LdrpGetOrLoadModule(SearchPath, ImportedName, &ImportedModule, TRUE);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("failed to load %s\n", ImportedName);
- break;
- }
-Success:
- if (Module == ImportedModule)
- {
- LdrpDecrementLoadCount(Module, FALSE);
- }
+ PIMAGE_SECTION_HEADER SectionHeader;
+ unsigned SectionIndex;
+ ULONG ResidentSize;
- TRACE_LDR("Initializing imports for %wZ from %s\n",
- &Module->BaseDllName, ImportedName);
- Status = LdrpProcessImportDirectoryEntry(Module, ImportedModule, ImportModuleDirectoryCurrent);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("failed to import %s\n", ImportedName);
- break;
- }
- ImportModuleDirectoryCurrent++;
- }
-
- if (!NT_SUCCESS(Status))
- {
- NTSTATUS errorStatus = Status;
-
- while (ImportModuleDirectoryCurrent >= ImportModuleDirectory)
- {
- ImportedName = (PCHAR)Module->DllBase + ImportModuleDirectoryCurrent->Name;
-
- Status = LdrpGetOrLoadModule(NULL, ImportedName, &ImportedModule, FALSE);
- if (NT_SUCCESS(Status) && Module != ImportedModule)
- {
- Status = LdrpUnloadModule(ImportedModule, FALSE);
- if (!NT_SUCCESS(Status)) DPRINT1("unable to unload %s\n", ImportedName);
- }
- ImportModuleDirectoryCurrent--;
- }
- return errorStatus;
- }
- }
-
- if (Module->EntryPointActivationContext) RtlDeactivateActivationContext( 0, cookie );
-
- return STATUS_SUCCESS;
-}
-
-
-/**********************************************************************
- * NAME
- * LdrPEStartup
- *
- * DESCRIPTION
- * 1. Relocate, if needed the EXE.
- * 2. Fixup any imported symbol.
- * 3. Compute the EXE's entry point.
- *
- * ARGUMENTS
- * ImageBase
- * Address at which the EXE's image
- * is loaded.
- *
- * SectionHandle
- * Handle of the section that contains
- * the EXE's image.
- *
- * RETURN VALUE
- * NULL on error; otherwise the entry point
- * to call for initializing the DLL.
- *
- * REVISIONS
- *
- * NOTE
- * 04.01.2004 hb Previous this function was used for all images (dll + exe).
- * Currently the function is only used for the exe.
- */
-PEPFUNC LdrPEStartup (PVOID ImageBase,
- HANDLE SectionHandle,
- PLDR_DATA_TABLE_ENTRY* Module,
- PWSTR FullDosName)
-{
- NTSTATUS Status;
- PEPFUNC EntryPoint = NULL;
- PIMAGE_DOS_HEADER DosHeader;
- PIMAGE_NT_HEADERS NTHeaders;
- PLDR_DATA_TABLE_ENTRY tmpModule;
- PVOID ActivationContextStack;
-
- DPRINT("LdrPEStartup(ImageBase %p SectionHandle %p)\n",
- ImageBase, SectionHandle);
-
- /*
- * Overlay DOS and WNT headers structures
- * to the DLL's image.
- */
- DosHeader = (PIMAGE_DOS_HEADER) ImageBase;
- NTHeaders = (PIMAGE_NT_HEADERS) ((ULONG_PTR)ImageBase + DosHeader->e_lfanew);
-
- /*
- * If the base address is different from the
- * one the DLL is actually loaded, perform any
- * relocation.
- */
- if (ImageBase != (PVOID)NTHeaders->OptionalHeader.ImageBase)
- {
- DPRINT("LDR: Performing relocations\n");
- Status = LdrPerformRelocations(NTHeaders, ImageBase);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("LdrPerformRelocations() failed\n");
- return NULL;
- }
- }
-
- if (Module != NULL)
- {
- *Module = LdrAddModuleEntry(ImageBase, NTHeaders, FullDosName);
- (*Module)->SectionPointer = SectionHandle;
- }
- else
- {
- Module = &tmpModule;
- Status = LdrFindEntryForAddress(ImageBase, Module);
- if (!NT_SUCCESS(Status))
- {
- return NULL;
- }
- }
-
- if (ImageBase != (PVOID) NTHeaders->OptionalHeader.ImageBase)
- {
- (*Module)->Flags |= LDRP_IMAGE_NOT_AT_BASE;
- }
-
- /* Allocate memory for the ActivationContextStack */
- /* FIXME: Verify RtlAllocateActivationContextStack behavior */
- Status = RtlAllocateActivationContextStack(&ActivationContextStack);
- if (NT_SUCCESS(Status))
- {
- DPRINT("ActivationContextStack %x\n",ActivationContextStack);
- DPRINT("ActiveFrame %x\n", ((PACTIVATION_CONTEXT_STACK)ActivationContextStack)->ActiveFrame);
- NtCurrentTeb()->ActivationContextStackPointer = ActivationContextStack;
- NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NULL;
- }
- else
- DPRINT1("Warning: Unable to allocate ActivationContextStack\n");
-
- /*
- * If the DLL's imports symbols from other
- * modules, fixup the imported calls entry points.
- */
- DPRINT("About to fixup imports\n");
- Status = LdrFixupImports(NULL, *Module);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("LdrFixupImports() failed for %wZ\n", &(*Module)->BaseDllName);
- return NULL;
- }
- DPRINT("Fixup done\n");
- RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock);
- Status = LdrpInitializeTls();
- if (NT_SUCCESS(Status))
- {
- Status = LdrpRunInitializeRoutines(NULL);
- }
- if (NT_SUCCESS(Status))
- {
- LdrpTlsCallback((*Module)->DllBase, DLL_PROCESS_ATTACH);
- }
-
-
- RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
- if (!NT_SUCCESS(Status))
- {
- return NULL;
- }
-
- /*
- * Compute the DLL's entry point's address.
- */
- DPRINT("ImageBase = %p\n", ImageBase);
- DPRINT("AddressOfEntryPoint = 0x%lx\n",(ULONG)NTHeaders->OptionalHeader.AddressOfEntryPoint);
- if (NTHeaders->OptionalHeader.AddressOfEntryPoint != 0)
- {
- EntryPoint = (PEPFUNC) ((ULONG_PTR)ImageBase
- + NTHeaders->OptionalHeader.AddressOfEntryPoint);
- }
- DPRINT("LdrPEStartup() = %p\n",EntryPoint);
- return EntryPoint;
-}
-
-static NTSTATUS
-LdrpLoadModule(IN PWSTR SearchPath OPTIONAL,
- IN ULONG LoadFlags,
- IN PUNICODE_STRING Name,
- PLDR_DATA_TABLE_ENTRY *Module,
- PVOID *BaseAddress OPTIONAL)
-{
- UNICODE_STRING AdjustedName;
- UNICODE_STRING FullDosName;
- NTSTATUS Status;
- PLDR_DATA_TABLE_ENTRY tmpModule;
- HANDLE SectionHandle;
- SIZE_T ViewSize;
- PVOID ImageBase;
- PIMAGE_NT_HEADERS NtHeaders;
- BOOLEAN MappedAsDataFile;
- PVOID ArbitraryUserPointer;
-
- if (Module == NULL)
- {
- Module = &tmpModule;
- }
- /* adjust the full dll name */
- LdrAdjustDllName(&AdjustedName, Name, FALSE);
-
- DPRINT("%wZ\n", &AdjustedName);
-
- MappedAsDataFile = FALSE;
- /* Test if dll is already loaded */
- Status = LdrFindEntryForName(&AdjustedName, Module, TRUE);
- if (NT_SUCCESS(Status))
- {
- RtlFreeUnicodeString(&AdjustedName);
- if (NULL != BaseAddress)
- {
- *BaseAddress = (*Module)->DllBase;
- }
- }
- else
- {
- /* Open or create dll image section */
- Status = LdrpMapKnownDll(&AdjustedName, &FullDosName, &SectionHandle);
- if (!NT_SUCCESS(Status))
- {
- MappedAsDataFile = (0 != (LoadFlags & LOAD_LIBRARY_AS_DATAFILE));
- Status = LdrpMapDllImageFile(SearchPath, &AdjustedName, &FullDosName,
- MappedAsDataFile, &SectionHandle);
- }
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to create or open dll section of '%wZ' (Status %lx)\n",
- &AdjustedName, Status);
- RtlFreeUnicodeString(&AdjustedName);
- return Status;
- }
- RtlFreeUnicodeString(&AdjustedName);
- /* Map the dll into the process */
- ViewSize = 0;
- ImageBase = 0;
- ArbitraryUserPointer = NtCurrentTeb()->NtTib.ArbitraryUserPointer;
- NtCurrentTeb()->NtTib.ArbitraryUserPointer = FullDosName.Buffer;
- Status = NtMapViewOfSection(SectionHandle,
- NtCurrentProcess(),
- &ImageBase,
- 0,
- 0,
- NULL,
- &ViewSize,
- ViewShare,
- 0,
- PAGE_READONLY);
- NtCurrentTeb()->NtTib.ArbitraryUserPointer = ArbitraryUserPointer;
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("map view of section failed (Status 0x%08lx)\n", Status);
- RtlFreeUnicodeString(&FullDosName);
- NtClose(SectionHandle);
- return(Status);
- }
- if (NULL != BaseAddress)
- {
- *BaseAddress = ImageBase;
- }
- if (!MappedAsDataFile)
- {
- /* Get and check the NT headers */
- NtHeaders = RtlImageNtHeader(ImageBase);
- if (NtHeaders == NULL)
- {
- DPRINT1("RtlImageNtHeaders() failed\n");
- NtUnmapViewOfSection (NtCurrentProcess (), ImageBase);
- NtClose (SectionHandle);
- RtlFreeUnicodeString(&FullDosName);
- return STATUS_UNSUCCESSFUL;
- }
- }
- DPRINT("Mapped %wZ at %x\n", &FullDosName, ImageBase);
- if (MappedAsDataFile)
- {
- ASSERT(NULL != BaseAddress);
- if (NULL != BaseAddress)
- {
- *BaseAddress = (PVOID) ((char *) *BaseAddress + 1);
- }
- *Module = NULL;
- RtlFreeUnicodeString(&FullDosName);
- NtClose(SectionHandle);
- return STATUS_SUCCESS;
- }
- /* If the base address is different from the
- * one the DLL is actually loaded, perform any
- * relocation. */
- if (ImageBase != (PVOID) NtHeaders->OptionalHeader.ImageBase)
- {
- DPRINT1("Relocating (%lx -> %p) %wZ\n",
- NtHeaders->OptionalHeader.ImageBase, ImageBase, &FullDosName);
- Status = LdrPerformRelocations(NtHeaders, ImageBase);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("LdrPerformRelocations() failed\n");
- NtUnmapViewOfSection (NtCurrentProcess (), ImageBase);
- NtClose (SectionHandle);
- RtlFreeUnicodeString(&FullDosName);
- return STATUS_UNSUCCESSFUL;
- }
- }
- *Module = LdrAddModuleEntry(ImageBase, NtHeaders, FullDosName.Buffer);
- (*Module)->SectionPointer = SectionHandle;
- if (ImageBase != (PVOID) NtHeaders->OptionalHeader.ImageBase)
- {
- (*Module)->Flags |= LDRP_IMAGE_NOT_AT_BASE;
- }
- if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL)
- {
- (*Module)->Flags |= LDRP_IMAGE_DLL;
- }
- /* fixup the imported calls entry points */
- Status = LdrFixupImports(SearchPath, *Module);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("LdrFixupImports failed for %wZ, status=%x\n", &(*Module)->BaseDllName, Status);
- NtUnmapViewOfSection (NtCurrentProcess (), ImageBase);
- NtClose (SectionHandle);
- RtlFreeUnicodeString (&FullDosName);
- RtlFreeUnicodeString (&(*Module)->FullDllName);
- RtlFreeUnicodeString (&(*Module)->BaseDllName);
- RemoveEntryList (&(*Module)->InLoadOrderLinks);
- return Status;
- }
-
- RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock);
- InsertTailList(&NtCurrentPeb()->Ldr->InInitializationOrderModuleList,
- &(*Module)->InInitializationOrderModuleList);
- RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
- }
- return STATUS_SUCCESS;
-}
-
-static NTSTATUS
-LdrpUnloadModule(PLDR_DATA_TABLE_ENTRY Module,
- BOOLEAN Unload)
-{
- PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory;
- PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptor;
- PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent;
- PCHAR ImportedName;
- PLDR_DATA_TABLE_ENTRY ImportedModule;
- NTSTATUS Status = 0;
- LONG LoadCount;
- ULONG Size;
-
- if (Unload)
- {
- RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock);
- }
-
- LoadCount = LdrpDecrementLoadCount(Module, Unload);
-
- TRACE_LDR("Unload %wZ, LoadCount %d\n", &Module->BaseDllName, LoadCount);
-
- if (LoadCount == 0)
- {
- /* ?????????????????? */
- }
- else if (!(Module->Flags & LDRP_STATIC_LINK) && LoadCount == 1)
- {
- BoundImportDescriptor = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)
- RtlImageDirectoryEntryToData(Module->DllBase,
- TRUE,
- IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT,
- &Size);
- if (BoundImportDescriptor)
- {
- /* dereferencing all imported modules, use the bound import descriptor */
- BoundImportDescriptorCurrent = BoundImportDescriptor;
- while (BoundImportDescriptorCurrent->OffsetModuleName)
- {
- ImportedName = (PCHAR)BoundImportDescriptor + BoundImportDescriptorCurrent->OffsetModuleName;
- TRACE_LDR("%wZ trys to unload %s\n", &Module->BaseDllName, ImportedName);
- Status = LdrpGetOrLoadModule(NULL, ImportedName, &ImportedModule, FALSE);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("unable to found imported modul %s\n", ImportedName);
- }
- else
- {
- if (Module != ImportedModule)
- {
- Status = LdrpUnloadModule(ImportedModule, FALSE);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("unable to unload %s\n", ImportedName);
- }
- }
- }
- BoundImportDescriptorCurrent++;
- }
- }
- else
- {
- ImportModuleDirectory = (PIMAGE_IMPORT_DESCRIPTOR)
- RtlImageDirectoryEntryToData(Module->DllBase,
- TRUE,
- IMAGE_DIRECTORY_ENTRY_IMPORT,
- &Size);
- if (ImportModuleDirectory)
- {
- /* dereferencing all imported modules, use the import descriptor */
- while (ImportModuleDirectory->Name)
- {
- ImportedName = (PCHAR)Module->DllBase + ImportModuleDirectory->Name;
- TRACE_LDR("%wZ trys to unload %s\n", &Module->BaseDllName, ImportedName);
- Status = LdrpGetOrLoadModule(NULL, ImportedName, &ImportedModule, FALSE);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("unable to found imported modul %s\n", ImportedName);
- }
- else
- {
- if (Module != ImportedModule)
- {
- Status = LdrpUnloadModule(ImportedModule, FALSE);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("unable to unload %s\n", ImportedName);
- }
- }
- }
- ImportModuleDirectory++;
- }
- }
- }
- }
-
- if (Unload)
- {
- if (!(Module->Flags & LDRP_STATIC_LINK))
- {
- LdrpDetachProcess(FALSE);
- }
-
- RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
- }
- return STATUS_SUCCESS;
-
-}
-
-/*
- * @implemented
- */
-NTSTATUS NTAPI
-LdrUnloadDll (IN PVOID BaseAddress)
-{
- PLDR_DATA_TABLE_ENTRY Module;
- NTSTATUS Status;
-
- if (BaseAddress == NULL)
- return STATUS_SUCCESS;
-
- if (LdrMappedAsDataFile(&BaseAddress))
- {
- Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
- }
- else
- {
- Status = LdrFindEntryForAddress(BaseAddress, &Module);
- if (NT_SUCCESS(Status))
- {
- TRACE_LDR("LdrUnloadDll, , unloading %wZ\n", &Module->BaseDllName);
- Status = LdrpUnloadModule(Module, TRUE);
- }
- }
-
- return Status;
-}
-
-/*
- * @implemented
- */
-NTSTATUS NTAPI
-LdrDisableThreadCalloutsForDll(IN PVOID BaseAddress)
-{
- PLIST_ENTRY ModuleListHead;
- PLIST_ENTRY Entry;
- PLDR_DATA_TABLE_ENTRY Module;
- NTSTATUS Status;
-
- DPRINT("LdrDisableThreadCalloutsForDll (BaseAddress %p)\n", BaseAddress);
-
- Status = STATUS_DLL_NOT_FOUND;
- RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
- ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
- Entry = ModuleListHead->Flink;
- while (Entry != ModuleListHead)
- {
- Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
-
- DPRINT("BaseDllName %wZ BaseAddress %p\n", &Module->BaseDllName, Module->DllBase);
-
- if (Module->DllBase == BaseAddress)
- {
- if (Module->TlsIndex == 0xFFFF)
- {
- Module->Flags |= LDRP_DONT_CALL_FOR_THREADS;
- Status = STATUS_SUCCESS;
- }
- break;
- }
- Entry = Entry->Flink;
- }
- RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
- return Status;
-}
-
-/*
- * @implemented
- */
-NTSTATUS NTAPI
-LdrGetDllHandle(IN PWSTR DllPath OPTIONAL,
- IN PULONG DllCharacteristics,
- IN PUNICODE_STRING DllName,
- OUT PVOID *DllHandle)
-{
- PLDR_DATA_TABLE_ENTRY Module;
- NTSTATUS Status;
-
- TRACE_LDR("LdrGetDllHandle, searching for %wZ from %S\n",
- DllName, DllPath ? DllPath : L"");
-
- /* NULL is the current executable */
- if (DllName == NULL)
- {
- *DllHandle = LdrpImageEntry->DllBase;
- DPRINT("BaseAddress 0x%lx\n", *DllHandle);
- return STATUS_SUCCESS;
- }
-
- Status = LdrFindEntryForName(DllName, &Module, FALSE);
- if (NT_SUCCESS(Status))
- {
- *DllHandle = Module->DllBase;
- return STATUS_SUCCESS;
- }
-
- DPRINT("Failed to find dll %wZ\n", DllName);
- *DllHandle = NULL;
- return STATUS_DLL_NOT_FOUND;
-}
-
-/*
- * @implemented
- */
-NTSTATUS NTAPI
-LdrAddRefDll(IN ULONG Flags,
- IN PVOID BaseAddress)
-{
- PLIST_ENTRY ModuleListHead;
- PLIST_ENTRY Entry;
- PLDR_DATA_TABLE_ENTRY Module;
- NTSTATUS Status;
-
- if (Flags & ~(LDR_PIN_MODULE))
- {
- return STATUS_INVALID_PARAMETER;
- }
-
- Status = STATUS_DLL_NOT_FOUND;
- RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
- ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
- Entry = ModuleListHead->Flink;
- while (Entry != ModuleListHead)
- {
- Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
-
- if (Module->DllBase == BaseAddress)
- {
- if (Flags & LDR_PIN_MODULE)
- {
- Module->Flags |= LDRP_STATIC_LINK;
- }
- else
- {
- LdrpIncrementLoadCount(Module,
- FALSE);
- }
- Status = STATUS_SUCCESS;
- break;
- }
- Entry = Entry->Flink;
- }
- RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
- return Status;
-}
-
-/*
- * @implemented
- */
-NTSTATUS NTAPI
-LdrGetProcedureAddress (IN PVOID BaseAddress,
- IN PANSI_STRING Name,
- IN ULONG Ordinal,
- OUT PVOID *ProcedureAddress)
-{
- NTSTATUS Status = STATUS_PROCEDURE_NOT_FOUND;
- if (Name && Name->Length)
- {
- TRACE_LDR("LdrGetProcedureAddress by NAME - %Z\n", Name);
- }
- else
- {
- TRACE_LDR("LdrGetProcedureAddress by ORDINAL - %d\n", Ordinal);
- }
-
- DPRINT("LdrGetProcedureAddress (BaseAddress %p Name %Z Ordinal %lu ProcedureAddress %p)\n",
- BaseAddress, Name, Ordinal, ProcedureAddress);
-
- _SEH2_TRY
- {
- if (Name && Name->Length)
- {
- /* by name */
- *ProcedureAddress = LdrGetExportByName(BaseAddress, (PUCHAR)Name->Buffer, 0xffff);
- if (*ProcedureAddress != NULL)
- {
- Status = STATUS_SUCCESS;
- }
- DPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name);
- }
- else
- {
- /* by ordinal */
- Ordinal &= 0x0000FFFF;
- *ProcedureAddress = LdrGetExportByOrdinal(BaseAddress, (WORD)Ordinal);
- if (*ProcedureAddress)
- {
- Status = STATUS_SUCCESS;
- }
- DPRINT("LdrGetProcedureAddress: Can't resolve symbol @%lu\n", Ordinal);
- }
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- Status = STATUS_DLL_NOT_FOUND;
- }
- _SEH2_END;
-
- return Status;
-}
-
-/**********************************************************************
- * NAME LOCAL
- * LdrpDetachProcess
- *
- * DESCRIPTION
- * Unload dll's which are no longer referenced from others dll's
- *
- * ARGUMENTS
- * none
- *
- * RETURN VALUE
- * none
- *
- * REVISIONS
- *
- * NOTE
- * The loader lock must be held on enty.
- */
-static VOID
-LdrpDetachProcess(BOOLEAN UnloadAll)
-{
- PLIST_ENTRY ModuleListHead;
- PLIST_ENTRY Entry;
- PLDR_DATA_TABLE_ENTRY Module;
- static ULONG CallingCount = 0;
-
- DPRINT("LdrpDetachProcess() called for %wZ\n",
- &LdrpImageEntry->BaseDllName);
-
- if (UnloadAll)
- LdrpDllShutdownInProgress = TRUE;
-
- CallingCount++;
-
- ModuleListHead = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList;
- Entry = ModuleListHead->Blink;
- while (Entry != ModuleListHead)
- {
- Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
- if (((UnloadAll && Module->LoadCount == LDRP_PROCESS_CREATION_TIME) || Module->LoadCount == 0) &&
- Module->Flags & LDRP_ENTRY_PROCESSED &&
- !(Module->Flags & LDRP_UNLOAD_IN_PROGRESS))
- {
- Module->Flags |= LDRP_UNLOAD_IN_PROGRESS;
- if (Module == LdrpLastModule)
- {
- LdrpLastModule = NULL;
- }
- if (Module->Flags & LDRP_PROCESS_ATTACH_CALLED)
- {
- TRACE_LDR("Unload %wZ - Calling entry point at %x\n",
- &Module->BaseDllName, Module->EntryPoint);
-
- /* Check if it has TLS */
- if (Module->TlsIndex)
- {
- /* Call TLS */
- LdrpTlsCallback(Module->DllBase, DLL_PROCESS_ATTACH);
- }
-
- if ((Module->Flags & LDRP_IMAGE_DLL) && Module->EntryPoint)
- {
- LdrpCallDllEntry(Module->EntryPoint,
- Module->DllBase,
- DLL_PROCESS_DETACH,
- (PVOID)(Module->LoadCount == LDRP_PROCESS_CREATION_TIME ? 1 : 0));
- }
- }
- else
- {
- TRACE_LDR("Unload %wZ\n", &Module->BaseDllName);
- }
- Entry = ModuleListHead->Blink;
- }
- else
- {
- Entry = Entry->Blink;
- }
- }
-
- if (CallingCount == 1)
- {
- Entry = ModuleListHead->Blink;
- while (Entry != ModuleListHead)
- {
- Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
- Entry = Entry->Blink;
- if (Module->Flags & LDRP_UNLOAD_IN_PROGRESS &&
- ((UnloadAll && Module->LoadCount != LDRP_PROCESS_CREATION_TIME) || Module->LoadCount == 0))
- {
- /* remove the module entry from the list */
- RemoveEntryList (&Module->InLoadOrderLinks);
- RemoveEntryList (&Module->InInitializationOrderModuleList);
-
- NtUnmapViewOfSection (NtCurrentProcess (), Module->DllBase);
- NtClose (Module->SectionPointer);
-
- TRACE_LDR("%wZ unloaded\n", &Module->BaseDllName);
-
- RtlFreeUnicodeString (&Module->FullDllName);
- RtlFreeUnicodeString (&Module->BaseDllName);
-
- RtlFreeHeap (RtlGetProcessHeap (), 0, Module);
- }
- }
- }
- CallingCount--;
- DPRINT("LdrpDetachProcess() done\n");
-}
-
-/*
- * @implemented
- */
-BOOLEAN NTAPI
-RtlDllShutdownInProgress (VOID)
-{
- return LdrpDllShutdownInProgress;
-}
-
-/*
- * @implemented
- */
-NTSTATUS NTAPI
-LdrShutdownProcess (VOID)
-{
- LdrpDetachProcess(TRUE);
- return STATUS_SUCCESS;
-}
-
-/*
- * @implemented
- */
-NTSTATUS
-NTAPI
-LdrpInitializeThread(IN PCONTEXT Context)
-{
- PLIST_ENTRY ModuleListHead;
- PLIST_ENTRY Entry;
- PLDR_DATA_TABLE_ENTRY Module;
- NTSTATUS Status;
-
- DPRINT("LdrpAttachThread() called for %wZ\n",
- &LdrpImageEntry->BaseDllName);
-
- RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
-
- Status = LdrpAllocateTls();
-
- if (NT_SUCCESS(Status))
- {
- ModuleListHead = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList;
- Entry = ModuleListHead->Flink;
-
- while (Entry != ModuleListHead)
- {
- Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
- if (Module->Flags & LDRP_PROCESS_ATTACH_CALLED &&
- !(Module->Flags & LDRP_DONT_CALL_FOR_THREADS) &&
- !(Module->Flags & LDRP_UNLOAD_IN_PROGRESS))
- {
- TRACE_LDR("%wZ - Calling entry point at %x for thread attaching\n",
- &Module->BaseDllName, Module->EntryPoint);
-
- /* Check if it has TLS */
- if (Module->TlsIndex)
- {
- /* Call TLS */
- LdrpTlsCallback(Module->DllBase, DLL_THREAD_ATTACH);
- }
-
- if ((Module->Flags & LDRP_IMAGE_DLL) && Module->EntryPoint)
- LdrpCallDllEntry(Module->EntryPoint, Module->DllBase, DLL_THREAD_ATTACH, NULL);
- }
- Entry = Entry->Flink;
- }
-
- Entry = NtCurrentPeb()->Ldr->InLoadOrderModuleList.Flink;
- Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
- LdrpTlsCallback(Module->DllBase, DLL_THREAD_ATTACH);
- }
-
- RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
-
- DPRINT("LdrpAttachThread() done\n");
-
- return Status;
-}
-
-
-/*
- * @implemented
- */
-NTSTATUS NTAPI
-LdrShutdownThread (VOID)
-{
- PLIST_ENTRY ModuleListHead;
- PLIST_ENTRY Entry;
- PLDR_DATA_TABLE_ENTRY Module;
-
- DPRINT("LdrShutdownThread() called for %wZ\n",
- &LdrpImageEntry->BaseDllName);
-
- RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
-
- ModuleListHead = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList;
- Entry = ModuleListHead->Blink;
- while (Entry != ModuleListHead)
- {
- Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
-
- if (Module->Flags & LDRP_PROCESS_ATTACH_CALLED &&
- !(Module->Flags & LDRP_DONT_CALL_FOR_THREADS) &&
- !(Module->Flags & LDRP_UNLOAD_IN_PROGRESS))
- {
- TRACE_LDR("%wZ - Calling entry point at %x for thread detaching\n",
- &Module->BaseDllName, Module->EntryPoint);
- /* Check if it has TLS */
- if (Module->TlsIndex)
- {
- /* Call TLS */
- LdrpTlsCallback(Module->DllBase, DLL_THREAD_DETACH);
- }
-
- if ((Module->Flags & LDRP_IMAGE_DLL) && Module->EntryPoint)
- LdrpCallDllEntry(Module->EntryPoint, Module->DllBase, DLL_THREAD_DETACH, NULL);
- }
- Entry = Entry->Blink;
- }
-
- /* Free TLS */
- LdrpFreeTls();
- RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
-
- DPRINT("LdrShutdownThread() done\n");
-
- return STATUS_SUCCESS;
-}
-
-/*
- * Compute size of an image as it is actually present in virt memory
- * (i.e. excluding NEVER_LOAD sections)
- */
-ULONG
-LdrpGetResidentSize(PIMAGE_NT_HEADERS NTHeaders)
-{
- PIMAGE_SECTION_HEADER SectionHeader;
- unsigned SectionIndex;
- ULONG ResidentSize;
+ DPRINT1("\n");
SectionHeader = (PIMAGE_SECTION_HEADER)((char *) &NTHeaders->OptionalHeader
+ NTHeaders->FileHeader.SizeOfOptionalHeader);
IN PUSHORT TypeOffset,
IN LONG_PTR Delta)
{
+ DPRINT1("\n");
return LdrProcessRelocationBlockLongLong(Address, Count, TypeOffset, Delta);
}
NTAPI
LdrUnloadAlternateResourceModule(IN PVOID BaseAddress)
{
- UNIMPLEMENTED;
+ //FIXME: We don't implement alternate resources anyway, don't spam the log
+ //UNIMPLEMENTED;
return FALSE;
}
}
}
- /* 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)
{
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)
{
/* 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
}
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 */
NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame->Previous;
return frame;
-#else
- return NULL;
-#endif
}