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
)
50 RtlZeroMemory(&AttributesCopy
, sizeof(AttributesCopy
));
54 ProbeForRead(ObjectAttributes
,
55 sizeof(ObjectAttributes
),
57 /* make a copy on the stack */
58 AttributesCopy
= *ObjectAttributes
;
62 Status
= _SEH_GetExceptionCode();
66 if(!NT_SUCCESS(Status
))
68 DPRINT1("ObpCaptureObjectAttributes failed to probe object attributes\n");
69 goto failbasiccleanup
;
72 else if(!CaptureIfKernel
)
74 if(ObjectAttributes
->Length
== sizeof(OBJECT_ATTRIBUTES
))
76 if(ObjectName
!= NULL
)
78 /* we don't have to capture any memory, the caller considers the passed data
80 if(ObjectAttributes
->ObjectName
!= NULL
)
82 *ObjectName
= *ObjectAttributes
->ObjectName
;
86 ObjectName
->Length
= ObjectName
->MaximumLength
= 0;
87 ObjectName
->Buffer
= NULL
;
90 if(CapturedObjectAttributes
!= NULL
)
92 CapturedObjectAttributes
->RootDirectory
= ObjectAttributes
->RootDirectory
;
93 CapturedObjectAttributes
->Attributes
= ObjectAttributes
->Attributes
;
94 CapturedObjectAttributes
->SecurityDescriptor
= ObjectAttributes
->SecurityDescriptor
;
95 CapturedObjectAttributes
->SecurityQualityOfService
= ObjectAttributes
->SecurityQualityOfService
;
98 return STATUS_SUCCESS
;
102 Status
= STATUS_INVALID_PARAMETER
;
103 goto failbasiccleanup
;
108 AttributesCopy
= *ObjectAttributes
;
111 /* if Length isn't as expected, bail with an invalid parameter status code so
112 the caller knows he passed garbage... */
113 if(AttributesCopy
.Length
!= sizeof(OBJECT_ATTRIBUTES
))
115 Status
= STATUS_INVALID_PARAMETER
;
116 goto failbasiccleanup
;
119 if(CapturedObjectAttributes
!= NULL
)
121 CapturedObjectAttributes
->RootDirectory
= AttributesCopy
.RootDirectory
;
122 CapturedObjectAttributes
->Attributes
= AttributesCopy
.Attributes
;
124 if(AttributesCopy
.SecurityDescriptor
!= NULL
)
126 Status
= SeCaptureSecurityDescriptor(AttributesCopy
.SecurityDescriptor
,
130 &CapturedObjectAttributes
->SecurityDescriptor
);
131 if(!NT_SUCCESS(Status
))
133 DPRINT1("Unable to capture the security descriptor!!!\n");
134 goto failbasiccleanup
;
139 CapturedObjectAttributes
->SecurityDescriptor
= NULL
;
142 if(AttributesCopy
.SecurityQualityOfService
!= NULL
)
144 SECURITY_QUALITY_OF_SERVICE SafeQoS
;
146 RtlZeroMemory(&SafeQoS
, sizeof(SafeQoS
));
150 ProbeForRead(AttributesCopy
.SecurityQualityOfService
,
151 sizeof(SECURITY_QUALITY_OF_SERVICE
),
153 SafeQoS
= *(PSECURITY_QUALITY_OF_SERVICE
)AttributesCopy
.SecurityQualityOfService
;
157 Status
= _SEH_GetExceptionCode();
161 if(!NT_SUCCESS(Status
))
163 DPRINT1("Unable to capture QoS!!!\n");
164 goto failcleanupsdescriptor
;
167 if(SafeQoS
.Length
!= sizeof(SECURITY_QUALITY_OF_SERVICE
))
169 DPRINT1("Unable to capture QoS, wrong size!!!\n");
170 Status
= STATUS_INVALID_PARAMETER
;
171 goto failcleanupsdescriptor
;
174 CapturedObjectAttributes
->SecurityQualityOfService
= ExAllocatePool(PoolType
,
175 sizeof(SECURITY_QUALITY_OF_SERVICE
));
176 if(CapturedObjectAttributes
->SecurityQualityOfService
!= NULL
)
178 *CapturedObjectAttributes
->SecurityQualityOfService
= SafeQoS
;
182 Status
= STATUS_INSUFFICIENT_RESOURCES
;
183 goto failcleanupsdescriptor
;
188 CapturedObjectAttributes
->SecurityQualityOfService
= NULL
;
192 if(ObjectName
!= NULL
)
194 if(AttributesCopy
.ObjectName
!= NULL
)
196 UNICODE_STRING OriginalCopy
;
198 if(AccessMode
!= KernelMode
)
200 RtlZeroMemory(&OriginalCopy
, sizeof(OriginalCopy
));
204 /* probe the ObjectName structure and make a local stack copy of it */
205 ProbeForRead(AttributesCopy
.ObjectName
,
206 sizeof(UNICODE_STRING
),
208 OriginalCopy
= *AttributesCopy
.ObjectName
;
209 if(OriginalCopy
.Length
> 0)
211 ProbeForRead(OriginalCopy
.Buffer
,
218 Status
= _SEH_GetExceptionCode();
222 if(NT_SUCCESS(Status
))
224 if(OriginalCopy
.Length
> 0)
226 ObjectName
->MaximumLength
= OriginalCopy
.Length
+ sizeof(WCHAR
);
227 ObjectName
->Buffer
= ExAllocatePool(PoolType
,
228 ObjectName
->MaximumLength
);
229 if(ObjectName
->Buffer
!= NULL
)
233 /* no need to probe OriginalCopy.Buffer again, we already did that
234 when capturing the UNICODE_STRING structure itself */
235 RtlCopyMemory(ObjectName
->Buffer
, OriginalCopy
.Buffer
, OriginalCopy
.Length
);
236 ObjectName
->Buffer
[OriginalCopy
.Length
/ sizeof(WCHAR
)] = L
'\0';
240 Status
= _SEH_GetExceptionCode();
244 if(!NT_SUCCESS(Status
))
246 DPRINT1("ObpCaptureObjectAttributes failed to copy the unicode string!\n");
251 Status
= STATUS_INSUFFICIENT_RESOURCES
;
254 else if(AttributesCopy
.RootDirectory
!= NULL
/* && OriginalCopy.Length == 0 */)
256 /* if the caller specified a root directory, there must be an object name! */
257 Status
= STATUS_OBJECT_NAME_INVALID
;
262 DPRINT1("ObpCaptureObjectAttributes failed to probe the object name UNICODE_STRING structure!\n");
265 else /* AccessMode == KernelMode */
267 OriginalCopy
= *AttributesCopy
.ObjectName
;
269 if(OriginalCopy
.Length
> 0)
271 ObjectName
->MaximumLength
= OriginalCopy
.Length
+ sizeof(WCHAR
);
272 ObjectName
->Buffer
= ExAllocatePool(PoolType
,
273 ObjectName
->MaximumLength
);
274 if(ObjectName
->Buffer
!= NULL
)
276 RtlCopyMemory(ObjectName
->Buffer
, OriginalCopy
.Buffer
, OriginalCopy
.Length
);
277 ObjectName
->Buffer
[OriginalCopy
.Length
/ sizeof(WCHAR
)] = L
'\0';
281 Status
= STATUS_INSUFFICIENT_RESOURCES
;
284 else if(AttributesCopy
.RootDirectory
!= NULL
/* && OriginalCopy.Length == 0 */)
286 /* if the caller specified a root directory, there must be an object name! */
287 Status
= STATUS_OBJECT_NAME_INVALID
;
293 ObjectName
->Length
= ObjectName
->MaximumLength
= 0;
294 ObjectName
->Buffer
= NULL
;
298 if(!NT_SUCCESS(Status
))
300 if(ObjectName
->Buffer
)
302 ExFreePool(ObjectName
->Buffer
);
305 failcleanupsdescriptor
:
306 if(CapturedObjectAttributes
!= NULL
)
308 /* cleanup allocated resources */
309 SeReleaseSecurityDescriptor(CapturedObjectAttributes
->SecurityDescriptor
,
315 if(ObjectName
!= NULL
)
317 ObjectName
->Length
= ObjectName
->MaximumLength
= 0;
318 ObjectName
->Buffer
= NULL
;
320 if(CapturedObjectAttributes
!= NULL
)
322 RtlZeroMemory(CapturedObjectAttributes
, sizeof(CAPTURED_OBJECT_ATTRIBUTES
));
331 ObpReleaseObjectAttributes(IN PCAPTURED_OBJECT_ATTRIBUTES CapturedObjectAttributes OPTIONAL
,
332 IN PUNICODE_STRING ObjectName OPTIONAL
,
333 IN KPROCESSOR_MODE AccessMode
,
334 IN BOOLEAN CaptureIfKernel
)
336 /* WARNING - You need to pass the same parameters to this function as you passed
337 to ObpCaptureObjectAttributes() to avoid memory leaks */
338 if(AccessMode
!= KernelMode
|| CaptureIfKernel
)
340 if(CapturedObjectAttributes
!= NULL
)
342 if(CapturedObjectAttributes
->SecurityDescriptor
!= NULL
)
344 ExFreePool(CapturedObjectAttributes
->SecurityDescriptor
);
345 CapturedObjectAttributes
->SecurityDescriptor
= NULL
;
347 if(CapturedObjectAttributes
->SecurityQualityOfService
!= NULL
)
349 ExFreePool(CapturedObjectAttributes
->SecurityQualityOfService
);
350 CapturedObjectAttributes
->SecurityQualityOfService
= NULL
;
353 if(ObjectName
!= NULL
&&
354 ObjectName
->Length
> 0)
356 ExFreePool(ObjectName
->Buffer
);
362 /**********************************************************************
374 * Pointer to a unicode string that will contain the
375 * remaining path if the function returns successfully.
376 * The caller must free the buffer after use by calling
377 * RtlFreeUnicodeString ().
380 * Optional pointer to an object type. This is used to
381 * descide if a symbolic link object will be parsed or not.
386 ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes
,
387 PVOID
* ReturnedObject
,
388 PUNICODE_STRING RemainingPath
,
389 POBJECT_TYPE ObjectType
)
394 POBJECT_HEADER CurrentHeader
;
397 UNICODE_STRING PathString
;
399 PUNICODE_STRING ObjectName
;
403 DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, "
404 "RemainingPath %x)\n",ObjectAttributes
,ReturnedObject
,RemainingPath
);
405 DPRINT("ObjectAttributes->ObjectName %wZ\n",
406 ObjectAttributes
->ObjectName
);
408 RtlInitUnicodeString (RemainingPath
, NULL
);
410 if (ObjectAttributes
->RootDirectory
== NULL
)
412 ObReferenceObjectByPointer(NameSpaceRoot
,
416 CurrentObject
= NameSpaceRoot
;
420 Status
= ObReferenceObjectByHandle(ObjectAttributes
->RootDirectory
,
426 if (!NT_SUCCESS(Status
))
432 ObjectName
= ObjectAttributes
->ObjectName
;
433 if (ObjectName
->Length
== 0 ||
434 ObjectName
->Buffer
[0] == UNICODE_NULL
)
436 *ReturnedObject
= CurrentObject
;
437 return STATUS_SUCCESS
;
440 if (ObjectAttributes
->RootDirectory
== NULL
&&
441 ObjectName
->Buffer
[0] != L
'\\')
443 ObDereferenceObject (CurrentObject
);
444 return STATUS_UNSUCCESSFUL
;
447 /* Create a zero-terminated copy of the object name */
448 PathString
.Length
= ObjectName
->Length
;
449 PathString
.MaximumLength
= ObjectName
->Length
+ sizeof(WCHAR
);
450 PathString
.Buffer
= ExAllocatePool (NonPagedPool
,
451 PathString
.MaximumLength
);
452 if (PathString
.Buffer
== NULL
)
454 ObDereferenceObject (CurrentObject
);
455 return STATUS_INSUFFICIENT_RESOURCES
;
458 RtlCopyMemory (PathString
.Buffer
,
461 PathString
.Buffer
[PathString
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
463 current
= PathString
.Buffer
;
465 RootObject
= CurrentObject
;
466 Attributes
= ObjectAttributes
->Attributes
;
467 if (ObjectType
== ObSymbolicLinkType
)
468 Attributes
|= OBJ_OPENLINK
;
472 DPRINT("current %S\n",current
);
473 CurrentHeader
= BODY_TO_HEADER(CurrentObject
);
475 DPRINT("Current ObjectType %wZ\n",
476 &CurrentHeader
->ObjectType
->TypeName
);
478 if (CurrentHeader
->ObjectType
->Parse
== NULL
)
480 DPRINT("Current object can't parse\n");
483 Status
= CurrentHeader
->ObjectType
->Parse(CurrentObject
,
488 if (Status
== STATUS_REPARSE
)
490 /* reparse the object path */
491 NextObject
= NameSpaceRoot
;
492 current
= PathString
.Buffer
;
494 ObReferenceObjectByPointer(NextObject
,
500 if (NextObject
== NULL
)
504 ObDereferenceObject(CurrentObject
);
505 CurrentObject
= NextObject
;
509 RtlpCreateUnicodeString (RemainingPath
, current
, NonPagedPool
);
510 RtlFreeUnicodeString (&PathString
);
511 *ReturnedObject
= CurrentObject
;
513 return STATUS_SUCCESS
;
517 /**********************************************************************
519 * ObQueryNameString@16
530 ObQueryNameString (IN PVOID Object
,
531 OUT POBJECT_NAME_INFORMATION ObjectNameInfo
,
533 OUT PULONG ReturnLength
)
535 POBJECT_NAME_INFORMATION LocalInfo
;
536 POBJECT_HEADER ObjectHeader
;
537 ULONG LocalReturnLength
;
544 if (Length
< sizeof(OBJECT_NAME_INFORMATION
) + sizeof(WCHAR
))
545 return STATUS_INVALID_BUFFER_SIZE
;
547 ObjectNameInfo
->Name
.MaximumLength
= (USHORT
)(Length
- sizeof(OBJECT_NAME_INFORMATION
));
548 ObjectNameInfo
->Name
.Length
= 0;
549 ObjectNameInfo
->Name
.Buffer
=
550 (PWCHAR
)((ULONG_PTR
)ObjectNameInfo
+ sizeof(OBJECT_NAME_INFORMATION
));
551 ObjectNameInfo
->Name
.Buffer
[0] = 0;
553 ObjectHeader
= BODY_TO_HEADER(Object
);
555 if (ObjectHeader
->ObjectType
!= NULL
&&
556 ObjectHeader
->ObjectType
->QueryName
!= NULL
)
558 DPRINT ("Calling %x\n", ObjectHeader
->ObjectType
->QueryName
);
559 Status
= ObjectHeader
->ObjectType
->QueryName (Object
,
564 else if (ObjectHeader
->Name
.Length
> 0 && ObjectHeader
->Name
.Buffer
!= NULL
)
566 DPRINT ("Object does not have a 'QueryName' function\n");
568 if (ObjectHeader
->Parent
== NameSpaceRoot
)
570 DPRINT ("Reached the root directory\n");
571 ObjectNameInfo
->Name
.Length
= 0;
572 ObjectNameInfo
->Name
.Buffer
[0] = 0;
573 Status
= STATUS_SUCCESS
;
575 else if (ObjectHeader
->Parent
!= NULL
)
577 LocalInfo
= ExAllocatePool (NonPagedPool
,
578 sizeof(OBJECT_NAME_INFORMATION
) +
579 MAX_PATH
* sizeof(WCHAR
));
580 if (LocalInfo
== NULL
)
581 return STATUS_INSUFFICIENT_RESOURCES
;
583 Status
= ObQueryNameString (ObjectHeader
->Parent
,
585 MAX_PATH
* sizeof(WCHAR
),
587 if (!NT_SUCCESS (Status
))
589 ExFreePool (LocalInfo
);
593 Status
= RtlAppendUnicodeStringToString (&ObjectNameInfo
->Name
,
596 ExFreePool (LocalInfo
);
598 if (!NT_SUCCESS (Status
))
602 DPRINT ("Object path %wZ\n", &ObjectHeader
->Name
);
603 Status
= RtlAppendUnicodeToString (&ObjectNameInfo
->Name
,
605 if (!NT_SUCCESS (Status
))
608 Status
= RtlAppendUnicodeStringToString (&ObjectNameInfo
->Name
,
609 &ObjectHeader
->Name
);
613 DPRINT ("Object is unnamed\n");
615 ObjectNameInfo
->Name
.MaximumLength
= 0;
616 ObjectNameInfo
->Name
.Length
= 0;
617 ObjectNameInfo
->Name
.Buffer
= NULL
;
619 Status
= STATUS_SUCCESS
;
622 if (NT_SUCCESS (Status
))
624 ObjectNameInfo
->Name
.MaximumLength
=
625 (ObjectNameInfo
->Name
.Length
) ? ObjectNameInfo
->Name
.Length
+ sizeof(WCHAR
) : 0;
627 sizeof(OBJECT_NAME_INFORMATION
) + ObjectNameInfo
->Name
.MaximumLength
;
628 DPRINT ("Returned object path: %wZ\n", &ObjectNameInfo
->Name
);
635 /**********************************************************************
649 ObCreateObject (IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL
,
650 IN POBJECT_TYPE Type
,
651 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
652 IN KPROCESSOR_MODE AccessMode
,
653 IN OUT PVOID ParseContext OPTIONAL
,
655 IN ULONG PagedPoolCharge OPTIONAL
,
656 IN ULONG NonPagedPoolCharge OPTIONAL
,
660 UNICODE_STRING RemainingPath
;
661 POBJECT_HEADER Header
;
662 POBJECT_HEADER ParentHeader
= NULL
;
664 BOOLEAN ObjectAttached
= FALSE
;
666 PSECURITY_DESCRIPTOR NewSecurityDescriptor
= NULL
;
667 SECURITY_SUBJECT_CONTEXT SubjectContext
;
671 if(ObjectAttributesAccessMode
== UserMode
&& ObjectAttributes
!= NULL
)
673 Status
= STATUS_SUCCESS
;
676 ProbeForRead(ObjectAttributes
,
677 sizeof(OBJECT_ATTRIBUTES
),
682 Status
= _SEH_GetExceptionCode();
686 if(!NT_SUCCESS(Status
))
692 DPRINT("ObCreateObject(Type %p ObjectAttributes %p, Object %p)\n",
693 Type
, ObjectAttributes
, Object
);
697 DPRINT1("Invalid object type!\n");
698 return STATUS_INVALID_PARAMETER
;
701 if (ObjectAttributes
!= NULL
&&
702 ObjectAttributes
->ObjectName
!= NULL
&&
703 ObjectAttributes
->ObjectName
->Buffer
!= NULL
)
705 Status
= ObFindObject(ObjectAttributes
,
709 if (!NT_SUCCESS(Status
))
711 DPRINT1("ObFindObject() failed! (Status 0x%x)\n", Status
);
716 ParentHeader
= BODY_TO_HEADER(Parent
);
719 RemainingPath
.Buffer
== NULL
)
721 if (ParentHeader
->ObjectType
!= Type
722 || !(ObjectAttributes
->Attributes
& OBJ_OPENIF
))
724 ObDereferenceObject(Parent
);
725 return STATUS_OBJECT_NAME_COLLISION
;
728 return STATUS_OBJECT_EXISTS
;
733 RtlInitUnicodeString(&RemainingPath
, NULL
);
736 Header
= (POBJECT_HEADER
)ExAllocatePoolWithTag(NonPagedPool
,
737 OBJECT_ALLOC_SIZE(ObjectSize
),
739 if (Header
== NULL
) {
740 DPRINT1("Not enough memory!\n");
741 return STATUS_INSUFFICIENT_RESOURCES
;
744 RtlZeroMemory(Header
, OBJECT_ALLOC_SIZE(ObjectSize
));
746 /* Initialize the object header */
747 DPRINT("Initalizing header 0x%x (%wZ)\n", Header
, &Type
->TypeName
);
748 Header
->HandleCount
= 0;
749 Header
->RefCount
= 1;
750 Header
->ObjectType
= Type
;
751 if (ObjectAttributes
!= NULL
&&
752 ObjectAttributes
->Attributes
& OBJ_PERMANENT
)
754 Header
->Permanent
= TRUE
;
758 Header
->Permanent
= FALSE
;
761 if (ObjectAttributes
!= NULL
&&
762 ObjectAttributes
->Attributes
& OBJ_INHERIT
)
764 Header
->Inherit
= TRUE
;
768 Header
->Inherit
= FALSE
;
771 RtlInitUnicodeString(&(Header
->Name
),NULL
);
773 DPRINT("Getting Parent and adding entry\n");
774 if (ParentHeader
!= NULL
&&
775 ParentHeader
->ObjectType
== ObDirectoryType
&&
776 RemainingPath
.Buffer
!= NULL
)
778 NamePtr
= RemainingPath
.Buffer
;
779 if (*NamePtr
== L
'\\')
782 ObpAddEntryDirectory(Parent
,
786 ObjectAttached
= TRUE
;
789 DPRINT("About to call Create Routine\n");
790 if (Header
->ObjectType
->Create
!= NULL
)
792 DPRINT("Calling %x\n", Header
->ObjectType
->Create
);
793 Status
= Header
->ObjectType
->Create(HEADER_TO_BODY(Header
),
795 RemainingPath
.Buffer
,
797 if (!NT_SUCCESS(Status
))
799 if (ObjectAttached
== TRUE
)
801 ObpRemoveEntryDirectory(Header
);
805 ObDereferenceObject(Parent
);
807 RtlFreeUnicodeString(&Header
->Name
);
808 RtlFreeUnicodeString(&RemainingPath
);
810 DPRINT("Create Failed\n");
814 RtlFreeUnicodeString(&RemainingPath
);
816 SeCaptureSubjectContext(&SubjectContext
);
818 DPRINT("Security Assignment in progress\n");
819 /* Build the new security descriptor */
820 Status
= SeAssignSecurity((ParentHeader
!= NULL
) ? ParentHeader
->SecurityDescriptor
: NULL
,
821 (ObjectAttributes
!= NULL
) ? ObjectAttributes
->SecurityDescriptor
: NULL
,
822 &NewSecurityDescriptor
,
823 (Header
->ObjectType
== ObDirectoryType
),
825 Header
->ObjectType
->Mapping
,
827 if (NT_SUCCESS(Status
))
829 DPRINT("NewSecurityDescriptor %p\n", NewSecurityDescriptor
);
831 if (Header
->ObjectType
->Security
!= NULL
)
833 /* Call the security method */
834 Status
= Header
->ObjectType
->Security(HEADER_TO_BODY(Header
),
835 AssignSecurityDescriptor
,
837 NewSecurityDescriptor
,
842 /* Assign the security descriptor to the object header */
843 Status
= ObpAddSecurityDescriptor(NewSecurityDescriptor
,
844 &Header
->SecurityDescriptor
);
845 DPRINT("Object security descriptor %p\n", Header
->SecurityDescriptor
);
848 /* Release the new security descriptor */
849 SeDeassignSecurity(&NewSecurityDescriptor
);
852 DPRINT("Security Complete\n");
853 SeReleaseSubjectContext(&SubjectContext
);
857 *Object
= HEADER_TO_BODY(Header
);
861 return STATUS_SUCCESS
;
866 * FUNCTION: Increments the pointer reference count for a given object
868 * ObjectBody = Object's body
869 * DesiredAccess = Desired access to the object
870 * ObjectType = Points to the object type structure
871 * AccessMode = Type of access check to perform
877 ObReferenceObjectByPointer(IN PVOID Object
,
878 IN ACCESS_MASK DesiredAccess
,
879 IN POBJECT_TYPE ObjectType
,
880 IN KPROCESSOR_MODE AccessMode
)
882 POBJECT_HEADER Header
;
884 /* NOTE: should be possible to reference an object above APC_LEVEL! */
886 DPRINT("ObReferenceObjectByPointer(Object %x, ObjectType %x)\n",
889 Header
= BODY_TO_HEADER(Object
);
891 if (ObjectType
!= NULL
&& Header
->ObjectType
!= ObjectType
)
893 DPRINT("Failed %x (type was %x %S) should be %x %S\n",
896 Header
->ObjectType
->TypeName
.Buffer
,
898 ObjectType
->TypeName
.Buffer
);
899 return(STATUS_UNSUCCESSFUL
);
901 if (Header
->ObjectType
== PsProcessType
)
903 DPRINT("Ref p 0x%x refcount %d type %x ",
904 Object
, Header
->RefCount
, PsProcessType
);
905 DPRINT("eip %x\n", ((PULONG
)&Object
)[-1]);
907 if (Header
->ObjectType
== PsThreadType
)
909 DPRINT("Deref t 0x%x with refcount %d type %x ",
910 Object
, Header
->RefCount
, PsThreadType
);
911 DPRINT("eip %x\n", ((PULONG
)&Object
)[-1]);
914 if (Header
->RefCount
== 0 && !Header
->Permanent
)
916 if (Header
->ObjectType
== PsProcessType
)
918 return STATUS_PROCESS_IS_TERMINATING
;
920 if (Header
->ObjectType
== PsThreadType
)
922 return STATUS_THREAD_IS_TERMINATING
;
924 return(STATUS_UNSUCCESSFUL
);
927 if (1 == InterlockedIncrement(&Header
->RefCount
) && !Header
->Permanent
)
932 return(STATUS_SUCCESS
);
940 ObOpenObjectByPointer(IN POBJECT Object
,
941 IN ULONG HandleAttributes
,
942 IN PACCESS_STATE PassedAccessState
,
943 IN ACCESS_MASK DesiredAccess
,
944 IN POBJECT_TYPE ObjectType
,
945 IN KPROCESSOR_MODE AccessMode
,
952 DPRINT("ObOpenObjectByPointer()\n");
954 Status
= ObReferenceObjectByPointer(Object
,
958 if (!NT_SUCCESS(Status
))
963 Status
= ObCreateHandle(PsGetCurrentProcess(),
966 (BOOLEAN
)(HandleAttributes
& OBJ_INHERIT
),
969 ObDereferenceObject(Object
);
971 return STATUS_SUCCESS
;
976 ObpDeleteObject(POBJECT_HEADER Header
)
978 DPRINT("ObpDeleteObject(Header %p)\n", Header
);
979 if (KeGetCurrentIrql() != PASSIVE_LEVEL
)
981 DPRINT("ObpDeleteObject called at an unsupported IRQL. Use ObpDeleteObjectDpcLevel instead.\n");
985 if (Header
->SecurityDescriptor
!= NULL
)
987 ObpRemoveSecurityDescriptor(Header
->SecurityDescriptor
);
990 if (Header
->ObjectType
!= NULL
&&
991 Header
->ObjectType
->Delete
!= NULL
)
993 Header
->ObjectType
->Delete(HEADER_TO_BODY(Header
));
996 if (Header
->Name
.Buffer
!= NULL
)
998 ObpRemoveEntryDirectory(Header
);
999 RtlFreeUnicodeString(&Header
->Name
);
1002 DPRINT("ObPerformRetentionChecks() = Freeing object\n");
1005 return(STATUS_SUCCESS
);
1010 ObpDeleteObjectWorkRoutine (IN PVOID Parameter
)
1012 PRETENTION_CHECK_PARAMS Params
= (PRETENTION_CHECK_PARAMS
)Parameter
;
1013 /* ULONG Tag; */ /* See below */
1016 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
); /* We need PAGED_CODE somewhere... */
1018 /* Turn this on when we have ExFreePoolWithTag
1019 Tag = Params->ObjectHeader->ObjectType->Tag; */
1020 ObpDeleteObject(Params
->ObjectHeader
);
1022 /* ExFreePoolWithTag(Params, Tag); */
1027 ObpDeleteObjectDpcLevel(IN POBJECT_HEADER ObjectHeader
,
1028 IN LONG OldRefCount
)
1031 if (ObjectHeader
->RefCount
< 0)
1033 CPRINT("Object %p/%p has invalid reference count (%d)\n",
1034 ObjectHeader
, HEADER_TO_BODY(ObjectHeader
),
1035 ObjectHeader
->RefCount
);
1039 if (ObjectHeader
->HandleCount
< 0)
1041 CPRINT("Object %p/%p has invalid handle count (%d)\n",
1042 ObjectHeader
, HEADER_TO_BODY(ObjectHeader
),
1043 ObjectHeader
->HandleCount
);
1049 switch (KeGetCurrentIrql ())
1052 return ObpDeleteObject (ObjectHeader
);
1055 case DISPATCH_LEVEL
:
1057 PRETENTION_CHECK_PARAMS Params
;
1060 We use must succeed pool here because if the allocation fails
1061 then we leak memory.
1063 Params
= (PRETENTION_CHECK_PARAMS
)
1064 ExAllocatePoolWithTag(NonPagedPoolMustSucceed
,
1065 sizeof(RETENTION_CHECK_PARAMS
),
1066 ObjectHeader
->ObjectType
->Tag
);
1067 Params
->ObjectHeader
= ObjectHeader
;
1068 ExInitializeWorkItem(&Params
->WorkItem
,
1069 ObpDeleteObjectWorkRoutine
,
1071 ExQueueWorkItem(&Params
->WorkItem
,
1074 return STATUS_PENDING
;
1077 DPRINT("ObpDeleteObjectDpcLevel called at unsupported "
1078 "IRQL %u!\n", KeGetCurrentIrql());
1080 return STATUS_UNSUCCESSFUL
;
1083 return STATUS_SUCCESS
;
1087 /**********************************************************************
1089 * ObfReferenceObject@4
1092 * Increments a given object's reference count and performs
1096 * ObjectBody = Body of the object.
1104 ObfReferenceObject(IN PVOID Object
)
1106 POBJECT_HEADER Header
;
1110 Header
= BODY_TO_HEADER(Object
);
1112 /* No one should be referencing an object once we are deleting it. */
1113 if (InterlockedIncrement(&Header
->RefCount
) == 1 && !Header
->Permanent
)
1121 /**********************************************************************
1123 * ObfDereferenceObject@4
1126 * Decrements a given object's reference count and performs
1130 * ObjectBody = Body of the object.
1138 ObfDereferenceObject(IN PVOID Object
)
1140 POBJECT_HEADER Header
;
1146 /* Extract the object header. */
1147 Header
= BODY_TO_HEADER(Object
);
1148 Permanent
= Header
->Permanent
;
1151 Drop our reference and get the new count so we can tell if this was the
1154 NewRefCount
= InterlockedDecrement(&Header
->RefCount
);
1155 DPRINT("ObfDereferenceObject(0x%x)==%d (%wZ)\n", Object
, NewRefCount
, &Header
->ObjectType
->TypeName
);
1156 ASSERT(NewRefCount
>= 0);
1158 /* Check whether the object can now be deleted. */
1159 if (NewRefCount
== 0 &&
1162 ObpDeleteObjectDpcLevel(Header
, NewRefCount
);
1167 /**********************************************************************
1169 * ObGetObjectPointerCount@4
1172 * Retrieves the pointer(reference) count of the given object.
1175 * ObjectBody = Body of the object.
1183 ObGetObjectPointerCount(PVOID Object
)
1185 POBJECT_HEADER Header
;
1190 Header
= BODY_TO_HEADER(Object
);
1192 return Header
->RefCount
;
1196 /**********************************************************************
1198 * ObGetObjectHandleCount@4
1201 * Retrieves the handle count of the given object.
1204 * ObjectBody = Body of the object.
1210 ObGetObjectHandleCount(PVOID Object
)
1212 POBJECT_HEADER Header
;
1217 Header
= BODY_TO_HEADER(Object
);
1219 return Header
->HandleCount
;
1223 /**********************************************************************
1225 * ObDereferenceObject@4
1228 * Decrements a given object's reference count and performs
1232 * ObjectBody = Body of the object.
1240 #ifdef ObDereferenceObject
1241 #undef ObDereferenceObject
1245 ObDereferenceObject(IN PVOID Object
)
1247 ObfDereferenceObject(Object
);