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 POBJECT_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(ObjectBody
, 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(ObjectHeader
);
81 /* remove the keep-alive reference */
82 ObDereferenceObject(ObjectBody
);
89 ObpQueryHandleAttributes(HANDLE Handle
,
90 POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo
)
92 PHANDLE_TABLE HandleTable
;
93 PHANDLE_TABLE_ENTRY HandleTableEntry
;
97 DPRINT("ObpQueryHandleAttributes(Handle %x)\n", Handle
);
99 if(ObIsKernelHandle(Handle
, ExGetPreviousMode()))
101 HandleTable
= ObpKernelHandleTable
;
102 Handle
= ObKernelHandleToHandle(Handle
);
106 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
109 KeEnterCriticalRegion();
111 HandleTableEntry
= ExMapHandleToPointer(HandleTable
,
113 if (HandleTableEntry
== NULL
)
115 KeLeaveCriticalRegion();
116 return STATUS_INVALID_HANDLE
;
119 HandleInfo
->Inherit
= (HandleTableEntry
->u1
.ObAttributes
& EX_HANDLE_ENTRY_INHERITABLE
) != 0;
120 HandleInfo
->ProtectFromClose
= (HandleTableEntry
->u1
.ObAttributes
& EX_HANDLE_ENTRY_PROTECTFROMCLOSE
) != 0;
122 ExUnlockHandleTableEntry(HandleTable
,
125 KeLeaveCriticalRegion();
127 return STATUS_SUCCESS
;
133 ObpSetHandleAttributes(HANDLE Handle
,
134 POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo
)
136 PHANDLE_TABLE HandleTable
;
137 PHANDLE_TABLE_ENTRY HandleTableEntry
;
141 DPRINT("ObpSetHandleAttributes(Handle %x)\n", Handle
);
143 if(ObIsKernelHandle(Handle
, ExGetPreviousMode()))
145 HandleTable
= ObpKernelHandleTable
;
146 Handle
= ObKernelHandleToHandle(Handle
);
150 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
153 KeEnterCriticalRegion();
155 HandleTableEntry
= ExMapHandleToPointer(HandleTable
,
157 if (HandleTableEntry
== NULL
)
159 KeLeaveCriticalRegion();
160 return STATUS_INVALID_HANDLE
;
163 if (HandleInfo
->Inherit
)
164 HandleTableEntry
->u1
.ObAttributes
|= EX_HANDLE_ENTRY_INHERITABLE
;
166 HandleTableEntry
->u1
.ObAttributes
&= ~EX_HANDLE_ENTRY_INHERITABLE
;
168 if (HandleInfo
->ProtectFromClose
)
169 HandleTableEntry
->u1
.ObAttributes
|= EX_HANDLE_ENTRY_PROTECTFROMCLOSE
;
171 HandleTableEntry
->u1
.ObAttributes
&= ~EX_HANDLE_ENTRY_PROTECTFROMCLOSE
;
173 /* FIXME: Do we need to set anything in the object header??? */
175 ExUnlockHandleTableEntry(HandleTable
,
178 KeLeaveCriticalRegion();
180 return STATUS_SUCCESS
;
185 ObpDeleteHandle(PHANDLE_TABLE HandleTable
,
188 PHANDLE_TABLE_ENTRY HandleEntry
;
190 POBJECT_HEADER ObjectHeader
;
194 DPRINT("ObpDeleteHandle(Handle %x)\n",Handle
);
196 KeEnterCriticalRegion();
198 HandleEntry
= ExMapHandleToPointer(HandleTable
,
200 if(HandleEntry
!= NULL
)
202 if(HandleEntry
->u1
.ObAttributes
& EX_HANDLE_ENTRY_PROTECTFROMCLOSE
)
204 ExUnlockHandleTableEntry(HandleTable
,
207 KeLeaveCriticalRegion();
209 return STATUS_HANDLE_NOT_CLOSABLE
;
212 ObjectHeader
= EX_HTE_TO_HDR(HandleEntry
);
213 Body
= &ObjectHeader
->Body
;
215 ObpDecrementHandleCount(Body
);
217 /* destroy and unlock the handle entry */
218 ExDestroyHandleByEntry(HandleTable
,
222 KeLeaveCriticalRegion();
224 return STATUS_SUCCESS
;
226 KeLeaveCriticalRegion();
227 return STATUS_INVALID_HANDLE
;
233 ObDuplicateObject(PEPROCESS SourceProcess
,
234 PEPROCESS TargetProcess
,
236 PHANDLE TargetHandle
,
237 ACCESS_MASK DesiredAccess
,
238 BOOLEAN InheritHandle
,
241 PHANDLE_TABLE SourceHandleTable
;
242 PHANDLE_TABLE_ENTRY SourceHandleEntry
;
243 HANDLE_TABLE_ENTRY NewHandleEntry
;
245 POBJECT_HEADER ObjectHeader
;
246 ULONG NewHandleCount
;
247 HANDLE NewTargetHandle
;
251 if(ObIsKernelHandle(SourceHandle
, ExGetPreviousMode()))
253 SourceHandleTable
= ObpKernelHandleTable
;
254 SourceHandle
= ObKernelHandleToHandle(SourceHandle
);
258 SourceHandleTable
= SourceProcess
->ObjectTable
;
261 KeEnterCriticalRegion();
263 SourceHandleEntry
= ExMapHandleToPointer(SourceHandleTable
,
265 if (SourceHandleEntry
== NULL
)
267 KeLeaveCriticalRegion();
268 return STATUS_INVALID_HANDLE
;
271 ObjectHeader
= EX_HTE_TO_HDR(SourceHandleEntry
);
272 ObjectBody
= &ObjectHeader
->Body
;
274 NewHandleEntry
.u1
.Object
= SourceHandleEntry
->u1
.Object
;
276 NewHandleEntry
.u1
.ObAttributes
|= EX_HANDLE_ENTRY_INHERITABLE
;
278 NewHandleEntry
.u1
.ObAttributes
&= ~EX_HANDLE_ENTRY_INHERITABLE
;
279 NewHandleEntry
.u2
.GrantedAccess
= ((Options
& DUPLICATE_SAME_ACCESS
) ?
280 SourceHandleEntry
->u2
.GrantedAccess
:
282 if (Options
& DUPLICATE_SAME_ACCESS
)
284 NewHandleEntry
.u2
.GrantedAccess
= SourceHandleEntry
->u2
.GrantedAccess
;
288 if (DesiredAccess
& GENERIC_ANY
)
290 RtlMapGenericMask(&DesiredAccess
,
291 &ObjectHeader
->Type
->TypeInfo
.GenericMapping
);
293 NewHandleEntry
.u2
.GrantedAccess
= DesiredAccess
;
296 /* reference the object so it doesn't get deleted after releasing the lock
297 and before creating a new handle for it */
298 ObReferenceObject(ObjectBody
);
300 /* increment the handle count of the object, it should always be >= 2 because
301 we're holding a handle lock to this object! if the new handle count was
302 1 here, we're in big trouble... it would've been safe to increment and
303 check the handle count without using interlocked functions because the
304 entry is locked, which means the handle count can't change. */
305 NewHandleCount
= InterlockedIncrement(&ObjectHeader
->HandleCount
);
306 ASSERT(NewHandleCount
>= 2);
308 ExUnlockHandleTableEntry(SourceHandleTable
,
311 KeLeaveCriticalRegion();
313 /* attempt to create the new handle */
314 NewTargetHandle
= ExCreateHandle(TargetProcess
->ObjectTable
,
316 if (NewTargetHandle
!= NULL
)
318 if (Options
& DUPLICATE_CLOSE_SOURCE
)
320 ObpDeleteHandle(SourceHandleTable
,
324 ObDereferenceObject(ObjectBody
);
326 *TargetHandle
= NewTargetHandle
;
328 return STATUS_SUCCESS
;
332 /* decrement the handle count we previously incremented, but don't call the
333 closing procedure because we're not closing a handle! */
334 if(InterlockedDecrement(&ObjectHeader
->HandleCount
) == 0)
336 ObDereferenceObject(ObjectBody
);
339 ObDereferenceObject(ObjectBody
);
340 return STATUS_UNSUCCESSFUL
;
348 NtDuplicateObject (IN HANDLE SourceProcessHandle
,
349 IN HANDLE SourceHandle
,
350 IN HANDLE TargetProcessHandle
,
351 OUT PHANDLE TargetHandle OPTIONAL
,
352 IN ACCESS_MASK DesiredAccess
,
353 IN ULONG InheritHandle
,
356 * FUNCTION: Copies a handle from one process space to another
358 * SourceProcessHandle = The source process owning the handle. The
359 * source process should have opened
360 * the SourceHandle with PROCESS_DUP_HANDLE
362 * SourceHandle = The handle to the object.
363 * TargetProcessHandle = The destination process owning the handle
364 * TargetHandle (OUT) = Caller should supply storage for the
366 * DesiredAccess = The desired access to the handle.
367 * InheritHandle = Indicates wheter the new handle will be inheritable
369 * Options = Specifies special actions upon duplicating the handle.
370 * Can be one of the values DUPLICATE_CLOSE_SOURCE |
371 * DUPLICATE_SAME_ACCESS. DUPLICATE_CLOSE_SOURCE specifies
372 * that the source handle should be closed after duplicating.
373 * DUPLICATE_SAME_ACCESS specifies to ignore the
374 * DesiredAccess paramter and just grant the same access to
377 * REMARKS: This function maps to the win32 DuplicateHandle.
380 PEPROCESS SourceProcess
;
381 PEPROCESS TargetProcess
;
383 KPROCESSOR_MODE PreviousMode
;
384 NTSTATUS Status
= STATUS_SUCCESS
;
388 PreviousMode
= ExGetPreviousMode();
390 if(TargetHandle
!= NULL
&& PreviousMode
!= KernelMode
)
394 ProbeForWriteHandle(TargetHandle
);
398 Status
= _SEH_GetExceptionCode();
402 if(!NT_SUCCESS(Status
))
408 Status
= ObReferenceObjectByHandle(SourceProcessHandle
,
412 (PVOID
*)&SourceProcess
,
414 if (!NT_SUCCESS(Status
))
419 Status
= ObReferenceObjectByHandle(TargetProcessHandle
,
423 (PVOID
*)&TargetProcess
,
425 if (!NT_SUCCESS(Status
))
427 ObDereferenceObject(SourceProcess
);
431 /* Check for magic handle first */
432 if (SourceHandle
== NtCurrentThread() ||
433 SourceHandle
== NtCurrentProcess())
436 POBJECT_TYPE ObjectType
;
438 ObjectType
= (SourceHandle
== NtCurrentThread()) ? PsThreadType
: PsProcessType
;
440 Status
= ObReferenceObjectByHandle(SourceHandle
,
446 if(NT_SUCCESS(Status
))
448 if (Options
& DUPLICATE_SAME_ACCESS
)
450 /* grant all access rights */
451 DesiredAccess
= ((ObjectType
== PsThreadType
) ? THREAD_ALL_ACCESS
: PROCESS_ALL_ACCESS
);
455 if (DesiredAccess
& GENERIC_ANY
)
457 RtlMapGenericMask(&DesiredAccess
,
458 &ObjectType
->TypeInfo
.GenericMapping
);
461 Status
= ObpCreateHandle(TargetProcess
,
467 ObDereferenceObject(ObjectBody
);
469 if (Options
& DUPLICATE_CLOSE_SOURCE
)
471 ObpDeleteHandle(SourceProcess
->ObjectTable
,
478 Status
= ObDuplicateObject(SourceProcess
,
487 ObDereferenceObject(TargetProcess
);
488 ObDereferenceObject(SourceProcess
);
490 if(NT_SUCCESS(Status
) && TargetHandle
!= NULL
)
494 *TargetHandle
= hTarget
;
498 Status
= _SEH_GetExceptionCode();
507 DeleteHandleCallback(PHANDLE_TABLE HandleTable
,
512 POBJECT_HEADER ObjectHeader
;
517 ObjectHeader
= EX_OBJ_TO_HDR(Object
);
518 ObjectBody
= &ObjectHeader
->Body
;
520 ObpDecrementHandleCount(ObjectBody
);
523 static BOOLEAN STDCALL
524 DuplicateHandleCallback(PHANDLE_TABLE HandleTable
,
525 PHANDLE_TABLE_ENTRY HandleTableEntry
,
528 POBJECT_HEADER ObjectHeader
;
533 Ret
= (HandleTableEntry
->u1
.ObAttributes
& EX_HANDLE_ENTRY_INHERITABLE
) != 0;
536 ObjectHeader
= EX_HTE_TO_HDR(HandleTableEntry
);
537 if(InterlockedIncrement(&ObjectHeader
->HandleCount
) == 1)
539 ObReferenceObject(&ObjectHeader
->Body
);
548 ObCreateHandleTable(PEPROCESS Parent
,
552 * FUNCTION: Creates a handle table for a process
554 * Parent = Parent process (or NULL if this is the first process)
555 * Inherit = True if the process should inherit its parent's handles
556 * Process = Process whose handle table is to be created
561 DPRINT("ObCreateHandleTable(Parent %x, Inherit %d, Process %x)\n",
562 Parent
,Inherit
,Process
);
565 Process
->ObjectTable
= ExDupHandleTable(Process
,
566 DuplicateHandleCallback
,
568 Parent
->ObjectTable
);
572 Process
->ObjectTable
= ExCreateHandleTable(Process
);
579 ObKillProcess(PEPROCESS Process
)
583 ExDestroyHandleTable(Process
->ObjectTable
,
584 DeleteHandleCallback
,
591 ObpCreateHandle(PEPROCESS Process
,
593 ACCESS_MASK GrantedAccess
,
595 PHANDLE HandleReturn
)
597 * FUNCTION: Add a handle referencing an object
599 * obj = Object body that the handle should refer to
600 * RETURNS: The created handle
601 * NOTE: The handle is valid only in the context of the current process
604 HANDLE_TABLE_ENTRY NewEntry
;
605 POBJECT_HEADER ObjectHeader
;
610 DPRINT("ObpCreateHandle(Process %x, obj %x)\n",Process
,ObjectBody
);
615 ObjectHeader
= BODY_TO_HEADER(ObjectBody
);
617 ASSERT((ULONG_PTR
)ObjectHeader
& EX_HANDLE_ENTRY_LOCKED
);
619 if (GrantedAccess
& MAXIMUM_ALLOWED
)
621 GrantedAccess
&= ~MAXIMUM_ALLOWED
;
622 GrantedAccess
|= GENERIC_ALL
;
625 if (GrantedAccess
& GENERIC_ANY
)
627 RtlMapGenericMask(&GrantedAccess
,
628 &ObjectHeader
->Type
->TypeInfo
.GenericMapping
);
631 NewEntry
.u1
.Object
= ObjectHeader
;
633 NewEntry
.u1
.ObAttributes
|= EX_HANDLE_ENTRY_INHERITABLE
;
635 NewEntry
.u1
.ObAttributes
&= ~EX_HANDLE_ENTRY_INHERITABLE
;
636 NewEntry
.u2
.GrantedAccess
= GrantedAccess
;
638 Handle
= ExCreateHandle(Process
->ObjectTable
,
640 DPRINT("ObCreateHandle(0x%x)==0x%x [HT:0x%x]\n", ObjectHeader
, Handle
, Process
->ObjectTable
);
643 if(InterlockedIncrement(&ObjectHeader
->HandleCount
) == 1)
645 ObReferenceObjectByPointer(ObjectBody
,
651 *HandleReturn
= Handle
;
653 return STATUS_SUCCESS
;
656 return STATUS_UNSUCCESSFUL
;
664 ObQueryObjectAuditingByHandle(IN HANDLE Handle
,
665 OUT PBOOLEAN GenerateOnClose
)
667 PHANDLE_TABLE_ENTRY HandleEntry
;
672 DPRINT("ObQueryObjectAuditingByHandle(Handle %x)\n", Handle
);
674 Process
= PsGetCurrentProcess();
676 KeEnterCriticalRegion();
678 HandleEntry
= ExMapHandleToPointer(Process
->ObjectTable
,
680 if(HandleEntry
!= NULL
)
682 *GenerateOnClose
= (HandleEntry
->u1
.ObAttributes
& EX_HANDLE_ENTRY_AUDITONCLOSE
) != 0;
684 ExUnlockHandleTableEntry(Process
->ObjectTable
,
687 KeLeaveCriticalRegion();
689 return STATUS_SUCCESS
;
692 KeLeaveCriticalRegion();
694 return STATUS_INVALID_HANDLE
;
699 * FUNCTION: Increments the reference count for an object and returns a
700 * pointer to its body
702 * Handle = Handle for the object
703 * DesiredAccess = Desired access to the object
706 * Object (OUT) = Points to the object body on return
707 * HandleInformation (OUT) = Contains information about the handle
714 ObReferenceObjectByHandle(HANDLE Handle
,
715 ACCESS_MASK DesiredAccess
,
716 POBJECT_TYPE ObjectType
,
717 KPROCESSOR_MODE AccessMode
,
719 POBJECT_HANDLE_INFORMATION HandleInformation
)
721 PHANDLE_TABLE_ENTRY HandleEntry
;
722 POBJECT_HEADER ObjectHeader
;
723 PHANDLE_TABLE HandleTable
;
725 ACCESS_MASK GrantedAccess
;
730 DPRINT("ObReferenceObjectByHandle(Handle %x, DesiredAccess %x, "
731 "ObjectType %x, AccessMode %d, Object %x)\n",Handle
,DesiredAccess
,
732 ObjectType
,AccessMode
,Object
);
736 return STATUS_INVALID_HANDLE
;
739 * Handle special handle names
741 if (Handle
== NtCurrentProcess() &&
742 (ObjectType
== PsProcessType
|| ObjectType
== NULL
))
744 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
746 ObReferenceObject(CurrentProcess
);
748 if (HandleInformation
!= NULL
)
750 HandleInformation
->HandleAttributes
= 0;
751 HandleInformation
->GrantedAccess
= PROCESS_ALL_ACCESS
;
754 *Object
= CurrentProcess
;
755 DPRINT("Referencing current process %x\n", CurrentProcess
);
756 return STATUS_SUCCESS
;
758 else if (Handle
== NtCurrentProcess())
761 return(STATUS_OBJECT_TYPE_MISMATCH
);
764 if (Handle
== NtCurrentThread() &&
765 (ObjectType
== PsThreadType
|| ObjectType
== NULL
))
767 PETHREAD CurrentThread
= PsGetCurrentThread();
769 ObReferenceObject(CurrentThread
);
771 if (HandleInformation
!= NULL
)
773 HandleInformation
->HandleAttributes
= 0;
774 HandleInformation
->GrantedAccess
= THREAD_ALL_ACCESS
;
777 *Object
= CurrentThread
;
779 return STATUS_SUCCESS
;
781 else if (Handle
== NtCurrentThread())
784 return(STATUS_OBJECT_TYPE_MISMATCH
);
787 /* desire as much access rights as possible */
788 if (DesiredAccess
& MAXIMUM_ALLOWED
)
790 DesiredAccess
&= ~MAXIMUM_ALLOWED
;
791 DesiredAccess
|= GENERIC_ALL
;
794 if(ObIsKernelHandle(Handle
, AccessMode
))
796 HandleTable
= ObpKernelHandleTable
;
797 Handle
= ObKernelHandleToHandle(Handle
);
801 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
804 KeEnterCriticalRegion();
806 HandleEntry
= ExMapHandleToPointer(HandleTable
,
808 if (HandleEntry
== NULL
)
810 KeLeaveCriticalRegion();
811 DPRINT("ExMapHandleToPointer() failed for handle 0x%x\n", Handle
);
812 return(STATUS_INVALID_HANDLE
);
815 ObjectHeader
= EX_HTE_TO_HDR(HandleEntry
);
816 ObjectBody
= &ObjectHeader
->Body
;
818 DPRINT("locked1: ObjectHeader: 0x%x [HT:0x%x]\n", ObjectHeader
, HandleTable
);
820 if (ObjectType
!= NULL
&& ObjectType
!= ObjectHeader
->Type
)
822 DPRINT("ObjectType mismatch: %wZ vs %wZ (handle 0x%x)\n", &ObjectType
->Name
, ObjectHeader
->Type
? &ObjectHeader
->Type
->Name
: NULL
, Handle
);
824 ExUnlockHandleTableEntry(HandleTable
,
827 KeLeaveCriticalRegion();
829 return(STATUS_OBJECT_TYPE_MISMATCH
);
832 /* map the generic access masks if the caller asks for generic access */
833 if (DesiredAccess
& GENERIC_ANY
)
835 RtlMapGenericMask(&DesiredAccess
,
836 &BODY_TO_HEADER(ObjectBody
)->Type
->TypeInfo
.GenericMapping
);
839 GrantedAccess
= HandleEntry
->u2
.GrantedAccess
;
841 /* Unless running as KernelMode, deny access if caller desires more access
842 rights than the handle can grant */
843 if(AccessMode
!= KernelMode
&& (~GrantedAccess
& DesiredAccess
))
845 ExUnlockHandleTableEntry(HandleTable
,
848 KeLeaveCriticalRegion();
850 DPRINT1("GrantedAccess: 0x%x, ~GrantedAccess: 0x%x, DesiredAccess: 0x%x, denied: 0x%x\n", GrantedAccess
, ~GrantedAccess
, DesiredAccess
, ~GrantedAccess
& DesiredAccess
);
852 return(STATUS_ACCESS_DENIED
);
855 ObReferenceObject(ObjectBody
);
857 Attributes
= HandleEntry
->u1
.ObAttributes
& (EX_HANDLE_ENTRY_PROTECTFROMCLOSE
|
858 EX_HANDLE_ENTRY_INHERITABLE
|
859 EX_HANDLE_ENTRY_AUDITONCLOSE
);
861 ExUnlockHandleTableEntry(HandleTable
,
864 KeLeaveCriticalRegion();
866 if (HandleInformation
!= NULL
)
868 HandleInformation
->HandleAttributes
= Attributes
;
869 HandleInformation
->GrantedAccess
= GrantedAccess
;
872 *Object
= ObjectBody
;
874 return(STATUS_SUCCESS
);
878 /**********************************************************************
883 * Closes a handle reference to an object.
895 NtClose(IN HANDLE Handle
)
897 PHANDLE_TABLE HandleTable
;
902 if(ObIsKernelHandle(Handle
, ExGetPreviousMode()))
904 HandleTable
= ObpKernelHandleTable
;
905 Handle
= ObKernelHandleToHandle(Handle
);
909 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
912 Status
= ObpDeleteHandle(HandleTable
,
914 if (!NT_SUCCESS(Status
))
916 if((ExGetPreviousMode() != KernelMode
) &&
917 (PsGetCurrentProcess()->ExceptionPort
))
919 KeRaiseUserException(Status
);
924 return(STATUS_SUCCESS
);
933 ObInsertObject(IN PVOID Object
,
934 IN PACCESS_STATE PassedAccessState OPTIONAL
,
935 IN ACCESS_MASK DesiredAccess
,
936 IN ULONG AdditionalReferences
,
937 OUT PVOID
* ReferencedObject OPTIONAL
,
940 POBJECT_CREATE_INFORMATION ObjectCreateInfo
;
941 POBJECT_HEADER Header
;
942 POBJECT_HEADER_NAME_INFO ObjectNameInfo
;
943 PVOID FoundObject
= NULL
;
944 POBJECT_HEADER FoundHeader
= NULL
;
945 NTSTATUS Status
= STATUS_SUCCESS
;
946 UNICODE_STRING RemainingPath
;
947 BOOLEAN ObjectAttached
= FALSE
;
948 PSECURITY_DESCRIPTOR NewSecurityDescriptor
= NULL
;
949 SECURITY_SUBJECT_CONTEXT SubjectContext
;
953 /* Get the Header and Create Info */
954 DPRINT("ObInsertObject: %x\n", Object
);
955 Header
= BODY_TO_HEADER(Object
);
956 ObjectCreateInfo
= Header
->ObjectCreateInfo
;
957 ObjectNameInfo
= HEADER_TO_OBJECT_NAME(Header
);
959 /* First try to find the Object */
960 if (ObjectNameInfo
&& ObjectNameInfo
->Name
.Buffer
)
962 DPRINT("Object has a name. Trying to find it: %wZ.\n", &ObjectNameInfo
->Name
);
963 Status
= ObFindObject(ObjectCreateInfo
,
964 &ObjectNameInfo
->Name
,
968 DPRINT("FoundObject: %x, Path: %wZ\n", FoundObject
, &RemainingPath
);
969 if (!NT_SUCCESS(Status
))
971 DPRINT1("ObFindObject() failed! (Status 0x%x)\n", Status
);
977 DPRINT("Getting header: %x\n", FoundObject
);
978 FoundHeader
= BODY_TO_HEADER(FoundObject
);
981 if (FoundHeader
&& RemainingPath
.Buffer
== NULL
)
983 DPRINT("Object exists\n");
984 ObDereferenceObject(FoundObject
);
985 return STATUS_OBJECT_NAME_COLLISION
;
990 DPRINT("No name, empty remaining path\n");
991 RtlInitUnicodeString(&RemainingPath
, NULL
);
994 if (FoundHeader
&& FoundHeader
->Type
== ObDirectoryType
&&
995 RemainingPath
.Buffer
)
997 /* The name was changed so let's update it */
998 /* FIXME: TEMPORARY HACK This will go in ObFindObject in the next commit */
1000 PWSTR BufferPos
= RemainingPath
.Buffer
;
1003 ObpAddEntryDirectory(FoundObject
, Header
, NULL
);
1004 ObjectAttached
= TRUE
;
1006 ObjectNameInfo
= HEADER_TO_OBJECT_NAME(Header
);
1008 if (BufferPos
[0] == L
'\\')
1011 Delta
= sizeof(WCHAR
);
1013 NewName
= ExAllocatePool(NonPagedPool
, RemainingPath
.MaximumLength
- Delta
);
1014 RtlMoveMemory(NewName
, BufferPos
, RemainingPath
.MaximumLength
- Delta
);
1015 if (ObjectNameInfo
->Name
.Buffer
) ExFreePool(ObjectNameInfo
->Name
.Buffer
);
1016 ObjectNameInfo
->Name
.Buffer
= NewName
;
1017 ObjectNameInfo
->Name
.Length
= RemainingPath
.Length
- Delta
;
1018 ObjectNameInfo
->Name
.MaximumLength
= RemainingPath
.MaximumLength
- Delta
;
1019 DPRINT("Name: %S\n", ObjectNameInfo
->Name
.Buffer
);
1022 if ((Header
->Type
== IoFileObjectType
) ||
1023 (Header
->Type
== ExDesktopObjectType
) ||
1024 (Header
->Type
->TypeInfo
.OpenProcedure
!= NULL
))
1026 DPRINT("About to call Open Routine\n");
1027 if (Header
->Type
== IoFileObjectType
)
1029 /* TEMPORARY HACK. DO NOT TOUCH -- Alex */
1030 DPRINT("Calling IopCreateFile: %x\n", FoundObject
);
1031 Status
= IopCreateFile(&Header
->Body
,
1033 RemainingPath
.Buffer
,
1035 DPRINT("Called IopCreateFile: %x\n", Status
);
1038 else if (Header
->Type
== ExDesktopObjectType
)
1040 /* TEMPORARY HACK. DO NOT TOUCH -- Alex */
1041 DPRINT("Calling ExpDesktopCreate\n");
1042 Status
= ExpDesktopCreate(&Header
->Body
,
1044 RemainingPath
.Buffer
,
1047 else if (Header
->Type
->TypeInfo
.OpenProcedure
!= NULL
)
1049 DPRINT("Calling %x\n", Header
->Type
->TypeInfo
.OpenProcedure
);
1050 Status
= Header
->Type
->TypeInfo
.OpenProcedure(ObCreateHandle
,
1057 if (!NT_SUCCESS(Status
))
1059 DPRINT("Create Failed\n");
1060 if (ObjectAttached
== TRUE
)
1062 ObpRemoveEntryDirectory(Header
);
1066 ObDereferenceObject(FoundObject
);
1068 RtlFreeUnicodeString(&RemainingPath
);
1073 RtlFreeUnicodeString(&RemainingPath
);
1075 DPRINT("Security Assignment in progress\n");
1076 SeCaptureSubjectContext(&SubjectContext
);
1078 /* Build the new security descriptor */
1079 Status
= SeAssignSecurity((FoundHeader
!= NULL
) ? FoundHeader
->SecurityDescriptor
: NULL
,
1080 (ObjectCreateInfo
!= NULL
) ? ObjectCreateInfo
->SecurityDescriptor
: NULL
,
1081 &NewSecurityDescriptor
,
1082 (Header
->Type
== ObDirectoryType
),
1084 &Header
->Type
->TypeInfo
.GenericMapping
,
1087 if (NT_SUCCESS(Status
))
1089 DPRINT("NewSecurityDescriptor %p\n", NewSecurityDescriptor
);
1091 if (Header
->Type
->TypeInfo
.SecurityProcedure
!= NULL
)
1093 /* Call the security method */
1094 Status
= Header
->Type
->TypeInfo
.SecurityProcedure(&Header
->Body
,
1095 AssignSecurityDescriptor
,
1097 NewSecurityDescriptor
,
1105 /* Assign the security descriptor to the object header */
1106 Status
= ObpAddSecurityDescriptor(NewSecurityDescriptor
,
1107 &Header
->SecurityDescriptor
);
1108 DPRINT("Object security descriptor %p\n", Header
->SecurityDescriptor
);
1111 /* Release the new security descriptor */
1112 SeDeassignSecurity(&NewSecurityDescriptor
);
1115 DPRINT("Security Complete\n");
1116 SeReleaseSubjectContext(&SubjectContext
);
1118 /* Create the Handle */
1119 /* HACKHACK: Because of ROS's incorrect startup, this can be called
1120 * without a valid Process until I finalize the startup patch,
1121 * so don't create a handle if this is the case. We also don't create
1122 * a handle if Handle is NULL when the Registry Code calls it, because
1123 * the registry code totally bastardizes the Ob and needs to be fixed
1125 DPRINT("Creating handle\n");
1128 Status
= ObpCreateHandle(PsGetCurrentProcess(),
1131 ObjectCreateInfo
->Attributes
& OBJ_INHERIT
,
1133 DPRINT("handle Created: %d. refcount. handlecount %d %d\n",
1134 *Handle
, Header
->PointerCount
, Header
->HandleCount
);
1137 /* We can delete the Create Info now */
1138 Header
->ObjectCreateInfo
= NULL
;
1139 ObpReleaseCapturedAttributes(ObjectCreateInfo
);
1140 ExFreePool(ObjectCreateInfo
);
1142 DPRINT("Status %x\n", Status
);
1149 ObpGetHandleCountByHandleTable(PHANDLE_TABLE HandleTable
)
1151 return HandleTable
->HandleCount
;
1155 * FUNCTION: Searches the handle table of a specified process whether it contains a
1156 * valid handle to the Object we're looking for. If not, it'll create one.
1159 * The parameters of this function is basically a mixture of some of the parameters
1160 * of ObReferenceObjectByHandle() and ObReferenceObjectByPointer(). A little thinking
1161 * about what this function does (by it's name) makes clear what parameters it requires.
1162 * For example the AccessMode parameter of ObReferenceObjectByHandle/Pointer() is not
1163 * required at all as it only has influence on the object security. This function doesn't
1164 * want to get access to an object, it just looks for a valid handle and if it can't find
1165 * one, it'll just create one. It wouldn't make sense to check for security again as the
1166 * caller already has a pointer to the object.
1168 * A test on an XP machine shows that this prototype appears to be correct.
1171 * Process = This parameter simply describes in which handle table we're looking
1172 * for a handle to the object.
1173 * Object = The object pointer that we're looking for
1174 * ObjectType = Just a sanity check as ObReferenceObjectByHandle() and
1175 * ObReferenceObjectByPointer() provides.
1176 * HandleInformation = This one has to be the opposite meaning of the usage in
1177 * ObReferenceObjectByHandle(). If we actually found a valid
1178 * handle in the table, we need to check against the information
1179 * provided so we make sure this handle has all access rights
1180 * (and attributes?!) we need. If they don't match, we can't
1181 * use this handle and keep looking because the caller is likely
1182 * to depend on these access rights.
1183 * HandleReturn = The last parameter is the same as in ObCreateHandle(). If we could
1184 * find a suitable handle in the handle table, return this handle, if
1185 * not, we'll just create one using ObCreateHandle() with all access
1186 * rights the caller needs.
1193 ObFindHandleForObject(IN PEPROCESS Process
,
1195 IN POBJECT_TYPE ObjectType
,
1196 IN POBJECT_HANDLE_INFORMATION HandleInformation
,
1197 OUT PHANDLE HandleReturn
)
1199 DPRINT("ObFindHandleForObject is unimplemented!\n");
1200 return STATUS_UNSUCCESSFUL
;
1204 ObpGetNextHandleByProcessCount(PSYSTEM_HANDLE_TABLE_ENTRY_INFO pshi
,
1211 // pshi->HandleValue;
1214 This will never work with ROS! M$, I guess uses 0 -> 65535.
1215 Ros uses 0 -> 4294967295!
1218 P
= (ULONG
) Process
->UniqueProcessId
;
1219 pshi
->UniqueProcessId
= (USHORT
) P
;
1221 // KeAcquireSpinLock( &Process->HandleTable.ListLock, &oldIrql );
1223 // pshi->GrantedAccess;
1226 // pshi->HandleAttributes;
1228 // KeReleaseSpinLock( &Process->HandleTable.ListLock, oldIrql );