ReactOS  r74405
special.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
#include <mm/ARM3/miarm.h>
Include dependency graph for special.c:

Go to the source code of this file.

Classes

struct  _MI_FREED_SPECIAL_POOL
 

Macros

#define NDEBUG
 
#define MODULE_INVOLVED_IN_ARM3
 
#define SPECIAL_POOL_PAGED_PTE   0x2000
 
#define SPECIAL_POOL_NONPAGED_PTE   0x4000
 
#define SPECIAL_POOL_PAGED   0x8000
 

Typedefs

typedef struct
_MI_FREED_SPECIAL_POOL 
MI_FREED_SPECIAL_POOL
 
typedef struct
_MI_FREED_SPECIAL_POOL
PMI_FREED_SPECIAL_POOL
 

Functions

PMMPTE NTAPI MiReserveAlignedSystemPtes (IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType, IN ULONG Alignment)
 
VOID NTAPI MiTestSpecialPool (VOID)
 
BOOLEAN NTAPI MmUseSpecialPool (SIZE_T NumberOfBytes, ULONG Tag)
 
BOOLEAN NTAPI MmIsSpecialPoolAddress (PVOID P)
 
BOOLEAN NTAPI MmIsSpecialPoolAddressFree (PVOID P)
 
VOID NTAPI MiInitializeSpecialPool (VOID)
 
NTSTATUS NTAPI MmExpandSpecialPool (VOID)
 
PVOID NTAPI MmAllocateSpecialPool (SIZE_T NumberOfBytes, ULONG Tag, POOL_TYPE PoolType, ULONG SpecialType)
 
VOID NTAPI MiSpecialPoolCheckPattern (PUCHAR P, PPOOL_HEADER Header)
 
VOID NTAPI MmFreeSpecialPool (PVOID P)
 

Variables

ULONG ExpPoolFlags
 
PMMPTE MmSystemPteBase
 
PVOID MmSpecialPoolStart
 
PVOID MmSpecialPoolEnd
 
PVOID MiSpecialPoolExtra
 
ULONG MiSpecialPoolExtraCount
 
PMMPTE MiSpecialPoolFirstPte
 
PMMPTE MiSpecialPoolLastPte
 
PFN_COUNT MmSpecialPagesInUse
 
PFN_COUNT MmSpecialPagesInUsePeak
 
PFN_COUNT MiSpecialPagesPagable
 
PFN_COUNT MiSpecialPagesPagablePeak
 
PFN_COUNT MiSpecialPagesNonPaged
 
PFN_COUNT MiSpecialPagesNonPagedPeak
 
PFN_COUNT MiSpecialPagesNonPagedMaximum
 
BOOLEAN MmSpecialPoolCatchOverruns = TRUE
 

Macro Definition Documentation

#define MODULE_INVOLVED_IN_ARM3

Definition at line 20 of file special.c.

#define NDEBUG

Definition at line 17 of file special.c.

#define SPECIAL_POOL_NONPAGED_PTE   0x4000

Definition at line 35 of file special.c.

Referenced by MmAllocateSpecialPool(), MmFreeSpecialPool(), and MmIsSpecialPoolAddressFree().

#define SPECIAL_POOL_PAGED   0x8000

Definition at line 36 of file special.c.

Referenced by MiSpecialPoolCheckPattern(), MmAllocateSpecialPool(), and MmFreeSpecialPool().

#define SPECIAL_POOL_PAGED_PTE   0x2000

Definition at line 34 of file special.c.

Referenced by MmAllocateSpecialPool(), MmFreeSpecialPool(), and MmIsSpecialPoolAddressFree().

Typedef Documentation

Function Documentation

VOID NTAPI MiInitializeSpecialPool ( VOID  )

Definition at line 123 of file special.c.

Referenced by MiBuildPagedPool().

