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.
19 /* $Id: handle.c,v 1.59 2004/08/20 23:46:21 navaraf Exp $
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 /* TYPES *******************************************************************/
39 * PURPOSE: Defines a handle
44 ACCESS_MASK GrantedAccess
;
45 } HANDLE_REP
, *PHANDLE_REP
;
47 #define HANDLE_BLOCK_ENTRIES \
49 (sizeof(LIST_ENTRY) + sizeof(ULONG))) / sizeof(HANDLE_REP))
51 #define OB_HANDLE_FLAG_MASK 0x00000007
52 #define OB_HANDLE_FLAG_AUDIT 0x00000004
53 #define OB_HANDLE_FLAG_PROTECT 0x00000002
54 #define OB_HANDLE_FLAG_INHERIT 0x00000001
56 #define OB_POINTER_TO_ENTRY(Pointer) \
57 (PVOID)((ULONG_PTR)(Pointer) & ~OB_HANDLE_FLAG_MASK)
59 #define OB_ENTRY_TO_POINTER(Entry) \
60 (PVOID)((ULONG_PTR)(Entry) & ~OB_HANDLE_FLAG_MASK)
63 * PURPOSE: Defines a 4 page's worth of handles
68 ULONG allocation_hint
;
69 ULONG allocation_count
;
70 HANDLE_REP handles
[HANDLE_BLOCK_ENTRIES
];
71 } HANDLE_BLOCK
, *PHANDLE_BLOCK
;
74 /* GLOBALS *******************************************************************/
76 #define TAG_HANDLE_TABLE TAG('H', 'T', 'B', 'L')
78 /* FUNCTIONS ***************************************************************/
82 ObpGetObjectByHandle(PHANDLE_TABLE HandleTable
, HANDLE h
, HANDLE_BLOCK
**Block
)
84 * FUNCTION: Get the data structure for a handle
86 * Process = Process to get the handle for
88 * ARGUMENTS: A pointer to the information about the handle on success,
93 unsigned int handle
= (((unsigned int)h
) >> 2) - 1;
94 unsigned int count
=handle
/HANDLE_BLOCK_ENTRIES
;
95 HANDLE_BLOCK
* blk
= NULL
;
98 DPRINT("ObpGetObjectByHandle(HandleTable %x, h %x)\n",HandleTable
,h
);
100 current
= HandleTable
->ListHead
.Flink
;
101 DPRINT("current %x\n",current
);
103 for (i
=0;i
<count
;i
++)
105 current
= current
->Flink
;
106 if (current
== (&(HandleTable
->ListHead
)))
112 blk
= CONTAINING_RECORD(current
,HANDLE_BLOCK
,entry
);
115 DPRINT("object: %p\n",&(blk
->handles
[handle
%HANDLE_BLOCK_ENTRIES
]));
116 return(&(blk
->handles
[handle
%HANDLE_BLOCK_ENTRIES
]));
121 ObpQueryHandleAttributes(HANDLE Handle
,
122 POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo
)
126 PHANDLE_REP HandleRep
;
128 DPRINT("ObpQueryHandleAttributes(Handle %x)\n", Handle
);
130 Process
= PsGetCurrentProcess();
132 KeAcquireSpinLock(&Process
->HandleTable
.ListLock
, &oldIrql
);
133 HandleRep
= ObpGetObjectByHandle(&Process
->HandleTable
,
136 if (HandleRep
== NULL
)
138 KeReleaseSpinLock(&Process
->HandleTable
.ListLock
, oldIrql
);
139 return STATUS_INVALID_HANDLE
;
142 HandleInfo
->Inherit
=
143 ((ULONG_PTR
)HandleRep
->ObjectBody
& OB_HANDLE_FLAG_INHERIT
);
144 HandleInfo
->ProtectFromClose
=
145 ((ULONG_PTR
)HandleRep
->ObjectBody
& OB_HANDLE_FLAG_PROTECT
);
147 KeReleaseSpinLock(&Process
->HandleTable
.ListLock
, oldIrql
);
149 return STATUS_SUCCESS
;
154 ObpSetHandleAttributes(HANDLE Handle
,
155 POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo
)
159 PHANDLE_REP HandleRep
;
161 DPRINT("ObpQueryHandleAttributes(Handle %x)\n", Handle
);
163 Process
= PsGetCurrentProcess();
165 KeAcquireSpinLock(&Process
->HandleTable
.ListLock
, &oldIrql
);
166 HandleRep
= ObpGetObjectByHandle(&Process
->HandleTable
,
169 if (HandleRep
== NULL
)
171 KeReleaseSpinLock(&Process
->HandleTable
.ListLock
, oldIrql
);
172 return STATUS_INVALID_HANDLE
;
175 if (HandleInfo
->Inherit
)
176 HandleRep
->ObjectBody
= (PVOID
)((ULONG_PTR
)HandleRep
->ObjectBody
| OB_HANDLE_FLAG_INHERIT
);
178 HandleRep
->ObjectBody
= (PVOID
)((ULONG_PTR
)HandleRep
->ObjectBody
& ~OB_HANDLE_FLAG_INHERIT
);
180 if (HandleInfo
->ProtectFromClose
)
181 HandleRep
->ObjectBody
= (PVOID
)((ULONG_PTR
)HandleRep
->ObjectBody
| OB_HANDLE_FLAG_PROTECT
);
183 HandleRep
->ObjectBody
= (PVOID
)((ULONG_PTR
)HandleRep
->ObjectBody
& ~OB_HANDLE_FLAG_PROTECT
);
185 /* FIXME: Do we need to set anything in the object header??? */
187 KeReleaseSpinLock(&Process
->HandleTable
.ListLock
, oldIrql
);
189 return STATUS_SUCCESS
;
194 ObDuplicateObject(PEPROCESS SourceProcess
,
195 PEPROCESS TargetProcess
,
197 PHANDLE TargetHandle
,
198 ACCESS_MASK DesiredAccess
,
199 BOOLEAN InheritHandle
,
203 PHANDLE_REP SourceHandleRep
;
206 KeAcquireSpinLock(&SourceProcess
->HandleTable
.ListLock
, &oldIrql
);
207 SourceHandleRep
= ObpGetObjectByHandle(&SourceProcess
->HandleTable
,
210 if (SourceHandleRep
== NULL
)
212 KeReleaseSpinLock(&SourceProcess
->HandleTable
.ListLock
, oldIrql
);
213 return(STATUS_INVALID_HANDLE
);
215 ObjectBody
= OB_ENTRY_TO_POINTER(SourceHandleRep
->ObjectBody
);
216 ObReferenceObjectByPointer(ObjectBody
,
221 if (Options
& DUPLICATE_SAME_ACCESS
)
223 DesiredAccess
= SourceHandleRep
->GrantedAccess
;
226 KeReleaseSpinLock(&SourceProcess
->HandleTable
.ListLock
, oldIrql
);
227 ObCreateHandle(TargetProcess
,
233 if (Options
& DUPLICATE_CLOSE_SOURCE
)
235 ZwClose(SourceHandle
);
238 ObDereferenceObject(ObjectBody
);
239 return(STATUS_SUCCESS
);
246 NtDuplicateObject (IN HANDLE SourceProcessHandle
,
247 IN HANDLE SourceHandle
,
248 IN HANDLE TargetProcessHandle
,
249 OUT PHANDLE UnsafeTargetHandle
,
250 IN ACCESS_MASK DesiredAccess
,
251 IN BOOLEAN InheritHandle
,
254 * FUNCTION: Copies a handle from one process space to another
256 * SourceProcessHandle = The source process owning the handle. The
257 * source process should have opened
258 * the SourceHandle with PROCESS_DUP_HANDLE
260 * SourceHandle = The handle to the object.
261 * TargetProcessHandle = The destination process owning the handle
262 * TargetHandle (OUT) = Caller should supply storage for the
264 * DesiredAccess = The desired access to the handle.
265 * InheritHandle = Indicates wheter the new handle will be inheritable
267 * Options = Specifies special actions upon duplicating the handle.
268 * Can be one of the values DUPLICATE_CLOSE_SOURCE |
269 * DUPLICATE_SAME_ACCESS. DUPLICATE_CLOSE_SOURCE specifies
270 * that the source handle should be closed after duplicating.
271 * DUPLICATE_SAME_ACCESS specifies to ignore the
272 * DesiredAccess paramter and just grant the same access to
275 * REMARKS: This function maps to the win32 DuplicateHandle.
278 PEPROCESS SourceProcess
;
279 PEPROCESS TargetProcess
;
280 PHANDLE_REP SourceHandleRep
;
286 ASSERT_IRQL(PASSIVE_LEVEL
);
288 Status
= ObReferenceObjectByHandle(SourceProcessHandle
,
292 (PVOID
*)&SourceProcess
,
294 if (!NT_SUCCESS(Status
))
298 Status
= ObReferenceObjectByHandle(TargetProcessHandle
,
302 (PVOID
*)&TargetProcess
,
304 if (!NT_SUCCESS(Status
))
306 ObDereferenceObject(SourceProcess
);
310 /* Check for magic handle first */
311 if (SourceHandle
== NtCurrentThread())
313 ObReferenceObjectByHandle(SourceHandle
,
320 ObCreateHandle(TargetProcess
,
328 KeAcquireSpinLock(&SourceProcess
->HandleTable
.ListLock
, &oldIrql
);
329 SourceHandleRep
= ObpGetObjectByHandle(&SourceProcess
->HandleTable
,
332 if (SourceHandleRep
== NULL
)
334 KeReleaseSpinLock(&SourceProcess
->HandleTable
.ListLock
, oldIrql
);
335 ObDereferenceObject(SourceProcess
);
336 ObDereferenceObject(TargetProcess
);
337 return(STATUS_INVALID_HANDLE
);
339 ObjectBody
= OB_ENTRY_TO_POINTER(SourceHandleRep
->ObjectBody
);
340 ObReferenceObjectByPointer(ObjectBody
,
345 if (Options
& DUPLICATE_SAME_ACCESS
)
347 DesiredAccess
= SourceHandleRep
->GrantedAccess
;
350 KeReleaseSpinLock(&SourceProcess
->HandleTable
.ListLock
, oldIrql
);
351 if (!((ULONG_PTR
)SourceHandleRep
->ObjectBody
& OB_HANDLE_FLAG_INHERIT
))
353 ObDereferenceObject(TargetProcess
);
354 ObDereferenceObject(SourceProcess
);
355 ObDereferenceObject(ObjectBody
);
356 return STATUS_INVALID_HANDLE
;
358 ObCreateHandle(TargetProcess
,
365 if (Options
& DUPLICATE_CLOSE_SOURCE
)
367 ZwClose(SourceHandle
);
370 ObDereferenceObject(TargetProcess
);
371 ObDereferenceObject(SourceProcess
);
372 ObDereferenceObject(ObjectBody
);
374 Status
= MmCopyToCaller(UnsafeTargetHandle
, &TargetHandle
, sizeof(HANDLE
));
375 if (!NT_SUCCESS(Status
))
380 return(STATUS_SUCCESS
);
383 VOID
ObCloseAllHandles(PEPROCESS Process
)
386 PHANDLE_TABLE HandleTable
;
387 PLIST_ENTRY current_entry
;
388 PHANDLE_BLOCK current
;
392 DPRINT("ObCloseAllHandles(Process %x)\n", Process
);
394 HandleTable
= &Process
->HandleTable
;
396 KeAcquireSpinLock(&HandleTable
->ListLock
, &oldIrql
);
398 current_entry
= HandleTable
->ListHead
.Flink
;
400 while (current_entry
!= &HandleTable
->ListHead
)
402 current
= CONTAINING_RECORD(current_entry
, HANDLE_BLOCK
, entry
);
404 for (i
= 0; i
< HANDLE_BLOCK_ENTRIES
; i
++)
406 ObjectBody
= OB_ENTRY_TO_POINTER(current
->handles
[i
].ObjectBody
);
408 if (ObjectBody
!= NULL
)
410 POBJECT_HEADER Header
= BODY_TO_HEADER(ObjectBody
);
412 if (Header
->ObjectType
== PsProcessType
||
413 Header
->ObjectType
== PsThreadType
)
415 DPRINT("Deleting handle to %x\n", ObjectBody
);
418 ObReferenceObjectByPointer(ObjectBody
,
422 InterlockedDecrement(&Header
->HandleCount
);
423 current
->handles
[i
].ObjectBody
= NULL
;
425 KeReleaseSpinLock(&HandleTable
->ListLock
, oldIrql
);
426 if ((Header
->ObjectType
!= NULL
) &&
427 (Header
->ObjectType
->Close
!= NULL
))
429 Header
->ObjectType
->Close(ObjectBody
,
430 Header
->HandleCount
);
433 ObDereferenceObject(ObjectBody
);
434 KeAcquireSpinLock(&HandleTable
->ListLock
, &oldIrql
);
435 current_entry
= &HandleTable
->ListHead
;
440 current_entry
= current_entry
->Flink
;
442 KeReleaseSpinLock(&HandleTable
->ListLock
, oldIrql
);
443 DPRINT("ObCloseAllHandles() finished\n");
444 DPRINT("Type %x\n", BODY_TO_HEADER(Process
)->ObjectType
);
447 VOID
ObDeleteHandleTable(PEPROCESS Process
)
449 * FUNCTION: Deletes the handle table associated with a process
452 PLIST_ENTRY current
= NULL
;
453 PHANDLE_TABLE HandleTable
= NULL
;
455 ObCloseAllHandles(Process
);
457 HandleTable
= &Process
->HandleTable
;
458 current
= RemoveHeadList(&HandleTable
->ListHead
);
460 while (current
!= &HandleTable
->ListHead
)
462 HANDLE_BLOCK
* HandleBlock
= CONTAINING_RECORD(current
,
465 DPRINT("Freeing %x\n", HandleBlock
);
466 ExFreePool(HandleBlock
);
468 current
= RemoveHeadList(&HandleTable
->ListHead
);
473 VOID
ObCreateHandleTable(PEPROCESS Parent
,
477 * FUNCTION: Creates a handle table for a process
479 * Parent = Parent process (or NULL if this is the first process)
480 * Inherit = True if the process should inherit its parent's handles
481 * Process = Process whose handle table is to be created
484 PHANDLE_TABLE ParentHandleTable
, HandleTable
;
486 PLIST_ENTRY parent_current
;
488 PHANDLE_BLOCK current_block
, new_block
;
490 DPRINT("ObCreateHandleTable(Parent %x, Inherit %d, Process %x)\n",
491 Parent
,Inherit
,Process
);
493 InitializeListHead(&(Process
->HandleTable
.ListHead
));
494 KeInitializeSpinLock(&(Process
->HandleTable
.ListLock
));
498 ParentHandleTable
= &Parent
->HandleTable
;
499 HandleTable
= &Process
->HandleTable
;
501 KeAcquireSpinLock(&Parent
->HandleTable
.ListLock
, &oldIrql
);
502 KeAcquireSpinLockAtDpcLevel(&Process
->HandleTable
.ListLock
);
504 parent_current
= ParentHandleTable
->ListHead
.Flink
;
506 while (parent_current
!= &ParentHandleTable
->ListHead
)
508 current_block
= CONTAINING_RECORD(parent_current
,
511 new_block
= ExAllocatePoolWithTag(NonPagedPool
,
512 sizeof(HANDLE_BLOCK
),
514 if (new_block
== NULL
)
518 RtlZeroMemory(new_block
, sizeof(HANDLE_BLOCK
));
520 for (i
=0; i
<HANDLE_BLOCK_ENTRIES
; i
++)
522 if (current_block
->handles
[i
].ObjectBody
)
524 if ((ULONG_PTR
)current_block
->handles
[i
].ObjectBody
& OB_HANDLE_FLAG_INHERIT
)
526 new_block
->handles
[i
].ObjectBody
=
527 current_block
->handles
[i
].ObjectBody
;
528 new_block
->handles
[i
].GrantedAccess
=
529 current_block
->handles
[i
].GrantedAccess
;
530 InterlockedIncrement(&(BODY_TO_HEADER(OB_ENTRY_TO_POINTER(current_block
->handles
[i
].ObjectBody
))->HandleCount
));
534 InsertTailList(&Process
->HandleTable
.ListHead
, &new_block
->entry
);
535 parent_current
= parent_current
->Flink
;
537 KeReleaseSpinLockFromDpcLevel(&Process
->HandleTable
.ListLock
);
538 KeReleaseSpinLock(&Parent
->HandleTable
.ListLock
, oldIrql
);
544 ObDeleteHandle(PEPROCESS Process
,
551 PHANDLE_TABLE HandleTable
;
552 POBJECT_HEADER Header
;
555 DPRINT("ObDeleteHandle(Handle %x)\n",Handle
);
557 HandleTable
= &Process
->HandleTable
;
559 KeAcquireSpinLock(&HandleTable
->ListLock
, &oldIrql
);
561 Rep
= ObpGetObjectByHandle(HandleTable
, Handle
, &Block
);
564 KeReleaseSpinLock(&HandleTable
->ListLock
, oldIrql
);
566 return STATUS_INVALID_HANDLE
;
569 if ((ULONG_PTR
)Rep
->ObjectBody
& OB_HANDLE_FLAG_PROTECT
)
571 KeReleaseSpinLock(&HandleTable
->ListLock
, oldIrql
);
573 return STATUS_HANDLE_NOT_CLOSABLE
;
576 Body
= OB_ENTRY_TO_POINTER(Rep
->ObjectBody
);
577 DPRINT("ObjectBody %x\n", Body
);
580 KeReleaseSpinLock(&HandleTable
->ListLock
, oldIrql
);
582 return STATUS_UNSUCCESSFUL
;
585 Header
= BODY_TO_HEADER(Body
);
586 ObReferenceObjectByPointer(Body
,
590 InterlockedDecrement(&Header
->HandleCount
);
591 Rep
->ObjectBody
= NULL
;
593 Block
->allocation_count
--;
594 Block
->allocation_hint
= (ULONG_PTR
)Handle
% HANDLE_BLOCK_ENTRIES
;
596 KeReleaseSpinLock(&HandleTable
->ListLock
, oldIrql
);
598 if ((Header
->ObjectType
!= NULL
) &&
599 (Header
->ObjectType
->Close
!= NULL
))
601 Header
->ObjectType
->Close(Body
, Header
->HandleCount
);
606 DPRINT("Finished ObDeleteHandle()\n");
608 return STATUS_SUCCESS
;
612 NTSTATUS
ObCreateHandle(PEPROCESS Process
,
614 ACCESS_MASK GrantedAccess
,
616 PHANDLE HandleReturn
)
618 * FUNCTION: Add a handle referencing an object
620 * obj = Object body that the handle should refer to
621 * RETURNS: The created handle
622 * NOTE: The handle is valid only in the context of the current process
626 unsigned int handle
=1;
627 unsigned int Loop
, Index
, MaxIndex
;
628 HANDLE_BLOCK
* new_blk
= NULL
;
629 PHANDLE_TABLE HandleTable
;
632 DPRINT("ObCreateHandle(Process %x, obj %x)\n",Process
,ObjectBody
);
636 if (ObjectBody
!= NULL
)
638 InterlockedIncrement(&(BODY_TO_HEADER(ObjectBody
)->HandleCount
));
640 HandleTable
= &Process
->HandleTable
;
641 KeAcquireSpinLock(&HandleTable
->ListLock
, &oldlvl
);
642 current
= HandleTable
->ListHead
.Flink
;
644 * Scan through the currently allocated handle blocks looking for a free
647 while (current
!= (&HandleTable
->ListHead
))
649 HANDLE_BLOCK
* blk
= CONTAINING_RECORD(current
,HANDLE_BLOCK
,entry
);
651 DPRINT("Current %x\n",current
);
653 if (blk
->allocation_count
== HANDLE_BLOCK_ENTRIES
)
655 handle
= handle
+ HANDLE_BLOCK_ENTRIES
;
656 current
= current
->Flink
;
660 Index
= blk
->allocation_hint
;
661 MaxIndex
= HANDLE_BLOCK_ENTRIES
;
662 for (Loop
= 0; Loop
< 2; Loop
++)
664 for (Index
= 0; Index
< MaxIndex
; Index
++)
666 DPRINT("Considering slot %d containing %x\n", Index
, blk
->handles
[Index
]);
667 if (blk
->handles
[Index
].ObjectBody
== NULL
)
669 blk
->handles
[Index
].ObjectBody
= OB_POINTER_TO_ENTRY(ObjectBody
);
671 blk
->handles
[Index
].ObjectBody
= (PVOID
)((ULONG_PTR
)blk
->handles
[Index
].ObjectBody
| OB_HANDLE_FLAG_INHERIT
);
672 blk
->handles
[Index
].GrantedAccess
= GrantedAccess
;
673 blk
->allocation_hint
= Index
+ 1;
674 blk
->allocation_count
++;
675 KeReleaseSpinLock(&HandleTable
->ListLock
, oldlvl
);
676 *HandleReturn
= (HANDLE
)((handle
+ Index
) << 2);
677 return(STATUS_SUCCESS
);
681 MaxIndex
= blk
->allocation_hint
;
684 handle
= handle
+ HANDLE_BLOCK_ENTRIES
;
685 current
= current
->Flink
;
689 * Add a new handle block to the end of the list
692 (HANDLE_BLOCK
*)ExAllocatePoolWithTag(NonPagedPool
,sizeof(HANDLE_BLOCK
),
696 *HandleReturn
= (PHANDLE
)NULL
;
697 return(STATUS_INSUFFICIENT_RESOURCES
);
699 RtlZeroMemory(new_blk
,sizeof(HANDLE_BLOCK
));
700 InsertTailList(&(Process
->HandleTable
.ListHead
),
702 new_blk
->handles
[0].ObjectBody
= OB_POINTER_TO_ENTRY(ObjectBody
);
704 new_blk
->handles
[0].ObjectBody
= (PVOID
)((ULONG_PTR
)new_blk
->handles
[0].ObjectBody
| OB_HANDLE_FLAG_INHERIT
);
705 new_blk
->handles
[0].GrantedAccess
= GrantedAccess
;
706 new_blk
->allocation_hint
= 1;
707 new_blk
->allocation_count
++;
708 KeReleaseSpinLock(&HandleTable
->ListLock
, oldlvl
);
709 *HandleReturn
= (HANDLE
)(handle
<< 2);
710 return(STATUS_SUCCESS
);
718 ObQueryObjectAuditingByHandle(IN HANDLE Handle
,
719 OUT PBOOLEAN GenerateOnClose
)
723 PHANDLE_REP HandleRep
;
725 DPRINT("ObQueryObjectAuditingByHandle(Handle %x)\n", Handle
);
727 Process
= PsGetCurrentProcess();
729 KeAcquireSpinLock(&Process
->HandleTable
.ListLock
, &oldIrql
);
730 HandleRep
= ObpGetObjectByHandle(&Process
->HandleTable
,
733 if (HandleRep
== NULL
)
735 KeReleaseSpinLock(&Process
->HandleTable
.ListLock
, oldIrql
);
736 return STATUS_INVALID_HANDLE
;
739 *GenerateOnClose
= (BOOLEAN
)((ULONG_PTR
)HandleRep
->ObjectBody
| OB_HANDLE_FLAG_AUDIT
);
741 KeReleaseSpinLock(&Process
->HandleTable
.ListLock
, oldIrql
);
743 return STATUS_SUCCESS
;
751 ObReferenceObjectByHandle(HANDLE Handle
,
752 ACCESS_MASK DesiredAccess
,
753 POBJECT_TYPE ObjectType
,
754 KPROCESSOR_MODE AccessMode
,
756 POBJECT_HANDLE_INFORMATION HandleInformation
)
758 * FUNCTION: Increments the reference count for an object and returns a
759 * pointer to its body
761 * Handle = Handle for the object
762 * DesiredAccess = Desired access to the object
765 * Object (OUT) = Points to the object body on return
766 * HandleInformation (OUT) = Contains information about the handle
771 PHANDLE_REP HandleRep
;
772 POBJECT_HEADER ObjectHeader
;
775 ACCESS_MASK GrantedAccess
;
779 ASSERT_IRQL(PASSIVE_LEVEL
);
781 DPRINT("ObReferenceObjectByHandle(Handle %x, DesiredAccess %x, "
782 "ObjectType %x, AccessMode %d, Object %x)\n",Handle
,DesiredAccess
,
783 ObjectType
,AccessMode
,Object
);
786 * Handle special handle names
788 if (Handle
== NtCurrentProcess() &&
789 (ObjectType
== PsProcessType
|| ObjectType
== NULL
))
791 DPRINT("Reference from %x\n", ((PULONG
)&Handle
)[-1]);
793 Status
= ObReferenceObjectByPointer(PsGetCurrentProcess(),
797 if (! NT_SUCCESS(Status
))
802 if (HandleInformation
!= NULL
)
804 HandleInformation
->HandleAttributes
= 0; /* FIXME? */
805 HandleInformation
->GrantedAccess
= PROCESS_ALL_ACCESS
;
808 *Object
= PsGetCurrentProcess();
809 DPRINT("Referencing current process %x\n", PsGetCurrentProcess());
810 return STATUS_SUCCESS
;
812 else if (Handle
== NtCurrentProcess())
815 return(STATUS_OBJECT_TYPE_MISMATCH
);
817 if (Handle
== NtCurrentThread() &&
818 (ObjectType
== PsThreadType
|| ObjectType
== NULL
))
820 Status
= ObReferenceObjectByPointer(PsGetCurrentThread(),
824 if (! NT_SUCCESS(Status
))
829 if (HandleInformation
!= NULL
)
831 HandleInformation
->HandleAttributes
= 0; /* FIXME? */
832 HandleInformation
->GrantedAccess
= THREAD_ALL_ACCESS
;
835 *Object
= PsGetCurrentThread();
837 return STATUS_SUCCESS
;
839 else if (Handle
== NtCurrentThread())
842 return(STATUS_OBJECT_TYPE_MISMATCH
);
845 KeAcquireSpinLock(&PsGetCurrentProcess()->HandleTable
.ListLock
,
847 HandleRep
= ObpGetObjectByHandle(&PsGetCurrentProcess()->HandleTable
,
850 if (HandleRep
== NULL
|| HandleRep
->ObjectBody
== 0)
852 KeReleaseSpinLock(&PsGetCurrentProcess()->HandleTable
.ListLock
,
854 return(STATUS_INVALID_HANDLE
);
856 ObjectBody
= OB_ENTRY_TO_POINTER(HandleRep
->ObjectBody
);
857 DPRINT("ObjectBody %p\n",ObjectBody
);
858 ObjectHeader
= BODY_TO_HEADER(ObjectBody
);
859 DPRINT("ObjectHeader->RefCount %lu\n",ObjectHeader
->RefCount
);
860 ObReferenceObjectByPointer(ObjectBody
,
864 Attributes
= (ULONG_PTR
)HandleRep
->ObjectBody
& OB_HANDLE_FLAG_MASK
;
865 GrantedAccess
= HandleRep
->GrantedAccess
;
866 KeReleaseSpinLock(&PsGetCurrentProcess()->HandleTable
.ListLock
,
869 ObjectHeader
= BODY_TO_HEADER(ObjectBody
);
870 DPRINT("ObjectHeader->RefCount %lu\n",ObjectHeader
->RefCount
);
872 if (ObjectType
!= NULL
&& ObjectType
!= ObjectHeader
->ObjectType
)
875 return(STATUS_OBJECT_TYPE_MISMATCH
);
878 if (ObjectHeader
->ObjectType
== PsProcessType
)
880 DPRINT("Reference from %x\n", ((PULONG
)&Handle
)[-1]);
883 if (DesiredAccess
&& AccessMode
== UserMode
)
885 RtlMapGenericMask(&DesiredAccess
, ObjectHeader
->ObjectType
->Mapping
);
887 if (!(GrantedAccess
& DesiredAccess
) &&
888 !((~GrantedAccess
) & DesiredAccess
))
891 return(STATUS_ACCESS_DENIED
);
895 if (HandleInformation
!= NULL
)
897 HandleInformation
->HandleAttributes
= Attributes
;
898 HandleInformation
->GrantedAccess
= GrantedAccess
;
901 *Object
= ObjectBody
;
904 return(STATUS_SUCCESS
);
908 /**********************************************************************
913 * Closes a handle reference to an object.
925 NtClose(IN HANDLE Handle
)
928 POBJECT_HEADER Header
;
931 ASSERT_IRQL(PASSIVE_LEVEL
);
933 DPRINT("NtClose(Handle %x)\n",Handle
);
935 Status
= ObDeleteHandle(PsGetCurrentProcess(),
938 if (!NT_SUCCESS(Status
))
940 if(((PEPROCESS
)(KeGetCurrentThread()->ApcState
.Process
))->ExceptionPort
)
941 KeRaiseUserException(Status
);
945 Header
= BODY_TO_HEADER(ObjectBody
);
947 DPRINT("Dereferencing %x\n", ObjectBody
);
948 ObDereferenceObject(ObjectBody
);
950 return(STATUS_SUCCESS
);
958 ObInsertObject(IN PVOID Object
,
959 IN PACCESS_STATE PassedAccessState OPTIONAL
,
960 IN ACCESS_MASK DesiredAccess
,
961 IN ULONG AdditionalReferences
,
962 OUT PVOID
* ReferencedObject OPTIONAL
,
965 POBJECT_HEADER ObjectHeader
;
968 Access
= DesiredAccess
;
969 ObjectHeader
= BODY_TO_HEADER(Object
);
971 RtlMapGenericMask(&Access
,
972 ObjectHeader
->ObjectType
->Mapping
);
974 return(ObCreateHandle(PsGetCurrentProcess(),
977 ObjectHeader
->Inherit
,
983 ObpGetHandleCountByHandleTable(PHANDLE_TABLE HandleTable
)
986 POBJECT_HEADER Header
;
993 KeAcquireSpinLock(&HandleTable
->ListLock
, &OldIrql
);
995 current
= HandleTable
->ListHead
.Flink
;
996 while (current
!= &HandleTable
->ListHead
)
998 blk
= CONTAINING_RECORD(current
, HANDLE_BLOCK
, entry
);
1000 for (i
= 0; i
< HANDLE_BLOCK_ENTRIES
; i
++)
1002 ObjectBody
= OB_ENTRY_TO_POINTER(blk
->handles
[i
].ObjectBody
);
1003 if (ObjectBody
!= NULL
)
1005 Header
= BODY_TO_HEADER(ObjectBody
);
1007 /* Make sure this is real. */
1008 if (Header
->ObjectType
!= NULL
)
1013 current
= current
->Flink
;
1016 KeReleaseSpinLock(&HandleTable
->ListLock
,