Commit in reactos/ntoskrnl on MAIN
include/internal/test.h+81.2 -> 1.3
ke/i386/exp.c+70-41.101 -> 1.102
mm/virtual.c+113-501.85 -> 1.86
+191-54
3 modified files
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.

reactos/ntoskrnl/include/internal
test.h 1.2 -> 1.3
diff -u -r1.2 -r1.3
--- test.h	29 Oct 2004 16:48:10 -0000	1.2
+++ test.h	22 Dec 2004 05:17:42 -0000	1.3
@@ -37,4 +37,12 @@
   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 */

reactos/ntoskrnl/ke/i386
exp.c 1.101 -> 1.102
diff -u -r1.101 -r1.102
--- exp.c	21 Dec 2004 04:05:17 -0000	1.101
+++ exp.c	22 Dec 2004 05:17:44 -0000	1.102
@@ -630,16 +630,38 @@
 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 @@
 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 @@
 #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 @@
 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 @@
 #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];
 		}
 	}

reactos/ntoskrnl/mm
virtual.c 1.85 -> 1.86
diff -u -r1.85 -r1.86
--- virtual.c	13 Nov 2004 22:27:16 -0000	1.85
+++ virtual.c	22 Dec 2004 05:17:44 -0000	1.86
@@ -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 @@
 /*
  * 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 @@
 }
 
 
-/* (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 @@
    {
       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 @@
 	       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 @@
 	             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 @@
 	             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 @@
       default:
          {
             Status = STATUS_INVALID_INFO_CLASS;
-            ResultLength = 0;
+            *ResultLength = 0;
             break;
          }
    }
@@ -266,6 +283,52 @@
       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 @@
          ResultLength = 0;
       }
    }
-   
+
    if (UnsafeResultLength != NULL)
    {
       MmCopyToCaller(UnsafeResultLength, &ResultLength, sizeof(ULONG));
@@ -284,7 +347,7 @@
 
 
 /* (tMk 2004.II.5)
- * FUNCTION: 
+ * FUNCTION:
  * Called from VirtualProtectEx (lib\kernel32\mem\virtual.c)
  *
  */
@@ -310,13 +373,13 @@
    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 @@
 
 
 /* (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 @@
       Mdl = MmCreateMdl(NULL,
                         Buffer,
                         NumberOfBytesToRead);
-      if(Mdl == NULL) 
+      if(Mdl == NULL)
       {
          ObDereferenceObject(Process);
          return(STATUS_NO_MEMORY);
@@ -482,7 +545,7 @@
    Mdl = MmCreateMdl(NULL,
                      BaseAddress,
                      NumberOfBytesToUnlock);
-   if(Mdl == NULL) 
+   if(Mdl == NULL)
    {
       ObDereferenceObject(Process);
       return(STATUS_NO_MEMORY);
@@ -506,7 +569,7 @@
 /* (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
CVSspam 0.2.8