- Add Ex*Spinlock macros and FLUSH_MULTIPLE_MAXIMUM definitions missing from DDK
[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/process.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 PMADDRESS_SPACE ProcessAddressSpace = (PMADDRESS_SPACE)&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 PMADDRESS_SPACE ProcessAddressSpace = (PMADDRESS_SPACE)&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 */
246 return KernelStack;
247 }
248
249 /*
250 * @implemented
251 */
252 NTSTATUS
253 STDCALL
254 MmGrowKernelStack(PVOID StackPointer)
255 {
256 PETHREAD Thread = PsGetCurrentThread();
257
258 /* Make sure we have reserved space for our grow */
259 ASSERT(((PCHAR)Thread->Tcb.StackBase - (PCHAR)Thread->Tcb.StackLimit) <=
260 (KERNEL_LARGE_STACK_SIZE + PAGE_SIZE));
261
262 /*
263 * We'll give you three more pages.
264 * NOTE: See note in MmCreateKernelStack. These pages are already being reserved.
265 * It would be more efficient to only grow them (commit them) here.
266 */
267 Thread->Tcb.StackLimit -= KERNEL_STACK_SIZE;
268
269 /* Return success */
270 return STATUS_SUCCESS;
271 }
272
273 NTSTATUS
274 STDCALL
275 MmCreatePeb(PEPROCESS Process)
276 {
277 PPEB Peb = NULL;
278 LARGE_INTEGER SectionOffset;
279 SIZE_T ViewSize = 0;
280 PVOID TableBase = NULL;
281 PIMAGE_NT_HEADERS NtHeaders;
282 PIMAGE_LOAD_CONFIG_DIRECTORY ImageConfigData;
283 NTSTATUS Status;
284 KAFFINITY ProcessAffinityMask = 0;
285 SectionOffset.QuadPart = (ULONGLONG)0;
286 DPRINT("MmCreatePeb\n");
287
288 /* Allocate the PEB */
289 Peb = MiCreatePebOrTeb(Process,
290 (PVOID)((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1));
291 ASSERT(Peb == (PVOID)0x7FFDF000);
292
293 /* Map NLS Tables */
294 DPRINT("Mapping NLS\n");
295 Status = MmMapViewOfSection(ExpNlsSectionPointer,
296 (PEPROCESS)Process,
297 &TableBase,
298 0,
299 0,
300 &SectionOffset,
301 &ViewSize,
302 ViewShare,
303 MEM_TOP_DOWN,
304 PAGE_READONLY);
305 if (!NT_SUCCESS(Status))
306 {
307 DPRINT1("MmMapViewOfSection() failed (Status %lx)\n", Status);
308 return(Status);
309 }
310 DPRINT("TableBase %p ViewSize %lx\n", TableBase, ViewSize);
311
312 /* Attach to Process */
313 KeAttachProcess(&Process->Pcb);
314
315 /* Initialize the PEB */
316 DPRINT("Allocated: %x\n", Peb);
317 RtlZeroMemory(Peb, sizeof(PEB));
318
319 /* Set up data */
320 DPRINT("Setting up PEB\n");
321 Peb->ImageBaseAddress = Process->SectionBaseAddress;
322 Peb->InheritedAddressSpace = 0;
323 Peb->Mutant = NULL;
324
325 /* NLS */
326 Peb->AnsiCodePageData = (PCHAR)TableBase + ExpAnsiCodePageDataOffset;
327 Peb->OemCodePageData = (PCHAR)TableBase + ExpOemCodePageDataOffset;
328 Peb->UnicodeCaseTableData = (PCHAR)TableBase + ExpUnicodeCaseTableDataOffset;
329
330 /* Default Version Data (could get changed below) */
331 Peb->OSMajorVersion = NtMajorVersion;
332 Peb->OSMinorVersion = NtMinorVersion;
333 Peb->OSBuildNumber = (USHORT)(NtBuildNumber & 0x3FFF);
334 Peb->OSPlatformId = 2; /* VER_PLATFORM_WIN32_NT */
335 Peb->OSCSDVersion = (USHORT)CmNtCSDVersion;
336
337 /* Heap and Debug Data */
338 Peb->NumberOfProcessors = KeNumberProcessors;
339 Peb->BeingDebugged = (BOOLEAN)(Process->DebugPort != NULL ? TRUE : FALSE);
340 Peb->NtGlobalFlag = NtGlobalFlag;
341 /*Peb->HeapSegmentReserve = MmHeapSegmentReserve;
342 Peb->HeapSegmentCommit = MmHeapSegmentCommit;
343 Peb->HeapDeCommitTotalFreeThreshold = MmHeapDeCommitTotalFreeThreshold;
344 Peb->HeapDeCommitFreeBlockThreshold = MmHeapDeCommitFreeBlockThreshold;*/
345 Peb->NumberOfHeaps = 0;
346 Peb->MaximumNumberOfHeaps = (PAGE_SIZE - sizeof(PEB)) / sizeof(PVOID);
347 Peb->ProcessHeaps = (PVOID*)Peb + 1;
348
349 /* Image Data */
350 if ((NtHeaders = RtlImageNtHeader(Peb->ImageBaseAddress)))
351 {
352 /* Write subsystem data */
353 Peb->ImageSubSystem = NtHeaders->OptionalHeader.Subsystem;
354 Peb->ImageSubSystemMajorVersion = NtHeaders->OptionalHeader.MajorSubsystemVersion;
355 Peb->ImageSubSystemMinorVersion = NtHeaders->OptionalHeader.MinorSubsystemVersion;
356
357 /* Write Version Data */
358 if (NtHeaders->OptionalHeader.Win32VersionValue)
359 {
360 Peb->OSMajorVersion = NtHeaders->OptionalHeader.Win32VersionValue & 0xFF;
361 Peb->OSMinorVersion = (NtHeaders->OptionalHeader.Win32VersionValue >> 8) & 0xFF;
362 Peb->OSBuildNumber = (NtHeaders->OptionalHeader.Win32VersionValue >> 16) & 0x3FFF;
363
364 /* Set the Platform ID */
365 Peb->OSPlatformId = (NtHeaders->OptionalHeader.Win32VersionValue >> 30) ^ 2;
366 }
367
368 /* Check if the image is not safe for SMP */
369 if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_UP_SYSTEM_ONLY)
370 {
371 /* FIXME: Choose one randomly */
372 Peb->ImageProcessAffinityMask = 1;
373 }
374 else
375 {
376 /* Use affinity from Image Header */
377 Peb->ImageProcessAffinityMask = ProcessAffinityMask;
378 }
379
380 _SEH_TRY
381 {
382 /* Get the Image Config Data too */
383 ImageConfigData = RtlImageDirectoryEntryToData(Peb->ImageBaseAddress,
384 TRUE,
385 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
386 &ViewSize);
387
388 ProbeForRead(ImageConfigData,
389 sizeof(IMAGE_LOAD_CONFIG_DIRECTORY),
390 sizeof(ULONG));
391
392 /* Process the image config data overrides if specfied. */
393 if (ImageConfigData != NULL)
394 {
395 if (ImageConfigData->CSDVersion)
396 {
397 Peb->OSCSDVersion = ImageConfigData->CSDVersion;
398 }
399 if (ImageConfigData->ProcessAffinityMask)
400 {
401 ProcessAffinityMask = ImageConfigData->ProcessAffinityMask;
402 }
403 }
404 }
405 _SEH_HANDLE
406 {
407 Status = _SEH_GetExceptionCode();
408 }
409 _SEH_END;
410 }
411
412 /* Misc data */
413 Peb->SessionId = Process->Session;
414 Process->Peb = Peb;
415
416 /* Detach from the Process */
417 KeDetachProcess();
418
419 DPRINT("MmCreatePeb: Peb created at %p\n", Peb);
420 return Status;
421 }
422
423 PTEB
424 STDCALL
425 MmCreateTeb(PEPROCESS Process,
426 PCLIENT_ID ClientId,
427 PINITIAL_TEB InitialTeb)
428 {
429 PTEB Teb;
430 BOOLEAN Attached = FALSE;
431
432 /* Attach to the process */
433 DPRINT("MmCreateTeb\n");
434 if (Process != PsGetCurrentProcess())
435 {
436 /* Attach to Target */
437 KeAttachProcess(&Process->Pcb);
438 Attached = TRUE;
439 }
440
441 /* Allocate the TEB */
442 Teb = MiCreatePebOrTeb(Process,
443 (PVOID)((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1));
444
445 /* Initialize the PEB */
446 RtlZeroMemory(Teb, sizeof(TEB));
447
448 /* Set TIB Data */
449 Teb->Tib.ExceptionList = (PVOID)0xFFFFFFFF;
450 Teb->Tib.Version = 1;
451 Teb->Tib.Self = (PNT_TIB)Teb;
452
453 /* Set TEB Data */
454 Teb->Cid = *ClientId;
455 Teb->RealClientId = *ClientId;
456 Teb->ProcessEnvironmentBlock = Process->Peb;
457 Teb->CurrentLocale = PsDefaultThreadLocaleId;
458
459 /* Store stack information from InitialTeb */
460 if(InitialTeb != NULL)
461 {
462 Teb->Tib.StackBase = InitialTeb->StackBase;
463 Teb->Tib.StackLimit = InitialTeb->StackLimit;
464 Teb->DeallocationStack = InitialTeb->AllocatedStackBase;
465 }
466
467 /* Return TEB Address */
468 DPRINT("Allocated: %x\n", Teb);
469 if (Attached) KeDetachProcess();
470 return Teb;
471 }
472
473 NTSTATUS
474 STDCALL
475 MmCreateProcessAddressSpace(IN PEPROCESS Process,
476 IN PROS_SECTION_OBJECT Section OPTIONAL,
477 IN POBJECT_NAME_INFORMATION *AuditName OPTIONAL)
478 {
479 NTSTATUS Status;
480 PMADDRESS_SPACE ProcessAddressSpace = (PMADDRESS_SPACE)&Process->VadRoot;
481 PVOID BaseAddress;
482 PMEMORY_AREA MemoryArea;
483 PHYSICAL_ADDRESS BoundaryAddressMultiple;
484 SIZE_T ViewSize = 0;
485 PVOID ImageBase = 0;
486 BoundaryAddressMultiple.QuadPart = 0;
487
488 /* Initialize the Addresss Space */
489 MmInitializeAddressSpace(Process, ProcessAddressSpace);
490
491 /* Acquire the Lock */
492 MmLockAddressSpace(ProcessAddressSpace);
493
494 /* Protect the highest 64KB of the process address space */
495 BaseAddress = (PVOID)MmUserProbeAddress;
496 Status = MmCreateMemoryArea(ProcessAddressSpace,
497 MEMORY_AREA_NO_ACCESS,
498 &BaseAddress,
499 0x10000,
500 PAGE_NOACCESS,
501 &MemoryArea,
502 FALSE,
503 0,
504 BoundaryAddressMultiple);
505 if (!NT_SUCCESS(Status))
506 {
507 DPRINT1("Failed to protect last 64KB\n");
508 goto exit;
509 }
510
511 /* Protect the 60KB above the shared user page */
512 BaseAddress = (char*)USER_SHARED_DATA + PAGE_SIZE;
513 Status = MmCreateMemoryArea(ProcessAddressSpace,
514 MEMORY_AREA_NO_ACCESS,
515 &BaseAddress,
516 0x10000 - PAGE_SIZE,
517 PAGE_NOACCESS,
518 &MemoryArea,
519 FALSE,
520 0,
521 BoundaryAddressMultiple);
522 if (!NT_SUCCESS(Status))
523 {
524 DPRINT1("Failed to protect the memory above the shared user page\n");
525 goto exit;
526 }
527
528 /* Create the shared data page */
529 BaseAddress = (PVOID)USER_SHARED_DATA;
530 Status = MmCreateMemoryArea(ProcessAddressSpace,
531 MEMORY_AREA_SHARED_DATA,
532 &BaseAddress,
533 PAGE_SIZE,
534 PAGE_EXECUTE_READ,
535 &MemoryArea,
536 FALSE,
537 0,
538 BoundaryAddressMultiple);
539 if (!NT_SUCCESS(Status))
540 {
541 DPRINT1("Failed to create Shared User Data\n");
542 goto exit;
543 }
544
545 /* The process now has an address space */
546 Process->HasAddressSpace = TRUE;
547
548 /* Check if there's a Section Object */
549 if (Section)
550 {
551 UNICODE_STRING FileName;
552 PWCHAR szSrc;
553 PCHAR szDest;
554 USHORT lnFName = 0;
555
556 /* Unlock the Address Space */
557 DPRINT("Unlocking\n");
558 MmUnlockAddressSpace(ProcessAddressSpace);
559
560 DPRINT("Mapping process image. Section: %p, Process: %p, ImageBase: %p\n",
561 Section, Process, &ImageBase);
562 Status = MmMapViewOfSection(Section,
563 (PEPROCESS)Process,
564 (PVOID*)&ImageBase,
565 0,
566 0,
567 NULL,
568 &ViewSize,
569 0,
570 MEM_COMMIT,
571 PAGE_READWRITE);
572 if (!NT_SUCCESS(Status))
573 {
574 DPRINT1("Failed to map process Image\n");
575 return Status;
576 }
577
578 /* Save the pointer */
579 Process->SectionBaseAddress = ImageBase;
580
581 /* Determine the image file name and save it to EPROCESS */
582 DPRINT("Getting Image name\n");
583 FileName = Section->FileObject->FileName;
584 szSrc = (PWCHAR)(FileName.Buffer + FileName.Length);
585 while (szSrc >= FileName.Buffer)
586 {
587 /* Make sure this isn't a backslash */
588 if (*--szSrc == OBJ_NAME_PATH_SEPARATOR)
589 {
590 /* If so, stop it here */
591 szSrc++;
592 break;
593 }
594 else
595 {
596 /* Otherwise, keep going */
597 lnFName++;
598 }
599 }
600
601 /* Copy the to the process and truncate it to 15 characters if necessary */
602 szDest = Process->ImageFileName;
603 lnFName = min(lnFName, sizeof(Process->ImageFileName) - 1);
604 while (lnFName--) *szDest++ = (UCHAR)*szSrc++;
605 *szDest = UNICODE_NULL;
606
607 /* Check if caller wants an audit name */
608 if (AuditName)
609 {
610 /* Setup the audit name */
611 SeInitializeProcessAuditName(Section->FileObject,
612 FALSE,
613 AuditName);
614 }
615
616 /* Return status to caller */
617 return Status;
618 }
619
620 exit:
621 /* Unlock the Address Space */
622 DPRINT("Unlocking\n");
623 MmUnlockAddressSpace(ProcessAddressSpace);
624
625 /* Return status to caller */
626 return Status;
627 }
628
629 VOID
630 NTAPI
631 MmCleanProcessAddressSpace(IN PEPROCESS Process)
632 {
633 /* FIXME: Add part of MmDeleteProcessAddressSpace here */
634 }
635
636 NTSTATUS
637 NTAPI
638 MmDeleteProcessAddressSpace(PEPROCESS Process)
639 {
640 PVOID Address;
641 PMEMORY_AREA MemoryArea;
642
643 DPRINT("MmDeleteProcessAddressSpace(Process %x (%s))\n", Process,
644 Process->ImageFileName);
645
646 MmLockAddressSpace((PMADDRESS_SPACE)&Process->VadRoot);
647
648 while ((MemoryArea = ((PMADDRESS_SPACE)&Process->VadRoot)->MemoryAreaRoot) != NULL)
649 {
650 switch (MemoryArea->Type)
651 {
652 case MEMORY_AREA_SECTION_VIEW:
653 Address = (PVOID)MemoryArea->StartingAddress;
654 MmUnlockAddressSpace((PMADDRESS_SPACE)&Process->VadRoot);
655 MmUnmapViewOfSection(Process, Address);
656 MmLockAddressSpace((PMADDRESS_SPACE)&Process->VadRoot);
657 break;
658
659 case MEMORY_AREA_VIRTUAL_MEMORY:
660 case MEMORY_AREA_PEB_OR_TEB:
661 MmFreeVirtualMemory(Process, MemoryArea);
662 break;
663
664 case MEMORY_AREA_SHARED_DATA:
665 case MEMORY_AREA_NO_ACCESS:
666 MmFreeMemoryArea((PMADDRESS_SPACE)&Process->VadRoot,
667 MemoryArea,
668 NULL,
669 NULL);
670 break;
671
672 case MEMORY_AREA_MDL_MAPPING:
673 KEBUGCHECK(PROCESS_HAS_LOCKED_PAGES);
674 break;
675
676 default:
677 KEBUGCHECK(0);
678 }
679 }
680
681 Mmi386ReleaseMmInfo(Process);
682
683 MmUnlockAddressSpace((PMADDRESS_SPACE)&Process->VadRoot);
684 MmDestroyAddressSpace((PMADDRESS_SPACE)&Process->VadRoot);
685
686 DPRINT("Finished MmReleaseMmInfo()\n");
687 return(STATUS_SUCCESS);
688 }