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>
18 #define UNICODE_PATH_SEP L'\\'
19 #define UNICODE_NO_PATH L"..."
21 typedef struct _RETENTION_CHECK_PARAMS
23 WORK_QUEUE_ITEM WorkItem
;
24 POBJECT_HEADER ObjectHeader
;
25 } RETENTION_CHECK_PARAMS
, *PRETENTION_CHECK_PARAMS
;
27 /* FUNCTIONS ************************************************************/
31 ObpCaptureObjectName(IN OUT PUNICODE_STRING CapturedName
,
32 IN PUNICODE_STRING ObjectName
,
33 IN KPROCESSOR_MODE AccessMode
)
35 NTSTATUS Status
= STATUS_SUCCESS
;
36 UNICODE_STRING LocalName
= {}; /* <= GCC 4.0 + Optimizer */
38 /* First Probe the String */
39 DPRINT("ObpCaptureObjectName: %wZ\n", ObjectName
);
40 if (AccessMode
!= KernelMode
)
42 DPRINT("Probing Struct\n");
45 /* FIXME: Explorer or win32 broken I think */
47 ProbeForRead(ObjectName
,
48 sizeof(UNICODE_STRING
),
51 LocalName
= *ObjectName
;
55 Status
= _SEH_GetExceptionCode();
59 if (NT_SUCCESS(Status
))
61 DPRINT("Probing OK\n");
65 DPRINT("Probing buffer\n");
66 ProbeForRead(LocalName
.Buffer
,
73 Status
= _SEH_GetExceptionCode();
78 /* Fail if anything up to here died */
79 if (!NT_SUCCESS(Status
))
81 DPRINT1("Probing failed\n");
87 LocalName
= *ObjectName
;
90 /* Make sure there really is a string */
91 DPRINT("Probing OK\n");
94 /* Allocate a non-paged buffer for this string */
95 DPRINT("Capturing String\n");
96 CapturedName
->Length
= LocalName
.Length
;
97 CapturedName
->MaximumLength
= LocalName
.Length
+ sizeof(WCHAR
);
98 CapturedName
->Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
99 CapturedName
->MaximumLength
,
100 TAG('O','b','N','m'));
102 /* Copy the string and null-terminate it */
103 RtlMoveMemory(CapturedName
->Buffer
, LocalName
.Buffer
, LocalName
.Length
);
104 CapturedName
->Buffer
[LocalName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
105 DPRINT("String Captured: %p, %wZ\n", CapturedName
, CapturedName
);
113 ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes
,
114 IN KPROCESSOR_MODE AccessMode
,
115 IN POBJECT_TYPE ObjectType
,
116 IN POBJECT_CREATE_INFORMATION ObjectCreateInfo
,
117 OUT PUNICODE_STRING ObjectName
)
119 NTSTATUS Status
= STATUS_SUCCESS
;
120 PSECURITY_DESCRIPTOR SecurityDescriptor
;
121 PSECURITY_QUALITY_OF_SERVICE SecurityQos
;
122 PUNICODE_STRING LocalObjectName
= NULL
;
124 /* Zero out the Capture Data */
125 DPRINT("ObpCaptureObjectAttributes\n");
126 RtlZeroMemory(ObjectCreateInfo
, sizeof(OBJECT_CREATE_INFORMATION
));
128 /* Check if we got Oba */
129 if (ObjectAttributes
)
131 if (AccessMode
!= KernelMode
)
133 DPRINT("Probing OBA\n");
136 /* FIXME: SMSS SENDS BULLSHIT. */
138 ProbeForRead(ObjectAttributes
,
139 sizeof(ObjectAttributes
),
145 Status
= _SEH_GetExceptionCode();
150 /* Validate the Size */
151 DPRINT("Validating OBA\n");
152 if (ObjectAttributes
->Length
!= sizeof(OBJECT_ATTRIBUTES
))
154 Status
= STATUS_INVALID_PARAMETER
;
157 /* Fail if SEH or Size Validation failed */
158 if(!NT_SUCCESS(Status
))
160 DPRINT1("ObpCaptureObjectAttributes failed to probe object attributes\n");
164 /* Set some Create Info */
165 DPRINT("Creating OBCI\n");
166 ObjectCreateInfo
->RootDirectory
= ObjectAttributes
->RootDirectory
;
167 ObjectCreateInfo
->Attributes
= ObjectAttributes
->Attributes
;
168 LocalObjectName
= ObjectAttributes
->ObjectName
;
169 SecurityDescriptor
= ObjectAttributes
->SecurityDescriptor
;
170 SecurityQos
= ObjectAttributes
->SecurityQualityOfService
;
172 /* Validate the SD */
173 if (SecurityDescriptor
)
175 DPRINT("Probing SD: %x\n", SecurityDescriptor
);
176 Status
= SeCaptureSecurityDescriptor(SecurityDescriptor
,
180 &ObjectCreateInfo
->SecurityDescriptor
);
181 if(!NT_SUCCESS(Status
))
183 DPRINT1("Unable to capture the security descriptor!!!\n");
184 ObjectCreateInfo
->SecurityDescriptor
= NULL
;
188 DPRINT("Probe done\n");
189 ObjectCreateInfo
->SecurityDescriptorCharge
= 0; /* FIXME */
190 ObjectCreateInfo
->ProbeMode
= AccessMode
;
193 /* Validate the QoS */
196 if (AccessMode
!= KernelMode
)
198 DPRINT("Probing QoS\n");
201 ProbeForRead(SecurityQos
,
202 sizeof(SECURITY_QUALITY_OF_SERVICE
),
207 Status
= _SEH_GetExceptionCode();
212 if(!NT_SUCCESS(Status
))
214 DPRINT1("Unable to capture QoS!!!\n");
218 ObjectCreateInfo
->SecurityQualityOfService
= *SecurityQos
;
219 ObjectCreateInfo
->SecurityQos
= &ObjectCreateInfo
->SecurityQualityOfService
;
223 /* Clear Local Object Name */
224 DPRINT("Clearing name\n");
225 RtlZeroMemory(ObjectName
, sizeof(UNICODE_STRING
));
227 /* Now check if the Object Attributes had an Object Name */
230 DPRINT("Name Buffer: %x\n", LocalObjectName
->Buffer
);
231 Status
= ObpCaptureObjectName(ObjectName
,
237 /* He can't have specified a Root Directory */
238 if (ObjectCreateInfo
->RootDirectory
)
240 DPRINT1("Invalid name\n");
241 Status
= STATUS_OBJECT_NAME_INVALID
;
246 if (!NT_SUCCESS(Status
))
248 DPRINT1("Failed to capture, cleaning up\n");
249 ObpReleaseCapturedAttributes(ObjectCreateInfo
);
252 DPRINT("Return to caller\n");
259 ObpReleaseCapturedAttributes(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo
)
261 /* Release the SD, it's the only thing we allocated */
262 if (ObjectCreateInfo
->SecurityDescriptor
)
264 SeReleaseSecurityDescriptor(ObjectCreateInfo
->SecurityDescriptor
,
265 ObjectCreateInfo
->ProbeMode
,
267 ObjectCreateInfo
->SecurityDescriptor
= NULL
;
272 /**********************************************************************
284 * Pointer to a unicode string that will contain the
285 * remaining path if the function returns successfully.
286 * The caller must free the buffer after use by calling
287 * RtlFreeUnicodeString ().
290 * Optional pointer to an object type. This is used to
291 * descide if a symbolic link object will be parsed or not.
296 ObFindObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo
,
297 PUNICODE_STRING ObjectName
,
298 PVOID
* ReturnedObject
,
299 PUNICODE_STRING RemainingPath
,
300 POBJECT_TYPE ObjectType
)
305 POBJECT_HEADER CurrentHeader
;
308 UNICODE_STRING PathString
;
313 DPRINT("ObFindObject(ObjectCreateInfo %x, ReturnedObject %x, "
314 "RemainingPath %x)\n",ObjectCreateInfo
,ReturnedObject
,RemainingPath
);
316 RtlInitUnicodeString (RemainingPath
, NULL
);
318 if (ObjectCreateInfo
->RootDirectory
== NULL
)
320 ObReferenceObjectByPointer(NameSpaceRoot
,
324 CurrentObject
= NameSpaceRoot
;
328 Status
= ObReferenceObjectByHandle(ObjectCreateInfo
->RootDirectory
,
334 if (!NT_SUCCESS(Status
))
340 if (ObjectName
->Length
== 0 ||
341 ObjectName
->Buffer
[0] == UNICODE_NULL
)
343 *ReturnedObject
= CurrentObject
;
344 return STATUS_SUCCESS
;
347 if (ObjectCreateInfo
->RootDirectory
== NULL
&&
348 ObjectName
->Buffer
[0] != L
'\\')
350 ObDereferenceObject (CurrentObject
);
352 return STATUS_UNSUCCESSFUL
;
355 /* Create a zero-terminated copy of the object name */
356 PathString
.Length
= ObjectName
->Length
;
357 PathString
.MaximumLength
= ObjectName
->Length
+ sizeof(WCHAR
);
358 PathString
.Buffer
= ExAllocatePool (NonPagedPool
,
359 PathString
.MaximumLength
);
360 if (PathString
.Buffer
== NULL
)
362 ObDereferenceObject (CurrentObject
);
363 return STATUS_INSUFFICIENT_RESOURCES
;
366 RtlCopyMemory (PathString
.Buffer
,
369 PathString
.Buffer
[PathString
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
371 current
= PathString
.Buffer
;
373 RootObject
= CurrentObject
;
374 Attributes
= ObjectCreateInfo
->Attributes
;
375 if (ObjectType
== ObSymbolicLinkType
)
376 Attributes
|= OBJ_OPENLINK
;
380 DPRINT("current %S\n",current
);
381 CurrentHeader
= BODY_TO_HEADER(CurrentObject
);
383 DPRINT("Current ObjectType %wZ\n",
384 &CurrentHeader
->Type
->Name
);
386 if (CurrentHeader
->Type
->TypeInfo
.ParseProcedure
== NULL
)
388 DPRINT("Current object can't parse\n");
391 Status
= CurrentHeader
->Type
->TypeInfo
.ParseProcedure(CurrentObject
,
396 if (Status
== STATUS_REPARSE
)
398 /* reparse the object path */
399 NextObject
= NameSpaceRoot
;
400 current
= PathString
.Buffer
;
402 ObReferenceObjectByPointer(NextObject
,
408 if (NextObject
== NULL
)
412 ObDereferenceObject(CurrentObject
);
413 CurrentObject
= NextObject
;
418 RtlpCreateUnicodeString (RemainingPath
, current
, NonPagedPool
);
421 RtlFreeUnicodeString (&PathString
);
422 *ReturnedObject
= CurrentObject
;
424 return STATUS_SUCCESS
;
428 /**********************************************************************
430 * ObQueryNameString@16
442 ObQueryNameString(IN PVOID Object
,
443 OUT POBJECT_NAME_INFORMATION ObjectNameInfo
,
445 OUT PULONG ReturnLength
)
447 POBJECT_HEADER_NAME_INFO LocalInfo
;
448 POBJECT_HEADER ObjectHeader
;
449 PDIRECTORY_OBJECT ParentDirectory
;
454 DPRINT("ObQueryNameString: %x, %x\n", Object
, ObjectNameInfo
);
456 /* Get the Kernel Meta-Structures */
457 ObjectHeader
= BODY_TO_HEADER(Object
);
458 LocalInfo
= HEADER_TO_OBJECT_NAME(ObjectHeader
);
460 /* Check if a Query Name Procedure is available */
461 if (ObjectHeader
->Type
->TypeInfo
.QueryNameProcedure
)
463 /* Call the procedure */
464 DPRINT("Calling Object's Procedure\n");
465 Status
= ObjectHeader
->Type
->TypeInfo
.QueryNameProcedure(Object
,
470 /* Return the status */
474 /* Check if the object doesn't even have a name */
475 if (!LocalInfo
|| !LocalInfo
->Name
.Buffer
)
477 /* We're returning the name structure */
478 DPRINT("Nameless Object\n");
479 *ReturnLength
= sizeof(OBJECT_NAME_INFORMATION
);
481 /* Check if we were given enough space */
482 if (*ReturnLength
> Length
)
484 DPRINT1("Not enough buffer space\n");
485 return STATUS_INFO_LENGTH_MISMATCH
;
488 /* Return an empty buffer */
489 ObjectNameInfo
->Name
.Length
= 0;
490 ObjectNameInfo
->Name
.MaximumLength
= 0;
491 ObjectNameInfo
->Name
.Buffer
= NULL
;
493 return STATUS_SUCCESS
;
497 * Find the size needed for the name. We won't do
498 * this during the Name Creation loop because we want
499 * to let the caller know that the buffer isn't big
500 * enough right at the beginning, not work our way through
501 * and find out at the end
503 if (Object
== NameSpaceRoot
)
505 /* Size of the '\' string */
506 DPRINT("Object is Root\n");
507 NameSize
= sizeof(UNICODE_PATH_SEP
);
511 /* Get the Object Directory and add name of Object */
512 ParentDirectory
= LocalInfo
->Directory
;
513 NameSize
= sizeof(UNICODE_PATH_SEP
) + LocalInfo
->Name
.Length
;
515 /* Loop inside the directory to get the top-most one (meaning root) */
516 while ((ParentDirectory
!= NameSpaceRoot
) && (ParentDirectory
))
518 /* Get the Name Information */
519 LocalInfo
= HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(ParentDirectory
));
521 /* Add the size of the Directory Name */
522 if (LocalInfo
&& LocalInfo
->Directory
)
524 /* Size of the '\' string + Directory Name */
525 NameSize
+= sizeof(UNICODE_PATH_SEP
) + LocalInfo
->Name
.Length
;
527 /* Move to next parent Directory */
528 ParentDirectory
= LocalInfo
->Directory
;
532 /* Directory with no name. We append "...\" */
533 DPRINT("Nameless Directory\n");
534 NameSize
+= sizeof(UNICODE_NO_PATH
) + sizeof(UNICODE_PATH_SEP
);
540 /* Finally, add the name of the structure and the null char */
541 *ReturnLength
= NameSize
+ sizeof(OBJECT_NAME_INFORMATION
) + sizeof(UNICODE_NULL
);
542 DPRINT("Final Length: %x\n", *ReturnLength
);
544 /* Check if we were given enough space */
545 if (*ReturnLength
> Length
)
547 DPRINT1("Not enough buffer space\n");
548 return STATUS_INFO_LENGTH_MISMATCH
;
552 * Now we will actually create the name. We work backwards because
553 * it's easier to start off from the Name we have and walk up the
554 * parent directories. We use the same logic as Name Length calculation.
556 LocalInfo
= HEADER_TO_OBJECT_NAME(ObjectHeader
);
557 ObjectName
= (PWCH
)((ULONG_PTR
)ObjectNameInfo
+ *ReturnLength
);
558 *--ObjectName
= UNICODE_NULL
;
560 if (Object
== NameSpaceRoot
)
562 /* This is already the Root Directory, return "\\" */
563 DPRINT("Returning Root Dir\n");
564 *--ObjectName
= UNICODE_PATH_SEP
;
565 ObjectNameInfo
->Name
.Length
= (USHORT
)NameSize
;
566 ObjectNameInfo
->Name
.MaximumLength
= (USHORT
)(NameSize
+ sizeof(UNICODE_NULL
));
567 ObjectNameInfo
->Name
.Buffer
= ObjectName
;
569 return STATUS_SUCCESS
;
573 /* Start by adding the Object's Name */
574 ObjectName
= (PWCH
)((ULONG_PTR
)ObjectName
- LocalInfo
->Name
.Length
);
575 RtlMoveMemory(ObjectName
, LocalInfo
->Name
.Buffer
, LocalInfo
->Name
.Length
);
577 /* Now parse the Parent directories until we reach the top */
578 ParentDirectory
= LocalInfo
->Directory
;
579 while ((ParentDirectory
!= NameSpaceRoot
) && (ParentDirectory
))
581 /* Get the name information */
582 LocalInfo
= HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(ParentDirectory
));
585 *(--ObjectName
) = UNICODE_PATH_SEP
;
587 /* Add the Parent Directory's Name */
588 if (LocalInfo
&& LocalInfo
->Name
.Buffer
)
591 ObjectName
= (PWCH
)((ULONG_PTR
)ObjectName
- LocalInfo
->Name
.Length
);
592 RtlMoveMemory(ObjectName
, LocalInfo
->Name
.Buffer
, LocalInfo
->Name
.Length
);
594 /* Move to next parent */
595 ParentDirectory
= LocalInfo
->Directory
;
599 /* Directory without a name, we add "..." */
600 DPRINT("Nameless Directory\n");
601 ObjectName
-= sizeof(UNICODE_NO_PATH
);
602 ObjectName
= UNICODE_NO_PATH
;
607 /* Add Root Directory Name */
608 *(--ObjectName
) = UNICODE_PATH_SEP
;
609 DPRINT("Current Buffer: %S\n", ObjectName
);
610 ObjectNameInfo
->Name
.Length
= (USHORT
)NameSize
;
611 ObjectNameInfo
->Name
.MaximumLength
= (USHORT
)(NameSize
+ sizeof(UNICODE_NULL
));
612 ObjectNameInfo
->Name
.Buffer
= ObjectName
;
613 DPRINT("Complete: %wZ\n", ObjectNameInfo
);
616 return STATUS_SUCCESS
;
621 ObpAllocateObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo
,
622 PUNICODE_STRING ObjectName
,
623 POBJECT_TYPE ObjectType
,
625 POBJECT_HEADER
*ObjectHeader
)
627 POBJECT_HEADER Header
;
628 BOOLEAN HasHandleInfo
= FALSE
;
629 BOOLEAN HasNameInfo
= FALSE
;
630 BOOLEAN HasCreatorInfo
= FALSE
;
631 POBJECT_HEADER_HANDLE_INFO HandleInfo
;
632 POBJECT_HEADER_NAME_INFO NameInfo
;
633 POBJECT_HEADER_CREATOR_INFO CreatorInfo
;
635 ULONG FinalSize
= ObjectSize
;
638 /* If we don't have an Object Type yet, force NonPaged */
639 DPRINT("ObpAllocateObject\n");
642 PoolType
= NonPagedPool
;
643 Tag
= TAG('O', 'b', 'j', 'T');
647 PoolType
= ObjectType
->TypeInfo
.PoolType
;
648 Tag
= ObjectType
->Key
;
651 DPRINT("Checking ObjectName: %x\n", ObjectName
);
652 /* Check if the Object has a name */
653 if (ObjectName
->Buffer
)
655 FinalSize
+= sizeof(OBJECT_HEADER_NAME_INFO
);
661 /* Check if the Object maintains handle counts */
662 DPRINT("Checking ObjectType->TypeInfo: %x\n", &ObjectType
->TypeInfo
);
663 if (ObjectType
->TypeInfo
.MaintainHandleCount
)
665 FinalSize
+= sizeof(OBJECT_HEADER_HANDLE_INFO
);
666 HasHandleInfo
= TRUE
;
669 /* Check if the Object maintains type lists */
670 if (ObjectType
->TypeInfo
.MaintainTypeList
)
672 FinalSize
+= sizeof(OBJECT_HEADER_CREATOR_INFO
);
673 HasCreatorInfo
= TRUE
;
677 /* Allocate memory for the Object and Header */
678 DPRINT("Allocating: %x %x\n", FinalSize
, Tag
);
679 Header
= ExAllocatePoolWithTag(PoolType
, FinalSize
, Tag
);
681 DPRINT1("Not enough memory!\n");
682 return STATUS_INSUFFICIENT_RESOURCES
;
685 /* Initialize Handle Info */
688 HandleInfo
= (POBJECT_HEADER_HANDLE_INFO
)Header
;
689 DPRINT("Info: %x\n", HandleInfo
);
690 HandleInfo
->SingleEntry
.HandleCount
= 0;
691 Header
= (POBJECT_HEADER
)(HandleInfo
+ 1);
694 /* Initialize the Object Name Info */
697 NameInfo
= (POBJECT_HEADER_NAME_INFO
)Header
;
698 DPRINT("Info: %x %wZ\n", NameInfo
, ObjectName
);
699 NameInfo
->Name
= *ObjectName
;
700 NameInfo
->Directory
= NULL
;
701 Header
= (POBJECT_HEADER
)(NameInfo
+ 1);
704 /* Initialize Creator Info */
707 CreatorInfo
= (POBJECT_HEADER_CREATOR_INFO
)Header
;
708 DPRINT("Info: %x\n", CreatorInfo
);
709 /* FIXME: Needs Alex's Init patch
710 * CreatorInfo->CreatorUniqueProcess = PsGetCurrentProcessId();
712 InitializeListHead(&CreatorInfo
->TypeList
);
713 Header
= (POBJECT_HEADER
)(CreatorInfo
+ 1);
716 /* Initialize the object header */
717 RtlZeroMemory(Header
, ObjectSize
);
718 DPRINT("Initalized header %p\n", Header
);
719 Header
->HandleCount
= 0;
720 Header
->PointerCount
= 1;
721 Header
->Type
= ObjectType
;
722 Header
->Flags
= OB_FLAG_CREATE_INFO
;
724 /* Set the Offsets for the Info */
727 Header
->HandleInfoOffset
= HasNameInfo
* sizeof(OBJECT_HEADER_NAME_INFO
) +
728 sizeof(OBJECT_HEADER_HANDLE_INFO
) +
729 HasCreatorInfo
* sizeof(OBJECT_HEADER_CREATOR_INFO
);
730 Header
->Flags
|= OB_FLAG_SINGLE_PROCESS
;
734 Header
->NameInfoOffset
= sizeof(OBJECT_HEADER_NAME_INFO
) +
735 HasCreatorInfo
* sizeof(OBJECT_HEADER_CREATOR_INFO
);
737 if (HasCreatorInfo
) Header
->Flags
|= OB_FLAG_CREATOR_INFO
;
739 if (ObjectCreateInfo
&& ObjectCreateInfo
->Attributes
& OBJ_PERMANENT
)
741 Header
->Flags
|= OB_FLAG_PERMANENT
;
743 if (ObjectCreateInfo
&& ObjectCreateInfo
->Attributes
& OBJ_EXCLUSIVE
)
745 Header
->Flags
|= OB_FLAG_EXCLUSIVE
;
748 /* Link stuff to Object Header */
749 Header
->ObjectCreateInfo
= ObjectCreateInfo
;
752 *ObjectHeader
= Header
;
753 return STATUS_SUCCESS
;
756 /**********************************************************************
771 ObCreateObject(IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL
,
772 IN POBJECT_TYPE Type
,
773 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
774 IN KPROCESSOR_MODE AccessMode
,
775 IN OUT PVOID ParseContext OPTIONAL
,
777 IN ULONG PagedPoolCharge OPTIONAL
,
778 IN ULONG NonPagedPoolCharge OPTIONAL
,
782 POBJECT_CREATE_INFORMATION ObjectCreateInfo
;
783 UNICODE_STRING ObjectName
;
784 POBJECT_HEADER Header
;
786 DPRINT("ObCreateObject(Type %p ObjectAttributes %p, Object %p)\n",
787 Type
, ObjectAttributes
, Object
);
789 /* Allocate a Buffer for the Object Create Info */
790 DPRINT("Allocating Create Buffer\n");
791 ObjectCreateInfo
= ExAllocatePoolWithTag(NonPagedPool
,
792 sizeof(*ObjectCreateInfo
),
793 TAG('O','b','C', 'I'));
795 /* Capture all the info */
796 DPRINT("Capturing Create Info\n");
797 Status
= ObpCaptureObjectAttributes(ObjectAttributes
,
803 if (NT_SUCCESS(Status
))
805 /* Allocate the Object */
806 DPRINT("Allocating: %wZ\n", &ObjectName
);
807 Status
= ObpAllocateObject(ObjectCreateInfo
,
810 OBJECT_ALLOC_SIZE(ObjectSize
),
813 if (NT_SUCCESS(Status
))
815 /* Return the Object */
816 DPRINT("Returning Object\n");
817 *Object
= &Header
->Body
;
819 /* Return to caller, leave the Capture Info Alive for ObInsert */
823 /* Release the Capture Info, we don't need it */
824 DPRINT1("Allocation failed\n");
825 ObpReleaseCapturedAttributes(ObjectCreateInfo
);
826 if (ObjectName
.Buffer
) ExFreePool(ObjectName
.Buffer
);
829 /* We failed, so release the Buffer */
830 DPRINT1("Capture failed\n");
831 ExFreePool(ObjectCreateInfo
);
836 * FUNCTION: Increments the pointer reference count for a given object
838 * ObjectBody = Object's body
839 * DesiredAccess = Desired access to the object
840 * ObjectType = Points to the object type structure
841 * AccessMode = Type of access check to perform
847 ObReferenceObjectByPointer(IN PVOID Object
,
848 IN ACCESS_MASK DesiredAccess
,
849 IN POBJECT_TYPE ObjectType
,
850 IN KPROCESSOR_MODE AccessMode
)
852 POBJECT_HEADER Header
;
854 /* NOTE: should be possible to reference an object above APC_LEVEL! */
856 DPRINT("ObReferenceObjectByPointer(Object %x, ObjectType %x)\n",
859 Header
= BODY_TO_HEADER(Object
);
861 if (ObjectType
!= NULL
&& Header
->Type
!= ObjectType
)
863 DPRINT("Failed %p (type was %x %wZ) should be %x %wZ\n",
866 &HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(Header
->Type
))->Name
,
868 &HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(ObjectType
))->Name
);
869 return(STATUS_UNSUCCESSFUL
);
871 if (Header
->Type
== PsProcessType
)
873 DPRINT("Ref p 0x%x PointerCount %d type %x ",
874 Object
, Header
->PointerCount
, PsProcessType
);
875 DPRINT("eip %x\n", ((PULONG
)&Object
)[-1]);
877 if (Header
->Type
== PsThreadType
)
879 DPRINT("Deref t 0x%x with PointerCount %d type %x ",
880 Object
, Header
->PointerCount
, PsThreadType
);
881 DPRINT("eip %x\n", ((PULONG
)&Object
)[-1]);
884 if (Header
->PointerCount
== 0 && !(Header
->Flags
& OB_FLAG_PERMANENT
))
886 if (Header
->Type
== PsProcessType
)
888 return STATUS_PROCESS_IS_TERMINATING
;
890 if (Header
->Type
== PsThreadType
)
892 return STATUS_THREAD_IS_TERMINATING
;
894 return(STATUS_UNSUCCESSFUL
);
897 if (1 == InterlockedIncrement(&Header
->PointerCount
) && !(Header
->Flags
& OB_FLAG_PERMANENT
))
902 return(STATUS_SUCCESS
);
910 ObOpenObjectByPointer(IN PVOID Object
,
911 IN ULONG HandleAttributes
,
912 IN PACCESS_STATE PassedAccessState
,
913 IN ACCESS_MASK DesiredAccess
,
914 IN POBJECT_TYPE ObjectType
,
915 IN KPROCESSOR_MODE AccessMode
,
922 DPRINT("ObOpenObjectByPointer()\n");
924 Status
= ObReferenceObjectByPointer(Object
,
928 if (!NT_SUCCESS(Status
))
933 Status
= ObpCreateHandle(PsGetCurrentProcess(),
936 (BOOLEAN
)(HandleAttributes
& OBJ_INHERIT
),
939 ObDereferenceObject(Object
);
941 return STATUS_SUCCESS
;
946 ObpDeleteObject(POBJECT_HEADER Header
)
948 PVOID HeaderLocation
= Header
;
949 POBJECT_HEADER_HANDLE_INFO HandleInfo
;
950 POBJECT_HEADER_NAME_INFO NameInfo
;
951 POBJECT_HEADER_CREATOR_INFO CreatorInfo
;
953 DPRINT("ObpDeleteObject(Header %p)\n", Header
);
954 if (KeGetCurrentIrql() != PASSIVE_LEVEL
)
956 DPRINT("ObpDeleteObject called at an unsupported IRQL. Use ObpDeleteObjectDpcLevel instead.\n");
960 if (Header
->Type
!= NULL
&&
961 Header
->Type
->TypeInfo
.DeleteProcedure
!= NULL
)
963 Header
->Type
->TypeInfo
.DeleteProcedure(&Header
->Body
);
966 if (Header
->SecurityDescriptor
!= NULL
)
968 ObpRemoveSecurityDescriptor(Header
->SecurityDescriptor
);
971 if (HEADER_TO_OBJECT_NAME(Header
))
973 if(HEADER_TO_OBJECT_NAME(Header
)->Name
.Buffer
)
975 ExFreePool(HEADER_TO_OBJECT_NAME(Header
)->Name
.Buffer
);
978 if (Header
->ObjectCreateInfo
)
980 ObpReleaseCapturedAttributes(Header
->ObjectCreateInfo
);
981 ExFreePool(Header
->ObjectCreateInfo
);
984 /* To find the header, walk backwards from how we allocated */
985 if ((CreatorInfo
= HEADER_TO_CREATOR_INFO(Header
)))
987 HeaderLocation
= CreatorInfo
;
989 if ((NameInfo
= HEADER_TO_OBJECT_NAME(Header
)))
991 HeaderLocation
= NameInfo
;
993 if ((HandleInfo
= HEADER_TO_HANDLE_INFO(Header
)))
995 HeaderLocation
= HandleInfo
;
998 DPRINT("ObPerformRetentionChecks() = Freeing object\n");
999 ExFreePool(HeaderLocation
);
1001 return(STATUS_SUCCESS
);
1006 ObpDeleteObjectWorkRoutine (IN PVOID Parameter
)
1008 PRETENTION_CHECK_PARAMS Params
= (PRETENTION_CHECK_PARAMS
)Parameter
;
1009 /* ULONG Tag; */ /* See below */
1012 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
); /* We need PAGED_CODE somewhere... */
1014 /* Turn this on when we have ExFreePoolWithTag
1015 Tag = Params->ObjectHeader->Type->Tag; */
1016 ObpDeleteObject(Params
->ObjectHeader
);
1018 /* ExFreePoolWithTag(Params, Tag); */
1023 ObpDeleteObjectDpcLevel(IN POBJECT_HEADER ObjectHeader
,
1024 IN LONG OldPointerCount
)
1027 if (ObjectHeader
->PointerCount
< 0)
1029 CPRINT("Object %p/%p has invalid reference count (%d)\n",
1030 ObjectHeader
, HEADER_TO_BODY(ObjectHeader
),
1031 ObjectHeader
->PointerCount
);
1035 if (ObjectHeader
->HandleCount
< 0)
1037 CPRINT("Object %p/%p has invalid handle count (%d)\n",
1038 ObjectHeader
, HEADER_TO_BODY(ObjectHeader
),
1039 ObjectHeader
->HandleCount
);
1045 switch (KeGetCurrentIrql ())
1048 return ObpDeleteObject (ObjectHeader
);
1051 case DISPATCH_LEVEL
:
1053 PRETENTION_CHECK_PARAMS Params
;
1056 We use must succeed pool here because if the allocation fails
1057 then we leak memory.
1059 Params
= (PRETENTION_CHECK_PARAMS
)
1060 ExAllocatePoolWithTag(NonPagedPoolMustSucceed
,
1061 sizeof(RETENTION_CHECK_PARAMS
),
1062 ObjectHeader
->Type
->Key
);
1063 Params
->ObjectHeader
= ObjectHeader
;
1064 ExInitializeWorkItem(&Params
->WorkItem
,
1065 ObpDeleteObjectWorkRoutine
,
1067 ExQueueWorkItem(&Params
->WorkItem
,
1070 return STATUS_PENDING
;
1073 DPRINT("ObpDeleteObjectDpcLevel called at unsupported "
1074 "IRQL %u!\n", KeGetCurrentIrql());
1076 return STATUS_UNSUCCESSFUL
;
1079 return STATUS_SUCCESS
;
1083 /**********************************************************************
1085 * ObfReferenceObject@4
1088 * Increments a given object's reference count and performs
1092 * ObjectBody = Body of the object.
1100 ObfReferenceObject(IN PVOID Object
)
1102 POBJECT_HEADER Header
;
1106 Header
= BODY_TO_HEADER(Object
);
1108 /* No one should be referencing an object once we are deleting it. */
1109 if (InterlockedIncrement(&Header
->PointerCount
) == 1 && !(Header
->Flags
& OB_FLAG_PERMANENT
))
1116 /**********************************************************************
1118 * ObfDereferenceObject@4
1121 * Decrements a given object's reference count and performs
1125 * ObjectBody = Body of the object.
1133 ObfDereferenceObject(IN PVOID Object
)
1135 POBJECT_HEADER Header
;
1136 LONG NewPointerCount
;
1141 /* Extract the object header. */
1142 Header
= BODY_TO_HEADER(Object
);
1143 Permanent
= Header
->Flags
& OB_FLAG_PERMANENT
;
1146 Drop our reference and get the new count so we can tell if this was the
1149 NewPointerCount
= InterlockedDecrement(&Header
->PointerCount
);
1150 DPRINT("ObfDereferenceObject(0x%x)==%d\n", Object
, NewPointerCount
);
1151 ASSERT(NewPointerCount
>= 0);
1153 /* Check whether the object can now be deleted. */
1154 if (NewPointerCount
== 0 &&
1157 ObpDeleteObjectDpcLevel(Header
, NewPointerCount
);
1163 ObInitializeFastReference(IN PEX_FAST_REF FastRef
,
1166 /* FIXME: Fast Referencing is Unimplemented */
1167 FastRef
->Object
= Object
;
1173 ObFastReferenceObject(IN PEX_FAST_REF FastRef
)
1175 /* FIXME: Fast Referencing is Unimplemented */
1177 /* Do a normal Reference */
1178 ObReferenceObject(FastRef
->Object
);
1180 /* Return the Object */
1181 return FastRef
->Object
;
1186 ObFastDereferenceObject(IN PEX_FAST_REF FastRef
,
1189 /* FIXME: Fast Referencing is Unimplemented */
1191 /* Do a normal Dereference */
1192 ObDereferenceObject(FastRef
->Object
);
1197 ObFastReplaceObject(IN PEX_FAST_REF FastRef
,
1200 PVOID OldObject
= FastRef
->Object
;
1202 /* FIXME: Fast Referencing is Unimplemented */
1203 FastRef
->Object
= Object
;
1205 /* Do a normal Dereference */
1206 ObDereferenceObject(OldObject
);
1208 /* Return old Object*/
1212 /**********************************************************************
1214 * ObGetObjectPointerCount@4
1217 * Retrieves the pointer(reference) count of the given object.
1220 * ObjectBody = Body of the object.
1228 ObGetObjectPointerCount(PVOID Object
)
1230 POBJECT_HEADER Header
;
1235 Header
= BODY_TO_HEADER(Object
);
1237 return Header
->PointerCount
;
1241 /**********************************************************************
1243 * ObGetObjectHandleCount@4
1246 * Retrieves the handle count of the given object.
1249 * ObjectBody = Body of the object.
1255 ObGetObjectHandleCount(PVOID Object
)
1257 POBJECT_HEADER Header
;
1262 Header
= BODY_TO_HEADER(Object
);
1264 return Header
->HandleCount
;
1268 /**********************************************************************
1270 * ObDereferenceObject@4
1273 * Decrements a given object's reference count and performs
1277 * ObjectBody = Body of the object.
1285 #ifdef ObDereferenceObject
1286 #undef ObDereferenceObject
1290 ObDereferenceObject(IN PVOID Object
)
1292 ObfDereferenceObject(Object
);