mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 17:34:57 +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
|
||||
|
@ -41,12 +41,12 @@ NtFlushVirtualMemory(IN HANDLE ProcessHandle,
|
|||
/*
|
||||
* FUNCTION: Flushes virtual memory to file
|
||||
* ARGUMENTS:
|
||||
* ProcessHandle = Points to the process that allocated the virtual
|
||||
* ProcessHandle = Points to the process that allocated the virtual
|
||||
* memory
|
||||
* BaseAddress = Points to the memory address
|
||||
* NumberOfBytesToFlush = Limits the range to flush,
|
||||
* NumberOfBytesFlushed = Actual number of bytes flushed
|
||||
* RETURNS: Status
|
||||
* RETURNS: Status
|
||||
*/
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
|
@ -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,14 +165,15 @@ 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);
|
||||
ObDereferenceObject(Process);
|
||||
return(STATUS_INFO_LENGTH_MISMATCH);
|
||||
}
|
||||
|
||||
|
||||
if (MemoryArea == NULL)
|
||||
{
|
||||
Info->Type = 0;
|
||||
|
@ -208,19 +184,19 @@ 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
|
||||
else
|
||||
{
|
||||
switch(MemoryArea->Type)
|
||||
{
|
||||
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);
|
||||
|
@ -274,7 +337,7 @@ NtQueryVirtualMemory (IN HANDLE ProcessHandle,
|
|||
ResultLength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (UnsafeResultLength != NULL)
|
||||
{
|
||||
MmCopyToCaller(UnsafeResultLength, &ResultLength, sizeof(ULONG));
|
||||
|
@ -284,7 +347,7 @@ NtQueryVirtualMemory (IN HANDLE ProcessHandle,
|
|||
|
||||
|
||||
/* (tMk 2004.II.5)
|
||||
* FUNCTION:
|
||||
* FUNCTION:
|
||||
* Called from VirtualProtectEx (lib\kernel32\mem\virtual.c)
|
||||
*
|
||||
*/
|
||||
|
@ -310,13 +373,13 @@ NtProtectVirtualMemory(IN HANDLE ProcessHandle,
|
|||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
|
||||
// (tMk 2004.II.5) in Microsoft SDK I read:
|
||||
// (tMk 2004.II.5) in Microsoft SDK I read:
|
||||
// 'if this parameter is NULL or does not point to a valid variable, the function fails'
|
||||
if(UnsafeOldAccessProtection == NULL)
|
||||
if(UnsafeOldAccessProtection == NULL)
|
||||
{
|
||||
return(STATUS_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
|
||||
NumberOfBytesToProtect =
|
||||
PAGE_ROUND_UP(BaseAddress + NumberOfBytesToProtect) -
|
||||
PAGE_ROUND_DOWN(BaseAddress);
|
||||
|
@ -372,7 +435,7 @@ NtProtectVirtualMemory(IN HANDLE ProcessHandle,
|
|||
|
||||
|
||||
/* (tMk 2004.II.05)
|
||||
* FUNCTION:
|
||||
* FUNCTION:
|
||||
* Called from ReadProcessMemory (lib\kernel32\mem\procmem.c) and KlInitPeb(lib\kernel32\process\create.c)
|
||||
*
|
||||
* NOTE: This function will be correct if MmProbeAndLockPages() would be fully IMPLEMENTED.
|
||||
|
@ -416,7 +479,7 @@ NtReadVirtualMemory(IN HANDLE ProcessHandle,
|
|||
Mdl = MmCreateMdl(NULL,
|
||||
Buffer,
|
||||
NumberOfBytesToRead);
|
||||
if(Mdl == NULL)
|
||||
if(Mdl == NULL)
|
||||
{
|
||||
ObDereferenceObject(Process);
|
||||
return(STATUS_NO_MEMORY);
|
||||
|
@ -482,7 +545,7 @@ NtUnlockVirtualMemory(HANDLE ProcessHandle,
|
|||
Mdl = MmCreateMdl(NULL,
|
||||
BaseAddress,
|
||||
NumberOfBytesToUnlock);
|
||||
if(Mdl == NULL)
|
||||
if(Mdl == NULL)
|
||||
{
|
||||
ObDereferenceObject(Process);
|
||||
return(STATUS_NO_MEMORY);
|
||||
|
@ -506,7 +569,7 @@ NtUnlockVirtualMemory(HANDLE ProcessHandle,
|
|||
/* (tMk 2004.II.05)
|
||||
* FUNCTION:
|
||||
* Called from WriteProcessMemory (lib\kernel32\mem\procmem.c) and KlInitPeb(lib\kernel32\process\create.c)
|
||||
*
|
||||
*
|
||||
* NOTE: This function will be correct if MmProbeAndLockPages() would be fully IMPLEMENTED.
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
|
|
Loading…
Reference in a new issue