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