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)
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.
20 #if (_WIN32_WINNT < 0x0600)
21 #define FILE_SKIP_COMPLETION_PORT_ON_SUCCESS 0x1
22 #define FILE_SKIP_SET_EVENT_ON_HANDLE 0x2
30 SetFileCompletionNotificationModes(IN HANDLE FileHandle
,
33 if (Flags
& ~(FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
| FILE_SKIP_SET_EVENT_ON_HANDLE
))
35 SetLastError(ERROR_INVALID_PARAMETER
);
48 CreateIoCompletionPort(IN HANDLE FileHandle
,
49 IN HANDLE ExistingCompletionPort
,
50 IN ULONG_PTR CompletionKey
,
51 IN DWORD NumberOfConcurrentThreads
)
55 FILE_COMPLETION_INFORMATION CompletionInformation
;
56 IO_STATUS_BLOCK IoStatusBlock
;
58 /* Check if this is a new port */
59 NewPort
= ExistingCompletionPort
;
60 if (!ExistingCompletionPort
)
63 Status
= NtCreateIoCompletion(&NewPort
,
64 IO_COMPLETION_ALL_ACCESS
,
66 NumberOfConcurrentThreads
);
67 if (!NT_SUCCESS(Status
))
69 /* Convert error and fail */
70 BaseSetLastNTError(Status
);
75 /* Check if no actual file is being associated with the completion port */
76 if (FileHandle
== INVALID_HANDLE_VALUE
)
78 /* Was there a port already associated? */
79 if (ExistingCompletionPort
)
81 /* You are not allowed using an old port and dropping the handle */
83 BaseSetLastNTError(STATUS_INVALID_PARAMETER
);
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
,
93 &CompletionInformation
,
94 sizeof(FILE_COMPLETION_INFORMATION
),
95 FileCompletionInformation
);
96 if (!NT_SUCCESS(Status
))
98 /* Convert the error code and close the newly created port, if any */
99 BaseSetLastNTError(Status
);
100 if (!ExistingCompletionPort
) NtClose(NewPort
);
105 /* Return the newly created port, if any */
114 GetQueuedCompletionStatus(IN HANDLE CompletionHandle
,
115 IN LPDWORD lpNumberOfBytesTransferred
,
116 OUT PULONG_PTR lpCompletionKey
,
117 OUT LPOVERLAPPED
*lpOverlapped
,
118 IN DWORD dwMilliseconds
)
121 IO_STATUS_BLOCK IoStatus
;
122 ULONG_PTR CompletionKey
;
124 PLARGE_INTEGER TimePtr
;
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
,
133 if (!(NT_SUCCESS(Status
)) || (Status
== STATUS_TIMEOUT
))
135 /* Clear out the overlapped output */
136 *lpOverlapped
= NULL
;
138 /* Check what kind of error we got */
139 if (Status
== STATUS_TIMEOUT
)
141 /* Timeout error is set directly since there's no conversion */
142 SetLastError(WAIT_TIMEOUT
);
146 /* Any other error gets converted */
147 BaseSetLastNTError(Status
);
150 /* This is a failure case */
154 /* Write back the output parameters */
155 *lpCompletionKey
= CompletionKey
;
156 *lpNumberOfBytesTransferred
= IoStatus
.Information
;
158 /* Check for error */
159 if (!NT_SUCCESS(IoStatus
.Status
))
161 /* Convert and fail */
162 BaseSetLastNTError(IoStatus
.Status
);
175 PostQueuedCompletionStatus(IN HANDLE CompletionHandle
,
176 IN DWORD dwNumberOfBytesTransferred
,
177 IN ULONG_PTR dwCompletionKey
,
178 IN LPOVERLAPPED lpOverlapped
)
182 /* Call the native API */
183 Status
= NtSetIoCompletion(CompletionHandle
,
184 (PVOID
)dwCompletionKey
,
187 dwNumberOfBytesTransferred
);
188 if (!NT_SUCCESS(Status
))
190 /* Convert the error and fail */
191 BaseSetLastNTError(Status
);
204 GetOverlappedResult(IN HANDLE hFile
,
205 IN LPOVERLAPPED lpOverlapped
,
206 OUT LPDWORD lpNumberOfBytesTransferred
,
212 /* Check for pending operation */
213 if (lpOverlapped
->Internal
== STATUS_PENDING
)
215 /* Check if the caller is okay with waiting */
219 WaitStatus
= WAIT_TIMEOUT
;
223 /* Wait for the result */
224 hObject
= lpOverlapped
->hEvent
? lpOverlapped
->hEvent
: hFile
;
225 WaitStatus
= WaitForSingleObject(hObject
, INFINITE
);
228 /* Check for timeout */
229 if (WaitStatus
== WAIT_TIMEOUT
)
231 /* We have to override the last error with INCOMPLETE instead */
232 SetLastError(ERROR_IO_INCOMPLETE
);
236 /* Fail if we had an error -- the last error is already set */
237 if (WaitStatus
) return FALSE
;
240 /* Return bytes transferred */
241 *lpNumberOfBytesTransferred
= lpOverlapped
->InternalHigh
;
243 /* Check for failure during I/O */
244 if (!NT_SUCCESS(lpOverlapped
->Internal
))
246 /* Set the error and fail */
247 BaseSetLastNTError(lpOverlapped
->Internal
);
260 BindIoCompletionCallback(IN HANDLE FileHandle
,
261 IN LPOVERLAPPED_COMPLETION_ROUTINE Function
,
267 Status
= RtlSetIoCompletionCallback(FileHandle
,
268 (PIO_APC_ROUTINE
)Function
,
270 if (!NT_SUCCESS(Status
))
272 /* Set error and fail */
273 BaseSetLastNTError(Status
);