diff --git a/main.c b/main.c
index 193487d..cdfce09 100644
--- a/main.c
+++ b/main.c
@@ -168,7 +168,6 @@ HRESULT __stdcall ddraw_RestoreDisplayMode(IDirectDrawImpl *This)
 
     if(!ddraw->windowed)
     {
-        This->mode.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFLAGS|DM_DISPLAYFREQUENCY|DM_POSITION;
         ChangeDisplaySettings(&This->mode, 0);
     }
 
@@ -309,57 +308,62 @@ LRESULT CALLBACK dummy_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
 LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
     RECT rc = { 0, 0, ddraw->render.width, ddraw->render.height };
-    POINT pt;
 
     switch(uMsg)
     {
-        case WM_DESTROY:
-            return ddraw->WndProc(hWnd, uMsg, wParam, lParam);
+        /* Carmageddon stops the main loop when it sees these, DefWindowProc is also bad */
+        case WM_WINDOWPOSCHANGING:
+        case WM_WINDOWPOSCHANGED:
+            return 0;
+
+        /* C&C and RA really don't want to close down */
         case WM_SYSCOMMAND:
-            if(wParam == SC_CLOSE)
+            if (wParam == SC_CLOSE)
             {
                 exit(0);
             }
-            break;
-        case WM_SIZE:
-            if(wParam == SIZE_RESTORED)
+            return DefWindowProc(hWnd, uMsg, wParam, lParam);
+
+        case WM_ACTIVATE:
+            if (wParam == WA_ACTIVE || wParam == WA_CLICKACTIVE)
             {
-                ddraw_SetDisplayMode(ddraw, ddraw->width, ddraw->height, ddraw->bpp);
+                if (wParam == WA_ACTIVE)
+                {
+                    mouse_lock();
+                }
+                if (!ddraw->windowed)
+                {
+                    ChangeDisplaySettings(&ddraw->render.mode, CDS_FULLSCREEN);
+                }
             }
-            if(wParam == SIZE_MINIMIZED)
-            {
-                ddraw_RestoreDisplayMode(ddraw);
-            }
-            /* disallow maximize, C&C does that when WCHAT DDE is used */
-            if(wParam == SIZE_MAXIMIZED)
-            {
-                ShowWindow(ddraw->hWnd, SW_RESTORE);
-            }
-            break;
-        case WM_NCACTIVATE:
-            if(wParam == FALSE)
+            else if (wParam == WA_INACTIVE)
             {
                 mouse_unlock();
-            }
 
-            if(!ddraw->windowed)
-            {
-                if(wParam == FALSE)
+                /* minimize our window on defocus when in fullscreen */
+                if (!ddraw->windowed)
                 {
+                    ChangeDisplaySettings(&ddraw->mode, 0);
                     ShowWindow(ddraw->hWnd, SW_MINIMIZE);
                 }
-                else
-                {
-                    ShowWindow(ddraw->hWnd, SW_RESTORE);
-                }
+            }
+            return 0;
+
+        case WM_ACTIVATEAPP:
+            /* C&C and RA stop drawing when they receive this with FALSE wParam, disable in windowed mode */
+            if (ddraw->windowed)
+            {
+                return 0;
             }
             break;
+
         case WM_KEYDOWN:
             if(wParam == VK_CONTROL || wParam == VK_TAB)
             {
                 if(GetAsyncKeyState(VK_CONTROL) & 0x8000 && GetAsyncKeyState(VK_TAB) & 0x8000)
                 {
                     mouse_unlock();
+                    return 0;
                 }
             }
 #ifdef HAVE_LIBPNG
@@ -368,16 +372,16 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
                 if(GetAsyncKeyState(VK_CONTROL) & 0x8000 && GetAsyncKeyState(0x53) & 0x8000)
                 {
                     screenshot(ddraw->primary);
+                    return 0;
                 }
             }
 #endif
-        case WM_KEYUP:
-        case WM_SYSKEYDOWN:
-        case WM_SYSKEYUP:
-        case WM_CHAR: /* for StarCraft and general support */
-            return ddraw->WndProc(hWnd, uMsg, wParam, lParam);
+            break;
+
+        /* button up messages reactivate cursor lock */
         case WM_LBUTTONUP:
         case WM_RBUTTONUP:
