Release 970202

Sun Feb  2 12:31:03 1997  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [files/drive.c]
	Fixed SetCurrentDirectory() to also change the current drive.

	* [win32/except.c] [tools/build.c]
	Use Win32 register functions to implement exception handling.
	Fixed UnhandledExceptionFilter.

Fri Jan 31 15:42:41  1997  David Faure  <david.faure@ihamy.insa-lyon.fr>

	* [windows/keyboard.c]
	Added KEYBOARD_GenerateMsg to generate Caps Lock and NumLock events
	Added calls to KEYBOARD_GenerateMsg when the key is pressed/released
	or when the state has changed, out of wine.
	Changed type 3-state 'ToggleKeyState' to boolean. The On/Off is given
	by InputKeyStateTable.

Wed Jan 29 21:53:04 1997  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [loader/*resource.c][if1632/thunk.c]
	EnumResource* added.

	* [loader/pe_resource.] [loader/resource.c]
	SizeofResource32(), LoadAccelerators32() added.

	* [misc/lstr.c]
	FormatMessage %n added.

	* [misc/crtdll.c][include/ctrdll.h][if1632/crtdll.spec]
	_chdrive,_errno,_isctype added.

	* [misc/cpu.c]
	Replaced runtime_cpu by GetSystemInfo().

	* [windows/hook.c][include/hook.h]
	Fixed mapping of hooks to win32/unicode.

	* [windows/keyboard.c] [windows/defwnd.c]
	Updated to win32 standard.
	ALT-<Menukey> fixed.

	* [windows/queue.c]
	GetWindowThreadProcessId() implemented.

Mon Jan 27 16:42:49 1997  John Harvey <john@division.co.uk>

	* [graphics/metafiledrv/*] [graphics/x11drv/*]
	  [objects/bitmap.c] [objects/brush.c] [objects/font.c]
	  [objects/gdiobj.c] [objects/pen.c]
	Moved SelectObject to graphics drivers. Printer support now works
	in a few cases but is definitely not complete. Generic/text driver
	works. The postscript driver works if true type fonts are disabled
	from the control panel. To enable printer support add Printer=on
	to the wine section of your wine.conf file. This causes write not
	to work properly. I know that several other printer drivers do not
	work.

	* [tools/build.c]
	Make .stabs not used for svr4 since it doesn't use GNU assembler.

	* [misc/fontengine.c]
	Make sure a printf doesn't crash the system.

Sat Jan 25 15:53:35 1997  Huw D M Davies <h.davies1@physics.oxford.ac.uk>

	* [objects/metafile.c]
	Fixed some problems with PlayMetaFileRecord().

	* [objects/dc.c]
	hClipRgn gets initialized in GetDCState().

Fri Jan 24 21:22:26 1997  Philippe De Muyter  <phdm@info.ucl.ac.be>

	* [debugger/stabs.c]
	Handle file names beginning with '/'.

Fri Jan 24 18:33:04 1997  Robert Pouliot <krynos@clic.net>

	* [*/*]
	Some more patches for OS/2 support.

Fri Jan 24 11:30:41 1997  Bang Jun-Young  <bangjy@nownuri.nowcom.co.kr>

	* [resources/sysres_Ko.rc]
	Updated support for Korean (Ko) language.
diff --git a/windows/caret.c b/windows/caret.c
index da49ee4..2419d96 100644
--- a/windows/caret.c
+++ b/windows/caret.c
@@ -172,9 +172,9 @@
     dprintf_caret(stddeb,"DestroyCaret: hwnd=%04x, timerid=%d\n",
 		Caret.hwnd, Caret.timerid);
 
-    DeleteObject32( Caret.hBrush );
     CARET_KillTimer();
     CARET_DisplayCaret(CARET_OFF);
+    DeleteObject32( Caret.hBrush );
     Caret.hwnd = 0;
     return TRUE;
 }
diff --git a/windows/defwnd.c b/windows/defwnd.c
index c393eb7..d408432 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -260,7 +260,7 @@
 	else if( wParam == VK_F10 )
 	         iF10Key = 1;
 	     else
-	         if( wParam == VK_ESCAPE && GetKeyState(VK_SHIFT) < 0 )
+	         if( wParam == VK_ESCAPE && (GetKeyState32(VK_SHIFT) & 0x8000))
 		     SendMessage16( wndPtr->hwndSelf, WM_SYSCOMMAND,
                                     (WPARAM16)SC_KEYMENU, (LPARAM)VK_SPACE);
 	break;
diff --git a/windows/dialog.c b/windows/dialog.c
index 5fbd4ee..7be07fe 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -5,10 +5,12 @@
  */
 
 #include <ctype.h>
+#include <errno.h>
 #include <limits.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <errno.h>
 #include "windows.h"
 #include "dialog.h"
 #include "drive.h"
@@ -904,7 +906,7 @@
             if (!(dlgCode & DLGC_WANTTAB))
             {
                 SendMessage16( hwndDlg, WM_NEXTDLGCTL,
-                             (GetKeyState(VK_SHIFT) & 0x8000), 0 );
+                             (GetKeyState32(VK_SHIFT) & 0x8000), 0 );
                 return TRUE;
             }
             break;
