2 * Windows hook functions
4 * Copyright 1994, 1995 Alexandre Julliard
7 * Based on investigations by Alex Korobka
12 * A HHOOK is a 32-bit handle for compatibility with Windows 3.0 where it was
13 * a pointer to the next function. Now it is in fact composed of a USER heap
14 * handle in the low 16 bits and of a HOOK_MAGIC value in the high 16 bits.
21 #include "wine/winuser16.h"
22 #include "wine/winbase16.h"
30 #include "debugtools.h"
32 DEFAULT_DEBUG_CHANNEL(hook);
36 /* Hook data (pointed to by a HHOOK) */
39 HANDLE16 next; /* 00 Next hook in chain */
40 HOOKPROC proc; /* 02 Hook procedure (original) */
41 INT16 id; /* 06 Hook id (WH_xxx) */
42 HQUEUE16 ownerQueue; /* 08 Owner queue (0 for system hook) */
43 HMODULE16 ownerModule; /* 0a Owner module */
44 WORD flags; /* 0c flags */
49 #define HOOK_MAGIC ((int)'H' | (int)'K' << 8) /* 'HK' */
51 /* This should probably reside in USER heap */
52 static HANDLE16 HOOK_systemHooks[WH_NB_HOOKS] = { 0, };
54 /* ### start build ### */
55 extern LONG CALLBACK HOOK_CallTo16_long_wwl(HOOKPROC16,WORD,WORD,LONG);
56 /* ### stop build ### */
59 /***********************************************************************
62 inline static LRESULT call_hook_16( HOOKPROC16 proc, INT id, INT code, WPARAM wparam, LPARAM lparam )
64 LRESULT ret = HOOK_CallTo16_long_wwl( proc, code, wparam, lparam );
65 /* Grrr. While the hook procedure is supposed to have an LRESULT return
66 value even in Win16, it seems that for those hook types where the
67 return value is interpreted as BOOL, Windows doesn't actually check
68 the HIWORD ... Some buggy Win16 programs, notably WINFILE, rely on
69 that, because they neglect to clear DX ... */
70 if (id != WH_JOURNALPLAYBACK) ret = LOWORD( ret );
75 /***********************************************************************
78 * Convert hook params to 32-bit and call 32-bit hook procedure
80 static LRESULT call_hook_16_to_32( HOOKPROC proc, INT id, INT code, WPARAM wparam, LPARAM lparam,
89 case WH_JOURNALRECORD:
91 MSG16 *msg16 = MapSL(lparam);
94 STRUCT32_MSG16to32( msg16, &msg32 );
95 ret = proc( code, wparam, (LPARAM)&msg32 );
101 MSG16 *msg16 = MapSL(lparam);
104 STRUCT32_MSG16to32( msg16, &msg32 );
105 ret = proc( code, wparam, (LPARAM)&msg32 );
106 STRUCT32_MSG32to16( &msg32, msg16 );
110 case WH_JOURNALPLAYBACK:
112 EVENTMSG16 *em16 = MapSL(lparam);
115 em32.message = em16->message;
116 em32.paramL = em16->paramL;
117 em32.paramH = em16->paramH;
118 em32.time = em16->time;
119 em32.hwnd = 0; /* FIXME */
120 ret = proc( code, wparam, (LPARAM)&em32 );
126 CWPSTRUCT16 *cwp16 = MapSL(lparam);
129 cwp32.hwnd = WIN_Handle32(cwp16->hwnd);
130 cwp32.lParam = cwp16->lParam;
133 WINPROC_MapMsg16To32W( cwp32.hwnd, cwp16->message, cwp16->wParam,
134 &cwp32.message, &cwp32.wParam, &cwp32.lParam );
136 WINPROC_MapMsg16To32A( cwp32.hwnd, cwp16->message, cwp16->wParam,
137 &cwp32.message, &cwp32.wParam, &cwp32.lParam );
139 ret = proc( code, wparam, (LPARAM)&cwp32 );
142 WINPROC_UnmapMsg16To32W( cwp32.hwnd, cwp32.message, cwp32.wParam, cwp32.lParam, 0 );
144 WINPROC_UnmapMsg16To32A( cwp32.hwnd, cwp32.message, cwp32.wParam, cwp32.lParam, 0 );
153 CBT_CREATEWNDA cbtcw32;
155 CBT_CREATEWND16 *cbtcw16 = MapSL(lparam);
156 CREATESTRUCT16 *cs16 = MapSL( (SEGPTR)cbtcw16->lpcs );
158 cbtcw32.lpcs = &cs32;
159 cbtcw32.hwndInsertAfter = WIN_Handle32( cbtcw16->hwndInsertAfter );
160 STRUCT32_CREATESTRUCT16to32A( cs16, &cs32 );
164 cs32.lpszName = (LPSTR)map_str_16_to_32W( cs16->lpszName );
165 cs32.lpszClass = (LPSTR)map_str_16_to_32W( cs16->lpszClass );
166 ret = proc( code, wparam, (LPARAM)&cbtcw32 );
167 unmap_str_16_to_32W( (LPWSTR)cs32.lpszName );
168 unmap_str_16_to_32W( (LPWSTR)cs32.lpszClass );
172 cs32.lpszName = MapSL( cs16->lpszName );
173 cs32.lpszClass = MapSL( cs16->lpszClass );
174 ret = proc( code, wparam, (LPARAM)&cbtcw32 );
176 cbtcw16->hwndInsertAfter = WIN_Handle16( cbtcw32.hwndInsertAfter );
181 CBTACTIVATESTRUCT16 *cas16 = MapSL(lparam);
182 CBTACTIVATESTRUCT cas32;
183 cas32.fMouse = cas16->fMouse;
184 cas32.hWndActive = WIN_Handle32(cas16->hWndActive);
185 ret = proc( code, wparam, (LPARAM)&cas32 );
188 case HCBT_CLICKSKIPPED:
190 MOUSEHOOKSTRUCT16 *ms16 = MapSL(lparam);
191 MOUSEHOOKSTRUCT ms32;
193 ms32.pt.x = ms16->pt.x;
194 ms32.pt.y = ms16->pt.y;
195 /* wHitTestCode may be negative, so convince compiler to do
196 correct sign extension. Yay. :| */
197 ms32.wHitTestCode = (INT)(INT16)ms16->wHitTestCode;
198 ms32.dwExtraInfo = ms16->dwExtraInfo;
199 ms32.hwnd = WIN_Handle32( ms16->hwnd );
200 ret = proc( code, wparam, (LPARAM)&ms32 );
205 RECT16 *rect16 = MapSL(lparam);
208 CONV_RECT16TO32( rect16, &rect32 );
209 ret = proc( code, wparam, (LPARAM)&rect32 );
217 MOUSEHOOKSTRUCT16 *ms16 = MapSL(lparam);
218 MOUSEHOOKSTRUCT ms32;
220 ms32.pt.x = ms16->pt.x;
221 ms32.pt.y = ms16->pt.y;
222 /* wHitTestCode may be negative, so convince compiler to do
223 correct sign extension. Yay. :| */
224 ms32.wHitTestCode = (INT)((INT16)ms16->wHitTestCode);
225 ms32.dwExtraInfo = ms16->dwExtraInfo;
226 ms32.hwnd = WIN_Handle32(ms16->hwnd);
227 ret = proc( code, wparam, (LPARAM)&ms32 );
233 DEBUGHOOKINFO16 *dh16 = MapSL(lparam);
236 dh32.idThread = 0; /* FIXME */
237 dh32.idThreadInstaller = 0; /* FIXME */
238 dh32.lParam = dh16->lParam; /* FIXME Check for sign ext */
239 dh32.wParam = dh16->wParam;
240 dh32.code = dh16->code;
242 /* do sign extension if it was WH_MSGFILTER */
243 if (wparam == 0xffff) wparam = WH_MSGFILTER;
244 ret = proc( code, wparam, (LPARAM)&dh32 );
250 ret = proc( code, wparam, lparam );
254 case WH_FOREGROUNDIDLE:
255 case WH_CALLWNDPROCRET:
257 FIXME("\t[%i] 16to32 translation unimplemented\n", id);
258 ret = proc( code, wparam, lparam );
265 /***********************************************************************
268 * Convert hook params to 16-bit and call 16-bit hook procedure
270 static LRESULT call_hook_32_to_16( HOOKPROC16 proc, INT id, INT code, WPARAM wparam, LPARAM lparam,
278 case WH_SYSMSGFILTER:
279 case WH_JOURNALRECORD:
281 MSG *msg32 = (MSG *)lparam;
284 STRUCT32_MSG32to16( msg32, &msg16 );
285 lparam = MapLS( &msg16 );
286 ret = call_hook_16( proc, id, code, wparam, lparam );
293 MSG *msg32 = (MSG *)lparam;
296 STRUCT32_MSG32to16( msg32, &msg16 );
297 lparam = MapLS( &msg16 );
298 ret = call_hook_16( proc, id, code, wparam, lparam );
300 STRUCT32_MSG16to32( &msg16, msg32 );
304 case WH_JOURNALPLAYBACK:
306 EVENTMSG *em32 = (EVENTMSG *)lparam;
309 em16.message = em32->message;
310 em16.paramL = em32->paramL;
311 em16.paramH = em32->paramH;
312 em16.time = em32->time;
313 lparam = MapLS( &em16 );
314 ret = call_hook_16( proc, id, code, wparam, lparam );
321 CWPSTRUCT *cwp32 = (CWPSTRUCT *)lparam;
325 cwp16.hwnd = WIN_Handle16(cwp32->hwnd);
326 cwp16.lParam = cwp32->lParam;
329 WINPROC_MapMsg32WTo16( cwp32->hwnd, cwp32->message, cwp32->wParam,
330 &cwp16.message, &cwp16.wParam, &cwp16.lParam );
332 WINPROC_MapMsg32ATo16( cwp32->hwnd, cwp32->message, cwp32->wParam,
333 &cwp16.message, &cwp16.wParam, &cwp16.lParam );
335 lparam = MapLS( &cwp16 );
336 ret = call_hook_16( proc, id, code, wparam, lparam );
339 mp16.wParam = cwp16.wParam;
340 mp16.lParam = cwp16.lParam;
343 WINPROC_UnmapMsg32WTo16( cwp32->hwnd, cwp32->message, cwp32->wParam,
344 cwp32->lParam, &mp16 );
346 WINPROC_UnmapMsg32ATo16( cwp32->hwnd, cwp32->message, cwp32->wParam,
347 cwp32->lParam, &mp16 );
356 CBT_CREATEWNDA *cbtcw32 = (CBT_CREATEWNDA *)lparam;
357 CBT_CREATEWND16 cbtcw16;
360 STRUCT32_CREATESTRUCT32Ato16( cbtcw32->lpcs, &cs16 );
361 cbtcw16.lpcs = (CREATESTRUCT16 *)MapLS( &cs16 );
362 cbtcw16.hwndInsertAfter = WIN_Handle16( cbtcw32->hwndInsertAfter );
363 lparam = MapLS( &cbtcw16 );
367 cs16.lpszName = map_str_32W_to_16( (LPWSTR)cbtcw32->lpcs->lpszName );
368 cs16.lpszClass = map_str_32W_to_16( (LPWSTR)cbtcw32->lpcs->lpszClass );
369 ret = call_hook_16( proc, id, code, wparam, lparam );
370 unmap_str_32W_to_16( cs16.lpszName );
371 unmap_str_32W_to_16( cs16.lpszClass );
375 cs16.lpszName = MapLS( cbtcw32->lpcs->lpszName );
376 cs16.lpszClass = MapLS( cbtcw32->lpcs->lpszClass );
377 ret = call_hook_16( proc, id, code, wparam, lparam );
378 UnMapLS( cs16.lpszName );
379 UnMapLS( cs16.lpszClass );
381 cbtcw32->hwndInsertAfter = WIN_Handle32( cbtcw16.hwndInsertAfter );
382 UnMapLS( (SEGPTR)cbtcw16.lpcs );
389 CBTACTIVATESTRUCT *cas32 = (CBTACTIVATESTRUCT *)lparam;
390 CBTACTIVATESTRUCT16 cas16;
392 cas16.fMouse = cas32->fMouse;
393 cas16.hWndActive = WIN_Handle16( cas32->hWndActive );
395 lparam = MapLS( &cas16 );
396 ret = call_hook_16( proc, id, code, wparam, lparam );
400 case HCBT_CLICKSKIPPED:
402 MOUSEHOOKSTRUCT *ms32 = (MOUSEHOOKSTRUCT *)lparam;
403 MOUSEHOOKSTRUCT16 ms16;
405 ms16.pt.x = ms32->pt.x;
406 ms16.pt.y = ms32->pt.y;
407 ms16.hwnd = WIN_Handle16( ms32->hwnd );
408 ms16.wHitTestCode = ms32->wHitTestCode;
409 ms16.dwExtraInfo = ms32->dwExtraInfo;
411 lparam = MapLS( &ms16 );
412 ret = call_hook_16( proc, id, code, wparam, lparam );
418 RECT *rect32 = (RECT *)lparam;
421 CONV_RECT32TO16( rect32, &rect16 );
422 lparam = MapLS( &rect16 );
423 ret = call_hook_16( proc, id, code, wparam, lparam );
432 MOUSEHOOKSTRUCT *ms32 = (MOUSEHOOKSTRUCT *)lparam;
433 MOUSEHOOKSTRUCT16 ms16;
435 ms16.pt.x = ms32->pt.x;
436 ms16.pt.y = ms32->pt.y;
437 ms16.hwnd = WIN_Handle16( ms32->hwnd );
438 ms16.wHitTestCode = ms32->wHitTestCode;
439 ms16.dwExtraInfo = ms32->dwExtraInfo;
441 lparam = MapLS( &ms16 );
442 ret = call_hook_16( proc, id, code, wparam, lparam );
449 DEBUGHOOKINFO *dh32 = (DEBUGHOOKINFO *)lparam;
450 DEBUGHOOKINFO16 dh16;
452 dh16.hModuleHook = 0; /* FIXME */
454 dh16.lParam = dh32->lParam;
455 dh16.wParam = dh32->wParam;
456 dh16.code = dh32->code;
458 lparam = MapLS( &dh16 );
459 ret = call_hook_16( proc, id, code, wparam, lparam );
466 ret = call_hook_16( proc, id, code, wparam, lparam );
470 case WH_FOREGROUNDIDLE:
471 case WH_CALLWNDPROCRET:
473 FIXME("\t[%i] 32to16 translation unimplemented\n", id);
474 ret = call_hook_16( proc, id, code, wparam, lparam );
481 /***********************************************************************
484 * Convert hook params to/from Unicode and call hook procedure
486 static LRESULT call_hook_32_to_32( HOOKPROC proc, INT id, INT code, WPARAM wparam, LPARAM lparam,
489 if (id != WH_CBT || code != HCBT_CREATEWND) return proc( code, wparam, lparam );
491 if (to_unicode) /* ASCII to Unicode */
493 CBT_CREATEWNDA *cbtcwA = (CBT_CREATEWNDA *)lparam;
494 CBT_CREATEWNDW cbtcwW;
499 cbtcwW.hwndInsertAfter = cbtcwA->hwndInsertAfter;
500 csW = *(CREATESTRUCTW *)cbtcwA->lpcs;
502 if (HIWORD(cbtcwA->lpcs->lpszName))
503 csW.lpszName = HEAP_strdupAtoW( GetProcessHeap(), 0, cbtcwA->lpcs->lpszName );
504 if (HIWORD(cbtcwA->lpcs->lpszClass))
505 csW.lpszClass = HEAP_strdupAtoW( GetProcessHeap(), 0, cbtcwA->lpcs->lpszClass );
506 ret = proc( code, wparam, (LPARAM)&cbtcwW );
507 cbtcwA->hwndInsertAfter = cbtcwW.hwndInsertAfter;
508 if (HIWORD(csW.lpszName)) HeapFree( GetProcessHeap(), 0, (LPWSTR)csW.lpszName );
509 if (HIWORD(csW.lpszClass)) HeapFree( GetProcessHeap(), 0, (LPWSTR)csW.lpszClass );
512 else /* Unicode to ASCII */
514 CBT_CREATEWNDW *cbtcwW = (CBT_CREATEWNDW *)lparam;
515 CBT_CREATEWNDA cbtcwA;
520 cbtcwA.hwndInsertAfter = cbtcwW->hwndInsertAfter;
521 csA = *(CREATESTRUCTA *)cbtcwW->lpcs;
523 if (HIWORD(cbtcwW->lpcs->lpszName))
524 csA.lpszName = HEAP_strdupWtoA( GetProcessHeap(), 0, cbtcwW->lpcs->lpszName );
525 if (HIWORD(cbtcwW->lpcs->lpszClass))
526 csA.lpszClass = HEAP_strdupWtoA( GetProcessHeap(), 0, cbtcwW->lpcs->lpszClass );
527 ret = proc( code, wparam, (LPARAM)&cbtcwA );
528 cbtcwW->hwndInsertAfter = cbtcwA.hwndInsertAfter;
529 if (HIWORD(csA.lpszName)) HeapFree( GetProcessHeap(), 0, (LPSTR)csA.lpszName );
530 if (HIWORD(csA.lpszClass)) HeapFree( GetProcessHeap(), 0, (LPSTR)csA.lpszClass );
536 /***********************************************************************
539 * Call a hook procedure.
541 inline static LRESULT call_hook( HOOKDATA *data, INT fromtype, INT code,
542 WPARAM wparam, LPARAM lparam )
544 INT type = (data->flags & HOOK_MAPTYPE);
547 /* Suspend window structure locks before calling user code */
548 int iWndsLocks = WIN_SuspendWndsLock();
550 if (type == HOOK_WIN16)
552 if (fromtype == HOOK_WIN16) /* 16->16 */
553 ret = call_hook_16( (HOOKPROC16)data->proc, data->id, code, wparam, lparam );
555 ret = call_hook_32_to_16( (HOOKPROC16)data->proc, data->id, code, wparam,
556 lparam, (type == HOOK_WIN32W) );
558 else if (fromtype == HOOK_WIN16) /* 16->32 */
559 ret = call_hook_16_to_32( data->proc, data->id, code, wparam,
560 lparam, (type == HOOK_WIN32W) );
561 else /* 32->32, check unicode */
563 if (type == fromtype)
564 ret = data->proc( code, wparam, lparam );
566 ret = call_hook_32_to_32( data->proc, data->id, code, wparam,
567 lparam, (type == HOOK_WIN32W) );
569 WIN_RestoreWndsLock(iWndsLocks);
574 /***********************************************************************
577 * Get the next hook of a given hook.
579 static HANDLE16 HOOK_GetNextHook( HANDLE16 hook )
581 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR( hook );
583 if (!data || !hook) return 0;
584 if (data->next) return data->next;
585 if (!data->ownerQueue) return 0; /* Already system hook */
587 /* Now start enumerating the system hooks */
588 return HOOK_systemHooks[data->id - WH_MINHOOK];
592 /***********************************************************************
595 * Get the first hook for a given type.
597 static HANDLE16 HOOK_GetHook( INT16 id )
602 if ((queue = QUEUE_Current()) != NULL)
603 hook = queue->hooks[id - WH_MINHOOK];
604 if (!hook) hook = HOOK_systemHooks[id - WH_MINHOOK];
609 /***********************************************************************
612 * Install a given hook.
614 static HHOOK HOOK_SetHook( INT16 id, LPVOID proc, INT type,
615 HMODULE16 hModule, DWORD dwThreadId )
621 if ((id < WH_MINHOOK) || (id > WH_MAXHOOK)) return 0;
623 TRACE("Setting hook %d: %08x %04x %08lx\n",
624 id, (UINT)proc, hModule, dwThreadId );
626 /* Create task queue if none present */
627 InitThreadInput16( 0, 0 );
629 if (id == WH_JOURNALPLAYBACK) EnableHardwareInput16(FALSE);
631 if (dwThreadId) /* Task-specific hook */
633 if ((id == WH_JOURNALRECORD) || (id == WH_JOURNALPLAYBACK) ||
634 (id == WH_SYSMSGFILTER)) return 0; /* System-only hooks */
635 if (!(hQueue = GetThreadQueue16( dwThreadId )))
639 /* Create the hook structure */
641 if (!(handle = USER_HEAP_ALLOC( sizeof(HOOKDATA) ))) return 0;
642 data = (HOOKDATA *) USER_HEAP_LIN_ADDR( handle );
645 data->ownerQueue = hQueue;
646 data->ownerModule = hModule;
649 /* Insert it in the correct linked list */
653 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue );
654 data->next = queue->hooks[id - WH_MINHOOK];
655 queue->hooks[id - WH_MINHOOK] = handle;
656 QUEUE_Unlock( queue );
660 data->next = HOOK_systemHooks[id - WH_MINHOOK];
661 HOOK_systemHooks[id - WH_MINHOOK] = handle;
663 TRACE("Setting hook %d: ret=%04x [next=%04x]\n",
664 id, handle, data->next );
666 return (HHOOK)( handle? MAKELONG( handle, HOOK_MAGIC ) : 0 );
670 /***********************************************************************
673 * Remove a hook from the list.
675 static BOOL HOOK_RemoveHook( HANDLE16 hook )
680 TRACE("Removing hook %04x\n", hook );
682 if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook))) return FALSE;
683 if (data->flags & HOOK_INUSE)
685 /* Mark it for deletion later on */
686 WARN("Hook still running, deletion delayed\n" );
687 data->proc = (HOOKPROC)0;
691 if (data->id == WH_JOURNALPLAYBACK) EnableHardwareInput16(TRUE);
693 /* Remove it from the linked list */
695 if (data->ownerQueue)
697 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( data->ownerQueue );
698 if (!queue) return FALSE;
699 prevHook = &queue->hooks[data->id - WH_MINHOOK];
700 QUEUE_Unlock( queue );
702 else prevHook = &HOOK_systemHooks[data->id - WH_MINHOOK];
704 while (*prevHook && *prevHook != hook)
705 prevHook = &((HOOKDATA *)USER_HEAP_LIN_ADDR(*prevHook))->next;
707 if (!*prevHook) return FALSE;
708 *prevHook = data->next;
710 USER_HEAP_FREE( hook );
715 /***********************************************************************
718 static HANDLE16 HOOK_FindValidHook( HANDLE16 hook )
724 if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook))) return 0;
725 if (data->proc) return hook;
730 /***********************************************************************
733 * Call a hook procedure.
735 static LRESULT HOOK_CallHook( HANDLE16 hook, INT fromtype, INT code,
736 WPARAM wParam, LPARAM lParam )
740 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
743 if (!(queue = QUEUE_Current())) return 0;
744 prevHook = queue->hCurHook;
745 queue->hCurHook = hook;
747 TRACE("Calling hook %04x: %d %08x %08lx\n", hook, code, wParam, lParam );
749 data->flags |= HOOK_INUSE;
750 ret = call_hook( data, fromtype, code, wParam, lParam );
751 data->flags &= ~HOOK_INUSE;
753 TRACE("Ret hook %04x = %08lx\n", hook, ret );
755 queue->hCurHook = prevHook;
756 if (!data->proc) HOOK_RemoveHook( hook );
760 /***********************************************************************
761 * Exported Functions & APIs
764 /***********************************************************************
767 * Replacement for calling HOOK_GetHook from other modules.
769 BOOL HOOK_IsHooked( INT16 id )
771 return HOOK_GetHook( id ) != 0;
775 /***********************************************************************
780 LRESULT HOOK_CallHooks16( INT16 id, INT16 code, WPARAM16 wParam,
785 if (!(hook = HOOK_GetHook( id ))) return 0;
786 if (!(hook = HOOK_FindValidHook(hook))) return 0;
787 return HOOK_CallHook( hook, HOOK_WIN16, code, wParam, lParam );
790 /***********************************************************************
795 LRESULT HOOK_CallHooksA( INT id, INT code, WPARAM wParam,
800 if (!(hook = HOOK_GetHook( id ))) return 0;
801 if (!(hook = HOOK_FindValidHook(hook))) return 0;
802 return HOOK_CallHook( hook, HOOK_WIN32A, code, wParam, lParam );
805 /***********************************************************************
810 LRESULT HOOK_CallHooksW( INT id, INT code, WPARAM wParam,
815 if (!(hook = HOOK_GetHook( id ))) return 0;
816 if (!(hook = HOOK_FindValidHook(hook))) return 0;
817 return HOOK_CallHook( hook, HOOK_WIN32W, code, wParam,
822 /***********************************************************************
823 * HOOK_FreeModuleHooks
825 void HOOK_FreeModuleHooks( HMODULE16 hModule )
827 /* remove all system hooks registered by this module */
833 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
835 hook = HOOK_systemHooks[id - WH_MINHOOK];
837 if( (hptr = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook)) )
840 if( hptr->ownerModule == hModule )
842 hptr->flags &= HOOK_MAPTYPE;
843 HOOK_RemoveHook(hook);
851 /***********************************************************************
852 * HOOK_FreeQueueHooks
854 void HOOK_FreeQueueHooks(void)
856 /* remove all hooks registered by the current queue */
858 HOOKDATA* hptr = NULL;
862 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
864 hook = HOOK_GetHook( id );
867 next = HOOK_GetNextHook(hook);
869 hptr = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
870 if( hptr && hptr->ownerQueue )
872 hptr->flags &= HOOK_MAPTYPE;
873 HOOK_RemoveHook(hook);
881 /***********************************************************************
882 * SetWindowsHook (USER.121)
884 FARPROC16 WINAPI SetWindowsHook16( INT16 id, HOOKPROC16 proc )
886 HINSTANCE16 hInst = FarGetOwner16( HIWORD(proc) );
888 /* WH_MSGFILTER is the only task-specific hook for SetWindowsHook() */
889 HTASK16 hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
891 return (FARPROC16)SetWindowsHookEx16( id, proc, hInst, hTask );
894 /***********************************************************************
895 * SetWindowsHookA (USER32.@)
897 HHOOK WINAPI SetWindowsHookA( INT id, HOOKPROC proc )
899 return SetWindowsHookExA( id, proc, 0, GetCurrentThreadId() );
902 /***********************************************************************
903 * SetWindowsHookW (USER32.@)
905 HHOOK WINAPI SetWindowsHookW( INT id, HOOKPROC proc )
907 return SetWindowsHookExW( id, proc, 0, GetCurrentThreadId() );
911 /***********************************************************************
912 * SetWindowsHookEx (USER.291)
913 * SetWindowsHookEx16 (USER32.@)
915 HHOOK WINAPI SetWindowsHookEx16( INT16 id, HOOKPROC16 proc, HINSTANCE16 hInst,
920 FIXME("WH_DEBUG is broken in 16-bit Windows.\n");
923 return HOOK_SetHook( id, proc, HOOK_WIN16, GetExePtr(hInst), (DWORD)hTask );
926 /***********************************************************************
927 * SetWindowsHookExA (USER32.@)
929 HHOOK WINAPI SetWindowsHookExA( INT id, HOOKPROC proc, HINSTANCE hInst,
932 return HOOK_SetHook( id, proc, HOOK_WIN32A, MapHModuleLS(hInst), dwThreadId );
935 /***********************************************************************
936 * SetWindowsHookExW (USER32.@)
938 HHOOK WINAPI SetWindowsHookExW( INT id, HOOKPROC proc, HINSTANCE hInst,
941 return HOOK_SetHook( id, proc, HOOK_WIN32W, MapHModuleLS(hInst), dwThreadId );
945 /***********************************************************************
946 * UnhookWindowsHook (USER.234)
948 BOOL16 WINAPI UnhookWindowsHook16( INT16 id, HOOKPROC16 proc )
950 return UnhookWindowsHook( id, (HOOKPROC)proc );
953 /***********************************************************************
954 * UnhookWindowsHook (USER32.@)
956 BOOL WINAPI UnhookWindowsHook( INT id, HOOKPROC proc )
958 HANDLE16 hook = HOOK_GetHook( id );
960 TRACE("%d %08lx\n", id, (DWORD)proc );
964 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
965 if (data->proc == proc) break;
966 hook = HOOK_GetNextHook( hook );
968 if (!hook) return FALSE;
969 return HOOK_RemoveHook( hook );
973 /***********************************************************************
974 * UnhookWindowsHookEx (USER.292)
976 BOOL16 WINAPI UnhookWindowsHookEx16( HHOOK hhook )
978 return UnhookWindowsHookEx( hhook );
981 /***********************************************************************
982 * UnhookWindowsHookEx (USER32.@)
984 BOOL WINAPI UnhookWindowsHookEx( HHOOK hhook )
986 if (HIWORD(hhook) != HOOK_MAGIC) return FALSE; /* Not a new format hook */
987 return HOOK_RemoveHook( LOWORD(hhook) );
991 /***********************************************************************
992 * CallNextHookEx (USER.293)
993 * CallNextHookEx16 (USER32.@)
995 * I wouldn't have separated this into 16 and 32 bit versions, but I
996 * need a way to figure out if I need to do a mapping or not.
998 LRESULT WINAPI CallNextHookEx16( HHOOK hhook, INT16 code, WPARAM16 wParam,
1003 if (HIWORD(hhook) != HOOK_MAGIC) return 0; /* Not a new format hook */
1004 if (!(next = HOOK_GetNextHook( LOWORD(hhook) ))) return 0;
1006 return HOOK_CallHook( next, HOOK_WIN16, code, wParam, lParam );
1010 /***********************************************************************
1011 * CallNextHookEx (USER32.@)
1013 * There aren't ANSI and UNICODE versions of this.
1015 LRESULT WINAPI CallNextHookEx( HHOOK hhook, INT code, WPARAM wParam,
1019 INT fromtype; /* figure out Ansi/Unicode */
1022 if (HIWORD(hhook) != HOOK_MAGIC) return 0; /* Not a new format hook */
1023 if (!(next = HOOK_GetNextHook( LOWORD(hhook) ))) return 0;
1025 oldhook = (HOOKDATA *)USER_HEAP_LIN_ADDR( LOWORD(hhook) );
1026 fromtype = oldhook->flags & HOOK_MAPTYPE;
1028 if (fromtype == HOOK_WIN16)
1029 ERR("called from 16bit hook!\n");
1031 return HOOK_CallHook( next, fromtype, code, wParam, lParam );
1035 /***********************************************************************
1036 * DefHookProc (USER.235)
1038 LRESULT WINAPI DefHookProc16( INT16 code, WPARAM16 wParam, LPARAM lParam,
1041 /* Note: the *hhook parameter is never used, since we rely on the
1042 * current hook value from the task queue to find the next hook. */
1043 MESSAGEQUEUE *queue;
1045 if (!(queue = QUEUE_Current())) return 0;
1046 return CallNextHookEx16( queue->hCurHook, code, wParam, lParam );
1050 /***********************************************************************
1051 * CallMsgFilter (USER.123)
1053 BOOL16 WINAPI CallMsgFilter16( SEGPTR msg, INT16 code )
1055 if (GetSysModalWindow16()) return FALSE;
1056 if (HOOK_CallHooks16( WH_SYSMSGFILTER, code, 0, (LPARAM)msg )) return TRUE;
1057 return HOOK_CallHooks16( WH_MSGFILTER, code, 0, (LPARAM)msg );
1061 /***********************************************************************
1062 * CallMsgFilter32 (USER.823)
1064 BOOL16 WINAPI CallMsgFilter32_16( SEGPTR msg16_32, INT16 code, BOOL16 wHaveParamHigh )
1066 MSG32_16 *lpmsg16_32 = MapSL(msg16_32);
1068 if (wHaveParamHigh == FALSE)
1070 lpmsg16_32->wParamHigh = 0;
1071 /* WARNING: msg16_32->msg has to be the first variable in the struct */
1072 return CallMsgFilter16(msg16_32, code);
1079 msg32.hwnd = WIN_Handle32( lpmsg16_32->msg.hwnd );
1080 msg32.message = lpmsg16_32->msg.message;
1081 msg32.wParam = MAKELONG(lpmsg16_32->msg.wParam, lpmsg16_32->wParamHigh);
1082 msg32.lParam = lpmsg16_32->msg.lParam;
1083 msg32.time = lpmsg16_32->msg.time;
1084 msg32.pt.x = lpmsg16_32->msg.pt.x;
1085 msg32.pt.y = lpmsg16_32->msg.pt.y;
1087 ret = (BOOL16)CallMsgFilterA(&msg32, (INT)code);
1089 lpmsg16_32->msg.hwnd = WIN_Handle16( msg32.hwnd );
1090 lpmsg16_32->msg.message = msg32.message;
1091 lpmsg16_32->msg.wParam = LOWORD(msg32.wParam);
1092 lpmsg16_32->msg.lParam = msg32.lParam;
1093 lpmsg16_32->msg.time = msg32.time;
1094 lpmsg16_32->msg.pt.x = msg32.pt.x;
1095 lpmsg16_32->msg.pt.y = msg32.pt.y;
1096 lpmsg16_32->wParamHigh = HIWORD(msg32.wParam);
1103 /***********************************************************************
1104 * CallMsgFilterA (USER32.@)
1106 * FIXME: There are ANSI and UNICODE versions of this, plus an unspecified
1107 * version, plus USER (the 16bit one) has a CallMsgFilter32 function.
1109 BOOL WINAPI CallMsgFilterA( LPMSG msg, INT code )
1111 if (GetSysModalWindow16()) return FALSE; /* ??? */
1112 if (HOOK_CallHooksA( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
1114 return HOOK_CallHooksA( WH_MSGFILTER, code, 0, (LPARAM)msg );
1118 /***********************************************************************
1119 * CallMsgFilterW (USER32.@)
1121 BOOL WINAPI CallMsgFilterW( LPMSG msg, INT code )
1123 if (GetSysModalWindow16()) return FALSE; /* ??? */
1124 if (HOOK_CallHooksW( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
1126 return HOOK_CallHooksW( WH_MSGFILTER, code, 0, (LPARAM)msg );