Generate CREATE_PROCESS/THREAD debug events internally in the server.

diff --git a/server/debugger.c b/server/debugger.c
index 01ce211..b62d0d3 100644
--- a/server/debugger.c
+++ b/server/debugger.c
@@ -97,30 +97,43 @@
                /* documented: THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME */
                                                               THREAD_ALL_ACCESS, FALSE )) == -1)
             return 0;
+        event->data.info.create_thread.teb   = thread->teb;
+        event->data.info.create_thread.start = thread->entry;
         break;
     case CREATE_PROCESS_DEBUG_EVENT:
-        if ((handle = event->data.info.create_process.file) != -1)
-        {
-            if ((handle = duplicate_handle( thread->process, handle, debugger->process,
-                                            GENERIC_READ, FALSE, 0 )) == -1)
-                return 0;
-            event->data.info.create_process.file = handle;
-        }
-        if ((event->data.info.create_process.process = alloc_handle( debugger->process, thread->process,
-                                           /* documented: PROCESS_VM_READ | PROCESS_VM_WRITE */
-                                                                PROCESS_ALL_ACCESS, FALSE )) == -1)
-        {
-            if (handle != -1) close_handle( debugger->process, handle );
+        if ((handle = alloc_handle( debugger->process, thread->process,
+                                    /* documented: PROCESS_VM_READ | PROCESS_VM_WRITE */
+                                    PROCESS_ALL_ACCESS, FALSE )) == -1)
             return 0;
-        }
-        if ((event->data.info.create_process.thread = alloc_handle( debugger->process, thread,
+        event->data.info.create_process.process = handle;
+
+        if ((handle = alloc_handle( debugger->process, thread,
                /* documented: THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME */
-                                                               THREAD_ALL_ACCESS, FALSE )) == -1)
+                                    THREAD_ALL_ACCESS, FALSE )) == -1)
         {
-            if (handle != -1) close_handle( debugger->process, handle );
             close_handle( debugger->process, event->data.info.create_process.process );
             return 0;
         }
+        event->data.info.create_process.thread = handle;
+
+        handle = -1;
+        if (thread->process->exe_file &&
+            ((handle = alloc_handle( debugger->process, thread->process->exe_file,
+                        /* the doc says write access too, but this doesn't seem a good idea */
+                                     GENERIC_READ, FALSE )) == -1))
+        {
+            close_handle( debugger->process, event->data.info.create_process.process );
+            close_handle( debugger->process, event->data.info.create_process.thread );
+            return 0;
+        }
+        event->data.info.create_process.file       = handle;
+        event->data.info.create_process.teb        = thread->teb;
+        event->data.info.create_process.base       = thread->process->module;
+        event->data.info.create_process.start      = thread->entry;
+        event->data.info.create_process.dbg_offset = 0;
+        event->data.info.create_process.dbg_size   = 0;
+        event->data.info.create_process.name       = 0;
+        event->data.info.create_process.unicode    = 0;
         break;
     case LOAD_DLL_DEBUG_EVENT:
         if ((handle = event->data.info.load_dll.handle) != -1)
@@ -131,6 +144,15 @@
             event->data.info.load_dll.handle = handle;
         }
         break;
+    case EXIT_PROCESS_DEBUG_EVENT:
+    case EXIT_THREAD_DEBUG_EVENT:
+        event->data.info.exit.exit_code = thread->exit_code;
+        break;
+    case EXCEPTION_DEBUG_EVENT:
+    case UNLOAD_DLL_DEBUG_EVENT:
+    case OUTPUT_DEBUG_STRING_EVENT:
+    case RIP_EVENT:
+        break;
     }
     return 1;
 }
@@ -189,7 +211,6 @@
         req->event.code = 0;
         req->pid  = 0;
         req->tid  = 0;
-        thread->error = signaled;
     }
 }
 
@@ -330,9 +351,10 @@
 }
 
 /* queue a debug event for a debugger */
