Alexandre Julliard : server: Get rid of alignment requirements in write_process_memory request.

Alexandre Julliard julliard at wine.codeweavers.com
Fri Apr 7 13:30:50 CDT 2006


Module: wine
Branch: refs/heads/master
Commit: 959bbf8b757eab6c0651c5683b1bf7cb3b8f33d2
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=959bbf8b757eab6c0651c5683b1bf7cb3b8f33d2

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Fri Apr  7 18:41:58 2006 +0200

server: Get rid of alignment requirements in write_process_memory request.

All the alignment handling is now done in the write_process_memory
function inside the server.

---

 dlls/ntdll/virtual.c           |   21 +---------------
 include/wine/server_protocol.h |    4 +--
 server/process.c               |   54 ++++++++++++++++++++++++----------------
 server/protocol.def            |    4 +--
 server/trace.c                 |    2 -
 5 files changed, 36 insertions(+), 49 deletions(-)

diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index 17f9081..ace9abf 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -1953,32 +1953,13 @@ NTSTATUS WINAPI NtReadVirtualMemory( HAN
 NTSTATUS WINAPI NtWriteVirtualMemory( HANDLE process, void *addr, const void *buffer,
                                       SIZE_T size, SIZE_T *bytes_written )
 {
-    static const unsigned int zero;
-    SIZE_T first_offset, last_offset, first_mask, last_mask;
     NTSTATUS status;
 
-    if (!size) return STATUS_INVALID_PARAMETER;
-
-    /* compute the mask for the first int */
-    first_mask = ~0;
-    first_offset = (ULONG_PTR)addr % sizeof(int);
-    memset( &first_mask, 0, first_offset );
-
-    /* compute the mask for the last int */
-    last_offset = (size + first_offset) % sizeof(int);
-    last_mask = 0;
-    memset( &last_mask, 0xff, last_offset ? last_offset : sizeof(int) );
-
     SERVER_START_REQ( write_process_memory )
     {
         req->handle     = process;
-        req->addr       = (char *)addr - first_offset;
-        req->first_mask = first_mask;
-        req->last_mask  = last_mask;
-        if (first_offset) wine_server_add_data( req, &zero, first_offset );
+        req->addr       = addr;
         wine_server_add_data( req, buffer, size );
-        if (last_offset) wine_server_add_data( req, &zero, sizeof(int) - last_offset );
-
         if ((status = wine_server_call( req ))) size = 0;
     }
     SERVER_END_REQ;
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 95587cd..a20e7e0 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -1691,8 +1691,6 @@ struct write_process_memory_request
     struct request_header __header;
     obj_handle_t handle;
     void*        addr;
-    unsigned int first_mask;
-    unsigned int last_mask;
     /* VARARG(data,bytes); */
 };
 struct write_process_memory_reply
@@ -4361,6 +4359,6 @@ union generic_reply
     struct query_symlink_reply query_symlink_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 231
+#define SERVER_PROTOCOL_VERSION 232
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/process.c b/server/process.c
index fc47cf1..2b605b2 100644
--- a/server/process.c
+++ b/server/process.c
@@ -752,21 +752,34 @@ static int check_process_write_access( s
 }
 
 /* write data to a process memory space */
-/* len is the total size (in ints), max is the size we can actually read from the input buffer */
-/* we check the total size for write permissions */
-static int write_process_memory( struct process *process, int *addr, size_t len,
-                                 unsigned int first_mask, unsigned int last_mask, const int *src )
+static int write_process_memory( struct process *process, void *ptr, size_t size, const char *src )
 {
     struct thread *thread = get_process_first_thread( process );
-    int ret = 0;
-
-    assert( !((unsigned int)addr % sizeof(int) ));  /* address must be aligned */
+    int ret = 0, data = 0;
+    size_t len;
+    int *addr;
+    unsigned int first_mask, first_offset, last_mask, last_offset;
 
     if (!thread)  /* process is dead */
     {
         set_error( STATUS_ACCESS_DENIED );
         return 0;
     }
+
+    /* compute the mask for the first int */
+    first_mask = ~0;
+    first_offset = (unsigned long)ptr % sizeof(int);
+    memset( &first_mask, 0, first_offset );
+
+    /* compute the mask for the last int */
+    last_offset = (size + first_offset) % sizeof(int);
+    if (!last_offset) last_offset = sizeof(int);
+    last_mask = 0;
+    memset( &last_mask, 0xff, last_offset );
+
+    addr = (int *)((char *)ptr - first_offset);
+    len = (size + first_offset + sizeof(int) - 1) / sizeof(int);
+
     if (suspend_for_ptrace( thread ))
     {
         if (!check_process_write_access( thread, addr, len ))
@@ -777,19 +790,25 @@ static int write_process_memory( struct 
         /* first word is special */
         if (len > 1)
         {
-            if (write_thread_int( thread, addr++, *src++, first_mask ) == -1) goto done;
+            memcpy( (char *)&data + first_offset, src, sizeof(int) - first_offset );
+            src += sizeof(int) - first_offset;
+            if (write_thread_int( thread, addr++, data, first_mask ) == -1) goto done;
+            first_offset = 0;
             len--;
         }
         else last_mask &= first_mask;
 
         while (len > 1)
         {
-            if (write_thread_int( thread, addr++, *src++, ~0 ) == -1) goto done;
+            memcpy( &data, src, sizeof(int) );
+            src += sizeof(int);
+            if (write_thread_int( thread, addr++, data, ~0 ) == -1) goto done;
             len--;
         }
 
         /* last word is special too */
-        if (write_thread_int( thread, addr, *src, last_mask ) == -1) goto done;
+        memcpy( (char *)&data + first_offset, src, last_offset - first_offset );
+        if (write_thread_int( thread, addr, data, last_mask ) == -1) goto done;
         ret = 1;
 
     done:
@@ -801,12 +820,10 @@ static int write_process_memory( struct 
 /* set the debugged flag in the process PEB */
 int set_process_debug_flag( struct process *process, int flag )
 {
-    int mask = 0, data = 0;
+    char data = (flag != 0);
 
     /* BeingDebugged flag is the byte at offset 2 in the PEB */
-    memset( (char *)&mask + 2, 0xff, 1 );
-    memset( (char *)&data + 2, flag, 1 );
-    return write_process_memory( process, process->peb, 1, mask, mask, &data );
+    return write_process_memory( process, (char *)process->peb + 2, 1, &data );
 }
 
 /* take a snapshot of currently running processes */
@@ -1080,13 +1097,8 @@ DECL_HANDLER(write_process_memory)
     if ((process = get_process_from_handle( req->handle, PROCESS_VM_WRITE )))
     {
         size_t len = get_req_data_size();
-        if ((len % sizeof(int)) || ((unsigned int)req->addr % sizeof(int)))
-            set_error( STATUS_INVALID_PARAMETER );
-        else
-        {
-            if (len) write_process_memory( process, req->addr, len / sizeof(int),
-                                           req->first_mask, req->last_mask, get_req_data() );
-        }
+        if (len) write_process_memory( process, req->addr, len, get_req_data() );
+        else set_error( STATUS_INVALID_PARAMETER );
         release_object( process );
     }
 }
diff --git a/server/protocol.def b/server/protocol.def
index 5db269a..ef9acb1 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1239,9 +1239,7 @@ enum char_info_mode
 /* Write data to a process address space */
 @REQ(write_process_memory)
     obj_handle_t handle;       /* process handle */
-    void*        addr;         /* addr to write to (must be int-aligned) */
-    unsigned int first_mask;   /* mask for first word */
-    unsigned int last_mask;    /* mask for last word */
+    void*        addr;         /* addr to write to */
     VARARG(data,bytes);        /* data to write */
 @END
 
diff --git a/server/trace.c b/server/trace.c
index 4b567f9..350b2ac 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -1661,8 +1661,6 @@ static void dump_write_process_memory_re
 {
     fprintf( stderr, " handle=%p,", req->handle );
     fprintf( stderr, " addr=%p,", req->addr );
-    fprintf( stderr, " first_mask=%08x,", req->first_mask );
-    fprintf( stderr, " last_mask=%08x,", req->last_mask );
     fprintf( stderr, " data=" );
     dump_varargs_bytes( cur_size );
 }




More information about the wine-cvs mailing list