124 {
125  ULONG SpecialPoolPtes, i;
126  PMMPTE PointerPte;
127 
128  /* Check if there is a special pool tag */
129  if ((MmSpecialPoolTag == 0) ||
130  (MmSpecialPoolTag == -1)) return;
131 
132  /* Calculate number of system PTEs for the special pool */
133  if (MmNumberOfSystemPtes >= 0x3000)
134  SpecialPoolPtes = MmNumberOfSystemPtes / 3;
135  else
136  SpecialPoolPtes = MmNumberOfSystemPtes / 6;
137 
138  /* Don't let the number go too high */
139  if (SpecialPoolPtes > 0x6000) SpecialPoolPtes = 0x6000;
140 
141  /* Round up to the page size */
142  SpecialPoolPtes = PAGE_ROUND_UP(SpecialPoolPtes);
143 
144  ASSERT((SpecialPoolPtes & (PTE_PER_PAGE - 1)) == 0);
145 
146  /* Reserve those PTEs */
147  do
148  {
149  PointerPte = MiReserveAlignedSystemPtes(SpecialPoolPtes,
151  /*0x400000*/0); // FIXME:
152  if (PointerPte) break;
153 
154  /* Reserving didn't work, so try to reduce the requested size */
155  ASSERT(SpecialPoolPtes >= PTE_PER_PAGE);
156  SpecialPoolPtes -= PTE_PER_PAGE;
157  } while (SpecialPoolPtes);
158 
159  /* Fail if we couldn't reserve them at all */
160  if (!SpecialPoolPtes) return;
161 
162  /* Make sure we got enough */
163  ASSERT(SpecialPoolPtes >= PTE_PER_PAGE);
164 
165  /* Save first PTE and its address */
166  MiSpecialPoolFirstPte = PointerPte;
167  MmSpecialPoolStart = MiPteToAddress(PointerPte);
168 
169  for (i = 0; i < PTE_PER_PAGE / 2; i++)
170  {
171  /* Point it to the next entry */
172  PointerPte->u.List.NextEntry = &PointerPte[2] - MmSystemPteBase;
173 
174  /* Move to the next pair */
175  PointerPte += 2;
176  }
177 
178  /* Save extra values */
179  MiSpecialPoolExtra = PointerPte;
180  MiSpecialPoolExtraCount = SpecialPoolPtes - PTE_PER_PAGE;
181 
182  /* Mark the previous PTE as the last one */
183  MiSpecialPoolLastPte = PointerPte - 2;
185 
186  /* Save end address of the special pool */
188 
189  /* Calculate maximum non-paged part of the special pool */
191 
192  /* And limit it if it turned out to be too big */
193  if (MmNumberOfPhysicalPages > 0x3FFF)
195 
196  DPRINT1("Special pool start %p - end %p\n", MmSpecialPoolStart, MmSpecialPoolEnd);
198 
199  //MiTestSpecialPool();
200 }
PFN_NUMBER MmResidentAvailablePages
Definition: freelist.c:27
ULONG MiSpecialPoolExtraCount
Definition: special.c:41
ULONG64 NextEntry
Definition: mmtypes.h:145
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
#define MM_EMPTY_PTE_LIST
Definition: mm.h:77
#define POOL_FLAG_SPECIAL_POOL
Definition: miarm.h:260
ULONG MmNumberOfSystemPtes
Definition: init.c:42
union _MMPTE::@1890 u
#define PAGE_ROUND_UP(x)
Definition: scsiport_int.h:13
PMMPTE MiSpecialPoolLastPte
Definition: special.c:44
PVOID MmSpecialPoolEnd
Definition: special.c:39
GLenum GLclampf GLint i
Definition: glfuncs.h:14
ULONG MmSpecialPoolTag
Definition: pool.c:27
PVOID FORCEINLINE MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:185
PFN_COUNT MiSpecialPagesNonPagedMaximum
Definition: special.c:52
PVOID MiSpecialPoolExtra
Definition: special.c:40
MMPTE_LIST List
Definition: mmtypes.h:222
#define PTE_PER_PAGE
Definition: mm.h:18
PMMPTE NTAPI MiReserveAlignedSystemPtes(IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType, IN ULONG Alignment)
Definition: syspte.c:88
PFN_COUNT MmNumberOfPhysicalPages
Definition: init.c:48
PVOID MmSpecialPoolStart
Definition: special.c:38
PMMPTE MmSystemPteBase
Definition: syspte.c:21
#define DPRINT1
Definition: precomp.h:8
ULONG ExpPoolFlags
Definition: expool.c:47
unsigned int ULONG
Definition: retypes.h:1
PMMPTE MiSpecialPoolFirstPte
Definition: special.c:43
PMMPTE NTAPI MiReserveAlignedSystemPtes ( IN ULONG  NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE  SystemPtePoolType,
IN ULONG  Alignment 
)

Definition at line 88 of file syspte.c.

Referenced by MiInitializeSpecialPool(), and MiReserveSystemPtes().

91 {
92  KIRQL OldIrql;
93  PMMPTE PreviousPte, NextPte, ReturnPte;
95 
96  //
97  // Sanity check
98  //
100 
101  //
102  // Acquire the System PTE lock
103  //
105 
106  //
107  // Find the last cluster in the list that doesn't contain enough PTEs
108  //
109  PreviousPte = &MmFirstFreeSystemPte[SystemPtePoolType];
110 
111  while (PreviousPte->u.List.NextEntry != MM_EMPTY_PTE_LIST)
112  {
113  //
114  // Get the next cluster and its size
115  //
116  NextPte = MmSystemPteBase + PreviousPte->u.List.NextEntry;
117  ClusterSize = MI_GET_CLUSTER_SIZE(NextPte);
118 
119  //
120  // Check if this cluster contains enough PTEs
121  //
122  if (NumberOfPtes <= ClusterSize)
123  break;
124 
125  //
126  // On to the next cluster
127  //
128  PreviousPte = NextPte;
129  }
130 
131  //
132  // Make sure we didn't reach the end of the cluster list
133  //
134  if (PreviousPte->u.List.NextEntry == MM_EMPTY_PTE_LIST)
135  {
136  //
137  // Release the System PTE lock and return failure
138  //
140  return NULL;
141  }
142 
143  //
144  // Unlink the cluster
145  //
146  PreviousPte->u.List.NextEntry = NextPte->u.List.NextEntry;
147 
148  //
149  // Check if the reservation spans the whole cluster
150  //
151  if (ClusterSize == NumberOfPtes)
152  {
153  //
154  // Return the first PTE of this cluster
155  //
156  ReturnPte = NextPte;
157 
158  //
159  // Zero the cluster
160  //
161  if (NextPte->u.List.OneEntry == 0)
162  {
163  NextPte->u.Long = 0;
164  NextPte++;
165  }
166  NextPte->u.Long = 0;
167  }
168  else
169  {
170  //
171  // Divide the cluster into two parts
172  //
173  ClusterSize -= NumberOfPtes;
174  ReturnPte = NextPte + ClusterSize;
175 
176  //
177  // Set the size of the first cluster, zero the second if needed
178  //
179  if (ClusterSize == 1)
180  {
181  NextPte->u.List.OneEntry = 1;
182  ReturnPte->u.Long = 0;
183  }
184  else
185  {
186  NextPte++;
187  NextPte->u.List.NextEntry = ClusterSize;
188  }
189 
190  //
191  // Step through the cluster list to find out where to insert the first
192  //
193  PreviousPte = &MmFirstFreeSystemPte[SystemPtePoolType];
194 
195  while (PreviousPte->u.List.NextEntry != MM_EMPTY_PTE_LIST)
196  {
197  //
198  // Get the next cluster
199  //
200  NextPte = MmSystemPteBase + PreviousPte->u.List.NextEntry;
201 
202  //
203  // Check if the cluster to insert is smaller or of equal size
204  //
205  if (ClusterSize <= MI_GET_CLUSTER_SIZE(NextPte))
206  break;
207 
208  //
209  // On to the next cluster
210  //
211  PreviousPte = NextPte;
212  }
213 
214  //
215  // Retrieve the first cluster and link it back into the cluster list
216  //
217  NextPte = ReturnPte - ClusterSize;
218 
219  NextPte->u.List.NextEntry = PreviousPte->u.List.NextEntry;
220  PreviousPte->u.List.NextEntry = NextPte - MmSystemPteBase;
221  }
222 
223  //
224  // Decrease availability
225  //
226  MmTotalFreeSystemPtes[SystemPtePoolType] -= NumberOfPtes;
227 
228  //
229  // Release the System PTE lock
230  //
232 
233  //
234  // Flush the TLB
235  //
237 
238  //
239  // Return the reserved PTEs
240  //
241  return ReturnPte;
242 }
ULONG64 NextEntry
Definition: mmtypes.h:145
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
#define MM_EMPTY_PTE_LIST
Definition: mm.h:77
ULONG64 OneEntry
Definition: mmtypes.h:139
union _MMPTE::@1890 u
UCHAR KIRQL
Definition: env_spec_w32.h:591
MMPTE MmFirstFreeSystemPte[MaximumPtePoolTypes]
Definition: syspte.c:24
smooth NULL
Definition: ftsmooth.c:464
ULONG MmTotalFreeSystemPtes[MaximumPtePoolTypes]
Definition: syspte.c:25
MMPTE_LIST List
Definition: mmtypes.h:222
DWORD ClusterSize
Definition: format.c:67
FORCEINLINE ULONG MI_GET_CLUSTER_SIZE(IN PMMPTE Pte)
Definition: syspte.c:71
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
#define PAGE_SIZE
Definition: env_spec_w32.h:49
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
PMMPTE MmSystemPteBase
Definition: syspte.c:21
ULONG_PTR Long
Definition: mmtypes.h:215
FORCEINLINE VOID KeFlushProcessTb(VOID)
Definition: ke.h:185
unsigned int ULONG
Definition: retypes.h:1
VOID NTAPI MiSpecialPoolCheckPattern ( PUCHAR  P,
PPOOL_HEADER  Header 
)

