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