5f1a6b92f7b7eae2f381fa33fae8530b9de49c76
[reactos.git] / reactos / lib / ntdll / ldr / startup.c
1 /* $Id: startup.c,v 1.36 2002/02/08 02:57:06 chorns Exp $
2 *
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)
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <reactos/config.h>
14 #include <ddk/ntddk.h>
15 #include <windows.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>
22
23 #define NDEBUG
24 #include <ntdll/ntdll.h>
25
26
27 VOID RtlInitializeHeapManager (VOID);
28
29 /* GLOBALS *******************************************************************/
30
31
32 extern unsigned int _image_base__;
33
34 static CRITICAL_SECTION PebLock;
35 static CRITICAL_SECTION LoaderLock;
36 static RTL_BITMAP TlsBitMap;
37
38 ULONG NtGlobalFlag = 0;
39
40
41 /* FUNCTIONS *****************************************************************/
42
43 VOID STDCALL
44 LdrInitializeThunk (ULONG Unknown1,
45 ULONG Unknown2,
46 ULONG Unknown3,
47 ULONG Unknown4)
48 {
49 PIMAGE_NT_HEADERS NTHeaders;
50 PEPFUNC EntryPoint;
51 PIMAGE_DOS_HEADER PEDosHeader;
52 NTSTATUS Status;
53 PVOID ImageBase;
54 PPEB Peb;
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];
60
61 DPRINT("LdrInitializeThunk()\n");
62
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)
68 {
69 DPRINT("ImageBase is null\n");
70 ZwTerminateProcess(NtCurrentProcess(), STATUS_UNSUCCESSFUL);
71 }
72
73 NtGlobalFlag = Peb->NtGlobalFlag;
74
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)
81 {
82 DbgPrint("Image has bad header\n");
83 ZwTerminateProcess(NtCurrentProcess(), STATUS_UNSUCCESSFUL);
84 }
85
86 /* normalize process parameters */
87 RtlNormalizeProcessParams (Peb->ProcessParameters);
88
89 #if 0
90 /* initialize NLS data */
91 RtlInitNlsTables (Peb->AnsiCodePageData,
92 Peb->OemCodePageData,
93 Peb->UnicodeCaseTableData,
94 &TranslationTable);
95 RtlResetRtlTranslations (&TranslationTable);
96 #endif
97
98 NTHeaders = (PIMAGE_NT_HEADERS)(ImageBase + PEDosHeader->e_lfanew);
99
100 /* create process heap */
101 RtlInitializeHeapManager();
102 Peb->ProcessHeap = RtlCreateHeap(0,
103 (PVOID)HEAP_BASE,
104 NTHeaders->OptionalHeader.SizeOfHeapCommit,
105 NTHeaders->OptionalHeader.SizeOfHeapReserve,
106 NULL,
107 NULL);
108 if (Peb->ProcessHeap == 0)
109 {
110 DbgPrint("Failed to create process heap\n");
111 ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
112 }
113
114 /* initalize peb lock support */
115 RtlInitializeCriticalSection (&PebLock);
116 Peb->FastPebLock = &PebLock;
117 Peb->FastPebLockRoutine = (PPEBLOCKROUTINE)RtlEnterCriticalSection;
118 Peb->FastPebUnlockRoutine = (PPEBLOCKROUTINE)RtlLeaveCriticalSection;
119
120 /* initialize tls bitmap */
121 RtlInitializeBitMap (&TlsBitMap,
122 Peb->TlsBitmapBits,
123 TLS_MINIMUM_AVAILABLE);
124 Peb->TlsBitmap = &TlsBitMap;
125 Peb->TlsExpansionCounter = TLS_MINIMUM_AVAILABLE;
126
127 /* Initialize table of callbacks for the kernel. */
128 Peb->KernelCallbackTable =
129 RtlAllocateHeap(RtlGetProcessHeap(),
130 0,
131 sizeof(PVOID) * USER32_CALLBACK_MAXIMUM);
132
133 /* initalize loader lock */
134 RtlInitializeCriticalSection (&LoaderLock);
135 Peb->LoaderLock = &LoaderLock;
136
137 /* create loader information */
138 Peb->Ldr = (PPEB_LDR_DATA)RtlAllocateHeap (Peb->ProcessHeap,
139 0,
140 sizeof(PEB_LDR_DATA));
141 if (Peb->Ldr == NULL)
142 {
143 DbgPrint("Failed to create loader data\n");
144 ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
145 }
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);
152
153 /* build full ntdll path */
154 wcscpy (FullNtDllPath, SharedUserData->NtSystemRoot);
155 wcscat (FullNtDllPath, L"\\system32\\ntdll.dll");
156
157 /* add entry for ntdll */
158 NtModule = (PLDR_MODULE)RtlAllocateHeap (Peb->ProcessHeap,
159 0,
160 sizeof(LDR_MODULE));
161 if (NtModule == NULL)
162 {
163 DbgPrint("Failed to create loader module entry (NTDLL)\n");
164 ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
165 }
166 memset(NtModule, 0, sizeof(LDR_MODULE));
167
168 NtModule->BaseAddress = (PVOID)&_image_base__;
169 NtModule->EntryPoint = 0; /* no entry point */
170 RtlCreateUnicodeString (&NtModule->FullDllName,
171 FullNtDllPath);
172 RtlCreateUnicodeString (&NtModule->BaseDllName,
173 L"ntdll.dll");
174 NtModule->Flags = 0;
175 NtModule->LoadCount = -1; /* don't unload */
176 NtModule->TlsIndex = 0;
177 NtModule->SectionHandle = NULL;
178 NtModule->CheckSum = 0;
179
180 NTHeaders = RtlImageNtHeader (NtModule->BaseAddress);
181 NtModule->SizeOfImage = NTHeaders->OptionalHeader.SizeOfImage;
182 NtModule->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp;
183
184 InsertTailList(&Peb->Ldr->InLoadOrderModuleList,
185 &NtModule->InLoadOrderModuleList);
186 InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
187 &NtModule->InInitializationOrderModuleList);
188
189 #ifdef KDBG
190 LdrLoadModuleSymbols(NtModule);
191 #endif /* KDBG */
192
193
194 /* add entry for executable (becomes first list entry) */
195 ExeModule = (PLDR_MODULE)RtlAllocateHeap (Peb->ProcessHeap,
196 0,
197 sizeof(LDR_MODULE));
198 if (ExeModule == NULL)
199 {
200 DbgPrint("Failed to create loader module infomation\n");
201 ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
202 }
203 ExeModule->BaseAddress = Peb->ImageBaseAddress;
204
205 if ((Peb->ProcessParameters != NULL) &&
206 (Peb->ProcessParameters->ImagePathName.Length != 0))
207 {
208 RtlCreateUnicodeString (&ExeModule->FullDllName,
209 Peb->ProcessParameters->ImagePathName.Buffer);
210 RtlCreateUnicodeString (&ExeModule->BaseDllName,
211 wcsrchr(ExeModule->FullDllName.Buffer, L'\\') + 1);
212 }
213 else
214 {
215 /* FIXME(???): smss.exe doesn't have a process parameter block */
216 RtlCreateUnicodeString (&ExeModule->BaseDllName,
217 L"smss.exe");
218 RtlCreateUnicodeString (&ExeModule->FullDllName,
219 L"C:\\reactos\\system32\\smss.exe");
220 }
221
222 ExeModule->Flags = 0;
223 ExeModule->LoadCount = -1; /* don't unload */
224 ExeModule->TlsIndex = 0;
225 ExeModule->SectionHandle = NULL;
226 ExeModule->CheckSum = 0;
227
228 NTHeaders = RtlImageNtHeader (ExeModule->BaseAddress);
229 ExeModule->SizeOfImage = NTHeaders->OptionalHeader.SizeOfImage;
230 ExeModule->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp;
231
232 InsertHeadList(&Peb->Ldr->InLoadOrderModuleList,
233 &ExeModule->InLoadOrderModuleList);
234
235 #ifdef KDBG
236 LdrLoadModuleSymbols(ExeModule);
237 #endif /* KDBG */
238
239 EntryPoint = LdrPEStartup((PVOID)ImageBase, NULL);
240 ExeModule->EntryPoint = (ULONG)EntryPoint;
241
242 /* all required dlls are loaded now */
243 Peb->Ldr->Initialized = TRUE;
244
245 if (EntryPoint == NULL)
246 {
247 DbgPrint("Failed to initialize image\n");
248 ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
249 }
250
251 Status = EntryPoint(Peb);
252 ZwTerminateProcess(NtCurrentProcess(),Status);
253 }
254
255 /* EOF */