windows-nt/Source/XPSP1/NT/base/fs/rdr2/rxce/prefix.c
2020-09-26 16:20:57 +08:00

855 lines
24 KiB
C

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
prefix.c
Abstract:
This module implements table functions for the net name prefix table and the per-netroot fcb table.
Author:
Joe Linn (JoeLinn) 8-8-94
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, RxTableComputeHashValue)
#pragma alloc_text(PAGE, RxpAcquirePrefixTableLockShared)
#pragma alloc_text(PAGE, RxpAcquirePrefixTableLockExclusive)
#pragma alloc_text(PAGE, RxExclusivePrefixTableLockToShared)
#pragma alloc_text(PAGE, RxpReleasePrefixTableLock)
#pragma alloc_text(PAGE, RxIsPrefixTableEmpty)
#pragma alloc_text(PAGE, RxPrefixTableLookupName)
#pragma alloc_text(PAGE, RxTableLookupName_ExactLengthMatch)
#pragma alloc_text(PAGE, RxTableLookupName)
#pragma alloc_text(PAGE, RxPrefixTableInsertName)
#pragma alloc_text(PAGE, RxRemovePrefixTableEntry)
#pragma alloc_text(PAGE, RxInitializePrefixTable)
#pragma alloc_text(PAGE, RxFinalizePrefixTable)
#endif
//
// The debug trace level
//
#define Dbg (DEBUG_TRACE_PREFIX)
PUNICODE_PREFIX_TABLE_ENTRY
RxTrivialPrefixFind (
IN PRX_PREFIX_TABLE ThisTable,
IN PUNICODE_STRING Name,
IN ULONG Flags
);
VOID
RxCheckTableConsistency_actual (
IN PRX_PREFIX_TABLE Table,
IN ULONG Tag
);
PVOID
RxTableLookupName (
IN PRX_PREFIX_TABLE ThisTable,
IN PUNICODE_STRING Name,
OUT PUNICODE_STRING RemainingName,
IN PRX_CONNECTION_ID RxConnectionId
);
PRX_PREFIX_ENTRY
RxTableInsertEntry (
IN OUT PRX_PREFIX_TABLE ThisTable,
IN OUT PRX_PREFIX_ENTRY ThisEntry
);
VOID
RxTableRemoveEntry (
IN OUT PRX_PREFIX_TABLE ThisTable,
IN OUT PRX_PREFIX_ENTRY Entry
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text( PAGE, RxPrefixTableLookupName )
#pragma alloc_text( PAGE, RxPrefixTableInsertName )
#pragma alloc_text( PAGE, RxRemovePrefixTableEntry )
#pragma alloc_text( PAGE, RxInitializePrefixTable )
#pragma alloc_text( PAGE, RxFinalizePrefixTable )
#endif
ULONG
RxTableComputeHashValue (
IN PUNICODE_STRING Name
)
/*++
Routine Description:
here, we compute a caseinsensitive hashvalue. we want to avoid a call/char to
the unicodeupcase routine but we want to still have some reasonable spread on
the hashvalues. many rules just dont work for known important cases. for
example, the (use the first k and the last n) rule that old c compilers used
doesn't pickup the difference among \nt\private\......\slm.ini and that would be
nice. note that the underlying comparison used already takes cognizance of the
length before comparing.
the rule we have selected is to use the 2nd, the last 4, and three selected
at 1/4 points
Arguments:
Name - the name to be hashed
Return Value:
ULONG which is a hashvalue for the name given.
--*/
{
ULONG HashValue;
LONG i,j;
LONG length = Name->Length/sizeof(WCHAR);
PWCHAR Buffer = Name->Buffer;
LONG Probe[8];
PAGED_CODE();
HashValue = 0;
Probe[0] = 1;
Probe[1] = length - 1;
Probe[2] = length - 2;
Probe[3] = length - 3;
Probe[4] = length - 4;
Probe[5] = length >> 2;
Probe[6] = (2 * length) >> 2;
Probe[7] = (3 * length) >> 2;
for (i = 0; i < 8; i++) {
j = Probe[i];
if ((j < 0) || (j >= length)) {
continue;
}
HashValue = (HashValue << 3) + RtlUpcaseUnicodeChar(Buffer[j]);
}
RxDbgTrace(0, Dbg, ("RxTableComputeHashValue Hashv=%ld Name=%wZ\n",
HashValue, Name));
return(HashValue);
}
#define HASH_BUCKET(TABLE,HASHVALUE) &((TABLE)->HashBuckets[(HASHVALUE) % (TABLE)->TableSize])
//#if DBG
//#define RxCheckTableConsistency(_xx,_yy) RxCheckTableConsistency_actual(_xx,_yy)
//#else
//#define RxCheckTableConsistency(_xx,_yy)
//#endif
#define RxCheckTableConsistency(_xx,_yy)
#if 0
ULONG RxLoudPrefixTableOperations = 0; //1;
#define RxLoudPrefixTableOperation(x) { \
if (RxLoudPrefixTableOperations) { \
DbgPrint("rdr2:%s on %08lx from %d:%s\n", \
x,pTable,LineNumber,FileName); \
}}
#else
#define RxLoudPrefixTableOperation(x) {NOTHING;}
#endif
BOOLEAN
RxpAcquirePrefixTableLockShared (
PRX_PREFIX_TABLE pTable,
BOOLEAN Wait,
BOOLEAN ProcessBufferingStateChangeRequests
RX_PREFIXTABLELOCK_PARAMS
)
{
BOOLEAN fResult;
PAGED_CODE();
RxLoudPrefixTableOperation("RxpAcquirePrefixTableLockShared");
fResult = ExAcquireResourceSharedLite(&pTable->TableLock,Wait);
return fResult;
}
BOOLEAN
RxpAcquirePrefixTableLockExclusive (
PRX_PREFIX_TABLE pTable,
BOOLEAN Wait,
BOOLEAN ProcessBufferingStateChangeRequests
RX_PREFIXTABLELOCK_PARAMS
)
{
BOOLEAN fResult;
PAGED_CODE();
RxLoudPrefixTableOperation("RxpAcquirePrefixTableLockExclusive");
fResult = ExAcquireResourceExclusiveLite(&pTable->TableLock,Wait);
return fResult;
}
VOID
RxExclusivePrefixTableLockToShared (
PRX_PREFIX_TABLE pTable
)
{
PAGED_CODE();
ExConvertExclusiveToSharedLite(&pTable->TableLock);
}
VOID
RxpReleasePrefixTableLock(
PRX_PREFIX_TABLE pTable,
BOOLEAN ProcessBufferingStateChangeRequests
RX_PREFIXTABLELOCK_PARAMS
)
{
PAGED_CODE();
RxLoudPrefixTableOperation("RxpReleasePrefixTableLock");
ExReleaseResourceLite(&pTable->TableLock);
}
BOOLEAN
RxIsPrefixTableEmpty(
IN PRX_PREFIX_TABLE ThisTable)
{
BOOLEAN IsEmpty;
PAGED_CODE();
ASSERT ( RxIsPrefixTableLockAcquired ( ThisTable ) );
RxCheckTableConsistency(ThisTable,' kue');
IsEmpty = IsListEmpty(&ThisTable->MemberQueue);
return IsEmpty;
}
PVOID
RxPrefixTableLookupName (
IN PRX_PREFIX_TABLE ThisTable,
IN PUNICODE_STRING CanonicalName,
OUT PUNICODE_STRING RemainingName,
IN PRX_CONNECTION_ID OPTIONAL RxConnectionId
)
/*++
Routine Description:
The routine looks up a name in a prefix table and converts from the underlying pointer to the containing
record. The table lock should be held AT LEAST shared for this operation.
Arguments:
ThisTable - the table to be looked in.
CanonicalName - the name to be looked up
RemainingName - the portion of the name unmatched.
Return Value:
Ptr to the found node or NULL.
--*/
{
PVOID pContainer = NULL;
PRX_PREFIX_ENTRY ThisEntry;
PAGED_CODE();
ASSERT ( RxIsPrefixTableLockAcquired ( ThisTable ) );
RxDbgTrace( +1, Dbg, ("RxPrefixTableLookupName Name = %wZ \n", CanonicalName));
RxCheckTableConsistency(ThisTable,' kul');
ASSERT(CanonicalName->Length > 0);
pContainer = RxTableLookupName(ThisTable, CanonicalName,RemainingName, RxConnectionId);
if (pContainer == NULL){
RxDbgTrace(-1, Dbg, ("RxPrefixTableLookupName Name = %wZ F A I L E D !!\n", CanonicalName));
return NULL;
} else {
IF_DEBUG {
if (RdbssReferenceTracingValue != 0) {
switch (NodeType(pContainer) & ~RX_SCAVENGER_MASK) {
case RDBSS_NTC_SRVCALL :
{
RxpTrackReference(RDBSS_REF_TRACK_SRVCALL,__FILE__,__LINE__,pContainer);
}
break;
case RDBSS_NTC_NETROOT :
{
RxpTrackReference(RDBSS_REF_TRACK_NETROOT,__FILE__,__LINE__,pContainer);
}
break;
case RDBSS_NTC_V_NETROOT:
{
RxpTrackReference(RDBSS_REF_TRACK_VNETROOT,__FILE__,__LINE__,pContainer);
}
break;
default:
{
ASSERT(!"Valid node type for referencing");
}
break;
}
}
}
RxReference(pContainer);
RxDbgTrace(-1, Dbg, ("RxPrefixTableLookupName Name = %wZ Container = 0x%8lx\n", CanonicalName, pContainer));
}
return pContainer;
}
PRX_PREFIX_ENTRY
RxTableLookupName_ExactLengthMatch (
IN PRX_PREFIX_TABLE ThisTable,
IN PUNICODE_STRING Name,
IN ULONG HashValue,
IN PRX_CONNECTION_ID RxConnectionId
)
/*++
Routine Description:
The routine looks up a name in a rxtable; whether or not to do case insensitive is a property
of the table. The table lock should be held AT LEAST
shared for this operation; the routine may boost itself to exclusive on the lock if it wants to rearrange the table.
Arguments:
ThisTable - the table to be looked in.
Name - the name to be looked up
HashValue - the precomputed hashvalue
Return Value:
Ptr to the found node or NULL.
--*/
{
PLIST_ENTRY HashBucket, ListEntry;
BOOLEAN CaseInsensitiveMatch = ThisTable->CaseInsensitiveMatch;
PAGED_CODE();
ASSERT( RxConnectionId );
HashBucket = HASH_BUCKET(ThisTable,HashValue);
for (ListEntry = HashBucket->Flink;
ListEntry != HashBucket;
ListEntry = ListEntry->Flink
) {
PRX_PREFIX_ENTRY PrefixEntry;
PVOID Container;
ASSERT(ListEntry!=NULL);
PrefixEntry = CONTAINING_RECORD( ListEntry, RX_PREFIX_ENTRY, HashLinks );
RxDbgTrace(0,Dbg,("Considering <%wZ> hashv=%d \n",&PrefixEntry->Prefix,PrefixEntry->SavedHashValue));
DbgDoit(ThisTable->Considers++);
ASSERT(HashBucket == HASH_BUCKET(ThisTable,PrefixEntry->SavedHashValue));
ASSERT(PrefixEntry!=NULL);
Container = PrefixEntry->ContainingRecord;
ASSERT(Container!=NULL);
if ( (PrefixEntry->SavedHashValue == HashValue)
&& (PrefixEntry->Prefix.Length==Name->Length) ){
USHORT CaseInsensitiveLength = PrefixEntry->CaseInsensitiveLength;
DbgDoit(ThisTable->Compares++);
if (CaseInsensitiveLength == 0) {
RxDbgTrace(0,Dbg,("Comparing <%wZ> with <%wZ>, ins=%x\n",Name,&PrefixEntry->Prefix,CaseInsensitiveMatch));
if (RtlEqualUnicodeString(Name,&PrefixEntry->Prefix,CaseInsensitiveMatch) ) {
if( !ThisTable->IsNetNameTable || RxEqualConnectionId( RxConnectionId, &PrefixEntry->ConnectionId ) )
{
return PrefixEntry;
}
}
} else {
//part of the compare will be case insensitive and part controlled by the flag
UNICODE_STRING PartOfName,PartOfPrefix;
ASSERT( CaseInsensitiveLength <= Name->Length );
PartOfName.Buffer = Name->Buffer;
PartOfName.Length = CaseInsensitiveLength;
PartOfPrefix.Buffer = PrefixEntry->Prefix.Buffer;
PartOfPrefix.Length = CaseInsensitiveLength;
RxDbgTrace(0,Dbg,("InsensitiveComparing <%wZ> with <%wZ>\n",&PartOfName,&PartOfPrefix));
if (RtlEqualUnicodeString(&PartOfName,&PartOfPrefix,TRUE) ) {
if (Name->Length == CaseInsensitiveLength ) {
if( !ThisTable->IsNetNameTable || RxEqualConnectionId( RxConnectionId, &PrefixEntry->ConnectionId ) )
{
return PrefixEntry;
}
}
PartOfName.Buffer = (PWCHAR)(((PCHAR)PartOfName.Buffer)+CaseInsensitiveLength);
PartOfName.Length = Name->Length - CaseInsensitiveLength;
PartOfPrefix.Buffer = (PWCHAR)(((PCHAR)PartOfPrefix.Buffer)+CaseInsensitiveLength);
PartOfPrefix.Length = PrefixEntry->Prefix.Length - CaseInsensitiveLength;
RxDbgTrace(0,Dbg,("AndthenComparing <%wZ> with <%wZ>\n",&PartOfName,&PartOfPrefix));
if (RtlEqualUnicodeString(&PartOfName,&PartOfPrefix,FALSE) ) {
if( !ThisTable->IsNetNameTable || RxEqualConnectionId( RxConnectionId, &PrefixEntry->ConnectionId ) )
{
return PrefixEntry;
}
}
}
}
}
}
return NULL;
}
PVOID
RxTableLookupName (
IN PRX_PREFIX_TABLE ThisTable,
IN PUNICODE_STRING Name,
OUT PUNICODE_STRING RemainingName,
IN PRX_CONNECTION_ID OPTIONAL RxConnectionId
)
/*++
Routine Description:
The routine looks up a name in a prefix table. The table lock should be held AT LEAST shared for this operation; the routine
may boost itself to exclusive on the lock if it wants to rearrange the table.
This routine conducts itself differently depending on whether the table is the netroot table. if so, it actually does
a prefix match; if not, it actually does an exact match and fails immediately if the exact match fails. Eventually, we may want
to actually point to different routines...what a concept.
Arguments:
ThisTable - the table to be looked in.
Name - the name to be looked up
Return Value:
Ptr to the found node or NULL.
--*/
{
ULONG HashValue;
UNICODE_STRING Prefix;
PRX_PREFIX_ENTRY pFoundPrefixEntry;
PVOID pContainer = NULL;
ULONG i,length;
PRX_PREFIX_ENTRY pPrefixEntry;
RX_CONNECTION_ID LocalId;
PAGED_CODE();
if( ThisTable->IsNetNameTable && !RxConnectionId )
{
RtlZeroMemory( &LocalId, sizeof(RX_CONNECTION_ID) );
RxConnectionId = &LocalId;
}
ASSERT(Name->Buffer[0]==L'\\');
RxDbgTrace(+1, Dbg, ("RxTableLookupName\n"));
//
//the code below takes cognizance of what it knows is stored in the netname table,
//i.e. netroots and vnetroots cause an immediate return, and srvcalls which require that we continue looking
//to see if we will find a netroot/vnetroot that is longer. so, we go down the table looking at each possible
//prefix. if we exhaust the list w/o finding a hit, it's a failure. if we find a v/netroot, instant out. if
//we find a srvcall we keep looking
//
length = Name->Length / sizeof(WCHAR);
Prefix.Buffer = Name->Buffer;
pFoundPrefixEntry = NULL;
for (i=1;;i++) {
if ((i>=length) ||
(Prefix.Buffer[i]==OBJ_NAME_PATH_SEPARATOR) ||
(Prefix.Buffer[i]==L':')) {
//we have a prefix...lookit up
Prefix.Length=(USHORT)(i*sizeof(WCHAR));
HashValue = RxTableComputeHashValue(&Prefix);
pPrefixEntry = RxTableLookupName_ExactLengthMatch(ThisTable, (&Prefix), HashValue, RxConnectionId);
DbgDoit(ThisTable->Lookups++);
if (pPrefixEntry!=NULL) {
pFoundPrefixEntry = pPrefixEntry;
pContainer = pFoundPrefixEntry->ContainingRecord;
ASSERT (pPrefixEntry->ContainingRecord != NULL);
if ((NodeType(pPrefixEntry->ContainingRecord) & ~RX_SCAVENGER_MASK)
== RDBSS_NTC_V_NETROOT) {
break;
}
if ((NodeType(pPrefixEntry->ContainingRecord) & ~RX_SCAVENGER_MASK)
== RDBSS_NTC_NETROOT) {
PNET_ROOT pNetRoot = (PNET_ROOT)pPrefixEntry->ContainingRecord;
if (pNetRoot->DefaultVNetRoot != NULL) {
pContainer = pNetRoot->DefaultVNetRoot;
} else if (!IsListEmpty(&pNetRoot->VirtualNetRoots)) {
pContainer = CONTAINING_RECORD(
pNetRoot->VirtualNetRoots.Flink,
V_NET_ROOT,
NetRootListEntry);
} else {
ASSERT(!"Invalid Net Root Entry in Prefix Table");
pFoundPrefixEntry = NULL;
pContainer = NULL;
}
break;
}
ASSERT ((NodeType(pPrefixEntry->ContainingRecord) & ~RX_SCAVENGER_MASK)
== RDBSS_NTC_SRVCALL );
//in this case we have to go around again to try to extend to the netroot
} else {
DbgDoit(ThisTable->FailedLookups++);
}
//dont do this because of long netroots
//if ((pPrefixEntry == NULL) && (pFoundPrefixEntry != NULL)) {
// break;
//}
}
if (i>=length) {
break;
}
}
// Update the remaining Name
if (pFoundPrefixEntry != NULL) {
RxDbgTrace(0,Dbg,("Found Container(%lx) Node Type(%lx) Length Matched (%ld)",
pFoundPrefixEntry,
NodeType(pFoundPrefixEntry->ContainingRecord),
pFoundPrefixEntry->Prefix.Length));
ASSERT(Name->Length >= pFoundPrefixEntry->Prefix.Length);
RemainingName->Buffer = (PWCH)((PCHAR)Name->Buffer + pFoundPrefixEntry->Prefix.Length);
RemainingName->Length = Name->Length - pFoundPrefixEntry->Prefix.Length;
RemainingName->MaximumLength = RemainingName->Length;
} else {
*RemainingName = *Name;
}
RxDbgTraceUnIndent(-1,Dbg);
return pContainer;
}
PRX_PREFIX_ENTRY
RxPrefixTableInsertName (
IN OUT PRX_PREFIX_TABLE ThisTable,
IN OUT PRX_PREFIX_ENTRY ThisEntry,
IN PVOID Container,
IN PULONG ContainerRefCount,
IN USHORT CaseInsensitiveLength,
IN PRX_CONNECTION_ID RxConnectionId
)
/*++
Routine Description:
The routine inserts the name into the table. The tablelock should be held
exclusive for this operation.
Arguments:
ThisTable - the table to be looked in.
ThisEntry - the prefixtable entry to use for the insertion.
Container - is a backptr to the enclosing structure. (can't use CONTAINING_RECORD....sigh)
ContainerRefCount - is a backptr to the refcount.....a different offset for fcbs from netroots
Name - the name to be inserted
Return Value:
Ptr to the inserted node.
--*/
{
ULONG HashValue;
PAGED_CODE();
RxDbgTrace(+1, Dbg, ("RxPrefixTableInsert Name = %wZ(%x/%x)\n", &ThisEntry->Prefix,
CaseInsensitiveLength,ThisEntry->Prefix.Length));
RxLoudFcbMsg("Insert: ",&ThisEntry->Prefix);
ASSERT ( RxIsPrefixTableLockExclusive ( ThisTable ) );
ASSERT( CaseInsensitiveLength <= ThisEntry->Prefix.Length );
ThisEntry->ContainingRecord = Container;
ThisEntry->ContainerRefCount = ContainerRefCount;
ThisEntry->CaseInsensitiveLength = CaseInsensitiveLength;
InterlockedIncrement(ContainerRefCount); //note: not set =1. should already be zero
HashValue = RxTableComputeHashValue(&ThisEntry->Prefix);
ThisEntry->SavedHashValue = HashValue;
if (ThisEntry->Prefix.Length){
ULONG HashValue = ThisEntry->SavedHashValue;
PLIST_ENTRY HashBucket;
HashBucket = HASH_BUCKET(ThisTable,HashValue);
RxDbgTrace(0,Dbg,("RxTableInsertEntry %wZ hashv=%d\n",&ThisEntry->Prefix,ThisEntry->SavedHashValue));
InsertHeadList(HashBucket,&ThisEntry->HashLinks);
} else {
ThisTable->TableEntryForNull = ThisEntry;
}
if( RxConnectionId )
{
RtlCopyMemory( &ThisEntry->ConnectionId, RxConnectionId, sizeof(RX_CONNECTION_ID) );
}
else
{
RtlZeroMemory( &ThisEntry->ConnectionId, sizeof(RX_CONNECTION_ID) );
}
InsertTailList(&ThisTable->MemberQueue,&ThisEntry->MemberQLinks);
ThisTable->Version++;
RxCheckTableConsistency(ThisTable,' tup');
RxDbgTrace(-1, Dbg, ("RxPrefixTableInsert Entry = %08lx Container = %08lx\n",
ThisEntry, ThisEntry->ContainingRecord));
return ThisEntry;
}
VOID
RxRemovePrefixTableEntry(
IN OUT PRX_PREFIX_TABLE ThisTable,
IN OUT PRX_PREFIX_ENTRY ThisEntry
)
/*++
Routine Description:
The routine to remove entry from the table. The table lock should be held exclusive during
this operation. Please note that we do NOT dereference the node; this may seem strange since we
ref the node in lookup and insert. The reason is that people are supposed to deref themselves after
a lookup/insert.
Arguments:
ThisTable - the table associated with the entry.
ThisEntry - the entry being removed.
Return Value:
None.
--*/
{
PAGED_CODE();
RxDbgTrace( 0, Dbg, (" RxRemovePrefixTableEntry, Name = %wZ\n", &ThisEntry->Prefix));
RxLoudFcbMsg("Remove: ",&ThisEntry->Prefix);
ASSERT( NodeType(ThisEntry) == RDBSS_NTC_PREFIX_ENTRY );
ASSERT ( RxIsPrefixTableLockExclusive ( ThisTable ) );
if (ThisEntry->Prefix.Length) {
RemoveEntryList(&ThisEntry->HashLinks);
} else {
ThisTable->TableEntryForNull = NULL;
}
ThisEntry->ContainingRecord = NULL;
RemoveEntryList( &ThisEntry->MemberQLinks );
ThisTable->Version++;
RxCheckTableConsistency(ThisTable,' mer');
return;
}
VOID
RxInitializePrefixTable(
IN OUT PRX_PREFIX_TABLE ThisTable,
IN ULONG TableSize OPTIONAL, //0=>use default
IN BOOLEAN CaseInsensitiveMatch
)
/*++
Routine Description:
The routine initializes the inner table linkage and the corresponding lock.
Arguments:
ThisTable - the table to be initialized.
Return Value:
None.
--*/
{
ULONG i;
PAGED_CODE();
if (TableSize==0) {
TableSize = RX_PREFIX_TABLE_DEFAULT_LENGTH;
}
// this is not zero'd so you have to be careful to init everything
ThisTable->NodeTypeCode = RDBSS_NTC_PREFIX_TABLE;
ThisTable->NodeByteSize = sizeof(RX_PREFIX_TABLE);
InitializeListHead(&ThisTable->MemberQueue);
ExInitializeResourceLite( &ThisTable->TableLock );
ThisTable->Version = 0;
ThisTable->TableEntryForNull = NULL;
ThisTable->IsNetNameTable = FALSE;
ThisTable->CaseInsensitiveMatch = CaseInsensitiveMatch;
ThisTable->TableSize = TableSize;
for (i=0;i<TableSize;i++) {
InitializeListHead(&ThisTable->HashBuckets[i]);
}
#if DBG
ThisTable->Lookups = 0;
ThisTable->FailedLookups = 0;
ThisTable->Considers = 0;
ThisTable->Compares = 0;
#endif
}
VOID
RxFinalizePrefixTable(
IN OUT PRX_PREFIX_TABLE ThisTable
)
/*++
Routine Description:
The routine deinitializes a prefix table.
Arguments:
ThisTable - the table to be finalized.
Return Value:
None.
--*/
{
ExDeleteResourceLite(&ThisTable->TableLock);
}
//#if DBG
#if 0
//the purpose of this routine is to catch errors in table manipulation; apparently, stuff is being deleted
//and not removed from the table. what we do is to keep a log of all the entries that we pass; if one of the
//entries is bad then it should be straightforward to compare this log with the previous log to see who did what.
//it probably happens on a failure case or something
#include "stdarg.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#define RX_PCTC_ENTRY_LENGTH 64
#define RX_PCTC_LOG_LENGTH (128*RX_PCTC_ENTRY_LENGTH)
#define RX_PCTC_LOG_LENGTH_PLUS (RX_PCTC_LOG_LENGTH+100) //the slop is 16 for the ----- and the rest for protection
UCHAR RxPCTC1[RX_PCTC_LOG_LENGTH_PLUS];
UCHAR RxPCTC2[RX_PCTC_LOG_LENGTH_PLUS];
PUCHAR RxPCTCCurrentLog = NULL;
VOID
RxCheckTableConsistency_actual (
IN PRX_PREFIX_TABLE Table,
IN ULONG Tag
)
{
ULONG i;
PLIST_ENTRY ListEntry, NextListEntry;
PAGED_CODE();
if (Table->IsNetNameTable) { return; }
ExAcquireResourceExclusiveLite(&Table->LoggingLock,TRUE);
if (RxPCTCCurrentLog==&RxPCTC2[0]) {
RxPCTCCurrentLog = &RxPCTC1[0];
} else {
RxPCTCCurrentLog = &RxPCTC2[0];
}
sprintf(RxPCTCCurrentLog,"----------");
for (i=0,ListEntry = Table->MemberQueue.Flink;
ListEntry != &Table->MemberQueue;
i+=RX_PCTC_ENTRY_LENGTH,ListEntry = NextListEntry
) {
PRX_PREFIX_ENTRY PrefixEntry;
PVOID Container;
ASSERT(ListEntry!=NULL);
NextListEntry = ListEntry->Flink;
PrefixEntry = CONTAINING_RECORD( ListEntry, RX_PREFIX_ENTRY, MemberQLinks );
ASSERT(PrefixEntry!=NULL);
Container = PrefixEntry->ContainingRecord;
ASSERT(Container!=NULL);
ASSERT(NodeTypeIsFcb(Container));
if (i>=RX_PCTC_LOG_LENGTH ) { continue; }
sprintf(&RxPCTCCurrentLog[i],"%4s %4s>> %-32.32wZ!!",&Tag,&Container,&PrefixEntry->Prefix);
sprintf(&RxPCTCCurrentLog[i+16],"----------");
}
RxDbgTrace(0, Dbg, ("RxCheckTableConsistency_actual %d entries\n", i/RX_PCTC_ENTRY_LENGTH));
ExReleaseResourceLite(&Table->LoggingLock);
return;
}
#endif