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 __true_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 Peb->OSMajorVersion = 4;
96 Peb->OSMinorVersion = 0;
97 Peb->OSBuildNumber = 0;
98 Peb->OSPlatformId = VER_PLATFORM_WIN32_NT;
100 NtGlobalFlag = Peb->NtGlobalFlag;
102 /* If MZ header exists */
103 PEDosHeader = (PIMAGE_DOS_HEADER) ImageBase;
104 DPRINT("PEDosHeader %x\n", PEDosHeader);
105 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC ||
106 PEDosHeader->e_lfanew == 0L ||
107 *(PULONG)((PUCHAR)ImageBase + PEDosHeader->e_lfanew) != IMAGE_PE_MAGIC)
109 DbgPrint("Image has bad header\n");
110 ZwTerminateProcess(NtCurrentProcess(), STATUS_UNSUCCESSFUL);
113 /* normalize process parameters */
114 RtlNormalizeProcessParams (Peb->ProcessParameters);
117 /* initialize NLS data */
118 RtlInitNlsTables (Peb->AnsiCodePageData,
119 Peb->OemCodePageData,
120 Peb->UnicodeCaseTableData,
122 RtlResetRtlTranslations (&TranslationTable);
125 NTHeaders = (PIMAGE_NT_HEADERS)(ImageBase + PEDosHeader->e_lfanew);
127 /* create process heap */
128 RtlInitializeHeapManager();
129 Peb->ProcessHeap = RtlCreateHeap(HEAP_GROWABLE,
131 NTHeaders->OptionalHeader.SizeOfHeapReserve,
132 NTHeaders->OptionalHeader.SizeOfHeapCommit,
135 if (Peb->ProcessHeap == 0)
137 DbgPrint("Failed to create process heap\n");
138 ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
141 /* initalize peb lock support */
142 RtlInitializeCriticalSection (&PebLock);
143 Peb->FastPebLock = &PebLock;
144 Peb->FastPebLockRoutine = (PPEBLOCKROUTINE)RtlEnterCriticalSection;
145 Peb->FastPebUnlockRoutine = (PPEBLOCKROUTINE)RtlLeaveCriticalSection;
147 /* initialize tls bitmap */
148 RtlInitializeBitMap (&TlsBitMap,
150 TLS_MINIMUM_AVAILABLE);
151 Peb->TlsBitmap = &TlsBitMap;
152 Peb->TlsExpansionCounter = TLS_MINIMUM_AVAILABLE;
154 /* Initialize table of callbacks for the kernel. */
155 Peb->KernelCallbackTable =
156 RtlAllocateHeap(RtlGetProcessHeap(),
158 sizeof(PVOID) * USER32_CALLBACK_MAXIMUM);
160 /* initalize loader lock */
161 RtlInitializeCriticalSection (&LoaderLock);
162 Peb->LoaderLock = &LoaderLock;
164 /* create loader information */
165 Peb->Ldr = (PPEB_LDR_DATA)RtlAllocateHeap (Peb->ProcessHeap,
167 sizeof(PEB_LDR_DATA));
168 if (Peb->Ldr == NULL)
170 DbgPrint("Failed to create loader data\n");
171 ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
173 Peb->Ldr->Length = sizeof(PEB_LDR_DATA);
174 Peb->Ldr->Initialized = FALSE;
175 Peb->Ldr->SsHandle = NULL;
176 InitializeListHead(&Peb->Ldr->InLoadOrderModuleList);
177 InitializeListHead(&Peb->Ldr->InMemoryOrderModuleList);
178 InitializeListHead(&Peb->Ldr->InInitializationOrderModuleList);
180 /* build full ntdll path */
181 wcscpy (FullNtDllPath, SharedUserData->NtSystemRoot);
182 wcscat (FullNtDllPath, L"\\system32\\ntdll.dll");
184 /* add entry for ntdll */
185 NtModule = (PLDR_MODULE)RtlAllocateHeap (Peb->ProcessHeap,
188 if (NtModule == NULL)
190 DbgPrint("Failed to create loader module entry (NTDLL)\n");
191 ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
193 memset(NtModule, 0, sizeof(LDR_MODULE));
195 NtModule->BaseAddress = (PVOID)&_image_base__;
196 NtModule->EntryPoint = 0; /* no entry point */
197 RtlCreateUnicodeString (&NtModule->FullDllName,
199 RtlCreateUnicodeString (&NtModule->BaseDllName,
202 NtModule->LoadCount = -1; /* don't unload */
203 NtModule->TlsIndex = 0;
204 NtModule->SectionHandle = NULL;
205 NtModule->CheckSum = 0;
207 NTHeaders = RtlImageNtHeader (NtModule->BaseAddress);
208 NtModule->SizeOfImage = NTHeaders->OptionalHeader.SizeOfImage;
209 NtModule->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp;
211 InsertTailList(&Peb->Ldr->InLoadOrderModuleList,
212 &NtModule->InLoadOrderModuleList);
213 InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
214 &NtModule->InInitializationOrderModuleList);
218 LdrpLoadUserModuleSymbols(NtModule);
222 /* add entry for executable (becomes first list entry) */
223 ExeModule = (PLDR_MODULE)RtlAllocateHeap (Peb->ProcessHeap,
226 if (ExeModule == NULL)
228 DbgPrint("Failed to create loader module infomation\n");
229 ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
231 ExeModule->BaseAddress = Peb->ImageBaseAddress;
233 if ((Peb->ProcessParameters == NULL) ||
234 (Peb->ProcessParameters->ImagePathName.Length == 0))
236 DbgPrint("Failed to access the process parameter block\n");
237 ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
240 RtlCreateUnicodeString(&ExeModule->FullDllName,
241 Peb->ProcessParameters->ImagePathName.Buffer);
242 RtlCreateUnicodeString(&ExeModule->BaseDllName,
243 wcsrchr(ExeModule->FullDllName.Buffer, L'\\') + 1);
245 DPRINT("BaseDllName '%wZ' FullDllName '%wZ'\n",
246 &ExeModule->BaseDllName,
247 &ExeModule->FullDllName);
249 ExeModule->Flags = 0;
250 ExeModule->LoadCount = -1; /* don't unload */
251 ExeModule->TlsIndex = 0;
252 ExeModule->SectionHandle = NULL;
253 ExeModule->CheckSum = 0;
255 NTHeaders = RtlImageNtHeader (ExeModule->BaseAddress);
256 ExeModule->SizeOfImage = NTHeaders->OptionalHeader.SizeOfImage;
257 ExeModule->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp;
259 InsertHeadList(&Peb->Ldr->InLoadOrderModuleList,
260 &ExeModule->InLoadOrderModuleList);
264 LdrpLoadUserModuleSymbols(ExeModule);
268 EntryPoint = LdrPEStartup((PVOID)ImageBase, NULL, NULL, NULL);
269 ExeModule->EntryPoint = (ULONG)EntryPoint;
271 /* all required dlls are loaded now */
272 Peb->Ldr->Initialized = TRUE;
274 /* Check before returning that we can run the image safely. */
275 if (EntryPoint == NULL)
277 DbgPrint("Failed to initialize image\n");
278 ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);