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