1 /* $Id: object.c,v 1.29 2000/10/22 16:36:53 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 return(STATUS_UNSUCCESSFUL
);
158 // if ( Path[0] != '\\' )
160 // RtlCreateUnicodeString (&PathString, L"\\");
161 // RtlAppendUnicodeToString (&PathString, Path);
164 RtlCreateUnicodeString (&PathString
, Path
);
165 current
= PathString
.Buffer
;
169 RtlInitUnicodeString (&PathString
, NULL
);
173 RootObject
= CurrentObject
;
177 DPRINT("current %S\n",current
);
178 CurrentHeader
= BODY_TO_HEADER(CurrentObject
);
179 if (CurrentHeader
->ObjectType
->Parse
== NULL
)
181 DPRINT("Current object can't parse\n");
184 Status
= CurrentHeader
->ObjectType
->Parse(CurrentObject
,
189 if (Status
== STATUS_REPARSE
)
191 /* reparse the object path */
192 NextObject
= RootObject
;
193 current
= PathString
.Buffer
;
195 ObReferenceObjectByPointer(NextObject
,
201 if (NextObject
== NULL
)
205 ObDereferenceObject(CurrentObject
);
206 CurrentObject
= NextObject
;
210 RtlCreateUnicodeString (RemainingPath
, current
);
211 RtlFreeUnicodeString (&PathString
);
212 *ReturnedObject
= CurrentObject
;
214 return(STATUS_SUCCESS
);
218 /**********************************************************************
228 PVOID STDCALL
ObCreateObject(PHANDLE Handle
,
229 ACCESS_MASK DesiredAccess
,
230 POBJECT_ATTRIBUTES ObjectAttributes
,
234 UNICODE_STRING RemainingPath
;
235 POBJECT_HEADER Header
;
238 assert_irql(APC_LEVEL
);
240 DPRINT("ObCreateObject(Handle %x, ObjectAttributes %x, Type %x)\n");
241 if (ObjectAttributes
!= NULL
&&
242 ObjectAttributes
->ObjectName
!= NULL
)
244 DPRINT("ObjectAttributes->ObjectName->Buffer %S\n",
245 ObjectAttributes
->ObjectName
->Buffer
);
248 if (ObjectAttributes
!= NULL
&&
249 ObjectAttributes
->ObjectName
!= NULL
)
251 ObFindObject(ObjectAttributes
,
258 RtlInitUnicodeString (&RemainingPath
, NULL
);
260 Header
= (POBJECT_HEADER
)ExAllocatePool(NonPagedPool
,
261 OBJECT_ALLOC_SIZE(Type
));
262 ObInitializeObject(Header
,
267 if (Header
->ObjectType
!= NULL
&&
268 Header
->ObjectType
->Create
!= NULL
)
270 DPRINT("Calling %x\n", Header
->ObjectType
);
271 DPRINT("Calling %x\n", Header
->ObjectType
->Create
);
272 Status
= Header
->ObjectType
->Create(HEADER_TO_BODY(Header
),
274 RemainingPath
.Buffer
,
276 if (!NT_SUCCESS(Status
))
278 ObDereferenceObject( Parent
);
279 RtlFreeUnicodeString( &Header
->Name
);
280 RtlFreeUnicodeString( &RemainingPath
);
281 ExFreePool( Header
);
285 RtlFreeUnicodeString( &RemainingPath
);
286 return(HEADER_TO_BODY(Header
));
289 NTSTATUS STDCALL
ObReferenceObjectByPointer(PVOID ObjectBody
,
290 ACCESS_MASK DesiredAccess
,
291 POBJECT_TYPE ObjectType
,
292 KPROCESSOR_MODE AccessMode
)
294 * FUNCTION: Increments the pointer reference count for a given object
296 * ObjectBody = Object's body
297 * DesiredAccess = Desired access to the object
298 * ObjectType = Points to the object type structure
299 * AccessMode = Type of access check to perform
303 POBJECT_HEADER ObjectHeader
;
305 // DPRINT("ObReferenceObjectByPointer(ObjectBody %x, ObjectType %x)\n",
306 // ObjectBody,ObjectType);
308 ObjectHeader
= BODY_TO_HEADER(ObjectBody
);
310 if (ObjectType
!= NULL
&& ObjectHeader
->ObjectType
!= ObjectType
)
312 DPRINT("Failed %x (type was %x %S) should %x\n",
314 ObjectHeader
->ObjectType
,
315 ObjectHeader
->ObjectType
->TypeName
.Buffer
,
318 return(STATUS_UNSUCCESSFUL
);
320 if (ObjectHeader
->ObjectType
== PsProcessType
)
322 DPRINT("Ref p 0x%x refcount %d type %x ",
323 ObjectBody
, ObjectHeader
->RefCount
, PsProcessType
);
324 DPRINT("eip %x\n", ((PULONG
)&ObjectBody
)[-1]);
326 if (ObjectHeader
->ObjectType
== PsThreadType
)
328 DPRINT("Deref t 0x%x with refcount %d type %x ",
329 ObjectBody
, ObjectHeader
->RefCount
, PsThreadType
);
330 DPRINT("eip %x\n", ((PULONG
)&ObjectBody
)[-1]);
333 ObjectHeader
->RefCount
++;
335 return(STATUS_SUCCESS
);
338 NTSTATUS
ObPerformRetentionChecks(POBJECT_HEADER Header
)
340 // DPRINT("ObPerformRetentionChecks(Header %x), RefCount %d, HandleCount %d\n",
341 // Header,Header->RefCount,Header->HandleCount);
343 if (Header
->RefCount
< 0)
345 DbgPrint("Object %x/%x has invalid reference count (%d)\n",
346 Header
, HEADER_TO_BODY(Header
), Header
->RefCount
);
349 if (Header
->HandleCount
< 0)
351 DbgPrint("Object %x/%x has invalid handle count (%d)\n",
352 Header
, HEADER_TO_BODY(Header
), Header
->HandleCount
);
356 if (Header
->RefCount
== 0 && Header
->HandleCount
== 0 &&
359 if (Header
->ObjectType
!= NULL
&&
360 Header
->ObjectType
->Delete
!= NULL
)
362 Header
->ObjectType
->Delete(HEADER_TO_BODY(Header
));
364 if (Header
->Name
.Buffer
!= NULL
)
366 ObRemoveEntry(Header
);
367 RtlFreeUnicodeString( &Header
->Name
);
369 DPRINT("ObPerformRetentionChecks() = Freeing object\n");
372 return(STATUS_SUCCESS
);
375 ULONG
ObGetReferenceCount(PVOID ObjectBody
)
377 POBJECT_HEADER Header
= BODY_TO_HEADER(ObjectBody
);
379 return(Header
->RefCount
);
382 ULONG
ObGetHandleCount(PVOID ObjectBody
)
384 POBJECT_HEADER Header
= BODY_TO_HEADER(ObjectBody
);
386 return(Header
->HandleCount
);
390 /**********************************************************************
392 * @ObfReferenceObject@0
395 * Increments a given object's reference count and performs
400 * Body of the object.
403 * The current value of the reference counter.
405 ULONG FASTCALL
ObfReferenceObject(PVOID ObjectBody
)
407 POBJECT_HEADER Header
= BODY_TO_HEADER(ObjectBody
);
408 ULONG ReferenceCount
;
410 ReferenceCount
= Header
->RefCount
++;
412 ObPerformRetentionChecks (Header
);
414 return(ReferenceCount
);
418 VOID FASTCALL
ObfDereferenceObject (PVOID ObjectBody
)
420 * FUNCTION: Decrements a given object's reference count and performs
423 * ObjectBody = Body of the object
426 POBJECT_HEADER Header
= BODY_TO_HEADER(ObjectBody
);
427 extern POBJECT_TYPE PsProcessType
;
429 // DPRINT("ObDeferenceObject(ObjectBody %x) RefCount %d\n",ObjectBody,
430 // Header->RefCount);
432 if (Header
->ObjectType
== PsProcessType
)
434 DPRINT("Deref p 0x%x with refcount %d type %x ",
435 ObjectBody
, Header
->RefCount
, PsProcessType
);
436 DPRINT("eip %x\n", ((PULONG
)&ObjectBody
)[-1]);
438 if (Header
->ObjectType
== PsThreadType
)
440 DPRINT("Deref t 0x%x with refcount %d type %x ",
441 ObjectBody
, Header
->RefCount
, PsThreadType
);
442 DPRINT("eip %x\n", ((PULONG
)&ObjectBody
)[-1]);
447 ObPerformRetentionChecks(Header
);
451 VOID STDCALL
ObDereferenceObject (PVOID ObjectBody
)
453 POBJECT_HEADER Header
= BODY_TO_HEADER(ObjectBody
);
454 extern POBJECT_TYPE PsProcessType
;
456 if (Header
->ObjectType
== PsProcessType
)
458 DPRINT("Deref p 0x%x with refcount %d type %x ",
459 ObjectBody
, Header
->RefCount
, PsProcessType
);
460 DPRINT("eip %x\n", ((PULONG
)&ObjectBody
)[-1]);
463 ObfDereferenceObject (ObjectBody
);