Compare commits

...

27 Commits

Author SHA1 Message Date
Alistair Leslie-Hughes
2dcacd0dbf Release v8.9.1 2023-05-29 07:26:53 +10:00
Alistair Leslie-Hughes
1039396c8e Updated vkd3d-latest patchset
Fix the mingw mac build.
2023-05-28 21:36:15 +10:00
Alistair Leslie-Hughes
f8cc3baab3 Release v8.9 2023-05-28 14:38:27 +10:00
Alistair Leslie-Hughes
7665942477 Added vkd3d-latest patchset 2023-05-28 11:14:22 +10:00
Alistair Leslie-Hughes
0cd181d0ce Rebase against c293cd781fb4b330b7d93171501134f86a5138b8. 2023-05-26 09:22:33 +10:00
Alistair Leslie-Hughes
a580edefe1 Rebase against e10da7ab2e3d151c8347802600862aa608672f6f. 2023-05-25 10:07:30 +10:00
Alistair Leslie-Hughes
fe6cfefe64 Add release script 2023-05-24 12:07:27 +10:00
Alistair Leslie-Hughes
6900845545 Rebase against f266dc094a9b4fbe95792ed706891609901834e3. 2023-05-24 12:06:20 +10:00
Paul Gofman
3e3ebf5cfc Update and reenable ntdll-ForceBottomUpAlloc. 2023-05-19 13:48:16 -06:00
Paul Gofman
f48794a9ce Update and reenable ntdll-Placeholders. 2023-05-19 13:45:49 -06:00
Alistair Leslie-Hughes
27397d1764 Rebase against d54e7cd51db7d3def7dab549a547b1b6bf7573e2. 2023-05-16 10:07:12 +10:00
Alistair Leslie-Hughes
ca7fc8fb51 Release v8.8 2023-05-15 07:49:40 +10:00
Alistair Leslie-Hughes
cc0df4cd1b Rebase against 5662d85e0e95a2715ab3b81c25c89121fc8db34d. 2023-05-13 12:38:27 +10:00
Alistair Leslie-Hughes
8791ceb20d Rebase against 19eab9c0e59201277f359d55ee5747383e014e87. 2023-05-13 07:41:59 +10:00
Alistair Leslie-Hughes
09808df495 Rebase against d2789ef0678619d7c56a9e0c1aaa06f582a41ee3. 2023-05-11 09:29:15 +10:00
Alistair Leslie-Hughes
9c995c8d8e Rebase against de034b36b7fbad0edae0a2700376273c74e48ac6. 2023-05-10 09:48:48 +10:00
Alistair Leslie-Hughes
b72829659d Rebase against 222d20a585c454cb591e3dc539f3bd52427ea30c. 2023-05-07 10:32:15 +10:00
Alistair Leslie-Hughes
88ffa2bda8 Rebase against bd89ab3040e30c11b34a95072d88f635ade03bdc. 2023-05-04 09:58:31 +10:00
Zebediah Figura
2524bc48fe Rebase against 0b9620266f08d57c2db41b934a77b6ce4a94aeda. 2023-05-02 18:03:24 -05:00
Alistair Leslie-Hughes
00ec1171cc Release v8.7 2023-04-29 18:38:56 +10:00
Alistair Leslie-Hughes
277ed0c6fb Rebase against 619e34500fc43f1103fddd91e86d581660d2ae4b. 2023-04-27 09:40:06 +10:00
Alistair Leslie-Hughes
0c2c469c7b Rebase against a500bb72f05058c985511ff35f191565f45cd6c0. 2023-04-26 11:01:51 +10:00
Alistair Leslie-Hughes
7f36a96808 Updated wined3d-WINED3DFMT_B8G8R8X8_UNORM patchset
Fixes: https://bugs.winehq.org/show_bug.cgi?id=54868
2023-04-20 07:28:44 +10:00
Zebediah Figura
566a2bcdfd Rebase against 9e99c6f66d236101a084b6a3a24c98b5c8677fe5. 2023-04-18 17:32:53 -05:00
Zebediah Figura
4eb322dc41 riched20-IText_Interface: Remove patch 0010 silencing FIXMEs.
If this is desired, it can be easily rewritten and submitted upstream.
2023-04-16 16:19:00 -05:00
Zebediah Figura
182d6c76e3 wined3d-Silence_FIXMEs: Remove patch set.
This would be desirable if we had a known application that needed it, but we don't. If the application ever resurfaces, it will be easy to rewrite and fix upstream.
2023-04-16 16:17:30 -05:00
Zebediah Figura
3e931ce80f ddraw-Silence_FIXMEs: Remove patch set.
This would be desirable if we had a known application that needed it, but we don't. If the application ever resurfaces, it will be easy to rewrite and fix upstream.
2023-04-16 16:17:14 -05:00
66 changed files with 30440 additions and 3185 deletions

View File

