1 /* $Id: object.c,v 1.55 2002/09/07 15:13:04 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 *****************************************************************/
17 #include <internal/debug.h>
20 /* FUNCTIONS ************************************************************/
22 PVOID
HEADER_TO_BODY(POBJECT_HEADER obj
)
24 return(((void *)obj
)+sizeof(OBJECT_HEADER
)-sizeof(COMMON_BODY_HEADER
));
27 POBJECT_HEADER
BODY_TO_HEADER(PVOID body
)
29 PCOMMON_BODY_HEADER chdr
= (PCOMMON_BODY_HEADER
)body
;
30 return(CONTAINING_RECORD((&(chdr
->Type
)),OBJECT_HEADER
,Type
));
34 /**********************************************************************
44 VOID
ObInitializeObject(POBJECT_HEADER ObjectHeader
,
46 ACCESS_MASK DesiredAccess
,
48 POBJECT_ATTRIBUTES ObjectAttributes
)
50 ObjectHeader
->HandleCount
= 0;
51 ObjectHeader
->RefCount
= 1;
52 ObjectHeader
->ObjectType
= Type
;
53 if (ObjectAttributes
!= NULL
&&
54 ObjectAttributes
->Attributes
& OBJ_PERMANENT
)
56 ObjectHeader
->Permanent
= TRUE
;
60 ObjectHeader
->Permanent
= FALSE
;
62 RtlInitUnicodeString(&(ObjectHeader
->Name
),NULL
);
65 ObCreateHandle(PsGetCurrentProcess(),
66 HEADER_TO_BODY(ObjectHeader
),
68 ObjectAttributes
&& (ObjectAttributes
->Attributes
& OBJ_INHERIT
) ? TRUE
: FALSE
,
74 /**********************************************************************
86 * Pointer to a unicode string that will contain the
87 * remaining path if the function returns successfully.
88 * The caller must free the buffer after use by calling
89 * RtlFreeUnicodeString ().
92 * Optional pointer to an object type. This is used to
93 * descide if a symbolic link object will be parsed or not.
97 NTSTATUS
ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes
,
98 PVOID
* ReturnedObject
,
99 PUNICODE_STRING RemainingPath
,
100 POBJECT_TYPE ObjectType
)
105 POBJECT_HEADER CurrentHeader
;
109 UNICODE_STRING PathString
;
111 DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, "
112 "RemainingPath %x)\n",ObjectAttributes
,ReturnedObject
,RemainingPath
);
113 DPRINT("ObjectAttributes->ObjectName %wZ\n",
114 ObjectAttributes
->ObjectName
);
116 RtlInitUnicodeString (RemainingPath
, NULL
);
118 if (ObjectAttributes
->RootDirectory
== NULL
)
120 ObReferenceObjectByPointer(NameSpaceRoot
,
124 CurrentObject
= NameSpaceRoot
;
128 Status
= ObReferenceObjectByHandle(ObjectAttributes
->RootDirectory
,
134 if (!NT_SUCCESS(Status
))
140 Path
= ObjectAttributes
->ObjectName
->Buffer
;
144 *ReturnedObject
= CurrentObject
;
145 return(STATUS_SUCCESS
);
148 if ((ObjectAttributes
->RootDirectory
== NULL
) && (Path
[0] != '\\'))
150 ObDereferenceObject(CurrentObject
);
151 return(STATUS_UNSUCCESSFUL
);
156 RtlCreateUnicodeString (&PathString
, Path
);
157 current
= PathString
.Buffer
;
161 RtlInitUnicodeString (&PathString
, NULL
);
165 RootObject
= CurrentObject
;
169 DPRINT("current %S\n",current
);
170 CurrentHeader
= BODY_TO_HEADER(CurrentObject
);
172 DPRINT("Current ObjectType %wZ\n",
173 &CurrentHeader
->ObjectType
->TypeName
);
175 if (CurrentHeader
->ObjectType
->Parse
== NULL
)
177 DPRINT("Current object can't parse\n");
180 Status
= CurrentHeader
->ObjectType
->Parse(CurrentObject
,
184 ObjectAttributes
->Attributes
);
185 if (Status
== STATUS_REPARSE
)
187 /* reparse the object path */
188 NextObject
= RootObject
;
189 current
= PathString
.Buffer
;
191 ObReferenceObjectByPointer(NextObject
,
197 if (NextObject
== NULL
)
201 ObDereferenceObject(CurrentObject
);
202 CurrentObject
= NextObject
;
206 RtlCreateUnicodeString (RemainingPath
, current
);
207 RtlFreeUnicodeString (&PathString
);
208 *ReturnedObject
= CurrentObject
;
210 return(STATUS_SUCCESS
);
214 /**********************************************************************
216 * ObRosCreateObject@36
225 ObRosCreateObject(OUT PHANDLE Handle
,
226 IN ACCESS_MASK DesiredAccess
,
227 IN POBJECT_ATTRIBUTES ObjectAttributes
,
228 IN POBJECT_TYPE Type
,
232 UNICODE_STRING RemainingPath
;
233 POBJECT_HEADER Header
;
234 POBJECT_HEADER ParentHeader
= NULL
;
236 BOOLEAN ObjectAttached
= FALSE
;
238 assert_irql(APC_LEVEL
);
240 DPRINT("ObRosCreateObject(Handle %x, ObjectAttributes %x, Type %x)\n",
241 Handle
, ObjectAttributes
, Type
);
243 if (ObjectAttributes
!= NULL
&&
244 ObjectAttributes
->ObjectName
!= NULL
&&
245 ObjectAttributes
->ObjectName
->Buffer
!= 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
,
264 Header
= (POBJECT_HEADER
)ExAllocatePoolWithTag(NonPagedPool
,
265 OBJECT_ALLOC_SIZE(Type
),
267 ObInitializeObject(Header
,
275 ParentHeader
= BODY_TO_HEADER(Parent
);
278 if (ParentHeader
!= NULL
&&
279 ParentHeader
->ObjectType
== ObDirectoryType
&&
280 RemainingPath
.Buffer
!= NULL
)
282 ObpAddEntryDirectory(Parent
,
284 RemainingPath
.Buffer
+1);
285 ObjectAttached
= TRUE
;
288 if ((Header
->ObjectType
!= NULL
) &&
289 (Header
->ObjectType
->Create
!= NULL
))
291 DPRINT("Calling %x\n", Header
->ObjectType
->Create
);
292 Status
= Header
->ObjectType
->Create(HEADER_TO_BODY(Header
),
294 RemainingPath
.Buffer
,
296 if (!NT_SUCCESS(Status
))
298 if (ObjectAttached
== TRUE
)
300 ObpRemoveEntryDirectory(Header
);
304 ObDereferenceObject(Parent
);
306 RtlFreeUnicodeString(&Header
->Name
);
307 RtlFreeUnicodeString(&RemainingPath
);
312 RtlFreeUnicodeString( &RemainingPath
);
316 *Object
= HEADER_TO_BODY(Header
);
321 ObCreateHandle(PsGetCurrentProcess(),
324 ObjectAttributes
&& (ObjectAttributes
->Attributes
& OBJ_INHERIT
) ? TRUE
: FALSE
,
328 return(STATUS_SUCCESS
);
333 ObReferenceObjectByPointer(IN PVOID Object
,
334 IN ACCESS_MASK DesiredAccess
,
335 IN POBJECT_TYPE ObjectType
,
336 IN KPROCESSOR_MODE AccessMode
)
338 * FUNCTION: Increments the pointer reference count for a given object
340 * ObjectBody = Object's body
341 * DesiredAccess = Desired access to the object
342 * ObjectType = Points to the object type structure
343 * AccessMode = Type of access check to perform
347 POBJECT_HEADER Header
;
349 // DPRINT("ObReferenceObjectByPointer(Object %x, ObjectType %x)\n",
350 // Object,ObjectType);
352 Header
= BODY_TO_HEADER(Object
);
354 if (ObjectType
!= NULL
&& Header
->ObjectType
!= ObjectType
)
356 DPRINT("Failed %x (type was %x %S) should be %x %S\n",
359 Header
->ObjectType
->TypeName
.Buffer
,
361 ObjectType
->TypeName
.Buffer
);
362 return(STATUS_UNSUCCESSFUL
);
364 if (Header
->ObjectType
== PsProcessType
)
366 DPRINT("Ref p 0x%x refcount %d type %x ",
367 Object
, Header
->RefCount
, PsProcessType
);
368 DPRINT("eip %x\n", ((PULONG
)&Object
)[-1]);
370 if (Header
->ObjectType
== PsThreadType
)
372 DPRINT("Deref t 0x%x with refcount %d type %x ",
373 Object
, Header
->RefCount
, PsThreadType
);
374 DPRINT("eip %x\n", ((PULONG
)&Object
)[-1]);
377 if (Header
->CloseInProcess
)
379 return(STATUS_UNSUCCESSFUL
);
382 InterlockedIncrement(&Header
->RefCount
);
384 return(STATUS_SUCCESS
);
389 ObOpenObjectByPointer(IN POBJECT Object
,
390 IN ULONG HandleAttributes
,
391 IN PACCESS_STATE PassedAccessState
,
392 IN ACCESS_MASK DesiredAccess
,
393 IN POBJECT_TYPE ObjectType
,
394 IN KPROCESSOR_MODE AccessMode
,
399 DPRINT("ObOpenObjectByPointer()\n");
401 Status
= ObReferenceObjectByPointer(Object
,
405 if (!NT_SUCCESS(Status
))
410 Status
= ObCreateHandle(PsGetCurrentProcess(),
413 HandleAttributes
& OBJ_INHERIT
,
416 ObDereferenceObject(Object
);
418 return STATUS_SUCCESS
;
423 ObpPerformRetentionChecks(POBJECT_HEADER Header
)
425 // DPRINT("ObPerformRetentionChecks(Header %x), RefCount %d, HandleCount %d\n",
426 // Header,Header->RefCount,Header->HandleCount);
428 if (Header
->RefCount
< 0)
430 CPRINT("Object %x/%x has invalid reference count (%d)\n",
431 Header
, HEADER_TO_BODY(Header
), Header
->RefCount
);
434 if (Header
->HandleCount
< 0)
436 CPRINT("Object %x/%x has invalid handle count (%d)\n",
437 Header
, HEADER_TO_BODY(Header
), Header
->HandleCount
);
441 if (Header
->RefCount
== 0 &&
442 Header
->HandleCount
== 0 &&
443 Header
->Permanent
== FALSE
)
445 if (Header
->CloseInProcess
)
448 return STATUS_UNSUCCESSFUL
;
450 Header
->CloseInProcess
= TRUE
;
451 if (Header
->ObjectType
!= NULL
&&
452 Header
->ObjectType
->Delete
!= NULL
)
454 Header
->ObjectType
->Delete(HEADER_TO_BODY(Header
));
456 if (Header
->Name
.Buffer
!= NULL
)
458 ObpRemoveEntryDirectory(Header
);
459 RtlFreeUnicodeString(&Header
->Name
);
461 DPRINT("ObPerformRetentionChecks() = Freeing object\n");
464 return(STATUS_SUCCESS
);
468 /**********************************************************************
470 * ObfReferenceObject@4
473 * Increments a given object's reference count and performs
477 * ObjectBody = Body of the object.
483 ObfReferenceObject(IN PVOID Object
)
485 POBJECT_HEADER Header
;
489 Header
= BODY_TO_HEADER(Object
);
491 if (Header
->CloseInProcess
)
495 InterlockedIncrement(&Header
->RefCount
);
497 ObpPerformRetentionChecks(Header
);
501 /**********************************************************************
503 * ObfDereferenceObject@4
506 * Decrements a given object's reference count and performs
510 * ObjectBody = Body of the object.
516 ObfDereferenceObject(IN PVOID Object
)
518 POBJECT_HEADER Header
;
519 extern POBJECT_TYPE PsProcessType
;
523 Header
= BODY_TO_HEADER(Object
);
525 if (Header
->ObjectType
== PsProcessType
)
527 DPRINT("Deref p 0x%x with refcount %d type %x ",
528 Object
, Header
->RefCount
, PsProcessType
);
529 DPRINT("eip %x\n", ((PULONG
)&Object
)[-1]);
531 if (Header
->ObjectType
== PsThreadType
)
533 DPRINT("Deref t 0x%x with refcount %d type %x ",
534 Object
, Header
->RefCount
, PsThreadType
);
535 DPRINT("eip %x\n", ((PULONG
)&Object
)[-1]);
538 InterlockedDecrement(&Header
->RefCount
);
540 ObpPerformRetentionChecks(Header
);
544 /**********************************************************************
546 * ObGetObjectPointerCount@4
549 * Retrieves the pointer(reference) count of the given object.
552 * ObjectBody = Body of the object.
558 ObGetObjectPointerCount(PVOID Object
)
560 POBJECT_HEADER Header
;
563 Header
= BODY_TO_HEADER(Object
);
565 return(Header
->RefCount
);
569 /**********************************************************************
571 * ObGetObjectHandleCount@4
574 * Retrieves the handle count of the given object.
577 * ObjectBody = Body of the object.
583 ObGetObjectHandleCount(PVOID Object
)
585 POBJECT_HEADER Header
;
588 Header
= BODY_TO_HEADER(Object
);
590 return(Header
->HandleCount
);