1 /* $Id: startup.c,v 1.36 2002/02/08 02:57:06 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 <napi/shared_data.h>
21 #include <user32/callback.h>
24 #include <ntdll/ntdll.h>
27 VOID
RtlInitializeHeapManager (VOID
);
29 /* GLOBALS *******************************************************************/
32 extern unsigned int _image_base__
;
34 static CRITICAL_SECTION PebLock
;
35 static CRITICAL_SECTION LoaderLock
;
36 static RTL_BITMAP TlsBitMap
;
38 ULONG NtGlobalFlag
= 0;
41 /* FUNCTIONS *****************************************************************/
44 LdrInitializeThunk (ULONG Unknown1
,
49 PIMAGE_NT_HEADERS NTHeaders
;
51 PIMAGE_DOS_HEADER PEDosHeader
;
55 PLDR_MODULE NtModule
; // ntdll
56 PLDR_MODULE ExeModule
; // executable
57 PKUSER_SHARED_DATA SharedUserData
=
58 (PKUSER_SHARED_DATA
)USER_SHARED_DATA_BASE
;
59 WCHAR FullNtDllPath
[MAX_PATH
];
61 DPRINT("LdrInitializeThunk()\n");
63 Peb
= (PPEB
)(PEB_BASE
);
64 DPRINT("Peb %x\n", Peb
);
65 ImageBase
= Peb
->ImageBaseAddress
;
66 DPRINT("ImageBase %x\n", ImageBase
);
67 if (ImageBase
<= (PVOID
)0x1000)
69 DPRINT("ImageBase is null\n");
70 ZwTerminateProcess(NtCurrentProcess(), STATUS_UNSUCCESSFUL
);
73 NtGlobalFlag
= Peb
->NtGlobalFlag
;
75 /* If MZ header exists */
76 PEDosHeader
= (PIMAGE_DOS_HEADER
) ImageBase
;
77 DPRINT("PEDosHeader %x\n", PEDosHeader
);
78 if (PEDosHeader
->e_magic
!= IMAGE_DOS_MAGIC
||
79 PEDosHeader
->e_lfanew
== 0L ||
80 *(PULONG
)((PUCHAR
)ImageBase
+ PEDosHeader
->e_lfanew
) != IMAGE_PE_MAGIC
)
82 DbgPrint("Image has bad header\n");
83 ZwTerminateProcess(NtCurrentProcess(), STATUS_UNSUCCESSFUL
);
86 /* normalize process parameters */
87 RtlNormalizeProcessParams (Peb
->ProcessParameters
);
90 /* initialize NLS data */
91 RtlInitNlsTables (Peb
->AnsiCodePageData
,
93 Peb
->UnicodeCaseTableData
,
95 RtlResetRtlTranslations (&TranslationTable
);
98 NTHeaders
= (PIMAGE_NT_HEADERS
)(ImageBase
+ PEDosHeader
->e_lfanew
);
100 /* create process heap */
101 RtlInitializeHeapManager();
102 Peb
->ProcessHeap
= RtlCreateHeap(0,
104 NTHeaders
->OptionalHeader
.SizeOfHeapCommit
,
105 NTHeaders
->OptionalHeader
.SizeOfHeapReserve
,
108 if (Peb
->ProcessHeap
== 0)
110 DbgPrint("Failed to create process heap\n");
111 ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL
);
114 /* initalize peb lock support */
115 RtlInitializeCriticalSection (&PebLock
);
116 Peb
->FastPebLock
= &PebLock
;
117 Peb
->FastPebLockRoutine
= (PPEBLOCKROUTINE
)RtlEnterCriticalSection
;
118 Peb
->FastPebUnlockRoutine
= (PPEBLOCKROUTINE
)RtlLeaveCriticalSection
;
120 /* initialize tls bitmap */
121 RtlInitializeBitMap (&TlsBitMap
,
123 TLS_MINIMUM_AVAILABLE
);
124 Peb
->TlsBitmap
= &TlsBitMap
;
125 Peb
->TlsExpansionCounter
= TLS_MINIMUM_AVAILABLE
;
127 /* Initialize table of callbacks for the kernel. */
128 Peb
->KernelCallbackTable
=
129 RtlAllocateHeap(RtlGetProcessHeap(),
131 sizeof(PVOID
) * USER32_CALLBACK_MAXIMUM
);
133 /* initalize loader lock */
134 RtlInitializeCriticalSection (&LoaderLock
);
135 Peb
->LoaderLock
= &LoaderLock
;
137 /* create loader information */
138 Peb
->Ldr
= (PPEB_LDR_DATA
)RtlAllocateHeap (Peb
->ProcessHeap
,
140 sizeof(PEB_LDR_DATA
));
141 if (Peb
->Ldr
== NULL
)
143 DbgPrint("Failed to create loader data\n");
144 ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL
);
146 Peb
->Ldr
->Length
= sizeof(PEB_LDR_DATA
);
147 Peb
->Ldr
->Initialized
= FALSE
;
148 Peb
->Ldr
->SsHandle
= NULL
;
149 InitializeListHead(&Peb
->Ldr
->InLoadOrderModuleList
);
150 InitializeListHead(&Peb
->Ldr
->InMemoryOrderModuleList
);
151 InitializeListHead(&Peb
->Ldr
->InInitializationOrderModuleList
);
153 /* build full ntdll path */
154 wcscpy (FullNtDllPath
, SharedUserData
->NtSystemRoot
);
155 wcscat (FullNtDllPath
, L
"\\system32\\ntdll.dll");
157 /* add entry for ntdll */
158 NtModule
= (PLDR_MODULE
)RtlAllocateHeap (Peb
->ProcessHeap
,
161 if (NtModule
== NULL
)
163 DbgPrint("Failed to create loader module entry (NTDLL)\n");
164 ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL
);
166 memset(NtModule
, 0, sizeof(LDR_MODULE
));
168 NtModule
->BaseAddress
= (PVOID
)&_image_base__
;
169 NtModule
->EntryPoint
= 0; /* no entry point */
170 RtlCreateUnicodeString (&NtModule
->FullDllName
,
172 RtlCreateUnicodeString (&NtModule
->BaseDllName
,
175 NtModule
->LoadCount
= -1; /* don't unload */
176 NtModule
->TlsIndex
= 0;
177 NtModule
->SectionHandle
= NULL
;
178 NtModule
->CheckSum
= 0;
180 NTHeaders
= RtlImageNtHeader (NtModule
->BaseAddress
);
181 NtModule
->SizeOfImage
= NTHeaders
->OptionalHeader
.SizeOfImage
;
182 NtModule
->TimeDateStamp
= NTHeaders
->FileHeader
.TimeDateStamp
;
184 InsertTailList(&Peb
->Ldr
->InLoadOrderModuleList
,
185 &NtModule
->InLoadOrderModuleList
);
186 InsertTailList(&Peb
->Ldr
->InInitializationOrderModuleList
,
187 &NtModule
->InInitializationOrderModuleList
);
190 LdrLoadModuleSymbols(NtModule
);
194 /* add entry for executable (becomes first list entry) */
195 ExeModule
= (PLDR_MODULE
)RtlAllocateHeap (Peb
->ProcessHeap
,
198 if (ExeModule
== NULL
)
200 DbgPrint("Failed to create loader module infomation\n");
201 ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL
);
203 ExeModule
->BaseAddress
= Peb
->ImageBaseAddress
;
205 if ((Peb
->ProcessParameters
!= NULL
) &&
206 (Peb
->ProcessParameters
->ImagePathName
.Length
!= 0))
208 RtlCreateUnicodeString (&ExeModule
->FullDllName
,
209 Peb
->ProcessParameters
->ImagePathName
.Buffer
);
210 RtlCreateUnicodeString (&ExeModule
->BaseDllName
,
211 wcsrchr(ExeModule
->FullDllName
.Buffer
, L
'\\') + 1);
215 /* FIXME(???): smss.exe doesn't have a process parameter block */
216 RtlCreateUnicodeString (&ExeModule
->BaseDllName
,
218 RtlCreateUnicodeString (&ExeModule
->FullDllName
,
219 L
"C:\\reactos\\system32\\smss.exe");
222 ExeModule
->Flags
= 0;
223 ExeModule
->LoadCount
= -1; /* don't unload */
224 ExeModule
->TlsIndex
= 0;
225 ExeModule
->SectionHandle
= NULL
;
226 ExeModule
->CheckSum
= 0;
228 NTHeaders
= RtlImageNtHeader (ExeModule
->BaseAddress
);
229 ExeModule
->SizeOfImage
= NTHeaders
->OptionalHeader
.SizeOfImage
;
230 ExeModule
->TimeDateStamp
= NTHeaders
->FileHeader
.TimeDateStamp
;
232 InsertHeadList(&Peb
->Ldr
->InLoadOrderModuleList
,
233 &ExeModule
->InLoadOrderModuleList
);
236 LdrLoadModuleSymbols(ExeModule
);
239 EntryPoint
= LdrPEStartup((PVOID
)ImageBase
, NULL
);
240 ExeModule
->EntryPoint
= (ULONG
)EntryPoint
;
242 /* all required dlls are loaded now */
243 Peb
->Ldr
->Initialized
= TRUE
;
245 if (EntryPoint
== NULL
)
247 DbgPrint("Failed to initialize image\n");
248 ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL
);
251 Status
= EntryPoint(Peb
);
252 ZwTerminateProcess(NtCurrentProcess(),Status
);