xref: /reactos/dll/ntdll/ldr/ldrinit.c (revision 032b5aac)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS NT User-Mode Library
4  * FILE:            dll/ntdll/ldr/ldrinit.c
5  * PURPOSE:         User-Mode Process/Thread Startup
6  * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
7  *                  Aleksey Bragin (aleksey@reactos.org)
8  */
9 
10 /* INCLUDES *****************************************************************/
11 
12 #include <ntdll.h>
13 #include <compat_undoc.h>
14 #include <compatguid_undoc.h>
15 
16 #define NDEBUG
17 #include <debug.h>
18 
19 
20 /* GLOBALS *******************************************************************/
21 
22 HANDLE ImageExecOptionsKey;
23 HANDLE Wow64ExecOptionsKey;
24 UNICODE_STRING ImageExecOptionsString = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options");
25 UNICODE_STRING Wow64OptionsString = RTL_CONSTANT_STRING(L"");
26 UNICODE_STRING NtDllString = RTL_CONSTANT_STRING(L"ntdll.dll");
27 UNICODE_STRING Kernel32String = RTL_CONSTANT_STRING(L"kernel32.dll");
28 const UNICODE_STRING LdrpDotLocal = RTL_CONSTANT_STRING(L".Local");
29 
30 BOOLEAN LdrpInLdrInit;
31 LONG LdrpProcessInitialized;
32 BOOLEAN LdrpLoaderLockInit;
33 BOOLEAN LdrpLdrDatabaseIsSetup;
34 BOOLEAN LdrpShutdownInProgress;
35 HANDLE LdrpShutdownThreadId;
36 
37 BOOLEAN LdrpDllValidation;
38 
39 PLDR_DATA_TABLE_ENTRY LdrpImageEntry;
40 PUNICODE_STRING LdrpTopLevelDllBeingLoaded;
41 WCHAR StringBuffer[156];
42 extern PTEB LdrpTopLevelDllBeingLoadedTeb; // defined in rtlsupp.c!
43 PLDR_DATA_TABLE_ENTRY LdrpCurrentDllInitializer;
44 PLDR_DATA_TABLE_ENTRY LdrpNtDllDataTableEntry;
45 
46 static NTSTATUS (WINAPI *Kernel32ProcessInitPostImportFunction)(VOID);
47 static BOOL (WINAPI *Kernel32BaseQueryModuleData)(IN LPSTR ModuleName, IN LPSTR Unk1, IN PVOID Unk2, IN PVOID Unk3, IN PVOID Unk4);
48 
49 RTL_BITMAP TlsBitMap;
50 RTL_BITMAP TlsExpansionBitMap;
51 RTL_BITMAP FlsBitMap;
52 BOOLEAN LdrpImageHasTls;
53 LIST_ENTRY LdrpTlsList;
54 ULONG LdrpNumberOfTlsEntries;
55 ULONG LdrpNumberOfProcessors;
56 PVOID NtDllBase;
57 extern LARGE_INTEGER RtlpTimeout;
58 BOOLEAN RtlpTimeoutDisable;
59 PVOID LdrpHeap;
60 LIST_ENTRY LdrpHashTable[LDR_HASH_TABLE_ENTRIES];
61 LIST_ENTRY LdrpDllNotificationList;
62 HANDLE LdrpKnownDllObjectDirectory;
63 UNICODE_STRING LdrpKnownDllPath;
64 WCHAR LdrpKnownDllPathBuffer[128];
65 UNICODE_STRING LdrpDefaultPath;
66 
67 PEB_LDR_DATA PebLdr;
68 
69 RTL_CRITICAL_SECTION_DEBUG LdrpLoaderLockDebug;
70 RTL_CRITICAL_SECTION LdrpLoaderLock =
71 {
72     &LdrpLoaderLockDebug,
73     -1,
74     0,
75     0,
76     0,
77     0
78 };
79 RTL_CRITICAL_SECTION FastPebLock;
80 
81 BOOLEAN ShowSnaps;
82 
83 ULONG LdrpFatalHardErrorCount;
84 ULONG LdrpActiveUnloadCount;
85 
86 //extern LIST_ENTRY RtlCriticalSectionList;
87 
88 VOID NTAPI RtlpInitializeVectoredExceptionHandling(VOID);
89 VOID NTAPI RtlpInitDeferedCriticalSection(VOID);
90 VOID NTAPI RtlInitializeHeapManager(VOID);
91 
92 ULONG RtlpDisableHeapLookaside; // TODO: Move to heap.c
93 ULONG RtlpShutdownProcessFlags; // TODO: Use it
94 
95 NTSTATUS LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders, PVOID ImageBase);
96 void actctx_init(PVOID* pOldShimData);
97 extern BOOLEAN RtlpUse16ByteSLists;
98 
99 #ifdef _WIN64
100 #define DEFAULT_SECURITY_COOKIE 0x00002B992DDFA232ll
101 #else
102 #define DEFAULT_SECURITY_COOKIE 0xBB40E64E
103 #endif
104 
105 /* FUNCTIONS *****************************************************************/
106 
107 /*
108  * @implemented
109  */
110 NTSTATUS
111 NTAPI
112 LdrOpenImageFileOptionsKey(IN PUNICODE_STRING SubKey,
113                            IN BOOLEAN Wow64,
114                            OUT PHANDLE NewKeyHandle)
115 {
116     PHANDLE RootKeyLocation;
117     HANDLE RootKey;
118     UNICODE_STRING SubKeyString;
119     OBJECT_ATTRIBUTES ObjectAttributes;
120     NTSTATUS Status;
121     PWCHAR p1;
122 
123     /* Check which root key to open */
124     if (Wow64)
125         RootKeyLocation = &Wow64ExecOptionsKey;
126     else
127         RootKeyLocation = &ImageExecOptionsKey;
128 
129     /* Get the current key */
130     RootKey = *RootKeyLocation;
131 
132     /* Setup the object attributes */
133     InitializeObjectAttributes(&ObjectAttributes,
134                                Wow64 ?
135                                &Wow64OptionsString : &ImageExecOptionsString,
136                                OBJ_CASE_INSENSITIVE,
137                                NULL,
138                                NULL);
139 
140     /* Open the root key */
141     Status = ZwOpenKey(&RootKey, KEY_ENUMERATE_SUB_KEYS, &ObjectAttributes);
142     if (NT_SUCCESS(Status))
143     {
144         /* Write the key handle */
145         if (InterlockedCompareExchangePointer(RootKeyLocation, RootKey, NULL) != NULL)
146         {
147             /* Someone already opened it, use it instead */
148             NtClose(RootKey);
149             RootKey = *RootKeyLocation;
150         }
151 
152         /* Extract the name */
153         SubKeyString = *SubKey;
154         p1 = (PWCHAR)((ULONG_PTR)SubKeyString.Buffer + SubKeyString.Length);
155         while (SubKeyString.Length)
156         {
157             if (p1[-1] == L'\\') break;
158             p1--;
159             SubKeyString.Length -= sizeof(*p1);
160         }
161         SubKeyString.Buffer = p1;
162         SubKeyString.Length = SubKey->Length - SubKeyString.Length;
163 
164         /* Setup the object attributes */
165         InitializeObjectAttributes(&ObjectAttributes,
166                                    &SubKeyString,
167                                    OBJ_CASE_INSENSITIVE,
168                                    RootKey,
169                                    NULL);
170 
171         /* Open the setting key */
172         Status = ZwOpenKey((PHANDLE)NewKeyHandle, GENERIC_READ, &ObjectAttributes);
173     }
174 
175     /* Return to caller */
176     return Status;
177 }
178 
179 /*
180  * @implemented
181  */
182 NTSTATUS
183 NTAPI
184 LdrQueryImageFileKeyOption(IN HANDLE KeyHandle,
185                            IN PCWSTR ValueName,
186                            IN ULONG Type,
187                            OUT PVOID Buffer,
188                            IN ULONG BufferSize,
189                            OUT PULONG ReturnedLength OPTIONAL)
190 {
191     ULONG KeyInfo[256];
192     UNICODE_STRING ValueNameString, IntegerString;
193     ULONG KeyInfoSize, ResultSize;
194     PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)&KeyInfo;
195     BOOLEAN FreeHeap = FALSE;
196     NTSTATUS Status;
197 
198     /* Build a string for the value name */
199     Status = RtlInitUnicodeStringEx(&ValueNameString, ValueName);
200     if (!NT_SUCCESS(Status)) return Status;
201 
202     /* Query the value */
203     Status = ZwQueryValueKey(KeyHandle,
204                              &ValueNameString,
205                              KeyValuePartialInformation,
206                              KeyValueInformation,
207                              sizeof(KeyInfo),
208                              &ResultSize);
209     if (Status == STATUS_BUFFER_OVERFLOW)
210     {
211         /* Our local buffer wasn't enough, allocate one */
212         KeyInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
213                       KeyValueInformation->DataLength;
214         KeyValueInformation = RtlAllocateHeap(RtlGetProcessHeap(),
215                                               0,
216                                               KeyInfoSize);
217         if (KeyValueInformation != NULL)
218         {
219             /* Try again */
220             Status = ZwQueryValueKey(KeyHandle,
221                                      &ValueNameString,
222                                      KeyValuePartialInformation,
223                                      KeyValueInformation,
224                                      KeyInfoSize,
225                                      &ResultSize);
226             FreeHeap = TRUE;
227         }
228         else
229         {
230             /* Give up this time */
231             Status = STATUS_NO_MEMORY;
232         }
233     }
234 
235     /* Check for success */
236     if (NT_SUCCESS(Status))
237     {
238         /* Handle binary data */
239         if (KeyValueInformation->Type == REG_BINARY)
240         {
241             /* Check validity */
242             if ((Buffer) && (KeyValueInformation->DataLength <= BufferSize))
243             {
244                 /* Copy into buffer */
245                 RtlMoveMemory(Buffer,
246                               &KeyValueInformation->Data,
247                               KeyValueInformation->DataLength);
248             }
249             else
250             {
251                 Status = STATUS_BUFFER_OVERFLOW;
252             }
253 
254             /* Copy the result length */
255             if (ReturnedLength) *ReturnedLength = KeyValueInformation->DataLength;
256         }
257         else if (KeyValueInformation->Type == REG_DWORD)
258         {
259             /* Check for valid type */
260             if (KeyValueInformation->Type != Type)
261             {
262                 /* Error */
263                 Status = STATUS_OBJECT_TYPE_MISMATCH;
264             }
265             else
266             {
267                 /* Check validity */
268                 if ((Buffer) &&
269                     (BufferSize == sizeof(ULONG)) &&
270                     (KeyValueInformation->DataLength <= BufferSize))
271                 {
272                     /* Copy into buffer */
273                     RtlMoveMemory(Buffer,
274                                   &KeyValueInformation->Data,
275                                   KeyValueInformation->DataLength);
276                 }
277                 else
278                 {
279                     Status = STATUS_BUFFER_OVERFLOW;
280                 }
281 
282                 /* Copy the result length */
283                 if (ReturnedLength) *ReturnedLength = KeyValueInformation->DataLength;
284             }
285         }
286         else if (KeyValueInformation->Type != REG_SZ)
287         {
288             /* We got something weird */
289             Status = STATUS_OBJECT_TYPE_MISMATCH;
290         }
291         else
292         {
293             /*  String, check what you requested */
294             if (Type == REG_DWORD)
295             {
296                 /* Validate */
297                 if (BufferSize != sizeof(ULONG))
298                 {
299                     /* Invalid size */
300                     BufferSize = 0;
301                     Status = STATUS_INFO_LENGTH_MISMATCH;
302                 }
303                 else
304                 {
305                     /* OK, we know what you want... */
306                     IntegerString.Buffer = (PWSTR)KeyValueInformation->Data;
307                     IntegerString.Length = (USHORT)KeyValueInformation->DataLength -
308                                            sizeof(WCHAR);
309                     IntegerString.MaximumLength = (USHORT)KeyValueInformation->DataLength;
310                     Status = RtlUnicodeStringToInteger(&IntegerString, 0, (PULONG)Buffer);
311                 }
312             }
313             else
314             {
315                 /* Validate */
316                 if (KeyValueInformation->DataLength > BufferSize)
317                 {
318                     /* Invalid */
319                     Status = STATUS_BUFFER_OVERFLOW;
320                 }
321                 else
322                 {
323                     /* Set the size */
324                     BufferSize = KeyValueInformation->DataLength;
325                 }
326 
327                 /* Copy the string */
328                 RtlMoveMemory(Buffer, &KeyValueInformation->Data, BufferSize);
329             }
330 
331             /* Copy the result length */
332             if (ReturnedLength) *ReturnedLength = KeyValueInformation->DataLength;
333         }
334     }
335 
336     /* Check if buffer was in heap */
337     if (FreeHeap) RtlFreeHeap(RtlGetProcessHeap(), 0, KeyValueInformation);
338 
339     /* Return status */
340     return Status;
341 }
342 
343 /*
344  * @implemented
345  */
346 NTSTATUS
347 NTAPI
348 LdrQueryImageFileExecutionOptionsEx(IN PUNICODE_STRING SubKey,
349                                     IN PCWSTR ValueName,
350                                     IN ULONG Type,
351                                     OUT PVOID Buffer,
352                                     IN ULONG BufferSize,
353                                     OUT PULONG ReturnedLength OPTIONAL,
354                                     IN BOOLEAN Wow64)
355 {
356     NTSTATUS Status;
357     HANDLE KeyHandle;
358 
359     /* Open a handle to the key */
360     Status = LdrOpenImageFileOptionsKey(SubKey, Wow64, &KeyHandle);
361 
362     /* Check for success */
363     if (NT_SUCCESS(Status))
364     {
365         /* Query the data */
366         Status = LdrQueryImageFileKeyOption(KeyHandle,
367                                             ValueName,
368                                             Type,
369                                             Buffer,
370                                             BufferSize,
371                                             ReturnedLength);
372 
373         /* Close the key */
374         NtClose(KeyHandle);
375     }
376 
377     /* Return to caller */
378     return Status;
379 }
380 
381 /*
382  * @implemented
383  */
384 NTSTATUS
385 NTAPI
386 LdrQueryImageFileExecutionOptions(IN PUNICODE_STRING SubKey,
387                                   IN PCWSTR ValueName,
388                                   IN ULONG Type,
389                                   OUT PVOID Buffer,
390                                   IN ULONG BufferSize,
391                                   OUT PULONG ReturnedLength OPTIONAL)
392 {
393     /* Call the newer function */
394     return LdrQueryImageFileExecutionOptionsEx(SubKey,
395                                                ValueName,
396                                                Type,
397                                                Buffer,
398                                                BufferSize,
399                                                ReturnedLength,
400                                                FALSE);
401 }
402 
403 VOID
404 NTAPI
405 LdrpEnsureLoaderLockIsHeld(VOID)
406 {
407     // Ignored atm
408 }
409 
410 PVOID
411 NTAPI
412 LdrpFetchAddressOfSecurityCookie(PVOID BaseAddress, ULONG SizeOfImage)
413 {
414     PIMAGE_LOAD_CONFIG_DIRECTORY ConfigDir;
415     ULONG DirSize;
416     PVOID Cookie = NULL;
417 
418     /* Check NT header first */
419     if (!RtlImageNtHeader(BaseAddress)) return NULL;
420 
421     /* Get the pointer to the config directory */
422     ConfigDir = RtlImageDirectoryEntryToData(BaseAddress,
423                                              TRUE,
424                                              IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
425                                              &DirSize);
426 
427     /* Check for sanity */
428     if (!ConfigDir ||
429         (DirSize != 64 && ConfigDir->Size != DirSize) ||
430         (ConfigDir->Size < 0x48))
431         return NULL;
432 
433     /* Now get the cookie */
434     Cookie = (PVOID)ConfigDir->SecurityCookie;
435 
436     /* Check this cookie */
437     if ((PCHAR)Cookie <= (PCHAR)BaseAddress ||
438         (PCHAR)Cookie >= (PCHAR)BaseAddress + SizeOfImage)
439     {
440         Cookie = NULL;
441     }
442 
443     /* Return validated security cookie */
444     return Cookie;
445 }
446 
447 PVOID
448 NTAPI
449 LdrpInitSecurityCookie(PLDR_DATA_TABLE_ENTRY LdrEntry)
450 {
451     PULONG_PTR Cookie;
452     LARGE_INTEGER Counter;
453     ULONG_PTR NewCookie;
454 
455     /* Fetch address of the cookie */
456     Cookie = LdrpFetchAddressOfSecurityCookie(LdrEntry->DllBase, LdrEntry->SizeOfImage);
457 
458     if (Cookie)
459     {
460         /* Check if it's a default one */
461         if ((*Cookie == DEFAULT_SECURITY_COOKIE) ||
462             (*Cookie == 0xBB40))
463         {
464             /* Make up a cookie from a bunch of values which may uniquely represent
465                current moment of time, environment, etc */
466             NtQueryPerformanceCounter(&Counter, NULL);
467 
468             NewCookie = Counter.LowPart ^ Counter.HighPart;
469             NewCookie ^= (ULONG_PTR)NtCurrentTeb()->ClientId.UniqueProcess;
470             NewCookie ^= (ULONG_PTR)NtCurrentTeb()->ClientId.UniqueThread;
471 
472             /* Loop like it's done in KeQueryTickCount(). We don't want to call it directly. */
473             while (SharedUserData->SystemTime.High1Time != SharedUserData->SystemTime.High2Time)
474             {
475                 YieldProcessor();
476             };
477 
478             /* Calculate the milliseconds value and xor it to the cookie */
479             NewCookie ^= Int64ShrlMod32(UInt32x32To64(SharedUserData->TickCountMultiplier, SharedUserData->TickCount.LowPart), 24) +
480                 (SharedUserData->TickCountMultiplier * (SharedUserData->TickCount.High1Time << 8));
481 
482             /* Make the cookie 16bit if necessary */
483             if (*Cookie == 0xBB40) NewCookie &= 0xFFFF;
484 
485             /* If the result is 0 or the same as we got, just subtract one from the existing value
486                and that's it */
487             if ((NewCookie == 0) || (NewCookie == *Cookie))
488             {
489                 NewCookie = *Cookie - 1;
490             }
491 
492             /* Set the new cookie value */
493             *Cookie = NewCookie;
494         }
495     }
496 
497     return Cookie;
498 }
499 
500 VOID
501 NTAPI
502 LdrpInitializeThread(IN PCONTEXT Context)
503 {
504     PPEB Peb = NtCurrentPeb();
505     PLDR_DATA_TABLE_ENTRY LdrEntry;
506     PLIST_ENTRY NextEntry, ListHead;
507     RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx;
508     NTSTATUS Status;
509     PVOID EntryPoint;
510 
511     DPRINT("LdrpInitializeThread() called for %wZ (%p/%p)\n",
512             &LdrpImageEntry->BaseDllName,
513             NtCurrentTeb()->RealClientId.UniqueProcess,
514             NtCurrentTeb()->RealClientId.UniqueThread);
515 
516     /* Allocate an Activation Context Stack */
517     DPRINT("ActivationContextStack %p\n", NtCurrentTeb()->ActivationContextStackPointer);
518     Status = RtlAllocateActivationContextStack(&NtCurrentTeb()->ActivationContextStackPointer);
519     if (!NT_SUCCESS(Status))
520     {
521         DPRINT1("Warning: Unable to allocate ActivationContextStack\n");
522     }
523 
524     /* Make sure we are not shutting down */
525     if (LdrpShutdownInProgress) return;
526 
527     /* Allocate TLS */
528     LdrpAllocateTls();
529 
530     /* Start at the beginning */
531     ListHead = &Peb->Ldr->InMemoryOrderModuleList;
532     NextEntry = ListHead->Flink;
533     while (NextEntry != ListHead)
534     {
535         /* Get the current entry */
536         LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
537 
538         /* Make sure it's not ourselves */
539         if (Peb->ImageBaseAddress != LdrEntry->DllBase)
540         {
541             /* Check if we should call */
542             if (!(LdrEntry->Flags & LDRP_DONT_CALL_FOR_THREADS))
543             {
544                 /* Get the entrypoint */
545                 EntryPoint = LdrEntry->EntryPoint;
546 
547                 /* Check if we are ready to call it */
548                 if ((EntryPoint) &&
549                     (LdrEntry->Flags & LDRP_PROCESS_ATTACH_CALLED) &&
550                     (LdrEntry->Flags & LDRP_IMAGE_DLL))
551                 {
552                     /* Set up the Act Ctx */
553                     ActCtx.Size = sizeof(ActCtx);
554                     ActCtx.Format = 1;
555                     RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
556 
557                     /* Activate the ActCtx */
558                     RtlActivateActivationContextUnsafeFast(&ActCtx,
559                                                            LdrEntry->EntryPointActivationContext);
560 
561                     _SEH2_TRY
562                     {
563                         /* Check if it has TLS */
564                         if (LdrEntry->TlsIndex)
565                         {
566                             /* Make sure we're not shutting down */
567                             if (!LdrpShutdownInProgress)
568                             {
569                                 /* Call TLS */
570                                 LdrpCallTlsInitializers(LdrEntry, DLL_THREAD_ATTACH);
571                             }
572                         }
573 
574                         /* Make sure we're not shutting down */
575                         if (!LdrpShutdownInProgress)
576                         {
577                             /* Call the Entrypoint */
578                             DPRINT("%wZ - Calling entry point at %p for thread attaching, %p/%p\n",
579                                    &LdrEntry->BaseDllName, LdrEntry->EntryPoint,
580                                    NtCurrentTeb()->RealClientId.UniqueProcess,
581                                    NtCurrentTeb()->RealClientId.UniqueThread);
582                             LdrpCallInitRoutine(LdrEntry->EntryPoint,
583                                                 LdrEntry->DllBase,
584                                                 DLL_THREAD_ATTACH,
585                                                 NULL);
586                         }
587                     }
588                     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
589                     {
590                         DPRINT1("WARNING: Exception 0x%x during LdrpCallInitRoutine(DLL_THREAD_ATTACH) for %wZ\n",
591                                 _SEH2_GetExceptionCode(), &LdrEntry->BaseDllName);
592                     }
593                     _SEH2_END;
594 
595                     /* Deactivate the ActCtx */
596                     RtlDeactivateActivationContextUnsafeFast(&ActCtx);
597                 }
598             }
599         }
600 
601         /* Next entry */
602         NextEntry = NextEntry->Flink;
603     }
604 
605     /* Check for TLS */
606     if (LdrpImageHasTls && !LdrpShutdownInProgress)
607     {
608         /* Set up the Act Ctx */
609         ActCtx.Size = sizeof(ActCtx);
610         ActCtx.Format = 1;
611         RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
612 
613         /* Activate the ActCtx */
614         RtlActivateActivationContextUnsafeFast(&ActCtx,
615                                                LdrpImageEntry->EntryPointActivationContext);
616 
617         _SEH2_TRY
618         {
619             /* Do TLS callbacks */
620             LdrpCallTlsInitializers(LdrpImageEntry, DLL_THREAD_ATTACH);
621         }
622         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
623         {
624             /* Do nothing */
625         }
626         _SEH2_END;
627 
628         /* Deactivate the ActCtx */
629         RtlDeactivateActivationContextUnsafeFast(&ActCtx);
630     }
631 
632     DPRINT("LdrpInitializeThread() done\n");
633 }
634 
635 NTSTATUS
636 NTAPI
637 LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL)
638 {
639     PLDR_DATA_TABLE_ENTRY LocalArray[16];
640     PLIST_ENTRY ListHead;
641     PLIST_ENTRY NextEntry;
642     PLDR_DATA_TABLE_ENTRY LdrEntry, *LdrRootEntry, OldInitializer;
643     PVOID EntryPoint;
644     ULONG Count, i;
645     //ULONG BreakOnInit;
646     NTSTATUS Status = STATUS_SUCCESS;
647     PPEB Peb = NtCurrentPeb();
648     RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx;
649     ULONG BreakOnDllLoad;
650     PTEB OldTldTeb;
651     BOOLEAN DllStatus;
652 
653     DPRINT("LdrpRunInitializeRoutines() called for %wZ (%p/%p)\n",
654         &LdrpImageEntry->BaseDllName,
655         NtCurrentTeb()->RealClientId.UniqueProcess,
656         NtCurrentTeb()->RealClientId.UniqueThread);
657 
658     /* Check the Loader Lock */
659     LdrpEnsureLoaderLockIsHeld();
660 
661      /* Get the number of entries to call */
662     if ((Count = LdrpClearLoadInProgress()))
663     {
664         /* Check if we can use our local buffer */
665         if (Count > 16)
666         {
667             /* Allocate space for all the entries */
668             LdrRootEntry = RtlAllocateHeap(LdrpHeap,
669                                            0,
670                                            Count * sizeof(*LdrRootEntry));
671             if (!LdrRootEntry) return STATUS_NO_MEMORY;
672         }
673         else
674         {
675             /* Use our local array */
676             LdrRootEntry = LocalArray;
677         }
678     }
679     else
680     {
681         /* Don't need one */
682         LdrRootEntry = NULL;
683     }
684 
685     /* Show debug message */
686     if (ShowSnaps)
687     {
688         DPRINT1("[%p,%p] LDR: Real INIT LIST for Process %wZ\n",
689                 NtCurrentTeb()->RealClientId.UniqueThread,
690                 NtCurrentTeb()->RealClientId.UniqueProcess,
691                 &Peb->ProcessParameters->ImagePathName);
692     }
693 
694     /* Loop in order */
695     ListHead = &Peb->Ldr->InInitializationOrderModuleList;
696     NextEntry = ListHead->Flink;
697     i = 0;
698     while (NextEntry != ListHead)
699     {
700         /* Get the Data Entry */
701         LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);
702 
703         /* Check if we have a Root Entry */
704         if (LdrRootEntry)
705         {
706             /* Check flags */
707             if (!(LdrEntry->Flags & LDRP_ENTRY_PROCESSED))
708             {
709                 /* Setup the Cookie for the DLL */
710                 LdrpInitSecurityCookie(LdrEntry);
711 
712                 /* Check for valid entrypoint */
713                 if (LdrEntry->EntryPoint)
714                 {
715                     /* Write in array */
716                     ASSERT(i < Count);
717                     LdrRootEntry[i] = LdrEntry;
718 
719                     /* Display debug message */
720                     if (ShowSnaps)
721                     {
722                         DPRINT1("[%p,%p] LDR: %wZ init routine %p\n",
723                                 NtCurrentTeb()->RealClientId.UniqueThread,
724                                 NtCurrentTeb()->RealClientId.UniqueProcess,
725                                 &LdrEntry->FullDllName,
726                                 LdrEntry->EntryPoint);
727                     }
728                     i++;
729                 }
730             }
731         }
732 
733         /* Set the flag */
734         LdrEntry->Flags |= LDRP_ENTRY_PROCESSED;
735         NextEntry = NextEntry->Flink;
736     }
737 
738     Status = STATUS_SUCCESS;
739 
740     /* If we got a context, then we have to call Kernel32 for TS support */
741     if (Context)
742     {
743         /* Check if we have one */
744         if (Kernel32ProcessInitPostImportFunction)
745         {
746             /* Call it */
747             Status = Kernel32ProcessInitPostImportFunction();
748             if (!NT_SUCCESS(Status))
749             {
750                 DPRINT1("LDR: LdrpRunInitializeRoutines - Failed running kernel32 post-import function, Status=0x%08lx\n", Status);
751             }
752         }
753         /* Clear it */
754         Kernel32ProcessInitPostImportFunction = NULL;
755     }
756 
757     /* No root entry? return */
758     if (!LdrRootEntry)
759         return Status;
760 
761     /* Set the TLD TEB */
762     OldTldTeb = LdrpTopLevelDllBeingLoadedTeb;
763     LdrpTopLevelDllBeingLoadedTeb = NtCurrentTeb();
764 
765     /* Loop */
766     i = 0;
767     while (i < Count)
768     {
769         /* Get an entry */
770         LdrEntry = LdrRootEntry[i];
771 
772         /* FIXME: Verify NX Compat */
773 
774         /* Move to next entry */
775         i++;
776 
777         /* Get its entrypoint */
778         EntryPoint = LdrEntry->EntryPoint;
779 
780         /* Are we being debugged? */
781         BreakOnDllLoad = 0;
782         if (Peb->BeingDebugged || Peb->ReadImageFileExecOptions)
783         {
784             /* Check if we should break on load */
785             Status = LdrQueryImageFileExecutionOptions(&LdrEntry->BaseDllName,
786                                                        L"BreakOnDllLoad",
787                                                        REG_DWORD,
788                                                        &BreakOnDllLoad,
789                                                        sizeof(ULONG),
790                                                        NULL);
791             if (!NT_SUCCESS(Status)) BreakOnDllLoad = 0;
792 
793             /* Reset status back to STATUS_SUCCESS */
794             Status = STATUS_SUCCESS;
795         }
796 
797         /* Break if aksed */
798         if (BreakOnDllLoad)
799         {
800             /* Check if we should show a message */
801             if (ShowSnaps)
802             {
803                 DPRINT1("LDR: %wZ loaded.", &LdrEntry->BaseDllName);
804                 DPRINT1(" - About to call init routine at %p\n", EntryPoint);
805             }
806 
807             /* Break in debugger */
808             DbgBreakPoint();
809         }
810 
811         /* Make sure we have an entrypoint */
812         if (EntryPoint)
813         {
814             /* Save the old Dll Initializer and write the current one */
815             OldInitializer = LdrpCurrentDllInitializer;
816             LdrpCurrentDllInitializer = LdrEntry;
817 
818             /* Set up the Act Ctx */
819             ActCtx.Size = sizeof(ActCtx);
820             ActCtx.Format = 1;
821             RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
822 
823             /* Activate the ActCtx */
824             RtlActivateActivationContextUnsafeFast(&ActCtx,
825                                                    LdrEntry->EntryPointActivationContext);
826 
827             _SEH2_TRY
828             {
829                 /* Check if it has TLS */
830                 if (LdrEntry->TlsIndex && Context)
831                 {
832                     /* Call TLS */
833                     LdrpCallTlsInitializers(LdrEntry, DLL_PROCESS_ATTACH);
834                 }
835 
836                 /* Call the Entrypoint */
837                 if (ShowSnaps)
838                 {
839                     DPRINT1("%wZ - Calling entry point at %p for DLL_PROCESS_ATTACH\n",
840                             &LdrEntry->BaseDllName, EntryPoint);
841                 }
842                 DllStatus = LdrpCallInitRoutine(EntryPoint,
843                                                 LdrEntry->DllBase,
844                                                 DLL_PROCESS_ATTACH,
845                                                 Context);
846             }
847             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
848             {
849                 DllStatus = FALSE;
850                 DPRINT1("WARNING: Exception 0x%x during LdrpCallInitRoutine(DLL_PROCESS_ATTACH) for %wZ\n",
851                         _SEH2_GetExceptionCode(), &LdrEntry->BaseDllName);
852             }
853             _SEH2_END;
854 
855             /* Deactivate the ActCtx */
856             RtlDeactivateActivationContextUnsafeFast(&ActCtx);
857 
858             /* Save the Current DLL Initializer */
859             LdrpCurrentDllInitializer = OldInitializer;
860 
861             /* Mark the entry as processed */
862             LdrEntry->Flags |= LDRP_PROCESS_ATTACH_CALLED;
863 
864             /* Fail if DLL init failed */
865             if (!DllStatus)
866             {
867                 DPRINT1("LDR: DLL_PROCESS_ATTACH for dll \"%wZ\" (InitRoutine: %p) failed\n",
868                     &LdrEntry->BaseDllName, EntryPoint);
869 
870                 Status = STATUS_DLL_INIT_FAILED;
871                 goto Quickie;
872             }
873         }
874     }
875 
876     /* Loop in order */
877     ListHead = &Peb->Ldr->InInitializationOrderModuleList;
878     NextEntry = NextEntry->Flink;
879     while (NextEntry != ListHead)
880     {
881         /* Get the Data Entry */
882         LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);
883 
884         /* FIXME: Verify NX Compat */
885         // LdrpCheckNXCompatibility()
886 
887         /* Next entry */
888         NextEntry = NextEntry->Flink;
889     }
890 
891     /* Check for TLS */
892     if (LdrpImageHasTls && Context)
893     {
894         /* Set up the Act Ctx */
895         ActCtx.Size = sizeof(ActCtx);
896         ActCtx.Format = 1;
897         RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
898 
899         /* Activate the ActCtx */
900         RtlActivateActivationContextUnsafeFast(&ActCtx,
901                                                LdrpImageEntry->EntryPointActivationContext);
902 
903         _SEH2_TRY
904         {
905             /* Do TLS callbacks */
906             LdrpCallTlsInitializers(LdrpImageEntry, DLL_PROCESS_ATTACH);
907         }
908         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
909         {
910             /* Do nothing */
911         }
912         _SEH2_END;
913 
914         /* Deactivate the ActCtx */
915         RtlDeactivateActivationContextUnsafeFast(&ActCtx);
916     }
917 
918 Quickie:
919     /* Restore old TEB */
920     LdrpTopLevelDllBeingLoadedTeb = OldTldTeb;
921 
922     /* Check if the array is in the heap */
923     if (LdrRootEntry != LocalArray)
924     {
925         /* Free the array */
926         RtlFreeHeap(LdrpHeap, 0, LdrRootEntry);
927     }
928 
929     /* Return to caller */
930     DPRINT("LdrpRunInitializeRoutines() done\n");
931     return Status;
932 }
933 
934 /*
935  * @implemented
936  */
937 NTSTATUS
938 NTAPI
939 LdrShutdownProcess(VOID)
940 {
941     PPEB Peb = NtCurrentPeb();
942     PLDR_DATA_TABLE_ENTRY LdrEntry;
943     PLIST_ENTRY NextEntry, ListHead;
944     RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx;
945     PVOID EntryPoint;
946 
947     DPRINT("LdrShutdownProcess() called for %wZ\n", &LdrpImageEntry->BaseDllName);
948     if (LdrpShutdownInProgress) return STATUS_SUCCESS;
949 
950     /* Tell the Shim Engine */
951     if (g_ShimsEnabled)
952     {
953         VOID(NTAPI *SE_ProcessDying)();
954         SE_ProcessDying = RtlDecodeSystemPointer(g_pfnSE_ProcessDying);
955         SE_ProcessDying();
956     }
957 
958     /* Tell the world */
959     if (ShowSnaps)
960     {
961         DPRINT1("\n");
962     }
963 
964     /* Set the shutdown variables */
965     LdrpShutdownThreadId = NtCurrentTeb()->RealClientId.UniqueThread;
966     LdrpShutdownInProgress = TRUE;
967 
968     /* Enter the Loader Lock */
969     RtlEnterCriticalSection(&LdrpLoaderLock);
970 
971     /* Cleanup trace logging data (Etw) */
972     if (SharedUserData->TraceLogging)
973     {
974         /* FIXME */
975         DPRINT1("We don't support Etw yet.\n");
976     }
977 
978     /* Start at the end */
979     ListHead = &Peb->Ldr->InInitializationOrderModuleList;
980     NextEntry = ListHead->Blink;
981     while (NextEntry != ListHead)
982     {
983         /* Get the current entry */
984         LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);
985         NextEntry = NextEntry->Blink;
986 
987         /* Make sure it's not ourselves */
988         if (Peb->ImageBaseAddress != LdrEntry->DllBase)
989         {
990             /* Get the entrypoint */
991             EntryPoint = LdrEntry->EntryPoint;
992 
993             /* Check if we are ready to call it */
994             if (EntryPoint &&
995                 (LdrEntry->Flags & LDRP_PROCESS_ATTACH_CALLED) &&
996                 LdrEntry->Flags)
997             {
998                 /* Set up the Act Ctx */
999                 ActCtx.Size = sizeof(ActCtx);
1000                 ActCtx.Format = 1;
1001                 RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
1002 
1003                 /* Activate the ActCtx */
1004                 RtlActivateActivationContextUnsafeFast(&ActCtx,
1005                                                        LdrEntry->EntryPointActivationContext);
1006 
1007                 _SEH2_TRY
1008                 {
1009                     /* Check if it has TLS */
1010                     if (LdrEntry->TlsIndex)
1011                     {
1012                         /* Call TLS */
1013                         LdrpCallTlsInitializers(LdrEntry, DLL_PROCESS_DETACH);
1014                     }
1015 
1016                     /* Call the Entrypoint */
1017                     DPRINT("%wZ - Calling entry point at %p for thread detaching\n",
1018                            &LdrEntry->BaseDllName, LdrEntry->EntryPoint);
1019                     LdrpCallInitRoutine(EntryPoint,
1020                                         LdrEntry->DllBase,
1021                                         DLL_PROCESS_DETACH,
1022                                         (PVOID)1);
1023                 }
1024                 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1025                 {
1026                     DPRINT1("WARNING: Exception 0x%x during LdrpCallInitRoutine(DLL_PROCESS_DETACH) for %wZ\n",
1027                             _SEH2_GetExceptionCode(), &LdrEntry->BaseDllName);
1028                 }
1029                 _SEH2_END;
1030 
1031                 /* Deactivate the ActCtx */
1032                 RtlDeactivateActivationContextUnsafeFast(&ActCtx);
1033             }
1034         }
1035     }
1036 
1037     /* Check for TLS */
1038     if (LdrpImageHasTls)
1039     {
1040         /* Set up the Act Ctx */
1041         ActCtx.Size = sizeof(ActCtx);
1042         ActCtx.Format = 1;
1043         RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
1044 
1045         /* Activate the ActCtx */
1046         RtlActivateActivationContextUnsafeFast(&ActCtx,
1047                                                LdrpImageEntry->EntryPointActivationContext);
1048 
1049         _SEH2_TRY
1050         {
1051             /* Do TLS callbacks */
1052             LdrpCallTlsInitializers(LdrpImageEntry, DLL_PROCESS_DETACH);
1053         }
1054         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1055         {
1056             /* Do nothing */
1057         }
1058         _SEH2_END;
1059 
1060         /* Deactivate the ActCtx */
1061         RtlDeactivateActivationContextUnsafeFast(&ActCtx);
1062     }
1063 
1064     /* FIXME: Do Heap detection and Etw final shutdown */
1065 
1066     /* Release the lock */
1067     RtlLeaveCriticalSection(&LdrpLoaderLock);
1068     DPRINT("LdrpShutdownProcess() done\n");
1069 
1070     return STATUS_SUCCESS;
1071 }
1072 
1073 /*
1074  * @implemented
1075  */
1076 NTSTATUS
1077 NTAPI
1078 LdrShutdownThread(VOID)
1079 {
1080     PPEB Peb = NtCurrentPeb();
1081     PTEB Teb = NtCurrentTeb();
1082     PLDR_DATA_TABLE_ENTRY LdrEntry;
1083     PLIST_ENTRY NextEntry, ListHead;
1084     RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx;
1085     PVOID EntryPoint;
1086 
1087     DPRINT("LdrShutdownThread() called for %wZ\n",
1088             &LdrpImageEntry->BaseDllName);
1089 
1090     /* Cleanup trace logging data (Etw) */
1091     if (SharedUserData->TraceLogging)
1092     {
1093         /* FIXME */
1094         DPRINT1("We don't support Etw yet.\n");
1095     }
1096 
1097     /* Get the Ldr Lock */
1098     RtlEnterCriticalSection(&LdrpLoaderLock);
1099 
1100     /* Start at the end */
1101     ListHead = &Peb->Ldr->InInitializationOrderModuleList;
1102     NextEntry = ListHead->Blink;
1103     while (NextEntry != ListHead)
1104     {
1105         /* Get the current entry */
1106         LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);
1107         NextEntry = NextEntry->Blink;
1108 
1109         /* Make sure it's not ourselves */
1110         if (Peb->ImageBaseAddress != LdrEntry->DllBase)
1111         {
1112             /* Check if we should call */
1113             if (!(LdrEntry->Flags & LDRP_DONT_CALL_FOR_THREADS) &&
1114                 (LdrEntry->Flags & LDRP_PROCESS_ATTACH_CALLED) &&
1115                 (LdrEntry->Flags & LDRP_IMAGE_DLL))
1116             {
1117                 /* Get the entrypoint */
1118                 EntryPoint = LdrEntry->EntryPoint;
1119 
1120                 /* Check if we are ready to call it */
1121                 if (EntryPoint)
1122                 {
1123                     /* Set up the Act Ctx */
1124                     ActCtx.Size = sizeof(ActCtx);
1125                     ActCtx.Format = 1;
1126                     RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
1127 
1128                     /* Activate the ActCtx */
1129                     RtlActivateActivationContextUnsafeFast(&ActCtx,
1130                                                            LdrEntry->EntryPointActivationContext);
1131 
1132                     _SEH2_TRY
1133                     {
1134                         /* Check if it has TLS */
1135                         if (LdrEntry->TlsIndex)
1136                         {
1137                             /* Make sure we're not shutting down */
1138                             if (!LdrpShutdownInProgress)
1139                             {
1140                                 /* Call TLS */
1141                                 LdrpCallTlsInitializers(LdrEntry, DLL_THREAD_DETACH);
1142                             }
1143                         }
1144 
1145                         /* Make sure we're not shutting down */
1146                         if (!LdrpShutdownInProgress)
1147                         {
1148                             /* Call the Entrypoint */
1149                             DPRINT("%wZ - Calling entry point at %p for thread detaching\n",
1150                                    &LdrEntry->BaseDllName, LdrEntry->EntryPoint);
1151                             LdrpCallInitRoutine(EntryPoint,
1152                                                 LdrEntry->DllBase,
1153                                                 DLL_THREAD_DETACH,
1154                                                 NULL);
1155                         }
1156                     }
1157                     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1158                     {
1159                         DPRINT1("WARNING: Exception 0x%x during LdrpCallInitRoutine(DLL_THREAD_DETACH) for %wZ\n",
1160                                 _SEH2_GetExceptionCode(), &LdrEntry->BaseDllName);
1161                     }
1162                     _SEH2_END;
1163 
1164                     /* Deactivate the ActCtx */
1165                     RtlDeactivateActivationContextUnsafeFast(&ActCtx);
1166                 }
1167             }
1168         }
1169     }
1170 
1171     /* Check for TLS */
1172     if (LdrpImageHasTls)
1173     {
1174         /* Set up the Act Ctx */
1175         ActCtx.Size = sizeof(ActCtx);
1176         ActCtx.Format = 1;
1177         RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
1178 
1179         /* Activate the ActCtx */
1180         RtlActivateActivationContextUnsafeFast(&ActCtx,
1181                                                LdrpImageEntry->EntryPointActivationContext);
1182 
1183         _SEH2_TRY
1184         {
1185             /* Do TLS callbacks */
1186             LdrpCallTlsInitializers(LdrpImageEntry, DLL_THREAD_DETACH);
1187         }
1188         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1189         {
1190             /* Do nothing */
1191         }
1192         _SEH2_END;
1193 
1194         /* Deactivate the ActCtx */
1195         RtlDeactivateActivationContextUnsafeFast(&ActCtx);
1196     }
1197 
1198     /* Free TLS */
1199     LdrpFreeTls();
1200     RtlLeaveCriticalSection(&LdrpLoaderLock);
1201 
1202     /* Check for expansion slots */
1203     if (Teb->TlsExpansionSlots)
1204     {
1205         /* Free expansion slots */
1206         RtlFreeHeap(RtlGetProcessHeap(), 0, Teb->TlsExpansionSlots);
1207     }
1208 
1209     /* Check for FLS Data */
1210     if (Teb->FlsData)
1211     {
1212         /* Mimic BaseRundownFls */
1213         ULONG n, FlsHighIndex;
1214         PRTL_FLS_DATA pFlsData;
1215         PFLS_CALLBACK_FUNCTION lpCallback;
1216 
1217         pFlsData = Teb->FlsData;
1218 
1219         RtlAcquirePebLock();
1220         FlsHighIndex = NtCurrentPeb()->FlsHighIndex;
1221         RemoveEntryList(&pFlsData->ListEntry);
1222         RtlReleasePebLock();
1223 
1224         for (n = 1; n <= FlsHighIndex; ++n)
1225         {
1226             lpCallback = NtCurrentPeb()->FlsCallback[n];
1227             if (lpCallback && pFlsData->Data[n])
1228             {
1229                 lpCallback(pFlsData->Data[n]);
1230             }
1231         }
1232 
1233         RtlFreeHeap(RtlGetProcessHeap(), 0, pFlsData);
1234         Teb->FlsData = NULL;
1235     }
1236 
1237     /* Check for Fiber data */
1238     if (Teb->HasFiberData)
1239     {
1240         /* Free Fiber data*/
1241         RtlFreeHeap(RtlGetProcessHeap(), 0, Teb->NtTib.FiberData);
1242         Teb->NtTib.FiberData = NULL;
1243     }
1244 
1245     /* Free the activation context stack */
1246     RtlFreeThreadActivationContextStack();
1247     DPRINT("LdrShutdownThread() done\n");
1248 
1249     return STATUS_SUCCESS;
1250 }
1251 
1252 NTSTATUS
1253 NTAPI
1254 LdrpInitializeTls(VOID)
1255 {
1256     PLIST_ENTRY NextEntry, ListHead;
1257     PLDR_DATA_TABLE_ENTRY LdrEntry;
1258     PIMAGE_TLS_DIRECTORY TlsDirectory;
1259     PLDRP_TLS_DATA TlsData;
1260     ULONG Size;
1261 
1262     /* Initialize the TLS List */
1263     InitializeListHead(&LdrpTlsList);
1264 
1265     /* Loop all the modules */
1266     ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
1267     NextEntry = ListHead->Flink;
1268     while (ListHead != NextEntry)
1269     {
1270         /* Get the entry */
1271         LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
1272         NextEntry = NextEntry->Flink;
1273 
1274         /* Get the TLS directory */
1275         TlsDirectory = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
1276                                                     TRUE,
1277                                                     IMAGE_DIRECTORY_ENTRY_TLS,
1278                                                     &Size);
1279 
1280         /* Check if we have a directory */
1281         if (!TlsDirectory) continue;
1282 
1283         /* Check if the image has TLS */
1284         if (!LdrpImageHasTls) LdrpImageHasTls = TRUE;
1285 
1286         /* Show debug message */
1287         if (ShowSnaps)
1288         {
1289             DPRINT1("LDR: Tls Found in %wZ at %p\n",
1290                     &LdrEntry->BaseDllName,
1291                     TlsDirectory);
1292         }
1293 
1294         /* Allocate an entry */
1295         TlsData = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(LDRP_TLS_DATA));
1296         if (!TlsData) return STATUS_NO_MEMORY;
1297 
1298         /* Lock the DLL and mark it for TLS Usage */
1299         LdrEntry->LoadCount = -1;
1300         LdrEntry->TlsIndex = -1;
1301 
1302         /* Save the cached TLS data */
1303         TlsData->TlsDirectory = *TlsDirectory;
1304         InsertTailList(&LdrpTlsList, &TlsData->TlsLinks);
1305 
1306         /* Update the index */
1307         *(PLONG)TlsData->TlsDirectory.AddressOfIndex = LdrpNumberOfTlsEntries;
1308         TlsData->TlsDirectory.Characteristics = LdrpNumberOfTlsEntries++;
1309     }
1310 
1311     /* Done setting up TLS, allocate entries */
1312     return LdrpAllocateTls();
1313 }
1314 
1315 NTSTATUS
1316 NTAPI
1317 LdrpAllocateTls(VOID)
1318 {
1319     PTEB Teb = NtCurrentTeb();
1320     PLIST_ENTRY NextEntry, ListHead;
1321     PLDRP_TLS_DATA TlsData;
1322     SIZE_T TlsDataSize;
1323     PVOID *TlsVector;
1324 
1325     /* Check if we have any entries */
1326     if (!LdrpNumberOfTlsEntries)
1327         return STATUS_SUCCESS;
1328 
1329     /* Allocate the vector array */
1330     TlsVector = RtlAllocateHeap(RtlGetProcessHeap(),
1331                                     0,
1332                                     LdrpNumberOfTlsEntries * sizeof(PVOID));
1333     if (!TlsVector) return STATUS_NO_MEMORY;
1334     Teb->ThreadLocalStoragePointer = TlsVector;
1335 
1336     /* Loop the TLS Array */
1337     ListHead = &LdrpTlsList;
1338     NextEntry = ListHead->Flink;
1339     while (NextEntry != ListHead)
1340     {
1341         /* Get the entry */
1342         TlsData = CONTAINING_RECORD(NextEntry, LDRP_TLS_DATA, TlsLinks);
1343         NextEntry = NextEntry->Flink;
1344 
1345         /* Allocate this vector */
1346         TlsDataSize = TlsData->TlsDirectory.EndAddressOfRawData -
1347                       TlsData->TlsDirectory.StartAddressOfRawData;
1348         TlsVector[TlsData->TlsDirectory.Characteristics] = RtlAllocateHeap(RtlGetProcessHeap(),
1349                                                                            0,
1350                                                                            TlsDataSize);
1351         if (!TlsVector[TlsData->TlsDirectory.Characteristics])
1352         {
1353             /* Out of memory */
1354             return STATUS_NO_MEMORY;
1355         }
1356 
1357         /* Show debug message */
1358         if (ShowSnaps)
1359         {
1360             DPRINT1("LDR: TlsVector %p Index %lu = %p copied from %x to %p\n",
1361                     TlsVector,
1362                     TlsData->TlsDirectory.Characteristics,
1363                     &TlsVector[TlsData->TlsDirectory.Characteristics],
1364                     TlsData->TlsDirectory.StartAddressOfRawData,
1365                     TlsVector[TlsData->TlsDirectory.Characteristics]);
1366         }
1367 
1368         /* Copy the data */
1369         RtlCopyMemory(TlsVector[TlsData->TlsDirectory.Characteristics],
1370                       (PVOID)TlsData->TlsDirectory.StartAddressOfRawData,
1371                       TlsDataSize);
1372     }
1373 
1374     /* Done */
1375     return STATUS_SUCCESS;
1376 }
1377 
1378 VOID
1379 NTAPI
1380 LdrpFreeTls(VOID)
1381 {
1382     PLIST_ENTRY ListHead, NextEntry;
1383     PLDRP_TLS_DATA TlsData;
1384     PVOID *TlsVector;
1385     PTEB Teb = NtCurrentTeb();
1386 
1387     /* Get a pointer to the vector array */
1388     TlsVector = Teb->ThreadLocalStoragePointer;
1389     if (!TlsVector) return;
1390 
1391     /* Loop through it */
1392     ListHead = &LdrpTlsList;
1393     NextEntry = ListHead->Flink;
1394     while (NextEntry != ListHead)
1395     {
1396         TlsData = CONTAINING_RECORD(NextEntry, LDRP_TLS_DATA, TlsLinks);
1397         NextEntry = NextEntry->Flink;
1398 
1399         /* Free each entry */
1400         if (TlsVector[TlsData->TlsDirectory.Characteristics])
1401         {
1402             RtlFreeHeap(RtlGetProcessHeap(),
1403                         0,
1404                         TlsVector[TlsData->TlsDirectory.Characteristics]);
1405         }
1406     }
1407 
1408     /* Free the array itself */
1409     RtlFreeHeap(RtlGetProcessHeap(),
1410                 0,
1411                 TlsVector);
1412 }
1413 
1414 NTSTATUS
1415 NTAPI
1416 LdrpInitializeExecutionOptions(PUNICODE_STRING ImagePathName, PPEB Peb, PHANDLE OptionsKey)
1417 {
1418     NTSTATUS Status;
1419     HANDLE KeyHandle;
1420     ULONG ExecuteOptions, MinimumStackCommit = 0, GlobalFlag;
1421 
1422     /* Return error if we were not provided a pointer where to save the options key handle */
1423     if (!OptionsKey) return STATUS_INVALID_HANDLE;
1424 
1425     /* Zero initialize the options key pointer */
1426     *OptionsKey = NULL;
1427 
1428     /* Open the options key */
1429     Status = LdrOpenImageFileOptionsKey(ImagePathName, 0, &KeyHandle);
1430 
1431     /* Save it if it was opened successfully */
1432     if (NT_SUCCESS(Status))
1433         *OptionsKey = KeyHandle;
1434 
1435     if (KeyHandle)
1436     {
1437         /* There are image specific options, read them starting with NXCOMPAT */
1438         Status = LdrQueryImageFileKeyOption(KeyHandle,
1439                                             L"ExecuteOptions",
1440                                             4,
1441                                             &ExecuteOptions,
1442                                             sizeof(ExecuteOptions),
1443                                             0);
1444 
1445         if (NT_SUCCESS(Status))
1446         {
1447             /* TODO: Set execution options for the process */
1448             /*
1449             if (ExecuteOptions == 0)
1450                 ExecuteOptions = 1;
1451             else
1452                 ExecuteOptions = 2;
1453             ZwSetInformationProcess(NtCurrentProcess(),
1454                                     ProcessExecuteFlags,
1455                                     &ExecuteOptions,
1456                                     sizeof(ULONG));*/
1457 
1458         }
1459 
1460         /* Check if this image uses large pages */
1461         if (Peb->ImageUsesLargePages)
1462         {
1463             /* TODO: If it does, open large page key */
1464             UNIMPLEMENTED;
1465         }
1466 
1467         /* Get various option values */
1468         LdrQueryImageFileKeyOption(KeyHandle,
1469                                    L"DisableHeapLookaside",
1470                                    REG_DWORD,
1471                                    &RtlpDisableHeapLookaside,
1472                                    sizeof(RtlpDisableHeapLookaside),
1473                                    NULL);
1474 
1475         LdrQueryImageFileKeyOption(KeyHandle,
1476                                    L"ShutdownFlags",
1477                                    REG_DWORD,
1478                                    &RtlpShutdownProcessFlags,
1479                                    sizeof(RtlpShutdownProcessFlags),
1480                                    NULL);
1481 
1482         LdrQueryImageFileKeyOption(KeyHandle,
1483                                    L"MinimumStackCommitInBytes",
1484                                    REG_DWORD,
1485                                    &MinimumStackCommit,
1486                                    sizeof(MinimumStackCommit),
1487                                    NULL);
1488 
1489         /* Update PEB's minimum stack commit if it's lower */
1490         if (Peb->MinimumStackCommit < MinimumStackCommit)
1491             Peb->MinimumStackCommit = MinimumStackCommit;
1492 
1493         /* Set the global flag */
1494         Status = LdrQueryImageFileKeyOption(KeyHandle,
1495                                             L"GlobalFlag",
1496                                             REG_DWORD,
1497                                             &GlobalFlag,
1498                                             sizeof(GlobalFlag),
1499                                             NULL);
1500 
1501         if (NT_SUCCESS(Status))
1502             Peb->NtGlobalFlag = GlobalFlag;
1503         else
1504             GlobalFlag = 0;
1505 
1506         /* Call AVRF if necessary */
1507         if (Peb->NtGlobalFlag & (FLG_APPLICATION_VERIFIER | FLG_HEAP_PAGE_ALLOCS))
1508         {
1509             Status = LdrpInitializeApplicationVerifierPackage(KeyHandle, Peb, TRUE, FALSE);
1510             if (!NT_SUCCESS(Status))
1511             {
1512                 DPRINT1("AVRF: LdrpInitializeApplicationVerifierPackage failed with %08X\n", Status);
1513             }
1514         }
1515     }
1516     else
1517     {
1518         /* There are no image-specific options, so perform global initialization */
1519         if (Peb->NtGlobalFlag & (FLG_APPLICATION_VERIFIER | FLG_HEAP_PAGE_ALLOCS))
1520         {
1521             /* Initialize app verifier package */
1522             Status = LdrpInitializeApplicationVerifierPackage(KeyHandle, Peb, TRUE, FALSE);
1523             if (!NT_SUCCESS(Status))
1524             {
1525                 DPRINT1("AVRF: LdrpInitializeApplicationVerifierPackage failed with %08X\n", Status);
1526             }
1527         }
1528     }
1529 
1530     return STATUS_SUCCESS;
1531 }
1532 
1533 VOID
1534 NTAPI
1535 LdrpValidateImageForMp(IN PLDR_DATA_TABLE_ENTRY LdrDataTableEntry)
1536 {
1537     UNIMPLEMENTED;
1538 }
1539 
1540 BOOLEAN
1541 NTAPI
1542 LdrpDisableProcessCompatGuidDetection(VOID)
1543 {
1544     UNICODE_STRING PolicyKey = RTL_CONSTANT_STRING(L"\\Registry\\MACHINE\\Software\\Policies\\Microsoft\\Windows\\AppCompat");
1545     UNICODE_STRING DisableDetection = RTL_CONSTANT_STRING(L"DisableCompatGuidDetection");
1546     OBJECT_ATTRIBUTES PolicyKeyAttributes = RTL_CONSTANT_OBJECT_ATTRIBUTES(&PolicyKey, OBJ_CASE_INSENSITIVE);
1547     KEY_VALUE_PARTIAL_INFORMATION KeyInfo;
1548     ULONG ResultLength;
1549     NTSTATUS Status;
1550     HANDLE KeyHandle;
1551 
1552     Status = NtOpenKey(&KeyHandle, KEY_QUERY_VALUE, &PolicyKeyAttributes);
1553     if (NT_SUCCESS(Status))
1554     {
1555         Status = NtQueryValueKey(KeyHandle,
1556                                  &DisableDetection,
1557                                  KeyValuePartialInformation,
1558                                  &KeyInfo,
1559                                  sizeof(KeyInfo),
1560                                  &ResultLength);
1561         NtClose(KeyHandle);
1562         if ((NT_SUCCESS(Status)) &&
1563             (KeyInfo.Type == REG_DWORD) &&
1564             (KeyInfo.DataLength == sizeof(ULONG)) &&
1565             (KeyInfo.Data[0] == TRUE))
1566         {
1567             return TRUE;
1568         }
1569     }
1570     return FALSE;
1571 }
1572 
1573 
1574 VOID
1575 NTAPI
1576 LdrpInitializeProcessCompat(PVOID pProcessActctx, PVOID* pOldShimData)
1577 {
1578     static const struct
1579     {
1580         const GUID* Guid;
1581         const DWORD Version;
1582     } KnownCompatGuids[] = {
1583         { &COMPAT_GUID_WIN10, _WIN32_WINNT_WIN10 },
1584         { &COMPAT_GUID_WIN81, _WIN32_WINNT_WINBLUE },
1585         { &COMPAT_GUID_WIN8, _WIN32_WINNT_WIN8 },
1586         { &COMPAT_GUID_WIN7, _WIN32_WINNT_WIN7 },
1587         { &COMPAT_GUID_VISTA, _WIN32_WINNT_VISTA },
1588     };
1589 
1590     ULONG Buffer[(sizeof(COMPATIBILITY_CONTEXT_ELEMENT) * 10 + sizeof(ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION)) / sizeof(ULONG)];
1591     ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION* ContextCompatInfo;
1592     SIZE_T SizeRequired;
1593     NTSTATUS Status;
1594     DWORD n, cur;
1595     ReactOS_ShimData* pShimData = *pOldShimData;
1596 
1597     if (pShimData)
1598     {
1599         if (pShimData->dwMagic != REACTOS_SHIMDATA_MAGIC ||
1600             pShimData->dwSize != sizeof(ReactOS_ShimData))
1601         {
1602             DPRINT1("LdrpInitializeProcessCompat: Corrupt pShimData (0x%x, %u)\n", pShimData->dwMagic, pShimData->dwSize);
1603             return;
1604         }
1605         if (pShimData->dwRosProcessCompatVersion)
1606         {
1607             if (pShimData->dwRosProcessCompatVersion == REACTOS_COMPATVERSION_IGNOREMANIFEST)
1608             {
1609                 DPRINT1("LdrpInitializeProcessCompat: ProcessCompatVersion set to ignore manifest\n");
1610             }
1611             else
1612             {
1613                 DPRINT1("LdrpInitializeProcessCompat: ProcessCompatVersion already set to 0x%x\n", pShimData->dwRosProcessCompatVersion);
1614             }
1615             return;
1616         }
1617     }
1618 
1619     SizeRequired = sizeof(Buffer);
1620     Status = RtlQueryInformationActivationContext(RTL_QUERY_ACTIVATION_CONTEXT_FLAG_NO_ADDREF,
1621                                                   pProcessActctx,
1622                                                   NULL,
1623                                                   CompatibilityInformationInActivationContext,
1624                                                   Buffer,
1625                                                   sizeof(Buffer),
1626                                                   &SizeRequired);
1627 
1628     if (!NT_SUCCESS(Status))
1629     {
1630         DPRINT1("LdrpInitializeProcessCompat: Unable to query process actctx with status %x\n", Status);
1631         return;
1632     }
1633 
1634     ContextCompatInfo = (ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*)Buffer;
1635     /* No Compatibility elements present, bail out */
1636     if (ContextCompatInfo->ElementCount == 0)
1637         return;
1638 
1639     /* Search for known GUID's, starting from newest to oldest. */
1640     for (cur = 0; cur < RTL_NUMBER_OF(KnownCompatGuids); ++cur)
1641     {
1642         for (n = 0; n < ContextCompatInfo->ElementCount; ++n)
1643         {
1644             if (ContextCompatInfo->Elements[n].Type == ACTCX_COMPATIBILITY_ELEMENT_TYPE_OS &&
1645                 RtlCompareMemory(&ContextCompatInfo->Elements[n].Id, KnownCompatGuids[cur].Guid, sizeof(GUID)) == sizeof(GUID))
1646             {
1647                 if (LdrpDisableProcessCompatGuidDetection())
1648                 {
1649                     DPRINT1("LdrpInitializeProcessCompat: Not applying automatic fix for winver 0x%x due to policy\n", KnownCompatGuids[cur].Version);
1650                     return;
1651                 }
1652 
1653                 /* If this process did not need shim data before, allocate and store it */
1654                 if (pShimData == NULL)
1655                 {
1656                     PPEB Peb = NtCurrentPeb();
1657 
1658                     ASSERT(Peb->pShimData == NULL);
1659                     pShimData = RtlAllocateHeap(Peb->ProcessHeap, HEAP_ZERO_MEMORY, sizeof(*pShimData));
1660 
1661                     if (!pShimData)
1662                     {
1663                         DPRINT1("LdrpInitializeProcessCompat: Unable to allocated %u bytes\n", sizeof(*pShimData));
1664                         return;
1665                     }
1666 
1667                     pShimData->dwSize = sizeof(*pShimData);
1668                     pShimData->dwMagic = REACTOS_SHIMDATA_MAGIC;
1669 
1670                     Peb->pShimData = pShimData;
1671                     *pOldShimData = pShimData;
1672                 }
1673 
1674                 /* Store the highest found version, and bail out. */
1675                 pShimData->dwRosProcessCompatVersion = KnownCompatGuids[cur].Version;
1676                 DPRINT1("LdrpInitializeProcessCompat: Found guid for winver 0x%x\n", KnownCompatGuids[cur].Version);
1677                 return;
1678             }
1679         }
1680     }
1681 }
1682 
1683 VOID
1684 NTAPI
1685 LdrpInitializeDotLocalSupport(PRTL_USER_PROCESS_PARAMETERS ProcessParameters)
1686 {
1687     UNICODE_STRING ImagePathName = ProcessParameters->ImagePathName;
1688     WCHAR LocalBuffer[MAX_PATH];
1689     UNICODE_STRING DotLocal;
1690     NTSTATUS Status;
1691     ULONG RequiredSize;
1692 
1693     RequiredSize = ImagePathName.Length + LdrpDotLocal.Length + sizeof(UNICODE_NULL);
1694     if (RequiredSize <= sizeof(LocalBuffer))
1695     {
1696         RtlInitEmptyUnicodeString(&DotLocal, LocalBuffer, sizeof(LocalBuffer));
1697     }
1698     else if (RequiredSize <= UNICODE_STRING_MAX_BYTES)
1699     {
1700         DotLocal.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, RequiredSize);
1701         DotLocal.Length = 0;
1702         DotLocal.MaximumLength = RequiredSize;
1703         if (!DotLocal.Buffer)
1704             DPRINT1("LDR: Failed to allocate memory for .local check\n");
1705     }
1706     else
1707     {
1708         DotLocal.Buffer = NULL;
1709         DotLocal.Length = 0;
1710         DotLocal.MaximumLength = 0;
1711         DPRINT1("LDR: String too big for .local check\n");
1712     }
1713 
1714     if (DotLocal.Buffer)
1715     {
1716         Status = RtlAppendUnicodeStringToString(&DotLocal, &ImagePathName);
1717         ASSERT(NT_SUCCESS(Status));
1718         if (NT_SUCCESS(Status))
1719         {
1720             Status = RtlAppendUnicodeStringToString(&DotLocal, &LdrpDotLocal);
1721             ASSERT(NT_SUCCESS(Status));
1722         }
1723 
1724         if (NT_SUCCESS(Status))
1725         {
1726             if (RtlDoesFileExists_UStr(&DotLocal))
1727             {
1728                 ProcessParameters->Flags |= RTL_USER_PROCESS_PARAMETERS_PRIVATE_DLL_PATH;
1729             }
1730         }
1731         else
1732         {
1733             DPRINT1("LDR: Failed to append: 0x%lx\n", Status);
1734         }
1735 
1736         if (DotLocal.Buffer != LocalBuffer)
1737         {
1738             RtlFreeHeap(RtlGetProcessHeap(), 0, DotLocal.Buffer);
1739         }
1740     }
1741 }
1742 
1743 
1744 NTSTATUS
1745 NTAPI
1746 LdrpInitializeProcess(IN PCONTEXT Context,
1747                       IN PVOID SystemArgument1)
1748 {
1749     RTL_HEAP_PARAMETERS HeapParameters;
1750     ULONG ComSectionSize;
1751     ANSI_STRING BaseProcessInitPostImportName = RTL_CONSTANT_STRING("BaseProcessInitPostImport");
1752     ANSI_STRING BaseQueryModuleDataName = RTL_CONSTANT_STRING("BaseQueryModuleData");
1753     PVOID OldShimData;
1754     OBJECT_ATTRIBUTES ObjectAttributes;
1755     //UNICODE_STRING LocalFileName, FullImageName;
1756     HANDLE SymLinkHandle;
1757     //ULONG DebugHeapOnly;
1758     UNICODE_STRING CommandLine, NtSystemRoot, ImagePathName, FullPath, ImageFileName, KnownDllString;
1759     PPEB Peb = NtCurrentPeb();
1760     BOOLEAN IsDotNetImage = FALSE;
1761     BOOLEAN FreeCurDir = FALSE;
1762     //HANDLE CompatKey;
1763     PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
1764     //LPWSTR ImagePathBuffer;
1765     ULONG ConfigSize;
1766     UNICODE_STRING CurrentDirectory;
1767     HANDLE OptionsKey;
1768     ULONG HeapFlags;
1769     PIMAGE_NT_HEADERS NtHeader;
1770     LPWSTR NtDllName = NULL;
1771     NTSTATUS Status, ImportStatus;
1772     NLSTABLEINFO NlsTable;
1773     PIMAGE_LOAD_CONFIG_DIRECTORY LoadConfig;
1774     PTEB Teb = NtCurrentTeb();
1775     PLIST_ENTRY ListHead;
1776     PLIST_ENTRY NextEntry;
1777     ULONG i;
1778     PWSTR ImagePath;
1779     ULONG DebugProcessHeapOnly = 0;
1780     PLDR_DATA_TABLE_ENTRY NtLdrEntry;
1781     PWCHAR Current;
1782     ULONG ExecuteOptions = 0;
1783     PVOID ViewBase;
1784 
1785     /* Set a NULL SEH Filter */
1786     RtlSetUnhandledExceptionFilter(NULL);
1787 
1788     /* Get the image path */
1789     ImagePath = Peb->ProcessParameters->ImagePathName.Buffer;
1790 
1791     /* Check if it's not normalized */
1792     if (!(Peb->ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_NORMALIZED))
1793     {
1794         /* Normalize it*/
1795         ImagePath = (PWSTR)((ULONG_PTR)ImagePath + (ULONG_PTR)Peb->ProcessParameters);
1796     }
1797 
1798     /* Create a unicode string for the Image Path */
1799     ImagePathName.Length = Peb->ProcessParameters->ImagePathName.Length;
1800     ImagePathName.MaximumLength = ImagePathName.Length + sizeof(WCHAR);
1801     ImagePathName.Buffer = ImagePath;
1802 
1803     /* Get the NT Headers */
1804     NtHeader = RtlImageNtHeader(Peb->ImageBaseAddress);
1805 
1806     /* Get the execution options */
1807     Status = LdrpInitializeExecutionOptions(&ImagePathName, Peb, &OptionsKey);
1808 
1809     /* Check if this is a .NET executable */
1810     if (RtlImageDirectoryEntryToData(Peb->ImageBaseAddress,
1811                                      TRUE,
1812                                      IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR,
1813                                      &ComSectionSize))
1814     {
1815         /* Remember this for later */
1816         IsDotNetImage = TRUE;
1817     }
1818 
1819     /* Save the NTDLL Base address */
1820     NtDllBase = SystemArgument1;
1821 
1822     /* If this is a Native Image */
1823     if (NtHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_NATIVE)
1824     {
1825         /* Then do DLL Validation */
1826         LdrpDllValidation = TRUE;
1827     }
1828 
1829     /* Save the old Shim Data */
1830     OldShimData = Peb->pShimData;
1831 
1832     /* ReactOS specific: do not clear it. (Windows starts doing the same in later versions) */
1833     //Peb->pShimData = NULL;
1834 
1835     /* Save the number of processors and CS Timeout */
1836     LdrpNumberOfProcessors = Peb->NumberOfProcessors;
1837     RtlpTimeout = Peb->CriticalSectionTimeout;
1838 
1839     /* Normalize the parameters */
1840     ProcessParameters = RtlNormalizeProcessParams(Peb->ProcessParameters);
1841     if (ProcessParameters)
1842     {
1843         /* Save the Image and Command Line Names */
1844         ImageFileName = ProcessParameters->ImagePathName;
1845         CommandLine = ProcessParameters->CommandLine;
1846     }
1847     else
1848     {
1849         /* It failed, initialize empty strings */
1850         RtlInitUnicodeString(&ImageFileName, NULL);
1851         RtlInitUnicodeString(&CommandLine, NULL);
1852     }
1853 
1854     /* Initialize NLS data */
1855     RtlInitNlsTables(Peb->AnsiCodePageData,
1856                      Peb->OemCodePageData,
1857                      Peb->UnicodeCaseTableData,
1858                      &NlsTable);
1859 
1860     /* Reset NLS Translations */
1861     RtlResetRtlTranslations(&NlsTable);
1862 
1863     /* Get the Image Config Directory */
1864     LoadConfig = RtlImageDirectoryEntryToData(Peb->ImageBaseAddress,
1865                                               TRUE,
1866                                               IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
1867                                               &ConfigSize);
1868 
1869     /* Setup the Heap Parameters */
1870     RtlZeroMemory(&HeapParameters, sizeof(HeapParameters));
1871     HeapFlags = HEAP_GROWABLE;
1872     HeapParameters.Length = sizeof(HeapParameters);
1873 
1874     /* Check if we have Configuration Data */
1875 #define VALID_CONFIG_FIELD(Name) (ConfigSize >= (FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, Name) + sizeof(LoadConfig->Name)))
1876     /* The 'original' load config ends after SecurityCookie */
1877     if ((LoadConfig) && ConfigSize && (VALID_CONFIG_FIELD(SecurityCookie) || ConfigSize == LoadConfig->Size))
1878     {
1879         if (ConfigSize != sizeof(IMAGE_LOAD_CONFIG_DIRECTORY))
1880             DPRINT1("WARN: Accepting different LOAD_CONFIG size!\n");
1881         else
1882             DPRINT1("Applying LOAD_CONFIG\n");
1883 
1884         if (VALID_CONFIG_FIELD(GlobalFlagsSet) && LoadConfig->GlobalFlagsSet)
1885             Peb->NtGlobalFlag |= LoadConfig->GlobalFlagsSet;
1886 
1887         if (VALID_CONFIG_FIELD(GlobalFlagsClear) && LoadConfig->GlobalFlagsClear)
1888             Peb->NtGlobalFlag &= ~LoadConfig->GlobalFlagsClear;
1889 
1890         if (VALID_CONFIG_FIELD(CriticalSectionDefaultTimeout) && LoadConfig->CriticalSectionDefaultTimeout)
1891             RtlpTimeout.QuadPart = Int32x32To64(LoadConfig->CriticalSectionDefaultTimeout, -10000000);
1892 
1893         if (VALID_CONFIG_FIELD(DeCommitFreeBlockThreshold) && LoadConfig->DeCommitFreeBlockThreshold)
1894             HeapParameters.DeCommitFreeBlockThreshold = LoadConfig->DeCommitFreeBlockThreshold;
1895 
1896         if (VALID_CONFIG_FIELD(DeCommitTotalFreeThreshold) && LoadConfig->DeCommitTotalFreeThreshold)
1897             HeapParameters.DeCommitTotalFreeThreshold = LoadConfig->DeCommitTotalFreeThreshold;
1898 
1899         if (VALID_CONFIG_FIELD(MaximumAllocationSize) && LoadConfig->MaximumAllocationSize)
1900             HeapParameters.MaximumAllocationSize = LoadConfig->MaximumAllocationSize;
1901 
1902         if (VALID_CONFIG_FIELD(VirtualMemoryThreshold) && LoadConfig->VirtualMemoryThreshold)
1903             HeapParameters.VirtualMemoryThreshold = LoadConfig->VirtualMemoryThreshold;
1904 
1905         if (VALID_CONFIG_FIELD(ProcessHeapFlags) && LoadConfig->ProcessHeapFlags)
1906             HeapFlags = LoadConfig->ProcessHeapFlags;
1907     }
1908 #undef VALID_CONFIG_FIELD
1909 
1910     /* Check for custom affinity mask */
1911     if (Peb->ImageProcessAffinityMask)
1912     {
1913         /* Set it */
1914         Status = NtSetInformationProcess(NtCurrentProcess(),
1915                                          ProcessAffinityMask,
1916                                          &Peb->ImageProcessAffinityMask,
1917                                          sizeof(Peb->ImageProcessAffinityMask));
1918     }
1919 
1920     /* Check if verbose debugging (ShowSnaps) was requested */
1921     ShowSnaps = Peb->NtGlobalFlag & FLG_SHOW_LDR_SNAPS;
1922 
1923     /* Start verbose debugging messages right now if they were requested */
1924     if (ShowSnaps)
1925     {
1926         DPRINT1("LDR: PID: 0x%p started - '%wZ'\n",
1927                 Teb->ClientId.UniqueProcess,
1928                 &CommandLine);
1929     }
1930 
1931     /* If the timeout is too long */
1932     if (RtlpTimeout.QuadPart < Int32x32To64(3600, -10000000))
1933     {
1934         /* Then disable CS Timeout */
1935         RtlpTimeoutDisable = TRUE;
1936     }
1937 
1938     /* Initialize Critical Section Data */
1939     RtlpInitDeferedCriticalSection();
1940 
1941     /* Initialize VEH Call lists */
1942     RtlpInitializeVectoredExceptionHandling();
1943 
1944     /* Set TLS/FLS Bitmap data */
1945     Peb->FlsBitmap = &FlsBitMap;
1946     Peb->TlsBitmap = &TlsBitMap;
1947     Peb->TlsExpansionBitmap = &TlsExpansionBitMap;
1948 
1949     /* Initialize FLS Bitmap */
1950     RtlInitializeBitMap(&FlsBitMap,
1951                         Peb->FlsBitmapBits,
1952                         FLS_MAXIMUM_AVAILABLE);
1953     RtlSetBit(&FlsBitMap, 0);
1954     InitializeListHead(&Peb->FlsListHead);
1955 
1956     /* Initialize TLS Bitmap */
1957     RtlInitializeBitMap(&TlsBitMap,
1958                         Peb->TlsBitmapBits,
1959                         TLS_MINIMUM_AVAILABLE);
1960     RtlSetBit(&TlsBitMap, 0);
1961     RtlInitializeBitMap(&TlsExpansionBitMap,
1962                         Peb->TlsExpansionBitmapBits,
1963                         TLS_EXPANSION_SLOTS);
1964     RtlSetBit(&TlsExpansionBitMap, 0);
1965 
1966     /* Initialize the Hash Table */
1967     for (i = 0; i < LDR_HASH_TABLE_ENTRIES; i++)
1968     {
1969         InitializeListHead(&LdrpHashTable[i]);
1970     }
1971 
1972     /* Initialize the Loader Lock */
1973     // FIXME: What's the point of initing it manually, if two lines lower
1974     //        a call to RtlInitializeCriticalSection() is being made anyway?
1975     //InsertTailList(&RtlCriticalSectionList, &LdrpLoaderLock.DebugInfo->ProcessLocksList);
1976     //LdrpLoaderLock.DebugInfo->CriticalSection = &LdrpLoaderLock;
1977     RtlInitializeCriticalSection(&LdrpLoaderLock);
1978     LdrpLoaderLockInit = TRUE;
1979 
1980     /* Check if User Stack Trace Database support was requested */
1981     if (Peb->NtGlobalFlag & FLG_USER_STACK_TRACE_DB)
1982     {
1983         DPRINT1("We don't support user stack trace databases yet\n");
1984     }
1985 
1986     /* Setup Fast PEB Lock */
1987     RtlInitializeCriticalSection(&FastPebLock);
1988     Peb->FastPebLock = &FastPebLock;
1989     //Peb->FastPebLockRoutine = (PPEBLOCKROUTINE)RtlEnterCriticalSection;
1990     //Peb->FastPebUnlockRoutine = (PPEBLOCKROUTINE)RtlLeaveCriticalSection;
1991 
1992     /* Setup Callout Lock and Notification list */
1993     //RtlInitializeCriticalSection(&RtlpCalloutEntryLock);
1994     InitializeListHead(&LdrpDllNotificationList);
1995 
1996     /* For old executables, use 16-byte aligned heap */
1997     if ((NtHeader->OptionalHeader.MajorSubsystemVersion <= 3) &&
1998         (NtHeader->OptionalHeader.MinorSubsystemVersion < 51))
1999     {
2000         HeapFlags |= HEAP_CREATE_ALIGN_16;
2001     }
2002 
2003     /* Setup the Heap */
2004     RtlInitializeHeapManager();
2005     Peb->ProcessHeap = RtlCreateHeap(HeapFlags,
2006                                      NULL,
2007                                      NtHeader->OptionalHeader.SizeOfHeapReserve,
2008                                      NtHeader->OptionalHeader.SizeOfHeapCommit,
2009                                      NULL,
2010                                      &HeapParameters);
2011 
2012     if (!Peb->ProcessHeap)
2013     {
2014         DPRINT1("Failed to create process heap\n");
2015         return STATUS_NO_MEMORY;
2016     }
2017 
2018     /* Allocate an Activation Context Stack */
2019     Status = RtlAllocateActivationContextStack(&Teb->ActivationContextStackPointer);
2020     if (!NT_SUCCESS(Status)) return Status;
2021 
2022     RtlZeroMemory(&HeapParameters, sizeof(HeapParameters));
2023     HeapFlags = HEAP_GROWABLE | HEAP_CLASS_1;
2024     HeapParameters.Length = sizeof(HeapParameters);
2025     LdrpHeap = RtlCreateHeap(HeapFlags, 0, 0x10000, 0x6000, 0, &HeapParameters);
2026     if (!LdrpHeap)
2027     {
2028         DPRINT1("Failed to create loader private heap\n");
2029         return STATUS_NO_MEMORY;
2030     }
2031 
2032     /* Check for Debug Heap */
2033     if (OptionsKey)
2034     {
2035         /* Query the setting */
2036         Status = LdrQueryImageFileKeyOption(OptionsKey,
2037                                             L"DebugProcessHeapOnly",
2038                                             REG_DWORD,
2039                                             &DebugProcessHeapOnly,
2040                                             sizeof(ULONG),
2041                                             NULL);
2042 
2043         if (NT_SUCCESS(Status))
2044         {
2045             /* Reset DPH if requested */
2046             if (RtlpPageHeapEnabled && DebugProcessHeapOnly)
2047             {
2048                 RtlpDphGlobalFlags &= ~DPH_FLAG_DLL_NOTIFY;
2049                 RtlpPageHeapEnabled = FALSE;
2050             }
2051         }
2052     }
2053 
2054     /* Build the NTDLL Path */
2055     FullPath.Buffer = StringBuffer;
2056     FullPath.Length = 0;
2057     FullPath.MaximumLength = sizeof(StringBuffer);
2058     RtlInitUnicodeString(&NtSystemRoot, SharedUserData->NtSystemRoot);
2059     RtlAppendUnicodeStringToString(&FullPath, &NtSystemRoot);
2060     RtlAppendUnicodeToString(&FullPath, L"\\System32\\");
2061 
2062     /* Open the Known DLLs directory */
2063     RtlInitUnicodeString(&KnownDllString, L"\\KnownDlls");
2064     InitializeObjectAttributes(&ObjectAttributes,
2065                                &KnownDllString,
2066                                OBJ_CASE_INSENSITIVE,
2067                                NULL,
2068                                NULL);
2069     Status = ZwOpenDirectoryObject(&LdrpKnownDllObjectDirectory,
2070                                    DIRECTORY_QUERY | DIRECTORY_TRAVERSE,
2071                                    &ObjectAttributes);
2072 
2073     /* Check if it exists */
2074     if (NT_SUCCESS(Status))
2075     {
2076         /* Open the Known DLLs Path */
2077         RtlInitUnicodeString(&KnownDllString, L"KnownDllPath");
2078         InitializeObjectAttributes(&ObjectAttributes,
2079                                    &KnownDllString,
2080                                    OBJ_CASE_INSENSITIVE,
2081                                    LdrpKnownDllObjectDirectory,
2082                                    NULL);
2083         Status = NtOpenSymbolicLinkObject(&SymLinkHandle,
2084                                           SYMBOLIC_LINK_QUERY,
2085                                           &ObjectAttributes);
2086         if (NT_SUCCESS(Status))
2087         {
2088             /* Query the path */
2089             LdrpKnownDllPath.Length = 0;
2090             LdrpKnownDllPath.MaximumLength = sizeof(LdrpKnownDllPathBuffer);
2091             LdrpKnownDllPath.Buffer = LdrpKnownDllPathBuffer;
2092             Status = ZwQuerySymbolicLinkObject(SymLinkHandle, &LdrpKnownDllPath, NULL);
2093             NtClose(SymLinkHandle);
2094             if (!NT_SUCCESS(Status))
2095             {
2096                 DPRINT1("LDR: %s - failed call to ZwQuerySymbolicLinkObject with status %x\n", "", Status);
2097                 return Status;
2098             }
2099         }
2100     }
2101 
2102     /* Check if we failed */
2103     if (!NT_SUCCESS(Status))
2104     {
2105         /* Assume System32 */
2106         LdrpKnownDllObjectDirectory = NULL;
2107         RtlInitUnicodeString(&LdrpKnownDllPath, StringBuffer);
2108         LdrpKnownDllPath.Length -= sizeof(WCHAR);
2109     }
2110 
2111     /* If we have process parameters, get the default path and current path */
2112     if (ProcessParameters)
2113     {
2114         /* Check if we have a Dll Path */
2115         if (ProcessParameters->DllPath.Length)
2116         {
2117             /* Get the path */
2118             LdrpDefaultPath = *(PUNICODE_STRING)&ProcessParameters->DllPath;
2119         }
2120         else
2121         {
2122             /* We need a valid path */
2123             DPRINT1("No valid DllPath was given!\n");
2124             LdrpInitFailure(STATUS_INVALID_PARAMETER);
2125         }
2126 
2127         /* Set the current directory */
2128         CurrentDirectory = ProcessParameters->CurrentDirectory.DosPath;
2129 
2130         /* Check if it's empty or invalid */
2131         if ((!CurrentDirectory.Buffer) ||
2132             (CurrentDirectory.Buffer[0] == UNICODE_NULL) ||
2133             (!CurrentDirectory.Length))
2134         {
2135             /* Allocate space for the buffer */
2136             CurrentDirectory.Buffer = RtlAllocateHeap(Peb->ProcessHeap,
2137                                                       0,
2138                                                       3 * sizeof(WCHAR) +
2139                                                       sizeof(UNICODE_NULL));
2140             if (!CurrentDirectory.Buffer)
2141             {
2142                 DPRINT1("LDR: LdrpInitializeProcess - unable to allocate current working directory buffer\n");
2143                 // FIXME: And what?
2144             }
2145 
2146             /* Copy the drive of the system root */
2147             RtlMoveMemory(CurrentDirectory.Buffer,
2148                           SharedUserData->NtSystemRoot,
2149                           3 * sizeof(WCHAR));
2150             CurrentDirectory.Buffer[3] = UNICODE_NULL;
2151             CurrentDirectory.Length = 3 * sizeof(WCHAR);
2152             CurrentDirectory.MaximumLength = CurrentDirectory.Length + sizeof(WCHAR);
2153 
2154             FreeCurDir = TRUE;
2155             DPRINT("Using dynamically allocd curdir\n");
2156         }
2157         else
2158         {
2159             /* Use the local buffer */
2160             DPRINT("Using local system root\n");
2161         }
2162     }
2163 
2164     /* Setup Loader Data */
2165     Peb->Ldr = &PebLdr;
2166     InitializeListHead(&PebLdr.InLoadOrderModuleList);
2167     InitializeListHead(&PebLdr.InMemoryOrderModuleList);
2168     InitializeListHead(&PebLdr.InInitializationOrderModuleList);
2169     PebLdr.Length = sizeof(PEB_LDR_DATA);
2170     PebLdr.Initialized = TRUE;
2171 
2172     /* Allocate a data entry for the Image */
2173     LdrpImageEntry = LdrpAllocateDataTableEntry(Peb->ImageBaseAddress);
2174 
2175     /* Set it up */
2176     LdrpImageEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(LdrpImageEntry->DllBase);
2177     LdrpImageEntry->LoadCount = -1;
2178     LdrpImageEntry->EntryPointActivationContext = 0;
2179     LdrpImageEntry->FullDllName = ImageFileName;
2180 
2181     if (IsDotNetImage)
2182         LdrpImageEntry->Flags = LDRP_COR_IMAGE;
2183     else
2184         LdrpImageEntry->Flags = 0;
2185 
2186     /* Check if the name is empty */
2187     if (!ImageFileName.Buffer[0])
2188     {
2189         /* Use the same Base name */
2190         LdrpImageEntry->BaseDllName = LdrpImageEntry->FullDllName;
2191     }
2192     else
2193     {
2194         /* Find the last slash */
2195         Current = ImageFileName.Buffer;
2196         while (*Current)
2197         {
2198             if (*Current++ == '\\')
2199             {
2200                 /* Set this path */
2201                 NtDllName = Current;
2202             }
2203         }
2204 
2205         /* Did we find anything? */
2206         if (!NtDllName)
2207         {
2208             /* Use the same Base name */
2209             LdrpImageEntry->BaseDllName = LdrpImageEntry->FullDllName;
2210         }
2211         else
2212         {
2213             /* Setup the name */
2214             LdrpImageEntry->BaseDllName.Length = (USHORT)((ULONG_PTR)ImageFileName.Buffer + ImageFileName.Length - (ULONG_PTR)NtDllName);
2215             LdrpImageEntry->BaseDllName.MaximumLength = LdrpImageEntry->BaseDllName.Length + sizeof(WCHAR);
2216             LdrpImageEntry->BaseDllName.Buffer = (PWSTR)((ULONG_PTR)ImageFileName.Buffer +
2217                                                      (ImageFileName.Length - LdrpImageEntry->BaseDllName.Length));
2218         }
2219     }
2220 
2221     /* Processing done, insert it */
2222     LdrpInsertMemoryTableEntry(LdrpImageEntry);
2223     LdrpImageEntry->Flags |= LDRP_ENTRY_PROCESSED;
2224 
2225     /* Now add an entry for NTDLL */
2226     NtLdrEntry = LdrpAllocateDataTableEntry(SystemArgument1);
2227     NtLdrEntry->Flags = LDRP_IMAGE_DLL;
2228     NtLdrEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(NtLdrEntry->DllBase);
2229     NtLdrEntry->LoadCount = -1;
2230     NtLdrEntry->EntryPointActivationContext = 0;
2231 
2232     NtLdrEntry->FullDllName.Length = FullPath.Length;
2233     NtLdrEntry->FullDllName.MaximumLength = FullPath.MaximumLength;
2234     NtLdrEntry->FullDllName.Buffer = StringBuffer;
2235     RtlAppendUnicodeStringToString(&NtLdrEntry->FullDllName, &NtDllString);
2236 
2237     NtLdrEntry->BaseDllName.Length = NtDllString.Length;
2238     NtLdrEntry->BaseDllName.MaximumLength = NtDllString.MaximumLength;
2239     NtLdrEntry->BaseDllName.Buffer = NtDllString.Buffer;
2240 
2241     /* Processing done, insert it */
2242     LdrpNtDllDataTableEntry = NtLdrEntry;
2243     LdrpInsertMemoryTableEntry(NtLdrEntry);
2244 
2245     /* Let the world know */
2246     if (ShowSnaps)
2247     {
2248         DPRINT1("LDR: NEW PROCESS\n");
2249         DPRINT1("     Image Path: %wZ (%wZ)\n", &LdrpImageEntry->FullDllName, &LdrpImageEntry->BaseDllName);
2250         DPRINT1("     Current Directory: %wZ\n", &CurrentDirectory);
2251         DPRINT1("     Search Path: %wZ\n", &LdrpDefaultPath);
2252     }
2253 
2254     /* Link the Init Order List */
2255     InsertHeadList(&Peb->Ldr->InInitializationOrderModuleList,
2256                    &LdrpNtDllDataTableEntry->InInitializationOrderLinks);
2257 
2258     /* Initialize Wine's active context implementation for the current process */
2259     actctx_init(&OldShimData);
2260 
2261     /* Set the current directory */
2262     Status = RtlSetCurrentDirectory_U(&CurrentDirectory);
2263     if (!NT_SUCCESS(Status))
2264     {
2265         /* We failed, check if we should free it */
2266         if (FreeCurDir) RtlFreeUnicodeString(&CurrentDirectory);
2267 
2268         /* Set it to the NT Root */
2269         CurrentDirectory = NtSystemRoot;
2270         RtlSetCurrentDirectory_U(&CurrentDirectory);
2271     }
2272     else
2273     {
2274         /* We're done with it, free it */
2275         if (FreeCurDir) RtlFreeUnicodeString(&CurrentDirectory);
2276     }
2277 
2278     /* Check if we should look for a .local file */
2279     if (ProcessParameters && !(ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_LOCAL_DLL_PATH))
2280     {
2281         LdrpInitializeDotLocalSupport(ProcessParameters);
2282     }
2283 
2284     /* Check if the Application Verifier was enabled */
2285     if (Peb->NtGlobalFlag & FLG_APPLICATION_VERIFIER)
2286     {
2287         Status = AVrfInitializeVerifier();
2288         if (!NT_SUCCESS(Status))
2289         {
2290             DPRINT1("LDR: AVrfInitializeVerifier failed (ntstatus 0x%x)\n", Status);
2291             return Status;
2292         }
2293 
2294     }
2295 
2296     if (IsDotNetImage)
2297     {
2298         /* FIXME */
2299         DPRINT1("We don't support .NET applications yet\n");
2300     }
2301 
2302     if (NtHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI ||
2303         NtHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI)
2304     {
2305         PVOID Kernel32BaseAddress;
2306         PVOID FunctionAddress;
2307 
2308         Status = LdrLoadDll(NULL, NULL, &Kernel32String, &Kernel32BaseAddress);
2309 
2310         if (!NT_SUCCESS(Status))
2311         {
2312             if (ShowSnaps)
2313                 DPRINT1("LDR: Unable to load %wZ, Status=0x%08lx\n", &Kernel32String, Status);
2314             return Status;
2315         }
2316 
2317         Status = LdrGetProcedureAddress(Kernel32BaseAddress,
2318                                         &BaseProcessInitPostImportName,
2319                                         0,
2320                                         &FunctionAddress);
2321 
2322         if (!NT_SUCCESS(Status))
2323         {
2324             if (ShowSnaps)
2325                 DPRINT1("LDR: Unable to find post-import process init function, Status=0x%08lx\n", &Kernel32String, Status);
2326             return Status;
2327         }
2328         Kernel32ProcessInitPostImportFunction = FunctionAddress;
2329 
2330         Status = LdrGetProcedureAddress(Kernel32BaseAddress,
2331                                         &BaseQueryModuleDataName,
2332                                         0,
2333                                         &FunctionAddress);
2334 
2335         if (!NT_SUCCESS(Status))
2336         {
2337             if (ShowSnaps)
2338                 DPRINT1("LDR: Unable to find BaseQueryModuleData, Status=0x%08lx\n", &Kernel32String, Status);
2339             return Status;
2340         }
2341         Kernel32BaseQueryModuleData = FunctionAddress;
2342     }
2343 
2344     /* Walk the IAT and load all the DLLs */
2345     ImportStatus = LdrpWalkImportDescriptor(LdrpDefaultPath.Buffer, LdrpImageEntry);
2346 
2347     /* Check if relocation is needed */
2348     if (Peb->ImageBaseAddress != (PVOID)NtHeader->OptionalHeader.ImageBase)
2349     {
2350         DPRINT1("LDR: Performing EXE relocation\n");
2351 
2352         /* Change the protection to prepare for relocation */
2353         ViewBase = Peb->ImageBaseAddress;
2354         Status = LdrpSetProtection(ViewBase, FALSE);
2355         if (!NT_SUCCESS(Status)) return Status;
2356 
2357         /* Do the relocation */
2358         Status = LdrRelocateImageWithBias(ViewBase,
2359                                           0LL,
2360                                           NULL,
2361                                           STATUS_SUCCESS,
2362                                           STATUS_CONFLICTING_ADDRESSES,
2363                                           STATUS_INVALID_IMAGE_FORMAT);
2364         if (!NT_SUCCESS(Status))
2365         {
2366             DPRINT1("LdrRelocateImageWithBias() failed\n");
2367             return Status;
2368         }
2369 
2370         /* Check if a start context was provided */
2371         if (Context)
2372         {
2373             DPRINT1("WARNING: Relocated EXE Context");
2374             UNIMPLEMENTED; // We should support this
2375             return STATUS_INVALID_IMAGE_FORMAT;
2376         }
2377 
2378         /* Restore the protection */
2379         Status = LdrpSetProtection(ViewBase, TRUE);
2380         if (!NT_SUCCESS(Status)) return Status;
2381     }
2382 
2383     /* Lock the DLLs */
2384     ListHead = &Peb->Ldr->InLoadOrderModuleList;
2385     NextEntry = ListHead->Flink;
2386     while (ListHead != NextEntry)
2387     {
2388         NtLdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
2389         NtLdrEntry->LoadCount = -1;
2390         NextEntry = NextEntry->Flink;
2391     }
2392 
2393     /* Phase 0 is done */
2394     LdrpLdrDatabaseIsSetup = TRUE;
2395 
2396     /* Check whether all static imports were properly loaded and return here */
2397     if (!NT_SUCCESS(ImportStatus)) return ImportStatus;
2398 
2399     /* Initialize TLS */
2400     Status = LdrpInitializeTls();
2401     if (!NT_SUCCESS(Status))
2402     {
2403         DPRINT1("LDR: LdrpProcessInitialization failed to initialize TLS slots; status %x\n",
2404                 Status);
2405         return Status;
2406     }
2407 
2408     /* FIXME Mark the DLL Ranges for Stack Traces later */
2409 
2410     /* Notify the debugger now */
2411     if (Peb->BeingDebugged)
2412     {
2413         /* Break */
2414         DbgBreakPoint();
2415 
2416         /* Update show snaps again */
2417         ShowSnaps = Peb->NtGlobalFlag & FLG_SHOW_LDR_SNAPS;
2418     }
2419 
2420     /* Validate the Image for MP Usage */
2421     if (LdrpNumberOfProcessors > 1) LdrpValidateImageForMp(LdrpImageEntry);
2422 
2423     /* Check NX Options */
2424     if (SharedUserData->NXSupportPolicy == 1)
2425     {
2426         ExecuteOptions = 0xD;
2427     }
2428     else if (!SharedUserData->NXSupportPolicy)
2429     {
2430         ExecuteOptions = 0xA;
2431     }
2432 
2433     /* Let Mm know */
2434     ZwSetInformationProcess(NtCurrentProcess(),
2435                             ProcessExecuteFlags,
2436                             &ExecuteOptions,
2437                             sizeof(ULONG));
2438 
2439     // FIXME: Should be done by Application Compatibility features,
2440     // by reading the registry, etc...
2441     // For now, this is the old code from ntdll!RtlGetVersion().
2442     RtlInitEmptyUnicodeString(&Peb->CSDVersion, NULL, 0);
2443     if (((Peb->OSCSDVersion >> 8) & 0xFF) != 0)
2444     {
2445         WCHAR szCSDVersion[128];
2446         LONG i;
2447         USHORT Length = (USHORT)ARRAYSIZE(szCSDVersion) - 1;
2448         i = _snwprintf(szCSDVersion, Length,
2449                        L"Service Pack %d",
2450                        ((Peb->OSCSDVersion >> 8) & 0xFF));
2451         if (i < 0)
2452         {
2453             /* Null-terminate if it was overflowed */
2454             szCSDVersion[Length] = UNICODE_NULL;
2455         }
2456 
2457         Length *= sizeof(WCHAR);
2458         Peb->CSDVersion.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
2459                                                  0,
2460                                                  Length + sizeof(UNICODE_NULL));
2461         if (Peb->CSDVersion.Buffer)
2462         {
2463             Peb->CSDVersion.Length = Length;
2464             Peb->CSDVersion.MaximumLength = Length + sizeof(UNICODE_NULL);
2465 
2466             RtlCopyMemory(Peb->CSDVersion.Buffer,
2467                           szCSDVersion,
2468                           Peb->CSDVersion.MaximumLength);
2469             Peb->CSDVersion.Buffer[Peb->CSDVersion.Length / sizeof(WCHAR)] = UNICODE_NULL;
2470         }
2471     }
2472 
2473     /* Check if we had Shim Data */
2474     if (OldShimData)
2475     {
2476         /* Load the Shim Engine */
2477         Peb->AppCompatInfo = NULL;
2478         LdrpLoadShimEngine(OldShimData, &ImagePathName, OldShimData);
2479     }
2480     else
2481     {
2482         /* Check for Application Compatibility Goo */
2483         //LdrQueryApplicationCompatibilityGoo(hKey);
2484         DPRINT("Querying app compat hacks is missing!\n");
2485     }
2486 
2487     /*
2488      * FIXME: Check for special images, SecuROM, SafeDisc and other NX-
2489      * incompatible images.
2490      */
2491 
2492     /* Now call the Init Routines */
2493     Status = LdrpRunInitializeRoutines(Context);
2494     if (!NT_SUCCESS(Status))
2495     {
2496         DPRINT1("LDR: LdrpProcessInitialization failed running initialization routines; status %x\n",
2497                 Status);
2498         return Status;
2499     }
2500 
2501     /* Notify Shim Engine */
2502     if (g_ShimsEnabled)
2503     {
2504         VOID(NTAPI *SE_InstallAfterInit)(PUNICODE_STRING, PVOID);
2505         SE_InstallAfterInit = RtlDecodeSystemPointer(g_pfnSE_InstallAfterInit);
2506         SE_InstallAfterInit(&ImagePathName, OldShimData);
2507     }
2508 
2509     /* Check if we have a user-defined Post Process Routine */
2510     if (NT_SUCCESS(Status) && Peb->PostProcessInitRoutine)
2511     {
2512         /* Call it */
2513         Peb->PostProcessInitRoutine();
2514     }
2515 
2516     /* Close the key if we have one opened */
2517     if (OptionsKey) NtClose(OptionsKey);
2518 
2519     /* Return status */
2520     return Status;
2521 }
2522 
2523 VOID
2524 NTAPI
2525 LdrpInitFailure(NTSTATUS Status)
2526 {
2527     ULONG Response;
2528     PPEB Peb = NtCurrentPeb();
2529 
2530     /* Print a debug message */
2531     DPRINT1("LDR: Process initialization failure for %wZ; NTSTATUS = %08lx\n",
2532             &Peb->ProcessParameters->ImagePathName, Status);
2533 
2534     /* Raise a hard error */
2535     if (!LdrpFatalHardErrorCount)
2536     {
2537         ZwRaiseHardError(STATUS_APP_INIT_FAILURE, 1, 0, (PULONG_PTR)&Status, OptionOk, &Response);
2538     }
2539 }
2540 
2541 VOID
2542 NTAPI
2543 LdrpInit(PCONTEXT Context,
2544          PVOID SystemArgument1,
2545          PVOID SystemArgument2)
2546 {
2547     LARGE_INTEGER Timeout;
2548     PTEB Teb = NtCurrentTeb();
2549     NTSTATUS Status, LoaderStatus = STATUS_SUCCESS;
2550     MEMORY_BASIC_INFORMATION MemoryBasicInfo;
2551     PPEB Peb = NtCurrentPeb();
2552 
2553     DPRINT("LdrpInit() %p/%p\n",
2554         NtCurrentTeb()->RealClientId.UniqueProcess,
2555         NtCurrentTeb()->RealClientId.UniqueThread);
2556 
2557 #ifdef _WIN64
2558     /* Set the SList header usage */
2559     RtlpUse16ByteSLists = SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE128];
2560 #endif /* _WIN64 */
2561 
2562     /* Check if we have a deallocation stack */
2563     if (!Teb->DeallocationStack)
2564     {
2565         /* We don't, set one */
2566         Status = NtQueryVirtualMemory(NtCurrentProcess(),
2567                                       Teb->NtTib.StackLimit,
2568                                       MemoryBasicInformation,
2569                                       &MemoryBasicInfo,
2570                                       sizeof(MEMORY_BASIC_INFORMATION),
2571                                       NULL);
2572         if (!NT_SUCCESS(Status))
2573         {
2574             /* Fail */
2575             LdrpInitFailure(Status);
2576             RtlRaiseStatus(Status);
2577             return;
2578         }
2579 
2580         /* Set the stack */
2581         Teb->DeallocationStack = MemoryBasicInfo.AllocationBase;
2582     }
2583 
2584     /* Now check if the process is already being initialized */
2585     while (_InterlockedCompareExchange(&LdrpProcessInitialized,
2586                                       1,
2587                                       0) == 1)
2588     {
2589         /* Set the timeout to 30 milliseconds */
2590         Timeout.QuadPart = Int32x32To64(30, -10000);
2591 
2592         /* Make sure the status hasn't changed */
2593         while (LdrpProcessInitialized == 1)
2594         {
2595             /* Do the wait */
2596             ZwDelayExecution(FALSE, &Timeout);
2597         }
2598     }
2599 
2600     /* Check if we have already setup LDR data */
2601     if (!Peb->Ldr)
2602     {
2603         /* Setup the Loader Lock */
2604         Peb->LoaderLock = &LdrpLoaderLock;
2605 
2606         /* Let other code know we're initializing */
2607         LdrpInLdrInit = TRUE;
2608 
2609         /* Protect with SEH */
2610         _SEH2_TRY
2611         {
2612             /* Initialize the Process */
2613             LoaderStatus = LdrpInitializeProcess(Context,
2614                                                  SystemArgument1);
2615 
2616             /* Check for success and if MinimumStackCommit was requested */
2617             if (NT_SUCCESS(LoaderStatus) && Peb->MinimumStackCommit)
2618             {
2619                 /* Enforce the limit */
2620                 //LdrpTouchThreadStack(Peb->MinimumStackCommit);
2621                 UNIMPLEMENTED;
2622             }
2623         }
2624         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2625         {
2626             /* Fail with the SEH error */
2627             LoaderStatus = _SEH2_GetExceptionCode();
2628         }
2629         _SEH2_END;
2630 
2631         /* We're not initializing anymore */
2632         LdrpInLdrInit = FALSE;
2633 
2634         /* Check if init worked */
2635         if (NT_SUCCESS(LoaderStatus))
2636         {
2637             /* Set the process as Initialized */
2638             _InterlockedIncrement(&LdrpProcessInitialized);
2639         }
2640     }
2641     else
2642     {
2643         /* Loader data is there... is this a fork() ? */
2644         if(Peb->InheritedAddressSpace)
2645         {
2646             /* Handle the fork() */
2647             //LoaderStatus = LdrpForkProcess();
2648             LoaderStatus = STATUS_NOT_IMPLEMENTED;
2649             UNIMPLEMENTED;
2650         }
2651         else
2652         {
2653             /* This is a new thread initializing */
2654             LdrpInitializeThread(Context);
2655         }
2656     }
2657 
2658     /* All done, test alert the thread */
2659     NtTestAlert();
2660 
2661     /* Return */
2662     if (!NT_SUCCESS(LoaderStatus))
2663     {
2664         /* Fail */
2665         LdrpInitFailure(LoaderStatus);
2666         RtlRaiseStatus(LoaderStatus);
2667     }
2668 }
2669 
2670 /* EOF */
2671