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 = lpcwp16->hwnd;
103 lpcwp32->lParam = lpcwp16->lParam;
105 if (bA) WINPROC_MapMsg16To32A( lpcwp16->message, lpcwp16->wParam,
106 &lpcwp32->message, &lpcwp32->wParam,
108 else WINPROC_MapMsg16To32W( lpcwp16->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 = 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 = 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 = 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 = 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:
234 FIXME("\t[%i] 16to32 translation unimplemented\n", id);
239 /***********************************************************************
242 static void HOOK_Map16To32A(INT id, INT code, WPARAM *pwParam,
245 HOOK_Map16To32Common( id, code, pwParam, plParam, TRUE );
249 /***********************************************************************
252 static void HOOK_Map16To32W(INT id, INT code, WPARAM *pwParam,
255 HOOK_Map16To32Common( id, code, pwParam, plParam, FALSE );
259 /***********************************************************************
260 * HOOK_UnMap16To32Common
262 static void HOOK_UnMap16To32Common(INT id, INT code, WPARAM wParamOrig,
263 LPARAM lParamOrig, WPARAM wParam,
264 LPARAM lParam, BOOL bA)
269 case WH_SYSMSGFILTER:
270 case WH_JOURNALRECORD:
271 case WH_JOURNALPLAYBACK:
273 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
278 LPCWPSTRUCT lpcwp32 = (LPCWPSTRUCT)lParam;
279 if (bA) WINPROC_UnmapMsg16To32A( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
280 lpcwp32->lParam, 0 );
281 else WINPROC_UnmapMsg16To32W( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
282 lpcwp32->lParam, 0 );
283 HeapFree( GetProcessHeap(), 0, lpcwp32 );
289 LPMSG16 lpmsg16 = MapSL(lParamOrig);
290 STRUCT32_MSG32to16( (LPMSG)lParam, lpmsg16 );
291 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
298 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
306 LPCBT_CREATEWNDA lpcbtcw32 = (LPCBT_CREATEWNDA)lParam;
307 LPCBT_CREATEWND16 lpcbtcw16 = MapSL(lParamOrig);
311 if (HIWORD(lpcbtcw32->lpcs->lpszName))
312 HeapFree( GetProcessHeap(), 0, (LPWSTR)lpcbtcw32->lpcs->lpszName );
313 if (HIWORD(lpcbtcw32->lpcs->lpszClass))
314 HeapFree( GetProcessHeap(), 0, (LPWSTR)lpcbtcw32->lpcs->lpszClass );
317 lpcbtcw16->hwndInsertAfter = lpcbtcw32->hwndInsertAfter;
319 HeapFree( GetProcessHeap(), 0, lpcbtcw32->lpcs );
323 case HCBT_CLICKSKIPPED:
326 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam);
336 case WH_FOREGROUNDIDLE:
337 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 = 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 = 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 = 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 = 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:
502 FIXME("\t[%i] 32to16 translation unimplemented\n", id);
507 /***********************************************************************
510 static void HOOK_Map32ATo16(INT id, INT code, WPARAM *pwParam,
513 if (id == WH_CBT && code == HCBT_CREATEWND)
515 LPCBT_CREATEWNDA lpcbtcw32 = (LPCBT_CREATEWNDA)*plParam;
516 LPCBT_CREATEWND16 lpcbtcw16 = SEGPTR_NEW( CBT_CREATEWND16 );
517 LPCREATESTRUCT16 lpcs16 = SEGPTR_NEW( CREATESTRUCT16 );
519 lpcbtcw16->lpcs = (LPCREATESTRUCT16)SEGPTR_GET( lpcs16 );
520 STRUCT32_CREATESTRUCT32Ato16( lpcbtcw32->lpcs, lpcs16 );
522 if (HIWORD(lpcbtcw32->lpcs->lpszName))
524 SEGPTR_GET( SEGPTR_STRDUP( lpcbtcw32->lpcs->lpszName ) );
526 lpcs16->lpszName = (SEGPTR)lpcbtcw32->lpcs->lpszName;
528 if (HIWORD(lpcbtcw32->lpcs->lpszClass))
530 SEGPTR_GET( SEGPTR_STRDUP( lpcbtcw32->lpcs->lpszClass ) );
532 lpcs16->lpszClass = (SEGPTR)lpcbtcw32->lpcs->lpszClass;
534 lpcbtcw16->hwndInsertAfter = lpcbtcw32->hwndInsertAfter;
536 *plParam = (LPARAM)SEGPTR_GET( lpcbtcw16 );
538 else HOOK_Map32To16Common(id, code, pwParam, plParam, TRUE);
542 /***********************************************************************
545 static void HOOK_Map32WTo16(INT id, INT code, WPARAM *pwParam,
548 if (id == WH_CBT && code == HCBT_CREATEWND)
551 LPCBT_CREATEWNDW lpcbtcw32 = (LPCBT_CREATEWNDW)*plParam;
552 LPCBT_CREATEWND16 lpcbtcw16 = SEGPTR_NEW( CBT_CREATEWND16 );
553 LPCREATESTRUCT16 lpcs16 = SEGPTR_NEW( CREATESTRUCT16 );
555 lpcbtcw16->lpcs = (LPCREATESTRUCT16)SEGPTR_GET( lpcs16 );
556 STRUCT32_CREATESTRUCT32Ato16( (LPCREATESTRUCTA)lpcbtcw32->lpcs,
559 name = SEGPTR_STRDUP_WtoA( lpcbtcw32->lpcs->lpszName );
560 cls = SEGPTR_STRDUP_WtoA( lpcbtcw32->lpcs->lpszClass );
561 lpcs16->lpszName = SEGPTR_GET( name );
562 lpcs16->lpszClass = SEGPTR_GET( cls );
563 lpcbtcw16->hwndInsertAfter = lpcbtcw32->hwndInsertAfter;
565 *plParam = (LPARAM)SEGPTR_GET( lpcbtcw16 );
567 else HOOK_Map32To16Common(id, code, pwParam, plParam, FALSE);
571 /***********************************************************************
572 * HOOK_UnMap32To16Common
574 static void HOOK_UnMap32To16Common(INT id, INT code, WPARAM wParamOrig,
575 LPARAM lParamOrig, WPARAM wParam,
576 LPARAM lParam, BOOL bA)
581 case WH_SYSMSGFILTER:
582 case WH_JOURNALRECORD:
583 case WH_JOURNALPLAYBACK:
586 SEGPTR_FREE( MapSL(lParam) );
591 LPCWPSTRUCT16 lpcwp16 = MapSL(lParam);
592 LPCWPSTRUCT lpcwp32 = (LPCWPSTRUCT)lParamOrig;
595 mp16.wParam = lpcwp16->wParam;
596 mp16.lParam = lpcwp16->lParam;
599 if (bA) WINPROC_UnmapMsg32ATo16( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
600 lpcwp32->lParam, &mp16 );
601 else WINPROC_UnmapMsg32WTo16( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
602 lpcwp32->lParam, &mp16 );
603 SEGPTR_FREE( MapSL(lParam) );
609 LPMSG lpmsg32 = (LPMSG)lParamOrig;
611 STRUCT32_MSG16to32( MapSL(lParam), lpmsg32 );
612 SEGPTR_FREE( MapSL(lParam) );
621 LPCBT_CREATEWNDA lpcbtcw32 = (LPCBT_CREATEWNDA)(lParamOrig);
622 LPCBT_CREATEWND16 lpcbtcw16 = MapSL(lParam);
623 LPCREATESTRUCT16 lpcs16 = MapSL((SEGPTR)lpcbtcw16->lpcs);
625 if (HIWORD(lpcs16->lpszName))
626 SEGPTR_FREE( MapSL(lpcs16->lpszName) );
628 if (HIWORD(lpcs16->lpszClass))
629 SEGPTR_FREE( MapSL(lpcs16->lpszClass) );
631 lpcbtcw32->hwndInsertAfter = lpcbtcw16->hwndInsertAfter;
633 SEGPTR_FREE( lpcs16 );
637 case HCBT_CLICKSKIPPED:
640 SEGPTR_FREE( MapSL(lParam) );
650 case WH_FOREGROUNDIDLE:
651 case WH_CALLWNDPROCRET:
652 FIXME("\t[%i] skipping unmap\n", id);
657 /***********************************************************************
660 static void HOOK_UnMap32ATo16(INT id, INT code, WPARAM wParamOrig,
661 LPARAM lParamOrig, WPARAM wParam,
664 HOOK_UnMap32To16Common( id, code, wParamOrig, lParamOrig, wParam,
669 /***********************************************************************
672 static void HOOK_UnMap32WTo16(INT id, INT code, WPARAM wParamOrig,
673 LPARAM lParamOrig, WPARAM wParam,
676 HOOK_UnMap32To16Common( id, code, wParamOrig, lParamOrig, wParam,
681 /***********************************************************************
684 static void HOOK_Map32ATo32W(INT id, INT code, WPARAM *pwParam,
687 if (id == WH_CBT && code == HCBT_CREATEWND)
689 LPCBT_CREATEWNDA lpcbtcwA = (LPCBT_CREATEWNDA)*plParam;
690 LPCBT_CREATEWNDW lpcbtcwW = HeapAlloc( GetProcessHeap(), 0,
692 lpcbtcwW->lpcs = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpcbtcwW->lpcs) );
694 lpcbtcwW->hwndInsertAfter = lpcbtcwA->hwndInsertAfter;
695 *lpcbtcwW->lpcs = *(LPCREATESTRUCTW)lpcbtcwA->lpcs;
697 if (HIWORD(lpcbtcwA->lpcs->lpszName))
699 lpcbtcwW->lpcs->lpszName = HEAP_strdupAtoW( GetProcessHeap(), 0,
700 lpcbtcwA->lpcs->lpszName );
703 lpcbtcwW->lpcs->lpszName = (LPWSTR)lpcbtcwA->lpcs->lpszName;
705 if (HIWORD(lpcbtcwA->lpcs->lpszClass))
707 lpcbtcwW->lpcs->lpszClass = HEAP_strdupAtoW( GetProcessHeap(), 0,
708 lpcbtcwA->lpcs->lpszClass );
711 lpcbtcwW->lpcs->lpszClass = (LPCWSTR)lpcbtcwA->lpcs->lpszClass;
712 *plParam = (LPARAM)lpcbtcwW;
718 /***********************************************************************
721 static void HOOK_UnMap32ATo32W(INT id, INT code, WPARAM wParamOrig,
722 LPARAM lParamOrig, WPARAM wParam,
725 if (id == WH_CBT && code == HCBT_CREATEWND)
727 LPCBT_CREATEWNDW lpcbtcwW = (LPCBT_CREATEWNDW)lParam;
728 if (HIWORD(lpcbtcwW->lpcs->lpszName))
729 HeapFree( GetProcessHeap(), 0, (LPWSTR)lpcbtcwW->lpcs->lpszName );
730 if (HIWORD(lpcbtcwW->lpcs->lpszClass))
731 HeapFree( GetProcessHeap(), 0, (LPWSTR)lpcbtcwW->lpcs->lpszClass );
732 HeapFree( GetProcessHeap(), 0, lpcbtcwW->lpcs );
733 HeapFree( GetProcessHeap(), 0, lpcbtcwW );
739 /***********************************************************************
742 static void HOOK_Map32WTo32A(INT id, INT code, WPARAM *pwParam,
745 if (id == WH_CBT && code == HCBT_CREATEWND)
747 LPCBT_CREATEWNDW lpcbtcwW = (LPCBT_CREATEWNDW)*plParam;
748 LPCBT_CREATEWNDA lpcbtcwA = HeapAlloc( GetProcessHeap(), 0,
750 lpcbtcwA->lpcs = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpcbtcwA->lpcs) );
752 lpcbtcwA->hwndInsertAfter = lpcbtcwW->hwndInsertAfter;
753 *lpcbtcwA->lpcs = *(LPCREATESTRUCTA)lpcbtcwW->lpcs;
755 if (HIWORD(lpcbtcwW->lpcs->lpszName))
756 lpcbtcwA->lpcs->lpszName = HEAP_strdupWtoA( GetProcessHeap(), 0,
757 lpcbtcwW->lpcs->lpszName );
759 lpcbtcwA->lpcs->lpszName = (LPSTR)lpcbtcwW->lpcs->lpszName;
761 if (HIWORD(lpcbtcwW->lpcs->lpszClass))
762 lpcbtcwA->lpcs->lpszClass = HEAP_strdupWtoA( GetProcessHeap(), 0,
763 lpcbtcwW->lpcs->lpszClass );
765 lpcbtcwA->lpcs->lpszClass = (LPSTR)lpcbtcwW->lpcs->lpszClass;
766 *plParam = (LPARAM)lpcbtcwA;
772 /***********************************************************************
775 static void HOOK_UnMap32WTo32A(INT id, INT code, WPARAM wParamOrig,
776 LPARAM lParamOrig, WPARAM wParam,
779 if (id == WH_CBT && code == HCBT_CREATEWND)
781 LPCBT_CREATEWNDA lpcbtcwA = (LPCBT_CREATEWNDA)lParam;
782 if (HIWORD(lpcbtcwA->lpcs->lpszName))
783 HeapFree( GetProcessHeap(), 0, (LPSTR)lpcbtcwA->lpcs->lpszName );
784 if (HIWORD(lpcbtcwA->lpcs->lpszClass))
785 HeapFree( GetProcessHeap(), 0, (LPSTR)lpcbtcwA->lpcs->lpszClass );
786 HeapFree( GetProcessHeap(), 0, lpcbtcwA->lpcs );
787 HeapFree( GetProcessHeap(), 0, lpcbtcwA );
793 /***********************************************************************
794 * Map Function Tables
796 static const HOOK_MapFunc HOOK_MapFuncs[3][3] =
798 { NULL, HOOK_Map16To32A, HOOK_Map16To32W },
799 { HOOK_Map32ATo16, NULL, HOOK_Map32ATo32W },
800 { HOOK_Map32WTo16, HOOK_Map32WTo32A, NULL }
803 static const HOOK_UnMapFunc HOOK_UnMapFuncs[3][3] =
805 { NULL, HOOK_UnMap16To32A, HOOK_UnMap16To32W },
806 { HOOK_UnMap32ATo16, NULL, HOOK_UnMap32ATo32W },
807 { HOOK_UnMap32WTo16, HOOK_UnMap32WTo32A, NULL }
811 /***********************************************************************
815 /***********************************************************************
818 * Get the next hook of a given hook.
820 static HANDLE16 HOOK_GetNextHook( HANDLE16 hook )
822 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR( hook );
824 if (!data || !hook) return 0;
825 if (data->next) return data->next;
826 if (!data->ownerQueue) return 0; /* Already system hook */
828 /* Now start enumerating the system hooks */
829 return HOOK_systemHooks[data->id - WH_MINHOOK];
833 /***********************************************************************
836 * Get the first hook for a given type.
838 static HANDLE16 HOOK_GetHook( INT16 id )
843 if ((queue = QUEUE_Current()) != NULL)
844 hook = queue->hooks[id - WH_MINHOOK];
845 if (!hook) hook = HOOK_systemHooks[id - WH_MINHOOK];
850 /***********************************************************************
853 * Install a given hook.
855 /* ### start build ### */
856 extern LONG CALLBACK HOOK_CallTo16_long_wwl(FARPROC16,WORD,WORD,LONG);
857 /* ### stop build ### */
858 static HHOOK HOOK_SetHook( INT16 id, LPVOID proc, INT type,
859 HMODULE16 hModule, DWORD dwThreadId )
865 if ((id < WH_MINHOOK) || (id > WH_MAXHOOK)) return 0;
867 TRACE("Setting hook %d: %08x %04x %08lx\n",
868 id, (UINT)proc, hModule, dwThreadId );
870 /* Create task queue if none present */
871 InitThreadInput16( 0, 0 );
873 if (id == WH_JOURNALPLAYBACK) EnableHardwareInput16(FALSE);
875 if (dwThreadId) /* Task-specific hook */
877 if ((id == WH_JOURNALRECORD) || (id == WH_JOURNALPLAYBACK) ||
878 (id == WH_SYSMSGFILTER)) return 0; /* System-only hooks */
879 if (!(hQueue = GetThreadQueue16( dwThreadId )))
883 /* Create the hook structure */
885 if (!(handle = USER_HEAP_ALLOC( sizeof(HOOKDATA) ))) return 0;
886 data = (HOOKDATA *) USER_HEAP_LIN_ADDR( handle );
889 data->ownerQueue = hQueue;
890 data->ownerModule = hModule;
893 /* Create CallTo16 thunk for 16-bit hooks */
895 if ( (data->flags & HOOK_MAPTYPE) == HOOK_WIN16 )
896 data->thunk = (HOOKPROC)THUNK_Alloc( (FARPROC16)data->proc,
897 (RELAY)HOOK_CallTo16_long_wwl );
899 data->thunk = data->proc;
901 if ( !data->thunk && data->proc )
903 USER_HEAP_FREE( handle );
907 /* Insert it in the correct linked list */
911 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue );
912 data->next = queue->hooks[id - WH_MINHOOK];
913 queue->hooks[id - WH_MINHOOK] = handle;
914 QUEUE_Unlock( queue );
918 data->next = HOOK_systemHooks[id - WH_MINHOOK];
919 HOOK_systemHooks[id - WH_MINHOOK] = handle;
921 TRACE("Setting hook %d: ret=%04x [next=%04x]\n",
922 id, handle, data->next );
924 return (HHOOK)( handle? MAKELONG( handle, HOOK_MAGIC ) : 0 );
928 /***********************************************************************
931 * Remove a hook from the list.
933 static BOOL HOOK_RemoveHook( HANDLE16 hook )
938 TRACE("Removing hook %04x\n", hook );
940 if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook))) return FALSE;
941 if (data->flags & HOOK_INUSE)
943 /* Mark it for deletion later on */
944 WARN("Hook still running, deletion delayed\n" );
945 data->proc = (HOOKPROC)0;
949 if (data->id == WH_JOURNALPLAYBACK) EnableHardwareInput16(TRUE);
951 /* Remove it from the linked list */
953 if (data->ownerQueue)
955 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( data->ownerQueue );
956 if (!queue) return FALSE;
957 prevHook = &queue->hooks[data->id - WH_MINHOOK];
958 QUEUE_Unlock( queue );
960 else prevHook = &HOOK_systemHooks[data->id - WH_MINHOOK];
962 while (*prevHook && *prevHook != hook)
963 prevHook = &((HOOKDATA *)USER_HEAP_LIN_ADDR(*prevHook))->next;
965 if (!*prevHook) return FALSE;
966 *prevHook = data->next;
968 if ( (data->flags & HOOK_MAPTYPE) == HOOK_WIN16 )
969 THUNK_Free( (FARPROC)data->thunk );
971 USER_HEAP_FREE( hook );
976 /***********************************************************************
979 static HANDLE16 HOOK_FindValidHook( HANDLE16 hook )
985 if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook))) return 0;
986 if (data->proc) return hook;
992 /***********************************************************************
995 * Call a hook procedure.
997 static LRESULT HOOK_CallHook( HANDLE16 hook, INT fromtype, INT code,
998 WPARAM wParam, LPARAM lParam )
1000 MESSAGEQUEUE *queue;
1002 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
1006 WPARAM wParamOrig = wParam;
1007 LPARAM lParamOrig = lParam;
1008 HOOK_MapFunc MapFunc;
1009 HOOK_UnMapFunc UnMapFunc;
1011 MapFunc = HOOK_MapFuncs[fromtype][data->flags & HOOK_MAPTYPE];
1012 UnMapFunc = HOOK_UnMapFuncs[fromtype][data->flags & HOOK_MAPTYPE];
1015 MapFunc( data->id, code, &wParam, &lParam );
1019 if (!(queue = QUEUE_Current())) return 0;
1020 prevHook = queue->hCurHook;
1021 queue->hCurHook = hook;
1022 data->flags |= HOOK_INUSE;
1024 TRACE("Calling hook %04x: %d %08x %08lx\n",
1025 hook, code, wParam, lParam );
1027 /* Suspend window structure locks before calling user code */
1028 iWndsLocks = WIN_SuspendWndsLock();
1030 ret = data->thunk(code, wParam, lParam);
1032 /* Grrr. While the hook procedure is supposed to have an LRESULT return
1033 value even in Win16, it seems that for those hook types where the
1034 return value is interpreted as BOOL, Windows doesn't actually check
1035 the HIWORD ... Some buggy Win16 programs, notably WINFILE, rely on
1036 that, because they neglect to clear DX ... */
1037 if ( (data->flags & HOOK_MAPTYPE) == HOOK_WIN16
1038 && data->id != WH_JOURNALPLAYBACK )
1039 ret = LOWORD( ret );
1041 WIN_RestoreWndsLock(iWndsLocks);
1043 TRACE("Ret hook %04x = %08lx\n", hook, ret );
1045 data->flags &= ~HOOK_INUSE;
1046 queue->hCurHook = prevHook;
1049 UnMapFunc( data->id, code, wParamOrig, lParamOrig, wParam, lParam );
1051 if (!data->proc) HOOK_RemoveHook( hook );
1056 /***********************************************************************
1057 * Exported Functions & APIs
1060 /***********************************************************************
1063 * Replacement for calling HOOK_GetHook from other modules.
1065 BOOL HOOK_IsHooked( INT16 id )
1067 return HOOK_GetHook( id ) != 0;
1071 /***********************************************************************
1074 * Call a hook chain.
1076 LRESULT HOOK_CallHooks16( INT16 id, INT16 code, WPARAM16 wParam,
1081 if (!(hook = HOOK_GetHook( id ))) return 0;
1082 if (!(hook = HOOK_FindValidHook(hook))) return 0;
1083 return HOOK_CallHook( hook, HOOK_WIN16, code, wParam, lParam );
1086 /***********************************************************************
1089 * Call a hook chain.
1091 LRESULT HOOK_CallHooksA( INT id, INT code, WPARAM wParam,
1096 if (!(hook = HOOK_GetHook( id ))) return 0;
1097 if (!(hook = HOOK_FindValidHook(hook))) return 0;
1098 return HOOK_CallHook( hook, HOOK_WIN32A, code, wParam, lParam );
1101 /***********************************************************************
1104 * Call a hook chain.
1106 LRESULT HOOK_CallHooksW( INT id, INT code, WPARAM wParam,
1111 if (!(hook = HOOK_GetHook( id ))) return 0;
1112 if (!(hook = HOOK_FindValidHook(hook))) return 0;
1113 return HOOK_CallHook( hook, HOOK_WIN32W, code, wParam,
1118 /***********************************************************************
1119 * HOOK_FreeModuleHooks
1121 void HOOK_FreeModuleHooks( HMODULE16 hModule )
1123 /* remove all system hooks registered by this module */
1129 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
1131 hook = HOOK_systemHooks[id - WH_MINHOOK];
1133 if( (hptr = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook)) )
1136 if( hptr->ownerModule == hModule )
1138 hptr->flags &= HOOK_MAPTYPE;
1139 HOOK_RemoveHook(hook);
1147 /***********************************************************************
1148 * HOOK_FreeQueueHooks
1150 void HOOK_FreeQueueHooks(void)
1152 /* remove all hooks registered by the current queue */
1154 HOOKDATA* hptr = NULL;
1158 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
1160 hook = HOOK_GetHook( id );
1163 next = HOOK_GetNextHook(hook);
1165 hptr = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
1166 if( hptr && hptr->ownerQueue )
1168 hptr->flags &= HOOK_MAPTYPE;
1169 HOOK_RemoveHook(hook);
1177 /***********************************************************************
1178 * SetWindowsHook (USER.121)
1180 FARPROC16 WINAPI SetWindowsHook16( INT16 id, HOOKPROC16 proc )
1182 HINSTANCE16 hInst = FarGetOwner16( HIWORD(proc) );
1184 /* WH_MSGFILTER is the only task-specific hook for SetWindowsHook() */
1185 HTASK16 hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
1187 return (FARPROC16)SetWindowsHookEx16( id, proc, hInst, hTask );
1190 /***********************************************************************
1191 * SetWindowsHookA (USER32.@)
1193 HHOOK WINAPI SetWindowsHookA( INT id, HOOKPROC proc )
1195 return SetWindowsHookExA( id, proc, 0, GetCurrentThreadId() );
1198 /***********************************************************************
1199 * SetWindowsHookW (USER32.@)
1201 HHOOK WINAPI SetWindowsHookW( INT id, HOOKPROC proc )
1203 return SetWindowsHookExW( id, proc, 0, GetCurrentThreadId() );
1207 /***********************************************************************
1208 * SetWindowsHookEx (USER.291)
1209 * SetWindowsHookEx16 (USER32.@)
1211 HHOOK WINAPI SetWindowsHookEx16( INT16 id, HOOKPROC16 proc, HINSTANCE16 hInst,
1216 FIXME("WH_DEBUG is broken in 16-bit Windows.\n");
1219 return HOOK_SetHook( id, proc, HOOK_WIN16, GetExePtr(hInst), (DWORD)hTask );
1222 /***********************************************************************
1223 * SetWindowsHookExA (USER32.@)
1225 HHOOK WINAPI SetWindowsHookExA( INT id, HOOKPROC proc, HINSTANCE hInst,
1228 return HOOK_SetHook( id, proc, HOOK_WIN32A, MapHModuleLS(hInst), dwThreadId );
1231 /***********************************************************************
1232 * SetWindowsHookExW (USER32.@)
1234 HHOOK WINAPI SetWindowsHookExW( INT id, HOOKPROC proc, HINSTANCE hInst,
1237 return HOOK_SetHook( id, proc, HOOK_WIN32W, MapHModuleLS(hInst), dwThreadId );
1241 /***********************************************************************
1242 * UnhookWindowsHook (USER.234)
1244 BOOL16 WINAPI UnhookWindowsHook16( INT16 id, HOOKPROC16 proc )
1246 return UnhookWindowsHook( id, (HOOKPROC)proc );
1249 /***********************************************************************
1250 * UnhookWindowsHook (USER32.@)
1252 BOOL WINAPI UnhookWindowsHook( INT id, HOOKPROC proc )
1254 HANDLE16 hook = HOOK_GetHook( id );
1256 TRACE("%d %08lx\n", id, (DWORD)proc );
1260 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
1261 if (data->proc == proc) break;
1262 hook = HOOK_GetNextHook( hook );
1264 if (!hook) return FALSE;
1265 return HOOK_RemoveHook( hook );
1269 /***********************************************************************
1270 * UnhookWindowsHookEx (USER.292)
1272 BOOL16 WINAPI UnhookWindowsHookEx16( HHOOK hhook )
1274 return UnhookWindowsHookEx( hhook );
1277 /***********************************************************************
1278 * UnhookWindowsHookEx (USER32.@)
1280 BOOL WINAPI UnhookWindowsHookEx( HHOOK hhook )
1282 if (HIWORD(hhook) != HOOK_MAGIC) return FALSE; /* Not a new format hook */
1283 return HOOK_RemoveHook( LOWORD(hhook) );
1287 /***********************************************************************
1288 * CallNextHookEx (USER.293)
1289 * CallNextHookEx16 (USER32.@)
1291 * I wouldn't have separated this into 16 and 32 bit versions, but I
1292 * need a way to figure out if I need to do a mapping or not.
1294 LRESULT WINAPI CallNextHookEx16( HHOOK hhook, INT16 code, WPARAM16 wParam,
1299 if (HIWORD(hhook) != HOOK_MAGIC) return 0; /* Not a new format hook */
1300 if (!(next = HOOK_GetNextHook( LOWORD(hhook) ))) return 0;
1302 return HOOK_CallHook( next, HOOK_WIN16, code, wParam, lParam );
1306 /***********************************************************************
1307 * CallNextHookEx (USER32.@)
1309 * There aren't ANSI and UNICODE versions of this.
1311 LRESULT WINAPI CallNextHookEx( HHOOK hhook, INT code, WPARAM wParam,
1315 INT fromtype; /* figure out Ansi/Unicode */
1318 if (HIWORD(hhook) != HOOK_MAGIC) return 0; /* Not a new format hook */
1319 if (!(next = HOOK_GetNextHook( LOWORD(hhook) ))) return 0;
1321 oldhook = (HOOKDATA *)USER_HEAP_LIN_ADDR( LOWORD(hhook) );
1322 fromtype = oldhook->flags & HOOK_MAPTYPE;
1324 if (fromtype == HOOK_WIN16)
1325 ERR("called from 16bit hook!\n");
1327 return HOOK_CallHook( next, fromtype, code, wParam, lParam );
1331 /***********************************************************************
1332 * DefHookProc (USER.235)
1334 LRESULT WINAPI DefHookProc16( INT16 code, WPARAM16 wParam, LPARAM lParam,
1337 /* Note: the *hhook parameter is never used, since we rely on the
1338 * current hook value from the task queue to find the next hook. */
1339 MESSAGEQUEUE *queue;
1341 if (!(queue = QUEUE_Current())) return 0;
1342 return CallNextHookEx16( queue->hCurHook, code, wParam, lParam );
1346 /***********************************************************************
1347 * CallMsgFilter (USER.123)
1349 BOOL16 WINAPI CallMsgFilter16( SEGPTR msg, INT16 code )
1351 if (GetSysModalWindow16()) return FALSE;
1352 if (HOOK_CallHooks16( WH_SYSMSGFILTER, code, 0, (LPARAM)msg )) return TRUE;
1353 return HOOK_CallHooks16( WH_MSGFILTER, code, 0, (LPARAM)msg );
1357 /***********************************************************************
1358 * CallMsgFilter32 (USER.823)
1360 BOOL16 WINAPI CallMsgFilter32_16( SEGPTR msg16_32, INT16 code, BOOL16 wHaveParamHigh )
1362 MSG32_16 *lpmsg16_32 = MapSL(msg16_32);
1364 if (wHaveParamHigh == FALSE)
1366 lpmsg16_32->wParamHigh = 0;
1367 /* WARNING: msg16_32->msg has to be the first variable in the struct */
1368 return CallMsgFilter16(msg16_32, code);
1375 msg32.hwnd = lpmsg16_32->msg.hwnd;
1376 msg32.message = lpmsg16_32->msg.message;
1378 MAKELONG(lpmsg16_32->msg.wParam, lpmsg16_32->wParamHigh);
1379 msg32.lParam = lpmsg16_32->msg.lParam;
1380 msg32.time = lpmsg16_32->msg.time;
1381 msg32.pt.x = (INT)lpmsg16_32->msg.pt.x;
1382 msg32.pt.y = (INT)lpmsg16_32->msg.pt.y;
1384 ret = (BOOL16)CallMsgFilterA(&msg32, (INT)code);
1386 lpmsg16_32->msg.hwnd = msg32.hwnd;
1387 lpmsg16_32->msg.message = msg32.message;
1388 lpmsg16_32->msg.wParam = LOWORD(msg32.wParam);
1389 lpmsg16_32->msg.lParam = msg32.lParam;
1390 lpmsg16_32->msg.time = msg32.time;
1391 lpmsg16_32->msg.pt.x = (INT16)msg32.pt.x;
1392 lpmsg16_32->msg.pt.y = (INT16)msg32.pt.y;
1393 lpmsg16_32->wParamHigh = HIWORD(msg32.wParam);
1400 /***********************************************************************
1401 * CallMsgFilterA (USER32.@)
1403 * FIXME: There are ANSI and UNICODE versions of this, plus an unspecified
1404 * version, plus USER (the 16bit one) has a CallMsgFilter32 function.
1406 BOOL WINAPI CallMsgFilterA( LPMSG msg, INT code )
1408 if (GetSysModalWindow16()) return FALSE; /* ??? */
1409 if (HOOK_CallHooksA( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
1411 return HOOK_CallHooksA( WH_MSGFILTER, code, 0, (LPARAM)msg );
1415 /***********************************************************************
1416 * CallMsgFilterW (USER32.@)
1418 BOOL WINAPI CallMsgFilterW( LPMSG msg, INT code )
1420 if (GetSysModalWindow16()) return FALSE; /* ??? */
1421 if (HOOK_CallHooksW( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
1423 return HOOK_CallHooksW( WH_MSGFILTER, code, 0, (LPARAM)msg );