Copy wininet to branch
[reactos.git] / reactos / 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 *
8 * PROGRAMMERS: David Welch (welch@mcmail.com)
9 * Eric Kohl (ekohl@rz-online.de)
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ntoskrnl.h>
15 #define NDEBUG
16 #include <internal/debug.h>
17
18 /* FUNCTIONS *****************************************************************/
19
20 /*
21 * @implemented
22 */
23 NTSTATUS STDCALL
24 NtDeviceIoControlFile (IN HANDLE DeviceHandle,
25 IN HANDLE Event OPTIONAL,
26 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
27 IN PVOID UserApcContext OPTIONAL,
28 OUT PIO_STATUS_BLOCK IoStatusBlock,
29 IN ULONG IoControlCode,
30 IN PVOID InputBuffer,
31 IN ULONG InputBufferLength OPTIONAL,
32 OUT PVOID OutputBuffer,
33 IN ULONG OutputBufferLength OPTIONAL)
34 {
35 NTSTATUS Status;
36 PFILE_OBJECT FileObject;
37 PDEVICE_OBJECT DeviceObject;
38 PIRP Irp;
39 PIO_STACK_LOCATION StackPtr;
40 PKEVENT EventObject;
41 KPROCESSOR_MODE PreviousMode;
42
43 DPRINT("NtDeviceIoControlFile(DeviceHandle %x Event %x UserApcRoutine %x "
44 "UserApcContext %x IoStatusBlock %x IoControlCode %x "
45 "InputBuffer %x InputBufferLength %x OutputBuffer %x "
46 "OutputBufferLength %x)\n",
47 DeviceHandle,Event,UserApcRoutine,UserApcContext,IoStatusBlock,
48 IoControlCode,InputBuffer,InputBufferLength,OutputBuffer,
49 OutputBufferLength);
50
51 if (IoStatusBlock == NULL)
52 return STATUS_ACCESS_VIOLATION;
53
54 PreviousMode = ExGetPreviousMode();
55
56 /* Check granted access against the access rights from IoContolCode */
57 Status = ObReferenceObjectByHandle (DeviceHandle,
58 (IoControlCode >> 14) & 0x3,
59 IoFileObjectType,
60 PreviousMode,
61 (PVOID *) &FileObject,
62 NULL);
63 if (!NT_SUCCESS(Status))
64 {
65 return Status;
66 }
67
68 if (Event != NULL)
69 {
70 Status = ObReferenceObjectByHandle (Event,
71 SYNCHRONIZE,
72 ExEventObjectType,
73 PreviousMode,
74 (PVOID*)&EventObject,
75 NULL);
76 if (!NT_SUCCESS(Status))
77 {
78 ObDereferenceObject (FileObject);
79 return Status;
80 }
81 }
82 else
83 {
84 EventObject = &FileObject->Event;
85 KeResetEvent (EventObject);
86 }
87
88 DeviceObject = FileObject->DeviceObject;
89
90 Irp = IoBuildDeviceIoControlRequest (IoControlCode,
91 DeviceObject,
92 InputBuffer,
93 InputBufferLength,
94 OutputBuffer,
95 OutputBufferLength,
96 FALSE,
97 EventObject,
98 IoStatusBlock);
99
100 /* Trigger FileObject/Event dereferencing */
101 Irp->Tail.Overlay.OriginalFileObject = FileObject;
102
103 Irp->RequestorMode = PreviousMode;
104 Irp->Overlay.AsynchronousParameters.UserApcRoutine = UserApcRoutine;
105 Irp->Overlay.AsynchronousParameters.UserApcContext = UserApcContext;
106
107 StackPtr = IoGetNextIrpStackLocation(Irp);
108 StackPtr->FileObject = FileObject;
109 StackPtr->DeviceObject = DeviceObject;
110 StackPtr->Parameters.DeviceIoControl.InputBufferLength = InputBufferLength;
111 StackPtr->Parameters.DeviceIoControl.OutputBufferLength = OutputBufferLength;
112
113 Status = IoCallDriver(DeviceObject,Irp);
114 if (Status == STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
115 {
116 Status = KeWaitForSingleObject (EventObject,
117 Executive,
118 PreviousMode,
119 FileObject->Flags & FO_ALERTABLE_IO,
120 NULL);
121 if (Status != STATUS_WAIT_0)
122 {
123 /* Wait failed. */
124 return Status;
125 }
126
127 Status = IoStatusBlock->Status;
128 }
129
130 return Status;
131 }
132
133 /* EOF */