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