-static struct debug_event *queue_debug_event( struct thread *debugger, struct thread *thread,
+static struct debug_event *queue_debug_event( struct thread *thread, int code,
                                               debug_event_t *data )
 {
+    struct thread *debugger = thread->process->debugger;
     struct debug_ctx *debug_ctx = debugger->debug_ctx;
     struct debug_event *event;
 
@@ -347,7 +369,8 @@
     event->state    = EVENT_QUEUED;
     event->sender   = (struct thread *)grab_object( thread );
     event->debugger = (struct thread *)grab_object( debugger );
-    memcpy( &event->data, data, sizeof(event->data) );
+    if (data) memcpy( &event->data, data, sizeof(event->data) );
+    event->data.code = code;
 
     if (!fill_debug_event( debugger, thread, event ))
     {
@@ -361,6 +384,16 @@
     return event;
 }
 
+/* generate a debug event from inside the server and queue it */
+void generate_debug_event( struct thread *thread, int code )
+{
+    if (thread->process->debugger)
+    {
+        struct debug_event *event = queue_debug_event( thread, code, NULL );
+        if (event) release_object( event );
+    }
+}
+
 /* return a pointer to the context in case the thread is inside an exception event */
 CONTEXT *get_debug_context( struct thread *thread )
 {
@@ -409,29 +442,14 @@
 }
 
 /* a thread is exiting */
-void debug_exit_thread( struct thread *thread, int exit_code )
+void debug_exit_thread( struct thread *thread )
 {
-    struct thread *debugger = thread->process->debugger;
-    struct debug_ctx *debug_ctx = thread->debug_ctx;
-
-    if (debugger)  /* being debugged -> send an event to the debugger */
-    {
-        struct debug_event *event;
-        debug_event_t exit;
-        exit.info.exit.exit_code = exit_code;
-        /* if this is the last thread, send an exit process event */
-        exit.code = ((thread->process->running_threads == 1) ?
-                     EXIT_PROCESS_DEBUG_EVENT : EXIT_THREAD_DEBUG_EVENT);
-        event = queue_debug_event( debugger, thread, &exit );
-        if (event) release_object( event );
-    }
-
-    if (debug_ctx)  /* this thread is a debugger */
+    if (thread->debug_ctx)  /* this thread is a debugger */
     {
         /* kill all debugged processes */
-        kill_debugged_processes( thread, exit_code );
+        kill_debugged_processes( thread, thread->exit_code );
+        release_object( thread->debug_ctx );
         thread->debug_ctx = NULL;
-        release_object( debug_ctx );
     }
 }
 
@@ -466,27 +484,30 @@
 DECL_HANDLER(debug_process)
 {
     struct process *process = get_process_from_id( req->pid );
-    if (process)
+    if (!process) return;
+    if (debugger_attach( process, current ))
     {
-        debugger_attach( process, current );
-        /* FIXME: should notify the debugged process somehow */
-        release_object( process );
+        struct thread *thread = process->thread_list;
+        generate_debug_event( thread, CREATE_PROCESS_DEBUG_EVENT );
+        while ((thread = thread->next)) generate_debug_event( thread, CREATE_THREAD_DEBUG_EVENT );
+        /* FIXME: load dll + breakpoint exception events */
     }
+    release_object( process );
 }
 
 /* Send a debug event */
 DECL_HANDLER(send_debug_event)
 {
-    struct thread *debugger = current->process->debugger;
     struct debug_event *event;
+    int code = req->event.code;
 
-    if ((req->event.code <= 0) || (req->event.code > RIP_EVENT))
+    if ((code <= 0) || (code > RIP_EVENT))
     {
-        fatal_protocol_error( current, "send_debug_event: bad code %d\n", req->event.code );
+        fatal_protocol_error( current, "send_debug_event: bad code %d\n", code );
         return;
     }
     req->status = 0;
-    if (debugger && ((event = queue_debug_event( debugger, current, &req->event ))))
+    if (current->process->debugger && ((event = queue_debug_event( current, code, &req->event ))))
     {
         /* wait for continue_debug_event */
         struct object *obj = &event->obj;
diff --git a/server/object.h b/server/object.h
index 0a7ad5d..3f87b85 100644
--- a/server/object.h
+++ b/server/object.h
@@ -154,7 +154,8 @@
 /* debugger functions */
 
 extern int debugger_attach( struct process *process, struct thread *debugger );
-extern void debug_exit_thread( struct thread *thread, int exit_code );
+extern void generate_debug_event( struct thread *thread, int code );
+extern void debug_exit_thread( struct thread *thread );
 extern CONTEXT *get_debug_context( struct thread *thread );
 
 /* mapping functions */
diff --git a/server/process.c b/server/process.c
index 0dd779d..9d01b5f 100644
--- a/server/process.c
+++ b/server/process.c
@@ -584,6 +584,9 @@
         fatal_protocol_error( current, "init_process_done: no event\n" );
         return;
     }
+    current->entry  = req->entry;
+    process->module = req->module;
+    generate_debug_event( current, CREATE_PROCESS_DEBUG_EVENT );
     set_event( process->init_event );
     release_object( process->init_event );
     process->init_event = NULL;
diff --git a/server/process.h b/server/process.h
index 873aad7..e8e7cc6 100644
--- a/server/process.h
+++ b/server/process.h
@@ -37,6 +37,7 @@
     struct event        *init_event;      /* event for init done */
     void                *ldt_copy;        /* pointer to LDT copy in client addr space */
     void                *ldt_flags;       /* pointer to LDT flags in client addr space */
+    void                *module;          /* main module base address */
     struct new_process_request *info;     /* startup info (freed after startup) */
 };
 
@@ -66,4 +67,6 @@
 extern void kill_debugged_processes( struct thread *debugger, int exit_code );
 extern struct process_snapshot *process_snap( int *count );
 
+static inline void *get_process_id( struct process *process ) { return process; }
+
 #endif  /* __WINE_SERVER_PROCESS_H */
diff --git a/server/thread.c b/server/thread.c
index b042158..14d7ea6 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -92,25 +92,32 @@
 /* allocate the buffer for the communication with the client */
 static int alloc_client_buffer( struct thread *thread )
 {
+    struct get_thread_buffer_request *req;
     int fd;
 
     if ((fd = create_anonymous_file()) == -1) return -1;
     if (ftruncate( fd, MAX_REQUEST_LENGTH ) == -1) goto error;
     if ((thread->buffer = mmap( 0, MAX_REQUEST_LENGTH, PROT_READ | PROT_WRITE,
                                 MAP_SHARED, fd, 0 )) == (void*)-1) goto error;
-    return fd;
+    /* build the first request into the buffer and send it */
+    req = thread->buffer;
+    req->pid  = get_process_id( thread->process );
+    req->tid  = get_thread_id( thread );
+    req->boot = (thread == booting_thread);
+    set_reply_fd( thread, fd );
+    send_reply( thread );
+    return 1;
 
  error:
     file_set_error();
     if (fd != -1) close( fd );
-    return -1;
+    return 0;
 }
 
 /* create a new thread */
 struct thread *create_thread( int fd, struct process *process, int suspend )
 {
     struct thread *thread;
-    int buf_fd;
 
     int flags = fcntl( fd, F_GETFL, 0 );
     fcntl( fd, F_SETFL, flags | O_NONBLOCK );
@@ -150,11 +157,8 @@
     first_thread = thread;
     add_process_thread( process, thread );
 
-    if ((buf_fd = alloc_client_buffer( thread )) == -1) goto error;
-
     set_select_events( &thread->obj, POLLIN );  /* start listening to events */
-    set_reply_fd( thread, buf_fd );  /* send the fd to the client */
-    send_reply( thread );
+    if (!alloc_client_buffer( thread )) goto error;
     return thread;
 
  error:
@@ -560,7 +564,9 @@
     if (current == thread) current = NULL;
     if (debug_level) trace_kill( thread );
     if (thread->wait) end_wait( thread );
-    debug_exit_thread( thread, exit_code );
+    generate_debug_event( thread, (thread->process->running_threads == 1) ?
+                          EXIT_PROCESS_DEBUG_EVENT : EXIT_THREAD_DEBUG_EVENT );
+    debug_exit_thread( thread );
     abandon_mutexes( thread );
     remove_process_thread( thread->process, thread );
     wake_up( &thread->obj, 0 );
@@ -623,10 +629,10 @@
     }
     current->unix_pid = req->unix_pid;
     current->teb      = req->teb;
+    current->entry    = req->entry;
     if (current->suspend + current->process->suspend > 0) stop_thread( current );
-    req->pid  = current->process;
-    req->tid  = current;
-    req->boot = (current == booting_thread);
+    if (current->process->running_threads > 1)
+        generate_debug_event( current, CREATE_THREAD_DEBUG_EVENT );
 }
 
 /* terminate a thread */
diff --git a/server/thread.h b/server/thread.h
index 5e46493..9cc088d 100644
--- a/server/thread.h
+++ b/server/thread.h
@@ -48,6 +48,7 @@
     int                 exit_code; /* thread exit code */
     int                 unix_pid;  /* Unix pid of client */
     void               *teb;       /* TEB address (in client address space) */
+    void               *entry;     /* thread entry point (in client address space) */
     int                 priority;  /* priority level */
     int                 affinity;  /* affinity mask */
     int                 suspend;   /* suspend count */
@@ -92,4 +93,6 @@
 static inline void set_error( int err ) { current->error = err; }
 static inline void clear_error(void)    { set_error(0); }
 
+static inline void *get_thread_id( struct thread *thread ) { return thread; }
+
 #endif  /* __WINE_SERVER_THREAD_H */
diff --git a/server/trace.c b/server/trace.c
index c38f7db..79ffa2e 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -258,25 +258,26 @@
 
 static void dump_init_process_done_request( const struct init_process_done_request *req )
 {
-    fprintf( stderr, " dummy=%d", req->dummy );
+    fprintf( stderr, " module=%p,", req->module );
+    fprintf( stderr, " entry=%p", req->entry );
 }
 
 static void dump_init_thread_request( const struct init_thread_request *req )
 {
     fprintf( stderr, " unix_pid=%d,", req->unix_pid );
-    fprintf( stderr, " teb=%p", req->teb );
-}
-
-static void dump_init_thread_reply( const struct init_thread_request *req )
-{
-    fprintf( stderr, " pid=%p,", req->pid );
-    fprintf( stderr, " tid=%p,", req->tid );
-    fprintf( stderr, " boot=%d", req->boot );
+    fprintf( stderr, " teb=%p,", req->teb );
+    fprintf( stderr, " entry=%p", req->entry );
 }
 
 static void dump_get_thread_buffer_request( const struct get_thread_buffer_request *req )
 {
-    fprintf( stderr, " dummy=%d", req->dummy );
+}
+
+static void dump_get_thread_buffer_reply( const struct get_thread_buffer_request *req )
+{
+    fprintf( stderr, " pid=%p,", req->pid );
+    fprintf( stderr, " tid=%p,", req->tid );
+    fprintf( stderr, " boot=%d", req->boot );
 }
 
 static void dump_terminate_process_request( const struct terminate_process_request *req )
@@ -1329,8 +1330,8 @@
     (dump_func)0,
     (dump_func)dump_init_process_reply,
     (dump_func)0,
-    (dump_func)dump_init_thread_reply,
     (dump_func)0,
+    (dump_func)dump_get_thread_buffer_reply,
     (dump_func)0,
     (dump_func)0,
     (dump_func)dump_get_process_info_reply,