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
73c72390
Commit
73c72390
authored
Nov 02, 2005
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixed Get/SetThreadContext to work properly on suspended threads.
Added a test case.
parent
9f9fd408
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
297 additions
and
64 deletions
+297
-64
thread.c
dlls/kernel/tests/thread.c
+41
-0
exception.c
dlls/ntdll/exception.c
+37
-0
ntdll_misc.h
dlls/ntdll/ntdll_misc.h
+2
-0
signal_i386.c
dlls/ntdll/signal_i386.c
+91
-39
signal_powerpc.c
dlls/ntdll/signal_powerpc.c
+4
-4
signal_sparc.c
dlls/ntdll/signal_sparc.c
+4
-4
signal_x86_64.c
dlls/ntdll/signal_x86_64.c
+4
-4
thread.c
dlls/ntdll/thread.c
+56
-4
server_protocol.h
include/wine/server_protocol.h
+3
-2
protocol.def
server/protocol.def
+2
-0
thread.c
server/thread.c
+48
-5
thread.h
server/thread.h
+1
-0
trace.c
server/trace.c
+4
-2
No files found.
dlls/kernel/tests/thread.c
View file @
73c72390
...
...
@@ -607,6 +607,44 @@ static VOID test_GetThreadExitCode(void)
ok
(
CloseHandle
(
thread
)
!=
0
,
"Error closing thread handle
\n
"
);
}
#ifdef __i386__
static
int
test_value
=
0
;
static
void
set_test_val
(
int
val
)
{
test_value
+=
val
;
}
static
DWORD
WINAPI
threadFunc6
(
LPVOID
p
)
{
test_value
*=
(
int
)
p
;
return
0
;
}
static
void
test_SetThreadContext
(
void
)
{
CONTEXT
ctx
;
int
*
stack
;
HANDLE
thread
=
CreateThread
(
NULL
,
0
,
threadFunc6
,
(
void
*
)
2
,
CREATE_SUSPENDED
,
NULL
);
ctx
.
ContextFlags
=
CONTEXT_FULL
;
ok
(
GetThreadContext
(
thread
,
&
ctx
),
"GetThreadContext failed
\n
"
);
/* simulate a call to set_test_val(10) */
stack
=
(
int
*
)
ctx
.
Esp
;
stack
[
-
1
]
=
10
;
stack
[
-
2
]
=
ctx
.
Eip
;
ctx
.
Esp
-=
2
*
sizeof
(
int
*
);
ctx
.
Eip
=
(
DWORD
)
set_test_val
;
ok
(
SetThreadContext
(
thread
,
&
ctx
),
"SetThreadContext failed
\n
"
);
ResumeThread
(
thread
);
WaitForSingleObject
(
thread
,
INFINITE
);
ok
(
test_value
==
20
,
"test_value %d instead of 20
\n
"
,
test_value
);
}
#endif
/* __i386__ */
START_TEST
(
thread
)
{
HINSTANCE
lib
;
...
...
@@ -628,4 +666,7 @@ START_TEST(thread)
test_GetThreadTimes
();
test_thread_processor
();
test_GetThreadExitCode
();
#ifdef __i386__
test_SetThreadContext
();
#endif
}
dlls/ntdll/exception.c
View file @
73c72390
...
...
@@ -143,6 +143,43 @@ extern DWORD EXC_CallHandler( EXCEPTION_RECORD *record, EXCEPTION_REGISTRATION_R
#endif
/**********************************************************************
* wait_suspend
*
* Wait until the thread is no longer suspended.
*/
void
wait_suspend
(
CONTEXT
*
context
)
{
LARGE_INTEGER
timeout
;
/* store the context we got at suspend time */
SERVER_START_REQ
(
set_thread_context
)
{
req
->
handle
=
GetCurrentThread
();
req
->
flags
=
CONTEXT_FULL
;
req
->
suspend
=
1
;
wine_server_add_data
(
req
,
context
,
sizeof
(
*
context
)
);
wine_server_call
(
req
);
}
SERVER_END_REQ
;
/* wait with 0 timeout, will only return once the thread is no longer suspended */
timeout
.
QuadPart
=
0
;
NTDLL_wait_for_multiple_objects
(
0
,
NULL
,
0
,
&
timeout
,
0
);
/* retrieve the new context */
SERVER_START_REQ
(
get_thread_context
)
{
req
->
handle
=
GetCurrentThread
();
req
->
flags
=
CONTEXT_FULL
;
req
->
suspend
=
1
;
wine_server_set_reply
(
req
,
context
,
sizeof
(
*
context
)
);
wine_server_call
(
req
);
}
SERVER_END_REQ
;
}
/**********************************************************************
* send_debug_event
*
* Send an EXCEPTION_DEBUG_EVENT event to the debugger.
...
...
dlls/ntdll/ntdll_misc.h
View file @
73c72390
...
...
@@ -30,6 +30,8 @@
#define MAX_NT_PATH_LENGTH 277
/* exceptions */
extern
void
wait_suspend
(
CONTEXT
*
context
);
extern
void
WINAPI
__regs_RtlRaiseException
(
PEXCEPTION_RECORD
,
PCONTEXT
);
/* debug helper */
...
...
dlls/ntdll/signal_i386.c
View file @
73c72390
...
...
@@ -85,7 +85,7 @@ typedef struct
unsigned
long
i387
;
unsigned
long
oldmask
;
unsigned
long
cr2
;
}
SIGCONTEXT
;
}
volatile
SIGCONTEXT
;
#define HANDLER_DEF(name) void name( int __signal, SIGCONTEXT __context )
#define HANDLER_CONTEXT (&__context)
...
...
@@ -641,12 +641,24 @@ typedef void (WINAPI *raise_func)( EXCEPTION_RECORD *rec, CONTEXT *context );
*
* Handler initialization when the full context is not needed.
*/
static
void
*
init_handler
(
const
SIGCONTEXT
*
sigcontext
)
inline
static
void
*
init_handler
(
const
SIGCONTEXT
*
sigcontext
,
WORD
*
fs
,
WORD
*
gs
)
{
void
*
stack
=
(
void
*
)
ESP_sig
(
sigcontext
);
TEB
*
teb
=
get_current_teb
();
struct
ntdll_thread_data
*
thread_data
=
(
struct
ntdll_thread_data
*
)
teb
->
SystemReserved2
;
/* get %fs and %gs at time of the fault */
#ifdef FS_sig
*
fs
=
LOWORD
(
FS_sig
(
sigcontext
));
#else
*
fs
=
wine_get_fs
();
#endif
#ifdef GS_sig
*
gs
=
LOWORD
(
GS_sig
(
sigcontext
));
#else
*
gs
=
wine_get_gs
();
#endif
wine_set_fs
(
thread_data
->
teb_sel
);
/* now restore a proper %gs for the fault handler */
...
...
@@ -718,6 +730,67 @@ inline static void restore_fpu( CONTEXT *context )
/***********************************************************************
* save_context
*
* Build a context structure from the signal info.
*/
inline
static
void
save_context
(
CONTEXT
*
context
,
const
SIGCONTEXT
*
sigcontext
,
WORD
fs
,
WORD
gs
)
{
context
->
ContextFlags
=
CONTEXT_FULL
;
context
->
Eax
=
EAX_sig
(
sigcontext
);
context
->
Ebx
=
EBX_sig
(
sigcontext
);
context
->
Ecx
=
ECX_sig
(
sigcontext
);
context
->
Edx
=
EDX_sig
(
sigcontext
);
context
->
Esi
=
ESI_sig
(
sigcontext
);
context
->
Edi
=
EDI_sig
(
sigcontext
);
context
->
Ebp
=
EBP_sig
(
sigcontext
);
context
->
EFlags
=
EFL_sig
(
sigcontext
);
context
->
Eip
=
EIP_sig
(
sigcontext
);
context
->
Esp
=
ESP_sig
(
sigcontext
);
context
->
SegCs
=
LOWORD
(
CS_sig
(
sigcontext
));
context
->
SegDs
=
LOWORD
(
DS_sig
(
sigcontext
));
context
->
SegEs
=
LOWORD
(
ES_sig
(
sigcontext
));
context
->
SegFs
=
fs
;
context
->
SegGs
=
gs
;
context
->
SegSs
=
LOWORD
(
SS_sig
(
sigcontext
));
}
/***********************************************************************
* restore_context
*
* Restore the signal info from the context.
*/
inline
static
void
restore_context
(
const
CONTEXT
*
context
,
SIGCONTEXT
*
sigcontext
)
{
EAX_sig
(
sigcontext
)
=
context
->
Eax
;
EBX_sig
(
sigcontext
)
=
context
->
Ebx
;
ECX_sig
(
sigcontext
)
=
context
->
Ecx
;
EDX_sig
(
sigcontext
)
=
context
->
Edx
;
ESI_sig
(
sigcontext
)
=
context
->
Esi
;
EDI_sig
(
sigcontext
)
=
context
->
Edi
;
EBP_sig
(
sigcontext
)
=
context
->
Ebp
;
EFL_sig
(
sigcontext
)
=
context
->
EFlags
;
EIP_sig
(
sigcontext
)
=
context
->
Eip
;
ESP_sig
(
sigcontext
)
=
context
->
Esp
;
CS_sig
(
sigcontext
)
=
context
->
SegCs
;
DS_sig
(
sigcontext
)
=
context
->
SegDs
;
ES_sig
(
sigcontext
)
=
context
->
SegEs
;
SS_sig
(
sigcontext
)
=
context
->
SegSs
;
#ifdef GS_sig
GS_sig
(
sigcontext
)
=
context
->
SegGs
;
#else
wine_set_gs
(
context
->
SegGs
);
#endif
#ifdef FS_sig
FS_sig
(
sigcontext
)
=
context
->
SegFs
;
#else
wine_set_fs
(
context
->
SegFs
);
#endif
}
/***********************************************************************
* setup_exception
*
* Setup a proper stack frame for the raise function, and modify the
...
...
@@ -740,19 +813,7 @@ static EXCEPTION_RECORD *setup_exception( SIGCONTEXT *sigcontext, raise_func fun
WORD
fs
,
gs
;
/* get %fs and %gs at time of the fault */
#ifdef FS_sig
fs
=
LOWORD
(
FS_sig
(
sigcontext
));
#else
fs
=
wine_get_fs
();
#endif
#ifdef GS_sig
gs
=
LOWORD
(
GS_sig
(
sigcontext
));
#else
gs
=
wine_get_gs
();
#endif
stack
=
init_handler
(
sigcontext
);
stack
=
init_handler
(
sigcontext
,
&
fs
,
&
gs
);
/* stack sanity checks */
...
...
@@ -792,23 +853,7 @@ static EXCEPTION_RECORD *setup_exception( SIGCONTEXT *sigcontext, raise_func fun
stack
->
rec
.
ExceptionAddress
=
(
LPVOID
)
EIP_sig
(
sigcontext
);
stack
->
rec
.
NumberParameters
=
0
;
stack
->
context
.
ContextFlags
=
CONTEXT_FULL
;
stack
->
context
.
Eax
=
EAX_sig
(
sigcontext
);
stack
->
context
.
Ebx
=
EBX_sig
(
sigcontext
);
stack
->
context
.
Ecx
=
ECX_sig
(
sigcontext
);
stack
->
context
.
Edx
=
EDX_sig
(
sigcontext
);
stack
->
context
.
Esi
=
ESI_sig
(
sigcontext
);
stack
->
context
.
Edi
=
EDI_sig
(
sigcontext
);
stack
->
context
.
Ebp
=
EBP_sig
(
sigcontext
);
stack
->
context
.
EFlags
=
EFL_sig
(
sigcontext
);
stack
->
context
.
Eip
=
EIP_sig
(
sigcontext
);
stack
->
context
.
Esp
=
ESP_sig
(
sigcontext
);
stack
->
context
.
SegCs
=
LOWORD
(
CS_sig
(
sigcontext
));
stack
->
context
.
SegDs
=
LOWORD
(
DS_sig
(
sigcontext
));
stack
->
context
.
SegEs
=
LOWORD
(
ES_sig
(
sigcontext
));
stack
->
context
.
SegFs
=
fs
;
stack
->
context
.
SegGs
=
gs
;
stack
->
context
.
SegSs
=
LOWORD
(
SS_sig
(
sigcontext
));
save_context
(
&
stack
->
context
,
sigcontext
,
fs
,
gs
);
/* now modify the sigcontext to return to the raise function */
ESP_sig
(
sigcontext
)
=
(
DWORD
)
stack
;
...
...
@@ -1108,10 +1153,13 @@ static HANDLER_DEF(fpe_handler)
* int_handler
*
* Handler for SIGINT.
*
* FIXME: should not be calling external functions on the signal stack.
*/
static
HANDLER_DEF
(
int_handler
)
{
init_handler
(
HANDLER_CONTEXT
);
WORD
fs
,
gs
;
init_handler
(
HANDLER_CONTEXT
,
&
fs
,
&
gs
);
if
(
!
dispatch_signal
(
SIGINT
))
{
EXCEPTION_RECORD
*
rec
=
setup_exception
(
HANDLER_CONTEXT
,
__regs_RtlRaiseException
);
...
...
@@ -1139,7 +1187,8 @@ static HANDLER_DEF(abrt_handler)
*/
static
HANDLER_DEF
(
term_handler
)
{
init_handler
(
HANDLER_CONTEXT
);
WORD
fs
,
gs
;
init_handler
(
HANDLER_CONTEXT
,
&
fs
,
&
gs
);
server_abort_thread
(
0
);
}
...
...
@@ -1151,12 +1200,13 @@ static HANDLER_DEF(term_handler)
*/
static
HANDLER_DEF
(
usr1_handler
)
{
LARGE_INTEGER
timeout
;
WORD
fs
,
gs
;
CONTEXT
context
;
init_handler
(
HANDLER_CONTEXT
);
/* wait with 0 timeout, will only return once the thread is no longer suspended */
timeout
.
QuadPart
=
0
;
NTDLL_wait_for_multiple_objects
(
0
,
NULL
,
0
,
&
timeout
,
0
);
init_handler
(
HANDLER_CONTEXT
,
&
fs
,
&
gs
);
save_context
(
&
context
,
HANDLER_CONTEXT
,
fs
,
gs
);
wait_suspend
(
&
context
)
;
restore_context
(
&
context
,
HANDLER_CONTEXT
);
}
...
...
@@ -1198,6 +1248,7 @@ static int set_handler( int sig, int have_sigaltstack, void (*func)() )
sig_act
.
ksa_handler
=
func
;
sig_act
.
ksa_flags
=
SA_RESTART
;
sig_act
.
ksa_mask
=
(
1
<<
(
SIGINT
-
1
))
|
(
1
<<
(
SIGUSR1
-
1
))
|
(
1
<<
(
SIGUSR2
-
1
));
/* point to the top of the signal stack */
sig_act
.
ksa_restorer
=
(
char
*
)
get_signal_stack
()
+
signal_stack_size
;
...
...
@@ -1207,6 +1258,7 @@ static int set_handler( int sig, int have_sigaltstack, void (*func)() )
sig_act
.
sa_handler
=
func
;
sigemptyset
(
&
sig_act
.
sa_mask
);
sigaddset
(
&
sig_act
.
sa_mask
,
SIGINT
);
sigaddset
(
&
sig_act
.
sa_mask
,
SIGUSR1
);
sigaddset
(
&
sig_act
.
sa_mask
,
SIGUSR2
);
#if defined(linux) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
...
...
dlls/ntdll/signal_powerpc.c
View file @
73c72390
...
...
@@ -577,11 +577,11 @@ static HANDLER_DEF(term_handler)
*/
static
HANDLER_DEF
(
usr1_handler
)
{
LARGE_INTEGER
timeou
t
;
CONTEXT
contex
t
;
/* wait with 0 timeout, will only return once the thread is no longer suspended */
timeout
.
QuadPart
=
0
;
NTDLL_wait_for_multiple_objects
(
0
,
NULL
,
0
,
&
timeout
,
0
);
save_context
(
&
context
,
HANDLER_CONTEXT
);
wait_suspend
(
&
context
)
;
restore_context
(
&
context
,
HANDLER_CONTEXT
);
}
...
...
dlls/ntdll/signal_sparc.c
View file @
73c72390
...
...
@@ -384,11 +384,11 @@ static HANDLER_DEF(term_handler)
*/
static
HANDLER_DEF
(
usr1_handler
)
{
LARGE_INTEGER
timeou
t
;
CONTEXT
contex
t
;
/* wait with 0 timeout, will only return once the thread is no longer suspended */
timeout
.
QuadPart
=
0
;
NTDLL_wait_for_multiple_objects
(
0
,
NULL
,
0
,
&
timeout
,
0
);
save_context
(
&
context
,
HANDLER_CONTEXT
);
wait_suspend
(
&
context
)
;
restore_context
(
&
context
,
HANDLER_CONTEXT
);
}
...
...
dlls/ntdll/signal_x86_64.c
View file @
73c72390
...
...
@@ -408,11 +408,11 @@ static HANDLER_DEF(term_handler)
*/
static
HANDLER_DEF
(
usr1_handler
)
{
LARGE_INTEGER
timeou
t
;
CONTEXT
contex
t
;
/* wait with 0 timeout, will only return once the thread is no longer suspended */
timeout
.
QuadPart
=
0
;
NTDLL_wait_for_multiple_objects
(
0
,
NULL
,
0
,
&
timeout
,
0
);
save_context
(
&
context
,
HANDLER_CONTEXT
);
wait_suspend
(
&
context
)
;
restore_context
(
&
context
,
HANDLER_CONTEXT
);
}
...
...
dlls/ntdll/thread.c
View file @
73c72390
...
...
@@ -485,15 +485,41 @@ NTSTATUS WINAPI NtQueueApcThread( HANDLE handle, PNTAPCFUNC func, ULONG_PTR arg1
NTSTATUS
WINAPI
NtSetContextThread
(
HANDLE
handle
,
const
CONTEXT
*
context
)
{
NTSTATUS
ret
;
DWORD
dummy
,
i
;
SERVER_START_REQ
(
set_thread_context
)
{
req
->
handle
=
handle
;
req
->
flags
=
context
->
ContextFlags
;
req
->
handle
=
handle
;
req
->
flags
=
context
->
ContextFlags
;
req
->
suspend
=
0
;
wine_server_add_data
(
req
,
context
,
sizeof
(
*
context
)
);
ret
=
wine_server_call
(
req
);
}
SERVER_END_REQ
;
if
(
ret
==
STATUS_PENDING
)
{
if
(
NtSuspendThread
(
handle
,
&
dummy
)
==
STATUS_SUCCESS
)
{
for
(
i
=
0
;
i
<
100
;
i
++
)
{
SERVER_START_REQ
(
set_thread_context
)
{
req
->
handle
=
handle
;
req
->
flags
=
context
->
ContextFlags
;
req
->
suspend
=
0
;
wine_server_add_data
(
req
,
context
,
sizeof
(
*
context
)
);
ret
=
wine_server_call
(
req
);
}
SERVER_END_REQ
;
if
(
ret
!=
STATUS_PENDING
)
break
;
NtYieldExecution
();
}
NtResumeThread
(
handle
,
&
dummy
);
}
}
if
(
ret
==
STATUS_PENDING
)
ret
=
STATUS_ACCESS_DENIED
;
return
ret
;
}
...
...
@@ -731,16 +757,42 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
{
NTSTATUS
ret
;
CONTEXT
ctx
;
DWORD
dummy
,
i
;
SERVER_START_REQ
(
get_thread_context
)
{
req
->
handle
=
handle
;
req
->
flags
=
context
->
ContextFlags
;
req
->
handle
=
handle
;
req
->
flags
=
context
->
ContextFlags
;
req
->
suspend
=
0
;
wine_server_set_reply
(
req
,
&
ctx
,
sizeof
(
ctx
)
);
ret
=
wine_server_call
(
req
);
}
SERVER_END_REQ
;
if
(
ret
==
STATUS_PENDING
)
{
if
(
NtSuspendThread
(
handle
,
&
dummy
)
==
STATUS_SUCCESS
)
{
for
(
i
=
0
;
i
<
100
;
i
++
)
{
SERVER_START_REQ
(
get_thread_context
)
{
req
->
handle
=
handle
;
req
->
flags
=
context
->
ContextFlags
;
req
->
suspend
=
0
;
wine_server_set_reply
(
req
,
&
ctx
,
sizeof
(
ctx
)
);
ret
=
wine_server_call
(
req
);
}
SERVER_END_REQ
;
if
(
ret
!=
STATUS_PENDING
)
break
;
NtYieldExecution
();
}
NtResumeThread
(
handle
,
&
dummy
);
}
}
if
(
ret
==
STATUS_SUCCESS
)
copy_context
(
context
,
&
ctx
,
context
->
ContextFlags
);
else
if
(
ret
==
STATUS_PENDING
)
ret
=
STATUS_ACCESS_DENIED
;
return
ret
;
}
...
...
include/wine/server_protocol.h
View file @
73c72390
...
...
@@ -1572,7 +1572,6 @@ struct get_exception_status_request
struct
get_exception_status_reply
{
struct
reply_header
__header
;
int
status
;
/* VARARG(context,context); */
};
...
...
@@ -1952,6 +1951,7 @@ struct get_thread_context_request
struct
request_header
__header
;
obj_handle_t
handle
;
unsigned
int
flags
;
int
suspend
;
};
struct
get_thread_context_reply
{
...
...
@@ -1966,6 +1966,7 @@ struct set_thread_context_request
struct
request_header
__header
;
obj_handle_t
handle
;
unsigned
int
flags
;
int
suspend
;
/* VARARG(context,context); */
};
struct
set_thread_context_reply
...
...
@@ -4207,6 +4208,6 @@ union generic_reply
struct
set_mailslot_info_reply
set_mailslot_info_reply
;
};
#define SERVER_PROTOCOL_VERSION 19
6
#define SERVER_PROTOCOL_VERSION 19
7
#endif
/* __WINE_WINE_SERVER_PROTOCOL_H */
server/protocol.def
View file @
73c72390
...
...
@@ -1401,6 +1401,7 @@ enum char_info_mode
@REQ(get_thread_context)
obj_handle_t handle; /* thread handle */
unsigned int flags; /* context flags */
int suspend; /* if getting context during suspend */
@REPLY
VARARG(context,context); /* thread context */
@END
...
...
@@ -1410,6 +1411,7 @@ enum char_info_mode
@REQ(set_thread_context)
obj_handle_t handle; /* thread handle */
unsigned int flags; /* context flags */
int suspend; /* if setting context during suspend */
VARARG(context,context); /* thread context */
@END
...
...
server/thread.c
View file @
73c72390
...
...
@@ -118,6 +118,7 @@ inline static void init_thread_structure( struct thread *thread )
thread
->
unix_pid
=
-
1
;
/* not known yet */
thread
->
unix_tid
=
-
1
;
/* not known yet */
thread
->
context
=
NULL
;
thread
->
suspend_context
=
NULL
;
thread
->
teb
=
NULL
;
thread
->
debug_ctx
=
NULL
;
thread
->
debug_event
=
NULL
;
...
...
@@ -212,6 +213,7 @@ static void cleanup_thread( struct thread *thread )
if
(
thread
->
request_fd
)
release_object
(
thread
->
request_fd
);
if
(
thread
->
reply_fd
)
release_object
(
thread
->
reply_fd
);
if
(
thread
->
wait_fd
)
release_object
(
thread
->
wait_fd
);
if
(
thread
->
suspend_context
)
free
(
thread
->
suspend_context
);
free_msg_queue
(
thread
);
cleanup_clipboard_thread
(
thread
);
destroy_thread_windows
(
thread
);
...
...
@@ -229,19 +231,19 @@ static void cleanup_thread( struct thread *thread )
thread
->
request_fd
=
NULL
;
thread
->
reply_fd
=
NULL
;
thread
->
wait_fd
=
NULL
;
thread
->
context
=
NULL
;
thread
->
suspend_context
=
NULL
;
thread
->
desktop
=
0
;
}
/* destroy a thread when its refcount is 0 */
static
void
destroy_thread
(
struct
object
*
obj
)
{
struct
thread_apc
*
apc
;
struct
thread
*
thread
=
(
struct
thread
*
)
obj
;
assert
(
obj
->
ops
==
&
thread_ops
);
assert
(
!
thread
->
debug_ctx
);
/* cannot still be debugging something */
list_remove
(
&
thread
->
entry
);
while
((
apc
=
thread_dequeue_apc
(
thread
,
0
)))
free
(
apc
);
cleanup_thread
(
thread
);
release_object
(
thread
->
process
);
if
(
thread
->
id
)
free_ptid
(
thread
->
id
);
...
...
@@ -1053,7 +1055,27 @@ DECL_HANDLER(get_thread_context)
}
if
(
!
(
thread
=
get_thread_from_handle
(
req
->
handle
,
THREAD_GET_CONTEXT
)))
return
;
if
((
data
=
set_reply_data_size
(
sizeof
(
CONTEXT
)
)))
if
(
req
->
suspend
)
{
if
(
thread
!=
current
||
!
thread
->
suspend_context
)
{
/* not suspended, shouldn't happen */
set_error
(
STATUS_INVALID_PARAMETER
);
}
else
{
if
(
thread
->
context
==
thread
->
suspend_context
)
thread
->
context
=
NULL
;
set_reply_data_ptr
(
thread
->
suspend_context
,
sizeof
(
CONTEXT
)
);
thread
->
suspend_context
=
NULL
;
}
}
else
if
(
thread
!=
current
&&
!
thread
->
context
)
{
/* thread is not suspended, retry (if it's still running) */
if
(
thread
->
state
!=
RUNNING
)
set_error
(
STATUS_ACCESS_DENIED
);
else
set_error
(
STATUS_PENDING
);
}
else
if
((
data
=
set_reply_data_size
(
sizeof
(
CONTEXT
)
)))
{
memset
(
data
,
0
,
sizeof
(
CONTEXT
)
);
get_thread_context
(
thread
,
data
,
req
->
flags
);
...
...
@@ -1071,11 +1093,32 @@ DECL_HANDLER(set_thread_context)
set_error
(
STATUS_INVALID_PARAMETER
);
return
;
}
if
((
thread
=
get_thread_from_handle
(
req
->
handle
,
THREAD_SET_CONTEXT
)))
if
(
!
(
thread
=
get_thread_from_handle
(
req
->
handle
,
THREAD_SET_CONTEXT
)))
return
;
if
(
req
->
suspend
)
{
if
(
thread
!=
current
||
thread
->
context
)
{
/* nested suspend or exception, shouldn't happen */
set_error
(
STATUS_INVALID_PARAMETER
);
}
else
if
((
thread
->
suspend_context
=
mem_alloc
(
sizeof
(
CONTEXT
)
)))
{
memcpy
(
thread
->
suspend_context
,
get_req_data
(),
sizeof
(
CONTEXT
)
);
thread
->
context
=
thread
->
suspend_context
;
}
}
else
if
(
thread
!=
current
&&
!
thread
->
context
)
{
/* thread is not suspended, retry (if it's still running) */
if
(
thread
->
state
!=
RUNNING
)
set_error
(
STATUS_ACCESS_DENIED
);
else
set_error
(
STATUS_PENDING
);
}
else
{
set_thread_context
(
thread
,
get_req_data
(),
req
->
flags
);
release_object
(
thread
);
}
release_object
(
thread
);
}
/* fetch a selector entry for a thread */
...
...
server/thread.h
View file @
73c72390
...
...
@@ -78,6 +78,7 @@ struct thread
int
unix_pid
;
/* Unix pid of client */
int
unix_tid
;
/* Unix tid of client */
CONTEXT
*
context
;
/* current context if in an exception handler */
CONTEXT
*
suspend_context
;
/* current context if suspended */
void
*
teb
;
/* TEB address (in client address space) */
int
priority
;
/* priority level */
int
affinity
;
/* affinity mask */
...
...
server/trace.c
View file @
73c72390
...
...
@@ -1577,7 +1577,6 @@ static void dump_get_exception_status_request( const struct get_exception_status
static
void
dump_get_exception_status_reply
(
const
struct
get_exception_status_reply
*
req
)
{
fprintf
(
stderr
,
" status=%d,"
,
req
->
status
);
fprintf
(
stderr
,
" context="
);
dump_varargs_context
(
cur_size
);
}
...
...
@@ -1856,7 +1855,8 @@ static void dump_get_timer_info_reply( const struct get_timer_info_reply *req )
static
void
dump_get_thread_context_request
(
const
struct
get_thread_context_request
*
req
)
{
fprintf
(
stderr
,
" handle=%p,"
,
req
->
handle
);
fprintf
(
stderr
,
" flags=%08x"
,
req
->
flags
);
fprintf
(
stderr
,
" flags=%08x,"
,
req
->
flags
);
fprintf
(
stderr
,
" suspend=%d"
,
req
->
suspend
);
}
static
void
dump_get_thread_context_reply
(
const
struct
get_thread_context_reply
*
req
)
...
...
@@ -1869,6 +1869,7 @@ static void dump_set_thread_context_request( const struct set_thread_context_req
{
fprintf
(
stderr
,
" handle=%p,"
,
req
->
handle
);
fprintf
(
stderr
,
" flags=%08x,"
,
req
->
flags
);
fprintf
(
stderr
,
" suspend=%d,"
,
req
->
suspend
);
fprintf
(
stderr
,
" context="
);
dump_varargs_context
(
cur_size
);
}
...
...
@@ -3740,6 +3741,7 @@ static const struct
{
"FILE_IS_A_DIRECTORY"
,
STATUS_FILE_IS_A_DIRECTORY
},
{
"FILE_LOCK_CONFLICT"
,
STATUS_FILE_LOCK_CONFLICT
},
{
"HANDLE_NOT_CLOSABLE"
,
STATUS_HANDLE_NOT_CLOSABLE
},
{
"INSTANCE_NOT_AVAILABLE"
,
STATUS_INSTANCE_NOT_AVAILABLE
},
{
"INVALID_CID"
,
STATUS_INVALID_CID
},
{
"INVALID_FILE_FOR_SECTION"
,
STATUS_INVALID_FILE_FOR_SECTION
},
{
"INVALID_HANDLE"
,
STATUS_INVALID_HANDLE
},
...
...
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