Release 980913
[wine/wine-kai.git] / msdos / int2f.c
blob0559fff1236c8760e09172fe330649d10de6b0b7
1 /*
2 * DOS interrupt 2fh handler
3 */
5 #include <stdlib.h>
6 #include <string.h>
7 #include <unistd.h>
9 #include "ldt.h"
10 #include "drive.h"
11 #include "msdos.h"
12 #include "miscemu.h"
13 #include "module.h"
14 /* #define DEBUG_INT */
15 #include "debug.h"
17 /* base WPROCS.DLL ordinal number for VxDs */
18 #define VXD_BASE 400
20 static void do_int2f_16( CONTEXT *context );
22 /**********************************************************************
23 * INT_Int2fHandler
25 * Handler for int 2fh (multiplex).
27 void WINAPI INT_Int2fHandler( CONTEXT *context )
29 TRACE(int,"Subfunction 0x%X\n", AH_reg(context));
31 switch(AH_reg(context))
33 case 0x10:
34 AL_reg(context) = 0xff; /* share is installed */
35 break;
37 case 0x12:
38 switch (AL_reg(context))
40 case 0x2e: /* get or set DOS error table address */
41 switch (DL_reg(context))
43 /* Four tables: even commands are 'get', odd are 'set' */
44 /* DOS 5.0+ ignores "set" commands */
45 case 0x01:
46 case 0x03:
47 case 0x05:
48 case 0x07:
49 case 0x09:
50 break;
51 /* Instead of having a message table in DOS-space, */
52 /* we can use a special case for MS-DOS to force */
53 /* the secondary interface. */
54 case 0x00:
55 case 0x02:
56 case 0x04:
57 case 0x06:
58 ES_reg(context) = 0x0001;
59 DI_reg(context) = 0x0000;
60 break;
61 case 0x08:
62 FIXME(int, "No real-mode handler for errors yet! (bye!)");
63 break;
64 default:
65 INT_BARF(context, 0x2f);
67 break;
68 default:
69 INT_BARF(context, 0x2f);
71 break;
73 case 0x15: /* mscdex */
74 do_mscdex(context);
75 break;
77 case 0x16:
78 do_int2f_16( context );
79 break;
80 case 0x43:
81 FIXME(int,"check for XMS (not supported)\n");
82 AL_reg(context) = 0x42; /* != 0x80 */
83 break;
85 case 0x45:
86 switch (AL_reg(context))
88 case 0x00:
89 case 0x01:
90 case 0x02:
91 case 0x03:
92 case 0x04:
93 case 0x05:
94 case 0x06:
95 case 0x07:
96 case 0x08:
97 /* Microsoft Profiler - not installed */
98 break;
99 default:
100 INT_BARF( context, 0x2f );
102 break;
104 case 0x4a:
105 switch(AL_reg(context))
107 case 0x10: /* smartdrv */
108 break; /* not installed */
109 case 0x11: /* dblspace */
110 break; /* not installed */
111 case 0x12: /* realtime compression interface */
112 break; /* not installed */
113 default:
114 INT_BARF( context, 0x2f );
116 break;
117 case 0x56: /* INTERLNK */
118 switch(AL_reg(context))
120 case 0x01: /* check if redirected drive */
121 AL_reg(context) = 0; /* not redirected */
122 break;
123 default:
124 INT_BARF( context, 0x2f );
126 break;
127 case 0x7a: /* NOVELL NetWare */
128 switch (AL_reg(context))
130 case 0x20: /* Get VLM Call Address */
131 /* return nothing -> NetWare not installed */
132 break;
133 default:
134 SET_CFLAG(context);
135 break;
137 break;
138 case 0xb7: /* append */
139 AL_reg(context) = 0; /* not installed */
140 break;
141 case 0xbd: /* some Novell network install check ??? */
142 AX_reg(context) = 0xa5a5; /* pretend to have Novell IPX installed */
143 break;
144 case 0xfa: /* Watcom debugger check, returns 0x666 if installed */
145 break;
146 default:
147 INT_BARF( context, 0x2f );
148 break;
153 /**********************************************************************
154 * do_int2f_16
156 static void do_int2f_16( CONTEXT *context )
158 DWORD addr;
160 switch(AL_reg(context))
162 case 0x00: /* Windows enhanced mode installation check */
163 AX_reg(context) = (GetWinFlags() & WF_ENHANCED) ?
164 LOWORD(GetVersion16()) : 0;
165 break;
167 case 0x0a: /* Get Windows version and type */
168 AX_reg(context) = 0;
169 BX_reg(context) = (LOWORD(GetVersion16()) << 8) |
170 (LOWORD(GetVersion16()) >> 8);
171 CX_reg(context) = (GetWinFlags() & WF_ENHANCED) ? 3 : 2;
172 break;
174 case 0x80: /* Release time-slice */
175 AL_reg(context) = 0;
176 /* FIXME: We need to do something that lets some other process run
177 here. */
178 sleep(0);
179 break;
181 case 0x81: /* Begin critical section. */
182 /* FIXME? */
183 break;
185 case 0x82: /* End critical section. */
186 /* FIXME? */
187 break;
189 case 0x83: /* Return Current Virtual Machine ID */
190 /* Virtual Machines are usually created/destroyed when Windows runs
191 * DOS programs. Since we never do, we are always in the System VM.
192 * According to Ralf Brown's Interrupt List, never return 0. But it
193 * seems to work okay (returning 0), just to be sure we return 1.
195 BX_reg(context) = 1; /* VM 1 is probably the System VM */
196 break;
198 case 0x84: /* Get device API entry point */
199 addr = (DWORD)NE_GetEntryPoint( GetModuleHandle16("WPROCS"),
200 VXD_BASE + BX_reg(context) );
201 if (!addr) /* not supported */
203 WARN(int,"Application attempted to access VxD %04x\n",
204 BX_reg(context) );
205 WARN(int,"This device is not known to Wine.");
206 WARN(int,"Expect a failure now\n");
208 ES_reg(context) = SELECTOROF(addr);
209 DI_reg(context) = OFFSETOF(addr);
210 break;
212 case 0x86: /* DPMI detect mode */
213 AX_reg(context) = 0; /* Running under DPMI */
214 break;
216 /* FIXME: is this right? Specs say that this should only be callable
217 in real (v86) mode which we never enter. */
218 /* FIXME: we do now, and this breaks pkunzip */
219 case 0x87: /* DPMI installation check */
220 if (ISV86(context)) break; /* so bail out for now if in v86 mode */
222 SYSTEM_INFO si;
224 GetSystemInfo(&si);
225 AX_reg(context) = 0x0000; /* DPMI Installed */
226 BX_reg(context) = 0x0001; /* 32bits available */
227 CL_reg(context) = si.wProcessorLevel;
228 DX_reg(context) = 0x005a; /* DPMI major/minor 0.90 */
229 SI_reg(context) = 0; /* # of para. of DOS extended private data */
230 ES_reg(context) = 0; /* ES:DI is DPMI switch entry point */
231 DI_reg(context) = 0;
232 break;
234 case 0x8a: /* DPMI get vendor-specific API entry point. */
235 /* The 1.0 specs say this should work with all 0.9 hosts. */
236 break;
238 default:
239 INT_BARF( context, 0x2f );
243 void do_mscdex( CONTEXT *context )
245 int drive, count;
246 char *p;
248 switch(AL_reg(context))
250 case 0x00: /* Installation check */
251 /* Count the number of contiguous CDROM drives
253 for (drive = count = 0; drive < MAX_DOS_DRIVES; drive++)
255 if (DRIVE_GetType(drive) == TYPE_CDROM)
257 while (DRIVE_GetType(drive + count) == TYPE_CDROM) count++;
258 break;
262 BX_reg(context) = count;
263 CX_reg(context) = (drive < MAX_DOS_DRIVES) ? drive : 0;
264 break;
266 case 0x0B: /* drive check */
267 AX_reg(context) = (DRIVE_GetType(CX_reg(context)) == TYPE_CDROM);
268 BX_reg(context) = 0xADAD;
269 break;
271 case 0x0C: /* get version */
272 BX_reg(context) = 0x020a;
273 break;
275 case 0x0D: /* get drive letters */
276 p = CTX_SEG_OFF_TO_LIN(context, ES_reg(context), BX_reg(context));
277 memset( p, 0, MAX_DOS_DRIVES );
278 for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
280 if (DRIVE_GetType(drive) == TYPE_CDROM) *p++ = drive;
282 break;
284 #ifdef linux
285 /* FIXME: why a new linux-only CDROM drive access, for crying out loud?
286 * There are pretty complete routines in multimedia/mcicda.c already! */
287 case 0x10: /* direct driver acces */
288 FIXME(cdaudio,"mscdex should use multimedia/mcicda.c");
289 do_mscdex_dd(context,ISV86(context));
290 break;
292 #endif
294 default:
295 FIXME(int, "Unimplemented MSCDEX function 0x%02X.\n", AL_reg(context));
296 break;