Add support for anonymous struct/unions on compilers that implement it.
[wine.git] / windows / hook.c
blobe9812de531cbc90686f15472a750dd44a66e97f4
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 "winuser.h"
18 #include "wine/winuser16.h"
19 #include "wine/winbase16.h"
20 #include "hook.h"
21 #include "win.h"
22 #include "queue.h"
23 #include "task.h"
24 #include "user.h"
25 #include "heap.h"
26 #include "struct32.h"
27 #include "winproc.h"
28 #include "debugtools.h"
30 DEFAULT_DEBUG_CHANNEL(hook)
32 #include "pshpack1.h"
34 /* Hook data (pointed to by a HHOOK) */
35 typedef struct
37 HANDLE16 next; /* 00 Next hook in chain */
38 HOOKPROC proc WINE_PACKED; /* 02 Hook procedure */
39 INT16 id; /* 06 Hook id (WH_xxx) */
40 HQUEUE16 ownerQueue; /* 08 Owner queue (0 for system hook) */
41 HMODULE16 ownerModule; /* 0a Owner module */
42 WORD flags; /* 0c flags */
43 } HOOKDATA;
45 #include "poppack.h"
47 #define HOOK_MAGIC ((int)'H' | (int)'K' << 8) /* 'HK' */
49 /* This should probably reside in USER heap */
50 static HANDLE16 HOOK_systemHooks[WH_NB_HOOKS] = { 0, };
52 typedef VOID (*HOOK_MapFunc)(INT, INT, WPARAM *, LPARAM *);
53 typedef VOID (*HOOK_UnMapFunc)(INT, INT, WPARAM, LPARAM, WPARAM,
54 LPARAM);
56 /***********************************************************************
57 * HOOK_Map16To32Common
59 static void HOOK_Map16To32Common(INT id, INT code, WPARAM *pwParam,
60 LPARAM *plParam, BOOL bA )
63 switch( id )
65 case WH_MSGFILTER:
66 case WH_SYSMSGFILTER:
67 case WH_GETMESSAGE:
68 case WH_JOURNALRECORD:
70 LPMSG16 lpmsg16 = PTR_SEG_TO_LIN(*plParam);
71 LPMSG lpmsg32 = HeapAlloc( SystemHeap, 0, sizeof(*lpmsg32) );
73 STRUCT32_MSG16to32( lpmsg16, lpmsg32 );
74 *plParam = (LPARAM)lpmsg32;
75 break;
78 case WH_JOURNALPLAYBACK:
80 LPEVENTMSG16 lpem16 = PTR_SEG_TO_LIN(*plParam);
81 LPEVENTMSG lpem32 = HeapAlloc( SystemHeap, 0, sizeof(*lpem32) );
83 lpem32->message = lpem16->message;
84 lpem32->paramL = lpem16->paramL;
85 lpem32->paramH = lpem16->paramH;
86 lpem32->time = lpem16->time;
87 lpem32->hwnd = 0; /* FIXME */
89 *plParam = (LPARAM)lpem32;
90 break;
93 case WH_CALLWNDPROC:
95 LPCWPSTRUCT16 lpcwp16 = PTR_SEG_TO_LIN(*plParam);
96 LPCWPSTRUCT lpcwp32 = HeapAlloc( SystemHeap, 0, sizeof(*lpcwp32) );
98 lpcwp32->hwnd = lpcwp16->hwnd;
99 lpcwp32->lParam = lpcwp16->lParam;
101 if (bA) WINPROC_MapMsg16To32A( lpcwp16->message, lpcwp16->wParam,
102 &lpcwp32->message, &lpcwp32->wParam,
103 &lpcwp32->lParam );
104 else WINPROC_MapMsg16To32W( lpcwp16->hwnd,lpcwp16->message, lpcwp16->wParam,
105 &lpcwp32->message, &lpcwp32->wParam,
106 &lpcwp32->lParam );
107 *plParam = (LPARAM)lpcwp32;
108 break;
111 case WH_CBT:
112 switch (code)
114 case HCBT_CREATEWND:
116 LPCBT_CREATEWND16 lpcbtcw16 = PTR_SEG_TO_LIN(*plParam);
117 LPCREATESTRUCT16 lpcs16 = PTR_SEG_TO_LIN(lpcbtcw16->lpcs);
118 LPCBT_CREATEWNDA lpcbtcw32 = HeapAlloc( SystemHeap, 0,
119 sizeof(*lpcbtcw32) );
120 lpcbtcw32->lpcs = HeapAlloc( SystemHeap, 0,
121 sizeof(*lpcbtcw32->lpcs) );
123 STRUCT32_CREATESTRUCT16to32A( lpcs16,
124 (LPCREATESTRUCTA)lpcbtcw32->lpcs );
126 if (HIWORD(lpcs16->lpszName))
127 lpcbtcw32->lpcs->lpszName =
128 (bA) ? PTR_SEG_TO_LIN(lpcs16->lpszName)
129 : HEAP_strdupAtoW( SystemHeap, 0,
130 PTR_SEG_TO_LIN(lpcs16->lpszName) );
131 else
132 lpcbtcw32->lpcs->lpszName = (LPCSTR)lpcs16->lpszName;
134 if (HIWORD(lpcs16->lpszClass))
135 lpcbtcw32->lpcs->lpszClass =
136 (bA) ? PTR_SEG_TO_LIN(lpcs16->lpszClass)
137 : HEAP_strdupAtoW( SystemHeap, 0,
138 PTR_SEG_TO_LIN(lpcs16->lpszClass) );
139 else
140 lpcbtcw32->lpcs->lpszClass = (LPCSTR)lpcs16->lpszClass;
142 lpcbtcw32->hwndInsertAfter = lpcbtcw16->hwndInsertAfter;
144 *plParam = (LPARAM)lpcbtcw32;
145 break;
147 case HCBT_ACTIVATE:
149 LPCBTACTIVATESTRUCT16 lpcas16 = PTR_SEG_TO_LIN(*plParam);
150 LPCBTACTIVATESTRUCT lpcas32 = HeapAlloc( SystemHeap, 0,
151 sizeof(*lpcas32) );
152 lpcas32->fMouse = lpcas16->fMouse;
153 lpcas32->hWndActive = lpcas16->hWndActive;
154 *plParam = (LPARAM)lpcas32;
155 break;
157 case HCBT_CLICKSKIPPED:
159 LPMOUSEHOOKSTRUCT16 lpms16 = PTR_SEG_TO_LIN(*plParam);
160 LPMOUSEHOOKSTRUCT lpms32 = HeapAlloc( SystemHeap, 0,
161 sizeof(*lpms32) );
163 CONV_POINT16TO32( &lpms16->pt, &lpms32->pt );
165 /* wHitTestCode may be negative, so convince compiler to do
166 correct sign extension. Yay. :| */
167 lpms32->wHitTestCode = (INT)((INT16)lpms16->wHitTestCode);
169 lpms32->dwExtraInfo = lpms16->dwExtraInfo;
170 lpms32->hwnd = lpms16->hwnd;
171 *plParam = (LPARAM)lpms32;
172 break;
174 case HCBT_MOVESIZE:
176 LPRECT16 lprect16 = PTR_SEG_TO_LIN(*plParam);
177 LPRECT lprect32 = HeapAlloc( SystemHeap, 0,
178 sizeof(*lprect32) );
180 CONV_RECT16TO32( lprect16, lprect32 );
181 *plParam = (LPARAM)lprect32;
182 break;
185 break;
187 case WH_MOUSE:
189 LPMOUSEHOOKSTRUCT16 lpms16 = PTR_SEG_TO_LIN(*plParam);
190 LPMOUSEHOOKSTRUCT lpms32 = HeapAlloc( SystemHeap, 0,
191 sizeof(*lpms32) );
193 CONV_POINT16TO32( &lpms16->pt, &lpms32->pt );
195 /* wHitTestCode may be negative, so convince compiler to do
196 correct sign extension. Yay. :| */
197 lpms32->wHitTestCode = (INT)((INT16)lpms16->wHitTestCode);
198 lpms32->dwExtraInfo = lpms16->dwExtraInfo;
199 lpms32->hwnd = lpms16->hwnd;
200 *plParam = (LPARAM)lpms32;
201 break;
204 case WH_DEBUG:
206 LPDEBUGHOOKINFO16 lpdh16 = PTR_SEG_TO_LIN(*plParam);
207 LPDEBUGHOOKINFO lpdh32 = HeapAlloc( SystemHeap, 0,
208 sizeof(*lpdh32) );
210 lpdh32->idThread = 0; /* FIXME */
211 lpdh32->idThreadInstaller = 0; /* FIXME */
212 lpdh32->lParam = lpdh16->lParam; /* FIXME Check for sign ext */
213 lpdh32->wParam = lpdh16->wParam;
214 lpdh32->code = lpdh16->code;
216 /* do sign extension if it was WH_MSGFILTER */
217 if (*pwParam == 0xffff) *pwParam = WH_MSGFILTER;
219 *plParam = (LPARAM)lpdh32;
220 break;
223 case WH_SHELL:
224 case WH_KEYBOARD:
225 break;
227 case WH_HARDWARE:
228 case WH_FOREGROUNDIDLE:
229 case WH_CALLWNDPROCRET:
230 FIXME("\t[%i] 16to32 translation unimplemented\n", id);
235 /***********************************************************************
236 * HOOK_Map16To32A
238 static void HOOK_Map16To32A(INT id, INT code, WPARAM *pwParam,
239 LPARAM *plParam)
241 HOOK_Map16To32Common( id, code, pwParam, plParam, TRUE );
245 /***********************************************************************
246 * HOOK_Map16To32W
248 static void HOOK_Map16To32W(INT id, INT code, WPARAM *pwParam,
249 LPARAM *plParam)
251 HOOK_Map16To32Common( id, code, pwParam, plParam, FALSE );
255 /***********************************************************************
256 * HOOK_UnMap16To32Common
258 static void HOOK_UnMap16To32Common(INT id, INT code, WPARAM wParamOrig,
259 LPARAM lParamOrig, WPARAM wParam,
260 LPARAM lParam, BOOL bA)
262 switch (id)
264 case WH_MSGFILTER:
265 case WH_SYSMSGFILTER:
266 case WH_JOURNALRECORD:
267 case WH_JOURNALPLAYBACK:
269 HeapFree( SystemHeap, 0, (LPVOID)lParam );
270 break;
272 case WH_CALLWNDPROC:
274 LPCWPSTRUCT lpcwp32 = (LPCWPSTRUCT)lParam;
275 if (bA) WINPROC_UnmapMsg16To32A( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
276 lpcwp32->lParam, 0 );
277 else WINPROC_UnmapMsg16To32W( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
278 lpcwp32->lParam, 0 );
279 HeapFree( SystemHeap, 0, lpcwp32 );
280 break;
283 case WH_GETMESSAGE:
285 LPMSG16 lpmsg16 = PTR_SEG_TO_LIN(lParamOrig);
286 STRUCT32_MSG32to16( (LPMSG)lParam, lpmsg16 );
287 HeapFree( SystemHeap, 0, (LPVOID)lParam );
288 break;
291 case WH_MOUSE:
292 case WH_DEBUG:
294 HeapFree( SystemHeap, 0, (LPVOID)lParam );
295 break;
297 case WH_CBT:
298 switch (code)
300 case HCBT_CREATEWND:
302 LPCBT_CREATEWNDA lpcbtcw32 = (LPCBT_CREATEWNDA)lParam;
303 LPCBT_CREATEWND16 lpcbtcw16 = PTR_SEG_TO_LIN(lParamOrig);
305 if( !bA )
307 if (HIWORD(lpcbtcw32->lpcs->lpszName))
308 HeapFree( SystemHeap, 0, (LPWSTR)lpcbtcw32->lpcs->lpszName );
309 if (HIWORD(lpcbtcw32->lpcs->lpszClass))
310 HeapFree( SystemHeap, 0, (LPWSTR)lpcbtcw32->lpcs->lpszClass );
313 lpcbtcw16->hwndInsertAfter = lpcbtcw32->hwndInsertAfter;
315 HeapFree( SystemHeap, 0, lpcbtcw32->lpcs );
316 } /* fall through */
318 case HCBT_ACTIVATE:
319 case HCBT_CLICKSKIPPED:
320 case HCBT_MOVESIZE:
322 HeapFree( SystemHeap, 0, (LPVOID)lParam);
323 break;
325 break;
327 case WH_SHELL:
328 case WH_KEYBOARD:
329 break;
331 case WH_HARDWARE:
332 case WH_FOREGROUNDIDLE:
333 case WH_CALLWNDPROCRET:
334 FIXME("\t[%i] skipping unmap\n", id);
335 break;
340 /***********************************************************************
341 * HOOK_UnMap16To32A
343 static void HOOK_UnMap16To32A(INT id, INT code, WPARAM wParamOrig,
344 LPARAM lParamOrig, WPARAM wParam,
345 LPARAM lParam)
347 HOOK_UnMap16To32Common( id, code, wParamOrig, lParamOrig, wParam,
348 lParam, TRUE );
352 /***********************************************************************
353 * HOOK_UnMap16To32W
355 static void HOOK_UnMap16To32W(INT id, INT code, WPARAM wParamOrig,
356 LPARAM lParamOrig, WPARAM wParam,
357 LPARAM lParam)
359 HOOK_UnMap16To32Common( id, code, wParamOrig, lParamOrig, wParam,
360 lParam, FALSE );
364 /***********************************************************************
365 * HOOK_Map32To16Common
367 static void HOOK_Map32To16Common(INT id, INT code, WPARAM *pwParam,
368 LPARAM *plParam, BOOL bA)
370 switch (id)
372 case WH_MSGFILTER:
373 case WH_SYSMSGFILTER:
374 case WH_GETMESSAGE:
375 case WH_JOURNALRECORD:
377 LPMSG lpmsg32 = (LPMSG)*plParam;
378 LPMSG16 lpmsg16 = SEGPTR_NEW( MSG16 );
380 STRUCT32_MSG32to16( lpmsg32, lpmsg16 );
382 *plParam = (LPARAM)SEGPTR_GET( lpmsg16 );
383 break;
386 case WH_JOURNALPLAYBACK:
388 LPEVENTMSG lpem32 = (LPEVENTMSG)*plParam;
389 LPEVENTMSG16 lpem16 = SEGPTR_NEW( EVENTMSG16 );
391 lpem16->message = lpem32->message;
392 lpem16->paramL = lpem32->paramL;
393 lpem16->paramH = lpem32->paramH;
394 lpem16->time = lpem32->time;
396 *plParam = (LPARAM)SEGPTR_GET( lpem16 );
397 break;
400 case WH_CALLWNDPROC:
402 LPCWPSTRUCT lpcwp32 = (LPCWPSTRUCT)*plParam;
403 LPCWPSTRUCT16 lpcwp16 = SEGPTR_NEW( CWPSTRUCT16 );
405 lpcwp16->hwnd = lpcwp32->hwnd;
406 lpcwp16->lParam = lpcwp32->lParam;
408 if (bA) WINPROC_MapMsg32ATo16( lpcwp32->hwnd, lpcwp32->message,
409 lpcwp32->wParam, &lpcwp16->message,
410 &lpcwp16->wParam, &lpcwp16->lParam );
411 else WINPROC_MapMsg32WTo16( lpcwp32->hwnd, lpcwp32->message,
412 lpcwp32->wParam, &lpcwp16->message,
413 &lpcwp16->wParam, &lpcwp16->lParam );
414 *plParam = (LPARAM)SEGPTR_GET( lpcwp16 );
415 break;
418 case WH_CBT:
419 switch (code)
421 case HCBT_ACTIVATE:
423 LPCBTACTIVATESTRUCT lpcas32 = (LPCBTACTIVATESTRUCT)*plParam;
424 LPCBTACTIVATESTRUCT16 lpcas16 =SEGPTR_NEW( CBTACTIVATESTRUCT16 );
426 lpcas16->fMouse = lpcas32->fMouse;
427 lpcas16->hWndActive = lpcas32->hWndActive;
429 *plParam = (LPARAM)SEGPTR_GET( lpcas16 );
430 break;
433 case HCBT_CLICKSKIPPED:
435 LPMOUSEHOOKSTRUCT lpms32 = (LPMOUSEHOOKSTRUCT)*plParam;
436 LPMOUSEHOOKSTRUCT16 lpms16 = SEGPTR_NEW( MOUSEHOOKSTRUCT16 );
438 CONV_POINT32TO16( &lpms32->pt, &lpms16->pt );
440 lpms16->hwnd = lpms32->hwnd;
441 lpms16->wHitTestCode = lpms32->wHitTestCode;
442 lpms16->dwExtraInfo = lpms32->dwExtraInfo;
444 *plParam = (LPARAM)SEGPTR_GET( lpms16 );
445 break;
448 case HCBT_MOVESIZE:
450 LPRECT lprect32 = (LPRECT)*plParam;
451 LPRECT16 lprect16 = SEGPTR_NEW( RECT16 );
453 CONV_RECT32TO16( lprect32, lprect16 );
455 *plParam = (LPARAM)SEGPTR_GET( lprect16 );
456 break;
459 break;
461 case WH_MOUSE:
463 LPMOUSEHOOKSTRUCT lpms32 = (LPMOUSEHOOKSTRUCT)*plParam;
464 LPMOUSEHOOKSTRUCT16 lpms16 = SEGPTR_NEW( MOUSEHOOKSTRUCT16 );
466 CONV_POINT32TO16( &lpms32->pt, &lpms16->pt );
468 lpms16->hwnd = lpms32->hwnd;
469 lpms16->wHitTestCode = lpms32->wHitTestCode;
470 lpms16->dwExtraInfo = lpms32->dwExtraInfo;
472 *plParam = (LPARAM)SEGPTR_GET( lpms16 );
473 break;
476 case WH_DEBUG:
478 LPDEBUGHOOKINFO lpdh32 = (LPDEBUGHOOKINFO)*plParam;
479 LPDEBUGHOOKINFO16 lpdh16 = SEGPTR_NEW( DEBUGHOOKINFO16 );
481 lpdh16->hModuleHook = 0; /* FIXME */
482 lpdh16->reserved = 0;
483 lpdh16->lParam = lpdh32->lParam;
484 lpdh16->wParam = lpdh32->wParam;
485 lpdh16->code = lpdh32->code;
487 *plParam = (LPARAM)SEGPTR_GET( lpdh16 );
488 break;
491 case WH_SHELL:
492 case WH_KEYBOARD:
493 break;
495 case WH_HARDWARE:
496 case WH_FOREGROUNDIDLE:
497 case WH_CALLWNDPROCRET:
498 FIXME("\t[%i] 32to16 translation unimplemented\n", id);
503 /***********************************************************************
504 * HOOK_Map32ATo16
506 static void HOOK_Map32ATo16(INT id, INT code, WPARAM *pwParam,
507 LPARAM *plParam)
509 if (id == WH_CBT && code == HCBT_CREATEWND)
511 LPCBT_CREATEWNDA lpcbtcw32 = (LPCBT_CREATEWNDA)*plParam;
512 LPCBT_CREATEWND16 lpcbtcw16 = SEGPTR_NEW( CBT_CREATEWND16 );
513 LPCREATESTRUCT16 lpcs16 = SEGPTR_NEW( CREATESTRUCT16 );
515 lpcbtcw16->lpcs = (LPCREATESTRUCT16)SEGPTR_GET( lpcs16 );
516 STRUCT32_CREATESTRUCT32Ato16( lpcbtcw32->lpcs, lpcs16 );
518 if (HIWORD(lpcbtcw32->lpcs->lpszName))
519 lpcs16->lpszName =
520 SEGPTR_GET( SEGPTR_STRDUP( lpcbtcw32->lpcs->lpszName ) );
521 else
522 lpcs16->lpszName = (SEGPTR)lpcbtcw32->lpcs->lpszName;
524 if (HIWORD(lpcbtcw32->lpcs->lpszClass))
525 lpcs16->lpszClass =
526 SEGPTR_GET( SEGPTR_STRDUP( lpcbtcw32->lpcs->lpszClass ) );
527 else
528 lpcs16->lpszClass = (SEGPTR)lpcbtcw32->lpcs->lpszClass;
530 lpcbtcw16->hwndInsertAfter = lpcbtcw32->hwndInsertAfter;
532 *plParam = (LPARAM)SEGPTR_GET( lpcbtcw16 );
534 else HOOK_Map32To16Common(id, code, pwParam, plParam, TRUE);
538 /***********************************************************************
539 * HOOK_Map32WTo16
541 static void HOOK_Map32WTo16(INT id, INT code, WPARAM *pwParam,
542 LPARAM *plParam)
544 if (id == WH_CBT && code == HCBT_CREATEWND)
546 LPSTR name, cls;
547 LPCBT_CREATEWNDW lpcbtcw32 = (LPCBT_CREATEWNDW)*plParam;
548 LPCBT_CREATEWND16 lpcbtcw16 = SEGPTR_NEW( CBT_CREATEWND16 );
549 LPCREATESTRUCT16 lpcs16 = SEGPTR_NEW( CREATESTRUCT16 );
551 lpcbtcw16->lpcs = (LPCREATESTRUCT16)SEGPTR_GET( lpcs16 );
552 STRUCT32_CREATESTRUCT32Ato16( (LPCREATESTRUCTA)lpcbtcw32->lpcs,
553 lpcs16 );
555 name = SEGPTR_STRDUP_WtoA( lpcbtcw32->lpcs->lpszName );
556 cls = SEGPTR_STRDUP_WtoA( lpcbtcw32->lpcs->lpszClass );
557 lpcs16->lpszName = SEGPTR_GET( name );
558 lpcs16->lpszClass = SEGPTR_GET( cls );
559 lpcbtcw16->hwndInsertAfter = lpcbtcw32->hwndInsertAfter;
561 *plParam = (LPARAM)SEGPTR_GET( lpcbtcw16 );
563 else HOOK_Map32To16Common(id, code, pwParam, plParam, FALSE);
567 /***********************************************************************
568 * HOOK_UnMap32To16Common
570 static void HOOK_UnMap32To16Common(INT id, INT code, WPARAM wParamOrig,
571 LPARAM lParamOrig, WPARAM wParam,
572 LPARAM lParam, BOOL bA)
574 switch (id)
576 case WH_MSGFILTER:
577 case WH_SYSMSGFILTER:
578 case WH_JOURNALRECORD:
579 case WH_JOURNALPLAYBACK:
580 case WH_MOUSE:
581 case WH_DEBUG:
582 SEGPTR_FREE( PTR_SEG_TO_LIN(lParam) );
583 break;
585 case WH_CALLWNDPROC:
587 LPCWPSTRUCT16 lpcwp16 = (LPCWPSTRUCT16)PTR_SEG_TO_LIN(lParam);
588 LPCWPSTRUCT lpcwp32 = (LPCWPSTRUCT)lParamOrig;
589 MSGPARAM16 mp16;
591 mp16.wParam = lpcwp16->wParam;
592 mp16.lParam = lpcwp16->lParam;
593 mp16.lResult = 0;
595 if (bA) WINPROC_UnmapMsg32ATo16( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
596 lpcwp32->lParam, &mp16 );
597 else WINPROC_UnmapMsg32WTo16( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
598 lpcwp32->lParam, &mp16 );
599 SEGPTR_FREE( PTR_SEG_TO_LIN(lParam) );
600 break;
603 case WH_GETMESSAGE:
605 LPMSG lpmsg32 = (LPMSG)lParamOrig;
607 STRUCT32_MSG16to32( (LPMSG16)PTR_SEG_TO_LIN(lParam), lpmsg32 );
608 SEGPTR_FREE( PTR_SEG_TO_LIN(lParam) );
609 break;
612 case WH_CBT:
613 switch (code)
615 case HCBT_CREATEWND:
617 LPCBT_CREATEWNDA lpcbtcw32 = (LPCBT_CREATEWNDA)(lParamOrig);
618 LPCBT_CREATEWND16 lpcbtcw16 = PTR_SEG_TO_LIN(lParam);
619 LPCREATESTRUCT16 lpcs16 = PTR_SEG_TO_LIN(lpcbtcw16->lpcs);
621 if (HIWORD(lpcs16->lpszName))
622 SEGPTR_FREE( PTR_SEG_TO_LIN(lpcs16->lpszName) );
624 if (HIWORD(lpcs16->lpszClass))
625 SEGPTR_FREE( PTR_SEG_TO_LIN(lpcs16->lpszClass) );
627 lpcbtcw32->hwndInsertAfter = lpcbtcw16->hwndInsertAfter;
629 SEGPTR_FREE( lpcs16 );
630 } /* fall through */
632 case HCBT_ACTIVATE:
633 case HCBT_CLICKSKIPPED:
634 case HCBT_MOVESIZE:
636 SEGPTR_FREE( PTR_SEG_TO_LIN(lParam) );
637 break;
639 break;
641 case WH_SHELL:
642 case WH_KEYBOARD:
643 break;
645 case WH_HARDWARE:
646 case WH_FOREGROUNDIDLE:
647 case WH_CALLWNDPROCRET:
648 FIXME("\t[%i] skipping unmap\n", id);
653 /***********************************************************************
654 * HOOK_UnMap32ATo16
656 static void HOOK_UnMap32ATo16(INT id, INT code, WPARAM wParamOrig,
657 LPARAM lParamOrig, WPARAM wParam,
658 LPARAM lParam)
660 HOOK_UnMap32To16Common( id, code, wParamOrig, lParamOrig, wParam,
661 lParam, TRUE );
665 /***********************************************************************
666 * HOOK_UnMap32WTo16
668 static void HOOK_UnMap32WTo16(INT id, INT code, WPARAM wParamOrig,
669 LPARAM lParamOrig, WPARAM wParam,
670 LPARAM lParam)
672 HOOK_UnMap32To16Common( id, code, wParamOrig, lParamOrig, wParam,
673 lParam, FALSE );
677 /***********************************************************************
678 * HOOK_Map32ATo32W
680 static void HOOK_Map32ATo32W(INT id, INT code, WPARAM *pwParam,
681 LPARAM *plParam)
683 if (id == WH_CBT && code == HCBT_CREATEWND)
685 LPCBT_CREATEWNDA lpcbtcwA = (LPCBT_CREATEWNDA)*plParam;
686 LPCBT_CREATEWNDW lpcbtcwW = HeapAlloc( SystemHeap, 0,
687 sizeof(*lpcbtcwW) );
688 lpcbtcwW->lpcs = HeapAlloc( SystemHeap, 0, sizeof(*lpcbtcwW->lpcs) );
690 lpcbtcwW->hwndInsertAfter = lpcbtcwA->hwndInsertAfter;
691 *lpcbtcwW->lpcs = *(LPCREATESTRUCTW)lpcbtcwA->lpcs;
693 if (HIWORD(lpcbtcwA->lpcs->lpszName))
695 lpcbtcwW->lpcs->lpszName = HEAP_strdupAtoW( SystemHeap, 0,
696 lpcbtcwA->lpcs->lpszName );
698 else
699 lpcbtcwW->lpcs->lpszName = (LPWSTR)lpcbtcwA->lpcs->lpszName;
701 if (HIWORD(lpcbtcwA->lpcs->lpszClass))
703 lpcbtcwW->lpcs->lpszClass = HEAP_strdupAtoW( SystemHeap, 0,
704 lpcbtcwA->lpcs->lpszClass );
706 else
707 lpcbtcwW->lpcs->lpszClass = (LPCWSTR)lpcbtcwA->lpcs->lpszClass;
708 *plParam = (LPARAM)lpcbtcwW;
710 return;
714 /***********************************************************************
715 * HOOK_UnMap32ATo32W
717 static void HOOK_UnMap32ATo32W(INT id, INT code, WPARAM wParamOrig,
718 LPARAM lParamOrig, WPARAM wParam,
719 LPARAM lParam)
721 if (id == WH_CBT && code == HCBT_CREATEWND)
723 LPCBT_CREATEWNDW lpcbtcwW = (LPCBT_CREATEWNDW)lParam;
724 if (HIWORD(lpcbtcwW->lpcs->lpszName))
725 HeapFree( SystemHeap, 0, (LPWSTR)lpcbtcwW->lpcs->lpszName );
726 if (HIWORD(lpcbtcwW->lpcs->lpszClass))
727 HeapFree( SystemHeap, 0, (LPWSTR)lpcbtcwW->lpcs->lpszClass );
728 HeapFree( SystemHeap, 0, lpcbtcwW->lpcs );
729 HeapFree( SystemHeap, 0, lpcbtcwW );
731 return;
735 /***********************************************************************
736 * HOOK_Map32WTo32A
738 static void HOOK_Map32WTo32A(INT id, INT code, WPARAM *pwParam,
739 LPARAM *plParam)
741 if (id == WH_CBT && code == HCBT_CREATEWND)
743 LPCBT_CREATEWNDW lpcbtcwW = (LPCBT_CREATEWNDW)*plParam;
744 LPCBT_CREATEWNDA lpcbtcwA = HeapAlloc( SystemHeap, 0,
745 sizeof(*lpcbtcwA) );
746 lpcbtcwA->lpcs = HeapAlloc( SystemHeap, 0, sizeof(*lpcbtcwA->lpcs) );
748 lpcbtcwA->hwndInsertAfter = lpcbtcwW->hwndInsertAfter;
749 *lpcbtcwA->lpcs = *(LPCREATESTRUCTA)lpcbtcwW->lpcs;
751 if (HIWORD(lpcbtcwW->lpcs->lpszName))
752 lpcbtcwA->lpcs->lpszName = HEAP_strdupWtoA( SystemHeap, 0,
753 lpcbtcwW->lpcs->lpszName );
754 else
755 lpcbtcwA->lpcs->lpszName = (LPSTR)lpcbtcwW->lpcs->lpszName;
757 if (HIWORD(lpcbtcwW->lpcs->lpszClass))
758 lpcbtcwA->lpcs->lpszClass = HEAP_strdupWtoA( SystemHeap, 0,
759 lpcbtcwW->lpcs->lpszClass );
760 else
761 lpcbtcwA->lpcs->lpszClass = (LPSTR)lpcbtcwW->lpcs->lpszClass;
762 *plParam = (LPARAM)lpcbtcwA;
764 return;
768 /***********************************************************************
769 * HOOK_UnMap32WTo32A
771 static void HOOK_UnMap32WTo32A(INT id, INT code, WPARAM wParamOrig,
772 LPARAM lParamOrig, WPARAM wParam,
773 LPARAM lParam)
775 if (id == WH_CBT && code == HCBT_CREATEWND)
777 LPCBT_CREATEWNDA lpcbtcwA = (LPCBT_CREATEWNDA)lParam;
778 if (HIWORD(lpcbtcwA->lpcs->lpszName))
779 HeapFree( SystemHeap, 0, (LPSTR)lpcbtcwA->lpcs->lpszName );
780 if (HIWORD(lpcbtcwA->lpcs->lpszClass))
781 HeapFree( SystemHeap, 0, (LPSTR)lpcbtcwA->lpcs->lpszClass );
782 HeapFree( SystemHeap, 0, lpcbtcwA->lpcs );
783 HeapFree( SystemHeap, 0, lpcbtcwA );
785 return;
789 /***********************************************************************
790 * Map Function Tables
792 static const HOOK_MapFunc HOOK_MapFuncs[3][3] =
794 { NULL, HOOK_Map16To32A, HOOK_Map16To32W },
795 { HOOK_Map32ATo16, NULL, HOOK_Map32ATo32W },
796 { HOOK_Map32WTo16, HOOK_Map32WTo32A, NULL }
799 static const HOOK_UnMapFunc HOOK_UnMapFuncs[3][3] =
801 { NULL, HOOK_UnMap16To32A, HOOK_UnMap16To32W },
802 { HOOK_UnMap32ATo16, NULL, HOOK_UnMap32ATo32W },
803 { HOOK_UnMap32WTo16, HOOK_UnMap32WTo32A, NULL }
807 /***********************************************************************
808 * Internal Functions
811 /***********************************************************************
812 * HOOK_GetNextHook
814 * Get the next hook of a given hook.
816 static HANDLE16 HOOK_GetNextHook( HANDLE16 hook )
818 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR( hook );
820 if (!data || !hook) return 0;
821 if (data->next) return data->next;
822 if (!data->ownerQueue) return 0; /* Already system hook */
824 /* Now start enumerating the system hooks */
825 return HOOK_systemHooks[data->id - WH_MINHOOK];
829 /***********************************************************************
830 * HOOK_GetHook
832 * Get the first hook for a given type.
834 static HANDLE16 HOOK_GetHook( INT16 id, HQUEUE16 hQueue )
836 MESSAGEQUEUE *queue;
837 HANDLE16 hook = 0;
839 if ((queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue )) != NULL)
840 hook = queue->hooks[id - WH_MINHOOK];
841 if (!hook) hook = HOOK_systemHooks[id - WH_MINHOOK];
843 QUEUE_Unlock( queue );
844 return hook;
848 /***********************************************************************
849 * HOOK_SetHook
851 * Install a given hook.
853 static HHOOK HOOK_SetHook( INT16 id, LPVOID proc, INT type,
854 HMODULE16 hModule, DWORD dwThreadId )
856 HOOKDATA *data;
857 HANDLE16 handle;
858 HQUEUE16 hQueue = 0;
860 if ((id < WH_MINHOOK) || (id > WH_MAXHOOK)) return 0;
862 TRACE("Setting hook %d: %08x %04x %08lx\n",
863 id, (UINT)proc, hModule, dwThreadId );
865 /* Create task queue if none present */
866 GetFastQueue16();
868 if (id == WH_JOURNALPLAYBACK) EnableHardwareInput16(FALSE);
870 if (dwThreadId) /* Task-specific hook */
872 if ((id == WH_JOURNALRECORD) || (id == WH_JOURNALPLAYBACK) ||
873 (id == WH_SYSMSGFILTER)) return 0; /* System-only hooks */
874 if (!(hQueue = GetThreadQueue16( dwThreadId )))
875 return 0;
878 /* Create the hook structure */
880 if (!(handle = USER_HEAP_ALLOC( sizeof(HOOKDATA) ))) return 0;
881 data = (HOOKDATA *) USER_HEAP_LIN_ADDR( handle );
882 data->proc = proc;
883 data->id = id;
884 data->ownerQueue = hQueue;
885 data->ownerModule = hModule;
886 data->flags = type;
888 /* Insert it in the correct linked list */
890 if (hQueue)
892 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue );
893 data->next = queue->hooks[id - WH_MINHOOK];
894 queue->hooks[id - WH_MINHOOK] = handle;
895 QUEUE_Unlock( queue );
897 else
899 data->next = HOOK_systemHooks[id - WH_MINHOOK];
900 HOOK_systemHooks[id - WH_MINHOOK] = handle;
902 TRACE("Setting hook %d: ret=%04x [next=%04x]\n",
903 id, handle, data->next );
905 return (HHOOK)( handle? MAKELONG( handle, HOOK_MAGIC ) : 0 );
909 /***********************************************************************
910 * HOOK_RemoveHook
912 * Remove a hook from the list.
914 static BOOL HOOK_RemoveHook( HANDLE16 hook )
916 HOOKDATA *data;
917 HANDLE16 *prevHook;
919 TRACE("Removing hook %04x\n", hook );
921 if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook))) return FALSE;
922 if (data->flags & HOOK_INUSE)
924 /* Mark it for deletion later on */
925 WARN("Hook still running, deletion delayed\n" );
926 data->proc = (HOOKPROC)0;
927 return TRUE;
930 if (data->id == WH_JOURNALPLAYBACK) EnableHardwareInput16(TRUE);
932 /* Remove it from the linked list */
934 if (data->ownerQueue)
936 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( data->ownerQueue );
937 if (!queue) return FALSE;
938 prevHook = &queue->hooks[data->id - WH_MINHOOK];
939 QUEUE_Unlock( queue );
941 else prevHook = &HOOK_systemHooks[data->id - WH_MINHOOK];
943 while (*prevHook && *prevHook != hook)
944 prevHook = &((HOOKDATA *)USER_HEAP_LIN_ADDR(*prevHook))->next;
946 if (!*prevHook) return FALSE;
947 *prevHook = data->next;
948 USER_HEAP_FREE( hook );
949 return TRUE;
953 /***********************************************************************
954 * HOOK_FindValidHook
956 static HANDLE16 HOOK_FindValidHook( HANDLE16 hook )
958 HOOKDATA *data;
960 for (;;)
962 if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook))) return 0;
963 if (data->proc) return hook;
964 hook = data->next;
969 /***********************************************************************
970 * HOOK_CallHook
972 * Call a hook procedure.
974 static LRESULT HOOK_CallHook( HANDLE16 hook, INT fromtype, INT code,
975 WPARAM wParam, LPARAM lParam )
977 MESSAGEQUEUE *queue;
978 HANDLE16 prevHook;
979 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
980 LRESULT ret;
981 int iWndsLocks;
983 WPARAM wParamOrig = wParam;
984 LPARAM lParamOrig = lParam;
985 HOOK_MapFunc MapFunc;
986 HOOK_UnMapFunc UnMapFunc;
988 MapFunc = HOOK_MapFuncs[fromtype][data->flags & HOOK_MAPTYPE];
989 UnMapFunc = HOOK_UnMapFuncs[fromtype][data->flags & HOOK_MAPTYPE];
991 if (MapFunc)
992 MapFunc( data->id, code, &wParam, &lParam );
994 /* Now call it */
996 if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() ))) return 0;
997 prevHook = queue->hCurHook;
998 queue->hCurHook = hook;
999 data->flags |= HOOK_INUSE;
1001 TRACE("Calling hook %04x: %d %08x %08lx\n",
1002 hook, code, wParam, lParam );
1004 /* Suspend window structure locks before calling user code */
1005 iWndsLocks = WIN_SuspendWndsLock();
1007 ret = data->proc(code, wParam, lParam);
1009 /* Grrr. While the hook procedure is supposed to have an LRESULT return
1010 value even in Win16, it seems that for those hook types where the
1011 return value is interpreted as BOOL, Windows doesn't actually check
1012 the HIWORD ... Some buggy Win16 programs, notably WINFILE, rely on
1013 that, because they neglect to clear DX ... */
1014 if ( (data->flags & HOOK_MAPTYPE) == HOOK_WIN16
1015 && data->id != WH_JOURNALPLAYBACK )
1016 ret = LOWORD( ret );
1018 WIN_RestoreWndsLock(iWndsLocks);
1020 TRACE("Ret hook %04x = %08lx\n", hook, ret );
1022 data->flags &= ~HOOK_INUSE;
1023 queue->hCurHook = prevHook;
1025 QUEUE_Unlock( queue );
1027 if (UnMapFunc)
1028 UnMapFunc( data->id, code, wParamOrig, lParamOrig, wParam, lParam );
1030 if (!data->proc) HOOK_RemoveHook( hook );
1032 return ret;
1035 /***********************************************************************
1036 * Exported Functions & APIs
1039 /***********************************************************************
1040 * HOOK_GetProc16
1042 * Don't call this unless you are the if1632/thunk.c.
1044 HOOKPROC16 HOOK_GetProc16( HHOOK hhook )
1046 HOOKDATA *data;
1047 if (HIWORD(hhook) != HOOK_MAGIC) return NULL;
1048 if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR( LOWORD(hhook) ))) return NULL;
1049 if ((data->flags & HOOK_MAPTYPE) != HOOK_WIN16) return NULL;
1050 return (HOOKPROC16)data->proc;
1054 /***********************************************************************
1055 * HOOK_IsHooked
1057 * Replacement for calling HOOK_GetHook from other modules.
1059 BOOL HOOK_IsHooked( INT16 id )
1061 /* Hmmm. Use GetThreadQueue(0) instead of GetFastQueue() here to
1062 avoid queue being created if someone wants to merely check ... */
1064 return HOOK_GetHook( id, GetThreadQueue16(0) ) != 0;
1068 /***********************************************************************
1069 * HOOK_CallHooks16
1071 * Call a hook chain.
1073 LRESULT HOOK_CallHooks16( INT16 id, INT16 code, WPARAM16 wParam,
1074 LPARAM lParam )
1076 HANDLE16 hook;
1078 if (!(hook = HOOK_GetHook( id, GetFastQueue16() ))) return 0;
1079 if (!(hook = HOOK_FindValidHook(hook))) return 0;
1080 return HOOK_CallHook( hook, HOOK_WIN16, code, wParam, lParam );
1083 /***********************************************************************
1084 * HOOK_CallHooks32A
1086 * Call a hook chain.
1088 LRESULT HOOK_CallHooksA( INT id, INT code, WPARAM wParam,
1089 LPARAM lParam )
1091 HANDLE16 hook;
1093 if (!(hook = HOOK_GetHook( id, GetFastQueue16() ))) return 0;
1094 if (!(hook = HOOK_FindValidHook(hook))) return 0;
1095 return HOOK_CallHook( hook, HOOK_WIN32A, code, wParam, lParam );
1098 /***********************************************************************
1099 * HOOK_CallHooks32W
1101 * Call a hook chain.
1103 LRESULT HOOK_CallHooksW( INT id, INT code, WPARAM wParam,
1104 LPARAM lParam )
1106 HANDLE16 hook;
1108 if (!(hook = HOOK_GetHook( id, GetFastQueue16() ))) return 0;
1109 if (!(hook = HOOK_FindValidHook(hook))) return 0;
1110 return HOOK_CallHook( hook, HOOK_WIN32W, code, wParam,
1111 lParam );
1115 /***********************************************************************
1116 * HOOK_ResetQueueHooks
1118 void HOOK_ResetQueueHooks( HQUEUE16 hQueue )
1120 MESSAGEQUEUE *queue;
1122 if ((queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue )) != NULL)
1124 HOOKDATA* data;
1125 HHOOK hook;
1126 int id;
1127 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
1129 hook = queue->hooks[id - WH_MINHOOK];
1130 while( hook )
1132 if( (data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook)) )
1134 data->ownerQueue = hQueue;
1135 hook = data->next;
1136 } else break;
1140 QUEUE_Unlock( queue );
1144 /***********************************************************************
1145 * HOOK_FreeModuleHooks
1147 void HOOK_FreeModuleHooks( HMODULE16 hModule )
1149 /* remove all system hooks registered by this module */
1151 HOOKDATA* hptr;
1152 HHOOK hook, next;
1153 int id;
1155 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
1157 hook = HOOK_systemHooks[id - WH_MINHOOK];
1158 while( hook )
1159 if( (hptr = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook)) )
1161 next = hptr->next;
1162 if( hptr->ownerModule == hModule )
1164 hptr->flags &= HOOK_MAPTYPE;
1165 HOOK_RemoveHook(hook);
1167 hook = next;
1169 else hook = 0;
1173 /***********************************************************************
1174 * HOOK_FreeQueueHooks
1176 void HOOK_FreeQueueHooks( HQUEUE16 hQueue )
1178 /* remove all hooks registered by this queue */
1180 HOOKDATA* hptr = NULL;
1181 HHOOK hook, next;
1182 int id;
1184 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
1186 hook = HOOK_GetHook( id, hQueue );
1187 while( hook )
1189 next = HOOK_GetNextHook(hook);
1191 hptr = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
1192 if( hptr && hptr->ownerQueue == hQueue )
1194 hptr->flags &= HOOK_MAPTYPE;
1195 HOOK_RemoveHook(hook);
1197 hook = next;
1203 /***********************************************************************
1204 * SetWindowsHook16 (USER.121)
1206 FARPROC16 WINAPI SetWindowsHook16( INT16 id, HOOKPROC16 proc )
1208 HINSTANCE16 hInst = FarGetOwner16( HIWORD(proc) );
1210 /* WH_MSGFILTER is the only task-specific hook for SetWindowsHook() */
1211 HTASK16 hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
1213 return (FARPROC16)SetWindowsHookEx16( id, proc, hInst, hTask );
1216 /***********************************************************************
1217 * SetWindowsHook32A (USER32.525)
1219 HHOOK WINAPI SetWindowsHookA( INT id, HOOKPROC proc )
1221 return SetWindowsHookExA( id, proc, 0, GetCurrentThreadId() );
1224 /***********************************************************************
1225 * SetWindowsHook32W (USER32.528)
1227 HHOOK WINAPI SetWindowsHookW( INT id, HOOKPROC proc )
1229 return SetWindowsHookExW( id, proc, 0, GetCurrentThreadId() );
1233 /***********************************************************************
1234 * SetWindowsHookEx16 (USER.291)
1236 HHOOK WINAPI SetWindowsHookEx16( INT16 id, HOOKPROC16 proc, HINSTANCE16 hInst,
1237 HTASK16 hTask )
1239 if (id == WH_DEBUG)
1241 FIXME("WH_DEBUG is broken in 16-bit Windows.\n");
1242 return 0;
1244 return HOOK_SetHook( id, proc, HOOK_WIN16, GetExePtr(hInst), (DWORD)hTask );
1247 /***********************************************************************
1248 * SetWindowsHookEx32A (USER32.526)
1250 HHOOK WINAPI SetWindowsHookExA( INT id, HOOKPROC proc, HINSTANCE hInst,
1251 DWORD dwThreadId )
1253 return HOOK_SetHook( id, proc, HOOK_WIN32A, MapHModuleLS(hInst), dwThreadId );
1256 /***********************************************************************
1257 * SetWindowsHookEx32W (USER32.527)
1259 HHOOK WINAPI SetWindowsHookExW( INT id, HOOKPROC proc, HINSTANCE hInst,
1260 DWORD dwThreadId )
1262 return HOOK_SetHook( id, proc, HOOK_WIN32W, MapHModuleLS(hInst), dwThreadId );
1266 /***********************************************************************
1267 * UnhookWindowsHook16 (USER.234)
1269 BOOL16 WINAPI UnhookWindowsHook16( INT16 id, HOOKPROC16 proc )
1271 return UnhookWindowsHook( id, (HOOKPROC)proc );
1274 /***********************************************************************
1275 * UnhookWindowsHook32 (USER32.557)
1277 BOOL WINAPI UnhookWindowsHook( INT id, HOOKPROC proc )
1279 HANDLE16 hook = HOOK_GetHook( id, GetFastQueue16() );
1281 TRACE("%d %08lx\n", id, (DWORD)proc );
1283 while (hook)
1285 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
1286 if (data->proc == proc) break;
1287 hook = HOOK_GetNextHook( hook );
1289 if (!hook) return FALSE;
1290 return HOOK_RemoveHook( hook );
1294 /***********************************************************************
1295 * UnhookWindowHookEx16 (USER.292)
1297 BOOL16 WINAPI UnhookWindowsHookEx16( HHOOK hhook )
1299 return UnhookWindowsHookEx( hhook );
1302 /***********************************************************************
1303 * UnhookWindowHookEx32 (USER32.558)
1305 BOOL WINAPI UnhookWindowsHookEx( HHOOK hhook )
1307 if (HIWORD(hhook) != HOOK_MAGIC) return FALSE; /* Not a new format hook */
1308 return HOOK_RemoveHook( LOWORD(hhook) );
1312 /***********************************************************************
1313 * CallNextHookEx16 (USER.293)
1315 * I wouldn't have separated this into 16 and 32 bit versions, but I
1316 * need a way to figure out if I need to do a mapping or not.
1318 LRESULT WINAPI CallNextHookEx16( HHOOK hhook, INT16 code, WPARAM16 wParam,
1319 LPARAM lParam )
1321 HANDLE16 next;
1323 if (HIWORD(hhook) != HOOK_MAGIC) return 0; /* Not a new format hook */
1324 if (!(next = HOOK_GetNextHook( LOWORD(hhook) ))) return 0;
1326 return HOOK_CallHook( next, HOOK_WIN16, code, wParam, lParam );
1330 /***********************************************************************
1331 * CallNextHookEx32 (USER32.17)
1333 * There aren't ANSI and UNICODE versions of this.
1335 LRESULT WINAPI CallNextHookEx( HHOOK hhook, INT code, WPARAM wParam,
1336 LPARAM lParam )
1338 HANDLE16 next;
1339 INT fromtype; /* figure out Ansi/Unicode */
1340 HOOKDATA *oldhook;
1342 if (HIWORD(hhook) != HOOK_MAGIC) return 0; /* Not a new format hook */
1343 if (!(next = HOOK_GetNextHook( LOWORD(hhook) ))) return 0;
1345 oldhook = (HOOKDATA *)USER_HEAP_LIN_ADDR( LOWORD(hhook) );
1346 fromtype = oldhook->flags & HOOK_MAPTYPE;
1348 if (fromtype == HOOK_WIN16)
1349 ERR("called from 16bit hook!\n");
1351 return HOOK_CallHook( next, fromtype, code, wParam, lParam );
1355 /***********************************************************************
1356 * DefHookProc16 (USER.235)
1358 LRESULT WINAPI DefHookProc16( INT16 code, WPARAM16 wParam, LPARAM lParam,
1359 HHOOK *hhook )
1361 /* Note: the *hhook parameter is never used, since we rely on the
1362 * current hook value from the task queue to find the next hook. */
1363 MESSAGEQUEUE *queue;
1364 LRESULT ret;
1366 if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() ))) return 0;
1367 ret = CallNextHookEx16( queue->hCurHook, code, wParam, lParam );
1368 QUEUE_Unlock( queue );
1369 return ret;
1373 /***********************************************************************
1374 * CallMsgFilter16 (USER.123)
1376 BOOL16 WINAPI CallMsgFilter16( SEGPTR msg, INT16 code )
1378 if (GetSysModalWindow16()) return FALSE;
1379 if (HOOK_CallHooks16( WH_SYSMSGFILTER, code, 0, (LPARAM)msg )) return TRUE;
1380 return HOOK_CallHooks16( WH_MSGFILTER, code, 0, (LPARAM)msg );
1384 /***********************************************************************
1385 * WIN16_CallMsgFilter32 (USER.823)
1387 BOOL16 WINAPI CallMsgFilter32_16( SEGPTR msg16_32, INT16 code, BOOL16 wHaveParamHigh )
1389 MSG32_16 *lpmsg16_32 = (MSG32_16 *)PTR_SEG_TO_LIN(msg16_32);
1391 if (wHaveParamHigh == FALSE)
1393 lpmsg16_32->wParamHigh = 0;
1394 /* WARNING: msg16_32->msg has to be the first variable in the struct */
1395 return CallMsgFilter16(msg16_32, code);
1397 else
1399 MSG msg32;
1400 BOOL16 ret;
1402 msg32.hwnd = lpmsg16_32->msg.hwnd;
1403 msg32.message = lpmsg16_32->msg.message;
1404 msg32.wParam =
1405 MAKELONG(lpmsg16_32->msg.wParam, lpmsg16_32->wParamHigh);
1406 msg32.lParam = lpmsg16_32->msg.lParam;
1407 msg32.time = lpmsg16_32->msg.time;
1408 msg32.pt.x = (INT)lpmsg16_32->msg.pt.x;
1409 msg32.pt.y = (INT)lpmsg16_32->msg.pt.y;
1411 ret = (BOOL16)CallMsgFilterA(&msg32, (INT)code);
1413 lpmsg16_32->msg.hwnd = msg32.hwnd;
1414 lpmsg16_32->msg.message = msg32.message;
1415 lpmsg16_32->msg.wParam = LOWORD(msg32.wParam);
1416 lpmsg16_32->msg.lParam = msg32.lParam;
1417 lpmsg16_32->msg.time = msg32.time;
1418 lpmsg16_32->msg.pt.x = (INT16)msg32.pt.x;
1419 lpmsg16_32->msg.pt.y = (INT16)msg32.pt.y;
1420 lpmsg16_32->wParamHigh = HIWORD(msg32.wParam);
1422 return ret;
1427 /***********************************************************************
1428 * CallMsgFilter32A (USER32.15)
1431 * FIXME: There are ANSI and UNICODE versions of this, plus an unspecified
1432 * version, plus USER (the 16bit one) has a CallMsgFilter32 function.
1434 BOOL WINAPI CallMsgFilterA( LPMSG msg, INT code )
1436 if (GetSysModalWindow16()) return FALSE; /* ??? */
1437 if (HOOK_CallHooksA( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
1438 return TRUE;
1439 return HOOK_CallHooksA( WH_MSGFILTER, code, 0, (LPARAM)msg );
1443 /***********************************************************************
1444 * CallMsgFilter32W (USER32.16)
1446 BOOL WINAPI CallMsgFilterW( LPMSG msg, INT code )
1448 if (GetSysModalWindow16()) return FALSE; /* ??? */
1449 if (HOOK_CallHooksW( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
1450 return TRUE;
1451 return HOOK_CallHooksW( WH_MSGFILTER, code, 0, (LPARAM)msg );