[KERNEL32] Improve the FILE header section. Brought to you by Adam Stachowicz. CORE...
[reactos.git] / reactos / dll / win32 / kernel32 / client / file / iocompl.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: dll/win32/kernel32/client/file/iocompl.c
5 * PURPOSE: Io Completion functions
6 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
7 * UPDATE HISTORY:
8 * Created 01/11/98
9 */
10
11 #include <k32.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /*
16 * SetFileCompletionNotificationModes is not entirely Vista-exclusive,
17 * it was actually added to Windows 2003 in SP2. Headers restrict it from
18 * pre-Vista though so define the flags we need for it.
19 */
20 #if (_WIN32_WINNT < 0x0600)
21 #define FILE_SKIP_COMPLETION_PORT_ON_SUCCESS 0x1
22 #define FILE_SKIP_SET_EVENT_ON_HANDLE 0x2
23 #endif
24
25 /*
26 * @unimplemented
27 */
28 BOOL
29 WINAPI
30 SetFileCompletionNotificationModes(IN HANDLE FileHandle,
31 IN UCHAR Flags)
32 {
33 if (Flags & ~(FILE_SKIP_COMPLETION_PORT_ON_SUCCESS | FILE_SKIP_SET_EVENT_ON_HANDLE))
34 {
35 SetLastError(ERROR_INVALID_PARAMETER);
36 return FALSE;
37 }
38
39 UNIMPLEMENTED;
40 return FALSE;
41 }
42
43 /*
44 * @implemented
45 */
46 HANDLE
47 WINAPI
48 CreateIoCompletionPort(IN HANDLE FileHandle,
49 IN HANDLE ExistingCompletionPort,
50 IN ULONG_PTR CompletionKey,
51 IN DWORD NumberOfConcurrentThreads)
52 {
53 NTSTATUS Status;
54 HANDLE NewPort;
55 FILE_COMPLETION_INFORMATION CompletionInformation;
56 IO_STATUS_BLOCK IoStatusBlock;
57
58 /* Check if this is a new port */
59 NewPort = ExistingCompletionPort;
60 if (!ExistingCompletionPort)
61 {
62 /* Create it */
63 Status = NtCreateIoCompletion(&NewPort,
64 IO_COMPLETION_ALL_ACCESS,
65 NULL,
66 NumberOfConcurrentThreads);
67 if (!NT_SUCCESS(Status))
68 {
69 /* Convert error and fail */
70 BaseSetLastNTError(Status);
71 return FALSE;
72 }
73 }
74
75 /* Check if no actual file is being associated with the completion port */
76 if (FileHandle == INVALID_HANDLE_VALUE)
77 {
78 /* Was there a port already associated? */
79 if (ExistingCompletionPort)
80 {
81 /* You are not allowed using an old port and dropping the handle */
82 NewPort = NULL;
83 BaseSetLastNTError(STATUS_INVALID_PARAMETER);
84 }
85 }
86 else
87 {
88 /* We have a file handle, so associated it with this completion port */
89 CompletionInformation.Port = NewPort;
90 CompletionInformation.Key = (PVOID)CompletionKey;
91 Status = NtSetInformationFile(FileHandle,
92 &IoStatusBlock,
93 &CompletionInformation,
94 sizeof(FILE_COMPLETION_INFORMATION),
95 FileCompletionInformation);
96 if (!NT_SUCCESS(Status))
97 {
98 /* Convert the error code and close the newly created port, if any */
99 BaseSetLastNTError(Status);
100 if (!ExistingCompletionPort) NtClose(NewPort);
101 return FALSE;
102 }
103 }
104
105 /* Return the newly created port, if any */
106 return NewPort;
107 }
108
109 /*
110 * @implemented
111 */
112 BOOL
113 WINAPI
114 GetQueuedCompletionStatus(IN HANDLE CompletionHandle,
115 IN LPDWORD lpNumberOfBytesTransferred,
116 OUT PULONG_PTR lpCompletionKey,
117 OUT LPOVERLAPPED *lpOverlapped,
118 IN DWORD dwMilliseconds)
119 {
120 NTSTATUS Status;
121 IO_STATUS_BLOCK IoStatus;
122 ULONG_PTR CompletionKey;
123 LARGE_INTEGER Time;
124 PLARGE_INTEGER TimePtr;
125
126 /* Convert the timeout and then call the native API */
127 TimePtr = BaseFormatTimeOut(&Time, dwMilliseconds);
128 Status = NtRemoveIoCompletion(CompletionHandle,
129 (PVOID*)&CompletionKey,
130 (PVOID*)lpOverlapped,
131 &IoStatus,
132 TimePtr);
133 if (!(NT_SUCCESS(Status)) || (Status == STATUS_TIMEOUT))
134 {
135 /* Clear out the overlapped output */
136 *lpOverlapped = NULL;
137
138 /* Check what kind of error we got */
139 if (Status == STATUS_TIMEOUT)
140 {
141 /* Timeout error is set directly since there's no conversion */
142 SetLastError(WAIT_TIMEOUT);
143 }
144 else
145 {
146 /* Any other error gets converted */
147 BaseSetLastNTError(Status);
148 }
149
150 /* This is a failure case */
151 return FALSE;
152 }
153
154 /* Write back the output parameters */
155 *lpCompletionKey = CompletionKey;
156 *lpNumberOfBytesTransferred = IoStatus.Information;
157
158 /* Check for error */
159 if (!NT_SUCCESS(IoStatus.Status))
160 {
161 /* Convert and fail */
162 BaseSetLastNTError(IoStatus.Status);
163 return FALSE;
164 }
165
166 /* Return success */
167 return TRUE;
168 }
169
170 /*
171 * @implemented
172 */
173 BOOL
174 WINAPI
175 PostQueuedCompletionStatus(IN HANDLE CompletionHandle,
176 IN DWORD dwNumberOfBytesTransferred,
177 IN ULONG_PTR dwCompletionKey,
178 IN LPOVERLAPPED lpOverlapped)
179 {
180 NTSTATUS Status;
181
182 /* Call the native API */
183 Status = NtSetIoCompletion(CompletionHandle,
184 (PVOID)dwCompletionKey,
185 (PVOID)lpOverlapped,
186 STATUS_SUCCESS,
187 dwNumberOfBytesTransferred);
188 if (!NT_SUCCESS(Status))
189 {
190 /* Convert the error and fail */
191 BaseSetLastNTError(Status);
192 return FALSE;
193 }
194
195 /* Success path */
196 return TRUE;
197 }
198
199 /*
200 * @implemented
201 */
202 BOOL
203 WINAPI
204 GetOverlappedResult(IN HANDLE hFile,
205 IN LPOVERLAPPED lpOverlapped,
206 OUT LPDWORD lpNumberOfBytesTransferred,
207 IN BOOL bWait)
208 {
209 DWORD WaitStatus;
210 HANDLE hObject;
211
212 /* Check for pending operation */
213 if (lpOverlapped->Internal == STATUS_PENDING)
214 {
215 /* Check if the caller is okay with waiting */
216 if (!bWait)
217 {
218 /* Set timeout */
219 WaitStatus = WAIT_TIMEOUT;
220 }
221 else
222 {
223 /* Wait for the result */
224 hObject = lpOverlapped->hEvent ? lpOverlapped->hEvent : hFile;
225 WaitStatus = WaitForSingleObject(hObject, INFINITE);
226 }
227
228 /* Check for timeout */
229 if (WaitStatus == WAIT_TIMEOUT)
230 {
231 /* We have to override the last error with INCOMPLETE instead */
232 SetLastError(ERROR_IO_INCOMPLETE);
233 return FALSE;
234 }
235
236 /* Fail if we had an error -- the last error is already set */
237 if (WaitStatus) return FALSE;
238 }
239
240 /* Return bytes transferred */
241 *lpNumberOfBytesTransferred = lpOverlapped->InternalHigh;
242
243 /* Check for failure during I/O */
244 if (!NT_SUCCESS(lpOverlapped->Internal))
245 {
246 /* Set the error and fail */
247 BaseSetLastNTError(lpOverlapped->Internal);
248 return FALSE;
249 }
250
251 /* All done */
252 return TRUE;
253 }
254
255 /*
256 * @implemented
257 */
258 BOOL
259 WINAPI
260 BindIoCompletionCallback(IN HANDLE FileHandle,
261 IN LPOVERLAPPED_COMPLETION_ROUTINE Function,
262 IN ULONG Flags)
263 {
264 NTSTATUS Status;
265
266 /* Call RTL */
267 Status = RtlSetIoCompletionCallback(FileHandle,
268 (PIO_APC_ROUTINE)Function,
269 Flags);
270 if (!NT_SUCCESS(Status))
271 {
272 /* Set error and fail */
273 BaseSetLastNTError(Status);
274 return FALSE;
275 }
276
277 /* Return success */
278 return TRUE;
279 }
280
281 /* EOF */