Tue Mar 1 11:30:21 1994 Bob Amstadt (bob@pooh) * [Configure] [*/Imakefile] Created configure script to handle different types of Wine builds. * [Configure] [tools/build.c] [if1632/Imakefile] [Wine.tmpl] Added ability to compile Wine on systems with 14-char filename limit. * [if1632/relay.c] [include/options.h] [misc/main.c] Added -relaydbg option to command line if DEBUG_RELAY is defined. * [loader/selector.c] Fixed bug in GetEntryDLLName() that caused Wine to seg fault. * [memory/heap.c] Fixed LocalInit() to work correctly. * [misc/user.c] Added code to call loaded DLLs' initialization routines. Tue Mar 1 01:01:17 MET 1994 julliard@di.epfl.ch (Alexandre Julliard) * [windows/dce.c] Added clipping of child windows by their parent's client area. * [windows/nonclient.c] Bug fix in NC_DoNCPaint(). * [windows/painting.c] Bug fix in RedrawWindow(). Feb 27, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte) * [mem/atom.c] Bug fix again in ATOM_DeleteAtom() : change LocalFree() by USER_HEAP_FREE(). (Previous patch done Feb 13th had been lost) * [controls/scroll.c] Move bitmaps loading in AllocScrollBar() instead of in WM_CREATE. * [windows/class.c] (sorry Alex ...) There was no bug there "in RegisterClass() : WNDCLASS->lpszClassName was reset to NULL." ^^^^^ * [misc/clipboard.c] --- New File --- New function EnumClipboardFormats(). New function OpenClipboard(). New function CloseClipboard(). New function EmptyClipboard(). New function GetClipboardOwner(). New function GetClipboardViewer(). New function CountClipboardFormats(). New function IsClipboardFormatAvailable(). New function OpenClipboard(). New function GetClipboardData(). New function SetClipboardViewer(). New function EnumClipboardFormats(). New function RegisterClipboardFormat(). New function ChangeClipboardChain(). New function SetClipboardData(). New function GetOpenClipboardWindow(). New function GetPriorityClipboardFormat(). New function GetClipboardFormatName(). Tue Mar 1 20:15:45 1994 Erik Bos <erik@trashcan.hacktic.nl> * [misc/comm.c] bugfix in OpenComm(). Tue Feb 22 18:04:02 1994 Jeffrey Hsu <hsu@freefall.cdrom.com> * [include/winsock.h] The sockproto struct is already defined in <sys/socket.h> * [misc/winsock.c] Need to include <netinet/in.h> for struct in-addr. Use sys_errlist[] instead of strerror[]. *[toolkit/heap.c] ANSI C specifies that the malloc functions are defined in stdlib.h, so we don't need to include malloc.h. *[loader/ldtlib.c] Print informative error message about probable cause of i386_set_ldt() failure and then exit. *[Imakefile] For systems that don't use gmake by default, set the MAKE variable to gmake and propagate it on recursive makes. Take out -li386 for FreeBSD systems and define __FreeBSD__ so Wine can be built with the FreeBSD 1.0.2 compiler. Tue Feb 22 02:52:19 EST 1994 jrichard@cs.uml.edu (John Richardson) * [objects/bitblt.c] Added in three functions to do stretching and compression for WHITEONBLACK, BLACKONWHITE, and color copies. Tue Feb 22 15:01:31 EST 1994 jrichard@cs.uml.edu (John Richardson) * [windows/graphics.c] Added FloodFill and FloodFill_rec. FloodFill_rec is pretty inefficent, but should suffice for now. * [include/windows.h] Changed the x,y paramaters for the FloodFill prototype from ints to shorts Tue Feb 22 00:58:28 MET 1994 julliard@di.epfl.ch (Alexandre Julliard) * [windows/widgets.c] Added desktop window class. * [windows/painting.c] Bug fix in RedrawWindow(). Implemented ExcludeUpdateRgn(). * [windows/win.c] [windows/winpos.c] Implemented desktop window. * [controls/desktop.c] Preliminary desktop window procedure. Feb 20, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte) * [controls/menu.c] New function LoadMenuIndirect(). New function GetMenuCheckMarkDimensions(). * [if1632/user.spec] Entry for DefDlgProc(). * [windows/class.c] Fix bug in RegisterClass() : WNDCLASS->lpszMenuName was reset to NULL. * [windows/win.c] In CreateWindowEx(), if hMenu == 0 then use wndclass->lpszMenuName to load Menu from resource; Mon Feb 21 22:38:28 1994 Erik Bos (erik@trashcan.hacktic.nl) * [loader/library.c] [loader/wine.c] Fixed runing DLL's as main executable problem. * [misc/dos_fs.c] Added wildcard support in DOS_readdir(). * [misc/winsocket.c] Added proper error handling of BSD winsocket functions. * [miscemu/int21.c] KERNEL_DOS3Call renamed to DOS3Call and modified to use do_int21(). * [main/main.c] Added functions for GetVersion, GetWinFlags and GetTimerResolution for libwine.a, SystemParametersInfo() partly implemented. Tue Feb 22 19:00:02 1994 Miguel de Icaza (miguel@xochitl.nuclecu.unam.mx) * [toolkit/winmain.c] Added _WinMain function. Setups the library (calls USER_InitApp). * [toolkit/sup.c] Added load_mz_header, load_ne_header, load_type_info and load_name_info functions. * [toolkit/heap.c] Code cleanup. * [misc/user.c] Moved from loader/misc.c. I hope to put back all the loader functions in the ~loader subdirectory in the future. CUrrently is needed since it has USER_InitApp. * [misc/resource.c] Since WineLib will probably need DLLs (currently it needs Sysres.dll). WineLib will be using much code of the loader again. So I removed some ifdefs that were used by WineLib. Added load_typeinfo and load_nameinfo (and the corresponding functions in [toolkit/sup.c] Added integer convertion functions in the needed places. Added very ugly patch (includes wine.c). In the next release I plan to move back all the loader routines to ~/loader. In the meantime I needed this patch. It doesn't affect any of the emulator code (its ifdefed for WineLib). * [misc/main.c] Cleaned up call to WinMain (now uses [toolkit/winmain.c] Ifdefed argument number checking when compiling the library. * [loader/wine.c] Modified to use load_(mz|ne)_header instead of doing a direct read. When compiling the emulator it still uses the direct read for performance. * [include/wine.h] Prototypes for loading routines. * [include/class.h] Added WINE_PACKED macro instead of __attribute__ ((packed)) * [include/arch.h] Macros for converting integers (Little endian to big-endian). Needed in the Sun to allow loading of DLL files. Mon Feb 14 23:48:09 MET 1994 julliard@di.epfl.ch (Alexandre Julliard) * [windows/clipping.c] Moved everything into windows/painting.c and removed this file. * [windows/message.c] Removed calls to memmove() in MSG_RemoveMsg(). * [windows/nonclient.c] Added WM_GETMINMAXINFO support for window resizing. * [windows/painting.c] Implemented RedrawWindow(). * [windows/scroll.c] Bug fix in ScrollWindowEx(). * [windows/win.c] Moved UpdateWindow() to windows/painting.c. Fri Feb 11 12:41:28 1994 Erik Bos (erik@trashcan.hacktic.nl) * [loader/wine.c] [misc/dos_fs.c] getenv() eq NULL bugfixes. * [misc/comm.c] cfmakeraw changed for SunOS. Feb 13, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte) * [mem/atom.c] Bug fix in ATOM_DeleteAtom() : change LocalFree() by USER_HEAP_FREE(). * [misc/message.c] New function FatalAppExit(). * [objects/font.c] New empty stub SetMapperFlags(). * [controls/menu.c] Better CheckMark & other bitmaps placement. * [windows/graphics.c] New function RoundRect() : calc.exe now working... Tue Feb 15 14:29:37 1994 John Richardson * [objects/bitblt.c] Fixed StretchBlt so it works quicker and faster. It still doesn't use the StretchMode bits for bitmap compression, but that will come soon. Mon Feb 14 13:21:04 1994 Miguel de Icaza (miguel@roxanne.nuclecu.unam.mx) * [include/windows.h,dialog.h,gdi.h] Changed __atribute__ ((packed)) for WINE_PACKED. When compiling the library this is defined as nothing. This gets rid with all the problems compiling under SunOS. Also * [windows/utility.c] Added DebugPrintString. * [toolkit/sup.c] Added hSysRes = 1 definition to resolve externals. Added CallLineDDAProc function (toolkit version). Added toy, and hi ineficient memmove until code in message.c get rewritten. * [objects/gdiobj.c] Ifdefed linux/emulator-dependent code to allow compilation of WineLib. * [misc/winsocket.c] Added ifdef to allow compilation under SunOS. * [misc/resource.c] When compiling the library, the resource file is expected to be in a file called $argv[0].Res. Also the information of the resource is expected to be at offset 0 of the .Res file. * [misc/main.c] Call WinMain with arguments if compiling WineLib. Call shutdown functions (Comm_DeInit, DOS_DeInitFS). Call sync_profiles to preserve changes to .INI files. * [misc/comm.c,dos_fs.c] removed call to atexit(Comm_DeInit) removed call to atexit(DOS_DeInitFS) Shutdown functions are now called from the return of WinMain * removed memorylib subdirectory * moved memory/atom.c to misc/atom.c moved memorylib/heap.c to toolkit/heap.c * [loader/wine.c] Moved DebugPrintString to windows/utility.c * [include/winsock.h] Define SO_DONTLINGER only if it has not been previously defined. * [include/windows.h] added definition for DLGPROC. added definition for LMEM_WINE_ALIGN and other LMEM_* constants. When compiling WineLib WNDPROC is defined with all the parameters to avoid compilation problems. * [include/user.h] When compiling WineLib USER_HEAP_(ALLOC|REALLOC|ADDR|FREE) the calls are translated to the library allocation routines. * [include/gdi.h,user.h] When compiling WineLib GDI_HEAP_(ALLOC|ADDR|FREE) the calls are translated to the library allocation routines. * [include/atom.h] Defined LocalAlign. When compiling the emulator it's translated as a call to LocalAlloc (the original code), when compiling WineLib as a call to LocalAlloc with a WINE-flag called LMEM_WINE_ALIGN (atom.c needs aligned data on a 4 byte boundary). * [misc/file.c] Renamed KERNEL_* functions and fixed prototypes. * [if1632/kernel.spec] Renamed KERNEL_* functions in order to be used by applications using Wine as a library (OpeFile, _lclose, _lread, _lcreate, _llseek, _lopen, _lwrite). * [Makefile] Create library instead of executable when building target libwine.a Tue Feb 8 13:52:11 1994 Miguel de Icaza (miguel@roxanne) * [Makefiles] Use $(CC) instead of cc. Added libwine target. * [include/prototypes] #ifdefed section for WineLib * moved loader/cursor.c to misc/cursor.c moved loader/resource.c to misc/resource.c moved misc/emulate.c to miscemu/emulate.c moved misc/int1a.c to miscemu/int1a.c moved misc/int21.c to miscemu/int21.c moved misc/kernel.c to miscemu/kernel.c moved misc/user.c to miscemu/user.c * [memorylib/heap.c] Heap management for WineLib * [misc/comm.c] Modified to allow compilation under SunOS (#include errno, SunOS doesn't have atexit ()). * [misc/dos_fs.c] Modified to allow compilation under SunOS (#include vfs.h) * [misc/file.c] Modified to allow compilation under SunOS (OPEN_MAX constant, #include unistd.h) * [objects/palette.c] Modified to allow compilation under SunOS (#include limits) * [toolkit/sup.c] WineLib version of CallWindowProc. * [windows/event.c] Typedef XPointer under X11R4 (OpenWindows). * [windows/win.c] When compiling WineLib, use direct callbacks instead of the windows supplied callbacks. Mon Feb 7 22:37:34 MET 1994 julliard@di.epfl.ch (Alexandre Julliard) * [loader/cursor.c] New function CURSOR_SetWinCursor(), for internal use, to set the cursor of a specific window more reliably than with SetCursor(). * [windows/nonclient.c] Better window management. Moving and resizing from the system menu should work now. Added scroll-bar mouse tracking. * [windows/win.c] Moved scroll-bar creation and destruction to defwnd.c. Feb 5, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte) * [windows/nonclient.c] Call to StdDrawMenuBar() during NC's drawing. New NC_TrackMouseMenuBar() function which call MenuButtonDown(), MenuButtonUp() & MenuMouseMove(). * [controls/menu.c] New ChangeMenu() function. Remove permanently old Xt menu code. Make common functions MenuButtonDown(), MenuButtonUp() & MenuMouseMove() for both popups & menubar. * [controls/combo.c] Paint OBM_COMBO directly in combo client. * [controls/listbox.c] Fix bug in multicolumns calculations. * [controls/Makefile] Remove rules for old file 'caption.c'. * [misc/kernel.c] Remove empty stub GetModuleFileName(). * [loader/library.c] New GetModuleHandle() function. New GetModuleUsage() function. New GetModuleFileName() function. * [loader/resource.c] Try to find the bug a missing menu loading ... Not found yet ! * [windows/win.c] Remove old menubar creation. Thu Feb 3 22:30:11 1994 Erik Bos (erik@trashcan.hacktic.nl) * [misc/winsocket.c] More functions added. * [if1632/winsock.spec] [misc/winsocket.c] Added John Brezak's winsock.dll stuff.
1201 lines
25 KiB
C
1201 lines
25 KiB
C
#include <time.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#ifndef __STDC__
|
|
#include <malloc.h>
|
|
#endif
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/stat.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
#include <utime.h>
|
|
|
|
#include "prototypes.h"
|
|
#include "regfunc.h"
|
|
#include "windows.h"
|
|
#include "wine.h"
|
|
#include "int21.h"
|
|
|
|
static char Copyright[] = "copyright Erik Bos, 1993";
|
|
|
|
WORD ExtendedError, CodePage = 437;
|
|
BYTE ErrorClass, Action, ErrorLocus;
|
|
|
|
extern char TempDirectory[];
|
|
|
|
void Error(int e, int class, int el)
|
|
{
|
|
ExtendedError = e;
|
|
ErrorClass = class;
|
|
Action = SA_Ask4Retry;
|
|
ErrorLocus = el;
|
|
}
|
|
|
|
void GetFreeDiskSpace(struct sigcontext_struct *context)
|
|
{
|
|
int drive;
|
|
long size,available;
|
|
|
|
if (!(EDX & 0xffL))
|
|
drive = DOS_GetDefaultDrive();
|
|
else
|
|
drive = (EDX & 0xffL) - 1;
|
|
|
|
if (!DOS_ValidDrive(drive)) {
|
|
Error(InvalidDrive, EC_MediaError , EL_Disk);
|
|
EAX |= 0xffffL;
|
|
return;
|
|
}
|
|
|
|
if (!DOS_GetFreeSpace(drive, &size, &available)) {
|
|
Error(GeneralFailure, EC_MediaError , EL_Disk);
|
|
EAX |= 0xffffL;
|
|
return;
|
|
}
|
|
|
|
EAX = (EAX & 0xffff0000L) | SectorsPerCluster;
|
|
ECX = (ECX & 0xffff0000L) | SectorSize;
|
|
|
|
EBX = (EBX & 0xffff0000L) | (available / (CX * AX));
|
|
EDX = (EDX & 0xffff0000L) | (size / (CX * AX));
|
|
Error (0,0,0);
|
|
}
|
|
|
|
void SetDefaultDrive(struct sigcontext_struct *context)
|
|
{
|
|
int drive;
|
|
|
|
drive = EDX & 0xffL;
|
|
|
|
if (!DOS_ValidDrive(drive)) {
|
|
Error (InvalidDrive, EC_MediaError, EL_Disk);
|
|
return;
|
|
} else {
|
|
DOS_SetDefaultDrive(drive);
|
|
EAX = (EAX &0xffffff00L) | MAX_DOS_DRIVES;
|
|
Error (0,0,0);
|
|
}
|
|
}
|
|
|
|
void GetDefaultDrive(struct sigcontext_struct *context)
|
|
{
|
|
EAX = (EAX & 0xffffff00L) | DOS_GetDefaultDrive();
|
|
Error (0,0,0);
|
|
}
|
|
|
|
void GetDriveAllocInfo(struct sigcontext_struct *context)
|
|
{
|
|
int drive;
|
|
long size, available;
|
|
BYTE mediaID;
|
|
|
|
drive = EDX & 0xffL;
|
|
|
|
if (!DOS_ValidDrive(drive)) {
|
|
EAX = (EAX & 0xffff0000L) | SectorsPerCluster;
|
|
ECX = (ECX & 0xffff0000L) | SectorSize;
|
|
EDX = (EDX & 0xffff0000L);
|
|
Error (InvalidDrive, EC_MediaError, EL_Disk);
|
|
return;
|
|
}
|
|
|
|
if (!DOS_GetFreeSpace(drive, &size, &available)) {
|
|
Error(GeneralFailure, EC_MediaError , EL_Disk);
|
|
EAX |= 0xffffL;
|
|
return;
|
|
}
|
|
|
|
EAX = (EAX & 0xffff0000L) | SectorsPerCluster;
|
|
ECX = (ECX & 0xffff0000L) | SectorSize;
|
|
EDX = (EDX & 0xffff0000L) | (size / (CX * AX));
|
|
|
|
mediaID = 0xf0;
|
|
|
|
DS = segment(mediaID);
|
|
EBX = offset(mediaID);
|
|
Error (0,0,0);
|
|
}
|
|
|
|
void GetDefDriveAllocInfo(struct sigcontext_struct *context)
|
|
{
|
|
EDX = DOS_GetDefaultDrive();
|
|
GetDriveAllocInfo(context);
|
|
}
|
|
|
|
void GetDrivePB(struct sigcontext_struct *context)
|
|
{
|
|
Error (InvalidDrive, EC_MediaError, EL_Disk);
|
|
EAX = (EAX & 0xffff0000L) | 0xffL;
|
|
/* I'm sorry but I only got networked drives :-) */
|
|
}
|
|
|
|
void ReadFile(struct sigcontext_struct *context)
|
|
{
|
|
char *ptr;
|
|
int size;
|
|
|
|
/* can't read from stdout / stderr */
|
|
|
|
if ((BX == 1) || (BX == 2)) {
|
|
Error (InvalidHandle, EL_Unknown, EC_Unknown);
|
|
EAX = (EAX & 0xffff0000L) | InvalidHandle;
|
|
SetCflag;
|
|
return;
|
|
}
|
|
|
|
ptr = (char *) pointer (DS,DX);
|
|
|
|
if (BX == 0) {
|
|
*ptr = EOF;
|
|
Error (0,0,0);
|
|
EAX = (EAX & 0xffff0000L) | 1;
|
|
ResetCflag;
|
|
return;
|
|
} else {
|
|
size = read(BX, ptr, CX);
|
|
if (size == 0) {
|
|
Error (ReadFault, EC_Unknown, EL_Unknown);
|
|
EAX = (EAX & 0xffffff00L) | ExtendedError;
|
|
return;
|
|
}
|
|
|
|
if (size == -1) {
|
|
switch (errno) {
|
|
case EAGAIN:
|
|
Error (ShareViolation, EC_Temporary, EL_Unknown);
|
|
break;
|
|
case EBADF:
|
|
Error (InvalidHandle, EC_AppError, EL_Unknown);
|
|
break;
|
|
default:
|
|
Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
|
|
break;
|
|
}
|
|
EAX = (EAX & 0xffffff00L) | ExtendedError;
|
|
SetCflag;
|
|
return;
|
|
}
|
|
Error (0,0,0);
|
|
EAX = (EAX & 0xffff0000L) | size;
|
|
ResetCflag;
|
|
}
|
|
}
|
|
|
|
void WriteFile(struct sigcontext_struct *context)
|
|
{
|
|
char *ptr;
|
|
int x,size;
|
|
|
|
ptr = (char *) pointer (DS,DX);
|
|
|
|
if (BX == 0) {
|
|
Error (InvalidHandle, EC_Unknown, EL_Unknown);
|
|
EAX = InvalidHandle;
|
|
SetCflag;
|
|
return;
|
|
}
|
|
|
|
if (BX < 3) {
|
|
for (x = 0;x != CX;x++) {
|
|
fprintf(stderr, "%c", *ptr++);
|
|
}
|
|
fflush(stderr);
|
|
|
|
Error (0,0,0);
|
|
EAX = (EAX & 0xffffff00L) | CX;
|
|
ResetCflag;
|
|
} else {
|
|
size = write(BX, ptr , CX);
|
|
if (size == 0) {
|
|
Error (WriteFault, EC_Unknown, EL_Unknown);
|
|
EAX = (EAX & 0xffffff00L) | ExtendedError;
|
|
return;
|
|
}
|
|
|
|
if (size == -1) {
|
|
switch (errno) {
|
|
case EAGAIN:
|
|
Error (ShareViolation, EC_Temporary, EL_Unknown);
|
|
break;
|
|
case EBADF:
|
|
Error (InvalidHandle, EC_AppError, EL_Unknown);
|
|
break;
|
|
case ENOSPC:
|
|
Error (DiskFull, EC_MediaError, EL_Disk);
|
|
break;
|
|
default:
|
|
Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
|
|
break;
|
|
}
|
|
EAX = (EAX & 0xffffff00L) | ExtendedError;
|
|
SetCflag;
|
|
return;
|
|
}
|
|
Error (0,0,0);
|
|
EAX = (EAX & 0xffff0000L) | size;
|
|
ResetCflag;
|
|
}
|
|
}
|
|
|
|
void UnlinkFile(struct sigcontext_struct *context)
|
|
{
|
|
if (unlink( GetUnixFileName((char *) pointer(DS,DX)) ) == -1) {
|
|
switch (errno) {
|
|
case EACCES:
|
|
case EPERM:
|
|
case EROFS:
|
|
Error (WriteProtected, EC_AccessDenied, EL_Unknown);
|
|
break;
|
|
case EBUSY:
|
|
Error (LockViolation, EC_AccessDenied, EL_Unknown);
|
|
break;
|
|
case EAGAIN:
|
|
Error (ShareViolation, EC_Temporary, EL_Unknown);
|
|
break;
|
|
case ENOENT:
|
|
Error (FileNotFound, EC_NotFound, EL_Unknown);
|
|
break;
|
|
default:
|
|
Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
|
|
break;
|
|
}
|
|
EAX = (EAX & 0xffffff00L) | ExtendedError; SetCflag;
|
|
return;
|
|
}
|
|
Error (0,0,0);
|
|
ResetCflag;
|
|
}
|
|
|
|
void SeekFile(struct sigcontext_struct *context)
|
|
{
|
|
int handle, status, fileoffset;
|
|
|
|
switch (EAX & 0xffL) {
|
|
case 1: fileoffset = SEEK_CUR;
|
|
break;
|
|
case 2: fileoffset = SEEK_END;
|
|
break;
|
|
default:
|
|
case 0: fileoffset = SEEK_SET;
|
|
break;
|
|
}
|
|
status = lseek(BX, (CX * 0x100) + DX, fileoffset);
|
|
if (status == -1) {
|
|
switch (errno) {
|
|
case EBADF:
|
|
Error (InvalidHandle, EC_AppError, EL_Unknown);
|
|
break;
|
|
case EINVAL:
|
|
Error (DataInvalid, EC_AppError, EL_Unknown);
|
|
break;
|
|
default:
|
|
Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
|
|
break;
|
|
}
|
|
EAX = (EAX & 0xffffff00L) | ExtendedError; SetCflag;
|
|
return;
|
|
}
|
|
Error (0,0,0);
|
|
ResetCflag;
|
|
}
|
|
|
|
void GetFileAttributes(struct sigcontext_struct *context)
|
|
{
|
|
EAX &= 0xfffff00L;
|
|
ResetCflag;
|
|
}
|
|
|
|
void SetFileAttributes(struct sigcontext_struct *context)
|
|
{
|
|
ResetCflag;
|
|
}
|
|
|
|
void DosIOCTL(struct sigcontext_struct *context)
|
|
{
|
|
fprintf(stderr,"int21: IOCTL\n");
|
|
EAX = (EAX & 0xfffff00L) | UnknownUnit;
|
|
SetCflag;
|
|
}
|
|
|
|
void DupeFileHandle(struct sigcontext_struct *context)
|
|
{
|
|
EAX = (EAX & 0xffff0000L) | dup(BX);
|
|
ResetCflag;
|
|
}
|
|
|
|
void GetSystemDate(struct sigcontext_struct *context)
|
|
{
|
|
struct tm *now;
|
|
time_t ltime;
|
|
|
|
ltime = time(NULL);
|
|
now = localtime(<ime);
|
|
|
|
ECX = (ECX & 0xffff0000L) | now->tm_year + 1900;
|
|
EDX = (EDX & 0xffff0000L) | ((now->tm_mon + 1) << 8) | now->tm_mday;
|
|
EAX = (EAX & 0xffff0000L) | now->tm_wday;
|
|
}
|
|
|
|
void GetSystemTime(struct sigcontext_struct *context)
|
|
{
|
|
struct tm *now;
|
|
time_t ltime;
|
|
|
|
ltime = time(NULL);
|
|
now = localtime(<ime);
|
|
|
|
ECX = (ECX & 0xffffff00L) | (now->tm_hour << 8) | now->tm_min;
|
|
EDX = (EDX & 0xffffff00L) | now->tm_sec << 8;
|
|
}
|
|
|
|
void GetExtendedErrorInfo(struct sigcontext_struct *context)
|
|
{
|
|
EAX = (EAX & 0xffffff00L) | ExtendedError;
|
|
EBX = (EBX & 0xffff0000L) | (0x100 * ErrorClass) | Action;
|
|
ECX = (ECX & 0xffff00ffL) | (0x100 * ErrorLocus);
|
|
}
|
|
|
|
void GetInDosFlag(struct sigcontext_struct *context)
|
|
{
|
|
const BYTE InDosFlag = 0;
|
|
|
|
ES = (ES & 0xffff0000L) | segment(InDosFlag);
|
|
EBX = (EBX & 0xffff0000L) | offset(InDosFlag);
|
|
}
|
|
|
|
void CreateFile(struct sigcontext_struct *context)
|
|
{
|
|
int handle;
|
|
|
|
if ((handle = open(GetUnixFileName((char *) pointer(DS,DX)), O_CREAT | O_TRUNC)) == -1) {
|
|
switch (errno) {
|
|
case EACCES:
|
|
case EPERM:
|
|
case EROFS:
|
|
Error (WriteProtected, EC_AccessDenied, EL_Unknown);
|
|
break;
|
|
case EISDIR:
|
|
Error (CanNotMakeDir, EC_AccessDenied, EL_Unknown);
|
|
break;
|
|
case ENFILE:
|
|
case EMFILE:
|
|
Error (NoMoreFiles, EC_MediaError, EL_Unknown);
|
|
case EEXIST:
|
|
Error (FileExists, EC_Exists, EL_Disk);
|
|
break;
|
|
case ENOSPC:
|
|
Error (DiskFull, EC_MediaError, EL_Disk);
|
|
break;
|
|
default:
|
|
Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
|
|
break;
|
|
}
|
|
EAX = (EAX & 0xffffff00L) | ExtendedError;
|
|
SetCflag;
|
|
return;
|
|
}
|
|
Error (0,0,0);
|
|
EBX = (EBX & 0xffff0000L) | handle;
|
|
EAX = (EAX & 0xffffff00L) | NoError;
|
|
ResetCflag;
|
|
}
|
|
|
|
void OpenExistingFile(struct sigcontext_struct *context)
|
|
{
|
|
int handle;
|
|
|
|
fprintf(stderr,"OpenExistingFile (%s)\n",(char *) pointer(DS,DX));
|
|
|
|
if ((handle = open(GetUnixFileName((char*) pointer(DS,DX)), O_RDWR)) == -1) {
|
|
switch (errno) {
|
|
case EACCES:
|
|
case EPERM:
|
|
case EROFS:
|
|
Error (WriteProtected, EC_AccessDenied, EL_Unknown);
|
|
break;
|
|
case EISDIR:
|
|
Error (CanNotMakeDir, EC_AccessDenied, EL_Unknown);
|
|
break;
|
|
case ENFILE:
|
|
case EMFILE:
|
|
Error (NoMoreFiles, EC_MediaError, EL_Unknown);
|
|
case EEXIST:
|
|
Error (FileExists, EC_Exists, EL_Disk);
|
|
break;
|
|
case ENOSPC:
|
|
Error (DiskFull, EC_MediaError, EL_Disk);
|
|
break;
|
|
case ENOENT:
|
|
Error (FileNotFound, EC_MediaError, EL_Disk);
|
|
break;
|
|
default:
|
|
Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
|
|
break;
|
|
}
|
|
EAX = (EAX & 0xffffff00L) | ExtendedError;
|
|
SetCflag;
|
|
return;
|
|
}
|
|
Error (0,0,0);
|
|
EBX = (EBX & 0xffff0000L) | handle;
|
|
EAX = (EAX & 0xffffff00L) | NoError;
|
|
ResetCflag;
|
|
}
|
|
|
|
void CloseFile(struct sigcontext_struct *context)
|
|
{
|
|
if (close(BX) == -1) {
|
|
switch (errno) {
|
|
case EBADF:
|
|
Error (InvalidHandle, EC_AppError, EL_Unknown);
|
|
break;
|
|
default:
|
|
Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
|
|
break;
|
|
}
|
|
EAX = (EAX & 0xffffff00L) | ExtendedError;
|
|
SetCflag;
|
|
return;
|
|
}
|
|
Error (0,0,0);
|
|
EAX = (EAX & 0xffffff00L) | NoError;
|
|
ResetCflag;
|
|
}
|
|
|
|
void RenameFile(struct sigcontext_struct *context)
|
|
{
|
|
char *newname, *oldname;
|
|
|
|
fprintf(stderr,"int21: renaming %s to %s\n",(char *) pointer(DS,DX), pointer(ES,DI) );
|
|
|
|
oldname = GetUnixFileName( (char *) pointer(DS,DX) );
|
|
newname = GetUnixFileName( (char *) pointer(ES,DI) );
|
|
|
|
rename( oldname, newname);
|
|
ResetCflag;
|
|
}
|
|
|
|
void GetTrueFileName(struct sigcontext_struct *context)
|
|
{
|
|
fprintf(stderr,"int21: GetTrueFileName of %s\n",(char *) pointer(DS,SI));
|
|
|
|
strncpy((char *) pointer(ES,DI), (char *) pointer(DS,SI), strlen((char *) pointer(DS,SI)) & 0x7f);
|
|
ResetCflag;
|
|
}
|
|
|
|
void MakeDir(struct sigcontext_struct *context)
|
|
{
|
|
char *dirname;
|
|
|
|
fprintf(stderr,"int21: makedir %s\n",(char *) pointer(DS,DX) );
|
|
|
|
if ((dirname = GetUnixFileName( (char *) pointer(DS,DX) ))== NULL) {
|
|
EAX = (EAX & 0xffffff00L) | CanNotMakeDir;
|
|
SetCflag;
|
|
return;
|
|
}
|
|
|
|
if (mkdir(dirname,0) == -1) {
|
|
EAX = (EAX & 0xffffff00L) | CanNotMakeDir;
|
|
SetCflag;
|
|
return;
|
|
}
|
|
ResetCflag;
|
|
}
|
|
|
|
void ChangeDir(struct sigcontext_struct *context)
|
|
{
|
|
fprintf(stderr,"int21: changedir %s\n",(char *) pointer(DS,DX) );
|
|
|
|
DOS_ChangeDir(DOS_GetDefaultDrive(), (char *) pointer (DS,DX));
|
|
}
|
|
|
|
void RemoveDir(struct sigcontext_struct *context)
|
|
{
|
|
char *dirname;
|
|
|
|
fprintf(stderr,"int21: removedir %s\n",(char *) pointer(DS,DX) );
|
|
|
|
if ((dirname = GetUnixFileName( (char *) pointer(DS,DX) ))== NULL) {
|
|
EAX = (EAX & 0xffffff00L) | CanNotMakeDir;
|
|
SetCflag;
|
|
return;
|
|
}
|
|
|
|
/*
|
|
if (strcmp(unixname,DosDrives[drive].CurrentDirectory)) {
|
|
EAX = (EAX & 0xffffff00L) | CanNotRemoveCwd;
|
|
SetCflag;
|
|
}
|
|
*/
|
|
if (rmdir(dirname) == -1) {
|
|
EAX = (EAX & 0xffffff00L) | CanNotMakeDir;
|
|
SetCflag;
|
|
}
|
|
ResetCflag;
|
|
}
|
|
|
|
void AllocateMemory(struct sigcontext_struct *context)
|
|
{
|
|
char *ptr;
|
|
|
|
fprintf(stderr,"int21: malloc %d bytes\n", BX * 0x10 );
|
|
|
|
if ((ptr = (void *) memalign((size_t) (BX * 0x10), 0x10)) == NULL) {
|
|
EAX = (EAX & 0xffffff00L) | OutOfMemory;
|
|
EBX = (EBX & 0xffffff00L); /* out of memory */
|
|
SetCflag;
|
|
}
|
|
fprintf(stderr,"int21: malloc (ptr = %d)\n", ptr );
|
|
|
|
EAX = (EAX & 0xffff0000L) | segment((unsigned long) ptr);
|
|
ResetCflag;
|
|
}
|
|
|
|
void FreeMemory(struct sigcontext_struct *context)
|
|
{
|
|
fprintf(stderr,"int21: freemem (ptr = %d)\n", ES * 0x10 );
|
|
|
|
free((void *)(ES * 0x10));
|
|
ResetCflag;
|
|
}
|
|
|
|
void ResizeMemoryBlock(struct sigcontext_struct *context)
|
|
{
|
|
char *ptr;
|
|
|
|
fprintf(stderr,"int21: realloc (ptr = %d)\n", ES * 0x10 );
|
|
|
|
if ((ptr = (void *) realloc((void *)(ES * 0x10), (size_t) BX * 0x10)) == NULL) {
|
|
EAX = (EAX & 0xffffff00L) | OutOfMemory;
|
|
EBX = (EBX & 0xffffff00L); /* out of memory */
|
|
SetCflag;
|
|
}
|
|
EBX = (EBX & 0xffff0000L) | segment((unsigned long) ptr);
|
|
ResetCflag;
|
|
}
|
|
|
|
void ExecProgram(struct sigcontext_struct *context)
|
|
{
|
|
execl("wine", GetUnixFileName((char *) pointer(DS,DX)) );
|
|
}
|
|
|
|
void GetReturnCode(struct sigcontext_struct *context)
|
|
{
|
|
EAX = (EAX & 0xffffff00L) | NoError; /* normal exit */
|
|
}
|
|
|
|
void FindFirst(struct sigcontext_struct *context)
|
|
{
|
|
|
|
}
|
|
|
|
void FindNext(struct sigcontext_struct *context)
|
|
{
|
|
|
|
}
|
|
|
|
void GetSysVars(struct sigcontext_struct *context)
|
|
{
|
|
/* return a null pointer, to encourage anyone who tries to
|
|
use the pointer */
|
|
|
|
ES = 0x0;
|
|
EBX = (EBX & 0xffff0000L);
|
|
}
|
|
|
|
void GetFileDateTime(struct sigcontext_struct *context)
|
|
{
|
|
char *filename;
|
|
struct stat filestat;
|
|
struct tm *now;
|
|
|
|
if ((filename = GetUnixFileName( (char *) pointer(DS,DX) ))== NULL) {
|
|
EAX = (EAX & 0xffffff00L) | FileNotFound;
|
|
SetCflag;
|
|
return;
|
|
}
|
|
stat(filename, &filestat);
|
|
|
|
now = localtime (&filestat.st_mtime);
|
|
|
|
ECX = (ECX & 0xffff0000L) | (now->tm_hour * 0x2000) + (now->tm_min * 0x20) + now->tm_sec/2;
|
|
EDX = (EDX & 0xffff0000L) | (now->tm_year * 0x200) + (now->tm_mon * 0x20) + now->tm_mday;
|
|
|
|
ResetCflag;
|
|
}
|
|
|
|
void SetFileDateTime(struct sigcontext_struct *context)
|
|
{
|
|
char *filename;
|
|
struct utimbuf filetime;
|
|
|
|
filename = GetUnixFileName((char *) pointer(DS,DX));
|
|
|
|
filetime.actime = 0L;
|
|
filetime.modtime = filetime.actime;
|
|
|
|
utime(filename, &filetime);
|
|
ResetCflag;
|
|
}
|
|
|
|
void CreateTempFile(struct sigcontext_struct *context)
|
|
{
|
|
char *filename, temp[256];
|
|
int drive, handle;
|
|
|
|
sprintf(temp,"%s\\win%d.tmp",TempDirectory,(int) getpid());
|
|
|
|
fprintf(stderr,"CreateTempFile %s\n",temp);
|
|
|
|
handle = open(GetUnixFileName(temp), O_CREAT | O_TRUNC | O_RDWR);
|
|
|
|
if (handle == -1) {
|
|
EAX = (EAX & 0xffffff00L) | WriteProtected;
|
|
SetCflag;
|
|
return;
|
|
}
|
|
|
|
strcpy((char *) pointer(DS,DX), temp);
|
|
|
|
EAX = (EAX & 0xffff0000L) | handle;
|
|
ResetCflag;
|
|
}
|
|
|
|
void CreateNewFile(struct sigcontext_struct *context)
|
|
{
|
|
int handle;
|
|
|
|
if ((handle = open(GetUnixFileName((char *) pointer(DS,DX)), O_CREAT | O_TRUNC | O_RDWR)) == -1) {
|
|
EAX = (EAX & 0xffffff00L) | WriteProtected;
|
|
SetCflag;
|
|
return;
|
|
}
|
|
|
|
EAX = (EAX & 0xffff0000L) | handle;
|
|
ResetCflag;
|
|
}
|
|
|
|
void FileLock(struct sigcontext_struct *context)
|
|
{
|
|
|
|
}
|
|
|
|
void GetExtendedCountryInfo(struct sigcontext_struct *context)
|
|
{
|
|
ResetCflag;
|
|
}
|
|
|
|
void GetCurrentDirectory(struct sigcontext_struct *context)
|
|
{
|
|
int drive;
|
|
|
|
if ((EDX & 0xffL) == 0)
|
|
drive = DOS_GetDefaultDrive();
|
|
else
|
|
drive = (EDX & 0xffL)-1;
|
|
|
|
if (!DOS_ValidDrive(drive)) {
|
|
EAX = (EAX & 0xffffff00L) | InvalidDrive;
|
|
SetCflag;
|
|
return;
|
|
}
|
|
|
|
DOS_GetCurrentDir(drive, (char *) pointer(DS,SI) );
|
|
ResetCflag;
|
|
}
|
|
|
|
void GetCurrentPSP(struct sigcontext_struct *context)
|
|
{
|
|
|
|
}
|
|
|
|
void GetDiskSerialNumber(struct sigcontext_struct *context)
|
|
{
|
|
int drive;
|
|
unsigned long serialnumber;
|
|
struct diskinfo *ptr;
|
|
|
|
if ((EBX & 0xffL) == 0)
|
|
drive = DOS_GetDefaultDrive();
|
|
else
|
|
drive = (EBX & 0xffL) - 1;
|
|
|
|
if (!DOS_ValidDrive(drive)) {
|
|
EAX = (EAX & 0xffffff00L) |InvalidDrive;
|
|
SetCflag;
|
|
return;
|
|
}
|
|
|
|
DOS_GetSerialNumber(drive,&serialnumber);
|
|
|
|
ptr = (struct diskinfo *) pointer(DS,SI);
|
|
|
|
ptr->infolevel = 0;
|
|
ptr->serialnumber = serialnumber;
|
|
strcpy(ptr->label,"NO NAME ");
|
|
strcpy(ptr->fstype,"FAT16 ");
|
|
|
|
EAX = (EAX & 0xffffff00L) | NoError;
|
|
ResetCflag;
|
|
}
|
|
|
|
void SetDiskSerialNumber(struct sigcontext_struct *context)
|
|
{
|
|
EAX = (EAX & 0xffffff00L) | 1L;
|
|
ResetCflag;
|
|
}
|
|
|
|
/************************************************************************/
|
|
|
|
int do_int21(struct sigcontext_struct * context)
|
|
{
|
|
int ah;
|
|
|
|
fprintf(stderr, "int21: AX %04x, BX %04x, CX %04x, DX %04x, SI %04x, DI %04x, DS %04x, ES %04x\n",
|
|
AX, BX, CX, DX, SI, DI, DS, ES);
|
|
|
|
ah = (EAX >> 8) & 0xffL;
|
|
|
|
if (ah == 0x59) {
|
|
GetExtendedErrorInfo(context);
|
|
return 1;
|
|
} else {
|
|
|
|
Error (0,0,0);
|
|
|
|
switch(ah) {
|
|
|
|
case 0x00: /* TERMINATE PROGRAM */
|
|
exit(0);
|
|
|
|
case 0x01: /* READ CHARACTER FROM STANDARD INPUT, WITH ECHO */
|
|
case 0x02: /* WRITE CHARACTER TO STANDARD OUTPUT */
|
|
case 0x03: /* READ CHARACTER FROM STDAUX */
|
|
case 0x04: /* WRITE CHARACTER TO STDAUX */
|
|
case 0x05: /* WRITE CHARACTER TO PRINTER */
|
|
case 0x06: /* DIRECT CONSOLE IN/OUTPUT */
|
|
case 0x07: /* DIRECT CHARACTER INPUT, WITHOUT ECHO */
|
|
case 0x08: /* CHARACTER INPUT WITHOUT ECHO */
|
|
case 0x09: /* WRITE STRING TO STANDARD OUTPUT */
|
|
case 0x0a: /* BUFFERED INPUT */
|
|
case 0x0b: /* GET STDIN STATUS */
|
|
case 0x0c: /* FLUSH BUFFER AND READ STANDARD INPUT */
|
|
case 0x0d: /* DISK BUFFER FLUSH */
|
|
break;
|
|
|
|
/* no FCB support for CP/M hackers */
|
|
|
|
case 0x0f: /* OPEN FILE USING FCB */
|
|
case 0x10: /* CLOSE FILE USING FCB */
|
|
case 0x11: /* FIND FIRST MATCHING FILE USING FCB */
|
|
case 0x12: /* FIND NEXT MATCHING FILE USING FCB */
|
|
case 0x13: /* DELETE FILE USING FCB */
|
|
case 0x14: /* SEQUENTIAL READ FROM FCB FILE */
|
|
case 0x15: /* SEQUENTIAL WRITE TO FCB FILE */
|
|
case 0x16: /* CREATE OR TRUNCATE FILE USING FCB */
|
|
case 0x17: /* RENAME FILE USING FCB */
|
|
case 0x1a: /* SET DISK TRANSFER AREA ADDRESS */
|
|
case 0x21: /* READ RANDOM RECORD FROM FCB FILE */
|
|
case 0x22: /* WRITE RANDOM RECORD TO FCB FILE */
|
|
case 0x23: /* GET FILE SIZE FOR FCB */
|
|
case 0x24: /* SET RANDOM RECORD NUMBER FOR FCB */
|
|
case 0x27: /* RANDOM BLOCK READ FROM FCB FILE */
|
|
case 0x28: /* RANDOM BLOCK WRITE TO FCB FILE */
|
|
case 0x29: /* PARSE FILENAME INTO FCB */
|
|
case 0x2f: /* GET DISK TRANSFER AREA ADDRESS */
|
|
|
|
case 0x2e: /* SET VERIFY FLAG */
|
|
break;
|
|
|
|
case 0x18: /* NULL FUNCTIONS FOR CP/M COMPATIBILITY */
|
|
case 0x1d:
|
|
case 0x1e:
|
|
case 0x20:
|
|
case 0x2b: /* SET SYSTEM DATE */
|
|
case 0x2d: /* SET SYSTEM TIME */
|
|
case 0x37: /* "SWITCHAR" - GET SWITCH CHARACTER
|
|
"SWITCHAR" - SET SWITCH CHARACTER
|
|
"AVAILDEV" - SPECIFY \DEV\ PREFIX USE */
|
|
case 0x54: /* GET VERIFY FLAG */
|
|
case 0x61: /* UNUSED */
|
|
case 0x6b: /* NULL FUNCTION */
|
|
EAX &= 0xff00;
|
|
break;
|
|
|
|
case 0x67: /* SET HANDLE COUNT */
|
|
ResetCflag;
|
|
break;
|
|
|
|
case 0x0e: /* SELECT DEFAULT DRIVE */
|
|
SetDefaultDrive(context);
|
|
break;
|
|
|
|
case 0x19: /* GET CURRENT DEFAULT DRIVE */
|
|
GetDefaultDrive(context);
|
|
break;
|
|
|
|
case 0x1b: /* GET ALLOCATION INFORMATION FOR DEFAULT DRIVE */
|
|
GetDefDriveAllocInfo(context);
|
|
break;
|
|
|
|
case 0x1c: /* GET ALLOCATION INFORMATION FOR SPECIFIC DRIVE */
|
|
GetDriveAllocInfo(context);
|
|
break;
|
|
|
|
case 0x1f: /* GET DRIVE PARAMETER BLOCK FOR DEFAULT DRIVE */
|
|
case 0x32: /* GET DOS DRIVE PARAMETER BLOCK FOR SPECIFIC DRIVE */
|
|
GetDrivePB(context);
|
|
break;
|
|
|
|
case 0x25: /* SET INTERRUPT VECTOR */
|
|
/* Ignore any attempt to set a segment vector */
|
|
return 1;
|
|
|
|
case 0x26: /* CREATE NEW PROGRAM SEGMENT PREFIX */
|
|
break;
|
|
|
|
case 0x2a: /* GET SYSTEM DATE */
|
|
GetSystemDate(context);
|
|
break;
|
|
|
|
case 0x2c: /* GET SYSTEM TIME */
|
|
GetSystemTime(context);
|
|
break;
|
|
|
|
case 0x30: /* GET DOS VERSION */
|
|
fprintf(stderr,"int21: GetDosVersion\n");
|
|
EAX = DosVersion; /* Hey folks, this is DOS V3.3! */
|
|
EBX = 0x0012; /* 0x123456 is Wine's serial # */
|
|
ECX = 0x3456;
|
|
break;
|
|
|
|
case 0x31: /* TERMINATE AND STAY RESIDENT */
|
|
break;
|
|
|
|
case 0x33: /* MULTIPLEXED */
|
|
switch (EAX & 0xff) {
|
|
case 0x00: /* GET CURRENT EXTENDED BREAK STATE */
|
|
if (!(EAX & 0xffL))
|
|
EDX &= 0xff00L;
|
|
break;
|
|
|
|
case 0x01: /* SET EXTENDED BREAK STATE */
|
|
break;
|
|
|
|
case 0x02: /* GET AND SET EXTENDED CONTROL-BREAK CHECKING STATE */
|
|
EDX &= 0xff00L;
|
|
break;
|
|
|
|
case 0x05: /* GET BOOT DRIVE */
|
|
EDX = (EDX & 0xff00L) | 2;
|
|
/* c: is Wine's bootdrive */
|
|
break;
|
|
|
|
case 0x06: /* GET TRUE VERSION NUMBER */
|
|
EBX = DosVersion;
|
|
EDX = 0x00;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 0x34: /* GET ADDRESS OF INDOS FLAG */
|
|
GetInDosFlag(context);
|
|
break;
|
|
|
|
case 0x35: /* GET INTERRUPT VECTOR */
|
|
/* Return a NULL segment selector - this will bomb,
|
|
if anyone ever tries to use it */
|
|
ES = 0;
|
|
EBX = 0;
|
|
break;
|
|
|
|
case 0x36: /* GET FREE DISK SPACE */
|
|
GetFreeDiskSpace(context);
|
|
break;
|
|
|
|
case 0x38: /* GET COUNTRY-SPECIFIC INFORMATION */
|
|
EAX &= 0xff00;
|
|
EAX |= 0x02; /* no country support available */
|
|
SetCflag;
|
|
break;
|
|
|
|
case 0x39: /* "MKDIR" - CREATE SUBDIRECTORY */
|
|
MakeDir(context);
|
|
break;
|
|
|
|
case 0x3a: /* "RMDIR" - REMOVE SUBDIRECTORY */
|
|
RemoveDir(context);
|
|
break;
|
|
|
|
case 0x3b: /* "CHDIR" - SET CURRENT DIRECTORY */
|
|
ChangeDir(context);
|
|
break;
|
|
|
|
case 0x3c: /* "CREAT" - CREATE OR TRUNCATE FILE */
|
|
CreateFile(context);
|
|
break;
|
|
|
|
case 0x3d: /* "OPEN" - OPEN EXISTING FILE */
|
|
OpenExistingFile(context);
|
|
break;
|
|
|
|
case 0x3e: /* "CLOSE" - CLOSE FILE */
|
|
CloseFile(context);
|
|
break;
|
|
|
|
case 0x3f: /* "READ" - READ FROM FILE OR DEVICE */
|
|
ReadFile(context);
|
|
break;
|
|
|
|
case 0x40: /* "WRITE" - WRITE TO FILE OR DEVICE */
|
|
WriteFile(context);
|
|
break;
|
|
|
|
case 0x41: /* "UNLINK" - DELETE FILE */
|
|
UnlinkFile(context);
|
|
break;
|
|
|
|
case 0x42: /* "LSEEK" - SET CURRENT FILE POSITION */
|
|
SeekFile(context);
|
|
break;
|
|
|
|
case 0x43: /* FILE ATTRIBUTES */
|
|
switch (EAX & 0xff) {
|
|
case 0x00:
|
|
GetFileAttributes(context);
|
|
break;
|
|
case 0x01:
|
|
SetFileAttributes(context);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 0x44: /* IOCTL */
|
|
DosIOCTL(context);
|
|
break;
|
|
|
|
case 0x45: /* "DUP" - DUPLICATE FILE HANDLE */
|
|
case 0x46: /* "DUP2", "FORCEDUP" - FORCE DUPLICATE FILE HANDLE */
|
|
DupeFileHandle(context);
|
|
break;
|
|
|
|
case 0x47: /* "CWD" - GET CURRENT DIRECTORY */
|
|
GetCurrentDirectory(context);
|
|
EAX = (EAX & 0xffff0000L) | 0x0100;
|
|
/* many Microsoft products for Windows rely on this */
|
|
break;
|
|
|
|
case 0x48: /* ALLOCATE MEMORY */
|
|
AllocateMemory(context);
|
|
break;
|
|
|
|
case 0x49: /* FREE MEMORY */
|
|
FreeMemory(context);
|
|
break;
|
|
|
|
case 0x4a: /* RESIZE MEMORY BLOCK */
|
|
ResizeMemoryBlock(context);
|
|
break;
|
|
|
|
case 0x4b: /* "EXEC" - LOAD AND/OR EXECUTE PROGRAM */
|
|
ExecProgram(context);
|
|
break;
|
|
|
|
case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */
|
|
fprintf(stderr,"int21: DosExit\n");
|
|
exit(EAX & 0xff);
|
|
break;
|
|
|
|
case 0x4d: /* GET RETURN CODE */
|
|
GetReturnCode(context);
|
|
break;
|
|
|
|
case 0x4e: /* "FINDFIRST" - FIND FIRST MATCHING FILE */
|
|
FindFirst(context);
|
|
break;
|
|
|
|
case 0x4f: /* "FINDNEXT" - FIND NEXT MATCHING FILE */
|
|
FindNext(context);
|
|
break;
|
|
|
|
case 0x52: /* "SYSVARS" - GET LIST OF LISTS */
|
|
GetSysVars(context);
|
|
break;
|
|
|
|
case 0x56: /* "RENAME" - RENAME FILE */
|
|
RenameFile(context);
|
|
break;
|
|
|
|
case 0x57: /* FILE DATE AND TIME */
|
|
switch (EAX & 0xff) {
|
|
case 0x00:
|
|
GetFileDateTime(context);
|
|
break;
|
|
case 0x01:
|
|
SetFileDateTime(context);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 0x58: /* GET OR SET MEMORY/UMB ALLOCATION STRATEGY */
|
|
switch (EAX & 0xff) {
|
|
case 0x00:
|
|
EAX = (EAX & 0xffffff00L) | 0x01L;
|
|
break;
|
|
case 0x02:
|
|
EAX &= 0xff00L;
|
|
break;
|
|
case 0x01:
|
|
case 0x03:
|
|
break;
|
|
}
|
|
ResetCflag;
|
|
break;
|
|
|
|
case 0x59: /* GET EXTENDED ERROR INFO */
|
|
GetExtendedErrorInfo(context);
|
|
break;
|
|
|
|
case 0x5a: /* CREATE TEMPORARY FILE */
|
|
CreateTempFile(context);
|
|
break;
|
|
|
|
case 0x5b: /* CREATE NEW FILE */
|
|
CreateNewFile(context);
|
|
break;
|
|
|
|
case 0x5c: /* "FLOCK" - RECORD LOCKING */
|
|
FileLock(context);
|
|
break;
|
|
|
|
case 0x5d: /* NETWORK */
|
|
case 0x5e:
|
|
EAX = (EAX & 0xfffff00L) | NoNetwork; /* network software not installed */
|
|
SetCflag;
|
|
break;
|
|
|
|
case 0x5f: /* NETWORK */
|
|
switch (EAX & 0xffL) {
|
|
case 0x07: /* ENABLE DRIVE */
|
|
if (!DOS_EnableDrive(EDX & 0xffL)) {
|
|
Error(InvalidDrive, EC_MediaError , EL_Disk);
|
|
EAX = (EAX & 0xfffff00L) | InvalidDrive;
|
|
SetCflag;
|
|
break;
|
|
} else {
|
|
ResetCflag;
|
|
break;
|
|
}
|
|
case 0x08: /* DISABLE DRIVE */
|
|
if (!DOS_DisableDrive(EDX & 0xffL)) {
|
|
Error(InvalidDrive, EC_MediaError , EL_Disk);
|
|
EAX = (EAX & 0xfffff00L) | InvalidDrive;
|
|
SetCflag;
|
|
break;
|
|
} else {
|
|
ResetCflag;
|
|
break;
|
|
}
|
|
default:
|
|
EAX = (EAX & 0xfffff00L) | NoNetwork; /* network software not installed */
|
|
SetCflag;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 0x60: /* "TRUENAME" - CANONICALIZE FILENAME OR PATH */
|
|
GetTrueFileName(context);
|
|
break;
|
|
|
|
case 0x62: /* GET CURRENT PSP ADDRESS */
|
|
GetCurrentPSP(context);
|
|
break;
|
|
|
|
case 0x65: /* GET EXTENDED COUNTRY INFORMATION */
|
|
GetExtendedCountryInfo(context);
|
|
break;
|
|
|
|
case 0x66: /* GLOBAL CODE PAGE TABLE */
|
|
switch (EAX & 0xffL) {
|
|
case 0x01:
|
|
EBX = CodePage;
|
|
EDX = EBX;
|
|
ResetCflag;
|
|
break;
|
|
case 0x02:
|
|
CodePage = EBX;
|
|
ResetCflag;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 0x68: /* "FFLUSH" - COMMIT FILE */
|
|
ResetCflag;
|
|
break;
|
|
|
|
case 0x69: /* DISK SERIAL NUMBER */
|
|
switch (EAX & 0xff) {
|
|
case 0x00:
|
|
GetDiskSerialNumber(context);
|
|
break;
|
|
case 0x01:
|
|
SetDiskSerialNumber(context);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 0x6a: /* COMMIT FILE */
|
|
ResetCflag;
|
|
break;
|
|
|
|
default:
|
|
fprintf(stderr,"Unable to handle int 0x21 %x\n", context->sc_eax);
|
|
return 1;
|
|
};
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/**********************************************************************
|
|
* DOS3Call
|
|
*/
|
|
int DOS3Call()
|
|
{
|
|
static struct sigcontext_struct *context = NULL;
|
|
|
|
if (!context)
|
|
context = malloc(sizeof(struct sigcontext_struct));
|
|
|
|
/* fprintf(stderr, "DOS3: AX %04x, BX %04x, CX %04x, DX %04x, SI %04x, DI %04x, DS %04x, ES %04x\n",
|
|
_AX, _BX, _CX, _DX, _SI, _DI, _DS, _ES);
|
|
*/
|
|
EAX = _AX;
|
|
EBX = _BX;
|
|
ECX = _CX;
|
|
EDX = _DX;
|
|
DS = _DS;
|
|
ES = _ES;
|
|
DI = _DI;
|
|
SI = _SI;
|
|
/* EFL = _FL;
|
|
*/
|
|
do_int21(context);
|
|
|
|
_AX = AX;
|
|
_BX = BX;
|
|
_CX = CX;
|
|
_DX = DX;
|
|
|
|
_DS = DS;
|
|
_ES = ES;
|
|
|
|
_DI = DI;
|
|
_SI = SI;
|
|
/* _FL = EFL;
|
|
*/
|
|
return 0;
|
|
}
|