2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ob/obhandle.c
5 * PURPOSE: Manages all functions related to the Object Manager handle
6 * implementation, including creating and destroying handles
7 * and/or handle tables, duplicating objects, and setting the
8 * permanent or temporary flags.
9 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
11 * Thomas Weidenmueller (w3seek@reactos.org)
14 /* INCLUDES ******************************************************************/
18 #include <internal/debug.h>
20 PHANDLE_TABLE ObpKernelHandleTable
= NULL
;
22 /* PRIVATE FUNCTIONS *********************************************************/
26 ObpChargeQuotaForObject(IN POBJECT_HEADER ObjectHeader
,
27 IN POBJECT_TYPE ObjectType
)
29 POBJECT_HEADER_QUOTA_INFO ObjectQuota
;
30 ULONG PagedPoolCharge
, NonPagedPoolCharge
;
33 /* Get quota information */
34 ObjectQuota
= OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader
);
36 /* Check if this is a new object */
37 if (ObjectHeader
->Flags
& OB_FLAG_CREATE_INFO
)
40 ObjectHeader
->Flags
&= ~ OB_FLAG_CREATE_INFO
;
43 /* We have a quota, get the charges */
44 PagedPoolCharge
= ObjectQuota
->PagedPoolCharge
;
45 NonPagedPoolCharge
= ObjectQuota
->NonPagedPoolCharge
;
49 /* Get it from the object type */
50 PagedPoolCharge
= ObjectType
->TypeInfo
.DefaultPagedPoolCharge
;
51 NonPagedPoolCharge
= ObjectType
->TypeInfo
.DefaultNonPagedPoolCharge
;
56 * FIXME: This is a *COMPLETE* guess and probably defintely not the way to do this.
58 Process
= PsGetCurrentProcess();
59 Process
->QuotaBlock
->QuotaEntry
[PagedPool
].Usage
+= PagedPoolCharge
;
60 Process
->QuotaBlock
->QuotaEntry
[NonPagedPool
].Usage
+= NonPagedPoolCharge
;
61 ObjectHeader
->QuotaBlockCharged
= Process
->QuotaBlock
;
65 return STATUS_SUCCESS
;
69 * @name ObpDecrementHandleCount
71 * The ObpDecrementHandleCount routine <FILLMEIN>
79 * @param GrantedAccess
89 ObpDecrementHandleCount(IN PVOID ObjectBody
,
91 IN ACCESS_MASK GrantedAccess
)
93 POBJECT_HEADER ObjectHeader
;
94 POBJECT_TYPE ObjectType
;
95 LONG SystemHandleCount
, ProcessHandleCount
;
97 POBJECT_HEADER_CREATOR_INFO CreatorInfo
;
99 /* Get the object type and header */
100 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(ObjectBody
);
101 ObjectType
= ObjectHeader
->Type
;
102 OBTRACE(OB_HANDLE_DEBUG
,
103 "%s - Decrementing count for: %p. HC LC %lx %lx\n",
106 ObjectHeader
->HandleCount
,
107 ObjectHeader
->PointerCount
);
109 /* Lock the object type */
110 ObpEnterObjectTypeMutex(ObjectType
);
112 /* FIXME: The process handle count should be in the Handle DB. Investigate */
113 SystemHandleCount
= ObjectHeader
->HandleCount
;
114 ProcessHandleCount
= 0;
116 /* Decrement the handle count */
117 NewCount
= InterlockedDecrement(&ObjectHeader
->HandleCount
);
119 /* Check if we're out of handles */
122 /* Get the creator info */
123 CreatorInfo
= OBJECT_HEADER_TO_CREATOR_INFO(ObjectHeader
);
124 if ((CreatorInfo
) && !(IsListEmpty(&CreatorInfo
->TypeList
)))
126 /* Remove it from the list and re-initialize it */
127 RemoveEntryList(&CreatorInfo
->TypeList
);
128 InitializeListHead(&CreatorInfo
->TypeList
);
132 /* Release the lock */
133 ObpLeaveObjectTypeMutex(ObjectType
);
135 /* Check if we have a close procedure */
136 if (ObjectType
->TypeInfo
.CloseProcedure
)
139 ObjectType
->TypeInfo
.CloseProcedure(Process
,
146 /* Check if we should delete the object */
147 ObpDeleteNameCheck(ObjectBody
);
149 /* Decrease the total number of handles for this type */
150 InterlockedDecrement((PLONG
)&ObjectType
->TotalNumberOfHandles
);
151 OBTRACE(OB_HANDLE_DEBUG
,
152 "%s - Decremented count for: %p. HC LC %lx %lx\n",
155 ObjectHeader
->HandleCount
,
156 ObjectHeader
->PointerCount
);
160 * @name ObpCloseHandleTableEntry
162 * The ObpCloseHandleTableEntry routine <FILLMEIN>
176 * @param IgnoreHandleProtection
179 * @return <FILLMEIN>.
186 ObpCloseHandleTableEntry(IN PHANDLE_TABLE HandleTable
,
187 IN PHANDLE_TABLE_ENTRY HandleEntry
,
189 IN KPROCESSOR_MODE AccessMode
,
190 IN BOOLEAN IgnoreHandleProtection
)
193 POBJECT_TYPE ObjectType
;
194 POBJECT_HEADER ObjectHeader
;
195 ACCESS_MASK GrantedAccess
;
198 /* Get the object data */
199 ObjectHeader
= EX_HTE_TO_HDR(HandleEntry
);
200 ObjectType
= ObjectHeader
->Type
;
201 Body
= &ObjectHeader
->Body
;
202 GrantedAccess
= HandleEntry
->GrantedAccess
;
203 OBTRACE(OB_HANDLE_DEBUG
,
204 "%s - Closing handle: %lx for %p. HC LC %lx %lx\n",
208 ObjectHeader
->HandleCount
,
209 ObjectHeader
->PointerCount
);
211 /* Check if the object has an Okay To Close procedure */
212 if (ObjectType
->TypeInfo
.OkayToCloseProcedure
)
214 /* Call it and check if it's not letting us close it */
215 if (!ObjectType
->TypeInfo
.OkayToCloseProcedure(PsGetCurrentProcess(),
221 ExUnlockHandleTableEntry(HandleTable
, HandleEntry
);
222 return STATUS_HANDLE_NOT_CLOSABLE
;
226 /* The callback allowed us to close it, but does the handle itself? */
227 if ((HandleEntry
->ObAttributes
& EX_HANDLE_ENTRY_PROTECTFROMCLOSE
) &&
228 !(IgnoreHandleProtection
))
230 /* It doesn't, are we from user mode? */
231 if (AccessMode
!= KernelMode
)
233 /* We are! Unlock the entry */
234 ExUnlockHandleTableEntry(HandleTable
, HandleEntry
);
236 /* Make sure we have an exception port */
237 if (PsGetCurrentProcess()->ExceptionPort
)
239 /* Raise an exception */
240 return KeRaiseUserException(STATUS_HANDLE_NOT_CLOSABLE
);
244 /* Return the error isntead */
245 return STATUS_HANDLE_NOT_CLOSABLE
;
249 /* Otherwise, we are kernel mode, so unlock the entry and return */
250 ExUnlockHandleTableEntry(HandleTable
, HandleEntry
);
251 return STATUS_HANDLE_NOT_CLOSABLE
;
254 /* Destroy and unlock the handle entry */
255 ExDestroyHandleByEntry(HandleTable
, HandleEntry
, Handle
);
257 /* Now decrement the handle count */
258 ObpDecrementHandleCount(Body
, PsGetCurrentProcess(), GrantedAccess
);
260 /* Dereference the object as well */
261 ASSERT(ObjectHeader
->Type
);
262 ASSERT(ObjectHeader
->PointerCount
!= 0xCCCCCCCC);
264 ObDereferenceObject(Body
);
266 /* Return to caller */
267 OBTRACE(OB_HANDLE_DEBUG
,
268 "%s - Closed handle: %lx for %p. HC LC %lx %lx\n",
272 ObjectHeader
->HandleCount
,
273 ObjectHeader
->PointerCount
);
274 return STATUS_SUCCESS
;
278 * @name ObpIncrementHandleCount
280 * The ObpIncrementHandleCount routine <FILLMEIN>
291 * @param HandleAttributes
300 * @return <FILLMEIN>.
307 ObpIncrementHandleCount(IN PVOID Object
,
308 IN PACCESS_STATE AccessState
,
309 IN KPROCESSOR_MODE AccessMode
,
310 IN ULONG HandleAttributes
,
311 IN PEPROCESS Process
,
312 IN OB_OPEN_REASON OpenReason
)
314 POBJECT_HEADER ObjectHeader
;
315 POBJECT_TYPE ObjectType
;
316 ULONG ProcessHandleCount
;
319 /* Get the object header and type */
320 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
321 ObjectType
= ObjectHeader
->Type
;
322 OBTRACE(OB_HANDLE_DEBUG
,
323 "%s - Incrementing count for: %p. Reason: %lx. HC LC %lx %lx\n",
327 ObjectHeader
->HandleCount
,
328 ObjectHeader
->PointerCount
);
330 /* Lock the object type */
331 ObpEnterObjectTypeMutex(ObjectType
);
333 /* Charge quota and remove the creator info flag */
334 Status
= ObpChargeQuotaForObject(ObjectHeader
, ObjectType
);
335 if (!NT_SUCCESS(Status
)) return Status
;
337 /* Check if we're opening an existing handle */
338 if (OpenReason
== ObOpenHandle
)
340 /* Validate the caller's access to this object */
341 if (!ObCheckObjectAccess(Object
,
347 /* Access was denied, so fail */
351 else if (OpenReason
== ObCreateHandle
)
353 /* Convert MAXIMUM_ALLOWED to GENERIC_ALL */
354 if (AccessState
->RemainingDesiredAccess
& MAXIMUM_ALLOWED
)
356 /* Mask out MAXIMUM_ALLOWED and stick GENERIC_ALL instead */
357 AccessState
->RemainingDesiredAccess
&= ~MAXIMUM_ALLOWED
;
358 AccessState
->RemainingDesiredAccess
|= GENERIC_ALL
;
361 /* Check if we have to map the GENERIC mask */
362 if (AccessState
->RemainingDesiredAccess
& GENERIC_ACCESS
)
364 /* Map it to the correct access masks */
365 RtlMapGenericMask(&AccessState
->RemainingDesiredAccess
,
366 &ObjectType
->TypeInfo
.GenericMapping
);
370 /* Increase the handle count */
371 InterlockedIncrement(&ObjectHeader
->HandleCount
);
373 /* Release the lock */
374 ObpLeaveObjectTypeMutex(ObjectType
);
376 /* FIXME: Use the Handle Database */
377 ProcessHandleCount
= 0;
379 /* Check if we have an open procedure */
380 if (ObjectType
->TypeInfo
.OpenProcedure
)
383 ObjectType
->TypeInfo
.OpenProcedure(OpenReason
,
386 AccessState
->PreviouslyGrantedAccess
,
390 /* Increase total number of handles */
391 InterlockedIncrement((PLONG
)&ObjectType
->TotalNumberOfHandles
);
392 OBTRACE(OB_HANDLE_DEBUG
,
393 "%s - Incremented count for: %p. Reason: %lx HC LC %lx %lx\n",
397 ObjectHeader
->HandleCount
,
398 ObjectHeader
->PointerCount
);
399 return STATUS_SUCCESS
;
403 * @name ObpIncrementUnnamedHandleCount
405 * The ObpIncrementUnnamedHandleCount routine <FILLMEIN>
416 * @param HandleAttributes
425 * @return <FILLMEIN>.
432 ObpIncrementUnnamedHandleCount(IN PVOID Object
,
433 IN PACCESS_MASK DesiredAccess
,
434 IN KPROCESSOR_MODE AccessMode
,
435 IN ULONG HandleAttributes
,
436 IN PEPROCESS Process
)
438 POBJECT_HEADER ObjectHeader
;
439 POBJECT_TYPE ObjectType
;
440 ULONG ProcessHandleCount
;
443 /* Get the object header and type */
444 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
445 ObjectType
= ObjectHeader
->Type
;
446 OBTRACE(OB_HANDLE_DEBUG
,
447 "%s - Incrementing count for: %p. UNNAMED. HC LC %lx %lx\n",
450 ObjectHeader
->HandleCount
,
451 ObjectHeader
->PointerCount
);
453 /* Lock the object type */
454 ObpEnterObjectTypeMutex(ObjectType
);
456 /* Charge quota and remove the creator info flag */
457 Status
= ObpChargeQuotaForObject(ObjectHeader
, ObjectType
);
458 if (!NT_SUCCESS(Status
)) return Status
;
460 /* Convert MAXIMUM_ALLOWED to GENERIC_ALL */
461 if (*DesiredAccess
& MAXIMUM_ALLOWED
)
463 /* Mask out MAXIMUM_ALLOWED and stick GENERIC_ALL instead */
464 *DesiredAccess
&= ~MAXIMUM_ALLOWED
;
465 *DesiredAccess
|= GENERIC_ALL
;
468 /* Check if we have to map the GENERIC mask */
469 if (*DesiredAccess
& GENERIC_ACCESS
)
471 /* Map it to the correct access masks */
472 RtlMapGenericMask(DesiredAccess
,
473 &ObjectType
->TypeInfo
.GenericMapping
);
476 /* Increase the handle count */
477 InterlockedIncrement(&ObjectHeader
->HandleCount
);
479 /* Release the object type */
480 ObpLeaveObjectTypeMutex(ObjectType
);
482 /* FIXME: Use the Handle Database */
483 ProcessHandleCount
= 0;
485 /* Check if we have an open procedure */
486 if (ObjectType
->TypeInfo
.OpenProcedure
)
489 ObjectType
->TypeInfo
.OpenProcedure(ObCreateHandle
,
496 /* Increase total number of handles */
497 InterlockedIncrement((PLONG
)&ObjectType
->TotalNumberOfHandles
);
498 OBTRACE(OB_HANDLE_DEBUG
,
499 "%s - Incremented count for: %p. UNNAMED HC LC %lx %lx\n",
502 ObjectHeader
->HandleCount
,
503 ObjectHeader
->PointerCount
);
504 return STATUS_SUCCESS
;
508 * @name ObpCreateUnnamedHandle
510 * The ObpCreateUnnamedHandle routine <FILLMEIN>
515 * @param DesiredAccess
518 * @param AdditionalReferences
521 * @param HandleAttributes
527 * @param ReturnedObject
530 * @param ReturnedHandle
533 * @return <FILLMEIN>.
540 ObpCreateUnnamedHandle(IN PVOID Object
,
541 IN ACCESS_MASK DesiredAccess
,
542 IN ULONG AdditionalReferences
,
543 IN ULONG HandleAttributes
,
544 IN KPROCESSOR_MODE AccessMode
,
545 OUT PVOID
*ReturnedObject
,
546 OUT PHANDLE ReturnedHandle
)
548 HANDLE_TABLE_ENTRY NewEntry
;
549 POBJECT_HEADER ObjectHeader
;
552 BOOLEAN AttachedToProcess
= FALSE
;
558 /* Get the object header and type */
559 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
560 OBTRACE(OB_HANDLE_DEBUG
,
561 "%s - Creating handle for: %p. UNNAMED. HC LC %lx %lx\n",
564 ObjectHeader
->HandleCount
,
565 ObjectHeader
->PointerCount
);
567 /* Check if this is a kernel handle */
568 if ((HandleAttributes
& OBJ_KERNEL_HANDLE
) && (AccessMode
== KernelMode
))
570 /* Set the handle table */
571 HandleTable
= ObpKernelHandleTable
;
573 /* Check if we're not in the system process */
574 if (PsGetCurrentProcess() != PsInitialSystemProcess
)
576 /* Attach to the system process */
577 KeStackAttachProcess(&PsInitialSystemProcess
->Pcb
, &ApcState
);
578 AttachedToProcess
= TRUE
;
583 /* Get the current handle table */
584 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
587 /* Increment the handle count */
588 Status
= ObpIncrementUnnamedHandleCount(Object
,
592 PsGetCurrentProcess());
593 if (!NT_SUCCESS(Status
))
596 * We failed (meaning security failure, according to NT Internals)
599 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
603 /* Save the object header (assert its validity too) */
604 ASSERT((ULONG_PTR
)ObjectHeader
& EX_HANDLE_ENTRY_LOCKED
);
605 NewEntry
.Object
= ObjectHeader
;
607 /* Mask out the internal attributes */
608 NewEntry
.ObAttributes
|= HandleAttributes
&
609 (EX_HANDLE_ENTRY_PROTECTFROMCLOSE
|
610 EX_HANDLE_ENTRY_INHERITABLE
|
611 EX_HANDLE_ENTRY_AUDITONCLOSE
);
613 /* Save the access mask */
614 NewEntry
.GrantedAccess
= DesiredAccess
;
616 /* Handle extra references */
617 if (AdditionalReferences
)
619 /* Make a copy in case we fail later below */
620 i
= AdditionalReferences
;
623 /* Increment the count */
624 InterlockedIncrement(&ObjectHeader
->PointerCount
);
629 * Create the actual handle. We'll need to do this *after* calling
630 * ObpIncrementHandleCount to make sure that Object Security is valid
631 * (specified in Gl00my documentation on Ob)
633 OBTRACE(OB_HANDLE_DEBUG
,
634 "%s - Handle Properties: [%p-%lx-%lx]\n",
636 NewEntry
.Object
, NewEntry
.ObAttributes
& 3, NewEntry
.GrantedAccess
);
637 Handle
= ExCreateHandle(HandleTable
, &NewEntry
);
639 /* Detach if needed */
640 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
642 /* Make sure we got a handle */
645 /* Check if this was a kernel handle */
646 if (HandleAttributes
& OBJ_KERNEL_HANDLE
)
648 /* Set the kernel handle bit */
649 Handle
= ObMarkHandleAsKernelHandle(Handle
);
652 /* Return handle and object */
653 *ReturnedHandle
= Handle
;
654 if (ReturnedObject
) *ReturnedObject
= Object
;
655 OBTRACE(OB_HANDLE_DEBUG
,
656 "%s - Returning Handle: %lx HC LC %lx %lx\n",
659 ObjectHeader
->HandleCount
,
660 ObjectHeader
->PointerCount
);
661 return STATUS_SUCCESS
;
664 /* Handle extra references */
665 while (AdditionalReferences
--)
667 /* Decrement the count */
668 InterlockedDecrement(&ObjectHeader
->PointerCount
);
671 /* Decrement the handle count and detach */
672 ObpDecrementHandleCount(&ObjectHeader
->Body
,
673 PsGetCurrentProcess(),
674 NewEntry
.GrantedAccess
);
675 return STATUS_INSUFFICIENT_RESOURCES
;
679 * @name ObpCreateHandle
681 * The ObpCreateHandle routine <FILLMEIN>
695 * @param AdditionalReferences
698 * @param HandleAttributes
704 * @param ReturnedObject
707 * @param ReturnedHandle
710 * @return <FILLMEIN>.
712 * @remarks Gloomy says OpenReason is "enables Security" if == 1.
713 * since this function *has* to call ObpIncrementHandleCount,
714 * which needs to somehow know the OpenReason, and since
715 * ObOpenHandle == 1, I'm guessing this is actually the
716 * OpenReason. Also makes sense since this function is shared
717 * by Duplication, Creation and Opening..
722 ObpCreateHandle(IN OB_OPEN_REASON OpenReason
,
724 IN POBJECT_TYPE Type OPTIONAL
,
725 IN PACCESS_STATE AccessState
,
726 IN ULONG AdditionalReferences
,
727 IN ULONG HandleAttributes
,
728 IN KPROCESSOR_MODE AccessMode
,
729 OUT PVOID
*ReturnedObject
,
730 OUT PHANDLE ReturnedHandle
)
732 HANDLE_TABLE_ENTRY NewEntry
;
733 POBJECT_HEADER ObjectHeader
;
736 BOOLEAN AttachedToProcess
= FALSE
;
737 POBJECT_TYPE ObjectType
;
743 /* Get the object header and type */
744 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
745 ObjectType
= ObjectHeader
->Type
;
746 OBTRACE(OB_HANDLE_DEBUG
,
747 "%s - Creating handle for: %p. Reason: %lx. HC LC %lx %lx\n",
751 ObjectHeader
->HandleCount
,
752 ObjectHeader
->PointerCount
);
754 /* Check if the types match */
755 if ((Type
) && (ObjectType
!= Type
)) return STATUS_OBJECT_TYPE_MISMATCH
;
757 /* Check if this is a kernel handle */
758 if ((HandleAttributes
& OBJ_KERNEL_HANDLE
) && (AccessMode
== KernelMode
))
760 /* Set the handle table */
761 HandleTable
= ObpKernelHandleTable
;
763 /* Check if we're not in the system process */
764 if (PsGetCurrentProcess() != PsInitialSystemProcess
)
766 /* Attach to the system process */
767 KeStackAttachProcess(&PsInitialSystemProcess
->Pcb
, &ApcState
);
768 AttachedToProcess
= TRUE
;
773 /* Get the current handle table */
774 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
777 /* Increment the handle count */
778 Status
= ObpIncrementHandleCount(Object
,
782 PsGetCurrentProcess(),
784 if (!NT_SUCCESS(Status
))
787 * We failed (meaning security failure, according to NT Internals)
790 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
794 /* Save the object header (assert its validity too) */
795 ASSERT((ULONG_PTR
)ObjectHeader
& EX_HANDLE_ENTRY_LOCKED
);
796 NewEntry
.Object
= ObjectHeader
;
798 /* Mask out the internal attributes */
799 NewEntry
.ObAttributes
|= HandleAttributes
&
800 (EX_HANDLE_ENTRY_PROTECTFROMCLOSE
|
801 EX_HANDLE_ENTRY_INHERITABLE
|
802 EX_HANDLE_ENTRY_AUDITONCLOSE
);
804 /* Save the access mask */
805 NewEntry
.GrantedAccess
= AccessState
->RemainingDesiredAccess
|
806 AccessState
->PreviouslyGrantedAccess
;
808 /* Handle extra references */
809 if (AdditionalReferences
)
811 /* Make a copy in case we fail later below */
812 i
= AdditionalReferences
;
815 /* Increment the count */
816 InterlockedIncrement(&ObjectHeader
->PointerCount
);
821 * Create the actual handle. We'll need to do this *after* calling
822 * ObpIncrementHandleCount to make sure that Object Security is valid
823 * (specified in Gl00my documentation on Ob)
825 OBTRACE(OB_HANDLE_DEBUG
,
826 "%s - Handle Properties: [%p-%lx-%lx]\n",
828 NewEntry
.Object
, NewEntry
.ObAttributes
& 3, NewEntry
.GrantedAccess
);
829 Handle
= ExCreateHandle(HandleTable
, &NewEntry
);
831 /* Detach if needed */
832 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
834 /* Make sure we got a handle */
837 /* Check if this was a kernel handle */
838 if (HandleAttributes
& OBJ_KERNEL_HANDLE
)
840 /* Set the kernel handle bit */
841 Handle
= ObMarkHandleAsKernelHandle(Handle
);
844 /* Return handle and object */
845 *ReturnedHandle
= Handle
;
846 if (ReturnedObject
) *ReturnedObject
= Object
;
847 OBTRACE(OB_HANDLE_DEBUG
,
848 "%s - Returning Handle: %lx HC LC %lx %lx\n",
851 ObjectHeader
->HandleCount
,
852 ObjectHeader
->PointerCount
);
853 return STATUS_SUCCESS
;
856 /* Handle extra references */
857 while (AdditionalReferences
--)
859 /* Increment the count */
860 InterlockedDecrement(&ObjectHeader
->PointerCount
);
863 /* Decrement the handle count and detach */
864 ObpDecrementHandleCount(&ObjectHeader
->Body
,
865 PsGetCurrentProcess(),
866 NewEntry
.GrantedAccess
);
867 return STATUS_INSUFFICIENT_RESOURCES
;
871 * @name ObpCloseHandle
873 * The ObpCloseHandle routine <FILLMEIN>
881 * @return <FILLMEIN>.
888 ObpCloseHandle(IN HANDLE Handle
,
889 IN KPROCESSOR_MODE AccessMode
)
892 BOOLEAN AttachedToProcess
= FALSE
;
894 PHANDLE_TABLE_ENTRY HandleTableEntry
;
897 OBTRACE(OB_HANDLE_DEBUG
,
898 "%s - Closing handle: %lx\n", __FUNCTION__
, Handle
);
900 /* Check if we're dealing with a kernel handle */
901 if (ObIsKernelHandle(Handle
, AccessMode
))
903 /* Use the kernel table and convert the handle */
904 HandleTable
= ObpKernelHandleTable
;
905 Handle
= ObKernelHandleToHandle(Handle
);
907 /* Check if we're not in the system process */
908 if (PsGetCurrentProcess() != PsInitialSystemProcess
)
910 /* Attach to the system process */
911 KeStackAttachProcess(&PsInitialSystemProcess
->Pcb
, &ApcState
);
912 AttachedToProcess
= TRUE
;
917 /* Use the process's handle table */
918 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
921 /* Enter a critical region to protect handle access */
922 KeEnterCriticalRegion();
924 /* Get the handle entry */
925 HandleTableEntry
= ExMapHandleToPointer(HandleTable
, Handle
);
926 if (HandleTableEntry
)
928 /* Now close the entry */
929 Status
= ObpCloseHandleTableEntry(HandleTable
,
935 /* We can quit the critical region now */
936 KeLeaveCriticalRegion();
938 /* Detach and return success */
939 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
940 return STATUS_SUCCESS
;
944 /* We failed, quit the critical region */
945 KeLeaveCriticalRegion();
948 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
950 /* Check if this was a user-mode caller with a valid exception port */
951 if ((AccessMode
!= KernelMode
) &&
952 (PsGetCurrentProcess()->ExceptionPort
))
954 /* Raise an exception */
955 Status
= KeRaiseUserException(STATUS_INVALID_HANDLE
);
959 /* Just return the status */
960 Status
= STATUS_INVALID_HANDLE
;
965 OBTRACE(OB_HANDLE_DEBUG
,
966 "%s - Closed handle: %lx S: %lx\n",
967 __FUNCTION__
, Handle
, Status
);
972 * @name ObpSetHandleAttributes
974 * The ObpSetHandleAttributes routine <FILLMEIN>
979 * @param HandleTableEntry
985 * @return <FILLMEIN>.
992 ObpSetHandleAttributes(IN PHANDLE_TABLE HandleTable
,
993 IN OUT PHANDLE_TABLE_ENTRY HandleTableEntry
,
996 POBP_SET_HANDLE_ATTRIBUTES_CONTEXT SetHandleInfo
=
997 (POBP_SET_HANDLE_ATTRIBUTES_CONTEXT
)Context
;
998 POBJECT_HEADER ObjectHeader
= EX_HTE_TO_HDR(HandleTableEntry
);
1001 /* Don't allow operations on kernel objects */
1002 if ((ObjectHeader
->Flags
& OB_FLAG_KERNEL_MODE
) &&
1003 (SetHandleInfo
->PreviousMode
!= KernelMode
))
1009 /* Check if making the handle inheritable */
1010 if (SetHandleInfo
->Information
.Inherit
)
1012 /* Check if inheriting is not supported for this object */
1013 if (ObjectHeader
->Type
->TypeInfo
.InvalidAttributes
& OBJ_INHERIT
)
1015 /* Fail without changing anything */
1020 HandleTableEntry
->ObAttributes
|= EX_HANDLE_ENTRY_INHERITABLE
;
1024 /* Otherwise this implies we're removing the flag */
1025 HandleTableEntry
->ObAttributes
&= ~EX_HANDLE_ENTRY_INHERITABLE
;
1028 /* Check if making the handle protected */
1029 if (SetHandleInfo
->Information
.ProtectFromClose
)
1032 HandleTableEntry
->ObAttributes
|= EX_HANDLE_ENTRY_PROTECTFROMCLOSE
;
1036 /* Otherwise, remove it */
1037 HandleTableEntry
->ObAttributes
&= ~EX_HANDLE_ENTRY_PROTECTFROMCLOSE
;
1040 /* Return success */
1045 * @name ObpCloseHandleCallback
1047 * The ObpCloseHandleCallback routine <FILLMEIN>
1049 * @param HandleTable
1055 * @param GrantedAccess
1061 * @return <FILLMEIN>.
1068 ObpCloseHandleCallback(IN PHANDLE_TABLE_ENTRY HandleTableEntry
,
1072 POBP_CLOSE_HANDLE_CONTEXT CloseContext
= (POBP_CLOSE_HANDLE_CONTEXT
)Context
;
1074 /* Simply decrement the handle count */
1075 ObpCloseHandleTableEntry(CloseContext
->HandleTable
,
1078 CloseContext
->AccessMode
,
1083 * @name ObpDuplicateHandleCallback
1085 * The ObpDuplicateHandleCallback routine <FILLMEIN>
1087 * @param HandleTable
1090 * @param HandleTableEntry
1096 * @return <FILLMEIN>.
1103 ObpDuplicateHandleCallback(IN PHANDLE_TABLE HandleTable
,
1104 IN PHANDLE_TABLE_ENTRY HandleTableEntry
,
1107 POBJECT_HEADER ObjectHeader
;
1108 BOOLEAN Ret
= FALSE
;
1109 ACCESS_STATE AccessState
;
1113 /* Make sure that the handle is inheritable */
1114 Ret
= (HandleTableEntry
->ObAttributes
& EX_HANDLE_ENTRY_INHERITABLE
) != 0;
1117 /* Get the object header */
1118 ObjectHeader
= EX_HTE_TO_HDR(HandleTableEntry
);
1120 /* Setup the access state */
1121 AccessState
.PreviouslyGrantedAccess
= HandleTableEntry
->GrantedAccess
;
1123 /* Call the shared routine for incrementing handles */
1124 Status
= ObpIncrementHandleCount(&ObjectHeader
->Body
,
1127 HandleTableEntry
->ObAttributes
,
1128 PsGetCurrentProcess(),
1130 if (!NT_SUCCESS(Status
))
1132 /* Return failure */
1137 /* Otherwise increment the pointer count */
1138 InterlockedIncrement(&ObjectHeader
->PointerCount
);
1142 /* Return duplication result */
1148 ObClearProcessHandleTable(IN PEPROCESS Process
)
1154 * @name ObpCreateHandleTable
1156 * The ObpCreateHandleTable routine <FILLMEIN>
1164 * @return <FILLMEIN>.
1171 ObpCreateHandleTable(IN PEPROCESS Parent
,
1172 IN PEPROCESS Process
)
1174 PHANDLE_TABLE HandleTable
;
1177 /* Check if we have a parent */
1180 /* Duplicate the parent's */
1181 HandleTable
= ExDupHandleTable(Process
,
1182 ObpDuplicateHandleCallback
,
1184 Parent
->ObjectTable
);
1188 /* Create a new one */
1189 HandleTable
= ExCreateHandleTable(Process
);
1192 /* Now write it and make sure we got one */
1193 Process
->ObjectTable
= HandleTable
;
1194 if (!HandleTable
) return STATUS_INSUFFICIENT_RESOURCES
;
1196 /* If we got here then the table was created OK */
1197 return STATUS_SUCCESS
;
1201 * @name ObKillProcess
1203 * The ObKillProcess routine <FILLMEIN>
1215 ObKillProcess(IN PEPROCESS Process
)
1217 PHANDLE_TABLE HandleTable
= Process
->ObjectTable
;
1218 OBP_CLOSE_HANDLE_CONTEXT Context
;
1221 /* Enter a critical region */
1222 KeEnterCriticalRegion();
1224 /* Fill out the context */
1225 Context
.AccessMode
= KernelMode
;
1226 Context
.HandleTable
= HandleTable
;
1228 /* Sweep the handle table to close all handles */
1229 ExSweepHandleTable(HandleTable
,
1230 ObpCloseHandleCallback
,
1233 /* Destroy the table and leave the critical region */
1234 ExDestroyHandleTable(HandleTable
);
1235 KeLeaveCriticalRegion();
1237 /* Clear the object table */
1238 Process
->ObjectTable
= NULL
;
1243 ObDuplicateObject(IN PEPROCESS SourceProcess
,
1244 IN HANDLE SourceHandle
,
1245 IN PEPROCESS TargetProcess OPTIONAL
,
1246 IN PHANDLE TargetHandle OPTIONAL
,
1247 IN ACCESS_MASK DesiredAccess
,
1248 IN ULONG HandleAttributes
,
1250 IN KPROCESSOR_MODE PreviousMode
)
1252 HANDLE_TABLE_ENTRY NewHandleEntry
;
1253 BOOLEAN AttachedToProcess
= FALSE
;
1255 POBJECT_HEADER ObjectHeader
;
1256 POBJECT_TYPE ObjectType
;
1258 KAPC_STATE ApcState
;
1259 NTSTATUS Status
= STATUS_SUCCESS
;
1260 ACCESS_MASK TargetAccess
, SourceAccess
;
1261 ACCESS_STATE AccessState
;
1262 PACCESS_STATE PassedAccessState
= NULL
;
1264 PHANDLE_TABLE HandleTable
= NULL
;
1265 OBJECT_HANDLE_INFORMATION HandleInformation
;
1267 OBTRACE(OB_HANDLE_DEBUG
,
1268 "%s - Duplicating handle: %lx for %p into %p\n",
1274 /* Check if we're not in the source process */
1275 if (SourceProcess
!= PsGetCurrentProcess())
1278 KeStackAttachProcess(&SourceProcess
->Pcb
, &ApcState
);
1279 AttachedToProcess
= TRUE
;
1282 /* Now reference the source handle */
1283 Status
= ObReferenceObjectByHandle(SourceHandle
,
1287 (PVOID
*)&SourceObject
,
1288 &HandleInformation
);
1290 /* Check if we were attached */
1291 if (AttachedToProcess
)
1293 /* We can safely detach now */
1294 KeUnstackDetachProcess(&ApcState
);
1295 AttachedToProcess
= FALSE
;
1298 /* Fail if we couldn't reference it */
1299 if (!NT_SUCCESS(Status
)) return Status
;
1301 /* Get the source access */
1302 SourceAccess
= HandleInformation
.GrantedAccess
;
1304 /* Check if we're not in the target process */
1305 if (TargetProcess
!= PsGetCurrentProcess())
1308 KeStackAttachProcess(&TargetProcess
->Pcb
, &ApcState
);
1309 AttachedToProcess
= TRUE
;
1312 /* Check if we're duplicating the attributes */
1313 if (Options
& DUPLICATE_SAME_ATTRIBUTES
)
1315 /* Duplicate them */
1316 HandleAttributes
= HandleInformation
.HandleAttributes
;
1319 /* Check if we're duplicating the access */
1320 if (Options
& DUPLICATE_SAME_ACCESS
) DesiredAccess
= SourceAccess
;
1322 /* Get object data */
1323 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(SourceObject
);
1324 ObjectType
= ObjectHeader
->Type
;
1326 /* Fill out the entry */
1327 NewHandleEntry
.Object
= ObjectHeader
;
1328 NewHandleEntry
.ObAttributes
|= HandleAttributes
&
1329 (EX_HANDLE_ENTRY_PROTECTFROMCLOSE
|
1330 EX_HANDLE_ENTRY_INHERITABLE
|
1331 EX_HANDLE_ENTRY_AUDITONCLOSE
);
1333 /* Check if we're using a generic mask */
1334 if (DesiredAccess
& GENERIC_ACCESS
)
1337 RtlMapGenericMask(&DesiredAccess
, &ObjectType
->TypeInfo
.GenericMapping
);
1340 /* Set the target access */
1341 TargetAccess
= DesiredAccess
;
1342 NewHandleEntry
.GrantedAccess
= TargetAccess
;
1344 /* Check if we're asking for new access */
1345 if (TargetAccess
& ~SourceAccess
)
1347 /* We are. We need the security procedure to validate this */
1348 if (ObjectType
->TypeInfo
.SecurityProcedure
== SeDefaultObjectMethod
)
1350 /* Use our built-in access state */
1351 PassedAccessState
= &AccessState
;
1352 Status
= SeCreateAccessState(&AccessState
,
1355 &ObjectType
->TypeInfo
.GenericMapping
);
1359 /* Otherwise we can't allow this privilege elevation */
1360 Status
= STATUS_ACCESS_DENIED
;
1365 /* We don't need an access state */
1366 Status
= STATUS_SUCCESS
;
1369 /* Make sure the access state was created OK */
1370 if (NT_SUCCESS(Status
))
1372 /* Add a new handle */
1373 Status
= ObpIncrementHandleCount(SourceObject
,
1377 PsGetCurrentProcess(),
1380 /* Set the handle table, now that we know this handle was added */
1381 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
1384 /* Check if we were attached */
1385 if (AttachedToProcess
)
1387 /* We can safely detach now */
1388 KeUnstackDetachProcess(&ApcState
);
1389 AttachedToProcess
= FALSE
;
1392 /* Check if we have to close the source handle */
1393 if (Options
& DUPLICATE_CLOSE_SOURCE
)
1395 /* Attach and close */
1396 KeStackAttachProcess(&SourceProcess
->Pcb
, &ApcState
);
1397 NtClose(SourceHandle
);
1398 KeUnstackDetachProcess(&ApcState
);
1401 /* Check if we had an access state */
1402 if (PassedAccessState
) SeDeleteAccessState(PassedAccessState
);
1404 /* Now check if incrementing actually failed */
1405 if (!NT_SUCCESS(Status
))
1407 /* Dereference the source object */
1408 ObDereferenceObject(SourceObject
);
1412 /* Now create the handle */
1413 NewHandle
= ExCreateHandle(HandleTable
, &NewHandleEntry
);
1416 /* Undo the increment */
1417 ObpDecrementHandleCount(SourceObject
,
1421 /* Deference the object and set failure status */
1422 ObDereferenceObject(SourceObject
);
1423 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1426 /* Return the handle */
1427 if (TargetHandle
) *TargetHandle
= NewHandle
;
1430 OBTRACE(OB_HANDLE_DEBUG
,
1431 "%s - Duplicated handle: %lx for %p into %p. Source: %p HC PC %lx %lx\n",
1437 ObjectHeader
->PointerCount
,
1438 ObjectHeader
->HandleCount
);
1442 /* PUBLIC FUNCTIONS *********************************************************/
1445 * @name ObOpenObjectByName
1448 * The ObOpenObjectByName routine <FILLMEIN>
1450 * @param ObjectAttributes
1459 * @param PassedAccessState
1462 * @param DesiredAccess
1465 * @param ParseContext
1471 * @return <FILLMEIN>.
1478 ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes
,
1479 IN POBJECT_TYPE ObjectType
,
1480 IN KPROCESSOR_MODE AccessMode
,
1481 IN PACCESS_STATE PassedAccessState
,
1482 IN ACCESS_MASK DesiredAccess
,
1483 IN OUT PVOID ParseContext
,
1486 PVOID Object
= NULL
;
1487 UNICODE_STRING ObjectName
;
1488 OBJECT_CREATE_INFORMATION ObjectCreateInfo
;
1490 OBP_LOOKUP_CONTEXT Context
;
1491 POBJECT_HEADER ObjectHeader
;
1493 PGENERIC_MAPPING GenericMapping
= NULL
;
1494 ACCESS_STATE AccessState
;
1495 OB_OPEN_REASON OpenReason
;
1498 /* Check if we didn't get any Object Attributes */
1499 if (!ObjectAttributes
)
1501 /* Fail with special status code */
1503 return STATUS_INVALID_PARAMETER
;
1506 /* Capture all the info */
1507 Status
= ObpCaptureObjectAttributes(ObjectAttributes
,
1512 if (!NT_SUCCESS(Status
)) return Status
;
1514 /* Check if we didn't get an access state */
1515 if (!PassedAccessState
)
1517 /* Try to get the generic mapping if we can */
1518 if (ObjectType
) GenericMapping
= &ObjectType
->TypeInfo
.GenericMapping
;
1520 /* Use our built-in access state */
1521 PassedAccessState
= &AccessState
;
1522 Status
= SeCreateAccessState(&AccessState
,
1526 if (!NT_SUCCESS(Status
)) goto Quickie
;
1529 /* Get the security descriptor */
1530 if (ObjectCreateInfo
.SecurityDescriptor
)
1532 /* Save it in the access state */
1533 PassedAccessState
->SecurityDescriptor
=
1534 ObjectCreateInfo
.SecurityDescriptor
;
1537 /* Now do the lookup */
1538 Status
= ObFindObject(ObjectCreateInfo
.RootDirectory
,
1540 ObjectCreateInfo
.Attributes
,
1546 ObjectCreateInfo
.SecurityQos
,
1549 if (!NT_SUCCESS(Status
)) goto Cleanup
;
1551 /* Check if this object has create information */
1552 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
1553 if (ObjectHeader
->Flags
& OB_FLAG_CREATE_INFO
)
1555 /* Then we are creating a new handle */
1556 OpenReason
= ObCreateHandle
;
1558 /* Check if we still have create info */
1559 if (ObjectHeader
->ObjectCreateInfo
)
1562 ObpFreeAndReleaseCapturedAttributes(ObjectHeader
->
1564 ObjectHeader
->ObjectCreateInfo
= NULL
;
1569 /* Otherwise, we are merely opening it */
1570 OpenReason
= ObOpenHandle
;
1573 /* Create the actual handle now */
1574 Status
= ObpCreateHandle(OpenReason
,
1579 ObjectCreateInfo
.Attributes
,
1583 if (!NT_SUCCESS(Status
)) ObDereferenceObject(Object
);
1586 /* Delete the access state */
1587 if (PassedAccessState
== &AccessState
)
1589 SeDeleteAccessState(PassedAccessState
);
1592 /* Release the object attributes and return status */
1594 ObpReleaseCapturedAttributes(&ObjectCreateInfo
);
1595 if (ObjectName
.Buffer
) ObpReleaseCapturedName(&ObjectName
);
1596 OBTRACE(OB_HANDLE_DEBUG
,
1597 "%s - returning Object %p with PC S: %lx %lx\n",
1600 Object
? OBJECT_TO_OBJECT_HEADER(Object
)->PointerCount
: -1,
1606 * @name ObOpenObjectByPointer
1609 * The ObOpenObjectByPointer routine <FILLMEIN>
1614 * @param HandleAttributes
1617 * @param PassedAccessState
1620 * @param DesiredAccess
1632 * @return <FILLMEIN>.
1639 ObOpenObjectByPointer(IN PVOID Object
,
1640 IN ULONG HandleAttributes
,
1641 IN PACCESS_STATE PassedAccessState
,
1642 IN ACCESS_MASK DesiredAccess
,
1643 IN POBJECT_TYPE ObjectType
,
1644 IN KPROCESSOR_MODE AccessMode
,
1647 POBJECT_HEADER Header
;
1649 ACCESS_STATE AccessState
;
1653 /* Get the Header Info */
1654 Header
= OBJECT_TO_OBJECT_HEADER(Object
);
1656 /* Reference the object */
1657 Status
= ObReferenceObjectByPointer(Object
,
1661 if (!NT_SUCCESS(Status
)) return Status
;
1663 /* Check if we didn't get an access state */
1664 if (!PassedAccessState
)
1666 /* Use our built-in access state */
1667 PassedAccessState
= &AccessState
;
1668 Status
= SeCreateAccessState(&AccessState
,
1671 &Header
->Type
->TypeInfo
.GenericMapping
);
1672 if (!NT_SUCCESS(Status
))
1675 ObDereferenceObject(Object
);
1680 /* Create the handle */
1681 Status
= ObpCreateHandle(ObOpenHandle
,
1690 if (!NT_SUCCESS(Status
)) ObDereferenceObject(Object
);
1692 /* Delete the access state */
1693 if (PassedAccessState
== &AccessState
)
1695 SeDeleteAccessState(PassedAccessState
);
1699 OBTRACE(OB_HANDLE_DEBUG
,
1700 "%s - returning Object with PC S: %lx %lx\n",
1702 OBJECT_TO_OBJECT_HEADER(Object
)->PointerCount
,
1708 ObFindHandleForObject(IN PEPROCESS Process
,
1710 IN POBJECT_TYPE ObjectType
,
1711 IN POBJECT_HANDLE_INFORMATION HandleInformation
,
1712 OUT PHANDLE HandleReturn
)
1714 DPRINT("ObFindHandleForObject is unimplemented!\n");
1715 return STATUS_UNSUCCESSFUL
;
1719 * @name ObInsertObject
1722 * The ObInsertObject routine <FILLMEIN>
1727 * @param PassedAccessState
1730 * @param DesiredAccess
1733 * @param AdditionalReferences
1736 * @param ReferencedObject
1742 * @return <FILLMEIN>.
1749 ObInsertObject(IN PVOID Object
,
1750 IN PACCESS_STATE PassedAccessState OPTIONAL
,
1751 IN ACCESS_MASK DesiredAccess
,
1752 IN ULONG AdditionalReferences
,
1753 OUT PVOID
*ReferencedObject OPTIONAL
,
1756 POBJECT_CREATE_INFORMATION ObjectCreateInfo
;
1757 POBJECT_HEADER Header
;
1758 POBJECT_TYPE ObjectType
;
1759 PVOID FoundObject
= Object
;
1760 POBJECT_HEADER FoundHeader
= NULL
;
1761 NTSTATUS Status
= STATUS_SUCCESS
, RealStatus
;
1762 PSECURITY_DESCRIPTOR DirectorySd
= NULL
;
1763 BOOLEAN SdAllocated
;
1764 OBP_LOOKUP_CONTEXT Context
;
1765 POBJECT_HEADER_NAME_INFO ObjectNameInfo
;
1766 ACCESS_STATE AccessState
;
1768 BOOLEAN IsNamed
= FALSE
;
1769 OB_OPEN_REASON OpenReason
= ObCreateHandle
;
1772 /* Get the Header and Create Info */
1773 Header
= OBJECT_TO_OBJECT_HEADER(Object
);
1774 ObjectCreateInfo
= Header
->ObjectCreateInfo
;
1775 ObjectNameInfo
= OBJECT_HEADER_TO_NAME_INFO(Header
);
1776 ObjectType
= Header
->Type
;
1778 /* Check if this is an named object */
1779 if ((ObjectNameInfo
) && (ObjectNameInfo
->Name
.Buffer
)) IsNamed
= TRUE
;
1781 /* Check if the object is unnamed and also doesn't have security */
1782 if ((!ObjectType
->TypeInfo
.SecurityRequired
) && !(IsNamed
))
1787 /* Assume failure */
1790 /* Create the handle */
1791 Status
= ObpCreateUnnamedHandle(Object
,
1793 AdditionalReferences
+ 1,
1794 ObjectCreateInfo
->Attributes
,
1795 ExGetPreviousMode(),
1800 /* Free the create information */
1801 ObpFreeAndReleaseCapturedAttributes(ObjectCreateInfo
);
1802 Header
->ObjectCreateInfo
= NULL
;
1804 /* Remove the extra keep-alive reference */
1805 if (Handle
) ObDereferenceObject(Object
);
1808 OBTRACE(OB_HANDLE_DEBUG
,
1809 "%s - returning Object with PC S: %lx %lx\n",
1811 OBJECT_TO_OBJECT_HEADER(Object
)->PointerCount
,
1816 /* Check if we didn't get an access state */
1817 if (!PassedAccessState
)
1819 /* Use our built-in access state */
1820 PassedAccessState
= &AccessState
;
1821 Status
= SeCreateAccessState(&AccessState
,
1824 &ObjectType
->TypeInfo
.GenericMapping
);
1825 if (!NT_SUCCESS(Status
))
1828 ObDereferenceObject(Object
);
1833 /* Save the security descriptor */
1834 PassedAccessState
->SecurityDescriptor
=
1835 ObjectCreateInfo
->SecurityDescriptor
;
1837 /* Check if the object is named */
1841 Status
= ObFindObject(ObjectCreateInfo
->RootDirectory
,
1842 &ObjectNameInfo
->Name
,
1843 ObjectCreateInfo
->Attributes
,
1844 (Header
->Flags
& OB_FLAG_KERNEL_MODE
) ?
1845 KernelMode
: UserMode
,
1850 ObjectCreateInfo
->SecurityQos
,
1851 ObjectCreateInfo
->ParseContext
,
1853 /* Check if we found an object that doesn't match the one requested */
1854 if ((NT_SUCCESS(Status
)) && (FoundObject
) && (Object
!= FoundObject
))
1856 /* This means we're opening an object, not creating a new one */
1857 FoundHeader
= OBJECT_TO_OBJECT_HEADER(FoundObject
);
1858 OpenReason
= ObOpenHandle
;
1860 /* Make sure the caller said it's OK to do this */
1861 if (ObjectCreateInfo
->Attributes
& OBJ_OPENIF
)
1863 /* He did, but did he want this type? */
1864 if (ObjectType
!= FoundHeader
->Type
)
1866 /* Wrong type, so fail */
1867 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
1871 /* Right type, so warn */
1872 Status
= STATUS_OBJECT_NAME_EXISTS
;
1877 /* Caller wanted to create a new object, fail */
1878 Status
= STATUS_OBJECT_NAME_COLLISION
;
1882 /* Check if anything until now failed */
1883 if (!NT_SUCCESS(Status
))
1885 /* We failed, dereference the object and delete the access state */
1886 ObDereferenceObject(Object
);
1887 if (PassedAccessState
== &AccessState
)
1889 /* We used a local one; delete it */
1890 SeDeleteAccessState(PassedAccessState
);
1893 /* Return failure code */
1898 /* Now check if this object is being created */
1899 if (FoundObject
== Object
)
1901 /* Check if it's named or forces security */
1902 if ((IsNamed
) || (ObjectType
->TypeInfo
.SecurityRequired
))
1904 /* Make sure it's inserted into an object directory */
1905 if ((ObjectNameInfo
) && (ObjectNameInfo
->Directory
))
1907 /* Get the current descriptor */
1908 ObGetObjectSecurity(ObjectNameInfo
->Directory
,
1914 Status
= ObAssignSecurity(PassedAccessState
,
1919 /* Check if we captured one */
1922 /* We did, release it */
1923 ObReleaseObjectSecurity(DirectorySd
, SdAllocated
);
1925 else if (NT_SUCCESS(Status
))
1927 /* Other we didn't, but we were able to use the current SD */
1928 SeReleaseSecurityDescriptor(ObjectCreateInfo
->SecurityDescriptor
,
1929 ObjectCreateInfo
->ProbeMode
,
1932 /* Clear the current one */
1933 PassedAccessState
->SecurityDescriptor
=
1934 ObjectCreateInfo
->SecurityDescriptor
= NULL
;
1938 /* Check if anything until now failed */
1939 if (!NT_SUCCESS(Status
))
1941 /* We failed, dereference the object and delete the access state */
1943 ObDereferenceObject(Object
);
1944 if (PassedAccessState
== &AccessState
)
1946 /* We used a local one; delete it */
1947 SeDeleteAccessState(PassedAccessState
);
1950 /* Return failure code */
1955 /* Save the actual status until here */
1956 RealStatus
= Status
;
1958 /* HACKHACK: Because of ROS's incorrect startup, this can be called
1959 * without a valid Process until I finalize the startup patch,
1960 * so don't create a handle if this is the case. We also don't create
1961 * a handle if Handle is NULL when the Registry Code calls it, because
1962 * the registry code totally bastardizes the Ob and needs to be fixed
1966 /* Create the handle */
1967 Status
= ObpCreateHandle(OpenReason
,
1971 AdditionalReferences
+ 1,
1972 ObjectCreateInfo
->Attributes
,
1973 ExGetPreviousMode(),
1978 /* We can delete the Create Info now */
1979 Header
->ObjectCreateInfo
= NULL
;
1980 ObpFreeAndReleaseCapturedAttributes(ObjectCreateInfo
);
1982 /* Check if creating the handle failed */
1983 if (!NT_SUCCESS(Status
))
1985 /* If the object had a name, backout everything */
1986 if (IsNamed
) ObpDeleteNameCheck(Object
);
1989 /* Remove the extra keep-alive reference */
1990 if (Handle
) ObDereferenceObject(Object
);
1992 /* Check our final status */
1993 if (!NT_SUCCESS(Status
))
1995 /* Return the status of the failure */
1997 RealStatus
= Status
;
2000 /* Check if we created our own access state */
2001 if (PassedAccessState
== &AccessState
)
2003 /* We used a local one; delete it */
2004 SeDeleteAccessState(PassedAccessState
);
2007 /* Return status code */
2008 OBTRACE(OB_HANDLE_DEBUG
,
2009 "%s - returning Object with PC S/RS: %lx %lx %lx\n",
2011 OBJECT_TO_OBJECT_HEADER(Object
)->PointerCount
,
2012 RealStatus
, Status
);
2017 * @name ObCloseHandle
2018 * @implemented NT5.1
2020 * The ObCloseHandle routine <FILLMEIN>
2028 * @return <FILLMEIN>.
2035 ObCloseHandle(IN HANDLE Handle
,
2036 IN KPROCESSOR_MODE AccessMode
)
2038 /* Call the internal API */
2039 return ObpCloseHandle(Handle
, AccessMode
);
2046 * The NtClose routine <FILLMEIN>
2051 * @return <FILLMEIN>.
2058 NtClose(IN HANDLE Handle
)
2061 // Call the internal API
2063 return ObpCloseHandle(Handle
, ExGetPreviousMode());
2068 NtDuplicateObject(IN HANDLE SourceProcessHandle
,
2069 IN HANDLE SourceHandle
,
2070 IN HANDLE TargetProcessHandle OPTIONAL
,
2071 OUT PHANDLE TargetHandle OPTIONAL
,
2072 IN ACCESS_MASK DesiredAccess
,
2073 IN ULONG HandleAttributes
,
2076 PEPROCESS SourceProcess
, TargetProcess
, Target
;
2078 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2079 NTSTATUS Status
= STATUS_SUCCESS
;
2081 OBTRACE(OB_HANDLE_DEBUG
,
2082 "%s - Duplicating handle: %lx for %lx into %lx.\n",
2085 SourceProcessHandle
,
2086 TargetProcessHandle
);
2088 if((TargetHandle
) && (PreviousMode
!= KernelMode
))
2093 /* Probe the handle */
2094 ProbeForWriteHandle(TargetHandle
);
2098 /* Get the exception status */
2099 Status
= _SEH_GetExceptionCode();
2103 /* Fail if the pointer was invalid */
2104 if (!NT_SUCCESS(Status
)) return Status
;
2107 /* Now reference the input handle */
2108 Status
= ObReferenceObjectByHandle(SourceProcessHandle
,
2112 (PVOID
*)&SourceProcess
,
2114 if (!NT_SUCCESS(Status
)) return(Status
);
2116 /* Check if got a target handle */
2117 if (TargetProcessHandle
)
2119 /* Now reference the output handle */
2120 Status
= ObReferenceObjectByHandle(TargetProcessHandle
,
2124 (PVOID
*)&TargetProcess
,
2126 if (NT_SUCCESS(Status
))
2128 /* Use this target process */
2129 Target
= TargetProcess
;
2133 /* No target process */
2139 /* No target process */
2140 Status
= STATUS_SUCCESS
;
2144 /* Call the internal routine */
2145 Status
= ObDuplicateObject(SourceProcess
,
2154 /* Check if the caller wanted the return handle */
2157 /* Protect the write to user mode */
2160 /* Write the new handle */
2161 *TargetHandle
= hTarget
;
2165 /* Otherwise, get the exception code */
2166 Status
= _SEH_GetExceptionCode();
2171 /* Dereference the processes */
2172 OBTRACE(OB_HANDLE_DEBUG
,
2173 "%s - Duplicated handle: %lx into %lx S %lx\n",
2176 TargetProcessHandle
,
2178 ObDereferenceObject(Target
);
2179 ObDereferenceObject(SourceProcess
);
2183 #undef ObIsKernelHandle
2186 ObIsKernelHandle(IN HANDLE Handle
)
2188 /* We know we're kernel mode, so just check for the kernel handle flag */
2189 return (BOOLEAN
)((ULONG_PTR
)Handle
& KERNEL_HANDLE_FLAG
);