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->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;
116 DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, "
117 "RemainingPath %x)\n",ObjectAttributes,ReturnedObject,RemainingPath);
118 DPRINT("ObjectAttributes->ObjectName %wZ\n",
119 ObjectAttributes->ObjectName);
121 RtlInitUnicodeString (RemainingPath, NULL);
123 if (ObjectAttributes->RootDirectory == NULL)
125 ObReferenceObjectByPointer(NameSpaceRoot,
129 CurrentObject = NameSpaceRoot;
133 Status = ObReferenceObjectByHandle(ObjectAttributes->RootDirectory,
139 if (!NT_SUCCESS(Status))
145 Path = ObjectAttributes->ObjectName->Buffer;
149 *ReturnedObject = CurrentObject;
150 return(STATUS_SUCCESS);
153 if ((ObjectAttributes->RootDirectory == NULL) && (Path[0] != '\\'))
155 ObDereferenceObject(CurrentObject);
156 return(STATUS_UNSUCCESSFUL);
161 RtlCreateUnicodeString (&PathString, Path);
162 current = PathString.Buffer;
166 RtlInitUnicodeString (&PathString, NULL);
170 RootObject = CurrentObject;
174 DPRINT("current %S\n",current);
175 CurrentHeader = BODY_TO_HEADER(CurrentObject);
177 DPRINT("Current ObjectType %wZ\n",
178 &CurrentHeader->ObjectType->TypeName);
180 if (CurrentHeader->ObjectType->Parse == NULL)
182 DPRINT("Current object can't parse\n");
185 Status = CurrentHeader->ObjectType->Parse(CurrentObject,
189 ObjectAttributes->Attributes);
190 if (Status == STATUS_REPARSE)
192 /* reparse the object path */
193 NextObject = RootObject;
194 current = PathString.Buffer;
196 ObReferenceObjectByPointer(NextObject,
202 if (NextObject == NULL)
206 ObDereferenceObject(CurrentObject);
207 CurrentObject = NextObject;
211 RtlCreateUnicodeString (RemainingPath, current);
212 RtlFreeUnicodeString (&PathString);
213 *ReturnedObject = CurrentObject;
215 return(STATUS_SUCCESS);
219 /**********************************************************************
230 ObCreateObject(OUT PHANDLE Handle,
231 IN ACCESS_MASK DesiredAccess,
232 IN POBJECT_ATTRIBUTES ObjectAttributes,
233 IN POBJECT_TYPE Type,
237 UNICODE_STRING RemainingPath;
238 POBJECT_HEADER Header;
239 POBJECT_HEADER ParentHeader = NULL;
241 BOOLEAN ObjectAttached = FALSE;
243 assert_irql(APC_LEVEL);
245 DPRINT("ObCreateObject(Handle %x, ObjectAttributes %x, Type %x)\n",
246 Handle, ObjectAttributes, Type);
248 if (ObjectAttributes != NULL &&
249 ObjectAttributes->ObjectName != NULL &&
250 ObjectAttributes->ObjectName->Buffer != NULL)
252 Status = ObFindObject(ObjectAttributes,
256 if (!NT_SUCCESS(Status))
258 DPRINT("ObFindObject() failed! (Status 0x%x)\n", Status);
264 RtlInitUnicodeString(&RemainingPath, NULL);
267 RtlMapGenericMask(&DesiredAccess,
270 Header = (POBJECT_HEADER)ExAllocatePoolWithTag(NonPagedPool,
271 OBJECT_ALLOC_SIZE(Type),
273 ObInitializeObject(Header,
281 ParentHeader = BODY_TO_HEADER(Parent);
284 if (ParentHeader != NULL &&
285 ParentHeader->ObjectType == ObDirectoryType &&
286 RemainingPath.Buffer != NULL)
288 ObpAddEntryDirectory(Parent,
290 RemainingPath.Buffer+1);
291 ObjectAttached = TRUE;
294 if ((Header->ObjectType != NULL) &&
295 (Header->ObjectType->Create != NULL))
297 DPRINT("Calling %x\n", Header->ObjectType->Create);
298 Status = Header->ObjectType->Create(HEADER_TO_BODY(Header),
300 RemainingPath.Buffer,
302 if (!NT_SUCCESS(Status))
304 if (ObjectAttached == TRUE)
306 ObpRemoveEntryDirectory(Header);
310 ObDereferenceObject(Parent);
312 RtlFreeUnicodeString(&Header->Name);
313 RtlFreeUnicodeString(&RemainingPath);
318 RtlFreeUnicodeString( &RemainingPath );
322 *Object = HEADER_TO_BODY(Header);
327 ObCreateHandle(PsGetCurrentProcess(),
330 ObjectAttributes && (ObjectAttributes->Attributes & OBJ_INHERIT) ? TRUE : FALSE,
334 return(STATUS_SUCCESS);
339 ObReferenceObjectByPointer(IN PVOID Object,
340 IN ACCESS_MASK DesiredAccess,
341 IN POBJECT_TYPE ObjectType,
342 IN KPROCESSOR_MODE AccessMode)
344 * FUNCTION: Increments the pointer reference count for a given object
346 * ObjectBody = Object's body
347 * DesiredAccess = Desired access to the object
348 * ObjectType = Points to the object type structure
349 * AccessMode = Type of access check to perform
353 POBJECT_HEADER Header;
355 // DPRINT("ObReferenceObjectByPointer(Object %x, ObjectType %x)\n",
356 // Object,ObjectType);
358 Header = BODY_TO_HEADER(Object);
360 if (ObjectType != NULL && Header->ObjectType != ObjectType)
362 DPRINT("Failed %x (type was %x %S) should be %x %S\n",
365 Header->ObjectType->TypeName.Buffer,
367 ObjectType->TypeName.Buffer);
368 return(STATUS_UNSUCCESSFUL);
370 if (Header->ObjectType == PsProcessType)
372 DPRINT("Ref p 0x%x refcount %d type %x ",
373 Object, Header->RefCount, PsProcessType);
374 DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
376 if (Header->ObjectType == PsThreadType)
378 DPRINT("Deref t 0x%x with refcount %d type %x ",
379 Object, Header->RefCount, PsThreadType);
380 DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
383 if (Header->CloseInProcess)
385 return(STATUS_UNSUCCESSFUL);
388 InterlockedIncrement(&Header->RefCount);
390 return(STATUS_SUCCESS);
396 ObOpenObjectByPointer(IN POBJECT Object,
397 IN ULONG HandleAttributes,
398 IN PACCESS_STATE PassedAccessState,
399 IN ACCESS_MASK DesiredAccess,
400 IN POBJECT_TYPE ObjectType,
401 IN KPROCESSOR_MODE AccessMode,
406 DPRINT("ObOpenObjectByPointer()\n");
408 Status = ObReferenceObjectByPointer(Object,
412 if (!NT_SUCCESS(Status))
417 Status = ObCreateHandle(PsGetCurrentProcess(),
420 HandleAttributes & OBJ_INHERIT,
423 ObDereferenceObject(Object);
425 return STATUS_SUCCESS;
428 #endif /* LIBCAPTIVE */
431 ObpPerformRetentionChecks(POBJECT_HEADER Header)
433 // DPRINT("ObPerformRetentionChecks(Header %x), RefCount %d, HandleCount %d\n",
434 // Header,Header->RefCount,Header->HandleCount);
436 if (Header->RefCount < 0)
438 CPRINT("Object %x/%x has invalid reference count (%d)\n",
439 Header, HEADER_TO_BODY(Header), Header->RefCount);
442 if (Header->HandleCount < 0)
444 CPRINT("Object %x/%x has invalid handle count (%d)\n",
445 Header, HEADER_TO_BODY(Header), Header->HandleCount);
449 if (Header->RefCount == 0 &&
450 Header->HandleCount == 0 &&
451 Header->Permanent == FALSE)
453 if (Header->CloseInProcess)
456 return STATUS_UNSUCCESSFUL;
458 Header->CloseInProcess = TRUE;
459 if (Header->ObjectType != NULL &&
460 Header->ObjectType->Delete != NULL)
462 Header->ObjectType->Delete(HEADER_TO_BODY(Header));
464 if (Header->Name.Buffer != NULL)
466 ObpRemoveEntryDirectory(Header);
467 RtlFreeUnicodeString(&Header->Name);
469 DPRINT("ObPerformRetentionChecks() = Freeing object\n");
472 return(STATUS_SUCCESS);
476 /**********************************************************************
478 * ObfReferenceObject@4
481 * Increments a given object's reference count and performs
485 * ObjectBody = Body of the object.
491 ObfReferenceObject(IN PVOID Object)
493 POBJECT_HEADER Header;
497 Header = BODY_TO_HEADER(Object);
499 if (Header->CloseInProcess)
503 InterlockedIncrement(&Header->RefCount);
505 ObpPerformRetentionChecks(Header);
509 /**********************************************************************
511 * ObfDereferenceObject@4
514 * Decrements a given object's reference count and performs
518 * ObjectBody = Body of the object.
524 ObfDereferenceObject(IN PVOID Object)
526 POBJECT_HEADER Header;
527 extern POBJECT_TYPE PsProcessType;
531 Header = BODY_TO_HEADER(Object);
533 if (Header->ObjectType == PsProcessType)
535 DPRINT("Deref p 0x%x with refcount %d type %x ",
536 Object, Header->RefCount, PsProcessType);
537 DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
539 if (Header->ObjectType == PsThreadType)
541 DPRINT("Deref t 0x%x with refcount %d type %x ",
542 Object, Header->RefCount, PsThreadType);
543 DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
546 InterlockedDecrement(&Header->RefCount);
548 ObpPerformRetentionChecks(Header);
553 /**********************************************************************
555 * ObGetObjectPointerCount@4
558 * Retrieves the pointer(reference) count of the given object.
561 * ObjectBody = Body of the object.
567 ObGetObjectPointerCount(PVOID Object)
569 POBJECT_HEADER Header;
572 Header = BODY_TO_HEADER(Object);
574 return(Header->RefCount);
578 /**********************************************************************
580 * ObGetObjectHandleCount@4
583 * Retrieves the handle count of the given object.
586 * ObjectBody = Body of the object.
592 ObGetObjectHandleCount(PVOID Object)
594 POBJECT_HEADER Header;
597 Header = BODY_TO_HEADER(Object);
599 return(Header->HandleCount);
602 #endif /* LIBCAPTIVE */