diff --git a/windows/hook.c b/windows/hook.c
index e7a073d..1a9b793 100644
--- a/windows/hook.c
+++ b/windows/hook.c
@@ -990,7 +990,7 @@
     HOOKDATA *data;
     if (HIWORD(hhook) != HOOK_MAGIC) return NULL;
     if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR( LOWORD(hhook) ))) return NULL;
-    if (data->flags & HOOK_WIN32) return NULL;
+    if ((data->flags & HOOK_MAPTYPE) != HOOK_WIN16) return NULL;
     return (HOOKPROC16)data->proc;
 }
 
@@ -1033,7 +1033,7 @@
 
     if (!(hook = HOOK_GetHook( id , GetTaskQueue(0) ))) return 0;
     if (!(hook = HOOK_FindValidHook(hook))) return 0;
-    return HOOK_CallHook( hook, HOOK_WIN32, code, wParam, lParam );
+    return HOOK_CallHook( hook, HOOK_WIN32A, code, wParam, lParam );
 }
 
 /***********************************************************************
@@ -1048,7 +1048,7 @@
 
     if (!(hook = HOOK_GetHook( id , GetTaskQueue(0) ))) return 0;
     if (!(hook = HOOK_FindValidHook(hook))) return 0;
-    return HOOK_CallHook( hook, HOOK_WIN32 | HOOK_UNICODE, code, wParam,
+    return HOOK_CallHook( hook, HOOK_WIN32W, code, wParam,
 			  lParam );
 }
 
@@ -1173,7 +1173,7 @@
     /* WH_MSGFILTER is the only task-specific hook for SetWindowsHook() */
     HTASK16 hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
 
-    HANDLE16 handle = HOOK_SetHook( id, proc, HOOK_WIN32, hInst, hTask );
+    HANDLE16 handle = HOOK_SetHook( id, proc, HOOK_WIN32A, hInst, hTask );
     return (handle) ? (HHOOK)MAKELONG( handle, HOOK_MAGIC ) : 0;
 }
 
@@ -1190,8 +1190,7 @@
     /* WH_MSGFILTER is the only task-specific hook for SetWindowsHook() */
     HTASK16 hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
 
-    HANDLE16 handle = HOOK_SetHook( id, proc, HOOK_WIN32 | HOOK_UNICODE,
-				    hInst, hTask );
+    HANDLE16 handle = HOOK_SetHook( id, proc, HOOK_WIN32W, hInst, hTask );
     return (handle) ? (HHOOK)MAKELONG( handle, HOOK_MAGIC ) : 0;
 }
 
@@ -1221,7 +1220,7 @@
     else
       hTask = LOWORD(dwThreadID);
 
-    handle = HOOK_SetHook( id, proc, HOOK_WIN32, hInst, hTask );
+    handle = HOOK_SetHook( id, proc, HOOK_WIN32A, hInst, hTask );
     return (handle) ? (HHOOK)MAKELONG( handle, HOOK_MAGIC ) : (HHOOK)NULL;
 }
 
@@ -1240,7 +1239,7 @@
     else
       hTask = LOWORD(dwThreadID);
 
-    handle = HOOK_SetHook( id, proc, HOOK_WIN32 | HOOK_UNICODE, hInst, hTask );
+    handle = HOOK_SetHook( id, proc, HOOK_WIN32W, hInst, hTask );
     return (handle) ? (HHOOK)MAKELONG( handle, HOOK_MAGIC ) : (HHOOK)NULL;
 }
 
@@ -1340,7 +1339,7 @@
     oldhook = (HOOKDATA *)USER_HEAP_LIN_ADDR( LOWORD(hhook) );
     fromtype = oldhook->flags & HOOK_MAPTYPE;
 
-    if (!(fromtype & HOOK_WIN32))
+    if (fromtype == HOOK_WIN16)
       fprintf(stderr, "CallNextHookEx32: called from 16bit hook!\n");
 
     return HOOK_CallHook( next, fromtype, code, wParam, lParam );
diff --git a/windows/keyboard.c b/windows/keyboard.c
index 12c3fce..f83cc16 100644
--- a/windows/keyboard.c
+++ b/windows/keyboard.c
@@ -6,6 +6,7 @@
  * Copyright 1997 David Faure
  *
  */
+#define NO_TRANSITION_TYPES
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -26,6 +27,7 @@
 #include "debug.h"
 #include "xmalloc.h"
 #include "accel.h"
+#include "struct32.h"
 
 BOOL32 MouseButtonsStates[3];
 BOOL32 AsyncMouseButtonsStates[3];
@@ -54,8 +56,6 @@
     unsigned long lp2;
 } KEYLP;
 
-typedef enum {OFF,INTERM,ON} ToggleKeyState;
-
 /* Keyboard translation tables */
 static const int special_key[] =
 {
@@ -269,6 +269,50 @@
     return TRUE;
 }
 
