1 /* $Id: object.c,v 1.35 2001/05/01 11:06:24 ekohl Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ob/object.c
6 * PURPOSE: Implements generic object managment functions
7 * PROGRAMMER: David Welch (welch@cwcom.net)
12 /* INCLUDES *****************************************************************/
14 #include <ddk/ntddk.h>
15 #include <internal/ob.h>
16 #include <internal/ps.h>
17 #include <internal/id.h>
18 #include <internal/ke.h>
21 #include <internal/debug.h>
23 /* FUNCTIONS ************************************************************/
25 PVOID
HEADER_TO_BODY(POBJECT_HEADER obj
)
27 return(((void *)obj
)+sizeof(OBJECT_HEADER
)-sizeof(COMMON_BODY_HEADER
));
30 POBJECT_HEADER
BODY_TO_HEADER(PVOID body
)
32 PCOMMON_BODY_HEADER chdr
= (PCOMMON_BODY_HEADER
)body
;
33 return(CONTAINING_RECORD((&(chdr
->Type
)),OBJECT_HEADER
,Type
));
37 /**********************************************************************
47 VOID
ObInitializeObject(POBJECT_HEADER ObjectHeader
,
49 ACCESS_MASK DesiredAccess
,
51 POBJECT_ATTRIBUTES ObjectAttributes
)
53 ObjectHeader
->HandleCount
= 0;
54 ObjectHeader
->RefCount
= 1;
55 ObjectHeader
->ObjectType
= Type
;
56 if (ObjectAttributes
!= NULL
&&
57 ObjectAttributes
->Attributes
& OBJ_PERMANENT
)
59 ObjectHeader
->Permanent
= TRUE
;
63 ObjectHeader
->Permanent
= FALSE
;
65 RtlInitUnicodeString(&(ObjectHeader
->Name
),NULL
);
68 ObCreateHandle(PsGetCurrentProcess(),
69 HEADER_TO_BODY(ObjectHeader
),
77 /**********************************************************************
89 * Pointer to a unicode string that will contain the
90 * remaining path if the function returns successfully.
91 * The caller must free the buffer after use by calling
92 * RtlFreeUnicodeString ().
95 * Optional pointer to an object type. This is used to
96 * descide if a symbolic link object will be parsed or not.
100 NTSTATUS
ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes
,
101 PVOID
* ReturnedObject
,
102 PUNICODE_STRING RemainingPath
,
103 POBJECT_TYPE ObjectType
)
108 POBJECT_HEADER CurrentHeader
;
112 UNICODE_STRING PathString
;
114 DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, "
115 "RemainingPath %x)\n",ObjectAttributes
,ReturnedObject
,RemainingPath
);
116 DPRINT("ObjectAttributes->ObjectName->Buffer %x\n",
117 ObjectAttributes
->ObjectName
->Buffer
);
119 RtlInitUnicodeString (RemainingPath
, NULL
);
121 if (ObjectAttributes
->RootDirectory
== NULL
)
123 ObReferenceObjectByPointer(NameSpaceRoot
,
127 CurrentObject
= NameSpaceRoot
;
131 Status
= ObReferenceObjectByHandle(ObjectAttributes
->RootDirectory
,
137 if (!NT_SUCCESS(Status
))
143 Path
= ObjectAttributes
->ObjectName
->Buffer
;
147 *ReturnedObject
= CurrentObject
;
148 return(STATUS_SUCCESS
);
151 if ((ObjectAttributes
->RootDirectory
== NULL
) && (Path
[0] != '\\'))
153 ObDereferenceObject(CurrentObject
);
154 return(STATUS_UNSUCCESSFUL
);
159 RtlCreateUnicodeString (&PathString
, Path
);
160 current
= PathString
.Buffer
;
164 RtlInitUnicodeString (&PathString
, NULL
);
168 RootObject
= CurrentObject
;
172 DPRINT("current %S\n",current
);
173 CurrentHeader
= BODY_TO_HEADER(CurrentObject
);
174 if (CurrentHeader
->ObjectType
->Parse
== NULL
)
176 DPRINT("Current object can't parse\n");
179 Status
= CurrentHeader
->ObjectType
->Parse(CurrentObject
,
184 if (Status
== STATUS_REPARSE
)
186 /* reparse the object path */
187 NextObject
= RootObject
;
188 current
= PathString
.Buffer
;
190 ObReferenceObjectByPointer(NextObject
,
196 if (NextObject
== NULL
)
200 ObDereferenceObject(CurrentObject
);
201 CurrentObject
= NextObject
;
205 RtlCreateUnicodeString (RemainingPath
, current
);
206 RtlFreeUnicodeString (&PathString
);
207 *ReturnedObject
= CurrentObject
;
209 return(STATUS_SUCCESS
);
213 /**********************************************************************
224 ObCreateObject(PHANDLE Handle
,
225 ACCESS_MASK DesiredAccess
,
226 POBJECT_ATTRIBUTES ObjectAttributes
,
230 UNICODE_STRING RemainingPath
;
231 POBJECT_HEADER Header
;
234 assert_irql(APC_LEVEL
);
236 DPRINT("ObCreateObject(Handle %x, ObjectAttributes %x, Type %x)\n");
237 if (ObjectAttributes
!= NULL
&&
238 ObjectAttributes
->ObjectName
!= NULL
)
240 DPRINT("ObjectAttributes->ObjectName->Buffer %S\n",
241 ObjectAttributes
->ObjectName
->Buffer
);
244 if (ObjectAttributes
!= NULL
&&
245 ObjectAttributes
->ObjectName
!= NULL
)
247 Status
= ObFindObject(ObjectAttributes
,
251 if (!NT_SUCCESS(Status
))
253 DPRINT("ObFindObject() failed! (Status 0x%x)\n", Status
);
259 RtlInitUnicodeString (&RemainingPath
, NULL
);
262 RtlMapGenericMask(&DesiredAccess
,
265 Header
= (POBJECT_HEADER
)ExAllocatePoolWithTag(NonPagedPool
,
266 OBJECT_ALLOC_SIZE(Type
),
268 ObInitializeObject(Header
,
273 if ((Header
->ObjectType
!= NULL
) &&
274 (Header
->ObjectType
->Create
!= NULL
))
276 DPRINT("Calling %x\n", Header
->ObjectType
);
277 DPRINT("Calling %x\n", Header
->ObjectType
->Create
);
278 Status
= Header
->ObjectType
->Create(HEADER_TO_BODY(Header
),
280 RemainingPath
.Buffer
,
282 if (!NT_SUCCESS(Status
))
284 ObDereferenceObject( Parent
);
285 RtlFreeUnicodeString( &Header
->Name
);
286 RtlFreeUnicodeString( &RemainingPath
);
287 ExFreePool( Header
);
291 RtlFreeUnicodeString( &RemainingPath
);
292 return(HEADER_TO_BODY(Header
));
296 ObReferenceObjectByPointer(PVOID ObjectBody
,
297 ACCESS_MASK DesiredAccess
,
298 POBJECT_TYPE ObjectType
,
299 KPROCESSOR_MODE AccessMode
)
301 * FUNCTION: Increments the pointer reference count for a given object
303 * ObjectBody = Object's body
304 * DesiredAccess = Desired access to the object
305 * ObjectType = Points to the object type structure
306 * AccessMode = Type of access check to perform
310 POBJECT_HEADER ObjectHeader
;
312 // DPRINT("ObReferenceObjectByPointer(ObjectBody %x, ObjectType %x)\n",
313 // ObjectBody,ObjectType);
315 ObjectHeader
= BODY_TO_HEADER(ObjectBody
);
317 if (ObjectType
!= NULL
&& ObjectHeader
->ObjectType
!= ObjectType
)
319 DPRINT("Failed %x (type was %x %S) should %x\n",
321 ObjectHeader
->ObjectType
,
322 ObjectHeader
->ObjectType
->TypeName
.Buffer
,
325 return(STATUS_UNSUCCESSFUL
);
327 if (ObjectHeader
->ObjectType
== PsProcessType
)
329 DPRINT("Ref p 0x%x refcount %d type %x ",
330 ObjectBody
, ObjectHeader
->RefCount
, PsProcessType
);
331 DPRINT("eip %x\n", ((PULONG
)&ObjectBody
)[-1]);
333 if (ObjectHeader
->ObjectType
== PsThreadType
)
335 DPRINT("Deref t 0x%x with refcount %d type %x ",
336 ObjectBody
, ObjectHeader
->RefCount
, PsThreadType
);
337 DPRINT("eip %x\n", ((PULONG
)&ObjectBody
)[-1]);
340 ObjectHeader
->RefCount
++;
342 return(STATUS_SUCCESS
);
347 ObOpenObjectByPointer(IN POBJECT Object
,
348 IN ULONG HandleAttributes
,
349 IN PACCESS_STATE PassedAccessState
,
350 IN ACCESS_MASK DesiredAccess
,
351 IN POBJECT_TYPE ObjectType
,
352 IN KPROCESSOR_MODE AccessMode
,
357 DPRINT("ObOpenObjectByPointer()\n");
359 Status
= ObReferenceObjectByPointer(Object
,
363 if (!NT_SUCCESS(Status
))
368 Status
= ObCreateHandle(PsGetCurrentProcess(),
374 ObDereferenceObject(Object
);
376 return STATUS_SUCCESS
;
380 NTSTATUS
ObPerformRetentionChecks(POBJECT_HEADER Header
)
382 // DPRINT("ObPerformRetentionChecks(Header %x), RefCount %d, HandleCount %d\n",
383 // Header,Header->RefCount,Header->HandleCount);
385 if (Header
->RefCount
< 0)
387 DbgPrint("Object %x/%x has invalid reference count (%d)\n",
388 Header
, HEADER_TO_BODY(Header
), Header
->RefCount
);
391 if (Header
->HandleCount
< 0)
393 DbgPrint("Object %x/%x has invalid handle count (%d)\n",
394 Header
, HEADER_TO_BODY(Header
), Header
->HandleCount
);
398 if (Header
->RefCount
== 0 && Header
->HandleCount
== 0 &&
401 if (Header
->ObjectType
!= NULL
&&
402 Header
->ObjectType
->Delete
!= NULL
)
404 Header
->ObjectType
->Delete(HEADER_TO_BODY(Header
));
406 if (Header
->Name
.Buffer
!= NULL
)
408 ObRemoveEntry(Header
);
409 RtlFreeUnicodeString( &Header
->Name
);
411 DPRINT("ObPerformRetentionChecks() = Freeing object\n");
414 return(STATUS_SUCCESS
);
417 ULONG
ObGetReferenceCount(PVOID ObjectBody
)
419 POBJECT_HEADER Header
= BODY_TO_HEADER(ObjectBody
);
421 return(Header
->RefCount
);
424 ULONG
ObGetHandleCount(PVOID ObjectBody
)
426 POBJECT_HEADER Header
= BODY_TO_HEADER(ObjectBody
);
428 return(Header
->HandleCount
);
432 /**********************************************************************
434 * @ObfReferenceObject@0
437 * Increments a given object's reference count and performs
442 * Body of the object.
445 * The current value of the reference counter.
447 ULONG FASTCALL
ObfReferenceObject(PVOID ObjectBody
)
449 POBJECT_HEADER Header
= BODY_TO_HEADER(ObjectBody
);
450 ULONG ReferenceCount
;
452 ReferenceCount
= Header
->RefCount
++;
454 ObPerformRetentionChecks (Header
);
456 return(ReferenceCount
);
460 VOID FASTCALL
ObfDereferenceObject (PVOID ObjectBody
)
462 * FUNCTION: Decrements a given object's reference count and performs
465 * ObjectBody = Body of the object
468 POBJECT_HEADER Header
= BODY_TO_HEADER(ObjectBody
);
469 extern POBJECT_TYPE PsProcessType
;
471 // DPRINT("ObDeferenceObject(ObjectBody %x) RefCount %d\n",ObjectBody,
472 // Header->RefCount);
474 if (Header
->ObjectType
== PsProcessType
)
476 DPRINT("Deref p 0x%x with refcount %d type %x ",
477 ObjectBody
, Header
->RefCount
, PsProcessType
);
478 DPRINT("eip %x\n", ((PULONG
)&ObjectBody
)[-1]);
480 if (Header
->ObjectType
== PsThreadType
)
482 DPRINT("Deref t 0x%x with refcount %d type %x ",
483 ObjectBody
, Header
->RefCount
, PsThreadType
);
484 DPRINT("eip %x\n", ((PULONG
)&ObjectBody
)[-1]);
489 ObPerformRetentionChecks(Header
);
493 VOID STDCALL
ObDereferenceObject (PVOID ObjectBody
)
495 POBJECT_HEADER Header
= BODY_TO_HEADER(ObjectBody
);
496 extern POBJECT_TYPE PsProcessType
;
498 if (Header
->ObjectType
== PsProcessType
)
500 DPRINT("Deref p 0x%x with refcount %d type %x ",
501 ObjectBody
, Header
->RefCount
, PsProcessType
);
502 DPRINT("eip %x\n", ((PULONG
)&ObjectBody
)[-1]);
505 ObfDereferenceObject (ObjectBody
);