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
);
88 ObpQueryHandleAttributes(HANDLE Handle
,
89 POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo
)
91 PHANDLE_TABLE HandleTable
;
92 PHANDLE_TABLE_ENTRY HandleTableEntry
;
96 DPRINT("ObpQueryHandleAttributes(Handle %x)\n", Handle
);
98 if(ObIsKernelHandle(Handle
, ExGetPreviousMode()))
100 HandleTable
= ObpKernelHandleTable
;
101 Handle
= ObKernelHandleToHandle(Handle
);
105 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
108 KeEnterCriticalRegion();
110 HandleTableEntry
= ExMapHandleToPointer(HandleTable
,
112 if (HandleTableEntry
== NULL
)
114 KeLeaveCriticalRegion();
115 return STATUS_INVALID_HANDLE
;
118 HandleInfo
->Inherit
= (HandleTableEntry
->u1
.ObAttributes
& EX_HANDLE_ENTRY_INHERITABLE
) != 0;
119 HandleInfo
->ProtectFromClose
= (HandleTableEntry
->u1
.ObAttributes
& EX_HANDLE_ENTRY_PROTECTFROMCLOSE
) != 0;
121 ExUnlockHandleTableEntry(HandleTable
,
124 KeLeaveCriticalRegion();
126 return STATUS_SUCCESS
;
131 ObpSetHandleAttributes(HANDLE Handle
,
132 POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo
)
134 PHANDLE_TABLE HandleTable
;
135 PHANDLE_TABLE_ENTRY HandleTableEntry
;
139 DPRINT("ObpSetHandleAttributes(Handle %x)\n", Handle
);
141 if(ObIsKernelHandle(Handle
, ExGetPreviousMode()))
143 HandleTable
= ObpKernelHandleTable
;
144 Handle
= ObKernelHandleToHandle(Handle
);
148 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
151 KeEnterCriticalRegion();
153 HandleTableEntry
= ExMapHandleToPointer(HandleTable
,
155 if (HandleTableEntry
== NULL
)
157 KeLeaveCriticalRegion();
158 return STATUS_INVALID_HANDLE
;
161 if (HandleInfo
->Inherit
)
162 HandleTableEntry
->u1
.ObAttributes
|= EX_HANDLE_ENTRY_INHERITABLE
;
164 HandleTableEntry
->u1
.ObAttributes
&= ~EX_HANDLE_ENTRY_INHERITABLE
;
166 if (HandleInfo
->ProtectFromClose
)
167 HandleTableEntry
->u1
.ObAttributes
|= EX_HANDLE_ENTRY_PROTECTFROMCLOSE
;
169 HandleTableEntry
->u1
.ObAttributes
&= ~EX_HANDLE_ENTRY_PROTECTFROMCLOSE
;
171 /* FIXME: Do we need to set anything in the object header??? */
173 ExUnlockHandleTableEntry(HandleTable
,
176 KeLeaveCriticalRegion();
178 return STATUS_SUCCESS
;
183 ObpDeleteHandle(PHANDLE_TABLE HandleTable
,
186 PHANDLE_TABLE_ENTRY HandleEntry
;
188 POBJECT_HEADER ObjectHeader
;
192 DPRINT("ObpDeleteHandle(Handle %x)\n",Handle
);
194 KeEnterCriticalRegion();
196 HandleEntry
= ExMapHandleToPointer(HandleTable
,
198 if(HandleEntry
!= NULL
)
200 if(HandleEntry
->u1
.ObAttributes
& EX_HANDLE_ENTRY_PROTECTFROMCLOSE
)
202 ExUnlockHandleTableEntry(HandleTable
,
205 KeLeaveCriticalRegion();
207 return STATUS_HANDLE_NOT_CLOSABLE
;
210 ObjectHeader
= EX_HTE_TO_HDR(HandleEntry
);
211 Body
= &ObjectHeader
->Body
;
213 ObpDecrementHandleCount(Body
);
215 /* destroy and unlock the handle entry */
216 ExDestroyHandleByEntry(HandleTable
,
220 KeLeaveCriticalRegion();
222 return STATUS_SUCCESS
;
224 KeLeaveCriticalRegion();
225 return STATUS_INVALID_HANDLE
;
230 ObDuplicateObject(PEPROCESS SourceProcess
,
231 PEPROCESS TargetProcess
,
233 PHANDLE TargetHandle
,
234 ACCESS_MASK DesiredAccess
,
235 BOOLEAN InheritHandle
,
238 PHANDLE_TABLE SourceHandleTable
;
239 PHANDLE_TABLE_ENTRY SourceHandleEntry
;
240 HANDLE_TABLE_ENTRY NewHandleEntry
;
242 POBJECT_HEADER ObjectHeader
;
243 ULONG NewHandleCount
;
244 HANDLE NewTargetHandle
;
248 if(ObIsKernelHandle(SourceHandle
, ExGetPreviousMode()))
250 SourceHandleTable
= ObpKernelHandleTable
;
251 SourceHandle
= ObKernelHandleToHandle(SourceHandle
);
255 SourceHandleTable
= SourceProcess
->ObjectTable
;
258 KeEnterCriticalRegion();
260 SourceHandleEntry
= ExMapHandleToPointer(SourceHandleTable
,
262 if (SourceHandleEntry
== NULL
)
264 KeLeaveCriticalRegion();
265 return STATUS_INVALID_HANDLE
;
268 ObjectHeader
= EX_HTE_TO_HDR(SourceHandleEntry
);
269 ObjectBody
= &ObjectHeader
->Body
;
271 NewHandleEntry
.u1
.Object
= SourceHandleEntry
->u1
.Object
;
273 NewHandleEntry
.u1
.ObAttributes
|= EX_HANDLE_ENTRY_INHERITABLE
;
275 NewHandleEntry
.u1
.ObAttributes
&= ~EX_HANDLE_ENTRY_INHERITABLE
;
276 NewHandleEntry
.u2
.GrantedAccess
= ((Options
& DUPLICATE_SAME_ACCESS
) ?
277 SourceHandleEntry
->u2
.GrantedAccess
:
279 if (Options
& DUPLICATE_SAME_ACCESS
)
281 NewHandleEntry
.u2
.GrantedAccess
= SourceHandleEntry
->u2
.GrantedAccess
;
285 if (DesiredAccess
& GENERIC_ANY
)
287 RtlMapGenericMask(&DesiredAccess
,
288 &ObjectHeader
->Type
->TypeInfo
.GenericMapping
);
290 NewHandleEntry
.u2
.GrantedAccess
= DesiredAccess
;
293 /* reference the object so it doesn't get deleted after releasing the lock
294 and before creating a new handle for it */
295 ObReferenceObject(ObjectBody
);
297 /* increment the handle count of the object, it should always be >= 2 because
298 we're holding a handle lock to this object! if the new handle count was
299 1 here, we're in big trouble... it would've been safe to increment and
300 check the handle count without using interlocked functions because the
301 entry is locked, which means the handle count can't change. */
302 NewHandleCount
= InterlockedIncrement(&ObjectHeader
->HandleCount
);
303 ASSERT(NewHandleCount
>= 2);
305 ExUnlockHandleTableEntry(SourceHandleTable
,
308 KeLeaveCriticalRegion();
310 /* attempt to create the new handle */
311 NewTargetHandle
= ExCreateHandle(TargetProcess
->ObjectTable
,
313 if (NewTargetHandle
!= NULL
)
315 if (Options
& DUPLICATE_CLOSE_SOURCE
)
317 ObpDeleteHandle(SourceHandleTable
,
321 ObDereferenceObject(ObjectBody
);
323 *TargetHandle
= NewTargetHandle
;
325 return STATUS_SUCCESS
;
329 /* decrement the handle count we previously incremented, but don't call the
330 closing procedure because we're not closing a handle! */
331 if(InterlockedDecrement(&ObjectHeader
->HandleCount
) == 0)
333 ObDereferenceObject(ObjectBody
);
336 ObDereferenceObject(ObjectBody
);
337 return STATUS_UNSUCCESSFUL
;
345 NtDuplicateObject (IN HANDLE SourceProcessHandle
,
346 IN HANDLE SourceHandle
,
347 IN HANDLE TargetProcessHandle
,
348 OUT PHANDLE TargetHandle OPTIONAL
,
349 IN ACCESS_MASK DesiredAccess
,
350 IN ULONG InheritHandle
,
353 * FUNCTION: Copies a handle from one process space to another
355 * SourceProcessHandle = The source process owning the handle. The
356 * source process should have opened
357 * the SourceHandle with PROCESS_DUP_HANDLE
359 * SourceHandle = The handle to the object.
360 * TargetProcessHandle = The destination process owning the handle
361 * TargetHandle (OUT) = Caller should supply storage for the
363 * DesiredAccess = The desired access to the handle.
364 * InheritHandle = Indicates wheter the new handle will be inheritable
366 * Options = Specifies special actions upon duplicating the handle.
367 * Can be one of the values DUPLICATE_CLOSE_SOURCE |
368 * DUPLICATE_SAME_ACCESS. DUPLICATE_CLOSE_SOURCE specifies
369 * that the source handle should be closed after duplicating.
370 * DUPLICATE_SAME_ACCESS specifies to ignore the
371 * DesiredAccess paramter and just grant the same access to
374 * REMARKS: This function maps to the win32 DuplicateHandle.
377 PEPROCESS SourceProcess
;
378 PEPROCESS TargetProcess
;
380 KPROCESSOR_MODE PreviousMode
;
381 NTSTATUS Status
= STATUS_SUCCESS
;
385 PreviousMode
= ExGetPreviousMode();
387 if(TargetHandle
!= NULL
&& PreviousMode
!= KernelMode
)
391 ProbeForWrite(TargetHandle
,
397 Status
= _SEH_GetExceptionCode();
401 if(!NT_SUCCESS(Status
))
407 Status
= ObReferenceObjectByHandle(SourceProcessHandle
,
411 (PVOID
*)&SourceProcess
,
413 if (!NT_SUCCESS(Status
))
418 Status
= ObReferenceObjectByHandle(TargetProcessHandle
,
422 (PVOID
*)&TargetProcess
,
424 if (!NT_SUCCESS(Status
))
426 ObDereferenceObject(SourceProcess
);
430 /* Check for magic handle first */
431 if (SourceHandle
== NtCurrentThread() ||
432 SourceHandle
== NtCurrentProcess())
435 POBJECT_TYPE ObjectType
;
437 ObjectType
= (SourceHandle
== NtCurrentThread()) ? PsThreadType
: PsProcessType
;
439 Status
= ObReferenceObjectByHandle(SourceHandle
,
445 if(NT_SUCCESS(Status
))
447 if (Options
& DUPLICATE_SAME_ACCESS
)
449 /* grant all access rights */
450 DesiredAccess
= ((ObjectType
== PsThreadType
) ? THREAD_ALL_ACCESS
: PROCESS_ALL_ACCESS
);
454 if (DesiredAccess
& GENERIC_ANY
)
456 RtlMapGenericMask(&DesiredAccess
,
457 &ObjectType
->TypeInfo
.GenericMapping
);
460 Status
= ObpCreateHandle(TargetProcess
,
466 ObDereferenceObject(ObjectBody
);
468 if (Options
& DUPLICATE_CLOSE_SOURCE
)
470 ObpDeleteHandle(SourceProcess
->ObjectTable
,
477 Status
= ObDuplicateObject(SourceProcess
,
486 ObDereferenceObject(TargetProcess
);
487 ObDereferenceObject(SourceProcess
);
489 if(NT_SUCCESS(Status
) && TargetHandle
!= NULL
)
493 *TargetHandle
= hTarget
;
497 Status
= _SEH_GetExceptionCode();
506 DeleteHandleCallback(PHANDLE_TABLE HandleTable
,
511 POBJECT_HEADER ObjectHeader
;
516 ObjectHeader
= EX_OBJ_TO_HDR(Object
);
517 ObjectBody
= &ObjectHeader
->Body
;
519 ObpDecrementHandleCount(ObjectBody
);
522 static BOOLEAN STDCALL
523 DuplicateHandleCallback(PHANDLE_TABLE HandleTable
,
524 PHANDLE_TABLE_ENTRY HandleTableEntry
,
527 POBJECT_HEADER ObjectHeader
;
532 Ret
= (HandleTableEntry
->u1
.ObAttributes
& EX_HANDLE_ENTRY_INHERITABLE
) != 0;
535 ObjectHeader
= EX_HTE_TO_HDR(HandleTableEntry
);
536 if(InterlockedIncrement(&ObjectHeader
->HandleCount
) == 1)
538 ObReferenceObject(&ObjectHeader
->Body
);
545 VOID
ObCreateHandleTable(PEPROCESS Parent
,
549 * FUNCTION: Creates a handle table for a process
551 * Parent = Parent process (or NULL if this is the first process)
552 * Inherit = True if the process should inherit its parent's handles
553 * Process = Process whose handle table is to be created
558 DPRINT("ObCreateHandleTable(Parent %x, Inherit %d, Process %x)\n",
559 Parent
,Inherit
,Process
);
562 Process
->ObjectTable
= ExDupHandleTable(Process
,
563 DuplicateHandleCallback
,
565 Parent
->ObjectTable
);
569 Process
->ObjectTable
= ExCreateHandleTable(Process
);
576 ObKillProcess(PEPROCESS Process
)
580 ExDestroyHandleTable(Process
->ObjectTable
,
581 DeleteHandleCallback
,
587 ObpCreateHandle(PEPROCESS Process
,
589 ACCESS_MASK GrantedAccess
,
591 PHANDLE HandleReturn
)
593 * FUNCTION: Add a handle referencing an object
595 * obj = Object body that the handle should refer to
596 * RETURNS: The created handle
597 * NOTE: The handle is valid only in the context of the current process
600 HANDLE_TABLE_ENTRY NewEntry
;
601 POBJECT_HEADER ObjectHeader
;
606 DPRINT("ObpCreateHandle(Process %x, obj %x)\n",Process
,ObjectBody
);
611 ObjectHeader
= BODY_TO_HEADER(ObjectBody
);
613 ASSERT((ULONG_PTR
)ObjectHeader
& EX_HANDLE_ENTRY_LOCKED
);
615 if (GrantedAccess
& MAXIMUM_ALLOWED
)
617 GrantedAccess
&= ~MAXIMUM_ALLOWED
;
618 GrantedAccess
|= GENERIC_ALL
;
621 if (GrantedAccess
& GENERIC_ANY
)
623 RtlMapGenericMask(&GrantedAccess
,
624 &ObjectHeader
->Type
->TypeInfo
.GenericMapping
);
627 NewEntry
.u1
.Object
= ObjectHeader
;
629 NewEntry
.u1
.ObAttributes
|= EX_HANDLE_ENTRY_INHERITABLE
;
631 NewEntry
.u1
.ObAttributes
&= ~EX_HANDLE_ENTRY_INHERITABLE
;
632 NewEntry
.u2
.GrantedAccess
= GrantedAccess
;
634 Handle
= ExCreateHandle(Process
->ObjectTable
,
636 DPRINT("ObCreateHandle(0x%x)==0x%x [HT:0x%x]\n", ObjectHeader
, Handle
, Process
->ObjectTable
);
639 if(InterlockedIncrement(&ObjectHeader
->HandleCount
) == 1)
641 ObReferenceObjectByPointer(ObjectBody
,
647 *HandleReturn
= Handle
;
649 return STATUS_SUCCESS
;
652 return STATUS_UNSUCCESSFUL
;
660 ObQueryObjectAuditingByHandle(IN HANDLE Handle
,
661 OUT PBOOLEAN GenerateOnClose
)
663 PHANDLE_TABLE_ENTRY HandleEntry
;
668 DPRINT("ObQueryObjectAuditingByHandle(Handle %x)\n", Handle
);
670 Process
= PsGetCurrentProcess();
672 KeEnterCriticalRegion();
674 HandleEntry
= ExMapHandleToPointer(Process
->ObjectTable
,
676 if(HandleEntry
!= NULL
)
678 *GenerateOnClose
= (HandleEntry
->u1
.ObAttributes
& EX_HANDLE_ENTRY_AUDITONCLOSE
) != 0;
680 ExUnlockHandleTableEntry(Process
->ObjectTable
,
683 KeLeaveCriticalRegion();
685 return STATUS_SUCCESS
;
688 KeLeaveCriticalRegion();
690 return STATUS_INVALID_HANDLE
;
695 * FUNCTION: Increments the reference count for an object and returns a
696 * pointer to its body
698 * Handle = Handle for the object
699 * DesiredAccess = Desired access to the object
702 * Object (OUT) = Points to the object body on return
703 * HandleInformation (OUT) = Contains information about the handle
710 ObReferenceObjectByHandle(HANDLE Handle
,
711 ACCESS_MASK DesiredAccess
,
712 POBJECT_TYPE ObjectType
,
713 KPROCESSOR_MODE AccessMode
,
715 POBJECT_HANDLE_INFORMATION HandleInformation
)
717 PHANDLE_TABLE_ENTRY HandleEntry
;
718 POBJECT_HEADER ObjectHeader
;
719 PHANDLE_TABLE HandleTable
;
721 ACCESS_MASK GrantedAccess
;
726 DPRINT("ObReferenceObjectByHandle(Handle %x, DesiredAccess %x, "
727 "ObjectType %x, AccessMode %d, Object %x)\n",Handle
,DesiredAccess
,
728 ObjectType
,AccessMode
,Object
);
732 return STATUS_INVALID_HANDLE
;
735 * Handle special handle names
737 if (Handle
== NtCurrentProcess() &&
738 (ObjectType
== PsProcessType
|| ObjectType
== NULL
))
740 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
742 ObReferenceObject(CurrentProcess
);
744 if (HandleInformation
!= NULL
)
746 HandleInformation
->HandleAttributes
= 0;
747 HandleInformation
->GrantedAccess
= PROCESS_ALL_ACCESS
;
750 *Object
= CurrentProcess
;
751 DPRINT("Referencing current process %x\n", CurrentProcess
);
752 return STATUS_SUCCESS
;
754 else if (Handle
== NtCurrentProcess())
757 return(STATUS_OBJECT_TYPE_MISMATCH
);
760 if (Handle
== NtCurrentThread() &&
761 (ObjectType
== PsThreadType
|| ObjectType
== NULL
))
763 PETHREAD CurrentThread
= PsGetCurrentThread();
765 ObReferenceObject(CurrentThread
);
767 if (HandleInformation
!= NULL
)
769 HandleInformation
->HandleAttributes
= 0;
770 HandleInformation
->GrantedAccess
= THREAD_ALL_ACCESS
;
773 *Object
= CurrentThread
;
775 return STATUS_SUCCESS
;
777 else if (Handle
== NtCurrentThread())
780 return(STATUS_OBJECT_TYPE_MISMATCH
);
783 /* desire as much access rights as possible */
784 if (DesiredAccess
& MAXIMUM_ALLOWED
)
786 DesiredAccess
&= ~MAXIMUM_ALLOWED
;
787 DesiredAccess
|= GENERIC_ALL
;
790 if(ObIsKernelHandle(Handle
, AccessMode
))
792 HandleTable
= ObpKernelHandleTable
;
793 Handle
= ObKernelHandleToHandle(Handle
);
797 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
800 KeEnterCriticalRegion();
802 HandleEntry
= ExMapHandleToPointer(HandleTable
,
804 if (HandleEntry
== NULL
)
806 KeLeaveCriticalRegion();
807 DPRINT("ExMapHandleToPointer() failed for handle 0x%x\n", Handle
);
808 return(STATUS_INVALID_HANDLE
);
811 ObjectHeader
= EX_HTE_TO_HDR(HandleEntry
);
812 ObjectBody
= &ObjectHeader
->Body
;
814 DPRINT("locked1: ObjectHeader: 0x%x [HT:0x%x]\n", ObjectHeader
, HandleTable
);
816 if (ObjectType
!= NULL
&& ObjectType
!= ObjectHeader
->Type
)
818 DPRINT("ObjectType mismatch: %wZ vs %wZ (handle 0x%x)\n", &ObjectType
->Name
, ObjectHeader
->Type
? &ObjectHeader
->Type
->Name
: NULL
, Handle
);
820 ExUnlockHandleTableEntry(HandleTable
,
823 KeLeaveCriticalRegion();
825 return(STATUS_OBJECT_TYPE_MISMATCH
);
828 /* map the generic access masks if the caller asks for generic access */
829 if (DesiredAccess
& GENERIC_ANY
)
831 RtlMapGenericMask(&DesiredAccess
,
832 &BODY_TO_HEADER(ObjectBody
)->Type
->TypeInfo
.GenericMapping
);
835 GrantedAccess
= HandleEntry
->u2
.GrantedAccess
;
837 /* Unless running as KernelMode, deny access if caller desires more access
838 rights than the handle can grant */
839 if(AccessMode
!= KernelMode
&& (~GrantedAccess
& DesiredAccess
))
841 ExUnlockHandleTableEntry(HandleTable
,
844 KeLeaveCriticalRegion();
846 DPRINT1("GrantedAccess: 0x%x, ~GrantedAccess: 0x%x, DesiredAccess: 0x%x, denied: 0x%x\n", GrantedAccess
, ~GrantedAccess
, DesiredAccess
, ~GrantedAccess
& DesiredAccess
);
848 return(STATUS_ACCESS_DENIED
);
851 ObReferenceObject(ObjectBody
);
853 Attributes
= HandleEntry
->u1
.ObAttributes
& (EX_HANDLE_ENTRY_PROTECTFROMCLOSE
|
854 EX_HANDLE_ENTRY_INHERITABLE
|
855 EX_HANDLE_ENTRY_AUDITONCLOSE
);
857 ExUnlockHandleTableEntry(HandleTable
,
860 KeLeaveCriticalRegion();
862 if (HandleInformation
!= NULL
)
864 HandleInformation
->HandleAttributes
= Attributes
;
865 HandleInformation
->GrantedAccess
= GrantedAccess
;
868 *Object
= ObjectBody
;
870 return(STATUS_SUCCESS
);
874 /**********************************************************************
879 * Closes a handle reference to an object.
891 NtClose(IN HANDLE Handle
)
893 PHANDLE_TABLE HandleTable
;
898 if(ObIsKernelHandle(Handle
, ExGetPreviousMode()))
900 HandleTable
= ObpKernelHandleTable
;
901 Handle
= ObKernelHandleToHandle(Handle
);
905 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
908 Status
= ObpDeleteHandle(HandleTable
,
910 if (!NT_SUCCESS(Status
))
912 if((ExGetPreviousMode() != KernelMode
) &&
913 (PsGetCurrentProcess()->ExceptionPort
))
915 KeRaiseUserException(Status
);
920 return(STATUS_SUCCESS
);
929 ObInsertObject(IN PVOID Object
,
930 IN PACCESS_STATE PassedAccessState OPTIONAL
,
931 IN ACCESS_MASK DesiredAccess
,
932 IN ULONG AdditionalReferences
,
933 OUT PVOID
* ReferencedObject OPTIONAL
,
936 POBJECT_CREATE_INFORMATION ObjectCreateInfo
;
937 POBJECT_HEADER Header
;
938 POBJECT_HEADER_NAME_INFO ObjectNameInfo
;
939 PVOID FoundObject
= NULL
;
940 POBJECT_HEADER FoundHeader
= NULL
;
941 NTSTATUS Status
= STATUS_SUCCESS
;
942 UNICODE_STRING RemainingPath
;
943 BOOLEAN ObjectAttached
= FALSE
;
944 PSECURITY_DESCRIPTOR NewSecurityDescriptor
= NULL
;
945 SECURITY_SUBJECT_CONTEXT SubjectContext
;
949 /* Get the Header and Create Info */
950 DPRINT("ObInsertObject: %x\n", Object
);
951 Header
= BODY_TO_HEADER(Object
);
952 ObjectCreateInfo
= Header
->ObjectCreateInfo
;
953 ObjectNameInfo
= HEADER_TO_OBJECT_NAME(Header
);
955 /* First try to find the Object */
956 if (ObjectNameInfo
&& ObjectNameInfo
->Name
.Buffer
)
958 DPRINT("Object has a name. Trying to find it: %wZ.\n", &ObjectNameInfo
->Name
);
959 Status
= ObFindObject(ObjectCreateInfo
,
960 &ObjectNameInfo
->Name
,
964 DPRINT("FoundObject: %x, Path: %wZ\n", FoundObject
, &RemainingPath
);
965 if (!NT_SUCCESS(Status
))
967 DPRINT1("ObFindObject() failed! (Status 0x%x)\n", Status
);
973 DPRINT("Getting header: %x\n", FoundObject
);
974 FoundHeader
= BODY_TO_HEADER(FoundObject
);
977 if (FoundHeader
&& RemainingPath
.Buffer
== NULL
)
979 DPRINT("Object exists\n");
980 ObDereferenceObject(FoundObject
);
981 return STATUS_OBJECT_NAME_COLLISION
;
986 DPRINT("No name, empty remaining path\n");
987 RtlInitUnicodeString(&RemainingPath
, NULL
);
990 if (FoundHeader
&& FoundHeader
->Type
== ObDirectoryType
&&
991 RemainingPath
.Buffer
)
993 /* The name was changed so let's update it */
994 /* FIXME: TEMPORARY HACK This will go in ObFindObject in the next commit */
996 PWSTR BufferPos
= RemainingPath
.Buffer
;
999 ObpAddEntryDirectory(FoundObject
, Header
, NULL
);
1000 ObjectAttached
= TRUE
;
1002 ObjectNameInfo
= HEADER_TO_OBJECT_NAME(Header
);
1004 if (BufferPos
[0] == L
'\\')
1007 Delta
= sizeof(WCHAR
);
1009 NewName
= ExAllocatePool(NonPagedPool
, RemainingPath
.MaximumLength
- Delta
);
1010 RtlMoveMemory(NewName
, BufferPos
, RemainingPath
.MaximumLength
- Delta
);
1011 if (ObjectNameInfo
->Name
.Buffer
) ExFreePool(ObjectNameInfo
->Name
.Buffer
);
1012 ObjectNameInfo
->Name
.Buffer
= NewName
;
1013 ObjectNameInfo
->Name
.Length
= RemainingPath
.Length
- Delta
;
1014 ObjectNameInfo
->Name
.MaximumLength
= RemainingPath
.MaximumLength
- Delta
;
1015 DPRINT("Name: %S\n", ObjectNameInfo
->Name
.Buffer
);
1018 if ((Header
->Type
== IoFileObjectType
) ||
1019 (Header
->Type
== ExDesktopObjectType
) ||
1020 (Header
->Type
->TypeInfo
.OpenProcedure
!= NULL
))
1022 DPRINT("About to call Open Routine\n");
1023 if (Header
->Type
== IoFileObjectType
)
1025 /* TEMPORARY HACK. DO NOT TOUCH -- Alex */
1026 DPRINT("Calling IopCreateFile: %x\n", FoundObject
);
1027 Status
= IopCreateFile(&Header
->Body
,
1029 RemainingPath
.Buffer
,
1031 DPRINT("Called IopCreateFile: %x\n", Status
);
1034 else if (Header
->Type
== ExDesktopObjectType
)
1036 /* TEMPORARY HACK. DO NOT TOUCH -- Alex */
1037 DPRINT("Calling ExpDesktopCreate\n");
1038 Status
= ExpDesktopCreate(&Header
->Body
,
1040 RemainingPath
.Buffer
,
1043 else if (Header
->Type
->TypeInfo
.OpenProcedure
!= NULL
)
1045 DPRINT("Calling %x\n", Header
->Type
->TypeInfo
.OpenProcedure
);
1046 Status
= Header
->Type
->TypeInfo
.OpenProcedure(ObCreateHandle
,
1053 if (!NT_SUCCESS(Status
))
1055 DPRINT("Create Failed\n");
1056 if (ObjectAttached
== TRUE
)
1058 ObpRemoveEntryDirectory(Header
);
1062 ObDereferenceObject(FoundObject
);
1064 RtlFreeUnicodeString(&RemainingPath
);
1069 RtlFreeUnicodeString(&RemainingPath
);
1071 DPRINT("Security Assignment in progress\n");
1072 SeCaptureSubjectContext(&SubjectContext
);
1074 /* Build the new security descriptor */
1075 Status
= SeAssignSecurity((FoundHeader
!= NULL
) ? FoundHeader
->SecurityDescriptor
: NULL
,
1076 (ObjectCreateInfo
!= NULL
) ? ObjectCreateInfo
->SecurityDescriptor
: NULL
,
1077 &NewSecurityDescriptor
,
1078 (Header
->Type
== ObDirectoryType
),
1080 &Header
->Type
->TypeInfo
.GenericMapping
,
1083 if (NT_SUCCESS(Status
))
1085 DPRINT("NewSecurityDescriptor %p\n", NewSecurityDescriptor
);
1087 if (Header
->Type
->TypeInfo
.SecurityProcedure
!= NULL
)
1089 /* Call the security method */
1090 Status
= Header
->Type
->TypeInfo
.SecurityProcedure(&Header
->Body
,
1091 AssignSecurityDescriptor
,
1093 NewSecurityDescriptor
,
1101 /* Assign the security descriptor to the object header */
1102 Status
= ObpAddSecurityDescriptor(NewSecurityDescriptor
,
1103 &Header
->SecurityDescriptor
);
1104 DPRINT("Object security descriptor %p\n", Header
->SecurityDescriptor
);
1107 /* Release the new security descriptor */
1108 SeDeassignSecurity(&NewSecurityDescriptor
);
1111 DPRINT("Security Complete\n");
1112 SeReleaseSubjectContext(&SubjectContext
);
1114 /* Create the Handle */
1115 /* HACKHACK: Because of ROS's incorrect startup, this can be called
1116 * without a valid Process until I finalize the startup patch,
1117 * so don't create a handle if this is the case. We also don't create
1118 * a handle if Handle is NULL when the Registry Code calls it, because
1119 * the registry code totally bastardizes the Ob and needs to be fixed
1121 DPRINT("Creating handle\n");
1124 Status
= ObpCreateHandle(PsGetCurrentProcess(),
1127 ObjectCreateInfo
->Attributes
& OBJ_INHERIT
,
1129 DPRINT("handle Created: %d. refcount. handlecount %d %d\n",
1130 *Handle
, Header
->PointerCount
, Header
->HandleCount
);
1133 /* We can delete the Create Info now */
1134 Header
->ObjectCreateInfo
= NULL
;
1135 ObpReleaseCapturedAttributes(ObjectCreateInfo
);
1136 ExFreePool(ObjectCreateInfo
);
1138 DPRINT("Status %x\n", Status
);
1144 ObpGetHandleCountByHandleTable(PHANDLE_TABLE HandleTable
)
1146 return HandleTable
->HandleCount
;
1150 * FUNCTION: Searches the handle table of a specified process whether it contains a
1151 * valid handle to the Object we're looking for. If not, it'll create one.
1154 * The parameters of this function is basically a mixture of some of the parameters
1155 * of ObReferenceObjectByHandle() and ObReferenceObjectByPointer(). A little thinking
1156 * about what this function does (by it's name) makes clear what parameters it requires.
1157 * For example the AccessMode parameter of ObReferenceObjectByHandle/Pointer() is not
1158 * required at all as it only has influence on the object security. This function doesn't
1159 * want to get access to an object, it just looks for a valid handle and if it can't find
1160 * one, it'll just create one. It wouldn't make sense to check for security again as the
1161 * caller already has a pointer to the object.
1163 * A test on an XP machine shows that this prototype appears to be correct.
1166 * Process = This parameter simply describes in which handle table we're looking
1167 * for a handle to the object.
1168 * Object = The object pointer that we're looking for
1169 * ObjectType = Just a sanity check as ObReferenceObjectByHandle() and
1170 * ObReferenceObjectByPointer() provides.
1171 * HandleInformation = This one has to be the opposite meaning of the usage in
1172 * ObReferenceObjectByHandle(). If we actually found a valid
1173 * handle in the table, we need to check against the information
1174 * provided so we make sure this handle has all access rights
1175 * (and attributes?!) we need. If they don't match, we can't
1176 * use this handle and keep looking because the caller is likely
1177 * to depend on these access rights.
1178 * HandleReturn = The last parameter is the same as in ObCreateHandle(). If we could
1179 * find a suitable handle in the handle table, return this handle, if
1180 * not, we'll just create one using ObCreateHandle() with all access
1181 * rights the caller needs.
1188 ObFindHandleForObject(IN PEPROCESS Process
,
1190 IN POBJECT_TYPE ObjectType
,
1191 IN POBJECT_HANDLE_INFORMATION HandleInformation
,
1192 OUT PHANDLE HandleReturn
)
1194 DPRINT("ObFindHandleForObject is unimplemented!\n");
1195 return STATUS_UNSUCCESSFUL
;
1199 ObpGetNextHandleByProcessCount(PSYSTEM_HANDLE_TABLE_ENTRY_INFO pshi
,
1206 // pshi->HandleValue;
1209 This will never work with ROS! M$, I guess uses 0 -> 65535.
1210 Ros uses 0 -> 4294967295!
1213 P
= (ULONG
) Process
->UniqueProcessId
;
1214 pshi
->UniqueProcessId
= (USHORT
) P
;
1216 // KeAcquireSpinLock( &Process->HandleTable.ListLock, &oldIrql );
1218 // pshi->GrantedAccess;
1221 // pshi->HandleAttributes;
1223 // KeReleaseSpinLock( &Process->HandleTable.ListLock, oldIrql );