Release 980927
[wine.git] / msdos / int2f.c
blob7a88d80e5743fa71433c7a6f05ec928936c97659
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 #include "task.h"
15 #include "dosexe.h"
16 /* #define DEBUG_INT */
17 #include "debug.h"
19 /* base WPROCS.DLL ordinal number for VxDs */
20 #define VXD_BASE 400
22 static void do_int2f_16( CONTEXT *context );
24 /**********************************************************************
25 * INT_Int2fHandler
27 * Handler for int 2fh (multiplex).
29 void WINAPI INT_Int2fHandler( CONTEXT *context )
31 TRACE(int,"Subfunction 0x%X\n", AH_reg(context));
33 switch(AH_reg(context))
35 case 0x10:
36 AL_reg(context) = 0xff; /* share is installed */
37 break;
39 case 0x11: /* Network Redirector / IFSFUNC */
40 switch (AL_reg(context))
42 case 0x00: /* Install check */
43 /* not installed */
44 break;
45 case 0x80: /* Enhanced services - Install check */
46 /* not installed */
47 break;
48 default:
49 INT_BARF( context, 0x2f );
50 break;
52 break;
54 case 0x12:
55 switch (AL_reg(context))
57 case 0x2e: /* get or set DOS error table address */
58 switch (DL_reg(context))
60 /* Four tables: even commands are 'get', odd are 'set' */
61 /* DOS 5.0+ ignores "set" commands */
62 case 0x01:
63 case 0x03:
64 case 0x05:
65 case 0x07:
66 case 0x09:
67 break;
68 /* Instead of having a message table in DOS-space, */
69 /* we can use a special case for MS-DOS to force */
70 /* the secondary interface. */
71 case 0x00:
72 case 0x02:
73 case 0x04:
74 case 0x06:
75 ES_reg(context) = 0x0001;
76 DI_reg(context) = 0x0000;
77 break;
78 case 0x08:
79 FIXME(int, "No real-mode handler for errors yet! (bye!)");
80 break;
81 default:
82 INT_BARF(context, 0x2f);
84 break;
85 default:
86 INT_BARF(context, 0x2f);
88 break;
90 case 0x15: /* mscdex */
91 do_mscdex(context);
92 break;
94 case 0x16:
95 do_int2f_16( context );
96 break;
97 case 0x43:
98 FIXME(int,"check for XMS (not supported)\n");
99 AL_reg(context) = 0x42; /* != 0x80 */
100 break;
102 case 0x45:
103 switch (AL_reg(context))
105 case 0x00:
106 case 0x01:
107 case 0x02:
108 case 0x03:
109 case 0x04:
110 case 0x05:
111 case 0x06:
112 case 0x07:
113 case 0x08:
114 /* Microsoft Profiler - not installed */
115 break;
116 default:
117 INT_BARF( context, 0x2f );
119 break;
121 case 0x4a:
122 switch(AL_reg(context))
124 case 0x10: /* smartdrv */
125 break; /* not installed */
126 case 0x11: /* dblspace */
127 break; /* not installed */
128 case 0x12: /* realtime compression interface */
129 break; /* not installed */
130 default:
131 INT_BARF( context, 0x2f );
133 break;
134 case 0x56: /* INTERLNK */
135 switch(AL_reg(context))
137 case 0x01: /* check if redirected drive */
138 AL_reg(context) = 0; /* not redirected */
139 break;
140 default:
141 INT_BARF( context, 0x2f );
143 break;
144 case 0x7a: /* NOVELL NetWare */
145 switch (AL_reg(context))
147 case 0x20: /* Get VLM Call Address */
148 /* return nothing -> NetWare not installed */
149 break;
150 default:
151 INT_BARF( context, 0x2f );
152 break;
154 break;
155 case 0xb7: /* append */
156 AL_reg(context) = 0; /* not installed */
157 break;
158 case 0xb8: /* network */
159 switch (AL_reg(context))
161 case 0x00: /* Install check */
162 /* not installed */
163 break;
164 default:
165 INT_BARF( context, 0x2f );
166 break;
168 break;
169 case 0xbd: /* some Novell network install check ??? */
170 AX_reg(context) = 0xa5a5; /* pretend to have Novell IPX installed */
171 break;
172 case 0xbf: /* REDIRIFS.EXE */
173 switch (AL_reg(context))
175 case 0x00: /* Install check */
176 /* not installed */
177 break;
178 default:
179 INT_BARF( context, 0x2f );
180 break;
182 break;
183 case 0xd7: /* Banyan Vines */
184 switch (AL_reg(context))
186 case 0x01: /* Install check - Get Int Number */
187 /* not installed */
188 break;
189 default:
190 INT_BARF( context, 0x2f );
191 break;
193 break;
194 case 0xfa: /* Watcom debugger check, returns 0x666 if installed */
195 break;
196 default:
197 INT_BARF( context, 0x2f );
198 break;
203 /**********************************************************************
204 * do_int2f_16
206 static void do_int2f_16( CONTEXT *context )
208 DWORD addr;
210 switch(AL_reg(context))
212 case 0x00: /* Windows enhanced mode installation check */
213 AX_reg(context) = (GetWinFlags() & WF_ENHANCED) ?
214 LOWORD(GetVersion16()) : 0;
215 break;
217 case 0x0a: /* Get Windows version and type */
218 AX_reg(context) = 0;
219 BX_reg(context) = (LOWORD(GetVersion16()) << 8) |
220 (LOWORD(GetVersion16()) >> 8);
221 CX_reg(context) = (GetWinFlags() & WF_ENHANCED) ? 3 : 2;
222 break;
224 case 0x80: /* Release time-slice */
225 AL_reg(context) = 0;
226 /* FIXME: We need to do something that lets some other process run
227 here. */
228 sleep(0);
229 break;
231 case 0x81: /* Begin critical section. */
232 /* FIXME? */
233 break;
235 case 0x82: /* End critical section. */
236 /* FIXME? */
237 break;
239 case 0x83: /* Return Current Virtual Machine ID */
240 /* Virtual Machines are usually created/destroyed when Windows runs
241 * DOS programs. Since we never do, we are always in the System VM.
242 * According to Ralf Brown's Interrupt List, never return 0. But it
243 * seems to work okay (returning 0), just to be sure we return 1.
245 BX_reg(context) = 1; /* VM 1 is probably the System VM */
246 break;
248 case 0x84: /* Get device API entry point */
249 addr = (DWORD)NE_GetEntryPoint( GetModuleHandle16("WPROCS"),
250 VXD_BASE + BX_reg(context) );
251 if (!addr) /* not supported */
253 ERR(int,"Accessing unknown VxD %04x - Expect a failure now.\n",
254 BX_reg(context) );
256 ES_reg(context) = SELECTOROF(addr);
257 DI_reg(context) = OFFSETOF(addr);
258 break;
260 case 0x86: /* DPMI detect mode */
261 AX_reg(context) = 0; /* Running under DPMI */
262 break;
264 case 0x87: /* DPMI installation check */
265 #if 1 /* DPMI still breaks pkunzip */
266 if (ISV86(context)) break; /* so bail out for now if in v86 mode */
267 #endif
269 TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
270 NE_MODULE *pModule = pTask ? NE_GetPtr( pTask->hModule ) : NULL;
271 SYSTEM_INFO si;
273 GlobalUnlock16( GetCurrentTask() );
274 GetSystemInfo(&si);
275 AX_reg(context) = 0x0000; /* DPMI Installed */
276 BX_reg(context) = 0x0001; /* 32bits available */
277 CL_reg(context) = si.wProcessorLevel;
278 DX_reg(context) = 0x005a; /* DPMI major/minor 0.90 */
279 SI_reg(context) = 0; /* # of para. of DOS extended private data */
280 #ifdef MZ_SUPPORTED /* ES:DI is DPMI switch entry point */
281 if (pModule && pModule->lpDosTask)
282 ES_reg(context) = pModule->lpDosTask->dpmi_seg;
283 else
284 #endif
285 ES_reg(context) = 0;
286 DI_reg(context) = 0;
287 break;
289 case 0x8a: /* DPMI get vendor-specific API entry point. */
290 /* The 1.0 specs say this should work with all 0.9 hosts. */
291 break;
293 default:
294 INT_BARF( context, 0x2f );
298 void do_mscdex( CONTEXT *context )
300 int drive, count;
301 char *p;
303 switch(AL_reg(context))
305 case 0x00: /* Installation check */
306 /* Count the number of contiguous CDROM drives
308 for (drive = count = 0; drive < MAX_DOS_DRIVES; drive++)
310 if (DRIVE_GetType(drive) == TYPE_CDROM)
312 while (DRIVE_GetType(drive + count) == TYPE_CDROM) count++;
313 break;
317 BX_reg(context) = count;
318 CX_reg(context) = (drive < MAX_DOS_DRIVES) ? drive : 0;
319 break;
321 case 0x0B: /* drive check */
322 AX_reg(context) = (DRIVE_GetType(CX_reg(context)) == TYPE_CDROM);
323 BX_reg(context) = 0xADAD;
324 break;
326 case 0x0C: /* get version */
327 BX_reg(context) = 0x020a;
328 break;
330 case 0x0D: /* get drive letters */
331 p = CTX_SEG_OFF_TO_LIN(context, ES_reg(context), BX_reg(context));
332 memset( p, 0, MAX_DOS_DRIVES );
333 for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
335 if (DRIVE_GetType(drive) == TYPE_CDROM) *p++ = drive;
337 break;
339 #ifdef linux
340 /* FIXME: why a new linux-only CDROM drive access, for crying out loud?
341 * There are pretty complete routines in multimedia/mcicda.c already! */
342 case 0x10: /* direct driver acces */
343 FIXME(cdaudio,"mscdex should use multimedia/mcicda.c");
344 do_mscdex_dd(context,ISV86(context));
345 break;
347 #endif
349 default:
350 FIXME(int, "Unimplemented MSCDEX function 0x%02X.\n", AL_reg(context));
351 break;