:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[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 NTSTATUS STDCALL NtDeviceIoControlFile (IN HANDLE DeviceHandle,
26                                         IN HANDLE Event,
27                                         IN PIO_APC_ROUTINE UserApcRoutine,
28                                         IN PVOID UserApcContext,
29                                         OUT PIO_STATUS_BLOCK IoStatusBlock,
30                                         IN ULONG IoControlCode,
31                                         IN PVOID InputBuffer,
32                                         IN ULONG InputBufferSize,
33                                         OUT PVOID OutputBuffer,
34                                         IN ULONG OutputBufferSize)
35 {
36    NTSTATUS Status;
37    PFILE_OBJECT FileObject;
38    PDEVICE_OBJECT DeviceObject;
39    PIRP Irp;
40    PIO_STACK_LOCATION StackPtr;
41    PKEVENT ptrEvent;
42    IO_STATUS_BLOCK IoSB;
43
44    DPRINT("NtDeviceIoControlFile(DeviceHandle %x Event %x UserApcRoutine %x "
45           "UserApcContext %x IoStatusBlock %x IoControlCode %x "
46           "InputBuffer %x InputBufferSize %x OutputBuffer %x "
47           "OutputBufferSize %x)\n",
48           DeviceHandle,Event,UserApcRoutine,UserApcContext,IoStatusBlock,
49           IoControlCode,InputBuffer,InputBufferSize,OutputBuffer,
50           OutputBufferSize);
51
52    Status = ObReferenceObjectByHandle(DeviceHandle,
53                                       FILE_READ_DATA | FILE_WRITE_DATA,
54                                       IoFileObjectType,
55                                       KernelMode,
56                                       (PVOID *) &FileObject,
57                                       NULL);
58    
59    if (!NT_SUCCESS(Status))
60      {
61         return(Status);
62      }
63    if (Event != NULL)
64      {
65         Status = ObReferenceObjectByHandle (Event,
66                                             SYNCHRONIZE,
67                                             ExEventObjectType,
68                                             UserMode,
69                                             (PVOID*)&ptrEvent,
70                                             NULL);
71         if (!NT_SUCCESS(Status))
72           {
73             ObDereferenceObject(FileObject);
74             return Status;
75           }
76       }
77     else
78       {
79          KeResetEvent (&FileObject->Event);
80          ptrEvent = &FileObject->Event;
81       }
82
83    DeviceObject = FileObject->DeviceObject;
84
85    Irp = IoBuildDeviceIoControlRequest(IoControlCode,
86                                        DeviceObject,
87                                        InputBuffer,
88                                        InputBufferSize,
89                                        OutputBuffer,
90                                        OutputBufferSize,
91                                        FALSE,
92                                        ptrEvent,
93                                        Event ? IoStatusBlock : &IoSB);
94
95    Irp->Overlay.AsynchronousParameters.UserApcRoutine = UserApcRoutine;
96    Irp->Overlay.AsynchronousParameters.UserApcContext = UserApcContext;
97
98    StackPtr = IoGetNextIrpStackLocation(Irp);
99    StackPtr->FileObject = FileObject;
100    StackPtr->DeviceObject = DeviceObject;
101    StackPtr->Parameters.DeviceIoControl.InputBufferLength = InputBufferSize;
102    StackPtr->Parameters.DeviceIoControl.OutputBufferLength = OutputBufferSize;
103
104    Status = IoCallDriver(DeviceObject,Irp);
105    if (Event == NULL && Status == STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO))
106    {
107       KeWaitForSingleObject(ptrEvent,Executive,KernelMode,FALSE,NULL);
108       Status = IoSB.Status;
109    }
110    if (IoStatusBlock)
111    {
112       *IoStatusBlock = IoSB;
113    }
114    return(Status);
115 }
116
117 /* EOF */