253 lines
6.1 KiB
C
253 lines
6.1 KiB
C
/*++
|
|
* 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;
|
|
}
|