Set or clear the BeingDebugged flag in the PEB when a debugger is
attached to or detached from a process.
Don't send exception events to the server unless a debugger is
present.
diff --git a/server/debugger.c b/server/debugger.c
index 5670617..e7c1b9a 100644
--- a/server/debugger.c
+++ b/server/debugger.c
@@ -436,6 +436,12 @@
resume_process( process );
return 0;
}
+ if (!set_process_debug_flag( process, 1 ))
+ {
+ process->debugger = NULL;
+ resume_process( process );
+ return 0;
+ }
return 1;
error:
@@ -480,8 +486,7 @@
/* remove relationships between process and its debugger */
process->debugger = NULL;
- release_object( debugger->debug_ctx );
- debugger->debug_ctx = NULL;
+ if (!set_process_debug_flag( process, 0 )) clear_error(); /* ignore error */
detach_process( process );
/* from this function */
diff --git a/server/process.c b/server/process.c
index 7be8afd..fd96614 100644
--- a/server/process.c
+++ b/server/process.c
@@ -271,6 +271,7 @@
process->idle_event = NULL;
process->queue = NULL;
process->atom_table = NULL;
+ process->peb = NULL;
process->ldt_copy = NULL;
process->exe.next = NULL;
process->exe.prev = NULL;
@@ -720,30 +721,6 @@
}
-/* get all information about a process */
-static void get_process_info( struct process *process, struct get_process_info_reply *reply )
-{
- reply->pid = get_process_id( process );
- reply->debugged = (process->debugger != 0);
- reply->exit_code = process->exit_code;
- reply->priority = process->priority;
- reply->process_affinity = process->affinity;
- reply->system_affinity = 1;
-}
-
-/* set all information about a process */
-static void set_process_info( struct process *process,
- const struct set_process_info_request *req )
-{
- if (req->mask & SET_PROCESS_INFO_PRIORITY)
- process->priority = req->priority;
- if (req->mask & SET_PROCESS_INFO_AFFINITY)
- {
- if (req->affinity != 1) set_error( STATUS_INVALID_PARAMETER );
- else process->affinity = req->affinity;
- }
-}
-
/* read data from a process memory space */
/* len is the total size (in ints) */
static int read_process_memory( struct process *process, const int *addr, size_t len, int *dest )
@@ -788,17 +765,18 @@
/* 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,
- unsigned int first_mask, unsigned int last_mask, const int *src )
+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 = process->thread_list;
+ int ret = 0;
assert( !((unsigned int)addr % sizeof(int) )); /* address must be aligned */
if (!thread) /* process is dead */
{
set_error( STATUS_ACCESS_DENIED );
- return;
+ return 0;
}
if (suspend_for_ptrace( thread ))
{
@@ -823,10 +801,23 @@
/* last word is special too */
if (write_thread_int( thread, addr, *src, last_mask ) == -1) goto done;
+ ret = 1;
done:
resume_after_ptrace( thread );
}
+ return ret;
+}
+
+/* set the debugged flag in the process PEB */
+int set_process_debug_flag( struct process *process, int flag )
+{
+ int mask = 0, data = 0;
+
+ /* BeingDebugged flag is the byte at offset 2 in the PEB */
+ memset( (char *)&mask + 2, 0xff, 1 );
+ memset( (char *)&data + 2, flag, 1 );
+ return write_process_memory( process, process->peb, 1, mask, mask, &data );
}
/* take a snapshot of currently running processes */
@@ -965,7 +956,18 @@
fatal_protocol_error( current, "init_process: called twice\n" );
return;
}
+ if (!req->peb || (unsigned int)req->peb % sizeof(int))
+ {
+ fatal_protocol_error( current, "init_process: bad peb address\n" );
+ return;
+ }
+ if (!req->ldt_copy || (unsigned int)req->ldt_copy % sizeof(int))
+ {
+ fatal_protocol_error( current, "init_process: bad ldt_copy address\n" );
+ return;
+ }
reply->info_size = 0;
+ current->process->peb = req->peb;
current->process->ldt_copy = req->ldt_copy;
current->process->startup_info = init_process( reply );
}
@@ -1002,7 +1004,7 @@
if (req->gui) process->idle_event = create_event( NULL, 0, 1, 0 );
if (current->suspend + process->suspend > 0) stop_thread( current );
- reply->debugged = (process->debugger != 0);
+ if (process->debugger) set_process_debug_flag( process, 1 );
}
/* open a handle to a process */
@@ -1037,7 +1039,11 @@
if ((process = get_process_from_handle( req->handle, PROCESS_QUERY_INFORMATION )))
{
- get_process_info( process, reply );
+ reply->pid = get_process_id( process );
+ reply->exit_code = process->exit_code;
+ reply->priority = process->priority;
+ reply->process_affinity = process->affinity;
+ reply->system_affinity = 1;
release_object( process );
}
}
@@ -1049,7 +1055,12 @@
if ((process = get_process_from_handle( req->handle, PROCESS_SET_INFORMATION )))
{
- set_process_info( process, req );
+ if (req->mask & SET_PROCESS_INFO_PRIORITY) process->priority = req->priority;
+ if (req->mask & SET_PROCESS_INFO_AFFINITY)
+ {
+ if (req->affinity != 1) set_error( STATUS_INVALID_PARAMETER );
+ else process->affinity = req->affinity;
+ }
release_object( process );
}
}
diff --git a/server/process.h b/server/process.h
index 10709d4..cd759f2 100644
--- a/server/process.h
+++ b/server/process.h
@@ -76,8 +76,8 @@
struct atom_table *atom_table; /* pointer to local atom table */
struct token *token; /* security token associated with this process */
struct process_dll exe; /* main exe file */
+ void *peb; /* PEB address in client address space */
void *ldt_copy; /* pointer to LDT copy in client addr space */
- void *ldt_flags; /* pointer to LDT flags in client addr space */
};
struct process_snapshot
@@ -107,6 +107,7 @@
extern struct process *get_process_from_handle( obj_handle_t handle, unsigned int access );
extern int process_set_debugger( struct process *process, struct thread *thread );
extern int debugger_detach( struct process* process, struct thread* debugger );
+extern int set_process_debug_flag( struct process *process, int flag );
extern void add_process_thread( struct process *process,
struct thread *thread );
diff --git a/server/protocol.def b/server/protocol.def
index e11111c..384eb24 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -229,6 +229,7 @@
/* Initialize a process; called from the new process context */
@REQ(init_process)
+ void* peb; /* addr of PEB */
void* ldt_copy; /* addr of LDT copy */
@REPLY
int create_flags; /* creation flags */
@@ -257,8 +258,6 @@
obj_handle_t exe_file; /* file handle for main exe */
int gui; /* is it a GUI process? */
VARARG(filename,unicode_str); /* file name of main exe */
-@REPLY
- int debugged; /* being debugged? */
@END
@@ -302,7 +301,6 @@
obj_handle_t handle; /* process handle */
@REPLY
process_id_t pid; /* server process id */
- int debugged; /* debugged? */
int exit_code; /* process exit code */
int priority; /* priority class */
int process_affinity; /* process affinity mask */
diff --git a/server/trace.c b/server/trace.c
index 99ae649..fb93e53 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -451,6 +451,7 @@
static void dump_init_process_request( const struct init_process_request *req )
{
+ fprintf( stderr, " peb=%p,", req->peb );
fprintf( stderr, " ldt_copy=%p", req->ldt_copy );
}
@@ -487,11 +488,6 @@
dump_varargs_unicode_str( cur_size );
}
-static void dump_init_process_done_reply( const struct init_process_done_reply *req )
-{
- fprintf( stderr, " debugged=%d", req->debugged );
-}
-
static void dump_init_thread_request( const struct init_thread_request *req )
{
fprintf( stderr, " unix_pid=%d,", req->unix_pid );
@@ -541,7 +537,6 @@
static void dump_get_process_info_reply( const struct get_process_info_reply *req )
{
fprintf( stderr, " pid=%04x,", req->pid );
- fprintf( stderr, " debugged=%d,", req->debugged );
fprintf( stderr, " exit_code=%d,", req->exit_code );
fprintf( stderr, " priority=%d,", req->priority );
fprintf( stderr, " process_affinity=%d,", req->process_affinity );
@@ -2738,7 +2733,7 @@
(dump_func)0,
(dump_func)dump_init_process_reply,
(dump_func)dump_get_startup_info_reply,
- (dump_func)dump_init_process_done_reply,
+ (dump_func)0,
(dump_func)dump_init_thread_reply,
(dump_func)dump_terminate_process_reply,
(dump_func)dump_terminate_thread_reply,