Fixed compilation for non-i386.
[wine/multimedia.git] / windows / hook.c
blob5c8c1f93c5c55c2a46e07b8e0f1d0d8dfab8d5fd
1 /*
2 * Windows hook functions
4 * Copyright 1994, 1995 Alexandre Julliard
5 * 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
25 * Warning!
26 * A HHOOK is a 32-bit handle for compatibility with Windows 3.0 where it was
27 * a pointer to the next function. Now it is in fact composed of a USER heap
28 * handle in the low 16 bits and of a HOOK_MAGIC value in the high 16 bits.
31 #include "windef.h"
32 #include "winbase.h"
33 #include "wingdi.h"
34 #include "winuser.h"
35 #include "wine/winuser16.h"
36 #include "wine/winbase16.h"
37 #include "wownt32.h"
38 #include "hook.h"
39 #include "win.h"
40 #include "queue.h"
41 #include "user.h"
42 #include "heap.h"
43 #include "struct32.h"
44 #include "winproc.h"
45 #include "wine/debug.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(hook);
49 #include "pshpack1.h"
51 /* Hook data (pointed to by a HHOOK) */
52 typedef struct
54 HANDLE16 next; /* 00 Next hook in chain */
55 HOOKPROC proc; /* 02 Hook procedure (original) */
56 INT16 id; /* 06 Hook id (WH_xxx) */
57 HQUEUE16 ownerQueue; /* 08 Owner queue (0 for system hook) */
58 HMODULE16 ownerModule; /* 0a Owner module */
59 WORD flags; /* 0c flags */
60 } HOOKDATA;
62 #include "poppack.h"
64 #define HOOK_MAGIC ((int)'H' | (int)'K' << 8) /* 'HK' */
65 #define HHOOK_32(h) ((HHOOK)(h ? MAKELONG(h, HOOK_MAGIC) : 0))
66 #define HHOOK_16(h) ((HANDLE16)((HIWORD(h) == HOOK_MAGIC) ? LOWORD(h) : 0))
68 /* This should probably reside in USER heap */
69 static HANDLE16 HOOK_systemHooks[WH_NB_HOOKS] = { 0, };
71 /* ### start build ### */
72 extern LONG CALLBACK HOOK_CallTo16_long_wwl(HOOKPROC16,WORD,WORD,LONG);
73 /* ### stop build ### */
76 /***********************************************************************
77 * call_hook_16
79 inline static LRESULT call_hook_16( HOOKPROC16 proc, INT id, INT code, WPARAM wparam, LPARAM lparam )
81 LRESULT ret = HOOK_CallTo16_long_wwl( proc, code, wparam, lparam );
82 /* Grrr. While the hook procedure is supposed to have an LRESULT return
83 value even in Win16, it seems that for those hook types where the
84 return value is interpreted as BOOL, Windows doesn't actually check
85 the HIWORD ... Some buggy Win16 programs, notably WINFILE, rely on
86 that, because they neglect to clear DX ... */
87 if (id != WH_JOURNALPLAYBACK) ret = LOWORD( ret );
88 return ret;
92 /***********************************************************************
93 * call_hook_16_to_32
95 * Convert hook params to 32-bit and call 32-bit hook procedure
97 static LRESULT call_hook_16_to_32( HOOKPROC proc, INT id, INT code, WPARAM wparam, LPARAM lparam,
98 BOOL unicode )
100 LRESULT ret = 0;
102 switch( id )
104 case WH_MSGFILTER:
105 case WH_SYSMSGFILTER:
106 case WH_JOURNALRECORD:
108 MSG16 *msg16 = MapSL(lparam);
109 MSG msg32;
111 STRUCT32_MSG16to32( msg16, &msg32 );
112 ret = proc( code, wparam, (LPARAM)&msg32 );
113 break;
116 case WH_GETMESSAGE:
118 MSG16 *msg16 = MapSL(lparam);
119 MSG msg32;
121 STRUCT32_MSG16to32( msg16, &msg32 );
122 ret = proc( code, wparam, (LPARAM)&msg32 );
123 STRUCT32_MSG32to16( &msg32, msg16 );
124 break;
127 case WH_JOURNALPLAYBACK:
129 EVENTMSG16 *em16 = MapSL(lparam);
130 EVENTMSG em32;
132 em32.message = em16->message;
133 em32.paramL = em16->paramL;
134 em32.paramH = em16->paramH;
135 em32.time = em16->time;
136 em32.hwnd = 0; /* FIXME */
137 ret = proc( code, wparam, (LPARAM)&em32 );
138 break;
141 case WH_CALLWNDPROC:
143 CWPSTRUCT16 *cwp16 = MapSL(lparam);
144 CWPSTRUCT cwp32;
146 cwp32.hwnd = WIN_Handle32(cwp16->hwnd);
147 cwp32.lParam = cwp16->lParam;
149 if (unicode)
150 WINPROC_MapMsg16To32W( cwp32.hwnd, cwp16->message, cwp16->wParam,
151 &cwp32.message, &cwp32.wParam, &cwp32.lParam );
152 else
153 WINPROC_MapMsg16To32A( cwp32.hwnd, cwp16->message, cwp16->wParam,
154 &cwp32.message, &cwp32.wParam, &cwp32.lParam );
156 ret = proc( code, wparam, (LPARAM)&cwp32 );
158 if (unicode)
159 WINPROC_UnmapMsg16To32W( cwp32.hwnd, cwp32.message, cwp32.wParam, cwp32.lParam, 0 );
160 else
161 WINPROC_UnmapMsg16To32A( cwp32.hwnd, cwp32.message, cwp32.wParam, cwp32.lParam, 0 );
162 break;
165 case WH_CBT:
166 switch (code)
168 case HCBT_CREATEWND:
170 CBT_CREATEWNDA cbtcw32;
171 CREATESTRUCTA cs32;
172 CBT_CREATEWND16 *cbtcw16 = MapSL(lparam);
173 CREATESTRUCT16 *cs16 = MapSL( (SEGPTR)cbtcw16->lpcs );
175 cbtcw32.lpcs = &cs32;
176 cbtcw32.hwndInsertAfter = WIN_Handle32( cbtcw16->hwndInsertAfter );
177 STRUCT32_CREATESTRUCT16to32A( cs16, &cs32 );
179 if (unicode)
181 cs32.lpszName = (LPSTR)map_str_16_to_32W( cs16->lpszName );
182 cs32.lpszClass = (LPSTR)map_str_16_to_32W( cs16->lpszClass );
183 ret = proc( code, wparam, (LPARAM)&cbtcw32 );
184 unmap_str_16_to_32W( (LPWSTR)cs32.lpszName );
185 unmap_str_16_to_32W( (LPWSTR)cs32.lpszClass );
187 else
189 cs32.lpszName = MapSL( cs16->lpszName );
190 cs32.lpszClass = MapSL( cs16->lpszClass );
191 ret = proc( code, wparam, (LPARAM)&cbtcw32 );
193 cbtcw16->hwndInsertAfter = HWND_16( cbtcw32.hwndInsertAfter );
194 break;
196 case HCBT_ACTIVATE:
198 CBTACTIVATESTRUCT16 *cas16 = MapSL(lparam);
199 CBTACTIVATESTRUCT cas32;
200 cas32.fMouse = cas16->fMouse;
201 cas32.hWndActive = WIN_Handle32(cas16->hWndActive);
202 ret = proc( code, wparam, (LPARAM)&cas32 );
203 break;
205 case HCBT_CLICKSKIPPED:
207 MOUSEHOOKSTRUCT16 *ms16 = MapSL(lparam);
208 MOUSEHOOKSTRUCT ms32;
210 ms32.pt.x = ms16->pt.x;
211 ms32.pt.y = ms16->pt.y;
212 /* wHitTestCode may be negative, so convince compiler to do
213 correct sign extension. Yay. :| */
214 ms32.wHitTestCode = (INT)(INT16)ms16->wHitTestCode;
215 ms32.dwExtraInfo = ms16->dwExtraInfo;
216 ms32.hwnd = WIN_Handle32( ms16->hwnd );
217 ret = proc( code, wparam, (LPARAM)&ms32 );
218 break;
220 case HCBT_MOVESIZE:
222 RECT16 *rect16 = MapSL(lparam);
223 RECT rect32;
225 CONV_RECT16TO32( rect16, &rect32 );
226 ret = proc( code, wparam, (LPARAM)&rect32 );
227 break;
230 break;
232 case WH_MOUSE:
234 MOUSEHOOKSTRUCT16 *ms16 = MapSL(lparam);
235 MOUSEHOOKSTRUCT ms32;
237 ms32.pt.x = ms16->pt.x;
238 ms32.pt.y = ms16->pt.y;
239 /* wHitTestCode may be negative, so convince compiler to do
240 correct sign extension. Yay. :| */
241 ms32.wHitTestCode = (INT)((INT16)ms16->wHitTestCode);
242 ms32.dwExtraInfo = ms16->dwExtraInfo;
243 ms32.hwnd = WIN_Handle32(ms16->hwnd);
244 ret = proc( code, wparam, (LPARAM)&ms32 );
245 break;
248 case WH_DEBUG:
250 DEBUGHOOKINFO16 *dh16 = MapSL(lparam);
251 DEBUGHOOKINFO dh32;
253 dh32.idThread = 0; /* FIXME */
254 dh32.idThreadInstaller = 0; /* FIXME */
255 dh32.lParam = dh16->lParam; /* FIXME Check for sign ext */
256 dh32.wParam = dh16->wParam;
257 dh32.code = dh16->code;
259 /* do sign extension if it was WH_MSGFILTER */
260 if (wparam == 0xffff) wparam = WH_MSGFILTER;
261 ret = proc( code, wparam, (LPARAM)&dh32 );
262 break;
265 case WH_SHELL:
266 case WH_KEYBOARD:
267 ret = proc( code, wparam, lparam );
268 break;
270 case WH_HARDWARE:
271 case WH_FOREGROUNDIDLE:
272 case WH_CALLWNDPROCRET:
273 default:
274 FIXME("\t[%i] 16to32 translation unimplemented\n", id);
275 ret = proc( code, wparam, lparam );
276 break;
278 return ret;
282 /***********************************************************************
283 * call_hook_32_to_16
285 * Convert hook params to 16-bit and call 16-bit hook procedure
287 static LRESULT call_hook_32_to_16( HOOKPROC16 proc, INT id, INT code, WPARAM wparam, LPARAM lparam,
288 BOOL unicode )
290 LRESULT ret = 0;
292 switch (id)
294 case WH_MSGFILTER:
295 case WH_SYSMSGFILTER:
296 case WH_JOURNALRECORD:
298 MSG *msg32 = (MSG *)lparam;
299 MSG16 msg16;
301 STRUCT32_MSG32to16( msg32, &msg16 );
302 lparam = MapLS( &msg16 );
303 ret = call_hook_16( proc, id, code, wparam, lparam );
304 UnMapLS( lparam );
305 break;
308 case WH_GETMESSAGE:
310 MSG *msg32 = (MSG *)lparam;
311 MSG16 msg16;
313 STRUCT32_MSG32to16( msg32, &msg16 );
314 lparam = MapLS( &msg16 );
315 ret = call_hook_16( proc, id, code, wparam, lparam );
316 UnMapLS( lparam );
317 STRUCT32_MSG16to32( &msg16, msg32 );
318 break;
321 case WH_JOURNALPLAYBACK:
323 EVENTMSG *em32 = (EVENTMSG *)lparam;
324 EVENTMSG16 em16;
326 em16.message = em32->message;
327 em16.paramL = em32->paramL;
328 em16.paramH = em32->paramH;
329 em16.time = em32->time;
330 lparam = MapLS( &em16 );
331 ret = call_hook_16( proc, id, code, wparam, lparam );
332 UnMapLS( lparam );
333 break;
336 case WH_CALLWNDPROC:
338 CWPSTRUCT *cwp32 = (CWPSTRUCT *)lparam;
339 CWPSTRUCT16 cwp16;
340 MSGPARAM16 mp16;
342 cwp16.hwnd = HWND_16(cwp32->hwnd);
343 cwp16.lParam = cwp32->lParam;
345 if (unicode)
346 WINPROC_MapMsg32WTo16( cwp32->hwnd, cwp32->message, cwp32->wParam,
347 &cwp16.message, &cwp16.wParam, &cwp16.lParam );
348 else
349 WINPROC_MapMsg32ATo16( cwp32->hwnd, cwp32->message, cwp32->wParam,
350 &cwp16.message, &cwp16.wParam, &cwp16.lParam );
352 lparam = MapLS( &cwp16 );
353 ret = call_hook_16( proc, id, code, wparam, lparam );
354 UnMapLS( lparam );
356 mp16.wParam = cwp16.wParam;
357 mp16.lParam = cwp16.lParam;
358 mp16.lResult = 0;
359 if (unicode)
360 WINPROC_UnmapMsg32WTo16( cwp32->hwnd, cwp32->message, cwp32->wParam,
361 cwp32->lParam, &mp16 );
362 else
363 WINPROC_UnmapMsg32ATo16( cwp32->hwnd, cwp32->message, cwp32->wParam,
364 cwp32->lParam, &mp16 );
365 break;
368 case WH_CBT:
369 switch (code)
371 case HCBT_CREATEWND:
373 CBT_CREATEWNDA *cbtcw32 = (CBT_CREATEWNDA *)lparam;
374 CBT_CREATEWND16 cbtcw16;
375 CREATESTRUCT16 cs16;
377 STRUCT32_CREATESTRUCT32Ato16( cbtcw32->lpcs, &cs16 );
378 cbtcw16.lpcs = (CREATESTRUCT16 *)MapLS( &cs16 );
379 cbtcw16.hwndInsertAfter = HWND_16( cbtcw32->hwndInsertAfter );
380 lparam = MapLS( &cbtcw16 );
382 if (unicode)
384 cs16.lpszName = map_str_32W_to_16( (LPWSTR)cbtcw32->lpcs->lpszName );
385 cs16.lpszClass = map_str_32W_to_16( (LPWSTR)cbtcw32->lpcs->lpszClass );
386 ret = call_hook_16( proc, id, code, wparam, lparam );
387 unmap_str_32W_to_16( cs16.lpszName );
388 unmap_str_32W_to_16( cs16.lpszClass );
390 else
392 cs16.lpszName = MapLS( cbtcw32->lpcs->lpszName );
393 cs16.lpszClass = MapLS( cbtcw32->lpcs->lpszClass );
394 ret = call_hook_16( proc, id, code, wparam, lparam );
395 UnMapLS( cs16.lpszName );
396 UnMapLS( cs16.lpszClass );
398 cbtcw32->hwndInsertAfter = WIN_Handle32( cbtcw16.hwndInsertAfter );
399 UnMapLS( (SEGPTR)cbtcw16.lpcs );
400 UnMapLS( lparam );
401 break;
404 case HCBT_ACTIVATE:
406 CBTACTIVATESTRUCT *cas32 = (CBTACTIVATESTRUCT *)lparam;
407 CBTACTIVATESTRUCT16 cas16;
409 cas16.fMouse = cas32->fMouse;
410 cas16.hWndActive = HWND_16( cas32->hWndActive );
412 lparam = MapLS( &cas16 );
413 ret = call_hook_16( proc, id, code, wparam, lparam );
414 UnMapLS( lparam );
415 break;
417 case HCBT_CLICKSKIPPED:
419 MOUSEHOOKSTRUCT *ms32 = (MOUSEHOOKSTRUCT *)lparam;
420 MOUSEHOOKSTRUCT16 ms16;
422 ms16.pt.x = ms32->pt.x;
423 ms16.pt.y = ms32->pt.y;
424 ms16.hwnd = HWND_16( ms32->hwnd );
425 ms16.wHitTestCode = ms32->wHitTestCode;
426 ms16.dwExtraInfo = ms32->dwExtraInfo;
428 lparam = MapLS( &ms16 );
429 ret = call_hook_16( proc, id, code, wparam, lparam );
430 UnMapLS( lparam );
431 break;
433 case HCBT_MOVESIZE:
435 RECT *rect32 = (RECT *)lparam;
436 RECT16 rect16;
438 CONV_RECT32TO16( rect32, &rect16 );
439 lparam = MapLS( &rect16 );
440 ret = call_hook_16( proc, id, code, wparam, lparam );
441 UnMapLS( lparam );
442 break;
445 break;
447 case WH_MOUSE:
449 MOUSEHOOKSTRUCT *ms32 = (MOUSEHOOKSTRUCT *)lparam;
450 MOUSEHOOKSTRUCT16 ms16;
452 ms16.pt.x = ms32->pt.x;
453 ms16.pt.y = ms32->pt.y;
454 ms16.hwnd = HWND_16( ms32->hwnd );
455 ms16.wHitTestCode = ms32->wHitTestCode;
456 ms16.dwExtraInfo = ms32->dwExtraInfo;
458 lparam = MapLS( &ms16 );
459 ret = call_hook_16( proc, id, code, wparam, lparam );
460 UnMapLS( lparam );
461 break;
464 case WH_DEBUG:
466 DEBUGHOOKINFO *dh32 = (DEBUGHOOKINFO *)lparam;
467 DEBUGHOOKINFO16 dh16;
469 dh16.hModuleHook = 0; /* FIXME */
470 dh16.reserved = 0;
471 dh16.lParam = dh32->lParam;
472 dh16.wParam = dh32->wParam;
473 dh16.code = dh32->code;
475 lparam = MapLS( &dh16 );
476 ret = call_hook_16( proc, id, code, wparam, lparam );
477 UnMapLS( lparam );
478 break;
481 case WH_SHELL:
482 case WH_KEYBOARD:
483 ret = call_hook_16( proc, id, code, wparam, lparam );
484 break;
486 case WH_HARDWARE:
487 case WH_FOREGROUNDIDLE:
488 case WH_CALLWNDPROCRET:
489 default:
490 FIXME("\t[%i] 32to16 translation unimplemented\n", id);
491 ret = call_hook_16( proc, id, code, wparam, lparam );
492 break;
494 return ret;
498 /***********************************************************************
499 * call_hook_32_to_32
501 * Convert hook params to/from Unicode and call hook procedure
503 static LRESULT call_hook_32_to_32( HOOKPROC proc, INT id, INT code, WPARAM wparam, LPARAM lparam,
504 BOOL to_unicode )
506 if (id != WH_CBT || code != HCBT_CREATEWND) return proc( code, wparam, lparam );
508 if (to_unicode) /* ASCII to Unicode */
510 CBT_CREATEWNDA *cbtcwA = (CBT_CREATEWNDA *)lparam;
511 CBT_CREATEWNDW cbtcwW;
512 CREATESTRUCTW csW;
513 LRESULT ret;
515 cbtcwW.lpcs = &csW;
516 cbtcwW.hwndInsertAfter = cbtcwA->hwndInsertAfter;
517 csW = *(CREATESTRUCTW *)cbtcwA->lpcs;
519 if (HIWORD(cbtcwA->lpcs->lpszName))
520 csW.lpszName = HEAP_strdupAtoW( GetProcessHeap(), 0, cbtcwA->lpcs->lpszName );
521 if (HIWORD(cbtcwA->lpcs->lpszClass))
522 csW.lpszClass = HEAP_strdupAtoW( GetProcessHeap(), 0, cbtcwA->lpcs->lpszClass );
523 ret = proc( code, wparam, (LPARAM)&cbtcwW );
524 cbtcwA->hwndInsertAfter = cbtcwW.hwndInsertAfter;
525 if (HIWORD(csW.lpszName)) HeapFree( GetProcessHeap(), 0, (LPWSTR)csW.lpszName );
526 if (HIWORD(csW.lpszClass)) HeapFree( GetProcessHeap(), 0, (LPWSTR)csW.lpszClass );
527 return ret;
529 else /* Unicode to ASCII */
531 CBT_CREATEWNDW *cbtcwW = (CBT_CREATEWNDW *)lparam;
532 CBT_CREATEWNDA cbtcwA;
533 CREATESTRUCTA csA;
534 LRESULT ret;
536 cbtcwA.lpcs = &csA;
537 cbtcwA.hwndInsertAfter = cbtcwW->hwndInsertAfter;
538 csA = *(CREATESTRUCTA *)cbtcwW->lpcs;
540 if (HIWORD(cbtcwW->lpcs->lpszName))
541 csA.lpszName = HEAP_strdupWtoA( GetProcessHeap(), 0, cbtcwW->lpcs->lpszName );
542 if (HIWORD(cbtcwW->lpcs->lpszClass))
543 csA.lpszClass = HEAP_strdupWtoA( GetProcessHeap(), 0, cbtcwW->lpcs->lpszClass );
544 ret = proc( code, wparam, (LPARAM)&cbtcwA );
545 cbtcwW->hwndInsertAfter = cbtcwA.hwndInsertAfter;
546 if (HIWORD(csA.lpszName)) HeapFree( GetProcessHeap(), 0, (LPSTR)csA.lpszName );
547 if (HIWORD(csA.lpszClass)) HeapFree( GetProcessHeap(), 0, (LPSTR)csA.lpszClass );
548 return ret;
553 /***********************************************************************
554 * call_hook
556 * Call a hook procedure.
558 inline static LRESULT call_hook( HOOKDATA *data, INT fromtype, INT code,
559 WPARAM wparam, LPARAM lparam )
561 INT type = (data->flags & HOOK_MAPTYPE);
562 LRESULT ret;
564 /* Suspend window structure locks before calling user code */
565 int iWndsLocks = WIN_SuspendWndsLock();
567 if (type == HOOK_WIN16)
569 if (fromtype == HOOK_WIN16) /* 16->16 */
570 ret = call_hook_16( (HOOKPROC16)data->proc, data->id, code, wparam, lparam );
571 else /* 32->16 */
572 ret = call_hook_32_to_16( (HOOKPROC16)data->proc, data->id, code, wparam,
573 lparam, (type == HOOK_WIN32W) );
575 else if (fromtype == HOOK_WIN16) /* 16->32 */
576 ret = call_hook_16_to_32( data->proc, data->id, code, wparam,
577 lparam, (type == HOOK_WIN32W) );
578 else /* 32->32, check unicode */
580 if (type == fromtype)
581 ret = data->proc( code, wparam, lparam );
582 else
583 ret = call_hook_32_to_32( data->proc, data->id, code, wparam,
584 lparam, (type == HOOK_WIN32W) );
586 WIN_RestoreWndsLock(iWndsLocks);
587 return ret;
591 /***********************************************************************
592 * HOOK_GetNextHook
594 * Get the next hook of a given hook.
596 static HHOOK HOOK_GetNextHook( HHOOK hook )
598 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(HHOOK_16(hook));
600 if (!data || !hook) return 0;
601 if (data->next) return HHOOK_32(data->next);
602 if (!data->ownerQueue) return 0; /* Already system hook */
604 /* Now start enumerating the system hooks */
605 return HHOOK_32(HOOK_systemHooks[data->id - WH_MINHOOK]);
609 /***********************************************************************
610 * HOOK_GetHook
612 * Get the first hook for a given type.
614 static HHOOK HOOK_GetHook( INT16 id )
616 MESSAGEQUEUE *queue;
617 HANDLE16 handle = 0;
619 if ((queue = QUEUE_Current()) != NULL)
620 handle = queue->hooks[id - WH_MINHOOK];
621 if (!handle) handle = HOOK_systemHooks[id - WH_MINHOOK];
622 return HHOOK_32(handle);
626 /***********************************************************************
627 * HOOK_SetHook
629 * Install a given hook.
631 static HHOOK HOOK_SetHook( INT16 id, LPVOID proc, INT type,
632 HMODULE16 hModule, DWORD dwThreadId )
634 HOOKDATA *data;
635 HANDLE16 handle;
636 HQUEUE16 hQueue = 0;
638 if ((id < WH_MINHOOK) || (id > WH_MAXHOOK)) return 0;
640 TRACE("Setting hook %d: %08x %04x %08lx\n",
641 id, (UINT)proc, hModule, dwThreadId );
643 /* Create task queue if none present */
644 InitThreadInput16( 0, 0 );
646 if (id == WH_JOURNALPLAYBACK) EnableHardwareInput16(FALSE);
648 if (dwThreadId) /* Task-specific hook */
650 if ((id == WH_JOURNALRECORD) || (id == WH_JOURNALPLAYBACK) ||
651 (id == WH_SYSMSGFILTER)) return 0; /* System-only hooks */
652 if (!(hQueue = GetThreadQueue16( dwThreadId )))
653 return 0;
656 /* Create the hook structure */
658 if (!(handle = USER_HEAP_ALLOC( sizeof(HOOKDATA) ))) return 0;
659 data = (HOOKDATA *) USER_HEAP_LIN_ADDR( handle );
660 data->proc = proc;
661 data->id = id;
662 data->ownerQueue = hQueue;
663 data->ownerModule = hModule;
664 data->flags = type;
666 /* Insert it in the correct linked list */
668 if (hQueue)
670 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue );
671 data->next = queue->hooks[id - WH_MINHOOK];
672 queue->hooks[id - WH_MINHOOK] = handle;
673 QUEUE_Unlock( queue );
675 else
677 data->next = HOOK_systemHooks[id - WH_MINHOOK];
678 HOOK_systemHooks[id - WH_MINHOOK] = handle;
680 TRACE("Setting hook %d: ret=%04x [next=%04x]\n",
681 id, handle, data->next );
683 return HHOOK_32(handle);
687 /***********************************************************************
688 * HOOK_RemoveHook
690 * Remove a hook from the list.
692 static BOOL HOOK_RemoveHook( HHOOK hook )
694 HOOKDATA *data;
695 HANDLE16 *prevHandle;
697 TRACE("Removing hook %04x\n", hook );
699 if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(HHOOK_16(hook)))) return FALSE;
700 if (data->flags & HOOK_INUSE)
702 /* Mark it for deletion later on */
703 WARN("Hook still running, deletion delayed\n" );
704 data->proc = (HOOKPROC)0;
705 return TRUE;
708 if (data->id == WH_JOURNALPLAYBACK) EnableHardwareInput16(TRUE);
710 /* Remove it from the linked list */
712 if (data->ownerQueue)
714 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( data->ownerQueue );
715 if (!queue) return FALSE;
716 prevHandle = &queue->hooks[data->id - WH_MINHOOK];
717 QUEUE_Unlock( queue );
719 else prevHandle = &HOOK_systemHooks[data->id - WH_MINHOOK];
721 while (*prevHandle && *prevHandle != HHOOK_16(hook))
722 prevHandle = &((HOOKDATA *)USER_HEAP_LIN_ADDR(*prevHandle))->next;
724 if (!*prevHandle) return FALSE;
725 *prevHandle = data->next;
727 USER_HEAP_FREE(HHOOK_16(hook));
728 return TRUE;
732 /***********************************************************************
733 * HOOK_FindValidHook
735 static HHOOK HOOK_FindValidHook( HHOOK hook )
737 HOOKDATA *data;
739 for (;;)
741 if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(HHOOK_16(hook)))) return 0;
742 if (data->proc) return hook;
743 hook = HHOOK_32(data->next);
747 /***********************************************************************
748 * HOOK_CallHook
750 * Call a hook procedure.
752 static LRESULT HOOK_CallHook( HHOOK hook, INT fromtype, INT code,
753 WPARAM wParam, LPARAM lParam )
755 MESSAGEQUEUE *queue;
756 HANDLE16 prevHandle;
757 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(HHOOK_16(hook));
758 LRESULT ret;
760 if (!(queue = QUEUE_Current())) return 0;
761 prevHandle = queue->hCurHook;
762 queue->hCurHook = HHOOK_16(hook);
764 TRACE("Calling hook %04x: %d %08x %08lx\n", hook, code, wParam, lParam );
766 data->flags |= HOOK_INUSE;
767 ret = call_hook( data, fromtype, code, wParam, lParam );
768 data->flags &= ~HOOK_INUSE;
770 TRACE("Ret hook %04x = %08lx\n", hook, ret );
772 queue->hCurHook = prevHandle;
773 if (!data->proc) HOOK_RemoveHook( hook );
774 return ret;
777 /***********************************************************************
778 * Exported Functions & APIs
781 /***********************************************************************
782 * HOOK_IsHooked
784 * Replacement for calling HOOK_GetHook from other modules.
786 BOOL HOOK_IsHooked( INT16 id )
788 return HOOK_GetHook( id ) != 0;
792 /***********************************************************************
793 * HOOK_CallHooks16
795 * Call a hook chain.
797 LRESULT HOOK_CallHooks16( INT16 id, INT16 code, WPARAM16 wParam,
798 LPARAM lParam )
800 HHOOK hook;
802 if (!(hook = HOOK_GetHook( id ))) return 0;
803 if (!(hook = HOOK_FindValidHook(hook))) return 0;
804 return HOOK_CallHook( hook, HOOK_WIN16, code, wParam, lParam );
807 /***********************************************************************
808 * HOOK_CallHooksA
810 * Call a hook chain.
812 LRESULT HOOK_CallHooksA( INT id, INT code, WPARAM wParam,
813 LPARAM lParam )
815 HHOOK hook;
817 if (!(hook = HOOK_GetHook( id ))) return 0;
818 if (!(hook = HOOK_FindValidHook(hook))) return 0;
819 return HOOK_CallHook( hook, HOOK_WIN32A, code, wParam, lParam );
822 /***********************************************************************
823 * HOOK_CallHooksW
825 * Call a hook chain.
827 LRESULT HOOK_CallHooksW( INT id, INT code, WPARAM wParam,
828 LPARAM lParam )
830 HHOOK hook;
832 if (!(hook = HOOK_GetHook( id ))) return 0;
833 if (!(hook = HOOK_FindValidHook(hook))) return 0;
834 return HOOK_CallHook( hook, HOOK_WIN32W, code, wParam,
835 lParam );
839 /***********************************************************************
840 * HOOK_FreeModuleHooks
842 void HOOK_FreeModuleHooks( HMODULE16 hModule )
844 /* remove all system hooks registered by this module */
846 HOOKDATA* hptr;
847 HANDLE16 handle, next;
848 int id;
850 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
852 handle = HOOK_systemHooks[id - WH_MINHOOK];
853 while( handle )
854 if( (hptr = (HOOKDATA *)USER_HEAP_LIN_ADDR(handle)) )
856 next = hptr->next;
857 if( hptr->ownerModule == hModule )
859 hptr->flags &= HOOK_MAPTYPE;
860 HOOK_RemoveHook(HHOOK_32(handle));
862 handle = next;
864 else handle = 0;
868 /***********************************************************************
869 * HOOK_FreeQueueHooks
871 void HOOK_FreeQueueHooks(void)
873 /* remove all hooks registered by the current queue */
875 HOOKDATA* hptr = NULL;
876 HHOOK hook, next;
877 int id;
879 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
881 hook = HOOK_GetHook( id );
882 while( hook )
884 next = HOOK_GetNextHook(hook);
886 hptr = (HOOKDATA *)USER_HEAP_LIN_ADDR(HHOOK_16(hook));
887 if( hptr && hptr->ownerQueue )
889 hptr->flags &= HOOK_MAPTYPE;
890 HOOK_RemoveHook(hook);
892 hook = next;
898 /***********************************************************************
899 * SetWindowsHook (USER.121)
901 FARPROC16 WINAPI SetWindowsHook16( INT16 id, HOOKPROC16 proc )
903 HINSTANCE16 hInst = FarGetOwner16( HIWORD(proc) );
905 /* WH_MSGFILTER is the only task-specific hook for SetWindowsHook() */
906 HTASK16 hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
908 return (FARPROC16)SetWindowsHookEx16( id, proc, hInst, hTask );
911 /***********************************************************************
912 * SetWindowsHookA (USER32.@)
914 HHOOK WINAPI SetWindowsHookA( INT id, HOOKPROC proc )
916 return SetWindowsHookExA( id, proc, 0, GetCurrentThreadId() );
919 /***********************************************************************
920 * SetWindowsHookW (USER32.@)
922 HHOOK WINAPI SetWindowsHookW( INT id, HOOKPROC proc )
924 return SetWindowsHookExW( id, proc, 0, GetCurrentThreadId() );
928 /***********************************************************************
929 * SetWindowsHookEx (USER.291)
931 HHOOK WINAPI SetWindowsHookEx16( INT16 id, HOOKPROC16 proc, HINSTANCE16 hInst,
932 HTASK16 hTask )
934 if (id == WH_DEBUG)
936 FIXME("WH_DEBUG is broken in 16-bit Windows.\n");
937 return 0;
939 return HOOK_SetHook( id, proc, HOOK_WIN16, GetExePtr(hInst), (DWORD)hTask );
942 /***********************************************************************
943 * SetWindowsHookExA (USER32.@)
945 HHOOK WINAPI SetWindowsHookExA( INT id, HOOKPROC proc, HINSTANCE hInst,
946 DWORD dwThreadId )
948 return HOOK_SetHook( id, proc, HOOK_WIN32A, MapHModuleLS(hInst), dwThreadId );
951 /***********************************************************************
952 * SetWindowsHookExW (USER32.@)
954 HHOOK WINAPI SetWindowsHookExW( INT id, HOOKPROC proc, HINSTANCE hInst,
955 DWORD dwThreadId )
957 return HOOK_SetHook( id, proc, HOOK_WIN32W, MapHModuleLS(hInst), dwThreadId );
961 /***********************************************************************
962 * UnhookWindowsHook (USER.234)
964 BOOL16 WINAPI UnhookWindowsHook16( INT16 id, HOOKPROC16 proc )
966 return UnhookWindowsHook( id, (HOOKPROC)proc );
969 /***********************************************************************
970 * UnhookWindowsHook (USER32.@)
972 BOOL WINAPI UnhookWindowsHook( INT id, HOOKPROC proc )
974 HHOOK hook = HOOK_GetHook( id );
976 TRACE("%d %08lx\n", id, (DWORD)proc );
978 while (hook)
980 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(HHOOK_16(hook));
981 if (data->proc == proc) break;
982 hook = HOOK_GetNextHook( hook );
984 if (!hook) return FALSE;
985 return HOOK_RemoveHook( hook );
989 /***********************************************************************
990 * UnhookWindowsHookEx (USER.292)
992 BOOL16 WINAPI UnhookWindowsHookEx16( HHOOK hhook )
994 return HOOK_RemoveHook(hhook);
997 /***********************************************************************
998 * UnhookWindowsHookEx (USER32.@)
1000 BOOL WINAPI UnhookWindowsHookEx( HHOOK hhook )
1002 return HOOK_RemoveHook(hhook);
1006 /***********************************************************************
1007 * CallNextHookEx (USER.293)
1009 * I wouldn't have separated this into 16 and 32 bit versions, but I
1010 * need a way to figure out if I need to do a mapping or not.
1012 LRESULT WINAPI CallNextHookEx16( HHOOK hhook, INT16 code, WPARAM16 wParam,
1013 LPARAM lParam )
1015 HHOOK next;
1017 if (!(next = HOOK_GetNextHook(hhook))) return 0;
1019 return HOOK_CallHook( next, HOOK_WIN16, code, wParam, lParam );
1023 /***********************************************************************
1024 * CallNextHookEx (USER32.@)
1026 * There aren't ANSI and UNICODE versions of this.
1028 LRESULT WINAPI CallNextHookEx( HHOOK hhook, INT code, WPARAM wParam,
1029 LPARAM lParam )
1031 HHOOK next;
1032 INT fromtype; /* figure out Ansi/Unicode */
1033 HOOKDATA *oldhook;
1035 if (!(next = HOOK_GetNextHook(hhook))) return 0;
1037 oldhook = (HOOKDATA *)USER_HEAP_LIN_ADDR(HHOOK_16(hhook));
1038 fromtype = oldhook->flags & HOOK_MAPTYPE;
1040 if (fromtype == HOOK_WIN16)
1041 ERR("called from 16bit hook!\n");
1043 return HOOK_CallHook( next, fromtype, code, wParam, lParam );
1047 /***********************************************************************
1048 * DefHookProc (USER.235)
1050 LRESULT WINAPI DefHookProc16( INT16 code, WPARAM16 wParam, LPARAM lParam,
1051 HHOOK *hhook )
1053 /* Note: the *hhook parameter is never used, since we rely on the
1054 * current hook value from the task queue to find the next hook. */
1055 MESSAGEQUEUE *queue;
1057 if (!(queue = QUEUE_Current())) return 0;
1058 return CallNextHookEx16(HHOOK_32(queue->hCurHook), code, wParam, lParam);
1062 /***********************************************************************
1063 * CallMsgFilter (USER.123)
1065 BOOL16 WINAPI CallMsgFilter16( SEGPTR msg, INT16 code )
1067 if (GetSysModalWindow16()) return FALSE;
1068 if (HOOK_CallHooks16( WH_SYSMSGFILTER, code, 0, (LPARAM)msg )) return TRUE;
1069 return HOOK_CallHooks16( WH_MSGFILTER, code, 0, (LPARAM)msg );
1073 /***********************************************************************
1074 * CallMsgFilter32 (USER.823)
1076 BOOL16 WINAPI CallMsgFilter32_16( SEGPTR msg16_32, INT16 code, BOOL16 wHaveParamHigh )
1078 MSG32_16 *lpmsg16_32 = MapSL(msg16_32);
1080 if (wHaveParamHigh == FALSE)
1082 lpmsg16_32->wParamHigh = 0;
1083 /* WARNING: msg16_32->msg has to be the first variable in the struct */
1084 return CallMsgFilter16(msg16_32, code);
1086 else
1088 MSG msg32;
1089 BOOL16 ret;
1091 msg32.hwnd = WIN_Handle32( lpmsg16_32->msg.hwnd );
1092 msg32.message = lpmsg16_32->msg.message;
1093 msg32.wParam = MAKELONG(lpmsg16_32->msg.wParam, lpmsg16_32->wParamHigh);
1094 msg32.lParam = lpmsg16_32->msg.lParam;
1095 msg32.time = lpmsg16_32->msg.time;
1096 msg32.pt.x = lpmsg16_32->msg.pt.x;
1097 msg32.pt.y = lpmsg16_32->msg.pt.y;
1099 ret = (BOOL16)CallMsgFilterA(&msg32, (INT)code);
1101 lpmsg16_32->msg.hwnd = HWND_16( msg32.hwnd );
1102 lpmsg16_32->msg.message = msg32.message;
1103 lpmsg16_32->msg.wParam = LOWORD(msg32.wParam);
1104 lpmsg16_32->msg.lParam = msg32.lParam;
1105 lpmsg16_32->msg.time = msg32.time;
1106 lpmsg16_32->msg.pt.x = msg32.pt.x;
1107 lpmsg16_32->msg.pt.y = msg32.pt.y;
1108 lpmsg16_32->wParamHigh = HIWORD(msg32.wParam);
1110 return ret;
1115 /***********************************************************************
1116 * CallMsgFilterA (USER32.@)
1118 * FIXME: There are ANSI and UNICODE versions of this, plus an unspecified
1119 * version, plus USER (the 16bit one) has a CallMsgFilter32 function.
1121 BOOL WINAPI CallMsgFilterA( LPMSG msg, INT code )
1123 if (GetSysModalWindow16()) return FALSE; /* ??? */
1124 if (HOOK_CallHooksA( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
1125 return TRUE;
1126 return HOOK_CallHooksA( WH_MSGFILTER, code, 0, (LPARAM)msg );
1130 /***********************************************************************
1131 * CallMsgFilterW (USER32.@)
1133 BOOL WINAPI CallMsgFilterW( LPMSG msg, INT code )
1135 if (GetSysModalWindow16()) return FALSE; /* ??? */
1136 if (HOOK_CallHooksW( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
1137 return TRUE;
1138 return HOOK_CallHooksW( WH_MSGFILTER, code, 0, (LPARAM)msg );
1142 /***********************************************************************
1143 * SetWinEventHook [USER32.@]
1145 * Set up an event hook for a set of events.
1147 * PARAMS
1148 * dwMin [I] Lowest event handled by pfnProc
1149 * dwMax [I] Highest event handled by pfnProc
1150 * hModule [I] DLL containing pfnProc
1151 * pfnProc [I] Callback event hook function
1152 * dwProcess [I] Process to get events from, or 0 for all processes
1153 * dwThread [I] Thread to get events from, or 0 for all threads
1154 * dwFlags [I] Flags indicating the status of pfnProc
1156 * RETURNS
1157 * Success: A handle representing the hook.
1158 * Failure: A NULL handle.
1160 * BUGS
1161 * Not implemented.
1163 HWINEVENTHOOK WINAPI SetWinEventHook(DWORD dwMin, DWORD dwMax, HMODULE hModule,
1164 WINEVENTPROC pfnProc, DWORD dwProcess,
1165 DWORD dwThread, DWORD dwFlags)
1167 FIXME("(%ld,%ld,0x%08x,%p,%ld,%ld,0x%08lx)-stub!\n", dwMin, dwMax, hModule,
1168 pfnProc, dwProcess, dwThread, dwFlags);
1170 return (HWINEVENTHOOK)0;
1173 /***********************************************************************
1174 * UnhookWinEvent [USER32.@]
1176 * Remove an event hook for a set of events.
1178 * PARAMS
1179 * hEventHook [I] Event hook to remove
1181 * RETURNS
1182 * Success: TRUE. The event hook has been removed.
1183 * Failure: FALSE, if hEventHook is invalid.
1185 * BUGS
1186 * Not implemented.
1188 BOOL WINAPI UnhookWinEvent(HWINEVENTHOOK hEventHook)
1190 FIXME("(%p)-stub!\n", (void*)hEventHook);
1192 if (!hEventHook)
1193 return FALSE;
1195 return TRUE;
1198 /***********************************************************************
1199 * NotifyWinEvent [USER32.@]
1201 * Inform the OS that an event has occurred.
1203 * PARAMS
1204 * dwEvent [I] Id of the event
1205 * hWnd [I] Window holding the object that created the event
1206 * nId [I] Type of object that created the event
1207 * nChildId [I] Child object of nId, or CHILDID_SELF.
1209 * RETURNS
1210 * Nothing.
1212 * BUGS
1213 * Not implemented.
1215 VOID WINAPI NotifyWinEvent(DWORD dwEvent, HWND hWnd, LONG nId, LONG nChildId)
1217 FIXME("(%ld,0x%08x,%ld,%ld)-stub!\n", dwEvent, hWnd, nId, nChildId);
1220 /***********************************************************************
1221 * IsWinEventHookInstalled [USER32.@]
1223 * Determine if an event hook is installed for an event.
1225 * PARAMS
1226 * dwEvent [I] Id of the event
1228 * RETURNS
1229 * TRUE, If there are any hooks installed for the event.
1230 * FALSE, Otherwise.
1232 * BUGS
1233 * Not implemented.
1235 BOOL WINAPI IsWinEventHookInstalled(DWORD dwEvent)
1237 FIXME("(%ld)-stub!\n", dwEvent);
1238 return TRUE;