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