[KERNEL32]: Aleksey wants debug channels, I agree this is the way forward. Leverage...
[reactos.git] / reactos / dll / win32 / kernel32 / file / deviceio.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: kernel32/file/deviceio.c
5 * PURPOSE: Device I/O Base Client Functionality
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <k32.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* FUNCTIONS ******************************************************************/
16
17 /*
18 * @implemented
19 */
20 BOOL
21 WINAPI
22 DeviceIoControl(IN HANDLE hDevice,
23 IN DWORD dwIoControlCode,
24 IN LPVOID lpInBuffer OPTIONAL,
25 IN DWORD nInBufferSize OPTIONAL,
26 OUT LPVOID lpOutBuffer OPTIONAL,
27 IN DWORD nOutBufferSize OPTIONAL,
28 OUT LPDWORD lpBytesReturned OPTIONAL,
29 IN LPOVERLAPPED lpOverlapped OPTIONAL)
30 {
31 BOOL FsIoCtl;
32 NTSTATUS Status;
33 PVOID ApcContext;
34 IO_STATUS_BLOCK Iosb;
35
36 /* Check what kind of IOCTL to send */
37 FsIoCtl = ((dwIoControlCode >> 16) == FILE_DEVICE_FILE_SYSTEM);
38
39 /* CHeck for async */
40 if (lpOverlapped != NULL)
41 {
42 /* Set pending status */
43 lpOverlapped->Internal = STATUS_PENDING;
44
45
46 /* Check if there's an APC context */
47 ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped);
48
49
50 /* Send file system control? */
51 if (FsIoCtl)
52 {
53 /* Send it */
54 Status = NtFsControlFile(hDevice,
55 lpOverlapped->hEvent,
56 NULL,
57 ApcContext,
58 (PIO_STATUS_BLOCK)lpOverlapped,
59 dwIoControlCode,
60 lpInBuffer,
61 nInBufferSize,
62 lpOutBuffer,
63 nOutBufferSize);
64 }
65 else
66 {
67 /* Otherwise send a device control */
68 Status = NtDeviceIoControlFile(hDevice,
69 lpOverlapped->hEvent,
70 NULL,
71 ApcContext,
72 (PIO_STATUS_BLOCK)lpOverlapped,
73 dwIoControlCode,
74 lpInBuffer,
75 nInBufferSize,
76 lpOutBuffer,
77 nOutBufferSize);
78 }
79
80 /* Check for or information instead of failure */
81 if (!(NT_ERROR(Status)) && (lpBytesReturned))
82 {
83 /* Protect with SEH */
84 _SEH2_TRY
85 {
86 /* Return the bytes */
87 *lpBytesReturned = lpOverlapped->InternalHigh;
88 }
89 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
90 {
91 /* Return zero bytes */
92 *lpBytesReturned = 0;
93 }
94 _SEH2_END;
95 }
96
97 /* Now check for any kind of failure except pending*/
98 if (!(NT_SUCCESS(Status)) || (Status == STATUS_PENDING))
99 {
100 /* Fail */
101 SetLastErrorByStatus(Status);
102 return FALSE;
103 }
104 }
105 else
106 {
107 /* Sync case -- send file system code? */
108 if (FsIoCtl)
109 {
110 /* Do it */
111 Status = NtFsControlFile(hDevice,
112 NULL,
113 NULL,
114 NULL,
115 &Iosb,
116 dwIoControlCode,
117 lpInBuffer,
118 nInBufferSize,
119 lpOutBuffer,
120 nOutBufferSize);
121 }
122 else
123 {
124 /* Send device code instead */
125 Status = NtDeviceIoControlFile(hDevice,
126 NULL,
127 NULL,
128 NULL,
129 &Iosb,
130 dwIoControlCode,
131 lpInBuffer,
132 nInBufferSize,
133 lpOutBuffer,
134 nOutBufferSize);
135 }
136
137 /* Now check if the operation isn't done yet */
138 if (Status == STATUS_PENDING)
139 {
140 /* Wait for it and get the final status */
141 Status = NtWaitForSingleObject(hDevice, FALSE, NULL);
142 if (NT_SUCCESS(Status)) Status = Iosb.Status;
143 }
144
145 /* Check for success */
146 if (NT_SUCCESS(Status))
147 {
148 /* Return the byte count */
149 *lpBytesReturned = Iosb.Information;
150 }
151 else
152 {
153 /* Check for informational or warning failure */
154 if (!NT_ERROR(Status)) *lpBytesReturned = Iosb.Information;
155
156 /* Return a failure */
157 SetLastErrorByStatus(Status);
158 return FALSE;
159 }
160 }
161
162 /* Return success */
163 return TRUE;
164 }
165
166
167 /*
168 * @implemented
169 */
170 BOOL
171 WINAPI
172 GetOverlappedResult(IN HANDLE hFile,
173 IN LPOVERLAPPED lpOverlapped,
174 OUT LPDWORD lpNumberOfBytesTransferred,
175 IN BOOL bWait)
176 {
177 DWORD WaitStatus;
178 HANDLE hObject;
179
180
181 /* Check for pending operation */
182 if (lpOverlapped->Internal == STATUS_PENDING)
183 {
184 /* Check if the caller is okay with waiting */
185 if (!bWait)
186 {
187 /* Set timeout */
188 WaitStatus = WAIT_TIMEOUT;
189 }
190 else
191 {
192 /* Wait for the result */
193 hObject = lpOverlapped->hEvent ? lpOverlapped->hEvent : hFile;
194 WaitStatus = WaitForSingleObject(hObject, INFINITE);
195 }
196
197
198 /* Check for timeout */
199 if (WaitStatus == WAIT_TIMEOUT)
200 {
201 /* We have to override the last error with INCOMPLETE instead */
202 SetLastError(ERROR_IO_INCOMPLETE);
203 return FALSE;
204 }
205
206
207 /* Fail if we had an error -- the last error is already set */
208 if (WaitStatus != 0) return FALSE;
209 }
210
211
212 /* Return bytes transferred */
213 *lpNumberOfBytesTransferred = lpOverlapped->InternalHigh;
214
215
216 /* Check for failure during I/O */
217 if (!NT_SUCCESS(lpOverlapped->Internal))
218 {
219 /* Set the error and fail */
220 SetLastErrorByStatus(lpOverlapped->Internal);
221 return FALSE;
222 }
223
224
225 /* All done */
226 return TRUE;
227 }
228
229 /* EOF */
230