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->HandleCount = 0;
55 ObjectHeader->RefCount = 1;
56 ObjectHeader->ObjectType = Type;
57 if (ObjectAttributes != NULL &&
58 ObjectAttributes->Attributes & OBJ_PERMANENT)
60 ObjectHeader->Permanent = TRUE;
64 ObjectHeader->Permanent = FALSE;
66 RtlInitUnicodeString(&(ObjectHeader->Name),NULL);
69 ObCreateHandle(PsGetCurrentProcess(),
70 HEADER_TO_BODY(ObjectHeader),
72 ObjectAttributes && (ObjectAttributes->Attributes & OBJ_INHERIT) ? TRUE : FALSE,
78 /**********************************************************************
90 * Pointer to a unicode string that will contain the
91 * remaining path if the function returns successfully.
92 * The caller must free the buffer after use by calling
93 * RtlFreeUnicodeString ().
96 * Optional pointer to an object type. This is used to
97 * descide if a symbolic link object will be parsed or not.
101 NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
102 PVOID* ReturnedObject,
103 PUNICODE_STRING RemainingPath,
104 POBJECT_TYPE ObjectType)
109 POBJECT_HEADER CurrentHeader;
113 UNICODE_STRING PathString;
115 DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, "
116 "RemainingPath %x)\n",ObjectAttributes,ReturnedObject,RemainingPath);
117 DPRINT("ObjectAttributes->ObjectName %wZ\n",
118 ObjectAttributes->ObjectName);
120 RtlInitUnicodeString (RemainingPath, NULL);
122 if (ObjectAttributes->RootDirectory == NULL)
124 ObReferenceObjectByPointer(NameSpaceRoot,
128 CurrentObject = NameSpaceRoot;
132 Status = ObReferenceObjectByHandle(ObjectAttributes->RootDirectory,
138 if (!NT_SUCCESS(Status))
144 Path = ObjectAttributes->ObjectName->Buffer;
148 *ReturnedObject = CurrentObject;
149 return(STATUS_SUCCESS);
152 if ((ObjectAttributes->RootDirectory == NULL) && (Path[0] != '\\'))
154 ObDereferenceObject(CurrentObject);
155 return(STATUS_UNSUCCESSFUL);
160 RtlCreateUnicodeString (&PathString, Path);
161 current = PathString.Buffer;
165 RtlInitUnicodeString (&PathString, NULL);
169 RootObject = CurrentObject;
173 DPRINT("current %S\n",current);
174 CurrentHeader = BODY_TO_HEADER(CurrentObject);
176 DPRINT("Current ObjectType %wZ\n",
177 &CurrentHeader->ObjectType->TypeName);
179 if (CurrentHeader->ObjectType->Parse == NULL)
181 DPRINT("Current object can't parse\n");
184 Status = CurrentHeader->ObjectType->Parse(CurrentObject,
188 ObjectAttributes->Attributes);
189 if (Status == STATUS_REPARSE)
191 /* reparse the object path */
192 NextObject = RootObject;
193 current = PathString.Buffer;
195 ObReferenceObjectByPointer(NextObject,
201 if (NextObject == NULL)
205 ObDereferenceObject(CurrentObject);
206 CurrentObject = NextObject;
210 RtlCreateUnicodeString (RemainingPath, current);
211 RtlFreeUnicodeString (&PathString);
212 *ReturnedObject = CurrentObject;
214 return(STATUS_SUCCESS);
218 /**********************************************************************
229 ObCreateObject(OUT PHANDLE Handle,
230 IN ACCESS_MASK DesiredAccess,
231 IN POBJECT_ATTRIBUTES ObjectAttributes,
232 IN POBJECT_TYPE Type,
236 UNICODE_STRING RemainingPath;
237 POBJECT_HEADER Header;
238 POBJECT_HEADER ParentHeader = NULL;
240 BOOLEAN ObjectAttached = FALSE;
242 assert_irql(APC_LEVEL);
244 DPRINT("ObCreateObject(Handle %x, ObjectAttributes %x, Type %x)\n",
245 Handle, ObjectAttributes, Type);
247 if (ObjectAttributes != NULL &&
248 ObjectAttributes->ObjectName != NULL &&
249 ObjectAttributes->ObjectName->Buffer != NULL)
251 Status = ObFindObject(ObjectAttributes,
255 if (!NT_SUCCESS(Status))
257 DPRINT("ObFindObject() failed! (Status 0x%x)\n", Status);
263 RtlInitUnicodeString(&RemainingPath, NULL);
266 RtlMapGenericMask(&DesiredAccess,
269 Header = (POBJECT_HEADER)ExAllocatePoolWithTag(NonPagedPool,
270 OBJECT_ALLOC_SIZE(Type),
272 ObInitializeObject(Header,
280 ParentHeader = BODY_TO_HEADER(Parent);
283 if (ParentHeader != NULL &&
284 ParentHeader->ObjectType == ObDirectoryType &&
285 RemainingPath.Buffer != NULL)
287 ObpAddEntryDirectory(Parent,
289 RemainingPath.Buffer+1);
290 ObjectAttached = TRUE;
293 if ((Header->ObjectType != NULL) &&
294 (Header->ObjectType->Create != NULL))
296 DPRINT("Calling %x\n", Header->ObjectType->Create);
297 Status = Header->ObjectType->Create(HEADER_TO_BODY(Header),
299 RemainingPath.Buffer,
301 if (!NT_SUCCESS(Status))
303 if (ObjectAttached == TRUE)
305 ObpRemoveEntryDirectory(Header);
309 ObDereferenceObject(Parent);
311 RtlFreeUnicodeString(&Header->Name);
312 RtlFreeUnicodeString(&RemainingPath);
317 RtlFreeUnicodeString( &RemainingPath );
321 *Object = HEADER_TO_BODY(Header);
326 ObCreateHandle(PsGetCurrentProcess(),
329 ObjectAttributes && (ObjectAttributes->Attributes & OBJ_INHERIT) ? TRUE : FALSE,
333 return(STATUS_SUCCESS);
338 ObReferenceObjectByPointer(IN PVOID Object,
339 IN ACCESS_MASK DesiredAccess,
340 IN POBJECT_TYPE ObjectType,
341 IN KPROCESSOR_MODE AccessMode)
343 * FUNCTION: Increments the pointer reference count for a given object
345 * ObjectBody = Object's body
346 * DesiredAccess = Desired access to the object
347 * ObjectType = Points to the object type structure
348 * AccessMode = Type of access check to perform
352 POBJECT_HEADER Header;
354 // DPRINT("ObReferenceObjectByPointer(Object %x, ObjectType %x)\n",
355 // Object,ObjectType);
357 Header = BODY_TO_HEADER(Object);
359 if (ObjectType != NULL && Header->ObjectType != ObjectType)
361 DPRINT("Failed %x (type was %x %S) should be %x %S\n",
364 Header->ObjectType->TypeName.Buffer,
366 ObjectType->TypeName.Buffer);
367 return(STATUS_UNSUCCESSFUL);
369 if (Header->ObjectType == PsProcessType)
371 DPRINT("Ref p 0x%x refcount %d type %x ",
372 Object, Header->RefCount, PsProcessType);
373 DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
375 if (Header->ObjectType == PsThreadType)
377 DPRINT("Deref t 0x%x with refcount %d type %x ",
378 Object, Header->RefCount, PsThreadType);
379 DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
382 if (Header->CloseInProcess)
384 return(STATUS_UNSUCCESSFUL);
387 InterlockedIncrement(&Header->RefCount);
389 return(STATUS_SUCCESS);
394 ObOpenObjectByPointer(IN POBJECT Object,
395 IN ULONG HandleAttributes,
396 IN PACCESS_STATE PassedAccessState,
397 IN ACCESS_MASK DesiredAccess,
398 IN POBJECT_TYPE ObjectType,
399 IN KPROCESSOR_MODE AccessMode,
404 DPRINT("ObOpenObjectByPointer()\n");
406 Status = ObReferenceObjectByPointer(Object,
410 if (!NT_SUCCESS(Status))
415 Status = ObCreateHandle(PsGetCurrentProcess(),
418 HandleAttributes & OBJ_INHERIT,
421 ObDereferenceObject(Object);
423 return STATUS_SUCCESS;
428 ObpPerformRetentionChecks(POBJECT_HEADER Header)
430 // DPRINT("ObPerformRetentionChecks(Header %x), RefCount %d, HandleCount %d\n",
431 // Header,Header->RefCount,Header->HandleCount);
433 if (Header->RefCount < 0)
435 CPRINT("Object %x/%x has invalid reference count (%d)\n",
436 Header, HEADER_TO_BODY(Header), Header->RefCount);
439 if (Header->HandleCount < 0)
441 CPRINT("Object %x/%x has invalid handle count (%d)\n",
442 Header, HEADER_TO_BODY(Header), Header->HandleCount);
446 if (Header->RefCount == 0 &&
447 Header->HandleCount == 0 &&
448 Header->Permanent == FALSE)
450 if (Header->CloseInProcess)
453 return STATUS_UNSUCCESSFUL;
455 Header->CloseInProcess = TRUE;
456 if (Header->ObjectType != NULL &&
457 Header->ObjectType->Delete != NULL)
459 Header->ObjectType->Delete(HEADER_TO_BODY(Header));
461 if (Header->Name.Buffer != NULL)
463 ObpRemoveEntryDirectory(Header);
464 RtlFreeUnicodeString(&Header->Name);
466 DPRINT("ObPerformRetentionChecks() = Freeing object\n");
469 return(STATUS_SUCCESS);
473 /**********************************************************************
475 * ObfReferenceObject@4
478 * Increments a given object's reference count and performs
482 * ObjectBody = Body of the object.
488 ObfReferenceObject(IN PVOID Object)
490 POBJECT_HEADER Header;
494 Header = BODY_TO_HEADER(Object);
496 if (Header->CloseInProcess)
500 InterlockedIncrement(&Header->RefCount);
502 ObpPerformRetentionChecks(Header);
506 /**********************************************************************
508 * ObfDereferenceObject@4
511 * Decrements a given object's reference count and performs
515 * ObjectBody = Body of the object.
521 ObfDereferenceObject(IN PVOID Object)
523 POBJECT_HEADER Header;
524 extern POBJECT_TYPE PsProcessType;
528 Header = BODY_TO_HEADER(Object);
530 if (Header->ObjectType == PsProcessType)
532 DPRINT("Deref p 0x%x with refcount %d type %x ",
533 Object, Header->RefCount, PsProcessType);
534 DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
536 if (Header->ObjectType == PsThreadType)
538 DPRINT("Deref t 0x%x with refcount %d type %x ",
539 Object, Header->RefCount, PsThreadType);
540 DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
543 InterlockedDecrement(&Header->RefCount);
545 ObpPerformRetentionChecks(Header);
549 /**********************************************************************
551 * ObGetObjectPointerCount@4
554 * Retrieves the pointer(reference) count of the given object.
557 * ObjectBody = Body of the object.
563 ObGetObjectPointerCount(PVOID Object)
565 POBJECT_HEADER Header;
568 Header = BODY_TO_HEADER(Object);
570 return(Header->RefCount);
574 /**********************************************************************
576 * ObGetObjectHandleCount@4
579 * Retrieves the handle count of the given object.
582 * ObjectBody = Body of the object.
588 ObGetObjectHandleCount(PVOID Object)
590 POBJECT_HEADER Header;
593 Header = BODY_TO_HEADER(Object);
595 return(Header->HandleCount);