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>
20 #include <internal/io.h>
23 #include <internal/debug.h>
25 /* FUNCTIONS ************************************************************/
27 PVOID HEADER_TO_BODY(POBJECT_HEADER obj)
29 return(((void *)obj)+sizeof(OBJECT_HEADER)-sizeof(COMMON_BODY_HEADER));
32 POBJECT_HEADER BODY_TO_HEADER(PVOID body)
34 PCOMMON_BODY_HEADER chdr = (PCOMMON_BODY_HEADER)body;
35 return(CONTAINING_RECORD((&(chdr->Type)),OBJECT_HEADER,Type));
39 /**********************************************************************
49 VOID ObInitializeObject(POBJECT_HEADER ObjectHeader,
51 ACCESS_MASK DesiredAccess,
53 POBJECT_ATTRIBUTES ObjectAttributes)
55 ObjectHeader->HandleCount = 0;
56 ObjectHeader->RefCount = 1;
57 ObjectHeader->ObjectType = Type;
58 if (ObjectAttributes != NULL &&
59 ObjectAttributes->Attributes & OBJ_PERMANENT)
61 ObjectHeader->Permanent = TRUE;
65 ObjectHeader->Permanent = FALSE;
67 RtlInitUnicodeString(&(ObjectHeader->Name),NULL);
70 ObCreateHandle(PsGetCurrentProcess(),
71 HEADER_TO_BODY(ObjectHeader),
73 ObjectAttributes && (ObjectAttributes->Attributes & OBJ_INHERIT) ? TRUE : FALSE,
79 /**********************************************************************
91 * Pointer to a unicode string that will contain the
92 * remaining path if the function returns successfully.
93 * The caller must free the buffer after use by calling
94 * RtlFreeUnicodeString ().
97 * Optional pointer to an object type. This is used to
98 * descide if a symbolic link object will be parsed or not.
102 NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
103 PVOID* ReturnedObject,
104 PUNICODE_STRING RemainingPath,
105 POBJECT_TYPE ObjectType)
110 POBJECT_HEADER CurrentHeader;
114 UNICODE_STRING PathString;
117 DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, "
118 "RemainingPath %x)\n",ObjectAttributes,ReturnedObject,RemainingPath);
119 DPRINT("ObjectAttributes->ObjectName %wZ\n",
120 ObjectAttributes->ObjectName);
122 RtlInitUnicodeString (RemainingPath, NULL);
124 if (ObjectAttributes->RootDirectory == NULL)
126 ObReferenceObjectByPointer(NameSpaceRoot,
130 CurrentObject = NameSpaceRoot;
134 Status = ObReferenceObjectByHandle(ObjectAttributes->RootDirectory,
140 if (!NT_SUCCESS(Status))
146 Path = ObjectAttributes->ObjectName->Buffer;
150 *ReturnedObject = CurrentObject;
151 return(STATUS_SUCCESS);
154 if ((ObjectAttributes->RootDirectory == NULL) && (Path[0] != '\\'))
156 ObDereferenceObject(CurrentObject);
157 return(STATUS_UNSUCCESSFUL);
162 RtlCreateUnicodeString (&PathString, Path);
163 current = PathString.Buffer;
167 RtlInitUnicodeString (&PathString, NULL);
171 RootObject = CurrentObject;
172 Attributes = ObjectAttributes->Attributes;
173 if (ObjectType == IoSymbolicLinkType)
174 Attributes |= OBJ_OPENLINK;
178 DPRINT("current %S\n",current);
179 CurrentHeader = BODY_TO_HEADER(CurrentObject);
181 DPRINT("Current ObjectType %wZ\n",
182 &CurrentHeader->ObjectType->TypeName);
184 if (CurrentHeader->ObjectType->Parse == NULL)
186 DPRINT("Current object can't parse\n");
189 Status = CurrentHeader->ObjectType->Parse(CurrentObject,
194 if (Status == STATUS_REPARSE)
196 /* reparse the object path */
197 NextObject = RootObject;
198 current = PathString.Buffer;
200 ObReferenceObjectByPointer(NextObject,
206 if (NextObject == NULL)
210 ObDereferenceObject(CurrentObject);
211 CurrentObject = NextObject;
215 RtlCreateUnicodeString (RemainingPath, current);
216 RtlFreeUnicodeString (&PathString);
217 *ReturnedObject = CurrentObject;
219 return(STATUS_SUCCESS);
223 /**********************************************************************
234 ObCreateObject(OUT PHANDLE Handle,
235 IN ACCESS_MASK DesiredAccess,
236 IN POBJECT_ATTRIBUTES ObjectAttributes,
237 IN POBJECT_TYPE Type,
241 UNICODE_STRING RemainingPath;
242 POBJECT_HEADER Header;
243 POBJECT_HEADER ParentHeader = NULL;
245 BOOLEAN ObjectAttached = FALSE;
247 assert_irql(APC_LEVEL);
249 DPRINT("ObCreateObject(Handle %x, ObjectAttributes %x, Type %x)\n",
250 Handle, ObjectAttributes, Type);
252 if (ObjectAttributes != NULL &&
253 ObjectAttributes->ObjectName != NULL &&
254 ObjectAttributes->ObjectName->Buffer != NULL)
256 Status = ObFindObject(ObjectAttributes,
260 if (!NT_SUCCESS(Status))
262 DPRINT("ObFindObject() failed! (Status 0x%x)\n", Status);
268 RtlInitUnicodeString(&RemainingPath, NULL);
271 RtlMapGenericMask(&DesiredAccess,
274 Header = (POBJECT_HEADER)ExAllocatePoolWithTag(NonPagedPool,
275 OBJECT_ALLOC_SIZE(Type),
277 ObInitializeObject(Header,
285 ParentHeader = BODY_TO_HEADER(Parent);
288 if (ParentHeader != NULL &&
289 ParentHeader->ObjectType == ObDirectoryType &&
290 RemainingPath.Buffer != NULL)
292 ObpAddEntryDirectory(Parent,
294 RemainingPath.Buffer+1);
295 ObjectAttached = TRUE;
298 if ((Header->ObjectType != NULL) &&
299 (Header->ObjectType->Create != NULL))
301 DPRINT("Calling %x\n", Header->ObjectType->Create);
302 Status = Header->ObjectType->Create(HEADER_TO_BODY(Header),
304 RemainingPath.Buffer,
306 if (!NT_SUCCESS(Status))
308 if (ObjectAttached == TRUE)
310 ObpRemoveEntryDirectory(Header);
314 ObDereferenceObject(Parent);
316 RtlFreeUnicodeString(&Header->Name);
317 RtlFreeUnicodeString(&RemainingPath);
322 RtlFreeUnicodeString( &RemainingPath );
326 *Object = HEADER_TO_BODY(Header);
331 ObCreateHandle(PsGetCurrentProcess(),
334 ObjectAttributes && (ObjectAttributes->Attributes & OBJ_INHERIT) ? TRUE : FALSE,
338 return(STATUS_SUCCESS);
343 ObReferenceObjectByPointer(IN PVOID Object,
344 IN ACCESS_MASK DesiredAccess,
345 IN POBJECT_TYPE ObjectType,
346 IN KPROCESSOR_MODE AccessMode)
348 * FUNCTION: Increments the pointer reference count for a given object
350 * ObjectBody = Object's body
351 * DesiredAccess = Desired access to the object
352 * ObjectType = Points to the object type structure
353 * AccessMode = Type of access check to perform
357 POBJECT_HEADER Header;
359 // DPRINT("ObReferenceObjectByPointer(Object %x, ObjectType %x)\n",
360 // Object,ObjectType);
362 Header = BODY_TO_HEADER(Object);
364 if (ObjectType != NULL && Header->ObjectType != ObjectType)
366 DPRINT("Failed %x (type was %x %S) should be %x %S\n",
369 Header->ObjectType->TypeName.Buffer,
371 ObjectType->TypeName.Buffer);
372 return(STATUS_UNSUCCESSFUL);
374 if (Header->ObjectType == PsProcessType)
376 DPRINT("Ref p 0x%x refcount %d type %x ",
377 Object, Header->RefCount, PsProcessType);
378 DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
380 if (Header->ObjectType == PsThreadType)
382 DPRINT("Deref t 0x%x with refcount %d type %x ",
383 Object, Header->RefCount, PsThreadType);
384 DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
387 if (Header->CloseInProcess)
389 return(STATUS_UNSUCCESSFUL);
392 InterlockedIncrement(&Header->RefCount);
394 return(STATUS_SUCCESS);
399 ObOpenObjectByPointer(IN POBJECT Object,
400 IN ULONG HandleAttributes,
401 IN PACCESS_STATE PassedAccessState,
402 IN ACCESS_MASK DesiredAccess,
403 IN POBJECT_TYPE ObjectType,
404 IN KPROCESSOR_MODE AccessMode,
409 DPRINT("ObOpenObjectByPointer()\n");
411 Status = ObReferenceObjectByPointer(Object,
415 if (!NT_SUCCESS(Status))
420 Status = ObCreateHandle(PsGetCurrentProcess(),
423 HandleAttributes & OBJ_INHERIT,
426 ObDereferenceObject(Object);
428 return STATUS_SUCCESS;
433 ObpPerformRetentionChecks(POBJECT_HEADER Header)
435 // DPRINT("ObPerformRetentionChecks(Header %x), RefCount %d, HandleCount %d\n",
436 // Header,Header->RefCount,Header->HandleCount);
438 if (Header->RefCount < 0)
440 CPRINT("Object %x/%x has invalid reference count (%d)\n",
441 Header, HEADER_TO_BODY(Header), Header->RefCount);
444 if (Header->HandleCount < 0)
446 CPRINT("Object %x/%x has invalid handle count (%d)\n",
447 Header, HEADER_TO_BODY(Header), Header->HandleCount);
451 if (Header->RefCount == 0 &&
452 Header->HandleCount == 0 &&
453 Header->Permanent == FALSE)
455 if (Header->CloseInProcess)
458 return STATUS_UNSUCCESSFUL;
460 Header->CloseInProcess = TRUE;
461 if (Header->ObjectType != NULL &&
462 Header->ObjectType->Delete != NULL)
464 Header->ObjectType->Delete(HEADER_TO_BODY(Header));
466 if (Header->Name.Buffer != NULL)
468 ObpRemoveEntryDirectory(Header);
469 RtlFreeUnicodeString(&Header->Name);
471 DPRINT("ObPerformRetentionChecks() = Freeing object\n");
474 return(STATUS_SUCCESS);
478 /**********************************************************************
480 * ObfReferenceObject@4
483 * Increments a given object's reference count and performs
487 * ObjectBody = Body of the object.
493 ObfReferenceObject(IN PVOID Object)
495 POBJECT_HEADER Header;
499 Header = BODY_TO_HEADER(Object);
501 if (Header->CloseInProcess)
505 InterlockedIncrement(&Header->RefCount);
507 ObpPerformRetentionChecks(Header);
511 /**********************************************************************
513 * ObfDereferenceObject@4
516 * Decrements a given object's reference count and performs
520 * ObjectBody = Body of the object.
526 ObfDereferenceObject(IN PVOID Object)
528 POBJECT_HEADER Header;
529 extern POBJECT_TYPE PsProcessType;
533 Header = BODY_TO_HEADER(Object);
535 if (Header->ObjectType == PsProcessType)
537 DPRINT("Deref p 0x%x with refcount %d type %x ",
538 Object, Header->RefCount, PsProcessType);
539 DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
541 if (Header->ObjectType == PsThreadType)
543 DPRINT("Deref t 0x%x with refcount %d type %x ",
544 Object, Header->RefCount, PsThreadType);
545 DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
548 InterlockedDecrement(&Header->RefCount);
550 ObpPerformRetentionChecks(Header);
554 /**********************************************************************
556 * ObGetObjectPointerCount@4
559 * Retrieves the pointer(reference) count of the given object.
562 * ObjectBody = Body of the object.
568 ObGetObjectPointerCount(PVOID Object)
570 POBJECT_HEADER Header;
573 Header = BODY_TO_HEADER(Object);
575 return(Header->RefCount);
579 /**********************************************************************
581 * ObGetObjectHandleCount@4
584 * Retrieves the handle count of the given object.
587 * ObjectBody = Body of the object.
593 ObGetObjectHandleCount(PVOID Object)
595 POBJECT_HEADER Header;
598 Header = BODY_TO_HEADER(Object);
600 return(Header->HandleCount);