source: trunk/src/user32/HOOK.CPP@ 8266

Last change on this file since 8266 was 8202, checked in by sandervl, 23 years ago

changed vmutex usage

File size: 25.6 KB
Line 
1/* $Id: HOOK.CPP,v 1.37 2002-04-07 14:36:59 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 0 //CB: not a Win32 API and unimplemented
734 if (GetSysModalWindow()) return FALSE; /* ??? */
735#endif
736 if (HOOK_CallHooksA( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
737 return TRUE;
738 return HOOK_CallHooksA( WH_MSGFILTER, code, 0, (LPARAM)msg );
739}
740
741
742/***********************************************************************
743 * CallMsgFilter32W (USER32.16)
744 */
745BOOL WIN32API CallMsgFilterW(LPMSG msg, INT code )
746{
747#if 0 //CB: not a Win32 API and unimplemented
748 if (GetSysModalWindow()) return FALSE; /* ??? */
749#endif
750 if (HOOK_CallHooksW( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
751 return TRUE;
752 return HOOK_CallHooksW( WH_MSGFILTER, code, 0, (LPARAM)msg );
753}
754
755BOOL ProcessKbdHook(LPMSG msg, BOOL remove )
756{
757 // call the low level hook first
758 if(ProcessKbdHookLL(msg, remove, FALSE) == TRUE) return TRUE;
759
760 // ALT-Key comes in with different scan code (0xa4 == VK_LMENU_W),
761 // then gets translated to 0x12
762 switch (msg->wParam)
763 {
764 case VK_LMENU:
765 case VK_RMENU:
766 msg->wParam = VK_MENU; // 0x12
767 break;
768
769 case VK_LCONTROL:
770 case VK_RCONTROL:
771 msg->wParam = VK_CONTROL; // 0x11
772 break;
773
774 case VK_LSHIFT:
775 case VK_RSHIFT:
776 msg->wParam = VK_SHIFT; // 0x10
777 break;
778 }
779
780 /* Handle F1 key by sending out WM_HELP message */
781 if ((msg->message == WM_KEYUP) &&
782 (msg->wParam == VK_F1) &&
783 remove &&
784 (msg->hwnd != GetDesktopWindow()) &&
785 !IsMenuActive())
786 {
787 HELPINFO hi;
788 Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle(msg->hwnd);
789
790 if (NULL != wnd)
791 {
792 hi.cbSize = sizeof(HELPINFO);
793 hi.iContextType = HELPINFO_WINDOW;
794 hi.iCtrlId = wnd->getWindowId();
795 hi.hItemHandle = msg->hwnd;
796 hi.dwContextId = wnd->getWindowContextHelpId();
797 hi.MousePos = msg->pt;
798 RELEASE_WNDOBJ(wnd);
799 SendMessageA(msg->hwnd, WM_HELP, 0, (LPARAM)&hi);
800 }
801 }
802
803 // this undoc (don't care) bit isn't passed through to this hook
804 // DWORD lParam = msg->lParam & ~0x02000000;
805 msg->lParam &= ~0x02000000;
806
807 return (HOOK_CallHooksA( WH_KEYBOARD, remove ? HC_ACTION : HC_NOREMOVE,
808 LOWORD (msg->wParam), msg->lParam )
809 ? TRUE : FALSE);
810}
811
812
813
814/***
815 * ProcessKbdHookLL
816 * this is a low-level version of the keyboard hook
817 * present under NT/2000/XP.
818 * It is supposed to be called for any keyboard event of the
819 * system-input queue AFAIK.
820 */
821BOOL ProcessKbdHookLL(LPMSG msg, BOOL flagRemove, BOOL flagInjected )
822{
823 // format KBDLLHOOKSTRUCT and pass it in as msg->lParam
824 KBDLLHOOKSTRUCT kbhs;
825
826 kbhs.vkCode = msg->wParam;
827
828 // Note: the "extended" bit seems to be filtered
829 kbhs.scanCode = ( (msg->lParam & 0x02ff0000) >> 16);
830
831 BOOL fKeyUp = (msg->message == WM_KEYUP) ||
832 (msg->message == WM_SYSKEYUP);
833
834 // check if alt is currently pressed
835 // Note: ALT seems to stick sometimes
836 // Note: ALTGR can't be queried
837 BOOL fAltDown = GetAsyncKeyState(VK_LMENU);
838
839 // this bit indicates if ALT was held
840 // fAltDown = msg->lParam & 0x20000000;
841
842 kbhs.flags = fKeyUp ? LLKHF_UP : 0;
843
844 kbhs.flags |= fAltDown ? LLKHF_ALTDOWN : 0;
845 kbhs.flags |= flagInjected ? LLKHF_INJECTED : 0;
846 kbhs.flags |= (msg->lParam & (1 << 24)) ? LLKHF_EXTENDED : 0;
847 kbhs.time = msg->time;
848 kbhs.dwExtraInfo = 0; // @@@PH not supported?
849
850 dprintf(("WH_KEYBOARD_LL: kbhs.vkCode %x kbhs.scanCode %x kbhs.flags %x", kbhs.vkCode, kbhs.scanCode, kbhs.flags));
851
852 return (HOOK_CallHooksA(WH_KEYBOARD_LL,
853 flagRemove ? HC_ACTION : HC_NOREMOVE,
854 msg->message,
855 (LPARAM)&kbhs )
856 ? TRUE : FALSE);
857}
858
859#ifdef __WIN32OS2__
860//******************************************************************************
861//Custom Odin hooks
862static HOOKPROC pfnOdinHook = NULL;
863//******************************************************************************
864HHOOK WIN32API SetOdinHookA(HOOKPROC proc )
865{
866 if(pfnOdinHook) DebugInt3();
867
868 pfnOdinHook = proc;
869 return (HHOOK)proc;
870}
871//******************************************************************************
872//******************************************************************************
873BOOL WIN32API UnhookOdinHook(HHOOK hhook)
874{
875 pfnOdinHook = NULL;
876 return TRUE;
877}
878//******************************************************************************
879//******************************************************************************
880LRESULT HOOK_CallOdinHookA(INT code, WPARAM wParam, LPARAM lParam)
881{
882 if(pfnOdinHook) {
883 return pfnOdinHook(code, wParam, lParam);
884 }
885 return 0;
886}
887//******************************************************************************
888//******************************************************************************
889#endif //__WIN32OS2__
Note: See TracBrowser for help on using the repository browser.