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

Last change on this file since 6003 was 5973, checked in by sandervl, 24 years ago

FillRect & CS_CLASSDC fixes; use critical secions for hooks

File size: 22.5 KB
Line 
1/* $Id: HOOK.CPP,v 1.21 2001-06-12 17:02:33 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
47#include "win32wbase.h"
48
49#define DBG_LOCALLOG DBG_hook
50#include "dbglocal.h"
51
52ODINDEBUGCHANNEL(USER32-HOOK)
53DEFAULT_DEBUG_CHANNEL(hook)
54
55#include "pshpack1.h"
56
57
58/*****************************************************************************
59 * Definitions, structures, and variables *
60 *****************************************************************************/
61
62/* Hook data (pointed to by a HHOOK) */
63typedef struct
64{
65 HANDLE next; /* 00 Next hook in chain */
66 HOOKPROC proc; /* 04 Hook procedure (original) */
67 INT id; /* 08 Hook id (WH_xxx) */
68 DWORD ownerThread; /* 0C Owner thread (0 for system hook) */
69 HMODULE ownerModule; /* 10 Owner module */
70 DWORD flags; /* 14 flags */
71 DWORD magic; /* 18 magic dword */
72} HOOKDATA;
73
74#include "poppack.h"
75
76#define HOOK_MAGIC1 ((int)'H' | (int)'K' << 8) /* 'HK' */
77#define HOOK_MAGIC ((HOOK_MAGIC1<<16)|HOOK_MAGIC1) // 'HKHK'
78
79#define CHECK_MAGIC(a) ((a != 0) && (((HOOKDATA *)a)->magic == HOOK_MAGIC))
80
81//NOTE: This must be in the local data segment -> if a shared semaphore was
82// created by a different process, the handle returned by DosOpenMutexSem
83// will be returned in hGlobalHookMutex
84static HMTX hGlobalHookMutex = 0;
85
86//Global DLL Data
87//SvL: Disabled global system hooks for now
88//#define GLOBAL_HOOKS
89#ifdef GLOBAL_HOOKS
90#pragma data_seg(_GLOBALDATA)
91#endif
92static HANDLE HOOK_systemHooks[WH_NB_HOOKS] = { 0 };
93#ifdef GLOBAL_HOOKS
94static VMutex systemHookMutex(VMUTEX_SHARED, &hGlobalHookMutex);
95#pragma data_seg()
96#else
97static CRITICAL_SECTION systemCritSect = {0};
98#endif
99static HANDLE HOOK_threadHooks[WH_NB_HOOKS] = { 0 };
100static CRITICAL_SECTION threadCritSect = {0};
101
102#ifdef GLOBAL_HOOKS
103#define SYSTEMHOOK_LOCK() systemHookMutex.enter(VMUTEX_WAIT_FOREVER, &hGlobalHookMutex);
104#define SYSTEMHOOK_UNLOCK() systemHookMutex.leave(&hGlobalHookMutex);
105#else
106#define SYSTEMHOOK_LOCK() EnterCriticalSection(&systemCritSect);
107#define SYSTEMHOOK_UNLOCK() LeaveCriticalSection(&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 dprintf(("Setting hook %d: %08x %04x %08lx\n", id, (UINT)proc, hModule, dwThreadId ));
305
306#ifndef __WIN32OS2__
307 /* Create task queue if none present */
308 GetFastQueue16();
309
310 if (id == WH_JOURNALPLAYBACK) EnableHardwareInput16(FALSE);
311#endif
312
313
314 if (dwThreadId) /* Task-specific hook */
315 {
316 if ((id == WH_JOURNALRECORD) || (id == WH_JOURNALPLAYBACK) ||
317 (id == WH_SYSMSGFILTER)) {
318 SetLastError(ERROR_INVALID_PARAMETER);
319 return 0; /* System-only hooks */
320 }
321 }
322
323 /* Create the hook structure */
324
325 data = (HOOKDATA *) HeapAlloc(GetProcessHeap(), 0, sizeof(HOOKDATA));
326 data->proc = (HOOKPROC)proc;
327 data->id = id;
328 data->ownerThread = dwThreadId;
329 data->ownerModule = hModule;
330 data->flags = type;
331 data->magic = HOOK_MAGIC;
332
333 /* Insert it in the correct linked list */
334 if(dwThreadId)
335 {
336 teb = GetTEBFromThreadId(dwThreadId);
337 if(!teb) {
338 dprintf(("HOOK_SetHook: can't find thread database for thread %x", dwThreadId));
339 return 0;
340 }
341 EnterCriticalSection(&threadCritSect);
342 data->next = teb->o.odin.hooks[id - WH_MINHOOK];
343 teb->o.odin.hooks[id - WH_MINHOOK] = (DWORD)data;
344 LeaveCriticalSection(&threadCritSect);
345 }
346 else
347 {
348 SYSTEMHOOK_LOCK();
349 data->next = HOOK_systemHooks[id - WH_MINHOOK];
350 HOOK_systemHooks[id - WH_MINHOOK] = (HANDLE)data;
351 SYSTEMHOOK_UNLOCK();
352 }
353
354 return (HHOOK)data;
355}
356
357
358/***********************************************************************
359 * HOOK_RemoveHook
360 *
361 * Remove a hook from the list.
362 */
363static BOOL HOOK_RemoveHook( HOOKDATA *data )
364{
365 HOOKDATA **prevHook;
366 TEB *teb;
367
368 dprintf(("Removing hook %08x\n", data));
369
370 if (data->flags & HOOK_INUSE)
371 {
372 /* Mark it for deletion later on */
373 dprintf(("Hook still running, deletion delayed\n" ));
374 data->flags |= HOOK_DELAYED_DELETE;
375 return TRUE;
376 }
377
378#ifndef __WIN32OS2__
379 if (data->id == WH_JOURNALPLAYBACK) EnableHardwareInput16(TRUE);
380#endif
381
382 /* Remove it from the linked list */
383
384 if (data->ownerThread)
385 {
386 teb = GetTEBFromThreadId(data->ownerThread);
387 if(!teb) {
388 dprintf(("HOOK_RemoveHook: can't find thread database for thread %x", data->ownerThread));
389 return FALSE;
390 }
391 EnterCriticalSection(&threadCritSect);
392 prevHook = (HOOKDATA **)&teb->o.odin.hooks[data->id - WH_MINHOOK];
393 }
394 else {
395 SYSTEMHOOK_LOCK();
396 prevHook = (HOOKDATA **)&HOOK_systemHooks[data->id - WH_MINHOOK];
397 }
398 while (*prevHook && *prevHook != data)
399 prevHook = (HOOKDATA **)&(*prevHook)->next;
400
401 if (!prevHook) {
402 if (data->ownerThread) {
403 LeaveCriticalSection(&threadCritSect);
404 }
405 else SYSTEMHOOK_UNLOCK();
406
407 return FALSE;
408 }
409 *prevHook = (HOOKDATA *)data->next;
410
411 if (data->ownerThread) {
412 LeaveCriticalSection(&threadCritSect);
413 }
414 else SYSTEMHOOK_UNLOCK();
415
416 HeapFree(GetProcessHeap(), 0, (LPVOID)data );
417 return TRUE;
418}
419
420
421/***********************************************************************
422 * HOOK_FindValidHook
423 */
424static HANDLE HOOK_FindValidHook( HANDLE hook )
425{
426 HOOKDATA *data;
427
428 for (;;)
429 {
430 if (!(data = (HOOKDATA *)hook)) return 0;
431 if (data->proc) return hook;
432 hook = data->next;
433 }
434}
435
436
437/***********************************************************************
438 * HOOK_CallHook
439 *
440 * Call a hook procedure.
441 */
442static LRESULT HOOK_CallHook( HANDLE hook, INT fromtype, INT code,
443 WPARAM wParam, LPARAM lParam )
444{
445 MESSAGEQUEUE *queue;
446 HANDLE prevHook;
447 HOOKDATA *data = (HOOKDATA *)hook;
448 LRESULT ret;
449
450 WPARAM wParamOrig = wParam;
451 LPARAM lParamOrig = lParam;
452 HOOK_MapFunc MapFunc;
453 HOOK_UnMapFunc UnMapFunc;
454
455 MapFunc = HOOK_MapFuncs[fromtype][data->flags & HOOK_MAPTYPE];
456 UnMapFunc = HOOK_UnMapFuncs[fromtype][data->flags & HOOK_MAPTYPE];
457
458 if (MapFunc)
459 MapFunc( data->id, code, &wParam, &lParam );
460
461 /* Now call it */
462
463 data->flags |= HOOK_INUSE;
464
465 dprintf2(("Calling hook %04x: %d %08x %08lx\n", hook, code, wParam, lParam ));
466
467 ret = data->proc(code, wParam, lParam);
468
469 data->flags &= ~HOOK_INUSE;
470
471 if (UnMapFunc)
472 UnMapFunc( data->id, code, wParamOrig, lParamOrig, wParam, lParam );
473
474 if(data->flags & HOOK_DELAYED_DELETE) HOOK_RemoveHook( data );
475
476 return ret;
477}
478
479/***********************************************************************
480 * Exported Functions & APIs
481 */
482
483/***********************************************************************
484 * HOOK_IsHooked
485 *
486 * Replacement for calling HOOK_GetHook from other modules.
487 */
488BOOL HOOK_IsHooked( INT id )
489{
490 /* Hmmm. Use GetThreadQueue(0) instead of GetFastQueue() here to
491 avoid queue being created if someone wants to merely check ... */
492
493 return HOOK_GetHook( id, GetCurrentThreadId() ) != 0;
494}
495
496/***********************************************************************
497 * HOOK_CallHooks32A
498 *
499 * Call a hook chain.
500 */
501LRESULT HOOK_CallHooksA( INT id, INT code, WPARAM wParam,
502 LPARAM lParam )
503{
504 HANDLE hook;
505
506 if (!(hook = HOOK_GetHook( id, GetCurrentThreadId() ))) return 0;
507 if (!(hook = HOOK_FindValidHook(hook))) return 0;
508 return HOOK_CallHook( hook, HOOK_WIN32A, code, wParam, lParam );
509}
510
511/***********************************************************************
512 * HOOK_CallHooks32W
513 *
514 * Call a hook chain.
515 */
516LRESULT HOOK_CallHooksW( INT id, INT code, WPARAM wParam,
517 LPARAM lParam )
518{
519 HANDLE hook;
520
521 if (!(hook = HOOK_GetHook( id, GetCurrentThreadId() ))) return 0;
522 if (!(hook = HOOK_FindValidHook(hook))) return 0;
523 return HOOK_CallHook( hook, HOOK_WIN32W, code, wParam,
524 lParam );
525}
526
527
528#if 0
529/***********************************************************************
530 * HOOK_ResetQueueHooks
531 */
532void HOOK_ResetQueueHooks( HQUEUE hQueue )
533{
534 MESSAGEQUEUE *queue;
535
536 if ((queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue )) != NULL)
537 {
538 HOOKDATA* data;
539 HHOOK hook;
540 int id;
541 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
542 {
543 hook = queue->hooks[id - WH_MINHOOK];
544 while( hook )
545 {
546 if( (data = (HOOKDATA *)hook) )
547 {
548 data->ownerQueue = hQueue;
549 hook = data->next;
550 } else break;
551 }
552 }
553
554 QUEUE_Unlock( queue );
555 }
556}
557#endif
558
559/***********************************************************************
560 * HOOK_FreeModuleHooks
561 */
562void HOOK_FreeModuleHooks( HMODULE hModule )
563{
564 /* remove all system hooks registered by this module */
565
566 HOOKDATA* hptr;
567 HHOOK hook, next;
568 int id;
569
570 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
571 {
572 hook = HOOK_systemHooks[id - WH_MINHOOK];
573 while( hook )
574 {
575 hptr = (HOOKDATA *)hook;
576 if (hptr)
577 {
578 next = hptr->next;
579 if( hptr->ownerModule == hModule )
580 {
581 hptr->flags &= HOOK_MAPTYPE;
582 HOOK_RemoveHook(hptr);
583 }
584 hook = next;
585 }
586 else hook = 0;
587 }
588 }
589}
590
591/***********************************************************************
592 * HOOK_FreeQueueHooks
593 */
594void HOOK_FreeQueueHooks( DWORD threadId )
595{
596 /* remove all hooks registered by this queue */
597
598 HOOKDATA* hptr = NULL;
599 HHOOK hook, next;
600 int id;
601
602 for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
603 {
604 hook = HOOK_GetHook( id, threadId );
605 while( hook )
606 {
607 next = HOOK_GetNextHook(hook);
608
609 hptr = (HOOKDATA *)hook;
610 if( hptr && hptr->ownerThread == threadId )
611 {
612 hptr->flags &= HOOK_MAPTYPE;
613 HOOK_RemoveHook(hptr);
614 }
615 hook = next;
616 }
617 }
618}
619
620
621/***********************************************************************
622 * SetWindowsHook32A (USER32.525)
623 */
624ODINFUNCTION2(HHOOK, SetWindowsHookA,
625 INT, id,
626 HOOKPROC, proc )
627{
628 return SetWindowsHookExA( id, proc, 0, GetCurrentThreadId() );
629}
630
631/***********************************************************************
632 * SetWindowsHook32W (USER32.528)
633 */
634ODINFUNCTION2(HHOOK, SetWindowsHookW,
635 INT, id,
636 HOOKPROC, proc)
637{
638 return SetWindowsHookExW( id, proc, 0, GetCurrentThreadId() );
639}
640
641/***********************************************************************
642 * SetWindowsHookEx32A (USER32.526)
643 */
644ODINFUNCTION4(HHOOK, SetWindowsHookExA,
645 INT, id,
646 HOOKPROC, proc,
647 HINSTANCE, hInst,
648 DWORD, dwThreadId )
649{
650 return HOOK_SetHook( id, proc, HOOK_WIN32A, hInst, dwThreadId );
651}
652
653/***********************************************************************
654 * SetWindowsHookEx32W (USER32.527)
655 */
656ODINFUNCTION4(HHOOK, SetWindowsHookExW,
657 INT, id,
658 HOOKPROC, proc,
659 HINSTANCE, hInst,
660 DWORD, dwThreadId )
661{
662 return HOOK_SetHook( id, proc, HOOK_WIN32W, hInst, dwThreadId );
663}
664
665/***********************************************************************
666 * UnhookWindowsHook32 (USER32.557)
667 */
668ODINFUNCTION2(BOOL, UnhookWindowsHook,
669 INT, id,
670 HOOKPROC, proc )
671{
672 HANDLE hook = HOOK_GetHook( id, GetCurrentThreadId() );
673
674 dprintf(("UnhookWindowsHook: %d %08lx\n", id, (DWORD)proc ));
675
676 while (hook)
677 {
678 HOOKDATA *data = (HOOKDATA *)hook;
679 if (data->proc == proc) break;
680 hook = HOOK_GetNextHook( hook );
681 }
682 if (!hook) return FALSE;
683 return HOOK_RemoveHook( (HOOKDATA *)hook );
684}
685
686
687/***********************************************************************
688 * UnhookWindowHookEx32 (USER32.558)
689 */
690ODINFUNCTION1(BOOL, UnhookWindowsHookEx,
691 HHOOK, hhook )
692{
693 if (CHECK_MAGIC(hhook) == FALSE) {
694 dprintf(("ERROR: UnhookWindowsHookEx invalid hook %x", hhook));
695 return FALSE;
696 }
697
698 return HOOK_RemoveHook( (HOOKDATA *)hhook );
699}
700
701/***********************************************************************
702 * CallNextHookEx32 (USER32.17)
703 *
704 * There aren't ANSI and UNICODE versions of this.
705 */
706LRESULT WINAPI CallNextHookEx(HHOOK hhook, INT code, WPARAM wParam, LPARAM lParam)
707{
708 HANDLE next;
709 INT fromtype; /* figure out Ansi/Unicode */
710 HOOKDATA *oldhook;
711
712 dprintf2(("CallNextHookEx %x %d %x %x", hhook, code, wParam, lParam));
713
714 if (CHECK_MAGIC(hhook) == FALSE) {
715 dprintf(("ERROR: CallNextHookEx invalid hook %x", hhook));
716 return FALSE;
717 }
718 if (!(next = HOOK_GetNextHook( hhook ))) return 0;
719
720 oldhook = (HOOKDATA *)hhook ;
721 fromtype = oldhook->flags & HOOK_MAPTYPE;
722
723 return HOOK_CallHook( next, fromtype, code, wParam, lParam );
724}
725
726
727/***********************************************************************
728 * CallMsgFilter32A (USER32.15)
729 */
730/*
731 * FIXME: There are ANSI and UNICODE versions of this, plus an unspecified
732 * version, plus USER (the 16bit one) has a CallMsgFilter32 function.
733 */
734ODINFUNCTION2(BOOL, CallMsgFilterA,
735 LPMSG, msg,
736 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 */
750ODINFUNCTION2(BOOL, CallMsgFilterW,
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_CallHooksW( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
758 return TRUE;
759 return HOOK_CallHooksW( WH_MSGFILTER, code, 0, (LPARAM)msg );
760}
761
762BOOL IsMenuActive(void);
763
764BOOL ProcessKbdHook(LPMSG msg, BOOL remove )
765{
766 /* Handle F1 key by sending out WM_HELP message */
767 if ((msg->message == WM_KEYUP) &&
768 (msg->wParam == VK_F1) &&
769 remove &&
770 (msg->hwnd != GetDesktopWindow()) &&
771 !IsMenuActive())
772 {
773 HELPINFO hi;
774 Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle(msg->hwnd);
775
776 if (NULL != wnd)
777 {
778 hi.cbSize = sizeof(HELPINFO);
779 hi.iContextType = HELPINFO_WINDOW;
780 hi.iCtrlId = wnd->getWindowId();
781 hi.hItemHandle = msg->hwnd;
782 hi.dwContextId = wnd->getWindowContextHelpId();
783 hi.MousePos = msg->pt;
784 RELEASE_WNDOBJ(wnd);
785 SendMessageA(msg->hwnd, WM_HELP, 0, (LPARAM)&hi);
786 }
787 }
788
789 return (HOOK_CallHooksA( WH_KEYBOARD, remove ? HC_ACTION : HC_NOREMOVE,
790 LOWORD (msg->wParam), msg->lParam )
791 ? TRUE : FALSE);
792}
Note: See TracBrowser for help on using the repository browser.