@@ -1,29 +0,0 @@
From ff117878cb3a0c74a50355ca64ac36c5fe6cee67 Mon Sep 17 00:00:00 2001
From: Christian Costa <titan.costa@gmail.com>
Date: Fri, 10 Mar 2017 22:07:37 +0100
Subject: ddraw: Silence noisy FIXME about unimplemented
D3DPROCESSVERTICES_UPDATEEXTENTS.
---
dlls/ddraw/executebuffer.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/dlls/ddraw/executebuffer.c b/dlls/ddraw/executebuffer.c
index 393c52c1e2..9b64c687d3 100644
--- a/dlls/ddraw/executebuffer.c
+++ b/dlls/ddraw/executebuffer.c
@@ -302,7 +302,10 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
ci->wStart, ci->wDest, ci->dwCount, ci->dwFlags);
if (ci->dwFlags & D3DPROCESSVERTICES_UPDATEEXTENTS)
- FIXME("D3DPROCESSVERTICES_UPDATEEXTENTS not implemented.\n");
+ {
+ static int once;
+ if (!once++) FIXME("D3DPROCESSVERTICES_UPDATEEXTENTS not implemented.\n");
+ }
if (ci->dwFlags & D3DPROCESSVERTICES_NOCOLOR)
FIXME("D3DPROCESSVERTICES_NOCOLOR not implemented.\n");
--
2.11.0

View File

@@ -1,4 +1,4 @@
From f4e3bbf1a91a5a99d703d3fee9a81a5c5089ab79 Mon Sep 17 00:00:00 2001
From 5bc649eecc617214650f5af105f3ae6b6fae5a11 Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Fri, 27 Mar 2015 20:48:19 +0000
Subject: [PATCH] dsound: Support getting and setting EAX buffer properties.
@@ -11,12 +11,12 @@ Subject: [PATCH] dsound: Support getting and setting EAX buffer properties.
4 files changed, 72 insertions(+)
diff --git a/dlls/dsound/buffer.c b/dlls/dsound/buffer.c
index b7a0fb26c4b..0aff7c96842 100644
index 5c8c495bfe4..ede6d9f1ba1 100644
--- a/dlls/dsound/buffer.c
+++ b/dlls/dsound/buffer.c
@@ -1127,6 +1127,8 @@ HRESULT secondarybuffer_create(DirectSoundDevice *device, const DSBUFFERDESC *ds
return DSERR_OUTOFMEMORY;
}
@@ -1107,6 +1107,8 @@ HRESULT secondarybuffer_create(DirectSoundDevice *device, const DSBUFFERDESC *ds
dsb->sec_mixpos = 0;
dsb->state = STATE_STOPPED;
+ dsb->eax.reverb_mix = EAX_REVERBMIX_USEDISTANCE;
+
@@ -39,7 +39,7 @@ index c90d82d9a3f..2ee83b94ff9 100644
}
#endif
diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h
index a11379f0f88..9b537ad80a5 100644
index 021844c414d..7a89b047b42 100644
--- a/dlls/dsound/dsound_private.h
+++ b/dlls/dsound/dsound_private.h
@@ -177,6 +177,8 @@ struct IDirectSoundBufferImpl
@@ -52,7 +52,7 @@ index a11379f0f88..9b537ad80a5 100644
};
diff --git a/dlls/dsound/eax.c b/dlls/dsound/eax.c
index cdd03becbee..3931681d295 100644
index 13471aec3a9..03b6e0a9813 100644
--- a/dlls/dsound/eax.c
+++ b/dlls/dsound/eax.c
@@ -178,6 +178,38 @@ HRESULT WINAPI EAX_Get(IDirectSoundBufferImpl *buf, REFGUID guidPropSet,
@@ -134,5 +134,5 @@ index cdd03becbee..3931681d295 100644
}
--
2.33.0
2.40.1

View File

