[PATCH 2/2] ntdll: allow HeapSize to work with global GMEM_MOVEABLE pointers

Damjan Jovanovic damjan.jov at gmail.com
Sat Oct 26 01:39:44 CDT 2019


This patch attempts to address the problem by patching RtlSizeHeap()
to subtract 8 (8 being HGLOBAL_STORAGE) from the pointer if it doesn't
seem like a valid pointer, to cater to GMEM_MOVEABLE pointers actually
starting 8 bytes earlier.

I am not familiar with the internals of Windows' memory management so
this might not be the best solution, but all the heap tests pass so it
can't be that wrong either ;). It certainly gets wxWidgets
applications working.

Signed-off-by: Damjan Jovanovic <damjan.jov at gmail.com>
---
 dlls/kernel32/tests/heap.c |  2 +-
 dlls/ntdll/heap.c          | 50 ++++++++++++++++++++++++--------------
 2 files changed, 33 insertions(+), 19 deletions(-)
-------------- next part --------------
diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c
index eff3242498..c26e12fd92 100644
--- a/dlls/kernel32/tests/heap.c
+++ b/dlls/kernel32/tests/heap.c
@@ -343,7 +343,7 @@ static void test_heap(void)
     mem = GlobalLock(gbl);
     ok(mem != NULL, "returned error %d\n", GetLastError());
     size = HeapSize(GetProcessHeap(), 0, mem);
-    todo_wine ok(size != (SIZE_T)-1 && size >= 100, "HeapSize returned %lu\n", size);
+    ok(size != (SIZE_T)-1 && size >= 100, "HeapSize returned %lu\n", size);
     GlobalFree(gbl);
 
 
diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c
index e8ac1ffa7a..5707ae37f0 100644
--- a/dlls/ntdll/heap.c
+++ b/dlls/ntdll/heap.c
@@ -2004,24 +2004,7 @@ BOOLEAN WINAPI RtlUnlockHeap( HANDLE heap )
 }
 
 
-/***********************************************************************
- *           RtlSizeHeap   (NTDLL.@)
- *
- * Get the actual size of a memory block allocated from a Heap.
- *
- * PARAMS
- *  heap  [I] Heap that block was allocated from
- *  flags [I] HEAP_ flags from "winnt.h"
- *  ptr   [I] Block to get the size of
- *
- * RETURNS
- *  Success: The size of the block.
- *  Failure: -1, heap or ptr are invalid.
- *
- * NOTES
- *  The size may be bigger than what was passed to RtlAllocateHeap().
- */
-SIZE_T WINAPI RtlSizeHeap( HANDLE heap, ULONG flags, const void *ptr )
+SIZE_T rtl_size_heap_0( HANDLE heap, ULONG flags, const void *ptr, BOOL retry )
 {
     SIZE_T ret;
     const ARENA_INUSE *pArena;
@@ -2040,6 +2023,14 @@ SIZE_T WINAPI RtlSizeHeap( HANDLE heap, ULONG flags, const void *ptr )
     pArena = (const ARENA_INUSE *)ptr - 1;
     if (!validate_block_pointer( heapPtr, &subheap, pArena ))
     {
+        if (retry && validate_block_pointer( heapPtr, &subheap, (const ARENA_INUSE *) (((BYTE*)ptr) - 8) - 1))
+        {
+            /* It came from GlobalAlloc() with GMEM_MOVEABLE */
+            SIZE_T originalSize = rtl_size_heap_0(heap, flags, ((BYTE*)ptr) - 8, FALSE);
+            if (originalSize != ~0UL)
+                return originalSize - 8;
+            return originalSize;
+        }
         RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_INVALID_PARAMETER );
         ret = ~0UL;
     }
@@ -2059,6 +2050,29 @@ SIZE_T WINAPI RtlSizeHeap( HANDLE heap, ULONG flags, const void *ptr )
 }
 
 
+/***********************************************************************
+ *           RtlSizeHeap   (NTDLL.@)
+ *
+ * Get the actual size of a memory block allocated from a Heap.
+ *
+ * PARAMS
+ *  heap  [I] Heap that block was allocated from
+ *  flags [I] HEAP_ flags from "winnt.h"
+ *  ptr   [I] Block to get the size of
+ *
+ * RETURNS
+ *  Success: The size of the block.
+ *  Failure: -1, heap or ptr are invalid.
+ *
+ * NOTES
+ *  The size may be bigger than what was passed to RtlAllocateHeap().
+ */
+SIZE_T WINAPI RtlSizeHeap( HANDLE heap, ULONG flags, const void *ptr )
+{
+    return rtl_size_heap_0(heap, flags, ptr, TRUE);
+}
+
+
 /***********************************************************************
  *           RtlValidateHeap   (NTDLL.@)
  *


More information about the wine-devel mailing list