windows-nt/Source/XPSP1/NT/base/mvdm/wow32/intthunk.c

253 lines
6.1 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
* intthunk.c
*
* WOW v5.0
*
* Copyright 1996, Microsoft Corporation. All Rights Reserved.
*
* WOW32.C
* WOW32 16-bit API support
*
* History:
* Created 7-Dec-96 DaveHart
*
--*/
#include "precomp.h"
#pragma hdrstop
#include "wowit.h"
MODNAME(intthunk.c);
extern DWORD WK32ICallProc32MakeCall(DWORD pfn, DWORD cbArgs, VOID *pArgs);
//
// On x86 we don't bother aligning pointers to DWORDs
// passed to APIs. Perhaps we shouldn't for Alpha?
//
#ifdef _X86_
#define ALIGNDWORDS 0
#else
#define ALIGNDWORDS 1
#endif
ULONG FASTCALL InterpretThunk(PVDMFRAME pFrame, DWORD dwIntThunkID)
{
PINT_THUNK_TABLEENTRY pit = &IntThunkTable[ dwIntThunkID ];
CONST BYTE * pbInstr = pit->pbInstr;
DWORD dwArgs32[MAX_IT_ARGS];
PDWORD pdwArg32 = dwArgs32;
#if ALIGNDWORDS
BOOL fAlignedUsed = FALSE;
DWORD adwAligned[MAX_IT_ARGS];
PDWORD pdwAligned = adwAligned;
DWORD avpAligned[MAX_IT_ARGS];
PDWORD pvpAligned = avpAligned;
#endif
WORD UNALIGNED *pwArg16 = (WORD UNALIGNED *) ((PBYTE)&pFrame->bArgs + pFrame->cbArgs - 2);
DWORD dwReturn;
DWORD dw;
WOW32ASSERTMSGF(dwIntThunkID <= ITID_MAX,
("WOW32 InterpretThunk error ID %d out of range (%d max).\n",
dwIntThunkID, ITID_MAX));
while ( ! (*pbInstr & IT_RETMASK)) {
switch (*pbInstr) {
case IT_WORD:
*pdwArg32 = *pwArg16;
break;
case IT_INT:
*pdwArg32 = INT32(*pwArg16);
break;
case IT_DWORD:
*pdwArg32 = *(DWORD UNALIGNED *) --pwArg16;
break;
case IT_LPDWORD:
#if ALIGNDWORDS
if (! fAlignedUsed) {
fAlignedUsed = TRUE;
RtlZeroMemory(avpAligned, sizeof avpAligned);
}
*pvpAligned = *(DWORD UNALIGNED *) --pwArg16;
if (*pvpAligned) {
*pdwArg32 = (DWORD) pdwAligned;
*pdwAligned = *(DWORD UNALIGNED *) GetPModeVDMPointer(*pvpAligned, 4);
} else {
*pdwArg32 = 0;
}
break;
#else
//
// If we aren't aligning DWORDs use the generic
// pointer code.
//
/* FALL THROUGH TO IT_PTR */
#endif
case IT_PTR:
dw = *(DWORD UNALIGNED *) --pwArg16;
do_IT_PTR_with_dw:
*pdwArg32 = (DWORD) GetPModeVDMPointer(dw, 0);
break;
case IT_PTRORATOM:
dw = *(DWORD UNALIGNED *) --pwArg16;
if (HIWORD(dw)) {
goto do_IT_PTR_with_dw;
}
*pdwArg32 = dw; // atom
break;
case IT_HGDI:
*pdwArg32 = (DWORD) GDI32( (HAND16) *pwArg16 );
break;
case IT_HUSER:
*pdwArg32 = (DWORD) USER32( (HAND16) *pwArg16 );
break;
case IT_COLOR:
dw = *(DWORD UNALIGNED *) --pwArg16;
*pdwArg32 = COLOR32(dw);
break;
case IT_HINST:
*pdwArg32 = (DWORD) HINSTRES32( (HAND16) *pwArg16 );
break;
case IT_HICON:
*pdwArg32 = (DWORD) HICON32( (HAND16) *pwArg16 );
break;
case IT_HCURS:
*pdwArg32 = (DWORD) HCURSOR32( (HAND16) *pwArg16 );
break;
case IT_16ONLY:
//
// This is for params that appear on 16-bit side but not 32-bit side,
// for example the hinstOwner passed to CopyImage in Win16 but not in Win32.
//
pdwArg32--;
break;
case IT_32ONLY:
//
// This is for params that appear on 32-bit side but not 16-bit side,
// we pass zero for the 32-bit argument.
//
*pdwArg32 = 0;
pwArg16++;
break;
default:
WOW32ASSERTMSGF(FALSE, ("WOW32 InterpretThunk error unknown opcode 0x%x.\n", *pbInstr));
}
pwArg16--;
pdwArg32++;
pbInstr++;
#if ALIGNDWORDS
pdwAligned++;
pvpAligned++;
#endif
WOW32ASSERT((pbInstr - pit->pbInstr) <= (MAX_IT_ARGS + 1));
}
//
// Call API
//
dwReturn = WK32ICallProc32MakeCall(
(DWORD) pit->pfnAPI,
(PBYTE) pdwArg32 - (PBYTE) dwArgs32,
dwArgs32
);
#ifdef DEBUG
pFrame = NULL; // Memory movement may have occurred.
#endif
//
// If we passed aligned DWORD pointers, copy the values back.
//
#if ALIGNDWORDS
if (fAlignedUsed) {
pdwAligned = adwAligned;
pvpAligned = avpAligned;
while (pvpAligned < (PDWORD)((PBYTE)avpAligned + sizeof avpAligned)) {
if (*pvpAligned) {
*(DWORD UNALIGNED *) GetPModeVDMPointer(*pvpAligned, 4) = *pdwAligned;
}
pdwAligned++;
pvpAligned++;
}
}
#endif
//
// Thunk return value using last instruction opcode
//
WOW32ASSERT(*pbInstr & IT_RETMASK);
switch (*pbInstr) {
case IT_DWORDRET:
// dwReturn is correct
break;
case IT_WORDRET:
dwReturn = GETWORD16(dwReturn);
break;
case IT_INTRET:
dwReturn = (DWORD) GETINT16(dwReturn);
break;
case IT_HGDIRET:
dwReturn = GDI16( (HAND32) dwReturn );
break;
case IT_HUSERRET:
dwReturn = USER16( (HAND32) dwReturn );
break;
case IT_ZERORET:
dwReturn = 0;
break;
case IT_HICONRET:
dwReturn = GETHICON16( (HAND32) dwReturn );
break;
case IT_HCURSRET:
dwReturn = GETHCURSOR16( (HAND32) dwReturn );
break;
case IT_ONERET:
dwReturn = 1;
break;
case IT_HPRNDWPRET:
dwReturn = GetPrn16( (HAND32) dwReturn );
break;
default:
WOW32ASSERTMSGF(FALSE, ("WOW32 InterpretThunk error unknown return opcode 0x%x.\n", *pbInstr));
}
return dwReturn;
}