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->CloseInProcess = FALSE;
55 ObjectHeader->HandleCount = 0;
56 ObjectHeader->RefCount = 1;
57 ObjectHeader->Parent = NULL;
58 ObjectHeader->ObjectType = Type;
59 if (ObjectAttributes != NULL &&
60 ObjectAttributes->Attributes & OBJ_PERMANENT)
62 ObjectHeader->Permanent = TRUE;
66 ObjectHeader->Permanent = FALSE;
68 RtlInitUnicodeString(&(ObjectHeader->Name),NULL);
71 ObCreateHandle(PsGetCurrentProcess(),
72 HEADER_TO_BODY(ObjectHeader),
74 ObjectAttributes && (ObjectAttributes->Attributes & OBJ_INHERIT) ? TRUE : FALSE,
78 memset(HEADER_TO_BODY(ObjectHeader),0,Type->NonpagedPoolCharge);
82 /**********************************************************************
94 * Pointer to a unicode string that will contain the
95 * remaining path if the function returns successfully.
96 * The caller must free the buffer after use by calling
97 * RtlFreeUnicodeString ().
100 * Optional pointer to an object type. This is used to
101 * descide if a symbolic link object will be parsed or not.
105 NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
106 PVOID* ReturnedObject,
107 PUNICODE_STRING RemainingPath,
108 POBJECT_TYPE ObjectType)
113 POBJECT_HEADER CurrentHeader;
117 UNICODE_STRING PathString;
120 DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, "
121 "RemainingPath %x)\n",ObjectAttributes,ReturnedObject,RemainingPath);
122 DPRINT("ObjectAttributes->ObjectName %wZ\n",
123 ObjectAttributes->ObjectName);
125 RtlInitUnicodeString (RemainingPath, NULL);
127 if (ObjectAttributes->RootDirectory == NULL)
129 ObReferenceObjectByPointer(NameSpaceRoot,
133 CurrentObject = NameSpaceRoot;
137 Status = ObReferenceObjectByHandle(ObjectAttributes->RootDirectory,
143 if (!NT_SUCCESS(Status))
149 Path = ObjectAttributes->ObjectName->Buffer;
153 *ReturnedObject = CurrentObject;
154 return(STATUS_SUCCESS);
157 if ((ObjectAttributes->RootDirectory == NULL) && (Path[0] != '\\'))
159 ObDereferenceObject(CurrentObject);
160 return(STATUS_UNSUCCESSFUL);
165 RtlCreateUnicodeString (&PathString, Path);
166 current = PathString.Buffer;
170 RtlInitUnicodeString (&PathString, NULL);
174 RootObject = CurrentObject;
175 Attributes = ObjectAttributes->Attributes;
177 if (ObjectType == ObSymbolicLinkType)
178 Attributes |= OBJ_OPENLINK;
179 #endif /* LIBCAPTIVE */
183 DPRINT("current %S\n",current);
184 CurrentHeader = BODY_TO_HEADER(CurrentObject);
186 DPRINT("Current ObjectType %wZ\n",
187 &CurrentHeader->ObjectType->TypeName);
189 if (CurrentHeader->ObjectType->Parse == NULL)
191 DPRINT("Current object can't parse\n");
194 Status = CurrentHeader->ObjectType->Parse(CurrentObject,
199 if (Status == STATUS_REPARSE)
201 /* reparse the object path */
202 NextObject = RootObject;
203 current = PathString.Buffer;
205 ObReferenceObjectByPointer(NextObject,
211 if (NextObject == NULL)
215 ObDereferenceObject(CurrentObject);
216 CurrentObject = NextObject;
220 RtlCreateUnicodeString (RemainingPath, current);
221 RtlFreeUnicodeString (&PathString);
222 *ReturnedObject = CurrentObject;
224 return(STATUS_SUCCESS);
228 /**********************************************************************
239 ObCreateObject(OUT PHANDLE Handle,
240 IN ACCESS_MASK DesiredAccess,
241 IN POBJECT_ATTRIBUTES ObjectAttributes,
242 IN POBJECT_TYPE Type,
246 UNICODE_STRING RemainingPath;
247 POBJECT_HEADER Header;
248 POBJECT_HEADER ParentHeader = NULL;
250 BOOLEAN ObjectAttached = FALSE;
252 assert_irql(APC_LEVEL);
254 DPRINT("ObCreateObject(Handle %x, ObjectAttributes %x, Type %x)\n",
255 Handle, ObjectAttributes, Type);
257 if (ObjectAttributes != NULL &&
258 ObjectAttributes->ObjectName != NULL &&
259 ObjectAttributes->ObjectName->Buffer != NULL)
261 Status = ObFindObject(ObjectAttributes,
265 if (!NT_SUCCESS(Status))
267 DPRINT("ObFindObject() failed! (Status 0x%x)\n", Status);
273 RtlInitUnicodeString(&RemainingPath, NULL);
276 RtlMapGenericMask(&DesiredAccess,
279 Header = (POBJECT_HEADER)ExAllocatePoolWithTag(NonPagedPool,
280 OBJECT_ALLOC_SIZE(Type),
282 ObInitializeObject(Header,
290 ParentHeader = BODY_TO_HEADER(Parent);
293 if (ParentHeader != NULL &&
294 ParentHeader->ObjectType == ObDirectoryType &&
295 RemainingPath.Buffer != NULL)
297 ObpAddEntryDirectory(Parent,
299 RemainingPath.Buffer+1);
300 ObjectAttached = TRUE;
303 if ((Header->ObjectType != NULL) &&
304 (Header->ObjectType->Create != NULL))
306 DPRINT("Calling %x\n", Header->ObjectType->Create);
307 Status = Header->ObjectType->Create(HEADER_TO_BODY(Header),
309 RemainingPath.Buffer,
311 if (!NT_SUCCESS(Status))
313 if (ObjectAttached == TRUE)
315 ObpRemoveEntryDirectory(Header);
319 ObDereferenceObject(Parent);
321 RtlFreeUnicodeString(&Header->Name);
322 RtlFreeUnicodeString(&RemainingPath);
327 RtlFreeUnicodeString( &RemainingPath );
331 *Object = HEADER_TO_BODY(Header);
336 ObCreateHandle(PsGetCurrentProcess(),
339 ObjectAttributes && (ObjectAttributes->Attributes & OBJ_INHERIT) ? TRUE : FALSE,
343 return(STATUS_SUCCESS);
348 ObReferenceObjectByPointer(IN PVOID Object,
349 IN ACCESS_MASK DesiredAccess,
350 IN POBJECT_TYPE ObjectType,
351 IN KPROCESSOR_MODE AccessMode)
353 * FUNCTION: Increments the pointer reference count for a given object
355 * ObjectBody = Object's body
356 * DesiredAccess = Desired access to the object
357 * ObjectType = Points to the object type structure
358 * AccessMode = Type of access check to perform
362 POBJECT_HEADER Header;
364 // DPRINT("ObReferenceObjectByPointer(Object %x, ObjectType %x)\n",
365 // Object,ObjectType);
367 Header = BODY_TO_HEADER(Object);
369 if (ObjectType != NULL && Header->ObjectType != ObjectType)
371 DPRINT("Failed %x (type was %x %S) should be %x %S\n",
374 Header->ObjectType->TypeName.Buffer,
376 ObjectType->TypeName.Buffer);
377 return(STATUS_UNSUCCESSFUL);
379 if (Header->ObjectType == PsProcessType)
381 DPRINT("Ref p 0x%x refcount %d type %x ",
382 Object, Header->RefCount, PsProcessType);
383 DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
385 if (Header->ObjectType == PsThreadType)
387 DPRINT("Deref t 0x%x with refcount %d type %x ",
388 Object, Header->RefCount, PsThreadType);
389 DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
392 if (Header->CloseInProcess)
394 return(STATUS_UNSUCCESSFUL);
397 InterlockedIncrement(&Header->RefCount);
399 return(STATUS_SUCCESS);
405 ObOpenObjectByPointer(IN POBJECT Object,
406 IN ULONG HandleAttributes,
407 IN PACCESS_STATE PassedAccessState,
408 IN ACCESS_MASK DesiredAccess,
409 IN POBJECT_TYPE ObjectType,
410 IN KPROCESSOR_MODE AccessMode,
415 DPRINT("ObOpenObjectByPointer()\n");
417 Status = ObReferenceObjectByPointer(Object,
421 if (!NT_SUCCESS(Status))
426 Status = ObCreateHandle(PsGetCurrentProcess(),
429 HandleAttributes & OBJ_INHERIT,
432 ObDereferenceObject(Object);
434 return STATUS_SUCCESS;
437 #endif /* LIBCAPTIVE */
440 extern BOOLEAN captive_cc_FileObject_delete(FILE_OBJECT *FileObject);
441 #endif /* LIBCAPTIVE */
444 ObpPerformRetentionChecks(POBJECT_HEADER Header)
446 // DPRINT("ObPerformRetentionChecks(Header %x), RefCount %d, HandleCount %d\n",
447 // Header,Header->RefCount,Header->HandleCount);
449 if (Header->RefCount < 0)
451 CPRINT("Object %x/%x has invalid reference count (%d)\n",
452 Header, HEADER_TO_BODY(Header), Header->RefCount);
455 if (Header->HandleCount < 0)
457 CPRINT("Object %x/%x has invalid handle count (%d)\n",
458 Header, HEADER_TO_BODY(Header), Header->HandleCount);
462 if (Header->RefCount == 0 &&
463 Header->HandleCount == 0 &&
464 Header->Permanent == FALSE)
467 captive_cc_FileObject_delete(HEADER_TO_BODY(Header));
468 #endif /* LIBCAPTIVE */
469 if (Header->CloseInProcess)
472 return STATUS_UNSUCCESSFUL;
474 Header->CloseInProcess = TRUE;
475 if (Header->ObjectType != NULL &&
476 Header->ObjectType->Delete != NULL)
478 Header->ObjectType->Delete(HEADER_TO_BODY(Header));
480 if (Header->Name.Buffer != NULL)
482 ObpRemoveEntryDirectory(Header);
483 RtlFreeUnicodeString(&Header->Name);
485 DPRINT("ObPerformRetentionChecks() = Freeing object\n");
486 if (Header->ObjectType != IoFileObjectType) /* LIBCAPTIVE */
489 return(STATUS_SUCCESS);
493 /**********************************************************************
495 * ObfReferenceObject@4
498 * Increments a given object's reference count and performs
502 * ObjectBody = Body of the object.
508 ObfReferenceObject(IN PVOID Object)
510 POBJECT_HEADER Header;
514 Header = BODY_TO_HEADER(Object);
516 if (Header->CloseInProcess)
520 InterlockedIncrement(&Header->RefCount);
522 ObpPerformRetentionChecks(Header);
526 /**********************************************************************
528 * ObfDereferenceObject@4
531 * Decrements a given object's reference count and performs
535 * ObjectBody = Body of the object.
541 ObfDereferenceObject(IN PVOID Object)
543 POBJECT_HEADER Header;
544 extern POBJECT_TYPE PsProcessType;
548 Header = BODY_TO_HEADER(Object);
550 if (Header->ObjectType == PsProcessType)
552 DPRINT("Deref p 0x%x with refcount %d type %x ",
553 Object, Header->RefCount, PsProcessType);
554 DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
556 if (Header->ObjectType == PsThreadType)
558 DPRINT("Deref t 0x%x with refcount %d type %x ",
559 Object, Header->RefCount, PsThreadType);
560 DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
563 InterlockedDecrement(&Header->RefCount);
565 ObpPerformRetentionChecks(Header);
570 /**********************************************************************
572 * ObGetObjectPointerCount@4
575 * Retrieves the pointer(reference) count of the given object.
578 * ObjectBody = Body of the object.
584 ObGetObjectPointerCount(PVOID Object)
586 POBJECT_HEADER Header;
589 Header = BODY_TO_HEADER(Object);
591 return(Header->RefCount);
595 /**********************************************************************
597 * ObGetObjectHandleCount@4
600 * Retrieves the handle count of the given object.
603 * ObjectBody = Body of the object.
609 ObGetObjectHandleCount(PVOID Object)
611 POBJECT_HEADER Header;
614 Header = BODY_TO_HEADER(Object);
616 return(Header->HandleCount);
619 #endif /* LIBCAPTIVE */