+static BOOL32 NumState=FALSE, CapsState=FALSE;
+
+void KEYBOARD_GenerateMsg( WORD vkey, int Evtype, XKeyEvent * event, KEYLP localkeylp )
+{
+  BOOL32 * State = (vkey==VK_NUMLOCK? &NumState : &CapsState);
+
+  if (*State) {
+    /* The INTERMEDIARY state means : just after a 'press' event, if a 'release' event comes,
+       don't treat it. It's from the same key press. Then the state goes to ON.
+       And from there, a 'release' event will switch off the toggle key. */
+    *State=FALSE;
+    dprintf_keyboard(stddeb,"INTERM : don\'t treat release of toggle key. InputKeyStateTable[%#x] = %#x\n",vkey,InputKeyStateTable[vkey]);
+  } else
+    {
+	if ( InputKeyStateTable[vkey] & 0x1 ) /* it was ON */
+	  {
+	    if (Evtype!=KeyPress)
+	      {
+		dprintf_keyboard(stddeb,"ON + KeyRelease => generating DOWN and UP messages.\n");
+		localkeylp.lp1.previous = 0; /* ? */
+		localkeylp.lp1.transition = 0;
+		hardware_event( WM_KEYDOWN, vkey, localkeylp.lp2, event->x_root - desktopX,
+				event->y_root - desktopY, event->time - MSG_WineStartTicks, 0);
+		hardware_event( WM_KEYUP, vkey, localkeylp.lp2, event->x_root - desktopX,
+				event->y_root - desktopY, event->time - MSG_WineStartTicks, 0);
+		*State=FALSE;
+		InputKeyStateTable[vkey] &= ~0x01; /* Toggle state to off. */ 
+	      } 
+	  }
+	else /* it was OFF */
+	  if (Evtype==KeyPress)
+	    {
+	      dprintf_keyboard(stddeb,"OFF + Keypress => generating DOWN and UP messages.\n");
+	      hardware_event( WM_KEYDOWN, vkey, localkeylp.lp2, event->x_root - desktopX,
+			      event->y_root - desktopY, event->time - MSG_WineStartTicks, 0);
+	      localkeylp.lp1.previous = 1;
+	      localkeylp.lp1.transition = 1;
+	      hardware_event( WM_KEYUP, vkey, localkeylp.lp2, event->x_root - desktopX,
+			      event->y_root - desktopY, event->time - MSG_WineStartTicks, 0);
+	      *State=TRUE; /* Goes to intermediary state before going to ON */
+	      InputKeyStateTable[vkey] |= 0x01; /* Toggle state to on. */
+	    }
+    }
+}
 
 /***********************************************************************
  *           KEYBOARD_HandleEvent
@@ -282,11 +326,7 @@
     KeySym keysym;
     WORD vkey = 0;
     KEYLP keylp;
-    WORD message;
-    static BOOL force_extended = FALSE; /* hack for AltGr translation */
-    BOOL DontPropagate;
-    ToggleKeyState * State;
-    static ToggleKeyState NumState=OFF, CapsState=OFF;
+    static BOOL32 force_extended = FALSE; /* hack for AltGr translation */
 
     int ascii_chars = XLookupString(event, Str, 1, &keysym, &cs);
 
@@ -318,21 +358,14 @@
                 keysym, ksname, ascii_chars, Str[0] & 0xff, Str);
 	}
 
-#if 0
-    /* Ctrl-Alt-Return enters the debugger */
-    if ((keysym == XK_Return) && (event->type == KeyPress) &&
-        (event->state & ControlMask) && (event->state & Mod1Mask))
-        DEBUG_EnterDebugger();
-#endif
-
     vkey = EVENT_event_to_vkey(event);
     if (force_extended) vkey |= 0x100;
 
     dprintf_key(stddeb, "keycode 0x%x converted to vkey 0x%x\n",
 		    event->keycode, vkey);
 
