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

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

customization updates

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