diff --git a/dlls/kernel32/tests/debugger.c b/dlls/kernel32/tests/debugger.c
index 8062c29461262dbd3f21abc6a593771c49241c1c..33e18d82e62032a6e6b9d339759da334fc739c37 100644
--- a/dlls/kernel32/tests/debugger.c
+++ b/dlls/kernel32/tests/debugger.c
@@ -1278,7 +1278,7 @@ static void test_debugger(const char *argv0)
     ok(ctx.ev.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT, "dwDebugEventCode = %d\n", ctx.ev.dwDebugEventCode);
 
     if ((skip_reply_later = !ContinueDebugEvent(ctx.ev.dwProcessId, ctx.ev.dwThreadId, DBG_REPLY_LATER)))
-        todo_wine win_skip("Skipping unsupported DBG_REPLY_LATER tests\n");
+        win_skip("Skipping unsupported DBG_REPLY_LATER tests\n");
     else
     {
         DEBUG_EVENT de;
@@ -1402,7 +1402,7 @@ static void test_debugger(const char *argv0)
     else win_skip("call_debug_service_code not supported on this architecture\n");
 
     if (skip_reply_later)
-        todo_wine win_skip("Skipping unsupported DBG_REPLY_LATER tests\n");
+        win_skip("Skipping unsupported DBG_REPLY_LATER tests\n");
     else if (sizeof(loop_code) > 1)
     {
         HANDLE thread_a, thread_b;
diff --git a/server/debugger.c b/server/debugger.c
index 5b06b73b4be469092db904359d68c2244f0433f7..5ff63b92b9c040226de22eda3c2b163ab8d48058 100644
--- a/server/debugger.c
+++ b/server/debugger.c
@@ -38,7 +38,7 @@
 #include "thread.h"
 #include "request.h"
 
-enum debug_event_state { EVENT_QUEUED, EVENT_SENT, EVENT_CONTINUED };
+enum debug_event_state { EVENT_QUEUED, EVENT_SENT, EVENT_DELAYED, EVENT_CONTINUED };
 
 /* debug event */
 struct debug_event
@@ -265,6 +265,31 @@ static void link_event( struct debug_event *event )
     }
 }
 
+/* resume a delayed debug event already in the queue */
+static void resume_event( struct debug_event *event )
+{
+    struct debug_ctx *debug_ctx = event->debugger->debug_ctx;
+
+    assert( debug_ctx );
+    event->state = EVENT_QUEUED;
+    if (!event->sender->process->debug_event)
+    {
+        grab_object( debug_ctx );
+        wake_up( &debug_ctx->obj, 0 );
+        release_object( debug_ctx );
+    }
+}
+
+/* delay a debug event already in the queue to be replayed when thread wakes up */
+static void delay_event( struct debug_event *event )
+{
+    struct debug_ctx *debug_ctx = event->debugger->debug_ctx;
+
+    assert( debug_ctx );
+    event->state = EVENT_DELAYED;
+    if (event->sender->process->debug_event == event) event->sender->process->debug_event = NULL;
+}
+
 /* find the next event that we can send to the debugger */
 static struct debug_event *find_event_to_send( struct debug_ctx *debug_ctx )
 {
@@ -273,6 +298,7 @@ static struct debug_event *find_event_to_send( struct debug_ctx *debug_ctx )
     LIST_FOR_EACH_ENTRY( event, &debug_ctx->event_queue, struct debug_event, entry )
     {
         if (event->state == EVENT_SENT) continue;  /* already sent */
+        if (event->state == EVENT_DELAYED) continue;  /* delayed until thread resumes */
         if (event->sender->process->debug_event) continue;  /* process busy with another one */
         return event;
     }
@@ -365,6 +391,29 @@ static int continue_debug_event( struct process *process, struct thread *thread,
     {
         struct debug_event *event;
 
+        if (status == DBG_REPLY_LATER)
+        {
+            /* if thread is suspended, delay all its events and resume process
+             * if not, reset the event for immediate replay */
+            LIST_FOR_EACH_ENTRY( event, &debug_ctx->event_queue, struct debug_event, entry )
+            {
+                if (event->sender != thread) continue;
+                if (thread->suspend)
+                {
+                    delay_event( event );
+                    resume_process( process );
+                }
+                else if (event->state == EVENT_SENT)
+                {
+                    assert( event->sender->process->debug_event == event );
+                    event->sender->process->debug_event = NULL;
+                    resume_event( event );
+                    return 1;
+                }
+            }
+            return 1;
+        }
+
         /* find the event in the queue */
         LIST_FOR_EACH_ENTRY( event, &debug_ctx->event_queue, struct debug_event, entry )
         {
@@ -372,7 +421,6 @@ static int continue_debug_event( struct process *process, struct thread *thread,
             if (event->sender == thread)
             {
                 assert( event->sender->process->debug_event == event );
-
                 event->status = status;
                 event->state  = EVENT_CONTINUED;
                 wake_up( &event->obj, 0 );
@@ -430,6 +478,24 @@ void generate_debug_event( struct thread *thread, int code, const void *arg )
     }
 }
 
+void resume_delayed_debug_events( struct thread *thread )
+{
+    struct thread *debugger = thread->process->debugger;
+    struct debug_event *event;
+
+    if (debugger)
+    {
+        assert( debugger->debug_ctx );
+        LIST_FOR_EACH_ENTRY( event, &debugger->debug_ctx->event_queue, struct debug_event, entry )
+        {
+            if (event->sender != thread) continue;
+            if (event->state != EVENT_DELAYED) continue;
+            resume_event( event );
+            suspend_process( thread->process );
+        }
+    }
+}
+
 /* attach a process to a debugger thread and suspend it */
 static int debugger_attach( struct process *process, struct thread *debugger )
 {
@@ -615,7 +681,8 @@ DECL_HANDLER(continue_debug_event)
     struct process *process;
 
     if (req->status != DBG_EXCEPTION_NOT_HANDLED &&
-        req->status != DBG_CONTINUE)
+        req->status != DBG_CONTINUE &&
+        req->status != DBG_REPLY_LATER)
     {
         set_error( STATUS_INVALID_PARAMETER );
         return;
diff --git a/server/object.h b/server/object.h
index 8114a8fb6b934a194d6655e9adbb4719b751fd2a..3144eb566789cf7484404ef02d86a339c21b2eb2 100644
--- a/server/object.h
+++ b/server/object.h
@@ -207,6 +207,7 @@ extern void sock_init(void);
 
 extern int set_process_debugger( struct process *process, struct thread *debugger );
 extern void generate_debug_event( struct thread *thread, int code, const void *arg );
+extern void resume_delayed_debug_events( struct thread *thread );
 extern void generate_startup_debug_events( struct process *process, client_ptr_t entry );
 extern void debug_exit_thread( struct thread *thread );
 
diff --git a/server/thread.c b/server/thread.c
index edf70c61bde9ea97b53be80dfeef49d610dbff88..6e677c8cf291f82e682e12d798132f6a045ee2ed 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -612,7 +612,8 @@ int resume_thread( struct thread *thread )
     int old_count = thread->suspend;
     if (thread->suspend > 0)
     {
-        if (!(--thread->suspend + thread->process->suspend)) wake_thread( thread );
+        if (!(--thread->suspend)) resume_delayed_debug_events( thread );
+        if (!(thread->suspend + thread->process->suspend)) wake_thread( thread );
     }
     return old_count;
 }