@@ -1,4 +1,4 @@
From 42c58e406220e9351337b079ae44364fbc39365d Mon Sep 17 00:00:00 2001
From e484e3dc512eacc9708c245a9e64372428bc1875 Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Fri, 27 Mar 2015 20:58:37 +0000
Subject: [PATCH] dsound: Add EAX init and free stubs.
@@ -10,11 +10,11 @@ Subject: [PATCH] dsound: Add EAX init and free stubs.
3 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/dlls/dsound/buffer.c b/dlls/dsound/buffer.c
index 22b23c9f877..72e96765883 100644
index ede6d9f1ba1..309d632397a 100644
--- a/dlls/dsound/buffer.c
+++ b/dlls/dsound/buffer.c
@@ -1152,6 +1152,8 @@ HRESULT secondarybuffer_create(DirectSoundDevice *device, const DSBUFFERDESC *ds
DSOUND_RecalcVolPan(&(dsb->volpan));
@@ -1145,6 +1145,8 @@ HRESULT secondarybuffer_create(DirectSoundDevice *device, const DSBUFFERDESC *ds
}
InitializeSRWLock(&dsb->lock);
+ if (dsb->device->eax.using_eax)
@@ -22,7 +22,7 @@ index 22b23c9f877..72e96765883 100644
/* register buffer */
err = DirectSoundDevice_AddBuffer(device, dsb);
@@ -1193,6 +1195,8 @@ void secondarybuffer_destroy(IDirectSoundBufferImpl *This)
@@ -1186,6 +1188,8 @@ void secondarybuffer_destroy(IDirectSoundBufferImpl *This)
free(This->filters);
}
@@ -32,7 +32,7 @@ index 22b23c9f877..72e96765883 100644
free(This);
diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h
index 09566b28a12..703b5da8225 100644
index 7a89b047b42..c5e84f07763 100644
--- a/dlls/dsound/dsound_private.h
+++ b/dlls/dsound/dsound_private.h
@@ -240,6 +240,8 @@ HRESULT WINAPI EAX_Get(IDirectSoundBufferImpl *buf, REFGUID guidPropSet,
@@ -97,5 +97,5 @@ index 03b6e0a9813..91438efc335 100644
HRESULT WINAPI EAX_Get(IDirectSoundBufferImpl *buf, REFGUID guidPropSet,
--
2.39.2
2.40.1

View File

@@ -1 +1,2 @@
Fixes: Improve performance of bilinear bitmap scaling
Disabled: True

View File

@@ -1,4 +1,4 @@
From 4e5fabb55f5ef955074cdab6db875e6d32592c2d Mon Sep 17 00:00:00 2001
From 612c0266b7a8cec562f82f1a2aaf55cffc15f35e Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Wed, 21 Oct 2020 16:03:21 -0500
Subject: [PATCH] winegstreamer: Allow videoconvert to parallelize.
@@ -11,12 +11,12 @@ Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
1 file changed, 3 insertions(+)
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index 2fa87ac611b..d2f682df281 100644
index dfb3da9a4ab..2135dea456b 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -812,6 +812,9 @@ static void pad_added_cb(GstElement *element, GstPad *pad, gpointer user)
@@ -842,6 +842,9 @@ static bool stream_create_post_processing_elements(struct wg_parser_stream *stre
|| !append_element(parser->container, element, &first, &last))
goto out;
return false;
+ /* Let GStreamer choose a default number of threads. */
+ gst_util_set_object_arg(G_OBJECT(element), "n-threads", "0");

View File

@@ -1,35 +1,26 @@
From ca64589b2447f378651f19eb15672f27c2133493 Mon Sep 17 00:00:00 2001
From 7d0af0dc23f87241726af6f7c48f47df441503a6 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Fri, 19 Mar 2021 17:01:54 -0400
Subject: [PATCH] winegstreamer: Report streams backwards in media source.
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
---
dlls/winegstreamer/media_source.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
dlls/winegstreamer/media_source.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
index 1b57d8bfba8..4d2a29a6bc1 100644
index 335b617becd..e6117fd0090 100644
--- a/dlls/winegstreamer/media_source.c
+++ b/dlls/winegstreamer/media_source.c
@@ -1497,7 +1497,7 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
DWORD len;
char *str;
- IMFMediaStream_GetStreamDescriptor(&object->streams[i]->IMFMediaStream_iface, &descriptors[i]);
+ IMFMediaStream_GetStreamDescriptor(&object->streams[i]->IMFMediaStream_iface, &descriptors[object->stream_count - 1 - i]);
for (j = 0; j < ARRAY_SIZE(tags); ++j)
{
@@ -1510,7 +1510,7 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
@@ -1604,7 +1604,7 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
}
strW = malloc(len * sizeof(*strW));
if (MultiByteToWideChar(CP_UTF8, 0, str, -1, strW, len))
- IMFStreamDescriptor_SetString(descriptors[i], tags[j].mf_attr, strW);
+ IMFStreamDescriptor_SetString(descriptors[object->stream_count - 1 - i], tags[j].mf_attr, strW);
- IMFStreamDescriptor_SetString(object->descriptors[i], tags[j].mf_attr, strW);
+ IMFStreamDescriptor_SetString(object->descriptors[object->stream_count - 1 - i], tags[j].mf_attr, strW);
free(strW);
free(str);
}
--
2.40.0
2.40.1

View File

@@ -1 +1,2 @@
Fixes: [49692] Multiple applications need a Media Foundation media source implementation
Disabled: True

View File

@@ -1,4 +1,4 @@
From 5814a4b9c7d4dec027b0c2dd29822664aa56ada1 Mon Sep 17 00:00:00 2001
From 5a81a28605ec0b32b020c84032e3f4a35d0e4768 Mon Sep 17 00:00:00 2001
From: Paul Gofman <pgofman@codeweavers.com>
Date: Tue, 14 Jan 2020 21:39:23 +0300
Subject: [PATCH] ntdll: Increase step after failed map attempt in
@@ -9,10 +9,10 @@ Subject: [PATCH] ntdll: Increase step after failed map attempt in
1 file changed, 1 insertion(+)
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
index 84a4e331ad7..a63882023e6 100644
index 2e61e8ba22f..039007f6a9b 100644
--- a/dlls/ntdll/unix/virtual.c
+++ b/dlls/ntdll/unix/virtual.c
@@ -1327,6 +1327,7 @@ static void* try_map_free_area( void *base, void *end, ptrdiff_t step,
@@ -1336,6 +1336,7 @@ static void* try_map_free_area( void *base, void *end, ptrdiff_t step,
step == 0)
break;
start = (char *)start + step;
@@ -21,5 +21,5 @@ index 84a4e331ad7..a63882023e6 100644
return NULL;
--
2.38.1
2.40.1

View File

@@ -1,4 +1,4 @@
From b1e6d32e7dc3bac93419f3a573f509ee6e1177b2 Mon Sep 17 00:00:00 2001
From b7c39298824976bbbc8788b60aa4195f3815d3b9 Mon Sep 17 00:00:00 2001
From: Paul Gofman <pgofman@codeweavers.com>
Date: Thu, 23 Jul 2020 18:40:39 +0300
Subject: [PATCH] ntdll: Increase free ranges view block size on 64 bit.
@@ -8,10 +8,10 @@ Subject: [PATCH] ntdll: Increase free ranges view block size on 64 bit.
1 file changed, 4 insertions(+)
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
index a63882023e6..83909f57d4a 100644
index 039007f6a9b..82a0a91cf14 100644
--- a/dlls/ntdll/unix/virtual.c
+++ b/dlls/ntdll/unix/virtual.c
@@ -205,7 +205,11 @@ static BYTE *pages_vprot;
@@ -212,7 +212,11 @@ static BYTE *pages_vprot;
#endif
static struct file_view *view_block_start, *view_block_end, *next_free_view;
@@ -24,5 +24,5 @@ index a63882023e6..83909f57d4a 100644
static void *preload_reserve_end;
static BOOL force_exec_prot; /* whether to force PROT_EXEC on all PROT_READ mmaps */
--
2.38.1
2.40.1

View File

@@ -1,4 +1,4 @@
From c3252fd68ecdcc0186b4d284df1b36ea11ca7d7f Mon Sep 17 00:00:00 2001
From 5be3a73fdd9728f6280a2c0b790166c94309bf73 Mon Sep 17 00:00:00 2001
From: Paul Gofman <pgofman@codeweavers.com>
Date: Mon, 25 Nov 2019 12:19:20 +0300
Subject: [PATCH] ntdll: Force virtual memory allocation order.
@@ -16,10 +16,10 @@ Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46568
1 file changed, 227 insertions(+), 223 deletions(-)
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
index 83909f57d4a..4bce8f2f806 100644
index 13aa67c2d82..fd5bb86e6de 100644
--- a/dlls/ntdll/unix/virtual.c
+++ b/dlls/ntdll/unix/virtual.c
@@ -1266,44 +1266,15 @@ static struct file_view *find_view_range( const void *addr, size_t size )
@@ -1275,44 +1275,15 @@ static struct file_view *find_view_range( const void *addr, size_t size )
return NULL;
}
@@ -72,7 +72,7 @@ index 83909f57d4a..4bce8f2f806 100644
/***********************************************************************
* try_map_free_area
@@ -1337,110 +1308,6 @@ static void* try_map_free_area( void *base, void *end, ptrdiff_t step,
@@ -1346,110 +1317,6 @@ static void* try_map_free_area( void *base, void *end, ptrdiff_t step,
return NULL;
}
@@ -183,7 +183,7 @@ index 83909f57d4a..4bce8f2f806 100644
/***********************************************************************
* add_reserved_area
*
@@ -1608,8 +1475,7 @@ static void free_view( struct file_view *view )
@@ -1617,8 +1484,7 @@ static void free_view( struct file_view *view )
*/
static void unregister_view( struct file_view *view )
{
@@ -193,7 +193,7 @@ index 83909f57d4a..4bce8f2f806 100644
wine_rb_remove( &views_tree, &view->entry );
}
@@ -1636,8 +1502,7 @@ static void delete_view( struct file_view *view ) /* [in] View */
@@ -1646,8 +1512,7 @@ static void delete_view( struct file_view *view ) /* [in] View */
static void register_view( struct file_view *view )
{
wine_rb_put( &views_tree, view->base, &view->entry );
@@ -203,7 +203,7 @@ index 83909f57d4a..4bce8f2f806 100644
}
@@ -1906,55 +1771,229 @@ static inline void *unmap_extra_space( void *ptr, size_t total_size, size_t want
@@ -1916,55 +1781,229 @@ static inline void *unmap_extra_space( void *ptr, size_t total_size, size_t want
return ptr;
}
@@ -241,7 +241,10 @@ index 83909f57d4a..4bce8f2f806 100644
+
+ if (area->map_area_end <= (char *)start)
+ return 0;
+
- if (start < address_space_start) start = address_space_start;
- if (is_beyond_limit( start, size, alloc->limit )) end = alloc->limit;
- if (start >= end) return 0;
+ if ((ULONG_PTR)area->map_area_end < area->size)
+ return 1;
+
@@ -255,10 +258,7 @@ index 83909f57d4a..4bce8f2f806 100644
+ alloc_start, area->size, area->unix_prot )))
+ return 1;
+ }
- if (start < address_space_start) start = address_space_start;
- if (is_beyond_limit( start, size, alloc->limit )) end = alloc->limit;
- if (start >= end) return 0;
+
+ if (intersect_end - intersect_start >= area->size)
+ {
+ alloc_start = ROUND_ADDR( intersect_end - area->size, align_mask );
@@ -467,7 +467,7 @@ index 83909f57d4a..4bce8f2f806 100644
/***********************************************************************
* map_fixed_area
*
@@ -2019,6 +2058,8 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
@@ -2029,6 +2068,8 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
void *ptr;
NTSTATUS status;
@@ -475,9 +475,9 @@ index 83909f57d4a..4bce8f2f806 100644
+
if (alloc_type & MEM_REPLACE_PLACEHOLDER)
{
if ((*view_ret = find_view( base, 0 )))
@@ -2044,6 +2085,8 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
return STATUS_INVALID_PARAMETER;
struct file_view *view;
@@ -2046,6 +2087,8 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
return STATUS_SUCCESS;
}
+ if (!align_mask) align_mask = granularity_mask;
@@ -485,7 +485,7 @@ index 83909f57d4a..4bce8f2f806 100644
if (base)
{
if (is_beyond_limit( base, size, address_space_limit ))
@@ -2052,52 +2095,10 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
@@ -2056,52 +2099,10 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
if (status != STATUS_SUCCESS) return status;
ptr = base;
}
@@ -540,7 +540,7 @@ index 83909f57d4a..4bce8f2f806 100644
status = create_view( view_ret, ptr, size, vprot );
if (status != STATUS_SUCCESS) unmap_area( ptr, size );
return status;
@@ -2758,6 +2759,7 @@ static NTSTATUS virtual_map_section( HANDLE handle, PVOID *addr_ptr, ULONG_PTR z
@@ -3050,6 +3051,7 @@ static unsigned int virtual_map_section( HANDLE handle, PVOID *addr_ptr, ULONG_P
done:
server_leave_uninterrupted_section( &virtual_mutex, &sigset );
if (needs_close) close( unix_handle );
@@ -548,7 +548,7 @@ index 83909f57d4a..4bce8f2f806 100644
return res;
}
@@ -2826,6 +2828,7 @@ void virtual_init(void)
@@ -3118,6 +3120,7 @@ void virtual_init(void)
if (preload_reserve_start)
address_space_start = min( address_space_start, preload_reserve_start );
}
@@ -556,7 +556,7 @@ index 83909f57d4a..4bce8f2f806 100644
}
/* try to find space in a reserved area for the views and pages protection table */
@@ -5579,6 +5582,7 @@ NTSTATUS WINAPI NtWow64AllocateVirtualMemory64( HANDLE process, ULONG64 *ret, UL
@@ -5842,6 +5845,7 @@ NTSTATUS WINAPI NtWow64AllocateVirtualMemory64( HANDLE process, ULONG64 *ret, UL
*ret = (ULONG_PTR)base;
*size_ptr = size;
}
@@ -565,5 +565,5 @@ index 83909f57d4a..4bce8f2f806 100644
}
--
2.38.1
2.40.1

View File

@@ -1,25 +1,35 @@
From d29a79d8cca2220c838fbbea6ea81b9f73070ba5 Mon Sep 17 00:00:00 2001
From bd1c2ee8168bc923e3040af04ea3bebc8c021ea5 Mon Sep 17 00:00:00 2001
From: Paul Gofman <pgofman@codeweavers.com>
Date: Tue, 2 Jun 2020 21:06:33 +0300
Subject: [PATCH] ntdll: Exclude natively mapped areas from free areas list.
---
dlls/ntdll/unix/virtual.c | 118 ++++++++++++++++++++++++++++++++------
1 file changed, 100 insertions(+), 18 deletions(-)
dlls/ntdll/unix/virtual.c | 126 ++++++++++++++++++++++++++++++++------
1 file changed, 107 insertions(+), 19 deletions(-)
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
index 4bce8f2f806..3c1bf6edc30 100644
index b189ded181b..00569e5e24c 100644
--- a/dlls/ntdll/unix/virtual.c
+++ b/dlls/ntdll/unix/virtual.c
@@ -125,6 +125,7 @@ struct file_view
@@ -130,6 +130,7 @@ C_ASSERT( offsetof( struct file_view, entry ) == 0 );
#define VPROT_SYSTEM 0x0200 /* system view (underlying mmap not under our control) */
#define VPROT_PLACEHOLDER 0x0400
#define VPROT_FROMPLACEHOLDER 0x0800
#define VPROT_PLACEHOLDER 0x0400
#define VPROT_FREE_PLACEHOLDER 0x0800
+#define VPROT_NATIVE 0x1000
/* Conversion from VPROT_* to Win32 flags */
static const BYTE VIRTUAL_Win32Flags[16] =
@@ -1119,7 +1120,9 @@ static void dump_view( struct file_view *view )
@@ -184,6 +185,9 @@ static void *working_set_limit = (void *)0x7fff0000;
static UINT64 *arm64ec_map;
+static const ptrdiff_t max_try_map_step = 0x40000000;
+static BOOL increase_try_map_step = TRUE;
+
struct _KUSER_SHARED_DATA *user_shared_data = (void *)0x7ffe0000;
/* TEB allocation blocks */
@@ -1164,7 +1168,9 @@ static void dump_view( struct file_view *view )
BYTE prot = get_page_vprot( addr );
TRACE( "View: %p - %p", addr, addr + view->size - 1 );
@@ -28,9 +38,9 @@ index 4bce8f2f806..3c1bf6edc30 100644
+ TRACE(" (native)\n");
+ else if (view->protect & VPROT_SYSTEM)
TRACE( " (builtin image)\n" );
else if (view->protect & VPROT_PLACEHOLDER)
else if (view->protect & VPROT_FREE_PLACEHOLDER)
TRACE( " (placeholder)\n" );
@@ -1274,6 +1277,8 @@ struct alloc_area
@@ -1283,6 +1289,8 @@ struct alloc_area
int unix_prot;
BOOL top_down;
UINT_PTR align_mask;
@@ -39,7 +49,7 @@ index 4bce8f2f806..3c1bf6edc30 100644
};
/***********************************************************************
@@ -1282,21 +1287,28 @@ struct alloc_area
@@ -1291,27 +1299,35 @@ struct alloc_area
* Try mmaping some expected free memory region, eventually stepping and
* retrying inside it, and return where it actually succeeded, or NULL.
*/
@@ -73,7 +83,15 @@ index 4bce8f2f806..3c1bf6edc30 100644
if ((step > 0 && (char *)end - (char *)start < step) ||
(step < 0 && (char *)start - (char *)base < -step) ||
step == 0)
@@ -1797,9 +1809,9 @@ static int alloc_area_in_reserved_or_between_callback( void *start, SIZE_T size,
break;
start = (char *)start + step;
- step *= 2;
+ if (increase_try_map_step && llabs(step) < max_try_map_step)
+ step *= 2;
}
return NULL;
@@ -1807,9 +1823,9 @@ static int alloc_area_in_reserved_or_between_callback( void *start, SIZE_T size,
assert(intersect_start <= intersect_end);
if (area->map_area_end - intersect_end >= area->size)
{
@@ -86,7 +104,7 @@ index 4bce8f2f806..3c1bf6edc30 100644
return 1;
}
@@ -1838,8 +1850,8 @@ static int alloc_area_in_reserved_or_between_callback( void *start, SIZE_T size,
@@ -1848,8 +1864,8 @@ static int alloc_area_in_reserved_or_between_callback( void *start, SIZE_T size,
if (intersect_start - area->map_area_start >= area->size)
{
alloc_start = ROUND_ADDR( area->map_area_start + align_mask, align_mask );
@@ -97,7 +115,7 @@ index 4bce8f2f806..3c1bf6edc30 100644
return 1;
}
@@ -1900,8 +1912,7 @@ static void *alloc_free_area_in_range( struct alloc_area *area, char *base, char
@@ -1910,8 +1926,7 @@ static void *alloc_free_area_in_range( struct alloc_area *area, char *base, char
if (start >= area->map_area_end || start < area->map_area_start)
return NULL;
@@ -107,7 +125,7 @@ index 4bce8f2f806..3c1bf6edc30 100644
}
else
{
@@ -1911,8 +1922,7 @@ static void *alloc_free_area_in_range( struct alloc_area *area, char *base, char
@@ -1921,8 +1936,7 @@ static void *alloc_free_area_in_range( struct alloc_area *area, char *base, char
|| area->map_area_end - start < area->size)
return NULL;
@@ -117,15 +135,15 @@ index 4bce8f2f806..3c1bf6edc30 100644
}
}
@@ -1922,6 +1932,7 @@ static void *alloc_free_area( void *limit, size_t size, BOOL top_down, int unix_
char *reserve_start, *reserve_end;
@@ -1933,6 +1947,7 @@ static void *alloc_free_area( void *limit, size_t size, BOOL top_down, int unix_
struct alloc_area area;
char *base, *end;
+ NTSTATUS status;
int ranges_inc;
+ UINT status;
TRACE("limit %p, size %p, top_down %#x.\n", limit, (void *)size, top_down);
@@ -1991,7 +2002,58 @@ static void *alloc_free_area( void *limit, size_t size, BOOL top_down, int unix_
@@ -2001,7 +2016,58 @@ static void *alloc_free_area( void *limit, size_t size, BOOL top_down, int unix_
if ((area.result = alloc_free_area_in_range( &area, base, end )))
break;
}
@@ -177,7 +195,7 @@ index 4bce8f2f806..3c1bf6edc30 100644
+ }
+ if ((status = create_view( &next, native_mapped_start, native_mapped_end - native_mapped_start,
+ VPROT_SYSTEM | VPROT_NATIVE )))
+ ERR("Could not cretae view for natively mapped area, status %#x.\n", status);
+ ERR("Could not create view for natively mapped area, status %#x.\n", status);
+ }
+ }
+
@@ -185,7 +203,7 @@ index 4bce8f2f806..3c1bf6edc30 100644
}
/***********************************************************************
@@ -2045,6 +2107,17 @@ static NTSTATUS map_fixed_area( void *base, size_t size, unsigned int vprot )
@@ -2055,6 +2121,17 @@ static NTSTATUS map_fixed_area( void *base, size_t size, unsigned int vprot )
return STATUS_SUCCESS;
}
@@ -203,20 +221,22 @@ index 4bce8f2f806..3c1bf6edc30 100644
/***********************************************************************
* map_view
*
@@ -2097,7 +2170,11 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
@@ -2114,7 +2191,13 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
}
else if (!(ptr = alloc_free_area( (void *)limit, size, top_down, get_unix_prot( vprot ), align_mask )))
{
- return STATUS_NO_MEMORY;
+ WARN("Allocation failed, clearing native views.\n");
+ WARN( "Allocation failed, clearing native views.\n" );
+
+ clear_native_views();
+ if (!(ptr = alloc_free_area( (void *)limit, size, top_down, get_unix_prot( vprot ), align_mask )))
+ return STATUS_NO_MEMORY;
+ if (!is_win64) increase_try_map_step = FALSE;
+ ptr = alloc_free_area( (void *)limit, size, top_down, get_unix_prot( vprot ), align_mask );
+ if (!is_win64) increase_try_map_step = TRUE;
+ if (!ptr) return STATUS_NO_MEMORY;
}
status = create_view( view_ret, ptr, size, vprot );
if (status != STATUS_SUCCESS) unmap_area( ptr, size );
@@ -3835,7 +3912,12 @@ void virtual_set_force_exec( BOOL enable )
@@ -4106,7 +4189,12 @@ void virtual_set_force_exec( BOOL enable )
WINE_RB_FOR_EACH_ENTRY( view, &views_tree, struct file_view, entry )
{
/* file mappings are always accessible */
@@ -231,5 +251,5 @@ index 4bce8f2f806..3c1bf6edc30 100644
mprotect_range( view->base, view->size, commit, 0 );
}
--
2.38.1
2.40.1

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1,81 +0,0 @@
From c97697f6bbc3c9671210e480f2fcfe761b54893d 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 | 41 ++++++++++++++++++++-------------------
1 file changed, 21 insertions(+), 20 deletions(-)
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
index 4cb0f349ffc..2dca5dfa45f 100644
--- a/dlls/ntdll/unix/virtual.c
+++ b/dlls/ntdll/unix/virtual.c
@@ -749,18 +749,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 virtual_alloc_thread_stack shrinks a view, then creates another one on top,
- * or 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)
@@ -810,9 +811,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;
@@ -820,13 +819,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.38.1

View File

@@ -1,85 +0,0 @@
From 4baf5566da8495ef3b260783ed88f175e43b4f70 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 2dca5dfa45f..bdc410472ec 100644
--- a/dlls/ntdll/unix/virtual.c
+++ b/dlls/ntdll/unix/virtual.c
@@ -1563,6 +1563,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
*
@@ -1572,11 +1597,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 );
+ 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 );
}
@@ -1620,9 +1655,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.38.1

