2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/include/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 ObpSelectObjectLockSlot(IN POBJECT_HEADER ObjectHeader
)
24 /* We have 4 locks total, this will return a 0-index slot */
25 return (((ULONG_PTR
)ObjectHeader
) >> 8) & 3;
30 ObpAcquireObjectLock(IN POBJECT_HEADER ObjectHeader
)
33 POBJECT_TYPE ObjectType
= ObjectHeader
->Type
;
36 ASSERT(KeGetCurrentIrql() <= APC_LEVEL
);
39 Slot
= ObpSelectObjectLockSlot(ObjectHeader
);
41 /* Enter a critical region and acquire the resource */
42 KeEnterCriticalRegion();
43 ExAcquireResourceExclusiveLite(&ObjectType
->ObjectLocks
[Slot
], TRUE
);
48 ObpAcquireObjectLockShared(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 ExAcquireResourceSharedLite(&ObjectType
->ObjectLocks
[Slot
], TRUE
);
66 ObpReleaseObjectLock(IN POBJECT_HEADER ObjectHeader
)
69 POBJECT_TYPE ObjectType
= ObjectHeader
->Type
;
72 Slot
= ObpSelectObjectLockSlot(ObjectHeader
);
74 /* Release the resource and leave a critical region */
75 ExReleaseResourceLite(&ObjectType
->ObjectLocks
[Slot
]);
76 KeLeaveCriticalRegion();
79 ASSERT(KeGetCurrentIrql() <= APC_LEVEL
);
83 POBJECT_HEADER_NAME_INFO
84 ObpReferenceNameInfo(IN POBJECT_HEADER ObjectHeader
)
86 POBJECT_HEADER_NAME_INFO ObjectNameInfo
;
87 ULONG NewValue
, References
;
89 /* Make sure we have name information at all */
90 ObjectNameInfo
= OBJECT_HEADER_TO_NAME_INFO(ObjectHeader
);
91 if (!ObjectNameInfo
) return NULL
;
93 /* Get the number of references */
94 References
= ObjectNameInfo
->QueryReferences
;
97 /* Check if the count is 0 and fail if so */
98 if (!References
) return NULL
;
100 /* Increment the number of references */
101 NewValue
= InterlockedCompareExchange((PLONG
)&ObjectNameInfo
->
105 if (NewValue
== References
) break;
107 /* We failed, try again */
108 References
= NewValue
;
111 /* Check for magic flag */
112 if (ObjectNameInfo
->QueryReferences
& 0x80000000)
114 /* FIXME: Unhandled*/
115 DbgPrint("OB: Unhandled path\n");
119 /* Return the name information */
120 return ObjectNameInfo
;
125 ObpDereferenceNameInfo(IN POBJECT_HEADER_NAME_INFO HeaderNameInfo
)
127 POBJECT_DIRECTORY Directory
;
129 /* Bail out if there's no info at all */
130 if (!HeaderNameInfo
) return;
132 /* Remove a query reference and check if it was the last one */
133 if (!InterlockedDecrement((PLONG
)&HeaderNameInfo
->QueryReferences
))
135 /* Check if we have a name */
136 if (HeaderNameInfo
->Name
.Buffer
)
138 /* We can get rid of the object name now */
139 ExFreePool(HeaderNameInfo
->Name
.Buffer
);
140 RtlInitEmptyUnicodeString(&HeaderNameInfo
->Name
, NULL
, 0);
143 /* Check if the object has a directory associated to it */
144 Directory
= HeaderNameInfo
->Directory
;
147 /* Delete the directory */
148 HeaderNameInfo
->Directory
= NULL
;
149 ObDereferenceObjectDeferDelete(Directory
);
156 ObpAcquireDirectoryLockShared(IN POBJECT_DIRECTORY Directory
,
157 IN POBP_LOOKUP_CONTEXT Context
)
159 /* It's not, set lock flag */
160 Context
->LockStateSignature
= OBP_LOCK_STATE_PRE_ACQUISITION_SHARED
;
163 KeEnterCriticalRegion();
164 ExAcquirePushLockShared(&Directory
->Lock
);
166 /* Update lock flag */
167 Context
->LockStateSignature
= OBP_LOCK_STATE_POST_ACQUISITION_SHARED
;
172 ObpAcquireDirectoryLockExclusive(IN POBJECT_DIRECTORY Directory
,
173 IN POBP_LOOKUP_CONTEXT Context
)
175 /* Update lock flag */
176 Context
->LockStateSignature
= OBP_LOCK_STATE_PRE_ACQUISITION_EXCLUSIVE
;
178 /* Acquire an exclusive directory lock */
179 KeEnterCriticalRegion();
180 ExAcquirePushLockExclusive(&Directory
->Lock
);
182 /* Set the directory */
183 Context
->Directory
= Directory
;
185 /* Update lock settings */
186 Context
->LockStateSignature
= OBP_LOCK_STATE_POST_ACQUISITION_EXCLUSIVE
;
187 Context
->DirectoryLocked
= TRUE
;
192 ObpReleaseDirectoryLock(IN POBJECT_DIRECTORY Directory
,
193 IN POBP_LOOKUP_CONTEXT Context
)
195 /* Release the lock */
196 ExReleasePushLock(&Directory
->Lock
);
197 Context
->LockStateSignature
= OBP_LOCK_STATE_RELEASED
;
198 KeLeaveCriticalRegion();
203 ObpInitializeLookupContext(IN POBP_LOOKUP_CONTEXT Context
)
205 /* Initialize a null context */
206 Context
->Object
= NULL
;
207 Context
->Directory
= NULL
;
208 Context
->DirectoryLocked
= FALSE
;
209 Context
->LockStateSignature
= OBP_LOCK_STATE_INITIALIZED
;
214 ObpReleaseLookupContextObject(IN POBP_LOOKUP_CONTEXT Context
)
216 POBJECT_HEADER ObjectHeader
;
217 POBJECT_HEADER_NAME_INFO HeaderNameInfo
;
219 /* Check if we had found an object */
222 /* Get the object name information */
223 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Context
->Object
);
224 HeaderNameInfo
= OBJECT_HEADER_TO_NAME_INFO(ObjectHeader
);
226 /* release the name information */
227 ObpDereferenceNameInfo(HeaderNameInfo
);
229 /* Dereference the object */
230 ObDereferenceObject(Context
->Object
);
231 Context
->Object
= NULL
;
237 ObpReleaseLookupContext(IN POBP_LOOKUP_CONTEXT Context
)
239 /* Check if we came back with the directory locked */
240 if (Context
->DirectoryLocked
)
242 /* Release the lock */
243 ObpReleaseDirectoryLock(Context
->Directory
, Context
);
244 Context
->Directory
= NULL
;
245 Context
->DirectoryLocked
= FALSE
;
248 /* Clear the context */
249 ObpReleaseLookupContextObject(Context
);
254 ObpEnterObjectTypeMutex(IN POBJECT_TYPE ObjectType
)
257 ASSERT(KeGetCurrentIrql() <= APC_LEVEL
);
259 /* Enter a critical region and acquire the resource */
260 KeEnterCriticalRegion();
261 ExAcquireResourceExclusiveLite(&ObjectType
->Mutex
, TRUE
);
266 ObpLeaveObjectTypeMutex(IN POBJECT_TYPE ObjectType
)
268 /* Enter a critical region and acquire the resource */
269 ExReleaseResourceLite(&ObjectType
->Mutex
);
270 KeLeaveCriticalRegion();
273 ASSERT(KeGetCurrentIrql() <= APC_LEVEL
);
278 ObpReleaseObjectCreateInformation(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo
)
280 /* Check if we have a security descriptor */
281 if (ObjectCreateInfo
->SecurityDescriptor
)
284 SeReleaseSecurityDescriptor(ObjectCreateInfo
->SecurityDescriptor
,
285 ObjectCreateInfo
->ProbeMode
,
287 ObjectCreateInfo
->SecurityDescriptor
= NULL
;
293 ObpAllocateObjectCreateInfoBuffer(IN PP_NPAGED_LOOKASIDE_NUMBER Type
)
296 PNPAGED_LOOKASIDE_LIST List
;
297 PKPRCB Prcb
= KeGetCurrentPrcb();
299 /* Get the P list first */
300 List
= (PNPAGED_LOOKASIDE_LIST
)Prcb
->PPLookasideList
[Type
].P
;
302 /* Attempt allocation */
303 List
->L
.TotalAllocates
++;
304 Buffer
= (PVOID
)InterlockedPopEntrySList(&List
->L
.ListHead
);
307 /* Let the balancer know that the P list failed */
308 List
->L
.AllocateMisses
++;
311 List
= (PNPAGED_LOOKASIDE_LIST
)Prcb
->PPLookasideList
[Type
].L
;
312 List
->L
.TotalAllocates
++;
313 Buffer
= (PVOID
)InterlockedPopEntrySList(&List
->L
.ListHead
);
316 /* Let the balancer know the L list failed too */
317 List
->L
.AllocateMisses
++;
320 Buffer
= List
->L
.Allocate(List
->L
.Type
, List
->L
.Size
, List
->L
.Tag
);
330 ObpFreeCapturedAttributes(IN PVOID Buffer
,
331 IN PP_NPAGED_LOOKASIDE_NUMBER Type
)
333 PNPAGED_LOOKASIDE_LIST List
;
334 PKPRCB Prcb
= KeGetCurrentPrcb();
337 List
= (PNPAGED_LOOKASIDE_LIST
)Prcb
->PPLookasideList
[Type
].P
;
338 List
->L
.TotalFrees
++;
340 /* Check if the Free was within the Depth or not */
341 if (ExQueryDepthSList(&List
->L
.ListHead
) >= List
->L
.Depth
)
343 /* Let the balancer know */
344 List
->L
.FreeMisses
++;
347 List
= (PNPAGED_LOOKASIDE_LIST
)Prcb
->PPLookasideList
[Type
].L
;
348 List
->L
.TotalFrees
++;
350 /* Check if the Free was within the Depth or not */
351 if (ExQueryDepthSList(&List
->L
.ListHead
) >= List
->L
.Depth
)
353 /* All lists failed, use the pool */
354 List
->L
.FreeMisses
++;
355 List
->L
.Free(Buffer
);
359 /* The free was within the Depth */
360 InterlockedPushEntrySList(&List
->L
.ListHead
,
361 (PSINGLE_LIST_ENTRY
)Buffer
);
366 /* The free was within the Depth */
367 InterlockedPushEntrySList(&List
->L
.ListHead
,
368 (PSINGLE_LIST_ENTRY
)Buffer
);
374 ObpFreeObjectCreateInformation(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo
)
376 /* First release the attributes, then free them from the lookaside list */
377 ObpReleaseObjectCreateInformation(ObjectCreateInfo
);
378 ObpFreeCapturedAttributes(ObjectCreateInfo
, LookasideCreateInfoList
);
384 ObpCalloutStart(IN PKIRQL CalloutIrql
)
386 /* Save the callout IRQL */
387 *CalloutIrql
= KeGetCurrentIrql();
392 ObpCalloutEnd(IN KIRQL CalloutIrql
,
394 IN POBJECT_TYPE ObjectType
,
397 /* Detect IRQL change */
398 if (CalloutIrql
!= KeGetCurrentIrql())
401 DbgPrint("OB: ObjectType: %wZ Procedure: %s Object: %08x\n",
402 &ObjectType
->Name
, Procedure
, Object
);
403 DbgPrint(" Returned at %x IRQL, but was called at %x IRQL\n",
404 KeGetCurrentIrql(), CalloutIrql
);
411 ObpCalloutStart(IN PKIRQL CalloutIrql
)
414 UNREFERENCED_PARAMETER(CalloutIrql
);
419 ObpCalloutEnd(IN KIRQL CalloutIrql
,
421 IN POBJECT_TYPE ObjectType
,
424 UNREFERENCED_PARAMETER(CalloutIrql
);