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

701 lines
16 KiB
C

/*++
*
* Windows NT v5.0 WOW
*
* Copyright (c) 1997, Microsoft Corporation
*
* WIN95.C
*
* WOW32 Hand-coded (as opposed to interpreted) thunks for new-for-Win95
* exports.
*
* History:
* 16 Feb 97 Created davehart
--*/
#include "precomp.h"
#pragma hdrstop
MODNAME(win95.c);
ULONG FASTCALL WU32TileWindows(PVDMFRAME pFrame)
{
return W32TileOrCascadeWindows(pFrame, TileWindows);
}
ULONG FASTCALL WU32CascadeWindows(PVDMFRAME pFrame)
{
return W32TileOrCascadeWindows(pFrame, CascadeWindows);
}
ULONG FASTCALL W32TileOrCascadeWindows(PVDMFRAME pFrame, PFNTILECASCADEWINDOWS pfnWin32)
{
register PCASCADEWINDOWS16 parg16;
ULONG ul;
RECT rc;
PRECT prc;
HWND ahwnd[8];
DWORD chwnd;
HWND16 UNALIGNED *phwnd16;
HWND *phwnd;
GETARGPTR(pFrame, sizeof(*parg16), parg16);
chwnd = parg16->chwnd;
if (parg16->lpRect) {
GETRECT16(parg16->lpRect, &rc);
prc = &rc;
} else {
prc = NULL;
}
if (parg16->ahwnd) {
phwnd = STACKORHEAPALLOC( chwnd * sizeof(HWND), sizeof(ahwnd), ahwnd);
phwnd16 = VDMPTR(parg16->ahwnd, chwnd * sizeof(HWND16));
for (ul = 0; ul < chwnd; ul++) {
phwnd[ul] = HWND32(phwnd16[ul]);
}
FREEVDMPTR(phwnd16);
} else {
phwnd = NULL;
}
ul = (*pfnWin32)(
HWND32(parg16->hwndParent),
parg16->wFlags,
prc,
chwnd,
phwnd
);
//
// Memory movement may have occurred due to message activity,
// so throw away flat pointers to 16-bit memory.
//
FREEARGPTR(parg16);
if (phwnd) {
STACKORHEAPFREE(phwnd, ahwnd);
}
return ul;
}
ULONG FASTCALL WU32DrawAnimatedRects(PVDMFRAME pFrame)
{
register PDRAWANIMATEDRECTS16 parg16;
ULONG ul;
RECT rcFrom, rcTo;
GETARGPTR(pFrame, sizeof(*parg16), parg16);
GETRECT16(parg16->lprcStart, &rcFrom);
GETRECT16(parg16->lprcEnd, &rcTo);
ul = DrawAnimatedRects(
HWND32(parg16->hwndClip),
parg16->idAnimation,
&rcFrom,
&rcTo
);
FREEARGPTR(parg16);
return ul;
}
ULONG FASTCALL WU32DrawCaption(PVDMFRAME pFrame)
{
register PDRAWCAPTION16 parg16;
ULONG ul;
RECT rc;
GETARGPTR(pFrame, sizeof(*parg16), parg16);
GETRECT16(parg16->lprc, &rc);
ul = DrawCaption(
HWND32(parg16->hwnd),
HDC32(parg16->hdc),
&rc,
parg16->wFlags
);
FREEARGPTR(parg16);
return ul;
}
ULONG FASTCALL WU32DrawEdge(PVDMFRAME pFrame)
{
return W32DrawEdgeOrFrameControl(pFrame, DrawEdge);
}
ULONG FASTCALL WU32DrawFrameControl(PVDMFRAME pFrame)
{
return W32DrawEdgeOrFrameControl(pFrame, DrawFrameControl);
}
ULONG FASTCALL W32DrawEdgeOrFrameControl(PVDMFRAME pFrame, PFNDRAWEDGEFRAMECONTROL pfnWin32)
{
register PDRAWEDGE16 parg16;
ULONG ul;
RECT rc;
GETARGPTR(pFrame, sizeof(*parg16), parg16);
GETRECT16(parg16->lprc, &rc);
ul = (*pfnWin32)(
HDC32(parg16->hdc),
&rc,
parg16->wEdge,
parg16->wFlags
);
PUTRECT16(parg16->lprc, &rc);
FREEARGPTR(parg16);
return ul;
}
ULONG FASTCALL WU32DrawTextEx(PVDMFRAME pFrame)
{
register PDRAWTEXTEX16 parg16;
ULONG ul;
PSZ psz;
RECT rc;
DRAWTEXTPARAMS dtp, *pdtp;
PDRAWTEXTPARAMS16 pdtp16;
GETARGPTR(pFrame, sizeof(*parg16), parg16);
GETVARSTRPTR(parg16->lpchText, parg16->cchText, psz);
GETRECT16(parg16->lprc, &rc);
if ( (parg16->lpDTparams) &&
(pdtp16 = VDMPTR(parg16->lpDTparams, sizeof(DRAWTEXTPARAMS16))) ) {
pdtp = &dtp;
dtp.cbSize = sizeof(dtp);
dtp.iTabLength = pdtp16->iTabLength;
dtp.iLeftMargin = pdtp16->iLeftMargin;
dtp.iRightMargin = pdtp16->iRightMargin;
dtp.uiLengthDrawn = 0;
} else {
pdtp = NULL;
}
ul = DrawTextEx(
HDC32(parg16->hdc),
psz,
parg16->cchText,
&rc,
parg16->dwDTformat,
pdtp
);
if (pdtp) {
pdtp16->uiLengthDrawn = (WORD)dtp.uiLengthDrawn;
}
FREEVDMPTR(pdtp16);
FREEVDMPTR(psz);
FREEARGPTR(parg16);
return ul;
}
ULONG FASTCALL WU32GetIconInfo(PVDMFRAME pFrame)
{
register PGETICONINFO16 parg16;
ULONG ul;
ICONINFO ii;
PICONINFO16 pii16;
GETARGPTR(pFrame, sizeof(*parg16), parg16);
ul = GetIconInfo(
HICON32(parg16->hicon),
&ii
);
pii16 = VDMPTR(parg16->lpiconinfo, sizeof(*pii16));
pii16->fIcon = (BOOL16)ii.fIcon;
pii16->xHotspot = (INT16)ii.xHotspot;
pii16->yHotspot = (INT16)ii.yHotspot;
pii16->hbmMask = GETHBITMAP16(ii.hbmMask);
pii16->hbmColor = GETHBITMAP16(ii.hbmColor);
FREEVDMPTR(pii16);
FREEARGPTR(pFrame);
return ul;
}
ULONG FASTCALL WU32GetMenuItemInfo(PVDMFRAME pFrame)
{
register PGETMENUITEMINFO16 parg16;
ULONG ul;
MENUITEMINFO mii;
PMENUITEMINFO16 pmii16;
GETARGPTR(pFrame, sizeof(*parg16), parg16);
GETVDMPTR(parg16->lpmii, sizeof(*pmii16), pmii16);
mii.cbSize = sizeof(mii);
mii.fMask = pmii16->fMask;
FREEVDMPTR(pmii16);
ul = GetMenuItemInfo(
HMENU32(parg16->hmenu),
parg16->wIndex,
parg16->fByPosition,
&mii
);
putmenuiteminfo16(parg16->lpmii, &mii);
FREEARGPTR(pFrame);
return ul;
}
ULONG FASTCALL WU32InsertMenuItem(PVDMFRAME pFrame)
{
register PINSERTMENUITEM16 parg16;
ULONG ul;
MENUITEMINFO mii;
GETARGPTR(pFrame, sizeof(*parg16), parg16);
getmenuiteminfo16(parg16->lpmii, &mii);
ul = InsertMenuItem(
HMENU32(parg16->hmenu),
parg16->wIndex,
parg16->fByPosition,
&mii
);
FREEARGPTR(pFrame);
return ul;
}
ULONG FASTCALL WU32SetMenuItemInfo(PVDMFRAME pFrame)
{
register PSETMENUITEMINFO16 parg16;
ULONG ul;
MENUITEMINFO mii;
GETARGPTR(pFrame, sizeof(*parg16), parg16);
getmenuiteminfo16(parg16->lpmii, &mii);
ul = SetMenuItemInfo(
HMENU32(parg16->hmenu),
parg16->wIndex,
parg16->fByPosition,
&mii
);
FREEARGPTR(pFrame);
return ul;
}
ULONG FASTCALL WU32GetMenuItemRect(PVDMFRAME pFrame)
{
register PGETMENUITEMRECT16 parg16;
ULONG ul;
RECT rc;
GETARGPTR(pFrame, sizeof(*parg16), parg16);
ul = GetMenuItemRect(
HWND32(parg16->hwnd),
HMENU32(parg16->hmenu),
parg16->wIndex,
&rc
);
PUTRECT16(parg16->lprcScreen, &rc);
FREEARGPTR(pFrame);
return ul;
}
ULONG FASTCALL WU32TrackPopupMenuEx(PVDMFRAME pFrame)
{
register PTRACKPOPUPMENUEX16 parg16;
ULONG ul;
TPMPARAMS tpmp;
LPTPMPARAMS lptpmp;
VPRECT16 vprcExclude;
GETARGPTR(pFrame, sizeof(*parg16), parg16);
if (parg16->lpTpm) {
lptpmp = &tpmp;
tpmp.cbSize = sizeof(tpmp);
vprcExclude = parg16->lpTpm + offsetof(TPMPARAMS16, rcExclude);
GETRECT16(vprcExclude, &tpmp.rcExclude);
} else {
lptpmp = NULL;
}
ul = TrackPopupMenuEx(
HMENU32(parg16->hmenu),
parg16->wFlags,
parg16->x,
parg16->y,
HWND32(parg16->hwndOwner),
lptpmp
);
FREEARGPTR(pFrame);
return ul;
}
ULONG FASTCALL WG32GetCharacterPlacement(PVDMFRAME pFrame)
{
register PGETCHARACTERPLACEMENT16 parg16;
ULONG ul;
PSZ pszText;
PGCP_RESULTS16 pgcp16;
GCP_RESULTS gcp;
//
// Thankfully on Win95 the 16-bit GCP_RESULTS structure
// points to 32-bit ints, so the structure thunking
// is trivial.
//
GETARGPTR(pFrame, sizeof(*parg16), parg16);
GETPSZPTR(parg16->lpszText, pszText);
GETVDMPTR(parg16->lpResults, sizeof(*pgcp16), pgcp16);
gcp.lStructSize = sizeof gcp;
gcp.nGlyphs = pgcp16->nGlyphs;
gcp.nMaxFit = pgcp16->nMaxFit;
GETOPTPTR(pgcp16->lpOutString, 1, gcp.lpOutString);
GETOPTPTR(pgcp16->lpOrder, 4, gcp.lpOrder);
GETOPTPTR(pgcp16->lpDx, 4, gcp.lpDx);
GETOPTPTR(pgcp16->lpCaretPos, 4, gcp.lpCaretPos);
GETOPTPTR(pgcp16->lpClass, 1, gcp.lpClass);
GETOPTPTR(pgcp16->lpGlyphs, 4, gcp.lpGlyphs);
ul = GetCharacterPlacement(
HDC32(parg16->hdc),
pszText,
parg16->wCount,
parg16->wMaxExtent,
&gcp,
parg16->dwFlags
);
pgcp16->nGlyphs = (SHORT)gcp.nGlyphs;
pgcp16->nMaxFit = (SHORT)gcp.nMaxFit;
FREEARGPTR(pFrame);
return ul;
}
//
// On Win95, GetProductName returns "Windows 95".
// We'll return "Windows NT" unless something forces us
// to be identical.
//
// Two flavors: call with cbBuffer == 0 and it returns
// the length required minus 1 (a bug I think). Call with
// cbBuffer > 0 and it copies as much as possible and returns
// lpBuffer.
//
ULONG FASTCALL WK32GetProductName(PVDMFRAME pFrame)
{
register PGETPRODUCTNAME16 parg16;
ULONG ul;
PSZ pszBuffer;
static char szProductName[] = "Windows NT";
GETARGPTR(pFrame, sizeof(*parg16), parg16);
if (0 == parg16->cbBuffer) {
ul = (sizeof szProductName) - 1;
} else {
GETVDMPTR(parg16->lpBuffer, parg16->cbBuffer, pszBuffer);
WOW32VERIFY(pszBuffer == lstrcpyn(pszBuffer, szProductName, parg16->cbBuffer));
FREEVDMPTR(pszBuffer);
ul = parg16->lpBuffer;
}
FREEARGPTR(pFrame);
return ul;
}
typedef struct _tagWOWDRAWSTATECALLBACK {
VPVOID vpfnCallback;
LPARAM lparamUser;
} WOWDRAWSTATECALLBACK, *PWOWDRAWSTATECALLBACK;
BOOL CALLBACK WOWDrawStateCallback(HDC hdc, LPARAM lData, WPARAM wData, int cx, int cy)
{
PWOWDRAWSTATECALLBACK pwds = (PWOWDRAWSTATECALLBACK) lData;
ULONG ul;
WORD awCallbackArgs[6];
awCallbackArgs[0] = (WORD)(SHORT)cy;
awCallbackArgs[1] = (WORD)(SHORT)cx;
awCallbackArgs[2] = (WORD)wData;
awCallbackArgs[3] = LOWORD(pwds->lparamUser);
awCallbackArgs[4] = HIWORD(pwds->lparamUser);
awCallbackArgs[5] = GETHDC16(hdc);
WOWCallback16Ex(
pwds->vpfnCallback,
WCB16_PASCAL,
sizeof awCallbackArgs,
awCallbackArgs,
&ul // retcode filled into ul
);
return LOWORD(ul);
}
ULONG FASTCALL WU32DrawState(PVDMFRAME pFrame)
{
register PDRAWSTATE16 parg16;
ULONG ul;
WOWDRAWSTATECALLBACK wds;
DRAWSTATEPROC pDrawStateCallback = NULL;
LPARAM lData;
HBRUSH hbr;
GETARGPTR(pFrame, sizeof(*parg16), parg16);
switch (parg16->uFlags & DST_TYPEMASK) {
case DST_COMPLEX:
if (parg16->pfnCallBack) {
wds.vpfnCallback = parg16->pfnCallBack;
wds.lparamUser = parg16->lData;
lData = (LPARAM) &wds;
pDrawStateCallback = (DRAWSTATEPROC) WOWDrawStateCallback;
}
break;
case DST_TEXT:
case DST_PREFIXTEXT:
lData = (LPARAM) VDMPTR(parg16->lData, parg16->wData);
break;
case DST_ICON:
lData = (LPARAM) HICON32( (WORD) parg16->lData );
break;
case DST_BITMAP:
lData = (LPARAM) HBITMAP32(parg16->lData);
break;
default:
WOW32WARNMSGF(FALSE, ("WOW32: Unknown DST_ code to DrawState %x.\n",
parg16->uFlags & DST_TYPEMASK));
}
hbr = (parg16->uFlags & DSS_MONO)
? HBRUSH32(parg16->hbrFore)
: NULL;
ul = GETBOOL16(DrawState(
HDC32(parg16->hdcDraw),
hbr,
pDrawStateCallback,
lData,
parg16->wData,
parg16->x,
parg16->y,
parg16->cx,
parg16->cy,
parg16->uFlags
));
FREEARGPTR(pFrame);
return ul;
}
ULONG FASTCALL WU32GetAppVer(PVDMFRAME pFrame)
{
return ((PTDB)SEGPTR(pFrame->wTDB,0))->TDB_ExpWinVer;
}
ULONG FASTCALL WU32CopyImage(PVDMFRAME pFrame)
{
register PCOPYIMAGE16 parg16;
ULONG ul;
BOOL fIconCursor; // as opposed to bitmap
GETARGPTR(pFrame, sizeof(*parg16), parg16);
//
// NOTE first parameter to Win16 CopyImage is hinstOwner,
// which isn't a parameter to Win32 CopyImage. It may
// be that we'll need to special-case LR_COPYFROMRESOURCE
// to work correctly.
//
fIconCursor = (parg16->wType != IMAGE_BITMAP);
ul = (ULONG) CopyImage(
(fIconCursor)
? HICON32(parg16->hImage)
: HBITMAP32(parg16->hImage),
parg16->wType,
parg16->cxNew,
parg16->cyNew,
parg16->wFlags
);
ul = (fIconCursor)
? GETHICON16(ul)
: GETHBITMAP16(ul);
return ul;
}
//
// WowMsgBoxIndirectCallback is called by User32 when a 16-bit app
// calls MessageBoxIndirect and specifies a help callback proc.
// User32 passes the 16:16 callback address to us along with a
// flat pointer to the HELPINFO structure to pass to the callback.
//
VOID FASTCALL WowMsgBoxIndirectCallback(DWORD vpfnCallback, LPHELPINFO lpHelpInfo)
{
VPVOID vpHelpInfo16;
LPHELPINFO lpHelpInfo16;
//
// As best as I can tell Win95 passes the WIN32 HELPINFO struct back to the
// 16-bit callback proc (i.e. there is no HELPINFO16).
//
// be sure allocation size matches stackfree16() size below
vpHelpInfo16 = stackalloc16( sizeof(*lpHelpInfo16) );
GETVDMPTR(vpHelpInfo16, sizeof(*lpHelpInfo16), lpHelpInfo16);
RtlCopyMemory(lpHelpInfo16, lpHelpInfo, sizeof(*lpHelpInfo16));
FREEVDMPTR(lpHelpInfo16);
WOWCallback16(
vpfnCallback,
vpHelpInfo16
);
if(vpHelpInfo16) {
stackfree16(vpHelpInfo16, sizeof(*lpHelpInfo16));
}
}
ULONG FASTCALL WU32MessageBoxIndirect(PVDMFRAME pFrame)
{
register PMESSAGEBOXINDIRECT16 parg16;
ULONG ul;
PMSGBOXPARAMS16 pmbp16;
MSGBOXPARAMS mbp;
GETARGPTR(pFrame, sizeof(*parg16), parg16);
GETVDMPTR(parg16->lpmbp, sizeof *pmbp16, pmbp16);
mbp.cbSize = sizeof mbp;
mbp.hwndOwner = HWND32(pmbp16->hwndOwner);
mbp.hInstance = HINSTRES32(pmbp16->hInstance);
GETPSZIDPTR(pmbp16->lpszText, mbp.lpszText);
GETPSZIDPTR(pmbp16->lpszCaption, mbp.lpszCaption);
mbp.dwStyle = pmbp16->dwStyle;
GETPSZIDPTR(pmbp16->lpszIcon, mbp.lpszIcon);
mbp.dwContextHelpId = pmbp16->dwContextHelpId;
if (pmbp16->vpfnMsgBoxCallback) {
MarkWOWProc(pmbp16->vpfnMsgBoxCallback, mbp.lpfnMsgBoxCallback)
} else {
mbp.lpfnMsgBoxCallback = 0;
}
mbp.dwLanguageId = pmbp16->dwLanguageId;
ul = GETINT16( MessageBoxIndirect(&mbp) );
FREEARGPTR(pFrame);
return ul;
}
//
// was in wow.it: HGDI CreateEnhMetaFile(HGDI, PTR, PTR, PTR);
// Using real thunk to ensure Win32 curdir matches Win16.
//
ULONG FASTCALL WG32CreateEnhMetaFile(PVDMFRAME pFrame)
{
register PCREATEENHMETAFILE16 parg16;
ULONG ul;
LPCSTR lpszFile, lpszDescription;
CONST RECT *prclFrame;
GETARGPTR(pFrame, sizeof(*parg16), parg16);
GETVDMPTR(parg16->lpszFile, 1, lpszFile);
// note lpszDescription is really two SZs with extra terminator
GETVDMPTR(parg16->lpszDescription, 3, lpszDescription);
// note lprclFrame is a LPRECTL, a Win32 RECT
GETVDMPTR(parg16->lprclFrame, sizeof(*prclFrame), prclFrame);
//
// Make sure the Win32 current directory matches this task's.
//
UpdateDosCurrentDirectory(DIR_DOS_TO_NT);
ul = GETHDC16(CreateEnhMetaFile(
HDC32(parg16->hdcRef),
lpszFile,
prclFrame,
lpszDescription
));
FREEVDMPTR(prclFrame);
FREEVDMPTR(lpszDescription);
FREEVDMPTR(lpszFile);
return ul;
}