/* INCLUDES *****************************************************************/
#include <ntdll.h>
-#include <callback.h>
+#include <compat_undoc.h>
+#include <compatguid_undoc.h>
#define NDEBUG
#include <debug.h>
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;
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;
PVOID NtDllBase;
extern LARGE_INTEGER RtlpTimeout;
BOOLEAN RtlpTimeoutDisable;
+PVOID LdrpHeap;
LIST_ENTRY LdrpHashTable[LDR_HASH_TABLE_ENTRIES];
LIST_ENTRY LdrpDllNotificationList;
HANDLE LdrpKnownDllObjectDirectory;
//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
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);
VOID
NTAPI
-LdrpEnsureLoaderLockIsHeld()
+LdrpEnsureLoaderLockIsHeld(VOID)
{
// Ignored atm
}
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)
NTSTATUS Status;
PVOID EntryPoint;
- DPRINT("LdrpInitializeThread() called for %wZ (%lx/%lx)\n",
+ DPRINT("LdrpInitializeThread() called for %wZ (%p/%p)\n",
&LdrpImageEntry->BaseDllName,
NtCurrentTeb()->RealClientId.UniqueProcess,
NtCurrentTeb()->RealClientId.UniqueThread);
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)
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, %lx/%lx\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);
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);
PTEB OldTldTeb;
BOOLEAN DllStatus;
- DPRINT("LdrpRunInitializeRoutines() called for %wZ (%lx/%lx)\n",
+ DPRINT("LdrpRunInitializeRoutines() called for %wZ (%p/%p)\n",
&LdrpImageEntry->BaseDllName,
NtCurrentTeb()->RealClientId.UniqueProcess,
NtCurrentTeb()->RealClientId.UniqueThread);
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;
/* Show debug message */
if (ShowSnaps)
{
- DPRINT1("[%x,%x] LDR: Real INIT LIST for Process %wZ\n",
+ DPRINT1("[%p,%p] LDR: Real INIT LIST for Process %wZ\n",
NtCurrentTeb()->RealClientId.UniqueThread,
NtCurrentTeb()->RealClientId.UniqueProcess,
&Peb->ProcessParameters->ImagePathName);
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)
/* Display debug message */
if (ShowSnaps)
{
- DPRINT1("[%x,%x] LDR: %wZ init routine %p\n",
+ DPRINT1("[%p,%p] LDR: %wZ init routine %p\n",
NtCurrentTeb()->RealClientId.UniqueThread,
NtCurrentTeb()->RealClientId.UniqueProcess,
&LdrEntry->FullDllName,
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;
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);
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()
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);
if (LdrRootEntry != LocalArray)
{
/* Free the array */
- RtlFreeHeap(RtlGetProcessHeap(), 0, LdrRootEntry);
+ RtlFreeHeap(LdrpHeap, 0, LdrRootEntry);
}
/* Return to caller */
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)
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 */
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 %x 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);
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);
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 */
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 %x 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);
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);
/* 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 */
/* Show debug message */
if (ShowSnaps)
{
- DPRINT1("LDR: TlsVector %x Index %d = %x copied from %x to %x\n",
+ DPRINT1("LDR: TlsVector %p Index %lu = %p copied from %x to %p\n",
TlsVector,
TlsData->TlsDirectory.Characteristics,
&TlsVector[TlsData->TlsDirectory.Characteristics],
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)
/* 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 */
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);
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);
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,
{
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;
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR,
&ComSectionSize))
{
- /* Remeber this for later */
+ /* Remember this for later */
IsDotNetImage = TRUE;
}
/* 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;
&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)))
/* Start verbose debugging messages right now if they were requested */
if (ShowSnaps)
{
- DPRINT1("LDR: PID: 0x%x started - '%wZ'\n",
+ DPRINT1("LDR: PID: 0x%p started - '%wZ'\n",
Teb->ClientId.UniqueProcess,
&CommandLine);
}
Peb->FlsBitmapBits,
FLS_MAXIMUM_AVAILABLE);
RtlSetBit(&FlsBitMap, 0);
+ InitializeListHead(&Peb->FlsListHead);
/* Initialize TLS Bitmap */
RtlInitializeBitMap(&TlsBitMap,
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(&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)
/* Check if we failed */
if (!NT_SUCCESS(Status))
{
- /* Aassume System32 */
+ /* Assume System32 */
LdrpKnownDllObjectDirectory = NULL;
RtlInitUnicodeString(&LdrpKnownDllPath, StringBuffer);
LdrpKnownDllPath.Length -= sizeof(WCHAR);
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
{
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);
/* 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))
}
/* 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)
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 */
&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
{
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)
MEMORY_BASIC_INFORMATION MemoryBasicInfo;
PPEB Peb = NtCurrentPeb();
- DPRINT("LdrpInit() %lx/%lx\n",
+ DPRINT("LdrpInit() %p/%p\n",
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)
{
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);