Release 0.4.10
[wine/multimedia.git] / if1632 / callback.c
blob1852185f8d5b039c32f693389cff7ab3cc85245f
1 static char RCSId[] = "$Id: wine.c,v 1.2 1993/07/04 04:04:21 root Exp root $";
2 static char Copyright[] = "Copyright Robert J. Amstadt, 1993";
4 #include "windows.h"
5 #include "callback.h"
6 #include "wine.h"
7 #include "segmem.h"
8 #include <setjmp.h>
10 extern unsigned short SelectorOwners[];
11 extern unsigned short IF1632_Saved16_ss;
12 extern unsigned long IF1632_Saved16_ebp;
13 extern unsigned long IF1632_Saved16_esp;
14 extern unsigned short IF1632_Saved32_ss;
15 extern unsigned long IF1632_Saved32_ebp;
16 extern unsigned long IF1632_Saved32_esp;
18 extern struct segment_descriptor_s *MakeProcThunks;
20 struct thunk_s
22 int used;
23 unsigned char thunk[10];
26 /**********************************************************************
27 * PushOn16
29 static void
30 PushOn16(int size, unsigned int value)
32 char *p = (char *) (((unsigned int)IF1632_Saved16_ss << 16) +
33 (IF1632_Saved16_esp & 0xffff));
34 if (size)
36 unsigned long *lp = (unsigned long *) p - 1;
38 *lp = value;
39 IF1632_Saved16_esp -= 4;
41 else
43 unsigned short *sp = (unsigned short *) p - 1;
45 *sp = value;
46 IF1632_Saved16_esp -= 2;
50 /**********************************************************************
51 * FindDataSegmentForCode
53 static unsigned short
54 FindDataSegmentForCode(unsigned long csip)
56 unsigned int seg_idx;
58 seg_idx = (unsigned short) (csip >> 19);
59 return SelectorOwners[seg_idx];
62 /**********************************************************************
63 * CallBack16
65 int
66 CallBack16(void *func, int n_args, ...)
68 va_list ap;
69 int i;
70 int arg_type, arg_value;
72 va_start(ap, n_args);
74 for (i = 0; i < n_args; i++)
76 arg_type = va_arg(ap, int);
77 arg_value = va_arg(ap, int);
78 PushOn16(arg_type, arg_value);
81 va_end(ap);
83 return CallTo16((unsigned int) func,
84 FindDataSegmentForCode((unsigned long) func));
87 /**********************************************************************
88 * CALLBACK_MakeProcInstance
90 void *
91 CALLBACK_MakeProcInstance(void *func, int instance)
93 int handle;
94 void *new_func;
95 struct thunk_s *tp;
96 int i;
98 tp = (struct thunk_s *) MakeProcThunks->base_addr;
99 for (i = 0; i < 0x10000 / sizeof(*tp); i++, tp++)
100 if (!tp->used)
101 break;
103 if (tp->used)
104 return (void *) 0;
106 tp->thunk[0] = 0xb8;
107 tp->thunk[1] = (unsigned char) instance;
108 tp->thunk[2] = (unsigned char) (instance >> 8);
109 tp->thunk[3] = 0x8e;
110 tp->thunk[4] = 0xd8;
111 tp->thunk[5] = 0xea;
112 memcpy(&tp->thunk[6], &func, 4);
113 tp->used = 1;
115 return tp->thunk;
118 /**********************************************************************
119 * FreeProcInstance (KERNEL.52)
121 void FreeProcInstance(FARPROC func)
123 int handle;
124 void *new_func;
125 struct thunk_s *tp;
126 int i;
128 tp = (struct thunk_s *) MakeProcThunks->base_addr;
129 for (i = 0; i < 0x10000 / sizeof(*tp); i++, tp++)
131 if ((void *) tp->thunk == (void *) func)
133 tp->used = 0;
134 break;
139 /**********************************************************************
140 * CallWindowProc (USER.122)
142 LONG CallWindowProc( FARPROC func, HWND hwnd, WORD message,
143 WORD wParam, LONG lParam )
145 if (Is16bitAddress(func))
147 PushOn16( CALLBACK_SIZE_WORD, hwnd );
148 PushOn16( CALLBACK_SIZE_WORD, message );
149 PushOn16( CALLBACK_SIZE_WORD, wParam );
150 PushOn16( CALLBACK_SIZE_LONG, lParam );
151 return CallTo16((unsigned int) func,
152 FindDataSegmentForCode((unsigned long) func));
154 else
156 return (*func)(hwnd, message, wParam, lParam);
160 /**********************************************************************
161 * CallLineDDAProc
163 void CallLineDDAProc(FARPROC func, short xPos, short yPos, long lParam)
165 if (Is16bitAddress(func))
167 PushOn16( CALLBACK_SIZE_WORD, xPos );
168 PushOn16( CALLBACK_SIZE_WORD, yPos );
169 PushOn16( CALLBACK_SIZE_LONG, lParam );
170 CallTo16((unsigned int) func,
171 FindDataSegmentForCode((unsigned long) func));
173 else
175 (*func)(xPos, yPos, lParam);
179 /* ------------------------------------------------------------------------ */
181 * The following functions realize the Catch/Throw functionality.
182 * My thought is to use the setjmp, longjmp combination to do the
183 * major part of this one. All I have to remember, in addition to
184 * whatever the jmp_buf contains, is the contents of the 16-bit
185 * sp, bp and ss. I do this by storing them in the structure passed
186 * to me by the 16-bit program (including my own jmp_buf...).
187 * Hopefully there isn't any program that modifies the contents!
188 * Bad thing: I have to save part of the stack, since this will
189 * get reused on the next call after my return, leaving it in an
190 * undefined state.
192 #define STACK_DEPTH_16 28
194 struct special_buffer {
195 jmp_buf buffer;
196 long regs [6];
197 char stack_part [STACK_DEPTH_16];
198 } *sb;
200 int Catch (LPCATCHBUF cbuf)
202 WORD retval;
203 jmp_buf *tmp_jmp;
204 char *stack16 = (char *) (((unsigned int)IF1632_Saved16_ss << 16) +
205 (IF1632_Saved16_esp & 0xffff));
207 sb = malloc (sizeof (struct special_buffer));
209 sb -> regs [0] = IF1632_Saved16_esp;
210 sb -> regs [1] = IF1632_Saved16_ebp;
211 sb -> regs [2] = IF1632_Saved16_ss & 0xffff;
212 sb -> regs [3] = IF1632_Saved32_esp;
213 sb -> regs [4] = IF1632_Saved32_ebp;
214 sb -> regs [5] = IF1632_Saved32_ss & 0xffff;
215 memcpy (sb -> stack_part, stack16, STACK_DEPTH_16);
216 tmp_jmp = &sb -> buffer;
217 *((struct special_buffer **)cbuf) = sb;
219 if ((retval = setjmp (*tmp_jmp)))
221 IF1632_Saved16_esp = sb -> regs [0];
222 IF1632_Saved16_ebp = sb -> regs [1];
223 IF1632_Saved16_ss = sb -> regs [2] & 0xffff;
224 IF1632_Saved32_esp = sb -> regs [3];
225 IF1632_Saved32_ebp = sb -> regs [4];
226 IF1632_Saved32_ss = sb -> regs [5] & 0xffff;
227 stack16 = (char *) (((unsigned int)IF1632_Saved16_ss << 16) +
228 (IF1632_Saved16_esp & 0xffff));
230 memcpy (stack16, sb -> stack_part, STACK_DEPTH_16);
231 #ifdef DEBUG_CATCH
232 printf ("Been thrown here: %d, retval = %d\n", sb, retval);
233 #endif
234 free ((void *) sb);
235 return (retval);
236 } else {
237 #ifdef DEBUG_CATCH
238 printf ("Will somtime get thrown here: %d\n", sb);
239 #endif
240 return (retval);
244 void Throw (LPCATCHBUF cbuf, int val)
246 sb = *((struct special_buffer **)cbuf);
247 #ifdef DEBUG_CATCH
248 printf ("Throwing to: %d\n", sb);
249 #endif
250 longjmp (sb -> buffer, val);