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