1 /* $Id: startup.c,v 1.44 2002/09/08 10:23:03 chorns Exp $
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(0,
126 NTHeaders
->OptionalHeader
.SizeOfHeapCommit
,
127 NTHeaders
->OptionalHeader
.SizeOfHeapReserve
,
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 RtlCreateUnicodeString (&ExeModule
->FullDllName
,
232 Peb
->ProcessParameters
->ImagePathName
.Buffer
);
233 RtlCreateUnicodeString (&ExeModule
->BaseDllName
,
234 wcsrchr(ExeModule
->FullDllName
.Buffer
, L
'\\') + 1);
238 /* FIXME(???): smss.exe doesn't have a process parameter block */
239 wcscpy (FullNtDllPath
, SharedUserData
->NtSystemRoot
);
240 wcscat (FullNtDllPath
, L
"\\system32\\smss.exe");
241 RtlCreateUnicodeString (&ExeModule
->BaseDllName
,
243 RtlCreateUnicodeString (&ExeModule
->FullDllName
,
247 ExeModule
->Flags
= 0;
248 ExeModule
->LoadCount
= -1; /* don't unload */
249 ExeModule
->TlsIndex
= 0;
250 ExeModule
->SectionHandle
= NULL
;
251 ExeModule
->CheckSum
= 0;
253 NTHeaders
= RtlImageNtHeader (ExeModule
->BaseAddress
);
254 ExeModule
->SizeOfImage
= NTHeaders
->OptionalHeader
.SizeOfImage
;
255 ExeModule
->TimeDateStamp
= NTHeaders
->FileHeader
.TimeDateStamp
;
257 InsertHeadList(&Peb
->Ldr
->InLoadOrderModuleList
,
258 &ExeModule
->InLoadOrderModuleList
);
262 LdrpLoadUserModuleSymbols(ExeModule
);
266 EntryPoint
= LdrPEStartup((PVOID
)ImageBase
, NULL
, NULL
, NULL
);
267 ExeModule
->EntryPoint
= (ULONG
)EntryPoint
;
269 /* all required dlls are loaded now */
270 Peb
->Ldr
->Initialized
= TRUE
;
272 /* Check before returning that we can run the image safely. */
273 if (EntryPoint
== NULL
)
275 DbgPrint("Failed to initialize image\n");
276 ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL
);