ReactOS  0.4.15-dev-2092-gf04890c
rmap.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top directory
3  * PROJECT: ReactOS kernel
4  * FILE: ntoskrnl/mm/rmap.c
5  * PURPOSE: Kernel memory managment functions
6  *
7  * PROGRAMMERS: David Welch (welch@cwcom.net)
8  */
9 
10 /* INCLUDES *****************************************************************/
11 
12 #include <ntoskrnl.h>
13 #include <cache/section/newmm.h>
14 #define NDEBUG
15 #include <debug.h>
16 
17 /* TYPES ********************************************************************/
18 
19 /* GLOBALS ******************************************************************/
20 
22 
23 /* FUNCTIONS ****************************************************************/
24 
26 static
27 VOID
28 NTAPI
29 RmapListFree(
31 {
33 }
34 
35 CODE_SEG("INIT")
36 VOID
37 NTAPI
39 {
41  NULL,
42  RmapListFree,
43  0,
44  sizeof(MM_RMAP_ENTRY),
45  TAG_RMAP,
46  50);
47 }
48 
50 NTAPI
52 {
56  PVOID Address = NULL;
60  LARGE_INTEGER SegmentOffset;
61  KIRQL OldIrql;
62 
63 GetEntry:
65 
67 
68  while (entry && RMAP_IS_SEGMENT(entry->Address))
69  entry = entry->Next;
70 
71  if (entry == NULL)
72  {
74  goto WriteSegment;
75  }
76 
77  Process = entry->Process;
78  Address = entry->Address;
79 
80  if ((((ULONG_PTR)Address) & 0xFFF) != 0)
81  {
82  KeBugCheck(MEMORY_MANAGEMENT);
83  }
84 
85  /* This is for user-mode address only */
87 
88  if (!ExAcquireRundownProtection(&Process->RundownProtect))
89  {
92  }
93 
96  if (!NT_SUCCESS(Status))
97  {
98  ExReleaseRundownProtection(&Process->RundownProtect);
99  return Status;
100  }
101  AddressSpace = &Process->Vm;
102 
104 
106  {
107  /* This changed in the short window where we didn't have any locks */
109  ExReleaseRundownProtection(&Process->RundownProtect);
111  goto GetEntry;
112  }
113 
116  {
118  ExReleaseRundownProtection(&Process->RundownProtect);
120  goto GetEntry;
121  }
122 
124  {
126  BOOLEAN Dirty;
127  PFN_NUMBER MapPage;
129  BOOLEAN Released;
130 
131  Offset.QuadPart = MemoryArea->SectionData.ViewOffset +
133 
134  Segment = MemoryArea->SectionData.Segment;
135 
137 
139  if (Entry && MM_IS_WAIT_PTE(Entry))
140  {
141  /* The segment is being read or something. Give up */
145  {
146  ExReleaseRundownProtection(&Process->RundownProtect);
148  }
149  return(STATUS_UNSUCCESSFUL);
150  }
151 
152  /* Delete this virtual mapping in the process */
153  MmDeleteVirtualMapping(Process, Address, &Dirty, &MapPage);
154 
155  /* We checked this earlier */
156  ASSERT(MapPage == Page);
157 
158  if (Page != PFN_FROM_SSE(Entry))
159  {
160  SWAPENTRY SwapEntry;
161 
162  /* This page is private to the process */
164 
165  /* Check if we should write it back to the page file */
166  SwapEntry = MmGetSavedSwapEntryPage(Page);
167 
168  if ((SwapEntry == 0) && Dirty)
169  {
170  /* We don't have a Swap entry, yet the page is dirty. Get one */
171  SwapEntry = MmAllocSwapPage();
172  if (!SwapEntry)
173  {
175  &MemoryArea->SectionData.RegionListHead,
176  Address, NULL);
177 
178  /* We can't, so let this page in the Process VM */
181 
184  {
185  ExReleaseRundownProtection(&Process->RundownProtect);
187  }
188 
189  return STATUS_UNSUCCESSFUL;
190  }
191  }
192 
193  if (Dirty)
194  {
195  Status = MmWriteToSwapPage(SwapEntry, Page);
196  if (!NT_SUCCESS(Status))
197  {
198  /* We failed at saving the content of this page. Keep it in */
200  &MemoryArea->SectionData.RegionListHead,
201  Address, NULL);
202 
203  /* This Swap Entry is useless to us */
205  MmFreeSwapPage(SwapEntry);
206 
207  /* We can't, so let this page in the Process VM */
210 
212  ExReleaseRundownProtection(&Process->RundownProtect);
214 
215  return STATUS_UNSUCCESSFUL;
216  }
217  }
218 
219  if (SwapEntry)
220  {
221  /* Keep this in the process VM */
224  }
225 
227 
228  /* We can finally let this page go */
230 #if DBG
234 #endif
236 
237  ExReleaseRundownProtection(&Process->RundownProtect);
239 
240  return STATUS_SUCCESS;
241  }
242 
243  /* Delete this RMAP */
245 
246  /* One less mapping referencing this segment */
248 
251 
252  ExReleaseRundownProtection(&Process->RundownProtect);
254 
255  if (Released) return STATUS_SUCCESS;
256  }
257 #ifdef NEWCC
258  else if (Type == MEMORY_AREA_CACHE)
259  {
260  /* NEWCC does locking itself */
263  }
264 #endif
265  else
266  {
267  KeBugCheck(MEMORY_MANAGEMENT);
268  }
269 
270 WriteSegment:
271  /* Now write this page to file, if needed */
272  Segment = MmGetSectionAssociation(Page, &SegmentOffset);
273  if (Segment)
274  {
275  BOOLEAN Released;
276 
278 
279  Released = MmCheckDirtySegment(Segment, &SegmentOffset, FALSE, TRUE);
280 
282 
284 
285  if (Released)
286  {
287  return STATUS_SUCCESS;
288  }
289  }
290 
291  /* If we are here, then we didn't release the page */
292  return STATUS_UNSUCCESSFUL;
293 }
294 
295 VOID
296 NTAPI
298 {
299  PMM_RMAP_ENTRY current_entry;
300  KIRQL OldIrql;
301 
303  current_entry = MmGetRmapListHeadPage(Page);
304  if (current_entry == NULL)
305  {
306  DPRINT1("MmSetCleanAllRmaps: No rmaps.\n");
307  KeBugCheck(MEMORY_MANAGEMENT);
308  }
309  while (current_entry != NULL)
310  {
311  if (!RMAP_IS_SEGMENT(current_entry->Address))
312  MmSetCleanPage(current_entry->Process, current_entry->Address);
313  current_entry = current_entry->Next;
314  }
316 }
317 
318 BOOLEAN
319 NTAPI
321 {
322  PMM_RMAP_ENTRY current_entry;
323  KIRQL OldIrql;
324  BOOLEAN Dirty = FALSE;
325 
327  current_entry = MmGetRmapListHeadPage(Page);
328  if (current_entry == NULL)
329  {
330  DPRINT1("MmIsDirtyPageRmap: No rmaps.\n");
331  KeBugCheck(MEMORY_MANAGEMENT);
332  }
333  while (current_entry != NULL)
334  {
335  if (!RMAP_IS_SEGMENT(current_entry->Address))
336  {
337  if (MmIsDirtyPage(current_entry->Process, current_entry->Address))
338  {
339  Dirty = TRUE;
340  break;
341  }
342  }
343  current_entry = current_entry->Next;
344  }
346 
347  return Dirty;
348 }
349 
350 VOID
351 NTAPI
353  PVOID Address)
354 {
355  PMM_RMAP_ENTRY current_entry;
356  PMM_RMAP_ENTRY new_entry;
357  ULONG PrevSize;
358  KIRQL OldIrql;
359 
360  if (!RMAP_IS_SEGMENT(Address))
362 
363  new_entry = ExAllocateFromNPagedLookasideList(&RmapLookasideList);
364  if (new_entry == NULL)
365  {
366  KeBugCheck(MEMORY_MANAGEMENT);
367  }
368  new_entry->Address = Address;
369  new_entry->Process = (PEPROCESS)Process;
370 #if DBG
371  new_entry->Caller = _ReturnAddress();
372 #endif
373 
374  if (
377  {
378  DPRINT1("Insert rmap (%d, 0x%.8X) 0x%.8X which doesn't match physical "
379  "address 0x%.8X\n", Process ? Process->UniqueProcessId : 0,
380  Address,
382  Page << PAGE_SHIFT);
383  KeBugCheck(MEMORY_MANAGEMENT);
384  }
385 
387  current_entry = MmGetRmapListHeadPage(Page);
388 
389  PMM_RMAP_ENTRY previous_entry = NULL;
390  /* Keep the list sorted */
391  while (current_entry && (current_entry->Address < Address))
392  {
393  previous_entry = current_entry;
394  current_entry = current_entry->Next;
395  }
396 
397  /* In case of clash in the address, sort by process */
398  if (current_entry && (current_entry->Address == Address))
399  {
400  while (current_entry && (current_entry->Process < Process))
401  {
402  previous_entry = current_entry;
403  current_entry = current_entry->Next;
404  }
405  }
406 
407  if (current_entry && (current_entry->Address == Address) && (current_entry->Process == Process))
408  {
409 #if DBG
410  DbgPrint("MmInsertRmap tries to add a second rmap entry for address %p\n", current_entry->Address);
411  DbgPrint(" current caller %p\n", new_entry->Caller);
412  DbgPrint(" previous caller %p\n", current_entry->Caller);
413 #endif
414  KeBugCheck(MEMORY_MANAGEMENT);
415  }
416 
417  new_entry->Next = current_entry;
418  if (previous_entry)
419  previous_entry->Next = new_entry;
420  else
421  MmSetRmapListHeadPage(Page, new_entry);
422 
424 
425  if (!RMAP_IS_SEGMENT(Address))
426  {
427  ASSERT(Process != NULL);
428  PrevSize = InterlockedExchangeAddUL(&Process->Vm.WorkingSetSize, PAGE_SIZE);
429  if (PrevSize >= Process->Vm.PeakWorkingSetSize)
430  {
431  Process->Vm.PeakWorkingSetSize = PrevSize + PAGE_SIZE;
432  }
433  }
434 }
435 
436 VOID
437 NTAPI
439  PVOID Address)
440 {
441  PMM_RMAP_ENTRY current_entry, previous_entry;
442  KIRQL OldIrql;
443 
445  previous_entry = NULL;
446  current_entry = MmGetRmapListHeadPage(Page);
447 
448  while (current_entry != NULL)
449  {
450  if (current_entry->Process == (PEPROCESS)Process &&
451  current_entry->Address == Address)
452  {
453  if (previous_entry == NULL)
454  {
455  MmSetRmapListHeadPage(Page, current_entry->Next);
456  }
457  else
458  {
459  previous_entry->Next = current_entry->Next;
460  }
462 
463  ExFreeToNPagedLookasideList(&RmapLookasideList, current_entry);
464  if (!RMAP_IS_SEGMENT(Address))
465  {
466  ASSERT(Process != NULL);
467  (void)InterlockedExchangeAddUL(&Process->Vm.WorkingSetSize, -PAGE_SIZE);
468  }
469  return;
470  }
471  previous_entry = current_entry;
472  current_entry = current_entry->Next;
473  }
474  KeBugCheck(MEMORY_MANAGEMENT);
475 }
476 
477 /*
478 
479 Return the process pointer given when a previous call to MmInsertRmap was
480 called with a process and address pointer that conform to the segment rmap
481 schema. In short, this requires the address part to be 0xffffff00 + n
482 where n is between 0 and 255. When such an rmap exists, it specifies a
483 segment rmap in which the process part is a pointer to a slice of a section
484 page table, and the low 8 bits of the address represent a page index in the
485 page table slice. Together, this information is used by
486 MmGetSectionAssociation to determine which page entry points to this page in
487 the segment page table.
488 
489 */
490 
491 PVOID
492 NTAPI
494 {
496  PMM_RMAP_ENTRY current_entry;//, previous_entry;
498 
499  //previous_entry = NULL;
500  current_entry = MmGetRmapListHeadPage(Page);
501  while (current_entry != NULL)
502  {
503  if (RMAP_IS_SEGMENT(current_entry->Address))
504  {
505  Result = (PCACHE_SECTION_PAGE_TABLE)current_entry->Process;
506  *RawOffset = (ULONG_PTR)current_entry->Address & ~RMAP_SEGMENT_MASK;
507  if (*Result->Segment->Flags & MM_SEGMENT_INDELETE)
508  {
510  return NULL;
511  }
512 
513  InterlockedIncrement64(Result->Segment->ReferenceCount);
515  return Result;
516  }
517  //previous_entry = current_entry;
518  current_entry = current_entry->Next;
519  }
521  return NULL;
522 }
523 
524 /*
525 
526 Remove the section rmap associated with the indicated page, if it exists.
527 
528 */
529 
530 VOID
531 NTAPI
533 {
534  PMM_RMAP_ENTRY current_entry, previous_entry;
536 
537  previous_entry = NULL;
538  current_entry = MmGetRmapListHeadPage(Page);
539  while (current_entry != NULL)
540  {
541  if (RMAP_IS_SEGMENT(current_entry->Address))
542  {
543  if (previous_entry == NULL)
544  {
545  MmSetRmapListHeadPage(Page, current_entry->Next);
546  }
547  else
548  {
549  previous_entry->Next = current_entry->Next;
550  }
552  ExFreeToNPagedLookasideList(&RmapLookasideList, current_entry);
553  return;
554  }
555  previous_entry = current_entry;
556  current_entry = current_entry->Next;
557  }
559 }
PMM_REGION NTAPI MmFindRegion(PVOID BaseAddress, PLIST_ENTRY RegionListHead, PVOID Address, PVOID *RegionBaseAddress)
Definition: region.c:257
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
VOID NTAPI MmDeleteRmap(PFN_NUMBER Page, PEPROCESS Process, PVOID Address)
Definition: rmap.c:438
#define MmGetPageEntrySectionSegment(S, O)
Definition: mm.h:1448
PEPROCESS Process
Definition: mm.h:236
struct LOOKASIDE_ALIGN _NPAGED_LOOKASIDE_LIST NPAGED_LOOKASIDE_LIST
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
ULONG Type
Definition: mm.h:219
#define PROCESS_ALL_ACCESS
Definition: nt_native.h:1324
struct _Entry Entry
Definition: kefuncs.h:627
#define DbgPrint
Definition: loader.c:25
NTSTATUS NTAPI MmCreateVirtualMapping(struct _EPROCESS *Process, PVOID Address, ULONG flProtect, PPFN_NUMBER Pages, ULONG PageCount)
NTKERNELAPI VOID FASTCALL ExReleaseRundownProtection(_Inout_ PEX_RUNDOWN_REF RunRef)
#define TRUE
Definition: types.h:120
#define MC_USER
Definition: mm.h:92
struct _MM_RMAP_ENTRY *NTAPI MmGetRmapListHeadPage(PFN_NUMBER Page)
Definition: freelist.c:458
#define PFN_FROM_SSE(E)
Definition: mm.h:1237
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG AddressSpace
Definition: iofuncs.h:2268
FORCEINLINE VOID MmUnlockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1526
Definition: mm.h:389
LONG NTSTATUS
Definition: precomp.h:26
struct _EPROCESS * PEPROCESS
Definition: nt_native.h:30
#define ExAcquireRundownProtection
Definition: ex.h:128
NTSTATUS NTAPI MmReleasePageMemoryConsumer(ULONG Consumer, PFN_NUMBER Page)
Definition: balance.c:77
#define PAGE_ROUND_DOWN(x)
Definition: mmtypes.h:36
FORCEINLINE KIRQL MiAcquirePfnLock(VOID)
Definition: mm.h:886
NTSTATUS NTAPI MmCreatePageFileMapping(struct _EPROCESS *Process, PVOID Address, SWAPENTRY SwapEntry)
BOOLEAN NTAPI MmUnsharePageEntrySectionSegment(PMEMORY_AREA MemoryArea, PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset, BOOLEAN Dirty, BOOLEAN PageOut, ULONG_PTR *InEntry)
Definition: section.c:1084
struct _CACHE_SECTION_PAGE_TABLE * PCACHE_SECTION_PAGE_TABLE
VOID NTAPI MmDeleteSectionAssociation(PFN_NUMBER Page)
Definition: rmap.c:532
BOOLEAN NTAPI MmIsDirtyPageRmap(PFN_NUMBER Page)
Definition: rmap.c:320
BOOLEAN NTAPI MmCheckDirtySegment(PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset, BOOLEAN ForceDirty, BOOLEAN PageOut)
PMEMORY_AREA NTAPI MmLocateMemoryAreaByAddress(PMMSUPPORT AddressSpace, PVOID Address)
Definition: marea.c:60
#define MmLockSectionSegment(x)
Definition: mm.h:1262
FORCEINLINE VOID MiReleasePfnLock(_In_ KIRQL OldIrql)
Definition: mm.h:893
uint32_t ULONG_PTR
Definition: typedefs.h:65
PVOID NTAPI MmGetSegmentRmap(PFN_NUMBER Page, PULONG RawOffset)
Definition: rmap.c:493
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG PFN_NUMBER
Definition: ke.h:9
VOID NTAPI MmSetDirtyPage(struct _EPROCESS *Process, PVOID Address)
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
_IRQL_requires_max_(DISPATCH_LEVEL)
Definition: rmap.c:25
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1427
NTSTATUS NTAPI MmpPageOutPhysicalAddress(PFN_NUMBER Page)
Definition: swapout.c:345
VOID NTAPI MmInitializeRmapList(VOID)
Definition: rmap.c:38
VOID NTAPI MmSetCleanPage(struct _EPROCESS *Process, PVOID Address)
unsigned char BOOLEAN
static WCHAR Address[46]
Definition: ping.c:68
VOID NTAPI MmDeleteVirtualMapping(struct _EPROCESS *Process, PVOID Address, BOOLEAN *WasDirty, PPFN_NUMBER Page)
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
NTSTATUS NTAPI ObReferenceObjectByPointer(IN PVOID Object, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode)
Definition: obref.c:383
PFN_NUMBER Page
Definition: section.c:4831
void * PVOID
Definition: retypes.h:9
#define MM_IS_WAIT_PTE(E)
Definition: mm.h:1239
#define MEMORY_AREA_SECTION_VIEW
Definition: mm.h:71
#define MmUnlockSectionSegment(x)
Definition: mm.h:1270
VOID NTAPI MmSetRmapListHeadPage(PFN_NUMBER Page, struct _MM_RMAP_ENTRY *ListHead)
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
Status
Definition: gdiplustypes.h:24
#define InterlockedIncrement64
Definition: interlocked.h:211
VOID NTAPI ExInitializeNPagedLookasideList(IN PNPAGED_LOOKASIDE_LIST Lookaside, IN PALLOCATE_FUNCTION Allocate OPTIONAL, IN PFREE_FUNCTION Free OPTIONAL, IN ULONG Flags, IN SIZE_T Size, IN ULONG Tag, IN USHORT Depth)
Definition: lookas.c:218
#define ASSERT(a)
Definition: mode.c:45
PMM_SECTION_SEGMENT NTAPI MmGetSectionAssociation(PFN_NUMBER Page, PLARGE_INTEGER Offset)
Definition: sptab.c:352
#define TAG_RMAP
Definition: tag.h:133
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
SWAPENTRY NTAPI MmAllocSwapPage(VOID)
Definition: pagefile.c:304
#define InterlockedExchangeAddUL(Addend, Value)
Definition: ex.h:1505
#define STATUS_PROCESS_IS_TERMINATING
Definition: ntstatus.h:502
#define ObDereferenceObject
Definition: obfuncs.h:203
BOOLEAN DeleteInProgress
Definition: mm.h:221
#define RMAP_SEGMENT_MASK
Definition: mm.h:824
Type
Definition: Type.h:6
#define RMAP_IS_SEGMENT(x)
Definition: mm.h:825
CODE_SEG("INIT")
Definition: fsrtlpc.c:19
VOID NTAPI MmSetCleanAllRmaps(PFN_NUMBER Page)
Definition: rmap.c:297
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
uint32_t entry
Definition: isohybrid.c:63
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define P(row, col)
#define MA_GetStartingAddress(_MemoryArea)
Definition: mm.h:212
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define _In_
Definition: no_sal2.h:158
PFN_NUMBER NTAPI MmGetPfnForProcess(struct _EPROCESS *Process, PVOID Address)
ULONG_PTR SWAPENTRY
Definition: mm.h:47
#define MM_SEGMENT_INDELETE
Definition: mm.h:208
unsigned int * PULONG
Definition: retypes.h:1
VOID NTAPI MmInsertRmap(PFN_NUMBER Page, PEPROCESS Process, PVOID Address)
Definition: rmap.c:352
#define NULL
Definition: types.h:112
#define __drv_freesMem(kind)
Definition: driverspecs.h:254
struct _MEMORY_AREA::@1775 SectionData
struct _MM_RMAP_ENTRY * Next
Definition: mm.h:235
#define DPRINT1
Definition: precomp.h:8
VOID NTAPI MmSetSavedSwapEntryPage(PFN_NUMBER Page, SWAPENTRY SavedSwapEntry)
Definition: freelist.c:483
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
void * _ReturnAddress(void)
unsigned int ULONG
Definition: retypes.h:1
Definition: mm.h:233
#define ULONG_PTR
Definition: config.h:101
NTSTATUS NTAPI MmWriteToSwapPage(SWAPENTRY SwapEntry, PFN_NUMBER Page)
Definition: pagefile.c:130
VOID NTAPI MmDereferenceSegment(PMM_SECTION_SEGMENT Segment)
Definition: section.c:991
static NPAGED_LOOKASIDE_LIST RmapLookasideList
Definition: rmap.c:21
PVOID Address
Definition: mm.h:237
#define STATUS_SUCCESS
Definition: shellext.h:65
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
NTSTATUS NTAPI MmPageOutPhysicalAddress(PFN_NUMBER Page)
Definition: rmap.c:51
struct _MEMORY_AREA * MemoryArea
Definition: newmm.h:47
FORCEINLINE VOID MmLockAddressSpace(PMMSUPPORT AddressSpace)
Definition: mm.h:1519
BOOLEAN NTAPI MmIsDirtyPage(struct _EPROCESS *Process, PVOID Address)
#define MmSystemRangeStart
Definition: mm.h:32
base of all file and directory entries
Definition: entries.h:82
VOID NTAPI MmFreeSwapPage(SWAPENTRY Entry)
Definition: pagefile.c:274
SWAPENTRY NTAPI MmGetSavedSwapEntryPage(PFN_NUMBER Page)
Definition: freelist.c:499