Definition at line 409 of file special.c.

Referenced by MmFreeSpecialPool().

410 {
411  ULONG BytesToCheck, BytesRequested, Index;
412  PUCHAR Ptr;
413 
414  /* Get amount of bytes user requested to be allocated by clearing out the paged mask */
415  BytesRequested = (Header->Ulong1 & ~SPECIAL_POOL_PAGED) & 0xFFFF;
416  ASSERT(BytesRequested <= PAGE_SIZE - sizeof(POOL_HEADER));
417 
418  /* Get a pointer to the end of user's area */
419  Ptr = P + BytesRequested;
420 
421  /* Calculate how many bytes to check */
422  BytesToCheck = (ULONG)((PUCHAR)PAGE_ALIGN(P) + PAGE_SIZE - Ptr);
423 
424  /* Remove pool header size if we're catching underruns */
425  if (((ULONG_PTR)P & (PAGE_SIZE - 1)) == 0)
426  {
427  /* User buffer is located in the beginning of the page */
428  BytesToCheck -= sizeof(POOL_HEADER);
429  }
430 
431  /* Check the pattern after user buffer */
432  for (Index = 0; Index < BytesToCheck; Index++)
433  {
434  /* Bugcheck if bytes don't match */
435  if (Ptr[Index] != Header->BlockSize)
436  {
437  KeBugCheckEx(SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION,
438  (ULONG_PTR)P,
439  (ULONG_PTR)&Ptr[Index],
440  Header->BlockSize,
441  0x24);
442  }
443  }
444 }
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
unsigned char * PUCHAR
Definition: retypes.h:3
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
struct _POOL_HEADER POOL_HEADER
_Must_inspect_result_ _In_ ULONG Index
Definition: fltkernel.h:1824
uint32_t ULONG_PTR
Definition: typedefs.h:64
#define PAGE_ALIGN(Va)
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define SPECIAL_POOL_PAGED
Definition: special.c:36
unsigned int ULONG
Definition: retypes.h:1
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:90
#define P(a, b, c, d, e, x)
VOID NTAPI MiTestSpecialPool ( VOID  )

Definition at line 643 of file special.c.

