11 #include "prototypes.h"
18 static char Copyright
[] = "copyright Erik Bos, 1993";
20 WORD ExtendedError
, CodePage
= 437;
21 BYTE ErrorClass
, Action
, ErrorLocus
;
24 extern char TempDirectory
[];
26 static int Error(int e
, int class, int el
)
29 Action
= SA_Ask4Retry
;
36 static void Barf(struct sigcontext_struct
*context
)
38 fprintf(stderr
, "int21: unknown/not implemented parameters:\n");
39 fprintf(stderr
, "int21: AX %04x, BX %04x, CX %04x, DX %04x, "
40 "SI %04x, DI %04x, DS %04x, ES %04x\n",
41 AX
, BX
, CX
, DX
, SI
, DI
, DS
, ES
);
44 void ChopOffWhiteSpace(char *string
)
48 for (length
= strlen(string
) ; length
; length
--)
49 if (string
[length
] == ' ')
50 string
[length
] = '\0';
53 static void CreateBPB(int drive
, BYTE
*data
)
60 setword(&data
[6], 240);
61 setword(&data
[8], 64000);
63 setword(&data
[0x0b], 40);
64 setword(&data
[0x0d], 56);
65 setword(&data
[0x0f], 2);
66 setword(&data
[0x11], 0);
67 setword(&data
[0x1f], 800);
69 setword(&data
[0x22], 1);
75 setword(&data
[6], 240);
76 setword(&data
[8], 2880);
78 setword(&data
[0x0b], 6);
79 setword(&data
[0x0d], 18);
80 setword(&data
[0x0f], 2);
81 setword(&data
[0x11], 0);
82 setword(&data
[0x1f], 80);
84 setword(&data
[0x22], 2);
88 static void GetFreeDiskSpace(struct sigcontext_struct
*context
)
94 drive
= DOS_GetDefaultDrive();
96 drive
= (EDX
& 0xffL
) - 1;
98 if (!DOS_ValidDrive(drive
)) {
99 Error(InvalidDrive
, EC_MediaError
, EL_Disk
);
104 if (!DOS_GetFreeSpace(drive
, &size
, &available
)) {
105 Error(GeneralFailure
, EC_MediaError
, EL_Disk
);
110 EAX
= (EAX
& 0xffff0000L
) | 4;
111 ECX
= (ECX
& 0xffff0000L
) | 512;
113 EBX
= (EBX
& 0xffff0000L
) | (available
/ (CX
* AX
));
114 EDX
= (EDX
& 0xffff0000L
) | (size
/ (CX
* AX
));
118 static void SetDefaultDrive(struct sigcontext_struct
*context
)
124 if (!DOS_ValidDrive(drive
)) {
125 Error (InvalidDrive
, EC_MediaError
, EL_Disk
);
128 DOS_SetDefaultDrive(drive
);
129 EAX
= (EAX
&0xffffff00L
) | MAX_DOS_DRIVES
;
134 static void GetDefaultDrive(struct sigcontext_struct
*context
)
136 EAX
= (EAX
& 0xffffff00L
) | DOS_GetDefaultDrive();
140 static void GetDriveAllocInfo(struct sigcontext_struct
*context
)
143 long size
, available
;
148 if (!DOS_ValidDrive(drive
)) {
149 EAX
= (EAX
& 0xffff0000L
) | 4;
150 ECX
= (ECX
& 0xffff0000L
) | 512;
151 EDX
= (EDX
& 0xffff0000L
);
152 Error (InvalidDrive
, EC_MediaError
, EL_Disk
);
156 if (!DOS_GetFreeSpace(drive
, &size
, &available
)) {
157 Error(GeneralFailure
, EC_MediaError
, EL_Disk
);
162 EAX
= (EAX
& 0xffff0000L
) | 4;
163 ECX
= (ECX
& 0xffff0000L
) | 512;
164 EDX
= (EDX
& 0xffff0000L
) | (size
/ (CX
* AX
));
168 DS
= segment(mediaID
);
169 EBX
= offset(mediaID
);
173 static void GetDefDriveAllocInfo(struct sigcontext_struct
*context
)
175 EDX
= DOS_GetDefaultDrive();
176 GetDriveAllocInfo(context
);
179 static void GetDrivePB(struct sigcontext_struct
*context
)
181 Error (InvalidDrive
, EC_MediaError
, EL_Disk
);
182 EAX
= (EAX
& 0xffff0000L
) | 0xffL
;
183 /* I'm sorry but I only got networked drives :-) */
186 static void ReadFile(struct sigcontext_struct
*context
)
191 /* can't read from stdout / stderr */
193 if ((BX
== 1) || (BX
== 2)) {
194 Error (InvalidHandle
, EL_Unknown
, EC_Unknown
);
195 EAX
= (EAX
& 0xffff0000L
) | InvalidHandle
;
200 ptr
= pointer (DS
,DX
);
205 EAX
= (EAX
& 0xffff0000L
) | 1;
209 size
= read(BX
, ptr
, CX
);
211 Error (ReadFault
, 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 (GeneralFailure
, EC_SystemFailure
, EL_Unknown
);
228 EAX
= (EAX
& 0xffffff00L
) | ExtendedError
;
233 EAX
= (EAX
& 0xffff0000L
) | size
;
238 static void WriteFile(struct sigcontext_struct
*context
)
243 ptr
= pointer (DS
,DX
);
246 Error (InvalidHandle
, EC_Unknown
, EL_Unknown
);
253 for (x
= 0;x
!= CX
;x
++) {
254 fprintf(stderr
, "%c", *ptr
++);
259 EAX
= (EAX
& 0xffffff00L
) | CX
;
262 size
= write(BX
, ptr
, CX
);
264 Error (WriteFault
, EC_Unknown
, EL_Unknown
);
265 EAX
= (EAX
& 0xffffff00L
) | ExtendedError
;
272 Error (ShareViolation
, EC_Temporary
, EL_Unknown
);
275 Error (InvalidHandle
, EC_AppError
, EL_Unknown
);
278 Error (DiskFull
, EC_MediaError
, EL_Disk
);
281 Error (GeneralFailure
, EC_SystemFailure
, EL_Unknown
);
284 EAX
= (EAX
& 0xffffff00L
) | ExtendedError
;
289 EAX
= (EAX
& 0xffff0000L
) | size
;
294 static void UnlinkFile(struct sigcontext_struct
*context
)
296 if (unlink( GetUnixFileName( pointer(DS
,DX
)) ) == -1) {
301 Error (WriteProtected
, EC_AccessDenied
, EL_Unknown
);
304 Error (LockViolation
, EC_AccessDenied
, EL_Unknown
);
307 Error (ShareViolation
, EC_Temporary
, EL_Unknown
);
310 Error (FileNotFound
, EC_NotFound
, EL_Unknown
);
313 Error (GeneralFailure
, EC_SystemFailure
, EL_Unknown
);
316 EAX
= (EAX
& 0xffffff00L
) | ExtendedError
; SetCflag
;
323 static void SeekFile(struct sigcontext_struct
*context
)
325 int status
, fileoffset
;
327 switch (EAX
& 0xffL
) {
328 case 1: fileoffset
= SEEK_CUR
;
330 case 2: fileoffset
= SEEK_END
;
333 case 0: fileoffset
= SEEK_SET
;
336 status
= lseek(BX
, (CX
* 0x100) + DX
, fileoffset
);
340 Error (InvalidHandle
, EC_AppError
, EL_Unknown
);
343 Error (DataInvalid
, EC_AppError
, EL_Unknown
);
346 Error (GeneralFailure
, EC_SystemFailure
, EL_Unknown
);
349 EAX
= (EAX
& 0xffffff00L
) | ExtendedError
; SetCflag
;
356 static void GetFileAttributes(struct sigcontext_struct
*context
)
362 static void SetFileAttributes(struct sigcontext_struct
*context
)
367 static void ioctlGetDeviceInfo(struct sigcontext_struct
*context
)
369 WORD handle
= EBX
& 0xffff;
375 EDX
= (EDX
& 0xffff0000) | 0x80d3;
380 EDX
= (EDX
& 0xffff0000) | 0x50;
385 static void ioctlGenericBlkDevReq(struct sigcontext_struct
*context
)
387 BYTE
*dataptr
= pointer(DS
, DX
);
391 drive
= DOS_GetDefaultDrive();
393 drive
= (EBX
& 0xffL
) - 1;
395 if ((ECX
& 0xff00L
) != 0x0800) {
399 switch (ECX
& 0xffL
) {
400 case 0x60: /* get device parameters */
401 /* used by w4wgrp's winfile */
403 dataptr
[6] = 0; /* media type */
406 dataptr
[1] = 0x05; /* fixed disk */
407 setword(&dataptr
[2], 0x01); /* non removable */
408 setword(&dataptr
[4], 0x300); /* # of cylinders */
412 dataptr
[1] = 0x07; /* block dev, floppy */
413 setword(&dataptr
[2], 0x02); /* removable */
414 setword(&dataptr
[4], 80); /* # of cylinders */
416 CreateBPB(drive
, &dataptr
[7]);
417 EAX
= (EAX
& 0xfffff00L
);
425 static void DupeFileHandle(struct sigcontext_struct
*context
)
427 EAX
= (EAX
& 0xffff0000L
) | dup(BX
);
431 static void GetSystemDate(struct sigcontext_struct
*context
)
437 now
= localtime(<ime
);
439 ECX
= (ECX
& 0xffff0000L
) | (now
->tm_year
+ 1900);
440 EDX
= (EDX
& 0xffff0000L
) | ((now
->tm_mon
+ 1) << 8) | now
->tm_mday
;
441 EAX
= (EAX
& 0xffff0000L
) | now
->tm_wday
;
444 static void GetSystemTime(struct sigcontext_struct
*context
)
450 now
= localtime(<ime
);
452 ECX
= (ECX
& 0xffffff00L
) | (now
->tm_hour
<< 8) | now
->tm_min
;
453 EDX
= (EDX
& 0xffffff00L
) | now
->tm_sec
<< 8;
456 static void GetExtendedErrorInfo(struct sigcontext_struct
*context
)
458 EAX
= (EAX
& 0xffffff00L
) | ExtendedError
;
459 EBX
= (EBX
& 0xffff0000L
) | (0x100 * ErrorClass
) | Action
;
460 ECX
= (ECX
& 0xffff00ffL
) | (0x100 * ErrorLocus
);
463 static void GetInDosFlag(struct sigcontext_struct
*context
)
465 const BYTE InDosFlag
= 0;
467 ES
= (ES
& 0xffff0000L
) | segment(InDosFlag
);
468 EBX
= (EBX
& 0xffff0000L
) | offset(InDosFlag
);
471 static void CreateFile(struct sigcontext_struct
*context
)
475 if ((handle
= open(GetUnixFileName( pointer(DS
,DX
)), O_CREAT
| O_TRUNC
)) == -1) {
480 Error (WriteProtected
, EC_AccessDenied
, EL_Unknown
);
483 Error (CanNotMakeDir
, EC_AccessDenied
, EL_Unknown
);
487 Error (NoMoreFiles
, EC_MediaError
, EL_Unknown
);
489 Error (FileExists
, EC_Exists
, EL_Disk
);
492 Error (DiskFull
, EC_MediaError
, EL_Disk
);
495 Error (GeneralFailure
, EC_SystemFailure
, EL_Unknown
);
498 EAX
= (EAX
& 0xffffff00L
) | ExtendedError
;
503 EBX
= (EBX
& 0xffff0000L
) | handle
;
504 EAX
= (EAX
& 0xffffff00L
) | NoError
;
508 static void OpenExistingFile(struct sigcontext_struct
*context
)
512 fprintf(stderr
,"OpenExistingFile (%s)\n", pointer(DS
,DX
));
514 if ((handle
= open(GetUnixFileName(pointer(DS
,DX
)), O_RDWR
)) == -1) {
519 Error (WriteProtected
, EC_AccessDenied
, EL_Unknown
);
522 Error (CanNotMakeDir
, EC_AccessDenied
, EL_Unknown
);
526 Error (NoMoreFiles
, EC_MediaError
, EL_Unknown
);
528 Error (FileExists
, EC_Exists
, EL_Disk
);
531 Error (DiskFull
, EC_MediaError
, EL_Disk
);
534 Error (FileNotFound
, EC_MediaError
, EL_Disk
);
537 Error (GeneralFailure
, EC_SystemFailure
, EL_Unknown
);
540 EAX
= (EAX
& 0xffffff00L
) | ExtendedError
;
545 EBX
= (EBX
& 0xffff0000L
) | handle
;
546 EAX
= (EAX
& 0xffffff00L
) | NoError
;
550 static void CloseFile(struct sigcontext_struct
*context
)
552 if (close(BX
) == -1) {
555 Error (InvalidHandle
, EC_AppError
, EL_Unknown
);
558 Error (GeneralFailure
, EC_SystemFailure
, EL_Unknown
);
561 EAX
= (EAX
& 0xffffff00L
) | ExtendedError
;
566 EAX
= (EAX
& 0xffffff00L
) | NoError
;
570 static void RenameFile(struct sigcontext_struct
*context
)
572 char *newname
, *oldname
;
574 fprintf(stderr
,"int21: renaming %s to %s\n",
575 pointer(DS
,DX
), pointer(ES
,DI
) );
577 oldname
= GetUnixFileName( pointer(DS
,DX
) );
578 newname
= GetUnixFileName( pointer(ES
,DI
) );
580 rename( oldname
, newname
);
584 static void GetTrueFileName(struct sigcontext_struct
*context
)
586 fprintf(stderr
,"int21: GetTrueFileName of %s\n", pointer(DS
,SI
) );
588 strncpy(pointer(ES
,DI
), pointer(DS
,SI
), strlen(pointer(DS
,SI
)) & 0x7f);
592 static void MakeDir(struct sigcontext_struct
*context
)
596 fprintf(stderr
,"int21: makedir %s\n", pointer(DS
,DX
) );
598 if ((dirname
= GetUnixFileName( pointer(DS
,DX
) ))== NULL
) {
599 EAX
= (EAX
& 0xffffff00L
) | CanNotMakeDir
;
604 if (mkdir(dirname
,0) == -1) {
605 EAX
= (EAX
& 0xffffff00L
) | CanNotMakeDir
;
612 static void ChangeDir(struct sigcontext_struct
*context
)
615 char *dirname
= pointer(DS
,DX
);
616 drive
= DOS_GetDefaultDrive();
617 fprintf(stderr
,"int21: changedir %s\n", dirname
);
618 if (dirname
!= NULL
&& dirname
[1] == ':') {
619 drive
= toupper(dirname
[0]) - 'A';
622 DOS_ChangeDir(drive
, dirname
);
625 static void RemoveDir(struct sigcontext_struct
*context
)
629 fprintf(stderr
,"int21: removedir %s\n", pointer(DS
,DX
) );
631 if ((dirname
= GetUnixFileName( pointer(DS
,DX
) ))== NULL
) {
632 EAX
= (EAX
& 0xffffff00L
) | CanNotMakeDir
;
638 if (strcmp(unixname,DosDrives[drive].CurrentDirectory)) {
639 EAX = (EAX & 0xffffff00L) | CanNotRemoveCwd;
643 if (rmdir(dirname
) == -1) {
644 EAX
= (EAX
& 0xffffff00L
) | CanNotMakeDir
;
650 static void AllocateMemory(struct sigcontext_struct
*context
)
654 fprintf(stderr
,"int21: malloc %d bytes\n", BX
* 0x10 );
656 /* if ((ptr = (void *) memalign((size_t) (BX * 0x10), 0x10)) == NULL) {
657 EAX = (EAX & 0xffffff00L) | OutOfMemory;
658 EBX = (EBX & 0xffffff00L);
661 fprintf(stderr,"int21: malloc (ptr = %d)\n", ptr );
663 EAX = (EAX & 0xffff0000L) | segment(ptr);
669 static void FreeMemory(struct sigcontext_struct
*context
)
671 fprintf(stderr
,"int21: freemem (ptr = %d)\n", ES
* 0x10 );
673 free((void *)(ES * 0x10));
678 static void ResizeMemoryBlock(struct sigcontext_struct
*context
)
682 fprintf(stderr
,"int21: realloc (ptr = %d)\n", ES
* 0x10 );
684 /* if ((ptr = (void *) realloc((void *)(ES * 0x10), (size_t) BX * 0x10)) == NULL) {
685 EAX = (EAX & 0xffffff00L) | OutOfMemory;
686 EBX = (EBX & 0xffffff00L);
689 EBX = (EBX & 0xffff0000L) | segment(ptr);
694 static void ExecProgram(struct sigcontext_struct
*context
)
696 execl("wine", GetUnixFileName( pointer(DS
,DX
)) );
699 static void GetReturnCode(struct sigcontext_struct
*context
)
701 EAX
= (EAX
& 0xffffff00L
) | NoError
; /* normal exit */
704 static void FindNext(struct sigcontext_struct
*context
)
706 struct dosdirent
*dp
;
708 dp
= (struct dosdirent
*)(dta
+ 0x0d);
711 if ((dp
= DOS_readdir(dp
)) == NULL
) {
713 Error(NoMoreFiles
, EC_MediaError
, EL_Disk
);
714 EAX
= (EAX
& 0xffffff00L
) | NoMoreFiles
;
718 } while (*(dta
+ 0x0c) != dp
->attribute
);
720 setword(&dta
[0x16], 0x1234); /* time */
721 setword(&dta
[0x18], 0x1234); /* date */
722 setdword(&dta
[0x1a], dp
->filesize
);
723 strncpy(dta
+ 0x1e, dp
->filename
, 13);
725 EAX
= (EAX
& 0xffffff00L
);
730 static void FindFirst(struct sigcontext_struct
*context
)
732 BYTE drive
, *path
= pointer(DS
, DX
);
733 struct dosdirent
*dp
;
735 if (path
[1] == ':') {
736 drive
= (islower(*path
) ? toupper(*path
) : *path
) - 'A';
738 if (!DOS_ValidDrive(drive
)) {
739 Error(InvalidDrive
, EC_MediaError
, EL_Disk
);
740 EAX
= (EAX
& 0xffffff00L
) | InvalidDrive
;
745 drive
= DOS_GetDefaultDrive();
748 memset(dta
+ 1 , '?', 11);
749 *(dta
+ 0x0c) = ECX
& (FA_LABEL
| FA_DIREC
);
751 if (ECX
& FA_LABEL
) {
752 /* return volume label */
754 if (DOS_GetVolumeLabel(drive
) != NULL
)
755 strncpy(dta
+ 0x1e, DOS_GetVolumeLabel(drive
), 8);
757 EAX
= (EAX
& 0xffffff00L
);
762 if ((dp
= DOS_opendir(path
)) == NULL
) {
763 Error(PathNotFound
, EC_MediaError
, EL_Disk
);
764 EAX
= (EAX
& 0xffffff00L
) | FileNotFound
;
768 /* strncpy(dta + 1, AsciizToFCB(dp->filemask), 11); */
770 /* *((BYTE *) ((void*)dta + 0x0d)) = (BYTE *) dp; */
772 *((struct dosdirent
*)(dta
+ 0x0d))
778 static void GetSysVars(struct sigcontext_struct
*context
)
780 /* return a null pointer, to encourage anyone who tries to
784 EBX
= (EBX
& 0xffff0000L
);
788 static void GetFileDateTime(struct sigcontext_struct
*context
)
791 struct stat filestat
;
794 if ((filename
= GetUnixFileName( pointer(DS
,DX
) ))== NULL
) {
795 EAX
= (EAX
& 0xffffff00L
) | FileNotFound
;
799 stat(filename
, &filestat
);
801 now
= localtime (&filestat
.st_mtime
);
803 ECX
= (ECX
& 0xffff0000L
) | ((now
->tm_hour
* 0x2000) + (now
->tm_min
* 0x20) + now
->tm_sec
/2);
804 EDX
= (EDX
& 0xffff0000L
) | ((now
->tm_year
* 0x200) + (now
->tm_mon
* 0x20) + now
->tm_mday
);
809 static void SetFileDateTime(struct sigcontext_struct
*context
)
812 struct utimbuf filetime
;
814 filename
= GetUnixFileName( pointer(DS
,DX
) );
816 filetime
.actime
= 0L;
817 filetime
.modtime
= filetime
.actime
;
819 utime(filename
, &filetime
);
823 static void CreateTempFile(struct sigcontext_struct
*context
)
828 sprintf(temp
,"%s\\win%d.tmp",TempDirectory
,(int) getpid());
830 fprintf(stderr
,"CreateTempFile %s\n",temp
);
832 handle
= open(GetUnixFileName(temp
), O_CREAT
| O_TRUNC
| O_RDWR
);
835 EAX
= (EAX
& 0xffffff00L
) | WriteProtected
;
840 strcpy(pointer(DS
,DX
), temp
);
842 EAX
= (EAX
& 0xffff0000L
) | handle
;
846 static void CreateNewFile(struct sigcontext_struct
*context
)
850 if ((handle
= open(GetUnixFileName( pointer(DS
,DX
) ), O_CREAT
| O_TRUNC
| O_RDWR
)) == -1) {
851 EAX
= (EAX
& 0xffffff00L
) | WriteProtected
;
856 EAX
= (EAX
& 0xffff0000L
) | handle
;
860 static void FileLock(struct sigcontext_struct
*context
)
862 fprintf(stderr
, "int21: flock()\n");
865 static void GetExtendedCountryInfo(struct sigcontext_struct
*context
)
870 static void GetCurrentDirectory(struct sigcontext_struct
*context
)
874 if ((EDX
& 0xffL
) == 0)
875 drive
= DOS_GetDefaultDrive();
877 drive
= (EDX
& 0xffL
)-1;
879 if (!DOS_ValidDrive(drive
)) {
880 EAX
= (EAX
& 0xffffff00L
) | InvalidDrive
;
885 strcpy(pointer(DS
,SI
), DOS_GetCurrentDir(drive
) );
889 static void GetCurrentPSP(struct sigcontext_struct
*context
)
894 static void GetDiskSerialNumber(struct sigcontext_struct
*context
)
897 BYTE
*dataptr
= pointer(DS
, DX
);
900 if ((EBX
& 0xffL
) == 0)
901 drive
= DOS_GetDefaultDrive();
903 drive
= (EBX
& 0xffL
) - 1;
905 if (!DOS_ValidDrive(drive
)) {
906 EAX
= (EAX
& 0xffffff00L
) |InvalidDrive
;
911 DOS_GetSerialNumber(drive
, &serialnumber
);
914 setdword(&dataptr
[2], serialnumber
);
915 strncpy(dataptr
+ 6, DOS_GetVolumeLabel(drive
), 8);
916 strncpy(dataptr
+ 0x11, "FAT16 ", 8);
918 EAX
= (EAX
& 0xffffff00L
);
922 static void SetDiskSerialNumber(struct sigcontext_struct
*context
)
925 BYTE
*dataptr
= pointer(DS
, DX
);
928 if ((EBX
& 0xffL
) == 0)
929 drive
= DOS_GetDefaultDrive();
931 drive
= (EBX
& 0xffL
) - 1;
933 if (!DOS_ValidDrive(drive
)) {
934 EAX
= (EAX
& 0xffffff00L
) | InvalidDrive
;
939 serialnumber
= dataptr
[1] + (dataptr
[2] << 8) + (dataptr
[3] << 16) +
942 DOS_SetSerialNumber(drive
, serialnumber
);
943 EAX
= (EAX
& 0xffffff00L
) | 1L;
947 static void DumpFCB(BYTE
*fcb
)
953 for (y
= 0; y
!=2 ; y
++) {
954 for (x
= 0; x
!=15;x
++)
955 fprintf(stderr
, "%02x ", *fcb
++);
956 fprintf(stderr
,"\n");
960 /* microsoft's programmers should be shot for using CP/M style int21
961 calls in Windows for Workgroup's winfile.exe */
963 static void FindFirstFCB(struct sigcontext_struct
*context
)
965 BYTE
*fcb
= pointer(DS
, DX
);
973 drive
= DOS_GetDefaultDrive();
975 if (*(fcb
- 7) == 0xff) {
976 if (*(fcb
- 1) == FA_DIREC
) {
977 /* return volume label */
979 memset(dta
, ' ', 11);
980 if (DOS_GetVolumeLabel(drive
) != NULL
)
981 strncpy(dta
, DOS_GetVolumeLabel(drive
), 8);
982 *(dta
+ 0x0b) = FA_DIREC
;
984 EAX
= (EAX
& 0xffffff00L
);
991 static void DeleteFileFCB(struct sigcontext_struct
*context
)
993 BYTE
*fcb
= pointer(DS
, DX
);
995 struct dosdirent
*dp
;
996 char temp
[256], *ptr
;
1003 drive
= DOS_GetDefaultDrive();
1005 strcpy(temp
, DOS_GetCurrentDir(drive
));
1007 strncat(temp
, fcb
+ 1, 8);
1008 ChopOffWhiteSpace(temp
);
1009 strncat(temp
, fcb
+ 9, 3);
1010 ChopOffWhiteSpace(temp
);
1012 if ((dp
= DOS_opendir(temp
)) == NULL
) {
1013 Error(InvalidDrive
, EC_MediaError
, EL_Disk
);
1014 EAX
= (EAX
& 0xffffff00L
) | 0xffL
;
1018 strcpy(temp
, DOS_GetCurrentDir(drive
) );
1021 ptr
= temp
+ strlen(temp
);
1023 while (DOS_readdir(dp
) != NULL
)
1025 strcpy(ptr
, dp
->filename
);
1026 fprintf(stderr
, "int21: delete file %s\n", temp
);
1027 /* unlink(GetUnixFileName(temp)); */
1031 EAX
= (EAX
& 0xffffff00L
);
1034 static void RenameFileFCB(struct sigcontext_struct
*context
)
1036 BYTE
*fcb
= pointer(DS
, DX
);
1038 struct dosdirent
*dp
;
1039 char temp
[256], oldname
[256], newname
[256], *oldnameptr
, *newnameptr
;
1046 drive
= DOS_GetDefaultDrive();
1048 strcpy(temp
, DOS_GetCurrentDir(drive
));
1050 strncat(temp
, fcb
+ 1, 8);
1051 ChopOffWhiteSpace(temp
);
1052 strncat(temp
, fcb
+ 9, 3);
1053 ChopOffWhiteSpace(temp
);
1055 if ((dp
= DOS_opendir(temp
)) == NULL
) {
1056 Error(InvalidDrive
, EC_MediaError
, EL_Disk
);
1057 EAX
= (EAX
& 0xffffff00L
) | 0xffL
;
1061 strcpy(oldname
, DOS_GetCurrentDir(drive
) );
1062 strcat(oldname
, "\\");
1063 oldnameptr
= oldname
+ strlen(oldname
);
1065 strcpy(newname
, DOS_GetCurrentDir(drive
) );
1066 strcat(newname
, "\\");
1067 newnameptr
= newname
+ strlen(newname
);
1069 while (DOS_readdir(dp
) != NULL
)
1071 strcpy(oldnameptr
, dp
->filename
);
1072 strcpy(newnameptr
, fcb
+ 1);
1073 fprintf(stderr
, "int21: renamefile %s -> %s\n", oldname
, newname
);
1077 EAX
= (EAX
& 0xffffff00L
);
1080 /************************************************************************/
1082 int do_int21(struct sigcontext_struct
* context
)
1086 if (Options
.relay_debug
)
1088 printf("int21: AX %04x, BX %04x, CX %04x, DX %04x, "
1089 "SI %04x, DI %04x, DS %04x, ES %04x\n",
1090 AX
, BX
, CX
, DX
, SI
, DI
, DS
, ES
);
1093 ah
= (EAX
>> 8) & 0xffL
;
1097 GetExtendedErrorInfo(context
);
1105 case 0x00: /* TERMINATE PROGRAM */
1108 case 0x01: /* READ CHARACTER FROM STANDARD INPUT, WITH ECHO */
1109 case 0x02: /* WRITE CHARACTER TO STANDARD OUTPUT */
1110 case 0x03: /* READ CHARACTER FROM STDAUX */
1111 case 0x04: /* WRITE CHARACTER TO STDAUX */
1112 case 0x05: /* WRITE CHARACTER TO PRINTER */
1113 case 0x06: /* DIRECT CONSOLE IN/OUTPUT */
1114 case 0x07: /* DIRECT CHARACTER INPUT, WITHOUT ECHO */
1115 case 0x08: /* CHARACTER INPUT WITHOUT ECHO */
1116 case 0x09: /* WRITE STRING TO STANDARD OUTPUT */
1117 case 0x0a: /* BUFFERED INPUT */
1118 case 0x0b: /* GET STDIN STATUS */
1119 case 0x0c: /* FLUSH BUFFER AND READ STANDARD INPUT */
1120 case 0x0f: /* OPEN FILE USING FCB */
1121 case 0x10: /* CLOSE FILE USING FCB */
1122 case 0x12: /* FIND NEXT MATCHING FILE USING FCB */
1123 case 0x14: /* SEQUENTIAL READ FROM FCB FILE */
1124 case 0x15: /* SEQUENTIAL WRITE TO FCB FILE */
1125 case 0x16: /* CREATE OR TRUNCATE FILE USING FCB */
1126 case 0x21: /* READ RANDOM RECORD FROM FCB FILE */
1127 case 0x22: /* WRITE RANDOM RECORD TO FCB FILE */
1128 case 0x23: /* GET FILE SIZE FOR FCB */
1129 case 0x24: /* SET RANDOM RECORD NUMBER FOR FCB */
1130 case 0x26: /* CREATE NEW PROGRAM SEGMENT PREFIX */
1131 case 0x27: /* RANDOM BLOCK READ FROM FCB FILE */
1132 case 0x28: /* RANDOM BLOCK WRITE TO FCB FILE */
1133 case 0x29: /* PARSE FILENAME INTO FCB */
1134 case 0x2e: /* SET VERIFY FLAG */
1138 case 0x18: /* NULL FUNCTIONS FOR CP/M COMPATIBILITY */
1142 case 0x2b: /* SET SYSTEM DATE */
1143 case 0x2d: /* SET SYSTEM TIME */
1144 case 0x37: /* "SWITCHAR" - GET SWITCH CHARACTER
1145 "SWITCHAR" - SET SWITCH CHARACTER
1146 "AVAILDEV" - SPECIFY \DEV\ PREFIX USE */
1147 case 0x54: /* GET VERIFY FLAG */
1148 case 0x61: /* UNUSED */
1149 case 0x6b: /* NULL FUNCTION */
1154 case 0x0d: /* DISK BUFFER FLUSH */
1155 ResetCflag
; /* dos 6+ only */
1158 case 0x0e: /* SELECT DEFAULT DRIVE */
1159 SetDefaultDrive(context
);
1162 case 0x11: /* FIND FIRST MATCHING FILE USING FCB */
1163 FindFirstFCB(context
);
1166 case 0x13: /* DELETE FILE USING FCB */
1167 DeleteFileFCB(context
);
1170 case 0x17: /* RENAME FILE USING FCB */
1171 RenameFileFCB(context
);
1174 case 0x19: /* GET CURRENT DEFAULT DRIVE */
1175 GetDefaultDrive(context
);
1178 case 0x1a: /* SET DISK TRANSFER AREA ADDRESS */
1179 dta
= pointer(DS
, DX
);
1182 case 0x1b: /* GET ALLOCATION INFORMATION FOR DEFAULT DRIVE */
1183 GetDefDriveAllocInfo(context
);
1186 case 0x1c: /* GET ALLOCATION INFORMATION FOR SPECIFIC DRIVE */
1187 GetDriveAllocInfo(context
);
1190 case 0x1f: /* GET DRIVE PARAMETER BLOCK FOR DEFAULT DRIVE */
1191 GetDrivePB(context
);
1194 case 0x25: /* SET INTERRUPT VECTOR */
1195 /* Ignore any attempt to set a segment vector */
1196 fprintf(stderr
, "int21: set interrupt vector %2x (%04x:%04x)\n", AX
& 0xff, DS
, DX
);
1199 case 0x2a: /* GET SYSTEM DATE */
1200 GetSystemDate(context
);
1203 case 0x2c: /* GET SYSTEM TIME */
1204 GetSystemTime(context
);
1207 case 0x2f: /* GET DISK TRANSFER AREA ADDRESS */
1209 EBX
= (EBX
& 0xffff0000L
) | offset(dta
);
1212 case 0x30: /* GET DOS VERSION */
1213 EAX
= (EAX
& 0xffff0000L
) | DOSVERSION
;
1214 EBX
= (EBX
& 0xffff0000L
) | 0x0012; /* 0x123456 is Wine's serial # */
1215 ECX
= (ECX
& 0xffff0000L
) | 0x3456;
1218 case 0x31: /* TERMINATE AND STAY RESIDENT */
1222 case 0x32: /* GET DOS DRIVE PARAMETER BLOCK FOR SPECIFIC DRIVE */
1223 GetDrivePB(context
);
1226 case 0x33: /* MULTIPLEXED */
1227 switch (EAX
& 0xff) {
1228 case 0x00: /* GET CURRENT EXTENDED BREAK STATE */
1233 case 0x01: /* SET EXTENDED BREAK STATE */
1236 case 0x02: /* GET AND SET EXTENDED CONTROL-BREAK CHECKING STATE*/
1240 case 0x05: /* GET BOOT DRIVE */
1241 EDX
= (EDX
& 0xff00L
) | 2;
1242 /* c: is Wine's bootdrive */
1245 case 0x06: /* GET TRUE VERSION NUMBER */
1254 case 0x34: /* GET ADDRESS OF INDOS FLAG */
1255 GetInDosFlag(context
);
1258 case 0x35: /* GET INTERRUPT VECTOR */
1259 /* Return a NULL segment selector - this will bomb,
1260 if anyone ever tries to use it */
1261 fprintf(stderr
, "int21: get interrupt vector %2x\n", AX
& 0xff);
1266 case 0x36: /* GET FREE DISK SPACE */
1267 GetFreeDiskSpace(context
);
1270 case 0x38: /* GET COUNTRY-SPECIFIC INFORMATION */
1272 EAX
|= 0x02; /* no country support available */
1276 case 0x39: /* "MKDIR" - CREATE SUBDIRECTORY */
1280 case 0x3a: /* "RMDIR" - REMOVE SUBDIRECTORY */
1284 case 0x3b: /* "CHDIR" - SET CURRENT DIRECTORY */
1288 case 0x3c: /* "CREAT" - CREATE OR TRUNCATE FILE */
1289 CreateFile(context
);
1292 case 0x3d: /* "OPEN" - OPEN EXISTING FILE */
1293 OpenExistingFile(context
);
1296 case 0x3e: /* "CLOSE" - CLOSE FILE */
1300 case 0x3f: /* "READ" - READ FROM FILE OR DEVICE */
1304 case 0x40: /* "WRITE" - WRITE TO FILE OR DEVICE */
1308 case 0x41: /* "UNLINK" - DELETE FILE */
1309 UnlinkFile(context
);
1312 case 0x42: /* "LSEEK" - SET CURRENT FILE POSITION */
1316 case 0x43: /* FILE ATTRIBUTES */
1317 switch (EAX
& 0xffL
)
1320 GetFileAttributes(context
);
1323 SetFileAttributes(context
);
1328 case 0x44: /* IOCTL */
1332 ioctlGetDeviceInfo(context
);
1336 ioctlGenericBlkDevReq(context
);
1346 case 0x45: /* "DUP" - DUPLICATE FILE HANDLE */
1347 case 0x46: /* "DUP2", "FORCEDUP" - FORCE DUPLICATE FILE HANDLE */
1348 DupeFileHandle(context
);
1351 case 0x47: /* "CWD" - GET CURRENT DIRECTORY */
1352 GetCurrentDirectory(context
);
1353 EAX
= (EAX
& 0xffff0000L
) | 0x0100;
1354 /* intlist: many Microsoft products for Windows rely on this */
1357 case 0x48: /* ALLOCATE MEMORY */
1358 AllocateMemory(context
);
1361 case 0x49: /* FREE MEMORY */
1362 FreeMemory(context
);
1365 case 0x4a: /* RESIZE MEMORY BLOCK */
1366 ResizeMemoryBlock(context
);
1369 case 0x4b: /* "EXEC" - LOAD AND/OR EXECUTE PROGRAM */
1370 ExecProgram(context
);
1373 case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */
1377 case 0x4d: /* GET RETURN CODE */
1378 GetReturnCode(context
);
1381 case 0x4e: /* "FINDFIRST" - FIND FIRST MATCHING FILE */
1385 case 0x4f: /* "FINDNEXT" - FIND NEXT MATCHING FILE */
1389 case 0x52: /* "SYSVARS" - GET LIST OF LISTS */
1390 GetSysVars(context
);
1393 case 0x56: /* "RENAME" - RENAME FILE */
1394 RenameFile(context
);
1397 case 0x57: /* FILE DATE AND TIME */
1398 switch (EAX
& 0xffL
)
1401 GetFileDateTime(context
);
1404 SetFileDateTime(context
);
1409 case 0x58: /* GET OR SET MEMORY/UMB ALLOCATION STRATEGY */
1410 switch (EAX
& 0xffL
)
1413 EAX
= (EAX
& 0xffffff00L
) | 0x01L
;
1425 case 0x5a: /* CREATE TEMPORARY FILE */
1426 CreateTempFile(context
);
1429 case 0x5b: /* CREATE NEW FILE */
1430 CreateNewFile(context
);
1433 case 0x5c: /* "FLOCK" - RECORD LOCKING */
1437 case 0x5d: /* NETWORK */
1439 /* network software not installed */
1440 EAX
= (EAX
& 0xfffff00L
) | NoNetwork
;
1444 case 0x5f: /* NETWORK */
1445 switch (EAX
& 0xffL
)
1447 case 0x07: /* ENABLE DRIVE */
1448 if (!DOS_EnableDrive(EDX
& 0xffL
))
1450 Error(InvalidDrive
, EC_MediaError
, EL_Disk
);
1451 EAX
= (EAX
& 0xfffff00L
) | InvalidDrive
;
1460 case 0x08: /* DISABLE DRIVE */
1461 if (!DOS_DisableDrive(EDX
& 0xffL
))
1463 Error(InvalidDrive
, EC_MediaError
, EL_Disk
);
1464 EAX
= (EAX
& 0xfffff00L
) | InvalidDrive
;
1474 /* network software not installed */
1475 EAX
= (EAX
& 0xfffff00L
) | NoNetwork
;
1481 case 0x60: /* "TRUENAME" - CANONICALIZE FILENAME OR PATH */
1482 GetTrueFileName(context
);
1485 case 0x62: /* GET CURRENT PSP ADDRESS */
1486 GetCurrentPSP(context
);
1489 case 0x65: /* GET EXTENDED COUNTRY INFORMATION */
1490 GetExtendedCountryInfo(context
);
1493 case 0x66: /* GLOBAL CODE PAGE TABLE */
1494 switch (EAX
& 0xffL
)
1508 case 0x68: /* "FFLUSH" - COMMIT FILE */
1512 case 0x69: /* DISK SERIAL NUMBER */
1513 switch (EAX
& 0xffL
)
1516 GetDiskSerialNumber(context
);
1519 SetDiskSerialNumber(context
);
1524 case 0x6a: /* COMMIT FILE */
1528 case 0x67: /* SET HANDLE COUNT */
1540 /**********************************************************************
1545 do_int21((struct sigcontext_struct
*) _CONTEXT
);
1546 ReturnFromRegisterFunc();