5b498c73ee4621b62d94e3d6f96a6913b1b5353f
[reactos.git] / ntoskrnl / io / ioctrl.c
1 /* $Id$
2  *
3  * COPYRIGHT:       See COPYING in the top level directory
4  * PROJECT:         ReactOS kernel
5  * FILE:            ntoskrnl/io/ioctrl.c
6  * PURPOSE:         Device IO control
7  * PROGRAMMER:      David Welch (welch@mcmail.com)
8  *                  Eric Kohl (ekohl@abo.rhein-zeitung.de)
9  * UPDATE HISTORY:
10  *                  Created 22/05/98
11  *                  Filled in ZwDeviceIoControlFile 22/02/99
12  *                  Fixed IO method handling 08/03/99
13  *                  Added APC support 05/11/99
14  */
15
16 /* INCLUDES *****************************************************************/
17
18 #include <ddk/ntddk.h>
19 #include <internal/io.h>
20 #define NDEBUG
21 #include <internal/debug.h>
22
23 /* FUNCTIONS *****************************************************************/
24
25 /*
26  * @implemented
27  */
28 NTSTATUS STDCALL NtDeviceIoControlFile (IN HANDLE DeviceHandle,
29                                         IN HANDLE Event,
30                                         IN PIO_APC_ROUTINE UserApcRoutine,
31                                         IN PVOID UserApcContext,
32                                         OUT PIO_STATUS_BLOCK IoStatusBlock,
33                                         IN ULONG IoControlCode,
34                                         IN PVOID InputBuffer,
35                                         IN ULONG InputBufferSize,
36                                         OUT PVOID OutputBuffer,
37                                         IN ULONG OutputBufferSize)
38 {
39    NTSTATUS Status;
40    PFILE_OBJECT FileObject;
41    PDEVICE_OBJECT DeviceObject;
42    PIRP Irp;
43    PIO_STACK_LOCATION StackPtr;
44    PKEVENT ptrEvent;
45    IO_STATUS_BLOCK IoSB;
46
47    DPRINT("NtDeviceIoControlFile(DeviceHandle %x Event %x UserApcRoutine %x "
48           "UserApcContext %x IoStatusBlock %x IoControlCode %x "
49           "InputBuffer %x InputBufferSize %x OutputBuffer %x "
50           "OutputBufferSize %x)\n",
51           DeviceHandle,Event,UserApcRoutine,UserApcContext,IoStatusBlock,
52           IoControlCode,InputBuffer,InputBufferSize,OutputBuffer,
53           OutputBufferSize);
54
55    Status = ObReferenceObjectByHandle(DeviceHandle,
56                                       FILE_READ_DATA | FILE_WRITE_DATA,
57                                       IoFileObjectType,
58                                       KernelMode,
59                                       (PVOID *) &FileObject,
60                                       NULL);
61    
62    if (!NT_SUCCESS(Status))
63      {
64         return(Status);
65      }
66    if (Event != NULL)
67      {
68         Status = ObReferenceObjectByHandle (Event,
69                                             SYNCHRONIZE,
70                                             ExEventObjectType,
71                                             UserMode,
72                                             (PVOID*)&ptrEvent,
73                                             NULL);
74         if (!NT_SUCCESS(Status))
75           {
76             ObDereferenceObject(FileObject);
77             return Status;
78           }
79       }
80     else
81       {
82          KeResetEvent (&FileObject->Event);
83          ptrEvent = &FileObject->Event;
84       }
85
86    DeviceObject = FileObject->DeviceObject;
87
88    Irp = IoBuildDeviceIoControlRequest(IoControlCode,
89                                        DeviceObject,
90                                        InputBuffer,
91                                        InputBufferSize,
92                                        OutputBuffer,
93                                        OutputBufferSize,
94                                        FALSE,
95                                        ptrEvent,
96                                        Event ? IoStatusBlock : &IoSB);
97
98    //trigger FileObject/Event dereferencing
99    Irp->Tail.Overlay.OriginalFileObject = FileObject;
100
101    Irp->Overlay.AsynchronousParameters.UserApcRoutine = UserApcRoutine;
102    Irp->Overlay.AsynchronousParameters.UserApcContext = UserApcContext;
103
104    StackPtr = IoGetNextIrpStackLocation(Irp);
105    StackPtr->FileObject = FileObject;
106    StackPtr->DeviceObject = DeviceObject;
107    StackPtr->Parameters.DeviceIoControl.InputBufferLength = InputBufferSize;
108    StackPtr->Parameters.DeviceIoControl.OutputBufferLength = OutputBufferSize;
109
110    Status = IoCallDriver(DeviceObject,Irp);
111    if (Event == NULL && Status == STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO))
112    {
113       KeWaitForSingleObject(ptrEvent,Executive,KernelMode,FALSE,NULL);
114       Status = IoSB.Status;
115    }
116    if (IoStatusBlock)
117    {
118       *IoStatusBlock = IoSB;
119    }
120    return(Status);
121 }
122
123 /* EOF */