Release 20030408.
[wine/gsoc-2012-control.git] / dlls / user / hook16.c
blobe6282236b24ea0304634014b89b4c54b17e6eaa6
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 "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "wownt32.h"
28 #include "wine/winuser16.h"
29 #include "message.h"
30 #include "win.h"
31 #include "winproc.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(hook);
37 static LRESULT CALLBACK call_WH_MSGFILTER( INT code, WPARAM wp, LPARAM lp );
38 static LRESULT CALLBACK call_WH_KEYBOARD( INT code, WPARAM wp, LPARAM lp );
39 static LRESULT CALLBACK call_WH_GETMESSAGE( INT code, WPARAM wp, LPARAM lp );
40 static LRESULT CALLBACK call_WH_CALLWNDPROC( INT code, WPARAM wp, LPARAM lp );
41 static LRESULT CALLBACK call_WH_CBT( INT code, WPARAM wp, LPARAM lp );
42 static LRESULT CALLBACK call_WH_MOUSE( INT code, WPARAM wp, LPARAM lp );
43 static LRESULT CALLBACK call_WH_SHELL( INT code, WPARAM wp, LPARAM lp );
45 #define WH_MAXHOOK16 WH_SHELL /* Win16 only supports up to WH_SHELL */
46 #define NB_HOOKS16 (WH_MAXHOOK16 - WH_MINHOOK + 1)
48 static const HOOKPROC hook_procs[NB_HOOKS16] =
50 call_WH_MSGFILTER, /* WH_MSGFILTER */
51 NULL, /* WH_JOURNALRECORD */
52 NULL, /* WH_JOURNALPLAYBACK */
53 call_WH_KEYBOARD, /* WH_KEYBOARD */
54 call_WH_GETMESSAGE, /* WH_GETMESSAGE */
55 call_WH_CALLWNDPROC, /* WH_CALLWNDPROC */
56 call_WH_CBT, /* WH_CBT */
57 NULL, /* WH_SYSMSGFILTER */
58 call_WH_MOUSE, /* WH_MOUSE */
59 NULL, /* WH_HARDWARE */
60 NULL, /* WH_DEBUG */
61 call_WH_SHELL /* WH_SHELL */
65 /* this structure is stored in the thread queue */
66 struct hook16_queue_info
68 INT id; /* id of current hook */
69 HHOOK hook[NB_HOOKS16]; /* Win32 hook handles */
70 HOOKPROC16 proc[NB_HOOKS16]; /* 16-bit hook procedures */
75 /***********************************************************************
76 * map_msg_16_to_32
78 inline static void map_msg_16_to_32( const MSG16 *msg16, MSG *msg32 )
80 msg32->hwnd = WIN_Handle32(msg16->hwnd);
81 msg32->message = msg16->message;
82 msg32->wParam = msg16->wParam;
83 msg32->lParam = msg16->lParam;
84 msg32->time = msg16->time;
85 msg32->pt.x = msg16->pt.x;
86 msg32->pt.y = msg16->pt.y;
90 /***********************************************************************
91 * map_msg_32_to_16
93 inline static void map_msg_32_to_16( const MSG *msg32, MSG16 *msg16 )
95 msg16->hwnd = HWND_16(msg32->hwnd);
96 msg16->message = msg32->message;
97 msg16->wParam = msg32->wParam;
98 msg16->lParam = msg32->lParam;
99 msg16->time = msg32->time;
100 msg16->pt.x = msg32->pt.x;
101 msg16->pt.y = msg32->pt.y;
105 /***********************************************************************
106 * call_hook_16
108 static LRESULT call_hook_16( INT id, INT code, WPARAM wp, LPARAM lp )
110 struct hook16_queue_info *info = QUEUE_Current()->hook16_info;
111 WORD args[4];
112 LRESULT ret;
113 INT prev_id = info->id;
114 info->id = id;
116 args[3] = code;
117 args[2] = wp;
118 args[1] = HIWORD(lp);
119 args[0] = LOWORD(lp);
120 WOWCallback16Ex( (DWORD)info->proc[id - WH_MINHOOK], WCB16_PASCAL, sizeof(args), args, &ret );
122 info->id = prev_id;
124 /* Grrr. While the hook procedure is supposed to have an LRESULT return
125 value even in Win16, it seems that for those hook types where the
126 return value is interpreted as BOOL, Windows doesn't actually check
127 the HIWORD ... Some buggy Win16 programs, notably WINFILE, rely on
128 that, because they neglect to clear DX ... */
129 if (id != WH_JOURNALPLAYBACK) ret = LOWORD( ret );
130 return ret;
134 /***********************************************************************
135 * call_WH_MSGFILTER
137 static LRESULT CALLBACK call_WH_MSGFILTER( INT code, WPARAM wp, LPARAM lp )
139 MSG *msg32 = (MSG *)lp;
140 MSG16 msg16;
141 LRESULT ret;
143 map_msg_32_to_16( msg32, &msg16 );
144 lp = MapLS( &msg16 );
145 ret = call_hook_16( WH_MSGFILTER, code, wp, lp );
146 UnMapLS( lp );
147 return ret;
151 /***********************************************************************
152 * call_WH_KEYBOARD
154 static LRESULT CALLBACK call_WH_KEYBOARD( INT code, WPARAM wp, LPARAM lp )
156 return call_hook_16( WH_KEYBOARD, code, wp, lp );
160 /***********************************************************************
161 * call_WH_GETMESSAGE
163 static LRESULT CALLBACK call_WH_GETMESSAGE( INT code, WPARAM wp, LPARAM lp )
165 MSG *msg32 = (MSG *)lp;
166 MSG16 msg16;
167 LRESULT ret;
169 map_msg_32_to_16( msg32, &msg16 );
171 lp = MapLS( &msg16 );
172 ret = call_hook_16( WH_GETMESSAGE, code, wp, lp );
173 UnMapLS( lp );
175 map_msg_16_to_32( &msg16, msg32 );
176 return ret;
180 /***********************************************************************
181 * call_WH_CALLWNDPROC
183 static LRESULT CALLBACK call_WH_CALLWNDPROC( INT code, WPARAM wp, LPARAM lp )
185 CWPSTRUCT *cwp32 = (CWPSTRUCT *)lp;
186 CWPSTRUCT16 cwp16;
187 MSGPARAM16 mp16;
188 LRESULT ret;
190 cwp16.hwnd = HWND_16(cwp32->hwnd);
191 cwp16.lParam = cwp32->lParam;
193 WINPROC_MapMsg32ATo16( cwp32->hwnd, cwp32->message, cwp32->wParam,
194 &cwp16.message, &cwp16.wParam, &cwp16.lParam );
196 lp = MapLS( &cwp16 );
197 ret = call_hook_16( WH_CALLWNDPROC, code, wp, lp );
198 UnMapLS( lp );
200 mp16.wParam = cwp16.wParam;
201 mp16.lParam = cwp16.lParam;
202 mp16.lResult = 0;
203 WINPROC_UnmapMsg32ATo16( cwp32->hwnd, cwp32->message, cwp32->wParam, cwp32->lParam, &mp16 );
204 return ret;
208 /***********************************************************************
209 * call_WH_CBT
211 static LRESULT CALLBACK call_WH_CBT( INT code, WPARAM wp, LPARAM lp )
213 LRESULT ret = 0;
215 switch (code)
217 case HCBT_CREATEWND:
219 CBT_CREATEWNDA *cbtcw32 = (CBT_CREATEWNDA *)lp;
220 CBT_CREATEWND16 cbtcw16;
221 CREATESTRUCT16 cs16;
223 cs16.lpCreateParams = cbtcw32->lpcs->lpCreateParams;
224 cs16.hInstance = MapHModuleLS(cbtcw32->lpcs->hInstance);
225 cs16.hMenu = HMENU_16(cbtcw32->lpcs->hMenu);
226 cs16.hwndParent = HWND_16(cbtcw32->lpcs->hwndParent);
227 cs16.cy = cbtcw32->lpcs->cy;
228 cs16.cx = cbtcw32->lpcs->cx;
229 cs16.y = cbtcw32->lpcs->y;
230 cs16.x = cbtcw32->lpcs->x;
231 cs16.style = cbtcw32->lpcs->style;
232 cs16.lpszName = MapLS( cbtcw32->lpcs->lpszName );
233 cs16.lpszClass = MapLS( cbtcw32->lpcs->lpszClass );
234 cs16.dwExStyle = cbtcw32->lpcs->dwExStyle;
236 cbtcw16.lpcs = (CREATESTRUCT16 *)MapLS( &cs16 );
237 cbtcw16.hwndInsertAfter = HWND_16( cbtcw32->hwndInsertAfter );
239 lp = MapLS( &cbtcw16 );
240 ret = call_hook_16( WH_CBT, code, wp, lp );
241 UnMapLS( cs16.lpszName );
242 UnMapLS( cs16.lpszClass );
244 cbtcw32->hwndInsertAfter = WIN_Handle32( cbtcw16.hwndInsertAfter );
245 UnMapLS( (SEGPTR)cbtcw16.lpcs );
246 UnMapLS( lp );
247 break;
250 case HCBT_ACTIVATE:
252 CBTACTIVATESTRUCT *cas32 = (CBTACTIVATESTRUCT *)lp;
253 CBTACTIVATESTRUCT16 cas16;
255 cas16.fMouse = cas32->fMouse;
256 cas16.hWndActive = HWND_16( cas32->hWndActive );
258 lp = MapLS( &cas16 );
259 ret = call_hook_16( WH_CBT, code, wp, lp );
260 UnMapLS( lp );
261 break;
263 case HCBT_CLICKSKIPPED:
265 MOUSEHOOKSTRUCT *ms32 = (MOUSEHOOKSTRUCT *)lp;
266 MOUSEHOOKSTRUCT16 ms16;
268 ms16.pt.x = ms32->pt.x;
269 ms16.pt.y = ms32->pt.y;
270 ms16.hwnd = HWND_16( ms32->hwnd );
271 ms16.wHitTestCode = ms32->wHitTestCode;
272 ms16.dwExtraInfo = ms32->dwExtraInfo;
274 lp = MapLS( &ms16 );
275 ret = call_hook_16( WH_CBT, code, wp, lp );
276 UnMapLS( lp );
277 break;
279 case HCBT_MOVESIZE:
281 RECT *rect32 = (RECT *)lp;
282 RECT16 rect16;
284 CONV_RECT32TO16( rect32, &rect16 );
285 lp = MapLS( &rect16 );
286 ret = call_hook_16( WH_CBT, code, wp, lp );
287 UnMapLS( lp );
288 break;
291 return ret;
295 /***********************************************************************
296 * call_WH_MOUSE
298 static LRESULT CALLBACK call_WH_MOUSE( INT code, WPARAM wp, LPARAM lp )
300 MOUSEHOOKSTRUCT *ms32 = (MOUSEHOOKSTRUCT *)lp;
301 MOUSEHOOKSTRUCT16 ms16;
302 LRESULT ret;
304 ms16.pt.x = ms32->pt.x;
305 ms16.pt.y = ms32->pt.y;
306 ms16.hwnd = HWND_16( ms32->hwnd );
307 ms16.wHitTestCode = ms32->wHitTestCode;
308 ms16.dwExtraInfo = ms32->dwExtraInfo;
310 lp = MapLS( &ms16 );
311 ret = call_hook_16( WH_MOUSE, code, wp, lp );
312 UnMapLS( lp );
313 return ret;
317 /***********************************************************************
318 * call_WH_SHELL
320 static LRESULT CALLBACK call_WH_SHELL( INT code, WPARAM wp, LPARAM lp )
322 return call_hook_16( WH_SHELL, code, wp, lp );
326 /***********************************************************************
327 * SetWindowsHook (USER.121)
329 FARPROC16 WINAPI SetWindowsHook16( INT16 id, HOOKPROC16 proc )
331 HINSTANCE16 hInst = FarGetOwner16( HIWORD(proc) );
333 /* WH_MSGFILTER is the only task-specific hook for SetWindowsHook() */
334 HTASK16 hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
336 return (FARPROC16)SetWindowsHookEx16( id, proc, hInst, hTask );
340 /***********************************************************************
341 * SetWindowsHookEx (USER.291)
343 HHOOK WINAPI SetWindowsHookEx16( INT16 id, HOOKPROC16 proc, HINSTANCE16 hInst, HTASK16 hTask )
345 MESSAGEQUEUE *queue = QUEUE_Current();
346 struct hook16_queue_info *info;
347 HHOOK hook;
348 int index = id - WH_MINHOOK;
350 if (!queue) return 0;
351 if (id < WH_MINHOOK || id > WH_MAXHOOK16) return 0;
352 if (!hook_procs[index])
354 FIXME( "hook type %d broken in Win16\n", id );
355 return 0;
357 if (!hTask) FIXME( "System-global hooks (%d) broken in Win16\n", id );
358 else if (hTask != GetCurrentTask())
360 FIXME( "setting hook (%d) on other task not supported\n", id );
361 return 0;
364 if (!(info = queue->hook16_info))
366 if (!(info = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*info) ))) return 0;
367 queue->hook16_info = info;
369 if (info->hook[index])
371 FIXME( "Multiple hooks (%d) for the same task not supported yet\n", id );
372 return 0;
374 if (!(hook = SetWindowsHookExA( id, hook_procs[index], 0, GetCurrentThreadId() ))) return 0;
375 info->hook[index] = hook;
376 info->proc[index] = proc;
377 return hook;
381 /***********************************************************************
382 * UnhookWindowsHook (USER.234)
384 BOOL16 WINAPI UnhookWindowsHook16( INT16 id, HOOKPROC16 proc )
386 MESSAGEQUEUE *queue = QUEUE_Current();
387 struct hook16_queue_info *info;
388 int index = id - WH_MINHOOK;
390 if (id < WH_MINHOOK || id > WH_MAXHOOK16) return FALSE;
391 if (!queue || !(info = queue->hook16_info)) return FALSE;
392 if (info->proc[index] != proc) return FALSE;
393 if (!UnhookWindowsHookEx( info->hook[index] )) return FALSE;
394 info->hook[index] = 0;
395 info->proc[index] = 0;
396 return TRUE;
400 /***********************************************************************
401 * UnhookWindowsHookEx (USER.292)
403 BOOL16 WINAPI UnhookWindowsHookEx16( HHOOK hhook )
405 MESSAGEQUEUE *queue = QUEUE_Current();
406 struct hook16_queue_info *info;
407 int index;
409 if (!queue || !(info = queue->hook16_info)) return FALSE;
410 for (index = 0; index < NB_HOOKS16; index++)
412 if (info->hook[index] == hhook)
414 info->hook[index] = 0;
415 info->proc[index] = 0;
416 return UnhookWindowsHookEx( hhook );
419 return FALSE;
423 /***********************************************************************
424 * CallMsgFilter32 (USER.823)
426 BOOL16 WINAPI CallMsgFilter32_16( MSG32_16 *lpmsg16_32, INT16 code, BOOL16 wHaveParamHigh )
428 MSG msg32;
429 BOOL16 ret;
431 if (GetSysModalWindow16()) return FALSE;
432 msg32.hwnd = WIN_Handle32( lpmsg16_32->msg.hwnd );
433 msg32.message = lpmsg16_32->msg.message;
434 msg32.lParam = lpmsg16_32->msg.lParam;
435 msg32.time = lpmsg16_32->msg.time;
436 msg32.pt.x = lpmsg16_32->msg.pt.x;
437 msg32.pt.y = lpmsg16_32->msg.pt.y;
438 if (wHaveParamHigh) msg32.wParam = MAKELONG(lpmsg16_32->msg.wParam, lpmsg16_32->wParamHigh);
439 else msg32.wParam = lpmsg16_32->msg.wParam;
441 ret = (BOOL16)CallMsgFilterA(&msg32, code);
443 lpmsg16_32->msg.hwnd = HWND_16( msg32.hwnd );
444 lpmsg16_32->msg.message = msg32.message;
445 lpmsg16_32->msg.wParam = LOWORD(msg32.wParam);
446 lpmsg16_32->msg.lParam = msg32.lParam;
447 lpmsg16_32->msg.time = msg32.time;
448 lpmsg16_32->msg.pt.x = msg32.pt.x;
449 lpmsg16_32->msg.pt.y = msg32.pt.y;
450 if (wHaveParamHigh) lpmsg16_32->wParamHigh = HIWORD(msg32.wParam);
451 return ret;
455 /***********************************************************************
456 * CallMsgFilter (USER.123)
458 BOOL16 WINAPI CallMsgFilter16( MSG16 *msg, INT16 code )
460 return CallMsgFilter32_16( (MSG32_16 *)msg, code, FALSE );
464 /***********************************************************************
465 * CallNextHookEx (USER.293)
467 LRESULT WINAPI CallNextHookEx16( HHOOK hhook, INT16 code, WPARAM16 wparam, LPARAM lparam )
469 MESSAGEQUEUE *queue = QUEUE_Current();
470 struct hook16_queue_info *info;
471 LRESULT ret = 0;
473 if (!queue || !(info = queue->hook16_info)) return 0;
475 switch (info->id)
477 case WH_MSGFILTER:
479 MSG16 *msg16 = MapSL(lparam);
480 MSG msg32;
482 map_msg_16_to_32( msg16, &msg32 );
483 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&msg32 );
484 break;
487 case WH_GETMESSAGE:
489 MSG16 *msg16 = MapSL(lparam);
490 MSG msg32;
492 map_msg_16_to_32( msg16, &msg32 );
493 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&msg32 );
494 map_msg_32_to_16( &msg32, msg16 );
495 break;
498 case WH_CALLWNDPROC:
500 CWPSTRUCT16 *cwp16 = MapSL(lparam);
501 CWPSTRUCT cwp32;
503 cwp32.hwnd = WIN_Handle32(cwp16->hwnd);
504 cwp32.lParam = cwp16->lParam;
506 WINPROC_MapMsg16To32A( cwp32.hwnd, cwp16->message, cwp16->wParam,
507 &cwp32.message, &cwp32.wParam, &cwp32.lParam );
508 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&cwp32 );
509 WINPROC_UnmapMsg16To32A( cwp32.hwnd, cwp32.message, cwp32.wParam, cwp32.lParam, 0 );
510 break;
513 case WH_CBT:
514 switch (code)
516 case HCBT_CREATEWND:
518 CBT_CREATEWNDA cbtcw32;
519 CREATESTRUCTA cs32;
520 CBT_CREATEWND16 *cbtcw16 = MapSL(lparam);
521 CREATESTRUCT16 *cs16 = MapSL( (SEGPTR)cbtcw16->lpcs );
523 cbtcw32.lpcs = &cs32;
524 cbtcw32.hwndInsertAfter = WIN_Handle32( cbtcw16->hwndInsertAfter );
526 cs32.lpCreateParams = cs16->lpCreateParams;
527 cs32.hInstance = MapHModuleSL(cs16->hInstance);
528 cs32.hMenu = HMENU_32(cs16->hMenu);
529 cs32.hwndParent = WIN_Handle32(cs16->hwndParent);
530 cs32.cy = cs16->cy;
531 cs32.cx = cs16->cx;
532 cs32.y = cs16->y;
533 cs32.x = cs16->x;
534 cs32.style = cs16->style;
535 cs32.lpszName = MapSL( cs16->lpszName );
536 cs32.lpszClass = MapSL( cs16->lpszClass );
537 cs32.dwExStyle = cs16->dwExStyle;
539 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&cbtcw32 );
540 cbtcw16->hwndInsertAfter = HWND_16( cbtcw32.hwndInsertAfter );
541 break;
543 case HCBT_ACTIVATE:
545 CBTACTIVATESTRUCT16 *cas16 = MapSL(lparam);
546 CBTACTIVATESTRUCT cas32;
547 cas32.fMouse = cas16->fMouse;
548 cas32.hWndActive = WIN_Handle32(cas16->hWndActive);
549 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&cas32 );
550 break;
552 case HCBT_CLICKSKIPPED:
554 MOUSEHOOKSTRUCT16 *ms16 = MapSL(lparam);
555 MOUSEHOOKSTRUCT ms32;
557 ms32.pt.x = ms16->pt.x;
558 ms32.pt.y = ms16->pt.y;
559 /* wHitTestCode may be negative, so convince compiler to do
560 correct sign extension. Yay. :| */
561 ms32.wHitTestCode = (INT)(INT16)ms16->wHitTestCode;
562 ms32.dwExtraInfo = ms16->dwExtraInfo;
563 ms32.hwnd = WIN_Handle32( ms16->hwnd );
564 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&ms32 );
565 break;
567 case HCBT_MOVESIZE:
569 RECT16 *rect16 = MapSL(lparam);
570 RECT rect32;
572 CONV_RECT16TO32( rect16, &rect32 );
573 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&rect32 );
574 break;
577 break;
579 case WH_MOUSE:
581 MOUSEHOOKSTRUCT16 *ms16 = MapSL(lparam);
582 MOUSEHOOKSTRUCT ms32;
584 ms32.pt.x = ms16->pt.x;
585 ms32.pt.y = ms16->pt.y;
586 /* wHitTestCode may be negative, so convince compiler to do
587 correct sign extension. Yay. :| */
588 ms32.wHitTestCode = (INT)((INT16)ms16->wHitTestCode);
589 ms32.dwExtraInfo = ms16->dwExtraInfo;
590 ms32.hwnd = WIN_Handle32(ms16->hwnd);
591 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&ms32 );
592 break;
595 case WH_SHELL:
596 case WH_KEYBOARD:
597 ret = CallNextHookEx( hhook, code, wparam, lparam );
598 break;
600 case WH_HARDWARE:
601 case WH_FOREGROUNDIDLE:
602 case WH_CALLWNDPROCRET:
603 case WH_SYSMSGFILTER:
604 case WH_JOURNALRECORD:
605 case WH_JOURNALPLAYBACK:
606 default:
607 FIXME("\t[%i] 16to32 translation unimplemented\n", info->id);
608 ret = CallNextHookEx( hhook, code, wparam, lparam );
609 break;
611 return ret;
615 /***********************************************************************
616 * DefHookProc (USER.235)
618 LRESULT WINAPI DefHookProc16( INT16 code, WPARAM16 wparam, LPARAM lparam, HHOOK *hhook )
620 return CallNextHookEx16( *hhook, code, wparam, lparam );