sync with trunk head (34904)
[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 <internal/debug.h>
15
16 extern ULONG NtMajorVersion;
17 extern ULONG NtMinorVersion;
18 extern ULONG CmNtCSDVersion;
19 extern ULONG NtBuildNumber;
20 extern MM_SYSTEMSIZE MmSystemSize;
21
22 #define MM_HIGHEST_VAD_ADDRESS \
23 (PVOID)((ULONG_PTR)MM_HIGHEST_USER_ADDRESS - (16 * PAGE_SIZE))
24
25 /* FUNCTIONS *****************************************************************/
26
27 NTSTATUS
28 NTAPI
29 MmSetMemoryPriorityProcess(IN PEPROCESS Process,
30 IN UCHAR MemoryPriority)
31 {
32 UCHAR OldPriority;
33
34 /* Check if we have less then 16MB of Physical Memory */
35 if ((MmSystemSize == MmSmallSystem) &&
36 (MmStats.NrTotalPages < ((15 * 1024 * 1024) / PAGE_SIZE)))
37 {
38 /* Always use background priority */
39 MemoryPriority = 0;
40 }
41
42 /* Save the old priority and update it */
43 OldPriority = (UCHAR)Process->Vm.Flags.MemoryPriority;
44 Process->Vm.Flags.MemoryPriority = MemoryPriority;
45
46 /* Return the old priority */
47 return OldPriority;
48 }
49
50 LCID
51 NTAPI
52 MmGetSessionLocaleId(VOID)
53 {
54 PEPROCESS Process;
55 PAGED_CODE();
56
57 /* Get the current process */
58 Process = PsGetCurrentProcess();
59
60 /* Check if it's the Session Leader */
61 if (Process->Vm.Flags.SessionLeader)
62 {
63 /* Make sure it has a valid Session */
64 if (Process->Session)
65 {
66 /* Get the Locale ID */
67 #if ROS_HAS_SESSIONS
68 return ((PMM_SESSION_SPACE)Process->Session)->LocaleId;
69 #endif
70 }
71 }
72
73 /* Not a session leader, return the default */
74 return PsDefaultThreadLocaleId;
75 }
76
77 PVOID
78 STDCALL
79 MiCreatePebOrTeb(PEPROCESS Process,
80 PVOID BaseAddress)
81 {
82 NTSTATUS Status;
83 PMM_AVL_TABLE ProcessAddressSpace = &Process->VadRoot;
84 PMEMORY_AREA MemoryArea;
85 PHYSICAL_ADDRESS BoundaryAddressMultiple;
86 PVOID AllocatedBase = BaseAddress;
87 BoundaryAddressMultiple.QuadPart = 0;
88
89 /* Acquire the Lock */
90 MmLockAddressSpace(ProcessAddressSpace);
91
92 /*
93 * Create a Peb or Teb.
94 * Loop until it works, decreasing by PAGE_SIZE each time. The logic here
95 * is that a PEB allocation should never fail since the address is free,
96 * while TEB allocation can fail, and we should simply try the address
97 * below. Is there a nicer way of doing this automagically? (ie: findning)
98 * a gap region? -- Alex
99 */
100 do {
101 DPRINT("Trying to allocate: %x\n", AllocatedBase);
102 Status = MmCreateMemoryArea(ProcessAddressSpace,
103 MEMORY_AREA_PEB_OR_TEB,
104 &AllocatedBase,
105 PAGE_SIZE,
106 PAGE_READWRITE,
107 &MemoryArea,
108 TRUE,
109 0,
110 BoundaryAddressMultiple);
111 AllocatedBase = RVA(AllocatedBase, -PAGE_SIZE);
112 } while (Status != STATUS_SUCCESS);
113
114 /* Initialize the Region */
115 MmInitializeRegion(&MemoryArea->Data.VirtualMemoryData.RegionListHead,
116 PAGE_SIZE,
117 MEM_COMMIT,
118 PAGE_READWRITE);
119
120 /* Reserve the pages */
121 MmReserveSwapPages(PAGE_SIZE);
122
123 /* Unlock Address Space */
124 DPRINT("Returning\n");
125 MmUnlockAddressSpace(ProcessAddressSpace);
126 return RVA(AllocatedBase, PAGE_SIZE);
127 }
128
129 VOID
130 MiFreeStackPage(PVOID Context,
131 MEMORY_AREA* MemoryArea,
132 PVOID Address,
133 PFN_TYPE Page,
134 SWAPENTRY SwapEntry,
135 BOOLEAN Dirty)
136 {
137 ASSERT(SwapEntry == 0);
138 if (Page) MmReleasePageMemoryConsumer(MC_NPPOOL, Page);
139 }
140
141 VOID
142 STDCALL
143 MmDeleteKernelStack(PVOID Stack,
144 BOOLEAN GuiStack)
145 {
146 /* Lock the Address Space */
147 MmLockAddressSpace(MmGetKernelAddressSpace());
148
149 /* Delete the Stack */
150 MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
151 Stack,
152 MiFreeStackPage,
153 NULL);
154
155 /* Unlock the Address Space */
156 MmUnlockAddressSpace(MmGetKernelAddressSpace());
157 }
158
159 VOID
160 STDCALL
161 MmDeleteTeb(PEPROCESS Process,
162 PTEB Teb)
163 {
164 PMM_AVL_TABLE ProcessAddressSpace = &Process->VadRoot;
165 PMEMORY_AREA MemoryArea;
166
167 /* Lock the Address Space */
168 MmLockAddressSpace(ProcessAddressSpace);
169
170 MemoryArea = MmLocateMemoryAreaByAddress(ProcessAddressSpace, (PVOID)Teb);
171 if (MemoryArea)
172 {
173 /* Delete the Teb */
174 MmFreeVirtualMemory(Process, MemoryArea);
175 }
176
177 /* Unlock the Address Space */
178 MmUnlockAddressSpace(ProcessAddressSpace);
179 }
180
181 PVOID
182 STDCALL
183 MmCreateKernelStack(BOOLEAN GuiStack,
184 UCHAR Node)
185 {
186 PMEMORY_AREA StackArea;
187 ULONG i;
188 PHYSICAL_ADDRESS BoundaryAddressMultiple;
189 ULONG StackSize = GuiStack ? KERNEL_LARGE_STACK_SIZE : KERNEL_STACK_SIZE;
190 PFN_TYPE Page[KERNEL_LARGE_STACK_SIZE / PAGE_SIZE];
191 PVOID KernelStack = NULL;
192 NTSTATUS Status;
193
194 /* Initialize the Boundary Address */
195 BoundaryAddressMultiple.QuadPart = 0;
196
197 /* Lock the Kernel Address Space */
198 MmLockAddressSpace(MmGetKernelAddressSpace());
199
200 /* Create a MAREA for the Kernel Stack */
201 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
202 MEMORY_AREA_KERNEL_STACK,
203 &KernelStack,
204 StackSize,
205 PAGE_READWRITE,
206 &StackArea,
207 FALSE,
208 0,
209 BoundaryAddressMultiple);
210
211 /* Unlock the Address Space */
212 MmUnlockAddressSpace(MmGetKernelAddressSpace());
213
214 /* Check for Success */
215 if (!NT_SUCCESS(Status))
216 {
217 DPRINT1("Failed to create thread stack\n");
218 KEBUGCHECK(0);
219 }
220
221 /*
222 * Mark the Stack in use.
223 * Note: Currently we mark all 60KB in use for a GUI Thread.
224 * We should only do this inside MmGrowKernelStack. TODO!
225 */
226 for (i = 0; i < (StackSize / PAGE_SIZE); i++)
227 {
228 Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Page[i]);
229 }
230
231 /* Create a Virtual Mapping for it */
232 Status = MmCreateVirtualMapping(NULL,
233 KernelStack,
234 PAGE_READWRITE,
235 Page,
236 StackSize / PAGE_SIZE);
237
238 /* Check for success */
239 if (!NT_SUCCESS(Status))
240 {
241 DPRINT1("Could not create Virtual Mapping for Kernel Stack\n");
242 KEBUGCHECK(0);
243 }
244
245 /* Return the stack base */
246 return (PVOID)((ULONG_PTR)KernelStack +
247 (GuiStack ? KERNEL_LARGE_STACK_SIZE : KERNEL_STACK_SIZE));
248 }
249
250 /*
251 * @implemented
252 */
253 NTSTATUS
254 STDCALL
255 MmGrowKernelStack(PVOID StackPointer)
256 {
257 PETHREAD Thread = PsGetCurrentThread();
258
259 /* Make sure we have reserved space for our grow */
260 ASSERT(((PCHAR)Thread->Tcb.StackBase - (PCHAR)Thread->Tcb.StackLimit) <=
261 (KERNEL_LARGE_STACK_SIZE + PAGE_SIZE));
262
263 /*
264 * We'll give you three more pages.
265 * NOTE: See note in MmCreateKernelStack. These pages are already being reserved.
266 * It would be more efficient to only grow them (commit them) here.
267 */
268 Thread->Tcb.StackLimit -= KERNEL_STACK_SIZE;
269
270 /* Return success */
271 return STATUS_SUCCESS;
272 }
273
274 NTSTATUS
275 STDCALL
276 MmCreatePeb(PEPROCESS Process)
277 {
278 PPEB Peb = NULL;
279 LARGE_INTEGER SectionOffset;
280 SIZE_T ViewSize = 0;
281 PVOID TableBase = NULL;
282 PIMAGE_NT_HEADERS NtHeaders;
283 PIMAGE_LOAD_CONFIG_DIRECTORY ImageConfigData;
284 NTSTATUS Status;
285 KAFFINITY ProcessAffinityMask = 0;
286 SectionOffset.QuadPart = (ULONGLONG)0;
287 DPRINT("MmCreatePeb\n");
288
289 /* Allocate the PEB */
290 Peb = MiCreatePebOrTeb(Process,
291 (PVOID)((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1));
292 ASSERT(Peb == (PVOID)0x7FFDF000);
293
294 /* Map NLS Tables */
295 DPRINT("Mapping NLS\n");
296 Status = MmMapViewOfSection(ExpNlsSectionPointer,
297 (PEPROCESS)Process,
298 &TableBase,
299 0,
300 0,
301 &SectionOffset,
302 &ViewSize,
303 ViewShare,
304 MEM_TOP_DOWN,
305 PAGE_READONLY);
306 if (!NT_SUCCESS(Status))
307 {
308 DPRINT1("MmMapViewOfSection() failed (Status %lx)\n", Status);
309 return(Status);
310 }
311 DPRINT("TableBase %p ViewSize %lx\n", TableBase, ViewSize);
312
313 /* Attach to Process */
314 KeAttachProcess(&Process->Pcb);
315
316 /* Initialize the PEB */
317 DPRINT("Allocated: %x\n", Peb);
318 RtlZeroMemory(Peb, sizeof(PEB));
319
320 /* Set up data */
321 DPRINT("Setting up PEB\n");
322 Peb->ImageBaseAddress = Process->SectionBaseAddress;
323 Peb->InheritedAddressSpace = 0;
324 Peb->Mutant = NULL;
325
326 /* NLS */
327 Peb->AnsiCodePageData = (PCHAR)TableBase + ExpAnsiCodePageDataOffset;
328 Peb->OemCodePageData = (PCHAR)TableBase + ExpOemCodePageDataOffset;
329 Peb->UnicodeCaseTableData = (PCHAR)TableBase + ExpUnicodeCaseTableDataOffset;
330
331 /* Default Version Data (could get changed below) */
332 Peb->OSMajorVersion = NtMajorVersion;
333 Peb->OSMinorVersion = NtMinorVersion;
334 Peb->OSBuildNumber = (USHORT)(NtBuildNumber & 0x3FFF);
335 Peb->OSPlatformId = 2; /* VER_PLATFORM_WIN32_NT */
336 Peb->OSCSDVersion = (USHORT)CmNtCSDVersion;
337
338 /* Heap and Debug Data */
339 Peb->NumberOfProcessors = KeNumberProcessors;
340 Peb->BeingDebugged = (BOOLEAN)(Process->DebugPort != NULL ? TRUE : FALSE);
341 Peb->NtGlobalFlag = NtGlobalFlag;
342 /*Peb->HeapSegmentReserve = MmHeapSegmentReserve;
343 Peb->HeapSegmentCommit = MmHeapSegmentCommit;
344 Peb->HeapDeCommitTotalFreeThreshold = MmHeapDeCommitTotalFreeThreshold;
345 Peb->HeapDeCommitFreeBlockThreshold = MmHeapDeCommitFreeBlockThreshold;*/
346 Peb->NumberOfHeaps = 0;
347 Peb->MaximumNumberOfHeaps = (PAGE_SIZE - sizeof(PEB)) / sizeof(PVOID);
348 Peb->ProcessHeaps = (PVOID*)Peb + 1;
349
350 /* Image Data */
351 if ((NtHeaders = RtlImageNtHeader(Peb->ImageBaseAddress)))
352 {
353 /* Write subsystem data */
354 Peb->ImageSubSystem = NtHeaders->OptionalHeader.Subsystem;
355 Peb->ImageSubSystemMajorVersion = NtHeaders->OptionalHeader.MajorSubsystemVersion;
356 Peb->ImageSubSystemMinorVersion = NtHeaders->OptionalHeader.MinorSubsystemVersion;
357
358 /* Write Version Data */
359 if (NtHeaders->OptionalHeader.Win32VersionValue)
360 {
361 Peb->OSMajorVersion = NtHeaders->OptionalHeader.Win32VersionValue & 0xFF;
362 Peb->OSMinorVersion = (NtHeaders->OptionalHeader.Win32VersionValue >> 8) & 0xFF;
363 Peb->OSBuildNumber = (NtHeaders->OptionalHeader.Win32VersionValue >> 16) & 0x3FFF;
364
365 /* Set the Platform ID */
366 Peb->OSPlatformId = (NtHeaders->OptionalHeader.Win32VersionValue >> 30) ^ 2;
367 }
368
369 /* Check if the image is not safe for SMP */
370 if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_UP_SYSTEM_ONLY)
371 {
372 /* FIXME: Choose one randomly */
373 Peb->ImageProcessAffinityMask = 1;
374 }
375 else
376 {
377 /* Use affinity from Image Header */
378 Peb->ImageProcessAffinityMask = ProcessAffinityMask;
379 }
380
381 _SEH_TRY
382 {
383 /* Get the Image Config Data too */
384 ImageConfigData = RtlImageDirectoryEntryToData(Peb->ImageBaseAddress,
385 TRUE,
386 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
387 &ViewSize);
388
389 ProbeForRead(ImageConfigData,
390 sizeof(IMAGE_LOAD_CONFIG_DIRECTORY),
391 sizeof(ULONG));
392
393 /* Process the image config data overrides if specfied. */
394 if (ImageConfigData != NULL)
395 {
396 if (ImageConfigData->CSDVersion)
397 {
398 Peb->OSCSDVersion = ImageConfigData->CSDVersion;
399 }
400 if (ImageConfigData->ProcessAffinityMask)
401 {
402 ProcessAffinityMask = ImageConfigData->ProcessAffinityMask;
403 }
404 }
405 }
406 _SEH_HANDLE
407 {
408 Status = _SEH_GetExceptionCode();
409 }
410 _SEH_END;
411 }
412
413 /* Misc data */
414 Peb->SessionId = Process->Session;
415 Process->Peb = Peb;
416
417 /* Detach from the Process */
418 KeDetachProcess();
419
420 DPRINT("MmCreatePeb: Peb created at %p\n", Peb);
421 return Status;
422 }
423
424 PTEB
425 STDCALL
426 MmCreateTeb(PEPROCESS Process,
427 PCLIENT_ID ClientId,
428 PINITIAL_TEB InitialTeb)
429 {
430 PTEB Teb;
431 BOOLEAN Attached = FALSE;
432
433 /* Attach to the process */
434 DPRINT("MmCreateTeb\n");
435 if (Process != PsGetCurrentProcess())
436 {
437 /* Attach to Target */
438 KeAttachProcess(&Process->Pcb);
439 Attached = TRUE;
440 }
441
442 /* Allocate the TEB */
443 Teb = MiCreatePebOrTeb(Process,
444 (PVOID)((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1));
445
446 /* Initialize the PEB */
447 RtlZeroMemory(Teb, sizeof(TEB));
448
449 /* Set TIB Data */
450 Teb->Tib.ExceptionList = (PVOID)0xFFFFFFFF;
451 Teb->Tib.Version = 1;
452 Teb->Tib.Self = (PNT_TIB)Teb;
453
454 /* Set TEB Data */
455 Teb->Cid = *ClientId;
456 Teb->RealClientId = *ClientId;
457 Teb->ProcessEnvironmentBlock = Process->Peb;
458 Teb->CurrentLocale = PsDefaultThreadLocaleId;
459
460 /* Store stack information from InitialTeb */
461 if(InitialTeb != NULL)
462 {
463 Teb->Tib.StackBase = InitialTeb->StackBase;
464 Teb->Tib.StackLimit = InitialTeb->StackLimit;
465 Teb->DeallocationStack = InitialTeb->AllocatedStackBase;
466 }
467
468 /* Initialize the static unicode string */
469 Teb->StaticUnicodeString.Length = 0;
470 Teb->StaticUnicodeString.MaximumLength = sizeof(Teb->StaticUnicodeBuffer);
471 Teb->StaticUnicodeString.Buffer = Teb->StaticUnicodeBuffer;
472
473 /* Return TEB Address */
474 DPRINT("Allocated: %x\n", Teb);
475 if (Attached) KeDetachProcess();
476 return Teb;
477 }
478
479 NTSTATUS
480 NTAPI
481 MmInitializeHandBuiltProcess2(IN PEPROCESS Process)
482 {
483 PVOID BaseAddress;
484 PMEMORY_AREA MemoryArea;
485 PHYSICAL_ADDRESS BoundaryAddressMultiple;
486 NTSTATUS Status;
487 PMM_AVL_TABLE ProcessAddressSpace = &Process->VadRoot;
488 BoundaryAddressMultiple.QuadPart = 0;
489
490 /* Create the shared data page */
491 BaseAddress = (PVOID)USER_SHARED_DATA;
492 Status = MmCreateMemoryArea(ProcessAddressSpace,
493 MEMORY_AREA_SHARED_DATA,
494 &BaseAddress,
495 PAGE_SIZE,
496 PAGE_EXECUTE_READ,
497 &MemoryArea,
498 FALSE,
499 0,
500 BoundaryAddressMultiple);
501 return Status;
502 }
503
504 NTSTATUS
505 NTAPI
506 MmInitializeProcessAddressSpace(IN PEPROCESS Process,
507 IN PEPROCESS ProcessClone OPTIONAL,
508 IN PVOID Section OPTIONAL,
509 IN OUT PULONG Flags,
510 IN POBJECT_NAME_INFORMATION *AuditName OPTIONAL)
511 {
512 NTSTATUS Status;
513 PMM_AVL_TABLE ProcessAddressSpace = &Process->VadRoot;
514 PVOID BaseAddress;
515 PMEMORY_AREA MemoryArea;
516 PHYSICAL_ADDRESS BoundaryAddressMultiple;
517 SIZE_T ViewSize = 0;
518 PVOID ImageBase = 0;
519 PROS_SECTION_OBJECT SectionObject = Section;
520 BoundaryAddressMultiple.QuadPart = 0;
521
522 /* Initialize the Addresss Space lock */
523 KeInitializeGuardedMutex(&Process->AddressCreationLock);
524 Process->VadRoot.BalancedRoot.u1.Parent = NULL;
525
526 /* Acquire the Lock */
527 MmLockAddressSpace(ProcessAddressSpace);
528
529 /* Protect the highest 64KB of the process address space */
530 BaseAddress = (PVOID)MmUserProbeAddress;
531 Status = MmCreateMemoryArea(ProcessAddressSpace,
532 MEMORY_AREA_NO_ACCESS,
533 &BaseAddress,
534 0x10000,
535 PAGE_NOACCESS,
536 &MemoryArea,
537 FALSE,
538 0,
539 BoundaryAddressMultiple);
540 if (!NT_SUCCESS(Status))
541 {
542 DPRINT1("Failed to protect last 64KB\n");
543 goto exit;
544 }
545
546 /* Protect the 60KB above the shared user page */
547 BaseAddress = (char*)USER_SHARED_DATA + PAGE_SIZE;
548 Status = MmCreateMemoryArea(ProcessAddressSpace,
549 MEMORY_AREA_NO_ACCESS,
550 &BaseAddress,
551 0x10000 - PAGE_SIZE,
552 PAGE_NOACCESS,
553 &MemoryArea,
554 FALSE,
555 0,
556 BoundaryAddressMultiple);
557 if (!NT_SUCCESS(Status))
558 {
559 DPRINT1("Failed to protect the memory above the shared user page\n");
560 goto exit;
561 }
562
563 /* Create the shared data page */
564 BaseAddress = (PVOID)USER_SHARED_DATA;
565 Status = MmCreateMemoryArea(ProcessAddressSpace,
566 MEMORY_AREA_SHARED_DATA,
567 &BaseAddress,
568 PAGE_SIZE,
569 PAGE_EXECUTE_READ,
570 &MemoryArea,
571 FALSE,
572 0,
573 BoundaryAddressMultiple);
574 if (!NT_SUCCESS(Status))
575 {
576 DPRINT1("Failed to create Shared User Data\n");
577 goto exit;
578 }
579
580 /* The process now has an address space */
581 Process->HasAddressSpace = TRUE;
582
583 /* Check if there's a Section Object */
584 if (SectionObject)
585 {
586 UNICODE_STRING FileName;
587 PWCHAR szSrc;
588 PCHAR szDest;
589 USHORT lnFName = 0;
590
591 /* Unlock the Address Space */
592 DPRINT("Unlocking\n");
593 MmUnlockAddressSpace(ProcessAddressSpace);
594
595 DPRINT("Mapping process image. Section: %p, Process: %p, ImageBase: %p\n",
596 SectionObject, Process, &ImageBase);
597 Status = MmMapViewOfSection(Section,
598 (PEPROCESS)Process,
599 (PVOID*)&ImageBase,
600 0,
601 0,
602 NULL,
603 &ViewSize,
604 0,
605 MEM_COMMIT,
606 PAGE_READWRITE);
607 if (!NT_SUCCESS(Status))
608 {
609 DPRINT1("Failed to map process Image\n");
610 return Status;
611 }
612
613 /* Save the pointer */
614 Process->SectionBaseAddress = ImageBase;
615
616 /* Determine the image file name and save it to EPROCESS */
617 DPRINT("Getting Image name\n");
618 FileName = SectionObject->FileObject->FileName;
619 szSrc = (PWCHAR)((PCHAR)FileName.Buffer + FileName.Length);
620 if (FileName.Buffer)
621 {
622 /* Loop the file name*/
623 while (szSrc > FileName.Buffer)
624 {
625 /* Make sure this isn't a backslash */
626 if (*--szSrc == OBJ_NAME_PATH_SEPARATOR)
627 {
628 /* If so, stop it here */
629 szSrc++;
630 break;
631 }
632 else
633 {
634 /* Otherwise, keep going */
635 lnFName++;
636 }
637 }
638 }
639
640 /* Copy the to the process and truncate it to 15 characters if necessary */
641 szDest = Process->ImageFileName;
642 lnFName = min(lnFName, sizeof(Process->ImageFileName) - 1);
643 while (lnFName--) *szDest++ = (UCHAR)*szSrc++;
644 *szDest = ANSI_NULL;
645
646 /* Check if caller wants an audit name */
647 if (AuditName)
648 {
649 /* Setup the audit name */
650 SeInitializeProcessAuditName(SectionObject->FileObject,
651 FALSE,
652 AuditName);
653 }
654
655 /* Return status to caller */
656 return Status;
657 }
658
659 exit:
660 /* Unlock the Address Space */
661 DPRINT("Unlocking\n");
662 MmUnlockAddressSpace(ProcessAddressSpace);
663
664 /* Return status to caller */
665 return Status;
666 }
667
668 VOID
669 NTAPI
670 MmCleanProcessAddressSpace(IN PEPROCESS Process)
671 {
672 /* FIXME: Add part of MmDeleteProcessAddressSpace here */
673 }
674
675 NTSTATUS
676 NTAPI
677 MmDeleteProcessAddressSpace(PEPROCESS Process)
678 {
679 PVOID Address;
680 PMEMORY_AREA MemoryArea;
681
682 DPRINT("MmDeleteProcessAddressSpace(Process %x (%s))\n", Process,
683 Process->ImageFileName);
684
685 MmLockAddressSpace(&Process->VadRoot);
686
687 while ((MemoryArea = (PMEMORY_AREA)Process->VadRoot.BalancedRoot.u1.Parent) != NULL)
688 {
689 switch (MemoryArea->Type)
690 {
691 case MEMORY_AREA_SECTION_VIEW:
692 Address = (PVOID)MemoryArea->StartingAddress;
693 MmUnlockAddressSpace(&Process->VadRoot);
694 MmUnmapViewOfSection(Process, Address);
695 MmLockAddressSpace(&Process->VadRoot);
696 break;
697
698 case MEMORY_AREA_VIRTUAL_MEMORY:
699 case MEMORY_AREA_PEB_OR_TEB:
700 MmFreeVirtualMemory(Process, MemoryArea);
701 break;
702
703 case MEMORY_AREA_SHARED_DATA:
704 case MEMORY_AREA_NO_ACCESS:
705 MmFreeMemoryArea(&Process->VadRoot,
706 MemoryArea,
707 NULL,
708 NULL);
709 break;
710
711 case MEMORY_AREA_MDL_MAPPING:
712 KEBUGCHECK(PROCESS_HAS_LOCKED_PAGES);
713 break;
714
715 default:
716 KEBUGCHECK(0);
717 }
718 }
719
720 Mmi386ReleaseMmInfo(Process);
721
722 MmUnlockAddressSpace(&Process->VadRoot);
723
724 DPRINT("Finished MmReleaseMmInfo()\n");
725 return(STATUS_SUCCESS);
726 }
727