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

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

Port USER32.DLL (continued).

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, (LPVOID)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, (LPVOID)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.