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.

287 lines
5.9 KiB

  1. /*++
  2. Copyright(c) 1995 Microsoft Corporation
  3. MODULE NAME
  4. table.c
  5. ABSTRACT
  6. Generic hash table manipulation routines.
  7. AUTHOR
  8. Anthony Discolo (adiscolo) 28-Jul-1995
  9. REVISION HISTORY
  10. --*/
  11. #include <ndis.h>
  12. #include <cxport.h>
  13. #include <tdi.h>
  14. #include <tdikrnl.h>
  15. #include <tdistat.h>
  16. #include <tdiinfo.h>
  17. #include <acd.h>
  18. #include <acdapi.h>
  19. #include "table.h"
  20. #include "acddefs.h"
  21. #include "mem.h"
  22. #include "debug.h"
  23. PHASH_TABLE
  24. NewTable()
  25. {
  26. PHASH_TABLE pTable;
  27. INT i;
  28. ALLOCATE_MEMORY(sizeof (HASH_TABLE), pTable);
  29. if (pTable == NULL) {
  30. // DbgPrint("AcdNewTable: ExAllocatePool failed\n");
  31. return NULL;
  32. }
  33. KeInitializeSpinLock(&pTable->SpinLock);
  34. for (i = 0; i < NBUCKETS; i++)
  35. InitializeListHead(&pTable->ListEntry[i]);
  36. return pTable;
  37. } // NewTable
  38. VOID
  39. FreeHashTableEntry(
  40. PHASH_ENTRY pHashEntry
  41. )
  42. {
  43. FREE_MEMORY(pHashEntry);
  44. } // FreeHashTableEntry
  45. VOID
  46. ClearTable(
  47. PHASH_TABLE pTable
  48. )
  49. {
  50. KIRQL irql;
  51. INT i;
  52. PLIST_ENTRY pHead;
  53. PHASH_ENTRY pHashEntry;
  54. KeAcquireSpinLock(&pTable->SpinLock, &irql);
  55. for (i = 0; i < NBUCKETS; i++) {
  56. while (!IsListEmpty(&pTable->ListEntry[i])) {
  57. pHead = RemoveHeadList(&pTable->ListEntry[i]);
  58. pHashEntry = CONTAINING_RECORD(pHead, HASH_ENTRY, ListEntry);
  59. FreeHashTableEntry(pHashEntry);
  60. }
  61. }
  62. KeReleaseSpinLock(&pTable->SpinLock, irql);
  63. } // ClearTable
  64. VOID
  65. FreeTable(
  66. PHASH_TABLE pTable
  67. )
  68. {
  69. ClearTable(pTable);
  70. FREE_MEMORY(pTable);
  71. } // FreeTable
  72. VOID
  73. EnumTable(
  74. IN PHASH_TABLE pTable,
  75. IN PHASH_TABLE_ENUM_PROC pProc,
  76. IN PVOID pArg
  77. )
  78. {
  79. INT i;
  80. PLIST_ENTRY pEntry;
  81. PHASH_ENTRY pHashEntry;
  82. KIRQL irql;
  83. KeAcquireSpinLock(&pTable->SpinLock, &irql);
  84. for (i = 0; i < NBUCKETS; i++) {
  85. for (pEntry = pTable->ListEntry[i].Flink;
  86. pEntry != &pTable->ListEntry[i];
  87. pEntry = pEntry->Flink)
  88. {
  89. pHashEntry = CONTAINING_RECORD(pEntry, HASH_ENTRY, ListEntry);
  90. //
  91. // If the enumerator procedure
  92. // returns FALSE, terminate the
  93. // enumeration.
  94. //
  95. if (!pProc(pArg, &pHashEntry->szKey, pHashEntry->ulData))
  96. goto done;
  97. }
  98. }
  99. done:
  100. KeReleaseSpinLock(&pTable->SpinLock, irql);
  101. } // EnumTable
  102. INT
  103. HashString(
  104. IN PACD_ADDR pszKey
  105. )
  106. {
  107. ULONG ulHashValue = 0;
  108. CHAR ch;
  109. PCSZ p = (PCSZ)pszKey;
  110. while (*p != L'\0') {
  111. ch = tolower(*p);
  112. ulHashValue += (INT)(ch) * (INT)(ch);
  113. p++;
  114. }
  115. return (INT)(ulHashValue % NBUCKETS);
  116. } // HashString
  117. BOOLEAN
  118. IsEqualKey(
  119. PACD_ADDR pszKey1,
  120. PACD_ADDR pszKey2
  121. )
  122. {
  123. BOOLEAN fFound;
  124. fFound = (BOOLEAN)RtlEqualMemory(pszKey1, pszKey2, sizeof (ACD_ADDR));
  125. IF_ACDDBG(ACD_DEBUG_TABLE) {
  126. AcdPrint(("AcdIsEqualKey(%s, %s) returns %d\n", pszKey1, pszKey2, fFound));
  127. }
  128. return fFound;
  129. } // IsEqualKey
  130. PHASH_ENTRY
  131. GetTableEntryNL(
  132. IN PHASH_TABLE pTable,
  133. IN PACD_ADDR pszKey
  134. )
  135. {
  136. INT nBucket = HashString(pszKey);
  137. PLIST_ENTRY pEntry;
  138. PHASH_ENTRY pHashEntry;
  139. for (pEntry = pTable->ListEntry[nBucket].Flink;
  140. pEntry != &pTable->ListEntry[nBucket];
  141. pEntry = pEntry->Flink)
  142. {
  143. pHashEntry = CONTAINING_RECORD(pEntry, HASH_ENTRY, ListEntry);
  144. if (IsEqualKey(&pHashEntry->szKey, pszKey)) {
  145. IF_ACDDBG(ACD_DEBUG_TABLE) {
  146. AcdPrint(("AcdGetTableEntryNL(0x%x, %s) returns 0x%x\n", pTable, pszKey, pHashEntry));
  147. }
  148. return pHashEntry;
  149. }
  150. }
  151. IF_ACDDBG(ACD_DEBUG_TABLE) {
  152. AcdPrint(("AcdGetTableEntryNL(0x%x, %s) returns NULL\n", pTable, pszKey));
  153. }
  154. return NULL;
  155. } // GetTableEntryNL
  156. BOOLEAN
  157. GetTableEntry(
  158. IN PHASH_TABLE pTable,
  159. IN PACD_ADDR pszKey,
  160. OUT PULONG pulData
  161. )
  162. {
  163. KIRQL irql;
  164. PHASH_ENTRY pHashEntry;
  165. KeAcquireSpinLock(&pTable->SpinLock, &irql);
  166. pHashEntry = GetTableEntryNL(pTable, pszKey);
  167. KeReleaseSpinLock(&pTable->SpinLock, irql);
  168. if (pHashEntry != NULL) {
  169. if (pulData != NULL)
  170. *pulData = pHashEntry->ulData;
  171. return TRUE;
  172. }
  173. return FALSE;
  174. } // GetTableEntry
  175. BOOLEAN
  176. PutTableEntry(
  177. IN PHASH_TABLE pTable,
  178. IN PACD_ADDR pszKey,
  179. IN ULONG ulData
  180. )
  181. {
  182. KIRQL irql;
  183. BOOLEAN fSuccess = FALSE;
  184. INT nBucket = HashString(pszKey);
  185. PHASH_ENTRY pHashEntry;
  186. IF_ACDDBG(ACD_DEBUG_TABLE) {
  187. AcdPrint(("AcdPutTableEntry(0x%x, %s)\n", pTable, pszKey));
  188. }
  189. KeAcquireSpinLock(&pTable->SpinLock, &irql);
  190. pHashEntry = GetTableEntryNL(pTable, pszKey);
  191. if (pHashEntry == NULL) {
  192. ALLOCATE_MEMORY(ACD_OBJECT_HASHENTRY, pHashEntry);
  193. if (pHashEntry == NULL) {
  194. // DbgPrint("PutTableEntry: ExAllocatePool failed\n");
  195. goto done;
  196. }
  197. RtlCopyMemory(pHashEntry->szKey, pszKey, sizeof (ACD_ADDR));
  198. InsertHeadList(
  199. &pTable->ListEntry[nBucket],
  200. &pHashEntry->ListEntry);
  201. }
  202. pHashEntry->ulData = ulData;
  203. fSuccess = TRUE;
  204. done:
  205. KeReleaseSpinLock(&pTable->SpinLock, irql);
  206. return fSuccess;
  207. } // PutTableEntry
  208. BOOLEAN
  209. DeleteTableEntry(
  210. IN PHASH_TABLE pTable,
  211. IN PACD_ADDR pszKey
  212. )
  213. {
  214. KIRQL irql;
  215. PHASH_ENTRY pHashEntry;
  216. KeAcquireSpinLock(&pTable->SpinLock, &irql);
  217. pHashEntry = GetTableEntryNL(pTable, pszKey);
  218. if (pHashEntry != NULL) {
  219. RemoveEntryList(&pHashEntry->ListEntry);
  220. FreeHashTableEntry(pHashEntry);
  221. }
  222. KeReleaseSpinLock(&pTable->SpinLock, irql);
  223. return (pHashEntry != NULL);
  224. } // DeleteTableEntry
  225.