Release 0.4.10
[wine/multimedia.git] / loader / int21.c
blobfdf506aa4868a7b3308129b9663cf1a7d8c15c32
1 #include <time.h>
2 #include <fcntl.h>
3 #include <errno.h>
4 #include <malloc.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <sys/stat.h>
8 #ifdef linux
9 #include <sys/vfs.h>
10 #endif
11 #ifdef __NetBSD__
12 #include <sys/mount.h>
13 #endif
14 #include <time.h>
15 #include <unistd.h>
16 #include <utime.h>
18 #include "windows.h"
19 #include "wine.h"
20 #include "int21.h"
21 #include "files.h"
23 #define MAX_DRIVES 26
25 static char Copyright[] = "int21.c, copyright Erik Bos, 1993";
27 extern struct DosDriveStruct DosDrives[];
28 extern int CurrentDrive;
29 extern void ParseDOSFileName();
31 int ValidDrive(int);
33 WORD ExtendedError, CodePage = 437;
34 BYTE ErrorClass, Action, ErrorLocus;
36 void Error(int e, int class, int el)
38 ExtendedError = e;
39 ErrorClass = class;
40 Action = SA_Ask4Retry;
41 ErrorLocus = el;
44 void GetFreeDiskSpace(struct sigcontext_struct *context)
46 int drive;
47 struct statfs info;
48 long size,avail;
50 if (!(DX & 0xff))
51 drive = CurrentDrive;
52 else
53 drive = (DX & 0xff) - 1;
55 if (!ValidDrive(drive)) {
56 Error(InvalidDrive, EC_MediaError , EL_Disk);
57 AX = 0xffff;
58 return;
62 if (statfs(DosDrives[drive].RootDirectory, &info) < 0) {
63 fprintf(stderr,"cannot do statfs(%s)\n",DosDrives[drive].RootDirectory);
64 Error(GeneralFailure, EC_MediaError , EL_Disk);
65 AX = 0xffff;
66 return;
69 size = info.f_bsize * info.f_blocks / 1024;
70 avail = info.f_bavail * info.f_bsize / 1024;
72 #ifdef DOSDEBUG
73 fprintf(stderr,"statfs: size: %8d avail: %8d\n",size,avail);
74 #endif
76 AX = SectorsPerCluster;
77 CX = SectorSize;
79 BX = (avail / (CX * AX));
80 DX = (size / (CX * AX));
81 Error (0,0,0);
85 void SetDefaultDrive(struct sigcontext_struct *context)
87 if ((DX & 0xff) < MAX_DRIVES) {
88 CurrentDrive = DX & 0xff;
89 AX &= 0xff00;
90 AX |= MAX_DRIVES; /* # of valid drive letters */
91 Error (0,0,0);
92 } else
93 Error (InvalidDrive, EC_MediaError, EL_Disk);
96 void GetDefaultDrive(struct sigcontext_struct *context)
98 AX &= 0xff00;
99 AX |= CurrentDrive;
100 Error (0,0,0);
103 void GetDriveAllocInfo(struct sigcontext_struct *context)
105 int drive;
106 long size;
107 BYTE mediaID;
108 struct statfs info;
110 drive = DX & 0xff;
112 if (!ValidDrive(drive)) {
113 AX = SectorsPerCluster;
114 CX = SectorSize;
115 DX = 0;
116 Error (InvalidDrive, EC_MediaError, EL_Disk);
117 return;
121 if (statfs(DosDrives[drive].RootDirectory, &info) < 0) {
122 fprintf(stderr,"cannot do statfs(%s)\n",DosDrives[drive].RootDirectory);
123 Error(GeneralFailure, EC_MediaError , EL_Disk);
124 AX = 0xffff;
125 return;
128 size = info.f_bsize * info.f_blocks / 1024;
130 #ifdef DOSDEBUG
131 fprintf(stderr,"statfs: size: %8d\n",size);
132 #endif
134 AX = SectorsPerCluster;
135 CX = SectorSize;
136 DX = (size / (CX * AX));
138 mediaID = 0xf0;
140 DS = segment(mediaID);
141 BX = offset(mediaID);
142 Error (0,0,0);
146 void GetDefDriveAllocInfo(struct sigcontext_struct *context)
148 DX = CurrentDrive;
149 GetDriveAllocInfo(context);
152 void GetDrivePB(struct sigcontext_struct *context)
154 Error (InvalidDrive, EC_MediaError, EL_Disk);
155 AX = 0xff; /* I'm sorry but I only got networked drives :-) */
158 void ReadFile(struct sigcontext_struct *context)
160 char *ptr;
161 int size;
163 /* can't read from stdout / stderr */
165 if (((BX & 0xffff) == 1) ||((BX & 0xffff) == 2)) {
166 Error (InvalidHandle, EL_Unknown, EC_Unknown);
167 AX = InvalidHandle;
168 SetCflag;
169 return;
172 ptr = (char *) pointer (DS,DX);
174 if ((BX & 0xffff) == 0) {
175 *ptr = EOF;
176 Error (0,0,0);
177 AX = 1;
178 ResetCflag;
179 return;
180 } else {
181 size = read(BX, ptr, CX);
182 if (size == 0) {
183 Error (ReadFault, EC_Unknown, EL_Unknown);
184 AX = ExtendedError;
185 return;
188 if (size == -1) {
189 switch (errno) {
190 case EAGAIN:
191 Error (ShareViolation, EC_Temporary, EL_Unknown);
192 break;
193 case EBADF:
194 Error (InvalidHandle, EC_AppError, EL_Unknown);
195 break;
196 default:
197 Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
198 break;
200 AX = ExtendedError;
201 SetCflag;
202 return;
204 Error (0,0,0);
205 AX = size;
206 ResetCflag;
210 void WriteFile(struct sigcontext_struct *context)
212 char *ptr;
213 int x,size;
215 ptr = (char *) pointer (DS,DX);
217 if ((BX & 0xffff) == 0) {
218 Error (InvalidHandle, EC_Unknown, EL_Unknown);
219 AX = InvalidHandle;
220 SetCflag;
221 return;
224 if ((BX & 0xffff) < 3) {
225 for (x = 0;x != CX;x++) {
226 fprintf(stderr, "%c", *ptr++);
228 fflush(stderr);
230 Error (0,0,0);
231 AX = CX;
232 ResetCflag;
233 } else {
234 size = write(BX, ptr , CX);
235 if (size == 0) {
236 Error (WriteFault, EC_Unknown, EL_Unknown);
237 AX = ExtendedError;
238 return;
241 if (size == -1) {
242 switch (errno) {
243 case EAGAIN:
244 Error (ShareViolation, EC_Temporary, EL_Unknown);
245 break;
246 case EBADF:
247 Error (InvalidHandle, EC_AppError, EL_Unknown);
248 break;
249 case ENOSPC:
250 Error (DiskFull, EC_MediaError, EL_Disk);
251 break;
252 default:
253 Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
254 break;
256 AX = ExtendedError;
257 SetCflag;
258 return;
260 Error (0,0,0);
261 AX = size;
262 ResetCflag;
266 void UnlinkFile(struct sigcontext_struct *context)
268 char UnixFileName[256];
269 int drive, status;
271 ParseDOSFileName(UnixFileName, (char *) pointer(DS,DX), &drive);
274 status = unlink((char *) pointer(DS,DX));
275 if (status == -1) {
276 switch (errno) {
277 case EACCES:
278 case EPERM:
279 case EROFS:
280 Error (WriteProtected, EC_AccessDenied, EL_Unknown);
281 break;
282 case EBUSY:
283 Error (LockViolation, EC_AccessDenied, EL_Unknown);
284 break;
285 case EAGAIN:
286 Error (ShareViolation, EC_Temporary, EL_Unknown);
287 break;
288 case ENOENT:
289 Error (FileNotFound, EC_NotFound, EL_Unknown);
290 break;
291 default:
292 Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
293 break;
295 AX = ExtendedError;
296 SetCflag;
297 return;
299 Error (0,0,0);
300 ResetCflag;
304 void SeekFile(struct sigcontext_struct *context)
306 char UnixFileName[256];
307 int drive, handle, status, fileoffset;
310 ParseDOSFileName(UnixFileName, (char *) pointer(DS,DX), &drive);
313 switch (AX & 0xff) {
314 case 1: fileoffset = SEEK_CUR;
315 break;
316 case 2: fileoffset = SEEK_END;
317 break;
318 default:
319 case 0: fileoffset = SEEK_SET;
320 break;
322 status = lseek(BX, (CX * 0x100) + DX, fileoffset);
323 if (status == -1) {
324 switch (errno) {
325 case EBADF:
326 Error (InvalidHandle, EC_AppError, EL_Unknown);
327 break;
328 case EINVAL:
329 Error (DataInvalid, EC_AppError, EL_Unknown);
330 break;
331 default:
332 Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
333 break;
335 AX = ExtendedError;
336 SetCflag;
337 return;
339 Error (0,0,0);
340 ResetCflag;
344 void GetFileAttributes(struct sigcontext_struct *context)
346 char UnixFileName[256];
347 int drive,handle;
349 ParseDOSFileName(UnixFileName, (char *) pointer(DS,DX), &drive);
352 CX = 0x0;
353 ResetCflag;
357 void SetFileAttributes(struct sigcontext_struct *context)
359 ResetCflag;
362 void DosIOCTL(struct sigcontext_struct *context)
364 AX = UnknownUnit;
365 SetCflag;
368 void DupeFileHandle(struct sigcontext_struct *context)
370 AX = dup(BX);
371 ResetCflag;
374 void GetSystemDate(struct sigcontext_struct *context)
376 struct tm *now;
377 time_t ltime;
379 ltime = time(NULL);
380 now = localtime(&ltime);
382 CX = now->tm_year + 1900;
383 DX = ((now->tm_mon + 1) << 8) | now->tm_mday;
384 AX &= 0xff00;
385 AX |= now->tm_wday;
388 void GetSystemTime(struct sigcontext_struct *context)
390 struct tm *now;
391 time_t ltime;
393 ltime = time(NULL);
394 now = localtime(&ltime);
396 CX = (now->tm_hour << 8) | now->tm_min;
397 DX = now->tm_sec << 8;
400 void GetExtendedErrorInfo(struct sigcontext_struct *context)
402 AX = ExtendedError;
403 BX = (0x100 * ErrorClass) | Action;
404 CX &= 0x00ff;
405 CX |= (0x100 * ErrorLocus);
408 void GetInDosFlag(struct sigcontext_struct *context)
410 const BYTE InDosFlag = 0;
412 ES = segment(InDosFlag);
413 BX = offset(InDosFlag);
416 void CreateFile(struct sigcontext_struct *context)
418 char UnixFileName[256];
419 int drive,handle;
421 ParseDOSFileName(UnixFileName, (char *) pointer(DS,DX), &drive);
424 handle = open(UnixFileName, O_CREAT | O_TRUNC);
426 if (handle == -1) {
427 switch (errno) {
428 case EACCES:
429 case EPERM:
430 case EROFS:
431 Error (WriteProtected, EC_AccessDenied, EL_Unknown);
432 break;
433 case EISDIR:
434 Error (CanNotMakeDir, EC_AccessDenied, EL_Unknown);
435 break;
436 case ENFILE:
437 case EMFILE:
438 Error (NoMoreFiles, EC_MediaError, EL_Unknown);
439 case EEXIST:
440 Error (FileExists, EC_Exists, EL_Disk);
441 break;
442 case ENOSPC:
443 Error (DiskFull, EC_MediaError, EL_Disk);
444 break;
445 default:
446 Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
447 break;
449 AX = ExtendedError;
450 SetCflag;
451 return;
453 Error (0,0,0);
454 BX = handle;
455 AX = NoError;
456 ResetCflag;
460 void OpenExistingFile(struct sigcontext_struct *context)
462 char UnixFileName[256];
463 int drive, handle;
465 ParseDOSFileName(UnixFileName, (char *) pointer(DS,DX), &drive);
468 handle = open(UnixFileName, O_RDWR);
470 if (handle == -1) {
471 switch (errno) {
472 case EACCES:
473 case EPERM:
474 case EROFS:
475 Error (WriteProtected, EC_AccessDenied, EL_Unknown);
476 break;
477 case EISDIR:
478 Error (CanNotMakeDir, EC_AccessDenied, EL_Unknown);
479 break;
480 case ENFILE:
481 case EMFILE:
482 Error (NoMoreFiles, EC_MediaError, EL_Unknown);
483 case EEXIST:
484 Error (FileExists, EC_Exists, EL_Disk);
485 break;
486 case ENOSPC:
487 Error (DiskFull, EC_MediaError, EL_Disk);
488 break;
489 case ENOENT:
490 Error (FileNotFound, EC_MediaError, EL_Disk);
491 break;
492 default:
493 Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
494 break;
496 AX = ExtendedError;
497 SetCflag;
498 return;
500 Error (0,0,0);
501 BX = handle;
502 AX = NoError;
503 ResetCflag;
507 void CloseFile(struct sigcontext_struct *context)
509 if (close(BX) == -1) {
510 switch (errno) {
511 case EBADF:
512 Error (InvalidHandle, EC_AppError, EL_Unknown);
513 break;
514 default:
515 Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
516 break;
518 AX = ExtendedError;
519 SetCflag;
520 return;
522 Error (0,0,0);
523 AX = NoError;
524 ResetCflag;
527 void RenameFile(struct sigcontext_struct *context)
529 rename((char *) pointer(DS,DX), (char *) pointer(ES,DI));
530 ResetCflag;
533 void GetTrueFileName(struct sigcontext_struct *context)
535 strncpy((char *) pointer(ES,DI), (char *) pointer(DS,SI), strlen((char *) pointer(DS,SI)) & 0x7f);
536 ResetCflag;
539 void MakeDir(struct sigcontext_struct *context)
541 int drive;
542 char *dirname;
543 char unixname[256];
545 dirname = (char *) pointer(DS,DX);
547 ParseDOSFileName(unixname,dirname,&drive);
550 if (mkdir(unixname,0) == -1) {
551 AX = CanNotMakeDir;
552 SetCflag;
554 ResetCflag;
558 void ChangeDir(struct sigcontext_struct *context)
560 int drive;
561 char *dirname;
562 char unixname[256];
564 dirname = (char *) pointer(DS,DX);
566 ParseDOSFileName(unixname,dirname,&drive);
569 strcpy(unixname,DosDrives[drive].CurrentDirectory);
570 ResetCflag;
574 void RemoveDir(struct sigcontext_struct *context)
576 int drive;
577 char *dirname;
578 char unixname[256];
580 dirname = (char *) pointer(DS,DX);
582 ParseDOSFileName(unixname,dirname,&drive);
585 if (strcmp(unixname,DosDrives[drive].CurrentDirectory)) {
586 AX = CanNotRemoveCwd;
587 SetCflag;
590 #ifdef DOSDEBUG
591 fprintf(stderr,"rmdir %s\n",unixname);
592 #endif
594 if (rmdir(unixname) == -1) {
595 AX = CanNotMakeDir; /* HUH ?*/
596 SetCflag;
598 ResetCflag;
602 void AllocateMemory(struct sigcontext_struct *context)
604 char *ptr;
606 if ((ptr = (void *) memalign((size_t) (BX * 0x10), 0x10)) == NULL) {
607 AX = OutOfMemory;
608 BX = 0x0; /* out of memory */
609 SetCflag;
611 AX = segment((unsigned long) ptr);
612 ResetCflag;
615 void FreeMemory(struct sigcontext_struct *context)
617 free((void *)(ES * 0x10));
618 ResetCflag;
621 void ResizeMemoryBlock(struct sigcontext_struct *context)
623 char *ptr;
625 if ((ptr = (void *) realloc((void *)(ES * 0x10), (size_t) BX * 0x10)) == NULL) {
626 AX = OutOfMemory;
627 BX = 0x0; /* out of memory */
628 SetCflag;
630 BX = segment((unsigned long) ptr);
631 ResetCflag;
634 void ExecProgram(struct sigcontext_struct *context)
636 execl("wine",(char *) pointer(DS,DX));
639 void GetReturnCode(struct sigcontext_struct *context)
641 AX = NoError; /* normal exit */
644 void FindFirst(struct sigcontext_struct *context)
649 void FindNext(struct sigcontext_struct *context)
654 void GetSysVars(struct sigcontext_struct *context)
656 ES = 0x0;
657 BX = 0x0;
660 void GetFileDateTime(struct sigcontext_struct *context)
662 int drive;
663 char *dirname;
664 char unixname[256];
665 struct stat filestat;
666 struct tm *now;
668 dirname = (char *) pointer(DS,DX);
669 ParseDOSFileName(unixname, dirname, &drive);
672 stat(unixname, &filestat);
674 now = localtime (&filestat.st_mtime);
676 CX = (now->tm_hour * 0x2000) + (now->tm_min * 0x20) + now->tm_sec/2;
677 DX = (now->tm_year * 0x200) + (now->tm_mon * 0x20) + now->tm_mday;
679 ResetCflag;
683 void SetFileDateTime(struct sigcontext_struct *context)
685 int drive;
686 char *dirname;
687 char unixname[256];
688 struct utimbuf filetime;
690 dirname = (char *) pointer(DS,DX);
692 ParseDOSFileName(unixname, dirname, &drive);
695 filetime.actime = 0L;
696 filetime.modtime = filetime.actime;
698 utime(unixname,&filetime);
699 ResetCflag;
703 void CreateTempFile(struct sigcontext_struct *context)
705 char UnixFileName[256],TempString[256];
706 int drive,handle;
708 ParseDOSFileName(UnixFileName, (char *) pointer(DS,DX), &drive);
710 sprintf(TempString,"%s%s%d",UnixFileName,"eb",(int) getpid());
713 handle = open(TempString, O_CREAT | O_TRUNC | O_RDWR);
715 if (handle == -1) {
716 AX = WriteProtected;
717 SetCflag;
718 return;
721 strcpy((char *) pointer(DS,DX), UnixFileName);
723 AX = handle;
724 ResetCflag;
728 void CreateNewFile(struct sigcontext_struct *context)
730 char UnixFileName[256];
731 int drive,handle;
733 ParseDOSFileName(UnixFileName, (char *) pointer(DS,DX), &drive);
736 handle = open(UnixFileName, O_CREAT | O_TRUNC | O_RDWR);
738 if (handle == -1) {
739 AX = WriteProtected;
740 SetCflag;
741 return;
744 AX = handle;
745 ResetCflag;
749 void FileLock(struct sigcontext_struct *context)
754 void GetExtendedCountryInfo(struct sigcontext_struct *context)
756 ResetCflag;
759 int ValidDrive(int d)
761 return 1;
764 void GetCurrentDirectory(struct sigcontext_struct *context)
766 int drive;
767 char *ptr;
769 if ((DX & 0xff) == 0)
770 drive = CurrentDrive;
771 else
772 drive = (DX & 0xff)-1;
774 if (!ValidDrive(drive)) {
775 AX = InvalidDrive;
776 SetCflag;
777 return;
780 strcpy((char *) pointer(DS,SI), DosDrives[drive].CurrentDirectory);
781 ResetCflag;
782 AX = 0x0100;
785 void GetCurrentPSP(struct sigcontext_struct *context)
790 void GetDiskSerialNumber(struct sigcontext_struct *context)
792 int drive;
793 struct diskinfo *ptr;
795 if ((BX & 0xff)== 0)
796 drive = CurrentDrive;
797 else
798 drive = (BX & 0xff)-1;
800 if (!ValidDrive(drive)) {
801 AX = InvalidDrive;
802 SetCflag;
803 return;
807 ptr =(struct diskinfo *) pointer(DS,SI);
809 ptr->infolevel = 0;
810 ptr->serialnumber = 0xEBEBEB00 | drive;
811 strcpy(ptr->label,"NO NAME ");
812 strcpy(ptr->fstype,"FAT16 ");
814 AX = NoError;
815 ResetCflag;
819 void SetDiskSerialNumber(struct sigcontext_struct *context)
821 AX &= 0xff00;
822 AX |= 1;
823 ResetCflag;
826 void CommitFile(struct sigcontext_struct *context)
831 /************************************************************************/
833 int do_int21(struct sigcontext_struct * context){
834 int ah;
836 fprintf(stderr,"int21: doing AX=%4x BX=%4x CX=%4x DX=%4x\n",
837 AX & 0xffff,BX & 0xffff,CX & 0xffff,DX & 0xffff);
839 ah = (AX >> 8) & 0xff;
841 if (ah == 0x59) {
842 GetExtendedErrorInfo(context);
843 return 1;
844 } else {
846 Error (0,0,0);
848 switch(ah) {
850 case 0x00: /* TERMINATE PROGRAM */
851 exit(0);
853 case 0x01: /* READ CHARACTER FROM STANDARD INPUT, WITH ECHO */
854 case 0x02: /* WRITE CHARACTER TO STANDARD OUTPUT */
855 case 0x03: /* READ CHARACTER FROM STDAUX */
856 case 0x04: /* WRITE CHARACTER TO STDAUX */
857 case 0x05: /* WRITE CHARACTER TO PRINTER */
858 case 0x06: /* DIRECT CONSOLE IN/OUTPUT */
859 case 0x07: /* DIRECT CHARACTER INPUT, WITHOUT ECHO */
860 case 0x08: /* CHARACTER INPUT WITHOUT ECHO */
861 case 0x09: /* WRITE STRING TO STANDARD OUTPUT */
862 case 0x0a: /* BUFFERED INPUT */
863 case 0x0b: /* GET STDIN STATUS */
864 case 0x0c: /* FLUSH BUFFER AND READ STANDARD INPUT */
865 case 0x0d: /* DISK BUFFER FLUSH */
866 break;
868 /* no FCB support for CP/M hackers */
870 case 0x0f: /* OPEN FILE USING FCB */
871 case 0x10: /* CLOSE FILE USING FCB */
872 case 0x11: /* FIND FIRST MATCHING FILE USING FCB */
873 case 0x12: /* FIND NEXT MATCHING FILE USING FCB */
874 case 0x13: /* DELETE FILE USING FCB */
875 case 0x14: /* SEQUENTIAL READ FROM FCB FILE */
876 case 0x15: /* SEQUENTIAL WRITE TO FCB FILE */
877 case 0x16: /* CREATE OR TRUNCATE FILE USING FCB */
878 case 0x17: /* RENAME FILE USING FCB */
879 case 0x1a: /* SET DISK TRANSFER AREA ADDRESS */
880 case 0x21: /* READ RANDOM RECORD FROM FCB FILE */
881 case 0x22: /* WRITE RANDOM RECORD TO FCB FILE */
882 case 0x23: /* GET FILE SIZE FOR FCB */
883 case 0x24: /* SET RANDOM RECORD NUMBER FOR FCB */
884 case 0x27: /* RANDOM BLOCK READ FROM FCB FILE */
885 case 0x28: /* RANDOM BLOCK WRITE TO FCB FILE */
886 case 0x29: /* PARSE FILENAME INTO FCB */
887 case 0x2f: /* GET DISK TRANSFER AREA ADDRESS */
889 case 0x2e: /* SET VERIFY FLAG */
890 break;
892 case 0x18: /* NULL FUNCTIONS FOR CP/M COMPATIBILITY */
893 case 0x1d:
894 case 0x1e:
895 case 0x20:
896 case 0x2b: /* SET SYSTEM DATE */
897 case 0x2d: /* SET SYSTEM TIME */
898 case 0x37: /* "SWITCHAR" - GET SWITCH CHARACTER
899 "SWITCHAR" - SET SWITCH CHARACTER
900 "AVAILDEV" - SPECIFY \DEV\ PREFIX USE */
901 case 0x54: /* GET VERIFY FLAG */
902 case 0x61: /* UNUSED */
903 case 0x6b: /* NULL FUNCTION */
904 AX &= 0xff00;
905 break;
907 case 0x67: /* SET HANDLE COUNT */
908 ResetCflag;
909 break;
911 case 0x0e: /* SELECT DEFAULT DRIVE */
912 SetDefaultDrive(context);
913 break;
915 case 0x19: /* GET CURRENT DEFAULT DRIVE */
916 GetDefaultDrive(context);
917 break;
919 case 0x1b: /* GET ALLOCATION INFORMATION FOR DEFAULT DRIVE */
920 GetDefDriveAllocInfo(context);
921 break;
923 case 0x1c: /* GET ALLOCATION INFORMATION FOR SPECIFIC DRIVE */
924 GetDriveAllocInfo(context);
925 break;
927 case 0x1f: /* GET DRIVE PARAMETER BLOCK FOR DEFAULT DRIVE */
928 case 0x32: /* GET DOS DRIVE PARAMETER BLOCK FOR SPECIFIC DRIVE */
929 GetDrivePB(context);
930 break;
932 case 0x25: /* SET INTERRUPT VECTOR */
933 /* Ignore any attempt to set a segment vector */
934 return 1;
936 case 0x26: /* CREATE NEW PROGRAM SEGMENT PREFIX */
937 break;
939 case 0x2a: /* GET SYSTEM DATE */
940 GetSystemDate(context);
941 break;
943 case 0x2c: /* GET SYSTEM TIME */
944 GetSystemTime(context);
945 break;
947 case 0x30: /* GET DOS VERSION */
948 AX = DosVersion; /* Hey folks, this is DOS V3.3! */
949 BX = 0x0012; /* 0x123456 is Wine's serial # */
950 CX = 0x3456;
951 break;
953 case 0x31: /* TERMINATE AND STAY RESIDENT */
954 break;
956 case 0x33: /* MULTIPLEXED */
957 switch (AX & 0xff) {
958 case 0x00: /* GET CURRENT EXTENDED BREAK STATE */
959 if (!(AX & 0xff))
960 DX &= 0xff00;
961 break;
963 case 0x01: /* SET EXTENDED BREAK STATE */
964 break;
966 case 0x02: /* GET AND SET EXTENDED CONTROL-BREAK CHECKING STATE */
967 DX &= 0xff00;
968 break;
970 case 0x05: /* GET BOOT DRIVE */
971 DX &= 0xff00;
972 DX |= 2; /* c: is Wine's bootdrive */
973 break;
975 case 0x06: /* GET TRUE VERSION NUMBER */
976 BX = DosVersion;
977 DX = 0x00;
978 break;
979 default:
980 break;
982 break;
984 case 0x34: /* GET ADDRESS OF INDOS FLAG */
985 GetInDosFlag(context);
986 break;
988 case 0x35: /* GET INTERRUPT VECTOR */
989 /* Return a NULL segment selector - this will bomb,
990 if anyone ever tries to use it */
991 ES = 0;
992 BX = 0;
993 break;
995 case 0x36: /* GET FREE DISK SPACE */
996 GetFreeDiskSpace(context);
997 break;
999 case 0x38: /* GET COUNTRY-SPECIFIC INFORMATION */
1000 AX &= 0xff00;
1001 AX |= 0x02; /* no country support available */
1002 SetCflag;
1003 break;
1005 case 0x39: /* "MKDIR" - CREATE SUBDIRECTORY */
1006 MakeDir(context);
1007 break;
1009 case 0x3a: /* "RMDIR" - REMOVE SUBDIRECTORY */
1010 RemoveDir(context);
1011 break;
1013 case 0x3b: /* "CHDIR" - SET CURRENT DIRECTORY */
1014 ChangeDir(context);
1015 break;
1017 case 0x3c: /* "CREAT" - CREATE OR TRUNCATE FILE */
1018 CreateFile(context);
1019 break;
1021 case 0x3d: /* "OPEN" - OPEN EXISTING FILE */
1022 OpenExistingFile(context);
1023 break;
1025 case 0x3e: /* "CLOSE" - CLOSE FILE */
1026 case 0x68: /* "FFLUSH" - COMMIT FILE */
1027 case 0x6a: /* COMMIT FILE */
1029 CloseFile(context);
1030 break;
1032 case 0x3f: /* "READ" - READ FROM FILE OR DEVICE */
1033 ReadFile(context);
1034 break;
1036 case 0x40: /* "WRITE" - WRITE TO FILE OR DEVICE */
1037 WriteFile(context);
1038 break;
1040 case 0x41: /* "UNLINK" - DELETE FILE */
1041 UnlinkFile(context);
1042 break;
1044 case 0x42: /* "LSEEK" - SET CURRENT FILE POSITION */
1045 SeekFile(context);
1046 break;
1048 case 0x43: /* FILE ATTRIBUTES */
1049 switch (AX & 0xff) {
1050 case 0x00:
1051 GetFileAttributes(context);
1052 break;
1053 case 0x01:
1054 SetFileAttributes(context);
1055 break;
1057 break;
1059 case 0x44: /* IOCTL */
1060 DosIOCTL(context);
1061 break;
1063 case 0x45: /* "DUP" - DUPLICATE FILE HANDLE */
1064 case 0x46: /* "DUP2", "FORCEDUP" - FORCE DUPLICATE FILE HANDLE */
1065 DupeFileHandle(context);
1066 break;
1068 case 0x47: /* "CWD" - GET CURRENT DIRECTORY */
1069 GetCurrentDirectory(context);
1070 AX = 0x0100; /* many Microsoft products for Windows rely
1071 on this */
1072 break;
1074 case 0x48: /* ALLOCATE MEMORY */
1075 AllocateMemory(context);
1076 break;
1078 case 0x49: /* FREE MEMORY */
1079 FreeMemory(context);
1080 break;
1082 case 0x4a: /* RESIZE MEMORY BLOCK */
1083 ResizeMemoryBlock(context);
1084 break;
1086 case 0x4b: /* "EXEC" - LOAD AND/OR EXECUTE PROGRAM */
1087 ExecProgram(context);
1088 break;
1090 case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */
1091 exit(AX & 0xff);
1093 case 0x4d: /* GET RETURN CODE */
1094 GetReturnCode(context);
1095 break;
1097 case 0x4e: /* "FINDFIRST" - FIND FIRST MATCHING FILE */
1098 FindFirst(context);
1099 break;
1101 case 0x4f: /* "FINDNEXT" - FIND NEXT MATCHING FILE */
1102 FindNext(context);
1103 break;
1105 case 0x52: /* "SYSVARS" - GET LIST OF LISTS */
1106 GetSysVars(context);
1107 break;
1109 case 0x56: /* "RENAME" - RENAME FILE */
1110 RenameFile(context);
1111 break;
1113 case 0x57: /* FILE DATE AND TIME */
1114 switch (AX & 0xff) {
1115 case 0x00:
1116 GetFileDateTime(context);
1117 break;
1118 case 0x01:
1119 SetFileDateTime(context);
1120 break;
1122 break;
1124 case 0x58: /* GET OR SET MEMORY/UMB ALLOCATION STRATEGY */
1125 switch (AX & 0xff) {
1126 case 0x00:
1127 AX = 0x01;
1128 break;
1129 case 0x02:
1130 AX &= 0xff00;
1131 break;
1132 case 0x01:
1133 case 0x03:
1134 break;
1136 ResetCflag;
1137 break;
1139 case 0x59: /* GET EXTENDED ERROR INFO */
1140 GetExtendedErrorInfo(context);
1141 break;
1143 case 0x5a: /* CREATE TEMPORARY FILE */
1144 CreateTempFile(context);
1145 break;
1147 case 0x5b: /* CREATE NEW FILE */
1148 CreateNewFile(context);
1149 break;
1151 case 0x5c: /* "FLOCK" - RECORD LOCKING */
1152 FileLock(context);
1153 break;
1155 case 0x5d: /* NETWORK */
1156 case 0x5e:
1157 case 0x5f:
1158 AX &= 0xff00;
1159 AX |= NoNetwork; /* network software not installed */
1160 SetCflag;
1161 break;
1163 case 0x60: /* "TRUENAME" - CANONICALIZE FILENAME OR PATH */
1164 GetTrueFileName(context);
1165 break;
1167 case 0x62: /* GET CURRENT PSP ADDRESS */
1168 GetCurrentPSP(context);
1169 break;
1171 case 0x65: /* GET EXTENDED COUNTRY INFORMATION */
1172 GetExtendedCountryInfo(context);
1173 break;
1175 case 0x66: /* GLOBAL CODE PAGE TABLE */
1176 switch (AX & 0xff) {
1177 case 0x01:
1178 BX = CodePage;
1179 DX = BX;
1180 ResetCflag;
1181 break;
1182 case 0x02:
1183 CodePage = BX;
1184 ResetCflag;
1185 break;
1187 break;
1189 case 0x69: /* DISK SERIAL NUMBER */
1190 switch (AX & 0xff) {
1191 case 0x00:
1192 GetDiskSerialNumber(context);
1193 break;
1194 case 0x01:
1195 SetDiskSerialNumber(context);
1196 break;
1198 break;
1200 default:
1201 fprintf(stderr,"Unable to handle int 0x21 %x\n", context->sc_eax);
1202 return 1;
1205 return 1;