Release 940301
[wine/dcerpc.git] / miscemu / int21.c
blob47368e1f2001e3819ecb94ba47e1bb43fa64d10b
1 #include <time.h>
2 #include <fcntl.h>
3 #include <errno.h>
4 #ifndef __STDC__
5 #include <malloc.h>
6 #endif
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <sys/stat.h>
10 #include <time.h>
11 #include <unistd.h>
12 #include <utime.h>
14 #include "prototypes.h"
15 #include "regfunc.h"
16 #include "windows.h"
17 #include "wine.h"
18 #include "int21.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)
29 ExtendedError = e;
30 ErrorClass = class;
31 Action = SA_Ask4Retry;
32 ErrorLocus = el;
35 void GetFreeDiskSpace(struct sigcontext_struct *context)
37 int drive;
38 long size,available;
40 if (!(EDX & 0xffL))
41 drive = DOS_GetDefaultDrive();
42 else
43 drive = (EDX & 0xffL) - 1;
45 if (!DOS_ValidDrive(drive)) {
46 Error(InvalidDrive, EC_MediaError , EL_Disk);
47 EAX |= 0xffffL;
48 return;
51 if (!DOS_GetFreeSpace(drive, &size, &available)) {
52 Error(GeneralFailure, EC_MediaError , EL_Disk);
53 EAX |= 0xffffL;
54 return;
57 EAX = (EAX & 0xffff0000L) | SectorsPerCluster;
58 ECX = (ECX & 0xffff0000L) | SectorSize;
60 EBX = (EBX & 0xffff0000L) | (available / (CX * AX));
61 EDX = (EDX & 0xffff0000L) | (size / (CX * AX));
62 Error (0,0,0);
65 void SetDefaultDrive(struct sigcontext_struct *context)
67 int drive;
69 drive = EDX & 0xffL;
71 if (!DOS_ValidDrive(drive)) {
72 Error (InvalidDrive, EC_MediaError, EL_Disk);
73 return;
74 } else {
75 DOS_SetDefaultDrive(drive);
76 EAX = (EAX &0xffffff00L) | MAX_DOS_DRIVES;
77 Error (0,0,0);
81 void GetDefaultDrive(struct sigcontext_struct *context)
83 EAX = (EAX & 0xffffff00L) | DOS_GetDefaultDrive();
84 Error (0,0,0);
87 void GetDriveAllocInfo(struct sigcontext_struct *context)
89 int drive;
90 long size, available;
91 BYTE mediaID;
93 drive = EDX & 0xffL;
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);
100 return;
103 if (!DOS_GetFreeSpace(drive, &size, &available)) {
104 Error(GeneralFailure, EC_MediaError , EL_Disk);
105 EAX |= 0xffffL;
106 return;
109 EAX = (EAX & 0xffff0000L) | SectorsPerCluster;
110 ECX = (ECX & 0xffff0000L) | SectorSize;
111 EDX = (EDX & 0xffff0000L) | (size / (CX * AX));
113 mediaID = 0xf0;
115 DS = segment(mediaID);
116 EBX = offset(mediaID);
117 Error (0,0,0);
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)
135 char *ptr;
136 int size;
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;
143 SetCflag;
144 return;
147 ptr = (char *) pointer (DS,DX);
149 if (BX == 0) {
150 *ptr = EOF;
151 Error (0,0,0);
152 EAX = (EAX & 0xffff0000L) | 1;
153 ResetCflag;
154 return;
155 } else {
156 size = read(BX, ptr, CX);
157 if (size == 0) {
158 Error (ReadFault, EC_Unknown, EL_Unknown);
159 EAX = (EAX & 0xffffff00L) | ExtendedError;
160 return;
163 if (size == -1) {
164 switch (errno) {
165 case EAGAIN:
166 Error (ShareViolation, EC_Temporary, EL_Unknown);
167 break;
168 case EBADF:
169 Error (InvalidHandle, EC_AppError, EL_Unknown);
170 break;
171 default:
172 Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
173 break;
175 EAX = (EAX & 0xffffff00L) | ExtendedError;
176 SetCflag;
177 return;
179 Error (0,0,0);
180 EAX = (EAX & 0xffff0000L) | size;
181 ResetCflag;
185 void WriteFile(struct sigcontext_struct *context)
187 char *ptr;
188 int x,size;
190 ptr = (char *) pointer (DS,DX);
192 if (BX == 0) {
193 Error (InvalidHandle, EC_Unknown, EL_Unknown);
194 EAX = InvalidHandle;
195 SetCflag;
196 return;
199 if (BX < 3) {
200 for (x = 0;x != CX;x++) {
201 fprintf(stderr, "%c", *ptr++);
203 fflush(stderr);
205 Error (0,0,0);
206 EAX = (EAX & 0xffffff00L) | CX;
207 ResetCflag;
208 } else {
209 size = write(BX, ptr , CX);
210 if (size == 0) {
211 Error (WriteFault, EC_Unknown, EL_Unknown);
212 EAX = (EAX & 0xffffff00L) | ExtendedError;
213 return;
216 if (size == -1) {
217 switch (errno) {
218 case EAGAIN:
219 Error (ShareViolation, EC_Temporary, EL_Unknown);
220 break;
221 case EBADF:
222 Error (InvalidHandle, EC_AppError, EL_Unknown);
223 break;
224 case ENOSPC:
225 Error (DiskFull, EC_MediaError, EL_Disk);
226 break;
227 default:
228 Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
229 break;
231 EAX = (EAX & 0xffffff00L) | ExtendedError;
232 SetCflag;
233 return;
235 Error (0,0,0);
236 EAX = (EAX & 0xffff0000L) | size;
237 ResetCflag;
241 void UnlinkFile(struct sigcontext_struct *context)
243 if (unlink( GetUnixFileName((char *) pointer(DS,DX)) ) == -1) {
244 switch (errno) {
245 case EACCES:
246 case EPERM:
247 case EROFS:
248 Error (WriteProtected, EC_AccessDenied, EL_Unknown);
249 break;
250 case EBUSY:
251 Error (LockViolation, EC_AccessDenied, EL_Unknown);
252 break;
253 case EAGAIN:
254 Error (ShareViolation, EC_Temporary, EL_Unknown);
255 break;
256 case ENOENT:
257 Error (FileNotFound, EC_NotFound, EL_Unknown);
258 break;
259 default:
260 Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
261 break;
263 EAX = (EAX & 0xffffff00L) | ExtendedError; SetCflag;
264 return;
266 Error (0,0,0);
267 ResetCflag;
270 void SeekFile(struct sigcontext_struct *context)
272 int handle, status, fileoffset;
274 switch (EAX & 0xffL) {
275 case 1: fileoffset = SEEK_CUR;
276 break;
277 case 2: fileoffset = SEEK_END;
278 break;
279 default:
280 case 0: fileoffset = SEEK_SET;
281 break;
283 status = lseek(BX, (CX * 0x100) + DX, fileoffset);
284 if (status == -1) {
285 switch (errno) {
286 case EBADF:
287 Error (InvalidHandle, EC_AppError, EL_Unknown);
288 break;
289 case EINVAL:
290 Error (DataInvalid, EC_AppError, EL_Unknown);
291 break;
292 default:
293 Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
294 break;
296 EAX = (EAX & 0xffffff00L) | ExtendedError; SetCflag;
297 return;
299 Error (0,0,0);
300 ResetCflag;
303 void GetFileAttributes(struct sigcontext_struct *context)
305 EAX &= 0xfffff00L;
306 ResetCflag;
309 void SetFileAttributes(struct sigcontext_struct *context)
311 ResetCflag;
314 void DosIOCTL(struct sigcontext_struct *context)
316 fprintf(stderr,"int21: IOCTL\n");
317 EAX = (EAX & 0xfffff00L) | UnknownUnit;
318 SetCflag;
321 void DupeFileHandle(struct sigcontext_struct *context)
323 EAX = (EAX & 0xffff0000L) | dup(BX);
324 ResetCflag;
327 void GetSystemDate(struct sigcontext_struct *context)
329 struct tm *now;
330 time_t ltime;
332 ltime = time(NULL);
333 now = localtime(&ltime);
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)
342 struct tm *now;
343 time_t ltime;
345 ltime = time(NULL);
346 now = localtime(&ltime);
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)
369 int handle;
371 if ((handle = open(GetUnixFileName((char *) pointer(DS,DX)), O_CREAT | O_TRUNC)) == -1) {
372 switch (errno) {
373 case EACCES:
374 case EPERM:
375 case EROFS:
376 Error (WriteProtected, EC_AccessDenied, EL_Unknown);
377 break;
378 case EISDIR:
379 Error (CanNotMakeDir, EC_AccessDenied, EL_Unknown);
380 break;
381 case ENFILE:
382 case EMFILE:
383 Error (NoMoreFiles, EC_MediaError, EL_Unknown);
384 case EEXIST:
385 Error (FileExists, EC_Exists, EL_Disk);
386 break;
387 case ENOSPC:
388 Error (DiskFull, EC_MediaError, EL_Disk);
389 break;
390 default:
391 Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
392 break;
394 EAX = (EAX & 0xffffff00L) | ExtendedError;
395 SetCflag;
396 return;
398 Error (0,0,0);
399 EBX = (EBX & 0xffff0000L) | handle;
400 EAX = (EAX & 0xffffff00L) | NoError;
401 ResetCflag;
404 void OpenExistingFile(struct sigcontext_struct *context)
406 int handle;
408 fprintf(stderr,"OpenExistingFile (%s)\n",(char *) pointer(DS,DX));
410 if ((handle = open(GetUnixFileName((char*) pointer(DS,DX)), O_RDWR)) == -1) {
411 switch (errno) {
412 case EACCES:
413 case EPERM:
414 case EROFS:
415 Error (WriteProtected, EC_AccessDenied, EL_Unknown);
416 break;
417 case EISDIR:
418 Error (CanNotMakeDir, EC_AccessDenied, EL_Unknown);
419 break;
420 case ENFILE:
421 case EMFILE:
422 Error (NoMoreFiles, EC_MediaError, EL_Unknown);
423 case EEXIST:
424 Error (FileExists, EC_Exists, EL_Disk);
425 break;
426 case ENOSPC:
427 Error (DiskFull, EC_MediaError, EL_Disk);
428 break;
429 case ENOENT:
430 Error (FileNotFound, EC_MediaError, EL_Disk);
431 break;
432 default:
433 Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
434 break;
436 EAX = (EAX & 0xffffff00L) | ExtendedError;
437 SetCflag;
438 return;
440 Error (0,0,0);
441 EBX = (EBX & 0xffff0000L) | handle;
442 EAX = (EAX & 0xffffff00L) | NoError;
443 ResetCflag;
446 void CloseFile(struct sigcontext_struct *context)
448 if (close(BX) == -1) {
449 switch (errno) {
450 case EBADF:
451 Error (InvalidHandle, EC_AppError, EL_Unknown);
452 break;
453 default:
454 Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
455 break;
457 EAX = (EAX & 0xffffff00L) | ExtendedError;
458 SetCflag;
459 return;
461 Error (0,0,0);
462 EAX = (EAX & 0xffffff00L) | NoError;
463 ResetCflag;
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);
476 ResetCflag;
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);
484 ResetCflag;
487 void MakeDir(struct sigcontext_struct *context)
489 char *dirname;
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;
495 SetCflag;
496 return;
499 if (mkdir(dirname,0) == -1) {
500 EAX = (EAX & 0xffffff00L) | CanNotMakeDir;
501 SetCflag;
502 return;
504 ResetCflag;
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)
516 char *dirname;
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;
522 SetCflag;
523 return;
527 if (strcmp(unixname,DosDrives[drive].CurrentDirectory)) {
528 EAX = (EAX & 0xffffff00L) | CanNotRemoveCwd;
529 SetCflag;
532 if (rmdir(dirname) == -1) {
533 EAX = (EAX & 0xffffff00L) | CanNotMakeDir;
534 SetCflag;
536 ResetCflag;
539 void AllocateMemory(struct sigcontext_struct *context)
541 char *ptr;
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 */
548 SetCflag;
550 fprintf(stderr,"int21: malloc (ptr = %d)\n", ptr );
552 EAX = (EAX & 0xffff0000L) | segment((unsigned long) ptr);
553 ResetCflag;
556 void FreeMemory(struct sigcontext_struct *context)
558 fprintf(stderr,"int21: freemem (ptr = %d)\n", ES * 0x10 );
560 free((void *)(ES * 0x10));
561 ResetCflag;
564 void ResizeMemoryBlock(struct sigcontext_struct *context)
566 char *ptr;
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 */
573 SetCflag;
575 EBX = (EBX & 0xffff0000L) | segment((unsigned long) ptr);
576 ResetCflag;
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
602 use the pointer */
604 ES = 0x0;
605 EBX = (EBX & 0xffff0000L);
608 void GetFileDateTime(struct sigcontext_struct *context)
610 char *filename;
611 struct stat filestat;
612 struct tm *now;
614 if ((filename = GetUnixFileName( (char *) pointer(DS,DX) ))== NULL) {
615 EAX = (EAX & 0xffffff00L) | FileNotFound;
616 SetCflag;
617 return;
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;
626 ResetCflag;
629 void SetFileDateTime(struct sigcontext_struct *context)
631 char *filename;
632 struct utimbuf filetime;
634 filename = GetUnixFileName((char *) pointer(DS,DX));
636 filetime.actime = 0L;
637 filetime.modtime = filetime.actime;
639 utime(filename, &filetime);
640 ResetCflag;
643 void CreateTempFile(struct sigcontext_struct *context)
645 char *filename, temp[256];
646 int drive, handle;
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);
654 if (handle == -1) {
655 EAX = (EAX & 0xffffff00L) | WriteProtected;
656 SetCflag;
657 return;
660 strcpy((char *) pointer(DS,DX), temp);
662 EAX = (EAX & 0xffff0000L) | handle;
663 ResetCflag;
666 void CreateNewFile(struct sigcontext_struct *context)
668 int handle;
670 if ((handle = open(GetUnixFileName((char *) pointer(DS,DX)), O_CREAT | O_TRUNC | O_RDWR)) == -1) {
671 EAX = (EAX & 0xffffff00L) | WriteProtected;
672 SetCflag;
673 return;
676 EAX = (EAX & 0xffff0000L) | handle;
677 ResetCflag;
680 void FileLock(struct sigcontext_struct *context)
685 void GetExtendedCountryInfo(struct sigcontext_struct *context)
687 ResetCflag;
690 void GetCurrentDirectory(struct sigcontext_struct *context)
692 int drive;
694 if ((EDX & 0xffL) == 0)
695 drive = DOS_GetDefaultDrive();
696 else
697 drive = (EDX & 0xffL)-1;
699 if (!DOS_ValidDrive(drive)) {
700 EAX = (EAX & 0xffffff00L) | InvalidDrive;
701 SetCflag;
702 return;
705 DOS_GetCurrentDir(drive, (char *) pointer(DS,SI) );
706 ResetCflag;
709 void GetCurrentPSP(struct sigcontext_struct *context)
714 void GetDiskSerialNumber(struct sigcontext_struct *context)
716 int drive;
717 unsigned long serialnumber;
718 struct diskinfo *ptr;
720 if ((EBX & 0xffL) == 0)
721 drive = DOS_GetDefaultDrive();
722 else
723 drive = (EBX & 0xffL) - 1;
725 if (!DOS_ValidDrive(drive)) {
726 EAX = (EAX & 0xffffff00L) |InvalidDrive;
727 SetCflag;
728 return;
731 DOS_GetSerialNumber(drive,&serialnumber);
733 ptr = (struct diskinfo *) pointer(DS,SI);
735 ptr->infolevel = 0;
736 ptr->serialnumber = serialnumber;
737 strcpy(ptr->label,"NO NAME ");
738 strcpy(ptr->fstype,"FAT16 ");
740 EAX = (EAX & 0xffffff00L) | NoError;
741 ResetCflag;
744 void SetDiskSerialNumber(struct sigcontext_struct *context)
746 EAX = (EAX & 0xffffff00L) | 1L;
747 ResetCflag;
750 /************************************************************************/
752 int do_int21(struct sigcontext_struct * context)
754 int ah;
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;
761 if (ah == 0x59) {
762 GetExtendedErrorInfo(context);
763 return 1;
764 } else {
766 Error (0,0,0);
768 switch(ah) {
770 case 0x00: /* TERMINATE PROGRAM */
771 exit(0);
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 */
786 break;
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 */
810 break;
812 case 0x18: /* NULL FUNCTIONS FOR CP/M COMPATIBILITY */
813 case 0x1d:
814 case 0x1e:
815 case 0x20:
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 */
824 EAX &= 0xff00;
825 break;
827 case 0x67: /* SET HANDLE COUNT */
828 ResetCflag;
829 break;
831 case 0x0e: /* SELECT DEFAULT DRIVE */
832 SetDefaultDrive(context);
833 break;
835 case 0x19: /* GET CURRENT DEFAULT DRIVE */
836 GetDefaultDrive(context);
837 break;
839 case 0x1b: /* GET ALLOCATION INFORMATION FOR DEFAULT DRIVE */
840 GetDefDriveAllocInfo(context);
841 break;
843 case 0x1c: /* GET ALLOCATION INFORMATION FOR SPECIFIC DRIVE */
844 GetDriveAllocInfo(context);
845 break;
847 case 0x1f: /* GET DRIVE PARAMETER BLOCK FOR DEFAULT DRIVE */
848 case 0x32: /* GET DOS DRIVE PARAMETER BLOCK FOR SPECIFIC DRIVE */
849 GetDrivePB(context);
850 break;
852 case 0x25: /* SET INTERRUPT VECTOR */
853 /* Ignore any attempt to set a segment vector */
854 return 1;
856 case 0x26: /* CREATE NEW PROGRAM SEGMENT PREFIX */
857 break;
859 case 0x2a: /* GET SYSTEM DATE */
860 GetSystemDate(context);
861 break;
863 case 0x2c: /* GET SYSTEM TIME */
864 GetSystemTime(context);
865 break;
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 # */
871 ECX = 0x3456;
872 break;
874 case 0x31: /* TERMINATE AND STAY RESIDENT */
875 break;
877 case 0x33: /* MULTIPLEXED */
878 switch (EAX & 0xff) {
879 case 0x00: /* GET CURRENT EXTENDED BREAK STATE */
880 if (!(EAX & 0xffL))
881 EDX &= 0xff00L;
882 break;
884 case 0x01: /* SET EXTENDED BREAK STATE */
885 break;
887 case 0x02: /* GET AND SET EXTENDED CONTROL-BREAK CHECKING STATE */
888 EDX &= 0xff00L;
889 break;
891 case 0x05: /* GET BOOT DRIVE */
892 EDX = (EDX & 0xff00L) | 2;
893 /* c: is Wine's bootdrive */
894 break;
896 case 0x06: /* GET TRUE VERSION NUMBER */
897 EBX = DosVersion;
898 EDX = 0x00;
899 break;
900 default:
901 break;
903 break;
905 case 0x34: /* GET ADDRESS OF INDOS FLAG */
906 GetInDosFlag(context);
907 break;
909 case 0x35: /* GET INTERRUPT VECTOR */
910 /* Return a NULL segment selector - this will bomb,
911 if anyone ever tries to use it */
912 ES = 0;
913 EBX = 0;
914 break;
916 case 0x36: /* GET FREE DISK SPACE */
917 GetFreeDiskSpace(context);
918 break;
920 case 0x38: /* GET COUNTRY-SPECIFIC INFORMATION */
921 EAX &= 0xff00;
922 EAX |= 0x02; /* no country support available */
923 SetCflag;
924 break;
926 case 0x39: /* "MKDIR" - CREATE SUBDIRECTORY */
927 MakeDir(context);
928 break;
930 case 0x3a: /* "RMDIR" - REMOVE SUBDIRECTORY */
931 RemoveDir(context);
932 break;
934 case 0x3b: /* "CHDIR" - SET CURRENT DIRECTORY */
935 ChangeDir(context);
936 break;
938 case 0x3c: /* "CREAT" - CREATE OR TRUNCATE FILE */
939 CreateFile(context);
940 break;
942 case 0x3d: /* "OPEN" - OPEN EXISTING FILE */
943 OpenExistingFile(context);
944 break;
946 case 0x3e: /* "CLOSE" - CLOSE FILE */
947 CloseFile(context);
948 break;
950 case 0x3f: /* "READ" - READ FROM FILE OR DEVICE */
951 ReadFile(context);
952 break;
954 case 0x40: /* "WRITE" - WRITE TO FILE OR DEVICE */
955 WriteFile(context);
956 break;
958 case 0x41: /* "UNLINK" - DELETE FILE */
959 UnlinkFile(context);
960 break;
962 case 0x42: /* "LSEEK" - SET CURRENT FILE POSITION */
963 SeekFile(context);
964 break;
966 case 0x43: /* FILE ATTRIBUTES */
967 switch (EAX & 0xff) {
968 case 0x00:
969 GetFileAttributes(context);
970 break;
971 case 0x01:
972 SetFileAttributes(context);
973 break;
975 break;
977 case 0x44: /* IOCTL */
978 DosIOCTL(context);
979 break;
981 case 0x45: /* "DUP" - DUPLICATE FILE HANDLE */
982 case 0x46: /* "DUP2", "FORCEDUP" - FORCE DUPLICATE FILE HANDLE */
983 DupeFileHandle(context);
984 break;
986 case 0x47: /* "CWD" - GET CURRENT DIRECTORY */
987 GetCurrentDirectory(context);
988 EAX = (EAX & 0xffff0000L) | 0x0100;
989 /* many Microsoft products for Windows rely on this */
990 break;
992 case 0x48: /* ALLOCATE MEMORY */
993 AllocateMemory(context);
994 break;
996 case 0x49: /* FREE MEMORY */
997 FreeMemory(context);
998 break;
1000 case 0x4a: /* RESIZE MEMORY BLOCK */
1001 ResizeMemoryBlock(context);
1002 break;
1004 case 0x4b: /* "EXEC" - LOAD AND/OR EXECUTE PROGRAM */
1005 ExecProgram(context);
1006 break;
1008 case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */
1009 fprintf(stderr,"int21: DosExit\n");
1010 exit(EAX & 0xff);
1011 break;
1013 case 0x4d: /* GET RETURN CODE */
1014 GetReturnCode(context);
1015 break;
1017 case 0x4e: /* "FINDFIRST" - FIND FIRST MATCHING FILE */
1018 FindFirst(context);
1019 break;
1021 case 0x4f: /* "FINDNEXT" - FIND NEXT MATCHING FILE */
1022 FindNext(context);
1023 break;
1025 case 0x52: /* "SYSVARS" - GET LIST OF LISTS */
1026 GetSysVars(context);
1027 break;
1029 case 0x56: /* "RENAME" - RENAME FILE */
1030 RenameFile(context);
1031 break;
1033 case 0x57: /* FILE DATE AND TIME */
1034 switch (EAX & 0xff) {
1035 case 0x00:
1036 GetFileDateTime(context);
1037 break;
1038 case 0x01:
1039 SetFileDateTime(context);
1040 break;
1042 break;
1044 case 0x58: /* GET OR SET MEMORY/UMB ALLOCATION STRATEGY */
1045 switch (EAX & 0xff) {
1046 case 0x00:
1047 EAX = (EAX & 0xffffff00L) | 0x01L;
1048 break;
1049 case 0x02:
1050 EAX &= 0xff00L;
1051 break;
1052 case 0x01:
1053 case 0x03:
1054 break;
1056 ResetCflag;
1057 break;
1059 case 0x59: /* GET EXTENDED ERROR INFO */
1060 GetExtendedErrorInfo(context);
1061 break;
1063 case 0x5a: /* CREATE TEMPORARY FILE */
1064 CreateTempFile(context);
1065 break;
1067 case 0x5b: /* CREATE NEW FILE */
1068 CreateNewFile(context);
1069 break;
1071 case 0x5c: /* "FLOCK" - RECORD LOCKING */
1072 FileLock(context);
1073 break;
1075 case 0x5d: /* NETWORK */
1076 case 0x5e:
1077 EAX = (EAX & 0xfffff00L) | NoNetwork; /* network software not installed */
1078 SetCflag;
1079 break;
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;
1087 SetCflag;
1088 break;
1089 } else {
1090 ResetCflag;
1091 break;
1093 case 0x08: /* DISABLE DRIVE */
1094 if (!DOS_DisableDrive(EDX & 0xffL)) {
1095 Error(InvalidDrive, EC_MediaError , EL_Disk);
1096 EAX = (EAX & 0xfffff00L) | InvalidDrive;
1097 SetCflag;
1098 break;
1099 } else {
1100 ResetCflag;
1101 break;
1103 default:
1104 EAX = (EAX & 0xfffff00L) | NoNetwork; /* network software not installed */
1105 SetCflag;
1106 break;
1108 break;
1110 case 0x60: /* "TRUENAME" - CANONICALIZE FILENAME OR PATH */
1111 GetTrueFileName(context);
1112 break;
1114 case 0x62: /* GET CURRENT PSP ADDRESS */
1115 GetCurrentPSP(context);
1116 break;
1118 case 0x65: /* GET EXTENDED COUNTRY INFORMATION */
1119 GetExtendedCountryInfo(context);
1120 break;
1122 case 0x66: /* GLOBAL CODE PAGE TABLE */
1123 switch (EAX & 0xffL) {
1124 case 0x01:
1125 EBX = CodePage;
1126 EDX = EBX;
1127 ResetCflag;
1128 break;
1129 case 0x02:
1130 CodePage = EBX;
1131 ResetCflag;
1132 break;
1134 break;
1136 case 0x68: /* "FFLUSH" - COMMIT FILE */
1137 ResetCflag;
1138 break;
1140 case 0x69: /* DISK SERIAL NUMBER */
1141 switch (EAX & 0xff) {
1142 case 0x00:
1143 GetDiskSerialNumber(context);
1144 break;
1145 case 0x01:
1146 SetDiskSerialNumber(context);
1147 break;
1149 break;
1151 case 0x6a: /* COMMIT FILE */
1152 ResetCflag;
1153 break;
1155 default:
1156 fprintf(stderr,"Unable to handle int 0x21 %x\n", context->sc_eax);
1157 return 1;
1160 return 1;
1163 /**********************************************************************
1164 * DOS3Call
1166 int DOS3Call()
1168 static struct sigcontext_struct *context = NULL;
1170 if (!context)
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);
1176 EAX = _AX;
1177 EBX = _BX;
1178 ECX = _CX;
1179 EDX = _DX;
1180 DS = _DS;
1181 ES = _ES;
1182 DI = _DI;
1183 SI = _SI;
1184 /* EFL = _FL;
1186 do_int21(context);
1188 _AX = AX;
1189 _BX = BX;
1190 _CX = CX;
1191 _DX = DX;
1193 _DS = DS;
1194 _ES = ES;
1196 _DI = DI;
1197 _SI = SI;
1198 /* _FL = EFL;
1200 return 0;