Sebastian Lackner : ntdll: Handle write watches in virtual_uninterrupted_write_memory.

Alexandre Julliard julliard at wine.codeweavers.com
Thu Mar 19 09:59:02 CDT 2015


Module: wine
Branch: master
Commit: 5f49f07d49d0c0c40a577332274b8d6ec85567cb
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=5f49f07d49d0c0c40a577332274b8d6ec85567cb

Author: Sebastian Lackner <sebastian at fds-team.de>
Date:   Sat Jan  3 19:11:40 2015 +0100

ntdll: Handle write watches in virtual_uninterrupted_write_memory.

---

 dlls/ntdll/virtual.c | 29 ++++++++++++++++++++++++-----
 1 file changed, 24 insertions(+), 5 deletions(-)

diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index ab6bf9b..9d29c33 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -1729,12 +1729,31 @@ SIZE_T virtual_uninterrupted_write_memory( void *addr, const void *buffer, SIZE_
     {
         if (!(view->protect & VPROT_SYSTEM))
         {
-            void *page = ROUND_ADDR( addr, page_mask );
-            BYTE *p = view->prot + (((const char *)page - (const char *)view->base) >> page_shift);
-
-            while (bytes_written < size && (VIRTUAL_GetUnixProt( *p++ ) & PROT_WRITE))
+            while (bytes_written < size)
             {
-                SIZE_T block_size = min( size, page_size - ((UINT_PTR)addr & page_mask) );
+                void *page = ROUND_ADDR( addr, page_mask );
+                BYTE *p = view->prot + (((const char *)page - (const char *)view->base) >> page_shift);
+                SIZE_T block_size;
+
+                /* If the page is not writeable then check for write watches
+                 * before giving up. This can be done without raising a real
+                 * exception. Similar to virtual_handle_fault. */
+                if (!(VIRTUAL_GetUnixProt( *p ) & PROT_WRITE))
+                {
+                    if (!(view->protect & VPROT_WRITEWATCH))
+                        break;
+
+                    if (*p & VPROT_WRITEWATCH)
+                    {
+                        *p &= ~VPROT_WRITEWATCH;
+                        VIRTUAL_SetProt( view, page, page_size, *p );
+                    }
+                    /* ignore fault if page is writable now */
+                    if (!(VIRTUAL_GetUnixProt( *p ) & PROT_WRITE))
+                        break;
+                }
+
+                block_size = min( size, page_size - ((UINT_PTR)addr & page_mask) );
                 memcpy( addr, buffer, block_size );
 
                 addr   = (void *)((char *)addr + block_size);




More information about the wine-cvs mailing list