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