Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232/*++
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>
#ifdef __REACTOS__#undef MdlMappingNoExecute#define MdlMappingNoExecute 0#define NonPagedPoolNx NonPagedPool#define NonPagedPoolNxCacheAligned NonPagedPoolCacheAligned#undef POOL_NX_ALLOCATION#define POOL_NX_ALLOCATION 0#endif
#define DICTIONARY_SIGNATURE 'tciD'
#ifdef _MSC_VER#pragma warning(push)#pragma warning(disable:4200) // nonstandard extension used : zero-sized array in struct/union#endifstruct _DICTIONARY_HEADER { PDICTIONARY_HEADER Next; ULONGLONG Key; UCHAR Data[0];};#ifdef _MSC_VER#pragma warning(pop)#endif
struct _DICTIONARY_HEADER;typedef struct _DICTIONARY_HEADER DICTIONARY_HEADER, *PDICTIONARY_HEADER;
VOIDInitializeDictionary( IN PDICTIONARY Dictionary ){ RtlZeroMemory(Dictionary, sizeof(DICTIONARY)); Dictionary->Signature = DICTIONARY_SIGNATURE; KeInitializeSpinLock(&Dictionary->SpinLock); return;}
BOOLEANTestDictionarySignature( IN PDICTIONARY Dictionary ){ return Dictionary->Signature == DICTIONARY_SIGNATURE;}
NTSTATUSAllocateDictionaryEntry( IN PDICTIONARY Dictionary, IN ULONGLONG Key, _In_range_(0, sizeof(FILE_OBJECT_EXTENSION)) 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(NonPagedPoolNx, 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)) { FREE_POOL(header); } else { *Entry = (PVOID) header->Data; } } return status;}
PVOIDGetDictionaryEntry( 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;}
VOIDFreeDictionaryEntry( 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 NT_ASSERT() that we never try to Free something not in the list //
NT_ASSERT(found); if (found) { FREE_POOL(header); }
return;
}