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 ******************************************************************/
20 PHANDLE_TABLE ObpKernelHandleTable
= NULL
;
21 ULONG ObpAccessProtectCloseBit
= MAXIMUM_ALLOWED
;
23 #define TAG_OB_HANDLE 'dHbO'
25 /* PRIVATE FUNCTIONS *********************************************************/
29 ObReferenceProcessHandleTable(IN PEPROCESS Process
)
31 PHANDLE_TABLE HandleTable
= NULL
;
33 /* Lock the process */
34 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
36 /* Get the handle table */
37 HandleTable
= Process
->ObjectTable
;
40 /* No table, release the lock */
41 ExReleaseRundownProtection(&Process
->RundownProtect
);
45 /* Return the handle table */
51 ObDereferenceProcessHandleTable(IN PEPROCESS Process
)
53 /* Release the process lock */
54 ExReleaseRundownProtection(&Process
->RundownProtect
);
59 ObGetProcessHandleCount(IN PEPROCESS Process
)
62 PHANDLE_TABLE HandleTable
;
66 /* Ensure the handle table doesn't go away while we use it */
67 HandleTable
= ObReferenceProcessHandleTable(Process
);
69 if (HandleTable
!= NULL
)
71 /* Count the number of handles the process has */
72 HandleCount
= HandleTable
->HandleCount
;
74 /* Let the handle table go */
75 ObDereferenceProcessHandleTable(Process
);
79 /* No handle table, no handles */
88 ObpReferenceProcessObjectByHandle(IN HANDLE Handle
,
90 IN PHANDLE_TABLE HandleTable
,
91 IN KPROCESSOR_MODE AccessMode
,
93 OUT POBJECT_HANDLE_INFORMATION HandleInformation
,
94 OUT PACCESS_MASK AuditMask
)
96 PHANDLE_TABLE_ENTRY HandleEntry
;
97 POBJECT_HEADER ObjectHeader
;
98 ACCESS_MASK GrantedAccess
;
100 PETHREAD Thread
= PsGetCurrentThread();
106 /* Check if this is a special handle */
107 if (HandleToLong(Handle
) < 0)
109 /* Check if the caller wants the current process */
110 if (Handle
== NtCurrentProcess())
112 /* Return handle info */
113 HandleInformation
->HandleAttributes
= 0;
114 HandleInformation
->GrantedAccess
= Process
->GrantedAccess
;
119 /* Reference ourselves */
120 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Process
);
121 InterlockedIncrement(&ObjectHeader
->PointerCount
);
123 /* Return the pointer */
125 ASSERT(*Object
!= NULL
);
126 return STATUS_SUCCESS
;
129 /* Check if the caller wants the current thread */
130 if (Handle
== NtCurrentThread())
132 /* Return handle information */
133 HandleInformation
->HandleAttributes
= 0;
134 HandleInformation
->GrantedAccess
= Thread
->GrantedAccess
;
136 /* Reference ourselves */
137 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Thread
);
138 InterlockedExchangeAdd(&ObjectHeader
->PointerCount
, 1);
143 /* Return the pointer */
145 ASSERT(*Object
!= NULL
);
146 return STATUS_SUCCESS
;
149 /* This is a kernel handle... do we have access? */
150 if (AccessMode
== KernelMode
)
152 /* Use the kernel handle table and get the actual handle value */
153 Handle
= ObKernelHandleToHandle(Handle
);
154 HandleTable
= ObpKernelHandleTable
;
158 /* This is an illegal attempt to access a kernel handle */
159 return STATUS_INVALID_HANDLE
;
163 /* Enter a critical region while we touch the handle table */
164 ASSERT(HandleTable
!= NULL
);
165 KeEnterCriticalRegion();
167 /* Get the handle entry */
168 HandleEntry
= ExMapHandleToPointer(HandleTable
, Handle
);
171 /* Get the object header and validate the type*/
172 ObjectHeader
= ObpGetHandleObject(HandleEntry
);
174 /* Get the granted access and validate it */
175 GrantedAccess
= HandleEntry
->GrantedAccess
;
177 /* Mask out the internal attributes */
178 Attributes
= HandleEntry
->ObAttributes
& OBJ_HANDLE_ATTRIBUTES
;
180 /* Fill out the information */
181 HandleInformation
->HandleAttributes
= Attributes
;
182 HandleInformation
->GrantedAccess
= GrantedAccess
;
184 /* No audit mask (FIXME!) */
187 /* Return the pointer */
188 *Object
= &ObjectHeader
->Body
;
190 /* Add a reference */
191 InterlockedExchangeAdd(&ObjectHeader
->PointerCount
, 1);
193 /* Unlock the handle */
194 ExUnlockHandleTableEntry(HandleTable
, HandleEntry
);
195 KeLeaveCriticalRegion();
198 ASSERT(*Object
!= NULL
);
199 return STATUS_SUCCESS
;
204 Status
= STATUS_INVALID_HANDLE
;
207 /* Return failure status */
208 KeLeaveCriticalRegion();
214 ObpEnumFindHandleProcedure(IN PHANDLE_TABLE_ENTRY HandleEntry
,
218 POBJECT_HEADER ObjectHeader
;
219 ACCESS_MASK GrantedAccess
;
220 ULONG HandleAttributes
;
221 POBP_FIND_HANDLE_DATA FindData
= Context
;
223 /* Get the object header */
224 ObjectHeader
= ObpGetHandleObject(HandleEntry
);
226 /* Make sure it's valid and matching */
227 if ((FindData
->ObjectHeader
) && (FindData
->ObjectHeader
!= ObjectHeader
))
233 /* Now attempt to match the object type */
234 if ((FindData
->ObjectType
) && (FindData
->ObjectType
!= ObjectHeader
->Type
))
240 /* Check if we have extra information */
241 if (FindData
->HandleInformation
)
243 /* Get the granted access and attributes */
244 GrantedAccess
= HandleEntry
->GrantedAccess
;
245 HandleAttributes
= HandleEntry
->ObAttributes
& OBJ_HANDLE_ATTRIBUTES
;
247 /* Attempt to match them */
248 if ((FindData
->HandleInformation
->HandleAttributes
!= HandleAttributes
) ||
249 (FindData
->HandleInformation
->GrantedAccess
!= GrantedAccess
))
256 /* We have a match */
260 POBJECT_HANDLE_COUNT_ENTRY
262 ObpInsertHandleCount(IN POBJECT_HEADER ObjectHeader
)
264 POBJECT_HEADER_HANDLE_INFO HandleInfo
;
265 POBJECT_HANDLE_COUNT_ENTRY FreeEntry
;
266 POBJECT_HANDLE_COUNT_DATABASE HandleDatabase
, OldHandleDatabase
;
269 OBJECT_HANDLE_COUNT_DATABASE SingleDatabase
;
272 /* Get the handle info */
273 HandleInfo
= OBJECT_HEADER_TO_HANDLE_INFO(ObjectHeader
);
274 if (!HandleInfo
) return NULL
;
276 /* Check if we only have one entry */
277 if (ObjectHeader
->Flags
& OB_FLAG_SINGLE_PROCESS
)
279 /* Fill out the single entry */
280 SingleDatabase
.CountEntries
= 1;
281 SingleDatabase
.HandleCountEntries
[0] = HandleInfo
->SingleEntry
;
283 /* Use this as the old size */
284 OldHandleDatabase
= &SingleDatabase
;
285 OldSize
= sizeof(SingleDatabase
);
287 /* Now we'll have two entries, and an entire DB */
289 Size
= sizeof(OBJECT_HANDLE_COUNT_DATABASE
) +
290 ((i
- 1) * sizeof(OBJECT_HANDLE_COUNT_ENTRY
));
294 /* We already have a DB, get the information from it */
295 OldHandleDatabase
= HandleInfo
->HandleCountDatabase
;
296 i
= OldHandleDatabase
->CountEntries
;
297 OldSize
= sizeof(OBJECT_HANDLE_COUNT_DATABASE
) +
298 ((i
- 1) * sizeof(OBJECT_HANDLE_COUNT_ENTRY
));
300 /* Add 4 more entries */
302 Size
= OldSize
+ (4 * sizeof(OBJECT_HANDLE_COUNT_ENTRY
));
305 /* Allocate the DB */
306 HandleDatabase
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_OB_HANDLE
);
307 if (!HandleDatabase
) return NULL
;
309 /* Copy the old database */
310 RtlCopyMemory(HandleDatabase
, OldHandleDatabase
, OldSize
);
312 /* Check if we he had a single entry before */
313 if (ObjectHeader
->Flags
& OB_FLAG_SINGLE_PROCESS
)
315 /* Now we have more */
316 ObjectHeader
->Flags
&= ~OB_FLAG_SINGLE_PROCESS
;
320 /* Otherwise we had a DB, free it */
321 ExFreePoolWithTag(OldHandleDatabase
, TAG_OB_HANDLE
);
324 /* Find the end of the copy and zero out the new data */
325 FreeEntry
= (PVOID
)((ULONG_PTR
)HandleDatabase
+ OldSize
);
326 RtlZeroMemory(FreeEntry
, Size
- OldSize
);
328 /* Set the new information and return the free entry */
329 HandleDatabase
->CountEntries
= i
;
330 HandleInfo
->HandleCountDatabase
= HandleDatabase
;
336 ObpIncrementHandleDataBase(IN POBJECT_HEADER ObjectHeader
,
337 IN PEPROCESS Process
,
338 IN OUT PULONG NewProcessHandleCount
)
340 POBJECT_HEADER_HANDLE_INFO HandleInfo
;
341 POBJECT_HANDLE_COUNT_ENTRY HandleEntry
, FreeEntry
= NULL
;
342 POBJECT_HANDLE_COUNT_DATABASE HandleDatabase
;
346 /* Get the handle info and check if we only have one entry */
347 HandleInfo
= OBJECT_HEADER_TO_HANDLE_INFO(ObjectHeader
);
348 if (ObjectHeader
->Flags
& OB_FLAG_SINGLE_PROCESS
)
350 /* Check if the entry is free */
351 if (!HandleInfo
->SingleEntry
.HandleCount
)
354 HandleInfo
->SingleEntry
.HandleCount
= 1;
355 HandleInfo
->SingleEntry
.Process
= Process
;
357 /* Return success and 1 handle */
358 *NewProcessHandleCount
= 1;
359 return STATUS_SUCCESS
;
361 else if (HandleInfo
->SingleEntry
.Process
== Process
)
363 /* Busy entry, but same process */
364 *NewProcessHandleCount
= ++HandleInfo
->SingleEntry
.HandleCount
;
365 return STATUS_SUCCESS
;
369 /* Insert a new entry */
370 FreeEntry
= ObpInsertHandleCount(ObjectHeader
);
371 if (!FreeEntry
) return STATUS_INSUFFICIENT_RESOURCES
;
372 ASSERT(!FreeEntry
->Process
);
373 ASSERT(!FreeEntry
->HandleCount
);
376 FreeEntry
->Process
= Process
;
377 FreeEntry
->HandleCount
= 1;
379 /* Return success and 1 handle */
380 *NewProcessHandleCount
= 1;
381 return STATUS_SUCCESS
;
385 /* We have a database instead */
386 HandleDatabase
= HandleInfo
->HandleCountDatabase
;
389 /* Get the entries and loop them */
390 i
= HandleDatabase
->CountEntries
;
391 HandleEntry
= &HandleDatabase
->HandleCountEntries
[0];
394 /* Check if this is a match */
395 if (HandleEntry
->Process
== Process
)
397 /* Found it, get the process handle count */
398 *NewProcessHandleCount
= ++HandleEntry
->HandleCount
;
399 return STATUS_SUCCESS
;
401 else if (!HandleEntry
->HandleCount
)
403 /* Found a free entry */
404 FreeEntry
= HandleEntry
;
412 /* Check if we couldn't find a free entry */
416 FreeEntry
= ObpInsertHandleCount(ObjectHeader
);
417 if (!FreeEntry
) return STATUS_INSUFFICIENT_RESOURCES
;
418 ASSERT(!FreeEntry
->Process
);
419 ASSERT(!FreeEntry
->HandleCount
);
422 /* Fill out the entry */
423 FreeEntry
->Process
= Process
;
424 FreeEntry
->HandleCount
= 1;
425 *NewProcessHandleCount
= 1;
428 /* Return success if we got here */
429 return STATUS_SUCCESS
;
434 ObpChargeQuotaForObject(IN POBJECT_HEADER ObjectHeader
,
435 IN POBJECT_TYPE ObjectType
,
436 OUT PBOOLEAN NewObject
)
438 POBJECT_HEADER_QUOTA_INFO ObjectQuota
;
439 ULONG PagedPoolCharge
, NonPagedPoolCharge
;
441 /* Get quota information */
442 ObjectQuota
= OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader
);
445 /* Check if this is a new object */
446 if (ObjectHeader
->Flags
& OB_FLAG_CREATE_INFO
)
448 /* Remove the flag */
449 ObjectHeader
->Flags
&= ~ OB_FLAG_CREATE_INFO
;
452 /* We have a quota, get the charges */
453 PagedPoolCharge
= ObjectQuota
->PagedPoolCharge
;
454 NonPagedPoolCharge
= ObjectQuota
->NonPagedPoolCharge
;
458 /* Get it from the object type */
459 PagedPoolCharge
= ObjectType
->TypeInfo
.DefaultPagedPoolCharge
;
460 NonPagedPoolCharge
= ObjectType
->TypeInfo
.DefaultNonPagedPoolCharge
;
463 /* Charge the quota */
464 ObjectHeader
->QuotaBlockCharged
= (PVOID
)1;
465 DPRINT("FIXME: Should charge: %lx %lx\n", PagedPoolCharge
, NonPagedPoolCharge
);
467 PsChargeSharedPoolQuota(PsGetCurrentProcess(),
472 /* Check if we don't have a quota block */
473 if (!ObjectHeader
->QuotaBlockCharged
) return STATUS_QUOTA_EXCEEDED
;
475 /* Now set the flag */
480 return STATUS_SUCCESS
;
485 ObpValidateAccessMask(IN PACCESS_STATE AccessState
)
488 return STATUS_SUCCESS
;
492 * @name ObpDecrementHandleCount
494 * The ObpDecrementHandleCount routine <FILLMEIN>
502 * @param GrantedAccess
512 ObpDecrementHandleCount(IN PVOID ObjectBody
,
513 IN PEPROCESS Process
,
514 IN ACCESS_MASK GrantedAccess
,
515 IN POBJECT_TYPE ObjectType
)
517 POBJECT_HEADER ObjectHeader
;
518 LONG SystemHandleCount
, ProcessHandleCount
;
521 POBJECT_HEADER_HANDLE_INFO HandleInfo
;
522 POBJECT_HANDLE_COUNT_ENTRY HandleEntry
;
523 POBJECT_HANDLE_COUNT_DATABASE HandleDatabase
;
527 /* Get the object type and header */
528 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(ObjectBody
);
529 OBTRACE(OB_HANDLE_DEBUG
,
530 "%s - Decrementing count for: %p. HC PC %lx %lx\n",
533 ObjectHeader
->HandleCount
,
534 ObjectHeader
->PointerCount
);
536 /* Lock the object */
537 ObpAcquireObjectLock(ObjectHeader
);
539 /* Set default counts */
540 SystemHandleCount
= ObjectHeader
->HandleCount
;
541 ProcessHandleCount
= 0;
543 /* Decrement the handle count */
544 NewCount
= InterlockedDecrement(&ObjectHeader
->HandleCount
);
546 /* Check if we're out of handles and this was an exclusive object */
547 if (!(NewCount
) && (ObjectHeader
->Flags
& OB_FLAG_EXCLUSIVE
))
549 /* Clear the exclusive flag */
550 OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader
)->ExclusiveProcess
= NULL
;
553 /* Is the object type keeping track of handles? */
554 if (ObjectType
->TypeInfo
.MaintainHandleCount
)
556 /* Get handle information */
557 HandleInfo
= OBJECT_HEADER_TO_HANDLE_INFO(ObjectHeader
);
559 /* Check if there's only a single entry */
560 if (ObjectHeader
->Flags
& OB_FLAG_SINGLE_PROCESS
)
562 /* It should be us */
563 ASSERT(HandleInfo
->SingleEntry
.Process
== Process
);
564 ASSERT(HandleInfo
->SingleEntry
.HandleCount
> 0);
566 /* Get the handle counts */
567 ProcessHandleCount
= HandleInfo
->SingleEntry
.HandleCount
--;
568 HandleEntry
= &HandleInfo
->SingleEntry
;
572 /* Otherwise, get the database */
573 HandleDatabase
= HandleInfo
->HandleCountDatabase
;
576 /* Get the entries and loop them */
577 i
= HandleDatabase
->CountEntries
;
578 HandleEntry
= &HandleDatabase
->HandleCountEntries
[0];
581 /* Check if this is a match */
582 if ((HandleEntry
->HandleCount
) &&
583 (HandleEntry
->Process
== Process
))
585 /* Found it, get the process handle count */
586 ProcessHandleCount
= HandleEntry
->HandleCount
--;
597 /* No database, so no entry */
602 /* Check if this is the last handle */
603 if (ProcessHandleCount
== 1)
605 /* Then clear the entry */
606 HandleEntry
->Process
= NULL
;
607 HandleEntry
->HandleCount
= 0;
611 /* Release the lock */
612 ObpReleaseObjectLock(ObjectHeader
);
614 /* Check if we have a close procedure */
615 if (ObjectType
->TypeInfo
.CloseProcedure
)
618 ObpCalloutStart(&CalloutIrql
);
619 ObjectType
->TypeInfo
.CloseProcedure(Process
,
624 ObpCalloutEnd(CalloutIrql
, "Close", ObjectType
, ObjectBody
);
627 /* Check if we should delete the object */
628 ObpDeleteNameCheck(ObjectBody
);
630 /* Decrease the total number of handles for this type */
631 InterlockedDecrement((PLONG
)&ObjectType
->TotalNumberOfHandles
);
632 OBTRACE(OB_HANDLE_DEBUG
,
633 "%s - Decremented count for: %p. HC PC %lx %lx\n",
636 ObjectHeader
->HandleCount
,
637 ObjectHeader
->PointerCount
);
641 * @name ObpCloseHandleTableEntry
643 * The ObpCloseHandleTableEntry routine <FILLMEIN>
657 * @param IgnoreHandleProtection
660 * @return <FILLMEIN>.
667 ObpCloseHandleTableEntry(IN PHANDLE_TABLE HandleTable
,
668 IN PHANDLE_TABLE_ENTRY HandleEntry
,
670 IN KPROCESSOR_MODE AccessMode
,
671 IN BOOLEAN IgnoreHandleProtection
)
674 POBJECT_TYPE ObjectType
;
675 POBJECT_HEADER ObjectHeader
;
676 ACCESS_MASK GrantedAccess
;
680 /* Get the object data */
681 ObjectHeader
= ObpGetHandleObject(HandleEntry
);
682 ObjectType
= ObjectHeader
->Type
;
683 Body
= &ObjectHeader
->Body
;
684 GrantedAccess
= HandleEntry
->GrantedAccess
;
685 OBTRACE(OB_HANDLE_DEBUG
,
686 "%s - Closing handle: %p for %p. HC PC %lx %lx\n",
690 ObjectHeader
->HandleCount
,
691 ObjectHeader
->PointerCount
);
693 /* Check if the object has an Okay To Close procedure */
694 if (ObjectType
->TypeInfo
.OkayToCloseProcedure
)
696 /* Call it and check if it's not letting us close it */
697 ObpCalloutStart(&CalloutIrql
);
698 if (!ObjectType
->TypeInfo
.OkayToCloseProcedure(PsGetCurrentProcess(),
704 ObpCalloutEnd(CalloutIrql
, "NtClose", ObjectType
, Body
);
705 ExUnlockHandleTableEntry(HandleTable
, HandleEntry
);
706 return STATUS_HANDLE_NOT_CLOSABLE
;
709 /* Success, validate callout retrn */
710 ObpCalloutEnd(CalloutIrql
, "NtClose", ObjectType
, Body
);
713 /* The callback allowed us to close it, but does the handle itself? */
714 if ((HandleEntry
->ObAttributes
& OBJ_PROTECT_CLOSE
) &&
715 !(IgnoreHandleProtection
))
717 /* It doesn't, are we from user mode? */
718 if (AccessMode
!= KernelMode
)
720 /* We are! Unlock the entry */
721 ExUnlockHandleTableEntry(HandleTable
, HandleEntry
);
723 /* Make sure we have a debug port */
724 if (PsGetCurrentProcess()->DebugPort
)
726 /* Raise an exception */
727 return KeRaiseUserException(STATUS_HANDLE_NOT_CLOSABLE
);
731 /* Return the error instead */
732 return STATUS_HANDLE_NOT_CLOSABLE
;
737 /* Otherwise, bugcheck the OS */
738 KeBugCheckEx(INVALID_KERNEL_HANDLE
, (ULONG_PTR
)Handle
, 0, 0, 0);
742 /* Destroy and unlock the handle entry */
743 ExDestroyHandle(HandleTable
, Handle
, HandleEntry
);
745 /* Now decrement the handle count */
746 ObpDecrementHandleCount(Body
,
747 PsGetCurrentProcess(),
751 /* Dereference the object as well */
752 ObDereferenceObject(Body
);
754 /* Return to caller */
755 OBTRACE(OB_HANDLE_DEBUG
,
756 "%s - Closed handle: %p for %p.\n",
760 return STATUS_SUCCESS
;
764 * @name ObpIncrementHandleCount
766 * The ObpIncrementHandleCount routine <FILLMEIN>
777 * @param HandleAttributes
786 * @return <FILLMEIN>.
793 ObpIncrementHandleCount(IN PVOID Object
,
794 IN PACCESS_STATE AccessState OPTIONAL
,
795 IN KPROCESSOR_MODE AccessMode
,
796 IN ULONG HandleAttributes
,
797 IN PEPROCESS Process
,
798 IN OB_OPEN_REASON OpenReason
)
800 POBJECT_HEADER ObjectHeader
;
801 POBJECT_TYPE ObjectType
;
802 ULONG ProcessHandleCount
;
804 PEPROCESS ExclusiveProcess
;
805 BOOLEAN Exclusive
= FALSE
, NewObject
;
806 POBJECT_HEADER_CREATOR_INFO CreatorInfo
;
808 KPROCESSOR_MODE ProbeMode
;
812 /* Get the object header and type */
813 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
814 ObjectType
= ObjectHeader
->Type
;
815 OBTRACE(OB_HANDLE_DEBUG
,
816 "%s - Incrementing count for: %p. Reason: %lx. HC PC %lx %lx\n",
820 ObjectHeader
->HandleCount
,
821 ObjectHeader
->PointerCount
);
823 /* Check if caller is forcing user mode */
824 if (HandleAttributes
& OBJ_FORCE_ACCESS_CHECK
)
827 ProbeMode
= UserMode
;
831 /* Keep original setting */
832 ProbeMode
= AccessMode
;
835 /* Lock the object */
836 ObpAcquireObjectLock(ObjectHeader
);
838 /* Charge quota and remove the creator info flag */
839 Status
= ObpChargeQuotaForObject(ObjectHeader
, ObjectType
, &NewObject
);
840 if (!NT_SUCCESS(Status
)) return Status
;
842 /* Check if the open is exclusive */
843 if (HandleAttributes
& OBJ_EXCLUSIVE
)
845 /* Check if the object allows this, or if the inherit flag was given */
846 if ((HandleAttributes
& OBJ_INHERIT
) ||
847 !(ObjectHeader
->Flags
& OB_FLAG_EXCLUSIVE
))
849 /* Incorrect attempt */
850 Status
= STATUS_INVALID_PARAMETER
;
854 /* Check if we have access to it */
855 ExclusiveProcess
= OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader
);
856 if ((!(ExclusiveProcess
) && (ObjectHeader
->HandleCount
)) ||
857 ((ExclusiveProcess
) && (ExclusiveProcess
!= PsGetCurrentProcess())))
859 /* This isn't the right process */
860 Status
= STATUS_ACCESS_DENIED
;
864 /* Now you got exclusive access */
867 else if ((ObjectHeader
->Flags
& OB_FLAG_EXCLUSIVE
) &&
868 (OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader
)))
870 /* Caller didn't want exclusive access, but the object is exclusive */
871 Status
= STATUS_ACCESS_DENIED
;
876 * Check if this is an object that went from 0 handles back to existence,
877 * but doesn't have an open procedure, only a close procedure. This means
878 * that it will never realize that the object is back alive, so we must
881 if (!(ObjectHeader
->HandleCount
) &&
883 (ObjectType
->TypeInfo
.MaintainHandleCount
) &&
884 !(ObjectType
->TypeInfo
.OpenProcedure
) &&
885 (ObjectType
->TypeInfo
.CloseProcedure
))
888 Status
= STATUS_UNSUCCESSFUL
;
892 /* Check if we're opening an existing handle */
893 if ((OpenReason
== ObOpenHandle
) ||
894 ((OpenReason
== ObDuplicateHandle
) && (AccessState
)))
896 /* Validate the caller's access to this object */
897 if (!ObCheckObjectAccess(Object
,
903 /* Access was denied, so fail */
907 else if (OpenReason
== ObCreateHandle
)
909 /* Convert MAXIMUM_ALLOWED to GENERIC_ALL */
910 if (AccessState
->RemainingDesiredAccess
& MAXIMUM_ALLOWED
)
912 /* Mask out MAXIMUM_ALLOWED and stick GENERIC_ALL instead */
913 AccessState
->RemainingDesiredAccess
&= ~MAXIMUM_ALLOWED
;
914 AccessState
->RemainingDesiredAccess
|= GENERIC_ALL
;
917 /* Check if we have to map the GENERIC mask */
918 if (AccessState
->RemainingDesiredAccess
& GENERIC_ACCESS
)
920 /* Map it to the correct access masks */
921 RtlMapGenericMask(&AccessState
->RemainingDesiredAccess
,
922 &ObjectType
->TypeInfo
.GenericMapping
);
925 /* Check if the caller is trying to access system security */
926 if (AccessState
->RemainingDesiredAccess
& ACCESS_SYSTEM_SECURITY
)
929 DPRINT1("ACCESS_SYSTEM_SECURITY not validated!\n");
933 /* Check if this is an exclusive handle */
936 /* Save the owner process */
937 OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader
)->ExclusiveProcess
= Process
;
940 /* Increase the handle count */
941 InterlockedIncrement(&ObjectHeader
->HandleCount
);
942 ProcessHandleCount
= 0;
944 /* Check if we have a handle database */
945 if (ObjectType
->TypeInfo
.MaintainHandleCount
)
947 /* Increment the handle database */
948 Status
= ObpIncrementHandleDataBase(ObjectHeader
,
950 &ProcessHandleCount
);
951 if (!NT_SUCCESS(Status
))
953 /* FIXME: This should never happen for now */
954 DPRINT1("Unhandled case\n");
960 /* Release the lock */
961 ObpReleaseObjectLock(ObjectHeader
);
963 /* Check if we have an open procedure */
964 Status
= STATUS_SUCCESS
;
965 if (ObjectType
->TypeInfo
.OpenProcedure
)
968 ObpCalloutStart(&CalloutIrql
);
969 Status
= ObjectType
->TypeInfo
.OpenProcedure(OpenReason
,
974 PreviouslyGrantedAccess
:
977 ObpCalloutEnd(CalloutIrql
, "Open", ObjectType
, Object
);
979 /* Check if the open procedure failed */
980 if (!NT_SUCCESS(Status
))
982 /* FIXME: This should never happen for now */
983 DPRINT1("Unhandled case\n");
989 /* Check if this is a create operation */
990 if (OpenReason
== ObCreateHandle
)
992 /* Check if we have creator info */
993 CreatorInfo
= OBJECT_HEADER_TO_CREATOR_INFO(ObjectHeader
);
996 /* We do, acquire the lock */
997 ObpEnterObjectTypeMutex(ObjectType
);
999 /* Insert us on the list */
1000 InsertTailList(&ObjectType
->TypeList
, &CreatorInfo
->TypeList
);
1002 /* Release the lock */
1003 ObpLeaveObjectTypeMutex(ObjectType
);
1007 /* Increase total number of handles */
1008 Total
= InterlockedIncrement((PLONG
)&ObjectType
->TotalNumberOfHandles
);
1009 if (Total
> ObjectType
->HighWaterNumberOfHandles
)
1012 ObjectType
->HighWaterNumberOfHandles
= Total
;
1015 /* Trace call and return */
1016 OBTRACE(OB_HANDLE_DEBUG
,
1017 "%s - Incremented count for: %p. Reason: %lx HC PC %lx %lx\n",
1021 ObjectHeader
->HandleCount
,
1022 ObjectHeader
->PointerCount
);
1026 /* Release lock and return */
1027 ObpReleaseObjectLock(ObjectHeader
);
1032 * @name ObpIncrementUnnamedHandleCount
1034 * The ObpIncrementUnnamedHandleCount routine <FILLMEIN>
1039 * @param AccessState
1045 * @param HandleAttributes
1054 * @return <FILLMEIN>.
1061 ObpIncrementUnnamedHandleCount(IN PVOID Object
,
1062 IN PACCESS_MASK DesiredAccess
,
1063 IN KPROCESSOR_MODE AccessMode
,
1064 IN ULONG HandleAttributes
,
1065 IN PEPROCESS Process
)
1067 POBJECT_HEADER ObjectHeader
;
1068 POBJECT_TYPE ObjectType
;
1069 ULONG ProcessHandleCount
;
1071 PEPROCESS ExclusiveProcess
;
1072 BOOLEAN Exclusive
= FALSE
, NewObject
;
1073 POBJECT_HEADER_CREATOR_INFO CreatorInfo
;
1077 /* Get the object header and type */
1078 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
1079 ObjectType
= ObjectHeader
->Type
;
1080 OBTRACE(OB_HANDLE_DEBUG
,
1081 "%s - Incrementing count for: %p. UNNAMED. HC PC %lx %lx\n",
1084 ObjectHeader
->HandleCount
,
1085 ObjectHeader
->PointerCount
);
1087 /* Lock the object */
1088 ObpAcquireObjectLock(ObjectHeader
);
1090 /* Charge quota and remove the creator info flag */
1091 Status
= ObpChargeQuotaForObject(ObjectHeader
, ObjectType
, &NewObject
);
1092 if (!NT_SUCCESS(Status
)) return Status
;
1094 /* Check if the open is exclusive */
1095 if (HandleAttributes
& OBJ_EXCLUSIVE
)
1097 /* Check if the object allows this, or if the inherit flag was given */
1098 if ((HandleAttributes
& OBJ_INHERIT
) ||
1099 !(ObjectHeader
->Flags
& OB_FLAG_EXCLUSIVE
))
1101 /* Incorrect attempt */
1102 Status
= STATUS_INVALID_PARAMETER
;
1106 /* Check if we have access to it */
1107 ExclusiveProcess
= OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader
);
1108 if ((!(ExclusiveProcess
) && (ObjectHeader
->HandleCount
)) ||
1109 ((ExclusiveProcess
) && (ExclusiveProcess
!= PsGetCurrentProcess())))
1111 /* This isn't the right process */
1112 Status
= STATUS_ACCESS_DENIED
;
1116 /* Now you got exclusive access */
1119 else if ((ObjectHeader
->Flags
& OB_FLAG_EXCLUSIVE
) &&
1120 (OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader
)))
1122 /* Caller didn't want exclusive access, but the object is exclusive */
1123 Status
= STATUS_ACCESS_DENIED
;
1128 * Check if this is an object that went from 0 handles back to existence,
1129 * but doesn't have an open procedure, only a close procedure. This means
1130 * that it will never realize that the object is back alive, so we must
1133 if (!(ObjectHeader
->HandleCount
) &&
1135 (ObjectType
->TypeInfo
.MaintainHandleCount
) &&
1136 !(ObjectType
->TypeInfo
.OpenProcedure
) &&
1137 (ObjectType
->TypeInfo
.CloseProcedure
))
1140 Status
= STATUS_UNSUCCESSFUL
;
1144 /* Convert MAXIMUM_ALLOWED to GENERIC_ALL */
1145 if (*DesiredAccess
& MAXIMUM_ALLOWED
)
1147 /* Mask out MAXIMUM_ALLOWED and stick GENERIC_ALL instead */
1148 *DesiredAccess
&= ~MAXIMUM_ALLOWED
;
1149 *DesiredAccess
|= GENERIC_ALL
;
1152 /* Check if we have to map the GENERIC mask */
1153 if (*DesiredAccess
& GENERIC_ACCESS
)
1155 /* Map it to the correct access masks */
1156 RtlMapGenericMask(DesiredAccess
,
1157 &ObjectType
->TypeInfo
.GenericMapping
);
1160 /* Check if this is an exclusive handle */
1163 /* Save the owner process */
1164 OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader
)->ExclusiveProcess
= Process
;
1167 /* Increase the handle count */
1168 InterlockedIncrement(&ObjectHeader
->HandleCount
);
1169 ProcessHandleCount
= 0;
1171 /* Check if we have a handle database */
1172 if (ObjectType
->TypeInfo
.MaintainHandleCount
)
1174 /* Increment the handle database */
1175 Status
= ObpIncrementHandleDataBase(ObjectHeader
,
1177 &ProcessHandleCount
);
1178 if (!NT_SUCCESS(Status
))
1180 /* FIXME: This should never happen for now */
1181 DPRINT1("Unhandled case\n");
1187 /* Release the lock */
1188 ObpReleaseObjectLock(ObjectHeader
);
1190 /* Check if we have an open procedure */
1191 Status
= STATUS_SUCCESS
;
1192 if (ObjectType
->TypeInfo
.OpenProcedure
)
1195 ObpCalloutStart(&CalloutIrql
);
1196 Status
= ObjectType
->TypeInfo
.OpenProcedure(ObCreateHandle
,
1200 ProcessHandleCount
);
1201 ObpCalloutEnd(CalloutIrql
, "Open", ObjectType
, Object
);
1203 /* Check if the open procedure failed */
1204 if (!NT_SUCCESS(Status
))
1206 /* FIXME: This should never happen for now */
1207 DPRINT1("Unhandled case\n");
1213 /* Check if we have creator info */
1214 CreatorInfo
= OBJECT_HEADER_TO_CREATOR_INFO(ObjectHeader
);
1217 /* We do, acquire the lock */
1218 ObpEnterObjectTypeMutex(ObjectType
);
1220 /* Insert us on the list */
1221 InsertTailList(&ObjectType
->TypeList
, &CreatorInfo
->TypeList
);
1223 /* Release the lock */
1224 ObpLeaveObjectTypeMutex(ObjectType
);
1227 /* Increase total number of handles */
1228 Total
= InterlockedIncrement((PLONG
)&ObjectType
->TotalNumberOfHandles
);
1229 if (Total
> ObjectType
->HighWaterNumberOfHandles
)
1232 ObjectType
->HighWaterNumberOfHandles
= Total
;
1235 /* Trace call and return */
1236 OBTRACE(OB_HANDLE_DEBUG
,
1237 "%s - Incremented count for: %p. UNNAMED HC PC %lx %lx\n",
1240 ObjectHeader
->HandleCount
,
1241 ObjectHeader
->PointerCount
);
1245 /* Release lock and return */
1246 ObpReleaseObjectLock(ObjectHeader
);
1251 * @name ObpCreateUnnamedHandle
1253 * The ObpCreateUnnamedHandle routine <FILLMEIN>
1258 * @param DesiredAccess
1261 * @param AdditionalReferences
1264 * @param HandleAttributes
1270 * @param ReturnedObject
1273 * @param ReturnedHandle
1276 * @return <FILLMEIN>.
1283 ObpCreateUnnamedHandle(IN PVOID Object
,
1284 IN ACCESS_MASK DesiredAccess
,
1285 IN ULONG AdditionalReferences
,
1286 IN ULONG HandleAttributes
,
1287 IN KPROCESSOR_MODE AccessMode
,
1288 OUT PVOID
*ReturnedObject
,
1289 OUT PHANDLE ReturnedHandle
)
1291 HANDLE_TABLE_ENTRY NewEntry
;
1292 POBJECT_HEADER ObjectHeader
;
1294 KAPC_STATE ApcState
;
1295 BOOLEAN AttachedToProcess
= FALSE
, KernelHandle
= FALSE
;
1298 ACCESS_MASK GrantedAccess
;
1299 POBJECT_TYPE ObjectType
;
1302 /* Get the object header and type */
1303 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
1304 ObjectType
= ObjectHeader
->Type
;
1305 OBTRACE(OB_HANDLE_DEBUG
,
1306 "%s - Creating handle for: %p. UNNAMED. HC PC %lx %lx\n",
1309 ObjectHeader
->HandleCount
,
1310 ObjectHeader
->PointerCount
);
1312 /* Save the object header */
1313 NewEntry
.Object
= ObjectHeader
;
1315 /* Mask out the internal attributes */
1316 NewEntry
.ObAttributes
|= HandleAttributes
& OBJ_HANDLE_ATTRIBUTES
;
1318 /* Check if this is a kernel handle */
1319 if (HandleAttributes
& OBJ_KERNEL_HANDLE
)
1321 /* Set the handle table */
1322 HandleTable
= ObpKernelHandleTable
;
1323 KernelHandle
= TRUE
;
1325 /* Check if we're not in the system process */
1326 if (PsGetCurrentProcess() != PsInitialSystemProcess
)
1328 /* Attach to the system process */
1329 KeStackAttachProcess(&PsInitialSystemProcess
->Pcb
, &ApcState
);
1330 AttachedToProcess
= TRUE
;
1335 /* Get the current handle table */
1336 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
1339 /* Increment the handle count */
1340 Status
= ObpIncrementUnnamedHandleCount(Object
,
1344 PsGetCurrentProcess());
1345 if (!NT_SUCCESS(Status
))
1348 * We failed (meaning security failure, according to NT Internals)
1351 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
1355 /* Remove what's not in the valid access mask */
1356 GrantedAccess
= DesiredAccess
& (ObjectType
->TypeInfo
.ValidAccessMask
|
1357 ACCESS_SYSTEM_SECURITY
);
1359 /* Handle extra references */
1360 if (AdditionalReferences
)
1362 /* Add them to the header */
1363 InterlockedExchangeAdd(&ObjectHeader
->PointerCount
,
1364 AdditionalReferences
);
1367 /* Save the access mask */
1368 NewEntry
.GrantedAccess
= GrantedAccess
;
1371 * Create the actual handle. We'll need to do this *after* calling
1372 * ObpIncrementHandleCount to make sure that Object Security is valid
1373 * (specified in Gl00my documentation on Ob)
1375 OBTRACE(OB_HANDLE_DEBUG
,
1376 "%s - Handle Properties: [%p-%lx-%lx]\n",
1378 NewEntry
.Object
, NewEntry
.ObAttributes
& 3, NewEntry
.GrantedAccess
);
1379 Handle
= ExCreateHandle(HandleTable
, &NewEntry
);
1381 /* Make sure we got a handle */
1384 /* Check if this was a kernel handle */
1385 if (KernelHandle
) Handle
= ObMarkHandleAsKernelHandle(Handle
);
1387 /* Return handle and object */
1388 *ReturnedHandle
= Handle
;
1390 /* Return the new object only if caller wanted it biased */
1391 if ((AdditionalReferences
) && (ReturnedObject
))
1394 *ReturnedObject
= Object
;
1397 /* Detach if needed */
1398 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
1400 /* Trace and return */
1401 OBTRACE(OB_HANDLE_DEBUG
,
1402 "%s - Returning Handle: %p HC PC %lx %lx\n",
1405 ObjectHeader
->HandleCount
,
1406 ObjectHeader
->PointerCount
);
1407 return STATUS_SUCCESS
;
1410 /* Handle extra references */
1411 if (AdditionalReferences
)
1413 /* Dereference it as many times as required */
1414 InterlockedExchangeAdd(&ObjectHeader
->PointerCount
,
1415 -(LONG
)AdditionalReferences
);
1418 /* Decrement the handle count and detach */
1419 ObpDecrementHandleCount(&ObjectHeader
->Body
,
1420 PsGetCurrentProcess(),
1424 /* Detach and fail */
1425 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
1426 return STATUS_INSUFFICIENT_RESOURCES
;
1430 * @name ObpCreateHandle
1432 * The ObpCreateHandle routine <FILLMEIN>
1443 * @param AccessState
1446 * @param AdditionalReferences
1449 * @param HandleAttributes
1455 * @param ReturnedObject
1458 * @param ReturnedHandle
1461 * @return <FILLMEIN>.
1463 * @remarks Cleans up the Lookup Context on return.
1468 ObpCreateHandle(IN OB_OPEN_REASON OpenReason
,
1470 IN POBJECT_TYPE Type OPTIONAL
,
1471 IN PACCESS_STATE AccessState
,
1472 IN ULONG AdditionalReferences
,
1473 IN ULONG HandleAttributes
,
1474 IN POBP_LOOKUP_CONTEXT Context
,
1475 IN KPROCESSOR_MODE AccessMode
,
1476 OUT PVOID
*ReturnedObject
,
1477 OUT PHANDLE ReturnedHandle
)
1479 HANDLE_TABLE_ENTRY NewEntry
;
1480 POBJECT_HEADER ObjectHeader
;
1482 KAPC_STATE ApcState
;
1483 BOOLEAN AttachedToProcess
= FALSE
, KernelHandle
= FALSE
;
1484 POBJECT_TYPE ObjectType
;
1487 ACCESS_MASK DesiredAccess
, GrantedAccess
;
1488 PAUX_ACCESS_DATA AuxData
;
1491 /* Get the object header and type */
1492 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
1493 ObjectType
= ObjectHeader
->Type
;
1494 OBTRACE(OB_HANDLE_DEBUG
,
1495 "%s - Creating handle for: %p. Reason: %lx. HC PC %lx %lx\n",
1499 ObjectHeader
->HandleCount
,
1500 ObjectHeader
->PointerCount
);
1502 /* Check if the types match */
1503 if ((Type
) && (ObjectType
!= Type
))
1505 /* They don't, cleanup */
1506 if (Context
) ObpReleaseLookupContext(Context
);
1507 return STATUS_OBJECT_TYPE_MISMATCH
;
1510 /* Save the object header */
1511 NewEntry
.Object
= ObjectHeader
;
1513 /* Check if this is a kernel handle */
1514 if (HandleAttributes
& OBJ_KERNEL_HANDLE
)
1516 /* Set the handle table */
1517 HandleTable
= ObpKernelHandleTable
;
1518 KernelHandle
= TRUE
;
1520 /* Check if we're not in the system process */
1521 if (PsGetCurrentProcess() != PsInitialSystemProcess
)
1523 /* Attach to the system process */
1524 KeStackAttachProcess(&PsInitialSystemProcess
->Pcb
, &ApcState
);
1525 AttachedToProcess
= TRUE
;
1530 /* Get the current handle table */
1531 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
1534 /* Increment the handle count */
1535 Status
= ObpIncrementHandleCount(Object
,
1539 PsGetCurrentProcess(),
1541 if (!NT_SUCCESS(Status
))
1544 * We failed (meaning security failure, according to NT Internals)
1547 if (Context
) ObpReleaseLookupContext(Context
);
1548 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
1552 /* Check if we are doing audits on close */
1553 if (AccessState
->GenerateOnClose
)
1555 /* Force the attribute on */
1556 HandleAttributes
|= OBJ_AUDIT_OBJECT_CLOSE
;
1559 /* Mask out the internal attributes */
1560 NewEntry
.ObAttributes
|= (HandleAttributes
& OBJ_HANDLE_ATTRIBUTES
);
1562 /* Get the original desired access */
1563 DesiredAccess
= AccessState
->RemainingDesiredAccess
|
1564 AccessState
->PreviouslyGrantedAccess
;
1566 /* Remove what's not in the valid access mask */
1567 GrantedAccess
= DesiredAccess
& (ObjectType
->TypeInfo
.ValidAccessMask
|
1568 ACCESS_SYSTEM_SECURITY
);
1570 /* Update the value in the access state */
1571 AccessState
->PreviouslyGrantedAccess
= GrantedAccess
;
1573 /* Get the auxiliary data */
1574 AuxData
= AccessState
->AuxData
;
1576 /* Handle extra references */
1577 if (AdditionalReferences
)
1579 /* Add them to the header */
1580 InterlockedExchangeAdd(&ObjectHeader
->PointerCount
, AdditionalReferences
);
1583 /* Now we can release the object */
1584 if (Context
) ObpReleaseLookupContext(Context
);
1586 /* Save the access mask */
1587 NewEntry
.GrantedAccess
= GrantedAccess
;
1590 * Create the actual handle. We'll need to do this *after* calling
1591 * ObpIncrementHandleCount to make sure that Object Security is valid
1592 * (specified in Gl00my documentation on Ob)
1594 OBTRACE(OB_HANDLE_DEBUG
,
1595 "%s - Handle Properties: [%p-%lx-%lx]\n",
1597 NewEntry
.Object
, NewEntry
.ObAttributes
& 3, NewEntry
.GrantedAccess
);
1598 Handle
= ExCreateHandle(HandleTable
, &NewEntry
);
1600 /* Make sure we got a handle */
1603 /* Check if this was a kernel handle */
1604 if (KernelHandle
) Handle
= ObMarkHandleAsKernelHandle(Handle
);
1607 *ReturnedHandle
= Handle
;
1609 /* Check if we need to generate on audit */
1610 if (AccessState
->GenerateAudit
)
1612 /* Audit the handle creation */
1613 //SeAuditHandleCreation(AccessState, Handle);
1616 /* Check if this was a create */
1617 if (OpenReason
== ObCreateHandle
)
1619 /* Check if we need to audit the privileges */
1620 if ((AuxData
->PrivilegeSet
) &&
1621 (AuxData
->PrivilegeSet
->PrivilegeCount
))
1625 SePrivilegeObjectAuditAlarm(Handle
,
1627 SubjectSecurityContext
,
1629 AuxData
->PrivilegeSet
,
1631 ExGetPreviousMode());
1636 /* Return the new object only if caller wanted it biased */
1637 if ((AdditionalReferences
) && (ReturnedObject
))
1640 *ReturnedObject
= Object
;
1643 /* Detach if needed */
1644 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
1646 /* Trace and return */
1647 OBTRACE(OB_HANDLE_DEBUG
,
1648 "%s - Returning Handle: %p HC PC %lx %lx\n",
1651 ObjectHeader
->HandleCount
,
1652 ObjectHeader
->PointerCount
);
1653 return STATUS_SUCCESS
;
1656 /* Decrement the handle count and detach */
1657 ObpDecrementHandleCount(&ObjectHeader
->Body
,
1658 PsGetCurrentProcess(),
1662 /* Handle extra references */
1663 if (AdditionalReferences
)
1665 /* Check how many extra references were added */
1666 if (AdditionalReferences
> 1)
1668 /* Dereference it many times */
1669 InterlockedExchangeAdd(&ObjectHeader
->PointerCount
,
1670 -(LONG
)(AdditionalReferences
- 1));
1673 /* Dereference the object one last time */
1674 ObDereferenceObject(Object
);
1677 /* Detach if necessary and fail */
1678 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
1679 return STATUS_INSUFFICIENT_RESOURCES
;
1683 * @name ObpCloseHandle
1685 * The ObpCloseHandle routine <FILLMEIN>
1693 * @return <FILLMEIN>.
1700 ObpCloseHandle(IN HANDLE Handle
,
1701 IN KPROCESSOR_MODE AccessMode
)
1704 BOOLEAN AttachedToProcess
= FALSE
;
1705 KAPC_STATE ApcState
;
1706 PHANDLE_TABLE_ENTRY HandleTableEntry
;
1708 PEPROCESS Process
= PsGetCurrentProcess();
1710 OBTRACE(OB_HANDLE_DEBUG
,
1711 "%s - Closing handle: %p\n", __FUNCTION__
, Handle
);
1713 if (AccessMode
== KernelMode
&& Handle
== (HANDLE
)-1)
1714 return STATUS_INVALID_HANDLE
;
1716 /* Check if we're dealing with a kernel handle */
1717 if (ObpIsKernelHandle(Handle
, AccessMode
))
1719 /* Use the kernel table and convert the handle */
1720 HandleTable
= ObpKernelHandleTable
;
1721 Handle
= ObKernelHandleToHandle(Handle
);
1723 /* Check if we're not in the system process */
1724 if (Process
!= PsInitialSystemProcess
)
1726 /* Attach to the system process */
1727 KeStackAttachProcess(&PsInitialSystemProcess
->Pcb
, &ApcState
);
1728 AttachedToProcess
= TRUE
;
1733 /* Use the process's handle table */
1734 HandleTable
= Process
->ObjectTable
;
1737 /* Enter a critical region to protect handle access */
1738 KeEnterCriticalRegion();
1740 /* Get the handle entry */
1741 HandleTableEntry
= ExMapHandleToPointer(HandleTable
, Handle
);
1742 if (HandleTableEntry
)
1744 /* Now close the entry */
1745 Status
= ObpCloseHandleTableEntry(HandleTable
,
1751 /* We can quit the critical region now */
1752 KeLeaveCriticalRegion();
1754 /* Detach and return success */
1755 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
1759 /* We failed, quit the critical region */
1760 KeLeaveCriticalRegion();
1763 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
1765 /* Check if we have a valid handle that's not the process or thread */
1767 (Handle
!= NtCurrentProcess()) &&
1768 (Handle
!= NtCurrentThread()))
1770 /* Check if we came from user mode */
1771 if (AccessMode
!= KernelMode
)
1773 /* Check if we have no debug port */
1774 if (Process
->DebugPort
)
1776 /* Make sure we're not attached */
1777 if (!KeIsAttachedProcess())
1779 /* Raise an exception */
1780 return KeRaiseUserException(STATUS_INVALID_HANDLE
);
1786 /* This is kernel mode. Check if we're exiting */
1787 if (!(PsIsThreadTerminating(PsGetCurrentThread())) &&
1790 /* Check if the debugger is enabled */
1791 if (KdDebuggerEnabled
)
1794 KeBugCheckEx(INVALID_KERNEL_HANDLE
, (ULONG_PTR
)Handle
, 1, 0, 0);
1800 /* Set invalid status */
1801 Status
= STATUS_INVALID_HANDLE
;
1805 OBTRACE(OB_HANDLE_DEBUG
,
1806 "%s - Closed handle: %p S: %lx\n",
1807 __FUNCTION__
, Handle
, Status
);
1812 * @name ObpSetHandleAttributes
1814 * The ObpSetHandleAttributes routine <FILLMEIN>
1816 * @param HandleTableEntry
1822 * @return <FILLMEIN>.
1829 ObpSetHandleAttributes(IN OUT PHANDLE_TABLE_ENTRY HandleTableEntry
,
1830 IN ULONG_PTR Context
)
1832 POBP_SET_HANDLE_ATTRIBUTES_CONTEXT SetHandleInfo
= (PVOID
)Context
;
1833 POBJECT_HEADER ObjectHeader
= ObpGetHandleObject(HandleTableEntry
);
1835 /* Check if making the handle inheritable */
1836 if (SetHandleInfo
->Information
.Inherit
)
1838 /* Check if inheriting is not supported for this object */
1839 if (ObjectHeader
->Type
->TypeInfo
.InvalidAttributes
& OBJ_INHERIT
)
1841 /* Fail without changing anything */
1846 HandleTableEntry
->ObAttributes
|= OBJ_INHERIT
;
1850 /* Otherwise this implies we're removing the flag */
1851 HandleTableEntry
->ObAttributes
&= ~OBJ_INHERIT
;
1854 /* Check if making the handle protected */
1855 if (SetHandleInfo
->Information
.ProtectFromClose
)
1858 HandleTableEntry
->GrantedAccess
|= ObpAccessProtectCloseBit
;
1862 /* Otherwise, remove it */
1863 HandleTableEntry
->GrantedAccess
&= ~ObpAccessProtectCloseBit
;
1866 /* Return success */
1871 * @name ObpCloseHandleCallback
1873 * The ObpCloseHandleCallback routine <FILLMEIN>
1875 * @param HandleTable
1881 * @param GrantedAccess
1887 * @return <FILLMEIN>.
1894 ObpCloseHandleCallback(IN PHANDLE_TABLE_ENTRY HandleTableEntry
,
1898 POBP_CLOSE_HANDLE_CONTEXT CloseContext
= (POBP_CLOSE_HANDLE_CONTEXT
)Context
;
1900 /* Simply decrement the handle count */
1901 ObpCloseHandleTableEntry(CloseContext
->HandleTable
,
1904 CloseContext
->AccessMode
,
1910 * @name ObpDuplicateHandleCallback
1912 * The ObpDuplicateHandleCallback routine <FILLMEIN>
1914 * @param HandleTable
1917 * @param HandleTableEntry
1923 * @return <FILLMEIN>.
1930 ObpDuplicateHandleCallback(IN PEPROCESS Process
,
1931 IN PHANDLE_TABLE HandleTable
,
1932 IN PHANDLE_TABLE_ENTRY OldEntry
,
1933 IN PHANDLE_TABLE_ENTRY HandleTableEntry
)
1935 POBJECT_HEADER ObjectHeader
;
1936 BOOLEAN Ret
= FALSE
;
1937 ACCESS_STATE AccessState
;
1941 /* Make sure that the handle is inheritable */
1942 Ret
= (HandleTableEntry
->ObAttributes
& OBJ_INHERIT
) != 0;
1945 /* Get the object header */
1946 ObjectHeader
= ObpGetHandleObject(HandleTableEntry
);
1948 /* Increment the pointer count */
1949 InterlockedIncrement(&ObjectHeader
->PointerCount
);
1951 /* Release the handle lock */
1952 ExUnlockHandleTableEntry(HandleTable
, OldEntry
);
1954 /* Setup the access state */
1955 AccessState
.PreviouslyGrantedAccess
= HandleTableEntry
->GrantedAccess
;
1957 /* Call the shared routine for incrementing handles */
1958 Status
= ObpIncrementHandleCount(&ObjectHeader
->Body
,
1961 HandleTableEntry
->ObAttributes
& OBJ_HANDLE_ATTRIBUTES
,
1964 if (!NT_SUCCESS(Status
))
1966 /* Return failure */
1967 ObDereferenceObject(&ObjectHeader
->Body
);
1973 /* Release the handle lock */
1974 ExUnlockHandleTableEntry(HandleTable
, OldEntry
);
1977 /* Return duplication result */
1983 ObClearProcessHandleTable(IN PEPROCESS Process
)
1989 * @name ObpCreateHandleTable
1991 * The ObpCreateHandleTable routine <FILLMEIN>
1999 * @return <FILLMEIN>.
2006 ObInitProcess(IN PEPROCESS Parent OPTIONAL
,
2007 IN PEPROCESS Process
)
2009 PHANDLE_TABLE ParentTable
, ObjectTable
;
2011 /* Check for a parent */
2014 /* Reference the parent's table */
2015 ParentTable
= ObReferenceProcessHandleTable(Parent
);
2016 if (!ParentTable
) return STATUS_PROCESS_IS_TERMINATING
;
2019 ObjectTable
= ExDupHandleTable(Process
,
2021 ObpDuplicateHandleCallback
,
2026 /* Otherwise just create a new table */
2028 ObjectTable
= ExCreateHandleTable(Process
);
2031 /* Make sure we have a table */
2035 Process
->ObjectTable
= ObjectTable
;
2037 /* Check for auditing */
2038 if (SeDetailedAuditingWithToken(NULL
))
2041 DPRINT1("Need auditing!\n");
2044 /* Get rid of the old table now */
2045 if (ParentTable
) ObDereferenceProcessHandleTable(Parent
);
2048 return STATUS_SUCCESS
;
2053 Process
->ObjectTable
= NULL
;
2054 if (ParentTable
) ObDereferenceProcessHandleTable(Parent
);
2055 return STATUS_INSUFFICIENT_RESOURCES
;
2060 * @name ObKillProcess
2062 * The ObKillProcess routine <FILLMEIN>
2074 ObKillProcess(IN PEPROCESS Process
)
2076 PHANDLE_TABLE HandleTable
;
2077 OBP_CLOSE_HANDLE_CONTEXT Context
;
2081 /* Wait for process rundown and then complete it */
2082 ExWaitForRundownProtectionRelease(&Process
->RundownProtect
);
2083 ExRundownCompleted(&Process
->RundownProtect
);
2085 /* Get the object table */
2086 HandleTable
= Process
->ObjectTable
;
2087 if (!HandleTable
) return;
2089 /* Disable hard errors while we close handles */
2090 HardErrors
= IoSetThreadHardErrorMode(FALSE
);
2092 /* Enter a critical region */
2093 KeEnterCriticalRegion();
2095 /* Fill out the context */
2096 Context
.AccessMode
= KernelMode
;
2097 Context
.HandleTable
= HandleTable
;
2099 /* Sweep the handle table to close all handles */
2100 ExSweepHandleTable(HandleTable
,
2101 ObpCloseHandleCallback
,
2103 ASSERT(HandleTable
->HandleCount
== 0);
2105 /* Leave the critical region */
2106 KeLeaveCriticalRegion();
2108 /* Re-enable hard errors */
2109 IoSetThreadHardErrorMode(HardErrors
);
2111 /* Destroy the object table */
2112 Process
->ObjectTable
= NULL
;
2113 ExDestroyHandleTable(HandleTable
, NULL
);
2118 ObDuplicateObject(IN PEPROCESS SourceProcess
,
2119 IN HANDLE SourceHandle
,
2120 IN PEPROCESS TargetProcess OPTIONAL
,
2121 IN PHANDLE TargetHandle OPTIONAL
,
2122 IN ACCESS_MASK DesiredAccess
,
2123 IN ULONG HandleAttributes
,
2125 IN KPROCESSOR_MODE PreviousMode
)
2127 HANDLE_TABLE_ENTRY NewHandleEntry
;
2128 BOOLEAN AttachedToProcess
= FALSE
;
2130 POBJECT_HEADER ObjectHeader
;
2131 POBJECT_TYPE ObjectType
;
2133 KAPC_STATE ApcState
;
2135 ACCESS_MASK TargetAccess
, SourceAccess
;
2136 ACCESS_STATE AccessState
;
2137 PACCESS_STATE PassedAccessState
= NULL
;
2138 AUX_ACCESS_DATA AuxData
;
2139 PHANDLE_TABLE HandleTable
;
2140 OBJECT_HANDLE_INFORMATION HandleInformation
;
2143 OBTRACE(OB_HANDLE_DEBUG
,
2144 "%s - Duplicating handle: %p for %p into %p\n",
2150 /* Assume failure */
2151 if (TargetHandle
) *TargetHandle
= NULL
;
2153 /* Check if we're not duplicating the same access */
2154 if (!(Options
& DUPLICATE_SAME_ACCESS
))
2156 /* Validate the desired access */
2157 Status
= STATUS_SUCCESS
; //ObpValidateDesiredAccess(DesiredAccess);
2158 if (!NT_SUCCESS(Status
)) return Status
;
2161 /* Reference the object table */
2162 HandleTable
= ObReferenceProcessHandleTable(SourceProcess
);
2163 if (!HandleTable
) return STATUS_PROCESS_IS_TERMINATING
;
2165 /* Reference the process object */
2166 Status
= ObpReferenceProcessObjectByHandle(SourceHandle
,
2173 if (!NT_SUCCESS(Status
))
2176 ObDereferenceProcessHandleTable(SourceProcess
);
2181 /* Check if we have to don't have to audit object close */
2182 if (!(HandleInformation
.HandleAttributes
& OBJ_AUDIT_OBJECT_CLOSE
))
2184 /* Then there is no audit mask */
2189 /* Check if there's no target process */
2192 /* Check if the caller wanted actual duplication */
2193 if (!(Options
& DUPLICATE_CLOSE_SOURCE
))
2195 /* Invalid request */
2196 Status
= STATUS_INVALID_PARAMETER
;
2200 /* Otherwise, do the attach */
2201 KeStackAttachProcess(&SourceProcess
->Pcb
, &ApcState
);
2203 /* Close the handle and detach */
2204 NtClose(SourceHandle
);
2205 KeUnstackDetachProcess(&ApcState
);
2209 ObDereferenceProcessHandleTable(SourceProcess
);
2210 ObDereferenceObject(SourceObject
);
2214 /* Get the target handle table */
2215 HandleTable
= ObReferenceProcessHandleTable(TargetProcess
);
2218 /* Check if the caller wanted us to close the handle */
2219 if (Options
& DUPLICATE_CLOSE_SOURCE
)
2222 KeStackAttachProcess(&SourceProcess
->Pcb
, &ApcState
);
2224 /* Close the handle and detach */
2225 NtClose(SourceHandle
);
2226 KeUnstackDetachProcess(&ApcState
);
2230 ObDereferenceProcessHandleTable(SourceProcess
);
2231 ObDereferenceObject(SourceObject
);
2232 return STATUS_PROCESS_IS_TERMINATING
;
2235 /* Get the source access */
2236 SourceAccess
= HandleInformation
.GrantedAccess
;
2238 /* Check if we're not in the target process */
2239 if (TargetProcess
!= PsGetCurrentProcess())
2242 KeStackAttachProcess(&TargetProcess
->Pcb
, &ApcState
);
2243 AttachedToProcess
= TRUE
;
2246 /* Check if we're duplicating the attributes */
2247 if (Options
& DUPLICATE_SAME_ATTRIBUTES
)
2249 /* Duplicate them */
2250 HandleAttributes
= HandleInformation
.HandleAttributes
;
2254 /* Don't allow caller to bypass auditing */
2255 HandleAttributes
|= HandleInformation
.HandleAttributes
&
2256 OBJ_AUDIT_OBJECT_CLOSE
;
2259 /* Check if we're duplicating the access */
2260 if (Options
& DUPLICATE_SAME_ACCESS
) DesiredAccess
= SourceAccess
;
2262 /* Get object data */
2263 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(SourceObject
);
2264 ObjectType
= ObjectHeader
->Type
;
2266 /* Fill out the entry */
2267 RtlZeroMemory(&NewHandleEntry
, sizeof(HANDLE_TABLE_ENTRY
));
2268 NewHandleEntry
.Object
= ObjectHeader
;
2269 NewHandleEntry
.ObAttributes
|= (HandleAttributes
& OBJ_HANDLE_ATTRIBUTES
);
2271 /* Check if we're using a generic mask */
2272 if (DesiredAccess
& GENERIC_ACCESS
)
2275 RtlMapGenericMask(&DesiredAccess
,
2276 &ObjectType
->TypeInfo
.GenericMapping
);
2279 /* Set the target access, always propagate ACCESS_SYSTEM_SECURITY */
2280 TargetAccess
= DesiredAccess
& (ObjectType
->TypeInfo
.ValidAccessMask
|
2281 ACCESS_SYSTEM_SECURITY
);
2282 NewHandleEntry
.GrantedAccess
= TargetAccess
;
2284 /* Check if we're asking for new access */
2285 if (TargetAccess
& ~SourceAccess
)
2287 /* We are. We need the security procedure to validate this */
2288 if (ObjectType
->TypeInfo
.SecurityProcedure
== SeDefaultObjectMethod
)
2290 /* Use our built-in access state */
2291 PassedAccessState
= &AccessState
;
2292 Status
= SeCreateAccessState(&AccessState
,
2295 &ObjectType
->TypeInfo
.GenericMapping
);
2299 /* Otherwise we can't allow this privilege elevation */
2300 Status
= STATUS_ACCESS_DENIED
;
2305 /* We don't need an access state */
2306 Status
= STATUS_SUCCESS
;
2309 /* Make sure the access state was created OK */
2310 if (NT_SUCCESS(Status
))
2312 /* Add a new handle */
2313 Status
= ObpIncrementHandleCount(SourceObject
,
2317 PsGetCurrentProcess(),
2321 /* Check if we were attached */
2322 if (AttachedToProcess
)
2324 /* We can safely detach now */
2325 KeUnstackDetachProcess(&ApcState
);
2326 AttachedToProcess
= FALSE
;
2329 /* Check if we have to close the source handle */
2330 if (Options
& DUPLICATE_CLOSE_SOURCE
)
2332 /* Attach and close */
2333 KeStackAttachProcess(&SourceProcess
->Pcb
, &ApcState
);
2334 NtClose(SourceHandle
);
2335 KeUnstackDetachProcess(&ApcState
);
2338 /* Check if we had an access state */
2339 if (PassedAccessState
) SeDeleteAccessState(PassedAccessState
);
2341 /* Now check if incrementing actually failed */
2342 if (!NT_SUCCESS(Status
))
2344 /* Dereference handle tables */
2345 ObDereferenceProcessHandleTable(SourceProcess
);
2346 ObDereferenceProcessHandleTable(TargetProcess
);
2348 /* Dereference the source object */
2349 ObDereferenceObject(SourceObject
);
2353 /* Now create the handle */
2354 NewHandle
= ExCreateHandle(HandleTable
, &NewHandleEntry
);
2357 /* Undo the increment */
2358 ObpDecrementHandleCount(SourceObject
,
2363 /* Deference the object and set failure status */
2364 ObDereferenceObject(SourceObject
);
2365 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2368 /* Return the handle */
2369 if (TargetHandle
) *TargetHandle
= NewHandle
;
2371 /* Dereference handle tables */
2372 ObDereferenceProcessHandleTable(SourceProcess
);
2373 ObDereferenceProcessHandleTable(TargetProcess
);
2376 OBTRACE(OB_HANDLE_DEBUG
,
2377 "%s - Duplicated handle: %p for %p into %p. Source: %p HC PC %lx %lx\n",
2383 ObjectHeader
->PointerCount
,
2384 ObjectHeader
->HandleCount
);
2388 /* PUBLIC FUNCTIONS *********************************************************/
2391 * @name ObOpenObjectByName
2394 * The ObOpenObjectByName routine <FILLMEIN>
2396 * @param ObjectAttributes
2405 * @param PassedAccessState
2408 * @param DesiredAccess
2411 * @param ParseContext
2417 * @return <FILLMEIN>.
2424 ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2425 IN POBJECT_TYPE ObjectType
,
2426 IN KPROCESSOR_MODE AccessMode
,
2427 IN PACCESS_STATE PassedAccessState
,
2428 IN ACCESS_MASK DesiredAccess
,
2429 IN OUT PVOID ParseContext
,
2432 PVOID Object
= NULL
;
2433 UNICODE_STRING ObjectName
;
2434 NTSTATUS Status
, Status2
;
2435 POBJECT_HEADER ObjectHeader
;
2436 PGENERIC_MAPPING GenericMapping
= NULL
;
2437 OB_OPEN_REASON OpenReason
;
2438 POB_TEMP_BUFFER TempBuffer
;
2441 /* Assume failure */
2444 /* Check if we didn't get any Object Attributes */
2445 if (!ObjectAttributes
)
2447 /* Fail with special status code */
2448 return STATUS_INVALID_PARAMETER
;
2451 /* Allocate the temporary buffer */
2452 TempBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2453 sizeof(OB_TEMP_BUFFER
),
2454 TAG_OB_TEMP_STORAGE
);
2455 if (!TempBuffer
) return STATUS_INSUFFICIENT_RESOURCES
;
2457 /* Capture all the info */
2458 Status
= ObpCaptureObjectCreateInformation(ObjectAttributes
,
2462 &TempBuffer
->ObjectCreateInfo
,
2464 if (!NT_SUCCESS(Status
))
2467 ExFreePoolWithTag(TempBuffer
, TAG_OB_TEMP_STORAGE
);
2471 /* Check if we didn't get an access state */
2472 if (!PassedAccessState
)
2474 /* Try to get the generic mapping if we can */
2475 if (ObjectType
) GenericMapping
= &ObjectType
->TypeInfo
.GenericMapping
;
2477 /* Use our built-in access state */
2478 PassedAccessState
= &TempBuffer
->LocalAccessState
;
2479 Status
= SeCreateAccessState(&TempBuffer
->LocalAccessState
,
2480 &TempBuffer
->AuxData
,
2483 if (!NT_SUCCESS(Status
)) goto Quickie
;
2486 /* Get the security descriptor */
2487 if (TempBuffer
->ObjectCreateInfo
.SecurityDescriptor
)
2489 /* Save it in the access state */
2490 PassedAccessState
->SecurityDescriptor
=
2491 TempBuffer
->ObjectCreateInfo
.SecurityDescriptor
;
2494 /* Validate the access mask */
2495 Status
= ObpValidateAccessMask(PassedAccessState
);
2496 if (!NT_SUCCESS(Status
))
2498 /* Cleanup after lookup */
2499 ObpReleaseLookupContext(&TempBuffer
->LookupContext
);
2503 /* Now do the lookup */
2504 Status
= ObpLookupObjectName(TempBuffer
->ObjectCreateInfo
.RootDirectory
,
2506 TempBuffer
->ObjectCreateInfo
.Attributes
,
2510 TempBuffer
->ObjectCreateInfo
.SecurityQos
,
2513 &TempBuffer
->LookupContext
,
2515 if (!NT_SUCCESS(Status
))
2517 /* Cleanup after lookup */
2518 ObpReleaseLookupContext(&TempBuffer
->LookupContext
);
2522 /* Check if this object has create information */
2523 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
2524 if (ObjectHeader
->Flags
& OB_FLAG_CREATE_INFO
)
2526 /* Then we are creating a new handle */
2527 OpenReason
= ObCreateHandle
;
2529 /* Check if we still have create info */
2530 if (ObjectHeader
->ObjectCreateInfo
)
2533 ObpFreeObjectCreateInformation(ObjectHeader
->
2535 ObjectHeader
->ObjectCreateInfo
= NULL
;
2540 /* Otherwise, we are merely opening it */
2541 OpenReason
= ObOpenHandle
;
2544 /* Check if we have invalid object attributes */
2545 if (ObjectHeader
->Type
->TypeInfo
.InvalidAttributes
&
2546 TempBuffer
->ObjectCreateInfo
.Attributes
)
2548 /* Set failure code */
2549 Status
= STATUS_INVALID_PARAMETER
;
2551 /* Cleanup after lookup */
2552 ObpReleaseLookupContext(&TempBuffer
->LookupContext
);
2554 /* Dereference the object */
2555 ObDereferenceObject(Object
);
2559 /* Create the actual handle now */
2560 Status2
= ObpCreateHandle(OpenReason
,
2565 TempBuffer
->ObjectCreateInfo
.Attributes
,
2566 &TempBuffer
->LookupContext
,
2570 if (!NT_SUCCESS(Status2
))
2572 ObDereferenceObject(Object
);
2578 /* Delete the access state */
2579 if (PassedAccessState
== &TempBuffer
->LocalAccessState
)
2581 SeDeleteAccessState(PassedAccessState
);
2585 /* Release the object attributes and temporary buffer */
2586 ObpReleaseObjectCreateInformation(&TempBuffer
->ObjectCreateInfo
);
2587 if (ObjectName
.Buffer
) ObpFreeObjectNameBuffer(&ObjectName
);
2588 ExFreePoolWithTag(TempBuffer
, TAG_OB_TEMP_STORAGE
);
2591 OBTRACE(OB_HANDLE_DEBUG
,
2592 "%s - returning Object %p with PC S: %lx %lx\n",
2595 Object
? OBJECT_TO_OBJECT_HEADER(Object
)->PointerCount
: -1,
2601 * @name ObOpenObjectByPointer
2604 * The ObOpenObjectByPointer routine <FILLMEIN>
2609 * @param HandleAttributes
2612 * @param PassedAccessState
2615 * @param DesiredAccess
2627 * @return <FILLMEIN>.
2634 ObOpenObjectByPointer(IN PVOID Object
,
2635 IN ULONG HandleAttributes
,
2636 IN PACCESS_STATE PassedAccessState
,
2637 IN ACCESS_MASK DesiredAccess
,
2638 IN POBJECT_TYPE ObjectType
,
2639 IN KPROCESSOR_MODE AccessMode
,
2642 POBJECT_HEADER Header
;
2644 ACCESS_STATE AccessState
;
2645 AUX_ACCESS_DATA AuxData
;
2648 /* Assume failure */
2651 /* Reference the object */
2652 Status
= ObReferenceObjectByPointer(Object
,
2656 if (!NT_SUCCESS(Status
)) return Status
;
2658 /* Get the Header Info */
2659 Header
= OBJECT_TO_OBJECT_HEADER(Object
);
2661 /* Check if we didn't get an access state */
2662 if (!PassedAccessState
)
2664 /* Use our built-in access state */
2665 PassedAccessState
= &AccessState
;
2666 Status
= SeCreateAccessState(&AccessState
,
2669 &Header
->Type
->TypeInfo
.GenericMapping
);
2670 if (!NT_SUCCESS(Status
))
2673 ObDereferenceObject(Object
);
2678 /* Check if we have invalid object attributes */
2679 if (Header
->Type
->TypeInfo
.InvalidAttributes
& HandleAttributes
)
2681 /* Delete the access state */
2682 if (PassedAccessState
== &AccessState
)
2684 SeDeleteAccessState(PassedAccessState
);
2687 /* Dereference the object */
2688 ObDereferenceObject(Object
);
2689 return STATUS_INVALID_PARAMETER
;
2692 /* Create the handle */
2693 Status
= ObpCreateHandle(ObOpenHandle
,
2703 if (!NT_SUCCESS(Status
)) ObDereferenceObject(Object
);
2705 /* Delete the access state */
2706 if (PassedAccessState
== &AccessState
)
2708 SeDeleteAccessState(PassedAccessState
);
2712 OBTRACE(OB_HANDLE_DEBUG
,
2713 "%s - returning Object with PC S: %lx %lx\n",
2715 OBJECT_TO_OBJECT_HEADER(Object
)->PointerCount
,
2721 * @name ObFindHandleForObject
2724 * The ObFindHandleForObject routine <FILLMEIN>
2735 * @param HandleInformation
2738 * @param HandleReturn
2741 * @return <FILLMEIN>.
2748 ObFindHandleForObject(IN PEPROCESS Process
,
2750 IN POBJECT_TYPE ObjectType
,
2751 IN POBJECT_HANDLE_INFORMATION HandleInformation
,
2754 OBP_FIND_HANDLE_DATA FindData
;
2755 BOOLEAN Result
= FALSE
;
2758 /* Make sure we have an object table */
2759 ObjectTable
= ObReferenceProcessHandleTable(Process
);
2762 /* Check if we have an object */
2765 /* Set its header */
2766 FindData
.ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
2770 /* Otherwise, no object to match*/
2771 FindData
.ObjectHeader
= NULL
;
2774 /* Set other information */
2775 FindData
.ObjectType
= ObjectType
;
2776 FindData
.HandleInformation
= HandleInformation
;
2778 /* Enumerate the handle table */
2779 if (ExEnumHandleTable(Process
->ObjectTable
,
2780 ObpEnumFindHandleProcedure
,
2788 /* Let go of the table */
2789 ObDereferenceProcessHandleTable(Process
);
2792 /* Return the result */
2797 * @name ObInsertObject
2800 * The ObInsertObject routine <FILLMEIN>
2805 * @param PassedAccessState
2808 * @param DesiredAccess
2811 * @param AdditionalReferences
2814 * @param ReferencedObject
2820 * @return <FILLMEIN>.
2827 ObInsertObject(IN PVOID Object
,
2828 IN PACCESS_STATE AccessState OPTIONAL
,
2829 IN ACCESS_MASK DesiredAccess
,
2830 IN ULONG ObjectPointerBias
,
2831 OUT PVOID
*NewObject OPTIONAL
,
2834 POBJECT_CREATE_INFORMATION ObjectCreateInfo
;
2835 POBJECT_HEADER ObjectHeader
;
2836 POBJECT_TYPE ObjectType
;
2837 PUNICODE_STRING ObjectName
;
2839 PSECURITY_DESCRIPTOR ParentDescriptor
= NULL
;
2840 BOOLEAN SdAllocated
= FALSE
;
2841 POBJECT_HEADER_NAME_INFO ObjectNameInfo
;
2842 OBP_LOOKUP_CONTEXT Context
;
2843 ACCESS_STATE LocalAccessState
;
2844 AUX_ACCESS_DATA AuxData
;
2845 OB_OPEN_REASON OpenReason
;
2846 KPROCESSOR_MODE PreviousMode
;
2847 NTSTATUS Status
= STATUS_SUCCESS
, RealStatus
;
2848 BOOLEAN IsNewObject
;
2851 /* Get the Header */
2852 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
2854 /* Detect invalid insert */
2855 if (!(ObjectHeader
->Flags
& OB_FLAG_CREATE_INFO
))
2857 /* Display warning and break into debugger */
2858 DPRINT1("OB: Attempting to insert existing object %p\n", Object
);
2861 /* Allow debugger to continue */
2862 ObDereferenceObject(Object
);
2863 return STATUS_INVALID_PARAMETER
;
2866 /* Get the create and name info, as well as the object type */
2867 ObjectCreateInfo
= ObjectHeader
->ObjectCreateInfo
;
2868 ObjectNameInfo
= ObpReferenceNameInfo(ObjectHeader
);
2869 ObjectType
= ObjectHeader
->Type
;
2872 /* Check if this is an named object */
2873 if ((ObjectNameInfo
) && (ObjectNameInfo
->Name
.Buffer
))
2875 /* Get the object name */
2876 ObjectName
= &ObjectNameInfo
->Name
;
2881 ((ObjectPointerBias
== 0) &&
2882 (ObjectName
== NULL
) &&
2883 (ObjectType
->TypeInfo
.SecurityRequired
) &&
2884 (NewObject
== NULL
)));
2886 /* Check if the object is unnamed and also doesn't have security */
2887 PreviousMode
= KeGetPreviousMode();
2888 if (!(ObjectType
->TypeInfo
.SecurityRequired
) && !(ObjectName
))
2890 /* Assume failure */
2892 ObjectHeader
->ObjectCreateInfo
= NULL
;
2894 /* Create the handle */
2895 Status
= ObpCreateUnnamedHandle(Object
,
2897 ObjectPointerBias
+ 1,
2898 ObjectCreateInfo
->Attributes
,
2903 /* Free the create information */
2904 ObpFreeObjectCreateInformation(ObjectCreateInfo
);
2906 /* Release the object name information */
2907 ObpDereferenceNameInfo(ObjectNameInfo
);
2909 /* Remove the extra keep-alive reference */
2910 ObDereferenceObject(Object
);
2913 OBTRACE(OB_HANDLE_DEBUG
,
2914 "%s - returning Object with PC S: %lx %lx\n",
2916 ObjectHeader
->PointerCount
,
2921 /* Check if we didn't get an access state */
2924 /* Use our built-in access state */
2925 AccessState
= &LocalAccessState
;
2926 Status
= SeCreateAccessState(&LocalAccessState
,
2929 &ObjectType
->TypeInfo
.GenericMapping
);
2930 if (!NT_SUCCESS(Status
))
2933 ObpDereferenceNameInfo(ObjectNameInfo
);
2934 ObDereferenceObject(Object
);
2939 /* Save the security descriptor */
2940 AccessState
->SecurityDescriptor
= ObjectCreateInfo
->SecurityDescriptor
;
2942 /* Validate the access mask */
2943 Status
= ObpValidateAccessMask(AccessState
);
2944 if (!NT_SUCCESS(Status
))
2947 ObpDereferenceNameInfo(ObjectNameInfo
);
2948 ObDereferenceObject(Object
);
2952 /* Setup a lookup context */
2953 ObpInitializeLookupContext(&Context
);
2954 InsertObject
= Object
;
2955 OpenReason
= ObCreateHandle
;
2957 /* Check if the object is named */
2961 Status
= ObpLookupObjectName(ObjectCreateInfo
->RootDirectory
,
2963 ObjectCreateInfo
->Attributes
,
2965 (ObjectHeader
->Flags
& OB_FLAG_KERNEL_MODE
) ?
2966 KernelMode
: UserMode
,
2967 ObjectCreateInfo
->ParseContext
,
2968 ObjectCreateInfo
->SecurityQos
,
2974 /* Check if we found an object that doesn't match the one requested */
2975 if ((NT_SUCCESS(Status
)) && (InsertObject
) && (Object
!= InsertObject
))
2977 /* This means we're opening an object, not creating a new one */
2978 OpenReason
= ObOpenHandle
;
2980 /* Make sure the caller said it's OK to do this */
2981 if (ObjectCreateInfo
->Attributes
& OBJ_OPENIF
)
2983 /* He did, but did he want this type? */
2984 if (ObjectType
!= OBJECT_TO_OBJECT_HEADER(InsertObject
)->Type
)
2986 /* Wrong type, so fail */
2987 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
2991 /* Right type, so warn */
2992 Status
= STATUS_OBJECT_NAME_EXISTS
;
2997 /* Check if this was a symbolic link */
2998 if (OBJECT_TO_OBJECT_HEADER(InsertObject
)->Type
==
3001 /* Dereference it */
3002 ObDereferenceObject(InsertObject
);
3005 /* Caller wanted to create a new object, fail */
3006 Status
= STATUS_OBJECT_NAME_COLLISION
;
3010 /* Check if anything until now failed */
3011 if (!NT_SUCCESS(Status
))
3013 /* Cleanup after lookup */
3014 ObpReleaseLookupContext(&Context
);
3016 /* Remove query reference that we added */
3017 ObpDereferenceNameInfo(ObjectNameInfo
);
3019 /* Dereference the object and delete the access state */
3020 ObDereferenceObject(Object
);
3021 if (AccessState
== &LocalAccessState
)
3023 /* We used a local one; delete it */
3024 SeDeleteAccessState(AccessState
);
3027 /* Return failure code */
3032 /* Check if this is a symbolic link */
3033 if (ObjectType
== ObSymbolicLinkType
)
3035 /* Create the internal name */
3036 ObpCreateSymbolicLinkName(Object
);
3041 /* Now check if this object is being created */
3042 if (InsertObject
== Object
)
3044 /* Check if it's named or forces security */
3045 if ((ObjectName
) || (ObjectType
->TypeInfo
.SecurityRequired
))
3047 /* Make sure it's inserted into an object directory */
3048 if ((ObjectNameInfo
) && (ObjectNameInfo
->Directory
))
3050 /* Get the current descriptor */
3051 ObGetObjectSecurity(ObjectNameInfo
->Directory
,
3057 Status
= ObAssignSecurity(AccessState
,
3062 /* Check if we captured one */
3063 if (ParentDescriptor
)
3065 /* We did, release it */
3066 ObReleaseObjectSecurity(ParentDescriptor
, SdAllocated
);
3068 else if (NT_SUCCESS(Status
))
3070 /* Other we didn't, but we were able to use the current SD */
3071 SeReleaseSecurityDescriptor(ObjectCreateInfo
->SecurityDescriptor
,
3072 ObjectCreateInfo
->ProbeMode
,
3075 /* Clear the current one */
3076 AccessState
->SecurityDescriptor
=
3077 ObjectCreateInfo
->SecurityDescriptor
= NULL
;
3081 /* Check if anything until now failed */
3082 if (!NT_SUCCESS(Status
))
3084 /* Check if the directory was added */
3085 if (Context
.DirectoryLocked
)
3087 /* Weird case where we need to do a manual delete */
3088 DPRINT1("Unhandled path\n");
3092 /* Cleanup the lookup */
3093 ObpReleaseLookupContext(&Context
);
3095 /* Remove query reference that we added */
3096 ObpDereferenceNameInfo(ObjectNameInfo
);
3098 /* Dereference the object and delete the access state */
3099 ObDereferenceObject(Object
);
3100 if (AccessState
== &LocalAccessState
)
3102 /* We used a local one; delete it */
3103 SeDeleteAccessState(AccessState
);
3106 /* Return failure code */
3112 /* Save the actual status until here */
3113 RealStatus
= Status
;
3115 /* Check if caller wants us to create a handle */
3116 ObjectHeader
->ObjectCreateInfo
= NULL
;
3119 /* Create the handle */
3120 Status
= ObpCreateHandle(OpenReason
,
3124 ObjectPointerBias
+ 1,
3125 ObjectCreateInfo
->Attributes
,
3130 if (!NT_SUCCESS(Status
))
3132 /* If the object had a name, backout everything */
3133 if (ObjectName
) ObpDeleteNameCheck(Object
);
3135 /* Return the status of the failure */
3137 RealStatus
= Status
;
3140 /* Remove a query reference */
3141 ObpDereferenceNameInfo(ObjectNameInfo
);
3143 /* Remove the extra keep-alive reference */
3144 ObDereferenceObject(Object
);
3148 /* Otherwise, lock the object */
3149 ObpAcquireObjectLock(ObjectHeader
);
3151 /* And charge quota for the process to make it appear as used */
3152 RealStatus
= ObpChargeQuotaForObject(ObjectHeader
,
3156 /* Release the lock */
3157 ObpReleaseObjectLock(ObjectHeader
);
3159 /* Check if we failed and dereference the object if so */
3160 if (!NT_SUCCESS(RealStatus
)) ObDereferenceObject(Object
);
3163 /* We can delete the Create Info now */
3164 ObpFreeObjectCreateInformation(ObjectCreateInfo
);
3166 /* Check if we created our own access state and delete it if so */
3167 if (AccessState
== &LocalAccessState
) SeDeleteAccessState(AccessState
);
3169 /* Return status code */
3170 OBTRACE(OB_HANDLE_DEBUG
,
3171 "%s - returning Object with PC RS/S: %lx %lx %lx\n",
3173 OBJECT_TO_OBJECT_HEADER(Object
)->PointerCount
,
3174 RealStatus
, Status
);
3179 * @name ObSetHandleAttributes
3180 * @implemented NT5.1
3182 * The ObSetHandleAttributes routine <FILLMEIN>
3187 * @param HandleFlags
3190 * @param PreviousMode
3193 * @return <FILLMEIN>.
3200 ObSetHandleAttributes(IN HANDLE Handle
,
3201 IN POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags
,
3202 IN KPROCESSOR_MODE PreviousMode
)
3204 OBP_SET_HANDLE_ATTRIBUTES_CONTEXT SetHandleAttributesContext
;
3205 BOOLEAN Result
, AttachedToSystemProcess
= FALSE
;
3206 PHANDLE_TABLE HandleTable
;
3207 KAPC_STATE ApcState
;
3210 /* Check if this is a kernel handle */
3211 if (ObpIsKernelHandle(Handle
, PreviousMode
))
3213 /* Use the kernel table and convert the handle */
3214 HandleTable
= ObpKernelHandleTable
;
3215 Handle
= ObKernelHandleToHandle(Handle
);
3217 /* Check if we're not in the system process */
3218 if (PsGetCurrentProcess() != PsInitialSystemProcess
)
3220 /* Attach to the system process */
3221 KeStackAttachProcess(&PsInitialSystemProcess
->Pcb
, &ApcState
);
3222 AttachedToSystemProcess
= TRUE
;
3227 /* Get the current process' handle table */
3228 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
3231 /* Initialize the handle attribute context */
3232 SetHandleAttributesContext
.PreviousMode
= PreviousMode
;
3233 SetHandleAttributesContext
.Information
= *HandleFlags
;
3235 /* Invoke the ObpSetHandleAttributes callback */
3236 Result
= ExChangeHandle(HandleTable
,
3238 ObpSetHandleAttributes
,
3239 (ULONG_PTR
)&SetHandleAttributesContext
);
3241 /* Did we attach to the system process? */
3242 if (AttachedToSystemProcess
)
3244 /* Detach from it */
3245 KeUnstackDetachProcess(&ApcState
);
3248 /* Return the result as an NTSTATUS value */
3249 return Result
? STATUS_SUCCESS
: STATUS_ACCESS_DENIED
;
3253 * @name ObCloseHandle
3254 * @implemented NT5.1
3256 * The ObCloseHandle routine <FILLMEIN>
3264 * @return <FILLMEIN>.
3271 ObCloseHandle(IN HANDLE Handle
,
3272 IN KPROCESSOR_MODE AccessMode
)
3274 /* Call the internal API */
3275 return ObpCloseHandle(Handle
, AccessMode
);
3282 * The NtClose routine <FILLMEIN>
3287 * @return <FILLMEIN>.
3294 NtClose(IN HANDLE Handle
)
3296 /* Call the internal API */
3297 return ObpCloseHandle(Handle
, ExGetPreviousMode());
3302 NtDuplicateObject(IN HANDLE SourceProcessHandle
,
3303 IN HANDLE SourceHandle
,
3304 IN HANDLE TargetProcessHandle OPTIONAL
,
3305 OUT PHANDLE TargetHandle OPTIONAL
,
3306 IN ACCESS_MASK DesiredAccess
,
3307 IN ULONG HandleAttributes
,
3310 PEPROCESS SourceProcess
, TargetProcess
, Target
;
3312 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
3314 OBTRACE(OB_HANDLE_DEBUG
,
3315 "%s - Duplicating handle: %p for %p into %p.\n",
3318 SourceProcessHandle
,
3319 TargetProcessHandle
);
3321 /* Check if we have a target handle */
3322 if ((TargetHandle
) && (PreviousMode
!= KernelMode
))
3327 /* Probe the handle and assume failure */
3328 ProbeForWriteHandle(TargetHandle
);
3329 *TargetHandle
= NULL
;
3331 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3333 /* Return the exception code */
3334 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3339 /* Now reference the input handle */
3340 Status
= ObReferenceObjectByHandle(SourceProcessHandle
,
3344 (PVOID
*)&SourceProcess
,
3346 if (!NT_SUCCESS(Status
)) return Status
;
3348 /* Check if got a target handle */
3349 if (TargetProcessHandle
)
3351 /* Now reference the output handle */
3352 Status
= ObReferenceObjectByHandle(TargetProcessHandle
,
3356 (PVOID
*)&TargetProcess
,
3358 if (NT_SUCCESS(Status
))
3360 /* Use this target process */
3361 Target
= TargetProcess
;
3365 /* No target process */
3371 /* No target process */
3372 Status
= STATUS_SUCCESS
;
3376 /* Call the internal routine */
3377 Status
= ObDuplicateObject(SourceProcess
,
3386 /* Check if the caller wanted the return handle */
3389 /* Protect the write to user mode */
3392 /* Write the new handle */
3393 *TargetHandle
= hTarget
;
3395 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3397 /* Otherwise, get the exception code */
3398 Status
= _SEH2_GetExceptionCode();
3403 /* Dereference the processes */
3404 OBTRACE(OB_HANDLE_DEBUG
,
3405 "%s - Duplicated handle: %p into %p S %lx\n",
3408 TargetProcessHandle
,
3410 if (Target
) ObDereferenceObject(Target
);
3411 ObDereferenceObject(SourceProcess
);
3417 ObIsKernelHandle(IN HANDLE Handle
)
3419 /* Use the inlined version. We know we are in kernel mode. */
3420 return ObpIsKernelHandle(Handle
, KernelMode
);