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