[RTL/DPH]
[reactos.git] / reactos / dll / ntdll / ldr / startup.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: dll/ntdll/ldr/startup.c
5 * PURPOSE: Process startup for PE executables
6 * PROGRAMMERS: Jean Michault
7 * Rex Jolliff (rex@lvcablemodem.com)
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include <ntdll.h>
13 #define NDEBUG
14 #include <debug.h>
15 #include <win32k/callback.h>
16
17 VOID RtlInitializeHeapManager(VOID);
18 VOID LdrpInitLoader(VOID);
19 VOID NTAPI RtlpInitDeferedCriticalSection(VOID);
20 NTSTATUS LdrpAttachThread(VOID);
21 VOID RtlpInitializeVectoredExceptionHandling(VOID);
22 extern PTEB LdrpTopLevelDllBeingLoadedTeb;
23
24 /* GLOBALS *******************************************************************/
25
26 PLDR_DATA_TABLE_ENTRY ExeModule;
27 static RTL_CRITICAL_SECTION PebLock;
28 static RTL_CRITICAL_SECTION LoaderLock;
29 static RTL_BITMAP TlsBitMap;
30 static RTL_BITMAP TlsExpansionBitMap;
31 static volatile BOOLEAN LdrpInitialized = FALSE;
32 static LONG LdrpInitLock = 0;
33
34 #define VALUE_BUFFER_SIZE 256
35
36 /* FUNCTIONS *****************************************************************/
37
38 BOOLEAN
39 FASTCALL
40 ReadCompatibilitySetting(HANDLE Key,
41 LPWSTR Value,
42 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo,
43 DWORD * Buffer)
44 {
45 UNICODE_STRING ValueName;
46 NTSTATUS Status;
47 ULONG Length;
48
49 RtlInitUnicodeString(&ValueName, Value);
50 Status = NtQueryValueKey(Key,
51 &ValueName,
52 KeyValuePartialInformation,
53 ValueInfo,
54 VALUE_BUFFER_SIZE,
55 &Length);
56
57 if (!NT_SUCCESS(Status) || (ValueInfo->Type != REG_DWORD))
58 {
59 RtlFreeUnicodeString(&ValueName);
60 return FALSE;
61 }
62
63 RtlCopyMemory(Buffer, &ValueInfo->Data[0], sizeof(DWORD));
64 RtlFreeUnicodeString(&ValueName);
65 return TRUE;
66 }
67
68 VOID
69 FASTCALL
70 LoadImageFileExecutionOptions(PPEB Peb)
71 {
72 NTSTATUS Status = STATUS_SUCCESS;
73 ULONG Value = 0;
74 UNICODE_STRING ImageName;
75 UNICODE_STRING ImagePathName;
76 ULONG ValueSize;
77 extern ULONG RtlpDphGlobalFlags, RtlpPageHeapSizeRangeStart, RtlpPageHeapSizeRangeEnd;
78 extern ULONG RtlpPageHeapDllRangeStart, RtlpPageHeapDllRangeEnd;
79 extern WCHAR RtlpDphTargetDlls[512];
80 extern BOOLEAN RtlpPageHeapEnabled;
81
82 if (Peb->ProcessParameters &&
83 Peb->ProcessParameters->ImagePathName.Length > 0)
84 {
85 DPRINT("%wZ\n", &Peb->ProcessParameters->ImagePathName);
86
87 ImagePathName = Peb->ProcessParameters->ImagePathName;
88 ImageName.Buffer = ImagePathName.Buffer + ImagePathName.Length / sizeof(WCHAR);
89 ImageName.Length = 0;
90
91 while (ImagePathName.Buffer < ImageName.Buffer)
92 {
93 ImageName.Buffer--;
94 if (*ImageName.Buffer == L'\\')
95 {
96 ImageName.Buffer++;
97 break;
98 }
99 }
100
101 ImageName.Length = ImagePathName.Length -
102 (ImageName.Buffer - ImagePathName.Buffer) * sizeof(WCHAR);
103 ImageName.MaximumLength = ImageName.Length +
104 ImagePathName.MaximumLength - ImagePathName.Length;
105
106 DPRINT("%wZ\n", &ImageName);
107
108 /* global flag */
109 Status = LdrQueryImageFileExecutionOptions(&ImageName,
110 L"GlobalFlag",
111 REG_DWORD,
112 (PVOID)&Value,
113 sizeof(Value),
114 &ValueSize);
115 if (NT_SUCCESS(Status))
116 {
117 Peb->NtGlobalFlag = Value;
118 DPRINT("GlobalFlag: Value=0x%lx\n", Value);
119 }
120 else
121 {
122 /* Add debugging flags if there is no GlobalFlags override */
123 if (Peb->BeingDebugged)
124 {
125 Peb->NtGlobalFlag |= FLG_HEAP_VALIDATE_PARAMETERS |
126 FLG_HEAP_ENABLE_FREE_CHECK |
127 FLG_HEAP_ENABLE_TAIL_CHECK;
128 }
129 }
130
131 /* Handle the case when page heap is enabled */
132 if (Peb->NtGlobalFlag & FLG_HEAP_PAGE_ALLOCS)
133 {
134 /* Disable all heap debugging flags so that no heap call goes via page heap branch */
135 Peb->NtGlobalFlag &= ~(FLG_HEAP_VALIDATE_PARAMETERS |
136 FLG_HEAP_VALIDATE_ALL |
137 FLG_HEAP_ENABLE_FREE_CHECK |
138 FLG_HEAP_ENABLE_TAIL_CHECK |
139 FLG_USER_STACK_TRACE_DB |
140 FLG_HEAP_ENABLE_TAGGING |
141 FLG_HEAP_ENABLE_TAG_BY_DLL);
142
143 /* Get page heap flags without checking return value */
144 LdrQueryImageFileExecutionOptions(&ImageName,
145 L"PageHeapFlags",
146 REG_DWORD,
147 (PVOID)&RtlpDphGlobalFlags,
148 sizeof(RtlpDphGlobalFlags),
149 &ValueSize);
150
151 LdrQueryImageFileExecutionOptions(&ImageName,
152 L"PageHeapSizeRangeStart",
153 REG_DWORD,
154 (PVOID)&RtlpPageHeapSizeRangeStart,
155 sizeof(RtlpPageHeapSizeRangeStart),
156 &ValueSize);
157
158 LdrQueryImageFileExecutionOptions(&ImageName,
159 L"PageHeapSizeRangeEnd",
160 REG_DWORD,
161 (PVOID)&RtlpPageHeapSizeRangeEnd,
162 sizeof(RtlpPageHeapSizeRangeEnd),
163 &ValueSize);
164
165 LdrQueryImageFileExecutionOptions(&ImageName,
166 L"PageHeapDllRangeStart",
167 REG_DWORD,
168 (PVOID)&RtlpPageHeapDllRangeStart,
169 sizeof(RtlpPageHeapDllRangeStart),
170 &ValueSize);
171
172 LdrQueryImageFileExecutionOptions(&ImageName,
173 L"PageHeapDllRangeEnd",
174 REG_DWORD,
175 (PVOID)&RtlpPageHeapDllRangeEnd,
176 sizeof(RtlpPageHeapDllRangeEnd),
177 &ValueSize);
178
179 LdrQueryImageFileExecutionOptions(&ImageName,
180 L"PageHeapTargetDlls",
181 REG_SZ,
182 (PVOID)RtlpDphTargetDlls,
183 sizeof(RtlpDphTargetDlls),
184 &ValueSize);
185
186 /* Now when all parameters are read, enable page heap */
187 RtlpPageHeapEnabled = TRUE;
188 }
189 }
190 }
191
192 BOOLEAN
193 FASTCALL
194 LoadCompatibilitySettings(PPEB Peb)
195 {
196 NTSTATUS Status;
197 HANDLE UserKey = NULL;
198 HANDLE KeyHandle;
199 HANDLE SubKeyHandle;
200 OBJECT_ATTRIBUTES ObjectAttributes;
201 UNICODE_STRING KeyName = RTL_CONSTANT_STRING(
202 L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers");
203 UNICODE_STRING ValueName;
204 UCHAR ValueBuffer[VALUE_BUFFER_SIZE];
205 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
206 ULONG Length;
207 DWORD MajorVersion, MinorVersion, BuildNumber, PlatformId,
208 SPMajorVersion, SPMinorVersion = 0;
209
210 if (Peb->ProcessParameters &&
211 (Peb->ProcessParameters->ImagePathName.Length > 0))
212 {
213 Status = RtlOpenCurrentUser(KEY_READ, &UserKey);
214 if (!NT_SUCCESS(Status))
215 {
216 return FALSE;
217 }
218
219 InitializeObjectAttributes(&ObjectAttributes,
220 &KeyName,
221 OBJ_CASE_INSENSITIVE,
222 UserKey,
223 NULL);
224
225 Status = NtOpenKey(&KeyHandle, KEY_QUERY_VALUE, &ObjectAttributes);
226
227 if (!NT_SUCCESS(Status))
228 {
229 if (UserKey)
230 NtClose(UserKey);
231 return FALSE;
232 }
233
234 /* query version name for application */
235 ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION) ValueBuffer;
236 Status = NtQueryValueKey(KeyHandle,
237 &Peb->ProcessParameters->ImagePathName,
238 KeyValuePartialInformation,
239 ValueBuffer,
240 VALUE_BUFFER_SIZE,
241 &Length);
242
243 if (!NT_SUCCESS(Status) || (ValueInfo->Type != REG_SZ))
244 {
245 NtClose(KeyHandle);
246 if (UserKey)
247 NtClose(UserKey);
248 return FALSE;
249 }
250
251 ValueName.Length = ValueInfo->DataLength;
252 ValueName.MaximumLength = ValueInfo->DataLength;
253 ValueName.Buffer = (PWSTR) ValueInfo->Data;
254
255 /* load version info */
256 InitializeObjectAttributes(&ObjectAttributes,
257 &ValueName,
258 OBJ_CASE_INSENSITIVE,
259 KeyHandle,
260 NULL);
261
262 Status = NtOpenKey(&SubKeyHandle, KEY_QUERY_VALUE, &ObjectAttributes);
263
264 if (!NT_SUCCESS(Status))
265 {
266 NtClose(KeyHandle);
267 if (UserKey)
268 NtClose(UserKey);
269 return FALSE;
270 }
271
272 DPRINT("Loading version information for: %wZ\n", &ValueName);
273
274 /* read settings from registry */
275 if (!ReadCompatibilitySetting(SubKeyHandle, L"MajorVersion", ValueInfo, &MajorVersion))
276 goto finish;
277 if (!ReadCompatibilitySetting(SubKeyHandle, L"MinorVersion", ValueInfo, &MinorVersion))
278 goto finish;
279 if (!ReadCompatibilitySetting(SubKeyHandle, L"BuildNumber", ValueInfo, &BuildNumber))
280 goto finish;
281 if (!ReadCompatibilitySetting(SubKeyHandle, L"PlatformId", ValueInfo, &PlatformId))
282 goto finish;
283
284 /* now assign the settings */
285 Peb->OSMajorVersion = (ULONG) MajorVersion;
286 Peb->OSMinorVersion = (ULONG) MinorVersion;
287 Peb->OSBuildNumber = (USHORT) BuildNumber;
288 Peb->OSPlatformId = (ULONG) PlatformId;
289
290 /* optional service pack version numbers */
291 if (ReadCompatibilitySetting(SubKeyHandle,
292 L"SPMajorVersion",
293 ValueInfo,
294 &SPMajorVersion) &&
295 ReadCompatibilitySetting(SubKeyHandle,
296 L"SPMinorVersion",
297 ValueInfo,
298 &SPMinorVersion))
299 {
300 Peb->OSCSDVersion = ((SPMajorVersion & 0xFF) << 8) |
301 (SPMinorVersion & 0xFF);
302 }
303
304 finish:
305 /* we're finished */
306 NtClose(SubKeyHandle);
307 NtClose(KeyHandle);
308 if (UserKey)
309 NtClose(UserKey);
310 return TRUE;
311 }
312
313 return FALSE;
314 }
315
316 static
317 VOID
318 LdrpInit2(PCONTEXT Context,
319 PVOID SystemArgument1,
320 PVOID SystemArgument2)
321 {
322 PIMAGE_NT_HEADERS NTHeaders;
323 PEPFUNC EntryPoint;
324 PIMAGE_DOS_HEADER PEDosHeader;
325 PVOID ImageBase;
326 PPEB Peb = NtCurrentPeb();
327 PLDR_DATA_TABLE_ENTRY NtModule; // ntdll
328 NLSTABLEINFO NlsTable;
329 WCHAR FullNtDllPath[MAX_PATH];
330 SYSTEM_BASIC_INFORMATION SystemInformation;
331 NTSTATUS Status;
332 PVOID BaseAddress = SystemArgument1;
333
334 DPRINT("LdrpInit()\n");
335 DPRINT("Peb %p\n", Peb);
336 ImageBase = Peb->ImageBaseAddress;
337 DPRINT("ImageBase %p\n", ImageBase);
338
339 if (ImageBase <= (PVOID) 0x1000)
340 {
341 DPRINT("ImageBase is null\n");
342 ZwTerminateProcess(NtCurrentProcess(), STATUS_INVALID_IMAGE_FORMAT);
343 }
344
345 /* If MZ header exists */
346 PEDosHeader = (PIMAGE_DOS_HEADER) ImageBase;
347 NTHeaders = (PIMAGE_NT_HEADERS)((ULONG_PTR)ImageBase + PEDosHeader->e_lfanew);
348 DPRINT("PEDosHeader %p\n", PEDosHeader);
349
350 if (PEDosHeader->e_magic != IMAGE_DOS_SIGNATURE ||
351 PEDosHeader->e_lfanew == 0L ||
352 NTHeaders->Signature != IMAGE_NT_SIGNATURE)
353 {
354 DPRINT1("Image has bad header\n");
355 ZwTerminateProcess(NtCurrentProcess(), STATUS_INVALID_IMAGE_FORMAT);
356 }
357
358 /* normalize process parameters */
359 RtlNormalizeProcessParams(Peb->ProcessParameters);
360
361 /* Initialize NLS data */
362 RtlInitNlsTables(Peb->AnsiCodePageData,
363 Peb->OemCodePageData,
364 Peb->UnicodeCaseTableData,
365 &NlsTable);
366 RtlResetRtlTranslations(&NlsTable);
367
368 /* Get number of processors */
369 DPRINT("Here\n");
370 Status = ZwQuerySystemInformation(SystemBasicInformation,
371 &SystemInformation,
372 sizeof(SYSTEM_BASIC_INFORMATION),
373 NULL);
374 DPRINT("Here2\n");
375 if (!NT_SUCCESS(Status))
376 {
377 ZwTerminateProcess(NtCurrentProcess(), Status);
378 }
379
380 Peb->NumberOfProcessors = SystemInformation.NumberOfProcessors;
381
382 /* Initialize Critical Section Data */
383 RtlpInitDeferedCriticalSection();
384
385 /* Load execution options */
386 LoadImageFileExecutionOptions(Peb);
387
388 /* create process heap */
389 RtlInitializeHeapManager();
390 Peb->ProcessHeap = RtlCreateHeap(HEAP_GROWABLE,
391 NULL,
392 NTHeaders->OptionalHeader.SizeOfHeapReserve,
393 NTHeaders->OptionalHeader.SizeOfHeapCommit,
394 NULL,
395 NULL);
396 if (Peb->ProcessHeap == 0)
397 {
398 DPRINT1("Failed to create process heap\n");
399 ZwTerminateProcess(NtCurrentProcess(), STATUS_INSUFFICIENT_RESOURCES);
400 }
401
402 /* Check for correct machine type */
403 if (NTHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_NATIVE)
404 {
405 ULONG_PTR HardErrorParameters[1];
406 UNICODE_STRING ImageNameU;
407 ANSI_STRING ImageNameA;
408 WCHAR *Ptr;
409 ULONG ErrorResponse;
410
411 DPRINT1("Image %wZ is for a foreign architecture (0x%x).\n",
412 &Peb->ProcessParameters->ImagePathName, NTHeaders->FileHeader.Machine);
413
414 /* Get the full image path name */
415 ImageNameU = Peb->ProcessParameters->ImagePathName;
416
417 /* Get the file name */
418 Ptr = Peb->ProcessParameters->ImagePathName.Buffer +
419 (Peb->ProcessParameters->ImagePathName.Length / sizeof(WCHAR)) -1;
420 while ((Ptr >= Peb->ProcessParameters->ImagePathName.Buffer) &&
421 (*Ptr != L'\\')) Ptr--;
422 ImageNameU.Buffer = Ptr + 1;
423 ImageNameU.Length = Peb->ProcessParameters->ImagePathName.Length -
424 (ImageNameU.Buffer - Peb->ProcessParameters->ImagePathName.Buffer) * sizeof(WCHAR);
425 ImageNameU.MaximumLength = ImageNameU.Length;
426
427 /*`Convert to ANSI, harderror message needs that */
428 RtlUnicodeStringToAnsiString(&ImageNameA, &ImageNameU, TRUE);
429
430 /* Raise harderror */
431 HardErrorParameters[0] = (ULONG_PTR)&ImageNameA;
432 NtRaiseHardError(STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE,
433 1,
434 1,
435 HardErrorParameters,
436 OptionOk,
437 &ErrorResponse);
438
439 RtlFreeAnsiString(&ImageNameA);
440 ZwTerminateProcess(NtCurrentProcess(), STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE);
441 }
442
443 /* initialized vectored exception handling */
444 RtlpInitializeVectoredExceptionHandling();
445
446 /* initalize peb lock support */
447 RtlInitializeCriticalSection(&PebLock);
448 Peb->FastPebLock = &PebLock;
449
450 /* initialize tls bitmaps */
451 RtlInitializeBitMap(&TlsBitMap, Peb->TlsBitmapBits, TLS_MINIMUM_AVAILABLE);
452 RtlInitializeBitMap(&TlsExpansionBitMap, Peb->TlsExpansionBitmapBits, TLS_EXPANSION_SLOTS);
453
454 Peb->TlsBitmap = &TlsBitMap;
455 Peb->TlsExpansionBitmap = &TlsExpansionBitMap;
456 Peb->TlsExpansionCounter = TLS_MINIMUM_AVAILABLE;
457
458 /* Initialize table of callbacks for the kernel. */
459 Peb->KernelCallbackTable = RtlAllocateHeap(RtlGetProcessHeap(),
460 0,
461 sizeof(PVOID) *
462 (USER32_CALLBACK_MAXIMUM + 1));
463 if (Peb->KernelCallbackTable == NULL)
464 {
465 DPRINT1("Failed to create callback table\n");
466 ZwTerminateProcess(NtCurrentProcess(), STATUS_INSUFFICIENT_RESOURCES);
467 }
468
469 /* initalize loader lock */
470 RtlInitializeCriticalSection(&LoaderLock);
471 Peb->LoaderLock = &LoaderLock;
472
473 /* create loader information */
474 Peb->Ldr = (PPEB_LDR_DATA) RtlAllocateHeap(Peb->ProcessHeap,
475 0,
476 sizeof(PEB_LDR_DATA));
477 if (Peb->Ldr == NULL)
478 {
479 DPRINT1("Failed to create loader data\n");
480 ZwTerminateProcess(NtCurrentProcess(), STATUS_INSUFFICIENT_RESOURCES);
481 }
482
483 Peb->Ldr->Length = sizeof(PEB_LDR_DATA);
484 Peb->Ldr->Initialized = FALSE;
485 Peb->Ldr->SsHandle = NULL;
486 InitializeListHead(&Peb->Ldr->InLoadOrderModuleList);
487 InitializeListHead(&Peb->Ldr->InMemoryOrderModuleList);
488 InitializeListHead(&Peb->Ldr->InInitializationOrderModuleList);
489
490 /* Load compatibility settings */
491 LoadCompatibilitySettings(Peb);
492
493 /* build full ntdll path */
494 wcscpy(FullNtDllPath, SharedUserData->NtSystemRoot);
495 wcscat(FullNtDllPath, L"\\system32\\ntdll.dll");
496
497 /* add entry for ntdll */
498 NtModule = (PLDR_DATA_TABLE_ENTRY)
499 RtlAllocateHeap(Peb->ProcessHeap,
500 0,
501 sizeof(LDR_DATA_TABLE_ENTRY));
502 if (NtModule == NULL)
503 {
504 DPRINT1("Failed to create loader module entry (NTDLL)\n");
505 ZwTerminateProcess(NtCurrentProcess(), STATUS_INSUFFICIENT_RESOURCES);
506 }
507 memset(NtModule, 0, sizeof(LDR_DATA_TABLE_ENTRY));
508
509 NtModule->DllBase = BaseAddress;
510 NtModule->EntryPoint = 0; /* no entry point */
511 RtlCreateUnicodeString(&NtModule->FullDllName, FullNtDllPath);
512 RtlCreateUnicodeString(&NtModule->BaseDllName, L"ntdll.dll");
513 NtModule->Flags = LDRP_IMAGE_DLL | LDRP_ENTRY_PROCESSED;
514
515 NtModule->LoadCount = -1; /* don't unload */
516 NtModule->TlsIndex = -1;
517 NtModule->SectionPointer = NULL;
518 NtModule->CheckSum = 0;
519
520 NTHeaders = RtlImageNtHeader(NtModule->DllBase);
521 NtModule->SizeOfImage = LdrpGetResidentSize(NTHeaders);
522 NtModule->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp;
523
524 InsertTailList(&Peb->Ldr->InLoadOrderModuleList,
525 &NtModule->InLoadOrderLinks);
526 InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
527 &NtModule->InInitializationOrderModuleList);
528
529 /* add entry for executable (becomes first list entry) */
530 ExeModule = (PLDR_DATA_TABLE_ENTRY)
531 RtlAllocateHeap(Peb->ProcessHeap,
532 HEAP_ZERO_MEMORY,
533 sizeof(LDR_DATA_TABLE_ENTRY));
534 if (ExeModule == NULL)
535 {
536 DPRINT1("Failed to create loader module infomation\n");
537 ZwTerminateProcess(NtCurrentProcess(), STATUS_INSUFFICIENT_RESOURCES);
538 }
539
540 ExeModule->DllBase = Peb->ImageBaseAddress;
541
542 if ((Peb->ProcessParameters == NULL) ||
543 (Peb->ProcessParameters->ImagePathName.Length == 0))
544 {
545 DPRINT1("Failed to access the process parameter block\n");
546 ZwTerminateProcess(NtCurrentProcess(), STATUS_UNSUCCESSFUL);
547 }
548
549 RtlCreateUnicodeString(&ExeModule->FullDllName,
550 Peb->ProcessParameters->ImagePathName.Buffer);
551 RtlCreateUnicodeString(&ExeModule->BaseDllName,
552 wcsrchr(ExeModule->FullDllName.Buffer, L'\\') + 1);
553
554 DPRINT("BaseDllName '%wZ' FullDllName '%wZ'\n", &ExeModule->BaseDllName, &ExeModule->FullDllName);
555
556 ExeModule->Flags = LDRP_ENTRY_PROCESSED;
557 ExeModule->LoadCount = -1; /* don't unload */
558 ExeModule->TlsIndex = -1;
559 ExeModule->SectionPointer = NULL;
560 ExeModule->CheckSum = 0;
561
562 NTHeaders = RtlImageNtHeader(ExeModule->DllBase);
563 ExeModule->SizeOfImage = LdrpGetResidentSize(NTHeaders);
564 ExeModule->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp;
565
566 LdrpTopLevelDllBeingLoadedTeb = NtCurrentTeb();
567
568 InsertHeadList(&Peb->Ldr->InLoadOrderModuleList,
569 &ExeModule->InLoadOrderLinks);
570
571 LdrpInitLoader();
572
573 EntryPoint = LdrPEStartup((PVOID)ImageBase, NULL, NULL, NULL);
574 ExeModule->EntryPoint = EntryPoint;
575
576 /* all required dlls are loaded now */
577 Peb->Ldr->Initialized = TRUE;
578
579 /* Check before returning that we can run the image safely. */
580 if (EntryPoint == NULL)
581 {
582 DPRINT1("Failed to initialize image\n");
583 ZwTerminateProcess(NtCurrentProcess(), STATUS_INVALID_IMAGE_FORMAT);
584 }
585
586 /* Break into debugger */
587 if (Peb->BeingDebugged)
588 DbgBreakPoint();
589 }
590
591 VOID
592 NTAPI
593 LdrpInit(PCONTEXT Context,
594 PVOID SystemArgument1,
595 PVOID SystemArgument2)
596 {
597 if (!LdrpInitialized)
598 {
599 if (!_InterlockedExchange(&LdrpInitLock, 1))
600 {
601 LdrpInit2(Context, SystemArgument1, SystemArgument2);
602 LdrpInitialized = TRUE;
603 }
604 else
605 {
606 LARGE_INTEGER Interval = {{-200000, -1}};
607
608 do
609 {
610 NtDelayExecution(FALSE, &Interval);
611 }
612 while (!LdrpInitialized);
613 }
614 }
615
616 /* attach the thread */
617 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock);
618 LdrpAttachThread();
619 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
620 }
621
622 /* EOF */