CreateFontIndirect() can get NULL pointers.
[wine.git] / windows / hook.c
blobdbe1d451bef90c6680d2b0603fed248673bfa908
1 /*
2 * Windows hook functions
4 * Copyright 1994, 1995 Alexandre Julliard
5 * 1996 Andrew Lewycky
7 * Based on investigations by Alex Korobka
8 */
11 * Warning!
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.
17 #include "windef.h"
18 #include "winbase.h"
19 #include "wingdi.h"
20 #include "winuser.h"
21 #include "wine/winuser16.h"
22 #include "wine/winbase16.h"
23 #include "callback.h"
24 #include "hook.h"
25 #include "win.h"
26 #include "queue.h"
27 #include "task.h"
28 #include "user.h"
29 #include "heap.h"
30 #include "struct32.h"
31 #include "winproc.h"
32 #include "debugtools.h"
34 DEFAULT_DEBUG_CHANNEL(hook);
36 #include "pshpack1.h"
38 /* Hook data (pointed to by a HHOOK) */
39 typedef struct
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) */
48 } HOOKDATA;
50 #include "poppack.h"
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,
59 LPARAM);
61 /***********************************************************************
62 * HOOK_Map16To32Common
64 static void HOOK_Map16To32Common(INT id, INT code, WPARAM *pwParam,
65 LPARAM *plParam, BOOL bA )
68 switch( id )
70 case WH_MSGFILTER:
71 case WH_SYSMSGFILTER:
72 case WH_GETMESSAGE:
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;
80 break;
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;
95 break;
98 case WH_CALLWNDPROC:
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,
108 &lpcwp32->lParam );
109 else WINPROC_MapMsg16To32W( lpcwp16->hwnd,lpcwp16->message, lpcwp16->wParam,
110 &lpcwp32->message, &lpcwp32->wParam,
111 &lpcwp32->lParam );
112 *plParam = (LPARAM)lpcwp32;
113 break;
116 case WH_CBT:
117 switch (code)
119 case HCBT_CREATEWND:
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) );
136 else
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) );
144 else
145 lpcbtcw32->lpcs->lpszClass = (LPCSTR)lpcs16->lpszClass;
147 lpcbtcw32->hwndInsertAfter = lpcbtcw16->hwndInsertAfter;
149 *plParam = (LPARAM)lpcbtcw32;
150 break;
152 case HCBT_ACTIVATE:
154 LPCBTACTIVATESTRUCT16 lpcas16 = MapSL(*plParam);
155 LPCBTACTIVATESTRUCT lpcas32 = HeapAlloc( GetProcessHeap(), 0,
156 sizeof(*lpcas32) );
157 lpcas32->fMouse = lpcas16->fMouse;
158 lpcas32->hWndActive = lpcas16->hWndActive;
159 *plParam = (LPARAM)lpcas32;
160 break;
162 case HCBT_CLICKSKIPPED:
164 LPMOUSEHOOKSTRUCT16 lpms16 = MapSL(*plParam);
165 LPMOUSEHOOKSTRUCT lpms32 = HeapAlloc( GetProcessHeap(), 0,
166 sizeof(*lpms32) );
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;
177 break;
179 case HCBT_MOVESIZE:
181 LPRECT16 lprect16 = MapSL(*plParam);
182 LPRECT lprect32 = HeapAlloc( GetProcessHeap(), 0,
183 sizeof(*lprect32) );
185 CONV_RECT16TO32( lprect16, lprect32 );
186 *plParam = (LPARAM)lprect32;
187 break;
190 break;
192 case WH_MOUSE:
194 LPMOUSEHOOKSTRUCT16 lpms16 = MapSL(*plParam);
195 LPMOUSEHOOKSTRUCT lpms32 = HeapAlloc( GetProcessHeap(), 0,
196 sizeof(*lpms32) );
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;
206 break;
209 case WH_DEBUG:
211 LPDEBUGHOOKINFO16 lpdh16 = MapSL(*plParam);
212 LPDEBUGHOOKINFO lpdh32 = HeapAlloc( GetProcessHeap(), 0,
213 sizeof(*lpdh32) );
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;
225 break;
228 case WH_SHELL:
229 case WH_KEYBOARD:
230 break;
232 case WH_HARDWARE:
233 case WH_FOREGROUNDIDLE:
234 case WH_CALLWNDPROCRET:
235 FIXME("\t[%i] 16to32 translation unimplemented\n", id);
240 /***********************************************************************
241 * HOOK_Map16To32A
243 static void HOOK_Map16To32A(INT id, INT code, WPARAM *pwParam,
244 LPARAM *plParam)
246 HOOK_Map16To32Common( id, code, pwParam, plParam, TRUE );
250 /***********************************************************************
251 * HOOK_Map16To32W
253 static void HOOK_Map16To32W(INT id, INT code, WPARAM *pwParam,
254 LPARAM *plParam)
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)
267 switch (id)
269 case WH_MSGFILTER:
270 case WH_SYSMSGFILTER:
271 case WH_JOURNALRECORD:
272 case WH_JOURNALPLAYBACK:
274 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
275 break;
277 case WH_CALLWNDPROC:
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 );
285 break;
288 case WH_GETMESSAGE:
290 LPMSG16 lpmsg16 = MapSL(lParamOrig);
291 STRUCT32_MSG32to16( (LPMSG)lParam, lpmsg16 );
292 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
293 break;
296 case WH_MOUSE:
297 case WH_DEBUG:
299 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
300 break;
302 case WH_CBT:
303 switch (code)
305 case HCBT_CREATEWND:
307 LPCBT_CREATEWNDA lpcbtcw32 = (LPCBT_CREATEWNDA)lParam;
308 LPCBT_CREATEWND16 lpcbtcw16 = MapSL(lParamOrig);
310 if( !bA )
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 );
321 } /* fall through */
323 case HCBT_ACTIVATE:
324 case HCBT_CLICKSKIPPED:
325 case HCBT_MOVESIZE:
327 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam);
328 break;
330 break;
332 case WH_SHELL:
333 case WH_KEYBOARD:
334 break;
336 case WH_HARDWARE:
337 case WH_FOREGROUNDIDLE:
338 case WH_CALLWNDPROCRET:
339 FIXME("\t[%i] skipping unmap\n", id);
340 break;
345 /***********************************************************************
346 * HOOK_UnMap16To32A
348 static void HOOK_UnMap16To32A(INT id, INT code, WPARAM wParamOrig,
349 LPARAM lParamOrig, WPARAM wParam,
350 LPARAM lParam)
352 HOOK_UnMap16To32Common( id, code, wParamOrig, lParamOrig, wParam,
353 lParam, TRUE );
357 /***********************************************************************
358 * HOOK_UnMap16To32W
360 static void HOOK_UnMap16To32W(INT id, INT code, WPARAM wParamOrig,
361 LPARAM lParamOrig, WPARAM wParam,
362 LPARAM lParam)
364 HOOK_UnMap16To32Common( id, code, wParamOrig, lParamOrig, wParam,
365 lParam, FALSE );
369 /***********************************************************************
370 * HOOK_Map32To16Common
372 static void HOOK_Map32To16Common(INT id, INT code, WPARAM *pwParam,
373 LPARAM *plParam, BOOL bA)
375 switch (id)
377 case WH_MSGFILTER:
378 case WH_SYSMSGFILTER:
379 case WH_GETMESSAGE:
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 );
388 break;
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 );
402 break;
405 case WH_CALLWNDPROC:
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 );
420 break;
423 case WH_CBT:
424 switch (code)
426 case HCBT_ACTIVATE:
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 );
435 break;
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 );
450 break;
453 case HCBT_MOVESIZE:
455 LPRECT lprect32 = (LPRECT)*plParam;
456 LPRECT16 lprect16 = SEGPTR_NEW( RECT16 );
458 CONV_RECT32TO16( lprect32, lprect16 );
460 *plParam = (LPARAM)SEGPTR_GET( lprect16 );
461 break;
464 break;
466 case WH_MOUSE:
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 );
478 break;
481 case WH_DEBUG:
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 );
493 break;
496 case WH_SHELL:
497 case WH_KEYBOARD:
498 break;
500 case WH_HARDWARE:
501 case WH_FOREGROUNDIDLE:
502 case WH_CALLWNDPROCRET:
503 FIXME("\t[%i] 32to16 translation unimplemented\n", id);
508 /***********************************************************************
509 * HOOK_Map32ATo16
511 static void HOOK_Map32ATo16(INT id, INT code, WPARAM *pwParam,
512 LPARAM *plParam)
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))
524 lpcs16->lpszName =
525 SEGPTR_GET( SEGPTR_STRDUP( lpcbtcw32->lpcs->lpszName ) );
526 else
527 lpcs16->lpszName = (SEGPTR)lpcbtcw32->lpcs->lpszName;
529 if (HIWORD(lpcbtcw32->lpcs->lpszClass))
530 lpcs16->lpszClass =
531 SEGPTR_GET( SEGPTR_STRDUP( lpcbtcw32->lpcs->lpszClass ) );
532 else
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 /***********************************************************************
544 * HOOK_Map32WTo16
546 static void HOOK_Map32WTo16(INT id, INT code, WPARAM *pwParam,
547 LPARAM *plParam)
549 if (id == WH_CBT && code == HCBT_CREATEWND)
551 LPSTR name, cls;
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,
558 lpcs16 );
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)
579 switch (id)
581 case WH_MSGFILTER:
582 case WH_SYSMSGFILTER:
583 case WH_JOURNALRECORD:
584 case WH_JOURNALPLAYBACK:
585 case WH_MOUSE:
586 case WH_DEBUG:
587 SEGPTR_FREE( MapSL(lParam) );
588 break;
590 case WH_CALLWNDPROC:
592 LPCWPSTRUCT16 lpcwp16 = MapSL(lParam);
593 LPCWPSTRUCT lpcwp32 = (LPCWPSTRUCT)lParamOrig;
594 MSGPARAM16 mp16;
596 mp16.wParam = lpcwp16->wParam;
597 mp16.lParam = lpcwp16->lParam;
598 mp16.lResult = 0;
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) );
605 break;
608 case WH_GETMESSAGE:
610 LPMSG lpmsg32 = (LPMSG)lParamOrig;
612 STRUCT32_MSG16to32( MapSL(lParam), lpmsg32 );
613 SEGPTR_FREE( MapSL(lParam) );
614 break;
617 case WH_CBT:
618 switch (code)
620 case HCBT_CREATEWND:
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 );
635 } /* fall through */
637 case HCBT_ACTIVATE:
638 case HCBT_CLICKSKIPPED:
639 case HCBT_MOVESIZE:
641 SEGPTR_FREE( MapSL(lParam) );
642 break;
644 break;
646 case WH_SHELL:
647 case WH_KEYBOARD:
648 break;
650 case WH_HARDWARE:
651 case WH_FOREGROUNDIDLE:
652 case WH_CALLWNDPROCRET:
653 FIXME("\t[%i] skipping unmap\n", id);
658 /***********************************************************************
659 * HOOK_UnMap32ATo16
661 static void HOOK_UnMap32ATo16(INT id, INT code, WPARAM wParamOrig,
662 LPARAM lParamOrig, WPARAM wParam,
663 LPARAM lParam)
665 HOOK_UnMap32To16Common( id, code, wParamOrig, lParamOrig, wParam,
666 lParam, TRUE );
670 /***********************************************************************
671 * HOOK_UnMap32WTo16
673 static void HOOK_UnMap32WTo16(INT id, INT code, WPARAM wParamOrig,
674 LPARAM lParamOrig, WPARAM wParam,
675 LPARAM lParam)
677 HOOK_UnMap32To16Common( id, code, wParamOrig, lParamOrig, wParam,
678 lParam, FALSE );
682 /***********************************************************************
683 * HOOK_Map32ATo32W
685 static void HOOK_Map32ATo32W(INT id, INT code, WPARAM *pwParam,
686 LPARAM *plParam)
688 if (id == WH_CBT && code == HCBT_CREATEWND)
690 LPCBT_CREATEWNDA lpcbtcwA = (LPCBT_CREATEWNDA)*plParam;
691 LPCBT_CREATEWNDW lpcbtcwW = HeapAlloc( GetProcessHeap(), 0,
692 sizeof(*lpcbtcwW) );
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 );
703 else
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 );
711 else
712 lpcbtcwW->lpcs->lpszClass = (LPCWSTR)lpcbtcwA->lpcs->lpszClass;
713 *plParam = (LPARAM)lpcbtcwW;
715 return;
719 /***********************************************************************
720 * HOOK_UnMap32ATo32W
722 static void HOOK_UnMap32ATo32W(INT id, INT code, WPARAM wParamOrig,
723 LPARAM lParamOrig, WPARAM wParam,
724 LPARAM lParam)
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 );
736 return;
740 /***********************************************************************
741 * HOOK_Map32WTo32A
743 static void HOOK_Map32WTo32A(INT id, INT code, WPARAM *pwParam,
744 LPARAM *plParam)
746 if (id == WH_CBT && code == HCBT_CREATEWND)
748 LPCBT_CREATEWNDW lpcbtcwW = (LPCBT_CREATEWNDW)*plParam;
749 LPCBT_CREATEWNDA lpcbtcwA = HeapAlloc( GetProcessHeap(), 0,
750 sizeof(*lpcbtcwA) );
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 );
759 else
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 );
765 else
766 lpcbtcwA->lpcs->lpszClass = (LPSTR)lpcbtcwW->lpcs->lpszClass;
767 *plParam = (LPARAM)lpcbtcwA;
769 return;
773 /***********************************************************************
774 * HOOK_UnMap32WTo32A
776 static void HOOK_UnMap32WTo32A(INT id, INT code, WPARAM wParamOrig,
777 LPARAM lParamOrig, WPARAM wParam,
778 LPARAM lParam)
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 );
790 return;
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 /***********************************************************************
813 * Internal Functions
816 /***********************************************************************
817 * HOOK_GetNextHook
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 /***********************************************************************
835 * HOOK_GetHook
837 * Get the first hook for a given type.
839 static HANDLE16 HOOK_GetHook( INT16 id, HQUEUE16 hQueue )
841 MESSAGEQUEUE *queue;
842 HANDLE16 hook = 0;
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 );
849 return hook;
853 /***********************************************************************
854 * HOOK_SetHook
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 )
864 HOOKDATA *data;
865 HANDLE16 handle;
866 HQUEUE16 hQueue = 0;
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 */
874 GetFastQueue16();
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 )))
883 return 0;
886 /* Create the hook structure */
888 if (!(handle = USER_HEAP_ALLOC( sizeof(HOOKDATA) ))) return 0;
889 data = (HOOKDATA *) USER_HEAP_LIN_ADDR( handle );
890 data->proc = proc;
891 data->id = id;
892 data->ownerQueue = hQueue;
893 data->ownerModule = hModule;
894 data->flags = type;
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 );
901 else
902 data->thunk = data->proc;
904 if ( !data->thunk && data->proc )
906 USER_HEAP_FREE( handle );
907 return 0;
910 /* Insert it in the correct linked list */
912 if (hQueue)
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 );
919 else
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 /***********************************************************************
932 * HOOK_RemoveHook
934 * Remove a hook from the list.
936 static BOOL HOOK_RemoveHook( HANDLE16 hook )
938 HOOKDATA *data;
939 HANDLE16 *prevHook;
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;
949 return TRUE;
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 );
975 return TRUE;
979 /***********************************************************************
980 * HOOK_FindValidHook
982 static HANDLE16 HOOK_FindValidHook( HANDLE16 hook )
984 HOOKDATA *data;
986 for (;;)
988 if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook))) return 0;
989 if (data->proc) return hook;
990 hook = data->next;
995 /***********************************************************************
996 * HOOK_CallHook
998 * Call a hook procedure.
1000 static LRESULT HOOK_CallHook( HANDLE16 hook, INT fromtype, INT code,
1001 WPARAM wParam, LPARAM lParam )
1003 MESSAGEQUEUE *queue;
1004 HANDLE16 prevHook;
1005 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
1006 LRESULT ret;
1007 int iWndsLocks;
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];
1017 if (MapFunc)
1018 MapFunc( data->id, code, &wParam, &lParam );
1020 /* Now call it */
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 );
1053 if (UnMapFunc)
1054 UnMapFunc( data->id, code, wParamOrig, lParamOrig, wParam, lParam );
1056 if (!data->proc) HOOK_RemoveHook( hook );
1058 return ret;
1061 /***********************************************************************
1062 * Exported Functions & APIs
1065 /***********************************************************************
1066 * HOOK_IsHooked
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 /***********************************************************************
1080 * HOOK_CallHooks16
1082 * Call a hook chain.
1084 LRESULT HOOK_CallHooks16( INT16 id, INT16 code, WPARAM16 wParam,
1085 LPARAM lParam )
1087 HANDLE16 hook;
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 /***********************************************************************
1095 * HOOK_CallHooksA
1097 * Call a hook chain.
1099 LRESULT HOOK_CallHooksA( INT id, INT code, WPARAM wParam,
1100 LPARAM lParam )
1102 HANDLE16 hook;
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 /***********************************************************************
1110 * HOOK_CallHooksW
1112 * Call a hook chain.
1114 LRESULT HOOK_CallHooksW( INT id, INT code, WPARAM wParam,
1115 LPARAM lParam )
1117 HANDLE16 hook;
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,
1122 lParam );
1126 /***********************************************************************
1127 * HOOK_ResetQueueHooks
1129 void HOOK_ResetQueueHooks( HQUEUE16 hQueue )
1131 MESSAGEQUEUE *queue;
1133 if ((queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue )) != NULL)
1135 HOOKDATA* data;
1136 HHOOK hook;
1137 int id;
1138 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
1140 hook = queue->hooks[id - WH_MINHOOK];
1141 while( hook )
1143 if( (data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook)) )
1145 data->ownerQueue = hQueue;
1146 hook = data->next;
1147 } else break;
1151 QUEUE_Unlock( queue );
1155 /***********************************************************************
1156 * HOOK_FreeModuleHooks
1158 void HOOK_FreeModuleHooks( HMODULE16 hModule )
1160 /* remove all system hooks registered by this module */
1162 HOOKDATA* hptr;
1163 HHOOK hook, next;
1164 int id;
1166 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
1168 hook = HOOK_systemHooks[id - WH_MINHOOK];
1169 while( hook )
1170 if( (hptr = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook)) )
1172 next = hptr->next;
1173 if( hptr->ownerModule == hModule )
1175 hptr->flags &= HOOK_MAPTYPE;
1176 HOOK_RemoveHook(hook);
1178 hook = next;
1180 else hook = 0;
1184 /***********************************************************************
1185 * HOOK_FreeQueueHooks
1187 void HOOK_FreeQueueHooks( HQUEUE16 hQueue )
1189 /* remove all hooks registered by this queue */
1191 HOOKDATA* hptr = NULL;
1192 HHOOK hook, next;
1193 int id;
1195 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
1197 hook = HOOK_GetHook( id, hQueue );
1198 while( hook )
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);
1208 hook = next;
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,
1248 HTASK16 hTask )
1250 if (id == WH_DEBUG)
1252 FIXME("WH_DEBUG is broken in 16-bit Windows.\n");
1253 return 0;
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,
1262 DWORD dwThreadId )
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,
1271 DWORD dwThreadId )
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 );
1294 while (hook)
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,
1330 LPARAM lParam )
1332 HANDLE16 next;
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,
1347 LPARAM lParam )
1349 HANDLE16 next;
1350 INT fromtype; /* figure out Ansi/Unicode */
1351 HOOKDATA *oldhook;
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,
1370 HHOOK *hhook )
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;
1375 LRESULT ret;
1377 if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() ))) return 0;
1378 ret = CallNextHookEx16( queue->hCurHook, code, wParam, lParam );
1379 QUEUE_Unlock( queue );
1380 return ret;
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);
1408 else
1410 MSG msg32;
1411 BOOL16 ret;
1413 msg32.hwnd = lpmsg16_32->msg.hwnd;
1414 msg32.message = lpmsg16_32->msg.message;
1415 msg32.wParam =
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);
1433 return ret;
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 ))
1448 return TRUE;
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 ))
1460 return TRUE;
1461 return HOOK_CallHooksW( WH_MSGFILTER, code, 0, (LPARAM)msg );