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:
parent
0c5a0f244d
commit
959bbf8b75
|
@ -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;
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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 );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue