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