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