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.
533 lines
15 KiB
533 lines
15 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: path.cxx
|
|
*
|
|
* PATHOBJ gdikdx extension code.
|
|
*
|
|
* Copyright (c) 2000 Microsoft Corporation
|
|
*
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.hxx"
|
|
|
|
// PATH
|
|
#define GetPATHField(field) \
|
|
GetPATHSubField(#field,field)
|
|
#define GetPATHSubField(field,local) \
|
|
GetFieldData(offPATH, "PATH", field, sizeof(local), &local)
|
|
// PATHRECORD
|
|
#define GetPATHRECORDField(field) \
|
|
GetPATHRECORDSubField(#field,field)
|
|
#define GetPATHRECORDSubField(field,local) \
|
|
GetFieldData(offPATHRECORD, "PATHRECORD", field, sizeof(local), &local)
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name:
|
|
*
|
|
* vPrintPOINTFIX
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* prints a POINTFIX
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pointer to a POINTFIX
|
|
*
|
|
* Return Value:
|
|
*
|
|
* none
|
|
*
|
|
\**************************************************************************/
|
|
|
|
void
|
|
vPrintPOINTFIX(ULONG64 pPOINTFIX)
|
|
{
|
|
FIX x;
|
|
FIX y;
|
|
ULONG error;
|
|
|
|
FIELD_INFO vFields[] =
|
|
{
|
|
{ DbgStr("x"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
|
|
{ DbgStr("y"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL}
|
|
};
|
|
|
|
SYM_DUMP_PARAM vSym =
|
|
{
|
|
sizeof (SYM_DUMP_PARAM),
|
|
DbgStr(GDIType(POINTFIX)),
|
|
DBG_DUMP_NO_PRINT,
|
|
0/*address*/,
|
|
NULL, NULL, NULL,
|
|
sizeof(vFields)/sizeof(vFields[0]),
|
|
vFields
|
|
};
|
|
|
|
vSym.addr = pPOINTFIX;
|
|
|
|
error = Ioctl(IG_DUMP_SYMBOL_INFO, &vSym, vSym.size);
|
|
if(error)
|
|
{
|
|
dprintf("Unable to get contents of POINTFIX\n");
|
|
dprintf(" (Ioctl returned %s)\n", pszWinDbgError(error));
|
|
return;
|
|
}
|
|
x = (FIX) vFields[0].address;
|
|
y = (FIX) vFields[1].address;
|
|
|
|
dprintf(
|
|
"(%-#10x, %-#10x) = (%d+(%d/16), %d+(%d/16))"
|
|
, x, y, x/16, x&15, y/16, y&15
|
|
);
|
|
}
|
|
|
|
ULONG
|
|
pointFixCallback(
|
|
PFIELD_INFO pField,
|
|
PVOID UserContext
|
|
)
|
|
{
|
|
if(pField)
|
|
{
|
|
vPrintPOINTFIX(pField->address);
|
|
dprintf("\n");
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* vPrintPATHRECORD
|
|
*
|
|
* History:
|
|
* Mon 20-Jun-1994 15:33:37 by Kirk Olynyk [kirko]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
void
|
|
vPrintPATHRECORD(ULONG64 offPATHRECORD)
|
|
{
|
|
FLONG flags, fl;
|
|
ULONG count;
|
|
ULONG64 pprnext, pprprev;
|
|
ULONG offaptfx;
|
|
ULONG error;
|
|
|
|
if(offPATHRECORD)
|
|
{
|
|
FIELD_INFO vFields[] =
|
|
{
|
|
{ DbgStr("pprnext"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
|
|
{ DbgStr("pprprev"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
|
|
{ DbgStr("flags"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
|
|
{ DbgStr("count"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL}
|
|
};
|
|
|
|
SYM_DUMP_PARAM vSym =
|
|
{
|
|
sizeof (SYM_DUMP_PARAM),
|
|
DbgStr(GDIType(PATHRECORD)),
|
|
DBG_DUMP_NO_PRINT,
|
|
0/*address*/,
|
|
NULL, NULL, NULL,
|
|
sizeof(vFields)/sizeof(vFields[0]),
|
|
vFields
|
|
};
|
|
|
|
vSym.addr = offPATHRECORD;
|
|
|
|
error = Ioctl(IG_DUMP_SYMBOL_INFO, &vSym, vSym.size);
|
|
if(error)
|
|
{
|
|
dprintf("Unable to get contents of PATHRECORD\n");
|
|
dprintf(" (Ioctl returned %s)\n", pszWinDbgError(error));
|
|
return;
|
|
}
|
|
|
|
pprnext = vFields[0].address;
|
|
pprprev = vFields[1].address;
|
|
dprintf("\tpprnext = %-#p\n", pprnext);
|
|
dprintf("\tpprprev = %-#p\n", pprprev);
|
|
flags = (FLONG)vFields[2].address;
|
|
fl = flags;
|
|
dprintf("\tflags = %-#x\n", fl);
|
|
|
|
for(FLAGDEF *pfd=afdPD; pfd->psz; pfd++)
|
|
{
|
|
if(fl & pfd->fl)
|
|
dprintf("\t\t\t %s\n", pfd->psz);
|
|
}
|
|
count = (ULONG)vFields[3].address;
|
|
dprintf("\tcount = %u\n", count);
|
|
|
|
// Get the offset of aptfx in PATHRECORD.
|
|
GetFieldOffset("PATHRECORD","aptfx",&offaptfx);
|
|
if(count)
|
|
{
|
|
FIELD_INFO vField = { NULL, NULL, count, 0, 0, pointFixCallback};
|
|
|
|
SYM_DUMP_PARAM vSym =
|
|
{
|
|
sizeof(SYM_DUMP_PARAM),
|
|
DbgStr(GDIType(POINTFIX)),
|
|
DBG_DUMP_ARRAY | DBG_DUMP_NO_PRINT,
|
|
offPATHRECORD+offaptfx,
|
|
&vField, NULL, NULL, 0, NULL
|
|
};
|
|
|
|
error = Ioctl(IG_DUMP_SYMBOL_INFO, &vSym, vSym.size);
|
|
if(error)
|
|
{
|
|
dprintf("Unable to dump contents of aptfx\n");
|
|
dprintf(" (Ioctl returned %s)\n", pszWinDbgError(error));
|
|
return;
|
|
}
|
|
}
|
|
dprintf("\n");
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* vPrintPATHList
|
|
*
|
|
* History:
|
|
* Sat 20-May-2000 18:25:21 by Pravin Santiago [pravins]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
void vPrintPATHList(ULONG64 offPATH)
|
|
{
|
|
ULONG64 pprfirst;
|
|
ULONG64 pprnext;
|
|
ULONG64 ppr_CD;
|
|
ULONG64 ppr;
|
|
ULONG64 offPATHRECORD;
|
|
ULONG count;
|
|
|
|
GetPATHField(pprfirst);
|
|
|
|
ppr = ppr_CD = offPATHRECORD = pprfirst;
|
|
|
|
while(ppr)
|
|
{
|
|
GetPATHRECORDField(pprnext);
|
|
|
|
//simple multi-rate cycle detection.
|
|
if(ppr_CD)
|
|
{
|
|
GetFieldData(ppr_CD,
|
|
"PATHRECORD",
|
|
"pprnext",
|
|
sizeof(ppr_CD),
|
|
&ppr_CD);
|
|
if(ppr_CD)
|
|
{
|
|
GetFieldData(ppr_CD,
|
|
"PATHRECORD",
|
|
"pprnext",
|
|
sizeof(ppr_CD),
|
|
&ppr_CD);
|
|
}
|
|
}
|
|
if(ppr==ppr_CD)
|
|
{
|
|
dprintf("ERROR: Cycle detected in linked list.\n");
|
|
break;
|
|
}
|
|
if(CheckControlC())
|
|
{
|
|
break;
|
|
}
|
|
|
|
vPrintPATHRECORD(offPATHRECORD);
|
|
|
|
ppr = offPATHRECORD = pprnext;
|
|
}
|
|
}
|
|
|
|
|
|
HRESULT
|
|
OutputPATH(
|
|
PDEBUG_CLIENT Client,
|
|
OutputControl *OutCtl,
|
|
ULONG64 Offset,
|
|
BOOL DumpRecords
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ULONG64 Module;
|
|
ULONG TypeId;
|
|
OutputControl FilterOutCtl(Client);
|
|
|
|
if ((hr = GetTypeId(Client, "PATH", &TypeId, &Module)) == S_OK)
|
|
{
|
|
OutputFilter OutFilter(Client);
|
|
OutputState OutState(Client);
|
|
|
|
if (!DumpRecords ||
|
|
((hr = OutState.Setup(0, &OutFilter)) == S_OK &&
|
|
(hr = FilterOutCtl.SetControl(DEBUG_OUTCTL_THIS_CLIENT |
|
|
DEBUG_OUTCTL_NOT_LOGGED |
|
|
DEBUG_OUTCTL_OVERRIDE_MASK,
|
|
OutState.Client)) == S_OK))
|
|
{
|
|
TypeOutputDumper TypeReader(Client,
|
|
(DumpRecords ? &FilterOutCtl : OutCtl));
|
|
|
|
OutCtl->Output(" PATH @ 0x%p:\n", Offset);
|
|
|
|
TypeReader.ExcludeMarked();
|
|
TypeReader.MarkField("cle.*");
|
|
|
|
hr = TypeReader.OutputVirtual(Module, TypeId, Offset);
|
|
|
|
if (hr != S_OK)
|
|
{
|
|
OutCtl->OutErr("Type Dump for PATH returned %s.\n", pszHRESULT(hr));
|
|
}
|
|
else if (DumpRecords)
|
|
{
|
|
DEBUG_VALUE RecOffset;
|
|
|
|
OutFilter.OutputText(OutCtl, DEBUG_OUTPUT_NORMAL);
|
|
|
|
if ((hr = OutFilter.Query("pprfirst", &RecOffset, DEBUG_VALUE_INT64)) == S_OK)
|
|
{
|
|
if (RecOffset.I64 != 0)
|
|
{
|
|
OutCtl->OutWarn("Path record dumping to be converted.\n");
|
|
vPrintPATHList(Offset);
|
|
}
|
|
else
|
|
{
|
|
OutCtl->OutErr(" No records to dump.\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
OutCtl->OutErr("Error evaluating 'pprfirst' member.\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* EPATHOBJ
|
|
*
|
|
\**************************************************************************/
|
|
|
|
DECLARE_API( epathobj )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL BadSwitch = FALSE;
|
|
BOOL DumpPath = FALSE;
|
|
BOOL DumpRecords = FALSE;
|
|
DEBUG_VALUE Offset;
|
|
ULONG64 Module;
|
|
ULONG TypeId;
|
|
OutputControl OutCtl(Client);
|
|
|
|
while (!BadSwitch)
|
|
{
|
|
while (isspace(*args)) args++;
|
|
|
|
if (*args != '-') break;
|
|
|
|
args++;
|
|
BadSwitch = (*args == '\0' || isspace(*args));
|
|
|
|
while (*args != '\0' && !isspace(*args))
|
|
{
|
|
switch (*args)
|
|
{
|
|
case 'r': DumpRecords = TRUE; // Make sure DumpPath is set too
|
|
case 'p': DumpPath = TRUE; break;
|
|
default:
|
|
BadSwitch = TRUE;
|
|
break;
|
|
}
|
|
|
|
if (BadSwitch) break;
|
|
args++;
|
|
}
|
|
}
|
|
|
|
if (BadSwitch ||
|
|
(hr = Evaluate(Client, args, DEBUG_VALUE_INT64, 0, &Offset, NULL)) != S_OK ||
|
|
Offset.I64 == 0)
|
|
{
|
|
OutCtl.Output("Usage: epathobj [-?pr] <EPATHOBJ Addr>\n"
|
|
" -p - dump path\n"
|
|
" -r - dump path records\n");
|
|
}
|
|
else
|
|
{
|
|
if ((hr = GetTypeId(Client, "EPATHOBJ", &TypeId, &Module)) == S_OK)
|
|
{
|
|
OutputFilter OutFilter(Client);
|
|
OutputState OutState(Client);
|
|
|
|
OutCtl.Output(" EPATHOBJ @ 0x%p:\n", Offset.I64);
|
|
|
|
if (!DumpPath ||
|
|
((hr = OutState.Setup(0, &OutFilter)) == S_OK &&
|
|
(hr = OutCtl.SetControl(DEBUG_OUTCTL_THIS_CLIENT |
|
|
DEBUG_OUTCTL_NOT_LOGGED |
|
|
DEBUG_OUTCTL_OVERRIDE_MASK,
|
|
OutState.Client)) == S_OK))
|
|
{
|
|
TypeOutputDumper TypeReader(Client, &OutCtl);
|
|
|
|
hr = TypeReader.OutputVirtual(Module, TypeId, Offset.I64);
|
|
|
|
if (DumpPath)
|
|
{
|
|
OutCtl.SetControl(DEBUG_OUTCTL_AMBIENT, Client);
|
|
}
|
|
|
|
if (hr != S_OK)
|
|
{
|
|
OutCtl.OutErr("Type Dump for EPATHOBJ returned %s.\n", pszHRESULT(hr));
|
|
}
|
|
else if (DumpPath)
|
|
{
|
|
OutFilter.OutputText(&OutCtl, DEBUG_OUTPUT_NORMAL);
|
|
|
|
if ((hr = OutFilter.Query("ppath", &Offset, DEBUG_VALUE_INT64)) == S_OK)
|
|
{
|
|
if (Offset.I64 != 0)
|
|
{
|
|
hr = OutputPATH(Client, &OutCtl, Offset.I64, DumpRecords);
|
|
}
|
|
else
|
|
{
|
|
OutCtl.OutErr(" No path to dump.\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
OutCtl.OutErr("Error evaluating 'ppath' member.\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* PATH
|
|
*
|
|
\**************************************************************************/
|
|
|
|
DECLARE_API( path )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL BadSwitch = FALSE;
|
|
BOOL DumpRecords = FALSE;
|
|
ULONG64 PathAddr;
|
|
DEBUG_VALUE Arg;
|
|
ULONG64 Module;
|
|
ULONG TypeId;
|
|
OutputControl OutCtl(Client);
|
|
|
|
while (!BadSwitch)
|
|
{
|
|
while (isspace(*args)) args++;
|
|
|
|
if (*args != '-') break;
|
|
|
|
args++;
|
|
BadSwitch = (*args == '\0' || isspace(*args));
|
|
|
|
while (*args != '\0' && !isspace(*args))
|
|
{
|
|
switch (*args)
|
|
{
|
|
case 'r': DumpRecords = TRUE; break;
|
|
default:
|
|
BadSwitch = TRUE;
|
|
break;
|
|
}
|
|
|
|
if (BadSwitch) break;
|
|
args++;
|
|
}
|
|
}
|
|
|
|
if (BadSwitch ||
|
|
(hr = Evaluate(Client, args, DEBUG_VALUE_INT64, 0, &Arg, NULL)) != S_OK ||
|
|
Arg.I64 == 0)
|
|
{
|
|
OutCtl.Output("Usage: path [-?r] <HPATH | PATH Addr>\n"
|
|
" -r - dump records\n");
|
|
}
|
|
else
|
|
{
|
|
hr = GetObjectAddress(Client, Arg.I64, &PathAddr, PATH_TYPE, TRUE, TRUE);
|
|
|
|
if (hr != S_OK || PathAddr == 0)
|
|
{
|
|
DEBUG_VALUE ObjHandle;
|
|
TypeOutputParser TypeParser(Client);
|
|
OutputState OutState(Client);
|
|
ULONG64 PathAddrFromHmgr;
|
|
|
|
PathAddr = Arg.I64;
|
|
|
|
if ((hr = OutState.Setup(0, &TypeParser)) != S_OK ||
|
|
(hr = OutState.OutputTypeVirtual(PathAddr, "PATH", 0)) != S_OK ||
|
|
(hr = TypeParser.Get(&ObjHandle, "hHmgr", DEBUG_VALUE_INT64)) != S_OK)
|
|
{
|
|
OutCtl.OutErr("Unable to get contents of PATH::hHmgr\n");
|
|
OutCtl.OutErr(" (Type Read returned %s)\n", pszHRESULT(hr));
|
|
OutCtl.OutErr(" 0x%p is neither an HPATH nor valid PATH address\n", Arg.I64);
|
|
}
|
|
else
|
|
{
|
|
if (GetObjectAddress(Client, ObjHandle.I64, &PathAddrFromHmgr,
|
|
PATH_TYPE, TRUE, FALSE) == S_OK &&
|
|
PathAddrFromHmgr != PathAddr)
|
|
{
|
|
OutCtl.OutWarn("\tNote: PATH may not be valid.\n"
|
|
"\t It does not have a valid handle manager entry.\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
hr = OutputPATH(Client, &OutCtl, PathAddr, DumpRecords);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* DECLARE_API( dpo )
|
|
*
|
|
* dpo -- "dump PATHOBJ"
|
|
*
|
|
* 21-Feb-1995 -by- Lingyun Wang [lingyunw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
DECLARE_API( dpo )
|
|
{
|
|
OutputControl OutCtl(Client);
|
|
OutCtl.OutWarn("dpo is obsolete. Please use epathobj.\n");
|
|
return epathobj(Client, args);
|
|
}
|
|
|