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 *******************************************************************/
12 #include <wine/debug.h>
14 /* FUNCTIONS ******************************************************************/
21 DeviceIoControl(IN HANDLE hDevice
,
22 IN DWORD dwIoControlCode
,
23 IN LPVOID lpInBuffer OPTIONAL
,
24 IN DWORD nInBufferSize OPTIONAL
,
25 OUT LPVOID lpOutBuffer OPTIONAL
,
26 IN DWORD nOutBufferSize OPTIONAL
,
27 OUT LPDWORD lpBytesReturned OPTIONAL
,
28 IN LPOVERLAPPED lpOverlapped OPTIONAL
)
35 /* Check what kind of IOCTL to send */
36 FsIoCtl
= ((dwIoControlCode
>> 16) == FILE_DEVICE_FILE_SYSTEM
);
39 if (lpOverlapped
!= NULL
)
41 /* Set pending status */
42 lpOverlapped
->Internal
= STATUS_PENDING
;
45 /* Check if there's an APC context */
46 ApcContext
= (((ULONG_PTR
)lpOverlapped
->hEvent
& 0x1) ? NULL
: lpOverlapped
);
49 /* Send file system control? */
53 Status
= NtFsControlFile(hDevice
,
57 (PIO_STATUS_BLOCK
)lpOverlapped
,
66 /* Otherwise send a device control */
67 Status
= NtDeviceIoControlFile(hDevice
,
71 (PIO_STATUS_BLOCK
)lpOverlapped
,
79 /* Check for or information instead of failure */
80 if (!(NT_ERROR(Status
)) && (lpBytesReturned
))
82 /* Protect with SEH */
85 /* Return the bytes */
86 *lpBytesReturned
= lpOverlapped
->InternalHigh
;
88 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
90 /* Return zero bytes */
96 /* Now check for any kind of failure except pending*/
97 if (!(NT_SUCCESS(Status
)) || (Status
== STATUS_PENDING
))
100 SetLastErrorByStatus(Status
);
106 /* Sync case -- send file system code? */
110 Status
= NtFsControlFile(hDevice
,
123 /* Send device code instead */
124 Status
= NtDeviceIoControlFile(hDevice
,
136 /* Now check if the operation isn't done yet */
137 if (Status
== STATUS_PENDING
)
139 /* Wait for it and get the final status */
140 Status
= NtWaitForSingleObject(hDevice
, FALSE
, NULL
);
141 if (NT_SUCCESS(Status
)) Status
= Iosb
.Status
;
144 /* Check for success */
145 if (NT_SUCCESS(Status
))
147 /* Return the byte count */
148 *lpBytesReturned
= Iosb
.Information
;
152 /* Check for informational or warning failure */
153 if (!NT_ERROR(Status
)) *lpBytesReturned
= Iosb
.Information
;
155 /* Return a failure */
156 SetLastErrorByStatus(Status
);
171 GetOverlappedResult(IN HANDLE hFile
,
172 IN LPOVERLAPPED lpOverlapped
,
173 OUT LPDWORD lpNumberOfBytesTransferred
,
180 /* Check for pending operation */
181 if (lpOverlapped
->Internal
== STATUS_PENDING
)
183 /* Check if the caller is okay with waiting */
187 WaitStatus
= WAIT_TIMEOUT
;
191 /* Wait for the result */
192 hObject
= lpOverlapped
->hEvent
? lpOverlapped
->hEvent
: hFile
;
193 WaitStatus
= WaitForSingleObject(hObject
, INFINITE
);
197 /* Check for timeout */
198 if (WaitStatus
== WAIT_TIMEOUT
)
200 /* We have to override the last error with INCOMPLETE instead */
201 SetLastError(ERROR_IO_INCOMPLETE
);
206 /* Fail if we had an error -- the last error is already set */
207 if (WaitStatus
!= 0) return FALSE
;
211 /* Return bytes transferred */
212 *lpNumberOfBytesTransferred
= lpOverlapped
->InternalHigh
;
215 /* Check for failure during I/O */
216 if (!NT_SUCCESS(lpOverlapped
->Internal
))
218 /* Set the error and fail */
219 SetLastErrorByStatus(lpOverlapped
->Internal
);