View File

@@ -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

View File

@@ -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

View File

@@ -1,58 +0,0 @@
From 72dcf52735e6306fa67f25f49fd78da24d7d89cb Mon Sep 17 00:00:00 2001
From: Paul Gofman <pgofman@codeweavers.com>
Date: Thu, 10 Nov 2022 18:40:18 -0600
Subject: [PATCH] ntdll: Handle NULL process handle in MapViewOfFile3().
Based on a patch by Nikolay Sivov.
---
dlls/kernelbase/memory.c | 2 ++
dlls/ntdll/tests/virtual.c | 13 +++++++++++++
2 files changed, 15 insertions(+)
diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c
index c01fe817972..ee12f6abb91 100644
--- a/dlls/kernelbase/memory.c
+++ b/dlls/kernelbase/memory.c
@@ -255,6 +255,8 @@ LPVOID WINAPI DECLSPEC_HOTPATCH MapViewOfFile3( HANDLE handle, HANDLE process, P
LARGE_INTEGER off;
void *addr;
+ if (!process) process = GetCurrentProcess();
+
addr = baseaddr;
off.QuadPart = offset;
if (!set_ntstatus( NtMapViewOfSectionEx( handle, process, &addr, &off, &size, alloc_type, protection,
diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c
index 0dccb35bd27..486efabaf70 100644
--- a/dlls/ntdll/tests/virtual.c
+++ b/dlls/ntdll/tests/virtual.c
@@ -1060,6 +1060,13 @@ static void test_NtMapViewOfSection(void)
process = create_target_process("sleep");
ok(process != NULL, "Can't start process\n");
+ ptr = NULL;
+ size = 0;
+ offset.QuadPart = 0;
+ status = NtMapViewOfSection(mapping, NULL, &ptr, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE);
+ ok(status == STATUS_INVALID_HANDLE, "NtMapViewOfSection returned %08lx\n", status);
+ ok(!((ULONG_PTR)ptr & 0xffff), "returned memory %p is not aligned to 64k\n", ptr);
+
ptr = NULL;
size = 0;
offset.QuadPart = 0;
@@ -1303,6 +1310,12 @@ static void test_NtMapViewOfSectionEx(void)
process = create_target_process("sleep");
ok(process != NULL, "Can't start process\n");
+ ptr = NULL;
+ size = 0;
+ offset.QuadPart = 0;
+ status = pNtMapViewOfSectionEx(mapping, NULL, &ptr, &offset, &size, 0, PAGE_READWRITE, NULL, 0);
+ ok(status == STATUS_INVALID_HANDLE, "Unexpected status %08lx\n", status);
+
ptr = NULL;
size = 0;
offset.QuadPart = 0;
--
2.38.1

View File

@@ -0,0 +1,205 @@
From 03f652283badc478f715d50d63de4cb9064ef7f1 Mon Sep 17 00:00:00 2001
From: Paul Gofman <pgofman@codeweavers.com>
Date: Thu, 10 Nov 2022 19:02:50 -0600
Subject: [PATCH] ntdll: Support MEM_COALESCE_PLACEHOLDERS in
NtFreeVirtualMemory().
---
dlls/ntdll/tests/virtual.c | 72 ++++++++++++++++++++++++++++++++++++--
dlls/ntdll/unix/virtual.c | 55 ++++++++++++++++++++++++++++-
2 files changed, 124 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c
index 45ba58868df..f5f1964e516 100644
--- a/dlls/ntdll/tests/virtual.c
+++ b/dlls/ntdll/tests/virtual.c
@@ -295,9 +295,9 @@ static void test_NtAllocateVirtualMemoryEx(void)
{
MEMORY_BASIC_INFORMATION mbi;
MEM_EXTENDED_PARAMETER ext[2];
+ char *p, *p1, *p2, *p3;
void *addresses[16];
SIZE_T size, size2;
- char *p, *p1, *p2;
ULONG granularity;
NTSTATUS status;
ULONG_PTR count;
@@ -510,6 +510,7 @@ static void test_NtAllocateVirtualMemoryEx(void)
p1 = addr1;
p2 = p1 + size / 4;
+ p3 = p2 + size / 4;
size2 = size / 4;
status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER);
ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
@@ -517,12 +518,79 @@ static void test_NtAllocateVirtualMemoryEx(void)
ok(size2 == 0x4000, "Unexpected size %#Ix.\n", size2);
ok(p1 == addr1, "Unexpected addr %p, expected %p.\n", p1, addr1);
+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER);
+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
+
+ check_region_size(p1, p2 - p1);
+ check_region_size(p2, p3 - p2);
+ check_region_size(p3, size - (p3 - p1));
+
+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS);
+ ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status);
+
+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size, MEM_COALESCE_PLACEHOLDERS);
+ ok(status == STATUS_INVALID_PARAMETER_4, "Unexpected status %08lx.\n", status);
+
+ size2 = size + 0x1000;
+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS);
+ ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status);
+
+ size2 = size - 0x1000;
+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS);
+ ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status);
+
+ p1 = (char *)addr1 + 0x1000;
+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS);
+ ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status);
+ p1 = addr1;
+
+ size2 = 0;
+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS);
+ ok(status == STATUS_INVALID_PARAMETER_3, "Unexpected status %08lx.\n", status);
+
+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size, MEM_RELEASE);
+ ok(status == STATUS_UNABLE_TO_FREE_VM, "Unexpected status %08lx.\n", status);
+
+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS);
+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
+ ok(size == 0x10000, "Unexpected size %#Ix.\n", size);
+ ok(p1 == addr1, "Unexpected addr %p, expected %p.\n", p1, addr1);
+ check_region_size(p1, size);
+
+ size2 = size / 4;
+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER);
+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
+ ok(size2 == 0x4000, "Unexpected size %#Ix.\n", size2);
+ ok(p1 == addr1, "Unexpected addr %p, expected %p.\n", p1, addr1);
check_region_size(p1, size / 4);
check_region_size(p2, size - size / 4);
- status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE);
+
+ size2 = size - size / 4;
+ status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), (void **)&p2, &size2, MEM_RESERVE | MEM_REPLACE_PLACEHOLDER,
+ PAGE_READWRITE, NULL, 0);
ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
+
+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS);
+ ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status);
+
+ size2 = size - size / 4;
status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE);
ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
+ ok(size2 == 0xc000, "Unexpected size %#Ix.\n", size2);
+ ok(p2 == p1 + size / 4, "Unexpected addr %p, expected %p.\n", p2, p1 + size / 4);
+
+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS);
+ ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status);
+
+ size2 = size / 4;
+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE);
+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
+ ok(size2 == 0x4000, "Unexpected size %#Ix.\n", size2);
+ ok(p1 == addr1, "Unexpected addr %p, expected %p.\n", p1, addr1);
+
+ size2 = 0;
+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p3, &size2, MEM_RELEASE);
+ ok(status == STATUS_MEMORY_NOT_ALLOCATED, "Unexpected status %08lx.\n", status);
/* Split in two regions, specifying second half. */
addr1 = NULL;
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
index f68c5ec84d6..26d4edb019a 100644
--- a/dlls/ntdll/unix/virtual.c
+++ b/dlls/ntdll/unix/virtual.c
@@ -114,6 +114,9 @@ struct file_view
unsigned int protect; /* protection for all pages at allocation time and SEC_* flags */
};
+/* Assert this so RB_ENTRY_VALUE() result can be checked for NULL. */
+C_ASSERT( offsetof( struct file_view, entry ) == 0 );
+
/* per-page protection flags */
#define VPROT_READ 0x01
#define VPROT_WRITE 0x02
@@ -2335,6 +2338,52 @@ static NTSTATUS free_pages( struct file_view *view, char *base, size_t size )
}
+/***********************************************************************
+ * coalesce_placeholders
+ *
+ * Coalesce placeholder views.
+ * virtual_mutex must be held by caller.
+ */
+static NTSTATUS coalesce_placeholders( struct file_view *view, char *base, size_t size, ULONG type )
+{
+ struct file_view *curr_view, *next_view;
+ unsigned int i, view_count = 0;
+ size_t views_size = 0;
+
+ if (type != (MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS)) return STATUS_INVALID_PARAMETER_4;
+ if (!size) return STATUS_INVALID_PARAMETER_3;
+ if (base != view->base) return STATUS_CONFLICTING_ADDRESSES;
+
+ curr_view = view;
+ while (curr_view->protect & VPROT_FREE_PLACEHOLDER)
+ {
+ ++view_count;
+ views_size += curr_view->size;
+ if (views_size >= size) break;
+ if (!(next_view = RB_ENTRY_VALUE( rb_next( &curr_view->entry ), struct file_view, entry ))) break;
+ if ((char *)curr_view->base + curr_view->size != next_view->base) break;
+ curr_view = next_view;
+ }
+
+ if (view_count < 2 || size != views_size) return STATUS_CONFLICTING_ADDRESSES;
+
+ for (i = 1; i < view_count; ++i)
+ {
+ curr_view = RB_ENTRY_VALUE( rb_next( &view->entry ), struct file_view, entry );
+ unregister_view( curr_view );
+ free_view( curr_view );
+ }
+
+ unregister_view( view );
+ view->size = views_size;
+ register_view( view );
+
+ VIRTUAL_DEBUG_DUMP_VIEW( view );
+
+ return STATUS_SUCCESS;
+}
+
+
/***********************************************************************
* allocate_dos_memory
*
@@ -4509,7 +4558,8 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si
else if (!(view = find_view( base, 0 ))) status = STATUS_MEMORY_NOT_ALLOCATED;
else if (!is_view_valloc( view )) status = STATUS_INVALID_PARAMETER;
else if (!size && base != view->base) status = STATUS_FREE_VM_NOT_AT_BASE;
- else if ((char *)view->base + view->size - base < size) status = STATUS_UNABLE_TO_FREE_VM;
+ else if ((char *)view->base + view->size - base < size && !(type & MEM_COALESCE_PLACEHOLDERS))
+ status = STATUS_UNABLE_TO_FREE_VM;
else switch (type)
{
case MEM_DECOMMIT:
@@ -4522,6 +4572,9 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si
case MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER:
status = free_pages_preserve_placeholder( view, base, size );
break;
+ case MEM_COALESCE_PLACEHOLDERS:
+ status = coalesce_placeholders( view, base, size, type );
+ break;
default:
status = STATUS_INVALID_PARAMETER;
break;
--
2.40.1

Some files were not shown because too many files have changed in this diff Show More