winex11drv: Distinguish left and right keys for shift, ctrl and alt.
[wine] / dlls / winedos / int21.c
index b2aa503..3b60719 100644 (file)
@@ -20,7 +20,7 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
 #include "config.h"
@@ -28,7 +28,9 @@
 
 #include <stdarg.h>
 #include <stdio.h>
-#include <sys/stat.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
 #endif
 #include "wine/debug.h"
 #include "wine/exception.h"
 
+BOOL    WINAPI VerifyConsoleIoHandle(HANDLE);
 /*
  * Note:
  * - Most of the file related functions are wrong. NT's kernel32
  *   doesn't maintain a per drive current directory, while DOS does. 
- *   We should in fact keep track in here of those per driver
- *   directories, and use this infro while dealing with partial paths
+ *   We should in fact keep track in here of those per drive
+ *   directories, and use this info while dealing with partial paths
  *   (drive defined, but only relative paths). This could even be
  *   created as an array of CDS (there should be an entry for that in
  *   the LOL)
@@ -246,13 +249,25 @@ typedef struct
 #define EL_Serial            0x04
 #define EL_Memory            0x05
 
+/* BIOS Keyboard Scancodes */
+#define KEY_LEFT        0x4B
+#define KEY_RIGHT       0x4D
+#define KEY_UP          0x48
+#define KEY_DOWN        0x50
+#define KEY_IC          0x52 /* insert char */
+#define KEY_DC          0x53 /* delete char */
+#define KEY_BACKSPACE   0x0E
+#define KEY_HOME        0x47
+#define KEY_END         0x4F
+#define KEY_NPAGE       0x49
+#define KEY_PPAGE       0x51
+
 
 struct magic_device
 {
     WCHAR  name[10];
     HANDLE handle;
-    dev_t  dev;
-    ino_t  ino;
+    LARGE_INTEGER index;
     void (*ioctl_handler)(CONTEXT86 *);
 };
 
@@ -262,9 +277,9 @@ static void INT21_IoctlHPScanHandler( CONTEXT86 * );
 
 static struct magic_device magic_devices[] =
 {
-    { {'s','c','s','i','m','g','r','$',0}, NULL, 0, 0, INT21_IoctlScsiMgrHandler },
-    { {'e','m','m','x','x','x','x','0',0}, NULL, 0, 0, INT21_IoctlEMSHandler },
-    { {'h','p','s','c','a','n',0},         NULL, 0, 0, INT21_IoctlHPScanHandler },
+    { {'s','c','s','i','m','g','r','$',0}, NULL, { { 0, 0 } }, INT21_IoctlScsiMgrHandler },
+    { {'e','m','m','x','x','x','x','0',0}, NULL, { { 0, 0 } }, INT21_IoctlEMSHandler },
+    { {'h','p','s','c','a','n',0},         NULL, { { 0, 0 } }, INT21_IoctlHPScanHandler },
 };
 
 #define NB_MAGIC_DEVICES  (sizeof(magic_devices)/sizeof(magic_devices[0]))
@@ -469,10 +484,14 @@ static void INT21_FillCountryInformation( BYTE *buffer )
  *           INT21_FillHeap
  *
  * Initialize DOS heap.
