mirror of https://github.com/lianthony/NT4.0
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.
295 lines
5.6 KiB
295 lines
5.6 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Tunnel.c
|
|
|
|
Abstract:
|
|
|
|
WinDbg Extension Api
|
|
|
|
Author:
|
|
|
|
Dan Lovinger 2-Apr-96
|
|
|
|
Environment:
|
|
|
|
User Mode.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
//
|
|
// XXX This must be kept in sync with ntos\fsrtl\tunnel.c
|
|
//
|
|
// It isn't in a header file because it should be opaque
|
|
// outside of the tunneling module
|
|
//
|
|
|
|
typedef struct {
|
|
|
|
//
|
|
// Splay links in the Cache tree
|
|
//
|
|
|
|
RTL_SPLAY_LINKS CacheLinks;
|
|
|
|
//
|
|
// List links in the timer queue
|
|
//
|
|
|
|
LIST_ENTRY ListLinks;
|
|
|
|
//
|
|
// Time this entry was created (for constant time insert)
|
|
//
|
|
|
|
LARGE_INTEGER CreateTime;
|
|
|
|
//
|
|
// Directory these names are associated with
|
|
//
|
|
|
|
ULONGLONG DirKey;
|
|
|
|
//
|
|
// Flags for the entry
|
|
//
|
|
|
|
ULONG Flags;
|
|
|
|
//
|
|
// Long/Short names of the file
|
|
//
|
|
|
|
UNICODE_STRING LongName;
|
|
UNICODE_STRING ShortName;
|
|
|
|
//
|
|
// Opaque tunneled data
|
|
//
|
|
|
|
PVOID TunnelData;
|
|
ULONG TunnelDataLength;
|
|
|
|
} TUNNEL_NODE, *PTUNNEL_NODE;
|
|
|
|
//
|
|
// printf 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];
|
|
|
|
#define SplitLI(LI) (LI).HighPart, (LI).LowPart
|
|
#define SplitLL(LL) (ULONG)((LL) >> 32), (ULONG)((LL) & 0xffffffff)
|
|
|
|
VOID
|
|
DumpTunnelNode (
|
|
PTUNNEL_NODE Node,
|
|
PVOID pNode,
|
|
ULONG Indent
|
|
)
|
|
{
|
|
WCHAR ShortName[8+1+3];
|
|
WCHAR LongName[64];
|
|
|
|
//
|
|
// Grab the strings from the debugee
|
|
//
|
|
|
|
if (!ReadAtAddress(Node->ShortName.Buffer,
|
|
&ShortName,
|
|
Node->ShortName.Length,
|
|
NULL)) {
|
|
|
|
return;
|
|
}
|
|
|
|
if (!ReadAtAddress(Node->LongName.Buffer,
|
|
&LongName,
|
|
MIN(Node->LongName.Length, sizeof(LongName)),
|
|
NULL)) {
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Modify the node in-place so we can use normal printing
|
|
//
|
|
|
|
Node->LongName.Buffer = LongName;
|
|
Node->ShortName.Buffer = ShortName;
|
|
Node->LongName.Length = MIN(Node->LongName.Length, sizeof(LongName));
|
|
|
|
MakeSpace(Indent);
|
|
|
|
dprintf("%sNode @ %08x Cr %08x%08x DK %08x%08x [",
|
|
Space,
|
|
pNode,
|
|
SplitLI(Node->CreateTime),
|
|
SplitLL(Node->DirKey));
|
|
|
|
//
|
|
// Must be kept in sync with flag usage in fsrtl\tunnel.c
|
|
//
|
|
|
|
if (Node->Flags & 0x1)
|
|
dprintf("NLA");
|
|
else
|
|
dprintf("LA");
|
|
|
|
if (Node->Flags & 0x2)
|
|
dprintf(" KYS");
|
|
else
|
|
dprintf(" KYL");
|
|
|
|
dprintf("]\n");
|
|
|
|
dprintf("%sP %08x R %08x L %08x Sfn/Lfn \"%wZ\"/\"%wZ\"\n",
|
|
Space,
|
|
DbgRtlParent(Node->CacheLinks),
|
|
DbgRtlRightChild(Node->CacheLinks),
|
|
DbgRtlLeftChild(Node->CacheLinks),
|
|
&Node->ShortName,
|
|
&Node->LongName );
|
|
|
|
dprintf("%sF %08x B %08x\n",
|
|
Space,
|
|
Node->ListLinks.Flink,
|
|
Node->ListLinks.Blink );
|
|
|
|
RestoreSpace(Indent);
|
|
}
|
|
|
|
VOID DumpTunnelNodeWrapper (
|
|
PVOID pCacheLinks,
|
|
ULONG Indent
|
|
)
|
|
{
|
|
TUNNEL_NODE Node, *pNode;
|
|
|
|
if (!ReadAtAddress(CONTAINING_RECORD(pCacheLinks, TUNNEL_NODE, CacheLinks),
|
|
&Node,
|
|
sizeof(TUNNEL_NODE),
|
|
&pNode)) {
|
|
|
|
return;
|
|
}
|
|
|
|
DumpTunnelNode(&Node, pNode, Indent);
|
|
}
|
|
|
|
VOID
|
|
DumpTunnel (
|
|
PVOID pTunnel
|
|
)
|
|
{
|
|
TUNNEL Tunnel;
|
|
LIST_ENTRY Link, *pLink, *pHead;
|
|
ULONG Indent = 0, EntryCount = 0;
|
|
TUNNEL_NODE Node, *pNode;
|
|
|
|
if (!ReadAtAddress(pTunnel, &Tunnel, sizeof(TUNNEL), NULL)) {
|
|
|
|
return;
|
|
}
|
|
|
|
dprintf("Tunnel @ %08x\n"
|
|
"NumEntries = %ld\n\n"
|
|
"Splay Tree @ %08x\n",
|
|
pTunnel,
|
|
Tunnel.NumEntries,
|
|
Tunnel.Cache);
|
|
|
|
EntryCount = DumpSplayTree(Tunnel.Cache, DumpTunnelNodeWrapper);
|
|
|
|
if (EntryCount != Tunnel.NumEntries) {
|
|
|
|
dprintf("Tree count mismatch (%d not expected %d)\n", EntryCount, Tunnel.NumEntries);
|
|
}
|
|
|
|
for (EntryCount = 0,
|
|
pHead = (PLIST_ENTRY)((PCHAR)pTunnel + FIELD_OFFSET(TUNNEL, TimerQueue)),
|
|
pLink = Tunnel.TimerQueue.Flink;
|
|
|
|
pLink != pHead;
|
|
|
|
pLink = Node.ListLinks.Flink,
|
|
EntryCount++) {
|
|
|
|
if (pLink == Tunnel.TimerQueue.Flink) {
|
|
|
|
dprintf("\nTimer Queue @ %08x\n", pHead);
|
|
}
|
|
|
|
if (!ReadAtAddress(CONTAINING_RECORD(pLink, TUNNEL_NODE, ListLinks),
|
|
&Node,
|
|
sizeof(TUNNEL_NODE),
|
|
&pNode)) {
|
|
|
|
return;
|
|
}
|
|
|
|
DumpTunnelNode(&Node, pNode, 0);
|
|
|
|
if ( CheckControlC() ) {
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (EntryCount != Tunnel.NumEntries) {
|
|
|
|
dprintf("Timer count mismatch (%d not expected %d)\n", EntryCount, Tunnel.NumEntries);
|
|
}
|
|
}
|
|
|
|
|
|
DECLARE_API( tunnel )
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dump tunnel caches
|
|
|
|
Arguments:
|
|
|
|
arg - <Address>
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PVOID Tunnel = NULL;
|
|
|
|
RtlFillMemory(Space, sizeof(Space), ' ');
|
|
|
|
if (sscanf(args, "%lx", &Tunnel) != 1) {
|
|
|
|
//
|
|
// No args
|
|
//
|
|
|
|
return;
|
|
}
|
|
|
|
DumpTunnel(Tunnel);
|
|
|
|
return;
|
|
}
|