source: branches/gcc-kmk/src/user32/hook.cpp@ 21692

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

Normalize file case.

Change all uppercase filenames and extensions to lowercase (except well known cases like LICENSE.TXT and so on).

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