+ *
+ * Filename Terminator Table of w2k DE NTVDM:
+ * 16 00 01 00 FF 00 00 20-02 0E 2E 22 2F 5C 5B 5D  ....... ..."/\[]
+ * 3A 7C 3C 3E 2B 3D 3B 2C-00                       :|<>+=;,
  */
 static void INT21_FillHeap( INT21_HEAP *heap )
 {
-    static const char terminators[] = "\"\\./[]:|<>+=;,";
+    static const char terminators[] = ".\"/\\[]:|<>+=;,";
     int i;
 
     /*
@@ -501,14 +520,14 @@ static void INT21_FillHeap( INT21_HEAP *heap )
      */
     heap->filename_size = 8 + strlen(terminators);
     heap->filename_illegal_size = strlen(terminators);
-    strcpy( heap->filename_illegal_table, terminators );
+    memcpy( heap->filename_illegal_table, terminators, heap->filename_illegal_size );
 
     heap->filename_reserved1 = 0x01;
-    heap->filename_lowest = 0;           /* FIXME: correct value? */
-    heap->filename_highest = 0xff;       /* FIXME: correct value? */
+    heap->filename_lowest = 0x00;
+    heap->filename_highest = 0xff;
     heap->filename_reserved2 = 0x00;    
-    heap->filename_exclude_first = 0x00; /* FIXME: correct value? */
-    heap->filename_exclude_last = 0x00;  /* FIXME: correct value? */
+    heap->filename_exclude_first = 0x00;
+    heap->filename_exclude_last = 0x20;
     heap->filename_reserved3 = 0x02;
 
     /*
@@ -666,16 +685,15 @@ static BOOL INT21_FillDrivePB( BYTE drive )
 static BOOL INT21_GetCurrentDirectory( CONTEXT86 *context, BOOL islong )
 {
     char  *buffer = CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Esi);
-    BYTE   new_drive = INT21_MapDrive( DL_reg(context) );
-    BYTE   old_drive = INT21_GetCurrentDrive();
+    BYTE   drive = INT21_MapDrive( DL_reg(context) );
     WCHAR  pathW[MAX_PATH];
     char   pathA[MAX_PATH];
     WCHAR *ptr = pathW;
 
     TRACE( "drive %d\n", DL_reg(context) );
 
-    if (new_drive == MAX_DOS_DRIVES)
-    {        
+    if (drive == MAX_DOS_DRIVES)
+    {
         SetLastError(ERROR_INVALID_DRIVE);
         return FALSE;
     }
@@ -684,13 +702,25 @@ static BOOL INT21_GetCurrentDirectory( CONTEXT86 *context, BOOL islong )
      * Grab current directory.
      */
 
-    INT21_SetCurrentDrive( new_drive );
-    if (!GetCurrentDirectoryW( MAX_PATH, pathW ))
-    {        
-        INT21_SetCurrentDrive( old_drive );
-        return FALSE;
+    if (!GetCurrentDirectoryW( MAX_PATH, pathW )) return FALSE;
+
+    if (toupperW(pathW[0]) - 'A' != drive || pathW[1] != ':')
+    {
+        /* cwd is not on the requested drive, get the environment string instead */
+
+        WCHAR env_var[4];
+
+        env_var[0] = '=';
+        env_var[1] = 'A' + drive;
+        env_var[2] = ':';
+        env_var[3] = 0;
+        if (!GetEnvironmentVariableW( env_var, pathW, MAX_PATH ))
+        {
+            /* return empty path */
+            buffer[0] = 0;
+            return TRUE;
+        }
     }
-    INT21_SetCurrentDrive( old_drive );
 
     /*
      * Convert into short format.
@@ -761,7 +791,7 @@ static BOOL INT21_GetCurrentDirectory( CONTEXT86 *context, BOOL islong )
         pathA[63] = 0;
     }
 
-    TRACE( "%c:=%s\n", 'A' + new_drive, pathA );
+    TRACE( "%c:=%s\n", 'A' + drive, pathA );
 
     strcpy( buffer, pathA );
     return TRUE;
@@ -778,6 +808,8 @@ static BOOL INT21_GetCurrentDirectory( CONTEXT86 *context, BOOL islong )
 static BOOL INT21_SetCurrentDirectory( CONTEXT86 *context )
 {
     WCHAR dirW[MAX_PATH];
+    WCHAR env_var[4];
+    DWORD attr;
     char *dirA = CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx);
     BYTE  drive = INT21_GetCurrentDrive();
     BOOL  result;
@@ -785,10 +817,23 @@ static BOOL INT21_SetCurrentDirectory( CONTEXT86 *context )
     TRACE( "SET CURRENT DIRECTORY %s\n", dirA );
 
     MultiByteToWideChar(CP_OEMCP, 0, dirA, -1, dirW, MAX_PATH);
-    result = SetCurrentDirectoryW( dirW );
+    if (!GetFullPathNameW( dirW, MAX_PATH, dirW, NULL )) return FALSE;
+
+    attr = GetFileAttributesW( dirW );
+    if (attr == INVALID_FILE_ATTRIBUTES || !(attr & FILE_ATTRIBUTE_DIRECTORY))
+    {
+        SetLastError( ERROR_PATH_NOT_FOUND );
+        return FALSE;
+    }
+
+    env_var[0] = '=';
+    env_var[1] = dirW[0];
+    env_var[2] = ':';
+    env_var[3] = 0;
+    result = SetEnvironmentVariableW( env_var, dirW );
 
-    /* This function must not change current drive. */
-    INT21_SetCurrentDrive( drive );
+    /* only set current directory if on the current drive */
+    if (result && (toupperW(dirW[0]) - 'A' == drive)) result = SetCurrentDirectoryW( dirW );
 
     return result;
 }
@@ -800,6 +845,7 @@ static BOOL INT21_SetCurrentDirectory( CONTEXT86 *context )
  */
 static HANDLE INT21_CreateMagicDeviceHandle( LPCWSTR name )
 {
+    static const WCHAR prefixW[] = {'\\','?','?','\\','u','n','i','x'};
     const char *dir = wine_get_server_dir();
     int len;
     HANDLE ret;
@@ -809,14 +855,16 @@ static HANDLE INT21_CreateMagicDeviceHandle( LPCWSTR name )
     IO_STATUS_BLOCK io;
 
     len = MultiByteToWideChar( CP_UNIXCP, 0, dir, -1, NULL, 0 );
-    nameW.Length = (len + 1 + strlenW( name )) * sizeof(WCHAR);
+    nameW.Length = sizeof(prefixW) + (len + strlenW( name )) * sizeof(WCHAR);
     nameW.MaximumLength = nameW.Length + sizeof(WCHAR);
-    if (!(nameW.Buffer = HeapAlloc( GetProcessHeap(), 0, nameW.Length )))
+    if (!(nameW.Buffer = HeapAlloc( GetProcessHeap(), 0, nameW.MaximumLength )))
     {
         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
         return 0;
     }
-    MultiByteToWideChar( CP_UNIXCP, 0, dir, -1, nameW.Buffer, len );
+    memcpy( nameW.Buffer, prefixW, sizeof(prefixW) );
+    MultiByteToWideChar( CP_UNIXCP, 0, dir, -1, nameW.Buffer + sizeof(prefixW)/sizeof(WCHAR), len );
+    len += sizeof(prefixW) / sizeof(WCHAR);
     nameW.Buffer[len-1] = '/';
     strcpyW( nameW.Buffer + len, name );
 
@@ -847,7 +895,7 @@ static HANDLE INT21_CreateMagicDeviceHandle( LPCWSTR name )
  */
 static HANDLE INT21_OpenMagicDevice( LPCWSTR name, DWORD access )
 {
-    int i;
+    unsigned int i;
     const WCHAR *p;
     HANDLE handle;
 
@@ -865,15 +913,13 @@ static HANDLE INT21_OpenMagicDevice( LPCWSTR name, DWORD access )
 
     if (!magic_devices[i].handle) /* need to open it */
     {
-        int fd;
-        struct stat st;
+        IO_STATUS_BLOCK io;
+        FILE_INTERNAL_INFORMATION info;
 
         if (!(handle = INT21_CreateMagicDeviceHandle( magic_devices[i].name ))) return 0;
-        wine_server_handle_to_fd( handle, 0, &fd, NULL, NULL );
-        fstat( fd, &st );
-        wine_server_release_fd( handle, fd );
-        magic_devices[i].dev = st.st_dev;
-        magic_devices[i].ino = st.st_ino;
+
+        NtQueryInformationFile( handle, &io, &info, sizeof(info), FileInternalInformation );
+        magic_devices[i].index = info.IndexNumber;
         magic_devices[i].handle = handle;
     }
     if (!DuplicateHandle( GetCurrentProcess(), magic_devices[i].handle,
@@ -1013,7 +1059,7 @@ static BOOL INT21_CreateFile( CONTEXT86 *context,
     {        
         WORD dosAttributes = CX_reg(context);
 
-        if (dosAttributes & FILE_ATTRIBUTE_LABEL)
+        if (dosAttributes & FA_LABEL)
         {
             /*
              * Application tried to create volume label entry.
@@ -1044,6 +1090,12 @@ static BOOL INT21_CreateFile( CONTEXT86 *context,
     {
         winHandle = CreateFileW( pathW, winAccess, winSharing, NULL,
                                  winMode, winAttributes, 0 );
+        /* DOS allows to open files on a CDROM R/W */
+        if( winHandle == INVALID_HANDLE_VALUE &&
+                GetLastError()== ERROR_WRITE_PROTECT) {
+            winHandle = CreateFileW( pathW, winAccess & ~GENERIC_WRITE,
+                    winSharing, NULL, winMode, winAttributes, 0 );
+        }
 
         if (winHandle == INVALID_HANDLE_VALUE)
             return FALSE;
@@ -1122,19 +1174,21 @@ static WORD INT21_BufferedInput( CONTEXT86 *context, BYTE *ptr, WORD capacity )
 
         if (ascii == '\r' || ascii == '\n')
         {
-            /*
-             * FIXME: What should be echoed here?
-             */
-            DOSVM_PutChar( '\r' );
-            DOSVM_PutChar( '\n' );
             ptr[length] = '\r';
             return length + 1;
         }
 
         /*
-         * FIXME: This function is supposed to support
-         *        DOS editing keys...
+         * DOS handles only backspace and KEY_LEFT
+         *        perhaps we should do more
          */
+        if (ascii == '\b' || scan == KEY_LEFT)
+        {
+            if (length==0) continue;
+            DOSVM_PutChar( '\b' );
+            length--;
+            continue;
+        }
 
         /*
          * If the buffer becomes filled to within one byte of
@@ -1331,7 +1385,7 @@ static void INT21_SequentialReadFromFCB( CONTEXT86 *context )
     struct XFCB *xfcb;
     HANDLE handle;
     DWORD record_number;
-    long position;
+    DWORD position;
     BYTE *disk_transfer_area;
     UINT bytes_read;
     BYTE AL_result;
@@ -1351,7 +1405,7 @@ static void INT21_SequentialReadFromFCB( CONTEXT86 *context )
         record_number = 128 * fcb->current_block_number + fcb->record_within_current_block;
         position = SetFilePointer(handle, record_number * fcb->logical_record_size, NULL, 0);
         if (position != record_number * fcb->logical_record_size) {
-            TRACE("seek(%d, %ld, 0) failed with %ld\n",
+            TRACE("seek(%d, %d, 0) failed with %u\n",
                   fcb->file_number, record_number * fcb->logical_record_size, position);
             AL_result = 0x01; /* end of file, no data read */
         } else {
@@ -1367,7 +1421,7 @@ static void INT21_SequentialReadFromFCB( CONTEXT86 *context )
                     AL_result = 0x03; /* end of file, partial record read */
                 } /* if */
             } else {
-                TRACE("successful read %d bytes from record %ld (position %ld) of file %d (handle %p)\n",
+                TRACE("successful read %d bytes from record %d (position %u) of file %d (handle %p)\n",
                     bytes_read, record_number, position, fcb->file_number, handle);
                 AL_result = 0x00; /* successful */
             } /* if */
@@ -1411,7 +1465,7 @@ static void INT21_SequentialWriteToFCB( CONTEXT86 *context )
     struct XFCB *xfcb;
     HANDLE handle;
     DWORD record_number;
-    long position;
+    DWORD position;
     BYTE *disk_transfer_area;
     UINT bytes_written;
     BYTE AL_result;
@@ -1431,18 +1485,18 @@ static void INT21_SequentialWriteToFCB( CONTEXT86 *context )
         record_number = 128 * fcb->current_block_number + fcb->record_within_current_block;
         position = SetFilePointer(handle, record_number * fcb->logical_record_size, NULL, 0);
         if (position != record_number * fcb->logical_record_size) {
-            TRACE("seek(%d, %ld, 0) failed with %ld\n",
+            TRACE("seek(%d, %d, 0) failed with %u\n",
                   fcb->file_number, record_number * fcb->logical_record_size, position);
             AL_result = 0x01; /* disk full */
         } else {
             disk_transfer_area = INT21_GetCurrentDTA(context);
-            bytes_written = _lwrite((HFILE) handle, disk_transfer_area, fcb->logical_record_size);
+            bytes_written = _lwrite((HFILE) handle, (LPCSTR)disk_transfer_area, fcb->logical_record_size);
             if (bytes_written != fcb->logical_record_size) {
                 TRACE("_lwrite(%d, %p, %d) failed with %d\n",
                       fcb->file_number, disk_transfer_area, fcb->logical_record_size, bytes_written);
                 AL_result = 0x01; /* disk full */
             } else {
-                TRACE("successful written %d bytes from record %ld (position %ld) of file %d (handle %p)\n",
+                TRACE("successful written %d bytes from record %d (position %u) of file %d (handle %p)\n",
                     bytes_written, record_number, position, fcb->file_number, handle);
                 AL_result = 0x00; /* successful */
             } /* if */
@@ -1487,7 +1541,7 @@ static void INT21_ReadRandomRecordFromFCB( CONTEXT86 *context )
     struct XFCB *xfcb;
     HANDLE handle;
     DWORD record_number;
-    long position;
+    DWORD position;
     BYTE *disk_transfer_area;
     UINT bytes_read;
     BYTE AL_result;
@@ -1507,7 +1561,7 @@ static void INT21_ReadRandomRecordFromFCB( CONTEXT86 *context )
     } else {
         position = SetFilePointer(handle, record_number * fcb->logical_record_size, NULL, 0);
         if (position != record_number * fcb->logical_record_size) {
-            TRACE("seek(%d, %ld, 0) failed with %ld\n",
+            TRACE("seek(%d, %d, 0) failed with %u\n",
                   fcb->file_number, record_number * fcb->logical_record_size, position);
             AL_result = 0x01; /* end of file, no data read */
         } else {
@@ -1523,7 +1577,7 @@ static void INT21_ReadRandomRecordFromFCB( CONTEXT86 *context )
                     AL_result = 0x03; /* end of file, partial record read */
                 } /* if */
             } else {
-                TRACE("successful read %d bytes from record %ld (position %ld) of file %d (handle %p)\n",
+                TRACE("successful read %d bytes from record %d (position %u) of file %d (handle %p)\n",
                     bytes_read, record_number, position, fcb->file_number, handle);
                 AL_result = 0x00; /* successful */
             } /* if */
@@ -1560,7 +1614,7 @@ static void INT21_WriteRandomRecordToFCB( CONTEXT86 *context )
     struct XFCB *xfcb;
     HANDLE handle;
     DWORD record_number;
-    long position;
+    DWORD position;
     BYTE *disk_transfer_area;
     UINT bytes_written;
     BYTE AL_result;
@@ -1580,18 +1634,18 @@ static void INT21_WriteRandomRecordToFCB( CONTEXT86 *context )
     } else {
         position = SetFilePointer(handle, record_number * fcb->logical_record_size, NULL, 0);
         if (position != record_number * fcb->logical_record_size) {
-            TRACE("seek(%d, %ld, 0) failed with %ld\n",
+            TRACE("seek(%d, %d, 0) failed with %u\n",
                   fcb->file_number, record_number * fcb->logical_record_size, position);
             AL_result = 0x01; /* disk full */
         } else {
             disk_transfer_area = INT21_GetCurrentDTA(context);
-            bytes_written = _lwrite((HFILE) handle, disk_transfer_area, fcb->logical_record_size);
+            bytes_written = _lwrite((HFILE) handle, (LPCSTR)disk_transfer_area, fcb->logical_record_size);
             if (bytes_written != fcb->logical_record_size) {
                 TRACE("_lwrite(%d, %p, %d) failed with %d\n",
                       fcb->file_number, disk_transfer_area, fcb->logical_record_size, bytes_written);
                 AL_result = 0x01; /* disk full */
             } else {
-                TRACE("successful written %d bytes from record %ld (position %ld) of file %d (handle %p)\n",
+                TRACE("successful written %d bytes from record %d (position %u) of file %d (handle %p)\n",
                     bytes_written, record_number, position, fcb->file_number, handle);
                 AL_result = 0x00; /* successful */
             } /* if */
@@ -1635,7 +1689,7 @@ static void INT21_RandomBlockReadFromFCB( CONTEXT86 *context )
     struct XFCB *xfcb;
     HANDLE handle;
     DWORD record_number;
-    long position;
+    DWORD position;
     BYTE *disk_transfer_area;
     UINT records_requested;
     UINT bytes_requested;
@@ -1659,14 +1713,14 @@ static void INT21_RandomBlockReadFromFCB( CONTEXT86 *context )
     } else {
         position = SetFilePointer(handle, record_number * fcb->logical_record_size, NULL, 0);
         if (position != record_number * fcb->logical_record_size) {
-            TRACE("seek(%d, %ld, 0) failed with %ld\n",
+            TRACE("seek(%d, %d, 0) failed with %u\n",
                   fcb->file_number, record_number * fcb->logical_record_size, position);
             records_read = 0;
             AL_result = 0x01; /* end of file, no data read */
         } else {
             disk_transfer_area = INT21_GetCurrentDTA(context);
             records_requested = CX_reg(context);
-            bytes_requested = (UINT) records_requested * fcb->logical_record_size;
+            bytes_requested = records_requested * fcb->logical_record_size;
             bytes_read = _lread((HFILE) handle, disk_transfer_area, bytes_requested);
             if (bytes_read != bytes_requested) {
                 TRACE("_lread(%d, %p, %d) failed with %d\n",
@@ -1680,7 +1734,7 @@ static void INT21_RandomBlockReadFromFCB( CONTEXT86 *context )
                     AL_result = 0x03; /* end of file, partial record read */
                 } /* if */
             } else {
-                TRACE("successful read %d bytes from record %ld (position %ld) of file %d (handle %p)\n",
+                TRACE("successful read %d bytes from record %d (position %u) of file %d (handle %p)\n",
                     bytes_read, record_number, position, fcb->file_number, handle);
                 records_read = records_requested;
                 AL_result = 0x00; /* successful */
@@ -1726,7 +1780,7 @@ static void INT21_RandomBlockWriteToFCB( CONTEXT86 *context )
     struct XFCB *xfcb;
     HANDLE handle;
     DWORD record_number;
-    long position;
+    DWORD position;
     BYTE *disk_transfer_area;
     UINT records_requested;
     UINT bytes_requested;
@@ -1750,22 +1804,22 @@ static void INT21_RandomBlockWriteToFCB( CONTEXT86 *context )
     } else {
         position = SetFilePointer(handle, record_number * fcb->logical_record_size, NULL, 0);
         if (position != record_number * fcb->logical_record_size) {
-            TRACE("seek(%d, %ld, 0) failed with %ld\n",
+            TRACE("seek(%d, %d, 0) failed with %u\n",
                   fcb->file_number, record_number * fcb->logical_record_size, position);
             records_written = 0;
             AL_result = 0x01; /* disk full */
         } else {
             disk_transfer_area = INT21_GetCurrentDTA(context);
             records_requested = CX_reg(context);
-            bytes_requested = (UINT) records_requested * fcb->logical_record_size;
-            bytes_written = _lwrite((HFILE) handle, disk_transfer_area, bytes_requested);
+            bytes_requested = records_requested * fcb->logical_record_size;
+            bytes_written = _lwrite((HFILE) handle, (LPCSTR)disk_transfer_area, bytes_requested);
             if (bytes_written != bytes_requested) {
                 TRACE("_lwrite(%d, %p, %d) failed with %d\n",
                       fcb->file_number, disk_transfer_area, bytes_requested, bytes_written);
                 records_written = bytes_written / fcb->logical_record_size;
                 AL_result = 0x01; /* disk full */
             } else {
-                TRACE("successful write %d bytes from record %ld (position %ld) of file %d (handle %p)\n",
+                TRACE("successful write %d bytes from record %d (position %u) of file %d (handle %p)\n",
                     bytes_written, record_number, position, fcb->file_number, handle);
                 records_written = records_requested;
                 AL_result = 0x00; /* successful */
@@ -1832,7 +1886,8 @@ static BOOL INT21_CreateDirectory( CONTEXT86 *context )
 static void INT21_ExtendedCountryInformation( CONTEXT86 *context )
 {
     BYTE *dataptr = CTX_SEG_OFF_TO_LIN( context, context->SegEs, context->Edi );
-
+    BYTE buffsize = CX_reg (context);
+    
     TRACE( "GET EXTENDED COUNTRY INFORMATION, subfunction %02x\n",
            AL_reg(context) );
 
@@ -1863,8 +1918,13 @@ static void INT21_ExtendedCountryInformation( CONTEXT86 *context )
         *(WORD*)(dataptr+1) = 38; /* Size of the following info */
         *(WORD*)(dataptr+3) = INT21_GetSystemCountryCode(); /* Country ID */
         *(WORD*)(dataptr+5) = GetOEMCP(); /* Code page */
-        INT21_FillCountryInformation( dataptr + 7 );
-        SET_CX( context, 41 ); /* Size of returned info */
+        /* FIXME: fill buffer partially up to buffsize bytes*/
+        if (buffsize >= 0x29){
+            INT21_FillCountryInformation( dataptr + 7 );
+            SET_CX( context, 0x29 ); /* Size of returned info */
+        }else{
+            SET_CX( context, 0x07 ); /* Size of returned info */        
+        }
         break;
         
     case 0x02: /* GET POINTER TO UPPERCASE TABLE */
@@ -1929,7 +1989,10 @@ static void INT21_ExtendedCountryInformation( CONTEXT86 *context )
     case 0x22: /* CAPITALIZE ASCIIZ STRING */
     case 0xa2: /* CAPITALIZE ASCIIZ FILENAME */
         TRACE("Convert ASCIIZ string to uppercase\n");
-        _strupr( (LPSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx) );
+        {
+            char *p = CTX_SEG_OFF_TO_LIN( context, context->SegDs, context->Edx );
+            for ( ; *p; p++) *p = toupper(*p);
+        }
         break;
 
     case 0x23: /* DETERMINE IF CHARACTER REPRESENTS YES/NO RESPONSE */
@@ -2367,6 +2430,13 @@ static void CreateBPB(int drive, BYTE *data, BOOL16 limited)
     }
 }
 
+static inline DWORD INT21_Ioctl_CylHeadSect2Lin(DWORD cyl, WORD head, WORD sec, WORD cyl_cnt,
+                                                 WORD head_cnt, WORD sec_cnt)
+{
+    DWORD res = (cyl * head_cnt*sec_cnt + head * sec_cnt + sec);
+    return res;
+}
+
 /***********************************************************************
  *           INT21_Ioctl_Block
  *
@@ -2421,7 +2491,7 @@ static void INT21_Ioctl_Block( CONTEXT86 *context )
         break;
 
     case 0x0d: /* GENERIC BLOCK DEVICE REQUEST */
-        /* Get pointer to IOCTL parameter block. */
+        /* Get pointer to IOCTL parameter block */
         dataptr = CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx);
 
         switch (CX_reg(context))
@@ -2430,13 +2500,31 @@ static void INT21_Ioctl_Block( CONTEXT86 *context )
             TRACE( "GENERIC IOCTL - Write logical device track - %c:\n",
                    'A' + drive);
             {
-                WORD head   = *(WORD *)dataptr+1;
-                WORD cyl    = *(WORD *)dataptr+3;
-                WORD sect   = *(WORD *)dataptr+5;
-                WORD nrsect = *(WORD *)dataptr+7;
-                BYTE *data  =  (BYTE *)dataptr+9; /* FIXME: is this correct? */
+                WORD head   = *(WORD *)(dataptr+1);
+                WORD cyl    = *(WORD *)(dataptr+3);
+                WORD sect   = *(WORD *)(dataptr+5);
+                WORD nrsect = *(WORD *)(dataptr+7);
+                BYTE *data  = CTX_SEG_OFF_TO_LIN(context, *(WORD *)(dataptr+11), *(WORD *)(dataptr+9));
+                WORD cyl_cnt, head_cnt, sec_cnt;
+
+                /* FIXME: we're faking some values here */
+                if (drive > 1)
+                {
+                    /* cyl_cnt = 0x300;
+                    head_cnt = 16;
+                    sec_cnt = 255; */
+                    SET_AX( context, ERROR_WRITE_FAULT );
+                    SET_CFLAG(context);
+                    break;
+                }
+                else
+                { /* floppy */
+                    cyl_cnt = 80;
+                    head_cnt = 2;
+                    sec_cnt = 18;
+                }
 
-                if (!DOSVM_RawWrite(drive, head*cyl*sect, nrsect, data, FALSE))
+                if (!DOSVM_RawWrite(drive, INT21_Ioctl_CylHeadSect2Lin(cyl, head, sect, cyl_cnt, head_cnt, sec_cnt), nrsect, data, FALSE))
                 {
                     SET_AX( context, ERROR_WRITE_FAULT );
                     SET_CFLAG(context);
@@ -2475,13 +2563,28 @@ static void INT21_Ioctl_Block( CONTEXT86 *context )
             TRACE( "GENERIC IOCTL - Read logical device track - %c:\n",
                    'A' + drive);
             {
-                WORD head   = *(WORD *)dataptr+1;
-                WORD cyl    = *(WORD *)dataptr+3;
-                WORD sect   = *(WORD *)dataptr+5;
-                WORD nrsect = *(WORD *)dataptr+7;
-                BYTE *data  =  (BYTE *)dataptr+9; /* FIXME: is this correct? */
+                WORD head   = *(WORD *)(dataptr+1);
+                WORD cyl    = *(WORD *)(dataptr+3);
+                WORD sect   = *(WORD *)(dataptr+5);
+                WORD nrsect = *(WORD *)(dataptr+7);
+                BYTE *data  = CTX_SEG_OFF_TO_LIN(context, *(WORD *)(dataptr+11), *(WORD *)(dataptr+9));
+                WORD cyl_cnt, head_cnt, sec_cnt;
+
+                /* FIXME: we're faking some values here */
+                if (drive > 1)
+                {
+                    cyl_cnt = 0x300;
+                    head_cnt = 16;
+                    sec_cnt = 255;
+                }
+                else
+                { /* floppy */
+                    cyl_cnt = 80;
+                    head_cnt = 2;
+                    sec_cnt = 18;
+                }
 
-                if (!DOSVM_RawRead(drive, head*cyl*sect, nrsect, data, FALSE))
+                if (!DOSVM_RawRead(drive, INT21_Ioctl_CylHeadSect2Lin(cyl, head, sect, cyl_cnt, head_cnt, sec_cnt), nrsect, data, FALSE))
                 {
                     SET_AX( context, ERROR_READ_FAULT );
                     SET_CFLAG(context);
@@ -2498,8 +2601,8 @@ static void INT21_Ioctl_Block( CONTEXT86 *context )
                 GetVolumeInformationW(drivespec, label, 12, &serial, NULL, NULL, fsname, 9);
                 *(WORD*)dataptr        = 0;
                 memcpy(dataptr+2,&serial,4);
-                WideCharToMultiByte(CP_OEMCP, 0, label, 11, dataptr + 6, 11, NULL, NULL);
-                WideCharToMultiByte(CP_OEMCP, 0, fsname, 8, dataptr + 17, 8, NULL, NULL);
+                WideCharToMultiByte(CP_OEMCP, 0, label, 11, (LPSTR)dataptr + 6, 11, NULL, NULL);
+                WideCharToMultiByte(CP_OEMCP, 0, fsname, 8, (LPSTR)dataptr + 17, 8, NULL, NULL);
             }
             break;
 
@@ -2516,7 +2619,7 @@ static void INT21_Ioctl_Block( CONTEXT86 *context )
             break;
 
         case 0x0872:
-            /* Trail on error implementation */
+            /* Trial and error implementation */
             SET_AX( context, drivetype == DRIVE_UNKNOWN ? 0x0f : 0x01 );
             SET_CFLAG(context);        /* Seems to be set all the time */
             break;
@@ -2534,19 +2637,10 @@ static void INT21_Ioctl_Block( CONTEXT86 *context )
         break;
 
     case 0x0f: /* SET LOGICAL DRIVE MAP */
-        {
-            WCHAR dev[3], tgt[4];
-
-            TRACE("IOCTL - SET LOGICAL DRIVE MAP for drive %s\n",
-                 INT21_DriveName( BL_reg(context)));
-            dev[0] = 'A' + drive; dev[1] = ':'; dev[2] = 0;
-            tgt[0] = 'A' + drive + 1; dev[1] = ':'; dev[2] = '\\'; dev[3] = 0;
-            if (!DefineDosDeviceW(DDD_RAW_TARGET_PATH, dev, tgt))
-           {
-               SET_CFLAG(context);
-               SET_AX( context, 0x000F );  /* invalid drive */
-           }
-        }
+        TRACE("IOCTL - SET LOGICAL DRIVE MAP for drive %s\n",
+              INT21_DriveName( BL_reg(context)));
+        /* FIXME: as of today, we don't support logical drive mapping... */
+        SET_AL( context, 0 );
         break;
 
     case 0x11: /* QUERY GENERIC IOCTL CAPABILITY */
@@ -2639,29 +2733,34 @@ static void INT21_IoctlHPScanHandler( CONTEXT86 *context )
  */
 static void INT21_Ioctl_Char( CONTEXT86 *context )
 {
-    struct stat st;
-    int status, i, fd;
+    int status;
+    int IsConsoleIOHandle = 0;
+    IO_STATUS_BLOCK io;
+    FILE_INTERNAL_INFORMATION info;
     HANDLE handle = DosFileHandleToWin32Handle(BX_reg(context));
 
-    status = wine_server_handle_to_fd( handle, 0, &fd, NULL, NULL );
+    status = NtQueryInformationFile( handle, &io, &info, sizeof(info), FileInternalInformation );
     if (status)
     {
-        SET_AX( context, RtlNtStatusToDosError(status) );
-        SET_CFLAG( context );
-        return;
-    }
-    fstat( fd, &st );
-    wine_server_release_fd( handle, fd );
-
-    for (i = 0; i < NB_MAGIC_DEVICES; i++)
-    {
-        if (!magic_devices[i].handle) continue;
-        if (magic_devices[i].dev == st.st_dev && magic_devices[i].ino == st.st_ino)
-        {
-            /* found it */
-            magic_devices[i].ioctl_handler( context );
+        if( VerifyConsoleIoHandle( handle))
+            IsConsoleIOHandle = 1;
+        else {
+            SET_AX( context, RtlNtStatusToDosError(status) );
+            SET_CFLAG( context );
             return;
         }
+    } else {
+        UINT i;
+        for (i = 0; i < NB_MAGIC_DEVICES; i++)
+        {
+            if (!magic_devices[i].handle) continue;
+            if (magic_devices[i].index.QuadPart == info.IndexNumber.QuadPart)
+            {
+                /* found it */
+                magic_devices[i].ioctl_handler( context );
+                return;
+            }
+        }
     }
 
     /* no magic device found, do default handling */
@@ -2670,7 +2769,7 @@ static void INT21_Ioctl_Char( CONTEXT86 *context )
     {
     case 0x00: /* GET DEVICE INFORMATION */
         TRACE( "IOCTL - GET DEVICE INFORMATION - %d\n", BX_reg(context) );
-        if (S_ISCHR(st.st_mode))
+        if (IsConsoleIOHandle || GetFileType(handle) == FILE_TYPE_CHAR)
         {
             /*
              * Returns attribute word in DX: 
@@ -2684,10 +2783,10 @@ static void INT21_Ioctl_Char( CONTEXT86 *context )
              *   Bit  4 - Device is special (uses int29).
              *   Bit  3 - Clock device.
              *   Bit  2 - NUL device.
-             *   Bit  1 - Standard output.
-             *   Bit  0 - Standard input.
+             *   Bit  1 - Console output device.
+             *   Bit  0 - Console input device.
              */
-            SET_DX( context, 0x80c0 /* FIXME */ );
+            SET_DX( context, IsConsoleIOHandle ? 0x80c3 : 0x80c0 /* FIXME */ );
         }
         else
         {
@@ -2860,7 +2959,7 @@ static BOOL INT21_Fat32( CONTEXT86 *context )
             source = &INT21_GetHeapPointer()->misc_dpb_list[drive];
 
             *ptr = sizeof(INT21_DPB);
-            memcpy( target, source, sizeof(INT21_DPB));
+            *target = *source;
 
             if (LOWORD(context->Esi) != 0xF1A6)
             {
@@ -3078,6 +3177,12 @@ static void INT21_LongFilename( CONTEXT86 *context )
 
             switch (CL_reg(context))
             {
+            case 0x00:  /* "truename" - Canonicalize path */
+                /* 
+                 * FIXME: This is not 100% equal to 0x01 case, 
+                 *        if you fix this, fix int21 subfunction 0x60, too.
+                 */
+
             case 0x01:  /* Get short filename or path */
                 MultiByteToWideChar(CP_OEMCP, 0, CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Esi), -1, pathW, MAX_PATH);
                 if (!GetShortPathNameW(pathW, res, 67))
@@ -3329,8 +3434,8 @@ static int INT21_GetDiskSerialNumber( CONTEXT86 *context )
 
     *(WORD *)dataptr = 0;
     memcpy(dataptr + 2, &serial, sizeof(DWORD));
-    WideCharToMultiByte(CP_OEMCP, 0, label, 11, dataptr + 6, 11, NULL, NULL);
-    strncpy(dataptr + 17, "FAT16   ", 8);
+    WideCharToMultiByte(CP_OEMCP, 0, label, 11, (LPSTR)dataptr + 6, 11, NULL, NULL);
+    memcpy(dataptr + 17, "FAT16   ", 8);
     return 1;
 }
 
@@ -3369,10 +3474,65 @@ static int INT21_GetFreeDiskSpace( CONTEXT86 *context )
 {
     DWORD cluster_sectors, sector_bytes, free_clusters, total_clusters;
     WCHAR root[] = {'A',':','\\',0};
+    const DWORD max_clusters = 0x3d83;
+    const DWORD max_sectors_per_cluster = 0x7f;
+    const DWORD max_bytes_per_sector = 0x200;
 
     root[0] += INT21_MapDrive(DL_reg(context));
     if (!GetDiskFreeSpaceW( root, &cluster_sectors, &sector_bytes,
                             &free_clusters, &total_clusters )) return 0;
+
+    /* Some old win31 apps (Lotus SmartSuite 5.1) crap out if there's too
+     * much disk space, so Windows XP seems to apply the following limits:
+     *  cluster_sectors <= 0x7f
+     *  sector size <= 0x200
+     *  clusters <= 0x3D83
+     * This means total reported space is limited to about 1GB.
+     */
+
+    /* Make sure bytes-per-sector is in [, max] */
+    while (sector_bytes > max_bytes_per_sector) {
+        sector_bytes >>= 1;
+        free_clusters <<= 1;
+        total_clusters <<= 1;
+    }
+    /* Then make sure sectors-per-cluster is in [max/2, max]. */
+    while (cluster_sectors <= max_sectors_per_cluster/2) {
+        cluster_sectors <<= 1;
+        free_clusters >>= 1;
+        total_clusters >>= 1;
+    }
+    while (cluster_sectors > max_sectors_per_cluster) {
+        cluster_sectors >>= 1;
+        free_clusters <<= 1;
+        total_clusters <<= 1;
+    }
+
+    /* scale up sectors_per_cluster to exactly max_sectors_per_cluster.
+     * We could skip this, but that would impose an artificially low
+     * limit on reported disk space.
+     * To avoid overflow, first apply a preliminary cap on sector count;
+     * this will not affect the correctness of the final result,
+     * because if the preliminary cap hits, the final one will, too.
+     */
+    if (total_clusters > 4 * max_clusters)
+        total_clusters = 4 * max_clusters;
+    if (free_clusters > 4 * max_clusters)
+        free_clusters = 4 * max_clusters;
+    if (cluster_sectors < max_sectors_per_cluster) {
+        free_clusters *= cluster_sectors;
+        free_clusters /= max_sectors_per_cluster;
+        total_clusters *= cluster_sectors;
+        total_clusters /= max_sectors_per_cluster;
+        cluster_sectors = max_sectors_per_cluster;
+    }
+
+    /* Finally, apply real cluster count cap. */
+    if (total_clusters > max_clusters)
+        total_clusters = max_clusters;
+    if (free_clusters > max_clusters)
+        free_clusters = max_clusters;
+
     SET_AX( context, cluster_sectors );
     SET_BX( context, free_clusters );
     SET_CX( context, sector_bytes );
@@ -3384,10 +3544,11 @@ static int INT21_GetFreeDiskSpace( CONTEXT86 *context )
  *             INT21_GetDriveAllocInfo
  *
  */
-static int INT21_GetDriveAllocInfo( CONTEXT86 *context, int drive )
+static int INT21_GetDriveAllocInfo( CONTEXT86 *context, BYTE drive )
 {
     INT21_DPB  *dpb;
 
+    drive = INT21_MapDrive( drive );
     if (!INT21_FillDrivePB( drive )) return 0;
     dpb = &(INT21_GetHeapPointer()->misc_dpb_list[drive]);
     SET_AL( context, dpb->cluster_sectors + 1 );
@@ -3651,7 +3812,7 @@ static const WCHAR *INT21_FindPath; /* will point to current dta->fullPath searc
  */
 static int INT21_FindFirst( CONTEXT86 *context )
 {
-    WCHAR *p;
+    WCHAR *p, *q;
     const char *path;
     FINDFILE_DTA *dta = (FINDFILE_DTA *)INT21_GetCurrentDTA(context);
     WCHAR maskW[12], pathW[MAX_PATH];
@@ -3661,6 +3822,8 @@ static int INT21_FindFirst( CONTEXT86 *context )
     MultiByteToWideChar(CP_OEMCP, 0, path, -1, pathW, MAX_PATH);
 
     p = strrchrW( pathW, '\\');
+    q = strrchrW( pathW, '/');
+    if (q>p) p = q;
     if (!p)
     {
         if (pathW[0] && pathW[1] == ':') p = pathW + 2;
@@ -3725,7 +3888,7 @@ static unsigned INT21_FindHelper(LPCWSTR fullPath, unsigned drive, unsigned coun
         RtlSecondsSince1970ToTime( (time_t)0, (LARGE_INTEGER *)&entry->ftCreationTime );
         RtlSecondsSince1970ToTime( (time_t)0, (LARGE_INTEGER *)&entry->ftLastAccessTime );
         RtlSecondsSince1970ToTime( (time_t)0, (LARGE_INTEGER *)&entry->ftLastWriteTime );
-        entry->dwFileAttributes = FILE_ATTRIBUTE_LABEL;
+        entry->dwFileAttributes = FA_LABEL;
         entry->nFileSizeHigh = entry->nFileSizeLow = 0;
         TRACE("returning %s as label\n", debugstr_w(entry->cAlternateFileName));
         return 1;
@@ -3851,7 +4014,8 @@ static int INT21_FindNextFCB( CONTEXT86 *context )
 {
     BYTE *fcb = (BYTE *)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx);
     FINDFILE_FCB *pFCB;
-    DOS_DIRENTRY_LAYOUT *pResult = (DOS_DIRENTRY_LAYOUT *)INT21_GetCurrentDTA(context);
+    LPBYTE pResult = INT21_GetCurrentDTA(context);
+    DOS_DIRENTRY_LAYOUT *ddl;
     WIN32_FIND_DATAW entry;
     BYTE attr;
     int n;
@@ -3882,26 +4046,25 @@ static int INT21_FindNextFCB( CONTEXT86 *context )
     if (*fcb == 0xff)
     {
         /* place extended FCB header before pResult if called with extended FCB */
-       *(BYTE *)pResult = 0xff;
-       (BYTE *)pResult +=6; /* leave reserved field behind */
-       *(BYTE *)pResult = entry.dwFileAttributes;
-       ((BYTE *)pResult)++;
+       *pResult = 0xff;
+        pResult += 6; /* leave reserved field behind */
+       *pResult++ = entry.dwFileAttributes;
     }
-    *(BYTE *)pResult = INT21_MapDrive( pFCB->drive ); /* DOS_DIRENTRY_LAYOUT after current drive number */
-    ((BYTE *)pResult)++;
-    pResult->fileattr = entry.dwFileAttributes;
-    pResult->cluster  = 0;  /* what else? */
-    pResult->filesize = entry.nFileSizeLow;
-    memset( pResult->reserved, 0, sizeof(pResult->reserved) );
+    *pResult++ = INT21_MapDrive( pFCB->drive ); /* DOS_DIRENTRY_LAYOUT after current drive number */
+    ddl = (DOS_DIRENTRY_LAYOUT*)pResult;
+    ddl->fileattr = entry.dwFileAttributes;
+    ddl->cluster  = 0;  /* what else? */
+    ddl->filesize = entry.nFileSizeLow;
+    memset( ddl->reserved, 0, sizeof(ddl->reserved) );
     FileTimeToDosDateTime( &entry.ftLastWriteTime,
-                           &pResult->filedate, &pResult->filetime );
+                           &ddl->filedate, &ddl->filetime );
 
     /* Convert file name to FCB format */
     if (entry.cAlternateFileName[0])
         INT21_ToDosFCBFormat( entry.cAlternateFileName, nameW );
     else
         INT21_ToDosFCBFormat( entry.cFileName, nameW );
-    WideCharToMultiByte(CP_OEMCP, 0, nameW, 11, pResult->filename, 11, NULL, NULL);
+    WideCharToMultiByte(CP_OEMCP, 0, nameW, 11, ddl->filename, 11, NULL, NULL);
     return 1;
 }
 
@@ -3994,7 +4157,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
     BOOL bSetDOSExtendedError = FALSE;
 
     TRACE( "AX=%04x BX=%04x CX=%04x DX=%04x "
-           "SI=%04x DI=%04x DS=%04x ES=%04x EFL=%08lx\n",
+           "SI=%04x DI=%04x DS=%04x ES=%04x EFL=%08x\n",
            AX_reg(context), BX_reg(context), 
            CX_reg(context), DX_reg(context),
            SI_reg(context), DI_reg(context),
@@ -4097,13 +4260,13 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
         break;
 
     case 0x09: /* WRITE STRING TO STANDARD OUTPUT */
-        TRACE("WRITE '$'-terminated string from %04lX:%04X to stdout\n",
+        TRACE("WRITE '$'-terminated string from %04X:%04X to stdout\n",
              context->SegDs, DX_reg(context) );
         {
             LPSTR data = CTX_SEG_OFF_TO_LIN( context, 
                                              context->SegDs, context->Edx );
             LPSTR p = data;
-
+            DWORD w;
             /*
              * Do NOT use strchr() to calculate the string length,
              * as '\0' is valid string content, too!
@@ -4113,7 +4276,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
 
             if (DOSVM_IsWin16())
                 WriteFile( DosFileHandleToWin32Handle(1), 
-                           data, p - data, 0, 0 );
+                           data, p - data, &w, NULL );
             else
                 for(; data != p; data++)
                     DOSVM_PutChar( *data );
@@ -4241,7 +4404,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
         break;
 
     case 0x1a: /* SET DISK TRANSFER AREA ADDRESS */
-        TRACE( "SET DISK TRANSFER AREA ADDRESS %04lX:%04X\n",
+        TRACE( "SET DISK TRANSFER AREA ADDRESS %04X:%04X\n",
                context->SegDs, DX_reg(context) );
         {
             TDB *task = GlobalLock16( GetCurrentTask() );
@@ -4510,7 +4673,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
         break;
 
     case 0x36: /* GET FREE DISK SPACE */
-       TRACE("GET FREE DISK SPACE FOR DRIVE %s\n",
+       TRACE("GET FREE DISK SPACE FOR DRIVE %s (limited to about 1GB)\n",
              INT21_DriveName( DL_reg(context) ));
         if (!INT21_GetFreeDiskSpace(context)) SET_AX( context, 0xffff );
         break;
@@ -4616,7 +4779,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
         break;
 
     case 0x3f: /* "READ" - READ FROM FILE OR DEVICE */
-        TRACE( "READ from %d to %04lX:%04X for %d bytes\n",
+        TRACE( "READ from %d to %04X:%04X for %d bytes\n",
                BX_reg(context),
                context->SegDs,
                DX_reg(context),
@@ -4631,7 +4794,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
             /* Some programs pass a count larger than the allocated buffer */
             if (DOSVM_IsWin16())
             {
-                WORD maxcount = GetSelectorLimit16( context->SegDs )
+                DWORD maxcount = GetSelectorLimit16( context->SegDs )
                     - DX_reg(context) + 1;
                 if (count > maxcount)
                     count = maxcount;
@@ -4657,11 +4820,11 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
         break;
 
     case 0x40:  /* "WRITE" - WRITE TO FILE OR DEVICE */
-        TRACE( "WRITE from %04lX:%04X to handle %d for %d byte\n",
+        TRACE( "WRITE from %04X:%04X to handle %d for %d byte\n",
                context->SegDs, DX_reg(context),
                BX_reg(context), CX_reg(context) );
         {
-            BYTE *ptr = CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx);
+            char *ptr = CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx);
 
             if (!DOSVM_IsWin16() && 
                 (BX_reg(context) == 1 || BX_reg(context) == 2))
@@ -4705,7 +4868,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
         break;
 
     case 0x42: /* "LSEEK" - SET CURRENT FILE POSITION */
-        TRACE( "LSEEK handle %d offset %ld from %s\n",
+        TRACE( "LSEEK handle %d offset %d from %s\n",
                BX_reg(context), 
                MAKELONG( DX_reg(context), CX_reg(context) ),
                (AL_reg(context) == 0) ? 
@@ -4789,7 +4952,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
                 selector = LOWORD( rv );
             }
             else
-                DOSMEM_GetBlock( bytes, &selector );
+                DOSMEM_AllocBlock( bytes, &selector );
 
             if (selector)
             {
@@ -4806,7 +4969,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
        break;
 
     case 0x49: /* FREE MEMORY */
-        TRACE( "FREE MEMORY segment %04lX\n", context->SegEs );
+        TRACE( "FREE MEMORY segment %04X\n", context->SegEs );
         {
             BOOL ok;
             
@@ -4819,7 +4982,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
                     context->SegEs = 0;
             }
             else
-                ok = DOSMEM_FreeBlock( (void*)((DWORD)context->SegEs << 4) );
+                ok = DOSMEM_FreeBlock( PTR_REAL_TO_LIN(context->SegEs, 0) );
 
             if (!ok)
             {
@@ -4831,7 +4994,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
         break;
 
     case 0x4a: /* RESIZE MEMORY BLOCK */
-        TRACE( "RESIZE MEMORY segment %04lX to %d paragraphs\n", 
+        TRACE( "RESIZE MEMORY segment %04X to %d paragraphs\n",
                context->SegEs, BX_reg(context) );
         {
             DWORD newsize = (DWORD)BX_reg(context) << 4;
@@ -4843,7 +5006,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
             }
             else
             {
-                LPVOID address = (void*)((DWORD)context->SegEs << 4);
+                LPVOID address = (void*)(context->SegEs << 4);
                 UINT blocksize = DOSMEM_ResizeBlock( address, newsize, FALSE );
 
                 RESET_CFLAG(context);
@@ -4864,7 +5027,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
 
     case 0x4b: /* "EXEC" - LOAD AND/OR EXECUTE PROGRAM */
         {
-            BYTE *program = CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx);
+            char *program = CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx);
             BYTE *paramblk = CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Ebx);
 
             TRACE( "EXEC %s\n", program );
@@ -4898,7 +5061,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
             /*
              * Exit from DPMI.
              */            
-            DWORD rv = AL_reg(context);
+            ULONG_PTR rv = AL_reg(context);
             RaiseException( EXCEPTION_VM86_INTx, 0, 1, &rv );
         }
         break;
@@ -5017,14 +5180,14 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
             switch (AL_reg(context))
             {
             case 0x00: /* LOCK */
-                TRACE( "lock handle %d offset %ld length %ld\n",
+                TRACE( "lock handle %d offset %d length %d\n",
                        BX_reg(context), offset, length );
                 if (!LockFile( handle, offset, 0, length, 0 ))
                     bSetDOSExtendedError = TRUE;
                 break;
 
             case 0x01: /* UNLOCK */
-                TRACE( "unlock handle %d offset %ld length %ld\n",
+                TRACE( "unlock handle %d offset %d length %d\n",
                        BX_reg(context), offset, length );
                 if (!UnlockFile( handle, offset, 0, length, 0 ))
                     bSetDOSExtendedError = TRUE;
@@ -5211,10 +5374,10 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
 
     /* Print error code if carry flag is set. */
     if (context->EFlags & 0x0001)
-        TRACE("failed, error %ld\n", GetLastError() );
+        TRACE("failed, error %d\n", GetLastError() );
 
     TRACE( "returning: AX=%04x BX=%04x CX=%04x DX=%04x "
-           "SI=%04x DI=%04x DS=%04x ES=%04x EFL=%08lx\n",
+           "SI=%04x DI=%04x DS=%04x ES=%04x EFL=%08x\n",
            AX_reg(context), BX_reg(context), 
            CX_reg(context), DX_reg(context), 
            SI_reg(context), DI_reg(context),