5162f1afed4458cc4362fc0f8536b9aa6a1a0143
[reactos.git] / dll / ntdll / ldr / ldrinit.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NT User-Mode Library
4 * FILE: dll/ntdll/ldr/ldrinit.c
5 * PURPOSE: User-Mode Process/Thread Startup
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
7 * Aleksey Bragin (aleksey@reactos.org)
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include <ntdll.h>
13 #include <compat_undoc.h>
14 #include <compatguid_undoc.h>
15
16 #define NDEBUG
17 #include <debug.h>
18
19
20 /* GLOBALS *******************************************************************/
21
22 HANDLE ImageExecOptionsKey;
23 HANDLE Wow64ExecOptionsKey;
24 UNICODE_STRING ImageExecOptionsString = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options");
25 UNICODE_STRING Wow64OptionsString = RTL_CONSTANT_STRING(L"");
26 UNICODE_STRING NtDllString = RTL_CONSTANT_STRING(L"ntdll.dll");
27
28 BOOLEAN LdrpInLdrInit;
29 LONG LdrpProcessInitialized;
30 BOOLEAN LdrpLoaderLockInit;
31 BOOLEAN LdrpLdrDatabaseIsSetup;
32 BOOLEAN LdrpShutdownInProgress;
33 HANDLE LdrpShutdownThreadId;
34
35 BOOLEAN LdrpDllValidation;
36
37 PLDR_DATA_TABLE_ENTRY LdrpImageEntry;
38 PUNICODE_STRING LdrpTopLevelDllBeingLoaded;
39 WCHAR StringBuffer[156];
40 extern PTEB LdrpTopLevelDllBeingLoadedTeb; // defined in rtlsupp.c!
41 PLDR_DATA_TABLE_ENTRY LdrpCurrentDllInitializer;
42 PLDR_DATA_TABLE_ENTRY LdrpNtDllDataTableEntry;
43
44 RTL_BITMAP TlsBitMap;
45 RTL_BITMAP TlsExpansionBitMap;
46 RTL_BITMAP FlsBitMap;
47 BOOLEAN LdrpImageHasTls;
48 LIST_ENTRY LdrpTlsList;
49 ULONG LdrpNumberOfTlsEntries;
50 ULONG LdrpNumberOfProcessors;
51 PVOID NtDllBase;
52 extern LARGE_INTEGER RtlpTimeout;
53 BOOLEAN RtlpTimeoutDisable;
54 LIST_ENTRY LdrpHashTable[LDR_HASH_TABLE_ENTRIES];
55 LIST_ENTRY LdrpDllNotificationList;
56 HANDLE LdrpKnownDllObjectDirectory;
57 UNICODE_STRING LdrpKnownDllPath;
58 WCHAR LdrpKnownDllPathBuffer[128];
59 UNICODE_STRING LdrpDefaultPath;
60
61 PEB_LDR_DATA PebLdr;
62
63 RTL_CRITICAL_SECTION_DEBUG LdrpLoaderLockDebug;
64 RTL_CRITICAL_SECTION LdrpLoaderLock =
65 {
66 &LdrpLoaderLockDebug,
67 -1,
68 0,
69 0,
70 0,
71 0
72 };
73 RTL_CRITICAL_SECTION FastPebLock;
74
75 BOOLEAN ShowSnaps;
76
77 ULONG LdrpFatalHardErrorCount;
78 ULONG LdrpActiveUnloadCount;
79
80 //extern LIST_ENTRY RtlCriticalSectionList;
81
82 VOID NTAPI RtlpInitializeVectoredExceptionHandling(VOID);
83 VOID NTAPI RtlpInitDeferedCriticalSection(VOID);
84 VOID NTAPI RtlInitializeHeapManager(VOID);
85 extern BOOLEAN RtlpPageHeapEnabled;
86
87 ULONG RtlpDisableHeapLookaside; // TODO: Move to heap.c
88 ULONG RtlpShutdownProcessFlags; // TODO: Use it
89
90 NTSTATUS LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders, PVOID ImageBase);
91 void actctx_init(void);
92 extern BOOLEAN RtlpUse16ByteSLists;
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(VOID)
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, InMemoryOrderLinks);
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, InInitializationOrderLinks);
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 Entry */
845 LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);
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 (g_ShimsEnabled)
907 {
908 VOID(NTAPI *SE_ProcessDying)();
909 SE_ProcessDying = RtlDecodeSystemPointer(g_pfnSE_ProcessDying);
910 SE_ProcessDying();
911 }
912
913 /* Tell the world */
914 if (ShowSnaps)
915 {
916 DPRINT1("\n");
917 }
918
919 /* Set the shutdown variables */
920 LdrpShutdownThreadId = NtCurrentTeb()->RealClientId.UniqueThread;
921 LdrpShutdownInProgress = TRUE;
922
923 /* Enter the Loader Lock */
924 RtlEnterCriticalSection(&LdrpLoaderLock);
925
926 /* Cleanup trace logging data (Etw) */
927 if (SharedUserData->TraceLogging)
928 {
929 /* FIXME */
930 DPRINT1("We don't support Etw yet.\n");
931 }
932
933 /* Start at the end */
934 ListHead = &Peb->Ldr->InInitializationOrderModuleList;
935 NextEntry = ListHead->Blink;
936 while (NextEntry != ListHead)
937 {
938 /* Get the current entry */
939 LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);
940 NextEntry = NextEntry->Blink;
941
942 /* Make sure it's not ourselves */
943 if (Peb->ImageBaseAddress != LdrEntry->DllBase)
944 {
945 /* Get the entrypoint */
946 EntryPoint = LdrEntry->EntryPoint;
947
948 /* Check if we are ready to call it */
949 if (EntryPoint &&
950 (LdrEntry->Flags & LDRP_PROCESS_ATTACH_CALLED) &&
951 LdrEntry->Flags)
952 {
953 /* Set up the Act Ctx */
954 ActCtx.Size = sizeof(ActCtx);
955 ActCtx.Format = 1;
956 RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
957
958 /* Activate the ActCtx */
959 RtlActivateActivationContextUnsafeFast(&ActCtx,
960 LdrEntry->EntryPointActivationContext);
961
962 /* Check if it has TLS */
963 if (LdrEntry->TlsIndex)
964 {
965 /* Call TLS */
966 LdrpCallTlsInitializers(LdrEntry->DllBase, DLL_PROCESS_DETACH);
967 }
968
969 /* Call the Entrypoint */
970 DPRINT("%wZ - Calling entry point at %p for thread detaching\n",
971 &LdrEntry->BaseDllName, LdrEntry->EntryPoint);
972 LdrpCallInitRoutine(EntryPoint,
973 LdrEntry->DllBase,
974 DLL_PROCESS_DETACH,
975 (PVOID)1);
976
977 /* Deactivate the ActCtx */
978 RtlDeactivateActivationContextUnsafeFast(&ActCtx);
979 }
980 }
981 }
982
983 /* Check for TLS */
984 if (LdrpImageHasTls)
985 {
986 /* Set up the Act Ctx */
987 ActCtx.Size = sizeof(ActCtx);
988 ActCtx.Format = 1;
989 RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
990
991 /* Activate the ActCtx */
992 RtlActivateActivationContextUnsafeFast(&ActCtx,
993 LdrpImageEntry->EntryPointActivationContext);
994
995 /* Do TLS callbacks */
996 LdrpCallTlsInitializers(Peb->ImageBaseAddress, DLL_PROCESS_DETACH);
997
998 /* Deactivate the ActCtx */
999 RtlDeactivateActivationContextUnsafeFast(&ActCtx);
1000 }
1001
1002 /* FIXME: Do Heap detection and Etw final shutdown */
1003
1004 /* Release the lock */
1005 RtlLeaveCriticalSection(&LdrpLoaderLock);
1006 DPRINT("LdrpShutdownProcess() done\n");
1007
1008 return STATUS_SUCCESS;
1009 }
1010
1011 /*
1012 * @implemented
1013 */
1014 NTSTATUS
1015 NTAPI
1016 LdrShutdownThread(VOID)
1017 {
1018 PPEB Peb = NtCurrentPeb();
1019 PTEB Teb = NtCurrentTeb();
1020 PLDR_DATA_TABLE_ENTRY LdrEntry;
1021 PLIST_ENTRY NextEntry, ListHead;
1022 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx;
1023 PVOID EntryPoint;
1024
1025 DPRINT("LdrShutdownThread() called for %wZ\n",
1026 &LdrpImageEntry->BaseDllName);
1027
1028 /* Cleanup trace logging data (Etw) */
1029 if (SharedUserData->TraceLogging)
1030 {
1031 /* FIXME */
1032 DPRINT1("We don't support Etw yet.\n");
1033 }
1034
1035 /* Get the Ldr Lock */
1036 RtlEnterCriticalSection(&LdrpLoaderLock);
1037
1038 /* Start at the end */
1039 ListHead = &Peb->Ldr->InInitializationOrderModuleList;
1040 NextEntry = ListHead->Blink;
1041 while (NextEntry != ListHead)
1042 {
1043 /* Get the current entry */
1044 LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);
1045 NextEntry = NextEntry->Blink;
1046
1047 /* Make sure it's not ourselves */
1048 if (Peb->ImageBaseAddress != LdrEntry->DllBase)
1049 {
1050 /* Check if we should call */
1051 if (!(LdrEntry->Flags & LDRP_DONT_CALL_FOR_THREADS) &&
1052 (LdrEntry->Flags & LDRP_PROCESS_ATTACH_CALLED) &&
1053 (LdrEntry->Flags & LDRP_IMAGE_DLL))
1054 {
1055 /* Get the entrypoint */
1056 EntryPoint = LdrEntry->EntryPoint;
1057
1058 /* Check if we are ready to call it */
1059 if (EntryPoint)
1060 {
1061 /* Set up the Act Ctx */
1062 ActCtx.Size = sizeof(ActCtx);
1063 ActCtx.Format = 1;
1064 RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
1065
1066 /* Activate the ActCtx */
1067 RtlActivateActivationContextUnsafeFast(&ActCtx,
1068 LdrEntry->EntryPointActivationContext);
1069
1070 /* Check if it has TLS */
1071 if (LdrEntry->TlsIndex)
1072 {
1073 /* Make sure we're not shutting down */
1074 if (!LdrpShutdownInProgress)
1075 {
1076 /* Call TLS */
1077 LdrpCallTlsInitializers(LdrEntry->DllBase, DLL_THREAD_DETACH);
1078 }
1079 }
1080
1081 /* Make sure we're not shutting down */
1082 if (!LdrpShutdownInProgress)
1083 {
1084 /* Call the Entrypoint */
1085 DPRINT("%wZ - Calling entry point at %p for thread detaching\n",
1086 &LdrEntry->BaseDllName, LdrEntry->EntryPoint);
1087 LdrpCallInitRoutine(EntryPoint,
1088 LdrEntry->DllBase,
1089 DLL_THREAD_DETACH,
1090 NULL);
1091 }
1092
1093 /* Deactivate the ActCtx */
1094 RtlDeactivateActivationContextUnsafeFast(&ActCtx);
1095 }
1096 }
1097 }
1098 }
1099
1100 /* Check for TLS */
1101 if (LdrpImageHasTls)
1102 {
1103 /* Set up the Act Ctx */
1104 ActCtx.Size = sizeof(ActCtx);
1105 ActCtx.Format = 1;
1106 RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
1107
1108 /* Activate the ActCtx */
1109 RtlActivateActivationContextUnsafeFast(&ActCtx,
1110 LdrpImageEntry->EntryPointActivationContext);
1111
1112 /* Do TLS callbacks */
1113 LdrpCallTlsInitializers(Peb->ImageBaseAddress, DLL_THREAD_DETACH);
1114
1115 /* Deactivate the ActCtx */
1116 RtlDeactivateActivationContextUnsafeFast(&ActCtx);
1117 }
1118
1119 /* Free TLS */
1120 LdrpFreeTls();
1121 RtlLeaveCriticalSection(&LdrpLoaderLock);
1122
1123 /* Check for expansion slots */
1124 if (Teb->TlsExpansionSlots)
1125 {
1126 /* Free expansion slots */
1127 RtlFreeHeap(RtlGetProcessHeap(), 0, Teb->TlsExpansionSlots);
1128 }
1129
1130 /* Check for FLS Data */
1131 if (Teb->FlsData)
1132 {
1133 /* FIXME */
1134 DPRINT1("We don't support FLS Data yet\n");
1135 }
1136
1137 /* Check for Fiber data */
1138 if (Teb->HasFiberData)
1139 {
1140 /* Free Fiber data*/
1141 RtlFreeHeap(RtlGetProcessHeap(), 0, Teb->NtTib.FiberData);
1142 Teb->NtTib.FiberData = NULL;
1143 }
1144
1145 /* Free the activation context stack */
1146 RtlFreeThreadActivationContextStack();
1147 DPRINT("LdrShutdownThread() done\n");
1148
1149 return STATUS_SUCCESS;
1150 }
1151
1152 NTSTATUS
1153 NTAPI
1154 LdrpInitializeTls(VOID)
1155 {
1156 PLIST_ENTRY NextEntry, ListHead;
1157 PLDR_DATA_TABLE_ENTRY LdrEntry;
1158 PIMAGE_TLS_DIRECTORY TlsDirectory;
1159 PLDRP_TLS_DATA TlsData;
1160 ULONG Size;
1161
1162 /* Initialize the TLS List */
1163 InitializeListHead(&LdrpTlsList);
1164
1165 /* Loop all the modules */
1166 ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
1167 NextEntry = ListHead->Flink;
1168 while (ListHead != NextEntry)
1169 {
1170 /* Get the entry */
1171 LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
1172 NextEntry = NextEntry->Flink;
1173
1174 /* Get the TLS directory */
1175 TlsDirectory = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
1176 TRUE,
1177 IMAGE_DIRECTORY_ENTRY_TLS,
1178 &Size);
1179
1180 /* Check if we have a directory */
1181 if (!TlsDirectory) continue;
1182
1183 /* Check if the image has TLS */
1184 if (!LdrpImageHasTls) LdrpImageHasTls = TRUE;
1185
1186 /* Show debug message */
1187 if (ShowSnaps)
1188 {
1189 DPRINT1("LDR: Tls Found in %wZ at %p\n",
1190 &LdrEntry->BaseDllName,
1191 TlsDirectory);
1192 }
1193
1194 /* Allocate an entry */
1195 TlsData = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(LDRP_TLS_DATA));
1196 if (!TlsData) return STATUS_NO_MEMORY;
1197
1198 /* Lock the DLL and mark it for TLS Usage */
1199 LdrEntry->LoadCount = -1;
1200 LdrEntry->TlsIndex = -1;
1201
1202 /* Save the cached TLS data */
1203 TlsData->TlsDirectory = *TlsDirectory;
1204 InsertTailList(&LdrpTlsList, &TlsData->TlsLinks);
1205
1206 /* Update the index */
1207 *(PLONG)TlsData->TlsDirectory.AddressOfIndex = LdrpNumberOfTlsEntries;
1208 TlsData->TlsDirectory.Characteristics = LdrpNumberOfTlsEntries++;
1209 }
1210
1211 /* Done setting up TLS, allocate entries */
1212 return LdrpAllocateTls();
1213 }
1214
1215 NTSTATUS
1216 NTAPI
1217 LdrpAllocateTls(VOID)
1218 {
1219 PTEB Teb = NtCurrentTeb();
1220 PLIST_ENTRY NextEntry, ListHead;
1221 PLDRP_TLS_DATA TlsData;
1222 SIZE_T TlsDataSize;
1223 PVOID *TlsVector;
1224
1225 /* Check if we have any entries */
1226 if (!LdrpNumberOfTlsEntries)
1227 return STATUS_SUCCESS;
1228
1229 /* Allocate the vector array */
1230 TlsVector = RtlAllocateHeap(RtlGetProcessHeap(),
1231 0,
1232 LdrpNumberOfTlsEntries * sizeof(PVOID));
1233 if (!TlsVector) return STATUS_NO_MEMORY;
1234 Teb->ThreadLocalStoragePointer = TlsVector;
1235
1236 /* Loop the TLS Array */
1237 ListHead = &LdrpTlsList;
1238 NextEntry = ListHead->Flink;
1239 while (NextEntry != ListHead)
1240 {
1241 /* Get the entry */
1242 TlsData = CONTAINING_RECORD(NextEntry, LDRP_TLS_DATA, TlsLinks);
1243 NextEntry = NextEntry->Flink;
1244
1245 /* Allocate this vector */
1246 TlsDataSize = TlsData->TlsDirectory.EndAddressOfRawData -
1247 TlsData->TlsDirectory.StartAddressOfRawData;
1248 TlsVector[TlsData->TlsDirectory.Characteristics] = RtlAllocateHeap(RtlGetProcessHeap(),
1249 0,
1250 TlsDataSize);
1251 if (!TlsVector[TlsData->TlsDirectory.Characteristics])
1252 {
1253 /* Out of memory */
1254 return STATUS_NO_MEMORY;
1255 }
1256
1257 /* Show debug message */
1258 if (ShowSnaps)
1259 {
1260 DPRINT1("LDR: TlsVector %p Index %lu = %p copied from %x to %p\n",
1261 TlsVector,
1262 TlsData->TlsDirectory.Characteristics,
1263 &TlsVector[TlsData->TlsDirectory.Characteristics],
1264 TlsData->TlsDirectory.StartAddressOfRawData,
1265 TlsVector[TlsData->TlsDirectory.Characteristics]);
1266 }
1267
1268 /* Copy the data */
1269 RtlCopyMemory(TlsVector[TlsData->TlsDirectory.Characteristics],
1270 (PVOID)TlsData->TlsDirectory.StartAddressOfRawData,
1271 TlsDataSize);
1272 }
1273
1274 /* Done */
1275 return STATUS_SUCCESS;
1276 }
1277
1278 VOID
1279 NTAPI
1280 LdrpFreeTls(VOID)
1281 {
1282 PLIST_ENTRY ListHead, NextEntry;
1283 PLDRP_TLS_DATA TlsData;
1284 PVOID *TlsVector;
1285 PTEB Teb = NtCurrentTeb();
1286
1287 /* Get a pointer to the vector array */
1288 TlsVector = Teb->ThreadLocalStoragePointer;
1289 if (!TlsVector) return;
1290
1291 /* Loop through it */
1292 ListHead = &LdrpTlsList;
1293 NextEntry = ListHead->Flink;
1294 while (NextEntry != ListHead)
1295 {
1296 TlsData = CONTAINING_RECORD(NextEntry, LDRP_TLS_DATA, TlsLinks);
1297 NextEntry = NextEntry->Flink;
1298
1299 /* Free each entry */
1300 if (TlsVector[TlsData->TlsDirectory.Characteristics])
1301 {
1302 RtlFreeHeap(RtlGetProcessHeap(),
1303 0,
1304 TlsVector[TlsData->TlsDirectory.Characteristics]);
1305 }
1306 }
1307
1308 /* Free the array itself */
1309 RtlFreeHeap(RtlGetProcessHeap(),
1310 0,
1311 TlsVector);
1312 }
1313
1314 NTSTATUS
1315 NTAPI
1316 LdrpInitializeApplicationVerifierPackage(PUNICODE_STRING ImagePathName, PPEB Peb, BOOLEAN SystemWide, BOOLEAN ReadAdvancedOptions)
1317 {
1318 /* If global flags request DPH, perform some additional actions */
1319 if (Peb->NtGlobalFlag & FLG_HEAP_PAGE_ALLOCS)
1320 {
1321 // TODO: Read advanced DPH flags from the registry if requested
1322 if (ReadAdvancedOptions)
1323 {
1324 UNIMPLEMENTED;
1325 }
1326
1327 /* Enable page heap */
1328 RtlpPageHeapEnabled = TRUE;
1329 }
1330
1331 return STATUS_SUCCESS;
1332 }
1333
1334 NTSTATUS
1335 NTAPI
1336 LdrpInitializeExecutionOptions(PUNICODE_STRING ImagePathName, PPEB Peb, PHANDLE OptionsKey)
1337 {
1338 NTSTATUS Status;
1339 HANDLE KeyHandle;
1340 ULONG ExecuteOptions, MinimumStackCommit = 0, GlobalFlag;
1341
1342 /* Return error if we were not provided a pointer where to save the options key handle */
1343 if (!OptionsKey) return STATUS_INVALID_HANDLE;
1344
1345 /* Zero initialize the options key pointer */
1346 *OptionsKey = NULL;
1347
1348 /* Open the options key */
1349 Status = LdrOpenImageFileOptionsKey(ImagePathName, 0, &KeyHandle);
1350
1351 /* Save it if it was opened successfully */
1352 if (NT_SUCCESS(Status))
1353 *OptionsKey = KeyHandle;
1354
1355 if (KeyHandle)
1356 {
1357 /* There are image specific options, read them starting with NXCOMPAT */
1358 Status = LdrQueryImageFileKeyOption(KeyHandle,
1359 L"ExecuteOptions",
1360 4,
1361 &ExecuteOptions,
1362 sizeof(ExecuteOptions),
1363 0);
1364
1365 if (NT_SUCCESS(Status))
1366 {
1367 /* TODO: Set execution options for the process */
1368 /*
1369 if (ExecuteOptions == 0)
1370 ExecuteOptions = 1;
1371 else
1372 ExecuteOptions = 2;
1373 ZwSetInformationProcess(NtCurrentProcess(),
1374 ProcessExecuteFlags,
1375 &ExecuteOptions,
1376 sizeof(ULONG));*/
1377
1378 }
1379
1380 /* Check if this image uses large pages */
1381 if (Peb->ImageUsesLargePages)
1382 {
1383 /* TODO: If it does, open large page key */
1384 UNIMPLEMENTED;
1385 }
1386
1387 /* Get various option values */
1388 LdrQueryImageFileKeyOption(KeyHandle,
1389 L"DisableHeapLookaside",
1390 REG_DWORD,
1391 &RtlpDisableHeapLookaside,
1392 sizeof(RtlpDisableHeapLookaside),
1393 NULL);
1394
1395 LdrQueryImageFileKeyOption(KeyHandle,
1396 L"ShutdownFlags",
1397 REG_DWORD,
1398 &RtlpShutdownProcessFlags,
1399 sizeof(RtlpShutdownProcessFlags),
1400 NULL);
1401
1402 LdrQueryImageFileKeyOption(KeyHandle,
1403 L"MinimumStackCommitInBytes",
1404 REG_DWORD,
1405 &MinimumStackCommit,
1406 sizeof(MinimumStackCommit),
1407 NULL);
1408
1409 /* Update PEB's minimum stack commit if it's lower */
1410 if (Peb->MinimumStackCommit < MinimumStackCommit)
1411 Peb->MinimumStackCommit = MinimumStackCommit;
1412
1413 /* Set the global flag */
1414 Status = LdrQueryImageFileKeyOption(KeyHandle,
1415 L"GlobalFlag",
1416 REG_DWORD,
1417 &GlobalFlag,
1418 sizeof(GlobalFlag),
1419 NULL);
1420
1421 if (NT_SUCCESS(Status))
1422 Peb->NtGlobalFlag = GlobalFlag;
1423 else
1424 GlobalFlag = 0;
1425
1426 /* Call AVRF if necessary */
1427 if (Peb->NtGlobalFlag & (FLG_POOL_ENABLE_TAIL_CHECK | FLG_HEAP_PAGE_ALLOCS))
1428 {
1429 Status = LdrpInitializeApplicationVerifierPackage(ImagePathName, Peb, TRUE, FALSE);
1430 if (!NT_SUCCESS(Status))
1431 {
1432 DPRINT1("AVRF: LdrpInitializeApplicationVerifierPackage failed with %08X\n", Status);
1433 }
1434 }
1435 }
1436 else
1437 {
1438 /* There are no image-specific options, so perform global initialization */
1439 if (Peb->NtGlobalFlag & (FLG_POOL_ENABLE_TAIL_CHECK | FLG_HEAP_PAGE_ALLOCS))
1440 {
1441 /* Initialize app verifier package */
1442 Status = LdrpInitializeApplicationVerifierPackage(ImagePathName, Peb, TRUE, FALSE);
1443 if (!NT_SUCCESS(Status))
1444 {
1445 DPRINT1("AVRF: LdrpInitializeApplicationVerifierPackage failed with %08X\n", Status);
1446 }
1447 }
1448 }
1449
1450 return STATUS_SUCCESS;
1451 }
1452
1453 VOID
1454 NTAPI
1455 LdrpValidateImageForMp(IN PLDR_DATA_TABLE_ENTRY LdrDataTableEntry)
1456 {
1457 UNIMPLEMENTED;
1458 }
1459
1460 VOID
1461 NTAPI
1462 LdrpInitializeProcessCompat(PVOID* pOldShimData)
1463 {
1464 static const GUID* GuidOrder[] = { &COMPAT_GUID_WIN10, &COMPAT_GUID_WIN81, &COMPAT_GUID_WIN8,
1465 &COMPAT_GUID_WIN7, &COMPAT_GUID_VISTA };
1466 static const DWORD GuidVersions[] = { WINVER_WIN10, WINVER_WIN81, WINVER_WIN8, WINVER_WIN7, WINVER_VISTA };
1467
1468 ULONG Buffer[(sizeof(COMPATIBILITY_CONTEXT_ELEMENT) * 10 + sizeof(ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION)) / sizeof(ULONG)];
1469 ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION* ContextCompatInfo;
1470 SIZE_T SizeRequired;
1471 NTSTATUS Status;
1472 DWORD n, cur;
1473 ReactOS_ShimData* pShimData = *pOldShimData;
1474
1475 C_ASSERT(RTL_NUMBER_OF(GuidOrder) == RTL_NUMBER_OF(GuidVersions));
1476
1477 if (pShimData)
1478 {
1479 if (pShimData->dwMagic != REACTOS_SHIMDATA_MAGIC ||
1480 pShimData->dwSize != sizeof(ReactOS_ShimData))
1481 {
1482 DPRINT1("LdrpInitializeProcessCompat: Corrupt pShimData (0x%x, %u)\n", pShimData->dwMagic, pShimData->dwSize);
1483 return;
1484 }
1485 if (pShimData->dwRosProcessCompatVersion)
1486 {
1487 DPRINT1("LdrpInitializeProcessCompat: ProcessCompatVersion already set to 0x%x\n", pShimData->dwRosProcessCompatVersion);
1488 return;
1489 }
1490 }
1491
1492 SizeRequired = sizeof(Buffer);
1493 Status = RtlQueryInformationActivationContext(RTL_QUERY_ACTIVATION_CONTEXT_FLAG_NO_ADDREF,
1494 NULL,
1495 NULL,
1496 CompatibilityInformationInActivationContext,
1497 Buffer,
1498 sizeof(Buffer),
1499 &SizeRequired);
1500
1501 if (!NT_SUCCESS(Status))
1502 {
1503 DPRINT1("LdrpInitializeProcessCompat: Unable to query process actctx with status %x\n", Status);
1504 return;
1505 }
1506
1507 ContextCompatInfo = (ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*)Buffer;
1508 /* No Compatibility elements present, bail out */
1509 if (ContextCompatInfo->ElementCount == 0)
1510 return;
1511
1512 /* Search for known GUID's, starting from newest to oldest. */
1513 for (cur = 0; cur < RTL_NUMBER_OF(GuidOrder); ++cur)
1514 {
1515 for (n = 0; n < ContextCompatInfo->ElementCount; ++n)
1516 {
1517 if (ContextCompatInfo->Elements[n].Type == ACTCX_COMPATIBILITY_ELEMENT_TYPE_OS &&
1518 RtlCompareMemory(&ContextCompatInfo->Elements[n].Id, GuidOrder[cur], sizeof(GUID)) == sizeof(GUID))
1519 {
1520 /* If this process did not need shim data before, allocate and store it */
1521 if (pShimData == NULL)
1522 {
1523 PPEB Peb = NtCurrentPeb();
1524
1525 ASSERT(Peb->pShimData == NULL);
1526 pShimData = RtlAllocateHeap(Peb->ProcessHeap, HEAP_ZERO_MEMORY, sizeof(*pShimData));
1527
1528 if (!pShimData)
1529 {
1530 DPRINT1("LdrpInitializeProcessCompat: Unable to allocated %u bytes\n", sizeof(*pShimData));
1531 return;
1532 }
1533
1534 pShimData->dwSize = sizeof(*pShimData);
1535 pShimData->dwMagic = REACTOS_SHIMDATA_MAGIC;
1536
1537 Peb->pShimData = pShimData;
1538 *pOldShimData = pShimData;
1539 }
1540
1541 /* Store the highest found version, and bail out. */
1542 pShimData->dwRosProcessCompatVersion = GuidVersions[cur];
1543 DPRINT1("LdrpInitializeProcessCompat: Found guid for winver 0x%x\n", GuidVersions[cur]);
1544 return;
1545 }
1546 }
1547 }
1548 }
1549
1550
1551 NTSTATUS
1552 NTAPI
1553 LdrpInitializeProcess(IN PCONTEXT Context,
1554 IN PVOID SystemArgument1)
1555 {
1556 RTL_HEAP_PARAMETERS HeapParameters;
1557 ULONG ComSectionSize;
1558 //ANSI_STRING FunctionName = RTL_CONSTANT_STRING("BaseQueryModuleData");
1559 PVOID OldShimData;
1560 OBJECT_ATTRIBUTES ObjectAttributes;
1561 //UNICODE_STRING LocalFileName, FullImageName;
1562 HANDLE SymLinkHandle;
1563 //ULONG DebugHeapOnly;
1564 UNICODE_STRING CommandLine, NtSystemRoot, ImagePathName, FullPath, ImageFileName, KnownDllString;
1565 PPEB Peb = NtCurrentPeb();
1566 BOOLEAN IsDotNetImage = FALSE;
1567 BOOLEAN FreeCurDir = FALSE;
1568 //HANDLE CompatKey;
1569 PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
1570 //LPWSTR ImagePathBuffer;
1571 ULONG ConfigSize;
1572 UNICODE_STRING CurrentDirectory;
1573 HANDLE OptionsKey;
1574 ULONG HeapFlags;
1575 PIMAGE_NT_HEADERS NtHeader;
1576 LPWSTR NtDllName = NULL;
1577 NTSTATUS Status, ImportStatus;
1578 NLSTABLEINFO NlsTable;
1579 PIMAGE_LOAD_CONFIG_DIRECTORY LoadConfig;
1580 PTEB Teb = NtCurrentTeb();
1581 PLIST_ENTRY ListHead;
1582 PLIST_ENTRY NextEntry;
1583 ULONG i;
1584 PWSTR ImagePath;
1585 ULONG DebugProcessHeapOnly = 0;
1586 PLDR_DATA_TABLE_ENTRY NtLdrEntry;
1587 PWCHAR Current;
1588 ULONG ExecuteOptions = 0;
1589 PVOID ViewBase;
1590
1591 /* Set a NULL SEH Filter */
1592 RtlSetUnhandledExceptionFilter(NULL);
1593
1594 /* Get the image path */
1595 ImagePath = Peb->ProcessParameters->ImagePathName.Buffer;
1596
1597 /* Check if it's not normalized */
1598 if (!(Peb->ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_NORMALIZED))
1599 {
1600 /* Normalize it*/
1601 ImagePath = (PWSTR)((ULONG_PTR)ImagePath + (ULONG_PTR)Peb->ProcessParameters);
1602 }
1603
1604 /* Create a unicode string for the Image Path */
1605 ImagePathName.Length = Peb->ProcessParameters->ImagePathName.Length;
1606 ImagePathName.MaximumLength = ImagePathName.Length + sizeof(WCHAR);
1607 ImagePathName.Buffer = ImagePath;
1608
1609 /* Get the NT Headers */
1610 NtHeader = RtlImageNtHeader(Peb->ImageBaseAddress);
1611
1612 /* Get the execution options */
1613 Status = LdrpInitializeExecutionOptions(&ImagePathName, Peb, &OptionsKey);
1614
1615 /* Check if this is a .NET executable */
1616 if (RtlImageDirectoryEntryToData(Peb->ImageBaseAddress,
1617 TRUE,
1618 IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR,
1619 &ComSectionSize))
1620 {
1621 /* Remember this for later */
1622 IsDotNetImage = TRUE;
1623 }
1624
1625 /* Save the NTDLL Base address */
1626 NtDllBase = SystemArgument1;
1627
1628 /* If this is a Native Image */
1629 if (NtHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_NATIVE)
1630 {
1631 /* Then do DLL Validation */
1632 LdrpDllValidation = TRUE;
1633 }
1634
1635 /* Save the old Shim Data */
1636 OldShimData = Peb->pShimData;
1637
1638 /* ReactOS specific: do not clear it. (Windows starts doing the same in later versions) */
1639 //Peb->pShimData = NULL;
1640
1641 /* Save the number of processors and CS Timeout */
1642 LdrpNumberOfProcessors = Peb->NumberOfProcessors;
1643 RtlpTimeout = Peb->CriticalSectionTimeout;
1644
1645 /* Normalize the parameters */
1646 ProcessParameters = RtlNormalizeProcessParams(Peb->ProcessParameters);
1647 if (ProcessParameters)
1648 {
1649 /* Save the Image and Command Line Names */
1650 ImageFileName = ProcessParameters->ImagePathName;
1651 CommandLine = ProcessParameters->CommandLine;
1652 }
1653 else
1654 {
1655 /* It failed, initialize empty strings */
1656 RtlInitUnicodeString(&ImageFileName, NULL);
1657 RtlInitUnicodeString(&CommandLine, NULL);
1658 }
1659
1660 /* Initialize NLS data */
1661 RtlInitNlsTables(Peb->AnsiCodePageData,
1662 Peb->OemCodePageData,
1663 Peb->UnicodeCaseTableData,
1664 &NlsTable);
1665
1666 /* Reset NLS Translations */
1667 RtlResetRtlTranslations(&NlsTable);
1668
1669 /* Get the Image Config Directory */
1670 LoadConfig = RtlImageDirectoryEntryToData(Peb->ImageBaseAddress,
1671 TRUE,
1672 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
1673 &ConfigSize);
1674
1675 /* Setup the Heap Parameters */
1676 RtlZeroMemory(&HeapParameters, sizeof(RTL_HEAP_PARAMETERS));
1677 HeapFlags = HEAP_GROWABLE;
1678 HeapParameters.Length = sizeof(RTL_HEAP_PARAMETERS);
1679
1680 /* Check if we have Configuration Data */
1681 if ((LoadConfig) && (ConfigSize == sizeof(IMAGE_LOAD_CONFIG_DIRECTORY)))
1682 {
1683 /* FIXME: Custom heap settings and misc. */
1684 DPRINT1("We don't support LOAD_CONFIG data yet\n");
1685 }
1686
1687 /* Check for custom affinity mask */
1688 if (Peb->ImageProcessAffinityMask)
1689 {
1690 /* Set it */
1691 Status = NtSetInformationProcess(NtCurrentProcess(),
1692 ProcessAffinityMask,
1693 &Peb->ImageProcessAffinityMask,
1694 sizeof(Peb->ImageProcessAffinityMask));
1695 }
1696
1697 /* Check if verbose debugging (ShowSnaps) was requested */
1698 ShowSnaps = Peb->NtGlobalFlag & FLG_SHOW_LDR_SNAPS;
1699
1700 /* Start verbose debugging messages right now if they were requested */
1701 if (ShowSnaps)
1702 {
1703 DPRINT1("LDR: PID: 0x%p started - '%wZ'\n",
1704 Teb->ClientId.UniqueProcess,
1705 &CommandLine);
1706 }
1707
1708 /* If the timeout is too long */
1709 if (RtlpTimeout.QuadPart < Int32x32To64(3600, -10000000))
1710 {
1711 /* Then disable CS Timeout */
1712 RtlpTimeoutDisable = TRUE;
1713 }
1714
1715 /* Initialize Critical Section Data */
1716 RtlpInitDeferedCriticalSection();
1717
1718 /* Initialize VEH Call lists */
1719 RtlpInitializeVectoredExceptionHandling();
1720
1721 /* Set TLS/FLS Bitmap data */
1722 Peb->FlsBitmap = &FlsBitMap;
1723 Peb->TlsBitmap = &TlsBitMap;
1724 Peb->TlsExpansionBitmap = &TlsExpansionBitMap;
1725
1726 /* Initialize FLS Bitmap */
1727 RtlInitializeBitMap(&FlsBitMap,
1728 Peb->FlsBitmapBits,
1729 FLS_MAXIMUM_AVAILABLE);
1730 RtlSetBit(&FlsBitMap, 0);
1731
1732 /* Initialize TLS Bitmap */
1733 RtlInitializeBitMap(&TlsBitMap,
1734 Peb->TlsBitmapBits,
1735 TLS_MINIMUM_AVAILABLE);
1736 RtlSetBit(&TlsBitMap, 0);
1737 RtlInitializeBitMap(&TlsExpansionBitMap,
1738 Peb->TlsExpansionBitmapBits,
1739 TLS_EXPANSION_SLOTS);
1740 RtlSetBit(&TlsExpansionBitMap, 0);
1741
1742 /* Initialize the Hash Table */
1743 for (i = 0; i < LDR_HASH_TABLE_ENTRIES; i++)
1744 {
1745 InitializeListHead(&LdrpHashTable[i]);
1746 }
1747
1748 /* Initialize the Loader Lock */
1749 // FIXME: What's the point of initing it manually, if two lines lower
1750 // a call to RtlInitializeCriticalSection() is being made anyway?
1751 //InsertTailList(&RtlCriticalSectionList, &LdrpLoaderLock.DebugInfo->ProcessLocksList);
1752 //LdrpLoaderLock.DebugInfo->CriticalSection = &LdrpLoaderLock;
1753 RtlInitializeCriticalSection(&LdrpLoaderLock);
1754 LdrpLoaderLockInit = TRUE;
1755
1756 /* Check if User Stack Trace Database support was requested */
1757 if (Peb->NtGlobalFlag & FLG_USER_STACK_TRACE_DB)
1758 {
1759 DPRINT1("We don't support user stack trace databases yet\n");
1760 }
1761
1762 /* Setup Fast PEB Lock */
1763 RtlInitializeCriticalSection(&FastPebLock);
1764 Peb->FastPebLock = &FastPebLock;
1765 //Peb->FastPebLockRoutine = (PPEBLOCKROUTINE)RtlEnterCriticalSection;
1766 //Peb->FastPebUnlockRoutine = (PPEBLOCKROUTINE)RtlLeaveCriticalSection;
1767
1768 /* Setup Callout Lock and Notification list */
1769 //RtlInitializeCriticalSection(&RtlpCalloutEntryLock);
1770 InitializeListHead(&LdrpDllNotificationList);
1771
1772 /* For old executables, use 16-byte aligned heap */
1773 if ((NtHeader->OptionalHeader.MajorSubsystemVersion <= 3) &&
1774 (NtHeader->OptionalHeader.MinorSubsystemVersion < 51))
1775 {
1776 HeapFlags |= HEAP_CREATE_ALIGN_16;
1777 }
1778
1779 /* Setup the Heap */
1780 RtlInitializeHeapManager();
1781 Peb->ProcessHeap = RtlCreateHeap(HeapFlags,
1782 NULL,
1783 NtHeader->OptionalHeader.SizeOfHeapReserve,
1784 NtHeader->OptionalHeader.SizeOfHeapCommit,
1785 NULL,
1786 &HeapParameters);
1787
1788 if (!Peb->ProcessHeap)
1789 {
1790 DPRINT1("Failed to create process heap\n");
1791 return STATUS_NO_MEMORY;
1792 }
1793
1794 /* Allocate an Activation Context Stack */
1795 Status = RtlAllocateActivationContextStack(&Teb->ActivationContextStackPointer);
1796 if (!NT_SUCCESS(Status)) return Status;
1797
1798 // FIXME: Loader private heap is missing
1799 //DPRINT1("Loader private heap is missing\n");
1800
1801 /* Check for Debug Heap */
1802 if (OptionsKey)
1803 {
1804 /* Query the setting */
1805 Status = LdrQueryImageFileKeyOption(OptionsKey,
1806 L"DebugProcessHeapOnly",
1807 REG_DWORD,
1808 &DebugProcessHeapOnly,
1809 sizeof(ULONG),
1810 NULL);
1811
1812 if (NT_SUCCESS(Status))
1813 {
1814 /* Reset DPH if requested */
1815 if (RtlpPageHeapEnabled && DebugProcessHeapOnly)
1816 {
1817 RtlpDphGlobalFlags &= ~DPH_FLAG_DLL_NOTIFY;
1818 RtlpPageHeapEnabled = FALSE;
1819 }
1820 }
1821 }
1822
1823 /* Build the NTDLL Path */
1824 FullPath.Buffer = StringBuffer;
1825 FullPath.Length = 0;
1826 FullPath.MaximumLength = sizeof(StringBuffer);
1827 RtlInitUnicodeString(&NtSystemRoot, SharedUserData->NtSystemRoot);
1828 RtlAppendUnicodeStringToString(&FullPath, &NtSystemRoot);
1829 RtlAppendUnicodeToString(&FullPath, L"\\System32\\");
1830
1831 /* Open the Known DLLs directory */
1832 RtlInitUnicodeString(&KnownDllString, L"\\KnownDlls");
1833 InitializeObjectAttributes(&ObjectAttributes,
1834 &KnownDllString,
1835 OBJ_CASE_INSENSITIVE,
1836 NULL,
1837 NULL);
1838 Status = ZwOpenDirectoryObject(&LdrpKnownDllObjectDirectory,
1839 DIRECTORY_QUERY | DIRECTORY_TRAVERSE,
1840 &ObjectAttributes);
1841
1842 /* Check if it exists */
1843 if (NT_SUCCESS(Status))
1844 {
1845 /* Open the Known DLLs Path */
1846 RtlInitUnicodeString(&KnownDllString, L"KnownDllPath");
1847 InitializeObjectAttributes(&ObjectAttributes,
1848 &KnownDllString,
1849 OBJ_CASE_INSENSITIVE,
1850 LdrpKnownDllObjectDirectory,
1851 NULL);
1852 Status = NtOpenSymbolicLinkObject(&SymLinkHandle,
1853 SYMBOLIC_LINK_QUERY,
1854 &ObjectAttributes);
1855 if (NT_SUCCESS(Status))
1856 {
1857 /* Query the path */
1858 LdrpKnownDllPath.Length = 0;
1859 LdrpKnownDllPath.MaximumLength = sizeof(LdrpKnownDllPathBuffer);
1860 LdrpKnownDllPath.Buffer = LdrpKnownDllPathBuffer;
1861 Status = ZwQuerySymbolicLinkObject(SymLinkHandle, &LdrpKnownDllPath, NULL);
1862 NtClose(SymLinkHandle);
1863 if (!NT_SUCCESS(Status))
1864 {
1865 DPRINT1("LDR: %s - failed call to ZwQuerySymbolicLinkObject with status %x\n", "", Status);
1866 return Status;
1867 }
1868 }
1869 }
1870
1871 /* Check if we failed */
1872 if (!NT_SUCCESS(Status))
1873 {
1874 /* Assume System32 */
1875 LdrpKnownDllObjectDirectory = NULL;
1876 RtlInitUnicodeString(&LdrpKnownDllPath, StringBuffer);
1877 LdrpKnownDllPath.Length -= sizeof(WCHAR);
1878 }
1879
1880 /* If we have process parameters, get the default path and current path */
1881 if (ProcessParameters)
1882 {
1883 /* Check if we have a Dll Path */
1884 if (ProcessParameters->DllPath.Length)
1885 {
1886 /* Get the path */
1887 LdrpDefaultPath = *(PUNICODE_STRING)&ProcessParameters->DllPath;
1888 }
1889 else
1890 {
1891 /* We need a valid path */
1892 DPRINT1("No valid DllPath was given!\n");
1893 LdrpInitFailure(STATUS_INVALID_PARAMETER);
1894 }
1895
1896 /* Set the current directory */
1897 CurrentDirectory = ProcessParameters->CurrentDirectory.DosPath;
1898
1899 /* Check if it's empty or invalid */
1900 if ((!CurrentDirectory.Buffer) ||
1901 (CurrentDirectory.Buffer[0] == UNICODE_NULL) ||
1902 (!CurrentDirectory.Length))
1903 {
1904 /* Allocate space for the buffer */
1905 CurrentDirectory.Buffer = RtlAllocateHeap(Peb->ProcessHeap,
1906 0,
1907 3 * sizeof(WCHAR) +
1908 sizeof(UNICODE_NULL));
1909 if (!CurrentDirectory.Buffer)
1910 {
1911 DPRINT1("LDR: LdrpInitializeProcess - unable to allocate current working directory buffer\n");
1912 // FIXME: And what?
1913 }
1914
1915 /* Copy the drive of the system root */
1916 RtlMoveMemory(CurrentDirectory.Buffer,
1917 SharedUserData->NtSystemRoot,
1918 3 * sizeof(WCHAR));
1919 CurrentDirectory.Buffer[3] = UNICODE_NULL;
1920 CurrentDirectory.Length = 3 * sizeof(WCHAR);
1921 CurrentDirectory.MaximumLength = CurrentDirectory.Length + sizeof(WCHAR);
1922
1923 FreeCurDir = TRUE;
1924 DPRINT("Using dynamically allocd curdir\n");
1925 }
1926 else
1927 {
1928 /* Use the local buffer */
1929 DPRINT("Using local system root\n");
1930 }
1931 }
1932
1933 /* Setup Loader Data */
1934 Peb->Ldr = &PebLdr;
1935 InitializeListHead(&PebLdr.InLoadOrderModuleList);
1936 InitializeListHead(&PebLdr.InMemoryOrderModuleList);
1937 InitializeListHead(&PebLdr.InInitializationOrderModuleList);
1938 PebLdr.Length = sizeof(PEB_LDR_DATA);
1939 PebLdr.Initialized = TRUE;
1940
1941 /* Allocate a data entry for the Image */
1942 LdrpImageEntry = LdrpAllocateDataTableEntry(Peb->ImageBaseAddress);
1943
1944 /* Set it up */
1945 LdrpImageEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(LdrpImageEntry->DllBase);
1946 LdrpImageEntry->LoadCount = -1;
1947 LdrpImageEntry->EntryPointActivationContext = 0;
1948 LdrpImageEntry->FullDllName = ImageFileName;
1949
1950 if (IsDotNetImage)
1951 LdrpImageEntry->Flags = LDRP_COR_IMAGE;
1952 else
1953 LdrpImageEntry->Flags = 0;
1954
1955 /* Check if the name is empty */
1956 if (!ImageFileName.Buffer[0])
1957 {
1958 /* Use the same Base name */
1959 LdrpImageEntry->BaseDllName = LdrpImageEntry->FullDllName;
1960 }
1961 else
1962 {
1963 /* Find the last slash */
1964 Current = ImageFileName.Buffer;
1965 while (*Current)
1966 {
1967 if (*Current++ == '\\')
1968 {
1969 /* Set this path */
1970 NtDllName = Current;
1971 }
1972 }
1973
1974 /* Did we find anything? */
1975 if (!NtDllName)
1976 {
1977 /* Use the same Base name */
1978 LdrpImageEntry->BaseDllName = LdrpImageEntry->FullDllName;
1979 }
1980 else
1981 {
1982 /* Setup the name */
1983 LdrpImageEntry->BaseDllName.Length = (USHORT)((ULONG_PTR)ImageFileName.Buffer + ImageFileName.Length - (ULONG_PTR)NtDllName);
1984 LdrpImageEntry->BaseDllName.MaximumLength = LdrpImageEntry->BaseDllName.Length + sizeof(WCHAR);
1985 LdrpImageEntry->BaseDllName.Buffer = (PWSTR)((ULONG_PTR)ImageFileName.Buffer +
1986 (ImageFileName.Length - LdrpImageEntry->BaseDllName.Length));
1987 }
1988 }
1989
1990 /* Processing done, insert it */
1991 LdrpInsertMemoryTableEntry(LdrpImageEntry);
1992 LdrpImageEntry->Flags |= LDRP_ENTRY_PROCESSED;
1993
1994 /* Now add an entry for NTDLL */
1995 NtLdrEntry = LdrpAllocateDataTableEntry(SystemArgument1);
1996 NtLdrEntry->Flags = LDRP_IMAGE_DLL;
1997 NtLdrEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(NtLdrEntry->DllBase);
1998 NtLdrEntry->LoadCount = -1;
1999 NtLdrEntry->EntryPointActivationContext = 0;
2000
2001 NtLdrEntry->FullDllName.Length = FullPath.Length;
2002 NtLdrEntry->FullDllName.MaximumLength = FullPath.MaximumLength;
2003 NtLdrEntry->FullDllName.Buffer = StringBuffer;
2004 RtlAppendUnicodeStringToString(&NtLdrEntry->FullDllName, &NtDllString);
2005
2006 NtLdrEntry->BaseDllName.Length = NtDllString.Length;
2007 NtLdrEntry->BaseDllName.MaximumLength = NtDllString.MaximumLength;
2008 NtLdrEntry->BaseDllName.Buffer = NtDllString.Buffer;
2009
2010 /* Processing done, insert it */
2011 LdrpNtDllDataTableEntry = NtLdrEntry;
2012 LdrpInsertMemoryTableEntry(NtLdrEntry);
2013
2014 /* Let the world know */
2015 if (ShowSnaps)
2016 {
2017 DPRINT1("LDR: NEW PROCESS\n");
2018 DPRINT1(" Image Path: %wZ (%wZ)\n", &LdrpImageEntry->FullDllName, &LdrpImageEntry->BaseDllName);
2019 DPRINT1(" Current Directory: %wZ\n", &CurrentDirectory);
2020 DPRINT1(" Search Path: %wZ\n", &LdrpDefaultPath);
2021 }
2022
2023 /* Link the Init Order List */
2024 InsertHeadList(&Peb->Ldr->InInitializationOrderModuleList,
2025 &LdrpNtDllDataTableEntry->InInitializationOrderLinks);
2026
2027 /* Initialize Wine's active context implementation for the current process */
2028 actctx_init();
2029
2030 /* ReactOS specific */
2031 LdrpInitializeProcessCompat(&OldShimData);
2032
2033 /* Set the current directory */
2034 Status = RtlSetCurrentDirectory_U(&CurrentDirectory);
2035 if (!NT_SUCCESS(Status))
2036 {
2037 /* We failed, check if we should free it */
2038 if (FreeCurDir) RtlFreeUnicodeString(&CurrentDirectory);
2039
2040 /* Set it to the NT Root */
2041 CurrentDirectory = NtSystemRoot;
2042 RtlSetCurrentDirectory_U(&CurrentDirectory);
2043 }
2044 else
2045 {
2046 /* We're done with it, free it */
2047 if (FreeCurDir) RtlFreeUnicodeString(&CurrentDirectory);
2048 }
2049
2050 /* Check if we should look for a .local file */
2051 if (ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_LOCAL_DLL_PATH)
2052 {
2053 /* FIXME */
2054 DPRINT1("We don't support .local overrides yet\n");
2055 }
2056
2057 /* Check if the Application Verifier was enabled */
2058 if (Peb->NtGlobalFlag & FLG_POOL_ENABLE_TAIL_CHECK)
2059 {
2060 /* FIXME */
2061 DPRINT1("We don't support Application Verifier yet\n");
2062 }
2063
2064 if (IsDotNetImage)
2065 {
2066 /* FIXME */
2067 DPRINT1("We don't support .NET applications yet\n");
2068 }
2069
2070 /* FIXME: Load support for Terminal Services */
2071 if (NtHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI)
2072 {
2073 /* Load kernel32 and call BasePostImportInit... */
2074 DPRINT("Unimplemented codepath!\n");
2075 }
2076
2077 /* Walk the IAT and load all the DLLs */
2078 ImportStatus = LdrpWalkImportDescriptor(LdrpDefaultPath.Buffer, LdrpImageEntry);
2079
2080 /* Check if relocation is needed */
2081 if (Peb->ImageBaseAddress != (PVOID)NtHeader->OptionalHeader.ImageBase)
2082 {
2083 DPRINT1("LDR: Performing EXE relocation\n");
2084
2085 /* Change the protection to prepare for relocation */
2086 ViewBase = Peb->ImageBaseAddress;
2087 Status = LdrpSetProtection(ViewBase, FALSE);
2088 if (!NT_SUCCESS(Status)) return Status;
2089
2090 /* Do the relocation */
2091 Status = LdrRelocateImageWithBias(ViewBase,
2092 0LL,
2093 NULL,
2094 STATUS_SUCCESS,
2095 STATUS_CONFLICTING_ADDRESSES,
2096 STATUS_INVALID_IMAGE_FORMAT);
2097 if (!NT_SUCCESS(Status))
2098 {
2099 DPRINT1("LdrRelocateImageWithBias() failed\n");
2100 return Status;
2101 }
2102
2103 /* Check if a start context was provided */
2104 if (Context)
2105 {
2106 DPRINT1("WARNING: Relocated EXE Context");
2107 UNIMPLEMENTED; // We should support this
2108 return STATUS_INVALID_IMAGE_FORMAT;
2109 }
2110
2111 /* Restore the protection */
2112 Status = LdrpSetProtection(ViewBase, TRUE);
2113 if (!NT_SUCCESS(Status)) return Status;
2114 }
2115
2116 /* Lock the DLLs */
2117 ListHead = &Peb->Ldr->InLoadOrderModuleList;
2118 NextEntry = ListHead->Flink;
2119 while (ListHead != NextEntry)
2120 {
2121 NtLdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
2122 NtLdrEntry->LoadCount = -1;
2123 NextEntry = NextEntry->Flink;
2124 }
2125
2126 /* Phase 0 is done */
2127 LdrpLdrDatabaseIsSetup = TRUE;
2128
2129 /* Check whether all static imports were properly loaded and return here */
2130 if (!NT_SUCCESS(ImportStatus)) return ImportStatus;
2131
2132 /* Initialize TLS */
2133 Status = LdrpInitializeTls();
2134 if (!NT_SUCCESS(Status))
2135 {
2136 DPRINT1("LDR: LdrpProcessInitialization failed to initialize TLS slots; status %x\n",
2137 Status);
2138 return Status;
2139 }
2140
2141 /* FIXME Mark the DLL Ranges for Stack Traces later */
2142
2143 /* Notify the debugger now */
2144 if (Peb->BeingDebugged)
2145 {
2146 /* Break */
2147 DbgBreakPoint();
2148
2149 /* Update show snaps again */
2150 ShowSnaps = Peb->NtGlobalFlag & FLG_SHOW_LDR_SNAPS;
2151 }
2152
2153 /* Validate the Image for MP Usage */
2154 if (LdrpNumberOfProcessors > 1) LdrpValidateImageForMp(LdrpImageEntry);
2155
2156 /* Check NX Options */
2157 if (SharedUserData->NXSupportPolicy == 1)
2158 {
2159 ExecuteOptions = 0xD;
2160 }
2161 else if (!SharedUserData->NXSupportPolicy)
2162 {
2163 ExecuteOptions = 0xA;
2164 }
2165
2166 /* Let Mm know */
2167 ZwSetInformationProcess(NtCurrentProcess(),
2168 ProcessExecuteFlags,
2169 &ExecuteOptions,
2170 sizeof(ULONG));
2171
2172 // FIXME: Should be done by Application Compatibility features,
2173 // by reading the registry, etc...
2174 // For now, this is the old code from ntdll!RtlGetVersion().
2175 RtlInitEmptyUnicodeString(&Peb->CSDVersion, NULL, 0);
2176 if (((Peb->OSCSDVersion >> 8) & 0xFF) != 0)
2177 {
2178 WCHAR szCSDVersion[128];
2179 LONG i;
2180 ULONG Length = ARRAYSIZE(szCSDVersion) - 1;
2181 i = _snwprintf(szCSDVersion, Length,
2182 L"Service Pack %d",
2183 ((Peb->OSCSDVersion >> 8) & 0xFF));
2184 if (i < 0)
2185 {
2186 /* Null-terminate if it was overflowed */
2187 szCSDVersion[Length] = UNICODE_NULL;
2188 }
2189
2190 Length *= sizeof(WCHAR);
2191 Peb->CSDVersion.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
2192 0,
2193 Length + sizeof(UNICODE_NULL));
2194 if (Peb->CSDVersion.Buffer)
2195 {
2196 Peb->CSDVersion.Length = Length;
2197 Peb->CSDVersion.MaximumLength = Length + sizeof(UNICODE_NULL);
2198
2199 RtlCopyMemory(Peb->CSDVersion.Buffer,
2200 szCSDVersion,
2201 Peb->CSDVersion.MaximumLength);
2202 Peb->CSDVersion.Buffer[Peb->CSDVersion.Length / sizeof(WCHAR)] = UNICODE_NULL;
2203 }
2204 }
2205
2206 /* Check if we had Shim Data */
2207 if (OldShimData)
2208 {
2209 /* Load the Shim Engine */
2210 Peb->AppCompatInfo = NULL;
2211 LdrpLoadShimEngine(OldShimData, &ImagePathName, OldShimData);
2212 }
2213 else
2214 {
2215 /* Check for Application Compatibility Goo */
2216 //LdrQueryApplicationCompatibilityGoo(hKey);
2217 DPRINT("Querying app compat hacks is missing!\n");
2218 }
2219
2220 /*
2221 * FIXME: Check for special images, SecuROM, SafeDisc and other NX-
2222 * incompatible images.
2223 */
2224
2225 /* Now call the Init Routines */
2226 Status = LdrpRunInitializeRoutines(Context);
2227 if (!NT_SUCCESS(Status))
2228 {
2229 DPRINT1("LDR: LdrpProcessInitialization failed running initialization routines; status %x\n",
2230 Status);
2231 return Status;
2232 }
2233
2234 /* Notify Shim Engine */
2235 if (g_ShimsEnabled)
2236 {
2237 VOID(NTAPI *SE_InstallAfterInit)(PUNICODE_STRING, PVOID);
2238 SE_InstallAfterInit = RtlDecodeSystemPointer(g_pfnSE_InstallAfterInit);
2239 SE_InstallAfterInit(&ImagePathName, OldShimData);
2240 }
2241
2242 /* Check if we have a user-defined Post Process Routine */
2243 if (NT_SUCCESS(Status) && Peb->PostProcessInitRoutine)
2244 {
2245 /* Call it */
2246 Peb->PostProcessInitRoutine();
2247 }
2248
2249 /* Close the key if we have one opened */
2250 if (OptionsKey) NtClose(OptionsKey);
2251
2252 /* Return status */
2253 return Status;
2254 }
2255
2256 VOID
2257 NTAPI
2258 LdrpInitFailure(NTSTATUS Status)
2259 {
2260 ULONG Response;
2261 PPEB Peb = NtCurrentPeb();
2262
2263 /* Print a debug message */
2264 DPRINT1("LDR: Process initialization failure for %wZ; NTSTATUS = %08lx\n",
2265 &Peb->ProcessParameters->ImagePathName, Status);
2266
2267 /* Raise a hard error */
2268 if (!LdrpFatalHardErrorCount)
2269 {
2270 ZwRaiseHardError(STATUS_APP_INIT_FAILURE, 1, 0, (PULONG_PTR)&Status, OptionOk, &Response);
2271 }
2272 }
2273
2274 VOID
2275 NTAPI
2276 LdrpInit(PCONTEXT Context,
2277 PVOID SystemArgument1,
2278 PVOID SystemArgument2)
2279 {
2280 LARGE_INTEGER Timeout;
2281 PTEB Teb = NtCurrentTeb();
2282 NTSTATUS Status, LoaderStatus = STATUS_SUCCESS;
2283 MEMORY_BASIC_INFORMATION MemoryBasicInfo;
2284 PPEB Peb = NtCurrentPeb();
2285
2286 DPRINT("LdrpInit() %p/%p\n",
2287 NtCurrentTeb()->RealClientId.UniqueProcess,
2288 NtCurrentTeb()->RealClientId.UniqueThread);
2289
2290 #ifdef _WIN64
2291 /* Set the SList header usage */
2292 RtlpUse16ByteSLists = SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE128];
2293 #endif /* _WIN64 */
2294
2295 /* Check if we have a deallocation stack */
2296 if (!Teb->DeallocationStack)
2297 {
2298 /* We don't, set one */
2299 Status = NtQueryVirtualMemory(NtCurrentProcess(),
2300 Teb->NtTib.StackLimit,
2301 MemoryBasicInformation,
2302 &MemoryBasicInfo,
2303 sizeof(MEMORY_BASIC_INFORMATION),
2304 NULL);
2305 if (!NT_SUCCESS(Status))
2306 {
2307 /* Fail */
2308 LdrpInitFailure(Status);
2309 RtlRaiseStatus(Status);
2310 return;
2311 }
2312
2313 /* Set the stack */
2314 Teb->DeallocationStack = MemoryBasicInfo.AllocationBase;
2315 }
2316
2317 /* Now check if the process is already being initialized */
2318 while (_InterlockedCompareExchange(&LdrpProcessInitialized,
2319 1,
2320 0) == 1)
2321 {
2322 /* Set the timeout to 30 milliseconds */
2323 Timeout.QuadPart = Int32x32To64(30, -10000);
2324
2325 /* Make sure the status hasn't changed */
2326 while (LdrpProcessInitialized == 1)
2327 {
2328 /* Do the wait */
2329 ZwDelayExecution(FALSE, &Timeout);
2330 }
2331 }
2332
2333 /* Check if we have already setup LDR data */
2334 if (!Peb->Ldr)
2335 {
2336 /* Setup the Loader Lock */
2337 Peb->LoaderLock = &LdrpLoaderLock;
2338
2339 /* Let other code know we're initializing */
2340 LdrpInLdrInit = TRUE;
2341
2342 /* Protect with SEH */
2343 _SEH2_TRY
2344 {
2345 /* Initialize the Process */
2346 LoaderStatus = LdrpInitializeProcess(Context,
2347 SystemArgument1);
2348
2349 /* Check for success and if MinimumStackCommit was requested */
2350 if (NT_SUCCESS(LoaderStatus) && Peb->MinimumStackCommit)
2351 {
2352 /* Enforce the limit */
2353 //LdrpTouchThreadStack(Peb->MinimumStackCommit);
2354 UNIMPLEMENTED;
2355 }
2356 }
2357 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2358 {
2359 /* Fail with the SEH error */
2360 LoaderStatus = _SEH2_GetExceptionCode();
2361 }
2362 _SEH2_END;
2363
2364 /* We're not initializing anymore */
2365 LdrpInLdrInit = FALSE;
2366
2367 /* Check if init worked */
2368 if (NT_SUCCESS(LoaderStatus))
2369 {
2370 /* Set the process as Initialized */
2371 _InterlockedIncrement(&LdrpProcessInitialized);
2372 }
2373 }
2374 else
2375 {
2376 /* Loader data is there... is this a fork() ? */
2377 if(Peb->InheritedAddressSpace)
2378 {
2379 /* Handle the fork() */
2380 //LoaderStatus = LdrpForkProcess();
2381 LoaderStatus = STATUS_NOT_IMPLEMENTED;
2382 UNIMPLEMENTED;
2383 }
2384 else
2385 {
2386 /* This is a new thread initializing */
2387 LdrpInitializeThread(Context);
2388 }
2389 }
2390
2391 /* All done, test alert the thread */
2392 NtTestAlert();
2393
2394 /* Return */
2395 if (!NT_SUCCESS(LoaderStatus))
2396 {
2397 /* Fail */
2398 LdrpInitFailure(LoaderStatus);
2399 RtlRaiseStatus(LoaderStatus);
2400 }
2401 }
2402
2403 /* EOF */