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 typedef VOID (*HOOK_MapFunc)(INT, INT, WPARAM *, LPARAM *);
55 typedef VOID (*HOOK_UnMapFunc)(INT, INT, WPARAM, LPARAM, WPARAM,
58 /***********************************************************************
59 * HOOK_Map16To32Common
61 static void HOOK_Map16To32Common(INT id, INT code, WPARAM *pwParam,
62 LPARAM *plParam, BOOL bA )
70 case WH_JOURNALRECORD:
72 LPMSG16 lpmsg16 = MapSL(*plParam);
73 LPMSG lpmsg32 = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpmsg32) );
75 STRUCT32_MSG16to32( lpmsg16, lpmsg32 );
76 *plParam = (LPARAM)lpmsg32;
80 case WH_JOURNALPLAYBACK:
82 LPEVENTMSG16 lpem16 = MapSL(*plParam);
83 LPEVENTMSG lpem32 = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpem32) );
85 lpem32->message = lpem16->message;
86 lpem32->paramL = lpem16->paramL;
87 lpem32->paramH = lpem16->paramH;
88 lpem32->time = lpem16->time;
89 lpem32->hwnd = 0; /* FIXME */
91 *plParam = (LPARAM)lpem32;
97 LPCWPSTRUCT16 lpcwp16 = MapSL(*plParam);
98 LPCWPSTRUCT lpcwp32 = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpcwp32) );
100 lpcwp32->hwnd = WIN_Handle32(lpcwp16->hwnd);
101 lpcwp32->lParam = lpcwp16->lParam;
103 if (bA) WINPROC_MapMsg16To32A( lpcwp32->hwnd, lpcwp16->message, lpcwp16->wParam,
104 &lpcwp32->message, &lpcwp32->wParam,
106 else WINPROC_MapMsg16To32W( lpcwp32->hwnd,lpcwp16->message, lpcwp16->wParam,
107 &lpcwp32->message, &lpcwp32->wParam,
109 *plParam = (LPARAM)lpcwp32;
118 LPCBT_CREATEWND16 lpcbtcw16 = MapSL(*plParam);
119 LPCREATESTRUCT16 lpcs16 = MapSL((SEGPTR)lpcbtcw16->lpcs);
120 LPCBT_CREATEWNDA lpcbtcw32 = HeapAlloc( GetProcessHeap(), 0,
121 sizeof(*lpcbtcw32) );
122 lpcbtcw32->lpcs = HeapAlloc( GetProcessHeap(), 0,
123 sizeof(*lpcbtcw32->lpcs) );
125 STRUCT32_CREATESTRUCT16to32A( lpcs16,
126 (LPCREATESTRUCTA)lpcbtcw32->lpcs );
128 if (HIWORD(lpcs16->lpszName))
129 lpcbtcw32->lpcs->lpszName =
130 (bA) ? MapSL(lpcs16->lpszName)
131 : HEAP_strdupAtoW( GetProcessHeap(), 0,
132 MapSL(lpcs16->lpszName) );
134 lpcbtcw32->lpcs->lpszName = (LPCSTR)lpcs16->lpszName;
136 if (HIWORD(lpcs16->lpszClass))
137 lpcbtcw32->lpcs->lpszClass =
138 (bA) ? MapSL(lpcs16->lpszClass)
139 : HEAP_strdupAtoW( GetProcessHeap(), 0,
140 MapSL(lpcs16->lpszClass) );
142 lpcbtcw32->lpcs->lpszClass = (LPCSTR)lpcs16->lpszClass;
144 lpcbtcw32->hwndInsertAfter = WIN_Handle32( lpcbtcw16->hwndInsertAfter );
146 *plParam = (LPARAM)lpcbtcw32;
151 LPCBTACTIVATESTRUCT16 lpcas16 = MapSL(*plParam);
152 LPCBTACTIVATESTRUCT lpcas32 = HeapAlloc( GetProcessHeap(), 0,
154 lpcas32->fMouse = lpcas16->fMouse;
155 lpcas32->hWndActive = WIN_Handle32(lpcas16->hWndActive);
156 *plParam = (LPARAM)lpcas32;
159 case HCBT_CLICKSKIPPED:
161 LPMOUSEHOOKSTRUCT16 lpms16 = MapSL(*plParam);
162 LPMOUSEHOOKSTRUCT lpms32 = HeapAlloc( GetProcessHeap(), 0,
165 CONV_POINT16TO32( &lpms16->pt, &lpms32->pt );
167 /* wHitTestCode may be negative, so convince compiler to do
168 correct sign extension. Yay. :| */
169 lpms32->wHitTestCode = (INT)((INT16)lpms16->wHitTestCode);
171 lpms32->dwExtraInfo = lpms16->dwExtraInfo;
172 lpms32->hwnd = WIN_Handle32( lpms16->hwnd );
173 *plParam = (LPARAM)lpms32;
178 LPRECT16 lprect16 = MapSL(*plParam);
179 LPRECT lprect32 = HeapAlloc( GetProcessHeap(), 0,
182 CONV_RECT16TO32( lprect16, lprect32 );
183 *plParam = (LPARAM)lprect32;
191 LPMOUSEHOOKSTRUCT16 lpms16 = MapSL(*plParam);
192 LPMOUSEHOOKSTRUCT lpms32 = HeapAlloc( GetProcessHeap(), 0,
195 CONV_POINT16TO32( &lpms16->pt, &lpms32->pt );
197 /* wHitTestCode may be negative, so convince compiler to do
198 correct sign extension. Yay. :| */
199 lpms32->wHitTestCode = (INT)((INT16)lpms16->wHitTestCode);
200 lpms32->dwExtraInfo = lpms16->dwExtraInfo;
201 lpms32->hwnd = WIN_Handle32(lpms16->hwnd);
202 *plParam = (LPARAM)lpms32;
208 LPDEBUGHOOKINFO16 lpdh16 = MapSL(*plParam);
209 LPDEBUGHOOKINFO lpdh32 = HeapAlloc( GetProcessHeap(), 0,
212 lpdh32->idThread = 0; /* FIXME */
213 lpdh32->idThreadInstaller = 0; /* FIXME */
214 lpdh32->lParam = lpdh16->lParam; /* FIXME Check for sign ext */
215 lpdh32->wParam = lpdh16->wParam;
216 lpdh32->code = lpdh16->code;
218 /* do sign extension if it was WH_MSGFILTER */
219 if (*pwParam == 0xffff) *pwParam = WH_MSGFILTER;
221 *plParam = (LPARAM)lpdh32;
230 case WH_FOREGROUNDIDLE:
231 case WH_CALLWNDPROCRET:
233 FIXME("\t[%i] 16to32 translation unimplemented\n", id);
238 /***********************************************************************
241 static void HOOK_Map16To32A(INT id, INT code, WPARAM *pwParam,
244 HOOK_Map16To32Common( id, code, pwParam, plParam, TRUE );
248 /***********************************************************************
251 static void HOOK_Map16To32W(INT id, INT code, WPARAM *pwParam,
254 HOOK_Map16To32Common( id, code, pwParam, plParam, FALSE );
258 /***********************************************************************
259 * HOOK_UnMap16To32Common
261 static void HOOK_UnMap16To32Common(INT id, INT code, WPARAM wParamOrig,
262 LPARAM lParamOrig, WPARAM wParam,
263 LPARAM lParam, BOOL bA)
268 case WH_SYSMSGFILTER:
269 case WH_JOURNALRECORD:
270 case WH_JOURNALPLAYBACK:
272 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
277 LPCWPSTRUCT lpcwp32 = (LPCWPSTRUCT)lParam;
278 if (bA) WINPROC_UnmapMsg16To32A( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
279 lpcwp32->lParam, 0 );
280 else WINPROC_UnmapMsg16To32W( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
281 lpcwp32->lParam, 0 );
282 HeapFree( GetProcessHeap(), 0, lpcwp32 );
288 LPMSG16 lpmsg16 = MapSL(lParamOrig);
289 STRUCT32_MSG32to16( (LPMSG)lParam, lpmsg16 );
290 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
297 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
305 LPCBT_CREATEWNDA lpcbtcw32 = (LPCBT_CREATEWNDA)lParam;
306 LPCBT_CREATEWND16 lpcbtcw16 = MapSL(lParamOrig);
310 if (HIWORD(lpcbtcw32->lpcs->lpszName))
311 HeapFree( GetProcessHeap(), 0, (LPWSTR)lpcbtcw32->lpcs->lpszName );
312 if (HIWORD(lpcbtcw32->lpcs->lpszClass))
313 HeapFree( GetProcessHeap(), 0, (LPWSTR)lpcbtcw32->lpcs->lpszClass );
316 lpcbtcw16->hwndInsertAfter = WIN_Handle16( lpcbtcw32->hwndInsertAfter );
318 HeapFree( GetProcessHeap(), 0, lpcbtcw32->lpcs );
322 case HCBT_CLICKSKIPPED:
325 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam);
335 case WH_FOREGROUNDIDLE:
336 case WH_CALLWNDPROCRET:
338 FIXME("\t[%i] skipping unmap\n", id);
344 /***********************************************************************
347 static void HOOK_UnMap16To32A(INT id, INT code, WPARAM wParamOrig,
348 LPARAM lParamOrig, WPARAM wParam,
351 HOOK_UnMap16To32Common( id, code, wParamOrig, lParamOrig, wParam,
356 /***********************************************************************
359 static void HOOK_UnMap16To32W(INT id, INT code, WPARAM wParamOrig,
360 LPARAM lParamOrig, WPARAM wParam,
363 HOOK_UnMap16To32Common( id, code, wParamOrig, lParamOrig, wParam,
368 /***********************************************************************
369 * HOOK_Map32To16Common
371 static void HOOK_Map32To16Common(INT id, INT code, WPARAM *pwParam,
372 LPARAM *plParam, BOOL bA)
377 case WH_SYSMSGFILTER:
379 case WH_JOURNALRECORD:
381 LPMSG lpmsg32 = (LPMSG)*plParam;
382 LPMSG16 lpmsg16 = SEGPTR_NEW( MSG16 );
384 STRUCT32_MSG32to16( lpmsg32, lpmsg16 );
386 *plParam = (LPARAM)SEGPTR_GET( lpmsg16 );
390 case WH_JOURNALPLAYBACK:
392 LPEVENTMSG lpem32 = (LPEVENTMSG)*plParam;
393 LPEVENTMSG16 lpem16 = SEGPTR_NEW( EVENTMSG16 );
395 lpem16->message = lpem32->message;
396 lpem16->paramL = lpem32->paramL;
397 lpem16->paramH = lpem32->paramH;
398 lpem16->time = lpem32->time;
400 *plParam = (LPARAM)SEGPTR_GET( lpem16 );
406 LPCWPSTRUCT lpcwp32 = (LPCWPSTRUCT)*plParam;
407 LPCWPSTRUCT16 lpcwp16 = SEGPTR_NEW( CWPSTRUCT16 );
409 lpcwp16->hwnd = WIN_Handle16(lpcwp32->hwnd);
410 lpcwp16->lParam = lpcwp32->lParam;
412 if (bA) WINPROC_MapMsg32ATo16( lpcwp32->hwnd, lpcwp32->message,
413 lpcwp32->wParam, &lpcwp16->message,
414 &lpcwp16->wParam, &lpcwp16->lParam );
415 else WINPROC_MapMsg32WTo16( lpcwp32->hwnd, lpcwp32->message,
416 lpcwp32->wParam, &lpcwp16->message,
417 &lpcwp16->wParam, &lpcwp16->lParam );
418 *plParam = (LPARAM)SEGPTR_GET( lpcwp16 );
427 LPCBTACTIVATESTRUCT lpcas32 = (LPCBTACTIVATESTRUCT)*plParam;
428 LPCBTACTIVATESTRUCT16 lpcas16 =SEGPTR_NEW( CBTACTIVATESTRUCT16 );
430 lpcas16->fMouse = lpcas32->fMouse;
431 lpcas16->hWndActive = WIN_Handle16( lpcas32->hWndActive );
433 *plParam = (LPARAM)SEGPTR_GET( lpcas16 );
437 case HCBT_CLICKSKIPPED:
439 LPMOUSEHOOKSTRUCT lpms32 = (LPMOUSEHOOKSTRUCT)*plParam;
440 LPMOUSEHOOKSTRUCT16 lpms16 = SEGPTR_NEW( MOUSEHOOKSTRUCT16 );
442 CONV_POINT32TO16( &lpms32->pt, &lpms16->pt );
444 lpms16->hwnd = WIN_Handle16( lpms32->hwnd );
445 lpms16->wHitTestCode = lpms32->wHitTestCode;
446 lpms16->dwExtraInfo = lpms32->dwExtraInfo;
448 *plParam = (LPARAM)SEGPTR_GET( lpms16 );
454 LPRECT lprect32 = (LPRECT)*plParam;
455 LPRECT16 lprect16 = SEGPTR_NEW( RECT16 );
457 CONV_RECT32TO16( lprect32, lprect16 );
459 *plParam = (LPARAM)SEGPTR_GET( lprect16 );
467 LPMOUSEHOOKSTRUCT lpms32 = (LPMOUSEHOOKSTRUCT)*plParam;
468 LPMOUSEHOOKSTRUCT16 lpms16 = SEGPTR_NEW( MOUSEHOOKSTRUCT16 );
470 CONV_POINT32TO16( &lpms32->pt, &lpms16->pt );
472 lpms16->hwnd = WIN_Handle16( lpms32->hwnd );
473 lpms16->wHitTestCode = lpms32->wHitTestCode;
474 lpms16->dwExtraInfo = lpms32->dwExtraInfo;
476 *plParam = (LPARAM)SEGPTR_GET( lpms16 );
482 LPDEBUGHOOKINFO lpdh32 = (LPDEBUGHOOKINFO)*plParam;
483 LPDEBUGHOOKINFO16 lpdh16 = SEGPTR_NEW( DEBUGHOOKINFO16 );
485 lpdh16->hModuleHook = 0; /* FIXME */
486 lpdh16->reserved = 0;
487 lpdh16->lParam = lpdh32->lParam;
488 lpdh16->wParam = lpdh32->wParam;
489 lpdh16->code = lpdh32->code;
491 *plParam = (LPARAM)SEGPTR_GET( lpdh16 );
500 case WH_FOREGROUNDIDLE:
501 case WH_CALLWNDPROCRET:
503 FIXME("\t[%i] 32to16 translation unimplemented\n", id);
508 /***********************************************************************
511 static void HOOK_Map32ATo16(INT id, INT code, WPARAM *pwParam,
514 if (id == WH_CBT && code == HCBT_CREATEWND)
516 LPCBT_CREATEWNDA lpcbtcw32 = (LPCBT_CREATEWNDA)*plParam;
517 LPCBT_CREATEWND16 lpcbtcw16 = SEGPTR_NEW( CBT_CREATEWND16 );
518 LPCREATESTRUCT16 lpcs16 = SEGPTR_NEW( CREATESTRUCT16 );
520 lpcbtcw16->lpcs = (LPCREATESTRUCT16)SEGPTR_GET( lpcs16 );
521 STRUCT32_CREATESTRUCT32Ato16( lpcbtcw32->lpcs, lpcs16 );
523 if (HIWORD(lpcbtcw32->lpcs->lpszName))
525 SEGPTR_GET( SEGPTR_STRDUP( lpcbtcw32->lpcs->lpszName ) );
527 lpcs16->lpszName = (SEGPTR)lpcbtcw32->lpcs->lpszName;
529 if (HIWORD(lpcbtcw32->lpcs->lpszClass))
531 SEGPTR_GET( SEGPTR_STRDUP( lpcbtcw32->lpcs->lpszClass ) );
533 lpcs16->lpszClass = (SEGPTR)lpcbtcw32->lpcs->lpszClass;
535 lpcbtcw16->hwndInsertAfter = WIN_Handle16( lpcbtcw32->hwndInsertAfter );
537 *plParam = (LPARAM)SEGPTR_GET( lpcbtcw16 );
539 else HOOK_Map32To16Common(id, code, pwParam, plParam, TRUE);
543 /***********************************************************************
546 static void HOOK_Map32WTo16(INT id, INT code, WPARAM *pwParam,
549 if (id == WH_CBT && code == HCBT_CREATEWND)
552 LPCBT_CREATEWNDW lpcbtcw32 = (LPCBT_CREATEWNDW)*plParam;
553 LPCBT_CREATEWND16 lpcbtcw16 = SEGPTR_NEW( CBT_CREATEWND16 );
554 LPCREATESTRUCT16 lpcs16 = SEGPTR_NEW( CREATESTRUCT16 );
556 lpcbtcw16->lpcs = (LPCREATESTRUCT16)SEGPTR_GET( lpcs16 );
557 STRUCT32_CREATESTRUCT32Ato16( (LPCREATESTRUCTA)lpcbtcw32->lpcs,
560 name = SEGPTR_STRDUP_WtoA( lpcbtcw32->lpcs->lpszName );
561 cls = SEGPTR_STRDUP_WtoA( lpcbtcw32->lpcs->lpszClass );
562 lpcs16->lpszName = SEGPTR_GET( name );
563 lpcs16->lpszClass = SEGPTR_GET( cls );
564 lpcbtcw16->hwndInsertAfter = WIN_Handle16( lpcbtcw32->hwndInsertAfter );
566 *plParam = (LPARAM)SEGPTR_GET( lpcbtcw16 );
568 else HOOK_Map32To16Common(id, code, pwParam, plParam, FALSE);
572 /***********************************************************************
573 * HOOK_UnMap32To16Common
575 static void HOOK_UnMap32To16Common(INT id, INT code, WPARAM wParamOrig,
576 LPARAM lParamOrig, WPARAM wParam,
577 LPARAM lParam, BOOL bA)
582 case WH_SYSMSGFILTER:
583 case WH_JOURNALRECORD:
584 case WH_JOURNALPLAYBACK:
587 SEGPTR_FREE( MapSL(lParam) );
592 LPCWPSTRUCT16 lpcwp16 = MapSL(lParam);
593 LPCWPSTRUCT lpcwp32 = (LPCWPSTRUCT)lParamOrig;
596 mp16.wParam = lpcwp16->wParam;
597 mp16.lParam = lpcwp16->lParam;
600 if (bA) WINPROC_UnmapMsg32ATo16( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
601 lpcwp32->lParam, &mp16 );
602 else WINPROC_UnmapMsg32WTo16( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
603 lpcwp32->lParam, &mp16 );
604 SEGPTR_FREE( MapSL(lParam) );
610 LPMSG lpmsg32 = (LPMSG)lParamOrig;
612 STRUCT32_MSG16to32( MapSL(lParam), lpmsg32 );
613 SEGPTR_FREE( MapSL(lParam) );
622 LPCBT_CREATEWNDA lpcbtcw32 = (LPCBT_CREATEWNDA)(lParamOrig);
623 LPCBT_CREATEWND16 lpcbtcw16 = MapSL(lParam);
624 LPCREATESTRUCT16 lpcs16 = MapSL((SEGPTR)lpcbtcw16->lpcs);
626 if (HIWORD(lpcs16->lpszName))
627 SEGPTR_FREE( MapSL(lpcs16->lpszName) );
629 if (HIWORD(lpcs16->lpszClass))
630 SEGPTR_FREE( MapSL(lpcs16->lpszClass) );
632 lpcbtcw32->hwndInsertAfter = WIN_Handle32( lpcbtcw16->hwndInsertAfter );
634 SEGPTR_FREE( lpcs16 );
638 case HCBT_CLICKSKIPPED:
641 SEGPTR_FREE( MapSL(lParam) );
651 case WH_FOREGROUNDIDLE:
652 case WH_CALLWNDPROCRET:
654 FIXME("\t[%i] skipping unmap\n", id);
659 /***********************************************************************
662 static void HOOK_UnMap32ATo16(INT id, INT code, WPARAM wParamOrig,
663 LPARAM lParamOrig, WPARAM wParam,
666 HOOK_UnMap32To16Common( id, code, wParamOrig, lParamOrig, wParam,
671 /***********************************************************************
674 static void HOOK_UnMap32WTo16(INT id, INT code, WPARAM wParamOrig,
675 LPARAM lParamOrig, WPARAM wParam,
678 HOOK_UnMap32To16Common( id, code, wParamOrig, lParamOrig, wParam,
683 /***********************************************************************
686 static void HOOK_Map32ATo32W(INT id, INT code, WPARAM *pwParam,
689 if (id == WH_CBT && code == HCBT_CREATEWND)
691 LPCBT_CREATEWNDA lpcbtcwA = (LPCBT_CREATEWNDA)*plParam;
692 LPCBT_CREATEWNDW lpcbtcwW = HeapAlloc( GetProcessHeap(), 0,
694 lpcbtcwW->lpcs = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpcbtcwW->lpcs) );
696 lpcbtcwW->hwndInsertAfter = lpcbtcwA->hwndInsertAfter;
697 *lpcbtcwW->lpcs = *(LPCREATESTRUCTW)lpcbtcwA->lpcs;
699 if (HIWORD(lpcbtcwA->lpcs->lpszName))
701 lpcbtcwW->lpcs->lpszName = HEAP_strdupAtoW( GetProcessHeap(), 0,
702 lpcbtcwA->lpcs->lpszName );
705 lpcbtcwW->lpcs->lpszName = (LPWSTR)lpcbtcwA->lpcs->lpszName;
707 if (HIWORD(lpcbtcwA->lpcs->lpszClass))
709 lpcbtcwW->lpcs->lpszClass = HEAP_strdupAtoW( GetProcessHeap(), 0,
710 lpcbtcwA->lpcs->lpszClass );
713 lpcbtcwW->lpcs->lpszClass = (LPCWSTR)lpcbtcwA->lpcs->lpszClass;
714 *plParam = (LPARAM)lpcbtcwW;
720 /***********************************************************************
723 static void HOOK_UnMap32ATo32W(INT id, INT code, WPARAM wParamOrig,
724 LPARAM lParamOrig, WPARAM wParam,
727 if (id == WH_CBT && code == HCBT_CREATEWND)
729 LPCBT_CREATEWNDW lpcbtcwW = (LPCBT_CREATEWNDW)lParam;
730 if (HIWORD(lpcbtcwW->lpcs->lpszName))
731 HeapFree( GetProcessHeap(), 0, (LPWSTR)lpcbtcwW->lpcs->lpszName );
732 if (HIWORD(lpcbtcwW->lpcs->lpszClass))
733 HeapFree( GetProcessHeap(), 0, (LPWSTR)lpcbtcwW->lpcs->lpszClass );
734 HeapFree( GetProcessHeap(), 0, lpcbtcwW->lpcs );
735 HeapFree( GetProcessHeap(), 0, lpcbtcwW );
741 /***********************************************************************
744 static void HOOK_Map32WTo32A(INT id, INT code, WPARAM *pwParam,
747 if (id == WH_CBT && code == HCBT_CREATEWND)
749 LPCBT_CREATEWNDW lpcbtcwW = (LPCBT_CREATEWNDW)*plParam;
750 LPCBT_CREATEWNDA lpcbtcwA = HeapAlloc( GetProcessHeap(), 0,
752 lpcbtcwA->lpcs = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpcbtcwA->lpcs) );
754 lpcbtcwA->hwndInsertAfter = lpcbtcwW->hwndInsertAfter;
755 *lpcbtcwA->lpcs = *(LPCREATESTRUCTA)lpcbtcwW->lpcs;
757 if (HIWORD(lpcbtcwW->lpcs->lpszName))
758 lpcbtcwA->lpcs->lpszName = HEAP_strdupWtoA( GetProcessHeap(), 0,
759 lpcbtcwW->lpcs->lpszName );
761 lpcbtcwA->lpcs->lpszName = (LPSTR)lpcbtcwW->lpcs->lpszName;
763 if (HIWORD(lpcbtcwW->lpcs->lpszClass))
764 lpcbtcwA->lpcs->lpszClass = HEAP_strdupWtoA( GetProcessHeap(), 0,
765 lpcbtcwW->lpcs->lpszClass );
767 lpcbtcwA->lpcs->lpszClass = (LPSTR)lpcbtcwW->lpcs->lpszClass;
768 *plParam = (LPARAM)lpcbtcwA;
774 /***********************************************************************
777 static void HOOK_UnMap32WTo32A(INT id, INT code, WPARAM wParamOrig,
778 LPARAM lParamOrig, WPARAM wParam,
781 if (id == WH_CBT && code == HCBT_CREATEWND)
783 LPCBT_CREATEWNDA lpcbtcwA = (LPCBT_CREATEWNDA)lParam;
784 if (HIWORD(lpcbtcwA->lpcs->lpszName))
785 HeapFree( GetProcessHeap(), 0, (LPSTR)lpcbtcwA->lpcs->lpszName );
786 if (HIWORD(lpcbtcwA->lpcs->lpszClass))
787 HeapFree( GetProcessHeap(), 0, (LPSTR)lpcbtcwA->lpcs->lpszClass );
788 HeapFree( GetProcessHeap(), 0, lpcbtcwA->lpcs );
789 HeapFree( GetProcessHeap(), 0, lpcbtcwA );
795 /***********************************************************************
796 * Map Function Tables
798 static const HOOK_MapFunc HOOK_MapFuncs[3][3] =
800 { NULL, HOOK_Map16To32A, HOOK_Map16To32W },
801 { HOOK_Map32ATo16, NULL, HOOK_Map32ATo32W },
802 { HOOK_Map32WTo16, HOOK_Map32WTo32A, NULL }
805 static const HOOK_UnMapFunc HOOK_UnMapFuncs[3][3] =
807 { NULL, HOOK_UnMap16To32A, HOOK_UnMap16To32W },
808 { HOOK_UnMap32ATo16, NULL, HOOK_UnMap32ATo32W },
809 { HOOK_UnMap32WTo16, HOOK_UnMap32WTo32A, NULL }
813 /***********************************************************************
817 /***********************************************************************
820 * Get the next hook of a given hook.
822 static HANDLE16 HOOK_GetNextHook( HANDLE16 hook )
824 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR( hook );
826 if (!data || !hook) return 0;
827 if (data->next) return data->next;
828 if (!data->ownerQueue) return 0; /* Already system hook */
830 /* Now start enumerating the system hooks */
831 return HOOK_systemHooks[data->id - WH_MINHOOK];
835 /***********************************************************************
838 * Get the first hook for a given type.
840 static HANDLE16 HOOK_GetHook( INT16 id )
845 if ((queue = QUEUE_Current()) != NULL)
846 hook = queue->hooks[id - WH_MINHOOK];
847 if (!hook) hook = HOOK_systemHooks[id - WH_MINHOOK];
852 /***********************************************************************
855 * Install a given hook.
857 /* ### start build ### */
858 extern LONG CALLBACK HOOK_CallTo16_long_wwl(FARPROC16,WORD,WORD,LONG);
859 /* ### stop build ### */
860 static HHOOK HOOK_SetHook( INT16 id, LPVOID proc, INT type,
861 HMODULE16 hModule, DWORD dwThreadId )
867 if ((id < WH_MINHOOK) || (id > WH_MAXHOOK)) return 0;
869 TRACE("Setting hook %d: %08x %04x %08lx\n",
870 id, (UINT)proc, hModule, dwThreadId );
872 /* Create task queue if none present */
873 InitThreadInput16( 0, 0 );
875 if (id == WH_JOURNALPLAYBACK) EnableHardwareInput16(FALSE);
877 if (dwThreadId) /* Task-specific hook */
879 if ((id == WH_JOURNALRECORD) || (id == WH_JOURNALPLAYBACK) ||
880 (id == WH_SYSMSGFILTER)) return 0; /* System-only hooks */
881 if (!(hQueue = GetThreadQueue16( dwThreadId )))
885 /* Create the hook structure */
887 if (!(handle = USER_HEAP_ALLOC( sizeof(HOOKDATA) ))) return 0;
888 data = (HOOKDATA *) USER_HEAP_LIN_ADDR( handle );
891 data->ownerQueue = hQueue;
892 data->ownerModule = hModule;
895 /* Insert it in the correct linked list */
899 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue );
900 data->next = queue->hooks[id - WH_MINHOOK];
901 queue->hooks[id - WH_MINHOOK] = handle;
902 QUEUE_Unlock( queue );
906 data->next = HOOK_systemHooks[id - WH_MINHOOK];
907 HOOK_systemHooks[id - WH_MINHOOK] = handle;
909 TRACE("Setting hook %d: ret=%04x [next=%04x]\n",
910 id, handle, data->next );
912 return (HHOOK)( handle? MAKELONG( handle, HOOK_MAGIC ) : 0 );
916 /***********************************************************************
919 * Remove a hook from the list.
921 static BOOL HOOK_RemoveHook( HANDLE16 hook )
926 TRACE("Removing hook %04x\n", hook );
928 if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook))) return FALSE;
929 if (data->flags & HOOK_INUSE)
931 /* Mark it for deletion later on */
932 WARN("Hook still running, deletion delayed\n" );
933 data->proc = (HOOKPROC)0;
937 if (data->id == WH_JOURNALPLAYBACK) EnableHardwareInput16(TRUE);
939 /* Remove it from the linked list */
941 if (data->ownerQueue)
943 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( data->ownerQueue );
944 if (!queue) return FALSE;
945 prevHook = &queue->hooks[data->id - WH_MINHOOK];
946 QUEUE_Unlock( queue );
948 else prevHook = &HOOK_systemHooks[data->id - WH_MINHOOK];
950 while (*prevHook && *prevHook != hook)
951 prevHook = &((HOOKDATA *)USER_HEAP_LIN_ADDR(*prevHook))->next;
953 if (!*prevHook) return FALSE;
954 *prevHook = data->next;
956 USER_HEAP_FREE( hook );
961 /***********************************************************************
964 static HANDLE16 HOOK_FindValidHook( HANDLE16 hook )
970 if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook))) return 0;
971 if (data->proc) return hook;
977 /***********************************************************************
980 * Call a hook procedure.
982 static LRESULT HOOK_CallHook( HANDLE16 hook, INT fromtype, INT code,
983 WPARAM wParam, LPARAM lParam )
987 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
991 WPARAM wParamOrig = wParam;
992 LPARAM lParamOrig = lParam;
993 HOOK_MapFunc MapFunc;
994 HOOK_UnMapFunc UnMapFunc;
996 MapFunc = HOOK_MapFuncs[fromtype][data->flags & HOOK_MAPTYPE];
997 UnMapFunc = HOOK_UnMapFuncs[fromtype][data->flags & HOOK_MAPTYPE];
1000 MapFunc( data->id, code, &wParam, &lParam );
1004 if (!(queue = QUEUE_Current())) return 0;
1005 prevHook = queue->hCurHook;
1006 queue->hCurHook = hook;
1007 data->flags |= HOOK_INUSE;
1009 TRACE("Calling hook %04x: %d %08x %08lx\n",
1010 hook, code, wParam, lParam );
1012 /* Suspend window structure locks before calling user code */
1013 iWndsLocks = WIN_SuspendWndsLock();
1015 if ((data->flags & HOOK_MAPTYPE) == HOOK_WIN16)
1017 ret = HOOK_CallTo16_long_wwl( data->proc, code, wParam, lParam );
1018 /* Grrr. While the hook procedure is supposed to have an LRESULT return
1019 value even in Win16, it seems that for those hook types where the
1020 return value is interpreted as BOOL, Windows doesn't actually check
1021 the HIWORD ... Some buggy Win16 programs, notably WINFILE, rely on
1022 that, because they neglect to clear DX ... */
1023 if (data->id != WH_JOURNALPLAYBACK) ret = LOWORD( ret );
1026 ret = data->proc(code, wParam, lParam);
1028 WIN_RestoreWndsLock(iWndsLocks);
1030 TRACE("Ret hook %04x = %08lx\n", hook, ret );
1032 data->flags &= ~HOOK_INUSE;
1033 queue->hCurHook = prevHook;
1036 UnMapFunc( data->id, code, wParamOrig, lParamOrig, wParam, lParam );
1038 if (!data->proc) HOOK_RemoveHook( hook );
1043 /***********************************************************************
1044 * Exported Functions & APIs
1047 /***********************************************************************
1050 * Replacement for calling HOOK_GetHook from other modules.
1052 BOOL HOOK_IsHooked( INT16 id )
1054 return HOOK_GetHook( id ) != 0;
1058 /***********************************************************************
1061 * Call a hook chain.
1063 LRESULT HOOK_CallHooks16( INT16 id, INT16 code, WPARAM16 wParam,
1068 if (!(hook = HOOK_GetHook( id ))) return 0;
1069 if (!(hook = HOOK_FindValidHook(hook))) return 0;
1070 return HOOK_CallHook( hook, HOOK_WIN16, code, wParam, lParam );
1073 /***********************************************************************
1076 * Call a hook chain.
1078 LRESULT HOOK_CallHooksA( INT id, INT code, WPARAM wParam,
1083 if (!(hook = HOOK_GetHook( id ))) return 0;
1084 if (!(hook = HOOK_FindValidHook(hook))) return 0;
1085 return HOOK_CallHook( hook, HOOK_WIN32A, code, wParam, lParam );
1088 /***********************************************************************
1091 * Call a hook chain.
1093 LRESULT HOOK_CallHooksW( INT id, INT code, WPARAM wParam,
1098 if (!(hook = HOOK_GetHook( id ))) return 0;
1099 if (!(hook = HOOK_FindValidHook(hook))) return 0;
1100 return HOOK_CallHook( hook, HOOK_WIN32W, code, wParam,
1105 /***********************************************************************
1106 * HOOK_FreeModuleHooks
1108 void HOOK_FreeModuleHooks( HMODULE16 hModule )
1110 /* remove all system hooks registered by this module */
1116 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
1118 hook = HOOK_systemHooks[id - WH_MINHOOK];
1120 if( (hptr = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook)) )
1123 if( hptr->ownerModule == hModule )
1125 hptr->flags &= HOOK_MAPTYPE;
1126 HOOK_RemoveHook(hook);
1134 /***********************************************************************
1135 * HOOK_FreeQueueHooks
1137 void HOOK_FreeQueueHooks(void)
1139 /* remove all hooks registered by the current queue */
1141 HOOKDATA* hptr = NULL;
1145 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
1147 hook = HOOK_GetHook( id );
1150 next = HOOK_GetNextHook(hook);
1152 hptr = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
1153 if( hptr && hptr->ownerQueue )
1155 hptr->flags &= HOOK_MAPTYPE;
1156 HOOK_RemoveHook(hook);
1164 /***********************************************************************
1165 * SetWindowsHook (USER.121)
1167 FARPROC16 WINAPI SetWindowsHook16( INT16 id, HOOKPROC16 proc )
1169 HINSTANCE16 hInst = FarGetOwner16( HIWORD(proc) );
1171 /* WH_MSGFILTER is the only task-specific hook for SetWindowsHook() */
1172 HTASK16 hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
1174 return (FARPROC16)SetWindowsHookEx16( id, proc, hInst, hTask );
1177 /***********************************************************************
1178 * SetWindowsHookA (USER32.@)
1180 HHOOK WINAPI SetWindowsHookA( INT id, HOOKPROC proc )
1182 return SetWindowsHookExA( id, proc, 0, GetCurrentThreadId() );
1185 /***********************************************************************
1186 * SetWindowsHookW (USER32.@)
1188 HHOOK WINAPI SetWindowsHookW( INT id, HOOKPROC proc )
1190 return SetWindowsHookExW( id, proc, 0, GetCurrentThreadId() );
1194 /***********************************************************************
1195 * SetWindowsHookEx (USER.291)
1196 * SetWindowsHookEx16 (USER32.@)
1198 HHOOK WINAPI SetWindowsHookEx16( INT16 id, HOOKPROC16 proc, HINSTANCE16 hInst,
1203 FIXME("WH_DEBUG is broken in 16-bit Windows.\n");
1206 return HOOK_SetHook( id, proc, HOOK_WIN16, GetExePtr(hInst), (DWORD)hTask );
1209 /***********************************************************************
1210 * SetWindowsHookExA (USER32.@)
1212 HHOOK WINAPI SetWindowsHookExA( INT id, HOOKPROC proc, HINSTANCE hInst,
1215 return HOOK_SetHook( id, proc, HOOK_WIN32A, MapHModuleLS(hInst), dwThreadId );
1218 /***********************************************************************
1219 * SetWindowsHookExW (USER32.@)
1221 HHOOK WINAPI SetWindowsHookExW( INT id, HOOKPROC proc, HINSTANCE hInst,
1224 return HOOK_SetHook( id, proc, HOOK_WIN32W, MapHModuleLS(hInst), dwThreadId );
1228 /***********************************************************************
1229 * UnhookWindowsHook (USER.234)
1231 BOOL16 WINAPI UnhookWindowsHook16( INT16 id, HOOKPROC16 proc )
1233 return UnhookWindowsHook( id, (HOOKPROC)proc );
1236 /***********************************************************************
1237 * UnhookWindowsHook (USER32.@)
1239 BOOL WINAPI UnhookWindowsHook( INT id, HOOKPROC proc )
1241 HANDLE16 hook = HOOK_GetHook( id );
1243 TRACE("%d %08lx\n", id, (DWORD)proc );
1247 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
1248 if (data->proc == proc) break;
1249 hook = HOOK_GetNextHook( hook );
1251 if (!hook) return FALSE;
1252 return HOOK_RemoveHook( hook );
1256 /***********************************************************************
1257 * UnhookWindowsHookEx (USER.292)
1259 BOOL16 WINAPI UnhookWindowsHookEx16( HHOOK hhook )
1261 return UnhookWindowsHookEx( hhook );
1264 /***********************************************************************
1265 * UnhookWindowsHookEx (USER32.@)
1267 BOOL WINAPI UnhookWindowsHookEx( HHOOK hhook )
1269 if (HIWORD(hhook) != HOOK_MAGIC) return FALSE; /* Not a new format hook */
1270 return HOOK_RemoveHook( LOWORD(hhook) );
1274 /***********************************************************************
1275 * CallNextHookEx (USER.293)
1276 * CallNextHookEx16 (USER32.@)
1278 * I wouldn't have separated this into 16 and 32 bit versions, but I
1279 * need a way to figure out if I need to do a mapping or not.
1281 LRESULT WINAPI CallNextHookEx16( HHOOK hhook, INT16 code, WPARAM16 wParam,
1286 if (HIWORD(hhook) != HOOK_MAGIC) return 0; /* Not a new format hook */
1287 if (!(next = HOOK_GetNextHook( LOWORD(hhook) ))) return 0;
1289 return HOOK_CallHook( next, HOOK_WIN16, code, wParam, lParam );
1293 /***********************************************************************
1294 * CallNextHookEx (USER32.@)
1296 * There aren't ANSI and UNICODE versions of this.
1298 LRESULT WINAPI CallNextHookEx( HHOOK hhook, INT code, WPARAM wParam,
1302 INT fromtype; /* figure out Ansi/Unicode */
1305 if (HIWORD(hhook) != HOOK_MAGIC) return 0; /* Not a new format hook */
1306 if (!(next = HOOK_GetNextHook( LOWORD(hhook) ))) return 0;
1308 oldhook = (HOOKDATA *)USER_HEAP_LIN_ADDR( LOWORD(hhook) );
1309 fromtype = oldhook->flags & HOOK_MAPTYPE;
1311 if (fromtype == HOOK_WIN16)
1312 ERR("called from 16bit hook!\n");
1314 return HOOK_CallHook( next, fromtype, code, wParam, lParam );
1318 /***********************************************************************
1319 * DefHookProc (USER.235)
1321 LRESULT WINAPI DefHookProc16( INT16 code, WPARAM16 wParam, LPARAM lParam,
1324 /* Note: the *hhook parameter is never used, since we rely on the
1325 * current hook value from the task queue to find the next hook. */
1326 MESSAGEQUEUE *queue;
1328 if (!(queue = QUEUE_Current())) return 0;
1329 return CallNextHookEx16( queue->hCurHook, code, wParam, lParam );
1333 /***********************************************************************
1334 * CallMsgFilter (USER.123)
1336 BOOL16 WINAPI CallMsgFilter16( SEGPTR msg, INT16 code )
1338 if (GetSysModalWindow16()) return FALSE;
1339 if (HOOK_CallHooks16( WH_SYSMSGFILTER, code, 0, (LPARAM)msg )) return TRUE;
1340 return HOOK_CallHooks16( WH_MSGFILTER, code, 0, (LPARAM)msg );
1344 /***********************************************************************
1345 * CallMsgFilter32 (USER.823)
1347 BOOL16 WINAPI CallMsgFilter32_16( SEGPTR msg16_32, INT16 code, BOOL16 wHaveParamHigh )
1349 MSG32_16 *lpmsg16_32 = MapSL(msg16_32);
1351 if (wHaveParamHigh == FALSE)
1353 lpmsg16_32->wParamHigh = 0;
1354 /* WARNING: msg16_32->msg has to be the first variable in the struct */
1355 return CallMsgFilter16(msg16_32, code);
1362 msg32.hwnd = WIN_Handle32( lpmsg16_32->msg.hwnd );
1363 msg32.message = lpmsg16_32->msg.message;
1364 msg32.wParam = MAKELONG(lpmsg16_32->msg.wParam, lpmsg16_32->wParamHigh);
1365 msg32.lParam = lpmsg16_32->msg.lParam;
1366 msg32.time = lpmsg16_32->msg.time;
1367 msg32.pt.x = lpmsg16_32->msg.pt.x;
1368 msg32.pt.y = lpmsg16_32->msg.pt.y;
1370 ret = (BOOL16)CallMsgFilterA(&msg32, (INT)code);
1372 lpmsg16_32->msg.hwnd = WIN_Handle16( msg32.hwnd );
1373 lpmsg16_32->msg.message = msg32.message;
1374 lpmsg16_32->msg.wParam = LOWORD(msg32.wParam);
1375 lpmsg16_32->msg.lParam = msg32.lParam;
1376 lpmsg16_32->msg.time = msg32.time;
1377 lpmsg16_32->msg.pt.x = msg32.pt.x;
1378 lpmsg16_32->msg.pt.y = msg32.pt.y;
1379 lpmsg16_32->wParamHigh = HIWORD(msg32.wParam);
1386 /***********************************************************************
1387 * CallMsgFilterA (USER32.@)
1389 * FIXME: There are ANSI and UNICODE versions of this, plus an unspecified
1390 * version, plus USER (the 16bit one) has a CallMsgFilter32 function.
1392 BOOL WINAPI CallMsgFilterA( LPMSG msg, INT code )
1394 if (GetSysModalWindow16()) return FALSE; /* ??? */
1395 if (HOOK_CallHooksA( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
1397 return HOOK_CallHooksA( WH_MSGFILTER, code, 0, (LPARAM)msg );
1401 /***********************************************************************
1402 * CallMsgFilterW (USER32.@)
1404 BOOL WINAPI CallMsgFilterW( LPMSG msg, INT code )
1406 if (GetSysModalWindow16()) return FALSE; /* ??? */
1407 if (HOOK_CallHooksW( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
1409 return HOOK_CallHooksW( WH_MSGFILTER, code, 0, (LPARAM)msg );