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