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.
This commit is contained in:
Alexandre Julliard 2006-04-07 18:41:58 +02:00
parent 0c5a0f244d
commit 959bbf8b75
5 changed files with 36 additions and 49 deletions

View File

@ -1953,32 +1953,13 @@ NTSTATUS WINAPI NtReadVirtualMemory( HANDLE process, const void *addr, void *buf
NTSTATUS WINAPI NtWriteVirtualMemory( HANDLE process, void *addr, const void *buffer, NTSTATUS WINAPI NtWriteVirtualMemory( HANDLE process, void *addr, const void *buffer,
SIZE_T size, SIZE_T *bytes_written ) SIZE_T size, SIZE_T *bytes_written )
{ {
static const unsigned int zero;
SIZE_T first_offset, last_offset, first_mask, last_mask;
NTSTATUS status; 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 ) SERVER_START_REQ( write_process_memory )
{ {
req->handle = process; req->handle = process;
req->addr = (char *)addr - first_offset; req->addr = addr;
req->first_mask = first_mask;
req->last_mask = last_mask;
if (first_offset) wine_server_add_data( req, &zero, first_offset );
wine_server_add_data( req, buffer, size ); 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; if ((status = wine_server_call( req ))) size = 0;
} }
SERVER_END_REQ; SERVER_END_REQ;

View File

@ -1691,8 +1691,6 @@ struct write_process_memory_request
struct request_header __header; struct request_header __header;
obj_handle_t handle; obj_handle_t handle;
void* addr; void* addr;
unsigned int first_mask;
unsigned int last_mask;
/* VARARG(data,bytes); */ /* VARARG(data,bytes); */
}; };
struct write_process_memory_reply struct write_process_memory_reply
@ -4361,6 +4359,6 @@ union generic_reply
struct query_symlink_reply query_symlink_reply; struct query_symlink_reply query_symlink_reply;
}; };
#define SERVER_PROTOCOL_VERSION 231 #define SERVER_PROTOCOL_VERSION 232
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ #endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View File

@ -752,21 +752,34 @@ static int check_process_write_access( struct thread *thread, int *addr, size_t
} }
/* write data to a process memory space */ /* 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 */ static int write_process_memory( struct process *process, void *ptr, size_t size, const char *src )
/* 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 )
{ {
struct thread *thread = get_process_first_thread( process ); struct thread *thread = get_process_first_thread( process );
int ret = 0; int ret = 0, data = 0;
size_t len;
assert( !((unsigned int)addr % sizeof(int) )); /* address must be aligned */ int *addr;
unsigned int first_mask, first_offset, last_mask, last_offset;
if (!thread) /* process is dead */ if (!thread) /* process is dead */
{ {
set_error( STATUS_ACCESS_DENIED ); set_error( STATUS_ACCESS_DENIED );
return 0; 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 (suspend_for_ptrace( thread ))
{ {
if (!check_process_write_access( thread, addr, len )) if (!check_process_write_access( thread, addr, len ))
@ -777,19 +790,25 @@ static int write_process_memory( struct process *process, int *addr, size_t len,
/* first word is special */ /* first word is special */
if (len > 1) 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--; len--;
} }
else last_mask &= first_mask; else last_mask &= first_mask;
while (len > 1) 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--; len--;
} }
/* last word is special too */ /* 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; ret = 1;
done: done:
@ -801,12 +820,10 @@ static int write_process_memory( struct process *process, int *addr, size_t len,
/* set the debugged flag in the process PEB */ /* set the debugged flag in the process PEB */
int set_process_debug_flag( struct process *process, int flag ) 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 */ /* BeingDebugged flag is the byte at offset 2 in the PEB */
memset( (char *)&mask + 2, 0xff, 1 ); return write_process_memory( process, (char *)process->peb + 2, 1, &data );
memset( (char *)&data + 2, flag, 1 );
return write_process_memory( process, process->peb, 1, mask, mask, &data );
} }
/* take a snapshot of currently running processes */ /* 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 ))) if ((process = get_process_from_handle( req->handle, PROCESS_VM_WRITE )))
{ {
size_t len = get_req_data_size(); size_t len = get_req_data_size();
if ((len % sizeof(int)) || ((unsigned int)req->addr % sizeof(int))) if (len) write_process_memory( process, req->addr, len, get_req_data() );
set_error( STATUS_INVALID_PARAMETER ); else 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() );
}
release_object( process ); release_object( process );
} }
} }

View File

@ -1239,9 +1239,7 @@ enum char_info_mode
/* Write data to a process address space */ /* Write data to a process address space */
@REQ(write_process_memory) @REQ(write_process_memory)
obj_handle_t handle; /* process handle */ obj_handle_t handle; /* process handle */
void* addr; /* addr to write to (must be int-aligned) */ void* addr; /* addr to write to */
unsigned int first_mask; /* mask for first word */
unsigned int last_mask; /* mask for last word */
VARARG(data,bytes); /* data to write */ VARARG(data,bytes); /* data to write */
@END @END

View File

@ -1661,8 +1661,6 @@ static void dump_write_process_memory_request( const struct write_process_memory
{ {
fprintf( stderr, " handle=%p,", req->handle ); fprintf( stderr, " handle=%p,", req->handle );
fprintf( stderr, " addr=%p,", req->addr ); 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=" ); fprintf( stderr, " data=" );
dump_varargs_bytes( cur_size ); dump_varargs_bytes( cur_size );
} }