mirror of https://github.com/lianthony/NT4.0
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
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;
|
|
}
|