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