880 lines
23 KiB
C
880 lines
23 KiB
C
/*++
|
||
|
||
Copyright (c) 1989 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
dmpaddr.c
|
||
|
||
Abstract:
|
||
|
||
Temporary routine to print valid addresses within an
|
||
address space.
|
||
|
||
Author:
|
||
|
||
Lou Perazzoli (loup) 20-Mar-1989
|
||
|
||
Environment:
|
||
|
||
Kernel Mode.
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "mi.h"
|
||
|
||
#if DBG
|
||
|
||
BOOLEAN
|
||
MiFlushUnusedSectionInternal (
|
||
IN PCONTROL_AREA ControlArea
|
||
);
|
||
|
||
#endif //DBG
|
||
|
||
#if DBG
|
||
VOID
|
||
MiDumpValidAddresses (
|
||
)
|
||
|
||
{
|
||
ULONG va = 0;
|
||
ULONG i,j;
|
||
PMMPTE PointerPde;
|
||
PMMPTE PointerPte;
|
||
|
||
PointerPde = MiGetPdeAddress (va);
|
||
|
||
|
||
for (i = 0; i < PDE_PER_PAGE; i++) {
|
||
if (PointerPde->u.Hard.Valid) {
|
||
DbgPrint(" **valid PDE, element %ld %lx %lx\n",i,i,
|
||
PointerPde->u.Long);
|
||
PointerPte = MiGetPteAddress (va);
|
||
for (j = 0 ; j < PTE_PER_PAGE; j++) {
|
||
if (PointerPte->u.Hard.Valid) {
|
||
DbgPrint("Valid address at %lx pte %lx\n", (ULONG)va,
|
||
PointerPte->u.Long);
|
||
}
|
||
va += PAGE_SIZE;
|
||
PointerPte++;
|
||
}
|
||
} else {
|
||
va += (ULONG)PDE_PER_PAGE * (ULONG)PAGE_SIZE;
|
||
}
|
||
|
||
PointerPde++;
|
||
}
|
||
|
||
return;
|
||
|
||
}
|
||
|
||
#endif //DBG
|
||
|
||
#if DBG
|
||
VOID
|
||
MiFormatPte (
|
||
IN PMMPTE PointerPte
|
||
)
|
||
|
||
{
|
||
// int j;
|
||
// unsigned long pte;
|
||
PMMPTE proto_pte;
|
||
PSUBSECTION subsect;
|
||
|
||
// struct a_bit {
|
||
// unsigned long biggies : 31;
|
||
// unsigned long bitties : 1;
|
||
// };
|
||
//
|
||
// struct a_bit print_pte;
|
||
|
||
|
||
proto_pte = MiPteToProto(PointerPte);
|
||
subsect = MiGetSubsectionAddress(PointerPte);
|
||
|
||
DbgPrint("***DumpPTE at %lx contains %lx protoaddr %lx subsect %lx\n\n",
|
||
(ULONG)PointerPte, PointerPte->u.Long, (ULONG)proto_pte,
|
||
(ULONG)subsect);
|
||
|
||
return;
|
||
|
||
// DbgPrint("page frame number 0x%lx proto PTE address 0x%lx\n",
|
||
//
|
||
// DbgPrint("PTE is 0x%lx\n", PTETOULONG(the_pte));
|
||
//
|
||
// proto_pte = MiPteToProto(PointerPte);
|
||
//
|
||
// DbgPrint("page frame number 0x%lx proto PTE address 0x%lx\n",
|
||
// PointerPte->u.Hard.PageFrameNumber,*(PULONG)&proto_pte);
|
||
//
|
||
// DbgPrint(" 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 \n");
|
||
// DbgPrint(" +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ \n");
|
||
// DbgPrint(" | pfn |c|p|t|r|r|d|a|c|p|o|w|v| \n");
|
||
// DbgPrint(" | |o|r|r|s|s|t|c|a|b|w|r|l| \n");
|
||
// DbgPrint(" | |w|o|n|v|v|y|c|c|o|n|t|d| \n");
|
||
// DbgPrint(" +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ \n ");
|
||
// pte = PTETOULONG(the_pte);
|
||
//
|
||
// for (j = 0; j < 32; j++) {
|
||
// *(PULONG)& print_pte = pte;
|
||
// DbgPrint(" %lx",print_pte.bitties);
|
||
// pte = pte << 1;
|
||
// }
|
||
// DbgPrint("\n");
|
||
//
|
||
|
||
}
|
||
#endif //DBG
|
||
|
||
#if DBG
|
||
|
||
VOID
|
||
MiDumpWsl ( )
|
||
|
||
{
|
||
ULONG i;
|
||
PMMWSLE wsle;
|
||
|
||
DbgPrint("***WSLE cursize %lx frstfree %lx Min %lx Max %lx\n",
|
||
PsGetCurrentProcess()->Vm.WorkingSetSize,
|
||
MmWorkingSetList->FirstFree,
|
||
PsGetCurrentProcess()->Vm.MinimumWorkingSetSize,
|
||
PsGetCurrentProcess()->Vm.MaximumWorkingSetSize);
|
||
|
||
DbgPrint(" quota %lx firstdyn %lx last ent %lx next slot %lx\n",
|
||
MmWorkingSetList->Quota,
|
||
MmWorkingSetList->FirstDynamic,
|
||
MmWorkingSetList->LastEntry,
|
||
MmWorkingSetList->NextSlot);
|
||
|
||
wsle = MmWsle;
|
||
|
||
for (i = 0; i < MmWorkingSetList->LastEntry; i++) {
|
||
DbgPrint(" index %lx %lx\n",i,wsle->u1.Long);
|
||
wsle++;
|
||
}
|
||
return;
|
||
|
||
}
|
||
|
||
#endif //DBG
|
||
|
||
#if 0 //COMMENTED OUT!!!
|
||
VOID
|
||
MiFlushUnusedSections (
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine rumages through the PFN database and attempts
|
||
to close any unused sections.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
PMMPFN LastPfn;
|
||
PMMPFN Pfn1;
|
||
PSUBSECTION Subsection;
|
||
KIRQL OldIrql;
|
||
|
||
LOCK_PFN (OldIrql);
|
||
Pfn1 = MI_PFN_ELEMENT (MmLowestPhysicalPage + 1);
|
||
LastPfn = MI_PFN_ELEMENT(MmHighestPhysicalPage);
|
||
|
||
while (Pfn1 < LastPfn) {
|
||
if (Pfn1->OriginalPte.u.Soft.Prototype == 1) {
|
||
if ((Pfn1->u3.e1.PageLocation == ModifiedPageList) ||
|
||
(Pfn1->u3.e1.PageLocation == StandbyPageList)) {
|
||
|
||
//
|
||
// Make sure the PTE is not waiting for I/O to complete.
|
||
//
|
||
|
||
if (MI_IS_PFN_DELETED (Pfn1)) {
|
||
|
||
Subsection = MiGetSubsectionAddress (&Pfn1->OriginalPte);
|
||
MiFlushUnusedSectionInternal (Subsection->ControlArea);
|
||
}
|
||
}
|
||
}
|
||
Pfn1++;
|
||
}
|
||
|
||
UNLOCK_PFN (OldIrql);
|
||
return;
|
||
}
|
||
|
||
BOOLEAN
|
||
MiFlushUnusedSectionInternal (
|
||
IN PCONTROL_AREA ControlArea
|
||
)
|
||
|
||
{
|
||
BOOLEAN result;
|
||
KIRQL OldIrql = APC_LEVEL;
|
||
|
||
if ((ControlArea->NumberOfMappedViews != 0) ||
|
||
(ControlArea->NumberOfSectionReferences != 0)) {
|
||
|
||
//
|
||
// The segment is currently in use.
|
||
//
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// The segment has no references, delete it. If the segment
|
||
// is already being deleted, set the event field in the control
|
||
// area and wait on the event.
|
||
//
|
||
|
||
if ((ControlArea->u.Flags.BeingDeleted) ||
|
||
(ControlArea->u.Flags.BeingCreated)) {
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
//
|
||
// Set the being deleted flag and up the number of mapped views
|
||
// for the segment. Upping the number of mapped views prevents
|
||
// the segment from being deleted and passed to the deletion thread
|
||
// while we are forcing a delete.
|
||
//
|
||
|
||
ControlArea->u.Flags.BeingDeleted = 1;
|
||
ControlArea->NumberOfMappedViews = 1;
|
||
|
||
//
|
||
// This is a page file backed or image Segment. The Segment is being
|
||
// deleted, remove all references to the paging file and physical memory.
|
||
//
|
||
|
||
UNLOCK_PFN (OldIrql);
|
||
|
||
MiCleanSection (ControlArea);
|
||
|
||
LOCK_PFN (OldIrql);
|
||
return TRUE;
|
||
}
|
||
#endif //0
|
||
|
||
|
||
#if DBG
|
||
|
||
#define ALLOC_SIZE ((ULONG)8*1024)
|
||
#define MM_SAVED_CONTROL 64
|
||
#define MM_KERN_MAP_SIZE 64
|
||
|
||
#define MM_NONPAGED_POOL_MARK ((PUCHAR)0xfffff123)
|
||
#define MM_PAGED_POOL_MARK ((PUCHAR)0xfffff124)
|
||
#define MM_KERNEL_STACK_MARK ((PUCHAR)0xfffff125)
|
||
|
||
extern ULONG MmSystemPtesStart[MaximumPtePoolTypes];
|
||
extern ULONG MmSystemPtesEnd[MaximumPtePoolTypes];
|
||
|
||
typedef struct _KERN_MAP {
|
||
ULONG StartVa;
|
||
ULONG EndVa;
|
||
PLDR_DATA_TABLE_ENTRY Entry;
|
||
} KERN_MAP, *PKERN_MAP;
|
||
|
||
ULONG
|
||
MiBuildKernelMap (
|
||
IN ULONG NumberOfElements,
|
||
IN OUT PKERN_MAP KernelMap
|
||
);
|
||
|
||
NTSTATUS
|
||
MmMemoryUsage (
|
||
IN PVOID Buffer,
|
||
IN ULONG Size,
|
||
IN ULONG Type,
|
||
OUT PULONG OutLength
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine (debugging only) dumps the current memory usage by
|
||
walking the PFN database.
|
||
|
||
Arguments:
|
||
|
||
Buffer - Supplies a buffer in which to copy the data.
|
||
|
||
Size - Supplies the size of the buffer.
|
||
|
||
Type - Supplies a value of 0 to dump everything,
|
||
a value of 1 to dump only valid pages.
|
||
|
||
OutLength - Returns how much data was written into the buffer.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
PMMPFN LastPfn;
|
||
PMMPFN Pfn1;
|
||
PMMPFN Pfn2;
|
||
PSUBSECTION Subsection;
|
||
KIRQL OldIrql;
|
||
PSYSTEM_MEMORY_INFORMATION MemInfo;
|
||
PSYSTEM_MEMORY_INFO Info;
|
||
PSYSTEM_MEMORY_INFO InfoStart;
|
||
PSYSTEM_MEMORY_INFO InfoEnd;
|
||
PUCHAR String;
|
||
PUCHAR Master;
|
||
PCONTROL_AREA ControlArea;
|
||
BOOLEAN Found;
|
||
BOOLEAN FoundMap;
|
||
PMDL Mdl;
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
ULONG Length;
|
||
PEPROCESS Process;
|
||
PUCHAR End;
|
||
PCONTROL_AREA SavedControl[MM_SAVED_CONTROL];
|
||
PSYSTEM_MEMORY_INFO SavedInfo[MM_SAVED_CONTROL];
|
||
ULONG j;
|
||
ULONG ControlCount = 0;
|
||
PUCHAR PagedSection = NULL;
|
||
ULONG Failed;
|
||
UCHAR PageFileMapped[] = "PageFile Mapped";
|
||
UCHAR MetaFile[] = "Fs Meta File";
|
||
UCHAR NoName[] = "No File Name";
|
||
UCHAR NonPagedPool[] = "NonPagedPool";
|
||
UCHAR PagedPool[] = "PagedPool";
|
||
UCHAR KernelStack[] = "Kernel Stack";
|
||
PUCHAR NameString;
|
||
KERN_MAP KernMap[MM_KERN_MAP_SIZE];
|
||
ULONG KernSize;
|
||
ULONG VirtualAddress;
|
||
PLDR_DATA_TABLE_ENTRY DataTableEntry;
|
||
|
||
Mdl = MmCreateMdl (NULL, Buffer, Size);
|
||
try {
|
||
|
||
MmProbeAndLockPages (Mdl, KeGetPreviousMode(), IoWriteAccess);
|
||
|
||
} except (EXCEPTION_EXECUTE_HANDLER) {
|
||
|
||
ExFreePool (Mdl);
|
||
return GetExceptionCode();
|
||
}
|
||
|
||
MemInfo = MmGetSystemAddressForMdl (Mdl);
|
||
InfoStart = &MemInfo->Memory[0];
|
||
InfoEnd = InfoStart;
|
||
End = (PUCHAR)MemInfo + Size;
|
||
|
||
Pfn1 = MI_PFN_ELEMENT (MmLowestPhysicalPage + 1);
|
||
LastPfn = MI_PFN_ELEMENT(MmHighestPhysicalPage);
|
||
|
||
KernSize = MiBuildKernelMap (MM_KERN_MAP_SIZE, &KernMap[0]);
|
||
|
||
LOCK_PFN (OldIrql);
|
||
|
||
while (Pfn1 < LastPfn) {
|
||
|
||
Info = InfoStart;
|
||
FoundMap = FALSE;
|
||
|
||
if ((Pfn1->u3.e1.PageLocation != FreePageList) &&
|
||
(Pfn1->u3.e1.PageLocation != ZeroedPageList) &&
|
||
(Pfn1->u3.e1.PageLocation != BadPageList)) {
|
||
|
||
if (Type == 1) {
|
||
if (Pfn1->u3.e1.PageLocation != ActiveAndValid) {
|
||
Pfn1++;
|
||
continue;
|
||
}
|
||
}
|
||
if (Pfn1->OriginalPte.u.Soft.Prototype == 1) {
|
||
Subsection = MiGetSubsectionAddress (&Pfn1->OriginalPte);
|
||
Master = (PUCHAR)Subsection->ControlArea;
|
||
ControlArea = Subsection->ControlArea;
|
||
if (!MmIsAddressValid(ControlArea)) {
|
||
DbgPrint ("Pfnp %lx not found %lx\n",Pfn1 - MmPfnDatabase,
|
||
(ULONG)Pfn1->PteAddress);
|
||
Pfn1++;
|
||
continue;
|
||
}
|
||
if (ControlArea->FilePointer != NULL) {
|
||
if (!MmIsAddressValid(ControlArea->FilePointer)) {
|
||
Pfn1++;
|
||
continue;
|
||
}
|
||
}
|
||
|
||
} else {
|
||
|
||
FoundMap = TRUE;
|
||
VirtualAddress = (ULONG)MiGetVirtualAddressMappedByPte (Pfn1->PteAddress);
|
||
|
||
if ((VirtualAddress >= (ULONG)MmPagedPoolStart) &&
|
||
(VirtualAddress <= (ULONG)MmPagedPoolEnd)) {
|
||
|
||
//
|
||
// This is paged pool, put it in the paged pool cell.
|
||
//
|
||
|
||
Master = MM_PAGED_POOL_MARK;
|
||
|
||
} else if ((VirtualAddress >= (ULONG)MmNonPagedPoolStart) &&
|
||
(VirtualAddress <= (ULONG)MmNonPagedPoolEnd)) {
|
||
|
||
//
|
||
// This is nonpaged pool, put it in the nonpaged pool cell.
|
||
//
|
||
|
||
Master = MM_NONPAGED_POOL_MARK;
|
||
|
||
} else {
|
||
FoundMap = FALSE;
|
||
for (j=0; j < KernSize; j++) {
|
||
if ((VirtualAddress >= KernMap[j].StartVa) &&
|
||
(VirtualAddress < KernMap[j].EndVa)) {
|
||
Master = (PUCHAR)&KernMap[j];
|
||
FoundMap = TRUE;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!FoundMap) {
|
||
if (((ULONG)Pfn1->PteAddress >= MmSystemPtesStart[SystemPteSpace]) &&
|
||
((ULONG)Pfn1->PteAddress <= MmSystemPtesEnd[SystemPteSpace])) {
|
||
|
||
//
|
||
// This is kernel stack.
|
||
//
|
||
|
||
Master = MM_KERNEL_STACK_MARK;
|
||
} else {
|
||
Pfn2 = MI_PFN_ELEMENT (Pfn1->PteFrame);
|
||
Master = (PUCHAR)Pfn2->PteFrame;
|
||
if (((ULONG)Master == 0) || ((ULONG)Master > MmHighestPhysicalPage)) {
|
||
DbgPrint ("Pfn %lx not found %lx\n",Pfn1 - MmPfnDatabase,
|
||
(ULONG)Pfn1->PteAddress);
|
||
Pfn1++;
|
||
continue;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// See if there is already a master info block.
|
||
//
|
||
|
||
Found = FALSE;
|
||
while (Info < InfoEnd) {
|
||
if (Info->StringOffset == Master) {
|
||
Found = TRUE;
|
||
break;
|
||
}
|
||
Info += 1;
|
||
}
|
||
|
||
if (!Found) {
|
||
|
||
Info = InfoEnd;
|
||
InfoEnd += 1;
|
||
if ((PUCHAR)Info >= ((PUCHAR)InfoStart + Size) - sizeof(SYSTEM_MEMORY_INFO)) {
|
||
status = STATUS_DATA_OVERRUN;
|
||
goto Done;
|
||
}
|
||
|
||
RtlZeroMemory (Info, sizeof(*Info));
|
||
Info->StringOffset = Master;
|
||
}
|
||
|
||
if ((Pfn1->u3.e1.PageLocation == StandbyPageList) ||
|
||
(Pfn1->u3.e1.PageLocation == TransitionPage)) {
|
||
|
||
Info->TransitionCount += 1;
|
||
|
||
} else if ((Pfn1->u3.e1.PageLocation == ModifiedPageList) ||
|
||
(Pfn1->u3.e1.PageLocation == ModifiedNoWritePageList)) {
|
||
Info->ModifiedCount += 1;
|
||
|
||
} else {
|
||
Info->ValidCount += 1;
|
||
if (Type == 1) {
|
||
if ((Pfn1->PteAddress >= MiGetPdeAddress (0x0)) &&
|
||
(Pfn1->PteAddress <= MiGetPdeAddress (0xFFFFFFFF))) {
|
||
Info->PageTableCount += 1;
|
||
}
|
||
}
|
||
}
|
||
if (Type != 1) {
|
||
if ((Pfn1->PteAddress >= MiGetPdeAddress (0x0)) &&
|
||
(Pfn1->PteAddress <= MiGetPdeAddress (0xFFFFFFFF))) {
|
||
Info->PageTableCount += 1;
|
||
}
|
||
}
|
||
}
|
||
Pfn1++;
|
||
}
|
||
|
||
MemInfo->StringStart = (ULONG)Buffer + (PUCHAR)InfoEnd - (PUCHAR)MemInfo;
|
||
String = (PUCHAR)InfoEnd;
|
||
|
||
//
|
||
// Process strings...
|
||
//
|
||
|
||
Info = InfoStart;
|
||
while (Info < InfoEnd) {
|
||
if (Info->StringOffset > (PUCHAR)0x80000000) {
|
||
|
||
//
|
||
// Make sure this is not stacks or other areas.
|
||
//
|
||
|
||
Length = 0;
|
||
ControlArea = NULL;
|
||
|
||
if (Info->StringOffset == MM_NONPAGED_POOL_MARK) {
|
||
Length = 14;
|
||
NameString = NonPagedPool;
|
||
} else if (Info->StringOffset == MM_PAGED_POOL_MARK) {
|
||
Length = 14;
|
||
NameString = PagedPool;
|
||
} else if (Info->StringOffset == MM_KERNEL_STACK_MARK) {
|
||
Length = 14;
|
||
NameString = KernelStack;
|
||
} else if (((PUCHAR)Info->StringOffset >= (PUCHAR)&KernMap[0]) &&
|
||
((PUCHAR)Info->StringOffset <= (PUCHAR)&KernMap[MM_KERN_MAP_SIZE])) {
|
||
|
||
DataTableEntry = ((PKERN_MAP)Info->StringOffset)->Entry;
|
||
NameString = (PUCHAR)DataTableEntry->BaseDllName.Buffer;
|
||
Length = DataTableEntry->BaseDllName.Length;
|
||
} else {
|
||
//
|
||
// This points to a control area.
|
||
// Get the file name.
|
||
//
|
||
|
||
ControlArea = (PCONTROL_AREA)(Info->StringOffset);
|
||
NameString = (PUCHAR)&ControlArea->FilePointer->FileName.Buffer[0];
|
||
}
|
||
|
||
Info->StringOffset = NULL;
|
||
Failed = TRUE;
|
||
if (Length == 0) {
|
||
if (MmIsAddressValid (&ControlArea->FilePointer->FileName.Length)) {
|
||
Length = ControlArea->FilePointer->FileName.Length;
|
||
if (Length == 0) {
|
||
if (ControlArea->u.Flags.NoModifiedWriting) {
|
||
Length = 14;
|
||
NameString = MetaFile;
|
||
} else if (ControlArea->u.Flags.File == 0) {
|
||
NameString = PageFileMapped;
|
||
Length = 16;
|
||
|
||
} else {
|
||
NameString = NoName;
|
||
Length = 14;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if ((String+Length+2) >= End) {
|
||
status = STATUS_DATA_OVERRUN;
|
||
goto Done;
|
||
}
|
||
if (MmIsAddressValid (&NameString[0]) &&
|
||
MmIsAddressValid (&NameString[Length - 1])) {
|
||
RtlMoveMemory (String,
|
||
NameString,
|
||
Length );
|
||
Info->StringOffset = (PUCHAR)Buffer + ((PUCHAR)String - (PUCHAR)MemInfo);
|
||
String[Length] = 0;
|
||
String[Length + 1] = 0;
|
||
String += Length + 2;
|
||
Failed = FALSE;
|
||
}
|
||
if (Failed && ControlArea) {
|
||
if (!(ControlArea->u.Flags.BeingCreated ||
|
||
ControlArea->u.Flags.BeingDeleted) &&
|
||
(ControlCount < MM_SAVED_CONTROL)) {
|
||
SavedControl[ControlCount] = ControlArea;
|
||
SavedInfo[ControlCount] = Info;
|
||
ControlArea->NumberOfSectionReferences += 1;
|
||
ControlCount += 1;
|
||
}
|
||
}
|
||
|
||
} else {
|
||
|
||
//
|
||
// Process...
|
||
//
|
||
|
||
Pfn1 = MI_PFN_ELEMENT (Info->StringOffset);
|
||
Info->StringOffset = NULL;
|
||
if ((String+16) >= End) {
|
||
status = STATUS_DATA_OVERRUN;
|
||
goto Done;
|
||
}
|
||
|
||
Process = (PEPROCESS)Pfn1->u1.Event;
|
||
if (Pfn1->PteAddress == MiGetPteAddress (PDE_BASE)) {
|
||
Info->StringOffset = (PUCHAR)Buffer + ((PUCHAR)String - (PUCHAR)MemInfo);
|
||
RtlMoveMemory (String,
|
||
&Process->ImageFileName[0],
|
||
16);
|
||
String += 16;
|
||
} else {
|
||
|
||
Info->StringOffset = PagedSection;
|
||
if (PagedSection == NULL) {
|
||
Info->StringOffset = (PUCHAR)Buffer + ((PUCHAR)String - (PUCHAR)MemInfo);
|
||
RtlMoveMemory (String,
|
||
&PageFileMapped,
|
||
16);
|
||
PagedSection = Info->StringOffset;
|
||
String += 16;
|
||
}
|
||
}
|
||
}
|
||
|
||
Info += 1;
|
||
}
|
||
|
||
Done:
|
||
UNLOCK_PFN (OldIrql);
|
||
while (ControlCount != 0) {
|
||
|
||
//
|
||
// Process all the pagable name strings.
|
||
//
|
||
|
||
ControlCount -= 1;
|
||
ControlArea = SavedControl[ControlCount];
|
||
Info = SavedInfo[ControlCount];
|
||
NameString = (PUCHAR)&ControlArea->FilePointer->FileName.Buffer[0];
|
||
Length = ControlArea->FilePointer->FileName.Length;
|
||
if (Length == 0) {
|
||
if (ControlArea->u.Flags.NoModifiedWriting) {
|
||
Length = 12;
|
||
NameString = MetaFile;
|
||
} else if (ControlArea->u.Flags.File == 0) {
|
||
NameString = PageFileMapped;
|
||
Length = 16;
|
||
|
||
} else {
|
||
NameString = NoName;
|
||
Length = 12;
|
||
}
|
||
}
|
||
if ((String+Length+2) >= End) {
|
||
status = STATUS_DATA_OVERRUN;
|
||
}
|
||
if (status != STATUS_DATA_OVERRUN) {
|
||
RtlMoveMemory (String,
|
||
NameString,
|
||
Length );
|
||
Info->StringOffset = (PUCHAR)Buffer + ((PUCHAR)String - (PUCHAR)MemInfo);
|
||
String[Length] = 0;
|
||
String[Length + 1] = 0;
|
||
String += Length + 2;
|
||
}
|
||
|
||
LOCK_PFN (OldIrql);
|
||
ControlArea->NumberOfSectionReferences -= 1;
|
||
MiCheckForControlAreaDeletion (ControlArea);
|
||
UNLOCK_PFN (OldIrql);
|
||
}
|
||
*OutLength = ((PUCHAR)String - (PUCHAR)MemInfo);
|
||
MmUnlockPages (Mdl);
|
||
ExFreePool (Mdl);;
|
||
return status;
|
||
}
|
||
#else //DBG
|
||
|
||
NTSTATUS
|
||
MmMemoryUsage (
|
||
IN PVOID Buffer,
|
||
IN ULONG Size,
|
||
IN ULONG Type,
|
||
OUT PULONG OutLength
|
||
)
|
||
{
|
||
return STATUS_NOT_IMPLEMENTED;
|
||
}
|
||
|
||
#endif //DBG
|
||
|
||
|
||
#if DBG
|
||
ULONG
|
||
MiBuildKernelMap (
|
||
IN ULONG NumberOfElements,
|
||
IN OUT PKERN_MAP KernelMap
|
||
)
|
||
|
||
{
|
||
PLIST_ENTRY Next;
|
||
PLIST_ENTRY NextEntry;
|
||
PLDR_DATA_TABLE_ENTRY DataTableEntry;
|
||
ULONG i = 0;
|
||
|
||
KeEnterCriticalRegion();
|
||
ExAcquireResourceShared (&PsLoadedModuleResource, TRUE);
|
||
|
||
NextEntry = PsLoadedModuleList.Flink;
|
||
do {
|
||
|
||
DataTableEntry = CONTAINING_RECORD(NextEntry,
|
||
LDR_DATA_TABLE_ENTRY,
|
||
InLoadOrderLinks);
|
||
|
||
KernelMap[i].Entry = DataTableEntry;
|
||
KernelMap[i].StartVa = (ULONG)DataTableEntry->DllBase;
|
||
KernelMap[i].EndVa = KernelMap[i].StartVa +
|
||
(ULONG)DataTableEntry->SizeOfImage;
|
||
i += 1;
|
||
if (i == NumberOfElements) {
|
||
break;
|
||
}
|
||
Next = DataTableEntry->InLoadOrderLinks.Flink;
|
||
|
||
NextEntry = NextEntry->Flink;
|
||
} while (NextEntry != &PsLoadedModuleList);
|
||
|
||
ExReleaseResource (&PsLoadedModuleResource);
|
||
KeLeaveCriticalRegion();
|
||
|
||
return i;
|
||
}
|
||
#endif //DBG
|
||
|
||
|
||
|
||
#if DBG
|
||
VOID
|
||
MiFlushCache (
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine (debugging only) flushes the "cache" by moving
|
||
all pages from the standby list to the free list. Modified
|
||
pages are not effected.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
KIRQL OldIrql;
|
||
ULONG Page;
|
||
|
||
LOCK_PFN (OldIrql);
|
||
|
||
while (MmPageLocationList[StandbyPageList]->Total != 0) {
|
||
|
||
Page = MiRemovePageFromList (MmPageLocationList[StandbyPageList]);
|
||
|
||
//
|
||
// A page has been removed from the standby list. The
|
||
// PTE which refers to this page is currently in the transtion
|
||
// state and must have its original contents restored to free
|
||
// the the last reference to this physical page.
|
||
//
|
||
|
||
MiRestoreTransitionPte (Page);
|
||
|
||
//
|
||
// Put the page into the free list.
|
||
//
|
||
|
||
MiInsertPageInList (MmPageLocationList[FreePageList], Page);
|
||
}
|
||
|
||
UNLOCK_PFN (OldIrql);
|
||
return;
|
||
}
|
||
VOID
|
||
MiDumpReferencedPages (
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine (debugging only) dumps all PFN entries which appear
|
||
to be locked in memory for i/o.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
KIRQL OldIrql;
|
||
PMMPFN Pfn1;
|
||
PMMPFN PfnLast;
|
||
|
||
LOCK_PFN (OldIrql);
|
||
|
||
Pfn1 = MI_PFN_ELEMENT (MmLowestPhysicalPage);
|
||
PfnLast = MI_PFN_ELEMENT (MmHighestPhysicalPage);
|
||
|
||
while (Pfn1 <= PfnLast) {
|
||
|
||
if ((Pfn1->u2.ShareCount == 0) && (Pfn1->u3.e2.ReferenceCount != 0)) {
|
||
MiFormatPfn (Pfn1);
|
||
}
|
||
|
||
if (Pfn1->u3.e2.ReferenceCount > 1) {
|
||
MiFormatPfn (Pfn1);
|
||
}
|
||
|
||
Pfn1 += 1;
|
||
}
|
||
|
||
UNLOCK_PFN (OldIrql);
|
||
return;
|
||
}
|
||
|
||
#endif //DBG
|