Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
eef7025e
Commit
eef7025e
authored
Nov 13, 1999
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added support for WriteProcessMemory through the server.
parent
c76ad35a
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
217 additions
and
20 deletions
+217
-20
server.h
include/server.h
+13
-0
process.c
scheduler/process.c
+67
-8
process.c
server/process.c
+115
-12
request.h
server/request.h
+2
-0
trace.c
server/trace.c
+20
-0
No files found.
include/server.h
View file @
eef7025e
...
...
@@ -817,6 +817,18 @@ struct read_process_memory_request
};
/* Write data to a process address space */
struct
write_process_memory_request
{
IN
int
handle
;
/* process handle */
IN
void
*
addr
;
/* addr to write to (must be int-aligned) */
IN
int
len
;
/* number of ints to write */
IN
unsigned
int
first_mask
;
/* mask for first word */
IN
unsigned
int
last_mask
;
/* mask for last word */
IN
unsigned
int
data
[
1
];
/* data to write */
};
/* Everything below this line is generated automatically by tools/make_requests */
/* ### make_requests begin ### */
...
...
@@ -894,6 +906,7 @@ enum request
REQ_CONTINUE_DEBUG_EVENT
,
REQ_DEBUG_PROCESS
,
REQ_READ_PROCESS_MEMORY
,
REQ_WRITE_PROCESS_MEMORY
,
REQ_NB_REQUESTS
};
...
...
scheduler/process.c
View file @
eef7025e
...
...
@@ -1116,18 +1116,77 @@ BOOL WINAPI ReadProcessMemory( HANDLE process, LPCVOID addr, LPVOID buffer, DWOR
/***********************************************************************
* WriteProcessMemory (KERNEL32)
* FIXME: check this, if we ever run win32 binaries in different addressspaces
* ... and add a sizecheck
*/
BOOL
WINAPI
WriteProcessMemory
(
HANDLE
hProcess
,
LPVOID
lpBaseAddress
,
LPVOID
lpBuffer
,
DWORD
nSize
,
LPDWORD
lpNumberOfBytesWritten
)
BOOL
WINAPI
WriteProcessMemory
(
HANDLE
process
,
LPVOID
addr
,
LPVOID
buffer
,
DWORD
size
,
LPDWORD
bytes_written
)
{
memcpy
(
lpBaseAddress
,
lpBuffer
,
nSize
);
if
(
lpNumberOfBytesWritten
)
*
lpNumberOfBytesWritten
=
nSize
;
return
TRUE
;
unsigned
int
first_offset
,
last_offset
;
struct
write_process_memory_request
*
req
=
get_req_buffer
();
unsigned
int
max
=
server_remaining
(
req
->
data
);
/* max length in one request */
unsigned
int
pos
,
last_mask
;
if
(
!
size
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
FALSE
;
}
if
(
bytes_written
)
*
bytes_written
=
size
;
/* compute the mask for the first int */
req
->
first_mask
=
~
0
;
first_offset
=
(
unsigned
int
)
addr
%
sizeof
(
int
);
memset
(
&
req
->
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
)
);
req
->
handle
=
process
;
req
->
addr
=
(
char
*
)
addr
-
first_offset
;
/* for the first request, use the total length */
req
->
len
=
(
size
+
first_offset
+
sizeof
(
int
)
-
1
)
/
sizeof
(
int
);
if
(
size
+
first_offset
<
max
)
/* we can do it in one round */
{
memcpy
(
(
char
*
)
req
->
data
+
first_offset
,
buffer
,
size
);
req
->
last_mask
=
last_mask
;
if
(
server_call
(
REQ_WRITE_PROCESS_MEMORY
))
goto
error
;
return
TRUE
;
}
/* needs multiple server calls */
memcpy
(
(
char
*
)
req
->
data
+
first_offset
,
buffer
,
max
-
first_offset
);
req
->
last_mask
=
~
0
;
if
(
server_call
(
REQ_WRITE_PROCESS_MEMORY
))
goto
error
;
pos
=
max
-
first_offset
;
size
-=
pos
;
while
(
size
)
{
if
(
size
<=
max
)
/* last one */
{
req
->
last_mask
=
last_mask
;
max
=
size
;
}
req
->
handle
=
process
;
req
->
addr
=
(
char
*
)
addr
+
pos
;
req
->
len
=
(
max
+
sizeof
(
int
)
-
1
)
/
sizeof
(
int
);
req
->
first_mask
=
~
0
;
memcpy
(
req
->
data
,
buffer
+
pos
,
max
);
if
(
server_call
(
REQ_WRITE_PROCESS_MEMORY
))
goto
error
;
pos
+=
max
;
size
-=
max
;
}
return
TRUE
;
error:
if
(
bytes_written
)
*
bytes_written
=
0
;
return
FALSE
;
}
/***********************************************************************
* RegisterServiceProcess (KERNEL, KERNEL32)
*
...
...
server/process.c
View file @
eef7025e
...
...
@@ -316,35 +316,125 @@ static void set_process_info( struct process *process,
}
}
/* wrapper for reading an int with ptrace */
static
inline
int
read_word
(
int
pid
,
const
int
*
addr
,
int
*
data
)
{
if
(((
*
data
=
ptrace
(
PT_READ_D
,
pid
,
addr
))
==
-
1
)
&&
errno
)
{
file_set_error
();
return
-
1
;
}
return
0
;
}
/* wrapper for writing an int with ptrace */
static
inline
int
write_word
(
int
pid
,
int
*
addr
,
int
data
,
unsigned
int
mask
)
{
int
res
;
if
(
mask
!=
~
0
)
{
if
(
read_word
(
pid
,
addr
,
&
res
)
==
-
1
)
return
-
1
;
data
=
(
data
&
mask
)
|
(
res
&
~
mask
);
}
if
((
res
=
ptrace
(
PT_WRITE_D
,
pid
,
addr
,
data
))
==
-
1
)
file_set_error
();
return
res
;
}
/* read data from a process memory space */
/* len is the total size (in ints), max is the size we can actually store in the
in
put buffer */
/* len is the total size (in ints), max is the size we can actually store in the
out
put buffer */
/* we read the total size in all cases to check for permissions */
static
void
read_process_memory
(
struct
process
*
process
,
const
int
*
addr
,
int
len
,
in
t
max
,
int
*
dest
)
static
void
read_process_memory
(
struct
process
*
process
,
const
int
*
addr
,
size_t
len
,
size_
t
max
,
int
*
dest
)
{
struct
thread
*
thread
=
process
->
thread_list
;
int
pid
=
thread
->
unix_pid
;
if
((
unsigned
int
)
addr
%
sizeof
(
int
))
/* address must be aligned */
{
set_error
(
ERROR_INVALID_PARAMETER
);
return
;
}
suspend_thread
(
thread
,
0
);
if
(
thread
->
attached
)
{
while
(
len
--
>
0
)
while
(
len
>
0
&&
max
)
{
if
(
read_word
(
pid
,
addr
++
,
dest
++
)
==
-
1
)
goto
done
;
max
--
;
len
--
;
}
/* check the rest for read permission */
if
(
len
>
0
)
{
int
d
ata
=
ptrace
(
PT_READ_D
,
pid
,
addr
);
if
((
data
==
-
1
)
&&
errno
)
int
d
ummy
,
page
=
get_page_size
()
/
sizeof
(
int
);
while
(
len
>=
page
)
{
file_set_error
();
break
;
addr
+=
page
;
len
-=
page
;
if
(
read_word
(
pid
,
addr
-
1
,
&
dummy
)
==
-
1
)
goto
done
;
}
if
(
max
)
if
(
len
&&
(
read_word
(
pid
,
addr
+
len
-
1
,
&
dummy
)
==
-
1
))
goto
done
;
}
}
else
set_error
(
ERROR_ACCESS_DENIED
);
done:
resume_thread
(
thread
);
}
/* 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
void
write_process_memory
(
struct
process
*
process
,
int
*
addr
,
size_t
len
,
size_t
max
,
unsigned
int
first_mask
,
unsigned
int
last_mask
,
const
int
*
src
)
{
struct
thread
*
thread
=
process
->
thread_list
;
int
pid
=
thread
->
unix_pid
;
if
(
!
len
||
((
unsigned
int
)
addr
%
sizeof
(
int
)))
/* address must be aligned */
{
set_error
(
ERROR_INVALID_PARAMETER
);
return
;
}
suspend_thread
(
thread
,
0
);
if
(
thread
->
attached
)
{
/* first word is special */
if
(
len
>
1
)
{
if
(
write_word
(
pid
,
addr
++
,
*
src
++
,
first_mask
)
==
-
1
)
goto
done
;
len
--
;
max
--
;
}
else
last_mask
&=
first_mask
;
while
(
len
>
1
&&
max
)
{
if
(
write_word
(
pid
,
addr
++
,
*
src
++
,
~
0
)
==
-
1
)
goto
done
;
max
--
;
len
--
;
}
if
(
max
)
{
/* last word is special too */
if
(
write_word
(
pid
,
addr
,
*
src
,
last_mask
)
==
-
1
)
goto
done
;
}
else
{
/* check the rest for write permission */
int
page
=
get_page_size
()
/
sizeof
(
int
);
while
(
len
>=
page
)
{
*
dest
++
=
data
;
max
--
;
addr
+=
page
;
len
-=
page
;
if
(
write_word
(
pid
,
addr
-
1
,
0
,
0
)
==
-
1
)
goto
done
;
}
addr
++
;
if
(
len
&&
(
write_word
(
pid
,
addr
+
len
-
1
,
0
,
0
)
==
-
1
))
goto
done
;
}
}
else
set_error
(
ERROR_ACCESS_DENIED
);
done:
resume_thread
(
thread
);
}
...
...
@@ -487,3 +577,16 @@ DECL_HANDLER(read_process_memory)
release_object
(
process
);
}
}
/* write data to a process address space */
DECL_HANDLER
(
write_process_memory
)
{
struct
process
*
process
;
if
((
process
=
get_process_from_handle
(
req
->
handle
,
PROCESS_VM_WRITE
)))
{
write_process_memory
(
process
,
req
->
addr
,
req
->
len
,
get_req_size
(
req
->
data
,
sizeof
(
int
)
),
req
->
first_mask
,
req
->
last_mask
,
req
->
data
);
release_object
(
process
);
}
}
server/request.h
View file @
eef7025e
...
...
@@ -133,6 +133,7 @@ DECL_HANDLER(send_debug_event);
DECL_HANDLER
(
continue_debug_event
);
DECL_HANDLER
(
debug_process
);
DECL_HANDLER
(
read_process_memory
);
DECL_HANDLER
(
write_process_memory
);
#ifdef WANT_REQUEST_HANDLERS
...
...
@@ -212,6 +213,7 @@ static const struct handler {
{
(
void
(
*
)())
req_continue_debug_event
,
sizeof
(
struct
continue_debug_event_request
)
},
{
(
void
(
*
)())
req_debug_process
,
sizeof
(
struct
debug_process_request
)
},
{
(
void
(
*
)())
req_read_process_memory
,
sizeof
(
struct
read_process_memory_request
)
},
{
(
void
(
*
)())
req_write_process_memory
,
sizeof
(
struct
write_process_memory_request
)
},
};
#endif
/* WANT_REQUEST_HANDLERS */
...
...
server/trace.c
View file @
eef7025e
...
...
@@ -61,6 +61,12 @@ static void dump_varargs_read_process_memory( struct read_process_memory_request
dump_bytes
(
(
unsigned
char
*
)
req
->
data
,
count
*
sizeof
(
int
)
);
}
static
void
dump_varargs_write_process_memory
(
struct
write_process_memory_request
*
req
)
{
int
count
=
MIN
(
req
->
len
,
get_req_size
(
req
->
data
,
sizeof
(
int
)
)
);
dump_bytes
(
(
unsigned
char
*
)
req
->
data
,
count
*
sizeof
(
int
)
);
}
typedef
void
(
*
dump_func
)(
const
void
*
req
);
...
...
@@ -800,6 +806,17 @@ static void dump_read_process_memory_reply( struct read_process_memory_request *
dump_varargs_read_process_memory
(
req
);
}
static
void
dump_write_process_memory_request
(
struct
write_process_memory_request
*
req
)
{
fprintf
(
stderr
,
" handle=%d,"
,
req
->
handle
);
fprintf
(
stderr
,
" addr=%p,"
,
req
->
addr
);
fprintf
(
stderr
,
" len=%d,"
,
req
->
len
);
fprintf
(
stderr
,
" first_mask=%08x,"
,
req
->
first_mask
);
fprintf
(
stderr
,
" last_mask=%08x,"
,
req
->
last_mask
);
fprintf
(
stderr
,
" data="
);
dump_varargs_write_process_memory
(
req
);
}
static
const
dump_func
req_dumpers
[
REQ_NB_REQUESTS
]
=
{
(
dump_func
)
dump_new_process_request
,
(
dump_func
)
dump_new_thread_request
,
...
...
@@ -873,6 +890,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(
dump_func
)
dump_continue_debug_event_request
,
(
dump_func
)
dump_debug_process_request
,
(
dump_func
)
dump_read_process_memory_request
,
(
dump_func
)
dump_write_process_memory_request
,
};
static
const
dump_func
reply_dumpers
[
REQ_NB_REQUESTS
]
=
{
...
...
@@ -948,6 +966,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(
dump_func
)
0
,
(
dump_func
)
0
,
(
dump_func
)
dump_read_process_memory_reply
,
(
dump_func
)
0
,
};
static
const
char
*
const
req_names
[
REQ_NB_REQUESTS
]
=
{
...
...
@@ -1023,6 +1042,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"continue_debug_event"
,
"debug_process"
,
"read_process_memory"
,
"write_process_memory"
,
};
/* ### make_requests end ### */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment