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 SweepHandleCallback(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 /* FIXME - Temporary hack: sweep and destroy here, needs to be fixed!!! */
584 ExSweepHandleTable(Process
->ObjectTable
,
587 ExDestroyHandleTable(Process
->ObjectTable
);
588 Process
->ObjectTable
= NULL
;
594 ObpCreateHandle(PEPROCESS Process
,
596 ACCESS_MASK GrantedAccess
,
598 PHANDLE HandleReturn
)
600 * FUNCTION: Add a handle referencing an object
602 * obj = Object body that the handle should refer to
603 * RETURNS: The created handle
604 * NOTE: The handle is valid only in the context of the current process
607 HANDLE_TABLE_ENTRY NewEntry
;
608 POBJECT_HEADER ObjectHeader
;
613 DPRINT("ObpCreateHandle(Process %x, obj %x)\n",Process
,ObjectBody
);
618 ObjectHeader
= BODY_TO_HEADER(ObjectBody
);
620 ASSERT((ULONG_PTR
)ObjectHeader
& EX_HANDLE_ENTRY_LOCKED
);
622 if (GrantedAccess
& MAXIMUM_ALLOWED
)
624 GrantedAccess
&= ~MAXIMUM_ALLOWED
;
625 GrantedAccess
|= GENERIC_ALL
;
628 if (GrantedAccess
& GENERIC_ANY
)
630 RtlMapGenericMask(&GrantedAccess
,
631 &ObjectHeader
->Type
->TypeInfo
.GenericMapping
);
634 NewEntry
.u1
.Object
= ObjectHeader
;
636 NewEntry
.u1
.ObAttributes
|= EX_HANDLE_ENTRY_INHERITABLE
;
638 NewEntry
.u1
.ObAttributes
&= ~EX_HANDLE_ENTRY_INHERITABLE
;
639 NewEntry
.u2
.GrantedAccess
= GrantedAccess
;
641 Handle
= ExCreateHandle(Process
->ObjectTable
,
643 DPRINT("ObCreateHandle(0x%x)==0x%x [HT:0x%x]\n", ObjectHeader
, Handle
, Process
->ObjectTable
);
646 if(InterlockedIncrement(&ObjectHeader
->HandleCount
) == 1)
648 ObReferenceObjectByPointer(ObjectBody
,
654 *HandleReturn
= Handle
;
656 return STATUS_SUCCESS
;
659 return STATUS_UNSUCCESSFUL
;
667 ObQueryObjectAuditingByHandle(IN HANDLE Handle
,
668 OUT PBOOLEAN GenerateOnClose
)
670 PHANDLE_TABLE_ENTRY HandleEntry
;
675 DPRINT("ObQueryObjectAuditingByHandle(Handle %x)\n", Handle
);
677 Process
= PsGetCurrentProcess();
679 KeEnterCriticalRegion();
681 HandleEntry
= ExMapHandleToPointer(Process
->ObjectTable
,
683 if(HandleEntry
!= NULL
)
685 *GenerateOnClose
= (HandleEntry
->u1
.ObAttributes
& EX_HANDLE_ENTRY_AUDITONCLOSE
) != 0;
687 ExUnlockHandleTableEntry(Process
->ObjectTable
,
690 KeLeaveCriticalRegion();
692 return STATUS_SUCCESS
;
695 KeLeaveCriticalRegion();
697 return STATUS_INVALID_HANDLE
;
702 * FUNCTION: Increments the reference count for an object and returns a
703 * pointer to its body
705 * Handle = Handle for the object
706 * DesiredAccess = Desired access to the object
709 * Object (OUT) = Points to the object body on return
710 * HandleInformation (OUT) = Contains information about the handle
717 ObReferenceObjectByHandle(HANDLE Handle
,
718 ACCESS_MASK DesiredAccess
,
719 POBJECT_TYPE ObjectType
,
720 KPROCESSOR_MODE AccessMode
,
722 POBJECT_HANDLE_INFORMATION HandleInformation
)
724 PHANDLE_TABLE_ENTRY HandleEntry
;
725 POBJECT_HEADER ObjectHeader
;
726 PHANDLE_TABLE HandleTable
;
728 ACCESS_MASK GrantedAccess
;
733 DPRINT("ObReferenceObjectByHandle(Handle %x, DesiredAccess %x, "
734 "ObjectType %x, AccessMode %d, Object %x)\n",Handle
,DesiredAccess
,
735 ObjectType
,AccessMode
,Object
);
739 return STATUS_INVALID_HANDLE
;
742 * Handle special handle names
744 if (Handle
== NtCurrentProcess() &&
745 (ObjectType
== PsProcessType
|| ObjectType
== NULL
))
747 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
749 ObReferenceObject(CurrentProcess
);
751 if (HandleInformation
!= NULL
)
753 HandleInformation
->HandleAttributes
= 0;
754 HandleInformation
->GrantedAccess
= PROCESS_ALL_ACCESS
;
757 *Object
= CurrentProcess
;
758 DPRINT("Referencing current process %x\n", CurrentProcess
);
759 return STATUS_SUCCESS
;
761 else if (Handle
== NtCurrentProcess())
764 return(STATUS_OBJECT_TYPE_MISMATCH
);
767 if (Handle
== NtCurrentThread() &&
768 (ObjectType
== PsThreadType
|| ObjectType
== NULL
))
770 PETHREAD CurrentThread
= PsGetCurrentThread();
772 ObReferenceObject(CurrentThread
);
774 if (HandleInformation
!= NULL
)
776 HandleInformation
->HandleAttributes
= 0;
777 HandleInformation
->GrantedAccess
= THREAD_ALL_ACCESS
;
780 *Object
= CurrentThread
;
782 return STATUS_SUCCESS
;
784 else if (Handle
== NtCurrentThread())
787 return(STATUS_OBJECT_TYPE_MISMATCH
);
790 /* desire as much access rights as possible */
791 if (DesiredAccess
& MAXIMUM_ALLOWED
)
793 DesiredAccess
&= ~MAXIMUM_ALLOWED
;
794 DesiredAccess
|= GENERIC_ALL
;
797 if(ObIsKernelHandle(Handle
, AccessMode
))
799 HandleTable
= ObpKernelHandleTable
;
800 Handle
= ObKernelHandleToHandle(Handle
);
804 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
807 KeEnterCriticalRegion();
809 HandleEntry
= ExMapHandleToPointer(HandleTable
,
811 if (HandleEntry
== NULL
)
813 KeLeaveCriticalRegion();
814 DPRINT("ExMapHandleToPointer() failed for handle 0x%x\n", Handle
);
815 return(STATUS_INVALID_HANDLE
);
818 ObjectHeader
= EX_HTE_TO_HDR(HandleEntry
);
819 ObjectBody
= &ObjectHeader
->Body
;
821 DPRINT("locked1: ObjectHeader: 0x%x [HT:0x%x]\n", ObjectHeader
, HandleTable
);
823 if (ObjectType
!= NULL
&& ObjectType
!= ObjectHeader
->Type
)
825 DPRINT("ObjectType mismatch: %wZ vs %wZ (handle 0x%x)\n", &ObjectType
->Name
, ObjectHeader
->Type
? &ObjectHeader
->Type
->Name
: NULL
, Handle
);
827 ExUnlockHandleTableEntry(HandleTable
,
830 KeLeaveCriticalRegion();
832 return(STATUS_OBJECT_TYPE_MISMATCH
);
835 /* map the generic access masks if the caller asks for generic access */
836 if (DesiredAccess
& GENERIC_ANY
)
838 RtlMapGenericMask(&DesiredAccess
,
839 &BODY_TO_HEADER(ObjectBody
)->Type
->TypeInfo
.GenericMapping
);
842 GrantedAccess
= HandleEntry
->u2
.GrantedAccess
;
844 /* Unless running as KernelMode, deny access if caller desires more access
845 rights than the handle can grant */
846 if(AccessMode
!= KernelMode
&& (~GrantedAccess
& DesiredAccess
))
848 ExUnlockHandleTableEntry(HandleTable
,
851 KeLeaveCriticalRegion();
853 DPRINT1("GrantedAccess: 0x%x, ~GrantedAccess: 0x%x, DesiredAccess: 0x%x, denied: 0x%x\n", GrantedAccess
, ~GrantedAccess
, DesiredAccess
, ~GrantedAccess
& DesiredAccess
);
855 return(STATUS_ACCESS_DENIED
);
858 ObReferenceObject(ObjectBody
);
860 Attributes
= HandleEntry
->u1
.ObAttributes
& (EX_HANDLE_ENTRY_PROTECTFROMCLOSE
|
861 EX_HANDLE_ENTRY_INHERITABLE
|
862 EX_HANDLE_ENTRY_AUDITONCLOSE
);
864 ExUnlockHandleTableEntry(HandleTable
,
867 KeLeaveCriticalRegion();
869 if (HandleInformation
!= NULL
)
871 HandleInformation
->HandleAttributes
= Attributes
;
872 HandleInformation
->GrantedAccess
= GrantedAccess
;
875 *Object
= ObjectBody
;
877 return(STATUS_SUCCESS
);
881 /**********************************************************************
886 * Closes a handle reference to an object.
898 NtClose(IN HANDLE Handle
)
900 PHANDLE_TABLE HandleTable
;
905 if(ObIsKernelHandle(Handle
, ExGetPreviousMode()))
907 HandleTable
= ObpKernelHandleTable
;
908 Handle
= ObKernelHandleToHandle(Handle
);
912 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
915 Status
= ObpDeleteHandle(HandleTable
,
917 if (!NT_SUCCESS(Status
))
919 if((ExGetPreviousMode() != KernelMode
) &&
920 (PsGetCurrentProcess()->ExceptionPort
))
922 KeRaiseUserException(Status
);
927 return(STATUS_SUCCESS
);
936 ObInsertObject(IN PVOID Object
,
937 IN PACCESS_STATE PassedAccessState OPTIONAL
,
938 IN ACCESS_MASK DesiredAccess
,
939 IN ULONG AdditionalReferences
,
940 OUT PVOID
* ReferencedObject OPTIONAL
,
943 POBJECT_CREATE_INFORMATION ObjectCreateInfo
;
944 POBJECT_HEADER Header
;
945 POBJECT_HEADER_NAME_INFO ObjectNameInfo
;
946 PVOID FoundObject
= NULL
;
947 POBJECT_HEADER FoundHeader
= NULL
;
948 NTSTATUS Status
= STATUS_SUCCESS
;
949 UNICODE_STRING RemainingPath
;
950 BOOLEAN ObjectAttached
= FALSE
;
951 PSECURITY_DESCRIPTOR NewSecurityDescriptor
= NULL
;
952 SECURITY_SUBJECT_CONTEXT SubjectContext
;
956 /* Get the Header and Create Info */
957 DPRINT("ObInsertObject: %x\n", Object
);
958 Header
= BODY_TO_HEADER(Object
);
959 ObjectCreateInfo
= Header
->ObjectCreateInfo
;
960 ObjectNameInfo
= HEADER_TO_OBJECT_NAME(Header
);
962 /* First try to find the Object */
963 if (ObjectNameInfo
&& ObjectNameInfo
->Name
.Buffer
)
965 DPRINT("Object has a name. Trying to find it: %wZ.\n", &ObjectNameInfo
->Name
);
966 Status
= ObFindObject(ObjectCreateInfo
,
967 &ObjectNameInfo
->Name
,
971 DPRINT("FoundObject: %x, Path: %wZ\n", FoundObject
, &RemainingPath
);
972 if (!NT_SUCCESS(Status
))
974 DPRINT1("ObFindObject() failed! (Status 0x%x)\n", Status
);
980 DPRINT("Getting header: %x\n", FoundObject
);
981 FoundHeader
= BODY_TO_HEADER(FoundObject
);
984 if (FoundHeader
&& RemainingPath
.Buffer
== NULL
)
986 DPRINT("Object exists\n");
987 ObDereferenceObject(FoundObject
);
988 return STATUS_OBJECT_NAME_COLLISION
;
993 DPRINT("No name, empty remaining path\n");
994 RtlInitUnicodeString(&RemainingPath
, NULL
);
997 if (FoundHeader
&& FoundHeader
->Type
== ObDirectoryType
&&
998 RemainingPath
.Buffer
)
1000 /* The name was changed so let's update it */
1001 /* FIXME: TEMPORARY HACK This will go in ObFindObject in the next commit */
1003 PWSTR BufferPos
= RemainingPath
.Buffer
;
1006 ObpAddEntryDirectory(FoundObject
, Header
, NULL
);
1007 ObjectAttached
= TRUE
;
1009 ObjectNameInfo
= HEADER_TO_OBJECT_NAME(Header
);
1011 if (BufferPos
[0] == L
'\\')
1014 Delta
= sizeof(WCHAR
);
1016 NewName
= ExAllocatePool(NonPagedPool
, RemainingPath
.MaximumLength
- Delta
);
1017 RtlMoveMemory(NewName
, BufferPos
, RemainingPath
.MaximumLength
- Delta
);
1018 if (ObjectNameInfo
->Name
.Buffer
) ExFreePool(ObjectNameInfo
->Name
.Buffer
);
1019 ObjectNameInfo
->Name
.Buffer
= NewName
;
1020 ObjectNameInfo
->Name
.Length
= RemainingPath
.Length
- Delta
;
1021 ObjectNameInfo
->Name
.MaximumLength
= RemainingPath
.MaximumLength
- Delta
;
1022 DPRINT("Name: %S\n", ObjectNameInfo
->Name
.Buffer
);
1025 if ((Header
->Type
== IoFileObjectType
) ||
1026 (Header
->Type
== ExDesktopObjectType
) ||
1027 (Header
->Type
->TypeInfo
.OpenProcedure
!= NULL
))
1029 DPRINT("About to call Open Routine\n");
1030 if (Header
->Type
== IoFileObjectType
)
1032 /* TEMPORARY HACK. DO NOT TOUCH -- Alex */
1033 DPRINT("Calling IopCreateFile: %x\n", FoundObject
);
1034 Status
= IopCreateFile(&Header
->Body
,
1036 RemainingPath
.Buffer
,
1038 DPRINT("Called IopCreateFile: %x\n", Status
);
1041 else if (Header
->Type
== ExDesktopObjectType
)
1043 /* TEMPORARY HACK. DO NOT TOUCH -- Alex */
1044 DPRINT("Calling ExpDesktopCreate\n");
1045 Status
= ExpDesktopCreate(&Header
->Body
,
1047 RemainingPath
.Buffer
,
1050 else if (Header
->Type
->TypeInfo
.OpenProcedure
!= NULL
)
1052 DPRINT("Calling %x\n", Header
->Type
->TypeInfo
.OpenProcedure
);
1053 Status
= Header
->Type
->TypeInfo
.OpenProcedure(ObCreateHandle
,
1060 if (!NT_SUCCESS(Status
))
1062 DPRINT("Create Failed\n");
1063 if (ObjectAttached
== TRUE
)
1065 ObpRemoveEntryDirectory(Header
);
1069 ObDereferenceObject(FoundObject
);
1071 RtlFreeUnicodeString(&RemainingPath
);
1076 RtlFreeUnicodeString(&RemainingPath
);
1078 DPRINT("Security Assignment in progress\n");
1079 SeCaptureSubjectContext(&SubjectContext
);
1081 /* Build the new security descriptor */
1082 Status
= SeAssignSecurity((FoundHeader
!= NULL
) ? FoundHeader
->SecurityDescriptor
: NULL
,
1083 (ObjectCreateInfo
!= NULL
) ? ObjectCreateInfo
->SecurityDescriptor
: NULL
,
1084 &NewSecurityDescriptor
,
1085 (Header
->Type
== ObDirectoryType
),
1087 &Header
->Type
->TypeInfo
.GenericMapping
,
1090 if (NT_SUCCESS(Status
))
1092 DPRINT("NewSecurityDescriptor %p\n", NewSecurityDescriptor
);
1094 if (Header
->Type
->TypeInfo
.SecurityProcedure
!= NULL
)
1096 /* Call the security method */
1097 Status
= Header
->Type
->TypeInfo
.SecurityProcedure(&Header
->Body
,
1098 AssignSecurityDescriptor
,
1100 NewSecurityDescriptor
,
1108 /* Assign the security descriptor to the object header */
1109 Status
= ObpAddSecurityDescriptor(NewSecurityDescriptor
,
1110 &Header
->SecurityDescriptor
);
1111 DPRINT("Object security descriptor %p\n", Header
->SecurityDescriptor
);
1114 /* Release the new security descriptor */
1115 SeDeassignSecurity(&NewSecurityDescriptor
);
1118 DPRINT("Security Complete\n");
1119 SeReleaseSubjectContext(&SubjectContext
);
1121 /* Create the Handle */
1122 /* HACKHACK: Because of ROS's incorrect startup, this can be called
1123 * without a valid Process until I finalize the startup patch,
1124 * so don't create a handle if this is the case. We also don't create
1125 * a handle if Handle is NULL when the Registry Code calls it, because
1126 * the registry code totally bastardizes the Ob and needs to be fixed
1128 DPRINT("Creating handle\n");
1131 Status
= ObpCreateHandle(PsGetCurrentProcess(),
1134 ObjectCreateInfo
->Attributes
& OBJ_INHERIT
,
1136 DPRINT("handle Created: %d. refcount. handlecount %d %d\n",
1137 *Handle
, Header
->PointerCount
, Header
->HandleCount
);
1140 /* We can delete the Create Info now */
1141 Header
->ObjectCreateInfo
= NULL
;
1142 ObpReleaseCapturedAttributes(ObjectCreateInfo
);
1143 ExFreePool(ObjectCreateInfo
);
1145 DPRINT("Status %x\n", Status
);
1152 ObpGetHandleCountByHandleTable(PHANDLE_TABLE HandleTable
)
1154 return HandleTable
->HandleCount
;
1158 * FUNCTION: Searches the handle table of a specified process whether it contains a
1159 * valid handle to the Object we're looking for. If not, it'll create one.
1162 * The parameters of this function is basically a mixture of some of the parameters
1163 * of ObReferenceObjectByHandle() and ObReferenceObjectByPointer(). A little thinking
1164 * about what this function does (by it's name) makes clear what parameters it requires.
1165 * For example the AccessMode parameter of ObReferenceObjectByHandle/Pointer() is not
1166 * required at all as it only has influence on the object security. This function doesn't
1167 * want to get access to an object, it just looks for a valid handle and if it can't find
1168 * one, it'll just create one. It wouldn't make sense to check for security again as the
1169 * caller already has a pointer to the object.
1171 * A test on an XP machine shows that this prototype appears to be correct.
1174 * Process = This parameter simply describes in which handle table we're looking
1175 * for a handle to the object.
1176 * Object = The object pointer that we're looking for
1177 * ObjectType = Just a sanity check as ObReferenceObjectByHandle() and
1178 * ObReferenceObjectByPointer() provides.
1179 * HandleInformation = This one has to be the opposite meaning of the usage in
1180 * ObReferenceObjectByHandle(). If we actually found a valid
1181 * handle in the table, we need to check against the information
1182 * provided so we make sure this handle has all access rights
1183 * (and attributes?!) we need. If they don't match, we can't
1184 * use this handle and keep looking because the caller is likely
1185 * to depend on these access rights.
1186 * HandleReturn = The last parameter is the same as in ObCreateHandle(). If we could
1187 * find a suitable handle in the handle table, return this handle, if
1188 * not, we'll just create one using ObCreateHandle() with all access
1189 * rights the caller needs.
1196 ObFindHandleForObject(IN PEPROCESS Process
,
1198 IN POBJECT_TYPE ObjectType
,
1199 IN POBJECT_HANDLE_INFORMATION HandleInformation
,
1200 OUT PHANDLE HandleReturn
)
1202 DPRINT("ObFindHandleForObject is unimplemented!\n");
1203 return STATUS_UNSUCCESSFUL
;
1207 ObpGetNextHandleByProcessCount(PSYSTEM_HANDLE_TABLE_ENTRY_INFO pshi
,
1214 // pshi->HandleValue;
1217 This will never work with ROS! M$, I guess uses 0 -> 65535.
1218 Ros uses 0 -> 4294967295!
1221 P
= (ULONG
) Process
->UniqueProcessId
;
1222 pshi
->UniqueProcessId
= (USHORT
) P
;
1224 // KeAcquireSpinLock( &Process->HandleTable.ListLock, &oldIrql );
1226 // pshi->GrantedAccess;
1229 // pshi->HandleAttributes;
1231 // KeReleaseSpinLock( &Process->HandleTable.ListLock, oldIrql );