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"
31 #include "debugtools.h"
33 DEFAULT_DEBUG_CHANNEL(hook);
37 /* Hook data (pointed to by a HHOOK) */
40 HANDLE16 next; /* 00 Next hook in chain */
41 HOOKPROC proc; /* 02 Hook procedure (original) */
42 INT16 id; /* 06 Hook id (WH_xxx) */
43 HQUEUE16 ownerQueue; /* 08 Owner queue (0 for system hook) */
44 HMODULE16 ownerModule; /* 0a Owner module */
45 WORD flags; /* 0c flags */
46 HOOKPROC thunk; /* 0e Hook procedure (CallTo16 thunk) */
51 #define HOOK_MAGIC ((int)'H' | (int)'K' << 8) /* 'HK' */
53 /* This should probably reside in USER heap */
54 static HANDLE16 HOOK_systemHooks[WH_NB_HOOKS] = { 0, };
56 typedef VOID (*HOOK_MapFunc)(INT, INT, WPARAM *, LPARAM *);
57 typedef VOID (*HOOK_UnMapFunc)(INT, INT, WPARAM, LPARAM, WPARAM,
60 /***********************************************************************
61 * HOOK_Map16To32Common
63 static void HOOK_Map16To32Common(INT id, INT code, WPARAM *pwParam,
64 LPARAM *plParam, BOOL bA )
72 case WH_JOURNALRECORD:
74 LPMSG16 lpmsg16 = MapSL(*plParam);
75 LPMSG lpmsg32 = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpmsg32) );
77 STRUCT32_MSG16to32( lpmsg16, lpmsg32 );
78 *plParam = (LPARAM)lpmsg32;
82 case WH_JOURNALPLAYBACK:
84 LPEVENTMSG16 lpem16 = MapSL(*plParam);
85 LPEVENTMSG lpem32 = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpem32) );
87 lpem32->message = lpem16->message;
88 lpem32->paramL = lpem16->paramL;
89 lpem32->paramH = lpem16->paramH;
90 lpem32->time = lpem16->time;
91 lpem32->hwnd = 0; /* FIXME */
93 *plParam = (LPARAM)lpem32;
99 LPCWPSTRUCT16 lpcwp16 = MapSL(*plParam);
100 LPCWPSTRUCT lpcwp32 = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpcwp32) );
102 lpcwp32->hwnd = WIN_Handle32(lpcwp16->hwnd);
103 lpcwp32->lParam = lpcwp16->lParam;
105 if (bA) WINPROC_MapMsg16To32A( lpcwp32->hwnd, lpcwp16->message, lpcwp16->wParam,
106 &lpcwp32->message, &lpcwp32->wParam,
108 else WINPROC_MapMsg16To32W( lpcwp32->hwnd,lpcwp16->message, lpcwp16->wParam,
109 &lpcwp32->message, &lpcwp32->wParam,
111 *plParam = (LPARAM)lpcwp32;
120 LPCBT_CREATEWND16 lpcbtcw16 = MapSL(*plParam);
121 LPCREATESTRUCT16 lpcs16 = MapSL((SEGPTR)lpcbtcw16->lpcs);
122 LPCBT_CREATEWNDA lpcbtcw32 = HeapAlloc( GetProcessHeap(), 0,
123 sizeof(*lpcbtcw32) );
124 lpcbtcw32->lpcs = HeapAlloc( GetProcessHeap(), 0,
125 sizeof(*lpcbtcw32->lpcs) );
127 STRUCT32_CREATESTRUCT16to32A( lpcs16,
128 (LPCREATESTRUCTA)lpcbtcw32->lpcs );
130 if (HIWORD(lpcs16->lpszName))
131 lpcbtcw32->lpcs->lpszName =
132 (bA) ? MapSL(lpcs16->lpszName)
133 : HEAP_strdupAtoW( GetProcessHeap(), 0,
134 MapSL(lpcs16->lpszName) );
136 lpcbtcw32->lpcs->lpszName = (LPCSTR)lpcs16->lpszName;
138 if (HIWORD(lpcs16->lpszClass))
139 lpcbtcw32->lpcs->lpszClass =
140 (bA) ? MapSL(lpcs16->lpszClass)
141 : HEAP_strdupAtoW( GetProcessHeap(), 0,
142 MapSL(lpcs16->lpszClass) );
144 lpcbtcw32->lpcs->lpszClass = (LPCSTR)lpcs16->lpszClass;
146 lpcbtcw32->hwndInsertAfter = WIN_Handle32( lpcbtcw16->hwndInsertAfter );
148 *plParam = (LPARAM)lpcbtcw32;
153 LPCBTACTIVATESTRUCT16 lpcas16 = MapSL(*plParam);
154 LPCBTACTIVATESTRUCT lpcas32 = HeapAlloc( GetProcessHeap(), 0,
156 lpcas32->fMouse = lpcas16->fMouse;
157 lpcas32->hWndActive = WIN_Handle32(lpcas16->hWndActive);
158 *plParam = (LPARAM)lpcas32;
161 case HCBT_CLICKSKIPPED:
163 LPMOUSEHOOKSTRUCT16 lpms16 = MapSL(*plParam);
164 LPMOUSEHOOKSTRUCT lpms32 = HeapAlloc( GetProcessHeap(), 0,
167 CONV_POINT16TO32( &lpms16->pt, &lpms32->pt );
169 /* wHitTestCode may be negative, so convince compiler to do
170 correct sign extension. Yay. :| */
171 lpms32->wHitTestCode = (INT)((INT16)lpms16->wHitTestCode);
173 lpms32->dwExtraInfo = lpms16->dwExtraInfo;
174 lpms32->hwnd = WIN_Handle32( lpms16->hwnd );
175 *plParam = (LPARAM)lpms32;
180 LPRECT16 lprect16 = MapSL(*plParam);
181 LPRECT lprect32 = HeapAlloc( GetProcessHeap(), 0,
184 CONV_RECT16TO32( lprect16, lprect32 );
185 *plParam = (LPARAM)lprect32;
193 LPMOUSEHOOKSTRUCT16 lpms16 = MapSL(*plParam);
194 LPMOUSEHOOKSTRUCT lpms32 = HeapAlloc( GetProcessHeap(), 0,
197 CONV_POINT16TO32( &lpms16->pt, &lpms32->pt );
199 /* wHitTestCode may be negative, so convince compiler to do
200 correct sign extension. Yay. :| */
201 lpms32->wHitTestCode = (INT)((INT16)lpms16->wHitTestCode);
202 lpms32->dwExtraInfo = lpms16->dwExtraInfo;
203 lpms32->hwnd = WIN_Handle32(lpms16->hwnd);
204 *plParam = (LPARAM)lpms32;
210 LPDEBUGHOOKINFO16 lpdh16 = MapSL(*plParam);
211 LPDEBUGHOOKINFO lpdh32 = HeapAlloc( GetProcessHeap(), 0,
214 lpdh32->idThread = 0; /* FIXME */
215 lpdh32->idThreadInstaller = 0; /* FIXME */
216 lpdh32->lParam = lpdh16->lParam; /* FIXME Check for sign ext */
217 lpdh32->wParam = lpdh16->wParam;
218 lpdh32->code = lpdh16->code;
220 /* do sign extension if it was WH_MSGFILTER */
221 if (*pwParam == 0xffff) *pwParam = WH_MSGFILTER;
223 *plParam = (LPARAM)lpdh32;
232 case WH_FOREGROUNDIDLE:
233 case WH_CALLWNDPROCRET:
235 FIXME("\t[%i] 16to32 translation unimplemented\n", id);
240 /***********************************************************************
243 static void HOOK_Map16To32A(INT id, INT code, WPARAM *pwParam,
246 HOOK_Map16To32Common( id, code, pwParam, plParam, TRUE );
250 /***********************************************************************
253 static void HOOK_Map16To32W(INT id, INT code, WPARAM *pwParam,
256 HOOK_Map16To32Common( id, code, pwParam, plParam, FALSE );
260 /***********************************************************************
261 * HOOK_UnMap16To32Common
263 static void HOOK_UnMap16To32Common(INT id, INT code, WPARAM wParamOrig,
264 LPARAM lParamOrig, WPARAM wParam,
265 LPARAM lParam, BOOL bA)
270 case WH_SYSMSGFILTER:
271 case WH_JOURNALRECORD:
272 case WH_JOURNALPLAYBACK:
274 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
279 LPCWPSTRUCT lpcwp32 = (LPCWPSTRUCT)lParam;
280 if (bA) WINPROC_UnmapMsg16To32A( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
281 lpcwp32->lParam, 0 );
282 else WINPROC_UnmapMsg16To32W( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
283 lpcwp32->lParam, 0 );
284 HeapFree( GetProcessHeap(), 0, lpcwp32 );
290 LPMSG16 lpmsg16 = MapSL(lParamOrig);
291 STRUCT32_MSG32to16( (LPMSG)lParam, lpmsg16 );
292 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
299 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
307 LPCBT_CREATEWNDA lpcbtcw32 = (LPCBT_CREATEWNDA)lParam;
308 LPCBT_CREATEWND16 lpcbtcw16 = MapSL(lParamOrig);
312 if (HIWORD(lpcbtcw32->lpcs->lpszName))
313 HeapFree( GetProcessHeap(), 0, (LPWSTR)lpcbtcw32->lpcs->lpszName );
314 if (HIWORD(lpcbtcw32->lpcs->lpszClass))
315 HeapFree( GetProcessHeap(), 0, (LPWSTR)lpcbtcw32->lpcs->lpszClass );
318 lpcbtcw16->hwndInsertAfter = WIN_Handle16( lpcbtcw32->hwndInsertAfter );
320 HeapFree( GetProcessHeap(), 0, lpcbtcw32->lpcs );
324 case HCBT_CLICKSKIPPED:
327 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam);
337 case WH_FOREGROUNDIDLE:
338 case WH_CALLWNDPROCRET:
340 FIXME("\t[%i] skipping unmap\n", id);
346 /***********************************************************************
349 static void HOOK_UnMap16To32A(INT id, INT code, WPARAM wParamOrig,
350 LPARAM lParamOrig, WPARAM wParam,
353 HOOK_UnMap16To32Common( id, code, wParamOrig, lParamOrig, wParam,
358 /***********************************************************************
361 static void HOOK_UnMap16To32W(INT id, INT code, WPARAM wParamOrig,
362 LPARAM lParamOrig, WPARAM wParam,
365 HOOK_UnMap16To32Common( id, code, wParamOrig, lParamOrig, wParam,
370 /***********************************************************************
371 * HOOK_Map32To16Common
373 static void HOOK_Map32To16Common(INT id, INT code, WPARAM *pwParam,
374 LPARAM *plParam, BOOL bA)
379 case WH_SYSMSGFILTER:
381 case WH_JOURNALRECORD:
383 LPMSG lpmsg32 = (LPMSG)*plParam;
384 LPMSG16 lpmsg16 = SEGPTR_NEW( MSG16 );
386 STRUCT32_MSG32to16( lpmsg32, lpmsg16 );
388 *plParam = (LPARAM)SEGPTR_GET( lpmsg16 );
392 case WH_JOURNALPLAYBACK:
394 LPEVENTMSG lpem32 = (LPEVENTMSG)*plParam;
395 LPEVENTMSG16 lpem16 = SEGPTR_NEW( EVENTMSG16 );
397 lpem16->message = lpem32->message;
398 lpem16->paramL = lpem32->paramL;
399 lpem16->paramH = lpem32->paramH;
400 lpem16->time = lpem32->time;
402 *plParam = (LPARAM)SEGPTR_GET( lpem16 );
408 LPCWPSTRUCT lpcwp32 = (LPCWPSTRUCT)*plParam;
409 LPCWPSTRUCT16 lpcwp16 = SEGPTR_NEW( CWPSTRUCT16 );
411 lpcwp16->hwnd = WIN_Handle16(lpcwp32->hwnd);
412 lpcwp16->lParam = lpcwp32->lParam;
414 if (bA) WINPROC_MapMsg32ATo16( lpcwp32->hwnd, lpcwp32->message,
415 lpcwp32->wParam, &lpcwp16->message,
416 &lpcwp16->wParam, &lpcwp16->lParam );
417 else WINPROC_MapMsg32WTo16( lpcwp32->hwnd, lpcwp32->message,
418 lpcwp32->wParam, &lpcwp16->message,
419 &lpcwp16->wParam, &lpcwp16->lParam );
420 *plParam = (LPARAM)SEGPTR_GET( lpcwp16 );
429 LPCBTACTIVATESTRUCT lpcas32 = (LPCBTACTIVATESTRUCT)*plParam;
430 LPCBTACTIVATESTRUCT16 lpcas16 =SEGPTR_NEW( CBTACTIVATESTRUCT16 );
432 lpcas16->fMouse = lpcas32->fMouse;
433 lpcas16->hWndActive = WIN_Handle16( lpcas32->hWndActive );
435 *plParam = (LPARAM)SEGPTR_GET( lpcas16 );
439 case HCBT_CLICKSKIPPED:
441 LPMOUSEHOOKSTRUCT lpms32 = (LPMOUSEHOOKSTRUCT)*plParam;
442 LPMOUSEHOOKSTRUCT16 lpms16 = SEGPTR_NEW( MOUSEHOOKSTRUCT16 );
444 CONV_POINT32TO16( &lpms32->pt, &lpms16->pt );
446 lpms16->hwnd = WIN_Handle16( lpms32->hwnd );
447 lpms16->wHitTestCode = lpms32->wHitTestCode;
448 lpms16->dwExtraInfo = lpms32->dwExtraInfo;
450 *plParam = (LPARAM)SEGPTR_GET( lpms16 );
456 LPRECT lprect32 = (LPRECT)*plParam;
457 LPRECT16 lprect16 = SEGPTR_NEW( RECT16 );
459 CONV_RECT32TO16( lprect32, lprect16 );
461 *plParam = (LPARAM)SEGPTR_GET( lprect16 );
469 LPMOUSEHOOKSTRUCT lpms32 = (LPMOUSEHOOKSTRUCT)*plParam;
470 LPMOUSEHOOKSTRUCT16 lpms16 = SEGPTR_NEW( MOUSEHOOKSTRUCT16 );
472 CONV_POINT32TO16( &lpms32->pt, &lpms16->pt );
474 lpms16->hwnd = WIN_Handle16( lpms32->hwnd );
475 lpms16->wHitTestCode = lpms32->wHitTestCode;
476 lpms16->dwExtraInfo = lpms32->dwExtraInfo;
478 *plParam = (LPARAM)SEGPTR_GET( lpms16 );
484 LPDEBUGHOOKINFO lpdh32 = (LPDEBUGHOOKINFO)*plParam;
485 LPDEBUGHOOKINFO16 lpdh16 = SEGPTR_NEW( DEBUGHOOKINFO16 );
487 lpdh16->hModuleHook = 0; /* FIXME */
488 lpdh16->reserved = 0;
489 lpdh16->lParam = lpdh32->lParam;
490 lpdh16->wParam = lpdh32->wParam;
491 lpdh16->code = lpdh32->code;
493 *plParam = (LPARAM)SEGPTR_GET( lpdh16 );
502 case WH_FOREGROUNDIDLE:
503 case WH_CALLWNDPROCRET:
505 FIXME("\t[%i] 32to16 translation unimplemented\n", id);
510 /***********************************************************************
513 static void HOOK_Map32ATo16(INT id, INT code, WPARAM *pwParam,
516 if (id == WH_CBT && code == HCBT_CREATEWND)
518 LPCBT_CREATEWNDA lpcbtcw32 = (LPCBT_CREATEWNDA)*plParam;
519 LPCBT_CREATEWND16 lpcbtcw16 = SEGPTR_NEW( CBT_CREATEWND16 );
520 LPCREATESTRUCT16 lpcs16 = SEGPTR_NEW( CREATESTRUCT16 );
522 lpcbtcw16->lpcs = (LPCREATESTRUCT16)SEGPTR_GET( lpcs16 );
523 STRUCT32_CREATESTRUCT32Ato16( lpcbtcw32->lpcs, lpcs16 );
525 if (HIWORD(lpcbtcw32->lpcs->lpszName))
527 SEGPTR_GET( SEGPTR_STRDUP( lpcbtcw32->lpcs->lpszName ) );
529 lpcs16->lpszName = (SEGPTR)lpcbtcw32->lpcs->lpszName;
531 if (HIWORD(lpcbtcw32->lpcs->lpszClass))
533 SEGPTR_GET( SEGPTR_STRDUP( lpcbtcw32->lpcs->lpszClass ) );
535 lpcs16->lpszClass = (SEGPTR)lpcbtcw32->lpcs->lpszClass;
537 lpcbtcw16->hwndInsertAfter = WIN_Handle16( lpcbtcw32->hwndInsertAfter );
539 *plParam = (LPARAM)SEGPTR_GET( lpcbtcw16 );
541 else HOOK_Map32To16Common(id, code, pwParam, plParam, TRUE);
545 /***********************************************************************
548 static void HOOK_Map32WTo16(INT id, INT code, WPARAM *pwParam,
551 if (id == WH_CBT && code == HCBT_CREATEWND)
554 LPCBT_CREATEWNDW lpcbtcw32 = (LPCBT_CREATEWNDW)*plParam;
555 LPCBT_CREATEWND16 lpcbtcw16 = SEGPTR_NEW( CBT_CREATEWND16 );
556 LPCREATESTRUCT16 lpcs16 = SEGPTR_NEW( CREATESTRUCT16 );
558 lpcbtcw16->lpcs = (LPCREATESTRUCT16)SEGPTR_GET( lpcs16 );
559 STRUCT32_CREATESTRUCT32Ato16( (LPCREATESTRUCTA)lpcbtcw32->lpcs,
562 name = SEGPTR_STRDUP_WtoA( lpcbtcw32->lpcs->lpszName );
563 cls = SEGPTR_STRDUP_WtoA( lpcbtcw32->lpcs->lpszClass );
564 lpcs16->lpszName = SEGPTR_GET( name );
565 lpcs16->lpszClass = SEGPTR_GET( cls );
566 lpcbtcw16->hwndInsertAfter = WIN_Handle16( lpcbtcw32->hwndInsertAfter );
568 *plParam = (LPARAM)SEGPTR_GET( lpcbtcw16 );
570 else HOOK_Map32To16Common(id, code, pwParam, plParam, FALSE);
574 /***********************************************************************
575 * HOOK_UnMap32To16Common
577 static void HOOK_UnMap32To16Common(INT id, INT code, WPARAM wParamOrig,
578 LPARAM lParamOrig, WPARAM wParam,
579 LPARAM lParam, BOOL bA)
584 case WH_SYSMSGFILTER:
585 case WH_JOURNALRECORD:
586 case WH_JOURNALPLAYBACK:
589 SEGPTR_FREE( MapSL(lParam) );
594 LPCWPSTRUCT16 lpcwp16 = MapSL(lParam);
595 LPCWPSTRUCT lpcwp32 = (LPCWPSTRUCT)lParamOrig;
598 mp16.wParam = lpcwp16->wParam;
599 mp16.lParam = lpcwp16->lParam;
602 if (bA) WINPROC_UnmapMsg32ATo16( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
603 lpcwp32->lParam, &mp16 );
604 else WINPROC_UnmapMsg32WTo16( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
605 lpcwp32->lParam, &mp16 );
606 SEGPTR_FREE( MapSL(lParam) );
612 LPMSG lpmsg32 = (LPMSG)lParamOrig;
614 STRUCT32_MSG16to32( MapSL(lParam), lpmsg32 );
615 SEGPTR_FREE( MapSL(lParam) );
624 LPCBT_CREATEWNDA lpcbtcw32 = (LPCBT_CREATEWNDA)(lParamOrig);
625 LPCBT_CREATEWND16 lpcbtcw16 = MapSL(lParam);
626 LPCREATESTRUCT16 lpcs16 = MapSL((SEGPTR)lpcbtcw16->lpcs);
628 if (HIWORD(lpcs16->lpszName))
629 SEGPTR_FREE( MapSL(lpcs16->lpszName) );
631 if (HIWORD(lpcs16->lpszClass))
632 SEGPTR_FREE( MapSL(lpcs16->lpszClass) );
634 lpcbtcw32->hwndInsertAfter = WIN_Handle32( lpcbtcw16->hwndInsertAfter );
636 SEGPTR_FREE( lpcs16 );
640 case HCBT_CLICKSKIPPED:
643 SEGPTR_FREE( MapSL(lParam) );
653 case WH_FOREGROUNDIDLE:
654 case WH_CALLWNDPROCRET:
656 FIXME("\t[%i] skipping unmap\n", id);
661 /***********************************************************************
664 static void HOOK_UnMap32ATo16(INT id, INT code, WPARAM wParamOrig,
665 LPARAM lParamOrig, WPARAM wParam,
668 HOOK_UnMap32To16Common( id, code, wParamOrig, lParamOrig, wParam,
673 /***********************************************************************
676 static void HOOK_UnMap32WTo16(INT id, INT code, WPARAM wParamOrig,
677 LPARAM lParamOrig, WPARAM wParam,
680 HOOK_UnMap32To16Common( id, code, wParamOrig, lParamOrig, wParam,
685 /***********************************************************************
688 static void HOOK_Map32ATo32W(INT id, INT code, WPARAM *pwParam,
691 if (id == WH_CBT && code == HCBT_CREATEWND)
693 LPCBT_CREATEWNDA lpcbtcwA = (LPCBT_CREATEWNDA)*plParam;
694 LPCBT_CREATEWNDW lpcbtcwW = HeapAlloc( GetProcessHeap(), 0,
696 lpcbtcwW->lpcs = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpcbtcwW->lpcs) );
698 lpcbtcwW->hwndInsertAfter = lpcbtcwA->hwndInsertAfter;
699 *lpcbtcwW->lpcs = *(LPCREATESTRUCTW)lpcbtcwA->lpcs;
701 if (HIWORD(lpcbtcwA->lpcs->lpszName))
703 lpcbtcwW->lpcs->lpszName = HEAP_strdupAtoW( GetProcessHeap(), 0,
704 lpcbtcwA->lpcs->lpszName );
707 lpcbtcwW->lpcs->lpszName = (LPWSTR)lpcbtcwA->lpcs->lpszName;
709 if (HIWORD(lpcbtcwA->lpcs->lpszClass))
711 lpcbtcwW->lpcs->lpszClass = HEAP_strdupAtoW( GetProcessHeap(), 0,
712 lpcbtcwA->lpcs->lpszClass );
715 lpcbtcwW->lpcs->lpszClass = (LPCWSTR)lpcbtcwA->lpcs->lpszClass;
716 *plParam = (LPARAM)lpcbtcwW;
722 /***********************************************************************
725 static void HOOK_UnMap32ATo32W(INT id, INT code, WPARAM wParamOrig,
726 LPARAM lParamOrig, WPARAM wParam,
729 if (id == WH_CBT && code == HCBT_CREATEWND)
731 LPCBT_CREATEWNDW lpcbtcwW = (LPCBT_CREATEWNDW)lParam;
732 if (HIWORD(lpcbtcwW->lpcs->lpszName))
733 HeapFree( GetProcessHeap(), 0, (LPWSTR)lpcbtcwW->lpcs->lpszName );
734 if (HIWORD(lpcbtcwW->lpcs->lpszClass))
735 HeapFree( GetProcessHeap(), 0, (LPWSTR)lpcbtcwW->lpcs->lpszClass );
736 HeapFree( GetProcessHeap(), 0, lpcbtcwW->lpcs );
737 HeapFree( GetProcessHeap(), 0, lpcbtcwW );
743 /***********************************************************************
746 static void HOOK_Map32WTo32A(INT id, INT code, WPARAM *pwParam,
749 if (id == WH_CBT && code == HCBT_CREATEWND)
751 LPCBT_CREATEWNDW lpcbtcwW = (LPCBT_CREATEWNDW)*plParam;
752 LPCBT_CREATEWNDA lpcbtcwA = HeapAlloc( GetProcessHeap(), 0,
754 lpcbtcwA->lpcs = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpcbtcwA->lpcs) );
756 lpcbtcwA->hwndInsertAfter = lpcbtcwW->hwndInsertAfter;
757 *lpcbtcwA->lpcs = *(LPCREATESTRUCTA)lpcbtcwW->lpcs;
759 if (HIWORD(lpcbtcwW->lpcs->lpszName))
760 lpcbtcwA->lpcs->lpszName = HEAP_strdupWtoA( GetProcessHeap(), 0,
761 lpcbtcwW->lpcs->lpszName );
763 lpcbtcwA->lpcs->lpszName = (LPSTR)lpcbtcwW->lpcs->lpszName;
765 if (HIWORD(lpcbtcwW->lpcs->lpszClass))
766 lpcbtcwA->lpcs->lpszClass = HEAP_strdupWtoA( GetProcessHeap(), 0,
767 lpcbtcwW->lpcs->lpszClass );
769 lpcbtcwA->lpcs->lpszClass = (LPSTR)lpcbtcwW->lpcs->lpszClass;
770 *plParam = (LPARAM)lpcbtcwA;
776 /***********************************************************************
779 static void HOOK_UnMap32WTo32A(INT id, INT code, WPARAM wParamOrig,
780 LPARAM lParamOrig, WPARAM wParam,
783 if (id == WH_CBT && code == HCBT_CREATEWND)
785 LPCBT_CREATEWNDA lpcbtcwA = (LPCBT_CREATEWNDA)lParam;
786 if (HIWORD(lpcbtcwA->lpcs->lpszName))
787 HeapFree( GetProcessHeap(), 0, (LPSTR)lpcbtcwA->lpcs->lpszName );
788 if (HIWORD(lpcbtcwA->lpcs->lpszClass))
789 HeapFree( GetProcessHeap(), 0, (LPSTR)lpcbtcwA->lpcs->lpszClass );
790 HeapFree( GetProcessHeap(), 0, lpcbtcwA->lpcs );
791 HeapFree( GetProcessHeap(), 0, lpcbtcwA );
797 /***********************************************************************
798 * Map Function Tables
800 static const HOOK_MapFunc HOOK_MapFuncs[3][3] =
802 { NULL, HOOK_Map16To32A, HOOK_Map16To32W },
803 { HOOK_Map32ATo16, NULL, HOOK_Map32ATo32W },
804 { HOOK_Map32WTo16, HOOK_Map32WTo32A, NULL }
807 static const HOOK_UnMapFunc HOOK_UnMapFuncs[3][3] =
809 { NULL, HOOK_UnMap16To32A, HOOK_UnMap16To32W },
810 { HOOK_UnMap32ATo16, NULL, HOOK_UnMap32ATo32W },
811 { HOOK_UnMap32WTo16, HOOK_UnMap32WTo32A, NULL }
815 /***********************************************************************
819 /***********************************************************************
822 * Get the next hook of a given hook.
824 static HANDLE16 HOOK_GetNextHook( HANDLE16 hook )
826 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR( hook );
828 if (!data || !hook) return 0;
829 if (data->next) return data->next;
830 if (!data->ownerQueue) return 0; /* Already system hook */
832 /* Now start enumerating the system hooks */
833 return HOOK_systemHooks[data->id - WH_MINHOOK];
837 /***********************************************************************
840 * Get the first hook for a given type.
842 static HANDLE16 HOOK_GetHook( INT16 id )
847 if ((queue = QUEUE_Current()) != NULL)
848 hook = queue->hooks[id - WH_MINHOOK];
849 if (!hook) hook = HOOK_systemHooks[id - WH_MINHOOK];
854 /***********************************************************************
857 * Install a given hook.
859 /* ### start build ### */
860 extern LONG CALLBACK HOOK_CallTo16_long_wwl(FARPROC16,WORD,WORD,LONG);
861 /* ### stop build ### */
862 static HHOOK HOOK_SetHook( INT16 id, LPVOID proc, INT type,
863 HMODULE16 hModule, DWORD dwThreadId )
869 if ((id < WH_MINHOOK) || (id > WH_MAXHOOK)) return 0;
871 TRACE("Setting hook %d: %08x %04x %08lx\n",
872 id, (UINT)proc, hModule, dwThreadId );
874 /* Create task queue if none present */
875 InitThreadInput16( 0, 0 );
877 if (id == WH_JOURNALPLAYBACK) EnableHardwareInput16(FALSE);
879 if (dwThreadId) /* Task-specific hook */
881 if ((id == WH_JOURNALRECORD) || (id == WH_JOURNALPLAYBACK) ||
882 (id == WH_SYSMSGFILTER)) return 0; /* System-only hooks */
883 if (!(hQueue = GetThreadQueue16( dwThreadId )))
887 /* Create the hook structure */
889 if (!(handle = USER_HEAP_ALLOC( sizeof(HOOKDATA) ))) return 0;
890 data = (HOOKDATA *) USER_HEAP_LIN_ADDR( handle );
893 data->ownerQueue = hQueue;
894 data->ownerModule = hModule;
897 /* Create CallTo16 thunk for 16-bit hooks */
899 if ( (data->flags & HOOK_MAPTYPE) == HOOK_WIN16 )
900 data->thunk = (HOOKPROC)THUNK_Alloc( (FARPROC16)data->proc,
901 (RELAY)HOOK_CallTo16_long_wwl );
903 data->thunk = data->proc;
905 if ( !data->thunk && data->proc )
907 USER_HEAP_FREE( handle );
911 /* Insert it in the correct linked list */
915 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue );
916 data->next = queue->hooks[id - WH_MINHOOK];
917 queue->hooks[id - WH_MINHOOK] = handle;
918 QUEUE_Unlock( queue );
922 data->next = HOOK_systemHooks[id - WH_MINHOOK];
923 HOOK_systemHooks[id - WH_MINHOOK] = handle;
925 TRACE("Setting hook %d: ret=%04x [next=%04x]\n",
926 id, handle, data->next );
928 return (HHOOK)( handle? MAKELONG( handle, HOOK_MAGIC ) : 0 );
932 /***********************************************************************
935 * Remove a hook from the list.
937 static BOOL HOOK_RemoveHook( HANDLE16 hook )
942 TRACE("Removing hook %04x\n", hook );
944 if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook))) return FALSE;
945 if (data->flags & HOOK_INUSE)
947 /* Mark it for deletion later on */
948 WARN("Hook still running, deletion delayed\n" );
949 data->proc = (HOOKPROC)0;
953 if (data->id == WH_JOURNALPLAYBACK) EnableHardwareInput16(TRUE);
955 /* Remove it from the linked list */
957 if (data->ownerQueue)
959 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( data->ownerQueue );
960 if (!queue) return FALSE;
961 prevHook = &queue->hooks[data->id - WH_MINHOOK];
962 QUEUE_Unlock( queue );
964 else prevHook = &HOOK_systemHooks[data->id - WH_MINHOOK];
966 while (*prevHook && *prevHook != hook)
967 prevHook = &((HOOKDATA *)USER_HEAP_LIN_ADDR(*prevHook))->next;
969 if (!*prevHook) return FALSE;
970 *prevHook = data->next;
972 if ( (data->flags & HOOK_MAPTYPE) == HOOK_WIN16 )
973 THUNK_Free( (FARPROC)data->thunk );
975 USER_HEAP_FREE( hook );
980 /***********************************************************************
983 static HANDLE16 HOOK_FindValidHook( HANDLE16 hook )
989 if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook))) return 0;
990 if (data->proc) return hook;
996 /***********************************************************************
999 * Call a hook procedure.
1001 static LRESULT HOOK_CallHook( HANDLE16 hook, INT fromtype, INT code,
1002 WPARAM wParam, LPARAM lParam )
1004 MESSAGEQUEUE *queue;
1006 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
1010 WPARAM wParamOrig = wParam;
1011 LPARAM lParamOrig = lParam;
1012 HOOK_MapFunc MapFunc;
1013 HOOK_UnMapFunc UnMapFunc;
1015 MapFunc = HOOK_MapFuncs[fromtype][data->flags & HOOK_MAPTYPE];
1016 UnMapFunc = HOOK_UnMapFuncs[fromtype][data->flags & HOOK_MAPTYPE];
1019 MapFunc( data->id, code, &wParam, &lParam );
1023 if (!(queue = QUEUE_Current())) return 0;
1024 prevHook = queue->hCurHook;
1025 queue->hCurHook = hook;
1026 data->flags |= HOOK_INUSE;
1028 TRACE("Calling hook %04x: %d %08x %08lx\n",
1029 hook, code, wParam, lParam );
1031 /* Suspend window structure locks before calling user code */
1032 iWndsLocks = WIN_SuspendWndsLock();
1034 ret = data->thunk(code, wParam, lParam);
1036 /* Grrr. While the hook procedure is supposed to have an LRESULT return
1037 value even in Win16, it seems that for those hook types where the
1038 return value is interpreted as BOOL, Windows doesn't actually check
1039 the HIWORD ... Some buggy Win16 programs, notably WINFILE, rely on
1040 that, because they neglect to clear DX ... */
1041 if ( (data->flags & HOOK_MAPTYPE) == HOOK_WIN16
1042 && data->id != WH_JOURNALPLAYBACK )
1043 ret = LOWORD( ret );
1045 WIN_RestoreWndsLock(iWndsLocks);
1047 TRACE("Ret hook %04x = %08lx\n", hook, ret );
1049 data->flags &= ~HOOK_INUSE;
1050 queue->hCurHook = prevHook;
1053 UnMapFunc( data->id, code, wParamOrig, lParamOrig, wParam, lParam );
1055 if (!data->proc) HOOK_RemoveHook( hook );
1060 /***********************************************************************
1061 * Exported Functions & APIs
1064 /***********************************************************************
1067 * Replacement for calling HOOK_GetHook from other modules.
1069 BOOL HOOK_IsHooked( INT16 id )
1071 return HOOK_GetHook( id ) != 0;
1075 /***********************************************************************
1078 * Call a hook chain.
1080 LRESULT HOOK_CallHooks16( INT16 id, INT16 code, WPARAM16 wParam,
1085 if (!(hook = HOOK_GetHook( id ))) return 0;
1086 if (!(hook = HOOK_FindValidHook(hook))) return 0;
1087 return HOOK_CallHook( hook, HOOK_WIN16, code, wParam, lParam );
1090 /***********************************************************************
1093 * Call a hook chain.
1095 LRESULT HOOK_CallHooksA( INT id, INT code, WPARAM wParam,
1100 if (!(hook = HOOK_GetHook( id ))) return 0;
1101 if (!(hook = HOOK_FindValidHook(hook))) return 0;
1102 return HOOK_CallHook( hook, HOOK_WIN32A, code, wParam, lParam );
1105 /***********************************************************************
1108 * Call a hook chain.
1110 LRESULT HOOK_CallHooksW( INT id, INT code, WPARAM wParam,
1115 if (!(hook = HOOK_GetHook( id ))) return 0;
1116 if (!(hook = HOOK_FindValidHook(hook))) return 0;
1117 return HOOK_CallHook( hook, HOOK_WIN32W, code, wParam,
1122 /***********************************************************************
1123 * HOOK_FreeModuleHooks
1125 void HOOK_FreeModuleHooks( HMODULE16 hModule )
1127 /* remove all system hooks registered by this module */
1133 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
1135 hook = HOOK_systemHooks[id - WH_MINHOOK];
1137 if( (hptr = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook)) )
1140 if( hptr->ownerModule == hModule )
1142 hptr->flags &= HOOK_MAPTYPE;
1143 HOOK_RemoveHook(hook);
1151 /***********************************************************************
1152 * HOOK_FreeQueueHooks
1154 void HOOK_FreeQueueHooks(void)
1156 /* remove all hooks registered by the current queue */
1158 HOOKDATA* hptr = NULL;
1162 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
1164 hook = HOOK_GetHook( id );
1167 next = HOOK_GetNextHook(hook);
1169 hptr = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
1170 if( hptr && hptr->ownerQueue )
1172 hptr->flags &= HOOK_MAPTYPE;
1173 HOOK_RemoveHook(hook);
1181 /***********************************************************************
1182 * SetWindowsHook (USER.121)
1184 FARPROC16 WINAPI SetWindowsHook16( INT16 id, HOOKPROC16 proc )
1186 HINSTANCE16 hInst = FarGetOwner16( HIWORD(proc) );
1188 /* WH_MSGFILTER is the only task-specific hook for SetWindowsHook() */
1189 HTASK16 hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
1191 return (FARPROC16)SetWindowsHookEx16( id, proc, hInst, hTask );
1194 /***********************************************************************
1195 * SetWindowsHookA (USER32.@)
1197 HHOOK WINAPI SetWindowsHookA( INT id, HOOKPROC proc )
1199 return SetWindowsHookExA( id, proc, 0, GetCurrentThreadId() );
1202 /***********************************************************************
1203 * SetWindowsHookW (USER32.@)
1205 HHOOK WINAPI SetWindowsHookW( INT id, HOOKPROC proc )
1207 return SetWindowsHookExW( id, proc, 0, GetCurrentThreadId() );
1211 /***********************************************************************
1212 * SetWindowsHookEx (USER.291)
1213 * SetWindowsHookEx16 (USER32.@)
1215 HHOOK WINAPI SetWindowsHookEx16( INT16 id, HOOKPROC16 proc, HINSTANCE16 hInst,
1220 FIXME("WH_DEBUG is broken in 16-bit Windows.\n");
1223 return HOOK_SetHook( id, proc, HOOK_WIN16, GetExePtr(hInst), (DWORD)hTask );
1226 /***********************************************************************
1227 * SetWindowsHookExA (USER32.@)
1229 HHOOK WINAPI SetWindowsHookExA( INT id, HOOKPROC proc, HINSTANCE hInst,
1232 return HOOK_SetHook( id, proc, HOOK_WIN32A, MapHModuleLS(hInst), dwThreadId );
1235 /***********************************************************************
1236 * SetWindowsHookExW (USER32.@)
1238 HHOOK WINAPI SetWindowsHookExW( INT id, HOOKPROC proc, HINSTANCE hInst,
1241 return HOOK_SetHook( id, proc, HOOK_WIN32W, MapHModuleLS(hInst), dwThreadId );
1245 /***********************************************************************
1246 * UnhookWindowsHook (USER.234)
1248 BOOL16 WINAPI UnhookWindowsHook16( INT16 id, HOOKPROC16 proc )
1250 return UnhookWindowsHook( id, (HOOKPROC)proc );
1253 /***********************************************************************
1254 * UnhookWindowsHook (USER32.@)
1256 BOOL WINAPI UnhookWindowsHook( INT id, HOOKPROC proc )
1258 HANDLE16 hook = HOOK_GetHook( id );
1260 TRACE("%d %08lx\n", id, (DWORD)proc );
1264 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
1265 if (data->proc == proc) break;
1266 hook = HOOK_GetNextHook( hook );
1268 if (!hook) return FALSE;
1269 return HOOK_RemoveHook( hook );
1273 /***********************************************************************
1274 * UnhookWindowsHookEx (USER.292)
1276 BOOL16 WINAPI UnhookWindowsHookEx16( HHOOK hhook )
1278 return UnhookWindowsHookEx( hhook );
1281 /***********************************************************************
1282 * UnhookWindowsHookEx (USER32.@)
1284 BOOL WINAPI UnhookWindowsHookEx( HHOOK hhook )
1286 if (HIWORD(hhook) != HOOK_MAGIC) return FALSE; /* Not a new format hook */
1287 return HOOK_RemoveHook( LOWORD(hhook) );
1291 /***********************************************************************
1292 * CallNextHookEx (USER.293)
1293 * CallNextHookEx16 (USER32.@)
1295 * I wouldn't have separated this into 16 and 32 bit versions, but I
1296 * need a way to figure out if I need to do a mapping or not.
1298 LRESULT WINAPI CallNextHookEx16( HHOOK hhook, INT16 code, WPARAM16 wParam,
1303 if (HIWORD(hhook) != HOOK_MAGIC) return 0; /* Not a new format hook */
1304 if (!(next = HOOK_GetNextHook( LOWORD(hhook) ))) return 0;
1306 return HOOK_CallHook( next, HOOK_WIN16, code, wParam, lParam );
1310 /***********************************************************************
1311 * CallNextHookEx (USER32.@)
1313 * There aren't ANSI and UNICODE versions of this.
1315 LRESULT WINAPI CallNextHookEx( HHOOK hhook, INT code, WPARAM wParam,
1319 INT fromtype; /* figure out Ansi/Unicode */
1322 if (HIWORD(hhook) != HOOK_MAGIC) return 0; /* Not a new format hook */
1323 if (!(next = HOOK_GetNextHook( LOWORD(hhook) ))) return 0;
1325 oldhook = (HOOKDATA *)USER_HEAP_LIN_ADDR( LOWORD(hhook) );
1326 fromtype = oldhook->flags & HOOK_MAPTYPE;
1328 if (fromtype == HOOK_WIN16)
1329 ERR("called from 16bit hook!\n");
1331 return HOOK_CallHook( next, fromtype, code, wParam, lParam );
1335 /***********************************************************************
1336 * DefHookProc (USER.235)
1338 LRESULT WINAPI DefHookProc16( INT16 code, WPARAM16 wParam, LPARAM lParam,
1341 /* Note: the *hhook parameter is never used, since we rely on the
1342 * current hook value from the task queue to find the next hook. */
1343 MESSAGEQUEUE *queue;
1345 if (!(queue = QUEUE_Current())) return 0;
1346 return CallNextHookEx16( queue->hCurHook, code, wParam, lParam );
1350 /***********************************************************************
1351 * CallMsgFilter (USER.123)
1353 BOOL16 WINAPI CallMsgFilter16( SEGPTR msg, INT16 code )
1355 if (GetSysModalWindow16()) return FALSE;
1356 if (HOOK_CallHooks16( WH_SYSMSGFILTER, code, 0, (LPARAM)msg )) return TRUE;
1357 return HOOK_CallHooks16( WH_MSGFILTER, code, 0, (LPARAM)msg );
1361 /***********************************************************************
1362 * CallMsgFilter32 (USER.823)
1364 BOOL16 WINAPI CallMsgFilter32_16( SEGPTR msg16_32, INT16 code, BOOL16 wHaveParamHigh )
1366 MSG32_16 *lpmsg16_32 = MapSL(msg16_32);
1368 if (wHaveParamHigh == FALSE)
1370 lpmsg16_32->wParamHigh = 0;
1371 /* WARNING: msg16_32->msg has to be the first variable in the struct */
1372 return CallMsgFilter16(msg16_32, code);
1379 msg32.hwnd = WIN_Handle32( lpmsg16_32->msg.hwnd );
1380 msg32.message = lpmsg16_32->msg.message;
1381 msg32.wParam = MAKELONG(lpmsg16_32->msg.wParam, lpmsg16_32->wParamHigh);
1382 msg32.lParam = lpmsg16_32->msg.lParam;
1383 msg32.time = lpmsg16_32->msg.time;
1384 msg32.pt.x = lpmsg16_32->msg.pt.x;
1385 msg32.pt.y = lpmsg16_32->msg.pt.y;
1387 ret = (BOOL16)CallMsgFilterA(&msg32, (INT)code);
1389 lpmsg16_32->msg.hwnd = WIN_Handle16( msg32.hwnd );
1390 lpmsg16_32->msg.message = msg32.message;
1391 lpmsg16_32->msg.wParam = LOWORD(msg32.wParam);
1392 lpmsg16_32->msg.lParam = msg32.lParam;
1393 lpmsg16_32->msg.time = msg32.time;
1394 lpmsg16_32->msg.pt.x = msg32.pt.x;
1395 lpmsg16_32->msg.pt.y = msg32.pt.y;
1396 lpmsg16_32->wParamHigh = HIWORD(msg32.wParam);
1403 /***********************************************************************
1404 * CallMsgFilterA (USER32.@)
1406 * FIXME: There are ANSI and UNICODE versions of this, plus an unspecified
1407 * version, plus USER (the 16bit one) has a CallMsgFilter32 function.
1409 BOOL WINAPI CallMsgFilterA( LPMSG msg, INT code )
1411 if (GetSysModalWindow16()) return FALSE; /* ??? */
1412 if (HOOK_CallHooksA( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
1414 return HOOK_CallHooksA( WH_MSGFILTER, code, 0, (LPARAM)msg );
1418 /***********************************************************************
1419 * CallMsgFilterW (USER32.@)
1421 BOOL WINAPI CallMsgFilterW( LPMSG msg, INT code )
1423 if (GetSysModalWindow16()) return FALSE; /* ??? */
1424 if (HOOK_CallHooksW( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
1426 return HOOK_CallHooksW( WH_MSGFILTER, code, 0, (LPARAM)msg );