X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=dll%2Fntdll%2Fldr%2Fldrinit.c;h=bc72c952cdd778319ca4e762c5212ee0b0dd2bf5;hp=2c7094d78733f53bb4199415fe56cc108448fafd;hb=04ff7481b1da008b4e49354dda548ff8aa4853de;hpb=b819608ed8503c9668a797e62597645d99261eaf diff --git a/dll/ntdll/ldr/ldrinit.c b/dll/ntdll/ldr/ldrinit.c index 2c7094d7873..bc72c952cdd 100644 --- a/dll/ntdll/ldr/ldrinit.c +++ b/dll/ntdll/ldr/ldrinit.c @@ -10,9 +10,8 @@ /* INCLUDES *****************************************************************/ #include - -#include -#include +#include +#include #define NDEBUG #include @@ -25,6 +24,7 @@ HANDLE Wow64ExecOptionsKey; UNICODE_STRING ImageExecOptionsString = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options"); UNICODE_STRING Wow64OptionsString = RTL_CONSTANT_STRING(L""); UNICODE_STRING NtDllString = RTL_CONSTANT_STRING(L"ntdll.dll"); +UNICODE_STRING Kernel32String = RTL_CONSTANT_STRING(L"kernel32.dll"); BOOLEAN LdrpInLdrInit; LONG LdrpProcessInitialized; @@ -42,6 +42,9 @@ extern PTEB LdrpTopLevelDllBeingLoadedTeb; // defined in rtlsupp.c! PLDR_DATA_TABLE_ENTRY LdrpCurrentDllInitializer; PLDR_DATA_TABLE_ENTRY LdrpNtDllDataTableEntry; +static NTSTATUS (WINAPI *Kernel32ProcessInitPostImportFunction)(VOID); +static BOOL (WINAPI *Kernel32BaseQueryModuleData)(IN LPSTR ModuleName, IN LPSTR Unk1, IN PVOID Unk2, IN PVOID Unk3, IN PVOID Unk4); + RTL_BITMAP TlsBitMap; RTL_BITMAP TlsExpansionBitMap; RTL_BITMAP FlsBitMap; @@ -52,6 +55,7 @@ ULONG LdrpNumberOfProcessors; PVOID NtDllBase; extern LARGE_INTEGER RtlpTimeout; BOOLEAN RtlpTimeoutDisable; +PVOID LdrpHeap; LIST_ENTRY LdrpHashTable[LDR_HASH_TABLE_ENTRIES]; LIST_ENTRY LdrpDllNotificationList; HANDLE LdrpKnownDllObjectDirectory; @@ -80,16 +84,16 @@ ULONG LdrpActiveUnloadCount; //extern LIST_ENTRY RtlCriticalSectionList; -VOID RtlpInitializeVectoredExceptionHandling(VOID); +VOID NTAPI RtlpInitializeVectoredExceptionHandling(VOID); VOID NTAPI RtlpInitDeferedCriticalSection(VOID); VOID NTAPI RtlInitializeHeapManager(VOID); -extern BOOLEAN RtlpPageHeapEnabled; ULONG RtlpDisableHeapLookaside; // TODO: Move to heap.c ULONG RtlpShutdownProcessFlags; // TODO: Use it NTSTATUS LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders, PVOID ImageBase); void actctx_init(void); +extern BOOLEAN RtlpUse16ByteSLists; #ifdef _WIN64 #define DEFAULT_SECURITY_COOKIE 0x00002B992DDFA232ll @@ -137,7 +141,7 @@ LdrOpenImageFileOptionsKey(IN PUNICODE_STRING SubKey, if (NT_SUCCESS(Status)) { /* Write the key handle */ - if (_InterlockedCompareExchange((LONG*)RootKeyLocation, (LONG)RootKey, 0) != 0) + if (InterlockedCompareExchangePointer(RootKeyLocation, RootKey, NULL) != NULL) { /* Someone already opened it, use it instead */ NtClose(RootKey); @@ -397,7 +401,7 @@ LdrQueryImageFileExecutionOptions(IN PUNICODE_STRING SubKey, VOID NTAPI -LdrpEnsureLoaderLockIsHeld() +LdrpEnsureLoaderLockIsHeld(VOID) { // Ignored atm } @@ -461,8 +465,8 @@ LdrpInitSecurityCookie(PLDR_DATA_TABLE_ENTRY LdrEntry) NtQueryPerformanceCounter(&Counter, NULL); NewCookie = Counter.LowPart ^ Counter.HighPart; - NewCookie ^= (ULONG)NtCurrentTeb()->ClientId.UniqueProcess; - NewCookie ^= (ULONG)NtCurrentTeb()->ClientId.UniqueThread; + NewCookie ^= (ULONG_PTR)NtCurrentTeb()->ClientId.UniqueProcess; + NewCookie ^= (ULONG_PTR)NtCurrentTeb()->ClientId.UniqueThread; /* Loop like it's done in KeQueryTickCount(). We don't want to call it directly. */ while (SharedUserData->SystemTime.High1Time != SharedUserData->SystemTime.High2Time) @@ -528,7 +532,7 @@ LdrpInitializeThread(IN PCONTEXT Context) while (NextEntry != ListHead) { /* Get the current entry */ - LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderModuleList); + LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks); /* Make sure it's not ourselves */ if (Peb->ImageBaseAddress != LdrEntry->DllBase) @@ -553,30 +557,39 @@ LdrpInitializeThread(IN PCONTEXT Context) RtlActivateActivationContextUnsafeFast(&ActCtx, LdrEntry->EntryPointActivationContext); - /* Check if it has TLS */ - if (LdrEntry->TlsIndex) + _SEH2_TRY { + /* Check if it has TLS */ + if (LdrEntry->TlsIndex) + { + /* Make sure we're not shutting down */ + if (!LdrpShutdownInProgress) + { + /* Call TLS */ + LdrpCallTlsInitializers(LdrEntry, DLL_THREAD_ATTACH); + } + } + /* Make sure we're not shutting down */ if (!LdrpShutdownInProgress) { - /* Call TLS */ - LdrpCallTlsInitializers(LdrEntry->DllBase, DLL_THREAD_ATTACH); + /* Call the Entrypoint */ + DPRINT("%wZ - Calling entry point at %p for thread attaching, %p/%p\n", + &LdrEntry->BaseDllName, LdrEntry->EntryPoint, + NtCurrentTeb()->RealClientId.UniqueProcess, + NtCurrentTeb()->RealClientId.UniqueThread); + LdrpCallInitRoutine(LdrEntry->EntryPoint, + LdrEntry->DllBase, + DLL_THREAD_ATTACH, + NULL); } } - - /* Make sure we're not shutting down */ - if (!LdrpShutdownInProgress) + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - /* Call the Entrypoint */ - DPRINT("%wZ - Calling entry point at %p for thread attaching, %p/%p\n", - &LdrEntry->BaseDllName, LdrEntry->EntryPoint, - NtCurrentTeb()->RealClientId.UniqueProcess, - NtCurrentTeb()->RealClientId.UniqueThread); - LdrpCallInitRoutine(LdrEntry->EntryPoint, - LdrEntry->DllBase, - DLL_THREAD_ATTACH, - NULL); + DPRINT1("WARNING: Exception 0x%x during LdrpCallInitRoutine(DLL_THREAD_ATTACH) for %wZ\n", + _SEH2_GetExceptionCode(), &LdrEntry->BaseDllName); } + _SEH2_END; /* Deactivate the ActCtx */ RtlDeactivateActivationContextUnsafeFast(&ActCtx); @@ -600,8 +613,16 @@ LdrpInitializeThread(IN PCONTEXT Context) RtlActivateActivationContextUnsafeFast(&ActCtx, LdrpImageEntry->EntryPointActivationContext); - /* Do TLS callbacks */ - LdrpCallTlsInitializers(Peb->ImageBaseAddress, DLL_THREAD_ATTACH); + _SEH2_TRY + { + /* Do TLS callbacks */ + LdrpCallTlsInitializers(LdrpImageEntry, DLL_THREAD_ATTACH); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Do nothing */ + } + _SEH2_END; /* Deactivate the ActCtx */ RtlDeactivateActivationContextUnsafeFast(&ActCtx); @@ -643,7 +664,7 @@ LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL) if (Count > 16) { /* Allocate space for all the entries */ - LdrRootEntry = RtlAllocateHeap(RtlGetProcessHeap(), + LdrRootEntry = RtlAllocateHeap(LdrpHeap, 0, Count * sizeof(*LdrRootEntry)); if (!LdrRootEntry) return STATUS_NO_MEMORY; @@ -676,7 +697,7 @@ LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL) while (NextEntry != ListHead) { /* Get the Data Entry */ - LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList); + LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks); /* Check if we have a Root Entry */ if (LdrRootEntry) @@ -713,23 +734,28 @@ LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL) NextEntry = NextEntry->Flink; } + Status = STATUS_SUCCESS; + /* If we got a context, then we have to call Kernel32 for TS support */ if (Context) { /* Check if we have one */ - //if (Kernel32ProcessInitPostImportfunction) - //{ + if (Kernel32ProcessInitPostImportFunction) + { /* Call it */ - //Kernel32ProcessInitPostImportfunction(); - //} - + Status = Kernel32ProcessInitPostImportFunction(); + if (!NT_SUCCESS(Status)) + { + DPRINT1("LDR: LdrpRunInitializeRoutines - Failed running kernel32 post-import function, Status=0x%08lx\n", Status); + } + } /* Clear it */ - //Kernel32ProcessInitPostImportfunction = NULL; - //UNIMPLEMENTED; + Kernel32ProcessInitPostImportFunction = NULL; } /* No root entry? return */ - if (!LdrRootEntry) return STATUS_SUCCESS; + if (!LdrRootEntry) + return Status; /* Set the TLD TEB */ OldTldTeb = LdrpTopLevelDllBeingLoadedTeb; @@ -797,23 +823,33 @@ LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL) RtlActivateActivationContextUnsafeFast(&ActCtx, LdrEntry->EntryPointActivationContext); - /* Check if it has TLS */ - if (LdrEntry->TlsIndex && Context) + _SEH2_TRY { - /* Call TLS */ - LdrpCallTlsInitializers(LdrEntry->DllBase, DLL_PROCESS_ATTACH); - } + /* Check if it has TLS */ + if (LdrEntry->TlsIndex && Context) + { + /* Call TLS */ + LdrpCallTlsInitializers(LdrEntry, DLL_PROCESS_ATTACH); + } - /* Call the Entrypoint */ - if (ShowSnaps) + /* Call the Entrypoint */ + if (ShowSnaps) + { + DPRINT1("%wZ - Calling entry point at %p for DLL_PROCESS_ATTACH\n", + &LdrEntry->BaseDllName, EntryPoint); + } + DllStatus = LdrpCallInitRoutine(EntryPoint, + LdrEntry->DllBase, + DLL_PROCESS_ATTACH, + Context); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - DPRINT1("%wZ - Calling entry point at %p for DLL_PROCESS_ATTACH\n", - &LdrEntry->BaseDllName, EntryPoint); + DllStatus = FALSE; + DPRINT1("WARNING: Exception 0x%x during LdrpCallInitRoutine(DLL_PROCESS_ATTACH) for %wZ\n", + _SEH2_GetExceptionCode(), &LdrEntry->BaseDllName); } - DllStatus = LdrpCallInitRoutine(EntryPoint, - LdrEntry->DllBase, - DLL_PROCESS_ATTACH, - Context); + _SEH2_END; /* Deactivate the ActCtx */ RtlDeactivateActivationContextUnsafeFast(&ActCtx); @@ -841,8 +877,8 @@ LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL) NextEntry = NextEntry->Flink; while (NextEntry != ListHead) { - /* Get the Data Entrry */ - LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList); + /* Get the Data Entry */ + LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks); /* FIXME: Verify NX Compat */ // LdrpCheckNXCompatibility() @@ -863,8 +899,16 @@ LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL) RtlActivateActivationContextUnsafeFast(&ActCtx, LdrpImageEntry->EntryPointActivationContext); - /* Do TLS callbacks */ - LdrpCallTlsInitializers(Peb->ImageBaseAddress, DLL_PROCESS_ATTACH); + _SEH2_TRY + { + /* Do TLS callbacks */ + LdrpCallTlsInitializers(LdrpImageEntry, DLL_PROCESS_ATTACH); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Do nothing */ + } + _SEH2_END; /* Deactivate the ActCtx */ RtlDeactivateActivationContextUnsafeFast(&ActCtx); @@ -878,7 +922,7 @@ Quickie: if (LdrRootEntry != LocalArray) { /* Free the array */ - RtlFreeHeap(RtlGetProcessHeap(), 0, LdrRootEntry); + RtlFreeHeap(LdrpHeap, 0, LdrRootEntry); } /* Return to caller */ @@ -903,10 +947,12 @@ LdrShutdownProcess(VOID) if (LdrpShutdownInProgress) return STATUS_SUCCESS; /* Tell the Shim Engine */ - //if (ShimsEnabled) - //{ - /* FIXME */ - //} + if (g_ShimsEnabled) + { + VOID(NTAPI *SE_ProcessDying)(); + SE_ProcessDying = RtlDecodeSystemPointer(g_pfnSE_ProcessDying); + SE_ProcessDying(); + } /* Tell the world */ if (ShowSnaps) @@ -934,7 +980,7 @@ LdrShutdownProcess(VOID) while (NextEntry != ListHead) { /* Get the current entry */ - LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList); + LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks); NextEntry = NextEntry->Blink; /* Make sure it's not ourselves */ @@ -957,20 +1003,29 @@ LdrShutdownProcess(VOID) RtlActivateActivationContextUnsafeFast(&ActCtx, LdrEntry->EntryPointActivationContext); - /* Check if it has TLS */ - if (LdrEntry->TlsIndex) + _SEH2_TRY { - /* Call TLS */ - LdrpCallTlsInitializers(LdrEntry->DllBase, DLL_PROCESS_DETACH); - } + /* Check if it has TLS */ + if (LdrEntry->TlsIndex) + { + /* Call TLS */ + LdrpCallTlsInitializers(LdrEntry, DLL_PROCESS_DETACH); + } - /* Call the Entrypoint */ - DPRINT("%wZ - Calling entry point at %p for thread detaching\n", - &LdrEntry->BaseDllName, LdrEntry->EntryPoint); - LdrpCallInitRoutine(EntryPoint, - LdrEntry->DllBase, - DLL_PROCESS_DETACH, - (PVOID)1); + /* Call the Entrypoint */ + DPRINT("%wZ - Calling entry point at %p for thread detaching\n", + &LdrEntry->BaseDllName, LdrEntry->EntryPoint); + LdrpCallInitRoutine(EntryPoint, + LdrEntry->DllBase, + DLL_PROCESS_DETACH, + (PVOID)1); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + DPRINT1("WARNING: Exception 0x%x during LdrpCallInitRoutine(DLL_PROCESS_DETACH) for %wZ\n", + _SEH2_GetExceptionCode(), &LdrEntry->BaseDllName); + } + _SEH2_END; /* Deactivate the ActCtx */ RtlDeactivateActivationContextUnsafeFast(&ActCtx); @@ -990,8 +1045,16 @@ LdrShutdownProcess(VOID) RtlActivateActivationContextUnsafeFast(&ActCtx, LdrpImageEntry->EntryPointActivationContext); - /* Do TLS callbacks */ - LdrpCallTlsInitializers(Peb->ImageBaseAddress, DLL_PROCESS_DETACH); + _SEH2_TRY + { + /* Do TLS callbacks */ + LdrpCallTlsInitializers(LdrpImageEntry, DLL_PROCESS_DETACH); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Do nothing */ + } + _SEH2_END; /* Deactivate the ActCtx */ RtlDeactivateActivationContextUnsafeFast(&ActCtx); @@ -1039,7 +1102,7 @@ LdrShutdownThread(VOID) while (NextEntry != ListHead) { /* Get the current entry */ - LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList); + LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks); NextEntry = NextEntry->Blink; /* Make sure it's not ourselves */ @@ -1065,28 +1128,37 @@ LdrShutdownThread(VOID) RtlActivateActivationContextUnsafeFast(&ActCtx, LdrEntry->EntryPointActivationContext); - /* Check if it has TLS */ - if (LdrEntry->TlsIndex) + _SEH2_TRY { + /* Check if it has TLS */ + if (LdrEntry->TlsIndex) + { + /* Make sure we're not shutting down */ + if (!LdrpShutdownInProgress) + { + /* Call TLS */ + LdrpCallTlsInitializers(LdrEntry, DLL_THREAD_DETACH); + } + } + /* Make sure we're not shutting down */ if (!LdrpShutdownInProgress) { - /* Call TLS */ - LdrpCallTlsInitializers(LdrEntry->DllBase, DLL_THREAD_DETACH); + /* Call the Entrypoint */ + DPRINT("%wZ - Calling entry point at %p for thread detaching\n", + &LdrEntry->BaseDllName, LdrEntry->EntryPoint); + LdrpCallInitRoutine(EntryPoint, + LdrEntry->DllBase, + DLL_THREAD_DETACH, + NULL); } } - - /* Make sure we're not shutting down */ - if (!LdrpShutdownInProgress) + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - /* Call the Entrypoint */ - DPRINT("%wZ - Calling entry point at %p for thread detaching\n", - &LdrEntry->BaseDllName, LdrEntry->EntryPoint); - LdrpCallInitRoutine(EntryPoint, - LdrEntry->DllBase, - DLL_THREAD_DETACH, - NULL); + DPRINT1("WARNING: Exception 0x%x during LdrpCallInitRoutine(DLL_THREAD_DETACH) for %wZ\n", + _SEH2_GetExceptionCode(), &LdrEntry->BaseDllName); } + _SEH2_END; /* Deactivate the ActCtx */ RtlDeactivateActivationContextUnsafeFast(&ActCtx); @@ -1107,8 +1179,16 @@ LdrShutdownThread(VOID) RtlActivateActivationContextUnsafeFast(&ActCtx, LdrpImageEntry->EntryPointActivationContext); - /* Do TLS callbacks */ - LdrpCallTlsInitializers(Peb->ImageBaseAddress, DLL_THREAD_DETACH); + _SEH2_TRY + { + /* Do TLS callbacks */ + LdrpCallTlsInitializers(LdrpImageEntry, DLL_THREAD_DETACH); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Do nothing */ + } + _SEH2_END; /* Deactivate the ActCtx */ RtlDeactivateActivationContextUnsafeFast(&ActCtx); @@ -1128,8 +1208,29 @@ LdrShutdownThread(VOID) /* Check for FLS Data */ if (Teb->FlsData) { - /* FIXME */ - DPRINT1("We don't support FLS Data yet\n"); + /* Mimic BaseRundownFls */ + ULONG n, FlsHighIndex; + PRTL_FLS_DATA pFlsData; + PFLS_CALLBACK_FUNCTION lpCallback; + + pFlsData = Teb->FlsData; + + RtlAcquirePebLock(); + FlsHighIndex = NtCurrentPeb()->FlsHighIndex; + RemoveEntryList(&pFlsData->ListEntry); + RtlReleasePebLock(); + + for (n = 1; n <= FlsHighIndex; ++n) + { + lpCallback = NtCurrentPeb()->FlsCallback[n]; + if (lpCallback && pFlsData->Data[n]) + { + lpCallback(pFlsData->Data[n]); + } + } + + RtlFreeHeap(RtlGetProcessHeap(), 0, pFlsData); + Teb->FlsData = NULL; } /* Check for Fiber data */ @@ -1309,26 +1410,6 @@ LdrpFreeTls(VOID) TlsVector); } -NTSTATUS -NTAPI -LdrpInitializeApplicationVerifierPackage(PUNICODE_STRING ImagePathName, PPEB Peb, BOOLEAN SystemWide, BOOLEAN ReadAdvancedOptions) -{ - /* If global flags request DPH, perform some additional actions */ - if (Peb->NtGlobalFlag & FLG_HEAP_PAGE_ALLOCS) - { - // TODO: Read advanced DPH flags from the registry if requested - if (ReadAdvancedOptions) - { - UNIMPLEMENTED; - } - - /* Enable page heap */ - RtlpPageHeapEnabled = TRUE; - } - - return STATUS_SUCCESS; -} - NTSTATUS NTAPI LdrpInitializeExecutionOptions(PUNICODE_STRING ImagePathName, PPEB Peb, PHANDLE OptionsKey) @@ -1340,7 +1421,7 @@ LdrpInitializeExecutionOptions(PUNICODE_STRING ImagePathName, PPEB Peb, PHANDLE /* Return error if we were not provided a pointer where to save the options key handle */ if (!OptionsKey) return STATUS_INVALID_HANDLE; - /* Zero initialize the optinos key pointer */ + /* Zero initialize the options key pointer */ *OptionsKey = NULL; /* Open the options key */ @@ -1422,9 +1503,9 @@ LdrpInitializeExecutionOptions(PUNICODE_STRING ImagePathName, PPEB Peb, PHANDLE GlobalFlag = 0; /* Call AVRF if necessary */ - if (Peb->NtGlobalFlag & (FLG_POOL_ENABLE_TAIL_CHECK | FLG_HEAP_PAGE_ALLOCS)) + if (Peb->NtGlobalFlag & (FLG_APPLICATION_VERIFIER | FLG_HEAP_PAGE_ALLOCS)) { - Status = LdrpInitializeApplicationVerifierPackage(ImagePathName, Peb, TRUE, FALSE); + Status = LdrpInitializeApplicationVerifierPackage(KeyHandle, Peb, TRUE, FALSE); if (!NT_SUCCESS(Status)) { DPRINT1("AVRF: LdrpInitializeApplicationVerifierPackage failed with %08X\n", Status); @@ -1434,10 +1515,10 @@ LdrpInitializeExecutionOptions(PUNICODE_STRING ImagePathName, PPEB Peb, PHANDLE else { /* There are no image-specific options, so perform global initialization */ - if (Peb->NtGlobalFlag & (FLG_POOL_ENABLE_TAIL_CHECK | FLG_HEAP_PAGE_ALLOCS)) + if (Peb->NtGlobalFlag & (FLG_APPLICATION_VERIFIER | FLG_HEAP_PAGE_ALLOCS)) { /* Initialize app verifier package */ - Status = LdrpInitializeApplicationVerifierPackage(ImagePathName, Peb, TRUE, FALSE); + Status = LdrpInitializeApplicationVerifierPackage(KeyHandle, Peb, TRUE, FALSE); if (!NT_SUCCESS(Status)) { DPRINT1("AVRF: LdrpInitializeApplicationVerifierPackage failed with %08X\n", Status); @@ -1455,6 +1536,97 @@ LdrpValidateImageForMp(IN PLDR_DATA_TABLE_ENTRY LdrDataTableEntry) UNIMPLEMENTED; } +VOID +NTAPI +LdrpInitializeProcessCompat(PVOID* pOldShimData) +{ + static const GUID* GuidOrder[] = { &COMPAT_GUID_WIN10, &COMPAT_GUID_WIN81, &COMPAT_GUID_WIN8, + &COMPAT_GUID_WIN7, &COMPAT_GUID_VISTA }; + static const DWORD GuidVersions[] = { WINVER_WIN10, WINVER_WIN81, WINVER_WIN8, WINVER_WIN7, WINVER_VISTA }; + + ULONG Buffer[(sizeof(COMPATIBILITY_CONTEXT_ELEMENT) * 10 + sizeof(ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION)) / sizeof(ULONG)]; + ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION* ContextCompatInfo; + SIZE_T SizeRequired; + NTSTATUS Status; + DWORD n, cur; + ReactOS_ShimData* pShimData = *pOldShimData; + + C_ASSERT(RTL_NUMBER_OF(GuidOrder) == RTL_NUMBER_OF(GuidVersions)); + + if (pShimData) + { + if (pShimData->dwMagic != REACTOS_SHIMDATA_MAGIC || + pShimData->dwSize != sizeof(ReactOS_ShimData)) + { + DPRINT1("LdrpInitializeProcessCompat: Corrupt pShimData (0x%x, %u)\n", pShimData->dwMagic, pShimData->dwSize); + return; + } + if (pShimData->dwRosProcessCompatVersion) + { + DPRINT1("LdrpInitializeProcessCompat: ProcessCompatVersion already set to 0x%x\n", pShimData->dwRosProcessCompatVersion); + return; + } + } + + SizeRequired = sizeof(Buffer); + Status = RtlQueryInformationActivationContext(RTL_QUERY_ACTIVATION_CONTEXT_FLAG_NO_ADDREF, + NULL, + NULL, + CompatibilityInformationInActivationContext, + Buffer, + sizeof(Buffer), + &SizeRequired); + + if (!NT_SUCCESS(Status)) + { + DPRINT1("LdrpInitializeProcessCompat: Unable to query process actctx with status %x\n", Status); + return; + } + + ContextCompatInfo = (ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*)Buffer; + /* No Compatibility elements present, bail out */ + if (ContextCompatInfo->ElementCount == 0) + return; + + /* Search for known GUID's, starting from newest to oldest. */ + for (cur = 0; cur < RTL_NUMBER_OF(GuidOrder); ++cur) + { + for (n = 0; n < ContextCompatInfo->ElementCount; ++n) + { + if (ContextCompatInfo->Elements[n].Type == ACTCX_COMPATIBILITY_ELEMENT_TYPE_OS && + RtlCompareMemory(&ContextCompatInfo->Elements[n].Id, GuidOrder[cur], sizeof(GUID)) == sizeof(GUID)) + { + /* If this process did not need shim data before, allocate and store it */ + if (pShimData == NULL) + { + PPEB Peb = NtCurrentPeb(); + + ASSERT(Peb->pShimData == NULL); + pShimData = RtlAllocateHeap(Peb->ProcessHeap, HEAP_ZERO_MEMORY, sizeof(*pShimData)); + + if (!pShimData) + { + DPRINT1("LdrpInitializeProcessCompat: Unable to allocated %u bytes\n", sizeof(*pShimData)); + return; + } + + pShimData->dwSize = sizeof(*pShimData); + pShimData->dwMagic = REACTOS_SHIMDATA_MAGIC; + + Peb->pShimData = pShimData; + *pOldShimData = pShimData; + } + + /* Store the highest found version, and bail out. */ + pShimData->dwRosProcessCompatVersion = GuidVersions[cur]; + DPRINT1("LdrpInitializeProcessCompat: Found guid for winver 0x%x\n", GuidVersions[cur]); + return; + } + } + } +} + + NTSTATUS NTAPI LdrpInitializeProcess(IN PCONTEXT Context, @@ -1462,7 +1634,8 @@ LdrpInitializeProcess(IN PCONTEXT Context, { RTL_HEAP_PARAMETERS HeapParameters; ULONG ComSectionSize; - //ANSI_STRING FunctionName = RTL_CONSTANT_STRING("BaseQueryModuleData"); + ANSI_STRING BaseProcessInitPostImportName = RTL_CONSTANT_STRING("BaseProcessInitPostImport"); + ANSI_STRING BaseQueryModuleDataName = RTL_CONSTANT_STRING("BaseQueryModuleData"); PVOID OldShimData; OBJECT_ATTRIBUTES ObjectAttributes; //UNICODE_STRING LocalFileName, FullImageName; @@ -1525,7 +1698,7 @@ LdrpInitializeProcess(IN PCONTEXT Context, IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR, &ComSectionSize)) { - /* Remeber this for later */ + /* Remember this for later */ IsDotNetImage = TRUE; } @@ -1542,8 +1715,8 @@ LdrpInitializeProcess(IN PCONTEXT Context, /* Save the old Shim Data */ OldShimData = Peb->pShimData; - /* Clear it */ - Peb->pShimData = NULL; + /* ReactOS specific: do not clear it. (Windows starts doing the same in later versions) */ + //Peb->pShimData = NULL; /* Save the number of processors and CS Timeout */ LdrpNumberOfProcessors = Peb->NumberOfProcessors; @@ -1580,9 +1753,9 @@ LdrpInitializeProcess(IN PCONTEXT Context, &ConfigSize); /* Setup the Heap Parameters */ - RtlZeroMemory(&HeapParameters, sizeof(RTL_HEAP_PARAMETERS)); + RtlZeroMemory(&HeapParameters, sizeof(HeapParameters)); HeapFlags = HEAP_GROWABLE; - HeapParameters.Length = sizeof(RTL_HEAP_PARAMETERS); + HeapParameters.Length = sizeof(HeapParameters); /* Check if we have Configuration Data */ if ((LoadConfig) && (ConfigSize == sizeof(IMAGE_LOAD_CONFIG_DIRECTORY))) @@ -1635,6 +1808,7 @@ LdrpInitializeProcess(IN PCONTEXT Context, Peb->FlsBitmapBits, FLS_MAXIMUM_AVAILABLE); RtlSetBit(&FlsBitMap, 0); + InitializeListHead(&Peb->FlsListHead); /* Initialize TLS Bitmap */ RtlInitializeBitMap(&TlsBitMap, @@ -1702,8 +1876,15 @@ LdrpInitializeProcess(IN PCONTEXT Context, Status = RtlAllocateActivationContextStack(&Teb->ActivationContextStackPointer); if (!NT_SUCCESS(Status)) return Status; - // FIXME: Loader private heap is missing - //DPRINT1("Loader private heap is missing\n"); + RtlZeroMemory(&HeapParameters, sizeof(HeapParameters)); + HeapFlags = HEAP_GROWABLE | HEAP_CLASS_1; + HeapParameters.Length = sizeof(HeapParameters); + LdrpHeap = RtlCreateHeap(HeapFlags, 0, 0x10000, 0x6000, 0, &HeapParameters); + if (!LdrpHeap) + { + DPRINT1("Failed to create loader private heap\n"); + return STATUS_NO_MEMORY; + } /* Check for Debug Heap */ if (OptionsKey) @@ -1778,7 +1959,7 @@ LdrpInitializeProcess(IN PCONTEXT Context, /* Check if we failed */ if (!NT_SUCCESS(Status)) { - /* Aassume System32 */ + /* Assume System32 */ LdrpKnownDllObjectDirectory = NULL; RtlInitUnicodeString(&LdrpKnownDllPath, StringBuffer); LdrpKnownDllPath.Length -= sizeof(WCHAR); @@ -1846,24 +2027,24 @@ LdrpInitializeProcess(IN PCONTEXT Context, PebLdr.Initialized = TRUE; /* Allocate a data entry for the Image */ - LdrpImageEntry = NtLdrEntry = LdrpAllocateDataTableEntry(Peb->ImageBaseAddress); + LdrpImageEntry = LdrpAllocateDataTableEntry(Peb->ImageBaseAddress); /* Set it up */ - NtLdrEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(NtLdrEntry->DllBase); - NtLdrEntry->LoadCount = -1; - NtLdrEntry->EntryPointActivationContext = 0; - NtLdrEntry->FullDllName = ImageFileName; + LdrpImageEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(LdrpImageEntry->DllBase); + LdrpImageEntry->LoadCount = -1; + LdrpImageEntry->EntryPointActivationContext = 0; + LdrpImageEntry->FullDllName = ImageFileName; if (IsDotNetImage) - NtLdrEntry->Flags = LDRP_COR_IMAGE; + LdrpImageEntry->Flags = LDRP_COR_IMAGE; else - NtLdrEntry->Flags = 0; + LdrpImageEntry->Flags = 0; /* Check if the name is empty */ if (!ImageFileName.Buffer[0]) { /* Use the same Base name */ - NtLdrEntry->BaseDllName = NtLdrEntry->FullDllName; + LdrpImageEntry->BaseDllName = LdrpImageEntry->FullDllName; } else { @@ -1882,21 +2063,21 @@ LdrpInitializeProcess(IN PCONTEXT Context, if (!NtDllName) { /* Use the same Base name */ - NtLdrEntry->BaseDllName = NtLdrEntry->FullDllName; + LdrpImageEntry->BaseDllName = LdrpImageEntry->FullDllName; } else { /* Setup the name */ - NtLdrEntry->BaseDllName.Length = (USHORT)((ULONG_PTR)ImageFileName.Buffer + ImageFileName.Length - (ULONG_PTR)NtDllName); - NtLdrEntry->BaseDllName.MaximumLength = NtLdrEntry->BaseDllName.Length + sizeof(WCHAR); - NtLdrEntry->BaseDllName.Buffer = (PWSTR)((ULONG_PTR)ImageFileName.Buffer + - (ImageFileName.Length - NtLdrEntry->BaseDllName.Length)); + LdrpImageEntry->BaseDllName.Length = (USHORT)((ULONG_PTR)ImageFileName.Buffer + ImageFileName.Length - (ULONG_PTR)NtDllName); + LdrpImageEntry->BaseDllName.MaximumLength = LdrpImageEntry->BaseDllName.Length + sizeof(WCHAR); + LdrpImageEntry->BaseDllName.Buffer = (PWSTR)((ULONG_PTR)ImageFileName.Buffer + + (ImageFileName.Length - LdrpImageEntry->BaseDllName.Length)); } } /* Processing done, insert it */ - LdrpInsertMemoryTableEntry(NtLdrEntry); - NtLdrEntry->Flags |= LDRP_ENTRY_PROCESSED; + LdrpInsertMemoryTableEntry(LdrpImageEntry); + LdrpImageEntry->Flags |= LDRP_ENTRY_PROCESSED; /* Now add an entry for NTDLL */ NtLdrEntry = LdrpAllocateDataTableEntry(SystemArgument1); @@ -1929,11 +2110,14 @@ LdrpInitializeProcess(IN PCONTEXT Context, /* Link the Init Order List */ InsertHeadList(&Peb->Ldr->InInitializationOrderModuleList, - &LdrpNtDllDataTableEntry->InInitializationOrderModuleList); + &LdrpNtDllDataTableEntry->InInitializationOrderLinks); /* Initialize Wine's active context implementation for the current process */ actctx_init(); + /* ReactOS specific */ + LdrpInitializeProcessCompat(&OldShimData); + /* Set the current directory */ Status = RtlSetCurrentDirectory_U(&CurrentDirectory); if (!NT_SUCCESS(Status)) @@ -1959,10 +2143,15 @@ LdrpInitializeProcess(IN PCONTEXT Context, } /* Check if the Application Verifier was enabled */ - if (Peb->NtGlobalFlag & FLG_POOL_ENABLE_TAIL_CHECK) + if (Peb->NtGlobalFlag & FLG_APPLICATION_VERIFIER) { - /* FIXME */ - DPRINT1("We don't support Application Verifier yet\n"); + Status = AVrfInitializeVerifier(); + if (!NT_SUCCESS(Status)) + { + DPRINT1("LDR: AVrfInitializeVerifier failed (ntstatus 0x%x)\n", Status); + return Status; + } + } if (IsDotNetImage) @@ -1971,11 +2160,46 @@ LdrpInitializeProcess(IN PCONTEXT Context, DPRINT1("We don't support .NET applications yet\n"); } - /* FIXME: Load support for Terminal Services */ - if (NtHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) + if (NtHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI || + NtHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI) { - /* Load kernel32 and call BasePostImportInit... */ - DPRINT("Unimplemented codepath!\n"); + PVOID Kernel32BaseAddress; + PVOID FunctionAddress; + + Status = LdrLoadDll(NULL, NULL, &Kernel32String, &Kernel32BaseAddress); + + if (!NT_SUCCESS(Status)) + { + if (ShowSnaps) + DPRINT1("LDR: Unable to load %wZ, Status=0x%08lx\n", &Kernel32String, Status); + return Status; + } + + Status = LdrGetProcedureAddress(Kernel32BaseAddress, + &BaseProcessInitPostImportName, + 0, + &FunctionAddress); + + if (!NT_SUCCESS(Status)) + { + if (ShowSnaps) + DPRINT1("LDR: Unable to find post-import process init function, Status=0x%08lx\n", &Kernel32String, Status); + return Status; + } + Kernel32ProcessInitPostImportFunction = FunctionAddress; + + Status = LdrGetProcedureAddress(Kernel32BaseAddress, + &BaseQueryModuleDataName, + 0, + &FunctionAddress); + + if (!NT_SUCCESS(Status)) + { + if (ShowSnaps) + DPRINT1("LDR: Unable to find BaseQueryModuleData, Status=0x%08lx\n", &Kernel32String, Status); + return Status; + } + Kernel32BaseQueryModuleData = FunctionAddress; } /* Walk the IAT and load all the DLLs */ @@ -2073,13 +2297,46 @@ LdrpInitializeProcess(IN PCONTEXT Context, &ExecuteOptions, sizeof(ULONG)); + // FIXME: Should be done by Application Compatibility features, + // by reading the registry, etc... + // For now, this is the old code from ntdll!RtlGetVersion(). + RtlInitEmptyUnicodeString(&Peb->CSDVersion, NULL, 0); + if (((Peb->OSCSDVersion >> 8) & 0xFF) != 0) + { + WCHAR szCSDVersion[128]; + LONG i; + ULONG Length = ARRAYSIZE(szCSDVersion) - 1; + i = _snwprintf(szCSDVersion, Length, + L"Service Pack %d", + ((Peb->OSCSDVersion >> 8) & 0xFF)); + if (i < 0) + { + /* Null-terminate if it was overflowed */ + szCSDVersion[Length] = UNICODE_NULL; + } + + Length *= sizeof(WCHAR); + Peb->CSDVersion.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + Length + sizeof(UNICODE_NULL)); + if (Peb->CSDVersion.Buffer) + { + Peb->CSDVersion.Length = Length; + Peb->CSDVersion.MaximumLength = Length + sizeof(UNICODE_NULL); + + RtlCopyMemory(Peb->CSDVersion.Buffer, + szCSDVersion, + Peb->CSDVersion.MaximumLength); + Peb->CSDVersion.Buffer[Peb->CSDVersion.Length / sizeof(WCHAR)] = UNICODE_NULL; + } + } + /* Check if we had Shim Data */ if (OldShimData) { /* Load the Shim Engine */ Peb->AppCompatInfo = NULL; - //LdrpLoadShimEngine(OldShimData, ImagePathName, OldShimData); - DPRINT1("We do not support shims yet\n"); + LdrpLoadShimEngine(OldShimData, &ImagePathName, OldShimData); } else { @@ -2102,7 +2359,13 @@ LdrpInitializeProcess(IN PCONTEXT Context, return Status; } - /* FIXME: Unload the Shim Engine if it was loaded */ + /* Notify Shim Engine */ + if (g_ShimsEnabled) + { + VOID(NTAPI *SE_InstallAfterInit)(PUNICODE_STRING, PVOID); + SE_InstallAfterInit = RtlDecodeSystemPointer(g_pfnSE_InstallAfterInit); + SE_InstallAfterInit(&ImagePathName, OldShimData); + } /* Check if we have a user-defined Post Process Routine */ if (NT_SUCCESS(Status) && Peb->PostProcessInitRoutine) @@ -2152,6 +2415,11 @@ LdrpInit(PCONTEXT Context, NtCurrentTeb()->RealClientId.UniqueProcess, NtCurrentTeb()->RealClientId.UniqueThread); +#ifdef _WIN64 + /* Set the SList header usage */ + RtlpUse16ByteSLists = SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE128]; +#endif /* _WIN64 */ + /* Check if we have a deallocation stack */ if (!Teb->DeallocationStack) { @@ -2179,11 +2447,11 @@ LdrpInit(PCONTEXT Context, 1, 0) == 1) { - /* Set the timeout to 30 seconds */ + /* Set the timeout to 30 milliseconds */ Timeout.QuadPart = Int32x32To64(30, -10000); /* Make sure the status hasn't changed */ - while (!LdrpProcessInitialized) + while (LdrpProcessInitialized == 1) { /* Do the wait */ ZwDelayExecution(FALSE, &Timeout);