3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * FILE: ntoskrnl/ob/handle.c
24 * PURPOSE: Managing handles
25 * PROGRAMMER: David Welch (welch@cwcom.net)
30 /* INCLUDES ****************************************************************/
34 #include <internal/debug.h>
36 #define EX_OBJ_TO_HDR(eob) ((POBJECT_HEADER)((ULONG_PTR)(eob) & \
37 ~(EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE | \
38 EX_HANDLE_ENTRY_AUDITONCLOSE)))
39 #define EX_HTE_TO_HDR(hte) ((POBJECT_HEADER)((ULONG_PTR)((hte)->u1.Object) & \
40 ~(EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE | \
41 EX_HANDLE_ENTRY_AUDITONCLOSE)))
43 #define GENERIC_ANY (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL)
45 /* GLOBALS *****************************************************************/
47 PHANDLE_TABLE ObpKernelHandleTable
= NULL
;
49 /* TEMPORARY HACK. DO NOT REMOVE -- Alex */
52 ExpDesktopCreate(PVOID ObjectBody
,
55 POBJECT_CREATE_INFORMATION ObjectCreateInformation
);
57 /* FUNCTIONS ***************************************************************/
60 ObpDecrementHandleCount(PVOID ObjectBody
)
62 POBJECT_HEADER ObjectHeader
= BODY_TO_HEADER(ObjectBody
);
63 DPRINT("Header: %x\n", ObjectHeader
);
64 LONG NewHandleCount
= InterlockedDecrement(&ObjectHeader
->HandleCount
);
65 DPRINT("NewHandleCount: %x\n", NewHandleCount
);
66 DPRINT("HEADER_TO_OBJECT_NAME: %x\n", HEADER_TO_OBJECT_NAME(ObjectHeader
));
68 if ((ObjectHeader
->Type
!= NULL
) &&
69 (ObjectHeader
->Type
->TypeInfo
.CloseProcedure
!= NULL
))
71 /* the handle count should be decremented but we pass the previous value
73 ObjectHeader
->Type
->TypeInfo
.CloseProcedure(ObjectBody
, NewHandleCount
+ 1);
76 if(NewHandleCount
== 0)
78 if(HEADER_TO_OBJECT_NAME(ObjectHeader
) &&
79 HEADER_TO_OBJECT_NAME(ObjectHeader
)->Directory
!= NULL
&&
80 !(ObjectHeader
->Flags
& OB_FLAG_PERMANENT
))
82 /* delete the object from the namespace when the last handle got closed.
83 Only do this if it's actually been inserted into the namespace and
84 if it's not a permanent object. */
85 ObpRemoveEntryDirectory(ObjectHeader
);
88 /* remove the keep-alive reference */
89 ObDereferenceObject(ObjectBody
);
95 ObpQueryHandleAttributes(HANDLE Handle
,
96 POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo
)
98 PHANDLE_TABLE HandleTable
;
99 PHANDLE_TABLE_ENTRY HandleTableEntry
;
104 DPRINT("ObpQueryHandleAttributes(Handle %x)\n", Handle
);
106 if(ObIsKernelHandle(Handle
, ExGetPreviousMode()))
108 HandleTable
= ObpKernelHandleTable
;
109 ExHandle
= HANDLE_TO_EX_HANDLE(ObKernelHandleToHandle(Handle
));
113 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
114 ExHandle
= HANDLE_TO_EX_HANDLE(Handle
);
117 KeEnterCriticalRegion();
119 HandleTableEntry
= ExMapHandleToPointer(HandleTable
,
121 if (HandleTableEntry
== NULL
)
123 KeLeaveCriticalRegion();
124 return STATUS_INVALID_HANDLE
;
127 HandleInfo
->Inherit
= (HandleTableEntry
->u1
.ObAttributes
& EX_HANDLE_ENTRY_INHERITABLE
) != 0;
128 HandleInfo
->ProtectFromClose
= (HandleTableEntry
->u1
.ObAttributes
& EX_HANDLE_ENTRY_PROTECTFROMCLOSE
) != 0;
130 ExUnlockHandleTableEntry(HandleTable
,
133 KeLeaveCriticalRegion();
135 return STATUS_SUCCESS
;
140 ObpSetHandleAttributes(HANDLE Handle
,
141 POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo
)
143 PHANDLE_TABLE HandleTable
;
144 PHANDLE_TABLE_ENTRY HandleTableEntry
;
149 DPRINT("ObpSetHandleAttributes(Handle %x)\n", Handle
);
151 if(ObIsKernelHandle(Handle
, ExGetPreviousMode()))
153 HandleTable
= ObpKernelHandleTable
;
154 ExHandle
= HANDLE_TO_EX_HANDLE(ObKernelHandleToHandle(Handle
));
158 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
159 ExHandle
= HANDLE_TO_EX_HANDLE(Handle
);
162 KeEnterCriticalRegion();
164 HandleTableEntry
= ExMapHandleToPointer(HandleTable
,
166 if (HandleTableEntry
== NULL
)
168 KeLeaveCriticalRegion();
169 return STATUS_INVALID_HANDLE
;
172 if (HandleInfo
->Inherit
)
173 HandleTableEntry
->u1
.ObAttributes
|= EX_HANDLE_ENTRY_INHERITABLE
;
175 HandleTableEntry
->u1
.ObAttributes
&= ~EX_HANDLE_ENTRY_INHERITABLE
;
177 if (HandleInfo
->ProtectFromClose
)
178 HandleTableEntry
->u1
.ObAttributes
|= EX_HANDLE_ENTRY_PROTECTFROMCLOSE
;
180 HandleTableEntry
->u1
.ObAttributes
&= ~EX_HANDLE_ENTRY_PROTECTFROMCLOSE
;
182 /* FIXME: Do we need to set anything in the object header??? */
184 ExUnlockHandleTableEntry(HandleTable
,
187 KeLeaveCriticalRegion();
189 return STATUS_SUCCESS
;
194 ObpDeleteHandle(PHANDLE_TABLE HandleTable
,
197 PHANDLE_TABLE_ENTRY HandleEntry
;
199 POBJECT_HEADER ObjectHeader
;
200 LONG ExHandle
= HANDLE_TO_EX_HANDLE(Handle
);
204 DPRINT("ObpDeleteHandle(Handle %x)\n",Handle
);
206 KeEnterCriticalRegion();
208 HandleEntry
= ExMapHandleToPointer(HandleTable
,
210 if(HandleEntry
!= NULL
)
212 if(HandleEntry
->u1
.ObAttributes
& EX_HANDLE_ENTRY_PROTECTFROMCLOSE
)
214 ExUnlockHandleTableEntry(HandleTable
,
217 KeLeaveCriticalRegion();
219 return STATUS_HANDLE_NOT_CLOSABLE
;
222 ObjectHeader
= EX_HTE_TO_HDR(HandleEntry
);
223 Body
= &ObjectHeader
->Body
;
225 ObpDecrementHandleCount(Body
);
227 /* destroy and unlock the handle entry */
228 ExDestroyHandleByEntry(HandleTable
,
232 KeLeaveCriticalRegion();
234 return STATUS_SUCCESS
;
236 KeLeaveCriticalRegion();
237 return STATUS_INVALID_HANDLE
;
242 ObDuplicateObject(PEPROCESS SourceProcess
,
243 PEPROCESS TargetProcess
,
245 PHANDLE TargetHandle
,
246 ACCESS_MASK DesiredAccess
,
247 BOOLEAN InheritHandle
,
250 PHANDLE_TABLE SourceHandleTable
;
251 PHANDLE_TABLE_ENTRY SourceHandleEntry
;
252 HANDLE_TABLE_ENTRY NewHandleEntry
;
254 POBJECT_HEADER ObjectHeader
;
257 ULONG NewHandleCount
;
261 if(ObIsKernelHandle(SourceHandle
, ExGetPreviousMode()))
263 SourceHandleTable
= ObpKernelHandleTable
;
264 SourceHandle
= ObKernelHandleToHandle(SourceHandle
);
268 SourceHandleTable
= SourceProcess
->ObjectTable
;
271 ExSourceHandle
= HANDLE_TO_EX_HANDLE(SourceHandle
);
273 KeEnterCriticalRegion();
275 SourceHandleEntry
= ExMapHandleToPointer(SourceHandleTable
,
277 if (SourceHandleEntry
== NULL
)
279 KeLeaveCriticalRegion();
280 return STATUS_INVALID_HANDLE
;
283 ObjectHeader
= EX_HTE_TO_HDR(SourceHandleEntry
);
284 ObjectBody
= &ObjectHeader
->Body
;
286 NewHandleEntry
.u1
.Object
= SourceHandleEntry
->u1
.Object
;
288 NewHandleEntry
.u1
.ObAttributes
|= EX_HANDLE_ENTRY_INHERITABLE
;
290 NewHandleEntry
.u1
.ObAttributes
&= ~EX_HANDLE_ENTRY_INHERITABLE
;
291 NewHandleEntry
.u2
.GrantedAccess
= ((Options
& DUPLICATE_SAME_ACCESS
) ?
292 SourceHandleEntry
->u2
.GrantedAccess
:
294 if (Options
& DUPLICATE_SAME_ACCESS
)
296 NewHandleEntry
.u2
.GrantedAccess
= SourceHandleEntry
->u2
.GrantedAccess
;
300 if (DesiredAccess
& GENERIC_ANY
)
302 RtlMapGenericMask(&DesiredAccess
,
303 &ObjectHeader
->Type
->TypeInfo
.GenericMapping
);
305 NewHandleEntry
.u2
.GrantedAccess
= DesiredAccess
;
308 /* reference the object so it doesn't get deleted after releasing the lock
309 and before creating a new handle for it */
310 ObReferenceObject(ObjectBody
);
312 /* increment the handle count of the object, it should always be >= 2 because
313 we're holding a handle lock to this object! if the new handle count was
314 1 here, we're in big trouble... it would've been safe to increment and
315 check the handle count without using interlocked functions because the
316 entry is locked, which means the handle count can't change. */
317 NewHandleCount
= InterlockedIncrement(&ObjectHeader
->HandleCount
);
318 ASSERT(NewHandleCount
>= 2);
320 ExUnlockHandleTableEntry(SourceHandleTable
,
323 KeLeaveCriticalRegion();
325 /* attempt to create the new handle */
326 ExTargetHandle
= ExCreateHandle(TargetProcess
->ObjectTable
,
328 if (ExTargetHandle
!= EX_INVALID_HANDLE
)
330 if (Options
& DUPLICATE_CLOSE_SOURCE
)
332 ObpDeleteHandle(SourceHandleTable
,
336 ObDereferenceObject(ObjectBody
);
338 *TargetHandle
= EX_HANDLE_TO_HANDLE(ExTargetHandle
);
340 return STATUS_SUCCESS
;
344 /* decrement the handle count we previously incremented, but don't call the
345 closing procedure because we're not closing a handle! */
346 if(InterlockedDecrement(&ObjectHeader
->HandleCount
) == 0)
348 ObDereferenceObject(ObjectBody
);
351 ObDereferenceObject(ObjectBody
);
352 return STATUS_UNSUCCESSFUL
;
360 NtDuplicateObject (IN HANDLE SourceProcessHandle
,
361 IN HANDLE SourceHandle
,
362 IN HANDLE TargetProcessHandle
,
363 OUT PHANDLE TargetHandle OPTIONAL
,
364 IN ACCESS_MASK DesiredAccess
,
365 IN BOOLEAN InheritHandle
,
368 * FUNCTION: Copies a handle from one process space to another
370 * SourceProcessHandle = The source process owning the handle. The
371 * source process should have opened
372 * the SourceHandle with PROCESS_DUP_HANDLE
374 * SourceHandle = The handle to the object.
375 * TargetProcessHandle = The destination process owning the handle
376 * TargetHandle (OUT) = Caller should supply storage for the
378 * DesiredAccess = The desired access to the handle.
379 * InheritHandle = Indicates wheter the new handle will be inheritable
381 * Options = Specifies special actions upon duplicating the handle.
382 * Can be one of the values DUPLICATE_CLOSE_SOURCE |
383 * DUPLICATE_SAME_ACCESS. DUPLICATE_CLOSE_SOURCE specifies
384 * that the source handle should be closed after duplicating.
385 * DUPLICATE_SAME_ACCESS specifies to ignore the
386 * DesiredAccess paramter and just grant the same access to
389 * REMARKS: This function maps to the win32 DuplicateHandle.
392 PEPROCESS SourceProcess
;
393 PEPROCESS TargetProcess
;
395 KPROCESSOR_MODE PreviousMode
;
396 NTSTATUS Status
= STATUS_SUCCESS
;
400 PreviousMode
= ExGetPreviousMode();
402 if(TargetHandle
!= NULL
&& PreviousMode
!= KernelMode
)
406 ProbeForWrite(TargetHandle
,
412 Status
= _SEH_GetExceptionCode();
416 if(!NT_SUCCESS(Status
))
422 Status
= ObReferenceObjectByHandle(SourceProcessHandle
,
426 (PVOID
*)&SourceProcess
,
428 if (!NT_SUCCESS(Status
))
433 Status
= ObReferenceObjectByHandle(TargetProcessHandle
,
437 (PVOID
*)&TargetProcess
,
439 if (!NT_SUCCESS(Status
))
441 ObDereferenceObject(SourceProcess
);
445 /* Check for magic handle first */
446 if (SourceHandle
== NtCurrentThread() ||
447 SourceHandle
== NtCurrentProcess())
450 POBJECT_TYPE ObjectType
;
452 ObjectType
= (SourceHandle
== NtCurrentThread()) ? PsThreadType
: PsProcessType
;
454 Status
= ObReferenceObjectByHandle(SourceHandle
,
460 if(NT_SUCCESS(Status
))
462 if (Options
& DUPLICATE_SAME_ACCESS
)
464 /* grant all access rights */
465 DesiredAccess
= ((ObjectType
== PsThreadType
) ? THREAD_ALL_ACCESS
: PROCESS_ALL_ACCESS
);
469 if (DesiredAccess
& GENERIC_ANY
)
471 RtlMapGenericMask(&DesiredAccess
,
472 &ObjectType
->TypeInfo
.GenericMapping
);
475 Status
= ObpCreateHandle(TargetProcess
,
481 ObDereferenceObject(ObjectBody
);
483 if (Options
& DUPLICATE_CLOSE_SOURCE
)
485 ObpDeleteHandle(SourceProcess
->ObjectTable
,
492 Status
= ObDuplicateObject(SourceProcess
,
501 ObDereferenceObject(TargetProcess
);
502 ObDereferenceObject(SourceProcess
);
504 if(NT_SUCCESS(Status
) && TargetHandle
!= NULL
)
508 *TargetHandle
= hTarget
;
512 Status
= _SEH_GetExceptionCode();
521 DeleteHandleCallback(PHANDLE_TABLE HandleTable
,
526 POBJECT_HEADER ObjectHeader
;
531 ObjectHeader
= EX_OBJ_TO_HDR(Object
);
532 ObjectBody
= &ObjectHeader
->Body
;
534 ObpDecrementHandleCount(ObjectBody
);
537 static BOOLEAN STDCALL
538 DuplicateHandleCallback(PHANDLE_TABLE HandleTable
,
539 PHANDLE_TABLE_ENTRY HandleTableEntry
,
542 POBJECT_HEADER ObjectHeader
;
547 Ret
= (HandleTableEntry
->u1
.ObAttributes
& EX_HANDLE_ENTRY_INHERITABLE
) != 0;
550 ObjectHeader
= EX_HTE_TO_HDR(HandleTableEntry
);
551 if(InterlockedIncrement(&ObjectHeader
->HandleCount
) == 1)
553 ObReferenceObject(&ObjectHeader
->Body
);
560 VOID
ObCreateHandleTable(PEPROCESS Parent
,
564 * FUNCTION: Creates a handle table for a process
566 * Parent = Parent process (or NULL if this is the first process)
567 * Inherit = True if the process should inherit its parent's handles
568 * Process = Process whose handle table is to be created
573 DPRINT("ObCreateHandleTable(Parent %x, Inherit %d, Process %x)\n",
574 Parent
,Inherit
,Process
);
577 Process
->ObjectTable
= ExDupHandleTable(Process
,
578 DuplicateHandleCallback
,
580 Parent
->ObjectTable
);
584 Process
->ObjectTable
= ExCreateHandleTable(Process
);
591 ObKillProcess(PEPROCESS Process
)
595 ExDestroyHandleTable(Process
->ObjectTable
,
596 DeleteHandleCallback
,
602 ObpCreateHandle(PEPROCESS Process
,
604 ACCESS_MASK GrantedAccess
,
606 PHANDLE HandleReturn
)
608 * FUNCTION: Add a handle referencing an object
610 * obj = Object body that the handle should refer to
611 * RETURNS: The created handle
612 * NOTE: The handle is valid only in the context of the current process
615 HANDLE_TABLE_ENTRY NewEntry
;
616 POBJECT_HEADER ObjectHeader
;
621 DPRINT("ObpCreateHandle(Process %x, obj %x)\n",Process
,ObjectBody
);
626 ObjectHeader
= BODY_TO_HEADER(ObjectBody
);
628 ASSERT((ULONG_PTR
)ObjectHeader
& EX_HANDLE_ENTRY_LOCKED
);
630 if (GrantedAccess
& MAXIMUM_ALLOWED
)
632 GrantedAccess
&= ~MAXIMUM_ALLOWED
;
633 GrantedAccess
|= GENERIC_ALL
;
636 if (GrantedAccess
& GENERIC_ANY
)
638 RtlMapGenericMask(&GrantedAccess
,
639 &ObjectHeader
->Type
->TypeInfo
.GenericMapping
);
642 NewEntry
.u1
.Object
= ObjectHeader
;
644 NewEntry
.u1
.ObAttributes
|= EX_HANDLE_ENTRY_INHERITABLE
;
646 NewEntry
.u1
.ObAttributes
&= ~EX_HANDLE_ENTRY_INHERITABLE
;
647 NewEntry
.u2
.GrantedAccess
= GrantedAccess
;
649 ExHandle
= ExCreateHandle(Process
->ObjectTable
,
651 DPRINT("ObCreateHandle(0x%x)==0x%x [HT:0x%x]\n", ObjectHeader
, *HandleReturn
, Process
->ObjectTable
);
652 if(ExHandle
!= EX_INVALID_HANDLE
)
654 if(InterlockedIncrement(&ObjectHeader
->HandleCount
) == 1)
656 ObReferenceObjectByPointer(ObjectBody
,
662 *HandleReturn
= EX_HANDLE_TO_HANDLE(ExHandle
);
664 return STATUS_SUCCESS
;
667 return STATUS_UNSUCCESSFUL
;
675 ObQueryObjectAuditingByHandle(IN HANDLE Handle
,
676 OUT PBOOLEAN GenerateOnClose
)
678 PHANDLE_TABLE_ENTRY HandleEntry
;
680 LONG ExHandle
= HANDLE_TO_EX_HANDLE(Handle
);
684 DPRINT("ObQueryObjectAuditingByHandle(Handle %x)\n", Handle
);
686 Process
= PsGetCurrentProcess();
688 KeEnterCriticalRegion();
690 HandleEntry
= ExMapHandleToPointer(Process
->ObjectTable
,
692 if(HandleEntry
!= NULL
)
694 *GenerateOnClose
= (HandleEntry
->u1
.ObAttributes
& EX_HANDLE_ENTRY_AUDITONCLOSE
) != 0;
696 ExUnlockHandleTableEntry(Process
->ObjectTable
,
699 KeLeaveCriticalRegion();
701 return STATUS_SUCCESS
;
704 KeLeaveCriticalRegion();
706 return STATUS_INVALID_HANDLE
;
711 * FUNCTION: Increments the reference count for an object and returns a
712 * pointer to its body
714 * Handle = Handle for the object
715 * DesiredAccess = Desired access to the object
718 * Object (OUT) = Points to the object body on return
719 * HandleInformation (OUT) = Contains information about the handle
726 ObReferenceObjectByHandle(HANDLE Handle
,
727 ACCESS_MASK DesiredAccess
,
728 POBJECT_TYPE ObjectType
,
729 KPROCESSOR_MODE AccessMode
,
731 POBJECT_HANDLE_INFORMATION HandleInformation
)
733 PHANDLE_TABLE_ENTRY HandleEntry
;
734 POBJECT_HEADER ObjectHeader
;
735 PHANDLE_TABLE HandleTable
;
737 ACCESS_MASK GrantedAccess
;
743 DPRINT("ObReferenceObjectByHandle(Handle %x, DesiredAccess %x, "
744 "ObjectType %x, AccessMode %d, Object %x)\n",Handle
,DesiredAccess
,
745 ObjectType
,AccessMode
,Object
);
749 return STATUS_INVALID_HANDLE
;
752 * Handle special handle names
754 if (Handle
== NtCurrentProcess() &&
755 (ObjectType
== PsProcessType
|| ObjectType
== NULL
))
757 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
759 ObReferenceObject(CurrentProcess
);
761 if (HandleInformation
!= NULL
)
763 HandleInformation
->HandleAttributes
= 0;
764 HandleInformation
->GrantedAccess
= PROCESS_ALL_ACCESS
;
767 *Object
= CurrentProcess
;
768 DPRINT("Referencing current process %x\n", CurrentProcess
);
769 return STATUS_SUCCESS
;
771 else if (Handle
== NtCurrentProcess())
774 return(STATUS_OBJECT_TYPE_MISMATCH
);
777 if (Handle
== NtCurrentThread() &&
778 (ObjectType
== PsThreadType
|| ObjectType
== NULL
))
780 PETHREAD CurrentThread
= PsGetCurrentThread();
782 ObReferenceObject(CurrentThread
);
784 if (HandleInformation
!= NULL
)
786 HandleInformation
->HandleAttributes
= 0;
787 HandleInformation
->GrantedAccess
= THREAD_ALL_ACCESS
;
790 *Object
= CurrentThread
;
792 return STATUS_SUCCESS
;
794 else if (Handle
== NtCurrentThread())
797 return(STATUS_OBJECT_TYPE_MISMATCH
);
800 /* desire as much access rights as possible */
801 if (DesiredAccess
& MAXIMUM_ALLOWED
)
803 DesiredAccess
&= ~MAXIMUM_ALLOWED
;
804 DesiredAccess
|= GENERIC_ALL
;
807 if(ObIsKernelHandle(Handle
, AccessMode
))
809 HandleTable
= ObpKernelHandleTable
;
810 ExHandle
= HANDLE_TO_EX_HANDLE(ObKernelHandleToHandle(Handle
));
814 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
815 ExHandle
= HANDLE_TO_EX_HANDLE(Handle
);
818 KeEnterCriticalRegion();
820 HandleEntry
= ExMapHandleToPointer(HandleTable
,
822 if (HandleEntry
== NULL
)
824 KeLeaveCriticalRegion();
825 DPRINT("ExMapHandleToPointer() failed for handle 0x%x\n", Handle
);
826 return(STATUS_INVALID_HANDLE
);
829 ObjectHeader
= EX_HTE_TO_HDR(HandleEntry
);
830 ObjectBody
= &ObjectHeader
->Body
;
832 DPRINT("locked1: ObjectHeader: 0x%x [HT:0x%x]\n", ObjectHeader
, HandleTable
);
834 if (ObjectType
!= NULL
&& ObjectType
!= ObjectHeader
->Type
)
836 DPRINT("ObjectType mismatch: %wZ vs %wZ (handle 0x%x)\n", &ObjectType
->TypeName
, ObjectHeader
->Type
? &ObjectHeader
->Type
->TypeName
: NULL
, Handle
);
838 ExUnlockHandleTableEntry(HandleTable
,
841 KeLeaveCriticalRegion();
843 return(STATUS_OBJECT_TYPE_MISMATCH
);
846 /* map the generic access masks if the caller asks for generic access */
847 if (DesiredAccess
& GENERIC_ANY
)
849 RtlMapGenericMask(&DesiredAccess
,
850 &BODY_TO_HEADER(ObjectBody
)->Type
->TypeInfo
.GenericMapping
);
853 GrantedAccess
= HandleEntry
->u2
.GrantedAccess
;
855 /* Unless running as KernelMode, deny access if caller desires more access
856 rights than the handle can grant */
857 if(AccessMode
!= KernelMode
&& (~GrantedAccess
& DesiredAccess
))
859 ExUnlockHandleTableEntry(HandleTable
,
862 KeLeaveCriticalRegion();
864 DPRINT1("GrantedAccess: 0x%x, ~GrantedAccess: 0x%x, DesiredAccess: 0x%x, denied: 0x%x\n", GrantedAccess
, ~GrantedAccess
, DesiredAccess
, ~GrantedAccess
& DesiredAccess
);
866 return(STATUS_ACCESS_DENIED
);
869 ObReferenceObject(ObjectBody
);
871 Attributes
= HandleEntry
->u1
.ObAttributes
& (EX_HANDLE_ENTRY_PROTECTFROMCLOSE
|
872 EX_HANDLE_ENTRY_INHERITABLE
|
873 EX_HANDLE_ENTRY_AUDITONCLOSE
);
875 ExUnlockHandleTableEntry(HandleTable
,
878 KeLeaveCriticalRegion();
880 if (HandleInformation
!= NULL
)
882 HandleInformation
->HandleAttributes
= Attributes
;
883 HandleInformation
->GrantedAccess
= GrantedAccess
;
886 *Object
= ObjectBody
;
888 return(STATUS_SUCCESS
);
892 /**********************************************************************
897 * Closes a handle reference to an object.
909 NtClose(IN HANDLE Handle
)
911 PHANDLE_TABLE HandleTable
;
916 if(ObIsKernelHandle(Handle
, ExGetPreviousMode()))
918 HandleTable
= ObpKernelHandleTable
;
919 Handle
= ObKernelHandleToHandle(Handle
);
923 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
926 Status
= ObpDeleteHandle(HandleTable
,
928 if (!NT_SUCCESS(Status
))
930 if((ExGetPreviousMode() != KernelMode
) &&
931 (PsGetCurrentProcess()->ExceptionPort
))
933 KeRaiseUserException(Status
);
938 return(STATUS_SUCCESS
);
947 ObInsertObject(IN PVOID Object
,
948 IN PACCESS_STATE PassedAccessState OPTIONAL
,
949 IN ACCESS_MASK DesiredAccess
,
950 IN ULONG AdditionalReferences
,
951 OUT PVOID
* ReferencedObject OPTIONAL
,
954 POBJECT_CREATE_INFORMATION ObjectCreateInfo
;
955 POBJECT_HEADER Header
;
956 POBJECT_HEADER_NAME_INFO ObjectNameInfo
;
957 PVOID FoundObject
= NULL
;
958 POBJECT_HEADER FoundHeader
= NULL
;
959 NTSTATUS Status
= STATUS_SUCCESS
;
960 UNICODE_STRING RemainingPath
;
961 BOOLEAN ObjectAttached
= FALSE
;
962 PSECURITY_DESCRIPTOR NewSecurityDescriptor
= NULL
;
963 SECURITY_SUBJECT_CONTEXT SubjectContext
;
967 /* Get the Header and Create Info */
968 DPRINT("ObInsertObject: %x\n", Object
);
969 Header
= BODY_TO_HEADER(Object
);
970 ObjectCreateInfo
= Header
->ObjectCreateInfo
;
971 ObjectNameInfo
= HEADER_TO_OBJECT_NAME(Header
);
973 /* First try to find the Object */
974 if (ObjectNameInfo
&& ObjectNameInfo
->Name
.Buffer
)
976 DPRINT("Object has a name. Trying to find it: %wZ.\n", &ObjectNameInfo
->Name
);
977 Status
= ObFindObject(ObjectCreateInfo
,
978 &ObjectNameInfo
->Name
,
982 DPRINT("FoundObject: %x, Path: %wZ\n", FoundObject
, &RemainingPath
);
983 if (!NT_SUCCESS(Status
))
985 DPRINT1("ObFindObject() failed! (Status 0x%x)\n", Status
);
991 DPRINT("Getting header: %x\n", FoundObject
);
992 FoundHeader
= BODY_TO_HEADER(FoundObject
);
995 if (FoundHeader
&& RemainingPath
.Buffer
== NULL
)
997 DPRINT("Object exists\n");
998 ObDereferenceObject(FoundObject
);
999 return STATUS_OBJECT_NAME_COLLISION
;
1004 DPRINT("No name, empty remaining path\n");
1005 RtlInitUnicodeString(&RemainingPath
, NULL
);
1008 if (FoundHeader
&& FoundHeader
->Type
== ObDirectoryType
&&
1009 RemainingPath
.Buffer
)
1011 ObpAddEntryDirectory(FoundObject
, Header
, NULL
);
1012 ObjectAttached
= TRUE
;
1014 /* The name was changed so let's update it */
1015 /* FIXME: TEMPORARY HACK This will go in ObFindObject in the next commit */
1017 PWSTR BufferPos
= RemainingPath
.Buffer
;
1019 NewName
= ExAllocatePool(NonPagedPool
, RemainingPath
.MaximumLength
);
1020 ObjectNameInfo
= HEADER_TO_OBJECT_NAME(Header
);
1022 if (BufferPos
[0] == L
'\\')
1027 RtlMoveMemory(NewName
, BufferPos
, RemainingPath
.MaximumLength
);
1028 if (ObjectNameInfo
->Name
.Buffer
) ExFreePool(ObjectNameInfo
->Name
.Buffer
);
1029 ObjectNameInfo
->Name
.Buffer
= NewName
;
1030 ObjectNameInfo
->Name
.Length
= RemainingPath
.Length
;
1031 ObjectNameInfo
->Name
.MaximumLength
= RemainingPath
.MaximumLength
;
1032 DPRINT("Name: %S\n", ObjectNameInfo
->Name
.Buffer
);
1035 if ((Header
->Type
== IoFileObjectType
) ||
1036 (Header
->Type
== ExDesktopObjectType
) ||
1037 (Header
->Type
->TypeInfo
.OpenProcedure
!= NULL
))
1039 DPRINT("About to call Open Routine\n");
1040 if (Header
->Type
== IoFileObjectType
)
1042 /* TEMPORARY HACK. DO NOT TOUCH -- Alex */
1043 DPRINT("Calling IopCreateFile: %x\n", FoundObject
);
1044 Status
= IopCreateFile(&Header
->Body
,
1046 RemainingPath
.Buffer
,
1048 DPRINT("Called IopCreateFile: %x\n", Status
);
1051 else if (Header
->Type
== ExDesktopObjectType
)
1053 /* TEMPORARY HACK. DO NOT TOUCH -- Alex */
1054 DPRINT("Calling ExpDesktopCreate\n");
1055 Status
= ExpDesktopCreate(&Header
->Body
,
1057 RemainingPath
.Buffer
,
1060 else if (Header
->Type
->TypeInfo
.OpenProcedure
!= NULL
)
1062 DPRINT("Calling %x\n", Header
->Type
->TypeInfo
.OpenProcedure
);
1063 Status
= Header
->Type
->TypeInfo
.OpenProcedure(ObCreateHandle
,
1070 if (!NT_SUCCESS(Status
))
1072 DPRINT("Create Failed\n");
1073 if (ObjectAttached
== TRUE
)
1075 ObpRemoveEntryDirectory(Header
);
1079 ObDereferenceObject(FoundObject
);
1081 RtlFreeUnicodeString(&RemainingPath
);
1086 RtlFreeUnicodeString(&RemainingPath
);
1088 DPRINT("Security Assignment in progress\n");
1089 SeCaptureSubjectContext(&SubjectContext
);
1091 /* Build the new security descriptor */
1092 Status
= SeAssignSecurity((FoundHeader
!= NULL
) ? FoundHeader
->SecurityDescriptor
: NULL
,
1093 (ObjectCreateInfo
!= NULL
) ? ObjectCreateInfo
->SecurityDescriptor
: NULL
,
1094 &NewSecurityDescriptor
,
1095 (Header
->Type
== ObDirectoryType
),
1097 &Header
->Type
->TypeInfo
.GenericMapping
,
1100 if (NT_SUCCESS(Status
))
1102 DPRINT("NewSecurityDescriptor %p\n", NewSecurityDescriptor
);
1104 if (Header
->Type
->TypeInfo
.SecurityProcedure
!= NULL
)
1106 /* Call the security method */
1107 Status
= Header
->Type
->TypeInfo
.SecurityProcedure(&Header
->Body
,
1108 AssignSecurityDescriptor
,
1110 NewSecurityDescriptor
,
1115 /* Assign the security descriptor to the object header */
1116 Status
= ObpAddSecurityDescriptor(NewSecurityDescriptor
,
1117 &Header
->SecurityDescriptor
);
1118 DPRINT("Object security descriptor %p\n", Header
->SecurityDescriptor
);
1121 /* Release the new security descriptor */
1122 SeDeassignSecurity(&NewSecurityDescriptor
);
1125 DPRINT("Security Complete\n");
1126 SeReleaseSubjectContext(&SubjectContext
);
1128 /* Create the Handle */
1129 /* HACKHACK: Because of ROS's incorrect startup, this can be called
1130 * without a valid Process until I finalize the startup patch,
1131 * so don't create a handle if this is the case. We also don't create
1132 * a handle if Handle is NULL when the Registry Code calls it, because
1133 * the registry code totally bastardizes the Ob and needs to be fixed
1135 DPRINT("Creating handle\n");
1138 Status
= ObpCreateHandle(PsGetCurrentProcess(),
1141 ObjectCreateInfo
->Attributes
& OBJ_INHERIT
,
1143 DPRINT("handle Created: %d. refcount. handlecount %d %d\n",
1144 *Handle
, Header
->RefCount
, Header
->HandleCount
);
1147 /* We can delete the Create Info now */
1148 Header
->ObjectCreateInfo
= NULL
;
1149 ObpReleaseCapturedAttributes(ObjectCreateInfo
);
1150 ExFreePool(ObjectCreateInfo
);
1152 DPRINT("Status %x\n", Status
);
1158 ObpGetHandleCountByHandleTable(PHANDLE_TABLE HandleTable
)
1160 return HandleTable
->HandleCount
;
1164 * FUNCTION: Searches the handle table of a specified process whether it contains a
1165 * valid handle to the Object we're looking for. If not, it'll create one.
1168 * The parameters of this function is basically a mixture of some of the parameters
1169 * of ObReferenceObjectByHandle() and ObReferenceObjectByPointer(). A little thinking
1170 * about what this function does (by it's name) makes clear what parameters it requires.
1171 * For example the AccessMode parameter of ObReferenceObjectByHandle/Pointer() is not
1172 * required at all as it only has influence on the object security. This function doesn't
1173 * want to get access to an object, it just looks for a valid handle and if it can't find
1174 * one, it'll just create one. It wouldn't make sense to check for security again as the
1175 * caller already has a pointer to the object.
1177 * A test on an XP machine shows that this prototype appears to be correct.
1180 * Process = This parameter simply describes in which handle table we're looking
1181 * for a handle to the object.
1182 * Object = The object pointer that we're looking for
1183 * ObjectType = Just a sanity check as ObReferenceObjectByHandle() and
1184 * ObReferenceObjectByPointer() provides.
1185 * HandleInformation = This one has to be the opposite meaning of the usage in
1186 * ObReferenceObjectByHandle(). If we actually found a valid
1187 * handle in the table, we need to check against the information
1188 * provided so we make sure this handle has all access rights
1189 * (and attributes?!) we need. If they don't match, we can't
1190 * use this handle and keep looking because the caller is likely
1191 * to depend on these access rights.
1192 * HandleReturn = The last parameter is the same as in ObCreateHandle(). If we could
1193 * find a suitable handle in the handle table, return this handle, if
1194 * not, we'll just create one using ObCreateHandle() with all access
1195 * rights the caller needs.
1202 ObFindHandleForObject(IN PEPROCESS Process
,
1204 IN POBJECT_TYPE ObjectType
,
1205 IN POBJECT_HANDLE_INFORMATION HandleInformation
,
1206 OUT PHANDLE HandleReturn
)
1209 return STATUS_UNSUCCESSFUL
;
1213 ObpGetNextHandleByProcessCount(PSYSTEM_HANDLE_TABLE_ENTRY_INFO pshi
,
1220 // pshi->HandleValue;
1223 This will never work with ROS! M$, I guess uses 0 -> 65535.
1224 Ros uses 0 -> 4294967295!
1227 P
= (ULONG
) Process
->UniqueProcessId
;
1228 pshi
->UniqueProcessId
= (USHORT
) P
;
1230 // KeAcquireSpinLock( &Process->HandleTable.ListLock, &oldIrql );
1232 // pshi->GrantedAccess;
1235 // pshi->HandleAttributes;
1237 // KeReleaseSpinLock( &Process->HandleTable.ListLock, oldIrql );