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"
32 #include "debugtools.h"
34 DEFAULT_DEBUG_CHANNEL(hook);
38 /* Hook data (pointed to by a HHOOK) */
41 HANDLE16 next; /* 00 Next hook in chain */
42 HOOKPROC proc; /* 02 Hook procedure (original) */
43 INT16 id; /* 06 Hook id (WH_xxx) */
44 HQUEUE16 ownerQueue; /* 08 Owner queue (0 for system hook) */
45 HMODULE16 ownerModule; /* 0a Owner module */
46 WORD flags; /* 0c flags */
47 HOOKPROC thunk; /* 0e Hook procedure (CallTo16 thunk) */
52 #define HOOK_MAGIC ((int)'H' | (int)'K' << 8) /* 'HK' */
54 /* This should probably reside in USER heap */
55 static HANDLE16 HOOK_systemHooks[WH_NB_HOOKS] = { 0, };
57 typedef VOID (*HOOK_MapFunc)(INT, INT, WPARAM *, LPARAM *);
58 typedef VOID (*HOOK_UnMapFunc)(INT, INT, WPARAM, LPARAM, WPARAM,
61 /***********************************************************************
62 * HOOK_Map16To32Common
64 static void HOOK_Map16To32Common(INT id, INT code, WPARAM *pwParam,
65 LPARAM *plParam, BOOL bA )
73 case WH_JOURNALRECORD:
75 LPMSG16 lpmsg16 = MapSL(*plParam);
76 LPMSG lpmsg32 = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpmsg32) );
78 STRUCT32_MSG16to32( lpmsg16, lpmsg32 );
79 *plParam = (LPARAM)lpmsg32;
83 case WH_JOURNALPLAYBACK:
85 LPEVENTMSG16 lpem16 = MapSL(*plParam);
86 LPEVENTMSG lpem32 = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpem32) );
88 lpem32->message = lpem16->message;
89 lpem32->paramL = lpem16->paramL;
90 lpem32->paramH = lpem16->paramH;
91 lpem32->time = lpem16->time;
92 lpem32->hwnd = 0; /* FIXME */
94 *plParam = (LPARAM)lpem32;
100 LPCWPSTRUCT16 lpcwp16 = MapSL(*plParam);
101 LPCWPSTRUCT lpcwp32 = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpcwp32) );
103 lpcwp32->hwnd = lpcwp16->hwnd;
104 lpcwp32->lParam = lpcwp16->lParam;
106 if (bA) WINPROC_MapMsg16To32A( lpcwp16->message, lpcwp16->wParam,
107 &lpcwp32->message, &lpcwp32->wParam,
109 else WINPROC_MapMsg16To32W( lpcwp16->hwnd,lpcwp16->message, lpcwp16->wParam,
110 &lpcwp32->message, &lpcwp32->wParam,
112 *plParam = (LPARAM)lpcwp32;
121 LPCBT_CREATEWND16 lpcbtcw16 = MapSL(*plParam);
122 LPCREATESTRUCT16 lpcs16 = MapSL((SEGPTR)lpcbtcw16->lpcs);
123 LPCBT_CREATEWNDA lpcbtcw32 = HeapAlloc( GetProcessHeap(), 0,
124 sizeof(*lpcbtcw32) );
125 lpcbtcw32->lpcs = HeapAlloc( GetProcessHeap(), 0,
126 sizeof(*lpcbtcw32->lpcs) );
128 STRUCT32_CREATESTRUCT16to32A( lpcs16,
129 (LPCREATESTRUCTA)lpcbtcw32->lpcs );
131 if (HIWORD(lpcs16->lpszName))
132 lpcbtcw32->lpcs->lpszName =
133 (bA) ? MapSL(lpcs16->lpszName)
134 : HEAP_strdupAtoW( GetProcessHeap(), 0,
135 MapSL(lpcs16->lpszName) );
137 lpcbtcw32->lpcs->lpszName = (LPCSTR)lpcs16->lpszName;
139 if (HIWORD(lpcs16->lpszClass))
140 lpcbtcw32->lpcs->lpszClass =
141 (bA) ? MapSL(lpcs16->lpszClass)
142 : HEAP_strdupAtoW( GetProcessHeap(), 0,
143 MapSL(lpcs16->lpszClass) );
145 lpcbtcw32->lpcs->lpszClass = (LPCSTR)lpcs16->lpszClass;
147 lpcbtcw32->hwndInsertAfter = lpcbtcw16->hwndInsertAfter;
149 *plParam = (LPARAM)lpcbtcw32;
154 LPCBTACTIVATESTRUCT16 lpcas16 = MapSL(*plParam);
155 LPCBTACTIVATESTRUCT lpcas32 = HeapAlloc( GetProcessHeap(), 0,
157 lpcas32->fMouse = lpcas16->fMouse;
158 lpcas32->hWndActive = lpcas16->hWndActive;
159 *plParam = (LPARAM)lpcas32;
162 case HCBT_CLICKSKIPPED:
164 LPMOUSEHOOKSTRUCT16 lpms16 = MapSL(*plParam);
165 LPMOUSEHOOKSTRUCT lpms32 = HeapAlloc( GetProcessHeap(), 0,
168 CONV_POINT16TO32( &lpms16->pt, &lpms32->pt );
170 /* wHitTestCode may be negative, so convince compiler to do
171 correct sign extension. Yay. :| */
172 lpms32->wHitTestCode = (INT)((INT16)lpms16->wHitTestCode);
174 lpms32->dwExtraInfo = lpms16->dwExtraInfo;
175 lpms32->hwnd = lpms16->hwnd;
176 *plParam = (LPARAM)lpms32;
181 LPRECT16 lprect16 = MapSL(*plParam);
182 LPRECT lprect32 = HeapAlloc( GetProcessHeap(), 0,
185 CONV_RECT16TO32( lprect16, lprect32 );
186 *plParam = (LPARAM)lprect32;
194 LPMOUSEHOOKSTRUCT16 lpms16 = MapSL(*plParam);
195 LPMOUSEHOOKSTRUCT lpms32 = HeapAlloc( GetProcessHeap(), 0,
198 CONV_POINT16TO32( &lpms16->pt, &lpms32->pt );
200 /* wHitTestCode may be negative, so convince compiler to do
201 correct sign extension. Yay. :| */
202 lpms32->wHitTestCode = (INT)((INT16)lpms16->wHitTestCode);
203 lpms32->dwExtraInfo = lpms16->dwExtraInfo;
204 lpms32->hwnd = lpms16->hwnd;
205 *plParam = (LPARAM)lpms32;
211 LPDEBUGHOOKINFO16 lpdh16 = MapSL(*plParam);
212 LPDEBUGHOOKINFO lpdh32 = HeapAlloc( GetProcessHeap(), 0,
215 lpdh32->idThread = 0; /* FIXME */
216 lpdh32->idThreadInstaller = 0; /* FIXME */
217 lpdh32->lParam = lpdh16->lParam; /* FIXME Check for sign ext */
218 lpdh32->wParam = lpdh16->wParam;
219 lpdh32->code = lpdh16->code;
221 /* do sign extension if it was WH_MSGFILTER */
222 if (*pwParam == 0xffff) *pwParam = WH_MSGFILTER;
224 *plParam = (LPARAM)lpdh32;
233 case WH_FOREGROUNDIDLE:
234 case WH_CALLWNDPROCRET:
235 FIXME("\t[%i] 16to32 translation unimplemented\n", id);
240 /***********************************************************************
243 static void HOOK_Map16To32A(INT id, INT code, WPARAM *pwParam,
246 HOOK_Map16To32Common( id, code, pwParam, plParam, TRUE );
250 /***********************************************************************
253 static void HOOK_Map16To32W(INT id, INT code, WPARAM *pwParam,
256 HOOK_Map16To32Common( id, code, pwParam, plParam, FALSE );
260 /***********************************************************************
261 * HOOK_UnMap16To32Common
263 static void HOOK_UnMap16To32Common(INT id, INT code, WPARAM wParamOrig,
264 LPARAM lParamOrig, WPARAM wParam,
265 LPARAM lParam, BOOL bA)
270 case WH_SYSMSGFILTER:
271 case WH_JOURNALRECORD:
272 case WH_JOURNALPLAYBACK:
274 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
279 LPCWPSTRUCT lpcwp32 = (LPCWPSTRUCT)lParam;
280 if (bA) WINPROC_UnmapMsg16To32A( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
281 lpcwp32->lParam, 0 );
282 else WINPROC_UnmapMsg16To32W( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
283 lpcwp32->lParam, 0 );
284 HeapFree( GetProcessHeap(), 0, lpcwp32 );
290 LPMSG16 lpmsg16 = MapSL(lParamOrig);
291 STRUCT32_MSG32to16( (LPMSG)lParam, lpmsg16 );
292 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
299 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
307 LPCBT_CREATEWNDA lpcbtcw32 = (LPCBT_CREATEWNDA)lParam;
308 LPCBT_CREATEWND16 lpcbtcw16 = MapSL(lParamOrig);
312 if (HIWORD(lpcbtcw32->lpcs->lpszName))
313 HeapFree( GetProcessHeap(), 0, (LPWSTR)lpcbtcw32->lpcs->lpszName );
314 if (HIWORD(lpcbtcw32->lpcs->lpszClass))
315 HeapFree( GetProcessHeap(), 0, (LPWSTR)lpcbtcw32->lpcs->lpszClass );
318 lpcbtcw16->hwndInsertAfter = lpcbtcw32->hwndInsertAfter;
320 HeapFree( GetProcessHeap(), 0, lpcbtcw32->lpcs );
324 case HCBT_CLICKSKIPPED:
327 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam);
337 case WH_FOREGROUNDIDLE:
338 case WH_CALLWNDPROCRET:
339 FIXME("\t[%i] skipping unmap\n", id);
345 /***********************************************************************
348 static void HOOK_UnMap16To32A(INT id, INT code, WPARAM wParamOrig,
349 LPARAM lParamOrig, WPARAM wParam,
352 HOOK_UnMap16To32Common( id, code, wParamOrig, lParamOrig, wParam,
357 /***********************************************************************
360 static void HOOK_UnMap16To32W(INT id, INT code, WPARAM wParamOrig,
361 LPARAM lParamOrig, WPARAM wParam,
364 HOOK_UnMap16To32Common( id, code, wParamOrig, lParamOrig, wParam,
369 /***********************************************************************
370 * HOOK_Map32To16Common
372 static void HOOK_Map32To16Common(INT id, INT code, WPARAM *pwParam,
373 LPARAM *plParam, BOOL bA)
378 case WH_SYSMSGFILTER:
380 case WH_JOURNALRECORD:
382 LPMSG lpmsg32 = (LPMSG)*plParam;
383 LPMSG16 lpmsg16 = SEGPTR_NEW( MSG16 );
385 STRUCT32_MSG32to16( lpmsg32, lpmsg16 );
387 *plParam = (LPARAM)SEGPTR_GET( lpmsg16 );
391 case WH_JOURNALPLAYBACK:
393 LPEVENTMSG lpem32 = (LPEVENTMSG)*plParam;
394 LPEVENTMSG16 lpem16 = SEGPTR_NEW( EVENTMSG16 );
396 lpem16->message = lpem32->message;
397 lpem16->paramL = lpem32->paramL;
398 lpem16->paramH = lpem32->paramH;
399 lpem16->time = lpem32->time;
401 *plParam = (LPARAM)SEGPTR_GET( lpem16 );
407 LPCWPSTRUCT lpcwp32 = (LPCWPSTRUCT)*plParam;
408 LPCWPSTRUCT16 lpcwp16 = SEGPTR_NEW( CWPSTRUCT16 );
410 lpcwp16->hwnd = lpcwp32->hwnd;
411 lpcwp16->lParam = lpcwp32->lParam;
413 if (bA) WINPROC_MapMsg32ATo16( lpcwp32->hwnd, lpcwp32->message,
414 lpcwp32->wParam, &lpcwp16->message,
415 &lpcwp16->wParam, &lpcwp16->lParam );
416 else WINPROC_MapMsg32WTo16( lpcwp32->hwnd, lpcwp32->message,
417 lpcwp32->wParam, &lpcwp16->message,
418 &lpcwp16->wParam, &lpcwp16->lParam );
419 *plParam = (LPARAM)SEGPTR_GET( lpcwp16 );
428 LPCBTACTIVATESTRUCT lpcas32 = (LPCBTACTIVATESTRUCT)*plParam;
429 LPCBTACTIVATESTRUCT16 lpcas16 =SEGPTR_NEW( CBTACTIVATESTRUCT16 );
431 lpcas16->fMouse = lpcas32->fMouse;
432 lpcas16->hWndActive = lpcas32->hWndActive;
434 *plParam = (LPARAM)SEGPTR_GET( lpcas16 );
438 case HCBT_CLICKSKIPPED:
440 LPMOUSEHOOKSTRUCT lpms32 = (LPMOUSEHOOKSTRUCT)*plParam;
441 LPMOUSEHOOKSTRUCT16 lpms16 = SEGPTR_NEW( MOUSEHOOKSTRUCT16 );
443 CONV_POINT32TO16( &lpms32->pt, &lpms16->pt );
445 lpms16->hwnd = lpms32->hwnd;
446 lpms16->wHitTestCode = lpms32->wHitTestCode;
447 lpms16->dwExtraInfo = lpms32->dwExtraInfo;
449 *plParam = (LPARAM)SEGPTR_GET( lpms16 );
455 LPRECT lprect32 = (LPRECT)*plParam;
456 LPRECT16 lprect16 = SEGPTR_NEW( RECT16 );
458 CONV_RECT32TO16( lprect32, lprect16 );
460 *plParam = (LPARAM)SEGPTR_GET( lprect16 );
468 LPMOUSEHOOKSTRUCT lpms32 = (LPMOUSEHOOKSTRUCT)*plParam;
469 LPMOUSEHOOKSTRUCT16 lpms16 = SEGPTR_NEW( MOUSEHOOKSTRUCT16 );
471 CONV_POINT32TO16( &lpms32->pt, &lpms16->pt );
473 lpms16->hwnd = lpms32->hwnd;
474 lpms16->wHitTestCode = lpms32->wHitTestCode;
475 lpms16->dwExtraInfo = lpms32->dwExtraInfo;
477 *plParam = (LPARAM)SEGPTR_GET( lpms16 );
483 LPDEBUGHOOKINFO lpdh32 = (LPDEBUGHOOKINFO)*plParam;
484 LPDEBUGHOOKINFO16 lpdh16 = SEGPTR_NEW( DEBUGHOOKINFO16 );
486 lpdh16->hModuleHook = 0; /* FIXME */
487 lpdh16->reserved = 0;
488 lpdh16->lParam = lpdh32->lParam;
489 lpdh16->wParam = lpdh32->wParam;
490 lpdh16->code = lpdh32->code;
492 *plParam = (LPARAM)SEGPTR_GET( lpdh16 );
501 case WH_FOREGROUNDIDLE:
502 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 = 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 = 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 = lpcbtcw16->hwndInsertAfter;
634 SEGPTR_FREE( lpcs16 );
638 case HCBT_CLICKSKIPPED:
641 SEGPTR_FREE( MapSL(lParam) );
651 case WH_FOREGROUNDIDLE:
652 case WH_CALLWNDPROCRET:
653 FIXME("\t[%i] skipping unmap\n", id);
658 /***********************************************************************
661 static void HOOK_UnMap32ATo16(INT id, INT code, WPARAM wParamOrig,
662 LPARAM lParamOrig, WPARAM wParam,
665 HOOK_UnMap32To16Common( id, code, wParamOrig, lParamOrig, wParam,
670 /***********************************************************************
673 static void HOOK_UnMap32WTo16(INT id, INT code, WPARAM wParamOrig,
674 LPARAM lParamOrig, WPARAM wParam,
677 HOOK_UnMap32To16Common( id, code, wParamOrig, lParamOrig, wParam,
682 /***********************************************************************
685 static void HOOK_Map32ATo32W(INT id, INT code, WPARAM *pwParam,
688 if (id == WH_CBT && code == HCBT_CREATEWND)
690 LPCBT_CREATEWNDA lpcbtcwA = (LPCBT_CREATEWNDA)*plParam;
691 LPCBT_CREATEWNDW lpcbtcwW = HeapAlloc( GetProcessHeap(), 0,
693 lpcbtcwW->lpcs = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpcbtcwW->lpcs) );
695 lpcbtcwW->hwndInsertAfter = lpcbtcwA->hwndInsertAfter;
696 *lpcbtcwW->lpcs = *(LPCREATESTRUCTW)lpcbtcwA->lpcs;
698 if (HIWORD(lpcbtcwA->lpcs->lpszName))
700 lpcbtcwW->lpcs->lpszName = HEAP_strdupAtoW( GetProcessHeap(), 0,
701 lpcbtcwA->lpcs->lpszName );
704 lpcbtcwW->lpcs->lpszName = (LPWSTR)lpcbtcwA->lpcs->lpszName;
706 if (HIWORD(lpcbtcwA->lpcs->lpszClass))
708 lpcbtcwW->lpcs->lpszClass = HEAP_strdupAtoW( GetProcessHeap(), 0,
709 lpcbtcwA->lpcs->lpszClass );
712 lpcbtcwW->lpcs->lpszClass = (LPCWSTR)lpcbtcwA->lpcs->lpszClass;
713 *plParam = (LPARAM)lpcbtcwW;
719 /***********************************************************************
722 static void HOOK_UnMap32ATo32W(INT id, INT code, WPARAM wParamOrig,
723 LPARAM lParamOrig, WPARAM wParam,
726 if (id == WH_CBT && code == HCBT_CREATEWND)
728 LPCBT_CREATEWNDW lpcbtcwW = (LPCBT_CREATEWNDW)lParam;
729 if (HIWORD(lpcbtcwW->lpcs->lpszName))
730 HeapFree( GetProcessHeap(), 0, (LPWSTR)lpcbtcwW->lpcs->lpszName );
731 if (HIWORD(lpcbtcwW->lpcs->lpszClass))
732 HeapFree( GetProcessHeap(), 0, (LPWSTR)lpcbtcwW->lpcs->lpszClass );
733 HeapFree( GetProcessHeap(), 0, lpcbtcwW->lpcs );
734 HeapFree( GetProcessHeap(), 0, lpcbtcwW );
740 /***********************************************************************
743 static void HOOK_Map32WTo32A(INT id, INT code, WPARAM *pwParam,
746 if (id == WH_CBT && code == HCBT_CREATEWND)
748 LPCBT_CREATEWNDW lpcbtcwW = (LPCBT_CREATEWNDW)*plParam;
749 LPCBT_CREATEWNDA lpcbtcwA = HeapAlloc( GetProcessHeap(), 0,
751 lpcbtcwA->lpcs = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpcbtcwA->lpcs) );
753 lpcbtcwA->hwndInsertAfter = lpcbtcwW->hwndInsertAfter;
754 *lpcbtcwA->lpcs = *(LPCREATESTRUCTA)lpcbtcwW->lpcs;
756 if (HIWORD(lpcbtcwW->lpcs->lpszName))
757 lpcbtcwA->lpcs->lpszName = HEAP_strdupWtoA( GetProcessHeap(), 0,
758 lpcbtcwW->lpcs->lpszName );
760 lpcbtcwA->lpcs->lpszName = (LPSTR)lpcbtcwW->lpcs->lpszName;
762 if (HIWORD(lpcbtcwW->lpcs->lpszClass))
763 lpcbtcwA->lpcs->lpszClass = HEAP_strdupWtoA( GetProcessHeap(), 0,
764 lpcbtcwW->lpcs->lpszClass );
766 lpcbtcwA->lpcs->lpszClass = (LPSTR)lpcbtcwW->lpcs->lpszClass;
767 *plParam = (LPARAM)lpcbtcwA;
773 /***********************************************************************
776 static void HOOK_UnMap32WTo32A(INT id, INT code, WPARAM wParamOrig,
777 LPARAM lParamOrig, WPARAM wParam,
780 if (id == WH_CBT && code == HCBT_CREATEWND)
782 LPCBT_CREATEWNDA lpcbtcwA = (LPCBT_CREATEWNDA)lParam;
783 if (HIWORD(lpcbtcwA->lpcs->lpszName))
784 HeapFree( GetProcessHeap(), 0, (LPSTR)lpcbtcwA->lpcs->lpszName );
785 if (HIWORD(lpcbtcwA->lpcs->lpszClass))
786 HeapFree( GetProcessHeap(), 0, (LPSTR)lpcbtcwA->lpcs->lpszClass );
787 HeapFree( GetProcessHeap(), 0, lpcbtcwA->lpcs );
788 HeapFree( GetProcessHeap(), 0, lpcbtcwA );
794 /***********************************************************************
795 * Map Function Tables
797 static const HOOK_MapFunc HOOK_MapFuncs[3][3] =
799 { NULL, HOOK_Map16To32A, HOOK_Map16To32W },
800 { HOOK_Map32ATo16, NULL, HOOK_Map32ATo32W },
801 { HOOK_Map32WTo16, HOOK_Map32WTo32A, NULL }
804 static const HOOK_UnMapFunc HOOK_UnMapFuncs[3][3] =
806 { NULL, HOOK_UnMap16To32A, HOOK_UnMap16To32W },
807 { HOOK_UnMap32ATo16, NULL, HOOK_UnMap32ATo32W },
808 { HOOK_UnMap32WTo16, HOOK_UnMap32WTo32A, NULL }
812 /***********************************************************************
816 /***********************************************************************
819 * Get the next hook of a given hook.
821 static HANDLE16 HOOK_GetNextHook( HANDLE16 hook )
823 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR( hook );
825 if (!data || !hook) return 0;
826 if (data->next) return data->next;
827 if (!data->ownerQueue) return 0; /* Already system hook */
829 /* Now start enumerating the system hooks */
830 return HOOK_systemHooks[data->id - WH_MINHOOK];
834 /***********************************************************************
837 * Get the first hook for a given type.
839 static HANDLE16 HOOK_GetHook( INT16 id, HQUEUE16 hQueue )
844 if ((queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue )) != NULL)
845 hook = queue->hooks[id - WH_MINHOOK];
846 if (!hook) hook = HOOK_systemHooks[id - WH_MINHOOK];
848 QUEUE_Unlock( queue );
853 /***********************************************************************
856 * Install a given hook.
858 /* ### start build ### */
859 extern LONG CALLBACK HOOK_CallTo16_long_wwl(FARPROC16,WORD,WORD,LONG);
860 /* ### stop build ### */
861 static HHOOK HOOK_SetHook( INT16 id, LPVOID proc, INT type,
862 HMODULE16 hModule, DWORD dwThreadId )
868 if ((id < WH_MINHOOK) || (id > WH_MAXHOOK)) return 0;
870 TRACE("Setting hook %d: %08x %04x %08lx\n",
871 id, (UINT)proc, hModule, dwThreadId );
873 /* Create task queue if none present */
876 if (id == WH_JOURNALPLAYBACK) EnableHardwareInput16(FALSE);
878 if (dwThreadId) /* Task-specific hook */
880 if ((id == WH_JOURNALRECORD) || (id == WH_JOURNALPLAYBACK) ||
881 (id == WH_SYSMSGFILTER)) return 0; /* System-only hooks */
882 if (!(hQueue = GetThreadQueue16( dwThreadId )))
886 /* Create the hook structure */
888 if (!(handle = USER_HEAP_ALLOC( sizeof(HOOKDATA) ))) return 0;
889 data = (HOOKDATA *) USER_HEAP_LIN_ADDR( handle );
892 data->ownerQueue = hQueue;
893 data->ownerModule = hModule;
896 /* Create CallTo16 thunk for 16-bit hooks */
898 if ( (data->flags & HOOK_MAPTYPE) == HOOK_WIN16 )
899 data->thunk = (HOOKPROC)THUNK_Alloc( (FARPROC16)data->proc,
900 (RELAY)HOOK_CallTo16_long_wwl );
902 data->thunk = data->proc;
904 if ( !data->thunk && data->proc )
906 USER_HEAP_FREE( handle );
910 /* Insert it in the correct linked list */
914 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue );
915 data->next = queue->hooks[id - WH_MINHOOK];
916 queue->hooks[id - WH_MINHOOK] = handle;
917 QUEUE_Unlock( queue );
921 data->next = HOOK_systemHooks[id - WH_MINHOOK];
922 HOOK_systemHooks[id - WH_MINHOOK] = handle;
924 TRACE("Setting hook %d: ret=%04x [next=%04x]\n",
925 id, handle, data->next );
927 return (HHOOK)( handle? MAKELONG( handle, HOOK_MAGIC ) : 0 );
931 /***********************************************************************
934 * Remove a hook from the list.
936 static BOOL HOOK_RemoveHook( HANDLE16 hook )
941 TRACE("Removing hook %04x\n", hook );
943 if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook))) return FALSE;
944 if (data->flags & HOOK_INUSE)
946 /* Mark it for deletion later on */
947 WARN("Hook still running, deletion delayed\n" );
948 data->proc = (HOOKPROC)0;
952 if (data->id == WH_JOURNALPLAYBACK) EnableHardwareInput16(TRUE);
954 /* Remove it from the linked list */
956 if (data->ownerQueue)
958 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( data->ownerQueue );
959 if (!queue) return FALSE;
960 prevHook = &queue->hooks[data->id - WH_MINHOOK];
961 QUEUE_Unlock( queue );
963 else prevHook = &HOOK_systemHooks[data->id - WH_MINHOOK];
965 while (*prevHook && *prevHook != hook)
966 prevHook = &((HOOKDATA *)USER_HEAP_LIN_ADDR(*prevHook))->next;
968 if (!*prevHook) return FALSE;
969 *prevHook = data->next;
971 if ( (data->flags & HOOK_MAPTYPE) == HOOK_WIN16 )
972 THUNK_Free( (FARPROC)data->thunk );
974 USER_HEAP_FREE( hook );
979 /***********************************************************************
982 static HANDLE16 HOOK_FindValidHook( HANDLE16 hook )
988 if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook))) return 0;
989 if (data->proc) return hook;
995 /***********************************************************************
998 * Call a hook procedure.
1000 static LRESULT HOOK_CallHook( HANDLE16 hook, INT fromtype, INT code,
1001 WPARAM wParam, LPARAM lParam )
1003 MESSAGEQUEUE *queue;
1005 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
1009 WPARAM wParamOrig = wParam;
1010 LPARAM lParamOrig = lParam;
1011 HOOK_MapFunc MapFunc;
1012 HOOK_UnMapFunc UnMapFunc;
1014 MapFunc = HOOK_MapFuncs[fromtype][data->flags & HOOK_MAPTYPE];
1015 UnMapFunc = HOOK_UnMapFuncs[fromtype][data->flags & HOOK_MAPTYPE];
1018 MapFunc( data->id, code, &wParam, &lParam );
1022 if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() ))) return 0;
1023 prevHook = queue->hCurHook;
1024 queue->hCurHook = hook;
1025 data->flags |= HOOK_INUSE;
1027 TRACE("Calling hook %04x: %d %08x %08lx\n",
1028 hook, code, wParam, lParam );
1030 /* Suspend window structure locks before calling user code */
1031 iWndsLocks = WIN_SuspendWndsLock();
1033 ret = data->thunk(code, wParam, lParam);
1035 /* Grrr. While the hook procedure is supposed to have an LRESULT return
1036 value even in Win16, it seems that for those hook types where the
1037 return value is interpreted as BOOL, Windows doesn't actually check
1038 the HIWORD ... Some buggy Win16 programs, notably WINFILE, rely on
1039 that, because they neglect to clear DX ... */
1040 if ( (data->flags & HOOK_MAPTYPE) == HOOK_WIN16
1041 && data->id != WH_JOURNALPLAYBACK )
1042 ret = LOWORD( ret );
1044 WIN_RestoreWndsLock(iWndsLocks);
1046 TRACE("Ret hook %04x = %08lx\n", hook, ret );
1048 data->flags &= ~HOOK_INUSE;
1049 queue->hCurHook = prevHook;
1051 QUEUE_Unlock( queue );
1054 UnMapFunc( data->id, code, wParamOrig, lParamOrig, wParam, lParam );
1056 if (!data->proc) HOOK_RemoveHook( hook );
1061 /***********************************************************************
1062 * Exported Functions & APIs
1065 /***********************************************************************
1068 * Replacement for calling HOOK_GetHook from other modules.
1070 BOOL HOOK_IsHooked( INT16 id )
1072 /* Hmmm. Use GetThreadQueue(0) instead of GetFastQueue() here to
1073 avoid queue being created if someone wants to merely check ... */
1075 return HOOK_GetHook( id, GetThreadQueue16(0) ) != 0;
1079 /***********************************************************************
1082 * Call a hook chain.
1084 LRESULT HOOK_CallHooks16( INT16 id, INT16 code, WPARAM16 wParam,
1089 if (!(hook = HOOK_GetHook( id, GetFastQueue16() ))) return 0;
1090 if (!(hook = HOOK_FindValidHook(hook))) return 0;
1091 return HOOK_CallHook( hook, HOOK_WIN16, code, wParam, lParam );
1094 /***********************************************************************
1097 * Call a hook chain.
1099 LRESULT HOOK_CallHooksA( INT id, INT code, WPARAM wParam,
1104 if (!(hook = HOOK_GetHook( id, GetFastQueue16() ))) return 0;
1105 if (!(hook = HOOK_FindValidHook(hook))) return 0;
1106 return HOOK_CallHook( hook, HOOK_WIN32A, code, wParam, lParam );
1109 /***********************************************************************
1112 * Call a hook chain.
1114 LRESULT HOOK_CallHooksW( INT id, INT code, WPARAM wParam,
1119 if (!(hook = HOOK_GetHook( id, GetFastQueue16() ))) return 0;
1120 if (!(hook = HOOK_FindValidHook(hook))) return 0;
1121 return HOOK_CallHook( hook, HOOK_WIN32W, code, wParam,
1126 /***********************************************************************
1127 * HOOK_ResetQueueHooks
1129 void HOOK_ResetQueueHooks( HQUEUE16 hQueue )
1131 MESSAGEQUEUE *queue;
1133 if ((queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue )) != NULL)
1138 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
1140 hook = queue->hooks[id - WH_MINHOOK];
1143 if( (data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook)) )
1145 data->ownerQueue = hQueue;
1151 QUEUE_Unlock( queue );
1155 /***********************************************************************
1156 * HOOK_FreeModuleHooks
1158 void HOOK_FreeModuleHooks( HMODULE16 hModule )
1160 /* remove all system hooks registered by this module */
1166 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
1168 hook = HOOK_systemHooks[id - WH_MINHOOK];
1170 if( (hptr = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook)) )
1173 if( hptr->ownerModule == hModule )
1175 hptr->flags &= HOOK_MAPTYPE;
1176 HOOK_RemoveHook(hook);
1184 /***********************************************************************
1185 * HOOK_FreeQueueHooks
1187 void HOOK_FreeQueueHooks( HQUEUE16 hQueue )
1189 /* remove all hooks registered by this queue */
1191 HOOKDATA* hptr = NULL;
1195 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
1197 hook = HOOK_GetHook( id, hQueue );
1200 next = HOOK_GetNextHook(hook);
1202 hptr = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
1203 if( hptr && hptr->ownerQueue == hQueue )
1205 hptr->flags &= HOOK_MAPTYPE;
1206 HOOK_RemoveHook(hook);
1214 /***********************************************************************
1215 * SetWindowsHook16 (USER.121)
1217 FARPROC16 WINAPI SetWindowsHook16( INT16 id, HOOKPROC16 proc )
1219 HINSTANCE16 hInst = FarGetOwner16( HIWORD(proc) );
1221 /* WH_MSGFILTER is the only task-specific hook for SetWindowsHook() */
1222 HTASK16 hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
1224 return (FARPROC16)SetWindowsHookEx16( id, proc, hInst, hTask );
1227 /***********************************************************************
1228 * SetWindowsHookA (USER32.@)
1230 HHOOK WINAPI SetWindowsHookA( INT id, HOOKPROC proc )
1232 return SetWindowsHookExA( id, proc, 0, GetCurrentThreadId() );
1235 /***********************************************************************
1236 * SetWindowsHookW (USER32.@)
1238 HHOOK WINAPI SetWindowsHookW( INT id, HOOKPROC proc )
1240 return SetWindowsHookExW( id, proc, 0, GetCurrentThreadId() );
1244 /***********************************************************************
1245 * SetWindowsHookEx16 (USER.291) (USER32.@)
1247 HHOOK WINAPI SetWindowsHookEx16( INT16 id, HOOKPROC16 proc, HINSTANCE16 hInst,
1252 FIXME("WH_DEBUG is broken in 16-bit Windows.\n");
1255 return HOOK_SetHook( id, proc, HOOK_WIN16, GetExePtr(hInst), (DWORD)hTask );
1258 /***********************************************************************
1259 * SetWindowsHookExA (USER32.@)
1261 HHOOK WINAPI SetWindowsHookExA( INT id, HOOKPROC proc, HINSTANCE hInst,
1264 return HOOK_SetHook( id, proc, HOOK_WIN32A, MapHModuleLS(hInst), dwThreadId );
1267 /***********************************************************************
1268 * SetWindowsHookExW (USER32.@)
1270 HHOOK WINAPI SetWindowsHookExW( INT id, HOOKPROC proc, HINSTANCE hInst,
1273 return HOOK_SetHook( id, proc, HOOK_WIN32W, MapHModuleLS(hInst), dwThreadId );
1277 /***********************************************************************
1278 * UnhookWindowsHook (USER.234)
1280 BOOL16 WINAPI UnhookWindowsHook16( INT16 id, HOOKPROC16 proc )
1282 return UnhookWindowsHook( id, (HOOKPROC)proc );
1285 /***********************************************************************
1286 * UnhookWindowsHook (USER32.@)
1288 BOOL WINAPI UnhookWindowsHook( INT id, HOOKPROC proc )
1290 HANDLE16 hook = HOOK_GetHook( id, GetFastQueue16() );
1292 TRACE("%d %08lx\n", id, (DWORD)proc );
1296 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
1297 if (data->proc == proc) break;
1298 hook = HOOK_GetNextHook( hook );
1300 if (!hook) return FALSE;
1301 return HOOK_RemoveHook( hook );
1305 /***********************************************************************
1306 * UnhookWindowsHookEx (USER.292)
1308 BOOL16 WINAPI UnhookWindowsHookEx16( HHOOK hhook )
1310 return UnhookWindowsHookEx( hhook );
1313 /***********************************************************************
1314 * UnhookWindowsHookEx (USER32.@)
1316 BOOL WINAPI UnhookWindowsHookEx( HHOOK hhook )
1318 if (HIWORD(hhook) != HOOK_MAGIC) return FALSE; /* Not a new format hook */
1319 return HOOK_RemoveHook( LOWORD(hhook) );
1323 /***********************************************************************
1324 * CallNextHookEx16 (USER.293) (USER32.@)
1326 * I wouldn't have separated this into 16 and 32 bit versions, but I
1327 * need a way to figure out if I need to do a mapping or not.
1329 LRESULT WINAPI CallNextHookEx16( HHOOK hhook, INT16 code, WPARAM16 wParam,
1334 if (HIWORD(hhook) != HOOK_MAGIC) return 0; /* Not a new format hook */
1335 if (!(next = HOOK_GetNextHook( LOWORD(hhook) ))) return 0;
1337 return HOOK_CallHook( next, HOOK_WIN16, code, wParam, lParam );
1341 /***********************************************************************
1342 * CallNextHookEx (USER32.@)
1344 * There aren't ANSI and UNICODE versions of this.
1346 LRESULT WINAPI CallNextHookEx( HHOOK hhook, INT code, WPARAM wParam,
1350 INT fromtype; /* figure out Ansi/Unicode */
1353 if (HIWORD(hhook) != HOOK_MAGIC) return 0; /* Not a new format hook */
1354 if (!(next = HOOK_GetNextHook( LOWORD(hhook) ))) return 0;
1356 oldhook = (HOOKDATA *)USER_HEAP_LIN_ADDR( LOWORD(hhook) );
1357 fromtype = oldhook->flags & HOOK_MAPTYPE;
1359 if (fromtype == HOOK_WIN16)
1360 ERR("called from 16bit hook!\n");
1362 return HOOK_CallHook( next, fromtype, code, wParam, lParam );
1366 /***********************************************************************
1367 * DefHookProc (USER.235)
1369 LRESULT WINAPI DefHookProc16( INT16 code, WPARAM16 wParam, LPARAM lParam,
1372 /* Note: the *hhook parameter is never used, since we rely on the
1373 * current hook value from the task queue to find the next hook. */
1374 MESSAGEQUEUE *queue;
1377 if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() ))) return 0;
1378 ret = CallNextHookEx16( queue->hCurHook, code, wParam, lParam );
1379 QUEUE_Unlock( queue );
1384 /***********************************************************************
1385 * CallMsgFilter (USER.123)
1387 BOOL16 WINAPI CallMsgFilter16( SEGPTR msg, INT16 code )
1389 if (GetSysModalWindow16()) return FALSE;
1390 if (HOOK_CallHooks16( WH_SYSMSGFILTER, code, 0, (LPARAM)msg )) return TRUE;
1391 return HOOK_CallHooks16( WH_MSGFILTER, code, 0, (LPARAM)msg );
1395 /***********************************************************************
1396 * CallMsgFilter32 (USER.823)
1398 BOOL16 WINAPI CallMsgFilter32_16( SEGPTR msg16_32, INT16 code, BOOL16 wHaveParamHigh )
1400 MSG32_16 *lpmsg16_32 = MapSL(msg16_32);
1402 if (wHaveParamHigh == FALSE)
1404 lpmsg16_32->wParamHigh = 0;
1405 /* WARNING: msg16_32->msg has to be the first variable in the struct */
1406 return CallMsgFilter16(msg16_32, code);
1413 msg32.hwnd = lpmsg16_32->msg.hwnd;
1414 msg32.message = lpmsg16_32->msg.message;
1416 MAKELONG(lpmsg16_32->msg.wParam, lpmsg16_32->wParamHigh);
1417 msg32.lParam = lpmsg16_32->msg.lParam;
1418 msg32.time = lpmsg16_32->msg.time;
1419 msg32.pt.x = (INT)lpmsg16_32->msg.pt.x;
1420 msg32.pt.y = (INT)lpmsg16_32->msg.pt.y;
1422 ret = (BOOL16)CallMsgFilterA(&msg32, (INT)code);
1424 lpmsg16_32->msg.hwnd = msg32.hwnd;
1425 lpmsg16_32->msg.message = msg32.message;
1426 lpmsg16_32->msg.wParam = LOWORD(msg32.wParam);
1427 lpmsg16_32->msg.lParam = msg32.lParam;
1428 lpmsg16_32->msg.time = msg32.time;
1429 lpmsg16_32->msg.pt.x = (INT16)msg32.pt.x;
1430 lpmsg16_32->msg.pt.y = (INT16)msg32.pt.y;
1431 lpmsg16_32->wParamHigh = HIWORD(msg32.wParam);
1438 /***********************************************************************
1439 * CallMsgFilterA (USER32.@)
1441 * FIXME: There are ANSI and UNICODE versions of this, plus an unspecified
1442 * version, plus USER (the 16bit one) has a CallMsgFilter32 function.
1444 BOOL WINAPI CallMsgFilterA( LPMSG msg, INT code )
1446 if (GetSysModalWindow16()) return FALSE; /* ??? */
1447 if (HOOK_CallHooksA( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
1449 return HOOK_CallHooksA( WH_MSGFILTER, code, 0, (LPARAM)msg );
1453 /***********************************************************************
1454 * CallMsgFilterW (USER32.@)
1456 BOOL WINAPI CallMsgFilterW( LPMSG msg, INT code )
1458 if (GetSysModalWindow16()) return FALSE; /* ??? */
1459 if (HOOK_CallHooksW( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
1461 return HOOK_CallHooksW( WH_MSGFILTER, code, 0, (LPARAM)msg );