1e5bd9afb2da0b295c226d23d90c57a77ced4ac9
[reactos.git] / reactos / ntoskrnl / mm / procsup.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/mm/procsup.c
5 * PURPOSE: Memory functions related to Processes
6 *
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 VOID NTAPI MiRosTakeOverPebTebRanges(IN PEPROCESS Process);
17
18 /* FUNCTIONS *****************************************************************/
19
20 PVOID
21 NTAPI
22 MiCreatePebOrTeb(PEPROCESS Process,
23 PVOID BaseAddress)
24 {
25 NTSTATUS Status;
26 PMMSUPPORT ProcessAddressSpace = &Process->Vm;
27 PMEMORY_AREA MemoryArea;
28 PHYSICAL_ADDRESS BoundaryAddressMultiple;
29 PVOID AllocatedBase = BaseAddress;
30 BoundaryAddressMultiple.QuadPart = 0;
31
32 /* Acquire the Lock */
33 MmLockAddressSpace(ProcessAddressSpace);
34
35 /*
36 * Create a Peb or Teb.
37 * Loop until it works, decreasing by PAGE_SIZE each time. The logic here
38 * is that a PEB allocation should never fail since the address is free,
39 * while TEB allocation can fail, and we should simply try the address
40 * below. Is there a nicer way of doing this automagically? (ie: findning)
41 * a gap region? -- Alex
42 */
43 do {
44 DPRINT("Trying to allocate: %x\n", AllocatedBase);
45 Status = MmCreateMemoryArea(ProcessAddressSpace,
46 MEMORY_AREA_PEB_OR_TEB,
47 &AllocatedBase,
48 PAGE_SIZE,
49 PAGE_READWRITE,
50 &MemoryArea,
51 TRUE,
52 0,
53 BoundaryAddressMultiple);
54 AllocatedBase = RVA(AllocatedBase, -PAGE_SIZE);
55 } while (Status != STATUS_SUCCESS);
56
57 /* Initialize the Region */
58 MmInitializeRegion(&MemoryArea->Data.VirtualMemoryData.RegionListHead,
59 PAGE_SIZE,
60 MEM_COMMIT,
61 PAGE_READWRITE);
62
63 /* Reserve the pages */
64 MmReserveSwapPages(PAGE_SIZE);
65
66 /* Unlock Address Space */
67 DPRINT("Returning\n");
68 MmUnlockAddressSpace(ProcessAddressSpace);
69 return RVA(AllocatedBase, PAGE_SIZE);
70 }
71
72 VOID
73 NTAPI
74 MmDeleteTeb(PEPROCESS Process,
75 PTEB Teb)
76 {
77 PMMSUPPORT ProcessAddressSpace = &Process->Vm;
78 PMEMORY_AREA MemoryArea;
79
80 /* Lock the Address Space */
81 MmLockAddressSpace(ProcessAddressSpace);
82
83 MemoryArea = MmLocateMemoryAreaByAddress(ProcessAddressSpace, (PVOID)Teb);
84 if (MemoryArea)
85 {
86 /* Delete the Teb */
87 MmFreeVirtualMemory(Process, MemoryArea);
88 }
89
90 /* Unlock the Address Space */
91 MmUnlockAddressSpace(ProcessAddressSpace);
92 }
93
94 NTSTATUS
95 NTAPI
96 MmInitializeHandBuiltProcess2(IN PEPROCESS Process)
97 {
98 PVOID BaseAddress;
99 PMEMORY_AREA MemoryArea;
100 PHYSICAL_ADDRESS BoundaryAddressMultiple;
101 NTSTATUS Status;
102 PMMSUPPORT ProcessAddressSpace = &Process->Vm;
103 BoundaryAddressMultiple.QuadPart = 0;
104
105 /* Create the shared data page */
106 BaseAddress = (PVOID)USER_SHARED_DATA;
107 Status = MmCreateMemoryArea(ProcessAddressSpace,
108 MEMORY_AREA_SHARED_DATA,
109 &BaseAddress,
110 PAGE_SIZE,
111 PAGE_EXECUTE_READ,
112 &MemoryArea,
113 FALSE,
114 0,
115 BoundaryAddressMultiple);
116
117 /* Lock the VAD, ARM3-owned ranges away */
118 MiRosTakeOverPebTebRanges(Process);
119 return Status;
120 }
121
122 NTSTATUS
123 NTAPI
124 MmInitializeProcessAddressSpace(IN PEPROCESS Process,
125 IN PEPROCESS ProcessClone OPTIONAL,
126 IN PVOID Section OPTIONAL,
127 IN OUT PULONG Flags,
128 IN POBJECT_NAME_INFORMATION *AuditName OPTIONAL)
129 {
130 NTSTATUS Status;
131 PMMSUPPORT ProcessAddressSpace = &Process->Vm;
132 PVOID BaseAddress;
133 PMEMORY_AREA MemoryArea;
134 PHYSICAL_ADDRESS BoundaryAddressMultiple;
135 SIZE_T ViewSize = 0;
136 PVOID ImageBase = 0;
137 PROS_SECTION_OBJECT SectionObject = Section;
138 BoundaryAddressMultiple.QuadPart = 0;
139
140 /* Initialize the Addresss Space lock */
141 KeInitializeGuardedMutex(&Process->AddressCreationLock);
142 Process->Vm.WorkingSetExpansionLinks.Flink = NULL;
143
144 /* Initialize AVL tree */
145 ASSERT(Process->VadRoot.NumberGenericTableElements == 0);
146 Process->VadRoot.BalancedRoot.u1.Parent = &Process->VadRoot.BalancedRoot;
147
148 /* Acquire the Lock */
149 MmLockAddressSpace(ProcessAddressSpace);
150
151 /* Protect the highest 64KB of the process address space */
152 BaseAddress = (PVOID)MmUserProbeAddress;
153 Status = MmCreateMemoryArea(ProcessAddressSpace,
154 MEMORY_AREA_NO_ACCESS,
155 &BaseAddress,
156 0x10000,
157 PAGE_NOACCESS,
158 &MemoryArea,
159 FALSE,
160 0,
161 BoundaryAddressMultiple);
162 if (!NT_SUCCESS(Status))
163 {
164 DPRINT1("Failed to protect last 64KB\n");
165 goto exit;
166 }
167
168 /* Protect the 60KB above the shared user page */
169 BaseAddress = (char*)USER_SHARED_DATA + PAGE_SIZE;
170 Status = MmCreateMemoryArea(ProcessAddressSpace,
171 MEMORY_AREA_NO_ACCESS,
172 &BaseAddress,
173 0x10000 - PAGE_SIZE,
174 PAGE_NOACCESS,
175 &MemoryArea,
176 FALSE,
177 0,
178 BoundaryAddressMultiple);
179 if (!NT_SUCCESS(Status))
180 {
181 DPRINT1("Failed to protect the memory above the shared user page\n");
182 goto exit;
183 }
184
185 /* Create the shared data page */
186 BaseAddress = (PVOID)USER_SHARED_DATA;
187 Status = MmCreateMemoryArea(ProcessAddressSpace,
188 MEMORY_AREA_SHARED_DATA,
189 &BaseAddress,
190 PAGE_SIZE,
191 PAGE_EXECUTE_READ,
192 &MemoryArea,
193 FALSE,
194 0,
195 BoundaryAddressMultiple);
196 if (!NT_SUCCESS(Status))
197 {
198 DPRINT1("Failed to create Shared User Data\n");
199 goto exit;
200 }
201
202 /* Lock the VAD, ARM3-owned ranges away */
203 MiRosTakeOverPebTebRanges(Process);
204
205 /* The process now has an address space */
206 Process->HasAddressSpace = TRUE;
207
208 /* Check if there's a Section Object */
209 if (SectionObject)
210 {
211 UNICODE_STRING FileName;
212 PWCHAR szSrc;
213 PCHAR szDest;
214 USHORT lnFName = 0;
215
216 /* Unlock the Address Space */
217 DPRINT("Unlocking\n");
218 MmUnlockAddressSpace(ProcessAddressSpace);
219
220 DPRINT("Mapping process image. Section: %p, Process: %p, ImageBase: %p\n",
221 SectionObject, Process, &ImageBase);
222 Status = MmMapViewOfSection(Section,
223 (PEPROCESS)Process,
224 (PVOID*)&ImageBase,
225 0,
226 0,
227 NULL,
228 &ViewSize,
229 0,
230 MEM_COMMIT,
231 PAGE_READWRITE);
232 if (!NT_SUCCESS(Status))
233 {
234 DPRINT1("Failed to map process Image\n");
235 return Status;
236 }
237
238 /* Save the pointer */
239 Process->SectionBaseAddress = ImageBase;
240
241 /* Determine the image file name and save it to EPROCESS */
242 DPRINT("Getting Image name\n");
243 FileName = SectionObject->FileObject->FileName;
244 szSrc = (PWCHAR)((PCHAR)FileName.Buffer + FileName.Length);
245 if (FileName.Buffer)
246 {
247 /* Loop the file name*/
248 while (szSrc > FileName.Buffer)
249 {
250 /* Make sure this isn't a backslash */
251 if (*--szSrc == OBJ_NAME_PATH_SEPARATOR)
252 {
253 /* If so, stop it here */
254 szSrc++;
255 break;
256 }
257 else
258 {
259 /* Otherwise, keep going */
260 lnFName++;
261 }
262 }
263 }
264
265 /* Copy the to the process and truncate it to 15 characters if necessary */
266 szDest = Process->ImageFileName;
267 lnFName = min(lnFName, sizeof(Process->ImageFileName) - 1);
268 while (lnFName--) *szDest++ = (UCHAR)*szSrc++;
269 *szDest = ANSI_NULL;
270
271 /* Check if caller wants an audit name */
272 if (AuditName)
273 {
274 /* Setup the audit name */
275 SeInitializeProcessAuditName(SectionObject->FileObject,
276 FALSE,
277 AuditName);
278 }
279
280 /* Return status to caller */
281 return Status;
282 }
283
284 exit:
285 /* Unlock the Address Space */
286 DPRINT("Unlocking\n");
287 MmUnlockAddressSpace(ProcessAddressSpace);
288
289 /* Return status to caller */
290 return Status;
291 }
292
293 VOID
294 NTAPI
295 MmCleanProcessAddressSpace(IN PEPROCESS Process)
296 {
297 /* FIXME: Add part of MmDeleteProcessAddressSpace here */
298 }
299
300 NTSTATUS
301 NTAPI
302 MmDeleteProcessAddressSpace(PEPROCESS Process)
303 {
304 PVOID Address;
305 PMEMORY_AREA MemoryArea;
306
307 DPRINT("MmDeleteProcessAddressSpace(Process %x (%s))\n", Process,
308 Process->ImageFileName);
309
310 MmLockAddressSpace(&Process->Vm);
311
312 while ((MemoryArea = (PMEMORY_AREA)Process->Vm.WorkingSetExpansionLinks.Flink) != NULL)
313 {
314 switch (MemoryArea->Type)
315 {
316 case MEMORY_AREA_SECTION_VIEW:
317 Address = (PVOID)MemoryArea->StartingAddress;
318 MmUnlockAddressSpace(&Process->Vm);
319 MmUnmapViewOfSection(Process, Address);
320 MmLockAddressSpace(&Process->Vm);
321 break;
322
323 case MEMORY_AREA_VIRTUAL_MEMORY:
324 case MEMORY_AREA_PEB_OR_TEB:
325 MmFreeVirtualMemory(Process, MemoryArea);
326 break;
327
328 case MEMORY_AREA_SHARED_DATA:
329 case MEMORY_AREA_NO_ACCESS:
330 case MEMORY_AREA_OWNED_BY_ARM3:
331 MmFreeMemoryArea(&Process->Vm,
332 MemoryArea,
333 NULL,
334 NULL);
335 break;
336
337 case MEMORY_AREA_MDL_MAPPING:
338 KeBugCheck(PROCESS_HAS_LOCKED_PAGES);
339 break;
340
341 default:
342 KeBugCheck(MEMORY_MANAGEMENT);
343 }
344 }
345
346 Mmi386ReleaseMmInfo(Process);
347
348 MmUnlockAddressSpace(&Process->Vm);
349
350 DPRINT("Finished MmReleaseMmInfo()\n");
351 return(STATUS_SUCCESS);
352 }
353