+        case WM_MBUTTONUP:
             if (ddraw->mhack && !ddraw->locked)
             {
                 ddraw->cursor.x = LOWORD(lParam) * ((float)ddraw->width / ddraw->render.width);
@@ -385,46 +389,41 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
                 mouse_lock();
                 return 0;
             }
+            /* fall through for lParam */
+
+        /* down messages are ignored if we have no cursor lock */
         case WM_LBUTTONDOWN:
         case WM_RBUTTONDOWN:
-        /* rest for StarCraft and general support */
         case WM_MBUTTONDOWN:
-        case WM_MBUTTONUP:
-        case WM_MBUTTONDBLCLK:
-        case WM_LBUTTONDBLCLK:
-        case WM_RBUTTONDBLCLK:
-            if(ddraw->mhack)
+        case WM_MOUSEMOVE:
+            if (ddraw->mhack)
             {
                 if (!ddraw->locked)
                 {
                     return 0;
                 }
 
+                fake_GetCursorPos(NULL); /* update our own cursor */
                 lParam = MAKELPARAM(ddraw->cursor.x, ddraw->cursor.y);
             }
-        case 1129: /* this somehow triggers network activity in C&C in WCHAT mode */
-        case 1139: /* this somehow triggers network activity in RA, investigate */
-        case 2024: /* this somehow allows RA edwin to work, investigate */
-            return ddraw->WndProc(hWnd, uMsg, wParam, lParam);
+            break;
 
-        /* for StarCraft and general support */
-        case WM_MOUSEMOVE:
-        case WM_NCMOUSEMOVE:
-            if(ddraw->mhack)
-            {
-                fake_GetCursorPos(&pt);
-                return ddraw->WndProc(hWnd, uMsg, wParam, MAKELPARAM(pt.x, pt.y));
-            }
-            return ddraw->WndProc(hWnd, uMsg, wParam, lParam);
+        /* make sure we redraw when WM_PAINT is requested */
+        case WM_PAINT:
+            EnterCriticalSection(&ddraw->cs);
+            ReleaseSemaphore(ddraw->render.sem, 1, NULL);
+            LeaveCriticalSection(&ddraw->cs);
+            break;
 
         case WM_ERASEBKGND:
             EnterCriticalSection(&ddraw->cs);
             FillRect(ddraw->render.hDC, &rc, (HBRUSH) GetStockObject(BLACK_BRUSH));
+            ReleaseSemaphore(ddraw->render.sem, 1, NULL);
             LeaveCriticalSection(&ddraw->cs);
-            return TRUE;
+            break;
     }
 
-    return DefWindowProc(hWnd, uMsg, wParam, lParam);
+    return ddraw->WndProc(hWnd, uMsg, wParam, lParam);
 }
 
 HRESULT __stdcall ddraw_SetCooperativeLevel(IDirectDrawImpl *This, HWND hWnd, DWORD dwFlags)
diff --git a/render.c b/render.c
index 2160875..418d38c 100644
--- a/render.c
+++ b/render.c
@@ -87,7 +87,7 @@ DWORD WINAPI render_main(void)
 
     glEnable(GL_TEXTURE_2D);
 
-    while(ddraw->render.run && WaitForSingleObject(ddraw->render.sem, 100) != WAIT_FAILED)
+    while(ddraw->render.run && WaitForSingleObject(ddraw->render.sem, INFINITE) != WAIT_FAILED)
     {
         scale_w = (float)ddraw->width/tex_width;
         scale_h = (float)ddraw->height/tex_height;
diff --git a/render_soft.c b/render_soft.c
index 6820abc..4abee4e 100644
--- a/render_soft.c
+++ b/render_soft.c
@@ -66,7 +66,7 @@ DWORD WINAPI render_soft_main(void)
         frame_len = 1000.0f / ddraw->render.maxfps;
     }
 
-    while (ddraw->render.run && WaitForSingleObject(ddraw->render.sem, 100) != WAIT_FAILED)
+    while (ddraw->render.run && WaitForSingleObject(ddraw->render.sem, INFINITE) != WAIT_FAILED)
     {
         if(ddraw->render.maxfps > 0)
         {