1 /* $Id: object.c,v 1.58 2003/02/25 16:49:08 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>
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
),
72 ObjectAttributes
&& (ObjectAttributes
->Attributes
& OBJ_INHERIT
) ? TRUE
: FALSE
,
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
;
116 DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, "
117 "RemainingPath %x)\n",ObjectAttributes
,ReturnedObject
,RemainingPath
);
118 DPRINT("ObjectAttributes->ObjectName %wZ\n",
119 ObjectAttributes
->ObjectName
);
121 RtlInitUnicodeString (RemainingPath
, NULL
);
123 if (ObjectAttributes
->RootDirectory
== NULL
)
125 ObReferenceObjectByPointer(NameSpaceRoot
,
129 CurrentObject
= NameSpaceRoot
;
133 Status
= ObReferenceObjectByHandle(ObjectAttributes
->RootDirectory
,
139 if (!NT_SUCCESS(Status
))
145 Path
= ObjectAttributes
->ObjectName
->Buffer
;
149 *ReturnedObject
= CurrentObject
;
150 return(STATUS_SUCCESS
);
153 if ((ObjectAttributes
->RootDirectory
== NULL
) && (Path
[0] != '\\'))
155 ObDereferenceObject(CurrentObject
);
156 return(STATUS_UNSUCCESSFUL
);
161 RtlCreateUnicodeString (&PathString
, Path
);
162 current
= PathString
.Buffer
;
166 RtlInitUnicodeString (&PathString
, NULL
);
170 RootObject
= CurrentObject
;
171 Attributes
= ObjectAttributes
->Attributes
;
172 if (ObjectType
== ObSymbolicLinkType
)
173 Attributes
|= OBJ_OPENLINK
;
177 DPRINT("current %S\n",current
);
178 CurrentHeader
= BODY_TO_HEADER(CurrentObject
);
180 DPRINT("Current ObjectType %wZ\n",
181 &CurrentHeader
->ObjectType
->TypeName
);
183 if (CurrentHeader
->ObjectType
->Parse
== NULL
)
185 DPRINT("Current object can't parse\n");
188 Status
= CurrentHeader
->ObjectType
->Parse(CurrentObject
,
193 if (Status
== STATUS_REPARSE
)
195 /* reparse the object path */
196 NextObject
= RootObject
;
197 current
= PathString
.Buffer
;
199 ObReferenceObjectByPointer(NextObject
,
205 if (NextObject
== NULL
)
209 ObDereferenceObject(CurrentObject
);
210 CurrentObject
= NextObject
;
214 RtlCreateUnicodeString (RemainingPath
, current
);
215 RtlFreeUnicodeString (&PathString
);
216 *ReturnedObject
= CurrentObject
;
218 return(STATUS_SUCCESS
);
222 /**********************************************************************
233 ObCreateObject(OUT PHANDLE Handle
,
234 IN ACCESS_MASK DesiredAccess
,
235 IN POBJECT_ATTRIBUTES ObjectAttributes
,
236 IN POBJECT_TYPE Type
,
240 UNICODE_STRING RemainingPath
;
241 POBJECT_HEADER Header
;
242 POBJECT_HEADER ParentHeader
= NULL
;
244 BOOLEAN ObjectAttached
= FALSE
;
246 assert_irql(APC_LEVEL
);
248 DPRINT("ObCreateObject(Handle %x, ObjectAttributes %x, Type %x)\n",
249 Handle
, ObjectAttributes
, Type
);
251 if (ObjectAttributes
!= NULL
&&
252 ObjectAttributes
->ObjectName
!= NULL
&&
253 ObjectAttributes
->ObjectName
->Buffer
!= NULL
)
255 Status
= ObFindObject(ObjectAttributes
,
259 if (!NT_SUCCESS(Status
))
261 DPRINT("ObFindObject() failed! (Status 0x%x)\n", Status
);
267 RtlInitUnicodeString(&RemainingPath
, NULL
);
270 RtlMapGenericMask(&DesiredAccess
,
273 Header
= (POBJECT_HEADER
)ExAllocatePoolWithTag(NonPagedPool
,
274 OBJECT_ALLOC_SIZE(Type
),
276 ObInitializeObject(Header
,
284 ParentHeader
= BODY_TO_HEADER(Parent
);
287 if (ParentHeader
!= NULL
&&
288 ParentHeader
->ObjectType
== ObDirectoryType
&&
289 RemainingPath
.Buffer
!= NULL
)
291 ObpAddEntryDirectory(Parent
,
293 RemainingPath
.Buffer
+1);
294 ObjectAttached
= TRUE
;
297 if ((Header
->ObjectType
!= NULL
) &&
298 (Header
->ObjectType
->Create
!= NULL
))
300 DPRINT("Calling %x\n", Header
->ObjectType
->Create
);
301 Status
= Header
->ObjectType
->Create(HEADER_TO_BODY(Header
),
303 RemainingPath
.Buffer
,
305 if (!NT_SUCCESS(Status
))
307 if (ObjectAttached
== TRUE
)
309 ObpRemoveEntryDirectory(Header
);
313 ObDereferenceObject(Parent
);
315 RtlFreeUnicodeString(&Header
->Name
);
316 RtlFreeUnicodeString(&RemainingPath
);
321 RtlFreeUnicodeString( &RemainingPath
);
325 *Object
= HEADER_TO_BODY(Header
);
330 ObCreateHandle(PsGetCurrentProcess(),
333 ObjectAttributes
&& (ObjectAttributes
->Attributes
& OBJ_INHERIT
) ? TRUE
: FALSE
,
337 return(STATUS_SUCCESS
);
342 ObReferenceObjectByPointer(IN PVOID Object
,
343 IN ACCESS_MASK DesiredAccess
,
344 IN POBJECT_TYPE ObjectType
,
345 IN KPROCESSOR_MODE AccessMode
)
347 * FUNCTION: Increments the pointer reference count for a given object
349 * ObjectBody = Object's body
350 * DesiredAccess = Desired access to the object
351 * ObjectType = Points to the object type structure
352 * AccessMode = Type of access check to perform
356 POBJECT_HEADER Header
;
358 // DPRINT("ObReferenceObjectByPointer(Object %x, ObjectType %x)\n",
359 // Object,ObjectType);
361 Header
= BODY_TO_HEADER(Object
);
363 if (ObjectType
!= NULL
&& Header
->ObjectType
!= ObjectType
)
365 DPRINT("Failed %x (type was %x %S) should be %x %S\n",
368 Header
->ObjectType
->TypeName
.Buffer
,
370 ObjectType
->TypeName
.Buffer
);
371 return(STATUS_UNSUCCESSFUL
);
373 if (Header
->ObjectType
== PsProcessType
)
375 DPRINT("Ref p 0x%x refcount %d type %x ",
376 Object
, Header
->RefCount
, PsProcessType
);
377 DPRINT("eip %x\n", ((PULONG
)&Object
)[-1]);
379 if (Header
->ObjectType
== PsThreadType
)
381 DPRINT("Deref t 0x%x with refcount %d type %x ",
382 Object
, Header
->RefCount
, PsThreadType
);
383 DPRINT("eip %x\n", ((PULONG
)&Object
)[-1]);
386 if (Header
->CloseInProcess
)
388 return(STATUS_UNSUCCESSFUL
);
391 InterlockedIncrement(&Header
->RefCount
);
393 return(STATUS_SUCCESS
);
398 ObOpenObjectByPointer(IN POBJECT Object
,
399 IN ULONG HandleAttributes
,
400 IN PACCESS_STATE PassedAccessState
,
401 IN ACCESS_MASK DesiredAccess
,
402 IN POBJECT_TYPE ObjectType
,
403 IN KPROCESSOR_MODE AccessMode
,
408 DPRINT("ObOpenObjectByPointer()\n");
410 Status
= ObReferenceObjectByPointer(Object
,
414 if (!NT_SUCCESS(Status
))
419 Status
= ObCreateHandle(PsGetCurrentProcess(),
422 HandleAttributes
& OBJ_INHERIT
,
425 ObDereferenceObject(Object
);
427 return STATUS_SUCCESS
;
432 ObpPerformRetentionChecks(POBJECT_HEADER Header
)
434 // DPRINT("ObPerformRetentionChecks(Header %x), RefCount %d, HandleCount %d\n",
435 // Header,Header->RefCount,Header->HandleCount);
437 if (Header
->RefCount
< 0)
439 CPRINT("Object %x/%x has invalid reference count (%d)\n",
440 Header
, HEADER_TO_BODY(Header
), Header
->RefCount
);
443 if (Header
->HandleCount
< 0)
445 CPRINT("Object %x/%x has invalid handle count (%d)\n",
446 Header
, HEADER_TO_BODY(Header
), Header
->HandleCount
);
450 if (Header
->RefCount
== 0 &&
451 Header
->HandleCount
== 0 &&
452 Header
->Permanent
== FALSE
)
454 if (Header
->CloseInProcess
)
457 return STATUS_UNSUCCESSFUL
;
459 Header
->CloseInProcess
= TRUE
;
460 if (Header
->ObjectType
!= NULL
&&
461 Header
->ObjectType
->Delete
!= NULL
)
463 Header
->ObjectType
->Delete(HEADER_TO_BODY(Header
));
465 if (Header
->Name
.Buffer
!= NULL
)
467 ObpRemoveEntryDirectory(Header
);
468 RtlFreeUnicodeString(&Header
->Name
);
470 DPRINT("ObPerformRetentionChecks() = Freeing object\n");
473 return(STATUS_SUCCESS
);
477 /**********************************************************************
479 * ObfReferenceObject@4
482 * Increments a given object's reference count and performs
486 * ObjectBody = Body of the object.
492 ObfReferenceObject(IN PVOID Object
)
494 POBJECT_HEADER Header
;
498 Header
= BODY_TO_HEADER(Object
);
500 if (Header
->CloseInProcess
)
504 InterlockedIncrement(&Header
->RefCount
);
506 ObpPerformRetentionChecks(Header
);
510 /**********************************************************************
512 * ObfDereferenceObject@4
515 * Decrements a given object's reference count and performs
519 * ObjectBody = Body of the object.
525 ObfDereferenceObject(IN PVOID Object
)
527 POBJECT_HEADER Header
;
528 extern POBJECT_TYPE PsProcessType
;
532 Header
= BODY_TO_HEADER(Object
);
534 if (Header
->ObjectType
== PsProcessType
)
536 DPRINT("Deref p 0x%x with refcount %d type %x ",
537 Object
, Header
->RefCount
, PsProcessType
);
538 DPRINT("eip %x\n", ((PULONG
)&Object
)[-1]);
540 if (Header
->ObjectType
== PsThreadType
)
542 DPRINT("Deref t 0x%x with refcount %d type %x ",
543 Object
, Header
->RefCount
, PsThreadType
);
544 DPRINT("eip %x\n", ((PULONG
)&Object
)[-1]);
547 InterlockedDecrement(&Header
->RefCount
);
549 ObpPerformRetentionChecks(Header
);
553 /**********************************************************************
555 * ObGetObjectPointerCount@4
558 * Retrieves the pointer(reference) count of the given object.
561 * ObjectBody = Body of the object.
567 ObGetObjectPointerCount(PVOID Object
)
569 POBJECT_HEADER Header
;
572 Header
= BODY_TO_HEADER(Object
);
574 return(Header
->RefCount
);
578 /**********************************************************************
580 * ObGetObjectHandleCount@4
583 * Retrieves the handle count of the given object.
586 * ObjectBody = Body of the object.
592 ObGetObjectHandleCount(PVOID Object
)
594 POBJECT_HEADER Header
;
597 Header
= BODY_TO_HEADER(Object
);
599 return(Header
->HandleCount
);