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