+    ExitCode rc = 0;
+
+    // Delete() is always safe to call, so consider all possible states
+
+    // we might need to resume the thread, but we might also not need to cancel
+    // it if it doesn't run yet
+    bool shouldResume = FALSE,
+         shouldCancel = TRUE,
+         isRunning = FALSE;
+
+    // check if the thread already started to run
+    {
+        wxCriticalSectionLocker         lock((wxCriticalSection &)m_critsect);
+
+        if ( m_internal->GetState() == STATE_NEW )
+        {
+            // WinThreadStart() will see it and terminate immediately, no need
+            // to cancel the thread - but we still need to resume it to let it
+            // run
+            m_internal->SetState(STATE_EXITED);
+
+            Resume();   // it knows about STATE_EXITED special case
+
+            shouldCancel = FALSE;
+            isRunning = TRUE;
+
+            // shouldResume is correctly set to FALSE here
+        }
+        else
+        {
+            shouldResume = IsPaused();
+        }
+    }
+
+    // resume the thread if it is paused
+    if ( shouldResume )
+        Resume();
+
+    TID                             hThread = m_internal->GetHandle();
+
+    if ( isRunning || IsRunning())
+    {
+        if (IsMain())
+        {
+            // set flag for wxIsWaitingForThread()
+            gs_bWaitingForThread = TRUE;
+        }
+
+        // ask the thread to terminate
+        if ( shouldCancel )
+        {
+            wxCriticalSectionLocker lock(m_critsect);
+
+            m_internal->Cancel();
+        }
+
+#if 0
+        // we can't just wait for the thread to terminate because it might be
+        // calling some GUI functions and so it will never terminate before we
+        // process the Windows messages that result from these functions
+        DWORD result = 0;       // suppress warnings from broken compilers
+        do
+        {
+            if ( IsMain() )
+            {
+                // give the thread we're waiting for chance to do the GUI call
+                // it might be in
+                if ( (gs_nWaitingForGui > 0) && wxGuiOwnedByMainThread() )
+                {
+                    wxMutexGuiLeave();
+                }
+            }
+
+            result = ::DosWaitThread(&hThread, DCWW_NOWAIT);
+            // FIXME: We ought to have a message processing loop here!!
+
+            switch ( result )
+            {
+                case ERROR_INTERRUPT:
+                case ERROR_THREAD_NOT_TERMINATED:
+                    break;
+                case ERROR_INVALID_THREADID:
+                case NO_ERROR:
+                    // thread we're waiting for just terminated
+                    // or even does not exist any more.
+                    result = NO_ERROR;
+                    break;
+                default:
+                    wxFAIL_MSG(wxT("unexpected result of DosWaitThread"));
+            }
+            if ( IsMain() )
+            {
+                // event processing - needed if we are the main thread
+                // to give other threads a chance to do remaining GUI
+                // processing and terminate cleanly.
+                wxTheApp->HandleSockets();
+                if (wxTheApp->Pending())
+                  if ( !wxTheApp->DoMessage() )
+                  {
+                      // WM_QUIT received: kill the thread
+                      Kill();
+
+                      return wxTHREAD_KILLED;
+                  }
+                  else
+                    wxUsleep(10);
+            }
+            else
+                wxUsleep(10);
+        } while ( result != NO_ERROR );
+#else // !wxUSE_GUI
+        // simply wait for the thread to terminate
+        //
+        // OTOH, even console apps create windows (in wxExecute, for WinSock
+        // &c), so may be use MsgWaitForMultipleObject() too here?
+        if ( ::DosWaitThread(&hThread, DCWW_WAIT) != NO_ERROR )
+        {
+            wxFAIL_MSG(wxT("unexpected result of DosWaitThread"));
+        }
+#endif // wxUSE_GUI/!wxUSE_GUI
+
+        if ( IsMain() )
+        {
+            gs_bWaitingForThread = FALSE;
+        }
+    }
+
+#if 0
+    // although the thread might be already in the EXITED state it might not
+    // have terminated yet and so we are not sure that it has actually
+    // terminated if the "if" above hadn't been taken
+    do
+    {
+        if ( !::GetExitCodeThread(hThread, (LPDWORD)&rc) )
+        {
+            wxLogLastError(wxT("GetExitCodeThread"));
+
+            rc = (ExitCode)-1;
+        }
+    } while ( (DWORD)rc == STILL_ACTIVE );
+#endif
+
+    if ( IsDetached() )
+    {
+        // if the thread exits normally, this is done in WinThreadStart, but in
+        // this case it would have been too early because
+        // MsgWaitForMultipleObject() would fail if the thread handle was
+        // closed while we were waiting on it, so we must do it here
+        delete this;
+    }
+
+    if ( pRc )
+        *pRc = rc;
+
+    return rc == (ExitCode)-1 ? wxTHREAD_MISC_ERROR : wxTHREAD_NO_ERROR;