ntoskrnl header cleanups
[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 #define SD_CACHE_ENTRIES 0x100
32
33 LIST_ENTRY ObpSdCache[SD_CACHE_ENTRIES];
34 FAST_MUTEX ObpSdCacheMutex;
35
36 /* FUNCTIONS ****************************************************************/
37
38 NTSTATUS
39 NTAPI
40 ObpInitSdCache(VOID)
41 {
42 ULONG i;
43
44 for (i = 0; i < (sizeof(ObpSdCache) / sizeof(ObpSdCache[0])); i++)
45 {
46 InitializeListHead(&ObpSdCache[i]);
47 }
48
49 ExInitializeFastMutex(&ObpSdCacheMutex);
50
51 return STATUS_SUCCESS;
52 }
53
54
55 static inline VOID
56 ObpSdCacheLock(VOID)
57 {
58 /* can't acquire a fast mutex in the early boot process... */
59 if(KeGetCurrentThread() != NULL)
60 {
61 ExAcquireFastMutex(&ObpSdCacheMutex);
62 }
63 }
64
65
66 static inline VOID
67 ObpSdCacheUnlock(VOID)
68 {
69 /* can't acquire a fast mutex in the early boot process... */
70 if(KeGetCurrentThread() != NULL)
71 {
72 ExReleaseFastMutex(&ObpSdCacheMutex);
73 }
74 }
75
76
77 static ULONG
78 ObpHash(PVOID Buffer,
79 ULONG Length)
80 {
81 PUCHAR Ptr;
82 ULONG Value;
83 ULONG i;
84
85 Ptr = (PUCHAR)Buffer;
86 Value = 0;
87 for (i = 0; i < Length; i++)
88 {
89 Value += *Ptr;
90 Ptr++;
91 }
92
93 return Value;
94 }
95
96
97 static ULONG
98 ObpHashSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)
99 {
100 ULONG Value;
101 BOOLEAN Defaulted;
102 BOOLEAN DaclPresent;
103 BOOLEAN SaclPresent;
104 PSID Owner = NULL;
105 PSID Group = NULL;
106 PACL Dacl = NULL;
107 PACL Sacl = NULL;
108
109 RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
110 &Owner,
111 &Defaulted);
112
113 RtlGetGroupSecurityDescriptor(SecurityDescriptor,
114 &Group,
115 &Defaulted);
116
117 RtlGetDaclSecurityDescriptor(SecurityDescriptor,
118 &DaclPresent,
119 &Dacl,
120 &Defaulted);
121
122 RtlGetSaclSecurityDescriptor(SecurityDescriptor,
123 &SaclPresent,
124 &Sacl,
125 &Defaulted);
126
127 Value = 0;
128 if (Owner != NULL)
129 {
130 Value += ObpHash(Owner, RtlLengthSid(Owner));
131 }
132
133 if (Group != NULL)
134 {
135 Value += ObpHash(Group, RtlLengthSid(Group));
136 }
137
138 if (DaclPresent == TRUE && Dacl != NULL)
139 {
140 Value += ObpHash(Dacl, Dacl->AclSize);
141 }
142
143 if (SaclPresent == TRUE && Sacl != NULL)
144 {
145 Value += ObpHash(Sacl, Sacl->AclSize);
146 }
147
148 return Value;
149 }
150
151
152 static PSD_CACHE_ENTRY
153 ObpCreateCacheEntry(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
154 IN ULONG HashValue,
155 IN ULONG Index,
156 OUT PSECURITY_DESCRIPTOR *NewSD)
157 {
158 PSECURITY_DESCRIPTOR Sd;
159 PSD_CACHE_ENTRY CacheEntry;
160 ULONG Length;
161
162 DPRINT("ObpCreateCacheEntry() called\n");
163
164 Length = RtlLengthSecurityDescriptor(SecurityDescriptor);
165
166 CacheEntry = ExAllocatePool(NonPagedPool,
167 sizeof(SD_CACHE_ENTRY) + Length);
168 if (CacheEntry == NULL)
169 {
170 DPRINT1("ExAllocatePool() failed\n");
171 return NULL;
172 }
173
174 CacheEntry->HashValue = HashValue;
175 CacheEntry->Index = Index;
176 CacheEntry->RefCount = 1;
177
178 Sd = (PSECURITY_DESCRIPTOR)(CacheEntry + 1);
179 RtlCopyMemory(Sd,
180 SecurityDescriptor,
181 Length);
182
183 *NewSD = Sd;
184
185 DPRINT("ObpCreateCacheEntry() done\n");
186
187 return CacheEntry;
188 }
189
190
191 static BOOLEAN
192 ObpCompareSecurityDescriptors(IN PSECURITY_DESCRIPTOR Sd1,
193 IN PSECURITY_DESCRIPTOR Sd2)
194 {
195 ULONG Length1;
196 ULONG Length2;
197
198 Length1 = RtlLengthSecurityDescriptor(Sd1);
199 Length2 = RtlLengthSecurityDescriptor(Sd2);
200 if (Length1 != Length2)
201 return FALSE;
202
203 if (RtlCompareMemory(Sd1, Sd2, Length1) != Length1)
204 return FALSE;
205
206 return TRUE;
207 }
208
209
210 NTSTATUS
211 NTAPI
212 ObpAddSecurityDescriptor(IN PSECURITY_DESCRIPTOR SourceSD,
213 OUT PSECURITY_DESCRIPTOR *DestinationSD)
214 {
215 PSECURITY_DESCRIPTOR Sd;
216 PLIST_ENTRY CurrentEntry;
217 PSD_CACHE_ENTRY CacheEntry;
218 ULONG HashValue;
219 ULONG Index;
220 NTSTATUS Status;
221
222 DPRINT("ObpAddSecurityDescriptor() called\n");
223
224 HashValue = ObpHashSecurityDescriptor(SourceSD);
225 Index = HashValue & 0xFF;
226
227 ObpSdCacheLock();
228
229 if (!IsListEmpty(&ObpSdCache[Index]))
230 {
231 CurrentEntry = ObpSdCache[Index].Flink;
232 while (CurrentEntry != &ObpSdCache[Index])
233 {
234 CacheEntry = CONTAINING_RECORD(CurrentEntry,
235 SD_CACHE_ENTRY,
236 ListEntry);
237 Sd = (PSECURITY_DESCRIPTOR)(CacheEntry + 1);
238
239 if (CacheEntry->HashValue == HashValue &&
240 ObpCompareSecurityDescriptors(SourceSD, Sd))
241 {
242 CacheEntry->RefCount++;
243 DPRINT("RefCount %lu\n", CacheEntry->RefCount);
244 *DestinationSD = Sd;
245
246 ObpSdCacheUnlock();
247
248 DPRINT("ObpAddSecurityDescriptor() done\n");
249
250 return STATUS_SUCCESS;
251 }
252
253 CurrentEntry = CurrentEntry->Flink;
254 }
255 }
256
257 CacheEntry = ObpCreateCacheEntry(SourceSD,
258 HashValue,
259 Index,
260 DestinationSD);
261 if (CacheEntry == NULL)
262 {
263 DPRINT1("ObpCreateCacheEntry() failed\n");
264 Status = STATUS_INSUFFICIENT_RESOURCES;
265 }
266 else
267 {
268 DPRINT("RefCount 1\n");
269 InsertTailList(&ObpSdCache[Index], &CacheEntry->ListEntry);
270 Status = STATUS_SUCCESS;
271 }
272
273 ObpSdCacheUnlock();
274
275 DPRINT("ObpAddSecurityDescriptor() done\n");
276
277 return Status;
278 }
279
280
281 NTSTATUS
282 NTAPI
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 NTAPI
312 ObpReferenceCachedSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)
313 {
314 PSD_CACHE_ENTRY CacheEntry;
315
316 DPRINT("ObpReferenceCachedSecurityDescriptor() called\n");
317
318 ObpSdCacheLock();
319
320 CacheEntry = (PSD_CACHE_ENTRY)((ULONG_PTR)SecurityDescriptor - sizeof(SD_CACHE_ENTRY));
321
322 CacheEntry->RefCount++;
323 DPRINT("RefCount %lu\n", CacheEntry->RefCount);
324
325 ObpSdCacheUnlock();
326
327 DPRINT("ObpReferenceCachedSecurityDescriptor() done\n");
328 }
329
330
331 VOID
332 NTAPI
333 ObpDereferenceCachedSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)
334 {
335 DPRINT("ObpDereferenceCachedSecurityDescriptor() called\n");
336
337 ObpRemoveSecurityDescriptor(SecurityDescriptor);
338
339 DPRINT("ObpDereferenceCachedSecurityDescriptor() done\n");
340 }
341
342 /* EOF */