diff --git a/dlls/kernel/debugger.c b/dlls/kernel/debugger.c
index fbe8ff6aba6c205cda54ed2c3b32f52f62ba47b5..1b6a90c3790158b91d14ec8bed794fc540a94568 100644
--- a/dlls/kernel/debugger.c
+++ b/dlls/kernel/debugger.c
@@ -150,7 +150,7 @@ BOOL WINAPI ContinueDebugEvent(
 /**********************************************************************
  *           DebugActiveProcess   (KERNEL32.@)
  *
- *  Attempts to attach the dugger to a process.
+ *  Attempts to attach the debugger to a process.
  *
  * RETURNS
  *
@@ -163,6 +163,30 @@ BOOL WINAPI DebugActiveProcess(
     SERVER_START_REQ( debug_process )
     {
         req->pid = (void *)pid;
+        req->attach = 1;
+        ret = !wine_server_call_err( req );
+    }
+    SERVER_END_REQ;
+    return ret;
+}
+
+/**********************************************************************
+ *           DebugActiveProcessStop   (KERNEL32.@)
+ *
+ *  Attempts to detach the debugger from a process.
+ *
+ * RETURNS
+ *
+ *  True if the debugger was detached from the process.
+ */
+BOOL WINAPI DebugActiveProcessStop(
+    DWORD pid) /* [in] The process to be detached. */
+{
+    BOOL ret;
+    SERVER_START_REQ( debug_process )
+    {
+        req->pid = (void *)pid;
+        req->attach = 0;
         ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
@@ -236,6 +260,32 @@ void WINAPI DebugBreak(void)
     DbgBreakPoint();
 }
 
+/***********************************************************************
+ *           DebugBreakProcess   (KERNEL32.@)
+ *
+ *  Raises an exception so that a debugger (if attached)
+ *  can take some action. Same as DebugBreak, but applies to any process.
+ */
+BOOL WINAPI DebugBreakProcess(HANDLE hProc)
+{
+#if 0  /* FIXME: not correct */
+    int res;
+    int pid;
+
+    TRACE("(%08lx)\n", (DWORD)hProc);
+
+    SERVER_START_REQ( get_process_info )
+    {
+        req->handle = hProc;
+        res = wine_server_call_err( req );
+        pid = (int)reply->pid;
+    }
+    SERVER_END_REQ;
+    return !res && kill(pid, SIGINT) == 0;
+#endif
+    return FALSE;
+}
+
 
 /***********************************************************************
  *           DebugBreak   (KERNEL.203)
@@ -309,3 +359,23 @@ void WINAPIV _DebugOutput( void )
     /* Output */
     FIXME("%s %04x %s\n", caller, flags, debugstr_a(MapSL(spec)) );
 }
+
+/***********************************************************************
+ *           DebugSetProcessKillOnExit                    (KERNEL.328)
+ *
+ * Let a debugger decide wether a debuggee will be killed upon debugger
+ * termination
+ */
+BOOL WINAPI DebugSetProcessKillOnExit(BOOL kill)
+{
+    BOOL ret = FALSE;
+
+    SERVER_START_REQ( set_debugger_kill_on_exit )
+    {
+        req->kill_on_exit = kill;
+        ret = !wine_server_call_err( req );
+    }
+    SERVER_END_REQ;
+    return ret;
+}
+
diff --git a/dlls/kernel/kernel32.spec b/dlls/kernel/kernel32.spec
index 301737ee9734877fc105e50903a22cbb20958546..922f8fa0db076fc5f252b5cf7a29fc6fe7bf5c1a 100644
--- a/dlls/kernel/kernel32.spec
+++ b/dlls/kernel/kernel32.spec
@@ -970,6 +970,11 @@ debug_channels (comm console debugstr dll int resource stress thunk toolhelp
 @ stdcall SetCalendarInfoA(long long long str) SetCalendarInfoA
 @ stdcall SetCalendarInfoW(long long long wstr) SetCalendarInfoW
 
+# XP extensions
+@ stdcall DebugActiveProcessStop(long) DebugActiveProcessStop
+@ stdcall DebugBreakProcess(long) DebugBreakProcess
+@ stdcall DebugSetProcessKillOnExit(long) DebugSetProcessKillOnExit
+
 ################################################################
 # Wine extensions: Win16 functions that are needed by other dlls
 #
diff --git a/include/winbase.h b/include/winbase.h
index dd083002dfde594914174f01efec9650a91addf5..12506d3a7a8ec31ab924cfcb7d49aca0e6db7c63 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -1135,7 +1135,10 @@ HANDLE      WINAPI CreateWaitableTimerA(LPSECURITY_ATTRIBUTES,BOOL,LPCSTR);
 HANDLE      WINAPI CreateWaitableTimerW(LPSECURITY_ATTRIBUTES,BOOL,LPCWSTR);
 #define     CreateWaitableTimer WINELIB_NAME_AW(CreateWaitableTimer)
 BOOL        WINAPI DebugActiveProcess(DWORD);
+BOOL        WINAPI DebugActiveProcessStop(DWORD);
 void        WINAPI DebugBreak(void);
+BOOL        WINAPI DebugBreakProcess(HANDLE);
+BOOL        WINAPI DebugSetProcessKillOnExit(BOOL);
 BOOL        WINAPI DeregisterEventSource(HANDLE);
 BOOL        WINAPI DeviceIoControl(HANDLE,DWORD,LPVOID,DWORD,LPVOID,DWORD,LPDWORD,LPOVERLAPPED);
 BOOL        WINAPI DisableThreadLibraryCalls(HMODULE);
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index af9fa98bfc40aeef7999b81dcd8951fc889cf351..d2b9ccb84dee6a7be32b511156332ece1118ed2c 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -1554,6 +1554,7 @@ struct debug_process_request
 {
     struct request_header __header;
     void*        pid;
+    int          attach;
 };
 struct debug_process_reply
 {
@@ -1562,6 +1563,18 @@ struct debug_process_reply
 
 
 
+struct set_debugger_kill_on_exit_request
+{
+    struct request_header __header;
+    int          kill_on_exit;
+};
+struct set_debugger_kill_on_exit_reply
+{
+    struct reply_header __header;
+};
+
+
+
 struct read_process_memory_request
 {
     struct request_header __header;
@@ -2668,6 +2681,7 @@ enum request
     REQ_output_debug_string,
     REQ_continue_debug_event,
     REQ_debug_process,
+    REQ_set_debugger_kill_on_exit,
     REQ_read_process_memory,
     REQ_write_process_memory,
     REQ_create_key,
@@ -2823,6 +2837,7 @@ union generic_request
     struct output_debug_string_request output_debug_string_request;
     struct continue_debug_event_request continue_debug_event_request;
     struct debug_process_request debug_process_request;
+    struct set_debugger_kill_on_exit_request set_debugger_kill_on_exit_request;
     struct read_process_memory_request read_process_memory_request;
     struct write_process_memory_request write_process_memory_request;
     struct create_key_request create_key_request;
@@ -2976,6 +2991,7 @@ union generic_reply
     struct output_debug_string_reply output_debug_string_reply;
     struct continue_debug_event_reply continue_debug_event_reply;
     struct debug_process_reply debug_process_reply;
+    struct set_debugger_kill_on_exit_reply set_debugger_kill_on_exit_reply;
     struct read_process_memory_reply read_process_memory_reply;
     struct write_process_memory_reply write_process_memory_reply;
     struct create_key_reply create_key_reply;
@@ -3043,6 +3059,6 @@ union generic_reply
     struct get_window_properties_reply get_window_properties_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 70
+#define SERVER_PROTOCOL_VERSION 71
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/debugger.c b/server/debugger.c
index e487eb0480c0c4df43ece4473e147896eb9684d9..42d73622a1157adf183e5a94e0ab8cd21da71e4c 100644
--- a/server/debugger.c
+++ b/server/debugger.c
@@ -38,6 +38,7 @@ struct debug_ctx
     struct object        obj;         /* object header */
     struct debug_event  *event_head;  /* head of pending events queue */
     struct debug_event  *event_tail;  /* tail of pending events queue */
+    int                  kill_on_exit;/* kill debuggees on debugger exit ? */
 };
 
 
@@ -422,11 +423,13 @@ static int debugger_attach( struct process *process, struct thread *debugger )
 
     /* we must have been able to attach all threads */
     for (thread = process->thread_list; thread; thread = thread->proc_next)
+    {
         if (!thread->attached)
         {
             resume_process( process );
             goto error;
         }
+    }
 
     if (set_process_debugger( process, debugger )) return 1;
     resume_process( process );
@@ -437,6 +440,65 @@ static int debugger_attach( struct process *process, struct thread *debugger )
     return 0;
 }
 
+
+/* detach a process from a debugger thread (and resume it ?) */
+int debugger_detach( struct process *process, struct thread *debugger )
+{
+    struct thread *thread;
+    struct debug_event *event;
+    struct debug_ctx *debug_ctx;
+
+    if (!process->debugger || process->debugger != debugger)
+        goto error;  /* not currently debugged, or debugged by another debugger */
+    if (!debugger->debug_ctx ) goto error; /* should be a debugger */
+    /* init should be done, otherwise wouldn't be attached */
+    assert(!process->init_event);
+
+    suspend_process( process );
+    /* send continue indication for all events */
+    debug_ctx = debugger->debug_ctx;
+
+    /* find the event in the queue
+     * FIXME: could loop on process' threads and look the debug_event field */
+    for (event = debug_ctx->event_head; event; event = event->next)
+    {
+        if (event->state != EVENT_QUEUED) continue;
+
+        if (event->sender->process == process)
+        {
+            assert( event->sender->debug_event == event );
+            event->status = DBG_CONTINUE;
+            event->state  = EVENT_CONTINUED;
+            wake_up( &event->obj, 0 );
+            unlink_event( debug_ctx, event );
+            /* from queued debug event */
+            resume_process( process );
+        }
+    }
+
+    /* remove relationships between process and its debugger */
+    process->debugger = NULL;
+    release_object( debugger->debug_ctx );
+    debugger->debug_ctx = NULL;
+
+    /* now detach all the threads */
+    for (thread = process->thread_list; thread; thread = thread->proc_next)
+    {
+        if (thread->attached)
+        {
+            detach_thread( thread, 0 );
+        }
+    }
+
+    /* from this function */
+    resume_process( process );
+    return 0;
+
+ error:
+    set_error( STATUS_ACCESS_DENIED );
+    return 0;
+}
+
 /* generate all startup events of a given process */
 void generate_startup_debug_events( struct process *process, void *entry )
 {
@@ -470,6 +532,7 @@ int set_process_debugger( struct process *process, struct thread *debugger )
         if (!(debug_ctx = alloc_object( &debug_ctx_ops, -1 ))) return 0;
         debug_ctx->event_head = NULL;
         debug_ctx->event_tail = NULL;
+        debug_ctx->kill_on_exit = 1;
         debugger->debug_ctx = debug_ctx;
     }
     process->debugger = debugger;
@@ -481,8 +544,15 @@ void debug_exit_thread( struct thread *thread )
 {
     if (thread->debug_ctx)  /* this thread is a debugger */
     {
-        /* kill all debugged processes */
-        kill_debugged_processes( thread, thread->exit_code );
+        if (thread->debug_ctx->kill_on_exit)
+        {
+            /* kill all debugged processes */
+            kill_debugged_processes( thread, thread->exit_code );
+        }
+        else
+        {
+            detach_debugged_processes( thread );
+        }
         release_object( thread->debug_ctx );
         thread->debug_ctx = NULL;
     }
@@ -538,12 +608,17 @@ DECL_HANDLER(continue_debug_event)
 /* Start debugging an existing process */
 DECL_HANDLER(debug_process)
 {
-    struct debug_event_exception data;
     struct process *process = get_process_from_id( req->pid );
     if (!process) return;
 
-    if (debugger_attach( process, current ))
+    if (!req->attach)
+    {
+        debugger_detach( process, current );
+    }
+    else if (debugger_attach( process, current ))
     {
+        struct debug_event_exception data;
+
         generate_startup_debug_events( process, NULL );
         resume_process( process );
 
@@ -622,3 +697,14 @@ DECL_HANDLER(output_debug_string)
     data.length  = req->length;
     generate_debug_event( current, OUTPUT_DEBUG_STRING_EVENT, &data );
 }
+
+/* set debugger kill on exit flag */
+DECL_HANDLER(set_debugger_kill_on_exit)
+{
+    if (!current->debug_ctx)
+    {
+        set_error( STATUS_ACCESS_DENIED );
+        return;
+    }
+    current->debug_ctx->kill_on_exit = req->kill_on_exit;
+}
diff --git a/server/process.c b/server/process.c
index 9b711080b4957ea4e5c04adaa4c8256a771bf3d8..43b5555e7ce61812bec3352735c05a225b744245 100644
--- a/server/process.c
+++ b/server/process.c
@@ -573,10 +573,24 @@ void kill_debugged_processes( struct thread *debugger, int exit_code )
 }
 
 
+/* detach a debugger from all its debuggees */
+void detach_debugged_processes( struct thread *debugger )
+{
+    struct process *process;
+    for (process = first_process; process; process = process->next)
+    {
+        if (process->debugger == debugger && process->running_threads)
+        {
+            debugger_detach( process, debugger );
+        }
+    }
+}
+
+
 /* get all information about a process */
 static void get_process_info( struct process *process, struct get_process_info_reply *reply )
 {
-    reply->pid              = process;
+    reply->pid              = get_process_id( process );
     reply->debugged         = (process->debugger != 0);
     reply->exit_code        = process->exit_code;
     reply->priority         = process->priority;
diff --git a/server/process.h b/server/process.h
index cc2dc981591ca428854c9142f469012b0b479f15..93b4354fc0ac745146967e25b8a91161793b4526 100644
--- a/server/process.h
+++ b/server/process.h
@@ -71,6 +71,8 @@ extern struct thread *create_process( int fd );
 extern struct process *get_process_from_id( void *id );
 extern struct process *get_process_from_handle( 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 void add_process_thread( struct process *process,
                                 struct thread *thread );
 extern void remove_process_thread( struct process *process,
@@ -80,6 +82,7 @@ extern void resume_process( struct process *process );
 extern void kill_process( struct process *process, struct thread *skip, int exit_code );
 extern void kill_console_processes( struct thread *renderer, int exit_code );
 extern void kill_debugged_processes( struct thread *debugger, int exit_code );
+extern void detach_debugged_processes( struct thread *debugger );
 extern struct process_snapshot *process_snap( int *count );
 extern struct module_snapshot *module_snap( struct process *process, int *count );
 
diff --git a/server/protocol.def b/server/protocol.def
index 7036de158ecf0cd3613426de2a7207f948499e32..f5dd291b9af8782d6b2ce39a85fa548fb7cccfa7 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1117,9 +1117,16 @@ enum char_info_mode
 @END
 
 
-/* Start debugging an existing process */
+/* Start/stop debugging an existing process */
 @REQ(debug_process)
     void*        pid;          /* id of the process to debug */
+    int          attach;       /* 1=attaching / 0=detaching from the process */
+@END
+
+
+/* Set debugger kill on exit flag */
+@REQ(set_debugger_kill_on_exit)
+    int          kill_on_exit;  /* 0=detach/1=kill debuggee when debugger dies */
 @END
 
 
diff --git a/server/request.h b/server/request.h
index ee18ecbb7f8f3b5efcaa7d8ce47e424cb2e3728a..44f2cafb20a8b64e4a3fc954fa290dacb3958480 100644
--- a/server/request.h
+++ b/server/request.h
@@ -170,6 +170,7 @@ DECL_HANDLER(get_exception_status);
 DECL_HANDLER(output_debug_string);
 DECL_HANDLER(continue_debug_event);
 DECL_HANDLER(debug_process);
+DECL_HANDLER(set_debugger_kill_on_exit);
 DECL_HANDLER(read_process_memory);
 DECL_HANDLER(write_process_memory);
 DECL_HANDLER(create_key);
@@ -324,6 +325,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
     (req_handler)req_output_debug_string,
     (req_handler)req_continue_debug_event,
     (req_handler)req_debug_process,
+    (req_handler)req_set_debugger_kill_on_exit,
     (req_handler)req_read_process_memory,
     (req_handler)req_write_process_memory,
     (req_handler)req_create_key,
diff --git a/server/trace.c b/server/trace.c
index c8bb3c50e31b34a98409ccccf4fc9d1f11959e4a..d7859db553a40332d9f4a21dff2d97ea8ae4afa0 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -1284,7 +1284,13 @@ static void dump_continue_debug_event_request( const struct continue_debug_event
 
 static void dump_debug_process_request( const struct debug_process_request *req )
 {
-    fprintf( stderr, " pid=%p", req->pid );
+    fprintf( stderr, " pid=%p,", req->pid );
+    fprintf( stderr, " attach=%d", req->attach );
+}
+
+static void dump_set_debugger_kill_on_exit_request( const struct set_debugger_kill_on_exit_request *req )
+{
+    fprintf( stderr, " kill_on_exit=%d", req->kill_on_exit );
 }
 
 static void dump_read_process_memory_request( const struct read_process_memory_request *req )
@@ -2115,6 +2121,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)dump_output_debug_string_request,
     (dump_func)dump_continue_debug_event_request,
     (dump_func)dump_debug_process_request,
+    (dump_func)dump_set_debugger_kill_on_exit_request,
     (dump_func)dump_read_process_memory_request,
     (dump_func)dump_write_process_memory_request,
     (dump_func)dump_create_key_request,
@@ -2266,6 +2273,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)0,
     (dump_func)0,
     (dump_func)0,
+    (dump_func)0,
     (dump_func)dump_read_process_memory_reply,
     (dump_func)0,
     (dump_func)dump_create_key_reply,
@@ -2417,6 +2425,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
     "output_debug_string",
     "continue_debug_event",
     "debug_process",
+    "set_debugger_kill_on_exit",
     "read_process_memory",
     "write_process_memory",
     "create_key",