644 {
645  ULONG i;
646  PVOID p1, p2[100];
647  //PUCHAR p3;
648  ULONG ByteSize;
650 
651  // First allocate/free
652  for (i=0; i<100; i++)
653  {
654  ByteSize = (100 * (i+1)) % (PAGE_SIZE - sizeof(POOL_HEADER));
655  p1 = MmAllocateSpecialPool(ByteSize, 'TEST', PoolType, 0);
656  DPRINT1("p1 %p size %lu\n", p1, ByteSize);
657  MmFreeSpecialPool(p1);
658  }
659 
660  // Now allocate all at once, then free at once
661  for (i=0; i<100; i++)
662  {
663  ByteSize = (100 * (i+1)) % (PAGE_SIZE - sizeof(POOL_HEADER));
664  p2[i] = MmAllocateSpecialPool(ByteSize, 'TEST', PoolType, 0);
665  DPRINT1("p2[%lu] %p size %lu\n", i, p1, ByteSize);
666  }
667  for (i=0; i<100; i++)
668  {
669  DPRINT1("Freeing %p\n", p2[i]);
670  MmFreeSpecialPool(p2[i]);
671  }
672 
673  // Overrun the buffer to test
674  //ByteSize = 16;
675  //p3 = MmAllocateSpecialPool(ByteSize, 'TEST', NonPagedPool, 0);
676  //p3[ByteSize] = 0xF1; // This should cause an exception
677 
678  // Underrun the buffer to test
679  //p3 = MmAllocateSpecialPool(ByteSize, 'TEST', NonPagedPool, 1);
680  //p3--;
681  //*p3 = 0xF1; // This should cause an exception
682 
683 }
DWORD *typedef PVOID
Definition: winlogon.h:52
PVOID NTAPI MmAllocateSpecialPool(SIZE_T NumberOfBytes, ULONG Tag, POOL_TYPE PoolType, ULONG SpecialType)
Definition: special.c:245
struct _POOL_HEADER POOL_HEADER
const GLfloat * p2
Definition: s_aatritemp.h:44
GLenum GLclampf GLint i
Definition: glfuncs.h:14
INT POOL_TYPE
Definition: typedefs.h:77
IN REFCLSID IN PUNKNOWN IN POOL_TYPE PoolType
Definition: unknown.h:68
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define DPRINT1
Definition: precomp.h:8
unsigned int ULONG
Definition: retypes.h:1
VOID NTAPI MmFreeSpecialPool(PVOID P)
Definition: special.c:448
const GLfloat * p1
Definition: s_aatritemp.h:43
_IRQL_requires_same_ _In_ CLONG ByteSize
Definition: rtltypes.h:389
PVOID NTAPI MmAllocateSpecialPool ( SIZE_T  NumberOfBytes,
ULONG  Tag,
POOL_TYPE  PoolType,
ULONG  SpecialType 
)

Definition at line 245 of file special.c.

Referenced by MiTestSpecialPool().

