windows-nt/Source/XPSP1/NT/base/tools/kdexts2/filelock.c

449 lines
9.2 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
FileLock.c
Abstract:
WinDbg Extension Api
Author:
Dan Lovinger 12-Apr-96
Environment:
User Mode.
Revision History:
--*/
#include "precomp.h"
//
// Common node type codes
//
#define NTFS_NTC_SCB_DATA 0x705
#define FAT_NTC_FCB 0x502
//
// dprintf is really expensive to iteratively call to do the indenting,
// so we just build up some avaliable spaces to mangle as required
//
#define MIN(a,b) ((a) > (b) ? (b) : (a))
#define MAXINDENT 128
#define INDENTSTEP 2
#define MakeSpace(I) Space[MIN((I)*INDENTSTEP, MAXINDENT)] = '\0'
#define RestoreSpace(I) Space[MIN((I)*INDENTSTEP, MAXINDENT)] = ' '
CHAR Space[MAXINDENT*INDENTSTEP + 1];
__inline VOID CheckForBreak()
/*++
Purpose:
Encapsulate control c checking code
Arguments:
None
Return:
None, raises if break is needed
--*/
{
if ( CheckControlC() ) {
RaiseException(0, EXCEPTION_NONCONTINUABLE, 0, NULL);
}
}
//
// Helper macros for printing 64bit quantities
//
#define SplitLI(LI) (LI).HighPart, (LI).LowPart
VOID
DumpFileLockInfo(
ULONG64 pFileLockInfo,
ULONG Indent
)
/*++
Purpose:
Dump the local internal FILE_LOCK_INFO structure
Arguments:
pFileLock - debugger address of FILE_LOCK_INFO to dump
Return:
None
--*/
{
MakeSpace(Indent);
InitTypeRead(pFileLockInfo, FILE_LOCK_INFO);
dprintf("%sStart = %08I64x Length = %08I64x End = %08I64x (%s)\n"
"%sKey = %08x FileOb = %08p ProcId = %08p\n",
Space,
ReadField(StartingByte),
ReadField(Length),
ReadField(EndingByte),
(ReadField(ExclusiveLock) ? "Ex":"Sh"),
Space,
(ULONG) ReadField(Key),
ReadField(FileObject),
ReadField(ProcessId));
RestoreSpace(Indent);
}
__inline
ULONG64
ExLockAddress(
ULONG64 ExLockSplayLinks
)
{
static ULONG Off=0, GotOff=0;
if (!GotOff) {
if (!GetFieldOffset("nt!_EX_LOCK", "Links", &Off))
GotOff = TRUE;
}
return ExLockSplayLinks ?
( ExLockSplayLinks - Off ) : 0;
}
VOID
DumpExclusiveNode(
ULONG64 ExclusiveNodeSplayLinks,
ULONG Indent
)
/*++
Purpose:
Dump an exclusive lock node
Arguments:
ExclusiveNodeSplayLinks - splay links of an exclusive node
Indent - indent level to use
Return:
None
--*/
{
ULONG64 Parent, pExLock;
ULONG Off;
pExLock = ExLockAddress(ExclusiveNodeSplayLinks);
if (GetFieldValue(pExLock, "nt!_EX_LOCK", "Links.Parent", Parent)) {
dprintf("Cannot read nt!_EX_LOCK at %p.\n", pExLock);
return;
}
MakeSpace(Indent);
InitTypeRead(pExLock, EX_LOCK);
dprintf("%sLock @ %08x ("
"P = %08x R = %08x L = %08x)\n",
Space,
pExLock,
ExLockAddress(Parent),
ExLockAddress(ReadField(Links.RightChild)),
ExLockAddress(ReadField(Links.LeftChild)));
RestoreSpace(Indent);
GetFieldOffset("nt!_EX_LOCK", "LockInfo", &Off);
DumpFileLockInfo(pExLock + Off, Indent);
}
__inline
ULONG64
LockTreeAddress(
ULONG64 LockTreeSplayLinks
)
{
static ULONG Off=0, GotOff=0;
if (!GotOff) {
if (GetFieldOffset("nt!_LOCKTREE_NODE", "Links", &Off))
GotOff = TRUE;
}
return LockTreeSplayLinks ?
( LockTreeSplayLinks - Off ) : 0;
}
VOID
DumpSharedNode(
ULONG64 SharedNodeSplayLinks,
ULONG Indent
)
/*++
Purpose:
Dump a shared lock node
Arguments:
SharedNodeSplayLinks - splay links of an exclusive node
Indent - indent level to use
Return:
None
--*/
{
ULONG64 pLockTreeNode;
ULONG64 pShLock;
ULONG64 pLink, Next;
ULONG Off, LockInfoOff;
pLockTreeNode = LockTreeAddress(SharedNodeSplayLinks);
if (GetFieldValue(pLockTreeNode, "nt!_LOCKTREE_NODE", "Locks.Next", Next)) {
dprintf("Cannot read nt!_LOCKTREE_NODE at %p\n", pLockTreeNode);
return;
}
MakeSpace(Indent);
InitTypeRead(pLockTreeNode, nt!_LOCKTREE_NODE);
dprintf("%sLockTreeNode @ %08p ("
"P = %08p R = %08p L = %08p)%s\n",
Space,
pLockTreeNode,
LockTreeAddress(ReadField(Links.Parent)),
LockTreeAddress(ReadField(Links.RightChild)),
LockTreeAddress(ReadField(Links.LeftChild)),
(ReadField(HoleyNode) ? " (Holey)" : ""));
RestoreSpace(Indent);
GetFieldOffset("nt!_SH_LOCK", "Link", &Off);
GetFieldOffset("nt!_SH_LOCK", "LockInfo", &LockInfoOff);
for (pLink = Next;
pLink;
pLink = Next) {
CheckForBreak();
pShLock = ( pLink - Off);
if (GetFieldValue(pShLock, "nt!_SH_LOCK", "Link.Next", Next)) {
dprintf("Cannot read nt!_SH_LOCK AT %p.\n", pShLock);
return;
}
MakeSpace(Indent);
dprintf("%sLock @ %08p\n", Space, pShLock);
RestoreSpace(Indent);
DumpFileLockInfo(pShLock + LockInfoOff, Indent);
}
}
VOID
DumpFileLock(
ULONG64 pFileLock
)
/*++
Purpose:
Dump the fsrtl FILE_LOCK structure at debugee
Arguments:
pFileLock - debugee address of FILE_LOCK
Return:
None
--*/
{
ULONG64 pFileLockInfo;
ULONG64 pLockInfo;
ULONG Count;
ULONG64 LastReturnedLock, LockInformation, LowestLockOffset;
ULONG64 SharedLockTree, ExclusiveLockTree;
if (GetFieldValue(pFileLock, "FILE_LOCK", "LastReturnedLock", LastReturnedLock)) {
dprintf("Cannot read FILE_LOCK at %p\n", pFileLock);
return;
}
InitTypeRead(pFileLock, FILE_LOCK);
dprintf("FileLock @ %08p\n"
"FastIoIsQuestionable = %c\n"
"CompletionRoutine = %08p\n"
"UnlockRoutine = %08p\n"
"LastReturnedLock = %08p\n",
pFileLock,
ReadField(FastIoIsQuestionable) ? 'T':'F',
ReadField(CompleteLockIrpRoutine),
ReadField(UnlockRoutine),
LastReturnedLock);
LockInformation = ReadField(LockInformation);
if (LastReturnedLock != 0) {
ULONG Off;
//
// We never reset the enumeration info, so it can be out of date ...
//
GetFieldOffset("FILE_LOCK", "LastReturnedLockInfo", &Off);
dprintf("LastReturnedLockInfo:\n");
DumpFileLockInfo(pFileLock + Off, 0);
}
if (LockInformation == 0) {
dprintf("No Locks\n");
return;
} else {
if (GetFieldValue(LockInformation, "nt!_LOCK_INFO", "LowestLockOffset", LowestLockOffset)) {
dprintf("Canot read nt!_LOCK_INFO at %p\n", LockInformation);
return;
}
}
dprintf("LowestLockOffset = %08p\n\n", LowestLockOffset);
GetFieldValue(LockInformation, "nt!_LOCK_INFO", "LockQueue.SharedLockTree", SharedLockTree);
GetFieldValue(LockInformation, "nt!_LOCK_INFO", "LockQueue.ExclusiveLockTree", ExclusiveLockTree);
Count = DumpSplayTree(SharedLockTree, DumpSharedNode);
if (!Count) {
dprintf("No Shared Locks\n");
}
dprintf("\n");
Count = DumpSplayTree(ExclusiveLockTree, DumpExclusiveNode);
if (!Count) {
dprintf("No Exclusive Locks\n");
}
}
DECLARE_API( filelock )
/*++
Routine Description:
Dump file locks
Arguments:
arg - <Address>
Return Value:
None
--*/
{
ULONG64 FileLock = 0;
CSHORT NodeType = 0;
CSHORT FileType = 0;
ULONG64 FsContext = 0;
ULONG Offset;
RtlFillMemory(Space, sizeof(Space), ' ');
if ((FileLock = GetExpression(args)) == 0) {
//
// No args
//
return E_INVALIDARG;
}
//
// We raise out if the user whacketh control-c
//
__try {
//
// Test for fileobject
//
GetFieldValue( FileLock, "nt!_FILE_OBJECT", "Type", FileType );
if (FileType == IO_TYPE_FILE) {
//
// its really a fileobject so grab the fscontext
//
if (!GetFieldValue( FileLock, "nt!_FILE_OBJECT", "FsContext", FsContext )) {
GetFieldValue( FsContext, "nt!_FSRTL_COMMON_FCB_HEADER", "NodeTypeCode", NodeType );
dprintf( "%x\n", NodeType );
if (NodeType == NTFS_NTC_SCB_DATA) {
GetFieldValue( FsContext, "ntfs!_SCB", "ScbType.Data.FileLock", FileLock );
} else if (NodeType == FAT_NTC_FCB) {
GetFieldOffset( "fastfat!_FCB", "Specific", &Offset );
dprintf( "Offset: 0x%x\n", Offset );
FileLock = FsContext + Offset;
} else {
dprintf( "Unknown fscontext - you'll have to find the filelock within the fileobject manually\n" );
return S_OK;
}
}
if (FileLock == 0) {
dprintf( "There is no filelock in this fileobject\n" );
return S_OK;
}
}
DumpFileLock(FileLock);
} __except (EXCEPTION_EXECUTE_HANDLER) {
NOTHING;
}
return S_OK;
}