Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

3971 lines
100 KiB

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
emdp.c
Abstract:
This file contains the main driver for the native execution models
supported by us. This file additionally contains the machine
independent portions of the execution model. The machine dependent
portions are in other files.
Author:
Jim Schaad (jimsch) 05-23-92
Environment:
Win32 -- User
Notes:
The orginal source for this came from the CodeView group.
--*/
#include "strings.h"
#ifdef FE_IME
#include <ime.h>
#endif
/*************************** DEFINES *****************************/
#define CBBUFFERDEF 1024
#define CEXM_MDL_native 0x20
#define cchErrMax 50
/******************* TYPEDEFS and STRUCTURE ***********************/
/*********************** LOCAL DATA *******************************/
CRITICAL_SECTION csCache;
LPBYTE LpSendBuf = NULL;
DWORD CbSendBuf = 0;
DWORD CbDmMsg = 0;
LPDM_MSG LpDmMsg = NULL;
LPDBF lpdbf = (LPDBF)NULL;
LPFNSVC lpfnsvcTL = (LPFNSVC)NULL;
XOSD (PASCAL LOADDS *CallTL) ( TLF, HPID, DWORD, LPV );
XOSD (PASCAL LOADDS *CallDB) ( DBC, HPID, HTID, DWORD, DWORD, LPV );
XOSD (PASCAL LOADDS *CallNT) ( EMF, HPID, HTID, DWORD, LPV );
HLLI llprc = (HLLI)NULL;
HPRC hprcCurr = 0;
HPID hpidCurr = 0;
PID pidCurr = 0;
HTHD hthdCurr = 0;
HTID htidCurr = 0;
TID tidCurr = 0;
HLLI HllEo = (HLLI) NULL;
API_VERSION ApiVersionForImagehlp = { 3, 5, API_VERSION_NUMBER, 0 };
#ifdef OSDEBUG4
LOADDMSTRUCT LoadDmStruct = {
"dm.dll"
};
#endif
#ifdef OSDEBUG4
#define DECL_MASK(n,v,s) n = v,
#define DECL_MSG(n,s,m)
enum {
#include "win32msg.h"
};
#undef DECL_MASK
#define DECL_MASK(n,v,s) { n, s },
MASKINFO MaskInfo[] = {
#include "win32msg.h"
};
#define MASKMAPSIZE (sizeof(MaskInfo)/sizeof(MASKINFO))
MASKMAP MaskMap = {MASKMAPSIZE, MaskInfo};
#undef DECL_MASK
#undef DECL_MSG
#define DECL_MASK(n,v,s)
#define DECL_MSG(n,s,m) { n, s, m },
MESSAGEINFO MessageInfo[] = {
#include "win32msg.h"
};
#define MESSAGEMAPSIZE (sizeof(MessageInfo)/sizeof(MESSAGEINFO))
MESSAGEMAP MessageMap = {MESSAGEMAPSIZE,MessageInfo};
#undef DECL_MASK
#undef DECL_MSG
#else // OSDEBUG4
MSGINFO MsgInfo[] = {
WM_NULL , "WM_NULL" , MSG_TYPE_OTHER ,
WM_CREATE , "WM_CREATE" , MSG_TYPE_WINDOW ,
WM_DESTROY , "WM_DESTROY" , MSG_TYPE_WINDOW ,
WM_MOVE , "WM_MOVE" , MSG_TYPE_WINDOW ,
WM_SIZE , "WM_SIZE" , MSG_TYPE_WINDOW ,
WM_ACTIVATE , "WM_ACTIVATE" , MSG_TYPE_WINDOW ,
WM_SETFOCUS , "WM_SETFOCUS" , MSG_TYPE_WINDOW ,
WM_KILLFOCUS , "WM_KILLFOCUS" , MSG_TYPE_WINDOW ,
WM_ENABLE , "WM_ENABLE" , MSG_TYPE_WINDOW ,
WM_SETREDRAW , "WM_SETREDRAW" , MSG_TYPE_WINDOW ,
WM_SETTEXT , "WM_SETTEXT" , MSG_TYPE_WINDOW ,
WM_GETTEXT , "WM_GETTEXT" , MSG_TYPE_WINDOW ,
WM_GETTEXTLENGTH , "WM_GETTEXTLENGTH" , MSG_TYPE_WINDOW ,
WM_PAINT , "WM_PAINT" , MSG_TYPE_WINDOW ,
WM_CLOSE , "WM_CLOSE" , MSG_TYPE_WINDOW ,
WM_QUERYENDSESSION , "WM_QUERYENDSESSION" , MSG_TYPE_WINDOW ,
WM_QUIT , "WM_QUIT" , MSG_TYPE_WINDOW ,
WM_QUERYOPEN , "WM_QUERYOPEN" , MSG_TYPE_WINDOW ,
WM_ERASEBKGND , "WM_ERASEBKGND" , MSG_TYPE_WINDOW ,
WM_SYSCOLORCHANGE , "WM_SYSCOLORCHANGE" , MSG_TYPE_SYSTEM ,
WM_ENDSESSION , "WM_ENDSESSION" , MSG_TYPE_SYSTEM ,
WM_SHOWWINDOW , "WM_SHOWWINDOW" , MSG_TYPE_WINDOW ,
WM_WININICHANGE , "WM_WININICHANGE" , MSG_TYPE_SYSTEM ,
WM_DEVMODECHANGE , "WM_DEVMODECHANGE" , MSG_TYPE_SYSTEM ,
WM_ACTIVATEAPP , "WM_ACTIVATEAPP" , MSG_TYPE_WINDOW ,
WM_FONTCHANGE , "WM_FONTCHANGE" , MSG_TYPE_SYSTEM ,
WM_TIMECHANGE , "WM_TIMECHANGE" , MSG_TYPE_SYSTEM ,
WM_CANCELMODE , "WM_CANCELMODE" , MSG_TYPE_WINDOW ,
WM_SETCURSOR , "WM_SETCURSOR" , MSG_TYPE_MOUSE ,
WM_MOUSEACTIVATE , "WM_MOUSEACTIVATE" , MSG_TYPE_MOUSE ,
WM_CHILDACTIVATE , "WM_CHILDACTIVATE" , MSG_TYPE_WINDOW ,
WM_QUEUESYNC , "WM_QUEUESYNC" , MSG_TYPE_SYSTEM ,
WM_GETMINMAXINFO , "WM_GETMINMAXINFO" , MSG_TYPE_WINDOW ,
WM_PAINTICON , "WM_PAINTICON" , MSG_TYPE_WINDOW ,
WM_ICONERASEBKGND , "WM_ICONERASEBKGND" , MSG_TYPE_WINDOW ,
WM_NEXTDLGCTL , "WM_NEXTDLGCTL" , MSG_TYPE_WINDOW ,
WM_SPOOLERSTATUS , "WM_SPOOLERSTATUS" , MSG_TYPE_OTHER ,
WM_DRAWITEM , "WM_DRAWITEM" , MSG_TYPE_WINDOW ,
WM_MEASUREITEM , "WM_MEASUREITEM" , MSG_TYPE_WINDOW ,
WM_DELETEITEM , "WM_DELETEITEM" , MSG_TYPE_WINDOW ,
WM_VKEYTOITEM , "WM_VKEYTOITEM" , MSG_TYPE_WINDOW ,
WM_CHARTOITEM , "WM_CHARTOITEM" , MSG_TYPE_WINDOW ,
WM_SETFONT , "WM_SETFONT" , MSG_TYPE_WINDOW ,
WM_GETFONT , "WM_GETFONT" , MSG_TYPE_WINDOW ,
WM_SETHOTKEY , "WM_SETHOTKEY" , MSG_TYPE_INPUT ,
WM_GETHOTKEY , "WM_GETHOTKEY" , MSG_TYPE_INPUT ,
WM_QUERYDRAGICON , "WM_QUERYDRAGICON" , MSG_TYPE_WINDOW ,
WM_COMPAREITEM , "WM_COMPAREITEM" , MSG_TYPE_WINDOW ,
WM_COMPACTING , "WM_COMPACTING" , MSG_TYPE_SYSTEM ,
// WM_OTHERWINDOWCREATED , "WM_OTHERWINDOWCREATED" , MSG_TYPE_SYSTEM ,
// WM_OTHERWINDOWDESTROYED , "WM_OTHERWINDOWDESTROYED" , MSG_TYPE_SYSTEM ,
// WM_COMMNOTIFY , "WM_COMMNOTIFY" , MSG_TYPE_SYSTEM ,
// WM_HOTKEYEVENT , "WM_HOTKEYEVENT" , MSG_TYPE_SYSTEM ,
WM_WINDOWPOSCHANGING , "WM_WINDOWPOSCHANGING" , MSG_TYPE_WINDOW ,
WM_WINDOWPOSCHANGED , "WM_WINDOWPOSCHANGED" , MSG_TYPE_WINDOW ,
WM_POWER , "WM_POWER" , MSG_TYPE_SYSTEM ,
WM_COPYDATA , "WM_COPYDATA" , MSG_TYPE_SYSTEM ,
WM_CANCELJOURNAL , "WM_CANCELJOURNAL" , MSG_TYPE_SYSTEM ,
WM_NCCREATE , "WM_NCCREATE" , MSG_TYPE_NONCLIENT ,
WM_NCDESTROY , "WM_NCDESTROY" , MSG_TYPE_NONCLIENT ,
WM_NCCALCSIZE , "WM_NCCALCSIZE" , MSG_TYPE_NONCLIENT ,
WM_NCHITTEST , "WM_NCHITTEST" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE ,
WM_NCPAINT , "WM_NCPAINT" , MSG_TYPE_NONCLIENT ,
WM_NCACTIVATE , "WM_NCACTIVATE" , MSG_TYPE_NONCLIENT ,
WM_GETDLGCODE , "WM_GETDLGCODE" , MSG_TYPE_WINDOW ,
WM_NCMOUSEMOVE , "WM_NCMOUSEMOVE" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE ,
WM_NCLBUTTONDOWN , "WM_NCLBUTTONDOWN" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE ,
WM_NCLBUTTONUP , "WM_NCLBUTTONUP" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE ,
WM_NCLBUTTONDBLCLK , "WM_NCLBUTTONDBLCLK" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE ,
WM_NCRBUTTONDOWN , "WM_NCRBUTTONDOWN" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE ,
WM_NCRBUTTONUP , "WM_NCRBUTTONUP" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE ,
WM_NCRBUTTONDBLCLK , "WM_NCRBUTTONDBLCLK" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE ,
WM_NCMBUTTONDOWN , "WM_NCMBUTTONDOWN" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE ,
WM_NCMBUTTONUP , "WM_NCMBUTTONUP" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE ,
WM_NCMBUTTONDBLCLK , "WM_NCMBUTTONDBLCLK" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE ,
WM_KEYDOWN , "WM_KEYDOWN" , MSG_TYPE_INPUT ,
WM_KEYUP , "WM_KEYUP" , MSG_TYPE_INPUT ,
WM_CHAR , "WM_CHAR" , MSG_TYPE_INPUT ,
WM_DEADCHAR , "WM_DEADCHAR" , MSG_TYPE_INPUT ,
WM_SYSKEYDOWN , "WM_SYSKEYDOWN" , MSG_TYPE_SYSTEM | MSG_TYPE_INPUT ,
WM_SYSKEYUP , "WM_SYSKEYUP" , MSG_TYPE_SYSTEM | MSG_TYPE_INPUT ,
WM_SYSCHAR , "WM_SYSCHAR" , MSG_TYPE_SYSTEM | MSG_TYPE_INPUT ,
WM_SYSDEADCHAR , "WM_SYSDEADCHAR" , MSG_TYPE_SYSTEM | MSG_TYPE_INPUT ,
WM_INITDIALOG , "WM_INITDIALOG" , MSG_TYPE_INIT ,
WM_COMMAND , "WM_COMMAND" , MSG_TYPE_INPUT ,
WM_SYSCOMMAND , "WM_SYSCOMMAND" , MSG_TYPE_SYSTEM ,
WM_TIMER , "WM_TIMER" , MSG_TYPE_INPUT ,
WM_HSCROLL , "WM_HSCROLL" , MSG_TYPE_INPUT ,
WM_VSCROLL , "WM_VSCROLL" , MSG_TYPE_INPUT ,
WM_INITMENU , "WM_INITMENU" , MSG_TYPE_INIT ,
WM_INITMENUPOPUP , "WM_INITMENUPOPUP" , MSG_TYPE_INIT ,
WM_MENUSELECT , "WM_MENUSELECT" , MSG_TYPE_INPUT ,
WM_MENUCHAR , "WM_MENUCHAR" , MSG_TYPE_INPUT ,
WM_ENTERIDLE , "WM_ENTERIDLE" , MSG_TYPE_SYSTEM ,
WM_CTLCOLORMSGBOX , "WM_CTLCOLORMSGBOX" , MSG_TYPE_WINDOW ,
WM_CTLCOLOREDIT , "WM_CTLCOLOREDIT" , MSG_TYPE_WINDOW ,
WM_CTLCOLORLISTBOX , "WM_CTLCOLORLISTBOX" , MSG_TYPE_WINDOW ,
WM_CTLCOLORBTN , "WM_CTLCOLORBTN" , MSG_TYPE_WINDOW ,
WM_CTLCOLORDLG , "WM_CTLCOLORDLG" , MSG_TYPE_WINDOW ,
WM_CTLCOLORSCROLLBAR , "WM_CTLCOLORSCROLLBAR" , MSG_TYPE_WINDOW ,
WM_CTLCOLORSTATIC , "WM_CTLCOLORSTATIC" , MSG_TYPE_WINDOW ,
WM_MOUSEMOVE , "WM_MOUSEMOVE" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE ,
WM_LBUTTONDOWN , "WM_LBUTTONDOWN" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE ,
WM_LBUTTONUP , "WM_LBUTTONUP" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE ,
WM_LBUTTONDBLCLK , "WM_LBUTTONDBLCLK" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE ,
WM_RBUTTONDOWN , "WM_RBUTTONDOWN" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE ,
WM_RBUTTONUP , "WM_RBUTTONUP" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE ,
WM_RBUTTONDBLCLK , "WM_RBUTTONDBLCLK" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE ,
WM_MBUTTONDOWN , "WM_MBUTTONDOWN" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE ,
WM_MBUTTONUP , "WM_MBUTTONUP" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE ,
WM_MBUTTONDBLCLK , "WM_MBUTTONDBLCLK" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE ,
WM_PARENTNOTIFY , "WM_PARENTNOTIFY" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE ,
//WM_ENTERMENULOOP , "WM_ENTERMENULOOP" , MSG_TYPE_SYSTEM ,
//WM_EXITMENULOOP , "WM_EXITMENULOOP" , MSG_TYPE_SYSTEM ,
WM_MDICREATE , "WM_MDICREATE" , MSG_TYPE_WINDOW ,
WM_MDIDESTROY , "WM_MDIDESTROY" , MSG_TYPE_WINDOW ,
WM_MDIACTIVATE , "WM_MDIACTIVATE" , MSG_TYPE_WINDOW ,
WM_MDIRESTORE , "WM_MDIRESTORE" , MSG_TYPE_WINDOW ,
WM_MDINEXT , "WM_MDINEXT" , MSG_TYPE_WINDOW ,
WM_MDIMAXIMIZE , "WM_MDIMAXIMIZE" , MSG_TYPE_WINDOW ,
WM_MDITILE , "WM_MDITILE" , MSG_TYPE_WINDOW ,
WM_MDICASCADE , "WM_MDICASCADE" , MSG_TYPE_WINDOW ,
WM_MDIICONARRANGE , "WM_MDIICONARRANGE" , MSG_TYPE_WINDOW ,
WM_MDIGETACTIVE , "WM_MDIGETACTIVE" , MSG_TYPE_WINDOW ,
WM_MDISETMENU , "WM_MDISETMENU" , MSG_TYPE_WINDOW ,
WM_DROPFILES , "WM_DROPFILES" , MSG_TYPE_WINDOW ,
WM_MDIREFRESHMENU , "WM_MDIREFRESHMENU" , MSG_TYPE_WINDOW ,
WM_CUT , "WM_CUT" , MSG_TYPE_CLIPBOARD ,
WM_COPY , "WM_COPY" , MSG_TYPE_CLIPBOARD ,
WM_PASTE , "WM_PASTE" , MSG_TYPE_CLIPBOARD ,
WM_CLEAR , "WM_CLEAR" , MSG_TYPE_CLIPBOARD ,
WM_UNDO , "WM_UNDO" , MSG_TYPE_CLIPBOARD ,
WM_RENDERFORMAT , "WM_RENDERFORMAT" , MSG_TYPE_CLIPBOARD ,
WM_RENDERALLFORMATS , "WM_RENDERALLFORMATS" , MSG_TYPE_CLIPBOARD ,
WM_DESTROYCLIPBOARD , "WM_DESTROYCLIPBOARD" , MSG_TYPE_CLIPBOARD ,
WM_DRAWCLIPBOARD , "WM_DRAWCLIPBOARD" , MSG_TYPE_CLIPBOARD ,
WM_PAINTCLIPBOARD , "WM_PAINTCLIPBOARD" , MSG_TYPE_CLIPBOARD ,
WM_VSCROLLCLIPBOARD , "WM_VSCROLLCLIPBOARD" , MSG_TYPE_CLIPBOARD ,
WM_SIZECLIPBOARD , "WM_SIZECLIPBOARD" , MSG_TYPE_CLIPBOARD ,
WM_ASKCBFORMATNAME , "WM_ASKCBFORMATNAME" , MSG_TYPE_CLIPBOARD ,
WM_CHANGECBCHAIN , "WM_CHANGECBCHAIN" , MSG_TYPE_CLIPBOARD ,
WM_HSCROLLCLIPBOARD , "WM_HSCROLLCLIPBOARD" , MSG_TYPE_CLIPBOARD ,
WM_QUERYNEWPALETTE , "WM_QUERYNEWPALETTE" , MSG_TYPE_WINDOW ,
WM_PALETTEISCHANGING , "WM_PALETTEISCHANGING" , MSG_TYPE_WINDOW ,
WM_PALETTECHANGED , "WM_PALETTECHANGED" , MSG_TYPE_WINDOW ,
WM_HOTKEY , "WM_HOTKEY" , MSG_TYPE_WINDOW ,
WM_DDE_INITIATE , "WM_DDE_INITIATE" , MSG_TYPE_DDE ,
WM_DDE_TERMINATE , "WM_DDE_TERMINATE" , MSG_TYPE_DDE ,
WM_DDE_ADVISE , "WM_DDE_ADVISE" , MSG_TYPE_DDE ,
WM_DDE_UNADVISE , "WM_DDE_UNADVISE" , MSG_TYPE_DDE ,
WM_DDE_ACK , "WM_DDE_ACK" , MSG_TYPE_DDE ,
WM_DDE_DATA , "WM_DDE_DATA" , MSG_TYPE_DDE ,
WM_DDE_REQUEST , "WM_DDE_REQUEST" , MSG_TYPE_DDE ,
WM_DDE_POKE , "WM_DDE_POKE" , MSG_TYPE_DDE ,
WM_DDE_EXECUTE , "WM_DDE_EXECUTE" , MSG_TYPE_DDE ,
#ifdef FE_IME
// we had better create IME class(e.g. MSG_TYPE_IME)
// for the following messages.
WM_CONVERTREQUEST , "WM_CONVERTREQUEST" , MSG_TYPE_INPUT ,
// WM_CONVERTREQUESTEX , "WM_CONVERTREQUESTEX" , MSG_TYPE_INPUT ,
WM_CONVERTRESULT , "WM_CONVERTRESULT" , MSG_TYPE_INPUT ,
WM_IME_REPORT , "WM_IME_REPORT" , MSG_TYPE_INPUT ,
WM_IMEKEYDOWN , "WM_IMEKEYDOWN" , MSG_TYPE_INPUT ,
WM_IMEKEYUP , "WM_IMEKEYUP" , MSG_TYPE_INPUT ,
WM_INTERIM , "WM_INTERIM" , MSG_TYPE_INPUT ,
WM_IME_CHAR , "WM_IME_CHAR" , MSG_TYPE_INPUT ,
WM_IME_COMPOSITION , "WM_IME_COMPOSITION" , MSG_TYPE_INPUT ,
WM_IME_COMPOSITIONFULL , "WM_IME_COMPOSITIONFULL" , MSG_TYPE_INPUT ,
WM_IME_CONTROL , "WM_IME_CONTROL" , MSG_TYPE_INPUT ,
WM_IME_ENDCOMPOSITION , "WM_IME_ENDCOMPOSITION" , MSG_TYPE_INPUT ,
WM_IME_KEYDOWN , "WM_IME_KEYDOWN" , MSG_TYPE_INPUT ,
WM_IME_KEYLAST , "WM_IME_KEYLAST" , MSG_TYPE_INPUT ,
WM_IME_KEYUP , "WM_IME_KEYUP" , MSG_TYPE_INPUT ,
WM_IME_NOTIFY , "WM_IME_NOTIFY" , MSG_TYPE_INPUT ,
WM_IME_SELECT , "WM_IME_SELECT" , MSG_TYPE_INPUT ,
WM_IME_SETCONTEXT , "WM_IME_SETCONTEXT" , MSG_TYPE_INPUT ,
WM_IME_STARTCOMPOSITION , "WM_IME_STARTCOMPOSITION" , MSG_TYPE_INPUT ,
#endif
0 , NULL , 0
};
MSGMAP MsgMap = {0,MsgInfo};
#endif // OSDEBUG4
/********************* EXTERNAL DATA ******************************/
/*********************** PROTOTYPES *******************************/
XOSD DoCustomCommand(HPID hpid, HTID htid, DWORD wValue, LPIOL lpiol);
/************************** &&&&&& ********************************/
/*
* This is the description of all registers and flags for the
* machine being debugged. These files are machine dependent.
*/
RD Rgrd[] = {
#include "regs.h"
};
const unsigned CRgrd = (sizeof(Rgrd)/sizeof(Rgrd[0]));
struct RGFD Rgfd[] = {
#include "flags.h"
};
const unsigned CRgfd = (sizeof(Rgfd)/sizeof(Rgfd[0]));
/*************************** CODE *****************************************/
/**** DBGVersionCheck ****
* *
* PURPOSE: *
* *
* To export out version information to the debugger. *
* *
* INPUTS: *
* *
* NONE. *
* *
* OUTPUTS: *
* *
* Returns - A pointer to the standard version information. *
* *
* IMPLEMENTATION: *
* *
* Just returns a pointer to a static structure. *
* *
***************************************************************************/
#ifdef DEBUGVER
DEBUG_VERSION('E','M',"Execution Model")
#else
RELEASE_VERSION('E','M',"Execution Model")
#endif
DBGVERSIONCHECK()
/**** SENDREQUEST - Send a request to the DM ****
* *
* PURPOSE: *
* Send a DMF request to the DM. *
* *
* INPUTS: *
* dmf - the request to send *
* hpid - the process *
* htid - the thread *
* *
* OUTPUTS: *
* xosd - error code indicating if request was sent successfully *
* LpDmMsg - global buffer filled in with returned data *
* *
* IMPLEMENTATION: *
* Unlike SendCommand, this function will wait for data to be *
* returned from the DM before returning to the caller. *
* *
***************************************************************************/
XOSD
SendRequest (
DMF dmf,
HPID hpid,
HTID htid
)
{
DBB dbb;
XOSD xosd;
dbb.dmf = dmf;
dbb.hpid = hpid;
dbb.htid = htid;
xosd = CallTL ( tlfRequest, hpid, sizeof ( DBB ), &dbb );
if (xosd != xosdNone)
return xosd;
xosd = (XOSD) LpDmMsg->xosdRet;
return xosd;
}
/**** SENDREQUESTX - Send a request with parameters to the DM ****
* *
* PURPOSE: *
* Send a DMF request and its parameter info to the DM. *
* *
* INPUTS: *
* dmf - the request to send *
* hpid - the process *
* htid - the thread *
* wLen - number of bytes in lpv *
* lpv - pointer to additional info needed by the DM; contents are *
* dependent on the DMF *
* *
* OUTPUTS: *
* xosd - error code indicating if request was sent successfully *
* *
* IMPLEMENTATION: *
* Unlike SendCommand, this function will wait for data to be *
* returned from the DM before returning to the caller. *
* *
***************************************************************************/
XOSD
SendRequestX (
DMF dmf,
HPID hpid,
HTID htid,
DWORD wLen,
LPV lpv
)
{
LPDBB lpdbb;
XOSD xosd;
if (wLen + sizeof(DBB) > CbSendBuf) {
if (LpSendBuf) {
MHFree(LpSendBuf);
}
CbSendBuf = sizeof(DBB) + wLen;
LpSendBuf = MHAlloc(CbSendBuf);
}
if (!LpSendBuf) {
return xosdOutOfMemory;
}
lpdbb = (LPDBB)LpSendBuf;
lpdbb->dmf = dmf;
lpdbb->hpid = hpid;
lpdbb->htid = htid;
_fmemcpy ( lpdbb->rgbVar, lpv, wLen );
xosd = CallTL ( tlfRequest, hpid, sizeof ( DBB ) + wLen, (LPV)lpdbb );
if (xosd != xosdNone) {
return xosd;
}
xosd = (XOSD) LpDmMsg->xosdRet;
return xosd;
}
XOSD
ProgramLoad (
HPID hpid,
DWORD cb,
LPPRL lpprl
)
/*++
Routine Description:
This routine is called to cause a program to be loaded by the
debug monitor.
Arguments:
hpid - Supplies the OSDEBUG handle to the process to be loaded
cb - Length of the command line
lpprl - Pointer to structure containning the command line
Return Value:
xosd error code
--*/
{
XOSD xosd = xosdNone;
LPPRC lpprc;
HPRC hprc = HprcFromHpid(hpid);
lpprc = LLLock ( hprc );
LLDestroy ( lpprc->llmdi );
lpprc->llmdi = LLInit ( sizeof ( MDI ), llfNull, NULL, MDIComp );
LLUnlock ( hprc );
PurgeCache ();
xosd = SendRequestX (
dmfProgLoad,
hpid,
NULL,
cb,
lpprl
);
if (xosd == xosdNone) {
xosd = LpDmMsg->xosdRet;
lpprc = LLLock ( hprc );
lpprc->stat = statStarted;
LLUnlock ( hprc );
}
return xosd;
} /* ProgramLoad() */
/**** PROGRAMFREE - Terminate the program and free the pid ****
* *
* PURPOSE: *
* *
* INPUTS: *
* *
* OUTPUTS: *
* *
* IMPLEMENTATION: *
* *
* *
***************************************************************************/
XOSD
ProgramFree (
HPID hpid,
HTID htid
)
{
return SendRequest( dmfProgFree, hpid, NULL);
}
#ifdef OSDEBUG4
XOSD
CompareAddrs(
HPID hpid,
HTID htid,
LPCAS lpcas
)
{
ADDR a1 = *lpcas->lpaddr1;
ADDR a2 = *lpcas->lpaddr2;
XOSD xosd = xosdNone;
LONG l;
// if both are LI, see if they are comparable:
if (ADDR_IS_LI(a1) && ADDR_IS_LI(a2)
&& emiAddr(a1) == emiAddr(a2)
&& GetAddrSeg(a1) == GetAddrSeg(a2))
{
l = GetAddrOff(a1) - GetAddrOff(a2);
*lpcas->lpResult = (l < 0) ? -1 : ((l == 0) ? 0 : 1);
}
else {
// if neccessary, fixup addresses:
if (ADDR_IS_LI(a1)) {
FixupAddr(hpid, &a1);
}
if (ADDR_IS_LI(a2)) {
FixupAddr(hpid, &a2);
}
// if real mode address, we can really compare
if (ADDR_IS_REAL(a1) && ADDR_IS_REAL(a2)) {
l = ((GetAddrSeg(a1) << 4) + (GetAddrOff(a1) & 0xffff))
- ((GetAddrSeg(a2) << 4) + (GetAddrOff(a2) & 0xffff));
*lpcas->lpResult = (l < 0) ? -1 : ((l == 0) ? 0 : 1);
}
else if (ADDR_IS_FLAT(a1) != ADDR_IS_FLAT(a2)) {
xosd = xosdInvalidParameter;
}
// if flat, ignore selectors
else if (ADDR_IS_FLAT(a1)) {
l = GetAddrOff(a1) - GetAddrOff(a2);
*lpcas->lpResult = (l < 0) ? -1 : ((l == 0) ? 0 : 1);
}
else if (GetAddrSeg(a1) == GetAddrSeg(a2)) {
l = GetAddrOff(a1) - GetAddrOff(a2);
*lpcas->lpResult = (l < 0) ? -1 : ((l == 0) ? 0 : 1);
}
// not flat, different selectors
else {
xosd = xosdInvalidParameter;
}
}
return xosd;
}
#endif // OSDEBUG4
static BOOL fCacheDisabled = FALSE;
#define cbMaxCache CACHESIZE
typedef struct _MCI {
WORD cb;
HPID hpid;
ADDR addr;
BYTE rgb [ cbMaxCache ];
} MCI; // Memory Cache Item
#define imciMax MAXCACHE
MCI FAR rgmci [ imciMax ] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } };
// Most recent used == 0, 2nd to last == 1, etc
int rgiUsage [ imciMax ] = {0};
void InitUsage ( void ) {
int iUsage;
for ( iUsage = 0; iUsage < imciMax; iUsage++ ) {
rgiUsage [ iUsage ] = imciMax - ( iUsage + 1 );
}
}
VOID
SetMostRecent (
int imci
)
{
int i;
if ( rgiUsage [ imci ] != 0 ) {
for ( i = 0; i < imciMax; i++ ) {
if ( rgiUsage [ i ] < rgiUsage [ imci ] ) {
rgiUsage [ i ] ++;
}
}
rgiUsage [ imci ] = 0;
}
}
int
GetLeastRecent (
VOID
)
{
int i;
for ( i = 0; i < imciMax; i++ ) {
assert ( rgiUsage [ i ] >= 0 && rgiUsage [ i ] < imciMax );
if ( rgiUsage [ i ] == imciMax - 1 ) {
return i;
}
}
assert ( FALSE );
return i;
}
VOID
SetLeastRecent (
int imci
)
{
int i;
if ( rgiUsage [ imci ] != imciMax - 1 ) {
for ( i = 0; i < imciMax; i++ ) {
if ( rgiUsage [ i ] > rgiUsage [ imci ] ) {
rgiUsage [ i ] --;
}
}
rgiUsage [ imci ] = imciMax-1;
}
}
XOSD
ReadPhysical (
HPID hpid,
DWORD cb,
LPBYTE lpbDest,
LPADDR lpaddr,
DWORD iCache,
LPDWORD lpcbr
)
{
BYTE rgb [ sizeof ( DBB ) + sizeof ( RWP ) ];
LPDBB lpdbb = (LPDBB) rgb;
PRWP prwp = (PRWP) lpdbb->rgbVar;
WORD wRet = 0;
XOSD xosd = xosdNone;
if (!ValidHprcFromHpid(hpid)) {
#ifdef OSDEBUG4
return xosdBadProcess;
#else
return xosdInvalidProc;
#endif
}
lpdbb->dmf = dmfReadMem;
lpdbb->hpid = hpid;
lpdbb->htid = NULL;
if ( cb + sizeof(DWORD) + FIELD_OFFSET(DM_MSG, rgb) > CbDmMsg ) {
MHFree ( LpDmMsg );
CbDmMsg = cb + sizeof ( DWORD ) + FIELD_OFFSET(DM_MSG, rgb);
LpDmMsg = MHAlloc ( CbDmMsg );
CallTL ( tlfSetBuffer, lpdbb->hpid, CbDmMsg, LpDmMsg );
}
prwp->cb = cb;
prwp->addr = *lpaddr;
xosd = CallTL(tlfRequest, lpdbb->hpid, sizeof (DBB) + sizeof(RWP), rgb);
if (xosd != xosdNone) {
return xosd;
}
xosd = LpDmMsg->xosdRet;
if (xosd == xosdNone) {
*lpcbr = *( (LPDWORD) (LpDmMsg->rgb) );
assert( *lpcbr <= cb );
_fmemcpy ( lpbDest, LpDmMsg->rgb + sizeof ( DWORD ), *lpcbr );
}
return xosd;
}
XOSD
EnableCache (
HPID hpid,
HTID htid,
BOOL state
)
{
fCacheDisabled = state;
if (fCacheDisabled) {
PurgeCache();
}
return xosdNone;
}
void
PurgeCache (
VOID
)
{
int imci;
for ( imci = 0; imci < imciMax; imci++ ) {
rgmci [ imci ].cb = 0;
}
}
void
PurgeCacheHpid (
HPID hpid
)
{
int imci;
for ( imci = 0; imci < imciMax; imci++ ) {
if ( rgmci [ imci ].hpid == hpid ) {
rgmci [ imci ].cb = 0;
SetLeastRecent ( imci );
}
}
}
XOSD
ReadForCache(
HPID hpid,
DWORD cbP,
LPBYTE lpbDest,
LPADDR lpaddr,
LPDWORD lpcb
)
/*++
Routine Description:
This function will fill in a cache entry with the bytes requested
to be read. The function puts the bytes in both the cache and the
memory buffer.
Arguments:
hpid - Supplies the process to do the read in
cbP - Supplies the number of bytes to be read
lpbDest - Supplies the buffer to place the bytes in
lpaddr - Supplies the address to read the bytes from
lpcb - Returns the number of bytes read
Return Value:
XOSD error code
--*/
{
int cb = cbP;
DWORD cbT = cb < cbMaxCache ? cbMaxCache : cb;
DWORD imci;
DWORD cbr;
int dbOverlap = 0;
XOSD xosd;
ADDR addrSave = *lpaddr;
MCI * pmci;
/*
* Determine if the starting address is contained in a
* voided cache entry
*/
for ( imci = 0, pmci = rgmci ; imci < imciMax; imci++, pmci++ ) {
if ( (pmci->cb == 0) &&
(pmci->hpid == hpid) &&
(ADDR_IS_REAL( pmci->addr) == ADDR_IS_REAL( *lpaddr )) &&
(GetAddrSeg ( pmci->addr ) == GetAddrSeg ( *lpaddr )) &&
(GetAddrOff ( *lpaddr ) >= GetAddrOff ( pmci->addr )) &&
(GetAddrOff ( *lpaddr ) + cbP < GetAddrOff ( pmci->addr ) + cbMaxCache)
) {
dbOverlap = (int) (GetAddrOff ( pmci->addr ) - GetAddrOff ( *lpaddr ) );
GetAddrOff ( *lpaddr ) = GetAddrOff ( pmci->addr );
break;
}
}
/*
* if we have not found a cache entry then just get one based on
* an LRU algorithm.
*/
if ( imci == imciMax ) {
imci = GetLeastRecent ( );
}
/*
* Do an actual read of memory from the debuggee
*/
xosd = ReadPhysical ( hpid, cbT, rgmci [ imci ].rgb, lpaddr, imci, &cbr );
if ( xosd != xosdNone ) {
return xosd;
}
/*
* If only a partial cache entry was read in then reset our read
* size variable.
*/
if ( cbr < cbT ) {
cbT = cbr;
}
/*
* if we did not anything (or enough), then don't adjust
*/
if ( (int)cbr + dbOverlap > 0 ) {
cbT += dbOverlap;
}
/*
* touch the LRU table
*/
SetMostRecent ( imci );
/*
* set up the cache entry
*/
rgmci [ imci ].cb = (WORD) cbT;
rgmci [ imci ].addr = *lpaddr;
rgmci [ imci ].hpid = hpid;
GetAddrOff ( *lpaddr ) += cbT;
*lpaddr = addrSave;
/*
* compute the number of bytes read
*/
cbT = (int)min( cbP, (DWORD)rgmci[ imci ].cb );
/*
* copy from the cache entry to the users space
*/
if ( dbOverlap >= 0 ) {
dbOverlap = 0;
}
_fmemcpy ( lpbDest, rgmci [ imci ].rgb - dbOverlap, cbT );
/*
* return the number of bytes read
*/
*lpcb = cbT;
return xosdNone;
} /* ReadForCache() */
int
GetCacheIndex(
HPID hpid,
LPADDR lpaddr
)
/*++
Routine Description:
This routine is given a process and an address and will locate
which cache entry (if any) the address is in.
Arguments:
hpid - Supplies the handle to the process
lpaddr - Supplies the address to look for
Return Value:
The index of the cache entry containing the address or imciMax if
no cache entry contains the address
--*/
{
int imci;
for ( imci = 0; imci < imciMax; imci++ ) {
LPADDR lpaddrT = &rgmci [ imci ].addr;
/*
* To be in the cache entry check:
*
* 1. The cache entry contains bytes
* 2. The cache entry is for the correct process
* 3. The cache entry if for the correct segment
* 4. The requested offset is between the starting and
* ending points of the cache
*/
if ( (rgmci [ imci ].cb != 0) &&
(rgmci [ imci ].hpid == hpid) &&
(ADDR_IS_REAL( *lpaddrT ) == ADDR_IS_REAL( *lpaddr )) &&
(GetAddrSeg ( *lpaddrT ) == GetAddrSeg ( *lpaddr )) &&
(GetAddrOff ( *lpaddrT ) <= GetAddrOff ( *lpaddr )) &&
(GetAddrOff ( *lpaddrT ) + rgmci[ imci ].cb > GetAddrOff ( *lpaddr ))) {
break;
}
}
return imci;
} /* GetCacheIndex() */
int
ReadFromCache (
HPID hpid,
DWORD cb,
LPBYTE lpbDest,
LPADDR lpaddr
)
/*++
Routine Description:
description-of-function.
Arguments:
hpid - Supplies a handle to the process
cb - Supplies the count of bytes to read from the cache
lpbDest - Suppiies the pointer to store bytes at
lpaddr - Supplies pointer to address to read at
Return Value:
> 0 - The number of bytes read from the cache
== 0 - No cache entry for the address was found
--*/
{
int imci;
/*
* See if the address for the start of the read is current contained
* in one of the cached buffers.
*/
imci = GetCacheIndex ( hpid, lpaddr );
/*
* If the starting address is in a cache entry then read as many
* bytes as is possible from that cache entry.
*/
if ( imci != imciMax ) {
DWORD ibStart;
DWORD cbT;
/*
* Compute the difference between the address for the cache start
* and the address for the read request start and then
* the number of bytes which can be read in
*/
ibStart = (DWORD)( GetAddrOff ( *lpaddr ) - GetAddrOff ( rgmci[imci].addr ) );
cbT = min ( cb, rgmci [ imci ].cb - ibStart );
/*
* Preform the copy
*/
_fmemcpy ( lpbDest, rgmci [ imci ].rgb + ibStart, cbT );
/*
* Return the number of bytes copied. If it is less than
* zero then for some reason the current cache was not
* filled to capacity.
*/
return cbT;
}
return 0;
} /* ReadFromCache() */
XOSD
ReadBuffer (
HPID hpid,
HTID htid,
LPADDR lpaddr,
DWORD cb,
LPBYTE lpbDest,
LPDWORD lpcbRead
)
/*++
Routine Description:
This function is called in response to an emfReadBuf message. The
address to start the read at was set earlier and is stored in the
adrCurrent Address Buffer.
Arguments:
hpid - Supplies the handle to the process to read memory for
htid - Supplies the handle to the thread to read memory for
(may be NULL)
lpaddr -
cb - Supplies count of bytes to read
lpbDest - Supplies pointer to buffer to place bytes read
lpcbRead - Returns number of bytes read
Return Value:
if >= 0 then it is the number of bytes actually read otherwise it
is an xosdError code.
--*/
{
XOSD xosd = xosdNone;
ADDR addr;
int cbT = 0;
int cbRead = 0;
HPRC hprc = HprcFromHpid(hpid);
LPPRC lpprc;
/*
* Retrieve the address to start the read at from the address buffer
* location
*/
if (cb == 0) {
if (lpcbRead) {
*lpcbRead = 0;
}
return xosdNone;
}
#ifdef OSDEBUG4
addr = *lpaddr;
#else
if (lpaddr) {
addr = *lpaddr;
} else {
xosd = GetAddr ( hpid, htid, adrCurrent, &addr );
if (xosd != xosdNone) {
return xosd;
}
}
#endif
assert( !ADDR_IS_LI(addr) );
/*
* Are we trying to read more bytes than is possible to store in
* a single cache? If so then skip trying to hit the cache and
* go directly to asking the DM for the memory.
*
* This generally is due to large memory dumps.
*/
lpprc = (LPPRC) LLLock(hprc);
if ( (cb > cbMaxCache) || (lpprc->fRunning ) || (fCacheDisabled) ) {
LLUnlock(hprc);
return ReadPhysical ( hpid, cb, lpbDest, &addr, MAXCACHE, lpcbRead );
}
LLUnlock(hprc);
/*
* Read as much as possible from the set of cached memory reads.
* If cbT > 0 then bytes were read from a cache entry
* if cbT == 0 then no bytes were read in
*/
while ((cb != 0) &&
( cbT = ReadFromCache ( hpid, cb, lpbDest, &addr ) ) > 0 ) {
cbRead += cbT;
lpbDest += cbT;
GetAddrOff ( addr ) += cbT;
cb -= cbT;
}
/*
* If there are still bytes left to be read then get the cache
* routines to read them in and copy both to a cache and to the
* buffer.
*/
if ( cb > 0 ) {
xosd = ReadForCache ( hpid, cb, lpbDest, &addr, &cbT );
if (xosd == xosdNone) {
cbRead += cbT;
}
}
if (lpcbRead) {
*lpcbRead = cbRead;
}
return xosd;
} /* ReadBuffer() */
#ifdef OSDEBUG4
XOSD
WriteBufferCache (
HPID hpid,
HTID htid,
LPADDR lpaddr,
DWORD cb,
LPBYTE lpb,
LPDWORD lpdwBytesWritten
)
{
PurgeCacheHpid ( hpid );
return WriteBuffer ( hpid, htid, lpaddr, cb, lpb, lpdwBytesWritten );
}
XOSD
WriteBuffer (
HPID hpid,
HTID htid,
LPADDR lpaddr,
DWORD cb,
LPBYTE lpb,
LPDWORD lpdwBytesWritten
)
/*++
Routine Description:
This routine is used to send a request to the Debug Monitor to
do a write to the debuggees memory.
Arguments:
hpid - Supplies the handle to the process to write memory in
htid - Supplies a thead handle
lpaddr - Supplies debuggee address to write at
cb - Supplies the number of bytes to be written
lpb - Supplies a pointer to the buffer to write
lpdwBytesWritten - Returns number of bytes actually written
Return Value:
an XOSD error code
--*/
{
LPRWP lprwp = MHAlloc( sizeof( RWP ) + cb );
XOSD xosd;
lprwp->cb = cb;
lprwp->addr = *lpaddr;
_fmemcpy ( lprwp->rgb, lpb, cb );
xosd = SendRequestX (dmfWriteMem,
hpid,
htid,
sizeof ( RWP ) + cb,
lprwp
);
MHFree ( lprwp );
if (xosd == xosdNone) {
*lpdwBytesWritten = *((LPDWORD)(LpDmMsg->rgb));
}
//
// Notify the shell that we changed memory. An error here is not
// tragic, so we ignore the return code. The shell uses this
// notification to update all its memory breakpoints.
//
CallDB (
dbcMemoryChanged,
hpid,
NULL,
CEXM_MDL_native,
cb,
(LPV)lpaddr
);
return xosd;
} /* WriteBuffer() */
#else // OSDEBUG4
XOSD
WriteBufferCache (
HPID hpid,
HTID htid,
DWORD cb,
LPBYTE lpb
)
{
PurgeCacheHpid ( hpid );
return WriteBuffer ( hpid, htid, cb, lpb );
}
XOSD
WriteBuffer (
HPID hpid,
HTID htid,
DWORD cb,
LPBYTE lpb
)
/*++
Routine Description:
This routine is used to send a request to the Debug Monitor to
do a write to the debuggees memory.
Arguments:
hpid - Supplies the handle to the process to write memory in
htid - Supplies a thead handle
cb - Supplies the number of bytes to be written
lpb - Supplies a pointer to the buffer to write
Return Value:
an XOSD error code
--*/
{
LPRWP lprwp = MHAlloc ( sizeof ( RWP ) + cb );
ADDR addr;
XOSD xosd;
GetAddr ( hpid, htid, adrCurrent, &addr );
lprwp->cb = (WORD) cb;
lprwp->addr = addr;
_fmemcpy ( lprwp->rgb, lpb, cb );
xosd = SendRequestX (
dmfWriteMem,
hpid,
htid,
sizeof ( RWP ) + cb,
lprwp
);
MHFree ( lprwp );
//
// Notify the shell that we changed memory. An error here is not
// tragic, so we ignore the return code. The shell uses this
// notification to update all its memory breakpoints.
//
CallDB (
dbcChangedMemory,
hpid,
NULL,
CEXM_MDL_native,
0,
(LPV)cb
);
return xosd;
} /* WriteBuffer() */
#endif
XOSD
UpdateChild (
HPID hpid,
HTID htid,
DMF dmfCommand
)
/*++
Routine Description:
This function is used to cause registers to be written back to
the child as necessary before the child is executed.
Arguments:
hprc - Supplies a process handle
hthdExec - Supplies the handle of the thread to update
dmfCommand - Supplies the command about to be executed.
Return Value:
XOSD error code
--*/
{
HPRC hprc;
HTHD hthd;
HTHD hthdExec;
XOSD xosd = xosdNone;
HLLI llthd;
LPPRC lpprc;
PST pst;
hprc = HprcFromHpid(hpid);
hthdExec = HthdFromHtid(hprc, htid);
llthd = LlthdFromHprc ( hprc );
xosd = ProcessStatus(hpid, &pst);
if (xosd != xosdNone) {
return xosd;
}
if (pst.dwProcessState == pstDead || pst.dwProcessState == pstExited) {
return xosdInvalidProc;
} else if (pst.dwProcessState != pstRunning) {
for ( hthd = LLNext ( llthd, hthdNull );
hthd != hthdNull;
hthd = LLNext ( llthd, hthd ) ) {
LPTHD lpthd = LLLock ( hthd );
if ( lpthd->drt & (drtCntrlDirty | drtAllDirty) ) {
assert(lpthd->drt & drtAllPresent);
SendRequestX (dmfWriteReg,
hpid,
lpthd->htid,
sizeof ( CONTEXT ),
&lpthd->regs
);
lpthd->drt &= ~(drtCntrlDirty | drtAllDirty);
}
if ( lpthd->drt & drtSpecialDirty ) {
assert(lpthd->drt & drtSpecialPresent);
if (lpthd->dwcbSpecial) {
#ifdef TARGET_i386
((PKSPECIAL_REGISTERS)(lpthd->pvSpecial))->KernelDr0 =
lpthd->regs.Dr0;
((PKSPECIAL_REGISTERS)(lpthd->pvSpecial))->KernelDr1 =
lpthd->regs.Dr1;
((PKSPECIAL_REGISTERS)(lpthd->pvSpecial))->KernelDr2 =
lpthd->regs.Dr2;
((PKSPECIAL_REGISTERS)(lpthd->pvSpecial))->KernelDr3 =
lpthd->regs.Dr3;
((PKSPECIAL_REGISTERS)(lpthd->pvSpecial))->KernelDr6 =
lpthd->regs.Dr6;
((PKSPECIAL_REGISTERS)(lpthd->pvSpecial))->KernelDr7 =
lpthd->regs.Dr7;
#endif
SendRequestX(dmfWriteRegEx,
hpid,
lpthd->htid,
lpthd->dwcbSpecial,
lpthd->pvSpecial
);
} else {
#ifdef TARGET_i386
DWORD DR[6];
DR[0] = lpthd->regs.Dr0;
DR[1] = lpthd->regs.Dr1;
DR[2] = lpthd->regs.Dr2;
DR[3] = lpthd->regs.Dr3;
DR[4] = lpthd->regs.Dr6;
DR[5] = lpthd->regs.Dr7;
SendRequestX (dmfWriteRegEx,
hpid,
lpthd->htid,
sizeof ( DR ),
DR
);
#endif
}
lpthd->drt &= ~drtSpecialDirty;
}
lpthd->fRunning = TRUE;
LLUnlock ( hthd );
if ( xosd != xosdNone ) {
break;
}
}
lpprc = (LPPRC) LLLock(hprc);
lpprc->fRunning = TRUE;
LLUnlock(hprc);
}
return xosd;
}
#ifndef OSDEBUG4
XOSD
Freeze (
HPID hpid,
HTID htid
)
{
HTHD hthd;
HPRC hprc = ValidHprcFromHpid(hpid);
if (!hprc) {
return xosdInvalidProc;
}
if ( (hthd = HthdFromHtid(hprc, htid)) == hthdInvalid || hthd == hthdNull ) {
return xosdInvalidTID;
}
SendRequest ( dmfFreeze, hpid, htid);
return LpDmMsg->xosdRet;
}
XOSD
Thaw (
HPID hpid,
HTID htid
)
{
HTHD hthd;
HPRC hprc = ValidHprcFromHpid(hpid);
if (!hprc) {
return xosdInvalidProc;
}
if ( (hthd = HthdFromHtid(hprc, htid)) == hthdInvalid || hthd == hthdNull ) {
return xosdInvalidTID;
}
SendRequest ( dmfResume, hpid, htid);
return LpDmMsg->xosdRet;
}
#endif // !OSDEBUG4
typedef struct _EMIC {
HEMI hemi;
WORD sel;
HPID hpid;
} EMIC; // EMI cache item
#define cemicMax 4
EMIC rgemic [ cemicMax ] = {0};
XOSD
FindEmi (
HPID hpid,
LPADDR lpaddr
)
{
XOSD xosd = xosdNone;
WORD sel = GetAddrSeg ( *lpaddr );
HPRC hprc = HprcFromHpid(hpid);
HLLI llmdi = LlmdiFromHprc ( hprc );
BOOL fFound = FALSE;
ULONG iobj = 0;
HMDI hmdi;
LPPRC lpprc = LLLock( hprc );
if ((lpprc->dmi.fAlwaysFlat) || (sel == lpprc->selFlatCs) || (sel == lpprc->selFlatDs)) {
ADDR_IS_FLAT(*lpaddr) = TRUE;
}
LLUnlock( hprc );
for ( hmdi = LLNext ( llmdi, hmdiNull );
hmdi != hmdiNull;
hmdi = LLNext ( llmdi, hmdi ) ) {
LPMDI lpmdi = LLLock ( hmdi );
LPOBJD rgobjd;
if (ADDR_IS_FLAT(*lpaddr) && (!ADDR_IS_LI(*lpaddr))) {
if (GetAddrOff(*lpaddr) < lpmdi->lpBaseOfDll ||
GetAddrOff(*lpaddr) >= lpmdi->lpBaseOfDll+lpmdi->dwSizeOfDll) {
//
// can't be in this dll so look at the next one
//
LLUnlock ( hmdi );
continue;
}
}
if (lpmdi && lpmdi->cobj == -1) {
if (GetSectionObjectsFromDM( hpid, lpmdi ) != xosdNone) {
// can't do it now; punt with hpid.
break;
}
}
rgobjd = &lpmdi->rgobjd[0];
for ( iobj = 0; iobj < lpmdi->cobj; iobj++ ) {
if (((lpmdi->fFlatMode && ADDR_IS_FLAT(*lpaddr)) ||
(rgobjd[iobj].wSel == sel) && !ADDR_IS_FLAT(*lpaddr)) &&
(rgobjd[iobj].offset <= GetAddrOff(*lpaddr)) &&
(GetAddrOff(*lpaddr) < rgobjd[iobj].offset + rgobjd[iobj].cb)) {
fFound = TRUE;
break;
}
}
LLUnlock ( hmdi );
// This break is here instead of in the "for" condition so
// that hmdi does not get advanced before we break
if ( fFound ) {
break;
}
}
if ( !fFound ) {
emiAddr ( *lpaddr ) = (HEMI) hpid;
} else {
emiAddr ( *lpaddr ) = (HEMI) HemiFromHmdi ( hmdi );
if ( LLNext ( llmdi, hmdiNull ) != hmdi ) {
// put the most recent hit at the head
// this is an optimization to speed up the fixup/unfixup process
LLRemove ( llmdi, hmdi );
LLAddHead ( llmdi, hmdi );
}
}
assert ( emiAddr ( *lpaddr ) != 0 );
return xosd;
}
#pragma optimize ("", off)
XOSD
SetEmiFromCache (
HPID hpid,
LPADDR lpaddr
)
{
XOSD xosd = xosdContinue;
#ifndef TARGET32
int iemic;
for ( iemic = 0; iemic < cemicMax; iemic++ ) {
if ( rgemic [ iemic ].hpid == hpid &&
rgemic [ iemic ].sel == GetAddrSeg ( *lpaddr ) ) {
if ( iemic != 0 ) {
EMIC emic = rgemic [ iemic ];
int iemicT;
for ( iemicT = iemic - 1; iemicT >= 0; iemicT-- ) {
rgemic [ iemicT + 1 ] = rgemic [ iemicT ];
}
rgemic [ 0 ] = emic;
}
xosd = xosdNone;
emiAddr ( *lpaddr ) = rgemic [ 0 ].hemi;
assert ( emiAddr ( *lpaddr ) != 0 );
break;
}
}
#else
Unreferenced( hpid );
Unreferenced( lpaddr );
#endif // !TARGET32
return xosd;
}
#pragma optimize ("", on)
XOSD
SetCacheFromEmi (
HPID hpid,
LPADDR lpaddr
)
{
int iemic;
assert ( emiAddr ( *lpaddr ) != 0 );
for ( iemic = cemicMax - 2; iemic >= 0; iemic-- ) {
rgemic [ iemic + 1 ] = rgemic [ iemic ];
}
rgemic [ 0 ].hpid = hpid;
rgemic [ 0 ].hemi = emiAddr ( *lpaddr );
rgemic [ 0 ].sel = GetAddrSeg ( *lpaddr );
return xosdNone;
}
/*** CleanCacheOfEmi
*
* Purpose:
* To purge the emi cache
*
* Notes:
* The emi cache must be purged whenever a RegisterEmi
* is done. Unpredicable results can occur otherwise.
*
*/
XOSD
CleanCacheOfEmi (
void
)
{
int iemic;
for ( iemic = 0; iemic < cemicMax; iemic++ ) {
rgemic [ iemic ].hpid = NULL;
rgemic [ iemic ].sel = 0;
}
return xosdNone;
}
XOSD
SetEmi (
HPID hpid,
LPADDR lpaddr
)
{
XOSD xosd = xosdNone;
if ( emiAddr ( *lpaddr ) == 0 ) {
//if (ADDR_IS_REAL(*lpaddr)) {
// emiAddr( *lpaddr ) = (HEMI) hpid;
// return xosd;
//}
if ( ( xosd = SetEmiFromCache ( hpid, lpaddr ) ) == xosdContinue ) {
xosd = FindEmi ( hpid, lpaddr );
if ( xosd == xosdNone ) {
SetCacheFromEmi ( hpid, lpaddr );
}
}
assert ( emiAddr ( *lpaddr ) != 0 );
}
return xosd;
}
XOSD
GetRegValue (
HPID hpid,
HTID htid,
DWORD ireg,
LPV lpvRegValue
)
{
HPRC hprc;
HTHD hthd;
LPTHD lpthd;
LPPRC lpprc;
LPCONTEXT lpregs;
hprc = ValidHprcFromHpid(hpid);
if (!hprc) {
#ifdef OSDEBUG4
return xosdBadProcess;
#else
return xosdInvalidProc;
#endif
}
hthd = HthdFromHtid(hprc, htid);
assert ( hthd != hthdNull );
lpthd = LLLock ( hthd );
lpprc = (LPPRC) LLLock( hprc );
lpregs = &lpthd->regs;
if (lpthd->fRunning) {
UpdateRegisters( lpthd->hprc, hthd );
UpdateSpecialRegisters( lpthd->hprc, hthd );
} else {
if ( !(lpthd->drt & drtAllPresent) ) {
switch ( ireg ) {
#ifdef TARGET_i386
case CV_REG_CS:
case CV_REG_IP:
case CV_REG_SS:
case CV_REG_BP:
case CV_REG_EIP:
case CV_REG_EBP:
#endif
#ifdef TARGET_MIPS
case CV_M4_Fir:
case CV_M4_IntSP:
#endif
#ifdef TARGET_ALPHA
case CV_ALPHA_Fir:
case CV_ALPHA_IntSP:
#endif
#ifdef TARGET_PPC
case CV_PPC_PC:
case CV_PPC_GPR1:
#endif
if (!(lpthd->drt & drtCntrlPresent)) {
UpdateRegisters( lpthd->hprc, hthd );
}
break;
default:
UpdateRegisters ( lpthd->hprc, hthd );
break;
}
}
if ( !(lpthd->drt & drtSpecialPresent) ) {
switch ( ireg ) {
#ifdef TARGET_i386
case CV_REG_GDTR:
case CV_REG_GDTL:
case CV_REG_IDTR:
case CV_REG_IDTL:
case CV_REG_LDTR:
case CV_REG_TR:
case CV_REG_CR0:
case CV_REG_CR1:
case CV_REG_CR2:
case CV_REG_CR3:
case CV_REG_CR4:
case CV_REG_DR0:
case CV_REG_DR1:
case CV_REG_DR2:
case CV_REG_DR3:
case CV_REG_DR4:
case CV_REG_DR5:
case CV_REG_DR6:
case CV_REG_DR7:
UpdateSpecialRegisters( lpthd->hprc, hthd );
break;
#endif
default:
break;
}
}
}
#ifdef TARGET_i386
if (lpprc->dmi.fAlwaysFlat || lpthd->regs.SegCs == lpprc->selFlatCs) {
lpthd->fFlat = lpthd->fOff32 = TRUE;
lpthd->fReal = FALSE;
} else {
/*
* BUGBUG -- jimsch -- some one might eventually catch on
* that this is incorrect. We are not checking to see if the
* current address is really a 16-bit WOW address but assuming
* that it is. This will be a problem for people who are doing
* real 16:32 programming (on WOW) and people who are doing
* real mode program -- but so what
*/
lpthd->fFlat = lpthd->fOff32 = lpthd->fReal = FALSE;
}
#else
lpthd->fFlat = lpthd->fOff32 = TRUE;
lpthd->fReal = FALSE;
#endif
switch ( ireg ) {
#ifdef TARGET_i386
case CV_REG_GDTR:
case CV_REG_GDTL:
case CV_REG_IDTR:
case CV_REG_IDTL:
case CV_REG_LDTR:
case CV_REG_TR:
case CV_REG_CR0:
case CV_REG_CR1:
case CV_REG_CR2:
case CV_REG_CR3:
case CV_REG_CR4:
lpregs = lpthd->pvSpecial;
break;
#endif
default:
break;
}
LLUnlock( hprc );
LLUnlock( hthd );
if (lpregs) {
lpvRegValue = DoGetReg ( lpregs, ireg & 0xff, lpvRegValue );
} else {
lpvRegValue = NULL;
}
if ( lpvRegValue != NULL ) {
ireg = ireg >> 8;
if ( ireg != CV_REG_NONE ) {
lpvRegValue = DoGetReg ( lpregs, ireg, lpvRegValue );
}
}
if ( lpvRegValue == NULL ) {
#ifdef OSDEBUG4
return xosdInvalidParameter;
#else
return xosdInvalidRegister;
#endif
}
return xosdNone;
} /* GetRegValue */
XOSD
SetRegValue (
HPID hpid,
HTID htid,
DWORD ireg,
LPV lpvRegValue
)
{
XOSD xosd = xosdNone;
HPRC hprc;
HTHD hthd;
LPTHD lpthd;
LPVOID lpregs = NULL;
hprc = ValidHprcFromHpid(hpid);
if (!hprc) {
#ifdef OSDEBUG4
return xosdBadProcess;
#else
return xosdInvalidProc;
#endif
}
hthd = HthdFromHtid(hprc, htid);
assert ( hthd != hthdNull );
lpthd = LLLock ( hthd );
switch ( ireg ) {
#ifdef TARGET_i386
case CV_REG_GDTR:
case CV_REG_GDTL:
case CV_REG_IDTR:
case CV_REG_IDTL:
case CV_REG_LDTR:
case CV_REG_TR:
case CV_REG_CR0:
case CV_REG_CR1:
case CV_REG_CR2:
case CV_REG_CR3:
case CV_REG_CR4:
lpregs = &lpthd->pvSpecial;
// fall thru
case CV_REG_DR0:
case CV_REG_DR1:
case CV_REG_DR2:
case CV_REG_DR3:
case CV_REG_DR4:
case CV_REG_DR5:
case CV_REG_DR6:
case CV_REG_DR7:
if (!(lpthd->drt & drtSpecialPresent)) {
UpdateSpecialRegisters( lpthd->hprc, hthd );
}
break;
#endif
default:
lpregs = &lpthd->regs;
if ( !(lpthd->drt & drtAllPresent) ) {
UpdateRegisters ( lpthd->hprc, hthd );
}
break;
}
lpvRegValue = DoSetReg ( lpregs, ireg & 0xff, lpvRegValue );
if ( lpvRegValue == NULL ) {
LLUnlock ( hthd );
#ifdef OSDEBUG4
return xosdInvalidParameter;
#else
return xosdInvalidRegister;
#endif
}
ireg = ireg >> 8;
if ( ireg != 0 ) {
lpvRegValue = DoSetReg ( lpregs, ireg, lpvRegValue );
}
if ( lpvRegValue == NULL ) {
LLUnlock ( hthd );
#ifdef OSDEBUG4
return xosdInvalidParameter;
#else
return xosdInvalidRegister;
#endif
}
switch ( ireg ) {
#ifdef TARGET_i386
case CV_REG_GDTR:
case CV_REG_GDTL:
case CV_REG_IDTR:
case CV_REG_IDTL:
case CV_REG_LDTR:
case CV_REG_TR:
case CV_REG_CR0:
case CV_REG_CR1:
case CV_REG_CR2:
case CV_REG_CR3:
case CV_REG_CR4:
case CV_REG_DR0:
case CV_REG_DR1:
case CV_REG_DR2:
case CV_REG_DR3:
case CV_REG_DR4:
case CV_REG_DR5:
case CV_REG_DR6:
case CV_REG_DR7:
lpthd->drt |= drtSpecialDirty;
break;
#endif
default:
lpthd->drt |= drtAllDirty;
break;
}
LLUnlock ( hthd );
return xosd;
}
#ifndef OSDEBUG4
/*++
Routine Description:
This routine sets the frame context.
Arguments:
hpid - handle for the process
htid - handle for the thread
frame - the frame number. The current frame is 0; caller is 1.
Return value:
xosd.
--*/
XOSD
SetFrameContext(
HPID hpid,
HTID htid,
DWORD frame
)
{
HPRC hprc;
HTHD hthd;
LPTHD lpthd;
hprc = ValidHprcFromHpid(hpid);
if (!hprc) {
return xosdInvalidProc;
}
hthd = HthdFromHtid(hprc, htid);
assert ( hthd != hthdNull );
assert ( (INT)frame > INVALID_FRAME );
lpthd = LLLock ( hthd );
lpthd->frameNumber = frame;
//
// If the frame to use is not the current frame,
// retrieve its registers into frameRegs
//
if ( frame != CURRENT_FRAME ) {
SendRequestX ( dmfReadFrameReg,
HpidFromHprc ( hprc ),
HtidFromHthd ( hthd ),
sizeof (frame),
&frame );
_fmemcpy ( &lpthd->frameRegs,
&((PFRAME_INFO)LpDmMsg->rgb)->frameRegs,
sizeof ( lpthd->frameRegs) );
_fmemcpy ( &lpthd->frameRegPtrs,
&((PFRAME_INFO)LpDmMsg->rgb)->frameRegPtrs,
sizeof (lpthd->frameRegPtrs) );
}
LLUnlock( hprc );
LLUnlock( hthd );
}
XOSD
SetFrameRegValue(
HPID hpid,
HTID htid,
DWORD ireg,
LPV lpvRegValue
)
{
HPRC hprc;
HTHD hthd;
LPTHD lpthd;
hprc = ValidHprcFromHpid(hpid);
if (!hprc) {
return xosdInvalidProc;
}
hthd = HthdFromHtid(hprc, htid);
assert ( hthd != hthdNull );
lpthd = LLLock ( hthd );
if (lpthd->frameNumber == CURRENT_FRAME) {
LLUnlock ( hthd );
return SetRegValue(hpid, htid, ireg, lpvRegValue);
}
//
// use the frame registers
//
lpvRegValue = DoSetFrameReg ( hpid,
htid,
lpthd,
&lpthd->frameRegPtrs,
ireg & 0xff,
lpvRegValue );
if ( lpvRegValue != NULL ) {
ireg = ireg >> 8;
if ( ireg != CV_REG_NONE ) {
lpvRegValue = DoSetFrameReg ( hpid,
htid,
lpthd,
&lpthd->frameRegPtrs,
ireg,
lpvRegValue );
}
}
LLUnlock ( hthd );
if ( lpvRegValue == NULL ) {
return xosdInvalidRegister;
}
return xosdNone;
}
XOSD
GetFrameRegValue (
HPID hpid,
HTID htid,
DWORD ireg,
LPV lpvRegValue
)
{
HPRC hprc;
HTHD hthd;
LPTHD lpthd;
hprc = ValidHprcFromHpid(hpid);
if (!hprc) {
return xosdInvalidProc;
}
hthd = HthdFromHtid(hprc, htid);
assert ( hthd != hthdNull );
lpthd = LLLock ( hthd );
if ( lpthd->frameNumber == CURRENT_FRAME ) {
LLUnlock ( hthd );
return GetRegValue(hpid, htid, ireg, lpvRegValue);
}
lpvRegValue = DoGetReg ( &lpthd->frameRegs, ireg & 0xff, lpvRegValue );
if ( lpvRegValue != NULL ) {
ireg = ireg >> 8;
if ( ireg != CV_REG_NONE ) {
lpvRegValue = DoGetReg ( &lpthd->frameRegs, ireg, lpvRegValue );
}
}
LLUnlock ( hthd );
if ( lpvRegValue == NULL ) {
return xosdInvalidRegister;
}
return xosdNone;
} /* GetFrameRegValue */
#endif // !OSDEBUG4
XOSD
SetFlagValue (
HPID hpid,
HTID htid,
DWORD iFlag,
LPV lpvRegValue
)
{
HPRC hprc;
HTHD hthd;
LPTHD lpthd;
LPCONTEXT lpregs;
LONG mask;
LONG l;
LONGLONG ll;
hprc = ValidHprcFromHpid(hpid);
if (!hprc) {
#ifdef OSDEBUG4
return xosdBadProcess;
#else
return xosdInvalidProc;
#endif
}
hthd = HthdFromHtid(hprc, htid);
assert ( hthd != hthdNull );
lpthd = LLLock( hthd );
lpregs = &lpthd->regs;
if ( !( lpthd->drt & drtAllPresent )) {
UpdateRegisters ( lpthd->hprc, hthd );
}
#ifdef OSDEBUG4
if (Rgrd[Rgfd[iFlag].fd.dwId].dwcbits > 32) {
if (DoGetReg ( lpregs, Rgfd[iFlag].fd.dwId, &ll ) == NULL) {
LLUnlock( hthd );
return xosdInvalidParameter;
}
mask = (1 << Rgfd[iFlag].fd.dwcbits) - 1;
mask <<= Rgfd[iFlag].iShift;
ll &= ~mask;
ll |= ((*((ULONG FAR *) lpvRegValue)) << Rgfd[iFlag].iShift) & mask;
DoSetReg(lpregs, Rgfd[iFlag].fd.dwId, &ll );
} else {
if (DoGetReg ( lpregs, Rgfd[iFlag].fd.dwId, &l ) == NULL) {
LLUnlock( hthd );
return xosdInvalidParameter;
}
mask = (1 << Rgfd[iFlag].fd.dwcbits) - 1;
mask <<= Rgfd[iFlag].iShift;
l &= ~mask;
l |= ((*((ULONG FAR *) lpvRegValue)) << Rgfd[iFlag].iShift) & mask;
DoSetReg(lpregs, Rgfd[iFlag].fd.dwId, &l );
}
#else
if (Rgrd[Rgfd[iFlag].fd.hReg].cbits > 32) {
if (DoGetReg ( lpregs, Rgfd[iFlag].fd.hReg, &ll ) == NULL) {
LLUnlock( hthd );
return xosdInvalidRegister;
}
mask = (1 << Rgfd[iFlag].fd.cbits) - 1;
mask <<= Rgfd[iFlag].iShift;
ll &= ~mask;
ll |= ((*((ULONG FAR *) lpvRegValue)) << Rgfd[iFlag].iShift) & mask;
DoSetReg(lpregs, Rgfd[iFlag].fd.hReg, &ll );
} else {
if (DoGetReg ( lpregs, Rgfd[iFlag].fd.hReg, &l ) == NULL) {
LLUnlock( hthd );
return xosdInvalidRegister;
}
mask = (1 << Rgfd[iFlag].fd.cbits) - 1;
mask <<= Rgfd[iFlag].iShift;
l &= ~mask;
l |= ((*((ULONG FAR *) lpvRegValue)) << Rgfd[iFlag].iShift) & mask;
DoSetReg(lpregs, Rgfd[iFlag].fd.hReg, &l );
}
#endif
lpthd->drt |= drtAllDirty;
LLUnlock ( hthd );
return xosdNone;
} /* SetFlagValue */
#ifdef OSDEBUG4
/*
Note: We are not guaranteed that the incoming address is actually
on an instruction boundary. When this happens, we derive the
boundary and send back the difference in the return value and
the address of the instruction previous to the DERIVED instruction
in the address.
Thus there are three classes of returns -
==0 - The incoming address was in fact on an instruction boundary
> 0 - The case noted above
< 0 - Error value - the most common "error" is that there is
no previous instruction.
When the return value >= 0, *lpaddr contains the address of the
previous instruction.
*/
#define doffMax 60
static HPID hpidGPI = NULL;
static BYTE rgbGPI [ doffMax ];
static ADDR addrGPI;
XOSD
GPIBuildCache (
HPID hpid,
HTID htid,
LPADDR lpaddr
)
{
XOSD xosd = xosdBadAddress;
int fFound = FALSE;
ADDR addr = *lpaddr;
ADDR addrT;
int ib = 0;
_fmemset ( rgbGPI, 0, doffMax );
addrGPI = *lpaddr;
hpidGPI = hpid;
GetAddrOff ( addr ) -= (int) min ( (UOFFSET) doffMax, GetAddrOff ( *lpaddr ) );
while ( !fFound && GetAddrOff ( addr ) < GetAddrOff ( *lpaddr ) ) {
SDI sdi;
sdi.dop = dopNone;
sdi.addr = addr;
addrT = addr;
disasm ( hpid, htid, &sdi );
addr = sdi.addr;
rgbGPI [ ib ] = (BYTE) ( GetAddrOff ( addrGPI ) - GetAddrOff ( addr ) );
if ( GetAddrOff ( addr ) == GetAddrOff ( *lpaddr ) ) {
xosd = xosdNone;
*lpaddr= addrT;
fFound = TRUE;
}
ib += 1;
}
// We haven't synced yet, so *lpaddr is probably pointing
// to something that isn't really syncronous
if ( !fFound ) {
xosd = (XOSD) ( GetAddrOff ( *lpaddr ) - GetAddrOff ( addrT ) );
GetAddrOff ( *lpaddr ) -= xosd;
if ( GetAddrOff ( *lpaddr ) != 0 ) {
(void) GetPrevInst ( hpid, htid, lpaddr );
}
}
return xosd;
}
VOID
GPIShiftCache (
LPADDR lpaddr,
int *pib
)
{
int doff = (int) ( GetAddrOff ( addrGPI ) - GetAddrOff ( *lpaddr ) );
int ib = 0;
*pib = 0;
while ( ib < doffMax && rgbGPI [ ib ] != 0 ) {
rgbGPI [ ib ] = (BYTE) max ( (int) rgbGPI [ ib ] - doff, 0 );
if ( rgbGPI [ ib ] == 0 && *pib == 0 ) {
*pib = ib;
}
ib += 1;
}
addrGPI = *lpaddr;
}
XOSD
GPIUseCache (
HPID hpid,
HTID htid,
LPADDR lpaddr
)
{
XOSD xosd = xosdBadAddress;
int fFound = FALSE;
ADDR addr = *lpaddr;
int ib = 0;
int ibCache= 0;
int ibMax = 0;
BYTE rgb [ doffMax ];
GPIShiftCache ( lpaddr, &ibMax );
_fmemset ( rgb, 0, doffMax );
GetAddrOff ( addr ) -= (int) min ( (UOFFSET) doffMax, GetAddrOff ( *lpaddr ) );
while ( !fFound && GetAddrOff ( addr ) < GetAddrOff ( *lpaddr ) ) {
ADDR addrT;
BYTE doff = (BYTE) ( GetAddrOff ( *lpaddr ) - GetAddrOff ( addr ) );
// Attempt to align with the cache
while ( doff < rgbGPI [ ibCache ] ) {
ibCache += 1;
}
if ( doff == rgbGPI [ ibCache ] ) {
// We have alignment with the cache
addr = *lpaddr;
addrT = addr;
GetAddrOff ( addrT ) -= rgbGPI [ ibMax - 1 ];
}
else {
SDI sdi;
sdi.dop = dopNone;
sdi.addr = addr;
addrT = addr;
disasm ( hpid, htid, &sdi );
addr = sdi.addr;
rgb [ ib ] = (BYTE) ( GetAddrOff ( addrGPI ) - GetAddrOff ( addr ) );
ib += 1;
}
if ( GetAddrOff ( addr ) == GetAddrOff ( *lpaddr ) ) {
xosd = xosdNone;
*lpaddr= addrT;
fFound = TRUE;
}
}
// Rebuild the cache
_fmemmove ( &rgbGPI [ ib - 1 ], &rgbGPI [ ibCache ], ibMax - ibCache );
_fmemcpy ( rgbGPI, rgb, ib - 1 );
return xosd;
}
XOSD
GetPrevInst (
HPID hpid,
HTID htid,
LPADDR lpaddr
)
{
if ( GetAddrOff ( *lpaddr ) == 0 ) {
return xosdBadAddress;
}
else if (
hpid == hpidGPI &&
GetAddrSeg ( *lpaddr ) == GetAddrSeg ( addrGPI ) &&
GetAddrOff ( *lpaddr ) < GetAddrOff ( addrGPI ) &&
GetAddrOff ( *lpaddr ) > GetAddrOff ( addrGPI ) - doffMax / 2
) {
return GPIUseCache ( hpid, htid, lpaddr );
}
else {
return GPIBuildCache ( hpid, htid, lpaddr );
}
}
#endif // OSDEBUG4
//
// Return xosdContinue if overlay is loaded
// Else return xosdNone
//
XOSD
FLoadedOverlay(
HPID hpid,
LPADDR lpaddr
)
{
XOSD xosd = xosdContinue;
#ifdef DOS16
HMDI hmdi;
LPMDI lpmdi;
LPGSI lpgsi;
WORD seg = (WORD)GetAddrSeg( *lpaddr );
assert( ADDR_IS_LI(*lpaddr) );
if ( emiAddr ( *lpaddr ) != HpidFromHprc ( hprc ) ) {
if ( hmdi = LLFind (LlmdiFromHprc ( hprc ),
wNull,
&emiAddr ( *lpaddr ),
(LONG) emdiEMI ) ) {
lpmdi = LLLock( hmdi );
// Segment is 1 based, make zero based like GSN table
--seg;
// If we've got a GSN table, make sure that the seg is in
// range. See if the GSN is an overlay. If so, andthe
// frame number if the lpsel table is zero,
// then the overlay is not loaded
if ( ( lpgsi = lpmdi->lpgsi ) && seg < lpgsi->csgMax &&
!lpgsi->rgsgi[ seg ].sgf.saAttr &&
!lpmdi->lpsel[ lpgsi->rgsgi[ seg ].iovl ] ) {
xosd = xosdNone;
LLUnlock( hmdi );
}
}
} else {
xosd = xosdNone;
}
#else
Unreferenced( hpid );
Unreferenced( lpaddr );
#endif // DOS16
return xosd;
}
XOSD
SetupExecute(
HPID hpid,
HTID htid,
LPHIND lphind
)
/*++
Routine Description:
This function is used to set up a thread for doing function evaluation.
The first thing it will do is to
Arguments:
argument-name - Supplies | Returns description of argument.
.
.
Return Value:
return-value - Description of conditions needed to return value. - or -
None.
--*/
{
HIND hind;
HTHD hthd;
HPRC hprc;
LPTHD lpthd;
LP_EXECUTE_OBJECT_EM lpeo;
XOSD xosd;
hprc = ValidHprcFromHpid(hpid);
if (!hprc) {
#ifdef OSDEBUG4
return xosdBadProcess;
#else
return xosdInvalidProc;
#endif
}
hthd = HthdFromHtid(hprc, htid);
if (!hthd || hthd == hthdInvalid) {
#ifdef OSDEBUG4
return xosdBadThread;
#else
return xosdInvalidThread;
#endif
}
/*
* If the list of execute objects has not yet been setup then it
* needs to be setup now.
*/
if (HllEo == 0) {
HllEo = LLInit(sizeof(EXECUTE_OBJECT_EM), llfNull, NULL, NULL);
}
/*
* Allocate an execute object for this working item.
*/
if ((hind = LLCreate( HllEo )) == 0) {
return xosdOutOfMemory;
}
lpeo = LLLock( hind );
/*
* Ask the DM to allocate a handle on its end for its low level
* execute object.
*/
xosd = SendRequest(dmfSetupExecute, hpid, htid );
if (xosd != xosdNone) {
LLUnlock( hind );
LLDelete( HllEo, hind );
return xosd;
}
lpeo->heoDm = *(HIND *) LpDmMsg->rgb;
/*
* Get the current register set for the thread on which we are going
* to do the exeucte.
*/
lpthd = LLLock( hthd );
lpeo->hthd = hthd;
if (!( lpthd->drt & drtAllPresent )) {
UpdateRegisters( hprc, hthd );
}
_fmemcpy( &lpeo->regs, &lpthd->regs, sizeof( CONTEXT ));
LLUnlock( hthd );
/*
* Unlock the execute object and return its handle
*/
LLUnlock( hind );
*lphind = hind;
return xosdNone;
} /* SetupExecute() */
XOSD
StartExecute(
HPID hpid,
HIND hind,
LPEXECUTE_STRUCT lpes
)
/*++
Routine Description:
description-of-function.
Arguments:
argument-name - Supplies | Returns description of argument.
.
.
Return Value:
return-value - Description of conditions needed to return value. - or -
None.
--*/
{
XOSD xosd;
LP_EXECUTE_OBJECT_EM lpeo;
HTHD hthd;
HTID htid;
HPRC hprc;
hprc = ValidHprcFromHpid(hpid);
if (!hprc) {
#ifdef OSDEBUG4
return xosdBadProcess;
#else
return xosdInvalidProc;
#endif
}
lpeo = LLLock( hind );
hthd= lpeo->hthd;
htid = HtidFromHthd(hthd),
lpes->hindDm = lpeo->heoDm;
FixupAddr(hpid, &lpes->addr);
LLUnlock( hind );
/*
* Cause any changes to registers to be written back
*/
UpdateChild(hpid, htid, dmfGo);
/*
* Issue the command to the DM
*/
xosd = SendRequestX(dmfStartExecute, hpid, htid,
sizeof(EXECUTE_STRUCT), lpes);
return xosd;
} /* StartExecute() */
XOSD
CleanUpExecute(
HPID hpid,
HIND hind
)
/*++
Routine Description:
description-of-function.
Arguments:
argument-name - Supplies | Returns description of argument.
.
.
Return Value:
return-value - Description of conditions needed to return value. - or -
None.
--*/
{
LPTHD lpthd;
LP_EXECUTE_OBJECT_EM lpeo;
lpeo = LLLock( hind );
lpthd = LLLock( lpeo->hthd );
_fmemcpy( &lpthd->regs, &lpeo->regs, sizeof( CONTEXT ));
lpthd->drt = drtAllPresent | drtCntrlPresent | drtAllDirty | drtCntrlDirty;
SendRequestX(dmfCleanUpExecute, hpid, HtidFromHthd(lpeo->hthd),
sizeof(HIND), &lpeo->heoDm);
LLUnlock( (lpeo->hthd) );
LLUnlock( hind );
LLDelete( HllEo, hind );
return xosdNone;
} /* CleanUpExecute() */
#ifndef OSDEBUG4
XOSD
DoCustomCommand(
HPID hpid,
HTID htid,
DWORD wValue,
LPIOL lpiol
)
{
LPSTR lpsz = lpiol->rgbVar;
LPSTR p;
XOSD xosd;
char cmd[256];
//
// parse the command from the command line
//
p = cmd;
while (*lpsz && !isspace(*lpsz)) {
*p++ = *lpsz++;
}
*p = '\0';
//
// this is where you would _stricmp() for your custom em command
// otherwise it is passed to the dm
//
return SendRequestX( dmfIOCTL, hpid, htid, wValue, (LPV) lpiol );
//
// this is what would be executed if you have a custom em command
// instead of the above sendrequest()
//
strcpy( lpiol->rgbVar, lpsz );
xosd = IoctlCmd(hpid, htid, wValue, lpiol);
return xosd;
} /* DoCustomCommand */
XOSD
IoctlCmd(
HPID hpid,
HTID htid,
DWORD wValue,
LPIOL lpiol
)
/*++
Routine Description:
This function examines IOCTL requests (escapes) and deal with
those which the EM knows about. All others are pass on to the
DM for later processing.
Arguments:
argument-name - Supplies | Returns description of argument.
.
.
Return Value:
return-value - Description of conditions needed to return value. - or -
None.
--*/
{
XOSD xosd;
HANDLE * ph;
switch( lpiol-> wFunction ) {
case ioctlGetProcessHandle:
case ioctlGetThreadHandle:
ph = *((HANDLE **) lpiol->rgbVar);
xosd = SendRequestX( dmfIOCTL, hpid, htid, wValue, lpiol );
*ph = *((HANDLE *) LpDmMsg->rgb);
return xosd;
case ioctlGetThreadContext:
return DoGetContext(hpid, htid, lpiol->rgbVar);
case ioctlSetThreadContext:
return DoSetContext(hpid, htid, lpiol->rgbVar);
case ioctlCustomCommand:
return DoCustomCommand(hpid, htid, wValue, lpiol);
case ioctlGeneric:
xosd = SendRequestX( dmfIOCTL, hpid, htid, wValue, (LPV) lpiol );
memcpy ( (LPVOID)lpiol->rgbVar, LpDmMsg->rgb, wValue-sizeof(IOL) );
return xosd;
default:
return SendRequestX( dmfIOCTL, hpid, htid, wValue, (LPV) lpiol );
}
}
XOSD
DebugActive(
HPID hpid,
HTID htid,
LPDBG_ACTIVE_STRUCT lpdba
)
{
XOSD xosd = SendRequestX(dmfDebugActive, hpid, htid, sizeof(*lpdba), lpdba);
if (xosd != xosdNone) {
lpdba->dwStatus = 0;
} else {
lpdba->dwStatus = *((DWORD *) LpDmMsg->rgb );
}
return xosd;
}
XOSD
GetModuleList(
HPID hpid,
HTID htid,
LPMODULE_LIST_REQUEST Request
)
{
XOSD xosd;
HLLI llmdi;
HMDI hmdi;
LPMDI lpmdi;
DWORD Count;
LPMODULE_LIST ModList;
LPMODULE_LIST TmpList;
LPMODULE_ENTRY Entry;
LDT_ENTRY Ldt;
DWORD MaxSize;
DWORD Size;
DWORD Delta;
DWORD i;
SEGMENT Selector;
DWORD Base;
DWORD Limit;
OBJD *ObjD;
if ( !Request || !(Request->List) ) {
return xosdInvalidParameter;
}
*(Request->List) = NULL;
llmdi = LlmdiFromHprc( HprcFromHpid ( hpid ));
if ( !llmdi ) {
return xosdInvalidProc;
}
//
// Estimate the list size, to minimize the calls to realloc.
//
hmdi = hmdiNull;
Count = 0;
while ( (hmdi = LLNext( llmdi, hmdi )) != hmdiNull ) {
lpmdi = LLLock( hmdi );
// No boolean xor operator in C...
if ( !(lpmdi->fFlatMode) == !(Request->Flat) ) {
Count += lpmdi->fFlatMode ? 1 : lpmdi->cobj;
}
LLUnlock( hmdi );
}
//
// Allocate the list
//
MaxSize = sizeof(MODULE_LIST) + Count * sizeof(MODULE_ENTRY);
ModList = malloc( MaxSize );
if ( !ModList ) {
return xosdOutOfMemory;
}
//
// Build the list
//
hmdi = hmdiNull;
Count = 0;
Size = sizeof(MODULE_LIST);
while ( (hmdi = LLNext( llmdi, hmdi )) != hmdiNull ) {
lpmdi = LLLock( hmdi );
if (lpmdi && lpmdi->cobj == -1) {
if (GetSectionObjectsFromDM( hpid, lpmdi ) != xosdNone) {
continue;
}
}
// No boolean xor operator in C...
if ( !(lpmdi->fFlatMode) == !(Request->Flat) ) {
Delta = lpmdi->fFlatMode ? 1 : lpmdi->cobj;
//
// Reallocate buffer if necessary
//
if ( Size + Delta * sizeof(MODULE_ENTRY) > MaxSize ) {
Size += Delta * sizeof(MODULE_ENTRY);
TmpList = realloc( ModList, Size );
if ( !TmpList ) {
FreeModuleList(ModList);
return xosdOutOfMemory;
}
ModList = TmpList;
}
//
// have buffer, fill it up
//
if ( lpmdi->fFlatMode ) {
Entry = NthModuleEntry(ModList,Count);
ModuleEntryFlat(Entry) = TRUE;
ModuleEntrySegment(Entry) = 0;
ModuleEntrySelector(Entry) = 0;
ModuleEntryBase(Entry) = lpmdi->lpBaseOfDll;
ModuleEntryLimit(Entry) = lpmdi->dwSizeOfDll;
if (lpmdi->lpDebug) {
ModuleEntryType(Entry) = (DWORD) lpmdi->lpDebug->she;
} else {
ModuleEntryType(Entry) = 0;
}
ModuleEntrySectionCount(Entry) = lpmdi->cobj;
ModuleEntryHexe(Entry) = (HEXE)lpmdi->hemi;
Count++;
} else {
for ( i=0, ObjD = lpmdi->rgobjd;
i < Delta;
i++, ObjD++ ) {
if ( ObjD->wSel ) {
Selector = ObjD->wSel;
Entry = NthModuleEntry(ModList,Count);
ModuleEntrySegment(Entry) = i+1;
ModuleEntrySelector(Entry) = Selector;
ModuleEntryType(Entry) = 0;
ModuleEntrySectionCount(Entry) = 0;
ModuleEntryHexe(Entry) = (HEXE)lpmdi->hemi;
if ( lpmdi->fRealMode ) {
ModuleEntryFlat(Entry) = FALSE;
ModuleEntryReal(Entry) = TRUE;
ModuleEntryBase(Entry) = 0xBAD00BAD;
ModuleEntryLimit(Entry) = 0xBAD00BAD;
Count++;
} else {
xosd = SendRequestX( dmfQuerySelector,
hpid,
htidNull,
sizeof(SEGMENT),
&Selector );
if (xosd == xosdNone) {
_fmemcpy( &Ldt, LpDmMsg->rgb, sizeof(Ldt));
Base = (Ldt.HighWord.Bits.BaseHi << 0x18) |
(Ldt.HighWord.Bits.BaseMid << 0x10) |
Ldt.BaseLow;
Limit = (Ldt.HighWord.Bits.LimitHi << 0x10) |
Ldt.LimitLow;
ModuleEntryFlat(Entry) = FALSE;
ModuleEntryReal(Entry) = FALSE;
ModuleEntryBase(Entry) = Base;
ModuleEntryLimit(Entry) = Limit;
Count++;
} else {
ModuleEntryFlat(Entry) = FALSE;
ModuleEntryReal(Entry) = FALSE;
ModuleEntryBase(Entry) = 0xBAD00BAD;
ModuleEntryLimit(Entry) = 0xBAD00BAD;
Count++;
}
}
}
}
}
}
LLUnlock( hmdi );
}
ModuleListCount(ModList) = Count;
*(Request->List) = ModList;
return xosdNone;
}
XOSD
GetMemInfo(
HPID hpid,
DWORD cbSize,
LPMEMINFO lpmi
)
{
PMEMORY_BASIC_INFORMATION lpmbi;
ADDR addr;
XOSD xosd = xosdNone;
assert(cbSize == sizeof(MEMINFO));
addr = lpmi->addr;
if (ADDR_IS_LI(addr)) {
xosd = FixupAddr(hpid, &addr);
}
if (xosd == xosdNone) {
xosd = SendRequestX( dmfVirtualQuery, hpid, 0, sizeof(ADDR), (LPV)&addr );
}
if (xosd == xosdNone) {
lpmbi = (PMEMORY_BASIC_INFORMATION) LpDmMsg->rgb;
lpmi->addrAllocBase = addr;
lpmi->addrAllocBase.addr.off = (UOFF32)lpmbi->AllocationBase;
lpmi->uRegionSize = (UOFF32)lpmbi->RegionSize;
lpmi->dwProtect = lpmbi->Protect;
lpmi->dwState = lpmbi->State;
lpmi->dwType = lpmbi->Type;
}
return xosd;
}
#endif // !OSDEBUG4
XOSD FAR PASCAL
EMFunc (
EMF emf,
HPID hpid,
HTID htid,
DWORD wValue,
LONG lValue
)
/*++
Routine Description:
This is the main dispatch routine for processing of commands to the
execution model.
Arguments:
emf - Supplies the function to be performed. (Execution Model Function )
hpid - Supplies The process to be used.
htid - Supplies The thread to be used.
wValue - Supplies Info about the command
lValue - Supplies Info about the command
Return Value:
returns an XOSD error code
Other:
Hpid and htid can never be invalid. In some cases, they can be
null. The entries under P and T marked with an 0 indicate that
the null value is valid for this function, an X indicates that
it is invalid.
Brief descriptions of the wValue and lValue
EMF P T WVALUE LVALUE
emfGo X X ---- ----
emfShowDebuggee X 0 ---- ----
emfStop X 0 ---- ----
emfWriteBuf X 0 #of bytes pointer to buffer
emfReadBuf X 0 #of bytes pointer to buffer
emfSingleStep X X ---- -----
emfStepOver X X ---- ----
emfSetBreakPoint X X ---- ----
emfRemoveBreakPoint X X ---- ----
emfSetWatchPoint X X ---- ----
emfRemoveWatchPoint X X ---- ----
emfRangeStep,
emfRangeOver,
emfThreadStatus X X ---- pointer to status buf.
emfProcStatus X X ---- pointer to status buf.
emfFreeze X X ---- ----
emfThaw X X ---- ----
emfRegisterDBF 0 0 ---- pointer to dbf
emfInit 0 0 ---- pointer to em serv.
emfUnInit 0 0 ---- ----
emfCreatePid X 0 ---- ----
emfDestroyPid X 0 ---- ----
emfDestroyTid X X ---- ----
emfDestroy 0 0 hem ----
emfIsValid X X hem ----
emfSetAddr X X ---- pointer to addr
emfGetAddr X X ---- pointer to addr
emfRegValue X X register index pointer to buffer
emfSetReg X X register index pointer to buffer
emfSetFrameContext X X frame
emfFrameRegValue X X register index pointer to buffer
emfFrameSetReg X X register index pointer to buffer
emfProgramLoad X 0 length pntr to cmd line
emfProgramFree X 0 ---- ----
emfDebugPacket X X ---- pointer to buffer
emfMetric X 0 ---- pointer to metric
emfUnassemble X X ---- pointer to buffer
emfAssemble X X ---- pointer to buffer
emfGetObjLength X X ---- pointer to addr
emfIOCTL X X IOCTL type pointer to data
emfGetRegStruct 0 0 register index pointer to buffer
emfGetFlagStruct 0 0 flag index pointer to buffer
emfGetFlag X X flag index pointer to buffer
emfSetFlag X X flag index pointer to data
emfIsStackSetup X X ---- pointer to addr
emfCompareAddr ? ? ---- pointerr to rglpaddr[2]
emfSetupExecute X X ---- pointer to handle
emfStartExecute X - Handle pointer to execute_struct
emfCleanUpExecute X 0 Handle -----
emfLoadDllAck X 0 ---- -----
emfUnLoadDllAck X 0 ---- pointer to MDI
emfAttach X 0 ----
emfStackWalkSetup X X PC In Prolog pointer to stack walk data
emfStackWalkNext X X ---- pointer to stack walk data
emfStackWalkCleanup X X ---- pointer to stack walk data
emfDebugActive X 0 ---- LPDBG_ACTIVE_STRUCT
emfConnect X 0 ---- ----
emfDisconnect X 0 ---- ----
emfEnableCache X 0 ---- ----
emfGetMemInfo X 0 sizeof MEMINFO LPMEMINFO
emfGetFunctionInfo X 0 PADDR PFUNCTION_INFO
--*/
{
XOSD xosd = xosdNone;
ValidateHeap();
switch ( emf ) {
case emfShowDebuggee :
xosd = SendRequestX ( dmfSelect, hpid, htid, sizeof ( BOOL ), &wValue );
break;
case emfStop:
xosd = SendRequestX ( dmfStop, hpid, htid, sizeof( BOOL ), &wValue );
break;
case emfRegisterDBF:
InitUsage ( );
lpdbf = (LPDBF) lValue;
break;
case emfInit:
llprc = LLInit ( sizeof ( PRC ), llfNull, PiDKill, PDComp );
CallDB = ( (LPEMCB) lValue)->lpfnCallBackDB;
CallTL = ( (LPEMCB) lValue)->lpfnCallBackTL;
CallNT = ( (LPEMCB) lValue)->lpfnCallBackNT;
LpDmMsg = MHAlloc ( CBBUFFERDEF );
CbDmMsg = CBBUFFERDEF;
CallTL ( tlfSetBuffer, hpid, CBBUFFERDEF, LpDmMsg );
ImagehlpApiVersionEx(&ApiVersionForImagehlp);
break;
case emfUnInit:
/*
* do any uninitialization for the EM itself
*/
MHFree(LpDmMsg);
LpDmMsg = NULL;
CbDmMsg = 0;
break;
case emfSetAddr:
xosd = SetAddr ( hpid, htid, (ADR) wValue, (LPADDR) lValue );
break;
case emfGetAddr:
xosd = GetAddr ( hpid, htid, (ADR) wValue, (LPADDR) lValue );
break;
case emfProgramLoad:
xosd = ProgramLoad ( hpid, wValue, (LPPRL) lValue );
break;
case emfProgramFree:
xosd = ProgramFree ( hpid, htid );
break;
case emfFixupAddr:
xosd = FixupAddr ( hpid, (LPADDR) lValue );
break;
case emfUnFixupAddr:
xosd = UnFixupAddr ( hpid, (LPADDR) lValue );
break;
case emfSetEmi:
xosd = SetEmi ( hpid, (LPADDR) lValue );
break;
case emfMetric:
xosd = DebugMetric ( hpid, htid, wValue, (LPLONG) lValue );
break;
case emfDebugPacket: {
LPRTP lprtp = (LPRTP) lValue;
xosd = DebugPacket (
lprtp->dbc,
lprtp->hpid,
lprtp->htid,
lprtp->cb,
(lprtp->cb == 0 ) ? NULL : (LPBYTE) lprtp->rgbVar
);
}
break;
case emfSetMulti:
xosd = SendRequest ( (DMF) (wValue ? dmfSetMulti : dmfClearMulti),
hpid, htid );
break;
case emfDebugger:
xosd = SendRequestX ( dmfDebugger, hpid, htid, wValue, (LPV) lValue );
break;
case emfRegisterEmi:
RegisterEmi ( hpid, (LPREMI) lValue );
break;
case emfGetModel:
*(WORD FAR *)lValue = CEXM_MDL_native;
break;
case emfGetRegStruct:
*((RD FAR *) lValue) = Rgrd[wValue];
break;
case emfGetFlagStruct:
*((FD FAR *) lValue) = Rgfd[wValue].fd;
break;
case emfGetFlag:
xosd = GetFlagValue ( hpid, htid, wValue, (LPV) lValue );
break;
case emfSetFlag:
xosd = SetFlagValue ( hpid, htid, wValue, (LPV) lValue );
break;
case emfSetupExecute:
xosd = SetupExecute(hpid, htid, (LPHIND) lValue);
break;
case emfStartExecute:
xosd = StartExecute(hpid, (HIND) wValue, (LPEXECUTE_STRUCT) lValue);
break;
case emfCleanUpExecute:
xosd = CleanUpExecute(hpid, (HIND) wValue);
break;
case emfBreakPoint:
xosd = HandleBreakpoints( hpid, wValue, lValue );
break;
case emfGo:
xosd = Go(hpid, htid, (LPEXOP)lValue);
break;
case emfSingleStep:
xosd = SingleStep ( hpid, htid, (LPEXOP)lValue );
break;
case emfRangeStep:
xosd = RangeStep(hpid, htid, (LPRSS)lValue);
break;
#if 0
case emfReturnStep:
xosd = ReturnStep(hpid, htid, (LPEXOP)lValue);
break;
#endif
case emfGetReg:
xosd = GetRegValue ( hpid, htid, wValue, (LPV) lValue );
break;
case emfSetReg:
xosd = SetRegValue ( hpid, htid, wValue, (LPV) lValue );
break;
#ifdef OSDEBUG4
case emfWriteMemory:
{
LPRWMS lprwms = (LPRWMS)lValue;
xosd = WriteBufferCache ( hpid, htid, lprwms->lpaddr, lprwms->cbBuffer,
lprwms->lpbBuffer, lprwms->lpcb);
break;
}
case emfReadMemory:
{
LPRWMS lprwms = (LPRWMS)lValue;
xosd = ReadBuffer ( hpid, htid, lprwms->lpaddr, lprwms->cbBuffer,
lprwms->lpbBuffer, lprwms->lpcb);
break;
}
case emfGetMemoryInfo:
xosd = GetMemoryInfo(hpid, htid, (LPMEMINFO)lValue);
break;
#endif
case emfProcessStatus:
xosd = ProcessStatus(hpid, (LPPST)lValue);
break;
case emfThreadStatus:
xosd = ThreadStatus(hpid, htid, (LPTST)lValue);
break;
case emfGetExceptionState:
xosd = GetExceptionState(hpid, htid, (EXCEPTION_CONTROL) wValue,
(LPEXCEPTION_DESCRIPTION) lValue);
break;
case emfSetExceptionState:
xosd = SetExceptionState(hpid, htid, (LPEXCEPTION_DESCRIPTION)lValue);
break;
#ifdef OSDEBUG4
case emfFreezeThread:
xosd = FreezeThread(hpid, htid, wValue);
break;
case emfCreateHpid:
xosd = CreateHprc ( hpid );
if ( xosd == xosdNone ) {
xosd = SendRequest ( dmfCreatePid, hpid, NULL );
}
SyncHprcWithDM( hpid );
break;
case emfDestroyHpid:
{
HPRC hprc = HprcFromHpid(hpid);
xosd = SendRequest ( dmfDestroyPid, hpid, NULL );
if ( xosd == xosdLineNotConnected ) {
//
// Communication line broke, we'll ignore this error.
//
xosd = xosdNone;
}
DestroyHprc ( hprc );
}
break;
case emfDestroyHtid:
{
HPRC hprc = HprcFromHpid(hpid);
DestroyHthd( HthdFromHtid( hprc, htid ));
}
break;
case emfUnassemble:
xosd = disasm ( hpid, htid, (LPSDI) lValue );
break;
case emfGetPrevInst:
xosd = GetPrevInst ( hpid, htid, (LPADDR) lValue );
break;
case emfAssemble:
xosd = Assemble ( hpid, htid, (LPADDR) wValue, (LPSTR) lValue );
break;
case emfDebugActive:
xosd = SendRequestX(dmfDebugActive, hpid, htid, wValue, (LPVOID)lValue);
if (xosd == xosdNone) {
xosd = LpDmMsg->xosdRet;
}
break;
case emfGetMessageMap:
*((LPMESSAGEMAP *)lValue) = &MessageMap;
break;
case emfGetMessageMaskMap:
*((LPMASKMAP *)lValue) = &MaskMap;
break;
case emfGetModuleList:
xosd = GetModuleList( hpid, htid, (LPSTR)wValue,
(LPMODULE_LIST FAR *)lValue );
break;
case emfCompareAddrs:
xosd = CompareAddrs( hpid, htid, (LPCAS) lValue );
break;
#endif // OSDEBUG4
#ifndef OSDEBUG4
case emfWriteBuf:
xosd = WriteBufferCache ( hpid, htid, wValue, (LPBYTE) lValue );
break;
case emfReadBuf:
{
DWORD cbr;
xosd = ReadBuffer ( hpid, htid, 0, wValue, (LPBYTE) lValue, &cbr );
if (xosd != xosdNone) {
cbr = 0;
}
xosd = cbr;
}
break;
case emfSetFrameContext:
xosd = SetFrameContext ( hpid, htid, wValue );
break;
case emfFrameRegValue:
xosd = GetFrameRegValue ( hpid, htid, wValue, (LPV) lValue );
break;
case emfFrameSetReg:
xosd = SetFrameRegValue ( hpid, htid, wValue, (LPV) lValue );
break;
case emfIsStackSetup:
{
ADDR addrStart = *(LPADDR)lValue;
xosd = IsStackSetup( hpid, htid, &addrStart );
}
break;
case emfStackWalkSetup:
xosd = StackWalkSetup( hpid, htid, (LPSTACKFRAME) lValue );
break;
case emfStackWalkNext:
xosd = StackWalkNext( hpid, htid, (LPSTACKFRAME) lValue );
break;
case emfStackWalkCleanup:
break;
case emfSetFrame:
xosd = SetFrame(hpid, htid, (PFRAME) lValue);
break;
case emfIOCTL:
xosd = IoctlCmd( hpid, htid, wValue, (LPIOL) lValue );
break;
case emfFreeze:
xosd = Freeze ( hpid, htid );
break;
case emfThaw:
xosd = Thaw ( hpid, htid );
break;
case emfCreatePid:
xosd = CreateHprc ( hpid );
if ( xosd == xosdNone ) {
xosd = SendRequest ( dmfCreatePid, hpid, NULL );
}
SyncHprcWithDM( hpid );
break;
case emfDestroyPid:
{
HPRC hprc = HprcFromHpid(hpid);
xosd = SendRequest ( dmfDestroyPid, hpid, NULL );
if ( xosd == xosdLineNotConnected ) {
//
// Communication line broke, we'll ignore this error.
//
xosd = xosdNone;
}
DestroyHprc ( hprc );
}
break;
case emfDestroyTid: {
HPRC hprc = HprcFromHpid(hpid);
DestroyHthd( HthdFromHtid( hprc, htid ));
}
break;
case emfUnassemble:
xosd = disasm ( hpid, htid, (LPSDI) lValue );
break;
case emfAssemble:
{
ADDR addr = {0};
GetAddr ( hpid, htid, adrCurrent, &addr );
xosd = Assemble ( hpid, htid, &addr, (LSZ) lValue );
SetAddr ( hpid, htid, adrCurrent, &addr );
}
break;
case emfGetMemInfo:
xosd = GetMemInfo(hpid, wValue, (LPMEMINFO)lValue);
break;
case emfIsOverlayLoaded:
xosd = FLoadedOverlay( hpid, (LPADDR) lValue );
break;
case emfDebugActive:
xosd = DebugActive(hpid, htid, (LPDBG_ACTIVE_STRUCT)lValue);
break;
case emfGetMsgMap:
MsgMap.Count = (sizeof( MsgInfo ) / sizeof( MsgInfo[0] ))-1;
*((LPMSGMAP *)lValue) = &MsgMap;
break;
#if defined ( WIN )
xosd = ( WMSGTranslate ( ((LPGTM)lValue)->lpwMsg,
((LPGTM)lValue)->lpwType,
((LPGTM)lValue)->lszMsg,
((LPGTM)lValue)->lpwMask ) ? xosdNone : xosdSyntax );
#else
xosd = xosdSyntax;
#endif
break;
#if defined ( WIN )
case emfSendChar:
xosd = SendRequestX ( dmfSendChar, hpid, htid, wValue, (LPV) lValue );
break;
#endif
case emfGetPrompt:
xosd = GetPrompt(hpid, htid, (LPPROMPTMSG)lValue);
break;
case emfGetModuleList:
xosd = GetModuleList( hpid, htid, (LPMODULE_LIST_REQUEST)lValue );
break;
#endif // !OSDEBUG4
/*
* This will tell the DM that we have finished processing the
* Module Load message.
*/
case emfLoadDllAck:
{
BYTE b = 1;
HPRC hprc = HprcFromHpid(hpid);
HTHD hthd = HthdFromHtid(hprc,htid);
LPPRC lpprc;
LPTHD lpthd;
lpprc = LLLock(hprc);
lpprc->fRunning = TRUE;
LLUnlock(hprc);
if (hthd) {
lpthd = LLLock(hthd);
lpthd->fRunning = TRUE;
LLUnlock(hthd);
}
CallTL ( tlfReply, hpid, 1, &b );
}
xosd = xosdNone;
break;
case emfUnLoadDllAck:
if ( UnLoadFixups (hpid, (HEMI)lValue, wValue ) ) {
xosd = xosdNone;
} else {
xosd = xosdUnknown;
}
break;
case emfSetPath:
xosd = SetPath(hpid, htid, wValue, (LSZ)lValue);
break;
case emfConnect:
#ifdef OSDEBUG4
xosd = CallTL( tlfLoadDM, hpid, sizeof(LOADDMSTRUCT), &LoadDmStruct);
if (xosd == xosdNone) {
xosd = SendRequest( dmfInit, hpid, htid );
}
#else
xosd = SendRequest( dmfInit, hpid, htid );
#endif
break;
case emfDisconnect:
xosd = SendRequest( dmfUnInit, hpid, htid );
break;
#ifdef OSDEBUG4
case emfInfoReply:
#else
case emfMiscReply:
#endif
CallTL ( tlfReply, hpid, wValue, (LPV)lValue );
xosd = xosdNone;
break;
case emfGetFunctionInfo:
xosd = GetFunctionInfo( hpid, (PADDR)wValue, (PFUNCTION_INFO)lValue );
break;
default:
assert ( FALSE );
xosd = xosdUnknown;
break;
}
ValidateHeap();
return xosd;
} /* EMFunc() */
/*
**
*/
DllInit(
HANDLE hModule,
DWORD dwReason,
DWORD dwReserved
)
{
Unreferenced(hModule);
Unreferenced(dwReserved);
switch (dwReason) {
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
if (LpSendBuf) {
MHFree(LpSendBuf);
CbSendBuf = 0;
}
if (LpDmMsg) {
MHFree(LpDmMsg);
CbDmMsg = 0;
}
DeleteCriticalSection(&csCache);
break;
case DLL_PROCESS_ATTACH:
InitializeCriticalSection(&csCache);
break;
}
return TRUE;
}