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.
215 lines
4.2 KiB
215 lines
4.2 KiB
/*++
|
|
|
|
Copyright (C) Microsoft Corporation, 1990 - 1999
|
|
|
|
Module Name:
|
|
|
|
dictlib.c
|
|
|
|
Abstract:
|
|
|
|
Support library for maintaining a dictionary list (list of objects
|
|
referenced by a key value).
|
|
|
|
Environment:
|
|
|
|
kernel mode only
|
|
|
|
Notes:
|
|
|
|
This module generates a static library
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include <ntddk.h>
|
|
#include <classpnp.h>
|
|
|
|
#define DICTIONARY_SIGNATURE 'tciD'
|
|
|
|
struct _DICTIONARY_HEADER {
|
|
PDICTIONARY_HEADER Next;
|
|
ULONGLONG Key;
|
|
UCHAR Data[0];
|
|
};
|
|
|
|
struct _DICTIONARY_HEADER;
|
|
typedef struct _DICTIONARY_HEADER DICTIONARY_HEADER, *PDICTIONARY_HEADER;
|
|
|
|
|
|
VOID
|
|
InitializeDictionary(
|
|
IN PDICTIONARY Dictionary
|
|
)
|
|
{
|
|
RtlZeroMemory(Dictionary, sizeof(DICTIONARY));
|
|
Dictionary->Signature = DICTIONARY_SIGNATURE;
|
|
KeInitializeSpinLock(&Dictionary->SpinLock);
|
|
return;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
TestDictionarySignature(
|
|
IN PDICTIONARY Dictionary
|
|
)
|
|
{
|
|
return Dictionary->Signature == DICTIONARY_SIGNATURE;
|
|
}
|
|
|
|
NTSTATUS
|
|
AllocateDictionaryEntry(
|
|
IN PDICTIONARY Dictionary,
|
|
IN ULONGLONG Key,
|
|
IN ULONG Size,
|
|
IN ULONG Tag,
|
|
OUT PVOID *Entry
|
|
)
|
|
{
|
|
PDICTIONARY_HEADER header;
|
|
KIRQL oldIrql;
|
|
PDICTIONARY_HEADER *entry;
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
*Entry = NULL;
|
|
|
|
header = ExAllocatePoolWithTag(NonPagedPool,
|
|
Size + sizeof(DICTIONARY_HEADER),
|
|
Tag);
|
|
|
|
if(header == NULL) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlZeroMemory(header, sizeof(DICTIONARY_HEADER) + Size);
|
|
header->Key = Key;
|
|
|
|
//
|
|
// Find the correct location for this entry in the dictionary.
|
|
//
|
|
|
|
KeAcquireSpinLock(&(Dictionary->SpinLock), &oldIrql);
|
|
|
|
TRY {
|
|
|
|
entry = &(Dictionary->List);
|
|
|
|
while(*entry != NULL) {
|
|
if((*entry)->Key == Key) {
|
|
|
|
//
|
|
// Dictionary must have unique keys.
|
|
//
|
|
|
|
status = STATUS_OBJECT_NAME_COLLISION;
|
|
LEAVE;
|
|
|
|
} else if ((*entry)->Key < Key) {
|
|
|
|
//
|
|
// We will go ahead and insert the key in here.
|
|
//
|
|
break;
|
|
} else {
|
|
entry = &((*entry)->Next);
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we make it here then we will go ahead and do the insertion.
|
|
//
|
|
|
|
header->Next = *entry;
|
|
*entry = header;
|
|
|
|
} FINALLY {
|
|
KeReleaseSpinLock(&(Dictionary->SpinLock), oldIrql);
|
|
|
|
if(!NT_SUCCESS(status)) {
|
|
ExFreePool(header);
|
|
} else {
|
|
*Entry = (PVOID) header->Data;
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
|
|
|
|
PVOID
|
|
GetDictionaryEntry(
|
|
IN PDICTIONARY Dictionary,
|
|
IN ULONGLONG Key
|
|
)
|
|
{
|
|
PDICTIONARY_HEADER entry;
|
|
PVOID data;
|
|
KIRQL oldIrql;
|
|
|
|
|
|
data = NULL;
|
|
|
|
KeAcquireSpinLock(&(Dictionary->SpinLock), &oldIrql);
|
|
|
|
entry = Dictionary->List;
|
|
while (entry != NULL) {
|
|
|
|
if (entry->Key == Key) {
|
|
data = entry->Data;
|
|
break;
|
|
} else {
|
|
entry = entry->Next;
|
|
}
|
|
}
|
|
|
|
KeReleaseSpinLock(&(Dictionary->SpinLock), oldIrql);
|
|
|
|
return data;
|
|
}
|
|
|
|
|
|
VOID
|
|
FreeDictionaryEntry(
|
|
IN PDICTIONARY Dictionary,
|
|
IN PVOID Entry
|
|
)
|
|
{
|
|
PDICTIONARY_HEADER header;
|
|
PDICTIONARY_HEADER *entry;
|
|
KIRQL oldIrql;
|
|
BOOLEAN found;
|
|
|
|
found = FALSE;
|
|
header = CONTAINING_RECORD(Entry, DICTIONARY_HEADER, Data);
|
|
|
|
KeAcquireSpinLock(&(Dictionary->SpinLock), &oldIrql);
|
|
|
|
entry = &(Dictionary->List);
|
|
while(*entry != NULL) {
|
|
|
|
if(*entry == header) {
|
|
*entry = header->Next;
|
|
found = TRUE;
|
|
break;
|
|
} else {
|
|
entry = &(*entry)->Next;
|
|
}
|
|
}
|
|
|
|
KeReleaseSpinLock(&(Dictionary->SpinLock), oldIrql);
|
|
|
|
//
|
|
// calling this w/an invalid pointer invalidates the dictionary system,
|
|
// so ASSERT() that we never try to Free something not in the list
|
|
//
|
|
|
|
ASSERT(found);
|
|
if (found) {
|
|
ExFreePool(header);
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|