You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3762 lines
118 KiB
3762 lines
118 KiB
/*++
|
|
|
|
*
|
|
* WOW v1.0
|
|
*
|
|
* Copyright (c) 1991, Microsoft Corporation
|
|
*
|
|
* WMDISP32.C
|
|
* WOW32 32-bit message thunks
|
|
*
|
|
* History:
|
|
* Created 19-Feb-1992 by Chandan S. Chauhan (ChandanC)
|
|
* Changed 12-May-1992 by Mike Tricker (MikeTri) Added MultiMedia thunks
|
|
* Changed 09-Jul-1992 by v-cjones Added msg profiling debugger extension
|
|
--*/
|
|
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
#ifdef FE_IME
|
|
#include "wownls.h"
|
|
#include "ime.h"
|
|
#include "prshtp.h"
|
|
#endif // FE_IME
|
|
|
|
MODNAME(wmdisp32.c);
|
|
|
|
BOOL fThunkDDEmsg = TRUE;
|
|
|
|
extern WORD msgFINDREPLACE; // see WCOMMDLG.C
|
|
|
|
#ifdef WOWPROFILE // for MSG profiling only (debugger extension)
|
|
INT fWMsgProfRT = 0;
|
|
#endif
|
|
|
|
|
|
BOOL W32Win16DlgProcEx(HWND hdlg, UINT uMsg, UINT uParam, LONG lParam,
|
|
VPWNDPROC vpDlgProc16, // Next WndProc to call or NULL if default
|
|
PWW pww) // hwnd's PWW if already known or NULL
|
|
{
|
|
BOOL fSuccess;
|
|
register PTD ptd;
|
|
WM32MSGPARAMEX wm32mpex;
|
|
BOOL fMessageNeedsThunking;
|
|
|
|
#ifdef WOWPROFILE // for MSG profiling only (debugger extension)
|
|
LONGLONG dwTics;
|
|
#endif
|
|
|
|
ptd = CURRENTPTD();
|
|
|
|
WOW32ASSERT(vpDlgProc16);
|
|
|
|
// take out the marker bits and fix the RPL bits
|
|
UnMarkWOWProc (vpDlgProc16,vpDlgProc16);
|
|
|
|
// If the app has GP Faulted we don't want to pass it any more input
|
|
// This should be removed when USER32 does clean up on task death so
|
|
// it doesn't call us - mattfe june 24 92 HACK32
|
|
|
|
if (ptd->dwFlags & TDF_IGNOREINPUT) {
|
|
LOGDEBUG(6,(" W32Dlg16WndProc Ignoring Input Messsage %04X\n",uMsg));
|
|
WOW32ASSERTMSG(gfIgnoreInputAssertGiven,
|
|
"W32Dlg16WndProc: TDF_IGNOREINPUT hack was used, shouldn't be, "
|
|
"please email DaveHart with repro instructions. Hit 'g' to ignore this "
|
|
"and suppress this assertion from now on.\n");
|
|
gfIgnoreInputAssertGiven = TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
wm32mpex.Parm16.WndProc.hwnd = GETHWND16(hdlg);
|
|
wm32mpex.Parm16.WndProc.wMsg = (WORD)uMsg;
|
|
wm32mpex.Parm16.WndProc.wParam = (WORD)uParam;
|
|
wm32mpex.Parm16.WndProc.lParam = (LONG)lParam;
|
|
wm32mpex.Parm16.WndProc.hInst = 0; // Forces AX = SS on WndProc entry,
|
|
// for Win 3.1 compatibility.
|
|
|
|
fMessageNeedsThunking = (uMsg < 0x400) &&
|
|
(aw32Msg[uMsg].lpfnM32 != WM32NoThunking);
|
|
|
|
if (fMessageNeedsThunking) {
|
|
LOGDEBUG(3,("%04X (%s)\n", CURRENTPTD()->htask16, (aw32Msg[uMsg].lpszW32)));
|
|
|
|
#ifdef WOWPROFILE // for MSG profiling only (debugger extension)
|
|
dwTics = GetWOWTicDiff(0I64);
|
|
#endif
|
|
wm32mpex.fThunk = THUNKMSG;
|
|
wm32mpex.hwnd = hdlg;
|
|
wm32mpex.uMsg = uMsg;
|
|
wm32mpex.uParam = uParam;
|
|
wm32mpex.lParam = lParam;
|
|
wm32mpex.pww = pww;
|
|
wm32mpex.fFree = TRUE;
|
|
wm32mpex.lpfnM32 = aw32Msg[uMsg].lpfnM32;
|
|
if (!(wm32mpex.lpfnM32)(&wm32mpex)) {
|
|
LOGDEBUG(LOG_ERROR,(" W32Win16DlgProcEx ERROR: cannot thunk 32-bit message %04x\n", uMsg));
|
|
goto Error;
|
|
}
|
|
|
|
#ifdef WOWPROFILE // for MSG profiling only (debugger extension)
|
|
if( !fWMsgProfRT ) { // only if not profiling round trip
|
|
aw32Msg[uMsg].cTics += GetWOWTicDiff(dwTics);
|
|
}
|
|
#endif
|
|
|
|
}
|
|
else {
|
|
LOGDEBUG(6,(" No Thunking was required for the 32-bit message %s(%04x)\n", (LPSZ)GetWMMsgName(uMsg), uMsg));
|
|
}
|
|
|
|
BlockWOWIdle(FALSE);
|
|
|
|
fSuccess = CallBack16(RET_WNDPROC, &wm32mpex.Parm16, vpDlgProc16, (PVPVOID)&wm32mpex.lReturn);
|
|
|
|
BlockWOWIdle(TRUE);
|
|
|
|
// the callback function of a dialog is of type FARPROC whose return value
|
|
// is of type 'int'. Since dx:ax is copied into lReturn in the above
|
|
// CallBack16 call, we need to zero out the hiword, otherwise we will be
|
|
// returning an erroneous value.
|
|
|
|
wm32mpex.lReturn = (LONG)((SHORT)(LOWORD(wm32mpex.lReturn)));
|
|
|
|
if (fMessageNeedsThunking) {
|
|
|
|
#ifdef WOWPROFILE // for MSG profiling only (debugger extension)
|
|
if( !fWMsgProfRT ) { // only if not round trip profiling
|
|
dwTics = GetWOWTicDiff(0I64);
|
|
}
|
|
#endif // WOWPROFILE
|
|
|
|
|
|
//
|
|
// if you send a message to a dialog what gets returned
|
|
// to the caller is the dlg's msgresult window long.
|
|
// app dialog functions will call
|
|
// SetWindowLong(hdlg, DWL_MSGRESULT, n);
|
|
// during message processing so the right thing gets returned.
|
|
// scottlu says we only need to do this for wm_gettext, it's
|
|
// the only message whose result is an output count.
|
|
//
|
|
|
|
if (uMsg == WM_GETTEXT && wm32mpex.lReturn != 0) {
|
|
wm32mpex.lReturn = GetWindowLong(hdlg, DWL_MSGRESULT);
|
|
}
|
|
|
|
wm32mpex.fThunk = UNTHUNKMSG;
|
|
(wm32mpex.lpfnM32)(&wm32mpex);
|
|
|
|
#ifdef WOWPROFILE // for MSG profiling only (debugger extension)
|
|
aw32Msg[uMsg].cTics += GetWOWTicDiff(dwTics);
|
|
aw32Msg[uMsg].cCalls++; // increment # times message passed
|
|
#endif // WOWPROFILE
|
|
|
|
}
|
|
|
|
if (!fSuccess)
|
|
goto Error;
|
|
|
|
Done:
|
|
|
|
return wm32mpex.lReturn;
|
|
|
|
Error:
|
|
LOGDEBUG(6,(" W32Win16DlgProcEx WARNING: cannot call back, using default message handling\n"));
|
|
wm32mpex.lReturn = 0;
|
|
goto Done;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LONG W32Win16WndProcEx(HWND hwnd, UINT uMsg, UINT uParam, LONG lParam,
|
|
VPWNDPROC vpWndProc16, // Next WndProc to call or NULL if default
|
|
PWW pww) // hwnd's PWW if already known or NULL
|
|
{
|
|
BOOL fSuccess;
|
|
LONG ulReturn;
|
|
register PTD ptd;
|
|
WM32MSGPARAMEX wm32mpex;
|
|
BOOL fMessageNeedsThunking;
|
|
//#ifdef DEBUG
|
|
// CHAR szClassName[80];
|
|
//#endif
|
|
|
|
#ifdef WOWPROFILE // for MSG profiling only (debugger extension)
|
|
LONGLONG dwTics;
|
|
#endif
|
|
|
|
ptd = CURRENTPTD();
|
|
|
|
WOW32ASSERT(vpWndProc16);
|
|
|
|
// take out the marker bits and fix the RPL bits
|
|
UnMarkWOWProc (vpWndProc16,vpWndProc16);
|
|
|
|
|
|
//
|
|
// If the app has GP Faulted we don't want to pass it any more input
|
|
// This should be removed when USER32 does clean up on task death so
|
|
// it doesn't call us - mattfe june 24 92 HACK32
|
|
//
|
|
// It's not a problem if the callback is going to a 16:16 proc in user.exe
|
|
// like DefWindowProc.
|
|
//
|
|
|
|
if (ptd->dwFlags & TDF_IGNOREINPUT &&
|
|
HIWORD(vpWndProc16) != HIWORD(gpfn16GetProcModule)) {
|
|
|
|
LOGDEBUG(6,(" W32Win16WndProcEx Ignoring Input Messsage %04X\n",uMsg));
|
|
WOW32ASSERTMSG(gfIgnoreInputAssertGiven,
|
|
"W32Win16WndProcEx: TDF_IGNOREINPUT hack was used, shouldn't be, "
|
|
"please email DaveHart with repro instructions. Hit 'g' to ignore this "
|
|
"and suppress this assertion from now on.\n");
|
|
gfIgnoreInputAssertGiven = TRUE;
|
|
goto SilentError;
|
|
}
|
|
|
|
//
|
|
// Don't send WM_DEVMODECHANGE if TDF_EATDEVMODEMSG is set
|
|
// access2.0 faults if it is in EnumMetaFile and receives WM_DEVMODECHANGE
|
|
// while in it whistler bug 189703
|
|
//
|
|
|
|
if (( ptd->dwFlags & TDF_EATDEVMODEMSG ) && ( uMsg == WM_DEVMODECHANGE )) {
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Figure out the class for this hwnd if we haven't seen it before
|
|
//
|
|
|
|
if (!pww) {
|
|
if (!(pww = (PWW) GetWindowLong(hwnd, GWL_WOWWORDS))) {
|
|
LOGDEBUG(LOG_ALWAYS,("WOW :: W32Win16WndProcEx ERROR: GetWindowLong(0x%x, GWL_WOWWORDS) fails\n", hwnd));
|
|
goto Error;
|
|
}
|
|
}
|
|
#ifdef FE_IME
|
|
if (( uMsg == WM_IME_REPORT ) && ( uParam == IR_STRINGEX )) {
|
|
HANDLE hInstance;
|
|
|
|
hInstance = (HANDLE)(ULONG)GetWindowLong(hwnd, GWL_HINSTANCE);
|
|
hInstance = (HANDLE)(ULONG)VALIDHMOD(hInstance);
|
|
if (W32GetExpWinVer(hInstance) < 0x030a)
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Don't dispatch Version 4.0 IMM Messages to 16bit apps.
|
|
//
|
|
// WM_IME_STARTCOMPOSITION 0x010D
|
|
// WM_IME_ENDCOMPOSITION 0x010E
|
|
// WM_IME_COMPOSITION 0x010F
|
|
// WM_IME_SETCONTEXT 0x0281
|
|
// WM_IME_NOTIFY 0x0282
|
|
// WM_IME_CONTROL 0x0283
|
|
// WM_IME_COMPOSITIONFULL 0x0284
|
|
// WM_IME_SELECT 0x0285
|
|
// WM_IME_CHAR 0x0286
|
|
// WM_IME_SYSTEM 0x0287
|
|
//
|
|
if ((( uMsg >= WM_IME_STARTCOMPOSITION ) && ( uMsg <= WM_IME_COMPOSITION )) ||
|
|
(( uMsg >= WM_IME_SETCONTEXT ) && (uMsg <= WM_IME_SYSTEM ))) {
|
|
|
|
// Korean Edit conrol need to dispatch new IMM messages.
|
|
if ( !(GetStdClassWndProc(WOWCLASS_EDIT) && GetSystemDefaultLangID()==0x412) ) {
|
|
HANDLE hInstance;
|
|
hInstance = (HANDLE)(ULONG)GetWindowLong(hwnd, GWL_HINSTANCE);
|
|
hInstance = (HANDLE)(ULONG)VALIDHMOD(hInstance);
|
|
if (W32GetExpWinVer(hInstance) < 0x0400)
|
|
goto Error;
|
|
}
|
|
}
|
|
#endif // FE_IME
|
|
|
|
// This message is WIN32 only. It is sent by WOW32 during the processing
|
|
// of an EM_SETSEL in WU32Send/PostMessage. If an MLE is subclassed the
|
|
// message will come through here attempting to travel back to the 16-bit
|
|
// app's wndproc. Instead of sending back a message that the 16-bit app
|
|
// doesn't understand it will be intercepted here and sent directly to the
|
|
// standard EditWindowProc. I'm not adding a Thunk because it shouldn't
|
|
// go to the app.
|
|
|
|
if (uMsg == EM_SCROLLCARET) {
|
|
WNDPROC EditWndProc;
|
|
|
|
// find the 32-bit EditWindowProc
|
|
// We should only be in this state if the app has subclassed so this
|
|
// call should be safe.
|
|
|
|
EditWndProc = (WNDPROC)GetStdClassWndProc(WOWCLASS_EDIT);
|
|
|
|
if (EditWndProc) {
|
|
CallWindowProc(EditWndProc, hwnd, EM_SCROLLCARET, 0, 0);
|
|
}
|
|
else {
|
|
LOGDEBUG(LOG_ALWAYS,(" W32Win16WndProcEx ERROR: cannot find 32-bit EditWindowProc\n"));
|
|
}
|
|
return 0; // notification message, no return code
|
|
}
|
|
|
|
// Thunk this 32 bit message to 16 bit message
|
|
|
|
LOGDEBUG(6,(" Thunking window %x message %s\n", hwnd, GetWMMsgName(uMsg)));
|
|
#ifdef DEBUG
|
|
if((uMsg & WOWPRIVATEMSG) && ((uMsg & ~WOWPRIVATEMSG) < 0x400)) {
|
|
LOGDEBUG(6,(" -- private WOW bit set for %s\n", GetWMMsgName(uMsg & ~WOWPRIVATEMSG)));
|
|
}
|
|
#endif
|
|
|
|
wm32mpex.Parm16.WndProc.hwnd = GETHWND16(hwnd);
|
|
wm32mpex.Parm16.WndProc.wMsg = (WORD)uMsg;
|
|
wm32mpex.Parm16.WndProc.wParam = (WORD)uParam;
|
|
wm32mpex.Parm16.WndProc.lParam = (LONG)lParam;
|
|
wm32mpex.Parm16.WndProc.hInst = LOWORD(pww->hModule);
|
|
|
|
// An app can send one of its private class windows a message say 401.
|
|
// This message will not be thunked in WMSG16.C because the
|
|
// messages >= 0x400 and we did not want to thunk it in WMSG16.C
|
|
//
|
|
|
|
fMessageNeedsThunking = (uMsg < 0x400) &&
|
|
(aw32Msg[uMsg].lpfnM32 != WM32NoThunking);
|
|
|
|
if (fMessageNeedsThunking) {
|
|
LOGDEBUG(6,("%04X (%s)\n", ptd->htask16, (aw32Msg[uMsg].lpszW32)));
|
|
|
|
#ifdef WOWPROFILE // for MSG profiling only (debugger extension)
|
|
dwTics = GetWOWTicDiff(0I64);
|
|
#endif
|
|
wm32mpex.fThunk = THUNKMSG;
|
|
wm32mpex.hwnd = hwnd;
|
|
wm32mpex.uMsg = uMsg;
|
|
wm32mpex.uParam = uParam;
|
|
wm32mpex.lParam = lParam;
|
|
wm32mpex.pww = pww;
|
|
wm32mpex.fFree = TRUE;
|
|
wm32mpex.lpfnM32 = aw32Msg[uMsg].lpfnM32;
|
|
ulReturn = (wm32mpex.lpfnM32)(&wm32mpex);
|
|
|
|
#ifdef WOWPROFILE // for MSG profiling only (debugger extension)
|
|
if( !fWMsgProfRT ) { // only if not profiling round trip
|
|
aw32Msg[uMsg].cTics += GetWOWTicDiff(dwTics);
|
|
}
|
|
#endif
|
|
|
|
if (!ulReturn) {
|
|
LOGDEBUG(LOG_ALWAYS,(" W32Win16WndProcEx ERROR: cannot thunk 32-bit message %s (%x)\n", GetWMMsgName(uMsg), uMsg));
|
|
goto Error;
|
|
}
|
|
}
|
|
|
|
if (vpWndProc16 == (VPVOID)NULL) {
|
|
WOW32ASSERT(vpWndProc16);
|
|
goto SilentError;
|
|
}
|
|
|
|
LOGDEBUG(6,("16-bit Window Proc = %08lX\n", vpWndProc16));
|
|
|
|
BlockWOWIdle(FALSE);
|
|
|
|
fSuccess = CallBack16(RET_WNDPROC, &wm32mpex.Parm16, vpWndProc16, (PVPVOID)&wm32mpex.lReturn);
|
|
|
|
BlockWOWIdle(TRUE);
|
|
|
|
// During CreateWindow some apps draw their own non-client area and don't
|
|
// pass WM_NCCALCSIZE to DefWindowProc which causes Win 95 and NT's user to
|
|
// not set some needed window flags. Mavis Beacon is an example. We'll pass
|
|
// the message for them.
|
|
|
|
if (uMsg == WM_NCCALCSIZE) {
|
|
if (CURRENTPTD()->dwWOWCompatFlagsEx & WOWCFEX_DEFWNDPROCNCCALCSIZE) {
|
|
DefWindowProc(hwnd, uMsg, uParam, lParam);
|
|
}
|
|
}
|
|
|
|
// UnThunk this 32 bit message
|
|
|
|
LOGDEBUG(6,(" UnThunking window %x message %s\n", hwnd, (LPSZ)GetWMMsgName(uMsg)));
|
|
#ifdef DEBUG
|
|
if((uMsg & WOWPRIVATEMSG) && ((uMsg - WOWPRIVATEMSG) < 0x400)) {
|
|
LOGDEBUG(6,(" -- private WOW bit set for %s\n", (LPSZ)GetWMMsgName(uMsg)));
|
|
}
|
|
#endif
|
|
|
|
if (fMessageNeedsThunking) {
|
|
|
|
#ifdef WOWPROFILE // for MSG profiling only (debugger extension)
|
|
if( !fWMsgProfRT ) { // only if not profiling round trip
|
|
dwTics = GetWOWTicDiff(0I64);
|
|
}
|
|
#endif
|
|
|
|
wm32mpex.fThunk = UNTHUNKMSG;
|
|
(wm32mpex.lpfnM32)(&wm32mpex);
|
|
|
|
#ifdef WOWPROFILE // for MSG profiling only (debugger extension)
|
|
aw32Msg[uMsg].cTics += GetWOWTicDiff(dwTics);
|
|
aw32Msg[uMsg].cCalls++; // increment # times message passed
|
|
#endif
|
|
|
|
}
|
|
|
|
if (!fSuccess) {
|
|
goto Error;
|
|
}
|
|
|
|
return (wm32mpex.lReturn);
|
|
|
|
Error:
|
|
LOGDEBUG(LOG_ALWAYS,(" W32Win16WndProcEx ERROR: cannot call back, using default message handling\n"));
|
|
SilentError:
|
|
return DefWindowProc(hwnd, uMsg, uParam, lParam);
|
|
}
|
|
|
|
|
|
|
|
// The following functions are used to "thunk" a 32 bit message to 16 bit
|
|
// message.
|
|
//
|
|
// To add a thunk function for a 32 bit message,
|
|
// - Modify the entry for the message in "aw32Msg" function array
|
|
// (in wmtbl32.c) to point to the new thunk function.
|
|
// - Define the new thunk function in this file.
|
|
//
|
|
|
|
|
|
// These messages do not require any thunking so just copy the 32 bit wParam
|
|
// and lParam to 16 bit wParam and lParam.
|
|
//
|
|
//
|
|
// WM_CANCELMODE
|
|
// WM_CHAR
|
|
// WM_CHILDACTIVATE
|
|
// WM_CLEAR
|
|
// WM_CLOSE
|
|
// WM_COMMNOTIFY
|
|
// WM_COMPACTING
|
|
// WM_COPY
|
|
// WM_CUT
|
|
// WM_DEADCHAR
|
|
// WM_DESTROY
|
|
// WM_DRAWCLIPBOARD
|
|
// WM_ENABLE
|
|
// WM_ENDSESSION
|
|
// WM_FONTCHANGE
|
|
// WM_GETFONT
|
|
// WM_GETTEXTLENGTH
|
|
// WM_HOTKEY
|
|
// WM_INPUTFOCUS
|
|
// WM_ISACTIVEICON (undocumented)
|
|
// WM_KEYDOWN
|
|
// WM_KEYUP
|
|
// WM_LBTRACKPOINT (undocumented)
|
|
// WM_LBUTTONDBLCLK
|
|
// WM_LBUTTONDOWN
|
|
// WM_LBUTTONUP
|
|
// WM_MBUTTONDBLCLK
|
|
// WM_MBUTTONDOWN
|
|
// WM_MBUTTONUP
|
|
// WM_MDICASCADE
|
|
// WM_MDIICONARRANGE
|
|
// WM_MDINEXT
|
|
// WM_MDITILE
|
|
// WM_MOUSEENTER
|
|
// WM_MOUSELEAVE
|
|
// WM_MOUSEMOVE
|
|
// WM_MOVE
|
|
// WM_NCCALCRGN
|
|
// WM_NCDESTROY
|
|
// WM_NCHITTEST
|
|
// WM_NCLBUTTONDBLCLK
|
|
// WM_NCLBUTTONDOWN
|
|
// WM_NCLBUTTONUP
|
|
// WM_NCMBUTTONDBLCLK
|
|
// WM_NCMBUTTONDOWN
|
|
// WM_NCMBUTTONUP
|
|
// WM_NCMOUSEMOVE
|
|
// WM_NCRBUTTONDBLCLK
|
|
// WM_NCRBUTTONDOWN
|
|
// WM_NCRBUTTONUP
|
|
// WM_PAINTICON
|
|
// WM_PASTE
|
|
// WM_POWER
|
|
// WM_QUERYENDSESSION
|
|
// WM_QUERYNEWPALETTE
|
|
// WM_QUERYOPEN
|
|
// WM_QUERYPARKICON (undocumented)
|
|
// WM_QUEUESYNC
|
|
// WM_QUIT
|
|
// WM_RBUTTONDBLCLK
|
|
// WM_RBUTTONDOWN
|
|
// WM_RBUTTONUP
|
|
// WM_RENDERALLFORMATS
|
|
// WM_RENDERFORMAT
|
|
// WM_SETREDRAW
|
|
// WM_SHOWWINDOW
|
|
// WM_SIZE
|
|
// WM_SPOOLERSTATUS (double-check lParam conversion on this one -JTP)
|
|
// WM_SYSCHAR
|
|
// WM_SYSCOLORCHANGE
|
|
// WM_SYSCOMMAND
|
|
// WM_SYSDEADCHAR
|
|
// WM_SYSKEYDOWN
|
|
// WM_SYSKEYUP
|
|
// WM_SYSTEMERROR
|
|
// WM_TIMECHANGE
|
|
// WM_UNDO
|
|
// MM_JOY1BUTTONDOWN - MultiMedia messages
|
|
// MM_JOY1BUTTONUP
|
|
// MM_JOY1MOVE
|
|
// MM_JOY1ZMOVE
|
|
// MM_JOY2BUTTONDOWN
|
|
// MM_JOY2BUTTONUP
|
|
// MM_JOY2MOVE
|
|
// MM_JOY2ZMOVE
|
|
// MM_MCINOTIFY - MultiMedia messages
|
|
|
|
|
|
BOOL FASTCALL WM32NoThunking(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
#if 0
|
|
//
|
|
// this routine is never called! It's used as a placeholder.
|
|
// if you want to make a change here, you have to make the change
|
|
// to the places where we compare the thunk routine to WM32NoThunking
|
|
// and only call the thunk routine if it's not this. also make sure
|
|
// that this 'default' thunking happens for NoThunking messages.
|
|
//
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
LOGDEBUG(6,(" No Thunking was required for the 32-bit message %s(%04x)\n", (LPSZ)GetWMMsgName(lpwm32mpex->uMsg), lpwm32mpex->uMsg));
|
|
|
|
lpwm32mpex->Parm16.WndProc.wMsg = (WORD)lpwm32mpex->uMsg;
|
|
lpwm32mpex->Parm16.WndProc.wParam = (WORD)lpwm32mpex->uParam;
|
|
lpwm32mpex->Parm16.WndProc.lParam = (LONG)lpwm32mpex->lParam;
|
|
}
|
|
|
|
//
|
|
// this routine is never called! It's used as a placeholder.
|
|
// if you want to make a change here, you have to make the change
|
|
// to the places where we compare the thunk routine to WM32NoThunking
|
|
// and only call the thunk routine if it's not this.
|
|
//
|
|
#endif
|
|
|
|
//
|
|
// Return FALSE, so if for some reason this routine gets used
|
|
// the failure to thunk will be apparent.
|
|
//
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
#ifdef DEBUG // see the macro WM32UNDOCUMENTED
|
|
|
|
// These are undocumented messages for Win 3.0 so take a look at the app
|
|
// who is using them.
|
|
|
|
BOOL FASTCALL WM32Undocumented(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
LOGDEBUG(3,(" Window %08lX is receiving Undocumented Message %s\n", lpwm32mpex->hwnd, (LPSZ)GetWMMsgName(lpwm32mpex->uMsg), lpwm32mpex->uMsg));
|
|
|
|
lpwm32mpex->Parm16.WndProc.wMsg = (WORD)lpwm32mpex->uMsg;
|
|
lpwm32mpex->Parm16.WndProc.wParam = (WORD)lpwm32mpex->uParam;
|
|
lpwm32mpex->Parm16.WndProc.lParam = (LONG)lpwm32mpex->lParam;
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_CREATE
|
|
// WM_NCCREATE
|
|
//
|
|
|
|
BOOL FASTCALL WM32Create(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
|
|
INT cb;
|
|
VPVOID vpClass = 0;
|
|
VPVOID vpName = 0;
|
|
VPVOID vpCreateParams = 0;
|
|
register PCREATESTRUCT16 pcws16;
|
|
LPCREATESTRUCT lParam = (LPCREATESTRUCT) lpwm32mpex->lParam;
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
|
|
if (HIWORD(lParam)) {
|
|
|
|
// BUGBUG -- The assumption here is that GlobalAlloc will never
|
|
// return a memory object that isn't word-aligned, so that we can
|
|
// assign word-aligned words directly; we have no idea whether the
|
|
// memory is dword-aligned or not however, so dwords must always
|
|
// be paranoidly stored with the STOREDWORD/STORELONG macros -JTP
|
|
|
|
|
|
if (lParam->lpszClass) {
|
|
if ( HIWORD(lParam->lpszClass) == 0 ) {
|
|
vpClass = (VPVOID)lParam->lpszClass;
|
|
}
|
|
else {
|
|
cb = strlen(lParam->lpszClass)+1;
|
|
if (!(vpClass = malloc16(cb)))
|
|
goto Error;
|
|
putstr16(vpClass, lParam->lpszClass, cb);
|
|
}
|
|
}
|
|
|
|
if (lParam->lpszName) {
|
|
cb = strlen(lParam->lpszName)+1;
|
|
if (!(vpName = malloc16(cb)))
|
|
goto Error;
|
|
putstr16(vpName, lParam->lpszName, cb);
|
|
}
|
|
|
|
if (lpwm32mpex->pww == NULL) {
|
|
lpwm32mpex->pww = (PWW)GetWindowLong(lpwm32mpex->hwnd, GWL_WOWWORDS);
|
|
if (lpwm32mpex->pww == NULL)
|
|
return FALSE; // Window is dead
|
|
}
|
|
|
|
if (lParam->lpCreateParams && (lpwm32mpex->pww->ExStyle & WS_EX_MDICHILD) ) {
|
|
// This works because wm32mdicreate thunk doesn't use any
|
|
// parameters except lParam
|
|
|
|
WM32MSGPARAMEX wm32mpexT;
|
|
wm32mpexT.fThunk = lpwm32mpex->fThunk;
|
|
wm32mpexT.hwnd = lpwm32mpex->hwnd;
|
|
wm32mpexT.uMsg = WM_MDICREATE;
|
|
wm32mpexT.uParam = lpwm32mpex->uParam;
|
|
wm32mpexT.lParam = (LONG)lParam->lpCreateParams;
|
|
wm32mpexT.pww = lpwm32mpex->pww;
|
|
wm32mpexT.fFree = lpwm32mpex->fFree;
|
|
wm32mpexT.Parm16.WndProc.lParam = 0;
|
|
WM32MDICreate(&wm32mpexT);
|
|
lpwm32mpex->dwParam = wm32mpexT.dwParam;
|
|
vpCreateParams = wm32mpexT.Parm16.WndProc.lParam;
|
|
}
|
|
else {
|
|
vpCreateParams = (VPVOID)lParam->lpCreateParams;
|
|
}
|
|
|
|
// be sure allocation size matches stackfree16() size below
|
|
if (!(lpwm32mpex->Parm16.WndProc.lParam = stackalloc16(sizeof(CREATESTRUCT16))))
|
|
return FALSE;
|
|
|
|
GETVDMPTR(lpwm32mpex->Parm16.WndProc.lParam, sizeof(CREATESTRUCT16), pcws16);
|
|
|
|
STOREDWORD(pcws16->vpszClass, vpClass);
|
|
STOREDWORD(pcws16->vpszWindow, vpName);
|
|
STOREDWORD(pcws16->vpCreateParams, vpCreateParams);
|
|
|
|
lpwm32mpex->dwTmp[0] = vpClass; // store for later freeing
|
|
lpwm32mpex->dwTmp[1] = vpName;
|
|
|
|
|
|
// BUGBUG 08-Apr-91 JeffPar -- What if hModule is for a 32-bit task?
|
|
pcws16->hInstance = GETHINST16(lParam->hInstance);
|
|
pcws16->hMenu = GETHMENU16(lParam->hMenu);
|
|
pcws16->hwndParent = GETHWND16(lParam->hwndParent);
|
|
pcws16->cy = (SHORT)lParam->cy;
|
|
pcws16->cx = (SHORT)lParam->cx;
|
|
pcws16->y = (SHORT)lParam->y;
|
|
pcws16->x = (SHORT)lParam->x;
|
|
STOREDWORD(pcws16->dwStyle, lParam->style);
|
|
STOREDWORD(pcws16->dwExStyle, lParam->dwExStyle);
|
|
|
|
FLUSHVDMPTR(lpwm32mpex->Parm16.WndProc.lParam, sizeof(CREATESTRUCT16), pcws16);
|
|
FREEVDMPTR(pcws16);
|
|
|
|
return TRUE;
|
|
|
|
Error:
|
|
LOGDEBUG(LOG_ALWAYS,(" !!!! WM32Create, WM_CREATE thunking failed !!!! Window %08lX ", lpwm32mpex->hwnd));
|
|
if (HIW(vpClass)) free16(vpClass);
|
|
if (vpName) free16(vpName);
|
|
return (FALSE);
|
|
|
|
// do some clean up
|
|
// UnThunkWMCreate32(lParam, lpwm32mpex->Parm16.WndProc.lParam);
|
|
|
|
} else {
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
else {
|
|
|
|
if (lpwm32mpex->Parm16.WndProc.lParam) {
|
|
|
|
if (lpwm32mpex->pww == NULL) {
|
|
lpwm32mpex->pww = (PWW)GetWindowLong(lpwm32mpex->hwnd, GWL_WOWWORDS);
|
|
if (lpwm32mpex->pww == NULL)
|
|
return FALSE; // Window is dead
|
|
}
|
|
|
|
if (lParam->lpCreateParams && (lpwm32mpex->pww->ExStyle & WS_EX_MDICHILD) ) {
|
|
WM32MSGPARAMEX wm32mpexT;
|
|
GETVDMPTR(lpwm32mpex->Parm16.WndProc.lParam, sizeof(CREATESTRUCT16), pcws16);
|
|
wm32mpexT.fThunk = lpwm32mpex->fThunk;
|
|
wm32mpexT.hwnd = lpwm32mpex->hwnd;
|
|
wm32mpexT.uMsg = WM_MDICREATE;
|
|
wm32mpexT.uParam = lpwm32mpex->uParam;
|
|
wm32mpexT.lParam = (LONG)lParam->lpCreateParams;
|
|
wm32mpexT.pww = lpwm32mpex->pww;
|
|
wm32mpexT.fFree = lpwm32mpex->fFree;
|
|
wm32mpexT.Parm16.WndProc.lParam = (VPVOID)FETCHDWORD(pcws16->vpCreateParams);
|
|
wm32mpexT.lReturn = 0;
|
|
wm32mpexT.dwParam = lpwm32mpex->dwParam;
|
|
WM32MDICreate(&wm32mpexT);
|
|
FREEVDMPTR(pcws16);
|
|
}
|
|
|
|
vpClass = lpwm32mpex->dwTmp[0];
|
|
vpName = lpwm32mpex->dwTmp[1];
|
|
|
|
// if HIWORD(class) is zero, class is an atom, else a pointer.
|
|
|
|
if (HIW16(vpClass)) {
|
|
free16(vpClass);
|
|
}
|
|
|
|
if (vpName) {
|
|
free16(vpName);
|
|
}
|
|
|
|
stackfree16((VPVOID) lpwm32mpex->Parm16.WndProc.lParam,
|
|
sizeof(CREATESTRUCT16));
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_NCACTIVATE
|
|
// WM_ACTIVATE
|
|
//
|
|
|
|
BOOL FASTCALL WM32Activate(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
lpwm32mpex->Parm16.WndProc.wParam = LOWORD(lpwm32mpex->uParam);
|
|
LOW(lpwm32mpex->Parm16.WndProc.lParam) = GETHWND16(lpwm32mpex->lParam);
|
|
HIW(lpwm32mpex->Parm16.WndProc.lParam) = HIWORD(lpwm32mpex->uParam);
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_VKEYTOITEM
|
|
// WM_CHARTOITEM
|
|
// WM_BEGINDRAG
|
|
//
|
|
|
|
BOOL FASTCALL WM32VKeyToItem(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
LOW(lpwm32mpex->Parm16.WndProc.lParam) = GETHWND16(lpwm32mpex->lParam);
|
|
HIW(lpwm32mpex->Parm16.WndProc.lParam) = HIWORD(lpwm32mpex->uParam);
|
|
}
|
|
else {
|
|
lpwm32mpex->lReturn = (INT)(SHORT)(lpwm32mpex->lReturn); // sign extend.
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_SETFOCUS
|
|
// WM_KILLFOCUS
|
|
// WM_SETCURSOR
|
|
// WM_MOUSEACTIVATE
|
|
// WM_MDIDESTROY
|
|
// WM_MDIRESTORE
|
|
// WM_MDIMAXIMIZE
|
|
// WM_VSCROLLCLIPBOARD
|
|
// WM_HSCROLLCLIPBOARD
|
|
// WM_PALETTECHANGED
|
|
// WM_PALETTEISCHANGING
|
|
// WM_INITDIALOG
|
|
//
|
|
|
|
BOOL FASTCALL WM32SetFocus(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
lpwm32mpex->Parm16.WndProc.wParam = GETHWND16(lpwm32mpex->uParam);
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_SETTEXT
|
|
// WM_WININICHANGE
|
|
// WM_DEVMODECHANGE
|
|
//
|
|
|
|
BOOL FASTCALL WM32SetText(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
INT cb;
|
|
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
if (lpwm32mpex->lParam) {
|
|
|
|
LONG lParam = (LONG)GetParam16(lpwm32mpex->lParam);
|
|
if (lParam) {
|
|
lpwm32mpex->Parm16.WndProc.lParam = lParam;
|
|
return (TRUE);
|
|
}
|
|
|
|
cb = strlen((LPSZ)lpwm32mpex->lParam)+1;
|
|
lpwm32mpex->dwTmp[0] = (DWORD)cb;
|
|
|
|
// winworks2.0a requires DS based string pointers for this message
|
|
if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_DSBASEDSTRINGPOINTERS) {
|
|
|
|
// be sure allocation size matches stackfree16() size below
|
|
if (!(lpwm32mpex->Parm16.WndProc.lParam = stackalloc16(cb)))
|
|
return FALSE;
|
|
|
|
} else {
|
|
if (!(lpwm32mpex->Parm16.WndProc.lParam = malloc16(cb)))
|
|
return FALSE;
|
|
}
|
|
putstr16((VPSZ)lpwm32mpex->Parm16.WndProc.lParam, (LPSZ)lpwm32mpex->lParam, cb);
|
|
}
|
|
}
|
|
else {
|
|
// BUGBUG 09-Apr-91 -- Should I copy back?
|
|
if (DeleteParamMap(lpwm32mpex->Parm16.WndProc.lParam, PARAM_16, NULL)) {
|
|
return TRUE;
|
|
}
|
|
|
|
if (lpwm32mpex->Parm16.WndProc.lParam) {
|
|
if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_DSBASEDSTRINGPOINTERS) {
|
|
stackfree16((VPVOID) lpwm32mpex->Parm16.WndProc.lParam,
|
|
((UINT)lpwm32mpex->dwTmp[0]));
|
|
} else {
|
|
free16((VPVOID) lpwm32mpex->Parm16.WndProc.lParam);
|
|
}
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the message,
|
|
//
|
|
// WM_GETTEXT
|
|
//
|
|
|
|
BOOL FASTCALL WM32GetText(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
INT cb;
|
|
LPSTR psz;
|
|
INT cbWrote;
|
|
|
|
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
|
|
if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_DSBASEDSTRINGPOINTERS) {
|
|
//
|
|
// msworks 2.0a has a wndproc called EdWnProc() which when it gets
|
|
// a WM_GETTEXT, assumes lParam is a based pointer whose segment
|
|
// value is equal to winwork's ds. That is true under win3.1, but
|
|
// if wow calls malloc16, it'll have a different segment value.
|
|
// so instead alloc the space on the caller's stack. Since most
|
|
// apps have SS == DS, this will fix apps that do this, including
|
|
// msworks 2.0a.
|
|
//
|
|
|
|
// be sure allocation size matches stackfree16() size below
|
|
lpwm32mpex->dwTmp[0] = (DWORD)lpwm32mpex->Parm16.WndProc.wParam;
|
|
lpwm32mpex->Parm16.WndProc.lParam = stackalloc16(lpwm32mpex->dwTmp[0]);
|
|
|
|
} else {
|
|
lpwm32mpex->Parm16.WndProc.lParam = malloc16(lpwm32mpex->Parm16.WndProc.wParam);
|
|
}
|
|
|
|
//
|
|
// non-zero fill to detect people who write more than they
|
|
// say that they do!
|
|
//
|
|
GETVDMPTR(lpwm32mpex->Parm16.WndProc.lParam, lpwm32mpex->Parm16.WndProc.wParam, psz);
|
|
RtlFillMemory(psz, lpwm32mpex->Parm16.WndProc.wParam, 0xff);
|
|
FLUSHVDMPTR(lpwm32mpex->Parm16.WndProc.lParam, lpwm32mpex->Parm16.WndProc.wParam, psz);
|
|
FREEVDMPTR(psz);
|
|
return (BOOL)lpwm32mpex->Parm16.WndProc.lParam;
|
|
}
|
|
else {
|
|
// some apps return garbage in the high word. safely assume
|
|
// that cbWindowText < 64K
|
|
HIW(lpwm32mpex->lReturn) = 0;
|
|
|
|
// it is necessary to check the length of the buffer, specified in
|
|
// lpwm32mpex->uParam. if number of bytes (lpwm32mpex->lReturn) that are to be copied is
|
|
// EQUAL to the length of the buffer, then copy ONLY the bytes EQUAL
|
|
// to the length of the buffer.
|
|
//
|
|
|
|
// Paradox is one of the apps where this condition is hit.
|
|
// bug # 4272.
|
|
|
|
|
|
//
|
|
|
|
if (lpwm32mpex->Parm16.WndProc.lParam) {
|
|
|
|
cb = lpwm32mpex->lReturn + 1;
|
|
|
|
if (lpwm32mpex->uParam == 0) {
|
|
// cb = 0 if lReturn == 0 && uParam == 0
|
|
|
|
if (cb == 1)
|
|
cb--;
|
|
}
|
|
else if (cb == 2 || cb == 1) {
|
|
// Here only if uParam != 0
|
|
//
|
|
// Determine how much of the buffer they touched!
|
|
//
|
|
// MyAdvancedLabelMaker returns 1 when they really return
|
|
// more than 1. Since the return 1, cb will be 2. Then
|
|
// We check to see how much of the buffer they really modified.
|
|
// Then we lie and say that they really filled in that much
|
|
// of the buffer.
|
|
//
|
|
// Sql administator also does this, except it returns 0
|
|
// bug 7731
|
|
|
|
GETVDMPTR(lpwm32mpex->Parm16.WndProc.lParam, lpwm32mpex->Parm16.WndProc.wParam, psz);
|
|
|
|
cbWrote = lpwm32mpex->uParam;
|
|
while (cbWrote && (psz[cbWrote-1] == '\xff')) {
|
|
cbWrote--;
|
|
}
|
|
// copy out as many bytes as they wrote
|
|
// distinguish between 'zerobytes written vs. one byte written'
|
|
|
|
lpwm32mpex->lReturn = (cbWrote) ? (cbWrote - 1) : 0;
|
|
cb = cbWrote;
|
|
|
|
FREEVDMPTR(psz);
|
|
}
|
|
|
|
|
|
// cb = min(cb, wparam) only if wparam != 0
|
|
// MSPROFIT: does
|
|
// ret = sendmessage(hwnd, wm_gettest, wparam = 0, lparam);
|
|
// where ret != 0. so we have to copy the necessary bytes into
|
|
// lparam eventhough wparam is zero. It does this for reading
|
|
// those ominprseent "$0.00" strings in the app (ledgers etc).
|
|
//
|
|
// - nanduri
|
|
|
|
if (lpwm32mpex->uParam && (UINT)cb > lpwm32mpex->uParam) {
|
|
cb = lpwm32mpex->uParam;
|
|
}
|
|
|
|
getstr16((VPSZ)lpwm32mpex->Parm16.WndProc.lParam, (LPSZ)lpwm32mpex->lParam, cb);
|
|
|
|
if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_DSBASEDSTRINGPOINTERS) {
|
|
stackfree16((VPVOID) lpwm32mpex->Parm16.WndProc.lParam,
|
|
((UINT)lpwm32mpex->dwTmp[0]));
|
|
} else {
|
|
free16((VPVOID) lpwm32mpex->Parm16.WndProc.lParam);
|
|
}
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_ERASEBKGND
|
|
// WM_ICONERASEBKGND
|
|
//
|
|
|
|
BOOL FASTCALL WM32EraseBkGnd(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
HAND16 hdc16;
|
|
BOOL bNotThere;
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
|
|
// Query to see if we've mapped hDC32 in uParam. If not, it means that
|
|
// hDC32 was created outside this VDM process and we will have to
|
|
// delete it from our table when un-thunking this message.
|
|
lpwm32mpex->dwTmp[0] = 0;
|
|
bNotThere = FALSE;
|
|
if(!IsGDIh32Mapped((HANDLE)lpwm32mpex->uParam)) {
|
|
bNotThere = TRUE;
|
|
}
|
|
|
|
// GETHDC16() may cause a new handle to be added to our handle table.
|
|
hdc16 = GETHDC16(lpwm32mpex->uParam);
|
|
|
|
// save the 32-bit & new 16-bit GDI handles for unthunking
|
|
if(bNotThere) {
|
|
lpwm32mpex->dwTmp[0] = (DWORD)hdc16;
|
|
lpwm32mpex->dwTmp[1] = lpwm32mpex->uParam;
|
|
}
|
|
|
|
lpwm32mpex->Parm16.WndProc.wParam = hdc16;
|
|
}
|
|
else {
|
|
// If this is !0, it means that the handle hadn't been mapped in our
|
|
// table at the time of the IsGDIh32Mapped() call above.
|
|
if(lpwm32mpex->dwTmp[0]) {
|
|
|
|
// Remove the hdc that was added to our table by the GETHDC16 macro
|
|
// in the inbound thunk of this message above.
|
|
hdc16 = (HAND16)LOWORD(lpwm32mpex->dwTmp[0]);
|
|
DeleteWOWGdiHandle((HANDLE)lpwm32mpex->dwTmp[1], hdc16);
|
|
}
|
|
}
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
// This function thunks the message
|
|
//
|
|
// WM_CHANGEUISTATE
|
|
// WM_UPDATEUISTATE
|
|
// WM_QUERYUISTATE
|
|
//
|
|
|
|
BOOL FASTCALL WM32xxxUIState(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
// just copy the wParam into the lParam
|
|
if (lpwm32mpex->fThunk) {
|
|
lpwm32mpex->Parm16.WndProc.lParam = (LONG)lpwm32mpex->uParam;
|
|
lpwm32mpex->Parm16.WndProc.wParam = 0;
|
|
|
|
// this is here because there is talk that they might extend this
|
|
// message to use lParam -- heck, they didn't even tell us that they
|
|
// implemented this message in the first place!! (shame on shell!!)
|
|
WOW32WARNMSG((lpwm32mpex->lParam == 0),
|
|
("WOW::WM32xxxUIState:lParam != 0. Better investigate!\n"));
|
|
}
|
|
|
|
// now just reverse the process
|
|
else {
|
|
lpwm32mpex->uParam = (UINT)lpwm32mpex->Parm16.WndProc.lParam;
|
|
lpwm32mpex->lParam = 0;
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_ACTIVATEAPP
|
|
//
|
|
|
|
BOOL FASTCALL WM32ActivateApp(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
extern void UpdateInt16State(void);
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
|
|
LOW(lpwm32mpex->Parm16.WndProc.lParam) =
|
|
lpwm32mpex->lParam
|
|
? ThreadID32toHtask16((DWORD)lpwm32mpex->lParam)
|
|
: 0;
|
|
|
|
// We need to update wow int 16 bios when I wow app gets the focus.
|
|
UpdateInt16State();
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_GETMINMAXINFO
|
|
//
|
|
|
|
BOOL FASTCALL WM32GetMinMaxInfo(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
LPPOINT lParam = (LPPOINT) lpwm32mpex->lParam;
|
|
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
if (lParam) {
|
|
|
|
// be sure allocation size matches stackfree16() size below
|
|
lpwm32mpex->Parm16.WndProc.lParam = stackalloc16(sizeof(POINT16)*5);
|
|
|
|
UnThunkWMGetMinMaxInfo16(lpwm32mpex->Parm16.WndProc.lParam, lParam);
|
|
}
|
|
}
|
|
else {
|
|
ThunkWMGetMinMaxInfo16(lpwm32mpex->Parm16.WndProc.lParam, &lParam);
|
|
if(lpwm32mpex->Parm16.WndProc.lParam) {
|
|
stackfree16((VPVOID) lpwm32mpex->Parm16.WndProc.lParam,
|
|
sizeof(POINT16)*5);
|
|
}
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_NCPAINT
|
|
// WM_PAINT
|
|
//
|
|
|
|
BOOL FASTCALL WM32NCPaint(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
HAND16 hrgn16;
|
|
BOOL bNotThere;
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
|
|
lpwm32mpex->dwTmp[0] = 0;
|
|
|
|
if(lpwm32mpex->uParam == 1) {
|
|
lpwm32mpex->Parm16.WndProc.wParam = 1;
|
|
}
|
|
|
|
else if(lpwm32mpex->uMsg == WM_NCPAINT) {
|
|
|
|
// Query to see if we've already mapped the hrgn32 in uParam. If
|
|
// not, it means that hrgn32 was created outside this vdm and we'll
|
|
// have to delete it from our table when un-thunking this message.
|
|
bNotThere = FALSE;
|
|
if(!IsGDIh32Mapped((HANDLE)lpwm32mpex->uParam)) {
|
|
bNotThere = TRUE;
|
|
}
|
|
|
|
hrgn16 = GETHRGN16(lpwm32mpex->uParam);
|
|
lpwm32mpex->Parm16.WndProc.wParam = hrgn16;
|
|
|
|
// save the 32-bit & new 16-bit GDI handles for unthunking
|
|
if(bNotThere) {
|
|
lpwm32mpex->dwTmp[0] = (DWORD)hrgn16;
|
|
lpwm32mpex->dwTmp[1] = lpwm32mpex->uParam;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
|
|
// If this is !0, it means that the handle hadn't been mapped in our
|
|
// table at the time of the IsGDIh32Mapped() call above.
|
|
if(lpwm32mpex->dwTmp[0]) {
|
|
|
|
// Remove the hrgn that was added to our table by the GETRGN16 macro
|
|
// in the inbound thunk of this message above.
|
|
hrgn16 = (HAND16)LOWORD(lpwm32mpex->dwTmp[0]);
|
|
DeleteWOWGdiHandle((HANDLE)lpwm32mpex->dwTmp[1], hrgn16);
|
|
}
|
|
}
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_NCDESTROY
|
|
//
|
|
|
|
BOOL FASTCALL WM32NCDestroy(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
// destroy any timers associated with this window
|
|
if (!lpwm32mpex->fThunk) {
|
|
FreeWindowTimers16(lpwm32mpex->hwnd);
|
|
}
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_GETDLGCODE
|
|
//
|
|
BOOL FASTCALL WM32GetDlgCode(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
if (lpwm32mpex->lParam) {
|
|
|
|
// BUGBUG -- The assumption here is that GlobalAlloc will never
|
|
// return a memory object that isn't word-aligned, so that we can
|
|
// assign word-aligned words directly; we have no idea whether the
|
|
// memory is dword-aligned or not however, so dwords must always
|
|
// be paranoidly stored with the STOREDWORD/STORELONG macros -JTP
|
|
|
|
if (!(lpwm32mpex->Parm16.WndProc.lParam = malloc16(sizeof(MSG16))))
|
|
return FALSE;
|
|
|
|
putmsg16(lpwm32mpex->Parm16.WndProc.lParam, (LPMSG)lpwm32mpex->lParam);
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
else {
|
|
// Message structure doesn't need to be copied back does it? -Bob
|
|
|
|
if (lpwm32mpex->Parm16.WndProc.lParam) {
|
|
free16((VPVOID) lpwm32mpex->Parm16.WndProc.lParam);
|
|
}
|
|
|
|
}
|
|
return (TRUE);
|
|
}
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_NEXTDLGCTL
|
|
//
|
|
|
|
BOOL FASTCALL WM32NextDlgCtl(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
if (lpwm32mpex->lParam) {
|
|
lpwm32mpex->Parm16.WndProc.wParam = GETHWND16(lpwm32mpex->uParam);
|
|
}
|
|
}
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_DRAWITEM
|
|
//
|
|
|
|
BOOL FASTCALL WM32DrawItem(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
HAND16 hdc16;
|
|
BOOL bNotThere;
|
|
LPDRAWITEMSTRUCT lParam = (LPDRAWITEMSTRUCT) lpwm32mpex->lParam;
|
|
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
|
|
lpwm32mpex->dwTmp[0] = 0;
|
|
|
|
if (lParam) {
|
|
|
|
// be sure allocation size matches stackfree16() size below
|
|
lpwm32mpex->Parm16.WndProc.lParam = stackalloc16(sizeof(DRAWITEMSTRUCT16));
|
|
|
|
// Query to see if we've already mapped the DRAWITEM->hDC. If not,
|
|
// it means that the hDC was created outside the app and we will
|
|
// have to delete it from our table when un-thunking this message.
|
|
bNotThere = FALSE;
|
|
if(!IsGDIh32Mapped(((LPDRAWITEMSTRUCT)lParam)->hDC)) {
|
|
bNotThere = TRUE;
|
|
}
|
|
|
|
// The call to putdrawitem16() may add a GDI handle mapping entry
|
|
// for the hDC in our mapping table (via the GETHDC16 macro)
|
|
hdc16 = putdrawitem16(lpwm32mpex->Parm16.WndProc.lParam, lParam);
|
|
|
|
// save the 32-bit & new 16-bit GDI handles for unthunking
|
|
if(bNotThere) {
|
|
lpwm32mpex->dwTmp[0] = (DWORD)hdc16;
|
|
lpwm32mpex->dwTmp[1] = (DWORD)((LPDRAWITEMSTRUCT)lParam)->hDC;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
// BUGBUG 08-Apr-91 JeffPar -- Reflect changes back to 32-bit structure?
|
|
if (lpwm32mpex->Parm16.WndProc.lParam) {
|
|
|
|
stackfree16((VPVOID) lpwm32mpex->Parm16.WndProc.lParam,
|
|
sizeof(DRAWITEMSTRUCT16));
|
|
|
|
// If this is !0, it means that the handle hadn't been mapped in our
|
|
// table at the time of the IsGDIh32Mapped() call above.
|
|
if(lpwm32mpex->dwTmp[0]) {
|
|
hdc16 = (HAND16)LOWORD(lpwm32mpex->dwTmp[0]);
|
|
DeleteWOWGdiHandle((HANDLE)lpwm32mpex->dwTmp[1], hdc16);
|
|
}
|
|
}
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_MEASUREITEM
|
|
//
|
|
|
|
BOOL FASTCALL WM32MeasureItem(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
PMEASUREITEMSTRUCT16 pmis16;
|
|
LPMEASUREITEMSTRUCT lParam = (LPMEASUREITEMSTRUCT) lpwm32mpex->lParam;
|
|
BOOL fHasStrings;
|
|
DWORD cSize;
|
|
|
|
|
|
//
|
|
// Compatibility hack
|
|
//
|
|
// CrossTalk 2.0 has a bug where it fails to distinguish between
|
|
// WM_MEASUREITEM and WM_INITDIALOG when doing file.open
|
|
// on WM_MEASUREITEM it calls CallWindowProc() to send what it
|
|
// thinks is lpOpenFileName->lpCust but is really random stack.
|
|
// currently the high word of this random pointer is an hInstance
|
|
// and gets through the validation layer, whereas on Win31 it doesn't.
|
|
// if this WM_MEASUREITEM gets to the app's proc then the app will
|
|
// initialize incorrectly and take a GP. i have increased the stack
|
|
// allocation by XTALKHACK to ensure that the random data does is not
|
|
// a valid pointer.
|
|
//
|
|
|
|
#define XTALKHACK (sizeof(OPENFILENAME16)-sizeof(MEASUREITEMSTRUCT16))
|
|
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
if (lParam) {
|
|
|
|
fHasStrings = FALSE;
|
|
if ( lParam->CtlType == ODT_COMBOBOX || lParam->CtlType == ODT_LISTBOX ) {
|
|
if (lParam->itemWidth == MIFLAG_FLAT) {
|
|
fHasStrings = TRUE;
|
|
}
|
|
}
|
|
|
|
cSize = sizeof(MEASUREITEMSTRUCT16);
|
|
if ( fHasStrings ) {
|
|
cSize += strlen((LPSTR)lParam->itemData) + 1;
|
|
}
|
|
|
|
if ( cSize < XTALKHACK+sizeof(MEASUREITEMSTRUCT16) ) {
|
|
cSize = XTALKHACK+sizeof(MEASUREITEMSTRUCT16);
|
|
}
|
|
|
|
// be sure allocation size matches stackfree16() size below
|
|
lpwm32mpex->dwTmp[0] = cSize;
|
|
if ( !(lpwm32mpex->Parm16.WndProc.lParam = stackalloc16(cSize)) )
|
|
return FALSE;
|
|
|
|
GETVDMPTR(lpwm32mpex->Parm16.WndProc.lParam, cSize, pmis16);
|
|
|
|
pmis16->CtlType = (WORD)lParam->CtlType;
|
|
pmis16->CtlID = (WORD)lParam->CtlID;
|
|
pmis16->itemID = (WORD)lParam->itemID;
|
|
pmis16->itemWidth = (WORD)lParam->itemWidth;
|
|
pmis16->itemHeight = (WORD)lParam->itemHeight;
|
|
|
|
#ifdef XTALKHACK
|
|
((POPENFILENAME16)pmis16)->lCustData = 7; // invalid far pointer
|
|
#endif
|
|
if ( fHasStrings ) {
|
|
pmis16->itemData = lpwm32mpex->Parm16.WndProc.lParam+sizeof(MEASUREITEMSTRUCT16);
|
|
strcpy( (LPSTR)(pmis16+1), (LPSTR)lParam->itemData );
|
|
} else {
|
|
STOREDWORD(pmis16->itemData, lParam->itemData);
|
|
}
|
|
|
|
WOW32ASSERT(HIWORD(cSize) == 0);
|
|
FLUSHVDMPTR(lpwm32mpex->Parm16.WndProc.lParam, (USHORT) cSize, pmis16);
|
|
FREEVDMPTR(pmis16);
|
|
}
|
|
}
|
|
else {
|
|
if (lpwm32mpex->Parm16.WndProc.lParam) {
|
|
GETVDMPTR(lpwm32mpex->Parm16.WndProc.lParam, sizeof(MEASUREITEMSTRUCT16), pmis16);
|
|
|
|
lParam->CtlType = WORD32(pmis16->CtlType);
|
|
lParam->CtlID = WORD32(pmis16->CtlID);
|
|
lParam->itemID = WORD32(pmis16->itemID);
|
|
|
|
// itemWidth must sign extend (PPT3 bug & Win3.1 treats it as signed!)
|
|
lParam->itemWidth = INT32(pmis16->itemWidth);
|
|
|
|
lParam->itemHeight = WORD32(pmis16->itemHeight);
|
|
lParam->itemData = pmis16->itemData;
|
|
|
|
FREEVDMPTR(pmis16);
|
|
|
|
stackfree16((VPVOID) lpwm32mpex->Parm16.WndProc.lParam,
|
|
((UINT)lpwm32mpex->dwTmp[0]));
|
|
}
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_DELETEITEM
|
|
//
|
|
|
|
|
|
BOOL FASTCALL WM32DeleteItem(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
register PDELETEITEMSTRUCT16 pdes16;
|
|
LPDELETEITEMSTRUCT lParam = (LPDELETEITEMSTRUCT) lpwm32mpex->lParam;
|
|
|
|
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
if (lParam) {
|
|
|
|
// BUGBUG -- The assumption here is that GlobalAlloc will never
|
|
// return a memory object that isn't word-aligned, so that we can
|
|
// assign word-aligned words directly; we have no idea whether the
|
|
// memory is dword-aligned or not however, so dwords must always
|
|
// be paranoidly stored with the STOREDWORD/STORELONG macros -JTP
|
|
|
|
// be sure allocation size matches stackfree16() size below
|
|
lpwm32mpex->Parm16.WndProc.lParam = stackalloc16(sizeof(DELETEITEMSTRUCT16));
|
|
GETVDMPTR(lpwm32mpex->Parm16.WndProc.lParam, sizeof(DELETEITEMSTRUCT16), pdes16);
|
|
|
|
pdes16->CtlType = (WORD)lParam->CtlType;
|
|
pdes16->CtlID = (WORD)lParam->CtlID;
|
|
pdes16->itemID = (WORD)lParam->itemID;
|
|
pdes16->hwndItem = GETHWND16(lParam->hwndItem);
|
|
STOREDWORD(pdes16->itemData, lParam->itemData);
|
|
|
|
FLUSHVDMPTR(lpwm32mpex->Parm16.WndProc.lParam, sizeof(DELETEITEMSTRUCT16), pdes16);
|
|
FREEVDMPTR(pdes16);
|
|
}
|
|
}
|
|
else {
|
|
if (lpwm32mpex->Parm16.WndProc.lParam)
|
|
stackfree16((VPVOID) lpwm32mpex->Parm16.WndProc.lParam,
|
|
sizeof(DELETEITEMSTRUCT16));
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_SETFONT
|
|
//
|
|
|
|
BOOL FASTCALL WM32SetFont(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
HAND16 hfont16;
|
|
BOOL bNotThere;
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
|
|
lpwm32mpex->dwTmp[0] = 0;
|
|
bNotThere = FALSE;
|
|
|
|
// Query to see if we've mapped the hfont. If not, it means that the
|
|
// hFont was created outside this VDM process and we will have to delete
|
|
// it from our table when un-thunking this message.
|
|
if(!IsGDIh32Mapped((HANDLE)lpwm32mpex->uParam)) {
|
|
bNotThere = TRUE;
|
|
}
|
|
hfont16 = GETHFONT16(lpwm32mpex->uParam);
|
|
lpwm32mpex->Parm16.WndProc.wParam = hfont16;
|
|
|
|
// save the 32-bit & new 16-bit GDI handles for unthunking
|
|
if(bNotThere) {
|
|
lpwm32mpex->dwTmp[0] = (DWORD)hfont16;
|
|
lpwm32mpex->dwTmp[1] = (DWORD)lpwm32mpex->uParam;
|
|
}
|
|
}
|
|
else {
|
|
// If this is !0, it means that the handle hadn't been mapped in our
|
|
// table at the time of the IsGDIh32Mapped() call above.
|
|
if(lpwm32mpex->dwTmp[0]) {
|
|
|
|
hfont16 = (HAND16)LOWORD(lpwm32mpex->dwTmp[0]);
|
|
DeleteWOWGdiHandle((HANDLE)lpwm32mpex->dwTmp[1], hfont16);
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_QUERYDRAGICON
|
|
|
|
BOOL FASTCALL WM32QueryDragIcon(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
if (!lpwm32mpex->fThunk) {
|
|
lpwm32mpex->lReturn = (LONG)HICON32(lpwm32mpex->lReturn);
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_COMPAREITEM
|
|
//
|
|
|
|
BOOL FASTCALL WM32CompareItem(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
LPCOMPAREITEMSTRUCT lParam = (LPCOMPAREITEMSTRUCT) lpwm32mpex->lParam;
|
|
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
if (lParam) {
|
|
|
|
// BUGBUG -- The assumption here is that GlobalAlloc will never
|
|
// return a memory object that isn't word-aligned, so that we can
|
|
// assign word-aligned words directly; we have no idea whether the
|
|
// memory is dword-aligned or not however, so dwords must always
|
|
// be paranoidly stored with the STOREDWORD/STORELONG macros -JTP
|
|
|
|
// be sure allocation size matches stackfree16() size below
|
|
lpwm32mpex->Parm16.WndProc.lParam = stackalloc16(sizeof(COMPAREITEMSTRUCT16));
|
|
putcompareitem16(lpwm32mpex->Parm16.WndProc.lParam, lParam);
|
|
}
|
|
}
|
|
else {
|
|
// BUGBUG 08-Apr-91 JeffPar -- Reflect changes back to 32-bit structure?
|
|
if (lpwm32mpex->Parm16.WndProc.lParam)
|
|
stackfree16((VPVOID) lpwm32mpex->Parm16.WndProc.lParam,
|
|
sizeof(COMPAREITEMSTRUCT16));
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_SIZING
|
|
//
|
|
|
|
BOOL FASTCALL WM32Sizing(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
VPRECT16 vpRect16;
|
|
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
|
|
if (lpwm32mpex->lParam) {
|
|
|
|
// be sure allocation size matches stackfree16() size below
|
|
vpRect16 = (VPVOID)stackalloc16(sizeof(RECT16));
|
|
|
|
if(vpRect16) {
|
|
putrect16(vpRect16, (LPRECT)lpwm32mpex->lParam);
|
|
|
|
lpwm32mpex->Parm16.WndProc.lParam = (LONG)vpRect16;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
|
|
if (lpwm32mpex->lParam) {
|
|
|
|
vpRect16 = (VPVOID)lpwm32mpex->Parm16.WndProc.lParam;
|
|
|
|
if(vpRect16) {
|
|
getrect16(vpRect16, (LPRECT)lpwm32mpex->lParam);
|
|
|
|
stackfree16(vpRect16, sizeof(RECT16));
|
|
}
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_NCCALCSIZE
|
|
//
|
|
|
|
BOOL FASTCALL WM32NCCalcSize(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
PNCCALCSIZE_PARAMS16 pnc16;
|
|
PNCCALCSIZE_PARAMS16 lpnc16;
|
|
VPWINDOWPOS16 vpwp16;
|
|
LPNCCALCSIZE_PARAMS lParam = (LPNCCALCSIZE_PARAMS)lpwm32mpex->lParam;
|
|
UINT cb;
|
|
VPVOID vp;
|
|
|
|
|
|
// lpwm32mpex->uParam == TRUE ? (lParam is LPNCCALCSIZE_PARAMS) : (lParam is LPRECT);
|
|
//
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
if (lParam) {
|
|
if (lpwm32mpex->uParam)
|
|
cb = sizeof(NCCALCSIZE_PARAMS16) + sizeof(WINDOWPOS16);
|
|
else
|
|
cb = sizeof(RECT16);
|
|
|
|
// be sure allocation size matches stackfree16() size below
|
|
lpwm32mpex->dwTmp[0] = cb;
|
|
vp = (VPVOID)stackalloc16(cb);
|
|
|
|
lpwm32mpex->Parm16.WndProc.lParam = (LONG)vp;
|
|
|
|
putrect16((VPRECT16)vp, (LPRECT)lParam);
|
|
if (lpwm32mpex->uParam) {
|
|
pnc16 = (PNCCALCSIZE_PARAMS16)vp;
|
|
putrect16((VPRECT16)(&pnc16->rgrc[1]), &lParam->rgrc[1]);
|
|
putrect16((VPRECT16)(&pnc16->rgrc[2]), &lParam->rgrc[2]);
|
|
|
|
GETVDMPTR( pnc16, sizeof(NCCALCSIZE_PARAMS16), lpnc16 );
|
|
|
|
vpwp16 = (VPWINDOWPOS16)(pnc16+1);
|
|
lpnc16->lppos = (PWINDOWPOS16)vpwp16;
|
|
|
|
FREEVDMPTR( lpnc16 );
|
|
|
|
putwindowpos16( vpwp16, lParam->lppos );
|
|
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
vp = (VPVOID)lpwm32mpex->Parm16.WndProc.lParam;
|
|
getrect16((VPRECT16)vp, (LPRECT)lParam);
|
|
if (lpwm32mpex->uParam) {
|
|
pnc16 = (PNCCALCSIZE_PARAMS16)vp;
|
|
|
|
getrect16((VPRECT16)(&pnc16->rgrc[1]), &lParam->rgrc[1]);
|
|
getrect16((VPRECT16)(&pnc16->rgrc[2]), &lParam->rgrc[2]);
|
|
|
|
GETVDMPTR( pnc16, sizeof(NCCALCSIZE_PARAMS16), lpnc16 );
|
|
|
|
vpwp16 = (VPWINDOWPOS16)lpnc16->lppos;
|
|
|
|
FREEVDMPTR( lpnc16 );
|
|
|
|
getwindowpos16( vpwp16, lParam->lppos );
|
|
|
|
|
|
}
|
|
if(vp) {
|
|
stackfree16(vp, ((UINT)lpwm32mpex->dwTmp[0]));
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_COMMAND
|
|
//
|
|
|
|
BOOL FASTCALL WM32Command(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
// it's from a control
|
|
HIW(lpwm32mpex->Parm16.WndProc.lParam) = HIWORD(lpwm32mpex->uParam);
|
|
LOW(lpwm32mpex->Parm16.WndProc.lParam) = GETHWND16(lpwm32mpex->lParam);
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_TIMER
|
|
//
|
|
|
|
BOOL FASTCALL WM32Timer(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
|
|
/*
|
|
** map the timer number and the timer proc address (cause its easy)
|
|
*/
|
|
PTMR ptmr;
|
|
|
|
ptmr = FindTimer32((HAND16)GETHWND16(lpwm32mpex->hwnd), lpwm32mpex->uParam);
|
|
|
|
if ( !ptmr ) {
|
|
/*
|
|
** Edit controls create their own timer, which can safely be
|
|
** thunked to itself.
|
|
*/
|
|
if ( lpwm32mpex->lParam || HIWORD(lpwm32mpex->uParam) ) {
|
|
LOGDEBUG(LOG_WARNING,(" WM32Timer ERROR: cannot find timer %08x\n", lpwm32mpex->uParam));
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
lpwm32mpex->Parm16.WndProc.lParam = ptmr->vpfnTimerProc;
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_HSCROLL
|
|
// WM_VSCROLL
|
|
//
|
|
|
|
BOOL FASTCALL WM32HScroll(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
LOW(lpwm32mpex->Parm16.WndProc.lParam) = HIWORD(lpwm32mpex->uParam);
|
|
HIW(lpwm32mpex->Parm16.WndProc.lParam) = GETHWND16(lpwm32mpex->lParam);
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_INITMENU
|
|
// WM_INITMENUPOPUP
|
|
//
|
|
|
|
BOOL FASTCALL WM32InitMenu(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
lpwm32mpex->Parm16.WndProc.wParam = GETHMENU16(lpwm32mpex->uParam);
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_MENUSELECT
|
|
//
|
|
|
|
BOOL FASTCALL WM32MenuSelect(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
|
|
// Copy the menu flags
|
|
LOW(lpwm32mpex->Parm16.WndProc.lParam) = HIWORD(lpwm32mpex->uParam);
|
|
|
|
// Copy the "main" menu
|
|
HIW(lpwm32mpex->Parm16.WndProc.lParam) = GETHMENU16(lpwm32mpex->lParam);
|
|
|
|
if (HIWORD(lpwm32mpex->uParam) == 0xFFFF || !(HIWORD(lpwm32mpex->uParam) & MF_POPUP)) {
|
|
lpwm32mpex->Parm16.WndProc.wParam = LOWORD(lpwm32mpex->uParam); // Its an ID
|
|
}
|
|
else {
|
|
// convert menu index into menu handle
|
|
lpwm32mpex->Parm16.WndProc.wParam = GETHMENU16(GetSubMenu((HMENU)lpwm32mpex->lParam, LOWORD(lpwm32mpex->uParam)));
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_MENUCHAR
|
|
//
|
|
|
|
BOOL FASTCALL WM32MenuChar(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
LOW(lpwm32mpex->Parm16.WndProc.lParam) = HIWORD(lpwm32mpex->uParam);
|
|
HIW(lpwm32mpex->Parm16.WndProc.lParam) = GETHMENU16(lpwm32mpex->lParam);
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_ENTERIDLE
|
|
//
|
|
|
|
BOOL FASTCALL WM32EnterIdle(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
if ((lpwm32mpex->uParam == MSGF_DIALOGBOX) || (lpwm32mpex->uParam == MSGF_MENU)) {
|
|
LOW(lpwm32mpex->Parm16.WndProc.lParam) = GETHWND16(lpwm32mpex->lParam);
|
|
HIW(lpwm32mpex->Parm16.WndProc.lParam) = 0;
|
|
}
|
|
else {
|
|
LOGDEBUG(LOG_ALWAYS,(" WOW::WM_ENTERIDLE: wParam has unknown value, wParam=%08x, Contact ChandanC\n", lpwm32mpex->uParam));
|
|
}
|
|
}
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_PARENTNOTIFY
|
|
//
|
|
|
|
BOOL FASTCALL WM32ParentNotify(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
if ((LOWORD(lpwm32mpex->uParam) == WM_CREATE) || (LOWORD(lpwm32mpex->uParam) == WM_DESTROY)) {
|
|
HIW(lpwm32mpex->Parm16.WndProc.lParam) = HIWORD(lpwm32mpex->uParam);
|
|
LOW(lpwm32mpex->Parm16.WndProc.lParam) = GETHWND16(lpwm32mpex->lParam);
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_MDICreate
|
|
//
|
|
|
|
BOOL FASTCALL WM32MDICreate(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
INT cb;
|
|
VPVOID vp;
|
|
register PMDICREATESTRUCT16 pmcs16;
|
|
LPMDICREATESTRUCT lParam = (LPMDICREATESTRUCT) lpwm32mpex->lParam;
|
|
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
if (lParam) {
|
|
|
|
lpwm32mpex->dwParam = (DWORD)0;
|
|
if (lParam->szClass) {
|
|
if ( HIWORD(lParam->szClass) == 0 ) {
|
|
vp = (VPVOID)lParam->szClass;
|
|
}
|
|
else {
|
|
cb = strlen(lParam->szClass)+1;
|
|
if (!(vp = malloc16(cb)))
|
|
goto Error;
|
|
putstr16(vp, lParam->szClass, cb);
|
|
}
|
|
}
|
|
else {
|
|
vp = (VPVOID)NULL;
|
|
}
|
|
|
|
//
|
|
// pfs:windowsworks overwrite pszclass, so we need to save the
|
|
// so that we can free the memory we just alloced
|
|
//
|
|
lpwm32mpex->dwParam = (DWORD)vp;
|
|
|
|
if (lParam->szTitle) {
|
|
cb = strlen(lParam->szTitle)+1;
|
|
if (!(vp = malloc16(cb)))
|
|
goto Error;
|
|
putstr16(vp, lParam->szTitle, cb);
|
|
}
|
|
else {
|
|
vp = (VPVOID)NULL;
|
|
}
|
|
|
|
// BUGBUG -- The assumption here is that GlobalAlloc will never
|
|
// return a memory object that isn't word-aligned, so that we can
|
|
// assign word-aligned words directly; we have no idea whether the
|
|
// memory is dword-aligned or not however, so dwords must always
|
|
// be paranoidly stored with the STOREDWORD/STORELONG macros -JTP
|
|
|
|
if (!(lpwm32mpex->Parm16.WndProc.lParam = malloc16(sizeof(MDICREATESTRUCT16))))
|
|
goto Error;
|
|
|
|
GETVDMPTR(lpwm32mpex->Parm16.WndProc.lParam, sizeof(MDICREATESTRUCT16), pmcs16);
|
|
STOREDWORD(pmcs16->vpszClass, lpwm32mpex->dwParam);
|
|
STOREDWORD(pmcs16->vpszTitle, vp);
|
|
pmcs16->hOwner = GETHINST16(lParam->hOwner);
|
|
pmcs16->x = (SHORT)lParam->x;
|
|
pmcs16->y = (SHORT)lParam->y;
|
|
pmcs16->cx = (SHORT)lParam->cx;
|
|
pmcs16->cy = (SHORT)lParam->cy;
|
|
STORELONG(pmcs16->style, lParam->style);
|
|
STORELONG(pmcs16->lParam, lParam->lParam);
|
|
|
|
FLUSHVDMPTR(lpwm32mpex->Parm16.WndProc.lParam, sizeof(MDICREATESTRUCT16), pmcs16);
|
|
FREEVDMPTR(pmcs16);
|
|
|
|
return (TRUE);
|
|
|
|
Error:
|
|
LOGDEBUG(LOG_ALWAYS,(" !!!! WM32MDICreate, WM_MDICREATE thunking failed !!!! Window %08lX ", lpwm32mpex->hwnd));
|
|
if (HIW16(lpwm32mpex->dwParam)) free16(lpwm32mpex->dwParam);
|
|
if (vp) free16(vp);
|
|
return FALSE;
|
|
}
|
|
}
|
|
else {
|
|
if (lpwm32mpex->Parm16.WndProc.lParam) {
|
|
GETVDMPTR(lpwm32mpex->Parm16.WndProc.lParam, sizeof(MDICREATESTRUCT16), pmcs16);
|
|
|
|
if (FETCHDWORD(pmcs16->vpszTitle)) {
|
|
free16(FETCHDWORD(pmcs16->vpszTitle));
|
|
}
|
|
|
|
FREEVDMPTR(pmcs16);
|
|
|
|
// if HIWORD(class) is zero, class is an atom, else a pointer.
|
|
|
|
if (HIW16(lpwm32mpex->dwParam)) {
|
|
free16(lpwm32mpex->dwParam);
|
|
}
|
|
|
|
|
|
lpwm32mpex->lReturn = (LONG)HWND32(LOWORD(lpwm32mpex->lReturn));
|
|
free16((VPVOID) lpwm32mpex->Parm16.WndProc.lParam);
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_MDIActivate
|
|
//
|
|
|
|
BOOL FASTCALL WM32MDIActivate(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
BOOL fHwndIsMdiChild;
|
|
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
|
|
// the format of the message is different based on the window that's
|
|
// receiving the message. If 'hwnd' is a MdiClient window it is of one
|
|
// form and if 'hwnd' is MdiChild it is of another form. We need to
|
|
// distinguish between the formats to correctly thunk the message.
|
|
//
|
|
// NOTE: we donot make calls like GetClassName because they are
|
|
// expensive and also I think we came across a case where a
|
|
// window of 'wow private class' processes these messages
|
|
//
|
|
// - Nanduri
|
|
|
|
if (lpwm32mpex->lParam) {
|
|
|
|
// lParam != NULL. The message is definitely going to a MdiChild.
|
|
//
|
|
|
|
fHwndIsMdiChild = TRUE;
|
|
}
|
|
else {
|
|
|
|
// lParam == NULL, doesnot necessarily mean that the message is
|
|
// going to a MdiClient window. So distinguish...
|
|
|
|
if (lpwm32mpex->uParam && (GETHWND16(lpwm32mpex->hwnd) ==
|
|
GETHWND16(lpwm32mpex->uParam))) {
|
|
|
|
// if hwnd is same as uParam then definitely hwnd is a MdiChild
|
|
// window. (because if hwnd is a MdiClient then uParam will be
|
|
// a MdiChild and thus they will not be equal)
|
|
|
|
fHwndIsMdiChild = TRUE;
|
|
}
|
|
else {
|
|
fHwndIsMdiChild = FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
if (fHwndIsMdiChild) {
|
|
lpwm32mpex->Parm16.WndProc.wParam =
|
|
(WORD)(GETHWND16(lpwm32mpex->hwnd) == GETHWND16(lpwm32mpex->lParam));
|
|
LOW(lpwm32mpex->Parm16.WndProc.lParam) = GETHWND16(lpwm32mpex->lParam);
|
|
HIW(lpwm32mpex->Parm16.WndProc.lParam) = GETHWND16(lpwm32mpex->uParam);
|
|
} else {
|
|
lpwm32mpex->Parm16.WndProc.wParam = GETHWND16(lpwm32mpex->uParam);
|
|
lpwm32mpex->Parm16.WndProc.lParam = 0;
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_MDIGETACTIVE
|
|
//
|
|
|
|
BOOL FASTCALL WM32MDIGetActive(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
lpwm32mpex->Parm16.WndProc.lParam = 0;
|
|
}
|
|
else {
|
|
|
|
if (lpwm32mpex->lParam != 0)
|
|
*((LPBOOL)lpwm32mpex->lParam) = (BOOL)HIWORD(lpwm32mpex->lReturn);
|
|
|
|
lpwm32mpex->lReturn = (LONG)HWND32(LOWORD(lpwm32mpex->lReturn));
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_MDISETMENU
|
|
//
|
|
|
|
BOOL FASTCALL WM32MDISetMenu(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
if (lpwm32mpex->uMsg == WM_MDIREFRESHMENU) {
|
|
lpwm32mpex->Parm16.WndProc.wParam = TRUE;
|
|
lpwm32mpex->Parm16.WndProc.wMsg = WM_MDISETMENU;
|
|
}
|
|
else {
|
|
lpwm32mpex->Parm16.WndProc.wParam = 0;
|
|
}
|
|
LOW(lpwm32mpex->Parm16.WndProc.lParam) = GETHMENU16(lpwm32mpex->uParam);
|
|
HIW(lpwm32mpex->Parm16.WndProc.lParam) = GETHMENU16(lpwm32mpex->lParam);
|
|
}
|
|
else {
|
|
lpwm32mpex->lReturn = (LONG)HMENU32(lpwm32mpex->lReturn);
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_SIZECLIPBOARD
|
|
// WM_PAINTCLIPBOARD
|
|
//
|
|
|
|
|
|
BOOL FASTCALL WM32SizeClipBoard(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
HAND16 hMem16 = 0;
|
|
VPVOID vp;
|
|
LPRECT lp;
|
|
HAND16 hdc16;
|
|
BOOL bNotThere;
|
|
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
|
|
lpwm32mpex->dwTmp[0] = 0;
|
|
|
|
lpwm32mpex->Parm16.WndProc.wParam = GETHWND16(lpwm32mpex->uParam);
|
|
|
|
vp = GlobalAllocLock16(GMEM_MOVEABLE, (lpwm32mpex->uMsg == WM_SIZECLIPBOARD) ?
|
|
sizeof(RECT) : sizeof(PAINTSTRUCT), &hMem16);
|
|
if (vp) {
|
|
|
|
if (lp = (LPRECT) GlobalLock((HANDLE) lpwm32mpex->lParam)) {
|
|
if (lpwm32mpex->uMsg == WM_SIZECLIPBOARD) {
|
|
PUTRECT16(vp, lp);
|
|
}
|
|
|
|
// else handle WM_PAINTCLIPBOARD message
|
|
else {
|
|
|
|
bNotThere = FALSE;
|
|
|
|
// Query to see if we've mapped the PAINTSTRUCT->hDC. If
|
|
// not, it means that the hDC was created outside this VDM
|
|
// process and we will have to delete it from our table when
|
|
// un-thunking this message.
|
|
if(!IsGDIh32Mapped(((LPPAINTSTRUCT)lp)->hdc)) {
|
|
bNotThere = TRUE;
|
|
}
|
|
|
|
// The call to putpaintstruct16() may add a GDI handle
|
|
// mapping entry for the hDC in our mapping table (via the
|
|
// GETHDC16 macro)
|
|
hdc16 = putpaintstruct16(vp, (LPPAINTSTRUCT) lp);
|
|
|
|
// save the 32-bit & new 16-bit GDI handles for unthunking
|
|
if(bNotThere) {
|
|
lpwm32mpex->dwTmp[0] = (DWORD)hdc16;
|
|
lpwm32mpex->dwTmp[1] = (DWORD)((LPPAINTSTRUCT)lp)->hdc;
|
|
}
|
|
}
|
|
GlobalUnlock((HANDLE) lpwm32mpex->lParam);
|
|
}
|
|
else {
|
|
LOGDEBUG(LOG_ALWAYS, ("WOW::WM32SizeClipboard: Couldn't lock 32 bit memory handle!\n"));
|
|
// WOW32ASSERT (FALSE);
|
|
}
|
|
|
|
GlobalUnlock16(hMem16);
|
|
}
|
|
else {
|
|
hMem16 = 0;
|
|
LOGDEBUG(LOG_ALWAYS, ("WOW::WM32SizeClipboard: Couldn't allocate memory !\n"));
|
|
WOW32ASSERT (FALSE);
|
|
}
|
|
|
|
LOW(lpwm32mpex->Parm16.WndProc.lParam) = (WORD) hMem16;
|
|
}
|
|
else {
|
|
// Get rid of the hDC added to our table by the call to putpaintstruct16
|
|
// call in the inbound thunk of this message above.
|
|
if (lpwm32mpex->uMsg == WM_PAINTCLIPBOARD) {
|
|
|
|
// If this is !0, it means that the handle hadn't been mapped in our
|
|
// table at the time of the IsGDIh32Mapped() call above.
|
|
if(lpwm32mpex->dwTmp[0]) {
|
|
|
|
hdc16 = (HAND16)LOWORD(lpwm32mpex->dwTmp[0]);
|
|
DeleteWOWGdiHandle((HANDLE)lpwm32mpex->dwTmp[1], hdc16);
|
|
}
|
|
}
|
|
|
|
if (LOW(lpwm32mpex->Parm16.WndProc.lParam)) {
|
|
GlobalUnlockFree16(GlobalLock16(LOW(lpwm32mpex->Parm16.WndProc.lParam), NULL));
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_ASKCBFORMATNAME
|
|
//
|
|
|
|
|
|
BOOL FASTCALL WM32AskCBFormatName(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
lpwm32mpex->Parm16.WndProc.lParam = malloc16(lpwm32mpex->Parm16.WndProc.wParam);
|
|
if (lpwm32mpex->Parm16.WndProc.lParam) {
|
|
putstr16((VPSZ)lpwm32mpex->Parm16.WndProc.lParam, (LPSZ)lpwm32mpex->lParam, lpwm32mpex->uParam);
|
|
}
|
|
|
|
return (BOOL)lpwm32mpex->Parm16.WndProc.lParam;
|
|
}
|
|
else {
|
|
if (lpwm32mpex->Parm16.WndProc.lParam) {
|
|
getstr16((VPSZ)lpwm32mpex->Parm16.WndProc.lParam, (LPSZ)lpwm32mpex->lParam, lpwm32mpex->uParam);
|
|
free16((VPVOID) lpwm32mpex->Parm16.WndProc.lParam);
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_CHANGECBCHAIN
|
|
//
|
|
|
|
BOOL FASTCALL WM32ChangeCBChain(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
lpwm32mpex->Parm16.WndProc.wParam = GETHWND16(lpwm32mpex->uParam);
|
|
lpwm32mpex->Parm16.WndProc.lParam = GETHWND16(lpwm32mpex->lParam);
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_DDEINITIATE
|
|
//
|
|
|
|
BOOL FASTCALL WM32DDEInitiate(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
lpwm32mpex->Parm16.WndProc.wParam = GETHWND16(lpwm32mpex->uParam);
|
|
lpwm32mpex->Parm16.WndProc.lParam = lpwm32mpex->lParam;
|
|
WI32DDEAddInitiator(lpwm32mpex->Parm16.WndProc.wParam);
|
|
}
|
|
else {
|
|
WI32DDEDeleteInitiator((HAND16)GETHWND16(lpwm32mpex->uParam));
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_DDEACK
|
|
//
|
|
|
|
BOOL FASTCALL WM32DDEAck(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
lpwm32mpex->Parm16.WndProc.wParam = GETHWND16(lpwm32mpex->uParam);
|
|
|
|
if (WI32DDEInitiate((HAND16)GETHWND16(lpwm32mpex->hwnd))) {
|
|
//
|
|
// Initiate ACK
|
|
//
|
|
lpwm32mpex->Parm16.WndProc.lParam = lpwm32mpex->lParam;
|
|
}
|
|
else {
|
|
//
|
|
// NON-Initiate ACK
|
|
//
|
|
|
|
UINT lLo = 0;
|
|
UINT lHi = 0;
|
|
PHDDE pDdeNode;
|
|
|
|
UnpackDDElParam(lpwm32mpex->uMsg, lpwm32mpex->lParam, &lLo, &lHi);
|
|
|
|
if (!HIWORD(lHi)) {
|
|
//
|
|
// NON-Execute ACK
|
|
//
|
|
HIW(lpwm32mpex->Parm16.WndProc.lParam) = (WORD) lHi;
|
|
}
|
|
else {
|
|
//
|
|
// Execute ACK
|
|
//
|
|
|
|
//
|
|
// The order of To_hwnd and From_hwnd is reversed in the following
|
|
// DDEFirstPair16(), below. This is done to locate the h32.
|
|
//
|
|
|
|
pDdeNode = DDEFindAckNode ((HAND16)lpwm32mpex->Parm16.WndProc.wParam,
|
|
(HAND16)GETHWND16(lpwm32mpex->hwnd),
|
|
(HANDLE) lHi);
|
|
|
|
if (!pDdeNode) {
|
|
|
|
//
|
|
// When ShellExecute does DDE_EXECUTE to open a document,
|
|
// we don't see its Win32 PostMessage calls so we have no
|
|
// record of the conversation. This is our first opportunity
|
|
// to rectify that, the context of WU32GetMessage thunking
|
|
// a WM_DDE_ACK message. We could also get here for other
|
|
// kinds of ACKs, fortunately the Win32 message alone gives
|
|
// enough context to distinguish the various flavors, unlike
|
|
// the Win16 WM_DDE_ACK.
|
|
//
|
|
|
|
if (lpwm32mpex->lParam >= 0xc0000000) {
|
|
|
|
//
|
|
// ack responding to initiate
|
|
//
|
|
|
|
lpwm32mpex->Parm16.WndProc.lParam = lpwm32mpex->lParam;
|
|
}
|
|
|
|
if (lHi > 0xffff) {
|
|
|
|
//
|
|
// ack responding to execute: global handle in hiword
|
|
//
|
|
|
|
HAND16 h16 = 0;
|
|
DWORD cb;
|
|
VPVOID vp;
|
|
LPBYTE lpMem16, lpMem32;
|
|
DDEINFO DdeInfo;
|
|
|
|
if (!lpwm32mpex->fFree) {
|
|
cb = GlobalSize((HANDLE)lHi);
|
|
vp = GlobalAllocLock16(GMEM_DDESHARE, cb, &h16);
|
|
if (vp) {
|
|
GETMISCPTR(vp, lpMem16);
|
|
lpMem32 = GlobalLock((HANDLE)lHi);
|
|
RtlCopyMemory(lpMem16, lpMem32, cb);
|
|
GlobalUnlock((HANDLE)lHi);
|
|
GlobalUnlock16(h16);
|
|
FREEMISCPTR(lpMem16);
|
|
|
|
DdeInfo.Msg = WM_DDE_EXECUTE;
|
|
DdeInfo.Format = 0;
|
|
DdeInfo.Flags = DDE_PACKET;
|
|
DdeInfo.h16 = 0;
|
|
|
|
DDEAddhandle(
|
|
lpwm32mpex->Parm16.WndProc.wParam,
|
|
GETHWND16(lpwm32mpex->hwnd),
|
|
h16,
|
|
(HANDLE)lHi,
|
|
&DdeInfo
|
|
);
|
|
|
|
pDdeNode = DDEFindAckNode (
|
|
(HAND16)lpwm32mpex->Parm16.WndProc.wParam,
|
|
(HAND16)GETHWND16(lpwm32mpex->hwnd),
|
|
(HANDLE) lHi);
|
|
|
|
WOW32ASSERTMSG(pDdeNode, "WM32DDEAck: Can't find just-added DDE node.\n");
|
|
}
|
|
}
|
|
|
|
lpwm32mpex->Parm16.WndProc.lParam = MAKELONG(LOWORD(lLo), h16);
|
|
|
|
} else {
|
|
|
|
//
|
|
// All other acks have same form: status in loword and
|
|
// item atom in hiword.
|
|
//
|
|
|
|
lpwm32mpex->Parm16.WndProc.lParam = MAKELONG(LOWORD(lLo), lHi);
|
|
}
|
|
|
|
}
|
|
|
|
if (pDdeNode && pDdeNode->DdeMsg == WM_DDE_EXECUTE) {
|
|
|
|
HIW(lpwm32mpex->Parm16.WndProc.lParam) = pDdeNode->hMem16;
|
|
|
|
if (lpwm32mpex->fFree) {
|
|
if (lHi) {
|
|
if (pDdeNode->DdeFlags & DDE_EXECUTE_FREE_MEM) {
|
|
LOGDEBUG (12, ("WOW::W32DDEAck : Freeing EXECUTE pair h16 = %04x, h32 = %08x\n",
|
|
pDdeNode->hMem16, lHi));
|
|
W32UnMarkDDEHandle (pDdeNode->hMem16);
|
|
GlobalUnlockFree16(GlobalLock16(pDdeNode->hMem16, NULL));
|
|
if (DDEDeletehandle(pDdeNode->hMem16, (HANDLE) lHi)) {
|
|
WOWGLOBALFREE((HANDLE)lHi);
|
|
}
|
|
else {
|
|
LOGDEBUG (0, ("WOW::DDE Ack : Ack can't find 16 - 32 aliasing : %04x, %04x, %04x, %08lx, %08lx\n",
|
|
lpwm32mpex->hwnd,
|
|
lpwm32mpex->uMsg,
|
|
lpwm32mpex->Parm16.WndProc.wParam,
|
|
lpwm32mpex->Parm16.WndProc.lParam,
|
|
lHi
|
|
));
|
|
}
|
|
}
|
|
else {
|
|
if (pDdeNode->DdeFlags & DDE_EXECUTE_FREE_H16) {
|
|
W32UnMarkDDEHandle (pDdeNode->hMem16);
|
|
GlobalUnlockFree16(GlobalLock16(pDdeNode->hMem16, NULL));
|
|
|
|
HIW(lpwm32mpex->Parm16.WndProc.lParam) = pDdeNode->h16;
|
|
}
|
|
|
|
if (DDEDeletehandle(pDdeNode->hMem16, (HANDLE) lHi)) {
|
|
WOWGLOBALFREE((HANDLE)lHi);
|
|
}
|
|
else {
|
|
LOGDEBUG (0, ("WOW::DDE Ack : Ack can't find 16 - 32 aliasing : %04x, %04x, %04x, %08lx, %08lx\n",
|
|
lpwm32mpex->hwnd,
|
|
lpwm32mpex->uMsg,
|
|
lpwm32mpex->Parm16.WndProc.wParam,
|
|
lpwm32mpex->Parm16.WndProc.lParam,
|
|
lHi
|
|
));
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
else {
|
|
LOGDEBUG (2, ("WOW::W32DDEAck : h32 is NULL \n"));
|
|
WOW32ASSERT (FALSE);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
LOGDEBUG (2, ("WOW::DDE Ack : Ack received unexpectedly : %x, %04x, %04x, %08lx, %08lx\n", lpwm32mpex->hwnd, lpwm32mpex->uMsg, lpwm32mpex->Parm16.WndProc.wParam, lpwm32mpex->Parm16.WndProc.lParam, lHi));
|
|
}
|
|
}
|
|
|
|
LOW(lpwm32mpex->Parm16.WndProc.lParam) = (WORD) lLo;
|
|
|
|
if (fThunkDDEmsg) {
|
|
FreeDDElParam(lpwm32mpex->uMsg, lpwm32mpex->lParam);
|
|
}
|
|
|
|
LOGDEBUG (12, ("WOW::DDE Ack : %04x, %04x, %04x, %08lx, %08lx\n", lpwm32mpex->hwnd, lpwm32mpex->uMsg, lpwm32mpex->Parm16.WndProc.wParam, lpwm32mpex->Parm16.WndProc.lParam, lHi));
|
|
}
|
|
}
|
|
else {
|
|
//
|
|
// We will execute this scenario only if the app ate the message,
|
|
// because we need to free up the memory.
|
|
//
|
|
|
|
if (!fThunkDDEmsg) {
|
|
if (lpwm32mpex->lReturn) {
|
|
FreeDDElParam(lpwm32mpex->uMsg, lpwm32mpex->lParam);
|
|
}
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_DDE_REQUEST
|
|
// WM_DDE_TERMINATE
|
|
// WM_DDE_UNADVISE
|
|
//
|
|
|
|
BOOL FASTCALL WM32DDERequest(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
lpwm32mpex->Parm16.WndProc.wParam = GETHWND16(lpwm32mpex->uParam);
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_DDEADVISE
|
|
//
|
|
|
|
BOOL FASTCALL WM32DDEAdvise(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
HAND16 h16;
|
|
VPVOID vp;
|
|
LPBYTE lpMem16;
|
|
LPBYTE lpMem32;
|
|
UINT lLo = 0;
|
|
UINT lHi = 0;
|
|
DDEINFO DdeInfo;
|
|
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
UnpackDDElParam(lpwm32mpex->uMsg, lpwm32mpex->lParam, &lLo, &lHi);
|
|
lpwm32mpex->Parm16.WndProc.wParam = GETHWND16(lpwm32mpex->uParam);
|
|
|
|
if (h16 = DDEFindPair16((HAND16)GETHWND16(lpwm32mpex->hwnd),
|
|
(HAND16)lpwm32mpex->Parm16.WndProc.wParam,
|
|
(HANDLE) lLo)) {
|
|
LOW(lpwm32mpex->Parm16.WndProc.lParam) = h16;
|
|
} else {
|
|
vp = GlobalAllocLock16(GMEM_DDESHARE, sizeof(DDEADVISE), &h16);
|
|
if (vp) {
|
|
GETMISCPTR(vp, lpMem16);
|
|
lpMem32 = GlobalLock((HANDLE) lLo);
|
|
RtlCopyMemory(lpMem16, lpMem32, sizeof(DDEADVISE));
|
|
GlobalUnlock((HANDLE) lLo);
|
|
GlobalUnlock16(h16);
|
|
DdeInfo.Msg = LOW(lpwm32mpex->uMsg);
|
|
DdeInfo.Format = 0;
|
|
DdeInfo.Flags = DDE_PACKET;
|
|
DdeInfo.h16 = 0;
|
|
DDEAddhandle((HAND16)GETHWND16(lpwm32mpex->hwnd),
|
|
(HAND16)lpwm32mpex->Parm16.WndProc.wParam,
|
|
h16,
|
|
(HANDLE) lLo,
|
|
&DdeInfo);
|
|
LOW(lpwm32mpex->Parm16.WndProc.lParam) = h16;
|
|
}
|
|
}
|
|
|
|
HIW(lpwm32mpex->Parm16.WndProc.lParam) = (WORD) lHi;
|
|
|
|
if (fThunkDDEmsg) {
|
|
FreeDDElParam(lpwm32mpex->uMsg, lpwm32mpex->lParam);
|
|
}
|
|
}
|
|
else {
|
|
//
|
|
// We will execute this scenario only if the app ate the message,
|
|
// because we need to free up the memory.
|
|
//
|
|
|
|
if (!fThunkDDEmsg) {
|
|
if (lpwm32mpex->lReturn) {
|
|
FreeDDElParam(lpwm32mpex->uMsg, lpwm32mpex->lParam);
|
|
}
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_DDEDATA
|
|
//
|
|
|
|
BOOL FASTCALL WM32DDEData(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
HAND16 h16;
|
|
UINT lLo = 0;
|
|
UINT lHi = 0;
|
|
DDEINFO DdeInfo;
|
|
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
UnpackDDElParam(lpwm32mpex->uMsg, lpwm32mpex->lParam, &lLo, &lHi);
|
|
lpwm32mpex->Parm16.WndProc.wParam = GETHWND16(lpwm32mpex->uParam);
|
|
|
|
if (!lLo) {
|
|
LOW(lpwm32mpex->Parm16.WndProc.lParam) = 0;
|
|
} else if (h16 = DDEFindPair16((HAND16)GETHWND16(lpwm32mpex->hwnd),
|
|
(HAND16)lpwm32mpex->Parm16.WndProc.wParam,
|
|
(HANDLE) lLo)) {
|
|
LOW(lpwm32mpex->Parm16.WndProc.lParam) = h16;
|
|
} else {
|
|
DdeInfo.Msg = LOW(lpwm32mpex->uMsg);
|
|
h16 = DDECopyhData16((HAND16)GETHWND16(lpwm32mpex->hwnd),
|
|
(HAND16)lpwm32mpex->Parm16.WndProc.wParam,
|
|
(HANDLE) lLo,
|
|
&DdeInfo);
|
|
|
|
//
|
|
// If we could not allocate 16 bit memory, then return NULL to the
|
|
// caller.
|
|
//
|
|
|
|
if (!h16) {
|
|
if (fThunkDDEmsg) {
|
|
FreeDDElParam(lpwm32mpex->uMsg, lpwm32mpex->lParam);
|
|
}
|
|
|
|
lpwm32mpex->Parm16.WndProc.wParam = (WORD) lHi;
|
|
lpwm32mpex->Parm16.WndProc.lParam = lLo;
|
|
return (0);
|
|
}
|
|
|
|
|
|
DdeInfo.Flags = DDE_PACKET;
|
|
DdeInfo.h16 = 0;
|
|
DDEAddhandle((HAND16)GETHWND16(lpwm32mpex->hwnd),
|
|
(HAND16)lpwm32mpex->Parm16.WndProc.wParam,
|
|
h16,
|
|
(HANDLE) lLo,
|
|
&DdeInfo);
|
|
|
|
LOW(lpwm32mpex->Parm16.WndProc.lParam) = h16;
|
|
}
|
|
|
|
HIW(lpwm32mpex->Parm16.WndProc.lParam) = (WORD) lHi;
|
|
|
|
if (fThunkDDEmsg) {
|
|
FreeDDElParam(lpwm32mpex->uMsg, lpwm32mpex->lParam);
|
|
}
|
|
|
|
|
|
}
|
|
else {
|
|
|
|
//
|
|
// We will execute this scenario only if the app ate the message,
|
|
// because we need to free up the memory.
|
|
//
|
|
|
|
if (!fThunkDDEmsg) {
|
|
if (lpwm32mpex->lReturn) {
|
|
FreeDDElParam(lpwm32mpex->uMsg, lpwm32mpex->lParam);
|
|
}
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_POKE
|
|
//
|
|
|
|
BOOL FASTCALL WM32DDEPoke(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
HAND16 h16;
|
|
UINT lLo = 0;
|
|
UINT lHi = 0;
|
|
DDEINFO DdeInfo;
|
|
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
UnpackDDElParam(lpwm32mpex->uMsg, lpwm32mpex->lParam, &lLo, &lHi);
|
|
lpwm32mpex->Parm16.WndProc.wParam = GETHWND16(lpwm32mpex->uParam);
|
|
|
|
// sudeepb 03-Apr-1996
|
|
// House Design Gold Edition sends a DDE_POKE message with lParam
|
|
// being 0. We are suppose to thunk this message with lParam being
|
|
// zero. Without this check, the below code will fail this call
|
|
// and the message will not be thunked to the app.
|
|
|
|
if (lLo == 0) {
|
|
LOW(lpwm32mpex->Parm16.WndProc.lParam) = 0;
|
|
HIW(lpwm32mpex->Parm16.WndProc.lParam) = (WORD) lHi;
|
|
return (TRUE);
|
|
}
|
|
|
|
if (h16 = DDEFindPair16((HAND16)GETHWND16(lpwm32mpex->hwnd),
|
|
(HAND16)lpwm32mpex->Parm16.WndProc.wParam,
|
|
(HANDLE) lLo)) {
|
|
LOW(lpwm32mpex->Parm16.WndProc.lParam) = h16;
|
|
} else {
|
|
DdeInfo.Msg = LOW(lpwm32mpex->uMsg);
|
|
h16 = DDECopyhData16((HAND16)GETHWND16(lpwm32mpex->hwnd),
|
|
(HAND16)lpwm32mpex->Parm16.WndProc.wParam,
|
|
(HANDLE) lLo,
|
|
&DdeInfo);
|
|
|
|
|
|
//
|
|
// If we could not allocate 16 bit memory, then return NULL to the
|
|
// caller.
|
|
//
|
|
|
|
if (!h16) {
|
|
if (fThunkDDEmsg) {
|
|
FreeDDElParam(lpwm32mpex->uMsg, lpwm32mpex->lParam);
|
|
}
|
|
|
|
lpwm32mpex->Parm16.WndProc.lParam = lLo;
|
|
return (0);
|
|
}
|
|
|
|
DdeInfo.Flags = DDE_PACKET;
|
|
DdeInfo.h16 = 0;
|
|
DDEAddhandle((HAND16)GETHWND16(lpwm32mpex->hwnd),
|
|
(HAND16)lpwm32mpex->Parm16.WndProc.wParam,
|
|
h16,
|
|
(HANDLE) lLo,
|
|
&DdeInfo);
|
|
|
|
LOW(lpwm32mpex->Parm16.WndProc.lParam) = h16;
|
|
}
|
|
|
|
HIW(lpwm32mpex->Parm16.WndProc.lParam) = (WORD) lHi;
|
|
|
|
if (fThunkDDEmsg) {
|
|
FreeDDElParam(lpwm32mpex->uMsg, lpwm32mpex->lParam);
|
|
}
|
|
}
|
|
else {
|
|
//
|
|
// We will execute this scenario only if the app ate the message,
|
|
// because we need to free up the memory.
|
|
//
|
|
|
|
if (!fThunkDDEmsg) {
|
|
if (lpwm32mpex->lReturn) {
|
|
FreeDDElParam(lpwm32mpex->uMsg, lpwm32mpex->lParam);
|
|
}
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_DDE_EXECUTE
|
|
//
|
|
|
|
BOOL FASTCALL WM32DDEExecute(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
HAND16 h16;
|
|
VPVOID vp;
|
|
LPBYTE lpMem16;
|
|
LPBYTE lpMem32;
|
|
DDEINFO DdeInfo;
|
|
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
lpwm32mpex->Parm16.WndProc.wParam = GETHWND16(lpwm32mpex->uParam);
|
|
|
|
if (h16 = DDEFindPair16((HAND16)GETHWND16(lpwm32mpex->hwnd),
|
|
(HAND16)lpwm32mpex->Parm16.WndProc.wParam,
|
|
(HANDLE) lpwm32mpex->lParam)) {
|
|
HIW(lpwm32mpex->Parm16.WndProc.lParam) = h16;
|
|
} else {
|
|
vp = GlobalAllocLock16(GMEM_DDESHARE, GlobalSize((HANDLE) lpwm32mpex->lParam), &h16);
|
|
if (vp) {
|
|
GETMISCPTR(vp, lpMem16);
|
|
lpMem32 = GlobalLock((HANDLE) lpwm32mpex->lParam);
|
|
RtlCopyMemory(lpMem16, lpMem32, GlobalSize((HANDLE) lpwm32mpex->lParam));
|
|
GlobalUnlock((HANDLE) lpwm32mpex->lParam);
|
|
GlobalUnlock16(h16);
|
|
|
|
DdeInfo.Msg = LOW(lpwm32mpex->uMsg);
|
|
DdeInfo.Format = 0;
|
|
DdeInfo.Flags = DDE_PACKET;
|
|
DdeInfo.h16 = 0;
|
|
DDEAddhandle((HAND16)GETHWND16(lpwm32mpex->hwnd),
|
|
(HAND16)lpwm32mpex->Parm16.WndProc.wParam,
|
|
h16,
|
|
(HANDLE) lpwm32mpex->lParam,
|
|
&DdeInfo);
|
|
|
|
HIW(lpwm32mpex->Parm16.WndProc.lParam) = h16;
|
|
}
|
|
}
|
|
LOW(lpwm32mpex->Parm16.WndProc.lParam) = 0;
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_CTLCOLORMSGBOX
|
|
// WM_CTLCOLOREDIT
|
|
// WM_CTLCOLORLISTBOX
|
|
// WM_CTLCOLORBTN
|
|
// WM_CTLCOLORDLG
|
|
// WM_CTLCOLORSCROLLBAR
|
|
// WM_CTLCOLORSTATIC
|
|
//
|
|
// into WM_CTLCOLOR and the high word of lParam specifies the
|
|
// control type.
|
|
//
|
|
|
|
BOOL FASTCALL WM32CtlColor(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
HAND16 hdc16;
|
|
BOOL bNotThere;
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
|
|
lpwm32mpex->dwTmp[0] = 0;
|
|
|
|
lpwm32mpex->Parm16.WndProc.wMsg = WM_CTLCOLOR;
|
|
if(lpwm32mpex->uMsg != WM_CTLCOLOR) { // see 16-bit thunk for this special case
|
|
// Query to see if we've mapped the hDC32 in uParam. If not, it
|
|
// means that hDC32 was created outside this VDM and we will have
|
|
// to delete it from our table when un-thunking this message.
|
|
bNotThere = FALSE;
|
|
if(!IsGDIh32Mapped((HANDLE)lpwm32mpex->uParam)) {
|
|
bNotThere = TRUE;
|
|
}
|
|
|
|
// The GetHDC16 macro may cause the hDC to be added to our mapping
|
|
// table if it wasn't already there.
|
|
hdc16 = GETHDC16(lpwm32mpex->uParam);
|
|
lpwm32mpex->Parm16.WndProc.wParam = hdc16;
|
|
|
|
// save the 32-bit & new 16-bit GDI handles for unthunking
|
|
if(bNotThere) {
|
|
lpwm32mpex->dwTmp[0] = (DWORD)hdc16;
|
|
lpwm32mpex->dwTmp[1] = lpwm32mpex->uParam;
|
|
}
|
|
|
|
LOW(lpwm32mpex->Parm16.WndProc.lParam) = GETHWND16(lpwm32mpex->lParam);
|
|
HIW(lpwm32mpex->Parm16.WndProc.lParam) = (WORD) (lpwm32mpex->uMsg - WM_CTLCOLORMSGBOX);
|
|
}
|
|
}
|
|
else {
|
|
if ((ULONG)lpwm32mpex->lReturn > COLOR_ENDCOLORS) {
|
|
lpwm32mpex->lReturn = (LONG) HBRUSH32(lpwm32mpex->lReturn);
|
|
}
|
|
|
|
// If this is !0, it means that the handle hadn't been mapped in our
|
|
// table at the time of the IsGDIh32Mapped() call above.
|
|
if(lpwm32mpex->dwTmp[0]) {
|
|
|
|
// Remove the hdc that was added to our table by the GETHDC16 macro
|
|
// in the inbound thunk of this message above.
|
|
hdc16 = (HAND16)LOWORD(lpwm32mpex->dwTmp[0]);
|
|
DeleteWOWGdiHandle((HANDLE)lpwm32mpex->dwTmp[1], hdc16);
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_GETFONT
|
|
//
|
|
|
|
BOOL FASTCALL WM32GetFont(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
if (!lpwm32mpex->fThunk) {
|
|
// This might be a possible GDI handle mapping table leak if the
|
|
// HFONT was created outside of this VDM process. In this case, the
|
|
// HFONT32 macro will cause the h32 to be added to our mapping table. We
|
|
// don't have any clues when to remove it. Not much we can do except
|
|
// remove it at reclaim time if it is no longer valid.
|
|
lpwm32mpex->lReturn = (LONG)HFONT32(lpwm32mpex->lReturn);
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_NEXTMENU
|
|
//
|
|
// Win16 NT
|
|
// wParam VK_KEY VK_KEY
|
|
// lParam.l hmenu PMDINEXTMENU
|
|
// lParam.h 0
|
|
// return.l menu BOOL
|
|
// return.h window
|
|
//
|
|
|
|
|
|
BOOL FASTCALL WM32NextMenu(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
if (lpwm32mpex->lParam) {
|
|
LOW(lpwm32mpex->Parm16.WndProc.lParam) = GETHMENU16(((PMDINEXTMENU)lpwm32mpex->lParam)->hmenuIn);
|
|
HIW(lpwm32mpex->Parm16.WndProc.lParam) = 0;
|
|
}
|
|
} else {
|
|
if (lpwm32mpex->lParam) {
|
|
((PMDINEXTMENU)lpwm32mpex->lParam)->hmenuNext = HMENU32(LOWORD(lpwm32mpex->lReturn));
|
|
((PMDINEXTMENU)lpwm32mpex->lParam)->hwndNext = HWND32(HIWORD(lpwm32mpex->lReturn));
|
|
lpwm32mpex->lReturn = TRUE;
|
|
} else {
|
|
lpwm32mpex->lReturn = FALSE;
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
BOOL FASTCALL WM32Destroy (LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
if (!lpwm32mpex->fThunk) {
|
|
if (CACHENOTEMPTY()) {
|
|
// because of our method of window aliasing, 'hwnd' may or may
|
|
// not be a real 32bit handle. ie. it may be (hwnd16 | 0xffff0000).
|
|
// So always use hwnd16.
|
|
|
|
ReleaseCachedDCs((CURRENTPTD())->htask16, GETHWND16(lpwm32mpex->hwnd), 0,
|
|
(HWND)0, SRCHDC_TASK16_HWND16);
|
|
}
|
|
}
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// This function thunks the messages,
|
|
// WM_DROPFILES
|
|
|
|
BOOL FASTCALL WM32DropFiles(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
if (lpwm32mpex->fThunk) {
|
|
return (BOOL)(lpwm32mpex->Parm16.WndProc.wParam = GETHDROP16(lpwm32mpex->uParam));
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// This function thunks the messages,
|
|
// WM_PRINT
|
|
// WM_PRINTCLIENT
|
|
|
|
BOOL FASTCALL WM32PrintClient(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
HAND16 hdc16;
|
|
BOOL bNotThere;
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
|
|
|
|
// Query to see if we've mapped hDC32 in uParam. If not, it means that
|
|
// hDC32 was created outside this VDM process and we will have to
|
|
// delete it from our table when un-thunking this message.
|
|
bNotThere = FALSE;
|
|
lpwm32mpex->dwTmp[0] = 0;
|
|
if(!IsGDIh32Mapped((HANDLE)lpwm32mpex->uParam)) {
|
|
bNotThere = TRUE;
|
|
}
|
|
|
|
// GETHDC16() may cause a new handle to be added to our handle table.
|
|
hdc16 = GETHDC16(lpwm32mpex->uParam);
|
|
|
|
// save the 32-bit & new 16-bit GDI handles for unthunking
|
|
if(bNotThere) {
|
|
lpwm32mpex->dwTmp[0] = (DWORD)hdc16;
|
|
lpwm32mpex->dwTmp[1] = lpwm32mpex->uParam;
|
|
}
|
|
|
|
lpwm32mpex->Parm16.WndProc.wParam = hdc16;
|
|
|
|
return ((BOOL)hdc16);
|
|
}
|
|
|
|
// unthunk
|
|
else {
|
|
|
|
// If this is !0, it means that the handle hadn't been mapped in our
|
|
// table at the time of the IsGDIh32Mapped() call above.
|
|
if(lpwm32mpex->dwTmp[0]) {
|
|
|
|
// Remove the hdc that was added to our table by the GETHDC16 macro
|
|
// in the inbound thunk of this message above.
|
|
hdc16 = (HAND16)LOWORD(lpwm32mpex->dwTmp[0]);
|
|
DeleteWOWGdiHandle((HANDLE)lpwm32mpex->dwTmp[1], hdc16);
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_DROPOBJECT
|
|
// WM_QUERYDROPOBJECT
|
|
// WM_DRAGLOOP
|
|
// WM_DRAGSELECT
|
|
// WM_DRAGMOVE
|
|
//
|
|
|
|
BOOL FASTCALL WM32DropObject(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
register PDROPSTRUCT16 pds16;
|
|
register LPDROPSTRUCT lParam = (LPDROPSTRUCT)lpwm32mpex->lParam;
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
|
|
lpwm32mpex->Parm16.WndProc.wParam = (WORD)lpwm32mpex->uParam;
|
|
|
|
// BUGBUG -- The assumption here is that GlobalAlloc will never
|
|
// return a memory object that isn't word-aligned, so that we can
|
|
// assign word-aligned words directly; we have no idea whether the
|
|
// memory is dword-aligned or not however, so dwords must always
|
|
// be paranoidly stored with the STOREDWORD/STORELONG macros -JTP
|
|
|
|
if (!(lpwm32mpex->Parm16.WndProc.lParam = malloc16(sizeof(DROPSTRUCT16))))
|
|
return FALSE;
|
|
|
|
GETVDMPTR(lpwm32mpex->Parm16.WndProc.lParam, sizeof(DROPSTRUCT16), pds16);
|
|
|
|
pds16->hwndSource = GETHWND16(lParam->hwndSource);
|
|
pds16->hwndSink = GETHWND16(lParam->hwndSink);
|
|
pds16->wFmt = (WORD) lParam->wFmt;
|
|
STOREDWORD(pds16->dwData, lParam->dwData);
|
|
|
|
pds16->ptDrop.x = (SHORT)lParam->ptDrop.x;
|
|
pds16->ptDrop.y = (SHORT)lParam->ptDrop.y;
|
|
STOREDWORD(pds16->dwControlData, lParam->dwControlData);
|
|
|
|
FLUSHVDMPTR(lpwm32mpex->Parm16.WndProc.lParam, sizeof(DROPSTRUCT16), pds16);
|
|
FREEVDMPTR(pds16);
|
|
|
|
} else {
|
|
|
|
free16((VPVOID) lpwm32mpex->Parm16.WndProc.lParam);
|
|
|
|
if (lpwm32mpex->uMsg == WM_QUERYDROPOBJECT) {
|
|
|
|
//
|
|
// Return value is either TRUE, FALSE,
|
|
// or a cursor!
|
|
//
|
|
if (lpwm32mpex->lReturn && lpwm32mpex->lReturn != (LONG)TRUE) {
|
|
lpwm32mpex->lReturn = (LONG)HCURSOR32(lpwm32mpex->lReturn);
|
|
}
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_WINDOWPOSCHANGING
|
|
// WM_WINDOWPOSCHANGED
|
|
//
|
|
|
|
BOOL FASTCALL WM32WindowPosChanging (LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
LPWINDOWPOS lParam = (LPWINDOWPOS) lpwm32mpex->lParam;
|
|
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
|
|
// be sure allocation size matches stackfree16() size below
|
|
lpwm32mpex->Parm16.WndProc.lParam = stackalloc16(sizeof(WINDOWPOS16));
|
|
|
|
putwindowpos16( (VPWINDOWPOS16)lpwm32mpex->Parm16.WndProc.lParam, lParam );
|
|
|
|
}
|
|
else {
|
|
getwindowpos16( (VPWINDOWPOS16)lpwm32mpex->Parm16.WndProc.lParam, lParam );
|
|
if(lpwm32mpex->Parm16.WndProc.lParam) {
|
|
stackfree16((VPVOID) lpwm32mpex->Parm16.WndProc.lParam,
|
|
sizeof(WINDOWPOS16));
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
// This function thunks the message,
|
|
//
|
|
// WM_COPYDATA
|
|
//
|
|
|
|
BOOL FASTCALL WM32CopyData (LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
|
|
HAND16 h16;
|
|
HAND16 hMem16;
|
|
VPVOID vpCDS16;
|
|
VPVOID vpData16;
|
|
LPBYTE lpMem16;
|
|
PCOPYDATASTRUCT lpCDS32;
|
|
PCOPYDATASTRUCT lpCDS16;
|
|
PCPDATA pTemp;
|
|
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
lpwm32mpex->Parm16.WndProc.wParam = GETHWND16(lpwm32mpex->uParam);
|
|
|
|
if (vpCDS16 = CopyDataFindData16 (GETHWND16(lpwm32mpex->hwnd), lpwm32mpex->Parm16.WndProc.wParam, lpwm32mpex->lParam)) {
|
|
lpwm32mpex->Parm16.WndProc.lParam = vpCDS16;
|
|
}
|
|
else {
|
|
vpCDS16 = GlobalAllocLock16(GMEM_DDESHARE, sizeof(COPYDATASTRUCT), &h16);
|
|
if (vpCDS16) {
|
|
GETMISCPTR(vpCDS16, lpCDS16);
|
|
lpCDS32 = (PCOPYDATASTRUCT) lpwm32mpex->lParam;
|
|
lpCDS16->dwData = lpCDS32->dwData;
|
|
if (lpCDS16->cbData = lpCDS32->cbData) {
|
|
|
|
FREEMISCPTR(lpCDS16);
|
|
|
|
vpData16 = GlobalAllocLock16(GMEM_DDESHARE, lpCDS32->cbData, &hMem16);
|
|
GETMISCPTR(vpData16, lpMem16);
|
|
if (lpMem16 && lpCDS32->lpData) {
|
|
RtlCopyMemory(lpMem16, lpCDS32->lpData, lpCDS32->cbData);
|
|
CopyDataAddNode (GETHWND16(lpwm32mpex->hwnd), lpwm32mpex->Parm16.WndProc.wParam, vpData16, (DWORD) lpCDS32->lpData, 0);
|
|
}
|
|
FREEMISCPTR(lpMem16);
|
|
|
|
GETMISCPTR(vpCDS16, lpCDS16);
|
|
lpCDS16->lpData = (PVOID) vpData16;
|
|
}
|
|
else {
|
|
lpCDS16->lpData = NULL;
|
|
}
|
|
FREEMISCPTR(lpCDS16);
|
|
}
|
|
|
|
lpwm32mpex->Parm16.WndProc.lParam = vpCDS16;
|
|
CopyDataAddNode (GETHWND16(lpwm32mpex->hwnd), lpwm32mpex->Parm16.WndProc.wParam, vpCDS16, lpwm32mpex->lParam, 0);
|
|
}
|
|
}
|
|
else {
|
|
if (lpwm32mpex->fFree) {
|
|
pTemp = CopyDataFindData32 (GETHWND16(lpwm32mpex->hwnd), GETHWND16(lpwm32mpex->uParam), lpwm32mpex->Parm16.WndProc.lParam);
|
|
if (pTemp && (!(pTemp->Flags))) {
|
|
GETMISCPTR(lpwm32mpex->Parm16.WndProc.lParam, lpCDS16);
|
|
GlobalUnlockFree16 ((VPVOID)lpCDS16->lpData);
|
|
CopyDataDeleteNode (GETHWND16(lpwm32mpex->hwnd), lpwm32mpex->Parm16.WndProc.wParam, (DWORD) ((PCOPYDATASTRUCT)lpwm32mpex->lParam)->lpData);
|
|
GlobalUnlockFree16 ((VPVOID)lpwm32mpex->Parm16.WndProc.lParam);
|
|
CopyDataDeleteNode (GETHWND16(lpwm32mpex->hwnd), lpwm32mpex->Parm16.WndProc.wParam, (DWORD) lpwm32mpex->lParam);
|
|
FREEMISCPTR(lpCDS16);
|
|
}
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
// This function thunks the message,
|
|
//
|
|
// WM_WINHELP
|
|
//
|
|
|
|
BOOL FASTCALL WM32WinHelp (LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
static WORD msgWinHelp = 0;
|
|
if (lpwm32mpex->fThunk) {
|
|
lpwm32mpex->Parm16.WndProc.wMsg = msgWinHelp ? msgWinHelp : (msgWinHelp = (WORD)RegisterWindowMessage("WM_WINHELP"));
|
|
lpwm32mpex->Parm16.WndProc.wParam = GETHWND16(lpwm32mpex->uParam);
|
|
if (lpwm32mpex->lParam) {
|
|
// lpwm32mpex->lParam is LPHLP - however we need only the firstword,ie the size of data
|
|
|
|
HAND16 hMem16 = 0;
|
|
VPVOID vp;
|
|
LPBYTE lpT;
|
|
WORD cb;
|
|
|
|
cb = ((LPHLP)lpwm32mpex->lParam)->cbData;
|
|
if (vp = GlobalAllocLock16(GMEM_DDESHARE | GMEM_MOVEABLE, cb, &hMem16)) {
|
|
GETMISCPTR(vp, lpT);
|
|
RtlCopyMemory(lpT, (PVOID)lpwm32mpex->lParam, cb);
|
|
FREEMISCPTR(lpT);
|
|
|
|
}
|
|
lpwm32mpex->Parm16.WndProc.lParam = hMem16;
|
|
lpwm32mpex->dwParam = vp;
|
|
}
|
|
}
|
|
else {
|
|
// Make sure WinHelp is in the foreground
|
|
SetForegroundWindow(lpwm32mpex->hwnd);
|
|
if (lpwm32mpex->Parm16.WndProc.lParam) {
|
|
GlobalUnlockFree16((VPVOID)lpwm32mpex->dwParam);
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
//
|
|
// Thunk the undocumented MM_CALCSCROLL MDI message. Message has no parameters,
|
|
// but has different message values; 32-bit msg: 0x3F, 16-bit msg: 0x10AC.
|
|
//
|
|
BOOL FASTCALL WM32MMCalcScroll (LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
if ( lpwm32mpex->fThunk ) {
|
|
lpwm32mpex->Parm16.WndProc.wMsg = (WORD) WIN31_MM_CALCSCROLL;
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
// Calculate the size of the structure passed with WM_NOTIFY based
|
|
// on the code field in NMHDR.
|
|
// NOTE: Do NOT rely on the documentation for the size of the struct passed in
|
|
// lParam. In some cases the struct is actually part of a larger struct
|
|
// and we need to copy all of it. See PSN_xxxx codes in comctl32\prsht.c
|
|
// They are documented to be NMHDR but are really a PSHNOTIFY which has
|
|
// NMHDR as the first field. Also watch for some of the WIDE UNICODE
|
|
// char cases -- the struct may or may not be the same size as the ANSI
|
|
// version of the struct.
|
|
// Heaven help us when they start adding more of these codes!
|
|
|
|
|
|
UINT GetNMHDRextensionSize(LPNMHDR pnmhdr32)
|
|
{
|
|
#ifdef DEBUG
|
|
char szLabel[40] = " WOW:WM_NOTIFY code: ";
|
|
#endif
|
|
|
|
|
|
// Caller already checked against NM_LAST.
|
|
if (pnmhdr32->code >= LVN_LAST) {
|
|
LOGDEBUG(2,("%sLVN_ %x\n", szLabel, pnmhdr32->code));
|
|
switch (pnmhdr32->code) {
|
|
|
|
case LVN_ITEMCHANGING:
|
|
case LVN_ITEMCHANGED:
|
|
case LVN_INSERTITEM:
|
|
case LVN_DELETEITEM:
|
|
case LVN_DELETEALLITEMS:
|
|
case LVN_COLUMNCLICK:
|
|
case LVN_BEGINDRAG:
|
|
case LVN_BEGINRDRAG:
|
|
case LVN_HOTTRACK:
|
|
return sizeof(NM_LISTVIEW);
|
|
|
|
case LVN_BEGINLABELEDITA:
|
|
case LVN_ENDLABELEDITA:
|
|
case LVN_GETDISPINFOA:
|
|
case LVN_SETDISPINFOA:
|
|
case LVN_BEGINLABELEDITW:
|
|
case LVN_ENDLABELEDITW:
|
|
case LVN_GETDISPINFOW:
|
|
case LVN_SETDISPINFOW:
|
|
return sizeof(LV_DISPINFO);
|
|
|
|
case LVN_KEYDOWN:
|
|
return sizeof(LV_KEYDOWN);
|
|
|
|
case LVN_ODCACHEHINT:
|
|
return sizeof(NM_CACHEHINT);
|
|
|
|
case LVN_ODFINDITEMA:
|
|
case LVN_ODFINDITEMW:
|
|
return sizeof(NM_FINDITEM);
|
|
|
|
case LVN_ODSTATECHANGED:
|
|
return sizeof(NM_ODSTATECHANGE);
|
|
|
|
case LVN_ITEMACTIVATE:
|
|
return sizeof(NMKEY);
|
|
|
|
default:
|
|
goto unknown_nmhdr_code;
|
|
}
|
|
}
|
|
|
|
if (pnmhdr32->code >= PSN_LAST) {
|
|
LOGDEBUG(2,("%sPSN_ %x\n", szLabel, pnmhdr32->code));
|
|
switch (pnmhdr32->code) {
|
|
case PSN_SETACTIVE:
|
|
case PSN_KILLACTIVE:
|
|
case PSN_APPLY:
|
|
case PSN_RESET:
|
|
case PSN_HELP:
|
|
case PSN_WIZBACK:
|
|
case PSN_WIZNEXT:
|
|
case PSN_WIZFINISH:
|
|
case PSN_QUERYCANCEL:
|
|
case PSN_TRANSLATEACCELERATOR:
|
|
case PSN_QUERYINITIALFOCUS:
|
|
case PSN_HASHELP: // this one "is dead" - RaymondC
|
|
return sizeof(PSHNOTIFY);
|
|
|
|
case PSN_GETOBJECT:
|
|
return sizeof(NMOBJECTNOTIFY);
|
|
|
|
case PSN_LASTCHANCEAPPLY: // this is undocumented
|
|
return sizeof(NMHDR); // (in widows\inc\prshtp.h)
|
|
|
|
default:
|
|
goto unknown_nmhdr_code;
|
|
}
|
|
}
|
|
|
|
if (pnmhdr32->code >= HDN_LAST) {
|
|
LOGDEBUG(2,("%sHDN_ %x\n", szLabel, pnmhdr32->code));
|
|
switch (pnmhdr32->code) {
|
|
case HDN_ITEMCHANGINGA:
|
|
case HDN_ITEMCHANGEDA:
|
|
case HDN_ITEMCLICKA:
|
|
case HDN_DIVIDERDBLCLICKA:
|
|
case HDN_BEGINTRACKA:
|
|
case HDN_ENDTRACKA:
|
|
case HDN_TRACKA:
|
|
case HDN_ITEMCHANGINGW:
|
|
case HDN_ITEMCHANGEDW:
|
|
case HDN_ITEMCLICKW:
|
|
case HDN_DIVIDERDBLCLICKW:
|
|
case HDN_BEGINTRACKW:
|
|
case HDN_ENDTRACKW:
|
|
case HDN_TRACKW:
|
|
case HDN_BEGINDRAG:
|
|
case HDN_ENDDRAG:
|
|
case HDN_ITEMDBLCLICKA:
|
|
case HDN_ITEMDBLCLICKW:
|
|
return sizeof(HD_NOTIFY);
|
|
|
|
case HDN_GETDISPINFOA:
|
|
case HDN_GETDISPINFOW:
|
|
return sizeof(NMHDDISPINFO);
|
|
|
|
default:
|
|
goto unknown_nmhdr_code;
|
|
}
|
|
}
|
|
|
|
if (pnmhdr32->code >= TVN_LAST) {
|
|
LOGDEBUG(2,("%sTVN_ %x\n", szLabel, pnmhdr32->code));
|
|
switch (pnmhdr32->code) {
|
|
case TVN_SELCHANGINGA:
|
|
case TVN_SELCHANGEDA:
|
|
case TVN_ITEMEXPANDINGA:
|
|
case TVN_ITEMEXPANDEDA:
|
|
case TVN_BEGINDRAGA:
|
|
case TVN_BEGINRDRAGA:
|
|
case TVN_DELETEITEMA:
|
|
case TVN_SELCHANGINGW:
|
|
case TVN_SELCHANGEDW:
|
|
case TVN_ITEMEXPANDINGW:
|
|
case TVN_ITEMEXPANDEDW:
|
|
case TVN_BEGINDRAGW:
|
|
case TVN_BEGINRDRAGW:
|
|
case TVN_DELETEITEMW:
|
|
case TVN_SINGLEEXPAND:
|
|
return sizeof(NM_TREEVIEW);
|
|
|
|
case TVN_GETDISPINFOA:
|
|
case TVN_SETDISPINFOA:
|
|
case TVN_BEGINLABELEDITA:
|
|
case TVN_ENDLABELEDITA:
|
|
case TVN_GETDISPINFOW:
|
|
case TVN_SETDISPINFOW:
|
|
case TVN_BEGINLABELEDITW:
|
|
case TVN_ENDLABELEDITW:
|
|
return sizeof(TV_DISPINFO);
|
|
|
|
case TVN_KEYDOWN:
|
|
return sizeof(TV_KEYDOWN);
|
|
|
|
case TVN_GETINFOTIPA:
|
|
case TVN_GETINFOTIPW:
|
|
return sizeof(NMTVGETINFOTIP);
|
|
|
|
default:
|
|
goto unknown_nmhdr_code;
|
|
}
|
|
}
|
|
|
|
if (pnmhdr32->code >= TTN_LAST) {
|
|
LOGDEBUG(2,("%sTTN_ %x\n", szLabel, pnmhdr32->code));
|
|
switch (pnmhdr32->code) {
|
|
case TTN_NEEDTEXTA: // (aka TTN_GETDISPINFO)
|
|
return sizeof(TOOLTIPTEXTA);
|
|
|
|
case TTN_NEEDTEXTW:
|
|
return sizeof(TOOLTIPTEXTW);
|
|
|
|
case TTN_SHOW:
|
|
case TTN_POP:
|
|
return sizeof(NMHDR);
|
|
|
|
default:
|
|
goto unknown_nmhdr_code;
|
|
}
|
|
}
|
|
|
|
if (pnmhdr32->code >= TCN_LAST) {
|
|
LOGDEBUG(2,("%sTCN_ %x\n", szLabel, pnmhdr32->code));
|
|
switch (pnmhdr32->code) {
|
|
case TCN_KEYDOWN:
|
|
return sizeof(TC_KEYDOWN);
|
|
|
|
case TCN_SELCHANGE:
|
|
case TCN_SELCHANGING:
|
|
return sizeof(NMHDR);
|
|
|
|
default:
|
|
goto unknown_nmhdr_code;
|
|
}
|
|
}
|
|
|
|
if (pnmhdr32->code >= UDN_LAST) {
|
|
LOGDEBUG(2,("%sUDN_ %x\n", szLabel, pnmhdr32->code));
|
|
switch (pnmhdr32->code) {
|
|
case UDN_DELTAPOS:
|
|
return sizeof(NM_UPDOWN);
|
|
|
|
default:
|
|
goto unknown_nmhdr_code;
|
|
}
|
|
}
|
|
|
|
unknown_nmhdr_code:
|
|
LOGDEBUG(LOG_ALWAYS, ("WOW:GetNMHDRextensionSize unknown nmhdr->code: %d!\n", pnmhdr32->code));
|
|
WOW32ASSERT(FALSE);
|
|
return sizeof(NMHDR); // the first field of most of the structs is NMHDR
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// This function thunks the 32-bit message WM_NOTIFY. This message existed
|
|
// but was undocumented in Win3.1. Win95 thunks it by translating lParam
|
|
// from a flat to 16:16 pointer without thunking the contents. That's tricky
|
|
// for us since on RISC we can't map random linear memory into the VDM without
|
|
// a lot of overhead. We'll use the code field in NMHDR to calculate the size
|
|
// of the passed structure.
|
|
//
|
|
BOOL FASTCALL WM32Notify(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
LPNMHDR pnmhdr32;
|
|
LPNMHDR pnmhdr16;
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
|
|
pnmhdr32 = (LPNMHDR) lpwm32mpex->Parm16.WndProc.lParam;
|
|
|
|
// Save the original 32-bit flat pointer for unthunking.
|
|
lpwm32mpex->dwTmp[0] = (DWORD) pnmhdr32;
|
|
|
|
// If this 32bit message came from WOW, we have the original
|
|
// 16:16 lparam squirrelled away. (mapped to the original 32-bit lParam)
|
|
// Note: If the mapping is found, the ref count gets incremented.
|
|
lpwm32mpex->Parm16.WndProc.lParam = (LONG)GetParam16(lpwm32mpex->lParam);
|
|
|
|
// if we don't already have a 16:16 ptr for this -- create one
|
|
// This means we are seeing this message for the 1st time -- coming
|
|
// from the 32-bit world.
|
|
if ( ! lpwm32mpex->Parm16.WndProc.lParam) {
|
|
if (pnmhdr32->code >= NM_LAST) {
|
|
lpwm32mpex->dwParam = sizeof(NMHDR);
|
|
}
|
|
else {
|
|
lpwm32mpex->dwParam = GetNMHDRextensionSize(pnmhdr32);
|
|
}
|
|
|
|
// be sure allocation size matches stackfree16() size below
|
|
lpwm32mpex->dwTmp[1] = (DWORD)lpwm32mpex->dwParam;
|
|
lpwm32mpex->Parm16.WndProc.lParam = stackalloc16(lpwm32mpex->dwTmp[1]);
|
|
GETVDMPTR(lpwm32mpex->Parm16.WndProc.lParam, lpwm32mpex->dwParam, pnmhdr16);
|
|
CopyMemory(pnmhdr16, pnmhdr32, lpwm32mpex->dwParam);
|
|
FREEVDMPTR(pnmhdr16);
|
|
|
|
// else don't allocate (or free) another 16:16 ptr
|
|
} else {
|
|
|
|
// set to FALSE so we don't free this thing too soon
|
|
lpwm32mpex->fFree = FALSE;
|
|
}
|
|
|
|
} else {
|
|
|
|
if (lpwm32mpex->fFree) {
|
|
GETVDMPTR(lpwm32mpex->Parm16.WndProc.lParam, lpwm32mpex->dwParam, pnmhdr16);
|
|
// retrieve original 32-bit pointer
|
|
pnmhdr32 = (LPNMHDR) lpwm32mpex->dwTmp[0];
|
|
CopyMemory(pnmhdr32, pnmhdr16, lpwm32mpex->dwParam);
|
|
FREEVDMPTR(pnmhdr16);
|
|
if(lpwm32mpex->Parm16.WndProc.lParam) {
|
|
stackfree16(lpwm32mpex->Parm16.WndProc.lParam, lpwm32mpex->dwTmp[1]);
|
|
}
|
|
} else {
|
|
|
|
// Decrement the ref count. If the ref count goes to zero, the
|
|
// mapping is nuked.
|
|
DeleteParamMap(lpwm32mpex->Parm16.WndProc.lParam, PARAM_16, NULL);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// This function thunks the 32-bit message WM_NOTIFYWOW.
|
|
// uParam dictates where the notification should be dispatched.
|
|
//
|
|
|
|
|
|
BOOL FASTCALL WM32NotifyWow(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
switch (lpwm32mpex->uParam) {
|
|
case WMNW_UPDATEFINDREPLACE:
|
|
if (lpwm32mpex->fThunk) {
|
|
// Update the 16-bit FINDREPLACE struct.
|
|
lpwm32mpex->Parm16.WndProc.lParam = WCD32UpdateFindReplaceTextAndFlags(lpwm32mpex->hwnd, lpwm32mpex->lParam);
|
|
lpwm32mpex->Parm16.WndProc.wMsg = msgFINDREPLACE;
|
|
return(TRUE);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
LOGDEBUG(LOG_ALWAYS, ("WOW::WM32NotifyWow: Unknown dispatch parameter!\n"));
|
|
WOW32ASSERT (FALSE);
|
|
|
|
}
|
|
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// In ThunkMsg16 we use the data in 32->16 message thunk table to optimize
|
|
// thunking process based on 'WM32NoThunking'.
|
|
//
|
|
// This is place holder for those messages which need nothunking on 32-16
|
|
// trasitions but need some kind of thunking on 16->32 transistions.
|
|
//
|
|
// So this marks the message as 'this message needs 16-32 thunking but
|
|
// not 32-16 thunking'
|
|
//
|
|
// - nanduri
|
|
|
|
BOOL FASTCALL WM32Thunk16To32(LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
return (TRUE);
|
|
}
|
|
#ifdef FE_IME
|
|
//
|
|
// This function thunks the messages,
|
|
//
|
|
// WM_IME_REPORT
|
|
|
|
/*
|
|
BOOL FASTCALL WM32IMEReport (HWND hwnd, UINT uMsg, UINT uParam, LONG lParam,
|
|
PWORD pwMsgNew, PWORD pwParamNew, PLONG plParamNew,
|
|
PLONG plReturn, BOOL fThunk, LPWM32MSGPARAMEX lpwm32mpex)
|
|
*/
|
|
BOOL FASTCALL WM32IMEReport (LPWM32MSGPARAMEX lpwm32mpex)
|
|
{
|
|
//lpwm32mpex->hwnd
|
|
//lpwm32mpex->uMsg
|
|
//lpwm32mpex->uParam
|
|
//lpwm32mpex->lParam
|
|
//lpwm32mpex->Param16.WndProc.wMsg
|
|
//lpwm32mpex->Param16.WndProc.wParam
|
|
//lpwm32mpex->Param16.WndProc.lParam
|
|
//&lpwm32mpex->lReturn
|
|
//lpwm32mpex->fThunk
|
|
//
|
|
|
|
INT cb;
|
|
INT i;
|
|
HMEM16 hMem16 = 0;
|
|
LPBYTE lpMem32 = 0;
|
|
LPBYTE lpMem16 = 0;
|
|
VPVOID vp;
|
|
|
|
|
|
if (lpwm32mpex->fThunk) {
|
|
if (lpwm32mpex->uParam == IR_STRING) {
|
|
lpMem32 = GlobalLock((HANDLE)lpwm32mpex->lParam);
|
|
if (lpMem32 == NULL)
|
|
goto Err;
|
|
|
|
cb = strlen( lpMem32 ) + 1;
|
|
if (!(lpwm32mpex->Parm16.WndProc.lParam = GlobalAllocLock16(GMEM_MOVEABLE | GMEM_SHARE | GMEM_ZEROINIT, cb, &hMem16 )))
|
|
goto Err;
|
|
putstr16((VPSZ)lpwm32mpex->Parm16.WndProc.lParam, lpMem32, cb);
|
|
LOW( lpwm32mpex->Parm16.WndProc.lParam ) = hMem16;
|
|
HIW( lpwm32mpex->Parm16.WndProc.lParam ) = 0; // must be zero
|
|
GlobalUnlock( (HANDLE)lpwm32mpex->lParam );
|
|
GlobalUnlock16( hMem16 );
|
|
}
|
|
/**** IR_STRINGEX ****/
|
|
else if ( lpwm32mpex->uParam == IR_STRINGEX ) {
|
|
LPSTRINGEXSTRUCT pss32;
|
|
PSTRINGEXSTRUCT16 pss16;
|
|
|
|
lpMem32 = GlobalLock((HANDLE)lpwm32mpex->lParam);
|
|
if (lpMem32 == NULL)
|
|
goto Err;
|
|
|
|
pss32 = (LPSTRINGEXSTRUCT)lpMem32;
|
|
|
|
cb = pss32->dwSize;
|
|
if ( cb >= ( 64 * K )) {
|
|
// It's problem !
|
|
LOGDEBUG(0,(" WOW:: WM_IME_REPORT:IR_STRINGEX data size must be less than 64K on WOW. cb = %d\n", cb ));
|
|
/** goto Err; **/
|
|
}
|
|
// Shuld I pack size of this structure ?
|
|
if (!(vp = GlobalAllocLock16(GMEM_MOVEABLE | GMEM_SHARE | GMEM_ZEROINIT, cb, &hMem16 )))
|
|
return FALSE;
|
|
|
|
GETVDMPTR(vp, cb, lpMem16 );
|
|
pss16 = (PSTRINGEXSTRUCT16)lpMem16;
|
|
|
|
STOREDWORD( pss16->dwSize, pss32->dwSize );
|
|
STOREWORD( pss16->uDeterminePos, pss32->uDeterminePos );
|
|
STOREWORD( pss16->uDetermineDelimPos, pss32->uDetermineDelimPos );
|
|
STOREWORD( pss16->uYomiPos, pss32->uYomiPos );
|
|
STOREWORD( pss16->uYomiDelimPos, pss32->uYomiDelimPos );
|
|
|
|
if ( pss32->uDeterminePos ) {
|
|
cb = strlen( (LPBYTE)&lpMem32[ pss32->uDeterminePos ] );
|
|
RtlCopyMemory( &lpMem16[ pss16->uDeterminePos ],
|
|
&lpMem32[ pss32->uDeterminePos ], cb + 1 );
|
|
if ( pss32->uDetermineDelimPos ) {
|
|
for ( i = 0; pss32->uDetermineDelimPos + i * sizeof(INT) < pss32->dwSize; i++ ) {
|
|
WORDOF16( lpMem16[ pss16->uDetermineDelimPos ], i ) = (WORD)
|
|
INTOF( lpMem32[ pss32->uDetermineDelimPos ], i );
|
|
if ( INTOF( lpMem32[ pss32->uDetermineDelimPos ], i ) >= cb )
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( pss32->uYomiPos ) {
|
|
cb = strlen( (LPBYTE)&lpMem32[ pss32->uYomiPos ] );
|
|
RtlCopyMemory( &lpMem16[ pss16->uYomiPos ],
|
|
&lpMem32[ pss32->uYomiPos ], cb + 1 );
|
|
if ( pss32->uYomiDelimPos ) {
|
|
for ( i = 0; pss32->uYomiDelimPos + i * sizeof(INT) < pss32->dwSize; i++ ) {
|
|
WORDOF16( lpMem16[ pss16->uYomiDelimPos ], i ) = (WORD)
|
|
INTOF( lpMem32[ pss32->uYomiDelimPos ], i );
|
|
if ( INTOF( lpMem32[ pss32->uYomiDelimPos ], i ) >= cb )
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
FLUSHVDMPTR(vp, cb, lpMem16);
|
|
FREEVDMPTR(lpMem16);
|
|
|
|
LOW( lpwm32mpex->Parm16.WndProc.lParam ) = hMem16;
|
|
HIW( lpwm32mpex->Parm16.WndProc.lParam ) = 0; // must be zero
|
|
GlobalUnlock( (HANDLE)lpwm32mpex->lParam );
|
|
GlobalUnlock16( hMem16 );
|
|
}
|
|
/**** IR_UNDETERMINE ****/
|
|
else if (lpwm32mpex->uParam == IR_UNDETERMINE) {
|
|
PUNDETERMINESTRUCT16 pus16;
|
|
LPUNDETERMINESTRUCT pus32;
|
|
|
|
lpMem32 = GlobalLock( (HANDLE)lpwm32mpex->lParam );
|
|
if (lpMem32 == NULL)
|
|
goto Err;
|
|
|
|
pus32 = (LPUNDETERMINESTRUCT)lpMem32;
|
|
cb = pus32->dwSize;
|
|
|
|
if ( cb >= ( 64 * K )) {
|
|
// It's problem !
|
|
LOGDEBUG(0,(" WOW:: WM_IME_REPORT:IR_UNDETERMINE data size must be less than 64K on WOW. cb = %d\n", cb ));
|
|
/** goto Err; **/
|
|
}
|
|
if (!( vp = GlobalAllocLock16(GMEM_MOVEABLE | GMEM_SHARE | GMEM_ZEROINIT, cb, &hMem16 )))
|
|
goto Err;
|
|
|
|
GETVDMPTR(vp, cb, lpMem16 );
|
|
pus16 = (PUNDETERMINESTRUCT16)lpMem16;
|
|
|
|
STOREDWORD( pus16->dwSize, (pus32)->dwSize );
|
|
STOREWORD( pus16->uDefIMESize, (pus32)->uDefIMESize );
|
|
STOREWORD( pus16->uDefIMEPos, (pus32)->uDefIMEPos );
|
|
STOREWORD( pus16->uUndetTextLen, (pus32)->uUndetTextLen );
|
|
STOREWORD( pus16->uUndetTextPos, (pus32)->uUndetTextPos );
|
|
STOREWORD( pus16->uUndetAttrPos, (pus32)->uUndetAttrPos );
|
|
STOREWORD( pus16->uCursorPos, (pus32)->uCursorPos );
|
|
STOREWORD( pus16->uDeltaStart, (pus32)->uDeltaStart );
|
|
STOREWORD( pus16->uDetermineTextLen, (pus32)->uDetermineTextLen );
|
|
STOREWORD( pus16->uDetermineTextPos, (pus32)->uDetermineTextPos );
|
|
STOREWORD( pus16->uDetermineDelimPos, (pus32)->uDetermineDelimPos );
|
|
STOREWORD( pus16->uYomiTextLen, (pus32)->uYomiTextLen );
|
|
STOREWORD( pus16->uYomiTextPos, (pus32)->uYomiTextPos );
|
|
STOREWORD( pus16->uYomiDelimPos, (pus32)->uYomiDelimPos );
|
|
|
|
|
|
// dada copy
|
|
RtlCopyMemory( &lpMem16[ sizeof(UNDETERMINESTRUCT) ],
|
|
&lpMem32[ sizeof(UNDETERMINESTRUCT) ],
|
|
cb - sizeof( UNDETERMINESTRUCT ));
|
|
|
|
//adjustment
|
|
if ( pus32->uDetermineDelimPos ) {
|
|
cb = pus32->uDetermineTextLen;
|
|
for ( i = 0; pus32->uDetermineDelimPos + i * sizeof(INT) < pus32->dwSize; i++ ) {
|
|
INTOF( lpMem16[ pus16->uDetermineDelimPos ], i ) = 0;
|
|
WORDOF16( lpMem16[ pus16->uDetermineDelimPos ], i ) = (WORD)
|
|
INTOF( lpMem32[ pus32->uDetermineDelimPos ], i );
|
|
if ( INTOF( lpMem32[ pus32->uDetermineDelimPos ], i ) >= cb )
|
|
break;
|
|
}
|
|
}
|
|
if ( pus32->uYomiDelimPos ) {
|
|
cb = pus32->uYomiTextLen;
|
|
for ( i = 0; pus32->uYomiDelimPos + i * sizeof(INT) < pus32->dwSize; i++ ) {
|
|
INTOF( lpMem16[ pus16->uYomiDelimPos ], i ) = 0;
|
|
WORDOF16( lpMem16[ pus16->uYomiDelimPos ], i ) = (WORD)
|
|
INTOF( lpMem32[ pus32->uYomiDelimPos ], i );
|
|
if ( INTOF( lpMem32[ pus32->uYomiDelimPos ], i ) >= cb )
|
|
break;
|
|
}
|
|
}
|
|
|
|
FLUSHVDMPTR(vp, cb, lpMem16);
|
|
FREEVDMPTR(lpMem16);
|
|
|
|
LOW( lpwm32mpex->Parm16.WndProc.lParam ) = hMem16;
|
|
HIW( lpwm32mpex->Parm16.WndProc.lParam ) = 0; // must be zero
|
|
GlobalUnlock( (HANDLE)lpwm32mpex->lParam );
|
|
GlobalUnlock16( hMem16 );
|
|
|
|
}
|
|
}
|
|
else { // fThunk
|
|
if (lpwm32mpex->Parm16.WndProc.lParam) {
|
|
GlobalUnlockFree16(GlobalLock16(LOW(lpwm32mpex->Parm16.WndProc.lParam), NULL));
|
|
}
|
|
}
|
|
return (TRUE);
|
|
|
|
Err:
|
|
if ( lpMem32 && lpwm32mpex->lParam )
|
|
GlobalUnlock( (HANDLE)lpwm32mpex->lParam );
|
|
return FALSE;
|
|
|
|
}
|
|
#endif // FE_IME
|