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
8 * PROGRAMMERS: David Welch (welch@cwcom.net)
9 * Skywing (skywing@valhallalegends.com)
12 /* INCLUDES *****************************************************************/
16 #include <internal/debug.h>
19 typedef struct _RETENTION_CHECK_PARAMS
21 WORK_QUEUE_ITEM WorkItem
;
22 POBJECT_HEADER ObjectHeader
;
23 } RETENTION_CHECK_PARAMS
, *PRETENTION_CHECK_PARAMS
;
26 /* FUNCTIONS ************************************************************/
28 PVOID
HEADER_TO_BODY(POBJECT_HEADER obj
)
30 return(((char*)obj
)+sizeof(OBJECT_HEADER
)-sizeof(COMMON_BODY_HEADER
));
34 POBJECT_HEADER
BODY_TO_HEADER(PVOID body
)
36 PCOMMON_BODY_HEADER chdr
= (PCOMMON_BODY_HEADER
)body
;
37 return(CONTAINING_RECORD((&(chdr
->Type
)),OBJECT_HEADER
,Type
));
41 ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
42 IN KPROCESSOR_MODE AccessMode
,
43 IN POOL_TYPE PoolType
,
44 IN BOOLEAN CaptureIfKernel
,
45 OUT PCAPTURED_OBJECT_ATTRIBUTES CapturedObjectAttributes OPTIONAL
,
46 OUT PUNICODE_STRING ObjectName OPTIONAL
)
48 OBJECT_ATTRIBUTES AttributesCopy
;
49 NTSTATUS Status
= STATUS_SUCCESS
;
51 /* at least one output parameter must be != NULL! */
52 ASSERT(((ULONG_PTR
)CapturedObjectAttributes
^ (ULONG_PTR
)ObjectName
) != 0);
54 if(ObjectAttributes
== NULL
)
57 if(ObjectName
!= NULL
)
59 RtlInitUnicodeString(ObjectName
, NULL
);
61 if(CapturedObjectAttributes
!= NULL
)
63 RtlZeroMemory(CapturedObjectAttributes
, sizeof(CAPTURED_OBJECT_ATTRIBUTES
));
65 return Status
; /* STATUS_SUCCESS */
68 if(AccessMode
!= KernelMode
)
72 ProbeForRead(ObjectAttributes
,
73 sizeof(ObjectAttributes
),
75 /* make a copy on the stack */
76 AttributesCopy
= *ObjectAttributes
;
80 Status
= _SEH_GetExceptionCode();
84 if(!NT_SUCCESS(Status
))
89 else if(AccessMode
== KernelMode
&& !CaptureIfKernel
)
91 if(ObjectAttributes
->Length
!= sizeof(OBJECT_ATTRIBUTES
))
93 /* we don't have to capture any memory, the caller considers the passed data
95 if(ObjectName
!= NULL
)
97 *ObjectName
= *ObjectAttributes
->ObjectName
;
99 if(CapturedObjectAttributes
!= NULL
)
101 CapturedObjectAttributes
->RootDirectory
= ObjectAttributes
->RootDirectory
;
102 CapturedObjectAttributes
->Attributes
= ObjectAttributes
->Attributes
;
103 CapturedObjectAttributes
->SecurityDescriptor
= ObjectAttributes
->SecurityDescriptor
;
106 return STATUS_SUCCESS
;
110 Status
= STATUS_INVALID_PARAMETER
;
111 goto failbasiccleanup
;
116 AttributesCopy
= *ObjectAttributes
;
119 /* if Length isn't as expected, bail with an invalid parameter status code so
120 the caller knows he passed garbage... */
121 if(AttributesCopy
.Length
!= sizeof(OBJECT_ATTRIBUTES
))
123 Status
= STATUS_INVALID_PARAMETER
;
124 goto failbasiccleanup
;
127 if(CapturedObjectAttributes
!= NULL
)
129 CapturedObjectAttributes
->RootDirectory
= AttributesCopy
.RootDirectory
;
130 CapturedObjectAttributes
->Attributes
= AttributesCopy
.Attributes
;
132 if(AttributesCopy
.SecurityDescriptor
!= NULL
)
134 Status
= SeCaptureSecurityDescriptor(AttributesCopy
.SecurityDescriptor
,
138 &CapturedObjectAttributes
->SecurityDescriptor
);
139 if(!NT_SUCCESS(Status
))
141 DPRINT1("Unable to capture the security descriptor!!!\n");
142 goto failbasiccleanup
;
147 CapturedObjectAttributes
->SecurityDescriptor
= NULL
;
151 if(ObjectName
!= NULL
)
153 if(AttributesCopy
.ObjectName
!= NULL
)
155 UNICODE_STRING OriginalCopy
;
157 if(AccessMode
!= KernelMode
)
161 /* probe the ObjectName structure and make a local stack copy of it */
162 ProbeForRead(AttributesCopy
.ObjectName
,
163 sizeof(UNICODE_STRING
),
165 OriginalCopy
= *AttributesCopy
.ObjectName
;
166 if(OriginalCopy
.Length
> 0)
168 ProbeForRead(OriginalCopy
.Buffer
,
175 Status
= _SEH_GetExceptionCode();
179 if(NT_SUCCESS(Status
))
181 if(OriginalCopy
.Length
> 0)
183 ObjectName
->MaximumLength
= OriginalCopy
.Length
+ sizeof(WCHAR
);
184 ObjectName
->Buffer
= ExAllocatePool(PoolType
,
185 ObjectName
->MaximumLength
);
186 if(ObjectName
->Buffer
!= NULL
)
190 /* no need to probe OriginalCopy.Buffer again, we already did that
191 when capturing the UNICODE_STRING structure itself */
192 RtlCopyMemory(ObjectName
->Buffer
, OriginalCopy
.Buffer
, OriginalCopy
.Length
);
193 ObjectName
->Buffer
[OriginalCopy
.Length
/ sizeof(WCHAR
)] = L
'\0';
197 Status
= _SEH_GetExceptionCode();
203 Status
= STATUS_INSUFFICIENT_RESOURCES
;
206 else if(AttributesCopy
.RootDirectory
!= NULL
/* && OriginalCopy.Length == 0 */)
208 /* if the caller specified a root directory, there must be an object name! */
209 Status
= STATUS_OBJECT_NAME_INVALID
;
214 if(!NT_SUCCESS(Status
))
216 failallocatedcleanup
:
217 if(ObjectName
->Buffer
)
219 ExFreePool(ObjectName
->Buffer
);
221 if(CapturedObjectAttributes
!= NULL
)
223 /* cleanup allocated resources */
224 SeReleaseSecurityDescriptor(CapturedObjectAttributes
->SecurityDescriptor
,
228 goto failbasiccleanup
;
231 else /* AccessMode == KernelMode */
233 OriginalCopy
= *AttributesCopy
.ObjectName
;
235 if(OriginalCopy
.Length
> 0)
237 ObjectName
->MaximumLength
= OriginalCopy
.Length
+ sizeof(WCHAR
);
238 ObjectName
->Buffer
= ExAllocatePool(PoolType
,
239 ObjectName
->MaximumLength
);
240 if(ObjectName
->Buffer
!= NULL
)
242 RtlCopyMemory(ObjectName
->Buffer
, OriginalCopy
.Buffer
, OriginalCopy
.Length
);
243 ObjectName
->Buffer
[OriginalCopy
.Length
/ sizeof(WCHAR
)] = L
'\0';
247 Status
= STATUS_INSUFFICIENT_RESOURCES
;
250 else if(AttributesCopy
.RootDirectory
!= NULL
/* && OriginalCopy.Length == 0 */)
252 /* if the caller specified a root directory, there must be an object name! */
253 Status
= STATUS_OBJECT_NAME_INVALID
;
256 if(!NT_SUCCESS(Status
))
258 goto failallocatedcleanup
;
264 RtlInitUnicodeString(ObjectName
, NULL
);
272 ObpReleaseObjectAttributes(IN PCAPTURED_OBJECT_ATTRIBUTES CapturedObjectAttributes OPTIONAL
,
273 IN PUNICODE_STRING ObjectName OPTIONAL
,
274 IN KPROCESSOR_MODE AccessMode
,
275 IN BOOLEAN CaptureIfKernel
)
277 /* WARNING - You need to pass the same parameters to this function as you passed
278 to ObpCaptureObjectAttributes() to avoid memory leaks */
279 if(AccessMode
!= KernelMode
||
280 (AccessMode
== KernelMode
&& CaptureIfKernel
))
282 if(CapturedObjectAttributes
!= NULL
&&
283 CapturedObjectAttributes
->SecurityDescriptor
!= NULL
)
285 ExFreePool(CapturedObjectAttributes
->SecurityDescriptor
);
286 CapturedObjectAttributes
->SecurityDescriptor
= NULL
;
288 if(ObjectName
!= NULL
&&
289 ObjectName
->Length
> 0)
291 ExFreePool(ObjectName
->Buffer
);
297 /**********************************************************************
309 * Pointer to a unicode string that will contain the
310 * remaining path if the function returns successfully.
311 * The caller must free the buffer after use by calling
312 * RtlFreeUnicodeString ().
315 * Optional pointer to an object type. This is used to
316 * descide if a symbolic link object will be parsed or not.
321 ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes
,
322 PVOID
* ReturnedObject
,
323 PUNICODE_STRING RemainingPath
,
324 POBJECT_TYPE ObjectType
)
329 POBJECT_HEADER CurrentHeader
;
332 UNICODE_STRING PathString
;
334 PUNICODE_STRING ObjectName
;
336 DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, "
337 "RemainingPath %x)\n",ObjectAttributes
,ReturnedObject
,RemainingPath
);
338 DPRINT("ObjectAttributes->ObjectName %wZ\n",
339 ObjectAttributes
->ObjectName
);
341 RtlInitUnicodeString (RemainingPath
, NULL
);
343 if (ObjectAttributes
->RootDirectory
== NULL
)
345 ObReferenceObjectByPointer(NameSpaceRoot
,
349 CurrentObject
= NameSpaceRoot
;
353 Status
= ObReferenceObjectByHandle(ObjectAttributes
->RootDirectory
,
359 if (!NT_SUCCESS(Status
))
365 ObjectName
= ObjectAttributes
->ObjectName
;
366 if (ObjectName
->Length
== 0 ||
367 ObjectName
->Buffer
[0] == UNICODE_NULL
)
369 *ReturnedObject
= CurrentObject
;
370 return STATUS_SUCCESS
;
373 if (ObjectAttributes
->RootDirectory
== NULL
&&
374 ObjectName
->Buffer
[0] != L
'\\')
376 ObDereferenceObject (CurrentObject
);
377 return STATUS_UNSUCCESSFUL
;
380 /* Create a zero-terminated copy of the object name */
381 PathString
.Length
= ObjectName
->Length
;
382 PathString
.MaximumLength
= ObjectName
->Length
+ sizeof(WCHAR
);
383 PathString
.Buffer
= ExAllocatePool (NonPagedPool
,
384 PathString
.MaximumLength
);
385 if (PathString
.Buffer
== NULL
)
387 ObDereferenceObject (CurrentObject
);
388 return STATUS_INSUFFICIENT_RESOURCES
;
391 RtlCopyMemory (PathString
.Buffer
,
394 PathString
.Buffer
[PathString
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
396 current
= PathString
.Buffer
;
398 RootObject
= CurrentObject
;
399 Attributes
= ObjectAttributes
->Attributes
;
400 if (ObjectType
== ObSymbolicLinkType
)
401 Attributes
|= OBJ_OPENLINK
;
405 DPRINT("current %S\n",current
);
406 CurrentHeader
= BODY_TO_HEADER(CurrentObject
);
408 DPRINT("Current ObjectType %wZ\n",
409 &CurrentHeader
->ObjectType
->TypeName
);
411 if (CurrentHeader
->ObjectType
->Parse
== NULL
)
413 DPRINT("Current object can't parse\n");
416 Status
= CurrentHeader
->ObjectType
->Parse(CurrentObject
,
421 if (Status
== STATUS_REPARSE
)
423 /* reparse the object path */
424 NextObject
= NameSpaceRoot
;
425 current
= PathString
.Buffer
;
427 ObReferenceObjectByPointer(NextObject
,
433 if (NextObject
== NULL
)
437 ObDereferenceObject(CurrentObject
);
438 CurrentObject
= NextObject
;
442 RtlCreateUnicodeString (RemainingPath
, current
);
443 RtlFreeUnicodeString (&PathString
);
444 *ReturnedObject
= CurrentObject
;
446 return STATUS_SUCCESS
;
450 /**********************************************************************
452 * ObQueryNameString@16
463 ObQueryNameString (IN PVOID Object
,
464 OUT POBJECT_NAME_INFORMATION ObjectNameInfo
,
466 OUT PULONG ReturnLength
)
468 POBJECT_NAME_INFORMATION LocalInfo
;
469 POBJECT_HEADER ObjectHeader
;
470 ULONG LocalReturnLength
;
475 if (Length
< sizeof(OBJECT_NAME_INFORMATION
) + sizeof(WCHAR
))
476 return STATUS_INVALID_BUFFER_SIZE
;
478 ObjectNameInfo
->Name
.MaximumLength
= (USHORT
)(Length
- sizeof(OBJECT_NAME_INFORMATION
));
479 ObjectNameInfo
->Name
.Length
= 0;
480 ObjectNameInfo
->Name
.Buffer
=
481 (PWCHAR
)((ULONG_PTR
)ObjectNameInfo
+ sizeof(OBJECT_NAME_INFORMATION
));
482 ObjectNameInfo
->Name
.Buffer
[0] = 0;
484 ObjectHeader
= BODY_TO_HEADER(Object
);
486 if (ObjectHeader
->ObjectType
!= NULL
&&
487 ObjectHeader
->ObjectType
->QueryName
!= NULL
)
489 DPRINT ("Calling %x\n", ObjectHeader
->ObjectType
->QueryName
);
490 Status
= ObjectHeader
->ObjectType
->QueryName (Object
,
495 else if (ObjectHeader
->Name
.Length
> 0 && ObjectHeader
->Name
.Buffer
!= NULL
)
497 DPRINT ("Object does not have a 'QueryName' function\n");
499 if (ObjectHeader
->Parent
== NameSpaceRoot
)
501 DPRINT ("Reached the root directory\n");
502 ObjectNameInfo
->Name
.Length
= 0;
503 ObjectNameInfo
->Name
.Buffer
[0] = 0;
504 Status
= STATUS_SUCCESS
;
506 else if (ObjectHeader
->Parent
!= NULL
)
508 LocalInfo
= ExAllocatePool (NonPagedPool
,
509 sizeof(OBJECT_NAME_INFORMATION
) +
510 MAX_PATH
* sizeof(WCHAR
));
511 if (LocalInfo
== NULL
)
512 return STATUS_INSUFFICIENT_RESOURCES
;
514 Status
= ObQueryNameString (ObjectHeader
->Parent
,
516 MAX_PATH
* sizeof(WCHAR
),
518 if (!NT_SUCCESS (Status
))
520 ExFreePool (LocalInfo
);
524 Status
= RtlAppendUnicodeStringToString (&ObjectNameInfo
->Name
,
527 ExFreePool (LocalInfo
);
529 if (!NT_SUCCESS (Status
))
533 DPRINT ("Object path %wZ\n", &ObjectHeader
->Name
);
534 Status
= RtlAppendUnicodeToString (&ObjectNameInfo
->Name
,
536 if (!NT_SUCCESS (Status
))
539 Status
= RtlAppendUnicodeStringToString (&ObjectNameInfo
->Name
,
540 &ObjectHeader
->Name
);
544 DPRINT ("Object is unnamed\n");
546 ObjectNameInfo
->Name
.MaximumLength
= 0;
547 ObjectNameInfo
->Name
.Length
= 0;
548 ObjectNameInfo
->Name
.Buffer
= NULL
;
550 Status
= STATUS_SUCCESS
;
553 if (NT_SUCCESS (Status
))
555 ObjectNameInfo
->Name
.MaximumLength
=
556 (ObjectNameInfo
->Name
.Length
) ? ObjectNameInfo
->Name
.Length
+ sizeof(WCHAR
) : 0;
558 sizeof(OBJECT_NAME_INFORMATION
) + ObjectNameInfo
->Name
.MaximumLength
;
559 DPRINT ("Returned object path: %wZ\n", &ObjectNameInfo
->Name
);
566 /**********************************************************************
580 ObCreateObject (IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL
,
581 IN POBJECT_TYPE Type
,
582 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
583 IN KPROCESSOR_MODE AccessMode
,
584 IN OUT PVOID ParseContext OPTIONAL
,
586 IN ULONG PagedPoolCharge OPTIONAL
,
587 IN ULONG NonPagedPoolCharge OPTIONAL
,
591 UNICODE_STRING RemainingPath
;
592 POBJECT_HEADER Header
;
593 POBJECT_HEADER ParentHeader
= NULL
;
595 BOOLEAN ObjectAttached
= FALSE
;
597 PSECURITY_DESCRIPTOR NewSecurityDescriptor
= NULL
;
598 SECURITY_SUBJECT_CONTEXT SubjectContext
;
600 ASSERT_IRQL(APC_LEVEL
);
602 if(ObjectAttributesAccessMode
== UserMode
&& ObjectAttributes
!= NULL
)
604 Status
= STATUS_SUCCESS
;
607 ProbeForRead(ObjectAttributes
,
608 sizeof(OBJECT_ATTRIBUTES
),
613 Status
= _SEH_GetExceptionCode();
617 if(!NT_SUCCESS(Status
))
623 DPRINT("ObCreateObject(Type %p ObjectAttributes %p, Object %p)\n",
624 Type
, ObjectAttributes
, Object
);
628 DPRINT1("Invalid object type!\n");
629 return STATUS_INVALID_PARAMETER
;
632 if (ObjectAttributes
!= NULL
&&
633 ObjectAttributes
->ObjectName
!= NULL
&&
634 ObjectAttributes
->ObjectName
->Buffer
!= NULL
)
636 Status
= ObFindObject(ObjectAttributes
,
640 if (!NT_SUCCESS(Status
))
642 DPRINT1("ObFindObject() failed! (Status 0x%x)\n", Status
);
648 RtlInitUnicodeString(&RemainingPath
, NULL
);
651 Header
= (POBJECT_HEADER
)ExAllocatePoolWithTag(NonPagedPool
,
652 OBJECT_ALLOC_SIZE(ObjectSize
),
654 if (Header
== NULL
) {
655 DPRINT1("Not enough memory!\n");
656 return STATUS_INSUFFICIENT_RESOURCES
;
659 RtlZeroMemory(Header
, OBJECT_ALLOC_SIZE(ObjectSize
));
661 /* Initialize the object header */
662 DPRINT("Initalizing header\n");
663 Header
->HandleCount
= 0;
664 Header
->RefCount
= 1;
665 Header
->ObjectType
= Type
;
666 if (ObjectAttributes
!= NULL
&&
667 ObjectAttributes
->Attributes
& OBJ_PERMANENT
)
669 Header
->Permanent
= TRUE
;
673 Header
->Permanent
= FALSE
;
676 if (ObjectAttributes
!= NULL
&&
677 ObjectAttributes
->Attributes
& OBJ_INHERIT
)
679 Header
->Inherit
= TRUE
;
683 Header
->Inherit
= FALSE
;
686 RtlInitUnicodeString(&(Header
->Name
),NULL
);
688 DPRINT("Getting Parent and adding entry\n");
691 ParentHeader
= BODY_TO_HEADER(Parent
);
694 if (ParentHeader
!= NULL
&&
695 ParentHeader
->ObjectType
== ObDirectoryType
&&
696 RemainingPath
.Buffer
!= NULL
)
698 NamePtr
= RemainingPath
.Buffer
;
699 if (*NamePtr
== L
'\\')
702 ObpAddEntryDirectory(Parent
,
706 ObjectAttached
= TRUE
;
709 DPRINT("About to call Create Routine\n");
710 if (Header
->ObjectType
->Create
!= NULL
)
712 DPRINT("Calling %x\n", Header
->ObjectType
->Create
);
713 Status
= Header
->ObjectType
->Create(HEADER_TO_BODY(Header
),
715 RemainingPath
.Buffer
,
717 if (!NT_SUCCESS(Status
))
719 if (ObjectAttached
== TRUE
)
721 ObpRemoveEntryDirectory(Header
);
725 ObDereferenceObject(Parent
);
727 RtlFreeUnicodeString(&Header
->Name
);
728 RtlFreeUnicodeString(&RemainingPath
);
730 DPRINT("Create Failed\n");
734 RtlFreeUnicodeString(&RemainingPath
);
736 SeCaptureSubjectContext(&SubjectContext
);
738 DPRINT("Security Assignment in progress\n");
739 /* Build the new security descriptor */
740 Status
= SeAssignSecurity((ParentHeader
!= NULL
) ? ParentHeader
->SecurityDescriptor
: NULL
,
741 (ObjectAttributes
!= NULL
) ? ObjectAttributes
->SecurityDescriptor
: NULL
,
742 &NewSecurityDescriptor
,
743 (Header
->ObjectType
== ObDirectoryType
),
745 Header
->ObjectType
->Mapping
,
747 if (NT_SUCCESS(Status
))
749 DPRINT("NewSecurityDescriptor %p\n", NewSecurityDescriptor
);
751 if (Header
->ObjectType
->Security
!= NULL
)
753 /* Call the security method */
754 Status
= Header
->ObjectType
->Security(HEADER_TO_BODY(Header
),
755 AssignSecurityDescriptor
,
757 NewSecurityDescriptor
,
762 /* Assign the security descriptor to the object header */
763 Status
= ObpAddSecurityDescriptor(NewSecurityDescriptor
,
764 &Header
->SecurityDescriptor
);
765 DPRINT("Object security descriptor %p\n", Header
->SecurityDescriptor
);
768 /* Release the new security descriptor */
769 SeDeassignSecurity(&NewSecurityDescriptor
);
772 DPRINT("Security Complete\n");
773 SeReleaseSubjectContext(&SubjectContext
);
777 *Object
= HEADER_TO_BODY(Header
);
781 return STATUS_SUCCESS
;
786 * FUNCTION: Increments the pointer reference count for a given object
788 * ObjectBody = Object's body
789 * DesiredAccess = Desired access to the object
790 * ObjectType = Points to the object type structure
791 * AccessMode = Type of access check to perform
797 ObReferenceObjectByPointer(IN PVOID Object
,
798 IN ACCESS_MASK DesiredAccess
,
799 IN POBJECT_TYPE ObjectType
,
800 IN KPROCESSOR_MODE AccessMode
)
802 POBJECT_HEADER Header
;
804 DPRINT("ObReferenceObjectByPointer(Object %x, ObjectType %x)\n",
807 Header
= BODY_TO_HEADER(Object
);
809 if (ObjectType
!= NULL
&& Header
->ObjectType
!= ObjectType
)
811 DPRINT("Failed %x (type was %x %S) should be %x %S\n",
814 Header
->ObjectType
->TypeName
.Buffer
,
816 ObjectType
->TypeName
.Buffer
);
817 return(STATUS_UNSUCCESSFUL
);
819 if (Header
->ObjectType
== PsProcessType
)
821 DPRINT("Ref p 0x%x refcount %d type %x ",
822 Object
, Header
->RefCount
, PsProcessType
);
823 DPRINT("eip %x\n", ((PULONG
)&Object
)[-1]);
825 if (Header
->ObjectType
== PsThreadType
)
827 DPRINT("Deref t 0x%x with refcount %d type %x ",
828 Object
, Header
->RefCount
, PsThreadType
);
829 DPRINT("eip %x\n", ((PULONG
)&Object
)[-1]);
832 if (Header
->CloseInProcess
)
834 if (Header
->ObjectType
== PsProcessType
)
836 return STATUS_PROCESS_IS_TERMINATING
;
838 if (Header
->ObjectType
== PsThreadType
)
840 return STATUS_THREAD_IS_TERMINATING
;
842 return(STATUS_UNSUCCESSFUL
);
845 InterlockedIncrement(&Header
->RefCount
);
847 return(STATUS_SUCCESS
);
855 ObOpenObjectByPointer(IN POBJECT Object
,
856 IN ULONG HandleAttributes
,
857 IN PACCESS_STATE PassedAccessState
,
858 IN ACCESS_MASK DesiredAccess
,
859 IN POBJECT_TYPE ObjectType
,
860 IN KPROCESSOR_MODE AccessMode
,
865 DPRINT("ObOpenObjectByPointer()\n");
867 Status
= ObReferenceObjectByPointer(Object
,
871 if (!NT_SUCCESS(Status
))
876 Status
= ObCreateHandle(PsGetCurrentProcess(),
879 (BOOLEAN
)(HandleAttributes
& OBJ_INHERIT
),
882 ObDereferenceObject(Object
);
884 return STATUS_SUCCESS
;
889 ObpDeleteObject(POBJECT_HEADER Header
)
891 DPRINT("ObpDeleteObject(Header %p)\n", Header
);
892 if (KeGetCurrentIrql() != PASSIVE_LEVEL
)
894 DPRINT("ObpDeleteObject called at an unsupported IRQL. Use ObpDeleteObjectDpcLevel instead.\n");
898 if (Header
->SecurityDescriptor
!= NULL
)
900 ObpRemoveSecurityDescriptor(Header
->SecurityDescriptor
);
903 if (Header
->ObjectType
!= NULL
&&
904 Header
->ObjectType
->Delete
!= NULL
)
906 Header
->ObjectType
->Delete(HEADER_TO_BODY(Header
));
909 if (Header
->Name
.Buffer
!= NULL
)
911 ObpRemoveEntryDirectory(Header
);
912 RtlFreeUnicodeString(&Header
->Name
);
915 DPRINT("ObPerformRetentionChecks() = Freeing object\n");
918 return(STATUS_SUCCESS
);
923 ObpDeleteObjectWorkRoutine (IN PVOID Parameter
)
925 PRETENTION_CHECK_PARAMS Params
= (PRETENTION_CHECK_PARAMS
)Parameter
;
926 /* ULONG Tag; */ /* See below */
929 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
); /* We need PAGED_CODE somewhere... */
931 /* Turn this on when we have ExFreePoolWithTag
932 Tag = Params->ObjectHeader->ObjectType->Tag; */
933 ObpDeleteObject(Params
->ObjectHeader
);
935 /* ExFreePoolWithTag(Params, Tag); */
940 ObpDeleteObjectDpcLevel(IN POBJECT_HEADER ObjectHeader
,
943 if (ObjectHeader
->RefCount
< 0)
945 CPRINT("Object %p/%p has invalid reference count (%d)\n",
946 ObjectHeader
, HEADER_TO_BODY(ObjectHeader
),
947 ObjectHeader
->RefCount
);
951 if (ObjectHeader
->HandleCount
< 0)
953 CPRINT("Object %p/%p has invalid handle count (%d)\n",
954 ObjectHeader
, HEADER_TO_BODY(ObjectHeader
),
955 ObjectHeader
->HandleCount
);
959 if (ObjectHeader
->CloseInProcess
)
962 return STATUS_UNSUCCESSFUL
;
964 ObjectHeader
->CloseInProcess
= TRUE
;
966 switch (KeGetCurrentIrql ())
969 return ObpDeleteObject (ObjectHeader
);
974 PRETENTION_CHECK_PARAMS Params
;
977 We use must succeed pool here because if the allocation fails
980 Params
= (PRETENTION_CHECK_PARAMS
)
981 ExAllocatePoolWithTag(NonPagedPoolMustSucceed
,
982 sizeof(RETENTION_CHECK_PARAMS
),
983 ObjectHeader
->ObjectType
->Tag
);
984 Params
->ObjectHeader
= ObjectHeader
;
985 ExInitializeWorkItem(&Params
->WorkItem
,
986 ObpDeleteObjectWorkRoutine
,
988 ExQueueWorkItem(&Params
->WorkItem
,
991 return STATUS_PENDING
;
994 DPRINT("ObpDeleteObjectDpcLevel called at unsupported "
995 "IRQL %u!\n", KeGetCurrentIrql());
997 return STATUS_UNSUCCESSFUL
;
1000 return STATUS_SUCCESS
;
1004 /**********************************************************************
1006 * ObfReferenceObject@4
1009 * Increments a given object's reference count and performs
1013 * ObjectBody = Body of the object.
1021 ObfReferenceObject(IN PVOID Object
)
1023 POBJECT_HEADER Header
;
1027 Header
= BODY_TO_HEADER(Object
);
1029 /* No one should be referencing an object once we are deleting it. */
1030 if (Header
->CloseInProcess
)
1035 (VOID
)InterlockedIncrement(&Header
->RefCount
);
1039 /**********************************************************************
1041 * ObfDereferenceObject@4
1044 * Decrements a given object's reference count and performs
1048 * ObjectBody = Body of the object.
1056 ObfDereferenceObject(IN PVOID Object
)
1058 POBJECT_HEADER Header
;
1065 /* Extract the object header. */
1066 Header
= BODY_TO_HEADER(Object
);
1067 Permanent
= Header
->Permanent
;
1068 HandleCount
= Header
->HandleCount
;
1071 Drop our reference and get the new count so we can tell if this was the
1074 NewRefCount
= InterlockedDecrement(&Header
->RefCount
);
1075 ASSERT(NewRefCount
>= 0);
1077 /* Check whether the object can now be deleted. */
1078 if (NewRefCount
== 0 &&
1082 ObpDeleteObjectDpcLevel(Header
, NewRefCount
);
1087 /**********************************************************************
1089 * ObGetObjectPointerCount@4
1092 * Retrieves the pointer(reference) count of the given object.
1095 * ObjectBody = Body of the object.
1103 ObGetObjectPointerCount(PVOID Object
)
1105 POBJECT_HEADER Header
;
1108 Header
= BODY_TO_HEADER(Object
);
1110 return Header
->RefCount
;
1114 /**********************************************************************
1116 * ObGetObjectHandleCount@4
1119 * Retrieves the handle count of the given object.
1122 * ObjectBody = Body of the object.
1128 ObGetObjectHandleCount(PVOID Object
)
1130 POBJECT_HEADER Header
;
1133 Header
= BODY_TO_HEADER(Object
);
1135 return Header
->HandleCount
;
1139 /**********************************************************************
1141 * ObDereferenceObject@4
1144 * Decrements a given object's reference count and performs
1148 * ObjectBody = Body of the object.
1156 #ifdef ObDereferenceObject
1157 #undef ObDereferenceObject
1161 ObDereferenceObject(IN PVOID Object
)
1163 ObfDereferenceObject(Object
);