Release 940518
[wine/multimedia.git] / if1632 / callback.c
blob02f5cda195203eacfab169f0045c386e7bf007ac
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 <stdio.h>
5 #include <stdlib.h>
6 #include "windows.h"
7 #include "callback.h"
8 #include "wine.h"
9 #include "segmem.h"
10 #include <setjmp.h>
12 extern SEGDESC Segments[];
13 extern unsigned short IF1632_Saved16_ss;
14 extern unsigned long IF1632_Saved16_ebp;
15 extern unsigned long IF1632_Saved16_esp;
16 extern unsigned short IF1632_Saved32_ss;
17 extern unsigned long IF1632_Saved32_ebp;
18 extern unsigned long IF1632_Saved32_esp;
20 extern struct segment_descriptor_s *MakeProcThunks;
22 struct thunk_s
24 int used;
25 unsigned char thunk[10];
28 /**********************************************************************
29 * PushOn16
31 static void
32 PushOn16(int size, unsigned int value)
34 char *p = (char *) (((unsigned int)IF1632_Saved16_ss << 16) +
35 (IF1632_Saved16_esp & 0xffff));
36 if (size)
38 unsigned long *lp = (unsigned long *) p - 1;
40 *lp = value;
41 IF1632_Saved16_esp -= 4;
43 else
45 unsigned short *sp = (unsigned short *) p - 1;
47 *sp = value;
48 IF1632_Saved16_esp -= 2;
52 /**********************************************************************
53 * FindDataSegmentForCode
55 static unsigned short
56 FindDataSegmentForCode(unsigned long csip)
58 unsigned int seg_idx;
60 seg_idx = (unsigned short) (csip >> 19);
61 return Segments[seg_idx].owner;
64 /**********************************************************************
65 * CallBack16
67 int
68 CallBack16(void *func, int n_args, ...)
70 va_list ap;
71 int i;
72 int arg_type, arg_value;
74 va_start(ap, n_args);
76 for (i = 0; i < n_args; i++)
78 arg_type = va_arg(ap, int);
79 arg_value = va_arg(ap, int);
80 PushOn16(arg_type, arg_value);
83 va_end(ap);
85 return CallTo16((unsigned int) func,
86 FindDataSegmentForCode((unsigned long) func));
89 /**********************************************************************
90 * CALLBACK_MakeProcInstance
92 void *
93 CALLBACK_MakeProcInstance(void *func, int instance)
95 int handle;
96 void *new_func;
97 struct thunk_s *tp;
98 int i;
100 tp = (struct thunk_s *) MakeProcThunks->base_addr;
101 for (i = 0; i < 0x10000 / sizeof(*tp); i++, tp++)
102 if (!tp->used)
103 break;
105 if (tp->used)
106 return (void *) 0;
108 tp->thunk[0] = 0xb8;
109 tp->thunk[1] = (unsigned char) instance;
110 tp->thunk[2] = (unsigned char) (instance >> 8);
111 tp->thunk[3] = 0x8e;
112 tp->thunk[4] = 0xd8;
113 tp->thunk[5] = 0xea;
114 memcpy(&tp->thunk[6], &func, 4);
115 tp->used = 1;
117 return tp->thunk;
120 /**********************************************************************
121 * FreeProcInstance (KERNEL.52)
123 void FreeProcInstance(FARPROC func)
125 int handle;
126 void *new_func;
127 struct thunk_s *tp;
128 int i;
130 tp = (struct thunk_s *) MakeProcThunks->base_addr;
131 for (i = 0; i < 0x10000 / sizeof(*tp); i++, tp++)
133 if ((void *) tp->thunk == (void *) func)
135 tp->used = 0;
136 break;
141 /**********************************************************************
142 * CallWindowProc (USER.122)
144 LONG CallWindowProc( FARPROC func, HWND hwnd, WORD message,
145 WORD wParam, LONG lParam )
147 SpyMessage(hwnd, message, wParam, lParam);
149 if (HIWORD((LONG)func) == WINE_CODE_SELECTOR)
151 static struct dll_table_entry_s *user_tab = NULL;
152 void *address = (void *) ((LONG) func & 0xffff);
154 if (user_tab == NULL)
155 user_tab = FindDLLTable("USER");
157 /* DefWindowProc */
158 if (user_tab[104].address == address)
159 return DefWindowProc(hwnd, message, wParam, lParam);
161 /* DefDlgProc */
162 else if (user_tab[308].address == address)
163 return DefDlgProc(hwnd, message, wParam, lParam);
165 /* DefMDIChildProc */
166 else if (user_tab[447].address == address)
167 return DefMDIChildProc(hwnd, message, wParam, lParam);
169 /* default */
170 else
172 fprintf(stderr, "wine: Unknown wine callback %08x\n", func);
173 exit(1);
176 else if (Is16bitAddress(func))
178 #ifdef DEBUG_CALLBACK
179 printf("CallWindowProc // 16bit func=%08X !\n", func);
180 #endif
181 PushOn16( CALLBACK_SIZE_WORD, hwnd );
182 PushOn16( CALLBACK_SIZE_WORD, message );
183 PushOn16( CALLBACK_SIZE_WORD, wParam );
184 PushOn16( CALLBACK_SIZE_LONG, lParam );
185 return CallTo16((unsigned int) func,
186 FindDataSegmentForCode((unsigned long) func));
188 else
190 #ifdef DEBUG_CALLBACK
191 printf("CallWindowProc // 32bit func=%08X !\n", func);
192 #endif
193 return (*func)(hwnd, message, wParam, lParam);
197 /**********************************************************************
198 * CallLineDDAProc
200 void CallLineDDAProc(FARPROC func, short xPos, short yPos, long lParam)
202 if (Is16bitAddress(func))
204 PushOn16( CALLBACK_SIZE_WORD, xPos );
205 PushOn16( CALLBACK_SIZE_WORD, yPos );
206 PushOn16( CALLBACK_SIZE_LONG, lParam );
207 CallTo16((unsigned int) func,
208 FindDataSegmentForCode((unsigned long) func));
210 else
212 (*func)(xPos, yPos, lParam);
216 /**********************************************************************
217 * CallHookProc
219 DWORD CallHookProc( HOOKPROC func, short code, WPARAM wParam, LPARAM lParam )
221 if (Is16bitAddress(func))
223 PushOn16( CALLBACK_SIZE_WORD, code );
224 PushOn16( CALLBACK_SIZE_WORD, wParam );
225 PushOn16( CALLBACK_SIZE_LONG, lParam );
226 return CallTo16((unsigned int) func,
227 FindDataSegmentForCode((unsigned long) func));
229 else
231 return (*func)( code, wParam, lParam );
235 /**********************************************************************
236 * CallGrayStringProc
238 BOOL CallGrayStringProc(FARPROC func, HDC hdc, LPARAM lParam, INT cch )
240 if (Is16bitAddress(func))
242 PushOn16( CALLBACK_SIZE_WORD, hdc );
243 PushOn16( CALLBACK_SIZE_LONG, lParam );
244 PushOn16( CALLBACK_SIZE_WORD, cch );
245 return CallTo16((unsigned int) func,
246 FindDataSegmentForCode((unsigned long) func));
248 else
250 return (*func)( hdc, lParam, cch );
254 /* ------------------------------------------------------------------------ */
256 * The following functions realize the Catch/Throw functionality.
257 * My thought is to use the setjmp, longjmp combination to do the
258 * major part of this one. All I have to remember, in addition to
259 * whatever the jmp_buf contains, is the contents of the 16-bit
260 * sp, bp and ss. I do this by storing them in the structure passed
261 * to me by the 16-bit program (including my own jmp_buf...).
262 * Hopefully there isn't any program that modifies the contents!
263 * Bad thing: I have to save part of the stack, since this will
264 * get reused on the next call after my return, leaving it in an
265 * undefined state.
267 #define STACK_DEPTH_16 28
269 struct special_buffer {
270 jmp_buf buffer;
271 long regs [6];
272 char stack_part [STACK_DEPTH_16];
273 } *sb;
275 int Catch (LPCATCHBUF cbuf)
277 WORD retval;
278 jmp_buf *tmp_jmp;
279 char *stack16 = (char *) (((unsigned int)IF1632_Saved16_ss << 16) +
280 (IF1632_Saved16_esp & 0xffff));
282 sb = malloc (sizeof (struct special_buffer));
284 sb -> regs [0] = IF1632_Saved16_esp;
285 sb -> regs [1] = IF1632_Saved16_ebp;
286 sb -> regs [2] = IF1632_Saved16_ss & 0xffff;
287 sb -> regs [3] = IF1632_Saved32_esp;
288 sb -> regs [4] = IF1632_Saved32_ebp;
289 sb -> regs [5] = IF1632_Saved32_ss & 0xffff;
290 memcpy (sb -> stack_part, stack16, STACK_DEPTH_16);
291 tmp_jmp = &sb -> buffer;
292 *((struct special_buffer **)cbuf) = sb;
294 if ((retval = setjmp (*tmp_jmp)))
296 IF1632_Saved16_esp = sb -> regs [0];
297 IF1632_Saved16_ebp = sb -> regs [1];
298 IF1632_Saved16_ss = sb -> regs [2] & 0xffff;
299 IF1632_Saved32_esp = sb -> regs [3];
300 IF1632_Saved32_ebp = sb -> regs [4];
301 IF1632_Saved32_ss = sb -> regs [5] & 0xffff;
302 stack16 = (char *) (((unsigned int)IF1632_Saved16_ss << 16) +
303 (IF1632_Saved16_esp & 0xffff));
305 memcpy (stack16, sb -> stack_part, STACK_DEPTH_16);
306 #ifdef DEBUG_CATCH
307 printf ("Been thrown here: %d, retval = %d\n", sb, retval);
308 #endif
309 free ((void *) sb);
310 return (retval);
311 } else {
312 #ifdef DEBUG_CATCH
313 printf ("Will somtime get thrown here: %d\n", sb);
314 #endif
315 return (retval);
319 void Throw (LPCATCHBUF cbuf, int val)
321 sb = *((struct special_buffer **)cbuf);
322 #ifdef DEBUG_CATCH
323 printf ("Throwing to: %d\n", sb);
324 #endif
325 longjmp (sb -> buffer, val);