mirror of
https://github.com/reactos/reactos.git
synced 2025-02-25 01:39:30 +00:00
MiQueryVirtualMemory(): created because ZwQueryVirtualMemory() didn't work for me, added cases for memory area types that I needed to walk stack traces.
Stack traces now use MiQueryVirtualMemory to make sure they never step outside the allocated stack they started in ( this prevents page faults at high irql ) - for some reason this patch eliminates the NtW32Callback() crash everybody is seeing with GDI_DEBUG enabled, tho I don't understand why. svn path=/trunk/; revision=12286
This commit is contained in:
parent
5dcad29338
commit
4cf6b9f489
3 changed files with 191 additions and 54 deletions
|
@ -37,4 +37,12 @@ MiLockVirtualMemory(HANDLE ProcessHandle,
|
|||
PMmProbeAndLockPages pMmProbeAndLockPages,
|
||||
PExFreePool pExFreePool);
|
||||
|
||||
NTSTATUS FASTCALL
|
||||
MiQueryVirtualMemory (IN HANDLE ProcessHandle,
|
||||
IN PVOID Address,
|
||||
IN CINT VirtualMemoryInformationClass,
|
||||
OUT PVOID VirtualMemoryInformation,
|
||||
IN ULONG Length,
|
||||
OUT PULONG ResultLength);
|
||||
|
||||
#endif /* __NTOSKRNL_INCLUDE_INTERNAL_TEST_H */
|
||||
|
|
|
@ -630,16 +630,38 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
|
|||
VOID
|
||||
KeDumpStackFrames(PULONG Frame)
|
||||
{
|
||||
PULONG StackBase, StackEnd;
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
ULONG ResultLength = sizeof(mbi);
|
||||
NTSTATUS Status;
|
||||
|
||||
DbgPrint("Frames: ");
|
||||
_SEH_TRY
|
||||
{
|
||||
while ( MmIsAddressValid(Frame) )
|
||||
Status = MiQueryVirtualMemory (
|
||||
(HANDLE)-1,
|
||||
Frame,
|
||||
MemoryBasicInformation,
|
||||
&mbi,
|
||||
sizeof(mbi),
|
||||
&ResultLength );
|
||||
if ( !NT_SUCCESS(Status) )
|
||||
{
|
||||
DPRINT1("Can't dump stack frames: NtQueryVirtualMemory() failed: %x\n", Status );
|
||||
return;
|
||||
}
|
||||
|
||||
StackBase = Frame;
|
||||
StackEnd = mbi.BaseAddress + mbi.RegionSize;
|
||||
|
||||
while ( Frame >= StackBase && Frame < StackEnd )
|
||||
{
|
||||
ULONG Addr = Frame[1];
|
||||
if (!KeRosPrintAddress((PVOID)Addr))
|
||||
DbgPrint("<%X>", Addr);
|
||||
if ( Addr == 0 || Addr == 0xDEADBEEF )
|
||||
break;
|
||||
StackBase = Frame;
|
||||
Frame = (PULONG)Frame[0];
|
||||
DbgPrint(" ");
|
||||
}
|
||||
|
@ -655,6 +677,10 @@ VOID STDCALL
|
|||
KeRosDumpStackFrames ( PULONG Frame, ULONG FrameCount )
|
||||
{
|
||||
ULONG i=0;
|
||||
PULONG StackBase, StackEnd;
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
ULONG ResultLength = sizeof(mbi);
|
||||
NTSTATUS Status;
|
||||
|
||||
DbgPrint("Frames: ");
|
||||
_SEH_TRY
|
||||
|
@ -668,13 +694,31 @@ KeRosDumpStackFrames ( PULONG Frame, ULONG FrameCount )
|
|||
#endif
|
||||
//Frame = (PULONG)Frame[0]; // step out of KeRosDumpStackFrames
|
||||
}
|
||||
while ( MmIsAddressValid(Frame) && i++ < FrameCount )
|
||||
|
||||
Status = MiQueryVirtualMemory (
|
||||
(HANDLE)-1,
|
||||
Frame,
|
||||
MemoryBasicInformation,
|
||||
&mbi,
|
||||
sizeof(mbi),
|
||||
&ResultLength );
|
||||
if ( !NT_SUCCESS(Status) )
|
||||
{
|
||||
DPRINT1("Can't dump stack frames: NtQueryVirtualMemory() failed: %x\n", Status );
|
||||
return;
|
||||
}
|
||||
|
||||
StackBase = Frame;
|
||||
StackEnd = mbi.BaseAddress + mbi.RegionSize;
|
||||
|
||||
while ( Frame >= StackBase && Frame < StackEnd && i++ < FrameCount )
|
||||
{
|
||||
ULONG Addr = Frame[1];
|
||||
if (!KeRosPrintAddress((PVOID)Addr))
|
||||
DbgPrint("<%X>", Addr);
|
||||
if ( Addr == 0 || Addr == 0xDEADBEEF )
|
||||
break;
|
||||
StackBase = Frame;
|
||||
Frame = (PULONG)Frame[0];
|
||||
DbgPrint(" ");
|
||||
}
|
||||
|
@ -690,7 +734,11 @@ ULONG STDCALL
|
|||
KeRosGetStackFrames ( PULONG Frames, ULONG FrameCount )
|
||||
{
|
||||
ULONG Count = 0;
|
||||
PULONG Frame;
|
||||
PULONG StackBase, StackEnd, Frame;
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
ULONG ResultLength = sizeof(mbi);
|
||||
NTSTATUS Status;
|
||||
|
||||
_SEH_TRY
|
||||
{
|
||||
#if defined __GNUC__
|
||||
|
@ -698,9 +746,27 @@ KeRosGetStackFrames ( PULONG Frames, ULONG FrameCount )
|
|||
#elif defined(_MSC_VER)
|
||||
__asm mov [Frame], ebp
|
||||
#endif
|
||||
while ( Count < FrameCount )
|
||||
|
||||
Status = MiQueryVirtualMemory (
|
||||
(HANDLE)-1,
|
||||
Frame,
|
||||
MemoryBasicInformation,
|
||||
&mbi,
|
||||
sizeof(mbi),
|
||||
&ResultLength );
|
||||
if ( !NT_SUCCESS(Status) )
|
||||
{
|
||||
DPRINT1("Can't get stack frames: NtQueryVirtualMemory() failed: %x\n", Status );
|
||||
return 0;
|
||||
}
|
||||
|
||||
StackBase = Frame;
|
||||
StackEnd = mbi.BaseAddress + mbi.RegionSize;
|
||||
|
||||
while ( Count < FrameCount && Frame >= StackBase && Frame < StackEnd )
|
||||
{
|
||||
Frames[Count++] = Frame[1];
|
||||
StackBase = Frame;
|
||||
Frame = (PULONG)Frame[0];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: virtual.c,v 1.85 2004/11/13 22:27:16 hbirr Exp $
|
||||
/* $Id: virtual.c,v 1.86 2004/12/22 05:17:44 royce Exp $
|
||||
*
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/mm/virtual.c
|
||||
|
@ -125,43 +125,18 @@ NtLockVirtualMemory(HANDLE ProcessHandle,
|
|||
}
|
||||
|
||||
|
||||
/* (tMk 2004.II.4)
|
||||
* FUNCTION:
|
||||
* Called from VirtualQueryEx (lib\kernel32\mem\virtual.c)
|
||||
*
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
NtQueryVirtualMemory (IN HANDLE ProcessHandle,
|
||||
NTSTATUS FASTCALL
|
||||
MiQueryVirtualMemory (IN HANDLE ProcessHandle,
|
||||
IN PVOID Address,
|
||||
IN CINT VirtualMemoryInformationClass,
|
||||
OUT PVOID VirtualMemoryInformation,
|
||||
IN ULONG Length,
|
||||
OUT PULONG UnsafeResultLength)
|
||||
OUT PULONG ResultLength)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PEPROCESS Process;
|
||||
MEMORY_AREA* MemoryArea;
|
||||
ULONG ResultLength = 0;
|
||||
PMADDRESS_SPACE AddressSpace;
|
||||
KPROCESSOR_MODE PrevMode;
|
||||
union
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION BasicInfo;
|
||||
}
|
||||
VirtualMemoryInfo;
|
||||
|
||||
DPRINT("NtQueryVirtualMemory(ProcessHandle %x, Address %x, "
|
||||
"VirtualMemoryInformationClass %d, VirtualMemoryInformation %x, "
|
||||
"Length %lu ResultLength %x)\n",ProcessHandle,Address,
|
||||
VirtualMemoryInformationClass,VirtualMemoryInformation,
|
||||
Length,ResultLength);
|
||||
|
||||
PrevMode = ExGetPreviousMode();
|
||||
|
||||
if (PrevMode == UserMode && Address >= (PVOID)KERNEL_BASE)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (Address < (PVOID)KERNEL_BASE)
|
||||
{
|
||||
|
@ -190,7 +165,8 @@ NtQueryVirtualMemory (IN HANDLE ProcessHandle,
|
|||
{
|
||||
case MemoryBasicInformation:
|
||||
{
|
||||
PMEMORY_BASIC_INFORMATION Info = &VirtualMemoryInfo.BasicInfo;
|
||||
PMEMORY_BASIC_INFORMATION Info =
|
||||
(PMEMORY_BASIC_INFORMATION)VirtualMemoryInformation;
|
||||
if (Length != sizeof(MEMORY_BASIC_INFORMATION))
|
||||
{
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
|
@ -208,7 +184,7 @@ NtQueryVirtualMemory (IN HANDLE ProcessHandle,
|
|||
Info->AllocationBase = NULL;
|
||||
Info->RegionSize = MmFindGapAtAddress(AddressSpace, Info->BaseAddress);
|
||||
Status = STATUS_SUCCESS;
|
||||
ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
|
||||
*ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -216,11 +192,11 @@ NtQueryVirtualMemory (IN HANDLE ProcessHandle,
|
|||
{
|
||||
case MEMORY_AREA_VIRTUAL_MEMORY:
|
||||
Status = MmQueryAnonMem(MemoryArea, Address, Info,
|
||||
&ResultLength);
|
||||
ResultLength);
|
||||
break;
|
||||
case MEMORY_AREA_SECTION_VIEW:
|
||||
Status = MmQuerySectionView(MemoryArea, Address, Info,
|
||||
&ResultLength);
|
||||
ResultLength);
|
||||
break;
|
||||
case MEMORY_AREA_NO_ACCESS:
|
||||
Info->Type = 0;
|
||||
|
@ -231,7 +207,7 @@ NtQueryVirtualMemory (IN HANDLE ProcessHandle,
|
|||
Info->AllocationBase = MemoryArea->BaseAddress;
|
||||
Info->RegionSize = MemoryArea->Length;
|
||||
Status = STATUS_SUCCESS;
|
||||
ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
|
||||
*ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
|
||||
break;
|
||||
case MEMORY_AREA_SHARED_DATA:
|
||||
Info->Type = 0;
|
||||
|
@ -242,11 +218,52 @@ NtQueryVirtualMemory (IN HANDLE ProcessHandle,
|
|||
Info->AllocationBase = MemoryArea->BaseAddress;
|
||||
Info->RegionSize = MemoryArea->Length;
|
||||
Status = STATUS_SUCCESS;
|
||||
ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
|
||||
*ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
|
||||
break;
|
||||
case MEMORY_AREA_SYSTEM:
|
||||
{
|
||||
static int warned = 0;
|
||||
if ( !warned )
|
||||
{
|
||||
DPRINT1("FIXME: MEMORY_AREA_SYSTEM case incomplete (or possibly wrong) for NtQueryVirtualMemory()\n");
|
||||
warned = 1;
|
||||
}
|
||||
}
|
||||
/* FIXME - don't have a clue if this is right, but it's better than nothing */
|
||||
Info->Type = 0;
|
||||
Info->State = MEM_COMMIT;
|
||||
Info->Protect = MemoryArea->Attributes;
|
||||
Info->AllocationProtect = MemoryArea->Attributes;
|
||||
Info->BaseAddress = MemoryArea->BaseAddress;
|
||||
Info->AllocationBase = MemoryArea->BaseAddress;
|
||||
Info->RegionSize = MemoryArea->Length;
|
||||
Status = STATUS_SUCCESS;
|
||||
*ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
|
||||
break;
|
||||
case MEMORY_AREA_KERNEL_STACK:
|
||||
{
|
||||
static int warned = 0;
|
||||
if ( !warned )
|
||||
{
|
||||
DPRINT1("FIXME: MEMORY_AREA_KERNEL_STACK case incomplete (or possibly wrong) for NtQueryVirtualMemory()\n");
|
||||
warned = 1;
|
||||
}
|
||||
}
|
||||
/* FIXME - don't have a clue if this is right, but it's better than nothing */
|
||||
Info->Type = 0;
|
||||
Info->State = MEM_COMMIT;
|
||||
Info->Protect = MemoryArea->Attributes;
|
||||
Info->AllocationProtect = MemoryArea->Attributes;
|
||||
Info->BaseAddress = MemoryArea->BaseAddress;
|
||||
Info->AllocationBase = MemoryArea->BaseAddress;
|
||||
Info->RegionSize = MemoryArea->Length;
|
||||
Status = STATUS_SUCCESS;
|
||||
*ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
|
||||
break;
|
||||
default:
|
||||
DPRINT1("unhandled memory area type: 0x%x\n", MemoryArea->Type);
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
ResultLength = 0;
|
||||
*ResultLength = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -255,7 +272,7 @@ NtQueryVirtualMemory (IN HANDLE ProcessHandle,
|
|||
default:
|
||||
{
|
||||
Status = STATUS_INVALID_INFO_CLASS;
|
||||
ResultLength = 0;
|
||||
*ResultLength = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -266,6 +283,52 @@ NtQueryVirtualMemory (IN HANDLE ProcessHandle,
|
|||
ObDereferenceObject(Process);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* (tMk 2004.II.4)
|
||||
* FUNCTION:
|
||||
* Called from VirtualQueryEx (lib\kernel32\mem\virtual.c)
|
||||
*
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
NtQueryVirtualMemory (IN HANDLE ProcessHandle,
|
||||
IN PVOID Address,
|
||||
IN CINT VirtualMemoryInformationClass,
|
||||
OUT PVOID VirtualMemoryInformation,
|
||||
IN ULONG Length,
|
||||
OUT PULONG UnsafeResultLength)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
ULONG ResultLength = 0;
|
||||
KPROCESSOR_MODE PrevMode;
|
||||
union
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION BasicInfo;
|
||||
}
|
||||
VirtualMemoryInfo;
|
||||
|
||||
DPRINT("NtQueryVirtualMemory(ProcessHandle %x, Address %x, "
|
||||
"VirtualMemoryInformationClass %d, VirtualMemoryInformation %x, "
|
||||
"Length %lu ResultLength %x)\n",ProcessHandle,Address,
|
||||
VirtualMemoryInformationClass,VirtualMemoryInformation,
|
||||
Length,ResultLength);
|
||||
|
||||
PrevMode = ExGetPreviousMode();
|
||||
|
||||
if (PrevMode == UserMode && Address >= (PVOID)KERNEL_BASE)
|
||||
{
|
||||
DPRINT1("Invalid parameter\n");
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = MiQueryVirtualMemory ( ProcessHandle,
|
||||
Address,
|
||||
VirtualMemoryInformationClass,
|
||||
&VirtualMemoryInfo,
|
||||
Length,
|
||||
&ResultLength );
|
||||
|
||||
if (NT_SUCCESS(Status) && ResultLength > 0)
|
||||
{
|
||||
Status = MmCopyToCaller(VirtualMemoryInformation, &VirtualMemoryInfo, ResultLength);
|
||||
|
|
Loading…
Reference in a new issue