3 * Copyright (C) 1998, 1999, 2000, 2001, 2002 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 * PROJECT: ReactOS kernel
21 * FILE: ntoskrnl/ldr/init.c
22 * PURPOSE: Loaders for PE executables
23 * PROGRAMMERS: Jean Michault
24 * Rex Jolliff (rex@lvcablemodem.com)
27 * RJJ 10/12/98 Completed image loader function and added hooks for MZ/PE
28 * RJJ 10/12/98 Built driver loader function and added hooks for PE/COFF
29 * RJJ 10/12/98 Rolled in David's code to load COFF drivers
30 * JM 14/12/98 Built initial PE user module loader
31 * RJJ 06/03/99 Moved user PE loader into NTDLL
32 * EA 19990717 LdrGetSystemDirectory()
33 * EK 20000618 Using SystemRoot link instead of LdrGetSystemDirectory()
36 /* INCLUDES *****************************************************************/
38 #include <ddk/ntddk.h>
39 #include <internal/i386/segment.h>
40 #include <internal/module.h>
41 #include <internal/ntoskrnl.h>
42 #include <internal/ob.h>
43 #include <internal/ps.h>
44 #include <internal/ldr.h>
48 #include <internal/debug.h>
50 /* FUNCTIONS *****************************************************************/
53 * FIXME: The location of the initial process should be configurable,
54 * from command line or registry
56 NTSTATUS
LdrLoadInitialProcess (VOID
)
60 UNICODE_STRING ProcessName
;
61 OBJECT_ATTRIBUTES ObjectAttributes
;
64 PIMAGE_NT_HEADERS NTHeaders
;
68 INITIAL_TEB InitialTeb
;
69 ULONG OldPageProtection
;
70 SECTION_IMAGE_INFORMATION Sii
;
72 PVOID ImageBaseAddress
;
73 ULONG InitialStack
[5];
76 * Get the absolute path to smss.exe using the
79 RtlInitUnicodeString(&ProcessName
,
80 L
"\\SystemRoot\\system32\\smss.exe");
83 * Open process image to determine ImageBase
86 InitializeObjectAttributes(&ObjectAttributes
,
91 DPRINT("Opening image file %S\n", ObjectAttributes
.ObjectName
->Buffer
);
92 Status
= ZwOpenFile(&FileHandle
,
98 if (!NT_SUCCESS(Status
))
100 DPRINT("Image open failed (Status was %x)\n", Status
);
105 * Create a section for the image
107 DPRINT("Creating section\n");
108 Status
= ZwCreateSection(&SectionHandle
,
113 SEC_COMMIT
| SEC_IMAGE
,
115 if (!NT_SUCCESS(Status
))
117 DPRINT("ZwCreateSection failed (Status %x)\n", Status
);
124 * Get information about the process image.
126 Status
= ZwQuerySection(SectionHandle
,
127 SectionImageInformation
,
131 if (!NT_SUCCESS(Status
) || ResultLength
!= sizeof(Sii
))
133 DPRINT("ZwQuerySection failed (Status %X)\n", Status
);
134 ZwClose(SectionHandle
);
138 DPRINT("Creating process\n");
139 Status
= ZwCreateProcess(&ProcessHandle
,
147 if (!NT_SUCCESS(Status
))
149 DPRINT("Could not create process\n");
154 * Create initial stack and thread
158 * Create page backed section for stack
160 DPRINT("Allocating stack\n");
162 DPRINT("Referencing process\n");
163 Status
= ObReferenceObjectByHandle(ProcessHandle
,
169 if (!NT_SUCCESS(Status
))
171 DPRINT("ObReferenceObjectByProcess() failed (Status %x)\n", Status
);
175 DPRINT("Attaching to process\n");
176 KeAttachProcess(Process
);
177 ImageBaseAddress
= Process
->Peb
->ImageBaseAddress
;
178 NTHeaders
= RtlImageNtHeader(ImageBaseAddress
);
179 DPRINT("NTHeaders %x\n", NTHeaders
);
180 InitialTeb
.StackReserve
= NTHeaders
->OptionalHeader
.SizeOfStackReserve
;
181 /* FIXME: use correct commit size */
182 InitialTeb
.StackCommit
= NTHeaders
->OptionalHeader
.SizeOfStackReserve
- PAGESIZE
;
183 // InitialTeb.StackCommit = NTHeaders->OptionalHeader.SizeOfStackCommit;
184 /* add guard page size */
185 InitialTeb
.StackCommit
+= PAGESIZE
;
186 DPRINT("StackReserve 0x%lX StackCommit 0x%lX\n",
187 InitialTeb
.StackReserve
, InitialTeb
.StackCommit
);
189 DPRINT("Dereferencing process\n");
190 ObDereferenceObject(Process
);
192 DPRINT("Allocating stack\n");
193 InitialTeb
.StackAllocate
= NULL
;
194 Status
= NtAllocateVirtualMemory(ProcessHandle
,
195 &InitialTeb
.StackAllocate
,
197 &InitialTeb
.StackReserve
,
200 if (!NT_SUCCESS(Status
))
202 DPRINT("Stack allocation failed (Status %x)", Status
);
206 DPRINT("StackAllocate: %p ReserveSize: 0x%lX\n",
207 InitialTeb
.StackAllocate
, InitialTeb
.StackReserve
);
209 InitialTeb
.StackBase
= (PVOID
)((ULONG
)InitialTeb
.StackAllocate
+ InitialTeb
.StackReserve
);
210 InitialTeb
.StackLimit
= (PVOID
)((ULONG
)InitialTeb
.StackBase
- InitialTeb
.StackCommit
);
212 DPRINT("StackBase: %p StackCommit: 0x%lX\n",
213 InitialTeb
.StackBase
, InitialTeb
.StackCommit
);
216 Status
= NtAllocateVirtualMemory(ProcessHandle
,
217 &InitialTeb
.StackLimit
,
219 &InitialTeb
.StackCommit
,
222 if (!NT_SUCCESS(Status
))
224 /* release the stack space */
225 NtFreeVirtualMemory(ProcessHandle
,
226 InitialTeb
.StackAllocate
,
227 &InitialTeb
.StackReserve
,
230 DPRINT("Error comitting stack page!\n");
234 DPRINT("StackLimit: %p\nStackCommit: 0x%lX\n",
235 InitialTeb
.StackLimit
,
236 InitialTeb
.StackCommit
);
238 /* Protect guard page */
239 Status
= NtProtectVirtualMemory(ProcessHandle
,
240 InitialTeb
.StackLimit
,
242 PAGE_GUARD
| PAGE_READWRITE
,
244 if (!NT_SUCCESS(Status
))
246 /* release the stack space */
247 NtFreeVirtualMemory(ProcessHandle
,
248 InitialTeb
.StackAllocate
,
249 &InitialTeb
.StackReserve
,
252 DPRINT("Error protecting guard page!\n");
257 * Initialize context to point to LdrStartup
259 memset(&Context
,0,sizeof(CONTEXT
));
260 Context
.Eip
= (ULONG
)(ImageBaseAddress
+ (ULONG
)Sii
.EntryPoint
);
261 Context
.SegCs
= USER_CS
;
262 Context
.SegDs
= USER_DS
;
263 Context
.SegEs
= USER_DS
;
264 Context
.SegFs
= TEB_SELECTOR
;
265 Context
.SegGs
= USER_DS
;
266 Context
.SegSs
= USER_DS
;
267 Context
.EFlags
= 0x202;
268 Context
.Esp
= (ULONG
)InitialTeb
.StackBase
- 20;
271 * Write in the initial stack.
274 InitialStack
[1] = PEB_BASE
;
275 Status
= ZwWriteVirtualMemory(ProcessHandle
,
278 sizeof(InitialStack
),
280 if (!NT_SUCCESS(Status
))
282 DPRINT1("Failed to write initial stack.\n");
287 * FIXME: Create process and let 'er rip
289 DPRINT("Creating thread for initial process\n");
290 Status
= ZwCreateThread(&ThreadHandle
,
298 if (!NT_SUCCESS(Status
))
300 DPRINT("Thread creation failed (Status %x)\n", Status
);
302 NtFreeVirtualMemory(ProcessHandle
,
303 InitialTeb
.StackAllocate
,
304 &InitialTeb
.StackReserve
,
307 /* FIXME: unmap the section here */
308 /* FIXME: destroy the section here */
309 /* FIXME: Kill the process here */
314 return(STATUS_SUCCESS
);