1 /* $Id: object.c,v 1.27 2000/09/29 15:03:21 jean 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 *****************************************************************/
15 #include <ddk/ntddk.h>
16 #include <internal/ob.h>
17 #include <internal/string.h>
18 #include <internal/ps.h>
19 #include <internal/id.h>
20 #include <internal/ke.h>
23 #include <internal/debug.h>
25 /* FUNCTIONS ************************************************************/
27 /**********************************************************************
37 VOID
ObInitializeObject(POBJECT_HEADER ObjectHeader
,
39 ACCESS_MASK DesiredAccess
,
41 POBJECT_ATTRIBUTES ObjectAttributes
)
43 ObjectHeader
->HandleCount
= 0;
44 ObjectHeader
->RefCount
= 1;
45 ObjectHeader
->ObjectType
= Type
;
46 if (ObjectAttributes
!= NULL
&&
47 ObjectAttributes
->Attributes
& OBJ_PERMANENT
)
49 ObjectHeader
->Permanent
= TRUE
;
53 ObjectHeader
->Permanent
= FALSE
;
55 RtlInitUnicodeString(&(ObjectHeader
->Name
),NULL
);
58 ObCreateHandle(PsGetCurrentProcess(),
59 HEADER_TO_BODY(ObjectHeader
),
67 /**********************************************************************
79 * Pointer to a unicode string that will contain the
80 * remaining path if the function returns successfully.
81 * The caller must free the buffer after use by calling
82 * RtlFreeUnicodeString ().
85 * Optional pointer to an object type. This is used to
86 * descide if a symbolic link object will be parsed or not.
90 NTSTATUS
ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes
,
91 PVOID
* ReturnedObject
,
92 PUNICODE_STRING RemainingPath
,
93 POBJECT_TYPE ObjectType
)
98 POBJECT_HEADER CurrentHeader
;
102 UNICODE_STRING PathString
;
104 DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, "
105 "RemainingPath %x)\n",ObjectAttributes
,ReturnedObject
,RemainingPath
);
106 DPRINT("ObjectAttributes->ObjectName->Buffer %x\n",
107 ObjectAttributes
->ObjectName
->Buffer
);
109 RtlInitUnicodeString (RemainingPath
, NULL
);
111 if (ObjectAttributes
->RootDirectory
== NULL
)
113 ObReferenceObjectByPointer(NameSpaceRoot
,
117 CurrentObject
= NameSpaceRoot
;
121 Status
= ObReferenceObjectByHandle(ObjectAttributes
->RootDirectory
,
127 if (!NT_SUCCESS(Status
))
133 Path
= ObjectAttributes
->ObjectName
->Buffer
;
137 *ReturnedObject
= CurrentObject
;
138 return(STATUS_SUCCESS
);
141 if ((ObjectAttributes
->RootDirectory
== NULL
) && (Path
[0] != '\\'))
143 return(STATUS_UNSUCCESSFUL
);
148 // if ( Path[0] != '\\' )
150 // RtlCreateUnicodeString (&PathString, L"\\");
151 // RtlAppendUnicodeToString (&PathString, Path);
154 RtlCreateUnicodeString (&PathString
, Path
);
155 current
= PathString
.Buffer
;
159 RtlInitUnicodeString (&PathString
, NULL
);
163 RootObject
= CurrentObject
;
167 DPRINT("current %S\n",current
);
168 CurrentHeader
= BODY_TO_HEADER(CurrentObject
);
169 if (CurrentHeader
->ObjectType
->Parse
== NULL
)
171 DPRINT("Current object can't parse\n");
174 Status
= CurrentHeader
->ObjectType
->Parse(CurrentObject
,
179 if (Status
== STATUS_REPARSE
)
181 /* reparse the object path */
182 NextObject
= RootObject
;
183 current
= PathString
.Buffer
;
185 ObReferenceObjectByPointer(NextObject
,
191 if (NextObject
== NULL
)
195 ObDereferenceObject(CurrentObject
);
196 CurrentObject
= NextObject
;
200 RtlCreateUnicodeString (RemainingPath
, current
);
201 RtlFreeUnicodeString (&PathString
);
202 *ReturnedObject
= CurrentObject
;
204 return(STATUS_SUCCESS
);
208 /**********************************************************************
218 PVOID STDCALL
ObCreateObject(PHANDLE Handle
,
219 ACCESS_MASK DesiredAccess
,
220 POBJECT_ATTRIBUTES ObjectAttributes
,
224 UNICODE_STRING RemainingPath
;
225 POBJECT_HEADER Header
;
228 assert_irql(APC_LEVEL
);
230 DPRINT("ObCreateObject(Handle %x, ObjectAttributes %x, Type %x)\n");
231 if (ObjectAttributes
!= NULL
&&
232 ObjectAttributes
->ObjectName
!= NULL
)
234 DPRINT("ObjectAttributes->ObjectName->Buffer %S\n",
235 ObjectAttributes
->ObjectName
->Buffer
);
238 if (ObjectAttributes
!= NULL
&&
239 ObjectAttributes
->ObjectName
!= NULL
)
241 ObFindObject(ObjectAttributes
,
248 RtlInitUnicodeString (&RemainingPath
, NULL
);
250 Header
= (POBJECT_HEADER
)ExAllocatePool(NonPagedPool
,
251 OBJECT_ALLOC_SIZE(Type
));
252 ObInitializeObject(Header
,
257 if (Header
->ObjectType
!= NULL
&&
258 Header
->ObjectType
->Create
!= NULL
)
260 DPRINT("Calling %x\n", Header
->ObjectType
);
261 DPRINT("Calling %x\n", Header
->ObjectType
->Create
);
262 Status
= Header
->ObjectType
->Create(HEADER_TO_BODY(Header
),
264 RemainingPath
.Buffer
,
266 if (!NT_SUCCESS(Status
))
268 ObDereferenceObject( Parent
);
269 RtlFreeUnicodeString( &Header
->Name
);
270 RtlFreeUnicodeString( &RemainingPath
);
271 ExFreePool( Header
);
275 RtlFreeUnicodeString( &RemainingPath
);
276 return(HEADER_TO_BODY(Header
));
279 NTSTATUS STDCALL
ObReferenceObjectByPointer(PVOID ObjectBody
,
280 ACCESS_MASK DesiredAccess
,
281 POBJECT_TYPE ObjectType
,
282 KPROCESSOR_MODE AccessMode
)
284 * FUNCTION: Increments the pointer reference count for a given object
286 * ObjectBody = Object's body
287 * DesiredAccess = Desired access to the object
288 * ObjectType = Points to the object type structure
289 * AccessMode = Type of access check to perform
293 POBJECT_HEADER ObjectHeader
;
295 // DPRINT("ObReferenceObjectByPointer(ObjectBody %x, ObjectType %x)\n",
296 // ObjectBody,ObjectType);
298 ObjectHeader
= BODY_TO_HEADER(ObjectBody
);
300 if (ObjectType
!= NULL
&& ObjectHeader
->ObjectType
!= ObjectType
)
302 DPRINT("Failed %x (type was %x %S) should %x\n",
304 ObjectHeader
->ObjectType
,
305 ObjectHeader
->ObjectType
->TypeName
.Buffer
,
308 return(STATUS_UNSUCCESSFUL
);
310 if (ObjectHeader
->ObjectType
== PsProcessType
)
312 DPRINT("Ref p 0x%x refcount %d type %x ",
313 ObjectBody
, ObjectHeader
->RefCount
, PsProcessType
);
314 DPRINT("eip %x\n", ((PULONG
)&ObjectBody
)[-1]);
316 if (ObjectHeader
->ObjectType
== PsThreadType
)
318 DPRINT("Deref t 0x%x with refcount %d type %x ",
319 ObjectBody
, ObjectHeader
->RefCount
, PsThreadType
);
320 DPRINT("eip %x\n", ((PULONG
)&ObjectBody
)[-1]);
323 ObjectHeader
->RefCount
++;
325 return(STATUS_SUCCESS
);
328 NTSTATUS
ObPerformRetentionChecks(POBJECT_HEADER Header
)
330 // DPRINT("ObPerformRetentionChecks(Header %x), RefCount %d, HandleCount %d\n",
331 // Header,Header->RefCount,Header->HandleCount);
333 if (Header
->RefCount
< 0)
335 DbgPrint("Object %x/%x has invalid reference count (%d)\n",
336 Header
, HEADER_TO_BODY(Header
), Header
->RefCount
);
339 if (Header
->HandleCount
< 0)
341 DbgPrint("Object %x/%x has invalid handle count (%d)\n",
342 Header
, HEADER_TO_BODY(Header
), Header
->HandleCount
);
346 if (Header
->RefCount
== 0 && Header
->HandleCount
== 0 &&
349 if (Header
->ObjectType
!= NULL
&&
350 Header
->ObjectType
->Delete
!= NULL
)
352 Header
->ObjectType
->Delete(HEADER_TO_BODY(Header
));
354 if (Header
->Name
.Buffer
!= NULL
)
356 ObRemoveEntry(Header
);
357 RtlFreeUnicodeString( &Header
->Name
);
359 DPRINT("ObPerformRetentionChecks() = Freeing object\n");
362 return(STATUS_SUCCESS
);
365 ULONG
ObGetReferenceCount(PVOID ObjectBody
)
367 POBJECT_HEADER Header
= BODY_TO_HEADER(ObjectBody
);
369 return(Header
->RefCount
);
372 ULONG
ObGetHandleCount(PVOID ObjectBody
)
374 POBJECT_HEADER Header
= BODY_TO_HEADER(ObjectBody
);
376 return(Header
->HandleCount
);
380 /**********************************************************************
382 * @ObfReferenceObject@0
385 * Increments a given object's reference count and performs
390 * Body of the object.
393 * The current value of the reference counter.
395 ULONG FASTCALL
ObfReferenceObject(PVOID ObjectBody
)
397 POBJECT_HEADER Header
= BODY_TO_HEADER(ObjectBody
);
398 ULONG ReferenceCount
;
400 ReferenceCount
= Header
->RefCount
++;
402 ObPerformRetentionChecks (Header
);
404 return(ReferenceCount
);
408 VOID FASTCALL
ObfDereferenceObject (PVOID ObjectBody
)
410 * FUNCTION: Decrements a given object's reference count and performs
413 * ObjectBody = Body of the object
416 POBJECT_HEADER Header
= BODY_TO_HEADER(ObjectBody
);
417 extern POBJECT_TYPE PsProcessType
;
419 // DPRINT("ObDeferenceObject(ObjectBody %x) RefCount %d\n",ObjectBody,
420 // Header->RefCount);
422 if (Header
->ObjectType
== PsProcessType
)
424 DPRINT("Deref p 0x%x with refcount %d type %x ",
425 ObjectBody
, Header
->RefCount
, PsProcessType
);
426 DPRINT("eip %x\n", ((PULONG
)&ObjectBody
)[-1]);
428 if (Header
->ObjectType
== PsThreadType
)
430 DPRINT("Deref t 0x%x with refcount %d type %x ",
431 ObjectBody
, Header
->RefCount
, PsThreadType
);
432 DPRINT("eip %x\n", ((PULONG
)&ObjectBody
)[-1]);
437 ObPerformRetentionChecks(Header
);
441 VOID STDCALL
ObDereferenceObject (PVOID ObjectBody
)
443 POBJECT_HEADER Header
= BODY_TO_HEADER(ObjectBody
);
444 extern POBJECT_TYPE PsProcessType
;
446 if (Header
->ObjectType
== PsProcessType
)
448 DPRINT("Deref p 0x%x with refcount %d type %x ",
449 ObjectBody
, Header
->RefCount
, PsProcessType
);
450 DPRINT("eip %x\n", ((PULONG
)&ObjectBody
)[-1]);
453 ObfDereferenceObject (ObjectBody
);