3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: lib/ntdll/ldr/startup.c
6 * PURPOSE: Process startup for PE executables
7 * PROGRAMMERS: Jean Michault
8 * Rex Jolliff (rex@lvcablemodem.com)
11 /* INCLUDES *****************************************************************/
13 #include <reactos/config.h>
14 #include <ddk/ntddk.h>
16 #include <ntdll/ldr.h>
17 #include <ntdll/rtl.h>
18 #include <csrss/csrss.h>
19 #include <ntdll/csr.h>
20 #include <user32/callback.h>
23 #include <ntdll/ntdll.h>
26 VOID RtlInitializeHeapManager (VOID);
28 /* GLOBALS *******************************************************************/
31 extern unsigned int _image_base__;
33 static CRITICAL_SECTION PebLock;
34 static CRITICAL_SECTION LoaderLock;
35 static RTL_BITMAP TlsBitMap;
37 ULONG NtGlobalFlag = 0;
40 /* FUNCTIONS *****************************************************************/
43 LdrInitializeThunk (ULONG Unknown1,
48 PIMAGE_NT_HEADERS NTHeaders;
50 PIMAGE_DOS_HEADER PEDosHeader;
54 PLDR_MODULE NtModule; // ntdll
55 PLDR_MODULE ExeModule; // executable
56 WCHAR FullNtDllPath[MAX_PATH];
58 DPRINT("LdrInitializeThunk()\n");
59 if (NtCurrentPeb()->Ldr != NULL && NtCurrentPeb()->Ldr->Initialized == TRUE)
61 PLIST_ENTRY current_entry;
62 PDLLMAIN_FUNC Entrypoint;
65 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
67 NtCurrentPeb()->Ldr->InInitializationOrderModuleList.Flink;
68 while (current_entry !=
69 &NtCurrentPeb()->Ldr->InInitializationOrderModuleList)
71 current = CONTAINING_RECORD(current_entry, LDR_MODULE,
72 InInitializationOrderModuleList);
73 Entrypoint = (PDLLMAIN_FUNC)current->EntryPoint;
74 if (Entrypoint != NULL &&
75 current->BaseAddress != NtCurrentPeb()->ImageBaseAddress)
77 (VOID)Entrypoint(current->BaseAddress, DLL_THREAD_ATTACH, NULL);
79 current_entry = current_entry->Flink;
81 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
85 Peb = (PPEB)(PEB_BASE);
86 DPRINT("Peb %x\n", Peb);
87 ImageBase = Peb->ImageBaseAddress;
88 DPRINT("ImageBase %x\n", ImageBase);
89 if (ImageBase <= (PVOID)0x1000)
91 DPRINT("ImageBase is null\n");
92 ZwTerminateProcess(NtCurrentProcess(), STATUS_UNSUCCESSFUL);
95 NtGlobalFlag = Peb->NtGlobalFlag;
97 /* If MZ header exists */
98 PEDosHeader = (PIMAGE_DOS_HEADER) ImageBase;
99 DPRINT("PEDosHeader %x\n", PEDosHeader);
100 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC ||
101 PEDosHeader->e_lfanew == 0L ||
102 *(PULONG)((PUCHAR)ImageBase + PEDosHeader->e_lfanew) != IMAGE_PE_MAGIC)
104 DbgPrint("Image has bad header\n");
105 ZwTerminateProcess(NtCurrentProcess(), STATUS_UNSUCCESSFUL);
108 /* normalize process parameters */
109 RtlNormalizeProcessParams (Peb->ProcessParameters);
112 /* initialize NLS data */
113 RtlInitNlsTables (Peb->AnsiCodePageData,
114 Peb->OemCodePageData,
115 Peb->UnicodeCaseTableData,
117 RtlResetRtlTranslations (&TranslationTable);
120 NTHeaders = (PIMAGE_NT_HEADERS)(ImageBase + PEDosHeader->e_lfanew);
122 /* create process heap */
123 RtlInitializeHeapManager();
124 Peb->ProcessHeap = RtlCreateHeap(HEAP_GROWABLE,
126 NTHeaders->OptionalHeader.SizeOfHeapReserve,
127 NTHeaders->OptionalHeader.SizeOfHeapCommit,
130 if (Peb->ProcessHeap == 0)
132 DbgPrint("Failed to create process heap\n");
133 ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
136 /* initalize peb lock support */
137 RtlInitializeCriticalSection (&PebLock);
138 Peb->FastPebLock = &PebLock;
139 Peb->FastPebLockRoutine = (PPEBLOCKROUTINE)RtlEnterCriticalSection;
140 Peb->FastPebUnlockRoutine = (PPEBLOCKROUTINE)RtlLeaveCriticalSection;
142 /* initialize tls bitmap */
143 RtlInitializeBitMap (&TlsBitMap,
145 TLS_MINIMUM_AVAILABLE);
146 Peb->TlsBitmap = &TlsBitMap;
147 Peb->TlsExpansionCounter = TLS_MINIMUM_AVAILABLE;
149 /* Initialize table of callbacks for the kernel. */
150 Peb->KernelCallbackTable =
151 RtlAllocateHeap(RtlGetProcessHeap(),
153 sizeof(PVOID) * USER32_CALLBACK_MAXIMUM);
155 /* initalize loader lock */
156 RtlInitializeCriticalSection (&LoaderLock);
157 Peb->LoaderLock = &LoaderLock;
159 /* create loader information */
160 Peb->Ldr = (PPEB_LDR_DATA)RtlAllocateHeap (Peb->ProcessHeap,
162 sizeof(PEB_LDR_DATA));
163 if (Peb->Ldr == NULL)
165 DbgPrint("Failed to create loader data\n");
166 ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
168 Peb->Ldr->Length = sizeof(PEB_LDR_DATA);
169 Peb->Ldr->Initialized = FALSE;
170 Peb->Ldr->SsHandle = NULL;
171 InitializeListHead(&Peb->Ldr->InLoadOrderModuleList);
172 InitializeListHead(&Peb->Ldr->InMemoryOrderModuleList);
173 InitializeListHead(&Peb->Ldr->InInitializationOrderModuleList);
175 /* build full ntdll path */
176 wcscpy (FullNtDllPath, SharedUserData->NtSystemRoot);
177 wcscat (FullNtDllPath, L"\\system32\\ntdll.dll");
179 /* add entry for ntdll */
180 NtModule = (PLDR_MODULE)RtlAllocateHeap (Peb->ProcessHeap,
183 if (NtModule == NULL)
185 DbgPrint("Failed to create loader module entry (NTDLL)\n");
186 ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
188 memset(NtModule, 0, sizeof(LDR_MODULE));
190 NtModule->BaseAddress = (PVOID)&_image_base__;
191 NtModule->EntryPoint = 0; /* no entry point */
192 RtlCreateUnicodeString (&NtModule->FullDllName,
194 RtlCreateUnicodeString (&NtModule->BaseDllName,
197 NtModule->LoadCount = -1; /* don't unload */
198 NtModule->TlsIndex = 0;
199 NtModule->SectionHandle = NULL;
200 NtModule->CheckSum = 0;
202 NTHeaders = RtlImageNtHeader (NtModule->BaseAddress);
203 NtModule->SizeOfImage = NTHeaders->OptionalHeader.SizeOfImage;
204 NtModule->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp;
206 InsertTailList(&Peb->Ldr->InLoadOrderModuleList,
207 &NtModule->InLoadOrderModuleList);
208 InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
209 &NtModule->InInitializationOrderModuleList);
213 LdrpLoadUserModuleSymbols(NtModule);
217 /* add entry for executable (becomes first list entry) */
218 ExeModule = (PLDR_MODULE)RtlAllocateHeap (Peb->ProcessHeap,
221 if (ExeModule == NULL)
223 DbgPrint("Failed to create loader module infomation\n");
224 ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
226 ExeModule->BaseAddress = Peb->ImageBaseAddress;
228 if ((Peb->ProcessParameters == NULL) ||
229 (Peb->ProcessParameters->ImagePathName.Length == 0))
231 DbgPrint("Failed to access the process parameter block\n");
232 ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
235 RtlCreateUnicodeString(&ExeModule->FullDllName,
236 Peb->ProcessParameters->ImagePathName.Buffer);
237 RtlCreateUnicodeString(&ExeModule->BaseDllName,
238 wcsrchr(ExeModule->FullDllName.Buffer, L'\\') + 1);
240 DPRINT("BaseDllName '%wZ' FullDllName '%wZ'\n",
241 &ExeModule->BaseDllName,
242 &ExeModule->FullDllName);
244 ExeModule->Flags = 0;
245 ExeModule->LoadCount = -1; /* don't unload */
246 ExeModule->TlsIndex = 0;
247 ExeModule->SectionHandle = NULL;
248 ExeModule->CheckSum = 0;
250 NTHeaders = RtlImageNtHeader (ExeModule->BaseAddress);
251 ExeModule->SizeOfImage = NTHeaders->OptionalHeader.SizeOfImage;
252 ExeModule->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp;
254 InsertHeadList(&Peb->Ldr->InLoadOrderModuleList,
255 &ExeModule->InLoadOrderModuleList);
259 LdrpLoadUserModuleSymbols(ExeModule);
263 EntryPoint = LdrPEStartup((PVOID)ImageBase, NULL, NULL, NULL);
264 ExeModule->EntryPoint = (ULONG)EntryPoint;
266 /* all required dlls are loaded now */
267 Peb->Ldr->Initialized = TRUE;
269 /* Check before returning that we can run the image safely. */
270 if (EntryPoint == NULL)
272 DbgPrint("Failed to initialize image\n");
273 ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);