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