diff --git a/win32/console.c b/win32/console.c
index 5f0b9e7a41e782bc35c831773b7bbfb21501969b..9c7d289419f9a1f1f7e0cc276166947085e33a9f 100644
--- a/win32/console.c
+++ b/win32/console.c
@@ -8,10 +8,15 @@
  */
 
 /* FIXME:
- * - completely lacks SCREENBUFFER interface
- * - No abstraction for something other than xterm
- * - Key input needs proper scancodes/virtualkeycodes
- * - win32 syncs deadlock for infinite waits
+ * - Completely lacks SCREENBUFFER interface.
+ * - No abstraction for something other than xterm.
+ * - Key input translation shouldn't use VkKeyScan and MapVirtualKey, since
+ *   they are window (USER) driver dependend.
+ * - Output sometimes is buffered (We switched off buffering by ~ICANON ?)
+ */
+/* Reference applications:
+ * -  IDA (interactive disassembler) full version 3.75. Works.
+ * -  LYNX/W32. Works mostly, some keys crash it.
  */
 
 #include <stdlib.h>
@@ -178,25 +183,36 @@ CONSOLE_string_to_IR(CONSOLE *console,unsigned char *buf,int len) {
 	if (inchar!=27) { /* no escape -> 'normal' keyboard event */
 	    ir.EventType = 1; /* Key_event */
 
-	    ir.Event.KeyEvent.bKeyDown = 1;
-	    ir.Event.KeyEvent.wRepeatCount = 0;
+	    ir.Event.KeyEvent.bKeyDown		= 1;
+	    ir.Event.KeyEvent.wRepeatCount	= 0;
 
-	    ir.Event.KeyEvent.wVirtualKeyCode = 0xdead;	/* FIXME */
-	    ir.Event.KeyEvent.wVirtualScanCode = 0xf0ad;	/* FIXME */
-	    ir.Event.KeyEvent.dwControlKeyState = 0;
+	    ir.Event.KeyEvent.dwControlKeyState	= 0;
 	    if (inchar & 0x80) {
 		ir.Event.KeyEvent.dwControlKeyState|=LEFT_ALT_PRESSED;
 		inchar &= ~0x80;
 	    }
-	    if (inchar>='A' && inchar <='Z') {
+	    ir.Event.KeyEvent.wVirtualKeyCode = VkKeyScan16(inchar);
+	    if (ir.Event.KeyEvent.wVirtualKeyCode & 0x0100)
 		ir.Event.KeyEvent.dwControlKeyState|=SHIFT_PRESSED;
-		inchar = inchar-'A'+'a';
-	    }
+	    if (ir.Event.KeyEvent.wVirtualKeyCode & 0x0200)
+		ir.Event.KeyEvent.dwControlKeyState|=LEFT_CTRL_PRESSED;
+	    if (ir.Event.KeyEvent.wVirtualKeyCode & 0x0400)
+		ir.Event.KeyEvent.dwControlKeyState|=LEFT_ALT_PRESSED;
+	    ir.Event.KeyEvent.wVirtualScanCode = MapVirtualKey16(
+	    	ir.Event.KeyEvent.wVirtualKeyCode & 0x00ff,
+		0 /* VirtualKeyCodes to ScanCode */
+	    );
 	    if (inchar=='\n') {
-		ir.Event.KeyEvent.wVirtualScanCode= 0x1c;
-		ir.Event.KeyEvent.uChar.AsciiChar = '\r';
+		ir.Event.KeyEvent.uChar.AsciiChar	= '\r';
+	    	ir.Event.KeyEvent.wVirtualKeyCode	= 0x0d;
+	    	ir.Event.KeyEvent.wVirtualScanCode	= 0x1c;
 	    } else {
 		ir.Event.KeyEvent.uChar.AsciiChar = inchar;
+		if (inchar<' ') {
+		    /* FIXME: find good values for ^X */
+		    ir.Event.KeyEvent.wVirtualKeyCode = 0xdead;
+		    ir.Event.KeyEvent.wVirtualScanCode = 0xbeef;
+		} 
 	    }
 
 	    CONSOLE_add_input_record(console,&ir);
@@ -207,12 +223,14 @@ CONSOLE_string_to_IR(CONSOLE *console,unsigned char *buf,int len) {
 	/* inchar is ESC */
 	if ((j==len-1) || (buf[j+1]!='[')) {/* add ESCape on its own */
 	    ir.EventType = 1; /* Key_event */
-	    ir.Event.KeyEvent.bKeyDown = 1;
-	    ir.Event.KeyEvent.wRepeatCount = 0;
+	    ir.Event.KeyEvent.bKeyDown		= 1;
+	    ir.Event.KeyEvent.wRepeatCount	= 0;
 
-	    ir.Event.KeyEvent.wVirtualKeyCode	= 0xdead;	/* FIXME */
+	    ir.Event.KeyEvent.wVirtualKeyCode	= VkKeyScan16(27);
+	    ir.Event.KeyEvent.wVirtualScanCode	= MapVirtualKey16(
+	    	ir.Event.KeyEvent.wVirtualKeyCode,0
+	    );
 	    ir.Event.KeyEvent.dwControlKeyState = 0;
-	    ir.Event.KeyEvent.wVirtualScanCode	= 0x01;
 	    ir.Event.KeyEvent.uChar.AsciiChar	= 27;
 	    CONSOLE_add_input_record(console,&ir);
 	    ir.Event.KeyEvent.bKeyDown = 0;
@@ -234,8 +252,8 @@ CONSOLE_string_to_IR(CONSOLE *console,unsigned char *buf,int len) {
 	    ir.Event.KeyEvent.wRepeatCount	= 0;
 	    ir.Event.KeyEvent.dwControlKeyState	= 0;
 
-	    ir.Event.KeyEvent.wVirtualKeyCode	= 0xdead;
-	    ir.Event.KeyEvent.wVirtualScanCode	= 0xbeef;
+	    ir.Event.KeyEvent.wVirtualKeyCode	= 0xad; /* FIXME */
+	    ir.Event.KeyEvent.wVirtualScanCode	= 0xad; /* FIXME */
 	    ir.Event.KeyEvent.uChar.AsciiChar	= 0;
 
 	    switch (buf[k]) {
@@ -291,6 +309,7 @@ CONSOLE_string_to_IR(CONSOLE *console,unsigned char *buf,int len) {
 	    }
 	    if (scancode) {
 		ir.Event.KeyEvent.wVirtualScanCode = scancode;
+		ir.Event.KeyEvent.wVirtualKeyCode = MapVirtualKey16(scancode,1);
 		CONSOLE_add_input_record(console,&ir);
 		ir.Event.KeyEvent.bKeyDown		= 0;
 		CONSOLE_add_input_record(console,&ir);
@@ -932,6 +951,12 @@ BOOL32 WINAPI WriteConsole32A( HANDLE32 hConsoleOutput,
 }
 
 
+#define CADD(c) 							\
+	if (bufused==curbufsize-1)					\
+	    buffer = HeapReAlloc(GetProcessHeap(),0,buffer,(curbufsize+=100));\
+	buffer[bufused++]=c;
+#define SADD(s) { char *x=s;while (*x) {CADD(*x);x++;}}
+
 /***********************************************************************
  *            WriteConsoleOutputA   (KERNEL32.732)
  */
@@ -942,7 +967,8 @@ BOOL32 WINAPI WriteConsoleOutput32A( HANDLE32 hConsoleOutput,
                                      LPSMALL_RECT lpWriteRegion)
 {
     int i,j,off=0,lastattr=-1;
-    char	buffer[20];
+    char	sbuf[20],*buffer=NULL;
+    int		bufused=0,curbufsize = 100;
     DWORD	res;
     const int colormap[8] = {
     	0,4,2,6,
@@ -955,6 +981,8 @@ BOOL32 WINAPI WriteConsoleOutput32A( HANDLE32 hConsoleOutput,
 	return FALSE;
     }
     CONSOLE_make_complex(console);
+    buffer = HeapAlloc(GetProcessHeap(),0,100);;
+    curbufsize = 100;
 
     TRACE(console,"wr: top = %d, bottom=%d, left=%d,right=%d\n",
     	lpWriteRegion->Top,
@@ -964,24 +992,27 @@ BOOL32 WINAPI WriteConsoleOutput32A( HANDLE32 hConsoleOutput,
     );
 
     for (i=lpWriteRegion->Top;i<=lpWriteRegion->Bottom;i++) {
-    	sprintf(buffer,"%c[%d;%dH",27,i+1,lpWriteRegion->Left+1);
-	WriteFile(hConsoleOutput,buffer,strlen(buffer),&res,NULL);
-	if (lastattr != lpBuffer[off].Attributes) {
+    	sprintf(sbuf,"%c[%d;%dH",27,i+1,lpWriteRegion->Left+1);
+	SADD(sbuf);
+	for (j=lpWriteRegion->Left;j<=lpWriteRegion->Right;j++) {
+	    if (lastattr!=lpBuffer[off].Attributes) {
 		lastattr = lpBuffer[off].Attributes;
-		sprintf(buffer,"%c[0;%s3%d;4%dm",
+		sprintf(sbuf,"%c[0;%s3%d;4%dm",
 			27,
 			(lastattr & FOREGROUND_INTENSITY)?"1;":"",
 			colormap[lastattr&7],
 			colormap[(lastattr&0x70)>>4]
 		);
 		/* FIXME: BACKGROUND_INTENSITY */
-		WriteFile(hConsoleOutput,buffer,strlen(buffer),&res,NULL);
+		SADD(sbuf);
+	    }
+	    CADD(lpBuffer[off].Char.AsciiChar);
+	    off++;
 	}
-	for (j=lpWriteRegion->Left;j<=lpWriteRegion->Right;j++)
-		WriteFile(hConsoleOutput,&(lpBuffer[off++].Char.AsciiChar),1,&res,NULL);
     }
-    sprintf(buffer,"%c[0m",27);
-    WriteFile(hConsoleOutput,buffer,strlen(buffer),&res,NULL);
+    sprintf(sbuf,"%c[0m",27);SADD(sbuf);
+    WriteFile(hConsoleOutput,buffer,bufused,&res,NULL);
+    HeapFree(GetProcessHeap(),0,buffer);
     K32OBJ_DecCount(&console->header);
     return TRUE;
 }
@@ -1041,7 +1072,7 @@ BOOL32 WINAPI ReadConsole32A( HANDLE32 hConsoleInput,
     	if (!console->irs[i].Event.KeyEvent.bKeyDown)
 		continue;
 	*xbuf++ = console->irs[i].Event.KeyEvent.uChar.AsciiChar; 
-	nNumberOfCharsToRead--;
+	charsread++;
     }
     CONSOLE_drain_input(console,i);
     if (lpNumberOfCharsRead)
@@ -1399,6 +1430,7 @@ BOOL32 WINAPI SetConsoleTextAttribute32(HANDLE32 hConsoleOutput,WORD wAttr)
     DWORD xlen;
     char buffer[20];
 
+    TRACE(console,"(%d,%d)\n",hConsoleOutput,wAttr);
     sprintf(buffer,"%c[0;%s3%d;4%dm",
 	27,
 	(wAttr & FOREGROUND_INTENSITY)?"1;":"",