@implemented and @unimplemented comments for ntoskrnl/ob/*.c
[reactos.git] / reactos / ntoskrnl / ob / handle.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 */
19 /* $Id: handle.c,v 1.47 2003/07/10 21:34:29 royce Exp $
20 *
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)
26 * REVISION HISTORY:
27 * 17/06/98: Created
28 */
29
30 /* INCLUDES ****************************************************************/
31
32 #define NTOS_MODE_KERNEL
33 #include <ntos.h>
34 #include <internal/ob.h>
35 #include <internal/ps.h>
36 #include <internal/pool.h>
37 #include <internal/safe.h>
38
39 #define NDEBUG
40 #include <internal/debug.h>
41
42 /* TYPES *******************************************************************/
43
44 /*
45 * PURPOSE: Defines a handle
46 */
47 typedef struct
48 {
49 PVOID ObjectBody;
50 ACCESS_MASK GrantedAccess;
51 BOOLEAN Inherit;
52 } HANDLE_REP, *PHANDLE_REP;
53
54 #define HANDLE_BLOCK_ENTRIES ((PAGE_SIZE-sizeof(LIST_ENTRY))/sizeof(HANDLE_REP))
55
56
57 /*
58 * PURPOSE: Defines a page's worth of handles
59 */
60 typedef struct
61 {
62 LIST_ENTRY entry;
63 HANDLE_REP handles[HANDLE_BLOCK_ENTRIES];
64 } HANDLE_BLOCK, *PHANDLE_BLOCK;
65
66
67 /* GLOBALS *******************************************************************/
68
69 #define TAG_HANDLE_TABLE TAG('H', 'T', 'B', 'L')
70
71 /* FUNCTIONS ***************************************************************/
72
73
74 static PHANDLE_REP ObpGetObjectByHandle(PHANDLE_TABLE HandleTable, HANDLE h)
75 /*
76 * FUNCTION: Get the data structure for a handle
77 * ARGUMENTS:
78 * Process = Process to get the handle for
79 * h = Handle
80 * ARGUMENTS: A pointer to the information about the handle on success,
81 * NULL on failure
82 */
83 {
84 PLIST_ENTRY current;
85 unsigned int handle = (((unsigned int)h) >> 2) - 1;
86 unsigned int count=handle/HANDLE_BLOCK_ENTRIES;
87 HANDLE_BLOCK* blk = NULL;
88 unsigned int i;
89
90 DPRINT("ObpGetObjectByHandle(HandleTable %x, h %x)\n",HandleTable,h);
91
92 current = HandleTable->ListHead.Flink;
93 DPRINT("current %x\n",current);
94
95 for (i=0;i<count;i++)
96 {
97 current = current->Flink;
98 if (current == (&(HandleTable->ListHead)))
99 {
100 return(NULL);
101 }
102 }
103
104 blk = CONTAINING_RECORD(current,HANDLE_BLOCK,entry);
105 DPRINT("object: %p\n",&(blk->handles[handle%HANDLE_BLOCK_ENTRIES]));
106 return(&(blk->handles[handle%HANDLE_BLOCK_ENTRIES]));
107 }
108
109 NTSTATUS
110 ObDuplicateObject(PEPROCESS SourceProcess,
111 PEPROCESS TargetProcess,
112 HANDLE SourceHandle,
113 PHANDLE TargetHandle,
114 ACCESS_MASK DesiredAccess,
115 BOOLEAN InheritHandle,
116 ULONG Options)
117 {
118 KIRQL oldIrql;
119 PHANDLE_REP SourceHandleRep;
120 PVOID ObjectBody;
121
122 KeAcquireSpinLock(&SourceProcess->HandleTable.ListLock, &oldIrql);
123 SourceHandleRep = ObpGetObjectByHandle(&SourceProcess->HandleTable,
124 SourceHandle);
125 if (SourceHandleRep == NULL)
126 {
127 KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql);
128 return(STATUS_INVALID_HANDLE);
129 }
130 ObjectBody = SourceHandleRep->ObjectBody;
131 ObReferenceObjectByPointer(ObjectBody,
132 0,
133 NULL,
134 UserMode);
135
136 if (Options & DUPLICATE_SAME_ACCESS)
137 {
138 DesiredAccess = SourceHandleRep->GrantedAccess;
139 }
140
141 KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql);
142 ObCreateHandle(TargetProcess,
143 ObjectBody,
144 DesiredAccess,
145 InheritHandle,
146 TargetHandle);
147
148 if (Options & DUPLICATE_CLOSE_SOURCE)
149 {
150 ZwClose(SourceHandle);
151 }
152
153 ObDereferenceObject(ObjectBody);
154 return(STATUS_SUCCESS);
155 }
156
157 /*
158 * @implemented
159 */
160 NTSTATUS STDCALL
161 NtDuplicateObject (IN HANDLE SourceProcessHandle,
162 IN HANDLE SourceHandle,
163 IN HANDLE TargetProcessHandle,
164 OUT PHANDLE UnsafeTargetHandle,
165 IN ACCESS_MASK DesiredAccess,
166 IN BOOLEAN InheritHandle,
167 ULONG Options)
168 /*
169 * FUNCTION: Copies a handle from one process space to another
170 * ARGUMENTS:
171 * SourceProcessHandle = The source process owning the handle. The
172 * source process should have opened
173 * the SourceHandle with PROCESS_DUP_HANDLE
174 * access.
175 * SourceHandle = The handle to the object.
176 * TargetProcessHandle = The destination process owning the handle
177 * TargetHandle (OUT) = Caller should supply storage for the
178 * duplicated handle.
179 * DesiredAccess = The desired access to the handle.
180 * InheritHandle = Indicates wheter the new handle will be inheritable
181 * or not.
182 * Options = Specifies special actions upon duplicating the handle.
183 * Can be one of the values DUPLICATE_CLOSE_SOURCE |
184 * DUPLICATE_SAME_ACCESS. DUPLICATE_CLOSE_SOURCE specifies
185 * that the source handle should be closed after duplicating.
186 * DUPLICATE_SAME_ACCESS specifies to ignore the
187 * DesiredAccess paramter and just grant the same access to
188 * the new handle.
189 * RETURNS: Status
190 * REMARKS: This function maps to the win32 DuplicateHandle.
191 */
192 {
193 PEPROCESS SourceProcess;
194 PEPROCESS TargetProcess;
195 PHANDLE_REP SourceHandleRep;
196 KIRQL oldIrql;
197 PVOID ObjectBody;
198 HANDLE TargetHandle;
199 NTSTATUS Status;
200
201 ASSERT_IRQL(PASSIVE_LEVEL);
202
203 Status = ObReferenceObjectByHandle(SourceProcessHandle,
204 PROCESS_DUP_HANDLE,
205 NULL,
206 UserMode,
207 (PVOID*)&SourceProcess,
208 NULL);
209 if (!NT_SUCCESS(Status))
210 {
211 return(Status);
212 }
213 Status = ObReferenceObjectByHandle(TargetProcessHandle,
214 PROCESS_DUP_HANDLE,
215 NULL,
216 UserMode,
217 (PVOID*)&TargetProcess,
218 NULL);
219 if (!NT_SUCCESS(Status))
220 {
221 ObDereferenceObject(SourceProcess);
222 return(Status);
223 }
224
225 /* Check for magic handle first */
226 if (SourceHandle == NtCurrentThread())
227 {
228 ObReferenceObjectByHandle(SourceHandle,
229 PROCESS_DUP_HANDLE,
230 NULL,
231 UserMode,
232 &ObjectBody,
233 NULL);
234
235 ObCreateHandle(TargetProcess,
236 ObjectBody,
237 THREAD_ALL_ACCESS,
238 InheritHandle,
239 &TargetHandle);
240 }
241 else
242 {
243 KeAcquireSpinLock(&SourceProcess->HandleTable.ListLock, &oldIrql);
244 SourceHandleRep = ObpGetObjectByHandle(&SourceProcess->HandleTable,
245 SourceHandle);
246 if (SourceHandleRep == NULL)
247 {
248 KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql);
249 ObDereferenceObject(SourceProcess);
250 ObDereferenceObject(TargetProcess);
251 return(STATUS_INVALID_HANDLE);
252 }
253 ObjectBody = SourceHandleRep->ObjectBody;
254 ObReferenceObjectByPointer(ObjectBody,
255 0,
256 NULL,
257 UserMode);
258
259 if (Options & DUPLICATE_SAME_ACCESS)
260 {
261 DesiredAccess = SourceHandleRep->GrantedAccess;
262 }
263
264 KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql);
265 if (!SourceHandleRep->Inherit)
266 {
267 ObDereferenceObject(TargetProcess);
268 ObDereferenceObject(SourceProcess);
269 ObDereferenceObject(ObjectBody);
270 return STATUS_INVALID_HANDLE;
271 }
272 ObCreateHandle(TargetProcess,
273 ObjectBody,
274 DesiredAccess,
275 InheritHandle,
276 &TargetHandle);
277 }
278
279 if (Options & DUPLICATE_CLOSE_SOURCE)
280 {
281 ZwClose(SourceHandle);
282 }
283
284 ObDereferenceObject(TargetProcess);
285 ObDereferenceObject(SourceProcess);
286 ObDereferenceObject(ObjectBody);
287
288 Status = MmCopyToCaller(UnsafeTargetHandle, &TargetHandle, sizeof(HANDLE));
289 if (!NT_SUCCESS(Status))
290 {
291 return(Status);
292 }
293
294 return(STATUS_SUCCESS);
295 }
296
297 VOID ObCloseAllHandles(PEPROCESS Process)
298 {
299 KIRQL oldIrql;
300 PHANDLE_TABLE HandleTable;
301 PLIST_ENTRY current_entry;
302 PHANDLE_BLOCK current;
303 ULONG i;
304 PVOID ObjectBody;
305 BOOLEAN IsProcessHandle;
306
307 DPRINT("ObCloseAllHandles(Process %x)\n", Process);
308
309 HandleTable = &Process->HandleTable;
310
311 KeAcquireSpinLock(&HandleTable->ListLock, &oldIrql);
312
313 current_entry = HandleTable->ListHead.Flink;
314
315 while (current_entry != &HandleTable->ListHead)
316 {
317 current = CONTAINING_RECORD(current_entry, HANDLE_BLOCK, entry);
318
319 for (i = 0; i < HANDLE_BLOCK_ENTRIES; i++)
320 {
321 ObjectBody = current->handles[i].ObjectBody;
322
323 if (ObjectBody != NULL)
324 {
325 POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody);
326
327 if (Header->ObjectType == PsProcessType ||
328 Header->ObjectType == PsThreadType)
329 {
330 DPRINT("Deleting handle to %x\n", ObjectBody);
331 }
332
333 ObReferenceObjectByPointer(ObjectBody,
334 0,
335 NULL,
336 UserMode);
337 InterlockedDecrement(&Header->HandleCount);
338 current->handles[i].ObjectBody = NULL;
339
340 KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
341
342 if (Header->ObjectType == PsProcessType)
343 {
344 IsProcessHandle = TRUE;
345 KeDetachProcess();
346 }
347 else
348 {
349 IsProcessHandle = FALSE;
350 }
351 if ((Header->ObjectType != NULL) &&
352 (Header->ObjectType->Close != NULL))
353 {
354 Header->ObjectType->Close(ObjectBody,
355 Header->HandleCount);
356 }
357
358 ObDereferenceObject(ObjectBody);
359 if (IsProcessHandle)
360 {
361 KeAttachProcess(Process);
362 }
363 KeAcquireSpinLock(&HandleTable->ListLock, &oldIrql);
364 current_entry = &HandleTable->ListHead;
365 break;
366 }
367 }
368
369 current_entry = current_entry->Flink;
370 }
371 KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
372 DPRINT("ObCloseAllHandles() finished\n");
373 DPRINT("Type %x\n", BODY_TO_HEADER(Process)->ObjectType);
374 }
375
376 VOID ObDeleteHandleTable(PEPROCESS Process)
377 /*
378 * FUNCTION: Deletes the handle table associated with a process
379 */
380 {
381 PLIST_ENTRY current = NULL;
382 PHANDLE_TABLE HandleTable = NULL;
383
384 ObCloseAllHandles(Process);
385
386 HandleTable = &Process->HandleTable;
387 current = RemoveHeadList(&HandleTable->ListHead);
388
389 while (current != &HandleTable->ListHead)
390 {
391 HANDLE_BLOCK* HandleBlock = CONTAINING_RECORD(current,
392 HANDLE_BLOCK,
393 entry);
394 DPRINT("Freeing %x\n", HandleBlock);
395 ExFreePool(HandleBlock);
396
397 current = RemoveHeadList(&HandleTable->ListHead);
398 }
399 }
400
401
402 VOID ObCreateHandleTable(PEPROCESS Parent,
403 BOOLEAN Inherit,
404 PEPROCESS Process)
405 /*
406 * FUNCTION: Creates a handle table for a process
407 * ARGUMENTS:
408 * Parent = Parent process (or NULL if this is the first process)
409 * Inherit = True if the process should inherit its parent's handles
410 * Process = Process whose handle table is to be created
411 */
412 {
413 PHANDLE_TABLE ParentHandleTable, HandleTable;
414 KIRQL oldIrql;
415 PLIST_ENTRY parent_current;
416 ULONG i;
417 PHANDLE_BLOCK current_block, new_block;
418
419 DPRINT("ObCreateHandleTable(Parent %x, Inherit %d, Process %x)\n",
420 Parent,Inherit,Process);
421
422 InitializeListHead(&(Process->HandleTable.ListHead));
423 KeInitializeSpinLock(&(Process->HandleTable.ListLock));
424
425 if (Parent != NULL)
426 {
427 ParentHandleTable = &Parent->HandleTable;
428 HandleTable = &Process->HandleTable;
429
430 KeAcquireSpinLock(&Parent->HandleTable.ListLock, &oldIrql);
431 KeAcquireSpinLockAtDpcLevel(&Process->HandleTable.ListLock);
432
433 parent_current = ParentHandleTable->ListHead.Flink;
434
435 while (parent_current != &ParentHandleTable->ListHead)
436 {
437 current_block = CONTAINING_RECORD(parent_current,
438 HANDLE_BLOCK,
439 entry);
440 new_block = ExAllocatePoolWithTag(NonPagedPool,
441 sizeof(HANDLE_BLOCK),
442 TAG_HANDLE_TABLE);
443 if (new_block == NULL)
444 {
445 break;
446 }
447 RtlZeroMemory(new_block, sizeof(HANDLE_BLOCK));
448
449 for (i=0; i<HANDLE_BLOCK_ENTRIES; i++)
450 {
451 if (current_block->handles[i].ObjectBody)
452 {
453 if (current_block->handles[i].Inherit && Inherit)
454 {
455 new_block->handles[i].ObjectBody =
456 current_block->handles[i].ObjectBody;
457 new_block->handles[i].GrantedAccess =
458 current_block->handles[i].GrantedAccess;
459 new_block->handles[i].Inherit = TRUE;
460 InterlockedIncrement(&(BODY_TO_HEADER(current_block->handles[i].ObjectBody)->HandleCount));
461 }
462 }
463 }
464 InsertTailList(&Process->HandleTable.ListHead, &new_block->entry);
465 parent_current = parent_current->Flink;
466 }
467 KeReleaseSpinLockFromDpcLevel(&Process->HandleTable.ListLock);
468 KeReleaseSpinLock(&Parent->HandleTable.ListLock, oldIrql);
469 }
470 }
471
472
473 PVOID ObDeleteHandle(PEPROCESS Process, HANDLE Handle)
474 {
475 PHANDLE_REP Rep;
476 PVOID ObjectBody;
477 KIRQL oldIrql;
478 PHANDLE_TABLE HandleTable;
479 POBJECT_HEADER Header;
480
481 DPRINT("ObDeleteHandle(Handle %x)\n",Handle);
482
483 HandleTable = &Process->HandleTable;
484
485 KeAcquireSpinLock(&HandleTable->ListLock, &oldIrql);
486
487 Rep = ObpGetObjectByHandle(HandleTable, Handle);
488 if (Rep == NULL)
489 {
490 KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
491 return(NULL);
492 }
493
494 ObjectBody = Rep->ObjectBody;
495 DPRINT("ObjectBody %x\n", ObjectBody);
496 if (ObjectBody != NULL)
497 {
498 Header = BODY_TO_HEADER(ObjectBody);
499 InterlockedDecrement(&(BODY_TO_HEADER(ObjectBody)->HandleCount));
500 ObReferenceObjectByPointer(ObjectBody,
501 0,
502 NULL,
503 UserMode);
504 Rep->ObjectBody = NULL;
505
506 KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
507
508 if ((Header->ObjectType != NULL) &&
509 (Header->ObjectType->Close != NULL))
510 {
511 Header->ObjectType->Close(ObjectBody, Header->HandleCount);
512 }
513 }
514 else
515 {
516 KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
517 }
518
519 DPRINT("Finished ObDeleteHandle()\n");
520 return(ObjectBody);
521 }
522
523
524 NTSTATUS ObCreateHandle(PEPROCESS Process,
525 PVOID ObjectBody,
526 ACCESS_MASK GrantedAccess,
527 BOOLEAN Inherit,
528 PHANDLE HandleReturn)
529 /*
530 * FUNCTION: Add a handle referencing an object
531 * ARGUMENTS:
532 * obj = Object body that the handle should refer to
533 * RETURNS: The created handle
534 * NOTE: The handle is valid only in the context of the current process
535 */
536 {
537 LIST_ENTRY* current;
538 unsigned int handle=1;
539 unsigned int i;
540 HANDLE_BLOCK* new_blk = NULL;
541 PHANDLE_TABLE HandleTable;
542 KIRQL oldlvl;
543
544 DPRINT("ObCreateHandle(Process %x, obj %x)\n",Process,ObjectBody);
545
546 assert(Process);
547
548 if (ObjectBody != NULL)
549 {
550 InterlockedIncrement(&(BODY_TO_HEADER(ObjectBody)->HandleCount));
551 }
552 HandleTable = &Process->HandleTable;
553 KeAcquireSpinLock(&HandleTable->ListLock, &oldlvl);
554 current = HandleTable->ListHead.Flink;
555 /*
556 * Scan through the currently allocated handle blocks looking for a free
557 * slot
558 */
559 while (current != (&HandleTable->ListHead))
560 {
561 HANDLE_BLOCK* blk = CONTAINING_RECORD(current,HANDLE_BLOCK,entry);
562
563 DPRINT("Current %x\n",current);
564
565 for (i=0;i<HANDLE_BLOCK_ENTRIES;i++)
566 {
567 DPRINT("Considering slot %d containing %x\n",i,blk->handles[i]);
568 if (blk->handles[i].ObjectBody==NULL)
569 {
570 blk->handles[i].ObjectBody = ObjectBody;
571 blk->handles[i].GrantedAccess = GrantedAccess;
572 blk->handles[i].Inherit = Inherit;
573 KeReleaseSpinLock(&HandleTable->ListLock, oldlvl);
574 *HandleReturn = (HANDLE)((handle + i) << 2);
575 return(STATUS_SUCCESS);
576 }
577 }
578
579 handle = handle + HANDLE_BLOCK_ENTRIES;
580 current = current->Flink;
581 }
582
583 /*
584 * Add a new handle block to the end of the list
585 */
586 new_blk =
587 (HANDLE_BLOCK *)ExAllocatePoolWithTag(NonPagedPool,sizeof(HANDLE_BLOCK),
588 TAG_HANDLE_TABLE);
589 if (!new_blk)
590 {
591 *HandleReturn = (PHANDLE)NULL;
592 return(STATUS_INSUFFICIENT_RESOURCES);
593 }
594 RtlZeroMemory(new_blk,sizeof(HANDLE_BLOCK));
595 InsertTailList(&(Process->HandleTable.ListHead),
596 &new_blk->entry);
597 new_blk->handles[0].ObjectBody = ObjectBody;
598 new_blk->handles[0].GrantedAccess = GrantedAccess;
599 new_blk->handles[0].Inherit = Inherit;
600 KeReleaseSpinLock(&HandleTable->ListLock, oldlvl);
601 *HandleReturn = (HANDLE)(handle << 2);
602 return(STATUS_SUCCESS);
603 }
604
605
606 /*
607 * @implemented
608 */
609 NTSTATUS STDCALL
610 ObReferenceObjectByHandle(HANDLE Handle,
611 ACCESS_MASK DesiredAccess,
612 POBJECT_TYPE ObjectType,
613 KPROCESSOR_MODE AccessMode,
614 PVOID* Object,
615 POBJECT_HANDLE_INFORMATION HandleInformationPtr)
616 /*
617 * FUNCTION: Increments the reference count for an object and returns a
618 * pointer to its body
619 * ARGUMENTS:
620 * Handle = Handle for the object
621 * DesiredAccess = Desired access to the object
622 * ObjectType
623 * AccessMode
624 * Object (OUT) = Points to the object body on return
625 * HandleInformation (OUT) = Contains information about the handle
626 * on return
627 * RETURNS: Status
628 */
629 {
630 PHANDLE_REP HandleRep;
631 POBJECT_HEADER ObjectHeader;
632 KIRQL oldIrql;
633 PVOID ObjectBody;
634 ACCESS_MASK GrantedAccess;
635 NTSTATUS Status;
636
637 ASSERT_IRQL(PASSIVE_LEVEL);
638
639 DPRINT("ObReferenceObjectByHandle(Handle %x, DesiredAccess %x, "
640 "ObjectType %x, AccessMode %d, Object %x)\n",Handle,DesiredAccess,
641 ObjectType,AccessMode,Object);
642
643
644 /*
645 * Handle special handle names
646 */
647 if (Handle == NtCurrentProcess() &&
648 (ObjectType == PsProcessType || ObjectType == NULL))
649 {
650 DPRINT("Reference from %x\n", ((PULONG)&Handle)[-1]);
651
652 Status = ObReferenceObjectByPointer(PsGetCurrentProcess(),
653 PROCESS_ALL_ACCESS,
654 PsProcessType,
655 UserMode);
656 if (! NT_SUCCESS(Status))
657 {
658 return Status;
659 }
660
661 *Object = PsGetCurrentProcess();
662 DPRINT("Referencing current process %x\n", PsGetCurrentProcess());
663 return STATUS_SUCCESS;
664 }
665 else if (Handle == NtCurrentProcess())
666 {
667 CHECKPOINT;
668 return(STATUS_OBJECT_TYPE_MISMATCH);
669 }
670 if (Handle == NtCurrentThread() &&
671 (ObjectType == PsThreadType || ObjectType == NULL))
672 {
673 Status = ObReferenceObjectByPointer(PsGetCurrentThread(),
674 THREAD_ALL_ACCESS,
675 PsThreadType,
676 UserMode);
677 if (! NT_SUCCESS(Status))
678 {
679 return Status;
680 }
681
682 *Object = PsGetCurrentThread();
683 CHECKPOINT;
684 return STATUS_SUCCESS;
685 }
686 else if (Handle == NtCurrentThread())
687 {
688 CHECKPOINT;
689 return(STATUS_OBJECT_TYPE_MISMATCH);
690 }
691
692 KeAcquireSpinLock(&PsGetCurrentProcess()->HandleTable.ListLock,
693 &oldIrql);
694 HandleRep = ObpGetObjectByHandle(&PsGetCurrentProcess()->HandleTable,
695 Handle);
696 if (HandleRep == NULL || HandleRep->ObjectBody == NULL)
697 {
698 KeReleaseSpinLock(&PsGetCurrentProcess()->HandleTable.ListLock,
699 oldIrql);
700 return(STATUS_INVALID_HANDLE);
701 }
702 ObjectBody = HandleRep->ObjectBody;
703 DPRINT("ObjectBody %p\n",ObjectBody);
704 ObjectHeader = BODY_TO_HEADER(ObjectBody);
705 DPRINT("ObjectHeader->RefCount %lu\n",ObjectHeader->RefCount);
706 ObReferenceObjectByPointer(ObjectBody,
707 0,
708 NULL,
709 UserMode);
710 GrantedAccess = HandleRep->GrantedAccess;
711 KeReleaseSpinLock(&PsGetCurrentProcess()->HandleTable.ListLock,
712 oldIrql);
713
714 ObjectHeader = BODY_TO_HEADER(ObjectBody);
715 DPRINT("ObjectHeader->RefCount %lu\n",ObjectHeader->RefCount);
716
717 if (ObjectType != NULL && ObjectType != ObjectHeader->ObjectType)
718 {
719 CHECKPOINT;
720 return(STATUS_OBJECT_TYPE_MISMATCH);
721 }
722
723 if (ObjectHeader->ObjectType == PsProcessType)
724 {
725 DPRINT("Reference from %x\n", ((PULONG)&Handle)[-1]);
726 }
727
728 if (DesiredAccess && AccessMode == UserMode)
729 {
730 RtlMapGenericMask(&DesiredAccess, ObjectHeader->ObjectType->Mapping);
731
732 if (!(GrantedAccess & DesiredAccess) &&
733 !((~GrantedAccess) & DesiredAccess))
734 {
735 CHECKPOINT;
736 return(STATUS_ACCESS_DENIED);
737 }
738 }
739
740 *Object = ObjectBody;
741
742 CHECKPOINT;
743 return(STATUS_SUCCESS);
744 }
745
746
747 /**********************************************************************
748 * NAME EXPORTED
749 * NtClose
750 *
751 * DESCRIPTION
752 * Closes a handle reference to an object.
753 *
754 * ARGUMENTS
755 * Handle
756 * Handle to close.
757 *
758 * RETURN VALUE
759 * Status.
760 *
761 * @implemented
762 */
763 NTSTATUS STDCALL NtClose(HANDLE Handle)
764 {
765 PVOID ObjectBody;
766 POBJECT_HEADER Header;
767
768 assert_irql(PASSIVE_LEVEL);
769
770 DPRINT("NtClose(Handle %x)\n",Handle);
771
772 ObjectBody = ObDeleteHandle(PsGetCurrentProcess(), Handle);
773 if (ObjectBody == NULL)
774 {
775 return(STATUS_INVALID_HANDLE);
776 }
777
778 Header = BODY_TO_HEADER(ObjectBody);
779
780 DPRINT("Dereferencing %x\n", ObjectBody);
781 ObDereferenceObject(ObjectBody);
782
783 return(STATUS_SUCCESS);
784 }
785
786 /*
787 * @implemented
788 */
789 NTSTATUS STDCALL
790 ObInsertObject(PVOID Object,
791 PACCESS_STATE PassedAccessState,
792 ACCESS_MASK DesiredAccess,
793 ULONG AdditionalReferences,
794 PVOID* ReferencedObject,
795 PHANDLE Handle)
796 {
797 return(ObCreateHandle(PsGetCurrentProcess(),
798 Object,
799 DesiredAccess,
800 FALSE,
801 Handle));
802 }
803
804 /* EOF */