Windows2000/private/windbg64/windbg/localwin.c
2020-09-30 17:12:32 +02:00

674 lines
17 KiB
C

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
localwin.c
Abstract:
This module contains the routines to manipulate the Locals Window
Author:
William J. Heaton (v-willhe) 20-Jul-1992
Griffith Wm. Kadnier (v-griffk) 10-Mar-1993
Environment:
Win32, User Mode
--*/
/*
* Preprocessor
*/
#include "precomp.h"
#pragma hdrstop
BOOL AcceptValueUpdate(PTRVIT pVit,PPANE p);
/*
* Global Memory (PROGRAM)
*/
extern CXF CxfIp; // The Current IP Context
extern LPSHF Lpshf; // Pointer to SH function vector
/*
* Global Memory (FILE)
*/
HWND hWndLocal;
PTRVIT pvitLocal;
/*
* Prototypes (Local)
*/
BOOL PASCAL NEAR GetLocalAtContext ( PTRVIT pvit, PCXF pcxf);
BOOL UpdateLocalsVit(PCXF pCxf, BOOL Expand1st);
/*
* Start of Code
*/
/*** GetLocalHWND
** Synopsis:
** hWnd = GetLocalHWND()
** Entry:
** None
** Returns:
** Pointer to the current watch window handle.
*/
HWND GetLocalHWND(VOID)
{
return(hWndLocal);
}
/*** GetLocalAtContext Return a local linked list for the specified context
** Purpose:
** Make a locals linked list for a given context
** Input:
** pvit - pointer to a vit packet to where the linked list is to start
** pctxt - pointer to a ctxt of the context.
** Output:
** pvit - is filled in and the linked list is allocated and generated.
** Returns
** TRUE/FALSE has the context changed.
** Exceptions:
*/
BOOL
PASCAL
GetLocalAtContext (
PTRVIT pvit,
PCXF pcxf
)
{
VIB vibT;
PTRVIB pvibCur;
int RetStatus = FALSE; // Default is context hasn't changed
EESTATUS RetErr;
CXF cxf;
HMEM hsyml = 0;
ULONG strIndex;
// If no Vit, we can't do anything (and the context has changed!)
if ( !pvit ) {
return(FALSE);
}
// If no Offset or Segment, same treatment
if ((GetAddrOff (*SHpADDRFrompCXT (SHpCXTFrompCXF (pcxf))) == 0) &&
(GetAddrOff (*SHpADDRFrompCXT (SHpCXTFrompCXF (pcxf))) == 0)) {
return(FALSE);
}
// copy context and frame and check to see if the context can
// handle locals.
cxf = *pcxf;
if (!ADDR_IS_LI (*SHpADDRFrompCXT (SHpCXTFrompCXF (&cxf))))
SYUnFixupAddr (SHpADDRFrompCXT (SHpCXTFrompCXF (&cxf)));
// If we don't have a context (no proc or no module) or we are
// still in the prolog -- we don't display anything
if (!( cxf.cxt.hProc && cxf.cxt.hMod) ||
SHIsInProlog(SHpCXTFrompCXF(&cxf))) {
pvit->cxf.cxt.hMod = 0;
pvit->cxf.cxt.hGrp = 0;
pvit->cxf.cxt.hProc = 0;
pvit->cxf.cxt.hBlk = 0;
pvit->cln = 0;
FTFreeAllSib( pvit->pvibChild );
pvit->pvibChild = NULL;
return(TRUE);
}
if ( (pvit->cxf.cxt.hBlk == cxf.cxt.hBlk) &&
(pvit->cxf.cxt.hProc == cxf.cxt.hProc)) {
SHhFrameFrompCXF(&pvit->cxf) = SHhFrameFrompCXF(&cxf);
return(FALSE);
}
// Release the Locals tree
FTFreeAllSib( pvit->pvibChild );
pvit->pvibChild = NULL;
RetStatus = TRUE;
// fill in the Variable Info block Top and clear line count
pvit->cxf = cxf;
pvit->cln = 0;
// make a dummy Variable Info Block to start the search
pvibCur = &vibT;
pvibCur->pvibSib = pvit->pvibChild;
// make the linked list
EEGetHSYMList ( &hsyml, &cxf.cxt, HSYMR_lexical + HSYMR_function,
NULL, TRUE );
if ( hsyml != (HMEM) NULL ) {
PHSL_HEAD lphsymhead;
PHSL_LIST lphsyml;
WORD i = 0;
WORD j = 0;
// get the syms
lphsymhead = (PHSL_HEAD) MMLpvLockMb ( hsyml );
lphsyml = (PHSL_LIST)(lphsymhead + 1);
for ( i = 0; i != lphsymhead->blockcnt; i++ ) {
for ( j = 0; j != lphsyml->symbolcnt; j++ ) {
// is this a displayable sym?
if ( SHCanDisplay ( lphsyml->hSym[j] ) ) {
HSYM hSym = lphsyml->hSym[j];
// get the new Variable Info Block. To maintain the tree, the old
// Variable Info Block is returned if it exists.
if ( !( pvibCur->pvibSib = FTvibGet ( pvibCur->pvibSib, (PTRVIB) pvit) ) ) {
goto nomoresyms;
}
// check to see if this Variable Info Block is an old vib that
// isn't correct anymore. We know offset is enough of a check
// because we checked the module above. If it is clear the vib chain.
if( pvibCur->pvibSib->vibPtr != vibUndefined &&
pvibCur->pvibSib->hSym != hSym ) {
FTvibInit(pvibCur->pvibSib, (PTRVIB) pvit);
}
// if we have a new tree, we must assign stuff
if ( pvibCur->pvibSib->vibPtr == vibUndefined ) {
DAssert (hSym != 0);
RetErr = EEGetTMFromHSYM(hSym,&pcxf->cxt,&pvibCur->pvibSib->hTMBd,
&strIndex, TRUE, TRUE);
if ( RetErr != EENOERROR && RetErr != EECATASTROPHIC ) {
pvibCur->pvibSib = NULL;
goto nextsym;
}
// assign this stuff only once
pvibCur->pvibSib->hSym = hSym;
pvibCur->pvibSib->vibPtr = vibSymbol;
}
// update the parent's (Variable Info block Top) number count
// the vit is alway initialized to zero
pvibCur = pvibCur->pvibSib;
pvibCur->pvibParent->cln += pvibCur->cln;
nextsym:
; // must have a statement after a label
}
}
lphsyml = (PHSL_LIST) &(lphsyml->hSym[j]);
}
nomoresyms:
MMbUnlockMb ( hsyml );
}
EEFreeHSYMList ( &hsyml );
// free any extra Variable Info Blocks
FTFreeAllSib ( pvibCur->pvibSib );
pvibCur->pvibSib = NULL;
// load in the child pointer from the dummy vit
pvit->pvibChild = vibT.pvibSib;
return(RetStatus);
} /* GetLocalAtContext() */
/*
** void = UpdateLocalsVit(pCxf)
** Entry:
** pCxf - pointer to context frame or Null if we are to use the
** Current IP context frame.
** Returns:
** Nothine
** Description:
*/
BOOL
UpdateLocalsVit(
PCXF pCxf,
BOOL Expand1st
)
{
PTRVIB pvib;
if ( pCxf == NULL ) {
pCxf = (PCXF)(&CxfIp);
}
if ( GetLocalAtContext(pvitLocal, pCxf) ) {
// Mark all top-level if need b
if ( Expand1st ) {
pvib = pvitLocal->pvibChild;
while ( pvib) {
pvib->flags.ExpandMe = TRUE;
pvib = pvib->pvibSib;
}
}
return(TRUE);
}
return(FALSE);
} /* UpdateLocalsVit() */
/*** InitLocalsVits
** Synopsis:
** bool = InitLocalsVits()
** Entry:
** Nothing
** Returns:
** TRUE if the initialization was successful else FALSE
** Description:
** This routine will allocate the initial structures which are used
** to contain information describing the contents of the locals window
*/
BOOL NEAR PASCAL InitLocalsVits(void)
{
pvitLocal = (PTRVIT) calloc(1, sizeof(VIT) );
return ( pvitLocal != NULL);
}
/*** FreeLocalsVits
** Synopsis:
** void = FreeLocalsVits()
** Entry:
** Nothing
** Returns:
** None
** Description:
** This function frees up the structures which describe the contents
** of the locals window
*/
void NEAR PASCAL FreeLocalsVits(void)
{
FTFreeAllSib(pvitLocal->pvibChild);
pvitLocal->pvibChild = NULL;
free(pvitLocal);
pvitLocal = NULL;
}
/*** LocalEditProc
** Synopsis:
** long = LocalEditProc(hwnd, msg, wParam, lParam)
** Entry:
** hwnd - handle to window to process message for
** msg - message to be processed
** wParam - information about message to be processed
** lParam - information about message to be processed
** Returns:
** Description:
** MDI function to handle Localwindow messages
*/
LRESULT
WINAPI
LocalEditProc(
HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam
)
{
PPANE p = (PPANE)lParam;
PCXF pCxf = (PCXF)wParam;
PPANEINFO pInfo = (PPANEINFO)wParam;
LONG Len = 0;
LONG lLen = 0;
PTRVIB pVib = NULL;
PVTEXT pvtext;
ULONG i;
RECT Rect, tRect;
HWND hFoc;
HCURSOR hOldCursor, hWaitCursor;
hFoc = GetFocus();
__try {
switch (msg) {
case WU_INITDEBUGWIN:
Dbg(InitLocalsVits());
hWndLocal = hwnd;
PostMessage(hwnd, WU_UPDATE, 0, 0L);
break;
case WM_DESTROY:
hWndLocal = NULL; // Lose the Local Window Handle
// fall thru...
case WU_DBG_UNLOADEE:
case WU_DBG_UNLOADEM:
if ( pvitLocal) {
FreeLocalsVits(); // Lose the Local Trees
SendMessage(p->hWndLeft, LB_SETCOUNT, 1, 0);
SendMessage(p->hWndButton, LB_SETCOUNT, 1, 0);
SendMessage(p->hWndRight, LB_SETCOUNT, 1, 0);
p->MaxIdx = (WORD)1;
PostMessage(hwnd, WU_UPDATE, 0, 0L);
}
break;
case WU_DBG_LOADEM:
case WU_DBG_LOADEE:
if (!pvitLocal) {
Dbg(InitLocalsVits());
hWndLocal = hwnd;
PostMessage(hwnd, WU_UPDATE, 0, 0L);
}
break;
case WU_OPTIONS:
pVib = FTvibGetAtLine( pvitLocal, pInfo->ItemId);
if ( pVib == NULL) {
return FALSE;
}
pvtext = &pVib->pvtext[pVib->vibIndex];
if ( pInfo->pFormat && (*(pvtext->pszValueC) != '{')) {
FTEnsureTextExists(pVib);
if ( pvtext->pszFormat) {
free(pvtext->pszFormat);
}
pvtext->pszFormat = _strdup(pInfo->pFormat);
if ( pvtext->pszValueC) {
free(pvtext->pszValueC);
}
pvtext->pszValueC = NULL;
PaneInvalidateRow(p);
} else {
FTEnsureTextExists(pVib);
if ( pvtext->pszFormat) {
free(pvtext->pszFormat);
}
pvtext->pszFormat = '\0';
if ( pvtext->pszValueC) {
free(pvtext->pszValueC);
}
pvtext->pszValueC = NULL;
PaneInvalidateRow(p);
}
return TRUE;
case WU_INFO:
// Default to a reasonable baseline
pInfo->pBuffer = pInfo->pFormat = NULL;
pInfo->NewText = FALSE;
pInfo->ReadOnly = TRUE;
pVib = FTvibGetAtLine( pvitLocal, pInfo->ItemId);
if ( pVib == NULL) {
return(FALSE);
}
FTEnsureTextExists(pVib);
pvtext = &pVib->pvtext[pVib->vibIndex];
pInfo->pFormat = pvtext->pszFormat;
pInfo->pBuffer = FTGetPanelString( pvitLocal, pVib, pInfo->CtrlId);
if ( pInfo->CtrlId == ID_PANE_RIGHT) {
pInfo->ReadOnly = FALSE;
pInfo->NewText = FTGetPanelStatus( pVib, pInfo->CtrlId);
} else {
pInfo->ReadOnly = TRUE;
pInfo->NewText = FALSE;
}
return TRUE;
case WU_SETWATCH:
if ( pvitLocal == NULL) {
return(FALSE);
}
if ( p->nCtrlId == ID_PANE_RIGHT) {
BOOL retval;
fUseFrameContext = TRUE;
retval = (AcceptValueUpdate( pvitLocal, p));
if (retval == TRUE) {
UpdateDebuggerState(UPDATE_DATAWINS);
}
fUseFrameContext = FALSE;
return retval;
}
break;
case WU_INVALIDATE:
if (p == (PPANE)NULL) {
p = (PPANE)GetWindowLongPtr(GetLocalHWND(), GWW_EDIT);
}
SendMessage(p->hWndLeft, LB_SETCOUNT, 0, 0);
SendMessage(p->hWndButton, LB_SETCOUNT, 0, 0);
SendMessage(p->hWndRight, LB_SETCOUNT, 0, 0);
p->MaxIdx = 0;
PostMessage(hwnd, WU_UPDATE, 0, 0L);
InvalidateRect(p->hWndButton, NULL, TRUE);
InvalidateRect(p->hWndLeft, NULL, TRUE);
InvalidateRect(p->hWndRight, NULL, TRUE);
UpdateWindow (p->hWndButton);
UpdateWindow (p->hWndLeft);
UpdateWindow (p->hWndRight);
break;
case WU_EXPANDWATCH:
if ( pvitLocal == NULL) {
return(FALSE);
}
if ( FTExpand(pvitLocal, (ULONG)(wParam)) != OK) {
return(FALSE);
}
p->LeftOk = p->RightOk = FALSE;
pCxf = &pvitLocal->cxf; // Update in vit context
// fall thru...
case WU_UPDATE:
if ( pvitLocal == NULL) {
return(FALSE);
}
if (!pCxf) {
pCxf = &CxfIp;
}
// Has the Context Changed?
if ( UpdateLocalsVit(pCxf, p->bFlags.Expand1st) || p->LeftOk == FALSE ) {
hWaitCursor = LoadCursor ( (HINSTANCE) NULL, IDC_WAIT);
hOldCursor = SetCursor (hWaitCursor);
// Do we need to expand first level?
if ( p->bFlags.Expand1st) {
FTExpandOne(pvitLocal->pvibChild);
}
Len = (LONG)pvitLocal->cln;
p->MaxIdx = (WORD)Len;
lLen = (long) SendMessage(p->hWndLeft, LB_GETCOUNT, 0, 0L);
lLen = (lLen < Len || lLen == 0) ? Len : lLen;
SendMessage( p->hWndLeft, LB_SETCOUNT, lLen, 0L );
SendMessage( p->hWndButton, LB_SETCOUNT, lLen, 0L );
SendMessage( p->hWndRight, LB_SETCOUNT, lLen, 0L );
// Resetting the count, lost where we were so put us back
if (p->MaxIdx > 0) {
PaneResetIdx(p, p->CurIdx);
}
p->LeftOk = TRUE;
} else {
// Set hourglass cursor
hWaitCursor = LoadCursor ( (HINSTANCE) NULL, IDC_WAIT);
hOldCursor = SetCursor (hWaitCursor);
}
// Reset the right pane
FTAgeVibValues(pvitLocal->pvibChild);
for ( i= (ULONG)p->TopIdx;
i < (ULONG)(p->TopIdx + p->PaneLines) ; i++) {
if (FTVerifyNew(pvitLocal,i) ) {
PaneInvalidateItem( p->hWndRight, (PPANE)p, (SHORT)i);
}
}
p->RightOk = TRUE;
PaneCaretNum(p);
if ((hFoc == p->hWndButton) ||
(hFoc == p->hWndLeft) || (hFoc == p->hWndRight)) {
SendMessage(p->hWndButton ,
LB_GETITEMRECT,
(WPARAM)p->CurIdx,
(LPARAM)&Rect);
GetClientRect (p->hWndButton, &tRect);
tRect.top = Rect.top;
InvalidateRect(p->hWndButton, &tRect, TRUE);
SendMessage(p->hWndLeft ,
LB_GETITEMRECT,
(WPARAM)p->CurIdx,
(LPARAM)&Rect);
GetClientRect (p->hWndLeft, &tRect);
tRect.top = Rect.top;
InvalidateRect(p->hWndLeft, &tRect, TRUE);
SendMessage(p->hWndRight ,
LB_GETITEMRECT,
(WPARAM)p->CurIdx,
(LPARAM)&Rect);
GetClientRect (p->hWndRight, &tRect);
tRect.top = Rect.top;
InvalidateRect(p->hWndRight, &tRect, TRUE);
}
CheckPaneScrollBar( p, (WORD)Len);
// Set original cursor
hOldCursor = SetCursor (hOldCursor);
break;
}
} __except(EXCEPTION_EXECUTE_HANDLER) {
return FALSE;
}
return FALSE;
} /* LocalEditProc() */