| /* | 
 |  * Windows 16-bit hook functions | 
 |  * | 
 |  * Copyright 1994, 1995, 2002 Alexandre Julliard | 
 |  * Copyright 1996 Andrew Lewycky | 
 |  * | 
 |  * Based on investigations by Alex Korobka | 
 |  * | 
 |  * This library is free software; you can redistribute it and/or | 
 |  * modify it under the terms of the GNU Lesser General Public | 
 |  * License as published by the Free Software Foundation; either | 
 |  * version 2.1 of the License, or (at your option) any later version. | 
 |  * | 
 |  * This library is distributed in the hope that it will be useful, | 
 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
 |  * Lesser General Public License for more details. | 
 |  * | 
 |  * You should have received a copy of the GNU Lesser General Public | 
 |  * License along with this library; if not, write to the Free Software | 
 |  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | 
 |  */ | 
 |  | 
 | #include <stdarg.h> | 
 |  | 
 | #include "windef.h" | 
 | #include "winbase.h" | 
 | #include "winuser.h" | 
 | #include "wownt32.h" | 
 | #include "wine/winuser16.h" | 
 | #include "win.h" | 
 | #include "user_private.h" | 
 | #include "winproc.h" | 
 | #include "wine/debug.h" | 
 |  | 
 | WINE_DEFAULT_DEBUG_CHANNEL(hook); | 
 |  | 
 |  | 
 | static LRESULT CALLBACK call_WH_MSGFILTER( INT code, WPARAM wp, LPARAM lp ); | 
 | static LRESULT CALLBACK call_WH_KEYBOARD( INT code, WPARAM wp, LPARAM lp ); | 
 | static LRESULT CALLBACK call_WH_GETMESSAGE( INT code, WPARAM wp, LPARAM lp ); | 
 | static LRESULT CALLBACK call_WH_CALLWNDPROC( INT code, WPARAM wp, LPARAM lp ); | 
 | static LRESULT CALLBACK call_WH_CBT( INT code, WPARAM wp, LPARAM lp ); | 
 | static LRESULT CALLBACK call_WH_MOUSE( INT code, WPARAM wp, LPARAM lp ); | 
 | static LRESULT CALLBACK call_WH_SHELL( INT code, WPARAM wp, LPARAM lp ); | 
 |  | 
 | #define WH_MAXHOOK16 WH_SHELL  /* Win16 only supports up to WH_SHELL */ | 
 | #define NB_HOOKS16 (WH_MAXHOOK16 - WH_MINHOOK + 1) | 
 |  | 
 | static const HOOKPROC hook_procs[NB_HOOKS16] = | 
 | { | 
 |     call_WH_MSGFILTER,   /* WH_MSGFILTER	*/ | 
 |     NULL,                /* WH_JOURNALRECORD */ | 
 |     NULL,                /* WH_JOURNALPLAYBACK */ | 
 |     call_WH_KEYBOARD,    /* WH_KEYBOARD */ | 
 |     call_WH_GETMESSAGE,  /* WH_GETMESSAGE */ | 
 |     call_WH_CALLWNDPROC, /* WH_CALLWNDPROC */ | 
 |     call_WH_CBT,         /* WH_CBT */ | 
 |     NULL,                /* WH_SYSMSGFILTER */ | 
 |     call_WH_MOUSE,       /* WH_MOUSE */ | 
 |     NULL,                /* WH_HARDWARE */ | 
 |     NULL,                /* WH_DEBUG */ | 
 |     call_WH_SHELL        /* WH_SHELL */ | 
 | }; | 
 |  | 
 |  | 
 | /* this structure is stored in the thread queue */ | 
 | struct hook16_queue_info | 
 | { | 
 |     INT        id;                /* id of current hook */ | 
 |     HHOOK      hook[NB_HOOKS16];  /* Win32 hook handles */ | 
 |     HOOKPROC16 proc[NB_HOOKS16];  /* 16-bit hook procedures */ | 
 | }; | 
 |  | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *           map_msg_16_to_32 | 
 |  */ | 
 | inline static void map_msg_16_to_32( const MSG16 *msg16, MSG *msg32 ) | 
 | { | 
 |     msg32->hwnd    = WIN_Handle32(msg16->hwnd); | 
 |     msg32->message = msg16->message; | 
 |     msg32->wParam  = msg16->wParam; | 
 |     msg32->lParam  = msg16->lParam; | 
 |     msg32->time    = msg16->time; | 
 |     msg32->pt.x    = msg16->pt.x; | 
 |     msg32->pt.y    = msg16->pt.y; | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *           map_msg_32_to_16 | 
 |  */ | 
 | inline static void map_msg_32_to_16( const MSG *msg32, MSG16 *msg16 ) | 
 | { | 
 |     msg16->hwnd    = HWND_16(msg32->hwnd); | 
 |     msg16->message = msg32->message; | 
 |     msg16->wParam  = msg32->wParam; | 
 |     msg16->lParam  = msg32->lParam; | 
 |     msg16->time    = msg32->time; | 
 |     msg16->pt.x    = msg32->pt.x; | 
 |     msg16->pt.y    = msg32->pt.y; | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *           call_hook_16 | 
 |  */ | 
 | static LRESULT call_hook_16( INT id, INT code, WPARAM wp, LPARAM lp ) | 
 | { | 
 |     struct hook16_queue_info *info = get_user_thread_info()->hook16_info; | 
 |     WORD args[4]; | 
 |     DWORD ret; | 
 |     INT prev_id = info->id; | 
 |     info->id = id; | 
 |  | 
 |     args[3] = code; | 
 |     args[2] = wp; | 
 |     args[1] = HIWORD(lp); | 
 |     args[0] = LOWORD(lp); | 
 |     WOWCallback16Ex( (DWORD)info->proc[id - WH_MINHOOK], WCB16_PASCAL, sizeof(args), args, &ret ); | 
 |  | 
 |     info->id = prev_id; | 
 |  | 
 |     /* Grrr. While the hook procedure is supposed to have an LRESULT return | 
 |        value even in Win16, it seems that for those hook types where the | 
 |        return value is interpreted as BOOL, Windows doesn't actually check | 
 |        the HIWORD ...  Some buggy Win16 programs, notably WINFILE, rely on | 
 |        that, because they neglect to clear DX ... */ | 
 |     if (id != WH_JOURNALPLAYBACK) ret = LOWORD( ret ); | 
 |     return ret; | 
 | } | 
 |  | 
 |  | 
 | struct wndproc_hook_params | 
 | { | 
 |     HHOOK  hhook; | 
 |     INT    code; | 
 |     WPARAM wparam; | 
 | }; | 
 |  | 
 | /* callback for WINPROC_Call16To32A */ | 
 | static LRESULT wndproc_hook_callback( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp, | 
 |                                       LRESULT *result, void *arg ) | 
 | { | 
 |     struct wndproc_hook_params *params = arg; | 
 |     CWPSTRUCT cwp; | 
 |  | 
 |     cwp.hwnd    = hwnd; | 
 |     cwp.message = msg; | 
 |     cwp.wParam  = wp; | 
 |     cwp.lParam  = lp; | 
 |     *result = 0; | 
 |     return CallNextHookEx( params->hhook, params->code, params->wparam, (LPARAM)&cwp ); | 
 | } | 
 |  | 
 | /* callback for WINPROC_Call32ATo16 */ | 
 | static LRESULT wndproc_hook_callback16( HWND16 hwnd, UINT16 msg, WPARAM16 wp, LPARAM lp, | 
 |                                         LRESULT *result, void *arg ) | 
 | { | 
 |     struct wndproc_hook_params *params = arg; | 
 |     CWPSTRUCT16 cwp; | 
 |     LRESULT ret; | 
 |  | 
 |     cwp.hwnd    = hwnd; | 
 |     cwp.message = msg; | 
 |     cwp.wParam  = wp; | 
 |     cwp.lParam  = lp; | 
 |  | 
 |     lp = MapLS( &cwp ); | 
 |     ret = call_hook_16( WH_CALLWNDPROC, params->code, params->wparam, lp ); | 
 |     UnMapLS( lp ); | 
 |  | 
 |     *result = 0; | 
 |     return ret; | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *		call_WH_MSGFILTER | 
 |  */ | 
 | static LRESULT CALLBACK call_WH_MSGFILTER( INT code, WPARAM wp, LPARAM lp ) | 
 | { | 
 |     MSG *msg32 = (MSG *)lp; | 
 |     MSG16 msg16; | 
 |     LRESULT ret; | 
 |  | 
 |     map_msg_32_to_16( msg32, &msg16 ); | 
 |     lp = MapLS( &msg16 ); | 
 |     ret = call_hook_16( WH_MSGFILTER, code, wp, lp ); | 
 |     UnMapLS( lp ); | 
 |     return ret; | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *		call_WH_KEYBOARD | 
 |  */ | 
 | static LRESULT CALLBACK call_WH_KEYBOARD( INT code, WPARAM wp, LPARAM lp ) | 
 | { | 
 |     return call_hook_16( WH_KEYBOARD, code, wp, lp ); | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *		call_WH_GETMESSAGE | 
 |  */ | 
 | static LRESULT CALLBACK call_WH_GETMESSAGE( INT code, WPARAM wp, LPARAM lp ) | 
 | { | 
 |     MSG *msg32 = (MSG *)lp; | 
 |     MSG16 msg16; | 
 |     LRESULT ret; | 
 |  | 
 |     map_msg_32_to_16( msg32, &msg16 ); | 
 |  | 
 |     lp = MapLS( &msg16 ); | 
 |     ret = call_hook_16( WH_GETMESSAGE, code, wp, lp ); | 
 |     UnMapLS( lp ); | 
 |  | 
 |     map_msg_16_to_32( &msg16, msg32 ); | 
 |     return ret; | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *		call_WH_CALLWNDPROC | 
 |  */ | 
 | static LRESULT CALLBACK call_WH_CALLWNDPROC( INT code, WPARAM wp, LPARAM lp ) | 
 | { | 
 |     struct wndproc_hook_params params; | 
 |     CWPSTRUCT *cwp32 = (CWPSTRUCT *)lp; | 
 |     LRESULT result; | 
 |  | 
 |     params.code   = code; | 
 |     params.wparam = wp; | 
 |     return WINPROC_CallProc32ATo16( wndproc_hook_callback16, cwp32->hwnd, cwp32->message, | 
 |                                     cwp32->wParam, cwp32->lParam, &result, ¶ms ); | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *		call_WH_CBT | 
 |  */ | 
 | static LRESULT CALLBACK call_WH_CBT( INT code, WPARAM wp, LPARAM lp ) | 
 | { | 
 |     LRESULT ret = 0; | 
 |  | 
 |     switch (code) | 
 |     { | 
 |     case HCBT_CREATEWND: | 
 |         { | 
 |             CBT_CREATEWNDA *cbtcw32 = (CBT_CREATEWNDA *)lp; | 
 |             CBT_CREATEWND16 cbtcw16; | 
 |             CREATESTRUCT16 cs16; | 
 |  | 
 |             cs16.lpCreateParams = (SEGPTR)cbtcw32->lpcs->lpCreateParams; | 
 |             cs16.hInstance      = HINSTANCE_16(cbtcw32->lpcs->hInstance); | 
 |             cs16.hMenu          = HMENU_16(cbtcw32->lpcs->hMenu); | 
 |             cs16.hwndParent     = HWND_16(cbtcw32->lpcs->hwndParent); | 
 |             cs16.cy             = cbtcw32->lpcs->cy; | 
 |             cs16.cx             = cbtcw32->lpcs->cx; | 
 |             cs16.y              = cbtcw32->lpcs->y; | 
 |             cs16.x              = cbtcw32->lpcs->x; | 
 |             cs16.style          = cbtcw32->lpcs->style; | 
 |             cs16.lpszName       = MapLS( cbtcw32->lpcs->lpszName ); | 
 |             cs16.lpszClass      = MapLS( cbtcw32->lpcs->lpszClass ); | 
 |             cs16.dwExStyle      = cbtcw32->lpcs->dwExStyle; | 
 |  | 
 |             cbtcw16.lpcs = (CREATESTRUCT16 *)MapLS( &cs16 ); | 
 |             cbtcw16.hwndInsertAfter = HWND_16( cbtcw32->hwndInsertAfter ); | 
 |  | 
 |             lp = MapLS( &cbtcw16 ); | 
 |             ret = call_hook_16( WH_CBT, code, wp, lp ); | 
 |             UnMapLS( cs16.lpszName ); | 
 |             UnMapLS( cs16.lpszClass ); | 
 |  | 
 |             cbtcw32->hwndInsertAfter = WIN_Handle32( cbtcw16.hwndInsertAfter ); | 
 |             UnMapLS( (SEGPTR)cbtcw16.lpcs ); | 
 |             UnMapLS( lp ); | 
 |             break; | 
 |         } | 
 |  | 
 |     case HCBT_ACTIVATE: | 
 |         { | 
 |             CBTACTIVATESTRUCT *cas32 = (CBTACTIVATESTRUCT *)lp; | 
 |             CBTACTIVATESTRUCT16 cas16; | 
 |  | 
 |             cas16.fMouse     = cas32->fMouse; | 
 |             cas16.hWndActive = HWND_16( cas32->hWndActive ); | 
 |  | 
 |             lp = MapLS( &cas16 ); | 
 |             ret = call_hook_16( WH_CBT, code, wp, lp ); | 
 |             UnMapLS( lp ); | 
 |             break; | 
 |         } | 
 |     case HCBT_CLICKSKIPPED: | 
 |         { | 
 |             MOUSEHOOKSTRUCT *ms32 = (MOUSEHOOKSTRUCT *)lp; | 
 |             MOUSEHOOKSTRUCT16 ms16; | 
 |  | 
 |             ms16.pt.x         = ms32->pt.x; | 
 |             ms16.pt.y         = ms32->pt.y; | 
 |             ms16.hwnd         = HWND_16( ms32->hwnd ); | 
 |             ms16.wHitTestCode = ms32->wHitTestCode; | 
 |             ms16.dwExtraInfo  = ms32->dwExtraInfo; | 
 |  | 
 |             lp = MapLS( &ms16 ); | 
 |             ret = call_hook_16( WH_CBT, code, wp, lp ); | 
 |             UnMapLS( lp ); | 
 |             break; | 
 |         } | 
 |     case HCBT_MOVESIZE: | 
 |         { | 
 |             RECT *rect32 = (RECT *)lp; | 
 |             RECT16 rect16; | 
 |  | 
 |             rect16.left   = rect32->left; | 
 |             rect16.top    = rect32->top; | 
 |             rect16.right  = rect32->right; | 
 |             rect16.bottom = rect32->bottom; | 
 |             lp = MapLS( &rect16 ); | 
 |             ret = call_hook_16( WH_CBT, code, wp, lp ); | 
 |             UnMapLS( lp ); | 
 |             break; | 
 |         } | 
 |     } | 
 |     return ret; | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *		call_WH_MOUSE | 
 |  */ | 
 | static LRESULT CALLBACK call_WH_MOUSE( INT code, WPARAM wp, LPARAM lp ) | 
 | { | 
 |     MOUSEHOOKSTRUCT *ms32 = (MOUSEHOOKSTRUCT *)lp; | 
 |     MOUSEHOOKSTRUCT16 ms16; | 
 |     LRESULT ret; | 
 |  | 
 |     ms16.pt.x         = ms32->pt.x; | 
 |     ms16.pt.y         = ms32->pt.y; | 
 |     ms16.hwnd         = HWND_16( ms32->hwnd ); | 
 |     ms16.wHitTestCode = ms32->wHitTestCode; | 
 |     ms16.dwExtraInfo  = ms32->dwExtraInfo; | 
 |  | 
 |     lp = MapLS( &ms16 ); | 
 |     ret = call_hook_16( WH_MOUSE, code, wp, lp ); | 
 |     UnMapLS( lp ); | 
 |     return ret; | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *		call_WH_SHELL | 
 |  */ | 
 | static LRESULT CALLBACK call_WH_SHELL( INT code, WPARAM wp, LPARAM lp ) | 
 | { | 
 |     return call_hook_16( WH_SHELL, code, wp, lp ); | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *		SetWindowsHook (USER.121) | 
 |  */ | 
 | FARPROC16 WINAPI SetWindowsHook16( INT16 id, HOOKPROC16 proc ) | 
 | { | 
 |     HINSTANCE16 hInst = FarGetOwner16( HIWORD(proc) ); | 
 |  | 
 |     /* WH_MSGFILTER is the only task-specific hook for SetWindowsHook() */ | 
 |     HTASK16 hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0; | 
 |  | 
 |     return (FARPROC16)SetWindowsHookEx16( id, proc, hInst, hTask ); | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *		SetWindowsHookEx (USER.291) | 
 |  */ | 
 | HHOOK WINAPI SetWindowsHookEx16( INT16 id, HOOKPROC16 proc, HINSTANCE16 hInst, HTASK16 hTask ) | 
 | { | 
 |     struct user_thread_info *thread_info = get_user_thread_info(); | 
 |     struct hook16_queue_info *info; | 
 |     HHOOK hook; | 
 |     int index = id - WH_MINHOOK; | 
 |  | 
 |     if (id < WH_MINHOOK || id > WH_MAXHOOK16) return 0; | 
 |     if (!hook_procs[index]) | 
 |     { | 
 |         FIXME( "hook type %d broken in Win16\n", id ); | 
 |         return 0; | 
 |     } | 
 |     if (!hTask) FIXME( "System-global hooks (%d) broken in Win16\n", id ); | 
 |     else if (hTask != GetCurrentTask()) | 
 |     { | 
 |         FIXME( "setting hook (%d) on other task not supported\n", id ); | 
 |         return 0; | 
 |     } | 
 |  | 
 |     if (!(info = thread_info->hook16_info)) | 
 |     { | 
 |         if (!(info = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*info) ))) return 0; | 
 |         thread_info->hook16_info = info; | 
 |     } | 
 |     if (info->hook[index]) | 
 |     { | 
 |         FIXME( "Multiple hooks (%d) for the same task not supported yet\n", id ); | 
 |         return 0; | 
 |     } | 
 |     if (!(hook = SetWindowsHookExA( id, hook_procs[index], 0, GetCurrentThreadId() ))) return 0; | 
 |     info->hook[index] = hook; | 
 |     info->proc[index] = proc; | 
 |     return hook; | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *		UnhookWindowsHook (USER.234) | 
 |  */ | 
 | BOOL16 WINAPI UnhookWindowsHook16( INT16 id, HOOKPROC16 proc ) | 
 | { | 
 |     struct hook16_queue_info *info; | 
 |     int index = id - WH_MINHOOK; | 
 |  | 
 |     if (id < WH_MINHOOK || id > WH_MAXHOOK16) return FALSE; | 
 |     if (!(info = get_user_thread_info()->hook16_info)) return FALSE; | 
 |     if (info->proc[index] != proc) return FALSE; | 
 |     if (!UnhookWindowsHookEx( info->hook[index] )) return FALSE; | 
 |     info->hook[index] = 0; | 
 |     info->proc[index] = 0; | 
 |     return TRUE; | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *		UnhookWindowsHookEx (USER.292) | 
 |  */ | 
 | BOOL16 WINAPI UnhookWindowsHookEx16( HHOOK hhook ) | 
 | { | 
 |     struct hook16_queue_info *info; | 
 |     int index; | 
 |  | 
 |     if (!(info = get_user_thread_info()->hook16_info)) return FALSE; | 
 |     for (index = 0; index < NB_HOOKS16; index++) | 
 |     { | 
 |         if (info->hook[index] == hhook) | 
 |         { | 
 |             info->hook[index] = 0; | 
 |             info->proc[index] = 0; | 
 |             return UnhookWindowsHookEx( hhook ); | 
 |         } | 
 |     } | 
 |     return FALSE; | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *		CallMsgFilter32 (USER.823) | 
 |  */ | 
 | BOOL16 WINAPI CallMsgFilter32_16( MSG32_16 *lpmsg16_32, INT16 code, BOOL16 wHaveParamHigh ) | 
 | { | 
 |     MSG msg32; | 
 |     BOOL16 ret; | 
 |  | 
 |     if (GetSysModalWindow16()) return FALSE; | 
 |     msg32.hwnd      = WIN_Handle32( lpmsg16_32->msg.hwnd ); | 
 |     msg32.message   = lpmsg16_32->msg.message; | 
 |     msg32.lParam    = lpmsg16_32->msg.lParam; | 
 |     msg32.time      = lpmsg16_32->msg.time; | 
 |     msg32.pt.x      = lpmsg16_32->msg.pt.x; | 
 |     msg32.pt.y      = lpmsg16_32->msg.pt.y; | 
 |     if (wHaveParamHigh) msg32.wParam = MAKELONG(lpmsg16_32->msg.wParam, lpmsg16_32->wParamHigh); | 
 |     else msg32.wParam = lpmsg16_32->msg.wParam; | 
 |  | 
 |     ret = (BOOL16)CallMsgFilterA(&msg32, code); | 
 |  | 
 |     lpmsg16_32->msg.hwnd    = HWND_16( msg32.hwnd ); | 
 |     lpmsg16_32->msg.message = msg32.message; | 
 |     lpmsg16_32->msg.wParam  = LOWORD(msg32.wParam); | 
 |     lpmsg16_32->msg.lParam  = msg32.lParam; | 
 |     lpmsg16_32->msg.time    = msg32.time; | 
 |     lpmsg16_32->msg.pt.x    = msg32.pt.x; | 
 |     lpmsg16_32->msg.pt.y    = msg32.pt.y; | 
 |     if (wHaveParamHigh) lpmsg16_32->wParamHigh = HIWORD(msg32.wParam); | 
 |     return ret; | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *		CallMsgFilter (USER.123) | 
 |  */ | 
 | BOOL16 WINAPI CallMsgFilter16( MSG16 *msg, INT16 code ) | 
 | { | 
 |     return CallMsgFilter32_16( (MSG32_16 *)msg, code, FALSE ); | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *		CallNextHookEx (USER.293) | 
 |  */ | 
 | LRESULT WINAPI CallNextHookEx16( HHOOK hhook, INT16 code, WPARAM16 wparam, LPARAM lparam ) | 
 | { | 
 |     struct hook16_queue_info *info; | 
 |     LRESULT ret = 0; | 
 |  | 
 |     if (!(info = get_user_thread_info()->hook16_info)) return 0; | 
 |  | 
 |     switch (info->id) | 
 |     { | 
 |     case WH_MSGFILTER: | 
 |     { | 
 |         MSG16 *msg16 = MapSL(lparam); | 
 |         MSG msg32; | 
 |  | 
 |         map_msg_16_to_32( msg16, &msg32 ); | 
 |         ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&msg32 ); | 
 |         break; | 
 |     } | 
 |  | 
 |     case WH_GETMESSAGE: | 
 |     { | 
 |         MSG16 *msg16 = MapSL(lparam); | 
 |         MSG msg32; | 
 |  | 
 |         map_msg_16_to_32( msg16, &msg32 ); | 
 |         ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&msg32 ); | 
 |         map_msg_32_to_16( &msg32, msg16 ); | 
 |         break; | 
 |     } | 
 |  | 
 |     case WH_CALLWNDPROC: | 
 |     { | 
 |         CWPSTRUCT16 *cwp16 = MapSL(lparam); | 
 |         LRESULT result; | 
 |         struct wndproc_hook_params params; | 
 |  | 
 |         params.hhook  = hhook; | 
 |         params.code   = code; | 
 |         params.wparam = wparam; | 
 |         ret = WINPROC_CallProc16To32A( wndproc_hook_callback, cwp16->hwnd, cwp16->message, | 
 |                                        cwp16->wParam, cwp16->lParam, &result, ¶ms ); | 
 |         break; | 
 |     } | 
 |  | 
 |     case WH_CBT: | 
 |         switch (code) | 
 |         { | 
 |         case HCBT_CREATEWND: | 
 |             { | 
 |                 CBT_CREATEWNDA cbtcw32; | 
 |                 CREATESTRUCTA cs32; | 
 |                 CBT_CREATEWND16 *cbtcw16 = MapSL(lparam); | 
 |                 CREATESTRUCT16 *cs16 = MapSL( (SEGPTR)cbtcw16->lpcs ); | 
 |  | 
 |                 cbtcw32.lpcs = &cs32; | 
 |                 cbtcw32.hwndInsertAfter = WIN_Handle32( cbtcw16->hwndInsertAfter ); | 
 |  | 
 |                 cs32.lpCreateParams = (LPVOID)cs16->lpCreateParams; | 
 |                 cs32.hInstance      = HINSTANCE_32(cs16->hInstance); | 
 |                 cs32.hMenu          = HMENU_32(cs16->hMenu); | 
 |                 cs32.hwndParent     = WIN_Handle32(cs16->hwndParent); | 
 |                 cs32.cy             = cs16->cy; | 
 |                 cs32.cx             = cs16->cx; | 
 |                 cs32.y              = cs16->y; | 
 |                 cs32.x              = cs16->x; | 
 |                 cs32.style          = cs16->style; | 
 |                 cs32.lpszName       = MapSL( cs16->lpszName ); | 
 |                 cs32.lpszClass      = MapSL( cs16->lpszClass ); | 
 |                 cs32.dwExStyle      = cs16->dwExStyle; | 
 |  | 
 |                 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&cbtcw32 ); | 
 |                 cbtcw16->hwndInsertAfter = HWND_16( cbtcw32.hwndInsertAfter ); | 
 |                 break; | 
 |             } | 
 |         case HCBT_ACTIVATE: | 
 |             { | 
 |                 CBTACTIVATESTRUCT16 *cas16 = MapSL(lparam); | 
 |                 CBTACTIVATESTRUCT cas32; | 
 |                 cas32.fMouse = cas16->fMouse; | 
 |                 cas32.hWndActive = WIN_Handle32(cas16->hWndActive); | 
 |                 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&cas32 ); | 
 |                 break; | 
 |             } | 
 |         case HCBT_CLICKSKIPPED: | 
 |             { | 
 |                 MOUSEHOOKSTRUCT16 *ms16 = MapSL(lparam); | 
 |                 MOUSEHOOKSTRUCT ms32; | 
 |  | 
 |                 ms32.pt.x = ms16->pt.x; | 
 |                 ms32.pt.y = ms16->pt.y; | 
 |                 /* wHitTestCode may be negative, so convince compiler to do | 
 |                    correct sign extension. Yay. :| */ | 
 |                 ms32.wHitTestCode = (INT)(INT16)ms16->wHitTestCode; | 
 |                 ms32.dwExtraInfo = ms16->dwExtraInfo; | 
 |                 ms32.hwnd = WIN_Handle32( ms16->hwnd ); | 
 |                 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&ms32 ); | 
 |                 break; | 
 |             } | 
 |         case HCBT_MOVESIZE: | 
 |             { | 
 |                 RECT16 *rect16 = MapSL(lparam); | 
 |                 RECT rect32; | 
 |  | 
 |                 rect32.left   = rect16->left; | 
 |                 rect32.top    = rect16->top; | 
 |                 rect32.right  = rect16->right; | 
 |                 rect32.bottom = rect16->bottom; | 
 |                 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&rect32 ); | 
 |                 break; | 
 |             } | 
 |         } | 
 |         break; | 
 |  | 
 |     case WH_MOUSE: | 
 |     { | 
 |         MOUSEHOOKSTRUCT16 *ms16 = MapSL(lparam); | 
 |         MOUSEHOOKSTRUCT ms32; | 
 |  | 
 |         ms32.pt.x = ms16->pt.x; | 
 |         ms32.pt.y = ms16->pt.y; | 
 |         /* wHitTestCode may be negative, so convince compiler to do | 
 |            correct sign extension. Yay. :| */ | 
 |         ms32.wHitTestCode = (INT)((INT16)ms16->wHitTestCode); | 
 |         ms32.dwExtraInfo = ms16->dwExtraInfo; | 
 |         ms32.hwnd = WIN_Handle32(ms16->hwnd); | 
 |         ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&ms32 ); | 
 |         break; | 
 |     } | 
 |  | 
 |     case WH_SHELL: | 
 |     case WH_KEYBOARD: | 
 |         ret = CallNextHookEx( hhook, code, wparam, lparam ); | 
 |         break; | 
 |  | 
 |     case WH_HARDWARE: | 
 |     case WH_FOREGROUNDIDLE: | 
 |     case WH_CALLWNDPROCRET: | 
 |     case WH_SYSMSGFILTER: | 
 |     case WH_JOURNALRECORD: | 
 |     case WH_JOURNALPLAYBACK: | 
 |     default: | 
 |         FIXME("\t[%i] 16to32 translation unimplemented\n", info->id); | 
 |         ret = CallNextHookEx( hhook, code, wparam, lparam ); | 
 |         break; | 
 |     } | 
 |     return ret; | 
 | } | 
 |  | 
 |  | 
 | /*********************************************************************** | 
 |  *		DefHookProc (USER.235) | 
 |  */ | 
 | LRESULT WINAPI DefHookProc16( INT16 code, WPARAM16 wparam, LPARAM lparam, HHOOK *hhook ) | 
 | { | 
 |     return CallNextHookEx16( *hhook, code, wparam, lparam ); | 
 | } |