-    if (vkey)
-    {
+   if (vkey)
+   {
     keylp.lp1.count = 1;
     keylp.lp1.code = LOBYTE(event->keycode) - 8;
     keylp.lp1.extended = (vkey & 0x100 ? 1 : 0);
@@ -341,75 +374,60 @@
 				/* it's '1' under windows, when a dialog box appears
 				 * and you press one of the underlined keys - DF*/
     vkey &= 0xff;
-    if (event->type == KeyPress)
-    {
-	keylp.lp1.previous = (InputKeyStateTable[vkey] & 0x80) != 0;
-        if (!(InputKeyStateTable[vkey] & 0x80))
-            InputKeyStateTable[vkey] ^= 0x01;
-	InputKeyStateTable[vkey] |= 0x80;
-	keylp.lp1.transition = 0;
-	message = (InputKeyStateTable[VK_MENU] & 0x80)
-		    && !(InputKeyStateTable[VK_CONTROL] & 0x80)
-			 ? WM_SYSKEYDOWN : WM_KEYDOWN;
-    }
-    else
-    {
-	UINT sysKey = (InputKeyStateTable[VK_MENU] & 0x80)
-			&& !(InputKeyStateTable[VK_CONTROL] & 0x80)
-			&& (force_extended == FALSE); /* for Alt from AltGr */
 
-	InputKeyStateTable[vkey] &= ~0x80; 
-	keylp.lp1.previous = 1;
-	keylp.lp1.transition = 1;
-	message = sysKey ? WM_SYSKEYUP : WM_KEYUP;
-    }
-    keylp.lp1.context = ( (event->state & Mod1Mask)  || 
-			  (InputKeyStateTable[VK_MENU] & 0x80)) ? 1 : 0;
-    DontPropagate = FALSE;
-    if ((vkey==VK_NUMLOCK) || (vkey==VK_CAPITAL))
+    switch(vkey)
+    {
+    case VK_NUMLOCK:    
+      KEYBOARD_GenerateMsg(VK_NUMLOCK,event->type,event,keylp); break;
+    case VK_CAPITAL:
+      dprintf_keyboard(stddeb,"Caps Lock event. (type %d). State before : %#.2x\n",event->type,InputKeyStateTable[vkey]);
+      KEYBOARD_GenerateMsg(VK_CAPITAL,event->type,event,keylp); 
+      dprintf_keyboard(stddeb,"State after : %#.2x\n",InputKeyStateTable[vkey]);
+      break;
+    default:
       {
-	
-	switch (*( State = (vkey==VK_NUMLOCK? &NumState : &CapsState))) {
-	case OFF:if (event->type==KeyPress)
+	WORD message;
+	if (event->type == KeyPress)
 	  {
-	    dprintf_keyboard(stddeb,"OFF + Keypress => DOWN and UP generated. \n");
-	    hardware_event( message, vkey, keylp.lp2, event->x_root - desktopX,
-			    event->y_root - desktopY, event->time - MSG_WineStartTicks, 0);
-	    message += WM_KEYUP - WM_KEYDOWN; /* create a *UP message from the *DOWN one */
+	    keylp.lp1.previous = (InputKeyStateTable[vkey] & 0x80) != 0;
+	    if (!(InputKeyStateTable[vkey] & 0x80))
+	      InputKeyStateTable[vkey] ^= 0x01;
+	    InputKeyStateTable[vkey] |= 0x80;
+	    keylp.lp1.transition = 0;
+	    message = (InputKeyStateTable[VK_MENU] & 0x80)
+	      && !(InputKeyStateTable[VK_CONTROL] & 0x80)
+	      ? WM_SYSKEYDOWN : WM_KEYDOWN;
+	  }
+	else
+	  {
+            BOOL32 sysKey = (InputKeyStateTable[VK_MENU] & 0x80)
+                && !(InputKeyStateTable[VK_CONTROL] & 0x80)
+                && (force_extended == FALSE); /* for Alt from AltGr */
+	    
+	    InputKeyStateTable[vkey] &= ~0x80; 
 	    keylp.lp1.previous = 1;
 	    keylp.lp1.transition = 1;
-	    *State = INTERM;
-	  } break;
-	case INTERM:
-	  /* The 'INTERM' state means : just after a 'press' event, if a 'release' event comes,
-	     don't "propagate" it. It's from the same key press. Then the state goes to ON.
-	     And from there, a 'release' event will switch off the toggle key. */
-	  DontPropagate = TRUE;
-	  *State=ON;
-	  InputKeyStateTable[vkey] |= 0x01; /* force to 'on' event if a release event was received */
-	  dprintf_keyboard(stddeb,"INTERM : don\'t propagate press/release of toggle key. InputKeyStateTable[%#x] = %#x",vkey,InputKeyStateTable[vkey]);
-	  break;
-	case ON: if (event->type==KeyPress) DontPropagate = TRUE; else
+	    message = sysKey ? WM_SYSKEYUP : WM_KEYUP;
+	  }
+	keylp.lp1.context = ( (event->state & Mod1Mask)  || 
+			      (InputKeyStateTable[VK_MENU] & 0x80)) ? 1 : 0;
+	if (!(InputKeyStateTable[VK_NUMLOCK] & 0x01) != !(event->state & NumLockMask))
+	  { 
+	    dprintf_keyboard(stddeb,"Adjusting NumLock state. \n");
+	    KEYBOARD_GenerateMsg(VK_NUMLOCK,KeyPress,event,keylp);
+	    KEYBOARD_GenerateMsg(VK_NUMLOCK,KeyRelease,event,keylp);
+	  }
+	if (!(InputKeyStateTable[VK_CAPITAL] & 0x01) != !(event->state & LockMask))
 	  {
-	    KEYLP downkeylp = keylp;
-	    dprintf_keyboard(stddeb,"ON + KeyRelease => generating DOWN msg before the UP\n");
-	    message += WM_KEYDOWN - WM_KEYUP; /* create the *DOWN from the *UP */
-	    downkeylp.lp1.previous = 0; /* ? */
-	    downkeylp.lp1.transition = 0;
-	    hardware_event( message, vkey, downkeylp.lp2, event->x_root - desktopX,
-			    event->y_root - desktopY, event->time - MSG_WineStartTicks, 0);
-	    message += WM_KEYUP - WM_KEYDOWN; /* back to the UP message */
-            *State=OFF;
-	  } break;
-	}
-	dprintf_keyboard(stddeb,"Internal State : %d (0=OFF 1=INTERM 2=ON). InputTable state : %#x \n",*State,InputKeyStateTable[vkey]);
-      } else {
-	if (NumState == INTERM) NumState = ON;
-	if (CapsState == INTERM) CapsState = ON;
-      }
-    
-    if (!DontPropagate)
-      {
+	    dprintf_keyboard(stddeb,"Adjusting Caps Lock state. State before %#.2x \n",InputKeyStateTable[VK_CAPITAL]);
+	    KEYBOARD_GenerateMsg(VK_CAPITAL,KeyPress,event,keylp);
+	    KEYBOARD_GenerateMsg(VK_CAPITAL,KeyRelease,event,keylp);
+	    dprintf_keyboard(stddeb,"State after %#.2x \n",InputKeyStateTable[VK_CAPITAL]);
+	  }
+	/* End of intermediary states. */
+	NumState = FALSE;
+	CapsState = FALSE;
+
 	dprintf_key(stddeb,"            wParam=%04X, lParam=%08lX\n", 
 		    vkey, keylp.lp2 );
 	dprintf_key(stddeb,"            InputKeyState=%X\n",
@@ -419,18 +437,27 @@
 			event->y_root - desktopY, event->time - MSG_WineStartTicks, 0 );
       }
     }
