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