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 #define TAG_OB_HANDLE TAG('O', 'b', 'H', 'd')
24 /* PRIVATE FUNCTIONS *********************************************************/
28 ObReferenceProcessHandleTable(IN PEPROCESS Process
)
30 PHANDLE_TABLE HandleTable
= NULL
;
32 /* Lock the process */
33 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
35 /* Get the handle table */
36 HandleTable
= Process
->ObjectTable
;
39 /* No table, release the lock */
40 ExReleaseRundownProtection(&Process
->RundownProtect
);
44 /* Return the handle table */
50 ObDereferenceProcessHandleTable(IN PEPROCESS Process
)
52 /* Release the process lock */
53 ExReleaseRundownProtection(&Process
->RundownProtect
);
58 ObpReferenceProcessObjectByHandle(IN HANDLE Handle
,
60 IN PHANDLE_TABLE HandleTable
,
61 IN KPROCESSOR_MODE AccessMode
,
63 OUT POBJECT_HANDLE_INFORMATION HandleInformation
)
65 PHANDLE_TABLE_ENTRY HandleEntry
;
66 POBJECT_HEADER ObjectHeader
;
67 ACCESS_MASK GrantedAccess
;
69 PEPROCESS CurrentProcess
;
70 PETHREAD CurrentThread
;
77 /* Check if the caller wants the current process */
78 if (Handle
== NtCurrentProcess())
80 /* Get the current process */
81 CurrentProcess
= PsGetCurrentProcess();
83 /* Check if the caller wanted handle information */
84 if (HandleInformation
)
87 HandleInformation
->HandleAttributes
= 0;
88 HandleInformation
->GrantedAccess
= Process
->GrantedAccess
;
91 /* Reference ourselves */
92 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(CurrentProcess
);
93 InterlockedExchangeAdd(&ObjectHeader
->PointerCount
, 1);
95 /* Return the pointer */
96 *Object
= CurrentProcess
;
97 return STATUS_SUCCESS
;
100 /* Check if the caller wants the current thread */
101 if (Handle
== NtCurrentThread())
103 /* Get the current thread */
104 CurrentThread
= PsGetCurrentThread();
106 /* Check if the caller wanted handle information */
107 if (HandleInformation
)
110 HandleInformation
->HandleAttributes
= 0;
111 HandleInformation
->GrantedAccess
= CurrentThread
->GrantedAccess
;
114 /* Reference ourselves */
115 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(CurrentThread
);
116 InterlockedExchangeAdd(&ObjectHeader
->PointerCount
, 1);
118 /* Return the pointer */
119 *Object
= CurrentThread
;
120 return STATUS_SUCCESS
;
123 /* Check if this is a kernel handle */
124 if (ObIsKernelHandle(Handle
, AccessMode
))
126 /* Use the kernel handle table and get the actual handle value */
127 Handle
= ObKernelHandleToHandle(Handle
);
128 HandleTable
= ObpKernelHandleTable
;
132 /* Otherwise use this process's handle table */
133 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
136 /* Enter a critical region while we touch the handle table */
137 ASSERT(HandleTable
!= NULL
);
138 KeEnterCriticalRegion();
140 /* Get the handle entry */
141 HandleEntry
= ExMapHandleToPointer(HandleTable
, Handle
);
144 /* Get the object header and validate the type*/
145 ObjectHeader
= EX_HTE_TO_HDR(HandleEntry
);
147 /* Get the granted access and validate it */
148 GrantedAccess
= HandleEntry
->GrantedAccess
;
150 /* Mask out the internal attributes */
151 Attributes
= HandleEntry
->ObAttributes
&
152 (EX_HANDLE_ENTRY_PROTECTFROMCLOSE
|
153 EX_HANDLE_ENTRY_INHERITABLE
|
154 EX_HANDLE_ENTRY_AUDITONCLOSE
);
156 /* Fill out the information */
157 HandleInformation
->HandleAttributes
= Attributes
;
158 HandleInformation
->GrantedAccess
= GrantedAccess
;
160 /* Return the pointer */
161 *Object
= &ObjectHeader
->Body
;
163 /* Add a reference */
164 InterlockedExchangeAdd(&ObjectHeader
->PointerCount
, 1);
166 /* Unlock the handle */
167 ExUnlockHandleTableEntry(HandleTable
, HandleEntry
);
168 KeLeaveCriticalRegion();
171 ASSERT(*Object
!= NULL
);
172 return STATUS_SUCCESS
;
177 Status
= STATUS_INVALID_HANDLE
;
180 /* Return failure status */
181 KeLeaveCriticalRegion();
187 ObpEnumFindHandleProcedure(IN PHANDLE_TABLE_ENTRY HandleEntry
,
192 DPRINT1("Not yet implemented!\n");
197 POBJECT_HANDLE_COUNT_ENTRY
199 ObpInsertHandleCount(IN POBJECT_HEADER ObjectHeader
)
201 POBJECT_HEADER_HANDLE_INFO HandleInfo
;
202 POBJECT_HANDLE_COUNT_ENTRY FreeEntry
;
203 POBJECT_HANDLE_COUNT_DATABASE HandleDatabase
, OldHandleDatabase
;
206 OBJECT_HANDLE_COUNT_DATABASE SingleDatabase
;
209 /* Get the handle info */
210 HandleInfo
= OBJECT_HEADER_TO_HANDLE_INFO(ObjectHeader
);
211 if (!HandleInfo
) return NULL
;
213 /* Check if we only have one entry */
214 if (ObjectHeader
->Flags
& OB_FLAG_SINGLE_PROCESS
)
216 /* Fill out the single entry */
217 SingleDatabase
.CountEntries
= 1;
218 SingleDatabase
.HandleCountEntries
[0] = HandleInfo
->SingleEntry
;
220 /* Use this as the old size */
221 OldHandleDatabase
= &SingleDatabase
;
222 OldSize
= sizeof(SingleDatabase
);
224 /* Now we'll have two entries, and an entire DB */
226 Size
= sizeof(OBJECT_HANDLE_COUNT_DATABASE
) +
227 sizeof(OBJECT_HANDLE_COUNT_ENTRY
);
231 /* We already have a DB, get the information from it */
232 OldHandleDatabase
= HandleInfo
->HandleCountDatabase
;
233 i
= OldHandleDatabase
->CountEntries
;
234 OldSize
= sizeof(OBJECT_HANDLE_COUNT_DATABASE
) +
235 ((i
- 1) * sizeof(OBJECT_HANDLE_COUNT_ENTRY
));
237 /* Add 4 more entries */
239 Size
= OldSize
+= (4 * sizeof(OBJECT_HANDLE_COUNT_ENTRY
));
242 /* Allocate the DB */
243 HandleDatabase
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_OB_HANDLE
);
244 if (!HandleDatabase
) return NULL
;
246 /* Copy the old database */
247 RtlMoveMemory(HandleDatabase
, OldHandleDatabase
, OldSize
);
249 /* Check if we he had a single entry before */
250 if (ObjectHeader
->Flags
& OB_FLAG_SINGLE_PROCESS
)
252 /* Now we have more */
253 ObjectHeader
->Flags
&= ~OB_FLAG_SINGLE_PROCESS
;
257 /* Otherwise we had a DB, free it */
258 ExFreePool(OldHandleDatabase
);
261 /* Find the end of the copy and zero out the new data */
262 FreeEntry
= (PVOID
)((ULONG_PTR
)HandleDatabase
+ OldSize
);
263 RtlZeroMemory(FreeEntry
, Size
- OldSize
);
265 /* Set the new information and return the free entry */
266 HandleDatabase
->CountEntries
= i
;
267 HandleInfo
->HandleCountDatabase
= HandleDatabase
;
273 ObpIncrementHandleDataBase(IN POBJECT_HEADER ObjectHeader
,
274 IN PEPROCESS Process
,
275 IN OUT PULONG NewProcessHandleCount
)
277 POBJECT_HEADER_HANDLE_INFO HandleInfo
;
278 POBJECT_HANDLE_COUNT_ENTRY HandleEntry
, FreeEntry
= NULL
;
279 POBJECT_HANDLE_COUNT_DATABASE HandleDatabase
;
283 /* Get the handle info and check if we only have one entry */
284 HandleInfo
= OBJECT_HEADER_TO_HANDLE_INFO(ObjectHeader
);
285 if (ObjectHeader
->Flags
& OB_FLAG_SINGLE_PROCESS
)
287 /* Check if the entry is free */
288 if (!HandleInfo
->SingleEntry
.HandleCount
)
291 HandleInfo
->SingleEntry
.HandleCount
= 1;
292 HandleInfo
->SingleEntry
.Process
= Process
;
294 /* Return success and 1 handle */
295 *NewProcessHandleCount
= 1;
296 return STATUS_SUCCESS
;
298 else if (HandleInfo
->SingleEntry
.Process
== Process
)
300 /* Busy entry, but same process */
301 *NewProcessHandleCount
= ++HandleInfo
->SingleEntry
.HandleCount
;
302 return STATUS_SUCCESS
;
306 /* Insert a new entry */
307 FreeEntry
= ObpInsertHandleCount(ObjectHeader
);
308 if (!FreeEntry
) return STATUS_INSUFFICIENT_RESOURCES
;
311 FreeEntry
->Process
= Process
;
312 FreeEntry
->HandleCount
= 1;
314 /* Return success and 1 handle */
315 *NewProcessHandleCount
= 1;
316 return STATUS_SUCCESS
;
320 /* We have a database instead */
321 HandleDatabase
= HandleInfo
->HandleCountDatabase
;
324 /* Get the entries and loop them */
325 i
= HandleDatabase
->CountEntries
;
326 HandleEntry
= &HandleDatabase
->HandleCountEntries
[0];
329 /* Check if this is a match */
330 if (HandleEntry
->Process
== Process
)
332 /* Found it, get the process handle count */
333 *NewProcessHandleCount
= ++HandleEntry
->HandleCount
;
334 return STATUS_SUCCESS
;
336 else if (!HandleEntry
->HandleCount
)
338 /* Found a free entry */
339 FreeEntry
= HandleEntry
;
347 /* Check if we couldn't find a free entry */
351 FreeEntry
= ObpInsertHandleCount(ObjectHeader
);
352 if (!FreeEntry
) return STATUS_INSUFFICIENT_RESOURCES
;
355 /* Fill out the entry */
356 FreeEntry
->Process
= Process
;
357 FreeEntry
->HandleCount
= 1;
358 *NewProcessHandleCount
= 1;
361 /* Return success if we got here */
362 return STATUS_SUCCESS
;
367 ObpChargeQuotaForObject(IN POBJECT_HEADER ObjectHeader
,
368 IN POBJECT_TYPE ObjectType
,
369 OUT PBOOLEAN NewObject
)
371 POBJECT_HEADER_QUOTA_INFO ObjectQuota
;
372 ULONG PagedPoolCharge
, NonPagedPoolCharge
;
375 /* Get quota information */
376 ObjectQuota
= OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader
);
379 /* Check if this is a new object */
380 if (ObjectHeader
->Flags
& OB_FLAG_CREATE_INFO
)
385 /* Remove the flag */
386 ObjectHeader
->Flags
&= ~ OB_FLAG_CREATE_INFO
;
389 /* We have a quota, get the charges */
390 PagedPoolCharge
= ObjectQuota
->PagedPoolCharge
;
391 NonPagedPoolCharge
= ObjectQuota
->NonPagedPoolCharge
;
395 /* Get it from the object type */
396 PagedPoolCharge
= ObjectType
->TypeInfo
.DefaultPagedPoolCharge
;
397 NonPagedPoolCharge
= ObjectType
->TypeInfo
.DefaultNonPagedPoolCharge
;
402 * FIXME: This is a *COMPLETE* guess and probably defintely not the way to do this.
404 Process
= PsGetCurrentProcess();
405 Process
->QuotaBlock
->QuotaEntry
[PagedPool
].Usage
+= PagedPoolCharge
;
406 Process
->QuotaBlock
->QuotaEntry
[NonPagedPool
].Usage
+= NonPagedPoolCharge
;
407 ObjectHeader
->QuotaBlockCharged
= Process
->QuotaBlock
;
411 return STATUS_SUCCESS
;
415 * @name ObpDecrementHandleCount
417 * The ObpDecrementHandleCount routine <FILLMEIN>
425 * @param GrantedAccess
435 ObpDecrementHandleCount(IN PVOID ObjectBody
,
436 IN PEPROCESS Process
,
437 IN ACCESS_MASK GrantedAccess
)
439 POBJECT_HEADER ObjectHeader
;
440 POBJECT_TYPE ObjectType
;
441 LONG SystemHandleCount
, ProcessHandleCount
;
443 POBJECT_HEADER_CREATOR_INFO CreatorInfo
;
445 POBJECT_HEADER_HANDLE_INFO HandleInfo
;
446 POBJECT_HANDLE_COUNT_ENTRY HandleEntry
;
447 POBJECT_HANDLE_COUNT_DATABASE HandleDatabase
;
450 /* Get the object type and header */
451 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(ObjectBody
);
452 ObjectType
= ObjectHeader
->Type
;
453 OBTRACE(OB_HANDLE_DEBUG
,
454 "%s - Decrementing count for: %p. HC LC %lx %lx\n",
457 ObjectHeader
->HandleCount
,
458 ObjectHeader
->PointerCount
);
460 /* Lock the object type */
461 ObpEnterObjectTypeMutex(ObjectType
);
463 /* Set default counts */
464 SystemHandleCount
= ObjectHeader
->HandleCount
;
465 ProcessHandleCount
= 0;
467 /* Decrement the handle count */
468 NewCount
= InterlockedDecrement(&ObjectHeader
->HandleCount
);
470 /* Check if we're out of handles */
473 /* Get the creator info */
474 CreatorInfo
= OBJECT_HEADER_TO_CREATOR_INFO(ObjectHeader
);
475 if ((CreatorInfo
) && !(IsListEmpty(&CreatorInfo
->TypeList
)))
477 /* Remove it from the list and re-initialize it */
478 RemoveEntryList(&CreatorInfo
->TypeList
);
479 InitializeListHead(&CreatorInfo
->TypeList
);
483 /* Is the object type keeping track of handles? */
484 if (ObjectType
->TypeInfo
.MaintainHandleCount
)
486 /* Get handle information */
487 HandleInfo
= OBJECT_HEADER_TO_HANDLE_INFO(ObjectHeader
);
489 /* Check if there's only a single entry */
490 if (ObjectHeader
->Flags
& OB_FLAG_SINGLE_PROCESS
)
492 /* It should be us */
493 ASSERT(HandleInfo
->SingleEntry
.Process
== Process
);
494 ASSERT(HandleInfo
->SingleEntry
.HandleCount
> 0);
496 /* Get the handle counts */
497 ProcessHandleCount
= HandleInfo
->SingleEntry
.HandleCount
--;
498 HandleEntry
= &HandleInfo
->SingleEntry
;
502 /* Otherwise, get the database */
503 HandleDatabase
= HandleInfo
->HandleCountDatabase
;
506 /* Get the entries and loop them */
507 i
= HandleDatabase
->CountEntries
;
508 HandleEntry
= &HandleDatabase
->HandleCountEntries
[0];
511 /* Check if this is a match */
512 if ((HandleEntry
->HandleCount
) &&
513 (HandleEntry
->Process
== Process
))
515 /* Found it, get the process handle count */
516 ProcessHandleCount
= HandleEntry
->HandleCount
--;
526 /* Check if this is the last handle */
527 if (ProcessHandleCount
== 1)
529 /* Then clear the entry */
530 HandleEntry
->Process
= NULL
;
531 HandleEntry
->HandleCount
= 0;
535 /* Release the lock */
536 ObpLeaveObjectTypeMutex(ObjectType
);
538 /* Check if we have a close procedure */
539 if (ObjectType
->TypeInfo
.CloseProcedure
)
542 ObpCalloutStart(&CalloutIrql
);
543 ObjectType
->TypeInfo
.CloseProcedure(Process
,
548 ObpCalloutEnd(CalloutIrql
, "Close", ObjectType
, ObjectBody
);
551 /* Check if we should delete the object */
552 ObpDeleteNameCheck(ObjectBody
);
554 /* Decrease the total number of handles for this type */
555 InterlockedDecrement((PLONG
)&ObjectType
->TotalNumberOfHandles
);
556 OBTRACE(OB_HANDLE_DEBUG
,
557 "%s - Decremented count for: %p. HC LC %lx %lx\n",
560 ObjectHeader
->HandleCount
,
561 ObjectHeader
->PointerCount
);
565 * @name ObpCloseHandleTableEntry
567 * The ObpCloseHandleTableEntry routine <FILLMEIN>
581 * @param IgnoreHandleProtection
584 * @return <FILLMEIN>.
591 ObpCloseHandleTableEntry(IN PHANDLE_TABLE HandleTable
,
592 IN PHANDLE_TABLE_ENTRY HandleEntry
,
594 IN KPROCESSOR_MODE AccessMode
,
595 IN BOOLEAN IgnoreHandleProtection
)
598 POBJECT_TYPE ObjectType
;
599 POBJECT_HEADER ObjectHeader
;
600 ACCESS_MASK GrantedAccess
;
604 /* Get the object data */
605 ObjectHeader
= EX_HTE_TO_HDR(HandleEntry
);
606 ObjectType
= ObjectHeader
->Type
;
607 Body
= &ObjectHeader
->Body
;
608 GrantedAccess
= HandleEntry
->GrantedAccess
;
609 OBTRACE(OB_HANDLE_DEBUG
,
610 "%s - Closing handle: %lx for %p. HC LC %lx %lx\n",
614 ObjectHeader
->HandleCount
,
615 ObjectHeader
->PointerCount
);
617 /* Check if the object has an Okay To Close procedure */
618 if (ObjectType
->TypeInfo
.OkayToCloseProcedure
)
620 /* Call it and check if it's not letting us close it */
621 ObpCalloutStart(&CalloutIrql
);
622 if (!ObjectType
->TypeInfo
.OkayToCloseProcedure(PsGetCurrentProcess(),
628 ObpCalloutEnd(CalloutIrql
, "NtClose", ObjectType
, Body
);
629 ExUnlockHandleTableEntry(HandleTable
, HandleEntry
);
630 return STATUS_HANDLE_NOT_CLOSABLE
;
633 /* Success, validate callout retrn */
634 ObpCalloutEnd(CalloutIrql
, "NtClose", ObjectType
, Body
);
637 /* The callback allowed us to close it, but does the handle itself? */
638 if ((HandleEntry
->ObAttributes
& EX_HANDLE_ENTRY_PROTECTFROMCLOSE
) &&
639 !(IgnoreHandleProtection
))
641 /* It doesn't, are we from user mode? */
642 if (AccessMode
!= KernelMode
)
644 /* We are! Unlock the entry */
645 ExUnlockHandleTableEntry(HandleTable
, HandleEntry
);
647 /* Make sure we have an exception port */
648 if (PsGetCurrentProcess()->ExceptionPort
)
650 /* Raise an exception */
651 return KeRaiseUserException(STATUS_HANDLE_NOT_CLOSABLE
);
655 /* Return the error instead */
656 return STATUS_HANDLE_NOT_CLOSABLE
;
660 /* Otherwise, we are kernel mode, so unlock the entry and return */
661 ExUnlockHandleTableEntry(HandleTable
, HandleEntry
);
662 return STATUS_HANDLE_NOT_CLOSABLE
;
665 /* Destroy and unlock the handle entry */
666 ExDestroyHandleByEntry(HandleTable
, HandleEntry
, Handle
);
668 /* Now decrement the handle count */
669 ObpDecrementHandleCount(Body
, PsGetCurrentProcess(), GrantedAccess
);
671 /* Dereference the object as well */
672 ObDereferenceObject(Body
);
674 /* Return to caller */
675 OBTRACE(OB_HANDLE_DEBUG
,
676 "%s - Closed handle: %lx for %p. HC LC %lx %lx\n",
680 ObjectHeader
->HandleCount
,
681 ObjectHeader
->PointerCount
);
682 return STATUS_SUCCESS
;
686 * @name ObpIncrementHandleCount
688 * The ObpIncrementHandleCount routine <FILLMEIN>
699 * @param HandleAttributes
708 * @return <FILLMEIN>.
715 ObpIncrementHandleCount(IN PVOID Object
,
716 IN PACCESS_STATE AccessState
,
717 IN KPROCESSOR_MODE AccessMode
,
718 IN ULONG HandleAttributes
,
719 IN PEPROCESS Process
,
720 IN OB_OPEN_REASON OpenReason
)
722 POBJECT_HEADER ObjectHeader
;
723 POBJECT_TYPE ObjectType
;
724 ULONG ProcessHandleCount
;
726 PEPROCESS ExclusiveProcess
;
727 BOOLEAN Exclusive
= FALSE
, NewObject
;
728 POBJECT_HEADER_CREATOR_INFO CreatorInfo
;
731 /* Get the object header and type */
732 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
733 ObjectType
= ObjectHeader
->Type
;
734 OBTRACE(OB_HANDLE_DEBUG
,
735 "%s - Incrementing count for: %p. Reason: %lx. HC LC %lx %lx\n",
739 ObjectHeader
->HandleCount
,
740 ObjectHeader
->PointerCount
);
742 /* Lock the object type */
743 ObpEnterObjectTypeMutex(ObjectType
);
745 /* Charge quota and remove the creator info flag */
746 Status
= ObpChargeQuotaForObject(ObjectHeader
, ObjectType
, &NewObject
);
747 if (!NT_SUCCESS(Status
)) return Status
;
749 /* Check if the open is exclusive */
750 if (HandleAttributes
& OBJ_EXCLUSIVE
)
752 /* Check if the object allows this, or if the inherit flag was given */
753 if ((HandleAttributes
& OBJ_INHERIT
) ||
754 !(ObjectHeader
->Flags
& OB_FLAG_EXCLUSIVE
))
756 /* Incorrect attempt */
757 Status
= STATUS_INVALID_PARAMETER
;
761 /* Check if we have access to it */
762 ExclusiveProcess
= OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader
);
763 if ((!(ExclusiveProcess
) && (ObjectHeader
->HandleCount
)) ||
764 ((ExclusiveProcess
) && (ExclusiveProcess
!= PsGetCurrentProcess())))
766 /* This isn't the right process */
767 Status
= STATUS_ACCESS_DENIED
;
771 /* Now you got exclusive access */
774 else if ((ObjectHeader
->Flags
& OB_FLAG_EXCLUSIVE
) &&
775 (OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader
)))
777 /* Caller didn't want exclusive access, but the object is exclusive */
778 Status
= STATUS_ACCESS_DENIED
;
783 * Check if this is an object that went from 0 handles back to existence,
784 * but doesn't have an open procedure, only a close procedure. This means
785 * that it will never realize that the object is back alive, so we must
788 if (!(ObjectHeader
->HandleCount
) &&
790 (ObjectType
->TypeInfo
.MaintainHandleCount
) &&
791 !(ObjectType
->TypeInfo
.OpenProcedure
) &&
792 (ObjectType
->TypeInfo
.CloseProcedure
))
795 Status
= STATUS_UNSUCCESSFUL
;
799 /* Check if we're opening an existing handle */
800 if (OpenReason
== ObOpenHandle
)
802 /* Validate the caller's access to this object */
803 if (!ObCheckObjectAccess(Object
,
809 /* Access was denied, so fail */
813 else if (OpenReason
== ObCreateHandle
)
815 /* Convert MAXIMUM_ALLOWED to GENERIC_ALL */
816 if (AccessState
->RemainingDesiredAccess
& MAXIMUM_ALLOWED
)
818 /* Mask out MAXIMUM_ALLOWED and stick GENERIC_ALL instead */
819 AccessState
->RemainingDesiredAccess
&= ~MAXIMUM_ALLOWED
;
820 AccessState
->RemainingDesiredAccess
|= GENERIC_ALL
;
823 /* Check if we have to map the GENERIC mask */
824 if (AccessState
->RemainingDesiredAccess
& GENERIC_ACCESS
)
826 /* Map it to the correct access masks */
827 RtlMapGenericMask(&AccessState
->RemainingDesiredAccess
,
828 &ObjectType
->TypeInfo
.GenericMapping
);
831 /* Check if the caller is trying to access system security */
832 if (AccessState
->RemainingDesiredAccess
& ACCESS_SYSTEM_SECURITY
)
835 DPRINT1("ACCESS_SYSTEM_SECURITY not validated!\n");
839 /* Check if this is an exclusive handle */
842 /* Save the owner process */
843 OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader
)->ExclusiveProcess
= Process
;
846 /* Increase the handle count */
847 InterlockedIncrement(&ObjectHeader
->HandleCount
);
848 ProcessHandleCount
= 0;
850 /* Check if we have a handle database */
851 if (ObjectType
->TypeInfo
.MaintainHandleCount
)
853 /* Increment the handle database */
854 Status
= ObpIncrementHandleDataBase(ObjectHeader
,
856 &ProcessHandleCount
);
857 if (!NT_SUCCESS(Status
))
859 /* FIXME: This should never happen for now */
860 DPRINT1("Unhandled case\n");
866 /* Release the lock */
867 ObpLeaveObjectTypeMutex(ObjectType
);
869 /* Check if we have an open procedure */
870 Status
= STATUS_SUCCESS
;
871 if (ObjectType
->TypeInfo
.OpenProcedure
)
874 ObpCalloutStart(&CalloutIrql
);
875 Status
= ObjectType
->TypeInfo
.OpenProcedure(OpenReason
,
878 AccessState
->PreviouslyGrantedAccess
,
880 ObpCalloutEnd(CalloutIrql
, "Open", ObjectType
, Object
);
882 /* Check if the open procedure failed */
883 if (!NT_SUCCESS(Status
))
885 /* FIXME: This should never happen for now */
886 DPRINT1("Unhandled case\n");
892 /* Check if we have creator info */
893 CreatorInfo
= OBJECT_HEADER_TO_CREATOR_INFO(ObjectHeader
);
896 /* We do, acquire the lock */
897 ObpEnterObjectTypeMutex(ObjectType
);
899 /* Insert us on the list */
900 InsertTailList(&ObjectType
->TypeList
, &CreatorInfo
->TypeList
);
902 /* Release the lock */
903 ObpLeaveObjectTypeMutex(ObjectType
);
906 /* Increase total number of handles */
907 InterlockedIncrement((PLONG
)&ObjectType
->TotalNumberOfHandles
);
908 if (ObjectType
->TotalNumberOfHandles
> ObjectType
->HighWaterNumberOfHandles
)
911 ObjectType
->HighWaterNumberOfHandles
= ObjectType
->TotalNumberOfHandles
;
914 /* Trace call and return */
915 OBTRACE(OB_HANDLE_DEBUG
,
916 "%s - Incremented count for: %p. Reason: %lx HC LC %lx %lx\n",
920 ObjectHeader
->HandleCount
,
921 ObjectHeader
->PointerCount
);
925 /* Release lock and return */
926 ObpLeaveObjectTypeMutex(ObjectType
);
931 * @name ObpIncrementUnnamedHandleCount
933 * The ObpIncrementUnnamedHandleCount routine <FILLMEIN>
944 * @param HandleAttributes
953 * @return <FILLMEIN>.
960 ObpIncrementUnnamedHandleCount(IN PVOID Object
,
961 IN PACCESS_MASK DesiredAccess
,
962 IN KPROCESSOR_MODE AccessMode
,
963 IN ULONG HandleAttributes
,
964 IN PEPROCESS Process
)
966 POBJECT_HEADER ObjectHeader
;
967 POBJECT_TYPE ObjectType
;
968 ULONG ProcessHandleCount
;
970 PEPROCESS ExclusiveProcess
;
971 BOOLEAN Exclusive
= FALSE
, NewObject
;
972 POBJECT_HEADER_CREATOR_INFO CreatorInfo
;
975 /* Get the object header and type */
976 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
977 ObjectType
= ObjectHeader
->Type
;
978 OBTRACE(OB_HANDLE_DEBUG
,
979 "%s - Incrementing count for: %p. UNNAMED. HC LC %lx %lx\n",
982 ObjectHeader
->HandleCount
,
983 ObjectHeader
->PointerCount
);
985 /* Lock the object type */
986 ObpEnterObjectTypeMutex(ObjectType
);
988 /* Charge quota and remove the creator info flag */
989 Status
= ObpChargeQuotaForObject(ObjectHeader
, ObjectType
, &NewObject
);
990 if (!NT_SUCCESS(Status
)) return Status
;
992 /* Check if the open is exclusive */
993 if (HandleAttributes
& OBJ_EXCLUSIVE
)
995 /* Check if the object allows this, or if the inherit flag was given */
996 if ((HandleAttributes
& OBJ_INHERIT
) ||
997 !(ObjectHeader
->Flags
& OB_FLAG_EXCLUSIVE
))
999 /* Incorrect attempt */
1000 Status
= STATUS_INVALID_PARAMETER
;
1004 /* Check if we have access to it */
1005 ExclusiveProcess
= OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader
);
1006 if ((!(ExclusiveProcess
) && (ObjectHeader
->HandleCount
)) ||
1007 ((ExclusiveProcess
) && (ExclusiveProcess
!= PsGetCurrentProcess())))
1009 /* This isn't the right process */
1010 Status
= STATUS_ACCESS_DENIED
;
1014 /* Now you got exclusive access */
1017 else if ((ObjectHeader
->Flags
& OB_FLAG_EXCLUSIVE
) &&
1018 (OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader
)))
1020 /* Caller didn't want exclusive access, but the object is exclusive */
1021 Status
= STATUS_ACCESS_DENIED
;
1026 * Check if this is an object that went from 0 handles back to existence,
1027 * but doesn't have an open procedure, only a close procedure. This means
1028 * that it will never realize that the object is back alive, so we must
1031 if (!(ObjectHeader
->HandleCount
) &&
1033 (ObjectType
->TypeInfo
.MaintainHandleCount
) &&
1034 !(ObjectType
->TypeInfo
.OpenProcedure
) &&
1035 (ObjectType
->TypeInfo
.CloseProcedure
))
1038 Status
= STATUS_UNSUCCESSFUL
;
1042 /* Convert MAXIMUM_ALLOWED to GENERIC_ALL */
1043 if (*DesiredAccess
& MAXIMUM_ALLOWED
)
1045 /* Mask out MAXIMUM_ALLOWED and stick GENERIC_ALL instead */
1046 *DesiredAccess
&= ~MAXIMUM_ALLOWED
;
1047 *DesiredAccess
|= GENERIC_ALL
;
1050 /* Check if we have to map the GENERIC mask */
1051 if (*DesiredAccess
& GENERIC_ACCESS
)
1053 /* Map it to the correct access masks */
1054 RtlMapGenericMask(DesiredAccess
,
1055 &ObjectType
->TypeInfo
.GenericMapping
);
1058 /* Check if this is an exclusive handle */
1061 /* Save the owner process */
1062 OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader
)->ExclusiveProcess
= Process
;
1065 /* Increase the handle count */
1066 InterlockedIncrement(&ObjectHeader
->HandleCount
);
1067 ProcessHandleCount
= 0;
1069 /* Check if we have a handle database */
1070 if (ObjectType
->TypeInfo
.MaintainHandleCount
)
1072 /* Increment the handle database */
1073 Status
= ObpIncrementHandleDataBase(ObjectHeader
,
1075 &ProcessHandleCount
);
1076 if (!NT_SUCCESS(Status
))
1078 /* FIXME: This should never happen for now */
1079 DPRINT1("Unhandled case\n");
1085 /* Release the lock */
1086 ObpLeaveObjectTypeMutex(ObjectType
);
1088 /* Check if we have an open procedure */
1089 Status
= STATUS_SUCCESS
;
1090 if (ObjectType
->TypeInfo
.OpenProcedure
)
1093 ObpCalloutStart(&CalloutIrql
);
1094 Status
= ObjectType
->TypeInfo
.OpenProcedure(ObCreateHandle
,
1098 ProcessHandleCount
);
1099 ObpCalloutEnd(CalloutIrql
, "Open", ObjectType
, Object
);
1101 /* Check if the open procedure failed */
1102 if (!NT_SUCCESS(Status
))
1104 /* FIXME: This should never happen for now */
1105 DPRINT1("Unhandled case\n");
1111 /* Check if we have creator info */
1112 CreatorInfo
= OBJECT_HEADER_TO_CREATOR_INFO(ObjectHeader
);
1115 /* We do, acquire the lock */
1116 ObpEnterObjectTypeMutex(ObjectType
);
1118 /* Insert us on the list */
1119 InsertTailList(&ObjectType
->TypeList
, &CreatorInfo
->TypeList
);
1121 /* Release the lock */
1122 ObpLeaveObjectTypeMutex(ObjectType
);
1125 /* Increase total number of handles */
1126 InterlockedIncrement((PLONG
)&ObjectType
->TotalNumberOfHandles
);
1127 if (ObjectType
->TotalNumberOfHandles
> ObjectType
->HighWaterNumberOfHandles
)
1130 ObjectType
->HighWaterNumberOfHandles
= ObjectType
->TotalNumberOfHandles
;
1133 /* Trace call and return */
1134 OBTRACE(OB_HANDLE_DEBUG
,
1135 "%s - Incremented count for: %p. UNNAMED HC LC %lx %lx\n",
1138 ObjectHeader
->HandleCount
,
1139 ObjectHeader
->PointerCount
);
1143 /* Release lock and return */
1144 ObpLeaveObjectTypeMutex(ObjectType
);
1149 * @name ObpCreateUnnamedHandle
1151 * The ObpCreateUnnamedHandle routine <FILLMEIN>
1156 * @param DesiredAccess
1159 * @param AdditionalReferences
1162 * @param HandleAttributes
1168 * @param ReturnedObject
1171 * @param ReturnedHandle
1174 * @return <FILLMEIN>.
1181 ObpCreateUnnamedHandle(IN PVOID Object
,
1182 IN ACCESS_MASK DesiredAccess
,
1183 IN ULONG AdditionalReferences
,
1184 IN ULONG HandleAttributes
,
1185 IN KPROCESSOR_MODE AccessMode
,
1186 OUT PVOID
*ReturnedObject
,
1187 OUT PHANDLE ReturnedHandle
)
1189 HANDLE_TABLE_ENTRY NewEntry
;
1190 POBJECT_HEADER ObjectHeader
;
1192 KAPC_STATE ApcState
;
1193 BOOLEAN AttachedToProcess
= FALSE
, KernelHandle
= FALSE
;
1196 ACCESS_MASK GrantedAccess
;
1197 POBJECT_TYPE ObjectType
;
1200 /* Get the object header and type */
1201 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
1202 ObjectType
= ObjectHeader
->Type
;
1203 OBTRACE(OB_HANDLE_DEBUG
,
1204 "%s - Creating handle for: %p. UNNAMED. HC LC %lx %lx\n",
1207 ObjectHeader
->HandleCount
,
1208 ObjectHeader
->PointerCount
);
1210 /* Check if this is a kernel handle */
1211 if ((HandleAttributes
& OBJ_KERNEL_HANDLE
) && (AccessMode
== KernelMode
))
1213 /* Set the handle table */
1214 HandleTable
= ObpKernelHandleTable
;
1215 KernelHandle
= TRUE
;
1217 /* Check if we're not in the system process */
1218 if (PsGetCurrentProcess() != PsInitialSystemProcess
)
1220 /* Attach to the system process */
1221 KeStackAttachProcess(&PsInitialSystemProcess
->Pcb
, &ApcState
);
1222 AttachedToProcess
= TRUE
;
1227 /* Get the current handle table */
1228 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
1231 /* Increment the handle count */
1232 Status
= ObpIncrementUnnamedHandleCount(Object
,
1236 PsGetCurrentProcess());
1237 if (!NT_SUCCESS(Status
))
1240 * We failed (meaning security failure, according to NT Internals)
1243 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
1247 /* Save the object header */
1248 NewEntry
.Object
= ObjectHeader
;
1250 /* Mask out the internal attributes */
1251 NewEntry
.ObAttributes
|= HandleAttributes
&
1252 (EX_HANDLE_ENTRY_PROTECTFROMCLOSE
|
1253 EX_HANDLE_ENTRY_INHERITABLE
|
1254 EX_HANDLE_ENTRY_AUDITONCLOSE
);
1256 /* Remove what's not in the valid access mask */
1257 GrantedAccess
= DesiredAccess
& (ObjectType
->TypeInfo
.ValidAccessMask
|
1258 ACCESS_SYSTEM_SECURITY
);
1260 /* Handle extra references */
1261 if (AdditionalReferences
)
1263 /* Add them to the header */
1264 InterlockedExchangeAdd(&ObjectHeader
->PointerCount
,
1265 AdditionalReferences
);
1268 /* Save the access mask */
1269 NewEntry
.GrantedAccess
= GrantedAccess
;
1272 * Create the actual handle. We'll need to do this *after* calling
1273 * ObpIncrementHandleCount to make sure that Object Security is valid
1274 * (specified in Gl00my documentation on Ob)
1276 OBTRACE(OB_HANDLE_DEBUG
,
1277 "%s - Handle Properties: [%p-%lx-%lx]\n",
1279 NewEntry
.Object
, NewEntry
.ObAttributes
& 3, NewEntry
.GrantedAccess
);
1280 Handle
= ExCreateHandle(HandleTable
, &NewEntry
);
1282 /* Make sure we got a handle */
1285 /* Check if this was a kernel handle */
1286 if (KernelHandle
) Handle
= ObMarkHandleAsKernelHandle(Handle
);
1288 /* Return handle and object */
1289 *ReturnedHandle
= Handle
;
1291 /* Return the new object only if caller wanted it biased */
1292 if ((AdditionalReferences
) && (ReturnedObject
))
1295 *ReturnedObject
= Object
;
1298 /* Detach if needed */
1299 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
1301 /* Trace and return */
1302 OBTRACE(OB_HANDLE_DEBUG
,
1303 "%s - Returning Handle: %lx HC LC %lx %lx\n",
1306 ObjectHeader
->HandleCount
,
1307 ObjectHeader
->PointerCount
);
1308 return STATUS_SUCCESS
;
1311 /* Handle extra references */
1312 if (AdditionalReferences
== 1)
1314 /* Dereference the object once */
1315 ObDereferenceObject(Object
);
1317 else if (AdditionalReferences
> 1)
1319 /* Dereference it many times */
1320 InterlockedExchangeAdd(&ObjectHeader
->PointerCount
,
1321 -AdditionalReferences
);
1324 /* Decrement the handle count and detach */
1325 ObpDecrementHandleCount(&ObjectHeader
->Body
,
1326 PsGetCurrentProcess(),
1329 /* Detach and fail */
1330 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
1331 return STATUS_INSUFFICIENT_RESOURCES
;
1335 * @name ObpCreateHandle
1337 * The ObpCreateHandle routine <FILLMEIN>
1348 * @param AccessState
1351 * @param AdditionalReferences
1354 * @param HandleAttributes
1360 * @param ReturnedObject
1363 * @param ReturnedHandle
1366 * @return <FILLMEIN>.
1368 * @remarks Cleans up the Lookup Context on return.
1373 ObpCreateHandle(IN OB_OPEN_REASON OpenReason
,
1375 IN POBJECT_TYPE Type OPTIONAL
,
1376 IN PACCESS_STATE AccessState
,
1377 IN ULONG AdditionalReferences
,
1378 IN ULONG HandleAttributes
,
1379 IN POBP_LOOKUP_CONTEXT Context
,
1380 IN KPROCESSOR_MODE AccessMode
,
1381 OUT PVOID
*ReturnedObject
,
1382 OUT PHANDLE ReturnedHandle
)
1384 HANDLE_TABLE_ENTRY NewEntry
;
1385 POBJECT_HEADER ObjectHeader
;
1387 KAPC_STATE ApcState
;
1388 BOOLEAN AttachedToProcess
= FALSE
, KernelHandle
= FALSE
;
1389 POBJECT_TYPE ObjectType
;
1392 ACCESS_MASK DesiredAccess
, GrantedAccess
;
1396 /* Get the object header and type */
1397 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
1398 ObjectType
= ObjectHeader
->Type
;
1399 OBTRACE(OB_HANDLE_DEBUG
,
1400 "%s - Creating handle for: %p. Reason: %lx. HC LC %lx %lx\n",
1404 ObjectHeader
->HandleCount
,
1405 ObjectHeader
->PointerCount
);
1407 /* Check if the types match */
1408 if ((Type
) && (ObjectType
!= Type
))
1410 /* They don't, cleanup */
1411 if (Context
) ObpCleanupDirectoryLookup(Context
);
1412 return STATUS_OBJECT_TYPE_MISMATCH
;
1415 /* Check if this is a kernel handle */
1416 if ((HandleAttributes
& OBJ_KERNEL_HANDLE
) && (AccessMode
== KernelMode
))
1418 /* Set the handle table */
1419 HandleTable
= ObpKernelHandleTable
;
1420 KernelHandle
= TRUE
;
1422 /* Check if we're not in the system process */
1423 if (PsGetCurrentProcess() != PsInitialSystemProcess
)
1425 /* Attach to the system process */
1426 KeStackAttachProcess(&PsInitialSystemProcess
->Pcb
, &ApcState
);
1427 AttachedToProcess
= TRUE
;
1432 /* Get the current handle table */
1433 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
1436 /* Increment the handle count */
1437 Status
= ObpIncrementHandleCount(Object
,
1441 PsGetCurrentProcess(),
1443 if (!NT_SUCCESS(Status
))
1446 * We failed (meaning security failure, according to NT Internals)
1449 if (Context
) ObpCleanupDirectoryLookup(Context
);
1450 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
1454 /* Check if we are doing audits on close */
1455 if (AccessState
->GenerateOnClose
)
1457 /* Force the attribute on */
1458 HandleAttributes
|= EX_HANDLE_ENTRY_AUDITONCLOSE
;
1461 /* Mask out the internal attributes */
1462 NewEntry
.ObAttributes
|= HandleAttributes
&
1463 (EX_HANDLE_ENTRY_PROTECTFROMCLOSE
|
1464 EX_HANDLE_ENTRY_INHERITABLE
|
1465 EX_HANDLE_ENTRY_AUDITONCLOSE
);
1467 /* Get the original desired access */
1468 DesiredAccess
= AccessState
->RemainingDesiredAccess
|
1469 AccessState
->PreviouslyGrantedAccess
;
1471 /* Remove what's not in the valid access mask */
1472 GrantedAccess
= DesiredAccess
& (ObjectType
->TypeInfo
.ValidAccessMask
|
1473 ACCESS_SYSTEM_SECURITY
);
1475 /* Update the value in the access state */
1476 AccessState
->PreviouslyGrantedAccess
= GrantedAccess
;
1478 /* Get the auxiliary data */
1479 AuxData
= AccessState
->AuxData
;
1481 /* Handle extra references */
1482 if (AdditionalReferences
)
1484 /* Add them to the header */
1485 InterlockedExchangeAdd(&ObjectHeader
->PointerCount
, AdditionalReferences
);
1488 /* Now we can release the object */
1489 if (Context
) ObpCleanupDirectoryLookup(Context
);
1491 /* Save the object header */
1492 NewEntry
.Object
= ObjectHeader
;
1494 /* Save the access mask */
1495 NewEntry
.GrantedAccess
= GrantedAccess
;
1498 * Create the actual handle. We'll need to do this *after* calling
1499 * ObpIncrementHandleCount to make sure that Object Security is valid
1500 * (specified in Gl00my documentation on Ob)
1502 OBTRACE(OB_HANDLE_DEBUG
,
1503 "%s - Handle Properties: [%p-%lx-%lx]\n",
1505 NewEntry
.Object
, NewEntry
.ObAttributes
& 3, NewEntry
.GrantedAccess
);
1506 Handle
= ExCreateHandle(HandleTable
, &NewEntry
);
1508 /* Make sure we got a handle */
1511 /* Check if we have auxiliary data */
1514 /* FIXME: Change handle security */
1517 /* Check if this was a kernel handle */
1518 if (KernelHandle
) Handle
= ObMarkHandleAsKernelHandle(Handle
);
1521 *ReturnedHandle
= Handle
;
1523 /* Check if we need to generate on audit */
1524 if (AccessState
->GenerateAudit
)
1526 /* Audit the handle creation */
1527 //SeAuditHandleCreation(AccessState, Handle);
1530 /* Check if this was a create */
1531 if (OpenReason
== ObCreateHandle
)
1533 /* Check if we need to audit the privileges */
1534 if ((AuxData
->PrivilegeSet
) &&
1535 (AuxData
->PrivilegeSet
->PrivilegeCount
))
1539 SePrivilegeObjectAuditAlarm(Handle
,
1541 SubjectSecurityContext
,
1543 AuxData
->PrivilegeSet
,
1545 ExGetPreviousMode());
1550 /* Return the new object only if caller wanted it biased */
1551 if ((AdditionalReferences
) && (ReturnedObject
))
1554 *ReturnedObject
= Object
;
1557 /* Detach if needed */
1558 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
1560 /* Trace and return */
1561 OBTRACE(OB_HANDLE_DEBUG
,
1562 "%s - Returning Handle: %lx HC LC %lx %lx\n",
1565 ObjectHeader
->HandleCount
,
1566 ObjectHeader
->PointerCount
);
1567 return STATUS_SUCCESS
;
1570 /* Decrement the handle count and detach */
1571 ObpDecrementHandleCount(&ObjectHeader
->Body
,
1572 PsGetCurrentProcess(),
1575 /* Handle extra references */
1576 if (AdditionalReferences
== 1)
1578 /* Dereference the object once */
1579 ObDereferenceObject(Object
);
1581 else if (AdditionalReferences
> 1)
1583 /* Dereference it many times */
1584 InterlockedExchangeAdd(&ObjectHeader
->PointerCount
,
1585 -AdditionalReferences
);
1588 /* Detach if necessary and fail */
1589 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
1590 return STATUS_INSUFFICIENT_RESOURCES
;
1594 * @name ObpCloseHandle
1596 * The ObpCloseHandle routine <FILLMEIN>
1604 * @return <FILLMEIN>.
1611 ObpCloseHandle(IN HANDLE Handle
,
1612 IN KPROCESSOR_MODE AccessMode
)
1615 BOOLEAN AttachedToProcess
= FALSE
;
1616 KAPC_STATE ApcState
;
1617 PHANDLE_TABLE_ENTRY HandleTableEntry
;
1620 OBTRACE(OB_HANDLE_DEBUG
,
1621 "%s - Closing handle: %lx\n", __FUNCTION__
, Handle
);
1623 /* Check if we're dealing with a kernel handle */
1624 if (ObIsKernelHandle(Handle
, AccessMode
))
1626 /* Use the kernel table and convert the handle */
1627 HandleTable
= ObpKernelHandleTable
;
1628 Handle
= ObKernelHandleToHandle(Handle
);
1630 /* Check if we're not in the system process */
1631 if (PsGetCurrentProcess() != PsInitialSystemProcess
)
1633 /* Attach to the system process */
1634 KeStackAttachProcess(&PsInitialSystemProcess
->Pcb
, &ApcState
);
1635 AttachedToProcess
= TRUE
;
1640 /* Use the process's handle table */
1641 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
1644 /* Enter a critical region to protect handle access */
1645 KeEnterCriticalRegion();
1647 /* Get the handle entry */
1648 HandleTableEntry
= ExMapHandleToPointer(HandleTable
, Handle
);
1649 if (HandleTableEntry
)
1651 /* Now close the entry */
1652 Status
= ObpCloseHandleTableEntry(HandleTable
,
1658 /* We can quit the critical region now */
1659 KeLeaveCriticalRegion();
1661 /* Detach and return success */
1662 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
1663 return STATUS_SUCCESS
;
1667 /* We failed, quit the critical region */
1668 KeLeaveCriticalRegion();
1671 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
1673 /* Check if this was a user-mode caller with a valid exception port */
1674 if ((AccessMode
!= KernelMode
) &&
1675 (PsGetCurrentProcess()->ExceptionPort
))
1677 /* Raise an exception */
1678 Status
= KeRaiseUserException(STATUS_INVALID_HANDLE
);
1682 /* Just return the status */
1683 Status
= STATUS_INVALID_HANDLE
;
1688 OBTRACE(OB_HANDLE_DEBUG
,
1689 "%s - Closed handle: %lx S: %lx\n",
1690 __FUNCTION__
, Handle
, Status
);
1695 * @name ObpSetHandleAttributes
1697 * The ObpSetHandleAttributes routine <FILLMEIN>
1699 * @param HandleTable
1702 * @param HandleTableEntry
1708 * @return <FILLMEIN>.
1715 ObpSetHandleAttributes(IN PHANDLE_TABLE HandleTable
,
1716 IN OUT PHANDLE_TABLE_ENTRY HandleTableEntry
,
1719 POBP_SET_HANDLE_ATTRIBUTES_CONTEXT SetHandleInfo
= Context
;
1720 POBJECT_HEADER ObjectHeader
= EX_HTE_TO_HDR(HandleTableEntry
);
1723 /* Don't allow operations on kernel objects */
1724 if ((ObjectHeader
->Flags
& OB_FLAG_KERNEL_MODE
) &&
1725 (SetHandleInfo
->PreviousMode
!= KernelMode
))
1731 /* Check if making the handle inheritable */
1732 if (SetHandleInfo
->Information
.Inherit
)
1734 /* Check if inheriting is not supported for this object */
1735 if (ObjectHeader
->Type
->TypeInfo
.InvalidAttributes
& OBJ_INHERIT
)
1737 /* Fail without changing anything */
1742 HandleTableEntry
->ObAttributes
|= EX_HANDLE_ENTRY_INHERITABLE
;
1746 /* Otherwise this implies we're removing the flag */
1747 HandleTableEntry
->ObAttributes
&= ~EX_HANDLE_ENTRY_INHERITABLE
;
1750 /* Check if making the handle protected */
1751 if (SetHandleInfo
->Information
.ProtectFromClose
)
1754 HandleTableEntry
->ObAttributes
|= EX_HANDLE_ENTRY_PROTECTFROMCLOSE
;
1758 /* Otherwise, remove it */
1759 HandleTableEntry
->ObAttributes
&= ~EX_HANDLE_ENTRY_PROTECTFROMCLOSE
;
1762 /* Return success */
1767 * @name ObpCloseHandleCallback
1769 * The ObpCloseHandleCallback routine <FILLMEIN>
1771 * @param HandleTable
1777 * @param GrantedAccess
1783 * @return <FILLMEIN>.
1790 ObpCloseHandleCallback(IN PHANDLE_TABLE_ENTRY HandleTableEntry
,
1794 POBP_CLOSE_HANDLE_CONTEXT CloseContext
= (POBP_CLOSE_HANDLE_CONTEXT
)Context
;
1796 /* Simply decrement the handle count */
1797 ObpCloseHandleTableEntry(CloseContext
->HandleTable
,
1800 CloseContext
->AccessMode
,
1805 * @name ObpDuplicateHandleCallback
1807 * The ObpDuplicateHandleCallback routine <FILLMEIN>
1809 * @param HandleTable
1812 * @param HandleTableEntry
1818 * @return <FILLMEIN>.
1825 ObpDuplicateHandleCallback(IN PHANDLE_TABLE HandleTable
,
1826 IN PHANDLE_TABLE_ENTRY HandleTableEntry
,
1829 POBJECT_HEADER ObjectHeader
;
1830 BOOLEAN Ret
= FALSE
;
1831 ACCESS_STATE AccessState
;
1835 /* Make sure that the handle is inheritable */
1836 Ret
= (HandleTableEntry
->ObAttributes
& EX_HANDLE_ENTRY_INHERITABLE
) != 0;
1839 /* Get the object header */
1840 ObjectHeader
= EX_HTE_TO_HDR(HandleTableEntry
);
1842 /* Setup the access state */
1843 AccessState
.PreviouslyGrantedAccess
= HandleTableEntry
->GrantedAccess
;
1845 /* Call the shared routine for incrementing handles */
1846 Status
= ObpIncrementHandleCount(&ObjectHeader
->Body
,
1849 HandleTableEntry
->ObAttributes
,
1850 PsGetCurrentProcess(),
1852 if (!NT_SUCCESS(Status
))
1854 /* Return failure */
1859 /* Otherwise increment the pointer count */
1860 InterlockedIncrement(&ObjectHeader
->PointerCount
);
1864 /* Return duplication result */
1870 ObClearProcessHandleTable(IN PEPROCESS Process
)
1876 * @name ObpCreateHandleTable
1878 * The ObpCreateHandleTable routine <FILLMEIN>
1886 * @return <FILLMEIN>.
1893 ObpCreateHandleTable(IN PEPROCESS Parent
,
1894 IN PEPROCESS Process
)
1896 PHANDLE_TABLE HandleTable
;
1899 /* Check if we have a parent */
1902 /* Get the parent's table */
1903 HandleTable
= ObReferenceProcessHandleTable(Parent
);
1904 if (!HandleTable
) return STATUS_PROCESS_IS_TERMINATING
;
1906 /* Duplicate the parent's */
1907 HandleTable
= ExDupHandleTable(Process
,
1908 ObpDuplicateHandleCallback
,
1914 /* Create a new one */
1915 HandleTable
= ExCreateHandleTable(Process
);
1919 Process
->ObjectTable
= HandleTable
;
1921 /* Dereference the parent's handle table if we have one */
1922 if (Parent
) ObDereferenceProcessHandleTable(Parent
);
1924 /* Fail or succeed depending on whether we got a handle table or not */
1925 if (!HandleTable
) return STATUS_INSUFFICIENT_RESOURCES
;
1926 return STATUS_SUCCESS
;
1930 * @name ObKillProcess
1932 * The ObKillProcess routine <FILLMEIN>
1944 ObKillProcess(IN PEPROCESS Process
)
1946 PHANDLE_TABLE HandleTable
;
1947 OBP_CLOSE_HANDLE_CONTEXT Context
;
1951 /* Wait for process rundown */
1952 ExWaitForRundownProtectionRelease(&Process
->RundownProtect
);
1954 /* Get the object table */
1955 HandleTable
= Process
->ObjectTable
;
1956 if (!HandleTable
) return;
1958 /* Disable hard errors while we close handles */
1959 HardErrors
= IoSetThreadHardErrorMode(FALSE
);
1961 /* Enter a critical region */
1962 KeEnterCriticalRegion();
1964 /* Fill out the context */
1965 Context
.AccessMode
= KernelMode
;
1966 Context
.HandleTable
= HandleTable
;
1968 /* Sweep the handle table to close all handles */
1969 ExSweepHandleTable(HandleTable
,
1970 ObpCloseHandleCallback
,
1972 ASSERT(HandleTable
->HandleCount
== 0);
1974 /* Leave the critical region */
1975 KeLeaveCriticalRegion();
1977 /* Re-enable hard errors */
1978 IoSetThreadHardErrorMode(HardErrors
);
1980 /* Destroy the object table */
1981 Process
->ObjectTable
= NULL
;
1982 ExDestroyHandleTable(HandleTable
);
1987 ObDuplicateObject(IN PEPROCESS SourceProcess
,
1988 IN HANDLE SourceHandle
,
1989 IN PEPROCESS TargetProcess OPTIONAL
,
1990 IN PHANDLE TargetHandle OPTIONAL
,
1991 IN ACCESS_MASK DesiredAccess
,
1992 IN ULONG HandleAttributes
,
1994 IN KPROCESSOR_MODE PreviousMode
)
1996 HANDLE_TABLE_ENTRY NewHandleEntry
;
1997 BOOLEAN AttachedToProcess
= FALSE
;
1999 POBJECT_HEADER ObjectHeader
;
2000 POBJECT_TYPE ObjectType
;
2002 KAPC_STATE ApcState
;
2004 ACCESS_MASK TargetAccess
, SourceAccess
;
2005 ACCESS_STATE AccessState
;
2006 PACCESS_STATE PassedAccessState
= NULL
;
2008 PHANDLE_TABLE HandleTable
;
2009 OBJECT_HANDLE_INFORMATION HandleInformation
;
2011 OBTRACE(OB_HANDLE_DEBUG
,
2012 "%s - Duplicating handle: %lx for %p into %p\n",
2018 /* Check if we're not duplicating the same access */
2019 if (!(Options
& DUPLICATE_SAME_ACCESS
))
2021 /* Validate the desired access */
2022 Status
= STATUS_SUCCESS
; //ObpValidateDesiredAccess(DesiredAccess);
2023 if (!NT_SUCCESS(Status
)) return Status
;
2026 /* Reference the object table */
2027 HandleTable
= ObReferenceProcessHandleTable(SourceProcess
);
2028 if (!HandleTable
) return STATUS_PROCESS_IS_TERMINATING
;
2030 /* Reference the process object */
2031 Status
= ObpReferenceProcessObjectByHandle(SourceHandle
,
2036 &HandleInformation
);
2037 if (!NT_SUCCESS(Status
))
2040 ObDereferenceProcessHandleTable(SourceProcess
);
2044 /* Check if there's no target process */
2047 /* Check if the caller wanted actual duplication */
2048 if (!(Options
& DUPLICATE_CLOSE_SOURCE
))
2050 /* Invalid request */
2051 Status
= STATUS_INVALID_PARAMETER
;
2055 /* Otherwise, do the attach */
2056 KeStackAttachProcess(&SourceProcess
->Pcb
, &ApcState
);
2058 /* Close the handle and detach */
2059 NtClose(SourceHandle
);
2060 KeUnstackDetachProcess(&ApcState
);
2064 ObDereferenceProcessHandleTable(SourceProcess
);
2065 ObDereferenceObject(SourceObject
);
2069 /* Get the target handle table */
2070 HandleTable
= ObReferenceProcessHandleTable(TargetProcess
);
2073 /* Check if the caller wanted us to close the handle */
2074 if (Options
& DUPLICATE_CLOSE_SOURCE
)
2077 KeStackAttachProcess(&SourceProcess
->Pcb
, &ApcState
);
2079 /* Close the handle and detach */
2080 NtClose(SourceHandle
);
2081 KeUnstackDetachProcess(&ApcState
);
2085 ObDereferenceProcessHandleTable(SourceProcess
);
2086 ObDereferenceObject(SourceObject
);
2087 return STATUS_PROCESS_IS_TERMINATING
;
2090 /* Get the source access */
2091 SourceAccess
= HandleInformation
.GrantedAccess
;
2093 /* Check if we're not in the target process */
2094 if (TargetProcess
!= PsGetCurrentProcess())
2097 KeStackAttachProcess(&TargetProcess
->Pcb
, &ApcState
);
2098 AttachedToProcess
= TRUE
;
2101 /* Check if we're duplicating the attributes */
2102 if (Options
& DUPLICATE_SAME_ATTRIBUTES
)
2104 /* Duplicate them */
2105 HandleAttributes
= HandleInformation
.HandleAttributes
;
2108 /* Check if we're duplicating the access */
2109 if (Options
& DUPLICATE_SAME_ACCESS
) DesiredAccess
= SourceAccess
;
2111 /* Get object data */
2112 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(SourceObject
);
2113 ObjectType
= ObjectHeader
->Type
;
2115 /* Fill out the entry */
2116 NewHandleEntry
.Object
= ObjectHeader
;
2117 NewHandleEntry
.ObAttributes
|= HandleAttributes
&
2118 (EX_HANDLE_ENTRY_PROTECTFROMCLOSE
|
2119 EX_HANDLE_ENTRY_INHERITABLE
|
2120 EX_HANDLE_ENTRY_AUDITONCLOSE
);
2122 /* Check if we're using a generic mask */
2123 if (DesiredAccess
& GENERIC_ACCESS
)
2126 RtlMapGenericMask(&DesiredAccess
,
2127 &ObjectType
->TypeInfo
.GenericMapping
);
2130 /* Set the target access */
2131 TargetAccess
= DesiredAccess
;
2132 NewHandleEntry
.GrantedAccess
= TargetAccess
;
2134 /* Check if we're asking for new access */
2135 if (TargetAccess
& ~SourceAccess
)
2137 /* We are. We need the security procedure to validate this */
2138 if (ObjectType
->TypeInfo
.SecurityProcedure
== SeDefaultObjectMethod
)
2140 /* Use our built-in access state */
2141 PassedAccessState
= &AccessState
;
2142 Status
= SeCreateAccessState(&AccessState
,
2145 &ObjectType
->TypeInfo
.GenericMapping
);
2149 /* Otherwise we can't allow this privilege elevation */
2150 Status
= STATUS_ACCESS_DENIED
;
2155 /* We don't need an access state */
2156 Status
= STATUS_SUCCESS
;
2159 /* Make sure the access state was created OK */
2160 if (NT_SUCCESS(Status
))
2162 /* Add a new handle */
2163 Status
= ObpIncrementHandleCount(SourceObject
,
2167 PsGetCurrentProcess(),
2171 /* Check if we were attached */
2172 if (AttachedToProcess
)
2174 /* We can safely detach now */
2175 KeUnstackDetachProcess(&ApcState
);
2176 AttachedToProcess
= FALSE
;
2179 /* Check if we have to close the source handle */
2180 if (Options
& DUPLICATE_CLOSE_SOURCE
)
2182 /* Attach and close */
2183 KeStackAttachProcess(&SourceProcess
->Pcb
, &ApcState
);
2184 NtClose(SourceHandle
);
2185 KeUnstackDetachProcess(&ApcState
);
2188 /* Check if we had an access state */
2189 if (PassedAccessState
) SeDeleteAccessState(PassedAccessState
);
2191 /* Now check if incrementing actually failed */
2192 if (!NT_SUCCESS(Status
))
2194 /* Dereference the source object */
2195 ObDereferenceObject(SourceObject
);
2199 /* Now create the handle */
2200 NewHandle
= ExCreateHandle(HandleTable
, &NewHandleEntry
);
2203 /* Undo the increment */
2204 ObpDecrementHandleCount(SourceObject
,
2208 /* Deference the object and set failure status */
2209 ObDereferenceObject(SourceObject
);
2210 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2213 /* Return the handle */
2214 if (TargetHandle
) *TargetHandle
= NewHandle
;
2216 /* Dereference handle tables */
2217 ObDereferenceProcessHandleTable(SourceProcess
);
2218 ObDereferenceProcessHandleTable(TargetProcess
);
2221 OBTRACE(OB_HANDLE_DEBUG
,
2222 "%s - Duplicated handle: %lx for %p into %p. Source: %p HC PC %lx %lx\n",
2228 ObjectHeader
->PointerCount
,
2229 ObjectHeader
->HandleCount
);
2233 /* PUBLIC FUNCTIONS *********************************************************/
2236 * @name ObOpenObjectByName
2239 * The ObOpenObjectByName routine <FILLMEIN>
2241 * @param ObjectAttributes
2250 * @param PassedAccessState
2253 * @param DesiredAccess
2256 * @param ParseContext
2262 * @return <FILLMEIN>.
2269 ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2270 IN POBJECT_TYPE ObjectType
,
2271 IN KPROCESSOR_MODE AccessMode
,
2272 IN PACCESS_STATE PassedAccessState
,
2273 IN ACCESS_MASK DesiredAccess
,
2274 IN OUT PVOID ParseContext
,
2277 PVOID Object
= NULL
;
2278 UNICODE_STRING ObjectName
;
2280 POBJECT_HEADER ObjectHeader
;
2281 PGENERIC_MAPPING GenericMapping
= NULL
;
2282 OB_OPEN_REASON OpenReason
;
2283 POB_TEMP_BUFFER TempBuffer
;
2286 /* Check if we didn't get any Object Attributes */
2287 if (!ObjectAttributes
)
2289 /* Fail with special status code */
2291 return STATUS_INVALID_PARAMETER
;
2294 /* Allocate the temporary buffer */
2295 TempBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2296 sizeof(OB_TEMP_BUFFER
),
2297 TAG_OB_TEMP_STORAGE
);
2298 if (!TempBuffer
) return STATUS_INSUFFICIENT_RESOURCES
;
2300 /* Capture all the info */
2301 Status
= ObpCaptureObjectAttributes(ObjectAttributes
,
2304 &TempBuffer
->ObjectCreateInfo
,
2306 if (!NT_SUCCESS(Status
)) return Status
;
2308 /* Check if we didn't get an access state */
2309 if (!PassedAccessState
)
2311 /* Try to get the generic mapping if we can */
2312 if (ObjectType
) GenericMapping
= &ObjectType
->TypeInfo
.GenericMapping
;
2314 /* Use our built-in access state */
2315 PassedAccessState
= &TempBuffer
->LocalAccessState
;
2316 Status
= SeCreateAccessState(&TempBuffer
->LocalAccessState
,
2317 &TempBuffer
->AuxData
,
2320 if (!NT_SUCCESS(Status
)) goto Quickie
;
2323 /* Get the security descriptor */
2324 if (TempBuffer
->ObjectCreateInfo
.SecurityDescriptor
)
2326 /* Save it in the access state */
2327 PassedAccessState
->SecurityDescriptor
=
2328 TempBuffer
->ObjectCreateInfo
.SecurityDescriptor
;
2331 /* Now do the lookup */
2332 Status
= ObpLookupObjectName(TempBuffer
->ObjectCreateInfo
.RootDirectory
,
2334 TempBuffer
->ObjectCreateInfo
.Attributes
,
2338 TempBuffer
->ObjectCreateInfo
.SecurityQos
,
2341 &TempBuffer
->LookupContext
,
2343 if (!NT_SUCCESS(Status
))
2345 /* Cleanup after lookup */
2346 ObpCleanupDirectoryLookup(&TempBuffer
->LookupContext
);
2350 /* Check if this object has create information */
2351 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
2352 if (ObjectHeader
->Flags
& OB_FLAG_CREATE_INFO
)
2354 /* Then we are creating a new handle */
2355 OpenReason
= ObCreateHandle
;
2357 /* Check if we still have create info */
2358 if (ObjectHeader
->ObjectCreateInfo
)
2361 ObpFreeAndReleaseCapturedAttributes(ObjectHeader
->
2363 ObjectHeader
->ObjectCreateInfo
= NULL
;
2368 /* Otherwise, we are merely opening it */
2369 OpenReason
= ObOpenHandle
;
2372 /* Check if we have invalid object attributes */
2373 if (ObjectHeader
->Type
->TypeInfo
.InvalidAttributes
&
2374 TempBuffer
->ObjectCreateInfo
.Attributes
)
2376 /* Set failure code */
2377 Status
= STATUS_INVALID_PARAMETER
;
2379 /* Cleanup after lookup */
2380 ObpCleanupDirectoryLookup(&TempBuffer
->LookupContext
);
2384 /* Create the actual handle now */
2385 Status
= ObpCreateHandle(OpenReason
,
2390 TempBuffer
->ObjectCreateInfo
.Attributes
,
2391 &TempBuffer
->LookupContext
,
2395 if (!NT_SUCCESS(Status
)) ObDereferenceObject(Object
);
2399 /* Delete the access state */
2400 if (PassedAccessState
== &TempBuffer
->LocalAccessState
)
2402 SeDeleteAccessState(PassedAccessState
);
2406 /* Release the object attributes and temporary buffer */
2407 ObpReleaseCapturedAttributes(&TempBuffer
->ObjectCreateInfo
);
2408 if (ObjectName
.Buffer
) ObpFreeObjectNameBuffer(&ObjectName
);
2409 ExFreePool(TempBuffer
);
2412 OBTRACE(OB_HANDLE_DEBUG
,
2413 "%s - returning Object %p with PC S: %lx %lx\n",
2416 Object
? OBJECT_TO_OBJECT_HEADER(Object
)->PointerCount
: -1,
2422 * @name ObOpenObjectByPointer
2425 * The ObOpenObjectByPointer routine <FILLMEIN>
2430 * @param HandleAttributes
2433 * @param PassedAccessState
2436 * @param DesiredAccess
2448 * @return <FILLMEIN>.
2455 ObOpenObjectByPointer(IN PVOID Object
,
2456 IN ULONG HandleAttributes
,
2457 IN PACCESS_STATE PassedAccessState
,
2458 IN ACCESS_MASK DesiredAccess
,
2459 IN POBJECT_TYPE ObjectType
,
2460 IN KPROCESSOR_MODE AccessMode
,
2463 POBJECT_HEADER Header
;
2465 ACCESS_STATE AccessState
;
2469 /* Get the Header Info */
2470 Header
= OBJECT_TO_OBJECT_HEADER(Object
);
2472 /* Reference the object */
2473 Status
= ObReferenceObjectByPointer(Object
,
2477 if (!NT_SUCCESS(Status
)) return Status
;
2479 /* Check if we didn't get an access state */
2480 if (!PassedAccessState
)
2482 /* Use our built-in access state */
2483 PassedAccessState
= &AccessState
;
2484 Status
= SeCreateAccessState(&AccessState
,
2487 &Header
->Type
->TypeInfo
.GenericMapping
);
2488 if (!NT_SUCCESS(Status
))
2491 ObDereferenceObject(Object
);
2496 /* Create the handle */
2497 Status
= ObpCreateHandle(ObOpenHandle
,
2507 if (!NT_SUCCESS(Status
)) ObDereferenceObject(Object
);
2509 /* Delete the access state */
2510 if (PassedAccessState
== &AccessState
)
2512 SeDeleteAccessState(PassedAccessState
);
2516 OBTRACE(OB_HANDLE_DEBUG
,
2517 "%s - returning Object with PC S: %lx %lx\n",
2519 OBJECT_TO_OBJECT_HEADER(Object
)->PointerCount
,
2525 * @name ObFindHandleForObject
2528 * The ObFindHandleForObject routine <FILLMEIN>
2539 * @param HandleInformation
2542 * @param HandleReturn
2545 * @return <FILLMEIN>.
2552 ObFindHandleForObject(IN PEPROCESS Process
,
2554 IN POBJECT_TYPE ObjectType
,
2555 IN POBJECT_HANDLE_INFORMATION HandleInformation
,
2558 OBP_FIND_HANDLE_DATA FindData
;
2559 BOOLEAN Result
= FALSE
;
2561 /* Make sure we have an object table */
2562 if (Process
->ObjectTable
)
2564 /* Check if we have an object */
2567 /* Set its header */
2568 FindData
.ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
2572 /* Otherwise, no object to match*/
2573 FindData
.ObjectHeader
= NULL
;
2576 /* Set other information */
2577 FindData
.ObjectType
= ObjectType
;
2578 FindData
.HandleInformation
= HandleInformation
;
2580 /* Enumerate the handle table */
2581 if (ExEnumHandleTable(Process
->ObjectTable
,
2582 ObpEnumFindHandleProcedure
,
2591 /* Return the result */
2596 * @name ObInsertObject
2599 * The ObInsertObject routine <FILLMEIN>
2604 * @param PassedAccessState
2607 * @param DesiredAccess
2610 * @param AdditionalReferences
2613 * @param ReferencedObject
2619 * @return <FILLMEIN>.
2626 ObInsertObject(IN PVOID Object
,
2627 IN PACCESS_STATE AccessState OPTIONAL
,
2628 IN ACCESS_MASK DesiredAccess
,
2629 IN ULONG ObjectPointerBias
,
2630 OUT PVOID
*NewObject OPTIONAL
,
2633 POBJECT_CREATE_INFORMATION ObjectCreateInfo
;
2634 POBJECT_HEADER ObjectHeader
;
2635 POBJECT_TYPE ObjectType
;
2636 PUNICODE_STRING ObjectName
;
2638 PSECURITY_DESCRIPTOR ParentDescriptor
= NULL
;
2639 BOOLEAN SdAllocated
= FALSE
;
2640 POBJECT_HEADER_NAME_INFO ObjectNameInfo
;
2641 OBP_LOOKUP_CONTEXT Context
;
2642 ACCESS_STATE LocalAccessState
;
2644 OB_OPEN_REASON OpenReason
;
2645 KPROCESSOR_MODE PreviousMode
;
2646 NTSTATUS Status
= STATUS_SUCCESS
, RealStatus
;
2647 BOOLEAN IsNewObject
;
2650 /* Get the Header */
2651 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
2653 /* Detect invalid insert */
2654 if (!(ObjectHeader
->Flags
& OB_FLAG_CREATE_INFO
))
2656 /* Display warning and break into debugger */
2657 DPRINT1("OB: Attempting to insert existing object %08x\n", Object
);
2661 /* Allow debugger to continue */
2662 ObDereferenceObject(Object
);
2663 return STATUS_INVALID_PARAMETER
;
2666 /* Get the create and name info, as well as the object type */
2667 ObjectCreateInfo
= ObjectHeader
->ObjectCreateInfo
;
2668 ObjectNameInfo
= OBJECT_HEADER_TO_NAME_INFO(ObjectHeader
);
2669 ObjectType
= ObjectHeader
->Type
;
2671 /* Check if we have name information */
2674 /* Add a query reference */
2675 if (!ObpIncrementQueryReference(ObjectHeader
, ObjectNameInfo
))
2677 /* There are no query references, so the name info is invalid */
2678 ObjectNameInfo
= NULL
;
2682 /* Check if this is an named object */
2684 if ((ObjectNameInfo
) && (ObjectNameInfo
->Name
.Buffer
))
2686 /* Get the object name */
2687 ObjectName
= &ObjectNameInfo
->Name
;
2692 ((ObjectPointerBias
== 0) &&
2693 (ObjectName
== NULL
) &&
2694 (ObjectType
->TypeInfo
.SecurityRequired
) &&
2695 (NewObject
== NULL
)));
2697 /* Check if the object is unnamed and also doesn't have security */
2698 PreviousMode
= KeGetPreviousMode();
2699 if (!(ObjectType
->TypeInfo
.SecurityRequired
) && !(ObjectName
))
2701 /* Assume failure */
2704 /* Create the handle */
2705 Status
= ObpCreateUnnamedHandle(Object
,
2707 ObjectPointerBias
+ 1,
2708 ObjectCreateInfo
->Attributes
,
2713 /* Free the create information */
2714 ObpFreeAndReleaseCapturedAttributes(ObjectCreateInfo
);
2715 ObjectHeader
->ObjectCreateInfo
= NULL
;
2717 /* Remove a query reference if we added one */
2718 if (ObjectNameInfo
) ObpDecrementQueryReference(ObjectNameInfo
);
2720 /* Remove the extra keep-alive reference */
2721 ObDereferenceObject(Object
);
2724 OBTRACE(OB_HANDLE_DEBUG
,
2725 "%s - returning Object with PC S: %lx %lx\n",
2727 ObjectHeader
->PointerCount
,
2732 /* Check if we didn't get an access state */
2735 /* Use our built-in access state */
2736 AccessState
= &LocalAccessState
;
2737 Status
= SeCreateAccessState(&LocalAccessState
,
2740 &ObjectType
->TypeInfo
.GenericMapping
);
2741 if (!NT_SUCCESS(Status
))
2744 if (ObjectNameInfo
) ObpDecrementQueryReference(ObjectNameInfo
);
2745 ObDereferenceObject(Object
);
2750 /* Save the security descriptor */
2751 AccessState
->SecurityDescriptor
= ObjectCreateInfo
->SecurityDescriptor
;
2753 /* Validate the access mask */
2754 Status
= STATUS_SUCCESS
;//ObpValidateAccessMask(AccessState);
2755 if (!NT_SUCCESS(Status
))
2758 if (ObjectNameInfo
) ObpDecrementQueryReference(ObjectNameInfo
);
2759 ObDereferenceObject(Object
);
2763 /* Setup a lookup context */
2764 ObpInitializeDirectoryLookup(&Context
);
2765 InsertObject
= Object
;
2766 OpenReason
= ObCreateHandle
;
2768 /* Check if the object is named */
2772 Status
= ObpLookupObjectName(ObjectCreateInfo
->RootDirectory
,
2774 ObjectCreateInfo
->Attributes
,
2776 (ObjectHeader
->Flags
& OB_FLAG_KERNEL_MODE
) ?
2777 KernelMode
: UserMode
,
2778 ObjectCreateInfo
->ParseContext
,
2779 ObjectCreateInfo
->SecurityQos
,
2785 /* Check if we found an object that doesn't match the one requested */
2786 if ((NT_SUCCESS(Status
)) && (InsertObject
) && (Object
!= InsertObject
))
2788 /* This means we're opening an object, not creating a new one */
2789 OpenReason
= ObOpenHandle
;
2791 /* Make sure the caller said it's OK to do this */
2792 if (ObjectCreateInfo
->Attributes
& OBJ_OPENIF
)
2794 /* He did, but did he want this type? */
2795 if (ObjectType
!= OBJECT_TO_OBJECT_HEADER(InsertObject
)->Type
)
2797 /* Wrong type, so fail */
2798 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
2802 /* Right type, so warn */
2803 Status
= STATUS_OBJECT_NAME_EXISTS
;
2808 /* Caller wanted to create a new object, fail */
2809 Status
= STATUS_OBJECT_NAME_COLLISION
;
2813 /* Check if anything until now failed */
2814 if (!NT_SUCCESS(Status
))
2816 /* Cleanup after lookup */
2817 ObpCleanupDirectoryLookup(&Context
);
2819 /* Remove query reference that we added */
2820 if (ObjectNameInfo
) ObpDecrementQueryReference(ObjectNameInfo
);
2822 /* Dereference the object and delete the access state */
2823 ObDereferenceObject(Object
);
2824 if (AccessState
== &LocalAccessState
)
2826 /* We used a local one; delete it */
2827 SeDeleteAccessState(AccessState
);
2830 /* Return failure code */
2835 /* Check if this is a symbolic link */
2836 if (ObjectType
== ObSymbolicLinkType
)
2838 /* Create the internal name */
2839 ObpCreateSymbolicLinkName(Object
);
2844 /* Now check if this object is being created */
2845 if (InsertObject
== Object
)
2847 /* Check if it's named or forces security */
2848 if ((ObjectName
) || (ObjectType
->TypeInfo
.SecurityRequired
))
2850 /* Make sure it's inserted into an object directory */
2851 if ((ObjectNameInfo
) && (ObjectNameInfo
->Directory
))
2853 /* Get the current descriptor */
2854 ObGetObjectSecurity(ObjectNameInfo
->Directory
,
2860 Status
= ObAssignSecurity(AccessState
,
2865 /* Check if we captured one */
2866 if (ParentDescriptor
)
2868 /* We did, release it */
2869 ObReleaseObjectSecurity(ParentDescriptor
, SdAllocated
);
2871 else if (NT_SUCCESS(Status
))
2873 /* Other we didn't, but we were able to use the current SD */
2874 SeReleaseSecurityDescriptor(ObjectCreateInfo
->SecurityDescriptor
,
2875 ObjectCreateInfo
->ProbeMode
,
2878 /* Clear the current one */
2879 AccessState
->SecurityDescriptor
=
2880 ObjectCreateInfo
->SecurityDescriptor
= NULL
;
2884 /* Check if anything until now failed */
2885 if (!NT_SUCCESS(Status
))
2887 /* Cleanup lookup context */
2888 ObpCleanupDirectoryLookup(&Context
);
2890 /* Remove query reference that we added */
2891 if (ObjectNameInfo
) ObpDecrementQueryReference(ObjectNameInfo
);
2893 /* Dereference the object and delete the access state */
2894 ObDereferenceObject(Object
);
2895 if (AccessState
== &LocalAccessState
)
2897 /* We used a local one; delete it */
2898 SeDeleteAccessState(AccessState
);
2901 /* Return failure code */
2907 /* Save the actual status until here */
2908 RealStatus
= Status
;
2910 /* Check if caller wants us to create a handle */
2911 ObjectHeader
->ObjectCreateInfo
= NULL
;
2914 /* Create the handle */
2915 Status
= ObpCreateHandle(OpenReason
,
2919 ObjectPointerBias
+ 1,
2920 ObjectCreateInfo
->Attributes
,
2925 if (!NT_SUCCESS(Status
))
2927 /* If the object had a name, backout everything */
2928 if (ObjectName
) ObpDeleteNameCheck(Object
);
2930 /* Return the status of the failure */
2932 RealStatus
= Status
;
2935 /* Remove a query reference */
2936 if (ObjectNameInfo
) ObpDecrementQueryReference(ObjectNameInfo
);
2938 /* Remove the extra keep-alive reference */
2939 ObDereferenceObject(Object
);
2943 /* Otherwise, lock the object type */
2944 ObpEnterObjectTypeMutex(ObjectType
);
2946 /* And charge quota for the process to make it appear as used */
2947 RealStatus
= ObpChargeQuotaForObject(ObjectHeader
,
2951 /* Release the lock */
2952 ObpLeaveObjectTypeMutex(ObjectType
);
2954 /* Check if we failed and dereference the object if so */
2955 if (!NT_SUCCESS(RealStatus
)) ObDereferenceObject(Object
);
2958 /* We can delete the Create Info now */
2959 ObpFreeAndReleaseCapturedAttributes(ObjectCreateInfo
);
2961 /* Check if we created our own access state and delete it if so */
2962 if (AccessState
== &LocalAccessState
) SeDeleteAccessState(AccessState
);
2964 /* Return status code */
2965 OBTRACE(OB_HANDLE_DEBUG
,
2966 "%s - returning Object with PC S/RS: %lx %lx %lx\n",
2968 OBJECT_TO_OBJECT_HEADER(Object
)->PointerCount
,
2969 RealStatus
, Status
);
2974 * @name ObCloseHandle
2975 * @implemented NT5.1
2977 * The ObCloseHandle routine <FILLMEIN>
2985 * @return <FILLMEIN>.
2992 ObCloseHandle(IN HANDLE Handle
,
2993 IN KPROCESSOR_MODE AccessMode
)
2995 /* Call the internal API */
2996 return ObpCloseHandle(Handle
, AccessMode
);
3003 * The NtClose routine <FILLMEIN>
3008 * @return <FILLMEIN>.
3015 NtClose(IN HANDLE Handle
)
3017 /* Call the internal API */
3018 return ObpCloseHandle(Handle
, ExGetPreviousMode());
3023 NtDuplicateObject(IN HANDLE SourceProcessHandle
,
3024 IN HANDLE SourceHandle
,
3025 IN HANDLE TargetProcessHandle OPTIONAL
,
3026 OUT PHANDLE TargetHandle OPTIONAL
,
3027 IN ACCESS_MASK DesiredAccess
,
3028 IN ULONG HandleAttributes
,
3031 PEPROCESS SourceProcess
, TargetProcess
, Target
;
3033 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
3034 NTSTATUS Status
= STATUS_SUCCESS
;
3036 OBTRACE(OB_HANDLE_DEBUG
,
3037 "%s - Duplicating handle: %lx for %lx into %lx.\n",
3040 SourceProcessHandle
,
3041 TargetProcessHandle
);
3043 if((TargetHandle
) && (PreviousMode
!= KernelMode
))
3048 /* Probe the handle */
3049 ProbeForWriteHandle(TargetHandle
);
3053 /* Get the exception status */
3054 Status
= _SEH_GetExceptionCode();
3058 /* Fail if the pointer was invalid */
3059 if (!NT_SUCCESS(Status
)) return Status
;
3062 /* Now reference the input handle */
3063 Status
= ObReferenceObjectByHandle(SourceProcessHandle
,
3067 (PVOID
*)&SourceProcess
,
3069 if (!NT_SUCCESS(Status
)) return(Status
);
3071 /* Check if got a target handle */
3072 if (TargetProcessHandle
)
3074 /* Now reference the output handle */
3075 Status
= ObReferenceObjectByHandle(TargetProcessHandle
,
3079 (PVOID
*)&TargetProcess
,
3081 if (NT_SUCCESS(Status
))
3083 /* Use this target process */
3084 Target
= TargetProcess
;
3088 /* No target process */
3094 /* No target process */
3095 Status
= STATUS_SUCCESS
;
3099 /* Call the internal routine */
3100 Status
= ObDuplicateObject(SourceProcess
,
3109 /* Check if the caller wanted the return handle */
3112 /* Protect the write to user mode */
3115 /* Write the new handle */
3116 *TargetHandle
= hTarget
;
3120 /* Otherwise, get the exception code */
3121 Status
= _SEH_GetExceptionCode();
3126 /* Dereference the processes */
3127 OBTRACE(OB_HANDLE_DEBUG
,
3128 "%s - Duplicated handle: %lx into %lx S %lx\n",
3131 TargetProcessHandle
,
3133 ObDereferenceObject(Target
);
3134 ObDereferenceObject(SourceProcess
);
3138 #undef ObIsKernelHandle
3141 ObIsKernelHandle(IN HANDLE Handle
)
3143 /* We know we're kernel mode, so just check for the kernel handle flag */
3144 return (BOOLEAN
)((ULONG_PTR
)Handle
& KERNEL_HANDLE_FLAG
);