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 InterlockedIncrementSizeT(&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 InterlockedIncrementSizeT(&ObjectHeader
->PointerCount
);
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 InterlockedIncrementSizeT(&ObjectHeader
->PointerCount
);
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
)
487 PISECURITY_DESCRIPTOR SecurityDescriptor
;
489 /* We're only interested if the object for this access state has an SD */
490 SecurityDescriptor
= AccessState
->SecurityDescriptor
;
491 if (SecurityDescriptor
)
493 /* Check if the SD has a system ACL but hasn't been granted access to get/set it */
494 if ((SecurityDescriptor
->Control
& SE_SACL_PRESENT
) &&
495 !(AccessState
->PreviouslyGrantedAccess
& ACCESS_SYSTEM_SECURITY
))
497 /* We're gonna need access */
498 AccessState
->RemainingDesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
502 /* This can't fail */
503 return STATUS_SUCCESS
;
507 * @name ObpDecrementHandleCount
509 * The ObpDecrementHandleCount routine <FILLMEIN>
517 * @param GrantedAccess
527 ObpDecrementHandleCount(IN PVOID ObjectBody
,
528 IN PEPROCESS Process
,
529 IN ACCESS_MASK GrantedAccess
,
530 IN POBJECT_TYPE ObjectType
)
532 POBJECT_HEADER ObjectHeader
;
533 LONG SystemHandleCount
, ProcessHandleCount
;
536 POBJECT_HEADER_HANDLE_INFO HandleInfo
;
537 POBJECT_HANDLE_COUNT_ENTRY HandleEntry
;
538 POBJECT_HANDLE_COUNT_DATABASE HandleDatabase
;
542 /* Get the object type and header */
543 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(ObjectBody
);
544 OBTRACE(OB_HANDLE_DEBUG
,
545 "%s - Decrementing count for: %p. HC PC %lx %lx\n",
548 ObjectHeader
->HandleCount
,
549 ObjectHeader
->PointerCount
);
551 /* Lock the object */
552 ObpAcquireObjectLock(ObjectHeader
);
554 /* Set default counts */
555 SystemHandleCount
= ObjectHeader
->HandleCount
;
556 ProcessHandleCount
= 0;
558 /* Decrement the handle count */
559 NewCount
= InterlockedDecrementSizeT(&ObjectHeader
->HandleCount
);
561 /* Check if we're out of handles and this was an exclusive object */
562 if (!(NewCount
) && (ObjectHeader
->Flags
& OB_FLAG_EXCLUSIVE
))
564 /* Clear the exclusive flag */
565 OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader
)->ExclusiveProcess
= NULL
;
568 /* Is the object type keeping track of handles? */
569 if (ObjectType
->TypeInfo
.MaintainHandleCount
)
571 /* Get handle information */
572 HandleInfo
= OBJECT_HEADER_TO_HANDLE_INFO(ObjectHeader
);
574 /* Check if there's only a single entry */
575 if (ObjectHeader
->Flags
& OB_FLAG_SINGLE_PROCESS
)
577 /* It should be us */
578 ASSERT(HandleInfo
->SingleEntry
.Process
== Process
);
579 ASSERT(HandleInfo
->SingleEntry
.HandleCount
> 0);
581 /* Get the handle counts */
582 ProcessHandleCount
= HandleInfo
->SingleEntry
.HandleCount
--;
583 HandleEntry
= &HandleInfo
->SingleEntry
;
587 /* Otherwise, get the database */
588 HandleDatabase
= HandleInfo
->HandleCountDatabase
;
591 /* Get the entries and loop them */
592 i
= HandleDatabase
->CountEntries
;
593 HandleEntry
= &HandleDatabase
->HandleCountEntries
[0];
596 /* Check if this is a match */
597 if ((HandleEntry
->HandleCount
) &&
598 (HandleEntry
->Process
== Process
))
600 /* Found it, get the process handle count */
601 ProcessHandleCount
= HandleEntry
->HandleCount
--;
612 /* No database, so no entry */
617 /* Check if this is the last handle */
618 if (ProcessHandleCount
== 1)
620 /* Then clear the entry */
621 HandleEntry
->Process
= NULL
;
622 HandleEntry
->HandleCount
= 0;
626 /* Release the lock */
627 ObpReleaseObjectLock(ObjectHeader
);
629 /* Check if we have a close procedure */
630 if (ObjectType
->TypeInfo
.CloseProcedure
)
633 ObpCalloutStart(&CalloutIrql
);
634 ObjectType
->TypeInfo
.CloseProcedure(Process
,
639 ObpCalloutEnd(CalloutIrql
, "Close", ObjectType
, ObjectBody
);
642 /* Check if we should delete the object */
643 ObpDeleteNameCheck(ObjectBody
);
645 /* Decrease the total number of handles for this type */
646 InterlockedDecrement((PLONG
)&ObjectType
->TotalNumberOfHandles
);
647 OBTRACE(OB_HANDLE_DEBUG
,
648 "%s - Decremented count for: %p. HC PC %lx %lx\n",
651 ObjectHeader
->HandleCount
,
652 ObjectHeader
->PointerCount
);
656 * @name ObpCloseHandleTableEntry
658 * The ObpCloseHandleTableEntry routine <FILLMEIN>
672 * @param IgnoreHandleProtection
675 * @return <FILLMEIN>.
682 ObpCloseHandleTableEntry(IN PHANDLE_TABLE HandleTable
,
683 IN PHANDLE_TABLE_ENTRY HandleEntry
,
685 IN KPROCESSOR_MODE AccessMode
,
686 IN BOOLEAN IgnoreHandleProtection
)
689 POBJECT_TYPE ObjectType
;
690 POBJECT_HEADER ObjectHeader
;
691 ACCESS_MASK GrantedAccess
;
695 /* Get the object data */
696 ObjectHeader
= ObpGetHandleObject(HandleEntry
);
697 ObjectType
= ObjectHeader
->Type
;
698 Body
= &ObjectHeader
->Body
;
699 GrantedAccess
= HandleEntry
->GrantedAccess
;
700 OBTRACE(OB_HANDLE_DEBUG
,
701 "%s - Closing handle: %p for %p. HC PC %lx %lx\n",
705 ObjectHeader
->HandleCount
,
706 ObjectHeader
->PointerCount
);
708 /* Check if the object has an Okay To Close procedure */
709 if (ObjectType
->TypeInfo
.OkayToCloseProcedure
)
711 /* Call it and check if it's not letting us close it */
712 ObpCalloutStart(&CalloutIrql
);
713 if (!ObjectType
->TypeInfo
.OkayToCloseProcedure(PsGetCurrentProcess(),
719 ObpCalloutEnd(CalloutIrql
, "NtClose", ObjectType
, Body
);
720 ExUnlockHandleTableEntry(HandleTable
, HandleEntry
);
721 return STATUS_HANDLE_NOT_CLOSABLE
;
724 /* Success, validate callout retrn */
725 ObpCalloutEnd(CalloutIrql
, "NtClose", ObjectType
, Body
);
728 /* The callback allowed us to close it, but does the handle itself? */
729 if ((HandleEntry
->ObAttributes
& OBJ_PROTECT_CLOSE
) &&
730 !(IgnoreHandleProtection
))
732 /* It doesn't, are we from user mode? */
733 if (AccessMode
!= KernelMode
)
735 /* We are! Unlock the entry */
736 ExUnlockHandleTableEntry(HandleTable
, HandleEntry
);
738 /* Make sure we have a debug port */
739 if (PsGetCurrentProcess()->DebugPort
)
741 /* Raise an exception */
742 return KeRaiseUserException(STATUS_HANDLE_NOT_CLOSABLE
);
746 /* Return the error instead */
747 return STATUS_HANDLE_NOT_CLOSABLE
;
752 /* Otherwise, bugcheck the OS */
753 KeBugCheckEx(INVALID_KERNEL_HANDLE
, (ULONG_PTR
)Handle
, 0, 0, 0);
757 /* Destroy and unlock the handle entry */
758 ExDestroyHandle(HandleTable
, Handle
, HandleEntry
);
760 /* Now decrement the handle count */
761 ObpDecrementHandleCount(Body
,
762 PsGetCurrentProcess(),
766 /* Dereference the object as well */
767 ObDereferenceObject(Body
);
769 /* Return to caller */
770 OBTRACE(OB_HANDLE_DEBUG
,
771 "%s - Closed handle: %p for %p.\n",
775 return STATUS_SUCCESS
;
779 * @name ObpIncrementHandleCount
781 * The ObpIncrementHandleCount routine <FILLMEIN>
792 * @param HandleAttributes
801 * @return <FILLMEIN>.
808 ObpIncrementHandleCount(IN PVOID Object
,
809 IN PACCESS_STATE AccessState OPTIONAL
,
810 IN KPROCESSOR_MODE AccessMode
,
811 IN ULONG HandleAttributes
,
812 IN PEPROCESS Process
,
813 IN OB_OPEN_REASON OpenReason
)
815 POBJECT_HEADER ObjectHeader
;
816 POBJECT_TYPE ObjectType
;
817 ULONG ProcessHandleCount
;
819 PEPROCESS ExclusiveProcess
;
820 BOOLEAN Exclusive
= FALSE
, NewObject
;
821 POBJECT_HEADER_CREATOR_INFO CreatorInfo
;
823 KPROCESSOR_MODE ProbeMode
;
825 POBJECT_HEADER_NAME_INFO NameInfo
;
828 /* Get the object header and type */
829 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
830 ObjectType
= ObjectHeader
->Type
;
831 OBTRACE(OB_HANDLE_DEBUG
,
832 "%s - Incrementing count for: %p. Reason: %lx. HC PC %lx %lx\n",
836 ObjectHeader
->HandleCount
,
837 ObjectHeader
->PointerCount
);
839 /* Check if caller is forcing user mode */
840 if (HandleAttributes
& OBJ_FORCE_ACCESS_CHECK
)
843 ProbeMode
= UserMode
;
847 /* Keep original setting */
848 ProbeMode
= AccessMode
;
851 /* Lock the object */
852 ObpAcquireObjectLock(ObjectHeader
);
854 /* Charge quota and remove the creator info flag */
855 Status
= ObpChargeQuotaForObject(ObjectHeader
, ObjectType
, &NewObject
);
856 if (!NT_SUCCESS(Status
)) return Status
;
858 /* Check if the open is exclusive */
859 if (HandleAttributes
& OBJ_EXCLUSIVE
)
861 /* Check if the object allows this, or if the inherit flag was given */
862 if ((HandleAttributes
& OBJ_INHERIT
) ||
863 !(ObjectHeader
->Flags
& OB_FLAG_EXCLUSIVE
))
865 /* Incorrect attempt */
866 Status
= STATUS_INVALID_PARAMETER
;
870 /* Check if we have access to it */
871 ExclusiveProcess
= OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader
);
872 if ((!(ExclusiveProcess
) && (ObjectHeader
->HandleCount
)) ||
873 ((ExclusiveProcess
) && (ExclusiveProcess
!= PsGetCurrentProcess())))
875 /* This isn't the right process */
876 Status
= STATUS_ACCESS_DENIED
;
880 /* Now you got exclusive access */
883 else if ((ObjectHeader
->Flags
& OB_FLAG_EXCLUSIVE
) &&
884 (OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader
)))
886 /* Caller didn't want exclusive access, but the object is exclusive */
887 Status
= STATUS_ACCESS_DENIED
;
891 /* Check for exclusive kernel object */
892 NameInfo
= OBJECT_HEADER_TO_NAME_INFO(ObjectHeader
);
893 if ((NameInfo
) && (NameInfo
->QueryReferences
& OB_FLAG_KERNEL_EXCLUSIVE
) &&
894 (ProbeMode
!= KernelMode
))
896 /* Caller is not kernel, but the object is kernel exclusive */
897 Status
= STATUS_ACCESS_DENIED
;
902 * Check if this is an object that went from 0 handles back to existence,
903 * but doesn't have an open procedure, only a close procedure. This means
904 * that it will never realize that the object is back alive, so we must
907 if (!(ObjectHeader
->HandleCount
) &&
909 (ObjectType
->TypeInfo
.MaintainHandleCount
) &&
910 !(ObjectType
->TypeInfo
.OpenProcedure
) &&
911 (ObjectType
->TypeInfo
.CloseProcedure
))
914 Status
= STATUS_UNSUCCESSFUL
;
918 /* Check if we're opening an existing handle */
919 if ((OpenReason
== ObOpenHandle
) ||
920 ((OpenReason
== ObDuplicateHandle
) && (AccessState
)))
922 /* Validate the caller's access to this object */
923 if (!ObCheckObjectAccess(Object
,
929 /* Access was denied, so fail */
933 else if (OpenReason
== ObCreateHandle
)
935 /* Convert MAXIMUM_ALLOWED to GENERIC_ALL */
936 if (AccessState
->RemainingDesiredAccess
& MAXIMUM_ALLOWED
)
938 /* Mask out MAXIMUM_ALLOWED and stick GENERIC_ALL instead */
939 AccessState
->RemainingDesiredAccess
&= ~MAXIMUM_ALLOWED
;
940 AccessState
->RemainingDesiredAccess
|= GENERIC_ALL
;
943 /* Check if we have to map the GENERIC mask */
944 if (AccessState
->RemainingDesiredAccess
& GENERIC_ACCESS
)
946 /* Map it to the correct access masks */
947 RtlMapGenericMask(&AccessState
->RemainingDesiredAccess
,
948 &ObjectType
->TypeInfo
.GenericMapping
);
951 /* Check if the caller is trying to access system security */
952 if (AccessState
->RemainingDesiredAccess
& ACCESS_SYSTEM_SECURITY
)
955 DPRINT1("ACCESS_SYSTEM_SECURITY not validated!\n");
959 /* Check if this is an exclusive handle */
962 /* Save the owner process */
963 OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader
)->ExclusiveProcess
= Process
;
966 /* Increase the handle count */
967 InterlockedIncrementSizeT(&ObjectHeader
->HandleCount
);
968 ProcessHandleCount
= 0;
970 /* Check if we have a handle database */
971 if (ObjectType
->TypeInfo
.MaintainHandleCount
)
973 /* Increment the handle database */
974 Status
= ObpIncrementHandleDataBase(ObjectHeader
,
976 &ProcessHandleCount
);
977 if (!NT_SUCCESS(Status
))
979 /* FIXME: This should never happen for now */
980 DPRINT1("Unhandled case\n");
986 /* Release the lock */
987 ObpReleaseObjectLock(ObjectHeader
);
989 /* Check if we have an open procedure */
990 Status
= STATUS_SUCCESS
;
991 if (ObjectType
->TypeInfo
.OpenProcedure
)
994 ObpCalloutStart(&CalloutIrql
);
995 Status
= ObjectType
->TypeInfo
.OpenProcedure(OpenReason
,
1000 PreviouslyGrantedAccess
:
1002 ProcessHandleCount
);
1003 ObpCalloutEnd(CalloutIrql
, "Open", ObjectType
, Object
);
1005 /* Check if the open procedure failed */
1006 if (!NT_SUCCESS(Status
))
1008 /* FIXME: This should never happen for now */
1009 DPRINT1("Unhandled case\n");
1015 /* Check if this is a create operation */
1016 if (OpenReason
== ObCreateHandle
)
1018 /* Check if we have creator info */
1019 CreatorInfo
= OBJECT_HEADER_TO_CREATOR_INFO(ObjectHeader
);
1022 /* We do, acquire the lock */
1023 ObpEnterObjectTypeMutex(ObjectType
);
1025 /* Insert us on the list */
1026 InsertTailList(&ObjectType
->TypeList
, &CreatorInfo
->TypeList
);
1028 /* Release the lock */
1029 ObpLeaveObjectTypeMutex(ObjectType
);
1033 /* Increase total number of handles */
1034 Total
= InterlockedIncrement((PLONG
)&ObjectType
->TotalNumberOfHandles
);
1035 if (Total
> ObjectType
->HighWaterNumberOfHandles
)
1038 ObjectType
->HighWaterNumberOfHandles
= Total
;
1041 /* Trace call and return */
1042 OBTRACE(OB_HANDLE_DEBUG
,
1043 "%s - Incremented count for: %p. Reason: %lx HC PC %lx %lx\n",
1047 ObjectHeader
->HandleCount
,
1048 ObjectHeader
->PointerCount
);
1052 /* Release lock and return */
1053 ObpReleaseObjectLock(ObjectHeader
);
1058 * @name ObpIncrementUnnamedHandleCount
1060 * The ObpIncrementUnnamedHandleCount routine <FILLMEIN>
1065 * @param AccessState
1071 * @param HandleAttributes
1080 * @return <FILLMEIN>.
1087 ObpIncrementUnnamedHandleCount(IN PVOID Object
,
1088 IN PACCESS_MASK DesiredAccess
,
1089 IN KPROCESSOR_MODE AccessMode
,
1090 IN ULONG HandleAttributes
,
1091 IN PEPROCESS Process
)
1093 POBJECT_HEADER ObjectHeader
;
1094 POBJECT_TYPE ObjectType
;
1095 ULONG ProcessHandleCount
;
1097 PEPROCESS ExclusiveProcess
;
1098 BOOLEAN Exclusive
= FALSE
, NewObject
;
1099 POBJECT_HEADER_CREATOR_INFO CreatorInfo
;
1103 /* Get the object header and type */
1104 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
1105 ObjectType
= ObjectHeader
->Type
;
1106 OBTRACE(OB_HANDLE_DEBUG
,
1107 "%s - Incrementing count for: %p. UNNAMED. HC PC %lx %lx\n",
1110 ObjectHeader
->HandleCount
,
1111 ObjectHeader
->PointerCount
);
1113 /* Lock the object */
1114 ObpAcquireObjectLock(ObjectHeader
);
1116 /* Charge quota and remove the creator info flag */
1117 Status
= ObpChargeQuotaForObject(ObjectHeader
, ObjectType
, &NewObject
);
1118 if (!NT_SUCCESS(Status
)) return Status
;
1120 /* Check if the open is exclusive */
1121 if (HandleAttributes
& OBJ_EXCLUSIVE
)
1123 /* Check if the object allows this, or if the inherit flag was given */
1124 if ((HandleAttributes
& OBJ_INHERIT
) ||
1125 !(ObjectHeader
->Flags
& OB_FLAG_EXCLUSIVE
))
1127 /* Incorrect attempt */
1128 Status
= STATUS_INVALID_PARAMETER
;
1132 /* Check if we have access to it */
1133 ExclusiveProcess
= OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader
);
1134 if ((!(ExclusiveProcess
) && (ObjectHeader
->HandleCount
)) ||
1135 ((ExclusiveProcess
) && (ExclusiveProcess
!= PsGetCurrentProcess())))
1137 /* This isn't the right process */
1138 Status
= STATUS_ACCESS_DENIED
;
1142 /* Now you got exclusive access */
1145 else if ((ObjectHeader
->Flags
& OB_FLAG_EXCLUSIVE
) &&
1146 (OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader
)))
1148 /* Caller didn't want exclusive access, but the object is exclusive */
1149 Status
= STATUS_ACCESS_DENIED
;
1154 * Check if this is an object that went from 0 handles back to existence,
1155 * but doesn't have an open procedure, only a close procedure. This means
1156 * that it will never realize that the object is back alive, so we must
1159 if (!(ObjectHeader
->HandleCount
) &&
1161 (ObjectType
->TypeInfo
.MaintainHandleCount
) &&
1162 !(ObjectType
->TypeInfo
.OpenProcedure
) &&
1163 (ObjectType
->TypeInfo
.CloseProcedure
))
1166 Status
= STATUS_UNSUCCESSFUL
;
1170 /* Convert MAXIMUM_ALLOWED to GENERIC_ALL */
1171 if (*DesiredAccess
& MAXIMUM_ALLOWED
)
1173 /* Mask out MAXIMUM_ALLOWED and stick GENERIC_ALL instead */
1174 *DesiredAccess
&= ~MAXIMUM_ALLOWED
;
1175 *DesiredAccess
|= GENERIC_ALL
;
1178 /* Check if we have to map the GENERIC mask */
1179 if (*DesiredAccess
& GENERIC_ACCESS
)
1181 /* Map it to the correct access masks */
1182 RtlMapGenericMask(DesiredAccess
,
1183 &ObjectType
->TypeInfo
.GenericMapping
);
1186 /* Check if this is an exclusive handle */
1189 /* Save the owner process */
1190 OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader
)->ExclusiveProcess
= Process
;
1193 /* Increase the handle count */
1194 InterlockedIncrementSizeT(&ObjectHeader
->HandleCount
);
1195 ProcessHandleCount
= 0;
1197 /* Check if we have a handle database */
1198 if (ObjectType
->TypeInfo
.MaintainHandleCount
)
1200 /* Increment the handle database */
1201 Status
= ObpIncrementHandleDataBase(ObjectHeader
,
1203 &ProcessHandleCount
);
1204 if (!NT_SUCCESS(Status
))
1206 /* FIXME: This should never happen for now */
1207 DPRINT1("Unhandled case\n");
1213 /* Release the lock */
1214 ObpReleaseObjectLock(ObjectHeader
);
1216 /* Check if we have an open procedure */
1217 Status
= STATUS_SUCCESS
;
1218 if (ObjectType
->TypeInfo
.OpenProcedure
)
1221 ObpCalloutStart(&CalloutIrql
);
1222 Status
= ObjectType
->TypeInfo
.OpenProcedure(ObCreateHandle
,
1226 ProcessHandleCount
);
1227 ObpCalloutEnd(CalloutIrql
, "Open", ObjectType
, Object
);
1229 /* Check if the open procedure failed */
1230 if (!NT_SUCCESS(Status
))
1232 /* FIXME: This should never happen for now */
1233 DPRINT1("Unhandled case\n");
1239 /* Check if we have creator info */
1240 CreatorInfo
= OBJECT_HEADER_TO_CREATOR_INFO(ObjectHeader
);
1243 /* We do, acquire the lock */
1244 ObpEnterObjectTypeMutex(ObjectType
);
1246 /* Insert us on the list */
1247 InsertTailList(&ObjectType
->TypeList
, &CreatorInfo
->TypeList
);
1249 /* Release the lock */
1250 ObpLeaveObjectTypeMutex(ObjectType
);
1253 /* Increase total number of handles */
1254 Total
= InterlockedIncrement((PLONG
)&ObjectType
->TotalNumberOfHandles
);
1255 if (Total
> ObjectType
->HighWaterNumberOfHandles
)
1258 ObjectType
->HighWaterNumberOfHandles
= Total
;
1261 /* Trace call and return */
1262 OBTRACE(OB_HANDLE_DEBUG
,
1263 "%s - Incremented count for: %p. UNNAMED HC PC %lx %lx\n",
1266 ObjectHeader
->HandleCount
,
1267 ObjectHeader
->PointerCount
);
1271 /* Release lock and return */
1272 ObpReleaseObjectLock(ObjectHeader
);
1277 * @name ObpCreateUnnamedHandle
1279 * The ObpCreateUnnamedHandle routine <FILLMEIN>
1284 * @param DesiredAccess
1287 * @param AdditionalReferences
1290 * @param HandleAttributes
1296 * @param ReturnedObject
1299 * @param ReturnedHandle
1302 * @return <FILLMEIN>.
1309 ObpCreateUnnamedHandle(IN PVOID Object
,
1310 IN ACCESS_MASK DesiredAccess
,
1311 IN ULONG AdditionalReferences
,
1312 IN ULONG HandleAttributes
,
1313 IN KPROCESSOR_MODE AccessMode
,
1314 OUT PVOID
*ReturnedObject
,
1315 OUT PHANDLE ReturnedHandle
)
1317 HANDLE_TABLE_ENTRY NewEntry
;
1318 POBJECT_HEADER ObjectHeader
;
1320 KAPC_STATE ApcState
;
1321 BOOLEAN AttachedToProcess
= FALSE
, KernelHandle
= FALSE
;
1324 ACCESS_MASK GrantedAccess
;
1325 POBJECT_TYPE ObjectType
;
1328 /* Get the object header and type */
1329 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
1330 ObjectType
= ObjectHeader
->Type
;
1331 OBTRACE(OB_HANDLE_DEBUG
,
1332 "%s - Creating handle for: %p. UNNAMED. HC PC %lx %lx\n",
1335 ObjectHeader
->HandleCount
,
1336 ObjectHeader
->PointerCount
);
1338 /* Save the object header */
1339 NewEntry
.Object
= ObjectHeader
;
1341 /* Mask out the internal attributes */
1342 NewEntry
.ObAttributes
|= HandleAttributes
& OBJ_HANDLE_ATTRIBUTES
;
1344 /* Check if this is a kernel handle */
1345 if (HandleAttributes
& OBJ_KERNEL_HANDLE
)
1347 /* Set the handle table */
1348 HandleTable
= ObpKernelHandleTable
;
1349 KernelHandle
= TRUE
;
1351 /* Check if we're not in the system process */
1352 if (PsGetCurrentProcess() != PsInitialSystemProcess
)
1354 /* Attach to the system process */
1355 KeStackAttachProcess(&PsInitialSystemProcess
->Pcb
, &ApcState
);
1356 AttachedToProcess
= TRUE
;
1361 /* Get the current handle table */
1362 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
1365 /* Increment the handle count */
1366 Status
= ObpIncrementUnnamedHandleCount(Object
,
1370 PsGetCurrentProcess());
1371 if (!NT_SUCCESS(Status
))
1374 * We failed (meaning security failure, according to NT Internals)
1377 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
1381 /* Remove what's not in the valid access mask */
1382 GrantedAccess
= DesiredAccess
& (ObjectType
->TypeInfo
.ValidAccessMask
|
1383 ACCESS_SYSTEM_SECURITY
);
1385 /* Handle extra references */
1386 if (AdditionalReferences
)
1388 /* Add them to the header */
1389 InterlockedExchangeAddSizeT(&ObjectHeader
->PointerCount
,
1390 AdditionalReferences
);
1393 /* Save the access mask */
1394 NewEntry
.GrantedAccess
= GrantedAccess
;
1397 * Create the actual handle. We'll need to do this *after* calling
1398 * ObpIncrementHandleCount to make sure that Object Security is valid
1399 * (specified in Gl00my documentation on Ob)
1401 OBTRACE(OB_HANDLE_DEBUG
,
1402 "%s - Handle Properties: [%p-%lx-%lx]\n",
1404 NewEntry
.Object
, NewEntry
.ObAttributes
& 3, NewEntry
.GrantedAccess
);
1405 Handle
= ExCreateHandle(HandleTable
, &NewEntry
);
1407 /* Make sure we got a handle */
1410 /* Check if this was a kernel handle */
1411 if (KernelHandle
) Handle
= ObMarkHandleAsKernelHandle(Handle
);
1413 /* Return handle and object */
1414 *ReturnedHandle
= Handle
;
1416 /* Return the new object only if caller wanted it biased */
1417 if ((AdditionalReferences
) && (ReturnedObject
))
1420 *ReturnedObject
= Object
;
1423 /* Detach if needed */
1424 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
1426 /* Trace and return */
1427 OBTRACE(OB_HANDLE_DEBUG
,
1428 "%s - Returning Handle: %p HC PC %lx %lx\n",
1431 ObjectHeader
->HandleCount
,
1432 ObjectHeader
->PointerCount
);
1433 return STATUS_SUCCESS
;
1436 /* Handle extra references */
1437 if (AdditionalReferences
)
1439 /* Dereference it as many times as required */
1440 InterlockedExchangeAddSizeT(&ObjectHeader
->PointerCount
,
1441 -(LONG
)AdditionalReferences
);
1444 /* Decrement the handle count and detach */
1445 ObpDecrementHandleCount(&ObjectHeader
->Body
,
1446 PsGetCurrentProcess(),
1450 /* Detach and fail */
1451 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
1452 return STATUS_INSUFFICIENT_RESOURCES
;
1456 * @name ObpCreateHandle
1458 * The ObpCreateHandle routine <FILLMEIN>
1469 * @param AccessState
1472 * @param AdditionalReferences
1475 * @param HandleAttributes
1481 * @param ReturnedObject
1484 * @param ReturnedHandle
1487 * @return <FILLMEIN>.
1489 * @remarks Cleans up the Lookup Context on return.
1494 ObpCreateHandle(IN OB_OPEN_REASON OpenReason
,
1496 IN POBJECT_TYPE Type OPTIONAL
,
1497 IN PACCESS_STATE AccessState
,
1498 IN ULONG AdditionalReferences
,
1499 IN ULONG HandleAttributes
,
1500 IN POBP_LOOKUP_CONTEXT Context
,
1501 IN KPROCESSOR_MODE AccessMode
,
1502 OUT PVOID
*ReturnedObject
,
1503 OUT PHANDLE ReturnedHandle
)
1505 HANDLE_TABLE_ENTRY NewEntry
;
1506 POBJECT_HEADER ObjectHeader
;
1508 KAPC_STATE ApcState
;
1509 BOOLEAN AttachedToProcess
= FALSE
, KernelHandle
= FALSE
;
1510 POBJECT_TYPE ObjectType
;
1513 ACCESS_MASK DesiredAccess
, GrantedAccess
;
1514 PAUX_ACCESS_DATA AuxData
;
1517 /* Get the object header and type */
1518 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
1519 ObjectType
= ObjectHeader
->Type
;
1520 OBTRACE(OB_HANDLE_DEBUG
,
1521 "%s - Creating handle for: %p. Reason: %lx. HC PC %lx %lx\n",
1525 ObjectHeader
->HandleCount
,
1526 ObjectHeader
->PointerCount
);
1528 /* Check if the types match */
1529 if ((Type
) && (ObjectType
!= Type
))
1531 /* They don't, cleanup */
1532 if (Context
) ObpReleaseLookupContext(Context
);
1533 return STATUS_OBJECT_TYPE_MISMATCH
;
1536 /* Save the object header */
1537 NewEntry
.Object
= ObjectHeader
;
1539 /* Check if this is a kernel handle */
1540 if (HandleAttributes
& OBJ_KERNEL_HANDLE
)
1542 /* Set the handle table */
1543 HandleTable
= ObpKernelHandleTable
;
1544 KernelHandle
= TRUE
;
1546 /* Check if we're not in the system process */
1547 if (PsGetCurrentProcess() != PsInitialSystemProcess
)
1549 /* Attach to the system process */
1550 KeStackAttachProcess(&PsInitialSystemProcess
->Pcb
, &ApcState
);
1551 AttachedToProcess
= TRUE
;
1556 /* Get the current handle table */
1557 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
1560 /* Increment the handle count */
1561 Status
= ObpIncrementHandleCount(Object
,
1565 PsGetCurrentProcess(),
1567 if (!NT_SUCCESS(Status
))
1570 * We failed (meaning security failure, according to NT Internals)
1573 if (Context
) ObpReleaseLookupContext(Context
);
1574 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
1578 /* Check if we are doing audits on close */
1579 if (AccessState
->GenerateOnClose
)
1581 /* Force the attribute on */
1582 HandleAttributes
|= OBJ_AUDIT_OBJECT_CLOSE
;
1585 /* Mask out the internal attributes */
1586 NewEntry
.ObAttributes
|= (HandleAttributes
& OBJ_HANDLE_ATTRIBUTES
);
1588 /* Get the original desired access */
1589 DesiredAccess
= AccessState
->RemainingDesiredAccess
|
1590 AccessState
->PreviouslyGrantedAccess
;
1592 /* Remove what's not in the valid access mask */
1593 GrantedAccess
= DesiredAccess
& (ObjectType
->TypeInfo
.ValidAccessMask
|
1594 ACCESS_SYSTEM_SECURITY
);
1596 /* Update the value in the access state */
1597 AccessState
->PreviouslyGrantedAccess
= GrantedAccess
;
1599 /* Get the auxiliary data */
1600 AuxData
= AccessState
->AuxData
;
1602 /* Handle extra references */
1603 if (AdditionalReferences
)
1605 /* Add them to the header */
1606 InterlockedExchangeAddSizeT(&ObjectHeader
->PointerCount
,
1607 AdditionalReferences
);
1610 /* Now we can release the object */
1611 if (Context
) ObpReleaseLookupContext(Context
);
1613 /* Save the access mask */
1614 NewEntry
.GrantedAccess
= GrantedAccess
;
1617 * Create the actual handle. We'll need to do this *after* calling
1618 * ObpIncrementHandleCount to make sure that Object Security is valid
1619 * (specified in Gl00my documentation on Ob)
1621 OBTRACE(OB_HANDLE_DEBUG
,
1622 "%s - Handle Properties: [%p-%lx-%lx]\n",
1624 NewEntry
.Object
, NewEntry
.ObAttributes
& 3, NewEntry
.GrantedAccess
);
1625 Handle
= ExCreateHandle(HandleTable
, &NewEntry
);
1627 /* Make sure we got a handle */
1630 /* Check if this was a kernel handle */
1631 if (KernelHandle
) Handle
= ObMarkHandleAsKernelHandle(Handle
);
1634 *ReturnedHandle
= Handle
;
1636 /* Check if we need to generate on audit */
1637 if (AccessState
->GenerateAudit
)
1639 /* Audit the handle creation */
1640 //SeAuditHandleCreation(AccessState, Handle);
1643 /* Check if this was a create */
1644 if (OpenReason
== ObCreateHandle
)
1646 /* Check if we need to audit the privileges */
1647 if ((AuxData
->PrivilegeSet
) &&
1648 (AuxData
->PrivilegeSet
->PrivilegeCount
))
1652 SePrivilegeObjectAuditAlarm(Handle
,
1654 SubjectSecurityContext
,
1656 AuxData
->PrivilegeSet
,
1658 ExGetPreviousMode());
1663 /* Return the new object only if caller wanted it biased */
1664 if ((AdditionalReferences
) && (ReturnedObject
))
1667 *ReturnedObject
= Object
;
1670 /* Detach if needed */
1671 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
1673 /* Trace and return */
1674 OBTRACE(OB_HANDLE_DEBUG
,
1675 "%s - Returning Handle: %p HC PC %lx %lx\n",
1678 ObjectHeader
->HandleCount
,
1679 ObjectHeader
->PointerCount
);
1680 return STATUS_SUCCESS
;
1683 /* Decrement the handle count and detach */
1684 ObpDecrementHandleCount(&ObjectHeader
->Body
,
1685 PsGetCurrentProcess(),
1689 /* Handle extra references */
1690 if (AdditionalReferences
)
1692 /* Check how many extra references were added */
1693 if (AdditionalReferences
> 1)
1695 /* Dereference it many times */
1696 InterlockedExchangeAddSizeT(&ObjectHeader
->PointerCount
,
1697 -(LONG
)(AdditionalReferences
- 1));
1700 /* Dereference the object one last time */
1701 ObDereferenceObject(Object
);
1704 /* Detach if necessary and fail */
1705 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
1706 return STATUS_INSUFFICIENT_RESOURCES
;
1710 * @name ObpCloseHandle
1712 * The ObpCloseHandle routine <FILLMEIN>
1720 * @return <FILLMEIN>.
1727 ObpCloseHandle(IN HANDLE Handle
,
1728 IN KPROCESSOR_MODE AccessMode
)
1731 BOOLEAN AttachedToProcess
= FALSE
;
1732 KAPC_STATE ApcState
;
1733 PHANDLE_TABLE_ENTRY HandleTableEntry
;
1735 PEPROCESS Process
= PsGetCurrentProcess();
1737 OBTRACE(OB_HANDLE_DEBUG
,
1738 "%s - Closing handle: %p\n", __FUNCTION__
, Handle
);
1740 if (AccessMode
== KernelMode
&& Handle
== (HANDLE
)-1)
1741 return STATUS_INVALID_HANDLE
;
1743 /* Check if we're dealing with a kernel handle */
1744 if (ObpIsKernelHandle(Handle
, AccessMode
))
1746 /* Use the kernel table and convert the handle */
1747 HandleTable
= ObpKernelHandleTable
;
1748 Handle
= ObKernelHandleToHandle(Handle
);
1750 /* Check if we're not in the system process */
1751 if (Process
!= PsInitialSystemProcess
)
1753 /* Attach to the system process */
1754 KeStackAttachProcess(&PsInitialSystemProcess
->Pcb
, &ApcState
);
1755 AttachedToProcess
= TRUE
;
1760 /* Use the process's handle table */
1761 HandleTable
= Process
->ObjectTable
;
1764 /* Enter a critical region to protect handle access */
1765 KeEnterCriticalRegion();
1767 /* Get the handle entry */
1768 HandleTableEntry
= ExMapHandleToPointer(HandleTable
, Handle
);
1769 if (HandleTableEntry
)
1771 /* Now close the entry */
1772 Status
= ObpCloseHandleTableEntry(HandleTable
,
1778 /* We can quit the critical region now */
1779 KeLeaveCriticalRegion();
1781 /* Detach and return success */
1782 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
1786 /* We failed, quit the critical region */
1787 KeLeaveCriticalRegion();
1790 if (AttachedToProcess
) KeUnstackDetachProcess(&ApcState
);
1792 /* Check if we have a valid handle that's not the process or thread */
1794 (Handle
!= NtCurrentProcess()) &&
1795 (Handle
!= NtCurrentThread()))
1797 /* Check if we came from user mode */
1798 if (AccessMode
!= KernelMode
)
1800 /* Check if we have no debug port */
1801 if (Process
->DebugPort
)
1803 /* Make sure we're not attached */
1804 if (!KeIsAttachedProcess())
1806 /* Raise an exception */
1807 return KeRaiseUserException(STATUS_INVALID_HANDLE
);
1813 /* This is kernel mode. Check if we're exiting */
1814 if (!(PsIsThreadTerminating(PsGetCurrentThread())) &&
1817 /* Check if the debugger is enabled */
1818 if (KdDebuggerEnabled
)
1821 KeBugCheckEx(INVALID_KERNEL_HANDLE
, (ULONG_PTR
)Handle
, 1, 0, 0);
1827 /* Set invalid status */
1828 Status
= STATUS_INVALID_HANDLE
;
1832 OBTRACE(OB_HANDLE_DEBUG
,
1833 "%s - Closed handle: %p S: %lx\n",
1834 __FUNCTION__
, Handle
, Status
);
1839 * @name ObpSetHandleAttributes
1841 * The ObpSetHandleAttributes routine <FILLMEIN>
1843 * @param HandleTableEntry
1849 * @return <FILLMEIN>.
1856 ObpSetHandleAttributes(IN OUT PHANDLE_TABLE_ENTRY HandleTableEntry
,
1857 IN ULONG_PTR Context
)
1859 POBP_SET_HANDLE_ATTRIBUTES_CONTEXT SetHandleInfo
= (PVOID
)Context
;
1860 POBJECT_HEADER ObjectHeader
= ObpGetHandleObject(HandleTableEntry
);
1862 /* Check if making the handle inheritable */
1863 if (SetHandleInfo
->Information
.Inherit
)
1865 /* Check if inheriting is not supported for this object */
1866 if (ObjectHeader
->Type
->TypeInfo
.InvalidAttributes
& OBJ_INHERIT
)
1868 /* Fail without changing anything */
1873 HandleTableEntry
->ObAttributes
|= OBJ_INHERIT
;
1877 /* Otherwise this implies we're removing the flag */
1878 HandleTableEntry
->ObAttributes
&= ~OBJ_INHERIT
;
1881 /* Check if making the handle protected */
1882 if (SetHandleInfo
->Information
.ProtectFromClose
)
1885 HandleTableEntry
->GrantedAccess
|= ObpAccessProtectCloseBit
;
1889 /* Otherwise, remove it */
1890 HandleTableEntry
->GrantedAccess
&= ~ObpAccessProtectCloseBit
;
1893 /* Return success */
1898 * @name ObpCloseHandleCallback
1900 * The ObpCloseHandleCallback routine <FILLMEIN>
1902 * @param HandleTable
1908 * @param GrantedAccess
1914 * @return <FILLMEIN>.
1921 ObpCloseHandleCallback(IN PHANDLE_TABLE_ENTRY HandleTableEntry
,
1925 POBP_CLOSE_HANDLE_CONTEXT CloseContext
= (POBP_CLOSE_HANDLE_CONTEXT
)Context
;
1927 /* Simply decrement the handle count */
1928 ObpCloseHandleTableEntry(CloseContext
->HandleTable
,
1931 CloseContext
->AccessMode
,
1937 * @name ObpDuplicateHandleCallback
1939 * The ObpDuplicateHandleCallback routine <FILLMEIN>
1941 * @param HandleTable
1944 * @param HandleTableEntry
1950 * @return <FILLMEIN>.
1957 ObpDuplicateHandleCallback(IN PEPROCESS Process
,
1958 IN PHANDLE_TABLE HandleTable
,
1959 IN PHANDLE_TABLE_ENTRY OldEntry
,
1960 IN PHANDLE_TABLE_ENTRY HandleTableEntry
)
1962 POBJECT_HEADER ObjectHeader
;
1963 BOOLEAN Ret
= FALSE
;
1964 ACCESS_STATE AccessState
;
1968 /* Make sure that the handle is inheritable */
1969 Ret
= (HandleTableEntry
->ObAttributes
& OBJ_INHERIT
) != 0;
1972 /* Get the object header */
1973 ObjectHeader
= ObpGetHandleObject(HandleTableEntry
);
1975 /* Increment the pointer count */
1976 InterlockedIncrementSizeT(&ObjectHeader
->PointerCount
);
1978 /* Release the handle lock */
1979 ExUnlockHandleTableEntry(HandleTable
, OldEntry
);
1981 /* Setup the access state */
1982 AccessState
.PreviouslyGrantedAccess
= HandleTableEntry
->GrantedAccess
;
1984 /* Call the shared routine for incrementing handles */
1985 Status
= ObpIncrementHandleCount(&ObjectHeader
->Body
,
1988 HandleTableEntry
->ObAttributes
& OBJ_HANDLE_ATTRIBUTES
,
1991 if (!NT_SUCCESS(Status
))
1993 /* Return failure */
1994 ObDereferenceObject(&ObjectHeader
->Body
);
2000 /* Release the handle lock */
2001 ExUnlockHandleTableEntry(HandleTable
, OldEntry
);
2004 /* Return duplication result */
2009 * @name ObClearProcessHandleTable
2011 * The ObClearProcessHandleTable routine clears the handle table
2012 * of the given process.
2015 * The process of which the handle table should be cleared.
2024 ObClearProcessHandleTable(IN PEPROCESS Process
)
2026 PHANDLE_TABLE HandleTable
;
2027 OBP_CLOSE_HANDLE_CONTEXT Context
;
2028 KAPC_STATE ApcState
;
2029 BOOLEAN AttachedToProcess
= FALSE
;
2033 /* Ensure the handle table doesn't go away while we use it */
2034 HandleTable
= ObReferenceProcessHandleTable(Process
);
2035 if (!HandleTable
) return;
2037 /* Attach to the current process if needed */
2038 if (PsGetCurrentProcess() != Process
)
2040 KeStackAttachProcess(&Process
->Pcb
, &ApcState
);
2041 AttachedToProcess
= TRUE
;
2044 /* Enter a critical region */
2045 KeEnterCriticalRegion();
2047 /* Fill out the context */
2048 Context
.AccessMode
= UserMode
;
2049 Context
.HandleTable
= HandleTable
;
2051 /* Sweep the handle table to close all handles */
2052 ExSweepHandleTable(HandleTable
,
2053 ObpCloseHandleCallback
,
2056 /* Leave the critical region */
2057 KeLeaveCriticalRegion();
2059 /* Detach if needed */
2060 if (AttachedToProcess
)
2061 KeUnstackDetachProcess(&ApcState
);
2063 /* Let the handle table go */
2064 ObDereferenceProcessHandleTable(Process
);
2068 * @name ObInitProcess
2070 * The ObInitProcess routine initializes the handle table for the process
2071 * to be initialized, by either creating a new one or duplicating it from
2072 * the parent process.
2075 * A parent process (optional).
2078 * The process to initialize.
2080 * @return Success or failure.
2087 ObInitProcess(IN PEPROCESS Parent OPTIONAL
,
2088 IN PEPROCESS Process
)
2090 PHANDLE_TABLE ParentTable
, ObjectTable
;
2092 /* Check for a parent */
2095 /* Reference the parent's table */
2096 ParentTable
= ObReferenceProcessHandleTable(Parent
);
2097 if (!ParentTable
) return STATUS_PROCESS_IS_TERMINATING
;
2100 ObjectTable
= ExDupHandleTable(Process
,
2102 ObpDuplicateHandleCallback
,
2107 /* Otherwise just create a new table */
2109 ObjectTable
= ExCreateHandleTable(Process
);
2112 /* Make sure we have a table */
2116 Process
->ObjectTable
= ObjectTable
;
2118 /* Check for auditing */
2119 if (SeDetailedAuditingWithToken(NULL
))
2122 DPRINT1("Need auditing!\n");
2125 /* Get rid of the old table now */
2126 if (ParentTable
) ObDereferenceProcessHandleTable(Parent
);
2129 return STATUS_SUCCESS
;
2134 Process
->ObjectTable
= NULL
;
2135 if (ParentTable
) ObDereferenceProcessHandleTable(Parent
);
2136 return STATUS_INSUFFICIENT_RESOURCES
;
2141 * @name ObKillProcess
2143 * The ObKillProcess routine performs rundown operations on the process,
2144 * then clears and destroys its handle table.
2147 * The process to be killed.
2151 * @remarks Called by the Object Manager cleanup code (kernel)
2152 * when a process is to be destroyed.
2157 ObKillProcess(IN PEPROCESS Process
)
2159 PHANDLE_TABLE HandleTable
;
2160 OBP_CLOSE_HANDLE_CONTEXT Context
;
2164 /* Wait for process rundown and then complete it */
2165 ExWaitForRundownProtectionRelease(&Process
->RundownProtect
);
2166 ExRundownCompleted(&Process
->RundownProtect
);
2168 /* Get the object table */
2169 HandleTable
= Process
->ObjectTable
;
2170 if (!HandleTable
) return;
2172 /* Disable hard errors while we close handles */
2173 HardErrors
= IoSetThreadHardErrorMode(FALSE
);
2175 /* Enter a critical region */
2176 KeEnterCriticalRegion();
2178 /* Fill out the context */
2179 Context
.AccessMode
= KernelMode
;
2180 Context
.HandleTable
= HandleTable
;
2182 /* Sweep the handle table to close all handles */
2183 ExSweepHandleTable(HandleTable
,
2184 ObpCloseHandleCallback
,
2186 ASSERT(HandleTable
->HandleCount
== 0);
2188 /* Leave the critical region */
2189 KeLeaveCriticalRegion();
2191 /* Re-enable hard errors */
2192 IoSetThreadHardErrorMode(HardErrors
);
2194 /* Destroy the object table */
2195 Process
->ObjectTable
= NULL
;
2196 ExDestroyHandleTable(HandleTable
, NULL
);
2201 ObDuplicateObject(IN PEPROCESS SourceProcess
,
2202 IN HANDLE SourceHandle
,
2203 IN PEPROCESS TargetProcess OPTIONAL
,
2204 IN PHANDLE TargetHandle OPTIONAL
,
2205 IN ACCESS_MASK DesiredAccess
,
2206 IN ULONG HandleAttributes
,
2208 IN KPROCESSOR_MODE PreviousMode
)
2210 HANDLE_TABLE_ENTRY NewHandleEntry
;
2211 BOOLEAN AttachedToProcess
= FALSE
;
2213 POBJECT_HEADER ObjectHeader
;
2214 POBJECT_TYPE ObjectType
;
2216 KAPC_STATE ApcState
;
2218 ACCESS_MASK TargetAccess
, SourceAccess
;
2219 ACCESS_STATE AccessState
;
2220 PACCESS_STATE PassedAccessState
= NULL
;
2221 AUX_ACCESS_DATA AuxData
;
2222 PHANDLE_TABLE HandleTable
;
2223 OBJECT_HANDLE_INFORMATION HandleInformation
;
2225 BOOLEAN KernelHandle
= FALSE
;
2228 OBTRACE(OB_HANDLE_DEBUG
,
2229 "%s - Duplicating handle: %p for %p into %p\n",
2235 /* Assume failure */
2236 if (TargetHandle
) *TargetHandle
= NULL
;
2238 /* Check if we're not duplicating the same access */
2239 if (!(Options
& DUPLICATE_SAME_ACCESS
))
2241 /* Validate the desired access */
2242 Status
= STATUS_SUCCESS
; //ObpValidateDesiredAccess(DesiredAccess);
2243 if (!NT_SUCCESS(Status
)) return Status
;
2246 /* Reference the object table */
2247 HandleTable
= ObReferenceProcessHandleTable(SourceProcess
);
2248 if (!HandleTable
) return STATUS_PROCESS_IS_TERMINATING
;
2250 /* Reference the process object */
2251 Status
= ObpReferenceProcessObjectByHandle(SourceHandle
,
2258 if (!NT_SUCCESS(Status
))
2261 ObDereferenceProcessHandleTable(SourceProcess
);
2266 /* Check if we have to don't have to audit object close */
2267 if (!(HandleInformation
.HandleAttributes
& OBJ_AUDIT_OBJECT_CLOSE
))
2269 /* Then there is no audit mask */
2274 /* Check if there's no target process */
2277 /* Check if the caller wanted actual duplication */
2278 if (!(Options
& DUPLICATE_CLOSE_SOURCE
))
2280 /* Invalid request */
2281 Status
= STATUS_INVALID_PARAMETER
;
2285 /* Otherwise, do the attach */
2286 KeStackAttachProcess(&SourceProcess
->Pcb
, &ApcState
);
2288 /* Close the handle and detach */
2289 NtClose(SourceHandle
);
2290 KeUnstackDetachProcess(&ApcState
);
2294 ObDereferenceProcessHandleTable(SourceProcess
);
2295 ObDereferenceObject(SourceObject
);
2299 /* Create a kernel handle if asked, but only in the system process */
2300 if (PreviousMode
== KernelMode
&&
2301 HandleAttributes
& OBJ_KERNEL_HANDLE
&&
2302 TargetProcess
== PsInitialSystemProcess
)
2304 KernelHandle
= TRUE
;
2307 /* Get the target handle table */
2308 HandleTable
= ObReferenceProcessHandleTable(TargetProcess
);
2311 /* Check if the caller wanted us to close the handle */
2312 if (Options
& DUPLICATE_CLOSE_SOURCE
)
2315 KeStackAttachProcess(&SourceProcess
->Pcb
, &ApcState
);
2317 /* Close the handle and detach */
2318 NtClose(SourceHandle
);
2319 KeUnstackDetachProcess(&ApcState
);
2323 ObDereferenceProcessHandleTable(SourceProcess
);
2324 ObDereferenceObject(SourceObject
);
2325 return STATUS_PROCESS_IS_TERMINATING
;
2328 /* Get the source access */
2329 SourceAccess
= HandleInformation
.GrantedAccess
;
2331 /* Check if we're not in the target process */
2332 if (TargetProcess
!= PsGetCurrentProcess())
2335 KeStackAttachProcess(&TargetProcess
->Pcb
, &ApcState
);
2336 AttachedToProcess
= TRUE
;
2339 /* Check if we're duplicating the attributes */
2340 if (Options
& DUPLICATE_SAME_ATTRIBUTES
)
2342 /* Duplicate them */
2343 HandleAttributes
= HandleInformation
.HandleAttributes
;
2347 /* Don't allow caller to bypass auditing */
2348 HandleAttributes
|= HandleInformation
.HandleAttributes
&
2349 OBJ_AUDIT_OBJECT_CLOSE
;
2352 /* Check if we're duplicating the access */
2353 if (Options
& DUPLICATE_SAME_ACCESS
) DesiredAccess
= SourceAccess
;
2355 /* Get object data */
2356 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(SourceObject
);
2357 ObjectType
= ObjectHeader
->Type
;
2359 /* Fill out the entry */
2360 RtlZeroMemory(&NewHandleEntry
, sizeof(HANDLE_TABLE_ENTRY
));
2361 NewHandleEntry
.Object
= ObjectHeader
;
2362 NewHandleEntry
.ObAttributes
|= (HandleAttributes
& OBJ_HANDLE_ATTRIBUTES
);
2364 /* Check if we're using a generic mask */
2365 if (DesiredAccess
& GENERIC_ACCESS
)
2368 RtlMapGenericMask(&DesiredAccess
,
2369 &ObjectType
->TypeInfo
.GenericMapping
);
2372 /* Set the target access, always propagate ACCESS_SYSTEM_SECURITY */
2373 TargetAccess
= DesiredAccess
& (ObjectType
->TypeInfo
.ValidAccessMask
|
2374 ACCESS_SYSTEM_SECURITY
);
2375 NewHandleEntry
.GrantedAccess
= TargetAccess
;
2377 /* Check if we're asking for new access */
2378 if (TargetAccess
& ~SourceAccess
)
2380 /* We are. We need the security procedure to validate this */
2381 if (ObjectType
->TypeInfo
.SecurityProcedure
== SeDefaultObjectMethod
)
2383 /* Use our built-in access state */
2384 PassedAccessState
= &AccessState
;
2385 Status
= SeCreateAccessState(&AccessState
,
2388 &ObjectType
->TypeInfo
.GenericMapping
);
2392 /* Otherwise we can't allow this privilege elevation */
2393 Status
= STATUS_ACCESS_DENIED
;
2398 /* We don't need an access state */
2399 Status
= STATUS_SUCCESS
;
2402 /* Make sure the access state was created OK */
2403 if (NT_SUCCESS(Status
))
2405 /* Add a new handle */
2406 Status
= ObpIncrementHandleCount(SourceObject
,
2410 PsGetCurrentProcess(),
2414 /* Check if we were attached */
2415 if (AttachedToProcess
)
2417 /* We can safely detach now */
2418 KeUnstackDetachProcess(&ApcState
);
2419 AttachedToProcess
= FALSE
;
2422 /* Check if we have to close the source handle */
2423 if (Options
& DUPLICATE_CLOSE_SOURCE
)
2425 /* Attach and close */
2426 KeStackAttachProcess(&SourceProcess
->Pcb
, &ApcState
);
2427 NtClose(SourceHandle
);
2428 KeUnstackDetachProcess(&ApcState
);
2431 /* Check if we had an access state */
2432 if (PassedAccessState
) SeDeleteAccessState(PassedAccessState
);
2434 /* Now check if incrementing actually failed */
2435 if (!NT_SUCCESS(Status
))
2437 /* Dereference handle tables */
2438 ObDereferenceProcessHandleTable(SourceProcess
);
2439 ObDereferenceProcessHandleTable(TargetProcess
);
2441 /* Dereference the source object */
2442 ObDereferenceObject(SourceObject
);
2446 if (NewHandleEntry
.ObAttributes
& OBJ_PROTECT_CLOSE
)
2448 NewHandleEntry
.ObAttributes
&= ~OBJ_PROTECT_CLOSE
;
2449 NewHandleEntry
.GrantedAccess
|= ObpAccessProtectCloseBit
;
2452 /* Now create the handle */
2453 NewHandle
= ExCreateHandle(HandleTable
, &NewHandleEntry
);
2456 /* Undo the increment */
2457 ObpDecrementHandleCount(SourceObject
,
2462 /* Deference the object and set failure status */
2463 ObDereferenceObject(SourceObject
);
2464 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2467 /* Mark it as a kernel handle if requested */
2470 NewHandle
= ObMarkHandleAsKernelHandle(NewHandle
);
2473 /* Return the handle */
2474 if (TargetHandle
) *TargetHandle
= NewHandle
;
2476 /* Dereference handle tables */
2477 ObDereferenceProcessHandleTable(SourceProcess
);
2478 ObDereferenceProcessHandleTable(TargetProcess
);
2481 OBTRACE(OB_HANDLE_DEBUG
,
2482 "%s - Duplicated handle: %p for %p into %p. Source: %p HC PC %lx %lx\n",
2488 ObjectHeader
->PointerCount
,
2489 ObjectHeader
->HandleCount
);
2493 /* PUBLIC FUNCTIONS *********************************************************/
2496 * @name ObOpenObjectByName
2499 * The ObOpenObjectByName routine <FILLMEIN>
2501 * @param ObjectAttributes
2510 * @param PassedAccessState
2513 * @param DesiredAccess
2516 * @param ParseContext
2522 * @return <FILLMEIN>.
2529 ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2530 IN POBJECT_TYPE ObjectType
,
2531 IN KPROCESSOR_MODE AccessMode
,
2532 IN PACCESS_STATE PassedAccessState
,
2533 IN ACCESS_MASK DesiredAccess
,
2534 IN OUT PVOID ParseContext
,
2537 PVOID Object
= NULL
;
2538 UNICODE_STRING ObjectName
;
2539 NTSTATUS Status
, Status2
;
2540 POBJECT_HEADER ObjectHeader
;
2541 PGENERIC_MAPPING GenericMapping
= NULL
;
2542 OB_OPEN_REASON OpenReason
;
2543 POB_TEMP_BUFFER TempBuffer
;
2546 /* Assume failure */
2549 /* Check if we didn't get any Object Attributes */
2550 if (!ObjectAttributes
)
2552 /* Fail with special status code */
2553 return STATUS_INVALID_PARAMETER
;
2556 /* Allocate the temporary buffer */
2557 TempBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2558 sizeof(OB_TEMP_BUFFER
),
2559 TAG_OB_TEMP_STORAGE
);
2560 if (!TempBuffer
) return STATUS_INSUFFICIENT_RESOURCES
;
2562 /* Capture all the info */
2563 Status
= ObpCaptureObjectCreateInformation(ObjectAttributes
,
2567 &TempBuffer
->ObjectCreateInfo
,
2569 if (!NT_SUCCESS(Status
))
2572 ExFreePoolWithTag(TempBuffer
, TAG_OB_TEMP_STORAGE
);
2576 /* Check if we didn't get an access state */
2577 if (!PassedAccessState
)
2579 /* Try to get the generic mapping if we can */
2580 if (ObjectType
) GenericMapping
= &ObjectType
->TypeInfo
.GenericMapping
;
2582 /* Use our built-in access state */
2583 PassedAccessState
= &TempBuffer
->LocalAccessState
;
2584 Status
= SeCreateAccessState(&TempBuffer
->LocalAccessState
,
2585 &TempBuffer
->AuxData
,
2588 if (!NT_SUCCESS(Status
)) goto Quickie
;
2591 /* Get the security descriptor */
2592 if (TempBuffer
->ObjectCreateInfo
.SecurityDescriptor
)
2594 /* Save it in the access state */
2595 PassedAccessState
->SecurityDescriptor
=
2596 TempBuffer
->ObjectCreateInfo
.SecurityDescriptor
;
2599 /* Validate the access mask */
2600 Status
= ObpValidateAccessMask(PassedAccessState
);
2601 if (!NT_SUCCESS(Status
))
2603 /* Cleanup after lookup */
2604 ObpReleaseLookupContext(&TempBuffer
->LookupContext
);
2608 /* Now do the lookup */
2609 Status
= ObpLookupObjectName(TempBuffer
->ObjectCreateInfo
.RootDirectory
,
2611 TempBuffer
->ObjectCreateInfo
.Attributes
,
2615 TempBuffer
->ObjectCreateInfo
.SecurityQos
,
2618 &TempBuffer
->LookupContext
,
2620 if (!NT_SUCCESS(Status
))
2622 /* Cleanup after lookup */
2623 ObpReleaseLookupContext(&TempBuffer
->LookupContext
);
2627 /* Check if this object has create information */
2628 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
2629 if (ObjectHeader
->Flags
& OB_FLAG_CREATE_INFO
)
2631 /* Then we are creating a new handle */
2632 OpenReason
= ObCreateHandle
;
2634 /* Check if we still have create info */
2635 if (ObjectHeader
->ObjectCreateInfo
)
2638 ObpFreeObjectCreateInformation(ObjectHeader
->
2640 ObjectHeader
->ObjectCreateInfo
= NULL
;
2645 /* Otherwise, we are merely opening it */
2646 OpenReason
= ObOpenHandle
;
2649 /* Check if we have invalid object attributes */
2650 if (ObjectHeader
->Type
->TypeInfo
.InvalidAttributes
&
2651 TempBuffer
->ObjectCreateInfo
.Attributes
)
2653 /* Set failure code */
2654 Status
= STATUS_INVALID_PARAMETER
;
2656 /* Cleanup after lookup */
2657 ObpReleaseLookupContext(&TempBuffer
->LookupContext
);
2659 /* Dereference the object */
2660 ObDereferenceObject(Object
);
2664 /* Create the actual handle now */
2665 Status2
= ObpCreateHandle(OpenReason
,
2670 TempBuffer
->ObjectCreateInfo
.Attributes
,
2671 &TempBuffer
->LookupContext
,
2675 if (!NT_SUCCESS(Status2
))
2677 ObDereferenceObject(Object
);
2683 /* Delete the access state */
2684 if (PassedAccessState
== &TempBuffer
->LocalAccessState
)
2686 SeDeleteAccessState(PassedAccessState
);
2690 /* Release the object attributes and temporary buffer */
2691 ObpReleaseObjectCreateInformation(&TempBuffer
->ObjectCreateInfo
);
2692 if (ObjectName
.Buffer
) ObpFreeObjectNameBuffer(&ObjectName
);
2693 ExFreePoolWithTag(TempBuffer
, TAG_OB_TEMP_STORAGE
);
2696 OBTRACE(OB_HANDLE_DEBUG
,
2697 "%s - returning Object %p with PC S: %lx %lx\n",
2700 Object
? OBJECT_TO_OBJECT_HEADER(Object
)->PointerCount
: -1,
2706 * @name ObOpenObjectByPointer
2709 * The ObOpenObjectByPointer routine <FILLMEIN>
2714 * @param HandleAttributes
2717 * @param PassedAccessState
2720 * @param DesiredAccess
2732 * @return <FILLMEIN>.
2739 ObOpenObjectByPointer(IN PVOID Object
,
2740 IN ULONG HandleAttributes
,
2741 IN PACCESS_STATE PassedAccessState
,
2742 IN ACCESS_MASK DesiredAccess
,
2743 IN POBJECT_TYPE ObjectType
,
2744 IN KPROCESSOR_MODE AccessMode
,
2747 POBJECT_HEADER Header
;
2749 ACCESS_STATE AccessState
;
2750 AUX_ACCESS_DATA AuxData
;
2753 /* Assume failure */
2756 /* Reference the object */
2757 Status
= ObReferenceObjectByPointer(Object
,
2761 if (!NT_SUCCESS(Status
)) return Status
;
2763 /* Get the Header Info */
2764 Header
= OBJECT_TO_OBJECT_HEADER(Object
);
2766 /* Check if we didn't get an access state */
2767 if (!PassedAccessState
)
2769 /* Use our built-in access state */
2770 PassedAccessState
= &AccessState
;
2771 Status
= SeCreateAccessState(&AccessState
,
2774 &Header
->Type
->TypeInfo
.GenericMapping
);
2775 if (!NT_SUCCESS(Status
))
2778 ObDereferenceObject(Object
);
2783 /* Check if we have invalid object attributes */
2784 if (Header
->Type
->TypeInfo
.InvalidAttributes
& HandleAttributes
)
2786 /* Delete the access state */
2787 if (PassedAccessState
== &AccessState
)
2789 SeDeleteAccessState(PassedAccessState
);
2792 /* Dereference the object */
2793 ObDereferenceObject(Object
);
2794 return STATUS_INVALID_PARAMETER
;
2797 /* Create the handle */
2798 Status
= ObpCreateHandle(ObOpenHandle
,
2808 if (!NT_SUCCESS(Status
)) ObDereferenceObject(Object
);
2810 /* Delete the access state */
2811 if (PassedAccessState
== &AccessState
)
2813 SeDeleteAccessState(PassedAccessState
);
2817 OBTRACE(OB_HANDLE_DEBUG
,
2818 "%s - returning Object with PC S: %lx %lx\n",
2820 OBJECT_TO_OBJECT_HEADER(Object
)->PointerCount
,
2826 * @name ObFindHandleForObject
2829 * The ObFindHandleForObject routine <FILLMEIN>
2840 * @param HandleInformation
2843 * @param HandleReturn
2846 * @return <FILLMEIN>.
2853 ObFindHandleForObject(IN PEPROCESS Process
,
2855 IN POBJECT_TYPE ObjectType
,
2856 IN POBJECT_HANDLE_INFORMATION HandleInformation
,
2859 OBP_FIND_HANDLE_DATA FindData
;
2860 BOOLEAN Result
= FALSE
;
2863 /* Make sure we have an object table */
2864 ObjectTable
= ObReferenceProcessHandleTable(Process
);
2867 /* Check if we have an object */
2870 /* Set its header */
2871 FindData
.ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
2875 /* Otherwise, no object to match*/
2876 FindData
.ObjectHeader
= NULL
;
2879 /* Set other information */
2880 FindData
.ObjectType
= ObjectType
;
2881 FindData
.HandleInformation
= HandleInformation
;
2883 /* Enumerate the handle table */
2884 if (ExEnumHandleTable(Process
->ObjectTable
,
2885 ObpEnumFindHandleProcedure
,
2893 /* Let go of the table */
2894 ObDereferenceProcessHandleTable(Process
);
2897 /* Return the result */
2902 * @name ObInsertObject
2905 * The ObInsertObject routine <FILLMEIN>
2910 * @param PassedAccessState
2913 * @param DesiredAccess
2916 * @param AdditionalReferences
2919 * @param ReferencedObject
2925 * @return <FILLMEIN>.
2932 ObInsertObject(IN PVOID Object
,
2933 IN PACCESS_STATE AccessState OPTIONAL
,
2934 IN ACCESS_MASK DesiredAccess
,
2935 IN ULONG ObjectPointerBias
,
2936 OUT PVOID
*NewObject OPTIONAL
,
2939 POBJECT_CREATE_INFORMATION ObjectCreateInfo
;
2940 POBJECT_HEADER ObjectHeader
;
2941 POBJECT_TYPE ObjectType
;
2942 PUNICODE_STRING ObjectName
;
2944 PSECURITY_DESCRIPTOR ParentDescriptor
= NULL
;
2945 BOOLEAN SdAllocated
= FALSE
;
2946 POBJECT_HEADER_NAME_INFO ObjectNameInfo
;
2947 OBP_LOOKUP_CONTEXT Context
;
2948 ACCESS_STATE LocalAccessState
;
2949 AUX_ACCESS_DATA AuxData
;
2950 OB_OPEN_REASON OpenReason
;
2951 KPROCESSOR_MODE PreviousMode
;
2952 NTSTATUS Status
= STATUS_SUCCESS
, RealStatus
;
2953 BOOLEAN IsNewObject
;
2956 /* Get the Header */
2957 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
2959 /* Detect invalid insert */
2960 if (!(ObjectHeader
->Flags
& OB_FLAG_CREATE_INFO
))
2962 /* Display warning and break into debugger */
2963 DPRINT1("OB: Attempting to insert existing object %p\n", Object
);
2966 /* Allow debugger to continue */
2967 ObDereferenceObject(Object
);
2968 return STATUS_INVALID_PARAMETER
;
2971 /* Get the create and name info, as well as the object type */
2972 ObjectCreateInfo
= ObjectHeader
->ObjectCreateInfo
;
2973 ObjectNameInfo
= ObpReferenceNameInfo(ObjectHeader
);
2974 ObjectType
= ObjectHeader
->Type
;
2977 /* Check if this is an named object */
2978 if ((ObjectNameInfo
) && (ObjectNameInfo
->Name
.Buffer
))
2980 /* Get the object name */
2981 ObjectName
= &ObjectNameInfo
->Name
;
2986 ((ObjectPointerBias
== 0) &&
2987 (ObjectName
== NULL
) &&
2988 (ObjectType
->TypeInfo
.SecurityRequired
) &&
2989 (NewObject
== NULL
)));
2991 /* Check if the object is unnamed and also doesn't have security */
2992 PreviousMode
= KeGetPreviousMode();
2993 if (!(ObjectType
->TypeInfo
.SecurityRequired
) && !(ObjectName
))
2995 /* Assume failure */
2997 ObjectHeader
->ObjectCreateInfo
= NULL
;
2999 /* Create the handle */
3000 Status
= ObpCreateUnnamedHandle(Object
,
3002 ObjectPointerBias
+ 1,
3003 ObjectCreateInfo
->Attributes
,
3008 /* Free the create information */
3009 ObpFreeObjectCreateInformation(ObjectCreateInfo
);
3011 /* Release the object name information */
3012 ObpDereferenceNameInfo(ObjectNameInfo
);
3014 /* Remove the extra keep-alive reference */
3015 ObDereferenceObject(Object
);
3018 OBTRACE(OB_HANDLE_DEBUG
,
3019 "%s - returning Object with PC S: %lx %lx\n",
3021 ObjectHeader
->PointerCount
,
3026 /* Check if we didn't get an access state */
3029 /* Use our built-in access state */
3030 AccessState
= &LocalAccessState
;
3031 Status
= SeCreateAccessState(&LocalAccessState
,
3034 &ObjectType
->TypeInfo
.GenericMapping
);
3035 if (!NT_SUCCESS(Status
))
3038 ObpDereferenceNameInfo(ObjectNameInfo
);
3039 ObDereferenceObject(Object
);
3044 /* Save the security descriptor */
3045 AccessState
->SecurityDescriptor
= ObjectCreateInfo
->SecurityDescriptor
;
3047 /* Validate the access mask */
3048 Status
= ObpValidateAccessMask(AccessState
);
3049 if (!NT_SUCCESS(Status
))
3052 ObpDereferenceNameInfo(ObjectNameInfo
);
3053 ObDereferenceObject(Object
);
3057 /* Setup a lookup context */
3058 ObpInitializeLookupContext(&Context
);
3059 InsertObject
= Object
;
3060 OpenReason
= ObCreateHandle
;
3062 /* Check if the object is named */
3066 Status
= ObpLookupObjectName(ObjectCreateInfo
->RootDirectory
,
3068 ObjectCreateInfo
->Attributes
,
3070 (ObjectHeader
->Flags
& OB_FLAG_KERNEL_MODE
) ?
3071 KernelMode
: UserMode
,
3072 ObjectCreateInfo
->ParseContext
,
3073 ObjectCreateInfo
->SecurityQos
,
3079 /* Check if we found an object that doesn't match the one requested */
3080 if ((NT_SUCCESS(Status
)) && (InsertObject
) && (Object
!= InsertObject
))
3082 /* This means we're opening an object, not creating a new one */
3083 OpenReason
= ObOpenHandle
;
3085 /* Make sure the caller said it's OK to do this */
3086 if (ObjectCreateInfo
->Attributes
& OBJ_OPENIF
)
3088 /* He did, but did he want this type? */
3089 if (ObjectType
!= OBJECT_TO_OBJECT_HEADER(InsertObject
)->Type
)
3091 /* Wrong type, so fail */
3092 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
3096 /* Right type, so warn */
3097 Status
= STATUS_OBJECT_NAME_EXISTS
;
3102 /* Check if this was a symbolic link */
3103 if (OBJECT_TO_OBJECT_HEADER(InsertObject
)->Type
==
3104 ObpSymbolicLinkObjectType
)
3106 /* Dereference it */
3107 ObDereferenceObject(InsertObject
);
3110 /* Caller wanted to create a new object, fail */
3111 Status
= STATUS_OBJECT_NAME_COLLISION
;
3115 /* Check if anything until now failed */
3116 if (!NT_SUCCESS(Status
))
3118 /* Cleanup after lookup */
3119 ObpReleaseLookupContext(&Context
);
3121 /* Remove query reference that we added */
3122 ObpDereferenceNameInfo(ObjectNameInfo
);
3124 /* Dereference the object and delete the access state */
3125 ObDereferenceObject(Object
);
3126 if (AccessState
== &LocalAccessState
)
3128 /* We used a local one; delete it */
3129 SeDeleteAccessState(AccessState
);
3132 /* Return failure code */
3137 /* Check if this is a symbolic link */
3138 if (ObjectType
== ObpSymbolicLinkObjectType
)
3140 /* Create the internal name */
3141 ObpCreateSymbolicLinkName(Object
);
3146 /* Now check if this object is being created */
3147 if (InsertObject
== Object
)
3149 /* Check if it's named or forces security */
3150 if ((ObjectName
) || (ObjectType
->TypeInfo
.SecurityRequired
))
3152 /* Make sure it's inserted into an object directory */
3153 if ((ObjectNameInfo
) && (ObjectNameInfo
->Directory
))
3155 /* Get the current descriptor */
3156 ObGetObjectSecurity(ObjectNameInfo
->Directory
,
3162 Status
= ObAssignSecurity(AccessState
,
3167 /* Check if we captured one */
3168 if (ParentDescriptor
)
3170 /* We did, release it */
3171 ObReleaseObjectSecurity(ParentDescriptor
, SdAllocated
);
3173 else if (NT_SUCCESS(Status
))
3175 /* Other we didn't, but we were able to use the current SD */
3176 SeReleaseSecurityDescriptor(ObjectCreateInfo
->SecurityDescriptor
,
3177 ObjectCreateInfo
->ProbeMode
,
3180 /* Clear the current one */
3181 AccessState
->SecurityDescriptor
=
3182 ObjectCreateInfo
->SecurityDescriptor
= NULL
;
3186 /* Check if anything until now failed */
3187 if (!NT_SUCCESS(Status
))
3189 /* Check if the directory was added */
3190 if (Context
.DirectoryLocked
)
3192 /* Weird case where we need to do a manual delete */
3193 DPRINT1("Unhandled path\n");
3197 /* Cleanup the lookup */
3198 ObpReleaseLookupContext(&Context
);
3200 /* Remove query reference that we added */
3201 ObpDereferenceNameInfo(ObjectNameInfo
);
3203 /* Dereference the object and delete the access state */
3204 ObDereferenceObject(Object
);
3205 if (AccessState
== &LocalAccessState
)
3207 /* We used a local one; delete it */
3208 SeDeleteAccessState(AccessState
);
3211 /* Return failure code */
3217 /* Save the actual status until here */
3218 RealStatus
= Status
;
3220 /* Check if caller wants us to create a handle */
3221 ObjectHeader
->ObjectCreateInfo
= NULL
;
3224 /* Create the handle */
3225 Status
= ObpCreateHandle(OpenReason
,
3229 ObjectPointerBias
+ 1,
3230 ObjectCreateInfo
->Attributes
,
3235 if (!NT_SUCCESS(Status
))
3237 /* If the object had a name, backout everything */
3238 if (ObjectName
) ObpDeleteNameCheck(Object
);
3240 /* Return the status of the failure */
3242 RealStatus
= Status
;
3245 /* Remove a query reference */
3246 ObpDereferenceNameInfo(ObjectNameInfo
);
3248 /* Remove the extra keep-alive reference */
3249 ObDereferenceObject(Object
);
3253 /* Otherwise, lock the object */
3254 ObpAcquireObjectLock(ObjectHeader
);
3256 /* And charge quota for the process to make it appear as used */
3257 RealStatus
= ObpChargeQuotaForObject(ObjectHeader
,
3261 /* Release the lock */
3262 ObpReleaseObjectLock(ObjectHeader
);
3264 /* Check if we failed and dereference the object if so */
3265 if (!NT_SUCCESS(RealStatus
)) ObDereferenceObject(Object
);
3268 /* We can delete the Create Info now */
3269 ObpFreeObjectCreateInformation(ObjectCreateInfo
);
3271 /* Check if we created our own access state and delete it if so */
3272 if (AccessState
== &LocalAccessState
) SeDeleteAccessState(AccessState
);
3274 /* Return status code */
3275 OBTRACE(OB_HANDLE_DEBUG
,
3276 "%s - returning Object with PC RS/S: %lx %lx %lx\n",
3278 OBJECT_TO_OBJECT_HEADER(Object
)->PointerCount
,
3279 RealStatus
, Status
);
3284 * @name ObSetHandleAttributes
3285 * @implemented NT5.1
3287 * The ObSetHandleAttributes routine <FILLMEIN>
3292 * @param HandleFlags
3295 * @param PreviousMode
3298 * @return <FILLMEIN>.
3305 ObSetHandleAttributes(IN HANDLE Handle
,
3306 IN POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags
,
3307 IN KPROCESSOR_MODE PreviousMode
)
3309 OBP_SET_HANDLE_ATTRIBUTES_CONTEXT SetHandleAttributesContext
;
3310 BOOLEAN Result
, AttachedToSystemProcess
= FALSE
;
3311 PHANDLE_TABLE HandleTable
;
3312 KAPC_STATE ApcState
;
3315 /* Check if this is a kernel handle */
3316 if (ObpIsKernelHandle(Handle
, PreviousMode
))
3318 /* Use the kernel table and convert the handle */
3319 HandleTable
= ObpKernelHandleTable
;
3320 Handle
= ObKernelHandleToHandle(Handle
);
3322 /* Check if we're not in the system process */
3323 if (PsGetCurrentProcess() != PsInitialSystemProcess
)
3325 /* Attach to the system process */
3326 KeStackAttachProcess(&PsInitialSystemProcess
->Pcb
, &ApcState
);
3327 AttachedToSystemProcess
= TRUE
;
3332 /* Get the current process' handle table */
3333 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
3336 /* Initialize the handle attribute context */
3337 SetHandleAttributesContext
.PreviousMode
= PreviousMode
;
3338 SetHandleAttributesContext
.Information
= *HandleFlags
;
3340 /* Invoke the ObpSetHandleAttributes callback */
3341 Result
= ExChangeHandle(HandleTable
,
3343 ObpSetHandleAttributes
,
3344 (ULONG_PTR
)&SetHandleAttributesContext
);
3346 /* Did we attach to the system process? */
3347 if (AttachedToSystemProcess
)
3349 /* Detach from it */
3350 KeUnstackDetachProcess(&ApcState
);
3353 /* Return the result as an NTSTATUS value */
3354 return Result
? STATUS_SUCCESS
: STATUS_ACCESS_DENIED
;
3358 * @name ObCloseHandle
3359 * @implemented NT5.1
3361 * The ObCloseHandle routine <FILLMEIN>
3369 * @return <FILLMEIN>.
3376 ObCloseHandle(IN HANDLE Handle
,
3377 IN KPROCESSOR_MODE AccessMode
)
3379 /* Call the internal API */
3380 return ObpCloseHandle(Handle
, AccessMode
);
3387 * The NtClose routine <FILLMEIN>
3392 * @return <FILLMEIN>.
3399 NtClose(IN HANDLE Handle
)
3401 /* Call the internal API */
3402 return ObpCloseHandle(Handle
, ExGetPreviousMode());
3407 NtDuplicateObject(IN HANDLE SourceProcessHandle
,
3408 IN HANDLE SourceHandle
,
3409 IN HANDLE TargetProcessHandle OPTIONAL
,
3410 OUT PHANDLE TargetHandle OPTIONAL
,
3411 IN ACCESS_MASK DesiredAccess
,
3412 IN ULONG HandleAttributes
,
3415 PEPROCESS SourceProcess
, TargetProcess
, Target
;
3417 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
3419 OBTRACE(OB_HANDLE_DEBUG
,
3420 "%s - Duplicating handle: %p for %p into %p.\n",
3423 SourceProcessHandle
,
3424 TargetProcessHandle
);
3426 /* Check if we have a target handle */
3427 if ((TargetHandle
) && (PreviousMode
!= KernelMode
))
3432 /* Probe the handle and assume failure */
3433 ProbeForWriteHandle(TargetHandle
);
3434 *TargetHandle
= NULL
;
3436 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3438 /* Return the exception code */
3439 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3444 /* Now reference the input handle */
3445 Status
= ObReferenceObjectByHandle(SourceProcessHandle
,
3449 (PVOID
*)&SourceProcess
,
3451 if (!NT_SUCCESS(Status
)) return Status
;
3453 /* Check if got a target handle */
3454 if (TargetProcessHandle
)
3456 /* Now reference the output handle */
3457 Status
= ObReferenceObjectByHandle(TargetProcessHandle
,
3461 (PVOID
*)&TargetProcess
,
3463 if (NT_SUCCESS(Status
))
3465 /* Use this target process */
3466 Target
= TargetProcess
;
3470 /* No target process */
3476 /* No target process */
3477 Status
= STATUS_SUCCESS
;
3481 /* Call the internal routine */
3482 Status
= ObDuplicateObject(SourceProcess
,
3491 /* Check if the caller wanted the return handle */
3494 /* Protect the write to user mode */
3497 /* Write the new handle */
3498 *TargetHandle
= hTarget
;
3500 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3502 /* Otherwise, get the exception code */
3503 Status
= _SEH2_GetExceptionCode();
3508 /* Dereference the processes */
3509 OBTRACE(OB_HANDLE_DEBUG
,
3510 "%s - Duplicated handle: %p into %p S %lx\n",
3513 TargetProcessHandle
,
3515 if (Target
) ObDereferenceObject(Target
);
3516 ObDereferenceObject(SourceProcess
);
3522 ObIsKernelHandle(IN HANDLE Handle
)
3524 /* Use the inlined version. We know we are in kernel mode. */
3525 return ObpIsKernelHandle(Handle
, KernelMode
);