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.
18 #include "wine/winuser16.h"
19 #include "wine/winbase16.h"
29 DEFAULT_DEBUG_CHANNEL(hook)
33 /* Hook data (pointed to by a HHOOK) */
36 HANDLE16 next; /* 00 Next hook in chain */
37 HOOKPROC proc WINE_PACKED; /* 02 Hook procedure */
38 INT16 id; /* 06 Hook id (WH_xxx) */
39 HQUEUE16 ownerQueue; /* 08 Owner queue (0 for system hook) */
40 HMODULE16 ownerModule; /* 0a Owner module */
41 WORD flags; /* 0c flags */
46 #define HOOK_MAGIC ((int)'H' | (int)'K' << 8) /* 'HK' */
48 /* This should probably reside in USER heap */
49 static HANDLE16 HOOK_systemHooks[WH_NB_HOOKS] = { 0, };
51 typedef VOID (*HOOK_MapFunc)(INT, INT, WPARAM *, LPARAM *);
52 typedef VOID (*HOOK_UnMapFunc)(INT, INT, WPARAM, LPARAM, WPARAM,
55 /***********************************************************************
56 * HOOK_Map16To32Common
58 static void HOOK_Map16To32Common(INT id, INT code, WPARAM *pwParam,
59 LPARAM *plParam, BOOL bA )
67 case WH_JOURNALRECORD:
69 LPMSG16 lpmsg16 = PTR_SEG_TO_LIN(*plParam);
70 LPMSG lpmsg32 = HeapAlloc( SystemHeap, 0, sizeof(*lpmsg32) );
72 STRUCT32_MSG16to32( lpmsg16, lpmsg32 );
73 *plParam = (LPARAM)lpmsg32;
77 case WH_JOURNALPLAYBACK:
79 LPEVENTMSG16 lpem16 = PTR_SEG_TO_LIN(*plParam);
80 LPEVENTMSG lpem32 = HeapAlloc( SystemHeap, 0, sizeof(*lpem32) );
82 lpem32->message = lpem16->message;
83 lpem32->paramL = lpem16->paramL;
84 lpem32->paramH = lpem16->paramH;
85 lpem32->time = lpem16->time;
86 lpem32->hwnd = 0; /* FIXME */
88 *plParam = (LPARAM)lpem32;
94 LPCWPSTRUCT16 lpcwp16 = PTR_SEG_TO_LIN(*plParam);
95 LPCWPSTRUCT lpcwp32 = HeapAlloc( SystemHeap, 0, sizeof(*lpcwp32) );
97 lpcwp32->hwnd = lpcwp16->hwnd;
98 lpcwp32->lParam = lpcwp16->lParam;
100 if (bA) WINPROC_MapMsg16To32A( lpcwp16->message, lpcwp16->wParam,
101 &lpcwp32->message, &lpcwp32->wParam,
103 else WINPROC_MapMsg16To32W( lpcwp16->hwnd,lpcwp16->message, lpcwp16->wParam,
104 &lpcwp32->message, &lpcwp32->wParam,
106 *plParam = (LPARAM)lpcwp32;
115 LPCBT_CREATEWND16 lpcbtcw16 = PTR_SEG_TO_LIN(*plParam);
116 LPCREATESTRUCT16 lpcs16 = PTR_SEG_TO_LIN(lpcbtcw16->lpcs);
117 LPCBT_CREATEWNDA lpcbtcw32 = HeapAlloc( SystemHeap, 0,
118 sizeof(*lpcbtcw32) );
119 lpcbtcw32->lpcs = HeapAlloc( SystemHeap, 0,
120 sizeof(*lpcbtcw32->lpcs) );
122 STRUCT32_CREATESTRUCT16to32A( lpcs16,
123 (LPCREATESTRUCTA)lpcbtcw32->lpcs );
125 if (HIWORD(lpcs16->lpszName))
126 lpcbtcw32->lpcs->lpszName =
127 (bA) ? PTR_SEG_TO_LIN(lpcs16->lpszName)
128 : HEAP_strdupAtoW( SystemHeap, 0,
129 PTR_SEG_TO_LIN(lpcs16->lpszName) );
131 lpcbtcw32->lpcs->lpszName = (LPCSTR)lpcs16->lpszName;
133 if (HIWORD(lpcs16->lpszClass))
134 lpcbtcw32->lpcs->lpszClass =
135 (bA) ? PTR_SEG_TO_LIN(lpcs16->lpszClass)
136 : HEAP_strdupAtoW( SystemHeap, 0,
137 PTR_SEG_TO_LIN(lpcs16->lpszClass) );
139 lpcbtcw32->lpcs->lpszClass = (LPCSTR)lpcs16->lpszClass;
141 lpcbtcw32->hwndInsertAfter = lpcbtcw16->hwndInsertAfter;
143 *plParam = (LPARAM)lpcbtcw32;
148 LPCBTACTIVATESTRUCT16 lpcas16 = PTR_SEG_TO_LIN(*plParam);
149 LPCBTACTIVATESTRUCT lpcas32 = HeapAlloc( SystemHeap, 0,
151 lpcas32->fMouse = lpcas16->fMouse;
152 lpcas32->hWndActive = lpcas16->hWndActive;
153 *plParam = (LPARAM)lpcas32;
156 case HCBT_CLICKSKIPPED:
158 LPMOUSEHOOKSTRUCT16 lpms16 = PTR_SEG_TO_LIN(*plParam);
159 LPMOUSEHOOKSTRUCT lpms32 = HeapAlloc( SystemHeap, 0,
162 CONV_POINT16TO32( &lpms16->pt, &lpms32->pt );
164 /* wHitTestCode may be negative, so convince compiler to do
165 correct sign extension. Yay. :| */
166 lpms32->wHitTestCode = (INT)((INT16)lpms16->wHitTestCode);
168 lpms32->dwExtraInfo = lpms16->dwExtraInfo;
169 lpms32->hwnd = lpms16->hwnd;
170 *plParam = (LPARAM)lpms32;
175 LPRECT16 lprect16 = PTR_SEG_TO_LIN(*plParam);
176 LPRECT lprect32 = HeapAlloc( SystemHeap, 0,
179 CONV_RECT16TO32( lprect16, lprect32 );
180 *plParam = (LPARAM)lprect32;
188 LPMOUSEHOOKSTRUCT16 lpms16 = PTR_SEG_TO_LIN(*plParam);
189 LPMOUSEHOOKSTRUCT lpms32 = HeapAlloc( SystemHeap, 0,
192 CONV_POINT16TO32( &lpms16->pt, &lpms32->pt );
194 /* wHitTestCode may be negative, so convince compiler to do
195 correct sign extension. Yay. :| */
196 lpms32->wHitTestCode = (INT)((INT16)lpms16->wHitTestCode);
197 lpms32->dwExtraInfo = lpms16->dwExtraInfo;
198 lpms32->hwnd = lpms16->hwnd;
199 *plParam = (LPARAM)lpms32;
205 LPDEBUGHOOKINFO16 lpdh16 = PTR_SEG_TO_LIN(*plParam);
206 LPDEBUGHOOKINFO lpdh32 = HeapAlloc( SystemHeap, 0,
209 lpdh32->idThread = 0; /* FIXME */
210 lpdh32->idThreadInstaller = 0; /* FIXME */
211 lpdh32->lParam = lpdh16->lParam; /* FIXME Check for sign ext */
212 lpdh32->wParam = lpdh16->wParam;
213 lpdh32->code = lpdh16->code;
215 /* do sign extension if it was WH_MSGFILTER */
216 if (*pwParam == 0xffff) *pwParam = WH_MSGFILTER;
218 *plParam = (LPARAM)lpdh32;
227 case WH_FOREGROUNDIDLE:
228 case WH_CALLWNDPROCRET:
229 FIXME(hook, "\t[%i] 16to32 translation unimplemented\n", id);
234 /***********************************************************************
237 static void HOOK_Map16To32A(INT id, INT code, WPARAM *pwParam,
240 HOOK_Map16To32Common( id, code, pwParam, plParam, TRUE );
244 /***********************************************************************
247 static void HOOK_Map16To32W(INT id, INT code, WPARAM *pwParam,
250 HOOK_Map16To32Common( id, code, pwParam, plParam, FALSE );
254 /***********************************************************************
255 * HOOK_UnMap16To32Common
257 static void HOOK_UnMap16To32Common(INT id, INT code, WPARAM wParamOrig,
258 LPARAM lParamOrig, WPARAM wParam,
259 LPARAM lParam, BOOL bA)
264 case WH_SYSMSGFILTER:
265 case WH_JOURNALRECORD:
266 case WH_JOURNALPLAYBACK:
268 HeapFree( SystemHeap, 0, (LPVOID)lParam );
273 LPCWPSTRUCT lpcwp32 = (LPCWPSTRUCT)lParam;
274 if (bA) WINPROC_UnmapMsg16To32A( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
275 lpcwp32->lParam, 0 );
276 else WINPROC_UnmapMsg16To32W( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
277 lpcwp32->lParam, 0 );
278 HeapFree( SystemHeap, 0, lpcwp32 );
284 LPMSG16 lpmsg16 = PTR_SEG_TO_LIN(lParamOrig);
285 STRUCT32_MSG32to16( (LPMSG)lParam, lpmsg16 );
286 HeapFree( SystemHeap, 0, (LPVOID)lParam );
293 HeapFree( SystemHeap, 0, (LPVOID)lParam );
301 LPCBT_CREATEWNDA lpcbtcw32 = (LPCBT_CREATEWNDA)lParam;
302 LPCBT_CREATEWND16 lpcbtcw16 = PTR_SEG_TO_LIN(lParamOrig);
306 if (HIWORD(lpcbtcw32->lpcs->lpszName))
307 HeapFree( SystemHeap, 0, (LPWSTR)lpcbtcw32->lpcs->lpszName );
308 if (HIWORD(lpcbtcw32->lpcs->lpszClass))
309 HeapFree( SystemHeap, 0, (LPWSTR)lpcbtcw32->lpcs->lpszClass );
312 lpcbtcw16->hwndInsertAfter = lpcbtcw32->hwndInsertAfter;
314 HeapFree( SystemHeap, 0, lpcbtcw32->lpcs );
318 case HCBT_CLICKSKIPPED:
321 HeapFree( SystemHeap, 0, (LPVOID)lParam);
331 case WH_FOREGROUNDIDLE:
332 case WH_CALLWNDPROCRET:
333 FIXME(hook, "\t[%i] skipping unmap\n", id);
339 /***********************************************************************
342 static void HOOK_UnMap16To32A(INT id, INT code, WPARAM wParamOrig,
343 LPARAM lParamOrig, WPARAM wParam,
346 HOOK_UnMap16To32Common( id, code, wParamOrig, lParamOrig, wParam,
351 /***********************************************************************
354 static void HOOK_UnMap16To32W(INT id, INT code, WPARAM wParamOrig,
355 LPARAM lParamOrig, WPARAM wParam,
358 HOOK_UnMap16To32Common( id, code, wParamOrig, lParamOrig, wParam,
363 /***********************************************************************
364 * HOOK_Map32To16Common
366 static void HOOK_Map32To16Common(INT id, INT code, WPARAM *pwParam,
367 LPARAM *plParam, BOOL bA)
372 case WH_SYSMSGFILTER:
374 case WH_JOURNALRECORD:
376 LPMSG lpmsg32 = (LPMSG)*plParam;
377 LPMSG16 lpmsg16 = SEGPTR_NEW( MSG16 );
379 STRUCT32_MSG32to16( lpmsg32, lpmsg16 );
381 *plParam = (LPARAM)SEGPTR_GET( lpmsg16 );
385 case WH_JOURNALPLAYBACK:
387 LPEVENTMSG lpem32 = (LPEVENTMSG)*plParam;
388 LPEVENTMSG16 lpem16 = SEGPTR_NEW( EVENTMSG16 );
390 lpem16->message = lpem32->message;
391 lpem16->paramL = lpem32->paramL;
392 lpem16->paramH = lpem32->paramH;
393 lpem16->time = lpem32->time;
395 *plParam = (LPARAM)SEGPTR_GET( lpem16 );
401 LPCWPSTRUCT lpcwp32 = (LPCWPSTRUCT)*plParam;
402 LPCWPSTRUCT16 lpcwp16 = SEGPTR_NEW( CWPSTRUCT16 );
404 lpcwp16->hwnd = lpcwp32->hwnd;
405 lpcwp16->lParam = lpcwp32->lParam;
407 if (bA) WINPROC_MapMsg32ATo16( lpcwp32->hwnd, lpcwp32->message,
408 lpcwp32->wParam, &lpcwp16->message,
409 &lpcwp16->wParam, &lpcwp16->lParam );
410 else WINPROC_MapMsg32WTo16( lpcwp32->hwnd, lpcwp32->message,
411 lpcwp32->wParam, &lpcwp16->message,
412 &lpcwp16->wParam, &lpcwp16->lParam );
413 *plParam = (LPARAM)SEGPTR_GET( lpcwp16 );
422 LPCBTACTIVATESTRUCT lpcas32 = (LPCBTACTIVATESTRUCT)*plParam;
423 LPCBTACTIVATESTRUCT16 lpcas16 =SEGPTR_NEW( CBTACTIVATESTRUCT16 );
425 lpcas16->fMouse = lpcas32->fMouse;
426 lpcas16->hWndActive = lpcas32->hWndActive;
428 *plParam = (LPARAM)SEGPTR_GET( lpcas16 );
432 case HCBT_CLICKSKIPPED:
434 LPMOUSEHOOKSTRUCT lpms32 = (LPMOUSEHOOKSTRUCT)*plParam;
435 LPMOUSEHOOKSTRUCT16 lpms16 = SEGPTR_NEW( MOUSEHOOKSTRUCT16 );
437 CONV_POINT32TO16( &lpms32->pt, &lpms16->pt );
439 lpms16->hwnd = lpms32->hwnd;
440 lpms16->wHitTestCode = lpms32->wHitTestCode;
441 lpms16->dwExtraInfo = lpms32->dwExtraInfo;
443 *plParam = (LPARAM)SEGPTR_GET( lpms16 );
449 LPRECT lprect32 = (LPRECT)*plParam;
450 LPRECT16 lprect16 = SEGPTR_NEW( RECT16 );
452 CONV_RECT32TO16( lprect32, lprect16 );
454 *plParam = (LPARAM)SEGPTR_GET( lprect16 );
462 LPMOUSEHOOKSTRUCT lpms32 = (LPMOUSEHOOKSTRUCT)*plParam;
463 LPMOUSEHOOKSTRUCT16 lpms16 = SEGPTR_NEW( MOUSEHOOKSTRUCT16 );
465 CONV_POINT32TO16( &lpms32->pt, &lpms16->pt );
467 lpms16->hwnd = lpms32->hwnd;
468 lpms16->wHitTestCode = lpms32->wHitTestCode;
469 lpms16->dwExtraInfo = lpms32->dwExtraInfo;
471 *plParam = (LPARAM)SEGPTR_GET( lpms16 );
477 LPDEBUGHOOKINFO lpdh32 = (LPDEBUGHOOKINFO)*plParam;
478 LPDEBUGHOOKINFO16 lpdh16 = SEGPTR_NEW( DEBUGHOOKINFO16 );
480 lpdh16->hModuleHook = 0; /* FIXME */
481 lpdh16->reserved = 0;
482 lpdh16->lParam = lpdh32->lParam;
483 lpdh16->wParam = lpdh32->wParam;
484 lpdh16->code = lpdh32->code;
486 *plParam = (LPARAM)SEGPTR_GET( lpdh16 );
495 case WH_FOREGROUNDIDLE:
496 case WH_CALLWNDPROCRET:
497 FIXME(hook,"\t[%i] 32to16 translation unimplemented\n", id);
502 /***********************************************************************
505 static void HOOK_Map32ATo16(INT id, INT code, WPARAM *pwParam,
508 if (id == WH_CBT && code == HCBT_CREATEWND)
510 LPCBT_CREATEWNDA lpcbtcw32 = (LPCBT_CREATEWNDA)*plParam;
511 LPCBT_CREATEWND16 lpcbtcw16 = SEGPTR_NEW( CBT_CREATEWND16 );
512 LPCREATESTRUCT16 lpcs16 = SEGPTR_NEW( CREATESTRUCT16 );
514 lpcbtcw16->lpcs = (LPCREATESTRUCT16)SEGPTR_GET( lpcs16 );
515 STRUCT32_CREATESTRUCT32Ato16( lpcbtcw32->lpcs, lpcs16 );
517 if (HIWORD(lpcbtcw32->lpcs->lpszName))
519 SEGPTR_GET( SEGPTR_STRDUP( lpcbtcw32->lpcs->lpszName ) );
521 lpcs16->lpszName = (SEGPTR)lpcbtcw32->lpcs->lpszName;
523 if (HIWORD(lpcbtcw32->lpcs->lpszClass))
525 SEGPTR_GET( SEGPTR_STRDUP( lpcbtcw32->lpcs->lpszClass ) );
527 lpcs16->lpszClass = (SEGPTR)lpcbtcw32->lpcs->lpszClass;
529 lpcbtcw16->hwndInsertAfter = lpcbtcw32->hwndInsertAfter;
531 *plParam = (LPARAM)SEGPTR_GET( lpcbtcw16 );
533 else HOOK_Map32To16Common(id, code, pwParam, plParam, TRUE);
537 /***********************************************************************
540 static void HOOK_Map32WTo16(INT id, INT code, WPARAM *pwParam,
543 if (id == WH_CBT && code == HCBT_CREATEWND)
546 LPCBT_CREATEWNDW lpcbtcw32 = (LPCBT_CREATEWNDW)*plParam;
547 LPCBT_CREATEWND16 lpcbtcw16 = SEGPTR_NEW( CBT_CREATEWND16 );
548 LPCREATESTRUCT16 lpcs16 = SEGPTR_NEW( CREATESTRUCT16 );
550 lpcbtcw16->lpcs = (LPCREATESTRUCT16)SEGPTR_GET( lpcs16 );
551 STRUCT32_CREATESTRUCT32Ato16( (LPCREATESTRUCTA)lpcbtcw32->lpcs,
554 name = SEGPTR_STRDUP_WtoA( lpcbtcw32->lpcs->lpszName );
555 cls = SEGPTR_STRDUP_WtoA( lpcbtcw32->lpcs->lpszClass );
556 lpcs16->lpszName = SEGPTR_GET( name );
557 lpcs16->lpszClass = SEGPTR_GET( cls );
558 lpcbtcw16->hwndInsertAfter = lpcbtcw32->hwndInsertAfter;
560 *plParam = (LPARAM)SEGPTR_GET( lpcbtcw16 );
562 else HOOK_Map32To16Common(id, code, pwParam, plParam, FALSE);
566 /***********************************************************************
567 * HOOK_UnMap32To16Common
569 static void HOOK_UnMap32To16Common(INT id, INT code, WPARAM wParamOrig,
570 LPARAM lParamOrig, WPARAM wParam,
571 LPARAM lParam, BOOL bA)
576 case WH_SYSMSGFILTER:
577 case WH_JOURNALRECORD:
578 case WH_JOURNALPLAYBACK:
581 SEGPTR_FREE( PTR_SEG_TO_LIN(lParam) );
586 LPCWPSTRUCT16 lpcwp16 = (LPCWPSTRUCT16)PTR_SEG_TO_LIN(lParam);
587 LPCWPSTRUCT lpcwp32 = (LPCWPSTRUCT)lParamOrig;
588 MSGPARAM16 mp16 = { lpcwp16->wParam, lpcwp16->lParam, 0 };
590 if (bA) WINPROC_UnmapMsg32ATo16( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
591 lpcwp32->lParam, &mp16 );
592 else WINPROC_UnmapMsg32WTo16( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
593 lpcwp32->lParam, &mp16 );
594 SEGPTR_FREE( PTR_SEG_TO_LIN(lParam) );
600 LPMSG lpmsg32 = (LPMSG)lParamOrig;
602 STRUCT32_MSG16to32( (LPMSG16)PTR_SEG_TO_LIN(lParam), lpmsg32 );
603 SEGPTR_FREE( PTR_SEG_TO_LIN(lParam) );
612 LPCBT_CREATEWNDA lpcbtcw32 = (LPCBT_CREATEWNDA)(lParamOrig);
613 LPCBT_CREATEWND16 lpcbtcw16 = PTR_SEG_TO_LIN(lParam);
614 LPCREATESTRUCT16 lpcs16 = PTR_SEG_TO_LIN(lpcbtcw16->lpcs);
616 if (HIWORD(lpcs16->lpszName))
617 SEGPTR_FREE( PTR_SEG_TO_LIN(lpcs16->lpszName) );
619 if (HIWORD(lpcs16->lpszClass))
620 SEGPTR_FREE( PTR_SEG_TO_LIN(lpcs16->lpszClass) );
622 lpcbtcw32->hwndInsertAfter = lpcbtcw16->hwndInsertAfter;
624 SEGPTR_FREE( lpcs16 );
628 case HCBT_CLICKSKIPPED:
631 SEGPTR_FREE( PTR_SEG_TO_LIN(lParam) );
641 case WH_FOREGROUNDIDLE:
642 case WH_CALLWNDPROCRET:
643 FIXME(hook, "\t[%i] skipping unmap\n", id);
648 /***********************************************************************
651 static void HOOK_UnMap32ATo16(INT id, INT code, WPARAM wParamOrig,
652 LPARAM lParamOrig, WPARAM wParam,
655 HOOK_UnMap32To16Common( id, code, wParamOrig, lParamOrig, wParam,
660 /***********************************************************************
663 static void HOOK_UnMap32WTo16(INT id, INT code, WPARAM wParamOrig,
664 LPARAM lParamOrig, WPARAM wParam,
667 HOOK_UnMap32To16Common( id, code, wParamOrig, lParamOrig, wParam,
672 /***********************************************************************
675 static void HOOK_Map32ATo32W(INT id, INT code, WPARAM *pwParam,
678 if (id == WH_CBT && code == HCBT_CREATEWND)
680 LPCBT_CREATEWNDA lpcbtcwA = (LPCBT_CREATEWNDA)*plParam;
681 LPCBT_CREATEWNDW lpcbtcwW = HeapAlloc( SystemHeap, 0,
683 lpcbtcwW->lpcs = HeapAlloc( SystemHeap, 0, sizeof(*lpcbtcwW->lpcs) );
685 lpcbtcwW->hwndInsertAfter = lpcbtcwA->hwndInsertAfter;
686 *lpcbtcwW->lpcs = *(LPCREATESTRUCTW)lpcbtcwA->lpcs;
688 if (HIWORD(lpcbtcwA->lpcs->lpszName))
690 lpcbtcwW->lpcs->lpszName = HEAP_strdupAtoW( SystemHeap, 0,
691 lpcbtcwA->lpcs->lpszName );
694 lpcbtcwW->lpcs->lpszName = (LPWSTR)lpcbtcwA->lpcs->lpszName;
696 if (HIWORD(lpcbtcwA->lpcs->lpszClass))
698 lpcbtcwW->lpcs->lpszClass = HEAP_strdupAtoW( SystemHeap, 0,
699 lpcbtcwA->lpcs->lpszClass );
702 lpcbtcwW->lpcs->lpszClass = (LPCWSTR)lpcbtcwA->lpcs->lpszClass;
703 *plParam = (LPARAM)lpcbtcwW;
709 /***********************************************************************
712 static void HOOK_UnMap32ATo32W(INT id, INT code, WPARAM wParamOrig,
713 LPARAM lParamOrig, WPARAM wParam,
716 if (id == WH_CBT && code == HCBT_CREATEWND)
718 LPCBT_CREATEWNDW lpcbtcwW = (LPCBT_CREATEWNDW)lParam;
719 if (HIWORD(lpcbtcwW->lpcs->lpszName))
720 HeapFree( SystemHeap, 0, (LPWSTR)lpcbtcwW->lpcs->lpszName );
721 if (HIWORD(lpcbtcwW->lpcs->lpszClass))
722 HeapFree( SystemHeap, 0, (LPWSTR)lpcbtcwW->lpcs->lpszClass );
723 HeapFree( SystemHeap, 0, lpcbtcwW->lpcs );
724 HeapFree( SystemHeap, 0, lpcbtcwW );
730 /***********************************************************************
733 static void HOOK_Map32WTo32A(INT id, INT code, WPARAM *pwParam,
736 if (id == WH_CBT && code == HCBT_CREATEWND)
738 LPCBT_CREATEWNDW lpcbtcwW = (LPCBT_CREATEWNDW)*plParam;
739 LPCBT_CREATEWNDA lpcbtcwA = HeapAlloc( SystemHeap, 0,
741 lpcbtcwA->lpcs = HeapAlloc( SystemHeap, 0, sizeof(*lpcbtcwA->lpcs) );
743 lpcbtcwA->hwndInsertAfter = lpcbtcwW->hwndInsertAfter;
744 *lpcbtcwA->lpcs = *(LPCREATESTRUCTA)lpcbtcwW->lpcs;
746 if (HIWORD(lpcbtcwW->lpcs->lpszName))
747 lpcbtcwA->lpcs->lpszName = HEAP_strdupWtoA( SystemHeap, 0,
748 lpcbtcwW->lpcs->lpszName );
750 lpcbtcwA->lpcs->lpszName = (LPSTR)lpcbtcwW->lpcs->lpszName;
752 if (HIWORD(lpcbtcwW->lpcs->lpszClass))
753 lpcbtcwA->lpcs->lpszClass = HEAP_strdupWtoA( SystemHeap, 0,
754 lpcbtcwW->lpcs->lpszClass );
756 lpcbtcwA->lpcs->lpszClass = (LPSTR)lpcbtcwW->lpcs->lpszClass;
757 *plParam = (LPARAM)lpcbtcwA;
763 /***********************************************************************
766 static void HOOK_UnMap32WTo32A(INT id, INT code, WPARAM wParamOrig,
767 LPARAM lParamOrig, WPARAM wParam,
770 if (id == WH_CBT && code == HCBT_CREATEWND)
772 LPCBT_CREATEWNDA lpcbtcwA = (LPCBT_CREATEWNDA)lParam;
773 if (HIWORD(lpcbtcwA->lpcs->lpszName))
774 HeapFree( SystemHeap, 0, (LPSTR)lpcbtcwA->lpcs->lpszName );
775 if (HIWORD(lpcbtcwA->lpcs->lpszClass))
776 HeapFree( SystemHeap, 0, (LPSTR)lpcbtcwA->lpcs->lpszClass );
777 HeapFree( SystemHeap, 0, lpcbtcwA->lpcs );
778 HeapFree( SystemHeap, 0, lpcbtcwA );
784 /***********************************************************************
785 * Map Function Tables
787 static const HOOK_MapFunc HOOK_MapFuncs[3][3] =
789 { NULL, HOOK_Map16To32A, HOOK_Map16To32W },
790 { HOOK_Map32ATo16, NULL, HOOK_Map32ATo32W },
791 { HOOK_Map32WTo16, HOOK_Map32WTo32A, NULL }
794 static const HOOK_UnMapFunc HOOK_UnMapFuncs[3][3] =
796 { NULL, HOOK_UnMap16To32A, HOOK_UnMap16To32W },
797 { HOOK_UnMap32ATo16, NULL, HOOK_UnMap32ATo32W },
798 { HOOK_UnMap32WTo16, HOOK_UnMap32WTo32A, NULL }
802 /***********************************************************************
806 /***********************************************************************
809 * Get the next hook of a given hook.
811 static HANDLE16 HOOK_GetNextHook( HANDLE16 hook )
813 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR( hook );
815 if (!data || !hook) return 0;
816 if (data->next) return data->next;
817 if (!data->ownerQueue) return 0; /* Already system hook */
819 /* Now start enumerating the system hooks */
820 return HOOK_systemHooks[data->id - WH_MINHOOK];
824 /***********************************************************************
827 * Get the first hook for a given type.
829 static HANDLE16 HOOK_GetHook( INT16 id, HQUEUE16 hQueue )
834 if ((queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue )) != NULL)
835 hook = queue->hooks[id - WH_MINHOOK];
836 if (!hook) hook = HOOK_systemHooks[id - WH_MINHOOK];
838 QUEUE_Unlock( queue );
843 /***********************************************************************
846 * Install a given hook.
848 static HHOOK HOOK_SetHook( INT16 id, LPVOID proc, INT type,
849 HMODULE16 hModule, DWORD dwThreadId )
855 if ((id < WH_MINHOOK) || (id > WH_MAXHOOK)) return 0;
857 TRACE(hook, "Setting hook %d: %08x %04x %08lx\n",
858 id, (UINT)proc, hModule, dwThreadId );
860 /* Create task queue if none present */
863 if (id == WH_JOURNALPLAYBACK) EnableHardwareInput16(FALSE);
865 if (dwThreadId) /* Task-specific hook */
867 if ((id == WH_JOURNALRECORD) || (id == WH_JOURNALPLAYBACK) ||
868 (id == WH_SYSMSGFILTER)) return 0; /* System-only hooks */
869 if (!(hQueue = GetThreadQueue16( dwThreadId )))
873 /* Create the hook structure */
875 if (!(handle = USER_HEAP_ALLOC( sizeof(HOOKDATA) ))) return 0;
876 data = (HOOKDATA *) USER_HEAP_LIN_ADDR( handle );
879 data->ownerQueue = hQueue;
880 data->ownerModule = hModule;
883 /* Insert it in the correct linked list */
887 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue );
888 data->next = queue->hooks[id - WH_MINHOOK];
889 queue->hooks[id - WH_MINHOOK] = handle;
890 QUEUE_Unlock( queue );
894 data->next = HOOK_systemHooks[id - WH_MINHOOK];
895 HOOK_systemHooks[id - WH_MINHOOK] = handle;
897 TRACE(hook, "Setting hook %d: ret=%04x [next=%04x]\n",
898 id, handle, data->next );
900 return (HHOOK)( handle? MAKELONG( handle, HOOK_MAGIC ) : 0 );
904 /***********************************************************************
907 * Remove a hook from the list.
909 static BOOL HOOK_RemoveHook( HANDLE16 hook )
914 TRACE(hook, "Removing hook %04x\n", hook );
916 if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook))) return FALSE;
917 if (data->flags & HOOK_INUSE)
919 /* Mark it for deletion later on */
920 WARN(hook, "Hook still running, deletion delayed\n" );
921 data->proc = (HOOKPROC)0;
925 if (data->id == WH_JOURNALPLAYBACK) EnableHardwareInput16(TRUE);
927 /* Remove it from the linked list */
929 if (data->ownerQueue)
931 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( data->ownerQueue );
932 if (!queue) return FALSE;
933 prevHook = &queue->hooks[data->id - WH_MINHOOK];
934 QUEUE_Unlock( queue );
936 else prevHook = &HOOK_systemHooks[data->id - WH_MINHOOK];
938 while (*prevHook && *prevHook != hook)
939 prevHook = &((HOOKDATA *)USER_HEAP_LIN_ADDR(*prevHook))->next;
941 if (!*prevHook) return FALSE;
942 *prevHook = data->next;
943 USER_HEAP_FREE( hook );
948 /***********************************************************************
951 static HANDLE16 HOOK_FindValidHook( HANDLE16 hook )
957 if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook))) return 0;
958 if (data->proc) return hook;
964 /***********************************************************************
967 * Call a hook procedure.
969 static LRESULT HOOK_CallHook( HANDLE16 hook, INT fromtype, INT code,
970 WPARAM wParam, LPARAM lParam )
974 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
977 WPARAM wParamOrig = wParam;
978 LPARAM lParamOrig = lParam;
979 HOOK_MapFunc MapFunc;
980 HOOK_UnMapFunc UnMapFunc;
982 MapFunc = HOOK_MapFuncs[fromtype][data->flags & HOOK_MAPTYPE];
983 UnMapFunc = HOOK_UnMapFuncs[fromtype][data->flags & HOOK_MAPTYPE];
986 MapFunc( data->id, code, &wParam, &lParam );
990 if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() ))) return 0;
991 prevHook = queue->hCurHook;
992 queue->hCurHook = hook;
993 data->flags |= HOOK_INUSE;
995 TRACE(hook, "Calling hook %04x: %d %08x %08lx\n",
996 hook, code, wParam, lParam );
998 ret = data->proc(code, wParam, lParam);
1000 /* Grrr. While the hook procedure is supposed to have an LRESULT return
1001 value even in Win16, it seems that for those hook types where the
1002 return value is interpreted as BOOL, Windows doesn't actually check
1003 the HIWORD ... Some buggy Win16 programs, notably WINFILE, rely on
1004 that, because they neglect to clear DX ... */
1005 if ( (data->flags & HOOK_MAPTYPE) == HOOK_WIN16
1006 && data->id != WH_JOURNALPLAYBACK )
1007 ret = LOWORD( ret );
1009 TRACE(hook, "Ret hook %04x = %08lx\n", hook, ret );
1011 data->flags &= ~HOOK_INUSE;
1012 queue->hCurHook = prevHook;
1014 QUEUE_Unlock( queue );
1017 UnMapFunc( data->id, code, wParamOrig, lParamOrig, wParam, lParam );
1019 if (!data->proc) HOOK_RemoveHook( hook );
1024 /***********************************************************************
1025 * Exported Functions & APIs
1028 /***********************************************************************
1031 * Don't call this unless you are the if1632/thunk.c.
1033 HOOKPROC16 HOOK_GetProc16( HHOOK hhook )
1036 if (HIWORD(hhook) != HOOK_MAGIC) return NULL;
1037 if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR( LOWORD(hhook) ))) return NULL;
1038 if ((data->flags & HOOK_MAPTYPE) != HOOK_WIN16) return NULL;
1039 return (HOOKPROC16)data->proc;
1043 /***********************************************************************
1046 * Replacement for calling HOOK_GetHook from other modules.
1048 BOOL HOOK_IsHooked( INT16 id )
1050 /* Hmmm. Use GetThreadQueue(0) instead of GetFastQueue() here to
1051 avoid queue being created if someone wants to merely check ... */
1053 return HOOK_GetHook( id, GetThreadQueue16(0) ) != 0;
1057 /***********************************************************************
1060 * Call a hook chain.
1062 LRESULT HOOK_CallHooks16( INT16 id, INT16 code, WPARAM16 wParam,
1067 if (!(hook = HOOK_GetHook( id, GetFastQueue16() ))) return 0;
1068 if (!(hook = HOOK_FindValidHook(hook))) return 0;
1069 return HOOK_CallHook( hook, HOOK_WIN16, code, wParam, lParam );
1072 /***********************************************************************
1075 * Call a hook chain.
1077 LRESULT HOOK_CallHooksA( INT id, INT code, WPARAM wParam,
1082 if (!(hook = HOOK_GetHook( id, GetFastQueue16() ))) return 0;
1083 if (!(hook = HOOK_FindValidHook(hook))) return 0;
1084 return HOOK_CallHook( hook, HOOK_WIN32A, code, wParam, lParam );
1087 /***********************************************************************
1090 * Call a hook chain.
1092 LRESULT HOOK_CallHooksW( INT id, INT code, WPARAM wParam,
1097 if (!(hook = HOOK_GetHook( id, GetFastQueue16() ))) return 0;
1098 if (!(hook = HOOK_FindValidHook(hook))) return 0;
1099 return HOOK_CallHook( hook, HOOK_WIN32W, code, wParam,
1104 /***********************************************************************
1105 * HOOK_ResetQueueHooks
1107 void HOOK_ResetQueueHooks( HQUEUE16 hQueue )
1109 MESSAGEQUEUE *queue;
1111 if ((queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue )) != NULL)
1116 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
1118 hook = queue->hooks[id - WH_MINHOOK];
1121 if( (data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook)) )
1123 data->ownerQueue = hQueue;
1129 QUEUE_Unlock( queue );
1133 /***********************************************************************
1134 * HOOK_FreeModuleHooks
1136 void HOOK_FreeModuleHooks( HMODULE16 hModule )
1138 /* remove all system hooks registered by this module */
1144 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
1146 hook = HOOK_systemHooks[id - WH_MINHOOK];
1148 if( (hptr = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook)) )
1151 if( hptr->ownerModule == hModule )
1153 hptr->flags &= HOOK_MAPTYPE;
1154 HOOK_RemoveHook(hook);
1162 /***********************************************************************
1163 * HOOK_FreeQueueHooks
1165 void HOOK_FreeQueueHooks( HQUEUE16 hQueue )
1167 /* remove all hooks registered by this queue */
1169 HOOKDATA* hptr = NULL;
1173 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
1175 hook = HOOK_GetHook( id, hQueue );
1178 next = HOOK_GetNextHook(hook);
1180 hptr = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
1181 if( hptr && hptr->ownerQueue == hQueue )
1183 hptr->flags &= HOOK_MAPTYPE;
1184 HOOK_RemoveHook(hook);
1192 /***********************************************************************
1193 * SetWindowsHook16 (USER.121)
1195 FARPROC16 WINAPI SetWindowsHook16( INT16 id, HOOKPROC16 proc )
1197 HINSTANCE16 hInst = FarGetOwner16( HIWORD(proc) );
1199 /* WH_MSGFILTER is the only task-specific hook for SetWindowsHook() */
1200 HTASK16 hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
1202 return (FARPROC16)SetWindowsHookEx16( id, proc, hInst, hTask );
1205 /***********************************************************************
1206 * SetWindowsHook32A (USER32.525)
1208 HHOOK WINAPI SetWindowsHookA( INT id, HOOKPROC proc )
1210 return SetWindowsHookExA( id, proc, 0, GetCurrentThreadId() );
1213 /***********************************************************************
1214 * SetWindowsHook32W (USER32.528)
1216 HHOOK WINAPI SetWindowsHookW( INT id, HOOKPROC proc )
1218 return SetWindowsHookExW( id, proc, 0, GetCurrentThreadId() );
1222 /***********************************************************************
1223 * SetWindowsHookEx16 (USER.291)
1225 HHOOK WINAPI SetWindowsHookEx16( INT16 id, HOOKPROC16 proc, HINSTANCE16 hInst,
1230 FIXME(hook, "WH_DEBUG is broken in 16-bit Windows.\n");
1233 return HOOK_SetHook( id, proc, HOOK_WIN16, GetExePtr(hInst), (DWORD)hTask );
1236 /***********************************************************************
1237 * SetWindowsHookEx32A (USER32.526)
1239 HHOOK WINAPI SetWindowsHookExA( INT id, HOOKPROC proc, HINSTANCE hInst,
1242 return HOOK_SetHook( id, proc, HOOK_WIN32A, MapHModuleLS(hInst), dwThreadId );
1245 /***********************************************************************
1246 * SetWindowsHookEx32W (USER32.527)
1248 HHOOK WINAPI SetWindowsHookExW( INT id, HOOKPROC proc, HINSTANCE hInst,
1251 return HOOK_SetHook( id, proc, HOOK_WIN32W, MapHModuleLS(hInst), dwThreadId );
1255 /***********************************************************************
1256 * UnhookWindowsHook16 (USER.234)
1258 BOOL16 WINAPI UnhookWindowsHook16( INT16 id, HOOKPROC16 proc )
1260 return UnhookWindowsHook( id, (HOOKPROC)proc );
1263 /***********************************************************************
1264 * UnhookWindowsHook32 (USER32.557)
1266 BOOL WINAPI UnhookWindowsHook( INT id, HOOKPROC proc )
1268 HANDLE16 hook = HOOK_GetHook( id, GetFastQueue16() );
1270 TRACE(hook, "%d %08lx\n", id, (DWORD)proc );
1274 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
1275 if (data->proc == proc) break;
1276 hook = HOOK_GetNextHook( hook );
1278 if (!hook) return FALSE;
1279 return HOOK_RemoveHook( hook );
1283 /***********************************************************************
1284 * UnhookWindowHookEx16 (USER.292)
1286 BOOL16 WINAPI UnhookWindowsHookEx16( HHOOK hhook )
1288 return UnhookWindowsHookEx( hhook );
1291 /***********************************************************************
1292 * UnhookWindowHookEx32 (USER32.558)
1294 BOOL WINAPI UnhookWindowsHookEx( HHOOK hhook )
1296 if (HIWORD(hhook) != HOOK_MAGIC) return FALSE; /* Not a new format hook */
1297 return HOOK_RemoveHook( LOWORD(hhook) );
1301 /***********************************************************************
1302 * CallNextHookEx16 (USER.293)
1304 * I wouldn't have separated this into 16 and 32 bit versions, but I
1305 * need a way to figure out if I need to do a mapping or not.
1307 LRESULT WINAPI CallNextHookEx16( HHOOK hhook, INT16 code, WPARAM16 wParam,
1312 if (HIWORD(hhook) != HOOK_MAGIC) return 0; /* Not a new format hook */
1313 if (!(next = HOOK_GetNextHook( LOWORD(hhook) ))) return 0;
1315 return HOOK_CallHook( next, HOOK_WIN16, code, wParam, lParam );
1319 /***********************************************************************
1320 * CallNextHookEx32 (USER32.17)
1322 * There aren't ANSI and UNICODE versions of this.
1324 LRESULT WINAPI CallNextHookEx( HHOOK hhook, INT code, WPARAM wParam,
1328 INT fromtype; /* figure out Ansi/Unicode */
1331 if (HIWORD(hhook) != HOOK_MAGIC) return 0; /* Not a new format hook */
1332 if (!(next = HOOK_GetNextHook( LOWORD(hhook) ))) return 0;
1334 oldhook = (HOOKDATA *)USER_HEAP_LIN_ADDR( LOWORD(hhook) );
1335 fromtype = oldhook->flags & HOOK_MAPTYPE;
1337 if (fromtype == HOOK_WIN16)
1338 ERR(hook, "called from 16bit hook!\n");
1340 return HOOK_CallHook( next, fromtype, code, wParam, lParam );
1344 /***********************************************************************
1345 * DefHookProc16 (USER.235)
1347 LRESULT WINAPI DefHookProc16( INT16 code, WPARAM16 wParam, LPARAM lParam,
1350 /* Note: the *hhook parameter is never used, since we rely on the
1351 * current hook value from the task queue to find the next hook. */
1352 MESSAGEQUEUE *queue;
1355 if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() ))) return 0;
1356 ret = CallNextHookEx16( queue->hCurHook, code, wParam, lParam );
1357 QUEUE_Unlock( queue );
1362 /***********************************************************************
1363 * CallMsgFilter16 (USER.123)
1365 BOOL16 WINAPI CallMsgFilter16( SEGPTR msg, INT16 code )
1367 if (GetSysModalWindow16()) return FALSE;
1368 if (HOOK_CallHooks16( WH_SYSMSGFILTER, code, 0, (LPARAM)msg )) return TRUE;
1369 return HOOK_CallHooks16( WH_MSGFILTER, code, 0, (LPARAM)msg );
1373 /***********************************************************************
1374 * WIN16_CallMsgFilter32 (USER.823)
1376 BOOL16 WINAPI CallMsgFilter32_16( SEGPTR msg16_32, INT16 code, BOOL16 wHaveParamHigh )
1378 MSG32_16 *lpmsg16_32 = (MSG32_16 *)PTR_SEG_TO_LIN(msg16_32);
1380 if (wHaveParamHigh == FALSE)
1382 lpmsg16_32->wParamHigh = 0;
1383 /* WARNING: msg16_32->msg has to be the first variable in the struct */
1384 return CallMsgFilter16(msg16_32, code);
1391 msg32.hwnd = lpmsg16_32->msg.hwnd;
1392 msg32.message = lpmsg16_32->msg.message;
1394 MAKELONG(lpmsg16_32->msg.wParam, lpmsg16_32->wParamHigh);
1395 msg32.lParam = lpmsg16_32->msg.lParam;
1396 msg32.time = lpmsg16_32->msg.time;
1397 msg32.pt.x = (INT)lpmsg16_32->msg.pt.x;
1398 msg32.pt.y = (INT)lpmsg16_32->msg.pt.y;
1400 ret = (BOOL16)CallMsgFilterA(&msg32, (INT)code);
1402 lpmsg16_32->msg.hwnd = msg32.hwnd;
1403 lpmsg16_32->msg.message = msg32.message;
1404 lpmsg16_32->msg.wParam = LOWORD(msg32.wParam);
1405 lpmsg16_32->msg.lParam = msg32.lParam;
1406 lpmsg16_32->msg.time = msg32.time;
1407 lpmsg16_32->msg.pt.x = (INT16)msg32.pt.x;
1408 lpmsg16_32->msg.pt.y = (INT16)msg32.pt.y;
1409 lpmsg16_32->wParamHigh = HIWORD(msg32.wParam);
1416 /***********************************************************************
1417 * CallMsgFilter32A (USER32.15)
1420 * FIXME: There are ANSI and UNICODE versions of this, plus an unspecified
1421 * version, plus USER (the 16bit one) has a CallMsgFilter32 function.
1423 BOOL WINAPI CallMsgFilterA( LPMSG msg, INT code )
1425 if (GetSysModalWindow16()) return FALSE; /* ??? */
1426 if (HOOK_CallHooksA( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
1428 return HOOK_CallHooksA( WH_MSGFILTER, code, 0, (LPARAM)msg );
1432 /***********************************************************************
1433 * CallMsgFilter32W (USER32.16)
1435 BOOL WINAPI CallMsgFilterW( LPMSG msg, INT code )
1437 if (GetSysModalWindow16()) return FALSE; /* ??? */
1438 if (HOOK_CallHooksW( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
1440 return HOOK_CallHooksW( WH_MSGFILTER, code, 0, (LPARAM)msg );