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 LONG NewHandleCount
= InterlockedDecrement(&ObjectHeader
->HandleCount
);
65 if ((ObjectHeader
->ObjectType
!= NULL
) &&
66 (ObjectHeader
->ObjectType
->TypeInfo
.CloseProcedure
!= NULL
))
68 /* the handle count should be decremented but we pass the previous value
70 ObjectHeader
->ObjectType
->TypeInfo
.CloseProcedure(ObjectBody
, NewHandleCount
+ 1);
73 if(NewHandleCount
== 0)
75 if(ObjectHeader
->NameInfo
->Directory
!= NULL
&& !ObjectHeader
->Permanent
)
77 /* delete the object from the namespace when the last handle got closed.
78 Only do this if it's actually been inserted into the namespace and
79 if it's not a permanent object. */
80 ObpRemoveEntryDirectory(ObjectHeader
);
83 /* remove the keep-alive reference */
84 ObDereferenceObject(ObjectBody
);
90 ObpQueryHandleAttributes(HANDLE Handle
,
91 POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo
)
93 PHANDLE_TABLE HandleTable
;
94 PHANDLE_TABLE_ENTRY HandleTableEntry
;
99 DPRINT("ObpQueryHandleAttributes(Handle %x)\n", Handle
);
101 if(ObIsKernelHandle(Handle
, ExGetPreviousMode()))
103 HandleTable
= ObpKernelHandleTable
;
104 ExHandle
= HANDLE_TO_EX_HANDLE(ObKernelHandleToHandle(Handle
));
108 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
109 ExHandle
= HANDLE_TO_EX_HANDLE(Handle
);
112 KeEnterCriticalRegion();
114 HandleTableEntry
= ExMapHandleToPointer(HandleTable
,
116 if (HandleTableEntry
== NULL
)
118 KeLeaveCriticalRegion();
119 return STATUS_INVALID_HANDLE
;
122 HandleInfo
->Inherit
= (HandleTableEntry
->u1
.ObAttributes
& EX_HANDLE_ENTRY_INHERITABLE
) != 0;
123 HandleInfo
->ProtectFromClose
= (HandleTableEntry
->u1
.ObAttributes
& EX_HANDLE_ENTRY_PROTECTFROMCLOSE
) != 0;
125 ExUnlockHandleTableEntry(HandleTable
,
128 KeLeaveCriticalRegion();
130 return STATUS_SUCCESS
;
135 ObpSetHandleAttributes(HANDLE Handle
,
136 POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo
)
138 PHANDLE_TABLE HandleTable
;
139 PHANDLE_TABLE_ENTRY HandleTableEntry
;
144 DPRINT("ObpSetHandleAttributes(Handle %x)\n", Handle
);
146 if(ObIsKernelHandle(Handle
, ExGetPreviousMode()))
148 HandleTable
= ObpKernelHandleTable
;
149 ExHandle
= HANDLE_TO_EX_HANDLE(ObKernelHandleToHandle(Handle
));
153 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
154 ExHandle
= HANDLE_TO_EX_HANDLE(Handle
);
157 KeEnterCriticalRegion();
159 HandleTableEntry
= ExMapHandleToPointer(HandleTable
,
161 if (HandleTableEntry
== NULL
)
163 KeLeaveCriticalRegion();
164 return STATUS_INVALID_HANDLE
;
167 if (HandleInfo
->Inherit
)
168 HandleTableEntry
->u1
.ObAttributes
|= EX_HANDLE_ENTRY_INHERITABLE
;
170 HandleTableEntry
->u1
.ObAttributes
&= ~EX_HANDLE_ENTRY_INHERITABLE
;
172 if (HandleInfo
->ProtectFromClose
)
173 HandleTableEntry
->u1
.ObAttributes
|= EX_HANDLE_ENTRY_PROTECTFROMCLOSE
;
175 HandleTableEntry
->u1
.ObAttributes
&= ~EX_HANDLE_ENTRY_PROTECTFROMCLOSE
;
177 /* FIXME: Do we need to set anything in the object header??? */
179 ExUnlockHandleTableEntry(HandleTable
,
182 KeLeaveCriticalRegion();
184 return STATUS_SUCCESS
;
189 ObpDeleteHandle(PHANDLE_TABLE HandleTable
,
192 PHANDLE_TABLE_ENTRY HandleEntry
;
194 POBJECT_HEADER ObjectHeader
;
195 LONG ExHandle
= HANDLE_TO_EX_HANDLE(Handle
);
199 DPRINT("ObpDeleteHandle(Handle %x)\n",Handle
);
201 KeEnterCriticalRegion();
203 HandleEntry
= ExMapHandleToPointer(HandleTable
,
205 if(HandleEntry
!= NULL
)
207 if(HandleEntry
->u1
.ObAttributes
& EX_HANDLE_ENTRY_PROTECTFROMCLOSE
)
209 ExUnlockHandleTableEntry(HandleTable
,
212 KeLeaveCriticalRegion();
214 return STATUS_HANDLE_NOT_CLOSABLE
;
217 ObjectHeader
= EX_HTE_TO_HDR(HandleEntry
);
218 Body
= HEADER_TO_BODY(ObjectHeader
);
220 ObpDecrementHandleCount(Body
);
222 /* destroy and unlock the handle entry */
223 ExDestroyHandleByEntry(HandleTable
,
227 KeLeaveCriticalRegion();
229 return STATUS_SUCCESS
;
231 KeLeaveCriticalRegion();
232 return STATUS_INVALID_HANDLE
;
237 ObDuplicateObject(PEPROCESS SourceProcess
,
238 PEPROCESS TargetProcess
,
240 PHANDLE TargetHandle
,
241 ACCESS_MASK DesiredAccess
,
242 BOOLEAN InheritHandle
,
245 PHANDLE_TABLE SourceHandleTable
;
246 PHANDLE_TABLE_ENTRY SourceHandleEntry
;
247 HANDLE_TABLE_ENTRY NewHandleEntry
;
249 POBJECT_HEADER ObjectHeader
;
252 ULONG NewHandleCount
;
256 if(ObIsKernelHandle(SourceHandle
, ExGetPreviousMode()))
258 SourceHandleTable
= ObpKernelHandleTable
;
259 SourceHandle
= ObKernelHandleToHandle(SourceHandle
);
263 SourceHandleTable
= SourceProcess
->ObjectTable
;
266 ExSourceHandle
= HANDLE_TO_EX_HANDLE(SourceHandle
);
268 KeEnterCriticalRegion();
270 SourceHandleEntry
= ExMapHandleToPointer(SourceHandleTable
,
272 if (SourceHandleEntry
== NULL
)
274 KeLeaveCriticalRegion();
275 return STATUS_INVALID_HANDLE
;
278 ObjectHeader
= EX_HTE_TO_HDR(SourceHandleEntry
);
279 ObjectBody
= HEADER_TO_BODY(ObjectHeader
);
281 NewHandleEntry
.u1
.Object
= SourceHandleEntry
->u1
.Object
;
283 NewHandleEntry
.u1
.ObAttributes
|= EX_HANDLE_ENTRY_INHERITABLE
;
285 NewHandleEntry
.u1
.ObAttributes
&= ~EX_HANDLE_ENTRY_INHERITABLE
;
286 NewHandleEntry
.u2
.GrantedAccess
= ((Options
& DUPLICATE_SAME_ACCESS
) ?
287 SourceHandleEntry
->u2
.GrantedAccess
:
289 if (Options
& DUPLICATE_SAME_ACCESS
)
291 NewHandleEntry
.u2
.GrantedAccess
= SourceHandleEntry
->u2
.GrantedAccess
;
295 if (DesiredAccess
& GENERIC_ANY
)
297 RtlMapGenericMask(&DesiredAccess
,
298 &ObjectHeader
->ObjectType
->TypeInfo
.GenericMapping
);
300 NewHandleEntry
.u2
.GrantedAccess
= DesiredAccess
;
303 /* reference the object so it doesn't get deleted after releasing the lock
304 and before creating a new handle for it */
305 ObReferenceObject(ObjectBody
);
307 /* increment the handle count of the object, it should always be >= 2 because
308 we're holding a handle lock to this object! if the new handle count was
309 1 here, we're in big trouble... it would've been safe to increment and
310 check the handle count without using interlocked functions because the
311 entry is locked, which means the handle count can't change. */
312 NewHandleCount
= InterlockedIncrement(&ObjectHeader
->HandleCount
);
313 ASSERT(NewHandleCount
>= 2);
315 ExUnlockHandleTableEntry(SourceHandleTable
,
318 KeLeaveCriticalRegion();
320 /* attempt to create the new handle */
321 ExTargetHandle
= ExCreateHandle(TargetProcess
->ObjectTable
,
323 if (ExTargetHandle
!= EX_INVALID_HANDLE
)
325 if (Options
& DUPLICATE_CLOSE_SOURCE
)
327 ObpDeleteHandle(SourceHandleTable
,
331 ObDereferenceObject(ObjectBody
);
333 *TargetHandle
= EX_HANDLE_TO_HANDLE(ExTargetHandle
);
335 return STATUS_SUCCESS
;
339 /* decrement the handle count we previously incremented, but don't call the
340 closing procedure because we're not closing a handle! */
341 if(InterlockedDecrement(&ObjectHeader
->HandleCount
) == 0)
343 ObDereferenceObject(ObjectBody
);
346 ObDereferenceObject(ObjectBody
);
347 return STATUS_UNSUCCESSFUL
;
355 NtDuplicateObject (IN HANDLE SourceProcessHandle
,
356 IN HANDLE SourceHandle
,
357 IN HANDLE TargetProcessHandle
,
358 OUT PHANDLE TargetHandle OPTIONAL
,
359 IN ACCESS_MASK DesiredAccess
,
360 IN BOOLEAN InheritHandle
,
363 * FUNCTION: Copies a handle from one process space to another
365 * SourceProcessHandle = The source process owning the handle. The
366 * source process should have opened
367 * the SourceHandle with PROCESS_DUP_HANDLE
369 * SourceHandle = The handle to the object.
370 * TargetProcessHandle = The destination process owning the handle
371 * TargetHandle (OUT) = Caller should supply storage for the
373 * DesiredAccess = The desired access to the handle.
374 * InheritHandle = Indicates wheter the new handle will be inheritable
376 * Options = Specifies special actions upon duplicating the handle.
377 * Can be one of the values DUPLICATE_CLOSE_SOURCE |
378 * DUPLICATE_SAME_ACCESS. DUPLICATE_CLOSE_SOURCE specifies
379 * that the source handle should be closed after duplicating.
380 * DUPLICATE_SAME_ACCESS specifies to ignore the
381 * DesiredAccess paramter and just grant the same access to
384 * REMARKS: This function maps to the win32 DuplicateHandle.
387 PEPROCESS SourceProcess
;
388 PEPROCESS TargetProcess
;
390 KPROCESSOR_MODE PreviousMode
;
391 NTSTATUS Status
= STATUS_SUCCESS
;
395 PreviousMode
= ExGetPreviousMode();
397 if(TargetHandle
!= NULL
&& PreviousMode
!= KernelMode
)
401 ProbeForWrite(TargetHandle
,
407 Status
= _SEH_GetExceptionCode();
411 if(!NT_SUCCESS(Status
))
417 Status
= ObReferenceObjectByHandle(SourceProcessHandle
,
421 (PVOID
*)&SourceProcess
,
423 if (!NT_SUCCESS(Status
))
428 Status
= ObReferenceObjectByHandle(TargetProcessHandle
,
432 (PVOID
*)&TargetProcess
,
434 if (!NT_SUCCESS(Status
))
436 ObDereferenceObject(SourceProcess
);
440 /* Check for magic handle first */
441 if (SourceHandle
== NtCurrentThread() ||
442 SourceHandle
== NtCurrentProcess())
445 POBJECT_TYPE ObjectType
;
447 ObjectType
= (SourceHandle
== NtCurrentThread()) ? PsThreadType
: PsProcessType
;
449 Status
= ObReferenceObjectByHandle(SourceHandle
,
455 if(NT_SUCCESS(Status
))
457 if (Options
& DUPLICATE_SAME_ACCESS
)
459 /* grant all access rights */
460 DesiredAccess
= ((ObjectType
== PsThreadType
) ? THREAD_ALL_ACCESS
: PROCESS_ALL_ACCESS
);
464 if (DesiredAccess
& GENERIC_ANY
)
466 RtlMapGenericMask(&DesiredAccess
,
467 &ObjectType
->TypeInfo
.GenericMapping
);
470 Status
= ObpCreateHandle(TargetProcess
,
476 ObDereferenceObject(ObjectBody
);
478 if (Options
& DUPLICATE_CLOSE_SOURCE
)
480 ObpDeleteHandle(SourceProcess
->ObjectTable
,
487 Status
= ObDuplicateObject(SourceProcess
,
496 ObDereferenceObject(TargetProcess
);
497 ObDereferenceObject(SourceProcess
);
499 if(NT_SUCCESS(Status
) && TargetHandle
!= NULL
)
503 *TargetHandle
= hTarget
;
507 Status
= _SEH_GetExceptionCode();
516 DeleteHandleCallback(PHANDLE_TABLE HandleTable
,
521 POBJECT_HEADER ObjectHeader
;
526 ObjectHeader
= EX_OBJ_TO_HDR(Object
);
527 ObjectBody
= HEADER_TO_BODY(ObjectHeader
);
529 ObpDecrementHandleCount(ObjectBody
);
532 static BOOLEAN STDCALL
533 DuplicateHandleCallback(PHANDLE_TABLE HandleTable
,
534 PHANDLE_TABLE_ENTRY HandleTableEntry
,
537 POBJECT_HEADER ObjectHeader
;
542 Ret
= (HandleTableEntry
->u1
.ObAttributes
& EX_HANDLE_ENTRY_INHERITABLE
) != 0;
545 ObjectHeader
= EX_HTE_TO_HDR(HandleTableEntry
);
546 if(InterlockedIncrement(&ObjectHeader
->HandleCount
) == 1)
548 ObReferenceObject(HEADER_TO_BODY(ObjectHeader
));
555 VOID
ObCreateHandleTable(PEPROCESS Parent
,
559 * FUNCTION: Creates a handle table for a process
561 * Parent = Parent process (or NULL if this is the first process)
562 * Inherit = True if the process should inherit its parent's handles
563 * Process = Process whose handle table is to be created
568 DPRINT("ObCreateHandleTable(Parent %x, Inherit %d, Process %x)\n",
569 Parent
,Inherit
,Process
);
572 Process
->ObjectTable
= ExDupHandleTable(Process
,
573 DuplicateHandleCallback
,
575 Parent
->ObjectTable
);
579 Process
->ObjectTable
= ExCreateHandleTable(Process
);
586 ObKillProcess(PEPROCESS Process
)
590 ExDestroyHandleTable(Process
->ObjectTable
,
591 DeleteHandleCallback
,
597 ObpCreateHandle(PEPROCESS Process
,
599 ACCESS_MASK GrantedAccess
,
601 PHANDLE HandleReturn
)
603 * FUNCTION: Add a handle referencing an object
605 * obj = Object body that the handle should refer to
606 * RETURNS: The created handle
607 * NOTE: The handle is valid only in the context of the current process
610 HANDLE_TABLE_ENTRY NewEntry
;
611 POBJECT_HEADER ObjectHeader
;
616 DPRINT("ObpCreateHandle(Process %x, obj %x)\n",Process
,ObjectBody
);
621 ObjectHeader
= BODY_TO_HEADER(ObjectBody
);
623 ASSERT((ULONG_PTR
)ObjectHeader
& EX_HANDLE_ENTRY_LOCKED
);
625 if (GrantedAccess
& MAXIMUM_ALLOWED
)
627 GrantedAccess
&= ~MAXIMUM_ALLOWED
;
628 GrantedAccess
|= GENERIC_ALL
;
631 if (GrantedAccess
& GENERIC_ANY
)
633 RtlMapGenericMask(&GrantedAccess
,
634 &ObjectHeader
->ObjectType
->TypeInfo
.GenericMapping
);
637 NewEntry
.u1
.Object
= ObjectHeader
;
639 NewEntry
.u1
.ObAttributes
|= EX_HANDLE_ENTRY_INHERITABLE
;
641 NewEntry
.u1
.ObAttributes
&= ~EX_HANDLE_ENTRY_INHERITABLE
;
642 NewEntry
.u2
.GrantedAccess
= GrantedAccess
;
644 ExHandle
= ExCreateHandle(Process
->ObjectTable
,
646 DPRINT("ObCreateHandle(0x%x)==0x%x [HT:0x%x]\n", ObjectHeader
, *HandleReturn
, Process
->ObjectTable
);
647 if(ExHandle
!= EX_INVALID_HANDLE
)
649 if(InterlockedIncrement(&ObjectHeader
->HandleCount
) == 1)
651 ObReferenceObjectByPointer(ObjectBody
,
657 *HandleReturn
= EX_HANDLE_TO_HANDLE(ExHandle
);
659 return STATUS_SUCCESS
;
662 return STATUS_UNSUCCESSFUL
;
670 ObQueryObjectAuditingByHandle(IN HANDLE Handle
,
671 OUT PBOOLEAN GenerateOnClose
)
673 PHANDLE_TABLE_ENTRY HandleEntry
;
675 LONG ExHandle
= HANDLE_TO_EX_HANDLE(Handle
);
679 DPRINT("ObQueryObjectAuditingByHandle(Handle %x)\n", Handle
);
681 Process
= PsGetCurrentProcess();
683 KeEnterCriticalRegion();
685 HandleEntry
= ExMapHandleToPointer(Process
->ObjectTable
,
687 if(HandleEntry
!= NULL
)
689 *GenerateOnClose
= (HandleEntry
->u1
.ObAttributes
& EX_HANDLE_ENTRY_AUDITONCLOSE
) != 0;
691 ExUnlockHandleTableEntry(Process
->ObjectTable
,
694 KeLeaveCriticalRegion();
696 return STATUS_SUCCESS
;
699 KeLeaveCriticalRegion();
701 return STATUS_INVALID_HANDLE
;
706 * FUNCTION: Increments the reference count for an object and returns a
707 * pointer to its body
709 * Handle = Handle for the object
710 * DesiredAccess = Desired access to the object
713 * Object (OUT) = Points to the object body on return
714 * HandleInformation (OUT) = Contains information about the handle
721 ObReferenceObjectByHandle(HANDLE Handle
,
722 ACCESS_MASK DesiredAccess
,
723 POBJECT_TYPE ObjectType
,
724 KPROCESSOR_MODE AccessMode
,
726 POBJECT_HANDLE_INFORMATION HandleInformation
)
728 PHANDLE_TABLE_ENTRY HandleEntry
;
729 POBJECT_HEADER ObjectHeader
;
730 PHANDLE_TABLE HandleTable
;
732 ACCESS_MASK GrantedAccess
;
738 DPRINT("ObReferenceObjectByHandle(Handle %x, DesiredAccess %x, "
739 "ObjectType %x, AccessMode %d, Object %x)\n",Handle
,DesiredAccess
,
740 ObjectType
,AccessMode
,Object
);
743 * Handle special handle names
745 if (Handle
== NtCurrentProcess() &&
746 (ObjectType
== PsProcessType
|| ObjectType
== NULL
))
748 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
750 ObReferenceObject(CurrentProcess
);
752 if (HandleInformation
!= NULL
)
754 HandleInformation
->HandleAttributes
= 0;
755 HandleInformation
->GrantedAccess
= PROCESS_ALL_ACCESS
;
758 *Object
= CurrentProcess
;
759 DPRINT("Referencing current process %x\n", CurrentProcess
);
760 return STATUS_SUCCESS
;
762 else if (Handle
== NtCurrentProcess())
765 return(STATUS_OBJECT_TYPE_MISMATCH
);
768 if (Handle
== NtCurrentThread() &&
769 (ObjectType
== PsThreadType
|| ObjectType
== NULL
))
771 PETHREAD CurrentThread
= PsGetCurrentThread();
773 ObReferenceObject(CurrentThread
);
775 if (HandleInformation
!= NULL
)
777 HandleInformation
->HandleAttributes
= 0;
778 HandleInformation
->GrantedAccess
= THREAD_ALL_ACCESS
;
781 *Object
= CurrentThread
;
783 return STATUS_SUCCESS
;
785 else if (Handle
== NtCurrentThread())
788 return(STATUS_OBJECT_TYPE_MISMATCH
);
791 /* desire as much access rights as possible */
792 if (DesiredAccess
& MAXIMUM_ALLOWED
)
794 DesiredAccess
&= ~MAXIMUM_ALLOWED
;
795 DesiredAccess
|= GENERIC_ALL
;
798 if(ObIsKernelHandle(Handle
, AccessMode
))
800 HandleTable
= ObpKernelHandleTable
;
801 ExHandle
= HANDLE_TO_EX_HANDLE(ObKernelHandleToHandle(Handle
));
805 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
806 ExHandle
= HANDLE_TO_EX_HANDLE(Handle
);
809 KeEnterCriticalRegion();
811 HandleEntry
= ExMapHandleToPointer(HandleTable
,
813 if (HandleEntry
== NULL
)
815 KeLeaveCriticalRegion();
816 DPRINT("ExMapHandleToPointer() failed for handle 0x%x\n", Handle
);
817 return(STATUS_INVALID_HANDLE
);
820 ObjectHeader
= EX_HTE_TO_HDR(HandleEntry
);
821 ObjectBody
= HEADER_TO_BODY(ObjectHeader
);
823 DPRINT("locked1: ObjectHeader: 0x%x [HT:0x%x]\n", ObjectHeader
, HandleTable
);
825 if (ObjectType
!= NULL
&& ObjectType
!= ObjectHeader
->ObjectType
)
827 DPRINT("ObjectType mismatch: %wZ vs %wZ (handle 0x%x)\n", &ObjectType
->TypeName
, ObjectHeader
->ObjectType
? &ObjectHeader
->ObjectType
->TypeName
: NULL
, Handle
);
829 ExUnlockHandleTableEntry(HandleTable
,
832 KeLeaveCriticalRegion();
834 return(STATUS_OBJECT_TYPE_MISMATCH
);
837 /* map the generic access masks if the caller asks for generic access */
838 if (DesiredAccess
& GENERIC_ANY
)
840 RtlMapGenericMask(&DesiredAccess
,
841 &BODY_TO_HEADER(ObjectBody
)->ObjectType
->TypeInfo
.GenericMapping
);
844 GrantedAccess
= HandleEntry
->u2
.GrantedAccess
;
846 /* Unless running as KernelMode, deny access if caller desires more access
847 rights than the handle can grant */
848 if(AccessMode
!= KernelMode
&& (~GrantedAccess
& DesiredAccess
))
850 ExUnlockHandleTableEntry(HandleTable
,
853 KeLeaveCriticalRegion();
855 DPRINT1("GrantedAccess: 0x%x, ~GrantedAccess: 0x%x, DesiredAccess: 0x%x, denied: 0x%x\n", GrantedAccess
, ~GrantedAccess
, DesiredAccess
, ~GrantedAccess
& DesiredAccess
);
857 return(STATUS_ACCESS_DENIED
);
860 ObReferenceObject(ObjectBody
);
862 Attributes
= HandleEntry
->u1
.ObAttributes
& (EX_HANDLE_ENTRY_PROTECTFROMCLOSE
|
863 EX_HANDLE_ENTRY_INHERITABLE
|
864 EX_HANDLE_ENTRY_AUDITONCLOSE
);
866 ExUnlockHandleTableEntry(HandleTable
,
869 KeLeaveCriticalRegion();
871 if (HandleInformation
!= NULL
)
873 HandleInformation
->HandleAttributes
= Attributes
;
874 HandleInformation
->GrantedAccess
= GrantedAccess
;
877 *Object
= ObjectBody
;
879 return(STATUS_SUCCESS
);
883 /**********************************************************************
888 * Closes a handle reference to an object.
900 NtClose(IN HANDLE Handle
)
902 PHANDLE_TABLE HandleTable
;
907 if(ObIsKernelHandle(Handle
, ExGetPreviousMode()))
909 HandleTable
= ObpKernelHandleTable
;
910 Handle
= ObKernelHandleToHandle(Handle
);
914 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
917 Status
= ObpDeleteHandle(HandleTable
,
919 if (!NT_SUCCESS(Status
))
921 if((ExGetPreviousMode() != KernelMode
) &&
922 (PsGetCurrentProcess()->ExceptionPort
))
924 KeRaiseUserException(Status
);
929 return(STATUS_SUCCESS
);
938 ObInsertObject(IN PVOID Object
,
939 IN PACCESS_STATE PassedAccessState OPTIONAL
,
940 IN ACCESS_MASK DesiredAccess
,
941 IN ULONG AdditionalReferences
,
942 OUT PVOID
* ReferencedObject OPTIONAL
,
945 POBJECT_CREATE_INFORMATION ObjectCreateInfo
;
946 POBJECT_HEADER Header
;
947 POBJECT_HEADER_NAME_INFO ObjectNameInfo
;
948 PVOID FoundObject
= NULL
;
949 POBJECT_HEADER FoundHeader
= NULL
;
950 NTSTATUS Status
= STATUS_SUCCESS
;
951 UNICODE_STRING RemainingPath
;
952 BOOLEAN ObjectAttached
= FALSE
;
953 PSECURITY_DESCRIPTOR NewSecurityDescriptor
= NULL
;
954 SECURITY_SUBJECT_CONTEXT SubjectContext
;
958 /* Get the Header and Create Info */
959 DPRINT("ObInsertObject: %x\n", Object
);
960 Header
= BODY_TO_HEADER(Object
);
961 ObjectCreateInfo
= Header
->ObjectCreateInfo
;
962 ObjectNameInfo
= Header
->NameInfo
;
964 /* First try to find the Object */
965 if (ObjectNameInfo
&& ObjectNameInfo
->Name
.Buffer
)
967 DPRINT("Object has a name. Trying to find it: %wZ.\n", &ObjectNameInfo
->Name
);
968 Status
= ObFindObject(ObjectCreateInfo
,
969 &ObjectNameInfo
->Name
,
973 DPRINT("FoundObject: %x, Path: %wZ\n", FoundObject
, &RemainingPath
);
974 if (!NT_SUCCESS(Status
))
976 DPRINT1("ObFindObject() failed! (Status 0x%x)\n", Status
);
982 DPRINT("Getting header: %x\n", FoundObject
);
983 FoundHeader
= BODY_TO_HEADER(FoundObject
);
986 if (FoundHeader
&& RemainingPath
.Buffer
== NULL
)
988 DPRINT("Object exists\n");
989 if (FoundHeader
->ObjectType
!= Header
->ObjectType
990 || !(ObjectCreateInfo
->Attributes
& OBJ_OPENIF
))
992 ObDereferenceObject(FoundObject
);
993 return STATUS_OBJECT_NAME_COLLISION
;
995 return STATUS_OBJECT_EXISTS
;
1000 DPRINT("No name, empty remaining path\n");
1001 RtlInitUnicodeString(&RemainingPath
, NULL
);
1004 if (FoundHeader
&& FoundHeader
->ObjectType
== ObDirectoryType
&&
1005 RemainingPath
.Buffer
)
1007 DPRINT("Adding to Object Directory\n");
1008 ObpAddEntryDirectory(FoundObject
, Header
, NULL
);
1009 ObjectAttached
= TRUE
;
1011 /* The name was changed so let's update it */
1012 /* FIXME: TEMPORARY HACK This will go in ObFindObject in the next commit */
1014 PWSTR BufferPos
= RemainingPath
.Buffer
;
1016 NewName
= ExAllocatePool(NonPagedPool
, RemainingPath
.MaximumLength
);
1017 ObjectNameInfo
= Header
->NameInfo
;
1019 if (BufferPos
[0] == L
'\\')
1024 RtlMoveMemory(NewName
, BufferPos
, RemainingPath
.MaximumLength
);
1025 if (ObjectNameInfo
->Name
.Buffer
) ExFreePool(ObjectNameInfo
->Name
.Buffer
);
1026 ObjectNameInfo
->Name
.Buffer
= NewName
;
1027 ObjectNameInfo
->Name
.Length
= RemainingPath
.Length
;
1028 ObjectNameInfo
->Name
.MaximumLength
= RemainingPath
.MaximumLength
;
1029 DPRINT("Name: %S\n", ObjectNameInfo
->Name
.Buffer
);
1032 if ((Header
->ObjectType
== IoFileObjectType
) ||
1033 (Header
->ObjectType
== ExDesktopObjectType
) ||
1034 (Header
->ObjectType
->TypeInfo
.OpenProcedure
!= NULL
))
1036 DPRINT("About to call Open Routine\n");
1037 if (Header
->ObjectType
== IoFileObjectType
)
1039 /* TEMPORARY HACK. DO NOT TOUCH -- Alex */
1040 DPRINT("Calling IopCreateFile: %x\n", FoundObject
);
1041 Status
= IopCreateFile(HEADER_TO_BODY(Header
),
1043 RemainingPath
.Buffer
,
1045 DPRINT("Called IopCreateFile: %x\n", Status
);
1048 else if (Header
->ObjectType
== ExDesktopObjectType
)
1050 /* TEMPORARY HACK. DO NOT TOUCH -- Alex */
1051 DPRINT("Calling ExpDesktopCreate\n");
1052 Status
= ExpDesktopCreate(HEADER_TO_BODY(Header
),
1054 RemainingPath
.Buffer
,
1057 else if (Header
->ObjectType
->TypeInfo
.OpenProcedure
!= NULL
)
1059 DPRINT("Calling %x\n", Header
->ObjectType
->TypeInfo
.OpenProcedure
);
1060 Status
= Header
->ObjectType
->TypeInfo
.OpenProcedure(ObCreateHandle
,
1061 HEADER_TO_BODY(Header
),
1067 if (!NT_SUCCESS(Status
))
1069 DPRINT("Create Failed\n");
1070 if (ObjectAttached
== TRUE
)
1072 ObpRemoveEntryDirectory(Header
);
1076 ObDereferenceObject(FoundObject
);
1078 RtlFreeUnicodeString(&RemainingPath
);
1083 RtlFreeUnicodeString(&RemainingPath
);
1085 DPRINT("Security Assignment in progress\n");
1086 SeCaptureSubjectContext(&SubjectContext
);
1088 /* Build the new security descriptor */
1089 Status
= SeAssignSecurity((FoundHeader
!= NULL
) ? FoundHeader
->SecurityDescriptor
: NULL
,
1090 (ObjectCreateInfo
!= NULL
) ? ObjectCreateInfo
->SecurityDescriptor
: NULL
,
1091 &NewSecurityDescriptor
,
1092 (Header
->ObjectType
== ObDirectoryType
),
1094 &Header
->ObjectType
->TypeInfo
.GenericMapping
,
1097 if (NT_SUCCESS(Status
))
1099 DPRINT("NewSecurityDescriptor %p\n", NewSecurityDescriptor
);
1101 if (Header
->ObjectType
->TypeInfo
.SecurityProcedure
!= NULL
)
1103 /* Call the security method */
1104 Status
= Header
->ObjectType
->TypeInfo
.SecurityProcedure(HEADER_TO_BODY(Header
),
1105 AssignSecurityDescriptor
,
1107 NewSecurityDescriptor
,
1112 /* Assign the security descriptor to the object header */
1113 Status
= ObpAddSecurityDescriptor(NewSecurityDescriptor
,
1114 &Header
->SecurityDescriptor
);
1115 DPRINT("Object security descriptor %p\n", Header
->SecurityDescriptor
);
1118 /* Release the new security descriptor */
1119 SeDeassignSecurity(&NewSecurityDescriptor
);
1122 DPRINT("Security Complete\n");
1123 SeReleaseSubjectContext(&SubjectContext
);
1125 /* We can delete the Create Info now */
1126 Header
->ObjectCreateInfo
= NULL
;
1127 ObpReleaseCapturedAttributes(ObjectCreateInfo
);
1128 ExFreePool(ObjectCreateInfo
);
1130 /* Create the Handle */
1131 /* HACKHACK: Because of ROS's incorrect startup, this can be called
1132 * without a valid Process until I finalize the startup patch,
1133 * so don't create a handle if this is the case. We also don't create
1134 * a handle if Handle is NULL when the Registry Code calls it, because
1135 * the registry code totally bastardizes the Ob and needs to be fixed
1137 DPRINT("Creating handle\n");
1140 Status
= ObpCreateHandle(PsGetCurrentProcess(),
1141 HEADER_TO_BODY(Header
),
1145 DPRINT("handle Created: %d. refcount. handlecount %d %d\n",
1146 *Handle
, Header
->RefCount
, Header
->HandleCount
);
1149 DPRINT("Status %x\n", Status
);
1155 ObpGetHandleCountByHandleTable(PHANDLE_TABLE HandleTable
)
1157 return HandleTable
->HandleCount
;
1161 * FUNCTION: Searches the handle table of a specified process whether it contains a
1162 * valid handle to the Object we're looking for. If not, it'll create one.
1165 * The parameters of this function is basically a mixture of some of the parameters
1166 * of ObReferenceObjectByHandle() and ObReferenceObjectByPointer(). A little thinking
1167 * about what this function does (by it's name) makes clear what parameters it requires.
1168 * For example the AccessMode parameter of ObReferenceObjectByHandle/Pointer() is not
1169 * required at all as it only has influence on the object security. This function doesn't
1170 * want to get access to an object, it just looks for a valid handle and if it can't find
1171 * one, it'll just create one. It wouldn't make sense to check for security again as the
1172 * caller already has a pointer to the object.
1174 * A test on an XP machine shows that this prototype appears to be correct.
1177 * Process = This parameter simply describes in which handle table we're looking
1178 * for a handle to the object.
1179 * Object = The object pointer that we're looking for
1180 * ObjectType = Just a sanity check as ObReferenceObjectByHandle() and
1181 * ObReferenceObjectByPointer() provides.
1182 * HandleInformation = This one has to be the opposite meaning of the usage in
1183 * ObReferenceObjectByHandle(). If we actually found a valid
1184 * handle in the table, we need to check against the information
1185 * provided so we make sure this handle has all access rights
1186 * (and attributes?!) we need. If they don't match, we can't
1187 * use this handle and keep looking because the caller is likely
1188 * to depend on these access rights.
1189 * HandleReturn = The last parameter is the same as in ObCreateHandle(). If we could
1190 * find a suitable handle in the handle table, return this handle, if
1191 * not, we'll just create one using ObCreateHandle() with all access
1192 * rights the caller needs.
1199 ObFindHandleForObject(IN PEPROCESS Process
,
1201 IN POBJECT_TYPE ObjectType
,
1202 IN POBJECT_HANDLE_INFORMATION HandleInformation
,
1203 OUT PHANDLE HandleReturn
)
1206 return STATUS_UNSUCCESSFUL
;
1210 ObpGetNextHandleByProcessCount(PSYSTEM_HANDLE_TABLE_ENTRY_INFO pshi
,
1217 // pshi->HandleValue;
1220 This will never work with ROS! M$, I guess uses 0 -> 65535.
1221 Ros uses 0 -> 4294967295!
1224 P
= (ULONG
) Process
->UniqueProcessId
;
1225 pshi
->UniqueProcessId
= (USHORT
) P
;
1227 // KeAcquireSpinLock( &Process->HandleTable.ListLock, &oldIrql );
1229 // pshi->GrantedAccess;
1231 // pshi->ObjectTypeIndex;
1232 // pshi->HandleAttributes;
1234 // KeReleaseSpinLock( &Process->HandleTable.ListLock, oldIrql );