diff --git a/include/allegro5/platform/aintwin.h b/include/allegro5/platform/aintwin.h
index 8484fef..de058b6 100644
--- a/include/allegro5/platform/aintwin.h
+++ b/include/allegro5/platform/aintwin.h
@@ -112,6 +112,8 @@ void _al_win_kbd_handle_key_press(int scode, int vcode, bool extended,
                            bool repeated, ALLEGRO_DISPLAY_WIN *win_disp);
 void _al_win_kbd_handle_key_release(int scode, int vcode, bool extended,
                            ALLEGRO_DISPLAY_WIN *win_disp);
+void _al_win_kbd_handle_char(int scode, int unichar, bool extended,
+                             bool repeated, ALLEGRO_DISPLAY_WIN *win_disp);
 void _al_win_fix_modifiers(void);
 
 /* mouse routines */
diff --git a/src/win/d3d_disp.cpp b/src/win/d3d_disp.cpp
index dea8a1a..67d8ca8 100644
--- a/src/win/d3d_disp.cpp
+++ b/src/win/d3d_disp.cpp
@@ -14,6 +14,8 @@
  *
  */
 
+#define UNICODE
+
 #include <windows.h>
 
 #include <string.h>
@@ -1389,7 +1391,7 @@ static void *d3d_display_thread_proc(void *arg)
          refresh_rate = d3d_get_default_refresh_rate(win_display->adapter);
       }
       d3d_display->device_name = (TCHAR *)al_malloc(sizeof(TCHAR)*32);
-      strcpy(d3d_display->device_name, info->dd.DeviceName);
+      strcpy((char*)d3d_display->device_name, (char*)info->dd.DeviceName);
       ALLEGRO_DEBUG("going to call _al_win_create_faux_fullscreen_window\n");
 
       info->display = al_display;
@@ -1466,11 +1468,13 @@ static void *d3d_display_thread_proc(void *arg)
    SetEvent(params->AckEvent);
 
    while (!win_display->end_thread) {
-      al_rest(0.001);
+      //~ al_rest(0.001);
 
       if (PeekMessage(&msg, NULL, 0, 0, FALSE)) {
-         if (GetMessage(&msg, NULL, 0, 0) != 0)
+         if (GetMessage(&msg, NULL, 0, 0) != 0) {
+            TranslateMessage(&msg);
             DispatchMessage(&msg);
+         }
          else
             break;                  /* WM_QUIT received or error (GetMessage returned -1)  */
       }
@@ -1479,56 +1483,54 @@ static void *d3d_display_thread_proc(void *arg)
          continue;
       }
       
