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 ************************************************************/
29 ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
30 IN KPROCESSOR_MODE AccessMode
,
31 IN POOL_TYPE PoolType
,
32 IN BOOLEAN CaptureIfKernel
,
33 OUT PCAPTURED_OBJECT_ATTRIBUTES CapturedObjectAttributes OPTIONAL
,
34 OUT PUNICODE_STRING ObjectName OPTIONAL
)
36 OBJECT_ATTRIBUTES AttributesCopy
;
37 NTSTATUS Status
= STATUS_SUCCESS
;
39 /* at least one output parameter must be != NULL! */
40 ASSERT(CapturedObjectAttributes
!= NULL
|| ObjectName
!= NULL
);
42 if(ObjectAttributes
== NULL
)
44 /* we're going to return STATUS_SUCCESS! */
45 goto failbasiccleanup
;
48 if(AccessMode
!= KernelMode
)
52 ProbeForRead(ObjectAttributes
,
53 sizeof(ObjectAttributes
),
55 /* make a copy on the stack */
56 AttributesCopy
= *ObjectAttributes
;
60 Status
= _SEH_GetExceptionCode();
64 if(!NT_SUCCESS(Status
))
66 DPRINT1("ObpCaptureObjectAttributes failed to probe object attributes\n");
67 goto failbasiccleanup
;
70 else if(!CaptureIfKernel
)
72 if(ObjectAttributes
->Length
== sizeof(OBJECT_ATTRIBUTES
))
74 if(ObjectName
!= NULL
)
76 /* we don't have to capture any memory, the caller considers the passed data
78 if(ObjectAttributes
->ObjectName
!= NULL
)
80 *ObjectName
= *ObjectAttributes
->ObjectName
;
84 ObjectName
->Length
= ObjectName
->MaximumLength
= 0;
85 ObjectName
->Buffer
= NULL
;
88 if(CapturedObjectAttributes
!= NULL
)
90 CapturedObjectAttributes
->RootDirectory
= ObjectAttributes
->RootDirectory
;
91 CapturedObjectAttributes
->Attributes
= ObjectAttributes
->Attributes
;
92 CapturedObjectAttributes
->SecurityDescriptor
= ObjectAttributes
->SecurityDescriptor
;
93 CapturedObjectAttributes
->SecurityQualityOfService
= ObjectAttributes
->SecurityQualityOfService
;
96 return STATUS_SUCCESS
;
100 Status
= STATUS_INVALID_PARAMETER
;
101 goto failbasiccleanup
;
106 AttributesCopy
= *ObjectAttributes
;
109 /* if Length isn't as expected, bail with an invalid parameter status code so
110 the caller knows he passed garbage... */
111 if(AttributesCopy
.Length
!= sizeof(OBJECT_ATTRIBUTES
))
113 Status
= STATUS_INVALID_PARAMETER
;
114 goto failbasiccleanup
;
117 if(CapturedObjectAttributes
!= NULL
)
119 CapturedObjectAttributes
->RootDirectory
= AttributesCopy
.RootDirectory
;
120 CapturedObjectAttributes
->Attributes
= AttributesCopy
.Attributes
;
122 if(AttributesCopy
.SecurityDescriptor
!= NULL
)
124 Status
= SeCaptureSecurityDescriptor(AttributesCopy
.SecurityDescriptor
,
128 &CapturedObjectAttributes
->SecurityDescriptor
);
129 if(!NT_SUCCESS(Status
))
131 DPRINT1("Unable to capture the security descriptor!!!\n");
132 goto failbasiccleanup
;
137 CapturedObjectAttributes
->SecurityDescriptor
= NULL
;
140 if(AttributesCopy
.SecurityQualityOfService
!= NULL
)
142 SECURITY_QUALITY_OF_SERVICE SafeQoS
;
146 ProbeForRead(AttributesCopy
.SecurityQualityOfService
,
147 sizeof(SECURITY_QUALITY_OF_SERVICE
),
149 SafeQoS
= *(PSECURITY_QUALITY_OF_SERVICE
)AttributesCopy
.SecurityQualityOfService
;
153 Status
= _SEH_GetExceptionCode();
157 if(!NT_SUCCESS(Status
))
159 DPRINT1("Unable to capture QoS!!!\n");
160 goto failcleanupsdescriptor
;
163 if(SafeQoS
.Length
!= sizeof(SECURITY_QUALITY_OF_SERVICE
))
165 DPRINT1("Unable to capture QoS, wrong size!!!\n");
166 Status
= STATUS_INVALID_PARAMETER
;
167 goto failcleanupsdescriptor
;
170 CapturedObjectAttributes
->SecurityQualityOfService
= ExAllocatePool(PoolType
,
171 sizeof(SECURITY_QUALITY_OF_SERVICE
));
172 if(CapturedObjectAttributes
->SecurityQualityOfService
!= NULL
)
174 *CapturedObjectAttributes
->SecurityQualityOfService
= SafeQoS
;
178 Status
= STATUS_INSUFFICIENT_RESOURCES
;
179 goto failcleanupsdescriptor
;
184 CapturedObjectAttributes
->SecurityQualityOfService
= NULL
;
188 if(ObjectName
!= NULL
)
190 if(AttributesCopy
.ObjectName
!= NULL
)
192 UNICODE_STRING OriginalCopy
;
194 if(AccessMode
!= KernelMode
)
198 /* probe the ObjectName structure and make a local stack copy of it */
199 ProbeForRead(AttributesCopy
.ObjectName
,
200 sizeof(UNICODE_STRING
),
202 OriginalCopy
= *AttributesCopy
.ObjectName
;
203 if(OriginalCopy
.Length
> 0)
205 ProbeForRead(OriginalCopy
.Buffer
,
212 Status
= _SEH_GetExceptionCode();
216 if(NT_SUCCESS(Status
))
218 if(OriginalCopy
.Length
> 0)
220 ObjectName
->MaximumLength
= OriginalCopy
.Length
+ sizeof(WCHAR
);
221 ObjectName
->Buffer
= ExAllocatePool(PoolType
,
222 ObjectName
->MaximumLength
);
223 if(ObjectName
->Buffer
!= NULL
)
227 /* no need to probe OriginalCopy.Buffer again, we already did that
228 when capturing the UNICODE_STRING structure itself */
229 RtlCopyMemory(ObjectName
->Buffer
, OriginalCopy
.Buffer
, OriginalCopy
.Length
);
230 ObjectName
->Buffer
[OriginalCopy
.Length
/ sizeof(WCHAR
)] = L
'\0';
234 Status
= _SEH_GetExceptionCode();
238 if(!NT_SUCCESS(Status
))
240 DPRINT1("ObpCaptureObjectAttributes failed to copy the unicode string!\n");
245 Status
= STATUS_INSUFFICIENT_RESOURCES
;
248 else if(AttributesCopy
.RootDirectory
!= NULL
/* && OriginalCopy.Length == 0 */)
250 /* if the caller specified a root directory, there must be an object name! */
251 Status
= STATUS_OBJECT_NAME_INVALID
;
256 DPRINT1("ObpCaptureObjectAttributes failed to probe the object name UNICODE_STRING structure!\n");
259 else /* AccessMode == KernelMode */
261 OriginalCopy
= *AttributesCopy
.ObjectName
;
263 if(OriginalCopy
.Length
> 0)
265 ObjectName
->MaximumLength
= OriginalCopy
.Length
+ sizeof(WCHAR
);
266 ObjectName
->Buffer
= ExAllocatePool(PoolType
,
267 ObjectName
->MaximumLength
);
268 if(ObjectName
->Buffer
!= NULL
)
270 RtlCopyMemory(ObjectName
->Buffer
, OriginalCopy
.Buffer
, OriginalCopy
.Length
);
271 ObjectName
->Buffer
[OriginalCopy
.Length
/ sizeof(WCHAR
)] = L
'\0';
275 Status
= STATUS_INSUFFICIENT_RESOURCES
;
278 else if(AttributesCopy
.RootDirectory
!= NULL
/* && OriginalCopy.Length == 0 */)
280 /* if the caller specified a root directory, there must be an object name! */
281 Status
= STATUS_OBJECT_NAME_INVALID
;
287 ObjectName
->Length
= ObjectName
->MaximumLength
= 0;
288 ObjectName
->Buffer
= NULL
;
292 if(!NT_SUCCESS(Status
))
294 if(ObjectName
->Buffer
)
296 ExFreePool(ObjectName
->Buffer
);
299 failcleanupsdescriptor
:
300 if(CapturedObjectAttributes
!= NULL
)
302 /* cleanup allocated resources */
303 SeReleaseSecurityDescriptor(CapturedObjectAttributes
->SecurityDescriptor
,
309 if(ObjectName
!= NULL
)
311 ObjectName
->Length
= ObjectName
->MaximumLength
= 0;
312 ObjectName
->Buffer
= NULL
;
314 if(CapturedObjectAttributes
!= NULL
)
316 RtlZeroMemory(CapturedObjectAttributes
, sizeof(CAPTURED_OBJECT_ATTRIBUTES
));
325 ObpReleaseObjectAttributes(IN PCAPTURED_OBJECT_ATTRIBUTES CapturedObjectAttributes OPTIONAL
,
326 IN PUNICODE_STRING ObjectName OPTIONAL
,
327 IN KPROCESSOR_MODE AccessMode
,
328 IN BOOLEAN CaptureIfKernel
)
330 /* WARNING - You need to pass the same parameters to this function as you passed
331 to ObpCaptureObjectAttributes() to avoid memory leaks */
332 if(AccessMode
!= KernelMode
|| CaptureIfKernel
)
334 if(CapturedObjectAttributes
!= NULL
)
336 if(CapturedObjectAttributes
->SecurityDescriptor
!= NULL
)
338 ExFreePool(CapturedObjectAttributes
->SecurityDescriptor
);
339 CapturedObjectAttributes
->SecurityDescriptor
= NULL
;
341 if(CapturedObjectAttributes
->SecurityQualityOfService
!= NULL
)
343 ExFreePool(CapturedObjectAttributes
->SecurityQualityOfService
);
344 CapturedObjectAttributes
->SecurityQualityOfService
= NULL
;
347 if(ObjectName
!= NULL
&&
348 ObjectName
->Length
> 0)
350 ExFreePool(ObjectName
->Buffer
);
356 /**********************************************************************
368 * Pointer to a unicode string that will contain the
369 * remaining path if the function returns successfully.
370 * The caller must free the buffer after use by calling
371 * RtlFreeUnicodeString ().
374 * Optional pointer to an object type. This is used to
375 * descide if a symbolic link object will be parsed or not.
380 ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes
,
381 PVOID
* ReturnedObject
,
382 PUNICODE_STRING RemainingPath
,
383 POBJECT_TYPE ObjectType
)
388 POBJECT_HEADER CurrentHeader
;
391 UNICODE_STRING PathString
;
393 PUNICODE_STRING ObjectName
;
397 DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, "
398 "RemainingPath %x)\n",ObjectAttributes
,ReturnedObject
,RemainingPath
);
399 DPRINT("ObjectAttributes->ObjectName %wZ\n",
400 ObjectAttributes
->ObjectName
);
402 RtlInitUnicodeString (RemainingPath
, NULL
);
404 if (ObjectAttributes
->RootDirectory
== NULL
)
406 ObReferenceObjectByPointer(NameSpaceRoot
,
410 CurrentObject
= NameSpaceRoot
;
414 Status
= ObReferenceObjectByHandle(ObjectAttributes
->RootDirectory
,
420 if (!NT_SUCCESS(Status
))
426 ObjectName
= ObjectAttributes
->ObjectName
;
427 if (ObjectName
->Length
== 0 ||
428 ObjectName
->Buffer
[0] == UNICODE_NULL
)
430 *ReturnedObject
= CurrentObject
;
431 return STATUS_SUCCESS
;
434 if (ObjectAttributes
->RootDirectory
== NULL
&&
435 ObjectName
->Buffer
[0] != L
'\\')
437 ObDereferenceObject (CurrentObject
);
438 return STATUS_UNSUCCESSFUL
;
441 /* Create a zero-terminated copy of the object name */
442 PathString
.Length
= ObjectName
->Length
;
443 PathString
.MaximumLength
= ObjectName
->Length
+ sizeof(WCHAR
);
444 PathString
.Buffer
= ExAllocatePool (NonPagedPool
,
445 PathString
.MaximumLength
);
446 if (PathString
.Buffer
== NULL
)
448 ObDereferenceObject (CurrentObject
);
449 return STATUS_INSUFFICIENT_RESOURCES
;
452 RtlCopyMemory (PathString
.Buffer
,
455 PathString
.Buffer
[PathString
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
457 current
= PathString
.Buffer
;
459 RootObject
= CurrentObject
;
460 Attributes
= ObjectAttributes
->Attributes
;
461 if (ObjectType
== ObSymbolicLinkType
)
462 Attributes
|= OBJ_OPENLINK
;
466 DPRINT("current %S\n",current
);
467 CurrentHeader
= BODY_TO_HEADER(CurrentObject
);
469 DPRINT("Current ObjectType %wZ\n",
470 &CurrentHeader
->ObjectType
->TypeName
);
472 if (CurrentHeader
->ObjectType
->Parse
== NULL
)
474 DPRINT("Current object can't parse\n");
477 Status
= CurrentHeader
->ObjectType
->Parse(CurrentObject
,
482 if (Status
== STATUS_REPARSE
)
484 /* reparse the object path */
485 NextObject
= NameSpaceRoot
;
486 current
= PathString
.Buffer
;
488 ObReferenceObjectByPointer(NextObject
,
494 if (NextObject
== NULL
)
498 ObDereferenceObject(CurrentObject
);
499 CurrentObject
= NextObject
;
503 RtlpCreateUnicodeString (RemainingPath
, current
, NonPagedPool
);
504 RtlFreeUnicodeString (&PathString
);
505 *ReturnedObject
= CurrentObject
;
507 return STATUS_SUCCESS
;
511 /**********************************************************************
513 * ObQueryNameString@16
524 ObQueryNameString (IN PVOID Object
,
525 OUT POBJECT_NAME_INFORMATION ObjectNameInfo
,
527 OUT PULONG ReturnLength
)
529 POBJECT_NAME_INFORMATION LocalInfo
;
530 POBJECT_HEADER ObjectHeader
;
531 ULONG LocalReturnLength
;
538 if (Length
< sizeof(OBJECT_NAME_INFORMATION
) + sizeof(WCHAR
))
539 return STATUS_INVALID_BUFFER_SIZE
;
541 ObjectNameInfo
->Name
.MaximumLength
= (USHORT
)(Length
- sizeof(OBJECT_NAME_INFORMATION
));
542 ObjectNameInfo
->Name
.Length
= 0;
543 ObjectNameInfo
->Name
.Buffer
=
544 (PWCHAR
)((ULONG_PTR
)ObjectNameInfo
+ sizeof(OBJECT_NAME_INFORMATION
));
545 ObjectNameInfo
->Name
.Buffer
[0] = 0;
547 ObjectHeader
= BODY_TO_HEADER(Object
);
549 if (ObjectHeader
->ObjectType
!= NULL
&&
550 ObjectHeader
->ObjectType
->QueryName
!= NULL
)
552 DPRINT ("Calling %x\n", ObjectHeader
->ObjectType
->QueryName
);
553 Status
= ObjectHeader
->ObjectType
->QueryName (Object
,
558 else if (ObjectHeader
->Name
.Length
> 0 && ObjectHeader
->Name
.Buffer
!= NULL
)
560 DPRINT ("Object does not have a 'QueryName' function\n");
562 if (ObjectHeader
->Parent
== NameSpaceRoot
)
564 DPRINT ("Reached the root directory\n");
565 ObjectNameInfo
->Name
.Length
= 0;
566 ObjectNameInfo
->Name
.Buffer
[0] = 0;
567 Status
= STATUS_SUCCESS
;
569 else if (ObjectHeader
->Parent
!= NULL
)
571 LocalInfo
= ExAllocatePool (NonPagedPool
,
572 sizeof(OBJECT_NAME_INFORMATION
) +
573 MAX_PATH
* sizeof(WCHAR
));
574 if (LocalInfo
== NULL
)
575 return STATUS_INSUFFICIENT_RESOURCES
;
577 Status
= ObQueryNameString (ObjectHeader
->Parent
,
579 MAX_PATH
* sizeof(WCHAR
),
581 if (!NT_SUCCESS (Status
))
583 ExFreePool (LocalInfo
);
587 Status
= RtlAppendUnicodeStringToString (&ObjectNameInfo
->Name
,
590 ExFreePool (LocalInfo
);
592 if (!NT_SUCCESS (Status
))
596 DPRINT ("Object path %wZ\n", &ObjectHeader
->Name
);
597 Status
= RtlAppendUnicodeToString (&ObjectNameInfo
->Name
,
599 if (!NT_SUCCESS (Status
))
602 Status
= RtlAppendUnicodeStringToString (&ObjectNameInfo
->Name
,
603 &ObjectHeader
->Name
);
607 DPRINT ("Object is unnamed\n");
609 ObjectNameInfo
->Name
.MaximumLength
= 0;
610 ObjectNameInfo
->Name
.Length
= 0;
611 ObjectNameInfo
->Name
.Buffer
= NULL
;
613 Status
= STATUS_SUCCESS
;
616 if (NT_SUCCESS (Status
))
618 ObjectNameInfo
->Name
.MaximumLength
=
619 (ObjectNameInfo
->Name
.Length
) ? ObjectNameInfo
->Name
.Length
+ sizeof(WCHAR
) : 0;
621 sizeof(OBJECT_NAME_INFORMATION
) + ObjectNameInfo
->Name
.MaximumLength
;
622 DPRINT ("Returned object path: %wZ\n", &ObjectNameInfo
->Name
);
629 /**********************************************************************
643 ObCreateObject (IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL
,
644 IN POBJECT_TYPE Type
,
645 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
646 IN KPROCESSOR_MODE AccessMode
,
647 IN OUT PVOID ParseContext OPTIONAL
,
649 IN ULONG PagedPoolCharge OPTIONAL
,
650 IN ULONG NonPagedPoolCharge OPTIONAL
,
654 UNICODE_STRING RemainingPath
;
655 POBJECT_HEADER Header
;
656 POBJECT_HEADER ParentHeader
= NULL
;
658 BOOLEAN ObjectAttached
= FALSE
;
660 PSECURITY_DESCRIPTOR NewSecurityDescriptor
= NULL
;
661 SECURITY_SUBJECT_CONTEXT SubjectContext
;
665 if(ObjectAttributesAccessMode
== UserMode
&& ObjectAttributes
!= NULL
)
667 Status
= STATUS_SUCCESS
;
670 ProbeForRead(ObjectAttributes
,
671 sizeof(OBJECT_ATTRIBUTES
),
676 Status
= _SEH_GetExceptionCode();
680 if(!NT_SUCCESS(Status
))
686 DPRINT("ObCreateObject(Type %p ObjectAttributes %p, Object %p)\n",
687 Type
, ObjectAttributes
, Object
);
691 DPRINT1("Invalid object type!\n");
692 return STATUS_INVALID_PARAMETER
;
695 if (ObjectAttributes
!= NULL
&&
696 ObjectAttributes
->ObjectName
!= NULL
&&
697 ObjectAttributes
->ObjectName
->Buffer
!= NULL
)
699 Status
= ObFindObject(ObjectAttributes
,
703 if (!NT_SUCCESS(Status
))
705 DPRINT1("ObFindObject() failed! (Status 0x%x)\n", Status
);
710 ParentHeader
= BODY_TO_HEADER(Parent
);
713 RemainingPath
.Buffer
== NULL
)
715 if (ParentHeader
->ObjectType
!= Type
716 || !(ObjectAttributes
->Attributes
& OBJ_OPENIF
))
718 ObDereferenceObject(Parent
);
719 return STATUS_OBJECT_NAME_COLLISION
;
722 return STATUS_OBJECT_EXISTS
;
727 RtlInitUnicodeString(&RemainingPath
, NULL
);
730 Header
= (POBJECT_HEADER
)ExAllocatePoolWithTag(NonPagedPool
,
731 OBJECT_ALLOC_SIZE(ObjectSize
),
733 if (Header
== NULL
) {
734 DPRINT1("Not enough memory!\n");
735 return STATUS_INSUFFICIENT_RESOURCES
;
738 RtlZeroMemory(Header
, OBJECT_ALLOC_SIZE(ObjectSize
));
740 /* Initialize the object header */
741 DPRINT("Initalizing header 0x%x (%wZ)\n", Header
, &Type
->TypeName
);
742 Header
->HandleCount
= 0;
743 Header
->RefCount
= 1;
744 Header
->ObjectType
= Type
;
745 if (ObjectAttributes
!= NULL
&&
746 ObjectAttributes
->Attributes
& OBJ_PERMANENT
)
748 Header
->Permanent
= TRUE
;
752 Header
->Permanent
= FALSE
;
755 if (ObjectAttributes
!= NULL
&&
756 ObjectAttributes
->Attributes
& OBJ_INHERIT
)
758 Header
->Inherit
= TRUE
;
762 Header
->Inherit
= FALSE
;
765 RtlInitUnicodeString(&(Header
->Name
),NULL
);
767 DPRINT("Getting Parent and adding entry\n");
768 if (ParentHeader
!= NULL
&&
769 ParentHeader
->ObjectType
== ObDirectoryType
&&
770 RemainingPath
.Buffer
!= NULL
)
772 NamePtr
= RemainingPath
.Buffer
;
773 if (*NamePtr
== L
'\\')
776 ObpAddEntryDirectory(Parent
,
780 ObjectAttached
= TRUE
;
783 DPRINT("About to call Create Routine\n");
784 if (Header
->ObjectType
->Create
!= NULL
)
786 DPRINT("Calling %x\n", Header
->ObjectType
->Create
);
787 Status
= Header
->ObjectType
->Create(HEADER_TO_BODY(Header
),
789 RemainingPath
.Buffer
,
791 if (!NT_SUCCESS(Status
))
793 if (ObjectAttached
== TRUE
)
795 ObpRemoveEntryDirectory(Header
);
799 ObDereferenceObject(Parent
);
801 RtlFreeUnicodeString(&Header
->Name
);
802 RtlFreeUnicodeString(&RemainingPath
);
804 DPRINT("Create Failed\n");
808 RtlFreeUnicodeString(&RemainingPath
);
810 SeCaptureSubjectContext(&SubjectContext
);
812 DPRINT("Security Assignment in progress\n");
813 /* Build the new security descriptor */
814 Status
= SeAssignSecurity((ParentHeader
!= NULL
) ? ParentHeader
->SecurityDescriptor
: NULL
,
815 (ObjectAttributes
!= NULL
) ? ObjectAttributes
->SecurityDescriptor
: NULL
,
816 &NewSecurityDescriptor
,
817 (Header
->ObjectType
== ObDirectoryType
),
819 Header
->ObjectType
->Mapping
,
821 if (NT_SUCCESS(Status
))
823 DPRINT("NewSecurityDescriptor %p\n", NewSecurityDescriptor
);
825 if (Header
->ObjectType
->Security
!= NULL
)
827 /* Call the security method */
828 Status
= Header
->ObjectType
->Security(HEADER_TO_BODY(Header
),
829 AssignSecurityDescriptor
,
831 NewSecurityDescriptor
,
836 /* Assign the security descriptor to the object header */
837 Status
= ObpAddSecurityDescriptor(NewSecurityDescriptor
,
838 &Header
->SecurityDescriptor
);
839 DPRINT("Object security descriptor %p\n", Header
->SecurityDescriptor
);
842 /* Release the new security descriptor */
843 SeDeassignSecurity(&NewSecurityDescriptor
);
846 DPRINT("Security Complete\n");
847 SeReleaseSubjectContext(&SubjectContext
);
851 *Object
= HEADER_TO_BODY(Header
);
855 return STATUS_SUCCESS
;
860 * FUNCTION: Increments the pointer reference count for a given object
862 * ObjectBody = Object's body
863 * DesiredAccess = Desired access to the object
864 * ObjectType = Points to the object type structure
865 * AccessMode = Type of access check to perform
871 ObReferenceObjectByPointer(IN PVOID Object
,
872 IN ACCESS_MASK DesiredAccess
,
873 IN POBJECT_TYPE ObjectType
,
874 IN KPROCESSOR_MODE AccessMode
)
876 POBJECT_HEADER Header
;
878 /* NOTE: should be possible to reference an object above APC_LEVEL! */
880 DPRINT("ObReferenceObjectByPointer(Object %x, ObjectType %x)\n",
883 Header
= BODY_TO_HEADER(Object
);
885 if (ObjectType
!= NULL
&& Header
->ObjectType
!= ObjectType
)
887 DPRINT("Failed %x (type was %x %S) should be %x %S\n",
890 Header
->ObjectType
->TypeName
.Buffer
,
892 ObjectType
->TypeName
.Buffer
);
893 return(STATUS_UNSUCCESSFUL
);
895 if (Header
->ObjectType
== PsProcessType
)
897 DPRINT("Ref p 0x%x refcount %d type %x ",
898 Object
, Header
->RefCount
, PsProcessType
);
899 DPRINT("eip %x\n", ((PULONG
)&Object
)[-1]);
901 if (Header
->ObjectType
== PsThreadType
)
903 DPRINT("Deref t 0x%x with refcount %d type %x ",
904 Object
, Header
->RefCount
, PsThreadType
);
905 DPRINT("eip %x\n", ((PULONG
)&Object
)[-1]);
908 if (Header
->RefCount
== 0 && !Header
->Permanent
)
910 if (Header
->ObjectType
== PsProcessType
)
912 return STATUS_PROCESS_IS_TERMINATING
;
914 if (Header
->ObjectType
== PsThreadType
)
916 return STATUS_THREAD_IS_TERMINATING
;
918 return(STATUS_UNSUCCESSFUL
);
921 if (1 == InterlockedIncrement(&Header
->RefCount
) && !Header
->Permanent
)
926 return(STATUS_SUCCESS
);
934 ObOpenObjectByPointer(IN POBJECT Object
,
935 IN ULONG HandleAttributes
,
936 IN PACCESS_STATE PassedAccessState
,
937 IN ACCESS_MASK DesiredAccess
,
938 IN POBJECT_TYPE ObjectType
,
939 IN KPROCESSOR_MODE AccessMode
,
946 DPRINT("ObOpenObjectByPointer()\n");
948 Status
= ObReferenceObjectByPointer(Object
,
952 if (!NT_SUCCESS(Status
))
957 Status
= ObCreateHandle(PsGetCurrentProcess(),
960 (BOOLEAN
)(HandleAttributes
& OBJ_INHERIT
),
963 ObDereferenceObject(Object
);
965 return STATUS_SUCCESS
;
970 ObpDeleteObject(POBJECT_HEADER Header
)
972 DPRINT("ObpDeleteObject(Header %p)\n", Header
);
973 if (KeGetCurrentIrql() != PASSIVE_LEVEL
)
975 DPRINT("ObpDeleteObject called at an unsupported IRQL. Use ObpDeleteObjectDpcLevel instead.\n");
979 if (Header
->SecurityDescriptor
!= NULL
)
981 ObpRemoveSecurityDescriptor(Header
->SecurityDescriptor
);
984 if (Header
->ObjectType
!= NULL
&&
985 Header
->ObjectType
->Delete
!= NULL
)
987 Header
->ObjectType
->Delete(HEADER_TO_BODY(Header
));
990 if (Header
->Name
.Buffer
!= NULL
)
992 ObpRemoveEntryDirectory(Header
);
993 RtlFreeUnicodeString(&Header
->Name
);
996 DPRINT("ObPerformRetentionChecks() = Freeing object\n");
999 return(STATUS_SUCCESS
);
1004 ObpDeleteObjectWorkRoutine (IN PVOID Parameter
)
1006 PRETENTION_CHECK_PARAMS Params
= (PRETENTION_CHECK_PARAMS
)Parameter
;
1007 /* ULONG Tag; */ /* See below */
1010 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
); /* We need PAGED_CODE somewhere... */
1012 /* Turn this on when we have ExFreePoolWithTag
1013 Tag = Params->ObjectHeader->ObjectType->Tag; */
1014 ObpDeleteObject(Params
->ObjectHeader
);
1016 /* ExFreePoolWithTag(Params, Tag); */
1021 ObpDeleteObjectDpcLevel(IN POBJECT_HEADER ObjectHeader
,
1022 IN LONG OldRefCount
)
1025 if (ObjectHeader
->RefCount
< 0)
1027 CPRINT("Object %p/%p has invalid reference count (%d)\n",
1028 ObjectHeader
, HEADER_TO_BODY(ObjectHeader
),
1029 ObjectHeader
->RefCount
);
1033 if (ObjectHeader
->HandleCount
< 0)
1035 CPRINT("Object %p/%p has invalid handle count (%d)\n",
1036 ObjectHeader
, HEADER_TO_BODY(ObjectHeader
),
1037 ObjectHeader
->HandleCount
);
1043 switch (KeGetCurrentIrql ())
1046 return ObpDeleteObject (ObjectHeader
);
1049 case DISPATCH_LEVEL
:
1051 PRETENTION_CHECK_PARAMS Params
;
1054 We use must succeed pool here because if the allocation fails
1055 then we leak memory.
1057 Params
= (PRETENTION_CHECK_PARAMS
)
1058 ExAllocatePoolWithTag(NonPagedPoolMustSucceed
,
1059 sizeof(RETENTION_CHECK_PARAMS
),
1060 ObjectHeader
->ObjectType
->Tag
);
1061 Params
->ObjectHeader
= ObjectHeader
;
1062 ExInitializeWorkItem(&Params
->WorkItem
,
1063 ObpDeleteObjectWorkRoutine
,
1065 ExQueueWorkItem(&Params
->WorkItem
,
1068 return STATUS_PENDING
;
1071 DPRINT("ObpDeleteObjectDpcLevel called at unsupported "
1072 "IRQL %u!\n", KeGetCurrentIrql());
1074 return STATUS_UNSUCCESSFUL
;
1077 return STATUS_SUCCESS
;
1081 /**********************************************************************
1083 * ObfReferenceObject@4
1086 * Increments a given object's reference count and performs
1090 * ObjectBody = Body of the object.
1098 ObfReferenceObject(IN PVOID Object
)
1100 POBJECT_HEADER Header
;
1104 Header
= BODY_TO_HEADER(Object
);
1106 /* No one should be referencing an object once we are deleting it. */
1107 if (InterlockedIncrement(&Header
->RefCount
) == 1 && !Header
->Permanent
)
1115 /**********************************************************************
1117 * ObfDereferenceObject@4
1120 * Decrements a given object's reference count and performs
1124 * ObjectBody = Body of the object.
1132 ObfDereferenceObject(IN PVOID Object
)
1134 POBJECT_HEADER Header
;
1140 /* Extract the object header. */
1141 Header
= BODY_TO_HEADER(Object
);
1142 Permanent
= Header
->Permanent
;
1145 Drop our reference and get the new count so we can tell if this was the
1148 NewRefCount
= InterlockedDecrement(&Header
->RefCount
);
1149 DPRINT("ObfDereferenceObject(0x%x)==%d (%wZ)\n", Object
, NewRefCount
, &Header
->ObjectType
->TypeName
);
1150 ASSERT(NewRefCount
>= 0);
1152 /* Check whether the object can now be deleted. */
1153 if (NewRefCount
== 0 &&
1156 ObpDeleteObjectDpcLevel(Header
, NewRefCount
);
1161 /**********************************************************************
1163 * ObGetObjectPointerCount@4
1166 * Retrieves the pointer(reference) count of the given object.
1169 * ObjectBody = Body of the object.
1177 ObGetObjectPointerCount(PVOID Object
)
1179 POBJECT_HEADER Header
;
1184 Header
= BODY_TO_HEADER(Object
);
1186 return Header
->RefCount
;
1190 /**********************************************************************
1192 * ObGetObjectHandleCount@4
1195 * Retrieves the handle count of the given object.
1198 * ObjectBody = Body of the object.
1204 ObGetObjectHandleCount(PVOID Object
)
1206 POBJECT_HEADER Header
;
1211 Header
= BODY_TO_HEADER(Object
);
1213 return Header
->HandleCount
;
1217 /**********************************************************************
1219 * ObDereferenceObject@4
1222 * Decrements a given object's reference count and performs
1226 * ObjectBody = Body of the object.
1234 #ifdef ObDereferenceObject
1235 #undef ObDereferenceObject
1239 ObDereferenceObject(IN PVOID Object
)
1241 ObfDereferenceObject(Object
);