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