|
|
//*****************************************************************************
//
// HOOKS -
//
// 32bit stubs and thunks for 16bit hooks
//
//
// 01-07-92 NanduriR Created.
//
//*****************************************************************************
#include "precomp.h"
#pragma hdrstop
MODNAME(wowhooks.c);
//*****************************************************************************
//
// Global data. Data is valid only in WOW process context. DLL Data is not
// Shared amongst various processes. If a WOW hook is set WIN32 USER will call
// the hookproc in the context of the thread that has the hook set. This implies
// that all the global data in this DLL is acessible by every WOW thread.
//
// Just reaffirming: since USER will call the hookprocs in our process/thread
// context there is no need for this data to be available
// in shared memory.
//
//*****************************************************************************
HOOKPERPROCESSDATA vaHookPPData = { NULL, 0};
//
// In SetWindowsHook we return an index into this array if it was
// successful. Since NULL implies an error, we cannot use the Zeroth element
// in this array. So we set its 'InUse' flag to TRUE.
//
HOOKSTATEDATA vaHookStateData[] = { 0, TRUE, 0, NULL, (HKPROC)NULL, 0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc01,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc02,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc03,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc04,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc05,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc06,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc07,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc08,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc09,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc10,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc11,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc12,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc13,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc14,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc15,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc16,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc17,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc18,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc19,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc20,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc21,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc22,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc23,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc24,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc25,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc26,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc27,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc28,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc29,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc30,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc31,0, 0, 0, NULL, 0, FALSE, 0, NULL, (HKPROC)WU32SubStdHookProc32,0, 0, 0, NULL };
HOOKPARAMS vHookParams = {0, 0, 0};
INT viCurrentHookStateDataIndex = 0; // this is used when 'DefHookProc' is called.
//*****************************************************************************
// Sub-Standard Hook Procs -
//
// Hook Stubs. The 'index' (the fourth parameter) is an index into the
// the HookStateData array. All needed info is available in this array.
// The hook stubs need to be exported.
//
//*****************************************************************************
LONG APIENTRY WU32SubStdHookProc01(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x01); }
LONG APIENTRY WU32SubStdHookProc02(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x02); }
LONG APIENTRY WU32SubStdHookProc03(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x03); }
LONG APIENTRY WU32SubStdHookProc04(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x04); }
LONG APIENTRY WU32SubStdHookProc05(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x05); }
LONG APIENTRY WU32SubStdHookProc06(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x06); }
LONG APIENTRY WU32SubStdHookProc07(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x07); }
LONG APIENTRY WU32SubStdHookProc08(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x08); }
LONG APIENTRY WU32SubStdHookProc09(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x09); }
LONG APIENTRY WU32SubStdHookProc10(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x0a); }
LONG APIENTRY WU32SubStdHookProc11(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x0b); }
LONG APIENTRY WU32SubStdHookProc12(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x0c); }
LONG APIENTRY WU32SubStdHookProc13(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x0d); }
LONG APIENTRY WU32SubStdHookProc14(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x0e); }
LONG APIENTRY WU32SubStdHookProc15(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x0f); } LONG APIENTRY WU32SubStdHookProc16(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x10); } LONG APIENTRY WU32SubStdHookProc17(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x11); } LONG APIENTRY WU32SubStdHookProc18(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x12); } LONG APIENTRY WU32SubStdHookProc19(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x13); } LONG APIENTRY WU32SubStdHookProc20(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x14); } LONG APIENTRY WU32SubStdHookProc21(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x15); } LONG APIENTRY WU32SubStdHookProc22(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x16); } LONG APIENTRY WU32SubStdHookProc23(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x17); } LONG APIENTRY WU32SubStdHookProc24(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x18); } LONG APIENTRY WU32SubStdHookProc25(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x19); } LONG APIENTRY WU32SubStdHookProc26(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x1a); } LONG APIENTRY WU32SubStdHookProc27(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x1b); } LONG APIENTRY WU32SubStdHookProc28(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x1c); } LONG APIENTRY WU32SubStdHookProc29(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x1d); } LONG APIENTRY WU32SubStdHookProc30(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x1e); } LONG APIENTRY WU32SubStdHookProc31(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x1f); } LONG APIENTRY WU32SubStdHookProc32(INT nCode, LONG wParam, LONG lParam) { return WU32StdHookProc(nCode, wParam, lParam, 0x20); }
//*****************************************************************************
// W32InitHookState:
//
// Initializes the global data. Note that this data is initialized for every
// Process that loads this DLL. However data that is visible only to the 'WOW'
// process is what we care about.
//
//*****************************************************************************
BOOL W32InitHookState(HANDLE hMod) { INT i;
vaHookPPData.hMod = hMod; vaHookPPData.cHookProcs = sizeof(vaHookStateData) / sizeof(vaHookStateData[0]);
for (i = 0; i < vaHookPPData.cHookProcs; i++) { vaHookStateData[i].iIndex = (BYTE)i; vaHookStateData[i].hMod = hMod; }
return TRUE; }
//*****************************************************************************
// W32GetNotInUseHookStateData:
//
// Steps through the Global HookStateData and returns a pointer to an 'unused'
// element. This is called only when the Hook is being Set.
//
//*****************************************************************************
BOOL W32GetNotInUseHookStateData(LPHOOKSTATEDATA lpData) { INT i; for (i = 0; i < vaHookPPData.cHookProcs; i++) { if (!vaHookStateData[i].InUse) { vaHookStateData[i].InUse = TRUE; *lpData = vaHookStateData[i]; return TRUE; } } LOGDEBUG(LOG_ALWAYS, ("W32GetNotInUseHookStateData: All thunk hook procs in use.\n")); return FALSE; }
//*****************************************************************************
// W32SetHookStateData:
//
// Writes into the global data structure at the specified index.
//
//*****************************************************************************
BOOL W32SetHookStateData(LPHOOKSTATEDATA lpData) { vaHookStateData[lpData->iIndex] = *lpData; return TRUE; }
//*****************************************************************************
// W32GetHookStateData:
//
// Retrieves data from the global data structure at the specified index.
//
//*****************************************************************************
BOOL W32GetHookStateData(LPHOOKSTATEDATA lpData) { if ( lpData->iIndex >= 0 && lpData->iIndex < vaHookPPData.cHookProcs ) { *lpData = vaHookStateData[lpData->iIndex]; return TRUE; } else { return FALSE; } }
//*****************************************************************************
// W32GetThunkHookProc:
//
// Its callled to find a 32stub for the hook that is being set.
// Returns TRUE if successful else FALSE.
// The data is partially updated to reflect the characteristics of the hook
// that is being set.
//
//*****************************************************************************
BOOL W32GetThunkHookProc(INT iHook, DWORD Proc16, LPHOOKSTATEDATA lpData) { register PTD ptd = CURRENTPTD();
if (W32GetNotInUseHookStateData(lpData)) { lpData->iHook = iHook; lpData->Proc16 = Proc16; lpData->TaskId = ptd->htask16 ; W32SetHookStateData(lpData); return TRUE; } else return FALSE;
}
//*****************************************************************************
// W32IsDuplicateHook:
//
// Verifies if the given hook has already been set. This is to catch
// certain apps which go on Setting the same hook without Unhooking the
// previous hook.
//
// Returns the 'stubindex' if hook already exists else 0;
//
//*****************************************************************************
INT W32IsDuplicateHook(INT iHook, DWORD Proc16, INT TaskId) { INT i; for (i = 0; i < vaHookPPData.cHookProcs; i++) { if (vaHookStateData[i].InUse && vaHookStateData[i].iHook == iHook && vaHookStateData[i].TaskId == TaskId && vaHookStateData[i].Proc16 == Proc16 ) { return i; } }
return 0; }
//*****************************************************************************
// W32FreeHHook:
//
// The state of the specified hook is set to 'Not in use'.
// Returns hHook of the hook being freed.
//
//*****************************************************************************
HHOOK W32FreeHHook(INT iHook, DWORD Proc16) {
register PTD ptd = CURRENTPTD(); INT i; for (i = 0; i < vaHookPPData.cHookProcs; i++) { if (vaHookStateData[i].InUse && vaHookStateData[i].iHook == iHook && vaHookStateData[i].TaskId == (INT)ptd->htask16 && vaHookStateData[i].Proc16 == Proc16) { vaHookStateData[i].InUse = FALSE; return vaHookStateData[i].hHook; } } LOGDEBUG(LOG_ALWAYS, ("W32FreeHHook: Couldn't locate the specified hook.")); return (HHOOK)NULL; }
//*****************************************************************************
// W32FreeHHookOfIndex:
//
// The state of the specified hook is set to 'Not in use'.
// Returns hHook of the hook being freed.
//
//*****************************************************************************
HHOOK W32FreeHHookOfIndex(INT iFunc) { register PTD ptd = CURRENTPTD();
if (iFunc && iFunc < vaHookPPData.cHookProcs) if (vaHookStateData[iFunc].InUse && vaHookStateData[iFunc].TaskId == (INT)ptd->htask16) { vaHookStateData[iFunc].InUse = FALSE; return vaHookStateData[iFunc].hHook; } LOGDEBUG(LOG_ALWAYS, ("W32FreeHHookOfIndex: Couldn't locate the specified hook.")); return (HHOOK)NULL; }
//*****************************************************************************
// W32GetHookParams:
//
// Returns the 32bit hookparams of the current hook.
//
//*****************************************************************************
BOOL W32GetHookParams(LPHOOKPARAMS lpHookParams) { if (lpHookParams) { *lpHookParams = vHookParams; }
return (BOOL)lpHookParams; }
//*****************************************************************************
// W32StdHookProc: (Standard Hook Proc)
//
// All the stubs call this proc.
// Return value is dependent on the hook type.
//
//*****************************************************************************
LONG APIENTRY WU32StdHookProc(INT nCode, LONG wParam, LONG lParam, INT iFunc) { //
// USER will call us in WOW context. Just Verify.
//
if (!vaHookStateData[iFunc].InUse) { // DbgPrint("WU32StdHookProc:Stub %04x called in WRONG process\n", iFunc);
return FALSE; }
//
// USER can call us even if we have GP Faulted - so just ignore the input
//
if (CURRENTPTD()->dwFlags & TDF_IGNOREINPUT) { LOGDEBUG(LOG_ALWAYS,("WU32StdHookProc Ignoring Input\n")); WOW32ASSERTMSG(gfIgnoreInputAssertGiven, "WU32StdHookProc: TDF_IGNOREINPUT hack was used, shouldn't be, " "please email DOSWOW with repro instructions. Hit 'g' to ignore this " "and suppress this assertion from now on.\n"); gfIgnoreInputAssertGiven = TRUE; return FALSE; }
//
// store the stubindex. If the hookproc calls the DefHookProc() we will
// be able to findout the Hook Type.
//
viCurrentHookStateDataIndex = iFunc;
//
// store the hook params. These will be used if DefHookProc gets called
// by the 16bit stub. We are interested only in lParam.
//
vHookParams.nCode = nCode; vHookParams.wParam = wParam; vHookParams.lParam = lParam;
switch (vaHookStateData[iFunc].iHook) { case WH_CALLWNDPROC: return ThunkCallWndProcHook(nCode, wParam, (LPCWPSTRUCT)lParam, &vaHookStateData[iFunc]);
case WH_CBT:
return ThunkCbtHook(nCode, wParam, lParam, &vaHookStateData[iFunc]);
case WH_KEYBOARD: return ThunkKeyBoardHook(nCode, wParam, lParam, &vaHookStateData[iFunc]);
case WH_MSGFILTER:
// This code is TEMP only and must be fixed. ChandanC 5/2/92.
if ((WORD)vaHookStateData[iFunc].TaskId != (WORD)((PTD)CURRENTPTD())->htask16) break;
WOW32ASSERT((WORD)vaHookStateData[iFunc].TaskId == (WORD)((PTD)CURRENTPTD())->htask16); case WH_SYSMSGFILTER: case WH_GETMESSAGE:
return ThunkMsgFilterHook(nCode, wParam, (LPMSG)lParam, &vaHookStateData[iFunc]); break;
case WH_JOURNALPLAYBACK: case WH_JOURNALRECORD: return ThunkJournalHook(nCode, wParam, (LPEVENTMSG)lParam, &vaHookStateData[iFunc]);
case WH_DEBUG: return ThunkDebugHook(nCode, wParam, lParam, &vaHookStateData[iFunc]);
case WH_MOUSE: return ThunkMouseHook(nCode, wParam, (LPMOUSEHOOKSTRUCT)lParam, &vaHookStateData[iFunc]);
case WH_SHELL: return ThunkShellHook(nCode, wParam, lParam, &vaHookStateData[iFunc]);
default: LOGDEBUG(LOG_ALWAYS,("W32StdHookProc: Unknown Hook type.")); }
return (LONG)FALSE;
}
//*****************************************************************************
//
// ThunkHookProc for Hooks of type WH_CALLWNDPROC -
//
// Return type is VOID.
//
//*****************************************************************************
LONG ThunkCallWndProcHook(INT nCode, LONG wParam, LPCWPSTRUCT lpCwpStruct, LPHOOKSTATEDATA lpHSData) { VPVOID vp; PCWPSTRUCT16 pCwpStruct16; PARM16 Parm16; WM32MSGPARAMEX wm32mpex; BOOL fMessageNeedsThunking;
wm32mpex.Parm16.WndProc.wMsg = (WORD) lpCwpStruct->message; wm32mpex.Parm16.WndProc.wParam = (WORD) lpCwpStruct->wParam; wm32mpex.Parm16.WndProc.lParam = (LONG) lpCwpStruct->lParam;
fMessageNeedsThunking = (lpCwpStruct->message < 0x400) && (aw32Msg[lpCwpStruct->message].lpfnM32 != WM32NoThunking); // This call to stackalloc16() needs to occur before the call to the message
// thunking function call below ((wm32mpex.lpfnM32)(&wm32mpex)) because the
// message thunks for some messages may also call stackalloc16(). This will
// ensure proper nesting of stackalloc16() & stackfree16() calls.
// Be sure allocation size matches stackfree16() size below
vp = stackalloc16(sizeof(CWPSTRUCT16));
if (fMessageNeedsThunking) {
LOGDEBUG(3,("%04X (%s)\n", CURRENTPTD()->htask16, (aw32Msg[lpCwpStruct->message].lpszW32)));
wm32mpex.fThunk = THUNKMSG; wm32mpex.hwnd = lpCwpStruct->hwnd; wm32mpex.uMsg = lpCwpStruct->message; wm32mpex.uParam = lpCwpStruct->wParam; wm32mpex.lParam = lpCwpStruct->lParam; wm32mpex.lpfnM32 = aw32Msg[wm32mpex.uMsg].lpfnM32; wm32mpex.pww = (PWW)NULL; wm32mpex.fFree = TRUE;
// note: this may call stackalloc16() and/or callback into 16-bit code
if (!(wm32mpex.lpfnM32)(&wm32mpex)) { LOGDEBUG(LOG_ALWAYS,("ThunkCallWndProcHook: cannot thunk 32-bit message %04x\n", lpCwpStruct->message)); } }
// don't call GETMISCPTR(vp..) until after returning from the thunk function
// above. If the thunk function calls back into 16-bit code, the flat ptr
// for vp could become invalid.
GETMISCPTR(vp, pCwpStruct16);
if(pCwpStruct16) { STOREWORD(pCwpStruct16->hwnd, GETHWND16(lpCwpStruct->hwnd)); STOREWORD(pCwpStruct16->message, wm32mpex.Parm16.WndProc.wMsg ); STOREWORD(pCwpStruct16->wParam, wm32mpex.Parm16.WndProc.wParam); STORELONG(pCwpStruct16->lParam, wm32mpex.Parm16.WndProc.lParam);
FLUSHVDMPTR(vp, sizeof(CWPSTRUCT16), pCwpStruct16); FREEVDMPTR(pCwpStruct16); } else { WOW32WARNMSG((FALSE),"WOW::ThunkCallWndProcHook:can't get flat pointer to struct!\n"); } Parm16.HookProc.nCode = (SHORT)nCode; Parm16.HookProc.wParam = (SHORT)wParam; Parm16.HookProc.lParam = vp;
CallBack16(RET_HOOKPROC, &Parm16, lpHSData->Proc16, (PVPVOID)&wm32mpex.lReturn);
#ifdef DEBUG
GETMISCPTR(vp, pCwpStruct16);
if (pCwpStruct16->message != wm32mpex.Parm16.WndProc.wMsg) LOGDEBUG(LOG_ALWAYS,("ThunkCallWndProcHook: IN message != OUT message"));
FREEVDMPTR(pCwpStruct16); #endif
if (fMessageNeedsThunking) {
wm32mpex.fThunk = UNTHUNKMSG;
// Note: If the thunk of this message called stackalloc16() this unthunk
// call should call stackfree16()
(wm32mpex.lpfnM32)(&wm32mpex); }
if(vp) {
// this stackfree16() call must come after the above message unthunk
// call to give the unthunk the opportunity to call stackfree16() also.
// this will preserve proper nesting of stackalloc16 & stackfree16 calls
stackfree16(vp, sizeof(CWPSTRUCT16)); }
return (LONG)FALSE; // return value doesn't matter
}
//*****************************************************************************
//
// ThunkHookProc for Hooks of type WH_CBT -
//
// Return type is BOOL.
//
//*****************************************************************************
LONG ThunkCbtHook(INT nCode, LONG wParam, LONG lParam, LPHOOKSTATEDATA lpHSData) { LONG lReturn = FALSE; PARM16 Parm16;
VPVOID vp; PMOUSEHOOKSTRUCT16 pMHStruct16; PCBTACTIVATESTRUCT16 pCbtAStruct16; VPCREATESTRUCT16 vpcs16; PCBT_CREATEWND16 pCbtCWnd16; WM32MSGPARAMEX wm32mpex;
Parm16.HookProc.nCode = (SHORT)nCode; Parm16.HookProc.wParam = (SHORT)wParam; Parm16.HookProc.lParam = lParam;
switch(nCode) { case HCBT_MOVESIZE:
// wParam = HWND, lParam = LPRECT
Parm16.HookProc.wParam = GETHWND16(wParam);
// be sure allocation size matches stackfree16() size below
vp = stackalloc16(sizeof(RECT16));
PUTRECT16(vp, (LPRECT)lParam);
Parm16.HookProc.lParam = vp;
break;
case HCBT_MINMAX:
// wParam = HWND, lParam = SW_* --- a command
Parm16.HookProc.wParam = GETHWND16(wParam); break;
case HCBT_QS:
// wParam = 0, lParam = 0
break;
case HCBT_CREATEWND:
// This stackalloc16() call needs to occur before the WM32Create()
// call below to ensure proper nesting of stackalloc16 & stackfree16
// calls.
// Be sure allocation size matches stackfree16() size(s) below
vp = stackalloc16(sizeof(CBT_CREATEWND16));
// wParam = HWND, lParam = LPCBT_CREATEWND
wm32mpex.fThunk = THUNKMSG; wm32mpex.hwnd = (HWND)wParam; wm32mpex.uMsg = 0; wm32mpex.uParam = 0; wm32mpex.lParam = (LONG)((LPCBT_CREATEWND)lParam)->lpcs; wm32mpex.pww = (PWW)GetWindowLong((HWND)wParam, GWL_WOWWORDS); /*
* WM32Create now requires that pww be initialized * WM32Create calls stackalloc16()!! */ if (!wm32mpex.pww || !WM32Create(&wm32mpex)) { stackfree16(vp, sizeof(CBT_CREATEWND16)); return FALSE; } vpcs16 = wm32mpex.Parm16.WndProc.lParam; lReturn = wm32mpex.lReturn;
GETMISCPTR(vp, pCbtCWnd16); STOREDWORD(pCbtCWnd16->vpcs, vpcs16); STOREWORD(pCbtCWnd16->hwndInsertAfter, GETHWNDIA16(((LPCBT_CREATEWND)lParam)->hwndInsertAfter));
Parm16.HookProc.wParam = GETHWND16(wParam); Parm16.HookProc.lParam = vp;
FLUSHVDMPTR(vp, sizeof(CBT_CREATEWND16), pCbtCWnd16); FREEVDMPTR(pCbtCWnd16); break;
case HCBT_DESTROYWND:
// wParam = HWND, lParam = 0
Parm16.HookProc.wParam = GETHWND16(wParam); break;
case HCBT_ACTIVATE:
// wParam = HWND, lParam = LPCBTACTIVATESTRUCT
// be sure allocation size matches stackfree16() size below
vp = stackalloc16(sizeof(CBTACTIVATESTRUCT16));
GETMISCPTR(vp, pCbtAStruct16); PUTCBTACTIVATESTRUCT16(pCbtAStruct16, ((LPCBTACTIVATESTRUCT)lParam));
Parm16.HookProc.wParam = GETHWND16(wParam); Parm16.HookProc.lParam = vp;
FLUSHVDMPTR(vp, sizeof(CBTACTIVATESTRUCT16), pCbtAStruct16); FREEVDMPTR(pCbtAStruct16); break;
case HCBT_CLICKSKIPPED:
// wParam = mouse message, lParam = LPMOUSEHOOKSTRUCT
// be sure allocation size matches stackfree16() size below
vp = stackalloc16(sizeof(MOUSEHOOKSTRUCT16));
GETMISCPTR(vp, pMHStruct16); PUTMOUSEHOOKSTRUCT16(pMHStruct16, (LPMOUSEHOOKSTRUCT)lParam);
Parm16.HookProc.lParam = vp;
FLUSHVDMPTR(vp, sizeof(MOUSEHOOKSTRUCT16), pMHStruct16); FREEVDMPTR(pMHStruct16); break;
case HCBT_KEYSKIPPED:
// wParam, lParam -- keyup/down message params
break;
case HCBT_SYSCOMMAND:
// wParam = SC_ syscomand, lParam = DWORD(x,y)
break;
case HCBT_SETFOCUS:
// wParam = HWND, lParam = HWND
Parm16.HookProc.wParam = GETHWND16(wParam); Parm16.HookProc.lParam = GETHWND16(lParam); break;
default: LOGDEBUG(LOG_ALWAYS, ("ThunkCbtHook: Unknown HCBT_ code\n")); break; }
CallBack16(RET_HOOKPROC, &Parm16, lpHSData->Proc16, (PVPVOID)&lReturn);
switch(nCode) { case HCBT_MOVESIZE:
GETRECT16(vp, (LPRECT)lParam); stackfree16(vp, sizeof(RECT16)); break;
case HCBT_CREATEWND: GETMISCPTR(vp, pCbtCWnd16); ((LPCBT_CREATEWND)lParam)->hwndInsertAfter = HWNDIA32(FETCHWORD(pCbtCWnd16->hwndInsertAfter)); FREEVDMPTR(pCbtCWnd16); wm32mpex.fThunk = UNTHUNKMSG; wm32mpex.lReturn = lReturn; WM32Create(&wm32mpex); // this calls stackfree16()!!!
lReturn = wm32mpex.lReturn; // this must be after call to WM32Create()
stackfree16(vp, sizeof(CBT_CREATEWND16)); break;
case HCBT_ACTIVATE:
GETMISCPTR(vp, pCbtAStruct16); GETCBTACTIVATESTRUCT16(pCbtAStruct16, (LPCBTACTIVATESTRUCT)lParam); FREEVDMPTR(pCbtAStruct16); stackfree16(vp, sizeof(CBTACTIVATESTRUCT16)); break;
case HCBT_CLICKSKIPPED:
GETMISCPTR(vp, pMHStruct16); GETMOUSEHOOKSTRUCT16(pMHStruct16, (LPMOUSEHOOKSTRUCT)lParam); FREEVDMPTR(pMHStruct16); stackfree16(vp, sizeof(MOUSEHOOKSTRUCT16)); break;
// case HCBT_MINMAX:
// case HCBT_QS:
// case HCBT_DESTROYWND:
// case HCBT_KEYSKIPPED:
// case HCBT_SYSCOMMAND:
// case HCBT_SETFOCUS:
default: break; }
// the value in LOWORD is the valid return value
return (LONG)(BOOL)LOWORD(lReturn); }
//*****************************************************************************
//
// ThunkHookProc for Hooks of type WH_KEYBOARD -
//
// Return type is BOOL.
//
//*****************************************************************************
LONG ThunkKeyBoardHook(INT nCode, LONG wParam, LONG lParam, LPHOOKSTATEDATA lpHSData) { LONG lReturn; PARM16 Parm16;
Parm16.HookProc.nCode = (SHORT)nCode; Parm16.HookProc.wParam = (SHORT)wParam; Parm16.HookProc.lParam = lParam;
CallBack16(RET_HOOKPROC, &Parm16, lpHSData->Proc16, (PVPVOID)&lReturn);
// the value in LOWORD is the valid return value
return (LONG)(BOOL)LOWORD(lReturn); }
//*****************************************************************************
//
// ThunkHookProc for Hooks of type WH_GETMESSAGE -
// WH_MSGFILTER -
// WH_SYSMSGFILTER -
//
// WARNING: May cause 16-bit memory movement, invalidating flat pointers.
//
// Return type is BOOL.
//
//*****************************************************************************
LONG ThunkMsgFilterHook(INT nCode, LONG wParam, LPMSG lpMsg, LPHOOKSTATEDATA lpHSData) { VPVOID vp; PMSG16 pMsg16; PARM16 Parm16; WM32MSGPARAMEX wm32mpex;
BOOL fHookModifiedLpMsg; HWND hwnd32; MSGPARAMEX mpex; BOOL fUseOld; static MSG msgSave; static int cRecurse = 0; static PARM16 Parm16Save; BOOL fMessageNeedsThunking;
// This should be removed when all thunk functions appropiately fill these
// in, till then we must have these 3 lines before calling thunk functions !
// ChandanC, 2/28/92
//
wm32mpex.Parm16.WndProc.wMsg = (WORD) lpMsg->message; wm32mpex.Parm16.WndProc.wParam = (WORD) lpMsg->wParam; wm32mpex.Parm16.WndProc.lParam = (LONG) lpMsg->lParam;
fMessageNeedsThunking = (lpMsg->message < 0x400) && (aw32Msg[lpMsg->message].lpfnM32 != WM32NoThunking); fThunkDDEmsg = FALSE;
if (fMessageNeedsThunking) { LOGDEBUG(3,("%04X (%s)\n", CURRENTPTD()->htask16, (aw32Msg[lpMsg->message].lpszW32)));
wm32mpex.fThunk = THUNKMSG; wm32mpex.hwnd = lpMsg->hwnd; wm32mpex.uMsg = lpMsg->message; wm32mpex.uParam = lpMsg->wParam; wm32mpex.lParam = lpMsg->lParam; wm32mpex.pww = (PWW)NULL; wm32mpex.fFree = FALSE; wm32mpex.lpfnM32 = aw32Msg[wm32mpex.uMsg].lpfnM32; if (!((wm32mpex.lpfnM32)(&wm32mpex))) { LOGDEBUG(LOG_ALWAYS,("ThunkMsgFilterHook: cannot thunk 32-bit message %04x\n", lpMsg->message)); } }
fThunkDDEmsg = TRUE;
//
// Check to see if we've recursed into this routine. If so and the message
// contents are the same, use the last message pointer we gave the 16
// bit app rather than allocating a new one. Need this to solve the
// SoundBits Browser problem. It checks to see if the lpmsg passed
// is the same as it got last time - if so, it doesn't call this other
// function that causes recursion.
//
fUseOld = FALSE;
if (cRecurse != 0 && lpMsg->hwnd == msgSave.hwnd && lpMsg->message == msgSave.message && lpMsg->wParam == msgSave.wParam && lpMsg->lParam == msgSave.lParam && lpMsg->time == msgSave.time && lpMsg->pt.x == msgSave.pt.x && lpMsg->pt.y == msgSave.pt.y) {
fUseOld = TRUE;
} else { //
// Not the same... reset this thing in case the count is screwed
// up. Also remember this message, in case we do recurse.
//
cRecurse = 0; msgSave = *lpMsg; }
if (!fUseOld) { vp = malloc16(sizeof(MSG16)); if (vp == (VPVOID)NULL) return FALSE;
GETMISCPTR(vp, pMsg16); STOREWORD(pMsg16->hwnd, GETHWND16((lpMsg)->hwnd)); STOREWORD(pMsg16->message, wm32mpex.Parm16.WndProc.wMsg ); STOREWORD(pMsg16->wParam, wm32mpex.Parm16.WndProc.wParam); STORELONG(pMsg16->lParam, wm32mpex.Parm16.WndProc.lParam); STORELONG(pMsg16->time, (lpMsg)->time); STOREWORD(pMsg16->pt.x, (lpMsg)->pt.x); STOREWORD(pMsg16->pt.y, (lpMsg)->pt.y);
Parm16.HookProc.nCode = (SHORT)nCode; Parm16.HookProc.wParam = (SHORT)wParam; Parm16.HookProc.lParam = vp;
//
// Remember Parm16 in case we need to use it again due to the recursion
// case.
//
Parm16Save = Parm16;
} else {
//
// Use old message contents.
//
Parm16 = Parm16Save; vp = (VPVOID)Parm16Save.HookProc.lParam;
GETMISCPTR(vp, pMsg16); }
FLUSHVDMPTR(vp, sizeof(MSG16), pMsg16);
//
// Count how many times we recurse through this hook proc. Need this count
// to solve the SoundBits Browser problem. It checks to see if the lpMsg
// passed is the same as it got last time - if so, it doesn't call this
// other function that causes recursion.
//
cRecurse++; CallBack16(RET_HOOKPROC, &Parm16, lpHSData->Proc16, (PVPVOID)&wm32mpex.lReturn); cRecurse--;
// set the correct return value BEFORE unthunking
wm32mpex.lReturn = (LONG)(BOOL)LOWORD(wm32mpex.lReturn);
//
// Free the 32 pointer to 16 bit args and get it again in case underlying
// memory movement occured.
//
FREEVDMPTR(pMsg16); GETMISCPTR(vp, pMsg16);
fThunkDDEmsg = FALSE;
// Theoretically an app can change the lpMsg and return a totall different
// data altogether. In practice most apps don't do anything so it is pretty
// expensive to go through the 'unthunk' procedure all the time. So here is
// a compromise. We copy the message params only if the output message is
// different from the input message.
//
// (davehart) Polaris PackRat modifies WM_KEYDOWN messages sent to its
// multiline "Note" edit control in its Phone Book Entry dialog box.
// It changes wParam (the VK_ code) from 0xD (VK_RETURN) to 0xA, which
// is understood by the edit control to be identical to VK_RETURN but
// won't cause the dialog box to close. So we special-case here
// WM_KEYDOWN where the hook proc changed the virtual key (in wParam)
// and unthunk it properly.
fHookModifiedLpMsg = (pMsg16->message != wm32mpex.Parm16.WndProc.wMsg) || (wm32mpex.Parm16.WndProc.wMsg == WM_KEYDOWN && pMsg16->wParam != wm32mpex.Parm16.WndProc.wParam) || (pMsg16->hwnd != GETHWND16(lpMsg->hwnd));
if (fHookModifiedLpMsg) { mpex.Parm16.WndProc.hwnd = pMsg16->hwnd; mpex.Parm16.WndProc.wMsg = pMsg16->message; mpex.Parm16.WndProc.wParam = pMsg16->wParam; mpex.Parm16.WndProc.lParam = pMsg16->lParam, mpex.iMsgThunkClass = WOWCLASS_WIN16; hwnd32 = ThunkMsg16(&mpex);
//
// Free the 32 pointer to 16 bit args and get it again in case
// underlying memory movement occured.
//
FREEVDMPTR(pMsg16); GETMISCPTR(vp, pMsg16);
// reset flag if message thunking failed.
if (!hwnd32) fHookModifiedLpMsg = FALSE; }
if (fMessageNeedsThunking) {
wm32mpex.fThunk = UNTHUNKMSG; (wm32mpex.lpfnM32)(&wm32mpex);
//
// Free the 32 pointer to 16 bit args and get it again in case
// underlying memory movement occured.
//
FREEVDMPTR(pMsg16); GETMISCPTR(vp, pMsg16); }
fThunkDDEmsg = TRUE;
if (fHookModifiedLpMsg) { lpMsg->hwnd = hwnd32; lpMsg->message = mpex.uMsg; lpMsg->wParam = mpex.uParam; lpMsg->lParam = mpex.lParam; lpMsg->time = FETCHLONG(pMsg16->time); lpMsg->pt.x = FETCHSHORT(pMsg16->pt.x); lpMsg->pt.y = FETCHSHORT(pMsg16->pt.y); }
FREEVDMPTR(pMsg16);
if (!fUseOld) { free16(vp); }
// the value in LOWORD is the valid return value
return (LONG)(BOOL)LOWORD(wm32mpex.lReturn); }
//*****************************************************************************
//
// ThunkHookProc for Hooks of type WH_JOURNALPLAYBACK -
// WH_JOUNRALRECORD -
//
// Return type is DWORD.
//
//*****************************************************************************
LONG ThunkJournalHook(INT nCode, LONG wParam, LPEVENTMSG lpEventMsg, LPHOOKSTATEDATA lpHSData) { LONG lReturn; VPVOID vp; PEVENTMSG16 pEventMsg16; PARM16 Parm16;
if ( lpEventMsg ) {
// be sure allocation size matches stackfree16() size below
vp = stackalloc16(sizeof(EVENTMSG16));
// The WIN32 EVENTMSG structure has an additional field 'hwnd', which
// is not there in WIN31 EVENTMSG structure. This field can be ignored
// without any repercussions.
if (lpHSData->iHook == WH_JOURNALRECORD) { GETMISCPTR(vp, pEventMsg16); PUTEVENTMSG16(pEventMsg16, lpEventMsg); FLUSHVDMPTR(vp, sizeof(EVENTMSG16), pEventMsg16); FREEVDMPTR(pEventMsg16); }
} else { // lpEventMsg can be NULL indicating that no message data is requested.
// If this is the case, there is no need to copy data for either
// journal record or playback.
vp = (VPVOID)0; }
Parm16.HookProc.nCode = (SHORT)nCode; Parm16.HookProc.wParam = (SHORT)wParam; Parm16.HookProc.lParam = vp;
CallBack16(RET_HOOKPROC, &Parm16, lpHSData->Proc16, (PVPVOID)&lReturn);
if ( lpEventMsg ) { GETMISCPTR(vp, pEventMsg16);
if (lpHSData->iHook == WH_JOURNALPLAYBACK) { GetEventMessage16(pEventMsg16, lpEventMsg); #ifdef FE_SB
switch (lpEventMsg->message) { case WM_CHAR: case WM_CHARTOITEM: case WM_DEADCHAR: case WM_KEYDOWN: case WM_KEYUP: case WM_MENUCHAR: case WM_SYSCHAR: case WM_SYSDEADCHAR: case WM_SYSKEYDOWN: case WM_SYSKEYUP: case WM_VKEYTOITEM: // only virtual key, not use scan code
lpEventMsg->paramL &= 0x0ff; } #endif // FE_SB
#ifdef DEBUG
if (MessageNeedsThunking(lpEventMsg->message)) { LOGDEBUG(LOG_ALWAYS, ("ThunkJournalHook: Playing back unexpected message 0x%x", lpEventMsg->message)); } #endif
} else { WOW32ASSERT(lpHSData->iHook == WH_JOURNALRECORD); WOW32ASSERT(aw32Msg[FETCHWORD(pEventMsg16->message)].lpfnM32 == WM32NoThunking);
// If the app modified the message then copy the new message info
// (rather than copying it every time we only copy it if the
// app change the message)
if (FETCHWORD(pEventMsg16->message) != lpEventMsg->message) { GetEventMessage16(pEventMsg16, lpEventMsg); } }
FREEVDMPTR(pEventMsg16); if(vp) { stackfree16(vp, sizeof(EVENTMSG16)); } }
return lReturn; }
//*****************************************************************************
//
// ThunkHookProc for Hooks of type WH_DEBUG -
//
// Return type is BOOL.
//
//*****************************************************************************
LONG ThunkDebugHook(INT nCode, LONG wParam, LONG lParam, LPHOOKSTATEDATA lpHSData) { LONG lReturn;
lReturn = TRUE;
UNREFERENCED_PARAMETER(nCode); UNREFERENCED_PARAMETER(wParam); UNREFERENCED_PARAMETER(lParam); UNREFERENCED_PARAMETER(lpHSData);
LOGDEBUG(LOG_ALWAYS, ("ThunkDebugHook:Not implemented.\n"));
// the value in LOWORD is the valid return value
return (LONG)(BOOL)LOWORD(lReturn); }
//*****************************************************************************
//
// ThunkHookProc for Hooks of type WH_MOUSE -
//
// Return type is BOOL.
//
//*****************************************************************************
LONG ThunkMouseHook(INT nCode, LONG wParam, LPMOUSEHOOKSTRUCT lpMHStruct, LPHOOKSTATEDATA lpHSData) { LONG lReturn; VPVOID vp; PMOUSEHOOKSTRUCT16 pMHStruct16; PARM16 Parm16;
// be sure allocation size matches stackfree16() size below
vp = stackalloc16(sizeof(MOUSEHOOKSTRUCT16));
GETMISCPTR(vp, pMHStruct16); PUTMOUSEHOOKSTRUCT16(pMHStruct16, lpMHStruct);
Parm16.HookProc.nCode = (SHORT)nCode; Parm16.HookProc.wParam = (SHORT)wParam; Parm16.HookProc.lParam = vp;
FLUSHVDMPTR(vp, sizeof(MOUSEHOOKSTRUCT16), pMHStruct16); FREEVDMPTR(pMHStruct16);
CallBack16(RET_HOOKPROC, &Parm16, lpHSData->Proc16, (PVPVOID)&lReturn);
GETMISCPTR(vp, pMHStruct16); GETMOUSEHOOKSTRUCT16(pMHStruct16, lpMHStruct); FREEVDMPTR(pMHStruct16); if(vp) { stackfree16(vp, sizeof(MOUSEHOOKSTRUCT16)); } return (LONG)(BOOL)LOWORD(lReturn); }
//*****************************************************************************
//
// ThunkHookProc for Hooks of type WH_SHELL -
//
// Return value apparently is zero.
//
//*****************************************************************************
LONG ThunkShellHook(INT nCode, LONG wParam, LONG lParam, LPHOOKSTATEDATA lpHSData) { LONG lReturn; PARM16 Parm16;
Parm16.HookProc.nCode = (SHORT)nCode; Parm16.HookProc.lParam = lParam;
switch (nCode) { case HSHELL_WINDOWCREATED: case HSHELL_WINDOWDESTROYED: Parm16.HookProc.wParam = (SHORT)GETHWND16(wParam); break;
case HSHELL_ACTIVATESHELLWINDOW: // fall thru
default: Parm16.HookProc.wParam = (SHORT)wParam; break; }
CallBack16(RET_HOOKPROC, &Parm16, lpHSData->Proc16, (PVPVOID)&lReturn);
// lReturn = 0?
return (LONG)lReturn; }
//*****************************************************************************
// W32UnhookHooks:
//
// Scans the list of active hooks for those for the passed in handle.
// Those that match are unhooked.
//
//*****************************************************************************
VOID W32UnhookHooks( HAND16 hMod16, BOOL fQueue ) { INT i;
for (i = 0; i < vaHookPPData.cHookProcs; i++) { if (vaHookStateData[i].InUse ) {
if ( !fQueue && ((HAND16)(vaHookStateData[i].hMod16) == hMod16) ) { //
// Unhook this guy!
//
if (UnhookWindowsHookEx(vaHookStateData[i].hHook)) { LOGDEBUG(7, ("W32FreeModuleHooks: Freed iHook (WH_*) %04x\n", vaHookStateData[i].iHook)); } else { LOGDEBUG(LOG_ALWAYS, ("W32FreeModuleHooks: ERROR Freeing iHook (WH_*) %04x\n", vaHookStateData[i].iHook)); }
// reset the state, even if Unhooking failed.
vaHookStateData[i].TaskId = 0; vaHookStateData[i].InUse = FALSE; } } } }
//*****************************************************************************
// W32FreeOwnedHooks -
//
// Called during thread exit time. Frees all hooks set by specified thread.
//
//*****************************************************************************
BOOL W32FreeOwnedHooks(INT iTaskId) { INT i; for (i = 0; i < vaHookPPData.cHookProcs; i++) { if (vaHookStateData[i].InUse && vaHookStateData[i].TaskId == iTaskId) { if (UnhookWindowsHookEx(vaHookStateData[i].hHook)) { LOGDEBUG(7, ("W32FreeOwnedHooks: Freed iHook (WH_*) %04x\n", vaHookStateData[i].iHook)); } else { LOGDEBUG(LOG_ALWAYS, ("W32FreeOwnedHooks: ERROR Freeing iHook (WH_*) %04x\n", vaHookStateData[i].iHook)); }
// reset the state, even if Unhooking failed.
vaHookStateData[i].TaskId = 0; vaHookStateData[i].InUse = FALSE; } }
return TRUE; }
//*****************************************************************************
// W32StdDefHookProc: (Standard Def Hook Proc)
//
// WU32DefHookProc is called here.
// WARNING: May cause 16-bit memory movement, invalidating flat pointers.
// Return value is the new lParam.
//
//*****************************************************************************
LONG APIENTRY WU32StdDefHookProc(INT nCode, LONG wParam, LONG lParam, INT iFunc) { switch (vaHookStateData[iFunc].iHook) { case WH_CALLWNDPROC: return ThunkCallWndProcHook16(nCode, wParam, (VPVOID)lParam, &vaHookStateData[iFunc]);
case WH_CBT:
return ThunkCbtHook16(nCode, wParam, (VPVOID)lParam, &vaHookStateData[iFunc]);
case WH_KEYBOARD: return ThunkKeyBoardHook16(nCode, wParam, lParam, &vaHookStateData[iFunc]);
case WH_MSGFILTER: case WH_SYSMSGFILTER: case WH_GETMESSAGE:
return ThunkMsgFilterHook16(nCode, wParam, (VPVOID)lParam, &vaHookStateData[iFunc]);
case WH_JOURNALPLAYBACK: case WH_JOURNALRECORD: return ThunkJournalHook16(nCode, wParam, (VPVOID)lParam, &vaHookStateData[iFunc]);
case WH_DEBUG: return ThunkDebugHook16(nCode, wParam, lParam, &vaHookStateData[iFunc]);
case WH_MOUSE: return ThunkMouseHook16(nCode, wParam, (VPVOID)lParam, &vaHookStateData[iFunc]);
case WH_SHELL: return ThunkShellHook16(nCode, wParam, lParam, &vaHookStateData[iFunc]);
default: LOGDEBUG(LOG_ALWAYS,("WU32StdDefHookProc: Unknown Hook type.\n")); }
return (LONG)FALSE;
}
//*****************************************************************************
//
// 16->32 ThunkHookProc for Hooks of type WH_CALLWNDPROC -
//
// Return type is VOID.
//
//*****************************************************************************
LONG ThunkCallWndProcHook16(INT nCode, LONG wParam, VPVOID vpCwpStruct, LPHOOKSTATEDATA lpHSData) { CWPSTRUCT CwpStruct; PCWPSTRUCT16 pCwpStruct16; MSGPARAMEX mpex;
GETMISCPTR(vpCwpStruct, pCwpStruct16);
mpex.Parm16.WndProc.hwnd = pCwpStruct16->hwnd; mpex.Parm16.WndProc.wMsg = pCwpStruct16->message; mpex.Parm16.WndProc.wParam = pCwpStruct16->wParam; mpex.Parm16.WndProc.lParam = pCwpStruct16->lParam, mpex.iMsgThunkClass = WOWCLASS_WIN16;
mpex.hwnd = ThunkMsg16(&mpex); // memory may have moved
FREEVDMPTR(pCwpStruct16);
CwpStruct.message = mpex.uMsg; CwpStruct.wParam = mpex.uParam; CwpStruct.lParam = mpex.lParam; CwpStruct.hwnd = mpex.hwnd;
mpex.lReturn = CallNextHookEx(lpHSData->hHook, nCode, wParam, (LPARAM)&CwpStruct); if (MSG16NEEDSTHUNKING(&mpex)) { mpex.uMsg = CwpStruct.message; mpex.uParam = CwpStruct.wParam; mpex.lParam = CwpStruct.lParam; (mpex.lpfnUnThunk16)(&mpex); }
return mpex.lReturn; }
//*****************************************************************************
//
// 16->32 ThunkHookProc for Hooks of type WH_CBT -
//
// Return type is BOOL.
//
//*****************************************************************************
LONG ThunkCbtHook16(INT nCode, LONG wParam, VPVOID lParam, LPHOOKSTATEDATA lpHSData) { LONG lReturn = FALSE; WPARAM wParamNew; LPARAM lParamNew; MSGPARAMEX mpex;
PMOUSEHOOKSTRUCT16 pMHStruct16; PCBTACTIVATESTRUCT16 pCbtAStruct16; PCBT_CREATEWND16 pCbtCWnd16; PRECT16 pRect16;
MOUSEHOOKSTRUCT MHStruct; RECT Rect; CBTACTIVATESTRUCT CbtAStruct; CBT_CREATEWND CbtCWnd;
// SudeepB 28-May-1996 updated DaveHart 16-July-96 to fix limit assertions.
//
// Some apps like SureTrack project management package are passing
// corrupted values in lParam. GETVDMPTR returns 0 for such an lParam.
// Using this 0 on X86 causes corruption of IVT and on RISC causes an
// AV in wow32 as zero is not a valid linear address. Such apps get
// away from such criminal acts on win3.1/Win95 as no thunking is needed
// there. So all the thunking below explicitly checks for GETVDMPTR
// returning 0 and in that case just leaves lParam unthunked.
wParamNew = (WPARAM) wParam; lParamNew = (LPARAM) lParam;
switch(nCode) {
//
// These don't have a pointer in lParam.
//
case HCBT_SETFOCUS: // wParam = HWND, lParam = HWND
// fall through to set wParamNew & lParamNew,
// this counts on HWND32 zero-extending.
case HCBT_MINMAX: // wParam = HWND, lParam = SW_* --- a command
// fall through to set wParamNew & lParamNew.
// this counts on HWND32 zero-extending.
case HCBT_DESTROYWND: // wParam = HWND, lParam = 0
// fall through to set wParamNew & lParamNew.
// this counts on HWND32 zero-extending.
WOW32ASSERTMSG((HWND32(0x1234) == (HWND)0x1234), "Code depending on HWND32 zero-extending needs revision.\n");
case HCBT_QS: // wParam = 0, lParam = 0
case HCBT_KEYSKIPPED: // wParam = VK_ keycode, lParam = WM_KEYUP/DOWN lParam
case HCBT_SYSCOMMAND: // wParam = SC_ syscomand, lParam = DWORD(x,y) if mouse
// lParamNew and wParamNew are initialized above with no thunking.
break;
//
// These use lParam as a pointer.
//
case HCBT_MOVESIZE: // wParam = HWND, lParam = LPRECT
#if 0 // HWND32 is a no-op, wParamNew already initialized.
wParamNew = (WPARAM) HWND32(wParam); #endif
GETVDMPTR(lParam, sizeof(*pRect16), pRect16); if (pRect16) { GETRECT16(lParam, &Rect); lParamNew = (LPARAM)&Rect; FREEVDMPTR(pRect16); } break;
case HCBT_CREATEWND: // wParam = HWND, lParam = LPCBT_CREATEWND
#if 0 // HWND32 is a no-op, wParamNew already initialized.
wParamNew = (WPARAM) HWND32(wParam); #endif
GETVDMPTR(lParam, sizeof(*pCbtCWnd16), pCbtCWnd16); if (pCbtCWnd16) { lParamNew = (LPARAM)&CbtCWnd;
mpex.Parm16.WndProc.hwnd = LOWORD(wParam); mpex.Parm16.WndProc.wMsg = WM_CREATE; mpex.Parm16.WndProc.wParam = 0; mpex.Parm16.WndProc.lParam = FETCHDWORD(pCbtCWnd16->vpcs); mpex.iMsgThunkClass = 0;
ThunkMsg16(&mpex);
//
// Memory movement can occur on the 16-bit side.
//
FREEVDMPTR(pCbtCWnd16); GETVDMPTR(lParam, sizeof(*pCbtCWnd16), pCbtCWnd16);
(LONG)CbtCWnd.lpcs = mpex.lParam; CbtCWnd.hwndInsertAfter = HWNDIA32(FETCHWORD(pCbtCWnd16->hwndInsertAfter));
FREEVDMPTR(pCbtCWnd16); } break;
case HCBT_ACTIVATE: // wParam = HWND, lParam = LPCBTACTIVATESTRUCT
#if 0 // HWND32 is a no-op, wParamNew already initialized.
wParamNew = (WPARAM) HWND32(wParam); #endif
GETVDMPTR(lParam, sizeof(*pCbtAStruct16), pCbtAStruct16); if (pCbtAStruct16) { lParamNew = (LPARAM)&CbtAStruct; GETCBTACTIVATESTRUCT16(pCbtAStruct16, &CbtAStruct); FREEVDMPTR(pCbtAStruct16); }
break;
case HCBT_CLICKSKIPPED: // wParam = mouse message, lParam = LPMOUSEHOOKSTRUCT
GETVDMPTR(lParam, sizeof(*pMHStruct16), pMHStruct16); if (pMHStruct16) { lParamNew = (LPARAM)&MHStruct; GETMOUSEHOOKSTRUCT16(pMHStruct16, &MHStruct); FREEVDMPTR(pMHStruct16); } break;
default: LOGDEBUG(LOG_ALWAYS, ("ThunkCbtHook: Unknown HCBT_ code 0x%x\n", nCode)); break; }
//
// Call the hook, memory movement can occur.
//
lReturn = CallNextHookEx(lpHSData->hHook, nCode, wParamNew, lParamNew);
switch(nCode) {
//
// These don't have a pointer in lParam.
//
// case HCBT_SETFOCUS: // wParam = HWND, lParam = HWND
// case HCBT_MINMAX: // wParam = HWND, lParam = SW_* --- a command
// case HCBT_DESTROYWND: // wParam = HWND, lParam = 0
// case HCBT_QS: // wParam = 0, lParam = 0
// case HCBT_KEYSKIPPED: // wParam = VK_ keycode, lParam = WM_KEYUP/DOWN lParam
// case HCBT_SYSCOMMAND: // wParam = SC_ syscomand, lParam = DWORD(x,y) if mouse
// break;
//
// These use lParam as a pointer.
//
case HCBT_MOVESIZE: // wParam = HWND, lParam = LPRECT
PUTRECT16(lParam, (LPRECT)lParamNew); break;
case HCBT_CREATEWND: // wParam = HWND, lParam = LPCBT_CREATEWND
GETVDMPTR(lParam, sizeof(*pCbtCWnd16), pCbtCWnd16); if (pCbtCWnd16) { mpex.lParam = (LONG)CbtCWnd.lpcs; mpex.lReturn = lReturn; WOW32ASSERT(MSG16NEEDSTHUNKING(&mpex)); (mpex.lpfnUnThunk16)(&mpex); lReturn = mpex.lReturn;
STOREWORD(pCbtCWnd16->hwndInsertAfter, GETHWNDIA16(((LPCBT_CREATEWND)lParamNew)-> hwndInsertAfter)); FLUSHVDMPTR((VPVOID)lParam, sizeof(CBT_CREATEWND16), pCbtCWnd16); FREEVDMPTR(pCbtCWnd16); } break;
case HCBT_ACTIVATE: // wParam = HWND, lParam = LPCBTACTIVATESTRUCT
GETVDMPTR(lParam, sizeof(*pCbtAStruct16), pCbtAStruct16); if (pCbtAStruct16) { PUTCBTACTIVATESTRUCT16(pCbtAStruct16, (LPCBTACTIVATESTRUCT)lParamNew); FLUSHVDMPTR((VPVOID)lParam, sizeof(CBTACTIVATESTRUCT16), pCbtAStruct16); FREEVDMPTR(pCbtAStruct16); } break;
case HCBT_CLICKSKIPPED: // wParam = mouse message, lParam = LPMOUSEHOOKSTRUCT
GETVDMPTR(lParam, sizeof(*pMHStruct16), pMHStruct16); if (pMHStruct16) { PUTMOUSEHOOKSTRUCT16(pMHStruct16, (LPMOUSEHOOKSTRUCT)lParamNew); FLUSHVDMPTR((VPVOID)lParam, sizeof(MOUSEHOOKSTRUCT16), pMHStruct16); FREEVDMPTR(pMHStruct16); } break;
}
// the value in LOWORD is the valid return value
return (LONG)(BOOL)LOWORD(lReturn); }
//*****************************************************************************
//
// 16->32 ThunkHookProc for Hooks of type WH_KEYBOARD -
//
// Return type is BOOL.
//
//*****************************************************************************
LONG ThunkKeyBoardHook16(INT nCode, LONG wParam, LONG lParam, LPHOOKSTATEDATA lpHSData) { LONG lReturn;
lReturn = CallNextHookEx(lpHSData->hHook, nCode, wParam, (LPARAM)lParam);
// the value in LOWORD is the valid return value
return (LONG)(BOOL)LOWORD(lReturn); }
//*****************************************************************************
//
// 16->32 ThunkHookProc for Hooks of type WH_GETMESSAGE -
// WH_MSGFILTER -
// WH_SYSMSGFILTER -
//
// Return type is BOOL.
//
//*****************************************************************************
LONG ThunkMsgFilterHook16(INT nCode, LONG wParam, VPVOID vpMsg, LPHOOKSTATEDATA lpHSData) { PMSG16 pMsg16; MSG Msg; MSGPARAMEX mpex;
GETMISCPTR(vpMsg, pMsg16);
fThunkDDEmsg = FALSE;
mpex.Parm16.WndProc.hwnd = pMsg16->hwnd; mpex.Parm16.WndProc.wMsg = pMsg16->message; mpex.Parm16.WndProc.wParam = pMsg16->wParam; mpex.Parm16.WndProc.lParam = pMsg16->lParam; mpex.iMsgThunkClass = 0;
ThunkMsg16(&mpex);
//
// Memory movement can occur on the 16-bit side.
//
FREEVDMPTR(pMsg16); GETMISCPTR(vpMsg, pMsg16);
fThunkDDEmsg = TRUE;
Msg.message = mpex.uMsg; Msg.wParam = mpex.uParam; Msg.lParam = mpex.lParam; Msg.hwnd = HWND32(FETCHWORD(pMsg16->hwnd)); Msg.time = FETCHLONG(pMsg16->time); Msg.pt.x = FETCHSHORT(pMsg16->pt.x); Msg.pt.y = FETCHSHORT(pMsg16->pt.y);
FREEVDMPTR(pMsg16);
mpex.lReturn = CallNextHookEx(lpHSData->hHook, nCode, wParam, (LPARAM)&Msg); GETMISCPTR(vpMsg, pMsg16);
if (MSG16NEEDSTHUNKING(&mpex)) { mpex.uMsg = Msg.message; mpex.uParam = Msg.wParam; mpex.lParam = Msg.lParam; FREEVDMPTR(pMsg16); // invalidate 16-bit ptr: memory may move
(mpex.lpfnUnThunk16)(&mpex); GETMISCPTR(vpMsg, pMsg16); // refresh 16-bit ptr
}
STORELONG(pMsg16->time, Msg.time); STOREWORD(pMsg16->pt.x, Msg.pt.x); STOREWORD(pMsg16->pt.y, Msg.pt.y);
FLUSHVDMPTR(vpMsg, sizeof(MSG16), pMsg16); FREEVDMPTR(pMsg16);
// the value in LOWORD is the valid return value
return (LONG)(BOOL)LOWORD(mpex.lReturn); }
//*****************************************************************************
//
// 16->32 ThunkHookProc for Hooks of type WH_JOURNALPLAYBACK -
// WH_JOUNRALRECORD -
//
// Return type is DWORD.
//
//*****************************************************************************
LONG ThunkJournalHook16(INT nCode, LONG wParam, VPVOID vpEventMsg, LPHOOKSTATEDATA lpHSData) { LONG lReturn; PEVENTMSG16 pEventMsg16; EVENTMSG EventMsg; LPEVENTMSG lpEventMsg;
if ( vpEventMsg ) {
// The WIN32 EVENTMSG structure has an additional field 'hwnd', which
// is not there in WIN31 EVENTMSG structure. This field can be ignored
// without any repercussions.
if (lpHSData->iHook == WH_JOURNALRECORD) { GETMISCPTR(vpEventMsg, pEventMsg16); GetEventMessage16(pEventMsg16, &EventMsg); EventMsg.hwnd = (HWND)0; FREEVDMPTR(pEventMsg16); } lpEventMsg = &EventMsg;
} else { lpEventMsg = NULL; }
lReturn = CallNextHookEx(lpHSData->hHook, nCode, wParam, (LPARAM)lpEventMsg );
if ( vpEventMsg ) {
if (lpHSData->iHook == WH_JOURNALPLAYBACK) { GETMISCPTR(vpEventMsg, pEventMsg16); PUTEVENTMSG16(pEventMsg16, &EventMsg); FLUSHVDMPTR(vpEventMsg, sizeof(EVENTMSG16), pEventMsg16); FREEVDMPTR(pEventMsg16); }
}
return lReturn; }
//*****************************************************************************
//
// 16->32 ThunkHookProc for Hooks of type WH_DEBUG -
//
// Return type is BOOL.
//
//*****************************************************************************
LONG ThunkDebugHook16(INT nCode, LONG wParam, LONG lParam, LPHOOKSTATEDATA lpHSData) { LONG lReturn;
lReturn = TRUE;
UNREFERENCED_PARAMETER(nCode); UNREFERENCED_PARAMETER(wParam); UNREFERENCED_PARAMETER(lParam); UNREFERENCED_PARAMETER(lpHSData);
LOGDEBUG(LOG_ALWAYS, ("ThunkDebugHook16:Not implemented.\n"));
// the value in LOWORD is the valid return value
return (LONG)(BOOL)LOWORD(lReturn); }
//*****************************************************************************
//
// 16->32 ThunkHookProc for Hooks of type WH_MOUSE -
//
// Return type is BOOL.
//
//*****************************************************************************
LONG ThunkMouseHook16(INT nCode, LONG wParam, VPVOID vpMHStruct, LPHOOKSTATEDATA lpHSData) { LONG lReturn; PMOUSEHOOKSTRUCT16 pMHStruct16; MOUSEHOOKSTRUCT MHStruct;
GETMISCPTR(vpMHStruct, pMHStruct16); GETMOUSEHOOKSTRUCT16(pMHStruct16, &MHStruct); FREEVDMPTR(pMHStruct16);
lReturn = CallNextHookEx(lpHSData->hHook, nCode, wParam, (LPARAM)&MHStruct);
GETMISCPTR(vpMHStruct, pMHStruct16); PUTMOUSEHOOKSTRUCT16(pMHStruct16, &MHStruct); FLUSHVDMPTR((VPVOID)vpMHStruct, sizeof(MOUSEHOOKSTRUCT16), pMHStruct16); FREEVDMPTR(pMHStruct16);
return (LONG)(BOOL)LOWORD(lReturn); }
//*****************************************************************************
//
// 16->32 ThunkHookProc for Hooks of type WH_SHELL -
//
// Return value is apparently zero.
//
//*****************************************************************************
LONG ThunkShellHook16(INT nCode, LONG wParam, LONG lParam, LPHOOKSTATEDATA lpHSData) { LONG lReturn;
switch (nCode) { case HSHELL_WINDOWCREATED: case HSHELL_WINDOWDESTROYED: wParam = (LONG)HWND32(wParam); break;
case HSHELL_ACTIVATESHELLWINDOW: // fall thru
default: break; }
lReturn = CallNextHookEx(lpHSData->hHook, nCode, wParam, (LPARAM)lParam);
// lReturn = 0?
return (LONG)lReturn; }
//*****************************************************************************
// W32GetHookDDEMsglParam:
//
// Returns the lParam of the actual hook message. called for dde messages
// only. returns valid lParam else 0.
//
//*****************************************************************************
DWORD W32GetHookDDEMsglParam() { INT iFunc; LONG lParam;
iFunc = viCurrentHookStateDataIndex; lParam = vHookParams.lParam;
if (lParam) { switch (vaHookStateData[iFunc].iHook) { case WH_CALLWNDPROC: lParam = ((LPCWPSTRUCT)lParam)->lParam; break;
case WH_MSGFILTER: case WH_SYSMSGFILTER: case WH_GETMESSAGE: lParam = ((LPMSG)lParam)->lParam; break;
default: lParam = 0; } }
return lParam;
}
//*****************************************************************************
// GetEventMessage16:
//
//*****************************************************************************
VOID GetEventMessage16(PEVENTMSG16 pEventMsg16, LPEVENTMSG lpEventMsg) { lpEventMsg->message = FETCHWORD(pEventMsg16->message); lpEventMsg->time = FETCHLONG(pEventMsg16->time); if ((lpEventMsg->message >= WM_KEYFIRST) && (lpEventMsg->message <= WM_KEYLAST)) { // Key event
lpEventMsg->paramL = FETCHWORD(pEventMsg16->paramL); lpEventMsg->paramH = FETCHWORD(pEventMsg16->paramH) & 0x8000; lpEventMsg->paramH |= (lpEventMsg->paramL & 0xFF00) >> 8; lpEventMsg->paramL &= 0xFF; } else { // Mouse event
lpEventMsg->paramL = FETCHWORD(pEventMsg16->paramL); lpEventMsg->paramH = FETCHWORD(pEventMsg16->paramH); } }
|