+   }
 }
 
 
 /**********************************************************************
  *		GetKeyState			[USER.106]
+ */
+WORD GetKeyState16(INT16 vkey)
+{
+    return GetKeyState32(vkey);
+}
+
+/**********************************************************************
+ *		GetKeyState			[USER32.248]
  * An application calls the GetKeyState function in response to a
  * keyboard-input message.  This function retrieves the state of the key
  * at the time the input message was generated.  (SDK 3.1 Vol 2. p 390)
  */
-INT GetKeyState(INT vkey)
+WORD GetKeyState32(INT32 vkey)
 {
-    INT retval;
+    INT32 retval;
 
     switch (vkey)
 	{
@@ -446,20 +473,20 @@
 	default :
 	    if (vkey >= 'a' && vkey <= 'z')
 		vkey += 'A' - 'a';
-	    retval = ( (INT)(QueueKeyStateTable[vkey] & 0x80) << 8 ) |
-		       (INT)(QueueKeyStateTable[vkey] & 0x01);
+	    retval = ( (WORD)(QueueKeyStateTable[vkey] & 0x80) << 8 ) |
+		       (WORD)(QueueKeyStateTable[vkey] & 0x01);
 	}
     dprintf_key(stddeb, "GetKeyState(0x%x) -> %x\n", vkey, retval);
     return retval;
 }
 
 /**********************************************************************
- *		GetKeyboardState			[USER.222]
+ *		GetKeyboardState	[USER.222][USER32.253]
  * An application calls the GetKeyboardState function in response to a
  * keyboard-input message.  This function retrieves the state of the keyboard
  * at the time the input message was generated.  (SDK 3.1 Vol 2. p 387)
  */
