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