2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/include/internal/ob_x.h
5 * PURPOSE: Intenral Inlined Functions for the Object Manager
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
11 #define OBP_LOCK_STATE_PRE_ACQUISITION_EXCLUSIVE 0xAAAA1234
12 #define OBP_LOCK_STATE_PRE_ACQUISITION_SHARED 0xBBBB1234
13 #define OBP_LOCK_STATE_POST_ACQUISITION_EXCLUSIVE 0xCCCC1234
14 #define OBP_LOCK_STATE_POST_ACQUISITION_SHARED 0xDDDD1234
15 #define OBP_LOCK_STATE_RELEASED 0xEEEE1234
16 #define OBP_LOCK_STATE_INITIALIZED 0xFFFF1234
18 #define OBP_NAME_LOOKASIDE_MAX_SIZE 248
22 ObpValidateAttributes(IN ULONG Attributes
,
23 IN KPROCESSOR_MODE PreviousMode
)
25 if (PreviousMode
== KernelMode
)
27 /* For kernel, allow any valid attributes */
28 return Attributes
& OBJ_VALID_KERNEL_ATTRIBUTES
;
32 /* For user, mask out kernel-only attributes */
33 return (Attributes
& OBJ_VALID_ATTRIBUTES
) &
40 ObpSelectObjectLockSlot(IN POBJECT_HEADER ObjectHeader
)
42 /* We have 4 locks total, this will return a 0-index slot */
43 return (((ULONG_PTR
)ObjectHeader
) >> 8) & 3;
48 ObpAcquireObjectLock(IN POBJECT_HEADER ObjectHeader
)
51 POBJECT_TYPE ObjectType
= ObjectHeader
->Type
;
54 ASSERT(KeGetCurrentIrql() <= APC_LEVEL
);
57 Slot
= ObpSelectObjectLockSlot(ObjectHeader
);
59 /* Enter a critical region and acquire the resource */
60 KeEnterCriticalRegion();
61 ExAcquireResourceExclusiveLite(&ObjectType
->ObjectLocks
[Slot
], TRUE
);
66 ObpAcquireObjectLockShared(IN POBJECT_HEADER ObjectHeader
)
69 POBJECT_TYPE ObjectType
= ObjectHeader
->Type
;
72 ASSERT(KeGetCurrentIrql() <= APC_LEVEL
);
75 Slot
= ObpSelectObjectLockSlot(ObjectHeader
);
77 /* Enter a critical region and acquire the resource */
78 KeEnterCriticalRegion();
79 ExAcquireResourceSharedLite(&ObjectType
->ObjectLocks
[Slot
], TRUE
);
84 ObpReleaseObjectLock(IN POBJECT_HEADER ObjectHeader
)
87 POBJECT_TYPE ObjectType
= ObjectHeader
->Type
;
90 Slot
= ObpSelectObjectLockSlot(ObjectHeader
);
92 /* Release the resource and leave a critical region */
93 ExReleaseResourceLite(&ObjectType
->ObjectLocks
[Slot
]);
94 KeLeaveCriticalRegion();
97 ASSERT(KeGetCurrentIrql() <= APC_LEVEL
);
101 POBJECT_HEADER_NAME_INFO
102 ObpReferenceNameInfo(IN POBJECT_HEADER ObjectHeader
)
104 POBJECT_HEADER_NAME_INFO ObjectNameInfo
;
105 ULONG NewValue
, References
;
107 /* Make sure we have name information at all */
108 ObjectNameInfo
= OBJECT_HEADER_TO_NAME_INFO(ObjectHeader
);
109 if (!ObjectNameInfo
) return NULL
;
111 /* Get the number of references */
112 References
= ObjectNameInfo
->QueryReferences
;
115 /* Check if the count is 0 and fail if so */
116 if (!References
) return NULL
;
118 /* Increment the number of references */
119 NewValue
= InterlockedCompareExchange((PLONG
)&ObjectNameInfo
->
123 if (NewValue
== References
) break;
125 /* We failed, try again */
126 References
= NewValue
;
129 /* Check for magic flag */
130 if (ObjectNameInfo
->QueryReferences
& 0x80000000)
132 /* FIXME: Unhandled*/
133 DbgPrint("OB: Unhandled path\n");
137 /* Return the name information */
138 return ObjectNameInfo
;
143 ObpDereferenceNameInfo(IN POBJECT_HEADER_NAME_INFO HeaderNameInfo
)
145 POBJECT_DIRECTORY Directory
;
147 /* Bail out if there's no info at all */
148 if (!HeaderNameInfo
) return;
150 /* Remove a query reference and check if it was the last one */
151 if (!InterlockedDecrement((PLONG
)&HeaderNameInfo
->QueryReferences
))
153 /* Check if we have a name */
154 if (HeaderNameInfo
->Name
.Buffer
)
156 /* We can get rid of the object name now */
157 ExFreePoolWithTag(HeaderNameInfo
->Name
.Buffer
, OB_NAME_TAG
);
158 RtlInitEmptyUnicodeString(&HeaderNameInfo
->Name
, NULL
, 0);
161 /* Check if the object has a directory associated to it */
162 Directory
= HeaderNameInfo
->Directory
;
165 /* Delete the directory */
166 HeaderNameInfo
->Directory
= NULL
;
167 ObDereferenceObjectDeferDelete(Directory
);
174 ObpAcquireDirectoryLockShared(IN POBJECT_DIRECTORY Directory
,
175 IN POBP_LOOKUP_CONTEXT Context
)
177 /* It's not, set lock flag */
178 Context
->LockStateSignature
= OBP_LOCK_STATE_PRE_ACQUISITION_SHARED
;
181 KeEnterCriticalRegion();
182 ExAcquirePushLockShared(&Directory
->Lock
);
184 /* Update lock flag */
185 Context
->LockStateSignature
= OBP_LOCK_STATE_POST_ACQUISITION_SHARED
;
190 ObpAcquireDirectoryLockExclusive(IN POBJECT_DIRECTORY Directory
,
191 IN POBP_LOOKUP_CONTEXT Context
)
193 /* Update lock flag */
194 Context
->LockStateSignature
= OBP_LOCK_STATE_PRE_ACQUISITION_EXCLUSIVE
;
196 /* Acquire an exclusive directory lock */
197 KeEnterCriticalRegion();
198 ExAcquirePushLockExclusive(&Directory
->Lock
);
200 /* Set the directory */
201 Context
->Directory
= Directory
;
203 /* Update lock settings */
204 Context
->LockStateSignature
= OBP_LOCK_STATE_POST_ACQUISITION_EXCLUSIVE
;
205 Context
->DirectoryLocked
= TRUE
;
210 ObpReleaseDirectoryLock(IN POBJECT_DIRECTORY Directory
,
211 IN POBP_LOOKUP_CONTEXT Context
)
213 /* Release the lock */
214 ExReleasePushLock(&Directory
->Lock
);
215 Context
->LockStateSignature
= OBP_LOCK_STATE_RELEASED
;
216 KeLeaveCriticalRegion();
221 ObpInitializeLookupContext(IN POBP_LOOKUP_CONTEXT Context
)
223 /* Initialize a null context */
224 Context
->Object
= NULL
;
225 Context
->Directory
= NULL
;
226 Context
->DirectoryLocked
= FALSE
;
227 Context
->LockStateSignature
= OBP_LOCK_STATE_INITIALIZED
;
232 ObpReleaseLookupContextObject(IN POBP_LOOKUP_CONTEXT Context
)
234 POBJECT_HEADER ObjectHeader
;
235 POBJECT_HEADER_NAME_INFO HeaderNameInfo
;
237 /* Check if we had found an object */
240 /* Get the object name information */
241 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Context
->Object
);
242 HeaderNameInfo
= OBJECT_HEADER_TO_NAME_INFO(ObjectHeader
);
244 /* release the name information */
245 ObpDereferenceNameInfo(HeaderNameInfo
);
247 /* Dereference the object */
248 ObDereferenceObject(Context
->Object
);
249 Context
->Object
= NULL
;
255 ObpReleaseLookupContext(IN POBP_LOOKUP_CONTEXT Context
)
257 /* Check if we came back with the directory locked */
258 if (Context
->DirectoryLocked
)
260 /* Release the lock */
261 ObpReleaseDirectoryLock(Context
->Directory
, Context
);
262 Context
->Directory
= NULL
;
263 Context
->DirectoryLocked
= FALSE
;
266 /* Clear the context */
267 ObpReleaseLookupContextObject(Context
);
272 ObpEnterObjectTypeMutex(IN POBJECT_TYPE ObjectType
)
275 ASSERT(KeGetCurrentIrql() <= APC_LEVEL
);
277 /* Enter a critical region and acquire the resource */
278 KeEnterCriticalRegion();
279 ExAcquireResourceExclusiveLite(&ObjectType
->Mutex
, TRUE
);
284 ObpLeaveObjectTypeMutex(IN POBJECT_TYPE ObjectType
)
286 /* Enter a critical region and acquire the resource */
287 ExReleaseResourceLite(&ObjectType
->Mutex
);
288 KeLeaveCriticalRegion();
291 ASSERT(KeGetCurrentIrql() <= APC_LEVEL
);
296 ObpReleaseObjectCreateInformation(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo
)
298 /* Check if we have a security descriptor */
299 if (ObjectCreateInfo
->SecurityDescriptor
)
302 SeReleaseSecurityDescriptor(ObjectCreateInfo
->SecurityDescriptor
,
303 ObjectCreateInfo
->ProbeMode
,
305 ObjectCreateInfo
->SecurityDescriptor
= NULL
;
311 ObpAllocateObjectCreateInfoBuffer(IN PP_NPAGED_LOOKASIDE_NUMBER Type
)
314 PNPAGED_LOOKASIDE_LIST List
;
315 PKPRCB Prcb
= KeGetCurrentPrcb();
317 /* Get the P list first */
318 List
= (PNPAGED_LOOKASIDE_LIST
)Prcb
->PPLookasideList
[Type
].P
;
320 /* Attempt allocation */
321 List
->L
.TotalAllocates
++;
322 Buffer
= (PVOID
)InterlockedPopEntrySList(&List
->L
.ListHead
);
325 /* Let the balancer know that the P list failed */
326 List
->L
.AllocateMisses
++;
329 List
= (PNPAGED_LOOKASIDE_LIST
)Prcb
->PPLookasideList
[Type
].L
;
330 List
->L
.TotalAllocates
++;
331 Buffer
= (PVOID
)InterlockedPopEntrySList(&List
->L
.ListHead
);
334 /* Let the balancer know the L list failed too */
335 List
->L
.AllocateMisses
++;
338 Buffer
= List
->L
.Allocate(List
->L
.Type
, List
->L
.Size
, List
->L
.Tag
);
348 ObpFreeCapturedAttributes(IN PVOID Buffer
,
349 IN PP_NPAGED_LOOKASIDE_NUMBER Type
)
351 PNPAGED_LOOKASIDE_LIST List
;
352 PKPRCB Prcb
= KeGetCurrentPrcb();
355 List
= (PNPAGED_LOOKASIDE_LIST
)Prcb
->PPLookasideList
[Type
].P
;
356 List
->L
.TotalFrees
++;
358 /* Check if the Free was within the Depth or not */
359 if (ExQueryDepthSList(&List
->L
.ListHead
) >= List
->L
.Depth
)
361 /* Let the balancer know */
362 List
->L
.FreeMisses
++;
365 List
= (PNPAGED_LOOKASIDE_LIST
)Prcb
->PPLookasideList
[Type
].L
;
366 List
->L
.TotalFrees
++;
368 /* Check if the Free was within the Depth or not */
369 if (ExQueryDepthSList(&List
->L
.ListHead
) >= List
->L
.Depth
)
371 /* All lists failed, use the pool */
372 List
->L
.FreeMisses
++;
373 List
->L
.Free(Buffer
);
377 /* The free was within the Depth */
378 InterlockedPushEntrySList(&List
->L
.ListHead
,
379 (PSLIST_ENTRY
)Buffer
);
384 /* The free was within the Depth */
385 InterlockedPushEntrySList(&List
->L
.ListHead
,
386 (PSLIST_ENTRY
)Buffer
);
392 ObpFreeObjectCreateInformation(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo
)
394 /* First release the attributes, then free them from the lookaside list */
395 ObpReleaseObjectCreateInformation(ObjectCreateInfo
);
396 ObpFreeCapturedAttributes(ObjectCreateInfo
, LookasideCreateInfoList
);
402 ObpCalloutStart(IN PKIRQL CalloutIrql
)
404 /* Save the callout IRQL */
405 *CalloutIrql
= KeGetCurrentIrql();
410 ObpCalloutEnd(IN KIRQL CalloutIrql
,
412 IN POBJECT_TYPE ObjectType
,
415 /* Detect IRQL change */
416 if (CalloutIrql
!= KeGetCurrentIrql())
419 DbgPrint("OB: ObjectType: %wZ Procedure: %s Object: %p\n",
420 &ObjectType
->Name
, Procedure
, Object
);
421 DbgPrint(" Returned at %x IRQL, but was called at %x IRQL\n",
422 KeGetCurrentIrql(), CalloutIrql
);
429 ObpCalloutStart(IN PKIRQL CalloutIrql
)
432 UNREFERENCED_PARAMETER(CalloutIrql
);
437 ObpCalloutEnd(IN KIRQL CalloutIrql
,
439 IN POBJECT_TYPE ObjectType
,
442 UNREFERENCED_PARAMETER(CalloutIrql
);