[LDR] Check forwarded imports against the manifest before trying to load them
[reactos.git] / dll / ntdll / ldr / ldrinit.c
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(void);
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 VOID
1541 NTAPI
1542 LdrpInitializeProcessCompat(PVOID* pOldShimData)
1543 {
1544 static const GUID* GuidOrder[] = { &COMPAT_GUID_WIN10, &COMPAT_GUID_WIN81, &COMPAT_GUID_WIN8,
1545 &COMPAT_GUID_WIN7, &COMPAT_GUID_VISTA };
1546 static const DWORD GuidVersions[] = { WINVER_WIN10, WINVER_WIN81, WINVER_WIN8, WINVER_WIN7, WINVER_VISTA };
1547
1548 ULONG Buffer[(sizeof(COMPATIBILITY_CONTEXT_ELEMENT) * 10 + sizeof(ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION)) / sizeof(ULONG)];
1549 ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION* ContextCompatInfo;
1550 SIZE_T SizeRequired;
1551 NTSTATUS Status;
1552 DWORD n, cur;
1553 ReactOS_ShimData* pShimData = *pOldShimData;
1554
1555 C_ASSERT(RTL_NUMBER_OF(GuidOrder) == RTL_NUMBER_OF(GuidVersions));
1556
1557 if (pShimData)
1558 {
1559 if (pShimData->dwMagic != REACTOS_SHIMDATA_MAGIC ||
1560 pShimData->dwSize != sizeof(ReactOS_ShimData))
1561 {
1562 DPRINT1("LdrpInitializeProcessCompat: Corrupt pShimData (0x%x, %u)\n", pShimData->dwMagic, pShimData->dwSize);
1563 return;
1564 }
1565 if (pShimData->dwRosProcessCompatVersion)
1566 {
1567 DPRINT1("LdrpInitializeProcessCompat: ProcessCompatVersion already set to 0x%x\n", pShimData->dwRosProcessCompatVersion);
1568 return;
1569 }
1570 }
1571
1572 SizeRequired = sizeof(Buffer);
1573 Status = RtlQueryInformationActivationContext(RTL_QUERY_ACTIVATION_CONTEXT_FLAG_NO_ADDREF,
1574 NULL,
1575 NULL,
1576 CompatibilityInformationInActivationContext,
1577 Buffer,
1578 sizeof(Buffer),
1579 &SizeRequired);
1580
1581 if (!NT_SUCCESS(Status))
1582 {
1583 DPRINT1("LdrpInitializeProcessCompat: Unable to query process actctx with status %x\n", Status);
1584 return;
1585 }
1586
1587 ContextCompatInfo = (ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*)Buffer;
1588 /* No Compatibility elements present, bail out */
1589 if (ContextCompatInfo->ElementCount == 0)
1590 return;
1591
1592 /* Search for known GUID's, starting from newest to oldest. */
1593 for (cur = 0; cur < RTL_NUMBER_OF(GuidOrder); ++cur)
1594 {
1595 for (n = 0; n < ContextCompatInfo->ElementCount; ++n)
1596 {
1597 if (ContextCompatInfo->Elements[n].Type == ACTCX_COMPATIBILITY_ELEMENT_TYPE_OS &&
1598 RtlCompareMemory(&ContextCompatInfo->Elements[n].Id, GuidOrder[cur], sizeof(GUID)) == sizeof(GUID))
1599 {
1600 /* If this process did not need shim data before, allocate and store it */
1601 if (pShimData == NULL)
1602 {
1603 PPEB Peb = NtCurrentPeb();
1604
1605 ASSERT(Peb->pShimData == NULL);
1606 pShimData = RtlAllocateHeap(Peb->ProcessHeap, HEAP_ZERO_MEMORY, sizeof(*pShimData));
1607
1608 if (!pShimData)
1609 {
1610 DPRINT1("LdrpInitializeProcessCompat: Unable to allocated %u bytes\n", sizeof(*pShimData));
1611 return;
1612 }
1613
1614 pShimData->dwSize = sizeof(*pShimData);
1615 pShimData->dwMagic = REACTOS_SHIMDATA_MAGIC;
1616
1617 Peb->pShimData = pShimData;
1618 *pOldShimData = pShimData;
1619 }
1620
1621 /* Store the highest found version, and bail out. */
1622 pShimData->dwRosProcessCompatVersion = GuidVersions[cur];
1623 DPRINT1("LdrpInitializeProcessCompat: Found guid for winver 0x%x\n", GuidVersions[cur]);
1624 return;
1625 }
1626 }
1627 }
1628 }
1629
1630 VOID
1631 NTAPI
1632 LdrpInitializeDotLocalSupport(PRTL_USER_PROCESS_PARAMETERS ProcessParameters)
1633 {
1634 UNICODE_STRING ImagePathName = ProcessParameters->ImagePathName;
1635 WCHAR LocalBuffer[MAX_PATH];
1636 UNICODE_STRING DotLocal;
1637 NTSTATUS Status;
1638 ULONG RequiredSize;
1639
1640 RequiredSize = ImagePathName.Length + LdrpDotLocal.Length + sizeof(UNICODE_NULL);
1641 if (RequiredSize <= sizeof(LocalBuffer))
1642 {
1643 RtlInitEmptyUnicodeString(&DotLocal, LocalBuffer, sizeof(LocalBuffer));
1644 }
1645 else if (RequiredSize <= UNICODE_STRING_MAX_BYTES)
1646 {
1647 DotLocal.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, RequiredSize);
1648 DotLocal.Length = 0;
1649 DotLocal.MaximumLength = RequiredSize;
1650 if (!DotLocal.Buffer)
1651 DPRINT1("LDR: Failed to allocate memory for .local check\n");
1652 }
1653 else
1654 {
1655 DotLocal.Buffer = NULL;
1656 DotLocal.Length = 0;
1657 DotLocal.MaximumLength = 0;
1658 DPRINT1("LDR: String too big for .local check\n");
1659 }
1660
1661 if (DotLocal.Buffer)
1662 {
1663 Status = RtlAppendUnicodeStringToString(&DotLocal, &ImagePathName);
1664 ASSERT(NT_SUCCESS(Status));
1665 if (NT_SUCCESS(Status))
1666 {
1667 Status = RtlAppendUnicodeStringToString(&DotLocal, &LdrpDotLocal);
1668 ASSERT(NT_SUCCESS(Status));
1669 }
1670
1671 if (NT_SUCCESS(Status))
1672 {
1673 if (RtlDoesFileExists_UStr(&DotLocal))
1674 {
1675 ProcessParameters->Flags |= RTL_USER_PROCESS_PARAMETERS_PRIVATE_DLL_PATH;
1676 }
1677 }
1678 else
1679 {
1680 DPRINT1("LDR: Failed to append: 0x%lx\n", Status);
1681 }
1682
1683 if (DotLocal.Buffer != LocalBuffer)
1684 {
1685 RtlFreeHeap(RtlGetProcessHeap(), 0, DotLocal.Buffer);
1686 }
1687 }
1688 }
1689
1690
1691 NTSTATUS
1692 NTAPI
1693 LdrpInitializeProcess(IN PCONTEXT Context,
1694 IN PVOID SystemArgument1)
1695 {
1696 RTL_HEAP_PARAMETERS HeapParameters;
1697 ULONG ComSectionSize;
1698 ANSI_STRING BaseProcessInitPostImportName = RTL_CONSTANT_STRING("BaseProcessInitPostImport");
1699 ANSI_STRING BaseQueryModuleDataName = RTL_CONSTANT_STRING("BaseQueryModuleData");
1700 PVOID OldShimData;
1701 OBJECT_ATTRIBUTES ObjectAttributes;
1702 //UNICODE_STRING LocalFileName, FullImageName;
1703 HANDLE SymLinkHandle;
1704 //ULONG DebugHeapOnly;
1705 UNICODE_STRING CommandLine, NtSystemRoot, ImagePathName, FullPath, ImageFileName, KnownDllString;
1706 PPEB Peb = NtCurrentPeb();
1707 BOOLEAN IsDotNetImage = FALSE;
1708 BOOLEAN FreeCurDir = FALSE;
1709 //HANDLE CompatKey;
1710 PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
1711 //LPWSTR ImagePathBuffer;
1712 ULONG ConfigSize;
1713 UNICODE_STRING CurrentDirectory;
1714 HANDLE OptionsKey;
1715 ULONG HeapFlags;
1716 PIMAGE_NT_HEADERS NtHeader;
1717 LPWSTR NtDllName = NULL;
1718 NTSTATUS Status, ImportStatus;
1719 NLSTABLEINFO NlsTable;
1720 PIMAGE_LOAD_CONFIG_DIRECTORY LoadConfig;
1721 PTEB Teb = NtCurrentTeb();
1722 PLIST_ENTRY ListHead;
1723 PLIST_ENTRY NextEntry;
1724 ULONG i;
1725 PWSTR ImagePath;
1726 ULONG DebugProcessHeapOnly = 0;
1727 PLDR_DATA_TABLE_ENTRY NtLdrEntry;
1728 PWCHAR Current;
1729 ULONG ExecuteOptions = 0;
1730 PVOID ViewBase;
1731
1732 /* Set a NULL SEH Filter */
1733 RtlSetUnhandledExceptionFilter(NULL);
1734
1735 /* Get the image path */
1736 ImagePath = Peb->ProcessParameters->ImagePathName.Buffer;
1737
1738 /* Check if it's not normalized */
1739 if (!(Peb->ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_NORMALIZED))
1740 {
1741 /* Normalize it*/
1742 ImagePath = (PWSTR)((ULONG_PTR)ImagePath + (ULONG_PTR)Peb->ProcessParameters);
1743 }
1744
1745 /* Create a unicode string for the Image Path */
1746 ImagePathName.Length = Peb->ProcessParameters->ImagePathName.Length;
1747 ImagePathName.MaximumLength = ImagePathName.Length + sizeof(WCHAR);
1748 ImagePathName.Buffer = ImagePath;
1749
1750 /* Get the NT Headers */
1751 NtHeader = RtlImageNtHeader(Peb->ImageBaseAddress);
1752
1753 /* Get the execution options */
1754 Status = LdrpInitializeExecutionOptions(&ImagePathName, Peb, &OptionsKey);
1755
1756 /* Check if this is a .NET executable */
1757 if (RtlImageDirectoryEntryToData(Peb->ImageBaseAddress,
1758 TRUE,
1759 IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR,
1760 &ComSectionSize))
1761 {
1762 /* Remember this for later */
1763 IsDotNetImage = TRUE;
1764 }
1765
1766 /* Save the NTDLL Base address */
1767 NtDllBase = SystemArgument1;
1768
1769 /* If this is a Native Image */
1770 if (NtHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_NATIVE)
1771 {
1772 /* Then do DLL Validation */
1773 LdrpDllValidation = TRUE;
1774 }
1775
1776 /* Save the old Shim Data */
1777 OldShimData = Peb->pShimData;
1778
1779 /* ReactOS specific: do not clear it. (Windows starts doing the same in later versions) */
1780 //Peb->pShimData = NULL;
1781
1782 /* Save the number of processors and CS Timeout */
1783 LdrpNumberOfProcessors = Peb->NumberOfProcessors;
1784 RtlpTimeout = Peb->CriticalSectionTimeout;
1785
1786 /* Normalize the parameters */
1787 ProcessParameters = RtlNormalizeProcessParams(Peb->ProcessParameters);
1788 if (ProcessParameters)
1789 {
1790 /* Save the Image and Command Line Names */
1791 ImageFileName = ProcessParameters->ImagePathName;
1792 CommandLine = ProcessParameters->CommandLine;
1793 }
1794 else
1795 {
1796 /* It failed, initialize empty strings */
1797 RtlInitUnicodeString(&ImageFileName, NULL);
1798 RtlInitUnicodeString(&CommandLine, NULL);
1799 }
1800
1801 /* Initialize NLS data */
1802 RtlInitNlsTables(Peb->AnsiCodePageData,
1803 Peb->OemCodePageData,
1804 Peb->UnicodeCaseTableData,
1805 &NlsTable);
1806
1807 /* Reset NLS Translations */
1808 RtlResetRtlTranslations(&NlsTable);
1809
1810 /* Get the Image Config Directory */
1811 LoadConfig = RtlImageDirectoryEntryToData(Peb->ImageBaseAddress,
1812 TRUE,
1813 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
1814 &ConfigSize);
1815
1816 /* Setup the Heap Parameters */
1817 RtlZeroMemory(&HeapParameters, sizeof(HeapParameters));
1818 HeapFlags = HEAP_GROWABLE;
1819 HeapParameters.Length = sizeof(HeapParameters);
1820
1821 /* Check if we have Configuration Data */
1822 if ((LoadConfig) && (ConfigSize == sizeof(IMAGE_LOAD_CONFIG_DIRECTORY)))
1823 {
1824 /* FIXME: Custom heap settings and misc. */
1825 DPRINT1("We don't support LOAD_CONFIG data yet\n");
1826 }
1827
1828 /* Check for custom affinity mask */
1829 if (Peb->ImageProcessAffinityMask)
1830 {
1831 /* Set it */
1832 Status = NtSetInformationProcess(NtCurrentProcess(),
1833 ProcessAffinityMask,
1834 &Peb->ImageProcessAffinityMask,
1835 sizeof(Peb->ImageProcessAffinityMask));
1836 }
1837
1838 /* Check if verbose debugging (ShowSnaps) was requested */
1839 ShowSnaps = Peb->NtGlobalFlag & FLG_SHOW_LDR_SNAPS;
1840
1841 /* Start verbose debugging messages right now if they were requested */
1842 if (ShowSnaps)
1843 {
1844 DPRINT1("LDR: PID: 0x%p started - '%wZ'\n",
1845 Teb->ClientId.UniqueProcess,
1846 &CommandLine);
1847 }
1848
1849 /* If the timeout is too long */
1850 if (RtlpTimeout.QuadPart < Int32x32To64(3600, -10000000))
1851 {
1852 /* Then disable CS Timeout */
1853 RtlpTimeoutDisable = TRUE;
1854 }
1855
1856 /* Initialize Critical Section Data */
1857 RtlpInitDeferedCriticalSection();
1858
1859 /* Initialize VEH Call lists */
1860 RtlpInitializeVectoredExceptionHandling();
1861
1862 /* Set TLS/FLS Bitmap data */
1863 Peb->FlsBitmap = &FlsBitMap;
1864 Peb->TlsBitmap = &TlsBitMap;
1865 Peb->TlsExpansionBitmap = &TlsExpansionBitMap;
1866
1867 /* Initialize FLS Bitmap */
1868 RtlInitializeBitMap(&FlsBitMap,
1869 Peb->FlsBitmapBits,
1870 FLS_MAXIMUM_AVAILABLE);
1871 RtlSetBit(&FlsBitMap, 0);
1872 InitializeListHead(&Peb->FlsListHead);
1873
1874 /* Initialize TLS Bitmap */
1875 RtlInitializeBitMap(&TlsBitMap,
1876 Peb->TlsBitmapBits,
1877 TLS_MINIMUM_AVAILABLE);
1878 RtlSetBit(&TlsBitMap, 0);
1879 RtlInitializeBitMap(&TlsExpansionBitMap,
1880 Peb->TlsExpansionBitmapBits,
1881 TLS_EXPANSION_SLOTS);
1882 RtlSetBit(&TlsExpansionBitMap, 0);
1883
1884 /* Initialize the Hash Table */
1885 for (i = 0; i < LDR_HASH_TABLE_ENTRIES; i++)
1886 {
1887 InitializeListHead(&LdrpHashTable[i]);
1888 }
1889
1890 /* Initialize the Loader Lock */
1891 // FIXME: What's the point of initing it manually, if two lines lower
1892 // a call to RtlInitializeCriticalSection() is being made anyway?
1893 //InsertTailList(&RtlCriticalSectionList, &LdrpLoaderLock.DebugInfo->ProcessLocksList);
1894 //LdrpLoaderLock.DebugInfo->CriticalSection = &LdrpLoaderLock;
1895 RtlInitializeCriticalSection(&LdrpLoaderLock);
1896 LdrpLoaderLockInit = TRUE;
1897
1898 /* Check if User Stack Trace Database support was requested */
1899 if (Peb->NtGlobalFlag & FLG_USER_STACK_TRACE_DB)
1900 {
1901 DPRINT1("We don't support user stack trace databases yet\n");
1902 }
1903
1904 /* Setup Fast PEB Lock */
1905 RtlInitializeCriticalSection(&FastPebLock);
1906 Peb->FastPebLock = &FastPebLock;
1907 //Peb->FastPebLockRoutine = (PPEBLOCKROUTINE)RtlEnterCriticalSection;
1908 //Peb->FastPebUnlockRoutine = (PPEBLOCKROUTINE)RtlLeaveCriticalSection;
1909
1910 /* Setup Callout Lock and Notification list */
1911 //RtlInitializeCriticalSection(&RtlpCalloutEntryLock);
1912 InitializeListHead(&LdrpDllNotificationList);
1913
1914 /* For old executables, use 16-byte aligned heap */
1915 if ((NtHeader->OptionalHeader.MajorSubsystemVersion <= 3) &&
1916 (NtHeader->OptionalHeader.MinorSubsystemVersion < 51))
1917 {
1918 HeapFlags |= HEAP_CREATE_ALIGN_16;
1919 }
1920
1921 /* Setup the Heap */
1922 RtlInitializeHeapManager();
1923 Peb->ProcessHeap = RtlCreateHeap(HeapFlags,
1924 NULL,
1925 NtHeader->OptionalHeader.SizeOfHeapReserve,
1926 NtHeader->OptionalHeader.SizeOfHeapCommit,
1927 NULL,
1928 &HeapParameters);
1929
1930 if (!Peb->ProcessHeap)
1931 {
1932 DPRINT1("Failed to create process heap\n");
1933 return STATUS_NO_MEMORY;
1934 }
1935
1936 /* Allocate an Activation Context Stack */
1937 Status = RtlAllocateActivationContextStack(&Teb->ActivationContextStackPointer);
1938 if (!NT_SUCCESS(Status)) return Status;
1939
1940 RtlZeroMemory(&HeapParameters, sizeof(HeapParameters));
1941 HeapFlags = HEAP_GROWABLE | HEAP_CLASS_1;
1942 HeapParameters.Length = sizeof(HeapParameters);
1943 LdrpHeap = RtlCreateHeap(HeapFlags, 0, 0x10000, 0x6000, 0, &HeapParameters);
1944 if (!LdrpHeap)
1945 {
1946 DPRINT1("Failed to create loader private heap\n");
1947 return STATUS_NO_MEMORY;
1948 }
1949
1950 /* Check for Debug Heap */
1951 if (OptionsKey)
1952 {
1953 /* Query the setting */
1954 Status = LdrQueryImageFileKeyOption(OptionsKey,
1955 L"DebugProcessHeapOnly",
1956 REG_DWORD,
1957 &DebugProcessHeapOnly,
1958 sizeof(ULONG),
1959 NULL);
1960
1961 if (NT_SUCCESS(Status))
1962 {
1963 /* Reset DPH if requested */
1964 if (RtlpPageHeapEnabled && DebugProcessHeapOnly)
1965 {
1966 RtlpDphGlobalFlags &= ~DPH_FLAG_DLL_NOTIFY;
1967 RtlpPageHeapEnabled = FALSE;
1968 }
1969 }
1970 }
1971
1972 /* Build the NTDLL Path */
1973 FullPath.Buffer = StringBuffer;
1974 FullPath.Length = 0;
1975 FullPath.MaximumLength = sizeof(StringBuffer);
1976 RtlInitUnicodeString(&NtSystemRoot, SharedUserData->NtSystemRoot);
1977 RtlAppendUnicodeStringToString(&FullPath, &NtSystemRoot);
1978 RtlAppendUnicodeToString(&FullPath, L"\\System32\\");
1979
1980 /* Open the Known DLLs directory */
1981 RtlInitUnicodeString(&KnownDllString, L"\\KnownDlls");
1982 InitializeObjectAttributes(&ObjectAttributes,
1983 &KnownDllString,
1984 OBJ_CASE_INSENSITIVE,
1985 NULL,
1986 NULL);
1987 Status = ZwOpenDirectoryObject(&LdrpKnownDllObjectDirectory,
1988 DIRECTORY_QUERY | DIRECTORY_TRAVERSE,
1989 &ObjectAttributes);
1990
1991 /* Check if it exists */
1992 if (NT_SUCCESS(Status))
1993 {
1994 /* Open the Known DLLs Path */
1995 RtlInitUnicodeString(&KnownDllString, L"KnownDllPath");
1996 InitializeObjectAttributes(&ObjectAttributes,
1997 &KnownDllString,
1998 OBJ_CASE_INSENSITIVE,
1999 LdrpKnownDllObjectDirectory,
2000 NULL);
2001 Status = NtOpenSymbolicLinkObject(&SymLinkHandle,
2002 SYMBOLIC_LINK_QUERY,
2003 &ObjectAttributes);
2004 if (NT_SUCCESS(Status))
2005 {
2006 /* Query the path */
2007 LdrpKnownDllPath.Length = 0;
2008 LdrpKnownDllPath.MaximumLength = sizeof(LdrpKnownDllPathBuffer);
2009 LdrpKnownDllPath.Buffer = LdrpKnownDllPathBuffer;
2010 Status = ZwQuerySymbolicLinkObject(SymLinkHandle, &LdrpKnownDllPath, NULL);
2011 NtClose(SymLinkHandle);
2012 if (!NT_SUCCESS(Status))
2013 {
2014 DPRINT1("LDR: %s - failed call to ZwQuerySymbolicLinkObject with status %x\n", "", Status);
2015 return Status;
2016 }
2017 }
2018 }
2019
2020 /* Check if we failed */
2021 if (!NT_SUCCESS(Status))
2022 {
2023 /* Assume System32 */
2024 LdrpKnownDllObjectDirectory = NULL;
2025 RtlInitUnicodeString(&LdrpKnownDllPath, StringBuffer);
2026 LdrpKnownDllPath.Length -= sizeof(WCHAR);
2027 }
2028
2029 /* If we have process parameters, get the default path and current path */
2030 if (ProcessParameters)
2031 {
2032 /* Check if we have a Dll Path */
2033 if (ProcessParameters->DllPath.Length)
2034 {
2035 /* Get the path */
2036 LdrpDefaultPath = *(PUNICODE_STRING)&ProcessParameters->DllPath;
2037 }
2038 else
2039 {
2040 /* We need a valid path */
2041 DPRINT1("No valid DllPath was given!\n");
2042 LdrpInitFailure(STATUS_INVALID_PARAMETER);
2043 }
2044
2045 /* Set the current directory */
2046 CurrentDirectory = ProcessParameters->CurrentDirectory.DosPath;
2047
2048 /* Check if it's empty or invalid */
2049 if ((!CurrentDirectory.Buffer) ||
2050 (CurrentDirectory.Buffer[0] == UNICODE_NULL) ||
2051 (!CurrentDirectory.Length))
2052 {
2053 /* Allocate space for the buffer */
2054 CurrentDirectory.Buffer = RtlAllocateHeap(Peb->ProcessHeap,
2055 0,
2056 3 * sizeof(WCHAR) +
2057 sizeof(UNICODE_NULL));
2058 if (!CurrentDirectory.Buffer)
2059 {
2060 DPRINT1("LDR: LdrpInitializeProcess - unable to allocate current working directory buffer\n");
2061 // FIXME: And what?
2062 }
2063
2064 /* Copy the drive of the system root */
2065 RtlMoveMemory(CurrentDirectory.Buffer,
2066 SharedUserData->NtSystemRoot,
2067 3 * sizeof(WCHAR));
2068 CurrentDirectory.Buffer[3] = UNICODE_NULL;
2069 CurrentDirectory.Length = 3 * sizeof(WCHAR);
2070 CurrentDirectory.MaximumLength = CurrentDirectory.Length + sizeof(WCHAR);
2071
2072 FreeCurDir = TRUE;
2073 DPRINT("Using dynamically allocd curdir\n");
2074 }
2075 else
2076 {
2077 /* Use the local buffer */
2078 DPRINT("Using local system root\n");
2079 }
2080 }
2081
2082 /* Setup Loader Data */
2083 Peb->Ldr = &PebLdr;
2084 InitializeListHead(&PebLdr.InLoadOrderModuleList);
2085 InitializeListHead(&PebLdr.InMemoryOrderModuleList);
2086 InitializeListHead(&PebLdr.InInitializationOrderModuleList);
2087 PebLdr.Length = sizeof(PEB_LDR_DATA);
2088 PebLdr.Initialized = TRUE;
2089
2090 /* Allocate a data entry for the Image */
2091 LdrpImageEntry = LdrpAllocateDataTableEntry(Peb->ImageBaseAddress);
2092
2093 /* Set it up */
2094 LdrpImageEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(LdrpImageEntry->DllBase);
2095 LdrpImageEntry->LoadCount = -1;
2096 LdrpImageEntry->EntryPointActivationContext = 0;
2097 LdrpImageEntry->FullDllName = ImageFileName;
2098
2099 if (IsDotNetImage)
2100 LdrpImageEntry->Flags = LDRP_COR_IMAGE;
2101 else
2102 LdrpImageEntry->Flags = 0;
2103
2104 /* Check if the name is empty */
2105 if (!ImageFileName.Buffer[0])
2106 {
2107 /* Use the same Base name */
2108 LdrpImageEntry->BaseDllName = LdrpImageEntry->FullDllName;
2109 }
2110 else
2111 {
2112 /* Find the last slash */
2113 Current = ImageFileName.Buffer;
2114 while (*Current)
2115 {
2116 if (*Current++ == '\\')
2117 {
2118 /* Set this path */
2119 NtDllName = Current;
2120 }
2121 }
2122
2123 /* Did we find anything? */
2124 if (!NtDllName)
2125 {
2126 /* Use the same Base name */
2127 LdrpImageEntry->BaseDllName = LdrpImageEntry->FullDllName;
2128 }
2129 else
2130 {
2131 /* Setup the name */
2132 LdrpImageEntry->BaseDllName.Length = (USHORT)((ULONG_PTR)ImageFileName.Buffer + ImageFileName.Length - (ULONG_PTR)NtDllName);
2133 LdrpImageEntry->BaseDllName.MaximumLength = LdrpImageEntry->BaseDllName.Length + sizeof(WCHAR);
2134 LdrpImageEntry->BaseDllName.Buffer = (PWSTR)((ULONG_PTR)ImageFileName.Buffer +
2135 (ImageFileName.Length - LdrpImageEntry->BaseDllName.Length));
2136 }
2137 }
2138
2139 /* Processing done, insert it */
2140 LdrpInsertMemoryTableEntry(LdrpImageEntry);
2141 LdrpImageEntry->Flags |= LDRP_ENTRY_PROCESSED;
2142
2143 /* Now add an entry for NTDLL */
2144 NtLdrEntry = LdrpAllocateDataTableEntry(SystemArgument1);
2145 NtLdrEntry->Flags = LDRP_IMAGE_DLL;
2146 NtLdrEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(NtLdrEntry->DllBase);
2147 NtLdrEntry->LoadCount = -1;
2148 NtLdrEntry->EntryPointActivationContext = 0;
2149
2150 NtLdrEntry->FullDllName.Length = FullPath.Length;
2151 NtLdrEntry->FullDllName.MaximumLength = FullPath.MaximumLength;
2152 NtLdrEntry->FullDllName.Buffer = StringBuffer;
2153 RtlAppendUnicodeStringToString(&NtLdrEntry->FullDllName, &NtDllString);
2154
2155 NtLdrEntry->BaseDllName.Length = NtDllString.Length;
2156 NtLdrEntry->BaseDllName.MaximumLength = NtDllString.MaximumLength;
2157 NtLdrEntry->BaseDllName.Buffer = NtDllString.Buffer;
2158
2159 /* Processing done, insert it */
2160 LdrpNtDllDataTableEntry = NtLdrEntry;
2161 LdrpInsertMemoryTableEntry(NtLdrEntry);
2162
2163 /* Let the world know */
2164 if (ShowSnaps)
2165 {
2166 DPRINT1("LDR: NEW PROCESS\n");
2167 DPRINT1(" Image Path: %wZ (%wZ)\n", &LdrpImageEntry->FullDllName, &LdrpImageEntry->BaseDllName);
2168 DPRINT1(" Current Directory: %wZ\n", &CurrentDirectory);
2169 DPRINT1(" Search Path: %wZ\n", &LdrpDefaultPath);
2170 }
2171
2172 /* Link the Init Order List */
2173 InsertHeadList(&Peb->Ldr->InInitializationOrderModuleList,
2174 &LdrpNtDllDataTableEntry->InInitializationOrderLinks);
2175
2176 /* Initialize Wine's active context implementation for the current process */
2177 actctx_init();
2178
2179 /* ReactOS specific */
2180 LdrpInitializeProcessCompat(&OldShimData);
2181
2182 /* Set the current directory */
2183 Status = RtlSetCurrentDirectory_U(&CurrentDirectory);
2184 if (!NT_SUCCESS(Status))
2185 {
2186 /* We failed, check if we should free it */
2187 if (FreeCurDir) RtlFreeUnicodeString(&CurrentDirectory);
2188
2189 /* Set it to the NT Root */
2190 CurrentDirectory = NtSystemRoot;
2191 RtlSetCurrentDirectory_U(&CurrentDirectory);
2192 }
2193 else
2194 {
2195 /* We're done with it, free it */
2196 if (FreeCurDir) RtlFreeUnicodeString(&CurrentDirectory);
2197 }
2198
2199 /* Check if we should look for a .local file */
2200 if (ProcessParameters && !(ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_LOCAL_DLL_PATH))
2201 {
2202 LdrpInitializeDotLocalSupport(ProcessParameters);
2203 }
2204
2205 /* Check if the Application Verifier was enabled */
2206 if (Peb->NtGlobalFlag & FLG_APPLICATION_VERIFIER)
2207 {
2208 Status = AVrfInitializeVerifier();
2209 if (!NT_SUCCESS(Status))
2210 {
2211 DPRINT1("LDR: AVrfInitializeVerifier failed (ntstatus 0x%x)\n", Status);
2212 return Status;
2213 }
2214
2215 }
2216
2217 if (IsDotNetImage)
2218 {
2219 /* FIXME */
2220 DPRINT1("We don't support .NET applications yet\n");
2221 }
2222
2223 if (NtHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI ||
2224 NtHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI)
2225 {
2226 PVOID Kernel32BaseAddress;
2227 PVOID FunctionAddress;
2228
2229 Status = LdrLoadDll(NULL, NULL, &Kernel32String, &Kernel32BaseAddress);
2230
2231 if (!NT_SUCCESS(Status))
2232 {
2233 if (ShowSnaps)
2234 DPRINT1("LDR: Unable to load %wZ, Status=0x%08lx\n", &Kernel32String, Status);
2235 return Status;
2236 }
2237
2238 Status = LdrGetProcedureAddress(Kernel32BaseAddress,
2239 &BaseProcessInitPostImportName,
2240 0,
2241 &FunctionAddress);
2242
2243 if (!NT_SUCCESS(Status))
2244 {
2245 if (ShowSnaps)
2246 DPRINT1("LDR: Unable to find post-import process init function, Status=0x%08lx\n", &Kernel32String, Status);
2247 return Status;
2248 }
2249 Kernel32ProcessInitPostImportFunction = FunctionAddress;
2250
2251 Status = LdrGetProcedureAddress(Kernel32BaseAddress,
2252 &BaseQueryModuleDataName,
2253 0,
2254 &FunctionAddress);
2255
2256 if (!NT_SUCCESS(Status))
2257 {
2258 if (ShowSnaps)
2259 DPRINT1("LDR: Unable to find BaseQueryModuleData, Status=0x%08lx\n", &Kernel32String, Status);
2260 return Status;
2261 }
2262 Kernel32BaseQueryModuleData = FunctionAddress;
2263 }
2264
2265 /* Walk the IAT and load all the DLLs */
2266 ImportStatus = LdrpWalkImportDescriptor(LdrpDefaultPath.Buffer, LdrpImageEntry);
2267
2268 /* Check if relocation is needed */
2269 if (Peb->ImageBaseAddress != (PVOID)NtHeader->OptionalHeader.ImageBase)
2270 {
2271 DPRINT1("LDR: Performing EXE relocation\n");
2272
2273 /* Change the protection to prepare for relocation */
2274 ViewBase = Peb->ImageBaseAddress;
2275 Status = LdrpSetProtection(ViewBase, FALSE);
2276 if (!NT_SUCCESS(Status)) return Status;
2277
2278 /* Do the relocation */
2279 Status = LdrRelocateImageWithBias(ViewBase,
2280 0LL,
2281 NULL,
2282 STATUS_SUCCESS,
2283 STATUS_CONFLICTING_ADDRESSES,
2284 STATUS_INVALID_IMAGE_FORMAT);
2285 if (!NT_SUCCESS(Status))
2286 {
2287 DPRINT1("LdrRelocateImageWithBias() failed\n");
2288 return Status;
2289 }
2290
2291 /* Check if a start context was provided */
2292 if (Context)
2293 {
2294 DPRINT1("WARNING: Relocated EXE Context");
2295 UNIMPLEMENTED; // We should support this
2296 return STATUS_INVALID_IMAGE_FORMAT;
2297 }
2298
2299 /* Restore the protection */
2300 Status = LdrpSetProtection(ViewBase, TRUE);
2301 if (!NT_SUCCESS(Status)) return Status;
2302 }
2303
2304 /* Lock the DLLs */
2305 ListHead = &Peb->Ldr->InLoadOrderModuleList;
2306 NextEntry = ListHead->Flink;
2307 while (ListHead != NextEntry)
2308 {
2309 NtLdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
2310 NtLdrEntry->LoadCount = -1;
2311 NextEntry = NextEntry->Flink;
2312 }
2313
2314 /* Phase 0 is done */
2315 LdrpLdrDatabaseIsSetup = TRUE;
2316
2317 /* Check whether all static imports were properly loaded and return here */
2318 if (!NT_SUCCESS(ImportStatus)) return ImportStatus;
2319
2320 /* Initialize TLS */
2321 Status = LdrpInitializeTls();
2322 if (!NT_SUCCESS(Status))
2323 {
2324 DPRINT1("LDR: LdrpProcessInitialization failed to initialize TLS slots; status %x\n",
2325 Status);
2326 return Status;
2327 }
2328
2329 /* FIXME Mark the DLL Ranges for Stack Traces later */
2330
2331 /* Notify the debugger now */
2332 if (Peb->BeingDebugged)
2333 {
2334 /* Break */
2335 DbgBreakPoint();
2336
2337 /* Update show snaps again */
2338 ShowSnaps = Peb->NtGlobalFlag & FLG_SHOW_LDR_SNAPS;
2339 }
2340
2341 /* Validate the Image for MP Usage */
2342 if (LdrpNumberOfProcessors > 1) LdrpValidateImageForMp(LdrpImageEntry);
2343
2344 /* Check NX Options */
2345 if (SharedUserData->NXSupportPolicy == 1)
2346 {
2347 ExecuteOptions = 0xD;
2348 }
2349 else if (!SharedUserData->NXSupportPolicy)
2350 {
2351 ExecuteOptions = 0xA;
2352 }
2353
2354 /* Let Mm know */
2355 ZwSetInformationProcess(NtCurrentProcess(),
2356 ProcessExecuteFlags,
2357 &ExecuteOptions,
2358 sizeof(ULONG));
2359
2360 // FIXME: Should be done by Application Compatibility features,
2361 // by reading the registry, etc...
2362 // For now, this is the old code from ntdll!RtlGetVersion().
2363 RtlInitEmptyUnicodeString(&Peb->CSDVersion, NULL, 0);
2364 if (((Peb->OSCSDVersion >> 8) & 0xFF) != 0)
2365 {
2366 WCHAR szCSDVersion[128];
2367 LONG i;
2368 ULONG Length = ARRAYSIZE(szCSDVersion) - 1;
2369 i = _snwprintf(szCSDVersion, Length,
2370 L"Service Pack %d",
2371 ((Peb->OSCSDVersion >> 8) & 0xFF));
2372 if (i < 0)
2373 {
2374 /* Null-terminate if it was overflowed */
2375 szCSDVersion[Length] = UNICODE_NULL;
2376 }
2377
2378 Length *= sizeof(WCHAR);
2379 Peb->CSDVersion.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
2380 0,
2381 Length + sizeof(UNICODE_NULL));
2382 if (Peb->CSDVersion.Buffer)
2383 {
2384 Peb->CSDVersion.Length = Length;
2385 Peb->CSDVersion.MaximumLength = Length + sizeof(UNICODE_NULL);
2386
2387 RtlCopyMemory(Peb->CSDVersion.Buffer,
2388 szCSDVersion,
2389 Peb->CSDVersion.MaximumLength);
2390 Peb->CSDVersion.Buffer[Peb->CSDVersion.Length / sizeof(WCHAR)] = UNICODE_NULL;
2391 }
2392 }
2393
2394 /* Check if we had Shim Data */
2395 if (OldShimData)
2396 {
2397 /* Load the Shim Engine */
2398 Peb->AppCompatInfo = NULL;
2399 LdrpLoadShimEngine(OldShimData, &ImagePathName, OldShimData);
2400 }
2401 else
2402 {
2403 /* Check for Application Compatibility Goo */
2404 //LdrQueryApplicationCompatibilityGoo(hKey);
2405 DPRINT("Querying app compat hacks is missing!\n");
2406 }
2407
2408 /*
2409 * FIXME: Check for special images, SecuROM, SafeDisc and other NX-
2410 * incompatible images.
2411 */
2412
2413 /* Now call the Init Routines */
2414 Status = LdrpRunInitializeRoutines(Context);
2415 if (!NT_SUCCESS(Status))
2416 {
2417 DPRINT1("LDR: LdrpProcessInitialization failed running initialization routines; status %x\n",
2418 Status);
2419 return Status;
2420 }
2421
2422 /* Notify Shim Engine */
2423 if (g_ShimsEnabled)
2424 {
2425 VOID(NTAPI *SE_InstallAfterInit)(PUNICODE_STRING, PVOID);
2426 SE_InstallAfterInit = RtlDecodeSystemPointer(g_pfnSE_InstallAfterInit);
2427 SE_InstallAfterInit(&ImagePathName, OldShimData);
2428 }
2429
2430 /* Check if we have a user-defined Post Process Routine */
2431 if (NT_SUCCESS(Status) && Peb->PostProcessInitRoutine)
2432 {
2433 /* Call it */
2434 Peb->PostProcessInitRoutine();
2435 }
2436
2437 /* Close the key if we have one opened */
2438 if (OptionsKey) NtClose(OptionsKey);
2439
2440 /* Return status */
2441 return Status;
2442 }
2443
2444 VOID
2445 NTAPI
2446 LdrpInitFailure(NTSTATUS Status)
2447 {
2448 ULONG Response;
2449 PPEB Peb = NtCurrentPeb();
2450
2451 /* Print a debug message */
2452 DPRINT1("LDR: Process initialization failure for %wZ; NTSTATUS = %08lx\n",
2453 &Peb->ProcessParameters->ImagePathName, Status);
2454
2455 /* Raise a hard error */
2456 if (!LdrpFatalHardErrorCount)
2457 {
2458 ZwRaiseHardError(STATUS_APP_INIT_FAILURE, 1, 0, (PULONG_PTR)&Status, OptionOk, &Response);
2459 }
2460 }
2461
2462 VOID
2463 NTAPI
2464 LdrpInit(PCONTEXT Context,
2465 PVOID SystemArgument1,
2466 PVOID SystemArgument2)
2467 {
2468 LARGE_INTEGER Timeout;
2469 PTEB Teb = NtCurrentTeb();
2470 NTSTATUS Status, LoaderStatus = STATUS_SUCCESS;
2471 MEMORY_BASIC_INFORMATION MemoryBasicInfo;
2472 PPEB Peb = NtCurrentPeb();
2473
2474 DPRINT("LdrpInit() %p/%p\n",
2475 NtCurrentTeb()->RealClientId.UniqueProcess,
2476 NtCurrentTeb()->RealClientId.UniqueThread);
2477
2478 #ifdef _WIN64
2479 /* Set the SList header usage */
2480 RtlpUse16ByteSLists = SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE128];
2481 #endif /* _WIN64 */
2482
2483 /* Check if we have a deallocation stack */
2484 if (!Teb->DeallocationStack)
2485 {
2486 /* We don't, set one */
2487 Status = NtQueryVirtualMemory(NtCurrentProcess(),
2488 Teb->NtTib.StackLimit,
2489 MemoryBasicInformation,
2490 &MemoryBasicInfo,
2491 sizeof(MEMORY_BASIC_INFORMATION),
2492 NULL);
2493 if (!NT_SUCCESS(Status))
2494 {
2495 /* Fail */
2496 LdrpInitFailure(Status);
2497 RtlRaiseStatus(Status);
2498 return;
2499 }
2500
2501 /* Set the stack */
2502 Teb->DeallocationStack = MemoryBasicInfo.AllocationBase;
2503 }
2504
2505 /* Now check if the process is already being initialized */
2506 while (_InterlockedCompareExchange(&LdrpProcessInitialized,
2507 1,
2508 0) == 1)
2509 {
2510 /* Set the timeout to 30 milliseconds */
2511 Timeout.QuadPart = Int32x32To64(30, -10000);
2512
2513 /* Make sure the status hasn't changed */
2514 while (LdrpProcessInitialized == 1)
2515 {
2516 /* Do the wait */
2517 ZwDelayExecution(FALSE, &Timeout);
2518 }
2519 }
2520
2521 /* Check if we have already setup LDR data */
2522 if (!Peb->Ldr)
2523 {
2524 /* Setup the Loader Lock */
2525 Peb->LoaderLock = &LdrpLoaderLock;
2526
2527 /* Let other code know we're initializing */
2528 LdrpInLdrInit = TRUE;
2529
2530 /* Protect with SEH */
2531 _SEH2_TRY
2532 {
2533 /* Initialize the Process */
2534 LoaderStatus = LdrpInitializeProcess(Context,
2535 SystemArgument1);
2536
2537 /* Check for success and if MinimumStackCommit was requested */
2538 if (NT_SUCCESS(LoaderStatus) && Peb->MinimumStackCommit)
2539 {
2540 /* Enforce the limit */
2541 //LdrpTouchThreadStack(Peb->MinimumStackCommit);
2542 UNIMPLEMENTED;
2543 }
2544 }
2545 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2546 {
2547 /* Fail with the SEH error */
2548 LoaderStatus = _SEH2_GetExceptionCode();
2549 }
2550 _SEH2_END;
2551
2552 /* We're not initializing anymore */
2553 LdrpInLdrInit = FALSE;
2554
2555 /* Check if init worked */
2556 if (NT_SUCCESS(LoaderStatus))
2557 {
2558 /* Set the process as Initialized */
2559 _InterlockedIncrement(&LdrpProcessInitialized);
2560 }
2561 }
2562 else
2563 {
2564 /* Loader data is there... is this a fork() ? */
2565 if(Peb->InheritedAddressSpace)
2566 {
2567 /* Handle the fork() */
2568 //LoaderStatus = LdrpForkProcess();
2569 LoaderStatus = STATUS_NOT_IMPLEMENTED;
2570 UNIMPLEMENTED;
2571 }
2572 else
2573 {
2574 /* This is a new thread initializing */
2575 LdrpInitializeThread(Context);
2576 }
2577 }
2578
2579 /* All done, test alert the thread */
2580 NtTestAlert();
2581
2582 /* Return */
2583 if (!NT_SUCCESS(LoaderStatus))
2584 {
2585 /* Fail */
2586 LdrpInitFailure(LoaderStatus);
2587 RtlRaiseStatus(LoaderStatus);
2588 }
2589 }
2590
2591 /* EOF */