Source code of Windows XP (NT5)
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.

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