Module: wine Branch: refs/heads/master Commit: 959bbf8b757eab6c0651c5683b1bf7cb3b8f33d2 URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=959bbf8b757eab6c0651c568...
Author: Alexandre Julliard julliard@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 ); }