2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ldr/loader.c
5 * PURPOSE: Loaders for PE executables
6 * PROGRAMMERS: Jean Michault
7 * Rex Jolliff (rex@lvcablemodem.com)
10 * RJJ 10/12/98 Completed image loader function and added hooks for MZ/PE
11 * RJJ 10/12/98 Built driver loader function and added hooks for PE/COFF
12 * RJJ 10/12/98 Rolled in David's code to load COFF drivers
13 * JM 14/12/98 Built initial PE user module loader
14 * RJJ 06/03/99 Moved user PE loader into NTDLL
15 * EA 19990717 GetSystemDirectory()
18 /* INCLUDES *****************************************************************/
22 #include <internal/i386/segment.h>
23 #include <internal/linkage.h>
24 #include <internal/module.h>
25 #include <internal/ntoskrnl.h>
26 #include <internal/ob.h>
27 #include <internal/ps.h>
29 #include <internal/string.h>
30 #include <internal/symbol.h>
31 #include <internal/teb.h>
32 #include <ddk/ntddk.h>
35 #include <internal/debug.h>
40 /* FUNCTIONS ****************************************************************/
42 /**********************************************************************
47 * Builds the initial environment for a process. Should be used
48 * to load the initial user process.
51 * HANDLE ProcessHandle handle of the process to load the module into
52 * PUNICODE_STRING Filename name of the module to load
58 #define STACK_TOP (0xb0000000)
62 LdrCreatePeb(HANDLE ProcessHandle
)
71 PebBase
= (PVOID
)PEB_BASE
;
73 Status
= ZwAllocateVirtualMemory(
81 if (!NT_SUCCESS(Status
))
92 Peb
.StartupInfo
= (PPROCESSINFOW
) PEB_STARTUPINFO
;
102 return(STATUS_SUCCESS
);
108 HANDLE ProcessHandle
,
109 PUNICODE_STRING Filename
112 CHAR BlockBuffer
[1024];
114 DWORD LdrStartupAddr
;
119 OBJECT_ATTRIBUTES FileObjectAttributes
;
121 HANDLE SectionHandle
;
122 HANDLE NTDllSectionHandle
;
124 HANDLE DupNTDllSectionHandle
;
126 UNICODE_STRING DllPathname
;
127 PIMAGE_DOS_HEADER DosHeader
;
128 PIMAGE_NT_HEADERS NTHeaders
;
130 ULONG InitialViewSize
;
132 HANDLE DupSectionHandle
;
134 WCHAR TmpNameBuffer
[MAX_PATH
];
140 * Locate and open NTDLL to determine ImageBase
151 RtlInitUnicodeString(
155 InitializeObjectAttributes(
156 & FileObjectAttributes
,
162 DPRINT("Opening NTDLL\n");
166 & FileObjectAttributes
,
171 if (!NT_SUCCESS(Status
))
173 DPRINT("NTDLL open failed ");
174 DbgPrintErrorMessage(Status
);
189 if (!NT_SUCCESS(Status
))
191 DPRINT("NTDLL header read failed ");
192 DbgPrintErrorMessage(Status
);
198 * FIXME: this will fail if the NT headers are
199 * more than 1024 bytes from start.
201 DosHeader
= (PIMAGE_DOS_HEADER
) BlockBuffer
;
202 NTHeaders
= (PIMAGE_NT_HEADERS
) (BlockBuffer
+ DosHeader
->e_lfanew
);
204 (DosHeader
->e_magic
!= IMAGE_DOS_MAGIC
)
205 || (DosHeader
->e_lfanew
== 0L)
206 || (*(PULONG
) NTHeaders
!= IMAGE_PE_MAGIC
)
209 DPRINT("NTDLL format invalid\n");
212 return STATUS_UNSUCCESSFUL
;
214 ImageBase
= NTHeaders
->OptionalHeader
.ImageBase
;
215 ImageSize
= NTHeaders
->OptionalHeader
.SizeOfImage
;
217 * FIXME: retrieve the offset of LdrStartup from NTDLL
219 DPRINT("ImageBase %x\n",ImageBase
);
222 + NTHeaders
->OptionalHeader
.AddressOfEntryPoint
;
224 * Create a section for NTDLL
226 Status
= ZwCreateSection(
227 & NTDllSectionHandle
,
235 if (!NT_SUCCESS(Status
))
237 DPRINT("NTDLL create section failed ");
238 DbgPrintErrorMessage(Status
);
244 * Map the NTDLL into the process
248 + sizeof (IMAGE_NT_HEADERS
)
249 + ( sizeof (IMAGE_SECTION_HEADER
)
250 * NTHeaders
->FileHeader
.NumberOfSections
252 Status
= ZwMapViewOfSection(
255 (PVOID
*) & ImageBase
,
264 if (!NT_SUCCESS(Status
))
266 DPRINT("NTDLL map view of secion failed ");
267 DbgPrintErrorMessage(Status
);
269 /* FIXME: destroy the section here */
276 (i
< NTHeaders
->FileHeader
.NumberOfSections
);
280 PIMAGE_SECTION_HEADER Sections
;
281 LARGE_INTEGER Offset
;
285 (PIMAGE_SECTION_HEADER
) SECHDROFFSET(BlockBuffer
);
287 Sections
[i
].VirtualAddress
290 Sections
[i
].PointerToRawData
;
293 Status
= ZwMapViewOfSection(
298 Sections
[i
].Misc
.VirtualSize
,
300 (PULONG
) & Sections
[i
].Misc
.VirtualSize
,
305 if (!NT_SUCCESS(Status
))
307 DPRINT("NTDLL map view of secion failed ");
308 DbgPrintErrorMessage(Status
);
310 /* FIXME: destroy the section here */
321 * Open process image to determine ImageBase
322 * and StackBase/Size.
324 InitializeObjectAttributes(
325 & FileObjectAttributes
,
332 "Opening image file %w\n",
333 FileObjectAttributes
.ObjectName
->Buffer
338 & FileObjectAttributes
,
343 if (!NT_SUCCESS(Status
))
345 DPRINT("Image open failed ");
346 DbgPrintErrorMessage(Status
);
361 if (!NT_SUCCESS(Status
))
363 DPRINT("Image header read failed ");
364 DbgPrintErrorMessage(Status
);
370 * FIXME: this will fail if the NT headers
371 * are more than 1024 bytes from start.
373 DosHeader
= (PIMAGE_DOS_HEADER
) BlockBuffer
;
375 (PIMAGE_NT_HEADERS
) (BlockBuffer
+ DosHeader
->e_lfanew
);
377 (DosHeader
->e_magic
!= IMAGE_DOS_MAGIC
)
378 || (DosHeader
->e_lfanew
== 0L)
379 || (*(PULONG
) NTHeaders
!= IMAGE_PE_MAGIC
)
382 DPRINT("Image invalid format rc=%08lx\n", Status
);
385 return STATUS_UNSUCCESSFUL
;
387 ImageBase
= NTHeaders
->OptionalHeader
.ImageBase
;
388 ImageSize
= NTHeaders
->OptionalHeader
.SizeOfImage
;
390 * Create a section for the image
392 Status
= ZwCreateSection(
401 if (!NT_SUCCESS(Status
))
403 DPRINT("Image create section failed ");
404 DbgPrintErrorMessage(Status
);
410 * Map the image into the process
414 + sizeof (IMAGE_NT_HEADERS
)
416 sizeof(IMAGE_SECTION_HEADER
)
417 * NTHeaders
->FileHeader
.NumberOfSections
419 DPRINT("InitialViewSize %x\n",InitialViewSize
);
420 Status
= ZwMapViewOfSection(
423 (PVOID
*) & ImageBase
,
432 if (!NT_SUCCESS(Status
))
434 DPRINT("Image map view of section failed ");
435 DbgPrintErrorMessage(Status
);
437 /* FIXME: destroy the section here */
448 * Create page backed section for stack
452 - NTHeaders
->OptionalHeader
.SizeOfStackReserve
455 NTHeaders
->OptionalHeader
.SizeOfStackReserve
;
457 Status
= ZwAllocateVirtualMemory(
459 (PVOID
*) & StackBase
,
465 if (!NT_SUCCESS(Status
))
467 DPRINT("Stack allocation failed ");
468 DbgPrintErrorMessage(Status
);
470 /* FIXME: unmap the section here */
471 /* FIXME: destroy the section here */
483 DUPLICATE_SAME_ACCESS
487 & NTDllSectionHandle
,
489 &DupNTDllSectionHandle
,
492 DUPLICATE_SAME_ACCESS
495 ZwWriteVirtualMemory(
497 (PVOID
) (STACK_TOP
- 4),
498 & DupNTDllSectionHandle
,
499 sizeof (DupNTDllSectionHandle
),
502 ZwWriteVirtualMemory(
504 (PVOID
) (STACK_TOP
- 8),
509 ZwWriteVirtualMemory(
511 (PVOID
) (STACK_TOP
- 12),
513 sizeof (DupSectionHandle
),
517 * Create a peb (grungy)
519 Status
= LdrCreatePeb(ProcessHandle
);
520 if (!NT_SUCCESS(Status
))
522 DbgPrint("LDR: Failed to create initial peb\n");
526 * Initialize context to point to LdrStartup
528 memset(&Context
,0,sizeof(CONTEXT
));
529 Context
.SegSs
= USER_DS
;
530 Context
.Esp
= STACK_TOP
- 16;
531 Context
.EFlags
= 0x202;
532 Context
.SegCs
= USER_CS
;
533 Context
.Eip
= LdrStartupAddr
;
534 Context
.SegDs
= USER_DS
;
535 Context
.SegEs
= USER_DS
;
536 Context
.SegFs
= USER_DS
;
537 Context
.SegGs
= USER_DS
;
539 DPRINT("LdrStartupAddr %x\n",LdrStartupAddr
);
541 * FIXME: Create process and let 'er rip
543 Status
= ZwCreateThread(
553 if (!NT_SUCCESS(Status
))
555 DPRINT("Thread creation failed ");
556 DbgPrintErrorMessage(Status
);
558 /* FIXME: destroy the stack memory block here */
559 /* FIXME: unmap the section here */
560 /* FIXME: destroy the section here */
565 return STATUS_SUCCESS
;
570 * FIXME: The location of the initial process should be configurable,
571 * from command line or registry
574 LdrLoadInitialProcess (VOID
)
577 HANDLE ProcessHandle
;
578 UNICODE_STRING ProcessName
;
579 WCHAR TmpNameBuffer
[MAX_PATH
];
582 Status
= ZwCreateProcess(
592 if (!NT_SUCCESS(Status
))
594 DbgPrint("Could not create process\n");
598 * Get the system directory's name (a DOS device
599 * alias name which is in \\??\\).
607 L
"\\shell.exe" /* FIXME: should be smss.exe */
609 RtlInitUnicodeString(
613 Status
= LdrLoadImage(