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.

374 lines
8.0 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. fcbtable.c
  5. Abstract:
  6. This module implements the data structures that facilitate management of the
  7. collection of FCB's associated with a NET_ROOT
  8. Author:
  9. Balan Sethu Raman (SethuR) 10/17/96
  10. Revision History:
  11. This was derived from the original implementation of prefix tables done
  12. by Joe Linn.
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. #ifdef ALLOC_PRAGMA
  17. #pragma alloc_text(PAGE, RxTableComputePathHashValue)
  18. #pragma alloc_text(PAGE, RxInitializeFcbTable)
  19. #pragma alloc_text(PAGE, RxFinalizeFcbTable)
  20. #pragma alloc_text(PAGE, RxFcbTableLookupFcb)
  21. #pragma alloc_text(PAGE, RxFcbTableInsertFcb)
  22. #pragma alloc_text(PAGE, RxFcbTableRemoveFcb)
  23. #endif
  24. //
  25. // The debug trace level
  26. //
  27. #define Dbg (DEBUG_TRACE_PREFIX)
  28. ULONG
  29. RxTableComputePathHashValue (
  30. IN PUNICODE_STRING Name
  31. )
  32. /*++
  33. Routine Description:
  34. here, we compute a caseinsensitive hashvalue. we want to avoid a call/char to
  35. the unicodeupcase routine but we want to still have some reasonable spread on
  36. the hashvalues. many rules just dont work for known important cases. for
  37. example, the (use the first k and the last n) rule that old c compilers used
  38. doesn't pickup the difference among \nt\private\......\slm.ini and that would be
  39. nice. note that the underlying comparison used already takes cognizance of the
  40. length before comparing.
  41. the rule we have selected is to use the 2nd, the last 4, and three selected
  42. at 1/4 points
  43. Arguments:
  44. Name - the name to be hashed
  45. Return Value:
  46. ULONG which is a hashvalue for the name given.
  47. --*/
  48. {
  49. ULONG HashValue;
  50. LONG i,j;
  51. LONG length = Name->Length/sizeof(WCHAR);
  52. PWCHAR Buffer = Name->Buffer;
  53. LONG Probe[8];
  54. PAGED_CODE();
  55. HashValue = 0;
  56. Probe[0] = 1;
  57. Probe[1] = length - 1;
  58. Probe[2] = length - 2;
  59. Probe[3] = length - 3;
  60. Probe[4] = length - 4;
  61. Probe[5] = length >> 2;
  62. Probe[6] = (2 * length) >> 2;
  63. Probe[7] = (3 * length) >> 2;
  64. for (i = 0; i < 8; i++) {
  65. j = Probe[i];
  66. if ((j < 0) || (j >= length)) {
  67. continue;
  68. }
  69. HashValue = (HashValue << 3) + RtlUpcaseUnicodeChar(Buffer[j]);
  70. }
  71. RxDbgTrace(0, Dbg, ("RxTableComputeHashValue Hashv=%ld Name=%wZ\n",
  72. HashValue, Name));
  73. return(HashValue);
  74. }
  75. #define HASH_BUCKET(TABLE,HASHVALUE) &((TABLE)->HashBuckets[(HASHVALUE) % (TABLE)->NumberOfBuckets])
  76. VOID
  77. RxInitializeFcbTable(
  78. IN OUT PRX_FCB_TABLE pFcbTable,
  79. IN BOOLEAN CaseInsensitiveMatch)
  80. /*++
  81. Routine Description:
  82. The routine initializes the RX_FCB_TABLE data structure
  83. Arguments:
  84. pFcbTable - the table instance to be initialized.
  85. CaseInsensitiveMatch - indicates if all the lookups will be case
  86. insensitive
  87. --*/
  88. {
  89. ULONG i;
  90. PAGED_CODE();
  91. // this is not zero'd so you have to be careful to init everything
  92. pFcbTable->NodeTypeCode = RDBSS_NTC_FCB_TABLE;
  93. pFcbTable->NodeByteSize = sizeof(RX_PREFIX_TABLE);
  94. ExInitializeResourceLite( &pFcbTable->TableLock );
  95. pFcbTable->Version = 0;
  96. pFcbTable->pTableEntryForNull = NULL;
  97. pFcbTable->CaseInsensitiveMatch = CaseInsensitiveMatch;
  98. pFcbTable->NumberOfBuckets = RX_FCB_TABLE_NUMBER_OF_HASH_BUCKETS;
  99. for (i=0; i < pFcbTable->NumberOfBuckets; i++) {
  100. InitializeListHead(&pFcbTable->HashBuckets[i]);
  101. }
  102. pFcbTable->Lookups = 0;
  103. pFcbTable->FailedLookups = 0;
  104. pFcbTable->Compares = 0;
  105. }
  106. VOID
  107. RxFinalizeFcbTable(
  108. IN OUT PRX_FCB_TABLE pFcbTable)
  109. /*++
  110. Routine Description:
  111. The routine deinitializes a prefix table.
  112. Arguments:
  113. pFcbTable - the table to be finalized.
  114. Return Value:
  115. None.
  116. --*/
  117. {
  118. ULONG i;
  119. PAGED_CODE();
  120. ExDeleteResourceLite(&pFcbTable->TableLock);
  121. IF_DEBUG {
  122. for (i=0; i < pFcbTable->NumberOfBuckets; i++) {
  123. ASSERT(IsListEmpty(&pFcbTable->HashBuckets[i]));
  124. }
  125. }
  126. }
  127. PFCB
  128. RxFcbTableLookupFcb(
  129. IN PRX_FCB_TABLE pFcbTable,
  130. IN PUNICODE_STRING pPath)
  131. /*++
  132. Routine Description:
  133. The routine looks up a path in the RX_FCB_TABLE instance.
  134. Arguments:
  135. pFcbTable - the table to be looked in.
  136. pPath - the name to be looked up
  137. Return Value:
  138. a pointer to an FCB instance if successful, otherwise NULL
  139. --*/
  140. {
  141. ULONG HashValue;
  142. PLIST_ENTRY pHashBucket, pListEntry;
  143. PRX_FCB_TABLE_ENTRY pFcbTableEntry;
  144. PFCB pFcb = NULL;
  145. PAGED_CODE();
  146. RxDbgTrace(+1, Dbg, ("RxFcbTableLookupName %lx %\n",pFcbTable));
  147. if (pPath->Length == 0) {
  148. pFcbTableEntry = pFcbTable->pTableEntryForNull;
  149. } else {
  150. HashValue = RxTableComputePathHashValue(pPath);
  151. pHashBucket = HASH_BUCKET(pFcbTable,HashValue);
  152. for (pListEntry = pHashBucket->Flink;
  153. pListEntry != pHashBucket;
  154. pListEntry = pListEntry->Flink) {
  155. (PVOID)pFcbTableEntry = CONTAINING_RECORD(
  156. pListEntry,
  157. RX_FCB_TABLE_ENTRY,
  158. HashLinks);
  159. InterlockedIncrement(&pFcbTable->Compares);
  160. if ((pFcbTableEntry->HashValue == HashValue) &&
  161. (pFcbTableEntry->Path.Length == pPath->Length) &&
  162. (RtlEqualUnicodeString(
  163. pPath,
  164. &pFcbTableEntry->Path,
  165. pFcbTable->CaseInsensitiveMatch))) {
  166. break;
  167. }
  168. }
  169. if (pListEntry == pHashBucket) {
  170. pFcbTableEntry = NULL;
  171. }
  172. }
  173. InterlockedIncrement(&pFcbTable->Lookups);
  174. if (pFcbTableEntry == NULL) {
  175. InterlockedIncrement(&pFcbTable->FailedLookups);
  176. } else {
  177. pFcb = (PFCB)CONTAINING_RECORD(
  178. pFcbTableEntry,
  179. FCB,
  180. FcbTableEntry);
  181. RxReferenceNetFcb(pFcb);
  182. }
  183. RxDbgTraceUnIndent(-1,Dbg);
  184. return pFcb;
  185. }
  186. NTSTATUS
  187. RxFcbTableInsertFcb(
  188. IN OUT PRX_FCB_TABLE pFcbTable,
  189. IN OUT PFCB pFcb)
  190. /*++
  191. Routine Description:
  192. This routine inserts a FCB in the RX_FCB_TABLE instance.
  193. Arguments:
  194. pFcbTable - the table to be looked in.
  195. pFcb - the FCB instance to be inserted
  196. Return Value:
  197. STATUS_SUCCESS if successful
  198. Notes:
  199. The insertion routine combines the semantics of an insertion followed by
  200. lookup. This is the reason for the additional reference. Otherwise an
  201. additional call to reference the FCB inserted in the table needs to
  202. be made
  203. --*/
  204. {
  205. PRX_FCB_TABLE_ENTRY pFcbTableEntry;
  206. ULONG HashValue;
  207. PLIST_ENTRY pListEntry,pHashBucket;
  208. PAGED_CODE();
  209. ASSERT( RxIsFcbTableLockExclusive( pFcbTable ) );
  210. pFcbTableEntry = &pFcb->FcbTableEntry;
  211. pFcbTableEntry->HashValue = RxTableComputePathHashValue(
  212. &pFcbTableEntry->Path);
  213. pHashBucket = HASH_BUCKET(
  214. pFcbTable,
  215. pFcbTableEntry->HashValue);
  216. RxReferenceNetFcb(pFcb);
  217. if (pFcbTableEntry->Path.Length){
  218. InsertHeadList(
  219. pHashBucket,
  220. &pFcbTableEntry->HashLinks);
  221. } else {
  222. pFcbTable->pTableEntryForNull = pFcbTableEntry;
  223. }
  224. InterlockedIncrement(&pFcbTable->Version);
  225. return STATUS_SUCCESS;
  226. }
  227. NTSTATUS
  228. RxFcbTableRemoveFcb(
  229. IN OUT PRX_FCB_TABLE pFcbTable,
  230. IN OUT PFCB pFcb)
  231. /*++
  232. Routine Description:
  233. This routine deletes an instance from the table
  234. Arguments:
  235. pFcbTable - the table to be looked in.
  236. pFcb - the FCB instance to be inserted
  237. Return Value:
  238. STATUS_SUCCESS if successful
  239. --*/
  240. {
  241. PRX_FCB_TABLE_ENTRY pFcbTableEntry;
  242. PAGED_CODE();
  243. ASSERT( RxIsPrefixTableLockExclusive(pFcbTable));
  244. pFcbTableEntry = &pFcb->FcbTableEntry;
  245. if (pFcbTableEntry->Path.Length) {
  246. RemoveEntryList(&pFcbTableEntry->HashLinks);
  247. } else {
  248. pFcbTable->pTableEntryForNull = NULL;
  249. }
  250. InitializeListHead(&pFcbTableEntry->HashLinks);
  251. InterlockedIncrement(&pFcbTable->Version);
  252. return STATUS_SUCCESS;
  253. }