Don't check the checksum of the original echo request packet in the
[wine/dcerpc.git] / windows / hook.c
blobf9e8cabeae456e8a2c8b8831eeed4b0fc3095ffd
1 /*
2 * Windows hook functions
4 * Copyright 1994, 1995 Alexandre Julliard
5 * 1996 Andrew Lewycky
7 * Based on investigations by Alex Korobka
8 */
11 * Warning!
12 * A HHOOK is a 32-bit handle for compatibility with Windows 3.0 where it was
13 * a pointer to the next function. Now it is in fact composed of a USER heap
14 * handle in the low 16 bits and of a HOOK_MAGIC value in the high 16 bits.
17 #include "windef.h"
18 #include "winbase.h"
19 #include "wingdi.h"
20 #include "winuser.h"
21 #include "wine/winuser16.h"
22 #include "wine/winbase16.h"
23 #include "hook.h"
24 #include "win.h"
25 #include "queue.h"
26 #include "user.h"
27 #include "heap.h"
28 #include "struct32.h"
29 #include "winproc.h"
30 #include "debugtools.h"
32 DEFAULT_DEBUG_CHANNEL(hook);
34 #include "pshpack1.h"
36 /* Hook data (pointed to by a HHOOK) */
37 typedef struct
39 HANDLE16 next; /* 00 Next hook in chain */
40 HOOKPROC proc; /* 02 Hook procedure (original) */
41 INT16 id; /* 06 Hook id (WH_xxx) */
42 HQUEUE16 ownerQueue; /* 08 Owner queue (0 for system hook) */
43 HMODULE16 ownerModule; /* 0a Owner module */
44 WORD flags; /* 0c flags */
45 } HOOKDATA;
47 #include "poppack.h"
49 #define HOOK_MAGIC ((int)'H' | (int)'K' << 8) /* 'HK' */
51 /* This should probably reside in USER heap */
52 static HANDLE16 HOOK_systemHooks[WH_NB_HOOKS] = { 0, };
54 /* ### start build ### */
55 extern LONG CALLBACK HOOK_CallTo16_long_wwl(HOOKPROC16,WORD,WORD,LONG);
56 /* ### stop build ### */
59 /***********************************************************************
60 * call_hook_16
62 inline static LRESULT call_hook_16( HOOKPROC16 proc, INT id, INT code, WPARAM wparam, LPARAM lparam )
64 LRESULT ret = HOOK_CallTo16_long_wwl( proc, code, wparam, lparam );
65 /* Grrr. While the hook procedure is supposed to have an LRESULT return
66 value even in Win16, it seems that for those hook types where the
67 return value is interpreted as BOOL, Windows doesn't actually check
68 the HIWORD ... Some buggy Win16 programs, notably WINFILE, rely on
69 that, because they neglect to clear DX ... */
70 if (id != WH_JOURNALPLAYBACK) ret = LOWORD( ret );
71 return ret;
75 /***********************************************************************
76 * call_hook_16_to_32
78 * Convert hook params to 32-bit and call 32-bit hook procedure
80 static LRESULT call_hook_16_to_32( HOOKPROC proc, INT id, INT code, WPARAM wparam, LPARAM lparam,
81 BOOL unicode )
83 LRESULT ret = 0;
85 switch( id )
87 case WH_MSGFILTER:
88 case WH_SYSMSGFILTER:
89 case WH_JOURNALRECORD:
91 MSG16 *msg16 = MapSL(lparam);
92 MSG msg32;
94 STRUCT32_MSG16to32( msg16, &msg32 );
95 ret = proc( code, wparam, (LPARAM)&msg32 );
96 break;
99 case WH_GETMESSAGE:
101 MSG16 *msg16 = MapSL(lparam);
102 MSG msg32;
104 STRUCT32_MSG16to32( msg16, &msg32 );
105 ret = proc( code, wparam, (LPARAM)&msg32 );
106 STRUCT32_MSG32to16( &msg32, msg16 );
107 break;
110 case WH_JOURNALPLAYBACK:
112 EVENTMSG16 *em16 = MapSL(lparam);
113 EVENTMSG em32;
115 em32.message = em16->message;
116 em32.paramL = em16->paramL;
117 em32.paramH = em16->paramH;
118 em32.time = em16->time;
119 em32.hwnd = 0; /* FIXME */
120 ret = proc( code, wparam, (LPARAM)&em32 );
121 break;
124 case WH_CALLWNDPROC:
126 CWPSTRUCT16 *cwp16 = MapSL(lparam);
127 CWPSTRUCT cwp32;
129 cwp32.hwnd = WIN_Handle32(cwp16->hwnd);
130 cwp32.lParam = cwp16->lParam;
132 if (unicode)
133 WINPROC_MapMsg16To32W( cwp32.hwnd, cwp16->message, cwp16->wParam,
134 &cwp32.message, &cwp32.wParam, &cwp32.lParam );
135 else
136 WINPROC_MapMsg16To32A( cwp32.hwnd, cwp16->message, cwp16->wParam,
137 &cwp32.message, &cwp32.wParam, &cwp32.lParam );
139 ret = proc( code, wparam, (LPARAM)&cwp32 );
141 if (unicode)
142 WINPROC_UnmapMsg16To32W( cwp32.hwnd, cwp32.message, cwp32.wParam, cwp32.lParam, 0 );
143 else
144 WINPROC_UnmapMsg16To32A( cwp32.hwnd, cwp32.message, cwp32.wParam, cwp32.lParam, 0 );
145 break;
148 case WH_CBT:
149 switch (code)
151 case HCBT_CREATEWND:
153 CBT_CREATEWNDA cbtcw32;
154 CREATESTRUCTA cs32;
155 CBT_CREATEWND16 *cbtcw16 = MapSL(lparam);
156 CREATESTRUCT16 *cs16 = MapSL( (SEGPTR)cbtcw16->lpcs );
158 cbtcw32.lpcs = &cs32;
159 cbtcw32.hwndInsertAfter = WIN_Handle32( cbtcw16->hwndInsertAfter );
160 STRUCT32_CREATESTRUCT16to32A( cs16, &cs32 );
162 if (unicode)
164 cs32.lpszName = (LPSTR)map_str_16_to_32W( cs16->lpszName );
165 cs32.lpszClass = (LPSTR)map_str_16_to_32W( cs16->lpszClass );
166 ret = proc( code, wparam, (LPARAM)&cbtcw32 );
167 unmap_str_16_to_32W( (LPWSTR)cs32.lpszName );
168 unmap_str_16_to_32W( (LPWSTR)cs32.lpszClass );
170 else
172 cs32.lpszName = MapSL( cs16->lpszName );
173 cs32.lpszClass = MapSL( cs16->lpszClass );
174 ret = proc( code, wparam, (LPARAM)&cbtcw32 );
176 cbtcw16->hwndInsertAfter = WIN_Handle16( cbtcw32.hwndInsertAfter );
177 break;
179 case HCBT_ACTIVATE:
181 CBTACTIVATESTRUCT16 *cas16 = MapSL(lparam);
182 CBTACTIVATESTRUCT cas32;
183 cas32.fMouse = cas16->fMouse;
184 cas32.hWndActive = WIN_Handle32(cas16->hWndActive);
185 ret = proc( code, wparam, (LPARAM)&cas32 );
186 break;
188 case HCBT_CLICKSKIPPED:
190 MOUSEHOOKSTRUCT16 *ms16 = MapSL(lparam);
191 MOUSEHOOKSTRUCT ms32;
193 ms32.pt.x = ms16->pt.x;
194 ms32.pt.y = ms16->pt.y;
195 /* wHitTestCode may be negative, so convince compiler to do
196 correct sign extension. Yay. :| */
197 ms32.wHitTestCode = (INT)(INT16)ms16->wHitTestCode;
198 ms32.dwExtraInfo = ms16->dwExtraInfo;
199 ms32.hwnd = WIN_Handle32( ms16->hwnd );
200 ret = proc( code, wparam, (LPARAM)&ms32 );
201 break;
203 case HCBT_MOVESIZE:
205 RECT16 *rect16 = MapSL(lparam);
206 RECT rect32;
208 CONV_RECT16TO32( rect16, &rect32 );
209 ret = proc( code, wparam, (LPARAM)&rect32 );
210 break;
213 break;
215 case WH_MOUSE:
217 MOUSEHOOKSTRUCT16 *ms16 = MapSL(lparam);
218 MOUSEHOOKSTRUCT ms32;
220 ms32.pt.x = ms16->pt.x;
221 ms32.pt.y = ms16->pt.y;
222 /* wHitTestCode may be negative, so convince compiler to do
223 correct sign extension. Yay. :| */
224 ms32.wHitTestCode = (INT)((INT16)ms16->wHitTestCode);
225 ms32.dwExtraInfo = ms16->dwExtraInfo;
226 ms32.hwnd = WIN_Handle32(ms16->hwnd);
227 ret = proc( code, wparam, (LPARAM)&ms32 );
228 break;
231 case WH_DEBUG:
233 DEBUGHOOKINFO16 *dh16 = MapSL(lparam);
234 DEBUGHOOKINFO dh32;
236 dh32.idThread = 0; /* FIXME */
237 dh32.idThreadInstaller = 0; /* FIXME */
238 dh32.lParam = dh16->lParam; /* FIXME Check for sign ext */
239 dh32.wParam = dh16->wParam;
240 dh32.code = dh16->code;
242 /* do sign extension if it was WH_MSGFILTER */
243 if (wparam == 0xffff) wparam = WH_MSGFILTER;
244 ret = proc( code, wparam, (LPARAM)&dh32 );
245 break;
248 case WH_SHELL:
249 case WH_KEYBOARD:
250 ret = proc( code, wparam, lparam );
251 break;
253 case WH_HARDWARE:
254 case WH_FOREGROUNDIDLE:
255 case WH_CALLWNDPROCRET:
256 default:
257 FIXME("\t[%i] 16to32 translation unimplemented\n", id);
258 ret = proc( code, wparam, lparam );
259 break;
261 return ret;
265 /***********************************************************************
266 * call_hook_32_to_16
268 * Convert hook params to 16-bit and call 16-bit hook procedure
270 static LRESULT call_hook_32_to_16( HOOKPROC16 proc, INT id, INT code, WPARAM wparam, LPARAM lparam,
271 BOOL unicode )
273 LRESULT ret = 0;
275 switch (id)
277 case WH_MSGFILTER:
278 case WH_SYSMSGFILTER:
279 case WH_JOURNALRECORD:
281 MSG *msg32 = (MSG *)lparam;
282 MSG16 msg16;
284 STRUCT32_MSG32to16( msg32, &msg16 );
285 lparam = MapLS( &msg16 );
286 ret = call_hook_16( proc, id, code, wparam, lparam );
287 UnMapLS( lparam );
288 break;
291 case WH_GETMESSAGE:
293 MSG *msg32 = (MSG *)lparam;
294 MSG16 msg16;
296 STRUCT32_MSG32to16( msg32, &msg16 );
297 lparam = MapLS( &msg16 );
298 ret = call_hook_16( proc, id, code, wparam, lparam );
299 UnMapLS( lparam );
300 STRUCT32_MSG16to32( &msg16, msg32 );
301 break;
304 case WH_JOURNALPLAYBACK:
306 EVENTMSG *em32 = (EVENTMSG *)lparam;
307 EVENTMSG16 em16;
309 em16.message = em32->message;
310 em16.paramL = em32->paramL;
311 em16.paramH = em32->paramH;
312 em16.time = em32->time;
313 lparam = MapLS( &em16 );
314 ret = call_hook_16( proc, id, code, wparam, lparam );
315 UnMapLS( lparam );
316 break;
319 case WH_CALLWNDPROC:
321 CWPSTRUCT *cwp32 = (CWPSTRUCT *)lparam;
322 CWPSTRUCT16 cwp16;
323 MSGPARAM16 mp16;
325 cwp16.hwnd = WIN_Handle16(cwp32->hwnd);
326 cwp16.lParam = cwp32->lParam;
328 if (unicode)
329 WINPROC_MapMsg32WTo16( cwp32->hwnd, cwp32->message, cwp32->wParam,
330 &cwp16.message, &cwp16.wParam, &cwp16.lParam );
331 else
332 WINPROC_MapMsg32ATo16( cwp32->hwnd, cwp32->message, cwp32->wParam,
333 &cwp16.message, &cwp16.wParam, &cwp16.lParam );
335 lparam = MapLS( &cwp16 );
336 ret = call_hook_16( proc, id, code, wparam, lparam );
337 UnMapLS( lparam );
339 mp16.wParam = cwp16.wParam;
340 mp16.lParam = cwp16.lParam;
341 mp16.lResult = 0;
342 if (unicode)
343 WINPROC_UnmapMsg32WTo16( cwp32->hwnd, cwp32->message, cwp32->wParam,
344 cwp32->lParam, &mp16 );
345 else
346 WINPROC_UnmapMsg32ATo16( cwp32->hwnd, cwp32->message, cwp32->wParam,
347 cwp32->lParam, &mp16 );
348 break;
351 case WH_CBT:
352 switch (code)
354 case HCBT_CREATEWND:
356 CBT_CREATEWNDA *cbtcw32 = (CBT_CREATEWNDA *)lparam;
357 CBT_CREATEWND16 cbtcw16;
358 CREATESTRUCT16 cs16;
360 STRUCT32_CREATESTRUCT32Ato16( cbtcw32->lpcs, &cs16 );
361 cbtcw16.lpcs = (CREATESTRUCT16 *)MapLS( &cs16 );
362 cbtcw16.hwndInsertAfter = WIN_Handle16( cbtcw32->hwndInsertAfter );
363 lparam = MapLS( &cbtcw16 );
365 if (unicode)
367 cs16.lpszName = map_str_32W_to_16( (LPWSTR)cbtcw32->lpcs->lpszName );
368 cs16.lpszClass = map_str_32W_to_16( (LPWSTR)cbtcw32->lpcs->lpszClass );
369 ret = call_hook_16( proc, id, code, wparam, lparam );
370 unmap_str_32W_to_16( cs16.lpszName );
371 unmap_str_32W_to_16( cs16.lpszClass );
373 else
375 cs16.lpszName = MapLS( cbtcw32->lpcs->lpszName );
376 cs16.lpszClass = MapLS( cbtcw32->lpcs->lpszClass );
377 ret = call_hook_16( proc, id, code, wparam, lparam );
378 UnMapLS( cs16.lpszName );
379 UnMapLS( cs16.lpszClass );
381 cbtcw32->hwndInsertAfter = WIN_Handle32( cbtcw16.hwndInsertAfter );
382 UnMapLS( (SEGPTR)cbtcw16.lpcs );
383 UnMapLS( lparam );
384 break;
387 case HCBT_ACTIVATE:
389 CBTACTIVATESTRUCT *cas32 = (CBTACTIVATESTRUCT *)lparam;
390 CBTACTIVATESTRUCT16 cas16;
392 cas16.fMouse = cas32->fMouse;
393 cas16.hWndActive = WIN_Handle16( cas32->hWndActive );
395 lparam = MapLS( &cas16 );
396 ret = call_hook_16( proc, id, code, wparam, lparam );
397 UnMapLS( lparam );
398 break;
400 case HCBT_CLICKSKIPPED:
402 MOUSEHOOKSTRUCT *ms32 = (MOUSEHOOKSTRUCT *)lparam;
403 MOUSEHOOKSTRUCT16 ms16;
405 ms16.pt.x = ms32->pt.x;
406 ms16.pt.y = ms32->pt.y;
407 ms16.hwnd = WIN_Handle16( ms32->hwnd );
408 ms16.wHitTestCode = ms32->wHitTestCode;
409 ms16.dwExtraInfo = ms32->dwExtraInfo;
411 lparam = MapLS( &ms16 );
412 ret = call_hook_16( proc, id, code, wparam, lparam );
413 UnMapLS( lparam );
414 break;
416 case HCBT_MOVESIZE:
418 RECT *rect32 = (RECT *)lparam;
419 RECT16 rect16;
421 CONV_RECT32TO16( rect32, &rect16 );
422 lparam = MapLS( &rect16 );
423 ret = call_hook_16( proc, id, code, wparam, lparam );
424 UnMapLS( lparam );
425 break;
428 break;
430 case WH_MOUSE:
432 MOUSEHOOKSTRUCT *ms32 = (MOUSEHOOKSTRUCT *)lparam;
433 MOUSEHOOKSTRUCT16 ms16;
435 ms16.pt.x = ms32->pt.x;
436 ms16.pt.y = ms32->pt.y;
437 ms16.hwnd = WIN_Handle16( ms32->hwnd );
438 ms16.wHitTestCode = ms32->wHitTestCode;
439 ms16.dwExtraInfo = ms32->dwExtraInfo;
441 lparam = MapLS( &ms16 );
442 ret = call_hook_16( proc, id, code, wparam, lparam );
443 UnMapLS( lparam );
444 break;
447 case WH_DEBUG:
449 DEBUGHOOKINFO *dh32 = (DEBUGHOOKINFO *)lparam;
450 DEBUGHOOKINFO16 dh16;
452 dh16.hModuleHook = 0; /* FIXME */
453 dh16.reserved = 0;
454 dh16.lParam = dh32->lParam;
455 dh16.wParam = dh32->wParam;
456 dh16.code = dh32->code;
458 lparam = MapLS( &dh16 );
459 ret = call_hook_16( proc, id, code, wparam, lparam );
460 UnMapLS( lparam );
461 break;
464 case WH_SHELL:
465 case WH_KEYBOARD:
466 ret = call_hook_16( proc, id, code, wparam, lparam );
467 break;
469 case WH_HARDWARE:
470 case WH_FOREGROUNDIDLE:
471 case WH_CALLWNDPROCRET:
472 default:
473 FIXME("\t[%i] 32to16 translation unimplemented\n", id);
474 ret = call_hook_16( proc, id, code, wparam, lparam );
475 break;
477 return ret;
481 /***********************************************************************
482 * call_hook_32_to_32
484 * Convert hook params to/from Unicode and call hook procedure
486 static LRESULT call_hook_32_to_32( HOOKPROC proc, INT id, INT code, WPARAM wparam, LPARAM lparam,
487 BOOL to_unicode )
489 if (id != WH_CBT || code != HCBT_CREATEWND) return proc( code, wparam, lparam );
491 if (to_unicode) /* ASCII to Unicode */
493 CBT_CREATEWNDA *cbtcwA = (CBT_CREATEWNDA *)lparam;
494 CBT_CREATEWNDW cbtcwW;
495 CREATESTRUCTW csW;
496 LRESULT ret;
498 cbtcwW.lpcs = &csW;
499 cbtcwW.hwndInsertAfter = cbtcwA->hwndInsertAfter;
500 csW = *(CREATESTRUCTW *)cbtcwA->lpcs;
502 if (HIWORD(cbtcwA->lpcs->lpszName))
503 csW.lpszName = HEAP_strdupAtoW( GetProcessHeap(), 0, cbtcwA->lpcs->lpszName );
504 if (HIWORD(cbtcwA->lpcs->lpszClass))
505 csW.lpszClass = HEAP_strdupAtoW( GetProcessHeap(), 0, cbtcwA->lpcs->lpszClass );
506 ret = proc( code, wparam, (LPARAM)&cbtcwW );
507 cbtcwA->hwndInsertAfter = cbtcwW.hwndInsertAfter;
508 if (HIWORD(csW.lpszName)) HeapFree( GetProcessHeap(), 0, (LPWSTR)csW.lpszName );
509 if (HIWORD(csW.lpszClass)) HeapFree( GetProcessHeap(), 0, (LPWSTR)csW.lpszClass );
510 return ret;
512 else /* Unicode to ASCII */
514 CBT_CREATEWNDW *cbtcwW = (CBT_CREATEWNDW *)lparam;
515 CBT_CREATEWNDA cbtcwA;
516 CREATESTRUCTA csA;
517 LRESULT ret;
519 cbtcwA.lpcs = &csA;
520 cbtcwA.hwndInsertAfter = cbtcwW->hwndInsertAfter;
521 csA = *(CREATESTRUCTA *)cbtcwW->lpcs;
523 if (HIWORD(cbtcwW->lpcs->lpszName))
524 csA.lpszName = HEAP_strdupWtoA( GetProcessHeap(), 0, cbtcwW->lpcs->lpszName );
525 if (HIWORD(cbtcwW->lpcs->lpszClass))
526 csA.lpszClass = HEAP_strdupWtoA( GetProcessHeap(), 0, cbtcwW->lpcs->lpszClass );
527 ret = proc( code, wparam, (LPARAM)&cbtcwA );
528 cbtcwW->hwndInsertAfter = cbtcwA.hwndInsertAfter;
529 if (HIWORD(csA.lpszName)) HeapFree( GetProcessHeap(), 0, (LPSTR)csA.lpszName );
530 if (HIWORD(csA.lpszClass)) HeapFree( GetProcessHeap(), 0, (LPSTR)csA.lpszClass );
531 return ret;
536 /***********************************************************************
537 * call_hook
539 * Call a hook procedure.
541 inline static LRESULT call_hook( HOOKDATA *data, INT fromtype, INT code,
542 WPARAM wparam, LPARAM lparam )
544 INT type = (data->flags & HOOK_MAPTYPE);
545 LRESULT ret;
547 /* Suspend window structure locks before calling user code */
548 int iWndsLocks = WIN_SuspendWndsLock();
550 if (type == HOOK_WIN16)
552 if (fromtype == HOOK_WIN16) /* 16->16 */
553 ret = call_hook_16( (HOOKPROC16)data->proc, data->id, code, wparam, lparam );
554 else /* 32->16 */
555 ret = call_hook_32_to_16( (HOOKPROC16)data->proc, data->id, code, wparam,
556 lparam, (type == HOOK_WIN32W) );
558 else if (fromtype == HOOK_WIN16) /* 16->32 */
559 ret = call_hook_16_to_32( data->proc, data->id, code, wparam,
560 lparam, (type == HOOK_WIN32W) );
561 else /* 32->32, check unicode */
563 if (type == fromtype)
564 ret = data->proc( code, wparam, lparam );
565 else
566 ret = call_hook_32_to_32( data->proc, data->id, code, wparam,
567 lparam, (type == HOOK_WIN32W) );
569 WIN_RestoreWndsLock(iWndsLocks);
570 return ret;
574 /***********************************************************************
575 * HOOK_GetNextHook
577 * Get the next hook of a given hook.
579 static HANDLE16 HOOK_GetNextHook( HANDLE16 hook )
581 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR( hook );
583 if (!data || !hook) return 0;
584 if (data->next) return data->next;
585 if (!data->ownerQueue) return 0; /* Already system hook */
587 /* Now start enumerating the system hooks */
588 return HOOK_systemHooks[data->id - WH_MINHOOK];
592 /***********************************************************************
593 * HOOK_GetHook
595 * Get the first hook for a given type.
597 static HANDLE16 HOOK_GetHook( INT16 id )
599 MESSAGEQUEUE *queue;
600 HANDLE16 hook = 0;
602 if ((queue = QUEUE_Current()) != NULL)
603 hook = queue->hooks[id - WH_MINHOOK];
604 if (!hook) hook = HOOK_systemHooks[id - WH_MINHOOK];
605 return hook;
609 /***********************************************************************
610 * HOOK_SetHook
612 * Install a given hook.
614 static HHOOK HOOK_SetHook( INT16 id, LPVOID proc, INT type,
615 HMODULE16 hModule, DWORD dwThreadId )
617 HOOKDATA *data;
618 HANDLE16 handle;
619 HQUEUE16 hQueue = 0;
621 if ((id < WH_MINHOOK) || (id > WH_MAXHOOK)) return 0;
623 TRACE("Setting hook %d: %08x %04x %08lx\n",
624 id, (UINT)proc, hModule, dwThreadId );
626 /* Create task queue if none present */
627 InitThreadInput16( 0, 0 );
629 if (id == WH_JOURNALPLAYBACK) EnableHardwareInput16(FALSE);
631 if (dwThreadId) /* Task-specific hook */
633 if ((id == WH_JOURNALRECORD) || (id == WH_JOURNALPLAYBACK) ||
634 (id == WH_SYSMSGFILTER)) return 0; /* System-only hooks */
635 if (!(hQueue = GetThreadQueue16( dwThreadId )))
636 return 0;
639 /* Create the hook structure */
641 if (!(handle = USER_HEAP_ALLOC( sizeof(HOOKDATA) ))) return 0;
642 data = (HOOKDATA *) USER_HEAP_LIN_ADDR( handle );
643 data->proc = proc;
644 data->id = id;
645 data->ownerQueue = hQueue;
646 data->ownerModule = hModule;
647 data->flags = type;
649 /* Insert it in the correct linked list */
651 if (hQueue)
653 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue );
654 data->next = queue->hooks[id - WH_MINHOOK];
655 queue->hooks[id - WH_MINHOOK] = handle;
656 QUEUE_Unlock( queue );
658 else
660 data->next = HOOK_systemHooks[id - WH_MINHOOK];
661 HOOK_systemHooks[id - WH_MINHOOK] = handle;
663 TRACE("Setting hook %d: ret=%04x [next=%04x]\n",
664 id, handle, data->next );
666 return (HHOOK)( handle? MAKELONG( handle, HOOK_MAGIC ) : 0 );
670 /***********************************************************************
671 * HOOK_RemoveHook
673 * Remove a hook from the list.
675 static BOOL HOOK_RemoveHook( HANDLE16 hook )
677 HOOKDATA *data;
678 HANDLE16 *prevHook;
680 TRACE("Removing hook %04x\n", hook );
682 if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook))) return FALSE;
683 if (data->flags & HOOK_INUSE)
685 /* Mark it for deletion later on */
686 WARN("Hook still running, deletion delayed\n" );
687 data->proc = (HOOKPROC)0;
688 return TRUE;
691 if (data->id == WH_JOURNALPLAYBACK) EnableHardwareInput16(TRUE);
693 /* Remove it from the linked list */
695 if (data->ownerQueue)
697 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( data->ownerQueue );
698 if (!queue) return FALSE;
699 prevHook = &queue->hooks[data->id - WH_MINHOOK];
700 QUEUE_Unlock( queue );
702 else prevHook = &HOOK_systemHooks[data->id - WH_MINHOOK];
704 while (*prevHook && *prevHook != hook)
705 prevHook = &((HOOKDATA *)USER_HEAP_LIN_ADDR(*prevHook))->next;
707 if (!*prevHook) return FALSE;
708 *prevHook = data->next;
710 USER_HEAP_FREE( hook );
711 return TRUE;
715 /***********************************************************************
716 * HOOK_FindValidHook
718 static HANDLE16 HOOK_FindValidHook( HANDLE16 hook )
720 HOOKDATA *data;
722 for (;;)
724 if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook))) return 0;
725 if (data->proc) return hook;
726 hook = data->next;
730 /***********************************************************************
731 * HOOK_CallHook
733 * Call a hook procedure.
735 static LRESULT HOOK_CallHook( HANDLE16 hook, INT fromtype, INT code,
736 WPARAM wParam, LPARAM lParam )
738 MESSAGEQUEUE *queue;
739 HANDLE16 prevHook;
740 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
741 LRESULT ret;
743 if (!(queue = QUEUE_Current())) return 0;
744 prevHook = queue->hCurHook;
745 queue->hCurHook = hook;
747 TRACE("Calling hook %04x: %d %08x %08lx\n", hook, code, wParam, lParam );
749 data->flags |= HOOK_INUSE;
750 ret = call_hook( data, fromtype, code, wParam, lParam );
751 data->flags &= ~HOOK_INUSE;
753 TRACE("Ret hook %04x = %08lx\n", hook, ret );
755 queue->hCurHook = prevHook;
756 if (!data->proc) HOOK_RemoveHook( hook );
757 return ret;
760 /***********************************************************************
761 * Exported Functions & APIs
764 /***********************************************************************
765 * HOOK_IsHooked
767 * Replacement for calling HOOK_GetHook from other modules.
769 BOOL HOOK_IsHooked( INT16 id )
771 return HOOK_GetHook( id ) != 0;
775 /***********************************************************************
776 * HOOK_CallHooks16
778 * Call a hook chain.
780 LRESULT HOOK_CallHooks16( INT16 id, INT16 code, WPARAM16 wParam,
781 LPARAM lParam )
783 HANDLE16 hook;
785 if (!(hook = HOOK_GetHook( id ))) return 0;
786 if (!(hook = HOOK_FindValidHook(hook))) return 0;
787 return HOOK_CallHook( hook, HOOK_WIN16, code, wParam, lParam );
790 /***********************************************************************
791 * HOOK_CallHooksA
793 * Call a hook chain.
795 LRESULT HOOK_CallHooksA( INT id, INT code, WPARAM wParam,
796 LPARAM lParam )
798 HANDLE16 hook;
800 if (!(hook = HOOK_GetHook( id ))) return 0;
801 if (!(hook = HOOK_FindValidHook(hook))) return 0;
802 return HOOK_CallHook( hook, HOOK_WIN32A, code, wParam, lParam );
805 /***********************************************************************
806 * HOOK_CallHooksW
808 * Call a hook chain.
810 LRESULT HOOK_CallHooksW( INT id, INT code, WPARAM wParam,
811 LPARAM lParam )
813 HANDLE16 hook;
815 if (!(hook = HOOK_GetHook( id ))) return 0;
816 if (!(hook = HOOK_FindValidHook(hook))) return 0;
817 return HOOK_CallHook( hook, HOOK_WIN32W, code, wParam,
818 lParam );
822 /***********************************************************************
823 * HOOK_FreeModuleHooks
825 void HOOK_FreeModuleHooks( HMODULE16 hModule )
827 /* remove all system hooks registered by this module */
829 HOOKDATA* hptr;
830 HHOOK hook, next;
831 int id;
833 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
835 hook = HOOK_systemHooks[id - WH_MINHOOK];
836 while( hook )
837 if( (hptr = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook)) )
839 next = hptr->next;
840 if( hptr->ownerModule == hModule )
842 hptr->flags &= HOOK_MAPTYPE;
843 HOOK_RemoveHook(hook);
845 hook = next;
847 else hook = 0;
851 /***********************************************************************
852 * HOOK_FreeQueueHooks
854 void HOOK_FreeQueueHooks(void)
856 /* remove all hooks registered by the current queue */
858 HOOKDATA* hptr = NULL;
859 HHOOK hook, next;
860 int id;
862 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
864 hook = HOOK_GetHook( id );
865 while( hook )
867 next = HOOK_GetNextHook(hook);
869 hptr = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
870 if( hptr && hptr->ownerQueue )
872 hptr->flags &= HOOK_MAPTYPE;
873 HOOK_RemoveHook(hook);
875 hook = next;
881 /***********************************************************************
882 * SetWindowsHook (USER.121)
884 FARPROC16 WINAPI SetWindowsHook16( INT16 id, HOOKPROC16 proc )
886 HINSTANCE16 hInst = FarGetOwner16( HIWORD(proc) );
888 /* WH_MSGFILTER is the only task-specific hook for SetWindowsHook() */
889 HTASK16 hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
891 return (FARPROC16)SetWindowsHookEx16( id, proc, hInst, hTask );
894 /***********************************************************************
895 * SetWindowsHookA (USER32.@)
897 HHOOK WINAPI SetWindowsHookA( INT id, HOOKPROC proc )
899 return SetWindowsHookExA( id, proc, 0, GetCurrentThreadId() );
902 /***********************************************************************
903 * SetWindowsHookW (USER32.@)
905 HHOOK WINAPI SetWindowsHookW( INT id, HOOKPROC proc )
907 return SetWindowsHookExW( id, proc, 0, GetCurrentThreadId() );
911 /***********************************************************************
912 * SetWindowsHookEx (USER.291)
913 * SetWindowsHookEx16 (USER32.@)
915 HHOOK WINAPI SetWindowsHookEx16( INT16 id, HOOKPROC16 proc, HINSTANCE16 hInst,
916 HTASK16 hTask )
918 if (id == WH_DEBUG)
920 FIXME("WH_DEBUG is broken in 16-bit Windows.\n");
921 return 0;
923 return HOOK_SetHook( id, proc, HOOK_WIN16, GetExePtr(hInst), (DWORD)hTask );
926 /***********************************************************************
927 * SetWindowsHookExA (USER32.@)
929 HHOOK WINAPI SetWindowsHookExA( INT id, HOOKPROC proc, HINSTANCE hInst,
930 DWORD dwThreadId )
932 return HOOK_SetHook( id, proc, HOOK_WIN32A, MapHModuleLS(hInst), dwThreadId );
935 /***********************************************************************
936 * SetWindowsHookExW (USER32.@)
938 HHOOK WINAPI SetWindowsHookExW( INT id, HOOKPROC proc, HINSTANCE hInst,
939 DWORD dwThreadId )
941 return HOOK_SetHook( id, proc, HOOK_WIN32W, MapHModuleLS(hInst), dwThreadId );
945 /***********************************************************************
946 * UnhookWindowsHook (USER.234)
948 BOOL16 WINAPI UnhookWindowsHook16( INT16 id, HOOKPROC16 proc )
950 return UnhookWindowsHook( id, (HOOKPROC)proc );
953 /***********************************************************************
954 * UnhookWindowsHook (USER32.@)
956 BOOL WINAPI UnhookWindowsHook( INT id, HOOKPROC proc )
958 HANDLE16 hook = HOOK_GetHook( id );
960 TRACE("%d %08lx\n", id, (DWORD)proc );
962 while (hook)
964 HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
965 if (data->proc == proc) break;
966 hook = HOOK_GetNextHook( hook );
968 if (!hook) return FALSE;
969 return HOOK_RemoveHook( hook );
973 /***********************************************************************
974 * UnhookWindowsHookEx (USER.292)
976 BOOL16 WINAPI UnhookWindowsHookEx16( HHOOK hhook )
978 return UnhookWindowsHookEx( hhook );
981 /***********************************************************************
982 * UnhookWindowsHookEx (USER32.@)
984 BOOL WINAPI UnhookWindowsHookEx( HHOOK hhook )
986 if (HIWORD(hhook) != HOOK_MAGIC) return FALSE; /* Not a new format hook */
987 return HOOK_RemoveHook( LOWORD(hhook) );
991 /***********************************************************************
992 * CallNextHookEx (USER.293)
993 * CallNextHookEx16 (USER32.@)
995 * I wouldn't have separated this into 16 and 32 bit versions, but I
996 * need a way to figure out if I need to do a mapping or not.
998 LRESULT WINAPI CallNextHookEx16( HHOOK hhook, INT16 code, WPARAM16 wParam,
999 LPARAM lParam )
1001 HANDLE16 next;
1003 if (HIWORD(hhook) != HOOK_MAGIC) return 0; /* Not a new format hook */
1004 if (!(next = HOOK_GetNextHook( LOWORD(hhook) ))) return 0;
1006 return HOOK_CallHook( next, HOOK_WIN16, code, wParam, lParam );
1010 /***********************************************************************
1011 * CallNextHookEx (USER32.@)
1013 * There aren't ANSI and UNICODE versions of this.
1015 LRESULT WINAPI CallNextHookEx( HHOOK hhook, INT code, WPARAM wParam,
1016 LPARAM lParam )
1018 HANDLE16 next;
1019 INT fromtype; /* figure out Ansi/Unicode */
1020 HOOKDATA *oldhook;
1022 if (HIWORD(hhook) != HOOK_MAGIC) return 0; /* Not a new format hook */
1023 if (!(next = HOOK_GetNextHook( LOWORD(hhook) ))) return 0;
1025 oldhook = (HOOKDATA *)USER_HEAP_LIN_ADDR( LOWORD(hhook) );
1026 fromtype = oldhook->flags & HOOK_MAPTYPE;
1028 if (fromtype == HOOK_WIN16)
1029 ERR("called from 16bit hook!\n");
1031 return HOOK_CallHook( next, fromtype, code, wParam, lParam );
1035 /***********************************************************************
1036 * DefHookProc (USER.235)
1038 LRESULT WINAPI DefHookProc16( INT16 code, WPARAM16 wParam, LPARAM lParam,
1039 HHOOK *hhook )
1041 /* Note: the *hhook parameter is never used, since we rely on the
1042 * current hook value from the task queue to find the next hook. */
1043 MESSAGEQUEUE *queue;
1045 if (!(queue = QUEUE_Current())) return 0;
1046 return CallNextHookEx16( queue->hCurHook, code, wParam, lParam );
1050 /***********************************************************************
1051 * CallMsgFilter (USER.123)
1053 BOOL16 WINAPI CallMsgFilter16( SEGPTR msg, INT16 code )
1055 if (GetSysModalWindow16()) return FALSE;
1056 if (HOOK_CallHooks16( WH_SYSMSGFILTER, code, 0, (LPARAM)msg )) return TRUE;
1057 return HOOK_CallHooks16( WH_MSGFILTER, code, 0, (LPARAM)msg );
1061 /***********************************************************************
1062 * CallMsgFilter32 (USER.823)
1064 BOOL16 WINAPI CallMsgFilter32_16( SEGPTR msg16_32, INT16 code, BOOL16 wHaveParamHigh )
1066 MSG32_16 *lpmsg16_32 = MapSL(msg16_32);
1068 if (wHaveParamHigh == FALSE)
1070 lpmsg16_32->wParamHigh = 0;
1071 /* WARNING: msg16_32->msg has to be the first variable in the struct */
1072 return CallMsgFilter16(msg16_32, code);
1074 else
1076 MSG msg32;
1077 BOOL16 ret;
1079 msg32.hwnd = WIN_Handle32( lpmsg16_32->msg.hwnd );
1080 msg32.message = lpmsg16_32->msg.message;
1081 msg32.wParam = MAKELONG(lpmsg16_32->msg.wParam, lpmsg16_32->wParamHigh);
1082 msg32.lParam = lpmsg16_32->msg.lParam;
1083 msg32.time = lpmsg16_32->msg.time;
1084 msg32.pt.x = lpmsg16_32->msg.pt.x;
1085 msg32.pt.y = lpmsg16_32->msg.pt.y;
1087 ret = (BOOL16)CallMsgFilterA(&msg32, (INT)code);
1089 lpmsg16_32->msg.hwnd = WIN_Handle16( msg32.hwnd );
1090 lpmsg16_32->msg.message = msg32.message;
1091 lpmsg16_32->msg.wParam = LOWORD(msg32.wParam);
1092 lpmsg16_32->msg.lParam = msg32.lParam;
1093 lpmsg16_32->msg.time = msg32.time;
1094 lpmsg16_32->msg.pt.x = msg32.pt.x;
1095 lpmsg16_32->msg.pt.y = msg32.pt.y;
1096 lpmsg16_32->wParamHigh = HIWORD(msg32.wParam);
1098 return ret;
1103 /***********************************************************************
1104 * CallMsgFilterA (USER32.@)
1106 * FIXME: There are ANSI and UNICODE versions of this, plus an unspecified
1107 * version, plus USER (the 16bit one) has a CallMsgFilter32 function.
1109 BOOL WINAPI CallMsgFilterA( LPMSG msg, INT code )
1111 if (GetSysModalWindow16()) return FALSE; /* ??? */
1112 if (HOOK_CallHooksA( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
1113 return TRUE;
1114 return HOOK_CallHooksA( WH_MSGFILTER, code, 0, (LPARAM)msg );
1118 /***********************************************************************
1119 * CallMsgFilterW (USER32.@)
1121 BOOL WINAPI CallMsgFilterW( LPMSG msg, INT code )
1123 if (GetSysModalWindow16()) return FALSE; /* ??? */
1124 if (HOOK_CallHooksW( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
1125 return TRUE;
1126 return HOOK_CallHooksW( WH_MSGFILTER, code, 0, (LPARAM)msg );