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

Last change on this file since 7154 was 7154, checked in by phaller, 24 years ago

.

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