mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
d33cdb84fd
Added patches by Andrew Wesie which complete the implementation and remove the configuration option that was previously disabled by default.
98 lines
4.0 KiB
Diff
98 lines
4.0 KiB
Diff
From 7656f468a405a0b399994f0cbb9bd8388100cfde Mon Sep 17 00:00:00 2001
|
|
From: Andrew Wesie <awesie@gmail.com>
|
|
Date: Fri, 24 Apr 2020 14:55:14 -0500
|
|
Subject: [PATCH] ntdll: Track if a WRITECOPY page has been modified.
|
|
|
|
Once a WRITECOPY page is modified, it should be mapped as if it is a normal
|
|
read-write page.
|
|
|
|
Signed-off-by: Andrew Wesie <awesie@gmail.com>
|
|
---
|
|
dlls/ntdll/virtual.c | 25 +++++++++++++++++++------
|
|
1 file changed, 19 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
|
|
index fa39a67b9ca..b5baa4c6242 100644
|
|
--- a/dlls/ntdll/virtual.c
|
|
+++ b/dlls/ntdll/virtual.c
|
|
@@ -84,6 +84,7 @@ struct file_view
|
|
#define VPROT_GUARD 0x10
|
|
#define VPROT_COMMITTED 0x20
|
|
#define VPROT_WRITEWATCH 0x40
|
|
+#define VPROT_WRITTEN 0x80
|
|
/* per-mapping protection flags */
|
|
#define VPROT_SYSTEM 0x0200 /* system view (underlying mmap not under our control) */
|
|
|
|
@@ -355,7 +356,7 @@ static int VIRTUAL_GetUnixProt( BYTE vprot )
|
|
#if defined(__i386__)
|
|
if (vprot & VPROT_WRITECOPY)
|
|
{
|
|
- if (experimental_WRITECOPY())
|
|
+ if (experimental_WRITECOPY() && !(vprot & VPROT_WRITTEN))
|
|
prot = (prot & ~PROT_WRITE) | PROT_READ;
|
|
else
|
|
prot |= PROT_WRITE | PROT_READ;
|
|
@@ -918,7 +919,11 @@ static NTSTATUS create_view( struct file_view **view_ret, void *base, size_t siz
|
|
*/
|
|
static DWORD VIRTUAL_GetWin32Prot( BYTE vprot, unsigned int map_prot )
|
|
{
|
|
- DWORD ret = VIRTUAL_Win32Flags[vprot & 0x0f];
|
|
+ DWORD ret;
|
|
+
|
|
+ if ((vprot & VPROT_WRITECOPY) && (vprot & VPROT_WRITTEN))
|
|
+ vprot = (vprot & ~VPROT_WRITECOPY) | VPROT_WRITE;
|
|
+ ret = VIRTUAL_Win32Flags[vprot & 0x0f];
|
|
if (vprot & VPROT_GUARD) ret |= PAGE_GUARD;
|
|
if (map_prot & SEC_NOCACHE) ret |= PAGE_NOCACHE;
|
|
return ret;
|
|
@@ -1042,7 +1047,7 @@ static BOOL VIRTUAL_SetProt( struct file_view *view, /* [in] Pointer to view */
|
|
if (view->protect & VPROT_WRITEWATCH)
|
|
{
|
|
/* each page may need different protections depending on write watch flag */
|
|
- set_page_vprot_bits( base, size, vprot & ~VPROT_WRITEWATCH, ~vprot & ~VPROT_WRITEWATCH );
|
|
+ set_page_vprot_bits( base, size, vprot & ~VPROT_WRITEWATCH, ~vprot & ~(VPROT_WRITEWATCH|VPROT_WRITTEN) );
|
|
mprotect_range( base, size, 0, 0 );
|
|
return TRUE;
|
|
}
|
|
@@ -1058,10 +1063,18 @@ static BOOL VIRTUAL_SetProt( struct file_view *view, /* [in] Pointer to view */
|
|
return TRUE;
|
|
}
|
|
|
|
+ /* check that we can map this memory with PROT_WRITE since we cannot fail later */
|
|
+ if (vprot & VPROT_WRITECOPY)
|
|
+ unix_prot |= PROT_WRITE;
|
|
+
|
|
if (mprotect_exec( base, size, unix_prot )) /* FIXME: last error */
|
|
return FALSE;
|
|
|
|
- set_page_vprot( base, size, vprot );
|
|
+ /* each page may need different protections depending on writecopy */
|
|
+ set_page_vprot_bits( base, size, vprot, ~vprot & ~VPROT_WRITTEN );
|
|
+ if (vprot & VPROT_WRITECOPY)
|
|
+ mprotect_range( base, size, 0, 0 );
|
|
+
|
|
return TRUE;
|
|
}
|
|
|
|
@@ -2319,7 +2332,7 @@ NTSTATUS virtual_handle_fault( LPCVOID addr, DWORD err, BOOL on_signal_stack )
|
|
}
|
|
if (vprot & VPROT_WRITECOPY)
|
|
{
|
|
- set_page_vprot_bits( page, page_size, VPROT_WRITE, VPROT_WRITECOPY );
|
|
+ set_page_vprot_bits( page, page_size, VPROT_WRITE | VPROT_WRITTEN, VPROT_WRITECOPY );
|
|
mprotect_range( page, page_size, 0, 0 );
|
|
}
|
|
/* ignore fault if page is writable now */
|
|
@@ -3265,7 +3278,7 @@ static NTSTATUS get_basic_memory_info( HANDLE process, LPCVOID addr,
|
|
else if (view->protect & (SEC_FILE | SEC_RESERVE | SEC_COMMIT)) info->Type = MEM_MAPPED;
|
|
else info->Type = MEM_PRIVATE;
|
|
for (ptr = base; ptr < base + range_size; ptr += page_size)
|
|
- if ((get_page_vprot( ptr ) ^ vprot) & ~VPROT_WRITEWATCH) break;
|
|
+ if ((get_page_vprot( ptr ) ^ vprot) & ~(VPROT_WRITEWATCH|VPROT_WRITTEN)) break;
|
|
info->RegionSize = ptr - base;
|
|
}
|
|
server_leave_uninterrupted_section( &csVirtual, &sigset );
|
|
--
|
|
2.25.4
|
|
|