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)
9 /* INCLUDES *******************************************************************/
15 /* FUNCTIONS ******************************************************************/
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
)
36 /* Check what kind of IOCTL to send */
37 FsIoCtl
= ((dwIoControlCode
>> 16) == FILE_DEVICE_FILE_SYSTEM
);
40 if (lpOverlapped
!= NULL
)
42 /* Set pending status */
43 lpOverlapped
->Internal
= STATUS_PENDING
;
46 /* Check if there's an APC context */
47 ApcContext
= (((ULONG_PTR
)lpOverlapped
->hEvent
& 0x1) ? NULL
: lpOverlapped
);
50 /* Send file system control? */
54 Status
= NtFsControlFile(hDevice
,
58 (PIO_STATUS_BLOCK
)lpOverlapped
,
67 /* Otherwise send a device control */
68 Status
= NtDeviceIoControlFile(hDevice
,
72 (PIO_STATUS_BLOCK
)lpOverlapped
,
80 /* Check for or information instead of failure */
81 if (!(NT_ERROR(Status
)) && (lpBytesReturned
))
83 /* Protect with SEH */
86 /* Return the bytes */
87 *lpBytesReturned
= lpOverlapped
->InternalHigh
;
89 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
91 /* Return zero bytes */
97 /* Now check for any kind of failure except pending*/
98 if (!(NT_SUCCESS(Status
)) || (Status
== STATUS_PENDING
))
101 SetLastErrorByStatus(Status
);
107 /* Sync case -- send file system code? */
111 Status
= NtFsControlFile(hDevice
,
124 /* Send device code instead */
125 Status
= NtDeviceIoControlFile(hDevice
,
137 /* Now check if the operation isn't done yet */
138 if (Status
== STATUS_PENDING
)
140 /* Wait for it and get the final status */
141 Status
= NtWaitForSingleObject(hDevice
, FALSE
, NULL
);
142 if (NT_SUCCESS(Status
)) Status
= Iosb
.Status
;
145 /* Check for success */
146 if (NT_SUCCESS(Status
))
148 /* Return the byte count */
149 *lpBytesReturned
= Iosb
.Information
;
153 /* Check for informational or warning failure */
154 if (!NT_ERROR(Status
)) *lpBytesReturned
= Iosb
.Information
;
156 /* Return a failure */
157 SetLastErrorByStatus(Status
);
172 GetOverlappedResult(IN HANDLE hFile
,
173 IN LPOVERLAPPED lpOverlapped
,
174 OUT LPDWORD lpNumberOfBytesTransferred
,
181 /* Check for pending operation */
182 if (lpOverlapped
->Internal
== STATUS_PENDING
)
184 /* Check if the caller is okay with waiting */
188 WaitStatus
= WAIT_TIMEOUT
;
192 /* Wait for the result */
193 hObject
= lpOverlapped
->hEvent
? lpOverlapped
->hEvent
: hFile
;
194 WaitStatus
= WaitForSingleObject(hObject
, INFINITE
);
198 /* Check for timeout */
199 if (WaitStatus
== WAIT_TIMEOUT
)
201 /* We have to override the last error with INCOMPLETE instead */
202 SetLastError(ERROR_IO_INCOMPLETE
);
207 /* Fail if we had an error -- the last error is already set */
208 if (WaitStatus
!= 0) return FALSE
;
212 /* Return bytes transferred */
213 *lpNumberOfBytesTransferred
= lpOverlapped
->InternalHigh
;
216 /* Check for failure during I/O */
217 if (!NT_SUCCESS(lpOverlapped
->Internal
))
219 /* Set the error and fail */
220 SetLastErrorByStatus(lpOverlapped
->Internal
);