Removed unnecessary includes.
[wine] / windows / hook.c
1 /*
2  * Windows hook functions
3  *
4  * Copyright 1994, 1995 Alexandre Julliard
5  *                 1996 Andrew Lewycky
6  *
7  * Based on investigations by Alex Korobka
8  */
9
10 /*
11  * Warning!
12  * A HHOOK is a 32-bit handle for compatibility with Windows 3.0 where it was
13  * a pointer to the next function. Now it is in fact composed of a USER heap
14  * handle in the low 16 bits and of a HOOK_MAGIC value in the high 16 bits.
15  */
16
17 #include "windef.h"
18 #include "winbase.h"
19 #include "wingdi.h"
20 #include "winuser.h"
21 #include "wine/winuser16.h"
22 #include "wine/winbase16.h"
23 #include "hook.h"
24 #include "win.h"
25 #include "queue.h"
26 #include "user.h"
27 #include "heap.h"
28 #include "struct32.h"
29 #include "winproc.h"
30 #include "debugtools.h"
31
32 DEFAULT_DEBUG_CHANNEL(hook);
33
34 #include "pshpack1.h"
35
36   /* Hook data (pointed to by a HHOOK) */
37 typedef struct
38 {
39     HANDLE16   next;               /* 00 Next hook in chain */
40     HOOKPROC   proc;               /* 02 Hook procedure (original) */
41     INT16      id;                 /* 06 Hook id (WH_xxx) */
42     HQUEUE16   ownerQueue;         /* 08 Owner queue (0 for system hook) */
43     HMODULE16  ownerModule;        /* 0a Owner module */
44     WORD       flags;              /* 0c flags */
45 } HOOKDATA;
46
47 #include "poppack.h"
48
49 #define HOOK_MAGIC  ((int)'H' | (int)'K' << 8)  /* 'HK' */
50
51   /* This should probably reside in USER heap */
52 static HANDLE16 HOOK_systemHooks[WH_NB_HOOKS] = { 0, };
53
54 typedef VOID (*HOOK_MapFunc)(INT, INT, WPARAM *, LPARAM *);
55 typedef VOID (*HOOK_UnMapFunc)(INT, INT, WPARAM, LPARAM, WPARAM,
56                                LPARAM);
57
58 /***********************************************************************
59  *           HOOK_Map16To32Common
60  */
61 static void HOOK_Map16To32Common(INT id, INT code, WPARAM *pwParam,
62                                  LPARAM *plParam, BOOL bA )
63 {
64
65    switch( id )
66    {
67         case WH_MSGFILTER:
68         case WH_SYSMSGFILTER: 
69         case WH_GETMESSAGE: 
70         case WH_JOURNALRECORD:
71         {
72             LPMSG16 lpmsg16 = MapSL(*plParam);
73             LPMSG lpmsg32 = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpmsg32) );
74         
75             STRUCT32_MSG16to32( lpmsg16, lpmsg32 );
76             *plParam = (LPARAM)lpmsg32;
77             break;
78         } 
79
80         case WH_JOURNALPLAYBACK:
81         {
82             LPEVENTMSG16 lpem16 = MapSL(*plParam);
83             LPEVENTMSG lpem32 = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpem32) );
84
85             lpem32->message = lpem16->message;
86             lpem32->paramL = lpem16->paramL;
87             lpem32->paramH = lpem16->paramH;
88             lpem32->time = lpem16->time;
89             lpem32->hwnd = 0;   /* FIXME */
90
91             *plParam = (LPARAM)lpem32;
92             break;
93         } 
94
95         case WH_CALLWNDPROC:
96         {
97             LPCWPSTRUCT16   lpcwp16 = MapSL(*plParam);
98             LPCWPSTRUCT   lpcwp32 = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpcwp32) );
99             
100             lpcwp32->hwnd = WIN_Handle32(lpcwp16->hwnd);
101             lpcwp32->lParam = lpcwp16->lParam;
102             
103             if (bA) WINPROC_MapMsg16To32A( lpcwp32->hwnd, lpcwp16->message, lpcwp16->wParam,
104                                            &lpcwp32->message, &lpcwp32->wParam,
105                                            &lpcwp32->lParam );
106             else WINPROC_MapMsg16To32W( lpcwp32->hwnd,lpcwp16->message, lpcwp16->wParam,
107                                         &lpcwp32->message, &lpcwp32->wParam,
108                                         &lpcwp32->lParam );
109             *plParam = (LPARAM)lpcwp32;
110             break;
111         }
112
113         case WH_CBT:
114           switch (code)
115           {
116             case HCBT_CREATEWND:
117             {
118                 LPCBT_CREATEWND16  lpcbtcw16 = MapSL(*plParam);
119                 LPCREATESTRUCT16   lpcs16 = MapSL((SEGPTR)lpcbtcw16->lpcs);
120                 LPCBT_CREATEWNDA lpcbtcw32 = HeapAlloc( GetProcessHeap(), 0,
121                                                           sizeof(*lpcbtcw32) );
122                 lpcbtcw32->lpcs = HeapAlloc( GetProcessHeap(), 0,
123                                              sizeof(*lpcbtcw32->lpcs) );
124
125                 STRUCT32_CREATESTRUCT16to32A( lpcs16,
126                                              (LPCREATESTRUCTA)lpcbtcw32->lpcs );
127
128                 if (HIWORD(lpcs16->lpszName))
129                     lpcbtcw32->lpcs->lpszName = 
130                         (bA) ? MapSL(lpcs16->lpszName)
131                              : HEAP_strdupAtoW( GetProcessHeap(), 0,
132                                                 MapSL(lpcs16->lpszName) );
133                 else
134                     lpcbtcw32->lpcs->lpszName = (LPCSTR)lpcs16->lpszName;
135
136                 if (HIWORD(lpcs16->lpszClass))
137                     lpcbtcw32->lpcs->lpszClass =
138                         (bA) ? MapSL(lpcs16->lpszClass)
139                              : HEAP_strdupAtoW( GetProcessHeap(), 0,
140                                                 MapSL(lpcs16->lpszClass) );
141                 else
142                     lpcbtcw32->lpcs->lpszClass = (LPCSTR)lpcs16->lpszClass;
143
144                 lpcbtcw32->hwndInsertAfter = WIN_Handle32( lpcbtcw16->hwndInsertAfter );
145
146                 *plParam = (LPARAM)lpcbtcw32;
147                 break;
148             } 
149             case HCBT_ACTIVATE:
150             {
151                 LPCBTACTIVATESTRUCT16 lpcas16 = MapSL(*plParam);
152                 LPCBTACTIVATESTRUCT lpcas32 = HeapAlloc( GetProcessHeap(), 0,
153                                                            sizeof(*lpcas32) );
154                 lpcas32->fMouse = lpcas16->fMouse;
155                 lpcas32->hWndActive = WIN_Handle32(lpcas16->hWndActive);
156                 *plParam = (LPARAM)lpcas32;
157                 break;
158             }
159             case HCBT_CLICKSKIPPED:
160             {
161                 LPMOUSEHOOKSTRUCT16 lpms16 = MapSL(*plParam);
162                 LPMOUSEHOOKSTRUCT lpms32 = HeapAlloc( GetProcessHeap(), 0,
163                                                         sizeof(*lpms32) );
164
165                 CONV_POINT16TO32( &lpms16->pt, &lpms32->pt );
166
167                 /* wHitTestCode may be negative, so convince compiler to do
168                    correct sign extension. Yay. :| */
169                 lpms32->wHitTestCode = (INT)((INT16)lpms16->wHitTestCode);
170
171                 lpms32->dwExtraInfo = lpms16->dwExtraInfo;
172                 lpms32->hwnd = WIN_Handle32( lpms16->hwnd );
173                 *plParam = (LPARAM)lpms32;
174                 break;
175             }
176             case HCBT_MOVESIZE:
177             {
178                 LPRECT16 lprect16 = MapSL(*plParam);
179                 LPRECT lprect32 = HeapAlloc( GetProcessHeap(), 0,
180                                                sizeof(*lprect32) );
181
182                 CONV_RECT16TO32( lprect16, lprect32 );
183                 *plParam = (LPARAM)lprect32;
184                 break;
185             }
186           } 
187           break;
188
189         case WH_MOUSE:
190         {
191             LPMOUSEHOOKSTRUCT16 lpms16 = MapSL(*plParam);
192             LPMOUSEHOOKSTRUCT lpms32 = HeapAlloc( GetProcessHeap(), 0,
193                                                     sizeof(*lpms32) );
194
195             CONV_POINT16TO32( &lpms16->pt, &lpms32->pt );
196
197             /* wHitTestCode may be negative, so convince compiler to do
198                correct sign extension. Yay. :| */
199             lpms32->wHitTestCode = (INT)((INT16)lpms16->wHitTestCode);
200             lpms32->dwExtraInfo = lpms16->dwExtraInfo;
201             lpms32->hwnd = WIN_Handle32(lpms16->hwnd);
202             *plParam = (LPARAM)lpms32;
203             break;
204         } 
205
206         case WH_DEBUG:
207         {
208             LPDEBUGHOOKINFO16 lpdh16 = MapSL(*plParam);
209             LPDEBUGHOOKINFO lpdh32 = HeapAlloc( GetProcessHeap(), 0,
210                                                   sizeof(*lpdh32) );
211
212             lpdh32->idThread = 0;               /* FIXME */
213             lpdh32->idThreadInstaller = 0;      /* FIXME */
214             lpdh32->lParam = lpdh16->lParam;    /* FIXME Check for sign ext */
215             lpdh32->wParam = lpdh16->wParam;
216             lpdh32->code = lpdh16->code;
217           
218             /* do sign extension if it was WH_MSGFILTER */
219             if (*pwParam == 0xffff) *pwParam = WH_MSGFILTER;
220
221             *plParam = (LPARAM)lpdh32;
222             break;
223         }
224
225         case WH_SHELL:
226         case WH_KEYBOARD:
227             break;
228
229         case WH_HARDWARE: 
230         case WH_FOREGROUNDIDLE: 
231         case WH_CALLWNDPROCRET:
232         default:
233             FIXME("\t[%i] 16to32 translation unimplemented\n", id);
234     }
235 }
236
237
238 /***********************************************************************
239  *           HOOK_Map16To32A
240  */
241 static void HOOK_Map16To32A(INT id, INT code, WPARAM *pwParam,
242                             LPARAM *plParam)
243 {
244     HOOK_Map16To32Common( id, code, pwParam, plParam, TRUE );
245 }
246
247
248 /***********************************************************************
249  *           HOOK_Map16To32W
250  */
251 static void HOOK_Map16To32W(INT id, INT code, WPARAM *pwParam,
252                             LPARAM *plParam)
253 {
254     HOOK_Map16To32Common( id, code, pwParam, plParam, FALSE );
255 }
256
257
258 /***********************************************************************
259  *           HOOK_UnMap16To32Common
260  */
261 static void HOOK_UnMap16To32Common(INT id, INT code, WPARAM wParamOrig,
262                                    LPARAM lParamOrig, WPARAM wParam,
263                                    LPARAM lParam, BOOL bA)
264 {
265     switch (id)
266     {
267         case WH_MSGFILTER:
268         case WH_SYSMSGFILTER:
269         case WH_JOURNALRECORD:
270         case WH_JOURNALPLAYBACK:
271       
272             HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
273             break;
274
275         case WH_CALLWNDPROC:
276         {
277             LPCWPSTRUCT   lpcwp32 = (LPCWPSTRUCT)lParam;
278             if (bA) WINPROC_UnmapMsg16To32A( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
279                                              lpcwp32->lParam, 0 );
280             else WINPROC_UnmapMsg16To32W( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
281                                           lpcwp32->lParam, 0 );
282             HeapFree( GetProcessHeap(), 0, lpcwp32 );
283             break;
284         }
285
286         case WH_GETMESSAGE:
287         {
288             LPMSG16 lpmsg16 = MapSL(lParamOrig);
289             STRUCT32_MSG32to16( (LPMSG)lParam, lpmsg16 );
290             HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
291             break;
292         }
293
294         case WH_MOUSE:
295         case WH_DEBUG:
296
297             HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
298             break;
299
300         case WH_CBT:
301             switch (code)
302             {
303               case HCBT_CREATEWND:
304               {
305                 LPCBT_CREATEWNDA lpcbtcw32 = (LPCBT_CREATEWNDA)lParam;
306                 LPCBT_CREATEWND16  lpcbtcw16 = MapSL(lParamOrig);
307
308                 if( !bA )
309                 {
310                    if (HIWORD(lpcbtcw32->lpcs->lpszName))
311                        HeapFree( GetProcessHeap(), 0, (LPWSTR)lpcbtcw32->lpcs->lpszName );
312                    if (HIWORD(lpcbtcw32->lpcs->lpszClass))
313                        HeapFree( GetProcessHeap(), 0, (LPWSTR)lpcbtcw32->lpcs->lpszClass );
314                 }
315
316                 lpcbtcw16->hwndInsertAfter = WIN_Handle16( lpcbtcw32->hwndInsertAfter );
317
318                 HeapFree( GetProcessHeap(), 0, lpcbtcw32->lpcs );
319               } /* fall through */
320
321               case HCBT_ACTIVATE:
322               case HCBT_CLICKSKIPPED:
323               case HCBT_MOVESIZE:
324
325                 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam);
326                 break;
327             }
328             break;
329
330         case WH_SHELL:
331         case WH_KEYBOARD:
332             break;
333
334         case WH_HARDWARE:
335         case WH_FOREGROUNDIDLE:
336         case WH_CALLWNDPROCRET:
337         default:
338             FIXME("\t[%i] skipping unmap\n", id);
339             break;
340     }
341 }
342
343
344 /***********************************************************************
345  *           HOOK_UnMap16To32A
346  */
347 static void HOOK_UnMap16To32A(INT id, INT code, WPARAM wParamOrig,
348                               LPARAM lParamOrig, WPARAM wParam,
349                               LPARAM lParam)
350 {
351     HOOK_UnMap16To32Common( id, code, wParamOrig, lParamOrig, wParam,
352                             lParam, TRUE );
353 }
354
355
356 /***********************************************************************
357  *           HOOK_UnMap16To32W
358  */
359 static void HOOK_UnMap16To32W(INT id, INT code, WPARAM wParamOrig,
360                               LPARAM lParamOrig, WPARAM wParam,
361                               LPARAM lParam)
362 {
363     HOOK_UnMap16To32Common( id, code, wParamOrig, lParamOrig, wParam, 
364                             lParam, FALSE );
365 }
366
367
368 /***********************************************************************
369  *           HOOK_Map32To16Common
370  */
371 static void HOOK_Map32To16Common(INT id, INT code, WPARAM *pwParam,
372                                  LPARAM *plParam, BOOL bA)
373 {
374     switch (id)
375     {
376       case WH_MSGFILTER:
377       case WH_SYSMSGFILTER:
378       case WH_GETMESSAGE:
379       case WH_JOURNALRECORD:
380       {
381           LPMSG lpmsg32 = (LPMSG)*plParam;
382           LPMSG16 lpmsg16 = SEGPTR_NEW( MSG16 );
383
384           STRUCT32_MSG32to16( lpmsg32, lpmsg16 );
385
386           *plParam = (LPARAM)SEGPTR_GET( lpmsg16 );
387           break;
388       }
389
390       case WH_JOURNALPLAYBACK:
391       {
392           LPEVENTMSG lpem32 = (LPEVENTMSG)*plParam;
393           LPEVENTMSG16 lpem16 = SEGPTR_NEW( EVENTMSG16 );
394
395           lpem16->message = lpem32->message;
396           lpem16->paramL  = lpem32->paramL;
397           lpem16->paramH  = lpem32->paramH;
398           lpem16->time    = lpem32->time;
399
400           *plParam = (LPARAM)SEGPTR_GET( lpem16 );
401           break;
402       }
403
404       case WH_CALLWNDPROC:
405       {
406           LPCWPSTRUCT   lpcwp32 = (LPCWPSTRUCT)*plParam;
407           LPCWPSTRUCT16   lpcwp16 = SEGPTR_NEW( CWPSTRUCT16 );
408
409           lpcwp16->hwnd = WIN_Handle16(lpcwp32->hwnd);
410           lpcwp16->lParam = lpcwp32->lParam;
411
412           if (bA) WINPROC_MapMsg32ATo16( lpcwp32->hwnd, lpcwp32->message,
413                                          lpcwp32->wParam, &lpcwp16->message,
414                                          &lpcwp16->wParam, &lpcwp16->lParam );
415           else WINPROC_MapMsg32WTo16( lpcwp32->hwnd, lpcwp32->message,
416                                       lpcwp32->wParam, &lpcwp16->message,
417                                       &lpcwp16->wParam, &lpcwp16->lParam );
418           *plParam = (LPARAM)SEGPTR_GET( lpcwp16 );
419           break;
420       }
421
422       case WH_CBT:
423         switch (code)
424         {
425           case HCBT_ACTIVATE:
426           {
427               LPCBTACTIVATESTRUCT lpcas32 = (LPCBTACTIVATESTRUCT)*plParam;
428               LPCBTACTIVATESTRUCT16 lpcas16 =SEGPTR_NEW( CBTACTIVATESTRUCT16 );
429
430               lpcas16->fMouse     = lpcas32->fMouse;
431               lpcas16->hWndActive = WIN_Handle16( lpcas32->hWndActive );
432
433               *plParam = (LPARAM)SEGPTR_GET( lpcas16 );
434               break;
435           }
436               
437           case HCBT_CLICKSKIPPED:
438           {
439               LPMOUSEHOOKSTRUCT lpms32 = (LPMOUSEHOOKSTRUCT)*plParam;
440               LPMOUSEHOOKSTRUCT16 lpms16 = SEGPTR_NEW( MOUSEHOOKSTRUCT16 );
441
442               CONV_POINT32TO16( &lpms32->pt, &lpms16->pt );
443
444               lpms16->hwnd         = WIN_Handle16( lpms32->hwnd );
445               lpms16->wHitTestCode = lpms32->wHitTestCode;
446               lpms16->dwExtraInfo  = lpms32->dwExtraInfo;
447
448               *plParam = (LPARAM)SEGPTR_GET( lpms16 );
449               break;
450           }
451
452           case HCBT_MOVESIZE:
453           {
454               LPRECT lprect32 = (LPRECT)*plParam;
455               LPRECT16 lprect16 = SEGPTR_NEW( RECT16 );
456
457               CONV_RECT32TO16( lprect32, lprect16 );
458
459               *plParam = (LPARAM)SEGPTR_GET( lprect16 );
460               break;
461           }
462         }
463         break;
464
465       case WH_MOUSE:
466       {
467           LPMOUSEHOOKSTRUCT lpms32 = (LPMOUSEHOOKSTRUCT)*plParam;
468           LPMOUSEHOOKSTRUCT16 lpms16 = SEGPTR_NEW( MOUSEHOOKSTRUCT16 );
469
470           CONV_POINT32TO16( &lpms32->pt, &lpms16->pt );
471
472           lpms16->hwnd = WIN_Handle16( lpms32->hwnd );
473           lpms16->wHitTestCode = lpms32->wHitTestCode;
474           lpms16->dwExtraInfo = lpms32->dwExtraInfo;
475
476           *plParam = (LPARAM)SEGPTR_GET( lpms16 );
477           break;
478       }
479
480       case WH_DEBUG:
481       {
482           LPDEBUGHOOKINFO lpdh32 = (LPDEBUGHOOKINFO)*plParam;
483           LPDEBUGHOOKINFO16 lpdh16 = SEGPTR_NEW( DEBUGHOOKINFO16 );
484
485           lpdh16->hModuleHook = 0;      /* FIXME */
486           lpdh16->reserved    = 0;
487           lpdh16->lParam      = lpdh32->lParam;
488           lpdh16->wParam      = lpdh32->wParam;
489           lpdh16->code        = lpdh32->code;
490           
491           *plParam = (LPARAM)SEGPTR_GET( lpdh16 );
492           break;
493       }
494
495       case WH_SHELL:
496       case WH_KEYBOARD:
497         break;
498
499       case WH_HARDWARE:
500       case WH_FOREGROUNDIDLE:
501       case WH_CALLWNDPROCRET:
502       default:
503         FIXME("\t[%i] 32to16 translation unimplemented\n", id);
504     }
505 }
506
507
508 /***********************************************************************
509  *           HOOK_Map32ATo16
510  */
511 static void HOOK_Map32ATo16(INT id, INT code, WPARAM *pwParam,
512                             LPARAM *plParam)
513 {
514     if (id == WH_CBT && code == HCBT_CREATEWND)
515     {
516         LPCBT_CREATEWNDA lpcbtcw32 = (LPCBT_CREATEWNDA)*plParam;
517         LPCBT_CREATEWND16 lpcbtcw16 = SEGPTR_NEW( CBT_CREATEWND16 );
518         LPCREATESTRUCT16 lpcs16 = SEGPTR_NEW( CREATESTRUCT16 );
519
520         lpcbtcw16->lpcs = (LPCREATESTRUCT16)SEGPTR_GET( lpcs16 );
521         STRUCT32_CREATESTRUCT32Ato16( lpcbtcw32->lpcs, lpcs16 );
522
523         if (HIWORD(lpcbtcw32->lpcs->lpszName))
524           lpcs16->lpszName =
525             SEGPTR_GET( SEGPTR_STRDUP( lpcbtcw32->lpcs->lpszName ) );
526         else
527           lpcs16->lpszName = (SEGPTR)lpcbtcw32->lpcs->lpszName;
528
529         if (HIWORD(lpcbtcw32->lpcs->lpszClass))
530           lpcs16->lpszClass =
531             SEGPTR_GET( SEGPTR_STRDUP( lpcbtcw32->lpcs->lpszClass ) );
532         else
533           lpcs16->lpszClass = (SEGPTR)lpcbtcw32->lpcs->lpszClass;
534
535         lpcbtcw16->hwndInsertAfter = WIN_Handle16( lpcbtcw32->hwndInsertAfter );
536
537         *plParam = (LPARAM)SEGPTR_GET( lpcbtcw16 );
538     }
539     else HOOK_Map32To16Common(id, code, pwParam, plParam, TRUE);
540 }
541
542
543 /***********************************************************************
544  *           HOOK_Map32WTo16
545  */
546 static void HOOK_Map32WTo16(INT id, INT code, WPARAM *pwParam,
547                             LPARAM *plParam)
548 {
549     if (id == WH_CBT && code == HCBT_CREATEWND)
550     {
551         LPSTR name, cls;
552         LPCBT_CREATEWNDW lpcbtcw32 = (LPCBT_CREATEWNDW)*plParam;
553         LPCBT_CREATEWND16 lpcbtcw16 = SEGPTR_NEW( CBT_CREATEWND16 );
554         LPCREATESTRUCT16 lpcs16 = SEGPTR_NEW( CREATESTRUCT16 );
555
556         lpcbtcw16->lpcs = (LPCREATESTRUCT16)SEGPTR_GET( lpcs16 );
557         STRUCT32_CREATESTRUCT32Ato16( (LPCREATESTRUCTA)lpcbtcw32->lpcs,
558                                       lpcs16 );
559
560         name = SEGPTR_STRDUP_WtoA( lpcbtcw32->lpcs->lpszName );
561         cls  = SEGPTR_STRDUP_WtoA( lpcbtcw32->lpcs->lpszClass );
562         lpcs16->lpszName  = SEGPTR_GET( name );
563         lpcs16->lpszClass = SEGPTR_GET( cls );
564         lpcbtcw16->hwndInsertAfter = WIN_Handle16( lpcbtcw32->hwndInsertAfter );
565
566         *plParam = (LPARAM)SEGPTR_GET( lpcbtcw16 );
567     }
568     else HOOK_Map32To16Common(id, code, pwParam, plParam, FALSE);
569 }
570
571
572 /***********************************************************************
573  *           HOOK_UnMap32To16Common
574  */
575 static void HOOK_UnMap32To16Common(INT id, INT code, WPARAM wParamOrig,
576                                    LPARAM lParamOrig, WPARAM wParam,
577                                    LPARAM lParam, BOOL bA)
578 {
579     switch (id)
580     {
581       case WH_MSGFILTER:
582       case WH_SYSMSGFILTER:
583       case WH_JOURNALRECORD:
584       case WH_JOURNALPLAYBACK:
585       case WH_MOUSE:
586       case WH_DEBUG:
587         SEGPTR_FREE( MapSL(lParam) );
588         break;
589
590       case WH_CALLWNDPROC:
591       {
592           LPCWPSTRUCT16   lpcwp16 = MapSL(lParam);
593           LPCWPSTRUCT   lpcwp32 = (LPCWPSTRUCT)lParamOrig;
594           MSGPARAM16      mp16;
595
596           mp16.wParam = lpcwp16->wParam;
597           mp16.lParam = lpcwp16->lParam;
598           mp16.lResult = 0;
599
600           if (bA) WINPROC_UnmapMsg32ATo16( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
601                                            lpcwp32->lParam, &mp16 );
602           else WINPROC_UnmapMsg32WTo16( lpcwp32->hwnd,lpcwp32->message, lpcwp32->wParam,
603                                         lpcwp32->lParam, &mp16 );
604           SEGPTR_FREE( MapSL(lParam) );
605           break;
606       }
607
608       case WH_GETMESSAGE:
609       {
610           LPMSG lpmsg32 = (LPMSG)lParamOrig;
611
612           STRUCT32_MSG16to32( MapSL(lParam), lpmsg32 );
613           SEGPTR_FREE( MapSL(lParam) );
614           break;
615       }
616
617       case WH_CBT:
618         switch (code)
619         {
620           case HCBT_CREATEWND:
621           {
622                LPCBT_CREATEWNDA lpcbtcw32 = (LPCBT_CREATEWNDA)(lParamOrig);
623                LPCBT_CREATEWND16 lpcbtcw16 = MapSL(lParam);
624                LPCREATESTRUCT16  lpcs16 = MapSL((SEGPTR)lpcbtcw16->lpcs);
625
626                if (HIWORD(lpcs16->lpszName))
627                    SEGPTR_FREE( MapSL(lpcs16->lpszName) );
628
629                if (HIWORD(lpcs16->lpszClass))
630                    SEGPTR_FREE( MapSL(lpcs16->lpszClass) );
631
632                lpcbtcw32->hwndInsertAfter = WIN_Handle32( lpcbtcw16->hwndInsertAfter );
633
634                SEGPTR_FREE( lpcs16 );
635           } /* fall through */
636
637           case HCBT_ACTIVATE:
638           case HCBT_CLICKSKIPPED:
639           case HCBT_MOVESIZE:
640
641                SEGPTR_FREE( MapSL(lParam) );
642                break;
643         }
644         break;
645
646       case WH_SHELL:
647       case WH_KEYBOARD:
648         break;
649
650       case WH_HARDWARE:
651       case WH_FOREGROUNDIDLE:
652       case WH_CALLWNDPROCRET:
653       default:
654         FIXME("\t[%i] skipping unmap\n", id);
655     }
656 }
657
658
659 /***********************************************************************
660  *           HOOK_UnMap32ATo16
661  */
662 static void HOOK_UnMap32ATo16(INT id, INT code, WPARAM wParamOrig,
663                               LPARAM lParamOrig, WPARAM wParam,
664                               LPARAM lParam)
665 {
666     HOOK_UnMap32To16Common( id, code, wParamOrig, lParamOrig, wParam,
667                             lParam, TRUE );
668 }
669
670
671 /***********************************************************************
672  *           HOOK_UnMap32WTo16
673  */
674 static void HOOK_UnMap32WTo16(INT id, INT code, WPARAM wParamOrig,
675                               LPARAM lParamOrig, WPARAM wParam,
676                               LPARAM lParam)
677 {
678     HOOK_UnMap32To16Common( id, code, wParamOrig, lParamOrig, wParam,
679                             lParam, FALSE );
680 }
681
682
683 /***********************************************************************
684  *           HOOK_Map32ATo32W
685  */
686 static void HOOK_Map32ATo32W(INT id, INT code, WPARAM *pwParam,
687                              LPARAM *plParam)
688 {
689     if (id == WH_CBT && code == HCBT_CREATEWND)
690     {
691         LPCBT_CREATEWNDA lpcbtcwA = (LPCBT_CREATEWNDA)*plParam;
692         LPCBT_CREATEWNDW lpcbtcwW = HeapAlloc( GetProcessHeap(), 0,
693                                                  sizeof(*lpcbtcwW) );
694         lpcbtcwW->lpcs = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpcbtcwW->lpcs) );
695
696         lpcbtcwW->hwndInsertAfter = lpcbtcwA->hwndInsertAfter;
697         *lpcbtcwW->lpcs = *(LPCREATESTRUCTW)lpcbtcwA->lpcs;
698
699         if (HIWORD(lpcbtcwA->lpcs->lpszName))
700         {
701             lpcbtcwW->lpcs->lpszName = HEAP_strdupAtoW( GetProcessHeap(), 0,
702                                                     lpcbtcwA->lpcs->lpszName );
703         }
704         else
705           lpcbtcwW->lpcs->lpszName = (LPWSTR)lpcbtcwA->lpcs->lpszName;
706
707         if (HIWORD(lpcbtcwA->lpcs->lpszClass))
708         {
709             lpcbtcwW->lpcs->lpszClass = HEAP_strdupAtoW( GetProcessHeap(), 0,
710                                                    lpcbtcwA->lpcs->lpszClass );
711         }
712         else
713           lpcbtcwW->lpcs->lpszClass = (LPCWSTR)lpcbtcwA->lpcs->lpszClass;
714         *plParam = (LPARAM)lpcbtcwW;
715     }
716     return;
717 }
718
719
720 /***********************************************************************
721  *           HOOK_UnMap32ATo32W
722  */
723 static void HOOK_UnMap32ATo32W(INT id, INT code, WPARAM wParamOrig,
724                                LPARAM lParamOrig, WPARAM wParam,
725                                LPARAM lParam)
726 {
727     if (id == WH_CBT && code == HCBT_CREATEWND)
728     {
729         LPCBT_CREATEWNDW lpcbtcwW = (LPCBT_CREATEWNDW)lParam;
730         if (HIWORD(lpcbtcwW->lpcs->lpszName))
731             HeapFree( GetProcessHeap(), 0, (LPWSTR)lpcbtcwW->lpcs->lpszName );
732         if (HIWORD(lpcbtcwW->lpcs->lpszClass))
733             HeapFree( GetProcessHeap(), 0, (LPWSTR)lpcbtcwW->lpcs->lpszClass );
734         HeapFree( GetProcessHeap(), 0, lpcbtcwW->lpcs );
735         HeapFree( GetProcessHeap(), 0, lpcbtcwW );
736     }
737     return;
738 }
739
740
741 /***********************************************************************
742  *           HOOK_Map32WTo32A
743  */
744 static void HOOK_Map32WTo32A(INT id, INT code, WPARAM *pwParam,
745                              LPARAM *plParam)
746 {
747     if (id == WH_CBT && code == HCBT_CREATEWND)
748     {
749         LPCBT_CREATEWNDW lpcbtcwW = (LPCBT_CREATEWNDW)*plParam;
750         LPCBT_CREATEWNDA lpcbtcwA = HeapAlloc( GetProcessHeap(), 0,
751                                                  sizeof(*lpcbtcwA) );
752         lpcbtcwA->lpcs = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpcbtcwA->lpcs) );
753
754         lpcbtcwA->hwndInsertAfter = lpcbtcwW->hwndInsertAfter;
755         *lpcbtcwA->lpcs = *(LPCREATESTRUCTA)lpcbtcwW->lpcs;
756
757         if (HIWORD(lpcbtcwW->lpcs->lpszName))
758           lpcbtcwA->lpcs->lpszName = HEAP_strdupWtoA( GetProcessHeap(), 0,
759                                                     lpcbtcwW->lpcs->lpszName );
760         else
761           lpcbtcwA->lpcs->lpszName = (LPSTR)lpcbtcwW->lpcs->lpszName;
762
763         if (HIWORD(lpcbtcwW->lpcs->lpszClass))
764           lpcbtcwA->lpcs->lpszClass = HEAP_strdupWtoA( GetProcessHeap(), 0,
765                                                    lpcbtcwW->lpcs->lpszClass );
766         else
767           lpcbtcwA->lpcs->lpszClass = (LPSTR)lpcbtcwW->lpcs->lpszClass;
768         *plParam = (LPARAM)lpcbtcwA;
769     }
770     return;
771 }
772
773
774 /***********************************************************************
775  *           HOOK_UnMap32WTo32A
776  */
777 static void HOOK_UnMap32WTo32A(INT id, INT code, WPARAM wParamOrig,
778                                LPARAM lParamOrig, WPARAM wParam,
779                                LPARAM lParam)
780 {
781     if (id == WH_CBT && code == HCBT_CREATEWND)
782     {
783         LPCBT_CREATEWNDA lpcbtcwA = (LPCBT_CREATEWNDA)lParam;
784         if (HIWORD(lpcbtcwA->lpcs->lpszName))
785             HeapFree( GetProcessHeap(), 0, (LPSTR)lpcbtcwA->lpcs->lpszName );
786         if (HIWORD(lpcbtcwA->lpcs->lpszClass))
787             HeapFree( GetProcessHeap(), 0, (LPSTR)lpcbtcwA->lpcs->lpszClass );
788         HeapFree( GetProcessHeap(), 0, lpcbtcwA->lpcs );
789         HeapFree( GetProcessHeap(), 0, lpcbtcwA );
790     }
791     return;
792 }
793
794
795 /***********************************************************************
796  *           Map Function Tables
797  */
798 static const HOOK_MapFunc HOOK_MapFuncs[3][3] = 
799 {
800     { NULL,            HOOK_Map16To32A,  HOOK_Map16To32W },
801     { HOOK_Map32ATo16, NULL,             HOOK_Map32ATo32W },
802     { HOOK_Map32WTo16, HOOK_Map32WTo32A, NULL }
803 };
804
805 static const HOOK_UnMapFunc HOOK_UnMapFuncs[3][3] = 
806 {
807     { NULL,              HOOK_UnMap16To32A,  HOOK_UnMap16To32W },
808     { HOOK_UnMap32ATo16, NULL,               HOOK_UnMap32ATo32W },
809     { HOOK_UnMap32WTo16, HOOK_UnMap32WTo32A, NULL }
810 };
811
812
813 /***********************************************************************
814  *           Internal Functions
815  */
816
817 /***********************************************************************
818  *           HOOK_GetNextHook
819  *
820  * Get the next hook of a given hook.
821  */
822 static HANDLE16 HOOK_GetNextHook( HANDLE16 hook )
823 {
824     HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR( hook );
825
826     if (!data || !hook) return 0;
827     if (data->next) return data->next;
828     if (!data->ownerQueue) return 0;  /* Already system hook */
829
830     /* Now start enumerating the system hooks */
831     return HOOK_systemHooks[data->id - WH_MINHOOK];
832 }
833
834
835 /***********************************************************************
836  *           HOOK_GetHook
837  *
838  * Get the first hook for a given type.
839  */
840 static HANDLE16 HOOK_GetHook( INT16 id )
841 {
842     MESSAGEQUEUE *queue;
843     HANDLE16 hook = 0;
844
845     if ((queue = QUEUE_Current()) != NULL)
846         hook = queue->hooks[id - WH_MINHOOK];
847     if (!hook) hook = HOOK_systemHooks[id - WH_MINHOOK];
848     return hook;
849 }
850
851
852 /***********************************************************************
853  *           HOOK_SetHook
854  *
855  * Install a given hook.
856  */
857 /* ### start build ### */
858 extern LONG CALLBACK HOOK_CallTo16_long_wwl(FARPROC16,WORD,WORD,LONG);
859 /* ### stop build ### */
860 static HHOOK HOOK_SetHook( INT16 id, LPVOID proc, INT type,
861                            HMODULE16 hModule, DWORD dwThreadId )
862 {
863     HOOKDATA *data;
864     HANDLE16 handle;
865     HQUEUE16 hQueue = 0;
866
867     if ((id < WH_MINHOOK) || (id > WH_MAXHOOK)) return 0;
868
869     TRACE("Setting hook %d: %08x %04x %08lx\n",
870                   id, (UINT)proc, hModule, dwThreadId );
871
872     /* Create task queue if none present */
873     InitThreadInput16( 0, 0 );
874
875     if (id == WH_JOURNALPLAYBACK) EnableHardwareInput16(FALSE);
876
877     if (dwThreadId)  /* Task-specific hook */
878     {
879         if ((id == WH_JOURNALRECORD) || (id == WH_JOURNALPLAYBACK) ||
880             (id == WH_SYSMSGFILTER)) return 0;  /* System-only hooks */
881         if (!(hQueue = GetThreadQueue16( dwThreadId )))
882             return 0;
883     }
884
885     /* Create the hook structure */
886
887     if (!(handle = USER_HEAP_ALLOC( sizeof(HOOKDATA) ))) return 0;
888     data = (HOOKDATA *) USER_HEAP_LIN_ADDR( handle );
889     data->proc        = proc;
890     data->id          = id;
891     data->ownerQueue  = hQueue;
892     data->ownerModule = hModule;
893     data->flags       = type;
894
895     /* Insert it in the correct linked list */
896
897     if (hQueue)
898     {
899         MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue );
900         data->next = queue->hooks[id - WH_MINHOOK];
901         queue->hooks[id - WH_MINHOOK] = handle;
902         QUEUE_Unlock( queue );
903     }
904     else
905     {
906         data->next = HOOK_systemHooks[id - WH_MINHOOK];
907         HOOK_systemHooks[id - WH_MINHOOK] = handle;
908     }
909     TRACE("Setting hook %d: ret=%04x [next=%04x]\n", 
910                            id, handle, data->next );
911
912     return (HHOOK)( handle? MAKELONG( handle, HOOK_MAGIC ) : 0 );
913 }
914
915
916 /***********************************************************************
917  *           HOOK_RemoveHook
918  *
919  * Remove a hook from the list.
920  */
921 static BOOL HOOK_RemoveHook( HANDLE16 hook )
922 {
923     HOOKDATA *data;
924     HANDLE16 *prevHook;
925
926     TRACE("Removing hook %04x\n", hook );
927
928     if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook))) return FALSE;
929     if (data->flags & HOOK_INUSE)
930     {
931         /* Mark it for deletion later on */
932         WARN("Hook still running, deletion delayed\n" );
933         data->proc = (HOOKPROC)0;
934         return TRUE;
935     }
936
937     if (data->id == WH_JOURNALPLAYBACK) EnableHardwareInput16(TRUE);
938      
939     /* Remove it from the linked list */
940
941     if (data->ownerQueue)
942     {
943         MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( data->ownerQueue );
944         if (!queue) return FALSE;
945         prevHook = &queue->hooks[data->id - WH_MINHOOK];
946         QUEUE_Unlock( queue );
947     }
948     else prevHook = &HOOK_systemHooks[data->id - WH_MINHOOK];
949
950     while (*prevHook && *prevHook != hook)
951         prevHook = &((HOOKDATA *)USER_HEAP_LIN_ADDR(*prevHook))->next;
952
953     if (!*prevHook) return FALSE;
954     *prevHook = data->next;
955
956     USER_HEAP_FREE( hook );
957     return TRUE;
958 }
959
960
961 /***********************************************************************
962  *           HOOK_FindValidHook
963  */
964 static HANDLE16 HOOK_FindValidHook( HANDLE16 hook )
965 {
966     HOOKDATA *data;
967
968     for (;;)
969     {
970         if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook))) return 0;
971         if (data->proc) return hook;
972         hook = data->next;
973     }
974 }
975
976
977 /***********************************************************************
978  *           HOOK_CallHook
979  *
980  * Call a hook procedure.
981  */
982 static LRESULT HOOK_CallHook( HANDLE16 hook, INT fromtype, INT code,
983                               WPARAM wParam, LPARAM lParam )
984 {
985     MESSAGEQUEUE *queue;
986     HANDLE16 prevHook;
987     HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
988     LRESULT ret;
989     int iWndsLocks;
990
991     WPARAM wParamOrig = wParam;
992     LPARAM lParamOrig = lParam;
993     HOOK_MapFunc MapFunc;
994     HOOK_UnMapFunc UnMapFunc;
995
996     MapFunc = HOOK_MapFuncs[fromtype][data->flags & HOOK_MAPTYPE];
997     UnMapFunc = HOOK_UnMapFuncs[fromtype][data->flags & HOOK_MAPTYPE];
998
999     if (MapFunc)
1000       MapFunc( data->id, code, &wParam, &lParam );
1001
1002     /* Now call it */
1003
1004     if (!(queue = QUEUE_Current())) return 0;
1005     prevHook = queue->hCurHook;
1006     queue->hCurHook = hook;
1007     data->flags |= HOOK_INUSE;
1008
1009     TRACE("Calling hook %04x: %d %08x %08lx\n",
1010                   hook, code, wParam, lParam );
1011
1012     /* Suspend window structure locks before calling user code */
1013     iWndsLocks = WIN_SuspendWndsLock();
1014
1015     if ((data->flags & HOOK_MAPTYPE) == HOOK_WIN16)
1016     {
1017         ret = HOOK_CallTo16_long_wwl( data->proc, code, wParam, lParam );
1018         /* Grrr. While the hook procedure is supposed to have an LRESULT return
1019            value even in Win16, it seems that for those hook types where the 
1020            return value is interpreted as BOOL, Windows doesn't actually check
1021            the HIWORD ...  Some buggy Win16 programs, notably WINFILE, rely on
1022            that, because they neglect to clear DX ... */
1023         if (data->id != WH_JOURNALPLAYBACK) ret = LOWORD( ret );
1024     }
1025     else
1026         ret = data->proc(code, wParam, lParam);
1027
1028     WIN_RestoreWndsLock(iWndsLocks);
1029
1030     TRACE("Ret hook %04x = %08lx\n", hook, ret );
1031
1032     data->flags &= ~HOOK_INUSE;
1033     queue->hCurHook = prevHook;
1034
1035     if (UnMapFunc)
1036       UnMapFunc( data->id, code, wParamOrig, lParamOrig, wParam, lParam );
1037
1038     if (!data->proc) HOOK_RemoveHook( hook );
1039
1040     return ret;
1041 }
1042
1043 /***********************************************************************
1044  *           Exported Functions & APIs
1045  */
1046
1047 /***********************************************************************
1048  *           HOOK_IsHooked
1049  *
1050  * Replacement for calling HOOK_GetHook from other modules.
1051  */
1052 BOOL HOOK_IsHooked( INT16 id )
1053 {
1054     return HOOK_GetHook( id ) != 0;
1055 }
1056
1057
1058 /***********************************************************************
1059  *           HOOK_CallHooks16
1060  *
1061  * Call a hook chain.
1062  */
1063 LRESULT HOOK_CallHooks16( INT16 id, INT16 code, WPARAM16 wParam,
1064                           LPARAM lParam )
1065 {
1066     HANDLE16 hook; 
1067
1068     if (!(hook = HOOK_GetHook( id ))) return 0;
1069     if (!(hook = HOOK_FindValidHook(hook))) return 0;
1070     return HOOK_CallHook( hook, HOOK_WIN16, code, wParam, lParam );
1071 }
1072
1073 /***********************************************************************
1074  *           HOOK_CallHooksA
1075  *
1076  * Call a hook chain.
1077  */
1078 LRESULT HOOK_CallHooksA( INT id, INT code, WPARAM wParam,
1079                            LPARAM lParam )
1080 {
1081     HANDLE16 hook; 
1082
1083     if (!(hook = HOOK_GetHook( id ))) return 0;
1084     if (!(hook = HOOK_FindValidHook(hook))) return 0;
1085     return HOOK_CallHook( hook, HOOK_WIN32A, code, wParam, lParam );
1086 }
1087
1088 /***********************************************************************
1089  *           HOOK_CallHooksW
1090  *
1091  * Call a hook chain.
1092  */
1093 LRESULT HOOK_CallHooksW( INT id, INT code, WPARAM wParam,
1094                            LPARAM lParam )
1095 {
1096     HANDLE16 hook; 
1097
1098     if (!(hook = HOOK_GetHook( id ))) return 0;
1099     if (!(hook = HOOK_FindValidHook(hook))) return 0;
1100     return HOOK_CallHook( hook, HOOK_WIN32W, code, wParam,
1101                           lParam );
1102 }
1103
1104
1105 /***********************************************************************
1106  *           HOOK_FreeModuleHooks
1107  */
1108 void HOOK_FreeModuleHooks( HMODULE16 hModule )
1109 {
1110  /* remove all system hooks registered by this module */
1111
1112   HOOKDATA*     hptr;
1113   HHOOK         hook, next;
1114   int           id;
1115
1116   for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
1117     {
1118        hook = HOOK_systemHooks[id - WH_MINHOOK];
1119        while( hook )
1120           if( (hptr = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook)) )
1121             {
1122               next = hptr->next;
1123               if( hptr->ownerModule == hModule )
1124                 {
1125                   hptr->flags &= HOOK_MAPTYPE;
1126                   HOOK_RemoveHook(hook);
1127                 }
1128               hook = next;
1129             }
1130           else hook = 0;
1131     }
1132 }
1133
1134 /***********************************************************************
1135  *           HOOK_FreeQueueHooks
1136  */
1137 void HOOK_FreeQueueHooks(void)
1138 {
1139   /* remove all hooks registered by the current queue */
1140
1141   HOOKDATA*     hptr = NULL;
1142   HHOOK         hook, next;
1143   int           id;
1144
1145   for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
1146     {
1147        hook = HOOK_GetHook( id );
1148        while( hook )
1149         {
1150           next = HOOK_GetNextHook(hook);
1151
1152           hptr = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
1153           if( hptr && hptr->ownerQueue )
1154             {
1155               hptr->flags &= HOOK_MAPTYPE;
1156               HOOK_RemoveHook(hook);
1157             }
1158           hook = next;
1159         }
1160     }
1161 }
1162
1163
1164 /***********************************************************************
1165  *              SetWindowsHook (USER.121)
1166  */
1167 FARPROC16 WINAPI SetWindowsHook16( INT16 id, HOOKPROC16 proc )
1168 {
1169     HINSTANCE16 hInst = FarGetOwner16( HIWORD(proc) );
1170
1171     /* WH_MSGFILTER is the only task-specific hook for SetWindowsHook() */
1172     HTASK16 hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
1173
1174     return (FARPROC16)SetWindowsHookEx16( id, proc, hInst, hTask );
1175 }
1176
1177 /***********************************************************************
1178  *              SetWindowsHookA (USER32.@)
1179  */
1180 HHOOK WINAPI SetWindowsHookA( INT id, HOOKPROC proc )
1181 {
1182     return SetWindowsHookExA( id, proc, 0, GetCurrentThreadId() );
1183 }
1184
1185 /***********************************************************************
1186  *              SetWindowsHookW (USER32.@)
1187  */
1188 HHOOK WINAPI SetWindowsHookW( INT id, HOOKPROC proc )
1189 {
1190     return SetWindowsHookExW( id, proc, 0, GetCurrentThreadId() );
1191 }
1192
1193
1194 /***********************************************************************
1195  *              SetWindowsHookEx (USER.291)
1196  *              SetWindowsHookEx16 (USER32.@)
1197  */
1198 HHOOK WINAPI SetWindowsHookEx16( INT16 id, HOOKPROC16 proc, HINSTANCE16 hInst,
1199                                  HTASK16 hTask )
1200 {
1201     if (id == WH_DEBUG)
1202     {
1203         FIXME("WH_DEBUG is broken in 16-bit Windows.\n");
1204         return 0;
1205     }
1206     return HOOK_SetHook( id, proc, HOOK_WIN16, GetExePtr(hInst), (DWORD)hTask );
1207 }
1208
1209 /***********************************************************************
1210  *              SetWindowsHookExA (USER32.@)
1211  */
1212 HHOOK WINAPI SetWindowsHookExA( INT id, HOOKPROC proc, HINSTANCE hInst,
1213                                   DWORD dwThreadId )
1214 {
1215     return HOOK_SetHook( id, proc, HOOK_WIN32A, MapHModuleLS(hInst), dwThreadId );
1216 }
1217
1218 /***********************************************************************
1219  *              SetWindowsHookExW (USER32.@)
1220  */
1221 HHOOK WINAPI SetWindowsHookExW( INT id, HOOKPROC proc, HINSTANCE hInst,
1222                                   DWORD dwThreadId )
1223 {
1224     return HOOK_SetHook( id, proc, HOOK_WIN32W, MapHModuleLS(hInst), dwThreadId );
1225 }
1226
1227
1228 /***********************************************************************
1229  *              UnhookWindowsHook (USER.234)
1230  */
1231 BOOL16 WINAPI UnhookWindowsHook16( INT16 id, HOOKPROC16 proc )
1232 {
1233     return UnhookWindowsHook( id, (HOOKPROC)proc );
1234 }
1235
1236 /***********************************************************************
1237  *              UnhookWindowsHook (USER32.@)
1238  */
1239 BOOL WINAPI UnhookWindowsHook( INT id, HOOKPROC proc )
1240 {
1241     HANDLE16 hook = HOOK_GetHook( id );
1242
1243     TRACE("%d %08lx\n", id, (DWORD)proc );
1244
1245     while (hook)
1246     {
1247         HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
1248         if (data->proc == proc) break;
1249         hook = HOOK_GetNextHook( hook );
1250     }
1251     if (!hook) return FALSE;
1252     return HOOK_RemoveHook( hook );
1253 }
1254
1255
1256 /***********************************************************************
1257  *              UnhookWindowsHookEx (USER.292)
1258  */
1259 BOOL16 WINAPI UnhookWindowsHookEx16( HHOOK hhook )
1260 {
1261     return UnhookWindowsHookEx( hhook );
1262 }
1263
1264 /***********************************************************************
1265  *              UnhookWindowsHookEx (USER32.@)
1266  */
1267 BOOL WINAPI UnhookWindowsHookEx( HHOOK hhook )
1268 {
1269     if (HIWORD(hhook) != HOOK_MAGIC) return FALSE;  /* Not a new format hook */
1270     return HOOK_RemoveHook( LOWORD(hhook) );
1271 }
1272
1273
1274 /***********************************************************************
1275  *              CallNextHookEx (USER.293)
1276  *              CallNextHookEx16 (USER32.@)
1277  *
1278  * I wouldn't have separated this into 16 and 32 bit versions, but I
1279  * need a way to figure out if I need to do a mapping or not.
1280  */
1281 LRESULT WINAPI CallNextHookEx16( HHOOK hhook, INT16 code, WPARAM16 wParam,
1282                                  LPARAM lParam )
1283 {
1284     HANDLE16 next;
1285
1286     if (HIWORD(hhook) != HOOK_MAGIC) return 0;  /* Not a new format hook */
1287     if (!(next = HOOK_GetNextHook( LOWORD(hhook) ))) return 0;
1288
1289     return HOOK_CallHook( next, HOOK_WIN16, code, wParam, lParam );
1290 }
1291
1292
1293 /***********************************************************************
1294  *              CallNextHookEx (USER32.@)
1295  *
1296  * There aren't ANSI and UNICODE versions of this.
1297  */
1298 LRESULT WINAPI CallNextHookEx( HHOOK hhook, INT code, WPARAM wParam,
1299                                  LPARAM lParam )
1300 {
1301     HANDLE16 next;
1302     INT fromtype;       /* figure out Ansi/Unicode */
1303     HOOKDATA *oldhook;
1304
1305     if (HIWORD(hhook) != HOOK_MAGIC) return 0;  /* Not a new format hook */
1306     if (!(next = HOOK_GetNextHook( LOWORD(hhook) ))) return 0;
1307
1308     oldhook = (HOOKDATA *)USER_HEAP_LIN_ADDR( LOWORD(hhook) );
1309     fromtype = oldhook->flags & HOOK_MAPTYPE;
1310
1311     if (fromtype == HOOK_WIN16)
1312       ERR("called from 16bit hook!\n");
1313
1314     return HOOK_CallHook( next, fromtype, code, wParam, lParam );
1315 }
1316
1317
1318 /***********************************************************************
1319  *              DefHookProc (USER.235)
1320  */
1321 LRESULT WINAPI DefHookProc16( INT16 code, WPARAM16 wParam, LPARAM lParam,
1322                               HHOOK *hhook )
1323 {
1324     /* Note: the *hhook parameter is never used, since we rely on the
1325      * current hook value from the task queue to find the next hook. */
1326     MESSAGEQUEUE *queue;
1327
1328     if (!(queue = QUEUE_Current())) return 0;
1329     return CallNextHookEx16( queue->hCurHook, code, wParam, lParam );
1330 }
1331
1332
1333 /***********************************************************************
1334  *              CallMsgFilter (USER.123)
1335  */
1336 BOOL16 WINAPI CallMsgFilter16( SEGPTR msg, INT16 code )
1337 {
1338     if (GetSysModalWindow16()) return FALSE;
1339     if (HOOK_CallHooks16( WH_SYSMSGFILTER, code, 0, (LPARAM)msg )) return TRUE;
1340     return HOOK_CallHooks16( WH_MSGFILTER, code, 0, (LPARAM)msg );
1341 }
1342
1343
1344 /***********************************************************************
1345  *              CallMsgFilter32 (USER.823)
1346  */
1347 BOOL16 WINAPI CallMsgFilter32_16( SEGPTR msg16_32, INT16 code, BOOL16 wHaveParamHigh )
1348 {
1349     MSG32_16 *lpmsg16_32 = MapSL(msg16_32);
1350
1351     if (wHaveParamHigh == FALSE)
1352     {
1353         lpmsg16_32->wParamHigh = 0;
1354         /* WARNING: msg16_32->msg has to be the first variable in the struct */ 
1355         return CallMsgFilter16(msg16_32, code);
1356     }
1357     else
1358     {
1359         MSG msg32;
1360         BOOL16 ret;
1361
1362         msg32.hwnd      = WIN_Handle32( lpmsg16_32->msg.hwnd );
1363         msg32.message   = lpmsg16_32->msg.message;
1364         msg32.wParam    = MAKELONG(lpmsg16_32->msg.wParam, lpmsg16_32->wParamHigh);
1365         msg32.lParam    = lpmsg16_32->msg.lParam;
1366         msg32.time      = lpmsg16_32->msg.time;
1367         msg32.pt.x      = lpmsg16_32->msg.pt.x;
1368         msg32.pt.y      = lpmsg16_32->msg.pt.y;
1369
1370         ret = (BOOL16)CallMsgFilterA(&msg32, (INT)code);
1371
1372         lpmsg16_32->msg.hwnd    = WIN_Handle16( msg32.hwnd );
1373         lpmsg16_32->msg.message = msg32.message;
1374         lpmsg16_32->msg.wParam  = LOWORD(msg32.wParam);
1375         lpmsg16_32->msg.lParam  = msg32.lParam;
1376         lpmsg16_32->msg.time    = msg32.time;
1377         lpmsg16_32->msg.pt.x    = msg32.pt.x;
1378         lpmsg16_32->msg.pt.y    = msg32.pt.y;
1379         lpmsg16_32->wParamHigh  = HIWORD(msg32.wParam);
1380
1381         return ret;
1382     }
1383 }
1384
1385
1386 /***********************************************************************
1387  *              CallMsgFilterA (USER32.@)
1388  *
1389  * FIXME: There are ANSI and UNICODE versions of this, plus an unspecified
1390  * version, plus USER (the 16bit one) has a CallMsgFilter32 function.
1391  */
1392 BOOL WINAPI CallMsgFilterA( LPMSG msg, INT code )
1393 {
1394     if (GetSysModalWindow16()) return FALSE;    /* ??? */
1395     if (HOOK_CallHooksA( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
1396       return TRUE;
1397     return HOOK_CallHooksA( WH_MSGFILTER, code, 0, (LPARAM)msg );
1398 }
1399
1400
1401 /***********************************************************************
1402  *              CallMsgFilterW (USER32.@)
1403  */
1404 BOOL WINAPI CallMsgFilterW( LPMSG msg, INT code )
1405 {
1406     if (GetSysModalWindow16()) return FALSE;    /* ??? */
1407     if (HOOK_CallHooksW( WH_SYSMSGFILTER, code, 0, (LPARAM)msg ))
1408       return TRUE;
1409     return HOOK_CallHooksW( WH_MSGFILTER, code, 0, (LPARAM)msg );
1410 }
1411