summaryrefslogtreecommitdiffstats
path: root/private/mvdm/wow32/wcall16.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/mvdm/wow32/wcall16.c
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/mvdm/wow32/wcall16.c')
-rw-r--r--private/mvdm/wow32/wcall16.c819
1 files changed, 819 insertions, 0 deletions
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;
+}