-void GetKeyboardState(BYTE *lpKeyState)
+VOID GetKeyboardState(LPBYTE lpKeyState)
 {
     dprintf_key(stddeb, "GetKeyboardState()\n");
     if (lpKeyState != NULL) {
@@ -471,9 +498,9 @@
 }
 
 /**********************************************************************
- *      SetKeyboardState            [USER.223]
+ *      SetKeyboardState            [USER.223][USER32.483]
  */
-void SetKeyboardState(BYTE *lpKeyState)
+VOID SetKeyboardState(LPBYTE lpKeyState)
 {
     dprintf_key(stddeb, "SetKeyboardState()\n");
     if (lpKeyState != NULL) {
@@ -485,7 +512,7 @@
 }
 
 /**********************************************************************
- *            GetAsyncKeyState        (USER.249)
+ *            GetAsyncKeyState        (USER32.206)
  *
  *	Determine if a key is or was pressed.  retval has high-order 
  * bit set to 1 if currently pressed, low-order bit set to 1 if key has
@@ -497,7 +524,7 @@
  * mouse or key had been depressed since the last call to 
  * GetAsyncKeyState.
  */
-int GetAsyncKeyState(int nKey)
+WORD GetAsyncKeyState32(INT32 nKey)
 {
     short retval;	
 
@@ -527,17 +554,34 @@
     return retval;
 }
 
+/**********************************************************************
+ *            GetAsyncKeyState        (USER.249)
+ */
+WORD GetAsyncKeyState16(INT16 nKey)
+{
+    return GetAsyncKeyState32(nKey);
+}
+
+
 
 /**********************************************************************
  *			TranslateAccelerator 	[USER.178]
  *
  * FIXME: should send some WM_INITMENU or/and WM_INITMENUPOPUP  -messages
  */
-INT16 TranslateAccelerator(HWND hWnd, HACCEL16 hAccel, LPMSG16 msg)
+INT32 TranslateAccelerator32(HWND32 hWnd, HACCEL32 hAccel, LPMSG32 msg)
+{
+    MSG16	msg16;
+
+    STRUCT32_MSG32to16(msg,&msg16);
+    return TranslateAccelerator16(hWnd,hAccel,&msg16);
+}
+	
+INT16 TranslateAccelerator16(HWND16 hWnd, HACCEL16 hAccel, LPMSG16 msg)
 {
     ACCELHEADER	*lpAccelTbl;
     int 	i;
-    BOOL sendmsg;
+    BOOL32 sendmsg;
     
     if (hAccel == 0 || msg == NULL) return 0;
     if (msg->message != WM_KEYDOWN &&
@@ -567,12 +611,12 @@
       {
        if(lpAccelTbl->tbl[i].type & VIRTKEY_ACCEL) 
        {
-	INT mask = 0;
+	INT32 mask = 0;
         dprintf_accel(stddeb,"found accel for virt_key %04x (scan %04x)",
   	                       msg->wParam,0xff & HIWORD(msg->lParam));                
-	if(GetKeyState(VK_SHIFT) & 0x8000) mask |= SHIFT_ACCEL;
-	if(GetKeyState(VK_CONTROL) & 0x8000) mask |= CONTROL_ACCEL;
-	if(GetKeyState(VK_MENU) & 0x8000) mask |= ALT_ACCEL;
+	if(GetKeyState32(VK_SHIFT) & 0x8000) mask |= SHIFT_ACCEL;
+	if(GetKeyState32(VK_CONTROL) & 0x8000) mask |= CONTROL_ACCEL;
+	if(GetKeyState32(VK_MENU) & 0x8000) mask |= ALT_ACCEL;
 	if(mask == (lpAccelTbl->tbl[i].type &
 			    (SHIFT_ACCEL | CONTROL_ACCEL | ALT_ACCEL)))
           sendmsg=TRUE;			    
@@ -672,6 +716,9 @@
 }
 
 
+/******************************************************************************
+ *    	OemKeyScan			[KEYBOARD.128][USER32.400]
+ */
 DWORD OemKeyScan(WORD wOemChar)
 {
     dprintf_keyboard(stddeb,"*OemKeyScan (%d)\n",wOemChar);
@@ -679,6 +726,9 @@
     return wOemChar;
 }
 
+/******************************************************************************
+ *    	VkKeyScanA			[USER32.572]
+ */
 /* VkKeyScan translates an ANSI character to a virtual-key and shift code
  * for the current keyboard.
  * FIXME high-order byte should yield :
@@ -691,7 +741,7 @@
  *	I.e. :	Shift = 1, Ctrl = 2, Alt = 4.
  */
 
-WORD VkKeyScan(WORD cChar)
+WORD VkKeyScan32A(CHAR cChar)
 {
 	KeyCode keycode;
     	dprintf_keyboard(stddeb,"VkKeyScan '%c'(%d) ",cChar,cChar);
@@ -706,13 +756,34 @@
 	return keyc2vkey[keycode];
 }
 
-WORD VkKeyScan32W(WORD cChar)
+/******************************************************************************
+ *    	VkKeyScan			[KEYBOARD.129]
+ */
+WORD VkKeyScan16(CHAR cChar)
 {
-	/* lower part of cChar is used anyway */
-	return VkKeyScan(cChar);
+	return VkKeyScan32A(cChar);
 }
 
-int GetKeyboardType(int nTypeFlag)
+/******************************************************************************
+ *    	VkKeyScanW			[USER32.575]
+ */
+WORD VkKeyScan32W(WCHAR cChar)
+{
+	return VkKeyScan32A((CHAR)cChar); /* FIXME: check unicode */
+}
+
+/******************************************************************************
+ *    	GetKeyboardType			[KEYBOARD.130]
+ */
+INT16 GetKeyboardType16(INT16 nTypeFlag)
+{
+  return GetKeyboardType32(nTypeFlag);
+}
+
+/******************************************************************************
+ *    	GetKeyboardType			[USER32.254]
+ */
+INT32 GetKeyboardType32(INT32 nTypeFlag)
 {
   dprintf_keyboard(stddeb,"GetKeyboardType(%d)\n",nTypeFlag);
   switch(nTypeFlag)
@@ -732,9 +803,26 @@
     }
 }
 
-/* MapVirtualKey translates keycodes from one format to another. */
 
-WORD MapVirtualKey(WORD wCode, WORD wMapType)
+/******************************************************************************
+ *    	MapVirtualKeyA			[USER32.382]
+ */
+UINT32 MapVirtualKey32A(UINT32 code, UINT32 maptype) {
+	return MapVirtualKey16(code,maptype);
+}
+
+/******************************************************************************
+ *    	MapVirtualKeyA			[USER32.384]
+ */
+UINT32 MapVirtualKey32W(UINT32 code, UINT32 maptype) {
+	return MapVirtualKey16(code,maptype);
+}
+
+/******************************************************************************
+ *    	MapVirtualKeyA			[KEYBOARD.131]
+ * MapVirtualKey translates keycodes from one format to another
+ */
+UINT16 MapVirtualKey16(UINT16 wCode, UINT16 wMapType)
 {
 #define returnMVK(value) { dprintf_keyboard(stddeb,"returning 0x%x.\n",value); return value; }
 
@@ -762,7 +850,7 @@
 			char s[2];
 			e.display = display;
 			e.state = 0; /* unshifted */
-			e.keycode = MapVirtualKey( wCode, 0);
+			e.keycode = MapVirtualKey16( wCode, 0);
 			if (!XLookupString(&e, s , 2 , &keysym, NULL))
 			  returnMVK (*s);
 			
@@ -776,7 +864,10 @@
 	return 0;
 }
 
-int GetKbCodePage(void)
+/****************************************************************************
+ *	GetKbCodePage   (KEYBOARD.132)
+ */
+INT16 GetKbCodePage(VOID)
 {
     	dprintf_keyboard(stddeb,"GetKbCodePage()\n");
 	return 850;
@@ -827,13 +918,27 @@
 	return 0;
 }
 
-int ToAscii(WORD wVirtKey, WORD wScanCode, LPSTR lpKeyState, 
-	LPVOID lpChar, WORD wFlags) 
+
+/****************************************************************************
+ *	ToAscii   (KEYBOARD.4)
+ */
+INT16 ToAscii16(UINT16 virtKey,UINT16 scanCode, LPBYTE lpKeyState, 
+	LPVOID lpChar, UINT16 flags) 
 {
+    return ToAscii32(virtKey,scanCode,lpKeyState,lpChar,flags);
+}
+
+/****************************************************************************
+ *	ToAscii   (USER32.545)
+ */
+INT32 ToAscii32(
+	UINT32 virtKey,UINT32 scanCode,LPBYTE lpKeyState,
+	LPWORD lpChar,UINT32 flags
+) {
     XKeyEvent e;
     KeySym keysym;
     static XComposeStatus cs;
-    int ret;
+    INT32 ret;
     WORD keyc;
 
     e.display = display;
@@ -841,26 +946,26 @@
     for (keyc=min_keycode; keyc<=max_keycode; keyc++)
       { /* this could be speeded up by making another table, an array of struct vkey,keycode
 	 * (vkey -> keycode) with vkeys sorted .... but it takes memory (512*3 bytes)!  DF */
-	if ((keyc2vkey[keyc] & 0xFF)== wVirtKey) /* no need to make a more precise test (with the extended bit correctly set above wVirtKey ... VK* are different enough... */
+	if ((keyc2vkey[keyc] & 0xFF)== virtKey) /* no need to make a more precise test (with the extended bit correctly set above virtKey ... VK* are different enough... */
 	  {
-	    if ((e.keycode) && ((wVirtKey<0x10) || (wVirtKey>0x12))) 
+	    if ((e.keycode) && ((virtKey<0x10) || (virtKey>0x12))) 
 		/* it's normal to have 2 shift, control, and alt ! */
 		dprintf_keyboard(stddeb,"ToAscii : The keycodes %X and %X are matching the same vkey %X\n",
-				 e.keycode,keyc,wVirtKey);
+				 e.keycode,keyc,virtKey);
 	    e.keycode = keyc;
 	  }
       }
     if ((!e.keycode) && (lpKeyState[VK_NUMLOCK] & 0x01)) 
       {
-	if ((wVirtKey>=VK_NUMPAD0) && (wVirtKey<=VK_NUMPAD9))
-	  e.keycode = XKeysymToKeycode(e.display, wVirtKey-VK_NUMPAD0+XK_KP_0);
-	if (wVirtKey==VK_DECIMAL)
+	if ((virtKey>=VK_NUMPAD0) && (virtKey<=VK_NUMPAD9))
+	  e.keycode = XKeysymToKeycode(e.display, virtKey-VK_NUMPAD0+XK_KP_0);
+	if (virtKey==VK_DECIMAL)
 	  e.keycode = XKeysymToKeycode(e.display, XK_KP_Decimal);
       }
     if (!e.keycode)
       {
-	fprintf(stderr,"ToAscii : Unknown virtual key %X !!! \n",wVirtKey);
-	return wVirtKey; /* whatever */
+	fprintf(stderr,"ToAscii : Unknown virtual key %X !!! \n",virtKey);
+	return virtKey; /* whatever */
       }
     e.state = 0;
     if (lpKeyState[VK_SHIFT] & 0x80)
@@ -876,8 +981,8 @@
     if (lpKeyState[VK_NUMLOCK] & 0x01)
 	e.state |= NumLockMask;
     dprintf_key(stddeb, "ToAscii(%04X, %04X) : faked state = %X\n",
-		wVirtKey, wScanCode, e.state);
-    ret = XLookupString(&e, lpChar, 2, &keysym, &cs);
+		virtKey, scanCode, e.state);
+    ret = XLookupString(&e, (LPVOID)lpChar, 2, &keysym, &cs);
     if (ret == 0)
 	{
 	BYTE dead_char = 0;
@@ -922,8 +1027,8 @@
 		{
 		fprintf(stderr, "Please report : no char for keysym %04lX (%s) :\n",
 			keysym, ksname);
-		fprintf(stderr, "  wVirtKey = %X, wScanCode = %X, keycode = %X, state = %X\n",
-			wVirtKey, wScanCode, e.keycode, e.state);
+		fprintf(stderr, "  virtKey = %X, scanCode = %X, keycode = %X, state = %X\n",
+			virtKey, scanCode, e.keycode, e.state);
 		}
 	    }
 	}
diff --git a/windows/mdi.c b/windows/mdi.c
index 558f9ce..317c8ae 100644
--- a/windows/mdi.c
+++ b/windows/mdi.c
@@ -1573,12 +1573,12 @@
   
   if( wnd->dwStyle & WS_DISABLED ) return 0;
    
-  if ((GetKeyState(VK_CONTROL) & 0x8000) && !(GetKeyState(VK_MENU) & 0x8000))
+  if ((GetKeyState32(VK_CONTROL) & 0x8000) && !(GetKeyState32(VK_MENU) & 0x8000))
     switch( msg->wParam )
       {
 	case VK_F6:
 	case VK_SEPARATOR:
-	     wParam = ( GetKeyState(VK_SHIFT) & 0x8000 )? SC_NEXTWINDOW: SC_PREVWINDOW;
+	     wParam = ( GetKeyState32(VK_SHIFT) & 0x8000 )? SC_NEXTWINDOW: SC_PREVWINDOW;
 	     break;
 	case VK_RBUTTON:
 	     wParam = SC_CLOSE; 
diff --git a/windows/message.c b/windows/message.c
index 7358f4b..4ceb269 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -1223,8 +1223,8 @@
 		msg->wParam, HIWORD(msg->lParam) );
 
 	/* FIXME : should handle ToAscii yielding 2 */
-	switch (ToAscii(msg->wParam, HIWORD(msg->lParam),
-		(LPSTR)&QueueKeyStateTable, wparam, 0)) 
+	switch (ToAscii32(msg->wParam, HIWORD(msg->lParam),
+		QueueKeyStateTable,(LPWORD)wparam, 0)) 
 	    {
 	    case 1 :
 		message = message == WM_KEYDOWN ? WM_CHAR : WM_SYSCHAR;
diff --git a/windows/msgbox.c b/windows/msgbox.c
index f5a5d26..1ad540d 100644
--- a/windows/msgbox.c
+++ b/windows/msgbox.c
@@ -197,6 +197,9 @@
 INT32 MessageBox32A( HWND32 hWnd, LPCSTR text, LPCSTR title, UINT32 type )
 {
     MSGBOX mbox;
+
+    if (!text) text="<WINE-NULL>";
+    if (!title) title="<WINE-NULL>";
     mbox.title = title;
     mbox.text  = text;
     mbox.type  = type;
@@ -221,6 +224,26 @@
 
 
 /**************************************************************************
+ *           MessageBoxEx32A   (USER32.391)
+ */
+INT32
+MessageBoxEx32A(HWND32 hWnd,LPCSTR text,LPCSTR title,UINT32 type,WORD langid) {
+    /* ignore language id for now */
+    return MessageBox32A(hWnd,text,title,type);
+}
+
+/**************************************************************************
+ *           MessageBoxEx32W   (USER32.392)
+ */
+INT32
+MessageBoxEx32W(HWND32 hWnd,LPCWSTR text,LPCWSTR title,UINT32 type,WORD langid)
+{
+    /* ignore language id for now */
+    return MessageBox32W(hWnd,text,title,type);
+}
+
+
+/**************************************************************************
  *           FatalAppExit16   (KERNEL.137)
  */
 void FatalAppExit16( UINT16 action, LPCSTR str )
@@ -247,3 +270,5 @@
     MessageBox32W( 0, str, NULL, MB_SYSTEMMODAL | MB_OK );
     TASK_KillCurrentTask(0);
 }
+
+
diff --git a/windows/queue.c b/windows/queue.c
index 83a8c7d..709fa02 100644
--- a/windows/queue.c
+++ b/windows/queue.c
@@ -11,6 +11,8 @@
 #include "task.h"
 #include "win.h"
 #include "hook.h"
+#include "thread.h"
+#include "process.h"
 #include "stddebug.h"
 #include "debug.h"
 
@@ -668,6 +670,29 @@
     return QUEUE_GetQueueTask( wndPtr->hmemTaskQ );
 }
 
+/***********************************************************************
+ *           GetWindowThreadProcessId   (USER32.312)
+ */
+DWORD
+GetWindowThreadProcessId(HWND32 hwnd,LPDWORD process) {
+    HTASK16 htask;
+    TDB	*tdb;
+
+    WND *wndPtr = WIN_FindWndPtr( hwnd );
+
+    if (!wndPtr) return 0;
+    htask=QUEUE_GetQueueTask( wndPtr->hmemTaskQ );
+    tdb = (TDB*)GlobalLock16(htask);
+    if (!tdb) return 0;
+    if (tdb->thdb) {
+    	if (process)
+		*process = (DWORD)tdb->thdb->process;
+	return (DWORD)tdb->thdb;
+    }
+    return 0;
+
+}
+
 
 /***********************************************************************
  *           SetMessageQueue   (USER.266)
diff --git a/windows/win.c b/windows/win.c
index 31ceffd..5d96ee1 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -309,7 +309,7 @@
 static void WIN_DestroyWindow( WND* wndPtr )
 {
     HWND hwnd = wndPtr->hwndSelf;
-    WND* pWnd,*pNext;
+    WND *pWnd;
 
     dprintf_win( stddeb, "WIN_DestroyWindow: %04x\n", wndPtr->hwndSelf );
 
@@ -320,10 +320,10 @@
 	
     /* free child windows */
 
-    pNext = wndPtr->child;
-    while( (pWnd = pNext) )
+    while ((pWnd = wndPtr->child))
     {
-        pNext = pWnd->next;
+        /* Make sure the linked list remains coherent */
+        wndPtr->child = pWnd->next;
         WIN_DestroyWindow( pWnd );
     }