3 * Copyright (C) 1998, 1999, 2000, 2001, 2002 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /* $Id: anonmem.c,v 1.1 2002/08/10 16:41:19 dwelch Exp $
21 * PROJECT: ReactOS kernel
22 * FILE: ntoskrnl/mm/anonmem.c
23 * PURPOSE: Implementing anonymous memory.
24 * PROGRAMMER: David Welch
27 /* INCLUDE *****************************************************************/
29 #include <ddk/ntddk.h>
30 #include <internal/mm.h>
31 #include <internal/ob.h>
32 #include <internal/io.h>
33 #include <internal/ps.h>
34 #include <internal/pool.h>
37 #include <internal/debug.h>
39 /* FUNCTIONS *****************************************************************/
42 MmWritePageVirtualMemory(PMADDRESS_SPACE AddressSpace
,
46 return(STATUS_UNSUCCESSFUL
);
51 MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace
,
52 PMEMORY_AREA MemoryArea
,
56 PHYSICAL_ADDRESS PhysicalAddress
;
62 DPRINT("MmPageOutVirtualMemory(Address 0x%.8X) PID %d\n",
63 Address
, MemoryArea
->Process
->UniqueProcessId
);
66 * Check for paging out from a deleted virtual memory area.
68 if (MemoryArea
->DeleteInProgress
)
70 return(STATUS_UNSUCCESSFUL
);
74 * Paging out code or readonly data is easy.
76 if ((MemoryArea
->Attributes
& PAGE_READONLY
) ||
77 (MemoryArea
->Attributes
& PAGE_EXECUTE_READ
))
79 MmDeleteVirtualMapping(MemoryArea
->Process
, Address
, FALSE
,
80 NULL
, &PhysicalAddress
);
81 MmDeleteAllRmaps(PhysicalAddress
, NULL
, NULL
);
82 if (MmGetSavedSwapEntryPage(PhysicalAddress
) != 0)
84 DPRINT1("Read-only page was swapped out.\n");
87 MmReleasePageMemoryConsumer(MC_USER
, PhysicalAddress
);
89 PageOp
->Status
= STATUS_SUCCESS
;
90 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
91 MmReleasePageOp(PageOp
);
92 return(STATUS_SUCCESS
);
96 * Otherwise this is read-write data
98 MmDisableVirtualMapping(MemoryArea
->Process
, Address
,
99 &WasDirty
, (PULONG
)&PhysicalAddress
);
100 if (PhysicalAddress
.QuadPart
== 0)
106 MmDeleteVirtualMapping(MemoryArea
->Process
, Address
, FALSE
, NULL
, NULL
);
107 MmDeleteAllRmaps(PhysicalAddress
, NULL
, NULL
);
108 if ((SwapEntry
= MmGetSavedSwapEntryPage(PhysicalAddress
)) != 0)
110 MmCreatePageFileMapping(MemoryArea
->Process
, Address
, SwapEntry
);
111 MmSetSavedSwapEntryPage(PhysicalAddress
, 0);
113 MmReleasePageMemoryConsumer(MC_USER
, PhysicalAddress
);
114 PageOp
->Status
= STATUS_SUCCESS
;
115 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
116 MmReleasePageOp(PageOp
);
117 return(STATUS_SUCCESS
);
121 * If necessary, allocate an entry in the paging file for this page
123 SwapEntry
= MmGetSavedSwapEntryPage(PhysicalAddress
);
126 SwapEntry
= MmAllocSwapPage();
129 MmEnableVirtualMapping(MemoryArea
->Process
, Address
);
130 PageOp
->Status
= STATUS_UNSUCCESSFUL
;
131 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
132 MmReleasePageOp(PageOp
);
133 return(STATUS_UNSUCCESSFUL
);
138 * Write the page to the pagefile
140 Mdl
= MmCreateMdl(NULL
, NULL
, PAGESIZE
);
141 MmBuildMdlFromPages(Mdl
, (PULONG
)&PhysicalAddress
);
142 Status
= MmWriteToSwapPage(SwapEntry
, Mdl
);
143 if (!NT_SUCCESS(Status
))
145 DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",
147 MmEnableVirtualMapping(MemoryArea
->Process
, Address
);
148 PageOp
->Status
= STATUS_UNSUCCESSFUL
;
149 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
150 MmReleasePageOp(PageOp
);
151 return(STATUS_UNSUCCESSFUL
);
155 * Otherwise we have succeeded, free the page
157 DPRINT("MM: Swapped out virtual memory page 0x%.8X!\n", PhysicalAddress
);
158 MmDeleteVirtualMapping(MemoryArea
->Process
, Address
, FALSE
, NULL
, NULL
);
159 MmCreatePageFileMapping(MemoryArea
->Process
, Address
, SwapEntry
);
160 MmDeleteAllRmaps(PhysicalAddress
, NULL
, NULL
);
161 MmSetSavedSwapEntryPage(PhysicalAddress
, 0);
162 MmReleasePageMemoryConsumer(MC_USER
, PhysicalAddress
);
163 PageOp
->Status
= STATUS_SUCCESS
;
164 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
165 MmReleasePageOp(PageOp
);
166 return(STATUS_SUCCESS
);
170 MmNotPresentFaultVirtualMemory(PMADDRESS_SPACE AddressSpace
,
171 MEMORY_AREA
* MemoryArea
,
175 * FUNCTION: Move data into memory to satisfy a page not present fault
177 * AddressSpace = Address space within which the fault occurred
178 * MemoryArea = The memory area within which the fault occurred
179 * Address = The absolute address of fault
181 * NOTES: This function is called with the address space lock held.
184 PHYSICAL_ADDRESS Page
;
190 * There is a window between taking the page fault and locking the
191 * address space when another thread could load the page so we check
194 if (MmIsPagePresent(NULL
, Address
))
198 MmLockPage(MmGetPhysicalAddressForProcess(NULL
, Address
));
200 return(STATUS_SUCCESS
);
204 * Check for the virtual memory area being deleted.
206 if (MemoryArea
->DeleteInProgress
)
208 return(STATUS_UNSUCCESSFUL
);
212 * Get the segment corresponding to the virtual address
214 Region
= MmFindRegion(MemoryArea
->BaseAddress
,
215 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
217 if (Region
->Type
== MEM_RESERVE
)
219 return(STATUS_UNSUCCESSFUL
);
223 * Get or create a page operation
225 PageOp
= MmGetPageOp(MemoryArea
, (ULONG
)PsGetCurrentProcessId(),
226 (PVOID
)PAGE_ROUND_DOWN(Address
), NULL
, 0,
230 DPRINT1("MmGetPageOp failed");
235 * Check if someone else is already handling this fault, if so wait
238 if (PageOp
->Thread
!= PsGetCurrentThread())
240 MmUnlockAddressSpace(AddressSpace
);
241 Status
= KeWaitForSingleObject(&PageOp
->CompletionEvent
,
247 * Check for various strange conditions
249 if (Status
!= STATUS_SUCCESS
)
251 DPRINT1("Failed to wait for page op\n");
254 if (PageOp
->Status
== STATUS_PENDING
)
256 DPRINT1("Woke for page op before completion\n");
260 * If this wasn't a pagein then we need to restart the handling
262 if (PageOp
->OpType
!= MM_PAGEOP_PAGEIN
)
264 MmLockAddressSpace(AddressSpace
);
265 MmReleasePageOp(PageOp
);
266 return(STATUS_MM_RESTART_OPERATION
);
269 * If the thread handling this fault has failed then we don't retry
271 if (!NT_SUCCESS(PageOp
->Status
))
273 MmLockAddressSpace(AddressSpace
);
274 MmReleasePageOp(PageOp
);
277 MmLockAddressSpace(AddressSpace
);
280 MmLockPage(MmGetPhysicalAddressForProcess(NULL
, Address
));
282 MmReleasePageOp(PageOp
);
283 return(STATUS_SUCCESS
);
287 * Try to allocate a page
289 Status
= MmRequestPageMemoryConsumer(MC_USER
, FALSE
, &Page
);
290 if (Status
== STATUS_NO_MEMORY
)
292 MmUnlockAddressSpace(AddressSpace
);
293 Status
= MmRequestPageMemoryConsumer(MC_USER
, TRUE
, &Page
);
294 MmLockAddressSpace(AddressSpace
);
298 * Handle swapped out pages.
300 if (MmIsPageSwapEntry(NULL
, Address
))
305 MmDeletePageFileMapping(NULL
, Address
, &SwapEntry
);
306 Mdl
= MmCreateMdl(NULL
, NULL
, PAGESIZE
);
307 MmBuildMdlFromPages(Mdl
, (PULONG
)&Page
);
308 Status
= MmReadFromSwapPage(SwapEntry
, Mdl
);
309 if (!NT_SUCCESS(Status
))
313 MmSetSavedSwapEntryPage(Page
, SwapEntry
);
317 * Set the page. If we fail because we are out of memory then
320 Status
= MmCreateVirtualMapping(PsGetCurrentProcess(),
322 MemoryArea
->Attributes
,
325 while (Status
== STATUS_NO_MEMORY
)
327 MmUnlockAddressSpace(AddressSpace
);
328 Status
= MmCreateVirtualMapping(PsGetCurrentProcess(),
330 MemoryArea
->Attributes
,
333 MmLockAddressSpace(AddressSpace
);
335 if (!NT_SUCCESS(Status
))
337 DPRINT1("MmCreateVirtualMapping failed, not out of memory\n");
343 * Add the page to the process's working set
345 MmInsertRmap(Page
, PsGetCurrentProcess(), (PVOID
)PAGE_ROUND_DOWN(Address
));
348 * Finish the operation
352 MmLockPage(MmGetPhysicalAddressForProcess(NULL
, Address
));
354 PageOp
->Status
= STATUS_SUCCESS
;
355 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
356 MmReleasePageOp(PageOp
);
357 return(STATUS_SUCCESS
);
361 MmModifyAttributes(PMADDRESS_SPACE AddressSpace
,
369 * FUNCTION: Modify the attributes of a memory region
373 * If we are switching a previously committed region to reserved then
374 * free any allocated pages within the region
376 if (NewType
== MEM_RESERVE
&& OldType
== MEM_COMMIT
)
380 for (i
=0; i
<= (RegionSize
/PAGESIZE
); i
++)
382 LARGE_INTEGER PhysicalAddr
;
384 if (MmIsPageSwapEntry(AddressSpace
->Process
,
385 BaseAddress
+ (i
* PAGESIZE
)))
389 MmDeletePageFileMapping(AddressSpace
->Process
,
390 BaseAddress
+ (i
* PAGESIZE
),
392 MmFreeSwapPage(SwapEntry
);
396 PhysicalAddr
= MmGetPhysicalAddress(BaseAddress
+ (i
*PAGESIZE
));
397 MmDeleteVirtualMapping(AddressSpace
->Process
,
398 BaseAddress
+ (i
*PAGESIZE
),
400 if (PhysicalAddr
.QuadPart
!= 0)
402 MmDeleteRmap(PhysicalAddr
, AddressSpace
->Process
,
403 BaseAddress
+ (i
* PAGESIZE
));
404 MmReleasePageMemoryConsumer(MC_USER
, PhysicalAddr
);
411 * If we are changing the protection attributes of a committed region then
412 * alter the attributes for any allocated pages within the region
414 if (NewType
== MEM_COMMIT
&& OldType
== MEM_COMMIT
&&
415 OldProtect
!= NewProtect
)
419 for (i
=0; i
<= (RegionSize
/PAGESIZE
); i
++)
421 if (MmIsPagePresent(AddressSpace
->Process
,
422 BaseAddress
+ (i
*PAGESIZE
)))
424 MmSetPageProtect(AddressSpace
->Process
,
425 BaseAddress
+ (i
*PAGESIZE
),
433 NtAllocateVirtualMemory(IN HANDLE ProcessHandle
,
434 IN OUT PVOID
* UBaseAddress
,
436 IN OUT PULONG URegionSize
,
437 IN ULONG AllocationType
,
440 * FUNCTION: Allocates a block of virtual memory in the process address space
442 * ProcessHandle = The handle of the process which owns the virtual memory
443 * BaseAddress = A pointer to the virtual memory allocated. If you
444 * supply a non zero value the system will try to
445 * allocate the memory at the address supplied. It round
446 * it down to a multiple of the page size.
447 * ZeroBits = (OPTIONAL) You can specify the number of high order bits
448 * that must be zero, ensuring that the memory will be
449 * allocated at a address below a certain value.
450 * RegionSize = The number of bytes to allocate
451 * AllocationType = Indicates the type of virtual memory you like to
452 * allocated, can be a combination of MEM_COMMIT,
453 * MEM_RESERVE, MEM_RESET, MEM_TOP_DOWN.
454 * Protect = Indicates the protection type of the pages allocated, can be
455 * a combination of PAGE_READONLY, PAGE_READWRITE,
456 * PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_GUARD,
459 * This function maps to the win32 VirtualAllocEx. Virtual memory is
460 * process based so the protocol starts with a ProcessHandle. I
461 * splitted the functionality of obtaining the actual address and
462 * specifying the start address in two parameters ( BaseAddress and
463 * StartAddress ) The NumberOfBytesAllocated specify the range and the
464 * AllocationType and ProctectionType map to the other two parameters.
469 MEMORY_AREA
* MemoryArea
;
472 PMADDRESS_SPACE AddressSpace
;
478 DPRINT("NtAllocateVirtualMemory(*UBaseAddress %x, "
479 "ZeroBits %d, *URegionSize %x, AllocationType %x, Protect %x)\n",
480 *UBaseAddress
,ZeroBits
,*URegionSize
,AllocationType
,
484 * Check the validity of the parameters
486 if ((Protect
& PAGE_FLAGS_VALID_FROM_USER_MODE
) != Protect
)
488 return(STATUS_INVALID_PAGE_PROTECTION
);
490 if ((AllocationType
& (MEM_COMMIT
| MEM_RESERVE
)) == 0)
492 return(STATUS_INVALID_PARAMETER
);
495 PBaseAddress
= *UBaseAddress
;
496 PRegionSize
= *URegionSize
;
499 BaseAddress
= (PVOID
)PAGE_ROUND_DOWN(PBaseAddress
);
500 RegionSize
= PAGE_ROUND_UP(PBaseAddress
+ PRegionSize
) -
501 PAGE_ROUND_DOWN(PBaseAddress
);
503 Status
= ObReferenceObjectByHandle(ProcessHandle
,
504 PROCESS_VM_OPERATION
,
509 if (!NT_SUCCESS(Status
))
511 DPRINT("NtAllocateVirtualMemory() = %x\n",Status
);
515 Type
= (AllocationType
& MEM_COMMIT
) ? MEM_COMMIT
: MEM_RESERVE
;
516 DPRINT("Type %x\n", Type
);
518 AddressSpace
= &Process
->AddressSpace
;
519 MmLockAddressSpace(AddressSpace
);
521 if (PBaseAddress
!= 0)
523 MemoryArea
= MmOpenMemoryAreaByAddress(&Process
->AddressSpace
,
526 if (MemoryArea
!= NULL
&&
527 MemoryArea
->Type
== MEMORY_AREA_VIRTUAL_MEMORY
&&
528 MemoryArea
->Length
>= RegionSize
)
531 MmAlterRegion(&Process
->AddressSpace
,
532 MemoryArea
->BaseAddress
,
533 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
534 PBaseAddress
, RegionSize
,
535 Type
, Protect
, MmModifyAttributes
);
536 MmUnlockAddressSpace(AddressSpace
);
537 ObDereferenceObject(Process
);
538 DPRINT("NtAllocateVirtualMemory() = %x\n",Status
);
541 else if (MemoryArea
!= NULL
)
543 MmUnlockAddressSpace(AddressSpace
);
544 ObDereferenceObject(Process
);
545 return(STATUS_UNSUCCESSFUL
);
549 Status
= MmCreateMemoryArea(Process
,
550 &Process
->AddressSpace
,
551 MEMORY_AREA_VIRTUAL_MEMORY
,
558 if (!NT_SUCCESS(Status
))
560 MmUnlockAddressSpace(AddressSpace
);
561 ObDereferenceObject(Process
);
562 DPRINT("NtAllocateVirtualMemory() = %x\n",Status
);
565 MmInitialiseRegion(&MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
566 RegionSize
, Type
, Protect
);
568 if ((AllocationType
& MEM_COMMIT
) &&
569 ((Protect
& PAGE_READWRITE
) ||
570 (Protect
& PAGE_EXECUTE_READWRITE
)))
572 MmReserveSwapPages(RegionSize
);
575 *UBaseAddress
= BaseAddress
;
576 *URegionSize
= RegionSize
;
577 DPRINT("*UBaseAddress %x *URegionSize %x\n", BaseAddress
, RegionSize
);
579 MmUnlockAddressSpace(AddressSpace
);
580 ObDereferenceObject(Process
);
581 return(STATUS_SUCCESS
);
585 MmFreeVirtualMemoryPage(PVOID Context
,
586 MEMORY_AREA
* MemoryArea
,
588 PHYSICAL_ADDRESS PhysicalAddr
,
592 PEPROCESS Process
= (PEPROCESS
)Context
;
594 if (PhysicalAddr
.QuadPart
!= 0)
596 MmDeleteRmap(PhysicalAddr
, Process
, Address
);
597 MmReleasePageMemoryConsumer(MC_USER
, PhysicalAddr
);
599 else if (SwapEntry
!= 0)
601 MmFreeSwapPage(SwapEntry
);
606 MmFreeVirtualMemory(PEPROCESS Process
,
607 PMEMORY_AREA MemoryArea
)
609 PLIST_ENTRY current_entry
;
613 DPRINT("MmFreeVirtualMemory(Process %p MemoryArea %p)\n", Process
,
616 /* Mark this memory area as about to be deleted. */
617 MemoryArea
->DeleteInProgress
= TRUE
;
620 * Wait for any ongoing paging operations. Notice that since we have
621 * flagged this memory area as deleted no more page ops will be added.
623 if (MemoryArea
->PageOpCount
> 0)
625 for (i
= 0; i
< (PAGE_ROUND_UP(MemoryArea
->Length
) / PAGESIZE
); i
++)
629 if (MemoryArea
->PageOpCount
== 0)
634 PageOp
= MmCheckForPageOp(MemoryArea
, Process
->UniqueProcessId
,
635 MemoryArea
->BaseAddress
+ (i
* PAGESIZE
),
640 MmUnlockAddressSpace(&Process
->AddressSpace
);
641 Status
= KeWaitForSingleObject(&PageOp
->CompletionEvent
,
646 if (Status
!= STATUS_SUCCESS
)
648 DPRINT1("Failed to wait for page op\n");
651 MmLockAddressSpace(&Process
->AddressSpace
);
652 MmReleasePageOp(PageOp
);
657 /* Free all the individual segments. */
658 current_entry
= MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
.Flink
;
659 while (current_entry
!= &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
)
661 current
= CONTAINING_RECORD(current_entry
, MM_REGION
, RegionListEntry
);
662 current_entry
= current_entry
->Flink
;
666 /* Actually free the memory area. */
667 MmFreeMemoryArea(&Process
->AddressSpace
,
668 MemoryArea
->BaseAddress
,
670 MmFreeVirtualMemoryPage
,
675 NtFreeVirtualMemory(IN HANDLE ProcessHandle
,
676 IN PVOID
* PBaseAddress
,
677 IN PULONG PRegionSize
,
680 * FUNCTION: Frees a range of virtual memory
682 * ProcessHandle = Points to the process that allocated the virtual
684 * BaseAddress = Points to the memory address, rounded down to a
685 * multiple of the pagesize
686 * RegionSize = Limits the range to free, rounded up to a multiple of
688 * FreeType = Can be one of the values: MEM_DECOMMIT, or MEM_RELEASE
692 MEMORY_AREA
* MemoryArea
;
695 PMADDRESS_SPACE AddressSpace
;
699 DPRINT("NtFreeVirtualMemory(ProcessHandle %x, *PBaseAddress %x, "
700 "*PRegionSize %x, FreeType %x)\n",ProcessHandle
,*PBaseAddress
,
701 *PRegionSize
,FreeType
);
703 BaseAddress
= (PVOID
)PAGE_ROUND_DOWN((*PBaseAddress
));
704 RegionSize
= PAGE_ROUND_UP((*PBaseAddress
) + (*PRegionSize
)) -
705 PAGE_ROUND_DOWN((*PBaseAddress
));
707 Status
= ObReferenceObjectByHandle(ProcessHandle
,
708 PROCESS_VM_OPERATION
,
713 if (!NT_SUCCESS(Status
))
718 AddressSpace
= &Process
->AddressSpace
;
720 MmLockAddressSpace(AddressSpace
);
721 MemoryArea
= MmOpenMemoryAreaByAddress(AddressSpace
,
723 if (MemoryArea
== NULL
)
725 MmUnlockAddressSpace(AddressSpace
);
726 ObDereferenceObject(Process
);
727 return(STATUS_UNSUCCESSFUL
);
733 /* We can only free a memory area in one step. */
734 if (MemoryArea
->BaseAddress
!= BaseAddress
)
736 MmUnlockAddressSpace(AddressSpace
);
737 ObDereferenceObject(Process
);
738 return(STATUS_UNSUCCESSFUL
);
740 MmFreeVirtualMemory(Process
, MemoryArea
);
741 MmUnlockAddressSpace(AddressSpace
);
742 ObDereferenceObject(Process
);
743 return(STATUS_SUCCESS
);
747 MmAlterRegion(AddressSpace
,
748 MemoryArea
->BaseAddress
,
749 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
755 MmUnlockAddressSpace(AddressSpace
);
756 ObDereferenceObject(Process
);
759 MmUnlockAddressSpace(AddressSpace
);
760 ObDereferenceObject(Process
);
761 return(STATUS_NOT_IMPLEMENTED
);
765 MmProtectAnonMem(PMADDRESS_SPACE AddressSpace
,
766 PMEMORY_AREA MemoryArea
,
775 Region
= MmFindRegion(MemoryArea
->BaseAddress
,
776 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
778 *OldProtect
= Region
->Protect
;
779 Status
= MmAlterRegion(AddressSpace
, MemoryArea
->BaseAddress
,
780 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
781 BaseAddress
, Length
, Region
->Type
, Protect
,
787 MmQueryAnonMem(PMEMORY_AREA MemoryArea
,
789 PMEMORY_BASIC_INFORMATION Info
,
795 Info
->BaseAddress
= (PVOID
)PAGE_ROUND_DOWN(Address
);
797 Region
= MmFindRegion(MemoryArea
->BaseAddress
,
798 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
799 Address
, &RegionBase
);
800 Info
->AllocationBase
= RegionBase
;
801 Info
->AllocationProtect
= Region
->Protect
; /* FIXME */
802 Info
->RegionSize
= Region
->Length
;
803 Info
->State
= Region
->Type
;
804 Info
->Protect
= Region
->Protect
;
805 Info
->Type
= MEM_PRIVATE
;
806 return(STATUS_SUCCESS
);