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