816 lines
20 KiB
C++
816 lines
20 KiB
C++
|
/*++
|
|||
|
|
|||
|
|
|||
|
Copyright (c) 1998-1999 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
dbglkrh.cxx
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
LKRhash support
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
George V. Reilly (GeorgeRe) 22-Feb-1999
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "inetdbgp.h"
|
|||
|
|
|||
|
#ifdef LOCK_INSTRUMENTATION
|
|||
|
LONG CLKRLinearHashTable::CBucket::sm_cBuckets = 0;
|
|||
|
LONG CLKRLinearHashTable::sm_cTables = 0;
|
|||
|
#endif // LOCK_INSTRUMENTATION
|
|||
|
|
|||
|
// #define SAMPLE_LKRHASH_TESTCLASS
|
|||
|
// #include <lkrhash.h>
|
|||
|
|
|||
|
|
|||
|
// There are several different DLLs in the IISRTL family. This is to
|
|||
|
// allow us to set the name of the DLL on the fly.
|
|||
|
// TODO: add a command to set this name dynamically.
|
|||
|
CHAR g_szIisRtlName[MAX_PATH] = IISRTL_NAME;
|
|||
|
|
|||
|
// sprintf-formatted string, e.g., "&%s!CLKRHashTable__sm_llGlobalList"
|
|||
|
// Has to return LPSTR, not LPCSTR, because GetExpression is not const-correct
|
|||
|
LPSTR
|
|||
|
IisRtlVar(
|
|||
|
LPCSTR pszFormat)
|
|||
|
{
|
|||
|
// we can get away with a static CHAR[] because debugger extensions
|
|||
|
// are single-threaded
|
|||
|
static CHAR szSymbol[MAX_SYMBOL_LEN];
|
|||
|
|
|||
|
sprintf(szSymbol, pszFormat, g_szIisRtlName);
|
|||
|
return szSymbol;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
class CTest
|
|||
|
{
|
|||
|
public:
|
|||
|
enum {BUFFSIZE=20};
|
|||
|
|
|||
|
int m_n; // This will also be a key
|
|||
|
char m_sz[BUFFSIZE]; // This will be the primary key
|
|||
|
bool m_fWhatever;
|
|||
|
mutable LONG m_cRefs; // Reference count for lifetime management.
|
|||
|
// Must be mutable to use 'const CTest*' in
|
|||
|
// hashtables
|
|||
|
|
|||
|
CTest(int n, const char* psz, bool f)
|
|||
|
: m_n(n), m_fWhatever(f), m_cRefs(0)
|
|||
|
{
|
|||
|
strncpy(m_sz, psz, BUFFSIZE-1);
|
|||
|
m_sz[BUFFSIZE-1] = '\0';
|
|||
|
}
|
|||
|
|
|||
|
~CTest()
|
|||
|
{
|
|||
|
IRTLASSERT(m_cRefs == 0);
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
BOOL
|
|||
|
TestEnum(
|
|||
|
IN const void* pvParam,
|
|||
|
IN DWORD dwSignature,
|
|||
|
IN INT nVerbose)
|
|||
|
{
|
|||
|
CTest* pTest = (CTest*) pvParam;
|
|||
|
CTest tst(0, "", 0);
|
|||
|
ReadMemory(pTest, &tst, sizeof(tst), NULL);
|
|||
|
dprintf("%8p: %d %s %d %d \n",
|
|||
|
pTest, tst.m_n, tst.m_sz, tst.m_fWhatever, tst.m_cRefs);
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
// Dummy implementations so that we can link
|
|||
|
|
|||
|
CLKRLinearHashTable::CLKRLinearHashTable(
|
|||
|
LPCSTR pszName, // An identifier for debugging
|
|||
|
PFnExtractKey pfnExtractKey, // Extract key from record
|
|||
|
PFnCalcKeyHash pfnCalcKeyHash, // Calculate hash signature of key
|
|||
|
PFnEqualKeys pfnEqualKeys, // Compare two keys
|
|||
|
PFnAddRefRecord pfnAddRefRecord,// AddRef in FindKey, etc
|
|||
|
double maxload, // Upperbound on average chain length
|
|||
|
DWORD initsize, // Initial size of hash table.
|
|||
|
DWORD num_subtbls // for signature compatiblity
|
|||
|
// with CLKRHashTable
|
|||
|
)
|
|||
|
#ifdef LKR_NEWCODE
|
|||
|
: m_nTableLockType(TableLock::LockType()),
|
|||
|
m_nBucketLockType(BucketLock::LockType()),
|
|||
|
m_phtParent(NULL)
|
|||
|
#endif // LKR_NEWCODE
|
|||
|
{}
|
|||
|
|
|||
|
#ifdef LKR_NEWCODE
|
|||
|
CLKRLinearHashTable::CLKRLinearHashTable(
|
|||
|
LPCSTR pszName, // An identifier for debugging
|
|||
|
PFnExtractKey pfnExtractKey, // Extract key from record
|
|||
|
PFnCalcKeyHash pfnCalcKeyHash, // Calculate hash signature of key
|
|||
|
PFnEqualKeys pfnEqualKeys, // Compare two keys
|
|||
|
PFnAddRefRecord pfnAddRefRecord,// AddRef in FindKey, etc
|
|||
|
double maxload, // Upperbound on average chain length
|
|||
|
DWORD initsize, // Initial size of hash table.
|
|||
|
CLKRHashTable* phtParent // Owning table.
|
|||
|
)
|
|||
|
: m_nTableLockType(TableLock::LockType()),
|
|||
|
m_nBucketLockType(BucketLock::LockType()),
|
|||
|
m_phtParent(NULL)
|
|||
|
{}
|
|||
|
#endif // LKR_NEWCODE
|
|||
|
|
|||
|
CLKRLinearHashTable::~CLKRLinearHashTable()
|
|||
|
{}
|
|||
|
|
|||
|
CLKRHashTable::CLKRHashTable(
|
|||
|
LPCSTR pszName, // An identifier for debugging
|
|||
|
PFnExtractKey pfnExtractKey, // Extract key from record
|
|||
|
PFnCalcKeyHash pfnCalcKeyHash, // Calculate hash signature of key
|
|||
|
PFnEqualKeys pfnEqualKeys, // Compare two keys
|
|||
|
PFnAddRefRecord pfnAddRefRecord,// AddRef in FindKey, etc
|
|||
|
double maxload, // Upperbound on average chain length
|
|||
|
DWORD initsize, // Initial size of hash table.
|
|||
|
DWORD num_subtbls // #subordinate hash tables
|
|||
|
)
|
|||
|
{}
|
|||
|
|
|||
|
CLKRHashTable::~CLKRHashTable()
|
|||
|
{}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/************************************************************
|
|||
|
* Dump LKRhash tables
|
|||
|
************************************************************/
|
|||
|
const char*
|
|||
|
LKRC2String(
|
|||
|
LK_RETCODE lkrc)
|
|||
|
{
|
|||
|
const char* psz = NULL;
|
|||
|
|
|||
|
switch (lkrc)
|
|||
|
{
|
|||
|
case LK_UNUSABLE:
|
|||
|
psz = "LK_UNUSABLE";
|
|||
|
break;
|
|||
|
case LK_ALLOC_FAIL:
|
|||
|
psz = "LK_ALLOC_FAIL";
|
|||
|
break;
|
|||
|
case LK_BAD_ITERATOR:
|
|||
|
psz = "LK_BAD_ITERATOR";
|
|||
|
break;
|
|||
|
case LK_BAD_RECORD:
|
|||
|
psz = "LK_BAD_RECORD";
|
|||
|
break;
|
|||
|
case LK_BAD_PARAMETERS:
|
|||
|
psz = "LK_BAD_PARAMETERS";
|
|||
|
break;
|
|||
|
case LK_NOT_INITIALIZED:
|
|||
|
psz = "LK_NOT_INITIALIZED";
|
|||
|
break;
|
|||
|
case LK_SUCCESS:
|
|||
|
psz = "LK_SUCCESS";
|
|||
|
break;
|
|||
|
case LK_KEY_EXISTS:
|
|||
|
psz = "LK_KEY_EXISTS";
|
|||
|
break;
|
|||
|
case LK_NO_SUCH_KEY:
|
|||
|
psz = "LK_NO_SUCH_KEY";
|
|||
|
break;
|
|||
|
case LK_NO_MORE_ELEMENTS:
|
|||
|
psz = "LK_NO_MORE_ELEMENTS";
|
|||
|
break;
|
|||
|
default:
|
|||
|
psz = "Unknown LK_RETCODE";
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
return psz;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
DefaultLKRhashEnum(
|
|||
|
IN const void* pvParam,
|
|||
|
IN DWORD dwSignature,
|
|||
|
IN INT nVerbose)
|
|||
|
{
|
|||
|
dprintf("%8p (%08x)\n", pvParam, dwSignature);
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
typedef CLKRLinearHashTable::CBucket CBucket;
|
|||
|
typedef CLKRLinearHashTable::CNodeClump CNodeClump;
|
|||
|
typedef CLKRLinearHashTable::CSegment CSegment;
|
|||
|
typedef CLKRLinearHashTable::CSmallSegment CSmallSegment;
|
|||
|
typedef CLKRLinearHashTable::CMediumSegment CMediumSegment;
|
|||
|
typedef CLKRLinearHashTable::CLargeSegment CLargeSegment;
|
|||
|
typedef CLKRLinearHashTable::CDirEntry CDirEntry;
|
|||
|
|
|||
|
enum {
|
|||
|
NODES_PER_CLUMP = CNodeClump::NODES_PER_CLUMP,
|
|||
|
HASH_INVALID_SIGNATURE = CLKRLinearHashTable::HASH_INVALID_SIGNATURE,
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
EnumerateBucketChain(
|
|||
|
IN PFN_ENUM_LKRHASH pfnEnum,
|
|||
|
IN LOCK_LOCKTYPE ltBucketLockType,
|
|||
|
IN CBucket* pbkt,
|
|||
|
IN INT nVerbose)
|
|||
|
{
|
|||
|
PSTR cmdName = "lkrhash";
|
|||
|
CBucket bkt;
|
|||
|
CNodeClump nc;
|
|||
|
CNodeClump* pncCurr;
|
|||
|
CNodeClump* pncPrev = NULL;
|
|||
|
DWORD cNodes = 0;
|
|||
|
|
|||
|
ReadMemory(pbkt, &bkt, sizeof(bkt), NULL);
|
|||
|
|
|||
|
PrintLock(ltBucketLockType, &pbkt->m_Lock, nVerbose);
|
|||
|
|
|||
|
for (pncCurr = (CNodeClump*) ((PBYTE) pbkt + LockSize(ltBucketLockType));
|
|||
|
pncCurr != NULL;
|
|||
|
pncPrev = pncCurr, pncCurr = nc.m_pncNext)
|
|||
|
{
|
|||
|
DWORD i, c;
|
|||
|
|
|||
|
ReadMemory(pncCurr, &nc, sizeof(nc), NULL);
|
|||
|
|
|||
|
for (i = c = 0; i < NODES_PER_CLUMP; i++)
|
|||
|
{
|
|||
|
if (nc.m_dwKeySigs[i] == HASH_INVALID_SIGNATURE)
|
|||
|
c++;
|
|||
|
}
|
|||
|
|
|||
|
if (c == NODES_PER_CLUMP)
|
|||
|
{
|
|||
|
dprintf(" 0-%d: -- empty\n", NODES_PER_CLUMP);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
for (i = 0; i < NODES_PER_CLUMP; i++)
|
|||
|
{
|
|||
|
if (nc.m_dwKeySigs[i] == HASH_INVALID_SIGNATURE)
|
|||
|
{
|
|||
|
dprintf(" %d: --\n", i);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
(*pfnEnum)(nc.m_pvNode[i], nc.m_dwKeySigs[i], nVerbose);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (CheckControlC())
|
|||
|
{
|
|||
|
dprintf("\n^C\n");
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
const DWORD MAX_NODES = 20;
|
|||
|
if (++cNodes > MAX_NODES)
|
|||
|
{
|
|||
|
dprintf("inetdbg.%s: Bucket chain contains more than %d nodes! "
|
|||
|
"Corrupted?\n", cmdName, MAX_NODES);
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
EnumerateLKRLinearHashTable(
|
|||
|
IN PFN_ENUM_LKRHASH pfnEnum,
|
|||
|
IN CLKRLinearHashTable* plht,
|
|||
|
IN INT nVerbose)
|
|||
|
{
|
|||
|
PSTR cmdName = "lkrhash";
|
|||
|
CLKRLinearHashTable lht(NULL, NULL, NULL, NULL, NULL);
|
|||
|
INT i;
|
|||
|
BOOL fRet = FALSE;
|
|||
|
LOCK_LOCKTYPE ltTableLockType = LOCK_SPINLOCK;
|
|||
|
LOCK_LOCKTYPE ltBucketLockType = LOCK_SPINLOCK;
|
|||
|
CDirEntry* paDirSegs = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Read the header, perform some sanity checks.
|
|||
|
//
|
|||
|
|
|||
|
if (!ReadMemory(plht, &lht, sizeof(lht), NULL) )
|
|||
|
{
|
|||
|
dprintf("inetdbg.%s: cannot read memory @ %p\n",
|
|||
|
cmdName, (PVOID)plht);
|
|||
|
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
dprintf(
|
|||
|
"\ninetdbg.%s: @ %p:\n"
|
|||
|
" CLKRLinearHashTable Signature = %08lx '%c%c%c%c' (%s), \"%s\",\n"
|
|||
|
" State = %d (%s)\n",
|
|||
|
cmdName,
|
|||
|
plht,
|
|||
|
lht.m_dwSignature,
|
|||
|
DECODE_SIGNATURE(lht.m_dwSignature),
|
|||
|
lht.m_dwSignature == CLKRLinearHashTable::SIGNATURE
|
|||
|
? "OK" : (lht.m_dwSignature == CLKRLinearHashTable::SIGNATURE_FREE
|
|||
|
? "FREED" : "INVALID"),
|
|||
|
lht.m_szName,
|
|||
|
lht.m_lkrcState, LKRC2String(lht.m_lkrcState));
|
|||
|
|
|||
|
if (nVerbose == 0)
|
|||
|
goto done;
|
|||
|
|
|||
|
#ifdef LKR_NEWCODE
|
|||
|
ltTableLockType = (LOCK_LOCKTYPE) lht.m_nTableLockType;
|
|||
|
ltBucketLockType = (LOCK_LOCKTYPE) lht.m_nBucketLockType;
|
|||
|
dprintf(
|
|||
|
" TableLock = %s, BucketLock = %s, Parent CLKRHashTable = %p\n",
|
|||
|
LockName(ltTableLockType),
|
|||
|
LockName(ltBucketLockType),
|
|||
|
lht.m_phtParent);
|
|||
|
#endif // LKR_NEWCODE
|
|||
|
|
|||
|
dprintf(
|
|||
|
" Size = %d, SegBits = %d, SegSize = %d, SegMask = %x\n",
|
|||
|
lht.m_lkts, lht.m_dwSegBits, lht.m_dwSegSize, lht.m_dwSegMask);
|
|||
|
dprintf(
|
|||
|
" MaxLoad = %3.1f, paDirSegs = %p, cDirSegs = %d\n",
|
|||
|
lht.m_MaxLoad, lht.m_paDirSegs, lht.m_cDirSegs);
|
|||
|
dprintf(
|
|||
|
" cRecords = %d, cActiveBuckets = %d, BucketSpins = %hd\n",
|
|||
|
lht.m_cRecords, lht.m_cActiveBuckets, lht.m_wBucketLockSpins);
|
|||
|
dprintf(
|
|||
|
" nLevel = %d, dwBktAddrMask = %x, iExpansionIdx = %d\n",
|
|||
|
lht.m_nLevel, lht.m_dwBktAddrMask, lht.m_iExpansionIdx);
|
|||
|
|
|||
|
PrintLock(ltTableLockType, &plht->m_Lock, nVerbose);
|
|||
|
|
|||
|
if (nVerbose == 1)
|
|||
|
goto done;
|
|||
|
|
|||
|
paDirSegs = (CDirEntry*) calloc(lht.m_cDirSegs, sizeof(CDirEntry));
|
|||
|
|
|||
|
if (paDirSegs == NULL) {
|
|||
|
dprintf("Out of memory\n");
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
ReadMemory(lht.m_paDirSegs, paDirSegs,
|
|||
|
sizeof(CDirEntry) * lht.m_cDirSegs, NULL);
|
|||
|
|
|||
|
for (i = 0; i < (INT) (lht.m_cDirSegs * lht.m_dwSegSize); i++)
|
|||
|
{
|
|||
|
const DWORD iSeg = i >> lht.m_dwSegBits;
|
|||
|
CLargeSegment* pseg =
|
|||
|
static_cast<CLargeSegment*>(paDirSegs[iSeg].m_pseg);
|
|||
|
|
|||
|
if ((i & lht.m_dwSegMask) == 0)
|
|||
|
dprintf("Segment %d: %p\n", iSeg, pseg);
|
|||
|
|
|||
|
if (pseg == NULL)
|
|||
|
continue;
|
|||
|
|
|||
|
if (nVerbose >= 2)
|
|||
|
{
|
|||
|
CBucket* const pbkt = pseg->m_bktSlots + (i & lht.m_dwSegMask);
|
|||
|
|
|||
|
dprintf("Bucket %4d: ", i);
|
|||
|
if (!EnumerateBucketChain(pfnEnum, ltBucketLockType,
|
|||
|
pbkt, nVerbose))
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
if (CheckControlC())
|
|||
|
{
|
|||
|
dprintf("\n^C\n");
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
done:
|
|||
|
fRet = TRUE;
|
|||
|
|
|||
|
cleanup:
|
|||
|
if (paDirSegs)
|
|||
|
free(paDirSegs);
|
|||
|
return fRet;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
EnumerateLKRhashTable(
|
|||
|
IN PFN_ENUM_LKRHASH pfnEnum,
|
|||
|
IN CLKRHashTable* pht,
|
|||
|
IN INT nVerbose)
|
|||
|
{
|
|||
|
CLKRHashTable ht(NULL, NULL, NULL, NULL, NULL);
|
|||
|
PSTR cmdName = "lkrhash";
|
|||
|
CLKRLinearHashTable** palhtDir = NULL;
|
|||
|
UINT i;
|
|||
|
BOOL fRet = FALSE;
|
|||
|
|
|||
|
//
|
|||
|
// Read the header, perform some sanity checks.
|
|||
|
//
|
|||
|
|
|||
|
if (!ReadMemory(pht, &ht, sizeof(ht), NULL) )
|
|||
|
{
|
|||
|
dprintf("inetdbg.%s: cannot read memory @ %p\n",
|
|||
|
cmdName, (PVOID)pht);
|
|||
|
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
dprintf(
|
|||
|
"inetdbg.%s: @ %p:\n"
|
|||
|
" CLKRHashTable Signature = %08lx '%c%c%c%c' (%s), \"%s\",\n"
|
|||
|
" %d subtables, State = %d (%s)\n",
|
|||
|
cmdName,
|
|||
|
pht,
|
|||
|
ht.m_dwSignature,
|
|||
|
DECODE_SIGNATURE(ht.m_dwSignature),
|
|||
|
ht.m_dwSignature == CLKRHashTable::SIGNATURE
|
|||
|
? "OK"
|
|||
|
: ht.m_dwSignature == CLKRHashTable::SIGNATURE_FREE
|
|||
|
? "FREED"
|
|||
|
: "INVALID",
|
|||
|
ht.m_szName,
|
|||
|
ht.m_cSubTables,
|
|||
|
ht.m_lkrcState, LKRC2String(ht.m_lkrcState)
|
|||
|
);
|
|||
|
|
|||
|
if (nVerbose == 0)
|
|||
|
goto done;
|
|||
|
|
|||
|
palhtDir = (CLKRLinearHashTable**) calloc(ht.m_cSubTables,
|
|||
|
sizeof(CLKRLinearHashTable*));
|
|||
|
if (!palhtDir)
|
|||
|
goto cleanup;
|
|||
|
|
|||
|
if (!ReadMemory(ht.m_palhtDir, palhtDir,
|
|||
|
ht.m_cSubTables * sizeof(CLKRLinearHashTable*), NULL))
|
|||
|
goto cleanup;
|
|||
|
|
|||
|
for (i = 0; i < ht.m_cSubTables; ++i)
|
|||
|
{
|
|||
|
dprintf("%d : ", i);
|
|||
|
if (!EnumerateLKRLinearHashTable(pfnEnum, palhtDir[i], nVerbose))
|
|||
|
break;
|
|||
|
|
|||
|
if (CheckControlC())
|
|||
|
{
|
|||
|
dprintf("\n^C\n");
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
done:
|
|||
|
fRet = TRUE;
|
|||
|
|
|||
|
cleanup:
|
|||
|
free(palhtDir);
|
|||
|
|
|||
|
return fRet;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
PrintLKRLinearHashTableThunk(
|
|||
|
PVOID psdDebuggee,
|
|||
|
PVOID psdDebugger,
|
|||
|
CHAR chVerbosity,
|
|||
|
DWORD iThunk)
|
|||
|
{
|
|||
|
DWORD dwSig = ((CLKRLinearHashTable*) psdDebugger)->m_dwSignature;
|
|||
|
|
|||
|
if (dwSig != CLKRLinearHashTable::SIGNATURE)
|
|||
|
{
|
|||
|
dprintf( "CLKRLinearHashTable(%08p) signature %08lx '%c%c%c%c' doesn't"
|
|||
|
" match expected: %08lx\n",
|
|||
|
psdDebuggee, dwSig, DECODE_SIGNATURE(dwSig),
|
|||
|
CLKRLinearHashTable::SIGNATURE
|
|||
|
);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
EnumerateLKRLinearHashTable(DefaultLKRhashEnum,
|
|||
|
(CLKRLinearHashTable*) psdDebuggee,
|
|||
|
chVerbosity);
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
PrintLKRHashTableThunk(
|
|||
|
PVOID psdDebuggee,
|
|||
|
PVOID psdDebugger,
|
|||
|
CHAR chVerbosity,
|
|||
|
DWORD iThunk)
|
|||
|
{
|
|||
|
DWORD dwSig = ((CLKRHashTable*) psdDebugger)->m_dwSignature;
|
|||
|
if (dwSig != CLKRHashTable::SIGNATURE)
|
|||
|
{
|
|||
|
dprintf( "CLKRHashTable(%08p) signature %08lx '%c%c%c%c' doesn't"
|
|||
|
" match expected: %08lx\n",
|
|||
|
psdDebuggee,
|
|||
|
dwSig, DECODE_SIGNATURE(dwSig),
|
|||
|
CLKRHashTable::SIGNATURE
|
|||
|
);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
EnumerateLKRhashTable(DefaultLKRhashEnum, (CLKRHashTable*) psdDebuggee,
|
|||
|
chVerbosity);
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
DumpLKRsList(
|
|||
|
IN INT nVerbose)
|
|||
|
{
|
|||
|
CLockedDoubleList* plstHashTables = (CLockedDoubleList*) GetExpression(
|
|||
|
IisRtlVar("&%s!CLKRHashTable__sm_llGlobalList"));
|
|||
|
|
|||
|
if (NULL == plstHashTables)
|
|||
|
{
|
|||
|
dprintf("Unable to get %s\n",
|
|||
|
IisRtlVar("%s!CLKRHashTable__sm_llGlobalList"));
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
dprintf("\nGlobal List of CLKRHashTables\n");
|
|||
|
|
|||
|
EnumLinkedList( (LIST_ENTRY*) &plstHashTables->m_list.m_leHead,
|
|||
|
PrintLKRHashTableThunk,
|
|||
|
(CHAR) nVerbose,
|
|||
|
sizeof(CLKRHashTable),
|
|||
|
FIELD_OFFSET( CLKRHashTable, m_leGlobalList)
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
plstHashTables = (CLockedDoubleList*) GetExpression(
|
|||
|
IisRtlVar( "&%s!CLKRLinearHashTable__sm_llGlobalList"));
|
|||
|
|
|||
|
if (NULL == plstHashTables)
|
|||
|
{
|
|||
|
dprintf("Unable to get %s\n",
|
|||
|
IisRtlVar("!CLKRLinearHashTable__sm_llGlobalList"));
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
dprintf("\nGlobal List of CLKRLinearHashTables\n");
|
|||
|
|
|||
|
EnumLinkedList( (LIST_ENTRY*) &plstHashTables->m_list.m_leHead,
|
|||
|
PrintLKRLinearHashTableThunk,
|
|||
|
(CHAR) nVerbose,
|
|||
|
sizeof(CLKRLinearHashTable),
|
|||
|
FIELD_OFFSET( CLKRLinearHashTable, m_leGlobalList)
|
|||
|
);
|
|||
|
return;
|
|||
|
} // DumpLKRsList()
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DECLARE_API( lkrhash )
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function is called as an NTSD extension to format and dump
|
|||
|
an LKRhash table.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hCurrentProcess - Supplies a handle to the current process (at the
|
|||
|
time the extension was called).
|
|||
|
|
|||
|
hCurrentThread - Supplies a handle to the current thread (at the
|
|||
|
time the extension was called).
|
|||
|
|
|||
|
CurrentPc - Supplies the current pc at the time the extension is
|
|||
|
called.
|
|||
|
|
|||
|
lpExtensionApis - Supplies the address of the functions callable
|
|||
|
by this extension.
|
|||
|
|
|||
|
lpArgumentString - Supplies the asciiz string that describes the
|
|||
|
ansi string to be dumped.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
INIT_API();
|
|||
|
|
|||
|
ULONG_PTR lkrAddress = 0;
|
|||
|
INT nVerbose = 0;
|
|||
|
PSTR cmdName = "lkrhash";
|
|||
|
|
|||
|
//
|
|||
|
// Skip leading blanks.
|
|||
|
//
|
|||
|
|
|||
|
while( *lpArgumentString == ' ' ||
|
|||
|
*lpArgumentString == '\t' ) {
|
|||
|
lpArgumentString++;
|
|||
|
}
|
|||
|
|
|||
|
if( *lpArgumentString == '\0' ) {
|
|||
|
PrintUsage( cmdName );
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if ( *lpArgumentString == '-' )
|
|||
|
{
|
|||
|
lpArgumentString++;
|
|||
|
|
|||
|
if ( *lpArgumentString == 'h' )
|
|||
|
{
|
|||
|
PrintUsage( cmdName );
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if ( *lpArgumentString == 'l' ) {
|
|||
|
lpArgumentString++;
|
|||
|
if ('0' <= *lpArgumentString && *lpArgumentString <= '9' ) {
|
|||
|
nVerbose = *lpArgumentString++ - '0';
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ( *lpArgumentString == 'v' )
|
|||
|
{
|
|||
|
lpArgumentString++;
|
|||
|
nVerbose = 99;
|
|||
|
}
|
|||
|
|
|||
|
if ( *lpArgumentString == 'g' )
|
|||
|
{
|
|||
|
lpArgumentString++;
|
|||
|
DumpLKRsList(nVerbose);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
while( *lpArgumentString == ' ' ||
|
|||
|
*lpArgumentString == '\t' ) {
|
|||
|
lpArgumentString++;
|
|||
|
}
|
|||
|
|
|||
|
lkrAddress = (ULONG_PTR) GetExpression( lpArgumentString );
|
|||
|
|
|||
|
if (lkrAddress == 0) {
|
|||
|
|
|||
|
dprintf(
|
|||
|
"inetdbg.%s: cannot evaluate \"%s\"\n",
|
|||
|
cmdName,
|
|||
|
lpArgumentString
|
|||
|
);
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Skip to end of expression, then skip any blanks.
|
|||
|
//
|
|||
|
|
|||
|
while( *lpArgumentString != ' ' &&
|
|||
|
*lpArgumentString != '\t' &&
|
|||
|
*lpArgumentString != '\0' ) {
|
|||
|
lpArgumentString++;
|
|||
|
}
|
|||
|
|
|||
|
DWORD dwSig;
|
|||
|
|
|||
|
if (!ReadMemory(lkrAddress, &dwSig, sizeof(dwSig), NULL) )
|
|||
|
{
|
|||
|
dprintf("inetdbg.%s: cannot read memory @ %p\n",
|
|||
|
cmdName, (PVOID)lkrAddress);
|
|||
|
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
if (dwSig == CLKRHashTable::SIGNATURE ||
|
|||
|
dwSig == CLKRHashTable::SIGNATURE_FREE)
|
|||
|
{
|
|||
|
EnumerateLKRhashTable(DefaultLKRhashEnum,
|
|||
|
(CLKRHashTable*) lkrAddress,
|
|||
|
nVerbose);
|
|||
|
}
|
|||
|
else if (dwSig == CLKRLinearHashTable::SIGNATURE ||
|
|||
|
dwSig == CLKRLinearHashTable::SIGNATURE_FREE)
|
|||
|
{
|
|||
|
EnumerateLKRLinearHashTable(DefaultLKRhashEnum,
|
|||
|
(CLKRLinearHashTable*) lkrAddress,
|
|||
|
nVerbose);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
dprintf("inetdbg.%s: %p does not contain a valid LKRhash table\n",
|
|||
|
cmdName, (PVOID)lkrAddress);
|
|||
|
}
|
|||
|
|
|||
|
cleanup:
|
|||
|
return;
|
|||
|
} // DECLARE_API( lkrhash )
|
|||
|
|
|||
|
|
|||
|
DECLARE_API( testhash )
|
|||
|
{
|
|||
|
INIT_API();
|
|||
|
|
|||
|
ULONG_PTR lkrAddress = 0;
|
|||
|
INT nVerbose = 0;
|
|||
|
PSTR cmdName = "testhash";
|
|||
|
|
|||
|
//
|
|||
|
// Skip leading blanks.
|
|||
|
//
|
|||
|
|
|||
|
while( *lpArgumentString == ' ' ||
|
|||
|
*lpArgumentString == '\t' ) {
|
|||
|
lpArgumentString++;
|
|||
|
}
|
|||
|
|
|||
|
if( *lpArgumentString == '\0' ) {
|
|||
|
PrintUsage( cmdName );
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if ( *lpArgumentString == '-' )
|
|||
|
{
|
|||
|
lpArgumentString++;
|
|||
|
|
|||
|
if ( *lpArgumentString == 'h' )
|
|||
|
{
|
|||
|
PrintUsage( cmdName );
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if ( *lpArgumentString == 'l' ) {
|
|||
|
lpArgumentString++;
|
|||
|
if ('0' <= *lpArgumentString && *lpArgumentString <= '9' ) {
|
|||
|
nVerbose = *lpArgumentString++ - '0';
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
while( *lpArgumentString == ' ' ||
|
|||
|
*lpArgumentString == '\t' ) {
|
|||
|
lpArgumentString++;
|
|||
|
}
|
|||
|
|
|||
|
lkrAddress = (ULONG_PTR)GetExpression( lpArgumentString );
|
|||
|
|
|||
|
if( lkrAddress == 0 ) {
|
|||
|
|
|||
|
dprintf(
|
|||
|
"inetdbg.%s: cannot evaluate \"%s\"\n",
|
|||
|
cmdName,
|
|||
|
lpArgumentString
|
|||
|
);
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Skip to end of expression, then skip any blanks.
|
|||
|
//
|
|||
|
|
|||
|
while( *lpArgumentString != ' ' &&
|
|||
|
*lpArgumentString != '\t' &&
|
|||
|
*lpArgumentString != '\0' ) {
|
|||
|
lpArgumentString++;
|
|||
|
}
|
|||
|
|
|||
|
EnumerateLKRhashTable(TestEnum,
|
|||
|
(CLKRHashTable*) lkrAddress,
|
|||
|
nVerbose);
|
|||
|
|
|||
|
} // DECLARE_API( testhash )
|
|||
|
|
|||
|
|