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