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