Leaked source code of windows server 2003
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.
 
 
 
 
 
 

598 lines
18 KiB

/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
region.cxx
Abstract:
This file contains the routines to debug regions.
Author:
Jason Hartman (JasonHa) 2001-04-30
Environment:
User Mode
--*/
#include "precomp.hxx"
/******************************Public*Routine******************************\
* DECLARE_API( dr )
*
* Debugger extension to dump a region
*
* 21-Feb-1995 -by- Lingyun Wang [lingyunw]
* Wrote it.
\**************************************************************************/
DECLARE_API( dr )
{
OutputControl OutCtl(Client);
OutCtl.Output("Obsolete: Use 'region hrgn|prgn'.\n");
return S_OK;
}
/******************************Public*Routine******************************\
* DECLARE_API( cr )
*
* Debugger extension to check a region
*
* 21-Feb-1995 -by- Lingyun Wang [lingyunw]
* Wrote it.
\**************************************************************************/
DECLARE_API( cr )
{
OutputControl OutCtl(Client);
OutCtl.Output("Obsolete: Use 'region -c hrgn|prgn'\n");
return S_OK;
}
/******************************Public*Routine******************************\
* DECLARE_API( region )
*
* Debugger extension to dump and validate a region
*
* 22-May-2000 -by- Jason Hartman [jasonha]
* Converted from old dr & cr
*
\**************************************************************************/
DECLARE_API( region )
{
ULONG64 RgnAddr;
ULONG error;
ULONG Flags = 0;
#define REGION_CSCANS 0
#define REGION_SCAN_ADDRESS 1
#define REGION_SCAN_TAIL 2
#define REGION_SIZEOBJ 3
#define NUM_REGION_BASEOBJ_FIELDS 3
FIELD_INFO RegionFields[] = {
{ DbgStr("cScans"), DbgStr("cScans :"), 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL}, // REGION_CSCANS
{ DbgStr("scan"), DbgStr("scan <- pscnHead :"), 0, DBG_DUMP_FIELD_RETURN_ADDRESS | DBG_DUMP_FIELD_FULL_NAME, 0, AddressPrintCallback}, // REGION_SCAN_ADDRESS
{ DbgStr("pscnTail"), DbgStr("pscnTail :"), 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL}, // REGION_SCAN_TAIL
{ DbgStr("sizeObj"), DbgStr("sizeObj :"), 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL}, // REGION_SIZEOBJ
{ DbgStr("sizeRgn"), DbgStr("sizeRgn :"), 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
{ DbgStr("cRefs"), DbgStr("cRefs :"), 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
{ DbgStr("rcl"), DbgStr("rcl :"), 0, DBG_DUMP_FIELD_RETURN_ADDRESS | DBG_DUMP_FIELD_FULL_NAME, 0, RECTLCallback},
{ DbgStr("hHmgr"), DbgStr("hHmgr :"), 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
{ DbgStr("cExclusiveLock"), DbgStr("cExclusiveLock :"), 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
{ DbgStr("Tid"), DbgStr("Tid :"), 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
};
SYM_DUMP_PARAM RegionSym = {
sizeof (SYM_DUMP_PARAM), DbgStr(GDIType(REGION)), DBG_DUMP_COMPACT_OUT, 0/*RgnAddr*/,
NULL, &RegionSym, NewlineCallback, sizeof(RegionFields)/sizeof(RegionFields[0]), RegionFields
};
PrepareCallbacks(TRUE);
INIT_API();
PARSE_POINTER(region_help);
if (ntok > 1)
{
if (parse_iFindSwitch(tokens, ntok, 'c')!=-1)
{
Flags |= SCAN_DUMPER_NO_PRINT;
}
else if (parse_iFindSwitch(tokens, ntok, 'f')!=-1)
{
Flags |= SCAN_DUMPER_FORCE;
}
if (parse_iFindSwitch(tokens, ntok, 'r')!=-1)
{
Flags |= SCAN_DUMPER_FROM_TAIL;
}
}
// get pointer to object from handle or use param as pointer
if ((GetObjectAddress(Client,arg,&RgnAddr,RGN_TYPE,TRUE,TRUE) != S_OK) ||
(RgnAddr == 0))
{
ULONG64 ObjHandle;
ULONG64 RgnAddrFromHmgr;
RgnAddr = arg;
if (error = GetFieldValue(RgnAddr, GDIType(REGION), "hHmgr", ObjHandle))
{
ExtErr("Unable to get contents of REGION::hHmgr\n");
ExtErr(" (Ioctl returned %s)\n", pszWinDbgError(error));
ExtErr(" %#p is neither an HRGN nor valid REGION address\n", arg);
EXIT_API(S_OK);
}
if (!ObjHandle)
{
ExtOut("\tREGION is reserved for system use (no handle manger entry).\n");
RegionSym.nFields -= NUM_REGION_BASEOBJ_FIELDS;
}
else if (GetObjectAddress(Client,ObjHandle,&RgnAddrFromHmgr,
RGN_TYPE,TRUE,FALSE) == S_OK &&
RgnAddrFromHmgr != RgnAddr)
{
ExtOut("\tNote: REGION may not be valid.\n\t It does not have a valid handle manager entry.\n");
}
}
ExtOut("REGION @ %#p\n ", RgnAddr);
RegionSym.addr = RgnAddr;
error = Ioctl( IG_DUMP_SYMBOL_INFO, &RegionSym, RegionSym.size );
if (error)
{
ExtErr("Unable to get contents of REGION\n");
ExtErr(" (Ioctl returned %s)\n", pszWinDbgError(error));
}
else
{
ScanDumper Dumper(RegionFields[REGION_SCAN_ADDRESS].address,
RegionFields[REGION_SCAN_TAIL].address,
(ULONG)RegionFields[REGION_CSCANS].address,
RegionFields[REGION_SCAN_ADDRESS].address,
RgnAddr+RegionFields[REGION_SIZEOBJ].address,
Flags
);
BOOL Valid;
if ((Flags & SCAN_DUMPER_FROM_TAIL) != 0 && !Dumper.Reverse)
{
// We rquested a reverse dump, but Dumper wouldn't allow it.
EXIT_API(S_OK);
}
Valid = Dumper.DumpScans((ULONG)RegionFields[REGION_CSCANS].address);
if (Dumper.Reverse)
{
if (Dumper.ScanAddr != RegionFields[REGION_SCAN_ADDRESS].address)
{
ExtOut(" * Final ScanAddr (%#p) is not at head address (%#p)\n",
Dumper.ScanAddr, RegionFields[REGION_SCAN_ADDRESS].address);
Valid = FALSE;
}
}
else
{
if (Dumper.ScanAddr != RegionFields[REGION_SCAN_TAIL].address)
{
ExtOut(" * Final ScanAddr (%#p) is not at tail address (%#p)\n",
Dumper.ScanAddr, RegionFields[REGION_SCAN_TAIL].address);
Valid = FALSE;
}
}
if (Valid)
{
ExtOut(" Region is valid.\n");
}
else
{
ExtOut(" Region is NOT valid.\n");
}
}
EXIT_API(S_OK);
region_help:
ExtOut("Usage: region [-?cfr] hrgn|prgn\n");
ExtOut(" dumps/validates a region\n");
ExtOut(" c - doesn't print scans; validation only\n");
ExtOut(" f - continue printing even if an error is found\n");
ExtOut(" r - read scans in reverse order\n");
EXIT_API(S_OK);
}
/**************************************************************************\
*
\**************************************************************************/
BOOL bStrInStr(CHAR *pchTrg, CHAR *pchSrc)
{
BOOL bRes = 0;
int c = strlen(pchSrc);
//CHECKLOOP umm? This could be difficult to detect
while (TRUE)
{
// find the first character
pchTrg = strchr(pchTrg,*pchSrc);
// didn't find it?, fail!
if (pchTrg == NULL)
return(FALSE);
// did we find the string? succeed
if (strncmp(pchTrg,pchSrc,c) == 0)
return(TRUE);
// go get the next one.
pchTrg++;
}
}
/******************************Public*Routine******************************\
* rgnlog
*
\**************************************************************************/
#define MAXSEARCH 4
DECLARE_API( rgnlog )
{
#if 1
HRESULT hr = S_OK;
BOOL BadArg = FALSE;
ULONG RemainingArgIndex;
DEBUG_VALUE DumpCount = { 0, DEBUG_VALUE_INVALID };
CHAR EmptySearchString[] = "";
PSTR SearchStringList = EmptySearchString;
PSTR SearchString = SearchStringList;
OutputControl OutCtl(Client);
while (!BadArg && hr == S_OK)
{
while (isspace(*args)) args++;
if (*args == '-')
{
args++;
if (*args == '\0' || isspace(*args))
{
BadArg = TRUE;
}
else if (DumpCount.Type == DEBUG_VALUE_INVALID &&
args[0] == '1' && (args[1] == '\0' || isspace(args[1])))
{
DumpCount.I32 = -1;
DumpCount.Type = DEBUG_VALUE_INT32;
}
else
{
while (*args != '\0' && !isspace(*args))
{
switch (*args)
{
case '?':
default:
BadArg = TRUE;
break;
}
if (BadArg) break;
args++;
}
}
}
else
{
if (DumpCount.Type == DEBUG_VALUE_INVALID)
{
if (Evaluate(Client, args, DEBUG_VALUE_INT32, EVALUATE_DEFAULT_RADIX,
&DumpCount, &RemainingArgIndex, NULL, EVALUATE_COMPACT_EXPR) != S_OK ||
DumpCount.I32 == 0)
{
BadArg = TRUE;
}
else
{
args += RemainingArgIndex;
}
}
else
{
if (SearchStringList == EmptySearchString)
{
SearchStringList = (PSTR)HeapAlloc(GetProcessHeap(), 0,
sizeof(*SearchStringList)*(strlen(args)+2));
if (SearchStringList == NULL)
{
hr = E_OUTOFMEMORY;
}
else
{
SearchString = SearchStringList;
*SearchString = '\0';
}
}
if (hr == S_OK)
{
if (*args == '`' || *args == '\'' || *args == '\"')
{
CHAR StringEnd = *args;
if (args[1] == StringEnd || args[1] == '\0')
{
BadArg = TRUE;
}
else
{
while (*args != StringEnd && *args != '\0')
{
*SearchString++ = *args++;
}
if (*args == StringEnd) args++;
if (!isspace(*args) || *args != '\0')
{
OutCtl.Output("Malformed Search String at '%s'.\n",
args);
BadArg = TRUE;
}
else
{
*SearchString++ = '\0';
}
}
}
else
{
while (!isspace(*args) && *args != '\0')
{
*SearchString++ = *args++;
}
*SearchString++ = '\0';
}
}
}
}
}
if (hr == S_OK)
{
if (BadArg)
{
if (*args == '?') OutCtl.Output("rgnlog - dump/search rgnlog from checked builds.\n");
OutCtl.Output("Usage: rgnlog [-?] <Entries> [<Search Strings>]\n"
"\n"
" Entries - Number of tailing entries to dump/search\n"
" Search Strings - Dump only logs contain one of strings specified\n");
}
else
{
// Mark end of search string list with a NULL string.
*SearchString = '\0';
LONG iLog, iPass;
ULONG LogArraySize, LogLength, LogEntrySize;
CHAR SymName[80];
sprintf(SymName, "%s!iLog", GDIKM_Module.Name);
hr = ReadSymbolData(Client, SymName, &iLog, sizeof(iLog), NULL);
if (hr != S_OK) OutCtl.OutErr("Unable to get contents of %s\n", SymName);
if (hr == S_OK)
{
sprintf(SymName, "%s!iPass", GDIKM_Module.Name);
hr = ReadSymbolData(Client, SymName, &iPass, sizeof(iPass), NULL);
if (hr != S_OK) OutCtl.OutErr("Unable to get contents of %s\n", SymName);
}
if (hr == S_OK)
{
sprintf(SymName, "%s!argnlog", GDIKM_Module.Name);
hr = GetArrayDimensions(Client, SymName, NULL,
&LogArraySize, &LogLength, &LogEntrySize);
if (hr != S_OK) OutCtl.OutErr("Unable to get dimensions of %s\n", SymName);
}
if (hr == S_OK)
{
}
if (hr == S_OK)
{
if (*SearchStringList != '\0')
{
OutCtl.Output("Searching last %ld entries for:\n",
DumpCount.I32);
for (SearchString = SearchStringList;
*SearchString != '\0';
*SearchString += strlen(SearchString)+1)
{
OutCtl.Output(" \"%s\"\n", SearchString);
}
}
else
{
OutCtl.Output("Dumping last %ld entries.\n",
DumpCount.I32);
}
// To Do
}
}
}
if (SearchStringList != EmptySearchString)
{
HeapFree(GetProcessHeap(), 0, SearchStringList);
}
return hr;
#else
dprintf("Extension 'rgnlog' is not converted.\n");
#if ENABLE_OLD_EXTS // DOES NOT SUPPORT API64
LONG cDump;
LONG iCurrent;
RGNLOGENTRY rl;
RGNLOGENTRY *prl;
LONG gml; // gMaxRgnLog
int i, j;
PVOID pv;
CHAR achTmp[30];
CHAR achBuf[256];
PCHAR pchS[MAXSEARCH];
int cSearch;
BOOL bPrint;
PARSE_ARGUMENTS(rgnlog_help);
if(ntok<1) { goto rgnlog_help; }
tok_pos = parse_FindNonSwitch(tokens, ntok);
if(tok_pos==-1) { goto rgnlog_help; }
//check that this supports decimal
cDump = (LONG)GetExpression(tokens[tok_pos]);
if(cDump==0) { goto rgnlog_help; }
cSearch = 0;
while(cSearch<MAXSEARCH) {
tok_pos = parse_FindNonSwitch(tokens, ntok, tok_pos+1);
if(tok_pos==-1) {break;}
pchS[cSearch]=tokens[tok_pos];
cSearch++;
}
for (i = 0; i < cSearch; ++i)
dprintf("search[%s]\n",pchS[i]);
// get some stuff
GetAddress(pv, "&win32k!iLog");
dprintf("&iLog = %lx\n",pv);
if (pv == NULL)
{
dprintf("iCurrent was NULL\n");
return;
}
move(iCurrent, pv);
GetAddress(i,"&win32k!iPass");
if (pv == NULL)
{
dprintf("iPass was NULL\n");
return;
}
move(i,i);
dprintf("--------------------------------------------------\n");
dprintf("rgn log list, cDump = %ld, iCur = %ld, iPass = %ld\n", cDump,iCurrent,i);
dprintf("%5s-%4s:%8s,%8s,(%8s),%8s,%8s,%4s\n",
"TEB ","i","hrgn","prgn","return","arg1","arg2","arg3");
dprintf("--------------------------------------------------\n");
// Dereference the handle via the engine's handle manager.
GetAddress(prl, "win32k!argnlog");
if (!prl)
{
dprintf("prl was NULL\n");
return;
}
GetAddress(gml, "&win32k!gMaxRgnLog");
if (!gml)
{
dprintf("gml was NULL\n");
return;
}
move(gml,gml);
// set iCurrent to the first thing to dump
if (cDump > gml)
cDump = gml;
if (cDump > iCurrent)
iCurrent += gml;
iCurrent -= cDump;
dprintf("prl = %lx, gml = %ld, cDump = %ld, iCurrent = %ld\n",prl,gml,cDump,iCurrent);
//CHECKLOOP add exit/more support
for (i = 0; i < cDump; ++i)
{
move(rl,&prl[iCurrent]);
if (rl.pszOperation != NULL)
{
move2(achTmp,rl.pszOperation,30);
}
else
achTmp[0] = 0;
sprintf(achBuf,"%5lx-%4ld:%p,%p,(%8lx),%p, %p,%p, %s, %p, %p\n",
(ULONG_PTR)rl.teb >> 12,iCurrent,rl.hrgn,rl.prgn,rl.lRes,rl.lParm1,
rl.lParm2,rl.lParm3,achTmp,rl.pvCaller,rl.pvCallersCaller);
bPrint = (cSearch == 0);
for (j = 0; (j < cSearch) && !bPrint; ++j)
bPrint |= bStrInStr(achBuf,pchS[j]);
if (bPrint)
{
dprintf(achBuf);
}
if (++iCurrent >= gml)
iCurrent = 0;
if (CheckControlC())
return;
}
return;
rgnlog_help:
dprintf("\n rgnlog nnn [search1] [search2] [search3] [search4]\n");
dprintf("\t nnn - dumps the last n entries of the rgn log\n");
dprintf("\t search[n] - displays only entries containing one of n strings\n");
dprintf("\t NOTE: only works on checked builds. you must set bLogRgn at run time\n");
#endif // DOES NOT SUPPORT API64
EXIT_API(S_OK);
#endif
}