288 lines
5.6 KiB
C
288 lines
5.6 KiB
C
/*++
|
||
|
||
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
|
||
|