1 /* $Id: object.c,v 1.38 2001/06/12 17:50:27 chorns 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/config.h>
16 #include <internal/ob.h>
17 #include <internal/ps.h>
18 #include <internal/id.h>
19 #include <internal/ke.h>
22 #include <internal/debug.h>
24 /* FUNCTIONS ************************************************************/
26 PVOID
HEADER_TO_BODY(POBJECT_HEADER obj
)
28 return(((void *)obj
)+sizeof(OBJECT_HEADER
)-sizeof(COMMON_BODY_HEADER
));
31 POBJECT_HEADER
BODY_TO_HEADER(PVOID body
)
33 PCOMMON_BODY_HEADER chdr
= (PCOMMON_BODY_HEADER
)body
;
34 return(CONTAINING_RECORD((&(chdr
->Type
)),OBJECT_HEADER
,Type
));
38 /**********************************************************************
48 VOID
ObInitializeObject(POBJECT_HEADER ObjectHeader
,
50 ACCESS_MASK DesiredAccess
,
52 POBJECT_ATTRIBUTES ObjectAttributes
)
54 ObjectHeader
->HandleCount
= 0;
55 ObjectHeader
->RefCount
= 1;
56 ObjectHeader
->ObjectType
= Type
;
57 if (ObjectAttributes
!= NULL
&&
58 ObjectAttributes
->Attributes
& OBJ_PERMANENT
)
60 ObjectHeader
->Permanent
= TRUE
;
64 ObjectHeader
->Permanent
= FALSE
;
66 RtlInitUnicodeString(&(ObjectHeader
->Name
),NULL
);
69 ObCreateHandle(PsGetCurrentProcess(),
70 HEADER_TO_BODY(ObjectHeader
),
78 /**********************************************************************
90 * Pointer to a unicode string that will contain the
91 * remaining path if the function returns successfully.
92 * The caller must free the buffer after use by calling
93 * RtlFreeUnicodeString ().
96 * Optional pointer to an object type. This is used to
97 * descide if a symbolic link object will be parsed or not.
101 NTSTATUS
ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes
,
102 PVOID
* ReturnedObject
,
103 PUNICODE_STRING RemainingPath
,
104 POBJECT_TYPE ObjectType
)
109 POBJECT_HEADER CurrentHeader
;
113 UNICODE_STRING PathString
;
115 DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, "
116 "RemainingPath %x)\n",ObjectAttributes
,ReturnedObject
,RemainingPath
);
117 DPRINT("ObjectAttributes->ObjectName %wZ\n",
118 ObjectAttributes
->ObjectName
);
120 RtlInitUnicodeString (RemainingPath
, NULL
);
122 if (ObjectAttributes
->RootDirectory
== NULL
)
124 ObReferenceObjectByPointer(NameSpaceRoot
,
128 CurrentObject
= NameSpaceRoot
;
132 Status
= ObReferenceObjectByHandle(ObjectAttributes
->RootDirectory
,
138 if (!NT_SUCCESS(Status
))
144 Path
= ObjectAttributes
->ObjectName
->Buffer
;
148 *ReturnedObject
= CurrentObject
;
149 return(STATUS_SUCCESS
);
152 if ((ObjectAttributes
->RootDirectory
== NULL
) && (Path
[0] != '\\'))
154 ObDereferenceObject(CurrentObject
);
155 return(STATUS_UNSUCCESSFUL
);
160 RtlCreateUnicodeString (&PathString
, Path
);
161 current
= PathString
.Buffer
;
165 RtlInitUnicodeString (&PathString
, NULL
);
169 RootObject
= CurrentObject
;
173 DPRINT("current %S\n",current
);
174 CurrentHeader
= BODY_TO_HEADER(CurrentObject
);
176 DPRINT("Current ObjectType %wZ\n",
177 &CurrentHeader
->ObjectType
->TypeName
);
179 if (CurrentHeader
->ObjectType
->Parse
== NULL
)
181 DPRINT("Current object can't parse\n");
184 Status
= CurrentHeader
->ObjectType
->Parse(CurrentObject
,
189 ObjectAttributes
->Attributes
);
190 if (Status
== STATUS_REPARSE
)
192 /* reparse the object path */
193 NextObject
= RootObject
;
194 current
= PathString
.Buffer
;
196 ObReferenceObjectByPointer(NextObject
,
202 if (NextObject
== NULL
)
206 ObDereferenceObject(CurrentObject
);
207 CurrentObject
= NextObject
;
211 RtlCreateUnicodeString (RemainingPath
, current
);
212 RtlFreeUnicodeString (&PathString
);
213 *ReturnedObject
= CurrentObject
;
215 return(STATUS_SUCCESS
);
219 /**********************************************************************
230 ObCreateObject(PHANDLE Handle
,
231 ACCESS_MASK DesiredAccess
,
232 POBJECT_ATTRIBUTES ObjectAttributes
,
236 UNICODE_STRING RemainingPath
;
237 POBJECT_HEADER Header
;
240 assert_irql(APC_LEVEL
);
242 DPRINT("ObCreateObject(Handle %x, ObjectAttributes %x, Type %x)\n");
243 if (ObjectAttributes
!= NULL
&&
244 ObjectAttributes
->ObjectName
!= NULL
)
246 DPRINT("ObjectAttributes->ObjectName->Buffer %S\n",
247 ObjectAttributes
->ObjectName
->Buffer
);
250 if (ObjectAttributes
!= NULL
&&
251 ObjectAttributes
->ObjectName
!= NULL
)
253 Status
= ObFindObject(ObjectAttributes
,
257 if (!NT_SUCCESS(Status
))
259 DPRINT("ObFindObject() failed! (Status 0x%x)\n", Status
);
265 RtlInitUnicodeString (&RemainingPath
, NULL
);
268 RtlMapGenericMask(&DesiredAccess
,
271 Header
= (POBJECT_HEADER
)ExAllocatePoolWithTag(NonPagedPool
,
272 OBJECT_ALLOC_SIZE(Type
),
274 ObInitializeObject(Header
,
279 if ((Header
->ObjectType
!= NULL
) &&
280 (Header
->ObjectType
->Create
!= NULL
))
282 DPRINT("Calling %x\n", Header
->ObjectType
->Create
);
283 Status
= Header
->ObjectType
->Create(HEADER_TO_BODY(Header
),
285 RemainingPath
.Buffer
,
287 if (!NT_SUCCESS(Status
))
291 ObDereferenceObject( Parent
);
293 RtlFreeUnicodeString( &Header
->Name
);
294 RtlFreeUnicodeString( &RemainingPath
);
295 ExFreePool( Header
);
299 RtlFreeUnicodeString( &RemainingPath
);
300 return(HEADER_TO_BODY(Header
));
304 ObReferenceObjectByPointer(PVOID ObjectBody
,
305 ACCESS_MASK DesiredAccess
,
306 POBJECT_TYPE ObjectType
,
307 KPROCESSOR_MODE AccessMode
)
309 * FUNCTION: Increments the pointer reference count for a given object
311 * ObjectBody = Object's body
312 * DesiredAccess = Desired access to the object
313 * ObjectType = Points to the object type structure
314 * AccessMode = Type of access check to perform
318 POBJECT_HEADER ObjectHeader
;
320 // DPRINT("ObReferenceObjectByPointer(ObjectBody %x, ObjectType %x)\n",
321 // ObjectBody,ObjectType);
323 ObjectHeader
= BODY_TO_HEADER(ObjectBody
);
325 if (ObjectType
!= NULL
&& ObjectHeader
->ObjectType
!= ObjectType
)
327 DPRINT("Failed %x (type was %x %S) should be %x %S\n",
329 ObjectHeader
->ObjectType
,
330 ObjectHeader
->ObjectType
->TypeName
.Buffer
,
332 ObjectType
->TypeName
.Buffer
);
333 return(STATUS_UNSUCCESSFUL
);
335 if (ObjectHeader
->ObjectType
== PsProcessType
)
337 DPRINT("Ref p 0x%x refcount %d type %x ",
338 ObjectBody
, ObjectHeader
->RefCount
, PsProcessType
);
339 DPRINT("eip %x\n", ((PULONG
)&ObjectBody
)[-1]);
341 if (ObjectHeader
->ObjectType
== PsThreadType
)
343 DPRINT("Deref t 0x%x with refcount %d type %x ",
344 ObjectBody
, ObjectHeader
->RefCount
, PsThreadType
);
345 DPRINT("eip %x\n", ((PULONG
)&ObjectBody
)[-1]);
348 ObjectHeader
->RefCount
++;
350 return(STATUS_SUCCESS
);
355 ObOpenObjectByPointer(IN POBJECT Object
,
356 IN ULONG HandleAttributes
,
357 IN PACCESS_STATE PassedAccessState
,
358 IN ACCESS_MASK DesiredAccess
,
359 IN POBJECT_TYPE ObjectType
,
360 IN KPROCESSOR_MODE AccessMode
,
365 DPRINT("ObOpenObjectByPointer()\n");
367 Status
= ObReferenceObjectByPointer(Object
,
371 if (!NT_SUCCESS(Status
))
376 Status
= ObCreateHandle(PsGetCurrentProcess(),
382 ObDereferenceObject(Object
);
384 return STATUS_SUCCESS
;
388 NTSTATUS
ObPerformRetentionChecks(POBJECT_HEADER Header
)
390 // DPRINT("ObPerformRetentionChecks(Header %x), RefCount %d, HandleCount %d\n",
391 // Header,Header->RefCount,Header->HandleCount);
393 if (Header
->RefCount
< 0)
395 DbgPrint("Object %x/%x has invalid reference count (%d)\n",
396 Header
, HEADER_TO_BODY(Header
), Header
->RefCount
);
399 if (Header
->HandleCount
< 0)
401 DbgPrint("Object %x/%x has invalid handle count (%d)\n",
402 Header
, HEADER_TO_BODY(Header
), Header
->HandleCount
);
406 if (Header
->RefCount
== 0 && Header
->HandleCount
== 0 &&
409 if (Header
->ObjectType
!= NULL
&&
410 Header
->ObjectType
->Delete
!= NULL
)
412 Header
->ObjectType
->Delete(HEADER_TO_BODY(Header
));
414 if (Header
->Name
.Buffer
!= NULL
)
416 ObRemoveEntry(Header
);
417 RtlFreeUnicodeString( &Header
->Name
);
419 DPRINT("ObPerformRetentionChecks() = Freeing object\n");
422 return(STATUS_SUCCESS
);
425 ULONG
ObGetReferenceCount(PVOID ObjectBody
)
427 POBJECT_HEADER Header
= BODY_TO_HEADER(ObjectBody
);
429 return(Header
->RefCount
);
432 ULONG
ObGetHandleCount(PVOID ObjectBody
)
434 POBJECT_HEADER Header
= BODY_TO_HEADER(ObjectBody
);
436 return(Header
->HandleCount
);
440 /**********************************************************************
442 * ObfReferenceObject@4
445 * Increments a given object's reference count and performs
449 * ObjectBody = Body of the object.
454 VOID FASTCALL
ObfReferenceObject(PVOID Object
)
456 POBJECT_HEADER Header
;
460 Header
= BODY_TO_HEADER(Object
);
464 ObPerformRetentionChecks (Header
);
468 VOID FASTCALL
ObfDereferenceObject (PVOID Object
)
470 * FUNCTION: Decrements a given object's reference count and performs
473 * Object = Body of the object
476 POBJECT_HEADER Header
;
477 extern POBJECT_TYPE PsProcessType
;
481 Header
= BODY_TO_HEADER(Object
);
483 if (Header
->ObjectType
== PsProcessType
)
485 DPRINT("Deref p 0x%x with refcount %d type %x ",
486 Object
, Header
->RefCount
, PsProcessType
);
487 DPRINT("eip %x\n", ((PULONG
)&Object
)[-1]);
489 if (Header
->ObjectType
== PsThreadType
)
491 DPRINT("Deref t 0x%x with refcount %d type %x ",
492 Object
, Header
->RefCount
, PsThreadType
);
493 DPRINT("eip %x\n", ((PULONG
)&Object
)[-1]);
498 ObPerformRetentionChecks(Header
);