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;