source: trunk/src/user32/hook.cpp@ 21916

Last change on this file since 21916 was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

File size: 25.5 KB
Line 
1/* $Id: HOOK.CPP,v 1.39 2003-01-03 16:35:50 sandervl Exp $ */
2
3/*
4 * Windows hook functions
5 *
6 * Copyright 1999 Sander van Leeuwen (OS/2 Port)
7 *
8 * Port of Wine code (windows\hook.c; dated 990920)
9 * All 16 bits code removed
10 *
11 * Copyright 1994, 1995 Alexandre Julliard
12 * 1996 Andrew Lewycky
13 *
14 * Based on investigations by Alex Korobka
15 *
16 *
17 * Project Odin Software License can be found in LICENSE.TXT
18 */
19
20/*
21 * Warning!
22 * A HHOOK is a 32-bit handle for compatibility with Windows 3.0 where it was
23 * a pointer to the next function. Now it is in fact composed of a USER heap
24 * handle in the low 16 bits and of a HOOK_MAGIC value in the high 16 bits.
25 */
26
27/*****************************************************************************
28 * Includes *
29 *****************************************************************************/
30
31#include <odin.h>
32#include <odinwrap.h>
33#include <os2sel.h>
34
35
36#include <os2win.h>
37#include "hook.h"
38#include "queue.h"
39#include "task.h"
40#include "winproc.h"
41#include "debugtools.h"
42#include <misc.h>
43#include <heapstring.h>
44#include <vmutex.h>
45#include <wprocess.h>
46#include "menu.h"
47#include <winscan.h>
48
49#include "win32wbase.h"
50
51#define DBG_LOCALLOG DBG_hook
52#include "dbglocal.h"
53
54ODINDEBUGCHANNEL(USER32-HOOK)
55DEFAULT_DEBUG_CHANNEL(hook)
56
57#include "pshpack1.h"
58
59
60/*****************************************************************************
61 * Definitions, structures, and variables *
62 *****************************************************************************/
63
64/* Hook data (pointed to by a HHOOK) */
65typedef struct
66{
67 HANDLE next; /* 00 Next hook in chain */
68 HOOKPROC proc; /* 04 Hook procedure (original) */
69 INT id; /* 08 Hook id (WH_xxx) */
70 DWORD ownerThread; /* 0C Owner thread (0 for system hook) */
71 HMODULE ownerModule; /* 10 Owner module */
72 DWORD flags; /* 14 flags */
73 DWORD magic; /* 18 magic dword */
74} HOOKDATA;
75
76#include "poppack.h"
77
78#define HOOK_MAGIC1 ((int)'H' | (int)'K' << 8) /* 'HK' */
79#define HOOK_MAGIC ((HOOK_MAGIC1<<16)|HOOK_MAGIC1) // 'HKHK'
80
81#define CHECK_MAGIC(a) ((a != 0) && (((HOOKDATA *)a)->magic == HOOK_MAGIC))
82
83//SvL: Disabled global system hooks for now
84//#define GLOBAL_HOOKS
85#ifdef GLOBAL_HOOKS
86//
87// Global DLL Data (keep it in sync with globaldata.asm!)
88//
89extern HANDLE HOOK_systemHooks[WH_NB_HOOKS]; // = { 0 }
90static VMutex systemHookMutex(VMUTEX_SHARED, &hGlobalHookMutex);
91#else
92static HANDLE HOOK_systemHooks[WH_NB_HOOKS] = { 0 };
93static CRITICAL_SECTION systemCritSect = {0};
94#endif
95static HANDLE HOOK_threadHooks[WH_NB_HOOKS] = { 0 };
96static CRITICAL_SECTION threadCritSect = {0};
97static BOOL fInitHook = FALSE;
98
99#ifdef GLOBAL_HOOKS
100#define SYSTEMHOOK_LOCK() systemHookMutex.enter(VMUTEX_WAIT_FOREVER, &hGlobalHookMutex);
101#define SYSTEMHOOK_UNLOCK() systemHookMutex.leave(&hGlobalHookMutex);
102#define INIT_SYSTEMHOOK() aldkjfslfjsdlkfj
103#else
104#define SYSTEMHOOK_LOCK() EnterCriticalSection(&systemCritSect);
105#define SYSTEMHOOK_UNLOCK() LeaveCriticalSection(&systemCritSect);
106#define INIT_SYSTEMHOOK() InitializeCriticalSection(&systemCritSect);
107#endif
108
109typedef VOID (*HOOK_MapFunc)(INT, INT, WPARAM *, LPARAM *);
110typedef VOID (*HOOK_UnMapFunc)(INT, INT, WPARAM, LPARAM, WPARAM,
111 LPARAM);
112
113/***********************************************************************
114 * HOOK_Map32ATo32W
115 */
116static void HOOK_Map32ATo32W(INT id, INT code, WPARAM *pwParam,
117 LPARAM *plParam)
118{
119 if (id == WH_CBT && code == HCBT_CREATEWND)
120 {
121 LPCBT_CREATEWNDA lpcbtcwA = (LPCBT_CREATEWNDA)*plParam;
122 LPCBT_CREATEWNDW lpcbtcwW = (LPCBT_CREATEWNDW)HeapAlloc(GetProcessHeap(), 0,
123 sizeof(*lpcbtcwW) );
124 lpcbtcwW->lpcs = (CREATESTRUCTW*)HeapAlloc( GetProcessHeap(), 0, sizeof(*lpcbtcwW->lpcs) );
125
126 lpcbtcwW->hwndInsertAfter = lpcbtcwA->hwndInsertAfter;
127 *lpcbtcwW->lpcs = *(LPCREATESTRUCTW)lpcbtcwA->lpcs;
128
129 if (HIWORD(lpcbtcwA->lpcs->lpszName))
130 {
131 lpcbtcwW->lpcs->lpszName = HEAP_strdupAtoW( GetProcessHeap(), 0,
132 lpcbtcwA->lpcs->lpszName );
133 }
134 else
135 lpcbtcwW->lpcs->lpszName = (LPWSTR)lpcbtcwA->lpcs->lpszName;
136
137 if (HIWORD(lpcbtcwA->lpcs->lpszClass))
138 {
139 lpcbtcwW->lpcs->lpszClass = HEAP_strdupAtoW( GetProcessHeap(), 0,
140 lpcbtcwA->lpcs->lpszClass );
141 }
142 else
143 lpcbtcwW->lpcs->lpszClass = (LPCWSTR)lpcbtcwA->lpcs->lpszClass;
144 *plParam = (LPARAM)lpcbtcwW;
145 }
146 return;
147}
148
149
150/***********************************************************************
151 * HOOK_UnMap32ATo32W
152 */
153static void HOOK_UnMap32ATo32W(INT id, INT code, WPARAM wParamOrig,
154 LPARAM lParamOrig, WPARAM wParam,
155 LPARAM lParam)
156{
157 if (id == WH_CBT && code == HCBT_CREATEWND)
158 {
159 LPCBT_CREATEWNDW lpcbtcwW = (LPCBT_CREATEWNDW)lParam;
160 if (HIWORD(lpcbtcwW->lpcs->lpszName))
161 HeapFree( GetProcessHeap(), 0, (LPWSTR)lpcbtcwW->lpcs->lpszName );
162 if (HIWORD(lpcbtcwW->lpcs->lpszClass))
163 HeapFree( GetProcessHeap(), 0, (LPWSTR)lpcbtcwW->lpcs->lpszClass );
164 HeapFree( GetProcessHeap(), 0, lpcbtcwW->lpcs );
165 HeapFree( GetProcessHeap(), 0, lpcbtcwW );
166 }
167 return;
168}
169
170
171/***********************************************************************
172 * HOOK_Map32WTo32A
173 */
174static void HOOK_Map32WTo32A(INT id, INT code, WPARAM *pwParam,
175 LPARAM *plParam)
176{
177 if (id == WH_CBT && code == HCBT_CREATEWND)
178 {
179 LPCBT_CREATEWNDW lpcbtcwW = (LPCBT_CREATEWNDW)*plParam;
180 LPCBT_CREATEWNDA lpcbtcwA = (LPCBT_CREATEWNDA)HeapAlloc(GetProcessHeap(), 0,
181 sizeof(*lpcbtcwA) );
182 lpcbtcwA->lpcs = (CREATESTRUCTA*)HeapAlloc( GetProcessHeap(), 0, sizeof(*lpcbtcwA->lpcs) );
183
184 lpcbtcwA->hwndInsertAfter = lpcbtcwW->hwndInsertAfter;
185 *lpcbtcwA->lpcs = *(LPCREATESTRUCTA)lpcbtcwW->lpcs;
186
187 if (HIWORD(lpcbtcwW->lpcs->lpszName))
188 lpcbtcwA->lpcs->lpszName = HEAP_strdupWtoA( GetProcessHeap(), 0,
189 lpcbtcwW->lpcs->lpszName );
190 else
191 lpcbtcwA->lpcs->lpszName = (LPSTR)lpcbtcwW->lpcs->lpszName;
192
193 if (HIWORD(lpcbtcwW->lpcs->lpszClass))
194 lpcbtcwA->lpcs->lpszClass = HEAP_strdupWtoA( GetProcessHeap(), 0,
195 lpcbtcwW->lpcs->lpszClass );
196 else
197 lpcbtcwA->lpcs->lpszClass = (LPSTR)lpcbtcwW->lpcs->lpszClass;
198 *plParam = (LPARAM)lpcbtcwA;
199 }
200 return;
201}
202
203
204/***********************************************************************
205 * HOOK_UnMap32WTo32A
206 */
207static void HOOK_UnMap32WTo32A(INT id, INT code, WPARAM wParamOrig,
208 LPARAM lParamOrig, WPARAM wParam,
209 LPARAM lParam)
210{
211 if (id == WH_CBT && code == HCBT_CREATEWND)
212 {
213 LPCBT_CREATEWNDA lpcbtcwA = (LPCBT_CREATEWNDA)lParam;
214 if (HIWORD(lpcbtcwA->lpcs->lpszName))
215 HeapFree( GetProcessHeap(), 0, (LPSTR)lpcbtcwA->lpcs->lpszName );
216 if (HIWORD(lpcbtcwA->lpcs->lpszClass))
217 HeapFree( GetProcessHeap(), 0, (LPSTR)lpcbtcwA->lpcs->lpszClass );
218 HeapFree( GetProcessHeap(), 0, lpcbtcwA->lpcs );
219 HeapFree( GetProcessHeap(), 0, lpcbtcwA );
220 }
221 return;
222}
223
224
225/***********************************************************************
226 * Map Function Tables
227 */
228static const HOOK_MapFunc HOOK_MapFuncs[3][3] =
229{
230 { NULL, NULL, NULL },
231 { NULL, NULL, HOOK_Map32ATo32W },
232 { NULL, HOOK_Map32WTo32A, NULL }
233};
234
235static const HOOK_UnMapFunc HOOK_UnMapFuncs[3][3] =
236{
237 { NULL, NULL, NULL },
238 { NULL, NULL, HOOK_UnMap32ATo32W },
239 { NULL, HOOK_UnMap32WTo32A, NULL }
240};
241
242
243/***********************************************************************
244 * Internal Functions
245 */
246
247/***********************************************************************
248 * HOOK_GetNextHook
249 *
250 * Get the next hook of a given hook.
251 */
252static HANDLE HOOK_GetNextHook( HANDLE hook )
253{
254 HOOKDATA *data = (HOOKDATA *)hook;
255
256 if (!data || !hook) return 0;
257 if (data->next) return data->next;
258 if (!data->ownerThread) return 0; /* Already system hook */
259
260 /* Now start enumerating the system hooks */
261 return HOOK_systemHooks[data->id - WH_MINHOOK];
262}
263
264
265/***********************************************************************
266 * HOOK_GetHook
267 *
268 * Get the first hook for a given type.
269 */
270static HANDLE HOOK_GetHook( INT id, DWORD threadId )
271{
272 MESSAGEQUEUE *queue;
273 HANDLE hook = 0;
274 TEB *teb;
275
276 teb = GetTEBFromThreadId(threadId);
277 if(teb) {
278 hook = teb->o.odin.hooks[id - WH_MINHOOK];
279 }
280 if (!hook) hook = HOOK_systemHooks[id - WH_MINHOOK];
281
282 return hook;
283}
284
285
286/***********************************************************************
287 * HOOK_SetHook
288 *
289 * Install a given hook.
290 */
291static HHOOK HOOK_SetHook( INT id, LPVOID proc, INT type,
292 HMODULE hModule, DWORD dwThreadId )
293{
294 HOOKDATA *data;
295 TEB *teb;
296
297 if ((id < WH_MINHOOK) || (id > WH_MAXHOOK) || !proc )
298 {
299 SetLastError(ERROR_INVALID_PARAMETER);
300 return 0;
301 }
302
303 if(!fInitHook) {
304 InitializeCriticalSection(&threadCritSect);
305 INIT_SYSTEMHOOK();
306 fInitHook = TRUE;
307 }
308
309 dprintf(("Setting hook %d: %08x %04x %08lx\n", id, (UINT)proc, hModule, dwThreadId ));
310
311#ifndef __WIN32OS2__
312 /* Create task queue if none present */
313 GetFastQueue16();
314
315 if (id == WH_JOURNALPLAYBACK) EnableHardwareInput16(FALSE);
316#endif
317
318
319 if (dwThreadId) /* Task-specific hook */
320 {
321 if ((id == WH_JOURNALRECORD) || (id == WH_JOURNALPLAYBACK) ||
322 (id == WH_SYSMSGFILTER)) {
323 SetLastError(ERROR_INVALID_PARAMETER);
324 return 0; /* System-only hooks */
325 }
326 }
327
328 /* Create the hook structure */
329
330 data = (HOOKDATA *) HeapAlloc(GetProcessHeap(), 0, sizeof(HOOKDATA));
331 data->proc = (HOOKPROC)proc;
332 data->id = id;
333 data->ownerThread = dwThreadId;
334 data->ownerModule = hModule;
335 data->flags = type;
336 data->magic = HOOK_MAGIC;
337
338 /* Insert it in the correct linked list */
339 if(dwThreadId)
340 {
341 teb = GetTEBFromThreadId(dwThreadId);
342 if(!teb) {
343 dprintf(("HOOK_SetHook: can't find thread database for thread %x", dwThreadId));
344 return 0;
345 }
346 EnterCriticalSection(&threadCritSect);
347 data->next = teb->o.odin.hooks[id - WH_MINHOOK];
348 teb->o.odin.hooks[id - WH_MINHOOK] = (DWORD)data;
349 LeaveCriticalSection(&threadCritSect);
350 }
351 else
352 {
353 SYSTEMHOOK_LOCK();
354 data->next = HOOK_systemHooks[id - WH_MINHOOK];
355 HOOK_systemHooks[id - WH_MINHOOK] = (HANDLE)data;
356 SYSTEMHOOK_UNLOCK();
357 }
358
359 return (HHOOK)data;
360}
361
362
363/***********************************************************************
364 * HOOK_RemoveHook
365 *
366 * Remove a hook from the list.
367 */
368static BOOL HOOK_RemoveHook( HOOKDATA *data )
369{
370 HOOKDATA **prevHook;
371 TEB *teb;
372
373 dprintf(("Removing hook %08x\n", data));
374
375 if(!fInitHook) {
376 InitializeCriticalSection(&threadCritSect);
377 INIT_SYSTEMHOOK();
378 fInitHook = TRUE;
379 }
380
381 if (data->flags & HOOK_INUSE)
382 {
383 /* Mark it for deletion later on */
384 dprintf(("Hook still running, deletion delayed\n" ));
385 data->flags |= HOOK_DELAYED_DELETE;
386 return TRUE;
387 }
388
389#ifndef __WIN32OS2__
390 if (data->id == WH_JOURNALPLAYBACK) EnableHardwareInput16(TRUE);
391#endif
392
393 /* Remove it from the linked list */
394
395 if (data->ownerThread)
396 {
397 teb = GetTEBFromThreadId(data->ownerThread);
398 if(!teb) {
399 dprintf(("HOOK_RemoveHook: can't find thread database for thread %x", data->ownerThread));
400 return FALSE;
401 }
402 EnterCriticalSection(&threadCritSect);
403 prevHook = (HOOKDATA **)&teb->o.odin.hooks[data->id - WH_MINHOOK];
404 }
405 else {
406 SYSTEMHOOK_LOCK();
407 prevHook = (HOOKDATA **)&HOOK_systemHooks[data->id - WH_MINHOOK];
408 }
409 while (*prevHook && *prevHook != data)
410 prevHook = (HOOKDATA **)&(*prevHook)->next;
411
412 if (!prevHook) {
413 if (data->ownerThread) {
414 LeaveCriticalSection(&threadCritSect);
415 }
416 else SYSTEMHOOK_UNLOCK();
417
418 return FALSE;
419 }
420 *prevHook = (HOOKDATA *)data->next;
421
422 if (data->ownerThread) {
423 LeaveCriticalSection(&threadCritSect);
424 }
425 else SYSTEMHOOK_UNLOCK();
426
427 HeapFree(GetProcessHeap(), 0, (LPVOID)data );
428 return TRUE;
429}
430
431
432/***********************************************************************
433 * HOOK_FindValidHook
434 */
435static HANDLE HOOK_FindValidHook( HANDLE hook )
436{
437 HOOKDATA *data;
438
439 for (;;)
440 {
441 if (!(data = (HOOKDATA *)hook)) return 0;
442 if (data->proc) return hook;
443 hook = data->next;
444 }
445}
446
447
448/***********************************************************************
449 * HOOK_CallHook
450 *
451 * Call a hook procedure.
452 */
453static LRESULT HOOK_CallHook( HANDLE hook, INT fromtype, INT code,
454 WPARAM wParam, LPARAM lParam )
455{
456 MESSAGEQUEUE *queue;
457 HANDLE prevHook;
458 HOOKDATA *data = (HOOKDATA *)hook;
459 LRESULT ret;
460
461 WPARAM wParamOrig = wParam;
462 LPARAM lParamOrig = lParam;
463 HOOK_MapFunc MapFunc;
464 HOOK_UnMapFunc UnMapFunc;
465
466 MapFunc = HOOK_MapFuncs[fromtype][data->flags & HOOK_MAPTYPE];
467 UnMapFunc = HOOK_UnMapFuncs[fromtype][data->flags & HOOK_MAPTYPE];
468
469 if (MapFunc)
470 MapFunc( data->id, code, &wParam, &lParam );
471
472 /* Now call it */
473
474 data->flags |= HOOK_INUSE;
475
476 dprintf2(("Calling hook %04x: %d %08x %08lx\n", hook, code, wParam, lParam ));
477
478 ret = data->proc(code, wParam, lParam);
479
480 data->flags &= ~HOOK_INUSE;
481
482 if (UnMapFunc)
483 UnMapFunc( data->id, code, wParamOrig, lParamOrig, wParam, lParam );
484
485 if(data->flags & HOOK_DELAYED_DELETE) HOOK_RemoveHook( data );
486
487 return ret;
488}
489
490/***********************************************************************
491 * Exported Functions & APIs
492 */
493
494/***********************************************************************
495 * HOOK_IsHooked
496 *
497 * Replacement for calling HOOK_GetHook from other modules.
498 */
499BOOL HOOK_IsHooked( INT id )
500{
501 /* Hmmm. Use GetThreadQueue(0) instead of GetFastQueue() here to
502 avoid queue being created if someone wants to merely check ... */
503
504 return HOOK_GetHook( id, GetCurrentThreadId() ) != 0;
505}
506
507/***********************************************************************
508 * HOOK_CallHooks32A
509 *
510 * Call a hook chain.
511 */
512LRESULT HOOK_CallHooksA( INT id, INT code, WPARAM wParam,
513 LPARAM lParam )
514{
515 HANDLE hook;
516
517 if (!(hook = HOOK_GetHook( id, GetCurrentThreadId() ))) return 0;
518 if (!(hook = HOOK_FindValidHook(hook))) return 0;
519 return HOOK_CallHook( hook, HOOK_WIN32A, code, wParam, lParam );
520}
521
522/***********************************************************************
523 * HOOK_CallHooks32W
524 *
525 * Call a hook chain.
526 */
527LRESULT HOOK_CallHooksW( INT id, INT code, WPARAM wParam,
528 LPARAM lParam )
529{
530 HANDLE hook;
531
532 if (!(hook = HOOK_GetHook( id, GetCurrentThreadId() ))) return 0;
533 if (!(hook = HOOK_FindValidHook(hook))) return 0;
534 return HOOK_CallHook( hook, HOOK_WIN32W, code, wParam,
535 lParam );
536}
537
538
539#if 0
540/***********************************************************************
541 * HOOK_ResetQueueHooks
542 */
543void HOOK_ResetQueueHooks( HQUEUE hQueue )
544{
545 MESSAGEQUEUE *queue;
546
547 if ((queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue )) != NULL)
548 {
549 HOOKDATA* data;
550 HHOOK hook;
551 int id;
552 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
553 {
554 hook = queue->hooks[id - WH_MINHOOK];
555 while( hook )
556 {
557 if( (data = (HOOKDATA *)hook) )
558 {
559 data->ownerQueue = hQueue;
560 hook = data->next;
561 } else break;
562 }
563 }
564
565 QUEUE_Unlock( queue );
566 }
567}
568#endif
569
570/***********************************************************************
571 * HOOK_FreeModuleHooks
572 */
573void HOOK_FreeModuleHooks( HMODULE hModule )
574{
575 /* remove all system hooks registered by this module */
576
577 HOOKDATA* hptr;
578 HHOOK hook, next;
579 int id;
580
581 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
582 {
583 hook = HOOK_systemHooks[id - WH_MINHOOK];
584 while( hook )
585 {
586 hptr = (HOOKDATA *)hook;
587 if (hptr)
588 {
589 next = hptr->next;
590 if( hptr->ownerModule == hModule )
591 {
592 hptr->flags &= HOOK_MAPTYPE;
593 HOOK_RemoveHook(hptr);
594 }
595 hook = next;
596 }
597 else hook = 0;
598 }
599 }
600}
601
602/***********************************************************************
603 * HOOK_FreeQueueHooks
604 */
605void HOOK_FreeQueueHooks( DWORD threadId )
606{
607 /* remove all hooks registered by this queue */
608
609 HOOKDATA* hptr = NULL;
610 HHOOK hook, next;
611 int id;
612
613 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
614 {
615 hook = HOOK_GetHook( id, threadId );
616 while( hook )
617 {
618 next = HOOK_GetNextHook(hook);
619
620 hptr = (HOOKDATA *)hook;
621 if( hptr && hptr->ownerThread == threadId )
622 {
623 hptr->flags &= HOOK_MAPTYPE;
624 HOOK_RemoveHook(hptr);
625 }
626 hook = next;
627 }
628 }
629}
630
631
632/***********************************************************************
633 * SetWindowsHook32A (USER32.525)
634 */
635HHOOK WIN32API SetWindowsHookA(INT id, HOOKPROC proc )
636{
637 return SetWindowsHookExA( id, proc, 0, GetCurrentThreadId() );
638}
639
640/***********************************************************************
641 * SetWindowsHook32W (USER32.528)
642 */
643HHOOK WIN32API SetWindowsHookW(INT id, HOOKPROC proc)
644{
645 return SetWindowsHookExW( id, proc, 0, GetCurrentThreadId() );
646}
647
648/***********************************************************************
649 * SetWindowsHookEx32A (USER32.526)
650 */
651HHOOK WIN32API SetWindowsHookExA(INT id, HOOKPROC proc,
652 HINSTANCE hInst, DWORD dwThreadId )
653{
654 return HOOK_SetHook( id, (LPVOID)proc, HOOK_WIN32A, hInst, dwThreadId );
655}
656
657/***********************************************************************
658 * SetWindowsHookEx32W (USER32.527)
659 */
660HHOOK WIN32API SetWindowsHookExW(INT id, HOOKPROC proc, HINSTANCE hInst,
661 DWORD dwThreadId )
662{
663 return HOOK_SetHook( id, (LPVOID)proc, HOOK_WIN32W, hInst, dwThreadId );
664}
665
666/***********************************************************************
667 * UnhookWindowsHook32 (USER32.557)
668 */
669BOOL WIN32API UnhookWindowsHook(INT id, HOOKPROC proc )
670{
671 HANDLE hook = HOOK_GetHook( id, GetCurrentThreadId() );
672
673 while (hook)
674 {
675 HOOKDATA *data = (HOOKDATA *)hook;
676 if (data->proc == proc) break;
677 hook = HOOK_GetNextHook( hook );
678 }
679 if (!hook) return FALSE;
680 return HOOK_RemoveHook( (HOOKDATA *)hook );
681}
682
683
684/***********************************************************************
685 * UnhookWindowHookEx32 (USER32.558)
686 */
687BOOL WIN32API UnhookWindowsHookEx(HHOOK hhook )
688{
689 if (CHECK_MAGIC(hhook) == FALSE) {
690 dprintf(("ERROR: UnhookWindowsHookEx invalid hook %x", hhook));
691 return FALSE;
692 }
693
694 return HOOK_RemoveHook( (HOOKDATA *)hhook );
695}
696
697/***********************************************************************
698 * CallNextHookEx32 (USER32.17)
699 *
700 * There aren't ANSI and UNICODE versions of this.
701 */
702LRESULT WINAPI CallNextHookEx(HHOOK hhook, INT code, WPARAM wParam, LPARAM lParam)
703{
704 HANDLE next;
705 INT fromtype; /* figure out Ansi/Unicode */
706 HOOKDATA *oldhook;
707
708 dprintf2(("CallNextHookEx %x %d %x %x", hhook, code, wParam, lParam));
709
710 if (CHECK_MAGIC(hhook) == FALSE) {
711 dprintf(("ERROR: CallNextHookEx invalid hook %x", hhook));
712 return FALSE;
713 }
714 if (!(next = HOOK_GetNextHook( hhook ))) return 0;
715
716 oldhook = (HOOKDATA *)hhook ;
717 fromtype = oldhook->flags & HOOK_MAPTYPE;
718
719 return HOOK_CallHook( next, fromtype, code, wParam, lParam );
720}
721
722
723/***********************************************************************
724 * CallMsgFilter32A (USER32.15)
725 */
726/*
727 * FIXME: There are ANSI and UNICODE versions of this, plus an unspecified
728 * version, plus USER (the 16bit one) has a CallMsgFilter32 function.
729 */
730BOOL WIN32API CallMsgFilterA(LPMSG msg, INT code )
731{
732 if (HOOK_CallHooksA( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
733 return TRUE;
734 return HOOK_CallHooksA( WH_MSGFILTER, code, 0, (LPARAM)msg );
735}
736
737
738/***********************************************************************
739 * CallMsgFilter32W (USER32.16)
740 */
741BOOL WIN32API CallMsgFilterW(LPMSG msg, INT code )
742{
743 if (HOOK_CallHooksW( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
744 return TRUE;
745 return HOOK_CallHooksW( WH_MSGFILTER, code, 0, (LPARAM)msg );
746}
747
748BOOL ProcessKbdHook(LPMSG msg, BOOL remove )
749{
750 // call the low level hook first
751 if(ProcessKbdHookLL(msg, remove, FALSE) == TRUE) return TRUE;
752
753 // ALT-Key comes in with different scan code (0xa4 == VK_LMENU_W),
754 // then gets translated to 0x12
755 switch (msg->wParam)
756 {
757 case VK_LMENU:
758 case VK_RMENU:
759 msg->wParam = VK_MENU; // 0x12
760 break;
761
762 case VK_LCONTROL:
763 case VK_RCONTROL:
764 msg->wParam = VK_CONTROL; // 0x11
765 break;
766
767 case VK_LSHIFT:
768 case VK_RSHIFT:
769 msg->wParam = VK_SHIFT; // 0x10
770 break;
771 }
772
773 /* Handle F1 key by sending out WM_HELP message */
774 if ((msg->message == WM_KEYUP) &&
775 (msg->wParam == VK_F1) &&
776 remove &&
777 (msg->hwnd != GetDesktopWindow()) &&
778 !MENU_IsMenuActive())
779 {
780 HELPINFO hi;
781 Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle(msg->hwnd);
782
783 if (NULL != wnd)
784 {
785 hi.cbSize = sizeof(HELPINFO);
786 hi.iContextType = HELPINFO_WINDOW;
787 hi.iCtrlId = wnd->getWindowId();
788 hi.hItemHandle = msg->hwnd;
789 hi.dwContextId = wnd->getWindowContextHelpId();
790 hi.MousePos = msg->pt;
791 RELEASE_WNDOBJ(wnd);
792 SendMessageA(msg->hwnd, WM_HELP, 0, (LPARAM)&hi);
793 }
794 }
795
796 // this undoc (don't care) bit isn't passed through to this hook
797 // DWORD lParam = msg->lParam & ~0x02000000;
798 msg->lParam &= ~0x02000000;
799
800 return (HOOK_CallHooksA( WH_KEYBOARD, remove ? HC_ACTION : HC_NOREMOVE,
801 LOWORD (msg->wParam), msg->lParam )
802 ? TRUE : FALSE);
803}
804
805
806
807/***
808 * ProcessKbdHookLL
809 * this is a low-level version of the keyboard hook
810 * present under NT/2000/XP.
811 * It is supposed to be called for any keyboard event of the
812 * system-input queue AFAIK.
813 */
814BOOL ProcessKbdHookLL(LPMSG msg, BOOL flagRemove, BOOL flagInjected )
815{
816 // format KBDLLHOOKSTRUCT and pass it in as msg->lParam
817 KBDLLHOOKSTRUCT kbhs;
818
819 kbhs.vkCode = msg->wParam;
820
821 // Note: the "extended" bit seems to be filtered
822 kbhs.scanCode = ( (msg->lParam & 0x02ff0000) >> 16);
823
824 BOOL fKeyUp = (msg->message == WM_KEYUP) ||
825 (msg->message == WM_SYSKEYUP);
826
827 // check if alt is currently pressed
828 // Note: ALT seems to stick sometimes
829 // Note: ALTGR can't be queried
830 BOOL fAltDown = GetAsyncKeyState(VK_LMENU) | GetAsyncKeyState(VK_RMENU);
831
832 // this bit indicates if ALT was held
833 // fAltDown = msg->lParam & 0x20000000;
834
835 kbhs.flags = fKeyUp ? LLKHF_UP : 0;
836
837 kbhs.flags |= fAltDown ? LLKHF_ALTDOWN : 0;
838 kbhs.flags |= flagInjected ? LLKHF_INJECTED : 0;
839 kbhs.flags |= (msg->lParam & (1 << 24)) ? LLKHF_EXTENDED : 0;
840 kbhs.time = msg->time;
841 kbhs.dwExtraInfo = 0; // @@@PH not supported?
842
843 dprintf(("WH_KEYBOARD_LL: kbhs.vkCode %x kbhs.scanCode %x kbhs.flags %x", kbhs.vkCode, kbhs.scanCode, kbhs.flags));
844
845 return (HOOK_CallHooksA(WH_KEYBOARD_LL,
846 flagRemove ? HC_ACTION : HC_NOREMOVE,
847 msg->message,
848 (LPARAM)&kbhs )
849 ? TRUE : FALSE);
850}
851
852#ifdef __WIN32OS2__
853//******************************************************************************
854//Custom Odin hooks
855static HOOKPROC pfnOdinHook = NULL;
856//******************************************************************************
857HHOOK WIN32API SetOdinHookA(HOOKPROC proc )
858{
859 if(pfnOdinHook) DebugInt3();
860
861 pfnOdinHook = proc;
862 return (HHOOK)proc;
863}
864//******************************************************************************
865//******************************************************************************
866BOOL WIN32API UnhookOdinHook(HHOOK hhook)
867{
868 pfnOdinHook = NULL;
869 return TRUE;
870}
871//******************************************************************************
872//******************************************************************************
873extern "C"
874LRESULT HOOK_CallOdinHookA(INT code, WPARAM wParam, LPARAM lParam)
875{
876 if(pfnOdinHook) {
877 return pfnOdinHook(code, wParam, lParam);
878 }
879 return 0;
880}
881//******************************************************************************
882//******************************************************************************
883#endif //__WIN32OS2__
Note: See TracBrowser for help on using the repository browser.