mirror of https://github.com/tongzx/nt5src
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.6 KiB
287 lines
5.6 KiB
/*++
|
|
|
|
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
|
|
|