windows-nt/Source/XPSP1/NT/base/mvdm/wow32/wmdisp32.c
2020-09-26 16:20:57 +08:00

3517 lines
105 KiB
C

/*++
*
* 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)
DWORD 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(0L);
#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(0L);
}
#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)
DWORD 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(0L);
#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(0L);
}
#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)
{
if (lpwm32mpex->fThunk) {
lpwm32mpex->Parm16.WndProc.wParam = GETHDC16(lpwm32mpex->uParam);
}
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
//
BOOL FASTCALL WM32NCPaint(LPWM32MSGPARAMEX lpwm32mpex)
{
if (lpwm32mpex->fThunk) {
lpwm32mpex->Parm16.WndProc.wParam = (lpwm32mpex->uParam == 1) ? 1 :
GETHDC16(lpwm32mpex->uParam);
}
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)
{
LPDRAWITEMSTRUCT lParam = (LPDRAWITEMSTRUCT) lpwm32mpex->lParam;
if (lpwm32mpex->fThunk) {
if (lParam) {
// be sure allocation size matches stackfree16() size below
lpwm32mpex->Parm16.WndProc.lParam = stackalloc16(sizeof(DRAWITEMSTRUCT16));
putdrawitem16(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(DRAWITEMSTRUCT16));
}
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)
{
if (lpwm32mpex->fThunk) {
lpwm32mpex->Parm16.WndProc.wParam = GETHFONT16(lpwm32mpex->uParam);
}
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;
if (lpwm32mpex->fThunk) {
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 {
putpaintstruct16(vp, (LPPAINTSTRUCT) lp);
}
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 {
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_DDEREQUEST
// WM_DDETERMINATE
// WM_DDEUNADVISE
//
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)
{
if (lpwm32mpex->fThunk) {
lpwm32mpex->Parm16.WndProc.wMsg = WM_CTLCOLOR;
if(lpwm32mpex->uMsg != WM_CTLCOLOR) { // see 16-bit thunk for this special case
lpwm32mpex->Parm16.WndProc.wParam = GETHDC16(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);
}
}
return (TRUE);
}
// This function thunks the messages,
//
// WM_GETFONT
//
BOOL FASTCALL WM32GetFont(LPWM32MSGPARAMEX lpwm32mpex)
{
if (!lpwm32mpex->fThunk) {
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)
{
if (lpwm32mpex->fThunk) {
return (BOOL)(lpwm32mpex->Parm16.WndProc.wParam = GETHDC16(lpwm32mpex->uParam));
}
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;
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