-      hr = d3d_display->device->TestCooperativeLevel();
+      if (d3d_display->device_lost) {
+         hr = d3d_display->device->TestCooperativeLevel();
 
-      if (hr == D3D_OK) {
-         d3d_display->device_lost = false;
-      }
-      else if (hr == D3DERR_DEVICELOST) {
-         /* device remains lost */
-         /* Set device_lost flag immediately.  This prevents a crash in
-          * the DrawPrimitiveUP call in d3d_flush_vertex_cache.
-          */
-         d3d_display->device_lost = true;
-         if (!lost_event_generated) {
-            ALLEGRO_DEBUG("D3DERR_DEVICELOST: d3d_display=%p\n", d3d_display);
-            lost_event_generated = true;
-            if (d3d_display->suppress_lost_events) {
-               ALLEGRO_DEBUG("DISPLAY_LOST event suppressed\n");
+         if (hr == D3D_OK) {
+            d3d_display->device_lost = false;
+         }
+         else if (hr == D3DERR_DEVICELOST) {
+            /* device remains lost */
+            if (!lost_event_generated) {
+               ALLEGRO_DEBUG("D3DERR_DEVICELOST: d3d_display=%p\n", d3d_display);
+               lost_event_generated = true;
+               if (d3d_display->suppress_lost_events) {
+                  ALLEGRO_DEBUG("DISPLAY_LOST event suppressed\n");
+               }
+               else {
+                  _al_event_source_lock(&al_display->es);
+                  if (_al_event_source_needs_to_generate_event(&al_display->es)) {
+                     ALLEGRO_EVENT event;
+                     memset(&event, 0, sizeof(event));
+                     event.display.type = ALLEGRO_EVENT_DISPLAY_LOST;
+                     event.display.timestamp = al_get_time();
+                     _al_event_source_emit_event(&al_display->es, &event);
+                  }
+                  _al_event_source_unlock(&al_display->es);
+                  al_rest(0.5); // give user time to respond
+               }
             }
-            else {
+         }
+         else if (hr == D3DERR_DEVICENOTRESET) {
+            if (_al_d3d_reset_device(d3d_display)) {
+               d3d_display->device_lost = false;
+               d3d_reset_state(d3d_display);
+               _al_d3d_set_ortho_projection(d3d_display,
+                  al_display->w, al_display->h);
                _al_event_source_lock(&al_display->es);
                if (_al_event_source_needs_to_generate_event(&al_display->es)) {
                   ALLEGRO_EVENT event;
                   memset(&event, 0, sizeof(event));
-                  event.display.type = ALLEGRO_EVENT_DISPLAY_LOST;
+                  event.display.type = ALLEGRO_EVENT_DISPLAY_FOUND;
                   event.display.timestamp = al_get_time();
                   _al_event_source_emit_event(&al_display->es, &event);
                }
                _al_event_source_unlock(&al_display->es);
-               al_rest(0.5); // give user time to respond
-            }
-         }
-      }
-      else if (hr == D3DERR_DEVICENOTRESET) {
-         if (_al_d3d_reset_device(d3d_display)) {
-            d3d_display->device_lost = false;
-            d3d_reset_state(d3d_display);
-            _al_d3d_set_ortho_projection(d3d_display,
-               al_display->w, al_display->h);
-            _al_event_source_lock(&al_display->es);
-            if (_al_event_source_needs_to_generate_event(&al_display->es)) {
-               ALLEGRO_EVENT event;
-               memset(&event, 0, sizeof(event));
-               event.display.type = ALLEGRO_EVENT_DISPLAY_FOUND;
-               event.display.timestamp = al_get_time();
-               _al_event_source_emit_event(&al_display->es, &event);
-            }
-            _al_event_source_unlock(&al_display->es);
-            lost_event_generated = false;
-            d3d_call_callbacks(&al_display->display_validated_callbacks, al_display);
-            if (d3d_restore_callback) {
-               (*d3d_restore_callback)(al_display);
+               lost_event_generated = false;
+               d3d_call_callbacks(&al_display->display_validated_callbacks, al_display);
+               if (d3d_restore_callback) {
+                  (*d3d_restore_callback)(al_display);
+               }
             }
          }
       }
diff --git a/src/win/wgl_disp.c b/src/win/wgl_disp.c
index aae741d..acda3f2 100644
--- a/src/win/wgl_disp.c
+++ b/src/win/wgl_disp.c
@@ -22,6 +22,9 @@
 #define WINVER 0x0501
 #endif
 #endif
+
+#define UNICODE
+
 #include <windows.h>
 
 #include "allegro5/allegro.h"
@@ -571,7 +574,7 @@ static bool change_display_mode(ALLEGRO_DISPLAY *d)
    DEVMODE dm;
    DEVMODE fallback_dm;
    DISPLAY_DEVICE dd;
-   char* dev_name = NULL;
+   TCHAR* dev_name = NULL;
    int i, modeswitch, result;
    int fallback_dm_valid = 0;
    int bpp;
@@ -1302,8 +1305,10 @@ static void display_thread_proc(void *arg)
 
    while (!win_disp->end_thread) {
       /* get a message from the queue */
-      if (GetMessage(&msg, NULL, 0, 0) != 0)
+      if (GetMessage(&msg, NULL, 0, 0) != 0) {
+         TranslateMessage(&msg);
          DispatchMessage(&msg);
+      }
       else
          break;                 /* WM_QUIT received or error (GetMessage returned -1)  */
    }
diff --git a/src/win/wkeyboard.c b/src/win/wkeyboard.c
index 39a7a97..4104822 100644
--- a/src/win/wkeyboard.c
+++ b/src/win/wkeyboard.c
@@ -22,6 +22,7 @@
 #include "allegro5/internal/aintern_events.h"
 #include "allegro5/internal/aintern_keyboard.h"
 #include "allegro5/platform/aintwin.h"
+#include <stdio.h>
 
 /* Missing from MSVC 2005 headers. */
 #ifndef MAPVK_VSC_TO_VK_EX
@@ -344,7 +345,7 @@ void _al_win_kbd_handle_key_press(int scode, int vcode, bool extended,
    update_modifiers(my_code, true);
 
    actual_repeat = repeated && _AL_KEYBOARD_STATE_KEY_DOWN(the_state, my_code);
-   _AL_KEYBOARD_STATE_SET_KEY_DOWN(the_state, my_code);
+                   _AL_KEYBOARD_STATE_SET_KEY_DOWN(the_state, my_code);
 
    if (!_al_event_source_needs_to_generate_event(&the_keyboard.es))
       return;
@@ -363,26 +364,6 @@ void _al_win_kbd_handle_key_press(int scode, int vcode, bool extended,
       _al_event_source_emit_event(&the_keyboard.es, &event);
    }
 
-   /* Send char events, but not for modifier keys or dead keys. */
-   if (my_code < ALLEGRO_KEY_MODIFIERS) {
-      char_count = ToUnicode(vcode, scode, GetKeyboardState(ks) ? ks : NULL, buf, 8, 0);
-      /* Send ASCII code 127 for both Del keys. */
-      if (char_count == 0 && vcode == VK_DELETE) {
-         char_count = 1;
-         buf[0] = 127;
-      }
-      if (char_count != -1) { /* -1 means it was a dead key. */
-         event_count = char_count ? char_count : 1;
-         event.keyboard.type = ALLEGRO_EVENT_KEY_CHAR;
-         update_toggle_modifiers();
-         event.keyboard.modifiers = modifiers;
-         event.keyboard.repeat = actual_repeat;
-         for (i = 0; i < event_count; i++) {
-            event.keyboard.unichar = buf[i];
-            _al_event_source_emit_event(&the_keyboard.es, &event);
-         }
-      }
-   }
    _al_event_source_unlock(&the_keyboard.es);
 
    /* Toggle mouse grab key. */
@@ -401,6 +382,47 @@ void _al_win_kbd_handle_key_press(int scode, int vcode, bool extended,
    }
 }
 
+void _al_win_kbd_handle_char(int scode, int unichar, bool extended,
+                             bool repeated, ALLEGRO_DISPLAY_WIN *win_disp)
+{
+   ALLEGRO_DISPLAY *display = (ALLEGRO_DISPLAY *)win_disp;
+   int my_code;
+   int vcode;
+
+   if (!installed)
+      return;
+
+   vcode = MapVirtualKey(scode, MAPVK_VSC_TO_VK_EX);
+
+   /* Check for an extended key first. */
+   my_code = 0;
+   if (extended)
+      my_code = extkey_to_keycode(vcode);
+   else
+      my_code = hw_to_mycode[vcode];
+
+   /* Send char events, but not for modifier keys or dead keys. */
+   if (my_code < ALLEGRO_KEY_MODIFIERS) {
+      ALLEGRO_EVENT event;
+      
+      bool actual_repeat = repeated && _AL_KEYBOARD_STATE_KEY_DOWN(the_state, my_code);
+                           _AL_KEYBOARD_STATE_SET_KEY_DOWN(the_state, my_code);
+      _al_event_source_lock(&the_keyboard.es);
+      printf("%d\n", vcode);
+      event.keyboard.timestamp = al_get_time();
+      event.keyboard.display = display;
+      event.keyboard.keycode = my_code;
+      event.keyboard.type = ALLEGRO_EVENT_KEY_CHAR;
+      update_toggle_modifiers();
+      event.keyboard.modifiers = modifiers;
+      event.keyboard.repeat = actual_repeat;
+      event.keyboard.unichar = unichar;
+      _al_event_source_emit_event(&the_keyboard.es, &event);
+
+      _al_event_source_unlock(&the_keyboard.es);
+   }
+}
+
 
 
 /* _al_win_kbd_handle_key_release:
diff --git a/src/win/wwindow.c b/src/win/wwindow.c
index c81d7d0..c58caa5 100644
--- a/src/win/wwindow.c
+++ b/src/win/wwindow.c
@@ -20,8 +20,11 @@
 #define WINVER 0x0501
 #endif
 
+#define UNICODE
+
 #include <windows.h>
 #include <windowsx.h>
+#include <stdio.h>
 
 /* Only used for Vista and up. */
 #ifndef WM_MOUSEHWHEEL
@@ -72,7 +75,7 @@ static void display_flags_to_window_styles(int flags,
 HWND _al_win_create_hidden_window()
 {
    HWND window = CreateWindowEx(0,
-      "ALEX", "hidden", WS_POPUP,
+      L"ALEX", L"hidden", WS_POPUP,
       -5000, -5000, 0, 0,
       NULL,NULL,window_class.hInstance,0);
    return window;
@@ -149,7 +152,7 @@ HWND _al_win_create_window(ALLEGRO_DISPLAY *display, int width, int height, int
    }
 
    my_window = CreateWindowEx(ex_style,
-      "ALEX", "Allegro", style,
+      L"ALEX", L"Allegro", style,
       pos_x, pos_y, width, height,
       NULL,NULL,window_class.hInstance,0);
 
@@ -210,7 +213,7 @@ HWND _al_win_create_faux_fullscreen_window(LPCTSTR devname, ALLEGRO_DISPLAY *dis
    ex_style = WS_EX_TOPMOST;
 
    my_window = CreateWindowEx(ex_style,
-      "ALEX", "Allegro", style,
+      L"ALEX", L"Allegro", style,
       x1, y1, width, height,
       NULL,NULL,window_class.hInstance,0);
 
@@ -671,11 +674,18 @@ static LRESULT CALLBACK window_callback(HWND hWnd, UINT message,
          int scode = (lParam >> 16) & 0xff;
          bool extended = (lParam >> 24) & 0x1;
          bool repeated = (lParam >> 30) & 0x1;
-         /* We can't use TranslateMessage() because we don't know if it will
-            produce a WM_CHAR or not. */
          _al_win_kbd_handle_key_press(scode, vcode, extended, repeated, win_display);
          break;
       }
+      case WM_SYSCHAR:
+      case WM_CHAR: {
+         int vcode = wParam;
+         int scode = (lParam >> 16) & 0xff;
+         bool extended = (lParam >> 24) & 0x1;
+         bool repeated = (lParam >> 30) & 0x1;
+         _al_win_kbd_handle_char(scode, vcode, extended, repeated, win_display);
+         break;
+      }
       case WM_SYSKEYUP:
       case WM_KEYUP: {
          int vcode = wParam;
@@ -803,7 +813,7 @@ static LRESULT CALLBACK window_callback(HWND hWnd, UINT message,
                SetWindowPos(GetForegroundWindow(), HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
             }
             // Show the taskbar in case we hid it
-            SetWindowPos(FindWindow("Shell_traywnd", ""), 0, 0, 0, 0, 0, SWP_SHOWWINDOW);
+            SetWindowPos(FindWindow(L"Shell_traywnd", L""), 0, 0, 0, 0, 0, SWP_SHOWWINDOW);
             if (d->flags & ALLEGRO_FULLSCREEN) {
                d->vt->switch_out(d);
             }
@@ -911,15 +921,15 @@ int _al_win_init_window()
    window_class.hIcon = NULL;
    window_class.hInstance = GetModuleHandle(NULL);
    window_class.lpfnWndProc = window_callback;
-   window_class.lpszClassName = "ALEX";
+   window_class.lpszClassName = L"ALEX";
    window_class.lpszMenuName = NULL;
    window_class.style = CS_VREDRAW|CS_HREDRAW|CS_OWNDC;
 
    RegisterClass(&window_class);
 
    if (_al_win_msg_call_proc == 0 && _al_win_msg_suicide == 0) {
-      _al_win_msg_call_proc = RegisterWindowMessage("Allegro call proc");
-      _al_win_msg_suicide = RegisterWindowMessage("Allegro window suicide");
+      _al_win_msg_call_proc = RegisterWindowMessage(L"Allegro call proc");
+      _al_win_msg_suicide = RegisterWindowMessage(L"Allegro window suicide");
    }
 
    return true;
@@ -1155,7 +1165,7 @@ bool _al_win_set_display_flag(ALLEGRO_DISPLAY *display, int flag, bool onoff)
             // Hide the taskbar if fullscreening on primary monitor
             if (win_display->adapter == 0) {
                SetWindowPos(
-                  FindWindow("Shell_traywnd", ""),
+                  FindWindow(L"Shell_traywnd", L""),
                   0,
                   0, 0,
                   0, 0,
@@ -1173,7 +1183,7 @@ bool _al_win_set_display_flag(ALLEGRO_DISPLAY *display, int flag, bool onoff)
 
             // Show the taskbar
             SetWindowPos(
-               FindWindow("Shell_traywnd", ""), 0, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOZORDER | SWP_NOMOVE);
+               FindWindow(L"Shell_traywnd", L""), 0, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOZORDER | SWP_NOMOVE);
             // Center the window
             _al_win_get_window_center(win_display, display->w, display->h, &pos_x, &pos_y);
             GetWindowInfo(win_display->window, &wi);
@@ -1199,7 +1209,9 @@ bool _al_win_set_display_flag(ALLEGRO_DISPLAY *display, int flag, bool onoff)
 void _al_win_set_window_title(ALLEGRO_DISPLAY *display, const char *title)
 {
    ALLEGRO_DISPLAY_WIN *win_display = (ALLEGRO_DISPLAY_WIN *)display;
-   SetWindowText(win_display->window, title);
+   (void)title;
+   (void)title;
+   //~ SetWindowText(win_display->window, title);
 }
 
 bool _al_win_set_window_constraints(ALLEGRO_DISPLAY *display,
