This patch is probably a little hackish but... ChangeLog: * dlls/winedos/int21.c * dlls/kernel/kernel32.spec * msdos/int21.c Move rest of code to winedos. nog.
--- msdos/int21.c.10 2002-11-27 16:56:26.000000000 +0200 +++ msdos/int21.c 2002-11-27 17:16:19.000000000 +0200 @@ -22,145 +22,12 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "config.h" -#include "wine/port.h" - -#include <time.h> -#include <fcntl.h> -#include <errno.h> -#include <stdlib.h> -#include <stdio.h> -#ifdef HAVE_SYS_FILE_H -# include <sys/file.h> -#endif -#include <string.h> -#ifdef HAVE_SYS_TIME_H -# include <sys/time.h> -#endif -#include <sys/types.h> -#ifdef HAVE_UNISTD_H -# include <unistd.h> -#endif -#ifdef HAVE_UTIME_H -# include <utime.h> -#endif -#include <ctype.h> -#include "windef.h" #include "winbase.h" -#include "winternl.h" -#include "wingdi.h" -#include "winuser.h" /* SW_NORMAL */ -#include "wine/winbase16.h" -#include "winerror.h" -#include "drive.h" -#include "file.h" -#include "callback.h" -#include "msdos.h" #include "miscemu.h" -#include "task.h" -#include "wine/unicode.h" +#include "callback.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(int21); -#if defined(__svr4__) || defined(_SCO_DS) -/* SVR4 DOESNT do locking the same way must implement properly */ -#define LOCK_EX 0 -#define LOCK_SH 1 -#define LOCK_NB 8 -#endif - - -#define DOS_GET_DRIVE(reg) ((reg) ? (reg) - 1 : DRIVE_GetCurrentDrive()) - -WORD CodePage = 437; - -extern char TempDirectory[]; - -/* Many calls translate a drive argument like this: - drive number (00h = default, 01h = A:, etc) - */ -static char drivestring[]="default"; - -char *INT21_DriveName(int drive) -{ - - if(drive >0) - { - drivestring[0]= (unsigned char)drive + '@'; - drivestring[1]=':'; - drivestring[2]=0; - } - return drivestring; -} - -static int INT21_GetDiskSerialNumber( CONTEXT86 *context ) -{ - BYTE *dataptr = CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx); - int drive = DOS_GET_DRIVE( BL_reg(context) ); - - if (!DRIVE_IsValid(drive)) - { - SetLastError( ERROR_INVALID_DRIVE ); - return 0; - } - - *(WORD *)dataptr = 0; - *(DWORD *)(dataptr + 2) = DRIVE_GetSerialNumber( drive ); - memcpy( dataptr + 6, DRIVE_GetLabel( drive ), 11 ); - strncpy(dataptr + 0x11, "FAT16 ", 8); - return 1; -} - - -static int INT21_SetDiskSerialNumber( CONTEXT86 *context ) -{ - BYTE *dataptr = CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx); - int drive = DOS_GET_DRIVE( BL_reg(context) ); - - if (!DRIVE_IsValid(drive)) - { - SetLastError( ERROR_INVALID_DRIVE ); - return 0; - } - - DRIVE_SetSerialNumber( drive, *(DWORD *)(dataptr + 2) ); - return 1; -} - - -/* microsoft's programmers should be shot for using CP/M style int21 - calls in Windows for Workgroup's winfile.exe */ - -static BOOL -INT21_networkfunc (CONTEXT86 *context) -{ - switch (AL_reg(context)) { - case 0x00: /* Get machine name. */ - { - char *dst = CTX_SEG_OFF_TO_LIN (context,context->SegDs,context->Edx); - TRACE("getting machine name to %p\n", dst); - if (gethostname (dst, 15)) - { - WARN("failed!\n"); - SetLastError( ER_NoNetwork ); - return TRUE; - } else { - int len = strlen (dst); - while (len < 15) - dst[len++] = ' '; - dst[15] = 0; - SET_CH( context, 1 ); /* Valid */ - SET_CL( context, 1 ); /* NETbios number??? */ - TRACE("returning %s\n", debugstr_an (dst, 16)); - return FALSE; - } - } - - default: - SetLastError( ER_NoNetwork ); - return TRUE; - } -} /*********************************************************************** * DOS3Call (KERNEL.102) @@ -168,185 +35,8 @@ */ void WINAPI DOS3Call( 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", - AX_reg(context), BX_reg(context), CX_reg(context), DX_reg(context), - SI_reg(context), DI_reg(context), - (WORD)context->SegDs, (WORD)context->SegEs, - context->EFlags ); - - - if (AH_reg(context) == 0x0C) /* Flush buffer and read standard input */ - { - TRACE("FLUSH BUFFER AND READ STANDARD INPUT\n"); - /* no flush here yet */ - SET_AH( context, AL_reg(context) ); - } - - if (AH_reg(context)>=0x2f) { - /* extended error is used by (at least) functions 0x2f to 0x62 */ - SetLastError(0); - } - RESET_CFLAG(context); /* Not sure if this is a good idea */ - - switch(AH_reg(context)) - { - case 0x44: /* IOCTL */ - switch (AL_reg(context)) - { - case 0x0F: /* Set logical drive mapping */ - { - int drive; - TRACE("IOCTL - SET LOGICAL DRIVE MAP for drive %s\n", - INT21_DriveName( BL_reg(context))); - drive = DOS_GET_DRIVE ( BL_reg(context) ); - if ( ! DRIVE_SetLogicalMapping ( drive, drive+1 ) ) - { - SET_CFLAG(context); - SET_AX( context, 0x000F ); /* invalid drive */ - } - break; - } - - default: - INT_BARF( context, 0x21 ); - break; - } - break; - - case 0x46: /* "DUP2", "FORCEDUP" - FORCE DUPLICATE FILE HANDLE */ - TRACE("FORCEDUP - FORCE DUPLICATE FILE HANDLE %d to %d\n", - BX_reg(context),CX_reg(context)); - bSetDOSExtendedError = (FILE_Dup2( BX_reg(context), CX_reg(context) ) == HFILE_ERROR16); - break; - - case 0x5e: - bSetDOSExtendedError = INT21_networkfunc (context); - break; - - case 0x5f: /* NETWORK */ - switch (AL_reg(context)) - { - case 0x07: /* ENABLE DRIVE */ - TRACE("ENABLE DRIVE %c:\n",(DL_reg(context)+'A')); - if (!DRIVE_Enable( DL_reg(context) )) - { - SetLastError( ERROR_INVALID_DRIVE ); - bSetDOSExtendedError = TRUE; - } - break; - - case 0x08: /* DISABLE DRIVE */ - TRACE("DISABLE DRIVE %c:\n",(DL_reg(context)+'A')); - if (!DRIVE_Disable( DL_reg(context) )) - { - SetLastError( ERROR_INVALID_DRIVE ); - bSetDOSExtendedError = TRUE; - } - break; - - default: - /* network software not installed */ - TRACE("NETWORK function AX=%04x not implemented\n",AX_reg(context)); - SetLastError( ER_NoNetwork ); - bSetDOSExtendedError = TRUE; - break; - } - break; - - case 0x65:{/* GET EXTENDED COUNTRY INFORMATION */ - BYTE *dataptr=CTX_SEG_OFF_TO_LIN(context, context->SegEs,context->Edi); - TRACE("GET EXTENDED COUNTRY INFORMATION code page %d country %d\n", - BX_reg(context), DX_reg(context)); - switch (AL_reg(context)) { - case 0x01: - TRACE("\tget general internationalization info\n"); - dataptr[0] = 0x1; - *(WORD*)(dataptr+1) = 41; - *(WORD*)(dataptr+3) = GetSystemDefaultLangID(); - *(WORD*)(dataptr+5) = CodePage; - *(DWORD*)(dataptr+0x19) = 0; /* FIXME: ptr to case map routine */ - break; - case 0x06: - TRACE("\tget pointer to collating sequence table\n"); - dataptr[0] = 0x06; - *(DWORD*)(dataptr+1) = MAKELONG(DOSMEM_CollateTable & 0xFFFF,DOSMEM_AllocSelector(DOSMEM_CollateTable>>16)); - SET_CX( context, 258 );/*FIXME: size of table?*/ - break; - case 0x20: - TRACE("\tConvert char to uppercase\n"); - SET_DL( context, toupper(DL_reg(context)) ); - break; - case 0x21: - TRACE("\tconvert string to uppercase with length\n"); - { - char *ptr = (char *)CTX_SEG_OFF_TO_LIN(context,context->SegDs,context->Edx); - WORD len = CX_reg(context); - while (len--) { *ptr = toupper(*ptr); ptr++; } - } - break; - case 0x22: - TRACE("\tConvert ASCIIZ string to uppercase\n"); - _strupr( (LPSTR)CTX_SEG_OFF_TO_LIN(context,context->SegDs,context->Edx) ); - break; - default: - TRACE("\tunimplemented function %d\n",AL_reg(context)); - INT_BARF( context, 0x21 ); - SET_CFLAG(context); - break; - } - break; - } - - case 0x67: /* SET HANDLE COUNT */ - TRACE("SET HANDLE COUNT to %d\n",BX_reg(context) ); - SetHandleCount16( BX_reg(context) ); - if (GetLastError()) bSetDOSExtendedError = TRUE; - break; - - case 0x69: /* DISK SERIAL NUMBER */ - switch (AL_reg(context)) - { - case 0x00: - TRACE("GET DISK SERIAL NUMBER for drive %s\n", - INT21_DriveName(BL_reg(context))); - if (!INT21_GetDiskSerialNumber(context)) bSetDOSExtendedError = TRUE; - else SET_AX( context, 0 ); - break; - - case 0x01: - TRACE("SET DISK SERIAL NUMBER for drive %s\n", - INT21_DriveName(BL_reg(context))); - if (!INT21_SetDiskSerialNumber(context)) bSetDOSExtendedError = TRUE; - else SET_AX( context, 1 ); - break; - } - break; - - default: - INT_BARF( context, 0x21 ); - break; - - } /* END OF SWITCH */ - - if( bSetDOSExtendedError ) /* set general error condition */ - { - SET_AX( context, GetLastError() ); - SET_CFLAG(context); - } - - if ((context->EFlags & 0x0001)) - TRACE("failed, error %ld\n", GetLastError() ); - - TRACE("returning: AX=%04x BX=%04x CX=%04x DX=%04x " - "SI=%04x DI=%04x DS=%04x ES=%04x EFL=%08lx\n", - AX_reg(context), BX_reg(context), CX_reg(context), - DX_reg(context), SI_reg(context), DI_reg(context), - (WORD)context->SegDs, (WORD)context->SegEs, - context->EFlags); + if(Dosvm.CallBuiltinHandler || DPMI_LoadDosSystem()) + Dosvm.CallBuiltinHandler(context, 0x21); } /*********************************************************************** --- dlls/winedos/int21.c.10 2002-11-27 16:56:18.000000000 +0200 +++ dlls/winedos/int21.c 2002-11-27 17:21:24.000000000 +0200 @@ -36,9 +36,14 @@ #include "msdos.h" #include "file.h" #include "task.h" +#include "drive.h" /* DRIVE_* */ #include "wine/unicode.h" #include "wine/debug.h" +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + WINE_DEFAULT_DEBUG_CHANNEL(int21); /* Define the drive parameter block, as used by int21/1F @@ -1328,6 +1333,19 @@ SET_AL(context, 0); /* drive has no mapping - FIXME: may be wrong */ break; + case 0x0f: /* Set logical drive mapping */ + { + int drive; + TRACE("IOCTL - SET LOGICAL DRIVE MAP for drive %s\n", + INT21_DriveName(BL_reg(context))); + drive = GetDosDrive(BL_reg(context)); + if(!DRIVE_SetLogicalMapping(drive, drive + 1)) { + SET_CFLAG(context); + SET_AX(context, 0x000F); /* invalid drive */ + } + break; + } + case 0x52: /* DR-DOS version */ /* This is not DR-DOS */ @@ -1339,13 +1357,21 @@ break; default: - DOS3Call(context); + INT_BARF(context, 0x21); break; } } /*********************************************************************** - * INT21_GetExtendedError + * INT21_GetExtendedError [internal] + * + * Parses the win32 Errors into dos extended errors. + * + * PARAMS: + * context [I]: Pointer to structure holding registers. + * + * RETURNS: + * Nothing. */ static void INT21_GetExtendedError(CONTEXT86 *context) { @@ -1459,9 +1485,19 @@ } /*********************************************************************** - * DOSVM_Int21Handler (WINEDOS16.133) + * DOSVM_Int21Handler [WINEDOS16.133] + * + * Int 21h handler. + * + * PARAMS: + * context [I]: Pointer to structure holding registers. + * + * REUTRNS: + * Nothing. * - * int 21h handler. Most calls are passed directly to DOS3Call. + * NOTES: + * Microsoft's programmers should be shot for using CP/M style int21 calls in + * Windows for Workgroup's winfile.exe */ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context ) { @@ -2056,6 +2092,13 @@ } break; + case 0x46: /* "DUP2", "FORCEDUP" - FORCE DUPLICATE FILE HANDLE */ + TRACE("FORCEDUP - FORCE DUPLICATE FILE HANDLE %d to %d\n", + BX_reg(context), CX_reg(context)); + bSetDOSExtendedError = (FILE_Dup2(BX_reg(context), CX_reg(context)) == + HFILE_ERROR16); + break; + case 0x47: /* "CWD" - GET CURRENT DIRECTORY */ TRACE("CWD - GET CURRENT DIRECTORY for %s drive\n", INT21_DriveName(DL_reg(context))); @@ -2330,6 +2373,61 @@ bSetDOSExtendedError = TRUE; break; + case 0x5e: /* NETWORK FUNCTION */ + switch(AL_reg(context)) { + case 0x00: /* Get machine name. */ + { + char *dst = CTX_SEG_OFF_TO_LIN(context, context->SegDs, + context->Edx); + TRACE("getting machine name to %p\n", dst); + if(gethostname(dst, 15)) { + WARN("failed!\n"); + SetLastError(ER_NoNetwork); + bSetDOSExtendedError = TRUE; + break; + } else { + int len = strlen(dst); + while(len < 15) + dst[len++] = ' '; + dst[15] = 0; + SET_CH(context, 1); /* Valid */ + SET_CL(context, 1); /* NETbios number??? */ + TRACE("returning %s\n", debugstr_an (dst, 16)); + break; + } + } + default: + FIXME("Unknown network function: %02x\n", AL_reg(context)); + SetLastError(ER_NoNetwork); + bSetDOSExtendedError = TRUE; + } + break; + + case 0x5f: /* NETWORK */ + switch (AL_reg(context)) + { + case 0x07: /* ENABLE DRIVE */ + TRACE("ENABLE DRIVE %c:\n",(DL_reg(context)+'A')); + if(!DRIVE_Enable(DL_reg(context))) { + SetLastError(ERROR_INVALID_DRIVE); + bSetDOSExtendedError = TRUE; + } + break; + + case 0x08: /* DISABLE DRIVE */ + TRACE("DISABLE DRIVE %c:\n", (DL_reg(context) + 'A')); + if(!DRIVE_Disable(DL_reg(context))) { + SetLastError(ERROR_INVALID_DRIVE); + bSetDOSExtendedError = TRUE; + } + break; + + default: + /* network software not installed */ + FIXME("NETWORK function AX=%04x not implemented\n",AX_reg(context)); bSetDOSExtendedError = TRUE; + break; + } + break; case 0x60: /* "TRUENAME" - CANONICALIZE FILENAME OR PATH */ TRACE("TRUENAME %s\n", @@ -2364,6 +2462,56 @@ SET_CFLAG(context); break; + case 0x65: /* GET EXTENDED COUNTRY INFORMATION */ + { + BYTE *dataptr = CTX_SEG_OFF_TO_LIN(context, context->SegEs, + context->Edi); + TRACE("GET EXTENDED COUNTRY INFORMATION code page %d country %d\n", + BX_reg(context), DX_reg(context)); + switch (AL_reg(context)) { + case 0x01: + TRACE("\tget general internationalization info\n"); + dataptr[0] = 0x1; + *(WORD*)(dataptr+1) = 41; + *(WORD*)(dataptr+3) = GetSystemDefaultLangID(); + *(WORD*)(dataptr+5) = CodePage; + *(DWORD*)(dataptr+0x19) = 0; /* FIXME: ptr to case map routine */ + break; + case 0x06: + TRACE("\tget pointer to collating sequence table\n"); + dataptr[0] = 0x06; + *(DWORD*)(dataptr+1) = + MAKELONG(*DOSMEM_GetCollateTable() & 0xFFFF, + DOSMEM_AllocSelector(*DOSMEM_GetCollateTable() >> 16)); SET_CX(context, 258);/*FIXME: size of table?*/ + break; + case 0x20: + TRACE("\tConvert char to uppercase\n"); + SET_DL(context, toupper(DL_reg(context))); + break; + case 0x21: + TRACE("\tconvert string to uppercase with length\n"); + { + char *ptr = (char *)CTX_SEG_OFF_TO_LIN(context, + context->SegDs, + context->Edx); + WORD len = CX_reg(context); + while (len--) { *ptr = toupper(*ptr); ptr++; } + } + break; + case 0x22: + TRACE("\tConvert ASCIIZ string to uppercase\n"); + _strupr((LPSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, + context->Edx)); + break; + default: + TRACE("\tunimplemented function %d\n",AL_reg(context)); + INT_BARF(context, 0x21); + SET_CFLAG(context); + break; + } + break; + } + case 0x66: /* GLOBAL CODE PAGE TABLE */ switch (AL_reg(context)) { @@ -2382,12 +2530,77 @@ } break; + case 0x67: /* SET HANDLE COUNT */ + TRACE("SET HANDLE COUNT to %d\n", BX_reg(context)); + SetHandleCount(BX_reg(context)); + if(GetLastError()) bSetDOSExtendedError = TRUE; + break; + case 0x68: /* "FFLUSH" - COMMIT FILE */ TRACE("FFLUSH/COMMIT handle %d\n",BX_reg(context)); bSetDOSExtendedError = (!FlushFileBuffers(DosFileHandleToWin32Handle( BX_reg(context)))); break; + case 0x69: /* DISK SERIAL NUMBER */ + switch (AL_reg(context)) { + case 0x00: /* GET DISK SERIAL NUMBER */ + { + BYTE *dataptr = CTX_SEG_OFF_TO_LIN(context, context->SegDs, + context->Edx); + int drive = GetDosDrive(BL_reg(context)); + char driveA[] = "A:\\"; + char VolLabel[12]; + char FileSys[9]; + + TRACE("GET DISK SERIAL NUMBER for drive %s\n", + INT21_DriveName(BL_reg(context))); + + *driveA += drive; + + if(!IsDriveValid(drive)) { + SetLastError(ERROR_INVALID_DRIVE); + bSetDOSExtendedError = TRUE; + break; + } + + GetVolumeInformationA(driveA, VolLabel, 12, + (DWORD *)(dataptr + 2), NULL, NULL, + FileSys, 9); + + *(WORD *)dataptr = 0; + memcpy(dataptr + 6, VolLabel, 11); + strncpy(dataptr + 0x11, FileSys, 8); + + TRACE("Disk serial number: %ld, Label: %s, FileSys: %s\n", + *(DWORD *)(dataptr + 2), VolLabel, FileSys); + + SET_AX(context, 0); + } + break; + + case 0x01: /* SET DISK SERIAL NUMBER */ + { + BYTE *dataptr = CTX_SEG_OFF_TO_LIN(context, context->SegDs, + context->Edx); + int drive = GetDosDrive(BL_reg(context)); + + if(!IsDriveValid(drive)) { + SetLastError(ERROR_INVALID_DRIVE); + bSetDOSExtendedError = TRUE; + break; + } + + DRIVE_SetSerialNumber(drive, *(DWORD *)(dataptr + 2)); + SET_AX(context, 1); + } + break; + + default: + INT_BARF(context, 0x21); + } + break; + case 0x6a: /* COMMIT FILE */ TRACE("FFLUSH/COMMIT handle %d\n",BX_reg(context)); bSetDOSExtendedError = (!FlushFileBuffers(DosFileHandleToWin32Handle( @@ -2707,7 +2920,7 @@ break; default: - DOS3Call( context ); + INT_BARF(context, 0x21); } if(bSetDOSExtendedError) /* set general error condition */ --- ../readwritewine/msdos/dosmem.c 2002-11-21 09:37:06.000000000 +0200 +++ msdos/dosmem.c 2002-11-27 17:23:20.000000000 +0200 @@ -394,6 +394,16 @@ } /*********************************************************************** + * DOSMEM_GetCollateTable + * + * Returns a pointer to the collate table + */ +DWORD *DOSMEM_GetCollateTable() +{ + return &DOSMEM_CollateTable; +} + +/*********************************************************************** * DOSMEM_InitCollateTable * * Initialises the collate table (character sorting, language dependent) --- include/miscemu.h.0 2002-11-27 17:23:30.000000000 +0200 +++ include/miscemu.h 2002-11-27 17:24:22.000000000 +0200 @@ -180,6 +180,7 @@ extern void DOSMEM_Tick(WORD timer); extern WORD DOSMEM_AllocSelector(WORD); extern LPVOID DOSMEM_GetBlock(UINT size, WORD* p); +extern DWORD *DOSMEM_GetCollateTable(); extern BOOL DOSMEM_FreeBlock(void* ptr); extern LPVOID DOSMEM_ResizeBlock(void* ptr, UINT size, WORD* p); extern UINT DOSMEM_Available(void); --- dlls/kernel/kernel32.spec.0 2002-11-27 18:29:36.000000000 +0200 +++ dlls/kernel/kernel32.spec 2002-11-27 18:30:14.000000000 +0200 @@ -1048,16 +1048,22 @@ # Wine dll separation hacks, these will go away, don't use them # @ cdecl DOSFS_GetDeviceByHandle(long) DOSFS_GetDeviceByHandle +@ cdecl DRIVE_Enable(long) DRIVE_Enable +@ cdecl DRIVE_Disable(long) DRIVE_Disable +@ cdecl DRIVE_SetLogicalMapping(long long) DRIVE_SetLogicalMapping +@ cdecl DRIVE_SetSerialNumber(long long) DRIVE_SetSerialNumber @ cdecl DOSMEM_AllocSelector(long) DOSMEM_AllocSelector @ cdecl DOSMEM_Available() DOSMEM_Available @ cdecl DOSMEM_FreeBlock(ptr) DOSMEM_FreeBlock @ cdecl DOSMEM_GetBlock(long ptr) DOSMEM_GetBlock +@ cdecl DOSMEM_GetCollateTable() DOSMEM_GetCollateTable @ cdecl DOSMEM_GetDPMISegments() DOSMEM_GetDPMISegments @ cdecl DOSMEM_Init(long) DOSMEM_Init @ cdecl DOSMEM_MapDosToLinear(long) DOSMEM_MapDosToLinear @ cdecl DOSMEM_MapLinearToDos(ptr) DOSMEM_MapLinearToDos @ cdecl DOSMEM_ResizeBlock(ptr long ptr) DOSMEM_ResizeBlock @ cdecl DRIVE_OpenDevice(long long) DRIVE_OpenDevice +@ cdecl FILE_Dup2(long long) FILE_Dup2 @ cdecl LOCAL_Alloc(long long long) LOCAL_Alloc @ cdecl LOCAL_Compact(long long long) LOCAL_Compact @ cdecl LOCAL_CountFree(long) LOCAL_CountFree