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