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