Source code of Windows XP (NT5)
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.0 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1990 - 1999
  3. Module Name:
  4. dictlib.c
  5. Abstract:
  6. Support library for maintaining a dictionary list (list of objects
  7. referenced by a key value).
  8. Environment:
  9. kernel mode only
  10. Notes:
  11. This module generates a static library
  12. Revision History:
  13. --*/
  14. #include <ntddk.h>
  15. #include <classpnp.h>
  16. #define DICTIONARY_SIGNATURE (((ULONG)'dict' << 32) + 'sig ')
  17. struct _DICTIONARY_HEADER {
  18. PDICTIONARY_HEADER Next;
  19. ULONGLONG Key;
  20. UCHAR Data[0];
  21. };
  22. struct _DICTIONARY_HEADER;
  23. typedef struct _DICTIONARY_HEADER DICTIONARY_HEADER, *PDICTIONARY_HEADER;
  24. VOID
  25. InitializeDictionary(
  26. IN PDICTIONARY Dictionary
  27. )
  28. {
  29. RtlZeroMemory(Dictionary, sizeof(Dictionary));
  30. Dictionary->Signature = DICTIONARY_SIGNATURE;
  31. KeInitializeSpinLock(&Dictionary->SpinLock);
  32. return;
  33. }
  34. BOOLEAN
  35. TestDictionarySignature(
  36. IN PDICTIONARY Dictionary
  37. )
  38. {
  39. return Dictionary->Signature == DICTIONARY_SIGNATURE;
  40. }
  41. NTSTATUS
  42. AllocateDictionaryEntry(
  43. IN PDICTIONARY Dictionary,
  44. IN ULONGLONG Key,
  45. IN ULONG Size,
  46. IN ULONG Tag,
  47. OUT PVOID *Entry
  48. )
  49. {
  50. PDICTIONARY_HEADER header;
  51. KIRQL oldIrql;
  52. PDICTIONARY_HEADER *entry;
  53. NTSTATUS status = STATUS_SUCCESS;
  54. *Entry = NULL;
  55. header = ExAllocatePoolWithTag(NonPagedPool,
  56. Size + sizeof(DICTIONARY_HEADER),
  57. Tag);
  58. if(header == NULL) {
  59. return STATUS_INSUFFICIENT_RESOURCES;
  60. }
  61. RtlZeroMemory(header, sizeof(DICTIONARY_HEADER) + Size);
  62. header->Key = Key;
  63. //
  64. // Find the correct location for this entry in the dictionary.
  65. //
  66. KeAcquireSpinLock(&(Dictionary->SpinLock), &oldIrql);
  67. TRY {
  68. entry = &(Dictionary->List);
  69. while(*entry != NULL) {
  70. if((*entry)->Key == Key) {
  71. //
  72. // Dictionary must have unique keys.
  73. //
  74. status = STATUS_OBJECT_NAME_COLLISION;
  75. LEAVE;
  76. } else if ((*entry)->Key < Key) {
  77. //
  78. // We will go ahead and insert the key in here.
  79. //
  80. break;
  81. } else {
  82. entry = &((*entry)->Next);
  83. }
  84. }
  85. //
  86. // If we make it here then we will go ahead and do the insertion.
  87. //
  88. header->Next = *entry;
  89. *entry = header;
  90. } FINALLY {
  91. KeReleaseSpinLock(&(Dictionary->SpinLock), oldIrql);
  92. if(!NT_SUCCESS(status)) {
  93. ExFreePool(header);
  94. } else {
  95. *Entry = (PVOID) header->Data;
  96. }
  97. }
  98. return status;
  99. }
  100. PVOID
  101. GetDictionaryEntry(
  102. IN PDICTIONARY Dictionary,
  103. IN ULONGLONG Key
  104. )
  105. {
  106. PDICTIONARY_HEADER entry;
  107. PVOID data;
  108. KIRQL oldIrql;
  109. data = NULL;
  110. KeAcquireSpinLock(&(Dictionary->SpinLock), &oldIrql);
  111. entry = Dictionary->List;
  112. while (entry != NULL) {
  113. if (entry->Key == Key) {
  114. data = entry->Data;
  115. break;
  116. } else {
  117. entry = entry->Next;
  118. }
  119. }
  120. KeReleaseSpinLock(&(Dictionary->SpinLock), oldIrql);
  121. return data;
  122. }
  123. VOID
  124. FreeDictionaryEntry(
  125. IN PDICTIONARY Dictionary,
  126. IN PVOID Entry
  127. )
  128. {
  129. PDICTIONARY_HEADER header;
  130. PDICTIONARY_HEADER *entry;
  131. KIRQL oldIrql;
  132. BOOLEAN found;
  133. found = FALSE;
  134. header = CONTAINING_RECORD(Entry, DICTIONARY_HEADER, Data);
  135. KeAcquireSpinLock(&(Dictionary->SpinLock), &oldIrql);
  136. entry = &(Dictionary->List);
  137. while(*entry != NULL) {
  138. if(*entry == header) {
  139. *entry = header->Next;
  140. found = TRUE;
  141. break;
  142. } else {
  143. entry = &(*entry)->Next;
  144. }
  145. }
  146. KeReleaseSpinLock(&(Dictionary->SpinLock), oldIrql);
  147. //
  148. // calling this w/an invalid pointer invalidates the dictionary system,
  149. // so ASSERT() that we never try to Free something not in the list
  150. //
  151. ASSERT(found);
  152. if (found) {
  153. ExFreePool(header);
  154. }
  155. return;
  156. }