:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / lib / kernel32 / file / deviceio.c
1 /* $Id$
2  *
3  * COPYRIGHT:       See COPYING in the top level directory
4  * PROJECT:         ReactOS system libraries
5  * FILE:            lib/kernel32/file/deviceio.c
6  * PURPOSE:         Device I/O and Overlapped Result functions
7  * PROGRAMMER:      Ariadne (ariadne@xs4all.nl)
8  * UPDATE HISTORY:
9  *                  Created 01/11/98
10  */
11
12 #include <ddk/ntddk.h>
13 #include <windows.h>
14
15 #define NDEBUG
16 //#define DBG
17 #include <kernel32/kernel32.h>
18 #include <kernel32/error.h>
19
20
21 WINBOOL
22 STDCALL
23 DeviceIoControl(
24                 HANDLE hDevice,
25                 DWORD dwIoControlCode,
26                 LPVOID lpInBuffer,
27                 DWORD nInBufferSize,
28                 LPVOID lpOutBuffer,
29                 DWORD nOutBufferSize,
30                 LPDWORD lpBytesReturned,
31                 LPOVERLAPPED lpOverlapped
32                 )
33 {
34         NTSTATUS errCode = 0;
35         HANDLE hEvent = NULL;
36         PIO_STATUS_BLOCK IoStatusBlock;
37         IO_STATUS_BLOCK IIosb;
38
39         WINBOOL bFsIoControlCode = FALSE;
40
41     DPRINT("DeviceIoControl(hDevice %x dwIoControlCode %d lpInBuffer %x "
42           "nInBufferSize %d lpOutBuffer %x nOutBufferSize %d "
43           "lpBytesReturned %x lpOverlapped %x)\n",
44           hDevice,dwIoControlCode,lpInBuffer,nInBufferSize,lpOutBuffer,
45           nOutBufferSize,lpBytesReturned,lpOverlapped);
46
47         if (lpBytesReturned == NULL)
48         {
49         DPRINT("DeviceIoControl() - returning STATUS_INVALID_PARAMETER\n");
50                 SetLastErrorByStatus (STATUS_INVALID_PARAMETER);
51                 return FALSE;
52         }
53         //
54         // TODO: Review and approve this change by RobD. IoCtrls for Serial.sys were 
55         //       going to NtFsControlFile instead of NtDeviceIoControlFile.
56         //               Don't know at this point if anything else is affected by this change.
57         //
58         // if (((dwIoControlCode >> 16) & FILE_DEVICE_FILE_SYSTEM) == FILE_DEVICE_FILE_SYSTEM) {
59         //
60
61         if ((dwIoControlCode >> 16) == FILE_DEVICE_FILE_SYSTEM) {
62
63                 bFsIoControlCode = TRUE;
64         DPRINT("DeviceIoControl() - FILE_DEVICE_FILE_SYSTEM == TRUE %x %x\n", dwIoControlCode, dwIoControlCode >> 16);
65         } else {
66                 bFsIoControlCode = FALSE;
67         DPRINT("DeviceIoControl() - FILE_DEVICE_FILE_SYSTEM == FALSE %x %x\n", dwIoControlCode, dwIoControlCode >> 16);
68         }
69
70         if(lpOverlapped  != NULL)
71         {
72                 hEvent = lpOverlapped->hEvent;
73                 lpOverlapped->Internal = STATUS_PENDING;
74                 IoStatusBlock = (PIO_STATUS_BLOCK)lpOverlapped;
75         }
76         else
77         {
78                 IoStatusBlock = &IIosb;
79         }
80
81         if (bFsIoControlCode == TRUE)
82         {
83                 errCode = NtFsControlFile (hDevice,
84                                            hEvent,
85                                            NULL,
86                                            NULL,
87                                            IoStatusBlock,
88                                            dwIoControlCode,
89                                            lpInBuffer,
90                                            nInBufferSize,
91                                            lpOutBuffer,
92                                            nOutBufferSize);
93         }
94         else
95         {
96                 errCode = NtDeviceIoControlFile (hDevice,
97                                                  hEvent,
98                                                  NULL,
99                                                  NULL,
100                                                  IoStatusBlock,
101                                                  dwIoControlCode,
102                                                  lpInBuffer,
103                                                  nInBufferSize,
104                                                  lpOutBuffer,
105                                                  nOutBufferSize);
106         }
107
108         if (errCode == STATUS_PENDING)
109         {
110         DPRINT("DeviceIoControl() - STATUS_PENDING\n");
111                 if (NtWaitForSingleObject(hDevice,FALSE,NULL) < 0)
112                 {
113                         *lpBytesReturned = IoStatusBlock->Information;
114                         SetLastErrorByStatus (errCode);
115             DPRINT("DeviceIoControl() - STATUS_PENDING wait failed.\n");
116                         return FALSE;
117                 }
118         }
119         else if (!NT_SUCCESS(errCode))
120         {
121                 SetLastErrorByStatus (errCode);
122         DPRINT("DeviceIoControl() - ERROR: %x\n", errCode);
123                 return FALSE;
124         }
125
126         if (lpOverlapped)
127                 *lpBytesReturned = lpOverlapped->InternalHigh;
128         else
129                 *lpBytesReturned = IoStatusBlock->Information;
130
131         return TRUE;
132 }
133
134
135 WINBOOL
136 STDCALL
137 GetOverlappedResult (
138         HANDLE          hFile,
139         LPOVERLAPPED    lpOverlapped,
140         LPDWORD         lpNumberOfBytesTransferred,
141         WINBOOL         bWait
142         )
143 {
144         DWORD WaitStatus;
145
146         if (lpOverlapped == NULL)
147         {
148                 SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
149                 return FALSE;
150         }
151
152         if (lpOverlapped ->Internal == STATUS_PENDING)
153         {
154                 if (lpNumberOfBytesTransferred == 0)
155                 {
156                         SetLastErrorByStatus (STATUS_PENDING);
157                         return FALSE;
158                 }
159                 else if (bWait == TRUE)
160                 {
161                         if (lpOverlapped->hEvent != NULL)
162                         {
163                                 WaitStatus = WaitForSingleObject (lpOverlapped->hEvent,
164                                                                   -1);
165                                 if (WaitStatus ==  STATUS_TIMEOUT)
166                                 {
167                                         SetLastError (ERROR_IO_INCOMPLETE);
168                                         return FALSE;
169                                 }
170                                 else
171                                         return GetOverlappedResult (hFile,
172                                                                     lpOverlapped,
173                                                                     lpNumberOfBytesTransferred,
174                                                                     FALSE);
175                         }
176                 }
177         }
178
179         *lpNumberOfBytesTransferred = lpOverlapped->InternalHigh;
180
181         if (lpOverlapped->Internal < 0)
182         {
183                 SetLastErrorByStatus (lpOverlapped->Internal);
184                 return FALSE;
185         }
186
187         return TRUE;
188 }
189
190 /* EOF */
191
192