mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-09-13 09:17:20 -07:00
Rebase against 19eab9c0e59201277f359d55ee5747383e014e87.
This commit is contained in:
parent
09808df495
commit
8791ceb20d
@ -1,3 +1,4 @@
|
||||
Fixes: [48175] AION (64 bit) - crashes in crysystem.dll.CryFree() due to high memory pointers allocated
|
||||
Fixes: [46568] 64-bit msxml6.dll from Microsoft Core XML Services 6.0 redist package fails to load (Wine doesn't respect 44-bit user-mode VA limitation from Windows < 8.1)
|
||||
Depends: ntdll-Placeholders
|
||||
Disabled: True
|
||||
|
@ -1,105 +0,0 @@
|
||||
From 7c13335d926a1b47f7cf88065d641c4d5fa80a59 Mon Sep 17 00:00:00 2001
|
||||
From: Paul Gofman <pgofman@codeweavers.com>
|
||||
Date: Fri, 11 Nov 2022 17:51:26 -0600
|
||||
Subject: [PATCH] ntdll/tests: Add tests for freeing a part of view.
|
||||
|
||||
---
|
||||
dlls/ntdll/tests/virtual.c | 70 ++++++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 67 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c
|
||||
index 6831fe3c522..8e94566fb7f 100644
|
||||
--- a/dlls/ntdll/tests/virtual.c
|
||||
+++ b/dlls/ntdll/tests/virtual.c
|
||||
@@ -1639,21 +1639,85 @@ static void test_syscalls(void)
|
||||
|
||||
static void test_NtFreeVirtualMemory(void)
|
||||
{
|
||||
+ void *addr1, *addr;
|
||||
NTSTATUS status;
|
||||
- void *addr1;
|
||||
SIZE_T size;
|
||||
|
||||
size = 0x10000;
|
||||
addr1 = NULL;
|
||||
- status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr1, 0, &size, MEM_RESERVE, PAGE_READWRITE);
|
||||
+ status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr1, 0, &size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
||||
ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
|
||||
|
||||
size = 0;
|
||||
status = NtFreeVirtualMemory(NULL, &addr1, &size, MEM_RELEASE);
|
||||
ok(status == STATUS_INVALID_HANDLE, "Unexpected status %08lx.\n", status);
|
||||
|
||||
+ addr = (char *)addr1 + 0x1000;
|
||||
+ size = 0;
|
||||
+ status = NtFreeVirtualMemory(NtCurrentProcess(), &addr, &size, MEM_RELEASE);
|
||||
+ ok(status == STATUS_FREE_VM_NOT_AT_BASE, "Unexpected status %08lx.\n", status);
|
||||
+
|
||||
+ size = 0x11000;
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), &addr1, &size, MEM_RELEASE);
|
||||
- ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
|
||||
+ todo_wine ok(status == STATUS_UNABLE_TO_FREE_VM, "Unexpected status %08lx.\n", status);
|
||||
+
|
||||
+ addr = (char *)addr1 + 0x1001;
|
||||
+ size = 0xffff;
|
||||
+ status = NtFreeVirtualMemory(NtCurrentProcess(), &addr, &size, MEM_RELEASE);
|
||||
+ todo_wine ok(status == STATUS_UNABLE_TO_FREE_VM, "Unexpected status %08lx.\n", status);
|
||||
+ ok(size == 0xffff, "Unexpected size %p.\n", (void *)size);
|
||||
+ ok(addr == (char *)addr1 + 0x1001, "Got addr %p, addr1 %p.\n", addr, addr1);
|
||||
+
|
||||
+ size = 0xfff;
|
||||
+ addr = (char *)addr1 + 0x1001;
|
||||
+ status = NtFreeVirtualMemory(NtCurrentProcess(), &addr, &size, MEM_RELEASE);
|
||||
+ todo_wine ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
|
||||
+ *(volatile char *)addr1 = 1;
|
||||
+ *((volatile char *)addr1 + 0x2000) = 1;
|
||||
+ todo_wine ok(size == 0x1000, "Unexpected size %p.\n", (void *)size);
|
||||
+ todo_wine ok(addr == (char *)addr1 + 0x1000, "Got addr %p, addr1 %p.\n", addr, addr1);
|
||||
+
|
||||
+ size = 0xfff;
|
||||
+ addr = (char *)addr1 + 1;
|
||||
+ status = NtFreeVirtualMemory(NtCurrentProcess(), &addr, &size, MEM_RELEASE);
|
||||
+ todo_wine ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
|
||||
+ *((volatile char *)addr1 + 0x2000) = 1;
|
||||
+ todo_wine ok(size == 0x1000, "Unexpected size %p.\n", (void *)size);
|
||||
+ todo_wine ok(addr == addr1, "Got addr %p, addr1 %p.\n", addr, addr1);
|
||||
+
|
||||
+ size = 0x1000;
|
||||
+ addr = addr1;
|
||||
+ status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr, 0, &size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
||||
+ todo_wine ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
|
||||
+ ok(addr == addr1, "Unexpected addr %p, addr1 %p.\n", addr, addr1);
|
||||
+ ok(size == 0x1000, "Unexpected size %p.\n", (void *)size);
|
||||
+
|
||||
+ size = 0x10000;
|
||||
+ status = NtFreeVirtualMemory(NtCurrentProcess(), &addr1, &size, MEM_DECOMMIT);
|
||||
+ todo_wine ok(status == STATUS_UNABLE_TO_FREE_VM, "Unexpected status %08lx.\n", status);
|
||||
+
|
||||
+ size = 0x10000;
|
||||
+ status = NtFreeVirtualMemory(NtCurrentProcess(), &addr1, &size, MEM_RELEASE);
|
||||
+ todo_wine ok(status == STATUS_UNABLE_TO_FREE_VM, "Unexpected status %08lx.\n", status);
|
||||
+
|
||||
+ size = 0;
|
||||
+ addr = (char *)addr1 + 0x1000;
|
||||
+ status = NtFreeVirtualMemory(NtCurrentProcess(), &addr, &size, MEM_RELEASE);
|
||||
+ todo_wine ok(status == STATUS_MEMORY_NOT_ALLOCATED, "Unexpected status %08lx.\n", status);
|
||||
+
|
||||
+ size = 0x1000;
|
||||
+ addr = (char *)addr1 + 0x1000;
|
||||
+ status = NtFreeVirtualMemory(NtCurrentProcess(), &addr, &size, MEM_DECOMMIT);
|
||||
+ todo_wine ok(status == STATUS_MEMORY_NOT_ALLOCATED, "Unexpected status %08lx.\n", status);
|
||||
+
|
||||
+ size = 0;
|
||||
+ addr = (char *)addr1 + 0x2000;
|
||||
+ status = NtFreeVirtualMemory(NtCurrentProcess(), &addr, &size, MEM_RELEASE);
|
||||
+ todo_wine ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
|
||||
+
|
||||
+ size = 0x1000;
|
||||
+ status = NtFreeVirtualMemory(NtCurrentProcess(), &addr1, &size, MEM_RELEASE);
|
||||
+ todo_wine ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
|
||||
}
|
||||
|
||||
static void test_prefetch(void)
|
||||
--
|
||||
2.38.1
|
||||
|
@ -1,30 +0,0 @@
|
||||
From bc937422e5f600be650e21de5f6c9b8656d5c23c Mon Sep 17 00:00:00 2001
|
||||
From: Paul Gofman <pgofman@codeweavers.com>
|
||||
Date: Fri, 11 Nov 2022 17:56:42 -0600
|
||||
Subject: [PATCH] kernelbase: Validate nonzero size for MEM_RELEASE in
|
||||
VirtualFreeEx().
|
||||
|
||||
---
|
||||
dlls/kernelbase/memory.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c
|
||||
index 2a503587e93..c01fe817972 100644
|
||||
--- a/dlls/kernelbase/memory.c
|
||||
+++ b/dlls/kernelbase/memory.c
|
||||
@@ -447,6 +447,12 @@ BOOL WINAPI DECLSPEC_HOTPATCH VirtualFree( void *addr, SIZE_T size, DWORD type )
|
||||
*/
|
||||
BOOL WINAPI DECLSPEC_HOTPATCH VirtualFreeEx( HANDLE process, void *addr, SIZE_T size, DWORD type )
|
||||
{
|
||||
+ if (type == MEM_RELEASE && size)
|
||||
+ {
|
||||
+ WARN( "Trying to release memory with specified size.\n" );
|
||||
+ SetLastError( ERROR_INVALID_PARAMETER );
|
||||
+ return FALSE;
|
||||
+ }
|
||||
return set_ntstatus( NtFreeVirtualMemory( process, &addr, &size, type ));
|
||||
}
|
||||
|
||||
--
|
||||
2.38.1
|
||||
|
@ -1,117 +0,0 @@
|
||||
From 22dc17764c3b231ebd226e479686a00c7aaaf01a Mon Sep 17 00:00:00 2001
|
||||
From: Paul Gofman <pgofman@codeweavers.com>
|
||||
Date: Fri, 11 Nov 2022 18:12:47 -0600
|
||||
Subject: [PATCH] ntdll: Fix size validation in NtFreeVirtualMemory().
|
||||
|
||||
---
|
||||
dlls/ntdll/tests/virtual.c | 16 ++++++++--------
|
||||
dlls/ntdll/unix/virtual.c | 26 ++++++++++++++++++--------
|
||||
2 files changed, 26 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c
|
||||
index 8e94566fb7f..81e9bd0bda3 100644
|
||||
--- a/dlls/ntdll/tests/virtual.c
|
||||
+++ b/dlls/ntdll/tests/virtual.c
|
||||
@@ -1659,12 +1659,12 @@ static void test_NtFreeVirtualMemory(void)
|
||||
|
||||
size = 0x11000;
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), &addr1, &size, MEM_RELEASE);
|
||||
- todo_wine ok(status == STATUS_UNABLE_TO_FREE_VM, "Unexpected status %08lx.\n", status);
|
||||
+ ok(status == STATUS_UNABLE_TO_FREE_VM, "Unexpected status %08lx.\n", status);
|
||||
|
||||
addr = (char *)addr1 + 0x1001;
|
||||
size = 0xffff;
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), &addr, &size, MEM_RELEASE);
|
||||
- todo_wine ok(status == STATUS_UNABLE_TO_FREE_VM, "Unexpected status %08lx.\n", status);
|
||||
+ ok(status == STATUS_UNABLE_TO_FREE_VM, "Unexpected status %08lx.\n", status);
|
||||
ok(size == 0xffff, "Unexpected size %p.\n", (void *)size);
|
||||
ok(addr == (char *)addr1 + 0x1001, "Got addr %p, addr1 %p.\n", addr, addr1);
|
||||
|
||||
@@ -1674,16 +1674,16 @@ static void test_NtFreeVirtualMemory(void)
|
||||
todo_wine ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
|
||||
*(volatile char *)addr1 = 1;
|
||||
*((volatile char *)addr1 + 0x2000) = 1;
|
||||
- todo_wine ok(size == 0x1000, "Unexpected size %p.\n", (void *)size);
|
||||
- todo_wine ok(addr == (char *)addr1 + 0x1000, "Got addr %p, addr1 %p.\n", addr, addr1);
|
||||
+ ok(size == 0x1000, "Unexpected size %p.\n", (void *)size);
|
||||
+ ok(addr == (char *)addr1 + 0x1000, "Got addr %p, addr1 %p.\n", addr, addr1);
|
||||
|
||||
size = 0xfff;
|
||||
addr = (char *)addr1 + 1;
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), &addr, &size, MEM_RELEASE);
|
||||
todo_wine ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
|
||||
*((volatile char *)addr1 + 0x2000) = 1;
|
||||
- todo_wine ok(size == 0x1000, "Unexpected size %p.\n", (void *)size);
|
||||
- todo_wine ok(addr == addr1, "Got addr %p, addr1 %p.\n", addr, addr1);
|
||||
+ ok(size == 0x1000, "Unexpected size %p.\n", (void *)size);
|
||||
+ ok(addr == addr1, "Got addr %p, addr1 %p.\n", addr, addr1);
|
||||
|
||||
size = 0x1000;
|
||||
addr = addr1;
|
||||
@@ -1703,12 +1703,12 @@ static void test_NtFreeVirtualMemory(void)
|
||||
size = 0;
|
||||
addr = (char *)addr1 + 0x1000;
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), &addr, &size, MEM_RELEASE);
|
||||
- todo_wine ok(status == STATUS_MEMORY_NOT_ALLOCATED, "Unexpected status %08lx.\n", status);
|
||||
+ ok(status == STATUS_MEMORY_NOT_ALLOCATED, "Unexpected status %08lx.\n", status);
|
||||
|
||||
size = 0x1000;
|
||||
addr = (char *)addr1 + 0x1000;
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), &addr, &size, MEM_DECOMMIT);
|
||||
- todo_wine ok(status == STATUS_MEMORY_NOT_ALLOCATED, "Unexpected status %08lx.\n", status);
|
||||
+ ok(status == STATUS_MEMORY_NOT_ALLOCATED, "Unexpected status %08lx.\n", status);
|
||||
|
||||
size = 0;
|
||||
addr = (char *)addr1 + 0x2000;
|
||||
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
|
||||
index 24d5a4e2da8..4cb0f349ffc 100644
|
||||
--- a/dlls/ntdll/unix/virtual.c
|
||||
+++ b/dlls/ntdll/unix/virtual.c
|
||||
@@ -4127,26 +4127,36 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si
|
||||
if (addr == (void *)1 && !size && type == MEM_RELEASE) virtual_release_address_space();
|
||||
else status = STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
- else if (!(view = find_view( base, size )) || !is_view_valloc( view ))
|
||||
- {
|
||||
- status = STATUS_INVALID_PARAMETER;
|
||||
- }
|
||||
+ else if (!(view = find_view( base, 0 ))) status = STATUS_MEMORY_NOT_ALLOCATED;
|
||||
+ else if (!is_view_valloc( view )) status = STATUS_INVALID_PARAMETER;
|
||||
else if (type == MEM_RELEASE)
|
||||
{
|
||||
/* Free the pages */
|
||||
|
||||
- if (size) status = STATUS_INVALID_PARAMETER;
|
||||
- else if (base != view->base) status = STATUS_FREE_VM_NOT_AT_BASE;
|
||||
+ if (size && (char *)view->base + view->size - base < size) status = STATUS_UNABLE_TO_FREE_VM;
|
||||
+ else if (!size && base != view->base) status = STATUS_FREE_VM_NOT_AT_BASE;
|
||||
else
|
||||
{
|
||||
+ if (!size) size = view->size;
|
||||
+
|
||||
+ if (size == view->size)
|
||||
+ {
|
||||
+ assert( base == view->base );
|
||||
+ delete_view( view );
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ FIXME( "Parial view release is not supported.\n" );
|
||||
+ status = STATUS_INVALID_PARAMETER;
|
||||
+ }
|
||||
*addr_ptr = base;
|
||||
- *size_ptr = view->size;
|
||||
- delete_view( view );
|
||||
+ *size_ptr = size;
|
||||
}
|
||||
}
|
||||
else if (type == MEM_DECOMMIT)
|
||||
{
|
||||
if (!size && base != view->base) status = STATUS_FREE_VM_NOT_AT_BASE;
|
||||
+ else if (base - (char *)view->base + size > view->size) status = STATUS_UNABLE_TO_FREE_VM;
|
||||
else status = decommit_pages( view, base - (char *)view->base, size );
|
||||
if (status == STATUS_SUCCESS)
|
||||
{
|
||||
--
|
||||
2.38.1
|
||||
|
@ -1,80 +0,0 @@
|
||||
From 6a2f524736ad25b89af90a74eedfa2f2b0f178e6 Mon Sep 17 00:00:00 2001
|
||||
From: Paul Gofman <pgofman@codeweavers.com>
|
||||
Date: Fri, 11 Nov 2022 18:30:20 -0600
|
||||
Subject: [PATCH] ntdll: Fully support unaligned views in free ranges
|
||||
management.
|
||||
|
||||
---
|
||||
dlls/ntdll/unix/virtual.c | 40 ++++++++++++++++++++-------------------
|
||||
1 file changed, 21 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
|
||||
index 847cfd750f3..cfa69d8d7f5 100644
|
||||
--- a/dlls/ntdll/unix/virtual.c
|
||||
+++ b/dlls/ntdll/unix/virtual.c
|
||||
@@ -742,17 +742,19 @@ static void free_ranges_insert_view( struct file_view *view )
|
||||
assert( range != free_ranges_end );
|
||||
assert( range->end > view_base || next != free_ranges_end );
|
||||
|
||||
- /* this happens because AT_ROUND_TO_PAGE was used with NtMapViewOfSection to force 4kB aligned mapping. */
|
||||
- if ((range->end > view_base && range->base >= view_end) ||
|
||||
- (range->end == view_base && next->base >= view_end))
|
||||
- {
|
||||
- /* on Win64, assert that it's correctly aligned so we're not going to be in trouble later */
|
||||
-#ifdef _WIN64
|
||||
- assert( view->base == view_base );
|
||||
-#endif
|
||||
- WARN( "range %p - %p is already mapped\n", view_base, view_end );
|
||||
+ /* Free ranges addresses are aligned at granularity_mask while the views may be not. */
|
||||
+
|
||||
+ if (range->base > view_base)
|
||||
+ view_base = range->base;
|
||||
+ if (range->end < view_end)
|
||||
+ view_end = range->end;
|
||||
+ if (range->end == view_base && next->base >= view_end)
|
||||
+ view_end = view_base;
|
||||
+
|
||||
+ TRACE( "%p - %p, aligned %p - %p.\n", view->base, (char *)view->base + view->size, view_base, view_end );
|
||||
+
|
||||
+ if (view_end <= view_base)
|
||||
return;
|
||||
- }
|
||||
|
||||
/* this should never happen */
|
||||
if (range->base > view_base || range->end < view_end)
|
||||
@@ -802,9 +804,7 @@ static void free_ranges_remove_view( struct file_view *view )
|
||||
struct range_entry *range = free_ranges_lower_bound( view_base );
|
||||
struct range_entry *next = range + 1;
|
||||
|
||||
- /* It's possible to use AT_ROUND_TO_PAGE on 32bit with NtMapViewOfSection to force 4kB alignment,
|
||||
- * and this breaks our assumptions. Look at the views around to check if the range is still in use. */
|
||||
-#ifndef _WIN64
|
||||
+ /* Free ranges addresses are aligned at granularity_mask while the views may be not. */
|
||||
struct file_view *prev_view = RB_ENTRY_VALUE( rb_prev( &view->entry ), struct file_view, entry );
|
||||
struct file_view *next_view = RB_ENTRY_VALUE( rb_next( &view->entry ), struct file_view, entry );
|
||||
void *prev_view_base = prev_view ? ROUND_ADDR( prev_view->base, granularity_mask ) : NULL;
|
||||
@@ -812,13 +812,15 @@ static void free_ranges_remove_view( struct file_view *view )
|
||||
void *next_view_base = next_view ? ROUND_ADDR( next_view->base, granularity_mask ) : NULL;
|
||||
void *next_view_end = next_view ? ROUND_ADDR( (char *)next_view->base + next_view->size + granularity_mask, granularity_mask ) : NULL;
|
||||
|
||||
- if ((prev_view_base < view_end && prev_view_end > view_base) ||
|
||||
- (next_view_base < view_end && next_view_end > view_base))
|
||||
- {
|
||||
- WARN( "range %p - %p is still mapped\n", view_base, view_end );
|
||||
+ if (prev_view_end && prev_view_end > view_base && prev_view_base < view_end)
|
||||
+ view_base = prev_view_end;
|
||||
+ if (next_view_base && next_view_base < view_end && next_view_end > view_base)
|
||||
+ view_end = next_view_base;
|
||||
+
|
||||
+ TRACE( "%p - %p, aligned %p - %p.\n", view->base, (char *)view->base + view->size, view_base, view_end );
|
||||
+
|
||||
+ if (view_end <= view_base)
|
||||
return;
|
||||
- }
|
||||
-#endif
|
||||
|
||||
/* free_ranges initial value is such that the view is either inside range or before another one. */
|
||||
assert( range != free_ranges_end );
|
||||
--
|
||||
2.40.1
|
||||
|
@ -1,85 +0,0 @@
|
||||
From e1f80e94e43d910a3d2b3bc5708a78507b11f4f5 Mon Sep 17 00:00:00 2001
|
||||
From: Paul Gofman <pgofman@codeweavers.com>
|
||||
Date: Fri, 11 Nov 2022 18:37:43 -0600
|
||||
Subject: [PATCH] ntdll: Factor out some view manipulation functions.
|
||||
|
||||
---
|
||||
dlls/ntdll/unix/virtual.c | 47 +++++++++++++++++++++++++++++++++------
|
||||
1 file changed, 40 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
|
||||
index cacde37e2e4..2dc66624ffc 100644
|
||||
--- a/dlls/ntdll/unix/virtual.c
|
||||
+++ b/dlls/ntdll/unix/virtual.c
|
||||
@@ -1593,6 +1593,31 @@ static struct file_view *alloc_view(void)
|
||||
}
|
||||
|
||||
|
||||
+/***********************************************************************
|
||||
+ * free_view
|
||||
+ *
|
||||
+ * Free memory for view structure. virtual_mutex must be held by caller.
|
||||
+ */
|
||||
+static void free_view( struct file_view *view )
|
||||
+{
|
||||
+ *(struct file_view **)view = next_free_view;
|
||||
+ next_free_view = view;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/***********************************************************************
|
||||
+ * unregister_view
|
||||
+ *
|
||||
+ * Remove view from the tree and update free ranges. virtual_mutex must be held by caller.
|
||||
+ */
|
||||
+static void unregister_view( struct file_view *view )
|
||||
+{
|
||||
+ if (mmap_is_in_reserved_area( view->base, view->size ))
|
||||
+ free_ranges_remove_view( view );
|
||||
+ wine_rb_remove( &views_tree, &view->entry );
|
||||
+}
|
||||
+
|
||||
+
|
||||
/***********************************************************************
|
||||
* delete_view
|
||||
*
|
||||
@@ -1603,11 +1628,21 @@ static void delete_view( struct file_view *view ) /* [in] View */
|
||||
if (!(view->protect & VPROT_SYSTEM)) unmap_area( view->base, view->size );
|
||||
set_page_vprot( view->base, view->size, 0 );
|
||||
if (arm64ec_map) clear_arm64ec_range( view->base, view->size );
|
||||
+ unregister_view( view );
|
||||
+ free_view( view );
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/***********************************************************************
|
||||
+ * register_view
|
||||
+ *
|
||||
+ * Add view to the tree and update free ranges. virtual_mutex must be held by caller.
|
||||
+ */
|
||||
+static void register_view( struct file_view *view )
|
||||
+{
|
||||
+ wine_rb_put( &views_tree, view->base, &view->entry );
|
||||
if (mmap_is_in_reserved_area( view->base, view->size ))
|
||||
- free_ranges_remove_view( view );
|
||||
- wine_rb_remove( &views_tree, &view->entry );
|
||||
- *(struct file_view **)view = next_free_view;
|
||||
- next_free_view = view;
|
||||
+ free_ranges_insert_view( view );
|
||||
}
|
||||
|
||||
|
||||
@@ -1651,9 +1686,7 @@ static NTSTATUS create_view( struct file_view **view_ret, void *base, size_t siz
|
||||
view->protect = vprot;
|
||||
set_page_vprot( base, size, vprot );
|
||||
|
||||
- wine_rb_put( &views_tree, view->base, &view->entry );
|
||||
- if (mmap_is_in_reserved_area( view->base, view->size ))
|
||||
- free_ranges_insert_view( view );
|
||||
+ register_view( view );
|
||||
|
||||
*view_ret = view;
|
||||
|
||||
--
|
||||
2.40.1
|
||||
|
@ -1,123 +0,0 @@
|
||||
From 261ba5e0003f13c83f9f08e5b3931862586f46d3 Mon Sep 17 00:00:00 2001
|
||||
From: Paul Gofman <pgofman@codeweavers.com>
|
||||
Date: Fri, 11 Nov 2022 18:41:50 -0600
|
||||
Subject: [PATCH] ntdll: Support partial view release in NtFreeVirtualMemory().
|
||||
|
||||
---
|
||||
dlls/ntdll/tests/virtual.c | 14 ++++++-------
|
||||
dlls/ntdll/unix/virtual.c | 42 ++++++++++++++++++++++++++++++++++++--
|
||||
2 files changed, 47 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c
|
||||
index 81e9bd0bda3..0dccb35bd27 100644
|
||||
--- a/dlls/ntdll/tests/virtual.c
|
||||
+++ b/dlls/ntdll/tests/virtual.c
|
||||
@@ -1671,7 +1671,7 @@ static void test_NtFreeVirtualMemory(void)
|
||||
size = 0xfff;
|
||||
addr = (char *)addr1 + 0x1001;
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), &addr, &size, MEM_RELEASE);
|
||||
- todo_wine ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
|
||||
+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
|
||||
*(volatile char *)addr1 = 1;
|
||||
*((volatile char *)addr1 + 0x2000) = 1;
|
||||
ok(size == 0x1000, "Unexpected size %p.\n", (void *)size);
|
||||
@@ -1680,7 +1680,7 @@ static void test_NtFreeVirtualMemory(void)
|
||||
size = 0xfff;
|
||||
addr = (char *)addr1 + 1;
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), &addr, &size, MEM_RELEASE);
|
||||
- todo_wine ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
|
||||
+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
|
||||
*((volatile char *)addr1 + 0x2000) = 1;
|
||||
ok(size == 0x1000, "Unexpected size %p.\n", (void *)size);
|
||||
ok(addr == addr1, "Got addr %p, addr1 %p.\n", addr, addr1);
|
||||
@@ -1688,17 +1688,17 @@ static void test_NtFreeVirtualMemory(void)
|
||||
size = 0x1000;
|
||||
addr = addr1;
|
||||
status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr, 0, &size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
||||
- todo_wine ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
|
||||
+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
|
||||
ok(addr == addr1, "Unexpected addr %p, addr1 %p.\n", addr, addr1);
|
||||
ok(size == 0x1000, "Unexpected size %p.\n", (void *)size);
|
||||
|
||||
size = 0x10000;
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), &addr1, &size, MEM_DECOMMIT);
|
||||
- todo_wine ok(status == STATUS_UNABLE_TO_FREE_VM, "Unexpected status %08lx.\n", status);
|
||||
+ ok(status == STATUS_UNABLE_TO_FREE_VM, "Unexpected status %08lx.\n", status);
|
||||
|
||||
size = 0x10000;
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), &addr1, &size, MEM_RELEASE);
|
||||
- todo_wine ok(status == STATUS_UNABLE_TO_FREE_VM, "Unexpected status %08lx.\n", status);
|
||||
+ ok(status == STATUS_UNABLE_TO_FREE_VM, "Unexpected status %08lx.\n", status);
|
||||
|
||||
size = 0;
|
||||
addr = (char *)addr1 + 0x1000;
|
||||
@@ -1713,11 +1713,11 @@ static void test_NtFreeVirtualMemory(void)
|
||||
size = 0;
|
||||
addr = (char *)addr1 + 0x2000;
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), &addr, &size, MEM_RELEASE);
|
||||
- todo_wine ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
|
||||
+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
|
||||
|
||||
size = 0x1000;
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), &addr1, &size, MEM_RELEASE);
|
||||
- todo_wine ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
|
||||
+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
|
||||
}
|
||||
|
||||
static void test_prefetch(void)
|
||||
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
|
||||
index bdc410472ec..5775287cd19 100644
|
||||
--- a/dlls/ntdll/unix/virtual.c
|
||||
+++ b/dlls/ntdll/unix/virtual.c
|
||||
@@ -4180,8 +4180,46 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si
|
||||
}
|
||||
else
|
||||
{
|
||||
- FIXME( "Parial view release is not supported.\n" );
|
||||
- status = STATUS_INVALID_PARAMETER;
|
||||
+ struct file_view *new_view = NULL;
|
||||
+
|
||||
+ if (view->base != base && base + size != (char *)view->base + view->size
|
||||
+ && !(new_view = alloc_view()))
|
||||
+ {
|
||||
+ ERR( "out of memory for %p-%p\n", base, (char *)base + size );
|
||||
+ return STATUS_NO_MEMORY;
|
||||
+ }
|
||||
+ unregister_view( view );
|
||||
+
|
||||
+ if (new_view)
|
||||
+ {
|
||||
+ new_view->base = base + size;
|
||||
+ new_view->size = (char *)view->base + view->size - (char *)new_view->base;
|
||||
+ new_view->protect = view->protect;
|
||||
+
|
||||
+ view->size = base - (char *)view->base;
|
||||
+ register_view( view );
|
||||
+ register_view( new_view );
|
||||
+
|
||||
+ VIRTUAL_DEBUG_DUMP_VIEW( view );
|
||||
+ VIRTUAL_DEBUG_DUMP_VIEW( new_view );
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ if (view->base == base)
|
||||
+ {
|
||||
+ view->base = base + size;
|
||||
+ view->size -= size;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ view->size = base - (char *)view->base;
|
||||
+ }
|
||||
+ register_view( view );
|
||||
+ VIRTUAL_DEBUG_DUMP_VIEW( view );
|
||||
+ }
|
||||
+
|
||||
+ set_page_vprot( base, size, 0 );
|
||||
+ unmap_area( base, size );
|
||||
}
|
||||
*addr_ptr = base;
|
||||
*size_ptr = size;
|
||||
--
|
||||
2.38.1
|
||||
|
@ -1,99 +0,0 @@
|
||||
From aa5b49a7893ddb97b11251c65506d242e2e160f9 Mon Sep 17 00:00:00 2001
|
||||
From: Paul Gofman <pgofman@codeweavers.com>
|
||||
Date: Tue, 4 Oct 2022 20:26:39 -0500
|
||||
Subject: [PATCH] ntdll: Add logging for free ranges.
|
||||
|
||||
---
|
||||
dlls/ntdll/unix/virtual.c | 25 +++++++++++++++++++++----
|
||||
1 file changed, 21 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
|
||||
index 5775287cd19..7142d2adf79 100644
|
||||
--- a/dlls/ntdll/unix/virtual.c
|
||||
+++ b/dlls/ntdll/unix/virtual.c
|
||||
@@ -76,6 +76,7 @@
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(virtual);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(module);
|
||||
+WINE_DECLARE_DEBUG_CHANNEL(virtual_ranges);
|
||||
|
||||
struct preload_info
|
||||
{
|
||||
@@ -186,6 +187,7 @@ static struct list teb_list = LIST_INIT( teb_list );
|
||||
#define ROUND_SIZE(addr,size) (((SIZE_T)(size) + ((UINT_PTR)(addr) & page_mask) + page_mask) & ~page_mask)
|
||||
|
||||
#define VIRTUAL_DEBUG_DUMP_VIEW(view) do { if (TRACE_ON(virtual)) dump_view(view); } while (0)
|
||||
+#define VIRTUAL_DEBUG_DUMP_RANGES() do { if (TRACE_ON(virtual_ranges)) dump_free_ranges(); } while (0)
|
||||
|
||||
#ifndef MAP_NORESERVE
|
||||
#define MAP_NORESERVE 0
|
||||
@@ -732,6 +734,12 @@ static struct range_entry *free_ranges_lower_bound( void *addr )
|
||||
return begin;
|
||||
}
|
||||
|
||||
+static void dump_free_ranges(void)
|
||||
+{
|
||||
+ struct range_entry *r;
|
||||
+ for (r = free_ranges; r != free_ranges_end; ++r)
|
||||
+ TRACE_(virtual_ranges)("%p - %p.\n", r->base, r->end);
|
||||
+}
|
||||
|
||||
/***********************************************************************
|
||||
* free_ranges_insert_view
|
||||
@@ -761,7 +769,10 @@ static void free_ranges_insert_view( struct file_view *view )
|
||||
TRACE( "%p - %p, aligned %p - %p.\n", view->base, (char *)view->base + view->size, view_base, view_end );
|
||||
|
||||
if (view_end <= view_base)
|
||||
+ {
|
||||
+ VIRTUAL_DEBUG_DUMP_RANGES();
|
||||
return;
|
||||
+ }
|
||||
|
||||
/* this should never happen */
|
||||
if (range->base > view_base || range->end < view_end)
|
||||
@@ -789,16 +800,19 @@ static void free_ranges_insert_view( struct file_view *view )
|
||||
else
|
||||
range->base = view_end;
|
||||
|
||||
- if (range->base < range->end) return;
|
||||
-
|
||||
+ if (range->base < range->end)
|
||||
+ {
|
||||
+ VIRTUAL_DEBUG_DUMP_RANGES();
|
||||
+ return;
|
||||
+ }
|
||||
/* and possibly remove it if it's now empty */
|
||||
memmove( range, next, (free_ranges_end - next) * sizeof(struct range_entry) );
|
||||
free_ranges_end -= 1;
|
||||
assert( free_ranges_end - free_ranges > 0 );
|
||||
}
|
||||
+ VIRTUAL_DEBUG_DUMP_RANGES();
|
||||
}
|
||||
|
||||
-
|
||||
/***********************************************************************
|
||||
* free_ranges_remove_view
|
||||
*
|
||||
@@ -827,8 +841,10 @@ static void free_ranges_remove_view( struct file_view *view )
|
||||
TRACE( "%p - %p, aligned %p - %p.\n", view->base, (char *)view->base + view->size, view_base, view_end );
|
||||
|
||||
if (view_end <= view_base)
|
||||
+ {
|
||||
+ VIRTUAL_DEBUG_DUMP_RANGES();
|
||||
return;
|
||||
-
|
||||
+ }
|
||||
/* free_ranges initial value is such that the view is either inside range or before another one. */
|
||||
assert( range != free_ranges_end );
|
||||
assert( range->end > view_base || next != free_ranges_end );
|
||||
@@ -870,6 +886,7 @@ static void free_ranges_remove_view( struct file_view *view )
|
||||
range->base = view_base;
|
||||
range->end = view_end;
|
||||
}
|
||||
+ VIRTUAL_DEBUG_DUMP_RANGES();
|
||||
}
|
||||
|
||||
|
||||
--
|
||||
2.38.1
|
||||
|
@ -2,3 +2,4 @@
|
||||
# and "Halo Infinite". Neither have been tested with upstream Wine. Added to
|
||||
# wine-staging primarly because ntdll-ForceBottomUpAlloc touches the same area.
|
||||
Depends: ntdll-WRITECOPY
|
||||
Disabled: True
|
||||
|
@ -1 +1 @@
|
||||
d2789ef0678619d7c56a9e0c1aaa06f582a41ee3
|
||||
19eab9c0e59201277f359d55ee5747383e014e87
|
||||
|
Loading…
Reference in New Issue
Block a user