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