Fixed some issues found by winapi_check.
[wine] / dlls / winedos / interrupts.c
1 /*
2  * Interrupt emulation
3  *
4  * Copyright 2002 Jukka Heinonen
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "dosexe.h"
22 #include "wine/debug.h"
23 #include "wine/winbase16.h"
24
25 WINE_DEFAULT_DEBUG_CHANNEL(int);
26
27 /***********************************************************************
28  *              DOSVM_Int11Handler (WINEDOS16.117)
29  *              DOSVM_Int12Handler (WINEDOS16.118)
30  *              DOSVM_Int13Handler (WINEDOS16.119)
31  *              DOSVM_Int15Handler (WINEDOS16.121)
32  *              DOSVM_Int1aHandler (WINEDOS16.126)
33  *              DOSVM_Int25Handler (WINEDOS16.137)
34  *              DOSVM_Int26Handler (WINEDOS16.138)
35  *              DOSVM_Int2aHandler (WINEDOS16.142)
36  *              DOSVM_Int2fHandler (WINEDOS16.147)
37  *              DOSVM_Int34Handler (WINEDOS16.152)
38  *              DOSVM_Int35Handler (WINEDOS16.153)
39  *              DOSVM_Int36Handler (WINEDOS16.154)
40  *              DOSVM_Int37Handler (WINEDOS16.155)
41  *              DOSVM_Int38Handler (WINEDOS16.156)
42  *              DOSVM_Int39Handler (WINEDOS16.157)
43  *              DOSVM_Int3aHandler (WINEDOS16.158)
44  *              DOSVM_Int3bHandler (WINEDOS16.159)
45  *              DOSVM_Int3cHandler (WINEDOS16.160)
46  *              DOSVM_Int3dHandler (WINEDOS16.161)
47  *              DOSVM_Int3eHandler (WINEDOS16.162)
48  *              DOSVM_Int41Handler (WINEDOS16.165)
49  *              DOSVM_Int4bHandler (WINEDOS16.175)
50  *              DOSVM_Int5cHandler (WINEDOS16.192)
51  *
52  * FIXME: Interrupt handlers for interrupts implemented in other DLLs.
53  *        These functions should be removed when the interrupt handlers have
54  *        been moved to winedos.
55  */
56 void WINAPI DOSVM_Int11Handler( CONTEXT86 *context ) { INT_Int11Handler(context); }
57 void WINAPI DOSVM_Int12Handler( CONTEXT86 *context ) { INT_Int12Handler(context); }
58 void WINAPI DOSVM_Int13Handler( CONTEXT86 *context ) { INT_Int13Handler(context); }
59 void WINAPI DOSVM_Int15Handler( CONTEXT86 *context ) { INT_Int15Handler(context); }
60 void WINAPI DOSVM_Int1aHandler( CONTEXT86 *context ) { INT_Int1aHandler(context); }
61 void WINAPI DOSVM_Int25Handler( CONTEXT86 *context ) { INT_Int25Handler(context); }
62 void WINAPI DOSVM_Int26Handler( CONTEXT86 *context ) { INT_Int26Handler(context); }
63 void WINAPI DOSVM_Int2aHandler( CONTEXT86 *context ) { INT_Int2aHandler(context); }
64 void WINAPI DOSVM_Int2fHandler( CONTEXT86 *context ) { INT_Int2fHandler(context); }
65 void WINAPI DOSVM_Int34Handler( CONTEXT86 *context ) { INT_Int34Handler(context); }
66 void WINAPI DOSVM_Int35Handler( CONTEXT86 *context ) { INT_Int35Handler(context); }
67 void WINAPI DOSVM_Int36Handler( CONTEXT86 *context ) { INT_Int36Handler(context); }
68 void WINAPI DOSVM_Int37Handler( CONTEXT86 *context ) { INT_Int37Handler(context); }
69 void WINAPI DOSVM_Int38Handler( CONTEXT86 *context ) { INT_Int38Handler(context); }
70 void WINAPI DOSVM_Int39Handler( CONTEXT86 *context ) { INT_Int39Handler(context); }
71 void WINAPI DOSVM_Int3aHandler( CONTEXT86 *context ) { INT_Int3aHandler(context); }
72 void WINAPI DOSVM_Int3bHandler( CONTEXT86 *context ) { INT_Int3bHandler(context); }
73 void WINAPI DOSVM_Int3cHandler( CONTEXT86 *context ) { INT_Int3cHandler(context); }
74 void WINAPI DOSVM_Int3dHandler( CONTEXT86 *context ) { INT_Int3dHandler(context); }
75 void WINAPI DOSVM_Int3eHandler( CONTEXT86 *context ) { INT_Int3eHandler(context); }
76 void WINAPI DOSVM_Int41Handler( CONTEXT86 *context ) { INT_Int41Handler(context); }
77 void WINAPI DOSVM_Int4bHandler( CONTEXT86 *context ) { INT_Int4bHandler(context); }
78 void WINAPI DOSVM_Int5cHandler( CONTEXT86 *context ) { NetBIOSCall16(context); }
79
80 static FARPROC16     DOSVM_Vectors16[256];
81 static FARPROC48     DOSVM_Vectors48[256];
82 static const INTPROC DOSVM_VectorsBuiltin[] =
83 {
84   /* 00 */ 0,                  0,                  0,                  0,
85   /* 04 */ 0,                  0,                  0,                  0,
86   /* 08 */ 0,                  DOSVM_Int09Handler, 0,                  0,
87   /* 0C */ 0,                  0,                  0,                  0,
88   /* 10 */ DOSVM_Int10Handler, DOSVM_Int11Handler, DOSVM_Int12Handler, DOSVM_Int13Handler,
89   /* 14 */ 0,                  DOSVM_Int15Handler, DOSVM_Int16Handler, DOSVM_Int17Handler,
90   /* 18 */ 0,                  0,                  DOSVM_Int1aHandler, 0,
91   /* 1C */ 0,                  0,                  0,                  0,
92   /* 20 */ DOSVM_Int20Handler, DOSVM_Int21Handler, 0,                  0,
93   /* 24 */ 0,                  DOSVM_Int25Handler, DOSVM_Int26Handler, 0,
94   /* 28 */ 0,                  DOSVM_Int29Handler, DOSVM_Int2aHandler, 0,
95   /* 2C */ 0,                  0,                  0,                  DOSVM_Int2fHandler,
96   /* 30 */ 0,                  DOSVM_Int31Handler, 0,                  DOSVM_Int33Handler,
97   /* 34 */ DOSVM_Int34Handler, DOSVM_Int35Handler, DOSVM_Int36Handler, DOSVM_Int37Handler,
98   /* 38 */ DOSVM_Int38Handler, DOSVM_Int39Handler, DOSVM_Int3aHandler, DOSVM_Int3bHandler,
99   /* 3C */ DOSVM_Int3cHandler, DOSVM_Int3dHandler, DOSVM_Int3eHandler, 0,
100   /* 40 */ 0,                  DOSVM_Int41Handler, 0,                  0,
101   /* 44 */ 0,                  0,                  0,                  0,
102   /* 48 */ 0,                  0,                  0,                  DOSVM_Int4bHandler,
103   /* 4C */ 0,                  0,                  0,                  0,
104   /* 50 */ 0,                  0,                  0,                  0,
105   /* 54 */ 0,                  0,                  0,                  0,
106   /* 58 */ 0,                  0,                  0,                  0,
107   /* 5C */ DOSVM_Int5cHandler, 0,                  0,                  0,
108   /* 60 */ 0,                  0,                  0,                  0,
109   /* 64 */ 0,                  0,                  0,                  DOSVM_Int67Handler
110 };
111
112 /* Ordinal number for interrupt 0 handler in winedos16.dll */
113 #define FIRST_INTERRUPT 100
114
115 /**********************************************************************
116  *         DOSVM_DefaultHandler (WINEDOS16.356)
117  *
118  * Default interrupt handler. This will be used to emulate all
119  * interrupts that don't have their own interrupt handler.
120  */
121 void WINAPI DOSVM_DefaultHandler( CONTEXT86 *context )
122 {
123 }
124
125 /**********************************************************************
126  *         DOSVM_EmulateInterruptPM
127  *
128  * Emulate software interrupt in 16-bit or 32-bit protected mode.
129  * Called from signal handler when intXX opcode is executed. 
130  *
131  * Pushes interrupt frame to stack and changes instruction 
132  * pointer to interrupt handler.
133  */
134 void WINAPI DOSVM_EmulateInterruptPM( CONTEXT86 *context, BYTE intnum ) 
135 {
136   BOOL islong;
137
138   if(context->SegCs == DOSVM_dpmi_segments->int48_sel) 
139     islong = FALSE;
140   else if(DOSVM_IsDos32())
141     islong = TRUE;
142   else if(IS_SELECTOR_32BIT(context->SegCs)) {
143     WARN("Interrupt in 32-bit code and mode is not DPMI32\n");
144     islong = TRUE;
145   } else
146     islong = FALSE;
147
148   if(islong)
149   {
150     FARPROC48 addr = DOSVM_GetPMHandler48( intnum );
151     DWORD *stack = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp);
152     /* Push the flags and return address on the stack */
153     *(--stack) = context->EFlags;
154     *(--stack) = context->SegCs;
155     *(--stack) = context->Eip;
156     /* Jump to the interrupt handler */
157     context->SegCs  = addr.selector;
158     context->Eip = addr.offset;
159   }
160   else
161   {
162     FARPROC16 addr = INT_GetPMHandler( intnum ); /* FIXME: DOSVM_GetPMHandler16 */
163     WORD *stack = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp);
164     /* Push the flags and return address on the stack */
165     *(--stack) = LOWORD(context->EFlags);
166     *(--stack) = context->SegCs;
167     *(--stack) = LOWORD(context->Eip);
168     /* Jump to the interrupt handler */
169     context->SegCs  = HIWORD(addr);
170     context->Eip = LOWORD(addr);
171   }
172
173   if (IS_SELECTOR_32BIT(context->SegSs))
174     context->Esp += islong ? -12 : -6;
175   else
176     ADD_LOWORD( context->Esp, islong ? -12 : -6 );
177 }
178
179 /**********************************************************************
180  *          DOSVM_GetRMHandler
181  *
182  * Return the real mode interrupt vector for a given interrupt.
183  */
184 FARPROC16 DOSVM_GetRMHandler( BYTE intnum )
185 {
186   return ((FARPROC16*)0)[intnum];
187 }
188
189 /**********************************************************************
190  *          DOSVM_SetRMHandler
191  *
192  * Set the real mode interrupt handler for a given interrupt.
193  */
194 void DOSVM_SetRMHandler( BYTE intnum, FARPROC16 handler )
195 {
196   TRACE("Set real mode interrupt vector %02x <- %04x:%04x\n",
197        intnum, HIWORD(handler), LOWORD(handler) );
198   ((FARPROC16*)0)[intnum] = handler;
199 }
200
201 /**********************************************************************
202  *          DOSVM_GetPMHandler16
203  *
204  * Return the protected mode interrupt vector for a given interrupt.
205  */
206 FARPROC16 DOSVM_GetPMHandler16( BYTE intnum )
207 {
208   static HMODULE16 procs;
209   FARPROC16 handler = DOSVM_Vectors16[intnum];
210
211   if (!handler)
212   {
213     if (!procs &&
214         (procs = GetModuleHandle16( "winedos16" )) < 32 &&
215         (procs = LoadLibrary16( "winedos16" )) < 32)
216     {
217       ERR("could not load winedos16.dll\n");
218       procs = 0;
219       return 0;
220     }
221
222     handler = GetProcAddress16( procs, (LPCSTR)(FIRST_INTERRUPT + intnum));
223     if (!handler) 
224     {
225       WARN("int%x not implemented, returning dummy handler\n", intnum );
226       handler = GetProcAddress16( procs, (LPCSTR)(FIRST_INTERRUPT + 256));
227     }
228
229     DOSVM_Vectors16[intnum] = handler;
230   }
231
232   return handler;
233 }
234
235
236 /**********************************************************************
237  *          DOSVM_SetPMHandler16
238  *
239  * Set the protected mode interrupt handler for a given interrupt.
240  */
241 void DOSVM_SetPMHandler16( BYTE intnum, FARPROC16 handler )
242 {
243   TRACE("Set protected mode interrupt vector %02x <- %04x:%04x\n",
244        intnum, HIWORD(handler), LOWORD(handler) );
245   DOSVM_Vectors16[intnum] = handler;
246 }
247
248 /**********************************************************************
249  *         DOSVM_GetPMHandler48
250  *
251  * Return the protected mode interrupt vector for a given interrupt.
252  * Used to get 48-bit pointer for 32-bit interrupt handlers in DPMI32.
253  */
254 FARPROC48 DOSVM_GetPMHandler48( BYTE intnum )
255 {
256   if (!DOSVM_Vectors48[intnum].selector)
257   {
258     DOSVM_Vectors48[intnum].selector = DOSVM_dpmi_segments->int48_sel;
259     DOSVM_Vectors48[intnum].offset = 6 * intnum;
260   }
261   return DOSVM_Vectors48[intnum];
262 }
263
264 /**********************************************************************
265  *         DOSVM_SetPMHandler48
266  *
267  * Set the protected mode interrupt handler for a given interrupt.
268  * Used to set 48-bit pointer for 32-bit interrupt handlers in DPMI32.
269  */
270 void DOSVM_SetPMHandler48( BYTE intnum, FARPROC48 handler )
271 {
272   TRACE("Set 32-bit protected mode interrupt vector %02x <- %04x:%08lx\n",
273        intnum, handler.selector, handler.offset );
274   DOSVM_Vectors48[intnum] = handler;
275 }
276
277 /**********************************************************************
278  *         DOSVM_GetBuiltinHandler
279  *
280  * Return Wine interrupt handler procedure for a given interrupt.
281  */
282 INTPROC DOSVM_GetBuiltinHandler( BYTE intnum )
283 {
284   if (intnum < sizeof(DOSVM_VectorsBuiltin)/sizeof(INTPROC)) {
285     INTPROC proc = DOSVM_VectorsBuiltin[intnum];
286     if(proc)
287       return proc;
288   }
289
290   WARN("int%x not implemented, returning dummy handler\n", intnum );
291   return DOSVM_DefaultHandler;
292 }