|
|
/*++
* * 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) { *phMem = Parm16.WndProc.wParam; } } 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;
Parm16.WndProc.wParam = hMem; CallBack16(RET_GLOBALLOCK, &Parm16, 0, &vp);
// Get size of 16-bit object (will be 0 if lock failed)
if (pcb) { *pcb = Parm16.WndProc.lParam; }
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);
//
// GetExePtr(hmod) returns hmod, don't cache these.
//
if (hInst != (HAND16)LOWORD(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;
Parm16.WndProc.wParam = hMem; CallBack16(RET_LOCKRESOURCE, &Parm16, 0, &vp);
// Get size of 16-bit object (will be 0 if lock failed)
if (pcb) { *pcb = Parm16.WndProc.lParam; }
return vp; }
int WINAPI WOWlstrcmp16(LPCWSTR lpString1, LPCWSTR lpString2) { PARM16 Parm16; DWORD dwReturn = 0; DWORD cb1, cb2; VPSTR vp1, vp2; LPSTR p1, p2;
//
// to handle DBCS correctly allocate enough room
// for two DBCS bytes for every unicode char.
//
cb1 = sizeof(WCHAR) * (wcslen(lpString1) + 1); cb2 = sizeof(WCHAR) * (wcslen(lpString2) + 1);
// be sure allocation size matches stackfree16() size below
vp1 = stackalloc16(cb1 + cb2); vp2 = vp1 + cb1;
p1 = VDMPTR(vp1, cb1); p2 = p1 + cb1;
RtlUnicodeToMultiByteN( p1, cb1, NULL, (LPWSTR) lpString1, // cast because arg isn't declared const
cb1 );
RtlUnicodeToMultiByteN( p2, cb2, NULL, (LPWSTR) lpString2, // cast because arg isn't declared const
cb2 );
FREEVDMPTR(p1);
Parm16.lstrcmpParms.lpstr1 = vp1; Parm16.lstrcmpParms.lpstr2 = vp2;
CallBack16(RET_LSTRCMP, &Parm16, 0, &dwReturn);
stackfree16(vp1, (cb1 + cb2));
return (int)(short int)LOWORD(dwReturn); }
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
"LSTRCMP", // RET_LSTRCMP
"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; BOOL fComDlgSync = FALSE; INT cStackAlloc16; VPVOID vpCBStack; // See NOTES in walloc16.c\stackalloc16()
#if FASTBOPPING
#else
USHORT SaveIp; #endif
#ifdef DEBUG
VPVOID vpStackT; #endif
WOW32ASSERT(iRetID != RET_RETURN && iRetID != RET_DEBUGRETURN);
ptd = CURRENTPTD();
// ssync 16-bit & 32-bit common dialog structs (see wcommdlg.c)
if(ptd->CommDlgTd) {
// only ssync for stuff that might actually callback into the app
// ie. we don't need to ssync every time wow32 calls GlobalLock16
switch(iRetID) { case RET_WNDPROC: // try to get these in a most frequently
case RET_HOOKPROC: // used order
case RET_WINSOCKBLOCKHOOK: case RET_ENUMFONTPROC: case RET_ENUMWINDOWPROC: case RET_ENUMOBJPROC: case RET_ENUMPROPSPROC: case RET_LINEDDAPROC: case RET_GRAYSTRINGPROC: case RET_SETWORDBREAKPROC: case RET_SETABORTPROC: // Note: This call can invalidate flat ptrs to 16-bit mem
Ssync_WOW_CommDlg_Structs(ptd->CommDlgTd, w32to16, 0); fComDlgSync = TRUE; // set this for return ssync
break; default: break; } }
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));
// set up the callback stack frame from the correct location
// & make it word aligned.
// if stackalloc16() hasn't been called since the app called into wow32
if (ptd->cStackAlloc16 == 0) { vpCBStack = ptd->vpStack; ptd->vpCBStack = (ptd->vpStack - sizeof(CBVDMFRAME)) & (~0x1); } else { vpCBStack = ptd->vpCBStack; 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;
// save the current context stackalloc16() count and set the count to
// 0 for the next context. This will force ptd->vpCBStack to be calc'd
// correctly in any future calls to stackalloc16() if the app callsback
// into WOW
cStackAlloc16 = ptd->cStackAlloc16; ptd->cStackAlloc16 = 0;
#ifdef DEBUG
// Save
vpStackT = ptd->vpStack; #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
ptd->vpCBStack = ptd->vpStack;
// reset the stackalloc16() count back to this context
ptd->cStackAlloc16 = cStackAlloc16;
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; }
switch(iRetID) {
case RET_GLOBALLOCK: case RET_LOCKRESOURCE: if(pParm16) { pParm16->WndProc.lParam = pCBFrame->wGenUse2 | (LONG)pCBFrame->wGenUse1 << 16; } break;
case RET_GLOBALALLOCLOCK: if(pParm16) { pParm16->WndProc.wParam = pCBFrame->wGenUse1; } break;
case RET_FINDRESOURCE: if(pParm16) { pParm16->WndProc.lParam = (ULONG)pCBFrame->wGenUse1; } break;
} // end switch
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);
// restore the stack & callback frame ptrs to original values
ptd->vpStack = pCBFrame->vpStack; ptd->vpCBStack = vpCBStack;
// ssync 16-bit & 32-bit common dialog structs (see wcommdlg.c)
if(fComDlgSync) { // Note: This call can invalidate flat ptrs to 16-bit mem
Ssync_WOW_CommDlg_Structs(ptd->CommDlgTd, w16to32, 0); }
FREEVDMPTR(pCBFrame);
return TRUE; }
|