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 /* TYPES *******************************************************************/
39 * PURPOSE: Defines a handle
41 typedef struct _HANDLE_ENTRY
44 ACCESS_MASK GrantedAccess
;
45 } HANDLE_ENTRY
, *PHANDLE_ENTRY
;
47 #define HANDLE_BLOCK_ENTRIES \
49 (sizeof(LIST_ENTRY) + sizeof(ULONG))) / sizeof(HANDLE_ENTRY))
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_ENTRY handles
[HANDLE_BLOCK_ENTRIES
];
71 } HANDLE_BLOCK
, *PHANDLE_BLOCK
;
74 /* GLOBALS *******************************************************************/
76 #define TAG_HANDLE_TABLE TAG('H', 'T', 'B', 'L')
78 /* FUNCTIONS ***************************************************************/
82 * FUNCTION: Get the data structure for a handle
84 * Process = Process to get the handle for
86 * ARGUMENTS: A pointer to the information about the handle on success,
90 ObpGetObjectByHandle(PHANDLE_TABLE HandleTable
,
95 unsigned int handle
= (((unsigned int)h
) >> 2) - 1;
96 unsigned int count
= handle
/ HANDLE_BLOCK_ENTRIES
;
97 HANDLE_BLOCK
* blk
= NULL
;
100 DPRINT("ObpGetObjectByHandle(HandleTable %x, h %x)\n",HandleTable
,h
);
102 current
= HandleTable
->ListHead
.Flink
;
103 DPRINT("current %x\n",current
);
105 for (i
= 0; i
< count
; i
++)
107 current
= current
->Flink
;
108 if (current
== (&(HandleTable
->ListHead
)))
114 blk
= CONTAINING_RECORD(current
,HANDLE_BLOCK
,entry
);
117 DPRINT("object: %p\n",&(blk
->handles
[handle
%HANDLE_BLOCK_ENTRIES
]));
118 return(&(blk
->handles
[handle
%HANDLE_BLOCK_ENTRIES
]));
123 ObpQueryHandleAttributes(HANDLE Handle
,
124 POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo
)
128 PHANDLE_ENTRY HandleEntry
;
130 DPRINT("ObpQueryHandleAttributes(Handle %x)\n", Handle
);
132 Process
= PsGetCurrentProcess();
134 KeAcquireSpinLock(&Process
->HandleTable
.ListLock
, &oldIrql
);
135 HandleEntry
= ObpGetObjectByHandle(&Process
->HandleTable
,
138 if (HandleEntry
== NULL
)
140 KeReleaseSpinLock(&Process
->HandleTable
.ListLock
, oldIrql
);
141 return STATUS_INVALID_HANDLE
;
144 HandleInfo
->Inherit
=
145 ((ULONG_PTR
)HandleEntry
->ObjectBody
& OB_HANDLE_FLAG_INHERIT
);
146 HandleInfo
->ProtectFromClose
=
147 ((ULONG_PTR
)HandleEntry
->ObjectBody
& OB_HANDLE_FLAG_PROTECT
);
149 KeReleaseSpinLock(&Process
->HandleTable
.ListLock
, oldIrql
);
151 return STATUS_SUCCESS
;
156 ObpSetHandleAttributes(HANDLE Handle
,
157 POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo
)
159 PHANDLE_ENTRY HandleEntry
;
163 DPRINT("ObpQueryHandleAttributes(Handle %x)\n", Handle
);
165 Process
= PsGetCurrentProcess();
167 KeAcquireSpinLock(&Process
->HandleTable
.ListLock
, &oldIrql
);
168 HandleEntry
= ObpGetObjectByHandle(&Process
->HandleTable
,
171 if (HandleEntry
== NULL
)
173 KeReleaseSpinLock(&Process
->HandleTable
.ListLock
, oldIrql
);
174 return STATUS_INVALID_HANDLE
;
177 if (HandleInfo
->Inherit
)
178 HandleEntry
->ObjectBody
= (PVOID
)((ULONG_PTR
)HandleEntry
->ObjectBody
| OB_HANDLE_FLAG_INHERIT
);
180 HandleEntry
->ObjectBody
= (PVOID
)((ULONG_PTR
)HandleEntry
->ObjectBody
& ~OB_HANDLE_FLAG_INHERIT
);
182 if (HandleInfo
->ProtectFromClose
)
183 HandleEntry
->ObjectBody
= (PVOID
)((ULONG_PTR
)HandleEntry
->ObjectBody
| OB_HANDLE_FLAG_PROTECT
);
185 HandleEntry
->ObjectBody
= (PVOID
)((ULONG_PTR
)HandleEntry
->ObjectBody
& ~OB_HANDLE_FLAG_PROTECT
);
187 /* FIXME: Do we need to set anything in the object header??? */
189 KeReleaseSpinLock(&Process
->HandleTable
.ListLock
, oldIrql
);
191 return STATUS_SUCCESS
;
196 ObDuplicateObject(PEPROCESS SourceProcess
,
197 PEPROCESS TargetProcess
,
199 PHANDLE TargetHandle
,
200 ACCESS_MASK DesiredAccess
,
201 BOOLEAN InheritHandle
,
205 PHANDLE_ENTRY SourceHandleEntry
;
208 KeAcquireSpinLock(&SourceProcess
->HandleTable
.ListLock
, &oldIrql
);
209 SourceHandleEntry
= ObpGetObjectByHandle(&SourceProcess
->HandleTable
,
212 if (SourceHandleEntry
== NULL
)
214 KeReleaseSpinLock(&SourceProcess
->HandleTable
.ListLock
, oldIrql
);
215 return STATUS_INVALID_HANDLE
;
218 ObjectBody
= OB_ENTRY_TO_POINTER(SourceHandleEntry
->ObjectBody
);
219 ObReferenceObjectByPointer(ObjectBody
,
224 if (Options
& DUPLICATE_SAME_ACCESS
)
226 DesiredAccess
= SourceHandleEntry
->GrantedAccess
;
229 KeReleaseSpinLock(&SourceProcess
->HandleTable
.ListLock
, oldIrql
);
230 ObCreateHandle(TargetProcess
,
236 if (Options
& DUPLICATE_CLOSE_SOURCE
)
238 ZwClose(SourceHandle
);
241 ObDereferenceObject(ObjectBody
);
243 return STATUS_SUCCESS
;
250 NtDuplicateObject (IN HANDLE SourceProcessHandle
,
251 IN HANDLE SourceHandle
,
252 IN HANDLE TargetProcessHandle
,
253 OUT PHANDLE UnsafeTargetHandle
,
254 IN ACCESS_MASK DesiredAccess
,
255 IN BOOLEAN InheritHandle
,
258 * FUNCTION: Copies a handle from one process space to another
260 * SourceProcessHandle = The source process owning the handle. The
261 * source process should have opened
262 * the SourceHandle with PROCESS_DUP_HANDLE
264 * SourceHandle = The handle to the object.
265 * TargetProcessHandle = The destination process owning the handle
266 * TargetHandle (OUT) = Caller should supply storage for the
268 * DesiredAccess = The desired access to the handle.
269 * InheritHandle = Indicates wheter the new handle will be inheritable
271 * Options = Specifies special actions upon duplicating the handle.
272 * Can be one of the values DUPLICATE_CLOSE_SOURCE |
273 * DUPLICATE_SAME_ACCESS. DUPLICATE_CLOSE_SOURCE specifies
274 * that the source handle should be closed after duplicating.
275 * DUPLICATE_SAME_ACCESS specifies to ignore the
276 * DesiredAccess paramter and just grant the same access to
279 * REMARKS: This function maps to the win32 DuplicateHandle.
282 PEPROCESS SourceProcess
;
283 PEPROCESS TargetProcess
;
284 PHANDLE_ENTRY SourceHandleEntry
;
292 Status
= ObReferenceObjectByHandle(SourceProcessHandle
,
296 (PVOID
*)&SourceProcess
,
298 if (!NT_SUCCESS(Status
))
303 Status
= ObReferenceObjectByHandle(TargetProcessHandle
,
307 (PVOID
*)&TargetProcess
,
309 if (!NT_SUCCESS(Status
))
311 ObDereferenceObject(SourceProcess
);
315 /* Check for magic handle first */
316 if (SourceHandle
== NtCurrentThread())
318 ObReferenceObjectByHandle(SourceHandle
,
325 ObCreateHandle(TargetProcess
,
333 KeAcquireSpinLock(&SourceProcess
->HandleTable
.ListLock
, &oldIrql
);
334 SourceHandleEntry
= ObpGetObjectByHandle(&SourceProcess
->HandleTable
,
337 if (SourceHandleEntry
== NULL
)
339 KeReleaseSpinLock(&SourceProcess
->HandleTable
.ListLock
, oldIrql
);
340 ObDereferenceObject(SourceProcess
);
341 ObDereferenceObject(TargetProcess
);
342 return(STATUS_INVALID_HANDLE
);
344 ObjectBody
= OB_ENTRY_TO_POINTER(SourceHandleEntry
->ObjectBody
);
345 ObReferenceObjectByPointer(ObjectBody
,
350 if (Options
& DUPLICATE_SAME_ACCESS
)
352 DesiredAccess
= SourceHandleEntry
->GrantedAccess
;
355 KeReleaseSpinLock(&SourceProcess
->HandleTable
.ListLock
, oldIrql
);
357 ObCreateHandle(TargetProcess
,
364 if (Options
& DUPLICATE_CLOSE_SOURCE
)
366 ZwClose(SourceHandle
);
369 ObDereferenceObject(TargetProcess
);
370 ObDereferenceObject(SourceProcess
);
371 ObDereferenceObject(ObjectBody
);
373 Status
= MmCopyToCaller(UnsafeTargetHandle
, &TargetHandle
, sizeof(HANDLE
));
374 if (!NT_SUCCESS(Status
))
379 return(STATUS_SUCCESS
);
382 VOID
ObCloseAllHandles(PEPROCESS Process
)
385 PHANDLE_TABLE HandleTable
;
386 PLIST_ENTRY current_entry
;
387 PHANDLE_BLOCK current
;
391 DPRINT("ObCloseAllHandles(Process %x)\n", Process
);
393 HandleTable
= &Process
->HandleTable
;
395 KeAcquireSpinLock(&HandleTable
->ListLock
, &oldIrql
);
397 current_entry
= HandleTable
->ListHead
.Flink
;
399 while (current_entry
!= &HandleTable
->ListHead
)
401 current
= CONTAINING_RECORD(current_entry
, HANDLE_BLOCK
, entry
);
403 for (i
= 0; i
< HANDLE_BLOCK_ENTRIES
; i
++)
405 ObjectBody
= OB_ENTRY_TO_POINTER(current
->handles
[i
].ObjectBody
);
407 if (ObjectBody
!= NULL
)
409 POBJECT_HEADER Header
= BODY_TO_HEADER(ObjectBody
);
412 if (Header
->ObjectType
== PsProcessType
||
413 Header
->ObjectType
== PsThreadType
)
415 DPRINT("Deleting handle to %x\n", ObjectBody
);
419 ObReferenceObjectByPointer(ObjectBody
,
423 InterlockedDecrement(&Header
->HandleCount
);
424 current
->handles
[i
].ObjectBody
= NULL
;
426 KeReleaseSpinLock(&HandleTable
->ListLock
, oldIrql
);
427 if ((Header
->ObjectType
!= NULL
) &&
428 (Header
->ObjectType
->Close
!= NULL
))
430 Header
->ObjectType
->Close(ObjectBody
,
431 Header
->HandleCount
);
434 ObDereferenceObject(ObjectBody
);
435 KeAcquireSpinLock(&HandleTable
->ListLock
, &oldIrql
);
436 current_entry
= &HandleTable
->ListHead
;
441 current_entry
= current_entry
->Flink
;
443 KeReleaseSpinLock(&HandleTable
->ListLock
, oldIrql
);
444 DPRINT("ObCloseAllHandles() finished\n");
445 DPRINT("Type %x\n", BODY_TO_HEADER(Process
)->ObjectType
);
448 VOID
ObDeleteHandleTable(PEPROCESS Process
)
450 * FUNCTION: Deletes the handle table associated with a process
453 PLIST_ENTRY current
= NULL
;
454 PHANDLE_TABLE HandleTable
= NULL
;
456 ObCloseAllHandles(Process
);
458 HandleTable
= &Process
->HandleTable
;
459 current
= RemoveHeadList(&HandleTable
->ListHead
);
461 while (current
!= &HandleTable
->ListHead
)
463 HANDLE_BLOCK
* HandleBlock
= CONTAINING_RECORD(current
,
466 DPRINT("Freeing %x\n", HandleBlock
);
467 ExFreePool(HandleBlock
);
469 current
= RemoveHeadList(&HandleTable
->ListHead
);
474 VOID
ObCreateHandleTable(PEPROCESS Parent
,
478 * FUNCTION: Creates a handle table for a process
480 * Parent = Parent process (or NULL if this is the first process)
481 * Inherit = True if the process should inherit its parent's handles
482 * Process = Process whose handle table is to be created
485 PHANDLE_TABLE ParentHandleTable
, HandleTable
;
487 PLIST_ENTRY parent_current
;
489 PHANDLE_BLOCK current_block
, new_block
;
491 DPRINT("ObCreateHandleTable(Parent %x, Inherit %d, Process %x)\n",
492 Parent
,Inherit
,Process
);
494 InitializeListHead(&(Process
->HandleTable
.ListHead
));
495 KeInitializeSpinLock(&(Process
->HandleTable
.ListLock
));
499 ParentHandleTable
= &Parent
->HandleTable
;
500 HandleTable
= &Process
->HandleTable
;
502 KeAcquireSpinLock(&Parent
->HandleTable
.ListLock
, &oldIrql
);
503 KeAcquireSpinLockAtDpcLevel(&Process
->HandleTable
.ListLock
);
505 parent_current
= ParentHandleTable
->ListHead
.Flink
;
507 while (parent_current
!= &ParentHandleTable
->ListHead
)
509 current_block
= CONTAINING_RECORD(parent_current
,
512 new_block
= ExAllocatePoolWithTag(NonPagedPool
,
513 sizeof(HANDLE_BLOCK
),
515 if (new_block
== NULL
)
519 RtlZeroMemory(new_block
, sizeof(HANDLE_BLOCK
));
521 for (i
=0; i
<HANDLE_BLOCK_ENTRIES
; i
++)
523 if (current_block
->handles
[i
].ObjectBody
)
525 if ((ULONG_PTR
)current_block
->handles
[i
].ObjectBody
& OB_HANDLE_FLAG_INHERIT
)
527 new_block
->handles
[i
].ObjectBody
=
528 current_block
->handles
[i
].ObjectBody
;
529 new_block
->handles
[i
].GrantedAccess
=
530 current_block
->handles
[i
].GrantedAccess
;
531 InterlockedIncrement(&(BODY_TO_HEADER(OB_ENTRY_TO_POINTER(current_block
->handles
[i
].ObjectBody
))->HandleCount
));
535 InsertTailList(&Process
->HandleTable
.ListHead
, &new_block
->entry
);
536 parent_current
= parent_current
->Flink
;
538 KeReleaseSpinLockFromDpcLevel(&Process
->HandleTable
.ListLock
);
539 KeReleaseSpinLock(&Parent
->HandleTable
.ListLock
, oldIrql
);
545 ObDeleteHandle(PEPROCESS Process
,
549 PHANDLE_ENTRY HandleEntry
;
552 PHANDLE_TABLE HandleTable
;
553 POBJECT_HEADER Header
;
558 DPRINT("ObDeleteHandle(Handle %x)\n",Handle
);
560 HandleTable
= &Process
->HandleTable
;
562 KeAcquireSpinLock(&HandleTable
->ListLock
, &oldIrql
);
564 HandleEntry
= ObpGetObjectByHandle(HandleTable
, Handle
, &Block
);
565 if (HandleEntry
== NULL
)
567 KeReleaseSpinLock(&HandleTable
->ListLock
, oldIrql
);
569 return STATUS_INVALID_HANDLE
;
572 if ((ULONG_PTR
)HandleEntry
->ObjectBody
& OB_HANDLE_FLAG_PROTECT
)
574 KeReleaseSpinLock(&HandleTable
->ListLock
, oldIrql
);
576 return STATUS_HANDLE_NOT_CLOSABLE
;
579 Body
= OB_ENTRY_TO_POINTER(HandleEntry
->ObjectBody
);
580 DPRINT("ObjectBody %x\n", Body
);
583 KeReleaseSpinLock(&HandleTable
->ListLock
, oldIrql
);
585 return STATUS_UNSUCCESSFUL
;
588 Header
= BODY_TO_HEADER(Body
);
589 ObReferenceObjectByPointer(Body
,
593 InterlockedDecrement(&Header
->HandleCount
);
594 HandleEntry
->ObjectBody
= NULL
;
596 Block
->allocation_count
--;
597 Block
->allocation_hint
= (ULONG_PTR
)Handle
% HANDLE_BLOCK_ENTRIES
;
599 KeReleaseSpinLock(&HandleTable
->ListLock
, oldIrql
);
601 if ((Header
->ObjectType
!= NULL
) &&
602 (Header
->ObjectType
->Close
!= NULL
))
604 Header
->ObjectType
->Close(Body
, Header
->HandleCount
);
609 DPRINT("Finished ObDeleteHandle()\n");
611 return STATUS_SUCCESS
;
616 ObCreateHandle(PEPROCESS Process
,
618 ACCESS_MASK GrantedAccess
,
620 PHANDLE HandleReturn
)
622 * FUNCTION: Add a handle referencing an object
624 * obj = Object body that the handle should refer to
625 * RETURNS: The created handle
626 * NOTE: The handle is valid only in the context of the current process
630 unsigned int handle
=1;
631 unsigned int Loop
, Index
, MaxIndex
;
632 HANDLE_BLOCK
* new_blk
= NULL
;
633 PHANDLE_TABLE HandleTable
;
638 DPRINT("ObCreateHandle(Process %x, obj %x)\n",Process
,ObjectBody
);
642 if (ObjectBody
!= NULL
)
644 InterlockedIncrement(&(BODY_TO_HEADER(ObjectBody
)->HandleCount
));
646 HandleTable
= &Process
->HandleTable
;
647 KeAcquireSpinLock(&HandleTable
->ListLock
, &oldlvl
);
648 current
= HandleTable
->ListHead
.Flink
;
650 * Scan through the currently allocated handle blocks looking for a free
653 while (current
!= (&HandleTable
->ListHead
))
655 HANDLE_BLOCK
* blk
= CONTAINING_RECORD(current
,HANDLE_BLOCK
,entry
);
657 DPRINT("Current %x\n",current
);
659 if (blk
->allocation_count
== HANDLE_BLOCK_ENTRIES
)
661 handle
= handle
+ HANDLE_BLOCK_ENTRIES
;
662 current
= current
->Flink
;
666 Index
= blk
->allocation_hint
;
667 MaxIndex
= HANDLE_BLOCK_ENTRIES
;
668 for (Loop
= 0; Loop
< 2; Loop
++)
670 for (Index
= 0; Index
< MaxIndex
; Index
++)
672 DPRINT("Considering slot %d containing %x\n", Index
, blk
->handles
[Index
]);
673 if (blk
->handles
[Index
].ObjectBody
== NULL
)
675 blk
->handles
[Index
].ObjectBody
= OB_POINTER_TO_ENTRY(ObjectBody
);
677 blk
->handles
[Index
].ObjectBody
= (PVOID
)((ULONG_PTR
)blk
->handles
[Index
].ObjectBody
| OB_HANDLE_FLAG_INHERIT
);
678 blk
->handles
[Index
].GrantedAccess
= GrantedAccess
;
679 blk
->allocation_hint
= Index
+ 1;
680 blk
->allocation_count
++;
681 KeReleaseSpinLock(&HandleTable
->ListLock
, oldlvl
);
682 *HandleReturn
= (HANDLE
)((handle
+ Index
) << 2);
683 return(STATUS_SUCCESS
);
687 MaxIndex
= blk
->allocation_hint
;
690 handle
= handle
+ HANDLE_BLOCK_ENTRIES
;
691 current
= current
->Flink
;
695 * Add a new handle block to the end of the list
698 (HANDLE_BLOCK
*)ExAllocatePoolWithTag(NonPagedPool
,sizeof(HANDLE_BLOCK
),
702 *HandleReturn
= (PHANDLE
)NULL
;
703 return(STATUS_INSUFFICIENT_RESOURCES
);
705 RtlZeroMemory(new_blk
,sizeof(HANDLE_BLOCK
));
706 InsertTailList(&(Process
->HandleTable
.ListHead
),
708 new_blk
->handles
[0].ObjectBody
= OB_POINTER_TO_ENTRY(ObjectBody
);
710 new_blk
->handles
[0].ObjectBody
= (PVOID
)((ULONG_PTR
)new_blk
->handles
[0].ObjectBody
| OB_HANDLE_FLAG_INHERIT
);
711 new_blk
->handles
[0].GrantedAccess
= GrantedAccess
;
712 new_blk
->allocation_hint
= 1;
713 new_blk
->allocation_count
++;
714 KeReleaseSpinLock(&HandleTable
->ListLock
, oldlvl
);
715 *HandleReturn
= (HANDLE
)(handle
<< 2);
716 return(STATUS_SUCCESS
);
724 ObQueryObjectAuditingByHandle(IN HANDLE Handle
,
725 OUT PBOOLEAN GenerateOnClose
)
729 PHANDLE_ENTRY HandleEntry
;
733 DPRINT("ObQueryObjectAuditingByHandle(Handle %x)\n", Handle
);
735 Process
= PsGetCurrentProcess();
737 KeAcquireSpinLock(&Process
->HandleTable
.ListLock
, &oldIrql
);
738 HandleEntry
= ObpGetObjectByHandle(&Process
->HandleTable
,
741 if (HandleEntry
== NULL
)
743 KeReleaseSpinLock(&Process
->HandleTable
.ListLock
, oldIrql
);
744 return STATUS_INVALID_HANDLE
;
747 *GenerateOnClose
= (BOOLEAN
)((ULONG_PTR
)HandleEntry
->ObjectBody
| OB_HANDLE_FLAG_AUDIT
);
749 KeReleaseSpinLock(&Process
->HandleTable
.ListLock
, oldIrql
);
751 return STATUS_SUCCESS
;
756 * FUNCTION: Increments the reference count for an object and returns a
757 * pointer to its body
759 * Handle = Handle for the object
760 * DesiredAccess = Desired access to the object
763 * Object (OUT) = Points to the object body on return
764 * HandleInformation (OUT) = Contains information about the handle
771 ObReferenceObjectByHandle(HANDLE Handle
,
772 ACCESS_MASK DesiredAccess
,
773 POBJECT_TYPE ObjectType
,
774 KPROCESSOR_MODE AccessMode
,
776 POBJECT_HANDLE_INFORMATION HandleInformation
)
778 PHANDLE_ENTRY HandleEntry
;
779 POBJECT_HEADER ObjectHeader
;
782 ACCESS_MASK GrantedAccess
;
788 DPRINT("ObReferenceObjectByHandle(Handle %x, DesiredAccess %x, "
789 "ObjectType %x, AccessMode %d, Object %x)\n",Handle
,DesiredAccess
,
790 ObjectType
,AccessMode
,Object
);
793 * Handle special handle names
795 if (Handle
== NtCurrentProcess() &&
796 (ObjectType
== PsProcessType
|| ObjectType
== NULL
))
798 DPRINT("Reference from %x\n", ((PULONG
)&Handle
)[-1]);
800 Status
= ObReferenceObjectByPointer(PsGetCurrentProcess(),
804 if (! NT_SUCCESS(Status
))
809 if (HandleInformation
!= NULL
)
811 HandleInformation
->HandleAttributes
= 0; /* FIXME? */
812 HandleInformation
->GrantedAccess
= PROCESS_ALL_ACCESS
;
815 *Object
= PsGetCurrentProcess();
816 DPRINT("Referencing current process %x\n", PsGetCurrentProcess());
817 return STATUS_SUCCESS
;
819 else if (Handle
== NtCurrentProcess())
822 return(STATUS_OBJECT_TYPE_MISMATCH
);
825 if (Handle
== NtCurrentThread() &&
826 (ObjectType
== PsThreadType
|| ObjectType
== NULL
))
828 Status
= ObReferenceObjectByPointer(PsGetCurrentThread(),
832 if (! NT_SUCCESS(Status
))
837 if (HandleInformation
!= NULL
)
839 HandleInformation
->HandleAttributes
= 0; /* FIXME? */
840 HandleInformation
->GrantedAccess
= THREAD_ALL_ACCESS
;
843 *Object
= PsGetCurrentThread();
845 return STATUS_SUCCESS
;
847 else if (Handle
== NtCurrentThread())
850 return(STATUS_OBJECT_TYPE_MISMATCH
);
853 KeAcquireSpinLock(&PsGetCurrentProcess()->HandleTable
.ListLock
,
855 HandleEntry
= ObpGetObjectByHandle(&PsGetCurrentProcess()->HandleTable
,
858 if (HandleEntry
== NULL
|| HandleEntry
->ObjectBody
== 0)
860 KeReleaseSpinLock(&PsGetCurrentProcess()->HandleTable
.ListLock
,
862 return(STATUS_INVALID_HANDLE
);
864 ObjectBody
= OB_ENTRY_TO_POINTER(HandleEntry
->ObjectBody
);
865 DPRINT("ObjectBody %p\n",ObjectBody
);
866 ObjectHeader
= BODY_TO_HEADER(ObjectBody
);
867 DPRINT("ObjectHeader->RefCount %lu\n",ObjectHeader
->RefCount
);
868 ObReferenceObjectByPointer(ObjectBody
,
872 Attributes
= (ULONG_PTR
)HandleEntry
->ObjectBody
& OB_HANDLE_FLAG_MASK
;
873 GrantedAccess
= HandleEntry
->GrantedAccess
;
874 KeReleaseSpinLock(&PsGetCurrentProcess()->HandleTable
.ListLock
,
877 ObjectHeader
= BODY_TO_HEADER(ObjectBody
);
878 DPRINT("ObjectHeader->RefCount %lu\n",ObjectHeader
->RefCount
);
880 if (ObjectType
!= NULL
&& ObjectType
!= ObjectHeader
->ObjectType
)
883 return(STATUS_OBJECT_TYPE_MISMATCH
);
886 if (ObjectHeader
->ObjectType
== PsProcessType
)
888 DPRINT("Reference from %x\n", ((PULONG
)&Handle
)[-1]);
891 if (DesiredAccess
&& AccessMode
== UserMode
)
893 RtlMapGenericMask(&DesiredAccess
, ObjectHeader
->ObjectType
->Mapping
);
895 if (!(GrantedAccess
& DesiredAccess
) &&
896 !((~GrantedAccess
) & DesiredAccess
))
899 return(STATUS_ACCESS_DENIED
);
903 if (HandleInformation
!= NULL
)
905 HandleInformation
->HandleAttributes
= Attributes
;
906 HandleInformation
->GrantedAccess
= GrantedAccess
;
909 *Object
= ObjectBody
;
912 return(STATUS_SUCCESS
);
916 /**********************************************************************
921 * Closes a handle reference to an object.
933 NtClose(IN HANDLE Handle
)
936 POBJECT_HEADER Header
;
941 DPRINT("NtClose(Handle %x)\n",Handle
);
943 Status
= ObDeleteHandle(PsGetCurrentProcess(),
946 if (!NT_SUCCESS(Status
))
948 if(((PEPROCESS
)(KeGetCurrentThread()->ApcState
.Process
))->ExceptionPort
)
949 KeRaiseUserException(Status
);
953 Header
= BODY_TO_HEADER(ObjectBody
);
955 DPRINT("Dereferencing %x\n", ObjectBody
);
956 ObDereferenceObject(ObjectBody
);
958 return(STATUS_SUCCESS
);
966 ObInsertObject(IN PVOID Object
,
967 IN PACCESS_STATE PassedAccessState OPTIONAL
,
968 IN ACCESS_MASK DesiredAccess
,
969 IN ULONG AdditionalReferences
,
970 OUT PVOID
* ReferencedObject OPTIONAL
,
973 POBJECT_HEADER ObjectHeader
;
978 Access
= DesiredAccess
;
979 ObjectHeader
= BODY_TO_HEADER(Object
);
981 RtlMapGenericMask(&Access
,
982 ObjectHeader
->ObjectType
->Mapping
);
984 return(ObCreateHandle(PsGetCurrentProcess(),
987 ObjectHeader
->Inherit
,
993 ObpGetHandleCountByHandleTable(PHANDLE_TABLE HandleTable
)
996 POBJECT_HEADER Header
;
1003 KeAcquireSpinLock(&HandleTable
->ListLock
, &OldIrql
);
1005 current
= HandleTable
->ListHead
.Flink
;
1006 while (current
!= &HandleTable
->ListHead
)
1008 blk
= CONTAINING_RECORD(current
, HANDLE_BLOCK
, entry
);
1010 for (i
= 0; i
< HANDLE_BLOCK_ENTRIES
; i
++)
1012 ObjectBody
= OB_ENTRY_TO_POINTER(blk
->handles
[i
].ObjectBody
);
1013 if (ObjectBody
!= NULL
)
1015 Header
= BODY_TO_HEADER(ObjectBody
);
1017 /* Make sure this is real. Okay! For real!*/
1018 if ((Header
->ObjectType
!= NULL
) &&
1019 (Header
->ObjectType
->Close
!= NULL
))
1024 current
= current
->Flink
;
1027 KeReleaseSpinLock(&HandleTable
->ListLock
,
1034 * FUNCTION: Searches the handle table of a specified process whether it contains a
1035 * valid handle to the Object we're looking for. If not, it'll create one.
1038 * The parameters of this function is basically a mixture of some of the parameters
1039 * of ObReferenceObjectByHandle() and ObReferenceObjectByPointer(). A little thinking
1040 * about what this function does (by it's name) makes clear what parameters it requires.
1041 * For example the AccessMode parameter of ObReferenceObjectByHandle/Pointer() is not
1042 * required at all as it only has influence on the object security. This function doesn't
1043 * want to get access to an object, it just looks for a valid handle and if it can't find
1044 * one, it'll just create one. It wouldn't make sense to check for security again as the
1045 * caller already has a pointer to the object.
1047 * A test on an XP machine shows that this prototype appears to be correct.
1050 * Process = This parameter simply describes in which handle table we're looking
1051 * for a handle to the object.
1052 * Object = The object pointer that we're looking for
1053 * ObjectType = Just a sanity check as ObReferenceObjectByHandle() and
1054 * ObReferenceObjectByPointer() provides.
1055 * HandleInformation = This one has to be the opposite meaning of the usage in
1056 * ObReferenceObjectByHandle(). If we actually found a valid
1057 * handle in the table, we need to check against the information
1058 * provided so we make sure this handle has all access rights
1059 * (and attributes?!) we need. If they don't match, we can't
1060 * use this handle and keep looking because the caller is likely
1061 * to depend on these access rights.
1062 * HandleReturn = The last parameter is the same as in ObCreateHandle(). If we could
1063 * find a suitable handle in the handle table, return this handle, if
1064 * not, we'll just create one using ObCreateHandle() with all access
1065 * rights the caller needs.
1072 ObFindHandleForObject(IN PEPROCESS Process
,
1074 IN POBJECT_TYPE ObjectType
,
1075 IN POBJECT_HANDLE_INFORMATION HandleInformation
,
1076 OUT PHANDLE HandleReturn
)
1079 return STATUS_UNSUCCESSFUL
;
1083 ObpGetNextHandleByProcessCount(PSYSTEM_HANDLE_TABLE_ENTRY_INFO pshi
,
1090 // pshi->HandleValue;
1093 This will never work with ROS! M$, I guess uses 0 -> 65535.
1094 Ros uses 0 -> 4294967295!
1097 P
= (ULONG
) Process
->UniqueProcessId
;
1098 pshi
->UniqueProcessId
= (USHORT
) P
;
1100 KeAcquireSpinLock( &Process
->HandleTable
.ListLock
, &oldIrql
);
1102 // pshi->GrantedAccess;
1104 // pshi->ObjectTypeIndex;
1105 // pshi->HandleAttributes;
1107 KeReleaseSpinLock( &Process
->HandleTable
.ListLock
, oldIrql
);