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.

875 lines
25 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. prefix.c
  5. Abstract:
  6. This module implements table functions for the net name prefix table and the per-netroot fcb table.
  7. Author:
  8. Joe Linn (JoeLinn) 8-8-94
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #ifdef ALLOC_PRAGMA
  14. #pragma alloc_text(PAGE, RxTableComputeHashValue)
  15. #if 0
  16. #pragma alloc_text(PAGE, RxpAcquirePrefixTableLockShared)
  17. #pragma alloc_text(PAGE, RxpAcquirePrefixTableLockExclusive)
  18. #pragma alloc_text(PAGE, RxpReleasePrefixTableLock)
  19. #endif
  20. #pragma alloc_text(PAGE, RxExclusivePrefixTableLockToShared)
  21. #pragma alloc_text(PAGE, RxIsPrefixTableEmpty)
  22. #pragma alloc_text(PAGE, RxPrefixTableLookupName)
  23. #pragma alloc_text(PAGE, RxTableLookupName_ExactLengthMatch)
  24. #pragma alloc_text(PAGE, RxTableLookupName)
  25. #pragma alloc_text(PAGE, RxPrefixTableInsertName)
  26. #pragma alloc_text(PAGE, RxRemovePrefixTableEntry)
  27. #pragma alloc_text(PAGE, RxInitializePrefixTable)
  28. #pragma alloc_text(PAGE, RxFinalizePrefixTable)
  29. #endif
  30. //
  31. // The debug trace level
  32. //
  33. #define Dbg (DEBUG_TRACE_PREFIX)
  34. PUNICODE_PREFIX_TABLE_ENTRY
  35. RxTrivialPrefixFind (
  36. IN PRX_PREFIX_TABLE ThisTable,
  37. IN PUNICODE_STRING Name,
  38. IN ULONG Flags
  39. );
  40. VOID
  41. RxCheckTableConsistency_actual (
  42. IN PRX_PREFIX_TABLE Table,
  43. IN ULONG Tag
  44. );
  45. PVOID
  46. RxTableLookupName (
  47. IN PRX_PREFIX_TABLE ThisTable,
  48. IN PUNICODE_STRING Name,
  49. OUT PUNICODE_STRING RemainingName,
  50. IN PRX_CONNECTION_ID RxConnectionId
  51. );
  52. PRX_PREFIX_ENTRY
  53. RxTableInsertEntry (
  54. IN OUT PRX_PREFIX_TABLE ThisTable,
  55. IN OUT PRX_PREFIX_ENTRY ThisEntry
  56. );
  57. VOID
  58. RxTableRemoveEntry (
  59. IN OUT PRX_PREFIX_TABLE ThisTable,
  60. IN OUT PRX_PREFIX_ENTRY Entry
  61. );
  62. #ifdef ALLOC_PRAGMA
  63. #pragma alloc_text( PAGE, RxPrefixTableLookupName )
  64. #pragma alloc_text( PAGE, RxPrefixTableInsertName )
  65. #pragma alloc_text( PAGE, RxRemovePrefixTableEntry )
  66. #pragma alloc_text( PAGE, RxInitializePrefixTable )
  67. #pragma alloc_text( PAGE, RxFinalizePrefixTable )
  68. #endif
  69. ULONG
  70. RxTableComputeHashValue (
  71. IN PUNICODE_STRING Name
  72. )
  73. /*++
  74. Routine Description:
  75. here, we compute a caseinsensitive hashvalue. we want to avoid a call/char to
  76. the unicodeupcase routine but we want to still have some reasonable spread on
  77. the hashvalues. many rules just dont work for known important cases. for
  78. example, the (use the first k and the last n) rule that old c compilers used
  79. doesn't pickup the difference among \nt\private\......\slm.ini and that would be
  80. nice. note that the underlying comparison used already takes cognizance of the
  81. length before comparing.
  82. the rule we have selected is to use the 2nd, the last 4, and three selected
  83. at 1/4 points
  84. Arguments:
  85. Name - the name to be hashed
  86. Return Value:
  87. ULONG which is a hashvalue for the name given.
  88. --*/
  89. {
  90. ULONG HashValue;
  91. LONG i,j;
  92. LONG length = Name->Length/sizeof(WCHAR);
  93. PWCHAR Buffer = Name->Buffer;
  94. LONG Probe[8];
  95. PAGED_CODE();
  96. HashValue = 0;
  97. Probe[0] = 1;
  98. Probe[1] = length - 1;
  99. Probe[2] = length - 2;
  100. Probe[3] = length - 3;
  101. Probe[4] = length - 4;
  102. Probe[5] = length >> 2;
  103. Probe[6] = (2 * length) >> 2;
  104. Probe[7] = (3 * length) >> 2;
  105. for (i = 0; i < 8; i++) {
  106. j = Probe[i];
  107. if ((j < 0) || (j >= length)) {
  108. continue;
  109. }
  110. HashValue = (HashValue << 3) + RtlUpcaseUnicodeChar(Buffer[j]);
  111. }
  112. RxDbgTrace(0, Dbg, ("RxTableComputeHashValue Hashv=%ld Name=%wZ\n",
  113. HashValue, Name));
  114. return(HashValue);
  115. }
  116. #define HASH_BUCKET(TABLE,HASHVALUE) &((TABLE)->HashBuckets[(HASHVALUE) % (TABLE)->TableSize])
  117. //#if DBG
  118. //#define RxCheckTableConsistency(_xx,_yy) RxCheckTableConsistency_actual(_xx,_yy)
  119. //#else
  120. //#define RxCheckTableConsistency(_xx,_yy)
  121. //#endif
  122. #define RxCheckTableConsistency(_xx,_yy)
  123. #if 0
  124. ULONG RxLoudPrefixTableOperations = 0; //1;
  125. #define RxLoudPrefixTableOperation(x) { \
  126. if (RxLoudPrefixTableOperations) { \
  127. DbgPrint("rdr2:%s on %08lx from %d:%s\n", \
  128. x,pTable,LineNumber,FileName); \
  129. }}
  130. #else
  131. #define RxLoudPrefixTableOperation(x) {NOTHING;}
  132. #endif
  133. #if 0
  134. BOOLEAN
  135. RxpAcquirePrefixTableLockShared (
  136. PRX_PREFIX_TABLE Table,
  137. BOOLEAN Wait,
  138. BOOLEAN ProcessBufferingStateChangeRequests,
  139. PSZ FileName,
  140. ULONG LineNumber
  141. )
  142. {
  143. BOOLEAN fResult;
  144. PAGED_CODE();
  145. RxLoudPrefixTableOperation( "RxpAcquirePrefixTableLockShared" );
  146. fResult = ExAcquireResourceSharedLite( &Table->TableLock, Wait );
  147. return fResult;
  148. }
  149. BOOLEAN
  150. RxpAcquirePrefixTableLockExclusive (
  151. PRX_PREFIX_TABLE Table,
  152. BOOLEAN Wait,
  153. BOOLEAN ProcessBufferingStateChangeRequests,
  154. PSZ FileName,
  155. ULONG LineNumber
  156. )
  157. {
  158. BOOLEAN fResult;
  159. PAGED_CODE();
  160. RxLoudPrefixTableOperation( "RxpAcquirePrefixTableLockExclusive" );
  161. fResult = ExAcquireResourceExclusiveLite( &Table->TableLock, Wait );
  162. return fResult;
  163. }
  164. VOID
  165. RxpReleasePrefixTableLock (
  166. PRX_PREFIX_TABLE Table,
  167. BOOLEAN ProcessBufferingStateChangeRequests,
  168. PSZ FileName,
  169. ULONG LineNumber
  170. )
  171. {
  172. PAGED_CODE();
  173. RxLoudPrefixTableOperation( "RxpReleasePrefixTableLock" );
  174. ExReleaseResourceLite( &Table->TableLock );
  175. }
  176. #endif
  177. VOID
  178. RxExclusivePrefixTableLockToShared (
  179. PRX_PREFIX_TABLE pTable
  180. )
  181. {
  182. PAGED_CODE();
  183. ExConvertExclusiveToSharedLite(&pTable->TableLock);
  184. }
  185. BOOLEAN
  186. RxIsPrefixTableEmpty(
  187. IN PRX_PREFIX_TABLE ThisTable)
  188. {
  189. BOOLEAN IsEmpty;
  190. PAGED_CODE();
  191. ASSERT ( RxIsPrefixTableLockAcquired ( ThisTable ) );
  192. RxCheckTableConsistency(ThisTable,' kue');
  193. IsEmpty = IsListEmpty(&ThisTable->MemberQueue);
  194. return IsEmpty;
  195. }
  196. PVOID
  197. RxPrefixTableLookupName (
  198. IN PRX_PREFIX_TABLE ThisTable,
  199. IN PUNICODE_STRING CanonicalName,
  200. OUT PUNICODE_STRING RemainingName,
  201. IN PRX_CONNECTION_ID OPTIONAL RxConnectionId
  202. )
  203. /*++
  204. Routine Description:
  205. The routine looks up a name in a prefix table and converts from the underlying pointer to the containing
  206. record. The table lock should be held AT LEAST shared for this operation.
  207. Arguments:
  208. ThisTable - the table to be looked in.
  209. CanonicalName - the name to be looked up
  210. RemainingName - the portion of the name unmatched.
  211. Return Value:
  212. Ptr to the found node or NULL. The found node will be referenced.
  213. --*/
  214. {
  215. PVOID pContainer = NULL;
  216. PRX_PREFIX_ENTRY ThisEntry;
  217. PAGED_CODE();
  218. ASSERT ( RxIsPrefixTableLockAcquired ( ThisTable ) );
  219. RxDbgTrace( +1, Dbg, ("RxPrefixTableLookupName Name = %wZ \n", CanonicalName));
  220. RxCheckTableConsistency(ThisTable,' kul');
  221. ASSERT(CanonicalName->Length > 0);
  222. pContainer = RxTableLookupName(ThisTable, CanonicalName,RemainingName, RxConnectionId);
  223. if (pContainer == NULL){
  224. RxDbgTrace(-1, Dbg, ("RxPrefixTableLookupName Name = %wZ F A I L E D !!\n", CanonicalName));
  225. return NULL;
  226. } else {
  227. IF_DEBUG {
  228. if (RdbssReferenceTracingValue != 0) {
  229. switch (NodeType(pContainer) & ~RX_SCAVENGER_MASK) {
  230. case RDBSS_NTC_SRVCALL :
  231. {
  232. RxpTrackReference(RDBSS_REF_TRACK_SRVCALL,__FILE__,__LINE__,pContainer);
  233. }
  234. break;
  235. case RDBSS_NTC_NETROOT :
  236. {
  237. RxpTrackReference(RDBSS_REF_TRACK_NETROOT,__FILE__,__LINE__,pContainer);
  238. }
  239. break;
  240. case RDBSS_NTC_V_NETROOT:
  241. {
  242. RxpTrackReference(RDBSS_REF_TRACK_VNETROOT,__FILE__,__LINE__,pContainer);
  243. }
  244. break;
  245. default:
  246. {
  247. ASSERT(!"Valid node type for referencing");
  248. }
  249. break;
  250. }
  251. }
  252. }
  253. RxReference(pContainer);
  254. RxDbgTrace(-1, Dbg, ("RxPrefixTableLookupName Name = %wZ Container = 0x%8lx\n", CanonicalName, pContainer));
  255. }
  256. return pContainer;
  257. }
  258. PRX_PREFIX_ENTRY
  259. RxTableLookupName_ExactLengthMatch (
  260. IN PRX_PREFIX_TABLE ThisTable,
  261. IN PUNICODE_STRING Name,
  262. IN ULONG HashValue,
  263. IN PRX_CONNECTION_ID RxConnectionId
  264. )
  265. /*++
  266. Routine Description:
  267. The routine looks up a name in a rxtable; whether or not to do case insensitive is a property
  268. of the table. The table lock should be held AT LEAST
  269. shared for this operation; the routine may boost itself to exclusive on the lock if it wants to rearrange the table.
  270. Arguments:
  271. ThisTable - the table to be looked in.
  272. Name - the name to be looked up
  273. HashValue - the precomputed hashvalue
  274. Return Value:
  275. Ptr to the found node or NULL.
  276. --*/
  277. {
  278. PLIST_ENTRY HashBucket, ListEntry;
  279. BOOLEAN CaseInsensitiveMatch = ThisTable->CaseInsensitiveMatch;
  280. PAGED_CODE();
  281. ASSERT( RxConnectionId );
  282. HashBucket = HASH_BUCKET(ThisTable,HashValue);
  283. for (ListEntry = HashBucket->Flink;
  284. ListEntry != HashBucket;
  285. ListEntry = ListEntry->Flink
  286. ) {
  287. PRX_PREFIX_ENTRY PrefixEntry;
  288. PVOID Container;
  289. ASSERT(ListEntry!=NULL);
  290. PrefixEntry = CONTAINING_RECORD( ListEntry, RX_PREFIX_ENTRY, HashLinks );
  291. RxDbgTrace(0,Dbg,("Considering <%wZ> hashv=%d \n",&PrefixEntry->Prefix,PrefixEntry->SavedHashValue));
  292. DbgDoit(ThisTable->Considers++);
  293. ASSERT(HashBucket == HASH_BUCKET(ThisTable,PrefixEntry->SavedHashValue));
  294. ASSERT(PrefixEntry!=NULL);
  295. Container = PrefixEntry->ContainingRecord;
  296. ASSERT(Container!=NULL);
  297. if ( (PrefixEntry->SavedHashValue == HashValue)
  298. && (PrefixEntry->Prefix.Length==Name->Length) ){
  299. USHORT CaseInsensitiveLength = PrefixEntry->CaseInsensitiveLength;
  300. DbgDoit(ThisTable->Compares++);
  301. if (CaseInsensitiveLength == 0) {
  302. RxDbgTrace(0,Dbg,("Comparing <%wZ> with <%wZ>, ins=%x\n",Name,&PrefixEntry->Prefix,CaseInsensitiveMatch));
  303. if (RtlEqualUnicodeString(Name,&PrefixEntry->Prefix,CaseInsensitiveMatch) ) {
  304. if( !ThisTable->IsNetNameTable || RxEqualConnectionId( RxConnectionId, &PrefixEntry->ConnectionId ) )
  305. {
  306. return PrefixEntry;
  307. }
  308. }
  309. } else {
  310. //part of the compare will be case insensitive and part controlled by the flag
  311. UNICODE_STRING PartOfName,PartOfPrefix;
  312. ASSERT( CaseInsensitiveLength <= Name->Length );
  313. PartOfName.Buffer = Name->Buffer;
  314. PartOfName.Length = CaseInsensitiveLength;
  315. PartOfPrefix.Buffer = PrefixEntry->Prefix.Buffer;
  316. PartOfPrefix.Length = CaseInsensitiveLength;
  317. RxDbgTrace(0,Dbg,("InsensitiveComparing <%wZ> with <%wZ>\n",&PartOfName,&PartOfPrefix));
  318. if (RtlEqualUnicodeString(&PartOfName,&PartOfPrefix,TRUE) ) {
  319. if (Name->Length == CaseInsensitiveLength ) {
  320. if( !ThisTable->IsNetNameTable || RxEqualConnectionId( RxConnectionId, &PrefixEntry->ConnectionId ) )
  321. {
  322. return PrefixEntry;
  323. }
  324. }
  325. PartOfName.Buffer = (PWCHAR)(((PCHAR)PartOfName.Buffer)+CaseInsensitiveLength);
  326. PartOfName.Length = Name->Length - CaseInsensitiveLength;
  327. PartOfPrefix.Buffer = (PWCHAR)(((PCHAR)PartOfPrefix.Buffer)+CaseInsensitiveLength);
  328. PartOfPrefix.Length = PrefixEntry->Prefix.Length - CaseInsensitiveLength;
  329. RxDbgTrace(0,Dbg,("AndthenComparing <%wZ> with <%wZ>\n",&PartOfName,&PartOfPrefix));
  330. if (RtlEqualUnicodeString(&PartOfName,&PartOfPrefix,FALSE) ) {
  331. if( !ThisTable->IsNetNameTable || RxEqualConnectionId( RxConnectionId, &PrefixEntry->ConnectionId ) )
  332. {
  333. return PrefixEntry;
  334. }
  335. }
  336. }
  337. }
  338. }
  339. }
  340. return NULL;
  341. }
  342. PVOID
  343. RxTableLookupName (
  344. IN PRX_PREFIX_TABLE ThisTable,
  345. IN PUNICODE_STRING Name,
  346. OUT PUNICODE_STRING RemainingName,
  347. IN PRX_CONNECTION_ID OPTIONAL RxConnectionId
  348. )
  349. /*++
  350. Routine Description:
  351. The routine looks up a name in a prefix table. The table lock should be held AT LEAST shared for this operation; the routine
  352. may boost itself to exclusive on the lock if it wants to rearrange the table.
  353. This routine conducts itself differently depending on whether the table is the netroot table. if so, it actually does
  354. a prefix match; if not, it actually does an exact match and fails immediately if the exact match fails. Eventually, we may want
  355. to actually point to different routines...what a concept.
  356. Arguments:
  357. ThisTable - the table to be looked in.
  358. Name - the name to be looked up
  359. Return Value:
  360. Ptr to the found node or NULL.
  361. --*/
  362. {
  363. ULONG HashValue;
  364. UNICODE_STRING Prefix;
  365. PRX_PREFIX_ENTRY pFoundPrefixEntry;
  366. PVOID pContainer = NULL;
  367. ULONG i,length;
  368. PRX_PREFIX_ENTRY pPrefixEntry;
  369. RX_CONNECTION_ID LocalId;
  370. PAGED_CODE();
  371. if( ThisTable->IsNetNameTable && !RxConnectionId )
  372. {
  373. RtlZeroMemory( &LocalId, sizeof(RX_CONNECTION_ID) );
  374. RxConnectionId = &LocalId;
  375. }
  376. ASSERT(Name->Buffer[0]==L'\\');
  377. RxDbgTrace(+1, Dbg, ("RxTableLookupName\n"));
  378. //
  379. //the code below takes cognizance of what it knows is stored in the netname table,
  380. //i.e. netroots and vnetroots cause an immediate return, and srvcalls which require that we continue looking
  381. //to see if we will find a netroot/vnetroot that is longer. so, we go down the table looking at each possible
  382. //prefix. if we exhaust the list w/o finding a hit, it's a failure. if we find a v/netroot, instant out. if
  383. //we find a srvcall we keep looking
  384. //
  385. length = Name->Length / sizeof(WCHAR);
  386. Prefix.Buffer = Name->Buffer;
  387. pFoundPrefixEntry = NULL;
  388. for (i=1;;i++) {
  389. if ((i>=length) ||
  390. (Prefix.Buffer[i]==OBJ_NAME_PATH_SEPARATOR) ||
  391. (Prefix.Buffer[i]==L':')) {
  392. //we have a prefix...lookit up
  393. Prefix.Length=(USHORT)(i*sizeof(WCHAR));
  394. HashValue = RxTableComputeHashValue(&Prefix);
  395. pPrefixEntry = RxTableLookupName_ExactLengthMatch(ThisTable, (&Prefix), HashValue, RxConnectionId);
  396. DbgDoit(ThisTable->Lookups++);
  397. if (pPrefixEntry!=NULL) {
  398. pFoundPrefixEntry = pPrefixEntry;
  399. pContainer = pFoundPrefixEntry->ContainingRecord;
  400. ASSERT (pPrefixEntry->ContainingRecord != NULL);
  401. if ((NodeType(pPrefixEntry->ContainingRecord) & ~RX_SCAVENGER_MASK)
  402. == RDBSS_NTC_V_NETROOT) {
  403. break;
  404. }
  405. if ((NodeType(pPrefixEntry->ContainingRecord) & ~RX_SCAVENGER_MASK)
  406. == RDBSS_NTC_NETROOT) {
  407. PNET_ROOT pNetRoot = (PNET_ROOT)pPrefixEntry->ContainingRecord;
  408. if (pNetRoot->DefaultVNetRoot != NULL) {
  409. pContainer = pNetRoot->DefaultVNetRoot;
  410. } else if (!IsListEmpty(&pNetRoot->VirtualNetRoots)) {
  411. pContainer = CONTAINING_RECORD(
  412. pNetRoot->VirtualNetRoots.Flink,
  413. V_NET_ROOT,
  414. NetRootListEntry);
  415. } else {
  416. ASSERT(!"Invalid Net Root Entry in Prefix Table");
  417. pFoundPrefixEntry = NULL;
  418. pContainer = NULL;
  419. }
  420. break;
  421. }
  422. ASSERT ((NodeType(pPrefixEntry->ContainingRecord) & ~RX_SCAVENGER_MASK)
  423. == RDBSS_NTC_SRVCALL );
  424. //in this case we have to go around again to try to extend to the netroot
  425. } else {
  426. DbgDoit(ThisTable->FailedLookups++);
  427. }
  428. //dont do this because of long netroots
  429. //if ((pPrefixEntry == NULL) && (pFoundPrefixEntry != NULL)) {
  430. // break;
  431. //}
  432. }
  433. if (i>=length) {
  434. break;
  435. }
  436. }
  437. // Update the remaining Name
  438. if (pFoundPrefixEntry != NULL) {
  439. RxDbgTrace(0,Dbg,("Found Container(%lx) Node Type(%lx) Length Matched (%ld)",
  440. pFoundPrefixEntry,
  441. NodeType(pFoundPrefixEntry->ContainingRecord),
  442. pFoundPrefixEntry->Prefix.Length));
  443. ASSERT(Name->Length >= pFoundPrefixEntry->Prefix.Length);
  444. RemainingName->Buffer = (PWCH)((PCHAR)Name->Buffer + pFoundPrefixEntry->Prefix.Length);
  445. RemainingName->Length = Name->Length - pFoundPrefixEntry->Prefix.Length;
  446. RemainingName->MaximumLength = RemainingName->Length;
  447. } else {
  448. *RemainingName = *Name;
  449. }
  450. RxDbgTraceUnIndent(-1,Dbg);
  451. return pContainer;
  452. }
  453. PRX_PREFIX_ENTRY
  454. RxPrefixTableInsertName (
  455. IN OUT PRX_PREFIX_TABLE ThisTable,
  456. IN OUT PRX_PREFIX_ENTRY ThisEntry,
  457. IN PVOID Container,
  458. IN PULONG ContainerRefCount,
  459. IN USHORT CaseInsensitiveLength,
  460. IN PRX_CONNECTION_ID RxConnectionId
  461. )
  462. /*++
  463. Routine Description:
  464. The routine inserts the name into the table. The tablelock should be held
  465. exclusive for this operation.
  466. Arguments:
  467. ThisTable - the table to be looked in.
  468. ThisEntry - the prefixtable entry to use for the insertion.
  469. Container - is a backptr to the enclosing structure. (can't use CONTAINING_RECORD....sigh)
  470. ContainerRefCount - is a backptr to the refcount.....a different offset for fcbs from netroots
  471. Name - the name to be inserted
  472. Return Value:
  473. Ptr to the inserted node.
  474. --*/
  475. {
  476. ULONG HashValue;
  477. PAGED_CODE();
  478. RxDbgTrace(+1, Dbg, ("RxPrefixTableInsert Name = %wZ(%x/%x)\n", &ThisEntry->Prefix,
  479. CaseInsensitiveLength,ThisEntry->Prefix.Length));
  480. RxLoudFcbMsg("Insert: ",&ThisEntry->Prefix);
  481. ASSERT ( RxIsPrefixTableLockExclusive ( ThisTable ) );
  482. ASSERT( CaseInsensitiveLength <= ThisEntry->Prefix.Length );
  483. ThisEntry->ContainingRecord = Container;
  484. ThisEntry->ContainerRefCount = ContainerRefCount;
  485. ThisEntry->CaseInsensitiveLength = CaseInsensitiveLength;
  486. InterlockedIncrement(ContainerRefCount); //note: not set =1. should already be zero
  487. HashValue = RxTableComputeHashValue(&ThisEntry->Prefix);
  488. ThisEntry->SavedHashValue = HashValue;
  489. if (ThisEntry->Prefix.Length){
  490. ULONG HashValue = ThisEntry->SavedHashValue;
  491. PLIST_ENTRY HashBucket;
  492. HashBucket = HASH_BUCKET(ThisTable,HashValue);
  493. RxDbgTrace(0,Dbg,("RxTableInsertEntry %wZ hashv=%d\n",&ThisEntry->Prefix,ThisEntry->SavedHashValue));
  494. InsertHeadList(HashBucket,&ThisEntry->HashLinks);
  495. } else {
  496. ThisTable->TableEntryForNull = ThisEntry;
  497. }
  498. if( RxConnectionId )
  499. {
  500. RtlCopyMemory( &ThisEntry->ConnectionId, RxConnectionId, sizeof(RX_CONNECTION_ID) );
  501. }
  502. else
  503. {
  504. RtlZeroMemory( &ThisEntry->ConnectionId, sizeof(RX_CONNECTION_ID) );
  505. }
  506. InsertTailList(&ThisTable->MemberQueue,&ThisEntry->MemberQLinks);
  507. ThisTable->Version++;
  508. RxCheckTableConsistency(ThisTable,' tup');
  509. RxDbgTrace(-1, Dbg, ("RxPrefixTableInsert Entry = %08lx Container = %08lx\n",
  510. ThisEntry, ThisEntry->ContainingRecord));
  511. return ThisEntry;
  512. }
  513. VOID
  514. RxRemovePrefixTableEntry(
  515. IN OUT PRX_PREFIX_TABLE ThisTable,
  516. IN OUT PRX_PREFIX_ENTRY ThisEntry
  517. )
  518. /*++
  519. Routine Description:
  520. The routine to remove entry from the table. The table lock should be held exclusive during
  521. this operation. Please note that we do NOT dereference the node; this may seem strange since we
  522. ref the node in lookup and insert. The reason is that people are supposed to deref themselves after
  523. a lookup/insert.
  524. Arguments:
  525. ThisTable - the table associated with the entry.
  526. ThisEntry - the entry being removed.
  527. Return Value:
  528. None.
  529. --*/
  530. {
  531. PAGED_CODE();
  532. RxDbgTrace( 0, Dbg, (" RxRemovePrefixTableEntry, Name = %wZ\n", &ThisEntry->Prefix));
  533. RxLoudFcbMsg("Remove: ",&ThisEntry->Prefix);
  534. ASSERT( NodeType(ThisEntry) == RDBSS_NTC_PREFIX_ENTRY );
  535. ASSERT ( RxIsPrefixTableLockExclusive ( ThisTable ) );
  536. if (ThisEntry->Prefix.Length) {
  537. RemoveEntryList(&ThisEntry->HashLinks);
  538. } else {
  539. ThisTable->TableEntryForNull = NULL;
  540. }
  541. ThisEntry->ContainingRecord = NULL;
  542. RemoveEntryList( &ThisEntry->MemberQLinks );
  543. ThisTable->Version++;
  544. RxCheckTableConsistency(ThisTable,' mer');
  545. return;
  546. }
  547. VOID
  548. RxInitializePrefixTable(
  549. IN OUT PRX_PREFIX_TABLE ThisTable,
  550. IN ULONG TableSize OPTIONAL,
  551. IN BOOLEAN CaseInsensitiveMatch
  552. )
  553. /*++
  554. Routine Description:
  555. The routine initializes the inner table linkage and the corresponding lock.
  556. Arguments:
  557. ThisTable - the table to be initialized.
  558. TableSize - 0=>use default
  559. Return Value:
  560. None.
  561. --*/
  562. {
  563. ULONG i;
  564. PAGED_CODE();
  565. if (TableSize == 0) {
  566. TableSize = RX_PREFIX_TABLE_DEFAULT_LENGTH;
  567. }
  568. //
  569. // this is not zero'd so you have to be careful to init everything
  570. //
  571. ThisTable->NodeTypeCode = RDBSS_NTC_PREFIX_TABLE;
  572. ThisTable->NodeByteSize = sizeof( RX_PREFIX_TABLE );
  573. InitializeListHead( &ThisTable->MemberQueue );
  574. ExInitializeResourceLite( &ThisTable->TableLock );
  575. ThisTable->Version = 0;
  576. ThisTable->TableEntryForNull = NULL;
  577. ThisTable->IsNetNameTable = FALSE;
  578. ThisTable->CaseInsensitiveMatch = CaseInsensitiveMatch;
  579. ThisTable->TableSize = TableSize;
  580. for (i=0;i<TableSize;i++) {
  581. InitializeListHead(&ThisTable->HashBuckets[i]);
  582. }
  583. #if DBG
  584. ThisTable->Lookups = 0;
  585. ThisTable->FailedLookups = 0;
  586. ThisTable->Considers = 0;
  587. ThisTable->Compares = 0;
  588. #endif
  589. }
  590. VOID
  591. RxFinalizePrefixTable(
  592. IN OUT PRX_PREFIX_TABLE ThisTable
  593. )
  594. /*++
  595. Routine Description:
  596. The routine deinitializes a prefix table.
  597. Arguments:
  598. ThisTable - the table to be finalized.
  599. Return Value:
  600. None.
  601. --*/
  602. {
  603. ExDeleteResourceLite( &ThisTable->TableLock );
  604. }
  605. //#if DBG
  606. #if 0
  607. //the purpose of this routine is to catch errors in table manipulation; apparently, stuff is being deleted
  608. //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
  609. //entries is bad then it should be straightforward to compare this log with the previous log to see who did what.
  610. //it probably happens on a failure case or something
  611. #include "stdarg.h"
  612. #include "stdio.h"
  613. #include "stdlib.h"
  614. #include "string.h"
  615. #define RX_PCTC_ENTRY_LENGTH 64
  616. #define RX_PCTC_LOG_LENGTH (128*RX_PCTC_ENTRY_LENGTH)
  617. #define RX_PCTC_LOG_LENGTH_PLUS (RX_PCTC_LOG_LENGTH+100) //the slop is 16 for the ----- and the rest for protection
  618. UCHAR RxPCTC1[RX_PCTC_LOG_LENGTH_PLUS];
  619. UCHAR RxPCTC2[RX_PCTC_LOG_LENGTH_PLUS];
  620. PUCHAR RxPCTCCurrentLog = NULL;
  621. VOID
  622. RxCheckTableConsistency_actual (
  623. IN PRX_PREFIX_TABLE Table,
  624. IN ULONG Tag
  625. )
  626. {
  627. ULONG i;
  628. PLIST_ENTRY ListEntry, NextListEntry;
  629. PAGED_CODE();
  630. if (Table->IsNetNameTable) { return; }
  631. ExAcquireResourceExclusiveLite(&Table->LoggingLock,TRUE);
  632. if (RxPCTCCurrentLog==&RxPCTC2[0]) {
  633. RxPCTCCurrentLog = &RxPCTC1[0];
  634. } else {
  635. RxPCTCCurrentLog = &RxPCTC2[0];
  636. }
  637. sprintf(RxPCTCCurrentLog,"----------");
  638. for (i=0,ListEntry = Table->MemberQueue.Flink;
  639. ListEntry != &Table->MemberQueue;
  640. i+=RX_PCTC_ENTRY_LENGTH,ListEntry = NextListEntry
  641. ) {
  642. PRX_PREFIX_ENTRY PrefixEntry;
  643. PVOID Container;
  644. ASSERT(ListEntry!=NULL);
  645. NextListEntry = ListEntry->Flink;
  646. PrefixEntry = CONTAINING_RECORD( ListEntry, RX_PREFIX_ENTRY, MemberQLinks );
  647. ASSERT(PrefixEntry!=NULL);
  648. Container = PrefixEntry->ContainingRecord;
  649. ASSERT(Container!=NULL);
  650. ASSERT(NodeTypeIsFcb(Container));
  651. if (i>=RX_PCTC_LOG_LENGTH ) { continue; }
  652. sprintf(&RxPCTCCurrentLog[i],"%4s %4s>> %-32.32wZ!!",&Tag,&Container,&PrefixEntry->Prefix);
  653. sprintf(&RxPCTCCurrentLog[i+16],"----------");
  654. }
  655. RxDbgTrace(0, Dbg, ("RxCheckTableConsistency_actual %d entries\n", i/RX_PCTC_ENTRY_LENGTH));
  656. ExReleaseResourceLite(&Table->LoggingLock);
  657. return;
  658. }
  659. #endif