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,
80 /**********************************************************************
92 * Pointer to a unicode string that will contain the
93 * remaining path if the function returns successfully.
94 * The caller must free the buffer after use by calling
95 * RtlFreeUnicodeString ().
98 * Optional pointer to an object type. This is used to
99 * descide if a symbolic link object will be parsed or not.
103 NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
104 PVOID* ReturnedObject,
105 PUNICODE_STRING RemainingPath,
106 POBJECT_TYPE ObjectType)
111 POBJECT_HEADER CurrentHeader;
115 UNICODE_STRING PathString;
118 DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, "
119 "RemainingPath %x)\n",ObjectAttributes,ReturnedObject,RemainingPath);
120 DPRINT("ObjectAttributes->ObjectName %wZ\n",
121 ObjectAttributes->ObjectName);
123 RtlInitUnicodeString (RemainingPath, NULL);
125 if (ObjectAttributes->RootDirectory == NULL)
127 ObReferenceObjectByPointer(NameSpaceRoot,
131 CurrentObject = NameSpaceRoot;
135 Status = ObReferenceObjectByHandle(ObjectAttributes->RootDirectory,
141 if (!NT_SUCCESS(Status))
147 Path = ObjectAttributes->ObjectName->Buffer;
151 *ReturnedObject = CurrentObject;
152 return(STATUS_SUCCESS);
155 if ((ObjectAttributes->RootDirectory == NULL) && (Path[0] != '\\'))
157 ObDereferenceObject(CurrentObject);
158 return(STATUS_UNSUCCESSFUL);
163 RtlCreateUnicodeString (&PathString, Path);
164 current = PathString.Buffer;
168 RtlInitUnicodeString (&PathString, NULL);
172 RootObject = CurrentObject;
173 Attributes = ObjectAttributes->Attributes;
175 if (ObjectType == ObSymbolicLinkType)
176 Attributes |= OBJ_OPENLINK;
177 #endif /* LIBCAPTIVE */
181 DPRINT("current %S\n",current);
182 CurrentHeader = BODY_TO_HEADER(CurrentObject);
184 DPRINT("Current ObjectType %wZ\n",
185 &CurrentHeader->ObjectType->TypeName);
187 if (CurrentHeader->ObjectType->Parse == NULL)
189 DPRINT("Current object can't parse\n");
192 Status = CurrentHeader->ObjectType->Parse(CurrentObject,
197 if (Status == STATUS_REPARSE)
199 /* reparse the object path */
200 NextObject = RootObject;
201 current = PathString.Buffer;
203 ObReferenceObjectByPointer(NextObject,
209 if (NextObject == NULL)
213 ObDereferenceObject(CurrentObject);
214 CurrentObject = NextObject;
218 RtlCreateUnicodeString (RemainingPath, current);
219 RtlFreeUnicodeString (&PathString);
220 *ReturnedObject = CurrentObject;
222 return(STATUS_SUCCESS);
226 /**********************************************************************
237 ObCreateObject(OUT PHANDLE Handle,
238 IN ACCESS_MASK DesiredAccess,
239 IN POBJECT_ATTRIBUTES ObjectAttributes,
240 IN POBJECT_TYPE Type,
244 UNICODE_STRING RemainingPath;
245 POBJECT_HEADER Header;
246 POBJECT_HEADER ParentHeader = NULL;
248 BOOLEAN ObjectAttached = FALSE;
250 assert_irql(APC_LEVEL);
252 DPRINT("ObCreateObject(Handle %x, ObjectAttributes %x, Type %x)\n",
253 Handle, ObjectAttributes, Type);
255 if (ObjectAttributes != NULL &&
256 ObjectAttributes->ObjectName != NULL &&
257 ObjectAttributes->ObjectName->Buffer != NULL)
259 Status = ObFindObject(ObjectAttributes,
263 if (!NT_SUCCESS(Status))
265 DPRINT("ObFindObject() failed! (Status 0x%x)\n", Status);
271 RtlInitUnicodeString(&RemainingPath, NULL);
274 RtlMapGenericMask(&DesiredAccess,
277 Header = (POBJECT_HEADER)ExAllocatePoolWithTag(NonPagedPool,
278 OBJECT_ALLOC_SIZE(Type),
280 ObInitializeObject(Header,
288 ParentHeader = BODY_TO_HEADER(Parent);
291 if (ParentHeader != NULL &&
292 ParentHeader->ObjectType == ObDirectoryType &&
293 RemainingPath.Buffer != NULL)
295 ObpAddEntryDirectory(Parent,
297 RemainingPath.Buffer+1);
298 ObjectAttached = TRUE;
301 if ((Header->ObjectType != NULL) &&
302 (Header->ObjectType->Create != NULL))
304 DPRINT("Calling %x\n", Header->ObjectType->Create);
305 Status = Header->ObjectType->Create(HEADER_TO_BODY(Header),
307 RemainingPath.Buffer,
309 if (!NT_SUCCESS(Status))
311 if (ObjectAttached == TRUE)
313 ObpRemoveEntryDirectory(Header);
317 ObDereferenceObject(Parent);
319 RtlFreeUnicodeString(&Header->Name);
320 RtlFreeUnicodeString(&RemainingPath);
325 RtlFreeUnicodeString( &RemainingPath );
329 *Object = HEADER_TO_BODY(Header);
334 ObCreateHandle(PsGetCurrentProcess(),
337 ObjectAttributes && (ObjectAttributes->Attributes & OBJ_INHERIT) ? TRUE : FALSE,
341 return(STATUS_SUCCESS);
346 ObReferenceObjectByPointer(IN PVOID Object,
347 IN ACCESS_MASK DesiredAccess,
348 IN POBJECT_TYPE ObjectType,
349 IN KPROCESSOR_MODE AccessMode)
351 * FUNCTION: Increments the pointer reference count for a given object
353 * ObjectBody = Object's body
354 * DesiredAccess = Desired access to the object
355 * ObjectType = Points to the object type structure
356 * AccessMode = Type of access check to perform
360 POBJECT_HEADER Header;
362 // DPRINT("ObReferenceObjectByPointer(Object %x, ObjectType %x)\n",
363 // Object,ObjectType);
365 Header = BODY_TO_HEADER(Object);
367 if (ObjectType != NULL && Header->ObjectType != ObjectType)
369 DPRINT("Failed %x (type was %x %S) should be %x %S\n",
372 Header->ObjectType->TypeName.Buffer,
374 ObjectType->TypeName.Buffer);
375 return(STATUS_UNSUCCESSFUL);
377 if (Header->ObjectType == PsProcessType)
379 DPRINT("Ref p 0x%x refcount %d type %x ",
380 Object, Header->RefCount, PsProcessType);
381 DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
383 if (Header->ObjectType == PsThreadType)
385 DPRINT("Deref t 0x%x with refcount %d type %x ",
386 Object, Header->RefCount, PsThreadType);
387 DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
390 if (Header->CloseInProcess)
392 return(STATUS_UNSUCCESSFUL);
395 InterlockedIncrement(&Header->RefCount);
397 return(STATUS_SUCCESS);
403 ObOpenObjectByPointer(IN POBJECT Object,
404 IN ULONG HandleAttributes,
405 IN PACCESS_STATE PassedAccessState,
406 IN ACCESS_MASK DesiredAccess,
407 IN POBJECT_TYPE ObjectType,
408 IN KPROCESSOR_MODE AccessMode,
413 DPRINT("ObOpenObjectByPointer()\n");
415 Status = ObReferenceObjectByPointer(Object,
419 if (!NT_SUCCESS(Status))
424 Status = ObCreateHandle(PsGetCurrentProcess(),
427 HandleAttributes & OBJ_INHERIT,
430 ObDereferenceObject(Object);
432 return STATUS_SUCCESS;
435 #endif /* LIBCAPTIVE */
438 extern BOOLEAN captive_cc_FileObject_delete(FILE_OBJECT *FileObject);
439 #endif /* LIBCAPTIVE */
442 ObpPerformRetentionChecks(POBJECT_HEADER Header)
444 // DPRINT("ObPerformRetentionChecks(Header %x), RefCount %d, HandleCount %d\n",
445 // Header,Header->RefCount,Header->HandleCount);
447 if (Header->RefCount < 0)
449 CPRINT("Object %x/%x has invalid reference count (%d)\n",
450 Header, HEADER_TO_BODY(Header), Header->RefCount);
453 if (Header->HandleCount < 0)
455 CPRINT("Object %x/%x has invalid handle count (%d)\n",
456 Header, HEADER_TO_BODY(Header), Header->HandleCount);
460 if (Header->RefCount == 0 &&
461 Header->HandleCount == 0 &&
462 Header->Permanent == FALSE)
465 captive_cc_FileObject_delete(HEADER_TO_BODY(Header));
466 #endif /* LIBCAPTIVE */
467 if (Header->CloseInProcess)
470 return STATUS_UNSUCCESSFUL;
472 Header->CloseInProcess = TRUE;
473 if (Header->ObjectType != NULL &&
474 Header->ObjectType->Delete != NULL)
476 Header->ObjectType->Delete(HEADER_TO_BODY(Header));
478 if (Header->Name.Buffer != NULL)
480 ObpRemoveEntryDirectory(Header);
481 RtlFreeUnicodeString(&Header->Name);
483 DPRINT("ObPerformRetentionChecks() = Freeing object\n");
486 return(STATUS_SUCCESS);
490 /**********************************************************************
492 * ObfReferenceObject@4
495 * Increments a given object's reference count and performs
499 * ObjectBody = Body of the object.
505 ObfReferenceObject(IN PVOID Object)
507 POBJECT_HEADER Header;
511 Header = BODY_TO_HEADER(Object);
513 if (Header->CloseInProcess)
517 InterlockedIncrement(&Header->RefCount);
519 ObpPerformRetentionChecks(Header);
523 /**********************************************************************
525 * ObfDereferenceObject@4
528 * Decrements a given object's reference count and performs
532 * ObjectBody = Body of the object.
538 ObfDereferenceObject(IN PVOID Object)
540 POBJECT_HEADER Header;
541 extern POBJECT_TYPE PsProcessType;
545 Header = BODY_TO_HEADER(Object);
547 if (Header->ObjectType == PsProcessType)
549 DPRINT("Deref p 0x%x with refcount %d type %x ",
550 Object, Header->RefCount, PsProcessType);
551 DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
553 if (Header->ObjectType == PsThreadType)
555 DPRINT("Deref t 0x%x with refcount %d type %x ",
556 Object, Header->RefCount, PsThreadType);
557 DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
560 InterlockedDecrement(&Header->RefCount);
562 ObpPerformRetentionChecks(Header);
567 /**********************************************************************
569 * ObGetObjectPointerCount@4
572 * Retrieves the pointer(reference) count of the given object.
575 * ObjectBody = Body of the object.
581 ObGetObjectPointerCount(PVOID Object)
583 POBJECT_HEADER Header;
586 Header = BODY_TO_HEADER(Object);
588 return(Header->RefCount);
592 /**********************************************************************
594 * ObGetObjectHandleCount@4
597 * Retrieves the handle count of the given object.
600 * ObjectBody = Body of the object.
606 ObGetObjectHandleCount(PVOID Object)
608 POBJECT_HEADER Header;
611 Header = BODY_TO_HEADER(Object);
613 return(Header->HandleCount);
616 #endif /* LIBCAPTIVE */