update for HEAD-2003050101
[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
221    /* Check for magic handle first */
222    if (SourceHandle == NtCurrentThread())
223      {
224        ObReferenceObjectByHandle(SourceHandle,
225                                  PROCESS_DUP_HANDLE,
226                                  NULL,
227                                  UserMode,
228                                  &ObjectBody,
229                                  NULL);
230
231        ObCreateHandle(TargetProcess,
232                       ObjectBody,
233                       THREAD_ALL_ACCESS,
234                       InheritHandle,
235                       &TargetHandle);
236      }
237    else
238      {
239        KeAcquireSpinLock(&SourceProcess->HandleTable.ListLock, &oldIrql);
240        SourceHandleRep = ObpGetObjectByHandle(&SourceProcess->HandleTable,
241                                               SourceHandle);
242        if (SourceHandleRep == NULL)
243          {
244            KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql);
245            ObDereferenceObject(SourceProcess);
246            ObDereferenceObject(TargetProcess);
247            return(STATUS_INVALID_HANDLE);
248          }
249        ObjectBody = SourceHandleRep->ObjectBody;
250        ObReferenceObjectByPointer(ObjectBody,
251                                   0,
252                                   NULL,
253                                   UserMode);
254    
255        if (Options & DUPLICATE_SAME_ACCESS)
256          {
257            DesiredAccess = SourceHandleRep->GrantedAccess;
258          }
259    
260        KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql);
261        if (!SourceHandleRep->Inherit)
262          {
263            ObDereferenceObject(TargetProcess);
264            ObDereferenceObject(SourceProcess);
265            ObDereferenceObject(ObjectBody);
266            return STATUS_INVALID_HANDLE;
267          }
268        ObCreateHandle(TargetProcess,
269                       ObjectBody,
270                       DesiredAccess,
271                       InheritHandle,
272                       &TargetHandle);
273      }
274    
275    if (Options & DUPLICATE_CLOSE_SOURCE)
276      {
277         ZwClose(SourceHandle);
278      }
279    
280    ObDereferenceObject(TargetProcess);
281    ObDereferenceObject(SourceProcess);
282    ObDereferenceObject(ObjectBody);
283    
284    Status = MmCopyToCaller(UnsafeTargetHandle, &TargetHandle, sizeof(HANDLE));
285    if (!NT_SUCCESS(Status))
286      {
287        return(Status);
288      }
289
290    return(STATUS_SUCCESS);
291 }
292
293 VOID ObCloseAllHandles(PEPROCESS Process)
294 {
295    KIRQL oldIrql;
296    PHANDLE_TABLE HandleTable;
297    PLIST_ENTRY current_entry;
298    PHANDLE_BLOCK current;
299    ULONG i;
300    PVOID ObjectBody;
301    BOOLEAN IsProcessHandle;
302    
303    DPRINT("ObCloseAllHandles(Process %x)\n", Process);
304    
305    HandleTable = &Process->HandleTable;
306    
307    KeAcquireSpinLock(&HandleTable->ListLock, &oldIrql);
308    
309    current_entry = HandleTable->ListHead.Flink;
310    
311    while (current_entry != &HandleTable->ListHead)
312      {
313         current = CONTAINING_RECORD(current_entry, HANDLE_BLOCK, entry);
314         
315         for (i = 0; i < HANDLE_BLOCK_ENTRIES; i++)
316           {
317              ObjectBody = current->handles[i].ObjectBody;
318              
319              if (ObjectBody != NULL)
320                {
321                   POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody);
322                   
323                   if (Header->ObjectType == PsProcessType ||
324                       Header->ObjectType == PsThreadType)
325                     {
326                        DPRINT("Deleting handle to %x\n", ObjectBody);
327                     }
328                   
329                   ObReferenceObjectByPointer(ObjectBody,
330                                              0,
331                                              NULL,
332                                              UserMode);
333                   InterlockedDecrement(&Header->HandleCount);
334                   current->handles[i].ObjectBody = NULL;
335                   
336                   KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
337                   
338                   if (Header->ObjectType == PsProcessType)
339                   {
340                      IsProcessHandle = TRUE;
341                      KeDetachProcess();
342                   }
343                   else
344                   {
345                      IsProcessHandle = FALSE;
346                   }
347                   if ((Header->ObjectType != NULL) &&
348                       (Header->ObjectType->Close != NULL))
349                     {
350                        Header->ObjectType->Close(ObjectBody, 
351                                                  Header->HandleCount);
352                     }
353                   
354                   ObDereferenceObject(ObjectBody);
355                   if (IsProcessHandle)
356                   {
357                      KeAttachProcess(Process);
358                   }
359                   KeAcquireSpinLock(&HandleTable->ListLock, &oldIrql);
360                   current_entry = &HandleTable->ListHead;
361                   break;
362                }
363           }
364         
365         current_entry = current_entry->Flink;
366      }
367    KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
368    DPRINT("ObCloseAllHandles() finished\n");
369    DPRINT("Type %x\n", BODY_TO_HEADER(Process)->ObjectType);
370 }
371
372 VOID ObDeleteHandleTable(PEPROCESS Process)
373 /*
374  * FUNCTION: Deletes the handle table associated with a process
375  */
376 {
377    PLIST_ENTRY current = NULL;
378    PHANDLE_TABLE HandleTable = NULL;
379    
380    ObCloseAllHandles(Process);
381    
382    HandleTable = &Process->HandleTable;
383    current = RemoveHeadList(&HandleTable->ListHead);
384    
385    while (current != &HandleTable->ListHead)
386      {
387         HANDLE_BLOCK* HandleBlock = CONTAINING_RECORD(current,
388                                                       HANDLE_BLOCK,
389                                                       entry);
390         DPRINT("Freeing %x\n", HandleBlock);
391         ExFreePool(HandleBlock);
392         
393         current = RemoveHeadList(&HandleTable->ListHead);
394      }
395 }
396
397
398 VOID ObCreateHandleTable(PEPROCESS Parent,
399                          BOOLEAN Inherit,
400                          PEPROCESS Process)
401 /*
402  * FUNCTION: Creates a handle table for a process
403  * ARGUMENTS:
404  *       Parent = Parent process (or NULL if this is the first process)
405  *       Inherit = True if the process should inherit its parent's handles
406  *       Process = Process whose handle table is to be created
407  */
408 {
409    PHANDLE_TABLE ParentHandleTable, HandleTable;
410    KIRQL oldIrql;
411    PLIST_ENTRY parent_current;
412    ULONG i;
413    PHANDLE_BLOCK current_block, new_block;   
414
415    DPRINT("ObCreateHandleTable(Parent %x, Inherit %d, Process %x)\n",
416           Parent,Inherit,Process);
417    
418    InitializeListHead(&(Process->HandleTable.ListHead));
419    KeInitializeSpinLock(&(Process->HandleTable.ListLock));
420    
421    if (Parent != NULL)
422      {
423         ParentHandleTable = &Parent->HandleTable;
424         HandleTable = &Process->HandleTable;
425
426         KeAcquireSpinLock(&Parent->HandleTable.ListLock, &oldIrql);
427         KeAcquireSpinLockAtDpcLevel(&Process->HandleTable.ListLock);
428         
429         parent_current = ParentHandleTable->ListHead.Flink;
430         
431         while (parent_current != &ParentHandleTable->ListHead)
432           {
433              current_block = CONTAINING_RECORD(parent_current,
434                                                HANDLE_BLOCK,
435                                                entry);
436              new_block = ExAllocatePoolWithTag(NonPagedPool,
437                                                sizeof(HANDLE_BLOCK),
438                                                TAG_HANDLE_TABLE);
439              if (new_block == NULL)
440              {
441                 break;
442              }
443              RtlZeroMemory(new_block, sizeof(HANDLE_BLOCK));
444
445              for (i=0; i<HANDLE_BLOCK_ENTRIES; i++)
446              {
447                 if (current_block->handles[i].ObjectBody)
448                 {
449                    if (current_block->handles[i].Inherit && Inherit)
450                    {
451                       new_block->handles[i].ObjectBody = 
452                         current_block->handles[i].ObjectBody;
453                       new_block->handles[i].GrantedAccess = 
454                         current_block->handles[i].GrantedAccess;
455                       new_block->handles[i].Inherit = TRUE;
456                       InterlockedIncrement(&(BODY_TO_HEADER(current_block->handles[i].ObjectBody)->HandleCount));
457                    }
458                 }
459              }
460              InsertTailList(&Process->HandleTable.ListHead, &new_block->entry);
461              parent_current = parent_current->Flink;
462           }
463         KeReleaseSpinLockFromDpcLevel(&Process->HandleTable.ListLock);
464         KeReleaseSpinLock(&Parent->HandleTable.ListLock, oldIrql);
465      }
466 }
467
468
469 PVOID ObDeleteHandle(PEPROCESS Process, HANDLE Handle)
470 {
471    PHANDLE_REP Rep;
472    PVOID ObjectBody;
473    KIRQL oldIrql;
474    PHANDLE_TABLE HandleTable;
475    POBJECT_HEADER Header;
476    
477    DPRINT("ObDeleteHandle(Handle %x)\n",Handle);
478    
479    HandleTable = &Process->HandleTable;
480    
481    KeAcquireSpinLock(&HandleTable->ListLock, &oldIrql);
482    
483    Rep = ObpGetObjectByHandle(HandleTable, Handle);
484    if (Rep == NULL)
485      {
486         KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);     
487         return(NULL);
488      }
489    
490    ObjectBody = Rep->ObjectBody;
491    DPRINT("ObjectBody %x\n", ObjectBody);
492    if (ObjectBody != NULL)
493      {
494         Header = BODY_TO_HEADER(ObjectBody);
495         InterlockedDecrement(&(BODY_TO_HEADER(ObjectBody)->HandleCount));
496         ObReferenceObjectByPointer(ObjectBody,
497                                    0,
498                                    NULL,
499                                    UserMode);
500         Rep->ObjectBody = NULL;
501    
502         KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
503    
504         if ((Header->ObjectType != NULL) &&
505             (Header->ObjectType->Close != NULL))
506           {
507              Header->ObjectType->Close(ObjectBody, Header->HandleCount);
508           }
509      }
510    else
511      {
512         KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
513      }
514    
515    DPRINT("Finished ObDeleteHandle()\n");
516    return(ObjectBody);
517 }
518
519
520 NTSTATUS ObCreateHandle(PEPROCESS Process,
521                         PVOID ObjectBody,
522                         ACCESS_MASK GrantedAccess,
523                         BOOLEAN Inherit,
524                         PHANDLE HandleReturn)
525 /*
526  * FUNCTION: Add a handle referencing an object
527  * ARGUMENTS:
528  *         obj = Object body that the handle should refer to
529  * RETURNS: The created handle
530  * NOTE: The handle is valid only in the context of the current process
531  */
532 {
533    LIST_ENTRY* current;
534    unsigned int handle=1;
535    unsigned int i;
536    HANDLE_BLOCK* new_blk = NULL;
537    PHANDLE_TABLE HandleTable;
538    KIRQL oldlvl;
539
540    DPRINT("ObCreateHandle(Process %x, obj %x)\n",Process,ObjectBody);
541
542    assert(Process);
543
544    if (ObjectBody != NULL)
545      {
546         InterlockedIncrement(&(BODY_TO_HEADER(ObjectBody)->HandleCount));
547      }
548    HandleTable = &Process->HandleTable;
549    KeAcquireSpinLock(&HandleTable->ListLock, &oldlvl);
550    current = HandleTable->ListHead.Flink;
551    /*
552     * Scan through the currently allocated handle blocks looking for a free
553     * slot
554     */
555    while (current != (&HandleTable->ListHead))
556      {
557         HANDLE_BLOCK* blk = CONTAINING_RECORD(current,HANDLE_BLOCK,entry);
558
559         DPRINT("Current %x\n",current);
560
561         for (i=0;i<HANDLE_BLOCK_ENTRIES;i++)
562           {
563              DPRINT("Considering slot %d containing %x\n",i,blk->handles[i]);
564              if (blk->handles[i].ObjectBody==NULL)
565                {
566                   blk->handles[i].ObjectBody = ObjectBody;
567                   blk->handles[i].GrantedAccess = GrantedAccess;
568                   blk->handles[i].Inherit = Inherit;
569                   KeReleaseSpinLock(&HandleTable->ListLock, oldlvl);
570                   *HandleReturn = (HANDLE)((handle + i) << 2);
571                   return(STATUS_SUCCESS);
572                }
573           }
574         
575         handle = handle + HANDLE_BLOCK_ENTRIES;
576         current = current->Flink;
577      }
578
579    /*
580     * Add a new handle block to the end of the list
581     */
582    new_blk = 
583      (HANDLE_BLOCK *)ExAllocatePoolWithTag(NonPagedPool,sizeof(HANDLE_BLOCK),
584                                            TAG_HANDLE_TABLE);
585    if (!new_blk)
586     {
587       *HandleReturn = (PHANDLE)NULL;
588       return(STATUS_INSUFFICIENT_RESOURCES);
589     }
590    RtlZeroMemory(new_blk,sizeof(HANDLE_BLOCK));
591    InsertTailList(&(Process->HandleTable.ListHead),
592                   &new_blk->entry);
593    new_blk->handles[0].ObjectBody = ObjectBody;
594    new_blk->handles[0].GrantedAccess = GrantedAccess;
595    new_blk->handles[0].Inherit = Inherit;
596    KeReleaseSpinLock(&HandleTable->ListLock, oldlvl);
597    *HandleReturn = (HANDLE)(handle << 2);
598    return(STATUS_SUCCESS);
599 }
600
601
602 NTSTATUS STDCALL
603 ObReferenceObjectByHandle(HANDLE Handle,
604                           ACCESS_MASK DesiredAccess,
605                           POBJECT_TYPE ObjectType,
606                           KPROCESSOR_MODE AccessMode,
607                           PVOID* Object,
608                           POBJECT_HANDLE_INFORMATION HandleInformationPtr)
609 /*
610  * FUNCTION: Increments the reference count for an object and returns a 
611  * pointer to its body
612  * ARGUMENTS:
613  *         Handle = Handle for the object
614  *         DesiredAccess = Desired access to the object
615  *         ObjectType
616  *         AccessMode 
617  *         Object (OUT) = Points to the object body on return
618  *         HandleInformation (OUT) = Contains information about the handle 
619  *                                   on return
620  * RETURNS: Status
621  */
622 {
623    PHANDLE_REP HandleRep;
624    POBJECT_HEADER ObjectHeader;
625    KIRQL oldIrql;
626    PVOID ObjectBody;
627    ACCESS_MASK GrantedAccess;
628    
629    ASSERT_IRQL(PASSIVE_LEVEL);
630    
631    DPRINT("ObReferenceObjectByHandle(Handle %x, DesiredAccess %x, "
632            "ObjectType %x, AccessMode %d, Object %x)\n",Handle,DesiredAccess,
633            ObjectType,AccessMode,Object);
634
635    
636    /*
637     * Handle special handle names
638     */
639    if (Handle == NtCurrentProcess() && 
640        (ObjectType == PsProcessType || ObjectType == NULL))
641      {
642         DPRINT("Reference from %x\n", ((PULONG)&Handle)[-1]);
643         
644         ObReferenceObjectByPointer(PsGetCurrentProcess(),
645                                    PROCESS_ALL_ACCESS,
646                                    PsProcessType,
647                                    UserMode);
648         *Object = PsGetCurrentProcess();
649         DPRINT("Referencing current process %x\n", PsGetCurrentProcess());
650         return(STATUS_SUCCESS);
651      }
652    else if (Handle == NtCurrentProcess())
653      {
654         CHECKPOINT;
655         return(STATUS_OBJECT_TYPE_MISMATCH);
656      }
657    if (Handle == NtCurrentThread() && 
658        (ObjectType == PsThreadType || ObjectType == NULL))
659      {
660         ObReferenceObjectByPointer(PsGetCurrentThread(),
661                                    THREAD_ALL_ACCESS,
662                                    PsThreadType,
663                                    UserMode);
664         *Object = PsGetCurrentThread();
665         CHECKPOINT;
666         return(STATUS_SUCCESS);
667      }
668    else if (Handle == NtCurrentThread())
669      {
670         CHECKPOINT;
671         return(STATUS_OBJECT_TYPE_MISMATCH);
672      }
673    
674    KeAcquireSpinLock(&PsGetCurrentProcess()->HandleTable.ListLock,
675                      &oldIrql);
676    HandleRep = ObpGetObjectByHandle(&PsGetCurrentProcess()->HandleTable,
677                                     Handle);
678    if (HandleRep == NULL || HandleRep->ObjectBody == NULL)
679      {
680         KeReleaseSpinLock(&PsGetCurrentProcess()->HandleTable.ListLock,
681                           oldIrql);
682         return(STATUS_INVALID_HANDLE);
683      }
684    ObjectBody = HandleRep->ObjectBody;
685    DPRINT("ObjectBody %p\n",ObjectBody);
686    ObjectHeader = BODY_TO_HEADER(ObjectBody);
687    DPRINT("ObjectHeader->RefCount %lu\n",ObjectHeader->RefCount);
688    ObReferenceObjectByPointer(ObjectBody,
689                               0,
690                               NULL,
691                               UserMode);
692    GrantedAccess = HandleRep->GrantedAccess;
693    KeReleaseSpinLock(&PsGetCurrentProcess()->HandleTable.ListLock,
694                      oldIrql);
695    
696    ObjectHeader = BODY_TO_HEADER(ObjectBody);
697    DPRINT("ObjectHeader->RefCount %lu\n",ObjectHeader->RefCount);
698
699    if (ObjectType != NULL && ObjectType != ObjectHeader->ObjectType)
700      {
701         CHECKPOINT;
702         return(STATUS_OBJECT_TYPE_MISMATCH);
703      }
704    
705    if (ObjectHeader->ObjectType == PsProcessType)
706      {
707         DPRINT("Reference from %x\n", ((PULONG)&Handle)[-1]);
708      }
709    
710    if (DesiredAccess && AccessMode == UserMode)
711      {
712         RtlMapGenericMask(&DesiredAccess, ObjectHeader->ObjectType->Mapping);
713
714         if (!(GrantedAccess & DesiredAccess) &&
715             !((~GrantedAccess) & DesiredAccess))
716           {
717              CHECKPOINT;
718              return(STATUS_ACCESS_DENIED);
719           }
720      }
721    
722    *Object = ObjectBody;
723    
724    CHECKPOINT;
725    return(STATUS_SUCCESS);
726 }
727
728
729 /**********************************************************************
730  * NAME                                                 EXPORTED
731  *      NtClose
732  *      
733  * DESCRIPTION
734  *      Closes a handle reference to an object.
735  *      
736  * ARGUMENTS
737  *      Handle
738  *              Handle to close.
739  *              
740  * RETURN VALUE
741  *      Status.
742  */
743 NTSTATUS STDCALL NtClose(HANDLE Handle)
744 {
745    PVOID                ObjectBody;
746    POBJECT_HEADER       Header;
747    
748    assert_irql(PASSIVE_LEVEL);
749    
750    DPRINT("NtClose(Handle %x)\n",Handle);
751    
752    ObjectBody = ObDeleteHandle(PsGetCurrentProcess(), Handle);
753    if (ObjectBody == NULL)
754      {
755         return(STATUS_INVALID_HANDLE);
756      }
757    
758    Header = BODY_TO_HEADER(ObjectBody);
759    
760    DPRINT("Dereferencing %x\n", ObjectBody);
761    ObDereferenceObject(ObjectBody);
762    
763    return(STATUS_SUCCESS);
764 }
765
766 NTSTATUS STDCALL
767 ObInsertObject(PVOID Object,
768                PACCESS_STATE PassedAccessState,
769                ACCESS_MASK DesiredAccess,
770                ULONG AdditionalReferences,
771                PVOID* ReferencedObject,
772                PHANDLE Handle)
773 {
774   return(ObCreateHandle(PsGetCurrentProcess(),
775                         Object,
776                         DesiredAccess,
777                         FALSE,
778                         Handle));
779 }
780
781 /* EOF */