From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/mvdm/wow32/wcall16.c | 819 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 819 insertions(+) create mode 100644 private/mvdm/wow32/wcall16.c (limited to 'private/mvdm/wow32/wcall16.c') diff --git a/private/mvdm/wow32/wcall16.c b/private/mvdm/wow32/wcall16.c new file mode 100644 index 000000000..c90570007 --- /dev/null +++ b/private/mvdm/wow32/wcall16.c @@ -0,0 +1,819 @@ +/*++ + * + * WOW v1.0 + * + * Copyright (c) 1991, Microsoft Corporation + * + * WCALL16.C + * WOW32 16-bit message/callback support + * + * History: + * Created 11-Mar-1991 by Jeff Parsons (jeffpar) + * Changed 18-Aug-1992 by Mike Tricker (MikeTri) Added DOS PDB and SFT functions +--*/ + + +#include "precomp.h" +#pragma hdrstop + + +MODNAME(wcall16.c); + +#define WOWFASTEDIT + +#ifdef WOWFASTEDIT + +typedef struct _LOCALHANDLEENTRY { + WORD lhe_address; // actual address of object + BYTE lhe_flags; // flags and priority level + BYTE lhe_count; // lock count +} LOCALHANDLEENTRY, *PLOCALHANDLEENTRY; + +#define LA_MOVEABLE 0x0002 // moveable or fixed? + +#define LHE_DISCARDED 0x0040 // Marks objects that have been discarded. + +#endif + +/* Common callback functions + */ +HANDLE LocalAlloc16(WORD wFlags, INT cb, HANDLE hInstance) +{ + PARM16 Parm16; + VPVOID vp = 0; + + if (LOWORD(hInstance) == 0 ) { /* if lo word == 0, then this is a 32-bit + hInstance, which makes no sense */ + WOW32ASSERT(LOWORD(hInstance)); + return (HANDLE)0; + } + + if (cb < 0 || cb > 0xFFFF) { + WOW32ASSERT(cb > 0 && cb <= 0xFFFF); + return (HANDLE)0; + } + + Parm16.WndProc.wMsg = LOWORD(hInstance) | 1; + + Parm16.WndProc.wParam = wFlags; + Parm16.WndProc.lParam = cb; + CallBack16(RET_LOCALALLOC, &Parm16, 0, &vp); + + if (LOWORD(vp) == 0) + vp = 0; + + return (HANDLE)vp; +} + + +HANDLE LocalReAlloc16(HANDLE hMem, INT cb, WORD wFlags) +{ + PARM16 Parm16; + VPVOID vp = 0; + + if (HIWORD(hMem) == 0 || cb < 0 || cb > 0xFFFF) { + WOW32ASSERT(HIWORD(hMem) && cb >= 0 && cb <= 0xFFFF); + return (HANDLE)0; + } + + LOGDEBUG(4,("LocalRealloc DS = %x, hMem = %x, bytes = %x, flags = %x\n",HIWORD(hMem),LOWORD(hMem),cb,wFlags)); + Parm16.WndProc.lParam = (LONG)hMem; + Parm16.WndProc.wParam = wFlags; + Parm16.WndProc.wMsg = (WORD)cb; + CallBack16(RET_LOCALREALLOC, &Parm16, 0, &vp); + + if (LOWORD(vp) == 0) + vp = 0; + + return (HANDLE)vp; +} + +#ifndef WOWFASTEDIT + +VPVOID LocalLock16(HANDLE hMem) +{ + PARM16 Parm16; + VPVOID vp = 0; + + if (HIWORD(hMem) == 0) { + WOW32ASSERT(HIWORD(hMem) != 0); + return (VPVOID)0; + } + + Parm16.WndProc.lParam = (LONG)hMem; + CallBack16(RET_LOCALLOCK, &Parm16, 0, &vp); + + return vp; +} + +BOOL LocalUnlock16(HANDLE hMem) +{ + PARM16 Parm16; + VPVOID vp = FALSE; + + if (HIWORD(hMem) == 0) { + WOW32ASSERT(HIWORD(hMem)); + return FALSE; + } + + Parm16.WndProc.lParam = (LONG)hMem; + CallBack16(RET_LOCALUNLOCK, &Parm16, 0, &vp); + + return (BOOL)vp; +} + +#else + +VPVOID LocalLock16(HANDLE hMem) +{ + WORD h16; + LONG retval; + + if (HIWORD(hMem) == 0) { + WOW32ASSERT(HIWORD(hMem) != 0); + return (VPVOID)0; + } + + h16 = LOWORD(hMem); + retval = (VPVOID)hMem; + + if (h16 & LA_MOVEABLE) { + PLOCALHANDLEENTRY plhe; + + GETVDMPTR(hMem, sizeof(*plhe), plhe); + + if (plhe->lhe_flags & LHE_DISCARDED) { + goto LOCK1; + } + + plhe->lhe_count++; + if (!plhe->lhe_count) + plhe->lhe_count--; + +LOCK1: + LOW(retval) = plhe->lhe_address; + FLUSHVDMPTR((ULONG)hMem, sizeof(*plhe), plhe); + FREEVDMPTR(plhe); + } + + if (LOWORD(retval) == 0) + retval = 0; + + return retval; +} + +BOOL LocalUnlock16(HANDLE hMem) +{ + WORD h16; + BOOL rc; + PLOCALHANDLEENTRY plhe; + BYTE count; + + if (HIWORD(hMem) == 0) { + WOW32ASSERT(HIWORD(hMem)); + return FALSE; + } + + rc = FALSE; + h16 = LOWORD(hMem); + + if (!(h16 & LA_MOVEABLE)) { + goto UNLOCK2; + } + + GETVDMPTR(hMem, sizeof(*plhe), plhe); + + if (plhe->lhe_flags & LHE_DISCARDED) + goto UNLOCK1; + + count = plhe->lhe_count; + count--; + + if (count >= (BYTE)(0xff-1)) + goto UNLOCK1; + + plhe->lhe_count = count; + rc = (BOOL)((SHORT)count); + + FLUSHVDMPTR((ULONG)hMem, sizeof(*plhe), plhe); + +UNLOCK1: + FREEVDMPTR(plhe); + +UNLOCK2: + return rc; +} + +#endif // WOWFASTEDIT + + +WORD LocalSize16(HANDLE hMem) +{ + PARM16 Parm16; + VPVOID vp = 0; + + if (HIWORD(hMem) == 0) { + WOW32ASSERT(HIWORD(hMem)); + return FALSE; + } + + Parm16.WndProc.lParam = (LONG)hMem; + CallBack16(RET_LOCALSIZE, &Parm16, 0, &vp); + + return (WORD)vp; +} + + +HANDLE LocalFree16(HANDLE hMem) +{ + PARM16 Parm16; + VPVOID vp = FALSE; + + if (HIWORD(hMem) == 0) { + WOW32ASSERT(HIWORD(hMem)); + return (HANDLE)0; + } + + Parm16.WndProc.lParam = (LONG)hMem; + CallBack16(RET_LOCALFREE, &Parm16, 0, &vp); + + if (LOWORD(vp) == 0) { + vp = 0; + } else { + WOW32ASSERT(LOWORD(vp) == LOWORD(hMem)); + vp = (VPVOID)hMem; + } + + return (HANDLE)vp; +} + + +BOOL LockSegment16(WORD wSeg) +{ + PARM16 Parm16; + VPVOID vp = FALSE; + + Parm16.WndProc.wParam = wSeg; + CallBack16(RET_LOCKSEGMENT, &Parm16, 0, &vp); + + return (BOOL)vp; +} + + +BOOL UnlockSegment16(WORD wSeg) +{ + PARM16 Parm16; + VPVOID vp = FALSE; + + Parm16.WndProc.wParam = wSeg; + CallBack16(RET_UNLOCKSEGMENT, &Parm16, 0, &vp); + + return (BOOL)vp; +} + + +VPVOID WOWGlobalAllocLock16(WORD wFlags, DWORD cb, HMEM16 *phMem) +{ + PARM16 Parm16; + VPVOID vp = 0; + + Parm16.WndProc.wParam = wFlags; + Parm16.WndProc.lParam = cb; + CallBack16(RET_GLOBALALLOCLOCK, &Parm16, 0, &vp); + + if (vp) { + + // Get handle of 16-bit object + if (phMem) { + PCBVDMFRAME pCBFrame; + + pCBFrame = CBFRAMEPTR(CURRENTPTD()->vpCBStack); + *phMem = pCBFrame->wGenUse1; + FREEVDMPTR(pCBFrame); + } + } + return vp; +} + + +HMEM16 WOWGlobalAlloc16(WORD wFlags, DWORD cb) +{ + HMEM16 hMem; + VPVOID vp; + + if (vp = WOWGlobalAllocLock16(wFlags, cb, &hMem)) { + WOWGlobalUnlock16(hMem); + } else { + hMem = 0; + } + + return hMem; +} + + +VPVOID WOWGlobalLockSize16(HMEM16 hMem, PDWORD pcb) +{ + PARM16 Parm16; + VPVOID vp = 0; + PCBVDMFRAME pCBFrame; + + Parm16.WndProc.wParam = hMem; + CallBack16(RET_GLOBALLOCK, &Parm16, 0, &vp); + + // Get size of 16-bit object (will be 0 if lock failed) + if (pcb) { + pCBFrame = CBFRAMEPTR(CURRENTPTD()->vpCBStack); + *pcb = pCBFrame->wGenUse2 | (LONG)pCBFrame->wGenUse1 << 16; + FREEVDMPTR(pCBFrame); + } + + return vp; +} + + +VPVOID WOWGlobalLock16(HMEM16 hMem) +{ + return WOWGlobalLockSize16(hMem, NULL); +} + + +BOOL WOWGlobalUnlock16(HMEM16 hMem) +{ + PARM16 Parm16; + VPVOID vp = FALSE; + + Parm16.WndProc.wParam = hMem; + CallBack16(RET_GLOBALUNLOCK, &Parm16, 0, &vp); + + return (BOOL)vp; +} + + +HMEM16 WOWGlobalUnlockFree16(VPVOID vpMem) +{ + PARM16 Parm16; + VPVOID vp = FALSE; + + Parm16.WndProc.lParam = vpMem; + CallBack16(RET_GLOBALUNLOCKFREE, &Parm16, 0, &vp); + + return (HMEM16)vp; +} + + +HMEM16 WOWGlobalFree16(HMEM16 hMem) +{ + VPVOID vp; + + if (vp = WOWGlobalLock16(hMem)) { + hMem = WOWGlobalUnlockFree16(vp); + } else { + // On failure we return the passed-in handle, + // so there's nothing to do. + } + + return hMem; +} + + +HAND16 GetExePtr16( HAND16 hInst ) +{ + PARM16 Parm16; + ULONG ul; + PTD ptd; + INT i; + + if (hInst == 0) return (HAND16)0; + + // + // see if this is the hInst for the current task + // + + ptd = CURRENTPTD(); + + if (hInst == ptd->hInst16) { + return ptd->hMod16; + } + + // + // check the cache + // + + for (i = 0; i < CHMODCACHE; i++) { + if (ghModCache[i].hInst16 == hInst) + return ghModCache[i].hMod16; + } + + /* + ** Function returns a hModule, given an hInstance + */ + Parm16.WndProc.wParam = hInst; + CallBack16(RET_GETEXEPTR, &Parm16, 0, &ul); + + + // + // update the cache + // slide everybody down 1 entry, put this new guy at the top + // + + RtlMoveMemory(ghModCache+1, ghModCache, sizeof(HMODCACHE)*(CHMODCACHE-1)); + ghModCache[0].hInst16 = hInst; + ghModCache[0].hMod16 = (HAND16)LOWORD(ul); + + return (HAND16)LOWORD(ul); +} + + +WORD GetModuleFileName16( HAND16 hInst, VPVOID lpszModuleName, WORD cchModuleName ) +{ + PARM16 Parm16; + ULONG ul; + + + if (hInst == 0) return 0; + + Parm16.WndProc.wParam = hInst; + Parm16.WndProc.lParam = lpszModuleName; + Parm16.WndProc.wMsg = cchModuleName; + CallBack16(RET_GETMODULEFILENAME, &Parm16, 0, &ul ); + + return( LOWORD(ul) ); +} + + +ULONG GetDosPDB16(VOID) +{ + PARM16 Parm16; + DWORD dwReturn = 0; + + CallBack16(RET_GETDOSPDB, &Parm16, 0, &dwReturn); + + return (ULONG)dwReturn; +} + + +ULONG GetDosSFT16(VOID) +{ + PARM16 Parm16; + DWORD dwReturn = 0; + + CallBack16(RET_GETDOSSFT, &Parm16, 0, &dwReturn); + + return (ULONG)dwReturn; +} + +// Given a data selector change it into a code selector + +WORD ChangeSelector16(WORD wSeg) +{ + PARM16 Parm16; + VPVOID vp = FALSE; + + Parm16.WndProc.wParam = wSeg; + CallBack16(RET_CHANGESELECTOR, &Parm16, 0, &vp); + + return LOWORD(vp); +} + +VPVOID RealLockResource16(HMEM16 hMem, PINT pcb) +{ + PARM16 Parm16; + VPVOID vp = 0; + PCBVDMFRAME pCBFrame; + + Parm16.WndProc.wParam = hMem; + CallBack16(RET_LOCKRESOURCE, &Parm16, 0, &vp); + + // Get size of 16-bit object (will be 0 if lock failed) + if (pcb) { + pCBFrame = CBFRAMEPTR(CURRENTPTD()->vpCBStack); + *pcb = pCBFrame->wGenUse2 | (LONG)pCBFrame->wGenUse1 << 16; + FREEVDMPTR(pCBFrame); + } + + return vp; +} + + +DWORD WOWCallback16(DWORD vpFn, DWORD dwParam) +{ + PARM16 Parm16; + VPVOID vp; + + // + // Copy DWORD parameter to PARM16 structure. + // + + RtlCopyMemory(&Parm16.WOWCallback16.wArgs, &dwParam, sizeof(dwParam)); + + // + // Use semi-slimy method to pass argument size to CallBack16. + // + + vp = (VPVOID) sizeof(dwParam); + + CallBack16(RET_WOWCALLBACK16, &Parm16, (VPPROC)vpFn, &vp); + + return (DWORD)vp; +} + + +BOOL WOWCallback16Ex( + DWORD vpFn, + DWORD dwFlags, + DWORD cbArgs, + PVOID pArgs, + PDWORD pdwRetCode + ) +{ +#ifdef DEBUG + static BOOL fFirstTime = TRUE; + + if (fFirstTime) { + + // + // Ensure that wownt32.h's definition of WCB16_MAX_CBARGS + // matches wow.h's definition of PARMWCB16. + // + + WOW32ASSERT( WCB16_MAX_CBARGS == sizeof(PARMWCB16) ); + + // + // If the PARMWCB16 structure is smaller than the PARM16 + // union, we should increase the size of PARMWCB16 and + // WCB16_MAX_CBARG to allow the use of the extra bytes. + // + + WOW32ASSERT( sizeof(PARMWCB16) == sizeof(PARM16) ); + + fFirstTime = FALSE; + } +#endif // DEBUG + + if (cbArgs > sizeof(PARM16)) { + LOGDEBUG(LOG_ALWAYS, ("WOWCallback16V: cbArgs = %u, must be <= %u", + cbArgs, (unsigned) sizeof(PARM16))); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + // + // For cdecl functions we don't want to "sub SP, cbArgs" after calling + // the function, so we pass 0 as cbArgs to the 16-bit side. + // + + if (dwFlags & WCB16_CDECL) { + cbArgs = 0; + } + + // + // Use semi-slimy method to pass argument size to CallBack16. + // + + *pdwRetCode = cbArgs; + + CallBack16(RET_WOWCALLBACK16, (PPARM16)pArgs, (VPPROC)vpFn, (PVPVOID)pdwRetCode); + + return TRUE; +} + + +BOOL CallBack16(INT iRetID, PPARM16 pParm16, VPPROC vpfnProc, PVPVOID pvpReturn) +{ +#ifdef DEBUG + static PSZ apszCallBacks[] = { + "ERROR:RETURN", // RET_RETURN (not a callback!) + "ERROR:DEBUGRETURN", // RET_DEBUGRETURN (not a callback!) + "DEBUG", // RET_DEBUG + "WNDPROC", // RET_WNDPROC + "ENUMFONTPROC", // RET_ENUMFONTPROC + "ENUMWINDOWPROC", // RET_ENUMWINDOWPROC + "LOCALALLOC", // RET_LOCALALLOC + "LOCALREALLOC", // RET_LOCALREALLOC + "LOCALLOCK", // RET_LOCALLOCK + "LOCALUNLOCK", // RET_LOCALUNLOCK + "LOCALSIZE", // RET_LOCALSIZE + "LOCALFREE", // RET_LOCALFREE + "GLOBALALLOCLOCK", // RET_GLOBALALLOCLOCK + "GLOBALLOCK", // RET_GLOBALLOCK + "GLOBALUNLOCK", // RET_GLOBALUNLOCK + "GLOBALUNLOCKFREE", // RET_GLOBALUNLOCKFREE + "FINDRESOURCE", // RET_FINDRESOURCE + "LOADRESOURCE", // RET_LOADRESOURCE + "FREERESOURCE", // RET_FREERESOURCE + "LOCKRESOURCE", // RET_LOCKRESOURCE + "UNLOCKRESOURCE", // RET_UNLOCKRESOURCE + "SIZEOFRESOURCE", // RET_SIZEOFRESOURCE + "LOCKSEGMENT", // RET_LOCKSEGMENT + "UNLOCKSEGMENT", // RET_UNLOCKSEGMENT + "ENUMMETAFILEPROC", // RET_ENUMMETAFILEPROC + "TASKSTARTED ", // RET_TASKSTARTED + "HOOKPROC", // RET_HOOKPROC + "SUBCLASSPROC", // RET_SUBCLASSPROC + "LINEDDAPROC", // RET_LINEDDAPROC + "GRAYSTRINGPROC", // RET_GRAYSTRINGPROC + "FORCETASKEXIT", // RET_FORCETASKEXIT + "SETCURDIR", // RET_SETCURDIR + "ENUMOBJPROC", // RET_ENUMOBJPROC + "SETCURSORICONFLAG", // RET_SETCURSORICONFLAG + "SETABORTPROC", // RET_SETABORTPROC + "ENUMPROPSPROC", // RET_ENUMPROPSPROC + "FORCESEGMENTFAULT", // RET_FORCESEGMENTFAULT + "UNUSEDFUNC", // + "UNUSEDFUNC", // + "UNUSEDFUNC", // + "UNUSEDFUNC", // + "UNUSEDFUNC", // + "GETEXEPTR", // RET_GETEXEPTR + "UNUSEDFUNC", // + "FORCETASKFAULT", // RET_FORCETASKFAULT + "GETEXPWINVER", // RET_GETEXPWINVER + "GETCURDIR", // RET_GETCURDIR + "GETDOSPDB", // RET_GETDOSPDB + "GETDOSSFT", // RET_GETDOSSFT + "FOREGROUNDIDLE", // RET_FOREGROUNDIDLE + "WINSOCKBLOCKHOOK", // RET_WINSOCKBLOCKHOOK + "WOWDDEFREEHANDLE", // RET_WOWDDEFREEHANDLE + "CHANGESELECTOR", // RET_CHANGESELECTOR + "GETMODULEFILENAME", // RET_GETMODULEFILENAME + "WORDBREAKPROC", // RET_WORDBREAKPROC + "WINEXEC", // RET_WINEXEC + "WOWCALLBACK16", // RET_WOWCALLBACK16 + "GETDIBSIZE", // RET_GETDIBSIZE + "GETDIBFLAGS", // RET_GETDIBFLAGS + "SETDIBSEL", // RET_SETDIBSEL + "FREEDIBSEL" // RET_FREEDIBSEL + }; +#endif + register PTD ptd; + register PVDMFRAME pFrame; + register PCBVDMFRAME pCBFrame; + WORD wAX; +#if FASTBOPPING +#else + USHORT SaveIp; +#endif +#ifdef DEBUG + VPVOID vpStackT, vpCBStackT; +#endif + + + WOW32ASSERT(iRetID != RET_RETURN && iRetID != RET_DEBUGRETURN); + + ptd = CURRENTPTD(); + + GETFRAMEPTR(ptd->vpStack, pFrame); + + // Just making sure that this thread matches the current 16-bit task + + WOW32ASSERT((pFrame->wTDB == ptd->htask16) || + (ptd->dwFlags & TDF_IGNOREINPUT) || + (ptd->htask16 == 0)); + + // Prep the frame for the callback + // make it word aligned. + + if (ptd->dwFlags & TDF_INITCALLBACKSTACK) { + ptd->vpCBStack = (ptd->vpStack - sizeof(CBVDMFRAME)) & (~0x1); + } + else { + ptd->dwFlags |= TDF_INITCALLBACKSTACK; + ptd->vpCBStack = (ptd->vpCBStack - sizeof(CBVDMFRAME)) & (~0x1); + } + GETFRAMEPTR(ptd->vpCBStack, (PVDMFRAME)pCBFrame); + pCBFrame->vpStack = ptd->vpStack; + pCBFrame->wRetID = (WORD)iRetID; + pCBFrame->wTDB = pFrame->wTDB; + pCBFrame->wLocalBP = pFrame->wLocalBP; + +#ifdef DEBUG + // Save + + vpStackT = ptd->vpStack; + vpCBStackT = ptd->vpCBStack; +#endif + + if (pParm16) + RtlCopyMemory(&pCBFrame->Parm16, pParm16, sizeof(PARM16)); + + //if (vpfnProc) // cheaper to just do it + STOREDWORD(pCBFrame->vpfnProc, vpfnProc); + + wAX = HIWORD(ptd->vpStack); // Put SS in AX register for callback + + if ( iRetID == RET_WNDPROC ) { + if ( pParm16->WndProc.hInst ) + wAX = pParm16->WndProc.hInst | 1; + } + + pCBFrame->wAX = wAX; // Use this AX for the callback + + // + // Semi-slimy way we pass byte count of arguments into this function + // for generic callbacks (WOWCallback16). + // + + if (RET_WOWCALLBACK16 == iRetID) { + pCBFrame->wGenUse1 = (WORD)(DWORD)*pvpReturn; + } + +#ifdef DEBUG + if (iRetID == RET_WNDPROC) { + LOGDEBUG(9,("%04X Calling WIN16 WNDPROC(%08lx:%04x,%04x,%04x,%04x,%04x)\n", + pFrame->wTDB, + vpfnProc, + pParm16->WndProc.hwnd, + pParm16->WndProc.wMsg, + pParm16->WndProc.wParam, + HIWORD(pParm16->WndProc.lParam), + LOWORD(pParm16->WndProc.lParam) + ) + ); + + } else if (iRetID == RET_HOOKPROC) { + LOGDEBUG(9,("%04X Calling WIN16 HOOKPROC(%08lx: %04x,%04x,%04x,%04x)\n", + pFrame->wTDB, + vpfnProc, + pParm16->HookProc.nCode, + pParm16->HookProc.wParam, + HIWORD(pParm16->HookProc.lParam), + LOWORD(pParm16->HookProc.lParam) + ) + ); + + + } else { + LOGDEBUG(9,("%04X Calling WIN16 %s(%04x,%04x,%04x)\n", + pFrame->wTDB, + apszCallBacks[iRetID], + pParm16->WndProc.wParam, + HIWORD(pParm16->WndProc.lParam), + LOWORD(pParm16->WndProc.lParam) + ) + ); + } +#endif + + FREEVDMPTR(pFrame); + FLUSHVDMPTR(ptd->vpCBStack, sizeof(CBVDMFRAME), pCBFrame); + FREEVDMPTR(pCBFrame); + + // Set up to use the right 16-bit stack for this thread + +#if FASTBOPPING + SETFASTVDMSTACK(ptd->vpCBStack); +#else + SETVDMSTACK(ptd->vpCBStack); +#endif + + // + // do the callback! + // + +#if FASTBOPPING + CurrentMonitorTeb = NtCurrentTeb(); + FastWOWCallbackCall(); + // fastbop code refreshes ptd->vpStack +#else + // Time to get the IEU running task-time code again + SaveIp = getIP(); + host_simulate(); + setIP(SaveIp); + ptd->vpStack = VDMSTACK(); +#endif + + // after return from callback ptd->vpStack will point to PCBVDMFRAME + + // consistency check + WOW32ASSERT(ptd->vpStack == vpCBStackT); + + ptd->vpCBStack = ptd->vpStack; + GETFRAMEPTR(ptd->vpCBStack, (PVDMFRAME)pCBFrame); + + // Just making sure that this thread matches the current 16-bit task + + WOW32ASSERT((pCBFrame->wTDB == ptd->htask16) || + (ptd->htask16 == 0)); + + if (pvpReturn) { + LOW(*pvpReturn) = pCBFrame->wAX; + HIW(*pvpReturn) = pCBFrame->wDX; + } + + LOGDEBUG(9,("%04X WIN16 %s returning: %lx\n", + pCBFrame->wTDB, apszCallBacks[iRetID], (pvpReturn) ? *pvpReturn : 0)); + + // restore the stack to its original value. + // ie. fake the 'pop' of callback stack by resetting the vpStack + // to its original value. The ss:sp will actually be updated when + // the 'api thunk' returns. + + // consistency check + WOW32ASSERT(pCBFrame->vpStack == vpStackT); + + ptd->vpStack = pCBFrame->vpStack; + + FREEVDMPTR(pCBFrame); + + return TRUE; +} -- cgit v1.2.3