#pragma pack(?) changed to #include "*pack*.h"
[wine.git] / windows / hook.c
blob2d694afcfe8f28e1571c38fedca8003136ab1f22
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 "queue.h"
22 #include "task.h"
23 #include "user.h"
24 #include "heap.h"
25 #include "struct32.h"
26 #include "winproc.h"
27 #include "debug.h"
29 DEFAULT_DEBUG_CHANNEL(hook)
31 #include "pshpack1.h"
33 /* Hook data (pointed to by a HHOOK) */
34 typedef struct
36 HANDLE16 next; /* 00 Next hook in chain */
37 HOOKPROC proc WINE_PACKED; /* 02 Hook procedure */
38 INT16 id; /* 06 Hook id (WH_xxx) */
39 HQUEUE16 ownerQueue; /* 08 Owner queue (0 for system hook) */
40 HMODULE16 ownerModule; /* 0a Owner module */
41 WORD flags; /* 0c flags */
42 } HOOKDATA;
44 #include "poppack.h"
46 #define HOOK_MAGIC ((int)'H' | (int)'K' << 8) /* 'HK' */
48 /* This should probably reside in USER heap */
49 static HANDLE16 HOOK_systemHooks[WH_NB_HOOKS] = { 0, };
51 typedef VOID (*HOOK_MapFunc)(INT, INT, WPARAM *, LPARAM *);
52 typedef VOID (*HOOK_UnMapFunc)(INT, INT, WPARAM, LPARAM, WPARAM,
53 LPARAM);
55 /***********************************************************************
56 * HOOK_Map16To32Common
58 static void HOOK_Map16To32Common(INT id, INT code, WPARAM *pwParam,
59 LPARAM *plParam, BOOL bA )
62 switch( id )
64 case WH_MSGFILTER:
65 case WH_SYSMSGFILTER:
66 case WH_GETMESSAGE:
67 case WH_JOURNALRECORD:
69 LPMSG16 lpmsg16 = PTR_SEG_TO_LIN(*plParam);
70 LPMSG lpmsg32 = HeapAlloc( SystemHeap, 0, sizeof(*lpmsg32) );
72 STRUCT32_MSG16to32( lpmsg16, lpmsg32 );
73 *plParam = (LPARAM)lpmsg32;
74 break;
77 case WH_JOURNALPLAYBACK:
79 LPEVENTMSG16 lpem16 = PTR_SEG_TO_LIN(*plParam);
80 LPEVENTMSG lpem32 = HeapAlloc( SystemHeap, 0, sizeof(*lpem32) );
82 lpem32->message = lpem16->message;
83 lpem32->paramL = lpem16->paramL;
84 lpem32->paramH = lpem16->paramH;
85 lpem32->time = lpem16->time;
86 lpem32->hwnd = 0; /* FIXME */
88 *plParam = (LPARAM)lpem32;
89 break;
92 case WH_CALLWNDPROC:
94 LPCWPSTRUCT16 lpcwp16 = PTR_SEG_TO_LIN(*plParam);
95 LPCWPSTRUCT lpcwp32 = HeapAlloc( SystemHeap, 0, sizeof(*lpcwp32) );
97 lpcwp32->hwnd = lpcwp16->hwnd;
98 lpcwp32->lParam = lpcwp16->lParam;
100 if (bA) WINPROC_MapMsg16To32A( lpcwp16->message, lpcwp16->wParam,
101 &lpcwp32->message, &lpcwp32->wParam,
102 &lpcwp32->lParam );
103 else WINPROC_MapMsg16To32W( lpcwp16->hwnd,lpcwp16->message, lpcwp16->wParam,
104 &lpcwp32->message, &lpcwp32->wParam,
105 &lpcwp32->lParam );
106 *plParam = (LPARAM)lpcwp32;
107 break;
110 case WH_CBT:
111 switch (code)
113 case HCBT_CREATEWND:
115 LPCBT_CREATEWND16 lpcbtcw16 = PTR_SEG_TO_LIN(*plParam);
116 LPCREATESTRUCT16 lpcs16 = PTR_SEG_TO_LIN(lpcbtcw16->lpcs);
117 LPCBT_CREATEWNDA lpcbtcw32 = HeapAlloc( SystemHeap, 0,
118 sizeof(*lpcbtcw32) );
119 lpcbtcw32->lpcs = HeapAlloc( SystemHeap, 0,
120 sizeof(*lpcbtcw32->lpcs) );
122 STRUCT32_CREATESTRUCT16to32A( lpcs16,
123 (LPCREATESTRUCTA)lpcbtcw32->lpcs );
125 if (HIWORD(lpcs16->lpszName))
126 lpcbtcw32->lpcs->lpszName =
127 (bA) ? PTR_SEG_TO_LIN(lpcs16->lpszName)
128 : HEAP_strdupAtoW( SystemHeap, 0,
129 PTR_SEG_TO_LIN(lpcs16->lpszName) );
130 else
131 lpcbtcw32->lpcs->lpszName = (LPCSTR)lpcs16->lpszName;
133 if (HIWORD(lpcs16->lpszClass))
134 lpcbtcw32->lpcs->lpszClass =
135 (bA) ? PTR_SEG_TO_LIN(lpcs16->lpszClass)
136 : HEAP_strdupAtoW( SystemHeap, 0,
137 PTR_SEG_TO_LIN(lpcs16->lpszClass) );
138 else
139 lpcbtcw32->lpcs->lpszClass = (LPCSTR)lpcs16->lpszClass;
141 lpcbtcw32->hwndInsertAfter = lpcbtcw16->hwndInsertAfter;
143 *plParam = (LPARAM)lpcbtcw32;
144 break;
146 case HCBT_ACTIVATE:
148 LPCBTACTIVATESTRUCT16 lpcas16 = PTR_SEG_TO_LIN(*plParam);
149 LPCBTACTIVATESTRUCT lpcas32 = HeapAlloc( SystemHeap, 0,
150 sizeof(*lpcas32) );
151 lpcas32->fMouse = lpcas16->fMouse;
152 lpcas32->hWndActive = lpcas16->hWndActive;
153 *plParam = (LPARAM)lpcas32;
154 break;
156 case HCBT_CLICKSKIPPED:
158 LPMOUSEHOOKSTRUCT16 lpms16 = PTR_SEG_TO_LIN(*plParam);
159 LPMOUSEHOOKSTRUCT lpms32 = HeapAlloc( SystemHeap, 0,
160 sizeof(*lpms32) );
162 CONV_POINT16TO32( &lpms16->pt, &lpms32->pt );
164 /* wHitTestCode may be negative, so convince compiler to do
165 correct sign extension. Yay. :| */
166 lpms32->wHitTestCode = (INT)((INT16)lpms16->wHitTestCode);
168 lpms32->dwExtraInfo = lpms16->dwExtraInfo;
169 lpms32->hwnd = lpms16->hwnd;
170 *plParam = (LPARAM)lpms32;
171 break;
173 case HCBT_MOVESIZE:
175 LPRECT16 lprect16 = PTR_SEG_TO_LIN(*plParam);
176 LPRECT lprect32 = HeapAlloc( SystemHeap, 0,
177 sizeof(*lprect32) );
179 CONV_RECT16TO32( lprect16, lprect32 );
180 *plParam = (LPARAM)lprect32;
181 break;
184 break;
186 case WH_MOUSE:
188 LPMOUSEHOOKSTRUCT16 lpms16 = PTR_SEG_TO_LIN(*plParam);
189 LPMOUSEHOOKSTRUCT lpms32 = HeapAlloc( SystemHeap, 0,
190 sizeof(*lpms32) );
192 CONV_POINT16TO32( &lpms16->pt, &lpms32->pt );
194 /* wHitTestCode may be negative, so convince compiler to do
195 correct sign extension. Yay. :| */
196 lpms32->wHitTestCode = (INT)((INT16)lpms16->wHitTestCode);
197 lpms32->dwExtraInfo = lpms16->dwExtraInfo;
198 lpms32->hwnd = lpms16->hwnd;
199 *plParam = (LPARAM)lpms32;
200 break;
203 case WH_DEBUG:
205 LPDEBUGHOOKINFO16 lpdh16 = PTR_SEG_TO_LIN(*plParam);
206 LPDEBUGHOOKINFO lpdh32 = HeapAlloc( SystemHeap, 0,
207 sizeof(*lpdh32) );
209 lpdh32->idThread = 0; /* FIXME */
210 lpdh32->idThreadInstaller = 0; /* FIXME */
211 lpdh32->lParam = lpdh16->lParam; /* FIXME Check for sign ext */
212 lpdh32->wParam = lpdh16->wParam;
213 lpdh32->code = lpdh16->code;
215 /* do sign extension if it was WH_MSGFILTER */
216 if (*pwParam == 0xffff) *pwParam = WH_MSGFILTER;
218 *plParam = (LPARAM)lpdh32;
219 break;
222 case WH_SHELL:
223 case WH_KEYBOARD:
224 break;
226 case WH_HARDWARE:
227 case WH_FOREGROUNDIDLE:
228 case WH_CALLWNDPROCRET:
229 FIXME(hook, "\t[%i] 16to32 translation unimplemented\n", id);
234 /***********************************************************************
235 * HOOK_Map16To32A
237 static void HOOK_Map16To32A(INT id, INT code, WPARAM *pwParam,
238 LPARAM *plParam)
240 HOOK_Map16To32Common( id, code, pwParam, plParam, TRUE );
244 /***********************************************************************
245 * HOOK_Map16To32W
247 static void HOOK_Map16To32W(INT id, INT code, WPARAM *pwParam,
248 LPARAM *plParam)
250 HOOK_Map16To32Common( id, code, pwParam, plParam, FALSE );
254 /***********************************************************************
255 * HOOK_UnMap16To32Common
257 static void HOOK_UnMap16To32Common(INT id, INT code, WPARAM wParamOrig,
258 LPARAM lParamOrig, WPARAM wParam,
259 LPARAM lParam, BOOL bA)
261 switch (id)
263 case WH_MSGFILTER:
264 case WH_SYSMSGFILTER:
265 case WH_JOURNALRECORD:
266 case WH_JOURNALPLAYBACK:
268 HeapFree( SystemHeap, 0, (LPVOID)lParam );
269 break;
271 case WH_CALLWNDPROC:
273 LPCWPSTRUCT lpcwp32 = (LPCWPSTRUCT)lParam;
274 if (bA) WINPROC_UnmapMsg16To32A( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
275 lpcwp32->lParam, 0 );
276 else WINPROC_UnmapMsg16To32W( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
277 lpcwp32->lParam, 0 );
278 HeapFree( SystemHeap, 0, lpcwp32 );
279 break;
282 case WH_GETMESSAGE:
284 LPMSG16 lpmsg16 = PTR_SEG_TO_LIN(lParamOrig);
285 STRUCT32_MSG32to16( (LPMSG)lParam, lpmsg16 );
286 HeapFree( SystemHeap, 0, (LPVOID)lParam );
287 break;
290 case WH_MOUSE:
291 case WH_DEBUG:
293 HeapFree( SystemHeap, 0, (LPVOID)lParam );
294 break;
296 case WH_CBT:
297 switch (code)
299 case HCBT_CREATEWND:
301 LPCBT_CREATEWNDA lpcbtcw32 = (LPCBT_CREATEWNDA)lParam;
302 LPCBT_CREATEWND16 lpcbtcw16 = PTR_SEG_TO_LIN(lParamOrig);
304 if( !bA )
306 if (HIWORD(lpcbtcw32->lpcs->lpszName))
307 HeapFree( SystemHeap, 0, (LPWSTR)lpcbtcw32->lpcs->lpszName );
308 if (HIWORD(lpcbtcw32->lpcs->lpszClass))
309 HeapFree( SystemHeap, 0, (LPWSTR)lpcbtcw32->lpcs->lpszClass );
312 lpcbtcw16->hwndInsertAfter = lpcbtcw32->hwndInsertAfter;
314 HeapFree( SystemHeap, 0, lpcbtcw32->lpcs );
315 } /* fall through */
317 case HCBT_ACTIVATE:
318 case HCBT_CLICKSKIPPED:
319 case HCBT_MOVESIZE:
321 HeapFree( SystemHeap, 0, (LPVOID)lParam);
322 break;
324 break;
326 case WH_SHELL:
327 case WH_KEYBOARD:
328 break;
330 case WH_HARDWARE:
331 case WH_FOREGROUNDIDLE:
332 case WH_CALLWNDPROCRET:
333 FIXME(hook, "\t[%i] skipping unmap\n", id);
334 break;
339 /***********************************************************************
340 * HOOK_UnMap16To32A
342 static void HOOK_UnMap16To32A(INT id, INT code, WPARAM wParamOrig,
343 LPARAM lParamOrig, WPARAM wParam,
344 LPARAM lParam)
346 HOOK_UnMap16To32Common( id, code, wParamOrig, lParamOrig, wParam,
347 lParam, TRUE );
351 /***********************************************************************
352 * HOOK_UnMap16To32W
354 static void HOOK_UnMap16To32W(INT id, INT code, WPARAM wParamOrig,
355 LPARAM lParamOrig, WPARAM wParam,
356 LPARAM lParam)
358 HOOK_UnMap16To32Common( id, code, wParamOrig, lParamOrig, wParam,
359 lParam, FALSE );
363 /***********************************************************************
364 * HOOK_Map32To16Common
366 static void HOOK_Map32To16Common(INT id, INT code, WPARAM *pwParam,
367 LPARAM *plParam, BOOL bA)
369 switch (id)
371 case WH_MSGFILTER:
372 case WH_SYSMSGFILTER:
373 case WH_GETMESSAGE:
374 case WH_JOURNALRECORD:
376 LPMSG lpmsg32 = (LPMSG)*plParam;
377 LPMSG16 lpmsg16 = SEGPTR_NEW( MSG16 );
379 STRUCT32_MSG32to16( lpmsg32, lpmsg16 );
381 *plParam = (LPARAM)SEGPTR_GET( lpmsg16 );
382 break;
385 case WH_JOURNALPLAYBACK:
387 LPEVENTMSG lpem32 = (LPEVENTMSG)*plParam;
388 LPEVENTMSG16 lpem16 = SEGPTR_NEW( EVENTMSG16 );
390 lpem16->message = lpem32->message;
391 lpem16->paramL = lpem32->paramL;
392 lpem16->paramH = lpem32->paramH;
393 lpem16->time = lpem32->time;
395 *plParam = (LPARAM)SEGPTR_GET( lpem16 );
396 break;
399 case WH_CALLWNDPROC:
401 LPCWPSTRUCT lpcwp32 = (LPCWPSTRUCT)*plParam;
402 LPCWPSTRUCT16 lpcwp16 = SEGPTR_NEW( CWPSTRUCT16 );
404 lpcwp16->hwnd = lpcwp32->hwnd;
405 lpcwp16->lParam = lpcwp32->lParam;
407 if (bA) WINPROC_MapMsg32ATo16( lpcwp32->hwnd, lpcwp32->message,
408 lpcwp32->wParam, &lpcwp16->message,
409 &lpcwp16->wParam, &lpcwp16->lParam );
410 else WINPROC_MapMsg32WTo16( lpcwp32->hwnd, lpcwp32->message,
411 lpcwp32->wParam, &lpcwp16->message,
412 &lpcwp16->wParam, &lpcwp16->lParam );
413 *plParam = (LPARAM)SEGPTR_GET( lpcwp16 );
414 break;
417 case WH_CBT:
418 switch (code)
420 case HCBT_ACTIVATE:
422 LPCBTACTIVATESTRUCT lpcas32 = (LPCBTACTIVATESTRUCT)*plParam;
423 LPCBTACTIVATESTRUCT16 lpcas16 =SEGPTR_NEW( CBTACTIVATESTRUCT16 );
425 lpcas16->fMouse = lpcas32->fMouse;
426 lpcas16->hWndActive = lpcas32->hWndActive;
428 *plParam = (LPARAM)SEGPTR_GET( lpcas16 );
429 break;
432 case HCBT_CLICKSKIPPED:
434 LPMOUSEHOOKSTRUCT lpms32 = (LPMOUSEHOOKSTRUCT)*plParam;
435 LPMOUSEHOOKSTRUCT16 lpms16 = SEGPTR_NEW( MOUSEHOOKSTRUCT16 );
437 CONV_POINT32TO16( &lpms32->pt, &lpms16->pt );
439 lpms16->hwnd = lpms32->hwnd;
440 lpms16->wHitTestCode = lpms32->wHitTestCode;
441 lpms16->dwExtraInfo = lpms32->dwExtraInfo;
443 *plParam = (LPARAM)SEGPTR_GET( lpms16 );
444 break;
447 case HCBT_MOVESIZE:
449 LPRECT lprect32 = (LPRECT)*plParam;
450 LPRECT16 lprect16 = SEGPTR_NEW( RECT16 );
452 CONV_RECT32TO16( lprect32, lprect16 );
454 *plParam = (LPARAM)SEGPTR_GET( lprect16 );
455 break;
458 break;
460 case WH_MOUSE:
462 LPMOUSEHOOKSTRUCT lpms32 = (LPMOUSEHOOKSTRUCT)*plParam;
463 LPMOUSEHOOKSTRUCT16 lpms16 = SEGPTR_NEW( MOUSEHOOKSTRUCT16 );
465 CONV_POINT32TO16( &lpms32->pt, &lpms16->pt );
467 lpms16->hwnd = lpms32->hwnd;
468 lpms16->wHitTestCode = lpms32->wHitTestCode;
469 lpms16->dwExtraInfo = lpms32->dwExtraInfo;
471 *plParam = (LPARAM)SEGPTR_GET( lpms16 );
472 break;
475 case WH_DEBUG:
477 LPDEBUGHOOKINFO lpdh32 = (LPDEBUGHOOKINFO)*plParam;
478 LPDEBUGHOOKINFO16 lpdh16 = SEGPTR_NEW( DEBUGHOOKINFO16 );
480 lpdh16->hModuleHook = 0; /* FIXME */
481 lpdh16->reserved = 0;
482 lpdh16->lParam = lpdh32->lParam;
483 lpdh16->wParam = lpdh32->wParam;
484 lpdh16->code = lpdh32->code;
486 *plParam = (LPARAM)SEGPTR_GET( lpdh16 );
487 break;
490 case WH_SHELL:
491 case WH_KEYBOARD:
492 break;
494 case WH_HARDWARE:
495 case WH_FOREGROUNDIDLE:
496 case WH_CALLWNDPROCRET:
497 FIXME(hook,"\t[%i] 32to16 translation unimplemented\n", id);
502 /***********************************************************************
503 * HOOK_Map32ATo16
505 static void HOOK_Map32ATo16(INT id, INT code, WPARAM *pwParam,
506 LPARAM *plParam)
508 if (id == WH_CBT && code == HCBT_CREATEWND)
510 LPCBT_CREATEWNDA lpcbtcw32 = (LPCBT_CREATEWNDA)*plParam;
511 LPCBT_CREATEWND16 lpcbtcw16 = SEGPTR_NEW( CBT_CREATEWND16 );
512 LPCREATESTRUCT16 lpcs16 = SEGPTR_NEW( CREATESTRUCT16 );
514 lpcbtcw16->lpcs = (LPCREATESTRUCT16)SEGPTR_GET( lpcs16 );
515 STRUCT32_CREATESTRUCT32Ato16( lpcbtcw32->lpcs, lpcs16 );
517 if (HIWORD(lpcbtcw32->lpcs->lpszName))
518 lpcs16->lpszName =
519 SEGPTR_GET( SEGPTR_STRDUP( lpcbtcw32->lpcs->lpszName ) );
520 else
521 lpcs16->lpszName = (SEGPTR)lpcbtcw32->lpcs->lpszName;
523 if (HIWORD(lpcbtcw32->lpcs->lpszClass))
524 lpcs16->lpszClass =
525 SEGPTR_GET( SEGPTR_STRDUP( lpcbtcw32->lpcs->lpszClass ) );
526 else
527 lpcs16->lpszClass = (SEGPTR)lpcbtcw32->lpcs->lpszClass;
529 lpcbtcw16->hwndInsertAfter = lpcbtcw32->hwndInsertAfter;
531 *plParam = (LPARAM)SEGPTR_GET( lpcbtcw16 );
533 else HOOK_Map32To16Common(id, code, pwParam, plParam, TRUE);
537 /***********************************************************************
538 * HOOK_Map32WTo16
540 static void HOOK_Map32WTo16(INT id, INT code, WPARAM *pwParam,
541 LPARAM *plParam)
543 if (id == WH_CBT && code == HCBT_CREATEWND)
545 LPSTR name, cls;
546 LPCBT_CREATEWNDW lpcbtcw32 = (LPCBT_CREATEWNDW)*plParam;
547 LPCBT_CREATEWND16 lpcbtcw16 = SEGPTR_NEW( CBT_CREATEWND16 );
548 LPCREATESTRUCT16 lpcs16 = SEGPTR_NEW( CREATESTRUCT16 );
550 lpcbtcw16->lpcs = (LPCREATESTRUCT16)SEGPTR_GET( lpcs16 );
551 STRUCT32_CREATESTRUCT32Ato16( (LPCREATESTRUCTA)lpcbtcw32->lpcs,
552 lpcs16 );
554 name = SEGPTR_STRDUP_WtoA( lpcbtcw32->lpcs->lpszName );
555 cls = SEGPTR_STRDUP_WtoA( lpcbtcw32->lpcs->lpszClass );
556 lpcs16->lpszName = SEGPTR_GET( name );
557 lpcs16->lpszClass = SEGPTR_GET( cls );
558 lpcbtcw16->hwndInsertAfter = lpcbtcw32->hwndInsertAfter;
560 *plParam = (LPARAM)SEGPTR_GET( lpcbtcw16 );
562 else HOOK_Map32To16Common(id, code, pwParam, plParam, FALSE);
566 /***********************************************************************
567 * HOOK_UnMap32To16Common
569 static void HOOK_UnMap32To16Common(INT id, INT code, WPARAM wParamOrig,
570 LPARAM lParamOrig, WPARAM wParam,
571 LPARAM lParam, BOOL bA)
573 switch (id)
575 case WH_MSGFILTER:
576 case WH_SYSMSGFILTER:
577 case WH_JOURNALRECORD:
578 case WH_JOURNALPLAYBACK:
579 case WH_MOUSE:
580 case WH_DEBUG:
581 SEGPTR_FREE( PTR_SEG_TO_LIN(lParam) );
582 break;
584 case WH_CALLWNDPROC:
586 LPCWPSTRUCT16 lpcwp16 = (LPCWPSTRUCT16)PTR_SEG_TO_LIN(lParam);
587 LPCWPSTRUCT lpcwp32 = (LPCWPSTRUCT)lParamOrig;
588 MSGPARAM16 mp16;
590 mp16.wParam = lpcwp16->wParam;
591 mp16.lParam = lpcwp16->lParam;
592 mp16.lResult = 0;
594 if (bA) WINPROC_UnmapMsg32ATo16( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
595 lpcwp32->lParam, &mp16 );
596 else WINPROC_UnmapMsg32WTo16( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
597 lpcwp32->lParam, &mp16 );
598 SEGPTR_FREE( PTR_SEG_TO_LIN(lParam) );
599 break;
602 case WH_GETMESSAGE:
604 LPMSG lpmsg32 = (LPMSG)lParamOrig;
606 STRUCT32_MSG16to32( (LPMSG16)PTR_SEG_TO_LIN(lParam), lpmsg32 );
607 SEGPTR_FREE( PTR_SEG_TO_LIN(lParam) );
608 break;
611 case WH_CBT:
612 switch (code)
614 case HCBT_CREATEWND:
616 LPCBT_CREATEWNDA lpcbtcw32 = (LPCBT_CREATEWNDA)(lParamOrig);
617 LPCBT_CREATEWND16 lpcbtcw16 = PTR_SEG_TO_LIN(lParam);
618 LPCREATESTRUCT16 lpcs16 = PTR_SEG_TO_LIN(lpcbtcw16->lpcs);
620 if (HIWORD(lpcs16->lpszName))
621 SEGPTR_FREE( PTR_SEG_TO_LIN(lpcs16->lpszName) );
623 if (HIWORD(lpcs16->lpszClass))
624 SEGPTR_FREE( PTR_SEG_TO_LIN(lpcs16->lpszClass) );
626 lpcbtcw32->hwndInsertAfter = lpcbtcw16->hwndInsertAfter;
628 SEGPTR_FREE( lpcs16 );
629 } /* fall through */
631 case HCBT_ACTIVATE:
632 case HCBT_CLICKSKIPPED:
633 case HCBT_MOVESIZE:
635 SEGPTR_FREE( PTR_SEG_TO_LIN(lParam) );
636 break;
638 break;
640 case WH_SHELL:
641 case WH_KEYBOARD:
642 break;
644 case WH_HARDWARE:
645 case WH_FOREGROUNDIDLE:
646 case WH_CALLWNDPROCRET:
647 FIXME(hook, "\t[%i] skipping unmap\n", id);
652 /***********************************************************************
653 * HOOK_UnMap32ATo16
655 static void HOOK_UnMap32ATo16(INT id, INT code, WPARAM wParamOrig,
656 LPARAM lParamOrig, WPARAM wParam,
657 LPARAM lParam)
659 HOOK_UnMap32To16Common( id, code, wParamOrig, lParamOrig, wParam,
660 lParam, TRUE );
664 /***********************************************************************
665 * HOOK_UnMap32WTo16
667 static void HOOK_UnMap32WTo16(INT id, INT code, WPARAM wParamOrig,
668 LPARAM lParamOrig, WPARAM wParam,
669 LPARAM lParam)
671 HOOK_UnMap32To16Common( id, code, wParamOrig, lParamOrig, wParam,
672 lParam, FALSE );
676 /***********************************************************************
677 * HOOK_Map32ATo32W
679 static void HOOK_Map32ATo32W(INT id, INT code, WPARAM *pwParam,
680 LPARAM *plParam)
682 if (id == WH_CBT && code == HCBT_CREATEWND)
684 LPCBT_CREATEWNDA lpcbtcwA = (LPCBT_CREATEWNDA)*plParam;
685 LPCBT_CREATEWNDW lpcbtcwW = HeapAlloc( SystemHeap, 0,
686 sizeof(*lpcbtcwW) );
687 lpcbtcwW->lpcs = HeapAlloc( SystemHeap, 0, sizeof(*lpcbtcwW->lpcs) );
689 lpcbtcwW->hwndInsertAfter = lpcbtcwA->hwndInsertAfter;
690 *lpcbtcwW->lpcs = *(LPCREATESTRUCTW)lpcbtcwA->lpcs;
692 if (HIWORD(lpcbtcwA->lpcs->lpszName))
694 lpcbtcwW->lpcs->lpszName = HEAP_strdupAtoW( SystemHeap, 0,
695 lpcbtcwA->lpcs->lpszName );
697 else
698 lpcbtcwW->lpcs->lpszName = (LPWSTR)lpcbtcwA->lpcs->lpszName;
700 if (HIWORD(lpcbtcwA->lpcs->lpszClass))
702 lpcbtcwW->lpcs->lpszClass = HEAP_strdupAtoW( SystemHeap, 0,
703 lpcbtcwA->lpcs->lpszClass );
705 else
706 lpcbtcwW->lpcs->lpszClass = (LPCWSTR)lpcbtcwA->lpcs->lpszClass;
707 *plParam = (LPARAM)lpcbtcwW;
709 return;
713 /***********************************************************************
714 * HOOK_UnMap32ATo32W
716 static void HOOK_UnMap32ATo32W(INT id, INT code, WPARAM wParamOrig,
717 LPARAM lParamOrig, WPARAM wParam,
718 LPARAM lParam)
720 if (id == WH_CBT && code == HCBT_CREATEWND)
722 LPCBT_CREATEWNDW lpcbtcwW = (LPCBT_CREATEWNDW)lParam;
723 if (HIWORD(lpcbtcwW->lpcs->lpszName))
724 HeapFree( SystemHeap, 0, (LPWSTR)lpcbtcwW->lpcs->lpszName );
725 if (HIWORD(lpcbtcwW->lpcs->lpszClass))
726 HeapFree( SystemHeap, 0, (LPWSTR)lpcbtcwW->lpcs->lpszClass );
727 HeapFree( SystemHeap, 0, lpcbtcwW->lpcs );
728 HeapFree( SystemHeap, 0, lpcbtcwW );
730 return;
734 /***********************************************************************
735 * HOOK_Map32WTo32A
737 static void HOOK_Map32WTo32A(INT id, INT code, WPARAM *pwParam,
738 LPARAM *plParam)
740 if (id == WH_CBT && code == HCBT_CREATEWND)
742 LPCBT_CREATEWNDW lpcbtcwW = (LPCBT_CREATEWNDW)*plParam;
743 LPCBT_CREATEWNDA lpcbtcwA = HeapAlloc( SystemHeap, 0,
744 sizeof(*lpcbtcwA) );
745 lpcbtcwA->lpcs = HeapAlloc( SystemHeap, 0, sizeof(*lpcbtcwA->lpcs) );
747 lpcbtcwA->hwndInsertAfter = lpcbtcwW->hwndInsertAfter;
748 *lpcbtcwA->lpcs = *(LPCREATESTRUCTA)lpcbtcwW->lpcs;
750 if (HIWORD(lpcbtcwW->lpcs->lpszName))
751 lpcbtcwA->lpcs->lpszName = HEAP_strdupWtoA( SystemHeap, 0,
752 lpcbtcwW->lpcs->lpszName );
753 else
754 lpcbtcwA->lpcs->lpszName = (LPSTR)lpcbtcwW->lpcs->lpszName;
756 if (HIWORD(lpcbtcwW->lpcs->lpszClass))
757 lpcbtcwA->lpcs->lpszClass = HEAP_strdupWtoA( SystemHeap, 0,
758 lpcbtcwW->lpcs->lpszClass );
759 else
760 lpcbtcwA->lpcs->lpszClass = (LPSTR)lpcbtcwW->lpcs->lpszClass;
761 *plParam = (LPARAM)lpcbtcwA;
763 return;
767 /***********************************************************************
768 * HOOK_UnMap32WTo32A
770 static void HOOK_UnMap32WTo32A(INT id, INT code, WPARAM wParamOrig,
771 LPARAM lParamOrig, WPARAM wParam,
772 LPARAM lParam)
774 if (id == WH_CBT && code == HCBT_CREATEWND)
776 LPCBT_CREATEWNDA lpcbtcwA = (LPCBT_CREATEWNDA)lParam;
777 if (HIWORD(lpcbtcwA->lpcs->lpszName))
778 HeapFree( SystemHeap, 0, (LPSTR)lpcbtcwA->lpcs->lpszName );
779 if (HIWORD(lpcbtcwA->lpcs->lpszClass))
780 HeapFree( SystemHeap, 0, (LPSTR)lpcbtcwA->lpcs->lpszClass );
781 HeapFree( SystemHeap, 0, lpcbtcwA->lpcs );
782 HeapFree( SystemHeap, 0, lpcbtcwA );
784 return;
788 /***********************************************************************
789 * Map Function Tables
791 static const HOOK_MapFunc HOOK_MapFuncs[3][3] =
793 { NULL, HOOK_Map16To32A, HOOK_Map16To32W },
794 { HOOK_Map32ATo16, NULL, HOOK_Map32ATo32W },
795 { HOOK_Map32WTo16, HOOK_Map32WTo32A, NULL }
798 static const HOOK_UnMapFunc HOOK_UnMapFuncs[3][3] =
800 { NULL, HOOK_UnMap16To32A, HOOK_UnMap16To32W },
801 { HOOK_UnMap32ATo16, NULL, HOOK_UnMap32ATo32W },
802 { HOOK_UnMap32WTo16, HOOK_UnMap32WTo32A, NULL }
806 /***********************************************************************
807 * Internal Functions
810 /***********************************************************************
811 * HOOK_GetNextHook
813 * Get the next hook of a given hook.
815 static HANDLE16 HOOK_GetNextHook( HANDLE16 hook )
817 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR( hook );
819 if (!data || !hook) return 0;
820 if (data->next) return data->next;
821 if (!data->ownerQueue) return 0; /* Already system hook */
823 /* Now start enumerating the system hooks */
824 return HOOK_systemHooks[data->id - WH_MINHOOK];
828 /***********************************************************************
829 * HOOK_GetHook
831 * Get the first hook for a given type.
833 static HANDLE16 HOOK_GetHook( INT16 id, HQUEUE16 hQueue )
835 MESSAGEQUEUE *queue;
836 HANDLE16 hook = 0;
838 if ((queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue )) != NULL)
839 hook = queue->hooks[id - WH_MINHOOK];
840 if (!hook) hook = HOOK_systemHooks[id - WH_MINHOOK];
842 QUEUE_Unlock( queue );
843 return hook;
847 /***********************************************************************
848 * HOOK_SetHook
850 * Install a given hook.
852 static HHOOK HOOK_SetHook( INT16 id, LPVOID proc, INT type,
853 HMODULE16 hModule, DWORD dwThreadId )
855 HOOKDATA *data;
856 HANDLE16 handle;
857 HQUEUE16 hQueue = 0;
859 if ((id < WH_MINHOOK) || (id > WH_MAXHOOK)) return 0;
861 TRACE(hook, "Setting hook %d: %08x %04x %08lx\n",
862 id, (UINT)proc, hModule, dwThreadId );
864 /* Create task queue if none present */
865 GetFastQueue16();
867 if (id == WH_JOURNALPLAYBACK) EnableHardwareInput16(FALSE);
869 if (dwThreadId) /* Task-specific hook */
871 if ((id == WH_JOURNALRECORD) || (id == WH_JOURNALPLAYBACK) ||
872 (id == WH_SYSMSGFILTER)) return 0; /* System-only hooks */
873 if (!(hQueue = GetThreadQueue16( dwThreadId )))
874 return 0;
877 /* Create the hook structure */
879 if (!(handle = USER_HEAP_ALLOC( sizeof(HOOKDATA) ))) return 0;
880 data = (HOOKDATA *) USER_HEAP_LIN_ADDR( handle );
881 data->proc = proc;
882 data->id = id;
883 data->ownerQueue = hQueue;
884 data->ownerModule = hModule;
885 data->flags = type;
887 /* Insert it in the correct linked list */
889 if (hQueue)
891 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue );
892 data->next = queue->hooks[id - WH_MINHOOK];
893 queue->hooks[id - WH_MINHOOK] = handle;
894 QUEUE_Unlock( queue );
896 else
898 data->next = HOOK_systemHooks[id - WH_MINHOOK];
899 HOOK_systemHooks[id - WH_MINHOOK] = handle;
901 TRACE(hook, "Setting hook %d: ret=%04x [next=%04x]\n",
902 id, handle, data->next );
904 return (HHOOK)( handle? MAKELONG( handle, HOOK_MAGIC ) : 0 );
908 /***********************************************************************
909 * HOOK_RemoveHook
911 * Remove a hook from the list.
913 static BOOL HOOK_RemoveHook( HANDLE16 hook )
915 HOOKDATA *data;
916 HANDLE16 *prevHook;
918 TRACE(hook, "Removing hook %04x\n", hook );
920 if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook))) return FALSE;
921 if (data->flags & HOOK_INUSE)
923 /* Mark it for deletion later on */
924 WARN(hook, "Hook still running, deletion delayed\n" );
925 data->proc = (HOOKPROC)0;
926 return TRUE;
929 if (data->id == WH_JOURNALPLAYBACK) EnableHardwareInput16(TRUE);
931 /* Remove it from the linked list */
933 if (data->ownerQueue)
935 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( data->ownerQueue );
936 if (!queue) return FALSE;
937 prevHook = &queue->hooks[data->id - WH_MINHOOK];
938 QUEUE_Unlock( queue );
940 else prevHook = &HOOK_systemHooks[data->id - WH_MINHOOK];
942 while (*prevHook && *prevHook != hook)
943 prevHook = &((HOOKDATA *)USER_HEAP_LIN_ADDR(*prevHook))->next;
945 if (!*prevHook) return FALSE;
946 *prevHook = data->next;
947 USER_HEAP_FREE( hook );
948 return TRUE;
952 /***********************************************************************
953 * HOOK_FindValidHook
955 static HANDLE16 HOOK_FindValidHook( HANDLE16 hook )
957 HOOKDATA *data;
959 for (;;)
961 if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook))) return 0;
962 if (data->proc) return hook;
963 hook = data->next;
968 /***********************************************************************
969 * HOOK_CallHook
971 * Call a hook procedure.
973 static LRESULT HOOK_CallHook( HANDLE16 hook, INT fromtype, INT code,
974 WPARAM wParam, LPARAM lParam )
976 MESSAGEQUEUE *queue;
977 HANDLE16 prevHook;
978 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
979 LRESULT ret;
981 WPARAM wParamOrig = wParam;
982 LPARAM lParamOrig = lParam;
983 HOOK_MapFunc MapFunc;
984 HOOK_UnMapFunc UnMapFunc;
986 MapFunc = HOOK_MapFuncs[fromtype][data->flags & HOOK_MAPTYPE];
987 UnMapFunc = HOOK_UnMapFuncs[fromtype][data->flags & HOOK_MAPTYPE];
989 if (MapFunc)
990 MapFunc( data->id, code, &wParam, &lParam );
992 /* Now call it */
994 if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() ))) return 0;
995 prevHook = queue->hCurHook;
996 queue->hCurHook = hook;
997 data->flags |= HOOK_INUSE;
999 TRACE(hook, "Calling hook %04x: %d %08x %08lx\n",
1000 hook, code, wParam, lParam );
1002 ret = data->proc(code, wParam, lParam);
1004 /* Grrr. While the hook procedure is supposed to have an LRESULT return
1005 value even in Win16, it seems that for those hook types where the
1006 return value is interpreted as BOOL, Windows doesn't actually check
1007 the HIWORD ... Some buggy Win16 programs, notably WINFILE, rely on
1008 that, because they neglect to clear DX ... */
1009 if ( (data->flags & HOOK_MAPTYPE) == HOOK_WIN16
1010 && data->id != WH_JOURNALPLAYBACK )
1011 ret = LOWORD( ret );
1013 TRACE(hook, "Ret hook %04x = %08lx\n", hook, ret );
1015 data->flags &= ~HOOK_INUSE;
1016 queue->hCurHook = prevHook;
1018 QUEUE_Unlock( queue );
1020 if (UnMapFunc)
1021 UnMapFunc( data->id, code, wParamOrig, lParamOrig, wParam, lParam );
1023 if (!data->proc) HOOK_RemoveHook( hook );
1025 return ret;
1028 /***********************************************************************
1029 * Exported Functions & APIs
1032 /***********************************************************************
1033 * HOOK_GetProc16
1035 * Don't call this unless you are the if1632/thunk.c.
1037 HOOKPROC16 HOOK_GetProc16( HHOOK hhook )
1039 HOOKDATA *data;
1040 if (HIWORD(hhook) != HOOK_MAGIC) return NULL;
1041 if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR( LOWORD(hhook) ))) return NULL;
1042 if ((data->flags & HOOK_MAPTYPE) != HOOK_WIN16) return NULL;
1043 return (HOOKPROC16)data->proc;
1047 /***********************************************************************
1048 * HOOK_IsHooked
1050 * Replacement for calling HOOK_GetHook from other modules.
1052 BOOL HOOK_IsHooked( INT16 id )
1054 /* Hmmm. Use GetThreadQueue(0) instead of GetFastQueue() here to
1055 avoid queue being created if someone wants to merely check ... */
1057 return HOOK_GetHook( id, GetThreadQueue16(0) ) != 0;
1061 /***********************************************************************
1062 * HOOK_CallHooks16
1064 * Call a hook chain.
1066 LRESULT HOOK_CallHooks16( INT16 id, INT16 code, WPARAM16 wParam,
1067 LPARAM lParam )
1069 HANDLE16 hook;
1071 if (!(hook = HOOK_GetHook( id, GetFastQueue16() ))) return 0;
1072 if (!(hook = HOOK_FindValidHook(hook))) return 0;
1073 return HOOK_CallHook( hook, HOOK_WIN16, code, wParam, lParam );
1076 /***********************************************************************
1077 * HOOK_CallHooks32A
1079 * Call a hook chain.
1081 LRESULT HOOK_CallHooksA( INT id, INT code, WPARAM wParam,
1082 LPARAM lParam )
1084 HANDLE16 hook;
1086 if (!(hook = HOOK_GetHook( id, GetFastQueue16() ))) return 0;
1087 if (!(hook = HOOK_FindValidHook(hook))) return 0;
1088 return HOOK_CallHook( hook, HOOK_WIN32A, code, wParam, lParam );
1091 /***********************************************************************
1092 * HOOK_CallHooks32W
1094 * Call a hook chain.
1096 LRESULT HOOK_CallHooksW( INT id, INT code, WPARAM wParam,
1097 LPARAM lParam )
1099 HANDLE16 hook;
1101 if (!(hook = HOOK_GetHook( id, GetFastQueue16() ))) return 0;
1102 if (!(hook = HOOK_FindValidHook(hook))) return 0;
1103 return HOOK_CallHook( hook, HOOK_WIN32W, code, wParam,
1104 lParam );
1108 /***********************************************************************
1109 * HOOK_ResetQueueHooks
1111 void HOOK_ResetQueueHooks( HQUEUE16 hQueue )
1113 MESSAGEQUEUE *queue;
1115 if ((queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue )) != NULL)
1117 HOOKDATA* data;
1118 HHOOK hook;
1119 int id;
1120 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
1122 hook = queue->hooks[id - WH_MINHOOK];
1123 while( hook )
1125 if( (data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook)) )
1127 data->ownerQueue = hQueue;
1128 hook = data->next;
1129 } else break;
1133 QUEUE_Unlock( queue );
1137 /***********************************************************************
1138 * HOOK_FreeModuleHooks
1140 void HOOK_FreeModuleHooks( HMODULE16 hModule )
1142 /* remove all system hooks registered by this module */
1144 HOOKDATA* hptr;
1145 HHOOK hook, next;
1146 int id;
1148 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
1150 hook = HOOK_systemHooks[id - WH_MINHOOK];
1151 while( hook )
1152 if( (hptr = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook)) )
1154 next = hptr->next;
1155 if( hptr->ownerModule == hModule )
1157 hptr->flags &= HOOK_MAPTYPE;
1158 HOOK_RemoveHook(hook);
1160 hook = next;
1162 else hook = 0;
1166 /***********************************************************************
1167 * HOOK_FreeQueueHooks
1169 void HOOK_FreeQueueHooks( HQUEUE16 hQueue )
1171 /* remove all hooks registered by this queue */
1173 HOOKDATA* hptr = NULL;
1174 HHOOK hook, next;
1175 int id;
1177 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
1179 hook = HOOK_GetHook( id, hQueue );
1180 while( hook )
1182 next = HOOK_GetNextHook(hook);
1184 hptr = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
1185 if( hptr && hptr->ownerQueue == hQueue )
1187 hptr->flags &= HOOK_MAPTYPE;
1188 HOOK_RemoveHook(hook);
1190 hook = next;
1196 /***********************************************************************
1197 * SetWindowsHook16 (USER.121)
1199 FARPROC16 WINAPI SetWindowsHook16( INT16 id, HOOKPROC16 proc )
1201 HINSTANCE16 hInst = FarGetOwner16( HIWORD(proc) );
1203 /* WH_MSGFILTER is the only task-specific hook for SetWindowsHook() */
1204 HTASK16 hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
1206 return (FARPROC16)SetWindowsHookEx16( id, proc, hInst, hTask );
1209 /***********************************************************************
1210 * SetWindowsHook32A (USER32.525)
1212 HHOOK WINAPI SetWindowsHookA( INT id, HOOKPROC proc )
1214 return SetWindowsHookExA( id, proc, 0, GetCurrentThreadId() );
1217 /***********************************************************************
1218 * SetWindowsHook32W (USER32.528)
1220 HHOOK WINAPI SetWindowsHookW( INT id, HOOKPROC proc )
1222 return SetWindowsHookExW( id, proc, 0, GetCurrentThreadId() );
1226 /***********************************************************************
1227 * SetWindowsHookEx16 (USER.291)
1229 HHOOK WINAPI SetWindowsHookEx16( INT16 id, HOOKPROC16 proc, HINSTANCE16 hInst,
1230 HTASK16 hTask )
1232 if (id == WH_DEBUG)
1234 FIXME(hook, "WH_DEBUG is broken in 16-bit Windows.\n");
1235 return 0;
1237 return HOOK_SetHook( id, proc, HOOK_WIN16, GetExePtr(hInst), (DWORD)hTask );
1240 /***********************************************************************
1241 * SetWindowsHookEx32A (USER32.526)
1243 HHOOK WINAPI SetWindowsHookExA( INT id, HOOKPROC proc, HINSTANCE hInst,
1244 DWORD dwThreadId )
1246 return HOOK_SetHook( id, proc, HOOK_WIN32A, MapHModuleLS(hInst), dwThreadId );
1249 /***********************************************************************
1250 * SetWindowsHookEx32W (USER32.527)
1252 HHOOK WINAPI SetWindowsHookExW( INT id, HOOKPROC proc, HINSTANCE hInst,
1253 DWORD dwThreadId )
1255 return HOOK_SetHook( id, proc, HOOK_WIN32W, MapHModuleLS(hInst), dwThreadId );
1259 /***********************************************************************
1260 * UnhookWindowsHook16 (USER.234)
1262 BOOL16 WINAPI UnhookWindowsHook16( INT16 id, HOOKPROC16 proc )
1264 return UnhookWindowsHook( id, (HOOKPROC)proc );
1267 /***********************************************************************
1268 * UnhookWindowsHook32 (USER32.557)
1270 BOOL WINAPI UnhookWindowsHook( INT id, HOOKPROC proc )
1272 HANDLE16 hook = HOOK_GetHook( id, GetFastQueue16() );
1274 TRACE(hook, "%d %08lx\n", id, (DWORD)proc );
1276 while (hook)
1278 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
1279 if (data->proc == proc) break;
1280 hook = HOOK_GetNextHook( hook );
1282 if (!hook) return FALSE;
1283 return HOOK_RemoveHook( hook );
1287 /***********************************************************************
1288 * UnhookWindowHookEx16 (USER.292)
1290 BOOL16 WINAPI UnhookWindowsHookEx16( HHOOK hhook )
1292 return UnhookWindowsHookEx( hhook );
1295 /***********************************************************************
1296 * UnhookWindowHookEx32 (USER32.558)
1298 BOOL WINAPI UnhookWindowsHookEx( HHOOK hhook )
1300 if (HIWORD(hhook) != HOOK_MAGIC) return FALSE; /* Not a new format hook */
1301 return HOOK_RemoveHook( LOWORD(hhook) );
1305 /***********************************************************************
1306 * CallNextHookEx16 (USER.293)
1308 * I wouldn't have separated this into 16 and 32 bit versions, but I
1309 * need a way to figure out if I need to do a mapping or not.
1311 LRESULT WINAPI CallNextHookEx16( HHOOK hhook, INT16 code, WPARAM16 wParam,
1312 LPARAM lParam )
1314 HANDLE16 next;
1316 if (HIWORD(hhook) != HOOK_MAGIC) return 0; /* Not a new format hook */
1317 if (!(next = HOOK_GetNextHook( LOWORD(hhook) ))) return 0;
1319 return HOOK_CallHook( next, HOOK_WIN16, code, wParam, lParam );
1323 /***********************************************************************
1324 * CallNextHookEx32 (USER32.17)
1326 * There aren't ANSI and UNICODE versions of this.
1328 LRESULT WINAPI CallNextHookEx( HHOOK hhook, INT code, WPARAM wParam,
1329 LPARAM lParam )
1331 HANDLE16 next;
1332 INT fromtype; /* figure out Ansi/Unicode */
1333 HOOKDATA *oldhook;
1335 if (HIWORD(hhook) != HOOK_MAGIC) return 0; /* Not a new format hook */
1336 if (!(next = HOOK_GetNextHook( LOWORD(hhook) ))) return 0;
1338 oldhook = (HOOKDATA *)USER_HEAP_LIN_ADDR( LOWORD(hhook) );
1339 fromtype = oldhook->flags & HOOK_MAPTYPE;
1341 if (fromtype == HOOK_WIN16)
1342 ERR(hook, "called from 16bit hook!\n");
1344 return HOOK_CallHook( next, fromtype, code, wParam, lParam );
1348 /***********************************************************************
1349 * DefHookProc16 (USER.235)
1351 LRESULT WINAPI DefHookProc16( INT16 code, WPARAM16 wParam, LPARAM lParam,
1352 HHOOK *hhook )
1354 /* Note: the *hhook parameter is never used, since we rely on the
1355 * current hook value from the task queue to find the next hook. */
1356 MESSAGEQUEUE *queue;
1357 LRESULT ret;
1359 if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() ))) return 0;
1360 ret = CallNextHookEx16( queue->hCurHook, code, wParam, lParam );
1361 QUEUE_Unlock( queue );
1362 return ret;
1366 /***********************************************************************
1367 * CallMsgFilter16 (USER.123)
1369 BOOL16 WINAPI CallMsgFilter16( SEGPTR msg, INT16 code )
1371 if (GetSysModalWindow16()) return FALSE;
1372 if (HOOK_CallHooks16( WH_SYSMSGFILTER, code, 0, (LPARAM)msg )) return TRUE;
1373 return HOOK_CallHooks16( WH_MSGFILTER, code, 0, (LPARAM)msg );
1377 /***********************************************************************
1378 * WIN16_CallMsgFilter32 (USER.823)
1380 BOOL16 WINAPI CallMsgFilter32_16( SEGPTR msg16_32, INT16 code, BOOL16 wHaveParamHigh )
1382 MSG32_16 *lpmsg16_32 = (MSG32_16 *)PTR_SEG_TO_LIN(msg16_32);
1384 if (wHaveParamHigh == FALSE)
1386 lpmsg16_32->wParamHigh = 0;
1387 /* WARNING: msg16_32->msg has to be the first variable in the struct */
1388 return CallMsgFilter16(msg16_32, code);
1390 else
1392 MSG msg32;
1393 BOOL16 ret;
1395 msg32.hwnd = lpmsg16_32->msg.hwnd;
1396 msg32.message = lpmsg16_32->msg.message;
1397 msg32.wParam =
1398 MAKELONG(lpmsg16_32->msg.wParam, lpmsg16_32->wParamHigh);
1399 msg32.lParam = lpmsg16_32->msg.lParam;
1400 msg32.time = lpmsg16_32->msg.time;
1401 msg32.pt.x = (INT)lpmsg16_32->msg.pt.x;
1402 msg32.pt.y = (INT)lpmsg16_32->msg.pt.y;
1404 ret = (BOOL16)CallMsgFilterA(&msg32, (INT)code);
1406 lpmsg16_32->msg.hwnd = msg32.hwnd;
1407 lpmsg16_32->msg.message = msg32.message;
1408 lpmsg16_32->msg.wParam = LOWORD(msg32.wParam);
1409 lpmsg16_32->msg.lParam = msg32.lParam;
1410 lpmsg16_32->msg.time = msg32.time;
1411 lpmsg16_32->msg.pt.x = (INT16)msg32.pt.x;
1412 lpmsg16_32->msg.pt.y = (INT16)msg32.pt.y;
1413 lpmsg16_32->wParamHigh = HIWORD(msg32.wParam);
1415 return ret;
1420 /***********************************************************************
1421 * CallMsgFilter32A (USER32.15)
1424 * FIXME: There are ANSI and UNICODE versions of this, plus an unspecified
1425 * version, plus USER (the 16bit one) has a CallMsgFilter32 function.
1427 BOOL WINAPI CallMsgFilterA( LPMSG msg, INT code )
1429 if (GetSysModalWindow16()) return FALSE; /* ??? */
1430 if (HOOK_CallHooksA( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
1431 return TRUE;
1432 return HOOK_CallHooksA( WH_MSGFILTER, code, 0, (LPARAM)msg );
1436 /***********************************************************************
1437 * CallMsgFilter32W (USER32.16)
1439 BOOL WINAPI CallMsgFilterW( LPMSG msg, INT code )
1441 if (GetSysModalWindow16()) return FALSE; /* ??? */
1442 if (HOOK_CallHooksW( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
1443 return TRUE;
1444 return HOOK_CallHooksW( WH_MSGFILTER, code, 0, (LPARAM)msg );