diff --git a/reactos/dll/ntdll/include/ntdllp.h b/reactos/dll/ntdll/include/ntdllp.h index a01a960cef2..dc4bf7593ba 100644 --- a/reactos/dll/ntdll/include/ntdllp.h +++ b/reactos/dll/ntdll/include/ntdllp.h @@ -10,6 +10,11 @@ #define LDR_HASH_TABLE_ENTRIES 32 +/* LdrpUpdateLoadCount2 flags */ +#define LDRP_UPDATE_REFCOUNT 0x01 +#define LDRP_UPDATE_DEREFCOUNT 0x02 +#define LDRP_UPDATE_PIN 0x03 + typedef struct _LDRP_TLS_DATA { LIST_ENTRY TlsLinks; @@ -27,10 +32,21 @@ extern BOOLEAN LdrpInLdrInit; extern LIST_ENTRY LdrpHashTable[LDR_HASH_TABLE_ENTRIES]; extern BOOLEAN ShowSnaps; extern UNICODE_STRING LdrpDefaultPath; +extern HANDLE LdrpKnownDllObjectDirectory; +extern ULONG LdrpNumberOfProcessors; +extern ULONG LdrpFatalHardErrorCount; +extern PUNICODE_STRING LdrpTopLevelDllBeingLoaded; +extern PLDR_DATA_TABLE_ENTRY LdrpCurrentDllInitializer; +extern UNICODE_STRING LdrApiDefaultExtension; +extern BOOLEAN LdrpLdrDatabaseIsSetup; +extern ULONG LdrpActiveUnloadCount; +extern BOOLEAN LdrpShutdownInProgress; +extern UNICODE_STRING LdrpKnownDllPath; +extern PLDR_DATA_TABLE_ENTRY LdrpGetModuleHandleCache; /* ldrinit.c */ NTSTATUS NTAPI LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL); -NTSTATUS NTAPI LdrpInitializeThread(IN PCONTEXT Context); +VOID NTAPI LdrpInitializeThread(IN PCONTEXT Context); NTSTATUS NTAPI LdrpInitializeTls(VOID); NTSTATUS NTAPI LdrpAllocateTls(VOID); VOID NTAPI LdrpFreeTls(VOID); @@ -38,7 +54,7 @@ VOID NTAPI LdrpTlsCallback(PVOID BaseAddress, ULONG Reason); BOOLEAN NTAPI LdrpCallDllEntry(PDLLMAIN_FUNC EntryPoint, PVOID BaseAddress, ULONG Reason, PVOID Context); NTSTATUS NTAPI LdrpInitializeProcess(PCONTEXT Context, PVOID SystemArgument1); VOID NTAPI LdrpInitFailure(NTSTATUS Status); - +VOID NTAPI LdrpValidateImageForMp(IN PLDR_DATA_TABLE_ENTRY LdrDataTableEntry); /* ldrpe.c */ NTSTATUS @@ -79,6 +95,10 @@ LdrpLoadDll(IN BOOLEAN Redirected, OUT PVOID *BaseAddress, IN BOOLEAN CallInit); +VOID NTAPI +LdrpUpdateLoadCount2(IN PLDR_DATA_TABLE_ENTRY LdrEntry, + IN ULONG Flags); + ULONG NTAPI LdrpClearLoadInProgress(); @@ -101,6 +121,9 @@ LdrpMapDll(IN PWSTR SearchPath OPTIONAL, PVOID NTAPI LdrpFetchAddressOfEntryPoint(PVOID ImageBase); +BOOLEAN NTAPI +LdrpFreeUnicodeString(PUNICODE_STRING String); + /* FIXME: Cleanup this mess */ typedef NTSTATUS (NTAPI *PEPFUNC)(PPEB); @@ -110,13 +133,8 @@ NTSTATUS LdrMapSections(HANDLE ProcessHandle, PIMAGE_NT_HEADERS NTHeaders); NTSTATUS LdrMapNTDllForProcess(HANDLE ProcessHandle, PHANDLE NTDllSectionHandle); -BOOLEAN LdrMappedAsDataFile(PVOID *BaseAddress); ULONG LdrpGetResidentSize(PIMAGE_NT_HEADERS NTHeaders); -PEPFUNC LdrPEStartup (PVOID ImageBase, - HANDLE SectionHandle, - PLDR_DATA_TABLE_ENTRY* Module, - PWSTR FullDosName); extern HANDLE WindowsApiPort; diff --git a/reactos/dll/ntdll/ldr/ldrapi.c b/reactos/dll/ntdll/ldr/ldrapi.c index e08f4ca5ec8..cf9b5d2d6d1 100644 --- a/reactos/dll/ntdll/ldr/ldrapi.c +++ b/reactos/dll/ntdll/ldr/ldrapi.c @@ -16,6 +16,8 @@ /* GLOBALS *******************************************************************/ LONG LdrpLoaderLockAcquisitonCount; +BOOLEAN LdrpShowRecursiveLoads; +UNICODE_STRING LdrApiDefaultExtension = RTL_CONSTANT_STRING(L".DLL"); /* FUNCTIONS *****************************************************************/ @@ -242,6 +244,483 @@ Quickie: return Status; } +/* + * @implemented + */ +NTSTATUS +NTAPI +LdrLoadDll(IN PWSTR SearchPath OPTIONAL, + IN PULONG DllCharacteristics OPTIONAL, + IN PUNICODE_STRING DllName, + OUT PVOID *BaseAddress) +{ + WCHAR StringBuffer[MAX_PATH]; + UNICODE_STRING DllString1, DllString2; + BOOLEAN RedirectedDll = FALSE; + NTSTATUS Status; + ULONG Cookie; + PUNICODE_STRING OldTldDll; + PTEB Teb = NtCurrentTeb(); + + /* Initialize the strings */ + RtlInitUnicodeString(&DllString2, NULL); + DllString1.Buffer = StringBuffer; + DllString1.Length = 0; + DllString1.MaximumLength = sizeof(StringBuffer); + + /* Check if the SxS Assemblies specify another file */ + Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE, + DllName, + &LdrApiDefaultExtension, + &DllString1, + &DllString2, + &DllName, + NULL, + NULL, + NULL); + + /* Check success */ + if (NT_SUCCESS(Status)) + { + /* Let Ldrp know */ + RedirectedDll = TRUE; + } + else if (Status != STATUS_SXS_KEY_NOT_FOUND) + { + /* Unrecoverable SxS failure; did we get a string? */ + if (DllString2.Buffer) + { + /* Free the string */ + RtlFreeUnicodeString(&DllString2); + return Status; + } + } + + /* Lock the loader lock */ + LdrLockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, NULL, &Cookie); + + /* Check if there's a TLD DLL being loaded */ + if ((OldTldDll = LdrpTopLevelDllBeingLoaded)) + { + /* This is a recursive load, do something about it? */ + if (ShowSnaps || LdrpShowRecursiveLoads) + { + /* Print out debug messages */ + DPRINT1("[%lx, %lx] LDR: Recursive DLL Load\n", + Teb->RealClientId.UniqueProcess, + Teb->RealClientId.UniqueThread); + DPRINT1("[%lx, %lx] Previous DLL being loaded \"%wZ\"\n", + Teb->RealClientId.UniqueProcess, + Teb->RealClientId.UniqueThread, + OldTldDll); + DPRINT1("[%lx, %lx] DLL being requested \"%wZ\"\n", + Teb->RealClientId.UniqueProcess, + Teb->RealClientId.UniqueThread, + DllName); + + /* Was it initializing too? */ + if (!LdrpCurrentDllInitializer) + { + DPRINT1("[%lx, %lx] LDR: No DLL Initializer was running\n", + Teb->RealClientId.UniqueProcess, + Teb->RealClientId.UniqueThread); + } + else + { + DPRINT1("[%lx, %lx] DLL whose initializer was currently running \"%wZ\"\n", + Teb->ClientId.UniqueProcess, + Teb->ClientId.UniqueThread, + &LdrpCurrentDllInitializer->BaseDllName); + } + } + } + + /* Set this one as the TLD DLL being loaded*/ + LdrpTopLevelDllBeingLoaded = DllName; + + /* Load the DLL */ + Status = LdrpLoadDll(RedirectedDll, + SearchPath, + DllCharacteristics, + DllName, + BaseAddress, + TRUE); + + /* Set it to success just to be sure */ + Status = STATUS_SUCCESS; + + /* Restore the old TLD DLL */ + LdrpTopLevelDllBeingLoaded = OldTldDll; + + /* Release the lock */ + LdrUnlockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, Cookie); + + /* Do we have a redirect string? */ + if (DllString2.Buffer) RtlFreeUnicodeString(&DllString2); + + /* Return */ + return Status; +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +LdrFindEntryForAddress(PVOID Address, + PLDR_DATA_TABLE_ENTRY *Module) +{ + PLIST_ENTRY ListHead, NextEntry; + PLDR_DATA_TABLE_ENTRY LdrEntry; + PIMAGE_NT_HEADERS NtHeader; + PPEB_LDR_DATA Ldr = NtCurrentPeb()->Ldr; + ULONG_PTR DllBase, DllEnd; + + DPRINT("LdrFindEntryForAddress(Address %p)\n", Address); + + /* Nothing to do */ + if (!Ldr) return STATUS_NO_MORE_ENTRIES; + + /* Loop the module list */ + ListHead = &Ldr->InMemoryOrderModuleList; + NextEntry = ListHead->Flink; + while (NextEntry != ListHead) + { + /* Get the entry and NT Headers */ + LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderModuleList); + if ((NtHeader = RtlImageNtHeader(LdrEntry->DllBase))) + { + /* Get the Image Base */ + DllBase = (ULONG_PTR)LdrEntry->DllBase; + DllEnd = DllBase + NtHeader->OptionalHeader.SizeOfImage; + + /* Check if they match */ + if (((ULONG_PTR)Address >= DllBase) && + ((ULONG_PTR)Address < DllEnd)) + { + /* Return it */ + *Module = LdrEntry; + return STATUS_SUCCESS; + } + + /* Next Entry */ + NextEntry = NextEntry->Flink; + } + } + + /* Nothing found */ + return STATUS_NO_MORE_ENTRIES; +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +LdrGetDllHandleEx(IN ULONG Flags, + IN PWSTR DllPath OPTIONAL, + IN PULONG DllCharacteristics OPTIONAL, + IN PUNICODE_STRING DllName, + OUT PVOID *DllHandle OPTIONAL) +{ + NTSTATUS Status = STATUS_DLL_NOT_FOUND; + PLDR_DATA_TABLE_ENTRY LdrEntry; + UNICODE_STRING RedirectName, DllString1; + UNICODE_STRING RawDllName; + PUNICODE_STRING pRedirectName = &RedirectName; + PUNICODE_STRING CompareName; + PWCHAR p1, p2, p3; + BOOLEAN Locked = FALSE; + BOOLEAN RedirectedDll = FALSE; + ULONG Cookie; + ULONG LoadFlag; + + /* Initialize the strings */ + RtlInitUnicodeString(&DllString1, NULL); + RtlInitUnicodeString(&RawDllName, NULL); + RedirectName = *DllName; + + /* Clear the handle */ + if (DllHandle) *DllHandle = NULL; + + /* Check for a valid flag */ + if ((Flags & ~3) || (!DllHandle && !(Flags & 2))) + { + DPRINT1("Flags are invalid or no DllHandle given\n"); + return STATUS_INVALID_PARAMETER; + } + + /* If not initializing */ + if (!LdrpInLdrInit) + { + /* Acquire the lock */ + Status = LdrLockLoaderLock(0, NULL, &Cookie); + Locked = TRUE; + } + + /* Check if the SxS Assemblies specify another file */ + Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE, + pRedirectName, + &LdrApiDefaultExtension, + NULL, + &DllString1, + &pRedirectName, + NULL, + NULL, + NULL); + + /* Check success */ + if (NT_SUCCESS(Status)) + { + /* Let Ldrp know */ + RedirectedDll = TRUE; + } + else if (Status != STATUS_SXS_KEY_NOT_FOUND) + { + /* Unrecoverable SxS failure; */ + goto Quickie; + } + + /* Use the cache if we can */ + if (LdrpGetModuleHandleCache) + { + /* Check if we were redirected */ + if (RedirectedDll) + { + /* Check the flag */ + if (LdrpGetModuleHandleCache->Flags & LDRP_REDIRECTED) + { + /* Use the right name */ + CompareName = &LdrpGetModuleHandleCache->FullDllName; + } + else + { + goto DontCompare; + } + } + else + { + /* Check the flag */ + if (!(LdrpGetModuleHandleCache->Flags & LDRP_REDIRECTED)) + { + /* Use the right name */ + CompareName = &LdrpGetModuleHandleCache->BaseDllName; + } + else + { + goto DontCompare; + } + } + + /* Check if the name matches */ + if (RtlEqualUnicodeString(pRedirectName, + CompareName, + TRUE)) + { + /* Skip the rest */ + LdrEntry = LdrpGetModuleHandleCache; + + /* Return success */ + Status = STATUS_SUCCESS; + + goto FoundEntry; + } + } + +DontCompare: + /* Find the name without the extension */ + p1 = pRedirectName->Buffer; + p3 = &p1[pRedirectName->Length / sizeof(WCHAR)]; +StartLoop: + p2 = NULL; + while (p1 != p3) + { + if (*p1++ == L'.') + { + p2 = p1; + } + else if (*p1 == L'\\') + { + goto StartLoop; + } + } + + /* Check if no extension was found or if we got a slash */ + if (!p2 || *p2 == L'\\' || *p2 == L'/') + { + /* Check that we have space to add one */ + if (pRedirectName->Length + LdrApiDefaultExtension.Length >= MAXLONG) + { + /* No space to add the extension */ + return STATUS_NAME_TOO_LONG; + } + + /* Setup the string */ + RawDllName.MaximumLength = pRedirectName->Length + LdrApiDefaultExtension.Length + sizeof(UNICODE_NULL); + RawDllName.Length = RawDllName.MaximumLength - sizeof(UNICODE_NULL); + RawDllName.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + RawDllName.MaximumLength); + + /* Copy the buffer */ + RtlMoveMemory(RawDllName.Buffer, + pRedirectName->Buffer, + pRedirectName->Length); + + /* Add extension */ + RtlMoveMemory((PVOID)((ULONG_PTR)RawDllName.Buffer + pRedirectName->Length), + LdrApiDefaultExtension.Buffer, + LdrApiDefaultExtension.Length); + + /* Null terminate */ + RawDllName.Buffer[RawDllName.Length / sizeof(WCHAR)] = UNICODE_NULL; + } + else + { + /* Check if there's something in the name */ + if (pRedirectName->Length) + { + /* Check and remove trailing period */ + if (pRedirectName->Buffer[(pRedirectName->Length - 2) / + sizeof(WCHAR)] == '.') + { + /* Decrease the size */ + pRedirectName->Length -= sizeof(WCHAR); + } + } + + /* Setup the string */ + RawDllName.MaximumLength = pRedirectName->Length + sizeof(WCHAR); + RawDllName.Length = pRedirectName->Length; + RawDllName.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + RawDllName.MaximumLength); + + /* Copy the buffer */ + RtlMoveMemory(RawDllName.Buffer, + pRedirectName->Buffer, + pRedirectName->Length); + + /* Null terminate */ + RawDllName.Buffer[RawDllName.Length / sizeof(WCHAR)] = UNICODE_NULL; + } + + /* Display debug string */ + if (ShowSnaps) + { + DPRINT1("LDR: LdrGetDllHandle, searching for %wZ from %ws\n", + &RawDllName, + DllPath ? ((ULONG_PTR)DllPath == 1 ? L"" : DllPath) : L""); + } + + /* Do the lookup */ + if (LdrpCheckForLoadedDll(DllPath, + &RawDllName, + ((ULONG_PTR)DllPath == 1) ? TRUE : FALSE, + RedirectedDll, + &LdrEntry)) + { + /* Update cached entry */ + LdrpGetModuleHandleCache = LdrEntry; + + /* Return success */ + Status = STATUS_SUCCESS; + } + else + { + /* Make sure to NULL this */ + LdrEntry = NULL; + } +FoundEntry: + DPRINT("Got LdrEntry->BaseDllName %wZ\n", LdrEntry ? &LdrEntry->BaseDllName : NULL); + + /* Check if we got an entry */ + if (LdrEntry) + { + /* Check for success */ + if (NT_SUCCESS(Status)) + { + /* Check if the DLL is locked */ + if (LdrEntry->LoadCount != -1) + { + /* Check what flag we got */ + if (!(Flags & 1)) + { + /* Check what to do with the load count */ + if (Flags & 2) + { + /* Pin it */ + LdrEntry->LoadCount = -1; + LoadFlag = LDRP_UPDATE_PIN; + } + else + { + /* Increase the load count */ + LdrEntry->LoadCount++; + LoadFlag = LDRP_UPDATE_REFCOUNT; + } + + /* Update the load count now */ + LdrpUpdateLoadCount2(LdrEntry, LoadFlag); + LdrpClearLoadInProgress(); + } + } + + /* Check if the caller is requesting the handle */ + if (DllHandle) *DllHandle = LdrEntry->DllBase; + } + } +Quickie: + /* Free string if needed */ + if (DllString1.Buffer) RtlFreeUnicodeString(&DllString1); + + /* Free the raw DLL Name if needed */ + if (RawDllName.Buffer) + { + /* Free the heap-allocated buffer */ + RtlFreeHeap(RtlGetProcessHeap(), 0, RawDllName.Buffer); + RawDllName.Buffer = NULL; + } + + /* Release lock */ + if (Locked) LdrUnlockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, Cookie); + + /* Return */ + return Status; +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +LdrGetDllHandle(IN PWSTR DllPath OPTIONAL, + IN PULONG DllCharacteristics OPTIONAL, + IN PUNICODE_STRING DllName, + OUT PVOID *DllHandle) +{ + /* Call the newer API */ + return LdrGetDllHandleEx(TRUE, + DllPath, + DllCharacteristics, + DllName, + DllHandle); +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +LdrGetProcedureAddress(IN PVOID BaseAddress, + IN PANSI_STRING Name, + IN ULONG Ordinal, + OUT PVOID *ProcedureAddress) +{ + /* Call the internal routine and tell it to execute DllInit */ + return LdrpGetProcedureAddress(BaseAddress, Name, Ordinal, ProcedureAddress, TRUE); +} + /* * @implemented */ @@ -374,21 +853,6 @@ LdrVerifyImageMatchesChecksum(IN HANDLE FileHandle, return !Result ? STATUS_IMAGE_CHECKSUM_MISMATCH : Status; } -/* - * @implemented - */ -NTSTATUS -NTAPI -LdrGetProcedureAddress_(IN PVOID BaseAddress, - IN PANSI_STRING Name, - IN ULONG Ordinal, - OUT PVOID *ProcedureAddress) -{ - /* Call the internal routine and tell it to execute DllInit */ - return LdrpGetProcedureAddress(BaseAddress, Name, Ordinal, ProcedureAddress, TRUE); -} - - NTSTATUS NTAPI LdrQueryProcessModuleInformationEx(IN ULONG ProcessId, diff --git a/reactos/dll/ntdll/ldr/ldrinit.c b/reactos/dll/ntdll/ldr/ldrinit.c index 6b08bed65dd..fd0aa391f11 100644 --- a/reactos/dll/ntdll/ldr/ldrinit.c +++ b/reactos/dll/ntdll/ldr/ldrinit.c @@ -10,9 +10,12 @@ /* INCLUDES *****************************************************************/ #include +#include + #define NDEBUG #include + /* GLOBALS *******************************************************************/ HKEY ImageExecOptionsKey; @@ -25,11 +28,14 @@ BOOLEAN LdrpInLdrInit; LONG LdrpProcessInitialized; BOOLEAN LdrpLoaderLockInit; BOOLEAN LdrpLdrDatabaseIsSetup; +BOOLEAN LdrpShutdownInProgress; +HANDLE LdrpShutdownThreadId; BOOLEAN LdrpDllValidation; PLDR_DATA_TABLE_ENTRY LdrpImageEntry; PUNICODE_STRING LdrpTopLevelDllBeingLoaded; +WCHAR StringBuffer[156]; extern PTEB LdrpTopLevelDllBeingLoadedTeb; // defined in rtlsupp.c! PLDR_DATA_TABLE_ENTRY LdrpCurrentDllInitializer; PLDR_DATA_TABLE_ENTRY LdrpNtDllDataTableEntry; @@ -68,6 +74,7 @@ RTL_CRITICAL_SECTION FastPebLock; BOOLEAN ShowSnaps; ULONG LdrpFatalHardErrorCount; +ULONG LdrpActiveUnloadCount; //extern LIST_ENTRY RtlCriticalSectionList; @@ -78,10 +85,12 @@ extern BOOLEAN RtlpPageHeapEnabled; extern ULONG RtlpDphGlobalFlags; NTSTATUS LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders, PVOID ImageBase); -NTSTATUS NTAPI -LdrpInitializeProcess_(PCONTEXT Context, - PVOID SystemArgument1); +#ifdef _WIN64 +#define DEFAULT_SECURITY_COOKIE 0x00002B992DDFA232ll +#else +#define DEFAULT_SECURITY_COOKIE 0xBB40E64E +#endif /* FUNCTIONS *****************************************************************/ @@ -414,8 +423,7 @@ LdrpFetchAddressOfSecurityCookie(PVOID BaseAddress, ULONG SizeOfImage) Cookie = (PVOID)ConfigDir->SecurityCookie; /* Check this cookie */ - if (Cookie == NULL || - (PCHAR)Cookie <= (PCHAR)BaseAddress || + if ((PCHAR)Cookie <= (PCHAR)BaseAddress || (PCHAR)Cookie >= (PCHAR)BaseAddress + SizeOfImage) { Cookie = NULL; @@ -429,20 +437,178 @@ PVOID NTAPI LdrpInitSecurityCookie(PLDR_DATA_TABLE_ENTRY LdrEntry) { - PVOID Cookie; + PULONG_PTR Cookie; + LARGE_INTEGER Counter; + //ULONG NewCookie; /* Fetch address of the cookie */ Cookie = LdrpFetchAddressOfSecurityCookie(LdrEntry->DllBase, LdrEntry->SizeOfImage); if (Cookie) { - UNIMPLEMENTED; - Cookie = NULL; + /* Check if it's a default one */ + if (*Cookie == DEFAULT_SECURITY_COOKIE || + *Cookie == 0xBB40) + { + /* We need to initialize it */ + + NtQueryPerformanceCounter(&Counter, NULL); +#if 0 + GetSystemTimeAsFileTime (&systime.ft_struct); +#ifdef _WIN64 + cookie = systime.ft_scalar; +#else + cookie = systime.ft_struct.dwLowDateTime; + cookie ^= systime.ft_struct.dwHighDateTime; +#endif + + cookie ^= GetCurrentProcessId (); + cookie ^= GetCurrentThreadId (); + cookie ^= GetTickCount (); + + QueryPerformanceCounter (&perfctr); +#ifdef _WIN64 + cookie ^= perfctr.QuadPart; +#else + cookie ^= perfctr.LowPart; + cookie ^= perfctr.HighPart; +#endif + +#ifdef _WIN64 + cookie &= 0x0000ffffffffffffll; +#endif +#endif + *Cookie = Counter.LowPart; + + //Cookie = NULL; + } } return Cookie; } +VOID +NTAPI +LdrpInitializeThread(IN PCONTEXT Context) +{ + PPEB Peb = NtCurrentPeb(); + PLDR_DATA_TABLE_ENTRY LdrEntry; + PLIST_ENTRY NextEntry, ListHead; + RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx; + NTSTATUS Status; + PVOID EntryPoint; + + DPRINT("LdrpInitializeThread() called for %wZ\n", + &LdrpImageEntry->BaseDllName); + + /* Allocate an Activation Context Stack */ + /* FIXME: This is a hack for Wine's actctx stuff */ + DPRINT("ActivationContextStack %p\n", NtCurrentTeb()->ActivationContextStackPointer); + if (!(NtCurrentTeb()->ActivationContextStackPointer)) + { + Status = RtlAllocateActivationContextStack((PVOID*)&NtCurrentTeb()->ActivationContextStackPointer); + if (NT_SUCCESS(Status)) + { + DPRINT("ActivationContextStack %p\n", NtCurrentTeb()->ActivationContextStackPointer); + DPRINT("ActiveFrame %p\n", ((PACTIVATION_CONTEXT_STACK)NtCurrentTeb()->ActivationContextStackPointer)->ActiveFrame); + NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NULL; + } + else + DPRINT1("Warning: Unable to allocate ActivationContextStack\n"); + } + + /* Make sure we are not shutting down */ + if (LdrpShutdownInProgress) return; + + /* Allocate TLS */ + LdrpAllocateTls(); + + /* Start at the beginning */ + ListHead = &Peb->Ldr->InMemoryOrderModuleList; + NextEntry = ListHead->Flink; + while (NextEntry != ListHead) + { + /* Get the current entry */ + LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderModuleList); + + /* Make sure it's not ourselves */ + if (Peb->ImageBaseAddress != LdrEntry->DllBase) + { + /* Check if we should call */ + if (!(LdrEntry->Flags & LDRP_DONT_CALL_FOR_THREADS)) + { + /* Get the entrypoint */ + EntryPoint = LdrEntry->EntryPoint; + + /* Check if we are ready to call it */ + if ((EntryPoint) && + (LdrEntry->Flags & LDRP_PROCESS_ATTACH_CALLED) && + (LdrEntry->Flags & LDRP_IMAGE_DLL)) + { + /* Set up the Act Ctx */ + ActCtx.Size = sizeof(ActCtx); + ActCtx.Format = 1; + RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); + + /* Activate the ActCtx */ + RtlActivateActivationContextUnsafeFast(&ActCtx, + LdrEntry->EntryPointActivationContext); + + /* Check if it has TLS */ + if (LdrEntry->TlsIndex) + { + /* Make sure we're not shutting down */ + if (!LdrpShutdownInProgress) + { + /* Call TLS */ + LdrpTlsCallback(LdrEntry->DllBase, DLL_THREAD_ATTACH); + } + } + + /* Make sure we're not shutting down */ + if (!LdrpShutdownInProgress) + { + /* Call the Entrypoint */ + DPRINT("%wZ - Calling entry point at %x for thread attaching\n", + &LdrEntry->BaseDllName, LdrEntry->EntryPoint); + LdrpCallDllEntry(LdrEntry->EntryPoint, + LdrEntry->DllBase, + DLL_THREAD_ATTACH, + NULL); + } + + /* Deactivate the ActCtx */ + RtlDeactivateActivationContextUnsafeFast(&ActCtx); + } + } + } + + /* Next entry */ + NextEntry = NextEntry->Flink; + } + + /* Check for TLS */ + if (LdrpImageHasTls && !LdrpShutdownInProgress) + { + /* Set up the Act Ctx */ + ActCtx.Size = sizeof(ActCtx); + ActCtx.Format = 1; + RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); + + /* Activate the ActCtx */ + RtlActivateActivationContextUnsafeFast(&ActCtx, + LdrpImageEntry->EntryPointActivationContext); + + /* Do TLS callbacks */ + LdrpTlsCallback(Peb->ImageBaseAddress, DLL_THREAD_ATTACH); + + /* Deactivate the ActCtx */ + RtlDeactivateActivationContextUnsafeFast(&ActCtx); + } + + DPRINT("LdrpInitializeThread() done\n"); +} + NTSTATUS NTAPI LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL) @@ -715,6 +881,267 @@ Quickie: return Status; } +/* + * @implemented + */ +NTSTATUS +NTAPI +LdrShutdownProcess(VOID) +{ + PPEB Peb = NtCurrentPeb(); + PLDR_DATA_TABLE_ENTRY LdrEntry; + PLIST_ENTRY NextEntry, ListHead; + RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx; + PVOID EntryPoint; + + DPRINT("LdrShutdownProcess() called for %wZ\n", &LdrpImageEntry->BaseDllName); + if (LdrpShutdownInProgress) return STATUS_SUCCESS; + + /* Tell the Shim Engine */ + //if (ShimsEnabled) + //{ + /* FIXME */ + //} + + /* Tell the world */ + if (ShowSnaps) + { + DPRINT1("\n"); + } + + /* Set the shutdown variables */ + LdrpShutdownThreadId = NtCurrentTeb()->RealClientId.UniqueThread; + LdrpShutdownInProgress = TRUE; + + /* Enter the Loader Lock */ + RtlEnterCriticalSection(&LdrpLoaderLock); + + /* Cleanup trace logging data (Etw) */ + if (SharedUserData->TraceLogging) + { + /* FIXME */ + DPRINT1("We don't support Etw yet.\n"); + } + + /* Start at the end */ + ListHead = &Peb->Ldr->InInitializationOrderModuleList; + NextEntry = ListHead->Blink; + while (NextEntry != ListHead) + { + /* Get the current entry */ + LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList); + NextEntry = NextEntry->Blink; + + /* Make sure it's not ourselves */ + if (Peb->ImageBaseAddress != LdrEntry->DllBase) + { + /* Get the entrypoint */ + EntryPoint = LdrEntry->EntryPoint; + + /* Check if we are ready to call it */ + if (EntryPoint && + (LdrEntry->Flags & LDRP_PROCESS_ATTACH_CALLED) && + LdrEntry->Flags) + { + /* Set up the Act Ctx */ + ActCtx.Size = sizeof(ActCtx); + ActCtx.Format = 1; + RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); + + /* Activate the ActCtx */ + RtlActivateActivationContextUnsafeFast(&ActCtx, + LdrEntry->EntryPointActivationContext); + + /* Check if it has TLS */ + if (LdrEntry->TlsIndex) + { + /* Call TLS */ + LdrpTlsCallback(LdrEntry->DllBase, DLL_PROCESS_DETACH); + } + + /* Call the Entrypoint */ + DPRINT("%wZ - Calling entry point at %x for thread detaching\n", + &LdrEntry->BaseDllName, LdrEntry->EntryPoint); + LdrpCallDllEntry(EntryPoint, + LdrEntry->DllBase, + DLL_PROCESS_DETACH, + (PVOID)1); + + /* Deactivate the ActCtx */ + RtlDeactivateActivationContextUnsafeFast(&ActCtx); + } + } + } + + /* Check for TLS */ + if (LdrpImageHasTls) + { + /* Set up the Act Ctx */ + ActCtx.Size = sizeof(ActCtx); + ActCtx.Format = 1; + RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); + + /* Activate the ActCtx */ + RtlActivateActivationContextUnsafeFast(&ActCtx, + LdrpImageEntry->EntryPointActivationContext); + + /* Do TLS callbacks */ + LdrpTlsCallback(Peb->ImageBaseAddress, DLL_PROCESS_DETACH); + + /* Deactivate the ActCtx */ + RtlDeactivateActivationContextUnsafeFast(&ActCtx); + } + + /* FIXME: Do Heap detection and Etw final shutdown */ + + /* Release the lock */ + RtlLeaveCriticalSection(&LdrpLoaderLock); + DPRINT("LdrpShutdownProcess() done\n"); + + return STATUS_SUCCESS; +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +LdrShutdownThread(VOID) +{ + PPEB Peb = NtCurrentPeb(); + PTEB Teb = NtCurrentTeb(); + PLDR_DATA_TABLE_ENTRY LdrEntry; + PLIST_ENTRY NextEntry, ListHead; + RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx; + PVOID EntryPoint; + + DPRINT("LdrShutdownThread() called for %wZ\n", + &LdrpImageEntry->BaseDllName); + + /* Cleanup trace logging data (Etw) */ + if (SharedUserData->TraceLogging) + { + /* FIXME */ + DPRINT1("We don't support Etw yet.\n"); + } + + /* Get the Ldr Lock */ + RtlEnterCriticalSection(&LdrpLoaderLock); + + /* Start at the end */ + ListHead = &Peb->Ldr->InInitializationOrderModuleList; + NextEntry = ListHead->Blink; + while (NextEntry != ListHead) + { + /* Get the current entry */ + LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList); + NextEntry = NextEntry->Blink; + + /* Make sure it's not ourselves */ + if (Peb->ImageBaseAddress != LdrEntry->DllBase) + { + /* Check if we should call */ + if (!(LdrEntry->Flags & LDRP_DONT_CALL_FOR_THREADS) && + (LdrEntry->Flags & LDRP_PROCESS_ATTACH_CALLED) && + (LdrEntry->Flags & LDRP_IMAGE_DLL)) + { + /* Get the entrypoint */ + EntryPoint = LdrEntry->EntryPoint; + + /* Check if we are ready to call it */ + if (EntryPoint) + { + /* Set up the Act Ctx */ + ActCtx.Size = sizeof(ActCtx); + ActCtx.Format = 1; + RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); + + /* Activate the ActCtx */ + RtlActivateActivationContextUnsafeFast(&ActCtx, + LdrEntry->EntryPointActivationContext); + + /* Check if it has TLS */ + if (LdrEntry->TlsIndex) + { + /* Make sure we're not shutting down */ + if (!LdrpShutdownInProgress) + { + /* Call TLS */ + LdrpTlsCallback(LdrEntry->DllBase, DLL_THREAD_DETACH); + } + } + + /* Make sure we're not shutting down */ + if (!LdrpShutdownInProgress) + { + /* Call the Entrypoint */ + DPRINT("%wZ - Calling entry point at %x for thread detaching\n", + &LdrEntry->BaseDllName, LdrEntry->EntryPoint); + LdrpCallDllEntry(EntryPoint, + LdrEntry->DllBase, + DLL_THREAD_DETACH, + NULL); + } + + /* Deactivate the ActCtx */ + RtlDeactivateActivationContextUnsafeFast(&ActCtx); + } + } + } + } + + /* Check for TLS */ + if (LdrpImageHasTls) + { + /* Set up the Act Ctx */ + ActCtx.Size = sizeof(ActCtx); + ActCtx.Format = 1; + RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); + + /* Activate the ActCtx */ + RtlActivateActivationContextUnsafeFast(&ActCtx, + LdrpImageEntry->EntryPointActivationContext); + + /* Do TLS callbacks */ + LdrpTlsCallback(Peb->ImageBaseAddress, DLL_THREAD_DETACH); + + /* Deactivate the ActCtx */ + RtlDeactivateActivationContextUnsafeFast(&ActCtx); + } + + /* Free TLS */ + LdrpFreeTls(); + RtlLeaveCriticalSection(&LdrpLoaderLock); + + /* Check for expansion slots */ + if (Teb->TlsExpansionSlots) + { + /* Free expansion slots */ + RtlFreeHeap(RtlGetProcessHeap(), 0, Teb->TlsExpansionSlots); + } + + /* Check for FLS Data */ + if (Teb->FlsData) + { + /* FIXME */ + DPRINT1("We don't support FLS Data yet\n"); + } + + /* Check for Fiber data */ + if (Teb->HasFiberData) + { + /* Free Fiber data*/ + RtlFreeHeap(RtlGetProcessHeap(), 0, Teb->NtTib.FiberData); + Teb->NtTib.FiberData = NULL; + } + + /* Free the activation context stack */ + RtlFreeThreadActivationContextStack(); + DPRINT("LdrShutdownThread() done\n"); + + return STATUS_SUCCESS; +} + NTSTATUS NTAPI LdrpInitializeTls(VOID) @@ -879,10 +1306,10 @@ LdrpFreeTls(VOID) NTSTATUS NTAPI -LdrpInitializeExecutionOptions(PUNICODE_STRING ImagePathName, PPEB Peb, PULONG Options) +LdrpInitializeExecutionOptions(PUNICODE_STRING ImagePathName, PPEB Peb, PHKEY OptionsKey) { UNIMPLEMENTED; - *Options = 0; + *OptionsKey = NULL; return STATUS_SUCCESS; } @@ -915,7 +1342,7 @@ LdrpInitializeProcess(IN PCONTEXT Context, //LPWSTR ImagePathBuffer; ULONG ConfigSize; UNICODE_STRING CurrentDirectory; - ULONG ExecuteOptions; + HKEY OptionsKey; ULONG HeapFlags; PIMAGE_NT_HEADERS NtHeader; LPWSTR NtDllName = NULL; @@ -928,9 +1355,9 @@ LdrpInitializeProcess(IN PCONTEXT Context, ULONG i; PWSTR ImagePath; ULONG DebugProcessHeapOnly = 0; - WCHAR FullNtDllPath[MAX_PATH]; PLDR_DATA_TABLE_ENTRY NtLdrEntry; PWCHAR Current; + ULONG ExecuteOptions = 0; /* Set a NULL SEH Filter */ RtlSetUnhandledExceptionFilter(NULL); @@ -954,7 +1381,7 @@ LdrpInitializeProcess(IN PCONTEXT Context, NtHeader = RtlImageNtHeader(Peb->ImageBaseAddress); /* Get the execution options */ - Status = LdrpInitializeExecutionOptions(&ImagePathName, Peb, &ExecuteOptions); + Status = LdrpInitializeExecutionOptions(&ImagePathName, Peb, &OptionsKey); /* Check if this is a .NET executable */ if (RtlImageDirectoryEntryToData(Peb->ImageBaseAddress, @@ -1040,7 +1467,7 @@ LdrpInitializeProcess(IN PCONTEXT Context, } /* Check if verbose debugging (ShowSnaps) was requested */ - ShowSnaps = TRUE;//Peb->NtGlobalFlag & FLG_SHOW_LDR_SNAPS; + ShowSnaps = Peb->NtGlobalFlag & FLG_SHOW_LDR_SNAPS; /* Start verbose debugging messages right now if they were requested */ if (ShowSnaps) @@ -1091,9 +1518,11 @@ LdrpInitializeProcess(IN PCONTEXT Context, } /* Initialize the Loader Lock */ + // FIXME: What's the point of initing it manually, if two lines lower + // a call to RtlInitializeCriticalSection() is being made anyway? //InsertTailList(&RtlCriticalSectionList, &LdrpLoaderLock.DebugInfo->ProcessLocksList); //LdrpLoaderLock.DebugInfo->CriticalSection = &LdrpLoaderLock; - UNIMPLEMENTED; + RtlInitializeCriticalSection(&LdrpLoaderLock); LdrpLoaderLockInit = TRUE; /* Check if User Stack Trace Database support was requested */ @@ -1134,19 +1563,30 @@ LdrpInitializeProcess(IN PCONTEXT Context, return STATUS_NO_MEMORY; } + // FIXME: Is it located properly? + /* Initialize table of callbacks for the kernel. */ + Peb->KernelCallbackTable = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + sizeof(PVOID) * + (USER32_CALLBACK_MAXIMUM + 1)); + if (!Peb->KernelCallbackTable) + { + DPRINT1("Failed to create callback table\n"); + ZwTerminateProcess(NtCurrentProcess(), STATUS_INSUFFICIENT_RESOURCES); + } + /* Allocate an Activation Context Stack */ Status = RtlAllocateActivationContextStack((PVOID *)&Teb->ActivationContextStackPointer); if (!NT_SUCCESS(Status)) return Status; // FIXME: Loader private heap is missing - DPRINT1("Loader private heap is missing\n"); + //DPRINT1("Loader private heap is missing\n"); /* Check for Debug Heap */ - DPRINT1("Check for a debug heap is missing\n"); - if (FALSE) + if (OptionsKey) { /* Query the setting */ - Status = LdrQueryImageFileKeyOption(NULL,//hKey + Status = LdrQueryImageFileKeyOption(OptionsKey, L"DebugProcessHeapOnly", REG_DWORD, &DebugProcessHeapOnly, @@ -1165,9 +1605,9 @@ LdrpInitializeProcess(IN PCONTEXT Context, } /* Build the NTDLL Path */ - FullPath.Buffer = FullNtDllPath; + FullPath.Buffer = StringBuffer; FullPath.Length = 0; - FullPath.MaximumLength = sizeof(FullNtDllPath); + FullPath.MaximumLength = sizeof(StringBuffer); RtlInitUnicodeString(&NtSystemRoot, SharedUserData->NtSystemRoot); RtlAppendUnicodeStringToString(&FullPath, &NtSystemRoot); RtlAppendUnicodeToString(&FullPath, L"\\System32\\"); @@ -1188,7 +1628,7 @@ LdrpInitializeProcess(IN PCONTEXT Context, { /* It doesn't, so assume System32 */ LdrpKnownDllObjectDirectory = NULL; - RtlInitUnicodeString(&LdrpKnownDllPath, FullPath.Buffer); + RtlInitUnicodeString(&LdrpKnownDllPath, StringBuffer); LdrpKnownDllPath.Length -= sizeof(WCHAR); } else @@ -1230,6 +1670,7 @@ LdrpInitializeProcess(IN PCONTEXT Context, else { /* We need a valid path */ + DPRINT1("No valid DllPath was given!\n"); LdrpInitFailure(STATUS_INVALID_PARAMETER); } @@ -1246,6 +1687,11 @@ LdrpInitializeProcess(IN PCONTEXT Context, 0, 3 * sizeof(WCHAR) + sizeof(UNICODE_NULL)); + if (!CurrentDirectory.Buffer) + { + DPRINT1("LDR: LdrpInitializeProcess - unable to allocate current working directory buffer\n"); + // FIXME: And what? + } /* Copy the drive of the system root */ RtlMoveMemory(CurrentDirectory.Buffer, @@ -1256,12 +1702,12 @@ LdrpInitializeProcess(IN PCONTEXT Context, CurrentDirectory.MaximumLength = CurrentDirectory.Length + sizeof(WCHAR); FreeCurDir = TRUE; + DPRINT("Using dynamically allocd curdir\n"); } else { /* Use the local buffer */ - CurrentDirectory.Length = NtSystemRoot.Length; - CurrentDirectory.Buffer = NtSystemRoot.Buffer; + DPRINT("Using local system root\n"); } } @@ -1280,8 +1726,8 @@ LdrpInitializeProcess(IN PCONTEXT Context, NtLdrEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(NtLdrEntry->DllBase); NtLdrEntry->LoadCount = -1; NtLdrEntry->EntryPointActivationContext = 0; - NtLdrEntry->FullDllName.Length = ImageFileName.Length; - NtLdrEntry->FullDllName.Buffer = ImageFileName.Buffer; + NtLdrEntry->FullDllName = ImageFileName; + if (IsDotNetImage) NtLdrEntry->Flags = LDRP_COR_IMAGE; else @@ -1291,7 +1737,7 @@ LdrpInitializeProcess(IN PCONTEXT Context, if (!ImageFileName.Buffer[0]) { /* Use the same Base name */ - NtLdrEntry->BaseDllName = NtLdrEntry->BaseDllName; + NtLdrEntry->BaseDllName = NtLdrEntry->FullDllName; } else { @@ -1332,14 +1778,16 @@ LdrpInitializeProcess(IN PCONTEXT Context, NtLdrEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(NtLdrEntry->DllBase); NtLdrEntry->LoadCount = -1; NtLdrEntry->EntryPointActivationContext = 0; - //NtLdrEntry->BaseDllName.Length = NtSystemRoot.Length; - //RtlAppendUnicodeStringToString(&NtSystemRoot, &NtDllString); + + NtLdrEntry->FullDllName.Length = FullPath.Length; + NtLdrEntry->FullDllName.MaximumLength = FullPath.MaximumLength; + NtLdrEntry->FullDllName.Buffer = StringBuffer; + RtlAppendUnicodeStringToString(&NtLdrEntry->FullDllName, &NtDllString); + NtLdrEntry->BaseDllName.Length = NtDllString.Length; NtLdrEntry->BaseDllName.MaximumLength = NtDllString.MaximumLength; NtLdrEntry->BaseDllName.Buffer = NtDllString.Buffer; - // FIXME: Full DLL name?! - /* Processing done, insert it */ LdrpNtDllDataTableEntry = NtLdrEntry; LdrpInsertMemoryTableEntry(NtLdrEntry); @@ -1510,7 +1958,7 @@ LdrpInitializeProcess(IN PCONTEXT Context, ///* Close the key if we have one opened */ //if (hKey) NtClose(hKey); -DbgBreakPoint(); + /* Return status */ return Status; } @@ -1596,7 +2044,7 @@ LdrpInit(PCONTEXT Context, _SEH2_TRY { /* Initialize the Process */ - LoaderStatus = LdrpInitializeProcess_(Context, + LoaderStatus = LdrpInitializeProcess(Context, SystemArgument1); /* Check for success and if MinimumStackCommit was requested */ diff --git a/reactos/dll/ntdll/ldr/ldrpe.c b/reactos/dll/ntdll/ldr/ldrpe.c index 12e24fe547d..41694d37e96 100644 --- a/reactos/dll/ntdll/ldr/ldrpe.c +++ b/reactos/dll/ntdll/ldr/ldrpe.c @@ -100,9 +100,7 @@ LdrpSnapIAT(IN PLDR_DATA_TABLE_ENTRY ExportLdrEntry, /* Deal with Watcom and other retarded compilers */ if (!IatSize) - { IatSize = SectionHeader->SizeOfRawData; - } /* Found it, get out */ break; @@ -255,7 +253,7 @@ NTSTATUS NTAPI LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL, IN PLDR_DATA_TABLE_ENTRY LdrEntry, - IN PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundEntry, + IN PIMAGE_BOUND_IMPORT_DESCRIPTOR *BoundEntryPtr, IN PIMAGE_BOUND_IMPORT_DESCRIPTOR FirstEntry) { LPSTR ImportName = NULL, BoundImportName, ForwarderName; @@ -264,11 +262,15 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL, PIMAGE_IMPORT_DESCRIPTOR ImportEntry; PLDR_DATA_TABLE_ENTRY DllLdrEntry, ForwarderLdrEntry; PIMAGE_BOUND_FORWARDER_REF ForwarderEntry; + PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundEntry; PPEB Peb = NtCurrentPeb(); ULONG i, IatSize; + /* Get the pointer to the bound entry */ + BoundEntry = *BoundEntryPtr; + /* Get the name's VA */ - BoundImportName = (LPSTR)(BoundEntry + BoundEntry->OffsetModuleName); + BoundImportName = (LPSTR)FirstEntry + BoundEntry->OffsetModuleName; /* Show debug mesage */ if (ShowSnaps) @@ -311,7 +313,7 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL, if (ShowSnaps) { DPRINT1("LDR: %wZ has stale binding to %s\n", - &DllLdrEntry->BaseDllName, + &LdrEntry->BaseDllName, BoundImportName); } @@ -324,7 +326,7 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL, if (ShowSnaps) { DPRINT1("LDR: %wZ has correct binding to %s\n", - &DllLdrEntry->BaseDllName, + &LdrEntry->BaseDllName, BoundImportName); } @@ -339,7 +341,7 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL, for (i = 0; i < BoundEntry->NumberOfModuleForwarderRefs; i++) { /* Get the name */ - ForwarderName = (LPSTR)(FirstEntry + ForwarderEntry->OffsetModuleName); + ForwarderName = (LPSTR)FirstEntry + ForwarderEntry->OffsetModuleName; /* Show debug message */ if (ShowSnaps) @@ -376,7 +378,7 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL, if (ShowSnaps) { DPRINT1("LDR: %wZ has stale binding to %s\n", - &ForwarderLdrEntry->BaseDllName, + &LdrEntry->BaseDllName, ForwarderName); } @@ -389,7 +391,7 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL, if (ShowSnaps) { DPRINT1("LDR: %wZ has correct binding to %s\n", - &ForwarderLdrEntry->BaseDllName, + &LdrEntry->BaseDllName, ForwarderName); } @@ -423,7 +425,7 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL, if (!_stricmp(ImportName, BoundImportName)) break; /* Move to next entry */ - ImportEntry += 1; + ImportEntry++; } /* If we didn't find a name, fail */ @@ -477,7 +479,7 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL, Quickie: /* Write where we are now and return */ - *BoundEntry = *FirstEntry; + *BoundEntryPtr = FirstEntry; return Status; } @@ -496,7 +498,7 @@ LdrpHandleNewFormatImportDescriptors(IN LPWSTR DllPath OPTIONAL, /* Parse this descriptor */ Status = LdrpHandleOneNewFormatImportDescriptor(DllPath, LdrEntry, - BoundEntry, + &BoundEntry, FirstEntry); if (!NT_SUCCESS(Status)) return Status; } @@ -642,8 +644,35 @@ LdrpNameToOrdinal(LPSTR ImportName, PULONG NameTable, PUSHORT OrdinalTable) { - UNIMPLEMENTED; - return 0; + ULONG Start, End, Next; + LONG CmpResult; + + /* Use classical binary search to find the ordinal */ + Start = 0; + End = NumberOfNames - 1; + while (End >= Start) + { + /* Next will be exactly between Start and End */ + Next = (Start + End) >> 1; + + /* Compare this name with the one we need to find */ + CmpResult = strcmp(ImportName, (PCHAR)((ULONG_PTR)ExportBase + NameTable[Next])); + + /* We found our entry if result is 0 */ + if (!CmpResult) break; + + /* We didn't find, update our range then */ + if (CmpResult < 0) + End = Next - 1; + else if (CmpResult > 0) + Start = Next + 1; + } + + /* If end is before start, then the search failed */ + if (End < Start) return -1; + + /* Return found name */ + return OrdinalTable[Next]; } NTSTATUS @@ -657,10 +686,12 @@ LdrpWalkImportDescriptor(IN LPWSTR DllPath OPTIONAL, PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundEntry = NULL; PIMAGE_IMPORT_DESCRIPTOR ImportEntry; ULONG BoundSize, IatSize; -DPRINT1("LdrpWalkImportDescriptor('%S' %x)\n", DllPath, LdrEntry); + + DPRINT("LdrpWalkImportDescriptor('%S' %x)\n", DllPath, LdrEntry); + /* Set up the Act Ctx */ ActCtx.Size = sizeof(ActCtx); - ActCtx.Frame.Flags = 1; + ActCtx.Format = 1; RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); /* Check if we have a manifest prober routine */ @@ -680,7 +711,7 @@ DPRINT1("LdrpWalkImportDescriptor('%S' %x)\n", DllPath, LdrEntry); RtlActivateActivationContextUnsafeFast(&ActCtx, LdrEntry->EntryPointActivationContext); - /* Check if we were directed */ + /* Check if we were redirected */ if (!(LdrEntry->Flags & LDRP_REDIRECTED)) { /* Get the Bound IAT */ @@ -764,7 +795,9 @@ LdrpLoadImportModule(IN PWSTR DllPath OPTIONAL, NTSTATUS Status; PPEB Peb = RtlGetCurrentPeb(); PTEB Teb = NtCurrentTeb(); -DPRINT1("LdrpLoadImportModule('%S' '%s' %p %p %p)\n", DllPath, ImportName, DllBase, DataTableEntry, Existing); + + DPRINT("LdrpLoadImportModule('%S' '%s' %p %p %p)\n", DllPath, ImportName, DllBase, DataTableEntry, Existing); + /* Convert import descriptor name to unicode string */ ImpDescName = &Teb->StaticUnicodeString; RtlInitAnsiString(&AnsiString, ImportName); @@ -788,8 +821,8 @@ DPRINT1("LdrpLoadImportModule('%S' '%s' %p %p %p)\n", DllPath, ImportName, DllBa /* Map it */ Status = LdrpMapDll(DllPath, - ImpDescName->Buffer, NULL, + ImpDescName->Buffer, NULL, TRUE, FALSE, @@ -893,6 +926,12 @@ FailurePath: /* Is this a static snap? */ if (Static) { + /* Inform the debug log */ + if (IsOrdinal) + DPRINT1("Failed to snap ordinal 0x%x\n", OriginalOrdinal); + else + DPRINT1("Failed to snap %s\n", ImportName); + /* These are critical errors. Setup a string for the DLL name */ RtlInitAnsiString(&TempString, DllName ? DllName : "Unknown"); RtlAnsiStringToUnicodeString(&HardErrorDllName, &TempString, TRUE); @@ -944,6 +983,14 @@ FailurePath: /* Return ordinal error */ RtlRaiseStatus(STATUS_ORDINAL_NOT_FOUND); } + else + { + /* Inform the debug log */ + if (IsOrdinal) + DPRINT("Non-fatal: Failed to snap ordinal 0x%x\n", OriginalOrdinal); + else + DPRINT("Non-fatal: Failed to snap %s\n", ImportName); + } /* Set this as a bad DLL */ Thunk->u1.Function = (ULONG_PTR)0xffbadd11; diff --git a/reactos/dll/ntdll/ldr/ldrutils.c b/reactos/dll/ntdll/ldr/ldrutils.c index 8c2783755ae..9ad33ee6fbf 100644 --- a/reactos/dll/ntdll/ldr/ldrutils.c +++ b/reactos/dll/ntdll/ldr/ldrutils.c @@ -14,8 +14,11 @@ #include /* 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)) @@ -32,6 +35,241 @@ LdrpCallDllEntry(PDLLMAIN_FUNC EntryPoint, 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; iNumberOfModuleForwarderRefs; 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) @@ -84,6 +322,259 @@ LdrpTlsCallback(PVOID BaseAddress, ULONG Reason) _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) @@ -105,6 +596,170 @@ LdrpFetchAddressOfEntryPoint(PVOID ImageBase) 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, @@ -115,8 +770,504 @@ LdrpMapDll(IN PWSTR SearchPath OPTIONAL, IN BOOLEAN Redirect, OUT PLDR_DATA_TABLE_ENTRY *DataTableEntry) { - UNIMPLEMENTED; - return STATUS_SUCCESS; + 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); + } + } + } + + // FIXME: LdrpCheckCorImage() is missing + + /* 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); + } + + // FIXME: LdrpCorUnloadImage() is missing + + /* Close section and return status */ + NtClose(SectionHandle); + return Status; } PLDR_DATA_TABLE_ENTRY @@ -126,6 +1277,8 @@ LdrpAllocateDataTableEntry(IN PVOID BaseAddress) 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) { @@ -163,6 +1316,33 @@ LdrpInsertMemoryTableEntry(IN PLDR_DATA_TABLE_ENTRY LdrEntry) 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, @@ -231,7 +1411,9 @@ LdrpCheckForLoadedDll(IN PWSTR DllPath, 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; @@ -499,7 +1681,7 @@ LdrpGetProcedureAddress(IN PVOID BaseAddress, 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) @@ -527,8 +1709,8 @@ LdrpGetProcedureAddress(IN PVOID BaseAddress, 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; @@ -540,7 +1722,7 @@ LdrpGetProcedureAddress(IN PVOID BaseAddress, ImageBase = NULL; /* Show debug message */ - if (ShowSnaps) DPRINT1("ORDINAL - %lx\n", Ordinal); + if (ShowSnaps) DbgPrint("ORDINAL - %lx\n", Ordinal); if (Ordinal) { @@ -563,7 +1745,7 @@ LdrpGetProcedureAddress(IN PVOID BaseAddress, 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;) } @@ -576,7 +1758,7 @@ LdrpGetProcedureAddress(IN PVOID BaseAddress, 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;) } @@ -657,8 +1839,474 @@ LdrpLoadDll(IN BOOLEAN Redirected, 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) Status = RtlLeaveCriticalSection(Peb->LoaderLock); + + /* FIXME: Rundown the Hotpatch data, if present */ + + /* Return to caller */ + return Status; } ULONG @@ -692,4 +2340,111 @@ LdrpClearLoadInProgress() 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); + Locked = TRUE; + + if (!NT_SUCCESS(Status)) goto quickie; + } + + /* 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 */ diff --git a/reactos/dll/ntdll/ldr/startup.c b/reactos/dll/ntdll/ldr/startup.c index f063aefdc0d..90c2ca8b417 100644 --- a/reactos/dll/ntdll/ldr/startup.c +++ b/reactos/dll/ntdll/ldr/startup.c @@ -10,12 +10,11 @@ /* INCLUDES *****************************************************************/ #include -#define NDEBUG +//#define NDEBUG #include #include VOID RtlInitializeHeapManager(VOID); -VOID LdrpInitLoader(VOID); extern PTEB LdrpTopLevelDllBeingLoadedTeb; VOID NTAPI RtlpInitDeferedCriticalSection(VOID); VOID RtlpInitializeVectoredExceptionHandling(VOID); @@ -309,280 +308,4 @@ finish: return FALSE; } -NTSTATUS -NTAPI -LdrpInitializeProcess_(PCONTEXT Context, - PVOID SystemArgument1) -{ - PIMAGE_NT_HEADERS NTHeaders; - PEPFUNC EntryPoint; - PIMAGE_DOS_HEADER PEDosHeader; - PVOID ImageBase; - PPEB Peb = NtCurrentPeb(); - PLDR_DATA_TABLE_ENTRY NtModule; // ntdll - NLSTABLEINFO NlsTable; - WCHAR FullNtDllPath[MAX_PATH]; - SYSTEM_BASIC_INFORMATION SystemInformation; - NTSTATUS Status; - PVOID BaseAddress = SystemArgument1; - - DPRINT("LdrpInit()\n"); - DPRINT("Peb %p\n", Peb); - ImageBase = Peb->ImageBaseAddress; - DPRINT("ImageBase %p\n", ImageBase); - - if (ImageBase <= (PVOID) 0x1000) - { - DPRINT("ImageBase is null\n"); - ZwTerminateProcess(NtCurrentProcess(), STATUS_INVALID_IMAGE_FORMAT); - } - - /* If MZ header exists */ - PEDosHeader = (PIMAGE_DOS_HEADER) ImageBase; - NTHeaders = (PIMAGE_NT_HEADERS)((ULONG_PTR)ImageBase + PEDosHeader->e_lfanew); - DPRINT("PEDosHeader %p\n", PEDosHeader); - - if (PEDosHeader->e_magic != IMAGE_DOS_SIGNATURE || - PEDosHeader->e_lfanew == 0L || - NTHeaders->Signature != IMAGE_NT_SIGNATURE) - { - DPRINT1("Image has bad header\n"); - ZwTerminateProcess(NtCurrentProcess(), STATUS_INVALID_IMAGE_FORMAT); - } - - /* normalize process parameters */ - RtlNormalizeProcessParams(Peb->ProcessParameters); - - /* Initialize NLS data */ - RtlInitNlsTables(Peb->AnsiCodePageData, - Peb->OemCodePageData, - Peb->UnicodeCaseTableData, - &NlsTable); - RtlResetRtlTranslations(&NlsTable); - - /* Get number of processors */ - DPRINT("Here\n"); - Status = ZwQuerySystemInformation(SystemBasicInformation, - &SystemInformation, - sizeof(SYSTEM_BASIC_INFORMATION), - NULL); - DPRINT("Here2\n"); - if (!NT_SUCCESS(Status)) - { - ZwTerminateProcess(NtCurrentProcess(), Status); - } - - Peb->NumberOfProcessors = SystemInformation.NumberOfProcessors; - - /* Initialize Critical Section Data */ - RtlpInitDeferedCriticalSection(); - - /* Load execution options */ - LoadImageFileExecutionOptions(Peb); - - /* create process heap */ - RtlInitializeHeapManager(); - Peb->ProcessHeap = RtlCreateHeap(HEAP_GROWABLE, - NULL, - NTHeaders->OptionalHeader.SizeOfHeapReserve, - NTHeaders->OptionalHeader.SizeOfHeapCommit, - NULL, - NULL); - if (Peb->ProcessHeap == 0) - { - DPRINT1("Failed to create process heap\n"); - ZwTerminateProcess(NtCurrentProcess(), STATUS_INSUFFICIENT_RESOURCES); - } - - /* Check for correct machine type */ - if (NTHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_NATIVE) - { - ULONG_PTR HardErrorParameters[1]; - UNICODE_STRING ImageNameU; - ANSI_STRING ImageNameA; - WCHAR *Ptr; - ULONG ErrorResponse; - - DPRINT1("Image %wZ is for a foreign architecture (0x%x).\n", - &Peb->ProcessParameters->ImagePathName, NTHeaders->FileHeader.Machine); - - /* Get the full image path name */ - ImageNameU = Peb->ProcessParameters->ImagePathName; - - /* Get the file name */ - Ptr = Peb->ProcessParameters->ImagePathName.Buffer + - (Peb->ProcessParameters->ImagePathName.Length / sizeof(WCHAR)) -1; - while ((Ptr >= Peb->ProcessParameters->ImagePathName.Buffer) && - (*Ptr != L'\\')) Ptr--; - ImageNameU.Buffer = Ptr + 1; - ImageNameU.Length = Peb->ProcessParameters->ImagePathName.Length - - (ImageNameU.Buffer - Peb->ProcessParameters->ImagePathName.Buffer) * sizeof(WCHAR); - ImageNameU.MaximumLength = ImageNameU.Length; - - /*`Convert to ANSI, harderror message needs that */ - RtlUnicodeStringToAnsiString(&ImageNameA, &ImageNameU, TRUE); - - /* Raise harderror */ - HardErrorParameters[0] = (ULONG_PTR)&ImageNameA; - NtRaiseHardError(STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE, - 1, - 1, - HardErrorParameters, - OptionOk, - &ErrorResponse); - - RtlFreeAnsiString(&ImageNameA); - ZwTerminateProcess(NtCurrentProcess(), STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE); - } - - /* initialized vectored exception handling */ - RtlpInitializeVectoredExceptionHandling(); - - /* initalize peb lock support */ - RtlInitializeCriticalSection(&FastPebLock); - Peb->FastPebLock = &FastPebLock; - - /* initialize tls bitmaps */ - RtlInitializeBitMap(&TlsBitMap, Peb->TlsBitmapBits, TLS_MINIMUM_AVAILABLE); - RtlInitializeBitMap(&TlsExpansionBitMap, Peb->TlsExpansionBitmapBits, TLS_EXPANSION_SLOTS); - - Peb->TlsBitmap = &TlsBitMap; - Peb->TlsExpansionBitmap = &TlsExpansionBitMap; - Peb->TlsExpansionCounter = TLS_MINIMUM_AVAILABLE; - - /* Initialize table of callbacks for the kernel. */ - Peb->KernelCallbackTable = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - sizeof(PVOID) * - (USER32_CALLBACK_MAXIMUM + 1)); - if (Peb->KernelCallbackTable == NULL) - { - DPRINT1("Failed to create callback table\n"); - ZwTerminateProcess(NtCurrentProcess(), STATUS_INSUFFICIENT_RESOURCES); - } - - /* initalize loader lock */ - RtlInitializeCriticalSection(&LdrpLoaderLock); - Peb->LoaderLock = &LdrpLoaderLock; - - /* create loader information */ - Peb->Ldr = (PPEB_LDR_DATA) RtlAllocateHeap(Peb->ProcessHeap, - 0, - sizeof(PEB_LDR_DATA)); - if (Peb->Ldr == NULL) - { - DPRINT1("Failed to create loader data\n"); - ZwTerminateProcess(NtCurrentProcess(), STATUS_INSUFFICIENT_RESOURCES); - } - - Peb->Ldr->Length = sizeof(PEB_LDR_DATA); - Peb->Ldr->Initialized = FALSE; - Peb->Ldr->SsHandle = NULL; - InitializeListHead(&Peb->Ldr->InLoadOrderModuleList); - InitializeListHead(&Peb->Ldr->InMemoryOrderModuleList); - InitializeListHead(&Peb->Ldr->InInitializationOrderModuleList); - - /* Load compatibility settings */ - LoadCompatibilitySettings(Peb); - - /* build full ntdll path */ - wcscpy(FullNtDllPath, SharedUserData->NtSystemRoot); - wcscat(FullNtDllPath, L"\\system32\\ntdll.dll"); - - /* add entry for ntdll */ - NtModule = (PLDR_DATA_TABLE_ENTRY) - RtlAllocateHeap(Peb->ProcessHeap, - 0, - sizeof(LDR_DATA_TABLE_ENTRY)); - if (NtModule == NULL) - { - DPRINT1("Failed to create loader module entry (NTDLL)\n"); - ZwTerminateProcess(NtCurrentProcess(), STATUS_INSUFFICIENT_RESOURCES); - } - memset(NtModule, 0, sizeof(LDR_DATA_TABLE_ENTRY)); - - NtModule->DllBase = BaseAddress; - NtModule->EntryPoint = 0; /* no entry point */ - RtlCreateUnicodeString(&NtModule->FullDllName, FullNtDllPath); - RtlCreateUnicodeString(&NtModule->BaseDllName, L"ntdll.dll"); - NtModule->Flags = LDRP_IMAGE_DLL | LDRP_ENTRY_PROCESSED; - - NtModule->LoadCount = -1; /* don't unload */ - NtModule->TlsIndex = -1; - NtModule->SectionPointer = NULL; - NtModule->CheckSum = 0; - - NTHeaders = RtlImageNtHeader(NtModule->DllBase); - NtModule->SizeOfImage = LdrpGetResidentSize(NTHeaders); - NtModule->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp; - - InsertTailList(&Peb->Ldr->InLoadOrderModuleList, - &NtModule->InLoadOrderLinks); - InsertTailList(&Peb->Ldr->InInitializationOrderModuleList, - &NtModule->InInitializationOrderModuleList); - - /* add entry for executable (becomes first list entry) */ - LdrpImageEntry = (PLDR_DATA_TABLE_ENTRY) - RtlAllocateHeap(Peb->ProcessHeap, - HEAP_ZERO_MEMORY, - sizeof(LDR_DATA_TABLE_ENTRY)); - if (LdrpImageEntry == NULL) - { - DPRINT1("Failed to create loader module infomation\n"); - ZwTerminateProcess(NtCurrentProcess(), STATUS_INSUFFICIENT_RESOURCES); - } - - LdrpImageEntry->DllBase = Peb->ImageBaseAddress; - - if ((Peb->ProcessParameters == NULL) || - (Peb->ProcessParameters->ImagePathName.Length == 0)) - { - DPRINT1("Failed to access the process parameter block\n"); - ZwTerminateProcess(NtCurrentProcess(), STATUS_UNSUCCESSFUL); - } - - RtlCreateUnicodeString(&LdrpImageEntry->FullDllName, - Peb->ProcessParameters->ImagePathName.Buffer); - RtlCreateUnicodeString(&LdrpImageEntry->BaseDllName, - wcsrchr(LdrpImageEntry->FullDllName.Buffer, L'\\') + 1); - - DPRINT("BaseDllName '%wZ' FullDllName '%wZ'\n", &LdrpImageEntry->BaseDllName, &LdrpImageEntry->FullDllName); - - LdrpImageEntry->Flags = LDRP_ENTRY_PROCESSED; - LdrpImageEntry->LoadCount = -1; /* don't unload */ - LdrpImageEntry->TlsIndex = -1; - LdrpImageEntry->SectionPointer = NULL; - LdrpImageEntry->CheckSum = 0; - - NTHeaders = RtlImageNtHeader(LdrpImageEntry->DllBase); - LdrpImageEntry->SizeOfImage = LdrpGetResidentSize(NTHeaders); - LdrpImageEntry->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp; - - LdrpTopLevelDllBeingLoadedTeb = NtCurrentTeb(); - - InsertHeadList(&Peb->Ldr->InLoadOrderModuleList, - &LdrpImageEntry->InLoadOrderLinks); - - LdrpInitLoader(); - - EntryPoint = LdrPEStartup((PVOID)ImageBase, NULL, NULL, NULL); - LdrpImageEntry->EntryPoint = EntryPoint; - - /* all required dlls are loaded now */ - Peb->Ldr->Initialized = TRUE; - - /* Check before returning that we can run the image safely. */ - if (EntryPoint == NULL) - { - DPRINT1("Failed to initialize image\n"); - ZwTerminateProcess(NtCurrentProcess(), STATUS_INVALID_IMAGE_FORMAT); - } - - /* Break into debugger */ - if (Peb->BeingDebugged) - DbgBreakPoint(); - - return STATUS_SUCCESS; -} - /* EOF */ diff --git a/reactos/dll/ntdll/ldr/utils.c b/reactos/dll/ntdll/ldr/utils.c index 9ce0cbb9feb..fe39e90053d 100644 --- a/reactos/dll/ntdll/ldr/utils.c +++ b/reactos/dll/ntdll/ldr/utils.c @@ -42,31 +42,12 @@ extern PLDR_DATA_TABLE_ENTRY LdrpImageEntry; 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; @@ -105,193 +86,6 @@ static __inline LONG LdrpIncrementLoadCount(PLDR_DATA_TABLE_ENTRY Module, BOOLEA 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 @@ -328,6 +122,8 @@ LdrAdjustDllName (PUNICODE_STRING FullDllName, PWCHAR Extension; PWCHAR Pointer; + DPRINT1("\n"); + Length = DllName->Length / sizeof(WCHAR); if (BaseName) @@ -379,6 +175,8 @@ LdrAddModuleEntry(PVOID ImageBase, { 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)); @@ -420,407 +218,6 @@ LdrAddModuleEntry(PVOID ImageBase, 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 @@ -944,6 +341,8 @@ LdrFixupForward(PCHAR ForwardName) PLDR_DATA_TABLE_ENTRY Module; PVOID BaseAddress; + DPRINT1("\n"); + strcpy(NameBuffer, ForwardName); p = strchr(NameBuffer, '.'); if (p != NULL) @@ -982,58 +381,6 @@ LdrFixupForward(PCHAR ForwardName) } -/********************************************************************** - * NAME LOCAL - * LdrGetExportByOrdinal - * - * DESCRIPTION - * - * ARGUMENTS - * - * RETURN VALUE - * - * REVISIONS - * - * NOTE - * - */ -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 @@ -1201,6 +548,8 @@ LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders, LONG_PTR Delta; NTSTATUS Status; + DPRINT1("\n"); + if (NTHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) { return STATUS_SUCCESS; @@ -1294,56 +643,6 @@ LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders, 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) { @@ -1353,6 +652,8 @@ RtlpRaiseImportNotFound(CHAR *FuncName, ULONG Ordinal, PUNICODE_STRING DllName) ANSI_STRING DllNameAnsi; CHAR Buffer[8]; + DPRINT1("\n"); + if (!FuncName) { _snprintf(Buffer, 8, "# %ld", Ordinal); @@ -1372,993 +673,6 @@ RtlpRaiseImportNotFound(CHAR *FuncName, ULONG Ordinal, PUNICODE_STRING DllName) RtlFreeAnsiString(&DllNameAnsi); } -static NTSTATUS -LdrpProcessImportDirectoryEntry(PLDR_DATA_TABLE_ENTRY Module, - PLDR_DATA_TABLE_ENTRY ImportedModule, - PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory) -{ - 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++; - } - - /* 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); - } - - 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); - - - 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, ImportedName)) - { - Status = LdrpProcessImportDirectoryEntry(Module, - ImportedModule, - ImportModuleDirectory); - if (!NT_SUCCESS(Status)) - { - return Status; - } - } - ImportModuleDirectory++; - } - - - return STATUS_SUCCESS; -} - - -static NTSTATUS -LdrpAdjustImportDirectory(PLDR_DATA_TABLE_ENTRY Module, - PLDR_DATA_TABLE_ENTRY ImportedModule, - PCHAR ImportedName) -{ - 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; -} - - -/********************************************************************** - * NAME LOCAL - * LdrFixupImports - * - * DESCRIPTION - * Compute the entry point for every symbol the DLL imports - * from other modules. - * - * ARGUMENTS - * - * RETURN VALUE - * - * REVISIONS - * - * NOTE - * - */ -static NTSTATUS -LdrFixupImports(IN PWSTR SearchPath OPTIONAL, - IN PLDR_DATA_TABLE_ENTRY Module) -{ - 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); - } - - 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 */ @@ -2397,379 +711,16 @@ LdrDisableThreadCalloutsForDll(IN PVOID BaseAddress) 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) { + DPRINT1("\n"); 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) @@ -2781,6 +732,8 @@ LdrpGetResidentSize(PIMAGE_NT_HEADERS NTHeaders) unsigned SectionIndex; ULONG ResidentSize; + DPRINT1("\n"); + SectionHeader = (PIMAGE_SECTION_HEADER)((char *) &NTHeaders->OptionalHeader + NTHeaders->FileHeader.SizeOfOptionalHeader); ResidentSize = 0; @@ -2807,6 +760,7 @@ LdrProcessRelocationBlock( IN PUSHORT TypeOffset, IN LONG_PTR Delta) { + DPRINT1("\n"); return LdrProcessRelocationBlockLongLong(Address, Count, TypeOffset, Delta); } @@ -2814,6 +768,7 @@ BOOLEAN NTAPI LdrUnloadAlternateResourceModule(IN PVOID BaseAddress) { - UNIMPLEMENTED; + //FIXME: We don't implement alternate resources anyway, don't spam the log + //UNIMPLEMENTED; return FALSE; } diff --git a/reactos/dll/win32/kernel32/misc/ldr.c b/reactos/dll/win32/kernel32/misc/ldr.c index b383f1dd6a1..b2874cf3b73 100644 --- a/reactos/dll/win32/kernel32/misc/ldr.c +++ b/reactos/dll/win32/kernel32/misc/ldr.c @@ -443,20 +443,11 @@ LoadLibraryExW(LPCWSTR lpLibFileName, } } - /* HACK!!! FIXME */ - if (InWindows) - { - /* Call the API Properly */ - Status = LdrLoadDll(SearchPath, - &DllCharacteristics, - &DllName, - (PVOID*)&hInst); - } - else - { - /* Call the ROS API. NOTE: Don't fix this, I have a patch to merge later. */ - Status = LdrLoadDll(SearchPath, &dwFlags, &DllName, (PVOID*)&hInst); - } + /* Call the API Properly */ + Status = LdrLoadDll(SearchPath, + &DllCharacteristics, + &DllName, + (PVOID*)&hInst); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { diff --git a/reactos/lib/rtl/actctx.c b/reactos/lib/rtl/actctx.c index 2abea6e172c..71a5459a52c 100644 --- a/reactos/lib/rtl/actctx.c +++ b/reactos/lib/rtl/actctx.c @@ -2736,6 +2736,10 @@ NTAPI RtlAllocateActivationContextStack(IN PVOID *Context) { PACTIVATION_CONTEXT_STACK ContextStack; + + /* FIXME: Check if it's already allocated */ + //if (*Context) return STATUS_SUCCESS; + ContextStack = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof (ACTIVATION_CONTEXT_STACK) ); if (!ContextStack) { @@ -2798,7 +2802,16 @@ RtlActivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTE /* Return pointer to the activation frame */ return &Frame->Frame; #else - return NULL; + + RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame = &Frame->Frame; + + frame->Previous = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; + frame->ActivationContext = Context; + frame->Flags = 0; + + NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame; + + return STATUS_SUCCESS; #endif } @@ -2806,7 +2819,6 @@ PRTL_ACTIVATION_CONTEXT_STACK_FRAME FASTCALL RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame) { -#if NEW_NTDLL_LOADER RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top; /* find the right frame */ @@ -2820,9 +2832,6 @@ RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CON NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame->Previous; return frame; -#else - return NULL; -#endif }