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