14 #include "prototypes.h"
20 static char Copyright
[] = "copyright Erik Bos, 1993";
22 WORD ExtendedError
, CodePage
= 437;
23 BYTE ErrorClass
, Action
, ErrorLocus
;
25 extern char TempDirectory
[];
27 void Error(int e
, int class, int el
)
31 Action
= SA_Ask4Retry
;
35 void GetFreeDiskSpace(struct sigcontext_struct
*context
)
41 drive
= DOS_GetDefaultDrive();
43 drive
= (EDX
& 0xffL
) - 1;
45 if (!DOS_ValidDrive(drive
)) {
46 Error(InvalidDrive
, EC_MediaError
, EL_Disk
);
51 if (!DOS_GetFreeSpace(drive
, &size
, &available
)) {
52 Error(GeneralFailure
, EC_MediaError
, EL_Disk
);
57 EAX
= (EAX
& 0xffff0000L
) | SectorsPerCluster
;
58 ECX
= (ECX
& 0xffff0000L
) | SectorSize
;
60 EBX
= (EBX
& 0xffff0000L
) | (available
/ (CX
* AX
));
61 EDX
= (EDX
& 0xffff0000L
) | (size
/ (CX
* AX
));
65 void SetDefaultDrive(struct sigcontext_struct
*context
)
71 if (!DOS_ValidDrive(drive
)) {
72 Error (InvalidDrive
, EC_MediaError
, EL_Disk
);
75 DOS_SetDefaultDrive(drive
);
76 EAX
= (EAX
&0xffffff00L
) | MAX_DOS_DRIVES
;
81 void GetDefaultDrive(struct sigcontext_struct
*context
)
83 EAX
= (EAX
& 0xffffff00L
) | DOS_GetDefaultDrive();
87 void GetDriveAllocInfo(struct sigcontext_struct
*context
)
95 if (!DOS_ValidDrive(drive
)) {
96 EAX
= (EAX
& 0xffff0000L
) | SectorsPerCluster
;
97 ECX
= (ECX
& 0xffff0000L
) | SectorSize
;
98 EDX
= (EDX
& 0xffff0000L
);
99 Error (InvalidDrive
, EC_MediaError
, EL_Disk
);
103 if (!DOS_GetFreeSpace(drive
, &size
, &available
)) {
104 Error(GeneralFailure
, EC_MediaError
, EL_Disk
);
109 EAX
= (EAX
& 0xffff0000L
) | SectorsPerCluster
;
110 ECX
= (ECX
& 0xffff0000L
) | SectorSize
;
111 EDX
= (EDX
& 0xffff0000L
) | (size
/ (CX
* AX
));
115 DS
= segment(mediaID
);
116 EBX
= offset(mediaID
);
120 void GetDefDriveAllocInfo(struct sigcontext_struct
*context
)
122 EDX
= DOS_GetDefaultDrive();
123 GetDriveAllocInfo(context
);
126 void GetDrivePB(struct sigcontext_struct
*context
)
128 Error (InvalidDrive
, EC_MediaError
, EL_Disk
);
129 EAX
= (EAX
& 0xffff0000L
) | 0xffL
;
130 /* I'm sorry but I only got networked drives :-) */
133 void ReadFile(struct sigcontext_struct
*context
)
138 /* can't read from stdout / stderr */
140 if ((BX
== 1) || (BX
== 2)) {
141 Error (InvalidHandle
, EL_Unknown
, EC_Unknown
);
142 EAX
= (EAX
& 0xffff0000L
) | InvalidHandle
;
147 ptr
= (char *) pointer (DS
,DX
);
152 EAX
= (EAX
& 0xffff0000L
) | 1;
156 size
= read(BX
, ptr
, CX
);
158 Error (ReadFault
, EC_Unknown
, EL_Unknown
);
159 EAX
= (EAX
& 0xffffff00L
) | ExtendedError
;
166 Error (ShareViolation
, EC_Temporary
, EL_Unknown
);
169 Error (InvalidHandle
, EC_AppError
, EL_Unknown
);
172 Error (GeneralFailure
, EC_SystemFailure
, EL_Unknown
);
175 EAX
= (EAX
& 0xffffff00L
) | ExtendedError
;
180 EAX
= (EAX
& 0xffff0000L
) | size
;
185 void WriteFile(struct sigcontext_struct
*context
)
190 ptr
= (char *) pointer (DS
,DX
);
193 Error (InvalidHandle
, EC_Unknown
, EL_Unknown
);
200 for (x
= 0;x
!= CX
;x
++) {
201 fprintf(stderr
, "%c", *ptr
++);
206 EAX
= (EAX
& 0xffffff00L
) | CX
;
209 size
= write(BX
, ptr
, CX
);
211 Error (WriteFault
, EC_Unknown
, EL_Unknown
);
212 EAX
= (EAX
& 0xffffff00L
) | ExtendedError
;
219 Error (ShareViolation
, EC_Temporary
, EL_Unknown
);
222 Error (InvalidHandle
, EC_AppError
, EL_Unknown
);
225 Error (DiskFull
, EC_MediaError
, EL_Disk
);
228 Error (GeneralFailure
, EC_SystemFailure
, EL_Unknown
);
231 EAX
= (EAX
& 0xffffff00L
) | ExtendedError
;
236 EAX
= (EAX
& 0xffff0000L
) | size
;
241 void UnlinkFile(struct sigcontext_struct
*context
)
243 if (unlink( GetUnixFileName((char *) pointer(DS
,DX
)) ) == -1) {
248 Error (WriteProtected
, EC_AccessDenied
, EL_Unknown
);
251 Error (LockViolation
, EC_AccessDenied
, EL_Unknown
);
254 Error (ShareViolation
, EC_Temporary
, EL_Unknown
);
257 Error (FileNotFound
, EC_NotFound
, EL_Unknown
);
260 Error (GeneralFailure
, EC_SystemFailure
, EL_Unknown
);
263 EAX
= (EAX
& 0xffffff00L
) | ExtendedError
; SetCflag
;
270 void SeekFile(struct sigcontext_struct
*context
)
272 int handle
, status
, fileoffset
;
274 switch (EAX
& 0xffL
) {
275 case 1: fileoffset
= SEEK_CUR
;
277 case 2: fileoffset
= SEEK_END
;
280 case 0: fileoffset
= SEEK_SET
;
283 status
= lseek(BX
, (CX
* 0x100) + DX
, fileoffset
);
287 Error (InvalidHandle
, EC_AppError
, EL_Unknown
);
290 Error (DataInvalid
, EC_AppError
, EL_Unknown
);
293 Error (GeneralFailure
, EC_SystemFailure
, EL_Unknown
);
296 EAX
= (EAX
& 0xffffff00L
) | ExtendedError
; SetCflag
;
303 void GetFileAttributes(struct sigcontext_struct
*context
)
309 void SetFileAttributes(struct sigcontext_struct
*context
)
314 void DosIOCTL(struct sigcontext_struct
*context
)
316 fprintf(stderr
,"int21: IOCTL\n");
317 EAX
= (EAX
& 0xfffff00L
) | UnknownUnit
;
321 void DupeFileHandle(struct sigcontext_struct
*context
)
323 EAX
= (EAX
& 0xffff0000L
) | dup(BX
);
327 void GetSystemDate(struct sigcontext_struct
*context
)
333 now
= localtime(<ime
);
335 ECX
= (ECX
& 0xffff0000L
) | now
->tm_year
+ 1900;
336 EDX
= (EDX
& 0xffff0000L
) | ((now
->tm_mon
+ 1) << 8) | now
->tm_mday
;
337 EAX
= (EAX
& 0xffff0000L
) | now
->tm_wday
;
340 void GetSystemTime(struct sigcontext_struct
*context
)
346 now
= localtime(<ime
);
348 ECX
= (ECX
& 0xffffff00L
) | (now
->tm_hour
<< 8) | now
->tm_min
;
349 EDX
= (EDX
& 0xffffff00L
) | now
->tm_sec
<< 8;
352 void GetExtendedErrorInfo(struct sigcontext_struct
*context
)
354 EAX
= (EAX
& 0xffffff00L
) | ExtendedError
;
355 EBX
= (EBX
& 0xffff0000L
) | (0x100 * ErrorClass
) | Action
;
356 ECX
= (ECX
& 0xffff00ffL
) | (0x100 * ErrorLocus
);
359 void GetInDosFlag(struct sigcontext_struct
*context
)
361 const BYTE InDosFlag
= 0;
363 ES
= (ES
& 0xffff0000L
) | segment(InDosFlag
);
364 EBX
= (EBX
& 0xffff0000L
) | offset(InDosFlag
);
367 void CreateFile(struct sigcontext_struct
*context
)
371 if ((handle
= open(GetUnixFileName((char *) pointer(DS
,DX
)), O_CREAT
| O_TRUNC
)) == -1) {
376 Error (WriteProtected
, EC_AccessDenied
, EL_Unknown
);
379 Error (CanNotMakeDir
, EC_AccessDenied
, EL_Unknown
);
383 Error (NoMoreFiles
, EC_MediaError
, EL_Unknown
);
385 Error (FileExists
, EC_Exists
, EL_Disk
);
388 Error (DiskFull
, EC_MediaError
, EL_Disk
);
391 Error (GeneralFailure
, EC_SystemFailure
, EL_Unknown
);
394 EAX
= (EAX
& 0xffffff00L
) | ExtendedError
;
399 EBX
= (EBX
& 0xffff0000L
) | handle
;
400 EAX
= (EAX
& 0xffffff00L
) | NoError
;
404 void OpenExistingFile(struct sigcontext_struct
*context
)
408 fprintf(stderr
,"OpenExistingFile (%s)\n",(char *) pointer(DS
,DX
));
410 if ((handle
= open(GetUnixFileName((char*) pointer(DS
,DX
)), O_RDWR
)) == -1) {
415 Error (WriteProtected
, EC_AccessDenied
, EL_Unknown
);
418 Error (CanNotMakeDir
, EC_AccessDenied
, EL_Unknown
);
422 Error (NoMoreFiles
, EC_MediaError
, EL_Unknown
);
424 Error (FileExists
, EC_Exists
, EL_Disk
);
427 Error (DiskFull
, EC_MediaError
, EL_Disk
);
430 Error (FileNotFound
, EC_MediaError
, EL_Disk
);
433 Error (GeneralFailure
, EC_SystemFailure
, EL_Unknown
);
436 EAX
= (EAX
& 0xffffff00L
) | ExtendedError
;
441 EBX
= (EBX
& 0xffff0000L
) | handle
;
442 EAX
= (EAX
& 0xffffff00L
) | NoError
;
446 void CloseFile(struct sigcontext_struct
*context
)
448 if (close(BX
) == -1) {
451 Error (InvalidHandle
, EC_AppError
, EL_Unknown
);
454 Error (GeneralFailure
, EC_SystemFailure
, EL_Unknown
);
457 EAX
= (EAX
& 0xffffff00L
) | ExtendedError
;
462 EAX
= (EAX
& 0xffffff00L
) | NoError
;
466 void RenameFile(struct sigcontext_struct
*context
)
468 char *newname
, *oldname
;
470 fprintf(stderr
,"int21: renaming %s to %s\n",(char *) pointer(DS
,DX
), pointer(ES
,DI
) );
472 oldname
= GetUnixFileName( (char *) pointer(DS
,DX
) );
473 newname
= GetUnixFileName( (char *) pointer(ES
,DI
) );
475 rename( oldname
, newname
);
479 void GetTrueFileName(struct sigcontext_struct
*context
)
481 fprintf(stderr
,"int21: GetTrueFileName of %s\n",(char *) pointer(DS
,SI
));
483 strncpy((char *) pointer(ES
,DI
), (char *) pointer(DS
,SI
), strlen((char *) pointer(DS
,SI
)) & 0x7f);
487 void MakeDir(struct sigcontext_struct
*context
)
491 fprintf(stderr
,"int21: makedir %s\n",(char *) pointer(DS
,DX
) );
493 if ((dirname
= GetUnixFileName( (char *) pointer(DS
,DX
) ))== NULL
) {
494 EAX
= (EAX
& 0xffffff00L
) | CanNotMakeDir
;
499 if (mkdir(dirname
,0) == -1) {
500 EAX
= (EAX
& 0xffffff00L
) | CanNotMakeDir
;
507 void ChangeDir(struct sigcontext_struct
*context
)
509 fprintf(stderr
,"int21: changedir %s\n",(char *) pointer(DS
,DX
) );
511 DOS_ChangeDir(DOS_GetDefaultDrive(), (char *) pointer (DS
,DX
));
514 void RemoveDir(struct sigcontext_struct
*context
)
518 fprintf(stderr
,"int21: removedir %s\n",(char *) pointer(DS
,DX
) );
520 if ((dirname
= GetUnixFileName( (char *) pointer(DS
,DX
) ))== NULL
) {
521 EAX
= (EAX
& 0xffffff00L
) | CanNotMakeDir
;
527 if (strcmp(unixname,DosDrives[drive].CurrentDirectory)) {
528 EAX = (EAX & 0xffffff00L) | CanNotRemoveCwd;
532 if (rmdir(dirname
) == -1) {
533 EAX
= (EAX
& 0xffffff00L
) | CanNotMakeDir
;
539 void AllocateMemory(struct sigcontext_struct
*context
)
543 fprintf(stderr
,"int21: malloc %d bytes\n", BX
* 0x10 );
545 if ((ptr
= (void *) memalign((size_t) (BX
* 0x10), 0x10)) == NULL
) {
546 EAX
= (EAX
& 0xffffff00L
) | OutOfMemory
;
547 EBX
= (EBX
& 0xffffff00L
); /* out of memory */
550 fprintf(stderr
,"int21: malloc (ptr = %d)\n", ptr
);
552 EAX
= (EAX
& 0xffff0000L
) | segment((unsigned long) ptr
);
556 void FreeMemory(struct sigcontext_struct
*context
)
558 fprintf(stderr
,"int21: freemem (ptr = %d)\n", ES
* 0x10 );
560 free((void *)(ES
* 0x10));
564 void ResizeMemoryBlock(struct sigcontext_struct
*context
)
568 fprintf(stderr
,"int21: realloc (ptr = %d)\n", ES
* 0x10 );
570 if ((ptr
= (void *) realloc((void *)(ES
* 0x10), (size_t) BX
* 0x10)) == NULL
) {
571 EAX
= (EAX
& 0xffffff00L
) | OutOfMemory
;
572 EBX
= (EBX
& 0xffffff00L
); /* out of memory */
575 EBX
= (EBX
& 0xffff0000L
) | segment((unsigned long) ptr
);
579 void ExecProgram(struct sigcontext_struct
*context
)
581 execl("wine", GetUnixFileName((char *) pointer(DS
,DX
)) );
584 void GetReturnCode(struct sigcontext_struct
*context
)
586 EAX
= (EAX
& 0xffffff00L
) | NoError
; /* normal exit */
589 void FindFirst(struct sigcontext_struct
*context
)
594 void FindNext(struct sigcontext_struct
*context
)
599 void GetSysVars(struct sigcontext_struct
*context
)
601 /* return a null pointer, to encourage anyone who tries to
605 EBX
= (EBX
& 0xffff0000L
);
608 void GetFileDateTime(struct sigcontext_struct
*context
)
611 struct stat filestat
;
614 if ((filename
= GetUnixFileName( (char *) pointer(DS
,DX
) ))== NULL
) {
615 EAX
= (EAX
& 0xffffff00L
) | FileNotFound
;
619 stat(filename
, &filestat
);
621 now
= localtime (&filestat
.st_mtime
);
623 ECX
= (ECX
& 0xffff0000L
) | (now
->tm_hour
* 0x2000) + (now
->tm_min
* 0x20) + now
->tm_sec
/2;
624 EDX
= (EDX
& 0xffff0000L
) | (now
->tm_year
* 0x200) + (now
->tm_mon
* 0x20) + now
->tm_mday
;
629 void SetFileDateTime(struct sigcontext_struct
*context
)
632 struct utimbuf filetime
;
634 filename
= GetUnixFileName((char *) pointer(DS
,DX
));
636 filetime
.actime
= 0L;
637 filetime
.modtime
= filetime
.actime
;
639 utime(filename
, &filetime
);
643 void CreateTempFile(struct sigcontext_struct
*context
)
645 char *filename
, temp
[256];
648 sprintf(temp
,"%s\\win%d.tmp",TempDirectory
,(int) getpid());
650 fprintf(stderr
,"CreateTempFile %s\n",temp
);
652 handle
= open(GetUnixFileName(temp
), O_CREAT
| O_TRUNC
| O_RDWR
);
655 EAX
= (EAX
& 0xffffff00L
) | WriteProtected
;
660 strcpy((char *) pointer(DS
,DX
), temp
);
662 EAX
= (EAX
& 0xffff0000L
) | handle
;
666 void CreateNewFile(struct sigcontext_struct
*context
)
670 if ((handle
= open(GetUnixFileName((char *) pointer(DS
,DX
)), O_CREAT
| O_TRUNC
| O_RDWR
)) == -1) {
671 EAX
= (EAX
& 0xffffff00L
) | WriteProtected
;
676 EAX
= (EAX
& 0xffff0000L
) | handle
;
680 void FileLock(struct sigcontext_struct
*context
)
685 void GetExtendedCountryInfo(struct sigcontext_struct
*context
)
690 void GetCurrentDirectory(struct sigcontext_struct
*context
)
694 if ((EDX
& 0xffL
) == 0)
695 drive
= DOS_GetDefaultDrive();
697 drive
= (EDX
& 0xffL
)-1;
699 if (!DOS_ValidDrive(drive
)) {
700 EAX
= (EAX
& 0xffffff00L
) | InvalidDrive
;
705 DOS_GetCurrentDir(drive
, (char *) pointer(DS
,SI
) );
709 void GetCurrentPSP(struct sigcontext_struct
*context
)
714 void GetDiskSerialNumber(struct sigcontext_struct
*context
)
717 unsigned long serialnumber
;
718 struct diskinfo
*ptr
;
720 if ((EBX
& 0xffL
) == 0)
721 drive
= DOS_GetDefaultDrive();
723 drive
= (EBX
& 0xffL
) - 1;
725 if (!DOS_ValidDrive(drive
)) {
726 EAX
= (EAX
& 0xffffff00L
) |InvalidDrive
;
731 DOS_GetSerialNumber(drive
,&serialnumber
);
733 ptr
= (struct diskinfo
*) pointer(DS
,SI
);
736 ptr
->serialnumber
= serialnumber
;
737 strcpy(ptr
->label
,"NO NAME ");
738 strcpy(ptr
->fstype
,"FAT16 ");
740 EAX
= (EAX
& 0xffffff00L
) | NoError
;
744 void SetDiskSerialNumber(struct sigcontext_struct
*context
)
746 EAX
= (EAX
& 0xffffff00L
) | 1L;
750 /************************************************************************/
752 int do_int21(struct sigcontext_struct
* context
)
756 fprintf(stderr
, "int21: AX %04x, BX %04x, CX %04x, DX %04x, SI %04x, DI %04x, DS %04x, ES %04x\n",
757 AX
, BX
, CX
, DX
, SI
, DI
, DS
, ES
);
759 ah
= (EAX
>> 8) & 0xffL
;
762 GetExtendedErrorInfo(context
);
770 case 0x00: /* TERMINATE PROGRAM */
773 case 0x01: /* READ CHARACTER FROM STANDARD INPUT, WITH ECHO */
774 case 0x02: /* WRITE CHARACTER TO STANDARD OUTPUT */
775 case 0x03: /* READ CHARACTER FROM STDAUX */
776 case 0x04: /* WRITE CHARACTER TO STDAUX */
777 case 0x05: /* WRITE CHARACTER TO PRINTER */
778 case 0x06: /* DIRECT CONSOLE IN/OUTPUT */
779 case 0x07: /* DIRECT CHARACTER INPUT, WITHOUT ECHO */
780 case 0x08: /* CHARACTER INPUT WITHOUT ECHO */
781 case 0x09: /* WRITE STRING TO STANDARD OUTPUT */
782 case 0x0a: /* BUFFERED INPUT */
783 case 0x0b: /* GET STDIN STATUS */
784 case 0x0c: /* FLUSH BUFFER AND READ STANDARD INPUT */
785 case 0x0d: /* DISK BUFFER FLUSH */
788 /* no FCB support for CP/M hackers */
790 case 0x0f: /* OPEN FILE USING FCB */
791 case 0x10: /* CLOSE FILE USING FCB */
792 case 0x11: /* FIND FIRST MATCHING FILE USING FCB */
793 case 0x12: /* FIND NEXT MATCHING FILE USING FCB */
794 case 0x13: /* DELETE FILE USING FCB */
795 case 0x14: /* SEQUENTIAL READ FROM FCB FILE */
796 case 0x15: /* SEQUENTIAL WRITE TO FCB FILE */
797 case 0x16: /* CREATE OR TRUNCATE FILE USING FCB */
798 case 0x17: /* RENAME FILE USING FCB */
799 case 0x1a: /* SET DISK TRANSFER AREA ADDRESS */
800 case 0x21: /* READ RANDOM RECORD FROM FCB FILE */
801 case 0x22: /* WRITE RANDOM RECORD TO FCB FILE */
802 case 0x23: /* GET FILE SIZE FOR FCB */
803 case 0x24: /* SET RANDOM RECORD NUMBER FOR FCB */
804 case 0x27: /* RANDOM BLOCK READ FROM FCB FILE */
805 case 0x28: /* RANDOM BLOCK WRITE TO FCB FILE */
806 case 0x29: /* PARSE FILENAME INTO FCB */
807 case 0x2f: /* GET DISK TRANSFER AREA ADDRESS */
809 case 0x2e: /* SET VERIFY FLAG */
812 case 0x18: /* NULL FUNCTIONS FOR CP/M COMPATIBILITY */
816 case 0x2b: /* SET SYSTEM DATE */
817 case 0x2d: /* SET SYSTEM TIME */
818 case 0x37: /* "SWITCHAR" - GET SWITCH CHARACTER
819 "SWITCHAR" - SET SWITCH CHARACTER
820 "AVAILDEV" - SPECIFY \DEV\ PREFIX USE */
821 case 0x54: /* GET VERIFY FLAG */
822 case 0x61: /* UNUSED */
823 case 0x6b: /* NULL FUNCTION */
827 case 0x67: /* SET HANDLE COUNT */
831 case 0x0e: /* SELECT DEFAULT DRIVE */
832 SetDefaultDrive(context
);
835 case 0x19: /* GET CURRENT DEFAULT DRIVE */
836 GetDefaultDrive(context
);
839 case 0x1b: /* GET ALLOCATION INFORMATION FOR DEFAULT DRIVE */
840 GetDefDriveAllocInfo(context
);
843 case 0x1c: /* GET ALLOCATION INFORMATION FOR SPECIFIC DRIVE */
844 GetDriveAllocInfo(context
);
847 case 0x1f: /* GET DRIVE PARAMETER BLOCK FOR DEFAULT DRIVE */
848 case 0x32: /* GET DOS DRIVE PARAMETER BLOCK FOR SPECIFIC DRIVE */
852 case 0x25: /* SET INTERRUPT VECTOR */
853 /* Ignore any attempt to set a segment vector */
856 case 0x26: /* CREATE NEW PROGRAM SEGMENT PREFIX */
859 case 0x2a: /* GET SYSTEM DATE */
860 GetSystemDate(context
);
863 case 0x2c: /* GET SYSTEM TIME */
864 GetSystemTime(context
);
867 case 0x30: /* GET DOS VERSION */
868 fprintf(stderr
,"int21: GetDosVersion\n");
869 EAX
= DosVersion
; /* Hey folks, this is DOS V3.3! */
870 EBX
= 0x0012; /* 0x123456 is Wine's serial # */
874 case 0x31: /* TERMINATE AND STAY RESIDENT */
877 case 0x33: /* MULTIPLEXED */
878 switch (EAX
& 0xff) {
879 case 0x00: /* GET CURRENT EXTENDED BREAK STATE */
884 case 0x01: /* SET EXTENDED BREAK STATE */
887 case 0x02: /* GET AND SET EXTENDED CONTROL-BREAK CHECKING STATE */
891 case 0x05: /* GET BOOT DRIVE */
892 EDX
= (EDX
& 0xff00L
) | 2;
893 /* c: is Wine's bootdrive */
896 case 0x06: /* GET TRUE VERSION NUMBER */
905 case 0x34: /* GET ADDRESS OF INDOS FLAG */
906 GetInDosFlag(context
);
909 case 0x35: /* GET INTERRUPT VECTOR */
910 /* Return a NULL segment selector - this will bomb,
911 if anyone ever tries to use it */
916 case 0x36: /* GET FREE DISK SPACE */
917 GetFreeDiskSpace(context
);
920 case 0x38: /* GET COUNTRY-SPECIFIC INFORMATION */
922 EAX
|= 0x02; /* no country support available */
926 case 0x39: /* "MKDIR" - CREATE SUBDIRECTORY */
930 case 0x3a: /* "RMDIR" - REMOVE SUBDIRECTORY */
934 case 0x3b: /* "CHDIR" - SET CURRENT DIRECTORY */
938 case 0x3c: /* "CREAT" - CREATE OR TRUNCATE FILE */
942 case 0x3d: /* "OPEN" - OPEN EXISTING FILE */
943 OpenExistingFile(context
);
946 case 0x3e: /* "CLOSE" - CLOSE FILE */
950 case 0x3f: /* "READ" - READ FROM FILE OR DEVICE */
954 case 0x40: /* "WRITE" - WRITE TO FILE OR DEVICE */
958 case 0x41: /* "UNLINK" - DELETE FILE */
962 case 0x42: /* "LSEEK" - SET CURRENT FILE POSITION */
966 case 0x43: /* FILE ATTRIBUTES */
967 switch (EAX
& 0xff) {
969 GetFileAttributes(context
);
972 SetFileAttributes(context
);
977 case 0x44: /* IOCTL */
981 case 0x45: /* "DUP" - DUPLICATE FILE HANDLE */
982 case 0x46: /* "DUP2", "FORCEDUP" - FORCE DUPLICATE FILE HANDLE */
983 DupeFileHandle(context
);
986 case 0x47: /* "CWD" - GET CURRENT DIRECTORY */
987 GetCurrentDirectory(context
);
988 EAX
= (EAX
& 0xffff0000L
) | 0x0100;
989 /* many Microsoft products for Windows rely on this */
992 case 0x48: /* ALLOCATE MEMORY */
993 AllocateMemory(context
);
996 case 0x49: /* FREE MEMORY */
1000 case 0x4a: /* RESIZE MEMORY BLOCK */
1001 ResizeMemoryBlock(context
);
1004 case 0x4b: /* "EXEC" - LOAD AND/OR EXECUTE PROGRAM */
1005 ExecProgram(context
);
1008 case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */
1009 fprintf(stderr
,"int21: DosExit\n");
1013 case 0x4d: /* GET RETURN CODE */
1014 GetReturnCode(context
);
1017 case 0x4e: /* "FINDFIRST" - FIND FIRST MATCHING FILE */
1021 case 0x4f: /* "FINDNEXT" - FIND NEXT MATCHING FILE */
1025 case 0x52: /* "SYSVARS" - GET LIST OF LISTS */
1026 GetSysVars(context
);
1029 case 0x56: /* "RENAME" - RENAME FILE */
1030 RenameFile(context
);
1033 case 0x57: /* FILE DATE AND TIME */
1034 switch (EAX
& 0xff) {
1036 GetFileDateTime(context
);
1039 SetFileDateTime(context
);
1044 case 0x58: /* GET OR SET MEMORY/UMB ALLOCATION STRATEGY */
1045 switch (EAX
& 0xff) {
1047 EAX
= (EAX
& 0xffffff00L
) | 0x01L
;
1059 case 0x59: /* GET EXTENDED ERROR INFO */
1060 GetExtendedErrorInfo(context
);
1063 case 0x5a: /* CREATE TEMPORARY FILE */
1064 CreateTempFile(context
);
1067 case 0x5b: /* CREATE NEW FILE */
1068 CreateNewFile(context
);
1071 case 0x5c: /* "FLOCK" - RECORD LOCKING */
1075 case 0x5d: /* NETWORK */
1077 EAX
= (EAX
& 0xfffff00L
) | NoNetwork
; /* network software not installed */
1081 case 0x5f: /* NETWORK */
1082 switch (EAX
& 0xffL
) {
1083 case 0x07: /* ENABLE DRIVE */
1084 if (!DOS_EnableDrive(EDX
& 0xffL
)) {
1085 Error(InvalidDrive
, EC_MediaError
, EL_Disk
);
1086 EAX
= (EAX
& 0xfffff00L
) | InvalidDrive
;
1093 case 0x08: /* DISABLE DRIVE */
1094 if (!DOS_DisableDrive(EDX
& 0xffL
)) {
1095 Error(InvalidDrive
, EC_MediaError
, EL_Disk
);
1096 EAX
= (EAX
& 0xfffff00L
) | InvalidDrive
;
1104 EAX
= (EAX
& 0xfffff00L
) | NoNetwork
; /* network software not installed */
1110 case 0x60: /* "TRUENAME" - CANONICALIZE FILENAME OR PATH */
1111 GetTrueFileName(context
);
1114 case 0x62: /* GET CURRENT PSP ADDRESS */
1115 GetCurrentPSP(context
);
1118 case 0x65: /* GET EXTENDED COUNTRY INFORMATION */
1119 GetExtendedCountryInfo(context
);
1122 case 0x66: /* GLOBAL CODE PAGE TABLE */
1123 switch (EAX
& 0xffL
) {
1136 case 0x68: /* "FFLUSH" - COMMIT FILE */
1140 case 0x69: /* DISK SERIAL NUMBER */
1141 switch (EAX
& 0xff) {
1143 GetDiskSerialNumber(context
);
1146 SetDiskSerialNumber(context
);
1151 case 0x6a: /* COMMIT FILE */
1156 fprintf(stderr
,"Unable to handle int 0x21 %x\n", context
->sc_eax
);
1163 /**********************************************************************
1168 static struct sigcontext_struct
*context
= NULL
;
1171 context
= malloc(sizeof(struct sigcontext_struct
));
1173 /* fprintf(stderr, "DOS3: AX %04x, BX %04x, CX %04x, DX %04x, SI %04x, DI %04x, DS %04x, ES %04x\n",
1174 _AX, _BX, _CX, _DX, _SI, _DI, _DS, _ES);