Fixed function 0xb.
[wine] / dlls / winedos / int21.c
1 /*
2  * DOS interrupt 21h handler
3  */
4
5 #include "config.h"
6
7 #include "windef.h"
8 #include "winbase.h"
9 #include "ntddk.h"
10 #include "wine/winbase16.h"
11 #include "dosexe.h"
12 #include "miscemu.h"
13 #include "msdos.h"
14 #include "console.h"
15 #include "file.h"
16 #include "debugtools.h"
17
18 DEFAULT_DEBUG_CHANNEL(int21);
19
20 void WINAPI DOSVM_Int21Handler_Ioctl( CONTEXT86 *context )
21 {
22   const DOS_DEVICE *dev = DOSFS_GetDeviceByHandle(
23       DosFileHandleToWin32Handle(BX_reg(context)) );
24
25   if (dev && !strcasecmp( dev->name, "EMMXXXX0" )) {
26     EMS_Ioctl_Handler(context);
27     return;
28   }
29
30   switch (AL_reg(context))
31   {
32   case 0x0b: /* SET SHARING RETRY COUNT */
33       TRACE("IOCTL - SET SHARING RETRY COUNT pause %d retries %d\n",
34            CX_reg(context), DX_reg(context));
35       if (!CX_reg(context))
36       {
37          AX_reg(context) = 1;
38          SET_CFLAG(context);
39          break;
40       }
41       DOSMEM_LOL()->sharing_retry_delay = CX_reg(context);
42       if (!DX_reg(context))
43          DOSMEM_LOL()->sharing_retry_count = DX_reg(context);
44       RESET_CFLAG(context);
45       break;
46   default:
47       DOS3Call( context );
48   }
49 }
50
51 /***********************************************************************
52  *           DOSVM_Int21Handler
53  *
54  * int 21h real-mode handler. Most calls are passed directly to DOS3Call.
55  */
56 void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
57 {
58     RESET_CFLAG(context);  /* Not sure if this is a good idea */
59
60     switch(AH_reg(context))
61     {
62     case 0x00: /* TERMINATE PROGRAM */
63         TRACE("TERMINATE PROGRAM\n");
64         MZ_Exit( context, FALSE, 0 );
65         break;
66
67     case 0x01: /* READ CHARACTER FROM STANDARD INPUT, WITH ECHO */
68         TRACE("DIRECT CHARACTER INPUT WITH ECHO\n");
69         AL_reg(context) = CONSOLE_GetCharacter();
70         /* FIXME: no echo */
71         break;
72
73     case 0x02: /* WRITE CHARACTER TO STANDARD OUTPUT */
74         TRACE("Write Character to Standard Output\n");
75         CONSOLE_Write(DL_reg(context), 0, 0, 0);
76         break;
77
78     case 0x06: /* DIRECT CONSOLE IN/OUTPUT */
79         /* FIXME: Use DOSDEV_Peek/Read/Write(DOSDEV_Console(),...) !! */
80         if (DL_reg(context) == 0xff) {
81             static char scan = 0;
82             TRACE("Direct Console Input\n");
83             if (scan) {
84                 /* return pending scancode */
85                 AL_reg(context) = scan;
86                 RESET_ZFLAG(context);
87                 scan = 0;
88             } else {
89                 char ascii;
90                 if (DOSVM_Int16ReadChar(&ascii,&scan,TRUE)) {
91                     DOSVM_Int16ReadChar(&ascii,&scan,FALSE);
92                     /* return ASCII code */
93                     AL_reg(context) = ascii;
94                     RESET_ZFLAG(context);
95                     /* return scan code on next call only if ascii==0 */
96                     if (ascii) scan = 0;
97                 } else {
98                     /* nothing pending, clear everything */
99                     AL_reg(context) = 0;
100                     SET_ZFLAG(context);
101                     scan = 0; /* just in case */
102                 }
103             }
104         } else {
105             TRACE("Direct Console Output\n");
106             CONSOLE_Write(DL_reg(context), 0, 0, 0);
107         }
108         break;
109
110     case 0x07: /* DIRECT CHARACTER INPUT WITHOUT ECHO */
111         /* FIXME: Use DOSDEV_Peek/Read(DOSDEV_Console(),...) !! */
112         TRACE("DIRECT CHARACTER INPUT WITHOUT ECHO\n");
113         DOSVM_Int16ReadChar(&AL_reg(context), NULL, FALSE);
114         break;
115
116     case 0x08: /* CHARACTER INPUT WITHOUT ECHO */
117         /* FIXME: Use DOSDEV_Peek/Read(DOSDEV_Console(),...) !! */
118         TRACE("CHARACTER INPUT WITHOUT ECHO\n");
119         DOSVM_Int16ReadChar(&AL_reg(context), NULL, FALSE);
120         break;
121
122     case 0x0b: /* GET STDIN STATUS */
123         {
124             BIOSDATA *data = DOSMEM_BiosData();
125             if(data->FirstKbdCharPtr == data->NextKbdCharPtr)
126                 AL_reg(context) = 0;
127             else
128                 AL_reg(context) = 0xff;
129         }
130         break;
131
132     case 0x25: /* SET INTERRUPT VECTOR */
133         DOSVM_SetRMHandler( AL_reg(context),
134                             (FARPROC16)MAKESEGPTR( context->SegDs, DX_reg(context)));
135         break;
136
137     case 0x35: /* GET INTERRUPT VECTOR */
138         TRACE("GET INTERRUPT VECTOR 0x%02x\n",AL_reg(context));
139         {
140             FARPROC16 addr = DOSVM_GetRMHandler( AL_reg(context) );
141             context->SegEs = SELECTOROF(addr);
142             BX_reg(context) = OFFSETOF(addr);
143         }
144         break;
145
146     case 0x44: /* IOCTL */
147         DOSVM_Int21Handler_Ioctl( context );
148         break;
149
150     case 0x4b: /* "EXEC" - LOAD AND/OR EXECUTE PROGRAM */
151         TRACE("EXEC %s\n", (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx ));
152         if (!MZ_Exec( context, CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx),
153                       AL_reg(context), CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Ebx) ))
154         {
155             AX_reg(context) = GetLastError();
156             SET_CFLAG(context);
157         }
158         break;
159
160     case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */
161         TRACE("EXIT with return code %d\n",AL_reg(context));
162         MZ_Exit( context, FALSE, AL_reg(context) );
163         break;
164
165     case 0x4d: /* GET RETURN CODE */
166         TRACE("GET RETURN CODE (ERRORLEVEL)\n");
167         AX_reg(context) = DOSVM_retval;
168         DOSVM_retval = 0;
169         break;
170
171     case 0x50: /* SET CURRENT PROCESS ID (SET PSP ADDRESS) */
172         TRACE("SET CURRENT PROCESS ID (SET PSP ADDRESS)\n");
173         DOSVM_psp = BX_reg(context);
174         break;
175
176     case 0x51: /* GET PSP ADDRESS */
177         TRACE("GET CURRENT PROCESS ID (GET PSP ADDRESS)\n");
178         /* FIXME: should we return the original DOS PSP upon */
179         /*        Windows startup ? */
180         BX_reg(context) = DOSVM_psp;
181         break;
182
183     case 0x52: /* "SYSVARS" - GET LIST OF LISTS */
184         TRACE("SYSVARS - GET LIST OF LISTS\n");
185         {
186             context->SegEs = HIWORD(DOS_LOLSeg);
187             BX_reg(context) = FIELD_OFFSET(DOS_LISTOFLISTS, ptr_first_DPB);
188         }
189         break;
190
191     case 0x62: /* GET PSP ADDRESS */
192         TRACE("GET CURRENT PSP ADDRESS\n");
193         /* FIXME: should we return the original DOS PSP upon */
194         /*        Windows startup ? */
195         BX_reg(context) = DOSVM_psp;
196         break;
197
198     default:
199         DOS3Call( context );
200     }
201 }