246 {
247  KIRQL Irql;
249  PMMPTE PointerPte;
250  PFN_NUMBER PageFrameNumber;
251  LARGE_INTEGER TickCount;
252  PVOID Entry;
254  PFN_COUNT PagesInUse;
255 
256  DPRINT("MmAllocateSpecialPool(%x %x %x %x)\n", NumberOfBytes, Tag, PoolType, SpecialType);
257 
258  /* Check if the pool is initialized and quit if it's not */
259  if (!MiSpecialPoolFirstPte) return NULL;
260 
261  /* Get the pool type */
263 
264  /* Check whether current IRQL matches the pool type */
265  Irql = KeGetCurrentIrql();
266 
267  if (((PoolType == PagedPool) && (Irql > APC_LEVEL)) ||
268  ((PoolType != PagedPool) && (Irql > DISPATCH_LEVEL)))
269  {
270  /* Bad caller */
271  KeBugCheckEx(SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION,
272  Irql,
273  PoolType,
275  0x30);
276  }
277 
278  /* Some allocations from Mm must never use special pool */
279  if (Tag == 'tSmM')
280  {
281  /* Reject and let normal pool handle it */
282  return NULL;
283  }
284 
285  /* TODO: Take into account various limitations */
286 
287  /* Heed the maximum limit of nonpaged pages */
288  if ((PoolType == NonPagedPool) &&
290  {
291  return NULL;
292  }
293 
294  /* Lock PFN database */
296 
297  /* Reject allocation in case amount of available pages is too small */
298  if (MmAvailablePages < 0x100)
299  {
300  /* Release the PFN database lock */
302  DPRINT1("Special pool: MmAvailablePages 0x%x is too small\n", MmAvailablePages);
303  return NULL;
304  }
305 
306  /* Check if special pool PTE list is exhausted */
308  {
309  /* Try to expand it */
311  {
312  /* No reserves left, reject this allocation */
313  static int once;
315  if (!once++) DPRINT1("Special pool: No PTEs left!\n");
316  return NULL;
317  }
319  }
320 
321  /* Save allocation time */
322  KeQueryTickCount(&TickCount);
323 
324  /* Get a pointer to the first PTE */
325  PointerPte = MiSpecialPoolFirstPte;
326 
327  /* Set the first PTE pointer to the next one in the list */
329 
330  /* Allocate a physical page */
331  PageFrameNumber = MiRemoveAnyPage(MI_GET_NEXT_COLOR());
332 
333  /* Initialize PFN and make it valid */
334  TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
335  MiInitializePfnAndMakePteValid(PageFrameNumber, PointerPte, TempPte);
336 
337  /* Release the PFN database lock */
339 
340  /* Increase page counter */
342  if (PagesInUse > MmSpecialPagesInUsePeak)
343  MmSpecialPagesInUsePeak = PagesInUse;
344 
345  /* Put some content into the page. Low value of tick count would do */
346  Entry = MiPteToAddress(PointerPte);
347  RtlFillMemory(Entry, PAGE_SIZE, TickCount.LowPart);
348 
349  /* Calculate header and entry addresses */
350  if ((SpecialType != 0) &&
351  ((SpecialType == 1) || (!MmSpecialPoolCatchOverruns)))
352  {
353  /* We catch underruns. Data is at the beginning of the page */
354  Header = (PPOOL_HEADER)((PUCHAR)Entry + PAGE_SIZE - sizeof(POOL_HEADER));
355  }
356  else
357  {
358  /* We catch overruns. Data is at the end of the page */
359  Header = (PPOOL_HEADER)Entry;
360  Entry = (PVOID)((ULONG_PTR)((PUCHAR)Entry - NumberOfBytes + PAGE_SIZE) & ~((LONG_PTR)sizeof(POOL_HEADER) - 1));
361  }
362 
363  /* Initialize the header */
364  RtlZeroMemory(Header, sizeof(POOL_HEADER));
365 
366  /* Save allocation size there */
367  Header->Ulong1 = (ULONG)NumberOfBytes;
368 
369  /* Make sure it's all good */
370  ASSERT((NumberOfBytes <= PAGE_SIZE - sizeof(POOL_HEADER)) &&
371  (PAGE_SIZE <= 32 * 1024));
372 
373  /* Mark it as paged or nonpaged */
374  if (PoolType == PagedPool)
375  {
376  /* Add pagedpool flag into the pool header too */
377  Header->Ulong1 |= SPECIAL_POOL_PAGED;
378 
379  /* Also mark the next PTE as special-pool-paged */
380  PointerPte[1].u.Soft.PageFileHigh |= SPECIAL_POOL_PAGED_PTE;
381 
382  /* Increase pagable counter */
384  if (PagesInUse > MiSpecialPagesPagablePeak)
385  MiSpecialPagesPagablePeak = PagesInUse;
386  }
387  else
388  {
389  /* Mark the next PTE as special-pool-nonpaged */
390  PointerPte[1].u.Soft.PageFileHigh |= SPECIAL_POOL_NONPAGED_PTE;
391 
392  /* Increase nonpaged counter */
394  if (PagesInUse > MiSpecialPagesNonPagedPeak)
395  MiSpecialPagesNonPagedPeak = PagesInUse;
396  }
397 
398  /* Finally save tag and put allocation time into the header's blocksize.
399  That time will be used to check memory consistency within the allocated
400  page. */
401  Header->PoolTag = Tag;
402  Header->BlockSize = (UCHAR)TickCount.LowPart;
403  DPRINT("%p\n", Entry);
404  return Entry;
405 }
DWORD *typedef PVOID
Definition: winlogon.h:52
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
ULONG64 NextEntry
Definition: mmtypes.h:145
struct _Entry Entry
Definition: kefuncs.h:640
ULONG PFN_COUNT
Definition: mmtypes.h:102
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
#define MM_EMPTY_PTE_LIST
Definition: mm.h:77
unsigned char * PUCHAR
Definition: retypes.h:3
#define MI_GET_NEXT_COLOR()
Definition: miarm.h:209
struct _POOL_HEADER POOL_HEADER
union _MMPTE::@1890 u
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
_Out_ PKIRQL Irql
Definition: csq.h:179
uint32_t ULONG_PTR
Definition: typedefs.h:64
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG PFN_NUMBER
Definition: ke.h:8
PFN_COUNT MiSpecialPagesNonPagedPeak
Definition: special.c:51
Definition: Header.h:8
PFN_COUNT MiSpecialPagesPagable
Definition: special.c:48
#define SPECIAL_POOL_PAGED_PTE
Definition: special.c:34
smooth NULL
Definition: ftsmooth.c:464
PVOID FORCEINLINE MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:185
void DPRINT(...)
Definition: polytest.cpp:61
#define BASE_POOL_TYPE_MASK
Definition: ExPools.c:15
struct _POOL_HEADER * PPOOL_HEADER
VOID NTAPI KeQueryTickCount(IN PLARGE_INTEGER TickCount)
Definition: clock.c:165
PFN_COUNT MiSpecialPagesNonPagedMaximum
Definition: special.c:52
MMPTE_LIST List
Definition: mmtypes.h:222
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
PFN_COUNT MiSpecialPagesNonPaged
Definition: special.c:50
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:75
MMPTE ValidKernelPte
Definition: init.c:31
unsigned char UCHAR
Definition: xmlstorage.h:181
IN REFCLSID IN PUNKNOWN IN POOL_TYPE PoolType
Definition: unknown.h:68
ULONG64 PageFileHigh
Definition: mmtypes.h:93
IN SIZE_T NumberOfBytes
Definition: ndis.h:3914
ULONG LowPart
Definition: typedefs.h:105
#define PAGE_SIZE
Definition: env_spec_w32.h:49
BOOLEAN MmSpecialPoolCatchOverruns
Definition: special.c:54
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
#define SPECIAL_POOL_PAGED
Definition: special.c:36
PFN_COUNT MmSpecialPagesInUse
Definition: special.c:46
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
PFN_NUMBER NTAPI MiRemoveAnyPage(IN ULONG Color)
Definition: pfnlist.c:475
NTSTATUS NTAPI MmExpandSpecialPool(VOID)
Definition: special.c:204
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define NT_SUCCESS(StatCode)
Definition: cmd.c:149
#define InterlockedIncrementUL(Addend)
Definition: ex.h:1455
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
PMMPTE MmSystemPteBase
Definition: syspte.c:21
#define DPRINT1
Definition: precomp.h:8
#define SPECIAL_POOL_NONPAGED_PTE
Definition: special.c:35
IN ULONG IN ULONG Tag
Definition: evtlib.h:153
PFN_COUNT MiSpecialPagesPagablePeak
Definition: special.c:49
VOID NTAPI MiInitializePfnAndMakePteValid(IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: pfnlist.c:1036
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
PFN_COUNT MmSpecialPagesInUsePeak
Definition: special.c:47
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:593
#define APC_LEVEL
Definition: env_spec_w32.h:695
PMMPTE MiSpecialPoolFirstPte
Definition: special.c:43
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:90
#define LONG_PTR
Definition: generated.c:23
NTSTATUS NTAPI MmExpandSpecialPool ( VOID  )

Definition at line 204 of file special.c.

Referenced by MmAllocateSpecialPool().

205 {
206  ULONG i;
207  PMMPTE PointerPte;
208 
210 
211  if (MiSpecialPoolExtraCount == 0)
213 
214  PointerPte = MiSpecialPoolExtra;
218 
220  for (i = 0; i < PTE_PER_PAGE / 2; i++)
221  {
222  /* Point it to the next entry */
223  PointerPte->u.List.NextEntry = &PointerPte[2] - MmSystemPteBase;
224 
225  /* Move to the next pair */
226  PointerPte += 2;
227  }
228 
229  /* Save remaining extra values */
230  MiSpecialPoolExtra = PointerPte;
232 
233  /* Mark the previous PTE as the last one */
234  MiSpecialPoolLastPte = PointerPte - 2;
236 
237  /* Save new end address of the special pool */
239 
240  return STATUS_SUCCESS;
241 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define STATUS_SUCCESS
Definition: contextmenu.cpp:55
ULONG MiSpecialPoolExtraCount
Definition: special.c:41
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
ULONG64 NextEntry
Definition: mmtypes.h:145
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
#define MM_EMPTY_PTE_LIST
Definition: mm.h:77
union _MMPTE::@1890 u
PMMPTE MiSpecialPoolLastPte
Definition: special.c:44
PVOID MmSpecialPoolEnd
Definition: special.c:39
GLenum GLclampf GLint i
Definition: glfuncs.h:14
PVOID FORCEINLINE MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:185
PVOID MiSpecialPoolExtra
Definition: special.c:40
MMPTE_LIST List
Definition: mmtypes.h:222
#define PTE_PER_PAGE
Definition: mm.h:18
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
PMMPTE MmSystemPteBase
Definition: syspte.c:21
unsigned int ULONG
Definition: retypes.h:1
PMMPTE MiSpecialPoolFirstPte
Definition: special.c:43
VOID NTAPI MmFreeSpecialPool ( PVOID  P)

Definition at line 448 of file special.c.

Referenced by MiTestSpecialPool().

449 {
450  PMMPTE PointerPte;
452  BOOLEAN Overruns = FALSE;
455  ULONG BytesRequested, BytesReal = 0;
457  PUCHAR b;
458  PMI_FREED_SPECIAL_POOL FreedHeader;
459  LARGE_INTEGER TickCount;
460  PMMPFN Pfn;
461 
462  DPRINT("MmFreeSpecialPool(%p)\n", P);
463 
464  /* Get the PTE */
465  PointerPte = MiAddressToPte(P);
466 
467  /* Check if it's valid */
468  if (PointerPte->u.Hard.Valid == 0)
469  {
470  /* Bugcheck if it has NOACCESS or 0 set as protection */
471  if (PointerPte->u.Soft.Protection == MM_NOACCESS ||
472  !PointerPte->u.Soft.Protection)
473  {
474  KeBugCheckEx(SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION,
475  (ULONG_PTR)P,
476  (ULONG_PTR)PointerPte,
477  0,
478  0x20);
479  }
480  }
481 
482  /* Determine if it's a underruns or overruns pool pointer */
483  PtrOffset = (ULONG)((ULONG_PTR)P & (PAGE_SIZE - 1));
484  if (PtrOffset)
485  {
486  /* Pool catches overruns */
487  Header = PAGE_ALIGN(P);
488  Overruns = TRUE;
489  }
490  else
491  {
492  /* Pool catches underruns */
493  Header = (PPOOL_HEADER)((PUCHAR)PAGE_ALIGN(P) + PAGE_SIZE - sizeof(POOL_HEADER));
494  }
495 
496  /* Check if it's non paged pool */
497  if ((Header->Ulong1 & SPECIAL_POOL_PAGED) == 0)
498  {
499  /* Non-paged allocation, ensure that IRQ is not higher that DISPATCH */
500  PoolType = NonPagedPool;
501  ASSERT(PointerPte[1].u.Soft.PageFileHigh == SPECIAL_POOL_NONPAGED_PTE);
502  if (Irql > DISPATCH_LEVEL)
503  {
504  KeBugCheckEx(SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION,
505  Irql,
506  PoolType,
507  (ULONG_PTR)P,
508  0x31);
509  }
510  }
511  else
512  {
513  /* Paged allocation, ensure */
514  PoolType = PagedPool;
515  ASSERT(PointerPte[1].u.Soft.PageFileHigh == SPECIAL_POOL_PAGED_PTE);
516  if (Irql > APC_LEVEL)
517  {
518  KeBugCheckEx(SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION,
519  Irql,
520  PoolType,
521  (ULONG_PTR)P,
522  0x31);
523  }
524  }
525 
526  /* Get amount of bytes user requested to be allocated by clearing out the paged mask */
527  BytesRequested = (Header->Ulong1 & ~SPECIAL_POOL_PAGED) & 0xFFFF;
528  ASSERT(BytesRequested <= PAGE_SIZE - sizeof(POOL_HEADER));
529 
530  /* Check memory before the allocated user buffer in case of overruns detection */
531  if (Overruns)
532  {
533  /* Calculate the real placement of the buffer */
534  BytesReal = PAGE_SIZE - PtrOffset;
535 
536  /* If they mismatch, it's unrecoverable */
537  if (BytesRequested > BytesReal)
538  {
539  KeBugCheckEx(SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION,
540  (ULONG_PTR)P,
541  BytesRequested,
542  BytesReal,
543  0x21);
544  }
545 
546  if (BytesRequested + sizeof(POOL_HEADER) < BytesReal)
547  {
548  KeBugCheckEx(SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION,
549  (ULONG_PTR)P,
550  BytesRequested,
551  BytesReal,
552  0x22);
553  }
554 
555  /* Actually check the memory pattern */
556  for (b = (PUCHAR)(Header + 1); b < (PUCHAR)P; b++)
557  {
558  if (*b != Header->BlockSize)
559  {
560  /* Bytes mismatch */
561  KeBugCheckEx(SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION,
562  (ULONG_PTR)P,
563  (ULONG_PTR)b,
564  Header->BlockSize,
565  0x23);
566  }
567  }
568  }
569 
570  /* Check the memory pattern after the user buffer */
571  MiSpecialPoolCheckPattern(P, Header);
572 
573  /* Fill the freed header */
574  KeQueryTickCount(&TickCount);
575  FreedHeader = (PMI_FREED_SPECIAL_POOL)PAGE_ALIGN(P);
576  FreedHeader->Signature = 0x98764321;
577  FreedHeader->TickCount = TickCount.LowPart;
578  FreedHeader->NumberOfBytesRequested = BytesRequested;
579  FreedHeader->Pagable = PoolType;
580  FreedHeader->VirtualAddress = P;
581  FreedHeader->Thread = PsGetCurrentThread();
582  /* TODO: Fill StackPointer and StackBytes */
583  FreedHeader->StackPointer = NULL;
584  FreedHeader->StackBytes = 0;
585 
586  if (PoolType == NonPagedPool)
587  {
588  /* Non pagable. Get PFN element corresponding to the PTE */
589  Pfn = MI_PFN_ELEMENT(PointerPte->u.Hard.PageFrameNumber);
590 
591  /* Count the page as free */
593 
594  /* Lock PFN database */
596 
597  /* Delete this PFN */
598  MI_SET_PFN_DELETED(Pfn);
599 
600  /* Decrement share count of this PFN */
601  MiDecrementShareCount(Pfn, PointerPte->u.Hard.PageFrameNumber);
602 
603  MI_ERASE_PTE(PointerPte);
604 
605  /* Flush the TLB */
606  //FIXME: Use KeFlushSingleTb() instead
608  }
609  else
610  {
611  /* Pagable. Delete that virtual address */
612  MiDeleteSystemPageableVm(PointerPte, 1, 0, NULL);
613 
614  /* Count the page as free */
616 
617  /* Lock PFN database */
619  }
620 
621  /* Mark next PTE as invalid */
622  MI_ERASE_PTE(PointerPte + 1);
623 
624  /* Make sure that the last entry is really the last one */
626 
627  /* Update the current last PTE next pointer */
629 
630  /* PointerPte becomes the new last PTE */
631  PointerPte->u.List.NextEntry = MM_EMPTY_PTE_LIST;
632  MiSpecialPoolLastPte = PointerPte;
633 
634  /* Release the PFN database lock */
636 
637  /* Update page counter */
639 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
FORCEINLINE VOID MI_ERASE_PTE(IN PMMPTE PointerPte)
Definition: miarm.h:957
ULONG64 NextEntry
Definition: mmtypes.h:145
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define PtrOffset(BASE, OFFSET)
Definition: cdprocs.h:1344
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
#define MM_EMPTY_PTE_LIST
Definition: mm.h:77
unsigned char * PUCHAR
Definition: retypes.h:3
#define TRUE
Definition: numbers.c:17
#define MM_NOACCESS
Definition: miarm.h:67
struct _POOL_HEADER POOL_HEADER
GLenum GLclampf GLint GLenum GLuint GLenum GLenum GLsizei GLenum const GLvoid GLfloat GLfloat GLfloat GLfloat GLclampd GLint GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean GLboolean GLboolean GLboolean GLint GLenum GLsizei const GLvoid GLenum GLint GLenum GLint GLint GLsizei GLint GLenum GLint GLint GLint GLint GLsizei GLenum GLsizei const GLuint GLboolean GLenum GLenum GLint GLsizei GLenum GLsizei GLenum const GLvoid GLboolean const GLboolean GLenum const GLdouble * u
Definition: glfuncs.h:88
union _MMPTE::@1890 u
_Out_ PKIRQL Irql
Definition: csq.h:179
uint32_t ULONG_PTR
Definition: typedefs.h:64
PMMPTE MiSpecialPoolLastPte
Definition: special.c:44
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define MiAddressToPte(x)
Definition: mmx86.c:19
Definition: Header.h:8
PFN_COUNT MiSpecialPagesPagable
Definition: special.c:48
#define SPECIAL_POOL_PAGED_PTE
Definition: special.c:34
smooth NULL
Definition: ftsmooth.c:464
void DPRINT(...)
Definition: polytest.cpp:61
VOID NTAPI MiDecrementShareCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1133
ULONG64 Protection
Definition: mmtypes.h:88
struct _POOL_HEADER * PPOOL_HEADER
ULONG NumberOfBytesRequested
Definition: special.c:62
VOID NTAPI KeQueryTickCount(IN PLARGE_INTEGER TickCount)
Definition: clock.c:165
VOID NTAPI KeFlushEntireTb(IN BOOLEAN Invalid, IN BOOLEAN AllProcessors)
Definition: cpu.c:423
#define b
Definition: ke_i.h:79
unsigned char BOOLEAN
MMPTE_LIST List
Definition: mmtypes.h:222
INT POOL_TYPE
Definition: typedefs.h:77
ULONG64 Valid
Definition: mmtypes.h:150
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
#define PAGE_ALIGN(Va)
PFN_COUNT MiSpecialPagesNonPaged
Definition: special.c:50
FORCEINLINE PMMPFN MI_PFN_ELEMENT(IN PFN_NUMBER Pfn)
Definition: miarm.h:1391
IN REFCLSID IN PUNKNOWN IN POOL_TYPE PoolType
Definition: unknown.h:68
Definition: mm.h:305
#define InterlockedDecrementUL(Addend)
Definition: ex.h:1452
ULONG LowPart
Definition: typedefs.h:105
#define PAGE_SIZE
Definition: env_spec_w32.h:49
VOID NTAPI MiSpecialPoolCheckPattern(PUCHAR P, PPOOL_HEADER Header)
Definition: special.c:409
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
#define SPECIAL_POOL_PAGED
Definition: special.c:36
PFN_COUNT MmSpecialPagesInUse
Definition: special.c:46
PFN_COUNT NTAPI MiDeleteSystemPageableVm(IN PMMPTE PointerPte, IN PFN_NUMBER PageCount, IN ULONG Flags, OUT PPFN_NUMBER ValidPages)
Definition: virtual.c:297
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define MI_SET_PFN_DELETED(x)
Definition: miarm.h:161
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
PMMPTE MmSystemPteBase
Definition: syspte.c:21
#define SPECIAL_POOL_NONPAGED_PTE
Definition: special.c:35
struct _MI_FREED_SPECIAL_POOL * PMI_FREED_SPECIAL_POOL
#define FALSE
Definition: numbers.c:16
unsigned int ULONG
Definition: retypes.h:1
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
#define APC_LEVEL
Definition: env_spec_w32.h:695
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:90
#define P(a, b, c, d, e, x)
BOOLEAN NTAPI MmIsSpecialPoolAddress ( PVOID  P)

Definition at line 95 of file special.c.

Referenced by MmIsSpecialPoolAddressFree().

96 {
97  return ((P >= MmSpecialPoolStart) &&
98  (P <= MmSpecialPoolEnd));
99 }
PVOID MmSpecialPoolEnd
Definition: special.c:39
PVOID MmSpecialPoolStart
Definition: special.c:38
#define P(a, b, c, d, e, x)
BOOLEAN NTAPI MmIsSpecialPoolAddressFree ( PVOID  P)

Definition at line 103 of file special.c.

104 {
105  PMMPTE PointerPte;
106 
108  PointerPte = MiAddressToPte(P);
109 
110  if (PointerPte->u.Soft.PageFileHigh == SPECIAL_POOL_PAGED_PTE ||
112  {
113  /* Guard page PTE */
114  return FALSE;
115  }
116 
117  /* Free PTE */
118  return TRUE;
119 }
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
#define TRUE
Definition: numbers.c:17
union _MMPTE::@1890 u
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define SPECIAL_POOL_PAGED_PTE
Definition: special.c:34
ULONG64 PageFileHigh
Definition: mmtypes.h:93
BOOLEAN NTAPI MmIsSpecialPoolAddress(PVOID P)
Definition: special.c:95
MMPTE_SOFTWARE Soft
Definition: mmtypes.h:219
#define SPECIAL_POOL_NONPAGED_PTE
Definition: special.c:35
#define FALSE
Definition: numbers.c:16
#define P(a, b, c, d, e, x)
BOOLEAN NTAPI MmUseSpecialPool ( SIZE_T  NumberOfBytes,
ULONG  Tag 
)

Definition at line 77 of file special.c.

78 {
79  /* Special pool is not suitable for allocations bigger than 1 page */
80  if (NumberOfBytes > (PAGE_SIZE - sizeof(POOL_HEADER)))
81  {
82  return FALSE;
83  }
84 
85  if (MmSpecialPoolTag == '*')
86  {
87  return TRUE;
88  }
89 
90  return Tag == MmSpecialPoolTag;
91 }
#define TRUE
Definition: numbers.c:17
ULONG MmSpecialPoolTag
Definition: pool.c:27
IN SIZE_T NumberOfBytes
Definition: ndis.h:3914
#define PAGE_SIZE
Definition: env_spec_w32.h:49
IN ULONG IN ULONG Tag
Definition: evtlib.h:153
#define FALSE
Definition: numbers.c:16

Variable Documentation

PFN_COUNT MiSpecialPagesNonPaged

Definition at line 50 of file special.c.

Referenced by MmAllocateSpecialPool(), and MmFreeSpecialPool().

PFN_COUNT MiSpecialPagesNonPagedMaximum

Definition at line 52 of file special.c.

Referenced by MiInitializeSpecialPool(), and MmAllocateSpecialPool().

PFN_COUNT MiSpecialPagesNonPagedPeak

Definition at line 51 of file special.c.

Referenced by MmAllocateSpecialPool().

PFN_COUNT MiSpecialPagesPagable

Definition at line 48 of file special.c.

Referenced by MmAllocateSpecialPool(), and MmFreeSpecialPool().

PFN_COUNT MiSpecialPagesPagablePeak

Definition at line 49 of file special.c.

Referenced by MmAllocateSpecialPool().

PVOID MiSpecialPoolExtra

Definition at line 40 of file special.c.

Referenced by MiInitializeSpecialPool(), and MmExpandSpecialPool().

ULONG MiSpecialPoolExtraCount

Definition at line 41 of file special.c.

Referenced by MiInitializeSpecialPool(), and MmExpandSpecialPool().

PMMPTE MiSpecialPoolFirstPte

Definition at line 43 of file special.c.

Referenced by MmAllocateSpecialPool().

PMMPTE MiSpecialPoolLastPte

Definition at line 44 of file special.c.

PFN_COUNT MmSpecialPagesInUse

Definition at line 46 of file special.c.

Referenced by MmAllocateSpecialPool(), and MmFreeSpecialPool().

PFN_COUNT MmSpecialPagesInUsePeak

Definition at line 47 of file special.c.

Referenced by MmAllocateSpecialPool().

BOOLEAN MmSpecialPoolCatchOverruns = TRUE

Definition at line 54 of file special.c.

Referenced by MmAllocateSpecialPool().

PVOID MmSpecialPoolEnd

Definition at line 39 of file special.c.

Referenced by MiInitializeSpecialPool(), MmExpandSpecialPool(), and MmIsSpecialPoolAddress().

PVOID MmSpecialPoolStart

Definition at line 38 of file special.c.

Referenced by MiInitializeSpecialPool(), and MmIsSpecialPoolAddress().