Standardize comment headers. Patch by Trevor McCort
[reactos.git] / reactos / ntoskrnl / ob / sdcache.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ob/sdcache.c
6 * PURPOSE: No purpose listed.
7 *
8 * PROGRAMMERS: David Welch (welch@cwcom.net)
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17
18 /* TYPES ********************************************************************/
19
20 typedef struct _SD_CACHE_ENTRY
21 {
22 LIST_ENTRY ListEntry;
23 ULONG HashValue;
24 ULONG Index;
25 ULONG RefCount;
26 } SD_CACHE_ENTRY, *PSD_CACHE_ENTRY;
27
28
29 /* GLOBALS ******************************************************************/
30
31 PLIST_ENTRY ObpSdCache;
32 KSPIN_LOCK ObpSdCacheSpinLock;
33 KIRQL ObpSdCacheIrql;
34
35
36 #define SD_CACHE_ENTRIES 0x100
37
38 /* FUNCTIONS ****************************************************************/
39
40 NTSTATUS
41 ObpInitSdCache(VOID)
42 {
43 ULONG i;
44
45 ObpSdCache = ExAllocatePool(NonPagedPool,
46 SD_CACHE_ENTRIES * sizeof(LIST_ENTRY));
47 if (ObpSdCache == NULL)
48 {
49 return STATUS_INSUFFICIENT_RESOURCES;
50 }
51
52 for (i = 0; i < SD_CACHE_ENTRIES; i++)
53 {
54 InitializeListHead(&ObpSdCache[i]);
55 }
56
57 KeInitializeSpinLock(&ObpSdCacheSpinLock);
58
59 return STATUS_SUCCESS;
60 }
61
62
63 static VOID
64 ObpSdCacheLock(VOID)
65 {
66 KeAcquireSpinLock(&ObpSdCacheSpinLock,
67 &ObpSdCacheIrql);
68 }
69
70
71 static VOID
72 ObpSdCacheUnlock(VOID)
73 {
74 KeReleaseSpinLock(&ObpSdCacheSpinLock,
75 ObpSdCacheIrql);
76 }
77
78
79 static ULONG
80 ObpHash(PVOID Buffer,
81 ULONG Length)
82 {
83 PUCHAR Ptr;
84 ULONG Value;
85 ULONG i;
86
87 Ptr = (PUCHAR)Buffer;
88 Value = 0;
89 for (i = 0; i < Length; i++)
90 {
91 Value += *Ptr;
92 Ptr++;
93 }
94
95 return Value;
96 }
97
98
99 static ULONG
100 ObpHashSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)
101 {
102 ULONG Value;
103 BOOLEAN Defaulted;
104 BOOLEAN DaclPresent;
105 BOOLEAN SaclPresent;
106 PSID Owner = NULL;
107 PSID Group = NULL;
108 PACL Dacl = NULL;
109 PACL Sacl = NULL;
110
111 RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
112 &Owner,
113 &Defaulted);
114
115 RtlGetGroupSecurityDescriptor(SecurityDescriptor,
116 &Group,
117 &Defaulted);
118
119 RtlGetDaclSecurityDescriptor(SecurityDescriptor,
120 &DaclPresent,
121 &Dacl,
122 &Defaulted);
123
124 RtlGetSaclSecurityDescriptor(SecurityDescriptor,
125 &SaclPresent,
126 &Sacl,
127 &Defaulted);
128
129 Value = 0;
130 if (Owner != NULL)
131 {
132 Value += ObpHash(Owner, RtlLengthSid(Owner));
133 }
134
135 if (Group != NULL)
136 {
137 Value += ObpHash(Group, RtlLengthSid(Group));
138 }
139
140 if (DaclPresent == TRUE && Dacl != NULL)
141 {
142 Value += ObpHash(Dacl, Dacl->AclSize);
143 }
144
145 if (SaclPresent == TRUE && Sacl != NULL)
146 {
147 Value += ObpHash(Sacl, Sacl->AclSize);
148 }
149
150 return Value;
151 }
152
153
154 static PSD_CACHE_ENTRY
155 ObpCreateCacheEntry(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
156 IN ULONG HashValue,
157 IN ULONG Index,
158 OUT PSECURITY_DESCRIPTOR *NewSD)
159 {
160 PSECURITY_DESCRIPTOR Sd;
161 PSD_CACHE_ENTRY CacheEntry;
162 ULONG Length;
163
164 DPRINT("ObpCreateCacheEntry() called\n");
165
166 Length = RtlLengthSecurityDescriptor(SecurityDescriptor);
167
168 CacheEntry = ExAllocatePool(NonPagedPool,
169 sizeof(SD_CACHE_ENTRY) + Length);
170 if (CacheEntry == NULL)
171 {
172 DPRINT1("ExAllocatePool() failed\n");
173 return NULL;
174 }
175
176 CacheEntry->HashValue = HashValue;
177 CacheEntry->Index = Index;
178 CacheEntry->RefCount = 1;
179
180 Sd = (PSECURITY_DESCRIPTOR)(CacheEntry + 1);
181 RtlCopyMemory(Sd,
182 SecurityDescriptor,
183 Length);
184
185 *NewSD = Sd;
186
187 DPRINT("ObpCreateCacheEntry() done\n");
188
189 return CacheEntry;
190 }
191
192
193 static BOOLEAN
194 ObpCompareSecurityDescriptors(IN PSECURITY_DESCRIPTOR Sd1,
195 IN PSECURITY_DESCRIPTOR Sd2)
196 {
197 ULONG Length1;
198 ULONG Length2;
199
200 Length1 = RtlLengthSecurityDescriptor(Sd1);
201 Length2 = RtlLengthSecurityDescriptor(Sd2);
202 if (Length1 != Length2)
203 return FALSE;
204
205 if (RtlCompareMemory(Sd1, Sd2, Length1) != Length1)
206 return FALSE;
207
208 return TRUE;
209 }
210
211
212 NTSTATUS
213 ObpAddSecurityDescriptor(IN PSECURITY_DESCRIPTOR SourceSD,
214 OUT PSECURITY_DESCRIPTOR *DestinationSD)
215 {
216 PSECURITY_DESCRIPTOR Sd;
217 PLIST_ENTRY CurrentEntry;
218 PSD_CACHE_ENTRY CacheEntry;
219 ULONG HashValue;
220 ULONG Index;
221 NTSTATUS Status;
222
223 DPRINT("ObpAddSecurityDescriptor() called\n");
224
225 HashValue = ObpHashSecurityDescriptor(SourceSD);
226 Index = HashValue & 0xFF;
227
228 ObpSdCacheLock();
229
230 if (!IsListEmpty(&ObpSdCache[Index]))
231 {
232 CurrentEntry = ObpSdCache[Index].Flink;
233 while (CurrentEntry != &ObpSdCache[Index])
234 {
235 CacheEntry = CONTAINING_RECORD(CurrentEntry,
236 SD_CACHE_ENTRY,
237 ListEntry);
238 Sd = (PSECURITY_DESCRIPTOR)(CacheEntry + 1);
239
240 if (CacheEntry->HashValue == HashValue &&
241 ObpCompareSecurityDescriptors(SourceSD, Sd))
242 {
243 CacheEntry->RefCount++;
244 DPRINT("RefCount %lu\n", CacheEntry->RefCount);
245 *DestinationSD = Sd;
246
247 ObpSdCacheUnlock();
248
249 DPRINT("ObpAddSecurityDescriptor() done\n");
250
251 return STATUS_SUCCESS;
252 }
253
254 CurrentEntry = CurrentEntry->Flink;
255 }
256 }
257
258 CacheEntry = ObpCreateCacheEntry(SourceSD,
259 HashValue,
260 Index,
261 DestinationSD);
262 if (CacheEntry == NULL)
263 {
264 DPRINT1("ObpCreateCacheEntry() failed\n");
265 Status = STATUS_INSUFFICIENT_RESOURCES;
266 }
267 else
268 {
269 DPRINT("RefCount 1\n");
270 InsertTailList(&ObpSdCache[Index], &CacheEntry->ListEntry);
271 Status = STATUS_SUCCESS;
272 }
273
274 ObpSdCacheUnlock();
275
276 DPRINT("ObpAddSecurityDescriptor() done\n");
277
278 return Status;
279 }
280
281
282 NTSTATUS
283 ObpRemoveSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)
284 {
285 PSD_CACHE_ENTRY CacheEntry;
286
287 DPRINT("ObpRemoveSecurityDescriptor() called\n");
288
289 ObpSdCacheLock();
290
291 CacheEntry = (PSD_CACHE_ENTRY)((ULONG_PTR)SecurityDescriptor - sizeof(SD_CACHE_ENTRY));
292
293 CacheEntry->RefCount--;
294 DPRINT("RefCount %lu\n", CacheEntry->RefCount);
295 if (CacheEntry->RefCount == 0)
296 {
297 DPRINT("Remove cache entry\n");
298 RemoveEntryList(&CacheEntry->ListEntry);
299 ExFreePool(CacheEntry);
300 }
301
302 ObpSdCacheUnlock();
303
304 DPRINT("ObpRemoveSecurityDescriptor() done\n");
305
306 return STATUS_SUCCESS;
307 }
308
309
310 VOID
311 ObpReferenceCachedSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)
312 {
313 PSD_CACHE_ENTRY CacheEntry;
314
315 DPRINT("ObpReferenceCachedSecurityDescriptor() called\n");
316
317 ObpSdCacheLock();
318
319 CacheEntry = (PSD_CACHE_ENTRY)((ULONG_PTR)SecurityDescriptor - sizeof(SD_CACHE_ENTRY));
320
321 CacheEntry->RefCount++;
322 DPRINT("RefCount %lu\n", CacheEntry->RefCount);
323
324 ObpSdCacheUnlock();
325
326 DPRINT("ObpReferenceCachedSecurityDescriptor() done\n");
327 }
328
329
330 VOID
331 ObpDereferenceCachedSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)
332 {
333 DPRINT("ObpDereferenceCachedSecurityDescriptor() called\n");
334
335 ObpRemoveSecurityDescriptor(SecurityDescriptor);
336
337 DPRINT("ObpDereferenceCachedSecurityDescriptor() done\n");
338 }
339
340 /* EOF */