summaryrefslogtreecommitdiffstats
path: root/private/ntos/tdi/acd/table.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/ntos/tdi/acd/table.c286
1 files changed, 286 insertions, 0 deletions
diff --git a/private/ntos/tdi/acd/table.c b/private/ntos/tdi/acd/table.c
new file mode 100644
index 000000000..0846b97e6
--- /dev/null
+++ b/private/ntos/tdi/acd/table.c
@@ -0,0 +1,286 @@
+/*++
+
+Copyright(c) 1995 Microsoft Corporation
+
+MODULE NAME
+ table.c
+
+ABSTRACT
+ Generic hash table manipulation routines.
+
+AUTHOR
+ Anthony Discolo (adiscolo) 28-Jul-1995
+
+REVISION HISTORY
+
+--*/
+
+#include <ndis.h>
+#include <cxport.h>
+#include <tdi.h>
+#include <tdikrnl.h>
+#include <tdistat.h>
+#include <tdiinfo.h>
+#include <acd.h>
+#include <acdapi.h>
+
+#include "table.h"
+#include "acddefs.h"
+#include "mem.h"
+#include "debug.h"
+
+
+
+PHASH_TABLE
+NewTable()
+{
+ PHASH_TABLE pTable;
+ INT i;
+
+ ALLOCATE_MEMORY(sizeof (HASH_TABLE), pTable);
+ if (pTable == NULL) {
+ DbgPrint("AcdNewTable: ExAllocatePool failed\n");
+ return NULL;
+ }
+ KeInitializeSpinLock(&pTable->SpinLock);
+ for (i = 0; i < NBUCKETS; i++)
+ InitializeListHead(&pTable->ListEntry[i]);
+
+ return pTable;
+} // NewTable
+
+
+
+VOID
+FreeHashTableEntry(
+ PHASH_ENTRY pHashEntry
+ )
+{
+ FREE_MEMORY(pHashEntry);
+} // FreeHashTableEntry
+
+
+
+VOID
+ClearTable(
+ PHASH_TABLE pTable
+ )
+{
+ KIRQL irql;
+ INT i;
+ PLIST_ENTRY pHead;
+ PHASH_ENTRY pHashEntry;
+
+ KeAcquireSpinLock(&pTable->SpinLock, &irql);
+ for (i = 0; i < NBUCKETS; i++) {
+ while (!IsListEmpty(&pTable->ListEntry[i])) {
+ pHead = RemoveHeadList(&pTable->ListEntry[i]);
+ pHashEntry = CONTAINING_RECORD(pHead, HASH_ENTRY, ListEntry);
+
+ FreeHashTableEntry(pHashEntry);
+ }
+ }
+ KeReleaseSpinLock(&pTable->SpinLock, irql);
+} // ClearTable
+
+
+
+VOID
+FreeTable(
+ PHASH_TABLE pTable
+ )
+{
+ ClearTable(pTable);
+ FREE_MEMORY(pTable);
+} // FreeTable
+
+
+
+VOID
+EnumTable(
+ IN PHASH_TABLE pTable,
+ IN PHASH_TABLE_ENUM_PROC pProc,
+ IN PVOID pArg
+ )
+{
+ INT i;
+ PLIST_ENTRY pEntry;
+ PHASH_ENTRY pHashEntry;
+ KIRQL irql;
+
+ KeAcquireSpinLock(&pTable->SpinLock, &irql);
+ for (i = 0; i < NBUCKETS; i++) {
+ for (pEntry = pTable->ListEntry[i].Flink;
+ pEntry != &pTable->ListEntry[i];
+ pEntry = pEntry->Flink)
+ {
+ pHashEntry = CONTAINING_RECORD(pEntry, HASH_ENTRY, ListEntry);
+
+ //
+ // If the enumerator procedure
+ // returns FALSE, terminate the
+ // enumeration.
+ //
+ if (!pProc(pArg, &pHashEntry->szKey, pHashEntry->ulData))
+ goto done;
+ }
+ }
+done:
+ KeReleaseSpinLock(&pTable->SpinLock, irql);
+} // EnumTable
+
+
+
+INT
+HashString(
+ IN PACD_ADDR pszKey
+ )
+{
+ ULONG ulHashValue = 0;
+ CHAR ch;
+ PCSZ p = (PCSZ)pszKey;
+
+ while (*p != L'\0') {
+ ch = tolower(*p);
+ ulHashValue += (INT)(ch) * (INT)(ch);
+ p++;
+ }
+
+ return (INT)(ulHashValue % NBUCKETS);
+} // HashString
+
+
+
+BOOLEAN
+IsEqualKey(
+ PACD_ADDR pszKey1,
+ PACD_ADDR pszKey2
+ )
+{
+ BOOLEAN fFound;
+
+ fFound = (BOOLEAN)RtlEqualMemory(pszKey1, pszKey2, sizeof (ACD_ADDR));
+ IF_ACDDBG(ACD_DEBUG_TABLE) {
+ AcdPrint(("AcdIsEqualKey(%s, %s) returns %d\n", pszKey1, pszKey2, fFound));
+ }
+ return fFound;
+} // IsEqualKey
+
+
+
+PHASH_ENTRY
+GetTableEntryNL(
+ IN PHASH_TABLE pTable,
+ IN PACD_ADDR pszKey
+ )
+{
+ INT nBucket = HashString(pszKey);
+ PLIST_ENTRY pEntry;
+ PHASH_ENTRY pHashEntry;
+
+ for (pEntry = pTable->ListEntry[nBucket].Flink;
+ pEntry != &pTable->ListEntry[nBucket];
+ pEntry = pEntry->Flink)
+ {
+ pHashEntry = CONTAINING_RECORD(pEntry, HASH_ENTRY, ListEntry);
+
+ if (IsEqualKey(&pHashEntry->szKey, pszKey)) {
+ IF_ACDDBG(ACD_DEBUG_TABLE) {
+ AcdPrint(("AcdGetTableEntryNL(0x%x, %s) returns 0x%x\n", pTable, pszKey, pHashEntry));
+ }
+ return pHashEntry;
+ }
+ }
+
+ IF_ACDDBG(ACD_DEBUG_TABLE) {
+ AcdPrint(("AcdGetTableEntryNL(0x%x, %s) returns NULL\n", pTable, pszKey));
+ }
+ return NULL;
+} // GetTableEntryNL
+
+
+
+BOOLEAN
+GetTableEntry(
+ IN PHASH_TABLE pTable,
+ IN PACD_ADDR pszKey,
+ OUT PULONG pulData
+ )
+{
+ KIRQL irql;
+ PHASH_ENTRY pHashEntry;
+
+ KeAcquireSpinLock(&pTable->SpinLock, &irql);
+ pHashEntry = GetTableEntryNL(pTable, pszKey);
+ KeReleaseSpinLock(&pTable->SpinLock, irql);
+
+ if (pHashEntry != NULL) {
+ if (pulData != NULL)
+ *pulData = pHashEntry->ulData;
+ return TRUE;
+ }
+
+ return FALSE;
+} // GetTableEntry
+
+
+
+BOOLEAN
+PutTableEntry(
+ IN PHASH_TABLE pTable,
+ IN PACD_ADDR pszKey,
+ IN ULONG ulData
+ )
+{
+ KIRQL irql;
+ BOOLEAN fSuccess = FALSE;
+ INT nBucket = HashString(pszKey);
+ PHASH_ENTRY pHashEntry;
+
+ IF_ACDDBG(ACD_DEBUG_TABLE) {
+ AcdPrint(("AcdPutTableEntry(0x%x, %s)\n", pTable, pszKey));
+ }
+
+ KeAcquireSpinLock(&pTable->SpinLock, &irql);
+
+ pHashEntry = GetTableEntryNL(pTable, pszKey);
+ if (pHashEntry == NULL) {
+ ALLOCATE_MEMORY(ACD_OBJECT_HASHENTRY, pHashEntry);
+ if (pHashEntry == NULL) {
+ DbgPrint("PutTableEntry: ExAllocatePool failed\n");
+ goto done;
+ }
+ RtlCopyMemory(pHashEntry->szKey, pszKey, sizeof (ACD_ADDR));
+ InsertHeadList(
+ &pTable->ListEntry[nBucket],
+ &pHashEntry->ListEntry);
+ }
+ pHashEntry->ulData = ulData;
+ fSuccess = TRUE;
+
+done:
+ KeReleaseSpinLock(&pTable->SpinLock, irql);
+ return fSuccess;
+} // PutTableEntry
+
+
+
+BOOLEAN
+DeleteTableEntry(
+ IN PHASH_TABLE pTable,
+ IN PACD_ADDR pszKey
+ )
+{
+ KIRQL irql;
+ PHASH_ENTRY pHashEntry;
+
+ KeAcquireSpinLock(&pTable->SpinLock, &irql);
+ pHashEntry = GetTableEntryNL(pTable, pszKey);
+ if (pHashEntry != NULL) {
+ RemoveEntryList(&pHashEntry->ListEntry);
+ FreeHashTableEntry(pHashEntry);
+ }
+ KeReleaseSpinLock(&pTable->SpinLock, irql);
+
+ return (pHashEntry != NULL);
+} // DeleteTableEntry