Fixes crash when running without external shell32.dll.
[wine/multimedia.git] / msdos / int2f.c
blobac8bf4b9f59edec145e887e73a9298df93cff7f4
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;
98 case 0x1a: /* ANSI.SYS / AVATAR.SYS Install Check */
99 /* Not supported yet, do nothing */
100 break;
102 case 0x43:
103 #if 1
104 switch (AL_reg(context))
106 case 0x00: /* XMS v2+ installation check */
107 WARN(int,"XMS is not fully implemented\n");
108 AL_reg(context) = 0x80;
109 break;
110 case 0x10: /* XMS v2+ get driver address */
112 TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
113 NE_MODULE *pModule = pTask ? NE_GetPtr( pTask->hModule ) : NULL;
114 GlobalUnlock16( GetCurrentTask() );
115 #ifdef MZ_SUPPORTED
116 if (pModule && pModule->lpDosTask)
117 ES_reg(context) = pModule->lpDosTask->xms_seg;
118 else
119 #endif
120 ES_reg(context) = 0;
121 BX_reg(context) = 0;
122 break;
124 default:
125 INT_BARF( context, 0x2f );
127 #else
128 FIXME(int,"check for XMS (not supported)\n");
129 AL_reg(context) = 0x42; /* != 0x80 */
130 #endif
131 break;
133 case 0x45:
134 switch (AL_reg(context))
136 case 0x00:
137 case 0x01:
138 case 0x02:
139 case 0x03:
140 case 0x04:
141 case 0x05:
142 case 0x06:
143 case 0x07:
144 case 0x08:
145 /* Microsoft Profiler - not installed */
146 break;
147 default:
148 INT_BARF( context, 0x2f );
150 break;
152 case 0x4a:
153 switch(AL_reg(context))
155 case 0x10: /* smartdrv */
156 break; /* not installed */
157 case 0x11: /* dblspace */
158 break; /* not installed */
159 case 0x12: /* realtime compression interface */
160 break; /* not installed */
161 case 0x32: /* patch IO.SYS (???) */
162 break; /* we have no IO.SYS, so we can't patch it :-/ */
163 default:
164 INT_BARF( context, 0x2f );
166 break;
167 case 0x56: /* INTERLNK */
168 switch(AL_reg(context))
170 case 0x01: /* check if redirected drive */
171 AL_reg(context) = 0; /* not redirected */
172 break;
173 default:
174 INT_BARF( context, 0x2f );
176 break;
177 case 0x7a: /* NOVELL NetWare */
178 switch (AL_reg(context))
180 case 0x20: /* Get VLM Call Address */
181 /* return nothing -> NetWare not installed */
182 break;
183 default:
184 INT_BARF( context, 0x2f );
185 break;
187 break;
188 case 0xb7: /* append */
189 AL_reg(context) = 0; /* not installed */
190 break;
191 case 0xb8: /* network */
192 switch (AL_reg(context))
194 case 0x00: /* Install check */
195 /* not installed */
196 break;
197 default:
198 INT_BARF( context, 0x2f );
199 break;
201 break;
202 case 0xbd: /* some Novell network install check ??? */
203 AX_reg(context) = 0xa5a5; /* pretend to have Novell IPX installed */
204 break;
205 case 0xbf: /* REDIRIFS.EXE */
206 switch (AL_reg(context))
208 case 0x00: /* Install check */
209 /* not installed */
210 break;
211 default:
212 INT_BARF( context, 0x2f );
213 break;
215 break;
216 case 0xd7: /* Banyan Vines */
217 switch (AL_reg(context))
219 case 0x01: /* Install check - Get Int Number */
220 /* not installed */
221 break;
222 default:
223 INT_BARF( context, 0x2f );
224 break;
226 break;
227 case 0xfa: /* Watcom debugger check, returns 0x666 if installed */
228 break;
229 default:
230 INT_BARF( context, 0x2f );
231 break;
236 /**********************************************************************
237 * do_int2f_16
239 static void do_int2f_16( CONTEXT *context )
241 DWORD addr;
243 switch(AL_reg(context))
245 case 0x00: /* Windows enhanced mode installation check */
246 AX_reg(context) = (GetWinFlags() & WF_ENHANCED) ?
247 LOWORD(GetVersion16()) : 0;
248 break;
250 case 0x0a: /* Get Windows version and type */
251 AX_reg(context) = 0;
252 BX_reg(context) = (LOWORD(GetVersion16()) << 8) |
253 (LOWORD(GetVersion16()) >> 8);
254 CX_reg(context) = (GetWinFlags() & WF_ENHANCED) ? 3 : 2;
255 break;
257 case 0x0b: /* Identify Windows-aware TSRs */
258 /* we don't have any pre-Windows TSRs */
259 break;
261 case 0x11: /* Get Shell Parameters - (SHELL= in CONFIG.SYS) */
262 /* We can mock this up. But not today... */
263 FIXME(int, "Get Shell Parameters\n");
264 break;
266 case 0x80: /* Release time-slice */
267 AL_reg(context) = 0;
268 /* FIXME: We need to do something that lets some other process run
269 here. */
270 sleep(0);
271 break;
273 case 0x81: /* Begin critical section. */
274 /* FIXME? */
275 break;
277 case 0x82: /* End critical section. */
278 /* FIXME? */
279 break;
281 case 0x83: /* Return Current Virtual Machine ID */
282 /* Virtual Machines are usually created/destroyed when Windows runs
283 * DOS programs. Since we never do, we are always in the System VM.
284 * According to Ralf Brown's Interrupt List, never return 0. But it
285 * seems to work okay (returning 0), just to be sure we return 1.
287 BX_reg(context) = 1; /* VM 1 is probably the System VM */
288 break;
290 case 0x84: /* Get device API entry point */
291 addr = (DWORD)NE_GetEntryPoint( GetModuleHandle16("WPROCS"),
292 VXD_BASE + BX_reg(context) );
293 if (!addr) /* not supported */
295 ERR(int,"Accessing unknown VxD %04x - Expect a failure now.\n",
296 BX_reg(context) );
298 ES_reg(context) = SELECTOROF(addr);
299 DI_reg(context) = OFFSETOF(addr);
300 break;
302 case 0x86: /* DPMI detect mode */
303 AX_reg(context) = 0; /* Running under DPMI */
304 break;
306 case 0x87: /* DPMI installation check */
307 #if 1 /* DPMI still breaks pkunzip */
308 if (ISV86(context)) break; /* so bail out for now if in v86 mode */
309 #endif
311 TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
312 NE_MODULE *pModule = pTask ? NE_GetPtr( pTask->hModule ) : NULL;
313 SYSTEM_INFO si;
315 GlobalUnlock16( GetCurrentTask() );
316 GetSystemInfo(&si);
317 AX_reg(context) = 0x0000; /* DPMI Installed */
318 BX_reg(context) = 0x0001; /* 32bits available */
319 CL_reg(context) = si.wProcessorLevel;
320 DX_reg(context) = 0x005a; /* DPMI major/minor 0.90 */
321 SI_reg(context) = 0; /* # of para. of DOS extended private data */
322 #ifdef MZ_SUPPORTED /* ES:DI is DPMI switch entry point */
323 if (pModule && pModule->lpDosTask)
324 ES_reg(context) = pModule->lpDosTask->dpmi_seg;
325 else
326 #endif
327 ES_reg(context) = 0;
328 DI_reg(context) = 0;
329 break;
331 case 0x8a: /* DPMI get vendor-specific API entry point. */
332 /* The 1.0 specs say this should work with all 0.9 hosts. */
333 break;
335 default:
336 INT_BARF( context, 0x2f );
340 void do_mscdex( CONTEXT *context )
342 int drive, count;
343 char *p;
345 switch(AL_reg(context))
347 case 0x00: /* Installation check */
348 /* Count the number of contiguous CDROM drives
350 for (drive = count = 0; drive < MAX_DOS_DRIVES; drive++)
352 if (DRIVE_GetType(drive) == TYPE_CDROM)
354 while (DRIVE_GetType(drive + count) == TYPE_CDROM) count++;
355 break;
359 BX_reg(context) = count;
360 CX_reg(context) = (drive < MAX_DOS_DRIVES) ? drive : 0;
361 break;
363 case 0x0B: /* drive check */
364 AX_reg(context) = (DRIVE_GetType(CX_reg(context)) == TYPE_CDROM);
365 BX_reg(context) = 0xADAD;
366 break;
368 case 0x0C: /* get version */
369 BX_reg(context) = 0x020a;
370 break;
372 case 0x0D: /* get drive letters */
373 p = CTX_SEG_OFF_TO_LIN(context, ES_reg(context), EBX_reg(context));
374 memset( p, 0, MAX_DOS_DRIVES );
375 for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
377 if (DRIVE_GetType(drive) == TYPE_CDROM) *p++ = drive;
379 break;
381 #ifdef linux
382 /* FIXME: why a new linux-only CDROM drive access, for crying out loud?
383 * There are pretty complete routines in multimedia/mcicda.c already! */
384 case 0x10: /* direct driver acces */
385 FIXME(cdaudio,"mscdex should use multimedia/mcicda.c");
386 do_mscdex_dd(context,ISV86(context));
387 break;
389 #endif
391 default:
392 FIXME(int, "Unimplemented MSCDEX function 0x%02X.\n", AL_reg(context));
393 break;