[CLT2012]
[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 "classp.h"
27
28 #define DICTIONARY_SIGNATURE 'dsig'
29
30 typedef struct _DICTIONARY_HEADER {
31 struct _DICTIONARY_HEADER* Next;
32 ULONGLONG Key;
33 UCHAR Data[0];
34 } DICTIONARY_HEADER, *PDICTIONARY_HEADER;
35
36
37 VOID
38 InitializeDictionary(
39 IN PDICTIONARY Dictionary
40 )
41 {
42 RtlZeroMemory(Dictionary, sizeof(DICTIONARY));
43 Dictionary->Signature = DICTIONARY_SIGNATURE;
44 KeInitializeSpinLock(&Dictionary->SpinLock);
45 return;
46 }
47
48
49 BOOLEAN
50 TestDictionarySignature(
51 IN PDICTIONARY Dictionary
52 )
53 {
54 return Dictionary->Signature == DICTIONARY_SIGNATURE;
55 }
56
57 NTSTATUS
58 AllocateDictionaryEntry(
59 IN PDICTIONARY Dictionary,
60 IN ULONGLONG Key,
61 IN ULONG Size,
62 IN ULONG Tag,
63 OUT PVOID *Entry
64 )
65 {
66 PDICTIONARY_HEADER header;
67 KIRQL oldIrql;
68 PDICTIONARY_HEADER *entry;
69
70 NTSTATUS status = STATUS_SUCCESS;
71
72 *Entry = NULL;
73
74 header = ExAllocatePoolWithTag(NonPagedPool,
75 Size + sizeof(DICTIONARY_HEADER),
76 Tag);
77
78 if(header == NULL) {
79 return STATUS_INSUFFICIENT_RESOURCES;
80 }
81
82 RtlZeroMemory(header, sizeof(DICTIONARY_HEADER) + Size);
83 header->Key = Key;
84
85 //
86 // Find the correct location for this entry in the dictionary.
87 //
88
89 KeAcquireSpinLock(&(Dictionary->SpinLock), &oldIrql);
90
91 TRY {
92
93 entry = &(Dictionary->List);
94
95 while(*entry != NULL) {
96 if((*entry)->Key == Key) {
97
98 //
99 // Dictionary must have unique keys.
100 //
101
102 status = STATUS_OBJECT_NAME_COLLISION;
103 LEAVE;
104
105 } else if ((*entry)->Key < Key) {
106
107 //
108 // We will go ahead and insert the key in here.
109 //
110 break;
111 } else {
112 entry = &((*entry)->Next);
113 }
114 }
115
116 //
117 // If we make it here then we will go ahead and do the insertion.
118 //
119
120 header->Next = *entry;
121 *entry = header;
122
123 } FINALLY {
124 KeReleaseSpinLock(&(Dictionary->SpinLock), oldIrql);
125
126 if(!NT_SUCCESS(status)) {
127 ExFreePool(header);
128 } else {
129 *Entry = (PVOID) header->Data;
130 }
131 }
132 return status;
133 }
134
135
136 PVOID
137 GetDictionaryEntry(
138 IN PDICTIONARY Dictionary,
139 IN ULONGLONG Key
140 )
141 {
142 PDICTIONARY_HEADER entry;
143 PVOID data;
144 KIRQL oldIrql;
145
146
147 data = NULL;
148
149 KeAcquireSpinLock(&(Dictionary->SpinLock), &oldIrql);
150
151 entry = Dictionary->List;
152 while (entry != NULL) {
153
154 if (entry->Key == Key) {
155 data = entry->Data;
156 break;
157 } else {
158 entry = entry->Next;
159 }
160 }
161
162 KeReleaseSpinLock(&(Dictionary->SpinLock), oldIrql);
163
164 return data;
165 }
166
167
168 VOID
169 FreeDictionaryEntry(
170 IN PDICTIONARY Dictionary,
171 IN PVOID Entry
172 )
173 {
174 PDICTIONARY_HEADER header;
175 PDICTIONARY_HEADER *entry;
176 KIRQL oldIrql;
177 BOOLEAN found;
178
179 found = FALSE;
180 header = CONTAINING_RECORD(Entry, DICTIONARY_HEADER, Data);
181
182 KeAcquireSpinLock(&(Dictionary->SpinLock), &oldIrql);
183
184 entry = &(Dictionary->List);
185 while(*entry != NULL) {
186
187 if(*entry == header) {
188 *entry = header->Next;
189 found = TRUE;
190 break;
191 } else {
192 entry = &(*entry)->Next;
193 }
194 }
195
196 KeReleaseSpinLock(&(Dictionary->SpinLock), oldIrql);
197
198 //
199 // calling this w/an invalid pointer invalidates the dictionary system,
200 // so ASSERT() that we never try to Free something not in the list
201 //
202
203 ASSERT(found);
204 if (found) {
205 ExFreePool(header);
206 }
207
208 return;
209
210 }
211
212