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 * PROGRAMMERS David Welch (welch@cwcom.net), Skywing (skywing@valhallalegends.com)
10 * 09/13/03: Fixed various ObXxx routines to not call retention
11 * checks directly at a raised IRQL.
14 /* INCLUDES *****************************************************************/
18 #include <internal/debug.h>
21 typedef struct _RETENTION_CHECK_PARAMS
23 WORK_QUEUE_ITEM WorkItem
;
24 POBJECT_HEADER ObjectHeader
;
25 } RETENTION_CHECK_PARAMS
, *PRETENTION_CHECK_PARAMS
;
28 /* FUNCTIONS ************************************************************/
30 PVOID
HEADER_TO_BODY(POBJECT_HEADER obj
)
32 return(((char*)obj
)+sizeof(OBJECT_HEADER
)-sizeof(COMMON_BODY_HEADER
));
36 POBJECT_HEADER
BODY_TO_HEADER(PVOID body
)
38 PCOMMON_BODY_HEADER chdr
= (PCOMMON_BODY_HEADER
)body
;
39 return(CONTAINING_RECORD((&(chdr
->Type
)),OBJECT_HEADER
,Type
));
43 ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
44 IN KPROCESSOR_MODE AccessMode
,
45 IN POOL_TYPE PoolType
,
46 IN BOOLEAN CaptureIfKernel
,
47 OUT PCAPTURED_OBJECT_ATTRIBUTES CapturedObjectAttributes OPTIONAL
,
48 OUT PUNICODE_STRING ObjectName OPTIONAL
)
50 OBJECT_ATTRIBUTES AttributesCopy
;
51 NTSTATUS Status
= STATUS_SUCCESS
;
53 /* at least one output parameter must be != NULL! */
54 ASSERT(((ULONG_PTR
)CapturedObjectAttributes
^ (ULONG_PTR
)ObjectName
) != 0);
56 if(ObjectAttributes
== NULL
)
59 if(ObjectName
!= NULL
)
61 RtlInitUnicodeString(ObjectName
, NULL
);
63 if(CapturedObjectAttributes
!= NULL
)
65 RtlZeroMemory(CapturedObjectAttributes
, sizeof(CAPTURED_OBJECT_ATTRIBUTES
));
67 return Status
; /* STATUS_SUCCESS */
70 if(AccessMode
!= KernelMode
)
74 ProbeForRead(ObjectAttributes
,
75 sizeof(ObjectAttributes
),
77 /* make a copy on the stack */
78 AttributesCopy
= *ObjectAttributes
;
82 Status
= _SEH_GetExceptionCode();
86 if(!NT_SUCCESS(Status
))
91 else if(AccessMode
== KernelMode
&& !CaptureIfKernel
)
93 if(ObjectAttributes
->Length
!= sizeof(OBJECT_ATTRIBUTES
))
95 /* we don't have to capture any memory, the caller considers the passed data
97 if(ObjectName
!= NULL
)
99 *ObjectName
= *ObjectAttributes
->ObjectName
;
101 if(CapturedObjectAttributes
!= NULL
)
103 CapturedObjectAttributes
->RootDirectory
= ObjectAttributes
->RootDirectory
;
104 CapturedObjectAttributes
->Attributes
= ObjectAttributes
->Attributes
;
105 CapturedObjectAttributes
->SecurityDescriptor
= ObjectAttributes
->SecurityDescriptor
;
108 return STATUS_SUCCESS
;
112 Status
= STATUS_INVALID_PARAMETER
;
113 goto failbasiccleanup
;
118 AttributesCopy
= *ObjectAttributes
;
121 /* if Length isn't as expected, bail with an invalid parameter status code so
122 the caller knows he passed garbage... */
123 if(AttributesCopy
.Length
!= sizeof(OBJECT_ATTRIBUTES
))
125 Status
= STATUS_INVALID_PARAMETER
;
126 goto failbasiccleanup
;
129 if(CapturedObjectAttributes
!= NULL
)
131 CapturedObjectAttributes
->RootDirectory
= AttributesCopy
.RootDirectory
;
132 CapturedObjectAttributes
->Attributes
= AttributesCopy
.Attributes
;
134 if(AttributesCopy
.SecurityDescriptor
!= NULL
)
136 Status
= SeCaptureSecurityDescriptor(AttributesCopy
.SecurityDescriptor
,
140 &CapturedObjectAttributes
->SecurityDescriptor
);
141 if(!NT_SUCCESS(Status
))
143 DPRINT1("Unable to capture the security descriptor!!!\n");
144 goto failbasiccleanup
;
149 CapturedObjectAttributes
->SecurityDescriptor
= NULL
;
153 if(ObjectName
!= NULL
)
155 if(AttributesCopy
.ObjectName
!= NULL
)
157 UNICODE_STRING OriginalCopy
;
159 if(AccessMode
!= KernelMode
)
163 /* probe the ObjectName structure and make a local stack copy of it */
164 ProbeForRead(AttributesCopy
.ObjectName
,
165 sizeof(UNICODE_STRING
),
167 OriginalCopy
= *AttributesCopy
.ObjectName
;
168 if(OriginalCopy
.Length
> 0)
170 ProbeForRead(OriginalCopy
.Buffer
,
177 Status
= _SEH_GetExceptionCode();
181 if(NT_SUCCESS(Status
))
183 if(OriginalCopy
.Length
> 0)
185 ObjectName
->MaximumLength
= OriginalCopy
.Length
+ sizeof(WCHAR
);
186 ObjectName
->Buffer
= ExAllocatePool(PoolType
,
187 ObjectName
->MaximumLength
);
188 if(ObjectName
->Buffer
!= NULL
)
192 /* no need to probe OriginalCopy.Buffer again, we already did that
193 when capturing the UNICODE_STRING structure itself */
194 RtlCopyMemory(ObjectName
->Buffer
, OriginalCopy
.Buffer
, OriginalCopy
.Length
);
195 ObjectName
->Buffer
[OriginalCopy
.Length
/ sizeof(WCHAR
)] = L
'\0';
199 Status
= _SEH_GetExceptionCode();
205 Status
= STATUS_INSUFFICIENT_RESOURCES
;
208 else if(AttributesCopy
.RootDirectory
!= NULL
/* && OriginalCopy.Length == 0 */)
210 /* if the caller specified a root directory, there must be an object name! */
211 Status
= STATUS_OBJECT_NAME_INVALID
;
216 if(!NT_SUCCESS(Status
))
218 failallocatedcleanup
:
219 if(ObjectName
->Buffer
)
221 ExFreePool(ObjectName
->Buffer
);
223 if(CapturedObjectAttributes
!= NULL
)
225 /* cleanup allocated resources */
226 SeReleaseSecurityDescriptor(CapturedObjectAttributes
->SecurityDescriptor
,
230 goto failbasiccleanup
;
233 else /* AccessMode == KernelMode */
235 OriginalCopy
= *AttributesCopy
.ObjectName
;
237 if(OriginalCopy
.Length
> 0)
239 ObjectName
->MaximumLength
= OriginalCopy
.Length
+ sizeof(WCHAR
);
240 ObjectName
->Buffer
= ExAllocatePool(PoolType
,
241 ObjectName
->MaximumLength
);
242 if(ObjectName
->Buffer
!= NULL
)
244 RtlCopyMemory(ObjectName
->Buffer
, OriginalCopy
.Buffer
, OriginalCopy
.Length
);
245 ObjectName
->Buffer
[OriginalCopy
.Length
/ sizeof(WCHAR
)] = L
'\0';
249 Status
= STATUS_INSUFFICIENT_RESOURCES
;
252 else if(AttributesCopy
.RootDirectory
!= NULL
/* && OriginalCopy.Length == 0 */)
254 /* if the caller specified a root directory, there must be an object name! */
255 Status
= STATUS_OBJECT_NAME_INVALID
;
258 if(!NT_SUCCESS(Status
))
260 goto failallocatedcleanup
;
266 RtlInitUnicodeString(ObjectName
, NULL
);
274 ObpReleaseObjectAttributes(IN PCAPTURED_OBJECT_ATTRIBUTES CapturedObjectAttributes OPTIONAL
,
275 IN PUNICODE_STRING ObjectName OPTIONAL
,
276 IN KPROCESSOR_MODE AccessMode
,
277 IN BOOLEAN CaptureIfKernel
)
279 /* WARNING - You need to pass the same parameters to this function as you passed
280 to ObpCaptureObjectAttributes() to avoid memory leaks */
281 if(AccessMode
!= KernelMode
||
282 (AccessMode
== KernelMode
&& CaptureIfKernel
))
284 if(CapturedObjectAttributes
!= NULL
&&
285 CapturedObjectAttributes
->SecurityDescriptor
!= NULL
)
287 ExFreePool(CapturedObjectAttributes
->SecurityDescriptor
);
288 CapturedObjectAttributes
->SecurityDescriptor
= NULL
;
290 if(ObjectName
!= NULL
&&
291 ObjectName
->Length
> 0)
293 ExFreePool(ObjectName
->Buffer
);
299 /**********************************************************************
311 * Pointer to a unicode string that will contain the
312 * remaining path if the function returns successfully.
313 * The caller must free the buffer after use by calling
314 * RtlFreeUnicodeString ().
317 * Optional pointer to an object type. This is used to
318 * descide if a symbolic link object will be parsed or not.
323 ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes
,
324 PVOID
* ReturnedObject
,
325 PUNICODE_STRING RemainingPath
,
326 POBJECT_TYPE ObjectType
)
331 POBJECT_HEADER CurrentHeader
;
334 UNICODE_STRING PathString
;
336 PUNICODE_STRING ObjectName
;
338 DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, "
339 "RemainingPath %x)\n",ObjectAttributes
,ReturnedObject
,RemainingPath
);
340 DPRINT("ObjectAttributes->ObjectName %wZ\n",
341 ObjectAttributes
->ObjectName
);
343 RtlInitUnicodeString (RemainingPath
, NULL
);
345 if (ObjectAttributes
->RootDirectory
== NULL
)
347 ObReferenceObjectByPointer(NameSpaceRoot
,
351 CurrentObject
= NameSpaceRoot
;
355 Status
= ObReferenceObjectByHandle(ObjectAttributes
->RootDirectory
,
361 if (!NT_SUCCESS(Status
))
367 ObjectName
= ObjectAttributes
->ObjectName
;
368 if (ObjectName
->Length
== 0 ||
369 ObjectName
->Buffer
[0] == UNICODE_NULL
)
371 *ReturnedObject
= CurrentObject
;
372 return STATUS_SUCCESS
;
375 if (ObjectAttributes
->RootDirectory
== NULL
&&
376 ObjectName
->Buffer
[0] != L
'\\')
378 ObDereferenceObject (CurrentObject
);
379 return STATUS_UNSUCCESSFUL
;
382 /* Create a zero-terminated copy of the object name */
383 PathString
.Length
= ObjectName
->Length
;
384 PathString
.MaximumLength
= ObjectName
->Length
+ sizeof(WCHAR
);
385 PathString
.Buffer
= ExAllocatePool (NonPagedPool
,
386 PathString
.MaximumLength
);
387 if (PathString
.Buffer
== NULL
)
389 ObDereferenceObject (CurrentObject
);
390 return STATUS_INSUFFICIENT_RESOURCES
;
393 RtlCopyMemory (PathString
.Buffer
,
396 PathString
.Buffer
[PathString
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
398 current
= PathString
.Buffer
;
400 RootObject
= CurrentObject
;
401 Attributes
= ObjectAttributes
->Attributes
;
402 if (ObjectType
== ObSymbolicLinkType
)
403 Attributes
|= OBJ_OPENLINK
;
407 DPRINT("current %S\n",current
);
408 CurrentHeader
= BODY_TO_HEADER(CurrentObject
);
410 DPRINT("Current ObjectType %wZ\n",
411 &CurrentHeader
->ObjectType
->TypeName
);
413 if (CurrentHeader
->ObjectType
->Parse
== NULL
)
415 DPRINT("Current object can't parse\n");
418 Status
= CurrentHeader
->ObjectType
->Parse(CurrentObject
,
423 if (Status
== STATUS_REPARSE
)
425 /* reparse the object path */
426 NextObject
= NameSpaceRoot
;
427 current
= PathString
.Buffer
;
429 ObReferenceObjectByPointer(NextObject
,
435 if (NextObject
== NULL
)
439 ObDereferenceObject(CurrentObject
);
440 CurrentObject
= NextObject
;
444 RtlCreateUnicodeString (RemainingPath
, current
);
445 RtlFreeUnicodeString (&PathString
);
446 *ReturnedObject
= CurrentObject
;
448 return STATUS_SUCCESS
;
452 /**********************************************************************
454 * ObQueryNameString@16
465 ObQueryNameString (IN PVOID Object
,
466 OUT POBJECT_NAME_INFORMATION ObjectNameInfo
,
468 OUT PULONG ReturnLength
)
470 POBJECT_NAME_INFORMATION LocalInfo
;
471 POBJECT_HEADER ObjectHeader
;
472 ULONG LocalReturnLength
;
477 if (Length
< sizeof(OBJECT_NAME_INFORMATION
) + sizeof(WCHAR
))
478 return STATUS_INVALID_BUFFER_SIZE
;
480 ObjectNameInfo
->Name
.MaximumLength
= (USHORT
)(Length
- sizeof(OBJECT_NAME_INFORMATION
));
481 ObjectNameInfo
->Name
.Length
= 0;
482 ObjectNameInfo
->Name
.Buffer
=
483 (PWCHAR
)((ULONG_PTR
)ObjectNameInfo
+ sizeof(OBJECT_NAME_INFORMATION
));
484 ObjectNameInfo
->Name
.Buffer
[0] = 0;
486 ObjectHeader
= BODY_TO_HEADER(Object
);
488 if (ObjectHeader
->ObjectType
!= NULL
&&
489 ObjectHeader
->ObjectType
->QueryName
!= NULL
)
491 DPRINT ("Calling %x\n", ObjectHeader
->ObjectType
->QueryName
);
492 Status
= ObjectHeader
->ObjectType
->QueryName (Object
,
497 else if (ObjectHeader
->Name
.Length
> 0 && ObjectHeader
->Name
.Buffer
!= NULL
)
499 DPRINT ("Object does not have a 'QueryName' function\n");
501 if (ObjectHeader
->Parent
== NameSpaceRoot
)
503 DPRINT ("Reached the root directory\n");
504 ObjectNameInfo
->Name
.Length
= 0;
505 ObjectNameInfo
->Name
.Buffer
[0] = 0;
506 Status
= STATUS_SUCCESS
;
508 else if (ObjectHeader
->Parent
!= NULL
)
510 LocalInfo
= ExAllocatePool (NonPagedPool
,
511 sizeof(OBJECT_NAME_INFORMATION
) +
512 MAX_PATH
* sizeof(WCHAR
));
513 if (LocalInfo
== NULL
)
514 return STATUS_INSUFFICIENT_RESOURCES
;
516 Status
= ObQueryNameString (ObjectHeader
->Parent
,
518 MAX_PATH
* sizeof(WCHAR
),
520 if (!NT_SUCCESS (Status
))
522 ExFreePool (LocalInfo
);
526 Status
= RtlAppendUnicodeStringToString (&ObjectNameInfo
->Name
,
529 ExFreePool (LocalInfo
);
531 if (!NT_SUCCESS (Status
))
535 DPRINT ("Object path %wZ\n", &ObjectHeader
->Name
);
536 Status
= RtlAppendUnicodeToString (&ObjectNameInfo
->Name
,
538 if (!NT_SUCCESS (Status
))
541 Status
= RtlAppendUnicodeStringToString (&ObjectNameInfo
->Name
,
542 &ObjectHeader
->Name
);
546 DPRINT ("Object is unnamed\n");
548 ObjectNameInfo
->Name
.MaximumLength
= 0;
549 ObjectNameInfo
->Name
.Length
= 0;
550 ObjectNameInfo
->Name
.Buffer
= NULL
;
552 Status
= STATUS_SUCCESS
;
555 if (NT_SUCCESS (Status
))
557 ObjectNameInfo
->Name
.MaximumLength
=
558 (ObjectNameInfo
->Name
.Length
) ? ObjectNameInfo
->Name
.Length
+ sizeof(WCHAR
) : 0;
560 sizeof(OBJECT_NAME_INFORMATION
) + ObjectNameInfo
->Name
.MaximumLength
;
561 DPRINT ("Returned object path: %wZ\n", &ObjectNameInfo
->Name
);
568 /**********************************************************************
582 ObCreateObject (IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL
,
583 IN POBJECT_TYPE Type
,
584 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
585 IN KPROCESSOR_MODE AccessMode
,
586 IN OUT PVOID ParseContext OPTIONAL
,
588 IN ULONG PagedPoolCharge OPTIONAL
,
589 IN ULONG NonPagedPoolCharge OPTIONAL
,
593 UNICODE_STRING RemainingPath
;
594 POBJECT_HEADER Header
;
595 POBJECT_HEADER ParentHeader
= NULL
;
597 BOOLEAN ObjectAttached
= FALSE
;
599 PSECURITY_DESCRIPTOR NewSecurityDescriptor
= NULL
;
600 SECURITY_SUBJECT_CONTEXT SubjectContext
;
602 ASSERT_IRQL(APC_LEVEL
);
604 if(AccessMode
== UserMode
)
606 Status
= STATUS_SUCCESS
;
609 ProbeForRead(ObjectAttributes
,
610 sizeof(OBJECT_ATTRIBUTES
),
615 Status
= _SEH_GetExceptionCode();
619 if(!NT_SUCCESS(Status
))
625 DPRINT("ObCreateObject(Type %p ObjectAttributes %p, Object %p)\n",
626 Type
, ObjectAttributes
, Object
);
630 DPRINT1("Invalid object type!\n");
631 return STATUS_INVALID_PARAMETER
;
634 if (ObjectAttributes
!= NULL
&&
635 ObjectAttributes
->ObjectName
!= NULL
&&
636 ObjectAttributes
->ObjectName
->Buffer
!= NULL
)
638 Status
= ObFindObject(ObjectAttributes
,
642 if (!NT_SUCCESS(Status
))
644 DPRINT1("ObFindObject() failed! (Status 0x%x)\n", Status
);
650 RtlInitUnicodeString(&RemainingPath
, NULL
);
653 Header
= (POBJECT_HEADER
)ExAllocatePoolWithTag(NonPagedPool
,
654 OBJECT_ALLOC_SIZE(ObjectSize
),
656 if (Header
== NULL
) {
657 DPRINT1("Not enough memory!\n");
658 return STATUS_INSUFFICIENT_RESOURCES
;
661 RtlZeroMemory(Header
, OBJECT_ALLOC_SIZE(ObjectSize
));
663 /* Initialize the object header */
664 DPRINT("Initalizing header\n");
665 Header
->HandleCount
= 0;
666 Header
->RefCount
= 1;
667 Header
->ObjectType
= Type
;
668 if (ObjectAttributes
!= NULL
&&
669 ObjectAttributes
->Attributes
& OBJ_PERMANENT
)
671 Header
->Permanent
= TRUE
;
675 Header
->Permanent
= FALSE
;
678 if (ObjectAttributes
!= NULL
&&
679 ObjectAttributes
->Attributes
& OBJ_INHERIT
)
681 Header
->Inherit
= TRUE
;
685 Header
->Inherit
= FALSE
;
688 RtlInitUnicodeString(&(Header
->Name
),NULL
);
690 DPRINT("Getting Parent and adding entry\n");
693 ParentHeader
= BODY_TO_HEADER(Parent
);
696 if (ParentHeader
!= NULL
&&
697 ParentHeader
->ObjectType
== ObDirectoryType
&&
698 RemainingPath
.Buffer
!= NULL
)
700 NamePtr
= RemainingPath
.Buffer
;
701 if (*NamePtr
== L
'\\')
704 ObpAddEntryDirectory(Parent
,
708 ObjectAttached
= TRUE
;
711 DPRINT("About to call Create Routine\n");
712 if (Header
->ObjectType
->Create
!= NULL
)
714 DPRINT("Calling %x\n", Header
->ObjectType
->Create
);
715 Status
= Header
->ObjectType
->Create(HEADER_TO_BODY(Header
),
717 RemainingPath
.Buffer
,
719 if (!NT_SUCCESS(Status
))
721 if (ObjectAttached
== TRUE
)
723 ObpRemoveEntryDirectory(Header
);
727 ObDereferenceObject(Parent
);
729 RtlFreeUnicodeString(&Header
->Name
);
730 RtlFreeUnicodeString(&RemainingPath
);
732 DPRINT("Create Failed\n");
736 RtlFreeUnicodeString(&RemainingPath
);
738 SeCaptureSubjectContext(&SubjectContext
);
740 DPRINT("Security Assignment in progress\n");
741 /* Build the new security descriptor */
742 Status
= SeAssignSecurity((ParentHeader
!= NULL
) ? ParentHeader
->SecurityDescriptor
: NULL
,
743 (ObjectAttributes
!= NULL
) ? ObjectAttributes
->SecurityDescriptor
: NULL
,
744 &NewSecurityDescriptor
,
745 (Header
->ObjectType
== ObDirectoryType
),
747 Header
->ObjectType
->Mapping
,
749 if (NT_SUCCESS(Status
))
751 DPRINT("NewSecurityDescriptor %p\n", NewSecurityDescriptor
);
753 if (Header
->ObjectType
->Security
!= NULL
)
755 /* Call the security method */
756 Status
= Header
->ObjectType
->Security(HEADER_TO_BODY(Header
),
757 AssignSecurityDescriptor
,
759 NewSecurityDescriptor
,
764 /* Assign the security descriptor to the object header */
765 Status
= ObpAddSecurityDescriptor(NewSecurityDescriptor
,
766 &Header
->SecurityDescriptor
);
767 DPRINT("Object security descriptor %p\n", Header
->SecurityDescriptor
);
770 /* Release the new security descriptor */
771 SeDeassignSecurity(&NewSecurityDescriptor
);
774 DPRINT("Security Complete\n");
775 SeReleaseSubjectContext(&SubjectContext
);
779 *Object
= HEADER_TO_BODY(Header
);
783 return STATUS_SUCCESS
;
788 * FUNCTION: Increments the pointer reference count for a given object
790 * ObjectBody = Object's body
791 * DesiredAccess = Desired access to the object
792 * ObjectType = Points to the object type structure
793 * AccessMode = Type of access check to perform
799 ObReferenceObjectByPointer(IN PVOID Object
,
800 IN ACCESS_MASK DesiredAccess
,
801 IN POBJECT_TYPE ObjectType
,
802 IN KPROCESSOR_MODE AccessMode
)
804 POBJECT_HEADER Header
;
806 DPRINT("ObReferenceObjectByPointer(Object %x, ObjectType %x)\n",
809 Header
= BODY_TO_HEADER(Object
);
811 if (ObjectType
!= NULL
&& Header
->ObjectType
!= ObjectType
)
813 DPRINT("Failed %x (type was %x %S) should be %x %S\n",
816 Header
->ObjectType
->TypeName
.Buffer
,
818 ObjectType
->TypeName
.Buffer
);
819 return(STATUS_UNSUCCESSFUL
);
821 if (Header
->ObjectType
== PsProcessType
)
823 DPRINT("Ref p 0x%x refcount %d type %x ",
824 Object
, Header
->RefCount
, PsProcessType
);
825 DPRINT("eip %x\n", ((PULONG
)&Object
)[-1]);
827 if (Header
->ObjectType
== PsThreadType
)
829 DPRINT("Deref t 0x%x with refcount %d type %x ",
830 Object
, Header
->RefCount
, PsThreadType
);
831 DPRINT("eip %x\n", ((PULONG
)&Object
)[-1]);
834 if (Header
->CloseInProcess
)
836 if (Header
->ObjectType
== PsProcessType
)
838 return STATUS_PROCESS_IS_TERMINATING
;
840 if (Header
->ObjectType
== PsThreadType
)
842 return STATUS_THREAD_IS_TERMINATING
;
844 return(STATUS_UNSUCCESSFUL
);
847 InterlockedIncrement(&Header
->RefCount
);
849 return(STATUS_SUCCESS
);
857 ObOpenObjectByPointer(IN POBJECT Object
,
858 IN ULONG HandleAttributes
,
859 IN PACCESS_STATE PassedAccessState
,
860 IN ACCESS_MASK DesiredAccess
,
861 IN POBJECT_TYPE ObjectType
,
862 IN KPROCESSOR_MODE AccessMode
,
867 DPRINT("ObOpenObjectByPointer()\n");
869 Status
= ObReferenceObjectByPointer(Object
,
873 if (!NT_SUCCESS(Status
))
878 Status
= ObCreateHandle(PsGetCurrentProcess(),
881 (BOOLEAN
)(HandleAttributes
& OBJ_INHERIT
),
884 ObDereferenceObject(Object
);
886 return STATUS_SUCCESS
;
891 ObpDeleteObject(POBJECT_HEADER Header
)
893 DPRINT("ObpDeleteObject(Header %p)\n", Header
);
894 if (KeGetCurrentIrql() != PASSIVE_LEVEL
)
896 DPRINT("ObpDeleteObject called at an unsupported IRQL. Use ObpDeleteObjectDpcLevel instead.\n");
900 if (Header
->SecurityDescriptor
!= NULL
)
902 ObpRemoveSecurityDescriptor(Header
->SecurityDescriptor
);
905 if (Header
->ObjectType
!= NULL
&&
906 Header
->ObjectType
->Delete
!= NULL
)
908 Header
->ObjectType
->Delete(HEADER_TO_BODY(Header
));
911 if (Header
->Name
.Buffer
!= NULL
)
913 ObpRemoveEntryDirectory(Header
);
914 RtlFreeUnicodeString(&Header
->Name
);
917 DPRINT("ObPerformRetentionChecks() = Freeing object\n");
920 return(STATUS_SUCCESS
);
925 ObpDeleteObjectWorkRoutine (IN PVOID Parameter
)
927 PRETENTION_CHECK_PARAMS Params
= (PRETENTION_CHECK_PARAMS
)Parameter
;
928 /* ULONG Tag; */ /* See below */
931 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
); /* We need PAGED_CODE somewhere... */
933 /* Turn this on when we have ExFreePoolWithTag
934 Tag = Params->ObjectHeader->ObjectType->Tag; */
935 ObpDeleteObject(Params
->ObjectHeader
);
937 /* ExFreePoolWithTag(Params, Tag); */
942 ObpDeleteObjectDpcLevel(IN POBJECT_HEADER ObjectHeader
,
945 if (ObjectHeader
->RefCount
< 0)
947 CPRINT("Object %p/%p has invalid reference count (%d)\n",
948 ObjectHeader
, HEADER_TO_BODY(ObjectHeader
),
949 ObjectHeader
->RefCount
);
953 if (ObjectHeader
->HandleCount
< 0)
955 CPRINT("Object %p/%p has invalid handle count (%d)\n",
956 ObjectHeader
, HEADER_TO_BODY(ObjectHeader
),
957 ObjectHeader
->HandleCount
);
961 if (ObjectHeader
->CloseInProcess
)
964 return STATUS_UNSUCCESSFUL
;
966 ObjectHeader
->CloseInProcess
= TRUE
;
968 switch (KeGetCurrentIrql ())
971 return ObpDeleteObject (ObjectHeader
);
976 PRETENTION_CHECK_PARAMS Params
;
979 We use must succeed pool here because if the allocation fails
982 Params
= (PRETENTION_CHECK_PARAMS
)
983 ExAllocatePoolWithTag(NonPagedPoolMustSucceed
,
984 sizeof(RETENTION_CHECK_PARAMS
),
985 ObjectHeader
->ObjectType
->Tag
);
986 Params
->ObjectHeader
= ObjectHeader
;
987 ExInitializeWorkItem(&Params
->WorkItem
,
988 ObpDeleteObjectWorkRoutine
,
990 ExQueueWorkItem(&Params
->WorkItem
,
993 return STATUS_PENDING
;
996 DPRINT("ObpDeleteObjectDpcLevel called at unsupported "
997 "IRQL %u!\n", KeGetCurrentIrql());
999 return STATUS_UNSUCCESSFUL
;
1002 return STATUS_SUCCESS
;
1006 /**********************************************************************
1008 * ObfReferenceObject@4
1011 * Increments a given object's reference count and performs
1015 * ObjectBody = Body of the object.
1023 ObfReferenceObject(IN PVOID Object
)
1025 POBJECT_HEADER Header
;
1029 Header
= BODY_TO_HEADER(Object
);
1031 /* No one should be referencing an object once we are deleting it. */
1032 if (Header
->CloseInProcess
)
1037 (VOID
)InterlockedIncrement(&Header
->RefCount
);
1041 /**********************************************************************
1043 * ObfDereferenceObject@4
1046 * Decrements a given object's reference count and performs
1050 * ObjectBody = Body of the object.
1058 ObfDereferenceObject(IN PVOID Object
)
1060 POBJECT_HEADER Header
;
1067 /* Extract the object header. */
1068 Header
= BODY_TO_HEADER(Object
);
1069 Permanent
= Header
->Permanent
;
1070 HandleCount
= Header
->HandleCount
;
1073 Drop our reference and get the new count so we can tell if this was the
1076 NewRefCount
= InterlockedDecrement(&Header
->RefCount
);
1077 ASSERT(NewRefCount
>= 0);
1079 /* Check whether the object can now be deleted. */
1080 if (NewRefCount
== 0 &&
1084 ObpDeleteObjectDpcLevel(Header
, NewRefCount
);
1089 /**********************************************************************
1091 * ObGetObjectPointerCount@4
1094 * Retrieves the pointer(reference) count of the given object.
1097 * ObjectBody = Body of the object.
1105 ObGetObjectPointerCount(PVOID Object
)
1107 POBJECT_HEADER Header
;
1110 Header
= BODY_TO_HEADER(Object
);
1112 return Header
->RefCount
;
1116 /**********************************************************************
1118 * ObGetObjectHandleCount@4
1121 * Retrieves the handle count of the given object.
1124 * ObjectBody = Body of the object.
1130 ObGetObjectHandleCount(PVOID Object
)
1132 POBJECT_HEADER Header
;
1135 Header
= BODY_TO_HEADER(Object
);
1137 return Header
->HandleCount
;
1141 /**********************************************************************
1143 * ObDereferenceObject@4
1146 * Decrements a given object's reference count and performs
1150 * ObjectBody = Body of the object.
1158 #ifdef ObDereferenceObject
1159 #undef ObDereferenceObject
1163 ObDereferenceObject(IN PVOID Object
)
1165 ObfDereferenceObject(Object
);