Release 940420
[wine/testsucceed.git] / if1632 / callback.c
blobac2ab9f79beb69e7a22b64c9b24b6741e32eeab7
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 SEGDESC Segments[];
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 Segments[seg_idx].owner;
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 SpyMessage(hwnd, message, wParam, lParam);
147 if (Is16bitAddress(func))
149 PushOn16( CALLBACK_SIZE_WORD, hwnd );
150 PushOn16( CALLBACK_SIZE_WORD, message );
151 PushOn16( CALLBACK_SIZE_WORD, wParam );
152 PushOn16( CALLBACK_SIZE_LONG, lParam );
153 return CallTo16((unsigned int) func,
154 FindDataSegmentForCode((unsigned long) func));
156 else
158 return (*func)(hwnd, message, wParam, lParam);
162 /**********************************************************************
163 * CallLineDDAProc
165 void CallLineDDAProc(FARPROC func, short xPos, short yPos, long lParam)
167 if (Is16bitAddress(func))
169 PushOn16( CALLBACK_SIZE_WORD, xPos );
170 PushOn16( CALLBACK_SIZE_WORD, yPos );
171 PushOn16( CALLBACK_SIZE_LONG, lParam );
172 CallTo16((unsigned int) func,
173 FindDataSegmentForCode((unsigned long) func));
175 else
177 (*func)(xPos, yPos, lParam);
181 /**********************************************************************
182 * CallHookProc
184 DWORD CallHookProc( HOOKPROC func, short code, WPARAM wParam, LPARAM lParam )
186 if (Is16bitAddress(func))
188 PushOn16( CALLBACK_SIZE_WORD, code );
189 PushOn16( CALLBACK_SIZE_WORD, wParam );
190 PushOn16( CALLBACK_SIZE_LONG, lParam );
191 return CallTo16((unsigned int) func,
192 FindDataSegmentForCode((unsigned long) func));
194 else
196 return (*func)( code, wParam, lParam );
200 /**********************************************************************
201 * CallGrayStringProc
203 BOOL CallGrayStringProc(FARPROC func, HDC hdc, LPARAM lParam, INT cch )
205 if (Is16bitAddress(func))
207 PushOn16( CALLBACK_SIZE_WORD, hdc );
208 PushOn16( CALLBACK_SIZE_LONG, lParam );
209 PushOn16( CALLBACK_SIZE_WORD, cch );
210 return CallTo16((unsigned int) func,
211 FindDataSegmentForCode((unsigned long) func));
213 else
215 return (*func)( hdc, lParam, cch );
219 /* ------------------------------------------------------------------------ */
221 * The following functions realize the Catch/Throw functionality.
222 * My thought is to use the setjmp, longjmp combination to do the
223 * major part of this one. All I have to remember, in addition to
224 * whatever the jmp_buf contains, is the contents of the 16-bit
225 * sp, bp and ss. I do this by storing them in the structure passed
226 * to me by the 16-bit program (including my own jmp_buf...).
227 * Hopefully there isn't any program that modifies the contents!
228 * Bad thing: I have to save part of the stack, since this will
229 * get reused on the next call after my return, leaving it in an
230 * undefined state.
232 #define STACK_DEPTH_16 28
234 struct special_buffer {
235 jmp_buf buffer;
236 long regs [6];
237 char stack_part [STACK_DEPTH_16];
238 } *sb;
240 int Catch (LPCATCHBUF cbuf)
242 WORD retval;
243 jmp_buf *tmp_jmp;
244 char *stack16 = (char *) (((unsigned int)IF1632_Saved16_ss << 16) +
245 (IF1632_Saved16_esp & 0xffff));
247 sb = malloc (sizeof (struct special_buffer));
249 sb -> regs [0] = IF1632_Saved16_esp;
250 sb -> regs [1] = IF1632_Saved16_ebp;
251 sb -> regs [2] = IF1632_Saved16_ss & 0xffff;
252 sb -> regs [3] = IF1632_Saved32_esp;
253 sb -> regs [4] = IF1632_Saved32_ebp;
254 sb -> regs [5] = IF1632_Saved32_ss & 0xffff;
255 memcpy (sb -> stack_part, stack16, STACK_DEPTH_16);
256 tmp_jmp = &sb -> buffer;
257 *((struct special_buffer **)cbuf) = sb;
259 if ((retval = setjmp (*tmp_jmp)))
261 IF1632_Saved16_esp = sb -> regs [0];
262 IF1632_Saved16_ebp = sb -> regs [1];
263 IF1632_Saved16_ss = sb -> regs [2] & 0xffff;
264 IF1632_Saved32_esp = sb -> regs [3];
265 IF1632_Saved32_ebp = sb -> regs [4];
266 IF1632_Saved32_ss = sb -> regs [5] & 0xffff;
267 stack16 = (char *) (((unsigned int)IF1632_Saved16_ss << 16) +
268 (IF1632_Saved16_esp & 0xffff));
270 memcpy (stack16, sb -> stack_part, STACK_DEPTH_16);
271 #ifdef DEBUG_CATCH
272 printf ("Been thrown here: %d, retval = %d\n", sb, retval);
273 #endif
274 free ((void *) sb);
275 return (retval);
276 } else {
277 #ifdef DEBUG_CATCH
278 printf ("Will somtime get thrown here: %d\n", sb);
279 #endif
280 return (retval);
284 void Throw (LPCATCHBUF cbuf, int val)
286 sb = *((struct special_buffer **)cbuf);
287 #ifdef DEBUG_CATCH
288 printf ("Throwing to: %d\n", sb);
289 #endif
290 longjmp (sb -> buffer, val);