Get rid of the WIN_SetRectangles export from user32.
[wine.git] / dlls / user / hook16.c
blob8bcef5ccc6e253031fec76989a8c25b59ebffde4
1 /*
2 * Windows 16-bit hook functions
4 * Copyright 1994, 1995, 2002 Alexandre Julliard
5 * Copyright 1996 Andrew Lewycky
7 * Based on investigations by Alex Korobka
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include <stdarg.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "wownt32.h"
30 #include "wine/winuser16.h"
31 #include "message.h"
32 #include "win.h"
33 #include "winproc.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(hook);
39 static LRESULT CALLBACK call_WH_MSGFILTER( INT code, WPARAM wp, LPARAM lp );
40 static LRESULT CALLBACK call_WH_KEYBOARD( INT code, WPARAM wp, LPARAM lp );
41 static LRESULT CALLBACK call_WH_GETMESSAGE( INT code, WPARAM wp, LPARAM lp );
42 static LRESULT CALLBACK call_WH_CALLWNDPROC( INT code, WPARAM wp, LPARAM lp );
43 static LRESULT CALLBACK call_WH_CBT( INT code, WPARAM wp, LPARAM lp );
44 static LRESULT CALLBACK call_WH_MOUSE( INT code, WPARAM wp, LPARAM lp );
45 static LRESULT CALLBACK call_WH_SHELL( INT code, WPARAM wp, LPARAM lp );
47 #define WH_MAXHOOK16 WH_SHELL /* Win16 only supports up to WH_SHELL */
48 #define NB_HOOKS16 (WH_MAXHOOK16 - WH_MINHOOK + 1)
50 static const HOOKPROC hook_procs[NB_HOOKS16] =
52 call_WH_MSGFILTER, /* WH_MSGFILTER */
53 NULL, /* WH_JOURNALRECORD */
54 NULL, /* WH_JOURNALPLAYBACK */
55 call_WH_KEYBOARD, /* WH_KEYBOARD */
56 call_WH_GETMESSAGE, /* WH_GETMESSAGE */
57 call_WH_CALLWNDPROC, /* WH_CALLWNDPROC */
58 call_WH_CBT, /* WH_CBT */
59 NULL, /* WH_SYSMSGFILTER */
60 call_WH_MOUSE, /* WH_MOUSE */
61 NULL, /* WH_HARDWARE */
62 NULL, /* WH_DEBUG */
63 call_WH_SHELL /* WH_SHELL */
67 /* this structure is stored in the thread queue */
68 struct hook16_queue_info
70 INT id; /* id of current hook */
71 HHOOK hook[NB_HOOKS16]; /* Win32 hook handles */
72 HOOKPROC16 proc[NB_HOOKS16]; /* 16-bit hook procedures */
77 /***********************************************************************
78 * map_msg_16_to_32
80 inline static void map_msg_16_to_32( const MSG16 *msg16, MSG *msg32 )
82 msg32->hwnd = WIN_Handle32(msg16->hwnd);
83 msg32->message = msg16->message;
84 msg32->wParam = msg16->wParam;
85 msg32->lParam = msg16->lParam;
86 msg32->time = msg16->time;
87 msg32->pt.x = msg16->pt.x;
88 msg32->pt.y = msg16->pt.y;
92 /***********************************************************************
93 * map_msg_32_to_16
95 inline static void map_msg_32_to_16( const MSG *msg32, MSG16 *msg16 )
97 msg16->hwnd = HWND_16(msg32->hwnd);
98 msg16->message = msg32->message;
99 msg16->wParam = msg32->wParam;
100 msg16->lParam = msg32->lParam;
101 msg16->time = msg32->time;
102 msg16->pt.x = msg32->pt.x;
103 msg16->pt.y = msg32->pt.y;
107 /***********************************************************************
108 * call_hook_16
110 static LRESULT call_hook_16( INT id, INT code, WPARAM wp, LPARAM lp )
112 struct hook16_queue_info *info = QUEUE_Current()->hook16_info;
113 WORD args[4];
114 LRESULT ret;
115 INT prev_id = info->id;
116 info->id = id;
118 args[3] = code;
119 args[2] = wp;
120 args[1] = HIWORD(lp);
121 args[0] = LOWORD(lp);
122 WOWCallback16Ex( (DWORD)info->proc[id - WH_MINHOOK], WCB16_PASCAL, sizeof(args), args, &ret );
124 info->id = prev_id;
126 /* Grrr. While the hook procedure is supposed to have an LRESULT return
127 value even in Win16, it seems that for those hook types where the
128 return value is interpreted as BOOL, Windows doesn't actually check
129 the HIWORD ... Some buggy Win16 programs, notably WINFILE, rely on
130 that, because they neglect to clear DX ... */
131 if (id != WH_JOURNALPLAYBACK) ret = LOWORD( ret );
132 return ret;
136 /***********************************************************************
137 * call_WH_MSGFILTER
139 static LRESULT CALLBACK call_WH_MSGFILTER( INT code, WPARAM wp, LPARAM lp )
141 MSG *msg32 = (MSG *)lp;
142 MSG16 msg16;
143 LRESULT ret;
145 map_msg_32_to_16( msg32, &msg16 );
146 lp = MapLS( &msg16 );
147 ret = call_hook_16( WH_MSGFILTER, code, wp, lp );
148 UnMapLS( lp );
149 return ret;
153 /***********************************************************************
154 * call_WH_KEYBOARD
156 static LRESULT CALLBACK call_WH_KEYBOARD( INT code, WPARAM wp, LPARAM lp )
158 return call_hook_16( WH_KEYBOARD, code, wp, lp );
162 /***********************************************************************
163 * call_WH_GETMESSAGE
165 static LRESULT CALLBACK call_WH_GETMESSAGE( INT code, WPARAM wp, LPARAM lp )
167 MSG *msg32 = (MSG *)lp;
168 MSG16 msg16;
169 LRESULT ret;
171 map_msg_32_to_16( msg32, &msg16 );
173 lp = MapLS( &msg16 );
174 ret = call_hook_16( WH_GETMESSAGE, code, wp, lp );
175 UnMapLS( lp );
177 map_msg_16_to_32( &msg16, msg32 );
178 return ret;
182 /***********************************************************************
183 * call_WH_CALLWNDPROC
185 static LRESULT CALLBACK call_WH_CALLWNDPROC( INT code, WPARAM wp, LPARAM lp )
187 CWPSTRUCT *cwp32 = (CWPSTRUCT *)lp;
188 CWPSTRUCT16 cwp16;
189 MSGPARAM16 mp16;
190 LRESULT ret;
192 cwp16.hwnd = HWND_16(cwp32->hwnd);
193 cwp16.lParam = cwp32->lParam;
195 WINPROC_MapMsg32ATo16( cwp32->hwnd, cwp32->message, cwp32->wParam,
196 &cwp16.message, &cwp16.wParam, &cwp16.lParam );
198 lp = MapLS( &cwp16 );
199 ret = call_hook_16( WH_CALLWNDPROC, code, wp, lp );
200 UnMapLS( lp );
202 mp16.wParam = cwp16.wParam;
203 mp16.lParam = cwp16.lParam;
204 mp16.lResult = 0;
205 WINPROC_UnmapMsg32ATo16( cwp32->hwnd, cwp32->message, cwp32->wParam, cwp32->lParam, &mp16 );
206 return ret;
210 /***********************************************************************
211 * call_WH_CBT
213 static LRESULT CALLBACK call_WH_CBT( INT code, WPARAM wp, LPARAM lp )
215 LRESULT ret = 0;
217 switch (code)
219 case HCBT_CREATEWND:
221 CBT_CREATEWNDA *cbtcw32 = (CBT_CREATEWNDA *)lp;
222 CBT_CREATEWND16 cbtcw16;
223 CREATESTRUCT16 cs16;
225 cs16.lpCreateParams = (SEGPTR)cbtcw32->lpcs->lpCreateParams;
226 cs16.hInstance = HINSTANCE_16(cbtcw32->lpcs->hInstance);
227 cs16.hMenu = HMENU_16(cbtcw32->lpcs->hMenu);
228 cs16.hwndParent = HWND_16(cbtcw32->lpcs->hwndParent);
229 cs16.cy = cbtcw32->lpcs->cy;
230 cs16.cx = cbtcw32->lpcs->cx;
231 cs16.y = cbtcw32->lpcs->y;
232 cs16.x = cbtcw32->lpcs->x;
233 cs16.style = cbtcw32->lpcs->style;
234 cs16.lpszName = MapLS( cbtcw32->lpcs->lpszName );
235 cs16.lpszClass = MapLS( cbtcw32->lpcs->lpszClass );
236 cs16.dwExStyle = cbtcw32->lpcs->dwExStyle;
238 cbtcw16.lpcs = (CREATESTRUCT16 *)MapLS( &cs16 );
239 cbtcw16.hwndInsertAfter = HWND_16( cbtcw32->hwndInsertAfter );
241 lp = MapLS( &cbtcw16 );
242 ret = call_hook_16( WH_CBT, code, wp, lp );
243 UnMapLS( cs16.lpszName );
244 UnMapLS( cs16.lpszClass );
246 cbtcw32->hwndInsertAfter = WIN_Handle32( cbtcw16.hwndInsertAfter );
247 UnMapLS( (SEGPTR)cbtcw16.lpcs );
248 UnMapLS( lp );
249 break;
252 case HCBT_ACTIVATE:
254 CBTACTIVATESTRUCT *cas32 = (CBTACTIVATESTRUCT *)lp;
255 CBTACTIVATESTRUCT16 cas16;
257 cas16.fMouse = cas32->fMouse;
258 cas16.hWndActive = HWND_16( cas32->hWndActive );
260 lp = MapLS( &cas16 );
261 ret = call_hook_16( WH_CBT, code, wp, lp );
262 UnMapLS( lp );
263 break;
265 case HCBT_CLICKSKIPPED:
267 MOUSEHOOKSTRUCT *ms32 = (MOUSEHOOKSTRUCT *)lp;
268 MOUSEHOOKSTRUCT16 ms16;
270 ms16.pt.x = ms32->pt.x;
271 ms16.pt.y = ms32->pt.y;
272 ms16.hwnd = HWND_16( ms32->hwnd );
273 ms16.wHitTestCode = ms32->wHitTestCode;
274 ms16.dwExtraInfo = ms32->dwExtraInfo;
276 lp = MapLS( &ms16 );
277 ret = call_hook_16( WH_CBT, code, wp, lp );
278 UnMapLS( lp );
279 break;
281 case HCBT_MOVESIZE:
283 RECT *rect32 = (RECT *)lp;
284 RECT16 rect16;
286 rect16.left = rect32->left;
287 rect16.top = rect32->top;
288 rect16.right = rect32->right;
289 rect16.bottom = rect32->bottom;
290 lp = MapLS( &rect16 );
291 ret = call_hook_16( WH_CBT, code, wp, lp );
292 UnMapLS( lp );
293 break;
296 return ret;
300 /***********************************************************************
301 * call_WH_MOUSE
303 static LRESULT CALLBACK call_WH_MOUSE( INT code, WPARAM wp, LPARAM lp )
305 MOUSEHOOKSTRUCT *ms32 = (MOUSEHOOKSTRUCT *)lp;
306 MOUSEHOOKSTRUCT16 ms16;
307 LRESULT ret;
309 ms16.pt.x = ms32->pt.x;
310 ms16.pt.y = ms32->pt.y;
311 ms16.hwnd = HWND_16( ms32->hwnd );
312 ms16.wHitTestCode = ms32->wHitTestCode;
313 ms16.dwExtraInfo = ms32->dwExtraInfo;
315 lp = MapLS( &ms16 );
316 ret = call_hook_16( WH_MOUSE, code, wp, lp );
317 UnMapLS( lp );
318 return ret;
322 /***********************************************************************
323 * call_WH_SHELL
325 static LRESULT CALLBACK call_WH_SHELL( INT code, WPARAM wp, LPARAM lp )
327 return call_hook_16( WH_SHELL, code, wp, lp );
331 /***********************************************************************
332 * SetWindowsHook (USER.121)
334 FARPROC16 WINAPI SetWindowsHook16( INT16 id, HOOKPROC16 proc )
336 HINSTANCE16 hInst = FarGetOwner16( HIWORD(proc) );
338 /* WH_MSGFILTER is the only task-specific hook for SetWindowsHook() */
339 HTASK16 hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
341 return (FARPROC16)SetWindowsHookEx16( id, proc, hInst, hTask );
345 /***********************************************************************
346 * SetWindowsHookEx (USER.291)
348 HHOOK WINAPI SetWindowsHookEx16( INT16 id, HOOKPROC16 proc, HINSTANCE16 hInst, HTASK16 hTask )
350 MESSAGEQUEUE *queue = QUEUE_Current();
351 struct hook16_queue_info *info;
352 HHOOK hook;
353 int index = id - WH_MINHOOK;
355 if (!queue) return 0;
356 if (id < WH_MINHOOK || id > WH_MAXHOOK16) return 0;
357 if (!hook_procs[index])
359 FIXME( "hook type %d broken in Win16\n", id );
360 return 0;
362 if (!hTask) FIXME( "System-global hooks (%d) broken in Win16\n", id );
363 else if (hTask != GetCurrentTask())
365 FIXME( "setting hook (%d) on other task not supported\n", id );
366 return 0;
369 if (!(info = queue->hook16_info))
371 if (!(info = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*info) ))) return 0;
372 queue->hook16_info = info;
374 if (info->hook[index])
376 FIXME( "Multiple hooks (%d) for the same task not supported yet\n", id );
377 return 0;
379 if (!(hook = SetWindowsHookExA( id, hook_procs[index], 0, GetCurrentThreadId() ))) return 0;
380 info->hook[index] = hook;
381 info->proc[index] = proc;
382 return hook;
386 /***********************************************************************
387 * UnhookWindowsHook (USER.234)
389 BOOL16 WINAPI UnhookWindowsHook16( INT16 id, HOOKPROC16 proc )
391 MESSAGEQUEUE *queue = QUEUE_Current();
392 struct hook16_queue_info *info;
393 int index = id - WH_MINHOOK;
395 if (id < WH_MINHOOK || id > WH_MAXHOOK16) return FALSE;
396 if (!queue || !(info = queue->hook16_info)) return FALSE;
397 if (info->proc[index] != proc) return FALSE;
398 if (!UnhookWindowsHookEx( info->hook[index] )) return FALSE;
399 info->hook[index] = 0;
400 info->proc[index] = 0;
401 return TRUE;
405 /***********************************************************************
406 * UnhookWindowsHookEx (USER.292)
408 BOOL16 WINAPI UnhookWindowsHookEx16( HHOOK hhook )
410 MESSAGEQUEUE *queue = QUEUE_Current();
411 struct hook16_queue_info *info;
412 int index;
414 if (!queue || !(info = queue->hook16_info)) return FALSE;
415 for (index = 0; index < NB_HOOKS16; index++)
417 if (info->hook[index] == hhook)
419 info->hook[index] = 0;
420 info->proc[index] = 0;
421 return UnhookWindowsHookEx( hhook );
424 return FALSE;
428 /***********************************************************************
429 * CallMsgFilter32 (USER.823)
431 BOOL16 WINAPI CallMsgFilter32_16( MSG32_16 *lpmsg16_32, INT16 code, BOOL16 wHaveParamHigh )
433 MSG msg32;
434 BOOL16 ret;
436 if (GetSysModalWindow16()) return FALSE;
437 msg32.hwnd = WIN_Handle32( lpmsg16_32->msg.hwnd );
438 msg32.message = lpmsg16_32->msg.message;
439 msg32.lParam = lpmsg16_32->msg.lParam;
440 msg32.time = lpmsg16_32->msg.time;
441 msg32.pt.x = lpmsg16_32->msg.pt.x;
442 msg32.pt.y = lpmsg16_32->msg.pt.y;
443 if (wHaveParamHigh) msg32.wParam = MAKELONG(lpmsg16_32->msg.wParam, lpmsg16_32->wParamHigh);
444 else msg32.wParam = lpmsg16_32->msg.wParam;
446 ret = (BOOL16)CallMsgFilterA(&msg32, code);
448 lpmsg16_32->msg.hwnd = HWND_16( msg32.hwnd );
449 lpmsg16_32->msg.message = msg32.message;
450 lpmsg16_32->msg.wParam = LOWORD(msg32.wParam);
451 lpmsg16_32->msg.lParam = msg32.lParam;
452 lpmsg16_32->msg.time = msg32.time;
453 lpmsg16_32->msg.pt.x = msg32.pt.x;
454 lpmsg16_32->msg.pt.y = msg32.pt.y;
455 if (wHaveParamHigh) lpmsg16_32->wParamHigh = HIWORD(msg32.wParam);
456 return ret;
460 /***********************************************************************
461 * CallMsgFilter (USER.123)
463 BOOL16 WINAPI CallMsgFilter16( MSG16 *msg, INT16 code )
465 return CallMsgFilter32_16( (MSG32_16 *)msg, code, FALSE );
469 /***********************************************************************
470 * CallNextHookEx (USER.293)
472 LRESULT WINAPI CallNextHookEx16( HHOOK hhook, INT16 code, WPARAM16 wparam, LPARAM lparam )
474 MESSAGEQUEUE *queue = QUEUE_Current();
475 struct hook16_queue_info *info;
476 LRESULT ret = 0;
478 if (!queue || !(info = queue->hook16_info)) return 0;
480 switch (info->id)
482 case WH_MSGFILTER:
484 MSG16 *msg16 = MapSL(lparam);
485 MSG msg32;
487 map_msg_16_to_32( msg16, &msg32 );
488 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&msg32 );
489 break;
492 case WH_GETMESSAGE:
494 MSG16 *msg16 = MapSL(lparam);
495 MSG msg32;
497 map_msg_16_to_32( msg16, &msg32 );
498 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&msg32 );
499 map_msg_32_to_16( &msg32, msg16 );
500 break;
503 case WH_CALLWNDPROC:
505 CWPSTRUCT16 *cwp16 = MapSL(lparam);
506 CWPSTRUCT cwp32;
508 cwp32.hwnd = WIN_Handle32(cwp16->hwnd);
509 cwp32.lParam = cwp16->lParam;
511 WINPROC_MapMsg16To32A( cwp32.hwnd, cwp16->message, cwp16->wParam,
512 &cwp32.message, &cwp32.wParam, &cwp32.lParam );
513 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&cwp32 );
514 WINPROC_UnmapMsg16To32A( cwp32.hwnd, cwp32.message, cwp32.wParam, cwp32.lParam, 0 );
515 break;
518 case WH_CBT:
519 switch (code)
521 case HCBT_CREATEWND:
523 CBT_CREATEWNDA cbtcw32;
524 CREATESTRUCTA cs32;
525 CBT_CREATEWND16 *cbtcw16 = MapSL(lparam);
526 CREATESTRUCT16 *cs16 = MapSL( (SEGPTR)cbtcw16->lpcs );
528 cbtcw32.lpcs = &cs32;
529 cbtcw32.hwndInsertAfter = WIN_Handle32( cbtcw16->hwndInsertAfter );
531 cs32.lpCreateParams = (LPVOID)cs16->lpCreateParams;
532 cs32.hInstance = HINSTANCE_32(cs16->hInstance);
533 cs32.hMenu = HMENU_32(cs16->hMenu);
534 cs32.hwndParent = WIN_Handle32(cs16->hwndParent);
535 cs32.cy = cs16->cy;
536 cs32.cx = cs16->cx;
537 cs32.y = cs16->y;
538 cs32.x = cs16->x;
539 cs32.style = cs16->style;
540 cs32.lpszName = MapSL( cs16->lpszName );
541 cs32.lpszClass = MapSL( cs16->lpszClass );
542 cs32.dwExStyle = cs16->dwExStyle;
544 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&cbtcw32 );
545 cbtcw16->hwndInsertAfter = HWND_16( cbtcw32.hwndInsertAfter );
546 break;
548 case HCBT_ACTIVATE:
550 CBTACTIVATESTRUCT16 *cas16 = MapSL(lparam);
551 CBTACTIVATESTRUCT cas32;
552 cas32.fMouse = cas16->fMouse;
553 cas32.hWndActive = WIN_Handle32(cas16->hWndActive);
554 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&cas32 );
555 break;
557 case HCBT_CLICKSKIPPED:
559 MOUSEHOOKSTRUCT16 *ms16 = MapSL(lparam);
560 MOUSEHOOKSTRUCT ms32;
562 ms32.pt.x = ms16->pt.x;
563 ms32.pt.y = ms16->pt.y;
564 /* wHitTestCode may be negative, so convince compiler to do
565 correct sign extension. Yay. :| */
566 ms32.wHitTestCode = (INT)(INT16)ms16->wHitTestCode;
567 ms32.dwExtraInfo = ms16->dwExtraInfo;
568 ms32.hwnd = WIN_Handle32( ms16->hwnd );
569 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&ms32 );
570 break;
572 case HCBT_MOVESIZE:
574 RECT16 *rect16 = MapSL(lparam);
575 RECT rect32;
577 rect32.left = rect16->left;
578 rect32.top = rect16->top;
579 rect32.right = rect16->right;
580 rect32.bottom = rect16->bottom;
581 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&rect32 );
582 break;
585 break;
587 case WH_MOUSE:
589 MOUSEHOOKSTRUCT16 *ms16 = MapSL(lparam);
590 MOUSEHOOKSTRUCT ms32;
592 ms32.pt.x = ms16->pt.x;
593 ms32.pt.y = ms16->pt.y;
594 /* wHitTestCode may be negative, so convince compiler to do
595 correct sign extension. Yay. :| */
596 ms32.wHitTestCode = (INT)((INT16)ms16->wHitTestCode);
597 ms32.dwExtraInfo = ms16->dwExtraInfo;
598 ms32.hwnd = WIN_Handle32(ms16->hwnd);
599 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&ms32 );
600 break;
603 case WH_SHELL:
604 case WH_KEYBOARD:
605 ret = CallNextHookEx( hhook, code, wparam, lparam );
606 break;
608 case WH_HARDWARE:
609 case WH_FOREGROUNDIDLE:
610 case WH_CALLWNDPROCRET:
611 case WH_SYSMSGFILTER:
612 case WH_JOURNALRECORD:
613 case WH_JOURNALPLAYBACK:
614 default:
615 FIXME("\t[%i] 16to32 translation unimplemented\n", info->id);
616 ret = CallNextHookEx( hhook, code, wparam, lparam );
617 break;
619 return ret;
623 /***********************************************************************
624 * DefHookProc (USER.235)
626 LRESULT WINAPI DefHookProc16( INT16 code, WPARAM16 wparam, LPARAM lparam, HHOOK *hhook )
628 return CallNextHookEx16( *hhook, code, wparam, lparam );