update for HEAD-2003021201
[reactos.git] / lib / ntdll / ldr / startup.c
1 /* $Id$
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 */