Simplified access to the shared user page.
[reactos.git] / reactos / lib / ntdll / ldr / startup.c
1 /* $Id: startup.c,v 1.37 2002/04/26 13:08:18 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 <user32/callback.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 WCHAR FullNtDllPath[MAX_PATH];
57
58 DPRINT("LdrInitializeThunk()\n");
59
60 Peb = (PPEB)(PEB_BASE);
61 DPRINT("Peb %x\n", Peb);
62 ImageBase = Peb->ImageBaseAddress;
63 DPRINT("ImageBase %x\n", ImageBase);
64 if (ImageBase <= (PVOID)0x1000)
65 {
66 DPRINT("ImageBase is null\n");
67 ZwTerminateProcess(NtCurrentProcess(), STATUS_UNSUCCESSFUL);
68 }
69
70 NtGlobalFlag = Peb->NtGlobalFlag;
71
72 /* If MZ header exists */
73 PEDosHeader = (PIMAGE_DOS_HEADER) ImageBase;
74 DPRINT("PEDosHeader %x\n", PEDosHeader);
75 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC ||
76 PEDosHeader->e_lfanew == 0L ||
77 *(PULONG)((PUCHAR)ImageBase + PEDosHeader->e_lfanew) != IMAGE_PE_MAGIC)
78 {
79 DbgPrint("Image has bad header\n");
80 ZwTerminateProcess(NtCurrentProcess(), STATUS_UNSUCCESSFUL);
81 }
82
83 /* normalize process parameters */
84 RtlNormalizeProcessParams (Peb->ProcessParameters);
85
86 #if 0
87 /* initialize NLS data */
88 RtlInitNlsTables (Peb->AnsiCodePageData,
89 Peb->OemCodePageData,
90 Peb->UnicodeCaseTableData,
91 &TranslationTable);
92 RtlResetRtlTranslations (&TranslationTable);
93 #endif
94
95 NTHeaders = (PIMAGE_NT_HEADERS)(ImageBase + PEDosHeader->e_lfanew);
96
97 /* create process heap */
98 RtlInitializeHeapManager();
99 Peb->ProcessHeap = RtlCreateHeap(0,
100 (PVOID)HEAP_BASE,
101 NTHeaders->OptionalHeader.SizeOfHeapCommit,
102 NTHeaders->OptionalHeader.SizeOfHeapReserve,
103 NULL,
104 NULL);
105 if (Peb->ProcessHeap == 0)
106 {
107 DbgPrint("Failed to create process heap\n");
108 ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
109 }
110
111 /* initalize peb lock support */
112 RtlInitializeCriticalSection (&PebLock);
113 Peb->FastPebLock = &PebLock;
114 Peb->FastPebLockRoutine = (PPEBLOCKROUTINE)RtlEnterCriticalSection;
115 Peb->FastPebUnlockRoutine = (PPEBLOCKROUTINE)RtlLeaveCriticalSection;
116
117 /* initialize tls bitmap */
118 RtlInitializeBitMap (&TlsBitMap,
119 Peb->TlsBitmapBits,
120 TLS_MINIMUM_AVAILABLE);
121 Peb->TlsBitmap = &TlsBitMap;
122 Peb->TlsExpansionCounter = TLS_MINIMUM_AVAILABLE;
123
124 /* Initialize table of callbacks for the kernel. */
125 Peb->KernelCallbackTable =
126 RtlAllocateHeap(RtlGetProcessHeap(),
127 0,
128 sizeof(PVOID) * USER32_CALLBACK_MAXIMUM);
129
130 /* initalize loader lock */
131 RtlInitializeCriticalSection (&LoaderLock);
132 Peb->LoaderLock = &LoaderLock;
133
134 /* create loader information */
135 Peb->Ldr = (PPEB_LDR_DATA)RtlAllocateHeap (Peb->ProcessHeap,
136 0,
137 sizeof(PEB_LDR_DATA));
138 if (Peb->Ldr == NULL)
139 {
140 DbgPrint("Failed to create loader data\n");
141 ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
142 }
143 Peb->Ldr->Length = sizeof(PEB_LDR_DATA);
144 Peb->Ldr->Initialized = FALSE;
145 Peb->Ldr->SsHandle = NULL;
146 InitializeListHead(&Peb->Ldr->InLoadOrderModuleList);
147 InitializeListHead(&Peb->Ldr->InMemoryOrderModuleList);
148 InitializeListHead(&Peb->Ldr->InInitializationOrderModuleList);
149
150 /* build full ntdll path */
151 wcscpy (FullNtDllPath, SharedUserData->NtSystemRoot);
152 wcscat (FullNtDllPath, L"\\system32\\ntdll.dll");
153
154 /* add entry for ntdll */
155 NtModule = (PLDR_MODULE)RtlAllocateHeap (Peb->ProcessHeap,
156 0,
157 sizeof(LDR_MODULE));
158 if (NtModule == NULL)
159 {
160 DbgPrint("Failed to create loader module entry (NTDLL)\n");
161 ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
162 }
163 memset(NtModule, 0, sizeof(LDR_MODULE));
164
165 NtModule->BaseAddress = (PVOID)&_image_base__;
166 NtModule->EntryPoint = 0; /* no entry point */
167 RtlCreateUnicodeString (&NtModule->FullDllName,
168 FullNtDllPath);
169 RtlCreateUnicodeString (&NtModule->BaseDllName,
170 L"ntdll.dll");
171 NtModule->Flags = 0;
172 NtModule->LoadCount = -1; /* don't unload */
173 NtModule->TlsIndex = 0;
174 NtModule->SectionHandle = NULL;
175 NtModule->CheckSum = 0;
176
177 NTHeaders = RtlImageNtHeader (NtModule->BaseAddress);
178 NtModule->SizeOfImage = NTHeaders->OptionalHeader.SizeOfImage;
179 NtModule->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp;
180
181 InsertTailList(&Peb->Ldr->InLoadOrderModuleList,
182 &NtModule->InLoadOrderModuleList);
183 InsertTailList(&Peb->Ldr->InInitializationOrderModuleList,
184 &NtModule->InInitializationOrderModuleList);
185
186 #ifdef KDBG
187 LdrLoadModuleSymbols(NtModule);
188 #endif /* KDBG */
189
190
191 /* add entry for executable (becomes first list entry) */
192 ExeModule = (PLDR_MODULE)RtlAllocateHeap (Peb->ProcessHeap,
193 0,
194 sizeof(LDR_MODULE));
195 if (ExeModule == NULL)
196 {
197 DbgPrint("Failed to create loader module infomation\n");
198 ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
199 }
200 ExeModule->BaseAddress = Peb->ImageBaseAddress;
201
202 if ((Peb->ProcessParameters != NULL) &&
203 (Peb->ProcessParameters->ImagePathName.Length != 0))
204 {
205 RtlCreateUnicodeString (&ExeModule->FullDllName,
206 Peb->ProcessParameters->ImagePathName.Buffer);
207 RtlCreateUnicodeString (&ExeModule->BaseDllName,
208 wcsrchr(ExeModule->FullDllName.Buffer, L'\\') + 1);
209 }
210 else
211 {
212 /* FIXME(???): smss.exe doesn't have a process parameter block */
213 RtlCreateUnicodeString (&ExeModule->BaseDllName,
214 L"smss.exe");
215 RtlCreateUnicodeString (&ExeModule->FullDllName,
216 L"C:\\reactos\\system32\\smss.exe");
217 }
218
219 ExeModule->Flags = 0;
220 ExeModule->LoadCount = -1; /* don't unload */
221 ExeModule->TlsIndex = 0;
222 ExeModule->SectionHandle = NULL;
223 ExeModule->CheckSum = 0;
224
225 NTHeaders = RtlImageNtHeader (ExeModule->BaseAddress);
226 ExeModule->SizeOfImage = NTHeaders->OptionalHeader.SizeOfImage;
227 ExeModule->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp;
228
229 InsertHeadList(&Peb->Ldr->InLoadOrderModuleList,
230 &ExeModule->InLoadOrderModuleList);
231
232 #ifdef KDBG
233 LdrLoadModuleSymbols(ExeModule);
234 #endif /* KDBG */
235
236 EntryPoint = LdrPEStartup((PVOID)ImageBase, NULL);
237 ExeModule->EntryPoint = (ULONG)EntryPoint;
238
239 /* all required dlls are loaded now */
240 Peb->Ldr->Initialized = TRUE;
241
242 if (EntryPoint == NULL)
243 {
244 DbgPrint("Failed to initialize image\n");
245 ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
246 }
247
248 Status = EntryPoint(Peb);
249 ZwTerminateProcess(NtCurrentProcess(),Status);
250 }
251
252 /* EOF */