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 GENERIC_ANY (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL)
38 /* GLOBALS *****************************************************************/
40 PHANDLE_TABLE ObpKernelHandleTable
= NULL
;
42 /* TEMPORARY HACK. DO NOT REMOVE -- Alex */
45 ExpDesktopCreate(PVOID ObjectBody
,
48 POBJECT_CREATE_INFORMATION ObjectCreateInformation
);
50 /* FUNCTIONS ***************************************************************/
53 ObpDecrementHandleCount(PVOID ObjectBody
)
55 PROS_OBJECT_HEADER ObjectHeader
= BODY_TO_HEADER(ObjectBody
);
56 LONG NewHandleCount
= InterlockedDecrement(&ObjectHeader
->HandleCount
);
57 DPRINT("Header: %x\n", ObjectHeader
);
58 DPRINT("NewHandleCount: %x\n", NewHandleCount
);
59 DPRINT("HEADER_TO_OBJECT_NAME: %x\n", HEADER_TO_OBJECT_NAME(ObjectHeader
));
61 if ((ObjectHeader
->Type
!= NULL
) &&
62 (ObjectHeader
->Type
->TypeInfo
.CloseProcedure
!= NULL
))
64 /* the handle count should be decremented but we pass the previous value
66 ObjectHeader
->Type
->TypeInfo
.CloseProcedure(NULL
, ObjectBody
, 0, NewHandleCount
+ 1, NewHandleCount
+ 1);
69 if(NewHandleCount
== 0)
71 if(HEADER_TO_OBJECT_NAME(ObjectHeader
) &&
72 HEADER_TO_OBJECT_NAME(ObjectHeader
)->Directory
!= NULL
&&
73 !(ObjectHeader
->Flags
& OB_FLAG_PERMANENT
))
75 /* delete the object from the namespace when the last handle got closed.
76 Only do this if it's actually been inserted into the namespace and
77 if it's not a permanent object. */
78 ObpRemoveEntryDirectory((PROS_OBJECT_HEADER
)ObjectHeader
);
81 /* remove the keep-alive reference */
82 ObDereferenceObject(ObjectBody
);
89 ObpQueryHandleAttributes(HANDLE Handle
,
90 POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo
)
92 PHANDLE_TABLE_ENTRY HandleTableEntry
;
93 PEPROCESS Process
, CurrentProcess
;
95 BOOLEAN AttachedToProcess
= FALSE
;
96 NTSTATUS Status
= STATUS_SUCCESS
;
100 DPRINT("ObpQueryHandleAttributes(Handle %p)\n", Handle
);
101 CurrentProcess
= PsGetCurrentProcess();
103 KeEnterCriticalRegion();
105 if(ObIsKernelHandle(Handle
, ExGetPreviousMode()))
107 Process
= PsInitialSystemProcess
;
108 Handle
= ObKernelHandleToHandle(Handle
);
110 if (Process
!= CurrentProcess
)
112 KeStackAttachProcess(&Process
->Pcb
,
114 AttachedToProcess
= TRUE
;
119 Process
= CurrentProcess
;
122 HandleTableEntry
= ExMapHandleToPointer(Process
->ObjectTable
,
124 if (HandleTableEntry
!= NULL
)
126 HandleInfo
->Inherit
= (HandleTableEntry
->u1
.ObAttributes
& EX_HANDLE_ENTRY_INHERITABLE
) != 0;
127 HandleInfo
->ProtectFromClose
= (HandleTableEntry
->u1
.ObAttributes
& EX_HANDLE_ENTRY_PROTECTFROMCLOSE
) != 0;
129 ExUnlockHandleTableEntry(Process
->ObjectTable
,
133 Status
= STATUS_INVALID_HANDLE
;
135 if (AttachedToProcess
)
137 KeUnstackDetachProcess(&ApcState
);
140 KeLeaveCriticalRegion();
148 ObpSetHandleAttributes(HANDLE Handle
,
149 POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo
)
151 PHANDLE_TABLE_ENTRY HandleTableEntry
;
152 PEPROCESS Process
, CurrentProcess
;
154 BOOLEAN AttachedToProcess
= FALSE
;
155 NTSTATUS Status
= STATUS_SUCCESS
;
159 DPRINT("ObpSetHandleAttributes(Handle %p)\n", Handle
);
160 CurrentProcess
= PsGetCurrentProcess();
162 KeEnterCriticalRegion();
164 if(ObIsKernelHandle(Handle
, ExGetPreviousMode()))
166 Process
= PsInitialSystemProcess
;
167 Handle
= ObKernelHandleToHandle(Handle
);
169 if (Process
!= CurrentProcess
)
171 KeStackAttachProcess(&Process
->Pcb
,
173 AttachedToProcess
= TRUE
;
178 Process
= CurrentProcess
;
181 HandleTableEntry
= ExMapHandleToPointer(Process
->ObjectTable
,
183 if (HandleTableEntry
!= NULL
)
185 if (HandleInfo
->Inherit
)
186 HandleTableEntry
->u1
.ObAttributes
|= EX_HANDLE_ENTRY_INHERITABLE
;
188 HandleTableEntry
->u1
.ObAttributes
&= ~EX_HANDLE_ENTRY_INHERITABLE
;
190 if (HandleInfo
->ProtectFromClose
)
191 HandleTableEntry
->u1
.ObAttributes
|= EX_HANDLE_ENTRY_PROTECTFROMCLOSE
;
193 HandleTableEntry
->u1
.ObAttributes
&= ~EX_HANDLE_ENTRY_PROTECTFROMCLOSE
;
195 /* FIXME: Do we need to set anything in the object header??? */
197 ExUnlockHandleTableEntry(Process
->ObjectTable
,
201 Status
= STATUS_INVALID_HANDLE
;
203 if (AttachedToProcess
)
205 KeUnstackDetachProcess(&ApcState
);
208 KeLeaveCriticalRegion();
215 ObpDeleteHandle(HANDLE Handle
)
217 PHANDLE_TABLE_ENTRY HandleEntry
;
219 PROS_OBJECT_HEADER ObjectHeader
;
220 PHANDLE_TABLE ObjectTable
;
224 DPRINT("ObpDeleteHandle(Handle %p)\n",Handle
);
226 ObjectTable
= PsGetCurrentProcess()->ObjectTable
;
228 KeEnterCriticalRegion();
230 HandleEntry
= ExMapHandleToPointer(ObjectTable
,
232 if(HandleEntry
!= NULL
)
234 if(HandleEntry
->u1
.ObAttributes
& EX_HANDLE_ENTRY_PROTECTFROMCLOSE
)
236 ExUnlockHandleTableEntry(ObjectTable
,
239 KeLeaveCriticalRegion();
241 return STATUS_HANDLE_NOT_CLOSABLE
;
244 ObjectHeader
= EX_HTE_TO_HDR(HandleEntry
);
245 Body
= &ObjectHeader
->Body
;
247 /* destroy and unlock the handle entry */
248 ExDestroyHandleByEntry(ObjectTable
,
252 ObpDecrementHandleCount(Body
);
254 KeLeaveCriticalRegion();
256 return STATUS_SUCCESS
;
258 KeLeaveCriticalRegion();
259 return STATUS_INVALID_HANDLE
;
265 ObDuplicateObject(PEPROCESS SourceProcess
,
266 PEPROCESS TargetProcess
,
268 PHANDLE TargetHandle
,
269 ACCESS_MASK DesiredAccess
,
270 ULONG HandleAttributes
,
273 PHANDLE_TABLE_ENTRY SourceHandleEntry
;
274 HANDLE_TABLE_ENTRY NewHandleEntry
;
275 BOOLEAN AttachedToProcess
= FALSE
;
277 PROS_OBJECT_HEADER ObjectHeader
;
278 ULONG NewHandleCount
;
279 HANDLE NewTargetHandle
;
280 PEPROCESS CurrentProcess
;
282 NTSTATUS Status
= STATUS_SUCCESS
;
286 if(SourceProcess
== NULL
||
287 ObIsKernelHandle(SourceHandle
, ExGetPreviousMode()))
289 SourceProcess
= PsInitialSystemProcess
;
290 SourceHandle
= ObKernelHandleToHandle(SourceHandle
);
293 CurrentProcess
= PsGetCurrentProcess();
295 KeEnterCriticalRegion();
297 if (SourceProcess
!= CurrentProcess
)
299 KeStackAttachProcess(&SourceProcess
->Pcb
,
301 AttachedToProcess
= TRUE
;
303 SourceHandleEntry
= ExMapHandleToPointer(SourceProcess
->ObjectTable
,
305 if (SourceHandleEntry
== NULL
)
307 if (AttachedToProcess
)
309 KeUnstackDetachProcess(&ApcState
);
312 KeLeaveCriticalRegion();
313 return STATUS_INVALID_HANDLE
;
316 ObjectHeader
= EX_HTE_TO_HDR(SourceHandleEntry
);
317 ObjectBody
= &ObjectHeader
->Body
;
319 NewHandleEntry
.u1
.Object
= SourceHandleEntry
->u1
.Object
;
320 if(HandleAttributes
& OBJ_INHERIT
)
321 NewHandleEntry
.u1
.ObAttributes
|= EX_HANDLE_ENTRY_INHERITABLE
;
323 NewHandleEntry
.u1
.ObAttributes
&= ~EX_HANDLE_ENTRY_INHERITABLE
;
324 NewHandleEntry
.u2
.GrantedAccess
= ((Options
& DUPLICATE_SAME_ACCESS
) ?
325 SourceHandleEntry
->u2
.GrantedAccess
:
327 if (Options
& DUPLICATE_SAME_ACCESS
)
329 NewHandleEntry
.u2
.GrantedAccess
= SourceHandleEntry
->u2
.GrantedAccess
;
333 if (DesiredAccess
& GENERIC_ANY
)
335 RtlMapGenericMask(&DesiredAccess
,
336 &ObjectHeader
->Type
->TypeInfo
.GenericMapping
);
338 NewHandleEntry
.u2
.GrantedAccess
= DesiredAccess
;
341 /* reference the object so it doesn't get deleted after releasing the lock
342 and before creating a new handle for it */
343 ObReferenceObject(ObjectBody
);
345 /* increment the handle count of the object, it should always be >= 2 because
346 we're holding a handle lock to this object! if the new handle count was
347 1 here, we're in big trouble... it would've been safe to increment and
348 check the handle count without using interlocked functions because the
349 entry is locked, which means the handle count can't change. */
350 NewHandleCount
= InterlockedIncrement(&ObjectHeader
->HandleCount
);
351 ASSERT(NewHandleCount
>= 2);
353 ExUnlockHandleTableEntry(SourceProcess
->ObjectTable
,
356 if (AttachedToProcess
)
358 KeUnstackDetachProcess(&ApcState
);
359 AttachedToProcess
= FALSE
;
362 if (TargetProcess
!= CurrentProcess
)
364 KeStackAttachProcess(&TargetProcess
->Pcb
,
366 AttachedToProcess
= TRUE
;
369 /* attempt to create the new handle */
370 NewTargetHandle
= ExCreateHandle(TargetProcess
->ObjectTable
,
372 if (AttachedToProcess
)
374 KeUnstackDetachProcess(&ApcState
);
375 AttachedToProcess
= FALSE
;
378 if (NewTargetHandle
!= NULL
)
380 if (Options
& DUPLICATE_CLOSE_SOURCE
)
382 if (SourceProcess
!= CurrentProcess
)
384 KeStackAttachProcess(&SourceProcess
->Pcb
,
386 AttachedToProcess
= TRUE
;
389 /* delete the source handle */
390 ObpDeleteHandle(SourceHandle
);
392 if (AttachedToProcess
)
394 KeUnstackDetachProcess(&ApcState
);
398 ObDereferenceObject(ObjectBody
);
400 *TargetHandle
= NewTargetHandle
;
404 /* decrement the handle count we previously incremented, but don't call the
405 closing procedure because we're not closing a handle! */
406 if(InterlockedDecrement(&ObjectHeader
->HandleCount
) == 0)
408 ObDereferenceObject(ObjectBody
);
411 ObDereferenceObject(ObjectBody
);
412 Status
= STATUS_UNSUCCESSFUL
;
415 KeLeaveCriticalRegion();
424 NtDuplicateObject (IN HANDLE SourceProcessHandle
,
425 IN HANDLE SourceHandle
,
426 IN HANDLE TargetProcessHandle
,
427 OUT PHANDLE TargetHandle OPTIONAL
,
428 IN ACCESS_MASK DesiredAccess
,
429 IN ULONG HandleAttributes
,
432 * FUNCTION: Copies a handle from one process space to another
434 * SourceProcessHandle = The source process owning the handle. The
435 * source process should have opened
436 * the SourceHandle with PROCESS_DUP_HANDLE
438 * SourceHandle = The handle to the object.
439 * TargetProcessHandle = The destination process owning the handle
440 * TargetHandle (OUT) = Caller should supply storage for the
442 * DesiredAccess = The desired access to the handle.
443 * HandleAttributes = The desired handle attributes.
444 * Options = Specifies special actions upon duplicating the handle.
445 * Can be one of the values DUPLICATE_CLOSE_SOURCE |
446 * DUPLICATE_SAME_ACCESS. DUPLICATE_CLOSE_SOURCE specifies
447 * that the source handle should be closed after duplicating.
448 * DUPLICATE_SAME_ACCESS specifies to ignore the
449 * DesiredAccess paramter and just grant the same access to
452 * REMARKS: This function maps to the win32 DuplicateHandle.
455 PEPROCESS SourceProcess
;
456 PEPROCESS TargetProcess
;
457 PEPROCESS CurrentProcess
;
459 BOOLEAN AttachedToProcess
= FALSE
;
460 KPROCESSOR_MODE PreviousMode
;
462 NTSTATUS Status
= STATUS_SUCCESS
;
466 PreviousMode
= ExGetPreviousMode();
468 if(TargetHandle
!= NULL
&& PreviousMode
!= KernelMode
)
472 ProbeForWriteHandle(TargetHandle
);
476 Status
= _SEH_GetExceptionCode();
480 if(!NT_SUCCESS(Status
))
486 Status
= ObReferenceObjectByHandle(SourceProcessHandle
,
490 (PVOID
*)&SourceProcess
,
492 if (!NT_SUCCESS(Status
))
497 Status
= ObReferenceObjectByHandle(TargetProcessHandle
,
501 (PVOID
*)&TargetProcess
,
503 if (!NT_SUCCESS(Status
))
505 ObDereferenceObject(SourceProcess
);
509 CurrentProcess
= PsGetCurrentProcess();
511 /* Check for magic handle first */
512 if (SourceHandle
== NtCurrentThread() ||
513 SourceHandle
== NtCurrentProcess())
516 POBJECT_TYPE ObjectType
;
518 ObjectType
= (SourceHandle
== NtCurrentThread()) ? PsThreadType
: PsProcessType
;
520 Status
= ObReferenceObjectByHandle(SourceHandle
,
526 if(NT_SUCCESS(Status
))
528 if (Options
& DUPLICATE_SAME_ACCESS
)
530 /* grant all access rights */
531 DesiredAccess
= ((ObjectType
== PsThreadType
) ? THREAD_ALL_ACCESS
: PROCESS_ALL_ACCESS
);
535 if (DesiredAccess
& GENERIC_ANY
)
537 RtlMapGenericMask(&DesiredAccess
,
538 &ObjectType
->TypeInfo
.GenericMapping
);
542 if (TargetProcess
!= CurrentProcess
)
544 KeStackAttachProcess(&TargetProcess
->Pcb
,
546 AttachedToProcess
= TRUE
;
549 Status
= ObpCreateHandle(ObjectBody
,
554 if (AttachedToProcess
)
556 KeUnstackDetachProcess(&ApcState
);
557 AttachedToProcess
= FALSE
;
560 ObDereferenceObject(ObjectBody
);
562 if (Options
& DUPLICATE_CLOSE_SOURCE
)
564 if (SourceProcess
!= CurrentProcess
)
566 KeStackAttachProcess(&SourceProcess
->Pcb
,
568 AttachedToProcess
= TRUE
;
571 ObpDeleteHandle(SourceHandle
);
573 if (AttachedToProcess
)
575 KeUnstackDetachProcess(&ApcState
);
582 Status
= ObDuplicateObject(SourceProcess
,
591 ObDereferenceObject(TargetProcess
);
592 ObDereferenceObject(SourceProcess
);
594 if(NT_SUCCESS(Status
) && TargetHandle
!= NULL
)
598 *TargetHandle
= hTarget
;
602 Status
= _SEH_GetExceptionCode();
611 SweepHandleCallback(PHANDLE_TABLE HandleTable
,
616 PROS_OBJECT_HEADER ObjectHeader
;
621 ObjectHeader
= EX_OBJ_TO_HDR(Object
);
622 ObjectBody
= &ObjectHeader
->Body
;
624 ObpDecrementHandleCount(ObjectBody
);
627 static BOOLEAN STDCALL
628 DuplicateHandleCallback(PHANDLE_TABLE HandleTable
,
629 PHANDLE_TABLE_ENTRY HandleTableEntry
,
632 PROS_OBJECT_HEADER ObjectHeader
;
637 Ret
= (HandleTableEntry
->u1
.ObAttributes
& EX_HANDLE_ENTRY_INHERITABLE
) != 0;
640 ObjectHeader
= EX_HTE_TO_HDR(HandleTableEntry
);
641 if(InterlockedIncrement(&ObjectHeader
->HandleCount
) == 1)
643 ObReferenceObject(&ObjectHeader
->Body
);
652 ObCreateHandleTable(PEPROCESS Parent
,
656 * FUNCTION: Creates a handle table for a process
658 * Parent = Parent process (or NULL if this is the first process)
659 * Inherit = True if the process should inherit its parent's handles
660 * Process = Process whose handle table is to be created
665 DPRINT("ObCreateHandleTable(Parent %x, Inherit %d, Process %x)\n",
666 Parent
,Inherit
,Process
);
669 Process
->ObjectTable
= ExDupHandleTable(Process
,
670 DuplicateHandleCallback
,
672 Parent
->ObjectTable
);
676 Process
->ObjectTable
= ExCreateHandleTable(Process
);
683 ObKillProcess(PEPROCESS Process
)
687 /* FIXME - Temporary hack: sweep and destroy here, needs to be fixed!!! */
688 ExSweepHandleTable(Process
->ObjectTable
,
691 ExDestroyHandleTable(Process
->ObjectTable
);
692 Process
->ObjectTable
= NULL
;
698 ObpCreateHandle(PVOID ObjectBody
,
699 ACCESS_MASK GrantedAccess
,
700 ULONG HandleAttributes
,
701 PHANDLE HandleReturn
)
703 * FUNCTION: Add a handle referencing an object
705 * obj = Object body that the handle should refer to
706 * RETURNS: The created handle
707 * NOTE: The handle is valid only in the context of the current process
710 HANDLE_TABLE_ENTRY NewEntry
;
711 PEPROCESS Process
, CurrentProcess
;
712 PROS_OBJECT_HEADER ObjectHeader
;
715 BOOLEAN AttachedToProcess
= FALSE
;
719 DPRINT("ObpCreateHandle(obj %p)\n",ObjectBody
);
723 CurrentProcess
= PsGetCurrentProcess();
725 ObjectHeader
= BODY_TO_HEADER(ObjectBody
);
727 /* check that this is a valid kernel pointer */
728 ASSERT((ULONG_PTR
)ObjectHeader
& EX_HANDLE_ENTRY_LOCKED
);
730 if (GrantedAccess
& MAXIMUM_ALLOWED
)
732 GrantedAccess
&= ~MAXIMUM_ALLOWED
;
733 GrantedAccess
|= GENERIC_ALL
;
736 if (GrantedAccess
& GENERIC_ANY
)
738 RtlMapGenericMask(&GrantedAccess
,
739 &ObjectHeader
->Type
->TypeInfo
.GenericMapping
);
742 NewEntry
.u1
.Object
= ObjectHeader
;
743 if(HandleAttributes
& OBJ_INHERIT
)
744 NewEntry
.u1
.ObAttributes
|= EX_HANDLE_ENTRY_INHERITABLE
;
746 NewEntry
.u1
.ObAttributes
&= ~EX_HANDLE_ENTRY_INHERITABLE
;
747 NewEntry
.u2
.GrantedAccess
= GrantedAccess
;
749 if ((HandleAttributes
& OBJ_KERNEL_HANDLE
) &&
750 ExGetPreviousMode
== KernelMode
)
752 Process
= PsInitialSystemProcess
;
753 if (Process
!= CurrentProcess
)
755 KeStackAttachProcess(&Process
->Pcb
,
757 AttachedToProcess
= TRUE
;
762 Process
= CurrentProcess
;
763 /* mask out the OBJ_KERNEL_HANDLE attribute */
764 HandleAttributes
&= ~OBJ_KERNEL_HANDLE
;
767 Handle
= ExCreateHandle(Process
->ObjectTable
,
770 if (AttachedToProcess
)
772 KeUnstackDetachProcess(&ApcState
);
777 if (HandleAttributes
& OBJ_KERNEL_HANDLE
)
779 /* mark the handle value */
780 Handle
= ObMarkHandleAsKernelHandle(Handle
);
783 if(InterlockedIncrement(&ObjectHeader
->HandleCount
) == 1)
785 ObReferenceObject(ObjectBody
);
788 *HandleReturn
= Handle
;
790 return STATUS_SUCCESS
;
793 return STATUS_UNSUCCESSFUL
;
801 ObQueryObjectAuditingByHandle(IN HANDLE Handle
,
802 OUT PBOOLEAN GenerateOnClose
)
804 PHANDLE_TABLE_ENTRY HandleEntry
;
805 PEPROCESS Process
, CurrentProcess
;
807 BOOLEAN AttachedToProcess
= FALSE
;
808 NTSTATUS Status
= STATUS_SUCCESS
;
812 DPRINT("ObQueryObjectAuditingByHandle(Handle %p)\n", Handle
);
814 CurrentProcess
= PsGetCurrentProcess();
816 KeEnterCriticalRegion();
818 if(ObIsKernelHandle(Handle
, ExGetPreviousMode()))
820 Process
= PsInitialSystemProcess
;
821 Handle
= ObKernelHandleToHandle(Handle
);
823 if (Process
!= CurrentProcess
)
825 KeStackAttachProcess(&Process
->Pcb
,
827 AttachedToProcess
= TRUE
;
831 Process
= CurrentProcess
;
833 HandleEntry
= ExMapHandleToPointer(Process
->ObjectTable
,
835 if(HandleEntry
!= NULL
)
837 *GenerateOnClose
= (HandleEntry
->u1
.ObAttributes
& EX_HANDLE_ENTRY_AUDITONCLOSE
) != 0;
839 ExUnlockHandleTableEntry(Process
->ObjectTable
,
843 Status
= STATUS_INVALID_HANDLE
;
845 if (AttachedToProcess
)
847 KeUnstackDetachProcess(&ApcState
);
850 KeLeaveCriticalRegion();
857 * FUNCTION: Increments the reference count for an object and returns a
858 * pointer to its body
860 * Handle = Handle for the object
861 * DesiredAccess = Desired access to the object
864 * Object (OUT) = Points to the object body on return
865 * HandleInformation (OUT) = Contains information about the handle
872 ObReferenceObjectByHandle(HANDLE Handle
,
873 ACCESS_MASK DesiredAccess
,
874 POBJECT_TYPE ObjectType
,
875 KPROCESSOR_MODE AccessMode
,
877 POBJECT_HANDLE_INFORMATION HandleInformation
)
879 PHANDLE_TABLE_ENTRY HandleEntry
;
880 PROS_OBJECT_HEADER ObjectHeader
;
882 ACCESS_MASK GrantedAccess
;
884 PEPROCESS CurrentProcess
, Process
;
885 BOOLEAN AttachedToProcess
= FALSE
;
890 DPRINT("ObReferenceObjectByHandle(Handle %p, DesiredAccess %x, "
891 "ObjectType %p, AccessMode %d, Object %p)\n",Handle
,DesiredAccess
,
892 ObjectType
,AccessMode
,Object
);
896 return STATUS_INVALID_HANDLE
;
899 CurrentProcess
= PsGetCurrentProcess();
902 * Handle special handle names
904 if (Handle
== NtCurrentProcess() &&
905 (ObjectType
== PsProcessType
|| ObjectType
== NULL
))
907 ObReferenceObject(CurrentProcess
);
909 if (HandleInformation
!= NULL
)
911 HandleInformation
->HandleAttributes
= 0;
912 HandleInformation
->GrantedAccess
= PROCESS_ALL_ACCESS
;
915 *Object
= CurrentProcess
;
916 DPRINT("Referencing current process %p\n", CurrentProcess
);
917 return STATUS_SUCCESS
;
919 else if (Handle
== NtCurrentProcess())
922 return(STATUS_OBJECT_TYPE_MISMATCH
);
925 if (Handle
== NtCurrentThread() &&
926 (ObjectType
== PsThreadType
|| ObjectType
== NULL
))
928 PETHREAD CurrentThread
= PsGetCurrentThread();
930 ObReferenceObject(CurrentThread
);
932 if (HandleInformation
!= NULL
)
934 HandleInformation
->HandleAttributes
= 0;
935 HandleInformation
->GrantedAccess
= THREAD_ALL_ACCESS
;
938 *Object
= CurrentThread
;
940 return STATUS_SUCCESS
;
942 else if (Handle
== NtCurrentThread())
945 return(STATUS_OBJECT_TYPE_MISMATCH
);
948 /* desire as much access rights as possible */
949 if (DesiredAccess
& MAXIMUM_ALLOWED
)
951 DesiredAccess
&= ~MAXIMUM_ALLOWED
;
952 DesiredAccess
|= GENERIC_ALL
;
955 if(ObIsKernelHandle(Handle
, AccessMode
))
957 Process
= PsInitialSystemProcess
;
958 Handle
= ObKernelHandleToHandle(Handle
);
962 Process
= CurrentProcess
;
965 KeEnterCriticalRegion();
967 if (Process
!= CurrentProcess
)
969 KeStackAttachProcess(&Process
->Pcb
,
971 AttachedToProcess
= TRUE
;
974 HandleEntry
= ExMapHandleToPointer(Process
->ObjectTable
,
976 if (HandleEntry
== NULL
)
978 if (AttachedToProcess
)
980 KeUnstackDetachProcess(&ApcState
);
982 KeLeaveCriticalRegion();
983 DPRINT("ExMapHandleToPointer() failed for handle 0x%p\n", Handle
);
984 return(STATUS_INVALID_HANDLE
);
987 ObjectHeader
= EX_HTE_TO_HDR(HandleEntry
);
988 ObjectBody
= &ObjectHeader
->Body
;
990 DPRINT("locked1: ObjectHeader: 0x%p [HT:0x%p]\n", ObjectHeader
, Process
->ObjectTable
);
992 if (ObjectType
!= NULL
&& ObjectType
!= ObjectHeader
->Type
)
994 DPRINT("ObjectType mismatch: %wZ vs %wZ (handle 0x%p)\n", &ObjectType
->Name
, ObjectHeader
->Type
? &ObjectHeader
->Type
->Name
: NULL
, Handle
);
996 ExUnlockHandleTableEntry(Process
->ObjectTable
,
999 if (AttachedToProcess
)
1001 KeUnstackDetachProcess(&ApcState
);
1004 KeLeaveCriticalRegion();
1006 return(STATUS_OBJECT_TYPE_MISMATCH
);
1009 /* map the generic access masks if the caller asks for generic access */
1010 if (DesiredAccess
& GENERIC_ANY
)
1012 RtlMapGenericMask(&DesiredAccess
,
1013 &BODY_TO_HEADER(ObjectBody
)->Type
->TypeInfo
.GenericMapping
);
1016 GrantedAccess
= HandleEntry
->u2
.GrantedAccess
;
1018 /* Unless running as KernelMode, deny access if caller desires more access
1019 rights than the handle can grant */
1020 if(AccessMode
!= KernelMode
&& (~GrantedAccess
& DesiredAccess
))
1022 ExUnlockHandleTableEntry(Process
->ObjectTable
,
1025 if (AttachedToProcess
)
1027 KeUnstackDetachProcess(&ApcState
);
1030 KeLeaveCriticalRegion();
1032 DPRINT1("GrantedAccess: 0x%x, ~GrantedAccess: 0x%x, DesiredAccess: 0x%x, denied: 0x%x\n", GrantedAccess
, ~GrantedAccess
, DesiredAccess
, ~GrantedAccess
& DesiredAccess
);
1034 return(STATUS_ACCESS_DENIED
);
1037 ObReferenceObject(ObjectBody
);
1039 Attributes
= HandleEntry
->u1
.ObAttributes
& (EX_HANDLE_ENTRY_PROTECTFROMCLOSE
|
1040 EX_HANDLE_ENTRY_INHERITABLE
|
1041 EX_HANDLE_ENTRY_AUDITONCLOSE
);
1043 ExUnlockHandleTableEntry(Process
->ObjectTable
,
1046 if (AttachedToProcess
)
1048 KeUnstackDetachProcess(&ApcState
);
1051 KeLeaveCriticalRegion();
1053 if (HandleInformation
!= NULL
)
1055 HandleInformation
->HandleAttributes
= Attributes
;
1056 HandleInformation
->GrantedAccess
= GrantedAccess
;
1059 *Object
= ObjectBody
;
1061 return(STATUS_SUCCESS
);
1065 /**********************************************************************
1070 * Closes a handle reference to an object.
1082 NtClose(IN HANDLE Handle
)
1084 PEPROCESS Process
, CurrentProcess
;
1085 BOOLEAN AttachedToProcess
= FALSE
;
1086 KAPC_STATE ApcState
;
1088 KPROCESSOR_MODE PreviousMode
;
1092 PreviousMode
= ExGetPreviousMode();
1093 CurrentProcess
= PsGetCurrentProcess();
1095 if(ObIsKernelHandle(Handle
, PreviousMode
))
1097 Process
= PsInitialSystemProcess
;
1098 Handle
= ObKernelHandleToHandle(Handle
);
1100 if (Process
!= CurrentProcess
)
1102 KeStackAttachProcess(&Process
->Pcb
,
1104 AttachedToProcess
= TRUE
;
1108 Process
= CurrentProcess
;
1110 Status
= ObpDeleteHandle(Handle
);
1112 if (AttachedToProcess
)
1114 KeUnstackDetachProcess(&ApcState
);
1117 if (!NT_SUCCESS(Status
))
1119 if((PreviousMode
!= KernelMode
) &&
1120 (CurrentProcess
->ExceptionPort
))
1122 KeRaiseUserException(Status
);
1127 return(STATUS_SUCCESS
);
1136 ObInsertObject(IN PVOID Object
,
1137 IN PACCESS_STATE PassedAccessState OPTIONAL
,
1138 IN ACCESS_MASK DesiredAccess
,
1139 IN ULONG AdditionalReferences
,
1140 OUT PVOID
* ReferencedObject OPTIONAL
,
1143 POBJECT_CREATE_INFORMATION ObjectCreateInfo
;
1144 PROS_OBJECT_HEADER Header
;
1145 POBJECT_HEADER_NAME_INFO ObjectNameInfo
;
1146 PVOID FoundObject
= NULL
;
1147 PROS_OBJECT_HEADER FoundHeader
= NULL
;
1148 NTSTATUS Status
= STATUS_SUCCESS
;
1149 UNICODE_STRING RemainingPath
;
1150 BOOLEAN ObjectAttached
= FALSE
;
1151 PSECURITY_DESCRIPTOR NewSecurityDescriptor
= NULL
;
1152 SECURITY_SUBJECT_CONTEXT SubjectContext
;
1156 /* Get the Header and Create Info */
1157 DPRINT("ObInsertObject: %x\n", Object
);
1158 Header
= BODY_TO_HEADER(Object
);
1159 ObjectCreateInfo
= Header
->ObjectCreateInfo
;
1160 ObjectNameInfo
= HEADER_TO_OBJECT_NAME(Header
);
1162 /* First try to find the Object */
1163 if (ObjectNameInfo
&& ObjectNameInfo
->Name
.Buffer
)
1165 DPRINT("Object has a name. Trying to find it: %wZ.\n", &ObjectNameInfo
->Name
);
1166 Status
= ObFindObject(ObjectCreateInfo
,
1167 &ObjectNameInfo
->Name
,
1171 DPRINT("FoundObject: %x, Path: %wZ\n", FoundObject
, &RemainingPath
);
1172 if (!NT_SUCCESS(Status
))
1174 DPRINT1("ObFindObject() failed! (Status 0x%x)\n", Status
);
1180 DPRINT("Getting header: %x\n", FoundObject
);
1181 FoundHeader
= BODY_TO_HEADER(FoundObject
);
1184 if (FoundHeader
&& RemainingPath
.Buffer
== NULL
)
1186 DPRINT("Object exists\n");
1187 ObDereferenceObject(FoundObject
);
1188 return STATUS_OBJECT_NAME_COLLISION
;
1193 DPRINT("No name, empty remaining path\n");
1194 RtlInitUnicodeString(&RemainingPath
, NULL
);
1197 if (FoundHeader
&& FoundHeader
->Type
== ObDirectoryType
&&
1198 RemainingPath
.Buffer
)
1200 /* The name was changed so let's update it */
1201 /* FIXME: TEMPORARY HACK This will go in ObFindObject in the next commit */
1203 PWSTR BufferPos
= RemainingPath
.Buffer
;
1206 ObpAddEntryDirectory(FoundObject
, (PROS_OBJECT_HEADER
)Header
, NULL
);
1207 ObjectAttached
= TRUE
;
1209 ObjectNameInfo
= HEADER_TO_OBJECT_NAME(Header
);
1211 if (BufferPos
[0] == L
'\\')
1214 Delta
= sizeof(WCHAR
);
1216 NewName
= ExAllocatePool(NonPagedPool
, RemainingPath
.MaximumLength
- Delta
);
1217 RtlMoveMemory(NewName
, BufferPos
, RemainingPath
.MaximumLength
- Delta
);
1218 if (ObjectNameInfo
->Name
.Buffer
) ExFreePool(ObjectNameInfo
->Name
.Buffer
);
1219 ObjectNameInfo
->Name
.Buffer
= NewName
;
1220 ObjectNameInfo
->Name
.Length
= RemainingPath
.Length
- Delta
;
1221 ObjectNameInfo
->Name
.MaximumLength
= RemainingPath
.MaximumLength
- Delta
;
1222 DPRINT("Name: %S\n", ObjectNameInfo
->Name
.Buffer
);
1225 if ((Header
->Type
== IoFileObjectType
) ||
1226 (Header
->Type
== ExDesktopObjectType
) ||
1227 (Header
->Type
->TypeInfo
.OpenProcedure
!= NULL
))
1229 DPRINT("About to call Open Routine\n");
1230 if (Header
->Type
== IoFileObjectType
)
1232 /* TEMPORARY HACK. DO NOT TOUCH -- Alex */
1233 DPRINT("Calling IopCreateFile: %x\n", FoundObject
);
1234 Status
= IopCreateFile(&Header
->Body
,
1236 RemainingPath
.Buffer
,
1238 DPRINT("Called IopCreateFile: %x\n", Status
);
1241 else if (Header
->Type
== ExDesktopObjectType
)
1243 /* TEMPORARY HACK. DO NOT TOUCH -- Alex */
1244 DPRINT("Calling ExpDesktopCreate\n");
1245 Status
= ExpDesktopCreate(&Header
->Body
,
1247 RemainingPath
.Buffer
,
1250 else if (Header
->Type
->TypeInfo
.OpenProcedure
!= NULL
)
1252 DPRINT("Calling %x\n", Header
->Type
->TypeInfo
.OpenProcedure
);
1253 Status
= Header
->Type
->TypeInfo
.OpenProcedure(ObCreateHandle
,
1260 if (!NT_SUCCESS(Status
))
1262 DPRINT("Create Failed\n");
1263 if (ObjectAttached
== TRUE
)
1265 ObpRemoveEntryDirectory((PROS_OBJECT_HEADER
)Header
);
1269 ObDereferenceObject(FoundObject
);
1271 RtlFreeUnicodeString(&RemainingPath
);
1276 RtlFreeUnicodeString(&RemainingPath
);
1278 DPRINT("Security Assignment in progress\n");
1279 SeCaptureSubjectContext(&SubjectContext
);
1281 /* Build the new security descriptor */
1282 Status
= SeAssignSecurity((FoundHeader
!= NULL
) ? FoundHeader
->SecurityDescriptor
: NULL
,
1283 (ObjectCreateInfo
!= NULL
) ? ObjectCreateInfo
->SecurityDescriptor
: NULL
,
1284 &NewSecurityDescriptor
,
1285 (Header
->Type
== ObDirectoryType
),
1287 &Header
->Type
->TypeInfo
.GenericMapping
,
1290 if (NT_SUCCESS(Status
))
1292 DPRINT("NewSecurityDescriptor %p\n", NewSecurityDescriptor
);
1294 if (Header
->Type
->TypeInfo
.SecurityProcedure
!= NULL
)
1296 /* Call the security method */
1297 Status
= Header
->Type
->TypeInfo
.SecurityProcedure(&Header
->Body
,
1298 AssignSecurityDescriptor
,
1300 NewSecurityDescriptor
,
1308 /* Assign the security descriptor to the object header */
1309 Status
= ObpAddSecurityDescriptor(NewSecurityDescriptor
,
1310 &Header
->SecurityDescriptor
);
1311 DPRINT("Object security descriptor %p\n", Header
->SecurityDescriptor
);
1314 /* Release the new security descriptor */
1315 SeDeassignSecurity(&NewSecurityDescriptor
);
1318 DPRINT("Security Complete\n");
1319 SeReleaseSubjectContext(&SubjectContext
);
1321 /* Create the Handle */
1322 /* HACKHACK: Because of ROS's incorrect startup, this can be called
1323 * without a valid Process until I finalize the startup patch,
1324 * so don't create a handle if this is the case. We also don't create
1325 * a handle if Handle is NULL when the Registry Code calls it, because
1326 * the registry code totally bastardizes the Ob and needs to be fixed
1328 DPRINT("Creating handle\n");
1331 Status
= ObpCreateHandle(&Header
->Body
,
1333 ObjectCreateInfo
->Attributes
,
1335 DPRINT("handle Created: %d. refcount. handlecount %d %d\n",
1336 *Handle
, Header
->PointerCount
, Header
->HandleCount
);
1339 /* We can delete the Create Info now */
1340 Header
->ObjectCreateInfo
= NULL
;
1341 ObpReleaseCapturedAttributes(ObjectCreateInfo
);
1342 ExFreePool(ObjectCreateInfo
);
1344 DPRINT("Status %x\n", Status
);
1351 ObpGetHandleCountByHandleTable(PHANDLE_TABLE HandleTable
)
1353 return HandleTable
->HandleCount
;
1357 * FUNCTION: Searches the handle table of a specified process whether it contains a
1358 * valid handle to the Object we're looking for. If not, it'll create one.
1361 * The parameters of this function is basically a mixture of some of the parameters
1362 * of ObReferenceObjectByHandle() and ObReferenceObjectByPointer(). A little thinking
1363 * about what this function does (by it's name) makes clear what parameters it requires.
1364 * For example the AccessMode parameter of ObReferenceObjectByHandle/Pointer() is not
1365 * required at all as it only has influence on the object security. This function doesn't
1366 * want to get access to an object, it just looks for a valid handle and if it can't find
1367 * one, it'll just create one. It wouldn't make sense to check for security again as the
1368 * caller already has a pointer to the object.
1370 * A test on an XP machine shows that this prototype appears to be correct.
1373 * Process = This parameter simply describes in which handle table we're looking
1374 * for a handle to the object.
1375 * Object = The object pointer that we're looking for
1376 * ObjectType = Just a sanity check as ObReferenceObjectByHandle() and
1377 * ObReferenceObjectByPointer() provides.
1378 * HandleInformation = This one has to be the opposite meaning of the usage in
1379 * ObReferenceObjectByHandle(). If we actually found a valid
1380 * handle in the table, we need to check against the information
1381 * provided so we make sure this handle has all access rights
1382 * (and attributes?!) we need. If they don't match, we can't
1383 * use this handle and keep looking because the caller is likely
1384 * to depend on these access rights.
1385 * HandleReturn = The last parameter is the same as in ObCreateHandle(). If we could
1386 * find a suitable handle in the handle table, return this handle, if
1387 * not, we'll just create one using ObCreateHandle() with all access
1388 * rights the caller needs.
1395 ObFindHandleForObject(IN PEPROCESS Process
,
1397 IN POBJECT_TYPE ObjectType
,
1398 IN POBJECT_HANDLE_INFORMATION HandleInformation
,
1399 OUT PHANDLE HandleReturn
)
1401 DPRINT("ObFindHandleForObject is unimplemented!\n");
1402 return STATUS_UNSUCCESSFUL
;
1406 ObpGetNextHandleByProcessCount(PSYSTEM_HANDLE_TABLE_ENTRY_INFO pshi
,
1413 // pshi->HandleValue;
1416 This will never work with ROS! M$, I guess uses 0 -> 65535.
1417 Ros uses 0 -> 4294967295!
1420 P
= (ULONG
) Process
->UniqueProcessId
;
1421 pshi
->UniqueProcessId
= (USHORT
) P
;
1423 // KeAcquireSpinLock( &Process->HandleTable.ListLock, &oldIrql );
1425 // pshi->GrantedAccess;
1428 // pshi->HandleAttributes;
1430 // KeReleaseSpinLock( &Process->HandleTable.ListLock, oldIrql );