be2a428094cf39f5444143295eff4c4113155dc5
[reactos.git] / reactos / ntoskrnl / ldr / sysdll.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ldr/sysdll.c
5 * PURPOSE: Loaders for PE executables
6 * PROGRAMMERS: Jean Michault
7 * Rex Jolliff (rex@lvcablemodem.com)
8 * UPDATE HISTORY:
9 * DW 26/01/00 Created
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <internal/i386/segment.h>
16 #include <internal/linkage.h>
17 #include <internal/module.h>
18 #include <internal/ntoskrnl.h>
19 #include <internal/ob.h>
20 #include <internal/ps.h>
21 #include <string.h>
22 #include <internal/string.h>
23 #include <internal/teb.h>
24
25 #define NDEBUG
26 #include <internal/debug.h>
27
28 /* GLOBALS *******************************************************************/
29
30 static PVOID SystemDllEntryPoint = NULL;
31 //static PVOID SystemDllApcDispatcher = NULL;
32 //static PVOID SystemDllCallbackDispatcher = NULL;
33 //static PVOID SystemDllExceptionDispatcher = NULL;
34
35 /* FUNCTIONS *****************************************************************/
36
37 PVOID LdrpGetSystemDllEntryPoint(VOID)
38 {
39 return(SystemDllEntryPoint);
40 }
41
42 NTSTATUS LdrpMapSystemDll(HANDLE ProcessHandle,
43 PVOID* LdrStartupAddr)
44 /*
45 * FUNCTION: LdrpMapSystemDll maps the system dll into the specified process
46 * address space and returns its startup address.
47 * PARAMETERS:
48 * ProcessHandle
49 * Points to the process to map the system dll into
50 *
51 * LdrStartupAddress
52 * Receives the startup address of the system dll on function
53 * completion
54 *
55 * RETURNS: Status
56 */
57 {
58 CHAR BlockBuffer [1024];
59 DWORD ImageBase;
60 ULONG ImageSize;
61 NTSTATUS Status;
62 OBJECT_ATTRIBUTES FileObjectAttributes;
63 HANDLE FileHandle;
64 HANDLE NTDllSectionHandle;
65 UNICODE_STRING DllPathname;
66 PIMAGE_DOS_HEADER DosHeader;
67 PIMAGE_NT_HEADERS NTHeaders;
68 ULONG InitialViewSize;
69 ULONG i;
70
71 /*
72 * Locate and open NTDLL to determine ImageBase
73 * and LdrStartup
74 */
75 RtlInitUnicodeString(&DllPathname,
76 L"\\SystemRoot\\system32\\ntdll.dll");
77 InitializeObjectAttributes(&FileObjectAttributes,
78 &DllPathname,
79 0,
80 NULL,
81 NULL);
82 DPRINT("Opening NTDLL\n");
83 Status = ZwOpenFile(&FileHandle,
84 FILE_ALL_ACCESS,
85 &FileObjectAttributes,
86 NULL,
87 0,
88 0);
89 if (!NT_SUCCESS(Status))
90 {
91 DbgPrint("NTDLL open failed (Status %x)\n", Status);
92 return Status;
93 }
94 Status = ZwReadFile(FileHandle,
95 0,
96 0,
97 0,
98 0,
99 BlockBuffer,
100 sizeof(BlockBuffer),
101 0,
102 0);
103 if (!NT_SUCCESS(Status))
104 {
105 DbgPrint("NTDLL header read failed (Status %x)\n", Status);
106 ZwClose(FileHandle);
107 return Status;
108 }
109
110 /*
111 * FIXME: this will fail if the NT headers are
112 * more than 1024 bytes from start.
113 */
114 DosHeader = (PIMAGE_DOS_HEADER) BlockBuffer;
115 NTHeaders = (PIMAGE_NT_HEADERS) (BlockBuffer + DosHeader->e_lfanew);
116 if ((DosHeader->e_magic != IMAGE_DOS_MAGIC)
117 || (DosHeader->e_lfanew == 0L)
118 || (*(PULONG) NTHeaders != IMAGE_PE_MAGIC))
119 {
120 DbgPrint("NTDLL format invalid\n");
121 ZwClose(FileHandle);
122 return(STATUS_UNSUCCESSFUL);
123 }
124 ImageBase = NTHeaders->OptionalHeader.ImageBase;
125 ImageSize = NTHeaders->OptionalHeader.SizeOfImage;
126
127 /*
128 * FIXME: retrieve the offset of LdrStartup from NTDLL
129 */
130 DPRINT("ImageBase %x\n",ImageBase);
131 *LdrStartupAddr =
132 (PVOID)ImageBase + NTHeaders->OptionalHeader.AddressOfEntryPoint;
133 DPRINT("LdrStartupAddr %x\n", LdrStartupAddr);
134 SystemDllEntryPoint = *LdrStartupAddr;
135
136 /*
137 * Create a section for NTDLL
138 */
139 DPRINT("Creating section\n");
140 Status = ZwCreateSection(&NTDllSectionHandle,
141 SECTION_ALL_ACCESS,
142 NULL,
143 NULL,
144 PAGE_READWRITE,
145 MEM_COMMIT,
146 FileHandle);
147 if (!NT_SUCCESS(Status))
148 {
149 DbgPrint("NTDLL create section failed (Status %x)\n", Status);
150 ZwClose(FileHandle);
151 return(Status);
152 }
153 ZwClose(FileHandle);
154
155 /*
156 * Map the NTDLL into the process
157 */
158 InitialViewSize = DosHeader->e_lfanew +
159 sizeof (IMAGE_NT_HEADERS) +
160 (sizeof (IMAGE_SECTION_HEADER) * NTHeaders->FileHeader.NumberOfSections);
161 DPRINT("Mapping view of section\n");
162 Status = ZwMapViewOfSection(NTDllSectionHandle,
163 ProcessHandle,
164 (PVOID*)&ImageBase,
165 0,
166 InitialViewSize,
167 NULL,
168 &InitialViewSize,
169 0,
170 MEM_COMMIT,
171 PAGE_READWRITE);
172 if (!NT_SUCCESS(Status))
173 {
174 DbgPrint("NTDLL map view of secion failed (Status %x)", Status);
175 ZwClose(NTDllSectionHandle);
176 return(Status);
177 }
178
179 for (i = 0; i < NTHeaders->FileHeader.NumberOfSections; i++)
180 {
181 PIMAGE_SECTION_HEADER Sections;
182 LARGE_INTEGER Offset;
183 ULONG Base;
184
185 DPRINT("Mapping view of section %d\n", i);
186 Sections = (PIMAGE_SECTION_HEADER) SECHDROFFSET(BlockBuffer);
187 DPRINT("Sections %x\n", Sections);
188 Base = Sections[i].VirtualAddress + ImageBase;
189 DPRINT("Base %x\n", Base);
190 Offset.u.LowPart = Sections[i].PointerToRawData;
191 Offset.u.HighPart = 0;
192 DPRINT("Mapping view of section\n");
193 Status = ZwMapViewOfSection(NTDllSectionHandle,
194 ProcessHandle,
195 (PVOID*)&Base,
196 0,
197 Sections[i].Misc.VirtualSize,
198 &Offset,
199 (PULONG)&Sections[i].Misc.VirtualSize,
200 0,
201 MEM_COMMIT,
202 PAGE_READWRITE);
203 if (!NT_SUCCESS(Status))
204 {
205 DbgPrint("NTDLL map view of secion failed (Status %x)\n", Status);
206 ZwClose(NTDllSectionHandle);
207 return(Status);
208 }
209 }
210 DPRINT("Finished mapping\n");
211 ZwClose(NTDllSectionHandle);
212
213 return(STATUS_SUCCESS);
214 }