Owen Wang
[wine.git] / windows / hook.c
blob5c591d3d16d36391138d0891496083215637ea3a
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 "wingdi.h"
19 #include "winuser.h"
20 #include "wine/winuser16.h"
21 #include "wine/winbase16.h"
22 #include "callback.h"
23 #include "hook.h"
24 #include "win.h"
25 #include "queue.h"
26 #include "task.h"
27 #include "user.h"
28 #include "heap.h"
29 #include "struct32.h"
30 #include "winproc.h"
31 #include "debugtools.h"
33 DEFAULT_DEBUG_CHANNEL(hook)
35 #include "pshpack1.h"
37 /* Hook data (pointed to by a HHOOK) */
38 typedef struct
40 HANDLE16 next; /* 00 Next hook in chain */
41 HOOKPROC proc; /* 02 Hook procedure (original) */
42 INT16 id; /* 06 Hook id (WH_xxx) */
43 HQUEUE16 ownerQueue; /* 08 Owner queue (0 for system hook) */
44 HMODULE16 ownerModule; /* 0a Owner module */
45 WORD flags; /* 0c flags */
46 HOOKPROC thunk; /* 0e Hook procedure (CallTo16 thunk) */
47 } HOOKDATA;
49 #include "poppack.h"
51 #define HOOK_MAGIC ((int)'H' | (int)'K' << 8) /* 'HK' */
53 /* This should probably reside in USER heap */
54 static HANDLE16 HOOK_systemHooks[WH_NB_HOOKS] = { 0, };
56 typedef VOID (*HOOK_MapFunc)(INT, INT, WPARAM *, LPARAM *);
57 typedef VOID (*HOOK_UnMapFunc)(INT, INT, WPARAM, LPARAM, WPARAM,
58 LPARAM);
60 /***********************************************************************
61 * HOOK_Map16To32Common
63 static void HOOK_Map16To32Common(INT id, INT code, WPARAM *pwParam,
64 LPARAM *plParam, BOOL bA )
67 switch( id )
69 case WH_MSGFILTER:
70 case WH_SYSMSGFILTER:
71 case WH_GETMESSAGE:
72 case WH_JOURNALRECORD:
74 LPMSG16 lpmsg16 = PTR_SEG_TO_LIN(*plParam);
75 LPMSG lpmsg32 = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpmsg32) );
77 STRUCT32_MSG16to32( lpmsg16, lpmsg32 );
78 *plParam = (LPARAM)lpmsg32;
79 break;
82 case WH_JOURNALPLAYBACK:
84 LPEVENTMSG16 lpem16 = PTR_SEG_TO_LIN(*plParam);
85 LPEVENTMSG lpem32 = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpem32) );
87 lpem32->message = lpem16->message;
88 lpem32->paramL = lpem16->paramL;
89 lpem32->paramH = lpem16->paramH;
90 lpem32->time = lpem16->time;
91 lpem32->hwnd = 0; /* FIXME */
93 *plParam = (LPARAM)lpem32;
94 break;
97 case WH_CALLWNDPROC:
99 LPCWPSTRUCT16 lpcwp16 = PTR_SEG_TO_LIN(*plParam);
100 LPCWPSTRUCT lpcwp32 = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpcwp32) );
102 lpcwp32->hwnd = lpcwp16->hwnd;
103 lpcwp32->lParam = lpcwp16->lParam;
105 if (bA) WINPROC_MapMsg16To32A( lpcwp16->message, lpcwp16->wParam,
106 &lpcwp32->message, &lpcwp32->wParam,
107 &lpcwp32->lParam );
108 else WINPROC_MapMsg16To32W( lpcwp16->hwnd,lpcwp16->message, lpcwp16->wParam,
109 &lpcwp32->message, &lpcwp32->wParam,
110 &lpcwp32->lParam );
111 *plParam = (LPARAM)lpcwp32;
112 break;
115 case WH_CBT:
116 switch (code)
118 case HCBT_CREATEWND:
120 LPCBT_CREATEWND16 lpcbtcw16 = PTR_SEG_TO_LIN(*plParam);
121 LPCREATESTRUCT16 lpcs16 = PTR_SEG_TO_LIN(lpcbtcw16->lpcs);
122 LPCBT_CREATEWNDA lpcbtcw32 = HeapAlloc( GetProcessHeap(), 0,
123 sizeof(*lpcbtcw32) );
124 lpcbtcw32->lpcs = HeapAlloc( GetProcessHeap(), 0,
125 sizeof(*lpcbtcw32->lpcs) );
127 STRUCT32_CREATESTRUCT16to32A( lpcs16,
128 (LPCREATESTRUCTA)lpcbtcw32->lpcs );
130 if (HIWORD(lpcs16->lpszName))
131 lpcbtcw32->lpcs->lpszName =
132 (bA) ? PTR_SEG_TO_LIN(lpcs16->lpszName)
133 : HEAP_strdupAtoW( GetProcessHeap(), 0,
134 PTR_SEG_TO_LIN(lpcs16->lpszName) );
135 else
136 lpcbtcw32->lpcs->lpszName = (LPCSTR)lpcs16->lpszName;
138 if (HIWORD(lpcs16->lpszClass))
139 lpcbtcw32->lpcs->lpszClass =
140 (bA) ? PTR_SEG_TO_LIN(lpcs16->lpszClass)
141 : HEAP_strdupAtoW( GetProcessHeap(), 0,
142 PTR_SEG_TO_LIN(lpcs16->lpszClass) );
143 else
144 lpcbtcw32->lpcs->lpszClass = (LPCSTR)lpcs16->lpszClass;
146 lpcbtcw32->hwndInsertAfter = lpcbtcw16->hwndInsertAfter;
148 *plParam = (LPARAM)lpcbtcw32;
149 break;
151 case HCBT_ACTIVATE:
153 LPCBTACTIVATESTRUCT16 lpcas16 = PTR_SEG_TO_LIN(*plParam);
154 LPCBTACTIVATESTRUCT lpcas32 = HeapAlloc( GetProcessHeap(), 0,
155 sizeof(*lpcas32) );
156 lpcas32->fMouse = lpcas16->fMouse;
157 lpcas32->hWndActive = lpcas16->hWndActive;
158 *plParam = (LPARAM)lpcas32;
159 break;
161 case HCBT_CLICKSKIPPED:
163 LPMOUSEHOOKSTRUCT16 lpms16 = PTR_SEG_TO_LIN(*plParam);
164 LPMOUSEHOOKSTRUCT lpms32 = HeapAlloc( GetProcessHeap(), 0,
165 sizeof(*lpms32) );
167 CONV_POINT16TO32( &lpms16->pt, &lpms32->pt );
169 /* wHitTestCode may be negative, so convince compiler to do
170 correct sign extension. Yay. :| */
171 lpms32->wHitTestCode = (INT)((INT16)lpms16->wHitTestCode);
173 lpms32->dwExtraInfo = lpms16->dwExtraInfo;
174 lpms32->hwnd = lpms16->hwnd;
175 *plParam = (LPARAM)lpms32;
176 break;
178 case HCBT_MOVESIZE:
180 LPRECT16 lprect16 = PTR_SEG_TO_LIN(*plParam);
181 LPRECT lprect32 = HeapAlloc( GetProcessHeap(), 0,
182 sizeof(*lprect32) );
184 CONV_RECT16TO32( lprect16, lprect32 );
185 *plParam = (LPARAM)lprect32;
186 break;
189 break;
191 case WH_MOUSE:
193 LPMOUSEHOOKSTRUCT16 lpms16 = PTR_SEG_TO_LIN(*plParam);
194 LPMOUSEHOOKSTRUCT lpms32 = HeapAlloc( GetProcessHeap(), 0,
195 sizeof(*lpms32) );
197 CONV_POINT16TO32( &lpms16->pt, &lpms32->pt );
199 /* wHitTestCode may be negative, so convince compiler to do
200 correct sign extension. Yay. :| */
201 lpms32->wHitTestCode = (INT)((INT16)lpms16->wHitTestCode);
202 lpms32->dwExtraInfo = lpms16->dwExtraInfo;
203 lpms32->hwnd = lpms16->hwnd;
204 *plParam = (LPARAM)lpms32;
205 break;
208 case WH_DEBUG:
210 LPDEBUGHOOKINFO16 lpdh16 = PTR_SEG_TO_LIN(*plParam);
211 LPDEBUGHOOKINFO lpdh32 = HeapAlloc( GetProcessHeap(), 0,
212 sizeof(*lpdh32) );
214 lpdh32->idThread = 0; /* FIXME */
215 lpdh32->idThreadInstaller = 0; /* FIXME */
216 lpdh32->lParam = lpdh16->lParam; /* FIXME Check for sign ext */
217 lpdh32->wParam = lpdh16->wParam;
218 lpdh32->code = lpdh16->code;
220 /* do sign extension if it was WH_MSGFILTER */
221 if (*pwParam == 0xffff) *pwParam = WH_MSGFILTER;
223 *plParam = (LPARAM)lpdh32;
224 break;
227 case WH_SHELL:
228 case WH_KEYBOARD:
229 break;
231 case WH_HARDWARE:
232 case WH_FOREGROUNDIDLE:
233 case WH_CALLWNDPROCRET:
234 FIXME("\t[%i] 16to32 translation unimplemented\n", id);
239 /***********************************************************************
240 * HOOK_Map16To32A
242 static void HOOK_Map16To32A(INT id, INT code, WPARAM *pwParam,
243 LPARAM *plParam)
245 HOOK_Map16To32Common( id, code, pwParam, plParam, TRUE );
249 /***********************************************************************
250 * HOOK_Map16To32W
252 static void HOOK_Map16To32W(INT id, INT code, WPARAM *pwParam,
253 LPARAM *plParam)
255 HOOK_Map16To32Common( id, code, pwParam, plParam, FALSE );
259 /***********************************************************************
260 * HOOK_UnMap16To32Common
262 static void HOOK_UnMap16To32Common(INT id, INT code, WPARAM wParamOrig,
263 LPARAM lParamOrig, WPARAM wParam,
264 LPARAM lParam, BOOL bA)
266 switch (id)
268 case WH_MSGFILTER:
269 case WH_SYSMSGFILTER:
270 case WH_JOURNALRECORD:
271 case WH_JOURNALPLAYBACK:
273 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
274 break;
276 case WH_CALLWNDPROC:
278 LPCWPSTRUCT lpcwp32 = (LPCWPSTRUCT)lParam;
279 if (bA) WINPROC_UnmapMsg16To32A( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
280 lpcwp32->lParam, 0 );
281 else WINPROC_UnmapMsg16To32W( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
282 lpcwp32->lParam, 0 );
283 HeapFree( GetProcessHeap(), 0, lpcwp32 );
284 break;
287 case WH_GETMESSAGE:
289 LPMSG16 lpmsg16 = PTR_SEG_TO_LIN(lParamOrig);
290 STRUCT32_MSG32to16( (LPMSG)lParam, lpmsg16 );
291 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
292 break;
295 case WH_MOUSE:
296 case WH_DEBUG:
298 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
299 break;
301 case WH_CBT:
302 switch (code)
304 case HCBT_CREATEWND:
306 LPCBT_CREATEWNDA lpcbtcw32 = (LPCBT_CREATEWNDA)lParam;
307 LPCBT_CREATEWND16 lpcbtcw16 = PTR_SEG_TO_LIN(lParamOrig);
309 if( !bA )
311 if (HIWORD(lpcbtcw32->lpcs->lpszName))
312 HeapFree( GetProcessHeap(), 0, (LPWSTR)lpcbtcw32->lpcs->lpszName );
313 if (HIWORD(lpcbtcw32->lpcs->lpszClass))
314 HeapFree( GetProcessHeap(), 0, (LPWSTR)lpcbtcw32->lpcs->lpszClass );
317 lpcbtcw16->hwndInsertAfter = lpcbtcw32->hwndInsertAfter;
319 HeapFree( GetProcessHeap(), 0, lpcbtcw32->lpcs );
320 } /* fall through */
322 case HCBT_ACTIVATE:
323 case HCBT_CLICKSKIPPED:
324 case HCBT_MOVESIZE:
326 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam);
327 break;
329 break;
331 case WH_SHELL:
332 case WH_KEYBOARD:
333 break;
335 case WH_HARDWARE:
336 case WH_FOREGROUNDIDLE:
337 case WH_CALLWNDPROCRET:
338 FIXME("\t[%i] skipping unmap\n", id);
339 break;
344 /***********************************************************************
345 * HOOK_UnMap16To32A
347 static void HOOK_UnMap16To32A(INT id, INT code, WPARAM wParamOrig,
348 LPARAM lParamOrig, WPARAM wParam,
349 LPARAM lParam)
351 HOOK_UnMap16To32Common( id, code, wParamOrig, lParamOrig, wParam,
352 lParam, TRUE );
356 /***********************************************************************
357 * HOOK_UnMap16To32W
359 static void HOOK_UnMap16To32W(INT id, INT code, WPARAM wParamOrig,
360 LPARAM lParamOrig, WPARAM wParam,
361 LPARAM lParam)
363 HOOK_UnMap16To32Common( id, code, wParamOrig, lParamOrig, wParam,
364 lParam, FALSE );
368 /***********************************************************************
369 * HOOK_Map32To16Common
371 static void HOOK_Map32To16Common(INT id, INT code, WPARAM *pwParam,
372 LPARAM *plParam, BOOL bA)
374 switch (id)
376 case WH_MSGFILTER:
377 case WH_SYSMSGFILTER:
378 case WH_GETMESSAGE:
379 case WH_JOURNALRECORD:
381 LPMSG lpmsg32 = (LPMSG)*plParam;
382 LPMSG16 lpmsg16 = SEGPTR_NEW( MSG16 );
384 STRUCT32_MSG32to16( lpmsg32, lpmsg16 );
386 *plParam = (LPARAM)SEGPTR_GET( lpmsg16 );
387 break;
390 case WH_JOURNALPLAYBACK:
392 LPEVENTMSG lpem32 = (LPEVENTMSG)*plParam;
393 LPEVENTMSG16 lpem16 = SEGPTR_NEW( EVENTMSG16 );
395 lpem16->message = lpem32->message;
396 lpem16->paramL = lpem32->paramL;
397 lpem16->paramH = lpem32->paramH;
398 lpem16->time = lpem32->time;
400 *plParam = (LPARAM)SEGPTR_GET( lpem16 );
401 break;
404 case WH_CALLWNDPROC:
406 LPCWPSTRUCT lpcwp32 = (LPCWPSTRUCT)*plParam;
407 LPCWPSTRUCT16 lpcwp16 = SEGPTR_NEW( CWPSTRUCT16 );
409 lpcwp16->hwnd = lpcwp32->hwnd;
410 lpcwp16->lParam = lpcwp32->lParam;
412 if (bA) WINPROC_MapMsg32ATo16( lpcwp32->hwnd, lpcwp32->message,
413 lpcwp32->wParam, &lpcwp16->message,
414 &lpcwp16->wParam, &lpcwp16->lParam );
415 else WINPROC_MapMsg32WTo16( lpcwp32->hwnd, lpcwp32->message,
416 lpcwp32->wParam, &lpcwp16->message,
417 &lpcwp16->wParam, &lpcwp16->lParam );
418 *plParam = (LPARAM)SEGPTR_GET( lpcwp16 );
419 break;
422 case WH_CBT:
423 switch (code)
425 case HCBT_ACTIVATE:
427 LPCBTACTIVATESTRUCT lpcas32 = (LPCBTACTIVATESTRUCT)*plParam;
428 LPCBTACTIVATESTRUCT16 lpcas16 =SEGPTR_NEW( CBTACTIVATESTRUCT16 );
430 lpcas16->fMouse = lpcas32->fMouse;
431 lpcas16->hWndActive = lpcas32->hWndActive;
433 *plParam = (LPARAM)SEGPTR_GET( lpcas16 );
434 break;
437 case HCBT_CLICKSKIPPED:
439 LPMOUSEHOOKSTRUCT lpms32 = (LPMOUSEHOOKSTRUCT)*plParam;
440 LPMOUSEHOOKSTRUCT16 lpms16 = SEGPTR_NEW( MOUSEHOOKSTRUCT16 );
442 CONV_POINT32TO16( &lpms32->pt, &lpms16->pt );
444 lpms16->hwnd = lpms32->hwnd;
445 lpms16->wHitTestCode = lpms32->wHitTestCode;
446 lpms16->dwExtraInfo = lpms32->dwExtraInfo;
448 *plParam = (LPARAM)SEGPTR_GET( lpms16 );
449 break;
452 case HCBT_MOVESIZE:
454 LPRECT lprect32 = (LPRECT)*plParam;
455 LPRECT16 lprect16 = SEGPTR_NEW( RECT16 );
457 CONV_RECT32TO16( lprect32, lprect16 );
459 *plParam = (LPARAM)SEGPTR_GET( lprect16 );
460 break;
463 break;
465 case WH_MOUSE:
467 LPMOUSEHOOKSTRUCT lpms32 = (LPMOUSEHOOKSTRUCT)*plParam;
468 LPMOUSEHOOKSTRUCT16 lpms16 = SEGPTR_NEW( MOUSEHOOKSTRUCT16 );
470 CONV_POINT32TO16( &lpms32->pt, &lpms16->pt );
472 lpms16->hwnd = lpms32->hwnd;
473 lpms16->wHitTestCode = lpms32->wHitTestCode;
474 lpms16->dwExtraInfo = lpms32->dwExtraInfo;
476 *plParam = (LPARAM)SEGPTR_GET( lpms16 );
477 break;
480 case WH_DEBUG:
482 LPDEBUGHOOKINFO lpdh32 = (LPDEBUGHOOKINFO)*plParam;
483 LPDEBUGHOOKINFO16 lpdh16 = SEGPTR_NEW( DEBUGHOOKINFO16 );
485 lpdh16->hModuleHook = 0; /* FIXME */
486 lpdh16->reserved = 0;
487 lpdh16->lParam = lpdh32->lParam;
488 lpdh16->wParam = lpdh32->wParam;
489 lpdh16->code = lpdh32->code;
491 *plParam = (LPARAM)SEGPTR_GET( lpdh16 );
492 break;
495 case WH_SHELL:
496 case WH_KEYBOARD:
497 break;
499 case WH_HARDWARE:
500 case WH_FOREGROUNDIDLE:
501 case WH_CALLWNDPROCRET:
502 FIXME("\t[%i] 32to16 translation unimplemented\n", id);
507 /***********************************************************************
508 * HOOK_Map32ATo16
510 static void HOOK_Map32ATo16(INT id, INT code, WPARAM *pwParam,
511 LPARAM *plParam)
513 if (id == WH_CBT && code == HCBT_CREATEWND)
515 LPCBT_CREATEWNDA lpcbtcw32 = (LPCBT_CREATEWNDA)*plParam;
516 LPCBT_CREATEWND16 lpcbtcw16 = SEGPTR_NEW( CBT_CREATEWND16 );
517 LPCREATESTRUCT16 lpcs16 = SEGPTR_NEW( CREATESTRUCT16 );
519 lpcbtcw16->lpcs = (LPCREATESTRUCT16)SEGPTR_GET( lpcs16 );
520 STRUCT32_CREATESTRUCT32Ato16( lpcbtcw32->lpcs, lpcs16 );
522 if (HIWORD(lpcbtcw32->lpcs->lpszName))
523 lpcs16->lpszName =
524 SEGPTR_GET( SEGPTR_STRDUP( lpcbtcw32->lpcs->lpszName ) );
525 else
526 lpcs16->lpszName = (SEGPTR)lpcbtcw32->lpcs->lpszName;
528 if (HIWORD(lpcbtcw32->lpcs->lpszClass))
529 lpcs16->lpszClass =
530 SEGPTR_GET( SEGPTR_STRDUP( lpcbtcw32->lpcs->lpszClass ) );
531 else
532 lpcs16->lpszClass = (SEGPTR)lpcbtcw32->lpcs->lpszClass;
534 lpcbtcw16->hwndInsertAfter = lpcbtcw32->hwndInsertAfter;
536 *plParam = (LPARAM)SEGPTR_GET( lpcbtcw16 );
538 else HOOK_Map32To16Common(id, code, pwParam, plParam, TRUE);
542 /***********************************************************************
543 * HOOK_Map32WTo16
545 static void HOOK_Map32WTo16(INT id, INT code, WPARAM *pwParam,
546 LPARAM *plParam)
548 if (id == WH_CBT && code == HCBT_CREATEWND)
550 LPSTR name, cls;
551 LPCBT_CREATEWNDW lpcbtcw32 = (LPCBT_CREATEWNDW)*plParam;
552 LPCBT_CREATEWND16 lpcbtcw16 = SEGPTR_NEW( CBT_CREATEWND16 );
553 LPCREATESTRUCT16 lpcs16 = SEGPTR_NEW( CREATESTRUCT16 );
555 lpcbtcw16->lpcs = (LPCREATESTRUCT16)SEGPTR_GET( lpcs16 );
556 STRUCT32_CREATESTRUCT32Ato16( (LPCREATESTRUCTA)lpcbtcw32->lpcs,
557 lpcs16 );
559 name = SEGPTR_STRDUP_WtoA( lpcbtcw32->lpcs->lpszName );
560 cls = SEGPTR_STRDUP_WtoA( lpcbtcw32->lpcs->lpszClass );
561 lpcs16->lpszName = SEGPTR_GET( name );
562 lpcs16->lpszClass = SEGPTR_GET( cls );
563 lpcbtcw16->hwndInsertAfter = lpcbtcw32->hwndInsertAfter;
565 *plParam = (LPARAM)SEGPTR_GET( lpcbtcw16 );
567 else HOOK_Map32To16Common(id, code, pwParam, plParam, FALSE);
571 /***********************************************************************
572 * HOOK_UnMap32To16Common
574 static void HOOK_UnMap32To16Common(INT id, INT code, WPARAM wParamOrig,
575 LPARAM lParamOrig, WPARAM wParam,
576 LPARAM lParam, BOOL bA)
578 switch (id)
580 case WH_MSGFILTER:
581 case WH_SYSMSGFILTER:
582 case WH_JOURNALRECORD:
583 case WH_JOURNALPLAYBACK:
584 case WH_MOUSE:
585 case WH_DEBUG:
586 SEGPTR_FREE( PTR_SEG_TO_LIN(lParam) );
587 break;
589 case WH_CALLWNDPROC:
591 LPCWPSTRUCT16 lpcwp16 = (LPCWPSTRUCT16)PTR_SEG_TO_LIN(lParam);
592 LPCWPSTRUCT lpcwp32 = (LPCWPSTRUCT)lParamOrig;
593 MSGPARAM16 mp16;
595 mp16.wParam = lpcwp16->wParam;
596 mp16.lParam = lpcwp16->lParam;
597 mp16.lResult = 0;
599 if (bA) WINPROC_UnmapMsg32ATo16( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
600 lpcwp32->lParam, &mp16 );
601 else WINPROC_UnmapMsg32WTo16( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
602 lpcwp32->lParam, &mp16 );
603 SEGPTR_FREE( PTR_SEG_TO_LIN(lParam) );
604 break;
607 case WH_GETMESSAGE:
609 LPMSG lpmsg32 = (LPMSG)lParamOrig;
611 STRUCT32_MSG16to32( (LPMSG16)PTR_SEG_TO_LIN(lParam), lpmsg32 );
612 SEGPTR_FREE( PTR_SEG_TO_LIN(lParam) );
613 break;
616 case WH_CBT:
617 switch (code)
619 case HCBT_CREATEWND:
621 LPCBT_CREATEWNDA lpcbtcw32 = (LPCBT_CREATEWNDA)(lParamOrig);
622 LPCBT_CREATEWND16 lpcbtcw16 = PTR_SEG_TO_LIN(lParam);
623 LPCREATESTRUCT16 lpcs16 = PTR_SEG_TO_LIN(lpcbtcw16->lpcs);
625 if (HIWORD(lpcs16->lpszName))
626 SEGPTR_FREE( PTR_SEG_TO_LIN(lpcs16->lpszName) );
628 if (HIWORD(lpcs16->lpszClass))
629 SEGPTR_FREE( PTR_SEG_TO_LIN(lpcs16->lpszClass) );
631 lpcbtcw32->hwndInsertAfter = lpcbtcw16->hwndInsertAfter;
633 SEGPTR_FREE( lpcs16 );
634 } /* fall through */
636 case HCBT_ACTIVATE:
637 case HCBT_CLICKSKIPPED:
638 case HCBT_MOVESIZE:
640 SEGPTR_FREE( PTR_SEG_TO_LIN(lParam) );
641 break;
643 break;
645 case WH_SHELL:
646 case WH_KEYBOARD:
647 break;
649 case WH_HARDWARE:
650 case WH_FOREGROUNDIDLE:
651 case WH_CALLWNDPROCRET:
652 FIXME("\t[%i] skipping unmap\n", id);
657 /***********************************************************************
658 * HOOK_UnMap32ATo16
660 static void HOOK_UnMap32ATo16(INT id, INT code, WPARAM wParamOrig,
661 LPARAM lParamOrig, WPARAM wParam,
662 LPARAM lParam)
664 HOOK_UnMap32To16Common( id, code, wParamOrig, lParamOrig, wParam,
665 lParam, TRUE );
669 /***********************************************************************
670 * HOOK_UnMap32WTo16
672 static void HOOK_UnMap32WTo16(INT id, INT code, WPARAM wParamOrig,
673 LPARAM lParamOrig, WPARAM wParam,
674 LPARAM lParam)
676 HOOK_UnMap32To16Common( id, code, wParamOrig, lParamOrig, wParam,
677 lParam, FALSE );
681 /***********************************************************************
682 * HOOK_Map32ATo32W
684 static void HOOK_Map32ATo32W(INT id, INT code, WPARAM *pwParam,
685 LPARAM *plParam)
687 if (id == WH_CBT && code == HCBT_CREATEWND)
689 LPCBT_CREATEWNDA lpcbtcwA = (LPCBT_CREATEWNDA)*plParam;
690 LPCBT_CREATEWNDW lpcbtcwW = HeapAlloc( GetProcessHeap(), 0,
691 sizeof(*lpcbtcwW) );
692 lpcbtcwW->lpcs = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpcbtcwW->lpcs) );
694 lpcbtcwW->hwndInsertAfter = lpcbtcwA->hwndInsertAfter;
695 *lpcbtcwW->lpcs = *(LPCREATESTRUCTW)lpcbtcwA->lpcs;
697 if (HIWORD(lpcbtcwA->lpcs->lpszName))
699 lpcbtcwW->lpcs->lpszName = HEAP_strdupAtoW( GetProcessHeap(), 0,
700 lpcbtcwA->lpcs->lpszName );
702 else
703 lpcbtcwW->lpcs->lpszName = (LPWSTR)lpcbtcwA->lpcs->lpszName;
705 if (HIWORD(lpcbtcwA->lpcs->lpszClass))
707 lpcbtcwW->lpcs->lpszClass = HEAP_strdupAtoW( GetProcessHeap(), 0,
708 lpcbtcwA->lpcs->lpszClass );
710 else
711 lpcbtcwW->lpcs->lpszClass = (LPCWSTR)lpcbtcwA->lpcs->lpszClass;
712 *plParam = (LPARAM)lpcbtcwW;
714 return;
718 /***********************************************************************
719 * HOOK_UnMap32ATo32W
721 static void HOOK_UnMap32ATo32W(INT id, INT code, WPARAM wParamOrig,
722 LPARAM lParamOrig, WPARAM wParam,
723 LPARAM lParam)
725 if (id == WH_CBT && code == HCBT_CREATEWND)
727 LPCBT_CREATEWNDW lpcbtcwW = (LPCBT_CREATEWNDW)lParam;
728 if (HIWORD(lpcbtcwW->lpcs->lpszName))
729 HeapFree( GetProcessHeap(), 0, (LPWSTR)lpcbtcwW->lpcs->lpszName );
730 if (HIWORD(lpcbtcwW->lpcs->lpszClass))
731 HeapFree( GetProcessHeap(), 0, (LPWSTR)lpcbtcwW->lpcs->lpszClass );
732 HeapFree( GetProcessHeap(), 0, lpcbtcwW->lpcs );
733 HeapFree( GetProcessHeap(), 0, lpcbtcwW );
735 return;
739 /***********************************************************************
740 * HOOK_Map32WTo32A
742 static void HOOK_Map32WTo32A(INT id, INT code, WPARAM *pwParam,
743 LPARAM *plParam)
745 if (id == WH_CBT && code == HCBT_CREATEWND)
747 LPCBT_CREATEWNDW lpcbtcwW = (LPCBT_CREATEWNDW)*plParam;
748 LPCBT_CREATEWNDA lpcbtcwA = HeapAlloc( GetProcessHeap(), 0,
749 sizeof(*lpcbtcwA) );
750 lpcbtcwA->lpcs = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpcbtcwA->lpcs) );
752 lpcbtcwA->hwndInsertAfter = lpcbtcwW->hwndInsertAfter;
753 *lpcbtcwA->lpcs = *(LPCREATESTRUCTA)lpcbtcwW->lpcs;
755 if (HIWORD(lpcbtcwW->lpcs->lpszName))
756 lpcbtcwA->lpcs->lpszName = HEAP_strdupWtoA( GetProcessHeap(), 0,
757 lpcbtcwW->lpcs->lpszName );
758 else
759 lpcbtcwA->lpcs->lpszName = (LPSTR)lpcbtcwW->lpcs->lpszName;
761 if (HIWORD(lpcbtcwW->lpcs->lpszClass))
762 lpcbtcwA->lpcs->lpszClass = HEAP_strdupWtoA( GetProcessHeap(), 0,
763 lpcbtcwW->lpcs->lpszClass );
764 else
765 lpcbtcwA->lpcs->lpszClass = (LPSTR)lpcbtcwW->lpcs->lpszClass;
766 *plParam = (LPARAM)lpcbtcwA;
768 return;
772 /***********************************************************************
773 * HOOK_UnMap32WTo32A
775 static void HOOK_UnMap32WTo32A(INT id, INT code, WPARAM wParamOrig,
776 LPARAM lParamOrig, WPARAM wParam,
777 LPARAM lParam)
779 if (id == WH_CBT && code == HCBT_CREATEWND)
781 LPCBT_CREATEWNDA lpcbtcwA = (LPCBT_CREATEWNDA)lParam;
782 if (HIWORD(lpcbtcwA->lpcs->lpszName))
783 HeapFree( GetProcessHeap(), 0, (LPSTR)lpcbtcwA->lpcs->lpszName );
784 if (HIWORD(lpcbtcwA->lpcs->lpszClass))
785 HeapFree( GetProcessHeap(), 0, (LPSTR)lpcbtcwA->lpcs->lpszClass );
786 HeapFree( GetProcessHeap(), 0, lpcbtcwA->lpcs );
787 HeapFree( GetProcessHeap(), 0, lpcbtcwA );
789 return;
793 /***********************************************************************
794 * Map Function Tables
796 static const HOOK_MapFunc HOOK_MapFuncs[3][3] =
798 { NULL, HOOK_Map16To32A, HOOK_Map16To32W },
799 { HOOK_Map32ATo16, NULL, HOOK_Map32ATo32W },
800 { HOOK_Map32WTo16, HOOK_Map32WTo32A, NULL }
803 static const HOOK_UnMapFunc HOOK_UnMapFuncs[3][3] =
805 { NULL, HOOK_UnMap16To32A, HOOK_UnMap16To32W },
806 { HOOK_UnMap32ATo16, NULL, HOOK_UnMap32ATo32W },
807 { HOOK_UnMap32WTo16, HOOK_UnMap32WTo32A, NULL }
811 /***********************************************************************
812 * Internal Functions
815 /***********************************************************************
816 * HOOK_GetNextHook
818 * Get the next hook of a given hook.
820 static HANDLE16 HOOK_GetNextHook( HANDLE16 hook )
822 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR( hook );
824 if (!data || !hook) return 0;
825 if (data->next) return data->next;
826 if (!data->ownerQueue) return 0; /* Already system hook */
828 /* Now start enumerating the system hooks */
829 return HOOK_systemHooks[data->id - WH_MINHOOK];
833 /***********************************************************************
834 * HOOK_GetHook
836 * Get the first hook for a given type.
838 static HANDLE16 HOOK_GetHook( INT16 id, HQUEUE16 hQueue )
840 MESSAGEQUEUE *queue;
841 HANDLE16 hook = 0;
843 if ((queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue )) != NULL)
844 hook = queue->hooks[id - WH_MINHOOK];
845 if (!hook) hook = HOOK_systemHooks[id - WH_MINHOOK];
847 QUEUE_Unlock( queue );
848 return hook;
852 /***********************************************************************
853 * HOOK_SetHook
855 * Install a given hook.
857 /* ### start build ### */
858 extern LONG CALLBACK HOOK_CallTo16_long_wwl(FARPROC16,WORD,WORD,LONG);
859 /* ### stop build ### */
860 static HHOOK HOOK_SetHook( INT16 id, LPVOID proc, INT type,
861 HMODULE16 hModule, DWORD dwThreadId )
863 HOOKDATA *data;
864 HANDLE16 handle;
865 HQUEUE16 hQueue = 0;
867 if ((id < WH_MINHOOK) || (id > WH_MAXHOOK)) return 0;
869 TRACE("Setting hook %d: %08x %04x %08lx\n",
870 id, (UINT)proc, hModule, dwThreadId );
872 /* Create task queue if none present */
873 GetFastQueue16();
875 if (id == WH_JOURNALPLAYBACK) EnableHardwareInput16(FALSE);
877 if (dwThreadId) /* Task-specific hook */
879 if ((id == WH_JOURNALRECORD) || (id == WH_JOURNALPLAYBACK) ||
880 (id == WH_SYSMSGFILTER)) return 0; /* System-only hooks */
881 if (!(hQueue = GetThreadQueue16( dwThreadId )))
882 return 0;
885 /* Create the hook structure */
887 if (!(handle = USER_HEAP_ALLOC( sizeof(HOOKDATA) ))) return 0;
888 data = (HOOKDATA *) USER_HEAP_LIN_ADDR( handle );
889 data->proc = proc;
890 data->id = id;
891 data->ownerQueue = hQueue;
892 data->ownerModule = hModule;
893 data->flags = type;
895 /* Create CallTo16 thunk for 16-bit hooks */
897 if ( (data->flags & HOOK_MAPTYPE) == HOOK_WIN16 )
898 data->thunk = (HOOKPROC)THUNK_Alloc( (FARPROC16)data->proc,
899 (RELAY)HOOK_CallTo16_long_wwl );
900 else
901 data->thunk = data->proc;
903 if ( !data->thunk && data->proc )
905 USER_HEAP_FREE( handle );
906 return 0;
909 /* Insert it in the correct linked list */
911 if (hQueue)
913 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue );
914 data->next = queue->hooks[id - WH_MINHOOK];
915 queue->hooks[id - WH_MINHOOK] = handle;
916 QUEUE_Unlock( queue );
918 else
920 data->next = HOOK_systemHooks[id - WH_MINHOOK];
921 HOOK_systemHooks[id - WH_MINHOOK] = handle;
923 TRACE("Setting hook %d: ret=%04x [next=%04x]\n",
924 id, handle, data->next );
926 return (HHOOK)( handle? MAKELONG( handle, HOOK_MAGIC ) : 0 );
930 /***********************************************************************
931 * HOOK_RemoveHook
933 * Remove a hook from the list.
935 static BOOL HOOK_RemoveHook( HANDLE16 hook )
937 HOOKDATA *data;
938 HANDLE16 *prevHook;
940 TRACE("Removing hook %04x\n", hook );
942 if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook))) return FALSE;
943 if (data->flags & HOOK_INUSE)
945 /* Mark it for deletion later on */
946 WARN("Hook still running, deletion delayed\n" );
947 data->proc = (HOOKPROC)0;
948 return TRUE;
951 if (data->id == WH_JOURNALPLAYBACK) EnableHardwareInput16(TRUE);
953 /* Remove it from the linked list */
955 if (data->ownerQueue)
957 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( data->ownerQueue );
958 if (!queue) return FALSE;
959 prevHook = &queue->hooks[data->id - WH_MINHOOK];
960 QUEUE_Unlock( queue );
962 else prevHook = &HOOK_systemHooks[data->id - WH_MINHOOK];
964 while (*prevHook && *prevHook != hook)
965 prevHook = &((HOOKDATA *)USER_HEAP_LIN_ADDR(*prevHook))->next;
967 if (!*prevHook) return FALSE;
968 *prevHook = data->next;
970 if ( (data->flags & HOOK_MAPTYPE) == HOOK_WIN16 )
971 THUNK_Free( (FARPROC)data->thunk );
973 USER_HEAP_FREE( hook );
974 return TRUE;
978 /***********************************************************************
979 * HOOK_FindValidHook
981 static HANDLE16 HOOK_FindValidHook( HANDLE16 hook )
983 HOOKDATA *data;
985 for (;;)
987 if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook))) return 0;
988 if (data->proc) return hook;
989 hook = data->next;
994 /***********************************************************************
995 * HOOK_CallHook
997 * Call a hook procedure.
999 static LRESULT HOOK_CallHook( HANDLE16 hook, INT fromtype, INT code,
1000 WPARAM wParam, LPARAM lParam )
1002 MESSAGEQUEUE *queue;
1003 HANDLE16 prevHook;
1004 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
1005 LRESULT ret;
1006 int iWndsLocks;
1008 WPARAM wParamOrig = wParam;
1009 LPARAM lParamOrig = lParam;
1010 HOOK_MapFunc MapFunc;
1011 HOOK_UnMapFunc UnMapFunc;
1013 MapFunc = HOOK_MapFuncs[fromtype][data->flags & HOOK_MAPTYPE];
1014 UnMapFunc = HOOK_UnMapFuncs[fromtype][data->flags & HOOK_MAPTYPE];
1016 if (MapFunc)
1017 MapFunc( data->id, code, &wParam, &lParam );
1019 /* Now call it */
1021 if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() ))) return 0;
1022 prevHook = queue->hCurHook;
1023 queue->hCurHook = hook;
1024 data->flags |= HOOK_INUSE;
1026 TRACE("Calling hook %04x: %d %08x %08lx\n",
1027 hook, code, wParam, lParam );
1029 /* Suspend window structure locks before calling user code */
1030 iWndsLocks = WIN_SuspendWndsLock();
1032 ret = data->thunk(code, wParam, lParam);
1034 /* Grrr. While the hook procedure is supposed to have an LRESULT return
1035 value even in Win16, it seems that for those hook types where the
1036 return value is interpreted as BOOL, Windows doesn't actually check
1037 the HIWORD ... Some buggy Win16 programs, notably WINFILE, rely on
1038 that, because they neglect to clear DX ... */
1039 if ( (data->flags & HOOK_MAPTYPE) == HOOK_WIN16
1040 && data->id != WH_JOURNALPLAYBACK )
1041 ret = LOWORD( ret );
1043 WIN_RestoreWndsLock(iWndsLocks);
1045 TRACE("Ret hook %04x = %08lx\n", hook, ret );
1047 data->flags &= ~HOOK_INUSE;
1048 queue->hCurHook = prevHook;
1050 QUEUE_Unlock( queue );
1052 if (UnMapFunc)
1053 UnMapFunc( data->id, code, wParamOrig, lParamOrig, wParam, lParam );
1055 if (!data->proc) HOOK_RemoveHook( hook );
1057 return ret;
1060 /***********************************************************************
1061 * Exported Functions & APIs
1064 /***********************************************************************
1065 * HOOK_IsHooked
1067 * Replacement for calling HOOK_GetHook from other modules.
1069 BOOL HOOK_IsHooked( INT16 id )
1071 /* Hmmm. Use GetThreadQueue(0) instead of GetFastQueue() here to
1072 avoid queue being created if someone wants to merely check ... */
1074 return HOOK_GetHook( id, GetThreadQueue16(0) ) != 0;
1078 /***********************************************************************
1079 * HOOK_CallHooks16
1081 * Call a hook chain.
1083 LRESULT HOOK_CallHooks16( INT16 id, INT16 code, WPARAM16 wParam,
1084 LPARAM lParam )
1086 HANDLE16 hook;
1088 if (!(hook = HOOK_GetHook( id, GetFastQueue16() ))) return 0;
1089 if (!(hook = HOOK_FindValidHook(hook))) return 0;
1090 return HOOK_CallHook( hook, HOOK_WIN16, code, wParam, lParam );
1093 /***********************************************************************
1094 * HOOK_CallHooksA
1096 * Call a hook chain.
1098 LRESULT HOOK_CallHooksA( INT id, INT code, WPARAM wParam,
1099 LPARAM lParam )
1101 HANDLE16 hook;
1103 if (!(hook = HOOK_GetHook( id, GetFastQueue16() ))) return 0;
1104 if (!(hook = HOOK_FindValidHook(hook))) return 0;
1105 return HOOK_CallHook( hook, HOOK_WIN32A, code, wParam, lParam );
1108 /***********************************************************************
1109 * HOOK_CallHooksW
1111 * Call a hook chain.
1113 LRESULT HOOK_CallHooksW( INT id, INT code, WPARAM wParam,
1114 LPARAM lParam )
1116 HANDLE16 hook;
1118 if (!(hook = HOOK_GetHook( id, GetFastQueue16() ))) return 0;
1119 if (!(hook = HOOK_FindValidHook(hook))) return 0;
1120 return HOOK_CallHook( hook, HOOK_WIN32W, code, wParam,
1121 lParam );
1125 /***********************************************************************
1126 * HOOK_ResetQueueHooks
1128 void HOOK_ResetQueueHooks( HQUEUE16 hQueue )
1130 MESSAGEQUEUE *queue;
1132 if ((queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue )) != NULL)
1134 HOOKDATA* data;
1135 HHOOK hook;
1136 int id;
1137 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
1139 hook = queue->hooks[id - WH_MINHOOK];
1140 while( hook )
1142 if( (data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook)) )
1144 data->ownerQueue = hQueue;
1145 hook = data->next;
1146 } else break;
1150 QUEUE_Unlock( queue );
1154 /***********************************************************************
1155 * HOOK_FreeModuleHooks
1157 void HOOK_FreeModuleHooks( HMODULE16 hModule )
1159 /* remove all system hooks registered by this module */
1161 HOOKDATA* hptr;
1162 HHOOK hook, next;
1163 int id;
1165 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
1167 hook = HOOK_systemHooks[id - WH_MINHOOK];
1168 while( hook )
1169 if( (hptr = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook)) )
1171 next = hptr->next;
1172 if( hptr->ownerModule == hModule )
1174 hptr->flags &= HOOK_MAPTYPE;
1175 HOOK_RemoveHook(hook);
1177 hook = next;
1179 else hook = 0;
1183 /***********************************************************************
1184 * HOOK_FreeQueueHooks
1186 void HOOK_FreeQueueHooks( HQUEUE16 hQueue )
1188 /* remove all hooks registered by this queue */
1190 HOOKDATA* hptr = NULL;
1191 HHOOK hook, next;
1192 int id;
1194 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
1196 hook = HOOK_GetHook( id, hQueue );
1197 while( hook )
1199 next = HOOK_GetNextHook(hook);
1201 hptr = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
1202 if( hptr && hptr->ownerQueue == hQueue )
1204 hptr->flags &= HOOK_MAPTYPE;
1205 HOOK_RemoveHook(hook);
1207 hook = next;
1213 /***********************************************************************
1214 * SetWindowsHook16 (USER.121)
1216 FARPROC16 WINAPI SetWindowsHook16( INT16 id, HOOKPROC16 proc )
1218 HINSTANCE16 hInst = FarGetOwner16( HIWORD(proc) );
1220 /* WH_MSGFILTER is the only task-specific hook for SetWindowsHook() */
1221 HTASK16 hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
1223 return (FARPROC16)SetWindowsHookEx16( id, proc, hInst, hTask );
1226 /***********************************************************************
1227 * SetWindowsHookA (USER32.525)
1229 HHOOK WINAPI SetWindowsHookA( INT id, HOOKPROC proc )
1231 return SetWindowsHookExA( id, proc, 0, GetCurrentThreadId() );
1234 /***********************************************************************
1235 * SetWindowsHookW (USER32.528)
1237 HHOOK WINAPI SetWindowsHookW( INT id, HOOKPROC proc )
1239 return SetWindowsHookExW( id, proc, 0, GetCurrentThreadId() );
1243 /***********************************************************************
1244 * SetWindowsHookEx16 (USER.291)
1246 HHOOK WINAPI SetWindowsHookEx16( INT16 id, HOOKPROC16 proc, HINSTANCE16 hInst,
1247 HTASK16 hTask )
1249 if (id == WH_DEBUG)
1251 FIXME("WH_DEBUG is broken in 16-bit Windows.\n");
1252 return 0;
1254 return HOOK_SetHook( id, proc, HOOK_WIN16, GetExePtr(hInst), (DWORD)hTask );
1257 /***********************************************************************
1258 * SetWindowsHookExA (USER32.526)
1260 HHOOK WINAPI SetWindowsHookExA( INT id, HOOKPROC proc, HINSTANCE hInst,
1261 DWORD dwThreadId )
1263 return HOOK_SetHook( id, proc, HOOK_WIN32A, MapHModuleLS(hInst), dwThreadId );
1266 /***********************************************************************
1267 * SetWindowsHookExW (USER32.527)
1269 HHOOK WINAPI SetWindowsHookExW( INT id, HOOKPROC proc, HINSTANCE hInst,
1270 DWORD dwThreadId )
1272 return HOOK_SetHook( id, proc, HOOK_WIN32W, MapHModuleLS(hInst), dwThreadId );
1276 /***********************************************************************
1277 * UnhookWindowsHook16 (USER.234)
1279 BOOL16 WINAPI UnhookWindowsHook16( INT16 id, HOOKPROC16 proc )
1281 return UnhookWindowsHook( id, (HOOKPROC)proc );
1284 /***********************************************************************
1285 * UnhookWindowsHook (USER32.557)
1287 BOOL WINAPI UnhookWindowsHook( INT id, HOOKPROC proc )
1289 HANDLE16 hook = HOOK_GetHook( id, GetFastQueue16() );
1291 TRACE("%d %08lx\n", id, (DWORD)proc );
1293 while (hook)
1295 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
1296 if (data->proc == proc) break;
1297 hook = HOOK_GetNextHook( hook );
1299 if (!hook) return FALSE;
1300 return HOOK_RemoveHook( hook );
1304 /***********************************************************************
1305 * UnhookWindowsHookEx16 (USER.292)
1307 BOOL16 WINAPI UnhookWindowsHookEx16( HHOOK hhook )
1309 return UnhookWindowsHookEx( hhook );
1312 /***********************************************************************
1313 * UnhookWindowsHookEx (USER32.558)
1315 BOOL WINAPI UnhookWindowsHookEx( HHOOK hhook )
1317 if (HIWORD(hhook) != HOOK_MAGIC) return FALSE; /* Not a new format hook */
1318 return HOOK_RemoveHook( LOWORD(hhook) );
1322 /***********************************************************************
1323 * CallNextHookEx16 (USER.293)
1325 * I wouldn't have separated this into 16 and 32 bit versions, but I
1326 * need a way to figure out if I need to do a mapping or not.
1328 LRESULT WINAPI CallNextHookEx16( HHOOK hhook, INT16 code, WPARAM16 wParam,
1329 LPARAM lParam )
1331 HANDLE16 next;
1333 if (HIWORD(hhook) != HOOK_MAGIC) return 0; /* Not a new format hook */
1334 if (!(next = HOOK_GetNextHook( LOWORD(hhook) ))) return 0;
1336 return HOOK_CallHook( next, HOOK_WIN16, code, wParam, lParam );
1340 /***********************************************************************
1341 * CallNextHookEx (USER32.17)
1343 * There aren't ANSI and UNICODE versions of this.
1345 LRESULT WINAPI CallNextHookEx( HHOOK hhook, INT code, WPARAM wParam,
1346 LPARAM lParam )
1348 HANDLE16 next;
1349 INT fromtype; /* figure out Ansi/Unicode */
1350 HOOKDATA *oldhook;
1352 if (HIWORD(hhook) != HOOK_MAGIC) return 0; /* Not a new format hook */
1353 if (!(next = HOOK_GetNextHook( LOWORD(hhook) ))) return 0;
1355 oldhook = (HOOKDATA *)USER_HEAP_LIN_ADDR( LOWORD(hhook) );
1356 fromtype = oldhook->flags & HOOK_MAPTYPE;
1358 if (fromtype == HOOK_WIN16)
1359 ERR("called from 16bit hook!\n");
1361 return HOOK_CallHook( next, fromtype, code, wParam, lParam );
1365 /***********************************************************************
1366 * DefHookProc16 (USER.235)
1368 LRESULT WINAPI DefHookProc16( INT16 code, WPARAM16 wParam, LPARAM lParam,
1369 HHOOK *hhook )
1371 /* Note: the *hhook parameter is never used, since we rely on the
1372 * current hook value from the task queue to find the next hook. */
1373 MESSAGEQUEUE *queue;
1374 LRESULT ret;
1376 if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() ))) return 0;
1377 ret = CallNextHookEx16( queue->hCurHook, code, wParam, lParam );
1378 QUEUE_Unlock( queue );
1379 return ret;
1383 /***********************************************************************
1384 * CallMsgFilter16 (USER.123)
1386 BOOL16 WINAPI CallMsgFilter16( SEGPTR msg, INT16 code )
1388 if (GetSysModalWindow16()) return FALSE;
1389 if (HOOK_CallHooks16( WH_SYSMSGFILTER, code, 0, (LPARAM)msg )) return TRUE;
1390 return HOOK_CallHooks16( WH_MSGFILTER, code, 0, (LPARAM)msg );
1394 /***********************************************************************
1395 * CallMsgFilter32 (USER.823)
1397 BOOL16 WINAPI CallMsgFilter32_16( SEGPTR msg16_32, INT16 code, BOOL16 wHaveParamHigh )
1399 MSG32_16 *lpmsg16_32 = (MSG32_16 *)PTR_SEG_TO_LIN(msg16_32);
1401 if (wHaveParamHigh == FALSE)
1403 lpmsg16_32->wParamHigh = 0;
1404 /* WARNING: msg16_32->msg has to be the first variable in the struct */
1405 return CallMsgFilter16(msg16_32, code);
1407 else
1409 MSG msg32;
1410 BOOL16 ret;
1412 msg32.hwnd = lpmsg16_32->msg.hwnd;
1413 msg32.message = lpmsg16_32->msg.message;
1414 msg32.wParam =
1415 MAKELONG(lpmsg16_32->msg.wParam, lpmsg16_32->wParamHigh);
1416 msg32.lParam = lpmsg16_32->msg.lParam;
1417 msg32.time = lpmsg16_32->msg.time;
1418 msg32.pt.x = (INT)lpmsg16_32->msg.pt.x;
1419 msg32.pt.y = (INT)lpmsg16_32->msg.pt.y;
1421 ret = (BOOL16)CallMsgFilterA(&msg32, (INT)code);
1423 lpmsg16_32->msg.hwnd = msg32.hwnd;
1424 lpmsg16_32->msg.message = msg32.message;
1425 lpmsg16_32->msg.wParam = LOWORD(msg32.wParam);
1426 lpmsg16_32->msg.lParam = msg32.lParam;
1427 lpmsg16_32->msg.time = msg32.time;
1428 lpmsg16_32->msg.pt.x = (INT16)msg32.pt.x;
1429 lpmsg16_32->msg.pt.y = (INT16)msg32.pt.y;
1430 lpmsg16_32->wParamHigh = HIWORD(msg32.wParam);
1432 return ret;
1437 /***********************************************************************
1438 * CallMsgFilterA (USER32.15)
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.16)
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 );