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 /* TEMPORARY HACK. DO NOT REMOVE -- Alex */
28 ExpDesktopCreate(PVOID ObjectBody
,
31 struct _OBJECT_ATTRIBUTES
* ObjectAttributes
);
32 /* FUNCTIONS ************************************************************/
35 ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
36 IN KPROCESSOR_MODE AccessMode
,
37 IN POOL_TYPE PoolType
,
38 IN BOOLEAN CaptureIfKernel
,
39 OUT PCAPTURED_OBJECT_ATTRIBUTES CapturedObjectAttributes OPTIONAL
,
40 OUT PUNICODE_STRING ObjectName OPTIONAL
)
42 OBJECT_ATTRIBUTES AttributesCopy
;
43 NTSTATUS Status
= STATUS_SUCCESS
;
45 /* at least one output parameter must be != NULL! */
46 ASSERT(CapturedObjectAttributes
!= NULL
|| ObjectName
!= NULL
);
48 if(ObjectAttributes
== NULL
)
50 /* we're going to return STATUS_SUCCESS! */
51 goto failbasiccleanup
;
54 if(AccessMode
!= KernelMode
)
56 RtlZeroMemory(&AttributesCopy
, sizeof(AttributesCopy
));
60 ProbeForRead(ObjectAttributes
,
61 sizeof(ObjectAttributes
),
63 /* make a copy on the stack */
64 AttributesCopy
= *ObjectAttributes
;
68 Status
= _SEH_GetExceptionCode();
72 if(!NT_SUCCESS(Status
))
74 DPRINT1("ObpCaptureObjectAttributes failed to probe object attributes\n");
75 goto failbasiccleanup
;
78 else if(!CaptureIfKernel
)
80 if(ObjectAttributes
->Length
== sizeof(OBJECT_ATTRIBUTES
))
82 if(ObjectName
!= NULL
)
84 /* we don't have to capture any memory, the caller considers the passed data
86 if(ObjectAttributes
->ObjectName
!= NULL
)
88 *ObjectName
= *ObjectAttributes
->ObjectName
;
92 ObjectName
->Length
= ObjectName
->MaximumLength
= 0;
93 ObjectName
->Buffer
= NULL
;
96 if(CapturedObjectAttributes
!= NULL
)
98 CapturedObjectAttributes
->RootDirectory
= ObjectAttributes
->RootDirectory
;
99 CapturedObjectAttributes
->Attributes
= ObjectAttributes
->Attributes
;
100 CapturedObjectAttributes
->SecurityDescriptor
= ObjectAttributes
->SecurityDescriptor
;
101 CapturedObjectAttributes
->SecurityQualityOfService
= ObjectAttributes
->SecurityQualityOfService
;
104 return STATUS_SUCCESS
;
108 Status
= STATUS_INVALID_PARAMETER
;
109 goto failbasiccleanup
;
114 AttributesCopy
= *ObjectAttributes
;
117 /* if Length isn't as expected, bail with an invalid parameter status code so
118 the caller knows he passed garbage... */
119 if(AttributesCopy
.Length
!= sizeof(OBJECT_ATTRIBUTES
))
121 Status
= STATUS_INVALID_PARAMETER
;
122 goto failbasiccleanup
;
125 if(CapturedObjectAttributes
!= NULL
)
127 CapturedObjectAttributes
->RootDirectory
= AttributesCopy
.RootDirectory
;
128 CapturedObjectAttributes
->Attributes
= AttributesCopy
.Attributes
;
130 if(AttributesCopy
.SecurityDescriptor
!= NULL
)
132 Status
= SeCaptureSecurityDescriptor(AttributesCopy
.SecurityDescriptor
,
136 &CapturedObjectAttributes
->SecurityDescriptor
);
137 if(!NT_SUCCESS(Status
))
139 DPRINT1("Unable to capture the security descriptor!!!\n");
140 goto failbasiccleanup
;
145 CapturedObjectAttributes
->SecurityDescriptor
= NULL
;
148 if(AttributesCopy
.SecurityQualityOfService
!= NULL
)
150 SECURITY_QUALITY_OF_SERVICE SafeQoS
;
152 RtlZeroMemory(&SafeQoS
, sizeof(SafeQoS
));
156 ProbeForRead(AttributesCopy
.SecurityQualityOfService
,
157 sizeof(SECURITY_QUALITY_OF_SERVICE
),
159 SafeQoS
= *(PSECURITY_QUALITY_OF_SERVICE
)AttributesCopy
.SecurityQualityOfService
;
163 Status
= _SEH_GetExceptionCode();
167 if(!NT_SUCCESS(Status
))
169 DPRINT1("Unable to capture QoS!!!\n");
170 goto failcleanupsdescriptor
;
173 if(SafeQoS
.Length
!= sizeof(SECURITY_QUALITY_OF_SERVICE
))
175 DPRINT1("Unable to capture QoS, wrong size!!!\n");
176 Status
= STATUS_INVALID_PARAMETER
;
177 goto failcleanupsdescriptor
;
180 CapturedObjectAttributes
->SecurityQualityOfService
= ExAllocatePool(PoolType
,
181 sizeof(SECURITY_QUALITY_OF_SERVICE
));
182 if(CapturedObjectAttributes
->SecurityQualityOfService
!= NULL
)
184 *CapturedObjectAttributes
->SecurityQualityOfService
= SafeQoS
;
188 Status
= STATUS_INSUFFICIENT_RESOURCES
;
189 goto failcleanupsdescriptor
;
194 CapturedObjectAttributes
->SecurityQualityOfService
= NULL
;
198 if(ObjectName
!= NULL
)
200 if(AttributesCopy
.ObjectName
!= NULL
)
202 UNICODE_STRING OriginalCopy
;
204 if(AccessMode
!= KernelMode
)
206 RtlZeroMemory(&OriginalCopy
, sizeof(OriginalCopy
));
210 /* probe the ObjectName structure and make a local stack copy of it */
211 ProbeForRead(AttributesCopy
.ObjectName
,
212 sizeof(UNICODE_STRING
),
214 OriginalCopy
= *AttributesCopy
.ObjectName
;
215 if(OriginalCopy
.Length
> 0)
217 ProbeForRead(OriginalCopy
.Buffer
,
224 Status
= _SEH_GetExceptionCode();
228 if(NT_SUCCESS(Status
))
230 if(OriginalCopy
.Length
> 0)
232 ObjectName
->MaximumLength
= OriginalCopy
.Length
+ sizeof(WCHAR
);
233 ObjectName
->Buffer
= ExAllocatePool(PoolType
,
234 ObjectName
->MaximumLength
);
235 if(ObjectName
->Buffer
!= NULL
)
239 /* no need to probe OriginalCopy.Buffer again, we already did that
240 when capturing the UNICODE_STRING structure itself */
241 RtlCopyMemory(ObjectName
->Buffer
, OriginalCopy
.Buffer
, OriginalCopy
.Length
);
242 ObjectName
->Buffer
[OriginalCopy
.Length
/ sizeof(WCHAR
)] = L
'\0';
246 Status
= _SEH_GetExceptionCode();
250 if(!NT_SUCCESS(Status
))
252 DPRINT1("ObpCaptureObjectAttributes failed to copy the unicode string!\n");
257 Status
= STATUS_INSUFFICIENT_RESOURCES
;
260 else if(AttributesCopy
.RootDirectory
!= NULL
/* && OriginalCopy.Length == 0 */)
262 /* if the caller specified a root directory, there must be an object name! */
263 Status
= STATUS_OBJECT_NAME_INVALID
;
268 DPRINT1("ObpCaptureObjectAttributes failed to probe the object name UNICODE_STRING structure!\n");
271 else /* AccessMode == KernelMode */
273 OriginalCopy
= *AttributesCopy
.ObjectName
;
275 if(OriginalCopy
.Length
> 0)
277 ObjectName
->MaximumLength
= OriginalCopy
.Length
+ sizeof(WCHAR
);
278 ObjectName
->Buffer
= ExAllocatePool(PoolType
,
279 ObjectName
->MaximumLength
);
280 if(ObjectName
->Buffer
!= NULL
)
282 RtlCopyMemory(ObjectName
->Buffer
, OriginalCopy
.Buffer
, OriginalCopy
.Length
);
283 ObjectName
->Buffer
[OriginalCopy
.Length
/ sizeof(WCHAR
)] = L
'\0';
287 Status
= STATUS_INSUFFICIENT_RESOURCES
;
290 else if(AttributesCopy
.RootDirectory
!= NULL
/* && OriginalCopy.Length == 0 */)
292 /* if the caller specified a root directory, there must be an object name! */
293 Status
= STATUS_OBJECT_NAME_INVALID
;
299 ObjectName
->Length
= ObjectName
->MaximumLength
= 0;
300 ObjectName
->Buffer
= NULL
;
304 if(!NT_SUCCESS(Status
))
306 if(ObjectName
->Buffer
)
308 ExFreePool(ObjectName
->Buffer
);
311 failcleanupsdescriptor
:
312 if(CapturedObjectAttributes
!= NULL
)
314 /* cleanup allocated resources */
315 SeReleaseSecurityDescriptor(CapturedObjectAttributes
->SecurityDescriptor
,
321 if(ObjectName
!= NULL
)
323 ObjectName
->Length
= ObjectName
->MaximumLength
= 0;
324 ObjectName
->Buffer
= NULL
;
326 if(CapturedObjectAttributes
!= NULL
)
328 RtlZeroMemory(CapturedObjectAttributes
, sizeof(CAPTURED_OBJECT_ATTRIBUTES
));
337 ObpReleaseObjectAttributes(IN PCAPTURED_OBJECT_ATTRIBUTES CapturedObjectAttributes OPTIONAL
,
338 IN PUNICODE_STRING ObjectName OPTIONAL
,
339 IN KPROCESSOR_MODE AccessMode
,
340 IN BOOLEAN CaptureIfKernel
)
342 /* WARNING - You need to pass the same parameters to this function as you passed
343 to ObpCaptureObjectAttributes() to avoid memory leaks */
344 if(AccessMode
!= KernelMode
|| CaptureIfKernel
)
346 if(CapturedObjectAttributes
!= NULL
)
348 if(CapturedObjectAttributes
->SecurityDescriptor
!= NULL
)
350 ExFreePool(CapturedObjectAttributes
->SecurityDescriptor
);
351 CapturedObjectAttributes
->SecurityDescriptor
= NULL
;
353 if(CapturedObjectAttributes
->SecurityQualityOfService
!= NULL
)
355 ExFreePool(CapturedObjectAttributes
->SecurityQualityOfService
);
356 CapturedObjectAttributes
->SecurityQualityOfService
= NULL
;
359 if(ObjectName
!= NULL
&&
360 ObjectName
->Length
> 0)
362 ExFreePool(ObjectName
->Buffer
);
368 /**********************************************************************
380 * Pointer to a unicode string that will contain the
381 * remaining path if the function returns successfully.
382 * The caller must free the buffer after use by calling
383 * RtlFreeUnicodeString ().
386 * Optional pointer to an object type. This is used to
387 * descide if a symbolic link object will be parsed or not.
392 ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes
,
393 PVOID
* ReturnedObject
,
394 PUNICODE_STRING RemainingPath
,
395 POBJECT_TYPE ObjectType
)
400 POBJECT_HEADER CurrentHeader
;
403 UNICODE_STRING PathString
;
405 PUNICODE_STRING ObjectName
;
409 DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, "
410 "RemainingPath %x)\n",ObjectAttributes
,ReturnedObject
,RemainingPath
);
411 DPRINT("ObjectAttributes->ObjectName %wZ\n",
412 ObjectAttributes
->ObjectName
);
414 RtlInitUnicodeString (RemainingPath
, NULL
);
416 if (ObjectAttributes
->RootDirectory
== NULL
)
418 ObReferenceObjectByPointer(NameSpaceRoot
,
422 CurrentObject
= NameSpaceRoot
;
426 Status
= ObReferenceObjectByHandle(ObjectAttributes
->RootDirectory
,
432 if (!NT_SUCCESS(Status
))
438 ObjectName
= ObjectAttributes
->ObjectName
;
439 if (ObjectName
->Length
== 0 ||
440 ObjectName
->Buffer
[0] == UNICODE_NULL
)
442 *ReturnedObject
= CurrentObject
;
443 return STATUS_SUCCESS
;
446 if (ObjectAttributes
->RootDirectory
== NULL
&&
447 ObjectName
->Buffer
[0] != L
'\\')
449 ObDereferenceObject (CurrentObject
);
450 return STATUS_UNSUCCESSFUL
;
453 /* Create a zero-terminated copy of the object name */
454 PathString
.Length
= ObjectName
->Length
;
455 PathString
.MaximumLength
= ObjectName
->Length
+ sizeof(WCHAR
);
456 PathString
.Buffer
= ExAllocatePool (NonPagedPool
,
457 PathString
.MaximumLength
);
458 if (PathString
.Buffer
== NULL
)
460 ObDereferenceObject (CurrentObject
);
461 return STATUS_INSUFFICIENT_RESOURCES
;
464 RtlCopyMemory (PathString
.Buffer
,
467 PathString
.Buffer
[PathString
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
469 current
= PathString
.Buffer
;
471 RootObject
= CurrentObject
;
472 Attributes
= ObjectAttributes
->Attributes
;
473 if (ObjectType
== ObSymbolicLinkType
)
474 Attributes
|= OBJ_OPENLINK
;
478 DPRINT("current %S\n",current
);
479 CurrentHeader
= BODY_TO_HEADER(CurrentObject
);
481 DPRINT("Current ObjectType %wZ\n",
482 &CurrentHeader
->ObjectType
->TypeName
);
484 if (CurrentHeader
->ObjectType
->TypeInfo
.ParseProcedure
== NULL
)
486 DPRINT("Current object can't parse\n");
489 Status
= CurrentHeader
->ObjectType
->TypeInfo
.ParseProcedure(CurrentObject
,
494 if (Status
== STATUS_REPARSE
)
496 /* reparse the object path */
497 NextObject
= NameSpaceRoot
;
498 current
= PathString
.Buffer
;
500 ObReferenceObjectByPointer(NextObject
,
506 if (NextObject
== NULL
)
510 ObDereferenceObject(CurrentObject
);
511 CurrentObject
= NextObject
;
515 RtlpCreateUnicodeString (RemainingPath
, current
, NonPagedPool
);
516 RtlFreeUnicodeString (&PathString
);
517 *ReturnedObject
= CurrentObject
;
519 return STATUS_SUCCESS
;
523 /**********************************************************************
525 * ObQueryNameString@16
536 ObQueryNameString (IN PVOID Object
,
537 OUT POBJECT_NAME_INFORMATION ObjectNameInfo
,
539 OUT PULONG ReturnLength
)
541 POBJECT_NAME_INFORMATION LocalInfo
;
542 POBJECT_HEADER ObjectHeader
;
543 ULONG LocalReturnLength
;
550 if (Length
< sizeof(OBJECT_NAME_INFORMATION
) + sizeof(WCHAR
))
551 return STATUS_INVALID_BUFFER_SIZE
;
553 ObjectNameInfo
->Name
.MaximumLength
= (USHORT
)(Length
- sizeof(OBJECT_NAME_INFORMATION
));
554 ObjectNameInfo
->Name
.Length
= 0;
555 ObjectNameInfo
->Name
.Buffer
=
556 (PWCHAR
)((ULONG_PTR
)ObjectNameInfo
+ sizeof(OBJECT_NAME_INFORMATION
));
557 ObjectNameInfo
->Name
.Buffer
[0] = 0;
559 ObjectHeader
= BODY_TO_HEADER(Object
);
561 if (ObjectHeader
->ObjectType
!= NULL
&&
562 ObjectHeader
->ObjectType
->TypeInfo
.QueryNameProcedure
!= NULL
)
564 DPRINT ("Calling %x\n", ObjectHeader
->ObjectType
->TypeInfo
.QueryNameProcedure
);
565 Status
= ObjectHeader
->ObjectType
->TypeInfo
.QueryNameProcedure (Object
,
570 else if (ObjectHeader
->Name
.Length
> 0 && ObjectHeader
->Name
.Buffer
!= NULL
)
572 DPRINT ("Object does not have a 'QueryName' function\n");
574 if (ObjectHeader
->Parent
== NameSpaceRoot
)
576 DPRINT ("Reached the root directory\n");
577 ObjectNameInfo
->Name
.Length
= 0;
578 ObjectNameInfo
->Name
.Buffer
[0] = 0;
579 Status
= STATUS_SUCCESS
;
581 else if (ObjectHeader
->Parent
!= NULL
)
583 LocalInfo
= ExAllocatePool (NonPagedPool
,
584 sizeof(OBJECT_NAME_INFORMATION
) +
585 MAX_PATH
* sizeof(WCHAR
));
586 if (LocalInfo
== NULL
)
587 return STATUS_INSUFFICIENT_RESOURCES
;
589 Status
= ObQueryNameString (ObjectHeader
->Parent
,
591 MAX_PATH
* sizeof(WCHAR
),
593 if (!NT_SUCCESS (Status
))
595 ExFreePool (LocalInfo
);
599 Status
= RtlAppendUnicodeStringToString (&ObjectNameInfo
->Name
,
602 ExFreePool (LocalInfo
);
604 if (!NT_SUCCESS (Status
))
608 DPRINT ("Object path %wZ\n", &ObjectHeader
->Name
);
609 Status
= RtlAppendUnicodeToString (&ObjectNameInfo
->Name
,
611 if (!NT_SUCCESS (Status
))
614 Status
= RtlAppendUnicodeStringToString (&ObjectNameInfo
->Name
,
615 &ObjectHeader
->Name
);
619 DPRINT ("Object is unnamed\n");
621 ObjectNameInfo
->Name
.MaximumLength
= 0;
622 ObjectNameInfo
->Name
.Length
= 0;
623 ObjectNameInfo
->Name
.Buffer
= NULL
;
625 Status
= STATUS_SUCCESS
;
628 if (NT_SUCCESS (Status
))
630 ObjectNameInfo
->Name
.MaximumLength
=
631 (ObjectNameInfo
->Name
.Length
) ? ObjectNameInfo
->Name
.Length
+ sizeof(WCHAR
) : 0;
633 sizeof(OBJECT_NAME_INFORMATION
) + ObjectNameInfo
->Name
.MaximumLength
;
634 DPRINT ("Returned object path: %wZ\n", &ObjectNameInfo
->Name
);
642 ObpAllocateObject(POBJECT_ATTRIBUTES ObjectAttributes
,
643 POBJECT_TYPE ObjectType
,
645 POBJECT_HEADER
*ObjectHeader
)
647 POBJECT_HEADER Header
;
651 /* If we don't have an Object Type yet, force NonPaged */
652 DPRINT("ObpAllocateObject\n");
655 PoolType
= NonPagedPool
;
656 Tag
= TAG('O', 'b', 'j', 'T');
660 PoolType
= ObjectType
->TypeInfo
.PoolType
;
661 Tag
= ObjectType
->Key
;
664 /* Allocate memory for the Object */
665 Header
= (POBJECT_HEADER
)ExAllocatePoolWithTag(PoolType
, ObjectSize
, Tag
);
667 DPRINT1("Not enough memory!\n");
668 return STATUS_INSUFFICIENT_RESOURCES
;
671 /* Initialize the object header */
672 RtlZeroMemory(Header
, ObjectSize
);
673 DPRINT("Initalizing header %p\n", Header
);
674 Header
->HandleCount
= 0;
675 Header
->RefCount
= 1;
676 Header
->ObjectType
= ObjectType
;
677 if (ObjectAttributes
&& ObjectAttributes
->Attributes
& OBJ_PERMANENT
)
679 Header
->Permanent
= TRUE
;
681 if (ObjectAttributes
&& ObjectAttributes
->Attributes
& OBJ_INHERIT
)
683 Header
->Inherit
= TRUE
;
685 RtlInitUnicodeString(&Header
->Name
, NULL
);
688 *ObjectHeader
= Header
;
689 return STATUS_SUCCESS
;
692 /**********************************************************************
706 ObCreateObject (IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL
,
707 IN POBJECT_TYPE Type
,
708 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
709 IN KPROCESSOR_MODE AccessMode
,
710 IN OUT PVOID ParseContext OPTIONAL
,
712 IN ULONG PagedPoolCharge OPTIONAL
,
713 IN ULONG NonPagedPoolCharge OPTIONAL
,
717 UNICODE_STRING RemainingPath
;
718 POBJECT_HEADER Header
;
719 POBJECT_HEADER ParentHeader
= NULL
;
721 BOOLEAN ObjectAttached
= FALSE
;
723 PSECURITY_DESCRIPTOR NewSecurityDescriptor
= NULL
;
724 SECURITY_SUBJECT_CONTEXT SubjectContext
;
728 if(ObjectAttributesAccessMode
== UserMode
&& ObjectAttributes
!= NULL
)
730 Status
= STATUS_SUCCESS
;
733 ProbeForRead(ObjectAttributes
,
734 sizeof(OBJECT_ATTRIBUTES
),
739 Status
= _SEH_GetExceptionCode();
743 if(!NT_SUCCESS(Status
))
749 DPRINT("ObCreateObject(Type %p ObjectAttributes %p, Object %p)\n",
750 Type
, ObjectAttributes
, Object
);
754 DPRINT1("Invalid object type!\n");
755 return STATUS_INVALID_PARAMETER
;
758 if (ObjectAttributes
!= NULL
&&
759 ObjectAttributes
->ObjectName
!= NULL
&&
760 ObjectAttributes
->ObjectName
->Buffer
!= NULL
)
762 Status
= ObFindObject(ObjectAttributes
,
766 if (!NT_SUCCESS(Status
))
768 DPRINT1("ObFindObject() failed! (Status 0x%x)\n", Status
);
773 ParentHeader
= BODY_TO_HEADER(Parent
);
776 RemainingPath
.Buffer
== NULL
)
778 if (ParentHeader
->ObjectType
!= Type
779 || !(ObjectAttributes
->Attributes
& OBJ_OPENIF
))
781 ObDereferenceObject(Parent
);
782 return STATUS_OBJECT_NAME_COLLISION
;
785 return STATUS_OBJECT_EXISTS
;
790 RtlInitUnicodeString(&RemainingPath
, NULL
);
793 /* Allocate the Object */
794 Status
= ObpAllocateObject(ObjectAttributes
,
796 OBJECT_ALLOC_SIZE(ObjectSize
),
798 if (!NT_SUCCESS(Status
))
800 DPRINT1("ObpAllocateObject failed!\n");
804 DPRINT("Getting Parent and adding entry\n");
805 if (ParentHeader
!= NULL
&&
806 ParentHeader
->ObjectType
== ObDirectoryType
&&
807 RemainingPath
.Buffer
!= NULL
)
809 NamePtr
= RemainingPath
.Buffer
;
810 if (*NamePtr
== L
'\\')
813 ObpAddEntryDirectory(Parent
,
817 ObjectAttached
= TRUE
;
820 if ((Header
->ObjectType
== IoFileObjectType
) ||
821 (Header
->ObjectType
== ExDesktopObjectType
) ||
822 (Header
->ObjectType
->TypeInfo
.OpenProcedure
!= NULL
))
824 DPRINT("About to call Open Routine\n");
825 if (Header
->ObjectType
== IoFileObjectType
)
827 /* TEMPORARY HACK. DO NOT TOUCH -- Alex */
828 DPRINT("Calling IopCreateFile\n");
829 Status
= IopCreateFile(HEADER_TO_BODY(Header
),
831 RemainingPath
.Buffer
,
834 else if (Header
->ObjectType
== ExDesktopObjectType
)
836 /* TEMPORARY HACK. DO NOT TOUCH -- Alex */
837 DPRINT("Calling ExpDesktopCreate\n");
838 Status
= ExpDesktopCreate(HEADER_TO_BODY(Header
),
840 RemainingPath
.Buffer
,
843 else if (Header
->ObjectType
->TypeInfo
.OpenProcedure
!= NULL
)
845 DPRINT("Calling %x\n", Header
->ObjectType
->TypeInfo
.OpenProcedure
);
846 Status
= Header
->ObjectType
->TypeInfo
.OpenProcedure(ObCreateHandle
,
847 HEADER_TO_BODY(Header
),
853 if (!NT_SUCCESS(Status
))
855 if (ObjectAttached
== TRUE
)
857 ObpRemoveEntryDirectory(Header
);
861 ObDereferenceObject(Parent
);
863 RtlFreeUnicodeString(&Header
->Name
);
864 RtlFreeUnicodeString(&RemainingPath
);
866 DPRINT("Create Failed\n");
871 RtlFreeUnicodeString(&RemainingPath
);
873 SeCaptureSubjectContext(&SubjectContext
);
875 DPRINT("Security Assignment in progress\n");
876 /* Build the new security descriptor */
877 Status
= SeAssignSecurity((ParentHeader
!= NULL
) ? ParentHeader
->SecurityDescriptor
: NULL
,
878 (ObjectAttributes
!= NULL
) ? ObjectAttributes
->SecurityDescriptor
: NULL
,
879 &NewSecurityDescriptor
,
880 (Header
->ObjectType
== ObDirectoryType
),
882 &Header
->ObjectType
->TypeInfo
.GenericMapping
,
884 if (NT_SUCCESS(Status
))
886 DPRINT("NewSecurityDescriptor %p\n", NewSecurityDescriptor
);
888 if (Header
->ObjectType
->TypeInfo
.SecurityProcedure
!= NULL
)
890 /* Call the security method */
891 Status
= Header
->ObjectType
->TypeInfo
.SecurityProcedure(HEADER_TO_BODY(Header
),
892 AssignSecurityDescriptor
,
894 NewSecurityDescriptor
,
899 /* Assign the security descriptor to the object header */
900 Status
= ObpAddSecurityDescriptor(NewSecurityDescriptor
,
901 &Header
->SecurityDescriptor
);
902 DPRINT("Object security descriptor %p\n", Header
->SecurityDescriptor
);
905 /* Release the new security descriptor */
906 SeDeassignSecurity(&NewSecurityDescriptor
);
909 DPRINT("Security Complete\n");
910 SeReleaseSubjectContext(&SubjectContext
);
914 *Object
= HEADER_TO_BODY(Header
);
918 return STATUS_SUCCESS
;
923 * FUNCTION: Increments the pointer reference count for a given object
925 * ObjectBody = Object's body
926 * DesiredAccess = Desired access to the object
927 * ObjectType = Points to the object type structure
928 * AccessMode = Type of access check to perform
934 ObReferenceObjectByPointer(IN PVOID Object
,
935 IN ACCESS_MASK DesiredAccess
,
936 IN POBJECT_TYPE ObjectType
,
937 IN KPROCESSOR_MODE AccessMode
)
939 POBJECT_HEADER Header
;
941 /* NOTE: should be possible to reference an object above APC_LEVEL! */
943 DPRINT("ObReferenceObjectByPointer(Object %x, ObjectType %x)\n",
946 Header
= BODY_TO_HEADER(Object
);
948 if (ObjectType
!= NULL
&& Header
->ObjectType
!= ObjectType
)
950 DPRINT("Failed %x (type was %x %S) should be %x %S\n",
953 Header
->ObjectType
->TypeName
.Buffer
,
955 ObjectType
->TypeName
.Buffer
);
956 return(STATUS_UNSUCCESSFUL
);
958 if (Header
->ObjectType
== PsProcessType
)
960 DPRINT("Ref p 0x%x refcount %d type %x ",
961 Object
, Header
->RefCount
, PsProcessType
);
962 DPRINT("eip %x\n", ((PULONG
)&Object
)[-1]);
964 if (Header
->ObjectType
== PsThreadType
)
966 DPRINT("Deref t 0x%x with refcount %d type %x ",
967 Object
, Header
->RefCount
, PsThreadType
);
968 DPRINT("eip %x\n", ((PULONG
)&Object
)[-1]);
971 if (Header
->RefCount
== 0 && !Header
->Permanent
)
973 if (Header
->ObjectType
== PsProcessType
)
975 return STATUS_PROCESS_IS_TERMINATING
;
977 if (Header
->ObjectType
== PsThreadType
)
979 return STATUS_THREAD_IS_TERMINATING
;
981 return(STATUS_UNSUCCESSFUL
);
984 if (1 == InterlockedIncrement(&Header
->RefCount
) && !Header
->Permanent
)
989 return(STATUS_SUCCESS
);
997 ObOpenObjectByPointer(IN POBJECT Object
,
998 IN ULONG HandleAttributes
,
999 IN PACCESS_STATE PassedAccessState
,
1000 IN ACCESS_MASK DesiredAccess
,
1001 IN POBJECT_TYPE ObjectType
,
1002 IN KPROCESSOR_MODE AccessMode
,
1009 DPRINT("ObOpenObjectByPointer()\n");
1011 Status
= ObReferenceObjectByPointer(Object
,
1015 if (!NT_SUCCESS(Status
))
1020 Status
= ObpCreateHandle(PsGetCurrentProcess(),
1023 (BOOLEAN
)(HandleAttributes
& OBJ_INHERIT
),
1026 ObDereferenceObject(Object
);
1028 return STATUS_SUCCESS
;
1033 ObpDeleteObject(POBJECT_HEADER Header
)
1035 DPRINT("ObpDeleteObject(Header %p)\n", Header
);
1036 if (KeGetCurrentIrql() != PASSIVE_LEVEL
)
1038 DPRINT("ObpDeleteObject called at an unsupported IRQL. Use ObpDeleteObjectDpcLevel instead.\n");
1042 if (Header
->SecurityDescriptor
!= NULL
)
1044 ObpRemoveSecurityDescriptor(Header
->SecurityDescriptor
);
1047 if (Header
->ObjectType
!= NULL
&&
1048 Header
->ObjectType
->TypeInfo
.DeleteProcedure
!= NULL
)
1050 Header
->ObjectType
->TypeInfo
.DeleteProcedure(HEADER_TO_BODY(Header
));
1053 if (Header
->Name
.Buffer
!= NULL
)
1055 ObpRemoveEntryDirectory(Header
);
1056 RtlFreeUnicodeString(&Header
->Name
);
1059 DPRINT("ObPerformRetentionChecks() = Freeing object\n");
1062 return(STATUS_SUCCESS
);
1067 ObpDeleteObjectWorkRoutine (IN PVOID Parameter
)
1069 PRETENTION_CHECK_PARAMS Params
= (PRETENTION_CHECK_PARAMS
)Parameter
;
1070 /* ULONG Tag; */ /* See below */
1073 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
); /* We need PAGED_CODE somewhere... */
1075 /* Turn this on when we have ExFreePoolWithTag
1076 Tag = Params->ObjectHeader->ObjectType->Tag; */
1077 ObpDeleteObject(Params
->ObjectHeader
);
1079 /* ExFreePoolWithTag(Params, Tag); */
1084 ObpDeleteObjectDpcLevel(IN POBJECT_HEADER ObjectHeader
,
1085 IN LONG OldRefCount
)
1088 if (ObjectHeader
->RefCount
< 0)
1090 CPRINT("Object %p/%p has invalid reference count (%d)\n",
1091 ObjectHeader
, HEADER_TO_BODY(ObjectHeader
),
1092 ObjectHeader
->RefCount
);
1096 if (ObjectHeader
->HandleCount
< 0)
1098 CPRINT("Object %p/%p has invalid handle count (%d)\n",
1099 ObjectHeader
, HEADER_TO_BODY(ObjectHeader
),
1100 ObjectHeader
->HandleCount
);
1106 switch (KeGetCurrentIrql ())
1109 return ObpDeleteObject (ObjectHeader
);
1112 case DISPATCH_LEVEL
:
1114 PRETENTION_CHECK_PARAMS Params
;
1117 We use must succeed pool here because if the allocation fails
1118 then we leak memory.
1120 Params
= (PRETENTION_CHECK_PARAMS
)
1121 ExAllocatePoolWithTag(NonPagedPoolMustSucceed
,
1122 sizeof(RETENTION_CHECK_PARAMS
),
1123 ObjectHeader
->ObjectType
->Key
);
1124 Params
->ObjectHeader
= ObjectHeader
;
1125 ExInitializeWorkItem(&Params
->WorkItem
,
1126 ObpDeleteObjectWorkRoutine
,
1128 ExQueueWorkItem(&Params
->WorkItem
,
1131 return STATUS_PENDING
;
1134 DPRINT("ObpDeleteObjectDpcLevel called at unsupported "
1135 "IRQL %u!\n", KeGetCurrentIrql());
1137 return STATUS_UNSUCCESSFUL
;
1140 return STATUS_SUCCESS
;
1144 /**********************************************************************
1146 * ObfReferenceObject@4
1149 * Increments a given object's reference count and performs
1153 * ObjectBody = Body of the object.
1161 ObfReferenceObject(IN PVOID Object
)
1163 POBJECT_HEADER Header
;
1167 Header
= BODY_TO_HEADER(Object
);
1169 /* No one should be referencing an object once we are deleting it. */
1170 if (InterlockedIncrement(&Header
->RefCount
) == 1 && !Header
->Permanent
)
1177 /**********************************************************************
1179 * ObfDereferenceObject@4
1182 * Decrements a given object's reference count and performs
1186 * ObjectBody = Body of the object.
1194 ObfDereferenceObject(IN PVOID Object
)
1196 POBJECT_HEADER Header
;
1202 /* Extract the object header. */
1203 Header
= BODY_TO_HEADER(Object
);
1204 Permanent
= Header
->Permanent
;
1207 Drop our reference and get the new count so we can tell if this was the
1210 NewRefCount
= InterlockedDecrement(&Header
->RefCount
);
1211 DPRINT("ObfDereferenceObject(0x%x)==%d (%wZ)\n", Object
, NewRefCount
, &Header
->ObjectType
->TypeName
);
1212 ASSERT(NewRefCount
>= 0);
1214 /* Check whether the object can now be deleted. */
1215 if (NewRefCount
== 0 &&
1218 ObpDeleteObjectDpcLevel(Header
, NewRefCount
);
1224 ObInitializeFastReference(IN PEX_FAST_REF FastRef
,
1227 /* FIXME: Fast Referencing is Unimplemented */
1228 FastRef
->Object
= Object
;
1234 ObFastReferenceObject(IN PEX_FAST_REF FastRef
)
1236 /* FIXME: Fast Referencing is Unimplemented */
1238 /* Do a normal Reference */
1239 ObReferenceObject(FastRef
->Object
);
1241 /* Return the Object */
1242 return FastRef
->Object
;
1247 ObFastDereferenceObject(IN PEX_FAST_REF FastRef
,
1250 /* FIXME: Fast Referencing is Unimplemented */
1252 /* Do a normal Dereference */
1253 ObDereferenceObject(FastRef
->Object
);
1258 ObFastReplaceObject(IN PEX_FAST_REF FastRef
,
1261 PVOID OldObject
= FastRef
->Object
;
1263 /* FIXME: Fast Referencing is Unimplemented */
1264 FastRef
->Object
= Object
;
1266 /* Do a normal Dereference */
1267 ObDereferenceObject(OldObject
);
1269 /* Return old Object*/
1273 /**********************************************************************
1275 * ObGetObjectPointerCount@4
1278 * Retrieves the pointer(reference) count of the given object.
1281 * ObjectBody = Body of the object.
1289 ObGetObjectPointerCount(PVOID Object
)
1291 POBJECT_HEADER Header
;
1296 Header
= BODY_TO_HEADER(Object
);
1298 return Header
->RefCount
;
1302 /**********************************************************************
1304 * ObGetObjectHandleCount@4
1307 * Retrieves the handle count of the given object.
1310 * ObjectBody = Body of the object.
1316 ObGetObjectHandleCount(PVOID Object
)
1318 POBJECT_HEADER Header
;
1323 Header
= BODY_TO_HEADER(Object
);
1325 return Header
->HandleCount
;
1329 /**********************************************************************
1331 * ObDereferenceObject@4
1334 * Decrements a given object's reference count and performs
1338 * ObjectBody = Body of the object.
1346 #ifdef ObDereferenceObject
1347 #undef ObDereferenceObject
1351 ObDereferenceObject(IN PVOID Object
)
1353 ObfDereferenceObject(Object
);