user: Dead code fix (Coverity).
[wine.git] / dlls / user / hook16.c
blob7b13985a2598869b5903f931bb0f342137717068
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 "win.h"
32 #include "user_private.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 = get_user_thread_info()->hook16_info;
113 WORD args[4];
114 DWORD 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 struct wndproc_hook_params
138 HHOOK hhook;
139 INT code;
140 WPARAM wparam;
143 /* callback for WINPROC_Call16To32A */
144 static LRESULT wndproc_hook_callback( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
145 LRESULT *result, void *arg )
147 struct wndproc_hook_params *params = arg;
148 CWPSTRUCT cwp;
150 cwp.hwnd = hwnd;
151 cwp.message = msg;
152 cwp.wParam = wp;
153 cwp.lParam = lp;
154 *result = 0;
155 return CallNextHookEx( params->hhook, params->code, params->wparam, (LPARAM)&cwp );
158 /* callback for WINPROC_Call32ATo16 */
159 static LRESULT wndproc_hook_callback16( HWND16 hwnd, UINT16 msg, WPARAM16 wp, LPARAM lp,
160 LRESULT *result, void *arg )
162 struct wndproc_hook_params *params = arg;
163 CWPSTRUCT16 cwp;
164 LRESULT ret;
166 cwp.hwnd = hwnd;
167 cwp.message = msg;
168 cwp.wParam = wp;
169 cwp.lParam = lp;
171 lp = MapLS( &cwp );
172 ret = call_hook_16( WH_CALLWNDPROC, params->code, params->wparam, lp );
173 UnMapLS( lp );
175 *result = 0;
176 return ret;
180 /***********************************************************************
181 * call_WH_MSGFILTER
183 static LRESULT CALLBACK call_WH_MSGFILTER( INT code, WPARAM wp, LPARAM lp )
185 MSG *msg32 = (MSG *)lp;
186 MSG16 msg16;
187 LRESULT ret;
189 map_msg_32_to_16( msg32, &msg16 );
190 lp = MapLS( &msg16 );
191 ret = call_hook_16( WH_MSGFILTER, code, wp, lp );
192 UnMapLS( lp );
193 return ret;
197 /***********************************************************************
198 * call_WH_KEYBOARD
200 static LRESULT CALLBACK call_WH_KEYBOARD( INT code, WPARAM wp, LPARAM lp )
202 return call_hook_16( WH_KEYBOARD, code, wp, lp );
206 /***********************************************************************
207 * call_WH_GETMESSAGE
209 static LRESULT CALLBACK call_WH_GETMESSAGE( INT code, WPARAM wp, LPARAM lp )
211 MSG *msg32 = (MSG *)lp;
212 MSG16 msg16;
213 LRESULT ret;
215 map_msg_32_to_16( msg32, &msg16 );
217 lp = MapLS( &msg16 );
218 ret = call_hook_16( WH_GETMESSAGE, code, wp, lp );
219 UnMapLS( lp );
221 map_msg_16_to_32( &msg16, msg32 );
222 return ret;
226 /***********************************************************************
227 * call_WH_CALLWNDPROC
229 static LRESULT CALLBACK call_WH_CALLWNDPROC( INT code, WPARAM wp, LPARAM lp )
231 struct wndproc_hook_params params;
232 CWPSTRUCT *cwp32 = (CWPSTRUCT *)lp;
233 LRESULT result;
235 params.code = code;
236 params.wparam = wp;
237 return WINPROC_CallProc32ATo16( wndproc_hook_callback16, cwp32->hwnd, cwp32->message,
238 cwp32->wParam, cwp32->lParam, &result, &params );
242 /***********************************************************************
243 * call_WH_CBT
245 static LRESULT CALLBACK call_WH_CBT( INT code, WPARAM wp, LPARAM lp )
247 LRESULT ret = 0;
249 switch (code)
251 case HCBT_CREATEWND:
253 CBT_CREATEWNDA *cbtcw32 = (CBT_CREATEWNDA *)lp;
254 CBT_CREATEWND16 cbtcw16;
255 CREATESTRUCT16 cs16;
257 cs16.lpCreateParams = (SEGPTR)cbtcw32->lpcs->lpCreateParams;
258 cs16.hInstance = HINSTANCE_16(cbtcw32->lpcs->hInstance);
259 cs16.hMenu = HMENU_16(cbtcw32->lpcs->hMenu);
260 cs16.hwndParent = HWND_16(cbtcw32->lpcs->hwndParent);
261 cs16.cy = cbtcw32->lpcs->cy;
262 cs16.cx = cbtcw32->lpcs->cx;
263 cs16.y = cbtcw32->lpcs->y;
264 cs16.x = cbtcw32->lpcs->x;
265 cs16.style = cbtcw32->lpcs->style;
266 cs16.lpszName = MapLS( cbtcw32->lpcs->lpszName );
267 cs16.lpszClass = MapLS( cbtcw32->lpcs->lpszClass );
268 cs16.dwExStyle = cbtcw32->lpcs->dwExStyle;
270 cbtcw16.lpcs = (CREATESTRUCT16 *)MapLS( &cs16 );
271 cbtcw16.hwndInsertAfter = HWND_16( cbtcw32->hwndInsertAfter );
273 lp = MapLS( &cbtcw16 );
274 ret = call_hook_16( WH_CBT, code, wp, lp );
275 UnMapLS( cs16.lpszName );
276 UnMapLS( cs16.lpszClass );
278 cbtcw32->hwndInsertAfter = WIN_Handle32( cbtcw16.hwndInsertAfter );
279 UnMapLS( (SEGPTR)cbtcw16.lpcs );
280 UnMapLS( lp );
281 break;
284 case HCBT_ACTIVATE:
286 CBTACTIVATESTRUCT *cas32 = (CBTACTIVATESTRUCT *)lp;
287 CBTACTIVATESTRUCT16 cas16;
289 cas16.fMouse = cas32->fMouse;
290 cas16.hWndActive = HWND_16( cas32->hWndActive );
292 lp = MapLS( &cas16 );
293 ret = call_hook_16( WH_CBT, code, wp, lp );
294 UnMapLS( lp );
295 break;
297 case HCBT_CLICKSKIPPED:
299 MOUSEHOOKSTRUCT *ms32 = (MOUSEHOOKSTRUCT *)lp;
300 MOUSEHOOKSTRUCT16 ms16;
302 ms16.pt.x = ms32->pt.x;
303 ms16.pt.y = ms32->pt.y;
304 ms16.hwnd = HWND_16( ms32->hwnd );
305 ms16.wHitTestCode = ms32->wHitTestCode;
306 ms16.dwExtraInfo = ms32->dwExtraInfo;
308 lp = MapLS( &ms16 );
309 ret = call_hook_16( WH_CBT, code, wp, lp );
310 UnMapLS( lp );
311 break;
313 case HCBT_MOVESIZE:
315 RECT *rect32 = (RECT *)lp;
316 RECT16 rect16;
318 rect16.left = rect32->left;
319 rect16.top = rect32->top;
320 rect16.right = rect32->right;
321 rect16.bottom = rect32->bottom;
322 lp = MapLS( &rect16 );
323 ret = call_hook_16( WH_CBT, code, wp, lp );
324 UnMapLS( lp );
325 break;
328 return ret;
332 /***********************************************************************
333 * call_WH_MOUSE
335 static LRESULT CALLBACK call_WH_MOUSE( INT code, WPARAM wp, LPARAM lp )
337 MOUSEHOOKSTRUCT *ms32 = (MOUSEHOOKSTRUCT *)lp;
338 MOUSEHOOKSTRUCT16 ms16;
339 LRESULT ret;
341 ms16.pt.x = ms32->pt.x;
342 ms16.pt.y = ms32->pt.y;
343 ms16.hwnd = HWND_16( ms32->hwnd );
344 ms16.wHitTestCode = ms32->wHitTestCode;
345 ms16.dwExtraInfo = ms32->dwExtraInfo;
347 lp = MapLS( &ms16 );
348 ret = call_hook_16( WH_MOUSE, code, wp, lp );
349 UnMapLS( lp );
350 return ret;
354 /***********************************************************************
355 * call_WH_SHELL
357 static LRESULT CALLBACK call_WH_SHELL( INT code, WPARAM wp, LPARAM lp )
359 return call_hook_16( WH_SHELL, code, wp, lp );
363 /***********************************************************************
364 * SetWindowsHook (USER.121)
366 FARPROC16 WINAPI SetWindowsHook16( INT16 id, HOOKPROC16 proc )
368 HINSTANCE16 hInst = FarGetOwner16( HIWORD(proc) );
370 /* WH_MSGFILTER is the only task-specific hook for SetWindowsHook() */
371 HTASK16 hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
373 return (FARPROC16)SetWindowsHookEx16( id, proc, hInst, hTask );
377 /***********************************************************************
378 * SetWindowsHookEx (USER.291)
380 HHOOK WINAPI SetWindowsHookEx16( INT16 id, HOOKPROC16 proc, HINSTANCE16 hInst, HTASK16 hTask )
382 struct user_thread_info *thread_info = get_user_thread_info();
383 struct hook16_queue_info *info;
384 HHOOK hook;
385 int index = id - WH_MINHOOK;
387 if (id < WH_MINHOOK || id > WH_MAXHOOK16) return 0;
388 if (!hook_procs[index])
390 FIXME( "hook type %d broken in Win16\n", id );
391 return 0;
393 if (!hTask) FIXME( "System-global hooks (%d) broken in Win16\n", id );
394 else if (hTask != GetCurrentTask())
396 FIXME( "setting hook (%d) on other task not supported\n", id );
397 return 0;
400 if (!(info = thread_info->hook16_info))
402 if (!(info = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*info) ))) return 0;
403 thread_info->hook16_info = info;
405 if (info->hook[index])
407 FIXME( "Multiple hooks (%d) for the same task not supported yet\n", id );
408 return 0;
410 if (!(hook = SetWindowsHookExA( id, hook_procs[index], 0, GetCurrentThreadId() ))) return 0;
411 info->hook[index] = hook;
412 info->proc[index] = proc;
413 return hook;
417 /***********************************************************************
418 * UnhookWindowsHook (USER.234)
420 BOOL16 WINAPI UnhookWindowsHook16( INT16 id, HOOKPROC16 proc )
422 struct hook16_queue_info *info;
423 int index = id - WH_MINHOOK;
425 if (id < WH_MINHOOK || id > WH_MAXHOOK16) return FALSE;
426 if (!(info = get_user_thread_info()->hook16_info)) return FALSE;
427 if (info->proc[index] != proc) return FALSE;
428 if (!UnhookWindowsHookEx( info->hook[index] )) return FALSE;
429 info->hook[index] = 0;
430 info->proc[index] = 0;
431 return TRUE;
435 /***********************************************************************
436 * UnhookWindowsHookEx (USER.292)
438 BOOL16 WINAPI UnhookWindowsHookEx16( HHOOK hhook )
440 struct hook16_queue_info *info;
441 int index;
443 if (!(info = get_user_thread_info()->hook16_info)) return FALSE;
444 for (index = 0; index < NB_HOOKS16; index++)
446 if (info->hook[index] == hhook)
448 info->hook[index] = 0;
449 info->proc[index] = 0;
450 return UnhookWindowsHookEx( hhook );
453 return FALSE;
457 /***********************************************************************
458 * CallMsgFilter32 (USER.823)
460 BOOL16 WINAPI CallMsgFilter32_16( MSG32_16 *lpmsg16_32, INT16 code, BOOL16 wHaveParamHigh )
462 MSG msg32;
463 BOOL16 ret;
465 if (GetSysModalWindow16()) return FALSE;
466 msg32.hwnd = WIN_Handle32( lpmsg16_32->msg.hwnd );
467 msg32.message = lpmsg16_32->msg.message;
468 msg32.lParam = lpmsg16_32->msg.lParam;
469 msg32.time = lpmsg16_32->msg.time;
470 msg32.pt.x = lpmsg16_32->msg.pt.x;
471 msg32.pt.y = lpmsg16_32->msg.pt.y;
472 if (wHaveParamHigh) msg32.wParam = MAKELONG(lpmsg16_32->msg.wParam, lpmsg16_32->wParamHigh);
473 else msg32.wParam = lpmsg16_32->msg.wParam;
475 ret = (BOOL16)CallMsgFilterA(&msg32, code);
477 lpmsg16_32->msg.hwnd = HWND_16( msg32.hwnd );
478 lpmsg16_32->msg.message = msg32.message;
479 lpmsg16_32->msg.wParam = LOWORD(msg32.wParam);
480 lpmsg16_32->msg.lParam = msg32.lParam;
481 lpmsg16_32->msg.time = msg32.time;
482 lpmsg16_32->msg.pt.x = msg32.pt.x;
483 lpmsg16_32->msg.pt.y = msg32.pt.y;
484 if (wHaveParamHigh) lpmsg16_32->wParamHigh = HIWORD(msg32.wParam);
485 return ret;
489 /***********************************************************************
490 * CallMsgFilter (USER.123)
492 BOOL16 WINAPI CallMsgFilter16( MSG16 *msg, INT16 code )
494 return CallMsgFilter32_16( (MSG32_16 *)msg, code, FALSE );
498 /***********************************************************************
499 * CallNextHookEx (USER.293)
501 LRESULT WINAPI CallNextHookEx16( HHOOK hhook, INT16 code, WPARAM16 wparam, LPARAM lparam )
503 struct hook16_queue_info *info;
504 LRESULT ret = 0;
506 if (!(info = get_user_thread_info()->hook16_info)) return 0;
508 switch (info->id)
510 case WH_MSGFILTER:
512 MSG16 *msg16 = MapSL(lparam);
513 MSG msg32;
515 map_msg_16_to_32( msg16, &msg32 );
516 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&msg32 );
517 break;
520 case WH_GETMESSAGE:
522 MSG16 *msg16 = MapSL(lparam);
523 MSG msg32;
525 map_msg_16_to_32( msg16, &msg32 );
526 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&msg32 );
527 map_msg_32_to_16( &msg32, msg16 );
528 break;
531 case WH_CALLWNDPROC:
533 CWPSTRUCT16 *cwp16 = MapSL(lparam);
534 LRESULT result;
535 struct wndproc_hook_params params;
537 params.hhook = hhook;
538 params.code = code;
539 params.wparam = wparam;
540 ret = WINPROC_CallProc16To32A( wndproc_hook_callback, cwp16->hwnd, cwp16->message,
541 cwp16->wParam, cwp16->lParam, &result, &params );
542 break;
545 case WH_CBT:
546 switch (code)
548 case HCBT_CREATEWND:
550 CBT_CREATEWNDA cbtcw32;
551 CREATESTRUCTA cs32;
552 CBT_CREATEWND16 *cbtcw16 = MapSL(lparam);
553 CREATESTRUCT16 *cs16 = MapSL( (SEGPTR)cbtcw16->lpcs );
555 cbtcw32.lpcs = &cs32;
556 cbtcw32.hwndInsertAfter = WIN_Handle32( cbtcw16->hwndInsertAfter );
558 cs32.lpCreateParams = (LPVOID)cs16->lpCreateParams;
559 cs32.hInstance = HINSTANCE_32(cs16->hInstance);
560 cs32.hMenu = HMENU_32(cs16->hMenu);
561 cs32.hwndParent = WIN_Handle32(cs16->hwndParent);
562 cs32.cy = cs16->cy;
563 cs32.cx = cs16->cx;
564 cs32.y = cs16->y;
565 cs32.x = cs16->x;
566 cs32.style = cs16->style;
567 cs32.lpszName = MapSL( cs16->lpszName );
568 cs32.lpszClass = MapSL( cs16->lpszClass );
569 cs32.dwExStyle = cs16->dwExStyle;
571 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&cbtcw32 );
572 cbtcw16->hwndInsertAfter = HWND_16( cbtcw32.hwndInsertAfter );
573 break;
575 case HCBT_ACTIVATE:
577 CBTACTIVATESTRUCT16 *cas16 = MapSL(lparam);
578 CBTACTIVATESTRUCT cas32;
579 cas32.fMouse = cas16->fMouse;
580 cas32.hWndActive = WIN_Handle32(cas16->hWndActive);
581 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&cas32 );
582 break;
584 case HCBT_CLICKSKIPPED:
586 MOUSEHOOKSTRUCT16 *ms16 = MapSL(lparam);
587 MOUSEHOOKSTRUCT ms32;
589 ms32.pt.x = ms16->pt.x;
590 ms32.pt.y = ms16->pt.y;
591 /* wHitTestCode may be negative, so convince compiler to do
592 correct sign extension. Yay. :| */
593 ms32.wHitTestCode = (INT)(INT16)ms16->wHitTestCode;
594 ms32.dwExtraInfo = ms16->dwExtraInfo;
595 ms32.hwnd = WIN_Handle32( ms16->hwnd );
596 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&ms32 );
597 break;
599 case HCBT_MOVESIZE:
601 RECT16 *rect16 = MapSL(lparam);
602 RECT rect32;
604 rect32.left = rect16->left;
605 rect32.top = rect16->top;
606 rect32.right = rect16->right;
607 rect32.bottom = rect16->bottom;
608 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&rect32 );
609 break;
612 break;
614 case WH_MOUSE:
616 MOUSEHOOKSTRUCT16 *ms16 = MapSL(lparam);
617 MOUSEHOOKSTRUCT ms32;
619 ms32.pt.x = ms16->pt.x;
620 ms32.pt.y = ms16->pt.y;
621 /* wHitTestCode may be negative, so convince compiler to do
622 correct sign extension. Yay. :| */
623 ms32.wHitTestCode = (INT)((INT16)ms16->wHitTestCode);
624 ms32.dwExtraInfo = ms16->dwExtraInfo;
625 ms32.hwnd = WIN_Handle32(ms16->hwnd);
626 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&ms32 );
627 break;
630 case WH_SHELL:
631 case WH_KEYBOARD:
632 ret = CallNextHookEx( hhook, code, wparam, lparam );
633 break;
635 case WH_HARDWARE:
636 case WH_FOREGROUNDIDLE:
637 case WH_CALLWNDPROCRET:
638 case WH_SYSMSGFILTER:
639 case WH_JOURNALRECORD:
640 case WH_JOURNALPLAYBACK:
641 default:
642 FIXME("\t[%i] 16to32 translation unimplemented\n", info->id);
643 ret = CallNextHookEx( hhook, code, wparam, lparam );
644 break;
646 return ret;
650 /***********************************************************************
651 * DefHookProc (USER.235)
653 LRESULT WINAPI DefHookProc16( INT16 code, WPARAM16 wparam, LPARAM lparam, HHOOK *hhook )
655 return CallNextHookEx16( *hhook, code, wparam, lparam );