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
19bf03ed
Commit
19bf03ed
authored
Apr 18, 2019
by
Nikolay Sivov
Committed by
Alexandre Julliard
Apr 19, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Add NtSuspendProcess()/NtResumeProcess() implementation.
Signed-off-by:
Nikolay Sivov
<
nsivov@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
c8b9aa00
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
278 additions
and
9 deletions
+278
-9
process.c
dlls/ntdll/process.c
+20
-4
exception.c
dlls/ntdll/tests/exception.c
+149
-2
server_protocol.h
include/wine/server_protocol.h
+31
-1
process.c
server/process.c
+38
-0
protocol.def
server/protocol.def
+12
-0
request.h
server/request.h
+8
-0
thread.c
server/thread.c
+2
-2
thread.h
server/thread.h
+2
-0
trace.c
server/trace.c
+16
-0
No files found.
dlls/ntdll/process.c
View file @
19bf03ed
...
...
@@ -763,8 +763,16 @@ NTSTATUS WINAPI NtOpenProcess(PHANDLE handle, ACCESS_MASK access,
*/
NTSTATUS
WINAPI
NtResumeProcess
(
HANDLE
handle
)
{
FIXME
(
"stub: %p
\n
"
,
handle
);
return
STATUS_NOT_IMPLEMENTED
;
NTSTATUS
ret
;
SERVER_START_REQ
(
resume_process
)
{
req
->
handle
=
wine_server_obj_handle
(
handle
);
ret
=
wine_server_call
(
req
);
}
SERVER_END_REQ
;
return
ret
;
}
/******************************************************************************
...
...
@@ -773,8 +781,16 @@ NTSTATUS WINAPI NtResumeProcess( HANDLE handle )
*/
NTSTATUS
WINAPI
NtSuspendProcess
(
HANDLE
handle
)
{
FIXME
(
"stub: %p
\n
"
,
handle
);
return
STATUS_NOT_IMPLEMENTED
;
NTSTATUS
ret
;
SERVER_START_REQ
(
suspend_process
)
{
req
->
handle
=
wine_server_obj_handle
(
handle
);
ret
=
wine_server_call
(
req
);
}
SERVER_END_REQ
;
return
ret
;
}
...
...
dlls/ntdll/tests/exception.c
View file @
19bf03ed
...
...
@@ -53,6 +53,8 @@ static NTSTATUS (WINAPI *pNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS,
static
NTSTATUS
(
WINAPI
*
pNtSetInformationProcess
)(
HANDLE
,
PROCESSINFOCLASS
,
PVOID
,
ULONG
);
static
BOOL
(
WINAPI
*
pIsWow64Process
)(
HANDLE
,
PBOOL
);
static
NTSTATUS
(
WINAPI
*
pNtClose
)(
HANDLE
);
static
NTSTATUS
(
WINAPI
*
pNtSuspendProcess
)(
HANDLE
process
);
static
NTSTATUS
(
WINAPI
*
pNtResumeProcess
)(
HANDLE
process
);
#if defined(__x86_64__)
typedef
struct
...
...
@@ -158,6 +160,9 @@ static VOID (CDECL *pRtlUnwindEx)(VOID*, VOID*, EXCEPTION_RECORD*, VOID*, C
static
int
(
CDECL
*
p_setjmp
)(
_JUMP_BUFFER
*
);
#endif
static
int
my_argc
;
static
char
**
my_argv
;
#ifdef __i386__
#ifndef __WINE_WINTRNL_H
...
...
@@ -167,8 +172,6 @@ static int (CDECL *p_setjmp)(_JUMP_BUFFER*);
#define MEM_EXECUTE_OPTION_PERMANENT 0x08
#endif
static
int
my_argc
;
static
char
**
my_argv
;
static
int
test_stage
;
static
BOOL
is_wow64
;
...
...
@@ -3190,6 +3193,138 @@ static void test_suspend_thread(void)
CloseHandle
(
thread
);
}
static
const
char
*
suspend_process_event_name
=
"suspend_process_event"
;
static
const
char
*
suspend_process_event2_name
=
"suspend_process_event2"
;
static
DWORD
WINAPI
dummy_thread_proc
(
void
*
arg
)
{
return
0
;
}
static
void
suspend_process_proc
(
void
)
{
HANDLE
event
=
OpenEventA
(
SYNCHRONIZE
,
FALSE
,
suspend_process_event_name
);
HANDLE
event2
=
OpenEventA
(
SYNCHRONIZE
|
EVENT_MODIFY_STATE
,
FALSE
,
suspend_process_event2_name
);
unsigned
int
count
;
NTSTATUS
status
;
HANDLE
thread
;
ok
(
event
!=
NULL
,
"Failed to open event handle.
\n
"
);
ok
(
event2
!=
NULL
,
"Failed to open event handle.
\n
"
);
thread
=
CreateThread
(
NULL
,
0
,
dummy_thread_proc
,
0
,
CREATE_SUSPENDED
,
NULL
);
ok
(
thread
!=
NULL
,
"Failed to create auxiliary thread.
\n
"
);
/* Suspend up to limit. */
while
(
!
(
status
=
NtSuspendThread
(
thread
,
NULL
)))
;
ok
(
status
==
STATUS_SUSPEND_COUNT_EXCEEDED
,
"Unexpected status %#x.
\n
"
,
status
);
for
(;;)
{
SetEvent
(
event2
);
if
(
WaitForSingleObject
(
event
,
100
)
==
WAIT_OBJECT_0
)
break
;
}
status
=
NtSuspendThread
(
thread
,
&
count
);
ok
(
!
status
,
"Failed to suspend a thread, status %#x.
\n
"
,
status
);
ok
(
count
==
125
,
"Unexpected suspend count %u.
\n
"
,
count
);
status
=
NtResumeThread
(
thread
,
NULL
);
ok
(
!
status
,
"Failed to resume a thread, status %#x.
\n
"
,
status
);
CloseHandle
(
event
);
CloseHandle
(
event2
);
}
static
void
test_suspend_process
(
void
)
{
PROCESS_INFORMATION
info
;
char
path_name
[
MAX_PATH
];
STARTUPINFOA
startup
;
HANDLE
event
,
event2
;
NTSTATUS
status
;
char
**
argv
;
DWORD
ret
;
event
=
CreateEventA
(
NULL
,
FALSE
,
FALSE
,
suspend_process_event_name
);
ok
(
event
!=
NULL
,
"Failed to create event.
\n
"
);
event2
=
CreateEventA
(
NULL
,
FALSE
,
FALSE
,
suspend_process_event2_name
);
ok
(
event2
!=
NULL
,
"Failed to create event.
\n
"
);
winetest_get_mainargs
(
&
argv
);
memset
(
&
startup
,
0
,
sizeof
(
startup
));
startup
.
cb
=
sizeof
(
startup
);
sprintf
(
path_name
,
"%s exception suspend_process"
,
argv
[
0
]);
ret
=
CreateProcessA
(
NULL
,
path_name
,
NULL
,
NULL
,
FALSE
,
0
,
NULL
,
NULL
,
&
startup
,
&
info
),
ok
(
ret
,
"Failed to create target process.
\n
"
);
/* New process signals this event. */
ResetEvent
(
event2
);
ret
=
WaitForSingleObject
(
event2
,
INFINITE
);
ok
(
ret
==
WAIT_OBJECT_0
,
"Wait failed, %#x.
\n
"
,
ret
);
/* Suspend main thread */
status
=
NtSuspendThread
(
info
.
hThread
,
&
ret
);
ok
(
!
status
&&
!
ret
,
"Failed to suspend main thread, status %#x.
\n
"
,
status
);
/* Process wasn't suspended yet. */
status
=
pNtResumeProcess
(
info
.
hProcess
);
ok
(
!
status
,
"Failed to resume a process, status %#x.
\n
"
,
status
);
status
=
pNtSuspendProcess
(
0
);
ok
(
status
==
STATUS_INVALID_HANDLE
,
"Unexpected status %#x.
\n
"
,
status
);
status
=
pNtResumeProcess
(
info
.
hProcess
);
ok
(
!
status
,
"Failed to resume a process, status %#x.
\n
"
,
status
);
ResetEvent
(
event2
);
ret
=
WaitForSingleObject
(
event2
,
200
);
ok
(
ret
==
WAIT_OBJECT_0
,
"Wait failed.
\n
"
);
status
=
pNtSuspendProcess
(
info
.
hProcess
);
ok
(
!
status
,
"Failed to suspend a process, status %#x.
\n
"
,
status
);
status
=
NtSuspendThread
(
info
.
hThread
,
&
ret
);
ok
(
!
status
&&
ret
==
1
,
"Failed to suspend main thread, status %#x.
\n
"
,
status
);
status
=
NtResumeThread
(
info
.
hThread
,
&
ret
);
ok
(
!
status
&&
ret
==
2
,
"Failed to resume main thread, status %#x.
\n
"
,
status
);
ResetEvent
(
event2
);
ret
=
WaitForSingleObject
(
event2
,
200
);
ok
(
ret
==
WAIT_TIMEOUT
,
"Wait failed.
\n
"
);
status
=
pNtSuspendProcess
(
info
.
hProcess
);
ok
(
!
status
,
"Failed to suspend a process, status %#x.
\n
"
,
status
);
status
=
pNtResumeProcess
(
info
.
hProcess
);
ok
(
!
status
,
"Failed to resume a process, status %#x.
\n
"
,
status
);
ResetEvent
(
event2
);
ret
=
WaitForSingleObject
(
event2
,
200
);
ok
(
ret
==
WAIT_TIMEOUT
,
"Wait failed.
\n
"
);
status
=
pNtResumeProcess
(
info
.
hProcess
);
ok
(
!
status
,
"Failed to resume a process, status %#x.
\n
"
,
status
);
ResetEvent
(
event2
);
ret
=
WaitForSingleObject
(
event2
,
200
);
ok
(
ret
==
WAIT_OBJECT_0
,
"Wait failed.
\n
"
);
SetEvent
(
event
);
winetest_wait_child_process
(
info
.
hProcess
);
CloseHandle
(
info
.
hProcess
);
CloseHandle
(
info
.
hThread
);
CloseHandle
(
event
);
CloseHandle
(
event2
);
}
START_TEST
(
exception
)
{
HMODULE
hntdll
=
GetModuleHandleA
(
"ntdll.dll"
);
...
...
@@ -3197,6 +3332,14 @@ START_TEST(exception)
HMODULE
hmsvcrt
=
LoadLibraryA
(
"msvcrt.dll"
);
#endif
my_argc
=
winetest_get_mainargs
(
&
my_argv
);
if
(
my_argc
>=
3
&&
!
strcmp
(
my_argv
[
2
],
"suspend_process"
))
{
suspend_process_proc
();
return
;
}
code_mem
=
VirtualAlloc
(
NULL
,
65536
,
MEM_RESERVE
|
MEM_COMMIT
,
PAGE_EXECUTE_READWRITE
);
if
(
!
code_mem
)
{
trace
(
"VirtualAlloc failed
\n
"
);
...
...
@@ -3224,6 +3367,8 @@ START_TEST(exception)
pNtSetInformationProcess
=
(
void
*
)
GetProcAddress
(
hntdll
,
"NtSetInformationProcess"
);
pIsWow64Process
=
(
void
*
)
GetProcAddress
(
GetModuleHandleA
(
"kernel32.dll"
),
"IsWow64Process"
);
pNtSuspendProcess
=
(
void
*
)
GetProcAddress
(
hntdll
,
"NtSuspendProcess"
);
pNtResumeProcess
=
(
void
*
)
GetProcAddress
(
hntdll
,
"NtResumeProcess"
);
#ifdef __i386__
if
(
!
pIsWow64Process
||
!
pIsWow64Process
(
GetCurrentProcess
(),
&
is_wow64
))
is_wow64
=
FALSE
;
...
...
@@ -3309,6 +3454,7 @@ START_TEST(exception)
test_prot_fault
();
test_thread_context
();
test_suspend_thread
();
test_suspend_process
();
#elif defined(__x86_64__)
pRtlAddFunctionTable
=
(
void
*
)
GetProcAddress
(
hntdll
,
...
...
@@ -3351,6 +3497,7 @@ START_TEST(exception)
test_dpe_exceptions
();
test_wow64_context
();
test_suspend_thread
();
test_suspend_process
();
if
(
pRtlAddFunctionTable
&&
pRtlDeleteFunctionTable
&&
pRtlInstallFunctionTableCallback
&&
pRtlLookupFunctionEntry
)
test_dynamic_unwind
();
...
...
include/wine/server_protocol.h
View file @
19bf03ed
...
...
@@ -5742,6 +5742,30 @@ struct terminate_job_reply
};
struct
suspend_process_request
{
struct
request_header
__header
;
obj_handle_t
handle
;
};
struct
suspend_process_reply
{
struct
reply_header
__header
;
};
struct
resume_process_request
{
struct
request_header
__header
;
obj_handle_t
handle
;
};
struct
resume_process_reply
{
struct
reply_header
__header
;
};
enum
request
{
REQ_new_process
,
...
...
@@ -6040,6 +6064,8 @@ enum request
REQ_set_job_limits
,
REQ_set_job_completion_port
,
REQ_terminate_job
,
REQ_suspend_process
,
REQ_resume_process
,
REQ_NB_REQUESTS
};
...
...
@@ -6343,6 +6369,8 @@ union generic_request
struct
set_job_limits_request
set_job_limits_request
;
struct
set_job_completion_port_request
set_job_completion_port_request
;
struct
terminate_job_request
terminate_job_request
;
struct
suspend_process_request
suspend_process_request
;
struct
resume_process_request
resume_process_request
;
};
union
generic_reply
{
...
...
@@ -6644,8 +6672,10 @@ union generic_reply
struct
set_job_limits_reply
set_job_limits_reply
;
struct
set_job_completion_port_reply
set_job_completion_port_reply
;
struct
terminate_job_reply
terminate_job_reply
;
struct
suspend_process_reply
suspend_process_reply
;
struct
resume_process_reply
resume_process_reply
;
};
#define SERVER_PROTOCOL_VERSION 57
8
#define SERVER_PROTOCOL_VERSION 57
9
#endif
/* __WINE_WINE_SERVER_PROTOCOL_H */
server/process.c
View file @
19bf03ed
...
...
@@ -1705,3 +1705,41 @@ DECL_HANDLER(set_job_completion_port)
release_object
(
job
);
}
/* Suspend a process */
DECL_HANDLER
(
suspend_process
)
{
struct
process
*
process
;
if
((
process
=
get_process_from_handle
(
req
->
handle
,
PROCESS_SUSPEND_RESUME
)))
{
struct
list
*
ptr
,
*
next
;
LIST_FOR_EACH_SAFE
(
ptr
,
next
,
&
process
->
thread_list
)
{
struct
thread
*
thread
=
LIST_ENTRY
(
ptr
,
struct
thread
,
proc_entry
);
suspend_thread
(
thread
);
}
release_object
(
process
);
}
}
/* Resume a process */
DECL_HANDLER
(
resume_process
)
{
struct
process
*
process
;
if
((
process
=
get_process_from_handle
(
req
->
handle
,
PROCESS_SUSPEND_RESUME
)))
{
struct
list
*
ptr
,
*
next
;
LIST_FOR_EACH_SAFE
(
ptr
,
next
,
&
process
->
thread_list
)
{
struct
thread
*
thread
=
LIST_ENTRY
(
ptr
,
struct
thread
,
proc_entry
);
resume_thread
(
thread
);
}
release_object
(
process
);
}
}
server/protocol.def
View file @
19bf03ed
...
...
@@ -3909,3 +3909,15 @@ struct handle_info
obj_handle_t handle; /* handle to the job */
int status; /* process exit code */
@END
/* Suspend a process */
@REQ(suspend_process)
obj_handle_t handle; /* process handle */
@END
/* Resume a process */
@REQ(resume_process)
obj_handle_t handle; /* process handle */
@END
server/request.h
View file @
19bf03ed
...
...
@@ -408,6 +408,8 @@ DECL_HANDLER(process_in_job);
DECL_HANDLER
(
set_job_limits
);
DECL_HANDLER
(
set_job_completion_port
);
DECL_HANDLER
(
terminate_job
);
DECL_HANDLER
(
suspend_process
);
DECL_HANDLER
(
resume_process
);
#ifdef WANT_REQUEST_HANDLERS
...
...
@@ -710,6 +712,8 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(
req_handler
)
req_set_job_limits
,
(
req_handler
)
req_set_job_completion_port
,
(
req_handler
)
req_terminate_job
,
(
req_handler
)
req_suspend_process
,
(
req_handler
)
req_resume_process
,
};
C_ASSERT
(
sizeof
(
affinity_t
)
==
8
);
...
...
@@ -2436,6 +2440,10 @@ C_ASSERT( sizeof(struct set_job_completion_port_request) == 32 );
C_ASSERT
(
FIELD_OFFSET
(
struct
terminate_job_request
,
handle
)
==
12
);
C_ASSERT
(
FIELD_OFFSET
(
struct
terminate_job_request
,
status
)
==
16
);
C_ASSERT
(
sizeof
(
struct
terminate_job_request
)
==
24
);
C_ASSERT
(
FIELD_OFFSET
(
struct
suspend_process_request
,
handle
)
==
12
);
C_ASSERT
(
sizeof
(
struct
suspend_process_request
)
==
16
);
C_ASSERT
(
FIELD_OFFSET
(
struct
resume_process_request
,
handle
)
==
12
);
C_ASSERT
(
sizeof
(
struct
resume_process_request
)
==
16
);
#endif
/* WANT_REQUEST_HANDLERS */
...
...
server/thread.c
View file @
19bf03ed
...
...
@@ -570,7 +570,7 @@ void stop_thread_if_suspended( struct thread *thread )
}
/* suspend a thread */
static
int
suspend_thread
(
struct
thread
*
thread
)
int
suspend_thread
(
struct
thread
*
thread
)
{
int
old_count
=
thread
->
suspend
;
if
(
thread
->
suspend
<
MAXIMUM_SUSPEND_COUNT
)
...
...
@@ -582,7 +582,7 @@ static int suspend_thread( struct thread *thread )
}
/* resume a thread */
static
int
resume_thread
(
struct
thread
*
thread
)
int
resume_thread
(
struct
thread
*
thread
)
{
int
old_count
=
thread
->
suspend
;
if
(
thread
->
suspend
>
0
)
...
...
server/thread.h
View file @
19bf03ed
...
...
@@ -131,6 +131,8 @@ extern struct token *thread_get_impersonation_token( struct thread *thread );
extern
int
set_thread_affinity
(
struct
thread
*
thread
,
affinity_t
affinity
);
extern
int
is_cpu_supported
(
enum
cpu_type
cpu
);
extern
unsigned
int
get_supported_cpu_mask
(
void
);
extern
int
suspend_thread
(
struct
thread
*
thread
);
extern
int
resume_thread
(
struct
thread
*
thread
);
/* ptrace functions */
...
...
server/trace.c
View file @
19bf03ed
...
...
@@ -4582,6 +4582,16 @@ static void dump_terminate_job_request( const struct terminate_job_request *req
fprintf
(
stderr
,
", status=%d"
,
req
->
status
);
}
static
void
dump_suspend_process_request
(
const
struct
suspend_process_request
*
req
)
{
fprintf
(
stderr
,
" handle=%04x"
,
req
->
handle
);
}
static
void
dump_resume_process_request
(
const
struct
resume_process_request
*
req
)
{
fprintf
(
stderr
,
" handle=%04x"
,
req
->
handle
);
}
static
const
dump_func
req_dumpers
[
REQ_NB_REQUESTS
]
=
{
(
dump_func
)
dump_new_process_request
,
(
dump_func
)
dump_exec_process_request
,
...
...
@@ -4879,6 +4889,8 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(
dump_func
)
dump_set_job_limits_request
,
(
dump_func
)
dump_set_job_completion_port_request
,
(
dump_func
)
dump_terminate_job_request
,
(
dump_func
)
dump_suspend_process_request
,
(
dump_func
)
dump_resume_process_request
,
};
static
const
dump_func
reply_dumpers
[
REQ_NB_REQUESTS
]
=
{
...
...
@@ -5178,6 +5190,8 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
};
static
const
char
*
const
req_names
[
REQ_NB_REQUESTS
]
=
{
...
...
@@ -5477,6 +5491,8 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"set_job_limits"
,
"set_job_completion_port"
,
"terminate_job"
,
"suspend_process"
,
"resume_process"
,
};
static
const
struct
...
...
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