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
;
25 /* FUNCTIONS ************************************************************/
29 ObpCaptureObjectName(IN OUT PUNICODE_STRING CapturedName
,
30 IN PUNICODE_STRING ObjectName
,
31 IN KPROCESSOR_MODE AccessMode
)
33 NTSTATUS Status
= STATUS_SUCCESS
;
34 UNICODE_STRING LocalName
= {}; /* <= GCC 4.0 + Optimizer */
36 /* First Probe the String */
37 DPRINT("ObpCaptureObjectName: %wZ\n", ObjectName
);
38 if (AccessMode
!= KernelMode
)
40 DPRINT("Probing Struct\n");
43 /* FIXME: Explorer or win32 broken I think */
45 ProbeForRead(ObjectName
,
46 sizeof(UNICODE_STRING
),
49 LocalName
= *ObjectName
;
53 Status
= _SEH_GetExceptionCode();
57 if (NT_SUCCESS(Status
))
59 DPRINT("Probing OK\n");
63 DPRINT("Probing buffer\n");
64 ProbeForRead(LocalName
.Buffer
,
71 Status
= _SEH_GetExceptionCode();
76 /* Fail if anything up to here died */
77 if (!NT_SUCCESS(Status
))
79 DPRINT1("Probing failed\n");
85 LocalName
= *ObjectName
;
88 /* Make sure there really is a string */
89 DPRINT("Probing OK\n");
92 /* Allocate a non-paged buffer for this string */
93 DPRINT("Capturing String\n");
94 CapturedName
->Length
= LocalName
.Length
;
95 CapturedName
->MaximumLength
= LocalName
.Length
+ sizeof(WCHAR
);
96 CapturedName
->Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
97 CapturedName
->MaximumLength
,
98 TAG('O','b','N','m'));
100 /* Copy the string and null-terminate it */
101 RtlMoveMemory(CapturedName
->Buffer
, LocalName
.Buffer
, LocalName
.Length
);
102 CapturedName
->Buffer
[LocalName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
103 DPRINT("String Captured: %p, %wZ\n", CapturedName
, CapturedName
);
111 ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes
,
112 IN KPROCESSOR_MODE AccessMode
,
113 IN POBJECT_TYPE ObjectType
,
114 IN POBJECT_CREATE_INFORMATION ObjectCreateInfo
,
115 OUT PUNICODE_STRING ObjectName
)
117 NTSTATUS Status
= STATUS_SUCCESS
;
118 PSECURITY_DESCRIPTOR SecurityDescriptor
;
119 PSECURITY_QUALITY_OF_SERVICE SecurityQos
;
120 PUNICODE_STRING LocalObjectName
= NULL
;
122 /* Zero out the Capture Data */
123 DPRINT("ObpCaptureObjectAttributes\n");
124 RtlZeroMemory(ObjectCreateInfo
, sizeof(OBJECT_CREATE_INFORMATION
));
126 /* Check if we got Oba */
127 if (ObjectAttributes
)
129 if (AccessMode
!= KernelMode
)
131 DPRINT("Probing OBA\n");
134 /* FIXME: SMSS SENDS BULLSHIT. */
136 ProbeForRead(ObjectAttributes
,
137 sizeof(ObjectAttributes
),
143 Status
= _SEH_GetExceptionCode();
148 /* Validate the Size */
149 DPRINT("Validating OBA\n");
150 if (ObjectAttributes
->Length
!= sizeof(OBJECT_ATTRIBUTES
))
152 Status
= STATUS_INVALID_PARAMETER
;
155 /* Fail if SEH or Size Validation failed */
156 if(!NT_SUCCESS(Status
))
158 DPRINT1("ObpCaptureObjectAttributes failed to probe object attributes\n");
162 /* Set some Create Info */
163 DPRINT("Creating OBCI\n");
164 ObjectCreateInfo
->RootDirectory
= ObjectAttributes
->RootDirectory
;
165 ObjectCreateInfo
->Attributes
= ObjectAttributes
->Attributes
;
166 LocalObjectName
= ObjectAttributes
->ObjectName
;
167 SecurityDescriptor
= ObjectAttributes
->SecurityDescriptor
;
168 SecurityQos
= ObjectAttributes
->SecurityQualityOfService
;
170 /* Validate the SD */
171 if (SecurityDescriptor
)
173 DPRINT("Probing SD: %x\n", SecurityDescriptor
);
174 Status
= SeCaptureSecurityDescriptor(SecurityDescriptor
,
178 &ObjectCreateInfo
->SecurityDescriptor
);
179 if(!NT_SUCCESS(Status
))
181 DPRINT1("Unable to capture the security descriptor!!!\n");
182 ObjectCreateInfo
->SecurityDescriptor
= NULL
;
186 DPRINT("Probe done\n");
187 ObjectCreateInfo
->SecurityDescriptorCharge
= 0; /* FIXME */
188 ObjectCreateInfo
->ProbeMode
= AccessMode
;
191 /* Validate the QoS */
194 if (AccessMode
!= KernelMode
)
196 DPRINT("Probing QoS\n");
199 ProbeForRead(SecurityQos
,
200 sizeof(SECURITY_QUALITY_OF_SERVICE
),
205 Status
= _SEH_GetExceptionCode();
210 if(!NT_SUCCESS(Status
))
212 DPRINT1("Unable to capture QoS!!!\n");
216 ObjectCreateInfo
->SecurityQualityOfService
= *SecurityQos
;
217 ObjectCreateInfo
->SecurityQos
= &ObjectCreateInfo
->SecurityQualityOfService
;
221 /* Clear Local Object Name */
222 DPRINT("Clearing name\n");
223 RtlZeroMemory(ObjectName
, sizeof(UNICODE_STRING
));
225 /* Now check if the Object Attributes had an Object Name */
228 DPRINT("Name Buffer: %x\n", LocalObjectName
->Buffer
);
229 Status
= ObpCaptureObjectName(ObjectName
,
235 /* He can't have specified a Root Directory */
236 if (ObjectCreateInfo
->RootDirectory
)
238 DPRINT1("Invalid name\n");
239 Status
= STATUS_OBJECT_NAME_INVALID
;
244 if (!NT_SUCCESS(Status
))
246 DPRINT1("Failed to capture, cleaning up\n");
247 ObpReleaseCapturedAttributes(ObjectCreateInfo
);
250 DPRINT("Return to caller\n");
257 ObpReleaseCapturedAttributes(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo
)
259 /* Release the SD, it's the only thing we allocated */
260 if (ObjectCreateInfo
->SecurityDescriptor
)
262 SeReleaseSecurityDescriptor(ObjectCreateInfo
->SecurityDescriptor
,
263 ObjectCreateInfo
->ProbeMode
,
265 ObjectCreateInfo
->SecurityDescriptor
= NULL
;
270 /**********************************************************************
282 * Pointer to a unicode string that will contain the
283 * remaining path if the function returns successfully.
284 * The caller must free the buffer after use by calling
285 * RtlFreeUnicodeString ().
288 * Optional pointer to an object type. This is used to
289 * descide if a symbolic link object will be parsed or not.
294 ObFindObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo
,
295 PUNICODE_STRING ObjectName
,
296 PVOID
* ReturnedObject
,
297 PUNICODE_STRING RemainingPath
,
298 POBJECT_TYPE ObjectType
)
303 POBJECT_HEADER CurrentHeader
;
306 UNICODE_STRING PathString
;
311 DPRINT("ObFindObject(ObjectCreateInfo %x, ReturnedObject %x, "
312 "RemainingPath %x)\n",ObjectCreateInfo
,ReturnedObject
,RemainingPath
);
314 RtlInitUnicodeString (RemainingPath
, NULL
);
316 if (ObjectCreateInfo
->RootDirectory
== NULL
)
318 ObReferenceObjectByPointer(NameSpaceRoot
,
322 CurrentObject
= NameSpaceRoot
;
326 Status
= ObReferenceObjectByHandle(ObjectCreateInfo
->RootDirectory
,
332 if (!NT_SUCCESS(Status
))
338 if (ObjectName
->Length
== 0 ||
339 ObjectName
->Buffer
[0] == UNICODE_NULL
)
341 *ReturnedObject
= CurrentObject
;
342 return STATUS_SUCCESS
;
345 if (ObjectCreateInfo
->RootDirectory
== NULL
&&
346 ObjectName
->Buffer
[0] != L
'\\')
348 ObDereferenceObject (CurrentObject
);
350 return STATUS_UNSUCCESSFUL
;
353 /* Create a zero-terminated copy of the object name */
354 PathString
.Length
= ObjectName
->Length
;
355 PathString
.MaximumLength
= ObjectName
->Length
+ sizeof(WCHAR
);
356 PathString
.Buffer
= ExAllocatePool (NonPagedPool
,
357 PathString
.MaximumLength
);
358 if (PathString
.Buffer
== NULL
)
360 ObDereferenceObject (CurrentObject
);
361 return STATUS_INSUFFICIENT_RESOURCES
;
364 RtlCopyMemory (PathString
.Buffer
,
367 PathString
.Buffer
[PathString
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
369 current
= PathString
.Buffer
;
371 RootObject
= CurrentObject
;
372 Attributes
= ObjectCreateInfo
->Attributes
;
373 if (ObjectType
== ObSymbolicLinkType
)
374 Attributes
|= OBJ_OPENLINK
;
378 DPRINT("current %S\n",current
);
379 CurrentHeader
= BODY_TO_HEADER(CurrentObject
);
381 DPRINT("Current ObjectType %wZ\n",
382 &CurrentHeader
->Type
->Name
);
384 if (CurrentHeader
->Type
->TypeInfo
.ParseProcedure
== NULL
)
386 DPRINT("Current object can't parse\n");
389 Status
= CurrentHeader
->Type
->TypeInfo
.ParseProcedure(CurrentObject
,
394 if (Status
== STATUS_REPARSE
)
396 /* reparse the object path */
397 NextObject
= NameSpaceRoot
;
398 current
= PathString
.Buffer
;
400 ObReferenceObjectByPointer(NextObject
,
406 if (NextObject
== NULL
)
410 ObDereferenceObject(CurrentObject
);
411 CurrentObject
= NextObject
;
416 RtlpCreateUnicodeString (RemainingPath
, current
, NonPagedPool
);
419 RtlFreeUnicodeString (&PathString
);
420 *ReturnedObject
= CurrentObject
;
422 return STATUS_SUCCESS
;
426 /**********************************************************************
428 * ObQueryNameString@16
439 ObQueryNameString (IN PVOID Object
,
440 OUT POBJECT_NAME_INFORMATION ObjectNameInfo
,
442 OUT PULONG ReturnLength
)
444 POBJECT_NAME_INFORMATION LocalInfo
;
445 POBJECT_HEADER ObjectHeader
;
446 ULONG LocalReturnLength
;
453 if (Length
< sizeof(OBJECT_NAME_INFORMATION
) + sizeof(WCHAR
))
454 return STATUS_INVALID_BUFFER_SIZE
;
456 ObjectNameInfo
->Name
.MaximumLength
= (USHORT
)(Length
- sizeof(OBJECT_NAME_INFORMATION
));
457 ObjectNameInfo
->Name
.Length
= 0;
458 ObjectNameInfo
->Name
.Buffer
=
459 (PWCHAR
)((ULONG_PTR
)ObjectNameInfo
+ sizeof(OBJECT_NAME_INFORMATION
));
460 ObjectNameInfo
->Name
.Buffer
[0] = 0;
462 ObjectHeader
= BODY_TO_HEADER(Object
);
464 if (ObjectHeader
->Type
!= NULL
&&
465 ObjectHeader
->Type
->TypeInfo
.QueryNameProcedure
!= NULL
)
467 DPRINT ("Calling %x\n", ObjectHeader
->Type
->TypeInfo
.QueryNameProcedure
);
468 Status
= ObjectHeader
->Type
->TypeInfo
.QueryNameProcedure (Object
,
473 else if (HEADER_TO_OBJECT_NAME(ObjectHeader
)->Name
.Length
> 0 && HEADER_TO_OBJECT_NAME(ObjectHeader
)->Name
.Buffer
!= NULL
)
475 DPRINT ("Object does not have a 'QueryName' function\n");
477 if (HEADER_TO_OBJECT_NAME(ObjectHeader
)->Directory
== NameSpaceRoot
)
479 DPRINT ("Reached the root directory\n");
480 ObjectNameInfo
->Name
.Length
= 0;
481 ObjectNameInfo
->Name
.Buffer
[0] = 0;
482 Status
= STATUS_SUCCESS
;
484 else if (HEADER_TO_OBJECT_NAME(ObjectHeader
)->Directory
!= NULL
)
486 LocalInfo
= ExAllocatePool (NonPagedPool
,
487 sizeof(OBJECT_NAME_INFORMATION
) +
488 MAX_PATH
* sizeof(WCHAR
));
489 if (LocalInfo
== NULL
)
490 return STATUS_INSUFFICIENT_RESOURCES
;
492 Status
= ObQueryNameString (HEADER_TO_OBJECT_NAME(ObjectHeader
)->Directory
,
494 MAX_PATH
* sizeof(WCHAR
),
496 if (!NT_SUCCESS (Status
))
498 ExFreePool (LocalInfo
);
502 Status
= RtlAppendUnicodeStringToString (&ObjectNameInfo
->Name
,
505 ExFreePool (LocalInfo
);
507 if (!NT_SUCCESS (Status
))
511 DPRINT ("Object path %wZ\n", &HEADER_TO_OBJECT_NAME(ObjectHeader
)->Name
);
512 Status
= RtlAppendUnicodeToString (&ObjectNameInfo
->Name
,
514 if (!NT_SUCCESS (Status
))
517 Status
= RtlAppendUnicodeStringToString (&ObjectNameInfo
->Name
,
518 &HEADER_TO_OBJECT_NAME(ObjectHeader
)->Name
);
522 DPRINT ("Object is unnamed\n");
524 ObjectNameInfo
->Name
.MaximumLength
= 0;
525 ObjectNameInfo
->Name
.Length
= 0;
526 ObjectNameInfo
->Name
.Buffer
= NULL
;
528 Status
= STATUS_SUCCESS
;
531 if (NT_SUCCESS (Status
))
533 ObjectNameInfo
->Name
.MaximumLength
=
534 (ObjectNameInfo
->Name
.Length
) ? ObjectNameInfo
->Name
.Length
+ sizeof(WCHAR
) : 0;
536 sizeof(OBJECT_NAME_INFORMATION
) + ObjectNameInfo
->Name
.MaximumLength
;
537 DPRINT ("Returned object path: %wZ\n", &ObjectNameInfo
->Name
);
545 ObpAllocateObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo
,
546 PUNICODE_STRING ObjectName
,
547 POBJECT_TYPE ObjectType
,
549 POBJECT_HEADER
*ObjectHeader
)
551 POBJECT_HEADER Header
;
552 BOOLEAN HasHandleInfo
= FALSE
;
553 BOOLEAN HasNameInfo
= FALSE
;
554 BOOLEAN HasCreatorInfo
= FALSE
;
555 POBJECT_HEADER_HANDLE_INFO HandleInfo
;
556 POBJECT_HEADER_NAME_INFO NameInfo
;
557 POBJECT_HEADER_CREATOR_INFO CreatorInfo
;
559 ULONG FinalSize
= ObjectSize
;
562 /* If we don't have an Object Type yet, force NonPaged */
563 DPRINT("ObpAllocateObject\n");
566 PoolType
= NonPagedPool
;
567 Tag
= TAG('O', 'b', 'j', 'T');
571 PoolType
= ObjectType
->TypeInfo
.PoolType
;
572 Tag
= ObjectType
->Key
;
575 DPRINT("Checking ObjectName: %x\n", ObjectName
);
576 /* Check if the Object has a name */
577 if (ObjectName
->Buffer
)
579 FinalSize
+= sizeof(OBJECT_HEADER_NAME_INFO
);
585 /* Check if the Object maintains handle counts */
586 DPRINT("Checking ObjectType->TypeInfo: %x\n", &ObjectType
->TypeInfo
);
587 if (ObjectType
->TypeInfo
.MaintainHandleCount
)
589 FinalSize
+= sizeof(OBJECT_HEADER_HANDLE_INFO
);
590 HasHandleInfo
= TRUE
;
593 /* Check if the Object maintains type lists */
594 if (ObjectType
->TypeInfo
.MaintainTypeList
)
596 FinalSize
+= sizeof(OBJECT_HEADER_CREATOR_INFO
);
597 HasCreatorInfo
= TRUE
;
601 /* Allocate memory for the Object and Header */
602 DPRINT("Allocating: %x %x\n", FinalSize
, Tag
);
603 Header
= ExAllocatePoolWithTag(PoolType
, FinalSize
, Tag
);
605 DPRINT1("Not enough memory!\n");
606 return STATUS_INSUFFICIENT_RESOURCES
;
609 /* Initialize Handle Info */
612 HandleInfo
= (POBJECT_HEADER_HANDLE_INFO
)Header
;
613 DPRINT("Info: %x\n", HandleInfo
);
614 HandleInfo
->SingleEntry
.HandleCount
= 0;
615 Header
= (POBJECT_HEADER
)(HandleInfo
+ 1);
618 /* Initialize the Object Name Info */
621 NameInfo
= (POBJECT_HEADER_NAME_INFO
)Header
;
622 DPRINT("Info: %x %wZ\n", NameInfo
, ObjectName
);
623 NameInfo
->Name
= *ObjectName
;
624 NameInfo
->Directory
= NULL
;
625 Header
= (POBJECT_HEADER
)(NameInfo
+ 1);
628 /* Initialize Creator Info */
631 CreatorInfo
= (POBJECT_HEADER_CREATOR_INFO
)Header
;
632 DPRINT("Info: %x\n", CreatorInfo
);
633 /* FIXME: Needs Alex's Init patch
634 * CreatorInfo->CreatorUniqueProcess = PsGetCurrentProcessId();
636 InitializeListHead(&CreatorInfo
->TypeList
);
637 Header
= (POBJECT_HEADER
)(CreatorInfo
+ 1);
640 /* Initialize the object header */
641 RtlZeroMemory(Header
, ObjectSize
);
642 DPRINT("Initalized header %p\n", Header
);
643 Header
->HandleCount
= 0;
644 Header
->PointerCount
= 1;
645 Header
->Type
= ObjectType
;
646 Header
->Flags
= OB_FLAG_CREATE_INFO
;
648 /* Set the Offsets for the Info */
651 Header
->HandleInfoOffset
= HasNameInfo
* sizeof(OBJECT_HEADER_NAME_INFO
) +
652 sizeof(OBJECT_HEADER_HANDLE_INFO
) +
653 HasCreatorInfo
* sizeof(OBJECT_HEADER_CREATOR_INFO
);
654 Header
->Flags
|= OB_FLAG_SINGLE_PROCESS
;
658 Header
->NameInfoOffset
= sizeof(OBJECT_HEADER_NAME_INFO
) +
659 HasCreatorInfo
* sizeof(OBJECT_HEADER_CREATOR_INFO
);
661 if (HasCreatorInfo
) Header
->Flags
|= OB_FLAG_CREATOR_INFO
;
663 if (ObjectCreateInfo
&& ObjectCreateInfo
->Attributes
& OBJ_PERMANENT
)
665 Header
->Flags
|= OB_FLAG_PERMANENT
;
667 if (ObjectCreateInfo
&& ObjectCreateInfo
->Attributes
& OBJ_EXCLUSIVE
)
669 Header
->Flags
|= OB_FLAG_EXCLUSIVE
;
672 /* Link stuff to Object Header */
673 Header
->ObjectCreateInfo
= ObjectCreateInfo
;
676 *ObjectHeader
= Header
;
677 return STATUS_SUCCESS
;
680 /**********************************************************************
695 ObCreateObject(IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL
,
696 IN POBJECT_TYPE Type
,
697 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
698 IN KPROCESSOR_MODE AccessMode
,
699 IN OUT PVOID ParseContext OPTIONAL
,
701 IN ULONG PagedPoolCharge OPTIONAL
,
702 IN ULONG NonPagedPoolCharge OPTIONAL
,
706 POBJECT_CREATE_INFORMATION ObjectCreateInfo
;
707 UNICODE_STRING ObjectName
;
708 POBJECT_HEADER Header
;
710 DPRINT("ObCreateObject(Type %p ObjectAttributes %p, Object %p)\n",
711 Type
, ObjectAttributes
, Object
);
713 /* Allocate a Buffer for the Object Create Info */
714 DPRINT("Allocating Create Buffer\n");
715 ObjectCreateInfo
= ExAllocatePoolWithTag(NonPagedPool
,
716 sizeof(*ObjectCreateInfo
),
717 TAG('O','b','C', 'I'));
719 /* Capture all the info */
720 DPRINT("Capturing Create Info\n");
721 Status
= ObpCaptureObjectAttributes(ObjectAttributes
,
727 if (NT_SUCCESS(Status
))
729 /* Allocate the Object */
730 DPRINT("Allocating: %wZ\n", &ObjectName
);
731 Status
= ObpAllocateObject(ObjectCreateInfo
,
734 OBJECT_ALLOC_SIZE(ObjectSize
),
737 if (NT_SUCCESS(Status
))
739 /* Return the Object */
740 DPRINT("Returning Object\n");
741 *Object
= &Header
->Body
;
743 /* Return to caller, leave the Capture Info Alive for ObInsert */
747 /* Release the Capture Info, we don't need it */
748 DPRINT1("Allocation failed\n");
749 ObpReleaseCapturedAttributes(ObjectCreateInfo
);
750 if (ObjectName
.Buffer
) ExFreePool(ObjectName
.Buffer
);
753 /* We failed, so release the Buffer */
754 DPRINT1("Capture failed\n");
755 ExFreePool(ObjectCreateInfo
);
760 * FUNCTION: Increments the pointer reference count for a given object
762 * ObjectBody = Object's body
763 * DesiredAccess = Desired access to the object
764 * ObjectType = Points to the object type structure
765 * AccessMode = Type of access check to perform
771 ObReferenceObjectByPointer(IN PVOID Object
,
772 IN ACCESS_MASK DesiredAccess
,
773 IN POBJECT_TYPE ObjectType
,
774 IN KPROCESSOR_MODE AccessMode
)
776 POBJECT_HEADER Header
;
778 /* NOTE: should be possible to reference an object above APC_LEVEL! */
780 DPRINT("ObReferenceObjectByPointer(Object %x, ObjectType %x)\n",
783 Header
= BODY_TO_HEADER(Object
);
785 if (ObjectType
!= NULL
&& Header
->Type
!= ObjectType
)
787 DPRINT("Failed %p (type was %x %wZ) should be %x %wZ\n",
790 &BODY_TO_HEADER(Header
->Type
)->NameInfo
,
792 &BODY_TO_HEADER(ObjectType
)->NameInfo
);
793 return(STATUS_UNSUCCESSFUL
);
795 if (Header
->Type
== PsProcessType
)
797 DPRINT("Ref p 0x%x PointerCount %d type %x ",
798 Object
, Header
->PointerCount
, PsProcessType
);
799 DPRINT("eip %x\n", ((PULONG
)&Object
)[-1]);
801 if (Header
->Type
== PsThreadType
)
803 DPRINT("Deref t 0x%x with PointerCount %d type %x ",
804 Object
, Header
->PointerCount
, PsThreadType
);
805 DPRINT("eip %x\n", ((PULONG
)&Object
)[-1]);
808 if (Header
->PointerCount
== 0 && !(Header
->Flags
& OB_FLAG_PERMANENT
))
810 if (Header
->Type
== PsProcessType
)
812 return STATUS_PROCESS_IS_TERMINATING
;
814 if (Header
->Type
== PsThreadType
)
816 return STATUS_THREAD_IS_TERMINATING
;
818 return(STATUS_UNSUCCESSFUL
);
821 if (1 == InterlockedIncrement(&Header
->PointerCount
) && !(Header
->Flags
& OB_FLAG_PERMANENT
))
826 return(STATUS_SUCCESS
);
834 ObOpenObjectByPointer(IN POBJECT Object
,
835 IN ULONG HandleAttributes
,
836 IN PACCESS_STATE PassedAccessState
,
837 IN ACCESS_MASK DesiredAccess
,
838 IN POBJECT_TYPE ObjectType
,
839 IN KPROCESSOR_MODE AccessMode
,
846 DPRINT("ObOpenObjectByPointer()\n");
848 Status
= ObReferenceObjectByPointer(Object
,
852 if (!NT_SUCCESS(Status
))
857 Status
= ObpCreateHandle(PsGetCurrentProcess(),
860 (BOOLEAN
)(HandleAttributes
& OBJ_INHERIT
),
863 ObDereferenceObject(Object
);
865 return STATUS_SUCCESS
;
870 ObpDeleteObject(POBJECT_HEADER Header
)
872 PVOID HeaderLocation
= Header
;
873 POBJECT_HEADER_HANDLE_INFO HandleInfo
;
874 POBJECT_HEADER_NAME_INFO NameInfo
;
875 POBJECT_HEADER_CREATOR_INFO CreatorInfo
;
877 DPRINT("ObpDeleteObject(Header %p)\n", Header
);
878 if (KeGetCurrentIrql() != PASSIVE_LEVEL
)
880 DPRINT("ObpDeleteObject called at an unsupported IRQL. Use ObpDeleteObjectDpcLevel instead.\n");
884 if (Header
->Type
!= NULL
&&
885 Header
->Type
->TypeInfo
.DeleteProcedure
!= NULL
)
887 Header
->Type
->TypeInfo
.DeleteProcedure(&Header
->Body
);
890 if (Header
->SecurityDescriptor
!= NULL
)
892 ObpRemoveSecurityDescriptor(Header
->SecurityDescriptor
);
895 if (HEADER_TO_OBJECT_NAME(Header
))
897 if(HEADER_TO_OBJECT_NAME(Header
)->Name
.Buffer
)
899 ExFreePool(HEADER_TO_OBJECT_NAME(Header
)->Name
.Buffer
);
902 if (Header
->ObjectCreateInfo
)
904 ObpReleaseCapturedAttributes(Header
->ObjectCreateInfo
);
905 ExFreePool(Header
->ObjectCreateInfo
);
908 /* To find the header, walk backwards from how we allocated */
909 if ((CreatorInfo
= HEADER_TO_CREATOR_INFO(Header
)))
911 HeaderLocation
= CreatorInfo
;
913 if ((NameInfo
= HEADER_TO_OBJECT_NAME(Header
)))
915 HeaderLocation
= NameInfo
;
917 if ((HandleInfo
= HEADER_TO_HANDLE_INFO(Header
)))
919 HeaderLocation
= HandleInfo
;
922 DPRINT("ObPerformRetentionChecks() = Freeing object\n");
923 ExFreePool(HeaderLocation
);
925 return(STATUS_SUCCESS
);
930 ObpDeleteObjectWorkRoutine (IN PVOID Parameter
)
932 PRETENTION_CHECK_PARAMS Params
= (PRETENTION_CHECK_PARAMS
)Parameter
;
933 /* ULONG Tag; */ /* See below */
936 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
); /* We need PAGED_CODE somewhere... */
938 /* Turn this on when we have ExFreePoolWithTag
939 Tag = Params->ObjectHeader->Type->Tag; */
940 ObpDeleteObject(Params
->ObjectHeader
);
942 /* ExFreePoolWithTag(Params, Tag); */
947 ObpDeleteObjectDpcLevel(IN POBJECT_HEADER ObjectHeader
,
948 IN LONG OldPointerCount
)
951 if (ObjectHeader
->PointerCount
< 0)
953 CPRINT("Object %p/%p has invalid reference count (%d)\n",
954 ObjectHeader
, HEADER_TO_BODY(ObjectHeader
),
955 ObjectHeader
->PointerCount
);
959 if (ObjectHeader
->HandleCount
< 0)
961 CPRINT("Object %p/%p has invalid handle count (%d)\n",
962 ObjectHeader
, HEADER_TO_BODY(ObjectHeader
),
963 ObjectHeader
->HandleCount
);
969 switch (KeGetCurrentIrql ())
972 return ObpDeleteObject (ObjectHeader
);
977 PRETENTION_CHECK_PARAMS Params
;
980 We use must succeed pool here because if the allocation fails
983 Params
= (PRETENTION_CHECK_PARAMS
)
984 ExAllocatePoolWithTag(NonPagedPoolMustSucceed
,
985 sizeof(RETENTION_CHECK_PARAMS
),
986 ObjectHeader
->Type
->Key
);
987 Params
->ObjectHeader
= ObjectHeader
;
988 ExInitializeWorkItem(&Params
->WorkItem
,
989 ObpDeleteObjectWorkRoutine
,
991 ExQueueWorkItem(&Params
->WorkItem
,
994 return STATUS_PENDING
;
997 DPRINT("ObpDeleteObjectDpcLevel called at unsupported "
998 "IRQL %u!\n", KeGetCurrentIrql());
1000 return STATUS_UNSUCCESSFUL
;
1003 return STATUS_SUCCESS
;
1007 /**********************************************************************
1009 * ObfReferenceObject@4
1012 * Increments a given object's reference count and performs
1016 * ObjectBody = Body of the object.
1024 ObfReferenceObject(IN PVOID Object
)
1026 POBJECT_HEADER Header
;
1030 Header
= BODY_TO_HEADER(Object
);
1032 /* No one should be referencing an object once we are deleting it. */
1033 if (InterlockedIncrement(&Header
->PointerCount
) == 1 && !(Header
->Flags
& OB_FLAG_PERMANENT
))
1040 /**********************************************************************
1042 * ObfDereferenceObject@4
1045 * Decrements a given object's reference count and performs
1049 * ObjectBody = Body of the object.
1057 ObfDereferenceObject(IN PVOID Object
)
1059 POBJECT_HEADER Header
;
1060 LONG NewPointerCount
;
1065 /* Extract the object header. */
1066 Header
= BODY_TO_HEADER(Object
);
1067 Permanent
= Header
->Flags
& OB_FLAG_PERMANENT
;
1070 Drop our reference and get the new count so we can tell if this was the
1073 NewPointerCount
= InterlockedDecrement(&Header
->PointerCount
);
1074 DPRINT("ObfDereferenceObject(0x%x)==%d\n", Object
, NewPointerCount
);
1075 ASSERT(NewPointerCount
>= 0);
1077 /* Check whether the object can now be deleted. */
1078 if (NewPointerCount
== 0 &&
1081 ObpDeleteObjectDpcLevel(Header
, NewPointerCount
);
1087 ObInitializeFastReference(IN PEX_FAST_REF FastRef
,
1090 /* FIXME: Fast Referencing is Unimplemented */
1091 FastRef
->Object
= Object
;
1097 ObFastReferenceObject(IN PEX_FAST_REF FastRef
)
1099 /* FIXME: Fast Referencing is Unimplemented */
1101 /* Do a normal Reference */
1102 ObReferenceObject(FastRef
->Object
);
1104 /* Return the Object */
1105 return FastRef
->Object
;
1110 ObFastDereferenceObject(IN PEX_FAST_REF FastRef
,
1113 /* FIXME: Fast Referencing is Unimplemented */
1115 /* Do a normal Dereference */
1116 ObDereferenceObject(FastRef
->Object
);
1121 ObFastReplaceObject(IN PEX_FAST_REF FastRef
,
1124 PVOID OldObject
= FastRef
->Object
;
1126 /* FIXME: Fast Referencing is Unimplemented */
1127 FastRef
->Object
= Object
;
1129 /* Do a normal Dereference */
1130 ObDereferenceObject(OldObject
);
1132 /* Return old Object*/
1136 /**********************************************************************
1138 * ObGetObjectPointerCount@4
1141 * Retrieves the pointer(reference) count of the given object.
1144 * ObjectBody = Body of the object.
1152 ObGetObjectPointerCount(PVOID Object
)
1154 POBJECT_HEADER Header
;
1159 Header
= BODY_TO_HEADER(Object
);
1161 return Header
->PointerCount
;
1165 /**********************************************************************
1167 * ObGetObjectHandleCount@4
1170 * Retrieves the handle count of the given object.
1173 * ObjectBody = Body of the object.
1179 ObGetObjectHandleCount(PVOID Object
)
1181 POBJECT_HEADER Header
;
1186 Header
= BODY_TO_HEADER(Object
);
1188 return Header
->HandleCount
;
1192 /**********************************************************************
1194 * ObDereferenceObject@4
1197 * Decrements a given object's reference count and performs
1201 * ObjectBody = Body of the object.
1209 #ifdef ObDereferenceObject
1210 #undef ObDereferenceObject
1214 ObDereferenceObject(IN PVOID Object
)
1216 ObfDereferenceObject(Object
);